Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

MilkShape.cpp

Go to the documentation of this file.
00001 
00007 #include "MilkShape.h"
00008 
00009 void MS_Vec_Transform(MS_Vec *pV, const Mat4 *pM) {
00021         float vector[4];
00022         const float *matrix = pM->getMatrix();
00023 
00024         vector[0] = pV->x * matrix[0] + pV->y * matrix[4] + pV->z * matrix[8] + matrix[12];
00025         vector[1] = pV->x * matrix[1] + pV->y * matrix[5] + pV->z * matrix[9] + matrix[13];
00026         vector[2] = pV->x * matrix[2] + pV->y * matrix[6] + pV->z * matrix[10] + matrix[14];
00027         vector[3] = pV->x * matrix[3] + pV->y * matrix[7] + pV->z * matrix[11] + matrix[15];
00028 
00029         pV->x = vector[0];
00030         pV->y = vector[1];
00031         pV->z = vector[2];
00032         pV->w = vector[3];
00033 
00034 }
00035 
00036 void MS_Vec_Transform3(MS_Vec *pV, const Mat4 *pM) {
00047         float vector[3];
00048         const float *matrix = pM->getMatrix();
00049 
00050         vector[0] = pV->x * matrix[0] + pV->y * matrix[4] + pV->z * matrix[8];
00051         vector[1] = pV->x * matrix[1] + pV->y * matrix[5] + pV->z * matrix[9];
00052         vector[2] = pV->x * matrix[2] + pV->y * matrix[6] + pV->z * matrix[10];
00053 
00054         pV->x = vector[0];
00055         pV->y = vector[1];
00056         pV->z = vector[2];
00057 }
00058 
00059 //-------------------------------------------------------------
00060 
00061 MilkShape::MilkShape() {
00062         this->numMeshes = 0;
00063         this->pMeshes   = NULL;
00064         this->numBones  = 0;
00065         this->pBones    = NULL;
00066         this->numMaterials = 0;
00067         this->pMaterials = NULL;
00068         this->materialIndices = NULL;
00069 }
00070 
00071 MilkShape::~MilkShape() {
00072         clear();
00073 }
00074 
00075 void MilkShape::clear() {
00076         unsigned int i;
00077 
00078         if (this->pMeshes != NULL) {
00079                 for (i=0; i<this->numMeshes; i++) {
00080                         //delete this->pMeshes[i];
00081                         pMeshes[i].clear();
00082                 }
00083                 //pMeshes->clear();
00084                 free(pMeshes);
00085                 pMeshes = NULL;
00086         }
00087 
00088         if (this->pMaterials != NULL) {
00089                 for (i=0; i<this->numMaterials; i++) {
00090                         pMaterials[i].clear();
00091                 }
00092                 //pMaterials->clear();
00093                 free(pMaterials);
00094                 pMaterials = NULL;
00095         }
00096 
00097         if (this->pBones != NULL) {
00098                 for (i=0; i<this->numBones; i++) {
00099                         pBones[i].clear();
00100                 }
00101                 //pBones->clear();
00102                 free(pBones);
00103                 pBones = NULL;
00104         }
00105 
00106         if (this->materialIndices != NULL) {
00107                 free(this->materialIndices);
00108                 this->materialIndices = NULL;
00109         }
00110 }
00111 
00112 bool MilkShape::linkBones() {
00113         int i, j;
00114 
00115         for (i=0; i<this->numBones; i++) {
00116                 this->pBones[i].parent = NULL;
00117 
00118                 // have a parent
00119                 if (strlen(this->pBones[i].parentName) > 0) {
00120                         // search parent
00121                         for (j=0; j<this->numBones; j++) {
00122                                 // j is pparent of i
00123                                 if (stricmp(this->pBones[j].name, this->pBones[i].parentName) == 0) {
00124                                         this->pBones[i].parent = &this->pBones[j];
00125                                         break;
00126                                 }
00127                         }
00128 
00129                         // unable to find parent
00130                         if (this->pBones[i].parent == NULL)
00131                                 return false;
00132                 }
00133         }
00134 
00135         return true;
00136 }
00137 
00138 void MilkShape::initializeBones() {
00139         int i;
00140 
00141         for (i=0; i<this->numBones; i++) {
00142                 this->pBones[i].initialize();
00143         }
00144 }
00145 
00146 void MilkShape::attachSkin() {
00147         int i, j;
00148         int bone;
00149         Mat4 *pMatrix;
00150         float v[3];
00151 
00152         for (i=0; i<this->numMeshes; i++) {
00153                 for (j=0; j<this->pMeshes[i].numVertices; j++) {
00154                         bone = this->pMeshes[i].vertices[j].bone;
00155 
00156                         // vertex attached to a bone
00157                         if (bone != -1) {
00158                                 //pMatrix = this->pBones[bone].matFinal;
00159                                 pMatrix = &this->pBones[bone].matFinal;
00160 
00161                                 v[0] = this->pMeshes[i].vertices[j].x;
00162                                 v[1] = this->pMeshes[i].vertices[j].y;
00163                                 v[2] = this->pMeshes[i].vertices[j].z;
00164 
00165                                 pMatrix->inverseTranslateVect(v);
00166                                 pMatrix->inverseRotateVect(v);
00167 
00168                                 this->pMeshes[i].vertices[j].x = v[0];
00169                                 this->pMeshes[i].vertices[j].y = v[1];
00170                                 this->pMeshes[i].vertices[j].z = v[2];
00171                         }
00172                 }
00173         }
00174 }
00175 
00176 void MilkShape::renderBones() {
00177         for (int i=0; i<this->numBones; i++) {
00178                 this->pBones[i].render();
00179         }
00180 }
00181 
00182 void MilkShape::advanceAnimation(float deltaTime) {
00183         int i;
00184 
00185         this->fCurrentTime += deltaTime;
00186 
00187         // loop animation
00188         if (this->fCurrentTime > this->fMaxTime)
00189                 this->fCurrentTime = 1.0f;
00190 
00191         for (i=0; i<this->numBones; i++) {
00192                 this->pBones[i].advanceTo(this->fCurrentTime);
00193         }
00194 }
00195 
00196 bool MilkShape::loadFromAsciiFile(const char *path, const char *filename) {
00197         float   StartTime;
00198         bool    bError = false;
00199         char    szpath[256];
00200         char    szLine[256] = {0};
00201         int             nFlags, nIndex, i;
00202 
00203         sprintf(szpath, "%s%s", path, filename);
00204 
00205         FILE *file = fopen(szpath, "r");
00206         if (!file) {
00207                 LOG_ERROR(("Unable to locate MilkShape ASCII file: %s", szpath));
00208                 return false;
00209         }
00210 
00211         //LOG_MISC(("Loading MilkShape ASCII file: %s", szpath));
00212 
00213         this->fCurrentTime = 0.0f;
00214         int nFrame;
00215 
00216         while (fgets(szLine, 256, file) != NULL && !bError) {
00217                 if (!strncmp(szLine, "//", 2))
00218                         continue;
00219 
00220                 // Length of animation
00221                 if (sscanf(szLine, "Frames: %d", &nFrame) == 1) {
00222                         this->fMaxTime = 1.0f*nFrame;
00223 
00224                         //LOG_MISC(("Animation length: %f", this->fMaxTime));
00225 
00226                         continue;
00227                 }
00228 
00229                 if (sscanf(szLine, "Frame: %d", &nFrame) == 1) {
00230                         StartTime = 1.0f*nFrame;
00231                         //LOG_MISC(("Animation start time: %f", StartTime));
00232                         continue;
00233                 }
00234 
00235                 //--------------------
00236                 // Meshes
00237                 //--------------------
00238                 if (sscanf(szLine, "Meshes: %d", &this->numMeshes) == 1) {
00239                         //LOG_MISC(("MilkShape # Loading mesh (%d)", this->numMeshes));
00240 
00241                         char szName[MS_MAX_NAME];
00242 
00243                         this->pMeshes = (MS_Mesh *)malloc(sizeof(MS_Mesh)*this->numMeshes);
00244                         this->materialIndices = (int *)malloc(sizeof(int)*this->numMeshes);
00245 
00246                         for (i=0; i<this->numMeshes && !bError; i++) {
00247                                 if (!fgets(szLine, 256, file)) {
00248                                         LOG_MISC(("MilkShape # Error loading Mesh"));
00249                                         bError = true;
00250                                         break;
00251                                 }
00252 
00253                                 // mesh: name, flags, material index
00254                                 if (sscanf(szLine, "\"%[^\"]\" %d %d", szName, &nFlags, &nIndex) != 3) {
00255                                         LOG_MISC(("MilkShape # Error loading Mesh info"));
00256                                         bError = true;
00257                                         break;
00258                                 }
00259                                 this->materialIndices[i] = nIndex;
00260 
00261                                 if (!this->pMeshes[i].loadFromAsciiSegment(file)) {
00262                                         LOG_ERROR(("MilkShape # Error loading Mesh ascii segment"));
00263                                         bError = true;
00264                                         break;
00265                                 }
00266                         }
00267 
00268                         //LOG_MISC(("MilkShape # Meshes loaded"));
00269 
00270                         continue;
00271                 }
00272                 
00273                 //--------------------
00274                 // Materials
00275                 //--------------------
00276                 if (sscanf(szLine, "Materials: %d", &this->numMaterials) == 1 && this->numMaterials > 0) {
00277                         //LOG_MISC(("MilkShape # Loading materials (%d)", this->numMaterials));
00278 
00279                         int i; // needed? don't think so
00280 
00281                         this->pMaterials = (MS_Material *)malloc(sizeof(MS_Material) * this->numMaterials);
00282 
00283                         for (i=0; i<this->numMaterials && !bError; i++) {
00284                                 if (!this->pMaterials[i].loadFromAsciiSegment(path, file)) {
00285                                         LOG_ERROR(("MilkShape # Error loading Material ascii segment"));
00286                                         bError = true;
00287                                         break;
00288                                 }
00289                         }
00290 
00291                         //LOG_MISC(("MilkShape # Materials loaded"));
00292 
00293                         continue;
00294                 }
00295 
00296                 //--------------------
00297                 // Bones
00298                 //--------------------
00299                 if (sscanf(szLine, "Bones: %d", &this->numBones) == 1 && this->numBones > 0) {
00300                         //LOG_MISC(("MilkShape # Loading bones (%d)", this->numBones));
00301 
00302                         int i = 0; // don't needed either I think
00303 
00304                         this->pBones = (MS_Bone *)malloc(sizeof(MS_Bone) * this->numBones);
00305 
00306                         for (i=0; i<this->numBones && !bError; i++) {
00307                                 if (!this->pBones[i].loadFromAsciiSegment(file)) {
00308                                         LOG_ERROR(("MilkShape # Error loading Bones ascii segment"));
00309                                         bError = true;
00310                                         break;
00311                                 }
00312                         }
00313 
00314                         //LOG_MISC(("MilkShape # Bones loaded"));
00315 
00316                         continue;
00317                 }
00318 
00319                 //--------------------
00320                 // Guns :)
00321                 //--------------------
00322                 if (sscanf(szLine, "Guns: %d", &this->numGuns) == 1 && this->numGuns > 0) {
00323                         if (this->numGuns > MS_PLAYER_MAX_GUNS) this->numGuns = MS_PLAYER_MAX_GUNS;
00324 
00325                         //LOG_MISC(("MilkShape # Loading guns (%d)", this->numGuns));
00326 
00327                         i = 0;
00328 
00329                         for (i=0; i<this->numGuns; i++) {
00330                                 if (!fgets(szLine, 256, file))
00331                                         return false;
00332                                 if (sscanf(szLine, "%f %f %f", &this->guns[i].x, &this->guns[i].y, &this->guns[i].z) != 3) {
00333                                         LOG_ERROR(("MilkShape # Error loading gun position"));
00334                                         return false;
00335                                 }
00336 
00337                                 //LOG_MISC(("x:%f, y:%f, z:%f", this->guns[i].x,this->guns[i].y,this->guns[i].z));
00338                         }
00339 
00340                         //LOG_MISC(("MilkShape # Guns loaded"));
00341                 }
00342         }
00343 
00344         fclose(file);
00345 
00346         if (!this->linkBones())
00347                 return false;
00348 
00349         this->initializeBones();
00350         this->attachSkin();
00351         this->advanceAnimation(StartTime);
00352 
00353         LOG_SUCCESS(("MilkShape ASCII file < %s >loaded", szpath));
00354 
00355         return true;
00356 }
00357 
00358 void MilkShape::render() {
00359         int k, i, j;
00360         MS_Tri          *pTri   = NULL;
00361         MS_Vec          *pVec   = NULL;
00362         MS_Normal       *pN             = NULL;
00363         MS_Bone         *pBone  = NULL;
00364         float           v[3];
00365         Mat4            *pMatrix;
00366 
00367         for (k=0; k<this->numMeshes; k++) {
00368 
00369                 if (this->numMaterials > 0) {
00370                         int materialIndex = this->materialIndices[k];
00371                         if (materialIndex >= 0) {
00372                                 this->pMaterials->activate();
00373                         }
00374                         else {
00375                                 //glDisable(GL_TEXTURE_2D);
00376                         }
00377                 }
00378 
00379 
00380                 glBegin(GL_TRIANGLES);
00381                 // for each triangle
00382                 for (i=0; i<this->pMeshes[k].numTriangles; i++) {
00383                         pTri = this->pMeshes[k].triangles + i;
00384 
00385                         // for each vertex
00386                         for (j=0; j<3; j++) {
00387 
00388                                 // normal
00389                                 pN = this->pMeshes[k].normals + pTri->n[j];
00390                                 glNormal3f(pN->x, pN->y, pN->z);
00391 
00392                                 // texture coordinate
00393                                 pVec = this->pMeshes[k].vertices + pTri->v[j];
00394                                 glMultiTexCoord2fARB(GL_TEXTURE0_ARB, pVec->u, pVec->v);
00395 
00396 
00397                                 if (pVec->bone == -1) {
00398                                         glVertex3f(pVec->x, pVec->y, pVec->z);
00399                                 }
00400                                 else {
00401                                         pBone = &this->pBones[pVec->bone];
00402                                         pMatrix = &pBone->matFinal;
00403                                         v[0] = pVec->x;
00404                                         v[1] = pVec->y;
00405                                         v[2] = pVec->z;
00406 
00407                                         pMatrix->rotateVect(v);
00408                                         pMatrix->translateVect(v);
00409 
00410                                         glVertex3fv(v);
00411                                 }
00412                         }
00413                 }
00414                 glEnd();
00415 
00441         }
00442 }

Generated on Sun Jun 5 15:47:04 2005 for Defacto by  doxygen 1.4.3