Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

 
Advanced search

877555 Posts in 32868 Topics- by 24308 Members - Latest Member: raguelep16

May 19, 2013, 07:14:34 PM
TIGSource ForumsDeveloperTechnical (Moderators: Glaiel-Gamer, ThemsAllTook)I believe i might need Quaternions ... (rotating voxel object)
Pages: [1] 2 3
Print
Author Topic: I believe i might need Quaternions ... (rotating voxel object)  (Read 1516 times)
nikki
Level 10
*****


View Profile Email
« on: June 13, 2012, 01:49:11 PM »

Hi

i am building an editor for my game to come and i'm walking into new area's.
atm i am using layers of small blocks to form a 3d object made of blocks; voxels .


now the blocks can only be rotated over its height axle by 90 degrees step only.
for all the environment stuff that works nicely but the characters need more juice.

so i was thinking:
i have a list of all the voxels that are in an object
i could walk that list and reposition every voxel, some research gave me Quaternions, but i havent got a clue, do you know some easy tutorial?, am i on the right track?, should i look elsewhere?




 

Logged
ThemsAllTook
Moderator
Level 8
******


Alex Diener


View Profile WWW
« Reply #1 on: June 13, 2012, 03:18:26 PM »

I wrote a tutorial on quaternions that might help you. I imagine what you described would work just fine, though it might give you some aliasing artifacts...thinking about anti-aliasing voxels is breaking my brain a bit, so hopefully just multiplying each voxel's position by a quaternion gives you the effect you want.
Logged
Danmark
Level 7
**



View Profile
« Reply #2 on: June 13, 2012, 08:13:21 PM »

The best tutorial and reference I've seen on Quaternions is here.

At your rendering step, convert each object's quaternion to a matrix. For each voxel in that object, calculate its local transform matrix (its local position should be the only relevant info), and multiply it with the object's matrix. You don't wanna rotate each voxel in an object individually, because they'd drift over time.

What are you using for rendering?
Logged
nikki
Level 10
*****


View Profile Email
« Reply #3 on: June 14, 2012, 02:58:08 AM »

Nice series ThemsAllTook, seems well-written/illustrated too!

probably a good idea to start learning at vector, then matrix then quaternion ?
at the moment i'm using some 3d math functions i've found somewhere, they allready give me the good answers, (I believe) but i'm just not understanding it at all.

Quote
"What are you using for rendering?"

I'm using blitzmax, so it could be opengl or dx, I'm using ogl
but why are you asking, what has that to do with rotating an 3d object in imaginary space ?

Logged
nikki
Level 10
*****


View Profile Email
« Reply #4 on: June 14, 2012, 10:05:07 AM »

instead of learning the tutorials i spend all afternoon getting up a little editor and plugging in an existing quaternion solution.


not a real success but a cool bad 3d visualizer
https://www.dropbox.com/s/ntdbe9kqv2bs67n/voxeltest.exe



now I'm off reading the tuts

btw "some aliasing artifacts..."  already spotted ! No No NO

edit: been playing with the quaternion playground ThemsAllTook made, I noticed when you rotate a quat that it flips axis when over a certain treshold, the 3d models don't do that, how is that done? Because I think thats bugging in my solution atm.
« Last Edit: June 14, 2012, 01:24:55 PM by nikki » Logged
Danmark
Level 7
**



View Profile
« Reply #5 on: June 14, 2012, 02:34:26 PM »

probably a good idea to start learning at vector, then matrix then quaternion ?

Yes.

I asked about your rendering system because it's the only easy way to see if your rotation solution is working.


btw "some aliasing artifacts..."  already spotted ! No No NO

It looks like each voxel is staying aligned to the global axes, while being positioned according to the object's local axes. You didn't specify, but I doubt this is what you want (ThemsAllTook thought otherwise), and it's what you should get by multiplying the voxel's (local) position by the object's quaternion. Again, you need to build transform matrices.

Also looks like the object's getting squashed and reflected, not just rotated. What procedure exactly are you doing here?

Dunno what you mean on quat flipping. Be aware that hardly anyone considers quaternions intuitive (unlike vectors and matrices).
Logged
nikki
Level 10
*****


View Profile Email
« Reply #6 on: June 14, 2012, 03:19:41 PM »

updated the editor :https://www.dropbox.com/s/iphhjwqde8qvu3f/main.exe (it now has a wired cube to begin with)

@Veracity:
quat flipping = squashed and reflected ..

my rendering system is actually a big 3d array of which every voxel thats there gets drawn.
(by me just doing a drawimage(pixelimage, x, y) the y gets calculated according to depth & height), i'm pretty sure thats working correctly though


the procedure:

when one of the 3 sliders is used:
use the data in the 3 slider in

Code:
Function EulerToQuat:Quaternion(pitch#,yaw#,roll#)


Local cr#=Cos(-roll#/2.0)
Local cp#=Cos(pitch#/2.0)
Local cy#=Cos(yaw#/2.0)
Local sr#=Sin(-roll#/2.0)
Local sp#=Sin(pitch#/2.0)
Local sy#=Sin(yaw#/2.0)
Local cpcy#=cp#*cy#
Local spsy#=sp#*sy#
Local spcy#=sp#*cy#
Local cpsy#=cp#*sy#
Local q:Quaternion=New Quaternion
q.n#=cr#*cpcy#+sr#*spsy#
q.v.x#=sr#*cpcy#-cr#*spsy#
q.v.y#=cr#*spcy#+sr#*cpsy#
q.v.z#=cr#*cpsy#-sr#*spcy#
Return q
endFunction

that should give me a quaternion with the desired rotations
with the original data and that quat i use:

Code:
Function rotateModel:TModel(model:TModel, rotationQuat:Quaternion)
'model is a container object for the 3d array
' newmodel is double the size in every dimension, so it will fit
Local newModel:TModel = TModel.Create(model.gridHeight*2,model.gridWidth*2,model.gridDepth*2)


For Local y:Int = 0 Until model.gridHeight
For Local z:Int = 0 Until model.gridDepth
For Local x:Int = 0 Until model.gridWidth
Local v:Int = model.map[y, z, x ]
If v>0

'create a quat (translate model so the middle is at 0,0,0)
Local quat:Quaternion = Quaternion.Create(0,x-(model.gridWidth/2),y-(model.gridHeight/2),z-(model.gridDepth/2))

Local c:Quaternion = Quaternion.MultiplyQuats(quat,rotationQuat)


'paste the new model in with a translation to get back at the middle
newModel.setAt(c.v.y + model.gridHeight, c.v.z+ model.gridDepth, c.v.x+ model.gridWidth, v)

EndIf
Next
Next
Next

Return newModel
EndFunction


the function that gets called there is this one:
Code:
Function MultiplyQuats:Quaternion(q1:Quaternion,q2:Quaternion)

Local q:Quaternion=New Quaternion

q.n = q1.n*q2.n -   q1.v.x*q2.v.x - q1.v.y*q2.v.y - q1.v.z*q2.v.z
q.v.x = q1.n*q2.v.x + q1.v.x*q2.n +   q1.v.y*q2.v.z - q1.v.z*q2.v.y
q.v.y = q1.n*q2.v.y + q1.v.y*q2.n + q1.v.z*q2.v.x - q1.v.x*q2.v.z
q.v.z = q1.n*q2.v.z + q1.v.z*q2.n + q1.v.x*q2.v.y - q1.v.y*q2.v.x

Return q

End Function



hope it makes more sense to you  Blink,
no Wait, hope it will make more sense  Blink Blink eventually




Logged
Danmark
Level 7
**



View Profile
« Reply #7 on: June 14, 2012, 07:52:49 PM »

Code:
Local cr#=Cos(-roll#/2.0)
Local cp#=Cos(pitch#/2.0)
Local cy#=Cos(yaw#/2.0)
Local sr#=Sin(-roll#/2.0)
Local sp#=Sin(pitch#/2.0)
Local sy#=Sin(yaw#/2.0)

Not the cause of your problem, but why are you inverting the roll?


Code:
Local quat:Quaternion = Quaternion.Create(0,x-(model.gridWidth/2),y-(model.gridHeight/2),z-(model.gridDepth/2))
     
      Local c:Quaternion = Quaternion.MultiplyQuats(quat,rotationQuat)

Multiplying two quaternions, and a vector by a quaternion, are completely different operations. quat:Quaternion is not a rotation quaternion at all (not that I know what it is). This is the source of the weirdness. Pass those same parameters as from quat (sans the w component of the quaternion) to a vector, and multiply the rotation quaternion by the vector. This is what ThemsAllTook meant.

Note that unit quaternions are used for rotation.
Logged
nikki
Level 10
*****


View Profile Email
« Reply #8 on: June 15, 2012, 12:17:49 AM »

multiplying the rotationquat with a vector gives the same results..

by the way: should i do something with the input (0, 720) ?
don't really know why but i need 720 degrees for a full rotation, maybe that causes trouble somewhere ?

edit: pff still havent got it, my mind is blown
« Last Edit: June 15, 2012, 05:15:43 AM by nikki » Logged
nikki
Level 10
*****


View Profile Email
« Reply #9 on: June 15, 2012, 05:55:50 AM »

its fixed now, i had to read god knows how many tutorials in greek letters, and/or these academic pdf's in a sort of rage, and finally it was just this :

Code:
//vec = xyz point in vector

Local c:Quaternion = rotationQuat.mulV(vec)  // multiply vector with rotationQuat
c= Quaternion.MultiplyQuats(c,rotationQuat.inverse())  //multiply Quat with inverse of rotationQuat

after the rotation i needed to multiply it again with the inverse..

anyway https://www.dropbox.com/s/yx4nmd7v5gan2fy/voxel2.exe

i've got some cleaning up to do
Logged
Danmark
Level 7
**



View Profile
« Reply #10 on: June 15, 2012, 01:23:50 PM »

^
Congrats on getting it working! But the issue you solved is odd. Multiplying a quaternion by a vector should give you a vector, and there's no need to assign to modify any retained quaternion through the process. Check the implementation of Quaternion's mulV().

If the vector's being passed by reference, you should be able to simplify that code to:

Code:
rotationQuat.mulV(vec)


by the way: should i do something with the input (0, 720) ?
don't really know why but i need 720 degrees for a full rotation, maybe that causes trouble somewhere ?

Haven't looked at the code again, but it probably has something to do with there being 2*pi radians in a full rotation (same as the circumference of the unit circle). Work with radians where possible- degrees are more trouble than they're worth.
Logged
nikki
Level 10
*****


View Profile Email
« Reply #11 on: June 15, 2012, 03:14:13 PM »

the implementation of Quaternion's mulV().
Code:
' Purpose: Multiply a Quaternion by a Vector
        ' Returns: Quaternion
        ' Example1: q1=q1*v1 would be written q1 = q1.MulV( v1 )
        Method MulV:Quaternion( v:Vector )
                Local res:Quaternion = New Quaternion
                res.n = -(Self.v.x*v.x + Self.v.y*v.y + Self.v.z*v.z)
                res.v.x = Self.n*v.x + Self.v.y*v.z - Self.v.z*v.y
                res.v.y = Self.n*v.y + Self.v.z*v.x - Self.v.x*v.z
                res.v.z = Self.n*v.z + Self.v.x*v.y - Self.v.y*v.x
                Return res
        End Method



Quote
input (0, 720)
yeah, since i divide all those numbers in the EulerToQuat function by 2 it makes sence.


anyhow, it was a productive day, i learned alot about scary imaginary numbers and 3d stuff, now sleeping and thinking about the next step:

building a character animation system with this.....
(thats probably not the immediate next step  Wink.)

goodnight!
Logged
ham and brie
Level 2
**



View Profile Email
« Reply #12 on: June 15, 2012, 03:45:32 PM »

That MulV() effectively treats the vector as a quaternion (with 0 for its real/scalar part) and does quaternion multiplication.

The result of doing that is not the vector rotated by the quaternion.

It's another quaternion. If that quaternion is multiplied with the inverse of the rotation quaternion, the vector part of the resulting quaternion should be the desired rotated vector.

Which is why the fix is right.

That is what the equation here means:



rotated vector = rotation quaternion * vector * conjugate of rotation quaternion

The two multiplications are quaternion multiplications. The conjugate and inverse of a rotation quaternion are the same (the imaginary/vector part is negated).
Logged
nikki
Level 10
*****


View Profile Email
« Reply #13 on: June 17, 2012, 05:27:51 AM »

so its correct ? nice  Cool

i just realized i way i could fix the antialiasing..  i guess
if i would use 3d shapes (cube, cone, piramids (4/3 sides) prisms ) to construct a voxel object with, i could rotate the important points of the shapes (the endpoints) and after the rotation i'd rebuild the shapes, fill the correct voxels and enjoy.

so basically the aliasing is fixed as it is always fixed, by using vector instead of pixel

this way of thinking/and building is fruitfull you guys would think ?
Logged
Ashaman73
Level 0
**



View Profile WWW
« Reply #14 on: June 18, 2012, 10:55:45 PM »

Just out of interest, why do you want to use quaternions ?

Unit quaternions and orthogonal rotation matricies are just different ways to describe the same rotation, so in general when it comes down to game developing, you often use quaternions only if you need to save space (rotation matrix = 3x3, quaternion = 4x1) or if you want to do easy, smooth rotations (slerp, this is the reason it is often used in animation or camera movement).

A matrix setup is often easier to understand (you can read the 4 important vectors, position+3 axis, directly from the 4x4 homogenous matrix) and to manipulate. When you need do smooth movement, write a simple slerp function which takes in matrices, uses internally quaternions and outputs a matrix again. This might help you to keep your sanity.  Wink

Logged

Pages: [1] 2 3
Print
Jump to:  

Theme orange-lt created by panic