
- ClipSprite3D
- CreateClippedSprite3D
- CopySprite3D
- SetSprite3DColor / GetSprite3DColor
- SetSprite3DAlpha / GetSprite3DAlpha
- MirrorSprite3D
- SetSprite3DSize (=> this function reset any rotation transforms)
- SetSprite3DHandle / GetSprite3DHandle (=> this function reset any rotation transforms)
- SetSprite3DAngle / GetSprite3DAngle
- Predefined BLEND mode ( NORMAL, LIGHT, SHADE, INVERT )
code based on these threads :
http://www.purebasic.fr/english/viewtopic.php?t=13605
http://www.purebasic.fr/english/viewtop ... ipsprite3d
Code: Select all
;{/// STRUCTURE AND CONSTANTS FOR SPRITE3D
Structure DDPIXELFORMAT
dwSize.l
dwFlags.l
dwFourCC.l
dwRGBBitCount.l
dwRBitMask.l
dwGBitMask.l
dwBBitMask.l
dwRGBAlphaBitMask.l
EndStructure
Structure DDCOLORKEY
dwColorSpaceLowValue.l
dwColorSpaceHighValue.l
EndStructure
Structure DDSCAPS2
dwCaps.l
dwCaps2.l
dwCaps3.l
dwCaps4.l
EndStructure
Structure DDSURFACEDESC2
dwSize.l
dwFlags.l
dwHeight.l
dwWidth.l
lPitch.l
dwBackBufferCount.l
dwRefreshRate.l
dwAlphaBitDepth.l
dwReserved.l
lpSurface.l
ddckCKDestOverlay.DDCOLORKEY
ddckCKDestBlt.DDCOLORKEY
ddckCKSrcOverlay.DDCOLORKEY
ddckCKSrcBlt.DDCOLORKEY
ddpfPixelFormat.DDPIXELFORMAT
ddsCaps.DDSCAPS2
dwTextureStage.l
EndStructure
Structure D3DTLVERTEX
sx.f
sy.f
sz.f
rhw.f
color.l
specular.l
tu.f
tv.f
EndStructure
;Standard Structure from PB
Structure PB_SPRITE3D
Texture.IDirectDrawSurface7; DirectDrawSurface7
Vertice.D3DTLVERTEX[4] ; The 4 vertices for the rectangle sprite
Width.w ; width set with ZoomSprite3D()
Height.w ; height set with ZoomSprite3D()
unknown.l
EndStructure
;Custom Structure for new functions
Structure PB_SPRITE3D_PLUS
dist.f[4] ;//distance
a.f[4] ;//angle
EndStructure
;Available Blend Effects
CompilerIf Defined(D3DBLEND_ZERO, #PB_Constant)=0
#D3DBLEND_ZERO=1
#D3DBLEND_ONE=2
#D3DBLEND_SRCCOLOR=3
#D3DBLEND_INVSRCCOLOR=4
#D3DBLEND_SRCALPHA=5
#D3DBLEND_INVSRCALPHA=6
#D3DBLEND_DESTALPHA=7
#D3DBLEND_INVDESTALPHA=8
#D3DBLEND_DESTCOLOR=9
#D3DBLEND_INVDESTCOLOR=10
#D3DBLEND_SRCALPHASAT=11
#D3DBLEND_BOTHSRCALPHA=12
#D3DBLEND_BOTHINVSRCALPHA=13
CompilerEndIf
;Available Mirror Effects
CompilerIf Defined(PB_MirrorSprite3D_None, #PB_Constant)=0
#MirrorSprite3D_None=0
#MirrorSprite3D_Horizontal=1
#MirrorSprite3D_Vertical=2
#MirrorSprite3D_Both=#MirrorSprite3D_Horizontal | #MirrorSprite3D_Vertical
CompilerEndIf
;}
;{/// CUSTOM SPRITE3D FUNCTIONS
ProcedureDLL.b MirrorSprite3D(Sprite3D, MirrorMode) ;Mirror 3D sprite image (returns TRUE if any changes)
Protected *Sprite3D.PB_SPRITE3D=IsSprite3D(Sprite3D)
Protected MirroringChanges.b=0
Protected IsMirrored.b
Protected DoMirroring.b
IsMirrored=*Sprite3D\Vertice[0]\tu>*Sprite3D\Vertice[1]\tu
DoMirroring=1 And MirrorMode & #MirrorSprite3D_Horizontal
If (DoMirroring And IsMirrored=0) Or (DoMirroring=0 And IsMirrored)
MirroringChanges=1
Swap *Sprite3D\Vertice[0]\tu, *Sprite3D\Vertice[1]\tu
Swap *Sprite3D\Vertice[2]\tu, *Sprite3D\Vertice[3]\tu
EndIf
IsMirrored=*Sprite3D\Vertice[0]\tv>*Sprite3D\Vertice[3]\tv
DoMirroring=1 And MirrorMode & #MirrorSprite3D_Vertical
If (DoMirroring And IsMirrored=0) Or (DoMirroring=0 And IsMirrored)
MirroringChanges=1
Swap *Sprite3D\Vertice[0]\tv, *Sprite3D\Vertice[3]\tv
Swap *Sprite3D\Vertice[1]\tv, *Sprite3D\Vertice[2]\tv
EndIf
ProcedureReturn MirroringChanges
EndProcedure
ProcedureDLL.b ClipSprite3D(Sprite3D, ClipX, ClipY, ClipWidth, ClipHeight) ;Add clip zone to the specified 3D sprite
Protected *Sprite3D.PB_SPRITE3D=IsSprite3D(Sprite3D)
If *Sprite3D=0 : ProcedureReturn 0 : EndIf
Protected *DDS.IDirectDrawSurface7=*Sprite3D\Texture
Protected DDSDESC.DDSURFACEDESC2
DDSDESC\dwSize=SizeOf(DDSURFACEDESC2)
Protected Result=*DDS\GetSurfaceDesc(DDSDESC)
If Result : ProcedureReturn 0 : EndIf
*Sprite3D\Vertice[0]\tu=ClipX/DDSDESC\dwWidth
*Sprite3D\Vertice[0]\tv=ClipY/DDSDESC\dwHeight
*Sprite3D\Vertice[1]\tu=(ClipX+ClipWidth)/DDSDESC\dwWidth
*Sprite3D\Vertice[1]\tv=ClipY/DDSDESC\dwHeight
*Sprite3D\Vertice[2]\tu=ClipX/DDSDESC\dwWidth
*Sprite3D\Vertice[2]\tv=(ClipY+ClipHeight)/DDSDESC\dwHeight
*Sprite3D\Vertice[3]\tu=(ClipX+ClipWidth)/DDSDESC\dwWidth
*Sprite3D\Vertice[3]\tv=(ClipY+ClipHeight)/DDSDESC\dwHeight
*Sprite3D\Vertice[0]\sx=0
*Sprite3D\Vertice[0]\sy=0
*Sprite3D\Vertice[0]\sz=0
*Sprite3D\Vertice[1]\sx=ClipWidth
*Sprite3D\Vertice[1]\sy=0
*Sprite3D\Vertice[1]\sz=0
*Sprite3D\Vertice[2]\sx=0
*Sprite3D\Vertice[2]\sy=ClipHeight
*Sprite3D\Vertice[2]\sz=0
*Sprite3D\Vertice[3]\sx=ClipWidth
*Sprite3D\Vertice[3]\sy=ClipHeight
*Sprite3D\Vertice[3]\sz=0
*Sprite3D\Width=ClipWidth
*Sprite3D\Height=ClipHeight
ProcedureReturn 1 ; return success
EndProcedure
ProcedureDLL.l CreateClippedSprite3D(Sprite3D, Sprite, ClipX, ClipY, ClipWidth, ClipHeight) ;Create a new 3D sprite with the selected area from 2D sprite
Protected res=CreateSprite3D(Sprite3D, Sprite)
If Sprite3D=#PB_Any : Sprite3D=res : EndIf
If res And ClipX<>#PB_Ignore
ClipSprite3D(Sprite3D, ClipX, ClipY, ClipWidth, ClipHeight)
EndIf
ProcedureReturn res
EndProcedure
ProcedureDLL.l CopySprite3D(Sprite3D1, Sprite3D2) ;Copy the #Sprite3D1 to #Sprite3D2
Protected *Sprite3D1.PB_SPRITE3D=IsSprite3D(Sprite3D1)
If *Sprite3D1=0 : ProcedureReturn 0 : EndIf
Protected Sprite=CreateSprite(#PB_Any, 1, 1, #PB_Sprite_Texture)
If Sprite=0 : ProcedureReturn 0 : EndIf
Protected res=CreateSprite3D(Sprite3D2, Sprite)
If res=0 : FreeSprite(Sprite) : ProcedureReturn 0 : EndIf
If Sprite3D2=#PB_Any : Sprite3D2=res : EndIf
Protected *Sprite3D2.PB_SPRITE3D=IsSprite3D(Sprite3D2)
*Sprite3D2\Texture=*Sprite3D1\Texture
*Sprite3D2\Width=*Sprite3D1\Width
*Sprite3D2\Height=*Sprite3D1\Height
*Sprite3D2\unknown=*Sprite3D1\unknown
For i=0 To 3
*Sprite3D2\Vertice[i]\sx=*Sprite3D1\Vertice[i]\sx
*Sprite3D2\Vertice[i]\sy=*Sprite3D1\Vertice[i]\sy
*Sprite3D2\Vertice[i]\sz=*Sprite3D1\Vertice[i]\sz
*Sprite3D2\Vertice[i]\rhw=*Sprite3D1\Vertice[i]\rhw
*Sprite3D2\Vertice[i]\color=*Sprite3D1\Vertice[i]\color
*Sprite3D2\Vertice[i]\specular=*Sprite3D1\Vertice[i]\specular
*Sprite3D2\Vertice[i]\tu=*Sprite3D1\Vertice[i]\tu
*Sprite3D2\Vertice[i]\tv=*Sprite3D1\Vertice[i]\tv
Next
FreeSprite(Sprite)
ProcedureReturn *Sprite3D2
EndProcedure
ProcedureDLL FreeSprite3DParameters(Sprite3D);Free memory allocated for new Sprite3D parameters
Protected *Sprite3D.PB_SPRITE3D=IsSprite3D(Sprite3D)
If *Sprite3D\Vertice[3]\sz
FreeMemory(*Sprite3D\Vertice[3]\sz)
*Sprite3D\Vertice[3]\sz=0
EndIf
EndProcedure
ProcedureDLL SetSprite3DAlpha(Sprite3D, alpha) ;Set 3D sprite alpha (transparency 0 - 255)
Protected *Sprite3D.PB_SPRITE3D=IsSprite3D(Sprite3D)
alpha<<24
For i=0 To 3
*Sprite3D\Vertice[i]\color & $00FFFFFF+alpha
Next
EndProcedure
ProcedureDLL SetSprite3DColor(Sprite3D, color) ;Set 3D sprite color (RGB)
Protected *Sprite3D.PB_SPRITE3D=IsSprite3D(Sprite3D)
color=Blue(color)+(Green(color)<<8)+(Red(color)<<16)
For i=0 To 3
*Sprite3D\Vertice[i]\color & $FF000000+color
Next
EndProcedure
ProcedureDLL SetSprite3DHandle(Sprite3D, HandleX, HandleY) ;Set 3D sprite handle (X,Y)
Protected *Sprite3D.PB_SPRITE3D=IsSprite3D(Sprite3D)
*Sprite3D\Vertice[0]\sx=-HandleX
*Sprite3D\Vertice[0]\sy=-HandleY
*Sprite3D\Vertice[0]\sz=(HandleX);Trick
*Sprite3D\Vertice[1]\sx=-HandleX+*Sprite3D\Width
*Sprite3D\Vertice[1]\sy=-HandleY
*Sprite3D\Vertice[1]\sz=(HandleY);Trick
*Sprite3D\Vertice[2]\sx=-HandleX
*Sprite3D\Vertice[2]\sy=-HandleY+*Sprite3D\Height
;*Sprite3D\Vertice[2]\sz=(Rotation);Trick
*Sprite3D\Vertice[3]\sx=-HandleX+*Sprite3D\Width
*Sprite3D\Vertice[3]\sy=-HandleY+*Sprite3D\Height
;*Sprite3D\Vertice[3]\sz=*param.PB_SPRITE3D_PLUS
Protected *param.PB_SPRITE3D_PLUS=*Sprite3D\Vertice[3]\sz
If *param=0
*param=AllocateMemory(SizeOf(PB_SPRITE3D_PLUS))
*Sprite3D\Vertice[3]\sz=*param
EndIf
For i=0 To 3
*param\dist[i]=Sqr(Pow(*Sprite3D\Vertice[i]\sx, 2)+Pow(*Sprite3D\Vertice[i]\sy, 2))
If (*Sprite3D\Vertice[i]\sx=0)
*param\a[i]=ATan(*Sprite3D\Vertice[i]\sy/0.0000000001)
ElseIf *Sprite3D\Vertice[i]\sx>0
*param\a[i]=ATan(*Sprite3D\Vertice[i]\sy/*Sprite3D\Vertice[i]\sx)
Else
*param\a[i]=ATan(*Sprite3D\Vertice[i]\sy/*Sprite3D\Vertice[i]\sx)+#PI
EndIf
Next
EndProcedure
ProcedureDLL SetSprite3DHandlePoint(Sprite3D, *Handle.POINT) ;Set 3D sprite handle POINT
SetSprite3DHandle(Sprite3D, *Handle\x, *Handle\y)
EndProcedure
ProcedureDLL SetSprite3DSize(Sprite3D, Width, Height) ;Set 3D sprite size
Protected *Sprite3D.PB_SPRITE3D=IsSprite3D(Sprite3D)
*Sprite3D\Width=Width
*Sprite3D\Height=Height
SetSprite3DHandle(Sprite3D, *Sprite3D\Vertice[0]\sz, *Sprite3D\Vertice[1]\sz)
EndProcedure
ProcedureDLL SetSprite3DAngle(Sprite3D, Angle, Mode) ;Set 3D sprite angle (rotation if mode=1)
Protected *Sprite3D.PB_SPRITE3D=IsSprite3D(Sprite3D)
If Mode : Angle+*Sprite3D\Vertice[2]\sz : EndIf
*Sprite3D\Vertice[2]\sz=Angle
If *Sprite3D\Vertice[3]\sz=0
SetSprite3DHandle(Sprite3D, *Sprite3D\Vertice[0]\sz, *Sprite3D\Vertice[1]\sz)
EndIf
Protected *param.PB_SPRITE3D_PLUS=*Sprite3D\Vertice[3]\sz
For i=0 To 3
Protected dist.f=*param\dist[i]
Protected a.f=*param\a[i]
a+Angle*#PI/180.0
*Sprite3D\Vertice[i]\sx=dist*Cos(a)
*Sprite3D\Vertice[i]\sy=dist*Sin(a)
Next
EndProcedure
ProcedureDLL.l GetSprite3DMirrorMode(Sprite3D) ;Get 3D sprite Mirroring mode
Protected *Sprite3D.PB_SPRITE3D=IsSprite3D(Sprite3D)
Protected MirroringMode=#MirrorSprite3D_None
If *Sprite3D\Vertice[0]\tu>*Sprite3D\Vertice[1]\tu
MirroringMode | #MirrorSprite3D_Horizontal
EndIf
If *Sprite3D\Vertice[0]\tv>*Sprite3D\Vertice[3]\tv
MirroringMode | #MirrorSprite3D_Vertical
EndIf
ProcedureReturn MirroringMode
EndProcedure
ProcedureDLL.l GetSprite3DAlpha(Sprite3D) ;Get 3D sprite alpha
Protected *Sprite3D.PB_SPRITE3D=IsSprite3D(Sprite3D)
Protected alpha=*Sprite3D\Vertice[0]\color & $FF000000
alpha>>24
ProcedureReturn alpha
EndProcedure
ProcedureDLL.l GetSprite3DColor(Sprite3D) ;Get 3D sprite color
Protected *Sprite3D.PB_SPRITE3D=IsSprite3D(Sprite3D)
Protected color=*Sprite3D\Vertice[0]\color & $00FFFFFF
ProcedureReturn color
EndProcedure
ProcedureDLL.l GetSprite3DAngle(Sprite3D) ;Get 3D sprite angle
Protected *Sprite3D.PB_SPRITE3D=IsSprite3D(Sprite3D)
Protected a=*Sprite3D\Vertice[2]\sz
ProcedureReturn a%360
EndProcedure
ProcedureDLL.l GetSprite3DHandleX(Sprite3D) ;Get 3D sprite handle X
Protected *Sprite3D.PB_SPRITE3D=IsSprite3D(Sprite3D)
Debug *Sprite3D\Vertice[3]\sz
ProcedureReturn *Sprite3D\Vertice[0]\sz
EndProcedure
ProcedureDLL.l GetSprite3DHandleY(Sprite3D) ;Get 3D sprite handle Y
Protected *Sprite3D.PB_SPRITE3D=IsSprite3D(Sprite3D)
ProcedureReturn *Sprite3D\Vertice[1]\sz
EndProcedure
ProcedureDLL GetSprite3DHandle(Sprite3D, *HandleX, *HandleY) ;Get 3D sprite handle (X,Y)
Protected *Sprite3D.PB_SPRITE3D=IsSprite3D(Sprite3D)
PokeL(*HandleX, *Sprite3D\Vertice[0]\sz)
PokeL(*HandleY, *Sprite3D\Vertice[1]\sz)
EndProcedure
ProcedureDLL GetSprite3DHandlePoint(Sprite3D, *Handle.POINT) ;Get 3D sprite handle POINT
Protected *Sprite3D.PB_SPRITE3D=IsSprite3D(Sprite3D)
*Handle\x=*Sprite3D\Vertice[0]\sz
*Handle\y=*Sprite3D\Vertice[1]\sz
EndProcedure
Macro SetSprite3DBlend_NORMAL()
Sprite3DBlendingMode(#D3DBLEND_SRCALPHA, #D3DBLEND_INVSRCALPHA)
EndMacro
Macro SetSprite3DBlend_INVERT()
Sprite3DBlendingMode(#D3DBLEND_INVDESTCOLOR, #D3DBLEND_INVSRCALPHA)
EndMacro
Macro SetSprite3DBlend_LIGHT()
Sprite3DBlendingMode(#D3DBLEND_SRCALPHA, #D3DBLEND_ONE)
EndMacro
Macro SetSprite3DBlend_SHADE()
Sprite3DBlendingMode(#D3DBLEND_ZERO, #D3DBLEND_SRCCOLOR)
EndMacro
Macro RotateSprite3D(Sprite3D, Angle, Mode) ;//WRAPPER
SetSprite3DAngle(Sprite3D, Angle, Mode)
EndMacro
Macro ZoomSprite3D(Sprite3D, Width, Height) ;//WRAPPER
SetSprite3DSize(Sprite3D, Width, Height)
EndMacro
Macro FreeSprite3D(Sprite3D, FreeSprite3DObject=FreeSprite3D) ;//WRAPPER
FreeSprite3DParameters(Sprite3D)
FreeSprite3DObject(Sprite3D)
EndMacro
;}
;********************
; Example
;********************
InitSprite()
InitSprite3D()
InitKeyboard()
OpenScreen(1024, 768, 32, "Custom PB Sprite3D")
Sprite3DQuality(1)
CreateSprite(1, 256, 256, #PB_Sprite_Texture)
StartDrawing(SpriteOutput(1))
Box(0, 0, 256, 256, RGB(231, 203, 107))
Box(0, 0, 50, 50, RGB(161, 87, 177))
Box(50, 50, 50, 50, #Red)
Box(236, 0, 20, 256, #Cyan)
StopDrawing()
;Normal Sprite3D + MIRROR
CreateSprite3D(10, 1)
MirrorSprite3D(10, #MirrorSprite3D_Horizontal)
;Clipped Sprite3D+ MIRROR
CreateSprite3D(20, 1)
ClipSprite3D(20, 0, 0, 40, 100)
MirrorSprite3D(20, #MirrorSprite3D_Vertical)
;Clipped Sprite3D + COLOR
CreateClippedSprite3D(30, 1, 0, 0, 40, 100)
SetSprite3DColor(30, RGB(0, 0, 255))
;Clipped Sprite3D + COLOR + TRANSPARENCY
CopySprite3D(30, 40)
SetSprite3DColor(40, RGB(255, 0, 0))
SetSprite3DAlpha(40, 100)
;Clipped Sprite3D + TRANSPARENCY + ZOOM
CopySprite3D(10, 50)
SetSprite3DAlpha(50, 1)
ZoomSprite3D(50, 64, 128)
;Set / Get handle
SetSprite3DHandle(50, 5, 155)
GetSprite3DHandle(50, @handleX, @handleY)
GetSprite3DHandlePoint(50, handle.POINT)
Repeat
ClearScreen(RGB(0, 0, 0))
Start3D()
SetSprite3DBlend_NORMAL()
DisplaySprite3D(10, 100, 200)
DisplaySprite3D(20, 400, 200)
DisplaySprite3D(30, 450, 200)
DisplaySprite3D(40, 430, 230)
RotateSprite3D(50, 1, 1)
SetSprite3DBlend_SHADE()
DisplaySprite3D(50, 150, 200)
SetSprite3DBlend_INVERT()
DisplaySprite3D(50, 150, 300)
Stop3D()
FlipBuffers()
ExamineKeyboard()
Until KeyboardPushed(#PB_Key_Escape)
FreeSprite3D(50)