ROOT logo
// $Id: MD2Object.cxx 2088 2008-11-23 20:26:46Z matevz $

// Copyright (C) 1999-2008, Matevz Tadel. All rights reserved.
// This file is part of GLED, released under GNU General Public License version 2.
// For the licensing terms see $GLEDSYS/LICENSE or http://www.gnu.org/.

//__________________________________________________________________________
// MD2Object
//
// Quake2 MD2 object -- minimal implementation.
// Snached from: http://www.moelhave.dk/2002/06/quake-2-md2-model-loader/
//
// Issues:
// 1. Triangles are back-facing ("fixed" in rendering).
// 2. Some models have inverted normals (fixed via mNormFac variable, set to -1).
//
//
// Should check some more models

#include "MD2Object.h"
#include "MD2Object.c7"

#include <fstream>

ClassImp(MD2Object);

/**************************************************************************/

void MD2Object::_init()
{
  mFrameTime = 0;
  mMaxFrame  = 0;
  mNormFac   = 1;

  m_akFrames = 0;
  m_akVertex = 0;
  m_akNormal = 0;
  m_akTriangle = 0;
  m_akTextureCoords = 0;
}


void MD2Object::_clear_data()
{
  delete m_akFrames; m_akFrames = 0;
  delete m_akVertex; m_akVertex = 0;
  delete m_akNormal; m_akNormal = 0;
  delete m_akTriangle; m_akTriangle = 0;
  delete m_akTextureCoords; m_akTextureCoords = 0;
}

/**************************************************************************/

void MD2Object::Load()
{
  // Loads the file given as parameter

  static const Exc_t _eh("MD2Object::Load ");

  //Load file

  std::ifstream kFile;
  kFile.open(mFile, std::ios::binary | std::ios::in);
  if (!kFile) {
    kFile.close();
    throw(_eh + "failed opening the file.");
  }

  //Loading header

  kFile.read((char *)&m_kHeader, sizeof(MD2Header));

  //Check magic number

  if (m_kHeader.iMagic != 0x32504449 ||m_kHeader.iVersion != 8) {
    kFile.close();
    throw(_eh + "wrong magic number.");
  }

  _clear_data();

  //Load the frames

  kFile.seekg(m_kHeader.iOffsetFrames, std::ios::beg); //seek to start

  m_akFrames = new char[m_kHeader.iFrameSize * m_kHeader.iNumFrames];
  kFile.read((char *)m_akFrames, m_kHeader.iFrameSize * m_kHeader.iNumFrames);

  //Read in to vertex array

  m_akVertex = new Vector3[m_kHeader.iNumFrames*m_kHeader.iNumVertices];
  m_akNormal = new Int_t  [m_kHeader.iNumFrames*m_kHeader.iNumVertices];
  for (int i = 0; i < m_kHeader.iNumFrames; i++) {

      for (int j = 0; j < m_kHeader.iNumVertices; j++) {

	  int iVertexIndex = i*m_kHeader.iNumVertices + j;
	  int iFrameIndex  = i*m_kHeader.iFrameSize;
	  m_akVertex[iVertexIndex].x = (float)(((MD2Frame*)&m_akFrames[iFrameIndex])->akVertices[j].abVertex[0]);
	  m_akVertex[iVertexIndex].y = (float)(((MD2Frame*)&m_akFrames[iFrameIndex])->akVertices[j].abVertex[1]);
	  m_akVertex[iVertexIndex].z = (float)(((MD2Frame*)&m_akFrames[iFrameIndex])->akVertices[j].abVertex[2]);

	  m_akVertex[iVertexIndex].x *= ((MD2Frame*)&m_akFrames[iFrameIndex])->afScale[0];
	  m_akVertex[iVertexIndex].y *= ((MD2Frame*)&m_akFrames[iFrameIndex])->afScale[1];
	  m_akVertex[iVertexIndex].z *= ((MD2Frame*)&m_akFrames[iFrameIndex])->afScale[2];

	  //scale them:

	  m_akVertex[iVertexIndex].x += ((MD2Frame*)&m_akFrames[iFrameIndex])->afTranslate[0];
	  m_akVertex[iVertexIndex].y += ((MD2Frame*)&m_akFrames[iFrameIndex])->afTranslate[1];
	  m_akVertex[iVertexIndex].z += ((MD2Frame*)&m_akFrames[iFrameIndex])->afTranslate[2];

	  m_akNormal[iVertexIndex] = ((MD2Frame*)&m_akFrames[iFrameIndex])->akVertices[j].abLightNormalIndex;
      }

  }

  //Read triangles

  m_akTriangle = new MD2Triangle[m_kHeader.iNumTriangles];
  kFile.seekg(m_kHeader.iOffsetTriangles, std::ios::beg);
  kFile.read((char *)m_akTriangle, m_kHeader.iNumTriangles * sizeof(MD2Triangle));


  //Read texture coordinates

  m_akTextureCoords = new MD2TextureCoord[m_kHeader.iNumTexCoords];
  kFile.seekg(m_kHeader.iOffsetTexCoords, std::ios::beg);
  kFile.read((char *)m_akTextureCoords, sizeof(MD2TextureCoord)*m_kHeader.iNumTexCoords);


  //Build bounding volume
  // m_kModelBound.ComputeFromData(m_akVertex, m_kHeader.iNumVertices);

  kFile.close();

  mMaxFrame = m_kHeader.iNumFrames;
  Stamp(FID());
}

/**************************************************************************/
 MD2Object.cxx:1
 MD2Object.cxx:2
 MD2Object.cxx:3
 MD2Object.cxx:4
 MD2Object.cxx:5
 MD2Object.cxx:6
 MD2Object.cxx:7
 MD2Object.cxx:8
 MD2Object.cxx:9
 MD2Object.cxx:10
 MD2Object.cxx:11
 MD2Object.cxx:12
 MD2Object.cxx:13
 MD2Object.cxx:14
 MD2Object.cxx:15
 MD2Object.cxx:16
 MD2Object.cxx:17
 MD2Object.cxx:18
 MD2Object.cxx:19
 MD2Object.cxx:20
 MD2Object.cxx:21
 MD2Object.cxx:22
 MD2Object.cxx:23
 MD2Object.cxx:24
 MD2Object.cxx:25
 MD2Object.cxx:26
 MD2Object.cxx:27
 MD2Object.cxx:28
 MD2Object.cxx:29
 MD2Object.cxx:30
 MD2Object.cxx:31
 MD2Object.cxx:32
 MD2Object.cxx:33
 MD2Object.cxx:34
 MD2Object.cxx:35
 MD2Object.cxx:36
 MD2Object.cxx:37
 MD2Object.cxx:38
 MD2Object.cxx:39
 MD2Object.cxx:40
 MD2Object.cxx:41
 MD2Object.cxx:42
 MD2Object.cxx:43
 MD2Object.cxx:44
 MD2Object.cxx:45
 MD2Object.cxx:46
 MD2Object.cxx:47
 MD2Object.cxx:48
 MD2Object.cxx:49
 MD2Object.cxx:50
 MD2Object.cxx:51
 MD2Object.cxx:52
 MD2Object.cxx:53
 MD2Object.cxx:54
 MD2Object.cxx:55
 MD2Object.cxx:56
 MD2Object.cxx:57
 MD2Object.cxx:58
 MD2Object.cxx:59
 MD2Object.cxx:60
 MD2Object.cxx:61
 MD2Object.cxx:62
 MD2Object.cxx:63
 MD2Object.cxx:64
 MD2Object.cxx:65
 MD2Object.cxx:66
 MD2Object.cxx:67
 MD2Object.cxx:68
 MD2Object.cxx:69
 MD2Object.cxx:70
 MD2Object.cxx:71
 MD2Object.cxx:72
 MD2Object.cxx:73
 MD2Object.cxx:74
 MD2Object.cxx:75
 MD2Object.cxx:76
 MD2Object.cxx:77
 MD2Object.cxx:78
 MD2Object.cxx:79
 MD2Object.cxx:80
 MD2Object.cxx:81
 MD2Object.cxx:82
 MD2Object.cxx:83
 MD2Object.cxx:84
 MD2Object.cxx:85
 MD2Object.cxx:86
 MD2Object.cxx:87
 MD2Object.cxx:88
 MD2Object.cxx:89
 MD2Object.cxx:90
 MD2Object.cxx:91
 MD2Object.cxx:92
 MD2Object.cxx:93
 MD2Object.cxx:94
 MD2Object.cxx:95
 MD2Object.cxx:96
 MD2Object.cxx:97
 MD2Object.cxx:98
 MD2Object.cxx:99
 MD2Object.cxx:100
 MD2Object.cxx:101
 MD2Object.cxx:102
 MD2Object.cxx:103
 MD2Object.cxx:104
 MD2Object.cxx:105
 MD2Object.cxx:106
 MD2Object.cxx:107
 MD2Object.cxx:108
 MD2Object.cxx:109
 MD2Object.cxx:110
 MD2Object.cxx:111
 MD2Object.cxx:112
 MD2Object.cxx:113
 MD2Object.cxx:114
 MD2Object.cxx:115
 MD2Object.cxx:116
 MD2Object.cxx:117
 MD2Object.cxx:118
 MD2Object.cxx:119
 MD2Object.cxx:120
 MD2Object.cxx:121
 MD2Object.cxx:122
 MD2Object.cxx:123
 MD2Object.cxx:124
 MD2Object.cxx:125
 MD2Object.cxx:126
 MD2Object.cxx:127
 MD2Object.cxx:128
 MD2Object.cxx:129
 MD2Object.cxx:130
 MD2Object.cxx:131
 MD2Object.cxx:132
 MD2Object.cxx:133
 MD2Object.cxx:134
 MD2Object.cxx:135
 MD2Object.cxx:136
 MD2Object.cxx:137
 MD2Object.cxx:138
 MD2Object.cxx:139
 MD2Object.cxx:140
 MD2Object.cxx:141