Three.js Pointerlockcontrols shooting along y-axis - javascript

Currently I am developing a FPS with three.js and pointerlockcontrols.
Using the code below I can shoot into any horizontal direction:
var direction = new THREE.Vector3( 0, 0, -1 );
var rotation = new THREE.Euler( 0, 0, 0, "XYZ" );
var cameraDirection = new THREE.Vector3(this.game.usermodel.root.children[0].position.x, this.game.usermodel.root.children[0].rotation._x, this.game.usermodel.root.children[0].position.z);
cameraDirection.copy( direction ).applyEuler( this.game.user.rotation );
var raycaster = new THREE.Raycaster(this.game.usermodel.root.children[0].position, cameraDirection);
But my code doesn't take the y-axis into account. The line below holds the pitch rotation:
this.game.usermodel.root.children[0].rotation._x
How can I apply this value so I can shoot along the y-axis (vertically into any direction) as well? Currently the bullet is going along a straight line.
Thanks in advance for your assistance.

If you are using PointerLockControls and you want to set a raycaster, you can use this pattern:
var direction = new THREE.Vector3();
var raycaster = new THREE.Raycaster(); // create once and reuse
...
controls.getDirection( direction );
raycater.set( controls.getObject().position, direction );
Do not set the camera position or rotation directly if you are using PointerLockControls.
three.js r.71

Investigating this a bit more, I finally came up with a workaround myself. It might not be the perfect way to do this, but it works.
It now works like this: I'm getting the basic mesh rotation and apply the euler, I then add the pitch rotation. In this way I pass the horizontal and vertical rotation into the raycaster.
var direction = new THREE.Vector3( 0, 0, -1 );
direction.copy( direction ).applyEuler( this.game.user.rotation );
direction.y = this.game.usermodel.root.children[0].rotation._x;
var raycaster = new THREE.Raycaster(this.game.usermodel.root.children[0].position, direction);
Everyone is still welcome to comment on this or come up with a more elegant solution.

Related

Quaterion-rotate bone untill it alignes with a Vector3, three js

I want to rotate a bone so it is aligned with a Vector3 (directionToTarget), I have:
const directionToTarget = new THREE.Vector3(random, random, random); //pseudocode randoms
directionToTarget.normalize();
var Hand2worldQ = new THREE.Quaternion();
this._anchor['LeftHandIndex1'].getWorldQuaternion(Hand2worldQ); // gets Lefthand bone quaternion
this._mesh.skeleton.bones[ 0 ].quaternion.set( SomeFunctionThatMakesVecintoQuarternion(directionToTarget );
// this._mesh.skeleton.bones inherits Hand2worldQ/LeftHand rotation
SomeFunctionThatMakesVec3intoQuarternion(directionToTarget ) is what i need
Object3D starts by looking down the 0, 0, 1 axis. You can use the Object3D.lookAt() method to make this object point towards your target vector. Then you can extract that rotation and use it for whatever else you need:
// Initialize an abstract object looking towards 0, 0, 1
const object3D = new THREE.Object3D();
// Rotate it so it looks towards the target xyz coordinates
object3D.lookAt(randomX, randomY, randomZ);
// This will now have the final rotation
const myQuaternion = object3D.quaternion;
console.log(myQuaternion);

Robotic arm's movements with three.js

i'm trying to realize a robotic arm using the three.js library. My idea is to use hierachical levels in order to create the arm's geometry in such a way that the first level of the geometry would be the basis of the movements for the entire arm. Could someone help me accomplishing this task?
You should use a different Mesh for each part in the robotic arm,
and then add each part to it's parent Mesh.
then when you will rotate a parent Mesh, It's children Meshes will rotate with him.
for example:
var mat = new THREE.MeshBasicMaterial();
var mainHandGeometry = new THREE.BoxGeometry(50,10,10);
var mainMesh = new THREE.Mesh(mainHandGeometry ,mat );
var midHandGeometry = new THREE.BoxGeometry(30,5,5);
var midMesh = new THREE.Mesh(midHandGeometry ,mat );
var lastHandGeometry = new THREE.BoxGeometry(15,3,3);
var lastMesh = new THREE.Mesh(lastHandGeometry ,mat );
midMesh.add(lastMesh);
lastMesh.position.set(10,10,10);
mainMesh.add(lastMesh);
midMesh.position.set(10,10,10);
Now when you will rotate mainMesh it will rotate with it's children.
If you will rotate midMesh it will rotate with lastMesh.

THREE.js lookAt - How to pan smoothly between old and new target positions?

Example JSfiddle
I can get my cone to point at each target sphere in turn (red,green,yellow,blue) using the THREE.js "lookAt" function.
// Initialisation
c_geometry = new THREE.CylinderGeometry(3, 40, 120, 40, 10, false);
c_geometry.applyMatrix( new THREE.Matrix4().makeRotationX( Math.PI / 2 ) );
c_material = new THREE.MeshNormalMaterial()
myCone = new THREE.Mesh(c_geometry, c_material);
scene.add(myCone);
// Application (within the Animation loop)
myCone.lookAt(target.position);
But now I want the cone to pan smoothly and slowly from the old target to the new target. I guess that I can do it by computing intermediate points on the circular arc which is centred at the cone centre Cxyz and which passes from the previous target position Pxyz to the new target position Nxyz.
Please can someone point me to suitable: (a) utilities or (b) trigonometry algorithms or (c) code examples for calculating the xyz coordinates of the intermediate points on such an arc? (I will supply the angular increment between points based on desired sweep rate and time interval between frames).
You want to smoothly transition from one orientation to another.
In your case, you would pre-calculate the target quaternions:
myCone.lookAt( s1.position );
q1 = new THREE.Quaternion().copy( myCone.quaternion );
myCone.lookAt( s2.position );
q2 = new THREE.Quaternion().copy( myCone.quaternion );
Then, in your render loop:
myCone.quaternion.slerpQuaternions( q1, q2, time ); // 0 < time < 1
three.js r.141
For those of you looking to lerp position and lookAt, you can create a initial lookAt target from the current look direction and lerp that towards the final target:
function MoveWhileLookingAt(object: Object3D, destination: Vector3, lookAt: Vector3){
const fromPosition = object.position.clone();
const fromLookAt = new Vector3(
0,
.1, // To avoid initial camera flip on certain starting points (like top down view)
-object.position.distanceTo(lookAt) // THREE.Camera looks down negative Z. Remove the minus if working with a regular object.
);
object.localToWorld(fromLookAt);
const tempTarget = fromLookAt.clone();
function LookAtLerp(alpha: number){
// This goes in your render loop
object.position.lerpVectors(fromPosition, destination, alpha);
tempTarget.lerpVectors(fromLookAt, lookAt, alpha);
object.lookAt(tempTarget);
}
}

how to flip a cube in air using three.js

I am using three.js framework and using physi.js for forces and gravity. My problem is that i has given some position to a dice on a plane and want to lob it or flip it from its position with some angle by clicking on it such that it rotate in air and fall on plane due to gravity force of plane.
i have idea about onclickevent method but i don't know how to set the dice to jump with some height in 90 degree and rotate it with some angle only one time for one click.
if you have some suggestion please give me method to set up the dice
thank you
i have no experience with physi.js, for physics i use cannon.js, so i do have some experience with physics. i can tell you how it's done, but i cant provide an example just yet. the first thing you need to do is cast a ray from the camera to the dice. This tells you if the object is clicked on. from there you apply a force to where the object is clicked. i hope this helps.
EDIT/Follow up:
I've been looking over physi.js, and it seems pretty similar to cannon.js. Also, there are many aspects to what you're asking, but i'll try to be as comprehensive as possible.
The first thing to do is set the gravity. In the examples it is done by:
var scene = new Physijs.Scene({ fixedTimeStep: 1 / 120 });
scene.setGravity(new THREE.Vector3( 0, -30, 0 ));
the next thing to do is define the plane the dice is sitting on as a rigid body, and the dice as a rigid body.
var dice = new Physijs.BoxMesh(
new THREE.CubeGeometry(5, 5, 5), //the collision geometry
new THREE.MeshLambertMaterial({ map: THREE.ImageUtils.loadTexture('images/dicetexture.jpg' )});, // material of the dice
5, // mass, for the plane use 0, meaning it doesnt move.
{ restitution: .2, friction: .8 } //contact material
);
and finally, you need to apply a force, i cant find an example of it, but going over the source real quick, i found:
// Physijs.Mesh.applyForce
Physijs.Mesh.prototype.applyForce = function ( force, offset ) {
if ( this.world ) {
this.world.execute( 'applyForce', { id: this._physijs.id, force_x: force.x, force_y : force.y, force_z : force.z, x: offset.x, y: offset.y, z: offset.z } );
}
};
both force and offset should be vectors. force being the direction and magnitude, offset being the point of origin.
i'll experiment a bit more with physi.js it seems to have solved some problems i've been pondering with. if this still doesnt solve the problem. i'll post an example.
as for letting it spin for a set number of times in a preset height, i think that's a lot of experimenting with the values...
EDIT 2:
In the fiddle you posted the problem you explained was an undefined variable, effect.
if (intersects.length > 0) {
intersects[ 0 ].applyImpulse(effect, offset);
}
change this to:
if (intersects.length > 0) {
var effect = new THREE.Vector3( 0, 100, 0 );
var offset = new THREE.Vector3( 0, 0, 0 );
intersects[ 0 ].object.applyImpulse(effect, offset);
}
the values ARE defined, but you define them in a different function.
function apply_force(){
var effect = new THREE.Vector3( 0, 100, 0 );
var offset = new THREE.Vector3( 0, 0, 0 );
object.applyImpulse( effect, offset );
}
this function will not be used anymore, so you might as well remove it.
CLICK TIMER:
if(canClick == true){
//process click
canClick = false;
setTimeout(function(){canClick = true}, 5000)//5 seconds before the user can click again.
}

How to get correct values for normals in threejs?

I don’t understand how normals are computed in threejs.
Here is my problem :
I create a simple plane
var plane = new THREE.PlaneGeometry(10, 100, 10, 10);
var material = new THREE.MeshBasicMaterial();
material.setValues({side: THREE.DoubleSide, color: 0xaabbcc});
var mesh = new THREE.Mesh(plane, material);
mesh.rotateY(Math.PI / 2);
scene.add(mesh);
When I read the normal of this plane, I get (0, 0, 1).
But the plane is parallel to the z axis so the value is wrong.
I tried adding
mesh.geometry.computeFaceNormals();
mesh.geometry.computeVertexNormals();
but I still get the same result.
Did I miss anything ?
How can I get correct values for normals from threejs ?
Thanks.
Geometry normals are in object space. To transform them to world space, first make sure the object matrix is updated.
object.updateMatrixWorld();
(The renderer does this for you in each render loop, so you may be able to skip this step.)
Then, compute the normal matrix:
var normalMatrix = new THREE.Matrix3().getNormalMatrix( object.matrixWorld );
Now transform the normal to world space like so:
var newNormal = normal.clone().applyMatrix3( normalMatrix ).normalize();
three.js r.66

Categories