Rotating a quad(?)

Blitz3D Forums/Blitz3D Programming/Rotating a quad(?)

EOF(Posted 2004) [#1]
Anybody got a quick/simple routine which can rotate a quad (set of 4 verts) in the same way as RotateImage works?

This example code creates a bunch of quads in a single-surface container. You can move one of the quads around with the mouse. Press [W] to toggle wireframe view.

This is how the quads are contructed and displayed on screen:

The quad verts are located at 2d pixel coordinates.
Each quad has a custom type holding the quads surface (container), vertex index number (top/left), and size (in pixels).

I'm sure there was a function posted which rotated a set of quads using Sin()/Cos()

NB: See the RotateQuad function

; Quad - Rotate?

Const sw=640,sh=480

Graphics3D sw,sh,0,2
SetBuffer BackBuffer()
HidePointer

Type quadtype
	Field container  ; conainter holding quad (surface)
	Field vert       ; quads first vertex in container
	Field w,h        ; quads width and height (in 2d pixels)
End Type

; init 3d display (camera + quads pivot)
spritecamera=CreateCamera()
pivot2d=CreatePivot(spritecamera)
aspect#=Float(GraphicsHeight())/Float(GraphicsWidth())
scale#=2.0/GraphicsWidth()
PositionEntity pivot2d,-1,aspect,1.0001
ScaleEntity pivot2d,scale,scale,scale

; create a quad containter (surface)
quadsurf=CreateQuadContainer(pivot2d)

; add random quads to container
For num=1 To 50
	NewQuad quadsurf,Rand(sw),Rand(sh),Rand(64),Rand(64),Rand(100),Rand(100),Rand(100)
Next
; add quad to container (pos=0,0 size=90x80 color=green)
quad1=NewQuad(quadsurf , 0,0 , 90,80 , $04,$f2,$07)

MoveMouse 320,240


; MAIN LOOP
Repeat

	If KeyHit(17) ; [W]
		w=Not w
		WireFrame w
	EndIf

	If KeyHit(57) ; [SPACE]
		RotateQuad quad1, Rand(360)
	EndIf

	mx=MouseX() :	my=MouseY()
	PositionQuad quad1,mx,my,0

	RenderWorld

	Text 20,40,"[MOUSE] = move large green quad"
	Text 20,60,"[W] = Wireframe"
	Text 20,80,"[SPACE] = Rotate quad"
	
	Line mx,my+8,mx,my-8
	Line mx+8,my,mx-8,my

	Flip

Until KeyHit(1)

End


; create a container (surface) for holding quads
Function CreateQuadContainer(pivot)
	Local quadmesh=CreateMesh(pivot)
	Local surf=CreateSurface(quadmesh)
	EntityFX quadmesh,1+2
	ScaleEntity quadmesh,1,-1,1
	PositionEntity quadmesh,-0.5,0.5,0
	Return surf
End Function

; adds a new quad to an existing container
Function NewQuad(surf,x,y,w,h,r=255,g=255,b=255)
	Local q.quadtype=New quadtype
	q\container=surf
	q\w=w : q\h=h
	q\vert=AddVertex(surf,x,y,0)
	AddVertex surf,x+w,y,0
	AddVertex surf,x,y+h,0
	AddVertex surf,x+w,y+h,0
	AddTriangle surf,q\vert+0,q\vert+1,q\vert+2
	AddTriangle surf,q\vert+3,q\vert+2,q\vert+1
	For o=0 To 3
		VertexColor surf,q\vert+o,r,g,b
	Next
	Return Handle(q)
End Function

; position a quad at 2d pixel coordinates
Function PositionQuad(qindex,x,y,z#=1.0001)
	Local q.quadtype=Object.quadtype(qindex)
	Local s=q\container , v=q\vert
	dx#=x-VertexX(s,v) : dy#=y-VertexY(s,v) :	dz#=z-VertexZ(s,v)
	For o=0 To 3
		VertexCoords s,v+o,VertexX(s,v+o)+dx,VertexY(s,v+o)+dy,VertexZ(s,v+o)+dz
	Next
End Function

; rotate a quad set
Function RotateQuad(qindex,ang)
	Local q.quadtype=Object.quadtype(qindex)
	Local s=q\container , v=q\vert
	; not sure how to do this part ?????????????
	For o=0 To 3
		;; dx#=? : dy#=?
		VertexCoords s,v+o,VertexX(s,v+o)+dx,VertexY(s,v+o)+dy,VertexZ(s,v+o)
	Next
End Function



Bouncer(Posted 2004) [#2]
for each vertex:

new_x = x * cos(angle) - y * sin(angle)
new_y = x * sin(angle) + y * cos(angle)

don't remember the z ...

oh and this rotates around a center point so x and y values are distances from the quad center. So store these values and add your quads location to them after a rotate.


Stevie G(Posted 2004) [#3]
Is this what you need ..

; rotate a quad set
Function RotateQuad(qindex,ang)
	Local q.quadtype=Object.quadtype(qindex)
	Local s=q\container , v=q\vert
	; not sure how to do this part ?????????????
	For o=0 To 3
		dx# = VertexX(s,v+o)*Cos(ang)-VertexY(s,v+o)*Sin(ang)
		dy# = VertexY(s,v+o)*Cos(ang)+VertexX(s,v+o)*Sin(ang)
		VertexCoords s,v+o,dx,dy,VertexZ( s,v+o)
	Next
End Function



Warren(Posted 2004) [#4]
I took the route of using a pivot point. I rotate the pivot point to where I want it to be and then transform the verts of the quad into the pivots coordinate space. Works pretty well. The variable names won't make sense to you guys, but basically:

RotateEntity( GRendererVars\Pivot, 0, 0, InAngle# )
		
TFormPoint( X0#, Y0#, 0, GRendererVars\Pivot, 0 ) : X0# = TFormedX() : Y0# = TFormedY()
TFormPoint( X1#, Y1#, 0, GRendererVars\Pivot, 0 ) : X1# = TFormedX() : Y1# = TFormedY()
TFormPoint( X2#, Y2#, 0, GRendererVars\Pivot, 0 ) : X2# = TFormedX() : Y2# = TFormedY()
TFormPoint( X3#, Y3#, 0, GRendererVars\Pivot, 0 ) : X3# = TFormedX() : Y3# = TFormedY()



EOF(Posted 2004) [#5]
Brilliant help!

Epic,
I previously used a similar approach to yours but maybe not as elegant. I used a dumming quad, rotated it with RotateMesh, then copied the vert positions to the real quad to be rotated.