sleepyraccoon / jsc3d

Automatically exported from code.google.com/p/jsc3d
0 stars 0 forks source link

Pointers on rotating model not scene? #73

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Hi,

I wonder if you could give me any pointers on using the math and matrix 
functions to rotate the model interactively rather than the scene? I have 
everything in place but need some help on making sure that (for example) the 
controls to rotate the model around its Z axis will always rotate it around ITS 
x axis no matter what it's orientation (since only rotation of the scene is 
exposed).

I'm new to 3D and would really appreciate any suggestions,

thanks!

Original issue reported on code.google.com by crawford...@gmail.com on 9 May 2014 at 12:47

GoogleCodeExporter commented 9 years ago
* ITS Z axis

Original comment by crawford...@gmail.com on 9 May 2014 at 3:25

GoogleCodeExporter commented 9 years ago
Jsc3d does not support interactive rotation of parts of the scene directly. If 
you want to implement it programmingly ... well, it can be done in a tricky and 
inefficient way for the lack of a scenegraph. The idea is like this:

1. Find the mesh that is to be rotated.

2. Constructing a matrix object (instance of JSC3D.Matrix3x4 
http://jsc3d.googlecode.com/svn/trunk/jsc3d/docs/symbols/JSC3D.Matrix3x4.html) 
and generate the rotation matrix around Z axis as this:

  var rotMat = new JSC3D.Matrix3x4;
  rotMat.rotateAboutZAxis(angleInDegrees);

3. Since Jsc3d does not use scenegraph, nor does each mesh has its attached 
matrix, you should bake the rotation directly into the vertices of the target 
mesh:

  JSC3D.Math3D.transformVectors(rotMat, targetMesh.vertexBuffer, targetMesh.vertexBuffer);

Likewise, the mesh's face normals and vertex normals also need to be altered in 
the same way to ensure correct culling and lighting:

  JSC3D.Math3D.transformVectors(rotMat, targetMesh.vertexNormalBuffer, targetMesh.vertexNormalBuffer);
  JSC3D.Math3D.transformVectors(rotMat, targetMesh.faceNormalBuffer, targetMesh.faceNormalBuffer);

4. Finally, the viewer.update() method should be invoked to render a new frame 
with all the changes.

That's it.

Original comment by Humu2...@gmail.com on 10 May 2014 at 8:16

GoogleCodeExporter commented 9 years ago
Thanks for the reply! I actually only have one object, so rotating the scene is 
fine - my problem is not understanding how to rotate the scene x,y,z such that 
the rotation is always relative to the object's axes.

From what you say, it sounds like I should maintain my own rotation matrix for 
the object, apply my rotations to it, then is there a way to turn the matrix 
into scene x,y,z rotation? or should I write my own method to apply my object 
rotation matrix to the scene maybe?

Original comment by crawford...@gmail.com on 10 May 2014 at 9:35

GoogleCodeExporter commented 9 years ago
Yes of course. You should maintain a matrix for each mesh that is to be rotated 
individually. It should not be a difficulty since JavaScript is a smart 
language. Just add the additional matrix to its corresponding mesh object and 
it will be ok.

I see what you mean. The private rotations should be applied before the default 
viewing transformation is taken. The right way is overriding the viewer's 
beforeupdate 
(http://jsc3d.googlecode.com/svn/trunk/jsc3d/docs/symbols/JSC3D.Viewer.html#befo
reupdate) callback handler to do this, as the following: 

  viewer.beforeupdate = function() {
    // perform all the additional rotations here
    ...
  };

This will be invoked automatically before the meshes are about to be sent to 
the render pipeline for each frame.

Original comment by Humu2...@gmail.com on 10 May 2014 at 4:13

GoogleCodeExporter commented 9 years ago
HI, thanks - I got this working, with rotation matrices being applied to the 
mesh on each change, but I'm kind of back where I started, so maybe I'm asking 
the wrong question... : / I'm now rotating the model in X and Y using the arrow 
keys (just to test the principal). This is what I'm going to want to do 
(control rotation in 2 axes).

My problem is still how to make sure rotations are done with respect to the 
object - for example, if I rotate the object by 90 degrees around the x axis, a 
rotation in z (WRT the object) would now equate to a rotation in Y WRT to the 
scene... Does that make sense?

So how can I implement that generally so the control keys always rotate the 
object on it's own axes??

I tried applying a negative rotation of the current accumulated rotation in Y, 
followed by the required change in X then re-applying the accumulated Y. This 
worked for 1 axis, but when I tried the same technique on the other it didn't.

Sorry I appreciate my problem here is really with 3D geometry but i'd 
appreciate any tips... so close to making this work and it'll be a really cool 
application...

thanks!

Original comment by crawford...@gmail.com on 12 May 2014 at 10:49

GoogleCodeExporter commented 9 years ago
A mesh's own space is the same with that of the whole scene at the initial 
stage (since obj files do not define transform hierarchy, neither does Jsc3d). 
When you attach a matrix to that mesh and make additional rotations for it, the 
matrix itself defines a space for the mesh.

As for what you'd like to implement, Euler angle rotation is not the right tool 
for this, for it depends on application order of the rotations. Instead, you'll 
need more powerful quaternion rotation 
(http://en.wikipedia.org/wiki/Quaternion#Three-dimensional_and_four-dimensional_
rotation_groups) fot your purpose. 

The basic idea may be like this: use a quaternion for each mesh that has its 
own additional rotation. When rotating, calculate the rotation using the 
quaternion method 
(http://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation) and then 
convert it to Euler angles and matrix and apply the transformation as what you 
have done.

The bad news is Jsc3d does not provide any utility for quaternions. You will 
have to implement it for your own.

Original comment by Humu2...@gmail.com on 13 May 2014 at 11:24