expo
Version:
The Expo SDK
117 lines (98 loc) • 3.36 kB
JavaScript
;
import React, { PropTypes } from 'react';
import { View, ViewPropTypes } from 'react-native';
import GLView from './GLView';
export default THREE => class THREEView extends React.Component {
static propTypes = {
// Parameters to http://threejs.org/docs/?q=webgl#Reference/Renderers/WebGLRenderer.render
scene: PropTypes.object,
camera: PropTypes.object,
// Whether to automatically set the aspect ratio of the camera from
// the viewport. Defaults to `true`.
autoAspect: PropTypes.bool,
// NOTE: 0x000000 is considered a PropType.number, while '#000000' is considered a PropType.string.
backgroundColor: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
backgroundColorAlpha: PropTypes.number,
// Called every animation frame with one parameter `dt` which is the
// time in seconds since the last animation frame
tick: PropTypes.func,
...ViewPropTypes,
};
static defaultProps = {
autoAspect: true,
backgroundColor: 0x000000,
backgroundColorAlpha: 1,
};
// Get a three.js texture from an Exponent Asset
static textureFromAsset(asset) {
if (!asset.localUri) {
throw new Error(
`Asset '${asset.name}' needs to be downloaded before ` +
`being used as an OpenGL texture.`
);
}
const texture = new THREE.Texture();
texture.image = {
data: asset,
width: asset.width,
height: asset.height,
};
texture.needsUpdate = true;
texture.isDataTexture = true; // send to gl.texImage2D() verbatim
return texture;
}
_onContextCreate = gl => {
const renderer = new THREE.WebGLRenderer({
canvas: {
width: gl.drawingBufferWidth,
height: gl.drawingBufferHeight,
style: {},
addEventListener: () => {},
removeEventListener: () => {},
clientHeight: gl.drawingBufferHeight,
},
context: gl,
});
renderer.setSize(gl.drawingBufferWidth, gl.drawingBufferHeight);
renderer.setClearColor(
this.props.backgroundColor,
this.props.backgroundColorAlpha
);
let lastFrameTime;
const animate = () => {
this._requestAnimationFrameID = requestAnimationFrame(animate);
const now = 0.001 * global.nativePerformanceNow();
const dt = typeof lastFrameTime !== 'undefined'
? now - lastFrameTime
: 0.16666;
if (this.props.tick) {
this.props.tick(dt);
}
if (this.props.scene && this.props.camera) {
const camera = this.props.camera;
if (this.props.autoAspect && camera.aspect) {
const desiredAspect = gl.drawingBufferWidth / gl.drawingBufferHeight;
if (camera.aspect !== desiredAspect) {
camera.aspect = desiredAspect;
camera.updateProjectionMatrix();
}
}
renderer.render(this.props.scene, camera);
}
gl.flush();
gl.endFrameEXP();
lastFrameTime = now;
};
animate();
};
componentWillUnmount() {
if (this._requestAnimationFrameID) {
cancelAnimationFrame(this._requestAnimationFrameID);
}
}
render() {
// eslint-disable-next-line no-unused-vars
const { scene, camera, autoAspect, tick, ...viewProps } = this.props;
return <GLView {...viewProps} onContextCreate={this._onContextCreate} />;
}
};