1 | 'use strict';
|
2 |
|
3 | import React, { PropTypes } from 'react';
|
4 | import { View } from 'react-native';
|
5 |
|
6 | import GLView from './GLView';
|
7 |
|
8 |
|
9 | export default (THREE) => class THREEView extends React.Component {
|
10 | static propTypes = {
|
11 |
|
12 | scene: PropTypes.object,
|
13 | camera: PropTypes.object,
|
14 |
|
15 |
|
16 |
|
17 | autoAspect: PropTypes.bool,
|
18 |
|
19 |
|
20 |
|
21 | tick: PropTypes.func,
|
22 |
|
23 | ...View.propTypes,
|
24 | };
|
25 |
|
26 | static defaultProps = {
|
27 | autoAspect: true,
|
28 | };
|
29 |
|
30 |
|
31 |
|
32 | static textureFromAsset(asset) {
|
33 | if (!asset.localUri) {
|
34 | throw new Error(`Asset '${asset.name}' needs to be downloaded before ` +
|
35 | `being used as an OpenGL texture.`);
|
36 | }
|
37 | const texture = new THREE.Texture();
|
38 | texture.image = {
|
39 | data: asset,
|
40 | width: asset.width,
|
41 | height: asset.height,
|
42 | };
|
43 | texture.needsUpdate = true;
|
44 | texture.isDataTexture = true;
|
45 | return texture;
|
46 | }
|
47 |
|
48 |
|
49 | _onContextCreate = (gl) => {
|
50 | const renderer = new THREE.WebGLRenderer({
|
51 | canvas: {
|
52 | width: gl.drawingBufferWidth,
|
53 | height: gl.drawingBufferHeight,
|
54 | style: {},
|
55 | addEventListener: () => {},
|
56 | removeEventListener: () => {},
|
57 | clientHeight: gl.drawingBufferHeight,
|
58 | },
|
59 | context: gl,
|
60 | });
|
61 | renderer.setSize(gl.drawingBufferWidth, gl.drawingBufferHeight);
|
62 |
|
63 | renderer.setClearColor(0x000000, 1);
|
64 |
|
65 | let lastFrameTime;
|
66 | const animate = () => {
|
67 | this._requestAnimationFrameID = requestAnimationFrame(animate);
|
68 |
|
69 | const now = 0.001 * global.nativePerformanceNow();
|
70 | const dt = typeof lastFrameTime !== 'undefined' ?
|
71 | now - lastFrameTime :
|
72 | 0.16666;
|
73 |
|
74 | if (this.props.tick) {
|
75 | this.props.tick(dt);
|
76 | }
|
77 |
|
78 | if (this.props.scene && this.props.camera) {
|
79 | const camera = this.props.camera;
|
80 | if (this.props.autoAspect && camera.aspect) {
|
81 | const desiredAspect = gl.drawingBufferWidth / gl.drawingBufferHeight;
|
82 | if (camera.aspect !== desiredAspect) {
|
83 | camera.aspect = desiredAspect;
|
84 | camera.updateProjectionMatrix();
|
85 | }
|
86 | }
|
87 | renderer.render(this.props.scene, camera);
|
88 | }
|
89 | gl.flush();
|
90 | gl.endFrameEXP();
|
91 |
|
92 | lastFrameTime = now;
|
93 | };
|
94 | animate();
|
95 | };
|
96 |
|
97 | componentWillUnmount() {
|
98 | if (this._requestAnimationFrameID) {
|
99 | cancelAnimationFrame(this._requestAnimationFrameID);
|
100 | }
|
101 | }
|
102 |
|
103 |
|
104 | render() {
|
105 |
|
106 | const { scene, camera, autoAspect, tick, ...viewProps } = this.props;
|
107 | return (
|
108 | <GLView
|
109 | {...viewProps}
|
110 | onContextCreate={this._onContextCreate}
|
111 | />
|
112 | );
|
113 | }
|
114 | };
|
115 |
|