Speaking Of NormalMapping...

Miscellaneous Forums/Graphics Showcase/Speaking Of NormalMapping...

... here's another Guess If This Is Real thread :)







the scenes in the screenshots... are they from DOOM3, or from another game done with another engine...

What's your best guess...


--Mike

Errr... from another game done with another engine?

But what engine?

I guess that they are in B3D due to the FOV on the lower shot and the general bluriness of distant textures, but I expect I'm completely wrong.

In anycase, they are scary screenshots !!!

brrrr !!!

Sergio.

They all seem to be in the same pose?

The anti-aliasing doesn't look quite doom-ish.

I'd take a guess and say you loaded the meshes from D3 into Blitz (hence the standard 'T' pose)

That's look pretty good Mike,

so, does the D3 game come with all source models un-encrypted? that's a great way to learn a lot about modelling,
how much polys in those models Mike? (and in the scenes ...?)


Paolo.

I'm going to guess that it's beyond Doom 3!! In fact I'd guess that it's "Beyond Virtual." Am I right?

hey Paolo!!! looooong time no see... how's everything going lately...

guys... the truth shall be revelaed shortly... i'm gonna let the guy who is responsible do the honors :)

--Mike

Any chance of seeing this with naked females?

not until you reach the age of 18 puk...

:)

--Mike

3drad??? Am i right?? ;)

Vorderman and Muzzer were, right just plain ol b3d.
(does anyone know how to Extract a md5 with anims intact?)

First off, some of the normals are little messed up ...Fattys neck and shirt for example, this seems to be a problem with the Exporter (seems to be exporting tri Strips)

I used the normalizing cubemap and a lighting Cubemap. I redid the Normalmaps a bit , d3 uses the polybump style normalmap and a heightmap for "bumpiness" so I normalized and combined them.
This lost some detail overall, so not as sharp as in doom3.
Also the Lack of Specular is good/Bad depending on who you ask.
If you thought D3 was "just to plastic looking" then its probably good.

Paolo , low poly 1200(bernie)-1400(fatty) , thats where the normal maps come in. They do work even if its bit washed out next to Doom3. For example, the eyesockets , fattys double chin and the wrinkles in the clothes all just normalmap.

The main disadvantage is lighting, you can probbaly get 3 lights into a cubemap but they need to be distant light (Sun or moon for example) and control the intensity but setting the models color (entitycolor)
and ofcourse they are static.

But there are advantages...while not animated here I can still Render 50 of them and stay above 300 fps

I wasnt really trying to even look like doom3, I just used the models to see what properly mapped models would look like, becuase My own were very ugly..heh

I think they rendered well for Dx7 :)

edit: paolo , you can open the Doom3 paks in winrar/winarj ect :)

Sam

Doom 3 is boring.

Try normal mapping HL2 stuff:



does HL do anything differant? Other than have higher poly meshes and not need the Normalmap(for normal faking) and just use it for bumpiness?

Sam

Red Ocktober: Is it possible to get the code for that piece, Please!!!!!!!!!!!!

Thats Rob Cummings zombie, and it looks like it's done in blitz3d :o)

8/ Code anyone ??

PLEASE!!!

Theres no real code Alien , just texture stages and model Color for brightness.

I can email you media and tell you how set it up if you would like :)
I dont have any webspace to put it on.

@Ross
Rob made Bernie the zombie? ;)

Im trying to Get the Spec maps work atleast somewhat now. I can get it to work somewhat like a gloss map But the cubelight only effects the Mask , good for metal..not people
This is probably why Doom3 uses the Heightmap and the normal map seperate.


Sam

Hmmm, maybe it's not the same one ;o) Looks quite similar though :D

I was just looking at your post in the other normalmaps thread...good stuff :)

If you want to try it with a D3 model,I can email one to you. They are from the demo,so I dont think we will get sued..lol


Sam

yeah guys... it's ZMatrix's code... i'm just his agent...

send all your questions to him... send the money and royalty checks to me :)

--Mike

Yeah, send that model across :D

Zmatrix: Please drop me a mail! thomas@...

Thanks Z, i got your email. Check the other post for the results. Sorry for the hi-jack, Red :S

Alien : Sorry I missed your post earlier.
Sent you an Email. If you want a differnt model
Let me know :)

Sam

did a md5 loader with animations a while back, (max) will post it up if anyone wants to convert

Yes please!

k heres the code, slightly older version, will try and find the new one later.

'doom 3\quake 4 model format loader
Type MD5_BBox
	Field BMin:Vector3
	Field BMax:Vector3
	
	Method New()
		
		BMin = New Vector3
		BMax = New Vector3
		
	End Method
End Type

Type MD5_Anim
	Field NumFrames:Int
	Field NumJoints:Int
	
	Field FrameRate:Int
	
	Field SkelIndex:MD5_SkelIndex[]
	Field BBoxes:MD5_BBox[]
End Type

Type MD5_AnimInfo
	Field CurrFrame:Int
	Field NextFrame:Int
	
	Field LastTime:Double
	Field MaxTime:Double
End Type

Type MD5_SkelIndex
	Field SkelFrames:MD5_Joint[]
	
	Method GetJoint:MD5_Joint(nParent:String)
		
		For Local i:MD5_Joint = EachIn SkelFrames
			If i.Name = nParent
				Return i
			EndIf
		Next
		
	End Method
End Type

Type MD5_Joint
	Field Name:String
	Field Parent:Int
	
	Field Pos:Vector3
	Field Pos2:Float[3]
	
	Field Orient:Quat_Class
	
	Method New()
		
		Pos = New Vector3
		Orient = New Quat_Class
		
	End Method
End Type

Type MD5_JointInfo
	Field Name:String
	Field Parent:Int
	Field Flags:Int
	Field StartIndex:Int
End Type

Type MD5_BaseFrameJoint
	Field Pos:Vector3
	Field Orient:Quat_Class
	
	Method New()
		
		Pos = New Vector3
		Orient = New Quat_Class
		
	End Method
End Type

Type MD5_Vertex
	Field St:Float[2]
	
	Field Start:Int
	Field Count:Int
	
	Field Normal:Vector3
	
	Field Tangent:Vector3[2]
	Field TangentNormal:Vector3
	
	Field xyz:Float[3]
End Type

Type MD5_Triangle
	Field Index:Int[3]
End Type

Type MD5_Weight
	Field Joint:Int
	Field Bias:Float
	
	Field Pos2:Float[3]
	Field Pos:Vector3
	
	Field Normal:Vector3
End Type

Type MD5_Mesh
	Field Vertices:MD5_Vertex[]
	Field Triangles:MD5_Triangle[]
	Field Weights:MD5_Weight[]
	
	Field NumVerts:Int
	Field NumTris:Int
	Field NumWeights:Int
	
	Field Shader:String
	Field VertexIndices:Int[]
	
	Field VertexBuffer:Float[]
	Field NormalBuffer:Float[]
	Field TextureBuffer:Float[]
	
	Method New()
		
		
		
	End Method
End Type

Type MD5_Class Extends Entity_Class
	Field Anim:MD5_Anim
	Field AnimInfo:MD5_AnimInfo
	
	Field BaseSkel:MD5_Joint[]
	Field Skeleton:MD5_Joint[]
	
	Field Meshes:MD5_Mesh[]
	
	Field NumJoints:Int
	Field NumMeshes:Int
	
	Field animinc:Double
	
	Method New()
		
		ListAddLast(Entity_List,Self)
		
		Entity_Matrix = New Matrix4
		Entity_Scale_Matrix = New Matrix4
		
	End Method
	
	Method Delete()
		
		Remove()
		
	End Method
	
	Method Remove()
		
		Entity_Matrix = Null
		Entity_Scale_Matrix = Null
		
		ListRemove(Entity_List,Self)
		
	End Method
	
	Method Load:Int(nFile:String,nAnimFile:String="")
		
		Local FileIn:TStream
		Local LineIn:String
		
		Local Version:Int,CommandLine:String
		
		Local CurrMesh:Int = 0
		Local i:Int
		
		Local ParseIndex:Int[2]
		
		'read file and parse data
		FileIn = OpenStream(nFile,True,False)
			While Not Eof(FileIn)
				'read line
				LineIn = ReadLine(FileIn)
				
				'skip if line is blank
				If LineIn.length = 0 Then Continue
				
				'version
				If Instr(LineIn,"MD5Version")
					Version = Int(Mid(LineIn,Instr(LineIn," ")+1))
					
					'if its not a version 10 then fail the file
					If Not Version = 10 Then Return False
					
					Continue
					
				'commandline
				ElseIf Instr(LineIn,"commandline")
					CommandLine = Mid(LineIn,Instr(LineIn," ")+1)
					
					Continue
					
				'joint count
				ElseIf Instr(LineIn,"numJoints")
					NumJoints = Int(Mid(LineIn,Instr(LineIn," ")+1))
					
					'check we have joints
					If NumJoints > 0
						BaseSkel = BaseSkel[..NumJoints]
					EndIf
					
					Continue
					
				'mesh count
				ElseIf Instr(LineIn,"numMeshes")
					NumMeshes = Int(Mid(LineIn,Instr(LineIn," ")+1))
					
					'check we have meshes
					If NumMeshes > 0
						Meshes = Meshes[..NumMeshes]
					EndIf
					
					Continue
					
				'read joints
				ElseIf Instr(LineIn,"joints {")
					For i:Int = 0 Until NumJoints
						'read joint data
						LineIn = ReadLine(FileIn)
						LineIn = Mid(LineIn,Instr(LineIn,Chr(34))+1)
						
						ParseIndex[0] = Instr(LineIn,Chr(34))
						
						'name
						BaseSkel[i] = New MD5_Joint
						BaseSkel[i].Name = Mid(LineIn,1,ParseIndex[0]-1)
						
						'parent
						LineIn = Mid(LineIn,ParseIndex[0]+1)
						ParseIndex[0] = Instr(LineIn,"(")
						
						BaseSkel[i].Parent = Int(Replace(Mid(LineIn,1,ParseIndex[0]-1)," ",""))
						
						'position
						LineIn = Mid(LineIn,ParseIndex[0]+1)
						ParseIndex[0] = Instr(LineIn,")")
						
						Local TmpLineIn:String
						Local TmpParseFinished:Int
						
						TmpLineIn = Mid(LineIn,1,ParseIndex[0]-1)
						LineIn = Mid(LineIn,ParseIndex[0]+3)
						
						For Local h:Int = 0 To 2
							TmpParseFinished = False
							
							For Local o:Int = 1 To Len(TmpLineIn)
								If Mid(TmpLineIn,o,1) <> " "
									ParseIndex[0] = o
									
									For o = ParseIndex[0]+1 To Len(TmpLineIn)
										If Mid(TmpLineIn,o,1) = " "
											ParseIndex[1] = o-1
											
											BaseSkel[i].Pos2[h] = Float(Mid(TmpLineIn,ParseIndex[0],ParseIndex[1]))
											
											TmpLineIn = Mid(TmpLineIn,ParseIndex[1]+1)
											TmpParseFinished = True
											
											Exit
										EndIf
									Next
								EndIf
								
								If TmpParseFinished Then Exit
							Next
						Next
						
						BaseSkel[i].Pos.x = BaseSkel[i].Pos2[0]
						BaseSkel[i].Pos.y = BaseSkel[i].Pos2[1]
						BaseSkel[i].Pos.z = BaseSkel[i].Pos2[2]
						
						TmpLineIn = Mid(LineIn,1,Instr(LineIn,")")-1)
						
						'orientation
						For h:Int = 0 To 2
							TmpParseFinished = False
							
							For o:Int = 1 To Len(TmpLineIn)
								If Mid(TmpLineIn,o,1) <> " "
									ParseIndex[0] = o
									
									For o = ParseIndex[0]+1 To Len(TmpLineIn)
										If Mid(TmpLineIn,o,1) = " "
											ParseIndex[1] = o-1
											
											BaseSkel[i].Orient.Val[h] = Float(Mid(TmpLineIn,ParseIndex[0],ParseIndex[1]))
											
											TmpLineIn = Mid(TmpLineIn,ParseIndex[1]+1)
											TmpParseFinished = True
											
											Exit
										EndIf
									Next
								EndIf
								
								If TmpParseFinished Then Exit
							Next
						Next
						
						BaseSkel[i].Orient.ComputeW(BaseSkel[i].Orient)
					Next
					
					Continue
					
				'read meshes
				ElseIf Instr(LineIn,"mesh {")
						'read mesh data
						Meshes[CurrMesh] = New MD5_Mesh
						
						'shader
						LineIn = ReadLine(FileIn)
						
						If Instr(LineIn,"//")
							LineIn = ReadLine(FileIn)
						EndIf
						
						LineIn = Mid(LineIn,Instr(LineIn,Chr(34))+1)
						
						Meshes[CurrMesh].Shader = Replace(LineIn,Chr(34),"")
						
						LineIn = ReadLine(FileIn)
						
						'verts
						LineIn = ReadLine(FileIn)
						LineIn = Mid(LineIn,Instr(LineIn,"numverts")+9)
						
						Meshes[CurrMesh].NumVerts = Int(LineIn)
						
						'check we have verts
						If Meshes[CurrMesh].NumVerts > 0
							Meshes[CurrMesh].Vertices = Meshes[CurrMesh].Vertices[..Meshes[CurrMesh].NumVerts]
						EndIf
						
						For h:Int = 0 Until Meshes[CurrMesh].NumVerts
							LineIn = ReadLine(FileIn)
							
							ParseIndex[0] = Instr(LineIn,".")
							ParseIndex[1] = Instr(LineIn,".",ParseIndex[0]+1)
							
							TmpLineIn = Mid(LineIn,ParseIndex[0]-1)
							ParseIndex[1] = Instr(TmpLineIn,".",3)
							
							Meshes[CurrMesh].Vertices[h] = New MD5_Vertex
							Meshes[CurrMesh].Vertices[h].St[0] = Float(Mid(TmpLineIn,1,ParseIndex[1]-2))
							
							TmpLineIn = Mid(TmpLineIn,ParseIndex[1]-1)
							ParseIndex[0] = Instr(TmpLineIn,")")
							
							Meshes[CurrMesh].Vertices[h].St[1] = Float(Mid(TmpLineIn,1,ParseIndex[0]-2))
							
							TmpLineIn = Mid(TmpLineIn,ParseIndex[0]+2)
							ParseIndex[1] = Instr(TmpLineIn," ")
							
							Meshes[CurrMesh].Vertices[h].Start = Int(Mid(TmpLineIn,1,ParseIndex[1]-1))
							Meshes[CurrMesh].Vertices[h].Count = Int(Mid(TmpLineIn,ParseIndex[1]+1))
							
							Meshes[CurrMesh].Vertices[h].Normal = New Vector3
						Next
						
						LineIn = ReadLine(FileIn)
						
						'tris
						LineIn = ReadLine(FileIn)
						LineIn = Mid(LineIn,Instr(LineIn,"numtris")+8)
						Meshes[CurrMesh].NumTris = Int(LineIn)
						
						'check we have tris
						If Meshes[CurrMesh].NumTris > 0
							Meshes[CurrMesh].VertexIndices = Meshes[CurrMesh].VertexIndices[..Meshes[CurrMesh].NumTris*3]
							Meshes[CurrMesh].Triangles = Meshes[CurrMesh].Triangles[..Meshes[CurrMesh].NumTris]
						EndIf
						
						For h:Int = 0 Until Meshes[CurrMesh].NumTris
							LineIn = ReadLine(FileIn)
							
							Meshes[CurrMesh].Triangles[h] = New MD5_Triangle
							
							LineIn = Mid(LineIn,Instr(LineIn,"tri ")+5)
							
							ParseIndex[0] = Instr(LineIn," ")
							LineIn = Mid(LineIn,ParseIndex[0]+1)
							
							ParseIndex[0] = Instr(LineIn," ")
							Meshes[CurrMesh].Triangles[h].Index[0] = Int(Mid(LineIn,1,ParseIndex[0]+1))
							
							LineIn = Mid(LineIn,ParseIndex[0]+1)
							
							ParseIndex[0] = Instr(LineIn," ")
							Meshes[CurrMesh].Triangles[h].Index[1] = Int(Mid(LineIn,1,ParseIndex[0]-1))
							
							LineIn = Mid(LineIn,ParseIndex[0]+1)
							
							Meshes[CurrMesh].Triangles[h].Index[2] = Int(LineIn)
						Next
						
						LineIn = ReadLine(FileIn)
						
						'weights
						LineIn = ReadLine(FileIn)
						LineIn = Mid(LineIn,Instr(LineIn,"numweights")+11)
						Meshes[CurrMesh].NumWeights = Int(LineIn)
						
						'check we have weights
						If Meshes[CurrMesh].NumWeights > 0
							Meshes[CurrMesh].Weights = Meshes[CurrMesh].Weights[..Meshes[CurrMesh].NumWeights]
						EndIf
						
						For h:Int = 0 Until Meshes[CurrMesh].NumWeights
							LineIn = ReadLine(FileIn)
							
							Meshes[CurrMesh].Weights[h] = New MD5_Weight
							Meshes[CurrMesh].Weights[h].Pos = New Vector3
							
							LineIn = Mid(LineIn,Instr(LineIn,"weight ")+8)
							
							ParseIndex[0] = Instr(LineIn," ")
							LineIn = Mid(LineIn,ParseIndex[0]+1)
							
							ParseIndex[0] = Instr(LineIn," ")
							Meshes[CurrMesh].Weights[h].Joint = Int(Mid(LineIn,1,ParseIndex[0]-1))
							
							LineIn = Mid(LineIn,ParseIndex[0]+1)
							
							ParseIndex[0] = Instr(LineIn," ")
							Meshes[CurrMesh].Weights[h].Bias = Float(Mid(LineIn,1,ParseIndex[0]-1))
							
							ParseIndex[0] = Instr(LineIn,"(")
							LineIn = Mid(LineIn,ParseIndex[0]+1)
							
							ParseIndex[1] = Instr(LineIn,")")
							LineIn = Mid(LineIn,1,ParseIndex[1]-1)
							
							TmpLineIn = LineIn
							
							'positions
							For Local n:Int = 0 To 2
								TmpParseFinished = False
								
								For o:Int = 1 To Len(TmpLineIn)
									If Mid(TmpLineIn,o,1) <> " "
										ParseIndex[0] = o
										
										For o = ParseIndex[0]+1 To Len(TmpLineIn)
											If Mid(TmpLineIn,o,1) = " "
												ParseIndex[1] = o-1
												
												Meshes[CurrMesh].Weights[h].Pos2[n] = Float(Mid(TmpLineIn,ParseIndex[0],ParseIndex[1]))
												
												TmpLineIn = Mid(TmpLineIn,ParseIndex[1]+1)
												TmpParseFinished = True
												
												Exit
											EndIf
										Next
									EndIf
									
									If TmpParseFinished Then Exit
								Next
							Next
							
							Meshes[CurrMesh].Weights[h].Pos.x = Meshes[CurrMesh].Weights[h].Pos2[0]
							Meshes[CurrMesh].Weights[h].Pos.y = Meshes[CurrMesh].Weights[h].Pos2[1]
							Meshes[CurrMesh].Weights[h].Pos.z = Meshes[CurrMesh].Weights[h].Pos2[2]
						Next
					
					CurrMesh:+1
					
					Continue
				EndIf
			Wend
		CloseStream(FileIn)
		
		If nAnimFile
			Anim = New MD5_Anim
			AnimInfo = New MD5_AnimInfo
			
			If Not LoadAnim(nAnimFile,Anim)
				Anim = Null
				AnimInfo = Null
			Else
				AnimInfo.CurrFrame = 0.0
				AnimInfo.NextFrame = 1.0
				
				AnimInfo.LastTime = 0.0
				AnimInfo.MaxTime = 1.0/Anim.FrameRate
				
				Skeleton = Skeleton[..Anim.NumJoints]
				
				For i:Int = 0 Until Anim.NumJoints
					Skeleton[i] = New MD5_Joint
				Next
			EndIf
			
			For i:Int = 0 Until NumMeshes
				For j:Int = 0 Until Anim.NumFrames
					BuildWeightNormals(Meshes[i],Anim.SkelIndex[j])
				Next
			Next
		EndIf
		
		TurnEntity(-90.0,0.0,-90.0)
		
	End Method
	
	Method LoadAnim:Int(nFile:String,nAnim:MD5_Anim Var)
		
		Local FileIn:TStream
		Local LineIn:String
		
		Local Version:Int,CommandLine:String
		
		Local i:Int,h:Int,o:Int
		
		Local ParseIndex:Int[2]
		Local ParseLine:String[2]
		
		Local NumAnimatedComponents:Int
		
		Local BaseFrame:MD5_BaseFrameJoint[]
		Local JointInfos:MD5_JointInfo[]
		
		Local AnimFrameData:Float[]
		Local FrameIndex:Int
		
		'read file and parse data
		FileIn = OpenStream(nFile,True,False)
			While Not Eof(FileIn)
				'read line
				LineIn = ReadLine(FileIn)
				
				'skip if line is blank
				If LineIn.length = 0 Then Continue
				
				'version
				If Instr(LineIn,"MD5Version")
					Version = Int(Mid(LineIn,Instr(LineIn," ")+1))
					
					'if its not a version 10 then fail the file
					If Not Version = 10 Then Return False
					
					Continue
					
				'commandline
				ElseIf Instr(LineIn,"commandline")
					CommandLine = Mid(LineIn,Instr(LineIn," ")+1)
					
					Continue
					
				'frame count
				ElseIf Instr(LineIn,"numFrames")
					nAnim.NumFrames = Int(Mid(LineIn,Instr(LineIn," ")+1))
					nAnim.SkelIndex = nAnim.SkelIndex[..nAnim.NumFrames]
					
					'check we have frames
					If nAnim.NumFrames > 0
						For i:Int = 0 Until nAnim.NumFrames
							nAnim.SkelIndex[i] = New MD5_SkelIndex
						Next
						
						nAnim.BBoxes = nAnim.BBoxes[..nAnim.NumFrames]
					EndIf
					
					Continue
					
				'joint count
				ElseIf Instr(LineIn,"numJoints")
					nAnim.NumJoints = Int(Mid(LineIn,Instr(LineIn," ")+1))
					
					'check we have joints
					If nAnim.NumJoints > 0
						For i:Int = 0 Until nAnim.NumFrames
							nAnim.SkelIndex[i].SkelFrames = nAnim.SkelIndex[i].SkelFrames[..nAnim.NumJoints]
							
							For o:Int = 0 Until nAnim.NumJoints
								nAnim.SkelIndex[i].SkelFrames[o] = New MD5_Joint
							Next
						Next
						
						BaseFrame = BaseFrame[..nAnim.NumJoints]
						JointInfos = JointInfos[..nAnim.NumJoints]
					EndIf
					
					Continue
					
				'framerate
				ElseIf Instr(LineIn,"frameRate")
					nAnim.Framerate = Int(Mid(LineIn,Instr(LineIn," ")+1))
					
					Continue
					
				'animated components
				ElseIf Instr(LineIn,"numAnimatedComponents")
					NumAnimatedComponents = Int(Mid(LineIn,Instr(LineIn," ")+1))
					
					If NumAnimatedComponents > 0
						AnimFrameData = AnimFrameData[..NumAnimatedComponents]
					EndIf
					
					Continue
					
				'hierarchy
				ElseIf Instr(LineIn,"hierarchy {")
					'read joint info
					For i = 0 Until nAnim.NumJoints
						LineIn = ReadLine(FileIn)
						LineIn = Mid(LineIn,Instr(LineIn,Chr(34))+1)
						
						ParseIndex[0] = Instr(LineIn,Chr(34))
						
						JointInfos[i] = New MD5_JointInfo
						JointInfos[i].Name = Mid(LineIn,1,ParseIndex[0]-1)
						
						LineIn = Mid(LineIn,ParseIndex[0]+1)
						
						For o:Int = 1 To Len(LineIn)
							If Mid(LineIn,o,1) <> " "
								LineIn = Mid(LineIn,o)
								ParseIndex[0] = Instr(LineIn," ")
								
								JointInfos[i].Parent = Int(Mid(LineIn,1,ParseIndex[0]-1))
								
								LineIn = Mid(LineIn,ParseIndex[0]+1)
								ParseIndex[0] = Instr(LineIn," ")
								
								JointInfos[i].Flags = Int(Mid(LineIn,1,ParseIndex[0]-1))
								
								LineIn = Mid(LineIn,ParseIndex[0]+1)
								ParseIndex[0] = Instr(LineIn," ")
								
								JointInfos[i].StartIndex = Int(Mid(LineIn,1,ParseIndex[0]-1))
								
								Exit
							EndIf
						Next
					Next
					
					Continue
					
				'bounds
				ElseIf Instr(LineIn,"bounds {")
					'read bounding box info
					For i:Int = 0 Until nAnim.NumFrames
						nAnim.BBoxes[i] = New MD5_BBox
						
						LineIn = ReadLine(FileIn)
						
						ParseIndex[0] = Instr(LineIn,"(")
						LineIn = Mid(LineIn,ParseIndex[0]+1)
						
						For o:Int = 1 To Len(LineIn)
							If Mid(LineIn,o,1) <> " "
								LineIn = Mid(LineIn,o)
								ParseIndex[0] = Instr(LineIn," ")
								
								nAnim.BBoxes[i].BMin.x = Float(Mid(LineIn,1,ParseIndex[0]-1))
								
								LineIn = Mid(LineIn,ParseIndex[0]+1)
								ParseIndex[0] = Instr(LineIn," ")
								
								nAnim.BBoxes[i].BMin.y = Float(Mid(LineIn,1,ParseIndex[0]-1))
								
								LineIn = Mid(LineIn,ParseIndex[0]+1)
								ParseIndex[0] = Instr(LineIn,")")
								
								nAnim.BBoxes[i].BMin.z = Float(Mid(LineIn,1,ParseIndex[0]-2))
								
								ParseIndex[0] = Instr(LineIn,"(")
								LineIn = Mid(LineIn,ParseIndex[0]+1)
								
								Exit
							EndIf
						Next
						
						For o:Int = 1 To Len(LineIn)
							If Mid(LineIn,o,1) <> " "
								LineIn = Mid(LineIn,o)
								ParseIndex[0] = Instr(LineIn," ")
								
								nAnim.BBoxes[i].BMax.x = Float(Mid(LineIn,1,ParseIndex[0]-1))
								
								LineIn = Mid(LineIn,ParseIndex[0]+1)
								ParseIndex[0] = Instr(LineIn," ")
								
								nAnim.BBoxes[i].BMax.y = Float(Mid(LineIn,1,ParseIndex[0]-1))
								
								LineIn = Mid(LineIn,ParseIndex[0]+1)
								ParseIndex[0] = Instr(LineIn,")")
								
								nAnim.BBoxes[i].BMax.z = Float(Mid(LineIn,1,ParseIndex[0]-1))
								
								Exit
							EndIf
						Next
					Next
					
					Continue
					
				'baseframe
				ElseIf Instr(LineIn,"baseframe {")
					For i = 0 Until nAnim.NumJoints
						'read base frame joint
						BaseFrame[i] = New MD5_BaseFrameJoint
						
						LineIn = ReadLine(FileIn)
						
						'pos
						ParseIndex[0] = Instr(LineIn,"(")
						
						LineIn = Mid(LineIn,ParseIndex[0]+2)
						ParseIndex[0] = Instr(LineIn," ")
						BaseFrame[i].Pos.x = Float(Mid(LineIn,1,ParseIndex[0]-1))
						
						LineIn = Mid(LineIn,ParseIndex[0]+1)
						ParseIndex[0] = Instr(LineIn," ")
						BaseFrame[i].Pos.y = Float(Mid(LineIn,1,ParseIndex[0]-1))
						
						LineIn = Mid(LineIn,ParseIndex[0]+1)
						ParseIndex[0] = Instr(LineIn," ")
						BaseFrame[i].Pos.z = Float(Mid(LineIn,1,ParseIndex[0]-1))
						
						'orient
						ParseIndex[0] = Instr(LineIn,"(")
						
						LineIn = Mid(LineIn,ParseIndex[0]+2)
						ParseIndex[0] = Instr(LineIn," ")
						BaseFrame[i].Orient.Val[0] = Float(Mid(LineIn,1,ParseIndex[0]-1))
						
						LineIn = Mid(LineIn,ParseIndex[0]+1)
						ParseIndex[0] = Instr(LineIn," ")
						BaseFrame[i].Orient.Val[1] = Float(Mid(LineIn,1,ParseIndex[0]-1))
						
						LineIn = Mid(LineIn,ParseIndex[0]+1)
						ParseIndex[0] = Instr(LineIn," ")
						BaseFrame[i].Orient.Val[2] = Float(Mid(LineIn,1,ParseIndex[0]-1))
						
						BaseFrame[i].Orient.ComputeW(BaseFrame[i].Orient)
					Next
					
					Continue
					
				'frames
				ElseIf Instr(LineIn,"frame ")
					FrameIndex = Int(Mid(LineIn,Instr(LineIn," ")+1))
					
					AnimFrameData = AnimFrameData[..NumAnimatedComponents]
					
					'read frame data
					Local k:Int = 0
					
					Repeat
						LineIn = ReadLine(FileIn)
						If Instr(LineIn,"}") Then Exit
						
						ParseLine[0]:+LineIn
					Forever
					
					ParseLine[0] = Replace(ParseLine[0]," ","|")
					
					For i:Int = 0 Until NumAnimatedComponents
						ParseIndex[0] = Instr(ParseLine[0],"|")
						ParseLine[0] = Mid(ParseLine[0],ParseIndex[0]+1)
						
						ParseIndex[0] = Instr(ParseLine[0],"|")
						ParseLine[1] = Mid(ParseLine[0],1,ParseIndex[0]-1)
						
						ParseLine[1] = Replace(ParseLine[1]," ","")
						AnimFrameData[i] = Float(ParseLine[1])
					Next
					
					BuildFrameSkeleton(JointInfos,BaseFrame,AnimFrameData,..
									   nAnim.SkelIndex[FrameIndex].SkelFrames,nAnim.NumJoints)
					
					Continue
				EndIf
			Wend
		CloseStream(FileIn)
		
		If ValidateAnim() = False Then Return False
		
		Return True
		
	End Method
	
	Method ValidateAnim:Int()
		
		Local i:Int
		
		'check joints
		If Not NumJoints = Anim.NumJoints
			Return False
		EndIf
		
		'check frames
		For i:Int = 0 Until NumJoints
			'joints must have same parent index
			If BaseSkel[i].Parent <> Anim.SkelIndex[0].SkelFrames[i].Parent
				Return False
			EndIf
			
			'joints must have same name
			If BaseSkel[i].Name <> Anim.SkelIndex[0].SkelFrames[i].Name
				Return False
			EndIf
		Next
		
		Return True
		
	End Method
	
	Method Draw()
		
		If Anim
			'Animate(Anim,Varptr AnimInfo,(CurrTime-LastTime))
			
	      	InterpolateSkeletons(Anim.SkelIndex[AnimInfo.CurrFrame],..
				    			 Anim.SkelIndex[AnimInfo.NextFrame],..
				    			 Anim.NumJoints,..
				    			 AnimInfo.LastTime*Anim.FrameRate,..
				    			 Skeleton)
		Else
			Skeleton = BaseSkel
		EndIf
		
		'draw skeleton
		'DrawSkeleton(Skeleton,NumJoints)
		
		'draw model
		Local nTexEnabled:Byte = glIsEnabled(GL_TEXTURE_2D)
		
		Local nVertexArrayEnabled:Byte = glIsEnabled(GL_VERTEX_ARRAY)
		Local nNormalArrayEnabled:Byte = glIsEnabled(GL_NORMAL_ARRAY)
		Local nTextureArrayEnabled:Byte = glIsEnabled(GL_TEXTURE_COORD_ARRAY)
		
		glFrontFace(GL_CW)
		
		If Not nVertexArrayEnabled Then glEnableClientState(GL_VERTEX_ARRAY)
		If Not nNormalArrayEnabled Then glEnableClientState(GL_NORMAL_ARRAY)
		If Not nTextureArrayEnabled Then glEnableClientState(GL_TEXTURE_COORD_ARRAY)
		
		If Not nTexEnabled Then glEnable(GL_TEXTURE_2D)
		
		For Local i:Int = 0 Until NumMeshes
			PrepareMesh(Meshes[i],Skeleton)
			
			glVertexPointer(3,GL_FLOAT,0,Meshes[i].VertexBuffer)
			glNormalPointer(GL_FLOAT,0,Meshes[i].NormalBuffer)
			glTexCoordPointer(2,GL_FLOAT,0,Meshes[i].TextureBuffer)
			
			glDrawElements(GL_TRIANGLES,Meshes[i].NumTris*3,GL_UNSIGNED_INT,Meshes[i].VertexIndices)
		Next
		
		If Not nTexEnabled Then glDisable(GL_TEXTURE_2D)
		
		If Not nVertexArrayEnabled Then glDisableClientState(GL_VERTEX_ARRAY)
		If Not nNormalArrayEnabled Then glDisableClientState(GL_NORMAL_ARRAY)
		If Not nTextureArrayEnabled Then glDisableClientState(GL_TEXTURE_COORD_ARRAY)
		
	End Method

	Method DrawSkeleton(Joints:MD5_Joint[],nNumJoints:Int)
		
		Local i:Int
		
		'draw each bone
		glDisable(GL_LIGHTING)
		glColor3f(1.0,1.0,1.0)
		
		glBegin(GL_LINES)
			For i:Int = 0 Until nNumJoints
				If Joints[i].Parent > -1
					glVertex3f(Joints[Joints[i].Parent].Pos.x,Joints[Joints[i].Parent].Pos.y,Joints[Joints[i].Parent].Pos.z)
					glVertex3f(Joints[i].Pos.x,Joints[i].Pos.y,Joints[i].Pos.z)
				EndIf
			Next
		glEnd()
		
		glEnable(GL_LIGHTING)
		glColor3f(1.0,1.0,1.0)
		
	End Method
	
	Method BuildFrameSkeleton(nJointInfos:MD5_JointInfo[],nBaseFrame:MD5_BaseFrameJoint[],..
							  nFrameData:Float[],nSkelFrame:MD5_Joint[] Var,..
							  nNumJoints:Int)
		
		Local i:Int
		
		For i:Int = 0 Until nNumJoints
			Local BaseJoint:MD5_BaseFrameJoint Ptr
			BaseJoint = Varptr nBaseFrame[i]
			
			Local AnimatedPos:Vector3 = New Vector3
			Local AnimatedOrient:Quat_Class = New Quat_Class
			
			Local j:Int = 0
			
			AnimatedPos.x = BaseJoint[0].Pos.x
			AnimatedPos.y = BaseJoint[0].Pos.y
			AnimatedPos.z = BaseJoint[0].Pos.z
			
			AnimatedOrient.Val[0] = BaseJoint[0].Orient.Val[0]
			AnimatedOrient.Val[1] = BaseJoint[0].Orient.Val[1]
			AnimatedOrient.Val[2] = BaseJoint[0].Orient.Val[2]
			AnimatedOrient.Val[3] = BaseJoint[0].Orient.Val[3]
			
			If nJointInfos[i].Flags & 1'Tx
				AnimatedPos.x = nFrameData[nJointInfos[i].StartIndex+j]
				j:+1
			EndIf
			
			If nJointInfos[i].Flags & 2'Ty
				AnimatedPos.y = nFrameData[nJointInfos[i].StartIndex+j]
				j:+1
			EndIf
			
			If nJointInfos[i].Flags & 4'Tz
				AnimatedPos.z = nFrameData[nJointInfos[i].StartIndex+j]
				j:+1
			EndIf
			
			If nJointInfos[i].Flags & 8'Qx
				AnimatedOrient.Val[0] = nFrameData[nJointInfos[i].StartIndex+j]
				j:+1
			EndIf
			
			If nJointInfos[i].Flags & 16'Qy
				AnimatedOrient.Val[1] = nFrameData[nJointInfos[i].StartIndex+j]
				j:+1
			EndIf
			
			If nJointInfos[i].Flags & 32'Qz
				AnimatedOrient.Val[2] = nFrameData[nJointInfos[i].StartIndex+j]
				j:+1
			EndIf
			
			'compute orient w val
			AnimatedOrient.ComputeW(AnimatedOrient)
			
			Local ThisJoint:MD5_Joint Ptr
			ThisJoint = Varptr nSkelFrame[i]
			
			Local Parent:Int = nJointInfos[i].Parent
			
			ThisJoint[0].Parent = Parent
			ThisJoint[0].Name = nJointInfos[i].Name
			
			'has parent?
			If ThisJoint[0].Parent < 0
				ThisJoint[0].Pos.x = AnimatedPos.x
				ThisJoint[0].Pos.y = AnimatedPos.y
				ThisJoint[0].Pos.z = AnimatedPos.z
				
				ThisJoint[0].Orient.Val[0] = AnimatedOrient.Val[0]
				ThisJoint[0].Orient.Val[1] = AnimatedOrient.Val[1]
				ThisJoint[0].Orient.Val[2] = AnimatedOrient.Val[2]
				ThisJoint[0].Orient.Val[3] = AnimatedOrient.Val[3]
			Else
				Local ParentJoint:MD5_Joint Ptr
				ParentJoint = Varptr nSkelFrame[Parent]
				
				Local RPos:Vector3 = New Vector3
				ThisJoint[0].Orient.RotatePoint(ParentJoint[0].Orient,AnimatedPos,Rpos)
				
				ThisJoint[0].Pos.x = RPos.x+ParentJoint[0].Pos.x
				ThisJoint[0].Pos.y = RPos.y+ParentJoint[0].Pos.y
				ThisJoint[0].Pos.z = RPos.z+ParentJoint[0].Pos.z
				
				ThisJoint[0].Orient.MultQuat(AnimatedOrient,ParentJoint[0].Orient,ThisJoint[0].Orient)
				ThisJoint[0].Orient.Normalize(ThisJoint[0].Orient)
			EndIf
		Next
		
	End Method
	
	Method BuildWeightNormals(nMesh:MD5_Mesh,nSkelFrame:MD5_SkelIndex)
		
		Local BindPoseVerts:Vector3[nMesh.NumVerts]
		Local BindPoseNorms:Vector3[nMesh.NumVerts]
		
		Local pWeight:MD5_Weight
		Local pJoint:MD5_Joint
		
		Local WV:Vector3 = New Vector3
		
		For Local i:Int = 0 Until nMesh.NumVerts
			For Local j:Int = 0 Until nMesh.Vertices[i].Count
				pWeight = nMesh.Weights[nMesh.Vertices[i].Start+j]
				pJoint = nSkelFrame.SkelFrames[pWeight.Joint]
				
				WV.x = pWeight.Pos.x
				WV.y = pWeight.Pos.y
				WV.z = pWeight.Pos.z
				
				BindPoseVerts[i] = New Vector3
				BindPoseNorms[i] = New Vector3
				
				BindPoseVerts[i].x:+(pJoint.Pos.x+WV.x)*pWeight.Bias
				BindPoseVerts[i].y:+(pJoint.Pos.y+WV.y)*pWeight.Bias
				BindPoseVerts[i].z:+(pJoint.Pos.z+WV.z)*pWeight.Bias
			Next
		Next
		
		'tri normals
		Local pTri:MD5_Triangle
		Local TriNorm:Vector3 = New Vector3
		
		For i:Int = 0 Until nMesh.NumTris
			pTri = nMesh.Triangles[i]
			
			TriNorm.ComputeNormal(TriNorm,BindPoseVerts[pTri.Index[0]],..
										  BindPoseVerts[pTri.Index[1]],..
										  BindPoseVerts[pTri.Index[2]])
			
			
			For j:Int = 0 Until 3
				BindPoseNorms[pTri.Index[j]].x:+TriNorm.x
				BindPoseNorms[pTri.Index[j]].y:+TriNorm.y
				BindPoseNorms[pTri.Index[j]].z:+TriNorm.z
			Next
		Next
		
		'average surface normals
		For i = 0 Until nMesh.NumVerts
			BindPoseNorms[i].Normalize()
			
			nMesh.Vertices[i].Normal.x = BindPoseNorms[i].x
			nMesh.Vertices[i].Normal.y = BindPoseNorms[i].y
			nMesh.Vertices[i].Normal.z = BindPoseNorms[i].z
		Next
		
		Rem
		Local InvRot:Quat_Class = New Quat_Class
		Local WN:Vector3
		
		'compute weight normals by invert-transforming the normal
		For i:Int = 0 Until nMesh.NumVerts
			For i:Int = 0 Until nMesh.Vertices[i].Count
				pWeight = nMesh.Weights[nMesh.Vertices[i].Start+j]
				pJoint = nSkelFrame.SkelFrames[pWeight.Joint]
				
				WN = BindPoseNorms[i]
				
				'compute inverse quat rotation
				'InvRot = 
				'InvRot.RotateVec(WV)
				'WN.RotVec(WN)
				
				pWeight.Normal.x:+WN.x
				pWeight.Normal.y:+WN.y
				pWeight.Normal.z:+WN.z
			Next
		Next
		
		'normalize all weight normals
		For i:Int = 0 Until nMesh.NumWeights
			nMesh.Weights[i].Normal.Normalize()
			
			nMesh.NormalBuffer[vbi] = nMesh.Weights[i].Normal.x'BindPoseNorms[i].x
			nMesh.NormalBuffer[vbi+1] = nMesh.Weights[i].Normal.y'BindPoseNorms[i].y
			nMesh.NormalBuffer[vbi+2] = nMesh.Weights[i].Normal.z'BindPoseNorms[i].z
			vbi:+3
		Next
		EndRem
		
		pWeight = Null
		pJoint = Null
		
		WV = Null
		
		BindPoseVerts = Null
		BindPoseNorms = Null
		
	End Method
	
	Method InterpolateSkeletons(SkelA:MD5_SkelIndex,SkelB:MD5_SkelIndex,nNumJoints:Int,Interp:Float,..
								SkelOut:MD5_Joint[] Var)
	
		Local i:Int
		
		For i = 0 Until nNumJoints
			'copy parent index
			SkelOut[i].Parent = SkelA.SkelFrames[i].Parent
			
			'linear interpolation (position)
			SkelOut[i].Pos.x = SkelA.SkelFrames[i].Pos.x+Interp*(SkelB.SkelFrames[i].Pos.x-SkelA.SkelFrames[i].Pos.x)
			SkelOut[i].Pos.y = SkelA.SkelFrames[i].Pos.y+Interp*(SkelB.SkelFrames[i].Pos.y-SkelA.SkelFrames[i].Pos.y)
			SkelOut[i].Pos.z = SkelA.SkelFrames[i].Pos.z+Interp*(SkelB.SkelFrames[i].Pos.z-SkelA.SkelFrames[i].Pos.z)
			
			'spherical linear interpolation (orientation)
			SkelOut[i].Orient.Slerp(SkelA.SkelFrames[i].Orient,SkelB.SkelFrames[i].Orient,Interp,SkelOut[i].Orient)
		Next
		
	End Method
	
	Method Animate(nAnim:MD5_Anim,nAnimInfo:MD5_AnimInfo Ptr,dt:Double)
		
		Local MaxFrames:Int = nAnim.NumFrames-1
		
		nAnimInfo[0].Lasttime:+dt
		
		'move to next frame
		If nAnimInfo[0].Lasttime >= nAnimInfo[0].MaxTime
			nAnimInfo[0].CurrFrame:+1
			nAnimInfo[0].NextFrame:+1
			nAnimInfo[0].LastTime = 0.0
		EndIf
		
		If nAnimInfo[0].CurrFrame > MaxFrames
			nAnimInfo[0].CurrFrame = 0
		ElseIf nAnimInfo[0].NextFrame > MaxFrames
			nAnimInfo[0].NextFrame = 0
		EndIf
		
	End Method
	
	Method PrepareMesh(nMesh:MD5_Mesh,nJoint:MD5_Joint[])
		
		Local i:Int,j:Int,k:Int
		
		'setup vertex indices
		For i = 0 Until nMesh.NumTris
			For j = 0 Until 3
				nMesh.VertexIndices[k] = nMesh.Triangles[i].Index[j]
				k:+1
			Next
		Next
		
		Local vbi:Int,tbi:Int
		
		'setup vertices
		nMesh.VertexBuffer = nMesh.VertexBuffer[..nMesh.NumVerts*3]
		nMesh.NormalBuffer = nMesh.NormalBuffer[..nMesh.NumVerts*3]
		nMesh.TextureBuffer = nMesh.TextureBuffer[..nMesh.NumVerts*2]
		
		For i = 0 Until nMesh.NumVerts
			Local FinalVertex:Vector3 = Vector3.Create(0.0,0.0,0.0)
			
			'calculate final vertex to draw with weights
			For j = 0 Until nMesh.Vertices[i].Count
				Local nWeight:MD5_Weight Ptr
				nWeight = Varptr nMesh.Weights[nMesh.Vertices[i].Start+j]
				
				Local nJoint2:MD5_Joint Ptr
				nJoint2 = Varptr nJoint[nWeight[0].Joint]
				
				Local WV:Vector3 = New Vector3
				nJoint2[0].Orient.RotatePoint(nJoint2[0].Orient,nWeight[0].Pos,WV)
				
				'sum of all weight bias should be 1.0
				FinalVertex.x :+ (nJoint2[0].Pos.x+WV.x)*nWeight[0].Bias
				FinalVertex.y :+ (nJoint2[0].Pos.y+WV.y)*nWeight[0].Bias
				FinalVertex.z :+ (nJoint2[0].Pos.z+WV.z)*nWeight[0].Bias
			Next
			
			nMesh.Vertices[i].xyz[0] = FinalVertex.x
			nMesh.Vertices[i].xyz[1] = FinalVertex.y
			nMesh.Vertices[i].xyz[2] = FinalVertex.z
			
			nMesh.VertexBuffer[vbi] = FinalVertex.x
			nMesh.VertexBuffer[vbi+1] = FinalVertex.y
			nMesh.VertexBuffer[vbi+2] = FinalVertex.z
			
			nMesh.NormalBuffer[vbi] = nMesh.Vertices[i].Normal.x
			nMesh.NormalBuffer[vbi+1] = nMesh.Vertices[i].Normal.y
			nMesh.NormalBuffer[vbi+2] = nMesh.Vertices[i].Normal.z
			
			nMesh.TextureBuffer[tbi] = nMesh.Vertices[i].St[0]
			nMesh.TextureBuffer[tbi+1] = nMesh.Vertices[i].St[1]
			
			tbi:+2
			vbi:+3
			
			FinalVertex = Null
			WV = Null
		Next
		
	End Method
End Type



Thanks!!!

sorry its a bit big:)

tye a codebox instead of code