Delgine 3D Tools & Content DeleD Community Edition
Forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Rotate polygon to parallel plane

 
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    DeleD Community Edition Forum Index -> DeleD Development
View previous topic :: View next topic  
Author Message
Jeroen
Site Admin


Joined: 07 Aug 2004
Posts: 5332
Location: The Netherlands

PostPosted: Sat May 15, 2010 5:58 pm    Post subject: Rotate polygon to parallel plane Reply with quote

Here's one for you:

I have this polygon (A) centered around 0,0,0. I have another polygon (B) in an arbitrary position and orientation. I'd like to get polygon A in the same orientation as polygon B so that they are parallel. Question: how to achieve that?

I've got some code that does the job but it's not 100% full-proof. It's also not very efficient. Of course, I'm looking for efficient ways (mathematical speaking really) to achieve the desired effect. Suggestions, anyone?
_________________
Check out Figuro, our online 3D app! More powerful 3D tools for free.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
AWM Mars
Member


Joined: 06 Jan 2010
Posts: 1195
Location: Wilts England

PostPosted: Sat May 15, 2010 6:20 pm    Post subject: Reply with quote

In these instances, I always evoke the DIY rule... Don't Involve Yourself Shocked

Ask me one on English Football from the 1970's.... I don't know anything about that subject either.
_________________
Politeness is priceless when received, cost nothing to own or give, yet some cannot afford.

Checkout:
http://www.awm.mars.yourinside.com/
http://www.bccservices.co.uk
http://www.localtradecheck.co.uk
Back to top
View user's profile Send private message Visit poster's website
Jeroen
Site Admin


Joined: 07 Aug 2004
Posts: 5332
Location: The Netherlands

PostPosted: Sat May 15, 2010 9:26 pm    Post subject: Reply with quote

lol AWM, I know the feeling. Wink But never mind - I figured it out already. For those interested, here's what I'm doing:

- setup an orthonormal base using vertices of polygon B. This is the coordinate system we want to rotate into.
- create a rotation matrix holding values of the orthonormal base.
- rotate polygon A using the rotation matrix.

If anyone wants more info, I got a .pdf explaining things in detail.
_________________
Check out Figuro, our online 3D app! More powerful 3D tools for free.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
chronozphere
DeleD PRO user


Joined: 20 Jun 2006
Posts: 1010
Location: Netherlands

PostPosted: Sat May 15, 2010 11:07 pm    Post subject: Reply with quote

Do you want to keep the original shape of the polygon? if not, you can just extract a plane from the vertices of polygon A and project polygon B onto that plane. I guess this is a bit too simple. Wink

What I'd do is the following:

> Compute two normals (one for each plane of each polygon)
> Take the two normal vectors and perform a cross product on them. This will give you an axis to rotate about to align the polygons.
> Use the dot product on both normals to determine the angle between them.
> Now make a arbitrary-axis rotation matrix that performs this kind of angle-axis transformation.

This approach alligns the polygons. The position is not affected. You didn't mention it in your post, so I thought I could leave that out. Smile

Quote:

- setup an orthonormal base using vertices of polygon B. This is the coordinate system we want to rotate into.
- create a rotation matrix holding values of the orthonormal base.
- rotate polygon A using the rotation matrix.


I guess this only works when your polygon A is perfectly aligned to one of the cardinal planes (XY, YZ, XZ) as you don't take A's orientation into account.

It might be that I didn't correctly understand your problem. My answer might not be 100% applicable here. Wink
Back to top
View user's profile Send private message
Jeroen
Site Admin


Joined: 07 Aug 2004
Posts: 5332
Location: The Netherlands

PostPosted: Sun May 16, 2010 8:32 am    Post subject: Reply with quote

Yeah, I want to keep the original shape of the polygon. And indeed, the method only works if polygon A is in one of the standard planes. I wonder how to adept the method so it takes the orientation of A into account as well...

I actually used the method you described before, but it seems I need multiple rotations to get the planes (polygons) to become parallel. Something like:

Code:

while (angle>1) and (angle<179.9999) do begin
  - do the stuff you described
end;


This seems to work, but I'm not happy with it. I might be doing it wrong though. I'm now using the method I described earlier which works like a charm (as long as polygon A is in a standard plane), but I would still love to see code of a working example of the method you're mentioning.
_________________
Check out Figuro, our online 3D app! More powerful 3D tools for free.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
chronozphere
DeleD PRO user


Joined: 20 Jun 2006
Posts: 1010
Location: Netherlands

PostPosted: Sun May 16, 2010 1:27 pm    Post subject: Reply with quote

Seems like you're using an iterative approach (while..do). This should not be neccesary. I could make an example for you to see my method, but not now as I'm extremely busy. Razz
Back to top
View user's profile Send private message
Jeroen
Site Admin


Joined: 07 Aug 2004
Posts: 5332
Location: The Netherlands

PostPosted: Mon May 17, 2010 8:06 am    Post subject: Reply with quote

chronozphere wrote:
Seems like you're using an iterative approach (while..do). This should not be neccesary. I could make an example for you to see my method, but not now as I'm extremely busy. Razz


No worries, I got it working using something like:

Code:

    axis := crossproduct(polygon.Normal, targetPolygon.Normal);
    angle := dotproduct(polygon.Normal, targetPolygon.Normal);
    angle := arccos(angle)*(180/pi);
    matrix := MatrixArbAxisSetup(axis, polygon.Center, angle);

    // now rotate the vertices of polygon


It seems to do the job nicely, although I noticed it might not be accurate all the time. Further investigation needed.

The orthonormal base approach works in my situation.
_________________
Check out Figuro, our online 3D app! More powerful 3D tools for free.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
chronozphere
DeleD PRO user


Joined: 20 Jun 2006
Posts: 1010
Location: Netherlands

PostPosted: Mon May 17, 2010 10:08 am    Post subject: Reply with quote

Yeah... that's basicly the approach I was thinking of. Wink
Back to top
View user's profile Send private message
Jeroen
Site Admin


Joined: 07 Aug 2004
Posts: 5332
Location: The Netherlands

PostPosted: Mon May 17, 2010 10:51 am    Post subject: Reply with quote

Still, that implementation doesn't work all the time. To get to a correct alignment, I still need to rotate multiple times. Don't know what causes that though.... Rounding errors perhaps?
_________________
Check out Figuro, our online 3D app! More powerful 3D tools for free.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
tpascal
Member


Joined: 23 Nov 2009
Posts: 11

PostPosted: Mon May 17, 2010 11:48 pm    Post subject: Reply with quote

This code is not mine, i have it stored to be used later so i dont even have tested it.

Quote:

#----------------------------------------------------------------------------
# Given two vectors v1 and v2, calculate a X-Y-Z euler rotation so that v1
# would be facing in the same direction as v2.
#----------------------------------------------------------------------------
import math
import sys
import AdditionalMathutils

def getEulerAngles(_srcV, _destV):
"""
Given two vectors v1 and v2, calculate a X-Y-Z euler rotation so that v1
would be facing in the same direction as v2.
"""
import Blender

# Make a copy of the original vectors
srcV = Blender.Mathutils.Vector(_srcV)
destV = Blender.Mathutils.Vector(_destV)

# Normalize them to just get the directions
srcV.normalize()
destV.normalize()

# Get the rotation axis
rotAxis = getRotationAxis(srcV, destV)

# We have no idea whether to rotate clockwise or counter clockwise, so
# we just have to try both.
angle = AdditionalMathutils.radToDeg(math.acos(srcV * destV))
mAngle = -angle

qAngle = Blender.Mathutils.Quaternion(rotAxis, angle)
qMAngle = Blender.Mathutils.Quaternion(rotAxis, mAngle)

rAngle = srcV * qAngle.toMatrix()
rMAngle = srcV * qMAngle.toMatrix()

# Pick the direction that rotates the src vector closest to the dest vector
if abs(rAngle * destV) < abs(rMAngle * destV):
return qMAngle.toEuler()

return filterOutUnnecessaryRotations(srcV, destV, qAngle.toEuler())


def filterOutUnnecessaryRotations(srcV, destV, euler):
"""
Apply the euler rotations in the order of X->Y->Z to filter out
the rotations that make no difference.
"""
import Blender

ex = Blender.Mathutils.Euler(euler.x, 0, 0).toMatrix()
ey = Blender.Mathutils.Euler(0, euler.y, 0).toMatrix()
ez = Blender.Mathutils.Euler(0, 0, euler.z).toMatrix()

newSrcVX = srcV * ex
newSrcVX.normalize()

if (newSrcVX - destV).length < 0.0001:
return Blender.Mathutils.Euler(euler.x, 0, 0)

newSrcVXY = srcV * ex * ey
newSrcVXY.normalize()

if (newSrcVXY - destV).length < 0.0001:
return Blender.Mathutils.Euler(euler.x, euler.y, 0)

return euler


def getRotationAxis(_v1, _v2):
"""
Given two vectors, find the axis that's normal to
both of them.
"""
import Blender
v1 = Blender.Mathutils.Vector(_v1)
v2 = Blender.Mathutils.Vector(_v2)
v1.normalize()
v2.normalize()
cross = Blender.Mathutils.CrossVecs(v1, v2)

# If v1 and v2 are not on the same line, cross will be non-zero
# and we are happy
if cross.length > 0:
return cross

# Otherwise we have to find our own rotation axis
x = 0.0
y = 0.0
z = 0.0
if v1.x * v1.y * v1.z == 0.0:
if v1.x != 0.0:
x = 0.0
else:
x = 1.0

if v1.y != 0.0:
y = 0.0
else:
y = 1.0

if v1.z != 0.0:
z = 0.0
else:
z = 1.0
else:
x = 0.0
y = -v1.z
z = v1.y

v = Blender.Mathutils.Vector(x, y, z)
v.normalize()
return v



def test():
"""
"""
import Blender
print >> sys.stderr, '-------------------------------'
v1 = Blender.Mathutils.Vector(0, 0, 1)
v2 = Blender.Mathutils.Vector(0, 0, -1)
euler = getEulerAngles(v1, v2)

print >> sys.stderr, 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV'
print >> sys.stderr, 'src vector =', v1, 'dest vector =', v2
print >> sys.stderr, 'Euler angles =', euler

ex = Blender.Mathutils.Euler(euler.x, 0, 0)
ey = Blender.Mathutils.Euler(0, euler.y, 0)
ez = Blender.Mathutils.Euler(0, 0, euler.z)

v2.normalize()
print >> sys.stderr, 'target =', v2

v1.normalize()
print >> sys.stderr, 'we got:', v1 * ex.toMatrix() * ey.toMatrix() * ez.toMatrix()

return

#----------------------------------------------------------------------------

if __name__ == '__main__':
test()
Back to top
View user's profile Send private message
tpascal
Member


Joined: 23 Nov 2009
Posts: 11

PostPosted: Mon May 17, 2010 11:49 pm    Post subject: re Reply with quote

I have a lighmapper app code, currently i am just using the triangle's normal and the triangle points for doing light calcs, as i am deriving every lumel in world space anyway i wonder if using a similar function like above would be useful for lets say "transform" a lumel's normal readed from the triangle's dot3 texture into world space and do lighting.

Or maybe it is way simpler to understand the traditional way transforming light position in texture space using tangent, binormal, which i dont have idea how to do it.


Last edited by tpascal on Tue May 18, 2010 12:16 am; edited 3 times in total
Back to top
View user's profile Send private message
Display posts from previous:   
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    DeleD Community Edition Forum Index -> DeleD Development All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum