AlignToVector

BlitzMax Forums/MiniB3D Module/AlignToVector

simonh(Posted 2006) [#1]
Right, rather than derail the 'XEdition' thread I'll start a new topic. The aim - to create a working AlignToVector function.

Here's my attempt:

	Function AlignToVector(vx#,vy#,vz#,axis,rate#=1.0)
	
		Local pitch#=Abs(EntityPitch())
		Local yaw#=Abs(EntityYaw())
		Local roll#=Abs(EntityRoll())

		Select axis
		
			Case 1
			
				Local dest_yaw#=Abs(ATan2(vz#,vx#))
				Local dest_roll#=Abs(ATan2(vy#,vx#))
			
				yaw#=UpdateValue#(yaw#,dest_yaw#,rate#)
				roll#=UpdateValue#(roll#,dest_roll#,rate#)

			Case 2
				
				Local dest_pitch#=Abs(ATan2(vz#,vy#))
				Local dest_roll#=Abs(-ATan2(vx#,vy#))
			
				pitch#=UpdateValue#(pitch#,dest_pitch#,rate#)
				roll#=UpdateValue#(roll#,dest_roll#,rate#)

			Case 3
			
				Local dest_pitch#=Abs(-ATan2(vy#,vz#))
				Local dest_yaw#=Abs(-ATan2(vx#,vz#))
	
				pitch#=UpdateValue#(pitch#,dest_pitch#,rate#)
				yaw#=UpdateValue#(yaw#,dest_yaw#,rate#)

		End Select
		
		Self.RotateEntity pitch#,yaw#,roll#
	
	End Function
	
	Function UpdateValue#(current#,destination#,rate#)
	
		'rate#=1.0/rate#
	
		current#=current#+((destination#-current#)*rate#)
	
		Return current#
	
	End Function

And example code (BMX):

Import "../MiniB3D.bmx"

Graphics3D 640,480

' set this to 1, 2 Or 3
axis=1

' set vector
vx#=0.0
vy#=1.0
vz#=0.0

camera=CreateCamera()
PositionEntity camera,0,2,-5
RotateEntity camera,15,0,0

light=CreateLight()
RotateEntity light,90,0,0

cone=CreateCone()

xaxis=CreateCylinder(8,True,cone)
RotateMesh xaxis,0,0,90
ScaleMesh xaxis,5.0,0.2,0.2
EntityColor xaxis,127,0,0

yaxis=CreateCylinder(8,True,cone)
ScaleMesh yaxis,0.2,5.0,0.2
EntityColor yaxis,0,127,0

zaxis=CreateCylinder(8,True,cone)
RotateMesh zaxis,90,0,0
ScaleMesh zaxis,0.2,0.2,5.0
EntityColor zaxis,0,0,127

marker=CreateSphere()
ScaleEntity marker,0.2,0.2,0.2
PositionEntity marker,vx#,vy#,vz#

' change color of marker depending on axis selected
Select axis
	Case 1 EntityColor marker,255,0,0	
	Case 2 EntityColor marker,0,255,0
	Case 3 EntityColor marker,0,0,255
End Select

While Not KeyDown(KEY_ESCAPE)
	
	AlignToVector cone,vx,vy,vz,axis,0.01

	RenderWorld
	
	glColor3f 255,0,0
	Text 0,0,"X"
	glColor3f 0,255,0
	Text 0,20,"Y"
	glColor3f 0,0,255
	Text 0,40,"Z"
	
	Flip
	
Wend

End

Function Text(x,y,text$)

	' reset texture matrix
	glMatrixMode(GL_TEXTURE)		
	glLoadIdentity()
		
	' set active texture to texture 0 so gldrawtext will work correctly
	glActiveTextureARB(GL_TEXTURE0)
	glClientActiveTextureARB(GL_TEXTURE0)
	
	' enable texture 2D
	glEnable(GL_TEXTURE_2D)
	
	glDisable(GL_LIGHTING)

	GLDrawText text$,x,y
	
	glEnable(GL_LIGHTING)
	
	' disable texture 2D - needed as gldrawtext enables it, but doesn't disable after use
	glDisable(GL_TEXTURE_2D)
	
End Function


Example code (B3D):

Graphics3D 640,480

; set this to 1, 2 or 3
axis=3

; set vector
vx#=0.0
vy#=1.0
vz#=0.0

camera=CreateCamera()
PositionEntity camera,0,2,-5
RotateEntity camera,15,0,0

light=CreateLight()
RotateEntity light,90,0,0

cone=CreateCone()

xaxis=CreateCylinder(8,True,cone)
RotateMesh xaxis,0,0,90
ScaleMesh xaxis,5.0,0.2,0.2
EntityColor xaxis,127,0,0

yaxis=CreateCylinder(8,True,cone)
ScaleMesh yaxis,0.2,5.0,0.2
EntityColor yaxis,0,127,0

zaxis=CreateCylinder(8,True,cone)
RotateMesh zaxis,90,0,0
ScaleMesh zaxis,0.2,0.2,5.0
EntityColor zaxis,0,0,127

marker=CreateSphere()
ScaleEntity marker,0.2,0.2,0.2
PositionEntity marker,vx#,vy#,vz#

; change color of marker depending on axis selected
Select axis
	Case 1 EntityColor marker,255,0,0	
	Case 2 EntityColor marker,0,255,0
	Case 3 EntityColor marker,0,0,255
End Select

While Not KeyDown(1)
	
	AlignToVector cone,vx,vy,vz,axis,0.01

	RenderWorld
	
	Color 255,0,0
	Text 0,0,"X"
	Color 0,255,0
	Text 0,20,"Y"
	Color 0,0,255
	Text 0,40,"Z"
	
	Flip
	
Wend

End


The bmx version must work the same as the b3d version. The above version works some of the time, but some vector inputs won't work - such as x=0,y=-1,0,z=0.0,axis=2.

Also, don't forget that this command can be used twice or three times to combine the axis rotations.


Amon(Posted 2006) [#2]
Ahhh! Thanks very much Simon. I appreciate you helping us. I can't test it myself but I'm sure antony will pop in to have a look at it.

Again, Thank You very much for your help. :)


AntonyWells(Posted 2006) [#3]
Good start, and thanks for helping out on the cause. We'll have a bump-mapped 3d engine in max oneday.

Not sure why yours doesn't work all the time, but if it works some of the time it must be on the right track.

Any chance mark will let just you sneak a peak at his aligntovector code to write us a version? No worries if not, just seems like the ideal solution.


FlameDuck(Posted 2007) [#4]
The aim - to create a working AlignToVector function.
Isn't AlignToVector simply a SLERP? Thus, doesn't it stand to reason thst your version doesn't work, because it's using Euler angle, and thus prone to gimbal lockage?


Floyd(Posted 2007) [#5]
When the 'rate' parameter was added to AlignToVector I was curious about what it really meant.
Some experimenting suggested it was doing this:

1. The axis to be aligned and the target vector determine a plane.
2. The entity turns about an axis perpendicular to this plane.
3. The rate gives the fraction of the "angle difference" to turn.

This last part means that a rate of 0.5 will turn half the way to the target.
Graphics3D 500, 400, 0, 2
SetBuffer FrontBuffer()

piv = CreatePivot() : TurnEntity piv, 0, 160, 0

For n = 1 To 5
	Print EntityYaw( piv )
	AlignToVector piv, 0, 0, 1,    3, 0.5   ; turn half the way to the target
Next

WaitKey : End

One possible glitch arises if the original axis and the target vector point in exactly opposite directions. In that case they do not determine a plane and the problem become ill-defined. Try changing 160 to 180 in the example.


JoshK(Posted 2007) [#6]
I just did a small test with some terrain I am working on. The Y axis worked when I got rid of the Abs().

For smooth angular interpolation, you have to use quaternions and perform a slerp routine.


-=TinBlue=-(Posted 2007) [#7]
Perhaps I'm being thick but the code submitted at the start of the thread doesn't work.

Compile Error: To Many Function Parameters


Matty(Posted 2009) [#8]
Was align to vector ever added to minib3d?
It's a very useful function...I used it all the time in blitz3d? Great for AI units in space combat sims.


Warner(Posted 2009) [#9]
I have written an AlignToVector function for my mod, but I'm not sure if it will work with the standard minib3d version.


TMatrix.bmx:



Romanski(Posted 2009) [#10]
something is strange... is there any fix for this?


Robert Cummings(Posted 2010) [#11]
bump :)

Looking for a simple AlignToVector (2) that I can port to iminib3d too otherwise I can't get it running on pc/mac as well as the ipad...

If its simple maths I can port to C++ no problem but the above uses a different TMatrix...


Warner(Posted 2010) [#12]
That's somewhat difficult, because I believe you need matrices to do that right. Here is what I tried:


Demo:



_Skully(Posted 2010) [#13]
what JoshK said


Robert Cummings(Posted 2010) [#14]
Thanks for the attempt Warner! I tried your code for AlignToVector but it won't align to the normal unfortunately. I'm just not sure why either! I would like to try and get an object to stand on a small sphere like super mario galaxy.

Thank you for the demo though, I will keep trying?


Whats happening is the character just turns away, is it possible it is mixing up a couple of numbers?

Last edited 2010


ima747(Posted 2010) [#15]
Define turns away? Is it always flipped along 1 axis, or does it change at some points? OpenGl uses some inverted numbers in it's matrixies which could potentially be a factor depending on how they are applied to the existing matrix for the object...


Warner(Posted 2010) [#16]
[edit]I think I see what you mean. Here is a slightly modified version:


Last edited 2010


Robert Cummings(Posted 2010) [#17]
Wow that looks like it does the trick! I don't know how to thank you :)


Warner(Posted 2010) [#18]
No problem, I do hope it suffices for what you need it for. The 'fix' line starts with if 'y < 0'. Could turn out that should be 'if y<=0' instead.

Last edited 2010