Rotating groups of objects?

BlitzMax Forums/BlitzMax Programming/Rotating groups of objects?

Diordna(Posted 2004) [#1]
I don't want to rotate a single line, I want to rotate a group of objects, for example a group of lines that make up a single bezier curve, or a player's ship. Using setrotation, of course, rotates each individual line and makes things look screwy. Any way to get around this? I haven't been able to use sethandle to my advantage, but maybe there's a way with that.


flying willy(Posted 2004) [#2]
Take each object and find the center of all the objects.
CenterX and CenterY should then be plugged into SetHandle.

Now Rotate all your objects, and they should all rotate relative to each other.

By changing handle, you can do quite a few nifty little effects.


Diordna(Posted 2004) [#3]
Graphics 640,480,0

Repeat
Cls
SetHandle(MouseX(),MouseY())
SetRotation(a)
a:+1
drawbezier(100,100,200,100,300,300,200,300,255,255,255)
Flip
Until KeyHit(key_escape)

Function drawbezier(x1,y1,vx1,vy1,x2,y2,vx2,vy2,r=0,g=0,b=0,drawHandles=False)
SetColor(r,g,b)
If drawHandles=True Then
DrawOval(vx1-2,vy1-2,4,4)
DrawOval(vx2-2,vy2-2,4,4)
DrawLine(x1,y1,vx1,vy1)
DrawLine(x2,y2,vx2,vy2)
End If
Local lastx#=x1
Local lasty#=y1
For t#=0 To 1 Step.01
pointx# = x1*(1-t)^3 + 3*vx1*(1-t)^2*t + 3*vx2*(1-t)*t^2 + x2*t^3
pointy# = y1*(1-t)^3 + 3*vy1*(1-t)^2*t + 3*vy2*(1-t)*t^2 + y2*t^3
DrawLine(pointx#,pointy#,lastx#,lasty#)
lastx#=pointx#
lasty#=pointy#
Next
End Function


ImaginaryHuman(Posted 2004) [#4]
You can do it by changing the handle as described above. Alternatively, here's my guess at what happens.

In OpenGL, which the BlitzMax graphics are based on, there is a coordinate system XYZ which can of course be rotated, translated, scaled, etc, and you make one change to it at a time. So if you do a rotation, say, then any lines or shapes or whatever that you draw afterwards are drawn with that rotation, until you change it to something else. However, I am guessing that with each CALL to rotate or scale or whatever, BlitzMax pushes the current settings onto the stack, does the rotation of a single object relative to a totally unrotated coordinate system, then pops the original settings back off the stack at the end. So then the next object comes along and it does it all over again starting from scratch. So what you're up against is probably actuall the way BlitzMax has implemented handling objects as separate, rather than being able to know that you might want to keep a certain rotation and apply it to all upcoming object drawing. That's my guess anyway. You could directly access OpenGL to set the rotation and such, not using the BlitzMax calls, and it should apply to all objects so long as Blitzmax doesn't reset it all for each object.


Dreamora(Posted 2004) [#5]
the "setrotation" is exactly this matrix setting you are talking about ...
and I think what the "sethandle" does is modifying the object space matrix according this values ( at least from what it behaves on draws afterwards )as you described above ...


ImaginaryHuman(Posted 2004) [#6]
I agree. What I'm not sure but suspect is that there is some re-setting of the matrix as you begin to draw each object so that each one acts independently. In normal OpenGL, without that added functionality, you could set the rotation and translation, draw a whole bunch of objects, and then undo the settings. ... but, to implement handles you'd need to do local translating as well anyway. So maybe SetImageHandle is best.


Diordna(Posted 2004) [#7]
But I'm not using images...


ImaginaryHuman(Posted 2004) [#8]
Oh, well Images are draw in the position of a polygon, so image or not the same still applies


skn3(Posted 2004) [#9]
framework brl.glmax2d
	
Type position
	Global rootlist:Tlist

	Field x:Float=0.0,y:Float=0.0
	Field radius:Float=0.0,angle:Float=0.0
	Field root:position=Null,parent:position=Null
	Field child:Tlist = CreateList()
	
	Function Create:position(x:Float,y:Float,parent:position=Null)
		'create a new position object and attatch it to the correct list
		Local position:position = New position
		
		'setup
		position.x = x
		position.y = y
		
		'check if this position should be parented to another position
		If parent <> Null
			'insert into parent child list
			ListAddLast(parent.child,position)
			'set parent link
			position.parent = parent
			'set root link
			position.root = parent.root
			'calulate initial angle and raidus of child
			position.CalculateVector()
		Else
			'insert into global list
			ListAddLast(position.rootlist,position)
			'set root link to self
			position.root = position
		End If
		
		'return created position
		Return position
	End Function
	
	Method New()
		'check to see if rootlist needs to be initiated
		If position.rootlist = Null position.rootlist = CreateList()
	End Method
	
	Method Turn(angle:Float)
		For Local child:position = EachIn Self.child
			child.angle:+angle
			child.x = Self.x+Cos(child.angle)*child.radius
			child.y = Self.y+Sin(child.angle)*child.radius
			child.Turn(angle)
		Next
	End Method
	
	Method Update()
		'update for this position
		If Self.parent DrawLine Self.x,Self.y,Self.parent.x,Self.parent.y
		DrawOval Self.x-5,Self.y-5,10,10
		'update children of position
		For Local child:position = EachIn Self.child
			child.Update()
		Next
	End Method
	
	Method CalculateVector()
		'calculate radius and angle based on parent -> self offset
		Self.angle:Float = ATan2(Self.y-Self.parent.y,Self.x-Self.parent.x)
		If Self.angle < 0 Self.angle = 360:Float + Self.angle
		Self.radius:Float = Sqr((Self.x-Self.parent.x)^2 + (Self.y-Self.parent.y)^2)
	End Method
End Type

Graphics 640,480,32,60

parent:position = position.create(320,240)
	child1:position = position.create(320,140,parent)
		child1ofchild1:position = position.create(320,90,child1)
		child2ofchild1:position = position.create(270,140,child1)
		child3ofchild1:position = position.create(370,140,child1)
		child4ofchild1:position = position.create(320,190,child1)
	child2:position = position.create(220,240,parent)
		child1ofchild2:position = position.create(220,190,child2)
		child2ofchild2:position = position.create(170,240,child2)
		child3ofchild2:position = position.create(270,240,child2)
		child4ofchild2:position = position.create(220,290,child2)
	child3:position = position.create(420,240,parent)
		child1ofchild3:position = position.create(420,190,child3)
		child2ofchild3:position = position.create(370,240,child3)
		child3ofchild3:position = position.create(470,240,child3)
		child4ofchild3:position = position.create(420,290,child3)
	child4:position = position.create(320,340,parent)
		child1ofchild4:position = position.create(320,290,child4)
		child2ofchild4:position = position.create(270,340,child4)
		child3ofchild4:position = position.create(370,340,child4)
		child4ofchild4:position = position.create(320,390,child4)

While KeyHit(KEY_ESCAPE) = False
	Cls
	parent.Turn(1)
	child1.Turn(-2)
	child2.Turn(-2)
	child3.Turn(-2)
	child4.Turn(-2)
	parent.Update()
	Flip
Wend



Hotcakes(Posted 2004) [#10]
Hey, look! Some code!


Jeremy Alessi(Posted 2004) [#11]
Hmmm... can't copy and paste the code into BlitzMax correctly ... it comes out in 1 line no matter which method I use to copy and paste or which way I highlight it.