I have a threejs project where I want to render a model and use the mouse to rotate around it.
this is the kind of idea
https://www.leroymerlin.fr/big2/guides-2021/experience-inspiration.html
I've got an example working, but the controls are bound by click and drags.
the goal is to render a model
have the ability of clicking on a button that will revolve the camera and render a new model as the old one dissipates (currently have a dropdown switching models)
on hovering over the model render a call to action/special mouse animation that would act as a link
be able to pan around the model using the mouse movement (not click drag).
-- I'm playing around with this demo first
https://threejs.org/examples/webgl_animation_keyframes.html
I tried adding stuff like here with the mouse
let mouseX = 0, mouseY = 0;
function onDocumentMouseMove( event ) {
mouseX = ( event.clientX - windowHalfX );
mouseY = ( event.clientY - windowHalfY );
}
function render() {
camera.position.x += ( mouseX - camera.position.x ) * 0.05;
camera.position.y += ( - mouseY - camera.position.y ) * 0.05;
camera.lookAt( scene.position );
renderer.render( scene, camera );
}
but it malfunctions causing the model to spin fast and zoom in too much.
Here is the latest code
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - animation - keyframes</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link type="text/css" rel="stylesheet" href="main.css">
<style>
body {
background-color: #bfe3dd;
color: #000;
}
a {
color: #2983ff;
}
</style>
</head>
<body>
<div id="container"></div>
<div id="info">
<!--
three.js webgl - animation - keyframes<br/>
Model: Littlest Tokyo by
Glen Fox, CC Attribution.
-->
<select id="models">
<option value="models/gltf/LittlestTokyo.glb">LittlestTokyo</option>
<option value="models/gltf/Flamingo.glb" selected="selected">Flamingo</option>
</select>
</div>
<script type="module">
import * as THREE from '../build/three.module.js';
//import Stats from './jsm/libs/stats.module.js';
import { OrbitControls } from './jsm/controls/OrbitControls.js';
import { RoomEnvironment } from './jsm/environments/RoomEnvironment.js';
import { GLTFLoader } from './jsm/loaders/GLTFLoader.js';
import { DRACOLoader } from './jsm/loaders/DRACOLoader.js';
let mixer;
const clock = new THREE.Clock();
const container = document.getElementById( 'container' );
//const stats = new Stats();
//container.appendChild( stats.dom );
const renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.outputEncoding = THREE.sRGBEncoding;
container.appendChild( renderer.domElement );
const pmremGenerator = new THREE.PMREMGenerator( renderer );
const scene = new THREE.Scene();
scene.background = new THREE.Color( 0xbfe3dd );
scene.environment = pmremGenerator.fromScene( new RoomEnvironment(), 0.04 ).texture;
const camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 100 );
camera.position.set( 5, 2, 8 );
const controls = new OrbitControls( camera, renderer.domElement );
controls.target.set( 0, 0.5, 0 );
controls.update();
controls.enablePan = false;
controls.enableDamping = true;
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath( 'js/libs/draco/gltf/' );
const loader = new GLTFLoader();
loader.setDRACOLoader( dracoLoader );
loadModel('models/gltf/Flamingo.glb')
function loadModel(path){
loader.load(path, function ( gltf ) {
//remove model
// remove last model
// if(model) model.parent.remove(model)
scene.clear();
//add model
add(gltf)
}, undefined, function ( e ) {
console.error(e);
});
}
window.onresize = function () {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
};
function add(gltf){
let model = gltf.scene;
model.position.set( 1, 1, 0 );
model.scale.set( 0.01, 0.01, 0.01 );
scene.add( model );
mixer = new THREE.AnimationMixer( model );
mixer.clipAction( gltf.animations[ 0 ] ).play();
animate();
}
function load(path) {
console.log("loading", path)
loadModel(path)
}
document.getElementById('models').addEventListener('change', function() {
console.log('You selected: ', this.value);
console.log("model", window.model)
load(this.value)
});
function animate() {
requestAnimationFrame( animate );
const delta = clock.getDelta();
mixer.update( delta );
controls.update();
//stats.update();
renderer.render( scene, camera );
}
</script>
</body>
</html>
When you do camera.position.x += mouseX - camera.position.x, you're using the x-position to set itself. These self-referencing values will give you erratic behavior. Try something simpler:
camera.position.x = mouseX * 0.05;
Or if you want a smooth animation, you could do linear-interpolation between 2 values:
let mouseXTarget = 0, mouseX = 0;
function onDocumentMouseMove( event ) {
mouseXTarget = ( event.clientX - windowHalfX ) * 0.05;
}
function render() {
// mouseX will smoothly try to reach its target
mouseX = THREE.MathUtils.lerp(mouseX, mouseXTarget, 0.1);
camera.position.x += mouseX;
camera.lookAt( scene.position );
}
Related
hey guys i am new to threejs and im trying to load a texture on top of my own gltf model and im trying to load it with gltf loader, imported using cdn scripts, however, i got this error saying gltf is not a constructor, any ideas how to fix it? thanks in advance. have a nice day. below attached is the code and errors involving this issue.
Uncaught TypeError: THREE.GLTFLoader is not a constructor
at init (index.html:90)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>3d model</title>
<style>
body {
margin: 0;
}
canvas {
position: fixed; top: 0; left: 0;
}
div#test2 {
height: 5000px;
}
</style>
</head>
<body>
<script type="module">
import * as THREE from 'https://cdn.jsdelivr.net/npm/three#0.114/build/three.module.js';
import { OrbitControls } from 'https://cdn.jsdelivr.net/npm/three#0.114/examples/jsm/controls/OrbitControls.js';
import { GLTFLoader } from 'https://cdn.jsdelivr.net/npm/three#0.114/examples/jsm/loaders/GLTFLoader.js';
import { RGBELoader } from 'https://cdn.jsdelivr.net/npm/three#0.114/examples/jsm/loaders/RGBELoader.js';
var container, controls;
var camera, scene, renderer, mixer, clock;
var obj , material , texture
init();
animate();
function init() {
container = document.getElementById( 'test' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.01, 1000 );
// camera.position.set(0, 5, 30);
camera.position.x = 0
camera.position.y = 5
camera.position.z = 10
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
var light = new THREE.HemisphereLight(0xffffff,0x000000,10);
scene.add(light);
clock = new THREE.Clock();
// model
// var loader = new GLTFLoader();
// loader.load( 'scene.gltf', function ( gltf ) {
// // var matcapTexture = new THREE.TextureLoader().load('purple.jpg')
// // var texture = new THREE.MeshMatcapMaterial( {matcap: matcapTexture})
// obj = scene.add( gltf.scene );
// // obj.material.map = texture
// // obj.material.needsUpdate = tru
// mixer = new THREE.AnimationMixer( gltf.scene );
// gltf.animations.forEach( ( clip ) => {
// mixer.clipAction( clip ).play();
// } );
// } );
var textureLoader = new THREE.TextureLoader();
var texture = textureLoader.load('purple.jpg');
texture.flipY = false;
var loader = new THREE.GLTFLoader();
loader.load('scene.gltf', function(gltf) {
model = gltf.scene;
scene.add(model);
});
model.material.map = texture;
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 0.8;
renderer.outputEncoding = THREE.sRGBEncoding;
container.appendChild( renderer.domElement );
function rotateFunction() {
obj.rotation.y += 0.02;
console.log(obj.rotation.y)
}
document.addEventListener('scroll', function(e) { rotateFunction() });
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
//
function animate() {
requestAnimationFrame( animate );
var delta = clock.getDelta();
if ( mixer ) mixer.update( delta );
renderer.render( scene, camera );
}
function adjustCamera() {
var t = scrollY / (5000 - innerHeight);
console.log(t)
// t is 0 to 1
camera.position.z = 10 + 5 * t;
}
document.addEventListener('scroll', function(e) { adjustCamera() });
function changeColor() {
obj.material = texture
console.log(obj)
}
document.addEventListener('scroll', function(e) { changeColor() });
</script>
</body>
<div id="test">
</div>
<div id="test2">
testing121
</div>
</html>
When you import GLTFLoader via ES6 imports, there is no need to use the THREE namespace. Just do this:
const loader = new GLTFLoader();
Hi I am facing a problem on cannot display the 3D model THREE.js GLTFLoader(), the following is my script:
Here is the html file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<link rel="stylesheet" href="./style.css" />
<title>Document</title>
</head>
<body>
<nav>
<ul>
<li>hey</li>
<li>heysda</li>
</ul>
</nav>
<div class="scene"></div>
<script src="./three.min.js"></script>
<script src="./GLTFLoader.js"></script>
<script src="./app.js"></script>
</body>
</html>
here is the js file:
//Variables for setup
let container;
let camera;
let renderer;
let scene;
let house;
function init() {
container = document.querySelector(".scene");
//Create scene
scene = new THREE.Scene();
const fov = 35;
const aspect = container.clientWidth / container.clientHeight;
const near = 0.1;
const far = 1000;
//Camera setup
camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0, 0, 100);
const ambient = new THREE.AmbientLight(0x404040, 2);
scene.add(ambient);
const light = new THREE.DirectionalLight(0xffffff, 2);
light.position.set(50, 50, 100);
scene.add(light);
//Renderer
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setSize(container.clientWidth, container.clientHeight);
renderer.setPixelRatio(window.devicePixelRatio);
container.appendChild(renderer.domElement);
//Load Model
let loader = new THREE.GLTFLoader();
loader.load("./house/scene.gltf", function(gltf) {
scene.add(gltf.scene);
house = gltf.scene.children[0];
animate();
});
}
function animate() {
requestAnimationFrame(animate);
house.rotation.z += 0.005;
renderer.render(scene, camera);
}
init();
function onWindowResize() {
camera.aspect = container.clientWidth / container.clientHeight;
camera.updateProjectionMatrix();
renderer.setSize(container.clientWidth, container.clientHeight);
}
window.addEventListener("resize", onWindowResize);
I ran the code on notepad++ and chrome browser, but it turned out blank screen without showing my 3D model.
Anyone knows the solution? thanks in advance!
The way how you work with container is problematic since clientHeight is zero when you access it to compute the aspect ratio. I suggest you start with using window.innerWidth and window.innerHeight at the beginning.
Besides, there are two minor issues with your model. The model has an extreme scale so you won't see it with your current camera position. You are way too close. Besides, the model has an offset so it's recommended to center it. Try it with this code:
//Variables for setup
let camera;
let renderer;
let scene;
let house;
init();
function init() {
//Create scene
scene = new THREE.Scene();
const fov = 60;
const aspect = window.innerWidth / window.innerHeight;
const near = 0.1;
const far = 1000;
//Camera setup
camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
camera.position.set( 0, 0, 5 );
const ambient = new THREE.AmbientLight( 0xffffff, 0.4 );
scene.add( ambient );
const light = new THREE.DirectionalLight( 0xffffff, 0.8 );
light.position.set( 0, 0, 10 );
scene.add( light );
//Renderer
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
//Load Model
const loader = new THREE.GLTFLoader();
loader.load( './house/scene.gltf', function ( gltf ) {
house = gltf.scene;
// scale model down
house.scale.setScalar( 0.001 );
// center it
const box = new THREE.Box3().setFromObject( house );
const center = box.getCenter( new THREE.Vector3() );
house.position.x += ( house.position.x - center.x );
house.position.y += ( house.position.y - center.y );
house.position.z += ( house.position.z - center.z );
scene.add( house );
animate();
} );
}
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
window.addEventListener( 'resize', onWindowResize );
im have been playing with the examples but since my knowledge is very limited because im a bit dumb, i cant figure out how to change the Model Source of the OBJLoader on click to load a different a model.
I have created a variable "var: name" and have place it as the en source in " loader.load( 'models/obj/goku/' + name, function"
I want to be able to create anchors where the name of the object is the Text of the anchor, but i am unable to change the source 1st.
Any help is greatly appreciated, thanks.
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - loaders - OBJ loader</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link type="text/css" rel="stylesheet" href="main.css">
</head>
<body>
<div id="info">
three.js - OBJLoader test
</div>
<a onclick="changename('GameBoy');">click</a>
<script type="module">
import * as THREE from '../build/three.module.js';
import { OBJLoader } from './jsm/loaders/OBJLoader.js';
import { OrbitControls } from './jsm/controls/OrbitControls.js';
var container;
var camera, scene, renderer;
var mouseX = 0, mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
var controls;
var object;
var name ="Engine.obj";
init();
animate();
function changename(newname){
name = newname;
}
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
camera.position.z = 250;
// scene
scene = new THREE.Scene();
var ambientLight = new THREE.AmbientLight( 0xcccccc, 0.4 );
scene.add( ambientLight );
var pointLight = new THREE.PointLight( 0xffffff, 0.8 );
camera.add( pointLight );
scene.add( camera );
// manager
function loadModel() {
object.traverse( function ( child ) {
if ( child.isMesh ) child.material.map = texture;
} );
object.position.y = -20;
scene.add( object );
}
var manager = new THREE.LoadingManager( loadModel );
manager.onProgress = function ( item, loaded, total ) {
console.log( item, loaded, total );
};
// texture
var textureLoader = new THREE.TextureLoader( manager );
var texture = textureLoader.load( 'textures/hardwood2_diffuse.jpg' );
// model
function onProgress( xhr ) {
if ( xhr.lengthComputable ) {
var percentComplete = xhr.loaded / xhr.total * 100;
console.log( 'model ' + Math.round( percentComplete, 2 ) + '% downloaded' );
}
}
function onError() {}
var loader = new OBJLoader( manager );
loader.load( 'models/obj/goku/' + name, function ( obj ) {
object = obj;
object.position.x = 0;
object.position.z = 1;
object.scale.set(0.5,0.5,0.5);
}, onProgress, onError );
//
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
// document.addEventListener( 'mousemove', onDocumentMouseMove, false );
//
window.addEventListener( 'resize', onWindowResize, false );
// controls
controls = new OrbitControls( camera, renderer.domElement );
//controls.addEventListener( 'change', render ); // call this only in static scenes (i.e., if there is no animation loop)
controls.enableDamping = true; // an animation loop is required when either damping or auto-rotation are enabled
controls.dampingFactor = 0.05;
// controls.screenSpacePanning = true;
// controls.minDistance = 100;
// controls.maxDistance = 500;
// controls.maxPolarAngle = Math.PI / 2;
}
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
// function onDocumentMouseMove( event ) {
//
// mouseX = ( event.clientX - windowHalfX ) / 2;
// mouseY = ( event.clientY - windowHalfY ) / 2;
//
// }
//
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
// camera.position.x += ( mouseX - camera.position.x ) * .05;
// camera.position.y += ( - mouseY - camera.position.y ) * .05;
// camera.lookAt( scene.position );
renderer.render( scene, camera );
controls.update(); // only required if controls.enableDamping = true, or if controls.autoRotate = true
}
</script>
</body>
</html>
When working with modules, you can't refer to module scope functions like so:
<a onclick="changename('GameBoy');">click</a>
That does not work since changename() only exists in module but not in global scope. You have to add the click event listener by defining an id for your link/button and then select it like so:
const element = document.getElementById( 'myButton' );
element.addEventListener( 'click', changename );
Notice that you can't pass the newname parameter like in your original code. Consider to store it in a data attribute if you want to reuse the function.
Even if you register the event listener like that, your code will not work as intended. Simply because changename() only changes the name but does not trigger a new call of OBJLoader.load().
I just recently started creating a 3D model for a website I am creating.. and for some reason one of the arms of the character is transparent, but only partially as in you can see inside it. As seen here:
Transparent arm and I can't figure it out. I tried back tracking some of my code to no avail, and I tried re rendering it in blender (as it is a .obj import) and it still has the same issue. Does anyone happen to know a fix for the issue?
<body>
<script src="./JS/three.js"></script>
<script src="./JS/DDSLoader.js"></script>
<script src="./JS/MTLLoader.js"></script>
<script src="./JS/OBJLoader.js"></script>
<script src="./JS/OrbitControls.js"></script>
<script src="./JS/Detector.js"></script>
<script src="./JS/stats.min.js"></script>
<script>
var container, stats;
var camera, scene, renderer;
var mouseX = 0, mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
renderer = new THREE.WebGLRenderer( {
alpha: true,
antialias: true
} );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( 200,300);
container.appendChild( renderer.domElement );
camera = new THREE.PerspectiveCamera( 14, window.innerWidth / window.innerHeight, .3, 1000 );
camera.position.z = 1;
camera.position.y = 8;
//camera.rotation.y = -90*(180/3.14159265)
var orbit = new THREE.OrbitControls( camera, renderer.domElement );
orbit.enableZoom = false;
orbit.enablePan = false;
orbit.autoRotate = true;
// scene
scene = new THREE.Scene();
var ambient = new THREE.AmbientLight( 0xffffff );
scene.add( ambient );
var dirLight = new THREE.DirectionalLight(0xffffff, .41);
dirLight.position.set(100, 100, 50);
scene.add(dirLight);
var light = new THREE.PointLight( 0xf8f8ff, 0.25, 10000 );
light.position.set( 0, 100,-75);
scene.add( light );
//var directionalLight = new THREE.DirectionalLight( 0xf8f8ff );
//directionalLight.position.set( 0, 0, 1 ).normalize();
//scene.add( directionalLight );
// model
var onProgress = function ( xhr ) {
if ( xhr.lengthComputable ) {
var percentComplete = xhr.loaded / xhr.total * 100;
console.log( Math.round(percentComplete, 2) + '% downloaded' );
}
};
var onError = function ( xhr ) { };
THREE.Loader.Handlers.add( /\.dds$/i, new THREE.DDSLoader() );
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setBaseUrl( './Avatar/' );
mtlLoader.setPath( './Avatar/' );
mtlLoader.load( 'Avatar.mtl', function( materials ) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials( materials );
objLoader.setPath( './Avatar/' );
objLoader.load( 'Avatar.obj', function ( object )
{
object.alphaTest = 0;
object.transparent = false;
object.side = THREE.DoubleSide;
//object.rotation.y = -25*(180/3.14159265)
//object.rotation.x = -35*(180/3.14159265)
object.position.y = 0;
scene.add( object );
}, onProgress, onError );
});
//
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
//
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
//renderer.setSize( window.innerWidth, window.innerHeight );
}
function onDocumentMouseMove( event ) {
mouseX = ( event.clientX - windowHalfX ) / 2;
mouseY = ( event.clientY - windowHalfY ) / 2;
}
//
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
//camera.position.x += ( mouseX - camera.position.x ) * .005;
//camera.position.y += ( - mouseY - camera.position.y ) * .005;
camera.lookAt( scene.position );
renderer.render( scene, camera );
}
</script>
I'm a bit lost at this point and could really use your help! Thanks in advance. If you have any questions, or not sure about something in my code let me know.
Face normals of the arm might be flipped backside. As you may know, if the face normal is facing backside, it will not be rendered, and only back-side will be rendered, even in 3d modeler too such as blender.
You can check normal direction in three.js using FaceNormalsHelper as well.
Docs for the helper:
http://threejs.org/docs/#Reference/Extras.Helpers/FaceNormalsHelper
http://threejs.org/examples/#webgl_helpers
If normal direction were wrong, flip them in your 3d modeler app.
I have a cube in ThreeJS and I would like to rotate it 90 degrees clockwise every time I press a button. I think I have the basic gist of it: create a Three.Animation instance, bind it to the cube, and then have the animation begin every time I press the correct button. However, I'm having a difficult time understanding ThreeJS's API, because it doesn't seem to contain any examples for its methods.
This is THREE.js's Animation constructor: ( root, data, interpolationType, JITCompile ) I don't understand what goes into the fields. I'm guessing root would be where I put my cube, but what about the rest?
Also can I just call animation.play() to cause the animation whenever I want? And how does the animationHandler work?
I think for for rotating an object 90 degrees clockwise, using the TWEEN class will do. I think the Animation class is handy for heavier stuff (like bones/skin morphs/etc.)
To use the tween class there are 3 basic steps:
include the class in your file (<script src="js/Tween.js"></script>)
add your tween for the event you need (new TWEEN.Tween( cube.rotation ).to( { y:Math.random()}, 1000 ).easing( TWEEN.Easing.Quadratic.EaseOut).start();)
update the tween in your render loop (TWEEN.update();)
You can have a have a look at the cubes tween example for a start.
I've modified the default cube example to have the tween in:
<!doctype html>
<html lang="en">
<head>
<title>three.js canvas - geometry - cube</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
font-family: Monospace;
background-color: #f0f0f0;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<script src="../build/Three.js"></script>
<script src="js/Tween.js"></script>
<script src="js/RequestAnimationFrame.js"></script>
<script src="js/Stats.js"></script>
<script>
var container, stats;
var camera, scene, renderer;
var cube, plane;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
var rad90 = Math.PI * .5;
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
var info = document.createElement( 'div' );
info.style.position = 'absolute';
info.style.top = '10px';
info.style.width = '100%';
info.style.textAlign = 'center';
info.innerHTML = 'click to tween';
container.appendChild( info );
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.y = 150;
camera.position.z = 500;
scene = new THREE.Scene();
// Cube
var materials = [];
for ( var i = 0; i < 6; i ++ ) {
materials.push( [ new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff } ) ] );
}
cube = new THREE.Mesh( new THREE.CubeGeometry( 200, 200, 200, 1, 1, 1, materials ), new THREE.MeshFaceMaterial() );
cube.position.y = 150;
cube.overdraw = true;
scene.add( cube );
// Plane
plane = new THREE.Mesh( new THREE.PlaneGeometry( 200, 200 ), new THREE.MeshBasicMaterial( { color: 0xe0e0e0 } ) );
plane.rotation.x = - 90 * ( Math.PI / 180 );
plane.overdraw = true;
scene.add( plane );
renderer = new THREE.CanvasRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
container.appendChild( stats.domElement );
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
}
//
function onDocumentMouseDown( event ) {
event.preventDefault();
new TWEEN.Tween( cube.rotation ).to( { y: cube.rotation.y + rad90}, 1000 ).easing( TWEEN.Easing.Quadratic.EaseOut).start();
new TWEEN.Tween( plane.rotation ).to( { z: plane.rotation.z + rad90}, 1000 ).easing( TWEEN.Easing.Quadratic.EaseOut).start();
console.log("click");
}
//
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}
function render() {
TWEEN.update();
renderer.render( scene, camera );
}
</script>
</body>
</html>