THREE.js weird rotation about X - javascript

So here's the full code in jsFiddle:
http://jsfiddle.net/73v15kb6/1/
Rotating about Y and Z is as I would expect it to be, same thing with all the transitions.
When I try to rotate about X axis, it looks like THREE.js is doing something special to make it look "more cool" - but that's not what I want to achieve.
Reading similar topics I'm sure it's something to do with my rotateX function:
camera.position.y = y * cos - z * sin;
camera.position.z = y * sin + z * cos;
camera.lookAt(scene.position);
When I initiate the 3d world I set the camera's coordinates with the following values, just to keep the desired view:
camera.position.x = -60;
camera.position.y = 30;
camera.position.z = 0;
Has anyone got a clue what I'm doing wrong? Thanks a lot!

I'm new to THREE.js, (In fact, this is my first time working with it), so I might not explain it properly :(
The part THREE.js did to make it look "more cool" was the camera.lookAt method.
camera.lookAt(sphere.position);
Here is the sample (modified) http://jsfiddle.net/73v15kb6/3/
Try to play around with the animate function for each axis and try with the lookAt option enabled. Playing with it for some time will give you the concept. :)
function animate() {
requestAnimationFrame(animate);
rotateX(5); // Try with Y & Z; (also with toggling lookAt())
}
The lookAt function may make the transformation functions seem weird since even if the camera transform as expected, the rendering area will still be the same.

Thanks Sen Jacob for fixing my fiddle!
I found a solution, so to have this working as I wanted - that camera always looks at the center point (0,0,0) and all the rotations of the word happens around the axis, I had to do the following for each rotation:
for rotZ and rotY
camera.up = new THREE.Vector3(0,1,0);
camera.lookAt(new THREE.Vector3(0,0,0));
for rotX:
camera.up = new THREE.Vector3(1,0,0);
camera.lookAt(new THREE.Vector3(0,0,0));
Notice the difference in up vector between X and Y&Z.

Related

How do you get a THREE.Line to render in the right order?

I'm working on a model solar system and I am using THREE.Line to make my orbits. They look fine until you go in front of a planet and you realize that they are all being rendered behind the Meshes. I've tried playing around with render order and depthwrite but they just make it so that the line is either entirely in front of or entirely behind the planet. I feel like this should be an extremely easy thing to do.
The effect, if you'd even consider it an effect is like this:
what i'm looking for, you can see one orbit that fully wraps around that planet.
this is what my problem looks like:[what i have][2].
Here is the function that makes my orbits:
function MakeOrbit_2(base, color) {
function semiminor(a, e) {
return a * Math.sqrt(1 - (e * e));
}
var curve = new THREE.EllipseCurve(
foci(1000 * base[9], semiminor(1000 * base[9], base[0])), 0, // where the middle is
1000 * base[9], semiminor(1000 * base[9], base[0]), // xRadius, yRadius
0, 2 * Math.PI, // aStartAngle, aEndAngle
false, // aClockwise
0 // aRotation
);
var material = color;
var geometry = new THREE.BufferGeometry().setFromPoints(curve.getPoints(points))
var orbit = new THREE.Line(geometry, material);
orbit.rotateX(- Math.PI / 2);
orbit.rotateZ(DegToRad(base[3]));//ascn
orbit.rotateX(DegToRad(base[2]));//inc
orbit.rotateZ(Math.PI + DegToRad(base[4]));//aop
scene.add(orbit);
return orbit;
}
I have renderer.sortObjects = false; so my transparent atmospheres and clouds render properly.
It is also worth noting that my less opaque lines behave differently than the fully opaque ones.
Update: turns out this weird effect was due to rounding errors, the scale was on billions of units and the difference in position were too minuscule to bother the z-buffer.
I found a working example by Sander Blue along with his GitHub source code. I was unaware of 3D Javascript until I saw this post, amazing! Also your name... my mom's family name is Logan and my dad's is Brotherston... how about that? I don't have a direct answer to your question but I hope that these links help. It appears to be a working example of just what you were asking about... showing orbits in front of a planet as you rotate the view.

Sphere rotation in Babylon.js

I want to ask for help regarding rotation using the Babylon.js framework.
I need the sphere to rotate 45 degrees, exactly aligned with the diagonal circle, which has a 45 degree orientation, but I'm not getting it.
The code I made is in the link below:
https://codepen.io/polalas/pen/VwvaKwL
The method responsible for the rotation is the loop () method, which is triggered every time the scene is rendered.
function loop () {
var y1 = scene.getMeshByName("I1");
y1.rotation.y - = 0.01 * Math.sin (Math.PI / 4);
y1.rotation.x - = 0.01 * Math.sin (Math.PI / 4);
}
I imagine that I mishandled the rotation. Could someone help, please?
Using your code, the best way to achieve that is to first rotate the parent of the sphere (what you called newMesh (or I1)) 45 degrees around the Z axis right before adding the sphere as a child:
newMesh.rotate(BABYLON.Axis.Z, Math.PI / 4);
Afterwards you can rotate it around its Local (!) X axis in your render loop:
function loop(){
var y1 = scene.getMeshByName("I1");
}
This way you get a perfect rotation around your (mocked) pivot.

VertexNormals calculation on Three.js

I'm not sure if this is an error or not, but once you call geometry.computeVertexNormals() in a THREE.BoxGeometry, and you calculate the vertex normals, I think the resulting vectors are wrong.
Take this as an example:
geometry = new THREE.BoxGeometry(50, 50, 50);
geometry.computeVertexNormals();
material = new THREE.MeshNormalMaterial();
as you see everything looks done properly, however if you rotate the X axis you see that the vectors are pointing in different directions.
mesh.rotation.x = 90 * Math.PI / 180;
Shouldn't we expect the vector to point exactly from the center of the 3 existing vectors before the geometry merge? Something like this:
If not, any explanation on why this happens?
Thanks in advance.
computeVertexNormals computes the average of the face normals of the faces connected to each vertex. For the box mesh, not all the vertices are connected to the same number of faces, so you have a different normal average. Drawing the wireframe makes this easier to see.

Three.js - How to get camera position with respect to origin

The title of this question might a bit ambiguous, but I don't know how to phrase it in a line.
Basically I've got this situation: there is a perspective camera in the scene and a mesh. The mesh is NOT centered at the origin of the axis.
The camera points directly to the center of this object, and it's position (I mean literally the "position" property of the Three.js camera object) is the position with respect to the center of the object, not the origin; so it works in another coordinate system.
My question is: how can I get the position of the camera not with respect of the object center but with respect of the origin of the "global" coordinate system?
To clarify, the situation is this. In this image you can see a hand mesh that has a position far away from the origin of the coordinate system. The camera points directly to the center of the hand (so the origin from the point of view of the camera is the center of the hand), and if I print it's position it gives me these values:
x: -53.46980763626004; y: -2.7201492246619283; z: -9.814480359970839
while actually I want the position with respect to the origin of the coordinate stystem (so in this case the values would be different; for example, the y value would be positive).
UPDATE:
I tried #leota's suggestion, so I used the localToWorld method in this way:
var camera = scene.getCamera();
var viewPos = camera.position;
var newView = new THREE.Vector3();
newView.copy(viewPos);
camera.localToWorld(newView);
I did an experiment with this mesh. As you can see this mesh is also not centered on the origin (you can see the axes on the bottom-left corner).
If I print the normal value of the camera's position (so, with respect to the center of the mesh) it gives me these results:
x: 0; y: 0; z: 15
If now I print the resulting values after the code above, the result is:
x: 0; y: 0; z: 30
which is wrong, because as you can see the camera position in the image has x and y values clearly different than 0 (while z = 30 could be true, as far as I can see).
If for example I rotate the camera so that it's very close to the origin, like this (in the image the camera is just behind the origin, so its position in world coordinates should have negative values for x, y, z), the coordinates with respect of the center of the object are:
x: -4.674180744175711; y: -4.8370441591630255; z: -4.877951155147168
while after the code above they become:
x: 3.6176076166961373; y: -4.98753160894295; z: -4.365141278155379
The y and z values might even be accurate at a glance, but the positive value of x tells me that it's totally wrong, and I don't know why.
I'm going to continue looking for a solution, but this might be a step in the right direction. Still, any more suggestions are appreciated!
UPDATE 2:
Found the solution. What #leota said is correct, that is indeed how you would get absolute coordinates for the camera. In my case though, I finally found a single line of code hidden in the project's code that was scaling everything according to some rule (project related). So the solution for me was to take the camera position as it is and then scale it back according to that rule.
Since #leota's answer was indeed the solution to the original question, I'm accepting it as the correct anwser
Not sure I got your question :) if I did then you need to switch between World and Local coordinate systems. The THREE.PerspectiveCamera inherits from THREE.Object3D so you can use the following methods to set your coordinate system:
.localToWorld ( vector )
vector - A local vector.
Updates the vector from local space to world space.
.worldToLocal ( vector )
vector - A world vector.
Updates the vector from world space to local space.
From Three.js Documentation
Update:
First update your camera Matrix:
camera.updateMatrixWorld();
Then:
var vector = camera.position.clone();
vector.applyMatrix( camera.matrixWorld );
The vector should hold the position in world coordinate
I had same question trying to answer I was confused for a while my guess but not sure is
var plot = camera.position.x - mesh.position.x;
var plotb = camera.position.y - mesh.position.y;
var plotc = camera.position.z - mesh.position.z;
mesh.position.x = (camera.position.x + plot) - mesh.position.x;
mesh.position.y = (camera.position.y + plotb) - mesh.position.y;
mesh.position.z = (camera.position.z + plotc) - mesh.position.z;
or
var plot = (camera.position.x * mesh.position.x) / 1000;
var plotb = (camera.position.y * mesh.position.y) / 1000;
var plotc = (camera.position.z * mesh.position.z) / 1000;
mesh.position.x = mesh.position.x + plot;
mesh.position.y = mesh.position.y + plotb;
mesh.position.z = mesh.position.z + plotc;

Three.js: Camera flying around sphere?

In Three.js (which uses JavaScript/ WebGL), how would one create a camera which flies around a sphere at fixed height, fixed forward speed, and fixed orientation in relation to the sphere, with the user only being able to steer left and right?
Imagine an airplane on an invisible string to the center of a globe, flying near ground and always seeing part of the sphere:
(I currently have code which rotates the sphere so to the camera it looks like it's flying -- left and right steering not implemented yet -- but I figure before I go further it might be cleaner to move the camera/ airplane, not the sphere group.)
Thanks!
You mean like in my Ludum Dare 23 game? I found this to be a bit more complicated than I expected. It's not difficult, though.
Here I'm assuming that you know the latitude and longitude of the camera and its distance from the center of the sphere (called radius), and want to create a transformation matrix for the camera.
Create the following objects only once to avoid creating new objects in the game loop:
var rotationY = new Matrix4();
var rotationX = new Matrix4();
var translation = new Matrix4();
var matrix = new Matrix4();
Then every time the camera moves, create the matrix as follows:
rotationY.setRotationY(longitude);
rotationX.setRotationX(-latitude);
translation.setTranslation(0, 0, radius);
matrix.multiply(rotationY, rotationX).multiplySelf(translation);
After this just set the camera matrix (assuming camera is your camera object):
// Clear the camera matrix.
// Strangely, Object3D doesn't have a way to just SET the matrix(?)
camera.matrix.identity();
camera.applyMatrix(matrix);
Thanks for Martin's answer! I've now got it running fine in another approach as follows (Martin's approach may be perfect too; also many thanks to Lmg!):
Set the camera to be a straight line atop the sphere in the beginning (i.e. a high y value, a bit beyond the radius, which was 200 in my case); make it look a bit lower:
camera.position.set(0, 210, 0);
camera.lookAt( new THREE.Vector3(0, 190, -50) );
Create an empty group (an Object3D) and put the camera in:
camGroup = new THREE.Object3D();
camGroup.add(camera);
scene.add(camGroup);
Track the mouse position in percent in relation to the screen half:
var halfWidth = window.innerWidth / 2, halfHeight = window.innerHeight / 2;
app.mouseX = event.pageX - halfWidth;
app.mouseY = event.pageY - halfHeight;
app.mouseXPercent = Math.ceil( (app.mouseX / halfWidth) * 100 );
app.mouseYPercent = Math.ceil( (app.mouseY / halfHeight) * 100 );
In the animation loop, apply this percent to a rotation, while automoving forward:
camGroup.matrix.rotateY(-app.mouseXPercent * .00025);
camGroup.matrix.rotateX(-.0025);
camGroup.rotation.getRotationFromMatrix(camGroup.matrix);
requestAnimationFrame(animate);
renderer.render(scene, camera);

Categories