
The MD2 (Quake 2 model format) is a boneless per frame (mesh) animated 3d model format
introduced in November 1997 by id Software for the Quake 2 game.
Frame based animations are faster than bone based animations (nowdays there is a comeback with blendshapes and shaders).
Bones however can still be used to create animations for MD2 models (they just wont get exported).
The MD2 model format is one of the simplest 3d model formats.
It is still useful ex. for a top down strategy games.
About Quake 2: https://en.wikipedia.org/wiki/Quake_II
Example model from ZDoom (doomguy.md2):

Update 19.02.2023:
- md2Animation() & md2Mesh() now make use of the frame_size variable as it is intended (i calculated it before for no reason)
Update 20.02.2023:
- Added Example load & animate (maybe there is a better way with submeshes...)
The Library (pb3d_md2.pb):
Code: Select all
EnableExplicit
;---------------------------------------------------------------
;Quake 2 (id Tech 2) MD2 (Version 8) model loader for Ogre
;https://github.com/id-Software/Quake-2
;---------------------------------------------------------------
;File: DLL - pb3d_md2.pb
;---------------------------------------------------------------
;Version: alpha
;Author: Mijikai
;License: GPL 2.0
;---------------------------------------------------------------
;Limitation: no support for MD2 commands!
;---------------------------------------------------------------
;MD2 format limits (for 3d modeling):
;- Skins: 32
;- Triangles: 4096
;- Vertices: 2048
;- Texels: 2048
;- Frames: 512
;---------------------------------------------------------------
Structure MD2_TRIANGLE
v.w[3]
st.w[3]
EndStructure
Structure MD2_VERTEX
v.a[3]
n.a
EndStructure
Structure MD2_TEXEL
s.w
t.w
EndStructure
Structure MD2_VECTOR
x.f
y.f
z.f
EndStructure
Structure MD2_FRAME
scale.MD2_VECTOR
translate.MD2_VECTOR
name.a[16]
vertex.MD2_VERTEX[0]
EndStructure
Structure MD2_SKIN
name.a[64]
EndStructure
Structure MD2
magic.l
version.l
skin_width.l
skin_height.l
frame_size.l
num_skins.l
num_vertice.l
num_texels.l
num_triangles.l
num_commands.l
num_frames.l
offset_skins.l
offset_texels.l
offset_triangles.l
offset_frames.l
offset_commands.l
offset_end.l
EndStructure
Structure LDR_COORD
x.f
y.f
EndStructure
Structure LDR_ACCESS
StructureUnion
indice.MD2_TRIANGLE[0]
coord.MD2_TEXEL[0]
index.MD2_VECTOR[0]
EndStructureUnion
EndStructure
#MD2_HEADER_MAGIC = $32504449
#MD2_HEADER_VERSION = 8
#LDR_MD2_VERSION = $000001
ProcedureDLL.i md2Open(File.s,*Buffer.MD2)
Protected *md2.MD2
Protected hfile.i
Protected bytes.i
If *Buffer
If *Buffer\magic = #MD2_HEADER_MAGIC And *Buffer\version = #MD2_HEADER_VERSION
bytes = *Buffer\offset_end
If bytes > SizeOf(MD2)
*md2 = AllocateMemory(bytes)
If *md2
CopyMemory(*Buffer,*md2,bytes)
EndIf
EndIf
EndIf
ElseIf File
hfile = ReadFile(#PB_Any,File)
If IsFile(hfile)
bytes = Lof(hfile)
If bytes > SizeOf(MD2)
*md2 = AllocateMemory(bytes)
If *md2
If ReadData(hfile,*md2,bytes) = bytes
If *md2\magic <> #MD2_HEADER_MAGIC Or *md2\version <> #MD2_HEADER_VERSION
FreeMemory(*md2)
*md2 = #Null
EndIf
Else
FreeMemory(*md2)
*md2 = #Null
EndIf
EndIf
EndIf
CloseFile(hfile)
EndIf
EndIf
ProcedureReturn *md2
EndProcedure
ProcedureDLL.i md2Texture(*md2.MD2,Index.i,*Texture)
Protected *skin.MD2_SKIN
Protected name.s
With *md2
If Index < \num_skins And *Texture
*skin = *md2 + \offset_skins + (Index * SizeOf(MD2_SKIN))
name = PeekS(@*skin\name[0],64,#PB_Ascii)
CopyMemory(@name,*Texture,128)
EndIf
ProcedureReturn \num_skins
EndWith
EndProcedure
ProcedureDLL.i md2Animation(*md2.MD2,Index.i,*Animation)
Protected *frame.MD2_FRAME
Protected name.s
With *md2
If Index < \num_frames And *Animation
*frame = *md2 + \offset_frames + (Index * \frame_size)
name = PeekS(@*frame\name[0],16,#PB_Ascii)
CopyMemory(@name,*Animation,32)
EndIf
ProcedureReturn \num_frames
EndWith
EndProcedure
ProcedureDLL.i md2Info(*md2.MD2,*Meshes.Integer,*Faces.Integer,*Indice.Integer,*Mode.Integer)
With *md2
If *Meshes
*Meshes\i = \num_frames
EndIf
If *Faces
*Faces\i = \num_triangles
EndIf
If *Indice
*Indice\i = 3
EndIf
If *Mode
*Mode\i = #PB_Mesh_TriangleList
EndIf
ProcedureReturn #Null
EndWith
EndProcedure
ProcedureDLL.i md2Mesh(*md2.MD2,Mesh.i,Face.i,Index.i,Blend.f,*TextureCoord.LDR_COORD,*Normal.MD2_VECTOR,*Vertex.MD2_VECTOR)
Protected *tex.LDR_ACCESS
Protected *nor.LDR_ACCESS
Protected *tri.LDR_ACCESS
Protected *frame1.MD2_FRAME
Protected *frame2.MD2_FRAME
Protected vn1.MD2_VECTOR
Protected vn2.MD2_VECTOR
Protected vt1.MD2_VECTOR
Protected vt2.MD2_VECTOR
With *md2
*tex = *md2 + \offset_texels
*nor = ?md2normals
*tri = *md2 + \offset_triangles
*frame1 = *md2 + \offset_frames + (Mesh * \frame_size)
Mesh + 1
*frame2 = *md2 + \offset_frames + (Mesh * \frame_size)
If Blend And Mesh < \num_frames
*TextureCoord\x = *tex\coord[*tri\indice[Face]\st[Index]]\s / \skin_width
*TextureCoord\y = *tex\coord[*tri\indice[Face]\st[Index]]\t / \skin_height
vn1\x = *nor\index[*frame1\vertex[*tri\indice[Face]\v[Index]]\n]\x
vn1\y = *nor\index[*frame1\vertex[*tri\indice[Face]\v[Index]]\n]\y
vn1\z = *nor\index[*frame1\vertex[*tri\indice[Face]\v[Index]]\n]\z
vn2\x = *nor\index[*frame2\vertex[*tri\indice[Face]\v[Index]]\n]\x
vn2\y = *nor\index[*frame2\vertex[*tri\indice[Face]\v[Index]]\n]\y
vn2\z = *nor\index[*frame2\vertex[*tri\indice[Face]\v[Index]]\n]\z
vn1\x = vn1\x + Blend * (vn2\x - vn1\x)
vn1\y = vn1\y + Blend * (vn2\y - vn1\y)
vn1\z = vn1\z + Blend * (vn2\z - vn1\z)
vt1\x = (*frame1\vertex[*tri\indice[Face]\v[Index]]\v[0] * *frame1\scale\x) + *frame1\translate\x
vt1\y = (*frame1\vertex[*tri\indice[Face]\v[Index]]\v[1] * *frame1\scale\y) + *frame1\translate\y
vt1\z = (*frame1\vertex[*tri\indice[Face]\v[Index]]\v[2] * *frame1\scale\z) + *frame1\translate\z
vt2\x = (*frame2\vertex[*tri\indice[Face]\v[Index]]\v[0] * *frame2\scale\x) + *frame2\translate\x
vt2\y = (*frame2\vertex[*tri\indice[Face]\v[Index]]\v[1] * *frame2\scale\y) + *frame2\translate\y
vt2\z = (*frame2\vertex[*tri\indice[Face]\v[Index]]\v[2] * *frame2\scale\z) + *frame2\translate\z
vt1\x = vt1\x + Blend * (vt2\x - vt1\x)
vt1\y = vt1\y + Blend * (vt2\y - vt1\y)
vt1\z = vt1\z + Blend * (vt2\z - vt1\z)
*Normal\x = vn1\x
*Normal\y = vn1\y
*Normal\z = vn1\z
*Vertex\x = vt1\x
*Vertex\y = vt1\y
*Vertex\z = 1.0 - vt1\z
Else
*TextureCoord\x = *tex\coord[*tri\indice[Face]\st[Index]]\s / \skin_width
*TextureCoord\y = *tex\coord[*tri\indice[Face]\st[Index]]\t / \skin_height
*Normal\x = *nor\index[*frame1\vertex[*tri\indice[Face]\v[Index]]\n]\x
*Normal\x = *nor\index[*frame1\vertex[*tri\indice[Face]\v[Index]]\n]\y
*Normal\z = *nor\index[*frame1\vertex[*tri\indice[Face]\v[Index]]\n]\z
*Vertex\x = (*frame1\vertex[*tri\indice[Face]\v[Index]]\v[0] * *frame1\scale\x) + *frame1\translate\x
*Vertex\y = (*frame1\vertex[*tri\indice[Face]\v[Index]]\v[1] * *frame1\scale\y) + *frame1\translate\y
*Vertex\z = 1.0 - ((*frame1\vertex[*tri\indice[Face]\v[Index]]\v[2] * *frame1\scale\z) + *frame1\translate\z)
EndIf
ProcedureReturn #Null
EndWith
EndProcedure
ProcedureDLL.i md2Close(*md2.MD2)
With *md2
FreeMemory(*md2)
ProcedureReturn #Null
EndWith
EndProcedure
ProcedureDLL.i md2Version()
ProcedureReturn #LDR_MD2_VERSION
EndProcedure
DataSection
md2normals:
Data.f -0.525731, 0.000000, 0.850651
Data.f -0.442863, 0.238856, 0.864188
Data.f -0.295242, 0.000000, 0.955423
Data.f -0.309017, 0.500000, 0.809017
Data.f -0.162460, 0.262866, 0.951056
Data.f 0.000000, 0.000000, 1.000000
Data.f 0.000000, 0.850651, 0.525731
Data.f -0.147621, 0.716567, 0.681718
Data.f 0.147621, 0.716567, 0.681718
Data.f 0.000000, 0.525731, 0.850651
Data.f 0.309017, 0.500000, 0.809017
Data.f 0.525731, 0.000000, 0.850651
Data.f 0.295242, 0.000000, 0.955423
Data.f 0.442863, 0.238856, 0.864188
Data.f 0.162460, 0.262866, 0.951056
Data.f -0.681718, 0.147621, 0.716567
Data.f -0.809017, 0.309017, 0.500000
Data.f -0.587785, 0.425325, 0.688191
Data.f -0.850651, 0.525731, 0.000000
Data.f -0.864188, 0.442863, 0.238856
Data.f -0.716567, 0.681718, 0.147621
Data.f -0.688191, 0.587785, 0.425325
Data.f -0.500000, 0.809017, 0.309017
Data.f -0.238856, 0.864188, 0.442863
Data.f -0.425325, 0.688191, 0.587785
Data.f -0.716567, 0.681718,-0.147621
Data.f -0.500000, 0.809017,-0.309017
Data.f -0.525731, 0.850651, 0.000000
Data.f 0.000000, 0.850651,-0.525731
Data.f -0.238856, 0.864188,-0.442863
Data.f 0.000000, 0.955423,-0.295242
Data.f -0.262866, 0.951056,-0.162460
Data.f 0.000000, 1.000000, 0.000000
Data.f 0.000000, 0.955423, 0.295242
Data.f -0.262866, 0.951056, 0.162460
Data.f 0.238856, 0.864188, 0.442863
Data.f 0.262866, 0.951056, 0.162460
Data.f 0.500000, 0.809017, 0.309017
Data.f 0.238856, 0.864188,-0.442863
Data.f 0.262866, 0.951056,-0.162460
Data.f 0.500000, 0.809017,-0.309017
Data.f 0.850651, 0.525731, 0.000000
Data.f 0.716567, 0.681718, 0.147621
Data.f 0.716567, 0.681718,-0.147621
Data.f 0.525731, 0.850651, 0.000000
Data.f 0.425325, 0.688191, 0.587785
Data.f 0.864188, 0.442863, 0.238856
Data.f 0.688191, 0.587785, 0.425325
Data.f 0.809017, 0.309017, 0.500000
Data.f 0.681718, 0.147621, 0.716567
Data.f 0.587785, 0.425325, 0.688191
Data.f 0.955423, 0.295242, 0.000000
Data.f 1.000000, 0.000000, 0.000000
Data.f 0.951056, 0.162460, 0.262866
Data.f 0.850651,-0.525731, 0.000000
Data.f 0.955423,-0.295242, 0.000000
Data.f 0.864188,-0.442863, 0.238856
Data.f 0.951056,-0.162460, 0.262866
Data.f 0.809017,-0.309017, 0.500000
Data.f 0.681718,-0.147621, 0.716567
Data.f 0.850651, 0.000000, 0.525731
Data.f 0.864188, 0.442863,-0.238856
Data.f 0.809017, 0.309017,-0.500000
Data.f 0.951056, 0.162460,-0.262866
Data.f 0.525731, 0.000000,-0.850651
Data.f 0.681718, 0.147621,-0.716567
Data.f 0.681718,-0.147621,-0.716567
Data.f 0.850651, 0.000000,-0.525731
Data.f 0.809017,-0.309017,-0.500000
Data.f 0.864188,-0.442863,-0.238856
Data.f 0.951056,-0.162460,-0.262866
Data.f 0.147621, 0.716567,-0.681718
Data.f 0.309017, 0.500000,-0.809017
Data.f 0.425325, 0.688191,-0.587785
Data.f 0.442863, 0.238856,-0.864188
Data.f 0.587785, 0.425325,-0.688191
Data.f 0.688191, 0.587785,-0.425325
Data.f -0.147621, 0.716567,-0.681718
Data.f -0.309017, 0.500000,-0.809017
Data.f 0.000000, 0.525731,-0.850651
Data.f -0.525731, 0.000000,-0.850651
Data.f -0.442863, 0.238856,-0.864188
Data.f -0.295242, 0.000000,-0.955423
Data.f -0.162460, 0.262866,-0.951056
Data.f 0.000000, 0.000000,-1.000000
Data.f 0.295242, 0.000000,-0.955423
Data.f 0.162460, 0.262866,-0.951056
Data.f -0.442863,-0.238856,-0.864188
Data.f -0.309017,-0.500000,-0.809017
Data.f -0.162460,-0.262866,-0.951056
Data.f 0.000000,-0.850651,-0.525731
Data.f -0.147621,-0.716567,-0.681718
Data.f 0.147621,-0.716567,-0.681718
Data.f 0.000000,-0.525731,-0.850651
Data.f 0.309017,-0.500000,-0.809017
Data.f 0.442863,-0.238856,-0.864188
Data.f 0.162460,-0.262866,-0.951056
Data.f 0.238856,-0.864188,-0.442863
Data.f 0.500000,-0.809017,-0.309017
Data.f 0.425325,-0.688191,-0.587785
Data.f 0.716567,-0.681718,-0.147621
Data.f 0.688191,-0.587785,-0.425325
Data.f 0.587785,-0.425325,-0.688191
Data.f 0.000000,-0.955423,-0.295242
Data.f 0.000000,-1.000000, 0.000000
Data.f 0.262866,-0.951056,-0.162460
Data.f 0.000000,-0.850651, 0.525731
Data.f 0.000000,-0.955423, 0.295242
Data.f 0.238856,-0.864188, 0.442863
Data.f 0.262866,-0.951056, 0.162460
Data.f 0.500000,-0.809017, 0.309017
Data.f 0.716567,-0.681718, 0.147621
Data.f 0.525731,-0.850651, 0.000000
Data.f -0.238856,-0.864188,-0.442863
Data.f -0.500000,-0.809017,-0.309017
Data.f -0.262866,-0.951056,-0.162460
Data.f -0.850651,-0.525731, 0.000000
Data.f -0.716567,-0.681718,-0.147621
Data.f -0.716567,-0.681718, 0.147621
Data.f -0.525731,-0.850651, 0.000000
Data.f -0.500000,-0.809017, 0.309017
Data.f -0.238856,-0.864188, 0.442863
Data.f -0.262866,-0.951056, 0.162460
Data.f -0.864188,-0.442863, 0.238856
Data.f -0.809017,-0.309017, 0.500000
Data.f -0.688191,-0.587785, 0.425325
Data.f -0.681718,-0.147621, 0.716567
Data.f -0.442863,-0.238856, 0.864188
Data.f -0.587785,-0.425325, 0.688191
Data.f -0.309017,-0.500000, 0.809017
Data.f -0.147621,-0.716567, 0.681718
Data.f -0.425325,-0.688191, 0.587785
Data.f -0.162460,-0.262866, 0.951056
Data.f 0.442863,-0.238856, 0.864188
Data.f 0.162460,-0.262866, 0.951056
Data.f 0.309017,-0.500000, 0.809017
Data.f 0.147621,-0.716567, 0.681718
Data.f 0.000000,-0.525731, 0.850651
Data.f 0.425325,-0.688191, 0.587785
Data.f 0.587785,-0.425325, 0.688191
Data.f 0.688191,-0.587785, 0.425325
Data.f -0.955423, 0.295242, 0.000000
Data.f -0.951056, 0.162460, 0.262866
Data.f -1.000000, 0.000000, 0.000000
Data.f -0.850651, 0.000000, 0.525731
Data.f -0.955423,-0.295242, 0.000000
Data.f -0.951056,-0.162460, 0.262866
Data.f -0.864188, 0.442863,-0.238856
Data.f -0.951056, 0.162460,-0.262866
Data.f -0.809017, 0.309017,-0.500000
Data.f -0.864188,-0.442863,-0.238856
Data.f -0.951056,-0.162460,-0.262866
Data.f -0.809017,-0.309017,-0.500000
Data.f -0.681718, 0.147621,-0.716567
Data.f -0.681718,-0.147621,-0.716567
Data.f -0.850651, 0.000000,-0.525731
Data.f -0.688191, 0.587785,-0.425325
Data.f -0.587785, 0.425325,-0.688191
Data.f -0.425325, 0.688191,-0.587785
Data.f -0.425325,-0.688191,-0.587785
Data.f -0.587785,-0.425325,-0.688191
Data.f -0.688191,-0.587785,-0.425325
EndDataSection
The Include (pb3d_md2.pbi):
Code: Select all
EnableExplicit
;---------------------------------------------------------------
;Quake 2 (id Tech 2) MD2 (Version 8) model loader for Ogre
;https://github.com/id-Software/Quake-2
;---------------------------------------------------------------
;File: INCLUDE - pb3d_md2.pbi
;---------------------------------------------------------------
;Version: alpha
;Author: Mijikai
;License: GPL 2.0
;---------------------------------------------------------------
;Limitation: no support for MD2 commands!
;---------------------------------------------------------------
;MD2 format limits (for 3d modeling):
;- Skins: 32
;- Triangles: 4096
;- Vertices: 2048
;- Texels: 2048
;- Frames: 512
;---------------------------------------------------------------
Import "pb3d_md2.lib"
md2Open(File.s,*Buffer = #Null)
md2Texture(Handle.i,Index.i = #Null,*Texture = #Null)
md2Animation(Handle.i,Index.i = #Null,*Animation = #Null)
md2Info(Handle.i,*Meshes,*Faces,*Indice,*Mode = #Null)
md2Mesh(Handle.i,Mesh.i,Face.i,Index.i,Blend.f,*TextureCoord,*Normal,*Vertex)
md2Close(Handle.i)
md2Version.i()
EndImport
#LDR_MD2_VERSION = $000001
Structure LDR_MD2_TEXTURE
id.s{64}
EndStructure
Structure LDR_MD2_ANIMATION
id.s{16}
EndStructure
Structure LDR_MD2_TEXEL
s.f
t.f
EndStructure
Structure LDR_MD2_VERTEX
x.f
y.f
z.f
EndStructure
Example:
Code: Select all
EnableExplicit
XIncludeFile "pb3d_md2.pbi"
Procedure.i Main(md2File.s,md2Texture.s)
Protected exit.i
Protected handle.i
Protected count.i
Protected face.i
Protected faces.i
Protected index.i
Protected indice.i
Protected build.i
Protected texture.LDR_MD2_TEXTURE
Protected animation.LDR_MD2_ANIMATION
Protected Dim texel.LDR_MD2_TEXEL(2)
Protected Dim normal.LDR_MD2_VERTEX(2)
Protected Dim vertex.LDR_MD2_VERTEX(2)
handle = md2Open(md2File)
If handle
; count = md2Texture(handle);<- uncomment to see the textures files referred to inside the model
; For index = 0 To count - 1
; md2Texture(handle,index,@texture)
; Debug texture\id
; Next
; count = md2Animation(handle);<- uncomment to see the mesh/frame animation tags
; For index = 0 To count - 1
; md2Animation(handle,index,@animation)
; Debug animation\id
; Next
If InitEngine3D() And InitSprite()
Add3DArchive(GetCurrentDirectory(),#PB_3DArchive_FileSystem)
If OpenWindow(0,0,0,800,600,#Null$,#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
If OpenWindowedScreen(WindowID(0),0,0,WindowWidth(0),WindowHeight(0))
SetFrameRate(60)
CreateMesh(0,#PB_Mesh_TriangleList)
md2Info(handle,#Null,@faces,@indice);<- how to build a mesh
indice - 1
While face < faces
For index = 0 To indice
md2Mesh(handle,#Null,face,index,0.0,@texel(index),@normal(index),@vertex(index));<- the Blend parameter allows to interpolate the vertex position between the current and next mesh/frame
MeshVertexPosition(vertex(index)\x,vertex(index)\y,vertex(index)\z)
MeshVertexNormal(normal(index)\x,normal(index)\y,normal(index)\z)
MeshVertexTextureCoordinate(texel(index)\s,texel(index)\t)
Next
MeshFace(build,build + 1,build + 2)
build + 3
face + 1
Wend
FinishMesh(#True)
NormalizeMesh(0)
UpdateMeshBoundingBox(0)
CreateMaterial(0,LoadTexture(0,md2Texture))
SetMaterialColor(0, #PB_Material_AmbientColor, #PB_Material_AmbientColors)
CreateEntity(0,MeshID(0),MaterialID(0))
ScaleEntity(0,8,8,8)
RotateEntity(0,90,0,0,#PB_Absolute)
CreateCamera(0,0,0,100,100)
MoveCamera(0,0,0,1000,#PB_Absolute)
CreateLight(0,RGB(255,255,255),300,600,-100)
AmbientColor(RGB(200,200,200))
Repeat
Repeat
Select WindowEvent()
Case #PB_Event_None
Break
Case #PB_Event_CloseWindow
exit = #True
EndSelect
ForEver
RotateEntity(0,0,0,1,#PB_Relative)
RenderWorld()
FlipBuffers()
Until exit
EndIf
CloseWindow(0)
EndIf
EndIf
md2Close(handle)
EndIf
ProcedureReturn #Null
EndProcedure
Main("md2\doomguy.md2","md2\doomguy.bmp")
;model downloaded from: https://sourceforge.net/projects/zdoomgl/files/zdoomgl%20models/Full%20Md2%20Pack/
End
Example load & animate (no interpolation):
Code: Select all
EnableExplicit
;---------------------------------------------------------------
;Quake 2 (id Tech 2) MD2 (Version 8) model loader for Ogre
;https://github.com/id-Software/Quake-2
;---------------------------------------------------------------
;File: DLL - pb3d_load_and_animate.pb
;---------------------------------------------------------------
;Version: alpha
;Author: Mijikai
;License: GPL 2.0
;---------------------------------------------------------------
;Limitation: no support for MD2 commands!
;---------------------------------------------------------------
;MD2 format limits (for 3d modeling):
;- Skins: 32
;- Triangles: 4096
;- Vertices: 2048
;- Texels: 2048
;- Frames: 512
;---------------------------------------------------------------
XIncludeFile "pb3d_md2.pbi"
Structure MD2_MODEL
texture.i
material.i
count.i
Array entity.i(0)
EndStructure
Procedure.i md2Model(Handle.i,Texture.s)
Protected *model.MD2_MODEL
Protected mesh.i
Protected meshes.i
Protected face.i
Protected faces.i
Protected index.i
Protected indice.i
Protected frame.i
Protected winding.i
Protected Dim texel.LDR_MD2_TEXEL(2)
Protected Dim normal.LDR_MD2_VERTEX(2)
Protected Dim vertex.LDR_MD2_VERTEX(2)
With *model
If Handle And Texture
*model = AllocateStructure(MD2_MODEL)
If *model
\texture = LoadTexture(#PB_Any,Texture)
If IsTexture(\texture)
\material = CreateMaterial(#PB_Any,TextureID(\texture))
If IsMaterial(\material)
SetMaterialColor(\material,#PB_Material_AmbientColor,#PB_Material_AmbientColors)
md2Info(Handle,@meshes,@faces,@indice)
meshes - 1
faces - 1
indice - 1
ReDim \entity(meshes)
If ArraySize(\entity()) = meshes
For mesh = 0 To meshes
frame = CreateMesh(#PB_Any,#PB_Mesh_TriangleList)
If frame
winding = 0
For face = 0 To faces
For index = 0 To indice
md2Mesh(Handle,mesh,face,index,#Null,@texel(index),@normal(index),@vertex(index))
MeshVertexPosition(vertex(index)\x,vertex(index)\y,vertex(index)\z)
MeshVertexNormal(normal(index)\x,normal(index)\y,normal(index)\z)
MeshVertexTextureCoordinate(texel(index)\s,texel(index)\t)
Next
MeshFace(winding,winding + 1,winding + 2)
winding + 3
Next
FinishMesh(#True)
NormalizeMesh(frame)
UpdateMeshBoundingBox(frame)
\entity(mesh) = CreateEntity(#PB_Any,MeshID(frame),MaterialID(\material))
If IsEntity(\entity(mesh))
ScaleEntity(\entity(mesh),8,8,8)
HideEntity(\entity(mesh),#True)
\count + 1
Else
FreeMesh(frame)
EndIf
EndIf
Next
If \count = meshes + 1
ProcedureReturn *model
EndIf
For mesh = 0 To meshes
If IsEntity(\entity(mesh))
frame = GetEntityMesh(\entity(mesh))
FreeEntity(\entity(mesh))
FreeMesh(frame)
EndIf
Next
EndIf
FreeMaterial(\material)
EndIf
FreeTexture(\texture)
EndIf
FreeStructure(*model)
EndIf
EndIf
ProcedureReturn #Null
EndWith
EndProcedure
Procedure.i Main(md2File.s,md2Texture.s)
Protected exit.i
Protected handle.i
Protected count.i
Protected index.i
Protected rot.f
Protected texture.LDR_MD2_TEXTURE
Protected animation.LDR_MD2_ANIMATION
Protected Dim texel.LDR_MD2_TEXEL(2)
Protected Dim normal.LDR_MD2_VERTEX(2)
Protected Dim vertex.LDR_MD2_VERTEX(2)
Protected *model.MD2_MODEL
handle = md2Open(md2File)
If handle
If InitEngine3D() And InitSprite()
Add3DArchive(GetCurrentDirectory(),#PB_3DArchive_FileSystem)
If OpenWindow(0,0,0,800,600,#Null$,#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
If OpenWindowedScreen(WindowID(0),0,0,WindowWidth(0),WindowHeight(0))
SetFrameRate(60)
*model = md2Model(handle,md2Texture)
CreateCamera(0,0,0,100,100)
MoveCamera(0,0,0,1000,#PB_Absolute)
CreateLight(0,RGB(255,255,255),300,600,-100)
AmbientColor(RGB(200,200,200))
Repeat
Repeat
Select WindowEvent()
Case #PB_Event_None
Break
Case #PB_Event_CloseWindow
exit = #True
EndSelect
ForEver
index + 1
If index % 6 = 0
count + 1
If count >= md2Animation(handle)
count = 0
EndIf
index = 1
EndIf
rot + 1.5
HideEntity(*model\entity(count),#False)
RotateEntity(*model\entity(count),90.0,0.0,rot,#PB_Absolute)
RenderWorld()
HideEntity(*model\entity(count),#True)
FlipBuffers()
Until exit
EndIf
CloseWindow(0)
EndIf
EndIf
md2Close(handle)
EndIf
ProcedureReturn #Null
EndProcedure
Main("md2\doomguy.md2","md2\doomguy.bmp")
;model downloaded from: https://sourceforge.net/projects/zdoomgl/files/zdoomgl%20models/Full%20Md2%20Pack/
End
