using eular positions or Quaternions to rotate about a given position (help)

before I start:
if this topic is in the wrong section, please move it, and notify me. :slight_smile:

anyways…
I want to replace the animation system with eular coords due to the ease of calculation.

the matrix system just relies on way too much multiplication and addition,
and I believe 3/4 of the processing can be removed.

but I have no idea what I’m doing as I’m a noob and have just recently learned matrix manipulation.

in this system, a set of coords defines the Location, Rotation, and Scale transformations
as well as the point of transformation in 3D space.
the transformations are local to that point rather than (0.0,0.0,0.0) or global/world

how would I apply these transformations to a slew of untransformed verts?? (not in T-Pose)
(the position is untransformed from the T-Pose, much like what gets stored in the animation buffer)

I don’t want to build a matrix, I want to do something like this:
Vx, Vy, Vz = Vx+(LxW), Vy+(LyW), Vz+(Lz*W) #relocate the vert to the new Location (affected by the weight)

thanx :slight_smile:

What you are trying to do is probably going to create a a bunch of equations that will be significantly more difficult to work with than learning the well-understood linear algebra (matrix math) that is the basis of 3D computer graphics.

Specifically, a set of “Euler Angles” is represented by a vector of 3 numbers and an order that they are applied. In Blender, look under the spot where you define your rotation angles, you will see a dropdown that has “XYZ Euler” in it. You will find options to use other Euler notations like “ZYX Euler”. That is telling the system the order that the angles will be applied.

Imagine you have a Euler angle that is defined as a “XYZ Euler” set to (90, 45, 10). To apply this to an object or vertex you:

  • First rotate by 90 degrees around the X axis
  • Then rotate by 45 degrees around the Y axis
  • Then rotate by 10 degrees around the Z axis

If you define the Euler angle as “ZYX Euler” and keep the numbers as (90, 45, 10) then you get this rotation:

  • First rotate 10 degrees around the Z axis
  • Then rotate 45 degrees around the Y axis
  • Then rotate 90 degrees around the X axis

You object will end up in a different location except in a few special cases.

The basic problem is that all those rotations are done by doing matrix multiplication. This is a fundamental thing that you cannot design around. Anything you do with an Euler angle will involve rotations and this will require matrix math.

ok, but I can’t rotate the vertex about the global axis…
I’ll get mis-transformations

I want to rotate around a point in space, not (0,0,0).
how do you apply the rotations to a vert from a local coord w/o using matrices??

let me decide which method is better for a perticular task, thank you though. :wink:

and yea, everything is applied as the logical XYZ (W,H,D)
(MD5 models use illogical YZX, and MCE schematic models use slightly illogical XZY…)
^ both of which need to be reordered before being processed

a problem with that representation though is that 1D is usually H, not W.

but anyways…
location is really easy, and is demonstraited in my first post…
scale seems pretty easy as you’re just repositioning the vert to/from the local coord, where the bone’s base is…
(I’d like to know an efficient way of applying this as well)

oh and lets not forget about weighting the rotation and scale coords. :stuck_out_tongue:

also, for your concern,
I’ve already learned the matrix manipulation system…
there’s alot of needless multiplication involved, which is why quaternions are better reccomended for efficient rotation transformation.

if it’ll help, here’s a function describing what I need:


def Transform( Vx,Vy,Vz, Coords):
    for (Px,Py,Pz),(Lx,Ly,Lz),(Rx,Ry,Rz),(Sx,Sy,Sz),W in Coords:

        Vx += Lx*W
        Vy += Ly*W
        Vz += Lz*W

        #need rotation and scale applications here

    return Vx,Vy,Vz

NOTE: L,R,S ia local to P

EDIT:
just to note, that’s a dummed down version of an older version of my code…
the newer version will calculate an influence coord before-hand and apply that to the vert:

for (Ix,Iy,Iz) in Coords:

it should work almost exactly like the matrix manipulation method,
but with less calculations, be 2-3 times faster.

The following is not an opinion, it is a mathematical truth:
You cannot rotate a vert w/o using matrices. Rotating a point/vert is an affine transformation and matrix operations are how these are expressed. You can come up with equations that might look like something other than a matrix operations but they will actually just be the matrix operations written out long hand.

Rotating about an arbitrary point is accomplished by combining translations and rotations. Check out this section of the OpenGL Redbook that explains how translations and rotations work.

http://www.glprogramming.com/red/chapter03.html skip to the section called “Viewing and Modeling Transformations”

let me decide which method is better for a perticular task, thank you though. :wink:

You asked for help. I’m sorry that what you want is mathematically impossible.

also, for your concern,
I’ve already learned the matrix manipulation system…
there’s alot of needless multiplication involved, which is why quaternions are better reccomended for efficient rotation transformation.

You frankly don’t know what you are talking about. There is just as much multiplication as is required to handle general purpose affine transformations. If you want a limited system, then you might be able to simply something.

Quaternions are mainly useful for rotations because they avoid gimbal lock and smooth interpolations between quats is straight forward. The fact that a quat rotation can save a few multiplications is almost meaningless on modern hardware.

well fine, then I’ll use a quat:

Rw = 1.0 - RxRx - RyRy - Rz*Rz
if Rw<0: Rw=0
else: Rw= -sqrt(Rw)

also
your insinuation that this is mathmatically impossible can be compaired to insinuating that RAW curve calculations are impossible.
(using sin() and cos() to modify a curve about an x/y axis)

using sin() an cos() with pi to rotate a point about an imaginary point is possible.
I believe it’s a 3-step process, but I don’t rmbr how it’s done. >_<

can we please stahp playing around here…
I’m asking for help, if you don’t know, don’t answer.
(instead of giving me a hard time)

EDIT: ok then I’ll change the title…

well, looking at some complex examples which demonstraite this,
I would have to say that yes a rotation matrix would be the best example of efficiency here

which makes the use of a 4x3 matrix only partially valid due to the code I’m working with.
(I need eular coords passed to the functions)
I’m sorry I doubted you guys and matrices. :slight_smile:

so…
can you just help me apply a 3x3 matrix to this and get the scale working, please. :slight_smile:

EDIT: for rotation, I just need to know how to rotate about P
once that’s done, I know how to apply it :wink:

EDIT2: found a 2D example: http://stackoverflow.com/questions/13695317/rotate-a-point-around-another-point

EDIT3: I think I’ve found the help I needed:
http://mathforum.org/library/drmath/view/65301.html
I’m still reading though, so I’ll report back if failed.
if succeeded, I’ll update the function… heh

well, I think I’ve gotten the rotation part down:


def Transform(Coords): #calculate the influence to apply to a group of verts
    Ix,Iy,Iz = 0.0,0.0,0.0
    for (Px,Py,Pz),(Lx,Ly,Lz),(Rx,Ry,Rz),(Sx,Sy,Sz),W in Coords:
        cx,sx = cos(x),sin(x)
        cy,sy = cos(y),sin(y)
        cz,sz = cos(z),sin(z)

        Ix += Lx*W
        Iy += Ly*W
        Iz += Lz*W

        #translate the vert to the origin, apply the rotation, then translate it back
        Ix -= Px; Iy -= Py; Iz -= Pz
        Ix = (((cy*cz)*Ix) + (sz*Iy) + (-sy*Iz))*W
        Iy = ((-sz*Ix) + ((cx*cz)*Iy) + (sx*Iz))*W
        Iz = ((sy*Ix) + (-sx*Iy) + ((cx*cy)*Iz))*W
        Ix += Px; Iy += Py; Iz += Pz

        #need scale application here

    return Ix,Iy,Iz

is that right??
(I know the weight application is wrong…)
^not sure how to do

I know how to apply the matrix, not calculate it :stuck_out_tongue:

EDIT:
also, I’m not worried about GPU usage as this is only used to grab a model, not render it.

just got some info over at DaniWeb explaining the use of quaternions,
and it looks like they are the best choice when it comes to rotation.

I think that you just about have it. As your first step before you do any rotation or translations, you just need to do a component-wise multiplication of your vertex with your scaling factor. I think that your scale is contained in (Sx, Sy, Sz) so something like this:


def Transform(Coords): #calculate the influence to apply to a group of verts
    Ix,Iy,Iz = 0.0,0.0,0.0
    for (Px,Py,Pz),(Lx,Ly,Lz),(Rx,Ry,Rz),(Sx,Sy,Sz),W in Coords:
        cx,sx = cos(x),sin(x)
        cy,sy = cos(y),sin(y)
        cz,sz = cos(z),sin(z)

        #-----
        # Scale the point here.
        Ix += (Lx*W) * Sx
        Iy += (Ly*W) * Sy
        Iz += (Lz*W) * Sz

        #translate the vert to the origin, apply the rotation, then translate it back
        Ix -= Px; Iy -= Py; Iz -= Pz
        Ix = (((cy*cz)*Ix) + (sz*Iy) + (-sy*Iz))*W
        Iy = ((-sz*Ix) + ((cx*cz)*Iy) + (sx*Iz))*W
        Iz = ((sy*Ix) + (-sx*Iy) + ((cx*cy)*Iz))*W
        Ix += Px; Iy += Py; Iz += Pz

        #need scale application here

    return Ix,Iy,Iz

If you point is starting in its object-space then this should make the object grow bigger.

Edit

And, yes, quats are a very useful tool when working with rotations.

IDK…
that looks more like a global scale…

though I’m an idiot, lol
to make the local scale global, simply apply the scale after rotating the vert ( about (0,0,0) )
and then translate the vert to it’s local position:

def Transform(Coords): #calculate the influence to apply to a group of verts
    Ix,Iy,Iz = 0.0,0.0,0.0
    for (Px,Py,Pz),(Lx,Ly,Lz),(Rx,Ry,Rz),(Sx,Sy,Sz),W in Coords:
        cx,sx = cos(x),sin(x)
        cy,sy = cos(y),sin(y)
        cz,sz = cos(z),sin(z)

        Ix += Lx*W
        Iy += Ly*W
        Iz += Lz*W

        #translate the vert to the origin, apply the rotation and scale, then translate it back
        Ix -= Px; Iy -= Py; Iz -= Pz
        Ix = (((cy*cz)*Ix) + (sz*Iy) + (-sy*Iz))*W
        Iy = ((-sz*Ix) + ((cx*cz)*Iy) + (sx*Iz))*W
        Iz = ((sy*Ix) + (-sx*Iy) + ((cx*cy)*Iz))*W
        Ix *= Sx*W
        Iy *= Sy*W
        Iz *= Sz*W
        Ix += Px; Iy += Py; Iz += Pz

    return Ix,Iy,Iz

don’t forget, P is the base of a bone, so when scaled, the verts should translate to that point.

I voted for the order Loc -> Rot -> Sca, but if you know Sca application to be better applied first,
then I’ll apply it before Rot and then the new translation afterwards.

or would that mess things up??
remember, we’re dealing with bone orientations were the RAW verts are untransformed.
(Note for others: the T-Pose is the verts in their transformed/un-animated positions)
here’s an example of an untransformed model:


^old image is old :stuck_out_tongue:

those are the RAW vertex positions you’d find in an animation buffer.
or to be more accurate, Nintendo’s XF transformation buffer.

if I’m right on this, I should only have to be added to V before it’ll be in the right spot.

I didn’t know the specific format that your data was coming in so your best bet is to check the documentation for the format and see if that gives any guidance.

we’re working on writing documentation…

but basically from what I understand, GX is GL w/o GPU implamentations.
(GX doesn’t have shaders, it uses GL’s immediate mode and advanced texturing interface with support for vector arrays and attributes)
^though most immediate mode functions now use the GPU >_>

in the CPU, the XF registers store the influence matrices used in transformation…
but I’ve been having problems with the matrix method,
and wanted to use something a little simpler, and easier to manage… (temporarily)

plus this makes normal management a little easier until I can fully figure out the XF register.

if this works though, the model should import alot faster
(undergoing only 3 addition processes instread of 18 multiplication/addition processes per vertex)
^this is the reason I question the matrix method to the euler method.

it was alot more actually till I was taught the influence method… heh

EDIT:
also, all transformations are local to P and affected by W.

I freakin give ><
transformations look like they’re not being applied at all. >
<
(even though they are)
and bone locations are completely messed up.

I already know they’re not global as they’re not in their default locations when referenced directly.

can I possibly get some help with this?? :confused:

for the bones, I’m given a slew of local transformations and an inverse matrix

when I try to build a local transform matrix and apply the parent transform matrix to it,
(bones are processed by pointers leading to the child and next bone’s position),
this happens:

however using an inverse of the inverse-bind matrix does yield proper results only for most models,
though 1: other models still fail, 2: inversing the inverse matrix is not the proper method, creating a transform matrix is.

could it possibly be my transform matrix generation code?? <.<

def TransformMatrix( translate, rotate, scale ):
        global degrad #degrad = pi/180
        cosx = cos(rotate[0] * degrad)
        sinx = sin(rotate[0] * degrad)
        cosy = cos(rotate[1] * degrad)
        siny = sin(rotate[1] * degrad)
        cosz = cos(rotate[2] * degrad)
        sinz = sin(rotate[2] * degrad)

        return [
            [   scale[0] * cosy * cosz,
                scale[1] * (sinx * cosz * siny - cosx * sinz),
                scale[2] * (sinx * sinz + cosx * cosz * siny),
                translate[0]],
            [   scale[0] * sinz * cosy,
                scale[1] * (sinx * sinz * siny + cosz * cosx),
                scale[2] * (cosx * sinz * siny - sinx * cosz),
                translate[1]],
            [   -scale[0] * siny,
                scale[1] * sinx * cosy,
                scale[2] * cosx * cosy,
                translate[2]],
            [0.0,0.0,0.0,1.0]]

code from BrawlBox (translated to Python) which handles the exact same data, just from a different game.

I just don’t even know anymore and am frustraited after years of trying to get this thing working. -.-*