Three js Obj loader Rotation - javascript

Ive made a stick in the Three js editor, after loading it with the following code i can position it but not rotate it.
Its a stick made of 4 meshes, so i probably have to make a rotation point but i cant figure out how i get that to work.
The ideal situation :
x -------
The x represents the point where i want to rotate the dashes(stick) around
can anyone help me?
thx in advance
var loader = new THREE.ObjectLoader();
loader.load("scene.json", function ( obj )
{
stick =obj;
scene.add( stick );
stick.position.z = -9;
stick.position.y = .4;
stick.children[3].rotation.x(45);
});

If I understand aright, you have an object with 4 children that are meshes.
Object3D
-Mesh
-Mesh
-Mesh
-Mesh
First, I would translate all the children, and then rotate the parent object.
for(var i=0; i<stick.children.length; i++) {
stick.children[i].position.set(0, 0.4, -9); // or another offset
}
stick.rotateX( 45 * Math.PI / 180 ); // make sure to use Radians

Related

(Three.JS) Transform controls for translation (Size Issue)

I am working on customizing the transform controls available in three.js for my project.
I have already changed the rotation part and now working on translation part.
if you notice in translation Gizmo, there is a XYZ octahedron in the center. I have removed all other planes and arrows and wrote all functionality only on that center mesh, which is working fine.
Now I am only stuck at one small problem, that is the size and position of that controller. I changed that Octahedron to boxGeometry and writing the code to make the size of that controller to be exact size of the selected object. for that I get the idea to make the size of the controller, same as the boxHelper size, which act as outline of object.
when I tried this logic in sample code, where I created a box, and getting the size of box helper and creating another box of same size, it was working fine. but when I am writing same code in threejs transform controls, result is not the same.
below is the geometry code init
XYZ: [[ new THREE.Mesh( new THREE.BoxGeometry( 0.1, 0.1, 0.1 ), pickerMaterial )]],
then I am getting the size of box3 when attaching to any object
this.addBoxHelper = function () {
this.removeBoxHelper();
if(this.object.box3) {
**this.object.box3.getSize(selectionBoxSize);**
console.log(selectionBoxSize)
this.objectBoxHelper = new THREE.Box3Helper(this.object.box3, 0xffff00);
this.objectBoxHelper.canSelect = function () {
return false;
}
this.object.add(this.objectBoxHelper);
}
}
then below is my update function of transform controls
this.update = function () {
if ( scope.object === undefined ) return;
scope.object.updateMatrixWorld();
worldPosition.setFromMatrixPosition( scope.object.matrixWorld );
worldRotation.setFromRotationMatrix( tempMatrix.extractRotation( scope.object.matrixWorld ) );
scope.object.box3.getSize(selectionBoxSize);
scope.object.getWorldPosition(selectionBoxPos);
camera.updateMatrixWorld();
camPosition.setFromMatrixPosition( camera.matrixWorld );
camRotation.setFromRotationMatrix( tempMatrix.extractRotation( camera.matrixWorld ) );
**scaleT = selectionBoxSize;**
//below three lines are for dynamic size change based on camera position..for
//next level functionality
//scaleT.x = worldPosition.distanceTo( camPosition ) / 6 * selectionBoxSize.x;
//scaleT.y = worldPosition.distanceTo( camPosition ) / 6 * selectionBoxSize.y;
//scaleT.z = worldPosition.distanceTo( camPosition ) / 6 * selectionBoxSize.z;
this.position.copy( selectionBoxPos );
this.scale.set( scaleT.x, scaleT.y, scaleT.z);
this.updateMatrixWorld();
below is the output of console log
TransformControls.js:526 Vector3 {x: 10.020332336425781, y: 2.621583938598633, z: 3.503500819206238}
TransformControls.js:601 Vector3 {x: 10.020332336425781, y: 2.621583938598633, z: 3.503500819206238}
as you can see, the scale is the same, but the result is different. see the result in below images.
as you see in images, that red color box at bottom is translation controller but smaller than selection box.
another issue is that pivot of my objects are at bottom, and I want this controller to come at the center of the selection box, that is also not happening with getCenter method of box3.
Please help!! let me know if I am unclear in explaining the issue
If you are getting the bounding box of the object from its geometry, that will be wrong because it doesn't take the objects transform into account. You have to use box3.setFromObject (yourObject) instead. does that help?

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.

THREE.js - Rotate the camera just like trackball controls

I'm using Trackball controls in a scene and I want to implement a function to rotate the camera just like the way dragging the mouse in the canvas does it. How can I accomplish something like that? I've been looking the code of the Trackball control module, but I can't find something to start.
EDIT: I've been looking several pages, the THREE documentation and whatnot, but still can't reproduce the Trackball style rotation. I've been using quaternions too but they can't reproduce the behavior(or I'm missing something, most probably). Any help?
EDIT 2 : What I'm looking for is a way to do something like this:
function rotateCam(angle) { // code }
var angle = 0.01; //some value
rotateCam(angle);
$('#button').addEventListener('mousedown', function() { rotateCam(angle); } );
Where button is an HTML element representing a button.
I noticed that the Trackball controls, apart of rotate via quaternion, do a zoom to correct some distances. I tried to read the code, and got this:
function rotate(L) {
var vector = controls.target.clone();
var l = (new THREE.Vector3()).subVectors(camera.position, vector).length();
var up = camera.up.clone();
var quaternion = new THREE.Quaternion();
// Zoom correction
camera.translateZ(L - l);
quaternion.setFromAxisAngle(up, 0.015);
camera.position.applyQuaternion(quaternion);
camera.lookAt(vector);
renderer.render(scene, camera);
}
Works like a charm...hope someone find this useful too. ;)
function cameraRotate(distance, angle){
camera.position.x = distance * Math.cos( angle );
camera.position.z = distance * Math.sin( angle );
}
This would rotate your camera at the specified distance and angle around the scene. If you want a smooth rotation you could call this with a small angle increase from the animate-loop, depending on input for example.
I'm on the right way I think...I did this:
function rotate() {
if (this.showCase) {
var vector = controls.target.clone(); // controls is a TrackballControls
var up = camera.up.clone();
var quaternion = new THREE.Quaternion();
quaternion.setFromAxisAngle(up, 0.015);
camera.position.applyQuaternion(quaternion);
camera.lookAt(vector);
renderer.render(this.scene, this.camera);
}
},
Still, it doesn't look right right like the TrackballControls rotation.

THREE.js - moving object relative to screen with rotated/scaled parent(s)

In THREE.js, I'm trying to move objects around on screen based on mouse position. After looking at some examples, it seemed pretty strait forward. Here's some code I borrowed from one of the examples that's mostly working for what I need:
function mouseMove(e){
mouse2D.x = ( (e.pageX-canvas.offsetParent.offsetLeft) / canvas.clientWidth ) * 2 - 1;
mouse2D.y = - ( (e.pageY-canvas.offsetParent.offsetTop) / canvas.clientHeight ) * 2 + 1;
if (selected) {
var ray = projector.pickingRay(mouse2D, PGL._camera).ray;
var targetPos = ray.direction.clone().addSelf(ray.origin);
targetPos.subSelf(_offset);
obj.position.x = initPos.x + targetPos.x;
obj.position.y = initPos.y + targetPos.y;
}
}
This works fine for moving immediate children within the scene. The problem is trying to move an object that has parent(s) that are rotated and/or scaled. How would you deal with that? Apply the objects matrixRotationWorld to the movement maybe?
I'm still trying to wrap my head around this stuff. Any help appreciated.
See these examples, they can help you :
http://mrdoob.github.com/three.js/examples/misc_controls_fly.html
or
http://mrdoob.github.com/three.js/examples/webgl_interactive_voxelpainter.html

Categories

Resources