Rotating groups of objects?
BlitzMax Forums/BlitzMax Programming/Rotating groups of objects?
| ||
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. |
| ||
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. |
| ||
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 |
| ||
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. |
| ||
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 ... |
| ||
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. |
| ||
But I'm not using images... |
| ||
Oh, well Images are draw in the position of a polygon, so image or not the same still applies |
| ||
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 |
| ||
Hey, look! Some code! |
| ||
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. |