Using three.js raycaster as the developers recommend? - three.js

My code works for picking objects and turning them a different color, but what is the technique to get them back to the original color after my mouse crosses the cube? Here is my code. As it stands, when I bring my mouse over the cube, it turns red.
(document).ready(function () {
window.addEventListener('mousemove', onMouseMove, false);
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
//start a scene
var scene = new THREE.Scene();
//add a cube
var cube = new THREE.Mesh(new THREE.CubeGeometry(3, 3, 3), new THREE.MeshBasicMaterial({ color:0x454545 }));
cube.position.set(0, 0, 0);
scene.add(cube);
//get a renderer
var renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0xffffff);
renderer.setSize(window.innerWidth, window.innerHeight);
$('#GameArea').append(renderer.domElement);
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(10, 10, 10);
camera.lookAt(0,0,0);
var controls = new THREE.TrackballControls(camera);
var light = new THREE.SpotLight(0xeeeeee);
light.position.set(-10, 5, 40);
scene.add(light);
render();
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;
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);
}
}
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);
controls.update();
renderer.render(scene, camera);
requestAnimationFrame(render);
}
});

Related

Bringing back the object to the starting position

Here I'm trying to bring back the object to the starting position in the button click. I tried with some fixing the position of the object with the static position where I have no idea where it works or not. I have searched for solutions where they say to move the camera to FOV direction axis(say calculating the x, y, z).
In detail, if I pan or rotate aa object from initial position to different position, in button click I have to undo it to the the start position.
Here's the https://jsfiddle.net/Ajay_Venkatesh/thpb8csv/1/
'use strict';
var camera, scene, renderer;
var cube, cube_geometry, cube_material;
var controls;
init();
render();
function init() {
scene = new THREE.Scene();
// renderer
renderer = new THREE.WebGLRenderer({
alpha: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 12;
// controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.addEventListener('change', render);
controls.enableZoom = false;
// mesh - cube
cube_geometry = new THREE.CubeGeometry(5, 5, 5);
for (var i = 0; i < cube_geometry.faces.length; i += 2) {
var color = Math.random() * 0xffffff;
cube_geometry.faces[i].color.setHex(color);
cube_geometry.faces[i + 1].color.setHex(color);
}
cube_material = new THREE.MeshLambertMaterial({
color: 0xffffff,
vertexColors: THREE.FaceColors
});
cube = new THREE.Mesh(cube_geometry, cube_material);
scene.add(cube);
// Lights
var light = new THREE.DirectionalLight(0xffffff);
light.position.set(1, 1, 1);
scene.add(light);
var light = new THREE.DirectionalLight(0x002288);
light.position.set(-1, -1, -1);
scene.add(light);
var light = new THREE.AmbientLight(0x222222);
scene.add(light);
// events
window.addEventListener('resize', onWindowResize, false);
}
function render() {
renderer.render(scene, camera);
}
function onWindowResize(event) {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
}

Making breakout game in three.js - detect end of the board

i'm trying to learn Three.js by making game, sadly most resources I would be interested in are outdated, since library seem to change so often.
Currently I am able to move my paddle with my mouse and launch the ball on mouse click, however I've got no clue how to stop paddle to go over the board and make ball bounce from the edges.
Can anyone point me in the right direction? Here is my current code:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 10000);
//renderer
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
//board
geometry = new THREE.BoxGeometry(10, 6, 0.00001)
material= new THREE.MeshBasicMaterial({color: "blue"});
var board = new THREE.Mesh(geometry,material);
scene.add(board);
//paddle
geometry = new THREE.BoxGeometry(1, 0.1, 0.2);
material = new THREE.MeshBasicMaterial({ color: "red" });
var paddle = new THREE.Mesh(geometry, material);
paddle.position.set(0, -2.5, 0);
scene.add(paddle);
camera.position.z = 5;
//ball
var geometry = new THREE.SphereGeometry(0.1, 32, 32);
var material = new THREE.MeshBasicMaterial({ color: 0xffff00 });
var ball = new THREE.Mesh(geometry, material);
ball.moving = false;
ball.position.set(0, -2.3, 0);
var velocityY = 0.05; //ball Y speed
scene.add(ball);
//mouse movements
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
function onMouseMove(e) {
mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
mouse.y = - (e.clientY / window.innerHeight) * 2 + 1;
paddle.position.x = mouse.x * 5.5;
}
function onMouseClick(e) {
ball.moving = true;
}
window.addEventListener('mousemove', onMouseMove, false);
window.addEventListener('click', onMouseClick, false);
function animate() {
requestAnimationFrame(animate);
// ball.position.y += -0.01;
if (ball.moving === false) {
// console.log('jest false')
ball.position.x = paddle.position.x;
} else {
ball.position.y += velocityY;
ball.position.x += 0.01;
}
renderer.render(scene, camera);
}
animate();
Go here:
https://threejs.org/editor/
Load the arkanoid example..
Select the Scene object in the list on the right...
Click edit on the Game Logic script at the bottom...

Detecting object collision by dragging. Trying to use the raycaster intersectObjects method

I am simply trying to detect when the lower sphere (the draggable one) is intersecting with the upper ones. I'm sure there's something I do not understand, unfortunately, nothing is crossing my mind on what.
<script src='https://threejs.org/build/three.min.js'></script>
<script src='https://threejs.org/examples/js/controls/DragControls.js'></script>
<script>
window.onload = init;
// Global variables
var renderer, raycaster, mouse,
scene, camera, sphere1, sphere2,
sphere3, sphere4;
raycaster = new THREE.Raycaster();
mouse = new THREE.Vector2();
function init(){
// Get WebGL ready
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer = this.renderer;
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 500);
camera.position.set(0, 0, 100);
camera.lookAt(0, 0, 0);
scene = new THREE.Scene();
// Get set
drawSpheres();
// Go
eventful();
animate();
};
function animate(){
requestAnimationFrame(animate);
renderer.render(scene, camera);
};
function eventful(){ // Where all events happen
new THREE.DragControls([sphere1], camera, renderer.domElement);
window.addEventListener( 'mousemove', onMouseMove, false);
};
function drawSphere(){ // Sphere geometry
var geometry, material, sphere;
geometry = new THREE.SphereBufferGeometry(3, 50, 50, 0, Math.PI * 2, 0, Math.PI * 2);
material = new THREE.MeshNormalMaterial();
sphere = new THREE.Mesh(geometry, material);
return sphere;
};
function drawSpheres(){ // Draw four corners for the quadrant
sphere1 = drawSphere(); sphere1.position.set(20, 0, 0);
sphere2 = drawSphere(); sphere2.position.set(15, 23, 0);
sphere3 = drawSphere(); sphere3.position.set(0, 22, 0);
sphere4 = drawSphere(); sphere4.position.set(-20, 20, 0);
scene.add(sphere1, sphere2, sphere3, sphere4);
};
function onMouseMove(event){ // Calculate mouse movements
// Pixel coordinates
mouse.x = event.clientX;
mouse.y = event.clientY;
raycasting(renderer, scene, camera);
};
function raycasting(renderer, scene, camera){
raycaster.setFromCamera(sphere1, camera); // Update the picking ray with the camera and mouse movements
intersects = raycaster.intersectObjects([sphere2, sphere3, sphere4]);
for(var i = 0; i < intersects.length; i++){
intersects[i].object.material.color.set(0xff0000);
console.log('Hit on: ', intersects[i]);
}
};
</script>
The only thing I can think of is my usage of the intersectObjects() method or the setFromCamera(), but I am not sure. I think this would make sense, since it is updated on mouse move. How would I say: "I want the draggable sphere to be the raycaster, as I move it, and detect collision"? Or something simpler to detect when things collide.
For instance, consider the following:
window.onload = init;
// Global variables
var renderer, raycaster, mouse,
scene, camera, sphere1, sphere2,
sphere3, sphere4;
raycaster = new THREE.Raycaster();
mouse = new THREE.Vector2();
console.log(raycaster);
function init(){
// Get WebGL ready
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer = this.renderer;
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 500);
camera.position.set(0, 0, 100);
camera.lookAt(0, 0, 0);
scene = new THREE.Scene();
// Get set
drawSpheres();
// Go
eventful();
animate();
};
function animate(){
requestAnimationFrame(animate);
renderer.render(scene, camera);
};
function eventful(){ // Where all events happen
new THREE.DragControls([sphere1], camera, renderer.domElement);
window.addEventListener( 'mousemove', onMouseMove, false);
};
function drawSphere(){ // Sphere geometry
var geometry, material, sphere;
geometry = new THREE.SphereBufferGeometry(3, 50, 50, 0, Math.PI * 2, 0, Math.PI * 2);
material = new THREE.MeshNormalMaterial();
sphere = new THREE.Mesh(geometry, material);
return sphere;
};
function drawSpheres(){ // Draw four corners for the quadrant
sphere1 = drawSphere(); sphere1.position.set(20, 0, 0);
sphere2 = sphere1.clone(); sphere2.position.set(15, 23, 0);
sphere3 = sphere1.clone(); sphere3.position.set(0, 22, 0);
sphere4 = sphere1.clone(); sphere4.position.set(-20, 20, 0);
console.log(sphere1, sphere2, sphere3, sphere4);
scene.add(sphere1, sphere2, sphere3, sphere4);
};
function onMouseMove(event){ // Calculate mouse movements
// Normalized Coordinate System
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
raycasting(renderer, scene, camera);
};
function raycasting(renderer, scene, camera){
raycaster.setFromCamera(mouse, camera); // Update the picking ray with the camera and mouse movements
intersects = raycaster.intersectObjects([sphere2, sphere3, sphere4]);
for(var i = 0; i < intersects.length; i++){
console.log('Hit on: ', intersects[i].object.uuid);
}
};
In this example, the raycaster is the mouse. You'll see the 'hit' message on the console, every time there is a mouse hover the spheres I've specified in the intersectObjects() method.
if you aren't casting a ray from the mouse cursor, you don't need .setFromCamera().. you would just set up the ray manually.
You can use raycasting to check if one sphere hits another, or you can do a sphere->sphere intersection test like this..
var tmp = new THREE.Vector3();
function spheresCollide(centerA,radiusA,centerB,radiusB){
var sqdist = radiusA+radiusB;
sqdist*=sqdist;
tmp.copy(centerB).sub(centerA)
if(tmp.lengthSq()<sqdist)return true;
return false;
}
//centerA and centerB are the vector3 positions of your spheres.. radiusA and B are the sphere radii
To do a raycast, you'll need to do something like the following, for each sphere:
rayCaster.ray.origin.copy(sphereA.position);
rayCaster.ray.direction.copy(sphereB.position).sub(sphereA.position).normalize()
intersects = raycaster.intersectObjects([sphereB]);
for(var i = 0; i < intersects.length; i++){
tmp.copy(intersects[i].position).sub(sphereA.position);
if(tmp.length()<(radiusA+radiusB)){
intersects[i].object.material.color.set(0xff0000);
console.log('Hit on: ', intersects[i]);
}
}
It took me a while to get through this. There's something different about raycasting to a moving object. The idea behind ray casting is that a ray is being casted. For this example, the setFromCamera() method won't do, because the 'sphere' is supposed to be the object the ray(s) is(are) coming from.
<script src='https://threejs.org/build/three.min.js'></script>
<script src='https://threejs.org/examples/js/controls/DragControls.js'></script>
<script>
window.onload = init;
// Global variables
var renderer, raycaster,
scene, camera, sphere1, sphere2,
sphere3, sphere4, dragControls;
function init(){
// Get WebGL ready
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer = this.renderer;
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 500);
camera.position.set(0, 0, 100);
camera.lookAt(0, 0, 0);
scene = new THREE.Scene();
// Get set
drawSpheres();
// Go
eventful();
animate();
};
function animate(){
requestAnimationFrame(animate);
renderer.render(scene, camera);
raycasting();
};
function eventful(){ // Where all events happen
dragControls = new THREE.DragControls([sphere1], camera, renderer.domElement);
dragControls.addEventListener('dragstart', onDragStart, false);
dragControls.addEventListener('dragend', onDragEnd, false);
};
function drawSphere(){ // Sphere geometry
var geometry, material, sphere;
geometry = new THREE.CubeGeometry(3,3,3,1,1,1);
material = new THREE.MeshBasicMaterial({
wireframe: true
});
sphere = new THREE.Mesh(geometry, material);
return sphere;
};
function drawSpheres(){ // Draw four corners for the quadrant
sphere1 = drawSphere(); sphere1.position.set(20, 0, 0);
sphere2 = sphere1.clone(); sphere2.position.set(15, 23, 0);
sphere3 = sphere1.clone(); sphere3.position.set(0, 22, 0);
sphere4 = sphere1.clone(); sphere4.position.set(-20, 20, 0);
console.log(sphere1, sphere2, sphere3, sphere4);
scene.add(sphere1, sphere2, sphere3, sphere4);
};
function onDragStart(event){
console.log('on drag start');
};
function onDragEnd(event){
console.log('on drag end');
};
function onMouseMove(event){ // Calculate mouse movements
// Normalized Coordinate System
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
};
//////////////////////////////
//////// RAYCASTING //////////
//////////////////////////////
function raycasting(){ // Blast rays like Cyclops or Superman, but only to measure proximity
var sphere1Origin, // The 3D position of sphere1 when the page loads
vIndex, // Vertex index
sphere1VLength, // The amount of vertices
dVector, // The directions the ray should be pointing to while it is moving
raycaster, // The ray casting from a given point
sphere1Origin = getUpdatedPosition();
sphere1VLength = sphere1.geometry.vertices.length;
for(vIndex = 0; vIndex < sphere1VLength; vIndex++){
dVector = bindRaysToVertices(sphere1, vIndex);
raycaster = raycast(sphere1Origin, dVector);
collided = detectCollision(raycaster, dVector).hasCollided;
if(collided){
console.log('Hit!');
}
}
};
function detectCollision(raycaster, dVector){ // Determines whether there is/are (a) collision(s)
var collisions, // Results of each collisions
collided; // True/False
collisions = raycaster.intersectObjects([sphere2, sphere3, sphere4]);
collided = collisions.length > 0 && collisions[0].distance < dVector.length();
return {
hasCollided: collided,
collisionsList: collisions
};
};
function bindRaysToVertices(sphere1, vIndex){ // Make the geometry blast rays in all directions, while moving
var lVertex, // The re-calculated (updated) vertices for the moving object
gVertex, // The complete representation of the re-calculated (updated) vertices
dVector; // The directions the ray should be pointing to while it is moving
lVertex = sphere1.geometry.vertices[vIndex].clone();
gVertex = lVertex.applyMatrix4(sphere1.matrix);
dVector = gVertex.sub(sphere1.position);
return dVector;
};
function getUpdatedPosition(){
var sphere1Origin, // The 3D position of sphere1 when the page loads
sphere1Origin = sphere1.position.clone();
return sphere1Origin;
};
function raycast(sphere1Origin, dVector){
// Make the sphere cast the ray, through its vertices,
// while moving, using a Normalized Coordinate System
return new THREE.Raycaster(sphere1Origin, toNCS(dVector));
};
function toNCS(dVector){ // To Normalize Coordinate System
return dVector.clone().normalize();
};
</script>
Following Stemkoski example, I've decided to use cubes as wireframes, and should there be a need to have a sphere, the cube should be within it. Otherwise it will be computationally expensive to have a sphere blasting rays like the Sun for proximity detection purposes.

Three.js - How to slowly change the camera's orientation untill it reaches a specific vector

I'm using Three.js to develop a player for 360° pictures, and I need some advice.
I have created a few cliquable meshs inside the scene. Currently, when the user clicks on a mesh, the camera's orientation is brutally changed to the mesh's direction. (this done by calling THREE.Camera.lookat()).
What I want is that when the users clicks, the camera transitions smoothly from it's target vector to the mesh's direction. I would like that the camera takes about 1 second to go from its current vector to the mesh's direction.
I have seen that tween is a library with which we can animate the scene, but I didn't really understand how it works.
Do you know what I could use to implement this animation ?
If tween can help me, can you explain how tween comes into play with three.js, or can you link some githubs or else ?
Thank you for feedbacks.
Just an extension of the manthrax's idea with Tween.js
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 0, 0);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var sphere = new THREE.Mesh(new THREE.SphereGeometry(10, 32, 24), new THREE.MeshBasicMaterial({
color: "yellow",
wireframe: true
}));
scene.add(sphere);
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var startRotation = new THREE.Quaternion();
var targetRotation = new THREE.Quaternion();
window.addEventListener("mousedown", onMouseDown, false);
function onMouseDown(event) {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
let newPosition = raycaster.ray.at(10);
setPoint(newPosition);
// manthrax's idea + Tween.js
startRotation.copy(camera.quaternion);
camera.lookAt(newPosition);
camera.updateMatrixWorld();
targetRotation = camera.quaternion.clone();
camera.quaternion.copy(startRotation);
new TWEEN.Tween(camera.quaternion).to(targetRotation, 1000).easing(TWEEN.Easing.Bounce.Out).delay(250).start();
// one of benefits of using Tween.js is easings
// you can find many of them here
// https://sole.github.io/tween.js/examples/03_graphs.html
}
function setPoint(position) {
let point = new THREE.Mesh(new THREE.SphereGeometry(0.125, 4, 2), new THREE.MeshBasicMaterial({
color: "red",
wireframe: true
}));
point.position.copy(position);
scene.add(point);
}
render()
function render() {
requestAnimationFrame(render);
TWEEN.update(); // don't forget to put this line into the animation loop, when you use Tween.js
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/91/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tween.js/17.2.0/Tween.min.js"></script>
Something like:
var targetRotation,startTime,transitionDuration;
var startRotation = camera.quaternion.clone();
function smoothTransition(newTarget){
startRotation.copy(camera.quaternion);
camera.lookAt(newTarget);
camera.updateMatrixWorld();
targetRotation = camera.rotation.clone();
startTime = performance.now();
transitionDuration = 1000;
}
In animate:
if(startRotation){
var playTime = (performance.now()-startTime)/transitionDuration;
if(playTime>1)playTime = 1;
Quaternion.slerp(startRotation,targetRotation,camera.rotation,playTime);
camera.updateMatrixWorld();
}

Three.js Raycasting with Camera as Origin

I'm trying to determine whether a point in space is visible to the camera or hidden behind other objects in the scene. I'm doing this by casting a ray from the position of the camera to that point in space and testing if that ray is intersected by an set of intersectable objects.
My problem is no intersections occur until the camera position itself intersects one of the objects in the set of intersectable objects.
I've created a jsfiddle in which, if an intersection is detected, a line is drawn from the camera position to the position in space i'm testing for visibility. Currently I believe, the line is only draw at specific points where the camera position intersects the set of intersectable objects.
How do I get the intersections to be registered as they should be, without having to have the camera position intersect objects in the set of intersectable objects?
the code:
var container;
var camera, controls, scene, renderer;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.z = 1000;
controls = new THREE.OrbitControls(camera);
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
controls.keys = [65, 83, 68];
controls.addEventListener('change', render);
// world
scene = new THREE.Scene();
var testObject_G = new THREE.CubeGeometry(100, 100, 5);
var testObject_M = new THREE.MeshBasicMaterial({
color: 0xBBBBBB
});
var testObject_Mesh = new THREE.Mesh(testObject_G, testObject_M);
testObject_Mesh.position.x = -150;
scene.add(testObject_Mesh);
var testObject_Mesh2 = new THREE.Mesh(testObject_G, testObject_M);
testObject_Mesh2.position.x = 0;
scene.add(testObject_Mesh2);
var testObject_Mesh3 = new THREE.Mesh(testObject_G, testObject_M);
testObject_Mesh3.position.x = 150;
scene.add(testObject_Mesh3);
scene2 = new THREE.Object3D();
// renderer
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0xffffff, 1);
container = document.getElementById('container');
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);
controls.handleResize();
render();
}
function animate() {
requestAnimationFrame(animate);
controls.update();
}
function render() {
renderer.render(scene, camera);
castRays();
}
function castRays() {
// rays
var direction = new THREE.Vector3(0, 200, -200);
var startPoint = camera.position.clone();
var ray = new THREE.Raycaster(startPoint, direction);
scene.updateMatrixWorld(); // required, since you haven't rendered yet
var rayIntersects = ray.intersectObjects(scene.children, true);
if (rayIntersects[0]) {
console.log(rayIntersects[0]);
var material = new THREE.LineBasicMaterial({
color: 0x0000ff
});
var geometry = new THREE.Geometry();
geometry.vertices.push(new THREE.Vector3(ray.ray.origin.x, ray.ray.origin.y, ray.ray.origin.z));
geometry.vertices.push(new THREE.Vector3(ray.ray.direction.x, ray.ray.direction.y, ray.ray.direction.z));
var line = new THREE.Line(geometry, material);
scene2.add( line );
}
scene.add(scene2);
}
Thank you
For anyone currently seeing this thread, THREE.Projector has been replaced.
Three.js THREE.Projector has been moved to
The code below handles a 3D vector. If you go to the link above, the first commenter provided the code for a 2D vector.
var vector = new THREE.Vector3();
var raycaster = new THREE.Raycaster();
var dir = new THREE.Vector3();
...
if ( camera instanceof THREE.OrthographicCamera ) {
vector.set( ( event.clientX / window.innerWidth ) * 2 - 1, - ( event.clientY / window.innerHeight ) * 2 + 1, - 1 ); // z = - 1 important!
vector.unproject( camera );
dir.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
raycaster.set( vector, dir );
} else if ( camera instanceof THREE.PerspectiveCamera ) {
vector.set( ( event.clientX / window.innerWidth ) * 2 - 1, - ( event.clientY / window.innerHeight ) * 2 + 1, 0.5 ); // z = 0.5 important!
vector.unproject( camera );
raycaster.set( camera.position, vector.sub( camera.position ).normalize());
}
var intersects = raycaster.intersectObjects( objects, recursiveFlag );`
Your idea of casting a ray is good, however raycasting in three.js already does this :
mouse.x = ( ( event.clientX - renderer.domElement.offsetLeft ) / renderer.domElement.width ) * 2 - 1;
mouse.y = - ( ( event.clientY - renderer.domElement.offsetTop ) / renderer.domElement.height ) * 2 + 1;
this formula maps a pixel coordinate from Screen Space to a point in Normalized Device Coordinate ( NDC ) Space.
projector.unprojectVector( vector, camera );
maps a point from NDC Space to a point in World space
Raycaster then creates a ray from the camera position through that world point.
Here is your working Fiddle in which I changed the way of raycasting in your scene and this works, all you have to do now is creating a ray with the right coordinates that I provided you.
r.68

Resources