Get distance of two objects from camera three js - javascript

I have two squares in space which are something like front and back wall of cube one vith vertices
x=-2 y=-1138 z=-2;
x=-2 y=-1134 z=-2;
x=2 y=-1138 z=-2;
x=2 y=-1134 z=-2
second
x=-2 y=1134 z=2;
x=-2 y=1138 z=2;
x=2 y=1134 z=2;
x=2 y=1138 z=2
when I calculate distanceTo from camera like this
var point1 = this.camera.matrixWorld.getPosition().clone();
var point2 = this.mesh.cubePlane3.children[0].matrixWorld.getPosition().clone();
var distance = point1.distanceTo( point2 );
I have always the same distance for both 20,09. These squres are rotated in space, so only rotation is changed and I would need somehow find out which wall is closer to camera to be able to do something that in cube 3 walls closer to camera are not displayed and next 3 walls are displayed.
And obviously I do not understand math behind this, for example why walls which are next to each other one have positive coordinates for y and next negative + why distance is the same value, when one is closer on z axis than second. Can you pls someone help me how I can get closer walls? Thank you

Each geometry has a computeBoundingBox function. So you can do:
var bbox = geometry.computeBoundingBox();
for each geometry that you are interested in and then use the
bbox.center()
to get the center of your geometry. A much faster computation is to use the computeBoundingSphere on your geometry.
Then you just compare the relation of the centers to your camera position.

I used computeBoundingBox with this code
this.mesh[cubePlane[0]].children[0].geometry.computeBoundingBox();
var position = new THREE.Vector3();
position.sub( this.mesh[cubePlane[0]].children[0].geometry.boundingBox.max, this.mesh[cubePlane[0]].children[0].geometry.boundingBox.min );
position.multiplyScalar( 0.5 );
position.addSelf(this.mesh[cubePlane[0]].children[0].geometry.boundingBox.min );
this.mesh[cubePlane[0]].children[0].matrixWorld.multiplyVector3( position );
var point1 = this.camera.matrixWorld.getPosition().clone();
var point2 = position;
var distance = point1.distanceTo( point2 );
and it works so thank you for your advice :)

Related

Object shrinks when rotated javascript

I have been developing a basic game engine just to learn the process and I have hit a issue with my rotation function.
It works fine except that the object shrinks and appears to invert.
Here is a jsfiddle that illustrates my point.
I think the problem would be in the rotation code its self but i'm not positive.
function Rotation(vec, rot){
if(Math.acos((vec.x + vec.y + vec.z -1)/2) === 0) { return vec; }
var qVec = new Quaternion(vec.x, vec.y, vec.z, 0);
qVec = Quaternions.multiply(qVec, rot);
qVec = Quaternions.multiply(qVec, rot.conjugate());
return new Vector3(qVec.x, qVec.y, qVec.z);
}
Couple things:
First, the rotation quaternion is not normalized, so it's inverse is not the same as its conjugate. Rotation by a quaternion is defined by:
Where q is the vector you're rotating around, p is the vector you're rotating, and p' is the final rotated vector.
So this is defined using the inverse of q, which is defined as conjugate(q) / magnitude(q)^2. In the case where q is normalized, magnitude(q)^2 == 1, so it's the same as just multiplying by the conjugate.
Also note the order of operations here. Quat multiplications are non-commutative so their order matters.
You can fix this by normalizing your rotation quaternion, and fixing the order of operations:
var qVec = new Quaternion(vec.x, vec.y, vec.z, 0);
qVec = Quaternions.multiply(rot.normalize(), qVec);
qVec = Quaternions.multiply(qVec, rot.conjugate());
return new Vector3(qVec.x, qVec.y, qVec.z);
Second, you want to define your rotation quat as normal to the plane you want to rotate around. In this case, you want to rotate around the x-y plane. The z-axis is normal to this plane, so we want to define the rotation vector along the z-axis:
function update(){
for(var i = 0; i < gameObjects.length; i++){
gameObjects[i].rotation = euler(new Vector3(0, 0, frames/100));
}
}
With these changes, I was able to get the box rotating correctly.
(In terms of why it was scaling up/down, I'm not 100% sure. Still trying to figure that out.)

Get position in parent mesh

I have this sort of meshes (each is the child of above)
Scene
-scene.add(SpaceMesh)
-SpaceMesh.add(ShipMesh)
SpaceMesh is moving in scene.
ShipMesh is not moving.
if i request ShipMesh.position.x it returns 0 (logically)
How can i get coordinates of my ShipMesh in SpaceMesh?
--
Example:
SpaceMesh.position.x = 100
ShipMesh.position.x = 0
Logical result will have to be ShipMesh.PositionInSpaceMesh.x = -100
I don't know if is the best way, but from:
how to: get the global/world position of a child object
spaceMesh.updateMatrixWorld();
var vector = new THREE.Vector3();
vector.setFromMatrixPosition( spaceMesh.matrixWorld );
vector.multiplyScalar( -1 );
console.log(vector); // my coords in SpaceMesh
If is there better solution, or some "best practices", please correct me, thank you.

Trying to workout how to use quaternions to rotate a camera that is moving along a path to look in new direction vector

I am trying to rotate the camera smoothly and without altering the y-vector of the camera direction, i can use look at, and it changes the camera direction in a flash, but this is not working for me, I would like a smooth transition as the direction of the camera changes. I have been reading up, and not understanding everything, but it seems to me that quaternions are the solution to this problem.
I have this.object (my camera) moving along a set path (this.spline.points). The location of the camera at any one time is (thisx,thisy, thisz)
I have cc[i] the direction vector for the direction I would like the camera to face (formerly I was using lookat(cc[i]) which changes the direction correctly, but too quickly/instantaneously)
Using info I have read, I have tried this below, and it just resulted in the screen going black at the point when the camera is due to move.
Could anyone please explain if I am on the right track, how to correct my code.
Thanks
var thisx = this.object.matrixWorld.getPosition().x.toPrecision(3);
var thisy = this.object.matrixWorld.getPosition().y.toPrecision(3);
var thisz = this.object.matrixWorld.getPosition().z.toPrecision(3);
var i = 0;
do {
var pathx = this.spline.points[i].x.toPrecision(3);
var pathz = this.spline.points[i].z.toPrecision(3);
if (thisx == pathx && thisz == pathz){
this.object.useQuaternion = true;
this.object.quaternion = new THREE.Quaternion(thisx, thisy, thisz, 1);
var newvect;
newvect.useQuaternion = true;
newvect.quaternion = new THREE.Quaternion(thisx+cc[i].x, thisy+cc[i].y, thisz+cc[i].z, 1);
var newQuaternion = new THREE.Quaternion();
THREE.Quaternion.slerp(this.object.quaternion, newvect.quaternion, newQuaternion, 0.5);
this.object.quaternion = newQuaternion;
//this.object.lookAt( cc[i]);
i = cc.length;
} else i++;
} while(i < cc.length);
There is no need to call this.object.useQuaternion = true. That is default behavior.
Also, this.object.quaternion contains the current rotation, so no need to generate that either.
You might want to try a different approach - construct the rotation matrix from the spline position, lookAt and up vectors, creating a path of quaternions as a preprocessing step:
var eye = this.spline.points[i].clone().normalize();
var center = cc[i].normalize();
var up = this.object.up.normalize();
var rotMatrix = new THREE.Matrix4().lookAt(eye, center, up);
You could then create the quaternions from the rotation matrix:
var quaternionAtSplineCoordinates = [];
quaternionAtSplineCoordinates.push(new THREE.Quaternion().setFromRotationMatrix(rotMatrix));
Once you have that path, you could apply the quaternion to the camera in your animation loop - provided you have a large enough number of samples. Otherwise, you could consider using slerp to generate the intermediate points.

Three JS - BoundingBox not being updated after performing rotations

I need to find out the bounding box of a geometry after applying rotations on it.
Code to rotate - taken from sample editor of Three JS
object.rotation.x = xRadians;
object.rotation.y = yRdians;
object.rotation.z = zRadians
This rotates the object just fine.
Now I need to get the updated bounding box
Code to get the bounding Box
var minX = parseFloat(object.boundingBox.min.x);
var minY = parseFloat(object.boundingBox.min.y);
var minZ = parseFloat(object.boundingBox.min.z);
I keep getting the same values in minX-Z no matter what the rotation is. What is the right way of getting the updated bounding box?
I am using r-66.
I also tried using:
var radians = x * Math.PI / 180;
var axisX = new THREE.Vector3(1, 0, 0);
var matrix = new THREE.Matrix4().makeRotationAxis(axisX, radians);
geometry.applyMatrix(matrix);
This method performs the relative rotation and also updates the bounding box correctly but I do not want relative rotation. The first approach is what I am looking for but that does not update the bounding box of the object.
Any ideas?
Thanks!
Box3.setFromObject( object ) computes the world-axis-aligned bounding box of an object (including its children), accounting for both the object's, and childrens', world transforms.
var box = new THREE.Box3().setFromObject( object );
three.js r.66
var box = new THREE.Box3().setFromObject( object );
will return the world coordinates, so you need to subtract them from it:
var bbox = new THREE.Box3().setFromObject(object);
bbox.min.sub(object.position);
bbox.max.sub(object.position);
This will give you the correct bounding box relative to the object.

Get distance in pixels between 2 LonLat objects in OpenLayers

I have 2 OpenLayers.LonLat objects, and I want to determine the distance in pixels for the current zoom between the 2. I'm using OpenLayers.Layer.getViewPortPxFromLonLat() to determine the x and y of the points and then subtract to see the difference between the 2, but the values that I get are very small for points that are 2000km apart.
Here is my code:
var center_lonlat = new OpenLayers.LonLat(geometry.lon, geometry.lat);
var center_px = layer.getViewPortPxFromLonLat(center_lonlat);
var radius_m = parseFloat(feature.attributes["radius"]);
var radius_lonlat = OpenLayers.Util.destinationVincenty(center_lonlat, 0, radius_m);
var radius_px = layer.getViewPortPxFromLonLat(radius_lonlat);
var radius = radius_px.y - center_px.y;
I'm trying here to draw a circle, giving that I receive a center point and a radius in meters. The LonLat object seems to be ok.
Am I doing something wrong ?
I found the issue: destinationVincenty() need and returns coordinates in wgs84 where my map was using spherical mercator projection.
I hope I got correctly the answer, because projections make me dizzy and never really understood them :(. I was looking in the console to the numbers for my coordinates and the coordinates from the map.getExtent() that is used to calculate the getViewPortPxFromLonLat() and I realised they are not in the right order of magnitude, and then it hit me.
So, the code is now:
var spherical_mercator = new OpenLayers.Projection("EPSG:900913");
var wgs84 = new OpenLayers.Projection("EPSG:4326");
var map = feature.layer.map;
var geometry = feature.geometry;
var center_lonlat = new OpenLayers.LonLat(geometry.y, geometry.x);
var center_px = map.getViewPortPxFromLonLat(center_lonlat);
var radius_m = parseFloat(feature.attributes["radius"]);
var radius_lonlat = OpenLayers.Util.destinationVincenty(center_lonlat.clone().transform(spherical_mercator, wgs84), 0, radius_m).transform(wgs84, spherical_mercator);
var radius_px = map.getViewPortPxFromLonLat(radius_lonlat);
var radius = Math.abs(radius_px.y - center_px.y);
Measured the circles with the OpenLayers.Control.ScaleLine, and the size is dead on :D
You seem to be doing right. If the distance you get is too small, maybe there is a problem with OpenLayers.Util.destinationVincenty function? Have you tried to replace the bearing (0) with anything else - its value seem to be not important in your case. But frankly speaking, I wasn't able to understand how it works while browsing the source

Categories

Resources