Ответ: OpenGL-загрузчики
Quake 3 Arena MD3
Вы спросите: сплю ли я? Я отвечу: зачем?
Как юзать:
Это кровный братишка MD2. Функции - те же самые, только кончаются на MD3. Но в загрузке есть нюанс. Если вы грузите модель откуда-то не из корневого каталога, вам нужно установить переменную MD3_Texture_Path на путь до папки с моделью. Путь должен кончаться на / или \. Загрузчик сам подберёт текстуры, сам забиндит их при рисовании, сказка вобщем :-D .
Словцо о тэгах - они загружаются, но не используются. Вы можете получить их сами, посмотрите структуру MD3Entity.
Загрузка:
Код:
; нам требуется переменная для хранения меша.
; она должна быть со структурой MD3Entity
myMD3.MD3Entity
; грузим меш. Первый параметр - ссылка на ваш объект, второй - путь. Текстуры загрузятся автоматически, если будут найдены. Q3-шейдеры не поддерживаются
LoadMD3(@myMD3, "mesh.md3")
Рисование:
Код:
; Параметры абсолютно идентичны MD2. Условия отрисовки - те же.
; UP: новый параметр - режим рисования. Может быть либо #MD3_RENDER_IMMEDIATE (через glBegin/end)
; либо #MD3_RENDER_ARRAY (через glDrawElements)
DisplayMD3(@myMD3, 1, 2, 0.3, #MD3_RENDER_ARRAY)
Код:
Код:
; ===================================
; MD3 Loader and Drawer
; 2013 Kirpi4
; ===================================
Global MD3_Texture_Path.s = ""
Enumeration
#MD3_IDENT
#MD3_VERSION
#MD3_FLAGS = 3
#MD3_NUM_FRAMES
#MD3_NUM_TAGS
#MD3_NUM_SURFACES
#MD3_NUM_SKINS
#MD3_OFF_FRAMES
#MD3_OFF_TAGS
#MD3_OFF_SURFACES
EndEnumeration
Enumeration
#MD3_SURF_IDENT
#MD3_SURF_FLAGS = 2
#MD3_SURF_NUM_FRAMES
#MD3_SURF_NUM_SHADERS
#MD3_SURF_NUM_VERTS
#MD3_SURF_NUM_TRIANGLES
#MD3_SURF_OFF_TRIANGLES
#MD3_SURF_OFF_SHADERS
#MD3_SURF_OFF_COORDS
#MD3_SURF_OFF_VERTS
#MD3_SURF_EOF
EndEnumeration
Enumeration 0
#MD3_RENDER_IMMEDIATE
#MD3_RENDER_ARRAY
EndEnumeration
; Vector
Structure MD3Vec
x.f
y.f
z.f
EndStructure
; Vertex
Structure MD3Vert
x.f
y.f
z.f
n.l
EndStructure
; Frame
Structure MD3Frame
min.MD3Vec
max.MD3Vec
orig.MD3Vec
rad.f
name.s
EndStructure
; VertexFrame (one frame of anim)
Structure MD3AnimFrame
Array verts.MD3Vert(0)
EndStructure
; Tag
Structure MD3Tag
name.s
orig.MD3Vec
Array orient.MD3Vec(3)
EndStructure
; Triangle
Structure MD3Tri
Array index.l(3)
EndStructure
; TexCoord
Structure MD3TexCoord
u.f
v.f
EndStructure
; Shader (i.e. texture)
Structure MD3Shader
name.s
number.l
EndStructure
; Surface
Structure MD3Surf
Array header.l(12)
name.s ; Must be number 2 in header
Array shaders.MD3Shader(0)
Array tris.MD3Tri(0)
Array coords.MD3TexCoord(0)
Array anims.MD3AnimFrame(0)
Array glCoords.f(0)
Array glIndices.w(0)
EndStructure
; MD3 Entity
Structure MD3Entity
Array header.l(12)
name.s ; Must be number 3 in header
Array frame.MD3Frame(0)
Array tag.MD3Tag(0)
Array surf.MD3Surf(0)
EndStructure
; Loaded MD3 textures, contains GL texture ID
Global NewMap MD3_LoadedTex.l()
Procedure.s MD3BufferString(f.l,len.l)
tmp.s = ""
For i=0 To len-1
tmp + Chr(ReadByte(f))
Next
ProcedureReturn RTrim(tmp)
EndProcedure
Procedure.f MD3Interpolate(x1.f,x2.f,interp.f)
dlt.f = x2-x1
ProcedureReturn x1 + (dlt*interp)
EndProcedure
Procedure MD3ReadVec(*v.MD3Vec,f.l)
*v\x = ReadFloat(f)
*v\y = ReadFloat(f)
*v\z = ReadFloat(f)
EndProcedure
Procedure.l MD3NearPowerOf2(size.l)
For i=0 To 31
If size<Pow(2,i)
ProcedureReturn Pow(2,i)
EndIf
Next
EndProcedure
Procedure MD3LoadTexture(name.s)
ImageNumber = LoadImage(-1,MD3_Texture_Path+name)
If ImageNumber=0
Debug "MD3 Texture not found: "+name
ProcedureReturn
EndIf
ResizeImage(ImageNumber,MD3NearPowerOf2(ImageWidth(ImageNumber)),MD3NearPowerOf2(ImageHeight(ImageNumber)),#PB_Image_Raw)
Protected Counter.l,Color.l,texture
Protected Dim ImageData.c(ImageWidth(ImageNumber)*ImageHeight(ImageNumber)*4)
StartDrawing(ImageOutput(ImageNumber))
For I = 0 To ImageHeight(ImageNumber)-1
For J = 0 To ImageWidth(ImageNumber)-1
color=Point(j,i)
ImageData(Counter)=color & $FF
ImageData(Counter+1)=color >> 8 & $FF
ImageData(Counter+2)=color >> 16 & $FF
ImageData(Counter+3)=255
Counter+4
Next
Next
StopDrawing()
glGenTextures_(1, @texture)
glBindTexture_(#GL_TEXTURE_2D, texture)
glTexEnvi_(#GL_TEXTURE_ENV, #GL_TEXTURE_ENV_MODE, #GL_MODULATE)
glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_MIN_FILTER, #GL_LINEAR)
glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_MAG_FILTER, #GL_NEAREST)
glTexImage2D_(#GL_TEXTURE_2D, 0, #GL_RGBA, ImageWidth(ImageNumber), ImageHeight(ImageNumber), 0, #GL_RGBA, #GL_UNSIGNED_BYTE, ImageData())
FreeImage(ImageNumber)
MD3_LoadedTex(MD3_Texture_Path+name) = texture
EndProcedure
Procedure MD3GetTexture(name.s)
If FindMapElement(MD3_LoadedTex(),MD3_Texture_Path+name)
glEnable_(#GL_TEXTURE_2D)
glBindTexture_(#GL_TEXTURE_2D,MD3_LoadedTex(MD3_Texture_Path+name))
Else
glDisable_(#GL_TEXTURE_2D)
EndIf
EndProcedure
Procedure LoadMD3(*m.md3entity,file.s)
f = ReadFile(-1,file)
; Header
For i=0 To 11
If i=2
*m\name = MD3BufferString(f,64)
Else
*m\header(i) = ReadLong(f)
EndIf
Next
; Frames
FileSeek(f,*m\header(#MD3_OFF_FRAMES))
Dim *m\frame.MD3Frame(*m\header(#MD3_NUM_FRAMES))
For i=0 To *m\header(#MD3_NUM_FRAMES)-1
With *m\frame(i)
MD3ReadVec(@\min,f)
MD3ReadVec(@\max,f)
MD3ReadVec(@\orig,f)
\rad = ReadFloat(f)
\name = MD3BufferString(f,16)
EndWith
Next
; Tags
FileSeek(f,*m\header(#MD3_OFF_TAGS))
Dim *m\tag.MD3Tag(*m\header(#MD3_NUM_TAGS))
For i=0 To *m\header(#MD3_NUM_TAGS)-1
With *m\tag(i)
\name = MD3BufferString(f,64)
MD3ReadVec(@\orig,f)
For j=0 To 2
MD3ReadVec(@\orient(j),f)
Next
EndWith
Next
; Surfaaaaaaaces
FileSeek(f,*m\header(#MD3_OFF_SURFACES))
Dim *m\surf.MD3Surf(*m\header(#MD3_NUM_SURFACES))
For srf=0 To *m\header(#MD3_NUM_SURFACES)-1
With *m\surf(srf)
surfStart.l = Loc(f)
; Header
For i=0 To 11
If i=1
\name = MD3BufferString(f,64)
Else
\header(i) = ReadLong(f)
EndIf
Next
; Shaders
FileSeek(f,surfStart+\header(#MD3_SURF_OFF_SHADERS))
Dim *m\surf(srf)\shaders.MD3Shader(\header(#MD3_SURF_NUM_SHADERS))
For i=0 To \header(#MD3_SURF_NUM_SHADERS)-1
*m\surf(srf)\shaders(i)\name = GetFilePart(MD3BufferString(f,64))
*m\surf(srf)\shaders(i)\number = ReadLong(f)
MD3LoadTexture(*m\surf(srf)\shaders(i)\name)
Next
; Triangles
FileSeek(f,surfStart+\header(#MD3_SURF_OFF_TRIANGLES))
Dim *m\surf(srf)\tris.MD3Tri(\header(#MD3_SURF_NUM_TRIANGLES))
For i=0 To \header(#MD3_SURF_NUM_TRIANGLES)-1
For j=0 To 2
*m\surf(srf)\tris(i)\index(j) = ReadLong(f)
Next
Next
; Coords
FileSeek(f,surfStart+\header(#MD3_SURF_OFF_COORDS))
Dim *m\surf(srf)\coords.MD3TexCoord(\header(#MD3_SURF_NUM_VERTS))
For i=0 To \header(#MD3_SURF_NUM_VERTS)-1
*m\surf(srf)\coords(i)\u = ReadFloat(f)
*m\surf(srf)\coords(i)\v = ReadFloat(f)
Next
; Verts
FileSeek(f,surfStart+\header(#MD3_SURF_OFF_VERTS))
Dim *m\surf(srf)\anims.MD3AnimFrame(*m\header(#MD3_NUM_FRAMES))
For j=0 To *m\header(#MD3_NUM_FRAMES)-1
Dim *m\surf(srf)\anims(j)\verts.MD3Vert(\header(#MD3_SURF_NUM_VERTS))
For i=0 To \header(#MD3_SURF_NUM_VERTS)-1
*m\surf(srf)\anims(j)\verts(i)\x = ReadWord(f)/64.0
*m\surf(srf)\anims(j)\verts(i)\y = ReadWord(f)/64.0
*m\surf(srf)\anims(j)\verts(i)\z = ReadWord(f)/64.0
*m\surf(srf)\anims(j)\verts(i)\n = ReadWord(f)
Next
Next
FileSeek(f,surfstart+\header(#MD3_SURF_EOF))
; Preparing for array rendering
Dim \glIndices.w(\header(#MD3_SURF_NUM_TRIANGLES)*3)
Dim \glCoords.f(\header(#MD3_SURF_NUM_VERTS)*2)
For tr = 0 To \header(#MD3_SURF_NUM_TRIANGLES)-1
For vr = 0 To 2
\glIndices(tr*3+vr) = \tris(tr)\index(vr)
Next
Next
For vr = 0 To \header(#MD3_SURF_NUM_VERTS)-1
\glCoords(vr*2) = \coords(vr)\u
\glCoords(vr*2+1) = \coords(vr)\v
Next
EndWith
Next
CloseFile(f)
EndProcedure
Procedure DisplayMD3(*m.md3entity,frame1.l,frame2.l,trans.f,dispMode.b = #MD3_RENDER_IMMEDIATE)
If frame1>=frame2
Swap frame1, frame2
trans = 1.0-trans
EndIf
For i=0 To *m\header(#MD3_NUM_SURFACES)-1
With *m\surf(i)
Select dispMode
Case #MD3_RENDER_IMMEDIATE
; Using glBegin/end
Protected Dim verts.MD3Vert(*m\surf(i)\header(#MD3_SURF_NUM_VERTS))
For v = 0 To \header(#MD3_SURF_NUM_VERTS)-1
verts(v)\x = MD3Interpolate(\anims(frame1)\verts(v)\x,\anims(frame2)\verts(v)\x,trans)
verts(v)\y = MD3Interpolate(\anims(frame1)\verts(v)\y,\anims(frame2)\verts(v)\y,trans)
verts(v)\z = MD3Interpolate(\anims(frame1)\verts(v)\z,\anims(frame2)\verts(v)\z,trans)
Next
For tx = 0 To \header(#MD3_SURF_NUM_SHADERS)-1
MD3GetTexture(\shaders(tx)\name)
Next
glBegin_(#GL_TRIANGLES)
For tr = 0 To \header(#MD3_SURF_NUM_TRIANGLES)-1
For vr = 0 To 2
glTexCoord2f_(\coords(\tris(tr)\index(vr))\u,\coords(\tris(tr)\index(vr))\v)
glVertex3f_(-verts(\tris(tr)\index(vr))\y,verts(\tris(tr)\index(vr))\z,-verts(\tris(tr)\index(vr))\x)
Next
Next
glEnd_()
FreeArray(verts())
Case #MD3_RENDER_ARRAY
; Using vertex buffers
Protected Dim verts2.f(*m\surf(i)\header(#MD3_SURF_NUM_VERTS)*3)
For v = 0 To \header(#MD3_SURF_NUM_VERTS)-1
verts2(v*3) = -MD3Interpolate(\anims(frame1)\verts(v)\y,\anims(frame2)\verts(v)\y,trans)
verts2(v*3+1) = MD3Interpolate(\anims(frame1)\verts(v)\z,\anims(frame2)\verts(v)\z,trans)
verts2(v*3+2) = -MD3Interpolate(\anims(frame1)\verts(v)\x,\anims(frame2)\verts(v)\x,trans)
Next
For tx = 0 To \header(#MD3_SURF_NUM_SHADERS)-1
MD3GetTexture(\shaders(tx)\name)
Next
glEnableClientState_(#GL_VERTEX_ARRAY)
glEnableClientState_(#GL_TEXTURE_COORD_ARRAY)
glEnableClientState_(#GL_INDEX_ARRAY)
glVertexPointer_(3,#GL_FLOAT,0,@verts2())
glTexCoordPointer_(2,#GL_FLOAT,0,@\glCoords())
glDrawElements_(#GL_TRIANGLES,\header(#MD3_SURF_NUM_TRIANGLES)*3,#GL_UNSIGNED_SHORT,@\glIndices())
glDisableClientState_(#GL_INDEX_ARRAY)
glDisableClientState_(#GL_TEXTURE_COORD_ARRAY)
glDisableClientState_(#GL_VERTEX_ARRAY)
FreeArray(verts2())
EndSelect
EndWith
Next
EndProcedure
|