strage behavior on different GPUs with direct3d9

BlitzMax Forums/BlitzMax Programming/strage behavior on different GPUs with direct3d9

Hi,

Now I am a step forward with direct3d. I restarted the implementation of the renderinterface and came to a strange behavior of direct3d...

I created a cube and a sphere for testing, but on my geforce 7950gt some tris are black...one side of the cube and also 30% of the sphere. But on Klepto's ATIx800 it is all ok.
Then I tested it with my laptop with ATIx300. There is only the sphere rendered and the cube is completely missing...

What results do you become?
Click here!

That's the type for renderables, which produces this things( Maybe I do something wrong, but its almost simple):


Type TDXRenderable

	Const VERTEXSIZE:Int = 44
	Const INDEXSIZE:Int = 2
	
	Global D3D_VERTEX_FORMAT:Int = (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX0 | D3DFVF_TEX1) 
	Global D3D_INDEX_FORMAT:Int = D3DFMT_INDEX16
	Global D3DDevice:IDirect3DDevice9
	
	Field VertexBufferObj:IDirect3DVertexBuffer9
	Field verts:Byte Ptr = New Byte[1] 
	Field no_verts:Int
	Field vert_array_size:Int = 1
	
	Field IndexBufferObj:IDirect3DIndexBuffer9
	Field tris:Short[] 
	Field no_tris:Int
	Field tri_array_size:Int = 1
	
	Field mat:TMatrix
	
	Method AddVertex:Int(x:Float, y:Float, z:Float, u:Float = 0.0, v:Float = 0.0, w:Float = 0.0) 
	
		no_verts:+1
		
		If no_verts * VERTEXSIZE > vert_array_size Then
			
			Local oldSize:Int = vert_array_size
			
			Repeat
				vert_array_size = vert_array_size * 2
			Until vert_array_size > no_verts * VERTEXSIZE
			
			Local tmp_verts:Byte Ptr = New Byte[vert_array_size] 
			MemCopy(tmp_verts, verts, oldSize) 
			MemFree(verts) 
			verts = tmp_verts
		
		EndIf
		
		Local vId:Int = (no_verts - 1) 
		SetVertexPos(vId, x, y, z) 
		SetVertexColor(vId, 1.0, 1.0, 1.0) 
		SetVertexTexCoord(vId, u, v, 0) 
		
		Return vId
		
	End Method
	
	Method SetVertexPos(vId:Int, x:Float, y:Float, z:Float) 
		vId:*VERTEXSIZE
		Local p:Float Ptr = Float Ptr(verts + vId ) 
		p[0] = x; p[1] = y; p[2] = z
	End Method
	
	Method SetVertexNormal(vId:Int, nx:Float, ny:Float, nz:Float) 
		vId:*VERTEXSIZE
		Local p:Float Ptr = Float Ptr(verts + vId + 12) 
		p[0] = nx; p[1] = ny; p[2] = nz
	End Method
	
	Method SetVertexColor(vId:Int, r:Float, g:Float, b:Float, a:Float = 1.0) 
		vId:*VERTEXSIZE
		Local p:Int Ptr = Int Ptr(verts + vId + 24) 
		'p[0] = Int((Int(a * 255.0) Shl 24) | (Int(r * 255.0) Shl 16) | (Int(g * 255.0) Shl 8) | Int(b * 255.0)) 
		p[0] = Int((255 Shl 24) | (Rand(0, 255) Shl 16) | (Rand(0, 255) Shl 8) | Rand(0, 255)) 
	End Method
	 
	Method SetVertexTexCoord(vId:Int, u:Float, v:Float, coord:Int) 
		vId = vId * VERTEXSIZE + coord * 8
		Local p:Float Ptr = Float Ptr(verts + vId + 28) 
		p[0] = u; p[1] = v
	End Method
	
	Method GetVertexPos:Float[] (vId:Int) 
		vId:*VERTEXSIZE
		Local p:Float Ptr = Float Ptr(verts + vId) 
		Return[p[0] , p[1] , p[2] ] 
	End Method
	
	Method GetVertexNormal:Float[] (vId:Int) 
		vId:*VERTEXSIZE
		Local p:Float Ptr = Float Ptr(verts + vId + 12) 
		Return[p[0] , p[1] , p[2] ] 
	End Method
	
	Method GetVertexColor:Float[] (vId:Int) 
		vId:*VERTEXSIZE
		Local color:Int = (Float Ptr(verts + vId + 24))[0] 
		Return[Float(((color & $ff000000) Shr 24) / 255.0), Float(((color & $00ff0000) Shr 16) / 255.0),  ..
			   Float(((color & $0000ff00) Shr 8) / 255.0), Float((color & $000000ff) / 255.0)] 
	End Method
	 
	Method GetVertexTexCoord:Float[] (vId:Int, coord:Int) 
		vId = vId * VERTEXSIZE + coord * 8
		Local p:Float Ptr = Float Ptr(verts + vId + 28) 
		Return[p[0] , p[1] ] 
	End Method
	
	Method AddTriangle:Int(v0:Int, v1:Int, v2:Int) 
	
		no_tris = no_tris + 1
		
		' resize array
		If no_tris * 3 >= tri_array_size
		
			Repeat
				tri_array_size=tri_array_size*2
			Until tri_array_size > no_tris * 3
		
			tris = tris[..tri_array_size] 
			
		EndIf
		
		Local vid:Int = (no_tris * 3) 
	
		tris[vid - 3] = v2
		tris[vid - 2] = v1
		tris[vid - 1] = v0
		
		Return no_tris
		
	End Method
	
	Method SetTriAngles:Int(start:Int, count:Int, triangles:Short Ptr, srcOffset:Int = 0) 
		If tris.length < start+count Then 
			tris = tris[..(start+count)]
			no_tris =  tris.length / 3
		EndIf 
		Local dstPtr:Byte Ptr = tris
		MemCopy(dstPtr+start*2, Byte Ptr(triangles)+srcOffset*2 , count*2 )  
	End Method 
	
	Method GetTriangles:Short Ptr() 
		Return tris
	End Method 
		
	Method OverrideVertexCount(count:Int) 
		no_verts = Count
	End Method
	
	Method OverrideTrisCount(count:Int)
		no_Tris = Count
	End Method
	
	Method Clear(clear_verts:Int = True, clear_tris:Int = True) 
	
		If clear_verts
			no_verts = 0
			MemFree verts		
			vert_array_size = 1
		EndIf
		
		If clear_tris
			no_tris = 0
			tris = tris[..0] 
			tri_array_size = 1
		EndIf
	
	End Method
	
	
	Method SetMatrix(Matrix:TMatrix) 
		mat = Matrix
	End Method

	Method EnableVBO(vbo_enabled:Int) 
		If vbo_enabled Then
			D3DDevice.CreateVertexBuffer(vert_array_size, D3DUSAGE_WRITEONLY, D3D_VERTEX_FORMAT, D3DPOOL_MANAGED, VertexBufferObj, Null) 
			D3DDevice.CreateIndexBuffer(tri_array_size, D3DUSAGE_WRITEONLY, D3D_INDEX_FORMAT, D3DPOOL_DEFAULT, IndexBufferObj, Null) 
		EndIf
	End Method

	Method Update() 
		D3DDevice.SetTransform(D3DTS_WORLD, mat.grid) 
		D3DDevice.SetFVF(D3D_VERTEX_FORMAT) 
		D3DDevice.SetStreamSource(0, VertexBufferObj, 0, VERTEXSIZE) 
		D3DDevice.SetIndices(IndexBufferObj) 
		D3DDevice.DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, no_verts, 0, no_tris) 
	End Method
	
	Method CountTriangles:Int() 
		Return no_tris
	End Method
	
	Method CountVertices:Int() 
		Return no_verts
	End Method
	
	Method UpdateVBO:Int(reset_vbo:Int Var) 
	
		If reset_vbo = -1 Then reset_vbo = 1 | 2 | 4 | 8 | 16
	
		If Not VertexBufferObj Or Not IndexBufferObj Or reset_vbo & 1 Or reset_vbo & 2 Or reset_vbo & 4 Or reset_vbo & 8 Or reset_vbo & 16 Then
		
			EnableVBO(True) 
						
			Local VertexBufferStart:Byte Ptr
			Local IndexBufferStart:Byte Ptr
		
			VertexBufferObj.Lock(0, no_verts * VERTEXSIZE, VertexBufferStart, D3DLOCK_NOSYSLOCK) 
			IndexBufferObj.Lock(0, no_tris * 3 * INDEXSIZE, IndexBufferStart, D3DLOCK_NOSYSLOCK) 
			
			MemCopy(VertexBufferStart, verts, no_verts * VERTEXSIZE) 
			MemCopy(IndexBufferStart, Byte Ptr(tris), no_tris * 3 * INDEXSIZE) 
		
			VertexBufferObj.Unlock() 
			IndexBufferObj.Unlock() 
			
		EndIf
		
		reset_vbo=False

		Return True
	End Method
	
	Method FreeVBO() 
		If VertexBufferObj Then VertexBufferObj.Release_() 
		If IndexBufferObj Then IndexBufferObj.Release_() 
	End Method
	
	
End Type


One suggestion is to error check your DX9 calls. You are just calling them all and assuming they are working. They all return HRESULTS for a reason. That will help locate your error. The other is to enable the debug runtime debugging and use a debugger capable of trapping the output.

Most like you are getting an error somewhere and it is a setup issue. When developing the Max2d Directx9 driver I had a lot of trouble bouncing between Nvidia and ATI and in every case there was always an issue in the DX9 debug log and sure enough something was coded wrong after cross referencing to the Windows Documentation.

Just like people find with OpenGL support different drivers are more or less tolerant of buggy code.

Doug

Thanks, I will try that.
btw: we are using your Max2dDirectx9 driver as the base for the d3d9 part of miniB3d...

cube fine on the sphere a quarter + 6 triangles are missing so I would guess the last xy "quads" you add.

one thing to add might be: why do you use byte ptr and assign byte arrays?
Why not just memalloc() if you are not interested in the TArray class instance at all ...

Do you mean using this:
Field verts:Byte Ptr = MemAlloc(vert_array_size)

instead of this:
Field verts:Byte Ptr = New Byte[vert_array_size]
?
Hmm, I did not think about, because I thought it makes no difference... but I will change it.

Well the difference is the later is handled by BMs GC, the first isn't.

So you have control over the alloc and the de allocation (memfree) without any BM interferences.

I don't know how large the difference otherwise is.

@Rone, let me know if you find anything borked in the driver. I know the texture creation code around TImageFrame probably could be more robust. The way I implemented MIPMAPPING just assumes the card can handle it.

Also you might want to try and understand how I used the AddDeviceObject and use SendMessage to communicate with Objects that have been bound to the Direct3D9Device to inform it of Resets with the device driver. That might be where your problem is as if the Device is lost the Dx9 driver will attempt to tear down rebuild the Direct3ddevice with a call to Reset and if your object doesnt respond to the message it will put Dx9 into a funky state. This is If if remember on area that is hugely important to be manged correctly. Your TDX9Renerable really needs to respond to that.

Doug


Doug

Tested here with an intel DX9 compatible card and the application just shows a window and closes inmediatelly. Nothing to see here.

@ziggy, same here at gf7200...what graphic card do you use?
Just for information, because there is apparently an complete different behavior between ATIx300, ATIx800, gf7200 and gf7950gt...

@Budman, thanks for info. I have not yet really looked at your
dx9 driver, just changed the initialization a little bit, in order to get it work...I will look into it after work.

It is an intel Movile Intel 945 Express Chipset Family

Sounds like the basic init is totally broken ...
Intels CPU to VGA adapters might not be that good but they work normally the most "standard" on DX9 (unlike NVIDIA and ATI with their optimations and fixed pipeline through shader emulation on the X1000+ GF7000+)

hmm, it seems that the problems comes exclusive from the D3D9GraphicsDriver inititialization. if I only use a very simple inititialization it works fine:
Direct3D9 = Direct3DCreate9( $900 )

If Not Direct3D9  Then 
	assert "error creating d3d9interface!"
EndIf

		
PParams = New D3DPRESENT_PARAMETERS
		
PParams.SwapEffect       = D3DSWAPEFFECT_DISCARD;
PParams.hDeviceWindow    = hwnd;
PParams.Windowed         = bWindowed;
PParams.BackBufferWidth  = w;
PParams.BackBufferHeight = h;
PParams.BackBufferFormat = D3DFMT_A8R8G8B8;


hr = Direct3D9.CreateDevice( 0 ,D3DDEVTYPE_HAL,hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING,PParams,Direct3DDevice9) <> D3D_OK
		
If hr Then 
	assert "error creating d3d9device!"
EndIf 


Direct3DDevice9.GetBackBuffer(0,0, D3DBACKBUFFER_TYPE_MONO, BackBuffer );


The missing tris, comes from using D3DCREATE_HARDWARE_VERTEXPROCESSING regardless that _Direct3D9.CreateDevice returns D3D_OK.

But when using D3DCREATE_SOFTWARE_VERTEXPROCESSING in the d3d9driver, the driver crashes after a few seconds with an unhandled memory exception at Flip... _SwapChain.Present(Null, Null, Null, Null, flags) ?!

So, I think I write a own small TGraphicsDriver, in order to quickly continue... impartial therefrom I dont know whats the problem with D3DCREATE_HARDWARE_VERTEXPROCESSING.

Sure that the $900 for the DX_VERSION is correct?
Thought it was 3x (depending on the DX SDK you use logically, see the _xx in the DLL)
$900 would be the major version not the DX Runtime Version ...

I am a little bit confused, because I have ever assigned DIRECT3D_VERSION, which is $900. Also in all my books and samples $900 is used...Budman's dxdriver also use it.

But the DX reference says really there must be D3D_SDK_VERSION assiged, which is 32 on my installation...
Create an IDirect3D9 object as shown here:

LPDIRECT3D9 g_pD3D = NULL;
    
if( NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)))
    return E_FAIL;

/*==========================================================================;
 *
 *  Copyright (C) Microsoft Corporation.  All Rights Reserved.
 *
 *  File:   d3d9.h
 *  Content:    Direct3D include file
 *
 ****************************************************************************/

#ifndef _D3D9_H_
#define _D3D9_H_

#ifndef DIRECT3D_VERSION
#define DIRECT3D_VERSION         0x0900
#endif  //DIRECT3D_VERSION

// include this file content only if compiling for DX9 interfaces
#if(DIRECT3D_VERSION >= 0x0900)
/*
...
*/
#ifdef D3D_DEBUG_INFO
#define D3D_SDK_VERSION   (32 | 0x80000000)
#define D3D9b_SDK_VERSION (31 | 0x80000000)

#else
#define D3D_SDK_VERSION   32
#define D3D9b_SDK_VERSION 31
#endif


I don't know.
It confused me as well but up to DX 9c there was never the situation that 10 concurrent version (+-) existed and you needed to switch which runtime DLL which you use (which makes a difference on how the shader compiler behaves etc)

The driver version number just version of the header you are using has no impact except to expose different features. The driver version used by my driver is from older SDK. Actually from Marks own header. Not the problem.

@Rone

here is the intilization code in my driver
' try to create different devices
		' falling back to full software vertex processing if necessary
		If _Direct3D9.CreateDevice( 0,D3DDEVTYPE_HAL,_FocusHWND,D3DCREATE_PUREDEVICE|D3DCREATE_HARDWARE_VERTEXPROCESSING|D3DCREATE_FPU_PRESERVE,_FocusPresentParams,_Direct3DDevice9)<>D3D_OK
			If _Direct3D9.CreateDevice( 0,D3DDEVTYPE_HAL,_FocusHWND,D3DCREATE_HARDWARE_VERTEXPROCESSING|D3DCREATE_FPU_PRESERVE,_FocusPresentParams,_Direct3DDevice9)<>D3D_OK
				If _Direct3D9.CreateDevice( 0,D3DDEVTYPE_HAL,_FocusHWND,D3DCREATE_SOFTWARE_VERTEXPROCESSING|D3DCREATE_FPU_PRESERVE,_FocusPresentParams,_Direct3DDevice9)<>D3D_OK			
				    DXLog "failed To create device _D3dDev9"
					_DestroyDirect3DDevice9()
					Return Null
				End If
			End If		
		EndIf	



As you see it is a fail through model. So it tries to create the most compatibile driver for the card.

Simple question does the rendering work in MAX2d?
ie the sample Applications I ship in the ZIP.

Thanks
Doug

Yes, directX9Max2d works fine.

The posted .exe was builded with unchanged initialization. Then automatically the first with HARDWARE_VERTEXPROCESSING is used...I have only comment out _PresentParams.EnableAutoDepthStencil = true, in order that the screen dont stay black...
_Direct3D9.CreateDevice(0,D3DDEVTYPE_HAL,_FocusHWND,D3DCREATE_PUREDEVICE|D3DCREATE_HARDWARE_VERTEXPROCESSING|D3DCREATE_FPU_PRESERVE,_FocusPresentParams,_Direct3DDevice9)

returns D3D_OK, but produces errors on the most cards. And that is also in my simple initialization...very strange.

_Direct3D9.CreateDevice(0,D3DDEVTYPE_HAL,_FocusHWND,D3DCREATE_SOFTWARE_VERTEXPROCESSING|D3DCREATE_FPU_PRESERVE,_FocusPresentParams,_Direct3DDevice9)
returns also D3D_OK and renders correctly, for a few seconds . Then the application crashes at _SwapChain.Present(Null, Null, Null, Null, flags)...I cant undersand this ;)

I not really want to write a new graphics driver, because yours looks good and I think the problem must be somewhere else.
Also I can not detect any error in my TDXRenderable type.

Well if the 2d is working the problem lies somewhere else, As the Max2d driver sets up vertex and index buffers and drives them fine. I have feeling its the creatation of your vertex/index buffers some combination of the flags or mechnism for filling is causing the fits.

	D3DDevice.CreateVertexBuffer(vert_array_size, D3DUSAGE_WRITEONLY, D3D_VERTEX_FORMAT, D3DPOOL_MANAGED, VertexBufferObj, Null) 
			D3DDevice.CreateIndexBuffer(tri_array_size, D3DUSAGE_WRITEONLY, D3D_INDEX_FORMAT, D3DPOOL_DEFAULT, IndexBufferObj, Null) 
		


Looking at this you are creating the Vertex Buffer the managed Pool and the Index Buffer in the Defaul Pool.

Not having my SDK docs handy Managed means if the device is lost DirectX will manange recreation across a reset of the device. Change them both to Managed.

Also and check creation succeeds
		If D3DDevice.CreateVertexBuffer(vert_array_size, D3DUSAGE_WRITEONLY, D3D_VERTEX_FORMAT, D3DPOOL_MANAGED, VertexBufferObj, Null) <>D3D_OK 
			Throw "Failed To Create VB"		
		End If		
				
		If D3DDevice.CreateIndexBuffer(tri_array_size, D3DUSAGE_WRITEONLY, D3D_INDEX_FORMAT, D3DPOOL_MANAGED, IndexBufferObj, Null) 
			<>D3D_OK 
			Throw "Failed To Create Index Buffer"		
		End If	


Next

Your method UpdateVBO.

I dont understand the flags with and or stuff but have to assume there is some purpose for that inside your implemenation.

I am concerned that you are writting to a buffer even if lock fails. So restructure this like so..

Dont hold two locks at same time.

			Local VertexBufferStart:Byte Ptr
			Local IndexBufferStart:Byte Ptr
		
			If VertexBufferObj.Lock(0, no_verts * VERTEXSIZE, VertexBufferStart, D3DLOCK_NOSYSLOCK) =D3D_OK
				MemCopy(VertexBufferStart, verts, no_verts * VERTEXSIZE) 
				VertexBufferObj.Unlock() 			
			End If
			
			If IndexBufferObj.Lock(0, no_tris * 3 * INDEXSIZE, IndexBufferStart, D3DLOCK_NOSYSLOCK) =D3D_OK 
				MemCopy(IndexBufferStart, Byte Ptr(tris), no_tris * 3 * INDEXSIZE) 
				IndexBufferObj.Unlock() 
			End If



FYI this was the biggest problem I had with Nvidia and ATI different cards and drivers caused way strange behavior. Originally in version 1 I held the locks open and pumped in tri's until full then unlocked and rendered. I forget which but one vendor always either crashed outright or failed to render if the lock was held across a windows message pump and due to structure of Max2d only way to fix was to create a memory buffer and lock fill unlock render. So I wound up creating my own system memory triangle buffer. Took the performance hit but got stablitiy.

Thinking about it now I know why your getting working results with a SOFTWARE_VERTEX_PROCESSING pipeline. The vertex buffers are kept in system memory until rendering so any kind of funky memory behavior with you locking unlocking with the types of Buffers your creating are being hidden since your always dealing with system memory. But with Hardware Vertex Processing your actually messing with GPU memory directly hence the strange behavior.

Hope this helps. Your questions have actually make me look at Max for first time in long (well since the reflection bug in 1.26/8???) caused a problem for someone using the Max2dDx9 Driver.

I had actually at one time started writing a Max3dDriver Model similar to what you guys are doing but some frustrations with the limitations of Max as language(Lack of system level thread-safety and awful debug capabilities having to expand all 3d math inline to avoid function call overhead) have had me table it to see if BRL tries to address this limitiations.

I will be more than willing to try to help you guys anyway I can. If I can get my old machine up and running I'll see if I can get can my Vertex/Index Buffer Objects available to you guys so you can just deal with filling them and rendering them. I had most of these nuainces pretty well under control and they plugged right into the Dx9Driver so it managed there state creation and destruction. Right now my full time job is killing me timewise not leaving much time for fun.

Doug

Thanks for your help.
I have made your suggested changes and played a little bit with the flags, but still have the same problems...

The reset_vbo flags I use in UpdateVBO comes from miniB3d and are set if the vertexdata is changed...but here it is only provisorily, reset_vbo <> 0 would be enough.
instead of that I will adapt the lock area according to to the changed VB or IB index.

btw: I think every frame lock, fill and unlock the vertexbuffer, cant be a solution, they must only be updated if the vertexdata chaged. That also not possible with many big meshes ;) ...or did I get you wrong?

requesting a lock is the more performance breaking problem than updating the mesh unless you push a massive amount of data through it.

so a few large objects are better than a lot of small.

If you have highly dynamic objects, having meshes handled like Blitz3D does by sending them every frame again instead of have them reside on GPU is most likely the better solution due to the cost of a lock compared to the cost of a send

@Rone,

I am doing sme reading of SDK while drinking the morning Joe.

When a vertex buffer is created, CreateVertexBuffer uses the usage parameter to decide whether to process vertices in hardware or software.

If CreateDevice uses D3DCREATE_HARDWARE_VERTEXPROCESSING, CreateVertexBuffer must use 0.
If CreateDevice uses D3DCREATE_SOFTWARE_VERTEXPROCESSING, CreateVertexBuffer must use either 0 or D3DUSAGE_SOFTWAREPROCESSING. For either value, vertices will be processed in software.
If CreateDevice uses D3DCREATE_MIXED_VERTEXPROCESSING, CreateVertexBuffer can use either 0 or D3DUSAGE_SOFTWAREPROCESSING


Now this is interesting since the documentation is somewhat ambiguous as it says use that WRITE_ONLY Flag or possibly suffer performance hit.

try changing the D3D_USAGE_WRITEONLY to 0.

Other thing and here I am guessing but your using a static VB not a Dynamic buffer like I use in the Max2d implmentation.

Are you changing the object while running or is this simple test like with a cube?

Doug

One final thing before I head off to work, just looking at your code.

You use EnableVB to create the buffer. If the underlyng memory describing your VB changes your not resizing the VB. That would be a problem if you change it after creating it. Not necessairy cause of this problem but down the road would be.

Doug

Unfortunately I am at work at the moment. Later I will test changing the D3d_USAGE addicted to D3DCREATE.
This is simply a test, UpdateVB is only called on time. I will post an complete sample with an own d3d initialization, which makes also trouble using HARDWARE_VERTEXPROCESSING, but works with SOFTWARE_VERTEXPROCESSING

hmm, I think EnableVB resizes automatically the Vertexbuffer to vert_array_size, which is increase when adding a vertex.

If you have something encapsulated outside everything, Ill debug it for you :)

Doug

So, here's the sample with latest changes. Instead of using my Direct3d type for initialization, you ca also use your driver with only comment out:

If _flags & GRAPHICS_DEPTHBUFFER
			'_PresentParams.EnableAutoDepthStencil = True ' true if we want z-buffer
			'_PresentParams.AutoDepthStencilFormat=D3DFMT_D16			
		End If	
		If _flags & GRAPHICS_STENCILBUFFER
			'_PresentParams.EnableAutoDepthStencil=True ' true if we want z-buffer
			'_PresentParams.AutoDepthStencilFormat=D3DFMT_D24S8			
		End If


Warning, it's ~1200 lines of code because of TMatrix and TSurface from miniB3d.
TSurface is completely adjusted to TRenderable, which is normaly an interface implementation...
Strict

Global d3dx9Lib=LoadLibraryA( "d3dx9d_33" )
Global D3DXMatrixPerspectiveFovLH( 	pOutMatrix:Float ptr ,  fovy:Float,  Aspect:Float,  zn:Float,zf:Float ) "win32"=GetProcAddress( d3dx9Lib,"D3DXMatrixPerspectiveFovLH" )										
Global D3DXMatrixLookAtLH:Float ptr(pOutMatrix:Float ptr, pEyeVector:Float ptr,  pAtVector:Float ptr,pUpVector:Float ptr ) "win32" = GetProcAddress( d3dx9Lib,"D3DXMatrixLookAtLH" )
Global _DX9GRAPHICSEXWINDOWCLASS:Byte Ptr="DX9WinClass".ToCString()
Global D3DXVec3TransformCoord:Float ptr(pOutVector:Float ptr,  pV:Float ptr, pM:Float ptr ) "win32" = GetProcAddress( d3dx9Lib,"D3DXVec3TransformCoord" )

'#################################################################################### 


local hwnd = CreateGameWindow(800,600)
Local d3d9Graphics:Direct3d = New Direct3d
d3d9Graphics._Init(hwnd,800,600,true)
d3d9Graphics.SetClsColor(255,255,255)

'####################################################################################

TDXRenderable.D3DDevice = d3d9Graphics.GetDevice()
TDXCamera.D3DDevice = d3d9Graphics.GetDevice()
local lpD3DDevice:IDirect3DDevice9 = d3d9Graphics.GetDevice()


'####################################################################################
	
Local cam:TDXCamera = New TDXCamera

Local cube:TDXMesh = New TDXMesh.CreateCube() 
cube.PositionEntity(- 1.5, 0, 0) 

Local sphere:TDXMesh = New TDXMesh.CreateSphere() 
sphere.PositionEntity(1.5, 0, 0) 

'####################################################################################

local e:TDXEntity = new TDXEntity 
e.PositionEntity(0, 0, -10)

cam.SetMatrix(e.mat)
cam.SetViewport(10,10,780,580) 
cam.SetClippingPlanes(1,2000)



Repeat

	

	If d3d9Graphics.BeginScene()

		cam.Update() 
		cube.TurnEntity(0.0, 0.6, 0.0) 
		sphere.TurnEntity(0.0, 0.6, 0.0) 
		cube.Update() 
		sphere.Update() 
		lpD3DDevice.EndScene()

	EndIf

	lpD3DDevice.Present(Null,Null,Null,Null);

until KeyHit(Key_Escape)
End




'####################################################################################

Type TDXCamera

	Global D3DDevice:IDirect3DDevice9
	
	Global vUp		:Float[] = [0.0,1.0,0.0]
	Global vLook	:Float[] = [0.0,0.0,1.0]

	Field vLookAt		:Float[3]
	Field vWorldUp		:Float[3]
	Field vWorldLook	:Float[3]
	Field mView			:Float[16]				
	Field mProj			:Float[16]				
	Field viewport		:D3DVIEWPORT9 = New D3DVIEWPORT9					  
	Field Zoom			:Float	= 1.0			  
	Field ClearColor	:Int = $FF000000
	Field ClsMode		:Int = D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER 

	field mat:TMatrix

	method SetMatrix(m:tMatrix)
		mat = m
	end method 

	method Clear()
		D3DDevice.Clear(0,Null, ClsMode, ClearColor,1.0,0)
	end method 

	method UpdateViewPort()
		D3DDevice.SetViewport( Byte ptr(viewport) ) 
	end method 

	method Update()
		UpdateViewPort()
		Clear()
		UpdateView() 
	end method 

	Method UpdateView() 
	
		' Only rotation values are needed
		Local mCam:TMatrix = mat.Copy()
		mCam.grid[3,0] = 0.0
		mCam.grid[3,1] = 0.0
		mCam.grid[3,2] = 0.0
		
		' Transform vectors based on camera's rotation matrix
	   	D3DXVec3TransformCoord( vWorldUp, vUp, mCam.grid )
	    D3DXVec3TransformCoord( vWorldLook, vLook, mCam.grid )
		 
	    'Update the lookAt position based on the eye position 
		Local vPos:Float[] = [mat.grid[3,0],mat.grid[3,1],mat.grid[3,2]]
		vLookAt[0] = vWorldLook[0] + vPos[0]
		vLookAt[1] = vWorldLook[1] + vPos[1]
		vLookAt[2] = vWorldLook[2] + vPos[2]

		 ' Update the view matrix
    	D3DXMatrixLookAtLH(mView, vPos, vLookAt, vUp) 
    	D3DDevice.SetTransform(D3DTS_VIEW, mView) 

		' Init Projection Matrix
	    D3DXMatrixPerspectiveFovLH(mProj, Pi / 4, 800.0 / 600.0, 1.0, 300.0) 
	    D3DDevice.SetTransform(D3DTS_PROJECTION, mProj) 
		
	End Method

	Method SetViewport(x:Int, y:Int, width:Int, height:Int) 
		viewport.X = x
		viewport.Y = y
		viewport.WIDTH = WIDTH
		viewport.HEIGHT = HEIGHT											
	End Method 
	
	Method SetClippingPlanes(n:Float,f:Float)
		viewport.MinZ = n
		viewport.MaxZ = f									
	End Method 
	
	Method SetZoom(zoom:Float)
		Zoom = zoom				 									
	End Method 
	
	Method SetClsMode(p:Int, d:Int)
		ClsMode = 0
		If p Then
			ClsMode = ClsMode | D3DCLEAR_TARGET
		End If
		If d Then
			ClsMode = ClsMode | D3DCLEAR_ZBUFFER
		End If				 									
	End Method 
	
	Method SetClsColor(r:Float, g:Float , b:Float, a:Float = 1.0)
		ClearColor = $ff000000|(Int(r) Shl 16)|(Int(G) Shl 8)|Int(b)			
	End Method 

	 Method GetViewport:Int[]() 
		Return [viewport.X, viewport.Y, viewport.WIDTH, viewport.HEIGHT]
	End Method
	
End Type

'####################################################################################

Type TDXRenderable

	Const VERTEXSIZE:Int = 44
	Const INDEXSIZE:Int = 2
	
	Global D3D_VERTEX_FORMAT:Int = (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX0 | D3DFVF_TEX1) 
	Global D3D_INDEX_FORMAT:Int = D3DFMT_INDEX16
	Global D3DDevice:IDirect3DDevice9
	
	Field VertexBufferObj:IDirect3DVertexBuffer9
	Field verts:Byte Ptr
	Field no_verts:Int
	Field vert_array_size:Int
	
	Field IndexBufferObj:IDirect3DIndexBuffer9
	Field tris:Short[] 
	Field no_tris:Int
	Field tri_array_size:Int
	
	Field mat:TMatrix
	
	Method New() 
		verts = MemAlloc(1) 
		vert_array_size = 1
		tri_array_size = 1
	End Method
	
	Method Delete() 
		MemFree verts
		tris = tris[..0] 
		If VertexBufferObj Then VertexBufferObj.Release_() 
		If IndexBufferObj Then IndexBufferObj.Release_() 
	End Method
	
	Method AddVertex:Int(x:Float, y:Float, z:Float, u:Float = 0.0, v:Float = 0.0, w:Float = 0.0) 
	
		no_verts:+1
		
		If no_verts * VERTEXSIZE > vert_array_size Then
			
			Local oldSize:Int = vert_array_size
			
			Repeat
				vert_array_size = vert_array_size * 2
			Until vert_array_size > no_verts * VERTEXSIZE
			
			Local tmp_verts:Byte Ptr = MemAlloc(vert_array_size) 
			MemCopy(tmp_verts, verts, oldSize) 
			MemFree(verts) 
			verts = tmp_verts
		
		EndIf
		
		Local vId:Int = (no_verts - 1) 
		SetVertexPos(vId, x, y, z) 
		SetVertexColor(vId, 1.0, 1.0, 1.0) 
		SetVertexTexCoord(vId, u, v, 0) 
		
		Return vId
		
	End Method
	
	Method SetVertexPos(vId:Int, x:Float, y:Float, z:Float) 
		vId:*VERTEXSIZE
		Local p:Float Ptr = Float Ptr(verts + vId ) 
		p[0] = x; p[1] = y; p[2] = z
	End Method
	
	Method SetVertexNormal(vId:Int, nx:Float, ny:Float, nz:Float) 
		vId:*VERTEXSIZE
		Local p:Float Ptr = Float Ptr(verts + vId + 12) 
		p[0] = nx; p[1] = ny; p[2] = nz
	End Method
	
	Method SetVertexColor(vId:Int, r:Float, g:Float, b:Float, a:Float = 1.0) 
		vId:*VERTEXSIZE
		Local p:Int Ptr = Int Ptr(verts + vId + 24) 
		'p[0] = Int((Int(a * 255.0) Shl 24) | (Int(r * 255.0) Shl 16) | (Int(g * 255.0) Shl 8) | Int(b * 255.0)) 
		p[0] = Int((255 Shl 24) | (Rand(0, 255) Shl 16) | (Rand(0, 255) Shl 8) | Rand(0, 255)) 
	End Method
	 
	Method SetVertexTexCoord(vId:Int, u:Float, v:Float, coord:Int) 
		vId = vId * VERTEXSIZE + coord * 8
		Local p:Float Ptr = Float Ptr(verts + vId + 28) 
		p[0] = u; p[1] = v
	End Method
	
	Method GetVertexPos:Float[] (vId:Int) 
		vId:*VERTEXSIZE
		Local p:Float Ptr = Float Ptr(verts + vId) 
		Return[p[0] , p[1] , p[2] ] 
	End Method
	
	Method GetVertexNormal:Float[] (vId:Int) 
		vId:*VERTEXSIZE
		Local p:Float Ptr = Float Ptr(verts + vId + 12) 
		Return[p[0] , p[1] , p[2] ] 
	End Method
	
	Method GetVertexColor:Float[] (vId:Int) 
		vId:*VERTEXSIZE
		Local color:Int = (Float Ptr(verts + vId + 24))[0] 
		Return[Float(((color & $ff000000) Shr 24) / 255.0), Float(((color & $00ff0000) Shr 16) / 255.0),  ..
			   Float(((color & $0000ff00) Shr 8) / 255.0), Float((color & $000000ff) / 255.0)] 
	End Method
	 
	Method GetVertexTexCoord:Float[] (vId:Int, coord:Int) 
		vId = vId * VERTEXSIZE + coord * 8
		Local p:Float Ptr = Float Ptr(verts + vId + 28) 
		Return[p[0] , p[1] ] 
	End Method
	
	Method AddTriangle:Int(v0:Int, v1:Int, v2:Int) 
	
		no_tris = no_tris + 1
		
		' resize array
		If no_tris * 3 >= tri_array_size
		
			Repeat
				tri_array_size=tri_array_size*2
			Until tri_array_size > no_tris * 3
		
			tris = tris[..tri_array_size] 
			
		EndIf
		
		Local vid:Int = (no_tris * 3) 
	
		tris[vid - 3] = v2
		tris[vid - 2] = v1
		tris[vid - 1] = v0
		
		Return no_tris
		
	End Method
	
	Method SetTriAngles:Int(start:Int, count:Int, triangles:Short Ptr, srcOffset:Int = 0) 
		If tris.length < start+count Then 
			tris = tris[..(start+count)]
			no_tris =  tris.length / 3
		EndIf 
		Local dstPtr:Byte Ptr = tris
		MemCopy(dstPtr+start*2, Byte Ptr(triangles)+srcOffset*2 , count*2 )  
	End Method 
	
	Method GetTriangles:Short Ptr() 
		Return tris
	End Method 
		
	Method OverrideVertexCount(count:Int) 
		no_verts = Count
	End Method
	
	Method OverrideTrisCount(count:Int)
		no_Tris = Count
	End Method
	
	Method Clear(clear_verts:Int = True, clear_tris:Int = True) 
	
		If clear_verts
			no_verts = 0
			MemFree verts		
			vert_array_size = 1
		EndIf
		
		If clear_tris
			no_tris = 0
			tris = tris[..0] 
			tri_array_size = 1
		EndIf
	
	End Method
	
	Method FreeVBO() 
		If VertexBufferObj Then VertexBufferObj.Release_() 
		If IndexBufferObj Then IndexBufferObj.Release_() 
	End Method
	
	Method SetMatrix(Matrix:TMatrix) 
		mat = Matrix
	End Method

	Method EnableVBO(vbo_enabled:Int) 
		If vbo_enabled Then
			If D3DDevice.CreateVertexBuffer(vert_array_size, 0, D3D_VERTEX_FORMAT, D3DPOOL_DEFAULT, VertexBufferObj, Null) <> D3D_OK Then
				Assert "Failed to create VB"
			EndIf
			If D3DDevice.CreateIndexBuffer(tri_array_size, 0, D3D_INDEX_FORMAT, D3DPOOL_DEFAULT, IndexBufferObj, Null) <> D3D_OK Then
				Assert "Failed to create IB"
			EndIf
		EndIf
	End Method

	Method Update() 
		D3DDevice.SetTransform(D3DTS_WORLD, mat.grid) 
		D3DDevice.SetFVF(D3D_VERTEX_FORMAT) 
		D3DDevice.SetStreamSource(0, VertexBufferObj, 0, VERTEXSIZE) 
		D3DDevice.SetIndices(IndexBufferObj) 
		D3DDevice.DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, no_verts, 0, no_tris) 
	End Method
	
	Method CountTriangles:Int() 
		Return no_tris
	End Method
	
	Method CountVertices:Int() 
		Return no_verts
	End Method
	
	Method UpdateVBO:Int(reset_vbo:Int Var) 
		
		If Not VertexBufferObj Or Not IndexBufferObj Or reset_vbo <> 0 Then
		
			EnableVBO(True) 
						
			Local VertexBufferStart:Byte Ptr
			Local IndexBufferStart:Byte Ptr
			
			If VertexBufferObj.Lock(0, no_verts * VERTEXSIZE, VertexBufferStart, D3DLOCK_NOSYSLOCK) = D3D_OK Then
				MemCopy(VertexBufferStart, verts, no_verts * VERTEXSIZE) 
				VertexBufferObj.Unlock() 
			EndIf
			 
			If IndexBufferObj.Lock(0, no_tris * 3 * INDEXSIZE, IndexBufferStart, D3DLOCK_NOSYSLOCK) = D3D_OK Then
				MemCopy(IndexBufferStart, Byte Ptr(tris), no_tris * 3 * INDEXSIZE) 
				IndexBufferObj.Unlock() 
			EndIf

			
			reset_vbo = False
			
		EndIf

		Return True
		
	End Method
	
End Type


Type TDXEntity
	
	Field rx:Float, ry:Float, rz:Float
	Field px:Float, py:Float, pz:Float
	Field sx:Float, sy:Float, sz:Float
	
	Field mat:TMatrix = New TMatrix
	
	Method New() 
		sx = 1.0; sy = 1.0; sz = 1.0
	End Method
	
	Method PositionEntity(x:Float, y:Float, z:Float) 
	
		px=x
		py=y
		pz = z
		UpdateMat(True) 
			
	End Method
	
	Method Turnentity(x:Float, y:Float, z:Float) 
	
		Local tx:Float = -x
		Local ty:Float = y
		Local tz:Float = z
				
		rx=rx+tx
		ry=ry+ty
		rz=rz+tz
		UpdateMat(True) 

	End Method
	
	Method RotateEntity(x:Float, y:Float, z:Float) 

		rx = -x
		ry = y
		rz = z
		UpdateMat(True) 
			
	End Method
	
	Method ScaleEntity(x:Float, y:Float, z:Float, glob = False) 

		sx = x
		sy = y
		sz = z
		UpdateMat(True) 
		
	End Method
	
	Method UpdateMat(load_identity = False) 

		If load_identity=True
			mat.LoadIdentity()
			mat.Translate(px,py,pz)
			mat.Rotate(rx,ry,rz)
			mat.Scale(sx,sy,sz)
		Else
			mat.Translate(px,py,pz)
			mat.Rotate(rx,ry,rz)
			mat.Scale(sx, sy, sz) 
		EndIf
	
	End Method
	

End Type


Type TDXSurface
	
	Field rederable:TDXRenderable = New TDXRenderable
	Field reset_vbo:Int
	Field new_bounds:Int
	
	Method Delete()
		rederable.FreeVBO() 
	End Method
	
	
	Method ClearSurface(clear_verts = True, clear_tris = True) 
		Self.rederable.Clear(clear_verts,clear_tris)
	End Method
			
	Method AddVertex(x#,y#,z#,u#=0.0,v#=0.0,w#=0.0)
		Return Self.rederable.AddVertex(x,y,z,u,v,W)
	End Method
	
	Method AddTriangle(v0,v1,v2)
		reset_vbo:|1 | 2 | 16
		new_bounds=True
		Return Self.rederable.AddTriangle(v0,v1,v2)
	End Method
	
	Method CountVertices()
		Return Self.rederable.CountVertices()
	End Method
	
	Method CountTriangles()
		Return Self.rederable.CountTriangles()
	End Method
	
	Method VertexCoords(vid,x#,y#,z#)
		Self.rederable.SetVertexPos(vid,x,y,z)
		reset_vbo:|1
	End Method
			
	Method VertexColor(vid,r#,g#,b#,a#=1.0)
		Self.rederable.SetVertexColor(vid,r,G,b,a)
		reset_vbo:|8
	End Method
	
	Method VertexNormal(vid,nx#,ny#,nz#)
		Self.rederable.SetVertexNormal(vid,nx#,ny#,nz#)
		reset_vbo:|4
	End Method
	
	Method VertexTexCoords(vid,u#,v#,w#=0.0,coord_set=0)
		Self.rederable.SetVertexTexCoord(vid,u#,v#,coord_set )	
		reset_vbo:|2
	End Method
		
	Method VertexX#(vid)
		Return Self.rederable.GetVertexPos(vid)[0]
	End Method

	Method VertexY#(vid)
		Return Self.rederable.GetVertexPos(vid)[1]
	End Method
	
	Method VertexZ#(vid)
		Return Self.rederable.GetVertexPos(vid)[2] 
	End Method
	
	Method VertexRed#(vid)
		Return Self.rederable.GetVertexColor(vid)[0]*255
	End Method
	
	Method VertexGreen#(vid)
		Return Self.rederable.GetVertexColor(vid)[1]*255
	End Method
	
	Method VertexBlue#(vid)
		Return Self.rederable.GetVertexColor(vid)[2]*255
	End Method
	
	Method VertexAlpha#(vid)
		Return Self.rederable.GetVertexColor(vid)[3]*255
	End Method
	
	Method VertexNX#(vid)
		Return Self.rederable.GetVertexNormal(vid)[0]
	End Method
	
	Method VertexNY#(vid)
		Return Self.rederable.GetVertexNormal(vid)[1]
	End Method
	
	Method VertexNZ#(vid)
		Return Self.rederable.GetVertexNormal(vid)[2]
	End Method
	
	Method VertexU#(vid,coord_set=0)
		Return Self.rederable.GetVertexTexCoord(vid,coord_set)[0]
	End Method
	
	Method VertexV#(vid,coord_set=0)
		Return Self.rederable.GetVertexTexCoord(vid,coord_set)[1]
	End Method
	
	Method VertexW#(vid,coord_set=0)
		Return 0
	End Method
	
	Method TriangleVertex(tri_no,corner)
		Local tris:Short Ptr = Self.rederable.GetTriAngles()
		Local vid[3]
		tri_no=(tri_no+1)*3
		vid[0]=tris[tri_no-1]
		vid[1]=tris[tri_no-2]
		vid[2]=tris[tri_no-3]
		Return vid[corner]
	End Method
	
	Method UpdateNormals()
		'rederable.UpdateNormals()
	End Method
	
	Method TriangleNX#(tri_no)

		Local v0=Self.TriangleVertex(tri_no,0)
		Local v1=Self.TriangleVertex(tri_no,1)
		Local v2=Self.TriangleVertex(tri_no,2)
	
		'Local ax#=VertexX#(v1)-VertexX#(v0)
		Local ay#=Self.VertexY#(v1)-Self.VertexY#(v0)
		Local az#=Self.VertexZ#(v1)-Self.VertexZ#(v0)
		
		'Local bx#=VertexX#(v2)-VertexX#(v1)
		Local by#=Self.VertexY#(v2)-Self.VertexY#(v1)
		Local bz#=Self.VertexZ#(v2)-Self.VertexZ#(v1)
		
		Return (ay#*bz#)-(az#*by#)
		
	End Method

	Method TriangleNY#(tri_no)
	
		Local v0=Self.TriangleVertex(tri_no,0)
		Local v1=Self.TriangleVertex(tri_no,1)
		Local v2=Self.TriangleVertex(tri_no,2)

		Local ax#=Self.VertexX#(v1)-Self.VertexX#(v0)
		'Local ay#=VertexY#(v1)-VertexY#(v0)
		Local az#=Self.VertexZ#(v1)-Self.VertexZ#(v0)
		
		Local bx#=Self.VertexX#(v2)-Self.VertexX#(v1)
		'Local by#=VertexY#(v2)-VertexY#(v1)
		Local bz#=Self.VertexZ#(v2)-Self.VertexZ#(v1)
	
		Return (az#*bx#)-(ax#*bz#)
			
	End Method

	Method TriangleNZ#(tri_no)
	
		Local v0=Self.TriangleVertex(tri_no,0)
		Local v1=Self.TriangleVertex(tri_no,1)
		Local v2=Self.TriangleVertex(tri_no,2)
		
		Local ax#=Self.VertexX#(v1)-Self.VertexX#(v0)
		Local ay#=Self.VertexY#(v1)-Self.VertexY#(v0)
		'Local az#=VertexZ#(v1)-VertexZ#(v0)
		
		Local bx#=Self.VertexX#(v2)-Self.VertexX#(v1)
		Local by#=Self.VertexY#(v2)-Self.VertexY#(v1)
		'Local bz#=VertexZ#(v2)-VertexZ#(v1)
		
		Return (ax#*by#)-(ay#*bx#)
		
	End Method
	
	Method UpdateVBO()
		Self.rederable.UpdateVBO(reset_vbo)
		Return True
	End Method
	
	Method FreeVBO()
		Self.rederable.FreeVBO()
		Return True
	End Method
	
End Type

Type TDXMesh Extends TDXEntity
	
	Field surf_list:TList = CreateList() 
	
	
	Method CreateCube:TDXMesh() 
		Local surf:TDXSurface = New TDXSurface
		
		'DebugStop
		surf.AddVertex(-1.0,-1.0,-1.0)
		surf.AddVertex(-1.0, 1.0,-1.0)
		surf.AddVertex( 1.0, 1.0,-1.0)
		surf.AddVertex( 1.0,-1.0,-1.0)
		
		surf.AddVertex(-1.0,-1.0, 1.0)
		surf.AddVertex(-1.0, 1.0, 1.0)
		surf.AddVertex( 1.0, 1.0, 1.0)
		surf.AddVertex( 1.0,-1.0, 1.0)
			
		surf.AddVertex(-1.0,-1.0, 1.0)
		surf.AddVertex(-1.0, 1.0, 1.0)
		surf.AddVertex( 1.0, 1.0, 1.0)
		surf.AddVertex( 1.0,-1.0, 1.0)
		
		surf.AddVertex(-1.0,-1.0,-1.0)
		surf.AddVertex(-1.0, 1.0,-1.0)
		surf.AddVertex( 1.0, 1.0,-1.0)
		surf.AddVertex( 1.0,-1.0,-1.0)

		surf.AddVertex(-1.0,-1.0, 1.0)
		surf.AddVertex(-1.0, 1.0, 1.0)
		surf.AddVertex( 1.0, 1.0, 1.0)
		surf.AddVertex( 1.0,-1.0, 1.0)
		
		surf.AddVertex(-1.0,-1.0,-1.0)
		surf.AddVertex(-1.0, 1.0,-1.0)
		surf.AddVertex( 1.0, 1.0,-1.0)
		surf.AddVertex( 1.0,-1.0,-1.0)

		surf.VertexNormal(0,0.0,0.0,-1.0)
		surf.VertexNormal(1,0.0,0.0,-1.0)
		surf.VertexNormal(2,0.0,0.0,-1.0)
		surf.VertexNormal(3,0.0,0.0,-1.0)
	
		surf.VertexNormal(4,0.0,0.0,1.0)
		surf.VertexNormal(5,0.0,0.0,1.0)
		surf.VertexNormal(6,0.0,0.0,1.0)
		surf.VertexNormal(7,0.0,0.0,1.0)
		
		surf.VertexNormal(8,0.0,-1.0,0.0)
		surf.VertexNormal(9,0.0,1.0,0.0)
		surf.VertexNormal(10,0.0,1.0,0.0)
		surf.VertexNormal(11,0.0,-1.0,0.0)
				
		surf.VertexNormal(12,0.0,-1.0,0.0)
		surf.VertexNormal(13,0.0,1.0,0.0)
		surf.VertexNormal(14,0.0,1.0,0.0)
		surf.VertexNormal(15,0.0,-1.0,0.0)
	
		surf.VertexNormal(16,-1.0,0.0,0.0)
		surf.VertexNormal(17,-1.0,0.0,0.0)
		surf.VertexNormal(18,1.0,0.0,0.0)
		surf.VertexNormal(19,1.0,0.0,0.0)
				
		surf.VertexNormal(20,-1.0,0.0,0.0)
		surf.VertexNormal(21,-1.0,0.0,0.0)
		surf.VertexNormal(22,1.0,0.0,0.0)
		surf.VertexNormal(23,1.0,0.0,0.0)

		surf.VertexTexCoords(0,0.0,1.0)
		surf.VertexTexCoords(1,0.0,0.0)
		surf.VertexTexCoords(2,1.0,0.0)
		surf.VertexTexCoords(3,1.0,1.0)
		
		surf.VertexTexCoords(4,1.0,1.0)
		surf.VertexTexCoords(5,1.0,0.0)
		surf.VertexTexCoords(6,0.0,0.0)
		surf.VertexTexCoords(7,0.0,1.0)
		
		surf.VertexTexCoords(8,0.0,1.0)
		surf.VertexTexCoords(9,0.0,0.0)
		surf.VertexTexCoords(10,1.0,0.0)
		surf.VertexTexCoords(11,1.0,1.0)
			
		surf.VertexTexCoords(12,0.0,0.0)
		surf.VertexTexCoords(13,0.0,1.0)
		surf.VertexTexCoords(14,1.0,1.0)
		surf.VertexTexCoords(15,1.0,0.0)
	
		surf.VertexTexCoords(16,0.0,1.0)
		surf.VertexTexCoords(17,0.0,0.0)
		surf.VertexTexCoords(18,1.0,0.0)
		surf.VertexTexCoords(19,1.0,1.0)
				
		surf.VertexTexCoords(20,1.0,1.0)
		surf.VertexTexCoords(21,1.0,0.0)
		surf.VertexTexCoords(22,0.0,0.0)
		surf.VertexTexCoords(23,0.0,1.0)

		surf.VertexTexCoords(0,0.0,1.0,0.0,1)
		surf.VertexTexCoords(1,0.0,0.0,0.0,1)
		surf.VertexTexCoords(2,1.0,0.0,0.0,1)
		surf.VertexTexCoords(3,1.0,1.0,0.0,1)
		
		surf.VertexTexCoords(4,1.0,1.0,0.0,1)
		surf.VertexTexCoords(5,1.0,0.0,0.0,1)
		surf.VertexTexCoords(6,0.0,0.0,0.0,1)
		surf.VertexTexCoords(7,0.0,1.0,0.0,1)
		
		surf.VertexTexCoords(8,0.0,1.0,0.0,1)
		surf.VertexTexCoords(9,0.0,0.0,0.0,1)
		surf.VertexTexCoords(10,1.0,0.0,0.0,1)
		surf.VertexTexCoords(11,1.0,1.0,0.0,1)
			
		surf.VertexTexCoords(12,0.0,0.0,0.0,1)
		surf.VertexTexCoords(13,0.0,1.0,0.0,1)
		surf.VertexTexCoords(14,1.0,1.0,0.0,1)
		surf.VertexTexCoords(15,1.0,0.0,0.0,1)
	
		surf.VertexTexCoords(16,0.0,1.0,0.0,1)
		surf.VertexTexCoords(17,0.0,0.0,0.0,1)
		surf.VertexTexCoords(18,1.0,0.0,0.0,1)
		surf.VertexTexCoords(19,1.0,1.0,0.0,1)
				
		surf.VertexTexCoords(20,1.0,1.0,0.0,1)
		surf.VertexTexCoords(21,1.0,0.0,0.0,1)
		surf.VertexTexCoords(22,0.0,0.0,0.0,1)
		surf.VertexTexCoords(23,0.0,1.0,0.0,1)
				
		surf.AddTriangle(0,1,2) ' front
		surf.AddTriangle(0,2,3)
		surf.AddTriangle(6,5,4) ' back
		surf.AddTriangle(7,6,4)
		surf.AddTriangle(6+8,5+8,1+8) ' top
		surf.AddTriangle(2+8,6+8,1+8)
		surf.AddTriangle(0+8,4+8,7+8) ' bottom
		surf.AddTriangle(0+8,7+8,3+8)
		surf.AddTriangle(6+16,2+16,3+16) ' right
		surf.AddTriangle(7+16,6+16,3+16)
		surf.AddTriangle(0+16,1+16,5+16) ' left
		surf.AddTriangle(0 + 16, 5 + 16, 4 + 16) 
		
		surf_list.AddLast(surf) 
		
		Return Self
	End Method
	
	' Function by Coyote
	Method CreateSphere:TDXMesh(segments = 8) 

		If segments<2 Or segments>100 Then Return Null
		
		Local thissurf:TDXSurface = New TDXSurface

		Local div#=Float(360.0/(segments*2))
		Local height#=1.0
		Local upos#=1.0
		Local udiv#=Float(1.0/(segments*2))
		Local vdiv#=Float(1.0/segments)
		Local RotAngle#=90	
	
		If segments=2 ' diamond shape - no center strips
		
			For Local i=1 To (segments*2)
				Local np=thissurf.AddVertex(0.0,height,0.0,upos#-(udiv#/2.0),0)'northpole
				Local sp=thissurf.AddVertex(0.0,-height,0.0,upos#-(udiv#/2.0),1)'southpole
				Local XPos#=-Cos(RotAngle#)
				Local ZPos#=Sin(RotAngle#)
				Local v0=thissurf.AddVertex(XPos#,0,ZPos#,upos#,0.5)
				RotAngle#=RotAngle#+div#
				If RotAngle#>=360.0 Then RotAngle#=RotAngle#-360.0
				XPos#=-Cos(RotAngle#)
				ZPos#=Sin(RotAngle#)
				upos#=upos#-udiv#
				Local v1=thissurf.AddVertex(XPos#,0,ZPos#,upos#,0.5)
				thissurf.AddTriangle(np,v0,v1)
				thissurf.AddTriangle(v1,v0,sp)	
			Next
			
		Else ' have center strips now
		
			' poles first
			For Local i=1 To (segments*2)
				
				Local np=thissurf.AddVertex(0.0,height,0.0,upos#-(udiv#/2.0),0)'northpole
				Local sp=thissurf.AddVertex(0.0,-height,0.0,upos#-(udiv#/2.0),1)'southpole
				
				Local YPos#=Cos(div#)
				
				Local XPos#=-Cos(RotAngle#)*(Sin(div#))
				Local ZPos#=Sin(RotAngle#)*(Sin(div#))
				
				Local v0t=thissurf.AddVertex(XPos#,YPos#,ZPos#,upos#,vdiv#)
				Local v0b=thissurf.AddVertex(XPos#,-YPos#,ZPos#,upos#,1-vdiv#)
				
				RotAngle#=RotAngle#+div#
				
				XPos#=-Cos(RotAngle#)*(Sin(div#))
				ZPos#=Sin(RotAngle#)*(Sin(div#))
				
				upos#=upos#-udiv#
	
				Local v1t=thissurf.AddVertex(XPos#,YPos#,ZPos#,upos#,vdiv#)
				Local v1b=thissurf.AddVertex(XPos#,-YPos#,ZPos#,upos#,1-vdiv#)
				
				thissurf.AddTriangle(np,v0t,v1t)
				thissurf.AddTriangle(v1b,v0b,sp)	
				
			Next
			
			' then center strips
	
			upos#=1.0
			RotAngle#=90
			For Local i=1 To (segments*2)
			
				Local mult#=1
				Local YPos#=Cos(div#*(mult#))
				Local YPos2#=Cos(div#*(mult#+1.0))
				Local Thisvdiv#=vdiv#
				For Local j=1 To (segments-2)
	
					
					Local XPos#=-Cos(RotAngle#)*(Sin(div#*(mult#)))
					Local ZPos#=Sin(RotAngle#)*(Sin(div#*(mult#)))
	
					Local XPos2#=-Cos(RotAngle#)*(Sin(div#*(mult#+1.0)))
					Local ZPos2#=Sin(RotAngle#)*(Sin(div#*(mult#+1.0)))
								
					Local v0t=thissurf.AddVertex(XPos#,YPos#,ZPos#,upos#,Thisvdiv#)
					Local v0b=thissurf.AddVertex(XPos2#,YPos2#,ZPos2#,upos#,Thisvdiv#+vdiv#)
				
					' 2nd tex coord set
					thissurf.VertexTexCoords(v0t,upos#,Thisvdiv#,0.0,1)
					thissurf.VertexTexCoords(v0b,upos#,Thisvdiv#+vdiv#,0.0,1)
				
					Local tempRotAngle#=RotAngle#+div#
				
					XPos#=-Cos(tempRotAngle#)*(Sin(div#*(mult#)))
					ZPos#=Sin(tempRotAngle#)*(Sin(div#*(mult#)))
					
					XPos2#=-Cos(tempRotAngle#)*(Sin(div#*(mult#+1.0)))
					ZPos2#=Sin(tempRotAngle#)*(Sin(div#*(mult#+1.0)))				
				
					Local temp_upos#=upos#-udiv#
	
					Local v1t=thissurf.AddVertex(XPos#,YPos#,ZPos#,temp_upos#,Thisvdiv#)
					Local v1b=thissurf.AddVertex(XPos2#,YPos2#,ZPos2#,temp_upos#,Thisvdiv#+vdiv#)
					
					' 2nd tex coord set
					thissurf.VertexTexCoords(v1t,temp_upos#,Thisvdiv#,0.0,1)
					thissurf.VertexTexCoords(v1b,temp_upos#,Thisvdiv#+vdiv#,0.0,1)
					
					thissurf.AddTriangle(v1t,v0t,v0b)
					thissurf.AddTriangle(v1b,v1t,v0b)
					
					Thisvdiv#=Thisvdiv#+vdiv#			
					mult#=mult#+1
					YPos#=Cos(div#*(mult#))
					YPos2#=Cos(div#*(mult#+1.0))
				
				Next
				upos#=upos#-udiv#
				RotAngle#=RotAngle#+div#
			Next
	
		EndIf
	
		'thissphere.UpdateNormals() 
	
		surf_list.AddLast(thissurf) 
		Return Self
	End Method
	
	Method Update() 
		For Local surf:TDXSurface = EachIn surf_list
			If surf.reset_vbo Then surf.UpdateVBO() 
			surf.rederable.SetMatrix(mat) 
			surf.rederable.Update() 
		Next
	End Method
	           
End Type

Type Direct3d

	Field clsColor				:Int 					= $FF000000
	Field Direct3D9 			:IDirect3D9				= Null 
	Field Direct3DDevice9		:IDirect3DDevice9		= Null
	Field BackBuffer			:IDirect3DSurface9 		= Null
	Field PParams				:D3DPRESENT_PARAMETERS  = Null
	Field hwnd					:Int 					= 0

	Method _Init(hwnd:Int, w:Int, h:Int, bWindowed:Int = False) 


		Self.hwnd = hwnd
		
		Direct3D9 = Direct3DCreate9( $900 )

		If Not Direct3D9  Then 
			assert "error creating d3d9interface!"
		EndIf
		
		PParams = New D3DPRESENT_PARAMETERS
		
		PParams.SwapEffect       = D3DSWAPEFFECT_DISCARD;
	    PParams.hDeviceWindow    = hwnd;
	    PParams.Windowed         = bWindowed;
	    PParams.BackBufferWidth  = w;
	    PParams.BackBufferHeight = h;
	    PParams.BackBufferFormat = D3DFMT_A8R8G8B8;

		PParams.EnableAutoDepthStencil = True 
		PParams.AutoDepthStencilFormat=D3DFMT_D16	
		
		
		If Direct3D9.CreateDevice(0, D3DDEVTYPE_HAL, hwnd , D3DCREATE_PUREDEVICE | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, PParams, Direct3DDevice9) <> D3D_OK
			If Direct3D9.CreateDevice(0, D3DDEVTYPE_HAL, hwnd , D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, PParams, Direct3DDevice9) <> D3D_OK
				If Direct3D9.CreateDevice(0, D3DDEVTYPE_HAL, hwnd , D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, PParams, Direct3DDevice9) <> D3D_OK
				    assert "failed To create device _D3dDev9"
				End If
			End If
		EndIf
		


		Direct3DDevice9.GetBackBuffer(0,0, D3DBACKBUFFER_TYPE_MONO, BackBuffer );


		Direct3DDevice9.SetRenderState(D3DRS_AMBIENT, $00FFFFFF) 
		Direct3DDevice9.SetRenderState(D3DRS_LIGHTING, false) 
		Direct3DDevice9.SetRenderState(D3DRS_CULLMODE, D3DCULL_CW) 
		Direct3DDevice9.SetRenderState(D3DRS_DITHERENABLE, true) 
		

	End Method 

	Method SetClsColor(r:Int,g:Int,b:Int)
		clsColor = Int(( 255 Shl 24)| (r Shl 16)| (g Shl 8)| b )
	End Method 

	Method BeginScene()
		'Direct3DDevice9.Clear(0,Null,D3DCLEAR_TARGET,clsColor,0,0);
		return Direct3DDevice9.BeginScene();
    End Method 

	Method EndScene()
		Direct3DDevice9.EndScene();
    	Direct3DDevice9.Present(Null,Null,Null,Null);
	End Method 

	Method GetDevice:IDirect3DDevice9()
		Return 	Direct3DDevice9
	End Method 

	Method GetBackBuffer:IDirect3DSurface9()
		Return BackBuffer
	End Method 

	method SetAmbientLight(color:int = $00FFFFFF)
		Direct3DDevice9.SetRenderState(D3DRS_AMBIENT, color) 
	end method 

	method SetLightningEnable(enable:int)
		Direct3DDevice9.SetRenderState(D3DRS_LIGHTING, enable) 
	end method 

	method SetCullMode(mode:int = D3DCULL_CW )
		Direct3DDevice9.SetRenderState(D3DRS_CULLMODE, mode ) 
	end method 
	
	method SetDitherEnable(enable:int = true)
		Direct3DDevice9.SetRenderState(D3DRS_DITHERENABLE, enable) 
	end method 

End Type

Type TMatrix

	Field grid#[4,4]
	

	
	Method LoadIdentity()
	
		grid[0,0]=1.0
		grid[1,0]=0.0
		grid[2,0]=0.0
		grid[3,0]=0.0
		grid[0,1]=0.0
		grid[1,1]=1.0
		grid[2,1]=0.0
		grid[3,1]=0.0
		grid[0,2]=0.0
		grid[1,2]=0.0
		grid[2,2]=1.0
		grid[3,2]=0.0
		
		grid[0,3]=0.0
		grid[1,3]=0.0
		grid[2,3]=0.0
		grid[3,3]=1.0
	
	End Method
	
	' copy - create new copy and returns it
	
	Method Copy:TMatrix()
	
		Local mat:TMatrix=New TMatrix
	
		mat.grid[0,0]=grid[0,0]
		mat.grid[1,0]=grid[1,0]
		mat.grid[2,0]=grid[2,0]
		mat.grid[3,0]=grid[3,0]
		mat.grid[0,1]=grid[0,1]
		mat.grid[1,1]=grid[1,1]
		mat.grid[2,1]=grid[2,1]
		mat.grid[3,1]=grid[3,1]
		mat.grid[0,2]=grid[0,2]
		mat.grid[1,2]=grid[1,2]
		mat.grid[2,2]=grid[2,2]
		mat.grid[3,2]=grid[3,2]
		
		' do not remove
		mat.grid[0,3]=grid[0,3]
		mat.grid[1,3]=grid[1,3]
		mat.grid[2,3]=grid[2,3]
		mat.grid[3,3]=grid[3,3]
		
		Return mat
	
	End Method
	
	' overwrite - overwrites self with matrix passed as parameter
	
	Method Overwrite(mat:TMatrix)
	
		grid[0,0]=mat.grid[0,0]
		grid[1,0]=mat.grid[1,0]
		grid[2,0]=mat.grid[2,0]
		grid[3,0]=mat.grid[3,0]
		grid[0,1]=mat.grid[0,1]
		grid[1,1]=mat.grid[1,1]
		grid[2,1]=mat.grid[2,1]
		grid[3,1]=mat.grid[3,1]
		grid[0,2]=mat.grid[0,2]
		grid[1,2]=mat.grid[1,2]
		grid[2,2]=mat.grid[2,2]
		grid[3,2]=mat.grid[3,2]
		
		grid[0,3]=mat.grid[0,3]
		grid[1,3]=mat.grid[1,3]
		grid[2,3]=mat.grid[2,3]
		grid[3,3]=mat.grid[3,3]
		
	End Method
	
	Method Inverse:TMatrix()

		Local mat:TMatrix=New TMatrix
	
		Local tx#=0
		Local ty#=0
		Local tz#=0
	
	  	' The rotational part of the matrix is simply the transpose of the
	  	' original matrix.
	  	mat.grid[0,0] = grid[0,0]
	  	mat.grid[1,0] = grid[0,1]
	  	mat.grid[2,0] = grid[0,2]
	
		mat.grid[0,1] = grid[1,0]
		mat.grid[1,1] = grid[1,1]
		mat.grid[2,1] = grid[1,2]
	
		mat.grid[0,2] = grid[2,0]
		mat.grid[1,2] = grid[2,1]
		mat.grid[2,2] = grid[2,2]
	
		' The right column vector of the matrix should always be [ 0 0 0 1 ]
		' in most cases. . . you don't need this column at all because it'll 
		' never be used in the program, but since this code is used with GL
		' and it does consider this column, it is here.
		mat.grid[0,3] = 0 
		mat.grid[1,3] = 0
		mat.grid[2,3] = 0
		mat.grid[3,3] = 1
	
		' The translation components of the original matrix.
		tx = grid[3,0]
		ty = grid[3,1]
		tz = grid[3,2]
	
		' Result = -(Tm * Rm) To get the translation part of the inverse
		mat.grid[3,0] = -( (grid[0,0] * tx) + (grid[0,1] * ty) + (grid[0,2] * tz) )
		mat.grid[3,1] = -( (grid[1,0] * tx) + (grid[1,1] * ty) + (grid[1,2] * tz) )
		mat.grid[3,2] = -( (grid[2,0] * tx) + (grid[2,1] * ty) + (grid[2,2] * tz) )
	
		Return mat

	End Method

	Method Multiply(mat:TMatrix)
	
		Local m00# = grid#[0,0]*mat.grid#[0,0] + grid#[1,0]*mat.grid#[0,1] + grid#[2,0]*mat.grid#[0,2] + grid#[3,0]*mat.grid#[0,3]
		Local m01# = grid#[0,1]*mat.grid#[0,0] + grid#[1,1]*mat.grid#[0,1] + grid#[2,1]*mat.grid#[0,2] + grid#[3,1]*mat.grid#[0,3]
		Local m02# = grid#[0,2]*mat.grid#[0,0] + grid#[1,2]*mat.grid#[0,1] + grid#[2,2]*mat.grid#[0,2] + grid#[3,2]*mat.grid#[0,3]
		'Local m03# = grid#[0,3]*mat.grid#[0,0] + grid#[1,3]*mat.grid#[0,1] + grid#[2,3]*mat.grid#[0,2] + grid#[3,3]*mat.grid#[0,3]
		Local m10# = grid#[0,0]*mat.grid#[1,0] + grid#[1,0]*mat.grid#[1,1] + grid#[2,0]*mat.grid#[1,2] + grid#[3,0]*mat.grid#[1,3]
		Local m11# = grid#[0,1]*mat.grid#[1,0] + grid#[1,1]*mat.grid#[1,1] + grid#[2,1]*mat.grid#[1,2] + grid#[3,1]*mat.grid#[1,3]
		Local m12# = grid#[0,2]*mat.grid#[1,0] + grid#[1,2]*mat.grid#[1,1] + grid#[2,2]*mat.grid#[1,2] + grid#[3,2]*mat.grid#[1,3]
		'Local m13# = grid#[0,3]*mat.grid#[1,0] + grid#[1,3]*mat.grid#[1,1] + grid#[2,3]*mat.grid#[1,2] + grid#[3,3]*mat.grid#[1,3]
		Local m20# = grid#[0,0]*mat.grid#[2,0] + grid#[1,0]*mat.grid#[2,1] + grid#[2,0]*mat.grid#[2,2] + grid#[3,0]*mat.grid#[2,3]
		Local m21# = grid#[0,1]*mat.grid#[2,0] + grid#[1,1]*mat.grid#[2,1] + grid#[2,1]*mat.grid#[2,2] + grid#[3,1]*mat.grid#[2,3]
		Local m22# = grid#[0,2]*mat.grid#[2,0] + grid#[1,2]*mat.grid#[2,1] + grid#[2,2]*mat.grid#[2,2] + grid#[3,2]*mat.grid#[2,3]
		'Local m23# = grid#[0,3]*mat.grid#[2,0] + grid#[1,3]*mat.grid#[2,1] + grid#[2,3]*mat.grid#[2,2] + grid#[3,3]*mat.grid#[2,3]
		Local m30# = grid#[0,0]*mat.grid#[3,0] + grid#[1,0]*mat.grid#[3,1] + grid#[2,0]*mat.grid#[3,2] + grid#[3,0]*mat.grid#[3,3]
		Local m31# = grid#[0,1]*mat.grid#[3,0] + grid#[1,1]*mat.grid#[3,1] + grid#[2,1]*mat.grid#[3,2] + grid#[3,1]*mat.grid#[3,3]
		Local m32# = grid#[0,2]*mat.grid#[3,0] + grid#[1,2]*mat.grid#[3,1] + grid#[2,2]*mat.grid#[3,2] + grid#[3,2]*mat.grid#[3,3]
		'Local m33# = grid#[0,3]*mat.grid#[3,0] + grid#[1,3]*mat.grid#[3,1] + grid#[2,3]*mat.grid#[3,2] + grid#[3,3]*mat.grid#[3,3]
	
		grid[0,0]=m00
		grid[0,1]=m01
		grid[0,2]=m02
		'grid[0,3]=m03
		grid[1,0]=m10
		grid[1,1]=m11
		grid[1,2]=m12
		'grid[1,3]=m13
		grid[2,0]=m20
		grid[2,1]=m21
		grid[2,2]=m22
		'grid[2,3]=m23
		grid[3,0]=m30
		grid[3,1]=m31
		grid[3,2]=m32
		'grid[3,3]=m33
		
	End Method

	Method Translate(x#,y#,z#)
	
		grid[3,0] = grid#[0,0]*x# + grid#[1,0]*y# + grid#[2,0]*z# + grid#[3,0]
		grid[3,1] = grid#[0,1]*x# + grid#[1,1]*y# + grid#[2,1]*z# + grid#[3,1]
		grid[3,2] = grid#[0,2]*x# + grid#[1,2]*y# + grid#[2,2]*z# + grid#[3,2]

	End Method
		
	Method Scale(x#,y#,z#)
	
		grid[0,0] = grid#[0,0]*x#
		grid[0,1] = grid#[0,1]*x#
		grid[0,2] = grid#[0,2]*x#

		grid[1,0] = grid#[1,0]*y#
		grid[1,1] = grid#[1,1]*y#
		grid[1,2] = grid#[1,2]*y#

		grid[2,0] = grid#[2,0]*z#
		grid[2,1] = grid#[2,1]*z#
		grid[2,2] = grid#[2,2]*z# 
	
	End Method
	
	Method Rotate(rx#,ry#,rz#)
	
		Local cos_ang#,sin_ang#
	
		' yaw
	
		cos_ang#=Cos(ry#)
		sin_ang#=Sin(ry#)
	
		Local m00# = grid#[0,0]*cos_ang + grid#[2,0]*-sin_ang#
		Local m01# = grid#[0,1]*cos_ang + grid#[2,1]*-sin_ang#
		Local m02# = grid#[0,2]*cos_ang + grid#[2,2]*-sin_ang#

		grid[2,0] = grid#[0,0]*sin_ang# + grid#[2,0]*cos_ang
		grid[2,1] = grid#[0,1]*sin_ang# + grid#[2,1]*cos_ang
		grid[2,2] = grid#[0,2]*sin_ang# + grid#[2,2]*cos_ang

		grid[0,0]=m00#
		grid[0,1]=m01#
		grid[0,2]=m02#
		
		' pitch
		
		cos_ang#=Cos(rx#)
		sin_ang#=Sin(rx#)
	
		Local m10# = grid#[1,0]*cos_ang + grid#[2,0]*sin_ang
		Local m11# = grid#[1,1]*cos_ang + grid#[2,1]*sin_ang
		Local m12# = grid#[1,2]*cos_ang + grid#[2,2]*sin_ang

		grid[2,0] = grid#[1,0]*-sin_ang + grid#[2,0]*cos_ang
		grid[2,1] = grid#[1,1]*-sin_ang + grid#[2,1]*cos_ang
		grid[2,2] = grid#[1,2]*-sin_ang + grid#[2,2]*cos_ang

		grid[1,0]=m10
		grid[1,1]=m11
		grid[1,2]=m12
		
		' roll
		
		cos_ang#=Cos(rz#)
		sin_ang#=Sin(rz#)

		m00# = grid#[0,0]*cos_ang# + grid#[1,0]*sin_ang#
		m01# = grid#[0,1]*cos_ang# + grid#[1,1]*sin_ang#
		m02# = grid#[0,2]*cos_ang# + grid#[1,2]*sin_ang#

		grid[1,0] = grid#[0,0]*-sin_ang# + grid#[1,0]*cos_ang#
		grid[1,1] = grid#[0,1]*-sin_ang# + grid#[1,1]*cos_ang#
		grid[1,2] = grid#[0,2]*-sin_ang# + grid#[1,2]*cos_ang#

		grid[0,0]=m00#
		grid[0,1]=m01#
		grid[0,2]=m02#
	
	End Method
	
	Method RotatePitch(ang#)
	
		Local cos_ang#=Cos(ang#)
		Local sin_ang#=Sin(ang#)
	
		Local m10# = grid#[1,0]*cos_ang + grid#[2,0]*sin_ang
		Local m11# = grid#[1,1]*cos_ang + grid#[2,1]*sin_ang
		Local m12# = grid#[1,2]*cos_ang + grid#[2,2]*sin_ang

		grid[2,0] = grid#[1,0]*-sin_ang + grid#[2,0]*cos_ang
		grid[2,1] = grid#[1,1]*-sin_ang + grid#[2,1]*cos_ang
		grid[2,2] = grid#[1,2]*-sin_ang + grid#[2,2]*cos_ang

		grid[1,0]=m10
		grid[1,1]=m11
		grid[1,2]=m12

	End Method
	
	Method RotateYaw(ang#)
	
		Local cos_ang#=Cos(ang#)
		Local sin_ang#=Sin(ang#)
	
		Local m00# = grid#[0,0]*cos_ang + grid#[2,0]*-sin_ang#
		Local m01# = grid#[0,1]*cos_ang + grid#[2,1]*-sin_ang#
		Local m02# = grid#[0,2]*cos_ang + grid#[2,2]*-sin_ang#

		grid[2,0] = grid#[0,0]*sin_ang# + grid#[2,0]*cos_ang
		grid[2,1] = grid#[0,1]*sin_ang# + grid#[2,1]*cos_ang
		grid[2,2] = grid#[0,2]*sin_ang# + grid#[2,2]*cos_ang

		grid[0,0]=m00#
		grid[0,1]=m01#
		grid[0,2]=m02#

	End Method
	
	Method RotateRoll(ang#)
	
		Local cos_ang#=Cos(ang#)
		Local sin_ang#=Sin(ang#)

		Local m00# = grid#[0,0]*cos_ang# + grid#[1,0]*sin_ang#
		Local m01# = grid#[0,1]*cos_ang# + grid#[1,1]*sin_ang#
		Local m02# = grid#[0,2]*cos_ang# + grid#[1,2]*sin_ang#

		grid[1,0] = grid#[0,0]*-sin_ang# + grid#[1,0]*cos_ang#
		grid[1,1] = grid#[0,1]*-sin_ang# + grid#[1,1]*cos_ang#
		grid[1,2] = grid#[0,2]*-sin_ang# + grid#[1,2]*cos_ang#

		grid[0,0]=m00#
		grid[0,1]=m01#
		grid[0,2]=m02#

	End Method
		
End Type



Type TRect
	Field _Left	:Int
	Field _Top	: Int
	Field _Right : Int
	Field _Bottom: Int
	
	Function Create:TRect(ALeft:Int,ATop:Int,ARight:Int,ABottom:Int)
		Local this:TRect=New TRect
		this._Left=ALeft
		this._Top=ATop
		this._Right=ARight		
		this._Bottom=ABottom
		Return this
	End Function
	Method Width:Int()
		Return _Right-_Left
	End Method
	Method Height:Int()
		Return _Bottom-_Top
	End Method
End Type

Function WndProc:Int( hwnd:Int,message:Int,wp:Int,lp:Int ) "win32"
	bbSystemEmitOSEvent hwnd,message,wp,lp,Null
	Select message
	Case WM_CLOSE
		end 
	Case WM_SYSKEYDOWN
		If wp<>KEY_F4 Return 0
	' ensure the valid Flag is current due to mode/focus changes	
	Case WM_SETFOCUS		
		'_dx9driver.ValidateGraphics
	' ensure the valid Flag is current due to mode/focus changes		
	Case WM_KILLFOCUS
		'_dx9driver.ValidateGraphics
	End Select
	Return DefWindowProcA( hwnd,message,wp,lp )
End Function

function CreateGameWindow:int(width:int, height:int )
	Local wc:WNDCLASS=New WNDCLASS
	wc.hInstance = GetModuleHandleA(0) 
	wc.lpfnWndProc = WndProc
	wc.hCursor=LoadCursorA( Null,Byte Ptr IDC_ARROW )
	wc.lpszClassName=_DX9GRAPHICSEXWINDOWCLASS
	RegisterClassA( wc )

	Local hinst:Int = GetModuleHandleA(0) 
	Local title:Byte Ptr=AppTitle.ToCString()
	
	Local hwnd:Int
	width:int = 800
	height:int = 600
	Local style:Int=WS_VISIBLE|WS_CAPTION|WS_SYSMENU |WS_SIZEBOX 
	Local rect :TRect = TRect.Create(32,32,width+32,height+32)
	AdjustWindowRect Int Ptr Byte Ptr rect,style,0
	width=rect.Width()
	height=rect.Height()

	hwnd=CreateWindowExA( 0,_DX9GRAPHICSEXWINDOWCLASS,title,style,rect._Left,rect._Top,width,height,0,0,hinst,Null )
	return hwnd
end function


Edit:
hmm, if I create the window with CreateWindowExA insted of using a maxgui window, the programm also chrashes at device.present, when using D3DCREATE_SOFTWARE_VERTEXPROCESSING...same as using your d3d9GraphicsDriver :)

Edit:
ok, _PresentParams.EnableAutoDepthStencil = True works also fine...I yust must clear the zBuffer( Field ClsMode :Int = D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER ) :)

I found it :)

Its a bug in the way you are allocating and locking the Index Buffer.

I am trying to figure out exactly what it should say but thought I would share what I found.

Reason sometimes it works sometimes it does depends on logic that resizes the index and vertex buffers.


Doug

awesome...big thanks :)

I changed the d3dx to one I had so you will need change it back to one you want to use.

Changes that I remember doing :)
If D3DDevice.CreateIndexBuffer(tri_array_size*INDEXSIZE,D3DUSAGE_WRITEONLY, D3D_INDEX_FORMAT, D3DPOOL_DEFAULT, IndexBufferObj, Null) <> D3D_OK Then
				Assert "Failed to create IB"
			EndIf


Need to multiply by indexsize since tri_array_size is number of elements not number of bytes added back D3DUSAGE_WRITEONLY directx9 debugger complained it needed to be there counter to documentation.

Method BeginScene()
		Direct3DDevice9.Clear(0,Null,D3DCLEAR_TARGET,clsColor,0,0);
    	Return Direct3DDevice9.BeginScene()=0
	End Method


You are expecting this to be true if succesful. All DirectX call return zero on succuss, if winapi returns HRESULT 0 means success.

There is a bunch of debug code i put in to track down to bad indexbuffer size.

Let me know if it now shows what you expect.

Doug




Strict

Global d3dx9Lib=LoadLibraryA( "d3dx9_35" )
If  d3dx9Lib Print "d3dx9Lib loaded"
Global D3DXMatrixPerspectiveFovLH( 	pOutMatrix:Float Ptr ,  fovy:Float,  Aspect:Float,  zn:Float,zf:Float ) "win32"=GetProcAddress( d3dx9Lib,"D3DXMatrixPerspectiveFovLH" )										
Global D3DXMatrixLookAtLH:Float Ptr(pOutMatrix:Float Ptr, pEyeVector:Float Ptr,  pAtVector:Float Ptr,pUpVector:Float Ptr ) "win32" = GetProcAddress( d3dx9Lib,"D3DXMatrixLookAtLH" )
Global _DX9GRAPHICSEXWINDOWCLASS:Byte Ptr="DX9WinClass".ToCString()


'#################################################################################### 


Local hwnd = CreateGameWindow(800,600)
Local d3d9Graphics:Direct3d = New Direct3d
d3d9Graphics._Init(hwnd,800,600,True)


'####################################################################################

TDXRenderable.D3DDevice = d3d9Graphics.GetDevice()
TDXCamera.D3DDevice = d3d9Graphics.GetDevice()
Local lpD3DDevice:IDirect3DDevice9 = d3d9Graphics.GetDevice()


'####################################################################################
	
Local cam:TDXCamera = New TDXCamera

Local cube:TDXMesh = New TDXMesh.CreateCube() 
cube.PositionEntity(- 1.5, 0, 0) 
'Rem
Local sphere:TDXMesh = New TDXMesh.CreateSphere() 
sphere.PositionEntity(1.5, 0, 0) 
'End Rem
'####################################################################################

Repeat

	If d3d9Graphics.BeginScene()

		cam.Update() 
		cube.TurnEntity(0.0, 0.6, 0.0) 
	sphere.TurnEntity(0.0, 0.6, 0.0) 
		cube.Update() 
		sphere.Update() 
		d3d9Graphics.EndScene()

	EndIf

	'lpD3DDevice.Present(Null,Null,Null,Null);

Until KeyHit(Key_Escape)
End




'####################################################################################

Type TDXCamera
	Global D3DDevice:IDirect3DDevice9
	
	Method Update() 
	
		Local ViewMatrix:Float[16] 
		Local pos:Float[] =[0.0, 0.0, - 10.0] 
		Local lookAt:Float[] =[0.0, 0.0, 0.0] 
		Local up:Float[] =[0.0, 1.0, 0.0] 
    	D3DXMatrixLookAtLH(ViewMatrix, pos, lookAt, up) 
    	D3DDevice.SetTransform(D3DTS_VIEW, ViewMatrix) 

		Local ProjMatrix:Float[16] 
	    D3DXMatrixPerspectiveFovLH(ProjMatrix, Pi / 4, 800.0 / 600.0, 1.0, 300.0) 
	    D3DDevice.SetTransform(D3DTS_PROJECTION, ProjMatrix) 
		
	End Method
	
End Type

'####################################################################################

Type TDXRenderable

	Const VERTEXSIZE:Int = 44
	Const INDEXSIZE:Int = 2
	'                                  12            12              4             8              8
	Global D3D_VERTEX_FORMAT:Int = (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX0 | D3DFVF_TEX1) 
	Global D3D_INDEX_FORMAT:Int = D3DFMT_INDEX16
	Global D3DDevice:IDirect3DDevice9
	
	Field VertexBufferObj:IDirect3DVertexBuffer9
	Field verts:Byte Ptr
	Field no_verts:Int
	Field vert_array_size:Int
	
	Field IndexBufferObj:IDirect3DIndexBuffer9
	Field tris:Short[] 
	Field no_tris:Int
	Field tri_array_size:Int
	
	Field mat:TMatrix
	
	Method New() 
		verts = MemAlloc(1) 
		vert_array_size = 1
		tri_array_size = 1
	End Method
	
	Method Delete() 
		MemFree verts
		tris = tris[..0] 
		If VertexBufferObj Then VertexBufferObj.Release_() 
		If IndexBufferObj Then IndexBufferObj.Release_() 
	End Method
	
	Method AddVertex:Int(x:Float, y:Float, z:Float, u:Float = 0.0, v:Float = 0.0, w:Float = 0.0) 
	
		no_verts:+1
		
		If no_verts * VERTEXSIZE > vert_array_size Then
			
			Local oldSize:Int = vert_array_size
			
			Repeat
				vert_array_size = vert_array_size * 2
			Until vert_array_size > no_verts * VERTEXSIZE
			Print "newsize"+vert_array_size
			Local tmp_verts:Byte Ptr = MemAlloc(vert_array_size) 
			MemCopy(tmp_verts, verts, oldSize) 
			MemFree(verts) 
			verts = tmp_verts
		
		EndIf
		
		Local vId:Int = (no_verts - 1) 
		SetVertexPos(vId, x, y, z) 
		SetVertexColor(vId, 1.0, 1.0, 1.0) 
		'SetVertexTexCoord(vId, u, v, 0) 
		'SetVertexTexCoord(vId, u, v, 1) 
		Return vId
		
	End Method
	
	Method SetVertexPos(vId:Int, x:Float, y:Float, z:Float) 
		vId:*VERTEXSIZE
		Local p:Float Ptr = Float Ptr(verts + vId ) 
		p[0] = x; p[1] = y; p[2] = z
	End Method
	
	Method SetVertexNormal(vId:Int, nx:Float, ny:Float, nz:Float) 
		vId:*VERTEXSIZE
		Local p:Float Ptr = Float Ptr(verts + vId + 12) 
		p[0] = nx; p[1] = ny; p[2] = nz
	End Method
	
	Method SetVertexColor(vId:Int, r:Float, g:Float, b:Float, a:Float = 1.0) 
		vId:*VERTEXSIZE
		Local p:Int Ptr = Int Ptr(verts + vId + 24) 
		'p[0] = Int((Int(a * 255.0) Shl 24) | (Int(r * 255.0) Shl 16) | (Int(g * 255.0) Shl 8) | Int(b * 255.0)) 
		p[0] = Int((255 Shl 24) | (Rand(0, 255) Shl 16) | (Rand(0, 255) Shl 8) | Rand(0, 255)) 
	End Method
	 
	Method SetVertexTexCoord(vId:Int, u:Float, v:Float, coord:Int) 
		vId = vId * VERTEXSIZE + coord * 8
		Local p:Float Ptr = Float Ptr(verts + vId + 28) 
		p[0] = u; p[1] = v
	End Method
	
	Method GetVertexPos:Float[] (vId:Int) 
		vId:*VERTEXSIZE
		Local p:Float Ptr = Float Ptr(verts + vId) 
		Return[p[0] , p[1] , p[2] ] 
	End Method
	
	Method GetVertexNormal:Float[] (vId:Int) 
		vId:*VERTEXSIZE
		Local p:Float Ptr = Float Ptr(verts + vId + 12) 
		Return[p[0] , p[1] , p[2] ] 
	End Method
	
	Method GetVertexColor:Float[] (vId:Int) 
		vId:*VERTEXSIZE
		Local color:Int = (Float Ptr(verts + vId + 24))[0] 
		Return[Float(((color & $ff000000) Shr 24) / 255.0), Float(((color & $00ff0000) Shr 16) / 255.0),  ..
			   Float(((color & $0000ff00) Shr 8) / 255.0), Float((color & $000000ff) / 255.0)] 
	End Method
	 
	Method GetVertexTexCoord:Float[] (vId:Int, coord:Int) 
		vId = vId * VERTEXSIZE + coord * 8
		Local p:Float Ptr = Float Ptr(verts + vId + 28) 
		Return[p[0] , p[1] ] 
	End Method
	
	Method AddTriangle:Int(v0:Int, v1:Int, v2:Int) 
	
		no_tris = no_tris + 1
		
		' resize array
		If no_tris * 3 >= tri_array_size
		
			Repeat
				tri_array_size=tri_array_size*2
			Until tri_array_size > no_tris * 3
		
			tris = tris[..tri_array_size] 
			
		EndIf
		
		Local vid:Int = (no_tris * 3) 
	
		tris[vid - 3] = v2
		tris[vid - 2] = v1
		tris[vid - 1] = v0
		
		Return no_tris
		
	End Method
	
	Method SetTriAngles:Int(start:Int, count:Int, triangles:Short Ptr, srcOffset:Int = 0) 
		If tris.length < start+count Then 
			tris = tris[..(start+count)]
			no_tris =  tris.length / 3
		EndIf 
		Local dstPtr:Byte Ptr = tris
		MemCopy(dstPtr+start*2, Byte Ptr(triangles)+srcOffset*2 , count*2 )  
	End Method 
	
	Method GetTriangles:Short Ptr() 
		Return tris
	End Method 
		
	Method OverrideVertexCount(count:Int) 
		no_verts = Count
	End Method
	
	Method OverrideTrisCount(count:Int)
		no_Tris = Count
	End Method
	
	Method Clear(clear_verts:Int = True, clear_tris:Int = True) 
	
		If clear_verts
			no_verts = 0
			MemFree verts		
			vert_array_size = 1
		EndIf
		
		If clear_tris
			no_tris = 0
			tris = tris[..0] 
			tri_array_size = 1
		EndIf
	
	End Method
	
	Method FreeVBO() 
		If VertexBufferObj Then VertexBufferObj.Release_() 
		If IndexBufferObj Then IndexBufferObj.Release_() 
	End Method
	
	Method SetMatrix(Matrix:TMatrix) 
		mat = Matrix
	End Method

	Method EnableVBO(vbo_enabled:Int) 
		If vbo_enabled Then
		    Print "VBSize"+vert_array_size
			If D3DDevice.CreateVertexBuffer(vert_array_size, D3DUSAGE_WRITEONLY, D3D_VERTEX_FORMAT, D3DPOOL_DEFAULT, VertexBufferObj, Null) <> D3D_OK Then
				Assert "Failed to create VB"
			EndIf
			Print "IBSize"+tri_array_size
			If D3DDevice.CreateIndexBuffer(tri_array_size*INDEXSIZE,D3DUSAGE_WRITEONLY, D3D_INDEX_FORMAT, D3DPOOL_DEFAULT, IndexBufferObj, Null) <> D3D_OK Then
				Assert "Failed to create IB"
			EndIf
		EndIf
	End Method

	Method Update()
		If D3DDevice.SetTransform(D3DTS_WORLD, mat.grid)  Print "Failed"
		If D3DDevice.SetFVF(D3D_VERTEX_FORMAT) Print "Failed"
		If D3DDevice.SetStreamSource(0, VertexBufferObj, 0, VERTEXSIZE) Print "Failed"
		If D3DDevice.SetIndices(IndexBufferObj) Print "Failed"
		If D3DDevice.DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, no_verts, 0, no_tris) Print "Failed"
	End Method
	
	Method CountTriangles:Int() 
		Return no_tris
	End Method
	
	Method CountVertices:Int() 
		Return no_verts
	End Method
	
	Method UpdateVBO:Int(reset_vbo:Int Var) 
		
		If Not VertexBufferObj Or Not IndexBufferObj Or reset_vbo <> 0 Then
		
			EnableVBO(True) 
						
			Local VertexBufferStart:Byte Ptr
			Local IndexBufferStart:Byte Ptr
			
			If VertexBufferObj.Lock(0, no_verts * VERTEXSIZE, VertexBufferStart,0) = D3D_OK Then
				MemCopy(VertexBufferStart, verts, no_verts * VERTEXSIZE) 
				VertexBufferObj.Unlock() 
			EndIf
			 
			If IndexBufferObj.Lock(0, no_tris * 3 * INDEXSIZE, IndexBufferStart, 0) = D3D_OK Then
				MemCopy(IndexBufferStart, Byte Ptr(tris), no_tris * 3 * INDEXSIZE) 
				IndexBufferObj.Unlock() 
			Else
			    Print "Requested"+no_tris * 3 * INDEXSIZE
			    Print "Actual size"+tri_array_size
				Throw "Bad lock"	
			EndIf
			

			
			reset_vbo = False
			
		EndIf

		Return True
		
	End Method
	
End Type


Type TDXEntity
	
	Field rx:Float, ry:Float, rz:Float
	Field px:Float, py:Float, pz:Float
	Field sx:Float, sy:Float, sz:Float
	
	Field mat:TMatrix = New TMatrix
	
	Method New() 
		sx = 1.0; sy = 1.0; sz = 1.0
	End Method
	
	Method PositionEntity(x:Float, y:Float, z:Float) 
	
		px=x
		py=y
		pz = z
		UpdateMat(True) 
			
	End Method
	
	Method Turnentity(x:Float, y:Float, z:Float) 
	
		Local tx:Float = -x
		Local ty:Float = y
		Local tz:Float = z
				
		rx=rx+tx
		ry=ry+ty
		rz=rz+tz
		UpdateMat(True) 

	End Method
	
	Method RotateEntity(x:Float, y:Float, z:Float) 

		rx = -x
		ry = y
		rz = z
		UpdateMat(True) 
			
	End Method
	
	Method ScaleEntity(x:Float, y:Float, z:Float, glob = False) 

		sx = x
		sy = y
		sz = z
		UpdateMat(True) 
		
	End Method
	
	Method UpdateMat(load_identity = False) 

		If load_identity=True
			mat.LoadIdentity()
			mat.Translate(px,py,pz)
			mat.Rotate(rx,ry,rz)
			mat.Scale(sx,sy,sz)
		Else
			mat.Translate(px,py,pz)
			mat.Rotate(rx,ry,rz)
			mat.Scale(sx, sy, sz) 
		EndIf
	
	End Method
	

End Type


Type TDXSurface
	
	Field rederable:TDXRenderable = New TDXRenderable
	Field reset_vbo:Int
	Field new_bounds:Int
	
	Method Delete()
		rederable.FreeVBO() 
	End Method
	
	
	Method ClearSurface(clear_verts = True, clear_tris = True) 
		Self.rederable.Clear(clear_verts,clear_tris)
	End Method
			
	Method AddVertex(x#,y#,z#,u#=0.0,v#=0.0,w#=0.0)
		Return Self.rederable.AddVertex(x,y,z,u,v,W)
	End Method
	
	Method AddTriangle(v0,v1,v2)
		reset_vbo:|1 | 2 | 16
		new_bounds=True
		Return Self.rederable.AddTriangle(v0,v1,v2)
	End Method
	
	Method CountVertices()
		Return Self.rederable.CountVertices()
	End Method
	
	Method CountTriangles()
		Return Self.rederable.CountTriangles()
	End Method
	
	Method VertexCoords(vid,x#,y#,z#)
		Self.rederable.SetVertexPos(vid,x,y,z)
		reset_vbo:|1
	End Method
			
	Method VertexColor(vid,r#,g#,b#,a#=1.0)
		Self.rederable.SetVertexColor(vid,r,G,b,a)
		reset_vbo:|8
	End Method
	
	Method VertexNormal(vid,nx#,ny#,nz#)
		Self.rederable.SetVertexNormal(vid,nx#,ny#,nz#)
		reset_vbo:|4
	End Method
	
	Method VertexTexCoords(vid,u#,v#,w#=0.0,coord_set=0)
		Self.rederable.SetVertexTexCoord(vid,u#,v#,coord_set )	
		reset_vbo:|2
	End Method
		
	Method VertexX#(vid)
		Return Self.rederable.GetVertexPos(vid)[0]
	End Method

	Method VertexY#(vid)
		Return Self.rederable.GetVertexPos(vid)[1]
	End Method
	
	Method VertexZ#(vid)
		Return Self.rederable.GetVertexPos(vid)[2] 
	End Method
	
	Method VertexRed#(vid)
		Return Self.rederable.GetVertexColor(vid)[0]*255
	End Method
	
	Method VertexGreen#(vid)
		Return Self.rederable.GetVertexColor(vid)[1]*255
	End Method
	
	Method VertexBlue#(vid)
		Return Self.rederable.GetVertexColor(vid)[2]*255
	End Method
	
	Method VertexAlpha#(vid)
		Return Self.rederable.GetVertexColor(vid)[3]*255
	End Method
	
	Method VertexNX#(vid)
		Return Self.rederable.GetVertexNormal(vid)[0]
	End Method
	
	Method VertexNY#(vid)
		Return Self.rederable.GetVertexNormal(vid)[1]
	End Method
	
	Method VertexNZ#(vid)
		Return Self.rederable.GetVertexNormal(vid)[2]
	End Method
	
	Method VertexU#(vid,coord_set=0)
		Return Self.rederable.GetVertexTexCoord(vid,coord_set)[0]
	End Method
	
	Method VertexV#(vid,coord_set=0)
		Return Self.rederable.GetVertexTexCoord(vid,coord_set)[1]
	End Method
	
	Method VertexW#(vid,coord_set=0)
		Return 0
	End Method
	
	Method TriangleVertex(tri_no,corner)
		Local tris:Short Ptr = Self.rederable.GetTriAngles()
		Local vid[3]
		tri_no=(tri_no+1)*3
		vid[0]=tris[tri_no-1]
		vid[1]=tris[tri_no-2]
		vid[2]=tris[tri_no-3]
		Return vid[corner]
	End Method
	
	Method UpdateNormals()
		'rederable.UpdateNormals()
	End Method
	
	Method TriangleNX#(tri_no)

		Local v0=Self.TriangleVertex(tri_no,0)
		Local v1=Self.TriangleVertex(tri_no,1)
		Local v2=Self.TriangleVertex(tri_no,2)
	
		'Local ax#=VertexX#(v1)-VertexX#(v0)
		Local ay#=Self.VertexY#(v1)-Self.VertexY#(v0)
		Local az#=Self.VertexZ#(v1)-Self.VertexZ#(v0)
		
		'Local bx#=VertexX#(v2)-VertexX#(v1)
		Local by#=Self.VertexY#(v2)-Self.VertexY#(v1)
		Local bz#=Self.VertexZ#(v2)-Self.VertexZ#(v1)
		
		Return (ay#*bz#)-(az#*by#)
		
	End Method

	Method TriangleNY#(tri_no)
	
		Local v0=Self.TriangleVertex(tri_no,0)
		Local v1=Self.TriangleVertex(tri_no,1)
		Local v2=Self.TriangleVertex(tri_no,2)

		Local ax#=Self.VertexX#(v1)-Self.VertexX#(v0)
		'Local ay#=VertexY#(v1)-VertexY#(v0)
		Local az#=Self.VertexZ#(v1)-Self.VertexZ#(v0)
		
		Local bx#=Self.VertexX#(v2)-Self.VertexX#(v1)
		'Local by#=VertexY#(v2)-VertexY#(v1)
		Local bz#=Self.VertexZ#(v2)-Self.VertexZ#(v1)
	
		Return (az#*bx#)-(ax#*bz#)
			
	End Method

	Method TriangleNZ#(tri_no)
	
		Local v0=Self.TriangleVertex(tri_no,0)
		Local v1=Self.TriangleVertex(tri_no,1)
		Local v2=Self.TriangleVertex(tri_no,2)
		
		Local ax#=Self.VertexX#(v1)-Self.VertexX#(v0)
		Local ay#=Self.VertexY#(v1)-Self.VertexY#(v0)
		'Local az#=VertexZ#(v1)-VertexZ#(v0)
		
		Local bx#=Self.VertexX#(v2)-Self.VertexX#(v1)
		Local by#=Self.VertexY#(v2)-Self.VertexY#(v1)
		'Local bz#=VertexZ#(v2)-VertexZ#(v1)
		
		Return (ax#*by#)-(ay#*bx#)
		
	End Method
	
	Method UpdateVBO()
		Self.rederable.UpdateVBO(reset_vbo)
		Return True
	End Method
	
	Method FreeVBO()
		Self.rederable.FreeVBO()
		Return True
	End Method
	
End Type

Type TDXMesh Extends TDXEntity
	
	Field surf_list:TList = CreateList() 
	
	
	Method CreateCube:TDXMesh() 
		Local surf:TDXSurface = New TDXSurface
		
		'DebugStop
		surf.AddVertex(-1.0,-1.0,-1.0)
		surf.AddVertex(-1.0, 1.0,-1.0)
		surf.AddVertex( 1.0, 1.0,-1.0)
		surf.AddVertex( 1.0,-1.0,-1.0)
		
		surf.AddVertex(-1.0,-1.0, 1.0)
		surf.AddVertex(-1.0, 1.0, 1.0)
		surf.AddVertex( 1.0, 1.0, 1.0)
		surf.AddVertex( 1.0,-1.0, 1.0)
			
		surf.AddVertex(-1.0,-1.0, 1.0)
		surf.AddVertex(-1.0, 1.0, 1.0)
		surf.AddVertex( 1.0, 1.0, 1.0)
		surf.AddVertex( 1.0,-1.0, 1.0)
		
		surf.AddVertex(-1.0,-1.0,-1.0)
		surf.AddVertex(-1.0, 1.0,-1.0)
		surf.AddVertex( 1.0, 1.0,-1.0)
		surf.AddVertex( 1.0,-1.0,-1.0)

		surf.AddVertex(-1.0,-1.0, 1.0)
		surf.AddVertex(-1.0, 1.0, 1.0)
		surf.AddVertex( 1.0, 1.0, 1.0)
		surf.AddVertex( 1.0,-1.0, 1.0)
		
		surf.AddVertex(-1.0,-1.0,-1.0)
		surf.AddVertex(-1.0, 1.0,-1.0)
		surf.AddVertex( 1.0, 1.0,-1.0)
		surf.AddVertex( 1.0,-1.0,-1.0)

		surf.VertexNormal(0,0.0,0.0,-1.0)
		surf.VertexNormal(1,0.0,0.0,-1.0)
		surf.VertexNormal(2,0.0,0.0,-1.0)
		surf.VertexNormal(3,0.0,0.0,-1.0)
	
		surf.VertexNormal(4,0.0,0.0,1.0)
		surf.VertexNormal(5,0.0,0.0,1.0)
		surf.VertexNormal(6,0.0,0.0,1.0)
		surf.VertexNormal(7,0.0,0.0,1.0)
		
		surf.VertexNormal(8,0.0,-1.0,0.0)
		surf.VertexNormal(9,0.0,1.0,0.0)
		surf.VertexNormal(10,0.0,1.0,0.0)
		surf.VertexNormal(11,0.0,-1.0,0.0)
				
		surf.VertexNormal(12,0.0,-1.0,0.0)
		surf.VertexNormal(13,0.0,1.0,0.0)
		surf.VertexNormal(14,0.0,1.0,0.0)
		surf.VertexNormal(15,0.0,-1.0,0.0)
	
		surf.VertexNormal(16,-1.0,0.0,0.0)
		surf.VertexNormal(17,-1.0,0.0,0.0)
		surf.VertexNormal(18,1.0,0.0,0.0)
		surf.VertexNormal(19,1.0,0.0,0.0)
				
		surf.VertexNormal(20,-1.0,0.0,0.0)
		surf.VertexNormal(21,-1.0,0.0,0.0)
		surf.VertexNormal(22,1.0,0.0,0.0)
		surf.VertexNormal(23,1.0,0.0,0.0)

		surf.VertexTexCoords(0,0.0,1.0)
		surf.VertexTexCoords(1,0.0,0.0)
		surf.VertexTexCoords(2,1.0,0.0)
		surf.VertexTexCoords(3,1.0,1.0)
		
		surf.VertexTexCoords(4,1.0,1.0)
		surf.VertexTexCoords(5,1.0,0.0)
		surf.VertexTexCoords(6,0.0,0.0)
		surf.VertexTexCoords(7,0.0,1.0)
		
		surf.VertexTexCoords(8,0.0,1.0)
		surf.VertexTexCoords(9,0.0,0.0)
		surf.VertexTexCoords(10,1.0,0.0)
		surf.VertexTexCoords(11,1.0,1.0)
			
		surf.VertexTexCoords(12,0.0,0.0)
		surf.VertexTexCoords(13,0.0,1.0)
		surf.VertexTexCoords(14,1.0,1.0)
		surf.VertexTexCoords(15,1.0,0.0)
	
		surf.VertexTexCoords(16,0.0,1.0)
		surf.VertexTexCoords(17,0.0,0.0)
		surf.VertexTexCoords(18,1.0,0.0)
		surf.VertexTexCoords(19,1.0,1.0)
				
		surf.VertexTexCoords(20,1.0,1.0)
		surf.VertexTexCoords(21,1.0,0.0)
		surf.VertexTexCoords(22,0.0,0.0)
		surf.VertexTexCoords(23,0.0,1.0)

		surf.VertexTexCoords(0,0.0,1.0,0.0,1)
		surf.VertexTexCoords(1,0.0,0.0,0.0,1)
		surf.VertexTexCoords(2,1.0,0.0,0.0,1)
		surf.VertexTexCoords(3,1.0,1.0,0.0,1)
		
		surf.VertexTexCoords(4,1.0,1.0,0.0,1)
		surf.VertexTexCoords(5,1.0,0.0,0.0,1)
		surf.VertexTexCoords(6,0.0,0.0,0.0,1)
		surf.VertexTexCoords(7,0.0,1.0,0.0,1)
		
		surf.VertexTexCoords(8,0.0,1.0,0.0,1)
		surf.VertexTexCoords(9,0.0,0.0,0.0,1)
		surf.VertexTexCoords(10,1.0,0.0,0.0,1)
		surf.VertexTexCoords(11,1.0,1.0,0.0,1)
			
		surf.VertexTexCoords(12,0.0,0.0,0.0,1)
		surf.VertexTexCoords(13,0.0,1.0,0.0,1)
		surf.VertexTexCoords(14,1.0,1.0,0.0,1)
		surf.VertexTexCoords(15,1.0,0.0,0.0,1)
	
		surf.VertexTexCoords(16,0.0,1.0,0.0,1)
		surf.VertexTexCoords(17,0.0,0.0,0.0,1)
		surf.VertexTexCoords(18,1.0,0.0,0.0,1)
		surf.VertexTexCoords(19,1.0,1.0,0.0,1)
				
		surf.VertexTexCoords(20,1.0,1.0,0.0,1)
		surf.VertexTexCoords(21,1.0,0.0,0.0,1)
		surf.VertexTexCoords(22,0.0,0.0,0.0,1)
		surf.VertexTexCoords(23,0.0,1.0,0.0,1)
				
		surf.AddTriangle(0,1,2) ' front
		surf.AddTriangle(0,2,3)
		surf.AddTriangle(6,5,4) ' back
		surf.AddTriangle(7,6,4)
		surf.AddTriangle(6+8,5+8,1+8) ' top
		surf.AddTriangle(2+8,6+8,1+8)
		surf.AddTriangle(0+8,4+8,7+8) ' bottom
		surf.AddTriangle(0+8,7+8,3+8)
		surf.AddTriangle(6+16,2+16,3+16) ' right
		surf.AddTriangle(7+16,6+16,3+16)
		surf.AddTriangle(0+16,1+16,5+16) ' left
		surf.AddTriangle(0 + 16, 5 + 16, 4 + 16) 
		
		surf_list.AddLast(surf) 
		
		Return Self
	End Method
	
	' Function by Coyote
	Method CreateSphere:TDXMesh(segments = 8) 

		If segments<2 Or segments>100 Then Return Null
		
		Local thissurf:TDXSurface = New TDXSurface

		Local div#=Float(360.0/(segments*2))
		Local height#=1.0
		Local upos#=1.0
		Local udiv#=Float(1.0/(segments*2))
		Local vdiv#=Float(1.0/segments)
		Local RotAngle#=90	
	
		If segments=2 ' diamond shape - no center strips
		
			For Local i=1 To (segments*2)
				Local np=thissurf.AddVertex(0.0,height,0.0,upos#-(udiv#/2.0),0)'northpole
				Local sp=thissurf.AddVertex(0.0,-height,0.0,upos#-(udiv#/2.0),1)'southpole
				Local XPos#=-Cos(RotAngle#)
				Local ZPos#=Sin(RotAngle#)
				Local v0=thissurf.AddVertex(XPos#,0,ZPos#,upos#,0.5)
				RotAngle#=RotAngle#+div#
				If RotAngle#>=360.0 Then RotAngle#=RotAngle#-360.0
				XPos#=-Cos(RotAngle#)
				ZPos#=Sin(RotAngle#)
				upos#=upos#-udiv#
				Local v1=thissurf.AddVertex(XPos#,0,ZPos#,upos#,0.5)
				thissurf.AddTriangle(np,v0,v1)
				thissurf.AddTriangle(v1,v0,sp)	
			Next
			
		Else ' have center strips now
		
			' poles first
			For Local i=1 To (segments*2)
				
				Local np=thissurf.AddVertex(0.0,height,0.0,upos#-(udiv#/2.0),0)'northpole
				Local sp=thissurf.AddVertex(0.0,-height,0.0,upos#-(udiv#/2.0),1)'southpole
				
				Local YPos#=Cos(div#)
				
				Local XPos#=-Cos(RotAngle#)*(Sin(div#))
				Local ZPos#=Sin(RotAngle#)*(Sin(div#))
				
				Local v0t=thissurf.AddVertex(XPos#,YPos#,ZPos#,upos#,vdiv#)
				Local v0b=thissurf.AddVertex(XPos#,-YPos#,ZPos#,upos#,1-vdiv#)
				
				RotAngle#=RotAngle#+div#
				
				XPos#=-Cos(RotAngle#)*(Sin(div#))
				ZPos#=Sin(RotAngle#)*(Sin(div#))
				
				upos#=upos#-udiv#
	
				Local v1t=thissurf.AddVertex(XPos#,YPos#,ZPos#,upos#,vdiv#)
				Local v1b=thissurf.AddVertex(XPos#,-YPos#,ZPos#,upos#,1-vdiv#)
				
				thissurf.AddTriangle(np,v0t,v1t)
				thissurf.AddTriangle(v1b,v0b,sp)	
				
			Next
			
			' then center strips
	
			upos#=1.0
			RotAngle#=90
			For Local i=1 To (segments*2)
			
				Local mult#=1
				Local YPos#=Cos(div#*(mult#))
				Local YPos2#=Cos(div#*(mult#+1.0))
				Local Thisvdiv#=vdiv#
				For Local j=1 To (segments-2)
	
					
					Local XPos#=-Cos(RotAngle#)*(Sin(div#*(mult#)))
					Local ZPos#=Sin(RotAngle#)*(Sin(div#*(mult#)))
	
					Local XPos2#=-Cos(RotAngle#)*(Sin(div#*(mult#+1.0)))
					Local ZPos2#=Sin(RotAngle#)*(Sin(div#*(mult#+1.0)))
								
					Local v0t=thissurf.AddVertex(XPos#,YPos#,ZPos#,upos#,Thisvdiv#)
					Local v0b=thissurf.AddVertex(XPos2#,YPos2#,ZPos2#,upos#,Thisvdiv#+vdiv#)
				
					' 2nd tex coord set
					thissurf.VertexTexCoords(v0t,upos#,Thisvdiv#,0.0,1)
					thissurf.VertexTexCoords(v0b,upos#,Thisvdiv#+vdiv#,0.0,1)
				
					Local tempRotAngle#=RotAngle#+div#
				
					XPos#=-Cos(tempRotAngle#)*(Sin(div#*(mult#)))
					ZPos#=Sin(tempRotAngle#)*(Sin(div#*(mult#)))
					
					XPos2#=-Cos(tempRotAngle#)*(Sin(div#*(mult#+1.0)))
					ZPos2#=Sin(tempRotAngle#)*(Sin(div#*(mult#+1.0)))				
				
					Local temp_upos#=upos#-udiv#
	
					Local v1t=thissurf.AddVertex(XPos#,YPos#,ZPos#,temp_upos#,Thisvdiv#)
					Local v1b=thissurf.AddVertex(XPos2#,YPos2#,ZPos2#,temp_upos#,Thisvdiv#+vdiv#)
					
					' 2nd tex coord set
					thissurf.VertexTexCoords(v1t,temp_upos#,Thisvdiv#,0.0,1)
					thissurf.VertexTexCoords(v1b,temp_upos#,Thisvdiv#+vdiv#,0.0,1)
					
					thissurf.AddTriangle(v1t,v0t,v0b)
					thissurf.AddTriangle(v1b,v1t,v0b)
					
					Thisvdiv#=Thisvdiv#+vdiv#			
					mult#=mult#+1
					YPos#=Cos(div#*(mult#))
					YPos2#=Cos(div#*(mult#+1.0))
				
				Next
				upos#=upos#-udiv#
				RotAngle#=RotAngle#+div#
			Next
	
		EndIf
	
		'thissphere.UpdateNormals() 
	
		surf_list.AddLast(thissurf) 
		Return Self
	End Method
	
	Method Update() 
		For Local surf:TDXSurface = EachIn surf_list
			If surf.reset_vbo Then surf.UpdateVBO() 
			surf.rederable.SetMatrix(mat) 
			surf.rederable.Update() 
		Next
	End Method
	           
End Type

Type Direct3d

	Field clsColor				:Int 					= $FF000000
	Field Direct3D9 			:IDirect3D9				= Null 
	Field Direct3DDevice9		:IDirect3DDevice9		= Null
	Field BackBuffer			:IDirect3DSurface9 		= Null
	Field PParams				:D3DPRESENT_PARAMETERS  = Null
	Field hwnd					:Int 					= 0

	Method _Init(hwnd:Int, w:Int, h:Int, bWindowed:Int = False) 


		Self.hwnd = hwnd
		
		Direct3D9 = Direct3DCreate9( $900 )

		If Not Direct3D9  Then 
			Assert "error creating d3d9interface!"
		EndIf
		
		PParams = New D3DPRESENT_PARAMETERS
		
		PParams.SwapEffect       = D3DSWAPEFFECT_DISCARD;
	    PParams.hDeviceWindow    = hwnd;
	    PParams.Windowed         = bWindowed;
	    PParams.BackBufferWidth  = w;
	    PParams.BackBufferHeight = h;
	    PParams.BackBufferFormat = D3DFMT_A8R8G8B8;
		
		
		If Direct3D9.CreateDevice(0, D3DDEVTYPE_HAL, hwnd , D3DCREATE_PUREDEVICE | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, PParams, Direct3DDevice9) <> D3D_OK
			
			If Direct3D9.CreateDevice(0, D3DDEVTYPE_HAL, hwnd , D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, PParams, Direct3DDevice9) <> D3D_OK
				
				If Direct3D9.CreateDevice(0, D3DDEVTYPE_HAL, hwnd , D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, PParams, Direct3DDevice9) <> D3D_OK
				    Assert "failed To create device _D3dDev9"
				End If
				Print "Sofware"
			
			Else
			Print "hardware"
			End If
		Else
			Print "Pure"	
		EndIf
		


		Direct3DDevice9.GetBackBuffer(0,0, D3DBACKBUFFER_TYPE_MONO, BackBuffer );


		Direct3DDevice9.SetRenderState(D3DRS_AMBIENT, $00FFFFFF) 
		Direct3DDevice9.SetRenderState(D3DRS_LIGHTING, False) 
		Direct3DDevice9.SetRenderState(D3DRS_CULLMODE, D3DCULL_CW) 
		Direct3DDevice9.SetRenderState(D3DRS_DITHERENABLE, True) 
		

	End Method 

	Method SetClsColor(r:Int,g:Int,b:Int)
		clsColor = Int(( 255 Shl 24)| (r Shl 16)| (g Shl 8)| b )
	End Method 

	Method BeginScene()
		Direct3DDevice9.Clear(0,Null,D3DCLEAR_TARGET,clsColor,0,0);
    	Return Direct3DDevice9.BeginScene()=0
	End Method 

	Method EndScene()
		Direct3DDevice9.EndScene();
    	Direct3DDevice9.Present(Null,Null,Null,Null);
	End Method 

	Method GetDevice:IDirect3DDevice9()
		Return 	Direct3DDevice9
	End Method 

	Method GetBackBuffer:IDirect3DSurface9()
		Return BackBuffer
	End Method 

	Method SetAmbientLight(color:Int = $00FFFFFF)
		Direct3DDevice9.SetRenderState(D3DRS_AMBIENT, color) 
	End Method 

	Method SetLightningEnable(enable:Int)
		Direct3DDevice9.SetRenderState(D3DRS_LIGHTING, enable) 
	End Method 

	Method SetCullMode(mode:Int = D3DCULL_CW )
		Direct3DDevice9.SetRenderState(D3DRS_CULLMODE, mode ) 
	End Method 
	
	Method SetDitherEnable(enable:Int = True)
		Direct3DDevice9.SetRenderState(D3DRS_DITHERENABLE, enable) 
	End Method 

End Type

Type TMatrix

	Field grid#[4,4]
	

	
	Method LoadIdentity()
	
		grid[0,0]=1.0
		grid[1,0]=0.0
		grid[2,0]=0.0
		grid[3,0]=0.0
		grid[0,1]=0.0
		grid[1,1]=1.0
		grid[2,1]=0.0
		grid[3,1]=0.0
		grid[0,2]=0.0
		grid[1,2]=0.0
		grid[2,2]=1.0
		grid[3,2]=0.0
		
		grid[0,3]=0.0
		grid[1,3]=0.0
		grid[2,3]=0.0
		grid[3,3]=1.0
	
	End Method
	
	' copy - create new copy and returns it
	
	Method Copy:TMatrix()
	
		Local mat:TMatrix=New TMatrix
	
		mat.grid[0,0]=grid[0,0]
		mat.grid[1,0]=grid[1,0]
		mat.grid[2,0]=grid[2,0]
		mat.grid[3,0]=grid[3,0]
		mat.grid[0,1]=grid[0,1]
		mat.grid[1,1]=grid[1,1]
		mat.grid[2,1]=grid[2,1]
		mat.grid[3,1]=grid[3,1]
		mat.grid[0,2]=grid[0,2]
		mat.grid[1,2]=grid[1,2]
		mat.grid[2,2]=grid[2,2]
		mat.grid[3,2]=grid[3,2]
		
		' do not remove
		mat.grid[0,3]=grid[0,3]
		mat.grid[1,3]=grid[1,3]
		mat.grid[2,3]=grid[2,3]
		mat.grid[3,3]=grid[3,3]
		
		Return mat
	
	End Method
	
	' overwrite - overwrites self with matrix passed as parameter
	
	Method Overwrite(mat:TMatrix)
	
		grid[0,0]=mat.grid[0,0]
		grid[1,0]=mat.grid[1,0]
		grid[2,0]=mat.grid[2,0]
		grid[3,0]=mat.grid[3,0]
		grid[0,1]=mat.grid[0,1]
		grid[1,1]=mat.grid[1,1]
		grid[2,1]=mat.grid[2,1]
		grid[3,1]=mat.grid[3,1]
		grid[0,2]=mat.grid[0,2]
		grid[1,2]=mat.grid[1,2]
		grid[2,2]=mat.grid[2,2]
		grid[3,2]=mat.grid[3,2]
		
		grid[0,3]=mat.grid[0,3]
		grid[1,3]=mat.grid[1,3]
		grid[2,3]=mat.grid[2,3]
		grid[3,3]=mat.grid[3,3]
		
	End Method
	
	Method Inverse:TMatrix()

		Local mat:TMatrix=New TMatrix
	
		Local tx#=0
		Local ty#=0
		Local tz#=0
	
	  	' The rotational part of the matrix is simply the transpose of the
	  	' original matrix.
	  	mat.grid[0,0] = grid[0,0]
	  	mat.grid[1,0] = grid[0,1]
	  	mat.grid[2,0] = grid[0,2]
	
		mat.grid[0,1] = grid[1,0]
		mat.grid[1,1] = grid[1,1]
		mat.grid[2,1] = grid[1,2]
	
		mat.grid[0,2] = grid[2,0]
		mat.grid[1,2] = grid[2,1]
		mat.grid[2,2] = grid[2,2]
	
		' The right column vector of the matrix should always be [ 0 0 0 1 ]
		' in most cases. . . you don't need this column at all because it'll 
		' never be used in the program, but since this code is used with GL
		' and it does consider this column, it is here.
		mat.grid[0,3] = 0 
		mat.grid[1,3] = 0
		mat.grid[2,3] = 0
		mat.grid[3,3] = 1
	
		' The translation components of the original matrix.
		tx = grid[3,0]
		ty = grid[3,1]
		tz = grid[3,2]
	
		' Result = -(Tm * Rm) To get the translation part of the inverse
		mat.grid[3,0] = -( (grid[0,0] * tx) + (grid[0,1] * ty) + (grid[0,2] * tz) )
		mat.grid[3,1] = -( (grid[1,0] * tx) + (grid[1,1] * ty) + (grid[1,2] * tz) )
		mat.grid[3,2] = -( (grid[2,0] * tx) + (grid[2,1] * ty) + (grid[2,2] * tz) )
	
		Return mat

	End Method

	Method Multiply(mat:TMatrix)
	
		Local m00# = grid#[0,0]*mat.grid#[0,0] + grid#[1,0]*mat.grid#[0,1] + grid#[2,0]*mat.grid#[0,2] + grid#[3,0]*mat.grid#[0,3]
		Local m01# = grid#[0,1]*mat.grid#[0,0] + grid#[1,1]*mat.grid#[0,1] + grid#[2,1]*mat.grid#[0,2] + grid#[3,1]*mat.grid#[0,3]
		Local m02# = grid#[0,2]*mat.grid#[0,0] + grid#[1,2]*mat.grid#[0,1] + grid#[2,2]*mat.grid#[0,2] + grid#[3,2]*mat.grid#[0,3]
		'Local m03# = grid#[0,3]*mat.grid#[0,0] + grid#[1,3]*mat.grid#[0,1] + grid#[2,3]*mat.grid#[0,2] + grid#[3,3]*mat.grid#[0,3]
		Local m10# = grid#[0,0]*mat.grid#[1,0] + grid#[1,0]*mat.grid#[1,1] + grid#[2,0]*mat.grid#[1,2] + grid#[3,0]*mat.grid#[1,3]
		Local m11# = grid#[0,1]*mat.grid#[1,0] + grid#[1,1]*mat.grid#[1,1] + grid#[2,1]*mat.grid#[1,2] + grid#[3,1]*mat.grid#[1,3]
		Local m12# = grid#[0,2]*mat.grid#[1,0] + grid#[1,2]*mat.grid#[1,1] + grid#[2,2]*mat.grid#[1,2] + grid#[3,2]*mat.grid#[1,3]
		'Local m13# = grid#[0,3]*mat.grid#[1,0] + grid#[1,3]*mat.grid#[1,1] + grid#[2,3]*mat.grid#[1,2] + grid#[3,3]*mat.grid#[1,3]
		Local m20# = grid#[0,0]*mat.grid#[2,0] + grid#[1,0]*mat.grid#[2,1] + grid#[2,0]*mat.grid#[2,2] + grid#[3,0]*mat.grid#[2,3]
		Local m21# = grid#[0,1]*mat.grid#[2,0] + grid#[1,1]*mat.grid#[2,1] + grid#[2,1]*mat.grid#[2,2] + grid#[3,1]*mat.grid#[2,3]
		Local m22# = grid#[0,2]*mat.grid#[2,0] + grid#[1,2]*mat.grid#[2,1] + grid#[2,2]*mat.grid#[2,2] + grid#[3,2]*mat.grid#[2,3]
		'Local m23# = grid#[0,3]*mat.grid#[2,0] + grid#[1,3]*mat.grid#[2,1] + grid#[2,3]*mat.grid#[2,2] + grid#[3,3]*mat.grid#[2,3]
		Local m30# = grid#[0,0]*mat.grid#[3,0] + grid#[1,0]*mat.grid#[3,1] + grid#[2,0]*mat.grid#[3,2] + grid#[3,0]*mat.grid#[3,3]
		Local m31# = grid#[0,1]*mat.grid#[3,0] + grid#[1,1]*mat.grid#[3,1] + grid#[2,1]*mat.grid#[3,2] + grid#[3,1]*mat.grid#[3,3]
		Local m32# = grid#[0,2]*mat.grid#[3,0] + grid#[1,2]*mat.grid#[3,1] + grid#[2,2]*mat.grid#[3,2] + grid#[3,2]*mat.grid#[3,3]
		'Local m33# = grid#[0,3]*mat.grid#[3,0] + grid#[1,3]*mat.grid#[3,1] + grid#[2,3]*mat.grid#[3,2] + grid#[3,3]*mat.grid#[3,3]
	
		grid[0,0]=m00
		grid[0,1]=m01
		grid[0,2]=m02
		'grid[0,3]=m03
		grid[1,0]=m10
		grid[1,1]=m11
		grid[1,2]=m12
		'grid[1,3]=m13
		grid[2,0]=m20
		grid[2,1]=m21
		grid[2,2]=m22
		'grid[2,3]=m23
		grid[3,0]=m30
		grid[3,1]=m31
		grid[3,2]=m32
		'grid[3,3]=m33
		
	End Method

	Method Translate(x#,y#,z#)
	
		grid[3,0] = grid#[0,0]*x# + grid#[1,0]*y# + grid#[2,0]*z# + grid#[3,0]
		grid[3,1] = grid#[0,1]*x# + grid#[1,1]*y# + grid#[2,1]*z# + grid#[3,1]
		grid[3,2] = grid#[0,2]*x# + grid#[1,2]*y# + grid#[2,2]*z# + grid#[3,2]

	End Method
		
	Method Scale(x#,y#,z#)
	
		grid[0,0] = grid#[0,0]*x#
		grid[0,1] = grid#[0,1]*x#
		grid[0,2] = grid#[0,2]*x#

		grid[1,0] = grid#[1,0]*y#
		grid[1,1] = grid#[1,1]*y#
		grid[1,2] = grid#[1,2]*y#

		grid[2,0] = grid#[2,0]*z#
		grid[2,1] = grid#[2,1]*z#
		grid[2,2] = grid#[2,2]*z# 
	
	End Method
	
	Method Rotate(rx#,ry#,rz#)
	
		Local cos_ang#,sin_ang#
	
		' yaw
	
		cos_ang#=Cos(ry#)
		sin_ang#=Sin(ry#)
	
		Local m00# = grid#[0,0]*cos_ang + grid#[2,0]*-sin_ang#
		Local m01# = grid#[0,1]*cos_ang + grid#[2,1]*-sin_ang#
		Local m02# = grid#[0,2]*cos_ang + grid#[2,2]*-sin_ang#

		grid[2,0] = grid#[0,0]*sin_ang# + grid#[2,0]*cos_ang
		grid[2,1] = grid#[0,1]*sin_ang# + grid#[2,1]*cos_ang
		grid[2,2] = grid#[0,2]*sin_ang# + grid#[2,2]*cos_ang

		grid[0,0]=m00#
		grid[0,1]=m01#
		grid[0,2]=m02#
		
		' pitch
		
		cos_ang#=Cos(rx#)
		sin_ang#=Sin(rx#)
	
		Local m10# = grid#[1,0]*cos_ang + grid#[2,0]*sin_ang
		Local m11# = grid#[1,1]*cos_ang + grid#[2,1]*sin_ang
		Local m12# = grid#[1,2]*cos_ang + grid#[2,2]*sin_ang

		grid[2,0] = grid#[1,0]*-sin_ang + grid#[2,0]*cos_ang
		grid[2,1] = grid#[1,1]*-sin_ang + grid#[2,1]*cos_ang
		grid[2,2] = grid#[1,2]*-sin_ang + grid#[2,2]*cos_ang

		grid[1,0]=m10
		grid[1,1]=m11
		grid[1,2]=m12
		
		' roll
		
		cos_ang#=Cos(rz#)
		sin_ang#=Sin(rz#)

		m00# = grid#[0,0]*cos_ang# + grid#[1,0]*sin_ang#
		m01# = grid#[0,1]*cos_ang# + grid#[1,1]*sin_ang#
		m02# = grid#[0,2]*cos_ang# + grid#[1,2]*sin_ang#

		grid[1,0] = grid#[0,0]*-sin_ang# + grid#[1,0]*cos_ang#
		grid[1,1] = grid#[0,1]*-sin_ang# + grid#[1,1]*cos_ang#
		grid[1,2] = grid#[0,2]*-sin_ang# + grid#[1,2]*cos_ang#

		grid[0,0]=m00#
		grid[0,1]=m01#
		grid[0,2]=m02#
	
	End Method
	
	Method RotatePitch(ang#)
	
		Local cos_ang#=Cos(ang#)
		Local sin_ang#=Sin(ang#)
	
		Local m10# = grid#[1,0]*cos_ang + grid#[2,0]*sin_ang
		Local m11# = grid#[1,1]*cos_ang + grid#[2,1]*sin_ang
		Local m12# = grid#[1,2]*cos_ang + grid#[2,2]*sin_ang

		grid[2,0] = grid#[1,0]*-sin_ang + grid#[2,0]*cos_ang
		grid[2,1] = grid#[1,1]*-sin_ang + grid#[2,1]*cos_ang
		grid[2,2] = grid#[1,2]*-sin_ang + grid#[2,2]*cos_ang

		grid[1,0]=m10
		grid[1,1]=m11
		grid[1,2]=m12

	End Method
	
	Method RotateYaw(ang#)
	
		Local cos_ang#=Cos(ang#)
		Local sin_ang#=Sin(ang#)
	
		Local m00# = grid#[0,0]*cos_ang + grid#[2,0]*-sin_ang#
		Local m01# = grid#[0,1]*cos_ang + grid#[2,1]*-sin_ang#
		Local m02# = grid#[0,2]*cos_ang + grid#[2,2]*-sin_ang#

		grid[2,0] = grid#[0,0]*sin_ang# + grid#[2,0]*cos_ang
		grid[2,1] = grid#[0,1]*sin_ang# + grid#[2,1]*cos_ang
		grid[2,2] = grid#[0,2]*sin_ang# + grid#[2,2]*cos_ang

		grid[0,0]=m00#
		grid[0,1]=m01#
		grid[0,2]=m02#

	End Method
	
	Method RotateRoll(ang#)
	
		Local cos_ang#=Cos(ang#)
		Local sin_ang#=Sin(ang#)

		Local m00# = grid#[0,0]*cos_ang# + grid#[1,0]*sin_ang#
		Local m01# = grid#[0,1]*cos_ang# + grid#[1,1]*sin_ang#
		Local m02# = grid#[0,2]*cos_ang# + grid#[1,2]*sin_ang#

		grid[1,0] = grid#[0,0]*-sin_ang# + grid#[1,0]*cos_ang#
		grid[1,1] = grid#[0,1]*-sin_ang# + grid#[1,1]*cos_ang#
		grid[1,2] = grid#[0,2]*-sin_ang# + grid#[1,2]*cos_ang#

		grid[0,0]=m00#
		grid[0,1]=m01#
		grid[0,2]=m02#

	End Method
		
End Type



Type TRect
	Field _Left	:Int
	Field _Top	: Int
	Field _Right : Int
	Field _Bottom: Int
	
	Function Create:TRect(ALeft:Int,ATop:Int,ARight:Int,ABottom:Int)
		Local this:TRect=New TRect
		this._Left=ALeft
		this._Top=ATop
		this._Right=ARight		
		this._Bottom=ABottom
		Return this
	End Function
	Method Width:Int()
		Return _Right-_Left
	End Method
	Method Height:Int()
		Return _Bottom-_Top
	End Method
End Type

Function WndProc:Int( hwnd:Int,message:Int,wp:Int,lp:Int ) "win32"
	bbSystemEmitOSEvent hwnd,message,wp,lp,Null
	Select message
	Case WM_CLOSE
		End 
	Case WM_SYSKEYDOWN
		If wp<>KEY_F4 Return 0
	' ensure the valid Flag is current due to mode/focus changes	
	Case WM_SETFOCUS		
		'_dx9driver.ValidateGraphics
	' ensure the valid Flag is current due to mode/focus changes		
	Case WM_KILLFOCUS
		'_dx9driver.ValidateGraphics
	End Select
	Return DefWindowProcA( hwnd,message,wp,lp )
End Function

Function CreateGameWindow:Int(width:Int, height:Int )
	Local wc:WNDCLASS=New WNDCLASS
	wc.hInstance = GetModuleHandleA(0) 
	wc.lpfnWndProc = WndProc
	wc.hCursor=LoadCursorA( Null,Byte Ptr IDC_ARROW )
	wc.lpszClassName=_DX9GRAPHICSEXWINDOWCLASS
	RegisterClassA( wc )

	Local hinst:Int = GetModuleHandleA(0) 
	Local title:Byte Ptr=AppTitle.ToCString()
	
	Local hwnd:Int
	width:Int = 800
	height:Int = 600
	Local style:Int=WS_VISIBLE|WS_CAPTION|WS_SYSMENU |WS_SIZEBOX 
	Local rect :TRect = TRect.Create(32,32,width+32,height+32)
	AdjustWindowRect Int Ptr Byte Ptr rect,style,0
	width=rect.Width()
	height=rect.Height()

	hwnd=CreateWindowExA( 0,_DX9GRAPHICSEXWINDOWCLASS,title,style,rect._Left,rect._Top,width,height,0,0,hinst,Null )
	Return hwnd
End Function


This has been interesting excercise. There is still one Debug message I am seeing that I dont like but it doesnt seem to have much impact nor can I explain it.

[5424] Direct3D9: (WARN) :Stream 0 stride and vertex size, computed from the current vertex declaration or FVF, are different, which might not work with pre-DX8 drivers 


I think this is due to fact your FVF has 2 texture coordinates and it knows your not using textures. It does not seem to affect behavior.

I would suggest you manage the IndexBuffer the same way you manage the VertexBuffer with direct memory manipulations instead of the sliceing.

Now the approach you are using for static geomitry is ok. Unless you have lots of tiny meshes then you would want to merge the vertex and index buffers.

This will be aweful for for anykind of dynamic or animated mesh. For that you need a global dynamic buffer similar to what I used in the Max2d.

I also would probably not use Dx9Max2d driver as the base as it manages the begin scene end scene states. Use the

Base driver.

SuperStrict
Framework pub.win32
Import "DX9Graphics.bmx"
Import brl.GLGraphics
SetGraphicsDriver(D3D9GraphicsDriver(),GRAPHICS_BACKBUFFER|GRAPHICS_DEPTHBUFFER)



Function Clear(dwColor:Int)
	D3D9GraphicsDriver().Direct3DDevice9().Clear(0,Null,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,dwColor,1.0,0)	
End Function

Function BeginScene:Int()
	Return   D3D9GraphicsDriver().BeginScene()=0
End Function

Function EndScene()
   D3D9GraphicsDriver().EndScene()
End Function

Graphics 640,480,0

While Not KeyHit(Key_Escape)
  Clear($FFFF0000)
  If BeginScene()

	EndScene()
  End If
  Flip 0
Wend



You really dont want to mix Max2d rendering be it Dx9 or OpenGL as Max2d. Its not very effeicent rendering and state managment which will affect 3d performance in complex scenes greatly.

Thanks for posting If you guys are interested I would like to show you some work that I had done similar to what your attempting but havent explored it fully out but might be something you would intereted in.

I will be making some changes to the Dx9Max2d library based upon some things that I have seen after relooking at it while trying to figure out your problem.

Doug

Thanks again!
Fundamentally a stupid mistake of me ;)
Works fine now :)

Ok, at first I will use the base driver, but in case of mixing Max2d with miniB3d, it must be definitely supported, because of compatibility to original miniB3d...the compatibility generally is difficulty, because there are some aspects, which we would design differently and also in case of the new features.

It would be nice to see your work and I am definitely interested...

@Budman, have you ever had problems while debugging a d3d9 application?
Since I am using textures, the application ends with 'Process complete' when I click on the debug tree or perform a debug step, but besides the program runs solid...

btw: I thaught about mixing 2d and 3d. And came to the conclusion that you're right. A single surface 2d system on top of miniB3d, like Draw3d, would be a better solution.

And what do you intend to do with Windows User of Max2D? You know that this is DX7 so you can and will not be able to intermix it, and I don't assume you plan to base your "core featureset" on something inofficial which does not work across all the machines. And I would not assume that DX9 will ever happen officially (and even if, DX7 is still present and will be used on many machines) ...

It would be simpler and more stable to replicated the Max2D function set within your code as a submodule but in a compatible way to your own rendering part. At least unless you intend to write a DX7 driver as well.

@Dreamora, I do not really understand what you mean, because Windows User which uses minib3d are currently bounded on OpenGl in case of using Max2d for a HUD or something...

Generally it was just an idea which was in my head for some time...and a DX7 implementation is nearest not planed from my side, because I think complete d3d9 will still take some time. And I am just a little bit unhappy with the RenderInterface design, so it will also be enhanced... Also I must see how much time-consuming study will be in the next semester ;)

@Rone
For debugging I havent noticed the behavior your talking about however I rarely use the built in debugger, I use debug logging to debug Dx Code in BMAX since the BMAX debugger is crap(Thats being polite). Its 2008 and I have to but debugstop and compile my code. Give me a break.

Do you have the DirectX Debug Drivers from the SDK activated. If not I cant recommend it enough. Get the SDK use the applet to enable debug drivers and use this
[url]http://technet.microsoft.com/en-us/sysinternals/bb896647.aspx[/url] to capture the drivers debug spew. It will find pretty much everything you might be doing wrong.

Doug

Thanks, DebugView is really an easing. :)
However the debugger chrashes after calling
Local hr:Int= D3DDevice.CreateTexture(WIDTH, HEIGHT,level,usage,Internal,D3DPOOL_MANAGED,Texture[i],Null)
but besides ttextures works well...

The texture loading method looks as follows:
(It is in almost the same manner as in your driver)
Method CreateTex:int(pixmap:TPixmap, w:Int, h:Int, frames:Int=1, flags:Int = 8, Format:Int = eTextureFormats.RGBA )
	
		Texture = Texture[..frames]
			
		Local pixmap2:TPixmap
		Local usage:Int=0
		Local level:Int=1

		If flags&8 Then 
			level=0
			usage = D3DUSAGE_AUTOGENMIPMAP
		endif 

		Local Internal:Int
		Select Format
			Case eTextureFormats.RGBA
				Internal = D3DFMT_A8R8G8B8
			Case eTextureFormats.DEPTH
				Internal = D3DFMT_D24X8 
		End Select
		
		Local x:int=0
		For Local i=0 until frames
		
			pixmap2=pixmap.Window(x*W,0,W,h)
			x=x+1
		
			pixmap2=AdjustPixmap(pixmap2)
			Local WIDTH=pixmap2.WIDTH
			Local HEIGHT=pixmap2.HEIGHT

			
			Local hr:Int= D3DDevice.CreateTexture(WIDTH, HEIGHT,level,usage,Internal,D3DPOOL_MANAGED,Texture[i],Null)
			If hr<>D3D_OK Then Assert "Failed to Create Texture:"+HR
			
			Local lockrect:D3DLOCKED_RECT=New D3DLOCKED_RECT
			If  Texture[i].LockRect(0,lockrect,Null,0)<> D3D_OK
				Texture[i].Release_
				Texture[i]=Null
				Throw "Failed to Lock Texture"
			End If	

			' Move the pixmap to offscreen surface
			Local sp:TPixmap=TPixmap.CreateStatic(lockrect.pBits,WIDTH,HEIGHT,lockrect.Pitch,PF_BGRA8888)
	        	sp.Paste(pixmap2,0,0)
			' unlock the surface
			Texture[i].UnlockRect(0)	
 
		Next
		
		return 0
		
	End Method 


@Rone I dont see anything in particular. But am wondering about the array of textures if the Debugger is choking on that. I know when reflection was added it caused problems with arrays of Objects that extened IUknown. So maybe if debugger is inspect array of textures its have fits.

I assume you are single stepping through this? And it makes the call and then crashes the IDE?

Doug

Thats really weird. I can duplicate it. Not sure what the deal is. Guess I need to do some debugging :)

Doug

Its a similar bug its the array of textures IDirectTexture9.

I changed your code to just use a single texture and its fine.

Unless BRL fixes it your code is not the problem. To work around you will need to create your own simple container wrapping the textures if you want to manage the array.

Might be good idea as you can put all the code to manage locking etc. inside that class

Doug

unbelievable...thanks a lot.

Works now with a texture container.
And I got Lightning and materials working, too.

At next I think I will paste into our render interface a test some miniB3d samples :)
If I dont oversight something miniB3d should run completly with d3d9 then! :) :)

Cant wait to see it!

Doug

Hi,
if you are interesseted, here is the actual source.
Any improvements are welcome :)

The material is not yet working as in miniB3d. Possibly I set some wrong Renderstates. It seems that sometimes only the shadowed areas are colored. Also the specular component does not work yet. So, still needs some improvements.. ;)

Here is the link for .exe and the textures:
Click here!

Strict

framework brl.Graphics
import pub.directX
Import BRL.JPGLoader
Import BRL.PNGLoader
Import BRL.Retro
Import brl.StandardIO


Apptitle = "d3d9 test"

'#################################################################################### 
' D3dX initialization

'if not D3DXCheckVersion(D3D_SDK_VERSION, D3DX_SDK_VERSION) then 
'        assert "weong d3dx version"
'endif 


Global d3dx9Lib=LoadLibraryA( "d3dx9d_33" )
Global D3DXMatrixPerspectiveFovLH( pOutMatrix:Float ptr ,  fovy:Float,  Aspect:Float,  zn:Float,zf:Float ) "win32"=GetProcAddress( d3dx9Lib,"D3DXMatrixPerspectiveFovLH" )										
Global D3DXMatrixLookAtLH:Float ptr(pOutMatrix:Float ptr, pEyeVector:Float ptr,  pAtVector:Float ptr,pUpVector:Float ptr ) "win32" = GetProcAddress( d3dx9Lib,"D3DXMatrixLookAtLH" )
Global D3DXVec3TransformCoord:Float ptr(pOutVector:Float ptr,  pV:Float ptr, pM:Float ptr ) "win32" = GetProcAddress( d3dx9Lib,"D3DXVec3TransformCoord" )
Global D3DXMatrixMultiply:Float ptr( pOut:Float ptr,  pM1:Float ptr,  pM2:Float ptr) "win32"=GetProcAddress( d3dx9Lib,"D3DXMatrixMultiply" )
Global D3DXMatrixRotationYawPitchRoll:Float ptr(pOut:Float ptr,  Yaw:Float,  Pitch:Float,  Roll:Float)"win32"=GetProcAddress( d3dx9Lib,"D3DXMatrixRotationYawPitchRoll" )
Global D3DXMatrixScaling:Float ptr( pOut:Float ptr,  sx:Float, sy:Float, sz:Float)"win32"=GetProcAddress( d3dx9Lib,"D3DXMatrixScaling" )

Global _DX9GRAPHICSEXWINDOWCLASS:Byte Ptr="DX9WinClass".ToCString()

Function D3DXMatrixIdentity(mat:Float Ptr)
  mat[0] = 1.0
  mat[1] = 0
  mat[2] = 0
  mat[3] = 0
  mat[4] = 0
  mat[5] = 1.0
  mat[6] = 0
  mat[7] = 0
  mat[8] = 0
  mat[9] = 0
  mat[10] = 1.0
  mat[11] = 0
  mat[12] = 0
  mat[13] = 0
  mat[14] = 0
  mat[15] = 1.0
EndFunction

Const D3DTTFF_DISABLE         = 0
Const D3DTTFF_COUNT1          = 1
Const D3DTTFF_COUNT2          = 2
Const D3DTTFF_COUNT3          = 3
Const D3DTTFF_COUNT4          = 4
Const D3DTTFF_PROJECTED       = 256
Const D3DTTFF_FORCE_DWORD     = $7fffffff

'#################################################################################### 
' Direct3d initialization

local hwnd = CreateGameWindow(800,600)
Local d3d9Graphics:Direct3d = New Direct3d
d3d9Graphics._Init(hwnd,800,600,true)
d3d9Graphics.SetClsColor(255,255,255)

TDXRenderable.D3DDevice 		= d3d9Graphics.GetDevice()
TDXCamera.D3DDevice 			= d3d9Graphics.GetDevice()
TDXTexture.D3DDevice			= d3d9Graphics.GetDevice()
TDXTextureContainer.D3DDevice 	= d3d9Graphics.GetDevice()
TDXLight.D3DDevice				= d3d9Graphics.GetDevice()
TDXMaterial.D3DDevice			= d3d9Graphics.GetDevice()


local lpD3DDevice:IDirect3DDevice9 = d3d9Graphics.GetDevice()


'####################################################################################
' World initialization

Local cam:TDXCamera = New TDXCamera
cam.PositionEntity(0, 0, -10)
cam.SetViewport(10,10,780,580) 
cam.SetClippingPlanes(0.0,1.0)

local light:TDXLight = new TDXLight
light.PositionEntity(0, 10, -10)
light.TurnEntity(45,0,0) 

Local cube:TDXMesh = New TDXMesh.CreateCube() 
cube.PositionEntity(- 1.5, 0, 0) 

Local sphere:TDXMesh = New TDXMesh.CreateSphere(32) 
sphere.PositionEntity(1.5, 0, 0) 


local boden:TDXMesh = New TDXMesh.CreateCube() 
boden.scaleentity(5,0.2,5)
boden.PositionEntity(0,-3,0)


local texture:TDXTexture = TDXTexture.Loadtexture("wcrate.jpg",0)
local texture2:TDXTexture = TDXTexture.Loadtexture("wcrate2.jpg",3)
local texture3:TDXTexture = TDXTexture.Loadtexture("StoneColor.png",0)
local texture4:TDXTexture = TDXTexture.Loadtexture("logo.png",3)


local brush:TDXBrush = new TDXBrush
brush.BrushTexture(texture,0)
brush.BrushTexture(texture2,1)
brush.BrushTexture(texture4,2)
brush.ScaleTexture(0, 2,2 )
brush.ScaleTexture(1, 3,3 )
brush.ScaleTexture(2, 1,1 )


local brush2:TDXBrush = new TDXBrush
brush2.BrushTexture(texture3,0)
brush2.BrushTexture(texture2,1)
brush2.ScaleTexture(0, 1,1 )
brush2.ScaleTexture(1, 1,1 )


local brush5:TDXBrush = new TDXBrush
brush5.BrushTexture(texture3,0)
brush5.ScaleTexture(0, 4,4 )
brush5.Brushcolor(255,50,50)


cube.PaintMesh(brush)
sphere.PaintMesh(brush2)
boden.PaintMesh(brush5)

'####################################################################################

Repeat

	If d3d9Graphics.BeginScene()

		cube.TurnEntity(0.60, 0.6, 0.6) 
		sphere.TurnEntity(0.6, 0.6, 0.6) 
		
		TDXEntity.RenderWorld()

		d3d9Graphics.EndScene()

	EndIf

until KeyHit(Key_Escape)
End


'####################################################################################

Type TDXCamera extends TDXEntity

	Global D3DDevice:IDirect3DDevice9
	
	Global vUp		:Float[] = [0.0,1.0,0.0]
	Global vLook	:Float[] = [0.0,0.0,1.0]

	Field vLookAt		:Float[3]
	Field vWorldUp		:Float[3]
	Field vWorldLook	:Float[3]
	Field mView			:Float[16]				
	Field mProj			:Float[16]				
	Field viewport		:D3DVIEWPORT9 = New D3DVIEWPORT9					  
	Field Zoom			:Float	= 1.0			  
	Field ClearColor	:Int = $FF000000
	Field ClsMode		:Int = D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER 


	method Clear()
		D3DDevice.Clear(0,Null, ClsMode, ClearColor,1.0,0)
	end method 

	method UpdateViewPort()
		D3DDevice.SetViewport( Byte ptr(viewport) ) 
	end method 

	method Update()
		UpdateViewPort()
		Clear()
		UpdateView() 
	end method 

	Method UpdateView() 
	
		' Only rotation values are needed
		Local mCam:TMatrix = mat.Copy()
		mCam.grid[3,0] = 0.0
		mCam.grid[3,1] = 0.0
		mCam.grid[3,2] = 0.0
		
		' Transform vectors based on camera's rotation matrix
	   	D3DXVec3TransformCoord( vWorldUp, vUp, mCam.grid )
	    D3DXVec3TransformCoord( vWorldLook, vLook, mCam.grid )
		 
	    'Update the lookAt position based on the eye position 
		Local vPos:Float[] = [mat.grid[3,0],mat.grid[3,1],mat.grid[3,2]]
		vLookAt[0] = vWorldLook[0] + vPos[0]
		vLookAt[1] = vWorldLook[1] + vPos[1]
		vLookAt[2] = vWorldLook[2] + vPos[2]

		 ' Update the view matrix
    	D3DXMatrixLookAtLH(mView, vPos, vLookAt, vUp) 
    	D3DDevice.SetTransform(D3DTS_VIEW, mView) 

		' Init Projection Matrix
	    D3DXMatrixPerspectiveFovLH(mProj, Pi / 4, 800.0 / 600.0, 1.0, 300.0) 
	    D3DDevice.SetTransform(D3DTS_PROJECTION, mProj) 
		
	End Method

	Method SetViewport(x:Int, y:Int, width:Int, height:Int) 
		viewport.X = x
		viewport.Y = y
		viewport.WIDTH = WIDTH
		viewport.HEIGHT = HEIGHT											
	End Method 
	
	Method SetClippingPlanes(n:Float,f:Float)
		viewport.MinZ = n
		viewport.MaxZ = f									
	End Method 
	
	Method SetZoom(zoom:Float)
		Zoom = zoom				 									
	End Method 
	
	Method SetClsMode(p:Int, d:Int)
		ClsMode = 0
		If p Then
			ClsMode = ClsMode | D3DCLEAR_TARGET
		End If
		If d Then
			ClsMode = ClsMode | D3DCLEAR_ZBUFFER
		End If				 									
	End Method 
	
	Method SetClsColor(r:Float, g:Float , b:Float, a:Float = 1.0)
		ClearColor = $ff000000|(Int(r) Shl 16)|(Int(G) Shl 8)|Int(b)			
	End Method 

	 Method GetViewport:Int[]() 
		Return [viewport.X, viewport.Y, viewport.WIDTH, viewport.HEIGHT]
	End Method
	
End Type

'####################################################################################


Type TDXRenderable

	Const VERTEXSIZE:Int = 44
	Const INDEXSIZE:Int = 2
	
	Global D3D_VERTEX_FORMAT:Int = (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX2 ) 
	Global D3D_INDEX_FORMAT:Int = D3DFMT_INDEX16
	Global D3DDevice:IDirect3DDevice9
	
	Field VertexBufferObj:IDirect3DVertexBuffer9
	Field verts:Byte Ptr
	Field no_verts:Int
	Field vert_array_size:Int
	
	Field IndexBufferObj:IDirect3DIndexBuffer9
	Field tris:Short[] 
	Field no_tris:Int
	Field tri_array_size:Int

	field vert_first_changed	:int
	field vert_last_changed		:int
	field tri_first_changed		:int
	field tri_last_changed		:int
	
	Field mat:TMatrix
	
	Method New() 
		verts = MemAlloc(1) 
		vert_array_size = 1
		tri_array_size = 1
		vert_first_changed = $0FFFFFFF
		vert_last_changed = -1
		tri_first_changed = $0FFFFFFF
		tri_last_changed = -1
	End Method

	method ChangeVertex(ID:int)
		if ID > vert_last_changed then 
			vert_last_changed = ID
		endif 
		if ID < vert_first_changed then 
			vert_first_changed = ID
		endif 	
	end method

	method ChangeTri(ID:int)
		if ID > tri_last_changed then 
			tri_last_changed = ID
		endif
		if ID < tri_first_changed then 
			tri_first_changed = ID
		endif 	
	end method

	Method Delete() 
		MemFree verts
		tris = tris[..0] 
		If VertexBufferObj Then VertexBufferObj.Release_() 
		If IndexBufferObj Then IndexBufferObj.Release_() 
	End Method
	
	Method AddVertex:Int(x:Float, y:Float, z:Float, u:Float = 0.0, v:Float = 0.0, w:Float = 0.0) 
	
		no_verts:+1
		
		If no_verts * VERTEXSIZE > vert_array_size Then
			
			Local oldSize:Int = vert_array_size
			
			Repeat
				vert_array_size = vert_array_size * 2
			Until vert_array_size > no_verts * VERTEXSIZE
			
			Local tmp_verts:Byte Ptr = MemAlloc(vert_array_size) 
			MemCopy(tmp_verts, verts, oldSize) 
			MemFree(verts) 
			verts = tmp_verts
		
		EndIf
		
		Local vId:Int = (no_verts - 1) 
		SetVertexPos(vId, x, y, z) 
		SetVertexColor(vId, 1.0, 1.0, 1.0) 
		SetVertexTexCoord(vId, u, v, 0) 
		
		Return vId
		
	End Method
	
	
	Method SetVertexPos(vId:Int, x:Float, y:Float, z:Float) 
		ChangeVertex(vId)
		vId:*VERTEXSIZE
		Local p:Float Ptr = Float Ptr(verts + vId ) 
		p[0] = x; p[1] = y; p[2] = z
	End Method
	
	Method SetVertexNormal(vId:Int, nx:Float, ny:Float, nz:Float) 
		ChangeVertex(vId)
		vId:*VERTEXSIZE
		Local p:Float Ptr = Float Ptr(verts + vId + 12) 
		p[0] = nx; p[1] = ny; p[2] = nz
	End Method
	
	Method SetVertexColor(vId:Int, r:Float, g:Float, b:Float, a:Float = 1.0) 
		ChangeVertex(vId)
		vId:*VERTEXSIZE
		Local p:Int Ptr = Int Ptr(verts + vId + 24) 
		p[0] = Int((Int(a * 255.0) Shl 24) | (Int(r * 255.0) Shl 16) | (Int(g * 255.0) Shl 8) | Int(b * 255.0)) 
	End Method
	 
	Method SetVertexTexCoord(vId:Int, u:Float, v:Float, coord:Int) 
		ChangeVertex(vId)
		vId = vId * VERTEXSIZE + coord * 8
		Local p:Float Ptr = Float Ptr(verts + vId + 28) 
		p[0] = u; p[1] = v
	End Method
	
	Method GetVertexPos:Float[] (vId:Int) 
		vId:*VERTEXSIZE
		Local p:Float Ptr = Float Ptr(verts + vId) 
		Return[p[0] , p[1] , p[2] ] 
	End Method
	
	Method GetVertexNormal:Float[] (vId:Int) 
		vId:*VERTEXSIZE
		Local p:Float Ptr = Float Ptr(verts + vId + 12) 
		Return[p[0] , p[1] , p[2] ] 
	End Method
	
	Method GetVertexColor:Float[] (vId:Int) 
		vId:*VERTEXSIZE
		Local color:Int = (Float Ptr(verts + vId + 24))[0] 
		Return[Float(((color & $ff000000) Shr 24) / 255.0), Float(((color & $00ff0000) Shr 16) / 255.0),  ..
			   Float(((color & $0000ff00) Shr 8) / 255.0), Float((color & $000000ff) / 255.0)] 
	End Method
	 
	Method GetVertexTexCoord:Float[] (vId:Int, coord:Int) 
		vId = vId * VERTEXSIZE + coord * 8
		Local p:Float Ptr = Float Ptr(verts + vId + 28) 
		Return[p[0] , p[1] ] 
	End Method
	
	Method AddTriangle:Int(v0:Int, v1:Int, v2:Int) 
		
		ChangeTri(no_tris)

		no_tris = no_tris + 1
		
		' resize array
		If no_tris * 3 >= tri_array_size
		
			Repeat
				tri_array_size=tri_array_size*2
			Until tri_array_size > no_tris * 3
		
			tris = tris[..tri_array_size] 
			
		EndIf
		
		Local vid:Int = (no_tris * 3) 
	
		tris[vid - 3] = v2
		tris[vid - 2] = v1
		tris[vid - 1] = v0
		
		Return no_tris
		
	End Method
	
	Method SetTriAngles:Int(start:Int, count:Int, triangles:Short Ptr, srcOffset:Int = 0) 
		ChangeTri(start)
		ChangeTri(start+count)
		If tris.length < start+count Then 
			tris = tris[..(start+count)]
			no_tris =  tris.length / 3
		EndIf 
		Local dstPtr:Byte Ptr = tris
		MemCopy(dstPtr+start*2, Byte Ptr(triangles)+srcOffset*2 , count*2 )  
	End Method 
	
	Method GetTriangles:Short Ptr() 
		Return tris
	End Method 
		
	Method OverrideVertexCount(count:Int) 
		no_verts = Count
	End Method
	
	Method OverrideTrisCount(count:Int)
		no_Tris = Count
	End Method
	
	Method Clear(clear_verts:Int = True, clear_tris:Int = True) 
	
		If clear_verts
			no_verts = 0
			MemFree verts		
			vert_array_size = 1
		EndIf
		
		If clear_tris
			no_tris = 0
			tris = tris[..0] 
			tri_array_size = 1
		EndIf
	
	End Method
	
	Method FreeVBO() 
		If VertexBufferObj Then VertexBufferObj.Release_() 
		If IndexBufferObj Then IndexBufferObj.Release_() 
	End Method
	
	Method SetMatrix(Matrix:TMatrix) 
		mat = Matrix
	End Method

	Method EnableVBO(vbo_enabled:Int) 
		If vbo_enabled Then
			If D3DDevice.CreateVertexBuffer(vert_array_size, D3DUSAGE_WRITEONLY, D3D_VERTEX_FORMAT, D3DPOOL_DEFAULT, VertexBufferObj, Null) <> D3D_OK Then
				Assert "Failed to create VB"
			EndIf
			If D3DDevice.CreateIndexBuffer(tri_array_size*INDEXSIZE,D3DUSAGE_WRITEONLY, D3D_INDEX_FORMAT, D3DPOOL_DEFAULT, IndexBufferObj, Null) <> D3D_OK Then
				Assert "Failed to create IB"
			EndIf
		EndIf
	End Method

	Method Update(vbo_enabled:Int) 
		
		D3DDevice.SetTransform(D3DTS_WORLD, mat.grid) 
		D3DDevice.SetFVF(D3D_VERTEX_FORMAT) 

		if vbo_enabled then 
			D3DDevice.SetStreamSource(0, VertexBufferObj, 0, VERTEXSIZE) 
			D3DDevice.SetIndices(IndexBufferObj) 
			D3DDevice.DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, no_verts, 0, no_tris) 
		else
			D3dDevice.DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, no_verts, no_tris, Byte Ptr(tris), D3D_INDEX_FORMAT, verts, VERTEXSIZE) 
		endif 

	End Method
	
	Method CountTriangles:Int() 
		Return no_tris
	End Method
	
	Method CountVertices:Int() 
		Return no_verts
	End Method
	
	Method UpdateVBO:Int(reset_vbo:Int Var) 
	
		If Not VertexBufferObj Or Not IndexBufferObj Or reset_vbo <> 0 Then
		
			EnableVBO(True) 
						
			Local VertexBufferStart:Byte Ptr
			Local IndexBufferStart:Byte Ptr
			
			rem
			If VertexBufferObj.Lock(0, no_verts * VERTEXSIZE, VertexBufferStart,0) = D3D_OK Then
				MemCopy(VertexBufferStart, verts, no_verts * VERTEXSIZE) 
				VertexBufferObj.Unlock() 
			EndIf
			 
			If IndexBufferObj.Lock(0, no_tris * 3 * INDEXSIZE, IndexBufferStart, 0) = D3D_OK Then
				MemCopy(IndexBufferStart, Byte Ptr(tris), no_tris * 3 * INDEXSIZE) 
				IndexBufferObj.Unlock() 	
			EndIf
			endrem
			
			local verts_offset:int = vert_first_changed * VERTEXSIZE
			local verts_size:int = (vert_last_changed - vert_first_changed + 1) * VERTEXSIZE

			If VertexBufferObj.Lock(verts_offset, verts_size, VertexBufferStart,0) = D3D_OK Then
				MemCopy(VertexBufferStart, verts+verts_offset,verts_size) 
				VertexBufferObj.Unlock() 
				vert_first_changed = $0FFFFFFF
				vert_last_changed = -1
			EndIf
			 
			local tris_offset:int = tri_first_changed* 3 * INDEXSIZE
			local tris_size:int = (tri_last_changed - tri_first_changed + 1) * 3 * INDEXSIZE

			If IndexBufferObj.Lock(tris_offset, tris_size, IndexBufferStart, 0) = D3D_OK Then
				MemCopy(IndexBufferStart, Byte Ptr(tris)+tris_offset, tris_size ) 
				IndexBufferObj.Unlock() 
				tri_first_changed = $0FFFFFFF
				tri_last_changed = -1	
			EndIf
			
			reset_vbo = False
			
		EndIf

		Return True
		
	End Method

	method UpdateNormals()
		
		Local norm_map:TMap=New TMap

		For Local t=3 Until no_tris 
			
			Local tri_no=(t+1)*3
			
			Local v0=tris[tri_no-3]
			Local v1=tris[tri_no-2]
			Local v2=tris[tri_no-1]

			local vPtr0:float ptr = Float Ptr(verts + v0*VERTEXSIZE) 
			local vPtr1:float ptr = Float Ptr(verts + v1*VERTEXSIZE)
			local vPtr2:float ptr = Float Ptr(verts + v2*VERTEXSIZE)

			Local ax#=vPtr1[0] - vPtr0[0]
			Local ay#=vPtr1[1] - vPtr0[1]
			Local az#=(-vPtr1[2]) - (-vPtr0[2])

			Local bx#=vPtr2[0]-vPtr1[0]
			Local by#=vPtr2[1]-vPtr1[1]
			Local bz#=(-vPtr2[2])- (-vPtr1[2])
	
			Local nx#=(ay#*bz#)-(az#*by#) 
			Local ny#=(az#*bx#)-(ax#*bz#) 
			Local nz#=-((ax#*by#)-(ay#*bx#) )
				
			Local vid[3]
	
			For Local c=0 Until 3

				vid[0]=tris[tri_no-1]
				vid[1]=tris[tri_no-2]
				vid[2]=tris[tri_no-3]

				Local v=vid[c]
			
				local vPtr0:float ptr = Float Ptr(verts + v * VERTEXSIZE) 
				Local vx#=vPtr0[0]  
				Local vy#=vPtr0[1] 
				Local vz#=-vPtr0[2] 
				
				Local vert:TVector=New TVector
				vert.x=vx
				vert.y=vy
				vert.z=vz

				Local norm:TVector=TVector( norm_map.ValueForKey( vert ) )
				
				If norm
				
					norm.x:+nx
					norm.y:+ny
					norm.z:+nz
					
				Else
				
					Local vec:TVector=New TVector
					vec.x=nx
					vec.y=ny
					vec.z=nz
					
					norm_map.Insert vert,vec
					
				EndIf
				
			Next
			
		Next
		
		For Local norm:TVector=EachIn norm_map.Values()
		
			Local d#=1/Sqr(norm.x*norm.x+norm.y*norm.y+norm.z*norm.z)
			norm.x:*d
			norm.y:*d
			norm.z:*d

		Next
	
		For Local v=0 Until no_verts

			local vPtr0:float ptr = Float Ptr(verts + v * VERTEXSIZE) 
			Local vx#=vPtr0[0]  
			Local vy#=vPtr0[1] 
			Local vz#=-vPtr0[2] 
			
			Local vert:TVector=New TVector
			vert.x=vx
			vert.y=vy
			vert.z=vz
			
			Local norm:TVector=TVector( norm_map.ValueForKey( vert ) )
			If Not norm then Continue	
			
			local vnPtr0:float ptr = Float Ptr(verts + v * VERTEXSIZE + 12) 
			vnPtr0[0] = norm.x
			vnPtr0[1] = norm.y
			vnPtr0[2] = norm.z
					
		Next

	end method 

	Method Fit(x#,y#,z#,width#,height#,depth#,wr#,hr#,dr#,minx#,maxx#,miny#,maxy#,minz#,maxz#)
	
		For Local v=0 To no_verts-1
	

			' update vertex positions
			local vPtr0:float ptr = Float Ptr(verts + v * VERTEXSIZE) 
			Local vx#=vPtr0[0]  
			Local vy#=vPtr0[1] 
			Local vz#=vPtr0[2] 
			
			Local ux#=(vx#-minx#)/(maxx#-minx#)
			Local uy#=(vy#-miny#)/(maxy#-miny#)
			Local uz#=(vz#-minz#)/(maxz#-minz#)
							
			vx#=x#+(ux#*width#)
			vy#=y#+(uy#*height#)
			vz#=z#+(uz#*depth#)
			
			vPtr0[0]  = vx
			vPtr0[1]  = vy
			vPtr0[2]  = vz
			
			' update normals
			
			local vnPtr0:float ptr = Float Ptr(verts + v * VERTEXSIZE + 12) 
			Local nx#=vnPtr0[0]
			Local ny#=vnPtr0[1]
			Local nz#=vnPtr0[2]
			
			nx#=nx#*wr#
			ny#=ny#*hr#
			nz#=nz#*dr#
			
			vnPtr0[0]=nx#
			vnPtr0[1]=ny#
			vnPtr0[2]=nz#

		Next
		
	End Method

	Method Flip()
		
		For Local t=1 To no_tris
		
			Local i0=t*3-3
			Local i1=t*3-2
			Local i2=t*3-1
		
			Local v0=tris[i0]
			Local v1=tris[i1]
			Local v2=tris[i2]
	
			tris[i0]=v2
			tris[i2]=v0
	
		Next
		
		' flip vertex normals
		For Local v=0 To no_verts-1
			local vnPtr0:float ptr = Float Ptr(verts + v * VERTEXSIZE + 12) 
			vnPtr0[0] :* -1 
			vnPtr0[1] :* -1 
			vnPtr0[2] :* -1 
		Next
		
	End Method

	Method Scale(sx:Float,sy:Float,sz:Float)
		For Local v=0 To no_verts-1
			local vPtr0:float ptr = Float Ptr(verts + v * VERTEXSIZE) 
			vPtr0[0]:*sx#
			vPtr0[1]:*sy#
			vPtr0[2]:*sz#
		Next											
	End Method 

	Method Rotate(mat:tMatrix)	
			
		For Local v=0 To no_verts-1
	
			local vPtr0:float ptr = Float Ptr(verts + v * VERTEXSIZE) 
			Local vx#=vPtr0[0]  
			Local vy#=vPtr0[1] 
			Local vz#=vPtr0[2] 

			vPtr0[0] = mat.grid#[0,0]*vx# + mat.grid#[1,0]*vy# + mat.grid#[2,0]*vz# + mat.grid#[3,0]
			vPtr0[1] = mat.grid#[0,1]*vx# + mat.grid#[1,1]*vy# + mat.grid#[2,1]*vz# + mat.grid#[3,1]
			vPtr0[2] = mat.grid#[0,2]*vx# + mat.grid#[1,2]*vy# + mat.grid#[2,2]*vz# + mat.grid#[3,2]

			local vnPtr0:float ptr = Float Ptr(verts + v * VERTEXSIZE + 12) 
			Local nx# = vnPtr0[0] 
			Local ny# = vnPtr0[1]
			Local nz# = vnPtr0[2] 

			vnPtr0[0]  = mat.grid#[0,0]*nx# + mat.grid#[1,0]*ny# + mat.grid#[2,0]*nz# + mat.grid#[3,0]
			vnPtr0[1]  = mat.grid#[0,1]*nx# + mat.grid#[1,1]*ny# + mat.grid#[2,1]*nz# + mat.grid#[3,1]
			vnPtr0[2]  = mat.grid#[0,2]*nx# + mat.grid#[1,2]*ny# + mat.grid#[2,2]*nz# + mat.grid#[3,2]

		Next
																				
	End Method 
	
End Type


Type TDXEntity
	
	global EntityList:TList = new TList

	Field rx:Float, ry:Float, rz:Float
	Field px:Float, py:Float, pz:Float
	Field sx:Float, sy:Float, sz:Float
	
	Field mat:TMatrix = New TMatrix
	
	method Update() Abstract 

	function RenderWorld()
		for local cam:TDXCamera = eachin Entitylist
			cam.Update()
			for local e:TDXLight = eachin EntityList
				e.Update()
			next
			for local e:TDXMesh = eachin EntityList
				e.Update()
			next
		next 
	end function 

	Method New() 
		sx = 1.0; sy = 1.0; sz = 1.0
		EntityList.AddLast Self
	End Method
	
	Method PositionEntity(x:Float, y:Float, z:Float) 
	
		px=x
		py=y
		pz = z
		UpdateMat(True) 
			
	End Method
	
	Method Turnentity(x:Float, y:Float, z:Float) 
	
		Local tx:Float = -x
		Local ty:Float = y
		Local tz:Float = z
				
		rx=rx+tx
		ry=ry+ty
		rz=rz+tz
		UpdateMat(True) 

	End Method
	
	Method RotateEntity(x:Float, y:Float, z:Float) 

		rx = -x
		ry = y
		rz = z
		UpdateMat(True) 
			
	End Method
	
	Method ScaleEntity(x:Float, y:Float, z:Float, glob = False) 

		sx = x
		sy = y
		sz = z
		UpdateMat(True) 
		
	End Method
	
	Method UpdateMat(load_identity = False) 

		If load_identity=True
			mat.LoadIdentity()
			mat.Translate(px,py,pz)
			mat.Rotate(rx,ry,rz)
			mat.Scale(sx,sy,sz)
		Else
			mat.Translate(px,py,pz)
			mat.Rotate(rx,ry,rz)
			mat.Scale(sx, sy, sz) 
		EndIf
	
	End Method
	

End Type

Type eTextureFilter Abstract 
	Const None 						:Int = 0
	Const Filter					:Int = 1
	Const MipMapedFilter			:Int = 2
	Const Anisotrope				:Int = 3
End Type

Type eTextureBlends Abstract 
	Const Add						:Int = 0
	Const Average					:Int = 1
	Const Multiply					:Int = 2
	Const VertexAlpha				:Int = 3
	Const PrimaryAlpha				:Int = 4
	Const SecondaryAlpha			:Int = 5
	Const PrimaryInverseAlpha		:Int = 6
	Const SecondaryInverseAlpha		:Int = 7
End Type

type eTextureFormats
	const RGBA = 1
	const DEPTH = 2
end type


rem
Woraround for BMax Bug with arrays of IDerect3DTexture9, because the debugger 
crahses when inspecting arrays of Objects that extened IUknown
endrem
type TDXTextureContainer

	global D3DDevice:IDirect3DDevice9

	field tex	:IDirect3DTexture9
	
	Method CreateTex:TDXTextureContainer(pixmap:TPixmap, w:Int, h:Int, usage:int,level:int, Format:Int )
	
		Local hr:Int= D3DDevice.CreateTexture(w, h,level,usage,Format,D3DPOOL_MANAGED,tex,Null)
		If hr<>D3D_OK Then Assert "Failed to Create Texture:"+HR
		
		Local lockrect:D3DLOCKED_RECT=New D3DLOCKED_RECT
		If  tex.LockRect(0,lockrect,Null,0)<> D3D_OK
			tex.Release_
			tex=Null
			Throw "Failed to Lock Texture"
		End If	

		' Move the pixmap to offscreen surface
		Local sp:TPixmap=TPixmap.CreateStatic(lockrect.pBits,w,h,lockrect.Pitch,PF_BGRA8888)
        sp.Paste(pixmap,0,0)
		' unlock the surface
		tex.UnlockRect(0)	
 		
		return Self
		
	End Method 


end type

type TDXTexture
	
	Global D3DDevice		:IDirect3DDevice9
	
	Field transMat			:TMatrix = new TMatrix 
	Field AnisotropeCount	:Int

	Field Texture			:TDXTextureContainer[]			
	Field CubeTexture		:IDirect3DCubeTexture9

	field sx#,sy
	field blend

	method Scaletexture(sx#,sy#)
		Self.sx = sx
		Self.sy = sy
	endmethod 


	function Loadtexture:TDXTexture (url:string, blend:int = 0)
		local pixmap:TPixmap = loadpixMap(url)
		local texture:TDXTexture = new TDXTexture
		texture.CreateTex(pixmap, pixmap.width,pixmap.width)
		texture.blend = blend
		return texture
	end function 


	Method CreateTex:int(pixmap:TPixmap, w:Int, h:Int, frames:Int=1, flags:Int = 8, Format:Int = eTextureFormats.RGBA )
	

		Texture = Texture[..frames]
		
		Local pixmap2:TPixmap
		Local usage:Int=0
		Local level:Int=1

		If flags&8 Then 
			level=0
			usage = D3DUSAGE_AUTOGENMIPMAP
		endif 

		Local Internal:Int
		Select Format
			Case eTextureFormats.RGBA
				Internal = D3DFMT_A8R8G8B8
			Case eTextureFormats.DEPTH
				Internal = D3DFMT_D24X8 
		End Select
		
		Local x:int=0
		For Local i=0 until frames
		
			pixmap2=pixmap.Window(x*W,0,W,h)
			x=x+1
		
			pixmap2=AdjustPixmap(pixmap2)
			Local WIDTH=pixmap2.WIDTH
			Local HEIGHT=pixmap2.HEIGHT

			Texture[i] = new TDXTextureContainer.CreateTex(pixmap2, width, height, usage ,level, Internal)

		Next
		
		return 0
		
	End Method 


	Method Activate(layer:Int,tex_coords:Int, frame:Int, mask:Int = 0)
	
		' Activate texture coordinates
		D3DDevice.SetTextureStageState(layer, D3DTSS_TEXCOORDINDEX,tex_coords )
		
		' Activate texture
		D3DDevice.SetTexture( layer, Texture[frame].tex )
		
		' Alpha
		If mask<>0
			D3DDevice.SetTextureStageState( layer, D3DTSS_ALPHAARG1, D3DTA_TEXTURE )  
			D3DDevice.SetTextureStageState( layer, D3DTSS_ALPHAARG2, D3DTA_CURRENT )
			D3DDevice.SetTextureStageState( layer, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1)   		
		Else
			D3DDevice.SetTextureStageState( layer, D3DTSS_ALPHAOP, D3DTOP_DISABLE)   
		EndIf	
		
	End Method

	Method ActivateBlend(blend:Int, layer:Int)	 	
		Select blend
			Case 0 
				'D3DDevice.SetTextureStageState(layer, D3DTSS_COLORARG1, D3DTA_CURRENT)
				'D3DDevice.SetTextureStageState(layer, D3DTSS_COLORARG2, D3DTA_TEXTURE)
				D3DDevice.SetTextureStageState(layer, D3DTSS_COLOROP, D3DTOP_MODULATE)   
			Case 1 
				'D3DDevice.SetTextureStageState(layer, D3DTSS_COLORARG1, D3DTA_CURRENT)
				'D3DDevice.SetTextureStageState(layer, D3DTSS_COLORARG2, D3DTA_TEXTURE)
				D3DDevice.SetTextureStageState(layer, D3DTSS_COLOROP, D3DTOP_MODULATE)  
			Case 2
				'D3DDevice.SetTextureStageState(layer, D3DTSS_COLORARG1, D3DTA_CURRENT)
				'D3DDevice.SetTextureStageState(layer, D3DTSS_COLORARG2, D3DTA_TEXTURE) 
				D3DDevice.SetTextureStageState(layer, D3DTSS_COLOROP, D3DTOP_MODULATE)    
			Case 3 
				'D3DDevice.SetTextureStageState(layer, D3DTSS_COLORARG1, D3DTA_CURRENT)
				'D3DDevice.SetTextureStageState(layer, D3DTSS_COLORARG2, D3DTA_TEXTURE)
				D3DDevice.SetTextureStageState(layer, D3DTSS_COLOROP, D3DTOP_ADD)  
			Case 4
				'D3DDevice.SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_CURRENT)
				'D3DDevice.SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_TFACTOR)
				D3DDevice.SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_DOTPRODUCT3)
			Case 5 
				'D3DDevice.SetTextureStageState(layer, D3DTSS_COLORARG1, D3DTA_CURRENT)
				'D3DDevice.SetTextureStageState(layer, D3DTSS_COLORARG2, D3DTA_TEXTURE) 
				D3DDevice.SetTextureStageState(layer, D3DTSS_COLOROP, D3DTOP_MODULATE2X)
			Case 6
				'D3DDevice.SetTextureStageState(layer, D3DTSS_COLORARG1, D3DTA_CURRENT)
				'D3DDevice.SetTextureStageState(layer, D3DTSS_COLORARG2, D3DTA_TEXTURE) 
				D3DDevice.SetTextureStageState(layer, D3DTSS_COLOROP, D3DTOP_SUBTRACT)
			case 7
				'D3DDevice.SetTextureStageState(layer, D3DTSS_COLORARG1, D3DTA_CURRENT)
				'D3DDevice.SetTextureStageState(layer, D3DTSS_COLORARG2, D3DTA_TEXTURE)
				D3DDevice.SetTextureStageState(layer, D3DTSS_COLOROP, D3DTOP_ADDSIGNED) 
			default
				'D3DDevice.SetTextureStageState(layer, D3DTSS_COLORARG1, D3DTA_CURRENT)
				'D3DDevice.SetTextureStageState(layer, D3DTSS_COLORARG2, D3DTA_TEXTURE) 
				D3DDevice.SetTextureStageState(layer, D3DTSS_COLOROP, D3DTOP_MODULATE) 
		End Select 						
	End Method 

	Method ActivateFilter(layer:Int, filter:Int)
		Select filter
			Case eTextureFilter.None
				D3DDevice.SetSamplerState(layer, D3DSAMP_MINFILTER, D3DTEXF_NONE )  
				D3DDevice.SetSamplerState(layer, D3DSAMP_MAGFILTER, D3DTEXF_NONE) 
			Case eTextureFilter.Filter
				D3DDevice.SetSamplerState(layer, D3DSAMP_MINFILTER, D3DTEXF_LINEAR) 
				D3DDevice.SetSamplerState(layer, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR) 
			Case eTextureFilter.MipMapedFilter 
			  	D3DDevice.SetSamplerState(layer, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR) 
			Case eTextureFilter.Anisotrope
			 	D3DDevice.SetSamplerState(layer, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC )  
				D3DDevice.SetSamplerState(layer, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC ) 
				D3DDevice.SetSamplerState(layer, D3DSAMP_MAXANISOTROPY,  AnisotropeCount )
		End Select 
	End Method

	Method ActivateTextureAdjustment(layer:Int, tex_u_pos:Float,tex_v_pos:Float,tex_u_scale:Float, tex_v_scale:Float,tex_ang:Float,updateAdjust:Int  )	
		
		Local  mat:TMatrix = New TMatrix
		
		D3DXMatrixIdentity(transMat.grid)

		D3DXMatrixIdentity(mat.grid)
		D3DXMatrixRotationYawPitchRoll(  mat.grid, 0.0, 0.0, tex_ang)
		D3DXMatrixMultiply(transMat.grid, transMat.grid, mat.grid)	
		
		D3DXMatrixIdentity(mat.grid)
		D3DXMatrixScaling(mat.grid ,tex_u_scale, tex_v_scale, 0.0)
		D3DXMatrixMultiply(transMat.grid, transMat.grid, mat.grid)

		D3DXMatrixIdentity(mat.grid)
		mat.grid[1,3] = tex_u_pos
		mat.grid[2,3] = tex_v_pos

		D3DXMatrixMultiply(transMat.grid, transMat.grid, mat.grid)
		

		D3DDevice.SetTransform(16 + layer, transMat.grid )
		D3DDevice.SetTextureStageState( layer ,D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 )

	End Method 

	method DisableTex(layer:int)
		D3DDevice.SetTextureStageState(layer,D3DTSS_COLOROP , D3DTOP_DISABLE ) 
		D3DDevice.SetTextureStageState( layer, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE )
		D3DDevice.SetTextureStageState( layer, D3DTSS_COLOROP,   D3DTOP_DISABLE )
        D3DDevice.SetTextureStageState( layer, D3DTSS_ALPHAOP,   D3DTOP_DISABLE )
	end method 


end type


Type eCullMode Abstract 
	Const None						:Int = 1
	Const Front						:Int = 2
	Const Back						:Int = 3
	Const FrontAndBack				:Int = 4
End Type

Type eMaterialFX  Abstract
	Const FullBight  				:Int = 1
	Const VertexColor  				:Int = 2
	Const FlatShaded	  			:Int = 4
	Const FogDisable  				:Int = 8
	Const CullingBack 				:Int = 16
	Const CullingFront:Int = 32
	Const CullingNone:Int = 64
End Type 
	
Type eFillModes Abstract 
	Const FillSolid					:Int = 1
	Const FillWire					:Int = 2
	Const FillPoint					:Int = 3
End Type

Type eBlendModes Abstract 
	Const Solid						:Int = 1
	Const Alpha						:Int = 2
	Const Add						:Int = 3
	Const Sub						:Int = 4
	Const Multiply					:Int = 5
	Const AdditiveAlpha				:Int = 6
End Type

Type eShadeModes Abstract 
	Const Smooth					:Int = 1
	Const Flat						:Int = 2
End Type



type TDXmaterial
	
	Global D3DDevice	:IDirect3DDevice9


	method SetFillMode(mode:int)
		Select mode
			case eFillModes.FillSolid
				D3DDevice.SetRenderState( D3DRS_FILLMODE , 3)'D3DFILL_SOLID)  
			case eFillModes.FillWire
				D3DDevice.SetRenderState( D3DRS_FILLMODE , 2)'D3DFILL_WIREFRAME )
			case eFillModes.FillPoint
				D3DDevice.SetRenderState( D3DRS_FILLMODE , 1)'D3DFILL_POINT)
		end select
	end method 


	Method SetMaterialFx(fx:Int, ambient:int )
		
		' Vertexcolor
		If fx & eMaterialFX.VertexColor Then 
			D3DDevice.SetRenderState( D3DRS_COLORVERTEX , True )  
		Else
			D3DDevice.SetRenderState( D3DRS_COLORVERTEX , False ) 
			D3DDevice.SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL)
		EndIf 
	
		' fullbright
		If  fx & eMaterialFX.FullBight Then 
			Local Color:Int = $ffffffff
			D3DDevice.SetRenderState(D3DRS_AMBIENT, Color )
		Else
			D3DDevice.SetRenderState(D3DRS_AMBIENT, ambient )
		EndIf 
	
		' Fog disable
		If fx & eMaterialFX.FogDisable Then 
			D3DDevice.SetRenderState(D3DRS_FOGENABLE, False)
		EndIf  
		
	End Method

	Method SetMaterialShading(shading:Int) 
		
		Select shading
			Case eShadeModes.Flat
				D3DDevice.SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT ) 
			Case eShadeModes.Smooth
				D3DDevice.SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD ) 
		End Select 		
							
	End Method 
	
	Method SetMaterialColor(culling:Int,color:D3DMATERIAL9)
	
		Select culling
			case eCullMode.Back
				D3DDevice.SetRenderState( D3DRS_CULLMODE, D3DCULL_CW ) 
			case eCullMode.None
				D3DDevice.SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE) 
			case eCullMode.Front
			 	D3DDevice.SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW ) 
		end select 
			
		D3DDevice.SetMaterial( Byte Ptr(color) )
		
	End Method 
	
	Method SetMaterialBlending(blending:Int, Alpha:Int)
	
		' If material contains alpha info, enable blending
		If  Alpha Then '< 1.0 or blending = eBlendModes.Alpha or blending = eBlendModes.AdditiveAlpha Then 
			D3DDevice.SetRenderState(D3DRS_ALPHABLENDENABLE, True ) 
			D3DDevice.SetRenderState(D3DRS_DEPTHBIAS,False )
		Else
			D3DDevice.SetRenderState(D3DRS_ALPHABLENDENABLE, False )
			D3DDevice.SetRenderState(D3DRS_DEPTHBIAS,True )
		EndIf 
		
		' richtigen blendmodes herausfinden
		Select blending 
			Case eBlendModes.Solid
				D3DDevice.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
				D3DDevice.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
			Case eBlendModes.Alpha
				D3DDevice.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA)
				D3DDevice.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA) 
			Case eBlendModes.Add
				D3DDevice.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
				D3DDevice.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
'				D3DDevice.SetRenderState(D3DRS_BLENDOP,D3DBLENDOP_ADD);
			Case eBlendModes.Sub
				D3DDevice.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
				D3DDevice.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO); 
'				D3DDevice.SetRenderState(D3DRS_BLENDOP,D3DBLENDOP_SUBTRACT);
			Case eBlendModes.Multiply
				D3DDevice.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
				D3DDevice.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_SRCCOLOR);
'				D3DDevice.SetRenderState(D3DRS_BLENDOP,D3DBLENDOP_ADD);
			Case eBlendModes.AdditiveAlpha
				D3DDevice.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA)
				D3DDevice.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA)
'				D3DDevice.SetRenderState(D3DRS_BLENDOP,D3DBLENDOP_ADD);

		End Select 	
	
	End Method


end type


Type eLightTypes Abstract 
	Const LightDirectional			:Int = 1
	Const LightPoint				:Int = 2
	Const LightSpot					:Int = 3
End Type 

Type eLightAttenuations Abstract 
	Const Constant					:Int = 1
	Const Liniear					:Int = 2
	Const Quadratic					:Int = 3
EndType

type TDXLight extends TDXEntity
	
	Global D3DDevice		:IDirect3DDevice9 
	Global dir				:float[] = [0.0, -1.0, 0.0]
	Global light_no			:Int = 0;
	Global no_lights		:Int = 0;
	Global max_lights		:Int = 8;
	
	Field enable			:Int 	
	Field light				:D3DLIGHT9
	
	Field _attentuation		:Int
	Field _type				:Int
	field _range			:int
	field _angle			:int


	method new()

		light = new D3DLIGHT9
		
		_attentuation = eLightAttenuations.Liniear
		_range = 100.0
		_angle = 100.0

		SetLightType(eLightTypes.LightPoint)
			
		light.Diffuse_a = 1.0
		light.Diffuse_r = 1.0
		light.Diffuse_g = 1.0
		light.Diffuse_b = 1.0
		
		enable = True	
		
		no_lights=no_lights+1
		D3DDevice.SetLight(no_lights-1, light )
		D3DDevice.LightEnable(no_lights-1,True )
		'D3DDevice.SetRenderState( D3DRS_LIGHTING, true )

	end method 

	method Update()

		light_no=light_no+1
		If light_no>no_lights Then light_no=1
		
		If enable = False Then 
			D3DDevice.LightEnable(no_lights-1,False )
			Return
		Else

			local light_mat:tMatrix = mat.copy()

			' position
			if _type = eLightTypes.LightSpot or _type = eLightTypes.LightPoint then 
				light.Position_x = light_mat.grid[3,0]
				light.Position_y = light_mat.grid[3,1]
				light.Position_z = light_mat.grid[3,2]
			endif 

			light_mat.grid[3,0] = 0.0
			light_mat.grid[3,1] = 0.0
			light_mat.grid[3,2] = 0.0
			
			'direction
			if _type = eLightTypes.LightDirectional or _type = eLightTypes.LightSpot then 
				local res_dir:float[3]
				D3DXVec3TransformCoord(res_dir, dir,light_mat.grid)
				light.Direction_x = res_dir[0]
				light.Direction_y = res_dir[1]
				light.Direction_z = res_dir[2]
			endif 
		
			D3DDevice.SetLight(no_lights-1, light )
			D3DDevice.LightEnable(no_lights-1,True )

		EndIf  

	end method 

	method SetLightType(lighttype:int)
		_type = lighttype
		memclear( byte ptr(light) + 52, 52 )
		Select lighttype
			Case eLightTypes.LightDirectional
				light.Type_ = D3DLIGHT_DIRECTIONAL
			Case eLightTypes.LightPoint
				light.Type_ = D3DLIGHT_POINT
				SetAttenuationType(_attentuation)	
				SetRange(_range) 
			Case eLightTypes.LightSpot
				light.Type_ = D3DLIGHT_SPOT 
				SetCutoff(_angle)
				SetAttenuationType(_attentuation)	
				SetRange(_range) 
		endselect
	end method 

	Method SetAmbient(r:Float, g:Float, b:Float, a:Float = 1.0)
		light.ambient_r = r/255.0
		light.ambient_g = G/255.0
		light.ambient_b = b/255.0
		light.ambient_a = a						
	End Method 
	
	Method SetSpecular(r:Float, g:Float, b:Float, a:Float = 1.0)
		light.specular_r = r/255.0
		light.specular_g = G/255.0
		light.specular_b = b/255.0
		light.specular_a = a								
	End Method 
	
	Method SetDiffuse(r:Float, g:Float, b:Float, a:Float = 1.0)		
		light.diffuse_r = r/255.0
		light.diffuse_g = G/255.0
		light.diffuse_b = b/255.0
		light.diffuse_a = a					
	End Method 
	
	Method SetAttenuationType(attentuation:Int)	
		_attentuation = attentuation
		Select attentuation
			Case eLightAttenuations.Constant
				light.Attenuation0 = 0.05
				light.Attenuation1 = 0.0
				light.Attenuation2 = 0.0
			Case eLightAttenuations.Liniear
				light.Attenuation0 = 0.0
				light.Attenuation1 = 0.05
				light.Attenuation2 = 0.0
			Case eLightAttenuations.Quadratic
				light.Attenuation0 = 0.0
				light.Attenuation1 = 0.0
				light.Attenuation2 = 0.05
		EndSelect 		
	End Method 
	
	Method SetRange(range:Float) 
		_range = range
		light.Range = _range								
	End Method 
	
	Method SetCutoff(a:Float)
		if a > 180.0 then a = 180.0
		_angle =  a
		light.Theta = a / 2.5
		light.Phi = a
		light.Falloff = 1.0						
	End Method 
	
end type

type TTextureSlot
	

	field tex:TDXTexture
	field sx#,sy#,u#,v#,angle#
	field tex_coords
	field frame
	field anim
	field filter
	field blend

	method CreateSlot:TTextureSlot(texture:TDXTexture)
		tex = texture
		sx = texture.sx
		sy = texture.sy
		u = 1.0
		v = 1.0
		angle = 0
		frame = 0
		anim = 0
		blend = texture.blend
		filter = eTextureFilter.Filter
		return self
	end method 

	method TurnOn(layer:int)
		tex.Activate(layer,tex_coords, frame)
		tex.ActivateTextureAdjustment(layer, u,v,sx, sy,angle,true )	
		tex.ActivateFilter(layer, filter)
		tex.ActivateBlend(blend, layer)	
	end method 

	method TurnOff(layer:int)
		tex.DisableTex(layer)
	end method 
	
end type

type TDXBrush
	
	field material:TDXmaterial
	field color:D3DMATERIAL9
	field blend:int
	field fx:int
	field texture:TTextureSlot[]
	field tex_count:int

	method new()
		material = new TDXMaterial
		color = new D3DMATERIAL9
		color.Ambient_r = 1.0; color.Ambient_g = 1.0; color.Ambient_b = 1.0; color.Ambient_a = 1.0 
		color.Diffuse_r = 1.0; color.Diffuse_g = 1.0; color.Diffuse_b = 1.0; color.Diffuse_a = 1.0 
		color.Specular_r = 10.0; color.Specular_g = 10.0; color.Specular_b = 10.0; color.Specular_a = 10.0 
		color.Power = 100.0
	end method 

	method CreateBrush(r#,g#,b#,a# = 1.0)
		BrushColor(r#,g#,b#,a# )
		Brushshininess(100)
		BrushBlend(2)
		BrushFX(0)
	end method 

	method ScaleTexture(layer, sx#, sy )
		?Debug
		if layer < 0 and layer >= texture.length then 
			Assert ".ScaleTexture: Layer does not Exist"
		endif 
		?
		texture[layer].sx=sx
		texture[layer].sy=sy
	end method 

	method BrushTexture(tex:TDXTexture, layer:int)
		if layer < 8 then  
			if layer >= tex_count then 
				texture = texture[..layer+1]
				tex_count:+1
			endif 
			texture[layer] = new  TTextureSlot.CreateSlot(tex )
		endif 
	end method 

	method BrushColor(r#,g#,b#,a# = 1.0 )
		color.Ambient_r = r/255.0; color.Ambient_g = g/255.0; color.Ambient_b = b/255.0; color.Ambient_a =a/255.0
		color.Diffuse_r = r/255.0; color.Diffuse_g = g/255.0; color.Diffuse_b = b/255.0; color.Diffuse_a = a/255.0
	end method 

	method Brushshininess(shine#)
		color.Specular_r = shine; color.Specular_g = shine; color.Specular_b = shine; color.Specular_a = shine 
	end method 

	method BrushBlend(blend)
		Self.blend = blend
	end method 

	method BrushFX(fx)
		Self.fx = fx
	end method 

	method TurnOn()
		material.SetMaterialShading(eShadeModes.Smooth) 
		material.SetMaterialFx(fx,$ff505050 )
		material.SetMaterialColor(eCullMode.Back,color)
		material.SetMaterialBlending(blend, true)
		for local i:int = 0 until tex_count
			texture[i].TurnOn(i)
		next 
	end method 

	method TurnOff()
		for local i:int = 0 until tex_count
			texture[i].TurnOff(i)
		next 
	end method 
	
end type


Type TDXSurface
	
	Field rederable:TDXRenderable = New TDXRenderable
	Field reset_vbo:Int
	Field new_bounds:Int
	field brush:TDXBrush
	
	Method Delete()
		rederable.FreeVBO() 
	End Method
	
	
	Method ClearSurface(clear_verts = True, clear_tris = True) 
		Self.rederable.Clear(clear_verts,clear_tris)
	End Method
			
	Method AddVertex(x#,y#,z#,u#=0.0,v#=0.0,w#=0.0)
		Return Self.rederable.AddVertex(x,y,z,u,v,W)
	End Method
	
	Method AddTriangle(v0,v1,v2)
		reset_vbo:|1 | 2 | 16
		new_bounds=True
		Return Self.rederable.AddTriangle(v0,v1,v2)
	End Method
	
	Method CountVertices()
		Return Self.rederable.CountVertices()
	End Method
	
	Method CountTriangles()
		Return Self.rederable.CountTriangles()
	End Method
	
	Method VertexCoords(vid,x#,y#,z#)
		Self.rederable.SetVertexPos(vid,x,y,z)
		reset_vbo:|1
	End Method
			
	Method VertexColor(vid,r#,g#,b#,a#=1.0)
		Self.rederable.SetVertexColor(vid,r,G,b,a)
		reset_vbo:|8
	End Method
	
	Method VertexNormal(vid,nx#,ny#,nz#)
		Self.rederable.SetVertexNormal(vid,nx#,ny#,nz#)
		reset_vbo:|4
	End Method
	
	Method VertexTexCoords(vid,u#,v#,w#=0.0,coord_set=0)
		Self.rederable.SetVertexTexCoord(vid,u#,v#,coord_set )	
		reset_vbo:|2
	End Method
		
	Method VertexX#(vid)
		Return Self.rederable.GetVertexPos(vid)[0]
	End Method

	Method VertexY#(vid)
		Return Self.rederable.GetVertexPos(vid)[1]
	End Method
	
	Method VertexZ#(vid)
		Return Self.rederable.GetVertexPos(vid)[2] 
	End Method
	
	Method VertexRed#(vid)
		Return Self.rederable.GetVertexColor(vid)[0]*255
	End Method
	
	Method VertexGreen#(vid)
		Return Self.rederable.GetVertexColor(vid)[1]*255
	End Method
	
	Method VertexBlue#(vid)
		Return Self.rederable.GetVertexColor(vid)[2]*255
	End Method
	
	Method VertexAlpha#(vid)
		Return Self.rederable.GetVertexColor(vid)[3]*255
	End Method
	
	Method VertexNX#(vid)
		Return Self.rederable.GetVertexNormal(vid)[0]
	End Method
	
	Method VertexNY#(vid)
		Return Self.rederable.GetVertexNormal(vid)[1]
	End Method
	
	Method VertexNZ#(vid)
		Return Self.rederable.GetVertexNormal(vid)[2]
	End Method
	
	Method VertexU#(vid,coord_set=0)
		Return Self.rederable.GetVertexTexCoord(vid,coord_set)[0]
	End Method
	
	Method VertexV#(vid,coord_set=0)
		Return Self.rederable.GetVertexTexCoord(vid,coord_set)[1]
	End Method
	
	Method VertexW#(vid,coord_set=0)
		Return 0
	End Method
	
	Method TriangleVertex(tri_no,corner)
		Local tris:Short Ptr = Self.rederable.GetTriAngles()
		Local vid[3]
		tri_no=(tri_no+1)*3
		vid[0]=tris[tri_no-1]
		vid[1]=tris[tri_no-2]
		vid[2]=tris[tri_no-3]
		Return vid[corner]
	End Method
	
	Method UpdateNormals()
		rederable.UpdateNormals()
	End Method
	
	Method TriangleNX#(tri_no)

		Local v0=Self.TriangleVertex(tri_no,0)
		Local v1=Self.TriangleVertex(tri_no,1)
		Local v2=Self.TriangleVertex(tri_no,2)
	
		'Local ax#=VertexX#(v1)-VertexX#(v0)
		Local ay#=Self.VertexY#(v1)-Self.VertexY#(v0)
		Local az#=Self.VertexZ#(v1)-Self.VertexZ#(v0)
		
		'Local bx#=VertexX#(v2)-VertexX#(v1)
		Local by#=Self.VertexY#(v2)-Self.VertexY#(v1)
		Local bz#=Self.VertexZ#(v2)-Self.VertexZ#(v1)
		
		Return (ay#*bz#)-(az#*by#)
		
	End Method

	Method TriangleNY#(tri_no)
	
		Local v0=Self.TriangleVertex(tri_no,0)
		Local v1=Self.TriangleVertex(tri_no,1)
		Local v2=Self.TriangleVertex(tri_no,2)

		Local ax#=Self.VertexX#(v1)-Self.VertexX#(v0)
		'Local ay#=VertexY#(v1)-VertexY#(v0)
		Local az#=Self.VertexZ#(v1)-Self.VertexZ#(v0)
		
		Local bx#=Self.VertexX#(v2)-Self.VertexX#(v1)
		'Local by#=VertexY#(v2)-VertexY#(v1)
		Local bz#=Self.VertexZ#(v2)-Self.VertexZ#(v1)
	
		Return (az#*bx#)-(ax#*bz#)
			
	End Method

	Method TriangleNZ#(tri_no)
	
		Local v0=Self.TriangleVertex(tri_no,0)
		Local v1=Self.TriangleVertex(tri_no,1)
		Local v2=Self.TriangleVertex(tri_no,2)
		
		Local ax#=Self.VertexX#(v1)-Self.VertexX#(v0)
		Local ay#=Self.VertexY#(v1)-Self.VertexY#(v0)
		'Local az#=VertexZ#(v1)-VertexZ#(v0)
		
		Local bx#=Self.VertexX#(v2)-Self.VertexX#(v1)
		Local by#=Self.VertexY#(v2)-Self.VertexY#(v1)
		'Local bz#=VertexZ#(v2)-VertexZ#(v1)
		
		Return (ax#*by#)-(ay#*bx#)
		
	End Method
	
	Method UpdateVBO()
		Self.rederable.UpdateVBO(reset_vbo)
		Return True
	End Method
	
	Method FreeVBO()
		Self.rederable.FreeVBO()
		Return True
	End Method
	
End Type

Type TDXMesh Extends TDXEntity
	
	Field surf_list:TList = CreateList() 
	field vbo_enabled:int = false
	

	method PaintMesh(b:TDXBrush)
		for local s:TDXSurface = eachin surf_list
			s.brush = b	
		next 
	end method 


	Method CreateCube:TDXMesh() 
		Local surf:TDXSurface = New TDXSurface
		
		'DebugStop
		surf.AddVertex(-1.0,-1.0,-1.0)
		surf.AddVertex(-1.0, 1.0,-1.0)
		surf.AddVertex( 1.0, 1.0,-1.0)
		surf.AddVertex( 1.0,-1.0,-1.0)
		
		surf.AddVertex(-1.0,-1.0, 1.0)
		surf.AddVertex(-1.0, 1.0, 1.0)
		surf.AddVertex( 1.0, 1.0, 1.0)
		surf.AddVertex( 1.0,-1.0, 1.0)
			
		surf.AddVertex(-1.0,-1.0, 1.0)
		surf.AddVertex(-1.0, 1.0, 1.0)
		surf.AddVertex( 1.0, 1.0, 1.0)
		surf.AddVertex( 1.0,-1.0, 1.0)
		
		surf.AddVertex(-1.0,-1.0,-1.0)
		surf.AddVertex(-1.0, 1.0,-1.0)
		surf.AddVertex( 1.0, 1.0,-1.0)
		surf.AddVertex( 1.0,-1.0,-1.0)

		surf.AddVertex(-1.0,-1.0, 1.0)
		surf.AddVertex(-1.0, 1.0, 1.0)
		surf.AddVertex( 1.0, 1.0, 1.0)
		surf.AddVertex( 1.0,-1.0, 1.0)
		
		surf.AddVertex(-1.0,-1.0,-1.0)
		surf.AddVertex(-1.0, 1.0,-1.0)
		surf.AddVertex( 1.0, 1.0,-1.0)
		surf.AddVertex( 1.0,-1.0,-1.0)

		surf.VertexNormal(0,0.0,0.0,-1.0)
		surf.VertexNormal(1,0.0,0.0,-1.0)
		surf.VertexNormal(2,0.0,0.0,-1.0)
		surf.VertexNormal(3,0.0,0.0,-1.0)
	
		surf.VertexNormal(4,0.0,0.0,1.0)
		surf.VertexNormal(5,0.0,0.0,1.0)
		surf.VertexNormal(6,0.0,0.0,1.0)
		surf.VertexNormal(7,0.0,0.0,1.0)
		
		surf.VertexNormal(8,0.0,-1.0,0.0)
		surf.VertexNormal(9,0.0,1.0,0.0)
		surf.VertexNormal(10,0.0,1.0,0.0)
		surf.VertexNormal(11,0.0,-1.0,0.0)
				
		surf.VertexNormal(12,0.0,-1.0,0.0)
		surf.VertexNormal(13,0.0,1.0,0.0)
		surf.VertexNormal(14,0.0,1.0,0.0)
		surf.VertexNormal(15,0.0,-1.0,0.0)
	
		surf.VertexNormal(16,-1.0,0.0,0.0)
		surf.VertexNormal(17,-1.0,0.0,0.0)
		surf.VertexNormal(18,1.0,0.0,0.0)
		surf.VertexNormal(19,1.0,0.0,0.0)
				
		surf.VertexNormal(20,-1.0,0.0,0.0)
		surf.VertexNormal(21,-1.0,0.0,0.0)
		surf.VertexNormal(22,1.0,0.0,0.0)
		surf.VertexNormal(23,1.0,0.0,0.0)

		surf.VertexTexCoords(0,0.0,1.0)
		surf.VertexTexCoords(1,0.0,0.0)
		surf.VertexTexCoords(2,1.0,0.0)
		surf.VertexTexCoords(3,1.0,1.0)
		
		surf.VertexTexCoords(4,1.0,1.0)
		surf.VertexTexCoords(5,1.0,0.0)
		surf.VertexTexCoords(6,0.0,0.0)
		surf.VertexTexCoords(7,0.0,1.0)
		
		surf.VertexTexCoords(8,0.0,1.0)
		surf.VertexTexCoords(9,0.0,0.0)
		surf.VertexTexCoords(10,1.0,0.0)
		surf.VertexTexCoords(11,1.0,1.0)
			
		surf.VertexTexCoords(12,0.0,0.0)
		surf.VertexTexCoords(13,0.0,1.0)
		surf.VertexTexCoords(14,1.0,1.0)
		surf.VertexTexCoords(15,1.0,0.0)
	
		surf.VertexTexCoords(16,0.0,1.0)
		surf.VertexTexCoords(17,0.0,0.0)
		surf.VertexTexCoords(18,1.0,0.0)
		surf.VertexTexCoords(19,1.0,1.0)
				
		surf.VertexTexCoords(20,1.0,1.0)
		surf.VertexTexCoords(21,1.0,0.0)
		surf.VertexTexCoords(22,0.0,0.0)
		surf.VertexTexCoords(23,0.0,1.0)

		surf.VertexTexCoords(0,0.0,1.0,0.0,1)
		surf.VertexTexCoords(1,0.0,0.0,0.0,1)
		surf.VertexTexCoords(2,1.0,0.0,0.0,1)
		surf.VertexTexCoords(3,1.0,1.0,0.0,1)
		
		surf.VertexTexCoords(4,1.0,1.0,0.0,1)
		surf.VertexTexCoords(5,1.0,0.0,0.0,1)
		surf.VertexTexCoords(6,0.0,0.0,0.0,1)
		surf.VertexTexCoords(7,0.0,1.0,0.0,1)
		
		surf.VertexTexCoords(8,0.0,1.0,0.0,1)
		surf.VertexTexCoords(9,0.0,0.0,0.0,1)
		surf.VertexTexCoords(10,1.0,0.0,0.0,1)
		surf.VertexTexCoords(11,1.0,1.0,0.0,1)
			
		surf.VertexTexCoords(12,0.0,0.0,0.0,1)
		surf.VertexTexCoords(13,0.0,1.0,0.0,1)
		surf.VertexTexCoords(14,1.0,1.0,0.0,1)
		surf.VertexTexCoords(15,1.0,0.0,0.0,1)
	
		surf.VertexTexCoords(16,0.0,1.0,0.0,1)
		surf.VertexTexCoords(17,0.0,0.0,0.0,1)
		surf.VertexTexCoords(18,1.0,0.0,0.0,1)
		surf.VertexTexCoords(19,1.0,1.0,0.0,1)
				
		surf.VertexTexCoords(20,1.0,1.0,0.0,1)
		surf.VertexTexCoords(21,1.0,0.0,0.0,1)
		surf.VertexTexCoords(22,0.0,0.0,0.0,1)
		surf.VertexTexCoords(23,0.0,1.0,0.0,1)
				
		surf.AddTriangle(0,1,2) ' front
		surf.AddTriangle(0,2,3)
		surf.AddTriangle(6,5,4) ' back
		surf.AddTriangle(7,6,4)
		surf.AddTriangle(6+8,5+8,1+8) ' top
		surf.AddTriangle(2+8,6+8,1+8)
		surf.AddTriangle(0+8,4+8,7+8) ' bottom
		surf.AddTriangle(0+8,7+8,3+8)
		surf.AddTriangle(6+16,2+16,3+16) ' right
		surf.AddTriangle(7+16,6+16,3+16)
		surf.AddTriangle(0+16,1+16,5+16) ' left
		surf.AddTriangle(0 + 16, 5 + 16, 4 + 16) 
		
		surf_list.AddLast(surf) 
		
		Return Self
	End Method
	
	' Function by Coyote
	Method CreateSphere:TDXMesh(segments = 8) 

		If segments<2 Or segments>100 Then Return Null
		
		Local thissurf:TDXSurface = New TDXSurface

		Local div#=Float(360.0/(segments*2))
		Local height#=1.0
		Local upos#=1.0
		Local udiv#=Float(1.0/(segments*2))
		Local vdiv#=Float(1.0/segments)
		Local RotAngle#=90	
	
		If segments=2 ' diamond shape - no center strips
		
			For Local i=1 To (segments*2)
				Local np=thissurf.AddVertex(0.0,height,0.0,upos#-(udiv#/2.0),0)'northpole
				Local sp=thissurf.AddVertex(0.0,-height,0.0,upos#-(udiv#/2.0),1)'southpole
				Local XPos#=-Cos(RotAngle#)
				Local ZPos#=Sin(RotAngle#)
				Local v0=thissurf.AddVertex(XPos#,0,ZPos#,upos#,0.5)
				RotAngle#=RotAngle#+div#
				If RotAngle#>=360.0 Then RotAngle#=RotAngle#-360.0
				XPos#=-Cos(RotAngle#)
				ZPos#=Sin(RotAngle#)
				upos#=upos#-udiv#
				Local v1=thissurf.AddVertex(XPos#,0,ZPos#,upos#,0.5)
				thissurf.AddTriangle(np,v0,v1)
				thissurf.AddTriangle(v1,v0,sp)	
			Next
			
		Else ' have center strips now
		
			' poles first
			For Local i=1 To (segments*2)
				
				Local np=thissurf.AddVertex(0.0,height,0.0,upos#-(udiv#/2.0),0)'northpole
				Local sp=thissurf.AddVertex(0.0,-height,0.0,upos#-(udiv#/2.0),1)'southpole
				
				Local YPos#=Cos(div#)
				
				Local XPos#=-Cos(RotAngle#)*(Sin(div#))
				Local ZPos#=Sin(RotAngle#)*(Sin(div#))
				
				Local v0t=thissurf.AddVertex(XPos#,YPos#,ZPos#,upos#,vdiv#)
				Local v0b=thissurf.AddVertex(XPos#,-YPos#,ZPos#,upos#,1-vdiv#)
				
				RotAngle#=RotAngle#+div#
				
				XPos#=-Cos(RotAngle#)*(Sin(div#))
				ZPos#=Sin(RotAngle#)*(Sin(div#))
				
				upos#=upos#-udiv#
	
				Local v1t=thissurf.AddVertex(XPos#,YPos#,ZPos#,upos#,vdiv#)
				Local v1b=thissurf.AddVertex(XPos#,-YPos#,ZPos#,upos#,1-vdiv#)
				
				thissurf.AddTriangle(np,v0t,v1t)
				thissurf.AddTriangle(v1b,v0b,sp)	
				
			Next
			
			' then center strips
	
			upos#=1.0
			RotAngle#=90
			For Local i=1 To (segments*2)
			
				Local mult#=1
				Local YPos#=Cos(div#*(mult#))
				Local YPos2#=Cos(div#*(mult#+1.0))
				Local Thisvdiv#=vdiv#
				For Local j=1 To (segments-2)
	
					
					Local XPos#=-Cos(RotAngle#)*(Sin(div#*(mult#)))
					Local ZPos#=Sin(RotAngle#)*(Sin(div#*(mult#)))
	
					Local XPos2#=-Cos(RotAngle#)*(Sin(div#*(mult#+1.0)))
					Local ZPos2#=Sin(RotAngle#)*(Sin(div#*(mult#+1.0)))
								
					Local v0t=thissurf.AddVertex(XPos#,YPos#,ZPos#,upos#,Thisvdiv#)
					Local v0b=thissurf.AddVertex(XPos2#,YPos2#,ZPos2#,upos#,Thisvdiv#+vdiv#)
				
					' 2nd tex coord set
					thissurf.VertexTexCoords(v0t,upos#,Thisvdiv#,0.0,1)
					thissurf.VertexTexCoords(v0b,upos#,Thisvdiv#+vdiv#,0.0,1)
				
					Local tempRotAngle#=RotAngle#+div#
				
					XPos#=-Cos(tempRotAngle#)*(Sin(div#*(mult#)))
					ZPos#=Sin(tempRotAngle#)*(Sin(div#*(mult#)))
					
					XPos2#=-Cos(tempRotAngle#)*(Sin(div#*(mult#+1.0)))
					ZPos2#=Sin(tempRotAngle#)*(Sin(div#*(mult#+1.0)))				
				
					Local temp_upos#=upos#-udiv#
	
					Local v1t=thissurf.AddVertex(XPos#,YPos#,ZPos#,temp_upos#,Thisvdiv#)
					Local v1b=thissurf.AddVertex(XPos2#,YPos2#,ZPos2#,temp_upos#,Thisvdiv#+vdiv#)
					
					' 2nd tex coord set
					thissurf.VertexTexCoords(v1t,temp_upos#,Thisvdiv#,0.0,1)
					thissurf.VertexTexCoords(v1b,temp_upos#,Thisvdiv#+vdiv#,0.0,1)
					
					thissurf.AddTriangle(v1t,v0t,v0b)
					thissurf.AddTriangle(v1b,v1t,v0b)
					
					Thisvdiv#=Thisvdiv#+vdiv#			
					mult#=mult#+1
					YPos#=Cos(div#*(mult#))
					YPos2#=Cos(div#*(mult#+1.0))
				
				Next
				upos#=upos#-udiv#
				RotAngle#=RotAngle#+div#
			Next
	
		EndIf
	
		thissurf.UpdateNormals() 
	
		surf_list.AddLast(thissurf) 
		Return Self
	End Method
	
	Method Update() 
		For Local surf:TDXSurface = EachIn surf_list

			If vbo_enabled Then 
				surf.UpdateVBO() 
			endif 

			if surf.brush then surf.brush.TurnOn()

			surf.rederable.SetMatrix(mat) 
			surf.rederable.Update(vbo_enabled) 

			if surf.brush then surf.brush.TurnOff()


		Next
	End Method
	           
End Type

Type Direct3d

	Field clsColor				:Int 					= $FF000000
	Field Direct3D9 			:IDirect3D9				= Null 
	Field Direct3DDevice9		:IDirect3DDevice9		= Null
	Field BackBuffer			:IDirect3DSurface9 		= Null
	Field PParams				:D3DPRESENT_PARAMETERS  = Null
	Field hwnd					:Int 					= 0

	Method _Init(hwnd:Int, w:Int, h:Int, bWindowed:Int = False) 


		Self.hwnd = hwnd
		
		Direct3D9 = Direct3DCreate9( $900 )

		If Not Direct3D9  Then 
			assert "error creating d3d9interface!"
		EndIf
		
		PParams = New D3DPRESENT_PARAMETERS
		
		PParams.SwapEffect       = D3DSWAPEFFECT_DISCARD;
	    PParams.hDeviceWindow    = hwnd;
	    PParams.Windowed         = bWindowed;
	    PParams.BackBufferWidth  = w;
	    PParams.BackBufferHeight = h;
	    PParams.BackBufferFormat = D3DFMT_A8R8G8B8;

		PParams.EnableAutoDepthStencil = True 
		PParams.AutoDepthStencilFormat=D3DFMT_D16

		PParams.BackBufferCount = 1
		PParams.MultiSampleType = D3DMULTISAMPLE_NONE
		
		
		If Direct3D9.CreateDevice(0, D3DDEVTYPE_HAL, hwnd , D3DCREATE_PUREDEVICE | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, PParams, Direct3DDevice9) <> D3D_OK
			If Direct3D9.CreateDevice(0, D3DDEVTYPE_HAL, hwnd , D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, PParams, Direct3DDevice9) <> D3D_OK
				If Direct3D9.CreateDevice(0, D3DDEVTYPE_HAL, hwnd , D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, PParams, Direct3DDevice9) <> D3D_OK
				    assert "failed To create device _D3dDev9"
				End If
			End If
		EndIf
		


		Direct3DDevice9.GetBackBuffer(0,0, D3DBACKBUFFER_TYPE_MONO, BackBuffer );


		Direct3DDevice9.SetRenderState(D3DRS_AMBIENT, $FFAAAAAA) 
		Direct3DDevice9.SetRenderState(D3DRS_LIGHTING, true) 
		Direct3DDevice9.SetRenderState(D3DRS_CULLMODE, D3DCULL_CW) 
		Direct3DDevice9.SetRenderState(D3DRS_DITHERENABLE, true) 
		Direct3DDevice9.SetRenderState( D3DRS_SPECULARENABLE, true )  

		

	End Method 

	Method SetClsColor(r:Int,g:Int,b:Int)
		clsColor = Int(( 255 Shl 24)| (r Shl 16)| (g Shl 8)| b )
	End Method 

	Method BeginScene()
		Direct3DDevice9.Clear(0,Null,D3DCLEAR_TARGET,clsColor,0,0);
    	Return Direct3DDevice9.BeginScene()=0
    End Method 

	Method EndScene()
		Direct3DDevice9.EndScene();
    	Direct3DDevice9.Present(Null,Null,Null,Null);
	End Method 

	Method GetDevice:IDirect3DDevice9()
		Return 	Direct3DDevice9
	End Method 

	Method GetBackBuffer:IDirect3DSurface9()
		Return BackBuffer
	End Method 

	method SetAmbientLight(color:int = $00FFFFFF)
		Direct3DDevice9.SetRenderState(D3DRS_AMBIENT, color) 
	end method 

	method SetLightningEnable(enable:int)
		Direct3DDevice9.SetRenderState(D3DRS_LIGHTING, enable) 
	end method 

	method SetCullMode(mode:int = D3DCULL_CW )
		Direct3DDevice9.SetRenderState(D3DRS_CULLMODE, mode ) 
	end method 
	
	method SetDitherEnable(enable:int = true)
		Direct3DDevice9.SetRenderState(D3DRS_DITHERENABLE, enable) 
	end method 

End Type


Seems that the code is too long for one post, is that possible? So here's the rest:


Type TMatrix

	Field grid#[4,4]
	

	
	Method LoadIdentity()
	
		grid[0,0]=1.0
		grid[1,0]=0.0
		grid[2,0]=0.0
		grid[3,0]=0.0
		grid[0,1]=0.0
		grid[1,1]=1.0
		grid[2,1]=0.0
		grid[3,1]=0.0
		grid[0,2]=0.0
		grid[1,2]=0.0
		grid[2,2]=1.0
		grid[3,2]=0.0
		
		grid[0,3]=0.0
		grid[1,3]=0.0
		grid[2,3]=0.0
		grid[3,3]=1.0
	
	End Method
	
	' copy - create new copy and returns it
	
	Method Copy:TMatrix()
	
		Local mat:TMatrix=New TMatrix
	
		mat.grid[0,0]=grid[0,0]
		mat.grid[1,0]=grid[1,0]
		mat.grid[2,0]=grid[2,0]
		mat.grid[3,0]=grid[3,0]
		mat.grid[0,1]=grid[0,1]
		mat.grid[1,1]=grid[1,1]
		mat.grid[2,1]=grid[2,1]
		mat.grid[3,1]=grid[3,1]
		mat.grid[0,2]=grid[0,2]
		mat.grid[1,2]=grid[1,2]
		mat.grid[2,2]=grid[2,2]
		mat.grid[3,2]=grid[3,2]
		
		' do not remove
		mat.grid[0,3]=grid[0,3]
		mat.grid[1,3]=grid[1,3]
		mat.grid[2,3]=grid[2,3]
		mat.grid[3,3]=grid[3,3]
		
		Return mat
	
	End Method
	
	' overwrite - overwrites self with matrix passed as parameter
	
	Method Overwrite(mat:TMatrix)
	
		grid[0,0]=mat.grid[0,0]
		grid[1,0]=mat.grid[1,0]
		grid[2,0]=mat.grid[2,0]
		grid[3,0]=mat.grid[3,0]
		grid[0,1]=mat.grid[0,1]
		grid[1,1]=mat.grid[1,1]
		grid[2,1]=mat.grid[2,1]
		grid[3,1]=mat.grid[3,1]
		grid[0,2]=mat.grid[0,2]
		grid[1,2]=mat.grid[1,2]
		grid[2,2]=mat.grid[2,2]
		grid[3,2]=mat.grid[3,2]
		
		grid[0,3]=mat.grid[0,3]
		grid[1,3]=mat.grid[1,3]
		grid[2,3]=mat.grid[2,3]
		grid[3,3]=mat.grid[3,3]
		
	End Method
	
	Method Inverse:TMatrix()

		Local mat:TMatrix=New TMatrix
	
		Local tx#=0
		Local ty#=0
		Local tz#=0
	
	  	' The rotational part of the matrix is simply the transpose of the
	  	' original matrix.
	  	mat.grid[0,0] = grid[0,0]
	  	mat.grid[1,0] = grid[0,1]
	  	mat.grid[2,0] = grid[0,2]
	
		mat.grid[0,1] = grid[1,0]
		mat.grid[1,1] = grid[1,1]
		mat.grid[2,1] = grid[1,2]
	
		mat.grid[0,2] = grid[2,0]
		mat.grid[1,2] = grid[2,1]
		mat.grid[2,2] = grid[2,2]
	
		' The right column vector of the matrix should always be [ 0 0 0 1 ]
		' in most cases. . . you don't need this column at all because it'll 
		' never be used in the program, but since this code is used with GL
		' and it does consider this column, it is here.
		mat.grid[0,3] = 0 
		mat.grid[1,3] = 0
		mat.grid[2,3] = 0
		mat.grid[3,3] = 1
	
		' The translation components of the original matrix.
		tx = grid[3,0]
		ty = grid[3,1]
		tz = grid[3,2]
	
		' Result = -(Tm * Rm) To get the translation part of the inverse
		mat.grid[3,0] = -( (grid[0,0] * tx) + (grid[0,1] * ty) + (grid[0,2] * tz) )
		mat.grid[3,1] = -( (grid[1,0] * tx) + (grid[1,1] * ty) + (grid[1,2] * tz) )
		mat.grid[3,2] = -( (grid[2,0] * tx) + (grid[2,1] * ty) + (grid[2,2] * tz) )
	
		Return mat

	End Method

	Method Multiply(mat:TMatrix)
	
		Local m00# = grid#[0,0]*mat.grid#[0,0] + grid#[1,0]*mat.grid#[0,1] + grid#[2,0]*mat.grid#[0,2] + grid#[3,0]*mat.grid#[0,3]
		Local m01# = grid#[0,1]*mat.grid#[0,0] + grid#[1,1]*mat.grid#[0,1] + grid#[2,1]*mat.grid#[0,2] + grid#[3,1]*mat.grid#[0,3]
		Local m02# = grid#[0,2]*mat.grid#[0,0] + grid#[1,2]*mat.grid#[0,1] + grid#[2,2]*mat.grid#[0,2] + grid#[3,2]*mat.grid#[0,3]
		'Local m03# = grid#[0,3]*mat.grid#[0,0] + grid#[1,3]*mat.grid#[0,1] + grid#[2,3]*mat.grid#[0,2] + grid#[3,3]*mat.grid#[0,3]
		Local m10# = grid#[0,0]*mat.grid#[1,0] + grid#[1,0]*mat.grid#[1,1] + grid#[2,0]*mat.grid#[1,2] + grid#[3,0]*mat.grid#[1,3]
		Local m11# = grid#[0,1]*mat.grid#[1,0] + grid#[1,1]*mat.grid#[1,1] + grid#[2,1]*mat.grid#[1,2] + grid#[3,1]*mat.grid#[1,3]
		Local m12# = grid#[0,2]*mat.grid#[1,0] + grid#[1,2]*mat.grid#[1,1] + grid#[2,2]*mat.grid#[1,2] + grid#[3,2]*mat.grid#[1,3]
		'Local m13# = grid#[0,3]*mat.grid#[1,0] + grid#[1,3]*mat.grid#[1,1] + grid#[2,3]*mat.grid#[1,2] + grid#[3,3]*mat.grid#[1,3]
		Local m20# = grid#[0,0]*mat.grid#[2,0] + grid#[1,0]*mat.grid#[2,1] + grid#[2,0]*mat.grid#[2,2] + grid#[3,0]*mat.grid#[2,3]
		Local m21# = grid#[0,1]*mat.grid#[2,0] + grid#[1,1]*mat.grid#[2,1] + grid#[2,1]*mat.grid#[2,2] + grid#[3,1]*mat.grid#[2,3]
		Local m22# = grid#[0,2]*mat.grid#[2,0] + grid#[1,2]*mat.grid#[2,1] + grid#[2,2]*mat.grid#[2,2] + grid#[3,2]*mat.grid#[2,3]
		'Local m23# = grid#[0,3]*mat.grid#[2,0] + grid#[1,3]*mat.grid#[2,1] + grid#[2,3]*mat.grid#[2,2] + grid#[3,3]*mat.grid#[2,3]
		Local m30# = grid#[0,0]*mat.grid#[3,0] + grid#[1,0]*mat.grid#[3,1] + grid#[2,0]*mat.grid#[3,2] + grid#[3,0]*mat.grid#[3,3]
		Local m31# = grid#[0,1]*mat.grid#[3,0] + grid#[1,1]*mat.grid#[3,1] + grid#[2,1]*mat.grid#[3,2] + grid#[3,1]*mat.grid#[3,3]
		Local m32# = grid#[0,2]*mat.grid#[3,0] + grid#[1,2]*mat.grid#[3,1] + grid#[2,2]*mat.grid#[3,2] + grid#[3,2]*mat.grid#[3,3]
		'Local m33# = grid#[0,3]*mat.grid#[3,0] + grid#[1,3]*mat.grid#[3,1] + grid#[2,3]*mat.grid#[3,2] + grid#[3,3]*mat.grid#[3,3]
	
		grid[0,0]=m00
		grid[0,1]=m01
		grid[0,2]=m02
		'grid[0,3]=m03
		grid[1,0]=m10
		grid[1,1]=m11
		grid[1,2]=m12
		'grid[1,3]=m13
		grid[2,0]=m20
		grid[2,1]=m21
		grid[2,2]=m22
		'grid[2,3]=m23
		grid[3,0]=m30
		grid[3,1]=m31
		grid[3,2]=m32
		'grid[3,3]=m33
		
	End Method

	Method Translate(x#,y#,z#)
	
		grid[3,0] = grid#[0,0]*x# + grid#[1,0]*y# + grid#[2,0]*z# + grid#[3,0]
		grid[3,1] = grid#[0,1]*x# + grid#[1,1]*y# + grid#[2,1]*z# + grid#[3,1]
		grid[3,2] = grid#[0,2]*x# + grid#[1,2]*y# + grid#[2,2]*z# + grid#[3,2]

	End Method
		
	Method Scale(x#,y#,z#)
	
		grid[0,0] = grid#[0,0]*x#
		grid[0,1] = grid#[0,1]*x#
		grid[0,2] = grid#[0,2]*x#

		grid[1,0] = grid#[1,0]*y#
		grid[1,1] = grid#[1,1]*y#
		grid[1,2] = grid#[1,2]*y#

		grid[2,0] = grid#[2,0]*z#
		grid[2,1] = grid#[2,1]*z#
		grid[2,2] = grid#[2,2]*z# 
	
	End Method
	
	Method Rotate(rx#,ry#,rz#)
	
		Local cos_ang#,sin_ang#
	
		' yaw
	
		cos_ang#=Cos(ry#)
		sin_ang#=Sin(ry#)
	
		Local m00# = grid#[0,0]*cos_ang + grid#[2,0]*-sin_ang#
		Local m01# = grid#[0,1]*cos_ang + grid#[2,1]*-sin_ang#
		Local m02# = grid#[0,2]*cos_ang + grid#[2,2]*-sin_ang#

		grid[2,0] = grid#[0,0]*sin_ang# + grid#[2,0]*cos_ang
		grid[2,1] = grid#[0,1]*sin_ang# + grid#[2,1]*cos_ang
		grid[2,2] = grid#[0,2]*sin_ang# + grid#[2,2]*cos_ang

		grid[0,0]=m00#
		grid[0,1]=m01#
		grid[0,2]=m02#
		
		' pitch
		
		cos_ang#=Cos(rx#)
		sin_ang#=Sin(rx#)
	
		Local m10# = grid#[1,0]*cos_ang + grid#[2,0]*sin_ang
		Local m11# = grid#[1,1]*cos_ang + grid#[2,1]*sin_ang
		Local m12# = grid#[1,2]*cos_ang + grid#[2,2]*sin_ang

		grid[2,0] = grid#[1,0]*-sin_ang + grid#[2,0]*cos_ang
		grid[2,1] = grid#[1,1]*-sin_ang + grid#[2,1]*cos_ang
		grid[2,2] = grid#[1,2]*-sin_ang + grid#[2,2]*cos_ang

		grid[1,0]=m10
		grid[1,1]=m11
		grid[1,2]=m12
		
		' roll
		
		cos_ang#=Cos(rz#)
		sin_ang#=Sin(rz#)

		m00# = grid#[0,0]*cos_ang# + grid#[1,0]*sin_ang#
		m01# = grid#[0,1]*cos_ang# + grid#[1,1]*sin_ang#
		m02# = grid#[0,2]*cos_ang# + grid#[1,2]*sin_ang#

		grid[1,0] = grid#[0,0]*-sin_ang# + grid#[1,0]*cos_ang#
		grid[1,1] = grid#[0,1]*-sin_ang# + grid#[1,1]*cos_ang#
		grid[1,2] = grid#[0,2]*-sin_ang# + grid#[1,2]*cos_ang#

		grid[0,0]=m00#
		grid[0,1]=m01#
		grid[0,2]=m02#
	
	End Method
	
	Method RotatePitch(ang#)
	
		Local cos_ang#=Cos(ang#)
		Local sin_ang#=Sin(ang#)
	
		Local m10# = grid#[1,0]*cos_ang + grid#[2,0]*sin_ang
		Local m11# = grid#[1,1]*cos_ang + grid#[2,1]*sin_ang
		Local m12# = grid#[1,2]*cos_ang + grid#[2,2]*sin_ang

		grid[2,0] = grid#[1,0]*-sin_ang + grid#[2,0]*cos_ang
		grid[2,1] = grid#[1,1]*-sin_ang + grid#[2,1]*cos_ang
		grid[2,2] = grid#[1,2]*-sin_ang + grid#[2,2]*cos_ang

		grid[1,0]=m10
		grid[1,1]=m11
		grid[1,2]=m12

	End Method
	
	Method RotateYaw(ang#)
	
		Local cos_ang#=Cos(ang#)
		Local sin_ang#=Sin(ang#)
	
		Local m00# = grid#[0,0]*cos_ang + grid#[2,0]*-sin_ang#
		Local m01# = grid#[0,1]*cos_ang + grid#[2,1]*-sin_ang#
		Local m02# = grid#[0,2]*cos_ang + grid#[2,2]*-sin_ang#

		grid[2,0] = grid#[0,0]*sin_ang# + grid#[2,0]*cos_ang
		grid[2,1] = grid#[0,1]*sin_ang# + grid#[2,1]*cos_ang
		grid[2,2] = grid#[0,2]*sin_ang# + grid#[2,2]*cos_ang

		grid[0,0]=m00#
		grid[0,1]=m01#
		grid[0,2]=m02#

	End Method
	
	Method RotateRoll(ang#)
	
		Local cos_ang#=Cos(ang#)
		Local sin_ang#=Sin(ang#)

		Local m00# = grid#[0,0]*cos_ang# + grid#[1,0]*sin_ang#
		Local m01# = grid#[0,1]*cos_ang# + grid#[1,1]*sin_ang#
		Local m02# = grid#[0,2]*cos_ang# + grid#[1,2]*sin_ang#

		grid[1,0] = grid#[0,0]*-sin_ang# + grid#[1,0]*cos_ang#
		grid[1,1] = grid#[0,1]*-sin_ang# + grid#[1,1]*cos_ang#
		grid[1,2] = grid#[0,2]*-sin_ang# + grid#[1,2]*cos_ang#

		grid[0,0]=m00#
		grid[0,1]=m01#
		grid[0,2]=m02#

	End Method
		
End Type

'###################################################################################################################

Type TVector

	Field x#,y#,z#
	
	Const EPSILON=.0001
	
	Method ToPtr:Float[]()
		Return [x,y,z]
	End Method

	Method New()
	
		'If LOG_NEW
		'	DebugLog "New TVector"
		'EndIf
	
	End Method
	
	Method Delete()
	
		'If LOG_DEL
		'	DebugLog "Del TVector"
		'EndIf
	
	End Method

	Function Create:TVector(x#,y#,z#)
	
		Local vec:TVector=New TVector
		vec.x=x
		vec.y=y
		vec.z=z
		
		Return vec
		
	End Function
	
	Method Copy:TVector()
	
		Local vec:TVector=New TVector
	
		vec.x=x
		vec.y=y
		vec.z=z
	
		Return vec
	
	End Method
	
	Method Add:TVector(vec:TVector)
	
		Local new_vec:TVector=New TVector
		
		new_vec.x=x+vec.x
		new_vec.y=y+vec.y
		new_vec.z=z+vec.z
		
		Return new_vec
	
	End Method
	
	Method Subtract:TVector(vec:TVector)
	
		Local new_vec:TVector=New TVector
		
		new_vec.x=x-vec.x
		new_vec.y=y-vec.y
		new_vec.z=z-vec.z
		
		Return new_vec
	
	End Method
	
	Method Multiply:TVector(val#)
	
		Local new_vec:TVector=New TVector
		
		new_vec.x=x*val#
		new_vec.y=y*val#
		new_vec.z=z*val#
		
		Return new_vec
	
	End Method
	
	Method Divide:TVector(val#)
	
		Local new_vec:TVector=New TVector
		
		new_vec.x=x/val#
		new_vec.y=y/val#
		new_vec.z=z/val#
		
		Return new_vec
	
	End Method
	
	Method Dot:Float(vec:TVector)
	
		Return (x#*vec.x#)+(y#*vec.y#)+(z#*vec.z#)
	
	End Method
	
	Method Cross:TVector(vec:TVector)
	
		Local new_vec:TVector=New TVector
		
		new_vec.x=(y*vec.z)-(z*vec.y)
		new_vec.y=(z*vec.x)-(x*vec.z)
		new_vec.z=(x*vec.y)-(y*vec.x)
		
		Return new_vec
	
	End Method
	
	Method Normalize()
	
		Local d#=1/Sqr(x*x+y*y+z*z)
		x:*d
		y:*d
		z:*d
		
	End Method
	
	Method Length#()
			
		Return Sqr(x*x+y*y+z*z)

	End Method
	
	Method SquaredLength#()
	
		Return x*x+y*y+z*z

	End Method
	
	Method SetLength#(val#)
	
		Normalize()
		x=x*val
		y=y*val
		z=z*val

	End Method
	
	Method Compare( with:Object )
		Local q:TVector=TVector(with)
		If x-q.x>EPSILON Return 1
		If q.x-x>EPSILON Return -1
		If y-q.y>EPSILON Return 1
		If q.y-y>EPSILON Return -1
		If z-q.z>EPSILON Return 1
		If q.z-z>EPSILON Return -1
		Return 0
	End Method

	' Function by patmaba
	Function VectorYaw#(vx#,vy#,vz#)

		Return ATan2(-vx#,vz#)
	
	End Function

	' Function by patmaba
	Function VectorPitch#(vx#,vy#,vz#)

		Local ang#=ATan2(Sqr(vx#*vx#+vz#*vz#),vy#)-90.0

		If ang#<=0.0001 And ang#>=-0.0001 Then ang#=0
	
		Return ang#
	
	End Function

End Type

'###################################################################################################################



Type TRect
	Field _Left	:Int
	Field _Top	: Int
	Field _Right : Int
	Field _Bottom: Int
	
	Function Create:TRect(ALeft:Int,ATop:Int,ARight:Int,ABottom:Int)
		Local this:TRect=New TRect
		this._Left=ALeft
		this._Top=ATop
		this._Right=ARight		
		this._Bottom=ABottom
		Return this
	End Function
	Method Width:Int()
		Return _Right-_Left
	End Method
	Method Height:Int()
		Return _Bottom-_Top
	End Method
End Type

Function WndProc:Int( hwnd:Int,message:Int,wp:Int,lp:Int ) "win32"
	bbSystemEmitOSEvent hwnd,message,wp,lp,Null
	Select message
	Case WM_CLOSE
		end 
	Case WM_SYSKEYDOWN
		If wp<>KEY_F4 Return 0
	' ensure the valid Flag is current due to mode/focus changes	
	Case WM_SETFOCUS		
		'_dx9driver.ValidateGraphics
	' ensure the valid Flag is current due to mode/focus changes		
	Case WM_KILLFOCUS
		'_dx9driver.ValidateGraphics
	End Select
	Return DefWindowProcA( hwnd,message,wp,lp )
End Function

function CreateGameWindow:int(width:int, height:int )
	Local wc:WNDCLASS=New WNDCLASS
	wc.hInstance = GetModuleHandleA(0) 
	wc.lpfnWndProc = WndProc
	wc.hCursor=LoadCursorA( Null,Byte Ptr IDC_ARROW )
	wc.lpszClassName=_DX9GRAPHICSEXWINDOWCLASS
	RegisterClassA( wc )

	Local hinst:Int = GetModuleHandleA(0) 
	Local title:Byte Ptr=AppTitle.ToCString()
	
	Local hwnd:Int
	width:int = 800
	height:int = 600
	Local style:Int=WS_VISIBLE|WS_CAPTION|WS_SYSMENU |WS_SIZEBOX 
	Local rect :TRect = TRect.Create(32,32,width+32,height+32)
	AdjustWindowRect Int Ptr Byte Ptr rect,style,0
	width=rect.Width()
	height=rect.Height()

	hwnd=CreateWindowExA( 0,_DX9GRAPHICSEXWINDOWCLASS,title,style,rect._Left,rect._Top,width,height,0,0,hinst,Null )
	return hwnd
end function



'###################
' UTILS
'###################

Function AdjustPixmap:TPixmap(pixmap:TPixmap)
	
	' adjust width and height size to next biggest power of 2 size
	Local width=Pow2Size(pixmap.width)
	Local height=Pow2Size(pixmap.height)

	' if width or height have changed then resize pixmap
	If width<>pixmap.width Or height<>pixmap.height
		pixmap=ResizePixmap(pixmap,width,height)
	EndIf
	
	' return pixmap
	Return pixmap
	
End Function

Function Pow2Size( n )
	Local t=1
	While t<n
		t:*2
	Wend
	Return t
End Function



Hi Rone,
on my RADEON 9600 TX all is working fine.

The only thing I had to change was the LoadLibraryA ("d3dx9d_33") to "d3dx9_36".
In a future state is there a posibility to use automatically the correct dll installed ?

the exe doesnt do anything, I see a window for a split second then it quits

if _36 was present, 33 should be present as well, otherwise you use Vista and forgot to run the DX Webinstaller which installs the about 10 missing versions of DX9.0c ... :)

@Yahfree: What graphic card do you use?

I have just implemented our miniB3d interface, basically copy/paste the above code...works fine on ATI, but still compatibility problems with nVidia-cards.

@Dreamora: I don't use Vista. The dll wich is present is "d3dx9_33" not "d3dx9d_33". Maybe it is a DX developer edition Rone is useing and the "d" is standing for. I don't know.

Before the change inside the code I had the same probleme like Yahfree if I run the exe.

Yupp the d3dx9d_33 specifies the debug dll instead of the retail one which would be what you first pointed out. Missed the d there and therefor only answered to the version part.
That error definitely needs to be fixed as it means crash on most systems and kills the performance. (above that it can affect shaders and lead to anomalies)