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
00081 pMeshes[i].clear();
00082 }
00083
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
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
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
00119 if (strlen(this->pBones[i].parentName) > 0) {
00120
00121 for (j=0; j<this->numBones; j++) {
00122
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
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
00157 if (bone != -1) {
00158
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
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
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
00221 if (sscanf(szLine, "Frames: %d", &nFrame) == 1) {
00222 this->fMaxTime = 1.0f*nFrame;
00223
00224
00225
00226 continue;
00227 }
00228
00229 if (sscanf(szLine, "Frame: %d", &nFrame) == 1) {
00230 StartTime = 1.0f*nFrame;
00231
00232 continue;
00233 }
00234
00235
00236
00237
00238 if (sscanf(szLine, "Meshes: %d", &this->numMeshes) == 1) {
00239
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
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
00269
00270 continue;
00271 }
00272
00273
00274
00275
00276 if (sscanf(szLine, "Materials: %d", &this->numMaterials) == 1 && this->numMaterials > 0) {
00277
00278
00279 int i;
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
00292
00293 continue;
00294 }
00295
00296
00297
00298
00299 if (sscanf(szLine, "Bones: %d", &this->numBones) == 1 && this->numBones > 0) {
00300
00301
00302 int i = 0;
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
00315
00316 continue;
00317 }
00318
00319
00320
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
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
00338 }
00339
00340
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
00376 }
00377 }
00378
00379
00380 glBegin(GL_TRIANGLES);
00381
00382 for (i=0; i<this->pMeshes[k].numTriangles; i++) {
00383 pTri = this->pMeshes[k].triangles + i;
00384
00385
00386 for (j=0; j<3; j++) {
00387
00388
00389 pN = this->pMeshes[k].normals + pTri->n[j];
00390 glNormal3f(pN->x, pN->y, pN->z);
00391
00392
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 }