Rotate object with rotated parent in world space? - javascript

I'm using this function to rotate object Y axis in world space:
function rotateWorldYAxis( obj, angle ) {
quat.setFromAxisAngle( new THREE.Vector3(0,1,0), angle );
obj.quaternion.multiplyQuaternions(quat,obj.quaternion);
obj.updateMatrixWorld();
}
But it doesn't work with the object has rotated parent.
Here is example Fiddle:
Correct behavior when parent not rotated:
var SCREEN_WIDTH = window.innerWidth;
var SCREEN_HEIGHT = window.innerHeight;
var container, stats;
var camera, scene, controls;
var renderer;
var quat = new THREE.Quaternion();
var axis = new THREE.Vector3();
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
// CAMERA
camera = new THREE.PerspectiveCamera( 30, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000 );
camera.position.set( 0, 0, 500 );
scene = new THREE.Scene();
scene.add( new THREE.AmbientLight( 0xaaaaaa ) );
var light = new THREE.PointLight( 0xffffff );
light.position.set(100,100,100);
scene.add( light );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
renderer.domElement.style.position = "relative";
container.appendChild( renderer.domElement );
//____________________________//
cube = new THREE.Mesh(
new THREE.CubeGeometry(50,100,50),
new THREE.MeshPhongMaterial()
);
cube.rotation.set(Math.PI/3, 0, 0);
cubeParent = new THREE.Object3D();
cubeParent.rotation.set(0,0,0) //Not rotated parent
cubeParent.add(cube)
scene.add(cubeParent)
//____________________________//
var grid = new THREE.Mesh(
new THREE.PlaneGeometry(200, 200, 10, 10),
new THREE.MeshBasicMaterial({wireframe: true})
)
grid.position.y = -100
grid.rotation.x = Math.PI/2
scene.add(grid);
window.addEventListener( 'resize', onWindowResize, false );
}
function rotateWorldYAxis( obj, angle ) {
quat.setFromAxisAngle( new THREE.Vector3(0,1,0), angle );
obj.quaternion.multiplyQuaternions(quat,obj.quaternion);
obj.updateMatrixWorld();
}
function animate() {
requestAnimationFrame( animate );
render();
rotateWorldYAxis(cube, 0.01)
}
function render() {
renderer.render( scene, camera );
}
function onWindowResize( event ) {
SCREEN_WIDTH = window.innerWidth;
SCREEN_HEIGHT = window.innerHeight;
renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
camera.aspect = SCREEN_WIDTH / SCREEN_HEIGHT;
camera.updateProjectionMatrix();
}
<script src="https://threejs.org/build/three.js"></script>
<p style="position: fixed;z-index:1;top:0;text-align:center;color: #fff">This is correct behavior</p>
Wrong behavior when parent is rotated:
var SCREEN_WIDTH = window.innerWidth;
var SCREEN_HEIGHT = window.innerHeight;
var container, stats;
var camera, scene, controls;
var renderer;
var quat = new THREE.Quaternion();
var axis = new THREE.Vector3();
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
// CAMERA
camera = new THREE.PerspectiveCamera( 30, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000 );
camera.position.set( 0, 0, 500 );
scene = new THREE.Scene();
scene.add( new THREE.AmbientLight( 0xaaaaaa ) );
var light = new THREE.PointLight( 0xffffff );
light.position.set(100,100,100);
scene.add( light );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
renderer.domElement.style.position = "relative";
container.appendChild( renderer.domElement );
//____________________________//
cube = new THREE.Mesh(
new THREE.CubeGeometry(50,100,50),
new THREE.MeshPhongMaterial()
);
cube.rotation.set(Math.PI/3, 0, 0);
cubeParent = new THREE.Object3D();
cubeParent.rotation.set(1,0,0) //Rotated parent
cubeParent.add(cube)
scene.add(cubeParent)
//____________________________//
var grid = new THREE.Mesh(
new THREE.PlaneGeometry(200, 200, 10, 10),
new THREE.MeshBasicMaterial({wireframe: true})
)
grid.position.y = -100
grid.rotation.x = Math.PI/2
scene.add(grid);
window.addEventListener( 'resize', onWindowResize, false );
}
function rotateWorldYAxis( obj, angle ) {
quat.setFromAxisAngle( new THREE.Vector3(0,1,0), angle );
obj.quaternion.multiplyQuaternions(quat,obj.quaternion);
obj.updateMatrixWorld();
}
function animate() {
requestAnimationFrame( animate );
render();
rotateWorldYAxis(cube, 0.01)
}
function render() {
renderer.render( scene, camera );
}
function onWindowResize( event ) {
SCREEN_WIDTH = window.innerWidth;
SCREEN_HEIGHT = window.innerHeight;
renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
camera.aspect = SCREEN_WIDTH / SCREEN_HEIGHT;
camera.updateProjectionMatrix();
}
<script src="https://threejs.org/build/three.js"></script>
<p style="position: fixed;z-index:1;top:0;text-align:center;color: #fff">Parent rotate cause this wrong behavior, this cube need to rotates on Y world axis</p>
Any help is appreciated! Thank you!

Related

Three.js Object3D division and custom coloring

I want to ask for some help with my project of temperature change on model. I'm using OBJLoader to load my model exported from autoCAD,
and I need to show temperature change on it by color change. I'm stuck on point, how to divide loaded object to smaller regions,
maybe set them some id and than set that region the particular color.
I will be grateful for any help or advice.
By now, I have this:
<body>
<div id="info">
three.js - Temperature model
</div>
<script src="../three.js-lib/build/three.min.js"></script>
<script src="../three.js-lib/examples/js/loaders/OBJLoader.js"></script>
<script src="../three.js-lib/examples/js/Detector.js"></script>
<script src="../three.js-lib/examples/js/controls/OrbitControls.js"></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var camera, scene, renderer;
var container;
init();
function init() {
container = document.getElementById("container");
scene = new THREE.Scene();
scene.add( new THREE.AmbientLight( 0x999999 ) );
camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 1, 500 );
camera.up.set( 0, 0, 10 );
camera.position.set( 0, -150, 95 );
camera.add( new THREE.PointLight( 0xffffff, 0.8 ) );
scene.add( camera );
var grid = new THREE.GridHelper( 200, 10.0 );
grid.setColors( 0xffffff, 0x555555 );
grid.rotateOnAxis( new THREE.Vector3( 1, 0, 0 ), 90 * ( Math.PI/180 ) );
scene.add( grid );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setClearColor( 0x999999 );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
//loader
loadModel();
var controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render );
controls.target.set( 0, 1.2, 2 );
controls.update();
window.addEventListener( 'resize', onWindowResize, false );
}
function loadModel() {
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) {};
var manager = new THREE.LoadingManager();
manager.onProgress = function (item, loaded, total) {
console.log(item, loaded, total);
};
var loader = new THREE.OBJLoader(manager);
loader.load('temperature/suciastka.obj', function (object) {
object.traverse(function (child){
if (child instanceof THREE.Mesh) {
child.material = new THREE.MeshPhongMaterial({color: 0x451E0C, vertexColors: THREE.VertexColors});
}
})
scene.add(object);
render();
}, onProgress, onError);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
render();
}
function render() {
renderer.render( scene, camera );
}
</script>

Loading an animation in a reflection cube using three.js

I made a reflection cube and I am trying to put an animated model inside. But something happen in my function render and I can not see anything.
I am making my first steps using javascript and playing with three.js. If you can help me would be amazing.
//var scene, camera, etc
var container, loader;
var camera, scene, projector, renderer;
var controls;
var mesh, mixer;
var pointLight;
var mouseX = 0;
var mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
var height = 300; // of camera frustum
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
//renderer
renderer = new THREE.WebGLRenderer( { alpha: true } );
renderer.setClearColor(0xffffff, 1);
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
renderer.gammaInput = true;
renderer.gammaOutput = true;
//set up the scene
scene = new THREE.Scene();
var aspect = window.innerWidth / window.innerHeight;
//set up the Orthographic Camera
camera = new THREE.OrthographicCamera( - height * aspect, height * aspect, height, - height, 1, 10000 );
camera.position.z = 1500;
scene.add( camera );
//set up the controls
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.enableZoom = true;
controls.enableDamping = true;
//set up the lights
var ambientLight = new THREE.AmbientLight( 0x111111 );
scene.add( ambientLight );
pointLight = new THREE.PointLight( 0x030303, 0.5 );
pointLight.position.z = 2500;
scene.add( pointLight );
var pointLight2 = new THREE.PointLight( 0x030303, 1 );
camera.add( pointLight2 );
var pointLight3 = new THREE.PointLight( 0xe8e4e4, 0.5 );
pointLight3.position.x = - 1000;
pointLight3.position.z = 1000;
scene.add( pointLight3 );
//create the environment map
var imgAr = [
'sources/instagram2/image1.jpg',
'sources/instagram2/image2.jpg',
'sources/instagram2/image3.jpg',
'sources/instagram2/image4.jpg',
'sources/instagram2/image5.jpg',
'sources/instagram2/image6.jpg',
'sources/instagram2/image7.jpg',
'sources/instagram2/image8.jpg',
'sources/instagram2/image9.jpg',
'sources/instagram2/image10.jpg',
'sources/instagram2/image11.jpg',
'sources/instagram2/image12.jpg',
'sources/instagram2/image13.jpg',
'sources/instagram2/image14.jpg',
'sources/instagram2/image15.jpg',
'sources/instagram2/image16.jpg'
];
var urls = imgAr.sort(function(){return .6 - Math.random()}).slice(0,6);
var reflectionCube = THREE.ImageUtils.loadTextureCube( urls, THREE.CubeReflectionMapping );
//Load the animation
var loader = new THREE.JSONLoader();
loader.load( "sources/models/animated/horse.js", function ( geometry ) {
var material = new THREE.MeshPhongMaterial( {
morphTargets: true,
overdraw: 0.5,
envMap: reflectionCube,
combine: THREE.AddOperation,
reflectivity: 1,
shininess: 0,
side: THREE.DoubleSide
} );
mesh = new THREE.Mesh( geometry, material );
mesh.scale.set( 1.5, 1.5, 1.5 );
mesh.position.set(0,-150,0);
scene.add( mesh );
mixer = new THREE.AnimationMixer( mesh );
var clip = THREE.AnimationClip.CreateFromMorphTargetSequence( 'gallop', geometry.morphTargets, 30 );
mixer.addAction( new THREE.AnimationAction( clip ).warpToDuration( 1 ) );
} );
// window resize
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
var aspect = window.innerWidth / window.innerHeight;
camera.left = - height * aspect;
camera.right = height * aspect;
camera.top = height;
camera.bottom = - height;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
//set up the background
var backgroundMesh = new THREE.Mesh(
new THREE.MeshBasicMaterial({
map: texture
}));
backgroundMesh .material.depthTest = false;
backgroundMesh .material.depthWrite = false;
var backgroundScene = new THREE.Scene();
var backgroundCamera = new THREE.Camera();
backgroundScene .add(backgroundCamera );
backgroundScene .add(backgroundMesh );
function animate() {
requestAnimationFrame( animate );
controls.update();
render();
}
var radius = 600;
var theta = 0;
var prevTime = Date.now();
function render() {
theta += 0.1;
camera.position.x = radius * Math.sin( THREE.Math.degToRad( theta ) );
camera.position.z = radius * Math.cos( THREE.Math.degToRad( theta ) );
camera.lookAt( camera.target );
if ( mixer ) {
var time = Date.now();
mixer.update( ( time - prevTime ) * 0.001 );
prevTime = time;
}
renderer.render( scene, camera );
renderer.render(backgroundScene , backgroundCamera );
mixer.update();
}
</script>nter code here

Problems making a tween on Three.js

I am making my first steps learning JavaScript and playing with Three.js.
I made a reflection cube with a tween animation and i would like to make this tween runs everytime that I reload my site without clicking.
I have two days trying to make it and cant. Can you tell me which is the problem with my code please? I tryied to verify it in the JavaScript console in Chrome and it didnt say anything. If you can help would be amazing because i am doing my best and it's something really hard.
Here is my code with some comments i made:
<script>
// set up the first variables scene, the camera, etc, etc
var container;
var camera, scene, renderer;
var raycaster;
var mouse;
init();
animate();
function init() {
// My scene is a div inside the html
container = document.createElement( 'div' );
document.body.appendChild( container );
//Set up the camera and make an scene
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 10000 );
camera.target = new THREE.Vector3( 0, 50, 0 );
camera.position.y = 300;
camera.position.z = 500;
scene = new THREE.Scene();
//environment map
var imgAr = [
'sources/cube_sides/0.jpg',
'sources/cube_sides/02.jpg',
'sources/cube_sides/03.jpg',
'sources/cube_sides/04.jpg',
'sources/cube_sides/05.jpg',
'sources/cube_sides/06.jpg',
'sources/cube_sides/07.jpg',
'sources/cube_sides/08.jpg',
'sources/cube_sides/09.jpg',
'sources/cube_sides/010.jpg',
'sources/cube_sides/011.jpg',
'sources/cube_sides/012.jpg',
'sources/cube_sides/013.jpg',
'sources/cube_sides/014.jpg',
'sources/cube_sides/015.jpg',
'sources/cube_sides/016.jpg',
'sources/cube_sides/017.jpg',
'sources/cube_sides/018.jpg'
];
var urls = imgAr.sort(function(){return .6 - Math.random()}).slice(0,6);
var reflectionCube = THREE.ImageUtils.loadTextureCube( urls, THREE.CubeReflectionMapping );
//load the model
var loader = new THREE.BinaryLoader();
loader.load( "sources/obj/mmlogo/mm_logo.js", function ( geometry ) {
var material = new THREE.MeshPhongMaterial( {
color: 0x515151,
morphTargets: true,
overdraw: 0.5,
envMap: reflectionCube,
combine: THREE.AddOperation,
reflectivity: 1,
shininess: 0,
side: THREE.DoubleSide,
} );
//assign a mesh to the geometry
mesh = new THREE.Mesh( geometry, material );
mesh.scale.set( 120, 120, 120 );
mesh.position.y = 50;
mesh.position.x = 0;
mesh.position.z = 700;
mesh.rotation.y = 10;
mesh.rotation.x = 10;
scene.add( mesh );
//mixer = new THREE.AnimationMixer( mesh );
//var clip = THREE.AnimationClip.CreateFromMorphTargetSequence( 'gallop', geometry.morphTargets, 30 );
//mixer.addAction( new THREE.AnimationAction( clip ).warpToDuration( 1 ) );
} );
//set up the Raycaster
raycaster = new THREE.Raycaster();
mouse = new THREE.Vector2();
//set up the renderer
renderer = new THREE.WebGLRenderer();
renderer.setClearColor( 0xffffff );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild(renderer.domElement);
document.addEventListener( 'load', onDocumentLoad, false );
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onDocumentLoad( event ) {
event.preventDefault();
var intersects = raycaster.intersectObjects( scene.children );
new TWEEN.Tween( intersects[ 0 ].object.position ).to( {
x: 0,
y: 50,
z: 70 }, 20000 )
.easing( TWEEN.Easing.Sinusoidal.In).start();
new TWEEN.Tween( intersects[ 0 ].object.rotation ).to( {
x: 0,
y: 0,
z: 0 }, 20000 )
.easing( TWEEN.Easing.Sinusoidal.In).start();
}
function animate() {
requestAnimationFrame( animate );
render();
}
var radius = 600;
var theta = 0;
function render() {
TWEEN.update();
theta += 0;
camera.position.y = radius * Math.sin( THREE.Math.degToRad( theta ) );
camera.position.z = radius * Math.cos( THREE.Math.degToRad( theta ) );
camera.lookAt( camera.target );
renderer.render( scene, camera );
}
</script>

webGL thee.js: pointing a camera at an .obj model

I am trying to work out how to direct the camera directly at an obj model. I have deliberately moved the obj model off center, so that when i achieve this aim, it will become centered in the frame. I've tried using camera.lookAt( object.position ); after camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 ); but unfortunately this just renders a black screen.
<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 );
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
camera.position.z = 300;
camera.position.x = 100;
camera.position.y = 500
// scene
scene = new THREE.Scene();
var ambient = new THREE.AmbientLight( 0x444444 );
scene.add( ambient );
var directionalLight = new THREE.DirectionalLight( 0xffeedd );
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 loader = new THREE.OBJMTLLoader();
loader.load( 'obj/male02/male02.obj', 'obj/male02/male02_dds.mtl', function ( object ) {
object.position.y = - 80;
object.position.x = - 80;
object.position.z = - 80;
scene.add( object );
}, 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 );
}
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 animate() {
requestAnimationFrame( animate );
render();
}
function render() {
camera.lookAt( scene.position );
renderer.render( scene, camera );
}
</script>

Three.js - VRML Loader

I'm trying to use the Three.js with VRML (WRL) models. What I am wondering is that the model is loaded with variations of colors (colored). How can I load the model in solid color as the original file?
My example is: http://dev.logicarts.com.br/semapro/projeto-3d/teste-1.html
The code:
<div id="info">
three.js -
vrml format loader test -
<!--model from VRML 2.0 Tutorial,-->
</div>
<script src="js/three.min.js"></script>
<script src="js/OrbitControls.js"></script>
<script src="js/VRMLLoader.js"></script>
<script src="js/Detector.js"></script>
<script src="js/stats.min.js"></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container, stats;
var camera, controls, scene, renderer;
var cross;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 0.01, 1e10 );
camera.position.z = 6;
controls = new THREE.OrbitControls( camera );
controls.rotateSpeed = 5.0;
controls.zoomSpeed = 5;
controls.noZoom = false;
controls.noPan = false;
scene = new THREE.Scene();
scene.add( camera );
// light
var dirLight = new THREE.DirectionalLight( 0xffffff );
dirLight.position.set( 200, 200, 1000 ).normalize();
camera.add( dirLight );
camera.add( dirLight.target );
var loader = new THREE.VRMLLoader();
loader.addEventListener( 'load', function ( event ) {
scene.add(event.content);
} );
loader.load( "3d/conjunto-carcaca.wrl" );
// renderer
renderer = new THREE.WebGLRenderer( { antialias: false } );
renderer.setSize( window.innerWidth, window.innerHeight );
container = document.createElement( 'div' );
document.body.appendChild( container );
container.appendChild( renderer.domElement );
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
container.appendChild( stats.domElement );
//
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
controls.handleResize();
}
function animate() {
requestAnimationFrame( animate );
controls.update();
renderer.render( scene, camera );
stats.update();
}
</script>
If you add this code under the scene.add(event.content); statement, all the objects in your scene will turn red.
scene.traverse (function (object)
{
if (object instanceof THREE.Mesh) {
object.material.color.setHex( 0xff0000 );
}
});

Categories