' Updates:
' 01/02/07 - ClearSurface
' 06/02/07 - VertexRed, VertexGreen, VertexBlue

Type TSurface

	' no of vertices and triangles in surface

	Field no_verts=0
	Field no_tris=0
	
	' arrays containing vertex and triangle info
	
	Field tris:Int[0]
	Field vert_coords#[0]
	Field vert_tex_coords0#[0]
	Field vert_tex_coords1#[0]
	Field vert_norm#[0]
	Field vert_col#[0]

	' brush applied to surface

	Field brush:TBrush
	
	' misc vars
	
	Field vert_array_size=1
	Field tri_array_size=1
	Field vmin=1000000 ' used for animation - seeb3dloader (tris)
	Field vmax=0 ' used for animation - see b3dloader (tris)
	Field new_bounds = False ' used by TMesh.GetBounds to check if mesh shape has changed, set to True by VertexCoords, AddTriangle
	
	'buffers
	Field vbuffers      : Int[6]
	Field triangles     : Int Ptr
	Field ibuffer : Int
	
	Field Bupdate:Byte = False
	Field BufferInit:Byte = False
	Field hidden:Byte = False
	
	
	Method InitBuffers()
		If THardwareInfo.VBOSupport Then
			BufferInit = True
			glGenBuffersARB(6, Self.vbuffers)
			glGenBuffersARB(1 , Varptr(Self.ibuffer) )' Generate HardwareBuffers for Vertices and Traingles
		EndIf
	End Method
	
	Method HideSurface()
		hidden = True
	End Method
	
	Method ShowSurface()
		hidden = False
	End Method

					
	Method Copy:TSurface()
	
		Local surf:TSurface=New TSurface
		
		surf.no_verts=no_verts
		surf.no_tris=no_tris
		
		surf.tris=tris[..]
		surf.vert_coords#=vert_coords#[..]
		surf.vert_tex_coords0#=vert_tex_coords0#[..]
		surf.vert_tex_coords1#=vert_tex_coords1#[..]
		surf.vert_norm#=vert_norm[..]
		surf.vert_col#=vert_col[..]
		
		If brush<>Null
			surf.brush=brush.Copy()
		EndIf
		
		surf.vert_array_size=vert_array_size
		surf.tri_array_size=tri_array_size
		surf.vmin=vmin
		surf.vmax = vmax
		
		surf.vbuffers = vbuffers
		surf.triangles = triangles
		surf.ibuffer = ibuffer		
		surf.Bupdate = BUpdate
		surf.BufferInit = BufferInit
		
		Return surf
	
	End Method
	
	Method PaintSurface(bru:TBrush)
	
		brush=bru
		
	End Method
	
	Method ClearSurface(clear_verts=True,clear_tris=True)
	
		If clear_verts
		
			no_verts=0
			
			vert_coords#=vert_coords#[..0]
			vert_tex_coords0#=vert_tex_coords0#[..0]
			vert_tex_coords1#=vert_tex_coords1#[..0]
			vert_norm#=vert_norm#[..0]
			vert_col#=vert_col#[..0]
			
			vert_array_size=1
		
		EndIf
		
		If clear_tris
		
			no_tris=0
			
			tris=tris[..0]

			tri_array_size=1
		
		EndIf
		
		' set new_bounds to true so TMesh -> GetBounds will update bounds values next time it's called
		new_bounds=True
	
	End Method
			
	Method AddVertex(x#,y#,z#,u#=0.0,v#=0.0,w#=0.0)
		
		no_verts=no_verts+1

		' resize arrays
		
		If no_verts>=vert_array_size
		
			Repeat
				vert_array_size=vert_array_size*2
			Until vert_array_size>no_verts
			
			Local vas=vert_array_size
		
			vert_coords=vert_coords[..vas*3]
			vert_tex_coords0=vert_tex_coords0[..vas*2]
			vert_tex_coords1=vert_tex_coords1[..vas*2]
			vert_norm=vert_norm[..vas*3]
			vert_col=vert_col[..vas*4]
		
		EndIf
		
		Local vxi=(no_verts*3)-3
		Local vyi=(no_verts*3)-2
		Local vzi=(no_verts*3)-1		
		Local vui=(no_verts*2)-2
		Local vvi=(no_verts*2)-1
		Local vri=(no_verts*4)-4
		Local vgi=(no_verts*4)-3
		Local vbi=(no_verts*4)-2
		Local vai=(no_verts*4)-1
		
		vert_coords[vxi]=x#
		vert_coords[vyi]=y#
		vert_coords[vzi]=-z# ' ***ogl***

		vert_tex_coords0[vui]=u#
		vert_tex_coords0[vvi]=v#
		
		' default vertex colours
		vert_col#[vri]=1.0
		vert_col#[vgi]=1.0
		vert_col#[vbi]=1.0
		vert_col#[vai]=1.0
				
		Return no_verts-1
	
	End Method
	
	Method AddTriangle(v0,v1,v2)
	
		no_tris=no_tris+1
		
		' resize array
		
		If no_tris>=tri_array_size
		
			Repeat
				tri_array_size=tri_array_size*2
			Until tri_array_size>no_tris
		
			Local tas=tri_array_size
		
			tris=tris[..tas*3]
			
		EndIf
		
		Local v0i=(no_tris*3)-3
		Local v1i=(no_tris*3)-2
		Local v2i=(no_tris*3)-1	
	
		tris[v0i]=v2
		tris[v1i]=v1
		tris[v2i]=v0
		
		' set new_bounds to true so TMesh -> GetBounds will update bounds values next time it's called
		new_bounds=True
		
		Return no_tris
	
	End Method
	
	Method CountVertices()
	
		Return no_verts
	
	End Method
	
	Method CountTriangles()
	
		Return no_tris
	
	End Method
	
	Method VertexCoords(vid,x#,y#,z#)
	
		vid=vid*3
		vert_coords#[vid]=x#
		vert_coords#[vid+1]=y#
		vert_coords#[vid+2]=z#*-1 ' ***ogl***
		
		' set new_bounds to true so TMesh -> GetBounds will update bounds values next time it's called
		new_bounds=True
		
	End Method
			
	Method VertexColor(vid,r#,g#,b#,a#=1.0)
	
		vid=vid*4
		vert_col#[vid]=r#/255.0
		vert_col#[vid+1]=g#/255.0
		vert_col#[vid+2]=b#/255.0
		vert_col#[vid+3]=a#

	End Method
	
	Method VertexNormal(vid,nx#,ny#,nz#)
	
		vid=vid*3
		vert_norm#[vid]=nx#
		vert_norm#[vid+1]=ny#
		vert_norm#[vid+2]=nz#*-1 ' ***ogl***

	End Method
	
	Method VertexTexCoords(vid,u#,v#,w#=0.0,coord_set=0)
	
		vid=vid*2
		
		If coord_set=0
		
			vert_tex_coords0#[vid]=u#
			vert_tex_coords0#[vid+1]=v#

		EndIf
		
		If coord_set=1
		
			vert_tex_coords1#[vid]=u#
			vert_tex_coords1#[vid+1]=v#
		
		EndIf

	End Method
		
	Method VertexX#(vid)
	
		Return vert_coords[vid*3]

	End Method

	Method VertexY#(vid)
	
		Return vert_coords[(vid*3)+1]

	End Method
	
	Method VertexZ#(vid)
	
		Return -vert_coords[(vid*3)+2] ' ***ogl***

	End Method
	
	Method VertexRed#(vid)
	
		Return vert_col[vid*4]*255.0

	End Method
	
	Method VertexGreen#(vid)
	
		Return vert_col[(vid*4)+1]*255.0

	End Method
	
	Method VertexBlue#(vid)
	
		Return vert_col[(vid*4)+2]*255.0

	End Method
	
	Method VertexAlpha#(vid)
	
		Return vert_col[(vid*4)+3]

	End Method
	
	Method VertexNX#(vid)
	
		Return vert_norm[vid*3]

	End Method
	
	Method VertexNY#(vid)
	
		Return vert_norm[(vid*3)+1]

	End Method
	
	Method VertexNZ#(vid)
	
		Return -vert_norm[(vid*3)+2] ' ***ogl***

	End Method
	
	Method VertexU#(vid,coord_set=0)
	
		If coord_set=0 Then Return vert_tex_coords0[vid*2]
		If coord_set=1 Then Return vert_tex_coords1[vid*2]

	End Method
	
	Method VertexV#(vid,coord_set=0)
	
		If coord_set=0 Then Return vert_tex_coords0[(vid*2)+1]
		If coord_set=1 Then Return vert_tex_coords1[(vid*2)+1]

	End Method
	
	Method VertexW#(vid,coord_set=0)
	
		Return 0

	End Method
	
	Method TriangleVertex(tri_no,corner)
	
		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
	
	' MiniB3D functions
	
	' Extra - offers extra functionality that Blitz3D does not
	
	Method TriangleNX#(tri_no)

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

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

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

	Method TriangleNZ#(tri_no)
	
		Local v0=TriangleVertex(tri_no,0)
		Local v1=TriangleVertex(tri_no,1)
		Local v2=TriangleVertex(tri_no,2)
		
		Local ax#=VertexX#(v1)-VertexX#(v0)
		Local ay#=VertexY#(v1)-VertexY#(v0)
		'Local az#=VertexZ#(v1)-VertexZ#(v0)
		
		Local bx#=VertexX#(v2)-VertexX#(v1)
		Local by#=VertexY#(v2)-VertexY#(v1)
		'Local bz#=VertexZ#(v2)-VertexZ#(v1)
		
		Return (ax#*by#)-(ay#*bx#)
		
	End Method
	
	Method UpdateVertices:Int(position:Int=True, Normal:Int=True, UV0:Int=True, ..
	                          UV1:Int=True, color:Int=True, Attributes:Int=True)

		' Check for VertexBufferObject-Support
		If Not THardwareInfo.VBOSupport Then Return False
		
		Rem
		Local vco:Float[] = vert_coords#[..]
		Local vtc0:Float[] = vert_tex_coords0#[..]
		Local vtc1:Float[] =  vert_tex_coords1#[..]
		Local vn:Float[] = vert_norm#[..]
		Local vc:Float[] =  vert_col#[..]
		End Rem

		
		' Transfer Buffer(s) from WorkRAM to VideoRAM
		If position Then
			glBindBufferARB(GL_ARRAY_BUFFER, Self.vbuffers[0])
			glBufferDataARB(GL_ARRAY_BUFFER, Self.no_verts*12, vert_coords#, GL_STATIC_DRAW)
		EndIf

		If Normal Then
			glBindBufferARB(GL_ARRAY_BUFFER, Self.vbuffers[1])
			glBufferDataARB(GL_ARRAY_BUFFER, Self.no_verts*12, vert_norm#, GL_STATIC_DRAW)
		EndIf

		If UV0 Then
			glBindBufferARB(GL_ARRAY_BUFFER, Self.vbuffers[2])
			glBufferDataARB(GL_ARRAY_BUFFER, Self.no_verts*8, vert_tex_coords0#, GL_STATIC_DRAW)
		EndIf

		If UV1 Then
			glBindBufferARB(GL_ARRAY_BUFFER, Self.vbuffers[3])
			glBufferDataARB(GL_ARRAY_BUFFER, Self.no_verts*8, vert_tex_coords1#, GL_STATIC_DRAW)
		EndIf

		If color Then
			glBindBufferARB(GL_ARRAY_BUFFER, Self.vbuffers[4])
			glBufferDataARB(GL_ARRAY_BUFFER, Self.no_verts*16, vert_col#, GL_STATIC_DRAW)
		EndIf
		
		glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, Null)
		glBindBufferARB(GL_ARRAY_BUFFER, Null)

		
		Return True
	End Method
	
	Method UpdateTriangles:Int()
		
		' Check for VertexBufferObject-Support
		If Not THardwareInfo.VBOSupport Then Return False
		'Local t:Int[] = tris[..]

		' Transfer TriangleBuffer from WorkRAM into VideoRAM
		glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, Self.ibuffer)
		glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER, Self.no_tris*12, tris, ..
		 GL_STATIC_DRAW)
		
		glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, Null)
		glBindBufferARB(GL_ARRAY_BUFFER, Null)

		Bupdate = True
		Return True
	End Method
	
	Method DeleteBuffers()
		If THardwareInfo.VBOSupport Then
			glDeleteBuffers(5, Self.VBuffers)
			glDeleteBuffers(1, Varptr(Self.IBuffer))
		EndIf
	End Method



End Type
