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
A simple test file that shows some of the commands:
ngltest.bmx
You need extra file called nmatrix.bmx for the lib to work, copy it from the post below.
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.