Page 1 of 3

ClipSprite3D for DirectX7 / DirectX9 (x86/x64)

Posted: Sun Mar 15, 2009 2:13 pm
by Fluid Byte
It seems my tenacity paid off since I finally found all needed information to update the famous ClipSprite3D code from S.M. The original code for DX7 has been cleaned, updated and extended. The dependency for the DirectDraw interface to retrieve the real width and height has been removed. That means a lot of the overhead is gone (DDPIXELFORMAT, DDCOLORKEY, etc.).

Though the best thing still is that it finally works correctly with the DirectX9 subsystem. It's now a compact piece of code which will automatically call the correct version depending on the selected subsystem.

* Updated the code to support DirectX 9 as the default subsystem (PB 4.40 and later) *

Code: Select all

; ==========================================
; #  ClipSprite3D for DirectX7 / DirectX9  #
; ==========================================

; Original by: S.M. (Stefan Moebius)
; Modfied by: Fluid Byte
; Platform: Windows
; E-Mail: fluidbyte@web.de

EnableExplicit

CompilerIf Subsystem("DirectX7")
	Structure D3DTLVERTEX
		x.f
		y.f
		z.f
		rhw.f
		Color.i
		Specular.i
		tu.f
		tv.f
	EndStructure
	
	Structure PB_DX7Sprite3D
		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.i
	EndStructure

	Procedure ClipSprite3D(Sprite3D,ClipX,ClipY,ClipWidth,ClipHeight)
		Protected *ptr.PB_DX7Sprite3D = IsSprite3D(Sprite3D)
		
		If *ptr = 0 : ProcedureReturn 0 : EndIf
		
		Protected RealWidth = SpriteWidth(Sprite3D)
		Protected RealHeight = SpriteHeight(Sprite3D)
			
		If ClipX < 0 : ClipX = 0 : EndIf
		If ClipY < 0 : ClipY = 0 : EndIf
		
		If ClipWidth < 0 : ClipWidth = 0 : EndIf
		If ClipHeight < 0 : ClipHeight = 0 : EndIf		

		If ClipX > RealWidth : ClipX =  RealWidth : EndIf
		If ClipY > RealHeight : ClipY = RealHeight : EndIf
		
		If ClipX + ClipWidth > RealWidth : ClipWidth = RealWidth - ClipX : EndIf
		If ClipY + ClipHeight > RealHeight : ClipHeight = RealHeight - ClipY : EndIf
		
		*ptr\Vertice[0]\tu = ClipX / RealWidth
		*ptr\Vertice[0]\tv = ClipY / RealHeight
		
		*ptr\Vertice[1]\tu = (ClipX + ClipWidth) / RealWidth
		*ptr\Vertice[1]\tv = ClipY / RealHeight
		
		*ptr\Vertice[2]\tu = ClipX / RealWidth
		*ptr\Vertice[2]\tv = (ClipY + ClipHeight) / RealHeight
		
		*ptr\Vertice[3]\tu = (ClipX + ClipWidth) / RealWidth
		*ptr\Vertice[3]\tv = (ClipY + ClipHeight) / RealHeight
		
		ProcedureReturn 1
	EndProcedure
CompilerElse
	Structure D3DTLVERTEX
	  x.f
	  y.f
	  z.f
	  rhw.f
	  Color.l
	  tu.f
	  tv.f
	EndStructure

	Structure PB_DX9Sprite3D
	  TexRes.i                  ; TexRes
	  Vertice.D3DTLVERTEX[4]    ; The 4 vertices for the rectangle sprite
	  TmpVertice.D3DTLVERTEX[4] ; The 4 vertices for the rectangle sprite
	  Width.l                   ; width set with ZoomSprite3D()
	  Height.l                  ; height set with ZoomSprite3D()
	  RealWidth.l
	  RealHeight.l
	  Angle.f
	  Transformed.l
	EndStructure

	Procedure ClipSprite3D(Sprite3D,ClipX,ClipY,ClipWidth,ClipHeight)
		Protected *ptr.PB_DX9Sprite3D = IsSprite3D(Sprite3D)
		
		If *ptr = 0 : ProcedureReturn #False : EndIf
		
		If ClipX < 0 : ClipX = 0 : EndIf
		If ClipY < 0 : ClipY = 0 : EndIf
		
		If ClipWidth < 0 : ClipWidth = 0 : EndIf
		If ClipHeight < 0 : ClipHeight = 0 : EndIf
		
		If ClipX > *ptr\RealWidth : ClipX = *ptr\RealWidth : EndIf
		If ClipY > *ptr\RealHeight : ClipY = *ptr\RealHeight : EndIf
		
		If ClipX + ClipWidth > *ptr\RealWidth : ClipWidth = *ptr\RealWidth - ClipX : EndIf
		If ClipY + ClipHeight > *ptr\RealHeight : ClipHeight = *ptr\RealHeight - ClipY : EndIf
		
		*ptr\Vertice[0]\tu = ClipX / *ptr\RealWidth
		*ptr\Vertice[0]\tv = ClipY / *ptr\RealHeight 
		
		*ptr\Vertice[1]\tu = (ClipX + ClipWidth) / *ptr\RealWidth 
		*ptr\Vertice[1]\tv = ClipY / *ptr\RealHeight
		
		*ptr\Vertice[2]\tu = ClipX / *ptr\RealWidth 
		*ptr\Vertice[2]\tv = (ClipY + ClipHeight) / *ptr\RealHeight 
		
		*ptr\Vertice[3]\tu = (ClipX + ClipWidth) / *ptr\RealWidth 
		*ptr\Vertice[3]\tv = (ClipY + ClipHeight) / *ptr\RealHeight 

		ProcedureReturn #True
	EndProcedure
CompilerEndIf

Posted: Sun Mar 15, 2009 2:13 pm
by Fluid Byte
* This demo doesn't work any more since a lot of images have been removed from the "examples" folder since 4.50 *

Enhanced demo version:

Code: Select all

InitSprite() : InitSprite3D() : InitKeyboard()

OpenWindow(0,0,0,640,480,"ClipSprite3D for DX7/DX9",#WS_SYSMENU | #WS_CAPTION | 1)
OpenWindowedScreen(WindowID(0),0,0,640,480,0,0,0)

Define i, EventID, AnimFrame, AnimDelay, CVL

; * Background
CreateSprite(0,640,480)
StartDrawing(SpriteOutput(0))
For i=0 To 479 : CVL = i * 125 / 479 : Box(0,i,640,1,RGB(70 + CVL,90 + CVL,110 + CVL)) : Next
StopDrawing()

; * Checkerboard
CreateSprite(1,128,128,#PB_Sprite_Texture)
StartDrawing(SpriteOutput(1))
Box(0,0,256,256,RGB(35,70,255))
Box(0,0,50,50,RGB(100,230,0))
Box(50,50,50,50,RGB(230,60,20))
StopDrawing()

CreateSprite3D(1,1)
ZoomSprite3D(1,192,192)
ClipSprite3D(1,0,0,100,100)

; * ImageStrip
CreateImage(0,512,512)
StartDrawing(ImageOutput(0))
For i=1 To 8
	LoadImage(i,#PB_Compiler_Home + "Examples\Sources - Advanced\Waponez II\Data\Explosion_" + Str(i) + ".bmp")
	DrawImage(ImageID(i),(i - 1) * 64,0) : FreeImage(i)
Next
StopDrawing()

SaveImage(0,GetTemporaryDirectory() + "tmp4f8s5.bmp") : FreeImage(0)
LoadSprite(2,GetTemporaryDirectory() + "tmp4f8s5.bmp",#PB_Sprite_Texture)

CreateSprite3D(2,2)
ZoomSprite3D(2,128,128)
ClipSprite3D(2,0,0,64,64)

Sprite3DQuality(1)

Repeat
	EventID = WindowEvent()
	
	ExamineKeyboard()
		
	ClearScreen(0)
	
	DisplaySprite(0,0,0)

	AnimDelay + 1
	
	If AnimDelay = 8
		AnimDelay = 0
		AnimFrame + 1
		If AnimFrame = 8 : AnimFrame = 0 : EndIf		
		ClipSprite3D(2,64 * AnimFrame,0,64,64)
	EndIf
	
	Start3D()
	Sprite3DBlendingMode(5,13)
	RotateSprite3D(1,1,1)
	DisplaySprite3D(1,70,140)	
	DisplaySprite3D(2,370,40)
	Sprite3DBlendingMode(5,2)
	DisplaySprite3D(2,440,180)
	Sprite3DBlendingMode(8,4)
	DisplaySprite3D(2,370,320)
	Stop3D()
		
	FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape) Or EventID = #PB_Event_CloseWindow

Posted: Sun Mar 15, 2009 5:28 pm
by J. Baker
Very nice work!

And is it just my eyes or does using the DirectX9 subsystem have better alpha-blending? I noticed on the edges of an animated sprite in DX7 there is slight pixel shifting or something. Either way using the DirectX9 subsystem looks cleaner to my eyes. Thanks for posting this. ;)

EDIT: Oh, I noticed the edge difference with my example combined with your DirectX9 code. http://www.purebasic.fr/english/viewtopic.php?t=36285

Posted: Sun Mar 15, 2009 5:43 pm
by Fluid Byte
And is it just my eyes or does using the DirectX9 subsystem have better alpha-blending?
Alpha-blending is the same but the texture-filtering is better. :wink:

Posted: Sun Mar 15, 2009 6:50 pm
by IceSoft
Should be a nativ function of the Sprite3D PureBasic library.

Posted: Sun Mar 15, 2009 8:38 pm
by Kaeru Gaman
as I already said: if native, then setting of u/v coordinates.
you can do clip with u/v setting, but you cannot do u/v setting with clip.

Posted: Mon Mar 16, 2009 12:21 pm
by djes
IceSoft wrote:Should be a nativ function of the Sprite3D PureBasic library.
+1

Posted: Wed Mar 25, 2009 5:44 pm
by J. Baker
Does anyone know why the third pic which is sprite #2 doesn't load but instead is a duplicate of sprite #1? All three images are located with the source. So it's not a path problem.

Code: Select all

Code Removed

Posted: Wed Mar 25, 2009 5:52 pm
by Fluid Byte
Could you provide the images please?

[edit]
you need to put IncludeBinary into DataSection/EndDataSection

Posted: Wed Mar 25, 2009 6:50 pm
by J. Baker
Fluid Byte wrote:Could you provide the images please?

[edit]
you need to put IncludeBinary into DataSection/EndDataSection
It seems to be a DisplaySprite3D error/bug. If I just use DisplaySprite it loads the correct image and it duplicates the first 3d sprite when DisplaySprite3D is used.

I would have to create another image. The third image is for something I'm working on.

Posted: Wed Mar 25, 2009 7:10 pm
by J. Baker
Fluid Byte wrote:Could you provide the images please?
EDIT: Images Removed

Posted: Wed Mar 25, 2009 8:03 pm
by Fluid Byte
Change

Code: Select all

CreateSprite3D(0, 0)
CreateSprite3D(1, 0)
CreateSprite3D(2, 0)
to

Code: Select all

CreateSprite3D(0, 0)
CreateSprite3D(2, 2)
PS: Could you remove your above code? I want to keep the thread clean.

Posted: Wed Mar 25, 2009 8:20 pm
by J. Baker
thanks, I should have caught that. ;)

Posted: Fri Mar 27, 2009 4:28 am
by J. Baker
It seems that Sprite3DQuality doesn't work with DirectX9. Does this have to do with DirectDraw?

Posted: Fri Mar 27, 2009 2:26 pm
by Fluid Byte
J. Baker wrote:It seems that Sprite3DQuality doesn't work with DirectX9. Does this have to do with DirectDraw?
That has nothing to do with this code. Besides, it works perfectly. Could you please post in "Coding Questions" and not here?