superadnim wrote:thanks but no i want to perform arbitrary rotation on objects not just fixed
Try this:
Code: Select all
Structure Point_f
x.f
y.f
EndStructure
;iso rotated right degrees
Procedure MakeSpriteIsoRight(spriteID, width, height, cx, cy, degree, newWidth, newHeight)
Protected.Point_f p1, p2, p3, p4
Protected.f wf = width / newWidth, hf = height / newHeight
If degree = 0
p1\x = (( -cx) / wf) - 0.5: p1\y = (( -cy) / hf) - 0.5
p2\x = ((width - cx) / wf) - 0.5: p2\y = (( -cy) / hf) - 0.5
p3\x = ((width - cx) / wf) - 0.5: p3\y = ((height - cy) / hf) - 0.5
p4\x = (( -cx) / wf) - 0.5: p4\y = ((height - cy) / hf) - 0.5
Else
Protected.f angCos = Cos(Radian(degree)), angSin = Sin(Radian(degree))
v1 = -cx * angCos: v3 = -cy * angSin
v2 = -cx * angSin: v4 = -cy * angCos
v6 = (width - cx) * angCos: v7 = (height - cy) * angSin
v5 = (width - cx) * angSin: v8 = (height - cy) * angCos
p1\x = ((v1 - v3) / wf) - 0.5: p1\y = ((v4 + v2) / hf) - 0.5
p2\x = ((v6 - v3) / wf) - 0.5: p2\y = ((v4 + v5) / hf) - 0.5
p3\x = ((v6 - v7) / wf) - 0.5: p3\y = ((v8 + v5) / hf) - 0.5
p4\x = ((v1 - v7) / wf) - 0.5: p4\y = ((v8 + v2) / hf) - 0.5
EndIf
TransformSprite3D(spriteID, p1\x, p1\y, p2\x, p2\y, p3\x, p3\y, p4\x, p4\y)
EndProcedure
;iso rotated left 45 degrees
Procedure MakeSpriteIsoLeft(spriteID, width, height, cx, cy, degree, newWidth, newHeight)
MakeSpriteIsoRight(spriteID, width, height, cx, cy, 360 - degree, newWidth, newHeight)
EndProcedure
If InitSprite() = 0 Or InitSprite3D() = 0
MessageRequester("Error", "Can't open screen & sprite enviroment!", 0)
End
EndIf
If OpenWindow(0, 0, 0, 800, 600, "Sprite3D", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
If OpenWindowedScreen(WindowID(0), 0, 0, 800, 600, 0, 0, 0)
CreateSprite(0, 64, 64, #PB_Sprite_Texture)
LoadFont(0, "Arial", 36)
If StartDrawing(SpriteOutput(0))
Box(0,0,64,64,RGB($FF,$FF,$00))
; DrawingMode(#PB_2DDrawing_Outlined)
; Box(0,0,64,64,RGB($00,$00,$FF))
; LineXY( 0,0,64,64,RGB($00,$00,$FF))
; LineXY(64,0, 0,64,RGB($00,$00,$FF))
DrawingMode(#PB_2DDrawing_Outlined)
DrawingFont(FontID(0))
DrawText(0,0,"PB",RGB($FF,$00,$00))
Box(0,0,64,64,RGB($00,$00,$FF))
LineXY( 0,0,64,64,RGB($00,$00,$FF))
LineXY(64,0, 0,64,RGB($00,$00,$FF))
StopDrawing()
EndIf
CreateSprite3D(0,0)
Else
MessageRequester("Error", "Can't open windowed screen!", 0)
End
EndIf
EndIf
direction = 2
zoomX = 64
zoomY = 64
Repeat
Repeat
event = WindowEvent()
Select event
Case #PB_Event_CloseWindow
End
EndSelect
Until event = 0
FlipBuffers()
ClearScreen(RGB($40, $40, $40))
If Start3D()
MakeSpriteIsoLeft(0, 64, 64, 32, 32, 0, 64, 64) ;normal
DisplaySprite3D(0, 100, 100)
MakeSpriteIsoLeft(0, 64, 64, 32, 32, angle, 64, 32) ;squished vertically
DisplaySprite3D(0, 200-zoomX*0.5, 300-zoomY*0.5)
MakeSpriteIsoLeft(0, 64, 64, 32, 32, angle, 32, 64) ;squished horizontally
DisplaySprite3D(0, 300-zoomX*0.5, 300-zoomY*0.5)
MakeSpriteIsoRight(0, 64, 64, 32, 32, angle, 2 * zoomX, 1 * zoomX) ;squished vertically and zoomed
DisplaySprite3D(0, 700-zoomX*0.5, 300-zoomY*0.5)
MakeSpriteIsoRight(0, 64, 64, 32, 32, angle, 1 * zoomX, 2 * zoomX) ;squished horizontally and zoomed
DisplaySprite3D(0, 500-zoomX*0.5, 300-zoomY*0.5)
MakeSpriteIsoLeft(0, 64, 64, 32, 32, angle, 64, 20 + zoomX / 2) ;squishiness varying vertically
DisplaySprite3D(0, 200, 500)
MakeSpriteIsoLeft(0, 64, 64, 32, 32, angle, 20 + zoomX / 2, 64) ;squishiness varying horizontally
DisplaySprite3D(0, 300, 500)
Stop3D()
EndIf
angle + 1: If angle > 360: angle = 0: EndIf
zoomX + direction
If zoomX > 100 : direction = -2 : EndIf
If zoomX < 20 : direction = 2 : EndIf
Delay(1)
ForEver
The demo above shows how you can compress the sprites horizontally and/or vertically and rotate them around an arbitrary point.
I worked out the transformation but ran into some slight calculation errors. I looked up some old code written by Kelebrindae that solved the problems I had. You will probably find some other functions he wrote helpful for sprite3D.
Here is the thread that had similar code to what I posted above.
I wrote it as a procedure but you may need or prefer to use it as a macro.
Here is an update of the previous code for PureBasic v5.20LTS:
Code: Select all
Structure Point_f
x.f
y.f
EndStructure
;iso rotated right degrees
Procedure MakeSpriteIsoRight(spriteID, width, height, cx, cy, degree, newWidth, newHeight)
Protected.Point_f p1, p2, p3, p4
Protected.f wf = width / newWidth, hf = height / newHeight
If degree = 0
p1\x = (( -cx) / wf) - 0.5: p1\y = (( -cy) / hf) - 0.5
p2\x = ((width - cx) / wf) - 0.5: p2\y = (( -cy) / hf) - 0.5
p3\x = ((width - cx) / wf) - 0.5: p3\y = ((height - cy) / hf) - 0.5
p4\x = (( -cx) / wf) - 0.5: p4\y = ((height - cy) / hf) - 0.5
Else
Protected.f angCos = Cos(Radian(degree)), angSin = Sin(Radian(degree))
v1 = -cx * angCos: v3 = -cy * angSin
v2 = -cx * angSin: v4 = -cy * angCos
v6 = (width - cx) * angCos: v7 = (height - cy) * angSin
v5 = (width - cx) * angSin: v8 = (height - cy) * angCos
p1\x = ((v1 - v3) / wf) - 0.5: p1\y = ((v4 + v2) / hf) - 0.5
p2\x = ((v6 - v3) / wf) - 0.5: p2\y = ((v4 + v5) / hf) - 0.5
p3\x = ((v6 - v7) / wf) - 0.5: p3\y = ((v8 + v5) / hf) - 0.5
p4\x = ((v1 - v7) / wf) - 0.5: p4\y = ((v8 + v2) / hf) - 0.5
EndIf
TransformSprite(spriteID, p1\x, p1\y, p2\x, p2\y, p3\x, p3\y, p4\x, p4\y)
EndProcedure
;iso rotated left 45 degrees
Procedure MakeSpriteIsoLeft(spriteID, width, height, cx, cy, degree, newWidth, newHeight)
MakeSpriteIsoRight(spriteID, width, height, cx, cy, 360 - degree, newWidth, newHeight)
EndProcedure
If InitSprite() = 0
MessageRequester("Error", "Can't open screen & sprite enviroment!", 0)
End
EndIf
If OpenWindow(0, 0, 0, 800, 600, "Sprite3D", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
If OpenWindowedScreen(WindowID(0), 0, 0, 800, 600, 0, 0, 0)
CreateSprite(0, 64, 64)
LoadFont(0, "Arial", 36)
If StartDrawing(SpriteOutput(0))
Box(0,0,64,64,RGB($FF,$FF,$00))
; DrawingMode(#PB_2DDrawing_Outlined)
; Box(0,0,64,64,RGB($00,$00,$FF))
; LineXY( 0,0,64,64,RGB($00,$00,$FF))
; LineXY(64,0, 0,64,RGB($00,$00,$FF))
DrawingMode(#PB_2DDrawing_Outlined)
DrawingFont(FontID(0))
DrawText(0,0,"PB",RGB($FF,$00,$00))
Box(0,0,64,64,RGB($00,$00,$FF))
LineXY( 0,0,64,64,RGB($00,$00,$FF))
LineXY(64,0, 0,64,RGB($00,$00,$FF))
StopDrawing()
EndIf
Else
MessageRequester("Error", "Can't open windowed screen!", 0)
End
EndIf
EndIf
direction = 2
zoomX = 64
zoomY = 64
Repeat
Repeat
Event = WindowEvent()
Select Event
Case #PB_Event_CloseWindow
End
EndSelect
Until Event = 0
FlipBuffers()
ClearScreen(RGB($40, $40, $40))
MakeSpriteIsoLeft(0, 64, 64, 32, 32, 0, 64, 64) ;normal
DisplaySprite(0, 100, 100)
MakeSpriteIsoLeft(0, 64, 64, 32, 32, angle, 64, 32) ;squished vertically
DisplaySprite(0, 200-zoomX*0.5, 300-zoomY*0.5)
MakeSpriteIsoLeft(0, 64, 64, 32, 32, angle, 32, 64) ;squished horizontally
DisplaySprite(0, 300-zoomX*0.5, 300-zoomY*0.5)
MakeSpriteIsoRight(0, 64, 64, 32, 32, angle, 2 * zoomX, 1 * zoomX) ;squished vertically and zoomed
DisplaySprite(0, 700-zoomX*0.5, 300-zoomY*0.5)
MakeSpriteIsoRight(0, 64, 64, 32, 32, angle, 1 * zoomX, 2 * zoomX) ;squished horizontally and zoomed
DisplaySprite(0, 500-zoomX*0.5, 300-zoomY*0.5)
MakeSpriteIsoLeft(0, 64, 64, 32, 32, angle, 64, 20 + zoomX / 2) ;squishiness varying vertically
DisplaySprite(0, 200, 500)
MakeSpriteIsoLeft(0, 64, 64, 32, 32, angle, 20 + zoomX / 2, 64) ;squishiness varying horizontally
DisplaySprite(0, 300, 500)
angle + 1: If angle > 360: angle = 0: EndIf
zoomX + direction
If zoomX > 100 : direction = -2 : EndIf
If zoomX < 20 : direction = 2 : EndIf
Delay(1)
ForEver
@Edit: Added an updated version for v5.20 LTS