'/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
'///////////////////////////////////  GDK_GL 2 - DEVELOPMENT EDITION .01 -  //////////////////////////////////////////////////
'/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
'////////////////////////////////////  By John Onyon a.k.a Unseen Machine  ///////////////////////////////////////////////////
'/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

'// .MD2 (Quake) Models \\

SUB MD2_TYPE_DEFS

 TYPE MD2
  Ident AS LONG '// ID tag must be 844121161 (= "IDP2")
  Version AS LONG '// File version number MUST BE 8
  SkinWidth AS LONG
  SkinHeight AS LONG
  FrameSize AS LONG
  Num_Skins AS LONG
  Num_Verts AS LONG '// Num verts per frame
  Num_ST AS LONG
  Num_Tris AS LONG
  Num_GlCmds AS LONG
  Num_Frames AS LONG
  Offset_Skins AS LONG
  Offset_ST AS LONG
  Offset_Tris AS LONG
  Offset_Frames AS LONG
  Offset_GlCmds AS LONG
  Offset_End AS LONG
 END TYPE

 TYPE MD2_Vec3
  X AS SINGLE
  Y AS SINGLE
  Z AS SINGLE
 END TYPE

 TYPE MD2_Skin
  Name AS STRING * 64
 END TYPE

 TYPE MD2_TexCoord
  S AS INTEGER
  T AS INTEGER
 END TYPE

 TYPE MD2_Triangle
  Vert1 AS _UNSIGNED INTEGER
  Vert2 AS _UNSIGNED INTEGER
  Vert3 AS _UNSIGNED INTEGER
  Tx1 AS _UNSIGNED INTEGER
  Tx2 AS _UNSIGNED INTEGER
  Tx3 AS _UNSIGNED INTEGER
 END TYPE

 TYPE MD2_Vertex
  V1 AS _UNSIGNED _BYTE
  V2 AS _UNSIGNED _BYTE
  V3 AS _UNSIGNED _BYTE
  NormalIndex AS _UNSIGNED _BYTE
 END TYPE

 TYPE MD2_Frame
  Scale AS MD2_Vec3
  Translate AS MD2_Vec3
  Name AS STRING * 16
 END TYPE

 TYPE MD2_VertexF
  X AS SINGLE
  Y AS SINGLE
  Z AS SINGLE
 END TYPE

END SUB


'##########################################################################################################################

SUB MD2_Load_Normals (Normals() AS MD2_VertexF)
 RESTORE MD2_Norms:
 FOR i% = 0 TO 161
  READ Normals(i%).X, Normals(i%).Y, Normals(i%).Z
 NEXT
 MD2_Norms:
 DATA -0.525731,0.000000,0.850651,-0.442863,0.238856,0.864188,-0.295242,0.000000,0.955423,-0.309017,0.500000,0.809017,-0.162460,0.262866,0.951056,0.000000,0.000000,1.000000,0.000000,0.850651,0.525731,-0.147621,0.716567,0.681718,0.147621,0.716567,0.681718,0.000000,0.525731,0.850651,0.309017,0.500000,0.809017,0.525731,0.000000,0.850651,0.295242,0.000000,0.955423,0.442863,0.238856,0.864188,0.162460,0.262866,0.951056,-0.681718,0.147621,0.716567,-0.809017,0.309017,0.500000,-0.587785,0.425325,0.688191,-0.850651,0.525731,0.000000,-0.864188,0.442863,0.238856,-0.716567,0.681718,0.147621,-0.688191,0.587785,0.425325,-0.500000,0.809017,0.309017,-0.238856,0.864188,0.442863,-0.425325,0.688191,0.587785,-0.716567,0.681718,-0.147621,-0.500000,0.809017,-0.309017,-0.525731,0.850651,0.000000,0.000000,0.850651,-0.525731,-0.238856,0.864188,-0.442863,0.000000,0.955423,-0.295242,-0.262866,0.951056,-0.162460,0.000000,1.000000,0.000000,0.000000,0.955423,0.295242,-0.262866,0.951056,0.162460,0.238856,0.864188,0.442863,0.262866,0.951056,0.162460,0.500000,0.809017,0.309017,0.238856,0.864188,-0.442863,0.262866,0.951056,-0.162460,0.500000,0.809017,-0.309017,0.850651,0.525731,0.000000,0.716567,0.681718,0.147621,0.716567,0.681718,-0.147621,0.525731,0.850651,0.000000,0.425325,0.688191,0.587785,0.864188,0.442863,0.238856,0.688191,0.587785,0.425325,0.809017,0.309017,0.500000,0.681718,0.147621,0.716567,0.587785,0.425325,0.688191,0.955423,0.295242,0.000000,1.000000,0.000000,0.000000,0.951056,0.162460,0.262866,0.850651,-0.525731,0.000000,0.955423,-0.295242,0.000000,0.864188,-0.442863,0.238856,0.951056,-0.162460,0.262866,0.809017,-0.309017,0.500000,0.681718,-0.147621,0.716567,0.850651,0.000000,0.525731,0.864188,0.442863,-0.238856,0.809017,0.309017,-0.500000,0.951056,0.162460,-0.262866,0.525731,0.000000,-0.850651,0.681718,0.147621,-0.716567,0.681718,-0.147621,-0.716567,0.850651,0.000000,-0.525731,0.809017,-0.309017,-0.500000,0.864188,-0.442863,-0.238856,0.951056,-0.162460,-0.262866,0.147621,0.716567,-0.681718,0.309017,0.500000,-0.809017,0.425325,0.688191,-0.587785,0.442863,0.238856,-0.864188,0.587785,0.425325,-0.688191,0.688191,0.587785,-0.425325,-0.147621,0.716567,-0.681718,-0.309017,0.500000,-0.809017,0.000000,0.525731,-0.850651,-0.525731,0.000000,-0.850651,-0.442863,0.238856,-0.864188,-0.295242,0.000000,-0.955423,-0.162460,0.262866,-0.951056,0.000000,0.000000,-1.000000,0.295242,0.000000,-0.955423,0.162460,0.262866,-0.951056,-0.442863,-0.238856,-0.864188,-0.309017,-0.500000,-0.809017,-0.162460,-0.262866,-0.951056,0.000000,-0.850651,-0.525731,-0.147621,-0.716567,-0.681718,0.147621,-0.716567,-0.681718,0.000000,-0.525731,-0.850651,0.309017,-0.500000,-0.809017,0.442863,-0.238856,-0.864188,0.162460,-0.262866,-0.951056,0.238856,-0.864188,-0.442863,0.500000,-0.809017,-0.309017,0.425325,-0.688191,-0.587785,0.716567,-0.681718,-0.147621,0.688191,-0.587785,-0.425325,0.587785,-0.425325,-0.688191,0.000000,-0.955423,-0.295242,0.000000,-1.000000,0.000000,0.262866,-0.951056,-0.162460,0.000000,-0.850651,0.525731,0.000000,-0.955423,0.295242,0.238856,-0.864188,0.442863,0.262866,-0.951056,0.162460,0.500000,-0.809017,0.309017,0.716567,-0.681718,0.147621,0.525731,-0.850651,0.000000,-0.238856,-0.864188,-0.442863,-0.500000,-0.809017,-0.309017,-0.262866,-0.951056,-0.162460,-0.850651,-0.525731,0.000000,-0.716567,-0.681718,-0.147621,-0.716567,-0.681718,0.147621,-0.525731,-0.850651,0.000000,-0.500000,-0.809017,0.309017,-0.238856,-0.864188,0.442863,-0.262866,-0.951056,0.162460,-0.864188,-0.442863,0.238856,-0.809017,-0.309017,0.500000,-0.688191,-0.587785,0.425325,-0.681718,-0.147621,0.716567,-0.442863,-0.238856,0.864188,-0.587785,-0.425325,0.688191,-0.309017,-0.500000,0.809017,-0.147621,-0.716567,0.681718,-0.425325,-0.688191,0.587785,-0.162460,-0.262866,0.951056,0.442863,-0.238856,0.864188,0.162460,-0.262866,0.951056,0.309017,-0.500000,0.809017,0.147621,-0.716567,0.681718,0.000000,-0.525731,0.850651,0.425325,-0.688191,0.587785,0.587785,-0.425325,0.688191,0.688191,-0.587785,0.425325,-0.955423,0.295242,0.000000,-0.951056,0.162460,0.262866,-1.000000,0.000000,0.000000,-0.850651,0.000000,0.525731,-0.955423,-0.295242,0.000000,-0.951056,-0.162460,0.262866,-0.864188,0.442863,-0.238856,-0.951056,0.162460,-0.262866,-0.809017,0.309017,-0.500000,-0.864188,-0.442863,-0.238856,-0.951056,-0.162460,-0.262866,-0.809017,-0.309017,-0.500000,-0.681718,0.147621,-0.716567,-0.681718,-0.147621,-0.716567,-0.850651,0.000000,-0.525731,-0.688191,0.587785,-0.425325,-0.587785,0.425325,-0.688191,-0.425325,0.688191,-0.587785,-0.425325,-0.688191,-0.587785,-0.587785,-0.425325,-0.688191,-0.688191,-0.587785,-0.425325
END SUB

'##########################################################################################################################



FUNCTION MD2_LOAD (Model AS MODEL, FileName$)

 IF _FILEEXISTS(FileName$) - 1 THEN '// File exists

  '// Figure out model type from extension and set ID flag
  FileName$ = LTRIM$(RTRIM$(FileName$))
  Ext$ = RIGHT$(FileName$, LEN(FileName$) - INSTR(FileName$, ".")) '// get file type i.e .mdl, .md2, .3ds etc

  IF Ext$ = "MD2" THEN

   DIM infile AS LONG, TmpMODEL AS MD2

   infile = FREEFILE
   OPEN FileName$ FOR BINARY ACCESS READ AS #infile
   GET #infile, 1, TmpMODEL '// Get header data
   IF TmpMODEL.Ident = 844121161 AND TmpMODEL.Version = 8 THEN '// Check if valid model file

    Model.ID = MD2 '// Set model id flag
    Model.HeaderPntr = _MEMNEW(LEN(TmpMODEL))
    _MEMPUT Model.HeaderPntr, Model.HeaderPntr.OFFSET, TmpMODEL

    DIM QMSkin AS MD2_Skin
    DIM QMTexCoord AS MD2_TexCoord
    DIM QMTri AS MD2_Triangle
    DIM QMFrame AS MD2_Frame
    DIM QMVert AS MD2_Vertex

    SkinSize& = TmpMODEL.Num_Skins * LEN(QMSkin)
    TexSize& = TmpMODEL.Num_ST * LEN(QMTexCoord)
    TriSize& = TmpMODEL.Num_Tris * LEN(QMTri)
    FrameSize& = TmpMODEL.Num_Frames * LEN(QMFrame)
    VertSize& = (TmpMODEL.Num_Frames * TmpMODEL.Num_Verts) * LEN(QMVert)
    MemBlockSize& = SkinSize& + TexSize& + TriSize& + FrameSize& + VertSize&
    Model.DataPntr = _MEMNEW(MemBlockSize&)

    MemOffset& = 0
    BytePos& = TmpMODEL.Offset_Skins + 1

    FOR I% = 0 TO TmpMODEL.Num_Skins - 1
     GET #infile, BytePos&, QMSkin
     _MEMPUT Model.DataPntr, Model.DataPntr.OFFSET + MemOffset&, QMSkin
     MemOffset& = MemOffset& + LEN(QMSkin)
     BytePos& = BytePos& + LEN(QMSkin)
    NEXT

    BytePos& = TmpMODEL.Offset_ST + 1
    FOR I% = 0 TO TmpMODEL.Num_ST - 1
     GET #infile, BytePos&, QMTexCoord
     _MEMPUT Model.DataPntr, Model.DataPntr.OFFSET + MemOffset&, QMTexCoord
     MemOffset& = MemOffset& + LEN(QMTexCoord)
     BytePos& = BytePos& + LEN(QMTexCoord)
    NEXT

    BytePos& = TmpMODEL.Offset_Tris + 1
    FOR i& = 0 TO TmpMODEL.Num_Tris - 1
     GET #infile, BytePos&, QMTri
     _MEMPUT Model.DataPntr, Model.DataPntr.OFFSET + MemOffset&, QMTri
     MemOffset& = MemOffset& + LEN(QMTri)
     BytePos& = BytePos& + LEN(QMTri)
    NEXT
    BytePos& = TmpMODEL.Offset_Frames + 1

    FOR FrameCnt% = 0 TO TmpMODEL.Num_Frames - 1
     GET #infile, BytePos&, QMFrame
     _MEMPUT Model.DataPntr, Model.DataPntr.OFFSET + MemOffset&, QMFrame
     MemOffset& = MemOffset& + LEN(QMFrame)
     BytePos& = BytePos& + LEN(QMFrame)
     FOR I% = 0 TO TmpMODEL.Num_Verts - 1
      GET #infile, BytePos&, QMVert
      _MEMPUT Model.DataPntr, Model.DataPntr.OFFSET + MemOffset&, QMVert
      MemOffset& = MemOffset& + LEN(QMVert)
      BytePos& = BytePos& + LEN(QMVert)
     NEXT
    NEXT
    MD2_LOAD = True
   ELSE
    MD2_LOAD = False
   END IF

   CLOSE #infile
   EXIT FUNCTION

  END IF
 END IF

END FUNCTION


SUB MD2_DRAW (Model AS MODEL, Frame%)

 DIM TmpModel AS MD2

 _MEMGET Model.HeaderPntr, Model.HeaderPntr.OFFSET, TmpModel

 DIM QMSkins(TmpModel.Num_Skins - 1) AS MD2_Skin
 DIM QMTexCoord(TmpModel.Num_ST - 1) AS MD2_TexCoord
 DIM QMTris(TmpModel.Num_Tris - 1) AS MD2_Triangle
 DIM QMFrames(TmpModel.Num_Frames - 1) AS MD2_Frame
 DIM QMVerts(TmpModel.Num_Frames - 1, TmpModel.Num_Verts - 1) AS MD2_Vertex
 DIM MD2_Normals(161) AS MD2_VertexF

 MemOffset& = 0

 _MEMGET Model.DataPntr, Model.DataPntr.OFFSET + MemOffset&, QMSkins()
 MemOffset& = MemOffset& + LEN(QMSkins(0)) * TmpModel.Num_Skins

 _MEMGET Model.DataPntr, Model.DataPntr.OFFSET + MemOffset&, QMTexCoord()
 MemOffset& = MemOffset& + LEN(QMTexCoord(0)) * TmpModel.Num_ST

 _MEMGET Model.DataPntr, Model.DataPntr.OFFSET + MemOffset&, QMTris()
 MemOffset& = MemOffset& + LEN(QMTris(0)) * TmpModel.Num_Tris

 FOR FrameCnt% = 0 TO TmpModel.Num_Frames - 1
  _MEMGET Model.DataPntr, Model.DataPntr.OFFSET + MemOffset&, QMFrames(FrameCnt%)
  MemOffset& = MemOffset& + LEN(QMFrames(0))
  FOR I% = 0 TO TmpModel.Num_Verts - 1
   _MEMGET Model.DataPntr, Model.DataPntr.OFFSET + MemOffset&, QMVerts(FrameCnt%, I%)
   MemOffset& = MemOffset& + LEN(QMVerts(0, 0))
  NEXT
 NEXT

 MD2_Load_Normals MD2_Normals()

 DIM Pvert(2) AS MD2_Vertex
 DIM VB_Vert(8, TmpModel.Num_Tris - 1) AS SINGLE
 DIM tc(5, TmpModel.Num_Tris - 1) AS SINGLE
 DIM Norm(8, TmpModel.Num_Tris - 1) AS SINGLE '// Normal index array

 FOR Tri% = 0 TO TmpModel.Num_Tris - 1

  Pvert(0) = QMVerts(Frame%, QMTris(Tri%).Vert1)
  Pvert(1) = QMVerts(Frame%, QMTris(Tri%).Vert2)
  Pvert(2) = QMVerts(Frame%, QMTris(Tri%).Vert3)

  VB_Vert(0, Tri%) = (QMFrames(Frame%).Scale.X * Pvert(0).V1) + QMFrames(Frame%).Translate.X
  VB_Vert(1, Tri%) = (QMFrames(Frame%).Scale.X * Pvert(0).V2) + QMFrames(Frame%).Translate.Y
  VB_Vert(2, Tri%) = (QMFrames(Frame%).Scale.X * Pvert(0).V3) + QMFrames(Frame%).Translate.Z
  VB_Vert(3, Tri%) = (QMFrames(Frame%).Scale.X * Pvert(1).V1) + QMFrames(Frame%).Translate.X
  VB_Vert(4, Tri%) = (QMFrames(Frame%).Scale.X * Pvert(1).V2) + QMFrames(Frame%).Translate.Y
  VB_Vert(5, Tri%) = (QMFrames(Frame%).Scale.X * Pvert(1).V3) + QMFrames(Frame%).Translate.Z
  VB_Vert(6, Tri%) = (QMFrames(Frame%).Scale.X * Pvert(2).V1) + QMFrames(Frame%).Translate.X
  VB_Vert(7, Tri%) = (QMFrames(Frame%).Scale.X * Pvert(2).V2) + QMFrames(Frame%).Translate.Y
  VB_Vert(8, Tri%) = (QMFrames(Frame%).Scale.X * Pvert(2).V3) + QMFrames(Frame%).Translate.Z

  tc(0, Tri%) = QMTexCoord(QMTris(Tri%).Tx1).S / TmpModel.SkinWidth
  tc(1, Tri%) = QMTexCoord(QMTris(Tri%).Tx1).T / TmpModel.SkinHeight
  tc(2, Tri%) = QMTexCoord(QMTris(Tri%).Tx2).S / TmpModel.SkinWidth
  tc(3, Tri%) = QMTexCoord(QMTris(Tri%).Tx2).T / TmpModel.SkinHeight
  tc(4, Tri%) = QMTexCoord(QMTris(Tri%).Tx3).S / TmpModel.SkinWidth
  tc(5, Tri%) = QMTexCoord(QMTris(Tri%).Tx3).T / TmpModel.SkinHeight

  Norm(0, Tri%) = MD2_Normals(Pvert(0).NormalIndex).X
  Norm(1, Tri%) = MD2_Normals(Pvert(0).NormalIndex).Y
  Norm(2, Tri%) = MD2_Normals(Pvert(0).NormalIndex).Z
  Norm(3, Tri%) = MD2_Normals(Pvert(1).NormalIndex).X
  Norm(4, Tri%) = MD2_Normals(Pvert(1).NormalIndex).Y
  Norm(5, Tri%) = MD2_Normals(Pvert(1).NormalIndex).Z
  Norm(6, Tri%) = MD2_Normals(Pvert(2).NormalIndex).X
  Norm(7, Tri%) = MD2_Normals(Pvert(2).NormalIndex).Y
  Norm(8, Tri%) = MD2_Normals(Pvert(2).NormalIndex).Z

 NEXT

 '// Render
 _glEnableClientState _GL_VERTEX_ARRAY
 IF Model.Skin <> 0 THEN _glEnableClientState _GL_TEXTURE_COORD_ARRAY
 _glEnableClientState _GL_NORMAL_ARRAY
 IF Model.Skin <> 0 THEN _glBindTexture _GL_TEXTURE_2D, Model.Skin
 _glVertexPointer 3, _GL_FLOAT, 0, _OFFSET(VB_Vert())
 IF Model.Skin <> 0 THEN _glTexCoordPointer 2, _GL_FLOAT, 0, _OFFSET(tc())
 _glNormalPointer _GL_FLOAT, 0, _OFFSET(Norm())
 _glDrawArrays _GL_TRIANGLES, 0, TmpModel.Num_Tris * 3
 _glDisableClientState _GL_VERTEX_ARRAY
 IF Model.Skin <> 0 THEN _glDisableClientState _GL_TEXTURE_COORD_ARRAY
 _glDisableClientState _GL_NORMAL_ARRAY

END SUB




