This is a frozen project which was laying around in my hd, so I decided to publish the code.
Does the basic stuff like animations etc, has a simple particle system and shader support, loads .md2 files, shadows don't work but are partially coded in.
The lib itself: ngl.bmx
SuperStrict
Const ShadowDistance:Float = 10.0
Include "nmatrix.bmx"
Type NPoint
Field X:Float
Field Y:Float
Field Z:Float
Method Translate(NewX:Float,NewY:Float,NewZ:Float)
X = X+NewX
Y = Y+NewY
Z = Z+NewZ
End Method
Method Position(NewX:Float,NewY:Float,NewZ:Float)
X = NewX
Y = NewY
Z = NewZ
End Method
Method DotProduct:Float(P2:NPoint)
Return X*P2.X+Y*P2.Y+Z*P2.Z
End Method
Method Normalize()
Local f:Float = 1.0/Sqr(DotProduct(Self))
X = X * f
Y = Y * f
Z = Z * f
End Method
Method RenderShadows()
ListAddLast(NGraphics.Gfx.ShadowList,Self)
End Method
End Type
Type NGraphics
Field Width:Int
Field Height:Int
Field Depth:Int
Field Fullscreen:Int
Field FPS:Int,FPSCount:Int,FPSTimer:Int
Field Lighting:Int
Field Triangles:Int
Field TextureEnabled:Int,CurrentTexture:Int
Field WireframeEnabled:Int,AlphaEnabled:Int
Field CurrentProgramObject:Int
Field ShadowList:TList
Global Gfx:NGraphics
Method Render()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
Triangles=0
For Local NCam:NCamera = EachIn NCamera.NCameraList
gluPerspective(45.0, Float(Width)/Float(Height), NCam.Near, NCam.Far)
If NCam.Enabled Then
glLoadIdentity()
glClearColor(NCam.ClsColor[0],NCam.ClsColor[1],NCam.ClsColor[2], 0.0)
If NCam.Fog Then
glEnable(GL_FOG)
glFogi(GL_FOG_MODE, GL_LINEAR)
glFogfv(GL_FOG_COLOR, NCam.FogColor)
glFogf(GL_FOG_DENSITY, NCam.FogDensity)
glHint(GL_FOG_HINT, GL_NICEST)
glFogf(GL_FOG_START, NCam.FogStart)
glFogf(GL_FOG_END, NCam.FogEnd)
Else
glDisable(GL_FOG)
EndIf
'Vertex buffer objects
'glEnableClientState(GL_VERTEX_ARRAY)
'glEnableClientState(GL_TEXTURE_COORD_ARRAY)
' 'Position camera
glRotatef(NCam.Pitch,1.0,0,0)
glRotatef(NCam.Yaw,0,1.0,0)
glRotatef(NCam.Roll,0,0,1.0)
glTranslatef(NCam.X,NCam.Y,NCam.Z)
'Lights
If Lighting Then
For Local NLi:NLight = EachIn NLight.NLightList
glLightfv(NLi.GL_LIGHT,GL_POSITION,[NLi.X,NLi.Y,NLi.Z,1.0])
Next
EndIf
'Z-Order
For Local NEnt:NEntity = EachIn NEntity.NEntityList
NEnt.CamDistance = Sqr((NCam.X-NEnt.X)*(NCam.X-NEnt.X)+(NCam.Y-NEnt.Y)*(NCam.Y-NEnt.Y)+(NCam.Z-NEnt.Z)*(NCam.Z-NEnt.Z))
If NEnt.RenderFirst Then NEnt.CamDistance = 0
'Display list
If NEnt.CreateDList Then
NEnt.CreateDisplayList()
NEnt.CreateDList = 0
EndIf
Next
NEntity.NEntityList.Sort(True,NEntity.CompareDistance)
'Loop entities
Local CAlpha:Float
For Local NEnt:NEntity = EachIn NEntity.NEntityList
If NEnt.Parent = Null Then RenderEntity(NEnt,NCam)
Next
If CurrentProgramObject <> 0 Then
CurrentProgramObject = 0
glUseProgramObjectARB(0)
glDisable(GL_VERTEX_PROGRAM_ARB)
glDisable(GL_FRAGMENT_PROGRAM_ARB)
EndIf
'Texture
If TextureEnabled<>1 Then
TextureEnabled = 1
glEnable(GL_TEXTURE_2D)
EndIf
'Draw particles
If Not AlphaEnabled Then glEnable(GL_BLEND)
For Local NEmit:NParticleEmitter = EachIn NParticleEmitter.NParticleEmitterList
If CurrentTexture<>NEmit.Texture Then
CurrentTexture = NEmit.Texture
glBindTexture (GL_TEXTURE_2D, CurrentTexture)
EndIf
NEmit.Update(NCam)
Next
If Not AlphaEnabled Then glDisable(GL_BLEND)
' CurrentTexture = 0
'TextureEnabled = 0
'glDisable(GL_TEXTURE_2D)
'Shadows
glDisable(GL_TEXTURE_2D)
glEnable(GL_BLEND)
For Local NP:NPoint = EachIn ShadowList
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE)
glDepthMask(GL_FALSE)
glEnable(GL_CULL_FACE)
glEnable(GL_STENCIL_TEST)
glEnable(GL_POLYGON_OFFSET_FILL)
glPolygonOffset(0.0, 100.0)
glCullFace(GL_FRONT)
glStencilFunc(GL_ALWAYS, 0, $ff)
glStencilOp(GL_KEEP, GL_INCR, GL_KEEP)
RenderShadow(NP.X,NP.Y,NP.Z,NCam)
glCullFace(GL_BACK)
glStencilFunc(GL_ALWAYS, 0, $ff)
glStencilOp(GL_KEEP, GL_DECR, GL_KEEP)
RenderShadow(NP.X,NP.Y,NP.Z,NCam)
glDisable(GL_POLYGON_OFFSET_FILL)
glDisable(GL_CULL_FACE)
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE)
glDepthMask(GL_TRUE)
glStencilFunc(GL_NOTEQUAL, 0, $ff)
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE)
DrawShadow()
glDisable(GL_STENCIL_TEST)
ListRemove(ShadowList,NP)
' glColor4f(1.0,1.0,1.0,0.1)
' glEnable(GL_CULL_FACE)
' glCullFace(GL_FRONT)
' RenderShadow(NP.X,NP.Y,NP.Z,NCam)
' glCullFace(GL_BACK)
Next
glEnable(GL_TEXTURE_2D)
glEnable(GL_CULL_FACE)
If Not AlphaEnabled Then glDisable(GL_BLEND)
EndIf
Next
FPSCount=FPSCount+1
If MilliSecs() > FPSTimer+999 Then
FPS=FPSCount
FPSTimer=MilliSecs()
FPSCount=0
EndIf
End Method
Method RenderShadow(X:Float,Y:Float,Z:Float,NCam:NCamera)
Local FX:Float[3],FY:Float[3],FZ:Float[3],BX:Float[3],BY:Float[3],BZ:Float[3],NP:NPoint = New NPoint
For Local NEnt:NEntity = EachIn NEntity.NEntityList
If NEnt.Shadows Then
For Local NTri:NTriangle = EachIn NEnt.NTriangleList[NEnt.Frame]
FX[0] = NTri.V1.X+NEnt.X; FY[0] = NTri.V1.Y+NEnt.Y; FZ[0] = NTri.V1.Z+NEnt.Z
FX[1] = NTri.V2.X+NEnt.X; FY[1] = NTri.V2.Y+NEnt.Y; FZ[1] = NTri.V2.Z+NEnt.Z
FX[2] = NTri.V3.X+NEnt.X; FY[2] = NTri.V3.Y+NEnt.Y; FZ[2] = NTri.V3.Z+NEnt.Z
NP.X = FX[0]-X; NP.Y = FY[0]-Y; NP.Z = FZ[0]-Z
NP.Normalize()
NP.X = NP.X * NCam.Far*ShadowDistance; NP.Y = NP.Y * NCam.Far*ShadowDistance; NP.Z = NP.Z * NCam.Far*ShadowDistance
BX[0] = NP.X; BY[0] = NP.Y; BZ[0] = NP.Z
NP.X = FX[1]-X; NP.Y = FY[1]-Y; NP.Z = FZ[1]-Z
NP.Normalize()
NP.X = NP.X * NCam.Far*ShadowDistance; NP.Y = NP.Y * NCam.Far*ShadowDistance; NP.Z = NP.Z * NCam.Far*ShadowDistance
BX[1] = NP.X; BY[1] = NP.Y; BZ[1] = NP.Z
NP.X = FX[2]-X; NP.Y = FY[2]-Y; NP.Z = FZ[2]-Z
NP.Normalize()
NP.X = NP.X * NCam.Far*ShadowDistance; NP.Y = NP.Y * NCam.Far*ShadowDistance; NP.Z = NP.Z * NCam.Far*ShadowDistance
BX[2] = NP.X; BY[2] = NP.Y; BZ[2] = NP.Z
Rem
glBegin(GL_TRIANGLES)
glVertex3f(FX[2],FY[2],FZ[2])
glVertex3f(FX[1],FY[1],FZ[1])
glVertex3f(FX[0],FY[0],FZ[0])
glVertex3f(BX[2],BY[2],BZ[2])
glVertex3f(BX[1],BY[1],BZ[1])
glVertex3f(BX[0],BY[0],BZ[0])
glEnd()
glBegin(GL_QUADS)
glVertex3f(BX[0],BY[0],BZ[0])
glVertex3f(BX[1],BY[1],BZ[1])
glVertex3f(FX[1],FY[1],FZ[1])
glVertex3f(FX[0],FY[0],FZ[0])
glVertex3f(BX[1],BY[1],BZ[1])
glVertex3f(BX[2],BY[2],BZ[2])
glVertex3f(FX[2],FY[2],FZ[2])
glVertex3f(FX[1],FY[1],FZ[1])
glVertex3f(BX[2],BY[2],BZ[2])
glVertex3f(BX[0],BY[0],BZ[0])
glVertex3f(FX[0],FY[0],FZ[0])
glVertex3f(FX[2],FY[2],FZ[2])
glEnd()
End Rem
glBegin(GL_TRIANGLES)
glVertex3f(FX[0],FY[0],FZ[0])
glVertex3f(FX[1],FY[1],FZ[1])
glVertex3f(FX[2],FY[2],FZ[2])
glEnd()
glBegin(GL_TRIANGLES)
glVertex3f(BX[0],BY[0],BZ[0])
glVertex3f(BX[1],BY[1],BZ[1])
glVertex3f(BX[2],BY[2],BZ[2])
glEnd()
glBegin(GL_QUADS)
glVertex3f(FX[0],FY[0],FZ[0])
glVertex3f(FX[1],FY[1],FZ[1])
glVertex3f(BX[1],BY[1],BZ[1])
glVertex3f(BX[0],BY[0],BZ[0])
glEnd()
glBegin(GL_QUADS)
glVertex3f(FX[1],FY[1],FZ[1])
glVertex3f(FX[2],FY[2],FZ[2])
glVertex3f(BX[2],BY[2],BZ[2])
glVertex3f(BX[1],BY[1],BZ[1])
glEnd()
glBegin(GL_QUADS)
glVertex3f(FX[2],FY[2],FZ[2])
glVertex3f(FX[0],FY[0],FZ[0])
glVertex3f(BX[0],BY[0],BZ[0])
glVertex3f(BX[2],BY[2],BZ[2])
glEnd()
Next
EndIf
Next
End Method
Method DrawShadow()
glPushMatrix()
glLoadIdentity()
glMatrixMode(GL_PROJECTION)
glPushMatrix()
glLoadIdentity()
glOrtho(0, 1, 1, 0, 0, 1)
glDisable(GL_DEPTH_TEST)
glColor4f(0.0, 0.0, 0.0, 1.0)
glBegin(GL_QUADS)
glVertex2i(0, 0)
glVertex2i(0, 1)
glVertex2i(1, 1)
glVertex2i(1, 0)
glEnd()
glEnable(GL_DEPTH_TEST)
glPopMatrix()
glMatrixMode(GL_MODELVIEW)
glPopMatrix()
End Method
Method DrawTri()
glPushMatrix()
glLoadIdentity()
glMatrixMode(GL_PROJECTION)
glPushMatrix()
glLoadIdentity()
glOrtho(0, 1, 1, 0, 0, 1)
glDisable(GL_DEPTH_TEST)
glColor4f(0.0, 0.0, 0.0, 1.0)
glBegin(GL_QUADS)
glVertex2i(0, 0)
glVertex2i(0, 0.1)
glVertex2i(0.1, 0.1)
glVertex2i(0.1, 0)
glEnd()
glEnable(GL_DEPTH_TEST)
glPopMatrix()
glMatrixMode(GL_MODELVIEW)
glPopMatrix()
End Method
Method RenderEntity(NEnt:NEntity,NCam:NCamera)
If NEnt.Alpha>0.0 And NEnt.CamDistance<NCam.Far Then
'Shader
If NEnt.Sha = Null Then
If CurrentProgramObject <> 0 Then
CurrentProgramObject = 0
glUseProgramObjectARB(0)
glDisable(GL_VERTEX_PROGRAM_ARB)
glDisable(GL_FRAGMENT_PROGRAM_ARB)
EndIf
Else
If CurrentProgramObject <> NEnt.Sha.ProgramObject Then
CurrentProgramObject = NEnt.Sha.ProgramObject
If Not NEnt.ShaderEnabled Then CurrentProgramObject = 0
glUseProgramObjectARB(CurrentProgramObject)
If CurrentProgramObject <> 0 Then
glEnable(GL_VERTEX_PROGRAM_ARB)
glEnable(GL_FRAGMENT_PROGRAM_ARB)
Else
glDisable(GL_VERTEX_PROGRAM_ARB)
glDisable(GL_FRAGMENT_PROGRAM_ARB)
EndIf
EndIf
EndIf
'Texture
If TextureEnabled<> NEnt.TextureEnabled Then
TextureEnabled = NEnt.TextureEnabled
If TextureEnabled Then
glEnable(GL_TEXTURE_2D)
Else
glDisable(GL_TEXTURE_2D)
EndIf
EndIf
If CurrentTexture<>NEnt.Texture And NEnt.TextureEnabled Then
CurrentTexture = NEnt.Texture
glBindTexture (GL_TEXTURE_2D, CurrentTexture)
EndIf
If WireframeEnabled <> NEnt.WireFrame Then
WireframeEnabled = NEnt.WireFrame
If WireframeEnabled Then
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
Else
glPolygonMode(GL_FRONT, GL_FILL)
EndIf
EndIf
If AlphaEnabled <> NEnt.AlphaEnabled Then
AlphaEnabled = NEnt.AlphaEnabled
If AlphaEnabled Then
glEnable(GL_BLEND)
Else
glDisable(GL_BLEND)
EndIf
EndIf
If NEnt.Blend And (AlphaEnabled = 0) Then
AlphaEnabled = 1
glEnable(GL_BLEND)
EndIf
glPushMatrix()
glTranslatef(NEnt.X,NEnt.Y,NEnt.Z)
glRotatef(NEnt.Pitch,1.0,0,0)
glRotatef(NEnt.Yaw,0,1.0,0)
glRotatef(NEnt.Roll,0,0,1.0)
If NEnt.DisplayListCreated[NEnt.Frame] Then
'glEnableClientState(GL_VERTEX_ARRAY)
'glEnableClientState(GL_TEXTURE_COORD_ARRAY)
'glBindBufferARB( GL_ARRAY_BUFFER_ARB, NEnt.VertexVBO[NEnt.Frame] )
'glVertexPointer( 3, GL_FLOAT, 0, Null)
'
'glBindBufferARB( GL_ARRAY_BUFFER_ARB, NEnt.UvVBO[NEnt.Frame] )
'glTexCoordPointer( 2, GL_FLOAT, 0, Null)
'glDrawArrays(GL_TRIANGLES,0, NEnt.VertexArrayLength[NEnt.Frame])
'glDisableClientState(GL_VERTEX_ARRAY)
'glDisableClientState(GL_TEXTURE_COORD_ARRAY)
glCallList(NEnt.DisplayList[NEnt.Frame])
Else
RuntimeError "Display list not created!"
EndIf
Triangles = Triangles+NEnt.Triangles/NEnt.Frames
For Local Chi:NEntity = EachIn NEnt.ChildList
RenderEntity(Chi,NCam)
Next
glPopMatrix()
EndIf
End Method
Method Swap(VWait:Int=1)
Flip VWait
End Method
Method Clear()
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
End Method
Method ClsColor(R:Int,G:Int,B:Int)
If R>255 Then R=255
If G>255 Then G=255
If B>255 Then B=255
If R<0 Then R=0
If G<0 Then G=0
If B<0 Then B=0
glClearColor(R/255.0,G/255.0,B/255.0,0.0)
End Method
Method New()
NGraphics.Gfx = Self
ShadowList = CreateList()
End Method
Function Start:NGraphics(NewWidth:Int=800,NewHeight:Int=600,NewDepth:Int=32,NewScreen:Int=0)
Local Gfx:NGraphics = New NGraphics
Gfx.Width = NewWidth
Gfx.Height = NewHeight
Gfx.Depth = NewDepth
Gfx.Fullscreen = NewScreen
Local Flags:Int = GRAPHICS_BACKBUFFER|GRAPHICS_DEPTHBUFFER|GRAPHICS_STENCILBUFFER
If NewScreen = 0 Then Gfx.Depth = 0
GLGraphics(Gfx.Width,Gfx.Height,Gfx.Depth,0,Flags)
GlewInit()
glViewport(0,0,Gfx.Width,Gfx.Height)
glShadeModel(GL_SMOOTH)
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST
glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST
glClearColor(0,0,0, 0.0)
glColor3f(1.0, 1.0, 1.0)
glClearDepth(1.0)
glEnable(GL_CULL_FACE)
'glEnable(GL_BLEND)
glEnable(GL_DEPTH_TEST)
glDepthFunc(GL_LEQUAL)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(45.0, Float(Gfx.Width)/Float(Gfx.Height), 0.1, 1000.0)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
'glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
Gfx.FPSTimer = MilliSecs()
Gfx.FPS = 1
If NEntity.NEntityList = Null Then NEntity.NEntityList = CreateList()
If NParticleEmitter.NParticleEmitterList = Null Then NParticleEmitter.NParticleEmitterList = CreateList()
Return Gfx
End Function
End Type
Type NEntity Extends NPoint
Field Name:String
Field Pitch:Float
Field Yaw:Float
Field Roll:Float
Field Alpha:Float
Field NTriangleList:TList[512]
Field NVertexList:TList[512]
Field Frame:Int
Field Frames:Int
Field FrameTime:Int
Field FrameTimer:Int
Field ScaleX:Float,ScaleY:Float,ScaleZ:Float
Field TextureEnabled:Int
Field TextureWidth:Int,TextureHeight:Int
Field Texture:Int
Field WireFrame:Int
Field CamDistance:Float
Field Triangles:Int
Field DisplayList:Int[512],DisplayListCreated:Int[512]
Field AlphaEnabled:Int
Field CreateDList:Int
Field ColX:Float,ColY:Float,ColZ:Float
Field ColWidth:Float,ColHeight:Float,ColDepth:Float
Field Sha:NShader
Field ShaderEnabled:Int
Field Parent:NEntity
Field ChildList:TList
Field EntityType:Int
Field Blend:Int
Field RenderFirst:Int
Field Shadows:Int
'VBO
Field VertexVBO:Int[512],UvVBO:Int[512]
Field VertexArray:Float[512,0]
Field UvArray:Float[512,0]
Field VertexArrayLength:Int[512]
Global NEntityList:TList
'Partly done Vertex Buffer Objects.. My benchmark shows them to be slower than display lists when using models with
'few thousands triangles..
Method CreateDisplayList_()
Print "Creating display lists"
Local Vertices:Int = NTriangleList[Frame].Count()*9,VertexC:Int=0,UVC:Int=0
VertexArray = New Float[1,Vertices]
UvArray = New Float[1,Vertices]
For Local Fr:Int = 0 To Frames-1
DisplayListCreated[Fr] = 1
VertexArrayLength[Fr] = Vertices/3
VertexC=0; UVC=0
Triangles=0
For Local NTri:NTriangle = EachIn NTriangleList[Fr]
Triangles:+1
VertexArray[Fr,VertexC] = NTri.V1.X
VertexArray[Fr,VertexC+1] = NTri.V1.Y
VertexArray[Fr,VertexC+2] = NTri.V1.Z
VertexArray[Fr,VertexC+3] = NTri.V2.X
VertexArray[Fr,VertexC+4] = NTri.V2.Y
VertexArray[Fr,VertexC+5] = NTri.V2.Z
VertexArray[Fr,VertexC+6] = NTri.V3.X
VertexArray[Fr,VertexC+7] = NTri.V3.Y
VertexArray[Fr,VertexC+8] = NTri.V3.Z
UvArray[Fr,UVC] = NTri.V1s
UvArray[Fr,UVC+1] = NTri.V1t
UvArray[Fr,UVC+2] = NTri.V2s
UvArray[Fr,UVC+3] = NTri.V2t
UvArray[Fr,UVC+4] = NTri.V3s
UvArray[Fr,UVC+5] = NTri.V3t
VertexC:+9
UVC:+6
Next
Next
Local TempVertex:Float[Vertices],TempUv:Float[Vertices]
For Local a:Int = 0 To Vertices-1
TempVertex[a] = VertexArray[Frame,a]
TempUv[a] = UvArray[Frame,a]
Next
glGenBuffersARB(1, Varptr(VertexVBO[Frame])) 'Get A Valid Name
glBindBufferARB( GL_ARRAY_BUFFER_ARB, VertexVBO[Frame] ) 'Bind The Buffer
glBufferDataARB( GL_ARRAY_BUFFER_ARB, SizeOf(TempVertex), TempVertex, GL_STATIC_DRAW_ARB )
glGenBuffersARB( 1, Varptr(UvVBO[Frame]) )
glBindBufferARB( GL_ARRAY_BUFFER_ARB, UvVBO[Frame] )
glBufferDataARB( GL_ARRAY_BUFFER_ARB, SizeOf(TempUv), TempUv, GL_STATIC_DRAW_ARB )
End Method
Method AttachShader(NewSha:NShader)
Sha = NewSha
ShaderEnabled = 1
End Method
Method CreateDisplayList()
AlphaEnabled = 0
Local CAlpha:Float,OptimizeColors:Int=0,Stepper:Int=0
For Local a:Int = 0 To Frames-1
If DisplayListCreated[a] = 1 Then glDeleteLists(DisplayList[a],1)
DisplayListCreated[a] = 1
DisplayList[a] = glGenLists(1)
glNewList(DisplayList[a], GL_COMPILE)
glBegin(GL_TRIANGLES)
For Local NTri:NTriangle = EachIn NTriangleList[a]
'If Stepper=0 Then glBegin(GL_TRIANGLES)
'Stepper:+1
If Alpha*(NTri.V1.Alpha+NTri.V2.Alpha+NTri.V3.Alpha) < 3.0 Then AlphaEnabled = 1
If NTri.V1.R+NTri.V1.G+NTri.V1.B+NTri.V2.R+NTri.V2.G+NTri.V2.B+NTri.V3.R+NTri.V3.G+NTri.V3.B=9.0 Then OptimizeColors=1
' glBegin(GL_TRIANGLES)
If TextureEnabled Then
glTexCoord2f (NTri.V1s,NTri.V1t)
If NTri.V1NX<>0.0 Or NTri.V1NY<>0.0 Or NTri.V1NZ<>0.0 glNormal3f(NTri.V1NX,NTri.V1NY,NTri.V1NZ)
EndIf
CAlpha = Alpha*NTri.V1.Alpha
If (CAlpha) <> 1.0 Then
glColor4f(NTri.V1.R,NTri.V1.G,NTri.V1.B,CAlpha)
Else
glColor3f(NTri.V1.R,NTri.V1.G,NTri.V1.B)
EndIf
glVertex3f(NTri.V1.X,NTri.V1.Y,NTri.V1.Z)
If TextureEnabled Then
glTexCoord2f (NTri.V2s,NTri.V2t)
If NTri.V2NX<>0.0 Or NTri.V2NY<>0.0 Or NTri.V2NZ<>0.0 glNormal3f(NTri.V2NX,NTri.V2NY,NTri.V2NZ)
EndIf
CAlpha = Alpha*NTri.V2.Alpha
If (CAlpha) <> 1.0 Then
glColor4f(NTri.V2.R,NTri.V2.G,NTri.V2.B,CAlpha)
ElseIf Not OptimizeColors
glColor3f(NTri.V2.R,NTri.V2.G,NTri.V2.B)
EndIf
glVertex3f(NTri.V2.X,NTri.V2.Y,NTri.V2.Z)
If TextureEnabled Then
glTexCoord2f (NTri.V3s,NTri.V3t)
If NTri.V3NX<>0.0 Or NTri.V3NY<>0.0 Or NTri.V3NZ<>0.0 glNormal3f(NTri.V3NX,NTri.V3NY,NTri.V3NZ)
EndIf
CAlpha = Alpha*NTri.V3.Alpha
If (CAlpha) <> 1.0 Then
glColor4f(NTri.V3.R,NTri.V3.G,NTri.V3.B,CAlpha)
ElseIf Not OptimizeColors
glColor3f(NTri.V3.R,NTri.V3.G,NTri.V3.B)
EndIf
glVertex3f(NTri.V3.X,NTri.V3.Y,NTri.V3.Z)
'If Stepper = 10 Then
'glEnd()
' Stepper=0
' EndIf
Next
glEnd()
glEndList()
Next
End Method
Method Turn(NewPitch:Float,NewYaw:Float,NewRoll:Float)
Pitch = Pitch+NewPitch Mod 360.0
Yaw = Yaw+NewYaw Mod 360.0
Roll = Roll+NewRoll Mod 360.0
If Pitch<0.0 Then Pitch=Pitch+360.0
If Yaw<0.0 Then Yaw=Yaw+360.0
If Roll<0.0 Then Roll=Roll+360.0
If Pitch>360.0 Then Pitch=Pitch-360.0
If Yaw>360.0 Then Yaw=Yaw-360.0
If Roll>360.0 Then Roll=Roll-360.0
End Method
Method Rotate(NewPitch:Float,NewYaw:Float,NewRoll:Float)
Pitch = NewPitch Mod 360.0
Yaw = NewYaw Mod 360.0
Roll = NewRoll Mod 360.0
While Pitch<0.0
Pitch=Pitch+360.0
Wend
While Yaw<0.0
Yaw=Yaw+360.0
Wend
While Roll<0.0
Roll=Roll+360.0
Wend
While Pitch>360.0
Pitch = Pitch-360.0
Wend
While Yaw>360.0
Yaw = Yaw-360.0
Wend
While Roll>360.0
Roll = roll-360.0
Wend
End Method
Method Move(NewX:Float,NewY:Float,NewZ:Float)
Local MoveMat:TMatrix=New TMatrix
MoveMat.LoadIdentity()
MoveMat.RotateYaw(Yaw)
MoveMat.RotatePitch(Pitch)
MoveMat.RotateRoll(Roll)
MoveMat.Translate(NewX,NewY,-NewZ)
X = X+MoveMat.grid[3,0]
Y = Y+MoveMat.grid[3,1]
Z = Z+MoveMat.grid[3,2]
End Method
Method AddTriangle(V1:NVertex,V2:NVertex,V3:NVertex,V1s:Float=0,V1t:Float=0,V2s:Float=0,V2t:Float=0,V3s:Float=0,V3t:Float=0,V1n:Byte=0,V2n:Byte=0,V3n:Byte=0)
Local NewTri:NTriangle = New NTriangle
NewTri.V1 = V1
NewTri.V2 = V2
NewTri.V3 = V3
NewTri.V1s=V1s
NewTri.V1t=V1t
NewTri.V2s=V2s
NewTri.V2t=V2t
NewTri.V3s=V3s
NewTri.V3t=V3t
NewTri.V1NX = Anorms[V1n*3]
NewTri.V1NY = Anorms[V1n*3+1]
NewTri.V1NZ = Anorms[V1n*3+2]
NewTri.V2NX = Anorms[V2n*3]
NewTri.V2NY = Anorms[V2n*3+1]
NewTri.V2NZ = Anorms[V2n*3+2]
NewTri.V3NX = Anorms[V3n*3]
NewTri.V3NY = Anorms[V3n*3+1]
NewTri.V3NZ = Anorms[V3n*3+2]
ListAddLast(Self.NTriangleList[Self.Frame],NewTri)
ListAddLast(Self.NVertexList[Self.Frame],V1)
ListAddLast(Self.NVertexList[Self.Frame],V2)
ListAddLast(Self.NVertexList[Self.Frame],V3)
Triangles=Triangles+1
End Method
Method AddTri(V1X:Float,V1Y:Float,V1Z:Float,V2X:Float,V2Y:Float,V2Z:Float,V3X:Float,V3Y:Float,V3Z:Float,V1s:Float=0,V1t:Float=0,V2s:Float=0,V2t:Float=0,V3s:Float=0,V3t:Float=0,V1n:Byte=0,V2n:Byte=0,V3n:Byte=0)
Local NV1:NVertex = New NVertex
Local NV2:NVertex = New NVertex
Local NV3:NVertex = New NVertex
NV1.OrigX = V1X; NV1.OrigY = V1Y; NV1.OrigZ = V1Z
NV2.OrigX = V2X; NV2.OrigY = V2Y; NV2.OrigZ = V2Z
NV3.OrigX = V3X; NV3.OrigY = V3Y; NV3.OrigZ = V3Z
NV1.X = V1X
NV1.Y = V1Y
NV1.Z = V1Z
NV2.X = V2X
NV2.Y = V2Y
NV2.Z = V2Z
NV3.X = V3X
NV3.Y = V3Y
NV3.Z = V3Z
Self.AddTriangle(NV1,NV2,NV3,V1s,V1t,V2s,V2t,V3s,V3t,V1n,V2n,V3n)
End Method
Method LoadTexture(Filename:String)
If TextureEnabled = False Then
If FileType(Filename)=0 Then RuntimeError Filename+" not found!"
Local TXMap:TPixmap = LoadPixmap(Filename)
If Not TXMap Then RuntimeError "Could not load texture!"
Texture = GLTexFromPixmap(TXMap)
If Not Texture Then RuntimeError "Could not load texture to memory!"
TextureEnabled = True
TextureWidth = TXMap.Width
TextureHeight = TXMap.Height
EndIf
CreateDList = 1
End Method
Method FreeTexture()
If NEntity.TextureUseCount(Texture) = 1 Then glDeleteTextures(1,Varptr(Texture))
End Method
Method ScaleMesh(NewScaleX:Float,NewScaleY:Float,NewScaleZ:Float)
For Local Fr:Int = 0 To Frames-1
For Local NVer:NVertex = EachIn NVertexList[Fr]
NVer.X = NVer.X*NewScaleX
NVer.Y = NVer.Y*NewScaleY
NVer.Z = NVer.Z*NewScaleZ
NVer.OrigX = NVer.X
NVer.OrigY = NVer.Y
NVer.OrigZ = NVer.Z
Next
Next
CreateDList = 1
End Method
Method MoveMesh(NewX:Float,NewY:Float,NewZ:Float)
For Local Fr:Int = 0 To Frames-1
For Local NVer:NVertex = EachIn NVertexList[Fr]
NVer.X = NVer.X+NewX
NVer.Y = NVer.Y+NewY
NVer.Z = NVer.Z+NewZ
Next
Next
CreateDList = 1
End Method
Method FreeEntity()
For Local Fr:Int = 0 To Frames-1
If NEntity.ListUseCount(DisplayList[Fr]) = 1 Then glDeleteLists(DisplayList[Fr],1)
Next
FreeTexture()
ListRemove(NEntityList,Self)
End Method
Method AddMesh(NEnt:NEntity)
Print "Adding mesh"
For Local NTri:NTriangle = EachIn NEnt.NTriangleList[NEnt.Frame]
Local NewTri:NTriangle = New NTriangle
NewTri.V1s = NTri.V1s; NewTri.V1t = NTri.V1t
NewTri.V2s = NTri.V2s; NewTri.V2t = NTri.V2t
NewTri.V3s = NTri.V3s; NewTri.V3t = NTri.V3t
NewTri.V1NX = NTri.V1NX; NewTri.V1NY = NTri.V1NY; NewTri.V1NZ = NTri.V1NZ
NewTri.V2NX = NTri.V2NX; NewTri.V2NY = NTri.V2NY; NewTri.V2NZ = NTri.V2NZ
NewTri.V3NX = NTri.V3NX; NewTri.V3NY = NTri.V3NY; NewTri.V3NZ = NTri.V3NZ
NewTri.V1 = New NVertex; NewTri.V2 = New NVertex; NewTri.V3 = New NVertex
NewTri.V1.X = NTri.V1.X
NewTri.V1.Y = NTri.V1.Y
NewTri.V1.Z = NTri.V1.Z
NewTri.V2.X = NTri.V2.X
NewTri.V2.Y = NTri.V2.Y
NewTri.V2.Z = NTri.V2.Z
NewTri.V3.X = NTri.V3.X; NewTri.V3.Y = NTri.V3.Y; NewTri.V3.Z = NTri.V3.Z
NewTri.V1.OrigX = NTri.V1.OrigX; NewTri.V1.OrigY = NTri.V1.OrigY; NewTri.V1.OrigZ = NTri.V1.OrigZ
NewTri.V2.OrigX = NTri.V2.OrigX; NewTri.V2.OrigY = NTri.V2.OrigY; NewTri.V2.OrigZ = NTri.V2.OrigZ
NewTri.V3.OrigX = NTri.V3.OrigX; NewTri.V3.OrigY = NTri.V3.OrigY; NewTri.V3.OrigZ = NTri.V3.OrigZ
NewTri.V1.Alpha = NTri.V1.Alpha; NewTri.V2.Alpha = NTri.V2.Alpha; NewTri.V3.Alpha = NTri.V3.Alpha
NewTri.V1.R = NTri.V1.R; NewTri.V1.G = NTri.V1.G; NewTri.V1.B = NTri.V1.B
NewTri.V2.R = NTri.V2.R; NewTri.V2.G = NTri.V2.G; NewTri.V2.B = NTri.V2.B
NewTri.V3.R = NTri.V3.R; NewTri.V3.G = NTri.V3.G; NewTri.V3.B = NTri.V3.B
ListAddLast(Self.NTriangleList[Self.Frame],NewTri)
ListAddLast(Self.NVertexList[Self.Frame],NewTri.V1)
ListAddLast(Self.NVertexList[Self.Frame],NewTri.V2)
ListAddLast(Self.NVertexList[Self.Frame],NewTri.V3)
Next
CreateDList = 1
End Method
Method FlipMesh()
Local HoldFloat:Float,HoldVertex:NVertex
For Local Fr:Int = 0 To Frames-1
For Local NTri:NTriangle = EachIn NTriangleList[Fr]
HoldVertex = NTri.V1
NTri.V1 = NTri.V3
NTri.V3 = HoldVertex
HoldFloat = NTri.V1s
NTri.V1s = NTri.V3s
NTri.v3s = HoldFloat
HoldFloat= NTri.V1t
NTri.V1t = NTri.V3t
NTri.V3t = HoldFloat
HoldFloat = NTri.V1NX
NTri.V1NX = NTri.V3NX
NTri.V3NX = HoldFloat
HoldFloat = NTri.V1NY
NTri.V1NY = NTri.V3NY
NTri.V3NY = HoldFloat
HoldFloat = NTri.V1NZ
NTri.V1NZ = NTri.V3NZ
NTri.V3NZ = HoldFloat
Next
Next
CreateDList = 1
End Method
Method TurnMesh(NewPitch:Float,NewYaw:Float,NewRoll:Float)
For Local Fr:Int = 0 To Frames-1
For Local NVer:NVertex = EachIn NVertexList[Fr]
Local OldX:Float = NVer.X
Local OldY:Float = NVer.Y
Local OldZ:Float = NVer.Z
NVer.Y = (OldY*Cos(NewPitch)) - (OldZ*Sin(NewPitch))
NVer.Z = (OldZ*Cos(NewPitch)) + (OldY*Sin(NewPitch))
OldY = NVer.Y
OldZ = NVer.Z
NVer.Z = (OldZ*Cos(NewYaw)) - (OldX*Sin(NewYaw))
NVer.X = (OldX*Cos(NewYaw)) + (OldZ*Sin(NewYaw))
OldZ = NVer.Z
OldX = NVer.X
NVer.X = (OldX*Cos(NewRoll)) - (OldY*Sin(NewRoll))
NVer.Y = (OldY*Cos(NewRoll)) + (OldX*Sin(NewRoll))
Next
Next
CreateDList = 1
End Method
Method ScaleEntity(NewScaleX:Float,NewScaleY:Float,NewScaleZ:Float)
ScaleX = ScaleX * NewScaleX
ScaleY = ScaleY * NewScaleY
ScaleZ = ScaleZ * NewScaleZ
For Local Fr:Int = 0 To Frames-1
For Local NVer:NVertex = EachIn NVertexList[Fr]
NVer.X = NVer.OrigX*ScaleX
NVer.Y = NVer.OrigY*ScaleY
NVer.Z = NVer.OrigZ*ScaleZ
Next
Next
CreateDList = 1
End Method
Method Animate()
If MilliSecs()>FrameTimer+FrameTime Then
FrameTimer = MilliSecs()
Frame=Frame+1
If Frame>=Frames Then Frame=0
EndIf
End Method
Method Free()
ListRemove(NEntity.NEntityList,Self)
End Method
Method EntityParent(NewParent:NEntity)
If NewParent <> Null Then
Parent = NewParent
ListAddLast(Parent.ChildList,Self)
Else
If Parent <> Null Then
ListRemove(Parent.ChildList,Self)
Parent = Null
EndIf
EndIf
End Method
Method New()
For Local a:Int = 0 To 511
NTriangleList[a] = CreateList()
NVertexList[a] = CreateList()
Next
ChildList = CreateList()
ListAddLast(NEntity.NEntityList,Self)
Alpha = 1.0
Frames = 1
ScaleX = 1.0
ScaleY = 1.0
ScaleZ = 1.0
FrameTimer = MilliSecs()
FrameTime = 1
End Method
Method EntityColor(NewR:Int,NewG:Int,NewB:Int)
For Local Fr:Int = 0 To Frames-1
For Local NVer:NVertex = EachIn NVertexList[Fr]
NVer.R = NewR/255.0
NVer.G = NewG/255.0
NVer.B = NewB/255.0
Next
Next
CreateDList = 1
End Method
Method EntityAlpha(NewAlpha:Float)
Alpha = NewAlpha
CreateDList = 1
End Method
Method Interpolate()
If Frames>1 Then
For Local a:Int = 0 To Frames-1
Local TriCount:Int=0
For Local NTri:NTriangle = EachIn NTriangleList[a]
TriCount:+1
Local NTri2:NTriangle = New NTriangle
NTri2.V1s=NTri.V1s; NTri2.V1t=NTri.V1t
NTri2.V2s=NTri.V2s; NTri2.V2t=NTri.V2t
NTri2.V3s=NTri.V3s; NTri2.V3t=NTri.V3t
NTri2.V1NX = NTri.V1NX; NTri2.V1NY = NTri.V1NY; NTri2.V1NZ = NTri.V1NZ
NTri2.V2NX = NTri.V2NX; NTri2.V2NY = NTri.V2NY; NTri2.V2NZ = NTri.V2NZ
NTri2.V3NX = NTri.V3NX; NTri2.V3NY = NTri.V3NY; NTri2.V3NZ = NTri.V3NZ
NTri2.V1 = New NVertex; NTri2.V2 = New NVertex; NTri2.V3 = New NVertex
NTri2.V1.R = NTri.V1.R; NTri2.V1.G = NTri.V1.G; NTri2.V1.B = NTri.V1.B; NTri2.V1.Alpha = NTri.V1.Alpha
NTri2.V2.R = NTri.V2.R; NTri2.V2.G = NTri.V2.G; NTri2.V2.B = NTri.V2.B; NTri2.V2.Alpha = NTri.V2.Alpha
NTri2.V3.R = NTri.V3.R; NTri2.V3.G = NTri.V3.G; NTri2.V3.B = NTri.V3.B; NTri2.V3.Alpha = NTri.V3.Alpha
NTri2.V1.X = (NTri.V1.X+GetTriangle(TriCount,NextFrame(a)).V1.X)*0.5
NTri2.V1.Y = (NTri.V1.Y+GetTriangle(TriCount,NextFrame(a)).V1.Y)*0.5
NTri2.V1.Z = (NTri.V1.Z+GetTriangle(TriCount,NextFrame(a)).V1.Z)*0.5
NTri2.V2.X = (NTri.V2.X+GetTriangle(TriCount,NextFrame(a)).V2.X)*0.5
NTri2.V2.Y = (NTri.V2.Y+GetTriangle(TriCount,NextFrame(a)).V2.Y)*0.5
NTri2.V2.Z = (NTri.V2.Z+GetTriangle(TriCount,NextFrame(a)).V2.Z)*0.5
NTri2.V3.X = (NTri.V3.X+GetTriangle(TriCount,NextFrame(a)).V3.X)*0.5
NTri2.V3.Y = (NTri.V3.Y+GetTriangle(TriCount,NextFrame(a)).V3.Y)*0.5
NTri2.V3.Z = (NTri.V3.Z+GetTriangle(TriCount,NextFrame(a)).V3.Z)*0.5
ListAddLast(NTriangleList[Frames+a],NTri2)
Next
Next
For Local a:Int = 1 To Frames*2-1
Next
Frames:*2
EndIf
End Method
Method NextFrame:Int(Fr:Int)
If Fr+1 >= Frames Then Return 0
Return Fr+1
End Method
Method Intersect:Int(NEnt:NEntity)
Local linept:NPoint = New NPoint,vect:NPoint = New NPoint,V1:NPoint = New NPoint,V2:NPoint = New NPoint,V3:NPoint = New NPoint
If NEnt = Self Then Return False
For Local NTri:NTriangle = EachIn NTriangleList[Frame]
For Local NTri2:NTriangle = EachIn NEnt.NTriangleList[NEnt.Frame]
V1.X = NTri2.V1.X+NEnt.X; V1.Y = NTri2.V1.Y+NEnt.Y; V1.Z = NTri2.V1.Z+NEnt.Z
V2.X = NTri2.V2.X+NEnt.X; V2.Y = NTri2.V2.Y+NEnt.Y; V2.Z = NTri2.V2.Z+NEnt.Z
V3.X = NTri2.V3.X+NEnt.X; V3.Y = NTri2.V3.Y+NEnt.Y; V3.Z = NTri2.V3.Z+NEnt.Z
linept.X = NTri.V1.X+X; linept.Y = NTri.V1.Y+Y; linept.Z = NTri.V1.Z+Z
vect.X = NTri.V2.X-NTri.V1.X
vect.Y = NTri.V2.Y-NTri.V1.Y
vect.Z = NTri.V2.Z-NTri.V1.Z
If LineIntersectsTriangle(V1,V2,V3,linept,vect) Then Return True
linept.X = NTri.V2.X+X; linept.Y = NTri.V2.Y+Y; linept.Z = NTri.V2.Z+Z
vect.X = NTri.V3.X-NTri.V2.X
vect.Y = NTri.V3.Y-NTri.V2.Y
vect.Z = NTri.V3.Z-NTri.V2.Z
If LineIntersectsTriangle(V1,V2,V3,linept,vect) Then Return True
linept.X = NTri.V3.X+X; linept.Y = NTri.V3.Y+Y; linept.Z = NTri.V3.Z+Z
vect.X = NTri.V1.X-NTri.V3.X
vect.Y = NTri.V1.Y-NTri.V3.Y
vect.Z = NTri.V1.Z-NTri.V3.Z
If LineIntersectsTriangle(V1,V2,V3,linept,vect) Then Return True
Next
Next
Return False
End Method
Method CopyEntity:NEntity()
CreateDisplayList(); CreateDList = 0
Local NEnt2:NEntity = New NEntity
NEnt2.Name = Self.Name
NEnt2.Alpha = Self.Alpha
NEnt2.Frame = Self.Frame
NEnt2.Frames = Self.Frames
NEnt2.FrameTime = Self.FrameTime
NEnt2.FrameTimer = Self.FrameTimer
NEnt2.ScaleX = Self.ScaleX
NEnt2.ScaleY = Self.ScaleY
NEnt2.ScaleZ = Self.ScaleZ
NEnt2.TextureEnabled = Self.TextureEnabled
NEnt2.TextureWidth = Self.TextureWidth
NEnt2.TextureHeight = Self.TextureHeight
NEnt2.Texture = Self.Texture
NEnt2.AlphaEnabled = Self.AlphaEnabled
NEnt2.VertexVBO = Self.VertexVBO
NEnt2.UvVBO = Self.UvVBO
NEnt2.VertexArray = Self.VertexArray
NEnt2.VertexArrayLength = Self.VertexArrayLength
NEnt2.UvArray = Self.UvArray
NEnt2.CreateDList = Self.CreateDList
NEnt2.Sha = Self.Sha
NEnt2.ShaderEnabled = Self.ShaderEnabled
NEnt2.EntityType = Self.EntityType
NEnt2.Blend = Self.Blend
NEnt2.RenderFirst = Self.RenderFirst
NEnt2.Shadows = Self.Shadows
For Local a:Int = 0 To Self.Frames-1
NEnt2.DisplayListCreated[a] = Self.DisplayListCreated[a]
NEnt2.DisplayList[a] = Self.DisplayList[a]
For Local NTri:NTriangle = EachIn Self.NTriangleList[a]
Local NTri2:NTriangle = New NTriangle
NEnt2.Triangles:+1
NTri2.V1s = NTri.V1s; NTri2.V1t = NTri.V1t
NTri2.V2s = NTri.V2s; NTri2.V2t = NTri.V2t
NTri2.V3s = NTri.V3s; NTri2.V3t = NTri.V3t
NTri2.V1NX = NTri.V1NX; NTri2.V1NY = NTri.V1NY; NTri2.V1NZ = NTri.V1NZ
NTri2.V2NX = NTri.V2NX; NTri2.V2NY = NTri.V2NY; NTri2.V2NZ = NTri.V2NZ
NTri2.V3NX = NTri.V3NX; NTri2.V3NY = NTri.V3NY; NTri2.V3NZ = NTri.V3NZ
NTri2.V1 = New NVertex
NTri2.V2 = New NVertex
NTri2.V3 = New NVertex
NTri2.V1.OrigX = NTri.V1.OrigX; NTri2.V1.OrigY = NTri.V1.OrigY; NTri2.V1.OrigZ = NTri.V1.OrigZ
NTri2.V2.OrigX = NTri.V2.OrigX; NTri2.V2.OrigY = NTri.V2.OrigY; NTri2.V2.OrigZ = NTri.V2.OrigZ
NTri2.V3.OrigX = NTri.V3.OrigX; NTri2.V3.OrigY = NTri.V3.OrigY; NTri2.V3.OrigZ = NTri.V3.OrigZ
NTri2.V1.X = NTri.V1.X; NTri2.V1.Y = NTri.V1.Y; NTri2.V1.Z = NTri.V1.Z
NTri2.V2.X = NTri.V2.X; NTri2.V2.Y = NTri.V2.Y; NTri2.V2.Z = NTri.V2.Z
NTri2.V3.X = NTri.V3.X; NTri2.V3.Y = NTri.V3.Y; NTri2.V3.Z = NTri.V3.Z
NTri2.V1.R = NTri.V1.R; NTri2.V1.G = NTri.V1.G; NTri2.V1.B = NTri.V1.B
NTri2.V2.R = NTri.V2.R; NTri2.V2.G = NTri.V2.G; NTri2.V2.B = NTri.V2.B
NTri2.V3.R = NTri.V3.R; NTri2.V3.G = NTri.V3.G; NTri2.V3.B = NTri.V3.B
NTri2.V1.Alpha = NTri.V1.Alpha
NTri2.V2.Alpha = NTri.V2.Alpha
NTri2.V3.Alpha = NTri.V3.Alpha
ListAddLast(NEnt2.NTriangleList[NEnt2.Frame],NTri2)
ListAddLast(NEnt2.NVertexList[NEnt2.Frame],NTri2.V1)
ListAddLast(NEnt2.NVertexList[NEnt2.Frame],NTri2.V2)
ListAddLast(NEnt2.NVertexList[NEnt2.Frame],NTri2.V3)
Next
Next
Return NEnt2
End End Method
Method GetTriangle:NTriangle(TriCount:Int,Fr:Int)
Local TriCounter:Int=0
For Local NTri:NTriangle = EachIn NTriangleList[Fr]
TriCounter:+1
If TriCounter=TriCount Then Return NTri
Next
End Method
Function CreateCube:NEntity()
Local NEnt:NEntity = New NEntity
NEnt.AddTri(-1,1,1,-1,-1,1,1,1,1,0,0,0,1,1,0) 'FRONT TRI 1
NEnt.AddTri(-1,-1,1,1,-1,1,1,1,1,0,1,1,1,1,0) 'FRONT TRI2
NEnt.AddTri(1,1,1,1,-1,1,1,-1,-1,1,0,1,1,0,1) 'RIGHT TRI1
NEnt.AddTri(1,1,1,1,-1,-1,1,1,-1,1,0,0,1,0,0) 'RIGHT TRI2
NEnt.AddTri(1,1,-1,1,-1,-1,-1,-1,-1,0,0,0,1,1,1) 'BACK TRI1
NEnt.AddTri(1,1,-1,-1,-1,-1,-1,1,-1,0,0,1,1,1,0) 'BACK TRI2
NEnt.AddTri(-1,1,-1,-1,-1,-1,-1,-1,1,1,0,1,1,0,1) 'LEFT TRI1
NEnt.AddTri(-1,1,-1,-1,-1,1,-1,1,1,1,0,0,1,0,0) 'LEFT TRI2
NEnt.AddTri(-1,-1,1,-1,-1,-1,1,-1,-1,0,1,0,0,1,0 ) 'BOTTOM TRI1
NEnt.AddTri(-1,-1,1,1,-1,-1,1,-1,1,0,1,1,0,1,1) 'BOTTOM TRI2
NEnt.AddTri(1,1,-1,-1,1,-1,-1,1,1,1,1,0,1,0,0) 'TOP TRI1
NEnt.AddTri(1,1,1, 1,1,-1,-1,1,1,1,0,1,1,0,0 ) 'TOP TRI2
NEnt.CreateDList = 1
Return NEnt
End Function
Function CreateSprite:NEntity()
Local NEnt:NEntity = New NEntity
NEnt.AddTri(-1,1,1,-1,-1,1,1,1,1,0,0,0,1,1,0) 'FRONT TRI 1
NEnt.AddTri(-1,-1,1,1,-1,1,1,1,1,0,1,1,1,1,0) 'FRONT TRI2
NEnt.CreateDList = 1
Return NEnt
End Function
Function Heightmap:NEntity(Filename:String)
If FileType(Filename)=0 Then RuntimeError Filename+" not found!"
Local Pixmap:TPixmap = LoadPixmap(Filename)
If Not Pixmap Then RuntimeError "Could not load "+Filename
Local NEnt:NEntity = New NEntity,Pixel%,R:Int,G:Int,B:Int
Local HArray:Float[Pixmap.width,Pixmap.height]
For Local tX:Int = 0 To Pixmap.Width-1
For Local tY:Int = 0 To Pixmap.Height-1
Pixel = ReadPixel(Pixmap,tX,tY)
R = (Pixel% & $00FF0000) Shr 16
G = (Pixel% & $0000FF00) Shr 8
B = (Pixel% & $000000FF)
HArray[tX,tY] = Float(R+G+B)/3.0
Next
Next
For Local tX:Int = 0 To Pixmap.Width-2
For Local tY:Int = 0 To Pixmap.Height-2
NEnt.AddTri(tX,HArray[tX,tY+1]*0.1,tY+1,tX+1,HArray[tX+1,tY+1]*0.1,tY+1,tX,HArray[tX,tY]*0.1,tY,1,1,1,0,0,1)
NEnt.AddTri(tX+1,HArray[tX+1,tY+1]*0.1,tY+1,tX+1,HArray[tX+1,tY]*0.1,tY,tX,HArray[tX,tY]*0.1,tY,1,0,0,0,0,1)
Next
Next
NEnt.CreateDList = 1
Return NEnt
End Function
Function LoadMesh:NEntity(Filename:String)
Print "Loading "+Filename
If FileType(Filename)=0 Then
RuntimeError Filename+" not found!"
Return Null
EndIf
Local File:TStream = ReadFile(Filename)
Local Ident:Int = ReadInt(File)
If Ident <> 844121161 Then RuntimeError "MD2 identification number not found!"
Local NEnt:NEntity = New NEntity
Local Version:Int = ReadInt(File)
Print "Version: "+Version
Local SkinWidth:Int = ReadInt(File)
Local SkinHeight:Int = ReadInt(File)
NEnt.TextureWidth = SkinWidth
NEnt.TextureHeight = SkinHeight
Print NEnt.TextureWidth+"x"+Nent.TextureHeight
Local FrameSize:Int = ReadInt(File)
Local NumSkins:Int = ReadInt(File)
Print NumSkins+" skins"
Local NumVertices:Int = ReadInt(File)
Print NumVertices+" vertices"
Local NumSt:Int = ReadInt(File)
Local NumTris:Int = ReadInt(File)
Print NumTris+" triangles"
Local NumGlcmds:Int = ReadInt(File)
Local NumFrames:Int = ReadInt(File)
Print NumFrames+" frames"
NEnt.Frames = NumFrames
Local OffsetSkins:Int = ReadInt(File)
Local OffsetSt:Int = ReadInt(File)
Local OffsetTris:Int = ReadInt(File)
Local OffsetFrames:Int = ReadInt(File)
Local OffsetGlcmds:Int = ReadInt(File)
Local OffsetEnd:Int = ReadInt(File)
'Read skins
Local SkinName:String[32]
SeekStream File,OffsetSkins
For Local a:Int=1 To NumSkins
Local StopRead:Int=False
For Local b:Int=1 To 64
Local c:Int = ReadByte(File)
If c=0 Then StopRead = True
If Not StopRead Then SkinName[a-1]=SkinName[a-1]+Chr$(c)
Next
Print "skinname: "+SkinName[a-1]
Print Len(SkinName[a-1])
Next
If NumSkins>0 Then
Local TXMap:TPixmap = LoadPixmap(GetFolder(Filename)+SkinName[0])
Print GetFolder(Filename)+SkinName[0]
If Not TXMap Then RuntimeError "Could not load texture!"
NEnt.Texture = GLTexFromPixmap(TXMap)
If Not NEnt.Texture Then RuntimeError "Could not load texture to memory!"
NEnt.TextureEnabled = 1
EndIf
'Read texture coordinates
Local s:Int[2048],t:Int[2048]
SeekStream File,OffsetSt
Print "NumSt"+ NumSt
For Local a:Int=1 To NumSt
s[a-1] = ReadShort(File)
t[a-1] = ReadShort(File)
Next
'Read vertices
Local v:Byte[512,2048,3]
Local normalIndex:Byte[512,2048]
Local scalex:Float[512],scaley:Float[512],scalez:Float[512]
Local translatex:Float[512],translatey:Float[512],translatez:Float[512]
Local frameName:String[512]
SeekStream File,OffsetFrames
For Local a:Int=1 To NumFrames
scalex[a-1] = ReadFloat(File)
scaley[a-1] = ReadFloat(File)
scalez[a-1] = ReadFloat(File)
translatex[a-1] = ReadFloat(File)
translatey[a-1] = ReadFloat(File)
translatez[a-1] = ReadFloat(File)
Local StopRead:Int=False
For Local b:Int=0 To 15
Local c:Int = ReadByte(File)
If c=0 Then StopRead=True
If Not StopRead Then frameName[a-1] = frameName[a-1]+Chr$(c)
Next
'Read vertices
For Local c:Int = 0 To NumVertices-1
v[a-1,c,0] = ReadByte(File)
v[a-1,c,1] = ReadByte(File)
v[a-1,c,2] = ReadByte(File)
normalIndex[a-1,c] = ReadByte(File)
Next
Next
'Read triangles
Local vertex:Short[4096,3]
Local st:Short[4096,3]
SeekStream File,OffsetTris
For Local a:Int=1 To NumTris
For Local b:Int=0 To 2
vertex[a-1,b] = ReadShort(File)
Next
For Local b:Int=0 To 2
st[a-1,b] = ReadShort(File)
Next
For Local b:Int=0 To NumFrames-1
NEnt.Frame = b
Local V3X:Float = (Float(v[b,vertex[a-1,0],0])*scalex[b])+translatex[b]
Local V3Y:Float = (Float(v[b,vertex[a-1,0],1])*scaley[b])+translatey[b]
Local V3Z:Float = (Float(v[b,vertex[a-1,0],2])*scalez[b])+translatez[b]
Local V2X:Float = (Float(v[b,vertex[a-1,1],0])*scalex[b])+translatex[b]
Local V2Y:Float = (Float(v[b,vertex[a-1,1],1])*scaley[b])+translatey[b]
Local V2Z:Float = (Float(v[b,vertex[a-1,1],2])*scalez[b])+translatez[b]
Local V1X:Float = (Float(v[b,vertex[a-1,2],0])*scalex[b])+translatex[b]
Local V1Y:Float = (Float(v[b,vertex[a-1,2],1])*scaley[b])+translatey[b]
Local V1Z:Float = (Float(v[b,vertex[a-1,2],2])*scalez[b])+translatez[b]
Local V1s:Float=Float(s[st[a-1,2]])/Float(SkinWidth)
Local V1t:Float=Float(t[st[a-1,2]])/Float(SkinHeight)
Local V2s:Float=Float(s[st[a-1,1]])/Float(SkinWidth)
Local V2t:Float=Float(t[st[a-1,1]])/Float(SkinHeight)
Local V3s:Float=Float(s[st[a-1,0]])/Float(SkinWidth)
Local V3t:Float=Float(t[st[a-1,0]])/Float(SkinHeight)
Local V1n:Int=normalIndex[b,vertex[a-1,2]]
Local V2n:Int=normalIndex[b,vertex[a-1,1]]
Local V3n:Int=normalIndex[b,vertex[a-1,0]]
NEnt.AddTri(V1X,V1Y,V1Z,V2X,V2Y,V2Z,V3X,V3Y,V3Z,V1s,V1t,V2s,V2t,V3s,V3t,V1n,V2n,V3n)
Next
Next
NEnt.Frame = 0
CloseFile File
NEnt.CreateDList = 1
Return NEnt
End Function
Function ListUseCount:Int(DList:Int)
Local ListCounter:Int = 0
For Local NEnt:NEntity = EachIn NEntityList
For Local Fr:Int = 0 To NEnt.Frames-1
If NEnt.DisplayList[Fr] = DList Then ListCounter:+1
Next
Next
Return ListCounter
End Function
Function TextureUsecount:Int(Texture:Int)
Local TextCounter:Int = 0
For Local NEnt:NEntity = EachIn NEntityList
If NEnt.Texture = Texture Then TextCounter:+1
Next
End Function
Function CompareDistance:Int(o1:Object,o2:Object)
If NEntity(o1).CamDistance>NEntity(o2).CamDistance Return 1
Return 0
End Function
End Type
Type NCamera Extends NPoint
Field Enabled:Int
Field Pitch:Float
Field Yaw:Float
Field Roll:Float
Field Near:Float,Far:Float
Field ClsColor:Float[4]
Field Fog:Int,FogStart:Float,FogEnd:Float,FogColor:Float[3],FogDensity:Float
Global NCameraList:TList
Method EnableFog(NewFogStart:Float,NewFogEnd:Float,NewFogR:Int=128,NewFogG:Int=128,NewFogB:Int=128,NewFogDensity:Float=0.35)
Fog = 1
FogStart = NewFogStart; FogEnd = NewFogEnd
FogColor[0] = NewFogR/255.0; FogColor[1] = NewFogG/255.0; FogColor[2] = NewFogB/255.0
FogDensity = NewFogDensity
End Method
Method DisableFog()
Fog = 0
End Method
Method Turn(NewPitch:Float,NewYaw:Float,NewRoll:Float)
Pitch = Pitch+NewPitch Mod 360.0
Yaw = Yaw+NewYaw Mod 360.0
Roll = Roll+NewRoll Mod 360.0
If Pitch<0.0 Then Pitch=Pitch+360.0
If Yaw<0.0 Then Yaw=Yaw+360.0
If Roll<0.0 Then Roll=Roll+360.0
If Pitch>360.0 Then Pitch=Pitch-360.0
If Yaw>360.0 Then Yaw=Yaw-360.0
If Roll>360.0 Then Roll=Roll-360.0
End Method
Method SetClearColor(NewR:Int,NewG:Int,NewB:Int)
ClsColor[0] = NewR/255.0; ClsColor[1] = NewG/255.0; ClsColor[2] = NewB/255.0;
End Method
Method Rotate(NewPitch:Float,NewYaw:Float,NewRoll:Float)
Pitch = NewPitch Mod 360.0
Yaw = NewYaw Mod 360.0
Roll = NewRoll Mod 360.0
While Pitch<0.0
Pitch=Pitch+360.0
Wend
While Yaw<0.0
Yaw=Yaw+360.0
Wend
While Roll<0.0
Roll=Roll+360.0
Wend
While Pitch>360.0
Pitch = Pitch-360.0
Wend
While Yaw>360.0
Yaw = Yaw-360.0
Wend
While Roll>360.0
Roll = roll-360.0
Wend
End Method
Method Move(NewX:Float,NewY:Float,NewZ:Float)
Local MoveMat:TMatrix=New TMatrix
MoveMat.LoadIdentity()
MoveMat.RotateYaw(-Yaw)
MoveMat.RotatePitch(-Pitch)
MoveMat.RotateRoll(-Roll)
MoveMat.Translate(-NewX,-NewY,NewZ)
X = X+MoveMat.grid[3,0]
Y = Y+MoveMat.grid[3,1]
Z = Z+MoveMat.grid[3,2]
End Method
Method Translate(NewX:Float,NewY:Float,NewZ:Float)
X = X-NewX
Y = Y-NewY
Z = Z+NewZ
End Method
Method Position(NewX:Float,NewY:Float,NewZ:Float)
X = -NewX
Y = -NewY
Z = NewZ
End Method
Method New()
If NCamera.NCameraList = Null Then NCameraList = CreateList()
ListAddLast(NCamera.NCameraList,Self)
Enabled = True
Near = 0.1
Far = 1000.0
'Yaw = -180
End Method
Function CreateCamera:NCamera()
Local NCam:NCamera = New NCamera
Return NCam
End Function
End Type
Type NLight Extends NPoint
Field Pitch:Float
Field Yaw:Float
Field Roll:Float
Global NLightList:TList
Field AR:Int,AG:Int,AB:Int
Field DR:Int,DG:Int,DB:Int
Field GL_LIGHT:Int
Global Lights:Int
Method Ambient(NewAR:Int,NewAG:Int,NewAB:Int)
AR=NewAR
AG=NewAG
AB=NewAB
glLightfv(GL_LIGHT,GL_AMBIENT,[AR/255.0,AG/255.0,AB/255.0,1.0])
End Method
Method Diffuse(NewDR:Int,NewDG:Int,NewDB:Int)
DR=NewDR
DG=NewDG
DB=NewDB
glLightfv(GL_LIGHT,GL_DIFFUSE,[DR/255.0,DG/255.0,DB/255.0,1.0])
End Method
Method Turn(NewPitch:Float,NewYaw:Float,NewRoll:Float)
Pitch = Pitch+NewPitch Mod 360.0
Yaw = Yaw+NewYaw Mod 360.0
Roll = Roll+NewRoll Mod 360.0
If Pitch<0.0 Then Pitch=Pitch+360.0
If Yaw<0.0 Then Yaw=Yaw+360.0
If Roll<0.0 Then Roll=Roll+360.0
If Pitch>360.0 Then Pitch=Pitch-360.0
If Yaw>360.0 Then Yaw=Yaw-360.0
If Roll>360.0 Then Roll=Roll-360.0
End Method
Method Rotate(NewPitch:Float,NewYaw:Float,NewRoll:Float)
Pitch = NewPitch Mod 360.0
Yaw = NewYaw Mod 360.0
Roll = NewRoll Mod 360.0
While Pitch<0.0
Pitch=Pitch+360.0
Wend
While Yaw<0.0
Yaw=Yaw+360.0
Wend
While Roll<0.0
Roll=Roll+360.0
Wend
While Pitch>360.0
Pitch = Pitch-360.0
Wend
While Yaw>360.0
Yaw = Yaw-360.0
Wend
While Roll>360.0
Roll = roll-360.0
Wend
End Method
Method Move(NewX:Float,NewY:Float,NewZ:Float)
Local MoveMat:TMatrix=New TMatrix
MoveMat.LoadIdentity()
MoveMat.RotateYaw(Yaw)
MoveMat.RotatePitch(Pitch)
MoveMat.RotateRoll(Roll)
MoveMat.Translate(NewX,NewY,NewZ)
X = X+MoveMat.grid[3,0]
Y = Y+MoveMat.grid[3,1]
Z = Z+MoveMat.grid[3,2]
End Method
Method New()
NLight.Lights:+1
If NLight.Lights>GL_MAX_LIGHTS Then RuntimeError "Too many lights created!"
If NLight.Lights=1 Then GL_LIGHT = GL_LIGHT0
If NLight.Lights=2 Then GL_LIGHT = GL_LIGHT1
If NLight.Lights=3 Then GL_LIGHT = GL_LIGHT2
If NLight.Lights=4 Then GL_LIGHT = GL_LIGHT3
If NLight.Lights=5 Then GL_LIGHT = GL_LIGHT4
If NLight.Lights=6 Then GL_LIGHT = GL_LIGHT5
If NLight.Lights=7 Then GL_LIGHT = GL_LIGHT6
If NLight.Lights=8 Then GL_LIGHT = GL_LIGHT7
If NLight.NLightList = Null Then NLightList = CreateList()
ListAddLast(NLight.NLightList,Self)
If Not NGraphics.Gfx.Lighting Then
glEnable(GL_LIGHTING)
NGRaphics.Gfx.Lighting = 1
EndIf
glEnable(GL_LIGHT)
End Method
Function CreateLight:NLight()
Local NLi:NLight = New NLight
Return NLi
End Function
End Type
Type NVertex Extends NPoint
Field OrigX:Float,OrigY:Float,OrigZ:Float
'Field Tri:NTriangle
Field R:Float,G:Float,B:Float
Field Alpha:Float
Method New()
Alpha = 1.0
R = 1.0
G = 1.0
B = 1.0
End Method
End Type
Type NTriangle
Field V1s:Float,V1t:Float
Field V2s:Float,V2t:Float
Field V3s:Float,V3t:Float
Field V1NX:Float,V1NY:Float,V1NZ:Float
Field V2NX:Float,V2NY:Float,V2NZ:Float
Field V3NX:Float,V3NY:Float,V3NZ:Float
Field V1:NVertex
Field V2:NVertex
Field V3:NVertex
End Type
Type NParticle Extends NPoint
Field XSpeed:Float,YSpeed:Float,ZSpeed:Float
Field R:Int,G:Int,B:Int
Field Alpha:Float,AlphaSpeed:Float
Field Starttime:Int
Field CamDistance:Float
End Type
Type NParticleEmitter Extends NPoint
Field Pitch:Float,Yaw:Float,Roll:Float
Field StartR:Int,StartG:Int,StartB:Int
Field RSpeed:Int,GSpeed:Int,BSpeed:Int
Field StartRRnd:Int,StartGRnd:Int,StartBRnd:Int
Field XAcceleration:Float,YAcceleration:Float,ZAcceleration:Float
Field StartXRnd:Float,StartYRnd:Float,StartZRnd:Float
Field StartXSpeedRnd:Float,StartYSpeedRnd:Float,StartZSpeedRnd:Float
Field StartXSpeed:Float,StartYSpeed:Float,StartZSpeed:Float
Field AlphaAcceleration:Float,StartAlphaRnd:Float,StartAlpha:Float,StartAlphaSpeed:Float
Field NParticleList:TList
Field Rate:Int
Field ParticleTimer:Int,Particles:Int
Field Texture:Int,TextureWidth:Int,TextureHeight:Int
Field Lifetime:Int
Field Enabled:Int,RenderEnabled:Int
Global NParticleEmitterList:TList
Method Update(NCam:NCamera)
Local UpdateTime:Int = MilliSecs() - ParticleTimer
ParticleTimer = MilliSecs()
'Loop particles
For Local NPar:NParticle = EachIn NParticleList
NPar.XSpeed = NPar.XSpeed+XAcceleration
NPar.YSpeed = NPar.YSpeed+YAcceleration
NPar.ZSpeed = NPar.ZSpeed+ZAcceleration
NPar.X=NPar.X+NPar.XSpeed
NPar.Y=NPar.Y+NPar.YSpeed
NPar.Z=NPar.Z+NPar.ZSpeed
NPar.AlphaSpeed = NPar.AlphaSpeed+AlphaAcceleration
NPar.Alpha = NPar.Alpha+NPar.AlphaSpeed
If NPar.Alpha>1.0 Then NPar.Alpha=1.0
NPar.R = NPar.R+RSpeed; NPar.G = NPar.G+GSpeed; NPar.B = NPar.B+BSpeed;
If NPar.Alpha<=0.0 Or (MilliSecs()-NPar.Starttime>Lifetime) Then
ListRemove(NParticleList,NPar)
Particles:-1
EndIf
Next
'Create particles
If Enabled
For Local a:Int=1 To Rate
Particles:+1
Local NPar:NParticle = New NParticle
ListAddLast(NParticleList,NPar)
NPar.X = X+Rnd(-StartXRnd,StartXRnd)
NPar.Y = Y+Rnd(-StartYRnd,StartYRnd)
NPar.Z = Z+Rnd(-StartZRnd,StartZRnd)
NPar.XSpeed = StartXSpeed+Rnd(-StartXSpeedRnd,StartXSpeedRnd)
NPar.YSpeed = StartYSpeed+Rnd(-StartYSpeedRnd,StartYSpeedRnd)
NPar.ZSpeed = StartZSpeed+Rnd(-StartZSpeedRnd,StartZSpeedRnd)
NPar.R = StartR + Rand(-StartRRnd,StartRRnd)
NPar.G = StartG + Rand(-StartGRnd,StartGRnd)
NPar.B = StartB + Rand(-StartBRnd,StartBRnd)
NPar.AlphaSpeed = StartAlphaSpeed
NPar.Alpha = StartAlpha+Rnd(-StartAlphaRnd,StartAlphaRnd)
NPar.Starttime=MilliSecs()
Next
EndIf
If RenderEnabled Then
SortParticles(NCam:NCamera)
'MergeSortList(NParticleList)
Render(NCam)
EndIf
End Method
Method Render(NCam:NCamera)
'glEnable(GL_TEXTURE_2D)
'glBlendFunc(GL_SRC_ALPHA, GL_ONE)
glDepthMask(GL_FALSE)
' glBindTexture (GL_TEXTURE_2D, Texture)
'glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST
'glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST
NGraphics.Gfx.Triangles:+Particles*2
Local maxsize:Float,quad:Float[]=[1.0,0.0,0.01]
glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB,quad)
glGetFloatv(GL_POINT_SIZE_MAX_ARB,Varptr(maxsize))
glPointSize(maxsize)
glPointParameterfARB(GL_POINT_FADE_THRESHOLD_SIZE_ARB,80.0)
glPointParameterfARB(GL_POINT_SIZE_MIN_ARB,1.0)
glPointParameterfARB(GL_POINT_SIZE_MAX_ARB,maxsize)
glTexEnvf(GL_POINT_SPRITE_ARB,GL_COORD_REPLACE_ARB,GL_TRUE)
glEnable( GL_POINT_SPRITE_ARB)
glBegin(GL_POINTS)
For Local NPar:NParticle = EachIn NParticleList
glColor4f(NPar.R/255.0,NPar.G/255.0,NPar.B/255.0,NPar.Alpha)
glVertex3f(NPar.X,NPar.Y,NPar.Z)
Next
glEnd()
glDisable(GL_POINT_SPRITE_ARB)
'glDisable(GL_TEXTURE_2D)
glDepthMask(GL_TRUE)
'glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
End Method
Method Turn(NewPitch:Float,NewYaw:Float,NewRoll:Float)
Pitch = Pitch+NewPitch Mod 360.0
Yaw = Yaw+NewYaw Mod 360.0
Roll = Roll+NewRoll Mod 360.0
If Pitch<0.0 Then Pitch=Pitch+360.0
If Yaw<0.0 Then Yaw=Yaw+360.0
If Roll<0.0 Then Roll=Roll+360.0
If Pitch>360.0 Then Pitch=Pitch-360.0
If Yaw>360.0 Then Yaw=Yaw-360.0
If Roll>360.0 Then Roll=Roll-360.0
End Method
Method Rotate(NewPitch:Float,NewYaw:Float,NewRoll:Float)
Pitch = NewPitch Mod 360.0
Yaw = NewYaw Mod 360.0
Roll = NewRoll Mod 360.0
While Pitch<0.0
Pitch=Pitch+360.0
Wend
While Yaw<0.0
Yaw=Yaw+360.0
Wend
While Roll<0.0
Roll=Roll+360.0
Wend
While Pitch>360.0
Pitch = Pitch-360.0
Wend
While Yaw>360.0
Yaw = Yaw-360.0
Wend
While Roll>360.0
Roll = roll-360.0
Wend
End Method
Method Move(NewX:Float,NewY:Float,NewZ:Float)
Local MoveMat:TMatrix=New TMatrix
MoveMat.LoadIdentity()
MoveMat.RotateYaw(Yaw)
MoveMat.RotatePitch(Pitch)
MoveMat.RotateRoll(Roll)
MoveMat.Translate(NewX,NewY,-NewZ)
X = X+MoveMat.grid[3,0]
Y = Y+MoveMat.grid[3,1]
Z = Z+MoveMat.grid[3,2]
End Method
Method SortParticles(NCam:NCamera)
For Local NPar:NParticle = EachIn NParticleList
NPar.CamDistance = (NCam.X-NPar.X)*(NCam.X-NPar.X)+(NCam.Y-NPar.Y)*(NCam.Y-NPar.Y)+(NCam.Z-NPar.Z)*(NCam.Z-NPar.Z)
Next
MergeSortList(NParticleList)
' NParticleList.Sort(True,NParticleEmitter.CompareDistance)
End Method
Function CompareDistance:Int(o1:Object,o2:Object)
If NParticle(o1).CamDistance>NParticle(o2).CamDistance Return 1
Return 0
End Function
Function CreateEmitter:NParticleEmitter(Filename:String)
Local NEmit:NParticleEmitter = New NParticleEmitter
NEmit.NParticleList = CreateList()
ListAddLast(NParticleEmitter.NParticleEmitterList,NEmit)
If FileType(Filename)=0 Then RuntimeError Filename+" not found!"
Local TXMap:TPixmap = LoadPixmap(Filename)
If Not TXMap Then RuntimeError "Could not load texture!"
NEmit.Texture = GLTexFromPixmap(TXMap)
If Not NEmit.Texture Then RuntimeError "Could not load texture to memory!"
NEmit.TextureWidth = TXMap.Width
NEmit.TextureHeight = TXMap.Height
NEmit.Enabled = 1
NEmit.RenderEnabled = 1
NEmit.ParticleTimer = MilliSecs()
Return NEmit
End Function
End Type
Type NShader
Field Shader:String
Field VertexShader:Byte,FragmentShader:Byte
Field ProgramObject:Int
Function LoadShader:NShader(VertexFilename:String,FragmentFilename:String)
If FileType(VertexFilename)<>1 Then RuntimeError VertexFilename+" not found!"
If FileType(FragmentFilename)<>1 Then RuntimeError FragmentFilename+" not found!"
Local VertexFile:TStream = OpenStream(VertexFilename)
Local FragmentFile:TStream = OpenStream(FragmentFilename)
Local Sha:NShader = New NShader
Local VertexArray:Byte[FileSize(VertexFilename)+1]
Local FragmentArray:Byte[FileSize(FragmentFilename)+1]
Local i:Int=0,j:Int=0,VertexSize:Int,FragmentSize:Int
VertexSize = FileSize(VertexFilename)
FragmentSize = FileSize(FragmentFilename)
While Not Eof(VertexFile)
VertexArray[i] = ReadByte(VertexFile)
i=i+1
If i>VertexSize Then i=VertexSize
Wend
While Not Eof(FragmentFile)
FragmentArray[j] = ReadByte(FragmentFile)
j=j+1
If j>FragmentSize Then j=FragmentSize
Wend
VertexArray[i] = 0
FragmentArray[j] = 0
Local VertexPointer:Byte Ptr[1]
Local FragmentPointer:Byte Ptr[1]
VertexPointer[0] = Varptr(VertexArray[0])
FragmentPointer[0] = Varptr(FragmentArray[0])
Sha.VertexShader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB)
Sha.FragmentShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB)
glShaderSourceARB(Sha.VertexShader, 1, VertexPointer, Null)
glShaderSourceARB(Sha.FragmentShader, 1, FragmentPointer, Null)
glCompileShaderARB(Sha.VertexShader)
glCompileShaderARB(Sha.FragmentShader)
Sha.ProgramObject = glCreateProgramObjectARB()
If Not Sha.ProgramObject Then RuntimeError "Could not create shader program object."
glAttachObjectARB(Sha.ProgramObject,Sha.VertexShader)
glAttachObjectARB(Sha.ProgramObject,Sha.FragmentShader)
glLinkProgramARB(Sha.ProgramObject)
Return Sha:NShader
End Function
End Type
Function SameDirection:Int(Pt1:NPoint,Pt2:NPoint,Pt3:NPoint,Norm:NPoint)
Local Testi:Float,Testj:Float,Testk:Float
Local DotProduct:Float
Testi = (((Pt2.y - Pt1.y)*(Pt3.z - Pt1.z)) - ((Pt3.y - Pt1.y)*(Pt2.z - Pt1.z)))
Testj = (((Pt2.z - Pt1.z)*(Pt3.x - Pt1.x)) - ((Pt3.z - Pt1.z)*(Pt2.x - Pt1.x)))
Testk = (((Pt2.x - Pt1.x)*(Pt3.y - Pt1.y)) - ((Pt3.x - Pt1.x)*(Pt2.y - Pt1.y)))
DotProduct = Testi*Norm.x + Testj*Norm.y + Testk*Norm.z
If DotProduct<0.0 Then
Return False
Else
Return True
EndIf
End Function
Function LineIntersectsTriangle:Int(pt1:NPoint,pt2:NPoint,pt3:NPoint,linept:NPoint,vect:NPoint)
Local V1x:Float, V1y:Float, V1z:Float
Local V2x:Float, V2y:Float, V2z:Float
Local norm:NPoint = New NPoint,pt_int:NPoint = New NPoint
Local dotprod:Float,t:Float
V1x = pt2.x - pt1.x
V1y = pt2.y - pt1.y
V1z = pt2.z - pt1.z
V2x = pt3.x - pt2.x
V2y = pt3.y - pt2.y
V2z = pt3.z - pt2.z
norm.x = V1y*V2z-V1z*V2y
norm.y = V1z*V2x-V1x*V2z
norm.z = V1x*V2y-V1y*V2x
dotprod = norm.x*vect.x + norm.y*vect.y + norm.z*vect.z
If dotprod<0 Then
t = -(norm.x*(linept.x-pt1.x)+norm.y*(linept.y-pt1.y)+norm.z*(linept.z-pt1.z))/(norm.x*vect.x+norm.y*vect.y+norm.z*vect.z)
If t < 0 Then Return False
pt_int.x = linept.x + vect.x*t
pt_int.y = linept.y + vect.y*t
pt_int.z = linept.z + vect.z*t
If SameDirection(pt1, pt2, pt_int, norm)
If SameDirection(pt2, pt3, pt_int, norm)
If SameDirection(pt3, pt1, pt_int, norm)
Return True
EndIf
EndIf
EndIf
EndIf
Return False
End Function
Function GetFolder:String(Filename:String)
If Filename.Find("/")=-1 And Filename.Find("\")=-1 Then Return ""
If Filename.Find("/") > 0 Then
Return Left(Filename,Filename.FindLast("/")+1)
Else
Return Left(Filename,Filename.FindLast("\")+1)
EndIf
End Function
Function MergeSortList( slist:TList)
Local p:TLink, q:TLink, e:TLink, tail:TLink, oldhead:TLink
Local insize:Int, nmerges:Int, psize:Int, qsize:Int, i:Int
Local list:TLink
If slist = Null Then Return
If slist._head._succ <> slist._head Then list = slist._head._succ
If list = Null Then Return
insize = 1
Repeat
p = list
oldhead = list
list = Null
tail = Null
nmerges = 0
While p <> Null
nmerges :+ 1
q = p
psize = 0
For i = 0 Until insize
psize :+ 1
If q._succ = oldhead Then
q = Null
Else
q = q._succ
EndIf
If q = Null Then Exit
Next
qsize = insize
While (psize > 0) Or ((qsize > 0) And (q <> Null))
If psize = 0 Then
e = q
q = q._succ
qsize :- 1
If q = oldhead Then q = Null
ElseIf (qsize = 0) Or (q = Null) Then
e = p
p = p._succ
psize :- 1
If p = oldhead Then p = Null
ElseIf NParticle(p._value).CamDistance<NParticle(q._value).CamDistance Then
e = p
p = p._succ
psize :- 1
If p = oldhead Then p = Null
Else
e = q
q = q._succ
qsize :- 1
If q = oldhead Then q = Null
EndIf
If tail <> Null Then
tail._succ = e
Else
list = e
EndIf
e._pred = tail
tail = e
Wend
p = q
Wend
tail._succ = list
list._pred = tail
If nmerges <= 1 Then Return
insize :* 2
Forever
EndFunction
A simple test file that shows some of the commands: ngltest.bmx
Strict
Import "ngl.bmx"
SeedRnd MilliSecs()
Local Gfx:NGraphics = NGraphics.Start(800,600)
Local Cam:NCamera = NCamera.CreateCamera()
Cam.Move(30,10,-60)
Cam.SetClearColor(163,192,255)
'Cam.EnableFog(150,520,163,192,255)
HideMouse
Local Cube:NEntity = NEntity.CreateCube()
Cube.ScaleMesh(0.1,0.1,0.1)
Cube.Position(15,6,4)
'Cube.LoadTexture("crate.jpg")
'Cube.EntityAlpha 0.3
'Local Cube2:NEntity = NEntity.CreateCube()
'Cube2.Translate(0,0,-5)
'Cube2.Shadows = 1
'Cube2.EntityColor(255,0,0)
Local Room:NEntity = NEntity.CreateCube()
Room.ScaleMesh(40,25,40)
Room.Move(0,20,0)
Room.LoadTexture("wall.jpg")
Room.FlipMesh()
'Local Mesh:NEntity = NEntity.LoadMesh("md2/fish.md2")
'Mesh.ScaleMesh(0.3,0.3,0.3)
'Mesh.Shadows = 0
'Local S:NEntity = NEntity.CreateSprite()
'S.LoadTexture("crate.jpg")
'S.Translate(0,0,15)
'S.Shadows = 1
'Local Mesh2:NEntity = NEntity.LoadMesh("md2/turret.md2")
'Mesh2.ScaleMesh(0.1,0.1,0.1)
'Mesh2.Move(6,3,0.4)
'Mesh2.Shadows = 0
'Mesh.FrameTime = 40
''Mesh.EntityAlpha 0.3
'Mesh.Move(15,-2,0)
'Mesh.MoveMesh(3,0,0)
'Mesh.Turn(-90,0,135)
'Mesh.FrameTime = 40
'Mesh.Interpolate()
'Mesh.Move -10000,0,0
'Local testshader:NShader = NShader.LoadShader("shader/water.vertex","shader/water.frag")
'Cube2.EntityParent Mesh
'Local tmesh:NEntity[100],counter
'For Local a=0 To 9
' For Local b=0 To 9
' tmesh:NEntity[counter]= Mesh.CopyEntity()
' tmesh[counter] .Move(b*10,0,a)
' counter:+1
' Next
'Next
'tmesh.FreeEntity
'Mesh.FreeEntity
'Mesh.Move(20,0,-50)
'Local Light:NLight = NLight.CreateLight()
'Light.Translate(20,40,0)
'Light.Ambient(255,255,255)
'Light.Diffuse(255,255,255)
'sprite.AttachShader(testshader)
'Local Smoke:NParticleEmitter = NParticleEmitter.CreateEmitter("smoke4.png")
'Smoke.StartR=205; Smoke.StartG=205; Smoke.StartB=105; Smoke.Translate(0,0,6)
'Smoke.RSpeed = -1; Smoke.GSpeed = -1; Smoke.BSPeed = -1
'Smoke.StartRRnd = 50; Smoke.StartGRnd = 50; Smoke.StartBRnd = 50
'Smoke.StartXSpeedRnd = 0.06; Smoke.StartYSpeedRnd = 0.06; Smoke.StartZSpeedRnd = 0
'Smoke.StartYSpeed = 0.1; Smoke.YAcceleration = -0.005; Smoke.StartZSpeed = 0.05
'Smoke.StartXRnd = 0.2; Smoke.StartYRnd = 0.2; Smoke.StartZRnd = 0.2;
'Smoke.Rate =30; Smoke.Lifetime=1000; Smoke.StartAlpha = 0.9; Smoke.StartAlphaRnd = 0.2
'Smoke.StartAlphaSpeed = -0.005
'Local Map:NEntity = NEntity.Heightmap("hmap.bmp")
'Map.LoadTexture("grass.png")
'Local Tree:NEntity = NEntity.CreateSprite()
'Tree.LoadTexture("tree.png")
'Tree.Blend = 1
'Tree.X = Map.X; Tree.Y = Map.Y; Tree.Z = Map.Z
'Local NewTree:NEntity
'Local Counter:Int = 0
'For Local NTri:NTriangle = EachIn Map.NTriangleList[Map.Frame]
' If Counter=Rand(1,30) Or Counter>30 And NTri.V1.Y>12.1 Then
' Tree.MoveMesh(NTri.V1.X,NTri.V1.Y+0.5,NTri.V1.Z)
'NewTree.AddMesh(Tree)
'' Tree.MoveMesh(-NTri.V1.X,-NTri.V1.Y-0.5,-NTri.V1.Z)
' NewTree:NEntity = Tree.CopyEntity()
' NewTree.Position(NTri.V1.X+Rnd(0.5),NTri.V1.Y+0.5,NTri.V1.Z+Rnd(0.5))
' Counter=0
' EndIf
' Counter:+1
'Next
'Tree.FreeEntity()
'Local Water:NEntity = NEntity.CreateSprite()
'Water.Turn(-90,0,0)
''Water.EntityColor(50,50,255)
'Water.LoadTexture("water.jpg")
'Water.ScaleMesh(1000,1000,1)
'Water.Translate(0,10,0)
'Water.RenderFirst = 1
Repeat
'Camera control
If KeyDown(KEY_LEFT) Then Cam.Move(-0.3,0,0)
If KeyDown(KEY_RIGHT) Then Cam.Move(0.3,0,0)
If KeyDown(KEY_UP) Then Cam.Move(0,0,0.3)
If KeyDown(KEY_DOWN) Then Cam.Move(0,0,-0.3)
If KeyDown(KEY_A) Then Cam.Move(0,0.1,0)
If KeyDown(KEY_Z) Then Cam.Move(0,-0.1,0)
If KeyDown(KEY_W) Then Cam.Turn(0,2,0)
If KeyDown(KEY_Q) Then Cam.Turn(0,-2,0)
If KeyDown(KEY_Y) Then Cube.Move(-0.3,0,0)
If KeyDown(KEY_U) Then Cube.Move(0.3,0,0)
'If Cube.Intersect(Mesh) Then Print "collision"
'Mesh.Animate()
' Mesh.Turn(0.3,1,2)
' Mesh.Move(0,0.1,0)
' Cube2.Turn(2,2,2)
'Mesh.Turn(0,0,2)
'Mesh.Move(0,0.05,0)
'Cube.Turn(2,2,2)
'Cube2.Turn(0,0.5,0)
Cube.RenderShadows()
Gfx.Render
Gfx.Swap(1)
Print Gfx.FPS+" fps "+Gfx.Triangles+" tris"
'Print GCMemAlloced()
Until KeyHit(KEY_ESCAPE)
You need extra file called nmatrix.bmx for the lib to work, copy it from the post below.
|