for (i = 0; i objcount; i++) { g = clp->atm[i].geometryindex; f = clp->atm[i].frameindex; if (clp->frm[f].display == 0) continue; glPushMatrix(); TransformFrame(clp->frm, f); // DrawAxis(); for (j = 0; j < clp->geo[g].splitcount; j++) { istransparent = 0; splt = &clp->geo[g].splt[j]; vert = clp->geo[g].vertices; norm = clp->geo[g].normals; vc = clp->geo[g].vc; uv = clp->geo[g].uv[0]; /* Disable reflection map and unbind any textures */ glActiveTextureARB(GL_TEXTURE2_ARB); glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glBindTexture(GL_TEXTURE_2D, 0); glActiveTextureARB(GL_TEXTURE0_ARB); glBindTexture(GL_TEXTURE_2D, 0); /* Bind a diffuse map if we have one */ if (clp->geo[g].mat[splt->matindex].hastexture) { t = &clp->geo[g].mat[splt->matindex].tex; texindex = GetTextureIndex(mdl->texturefiles, t->tex); glActiveTextureARB(GL_TEXTURE0_ARB); glBindTexture(GL_TEXTURE_2D, mdl->textures[texindex]); /* If we have an alpha, use this instead */ if (strcmp(t->alpha, "") != 0) istransparent = 1; if (0) { // if (strcmp(t->alpha, "") != 0) { glActiveTextureARB(GL_TEXTURE1_ARB); glClientActiveTextureARB(GL_TEXTURE1_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_ALPHA); texindex = GetTextureIndex(mdl-> texturefiles, t->alpha); glBindTexture(GL_TEXTURE_2D, mdl->textures[texindex]); istransparent = 1; } // glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } /* Bind a reflection map if we have one */ if (clp->geo[g].mat[splt->matindex].hasreflection) { t = &clp->geo[g].mat[splt->matindex].reflection; texindex = GetTextureIndex(mdl->texturefiles, t->tex); glActiveTextureARB(GL_TEXTURE2_ARB); glBindTexture(GL_TEXTURE_2D, mdl->textures[texindex]); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD); } /* Set Colors to material color */ color[0] = (float) clp->geo[g].mat[splt->matindex].color[0]/255; color[1] = (float) clp->geo[g].mat[splt->matindex].color[1]/255; color[2] = (float) clp->geo[g].mat[splt->matindex].color[2]/255; color[3] = (float) clp->geo[g].mat[splt->matindex].color[3]/255; if (color[3] != 1.0) istransparent = 1; /* If the split is transparent and we don't want * to draw it (or vice versa), skip to the next */ if (istransparent != disptrans) continue; glDisable(GL_BLEND); if (istransparent) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color); if (clp->geo[g].facetype == 1) { glBegin(GL_TRIANGLE_STRIP); for (k = 0; k < splt->indexcount-2; k++) { int m; for (m = 0; m < 3; m++) { l = splt->indices[k+m]; if (clp->geo[g].normaltype == 0) glNormal3fv(norm[l]); else if (clp->geo[g].normaltype == 1) glNormal3fv(splt->normals[k]); else { fprintf(stderr,"Unknown normal type\n"); exitprog(0); } if (clp->geo[g].newuvsets >= 1) glMultiTexCoord2f(GL_TEXTURE0_ARB, uv[l][0], uv[l][1]); glVertex3fv(vert[l]); } } glEnd(); } else { glBegin(GL_TRIANGLES); for (k = 0; k < splt->indexcount; k++) { l = splt->indices[k]; if (clp->geo[g].normaltype == 0) glNormal3fv(norm[l]); else if (clp->geo[g].normaltype == 2) glNormal3fv(splt->normals[k/3]); else { fprintf(stderr,"Unknown normal type\n"); exitprog(0); } if (clp->geo[g].newuvsets >= 1) glMultiTexCoord2f(GL_TEXTURE0_ARB, uv[l][0], uv[l][1]); glVertex3fv(vert[l]); } glEnd(); } // if ((clp->geo[g].flags & HASVCOLORS) != 0) { // color[0] = (float) vc[0]/255; // color[1] = (float) vc[1]/255; // color[2] = (float) vc[2]/255; // color[3] = (float) vc[3]/255; // glMaterialfv(GL_FRONT_AND_BACK, // GL_DIFFUSE, color); // } else { // color[0] = (float) 128/255; // color[1] = (float) 128/255; // color[2] = (float) 128/255; // color[3] = (float) 255/255; // glMaterialfv(GL_FRONT_AND_BACK, // GL_DIFFUSE, color); // } glPopMatrix(); void LoadTextures(Model *mdl) int i, j; int found; found = 0; glEnable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glGenTextures(mdl->texturecount, mdl->textures); for (i = 0; i < mdl->texturecount; i++) { glBindTexture(GL_TEXTURE_2D, mdl->textures[i]); for (j = 0; j < mdl->txdcount; j++) { if (strcmp(mdl->texturefiles[i], mdl->texlist[j].name) == 0 || strcmp(mdl->texturefiles[i], mdl->texlist[j].alpha) == 0) { found = 1; break; } else found = 0; if (!found) continue; if (mdl->texlist[j].bpp == 8 || mdl->texlist[j].bpp == 4) { printf("paletted picture\n"); glTexImage2D(GL_TEXTURE_2D, 0, mdl->texlist[j].channels, mdl->texlist[j].width, mdl->texlist[j].height, 0, mdl->texlist[j].format, GL_UNSIGNED_BYTE, mdl->texlist[j].data[0]); } else if (mdl->texlist[j].bpp == 16) { printf("16 bit picture..not supported\n"); exitprog(0); switch (mdl->texlist[j].compression) { case 1: if (mdl->texlist[j].hasalpha) glCompressedTexImage2DARB(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, mdl->texlist[j].width, mdl->texlist[j].height, 0, mdl->texlist[j].size, mdl->texlist[j].data[0]); else glCompressedTexImage2DARB(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, mdl->texlist[j].width, mdl->texlist[j].height, 0, mdl->texlist[j].size, mdl->texlist[j].data[0]); break; case 3: glCompressedTexImage2DARB(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, mdl->texlist[j].width, mdl->texlist[j].height, 0, mdl->texlist[j].size, mdl->texlist[j].data[0]); break; case 5: glCompressedTexImage2DARB(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, mdl->texlist[j].width, mdl->texlist[j].height, 0, mdl->texlist[j].size, mdl->texlist[j].data); break; default: printf("Unknown compression format\n"); exitprog(0); } } else if (mdl->texlist[j].bpp == 32) { glTexImage2D(GL_TEXTURE_2D, 0, 4, mdl->texlist[j].width, mdl->texlist[j].height, 0, GL_RGBA, GL_UNSIGNED_BYTE, mdl->texlist[j].data_a[0]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); void RenderScene(void) int i; finish = clock() ; duration += (double)(finish - start) / CLOCKS_PER_SEC ; frames ++ ; FPS = frames / duration ; start = clock() ; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluOrtho2D(0.0f, 1.0f, 0.0f, 1.0f); glMatrixMode(GL_MODELVIEW); PrintFPS(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glTranslatef(xPos, yPos, zPos); glRotatef(xRot, 1.0f, 0.0f, 0.0f); glRotatef(yRot, 0.0f, 1.0f, 0.0f); glRotatef(zRot, 0.0f, 0.0f, 1.0f); /* Display solid objects */ for (i = 0; i < objscount; i++) DisplayModel(objs[i].mdl, 0); /* Display transparent objects */ for (i = 0; i < objscount; i++) DisplayModel(objs[i].mdl, 1); glutSwapBuffers(); void SpecialKeyPressed(int key, int x, int y) switch (key) { case GLUT_KEY_UP: if (glutGetModifiers() == GLUT_ACTIVE_SHIFT) xRot -= 2.0f; else xRot -= 0.7f; break; case GLUT_KEY_DOWN: if (glutGetModifiers() == GLUT_ACTIVE_SHIFT) xRot += 2.0f; else xRot += 0.7f; break; case GLUT_KEY_LEFT: if (glutGetModifiers() == GLUT_ACTIVE_SHIFT) zRot -= 2.0f; else zRot -= 0.7f; break; case GLUT_KEY_RIGHT: if (glutGetModifiers() == GLUT_ACTIVE_SHIFT) zRot += 2.0f; else zRot += 0.7f; break; case GLUT_KEY_PAGE_UP: if (glutGetModifiers() == GLUT_ACTIVE_SHIFT) zPos += 0.7f; else zPos += 0.2f; break; case GLUT_KEY_PAGE_DOWN: if (glutGetModifiers() == GLUT_ACTIVE_SHIFT) zPos -= 0.7f; else zPos -= 0.2f; break; default: break; glutPostRedisplay(); void isvisible(void) if (objs[whichobj].mdl->clp->frm[whichframe].display == 1) printf("Object \"%s\" is visible.\n", objs[whichobj].mdl->clp->frm[whichframe].name); else printf("Object \"%s\" is not visible.\n", objs[whichobj].mdl->clp->frm[whichframe].name); void KeyPressed(unsigned char key, int z, int y) switch(key) { case 'q': yRot -= 0.7f; break; case 'Q': yRot -= 2.0f; break; case 'e': yRot += 0.7f; break; case 'E': yRot += 2.0f; break; case 'h': xPos += 0.1f; break; case 'H': xPos += 0.2f; break; case 'j': yPos += 0.1f; break; case 'J': yPos += 0.2f; break; case 'k': yPos -= 0.1f; break; case 'K': yPos -= 0.2f; break; case 'l': xPos -= 0.1f; break; case 'L': xPos -= 0.2f; break; case 't': case 'T': if (textured == 1) glDisable(GL_TEXTURE_2D); else glEnable(GL_TEXTURE_2D); textured = !textured; break; case 'O': if (whichobj == 0) whichobj = objscount; whichobj--; whichframe = 0; isvisible(); break; case 'o': whichobj++; if (whichobj == objscount) whichobj = 0; isvisible(); break; case 'F': if (whichframe == 0) whichframe = objs[whichobj].mdl->clp->frmcount; whichframe--; isvisible(); break; case 'f': whichframe++; if (whichframe == objs[whichobj].mdl->clp->frmcount) whichframe = 0; isvisible(); break; case 'V': case 'v': objs[whichobj].mdl->clp->frm[whichframe].display = !objs[whichobj].mdl->clp->frm[whichframe].display; isvisible(); break; case 'c': case 'C': printf("\nCamera position: %f %f %f\n", xPos, yPos, zPos); printf("Camera roatation: %f %f %f\n\n", xRot, yRot, zRot); break; case 'i': case 'I': objscount = 0; if (objs != NULL) { DestroyObjs(objs); free(objs); if ((objs = ReadIde(ide)) == NULL) { objscount = 0; exitprog(0); objs->mdl = LoadModel(objs->Model, objs->Texture, img, 0); objscount = 1; break; case ESCAPE: exitprog(0); default: break; glutPostRedisplay(); void ChangeSize(int w, int h) if(h == 0) h = 1; glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f, (GLfloat) w/(GLfloat)h, 0.1f, 2000.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glLightfv(GL_LIGHT0, GL_POSITION, LightPosition); glTranslatef(0.0f, 0.0f, 0.0f); Model *LoadModel(char *dfffile, char *txdfile, FILE **img, int arnum) int generictxd; int i; DirEntry *dff, *txd; Model *mdl; UseTextures = 1; txd = NULL; dff = GetFileOffset(filenum[arnum], filelist[arnum], dfffile); if (dff == NULL) { fprintf(stderr, "Could not find %s in img file\n", dfffile); exitprog(0); if (strcmp(txdfile, "generic.txd") == 0) generictxd = 1; else generictxd = 0; if (!generictxd) { txd = GetFileOffset(filenum[arnum], filelist[arnum], txdfile); if (txd == NULL) { fprintf(stderr, "Could not find %s in img file\n", txdfile); exitprog(0); mdl = (Model *) malloc(sizeof(Model)); mdl->clp = (clump *) malloc(sizeof(clumHX