/*! * Render node recursively, first children, then parent. * Each node receives its own OpenGL display list. */ static void render_node(Lib3dsNode *node) { ASSERT(file); { Lib3dsNode *p; for (p=node->childs; p!=0; p=p->next) { render_node(p); } } if (node->type==LIB3DS_OBJECT_NODE) { Lib3dsMesh *mesh; if (strcmp(node->name,"$$$DUMMY")==0) { return; } mesh = lib3ds_file_mesh_by_name(file, node->data.object.morph); if( mesh == NULL ) mesh = lib3ds_file_mesh_by_name(file, node->name); if (!mesh->user.d) { ASSERT(mesh); if (!mesh) { return; } mesh->user.d=glGenLists(1); glNewList(mesh->user.d, GL_COMPILE); { unsigned p; Lib3dsVector *normalL=malloc(3*sizeof(Lib3dsVector)*mesh->faces); Lib3dsMaterial *oldmat = (Lib3dsMaterial *)-1; { Lib3dsMatrix M; lib3ds_matrix_copy(M, mesh->matrix); lib3ds_matrix_inv(M); glMultMatrixf(&M[0][0]); } lib3ds_mesh_calculate_normals(mesh, normalL); for (p=0; p<mesh->faces; ++p) { Lib3dsFace *f=&mesh->faceL[p]; Lib3dsMaterial *mat=0; #ifdef USE_SDL Player_texture *pt = NULL; int tex_mode = 0; #endif if (f->material[0]) { mat=lib3ds_file_material_by_name(file, f->material); } if( mat != oldmat ) { if (mat) { if( mat->two_sided ) glDisable(GL_CULL_FACE); else glEnable(GL_CULL_FACE); glDisable(GL_CULL_FACE); /* Texturing added by Gernot < *****@*****.** > */ if (mat->texture1_map.name[0]) { /* texture map? */ Lib3dsTextureMap *tex = &mat->texture1_map; if (!tex->user.p) { /* no player texture yet? */ char texname[1024]; pt = malloc(sizeof(*pt)); tex->user.p = pt; //snprintf(texname, sizeof(texname), "%s/%s", datapath, tex->name); strcpy(texname, datapath); strcat(texname, "/"); strcat(texname, tex->name); #ifdef DEBUG printf("Loading texture map, name %s\n", texname); #endif /* DEBUG */ #ifdef USE_SDL #ifdef USE_SDL_IMG_load pt->bitmap = IMG_load(texname); #else pt->bitmap = IMG_Load(texname); #endif /* IMG_Load */ #else /* USE_SDL */ pt->bitmap = NULL; fputs("3dsplayer: Warning: No image loading support, skipping texture.\n", stderr); #endif /* USE_SDL */ if (pt->bitmap) { /* could image be loaded ? */ /* this OpenGL texupload code is incomplete format-wise! * to make it complete, examine SDL_surface->format and * tell us @lib3ds.sf.net about your improvements :-) */ int upload_format = GL_RED; /* safe choice, shows errors */ #ifdef USE_SDL int bytespp = pt->bitmap->format->BytesPerPixel; void *pixel = NULL; glGenTextures(1, &pt->tex_id); #ifdef DEBUG printf("Uploading texture to OpenGL, id %d, at %d bytepp\n", pt->tex_id, bytespp); #endif /* DEBUG */ if (pt->bitmap->format->palette) { pixel = convert_to_RGB_Surface(pt->bitmap); upload_format = GL_RGBA; } else { pixel = pt->bitmap->pixels; /* e.g. this could also be a color palette */ if (bytespp == 1) upload_format = GL_LUMINANCE; else if (bytespp == 3) upload_format = GL_RGB; else if (bytespp == 4) upload_format = GL_RGBA; } glBindTexture(GL_TEXTURE_2D, pt->tex_id); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEX_XSIZE, TEX_YSIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, pt->bitmap->w, pt->bitmap->h, upload_format, GL_UNSIGNED_BYTE, pixel); pt->scale_x = (float)pt->bitmap->w/(float)TEX_XSIZE; pt->scale_y = (float)pt->bitmap->h/(float)TEX_YSIZE; #endif /* USE_SDL */ pt->valid = 1; } else { fprintf(stderr, "Load of texture %s did not succeed " "(format not supported !)\n", texname); pt->valid = 0; } } else { pt = (Player_texture *)tex->user.p; } tex_mode = pt->valid; } else { tex_mode = 0; } glMaterialfv(GL_FRONT, GL_AMBIENT, mat->ambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat->diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat->specular); glMaterialf(GL_FRONT, GL_SHININESS, pow(2, 10.0*mat->shininess)); } else { static const Lib3dsRgba a={0.7, 0.7, 0.7, 1.0}; static const Lib3dsRgba d={0.7, 0.7, 0.7, 1.0}; static const Lib3dsRgba s={1.0, 1.0, 1.0, 1.0}; glMaterialfv(GL_FRONT, GL_AMBIENT, a); glMaterialfv(GL_FRONT, GL_DIFFUSE, d); glMaterialfv(GL_FRONT, GL_SPECULAR, s); glMaterialf(GL_FRONT, GL_SHININESS, pow(2, 10.0*0.5)); } oldmat = mat; } else if (mat != NULL && mat->texture1_map.name[0]) { Lib3dsTextureMap *tex = &mat->texture1_map; if (tex != NULL && tex->user.p != NULL) { pt = (Player_texture *)tex->user.p; tex_mode = pt->valid; } } { int i; if (tex_mode) { //printf("Binding texture %d\n", pt->tex_id); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, pt->tex_id); } glBegin(GL_TRIANGLES); glNormal3fv(f->normal); for (i=0; i<3; ++i) { glNormal3fv(normalL[3*p+i]); if (tex_mode) { glTexCoord2f(mesh->texelL[f->points[i]][1]*pt->scale_x, pt->scale_y - mesh->texelL[f->points[i]][0]*pt->scale_y); } glVertex3fv(mesh->pointL[f->points[i]].pos); } glEnd(); if (tex_mode) glDisable(GL_TEXTURE_2D); } } free(normalL); } glEndList(); } if (mesh->user.d) { Lib3dsObjectData *d; glPushMatrix(); d=&node->data.object; glMultMatrixf(&node->matrix[0][0]); glTranslatef(-d->pivot[0], -d->pivot[1], -d->pivot[2]); glCallList(mesh->user.d); /* glutSolidSphere(50.0, 20,20); */ glPopMatrix(); if( flush ) glFlush(); } } }
/*! * Render node recursively, first children, then parent. * Each node receives its own OpenGL display list. */ static void render_node(Lib3dsNode *node) { assert(file); { Lib3dsNode *p; for (p = node->childs; p != 0; p = p->next) { render_node(p); } } if (node->type == LIB3DS_NODE_MESH_INSTANCE) { int index; Lib3dsMesh *mesh; Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; if (strcmp(node->name, "$$$DUMMY") == 0) { return; } index = lib3ds_file_mesh_by_name(file, n->instance_name); if (index < 0) index = lib3ds_file_mesh_by_name(file, node->name); if (index < 0) { return; } mesh = file->meshes[index]; if (!mesh->user_id) { assert(mesh); mesh->user_id = glGenLists(1); glNewList(mesh->user_id, GL_COMPILE); { int p; float (*normalL)[3] = (float(*)[3])malloc(3 * 3 * sizeof(float) * mesh->nfaces); Lib3dsMaterial *oldmat = (Lib3dsMaterial *) - 1; { float M[4][4]; lib3ds_matrix_copy(M, mesh->matrix); lib3ds_matrix_inv(M); glMultMatrixf(&M[0][0]); } lib3ds_mesh_calculate_vertex_normals(mesh, normalL); for (p = 0; p < mesh->nfaces; ++p) { Lib3dsMaterial *mat = 0; #ifdef USE_SDL Player_texture *pt = NULL; int tex_mode = 0; #endif if (mesh->faces[p].material > 0) { mat = file->materials[mesh->faces[p].material]; } if (mat != oldmat) { if (mat) { if (mat->two_sided) glDisable(GL_CULL_FACE); else glEnable(GL_CULL_FACE); glDisable(GL_CULL_FACE); /* Texturing added by Gernot < *****@*****.** > */ if (mat->texture1_map.name[0]) { /* texture map? */ Lib3dsTextureMap *tex = &mat->texture1_map; if (!tex->user_ptr) { /* no player texture yet? */ char texname[1024]; pt = (Player_texture*)malloc(sizeof(*pt)); tex->user_ptr = pt; //snprintf(texname, sizeof(texname), "%s/%s", datapath, tex->name); strcpy(texname, datapath); strcat(texname, "/"); strcat(texname, tex->name); #ifdef DEBUG printf("Loading texture map, name %s\n", texname); #endif /* DEBUG */ #ifdef USE_SDL #ifdef USE_SDL_IMG_load pt->bitmap = IMG_load(texname); #else pt->bitmap = IMG_Load(texname); #endif /* IMG_Load */ #else /* USE_SDL */ pt->bitmap = NULL; fputs("3dsplayer: Warning: No image loading support, skipping texture.\n", stderr); #endif /* USE_SDL */ if (pt->bitmap) { /* could image be loaded ? */ /* this OpenGL texupload code is incomplete format-wise! * to make it complete, examine SDL_surface->format and * tell us @lib3ds.sf.net about your improvements :-) */ int upload_format = GL_RED; /* safe choice, shows errors */ #ifdef USE_SDL int bytespp = pt->bitmap->format->BytesPerPixel; void *pixel = NULL; glGenTextures(1, &pt->tex_id); #ifdef DEBUG printf("Uploading texture to OpenGL, id %d, at %d bytepp\n", pt->tex_id, bytespp); #endif /* DEBUG */ if (pt->bitmap->format->palette) { pixel = convert_to_RGB_Surface(pt->bitmap); upload_format = GL_RGBA; } else { pixel = pt->bitmap->pixels; /* e.g. this could also be a color palette */ if (bytespp == 1) upload_format = GL_LUMINANCE; else if (bytespp == 3) upload_format = GL_RGB; else if (bytespp == 4) upload_format = GL_RGBA; } glBindTexture(GL_TEXTURE_2D, pt->tex_id); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEX_XSIZE, TEX_YSIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, pt->bitmap->w, pt->bitmap->h, upload_format, GL_UNSIGNED_BYTE, pixel); pt->scale_x = (float)pt->bitmap->w / (float)TEX_XSIZE; pt->scale_y = (float)pt->bitmap->h / (float)TEX_YSIZE; #endif /* USE_SDL */ pt->valid = 1; } else { fprintf(stderr, "Load of texture %s did not succeed " "(format not supported !)\n", texname); pt->valid = 0; } } else { pt = (Player_texture *)tex->user_ptr; } tex_mode = pt->valid; } else { tex_mode = 0; } { float a[4], d[4], s[4]; int i; for (i=0; i<3; ++i) { a[i] = mat->ambient[i]; d[i] = mat->diffuse[i]; s[i] = mat->specular[i]; } a[3] = d[3] = s[3] = 1.0f; glMaterialfv(GL_FRONT, GL_AMBIENT, a); glMaterialfv(GL_FRONT, GL_DIFFUSE, d); glMaterialfv(GL_FRONT, GL_SPECULAR, s); } glMaterialf(GL_FRONT, GL_SHININESS, pow(2, 10.0*mat->shininess)); } else { static const float a[4] = {0.7, 0.7, 0.7, 1.0}; static const float d[4] = {0.7, 0.7, 0.7, 1.0}; static const float s[4] = {1.0, 1.0, 1.0, 1.0}; glMaterialfv(GL_FRONT, GL_AMBIENT, a); glMaterialfv(GL_FRONT, GL_DIFFUSE, d); glMaterialfv(GL_FRONT, GL_SPECULAR, s); glMaterialf(GL_FRONT, GL_SHININESS, pow(2, 10.0*0.5)); } oldmat = mat; } else if (mat != NULL && mat->texture1_map.name[0]) { Lib3dsTextureMap *tex = &mat->texture1_map; if (tex != NULL && tex->user_ptr != NULL) { pt = (Player_texture *)tex->user_ptr; tex_mode = pt->valid; } } { int i; #ifndef USE_GL10 if (tex_mode) { //printf("Binding texture %d\n", pt->tex_id); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, pt->tex_id); } #endif #if 0 { float v1[3], n[3], v2[3]; glBegin(GL_LINES); for (i = 0; i < 3; ++i) { lib3ds_vector_copy(v1, mesh->vertices[f->points[i]]); glVertex3fv(v1); lib3ds_vector_copy(n, normalL[3*p+i]); lib3ds_vector_scalar(n, 10.f); lib3ds_vector_add(v2, v1, n); glVertex3fv(v2); } glEnd(); } #endif glBegin(GL_TRIANGLES); for (i = 0; i < 3; ++i) { glNormal3fv(normalL[3*p+i]); if (tex_mode) { glTexCoord2f( mesh->texcos[mesh->faces[p].index[i]][1]*pt->scale_x, pt->scale_y - mesh->texcos[mesh->faces[p].index[i]][0]*pt->scale_y); } glVertex3fv(mesh->vertices[mesh->faces[p].index[i]]); } glEnd(); if (tex_mode) glDisable(GL_TEXTURE_2D); } } free(normalL); } glEndList(); } if (mesh->user_id) { glPushMatrix(); glMultMatrixf(&node->matrix[0][0]); glTranslatef(-n->pivot[0], -n->pivot[1], -n->pivot[2]); glCallList(mesh->user_id); /* glutSolidSphere(50.0, 20,20); */ glPopMatrix(); if (flush) glFlush(); } } }