MD2 Loader + Animation - Texturing

BlitzMax Forums/BlitzMax OpenGL Programming/MD2 Loader + Animation - Texturing

Hi guys,

I have been working on a translation of a Java MD2 loader, found on the net, into a Blitzmax version.
It works great besides the texturing part. Being a newbie in opengl I thought it was time to ask for help.

I am posting my code below. If you manage to texture the model correctly please post an updated version of the code so that we can all benefit from it.


You can move the camera around the animated model using the arrow keys. You will have to find a MD2 model and update the model path aswell as the texture path in the code in the New Method of the MD2 type.

Thanks for your help
bye
Nennig

Global ScreenWidth:Int=1024
Global ScreenHeight:Int=768
Global ScreenDepth:Int=32

bglCreateContext(ScreenWidth,ScreenHeight,ScreenDepth,0,BGL_BACKBUFFER | BGL_DEPTHBUFFER)


Type Face
	Field vertIndex:Int[3]
	Field uvIndex:Int[3]
End Type


Type animFrame
	Field name:String
	Field vertices:Float[]
End Type


Type MD2

Field myCamera:TCamera 
Field name:String
Field magic:Int
Field version:Int
Field skinWitdh:Int
Field skinHeight:Int
Field frameSize:Int
Field numSkins:Int
Field numVertices:Int
Field numTexCoords:Int
Field numTriangles:Int
Field numGLcommands:Int
Field numFrames:Int
Field offsetSkins:Int
Field offsetTexCoords:Int
Field offsetTriangles:Int
Field offsetFrames:Int
Field offsetGLcommands:Int
Field offsetEnd:Int


Field uvs:Float[]
Field faces:Face[]
Field normals:Float[]
Field interpolatedFrame:animFrame
Field frames:animFrame[]

Field startFrame:Int=0
Field endFrame:Int=0

Field curAnimFrame:Int=0
Field nextAnimFrame:Int=1

Field lastAnimTime:Long=0

Field fps:Int=30
Field animate=False



Function LoadGLTexture(filename:String)
	Local TextureImage:TPixmap
	TextureImage:TPixmap=LoadPixmap(filename)							
	

	
	If TextureImage <> Null											
		glGenTextures(1, Varptr texture)								
		glBindTexture(GL_TEXTURE_2D, texture)
		glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage.width, TextureImage.height, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage.pixels)
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR)
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR)
	EndIf
	Return texture													
End Function


Method New()
	myCamera = New TCamera
	hBMP=LoadGLTexture("blade_red.bmp")
	filename:String="tris.md2"
	glEnable(GL_TEXTURE_2D)	
	glClearColor(0.0, 2.0, 0.0, 0.0)
	glClearDepth 1.0
	glDepthFunc(GL_LESS)
	glEnable(GL_DEPTH_TEST)
	glFrontFace(GL_CW)
	glShadeModel(GL_SMOOTH)
	glViewport(0,1,ScreenWidth,ScreenHeight)
	glMatriXMode(GL_PROJECTION)
	glLoadIdentitY()
	gluPerspective(45.0,Float(ScreenWidth)/Float(ScreenHeight),1.0,1000.0)
	gluLookAt(mYCamera.Eye.X,mYCamera.Eye.Y,mYCamera.Eye.Z,mYCamera.Target.X,mYCamera.Target.Y,mYCamera.Target.Z,mYCamera.Up.X,mYCamera.Up.Y,mYCamera.Up.Z)
	glMatriXMode(GL_MODELVIEW)
	
	
	fichier=OpenFile(filename)
	taille= FileSize(fichier)
	magic=Readint(fichier)
	version=Readint(fichier)
	skinWitdh=Readint(fichier)
	skinHeight=Readint(fichier)
	framSize=Readint(fichier)
	numSkins=Readint(fichier)
	numVertices=Readint(fichier)
	numTexCoords=Readint(fichier)
	numTriangles=Readint(fichier)
	numGLcommands=Readint(fichier)
	numFrames=Readint(fichier)
	offsetSkins=Readint(fichier)
	offsetTexCoords=Readint(fichier)
	offsetTriangles=Readint(fichier)
	offsetFrames=Readint(fichier)
	offsetGLcommands=Readint(fichier)
	offsetEnd=Readint(fichier)
			
	
	uvs= New Float[numTexCoords*2]
	SeekStream (fichier, offsetTexCoords)
	For i=0 To numTexCoords-1
		uvs[i*2]=ReadShort(fichier)/ skinWitdh
		uvs[(i*2)+1]=1-ReadShort(fichier)/ skinHeight

	Next 
	
	
	SeekStream (fichier, offsetTriangles)
	faces=New Face[numTriangles]
	For i=0 To numTriangles-1
		faces[i]= New Face
		curFace:Face=faces[i]
		curFace.vertIndex[2] = ReadShort(fichier)
		curFace.vertIndex[1] = ReadShort(fichier)
		curFace.vertIndex[0] = ReadShort(fichier)
		curFace.uvIndex[2] = ReadShort(fichier)
		curFace.uvIndex[1] = ReadShort(fichier)
		curFace.uvIndex[0] = ReadShort(fichier)
	Next

	frames = New animFrame[numFrames]
	interpolatedFrame = New animFrame
	interpolatedFrame.vertices = New Float[numVertices*3]
	SeekStream(fichier, offsetFrames)
	Local scale:Float [3]
	Local translate:Float[3]
	Local curFrame:animFrame
	Local tempx:Int
	Local tempy:Int
	Local tempz:Int
	Local dummy:Int
	
	For i=0 To numFrames-1
            
                frames[i] = New animFrame
                frames[i].vertices = New Float[numVertices * 3]
                curFrame = frames[i]                                
                                                
                scale[0] = ReadFloat(fichier)
		       scale[1] = ReadFloat(fichier)
		       scale[2] = ReadFloat(fichier)
		       translate[0] = ReadFloat(fichier)
		       translate[1] = ReadFloat(fichier)
		       translate[2] = ReadFloat(fichier)
		       curFrame.name = ReadString(fichier,16)
                                
                For v= 0 To numVertices-1
                                
                    tempx = ReadByte(fichier)
                    tempy = ReadByte(fichier)
                    tempz = ReadByte(fichier)
                    dummy = ReadByte(fichier)
                    curFrame.vertices[(v*3)] = tempx * scale[0] + translate[0]
                    curFrame.vertices[(v*3)+2] = -1 * (tempy * scale[1] + translate[1])
                    curFrame.vertices[(v*3)+1] = tempz * scale[2] + translate[2] 
	
		    	Next
	Next		
	CloseStream(fichier)	
	
End Method

Method Render()
		glClearColor(0.0, 0.1, 0.6, 0.0)
		glClear GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT
		glLoadIdentitY()
		glTranslatef(0.0,0.0,155.0)
		gluLookAt(mYCamera.Eye.X,mYCamera.Eye.Y,mYCamera.Eye.Z,mYCamera.Target.X,mYCamera.Target.Y,mYCamera.Target.Z,mYCamera.Up.X,mYCamera.Up.Y,mYCamera.Up.Z)
		bglDrawText("Eye.X " + mYCamera.Eye.X,10,24)
		bglDrawText("Eye.Y " + mYCamera.Eye.Y,10,44)
		bglDrawText("Eye.Z " + mYCamera.Eye.Z,10,64)
		
		bglDrawText("Target.X " + mYCamera.Target.X,260,24)
		bglDrawText("Target.Y " + mYCamera.Target.Y,260,44)
		bglDrawText("Target.Z " + mYCamera.Target.Z,260,64)

        frame:animFrame = frames[startFrame]
		        
        If (animate=True) Then
      
            createInterpolatedFrame()
            frame = interpolatedFrame

      	End If 
	   
	    glBegin GL_TRIANGLES
	     
        For  i = 0 To faces.length-1 
           
         curFace:Face = faces[i]
            
         For v= 0 To  2
			
		glTexCoord2f(uvs[(curFace.uvIndex[v]*2)], uvs[(curFace.uvIndex[v]*2)+1])
         glVertex3f(frame.vertices[(curFace.vertIndex[v]*3)], frame.vertices[(curFace.vertIndex[v]*3)+1], frame.vertices[(curFace.vertIndex[v]*3)+2])               
      				
		Next 
        Next
		glEnd
		
		
End Method

Method setFrameRange(startFrame:Int,endFrame:Int)
    
        self.startFrame = startFrame
        self.endFrame = endFrame
       
        If (startFrame < 0) Then startFrame = 0
        If (startFrame > frames.length) Then startFrame = frames.length
        If (endFrame < 0) Then endFrame = 0
        If (endFrame > frames.length) Then endFrame = frames.length
       
        curAnimFrame = startFrame
        nextAnimFrame = startFrame+1

End Method
    
Method setFPS(fps:Int)
           
        self.fps = fps
End Method   


Method toggleAnim(enable:Int)
    
	self.animate = enable
    
End Method    



Method resetAnim()
        curAnimFrame = startFrame
        nextAnimFrame = startFrame+1
        lastAnimTime = 0
End Method

Method createInterpolatedFrame()
              
        curTime:Long = MilliSecs()
        elapsedTime:Long = curTime - lastAnimTime
               
	    t:Float = elapsedTime / (1000.0 / self.fps)
        
        nextAnimFrame = (curAnimFrame + 1) Mod endFrame
        If (nextAnimFrame > endFrame) Then  nextAnimFrame = startFrame
        	
        If(elapsedTime > (1000.0 / fps)) Then
	       curAnimFrame = nextAnimFrame                                  
           lastAnimTime = curTime
	    End If
	        
         For v = 0 To frames[curAnimFrame].vertices.length -1 
        
         interpolatedFrame.vertices[v] = (frames[curAnimFrame].vertices[v] + t * (frames[nextAnimFrame].vertices[v] - frames[curAnimFrame].vertices[v]))
        	
    		Next 

End Method

End Type

Type TCamera 
	
	Field Eye:Vector3 = New Vector3
	Field Target:Vector3 = New Vector3
	Field Dir:Vector3 = New Vector3
	Field Up:Vector3 = New Vector3
	Field VRight:Vector3= New Vector3
	
	Method New()
		
		Eye.X=0.0
		Eye.Y=10.0
		Eye.Z=-22.0
		Target.X=0.0
		Target.Y=0.0
		Target.Z=100.0
		Up.X=0.0
		Up.Y=1.0
		Up.Z=0.0
		VRight.X=0.0
		VRight.Y=0.0
		VRight.Z=0.0
		
	End Method
	
	Method Move(speed:Float)
		
		Dir=Target.Sub(Eye)
		Eye.X:+Dir.X *speed
		Eye.Z:+Dir.Z *speed
		
		Target.X:+Dir.X *speed
		Target.Z:+Dir.Z *speed
		
	End Method		
	
	Method Rotate(speed:Float)
			
		Dir=Target.Sub(Eye)
		s:Float=DegreeToRadian(speed)
		Target.Z=(Eye.Z+Sin(s)*Dir.X + Cos(s)*Dir.Z)
		Target.X=(Eye.X+Cos(s)*Dir.X - Sin(s)*Dir.Z)
	End Method


	Function  DegreeToRadian:Float(degree:Float)
			 out:Float= degree * (3.1415926/180)
			 Return out	
	End Function
	

End Type


Type Vector3
	Field X:Float										
	Field Y:Float										
	Field Z:Float		
	
	Method Sub:Vector3(v:Vector3)
		result:Vector3=New Vector3
		result.X=X-v.X ; result.Y=Y-v.Y ; result.Z=Z-v.Z
		Return result
	End Method
	
	Method New()
		X=0.0 ; Y=0.0 ; Z=0.0
	End Method

End Type


Global myModel:MD2= New MD2
myModel.setFrameRange(0,198)
myModel.toggleAnim(1)
myModel.setFPS(10)

While Not KeyHit( KEY_ESCAPE )
	If KeyDown(KEY_DOWN) Then myModel.mYCamera.Move(+0.01)
	If KeyDown(KEY_UP) Then myModel.mYCamera.Move(-0.01)
	If KeyDown(KEY_LEFT) Then myModel.mYCamera.Rotate(10)
	If KeyDown(KEY_RIGHT) Then myModel.mYCamera.Rotate(-10)
	myModel.Render()
	bglSwapBuffers
	FlushMem
Wend