threejs/raycaster will not see the objects i need - three.js

my raycaster is not seeing the objects it needs to see, i tried putting the mouse x y z on the cordinates the object is in and that still does not work, im new to three.js and raycasting so im stuck on this problem for the last 2 days
this.raycaster = new THREE.Raycaster();
this.mouse = new THREE.Vector3();
s.raycaster.setFromCamera(s.mouse, s.getCamera() );
s.canvas_model[0].addEventListener( 'mousedown', function(event)
{s.onMouseDown(event);} , false);
onMouseDown(event) {
let s = this;
s.bounds = s.canvas_model[0].getBoundingClientRect()
s.mouse.x = ( (event.clientX - s.bounds.left) / s.canvas_model[0].clientWidth ) * 2 - 1;
s.mouse.y = - ( (event.clientY - s.bounds.top) / s.canvas_model[0].clientHeight ) * 2 + 1;
s.intersects = s.raycaster.intersectObjects(s.blocks, true);
for ( var i = 0; i < s.intersects.length; i++){
s.intersects[ i ].object.material.color.set( 0xff0000 );
console.log(s.intersects)
console.log(s.mouse.x);
console.log(s.mouse.y);
}
if (s.intersects == 0){
// console.log(s.intersects)
// console.log(s.mouse.x)
// console.log(s.mouse.y)
}
i have tried s.scene.children it will see the floor and grid but not the blocks screenshot of application
hope someone here has had a problem like this and can help me out here

Related

Tracking Elements on ctx, ctx placed on boxgeometry threejs

I've applied ctx to all the side of BoxGeometry .furthermore, I'm using raycaster to get the data present on ctx so that onclick it gives x,y co-ordinates of ctx and index of that partcular side to understand which side the ctx is present.
this is my code
document.addEventListener ("mousedown",( event ) => {
var vector = new THREE.Vector3();
pointer.x = ( event.clientX / window.innerWidth ) * 2 - 1;
pointer.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
vector.unproject( camera );
raycaster.setFromCamera( pointer, camera);
var intersects = raycaster.intersectObject( this.cube );
if (intersects.length > 0) {
index = Math.floor(intersects[0].faceIndex / 2);
if (index == 0) {
let templabelarray = []
for (let i = 0; i < this.labels.length; i++) {
if (this.labels[i].typename == 'Left' ) {
templabelarray.push(this.labels[i]);
}
this.state.totalLabels.push(templabelarray);
let rect = this.ctxArr[0].getBoundingClientRect()
this.x = e.clientX - rect.left
this.y = e.clientY - rect.top
let i = 0, r;
this.labels will give me the array for ctx present on the particular side and further i"m pssing it into state variable
Using this I'm able to get the index but, unable to fetch x,y co-ordinates for ctx.
any help would be greatly appreciated

Uncaught TypeError: Cannot read property 'length' of null - Three.js

I've trying to draw the square wall by getting mouse clicks coordinates and extrude it.
I've picking up the mouse coordinates by clicking at the scene.
var onDocumentMouseDown = function ( event )
{
//update the mouse variable
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = -( event.clientY / window.innerHeight ) * 2 + 1;
var vector = new THREE.Vector3(mouse.x, mouse.y, 0.5);
vector.unproject( camera );
var dir = vector.sub( camera.position ).normalize();
var distance = - camera.position.z / dir.z;
var pos = camera.position.clone().add( dir.multiplyScalar( distance));
console.log('mouse_x ' + pos.x + ' mouse_y ' + pos.y);
if (clickCount <= 3){
coord[clickCount] = {'x' : pos.x, 'y' : pos.y};
clickCount ++;
} else {
//make new wall and stop function
newshape = new THREE.Shape();
shape.moveTo(coord['0'].x ,coord['0'].y);
shape.lineTo(coord['0'].x, coord['1'].y);
shape.lineTo(coord['2'].x, +coord['2'].y);
shape.lineTo(coord['3'].x, coord['3'].y);
shape.lineTo(coord['0'].x, coord['0'].y);
var newextrudeSettings = {
//*******/
};
}
And when I've recived four coordinates, three.js throw the error:
Uncaught TypeError: Cannot read property 'length' of null
at Object.triangulateShape (three.js:26140)
at ExtrudeGeometry.addShape (three.js:26330)
at ExtrudeGeometry.addShapeList (three.js:26235)
at new ExtrudeGeometry (three.js:26211)
at HTMLDocument.onDocumentMouseDown (script.js:116)
To find points of intersection I prefer to use THREE.Raycaster() (though I've never used THREE.Projector() for this purpose).
This is the result of my code:
I hope I got your conception. Thus, all the stuff you need is here:
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var intersects;
var controlPoints = [];
var clickCount = 0;
function onMouseDown(event) {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
intersects = raycaster.intersectObjects(objects); // objects is an array which contains just the mesh of the plane
if (intersects.length > 0) {
if (clickCount <= 3) { // I took your idea of 4 clicks
controlPoints[clickCount] = intersects[0].point.clone(); // add a control point to the array
// visualization of a control point
var cp = new THREE.Mesh(new THREE.SphereGeometry(0.125, 16, 12), new THREE.MeshBasicMaterial({color: "red"}));
cp.position.copy(intersects[0].point);
scene.add(cp);
clickCount++;
} else { // on the fifth click we'll create our wall
shape = new THREE.Shape();
shape.moveTo(controlPoints[0].x, -controlPoints[0].z);
shape.lineTo(controlPoints[1].x, -controlPoints[1].z);
shape.lineTo(controlPoints[2].x, -controlPoints[2].z);
shape.lineTo(controlPoints[3].x, -controlPoints[3].z);
shape.lineTo(controlPoints[0].x, -controlPoints[0].z);
var extrudeSettings = {
steps: 1,
amount: 2,
bevelEnabled: false
};
var extrudeGeom = new THREE.ExtrudeGeometry(shape, extrudeSettings);
extrudeGeom.rotateX(-Math.PI / 2);
var wall = new THREE.Mesh(extrudeGeom, new THREE.MeshStandardMaterial({
color: "gray"
}));
scene.add(wall);
controlPoints = []; // we clear the array of control points
clickCount = 0; // and reset the counter of clicks
};
};
};
jsfiddle example. 4 clicks for setting control points, the fifth click creates a wall, and so on.

Unable to intersect Points

I unable to intersect Three.Points but i am able to intersect THREE.Mesh, below is my code: Can someone please help me to understand what mistake i am making. When i intersect the Points all i get is 0.
function init()
{
geometry = new THREE.Geometry();
vertex = new THREE.Vector3();
vertex.x=( [i + 3 ] * 140 ) - 1330;
vertex.y = - ( [i + 3 ] * 180 ) + 990;
vertex.z = 100;
geometry.vertices.push(vertex);
var particleTexture = THREE.ImageUtils.loadTexture(imgstr);
var materials = new THREE.PointsMaterial({
map:particleTexture,
size: 150
});
particles = new THREE.Points(geometry, materials);
scene.add(particles);
targetList.push(particles);
}
function onDocumentMouseMove( event ) {
event.preventDefault();
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
}
function onDocumentMouseDown(event){
var projector = new THREE.Projector();
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(targetList);
console.log(intersects.length);
}
function onDocumentMouseDown( event ) {
event.preventDefault();
if(event.which == 1) {
var raycaster = new THREE.Raycaster();
raycaster.setFromCamera( mouse, camera );
raycaster.params.Points.threshold = 100000; // bigger number = bigger sensitivity
var intersects = raycaster.intersectObjects( myobjectsarray,false); // myobject array is array of THREE.Points object
if ( intersects.length > 0 ) {console.log('tadaah',intersects);}
}
}

Three.js mouse picking, 3D model with OBJMTLLoader

i started programing with Three.js. Now i have a problem, when i load an Object with the OBJMTLLoader i dont get any access to change the position of the object with mouseMove. I have pushed the obects into the objects array but it doesnt work. If anybody could help or knowes a good tutorial would be really fine. I hope the structure how i wrote the question is clear....its the first time i´m using stacko.
These are my variables and the function i try to change the objects:
var mouse = new THREE.Vector2();
var raycaster = new THREE.Raycaster();
var objects = [];
function onDocumentMouseMove( event ) {
event.preventDefault();
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
raycaster.setFromCamera(mouse,camera);
intersects = raycaster.intersectObjects(objects);
if (intersects.length> 0) {
intersects[0].object.position.set(5, 5 ,5);
}
}
Here i load the object with the OBJMTLLoader....this works:)
var loader = new THREE.OBJMTLLoader();
loader.load('models/sofa4.obj', 'models/sofa4.mtl', function(object) {
// console.log(object);
object.traverse(function(child) {
if (child instanceof THREE.Mesh) {
child.material.shininess = 0;
// console.log(child.material);
}
});
object.position.z = 2;
object.position.y = -5.95;
object.scale.set(0.05,0.05,0.05);
scene.add(object);
objects.push(object);
});

Threejs raycaster only works super close

I was following mrdoobs examples of how to use raycasting to handle clickable objects. I have also looked at all of the many many similar questions and have tried countless things.
The raycasting works... If I am at a distance of less than 1.
The Raycaster is set to near 0 and far infinity though (defaults).
I haven't seen any code examples where distance was set.
I am hoping for another pair of eyes.
// snippet
glow.clickables = [];
var cubeGeo = new THREE.CubeGeometry(2, 2, 2);
cubeGeo.computeFaceNormals();
var cube = new THREE.Mesh(cubeGeo, redmat);
cube.position.y = 10;
cube.position.x = 0;
cube.position.z = -12;
cube.overdraw = true;
glow.Vis.scene.add(cube);
glow.clickables.push(cube);
onclick_();
var onclick_ = function() {
$('#world').on('mousedown', function(e){
var mouseX = (event.offsetX / $('#world').width()) * 2 - 1;
var mouseY = - ( event.offsetY / $('#world').height()) * 2 + 1;
var vector = new THREE.Vector3(mouseX, mouseY, 0.1); //what should z be set to?
//console.info(vector); // A vector between -1,1 for both x and y. Z is whatever is set on the line above
projector.unprojectVector(vector, glow.Vis.camera);
var conts = glow.Vis.controls.getObject().position; // control 3dObject which the camera is added to.
var clickRay = new THREE.Raycaster(conts, vector.sub(conts).normalize());
var intersects = clickRay.intersectObjects(glow.clickables);
console.info(intersects.length);
if(intersects.length > 0) {
alert("Click detected!");
}
});
}
Setting the mouse position this way is more accurate.
var rect = renderer.domElement.getBoundingClientRect();
mouse.x = ( ( event.clientX - rect.left ) / rect.width ) * 2 - 1;
mouse.y = - ( ( event.clientY - rect.top ) / rect.height ) * 2 + 1;
For mouse detecting (far or near! no matter!), do this:
put this in your global:
var pointerDetectRay, projector, mouse2D;
put this in your init() function:
pointerDetectRay = new THREE.Raycaster();
pointerDetectRay.ray.direction.set(0, -1, 0);
projector = new THREE.Projector();
mouse2D = new THREE.Vector3(0, 0, 0);
put this in your render() loop function:
pointerDetectRay = projector.pickingRay(mouse2D.clone(), camera);
and it's your mouse event:
function onDocumentMouseMove(event) {
event.preventDefault();
mouse2D.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse2D.y = -(event.clientY / window.innerHeight) * 2 + 1;
}
Now, every where that you want to detect the objects under your mouse pointer, use this:
var intersects = pointerDetectRay.intersectObjects(scene.children);
if (intersects.length > 0) {
var intersect = intersects[0];
// intersect is the object under your mouse!
// do what ever you want!
}
I use the following which, for me, works for larger distances:
var projector = new THREE.Projector();
function onDocumentMouseDown( event ) {
event.preventDefault();
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( [sphere,cylinder,cube] );
if ( intersects.length > 0 ) {
intersects[ 0 ].object.material.transparent=true;
intersects[ 0 ].object.material.opacity=0.1;
console.log(intersects[0]);
}
}
This just sets the first selected object to semitransparent. Complete example at: https://github.com/josdirksen/learning-threejs/blob/master/chapter-09/02-selecting-objects.html

Resources