Page 1 of 1

scale sprite 3d

Posted: Sun Jul 01, 2012 9:42 pm
by superadnim
how can i scale a sprite3d down in width so it's not square anymore? i tried using TransformSprite3D but the help document isnt very helpful

worth noting: i have to rotate the sprite and they are of course textured

i dont want to use external libraries if possible

thanks

Re: scale sprite 3d

Posted: Sun Jul 01, 2012 11:06 pm
by Danilo
superadnim wrote:how can i scale a sprite3d down in width so it's not square anymore?
ZoomSprite3D(#Sprite, NewWidth, NewHeight)

Code: Select all

  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)
      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))
        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()
        ZoomSprite3D(0,zoomX,zoomY)
        ;RotateSprite3D(0,3,#PB_Relative)
        DisplaySprite3D(0, 400-zoomX*0.5, 300-zoomY*0.5)
        Stop3D()
    EndIf
    zoomX + direction
    If zoomX > 300  : direction = -2 : EndIf
    If zoomX < 20   : direction =  2 : EndIf
    Delay(1)
  ForEver

Re: scale sprite 3d

Posted: Mon Jul 02, 2012 12:42 am
by superadnim
hi thanks!

the problem is that the transformation matrix seems to be pushed or something because i cant get the effect im after by calling ZoomSprite3D and then RotateSprite3D

i have square images that need to be sized down in one axis so i can get a iso effect when i rotate it (so i would scale it down by height not width but i need to perform both actions anyway)

thats the reason why i think the only way of doing it is through TransformSprite3D but i dont know how

in legacy opengl you would push or pop the matrix off the stack to achieve what im after

Re: scale sprite 3d

Posted: Mon Jul 02, 2012 2:53 am
by Danilo
I think I know what you want:

Code: Select all

  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)
      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))

        For y = 0 To 64 Step 4
            LineXY(0,y,64,y,RGB($00,$FF,$FF))
        Next y

        LineXY( 0,0,64,64,RGB($00,$00,$FF))
        ;LineXY(63,0, 0,63,RGB($00,$00,$FF))
        LineXY(64,0, 0,64,RGB($00,$00,$FF))
        ;LineXY(65,0, 0,65,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()
        TransformSprite3D(0,   0,0,   64,0,   64,64,   0,64)
        DisplaySprite3D(0,0,0)
        
    
        TransformSprite3D(0,   200,175,   300,175,   200,200,   100,200)
        DisplaySprite3D(0,0,0)

        TransformSprite3D(0,   400,175,   800,175,   500,275,   100,275)
        DisplaySprite3D(0,0,0)

        Stop3D()
    EndIf
    Delay(1)
  ForEver
TransformSprite3D() + DisplaySprite3D(#Sprite,0,0) display the sprite exactly at the co-ordinates pairs (x,y)
of TransformSprite3D().
Unfortunately I don't know more about TransformSprite3D() and I don't understand the 'z' parameter myself, as it is not documented
and I think the PB developers can't explain it themselves.
Zoom and Rotate don't seem to work together with TransformSprite3D(). So I am sorry, can't help.

Re: scale sprite 3d

Posted: Mon Jul 02, 2012 3:07 am
by xorc1zt
the best i can do :( only work with directx, look like opengl has zbuffer not activated.

Code: Select all

Procedure RotateSprY(spriteId.i, width.i, height.i, angle.f )
    Define sine.f
    Define cosine.f
    Define x.f
    Define z.f
    
    angle  = Radian(angle)
    sine = Sin( angle )
    cosine = Cos( angle )
    
    ; Y rotation:
    ; _______________________________     _
    ;|cos(angle)    0   -sin(angle)  | * |x|
    ;|0             1   0            |   |y|
    ;|sin(angle)    0   cos(angle)   |   |z|
    ; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯     ¯
    
    x = (1 * cosine) - (width * sine )
    z = (1 * sine) + (width * cosine)
    
    If (x>0.0)
        TransformSprite3D(spriteId, 0, 0, 100, x, 0, 100+z, x, height, 100+z, 0, height, 100)
    Else
        TransformSprite3D(spriteId, x, 0, 100+z, 0, 0, 100, 0, height, 100, x, height, 100+z)
    EndIf
EndProcedure

Re: scale sprite 3d

Posted: Mon Jul 02, 2012 3:31 am
by superadnim
thanks for your help guys

xorc1zt: im not sure how your code works :( but what im trying to do is rotate a sprite 45 degrees and then squish it pretty much by half so it looks like an isometric sprite the trick is that when you rotate this sprite it has to rotate around this plane but because pb rotation and scale functions do the transformation separately it doesnt work hence why i think the only way to do it natively is by using TransformSprite3D

if i do it with the native functions the scaling is performed separately and what i get is a rotating rectangle instead of what should look like an isometric sprite

otherwise is it possible to change the view matrix or some other transformation to 'abuse' the native engine?

Re: scale sprite 3d

Posted: Mon Jul 02, 2012 3:47 am
by xorc1zt
this ?

Code: Select all

Macro MakeSpriteIso(spriteID, width, height)
    TransformSprite3D(spriteId, 0, height/2, 1, width/2, 0, 1, width, height/2, 1, width/2, height, 1)
EndMacro

;alternative
Macro MakeSpriteIso2(spriteID, width, height)
    TransformSprite3D(spriteId, width/2, 0, 1, width, height/2, 1, width/2, height, 1, 0, height/2, 1)
EndMacro

Re: scale sprite 3d

Posted: Mon Jul 02, 2012 4:42 am
by superadnim
this has no effect if we use the rotation function it must all be integrated otherwise each function cancels each other out

Re: scale sprite 3d

Posted: Mon Jul 02, 2012 4:44 am
by Demivec
I think one of these two are what you are after:

Code: Select all

;iso rotated left 45 degrees
Macro MakeSpriteIso(spriteID, width, height)
  TransformSprite3D(spriteID, 0, height/4, width/2,  0,  width, height/4,  width/2, height/2)
EndMacro

;iso rotated right degrees
Macro MakeSpriteIso2(spriteID, width, height)
  TransformSprite3D(spriteID, width/2, 0,  width, height/4,  width/2, height/2,  0, height/4)
EndMacro

Re: scale sprite 3d

Posted: Mon Jul 02, 2012 5:08 am
by superadnim
thanks but no i want to perform arbitrary rotation on objects not just fixed

Re: scale sprite 3d

Posted: Tue Jul 03, 2012 1:11 am
by Demivec
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

Re: scale sprite 3d

Posted: Tue Jul 03, 2012 1:43 am
by superadnim
ohh this works! thanks!

although if we use opengl then it doesnt work properly :( but it does in dx

strange thing it looks like theres an issue with the vertices not just the UV coords in fact those are fine in OGL but the vertices arent