Last active
April 6, 2018 03:30
-
-
Save agm1984/1fa1368631293fc694522aa1e50aaea7 to your computer and use it in GitHub Desktop.
Some THREE.js experiementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { Component } from 'react' | |
import * as THREE from 'three' | |
// import * as OBJLoader from 'three-obj-loader' | |
// import MTLLoader from 'three-react-mtl-loader' | |
// import OBJLoader from 'three-react-obj-loader' | |
// const loader = require('three-json-loader')(THREE) | |
const OrbitControls = require('three-orbit-controls')(THREE) | |
// OrbitControls: for Camera | |
// - This file should contain all the basic ingredients and how they fit together | |
// based on about 100 hours research. | |
// - This file's utility will magnify as you gain experience. | |
class Scene extends Component { | |
constructor(props) { | |
super(props) | |
this.state = {} | |
this.cat = { | |
rotation: { | |
x: 0, | |
y: 0, | |
z: 0, | |
}, | |
} | |
this.adamAction = {} | |
this.isLoaded = false | |
this.clock = null | |
this.delta = 0 | |
this.adamAction = {} | |
this.adamMixer = null | |
this.from = null | |
this.to = null | |
this.activeActionName = 'idle' | |
this.arrAnimations = ['idle', 'walk', 'run', 'hello'] | |
this.currentAnimation = 0 | |
this.mount = null | |
this.handleDoubleClick = this.handleDoubleClick.bind(this) | |
this.start = this.start.bind(this) | |
this.stop = this.stop.bind(this) | |
this.animate = this.animate.bind(this) | |
} | |
componentDidMount() { | |
// SETUP | |
this.clock = new THREE.Clock() | |
this.width = this.mount.clientWidth | |
this.height = this.mount.clientHeight | |
this.windowHalfX = this.mount.clientWidth / 2 | |
this.windowHalfY = this.mount.clientHeight / 2 | |
// CAMERA | |
this.camera = new THREE.PerspectiveCamera(85, this.width / this.height, 1, 4000) | |
// this.camera.up = new THREE.Vector3(0, 0, 1) | |
// this.camera.lookAt(new THREE.Vector3(0, 0, 10)) | |
this.camera.position.x = 5 | |
this.camera.position.y = 5 | |
this.camera.position.z = 5 | |
this.camera.position.set(0, 0, -10) | |
// this.controls = new THREE.FirstPersonControls(this.camera, this.mount) | |
// this.controls.movementSpeed = 50 | |
// this.controls.lookSpeed = 0.05 | |
// this.controls.noFly = true | |
// this.controls.lookVertical = false | |
// SCENE | |
this.scene = new THREE.Scene() | |
this.ambient = new THREE.AmbientLight(0xffffff, 1.0) | |
this.scene.add(this.ambient) | |
// LIGHTS | |
// this.keyLight = new THREE.DirectionalLight(new THREE.Color('hsl(30, 100%, 75%)'), 1.0) | |
// this.keyLight.position.set(-100, 0, 100) | |
// this.fillLight = new THREE.DirectionalLight(new THREE.Color('hsl(240, 100%, 75%)'), 0.75) | |
// this.fillLight.position.set(100, 0, 100) | |
// this.backLight = new THREE.DirectionalLight(0xffffff, 1.0) | |
// this.backLight.position.set(100, 0, -100).normalize() | |
// this.scene.add(this.keyLight) | |
// this.scene.add(this.fillLight) | |
// this.scene.add(this.backLight) | |
// // FEMALE MODEL | |
// this.mtlLoader = new MTLLoader() | |
// this.mtlLoader.setBaseUrl('') | |
// this.mtlLoader.setPath('female3d/') | |
// this.mtlLoader.load('female-croupier-2013-03-26.mtl', (materials) => { | |
// materials.preload() /* eslint-disable no-param-reassign */ | |
// materials.materials.default.map.magFilter = THREE.NearestFilter | |
// materials.materials.default.map.minFilter = THREE.LinearFilter | |
// this.objLoader = new OBJLoader() /* eslint-enable no-param-reassign */ | |
// this.objLoader.setMaterials(materials) | |
// this.objLoader.setPath('guy/') | |
// this.objLoader.load('female-croupier-2013-03-26.obj', (object) => { | |
// this.scene.add(object) | |
// }) | |
// }) | |
// ADAM MODEL | |
this.adamLoader = new THREE.JSONLoader() | |
this.adamLoader.load('anime.json', (geometry, materials) => { | |
materials.forEach((material) => { | |
material.skinning = true // eslint-disable-line no-param-reassign | |
}) | |
this.adamCharacter = new THREE.SkinnedMesh( | |
geometry, | |
new THREE.MeshFaceMaterial(materials), | |
) | |
this.adamMixer = new THREE.AnimationMixer(this.adamCharacter) | |
this.adamAction.hello = this.adamMixer.clipAction(geometry.animations[0]) | |
this.adamAction.idle = this.adamMixer.clipAction(geometry.animations[1]) | |
this.adamAction.run = this.adamMixer.clipAction(geometry.animations[3]) | |
this.adamAction.walk = this.adamMixer.clipAction(geometry.animations[4]) | |
this.adamAction.hello.setEffectiveWeight(1) | |
this.adamAction.idle.setEffectiveWeight(1) | |
this.adamAction.run.setEffectiveWeight(1) | |
this.adamAction.walk.setEffectiveWeight(1) | |
this.adamAction.hello.setLoop(THREE.LoopOnce, 0) | |
this.adamAction.hello.clampWhenFinished = true | |
this.adamAction.hello.enabled = true | |
this.adamAction.idle.enabled = true | |
this.adamAction.run.enabled = true | |
this.adamAction.walk.enabled = true | |
this.scene.add(this.adamCharacter) | |
// window.addEventListener('resize', onWindowResize, false) | |
// window.addEventListener('click', onDoubleClick, false) | |
console.log('Double click to change animation') | |
this.animate() | |
this.isLoaded = true | |
this.adamAction.idle.play() | |
}) | |
// CAT MODEL | |
this.catMaterial = new THREE.MeshBasicMaterial({ | |
map: THREE.ImageUtils.loadTexture('newCat.png'), | |
side: THREE.DoubleSide, | |
}) | |
this.catLoader = new THREE.JSONLoader() | |
this.catLoader.load('newCat.json', (geometry) => { | |
this.cat = new THREE.Mesh(geometry, this.catMaterial) | |
this.cat.position.x = 2 | |
this.cat.position.y = 0 | |
this.cat.position.z = -1 | |
// this.cat.dir = (Math.random() - Math.random()) * 0.1 | |
this.scene.add(this.cat) | |
}) | |
// // GUY MODEL | |
// this.guyMaterial = new THREE.MeshBasicMaterial({ | |
// map: THREE.ImageUtils.loadTexture('guy/Malcom_Body_Diffuse.png'), | |
// side: THREE.DoubleSide, | |
// }) | |
// this.guyLoader = new THREE.JSONLoader() // | |
// this.guyLoader.load('guy/walking-animation.json', (geometry) => { | |
// this.guy = new THREE.Mesh(geometry, this.guyMaterial) | |
// this.guy.position.x = 0 | |
// this.guy.position.y = 0 | |
// this.guy.position.z = -2 | |
// // this.guy.dir = (Math.random() - Math.random()) * 0.1 | |
// this.scene.add(this.guy) | |
// }) | |
// RENDER | |
this.renderer = new THREE.WebGLRenderer() | |
this.renderer.setPixelRatio(window.devicePixelRatio) | |
this.renderer.setSize(this.width, this.height) | |
this.renderer.setClearColor(new THREE.Color('hsl(0, 0%, 10%)')) | |
this.mount.appendChild(this.renderer.domElement) | |
this.controls = new OrbitControls(this.camera, this.renderer.domElement) | |
this.controls.center.set(0, 0, 0) | |
this.controls.addEventListener('change', this.renderScene) | |
// // TERRAIN | |
// const geometry = new THREE.PlaneGeometry(600, 600, 30, 30) | |
// const { length } = geometry.vertices | |
// for (let index = 0; index < length; index += 1) { | |
// geometry.vertices[index].z = Math.floor((Math.random() * 10) + 1) | |
// } | |
// const material = new THREE.MeshBasicMaterial({ | |
// wireframe: true, | |
// color: '#66FCF1', | |
// }) | |
// this.terrain = new THREE.Mesh(geometry, material) | |
// this.terrain.overdraw = true | |
// this.terrain.rotation.x = 90 | |
// this.terrain.rotation.y = 0 | |
// this.terrain.rotation.z = 0 | |
// this.terrain.position.x = 0 | |
// this.terrain.position.y = 2 | |
// this.terrain.position.z = 0 | |
// this.scene.add(this.terrain) | |
window.scene = this.scene | |
window.THREE = THREE | |
this.start() | |
} | |
componentWillUnmount() { | |
this.stop() | |
this.mount.removeChild(this.renderer.domElement) | |
} | |
handleDoubleClick() { | |
this.currentAnimation += 1 | |
this.fadeAction(this.arrAnimations[this.currentAnimation]) | |
} | |
fadeAction(name) { | |
this.from = this.adamAction[this.activeActionName].play() | |
this.to = this.adamAction[name].play() | |
this.from.enabled = true | |
this.to.enabled = true | |
if (this.to.loop === THREE.LoopOnce) { | |
this.to.reset() | |
} | |
this.from.crossFadeTo(this.to, 0.3) | |
this.activeActionName = name | |
} | |
start() { | |
if (!this.frameId) { | |
this.frameId = requestAnimationFrame(this.animate) | |
} | |
} | |
stop() { | |
cancelAnimationFrame(this.frameId) | |
} | |
animate = () => { | |
// this.cat = this.cat || {} | |
// this.cat.position.x += 0.01 | |
// this.cat.rotation.y += 0.01 | |
// this.cat.rotation.z += 0.01 | |
// this.camera.position.z += 0.01 | |
this.frameId = window.requestAnimationFrame(this.animate) | |
this.controls.update() | |
this.renderScene() | |
} | |
renderScene = () => { | |
if (!this.adamMixer) { | |
return | |
} | |
this.delta = this.clock.getDelta() | |
this.adamMixer.update(this.delta) | |
this.renderer.render(this.scene, this.camera) | |
} | |
render() { | |
return ( | |
<div | |
style={{ | |
overflow: 'hidden', | |
position: 'absolute', | |
top: 0, | |
left: 0, | |
width: '100%', | |
height: '100vh', | |
}} | |
ref={(mount) => { this.mount = mount }} | |
onDoubleClick={this.handleDoubleClick} | |
/> | |
) | |
} | |
} | |
export default Scene |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment