strage behavior on different GPUs with direct3d9

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

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