I have a problem .
I want move the earth in 360° with the mouse but nothing happens .
However , I would like the world is fixed and does not move when I use the mouse to rotate 360 .
Waiting for a response .
<!DOCTYPE html>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
color: #808080;
font-family:Monospace;
font-size:13px;
text-align:center;
background-color: #000000;
margin: 0px;
overflow: hidden;
}
#info {
position: absolute;
top: 0px; width: 100%;
padding: 5px;
}
a {
color: #0080ff;
}
</style>
</head>
<body>
<div id="container"></div>
<div id="info">three.js - earth demo</div>
<script src="../build/three.min.js"></script>
<script src="js/libs/stats.min.js"></script>
<script>
var container, stats;
var camera, scene, renderer;
var group;
var mouseX = 0, mouseY = 0;
init();
animate();
function init() {
container = document.getElementById( 'container' );
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.z = 900;
scene = new THREE.Scene();
group = new THREE.Object3D();
scene.add( group );
// earth
var earthTexture = new THREE.Texture();
var loader = new THREE.ImageLoader();
loader.addEventListener( 'load', function ( event ) {
earthTexture.image = event.content;
earthTexture.needsUpdate = true;
} );
loader.load( 'textures/1.jpg');
var geometry = new THREE.SphereGeometry( 250, 55, 55 );
var material = new THREE.MeshBasicMaterial( { map: earthTexture, overdraw: true } );
var mesh = new THREE.Mesh( geometry, material );
group.add( mesh );
// shadow
var canvas = document.createElement( 'canvas' );
canvas.width = 128;
canvas.height = 128;
var context = canvas.getContext( '2d' );
var gradient = context.createRadialGradient( canvas.width / 2, canvas.height / 2, 0, canvas.width / 2, canvas.height / 2, canvas.width / 2 );
gradient.addColorStop( 0.1, 'rgba(210,210,210,1)' );
gradient.addColorStop( 1, 'rgba(255,255,255,1)' );
context.fillStyle = gradient;
context.fillRect( 0, 0, canvas.width, canvas.height );
var texture = new THREE.Texture( canvas );
texture.needsUpdate = true;
var geometry = new THREE.PlaneGeometry( 300, 300, 3, 3 );
var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: true } );
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( '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 );
mouseY = ( event.clientY - windowHalfY );
}
//
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}
function render() {
camera.position.x += ( mouseX - camera.position.x ) * 0.50;
camera.position.y += ( - mouseY - camera.position.y ) * 0.50;
camera.lookAt( scene.position );
group.rotation.y -= 0.01;
renderer.render( scene, camera );
}
// add subtle ambient lighting
var ambientLight = new THREE.AmbientLight(0x555555);
scene.add(ambientLight);
</script>
</body>
the problem that you are having is that you are only moving the camera in the X and Y direction, when the camera is a 3D entity.
In order to do the rotation, you need to move convert the mouse coordinate from 3D spherical coordinates (like latitude, longitude, altitude, assuming a constant altitude, you can assign X to longitude and Y to latitude).
Then assign the 3D cartesian coordinates to your camera:
The formula is (replacing what you have in your render function):
(assume altitude is 960, which works with your model)
camera.position.x = 960 * Math.sin(mouseX) * Math.cos(mouseY);
camera.position.y = 960 * Math.sin(mouseX) * Math.sin(mouseY);
camera.position.z = 960 * Math.cos(mouseX);
The next caveat is that sin and cos take radians (range from -pi to pi (-3.14159 to 3.14159)...so you will need to adjust your onDocumentMouseMove event to something like
mouseX = -Math.PI + (event.clientX)/(windowHalfX*2)*Math.PI*2;
mouseY = -Math.PI + (event.clientY)/(windowHalfY*2)*Math.PI*2;
This will cause the mouse to act in lat/long coordinate (which can still be a little strange if you are looking at the top of the world. You could restrict mouseY=0, then the X rotation would always be on the equator.
The math is a little more complicated if you want moving the mouse to be on a moving frame vs. the earth centric frame I've shown. But this should at least be a start.
Related
I'm trying to load a 3D globe into my HTML site using a ThreeJS script (found below) But it's stitched together with code from other sources, meaning the camera is mapped to MouseX and MouseY positions. I want the object to sit in the center of the page with a simple slow spin, but every time I try and achieve this the object vanishes.
The Javascript:
<script>
var container;
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( 5, window.innerWidth / window.innerHeight, 1, 5000 );
camera.position.z = 250;
scene = new THREE.Scene();
var ambientLight = new THREE.AmbientLight( 0xcccccc, 0.8 );
scene.add( ambientLight );
var pointLight = new THREE.PointLight( 0xFFF1CF, 0.6 , 0 );
camera.add( pointLight );
scene.add( camera );
var manager = new THREE.LoadingManager();
manager.onProgress = function ( item, loaded, total ) {
console.log( item, loaded, total );
};
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 mtlLoader = new THREE.MTLLoader();
mtlLoader.load('planet.mtl', function(materials) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.load('planet.obj', function(object) {
object.position.y = 0;
scene.add(object);
}, onProgress, onError);
});
//
renderer = new THREE.WebGLRenderer( {alpha: true});
renderer.setClearColor( 0x000000, 0 );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
document.addEventListener( 'mouseclick', onmousedown, 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 );
mouseY = ( event.clientY );
}
//
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 );
}
</script>
You need to change your code a little bit,
In the 'init' function, change the object loading logic as follows
var mtlLoader = new THREE.MTLLoader();
var objLoader = new THREE.OBJLoader();
mtlLoader.load( 'planet.mtl', function(materials) {
materials.preload();
objLoader.setMaterials(materials);
objLoader.load( 'planet.obj', function( object ){
object.position.set( 0, 0, 0 ); // set the position as (0,0,0)
globe = object; // globe is the object to be added to the scene
scene.add(globe);
animate(); //call the animate function only after the object is loaded
}, onProgress, onError);
} );
And change the render method,
function render() {
globe.rotation.y += 0.01; // this will rotate the object
camera.lookAt( scene.position );
renderer.render( scene, camera );
}
i am using google Chrome (59.0.3071.125) in my mobile
i was Enabled : WebVR , Gamepad in my chrome using chrome://flags/ to support WEBVR when i tried first time it worked
BUT after 2 days now its givig this exception:
Uncaught (in promise) DOMException: Presentation request was denied.
I have no clue why.
i tried to search around but i found nothing
below is the code of https://threejs.org/examples/?q=vr#webvr_cubes i have tried
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webvr - cubes</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<!-- Origin Trial Token, feature = WebVR, origin = https://threejs.org, expires = 2017-06-13 -->
<meta http-equiv="origin-trial" data-feature="WebVR" data-expires="2017-06-13" content="ApAQvHfiHMQB7SmRhfvCUX61adJaTA6pAu0Ry439jjeipa5lGm1RcTQynFoHGGcaSJkWfMOv7qK6pwSUb95ClQgAAABKeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJWUiIsImV4cGlyeSI6MTQ5NzMxMjAwMH0=">
<style>
body {
font-family: Monospace;
background-color: #101010;
color: #fff;
margin: 0px;
overflow: hidden;
}
a {
color: #f00;
}
</style>
</head>
<body>
<script src="../build/three.js"></script>
<script src="js/controls/VRControls.js"></script>
<script src="js/effects/VREffect.js"></script>
<script src="js/vr/WebVR.js"></script>
<script>
if ( WEBVR.isAvailable() === false ) {
document.body.appendChild( WEBVR.getMessage() );
}
//
var clock = new THREE.Clock();
var container;
var camera, scene, raycaster, renderer;
var effect, controls;
var room;
var isMouseDown = false;
var INTERSECTED;
var crosshair;
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 = 'three.js webgl - interactive cubes';
container.appendChild( info );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 10 );
scene.add( camera );
crosshair = new THREE.Mesh(
new THREE.RingGeometry( 0.02, 0.04, 32 ),
new THREE.MeshBasicMaterial( {
color: 0xffffff,
opacity: 0.5,
transparent: true
} )
);
crosshair.position.z = - 2;
camera.add( crosshair );
room = new THREE.Mesh(
new THREE.BoxGeometry( 6, 6, 6, 8, 8, 8 ),
new THREE.MeshBasicMaterial( { color: 0x404040, wireframe: true } )
);
scene.add( room );
scene.add( new THREE.HemisphereLight( 0x606060, 0x404040 ) );
var light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 1, 1, 1 ).normalize();
scene.add( light );
var geometry = new THREE.BoxGeometry( 0.15, 0.15, 0.15 );
for ( var i = 0; i < 200; i ++ ) {
var object = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: Math.random() * 0xffffff } ) );
object.position.x = Math.random() * 4 - 2;
object.position.y = Math.random() * 4 - 2;
object.position.z = Math.random() * 4 - 2;
object.rotation.x = Math.random() * 2 * Math.PI;
object.rotation.y = Math.random() * 2 * Math.PI;
object.rotation.z = Math.random() * 2 * Math.PI;
object.scale.x = Math.random() + 0.5;
object.scale.y = Math.random() + 0.5;
object.scale.z = Math.random() + 0.5;
object.userData.velocity = new THREE.Vector3();
object.userData.velocity.x = Math.random() * 0.01 - 0.005;
object.userData.velocity.y = Math.random() * 0.01 - 0.005;
object.userData.velocity.z = Math.random() * 0.01 - 0.005;
room.add( object );
}
raycaster = new THREE.Raycaster();
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setClearColor( 0x505050 );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.sortObjects = false;
container.appendChild( renderer.domElement );
controls = new THREE.VRControls( camera );
effect = new THREE.VREffect( renderer );
WEBVR.getVRDisplay( function ( display ) {
document.body.appendChild( WEBVR.getButton( display, renderer.domElement ) );
} );
renderer.domElement.addEventListener( 'mousedown', onMouseDown, false );
renderer.domElement.addEventListener( 'mouseup', onMouseUp, false );
renderer.domElement.addEventListener( 'touchstart', onMouseDown, false );
renderer.domElement.addEventListener( 'touchend', onMouseUp, false );
//
window.addEventListener( 'resize', onWindowResize, false );
}
function onMouseDown() {
isMouseDown = true;
}
function onMouseUp() {
isMouseDown = false;
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
effect.setSize( window.innerWidth, window.innerHeight );
}
//
function animate() {
effect.requestAnimationFrame( animate );
render();
}
function render() {
var delta = clock.getDelta() * 60;
if ( isMouseDown === true ) {
var cube = room.children[ 0 ];
room.remove( cube );
cube.position.set( 0, 0, - 0.75 );
cube.position.applyQuaternion( camera.quaternion );
cube.userData.velocity.x = ( Math.random() - 0.5 ) * 0.02 * delta;
cube.userData.velocity.y = ( Math.random() - 0.5 ) * 0.02 * delta;
cube.userData.velocity.z = ( Math.random() * 0.01 - 0.05 ) * delta;
cube.userData.velocity.applyQuaternion( camera.quaternion );
room.add( cube );
}
// find intersections
raycaster.setFromCamera( { x: 0, y: 0 }, camera );
var intersects = raycaster.intersectObjects( room.children );
if ( intersects.length > 0 ) {
if ( INTERSECTED != intersects[ 0 ].object ) {
if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );
INTERSECTED = intersects[ 0 ].object;
INTERSECTED.currentHex = INTERSECTED.material.emissive.getHex();
INTERSECTED.material.emissive.setHex( 0xff0000 );
}
} else {
if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );
INTERSECTED = undefined;
}
// Keep cubes inside room
for ( var i = 0; i < room.children.length; i ++ ) {
var cube = room.children[ i ];
cube.userData.velocity.multiplyScalar( 1 - ( 0.001 * delta ) );
cube.position.add( cube.userData.velocity );
if ( cube.position.x < - 3 || cube.position.x > 3 ) {
cube.position.x = THREE.Math.clamp( cube.position.x, - 3, 3 );
cube.userData.velocity.x = - cube.userData.velocity.x;
}
if ( cube.position.y < - 3 || cube.position.y > 3 ) {
cube.position.y = THREE.Math.clamp( cube.position.y, - 3, 3 );
cube.userData.velocity.y = - cube.userData.velocity.y;
}
if ( cube.position.z < - 3 || cube.position.z > 3 ) {
cube.position.z = THREE.Math.clamp( cube.position.z, - 3, 3 );
cube.userData.velocity.z = - cube.userData.velocity.z;
}
cube.rotation.x += cube.userData.velocity.x * 2 * delta;
cube.rotation.y += cube.userData.velocity.y * 2 * delta;
cube.rotation.z += cube.userData.velocity.z * 2 * delta;
}
controls.update();
effect.render( scene, camera );
}
</script>
</body>
</html>
I just hit a very similar issue. It seems that VRButton does not work well with requestAnimationFrame. Instead you need to use renderer.setAnimiationLoop.
Your code:
function animate() {
effect.requestAnimationFrame( animate );
render();
}
Change it to this:
function animate() {
renderer.setAnimationLoop(() => { render(); });
}
I wish to move a cube based on the movement of another cube to which TransformControls is attached by means of Matrix4() method only.
The attempts so far have failed to shift the follower cube.
I'm not sure why the follower doesn't seem to take the world co-ordinates of the directing cube.
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - transform controls</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 {
margin: 0px;
background-color: #000000;
color: #fff;
font-family:Monospace;
text-align: center;
font-size: 15px;
line-height: 30px;
overflow: hidden;
}
#info {
position: absolute;
top: 0px; width: 100%;
padding: 15px;
z-index:100;
}
</style>
</head>
<body>
<div id="info">
"W" translate | "E" rotate | "R" scale | "+" increase size | "-" decrease size<br />
Press "Q" to toggle world/local space, keep "Ctrl" down to snap to grid
</div>
<script src="build/three.js"></script>
<script src="js/controls/TransformControls.js"></script>
<script src="js/controls/OrbitControls.js"></script>
<script>
var camera, scene, renderer, control, mesh, mesh1;
init();
animate();
//render();
//update();
function init() {
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.sortObjects = false;
document.body.appendChild( renderer.domElement );
//
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 3000 );
camera.position.set( 1000, 500, 1000 );
camera.lookAt( new THREE.Vector3( 0, 200, 0 ) );
scene = new THREE.Scene();
scene.add( new THREE.GridHelper( 1000, 10 ) );
var light = new THREE.DirectionalLight( 0xffffff, 2 );
light.position.set( 1, 1, 1 );
scene.add( light );
//var texture = new THREE.TextureLoader().load( 'textures/crate.gif', render );
//texture.mapping = THREE.UVMapping;
//texture.anisotropy = renderer.getMaxAnisotropy();
var geometry = new THREE.BoxGeometry( 200, 200, 200 );
var material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );
control = new THREE.TransformControls( camera, renderer.domElement );
control.addEventListener( 'change', render );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
control.attach( mesh );
scene.add( control );
var followerCube = new THREE.BoxGeometry( 200, 200, 200 );
var material1 = new THREE.MeshBasicMaterial( { color: 0xff9909 } );
mesh1 = new THREE.Mesh( followerCube, mesh1 );
scene.updateMatrixWorld();
mesh1.matrixAutoUpdate = false;
var relativeMeshOffset = new THREE.Vector3( 100, 100, 200 );
var offsetPosition = relativeMeshOffset.applyMatrix4( mesh.matrixWorld );
mesh1.position.x = offsetPosition.x;
mesh1.position.y = offsetPosition.y;
mesh1.position.z = offsetPosition.z;
scene.add( mesh1 );
console.log(mesh1.position);
var orbitControl = new THREE.OrbitControls( camera, renderer.domElement );
orbitControl.addEventListener( 'change', render );
window.addEventListener( 'resize', onWindowResize, false );
window.addEventListener( 'keydown', function ( event ) {
switch ( event.keyCode ) {
case 81: // Q
control.setSpace( control.space === "local" ? "world" : "local" );
break;
case 17: // Ctrl
control.setTranslationSnap( 100 );
control.setRotationSnap( THREE.Math.degToRad( 15 ) );
break;
case 87: // W
control.setMode( "translate" );
break;
case 69: // E
control.setMode( "rotate" );
break;
case 82: // R
control.setMode( "scale" );
break;
case 187:
case 107: // +, =, num+
control.setSize( control.size + 0.1 );
break;
case 189:
case 109: // -, _, num-
control.setSize( Math.max( control.size - 0.1, 0.1 ) );
break;
}
});
window.addEventListener( 'keyup', function ( event ) {
switch ( event.keyCode ) {
case 17: // Ctrl
control.setTranslationSnap( null );
control.setRotationSnap( null );
break;
}
});
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
render();
}
function animate() {
requestAnimationFrame( animate );
render();
update();
}
function update() {
var relativeMeshOffset = new THREE.Vector3( 100, 100, 200 );
var offsetPosition = relativeMeshOffset.applyMatrix4( mesh.matrixWorld );
mesh1.position.x = offsetPosition.x;
mesh1.position.y = offsetPosition.y;
mesh1.position.z = offsetPosition.z;
}
function render() {
control.update();
renderer.render( scene, camera );
}
</script>
</body>
</html>
Cause you set mesh1.matrixAutoUpdate = false; in line 75. If you do that, the mesh1 wouldn't change its position.
I used the following code (which is not mine, it's taken from this article http://blog.andrewray.me/how-to-export-a-rigged-animated-model-from-3ds-max-three-js/) in my project and tried to load my model. But the ptoblem is that the author uses animated skinned mesh, I have a simple model. I copied his complete demo page code to my project, changed the path to the js model and it doesn't show up. What should I adjust to make it work?
var container;
var camera, scene, renderer, objects;
var particleLight, pointLight;
var mesh, wiggly;
var loader = new THREE.JSONLoader();
loader.load( './humpback-whale-animated-threejs-max-exporter.js', function ( geometry, materials ) {
var originalMaterial = materials[ 0 ];
originalMaterial.skinning = true;
mesh = new THREE.SkinnedMesh( geometry, originalMaterial );
mesh.scale.set( 0.1, 0.1, 0.1 );
var animation = new THREE.Animation(
mesh,
geometry.animation
);
animation.play();
init();
animate();
});
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
scene = new THREE.Scene();
scene.add( mesh );
// Lights
scene.add( new THREE.AmbientLight( 0xcccccc ) );
var directionalLight = new THREE.DirectionalLight(/*Math.random() * 0xffffff*/0xeeeeee );
directionalLight.position.x = Math.random() - 0.5;
directionalLight.position.y = Math.random() - 0.5;
directionalLight.position.z = Math.random() - 0.5;
directionalLight.position.normalize();
scene.add( directionalLight );
pointLight = new THREE.PointLight( 0xffffff, 4 );
scene.add( pointLight );
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
var clock = new THREE.Clock();
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
var delta = clock.getDelta();
var timer = Date.now() * 0.0005;
THREE.AnimationHandler.update( delta );
camera.position.x = Math.cos( 0.5 ) * 20;
camera.position.y = 5;
camera.position.z = Math.sin( 0.5 ) * 20;
camera.lookAt( scene.position );
renderer.render( scene, camera );
}
I know there are different loaders in three.js and I don't know which one to use for a simple static textured mesh.
I am trying to combine webgl and css3d scenes so that the objects in the two scenes properly blend together. I am following the pattern described here:
and have created a simple example by modifying the three.js example css3d_sandbox.html.
In my version I have added a cube to the webGl scene and expect it to properly blend with the existing planes whether the cube is in front of or behind those objects.
I notice two anomalies. The first is that once the cube is added the planes disappear in unexpected positions as you pan around as if the far and near plane values are not being honored correctly or the objects are being incorrectly determined to be behind something else.
The second issue is that the css3d objects do not render at all when running against three.js r67, but they do render when running against r61. I tried replacing the r67 version of CSS3DRenderer.js with r61, but still do not see any css3d objects.
In r67 when the line to add the webGl dom as a child of the css3d dom is commented out, the css3d objects do appear.
I would appreciate any suggestions on how to resolve these issues. Sample code is below and may be run by dropping into any version of the three.js examples folder (e.g. r61 or r67).
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
body {
background-color: #ffffff;
margin: 0;
overflow: hidden;
}
#info {
position: absolute;
top: 0px;
width: 100%;
color: #000000;
padding: 5px;
font-family: Monospace;
font-size: 13px;
text-align: center;
z-index: 1;
}
a {
color: #000000;
}
</style>
</head>
<body>
<div id="info">three.js - css3d sandbox</div>
<script src="../build/three.min.js"></script>
<script src="js/controls/TrackballControls.js"></script>
<!--<script src="js/renderers/CSS3DRenderer-r61.js"></script>-->
<script src="js/renderers/CSS3DRenderer.js"></script>
<script>
var camera, sceneGl, rendererGl;
var sceneCss, rendererCss;
var controls;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 200, 200, 200 );
controls = new THREE.TrackballControls( camera );
sceneGl = new THREE.Scene();
sceneCss = new THREE.Scene();
var material = new THREE.MeshBasicMaterial( { color: 0x000000, opacity : 0.0 } );
material.blending = THREE.NoBlending;
//
var xpos = [50, -10, 30, 70, 110];
var ypos = [60, -40, 0, 40, 80];
var zpos = [-30, -50, 0, 50, 100];
for ( var i = 0; i < 5; i ++ ) {
var element = document.createElement( 'div' );
element.style.width = '100px';
element.style.height = '100px';
element.style.opacity = 1.0;
element.style.background = new THREE.Color( Math.random() * 0xffffff ).getStyle();
var object = new THREE.CSS3DObject( element );
object.position.x = xpos[i];
object.position.y = ypos[i];
object.position.z = zpos[i];
object.rotation.x = Math.PI/(i + 5);
object.rotation.y = Math.PI/(21 - 2 * i);
object.rotation.z = Math.PI/(3 * i + 25);
object.scale.x = i/12 + 0.5;
object.scale.y = 1/ (12 - i) + 0.5;
sceneCss.add( object );
var geometry = new THREE.PlaneGeometry( 100, 100 );
var mesh = new THREE.Mesh( geometry, material );
mesh.position.copy( object.position );
mesh.rotation.copy( object.rotation );
mesh.scale.copy( object.scale );
sceneGl.add( mesh );
}
//
var boxGeom = new THREE.CubeGeometry( 60, 60, 60 );
var cubeMaterial = new THREE.MeshBasicMaterial(
{ color: 0x05009A, shading : THREE.FlatShading, side: THREE.FrontSide } );
var cube = new THREE.Mesh( boxGeom, cubeMaterial );
cube.position.copy( new THREE.Vector3(100, 75, 50) );
cube.rotation.copy( Math.PI/ 6 );
sceneGl.add( cube );
rendererCss = new THREE.CSS3DRenderer();
rendererCss.setSize( window.innerWidth, window.innerHeight );
rendererCss.domElement.style.position = 'absolute';
rendererCss.domElement.style.top = 0;
rendererGl = new THREE.WebGLRenderer();
rendererGl.setClearColor( 0xf0f0f0 );
rendererGl.setSize( window.innerWidth, window.innerHeight );
rendererGl.domElement.style.position = 'absolute';
rendererGl.domElement.style.zIndex = 1;
rendererGl.domElement.style.top = 0;
rendererCss.domElement.appendChild( rendererGl.domElement );
document.body.appendChild( rendererCss.domElement );
}
function animate() {
requestAnimationFrame( animate );
controls.update();
rendererGl.render( sceneGl, camera );
rendererCss.render( sceneCss, camera );
}
</script>
</body>
</html>
Here is a fiddle with the code.
The link in the comment was helpful. As that solution mentions, setting alpha to true solves the issue of getting the css3d objects to render using r67. Making the webGl background transparent solves the problem of the css3d objects disappearing when panning around.
The solution mentioned in the link however adds both the webgl and css3d dom as child elements of the document. This approach did not work in my case. I find it necessary to still have the webgl dom as a child of the css3d dom for the cube to blend correctly with the planes when it is both in front of and behind those objects.
Working code below:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
body {
background-color: #ffffff;
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<script src="../build/three.min.js"></script>
<script src="js/controls/TrackballControls.js"></script>
<script src="js/renderers/CSS3DRenderer.js"></script>
<script>
var camera, sceneGl, rendererGl;
var sceneCss, rendererCss;
var controls;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(200, 200, 200);
controls = new THREE.TrackballControls(camera);
sceneGl = new THREE.Scene();
sceneCss = new THREE.Scene();
var material = new THREE.MeshBasicMaterial({
color: 0x000000,
opacity: 0.0,
side: THREE.DoubleSide
});
var xpos = [50, -10, 30, 70, 110];
var ypos = [60, -40, 0, 40, 80];
var zpos = [-30, -50, 0, 50, 100];
for (var i = 0; i < 5; i++) {
var element = document.createElement('div');
element.style.width = '100px';
element.style.height = '100px';
element.style.opacity = 1.0;
element.style.background = new THREE.Color(Math.random() * 0xff0000).getStyle();
var object = new THREE.CSS3DObject(element);
object.position.x = xpos[i];
object.position.y = ypos[i];
object.position.z = zpos[i];
object.rotation.x = Math.PI / (i + 5);
object.rotation.y = Math.PI / (21 - 2 * i);
object.rotation.z = Math.PI / (3 * i + 25);
object.scale.x = i / 12 + 0.5;
object.scale.y = 1 / (12 - i) + 0.5;
sceneCss.add(object);
var geometry = new THREE.PlaneGeometry(100, 100);
var mesh = new THREE.Mesh(geometry, material);
mesh.position.copy(object.position);
mesh.rotation.copy(object.rotation);
mesh.scale.copy(object.scale);
sceneGl.add(mesh);
}
var boxGeom = new THREE.CubeGeometry(60, 60, 60);
var cubeMaterial = new THREE.MeshBasicMaterial({
color: 0x05009A,
shading: THREE.FlatShading,
side: THREE.DoubleSide
});
var cube = new THREE.Mesh(boxGeom, cubeMaterial);
cube.position.copy(new THREE.Vector3(100, 75, 50));
cube.rotation.copy(Math.PI / 6);
sceneGl.add(cube);
rendererCss = new THREE.CSS3DRenderer();
rendererCss.setSize(window.innerWidth, window.innerHeight);
rendererCss.domElement.style.position = 'absolute';
rendererCss.domElement.style.top = 0;
rendererGl = new THREE.WebGLRenderer({alpha:true});
rendererGl.setClearColor(0x00ff00, 0.0);
rendererGl.setSize(window.innerWidth, window.innerHeight);
rendererGl.domElement.style.position = 'absolute';
rendererGl.domElement.style.zIndex = 1;
rendererGl.domElement.style.top = 0;
rendererCss.domElement.appendChild(rendererGl.domElement);
document.body.appendChild(rendererCss.domElement);
}
function animate() {
requestAnimationFrame(animate);
controls.update();
rendererGl.render(sceneGl, camera);
rendererCss.render(sceneCss, camera);
}
</script>
</body>
</html>