for example: [ // import THREE from 'threejs_react';
import { THREE , CarControls , DRACOLoader , GLTFLoader , PMREMCubeUVPacker , PMREMGenerator } from 'threejs_react';
import { FormControl, FormHelperText, NativeSelect, Typography , Checkbox } from '@material-ui/core'; import * as React from 'react'; import './carshow.css';
interface IProps { a: any ; }
class CarShow extends React.Component<any, any> {
private camera ;
private scene ;
private renderer ;
private stats ;
private carModel;
private envMap = null;
private clock = new THREE.Clock();
private carControls = new CarControls();
private carParts = {
body: [],
rim: [],
glass: [],
};
private damping = 5.0;
private distance = 5;
private cameraTarget = new THREE.Vector3();
private pmremGenerator;
private pmremCubeUVPacker;
constructor(props: IProps) {
super(props);
this.carControls.turningRadius = 75;
this.state = {
followCamera: false ,
materialsLib : {
main: [],
glass: [],
},
bodySelectIndex: 0,
rimsSelectIndex: 0,
glassSelectIndex: 0,
};
}
componentDidMount() {
this.init();
}
public async init() {
const container = document.getElementById('container');
this.camera = new THREE.PerspectiveCamera(50 , window.innerWidth / window.innerHeight , 0.1 , 200 );
this.camera.position.set( 3.25, 2.0, - 5 );
this.camera.lookAt( 0 , 0.5 , 0 );
this.scene = new THREE.Scene();
this.scene.fog = new THREE.Fog( 0xd7cbb1, 1 , 80 );
console.log(this.scene);
let light = new THREE.HemisphereLight( 0xffffff, 0x444444 );
light.position.set( 0, 20, 0 );
// this.scene.add( light );
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 0, 20, 10 );
// this.scene.add( light );
const urls = [ 'px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg' ];
let loader = new THREE.CubeTextureLoader();
loader.setPath( './textures/cube/skyboxsun25deg/');
await loader.load( urls, (texture: any) => {
console.log(texture);
this.scene.background = texture;
console.log(this.scene);
this.pmremGenerator = new PMREMGenerator( texture );
this.pmremGenerator.update( this.renderer );
this.pmremCubeUVPacker = new PMREMCubeUVPacker( this.pmremGenerator.cubeLods );
this.pmremCubeUVPacker.update( this.renderer );
console.log(this.pmremCubeUVPacker.CubeUVRenderTarget.texture);
this.envMap = this.pmremCubeUVPacker.CubeUVRenderTarget.texture;
console.log(this.envMap);
this.pmremGenerator.dispose();
this.pmremCubeUVPacker.dispose();
this.initCar();
this.initMaterials();
});
console.log(loader);
let grid = new THREE.GridHelper(400 , 40 , 0x000000, 0x000000);
grid.material.opacity = 0.2;
grid.material.depthWrite = false;
grid.material.transparent = true;
this.scene.add(grid);
this.renderer = new THREE.WebGLRenderer( { antialias: true } );
this.renderer.gammaOutput = true;
this.renderer.setPixelRatio( window.devicePixelRatio );
this.renderer.setSize( window.innerWidth, window.innerHeight );
console.log(this.camera);
console.log(this.renderer);
container.appendChild( this.renderer.domElement );
window.addEventListener( 'resize', this.onWindowResize , false );
this.animation();
}
private onWindowResize = () => {
this.camera.aspect = (window.innerWidth / window.innerHeight);
this.camera.updateProjectionMatrix();
this.renderer.setSize(window.innerWidth, window.innerHeight);
console.log(window.innerWidth, window.innerHeight);
console.log( document.body.clientWidth , document.body.clientHeight);
}
private initCar() {
DRACOLoader.setDecoderPath( '/js/libs/draco/gltf/' );
const loader = new GLTFLoader();
loader.setDRACOLoader( new DRACOLoader() );
loader.load( '/models/gltf/ferrari.glb', ( gltf: any ) => {
console.log( gltf.scene.children[ 0 ]);
this.carModel = gltf.scene.children[ 0 ];
this.carControls.setModel( this.carModel , null );
this.carModel.traverse( ( child: any ) => {
if ( child.isMesh ) {
child.material.envMap = this.envMap;
}
} );
// shadow
const texture = new THREE.TextureLoader().load( '/models/gltf/ferrari_ao.png' );
const shadow = new THREE.Mesh(
new THREE.PlaneBufferGeometry( 0.655 * 4, 1.3 * 4 ).rotateX( - Math.PI / 2 ),
new THREE.MeshBasicMaterial( { map: texture, opacity: 0.8, transparent: true } )
);
shadow.renderOrder = 2;
this.carModel.add( shadow );
this.scene.add( this.carModel );
// car parts for material selection
this. carParts.body.push( this.carModel.getObjectByName( 'body' ) );
this.carParts.rim.push(
this.carModel.getObjectByName( 'rim_fl' ),
this.carModel.getObjectByName( 'rim_fr' ),
this.carModel.getObjectByName( 'rim_rr' ),
this. carModel.getObjectByName( 'rim_rl' ),
this.carModel.getObjectByName( 'trim' ),
);
this.carParts.glass.push(
this.carModel.getObjectByName( 'glass' ),
);
this.updateMaterials();
}) ;
}
private initMaterials() {
let materialsLib = {
main: [
new THREE.MeshStandardMaterial( {
color: 0xff4400, envMap: this.envMap, metalness: 0.9, roughness: 0.2, name: 'orange' } ),
new THREE.MeshStandardMaterial( {
color: 0x001166, envMap: this.envMap, metalness: 0.9, roughness: 0.2, name: 'blue' } ),
new THREE.MeshStandardMaterial( {
color: 0x990000, envMap: this.envMap, metalness: 0.9, roughness: 0.2, name: 'red' } ),
new THREE.MeshStandardMaterial( {
color: 0x000000, envMap: this.envMap, metalness: 0.9, roughness: 0.5, name: 'black' } ),
new THREE.MeshStandardMaterial( {
color: 0xffffff, envMap: this.envMap, metalness: 0.9, roughness: 0.5, name: 'white' } ),
new THREE.MeshStandardMaterial( {
color: 0x555555, envMap: this.envMap, envMapIntensity: 2.0, metalness: 1.0,
roughness: 0.2, name: 'metallic' } ),
],
glass: [
new THREE.MeshStandardMaterial( {
color: 0xffffff, envMap: this.envMap, metalness: 1, roughness: 0,
// tslint:disable-next-line: max-line-length
opacity: 0.2, transparent: true, premultipliedAlpha: true, name: 'clear' } ),
new THREE.MeshStandardMaterial( {
color: 0x000000, envMap: this.envMap, metalness: 1, roughness: 0,
// tslint:disable-next-line: max-line-length
opacity: 0.2, transparent: true, premultipliedAlpha: true, name: 'smoked' } ),
new THREE.MeshStandardMaterial( {
color: 0x001133, envMap: this.envMap, metalness: 1, roughness: 0,
opacity: 0.2, transparent: true, premultipliedAlpha: true, name: 'blue' } ),
],
};
this.setState({
materialsLib: materialsLib
});
}
private updateMaterials() {
const e1 = {target: {value: 3}};
this.handleChange(e1);
const e2 = {target: {value: 5}};
this.handleRimsChange(e2);
const e3 = {target: {value: 0}};
this.handleGlassChange(e3);
}
private animation() {
this.update();
requestAnimationFrame(() => this.animation());
}
private update() {
const delta = this.clock.getDelta();
const {followCamera} = this.state;
if ( this.carModel ) {
this.carControls.update(delta / 3);
if ( this.carModel.position.length() > 200 ) {
this.carModel.position.set(0, 0 , 0);
this.carControls.speed = 0;
}
if ( followCamera ) {
this.carModel.getWorldPosition( this.cameraTarget );
this.cameraTarget.y = 2.5;
this.cameraTarget.z += this.distance;
this.camera.position.lerp( this.cameraTarget , delta * this.damping );
} else {
this.carModel.getWorldPosition( this.cameraTarget );
this.cameraTarget.y += 0.5;
this.camera.position.set( 3.25, 2.0, - 5 );
}
this.camera.lookAt( this.carModel.position );
}
this.renderer.render(this.scene , this.camera);
}
handleChange(event: any) {
console.log(event);
const bodyMat = this.state.materialsLib.main[ event.target.value ];
this.setState({
bodySelectIndex: event.target.value
});
this.carParts.body.forEach( part => part.material = bodyMat );
}
// 渲染车身颜色下拉列表
public renderBodyColor() {
return (
<Typography component="span">
车身颜色:
<FormControl className={' '}>
<NativeSelect
value={this.state.bodySelectIndex}
onChange={(event) => this.handleChange(event)}
name="age"
className={''}
inputProps={{ 'aria-label': 'age' }}
>
{this.state.materialsLib.main.map( (val , index) => {
return(
<option value={index} key = {index}>{val.name}</option>
);
})}
</NativeSelect>
<FormHelperText>Body Color</FormHelperText>
</FormControl>
</Typography>
);
}
// 细节选择的点击事件
handleRimsChange(event: any) {
console.log(event);
const bodyMat = this.state.materialsLib.main[ event.target.value ];
this.setState({
rimsSelectIndex: event.target.value
});
this.carParts.rim.forEach( part => part.material = bodyMat );
}
// 渲染细节颜色下拉列表
public renderRimsColor() {
return (
<Typography component="span">
细节颜色:
<FormControl className={' '}>
<NativeSelect
value={this.state.rimsSelectIndex}
onChange={(event) => this.handleRimsChange(event)}
name="age"
className={''}
inputProps={{ 'aria-label': 'age' }}
>
{this.state.materialsLib.main.map( (val , index) => {
return(
<option value={index} key = {index}>{val.name}</option>
);
})}
</NativeSelect>
<FormHelperText>Rims Color</FormHelperText>
</FormControl>
</Typography>
);
}
// 玻璃选择的点击事件
handleGlassChange(event: any) {
console.log(event);
const bodyMat = this.state.materialsLib.glass[ event.target.value ];
this.setState({
glassSelectIndex: event.target.value
});
this.carParts.glass.forEach( part => part.material = bodyMat );
}
// 渲染玻璃颜色下拉列表
public renderGlassColor() {
return (
<Typography component="span">
玻璃颜色:
<FormControl className={' '}>
<NativeSelect
value={this.state.glassSelectIndex}
onChange={(event) => this.handleGlassChange(event)}
name="age"
className={''}
inputProps={{ 'aria-label': 'age' }}
>
{this.state.materialsLib.glass.map( (val , index) => {
return(
<option value={index} key = {index}>{val.name}</option>
);
})}
</NativeSelect>
<FormHelperText>Glass Color</FormHelperText>
</FormControl>
</Typography>
);
}
handleCheckChange(event: any) {
const val = !this.state.followCamera;
this.setState({
followCamera: val,
});
}
renderCheckBox() {
return(
<Checkbox
checked={this.state.followCamera}
onChange= {(event) => this.handleCheckChange(event)}
value="checkedA"
inputProps={{
'aria-label': 'primary checkbox',
}}
/>
);
}
public render() {
return(
<div>
汽车测试
{this.renderBodyColor()}
{this.renderRimsColor()}
{this.renderGlassColor()}
{this.renderCheckBox()}
<div id = "container" className = "pos">
</div>
</div>
);
}
}
export default CarShow ; ]