Move moon orbit from sun to planet - three.js

yesterday #prisoner849 help me very well with the plante Orbit: Create a planet orbit
But now i have the problem to modify the script to create the orbit for the moons around the planets. I test to modify the start Point, but allways the Obrits are created at 0,0,0 around the sun not around the planet.
<!doctype html>
<html>
<head>
</head>
<body>
<div id="container"></div>
<!--Load three.js-->
<script src="js/three.js"></script>
<script src="js/controls/OrbitControls.js"></script>
<script>
var camera, controls, scene, renderer, raycaster;
var mouse = new THREE.Vector2();
init();
animate();
function init() {
scene = new THREE.Scene();
raycaster = new THREE.Raycaster();
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x000000);
var container = document.getElementById( 'container' );
container.appendChild( renderer.domElement );
camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 1, 100000000000000000);
camera.position.z = 30;
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render );
controls.enableKeys = true;
var planet = ["-4067664386091","-710580828973","-3956610895959",
"29476716044","5149291420","-46417511315",
"124056083719","21671373654","16235707106",
"-107354576606","-18753785170","436797007078",
"-639929607985","-111789387758","-1118379774141",
"2907924314427","507985682645","-950946134275",
"-2275005926406","-397421085828","3223734974754"]
for ( var i = 0; i < 7; i ++ ) {
var planet_geometry = new THREE.SphereGeometry(10, 32, 32);
var planet_material = new THREE.MeshBasicMaterial( {color: 0x09F425} );
var planet_mesh = new THREE.Mesh( planet_geometry, planet_material );
planet_mesh.position.x = planet[i * 3] / 1000000000;
planet_mesh.position.y = planet[i * 3 + 1] / 1000000000;
planet_mesh.position.z = planet[i * 3 + 2] / 1000000000;
scene.add( planet_mesh );
var startPoint = new THREE.Vector3(0,0,0);
var endPoint = new THREE.Vector3(planet[i * 3] / 1000000000,planet[i * 3 + 1] / 1000000000,planet[i * 3 + 2] / 1000000000);
var planet_orbit_geometry = new THREE.CircleGeometry(startPoint.distanceTo(endPoint), 128);
planet_orbit_geometry.vertices.shift();
planet_orbit_geometry.rotateX(-Math.PI / 2);
var planet_orbit_material = new THREE.LineBasicMaterial( { color: 0xCC0000 } );
var planet_orbit_mesh = new THREE.Line( planet_orbit_geometry, planet_orbit_material );
planet_orbit_mesh.lookAt(endPoint);
scene.add(planet_orbit_mesh);
}
var moon = ["124366664452","21725629043","16083110466","560000","2",
"-107312642157","-18746459635","436850790914","150000","3",
"-107401228066","-18761934719","436860507268","140000","3",
"-107302625280","-18745221120","436489789440","270000","3"]
for ( var i = 0; i < 4; i ++ ) {
var moon_geometry = new THREE.SphereGeometry(moon[i * 5 + 3] / 100000, 32, 32);
var moon_material = new THREE.MeshBasicMaterial( {color: 0xf6cf46} );
var moon_mesh = new THREE.Mesh( moon_geometry, moon_material );
moon_mesh.position.x = moon[i * 5] / 850000000;
moon_mesh.position.y = moon[i * 5 + 1] / 850000000;
moon_mesh.position.z = moon[i * 5 + 2] / 850000000;
scene.add( moon_mesh );
var startPoint = new THREE.Vector3(planet[moon[i * 5 + 4] * 3] / 1000000000,planet[moon[i * 5 + 4] * 3 + 1] / 1000000000,planet[moon[i * 5 + 4] * 3 + 2] / 1000000000);;
var endPoint = new THREE.Vector3(moon[i * 5] / 850000000, moon[i * 5 + 1] / 850000000, moon[i * 5 + 2] / 850000000);
var moon_obrit_geometry = new THREE.CircleGeometry(startPoint.distanceTo(endPoint), 128);
moon_obrit_geometry.vertices.shift();
moon_obrit_geometry.rotateX(-Math.PI / 2);
var moon_orbit_material = new THREE.LineBasicMaterial( { color: 0xCCCC00 } );
var moon_orbit_mesh = new THREE.Line( moon_obrit_geometry, moon_orbit_material );
moon_orbit_mesh.lookAt(endPoint);
scene.add(moon_orbit_mesh);
}
var sun_geometry = new THREE.SphereGeometry(10, 32, 32);
var sun_material = new THREE.MeshBasicMaterial( {color: 0xCDF409} );
var sun_mesh = new THREE.Mesh( sun_geometry, sun_material );
sun_mesh.position.x = 0;
sun_mesh.position.y = 0;
sun_mesh.position.z = 0;
scene.add( sun_mesh );
window.addEventListener( 'mousemove', onMouseMove, false );
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onMouseMove( event ) {
// calculate mouse position in normalized device coordinates
// (-1 to +1) for both components
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
renderer.render(scene, camera);
}
</script>
</body>
</html>
Here are the jsfiddle: https://jsfiddle.net/n9x3wtnx/2/

Simply, you have to put your moon orbits' positions to positions of planets:
var orbGeometry = new THREE.CircleGeometry(startPoint.distanceTo(endPoint), 128);
orbGeometry.vertices.shift();
orbGeometry.rotateX(-Math.PI / 2);
var orbMaterial = new THREE.LineBasicMaterial( { color: 0xCCCC00 } );
var orbit = new THREE.Line( orbGeometry, orbMaterial );
orbit.position.copy(startPoint); // orbit's origin at planet's position
orbit.lookAt(endPoint);
scene.add(orbit);
jsfiddle example

Related

Threejs / Raycast doesn't compute intersection with my cube

Here is my js files. It works. When I click on the cube, it goes inside raycast function, but doesn't enter the for loop and console.log( intersects[ 0 ] ) gives undefined
let camera, scene, renderer;
let mesh, mesh_green;
let raycaster, mouse = { x : 0, y : 0 };
init();
function init() {
camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 40;
scene = new THREE.Scene();
const geometry = new THREE.BoxGeometry( 1, 1, 1 );
const material = new THREE.MeshBasicMaterial( { color: "red" } );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
mesh.position.set( 0, 10, 0 );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
raycaster = new THREE.Raycaster();
renderer.domElement.addEventListener( 'click', raycast, false );
function raycast ( e ) {
mouse.x = ( e.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( e.clientY / window.innerHeight ) * 2 + 1;
console.log( "raycast" , e.clientX, mouse.x, window.innerWidth);
raycaster.setFromCamera( mouse, camera );
const intersects = raycaster.intersectObjects( scene.children );
for ( let i = 0; i < intersects.length; i++ ) {
console.log( intersects[ i ] );
}
}
It seems your code works by using a latest version of three.js. I've just refactored/simplified it a bit.
let camera, scene, renderer;
let mesh;
let raycaster, pointer = new THREE.Vector2();
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 40;
scene = new THREE.Scene();
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({
color: "red"
});
mesh = new THREE.Mesh(geometry, material);
mesh.position.set(0, 10, 0);
scene.add(mesh);
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
raycaster = new THREE.Raycaster();
renderer.domElement.addEventListener('pointerdown', raycast);
}
function raycast(e) {
pointer.x = (e.clientX / window.innerWidth) * 2 - 1;
pointer.y = -(e.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(pointer, camera);
const intersects = raycaster.intersectObject(scene);
for (let i = 0; i < intersects.length; i++) {
console.log(intersects[i]);
}
}
function animate() {
requestAnimationFrame(animate);
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.02;
renderer.render(scene, camera);
}
body {
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.140.2/build/three.min.js"></script>

ThreeJS raycasting problem with an Orthographic camera in isometric-like view

I'm pulling my hair off this one. I have to work with a specific camera angle for a 3D projet with the constraint of using an Orthographic Camera. I need to be able to precisely click on the floor for gameplay purposes. The ThreeJS Raycast doesn't seem to work properly (or maybe I set something the wrong way?). In a top-down view like angle, it works better.
Here is a fiddle that explains the kind of situation I'm in: https://jsfiddle.net/p6td5oak/42/
const sceneWidth = window.innerWidth;
const sceneHeight = window.innerHeight;
const scene = new THREE.Scene();
const camera = new THREE.OrthographicCamera( -sceneWidth / 2, sceneWidth / 2, sceneHeight / 2, -sceneHeight / 2, -1000, 1000 );
camera.rotation.set(
-Math.PI / 12,
Math.PI / 12,
Math.PI / 24
);
camera.position.set(0, 1, 0);
camera.zoom = 2;
camera.updateProjectionMatrix();
const renderer = new THREE.WebGLRenderer();
renderer.setSize( sceneWidth, sceneHeight );
document.body.appendChild( renderer.domElement );
const whiteMaterial = new THREE.MeshBasicMaterial({});
const redMaterial = new THREE.MeshBasicMaterial({
color: 0xFF0000
});
const size = 100;
const geometry = new THREE.PlaneGeometry(size, size, 10, 10);
for (var x = 0; x < 2; x++)
{
for (var z = 0; z < 2; z++)
{
let mesh = new THREE.Mesh(geometry, ((x + z) % 2 ? whiteMaterial : redMaterial));
mesh.rotation.set(
-Math.PI / 2,
0,
0
);
mesh.position.set(
x*size,
0,
z*size
)
scene.add(mesh);
}
}
var raycaster = new THREE.Raycaster();
window.addEventListener("pointerup", function(e)
{
var screenPos = new THREE.Vector2();
screenPos.x = (e.clientX / window.innerWidth) * 2 - 1;
screenPos.y = - (e.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(screenPos, camera);
var rays = raycaster.intersectObjects(scene.children, true);
for (var i = 0; i < rays.length; i++)
{
scene.remove(rays[i].object);
}
}
.bind(this));
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
animate();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
In the example, I try to remove the planes as soon as they are clicked. As you can see, the top two planes can be removed if you click around their top-left corner. The other twos cannot even be triggered.
If someone have an idea what's going on, you'll be my hero.
Thanks!
PS: I have basic knowledge of ThreeJS but I'm far from being expert
Raycaster only detects objects in front of the camera, and your camera is located near the origin. Move the camera back.
Also, the near value of your orthographic camera is invalid. From the documentation:
The valid range is between 0 and the current value of the far plane.
Negative values are not supported.
const sceneWidth = window.innerWidth;
const sceneHeight = window.innerHeight;
const scene = new THREE.Scene();
const camera = new THREE.OrthographicCamera(-sceneWidth / 2, sceneWidth / 2, sceneHeight / 2, -sceneHeight / 2, 0.1, 1000);
camera.rotation.set(
-Math.PI / 12,
Math.PI / 12,
Math.PI / 24
);
camera.position.set(100, 100, 500);
camera.zoom = 2;
camera.updateProjectionMatrix();
const renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(sceneWidth, sceneHeight);
document.body.appendChild(renderer.domElement);
const whiteMaterial = new THREE.MeshBasicMaterial();
const redMaterial = new THREE.MeshBasicMaterial({
color: 0xFF0000
});
const size = 100;
const geometry = new THREE.PlaneGeometry(size, size, 10, 10);
for (let x = 0; x < 2; x++) {
for (let z = 0; z < 2; z++) {
let mesh = new THREE.Mesh(geometry, ((x + z) % 2 ? whiteMaterial : redMaterial));
mesh.rotation.set(
-Math.PI / 2,
0,
0
);
mesh.position.set(
x * size,
0,
z * size
)
scene.add(mesh);
}
}
const raycaster = new THREE.Raycaster();
const screenPos = new THREE.Vector2();
renderer.domElement.addEventListener("pointerup", function(e) {
screenPos.x = (e.clientX / window.innerWidth) * 2 - 1;
screenPos.y = -(e.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(screenPos, camera);
const intersections = raycaster.intersectObject(scene, true);
for (let i = 0; i < intersections.length; i++) {
scene.remove(intersections[i].object);
}
});
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
body {
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.129/build/three.js"></script>

Create a planet orbit

i want create a red ring to visualize the Orbit of the green Sphere around the yellow Sphere. With lookat() i have orientate the rings to the green Spheres but i have no idea how i can move the rings in the right angel.
My script:
<!doctype html>
<html>
<head>
</head>
<body>
<div id="container"></div>
<!--Load three.js-->
<script src="js/three.js"></script>
<script src="js/controls/OrbitControls.js"></script>
<script>
var camera, controls, scene, renderer, raycaster;
var mouse = new THREE.Vector2();
init();
animate();
function init() {
scene = new THREE.Scene();
raycaster = new THREE.Raycaster();
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x000000);
var container = document.getElementById( 'container' );
container.appendChild( renderer.domElement );
camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 1, 100000000000000000);
camera.position.z = 30;
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render );
controls.enableKeys = false;
var planet = ["-4067664386091","-710580828973","-3956610895959","2060000",
"29476716044","5149291420","-46417511315","2660000",
"124056083719","21671373654","16235707106","4810000",
"-107354576606","-18753785170","436797007078","18890000",
"-639929607985","-111789387758","-1118379774141","57970000",
"2907924314427","507985682645","-950946134275","2830000",
"-2275005926406","-397421085828","3223734974754","7480000",
"-4067664386091","-710580828973","-3956610895959","5110000"]
for ( var i = 0; i < 7; i ++ ) {
var geometry = new THREE.SphereGeometry(5, 32, 32);
var material = new THREE.MeshBasicMaterial( {color: 0x09F425} );
var mesh = new THREE.Mesh( geometry, material );
mesh.position.x = planet[i * 4] / 1000000000;
mesh.position.y = planet[i * 4 + 1] / 1000000000;
mesh.position.z = planet[i * 4 + 2] / 1000000000;
scene.add( mesh );
var startPoint = new THREE.Vector3(0,0,0);
var endPoint = new THREE.Vector3(planet[i * 4] / 1000000000,planet[i * 4 + 1] / 1000000000,planet[i * 4 + 2] / 1000000000);
var direction = new THREE.Vector3().subVectors(endPoint, startPoint).normalize();
var arrow = new THREE.ArrowHelper(direction, startPoint, startPoint.distanceTo(endPoint), 0xCC0000 );
scene.add(arrow);
<!-- I want this red ring in to show the Orbit of the green Spheres -->
var geometry = new THREE.RingGeometry(startPoint.distanceTo(endPoint) - 1, startPoint.distanceTo(endPoint), 32);
var material = new THREE.MeshBasicMaterial( { color: 0xCC0000, side: THREE.DoubleSide } );
var mesh = new THREE.Mesh( geometry, material );
var testPoint = new THREE.Vector3(planet[i * 4] / 1000000000,(planet[i * 4 + 1] / 1000000000)*0.5,planet[i * 4 + 2] / 1000000000);
var pos = new THREE.Vector3();
pos.addVectors(testPoint, mesh.position);
mesh.lookAt(pos);
scene.add(mesh);
<!--------->
}
var geometry = new THREE.SphereGeometry(10, 32, 32);
var material = new THREE.MeshBasicMaterial( {color: 0xCDF409} );
var mesh = new THREE.Mesh( geometry, material );
mesh.position.x = 0;
mesh.position.y = 0;
mesh.position.z = 0;
scene.add( mesh );
window.addEventListener( 'mousemove', onMouseMove, false );
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onMouseMove( event ) {
// calculate mouse position in normalized device coordinates
// (-1 to +1) for both components
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
// update the picking ray with the camera and mouse position
raycaster.setFromCamera( mouse, camera );
// calculate objects intersecting the picking ray
var intersects = raycaster.intersectObjects( scene.children );
for ( var i = 0; i < intersects.length; i++ ) {
//intersects[ i ].object.material.color.set( 0xff0000 );
}
renderer.render(scene, camera);
}
</script>
</body>
</html>
If I got you right.
For orbits, there can be a rough solution:
var geometry = new THREE.CircleGeometry(startPoint.distanceTo(endPoint), 128);
geometry.vertices.shift();
geometry.rotateX(-Math.PI / 2);
var material = new THREE.LineBasicMaterial( { color: 0xCC0000 } );
var mesh = new THREE.Line( geometry, material );
and then to align your orbits to their planets:
mesh.lookAt(endPoint); // as you calculated endPoint before, then no need to calculate the same for testPoint
jsfidde example. Clarify, if I missed something from your question.

Why find intersections does not work with THREE.UTF8Loader?

I clone https://github.com/mrdoob/three.js.git, and I did 2 changes for sample webgl_loader_utf8.html
Add CubeGeometry
Support find intersections
When I clicked Cubes can find intersections, but clicked utf8 models(for instance, ben or hand models) can't find intersections. Any ideas about this? Many thanks!
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - io - UTF8 loader</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: #000;
color: #fff;
margin: 0px;
overflow: hidden;
}
#info {
color: #fff;
position: absolute;
top: 10px;
width: 100%;
text-align: center;
z-index: 100;
display:block;
}
#info a, .button { color: #f00; font-weight: bold; text-decoration: underline; cursor: pointer }
</style>
</head>
<body>
<div id="info">
three.js -
UTF8 format loader test -
models from The Utah 3D Animation Repository
<div id="show"></div>
</div>
<script src="../build/three.min.js"></script>
<script src="js/loaders/UTF8Loader.js"></script>
<script src="js/loaders/MTLLoader.js"></script>
<script src="js/Detector.js"></script>
<script src="js/libs/stats.min.js"></script>
<script src="js/libs/tween.min.js"></script>
<script>
var SCREEN_WIDTH = window.innerWidth;
var SCREEN_HEIGHT = window.innerHeight;
var FLOOR = -150;
var container, stats;
var camera, scene, renderer;
var projector, raycaster;
var mouse = new THREE.Vector2();
var mesh, zmesh, geometry;
var mouseX = 0, mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
document.addEventListener('mousemove', onDocumentMouseMove, false);
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
var show = document.getElementById("show");
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 20, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 2000 );
camera.position.z = 800;
scene = new THREE.Scene();
scene.fog = new THREE.Fog( 0x000000, 800, 2000 );
var path = "textures/cube/SwedishRoyalCastle/";
var format = '.jpg';
var urls = [
path + 'px' + format, path + 'nx' + format,
path + 'py' + format, path + 'ny' + format,
path + 'pz' + format, path + 'nz' + format
];
reflectionCube = THREE.ImageUtils.loadTextureCube( urls );
// LIGHTS
var ambient = new THREE.AmbientLight( 0x222222 );
scene.add( ambient );
var directionalLight = new THREE.DirectionalLight( 0xffffff, 1.1 );
directionalLight.position.set( 0, 20, 300 );
scene.add( directionalLight );
directionalLight.castShadow = true;
//directionalLight.shadowCameraVisible = true;
directionalLight.shadowMapWidth = 2048;
directionalLight.shadowMaHeight = 2048;
var d = 150;
directionalLight.shadowCameraLeft = -d * 1.2;
directionalLight.shadowCameraRight = d * 1.2;
directionalLight.shadowCameraTop = d;
directionalLight.shadowCameraBottom = -d;
directionalLight.shadowCameraNear = 200;
directionalLight.shadowCameraFar = 500;
// RENDERER
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
renderer.setClearColor( scene.fog.color, 1 );
renderer.domElement.style.position = "relative";
container.appendChild( renderer.domElement );
//
/**
renderer.gammaInput = true;
renderer.gammaOutput = true;
renderer.physicallyBasedShading = true;
renderer.shadowMapEnabled = true;
renderer.shadowMapType = THREE.PCFShadowMap;
**/
// STATS
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
stats.domElement.style.zIndex = 100;
container.appendChild( stats.domElement );
var start = Date.now();
var loader = new THREE.UTF8Loader();
loader.load( "models/utf8/hand.js", function ( object ) {
var end = Date.now();
console.log( "hand", end - start, "ms" );
var s = 350;
object.scale.set( s, s, s );
object.position.x = 125;
object.position.y = -125;
//scene.add( object );
object.traverse( function( node ) {
node.castShadow = true;
node.receiveShadow = true;
if ( node.material && node.material.name === "skin" ) {
node.material.wrapAround = true;
node.material.wrapRGB.set( 0.6, 0.2, 0.1 );
}
} );
}, { normalizeRGB: true } );
loader.load( "models/utf8/ben_dds.js", function ( object ) {
var end = Date.now();
console.log( "ben", end - start, "ms" );
var s = 350;
object.scale.set( s, s, s );
object.position.x = -125;
object.position.y = -125;
scene.add( object );
object.traverse( function( node ) {
node.castShadow = true;
node.receiveShadow = true;
if ( node.material && ( node.material.name === "head" || node.material.name === "skinbody" ) ) {
node.material.wrapAround = true;
node.material.wrapRGB.set( 0.6, 0.2, 0.1 );
}
} );
}, { normalizeRGB: true } );
var geometry = new THREE.CubeGeometry( 20, 20, 20 );
for ( var i = 0; i < 20; i ++ ) {
var object = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: Math.random() * 0xffffff } ) );
object.position.x = Math.random() * 800 - 400;
object.position.y = Math.random() * 800 - 400;
object.position.z = Math.random() * 800 - 400;
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;
scene.add( object );
}
projector = new THREE.Projector();
raycaster = new THREE.Raycaster();
//
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 );
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
}
//
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}
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 );
}
function onDocumentMouseDown( event ) {
event.preventDefault();
show.innerText = "";
var vector = new THREE.Vector3( ( event.clientX / window.innerWidth ) * 2 - 1, - ( event.clientY / window.innerHeight ) * 2 + 1, 0.5 );
projector.unprojectVector( vector, camera );
var raycaster = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );
var intersects = raycaster.intersectObjects( scene.children );
if ( intersects.length > 0 ) {
show.innerText = "intersects=" + intersects.length + " at " + Date.now();
console.log(intersects.length);
}
}
</script>
</body>
</html>
You need to add the recursive flag to raycaster.intersectObjects().
var intersects = raycaster.intersectObjects( scene.children, true );
three.js r.58

Three Js Object3D Button Group Detect Single Object Click While Mouse Movement Causes Object3D Button Group Zoomi

I am trying to detect a cube click in an Object3D group of Cubes. I have viewed, and tried to incorporate the examples and tutorials found at:
http://mrdoob.github.com/three.js/examples/webgl_interactive_cubes.html
and
http://mrdoob.github.com/three.js/examples/canvas_interactive_cubes.html
Also, I have consulted the posts on this site at:
Three.js - how to detect what shape was selected? after drag
and
how to Get CLICKED element in THREE.js
But for some reason, it's still not working. Can anyone please tell me what I'm doing wrong?
Here is my code, thanks:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Double Stamp It No Erasies</title>
<style>
html {
background: url(Images/ComicBookExplosionBackground.jpg) no-repeat center center fixed;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
}
body {
}
</style>
<script src="ThreeJs/build/three.min.js"></script>
</head>
<body onLoad="onLoad();" style="">
<div id="container" style="width:100%; height:100%; position:absolute;"></div>
<script>
var container, ButtonsCamera, ButtonsScene, ButtonsRenderer, ButtonsGeometry, ButtonsGroup;
var mouseX = 0, mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
/****************************** CLICK START **********************************/
var mouse = { x: 0, y: 0 }, projector, INTERSECTED;
var objects = [];
/****************************** CLICK END **********************************/
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
//document.addEventListener( 'mousedown', onDocumentMouseDown, false );
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
ButtonsCamera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 10000 );
ButtonsCamera.position.z = 500;
ButtonsScene = new THREE.Scene();
ButtonsScene.fog = new THREE.Fog( 0xffffff, 1, 10000 );
/*************************** STACKOVERFLOW 1ST ANSWER START **********************************/
var ButtonsGeometry = new THREE.CubeGeometry( 100, 100, 100 );
var ButtonsMaterial = new THREE.MeshFaceMaterial( [
new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'Images/Twitter.jpg' ) } ),
new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'Images/Twitter.jpg' ) } ),
new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'Images/Twitter.jpg' ) } ),
new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'Images/Twitter.jpg' ) } ),
new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'Images/Twitter.jpg' ) } ),
new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'Images/Twitter.jpg' ) } )] );
/*************************** STACKOVERFLOW 1ST ANSWER END **********************************/
ButtonsGroup = new THREE.Object3D();
for ( var i = 0; i < 100; i ++ ) {
var ButtonsMesh;
if(i == 0)
{
ButtonsMesh = new THREE.Mesh( ButtonsGeometry, ButtonsMaterial );
}
else
{
ButtonsMesh = new THREE.Mesh( ButtonsGeometry, ButtonsMaterial );
}
ButtonsMesh.position.x = Math.random() * 2000 - 1000;
ButtonsMesh.position.y = Math.random() * 2000 - 1000;
ButtonsMesh.position.z = Math.random() * 2000 - 1000;
ButtonsMesh.rotation.x = Math.random() * 360 * ( Math.PI / 180 );
ButtonsMesh.rotation.y = Math.random() * 360 * ( Math.PI / 180 );
ButtonsMesh.matrixAutoUpdate = false;
ButtonsMesh.updateMatrix();
ButtonsGroup.add( ButtonsMesh );
}
ButtonsScene.add( ButtonsGroup );
/****************************** CLICK START **********************************/
objects.push( ButtonsMesh );
projector = new THREE.Projector();
/****************************** CLICK END **********************************/
ButtonsRenderer = new THREE.WebGLRenderer();
ButtonsRenderer.setSize( window.innerWidth, window.innerHeight );
ButtonsRenderer.sortObjects = false;
container.appendChild( ButtonsRenderer.domElement );
window.addEventListener( 'resize', onWindowResize, false );
/****************************** CLICK START **********************************/
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
/****************************** CLICK END **********************************/
}
/****************************** CLICK START **********************************/
function onDocumentMouseDown( event ) {
//alert('clicky');
event.preventDefault();
var vector = new THREE.Vector3( ( event.clientX / window.innerWidth ) * 2 - 1, - ( event.clientY / window.innerHeight ) * 2 + 1, 0.5 );
projector.unprojectVector( vector, ButtonsCamera );
var raycaster = new THREE.Raycaster( ButtonsCamera.position, vector.subSelf( ButtonsCamera.position ).normalize() );
var intersects = raycaster.intersectObjects( objects);
if ( intersects.length > 0 ) {
intersects[ 0 ].object.material.color.setHex( Math.random() * 0xffffff );
var particle = new THREE.Particle( particleMaterial );
particle.position = intersects[ 0 ].point;
particle.scale.x = particle.scale.y = 8;
ButtonsScene.add( particle );
}
/*
// Parse all the faces
for ( var i in intersects ) {
intersects[ i ].face.material[ 0 ].color.setHex( Math.random() * 0xffffff | 0x80000000 );
}
*/
}
/****************************** CLICK END **********************************/
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
ButtonsCamera.aspect = window.innerWidth / window.innerHeight;
ButtonsCamera.updateProjectionMatrix();
ButtonsRenderer.setSize( window.innerWidth, window.innerHeight );
}
function onDocumentMouseMove(event) {
mouseX = ( event.clientX - windowHalfX ) * 10;
mouseY = ( event.clientY - windowHalfY ) * 10;
}
function animate() {
requestAnimationFrame( animate );
render();
ButtonsStats.update();
}
/****************************** CLICK START **********************************/
var radius = 100;
var theta = 0;
/****************************** CLICK END **********************************/
function render() {
var ButtonsTime = Date.now() * 0.001;
var rx = Math.sin( ButtonsTime * 0.7 ) * 0.5,
ry = Math.sin( ButtonsTime * 0.3 ) * 0.5,
rz = Math.sin( ButtonsTime * 0.2 ) * 0.5;
ButtonsCamera.position.x += ( mouseX - ButtonsCamera.position.x ) * .05;
ButtonsCamera.position.y += ( - mouseY - ButtonsCamera.position.y ) * .05;
ButtonsCamera.lookAt( ButtonsScene.position );
ButtonsGroup.rotation.x = rx;
ButtonsGroup.rotation.y = ry;
ButtonsGroup.rotation.z = rz;
ButtonsRenderer.render( ButtonsScene, ButtonsCamera );
}
</script>
</body>
</html>
Hey I hope I am not too late but anyway the solution to your problem is
a misplaced statement and a deprecated method.
You only have one object in your objects array that is why when you click on a
random box the raycaster is unlikely to detect an intersection.
Move the array push call into the for loop in order to add every object into
the array instead of the last object created.
for (var i = 0; i < 100; i++) {
var ButtonsMesh;
if (i == 0)
{
ButtonsMesh = new THREE.Mesh(ButtonsGeometry, ButtonsMaterial);
}
else
{
ButtonsMesh = new THREE.Mesh(ButtonsGeometry, ButtonsMaterial);
}
ButtonsMesh.position.x = Math.random() * 2000 - 1000;
ButtonsMesh.position.y = Math.random() * 2000 - 1000;
ButtonsMesh.position.z = Math.random() * 2000 - 1000;
ButtonsMesh.rotation.x = Math.random() * 360 * (Math.PI / 180);
ButtonsMesh.rotation.y = Math.random() * 360 * (Math.PI / 180);
ButtonsMesh.matrixAutoUpdate = false;
ButtonsMesh.updateMatrix();
ButtonsGroup.add(ButtonsMesh);
objects.push(ButtonsMesh);
}
The second problem is that newer versions of THREE don't use subSelf(),
it is replaced by sub(). So make the change to the Raycaster definition.
var raycaster = new THREE.Raycaster(ButtonsCamera.position,
vector.sub(ButtonsCamera.position).normalize());
That should solve your problems but there are more errors in your code
but they are all trivial.
I hope this helps and here is a working version: http://jsbin.com/uhihoq/1/edit
Peace!

Resources