00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00027 #include "../Include/Globals.h"
00028 #include "../Include/FlyLegacy.h"
00029 #include "../Include/Utility.h"
00030
00031
00032
00033
00034
00035 typedef struct {
00036 float dx, dy, dz, p, b, h;
00037 } SAcmKeyframe;
00038
00039
00040
00041
00042 typedef struct {
00043 float x, y, z;
00044 float nx, ny, nz;
00045 float u, v;
00046 } SAcmVertex;
00047
00048
00049
00050 CModelACM::CModelACM (const char* acmFilename)
00051 {
00052 top = new ssgTransform;
00053 top->setName (acmFilename);
00054
00055 tifftexture = NULL;
00056
00057 PODFILE *p = popen (&globals->pfs, acmFilename);
00058 if (p == NULL) {
00059 gtfo ("CModelACM : Could not open ACM model %s", acmFilename);
00060 }
00061
00062 GLuint texid = 0;
00063 char texfilename[256];
00064
00065 static const int LINE_LENGTH = 128;
00066 char s[LINE_LENGTH+1];
00067
00068
00069 pgets (s, LINE_LENGTH, p);
00070 if (strncmp (s, "CAircraftModel", strlen("CAircraftModel")) != 0) {
00071
00072 globals->logWarning->Write ("CModelACM : Incorrect object type in %s", acmFilename);
00073 }
00074
00075
00076 pgets (s, LINE_LENGTH, p);
00077
00078
00079 int nParts;
00080 pgets (s, LINE_LENGTH, p);
00081 if (sscanf (s, "%d", &nParts) != 1) {
00082
00083 gtfo ("CModelACM : Error parsing part count in %s", acmFilename);
00084 }
00085
00086
00087
00088 ssgBranch **parentList = new ssgBranch*[nParts];
00089
00090
00091 for (int i=0; i<nParts; i++) {
00092
00093
00094 ssgKeyframeTransform *xform = new ssgKeyframeTransform (31, 0.0f, 1.0f);
00095
00096
00097 char name[LINE_LENGTH];
00098 pgets (s, LINE_LENGTH, p);
00099 TrimTrailingWhitespace (s);
00100 strcpy (name, s);
00101
00102
00103 pgets (s, LINE_LENGTH, p);
00104
00105
00106 int parent_index = -1;
00107 pgets (s, LINE_LENGTH, p);
00108 if (sscanf (s, "%d", &parent_index) != 1) {
00109
00110 gtfo ("CModelACM : Error parsing parent index in %s", acmFilename);
00111 }
00112
00113
00114 ssgBranch *parent = top;
00115 if (parent_index != -1) {
00116 parent = parentList[parent_index];
00117 }
00118
00119
00120 parentList[i] = xform;
00121
00122
00123 pgets (s, LINE_LENGTH, p);
00124
00125
00126 int nVerts, nFrames, nFaces, dummy;
00127 pgets (s, LINE_LENGTH, p);
00128 if (sscanf (s, "%d,%d,%d,%d", &nVerts, &nFrames, &nFaces, &dummy) != 4) {
00129
00130 gtfo ("CModelACM : Error parsing vertex and face counts in %s", acmFilename);
00131 }
00132
00133
00134 bool v1flag = false;
00135 pgets (s, LINE_LENGTH, p);
00136 if (strncmp (s, "v1", 2) == 0) {
00137
00138 v1flag = true;
00139
00140 pgets (s, LINE_LENGTH, p);
00141 }
00142
00143
00144
00145 int diffuse, specular, specpower, transparent, envmap;
00146 char texturename[LINE_LENGTH];
00147 if (sscanf (s, "%d,%d,%d,%d,%d,%s",
00148 &diffuse, &specular, &specpower, &transparent, &envmap, texturename) != 6) {
00149
00150 gtfo ("CModelACM : Error parsing material parameters in %s", acmFilename) ;
00151 }
00152
00153
00154 if (texid == 0) {
00155 strcpy (texfilename, texturename);
00156 char texfullname[256];
00157 strcpy (texfullname, "Art\\");
00158 strcat (texfullname, texfilename);
00159 tifftexture = new CImageTIFF (texfullname);
00160 texid = tifftexture->CreateTexture (false);
00161 if (texid == 0) {
00162 gtfo ("CModelACM : Failed to create texture from %s in %s",
00163 texfullname, acmFilename);
00164 }
00165 } else {
00166
00167 if (strcmp (texfilename, texturename) != 0) {
00168 gtfo ("CModelACM : More than one texture filename in %s", acmFilename);
00169 }
00170 }
00171
00172
00173 ssgSimpleState *state = new ssgSimpleState ();
00174
00175 sgVec4 spec = { 0.0f, 0.0f, 0.0f, 1.0f };
00176 sgVec4 emis = { 0.0f, 0.0f, 0.0f, 1.0f } ;
00177 float shi = { 0.0f } ;
00178
00179 state -> setMaterial ( GL_SPECULAR, spec ) ;
00180 state -> setMaterial ( GL_EMISSION, emis ) ;
00181 state -> setShininess ( shi ) ;
00182 state -> enable ( GL_COLOR_MATERIAL ) ;
00183 state -> setColourMaterial ( GL_AMBIENT_AND_DIFFUSE ) ;
00184 state -> enable ( GL_LIGHTING ) ;
00185 state -> setShadeModel ( GL_SMOOTH ) ;
00186
00187 if (texid != 0) {
00188
00189 state-> enable (GL_TEXTURE_2D);
00190 state-> setTexture (texid);
00191
00192
00193 if (transparent) {
00194 state->enable (GL_BLEND);
00195 state->enable (GL_ALPHA_TEST);
00196 state->setTranslucent();
00197 } else {
00198 state->disable (GL_BLEND);
00199 state->disable (GL_ALPHA_TEST);
00200 state->setOpaque();
00201 }
00202 } else {
00203 state->disable (GL_TEXTURE_2D);
00204 state->disable (GL_BLEND);
00205 }
00206
00207
00208
00209 if (v1flag) {
00210 pgets (s, LINE_LENGTH, p);
00211 }
00212
00213
00214
00215 SAcmVertex *vt = new SAcmVertex[nVerts];
00216
00217
00218 for (int j=0; j<nVerts; j++) {
00219
00220 float x, y, z, nx, ny, nz, u, v;
00221 pgets (s, LINE_LENGTH, p);
00222 if (sscanf (s, "%f,%f,%f,%f,%f,%f,%f,%f",
00223 &x, &y, &z, &nx, &ny, &nz, &u, &v) != 8) {
00224
00225 gtfo ("CModelACM : Error parsing vertex %d in %s", j, acmFilename) ;
00226 }
00227
00228
00229
00230 SAcmVertex *pNext = &vt[j];
00231 pNext->x = x;
00232 pNext->y = z;
00233 pNext->z = y;
00234 pNext->nx = nx;
00235 pNext->ny = nz;
00236 pNext->nz = ny;
00237 pNext->u = u;
00238 pNext->v = v;
00239
00240 }
00241
00242
00243
00244 ssgVertexArray *va = new ssgVertexArray(nFaces*3);
00245 ssgNormalArray *na = new ssgNormalArray(nFaces*3);
00246 ssgTexCoordArray *tca = new ssgTexCoordArray(nFaces*3);
00247
00248
00249 for (int k=0; k<nFaces; k++) {
00250
00251 int i1, i2, i3;
00252 pgets (s, LINE_LENGTH, p);
00253 if (sscanf (s, "%d,%d,%d",
00254 &i1, &i2, &i3) != 3)
00255 {
00256
00257 gtfo ("CModelACM : Error parsing face %d in %s", k, acmFilename) ;
00258 }
00259
00260
00261
00262
00263
00264
00265 sgVec3 v1, v2, v3;
00266 sgSetVec3 (v1, vt[i1].x, vt[i1].y, vt[i1].z);
00267 sgSetVec3 (v2, vt[i2].x, vt[i2].y, vt[i2].z);
00268 sgSetVec3 (v3, vt[i3].x, vt[i3].y, vt[i3].z);
00269 va->add (v3);
00270 va->add (v2);
00271 va->add (v1);
00272
00273
00274 sgVec3 n1, n2, n3;
00275 sgSetVec3 (n1, vt[i1].nx, vt[i1].ny, vt[i1].nz);
00276 sgSetVec3 (n2, vt[i2].nx, vt[i2].ny, vt[i2].nz);
00277 sgSetVec3 (n3, vt[i3].nx, vt[i3].ny, vt[i3].nz);
00278 na->add (n3);
00279 na->add (n2);
00280 na->add (n1);
00281
00282
00283 sgVec2 tc1, tc2, tc3;
00284 sgSetVec2 (tc1, vt[i1].u, vt[i1].v);
00285 sgSetVec2 (tc2, vt[i2].u, vt[i2].v);
00286 sgSetVec2 (tc3, vt[i3].u, vt[i3].v);
00287 tca->add (tc3);
00288 tca->add (tc2);
00289 tca->add (tc1);
00290 }
00291
00292
00293 delete vt;
00294
00295
00296 static const float epsilon = (float)1e-3;
00297 float kfStep = 1.0f / 30.0f;
00298 for (int m=0; m<31; m++) {
00299
00300 float dx, dy, dz, pitch, bank, hdg;
00301 pgets (s, LINE_LENGTH, p);
00302 if (sscanf (s, "%f,%f,%f,%f,%f,%f",
00303 &dx, &dy, &dz, &pitch, &bank, &hdg) != 6)
00304 {
00305
00306 gtfo ("CModelACM : Error parsing animation frame %d for part %d in %s",
00307 m, i, acmFilename) ;
00308 }
00309
00310
00311 if (fabs(dx) < epsilon) dx = 0.0f;
00312 if (fabs(dy) < epsilon) dy = 0.0f;
00313 if (fabs(dz) < epsilon) dz = 0.0f;
00314 if (fabs(pitch) < epsilon) pitch = 0.0f;
00315 if (fabs(bank) < epsilon) bank = 0.0f;
00316 if (fabs(hdg) < epsilon) hdg = 0.0f;
00317
00318 pitch = WrapTwoPi (pitch);
00319 bank = WrapTwoPi (bank);
00320 hdg = WrapTwoPi (hdg);
00321
00322
00323
00325
00326 sgCoord kf;
00327 sgSetCoord (&kf,
00328 dx,
00329 dz,
00330 dy,
00331 -hdg * SG_RADIANS_TO_DEGREES,
00332 -pitch * SG_RADIANS_TO_DEGREES,
00333 -bank * SG_RADIANS_TO_DEGREES
00334 );
00335
00336 xform->addKeyframe (kfStep * (float)m, &kf);
00337 }
00338
00339
00340 xform->setKeyframe (0.0f);
00341
00342
00343 ssgVtxTable *vtab = new ssgVtxTable (GL_TRIANGLES, va, na, tca, NULL);
00344 vtab->setName (name);
00345 vtab->setState (state);
00346
00347 xform->setName (name);
00348 xform->addKid (vtab);
00349
00350
00351 parent->addKid (xform);
00352 }
00353
00354
00355 delete parentList;
00356
00357
00358 pclose (p);
00359 }
00360
00361 CModelACM::~CModelACM (void)
00362 {
00363 if (top->getRef() == 0) {
00364 top->removeAllKids();
00365 delete top;
00366 }
00367 if (tifftexture != NULL) delete tifftexture;
00368 }
00369
00370 ssgEntity *CModelACM::GetSSGEntity (void)
00371 {
00372 return top;
00373 }
00374