
DeleD Community Edition Forums

View previous topic :: View next topic 
Author 
Message 
Jeroen Site Admin
Joined: 07 Aug 2004 Posts: 5334 Location: The Netherlands

Posted: Sat May 15, 2010 5:58 pm Post subject: Rotate polygon to parallel plane 


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% fullproof. 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 


AWM Mars Member
Joined: 06 Jan 2010 Posts: 1195 Location: Wilts England


Back to top 


Jeroen Site Admin
Joined: 07 Aug 2004 Posts: 5334 Location: The Netherlands

Posted: Sat May 15, 2010 9:26 pm Post subject: 


lol AWM, I know the feeling. 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 


chronozphere DeleD PRO user
Joined: 20 Jun 2006 Posts: 1010 Location: Netherlands

Posted: Sat May 15, 2010 11:07 pm Post subject: 


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.
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 arbitraryaxis rotation matrix that performs this kind of angleaxis 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.
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. 

Back to top 


Jeroen Site Admin
Joined: 07 Aug 2004 Posts: 5334 Location: The Netherlands

Posted: Sun May 16, 2010 8:32 am Post subject: 


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 


chronozphere DeleD PRO user
Joined: 20 Jun 2006 Posts: 1010 Location: Netherlands

Posted: Sun May 16, 2010 1:27 pm Post subject: 


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. 

Back to top 


Jeroen Site Admin
Joined: 07 Aug 2004 Posts: 5334 Location: The Netherlands

Posted: Mon May 17, 2010 8:06 am Post subject: 


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. 
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 


chronozphere DeleD PRO user
Joined: 20 Jun 2006 Posts: 1010 Location: Netherlands

Posted: Mon May 17, 2010 10:08 am Post subject: 


Yeah... that's basicly the approach I was thinking of. 

Back to top 


Jeroen Site Admin
Joined: 07 Aug 2004 Posts: 5334 Location: The Netherlands

Posted: Mon May 17, 2010 10:51 am Post subject: 


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 


tpascal Member
Joined: 23 Nov 2009 Posts: 11

Posted: Mon May 17, 2010 11:48 pm Post subject: 


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 XYZ 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 XYZ 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 nonzero
# 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 


tpascal Member
Joined: 23 Nov 2009 Posts: 11

Posted: Mon May 17, 2010 11:49 pm Post subject: re 


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 




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

