THREE js rotationon one axes toward camera, not affected by parent - three.js

I have situaton:
var camera = new THREE.PerspectiveCamera(...);
scene.add(camera);
var parent = new THREE.Object3D();
parent.position.set(1,2,3);
scene.add(parent);
var child = new THREE.Object3D();
child.position.set(4,5,6);
parent.add(child);
var v = new THREE.Vector3().copy(child.position);
child.localToWorld(v);
child.rotation.z = Math.atan2( ( v.x - camera.position.x ), ( v.y - camera.position.y ) );
It works and child is facing camera on Z axis.
When i do:
parent.rotation.set(1,2,3); // or whatever
child is affected by rotation, how to avoid that rotation and keep the child in same rotation like before the parent was rotated (update local rotation to be the visually unchanged by parent transformation), but to keep a global position changed due parent rotation?

Please try the following after you have set the rotation of your child object:
var matrix = new Matrix4();
var quaternion = new THREE.Quaternion();
parent.updateMatrixWorld(); // ensure matrixWorld is up to date
matrix.extractRotation( parent.matrixWorld );
quaternion.setFromRotationMatrix( matrix );
child.quaternion.premultiply( quaternion.inverse() );

Related

Raycaster Set getting Z value for respective XY

I have array of XY coordinates from which i have to get the respective Z positions. I have created the following code to achieve same.
This function loops through array and calls further function to get the Z value.
function generate_section(){
for(var i=0;i<points.length;i++){
//temporary try to get for the same.
var pts = points[i];
var z = sectioncall(pts.x,pts.y);
console.log(pts,z);
}
}
The following function is a raycaster which cast the ray for the provided x& y value and cast a downward ray.
function sectioncall(x,y){ //grabs the Z value for the provided XY
var top = new THREE.Vector3(x, y , 30 );
var bottom = new THREE.Vector3(x , y , -30 );
var direction = new THREE.Vector3();
direction = direction.subVectors( bottom, top ).normalize();
//start raycaster
var raycaster = new THREE.Raycaster();
raycaster.set( top, direction );
// calculate objects intersecting the picking ray
var intersects = rayCaster.intersectObjects(scene.getObjectByName('MyObj_s').children);
var rpt = intersects[0].point;
//draw a line the way ray caster casting the ray
var geometry = new THREE.Geometry();
geometry.vertices.push( top );
geometry.vertices.push( rpt );
var material = new THREE.LineBasicMaterial( { color : 0xff0000 } );
var line = new THREE.Line( geometry, material );
scene.add( line );
return rpt;
}
With the above code i get the result like this:
but what i want to achive is the result like this:
So that the returning values will be about for respective XY instead of last XY as you see on the console.
You have slightly made a mistake in the code.
it should be
var intersects = raycaster.intersectObjects(scene.getObjectByName('MyObj_s').children);
you misspelled it as rayCaster.

How to set pivot point for an arrow-like shape

I'm creating this arrow-like shape with three.js:
let planeShape = new THREE.Shape()
planeShape.moveTo(0, 0)
planeShape.lineTo(3, 1)
planeShape.lineTo(0, 2)
planeShape.lineTo(1, 1)
planeShape.lineTo(0, 0)
var geometry = new THREE.ShapeGeometry( planeShape )
// Appropriate rotation or translation should take place here
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } )
var mesh = new THREE.Mesh( geometry, planeMaterial )
scene.add( mesh )
And I want to be able to use mesh.lookAt(position) so that the tip of the arrow ends up pointing the specified position. However, I haven't been able to set an appropriate pivot point. I think I'm having problems because I'm creating the arrow shape points in 2D but I end up with a 3D object losing track of my origin point.
Here's an example of what I want to accomplish: https://threejs.org/examples/misc_lookat.html
After var geometry = new THREE.ShapeGeometry( planeShape ) add
geometry.translate(0, -1, 0); // center with x-axis
geometry.rotateY(-Math.PI * 0.5); // align with z-axis to use with lookAt()

Solar system using Three js animation

I am creating a solar system using three js.In that I want to display some of the details on clicking on any objects.I have used object picking concepts.In that I am trying to get the objects which are intersecting with the
clicking.But I am unable get any objects which are intersecting.When I tried to print the objects in the intersects array I am getting as "undefined" and length of the intersects array as 0.
function mous(event) {
var vector = new THREE.Vector3(( event.clientX / window.innerWidth ) * 2 - 1, -( event.clientY / window.innerHeight ) * 2 + 1, 0.5);
vector = vector.unproject(camera);
raycaster = new THREE.Raycaster(camera.position, vector);
var intersects = raycaster.intersectObjects([orbitDir1,orbitDir2,orbitDir3,orbitDir4,orbitDir5]);
alert(intersects[0]);
alert(intersects.length);
}`
And here is the code for orbitDir.
geometry = new THREE.CircleGeometry(2.3, 100);
geometry.vertices.shift();
circle = new THREE.Line(
geometry,
new THREE.LineDashedMaterial({color: 'red'})
);
circle.rotation.x = Math.PI * 0.5 ;
tex = new THREE.ImageUtils.loadTexture("Mercury.jpeg") ;
planet = new THREE.Mesh(
new THREE.SphereBufferGeometry(0.3, 32, 32),
new THREE.MeshPhongMaterial({ map : tex})
);
planet.position.set(2.3, 0, 0);
scene.add(planet);
orbit = new THREE.Group();
orbit.add(circle);
orbit.add(planet);
orbitDir = new THREE.Group();
orbitDir.add(orbit);
//orbitDir.position.x += 0.1 ;
orbitDir.position.y += 4 ;
orbitDir.position.z += 5 ;
orbitDir.rotation.x +=2.3 ;
scene.add(orbitDir);
The code for »unprojection« and raycasting look fine, so I guess that the x and y values might not be right. You are using clientX and clientY which are the mouse coordinates relative to the upper left corner of the window. Those are only valid if your <canvas> is full page. If that is not the case, make sure to use mouse coordinates relative to the upper left edge of the <canvas>.
I think you can do the raycasting like that:
raycaster.intersectObjects(scene, true) //scan the whole scene recursive
docs
Probably the answer you are looking for is here
projector.unprojectVector( vector, camera.position );

Draw line in direction of raycaster in three.js

In three.js, I'm using PointerLock controls the make a basic first person shooter.
I use
function onDocumentMouseDown( event ) {
var raycaster = new THREE.Raycaster();
mouse3D.normalize();
controls.getDirection( mouse3D );
raycaster.set( controls.getObject().position, mouse3D );
var intersects = raycaster.intersectObjects( objects );
...
}
to detect a collision with an object, which means you "shot" the object.
Now, I want to visualize the path the bullet took. I was thinking about drawing a line from where the user is looking to, in direction of the raycaster, but I can't figure out how to do this... Anyone who can help me? I'm new to three.js, never thought drawing a line would be this hard.
Update:
I'm trying to draw a line using:
var geometry = new THREE.Geometry();
geometry.vertices.push(...);
geometry.vertices.push(...);
var line = new THREE.Line(geometry, material);
scene.add(line);
but I can't figure out what to put in place of the "..." . How can I detect which point the line should go to? And how to determine which point it starts from? The player is able to move and even jump so the starting point is always different too.
You can use the following (using r83):
// Draw a line from pointA in the given direction at distance 100
var pointA = new THREE.Vector3( 0, 0, 0 );
var direction = new THREE.Vector3( 10, 0, 0 );
direction.normalize();
var distance = 100; // at what distance to determine pointB
var pointB = new THREE.Vector3();
pointB.addVectors ( pointA, direction.multiplyScalar( distance ) );
var geometry = new THREE.Geometry();
geometry.vertices.push( pointA );
geometry.vertices.push( pointB );
var material = new THREE.LineBasicMaterial( { color : 0xff0000 } );
var line = new THREE.Line( geometry, material );
scene.add( line );
Codepen at: https://codepen.io/anon/pen/evNqGy
You can use something like this:
function animate_Line(frame, totalFrames) {
//Calculate how much of the line should be drawn every iteration
var delta = lineDistance/(totalFrames);
var deltaSpeed = delta * frame;
for(var i=0; i<f_Ray_List[0].length; i++) {
for(var j=0; j<f_Ray_List[1].length; j++) {
//Change Offsets
line.geometry.vertices[1].y = line.geometry.vertices[0].y - deltaSpeed;
//Update Rays = true (Make FRT rays draw-able)
line.geometry.verticesNeedUpdate = true;
}
}
}
where frame is the current frame (a counter in your animate function), totalFrames would be the amount of frames that the line would take to be animated. The lineDistance can be calculated by using this:
lineDistance = line.geometry.vertices[0].y - line.vertices[1].y; //Add this line where you create the line object.
and remember to call line.geometry.verticesNeedUpdate = true; in every line individually, so that the line would able to be animated.
Notice that this is only based on Line.y axis. This would not be great at first. I'm currently working on converting this to Polar coordinates instead but I have no idea what is going on hahah.

Three js Raycast inside a Skydome

So I'm working at a game world where everything is contained in a skydome(giant sphere with environment texture applied).
I'm trying to find out the intersect point of the ray inside the skydome in order to find out the vector player will need to move towards.
the only Issue I found out so far is that the ray wont be casted inside the skydome but when zooming outside of it.
This is how the raycaster looks like on my side.
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
// update the picking ray with the camera and mouse position
raycaster.setFromCamera( mouse, camera );
// raycaster.set(playerModel, c);
// calculate objects intersecting the picking ray
var intersects = raycaster.intersectObjects( scene.children, true );
console.log(intersects);
for ( var i = 0; i < intersects.length; i++ ) {
intersects[ i ].object.material.color.set( 0xff0000 );
}
Also, I would be gratefull if anyone can explain me how do I get the vector where the raycast goes to, not by using raycaster.setFromCamera( mouse, camera ); but raycaster.set(playerModel, targetVector);
Does the target vector needs to be the position vector of the skydome?
Working example i used manytimes:
var spaceplane = [];
var spaceMaterial = new THREE.MeshBasicMaterial();
spaceMaterial.side = THREE.BackSide;
var meshSpace = new THREE.Mesh( new THREE.IcosahedronGeometry( 1000000, 1 ) , spaceMaterial );
meshSpace.rotation.order = 'XZY';
spaceplane.push( meshSpace );
//// add to the scene of course
//////////////// selection on mouse click etc...
var raycaster = new THREE.Raycaster();
raycaster.setFromCamera( mouse, camera );
var intersects = raycaster.intersectObjects( spaceplane, true );
if ( intersects.length > 0 ) {
/// here you have intersection
}

Resources