Is object facing another - javascript

I'd like to derive a value for how much one object is facing another. For example if it is directly facing the value would be 1 and facing directly away -1.
I have the object's global position and a quaternion for orientation. I'm using three.js
This is what I have so far, but its not giving me numbers I would expect.
Storing the object orientation as 3 part vector:
const lookVector = new THREE.Vector3(0,0,1);
const direction = lookVector.clone().applyMatrix4(torsoMesh.matrix);
this.lookVector = direction.sub(this.worldPosition);
Then using this to derive an angle to another point:
angleTo(pointOfInterest){
const vectorToPOI = pointOfInterest.sub(this.worldPosition);
const angle = this.lookVector.angleTo(vectorToPOI);
return angle;
}

one way to achieve this is using dot product. It is very simple, you just normalize both vectors and multiply each component respectively, then sum them up. I won't go into more detail here, because there is loads of resources explaining this on the internet. But here is an example of how to do it in three.js:
this.lookVector.normalize();
pointOfInterest.normalize();
var angleValue = this.lookVector.dot(pointOfInterest);
this will give exactly what you asked for (just remember that by calling normalize() on a vector, you are modifying it).
angleValue is actually just the cosine of the angle between the two vectors, so another way would just be to do:
.
.
return Math.cos(angle);
hope I understood you question correctly.

I know the mesh objects keep rotation values in radians. Maybe you can have a "parent mesh" so to speak and its its rotation values to determine this.

Related

Three JS rotate model towards xyz position

I'm trying to rotate an object in Three JS towards a fixed xyz location within a space. Currently I'm able to achieve it like this:
var position_x = -0.85;
var position_z = -4.44;
model.lookAt(position_x, 0, position_z);
However the lookAt() function rotates the model instantly and I would like to rotate the model more slowly. Is there a way to accomplish this using built in Three JS functions?
Thanks!
Is there a way to accomplish this using built in Three JS functions?
Yes, you can use Quaternion.rotateTowards() which works similar to Unity's Quaternion.rotateTowards() method.
The idea is to compute a target orientation which is represented by a quaternion. You can do this by using Matrix4.lookAt() and then create a quaternion based on this matrix via Quaternion.setFromRotationMatrix().
Next, you compute an angular step per frame the will define how much your object is turned towards the target. The computation of step looks like so:
const step = speed * delta;
delta is the time delta value in seconds and speed represents the turn rate of our model in radians per second.
A complete code example is available is here:
https://threejs.org/examples/webgl_math_orientation_transform

Detecting a Fist with Leap Motion SDK V2

I want to check if a Hand in a Leap Motion Frame is currently a Fist.
The usually suggested method is to look for hand.grabStrength with a value of 1. The problem is that the value jumps to 1 even with a "Claw-Like" Hand, or anything else with very slightly curled fingers.
Another approach would be to check on each finger if it is extended. But this has a similiar issue, Fingers only count as extended if they are completely straight. So even if i check for all fingers to be not extended, the same issue as above occurs (claw-like hands get recognized as grabbed).
Combining these two methods also does not solve the issue, which is not surprising given that they both suffer from the same problems.
Now, we do have all the bones of each finger available, with positions and everything. But I have no idea where to start with the math to detect if a finger is curled.
Basically I have this setup for now:
var controller = Leap.loop(function(frame){
if(frame.hands.length>0){
//we only look at the first available hand
var hand = frame.hands[0];
//we get the index finger only, but later on we should look at all 5 fingers.
var index = hands.fingers[1];
//after that we get the positions of the joints between the bones in a hand
//the position of the metacarpal bone (i.e. the base of your hand)
var carp = index.carpPosition;
//the position of the joint on the knuckle of your hand
var mcp = index.mcpPosition;
//the position of the following joint, between the proximal and the intermediate bones
var pip = index.pipPosition;
//the position of the distal bone (the very tip of your finger)
var dip = index.dipPosition;
//and now we need the angle between each of those positions, which is where i'm stuck
}
});
So, how do I get the angle between two of those positions (carp to mcp, mcp to pip, pip to dip)? Any ideas?
Alright, I think I found a sort of working approach to detect an actual fist, and not a claw.
First off, instead of the positions of the joints, we need the distance Vectors for each Bone.
Then we calculate the Dot product between the Metacarpal and the Proximal bone, as well as the dot Product between the Proximal and the Intermediate Bone. We can ignore the Distal bone, it doesn't change the result too much.
We sum all the calculated dot products (10 in total) and calculate the average out (we divide by 10). This will give us a value between 0 and 1. A Fist is beneath 0.5 and everything above that is basically not a fist.
Additionally you might also want to check for the amount of extended fingers on a Hand and check if it is 0. This will ensure that a "Thumbs-up" and similiar 1-digit poses do not get recognized as a Fist.
Here is my implementation:
const minValue = 0.5;
var controller = Leap.loop(function(frame){
if(frame.hands.length>0)
{
var hand = frame.hands[0];
var isFist = checkFist(hand);
}
});
function getExtendedFingers(hand){
var f = 0;
for(var i=0;i<hand.fingers.length;i++){
if(hand.fingers[i].extended){
f++;
}
}
return f;
}
function checkFist(hand){
var sum = 0;
for(var i=0;i<hand.fingers.length;i++){
var finger = hand.fingers[i];
var meta = finger.bones[0].direction();
var proxi = finger.bones[1].direction();
var inter = finger.bones[2].direction();
var dMetaProxi = Leap.vec3.dot(meta,proxi);
var dProxiInter = Leap.vec3.dot(proxi,inter);
sum += dMetaProxi;
sum += dProxiInter
}
sum = sum/10;
if(sum<=minValue && getExtendedFingers(hand)==0){
return true;
}else{
return false;
}
}
While this works like it should, I doubt that this is the correct and best approach to detect a Fist. So please, if you know of a better way, post it.
Solution works perfect, any chance you could explain why you divide by 10 and why the minValue is 0.5? Thanks!
Well, it doesn't work that good, to be honest. I'll soon start to work on a little project that has the goal to improve the detection of fists with Leap Motion.
Regarding your questions, We divide the sum by 10 because we have 2 Bone Joints per finger, with 5 fingers. We want the average value from the sum of all those calculations, because not all fingers will be angled in the same way. So we want some value that encompasses all of these values into a single one: the average value. Given that we have 10 calculations in total (2 per each finger, 5 fingers), we divide the sum of those calculations and there we go. We will get a value between 0 and 1.
Regarding the minValue: Trial&Error. In a project of mine, I used a value of 0.6 instead.
This is another problem of this approach: ideally a flat hand should be a value of nearly 0, while a fist should be 1.
I know it is an old topic but if you guys still around the answer could be simpler just by using sphereRadius() ;
I found "grabStrength" is good

Calculate speed from velocity vector using box2d GetLinearVelocity();

I need to find the speed of an object in a game. The game is made in HTML5 with jquery and jquery.box2d.
For this I can use these methods:
GetLinearVelocity().x;
GetLinearVelocity().y;
I'm then trying to calculate the speed from this piece of code, but get some values that doesn't make sense when I console.log it. This is my code:
var heroVelX = game.currentHero.GetLinearVelocity().x;
var heroVelY = game.currentHero.GetLinearVelocity().y;
var speed = Math.sqrt(heroVelX^2 + heroVelY^2);
console.log(speed);
Some of the values in console.log are numbers, but most of them are NaN (Not-A-Number), which confuses me? Can someone help me solve this?
The goal I want to achieve, is to see when the speed(of object .currenHero) drop below a certain value, so I can excute a new state in the game.
Your problem is that you're using the wrong operator (Bitwise XOR) for doing square - see here.
What you need to do is:
var speed = Math.sqrt(Math.pow(heroVelX, 2) + Math.pow(heroVelY, 2));
The only time the square root function should return NaN is when the value being square rooted is negative. A way to go about testing if this is the issue would be to try squaring the values in a different line of code before square rooting them.
heroVelX = (heroVelX) * (heroVelX)
Another way to potentially shine some light on the problem would be to add log statements printing out the values of the velocities and the velocities squared before square rooting.

Three.js - How to rotate an object to lookAt one point and orient towards another

I'm new to three.js and 3d programming in general, so this may seem like a very simple question. Ideally, I hope the answer can help me understand the underlying principles.
I have an object that needs to "point" at another point (the origin, in this case, for simplicity), which can be done easily with the Object3D.lookAt(point) function. This points the Z axis of the object at the point nicely.
I also want to rotate my object, called looker, around its Z axis such that its X axis points generally towards another object, refObj. I know that the X axis can't point directly at the refObj unless that object happens form a right angle with the origin. I want the X axis of looker to lie on the plane created by origin, refObj and looker, as diagramed below:
The simplest way of doing the rotation would seem to be to modify looker.rotation.z, but I don't know how to calculate what the value should be.
In general, I would like an extended version of the lookAt function which takes a second coordinate to which the X axis would be oriented. Something like this:
function lookAtAndOrient(objectToAdjust, pointToLookAt, pointToOrientXTowards)
{
// First we look at the pointToLookAt
objectToAdjust.lookAt(pointToLookAt);
// Then we rotate the object
objectToAdjust.rotation.z = ??;
}
I have created a jsFiddle with the example diagramed above
What you are really saying is you want the y-axis of the object (the object's up-vector) to be orthogonal to the plane.
All you have to do is set the object's up-vector before you call lookAt( origin ).
You compute the desired up vector by taking a cross-product of two vectors you know lie in the plane.
three.js r.143

First person simulation with three.js using keyboard arrows

For my source, visit http://jsfiddle.net/fYtwf/
Background
I have a simple 3d simulation using three.js where the camera is surrounded in 3 dimensions by cubes. These cubes are to help visualise where the camera is looking until the view controls are coded and tested. I want to create a simple 3D application, where the camera is controlled via up, down, left and right keys. Just like moving your head
Issues
In my current application, when facing forward, and starting to look up, we are successful. However when we turn left 90 degrees, and we press the up arrow... The wrong thing happens. the camera increments the x axis, but because we're facing another direction, modifying the x axis ALONE is WRONG...
Now I'm assuming this is because some trigonometry is required to calculate the correct values for the z axis. However, my trig isn't brilliant.
Current
To get a better understanding of what i mean, please visit my jsfiddle : http://jsfiddle.net/fYtwf/
UP key ONLY increments X
DOWN key ONLY decrements X
LEFT key ONLY increments Y
RIGHT key ONLY decrements Y
Q key ONLY increments Z
W key ONLY decrements Z
( Q and W were only coded to try and help me understand. )
From my current understanding, when I press the UP key, X must increment and the Z axis must be modified based on what the current Y axis is. However I don't know the algorithm :(
So X and Z must be modified in the KEYUP code ( I think, please correct me if I am wrong )
// setRotateX, getRotateX, setRotateY and getRotateY are extended
// camera functions I wrote so I could work with degrees. Solution
// IS NOT required to use them, they just helped me
switch( key )
{
case KEYUP:
if ( camera.getRotateX() < 90 ){ // restrict so they cannot look overhead
camera.setRotateX( camera.getRotateX() + VIEW_INCREMENT );
}
break;
case KEYDOWN:
if ( camera.getRotateX() > -90 ){ // restrict so they cannot look under feet
camera.setRotateX( camera.getRotateX() - VIEW_INCREMENT );
}
break;
case KEYLEFT:
camera.setRotateY( camera.getRotateY() + VIEW_INCREMENT );
break;
case KEYRIGHT:
camera.setRotateY( camera.getRotateY() - VIEW_INCREMENT );
break;
}
There are a number of solutions to this problem, but since you only want the camera to rotate up, down, left, and right, the answer in this case is easy.
You just need to set the camera Euler order to "YXZ" like so:
camera.rotation.order = "YXZ"; // three.js r.65
If you do that, everything becomes very intuitive.
Here is an updated fiddle: http://jsfiddle.net/fYtwf/3/ (this demo is using r.54, however)
Once you change camera.rotation.z from it's default value of zero, things will become very confusing. So don't do that. :-)
three.js r.65
While this does not directly fix your code, I thought I'd mention that Three.js provides two ready-made controllers to navigate in FPS mode. They both use mouse for looking and can move, but should be rather simple to adapt to keyboard look and remove movement if needed. They are:
FirstPersonControls
PointerLockControls
I'd recommend the latter as a starting point because it's rather simple and the former confusingly has the looking code twice, probably as an artifact from old features.

Categories