Projection matrix - DX7 or DX9?

BlitzMax Forums/BlitzMax Programming/Projection matrix - DX7 or DX9?

GfK(Posted 2009) [#1]
I'm using projection matrix code which I found on this forum. I've modified it (below) so it works with DStastny's DX9 module.

How would I modify this further so that it automatically detects whether the DX7 or DX9 driver is set? I need to do this at runtime - not compile time.

My modified version. Credit to original author (whoever it was).
Type TVirtualGraphics
	Global virtualWidth, virtualHeight
	Global xRatio!, yRatio!
	
	Function Set(width=640, height=480, scale#=1)
		TVirtualGraphics.virtualWidth = width
		TVirtualGraphics.virtualHeight = height
		TVirtualGraphics.xRatio! = width / Double(GraphicsWidth())
		TVirtualGraphics.yRatio! = height / Double(GraphicsHeight())
		
	?Win32
		Local D3D9Driver:TD3D9Max2DDriver = TD3D9Max2DDriver(_max2dDriver)
			
		If D3D9Driver
			Local matrix#[] = [2.0 / (width / scale#), 0.0, 0.0, 0.0,..
 								0.0, -2.0 / (height / scale#), 0.0, 0.0,..
								0.0, 0.0, 1.0, 0.0,..
								-1 - (1.0 / width), 1 + (1.0 / height), 1.0, 1.0] ',scale#]
			
			D3D9Driver._D3DDevice9.SetTransform(D3DTS_PROJECTION, matrix)
		Else
	? 
		glMatrixMode(GL_PROJECTION)
		glLoadIdentity()
		glortho(0, width / scale#, height / scale#, 0, -1, 1)
		glMatrixMode(GL_MODELVIEW)
		glLoadIdentity()
	?Win32
		EndIf
	?
	End Function
	
	Function MouseX()
		Return (BRL.PolledInput.MouseX() * TVirtualGraphics.xRatio!)
	End Function
	
	Function MouseY()
		Return (BRL.PolledInput.MouseY() * TVirtualGraphics.yRatio!)
	End Function
End Type



markcw(Posted 2009) [#2]
If you want to find out the DX version on Windows wouldn't this sort of thing be the best way?


DStastny(Posted 2009) [#3]
I think he wants to know if the selected driver is Dx7, Dx9 or GL.

I have something around my hard drive that does I think exactly what he wants. I just got home from work I will dig around to see if I can find it. I think it was tied to my playing around with InidePaths subtexture stuff.

Doug


skidracer(Posted 2009) [#4]
I think typecast testing is simplest:

isdx9=TD3D9Max2DDriver(_max2dDriver)<>null
isdx7=TD3D7Max2DDriver(_max2dDriver)<>null


DStastny(Posted 2009) [#5]
Thanks Skid, thats exactly what I was thinking about. Just brain dead after long day.


Doug


GfK(Posted 2009) [#6]
Yep, that's what I wanted - thanks!


GfK(Posted 2009) [#7]
Just got around to fixing this up. The downside is that you must include the DX9 *and* DX7 modules, otherwise you can't do casting to check which driver has been set. Anyway, if anybody's interested in using DStastny's DX9 module with a projection matrix, here's what I'm currently using.

If you don't want to include both DX modules (it makes the EXE bigger), just rip out whichever bits you don't need.

Type TVirtualGraphics
	Global virtualWidth, virtualHeight
	Global xRatio!, yRatio!
	
	Function Set(width=640, height=480, scale#=1)
		TVirtualGraphics.virtualWidth = width
		TVirtualGraphics.virtualHeight = height
		TVirtualGraphics.xRatio! = width / Double(GraphicsWidth())
		TVirtualGraphics.yRatio! = height / Double(GraphicsHeight())
		
	?Win32
		Local dxVer:Byte
		Local D3D7Driver:TD3D7Max2DDriver = TD3D7Max2DDriver(_max2dDriver)
		Local D3D9Driver:TD3D9Max2DDriver = TD3D9Max2DDriver(_max2dDriver)

		If TD3D7Max2DDriver(_max2dDriver) <> Null
			dxVer = 7
		EndIf
 		If TD3D9Max2DDriver(_max2dDriver) <> Null
			dxVer = 9
		EndIf

		If dxVer <> 0 'dx driver was set, otherwise its GL
			Local matrix#[] = [2.0 / (width / scale#), 0.0, 0.0, 0.0,..
			 										0.0, -2.0 / (height / scale#), 0.0, 0.0,..
			 										0.0, 0.0, 1.0, 0.0,..
		 											-1 - (1.0 / width), 1 + (1.0 / height), 1.0, 1.0] ',scale#]
			
			Select dxVer
				Case 7
					D3D7Driver.device.SetTransform(D3DTS_PROJECTION, matrix)
				Case 9
					D3D9Driver._D3DDevice9.SetTransform(D3DTS_PROJECTION, matrix)
			End Select
		Else
	? 
		glMatrixMode(GL_PROJECTION)
		glLoadIdentity()
		glOrtho(0, width / scale:Float, height / scale:Float, 0, - 1, 1)
		glMatrixMode(GL_MODELVIEW)
		glLoadIdentity()
	?Win32
		EndIf
	?
	End Function
	
	Function MouseX()
		Return (BRL.PolledInput.MouseX() * TVirtualGraphics.xRatio!)
	End Function
	
	Function MouseY()
		Return (BRL.PolledInput.MouseY() * TVirtualGraphics.yRatio!)
	End Function
End Type



_Skully(Posted 2009) [#8]
OK, this seems to be working very well

Testing testing... :)


QuickSilva(Posted 2009) [#9]
I wonder if this could ever be included in the main BMax installation? It seems that a great deal of people have a use for it.

Is there a reason why it is not I wonder...

One thing that I would be interested in knowing, from those that have used this method, is whether there is a performance hit. When I scale a 320x240 game window up from 1:1 to double size (640x480), using the standard SetScale command on all of my game objects, my frames per second drops by half which is understandable. My question is, does this happen when using a projection matrix also? I`m guessing it does but just wanted to ask. It would be handy to know for future reference.

Jason.


GfK(Posted 2009) [#10]
No, it runs at the same speed. I was using SetScale originally, too, until I decided I need to rotate stuff, and that screws the whole thing up.

A projection matrix is the only safe way.

One note of caution though - and I did start a thread about this somewhere. If I use the above code, run my app and then CTRL/ALT/DEL in Vista, you get the popup screen where you can open Task Manager and stuff. After that, sometimes but not always, the edges of my graphics become visible as feint lines.

Even if I reload graphics after that, I still get the same problem, so its my guess that there's a glitch in the matrix (sorry). I didn't write the original code and I'm not clever enough to know how to fix it, or if it can be fixed.

I never really got any answers as to why that is.

[edit] I'm a big fat liar - I didn't start a thread, I dug up an old one. And it's here.

[edit again] Actually, I'll get back to you on that. I just tested a recent-ish build of my game on my laptop and I can't get this glitch to happen any more. Obviously I've installed a lot of Vista updates since then, and also I was using a fliphook before and now I'm not.

I'll test more on my main dev PC tomorrow, but I'm 99.9% certain I was getting this problem at least 50% of the time on here too.


MGE(Posted 2009) [#11]
You'll get the problem if you don't properly handle device lost. You have to rebuild everything in that event.


GfK(Posted 2009) [#12]
Yes, problem still happens on my dev PC.

You'll get the problem if you don't properly handle device lost.
Define "properly handle"?

I already stated that even newly loaded graphics exhibit the problem. I already reset the projection matrix after focus is lost, too.

[edit] When I run in debug mode and this 'problem' happens, I get the following error in d3d7graphics.bmx:
DXERROR err=UNKNOWN:-2147467259 16389

The DXASS function is being called from line 491:
DXASS _d3ddev7.SetRenderTarget( renderSurf,0 )


I tried reinitialising the graphics mode on receipt of an EVENT_APPRESUME - naturally the graphics object is recreated over and over, as the task itself fires an EVENT_APPRESUME.

Presumably I'm not using the correct method of losing/acquiring focus?
Help?


GfK(Posted 2009) [#13]
Right - confirmed this is nothing to do with the projection matrix.

I'm going to start a new thread.


SLotman(Posted 2009) [#14]
Is there any way to get GrabImage/GrabPixmap to work with this projection Matrix? Last time I tried it didn't work :(


_Skully(Posted 2009) [#15]
It works but it grabs the scaled version... my suggestion would be to set the projection matrix to a 1:1 ratio before doing any operations of this nature and then switch it back after for rendering

StartGraphics(1024,768,0,60)

t:TVirtualGraphics=New TVirtualGraphics
' if Projection matrix is the same as above it will work perfectly... but set it to 800,600 and you get the scaled version
t.Set(1024,768)

i:TImage=CreateImage(64,64,,DYNAMICIMAGE|MASKEDIMAGE)
DrawLine 0,0,64,64
DrawLine 64,0,0,64

GrabImage(i,0,0)
Cls
DrawImage i,0,0
Flip
WaitKey()


function StartGraphics(width:Int=1024,height:Int=768,depth:Int=0,refresh:Int=60)
	SetGraphicsDriver GLMax2DDriver()
	Graphics Width,Height,Depth,Refresh
	ScreenWidth=width
	ScreenHeight=height
	ScreenDepth=depth
	screenRefresh=refresh
End Function



Type TVirtualGraphics
	Global virtualWidth!, virtualHeight!
	Global xRatio!, yRatio!
	
	Function Set(width#=640, height#=480, scale#=1)
		TVirtualGraphics.virtualWidth = width
		TVirtualGraphics.virtualHeight = height
		TVirtualGraphics.xRatio! = width / Double(GraphicsWidth())
		TVirtualGraphics.yRatio! = height / Double(GraphicsHeight())
		
	?Win32
		Local dxVer:Byte
		Local D3D7Driver:TD3D7Max2DDriver = TD3D7Max2DDriver(_max2dDriver)
'		Local D3D9Driver:TD3D9Max2DDriver = TD3D9Max2DDriver(_max2dDriver)

		If TD3D7Max2DDriver(_max2dDriver) <> Null
			dxVer = 7
		EndIf
 '		If TD3D9Max2DDriver(_max2dDriver) <> Null
'			dxVer = 9
'		EndIf

		If dxVer <> 0 'dx driver was set, otherwise its GL
			Local matrix#[] = [2.0 / (width / scale#), 0.0, 0.0, 0.0,..
			 										0.0, -2.0 / (height / scale#), 0.0, 0.0,..
			 										0.0, 0.0, 1.0, 0.0,..
		 											-1 - (1.0 / width), 1 + (1.0 / height), 1.0, 1.0] ',scale#]
			
			Select dxVer
				Case 7
					D3D7Driver.device.SetTransform(D3DTS_PROJECTION, matrix)
				Case 9
'					D3D9Driver._D3DDevice9.SetTransform(D3DTS_PROJECTION, matrix)
			End Select
		Else
	? 
		glMatrixMode(GL_PROJECTION)
		glLoadIdentity()
		glOrtho(0, width / scale:Float, height / scale:Float, 0, - 1, 1)
		glMatrixMode(GL_MODELVIEW)
		glLoadIdentity()
	?Win32
		EndIf
	?
	End Function
	
	Function MouseX:Float()
		Return (BRL.PolledInput.MouseX() * TVirtualGraphics.xRatio!)
	End Function
	
	Function MouseY:Float()
		Return (BRL.PolledInput.MouseY() * TVirtualGraphics.yRatio!)
	End Function
End Type