static void point_array_write(Lib3dsMesh *mesh, Lib3dsIo *io) { Lib3dsChunk c; int i; c.chunk = CHK_POINT_ARRAY; c.size = 8 + 12 * mesh->nvertices; lib3ds_chunk_write(&c, io); lib3ds_io_write_word(io, (uint16_t) mesh->nvertices); if (lib3ds_matrix_det(mesh->matrix) >= 0.0f) { for (i = 0; i < mesh->nvertices; ++i) { lib3ds_io_write_vector(io, mesh->vertices[i]); } } else { /* Flip X coordinate of vertices if mesh matrix has negative determinant */ float inv_matrix[4][4], M[4][4]; float tmp[3]; lib3ds_matrix_copy(inv_matrix, mesh->matrix); lib3ds_matrix_inv(inv_matrix); lib3ds_matrix_copy(M, mesh->matrix); lib3ds_matrix_scale(M, -1.0f, 1.0f, 1.0f); lib3ds_matrix_mult(M, M, inv_matrix); for (i = 0; i < mesh->nvertices; ++i) { lib3ds_vector_transform(tmp, M, mesh->vertices[i]); lib3ds_io_write_vector(io, tmp); } } }
/*! * \ingroup matrix */ void lib3ds_matrix_rotate(Lib3dsMatrix m, Lib3dsQuat q) { Lib3dsFloat s,xs,ys,zs,wx,wy,wz,xx,xy,xz,yy,yz,zz,l; Lib3dsMatrix a,b; lib3ds_matrix_copy(a, m); l=q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]; if (fabs(l)<LIB3DS_EPSILON) { s=1.0f; } else { s=2.0f/l; } xs = q[0] * s; ys = q[1] * s; zs = q[2] * s; wx = q[3] * xs; wy = q[3] * ys; wz = q[3] * zs; xx = q[0] * xs; xy = q[0] * ys; xz = q[0] * zs; yy = q[1] * ys; yz = q[1] * zs; zz = q[2] * zs; b[0][0]=1.0f - (yy +zz); b[1][0]=xy - wz; b[2][0]=xz + wy; b[0][1]=xy + wz; b[1][1]=1.0f - (xx +zz); b[2][1]=yz - wx; b[0][2]=xz - wy; b[1][2]=yz + wx; b[2][2]=1.0f - (xx + yy); b[3][0]=b[3][1]=b[3][2]=b[0][3]=b[1][3]=b[2][3]=0.0f; b[3][3]=1.0f; lib3ds_matrix_mul(m,a,b); }
void draw3DSNode(Lib3dsNode *node) { Lib3dsNode *n; for(n=node->childs;n!=NULL;n=n->next) draw3DSNode(n); if(node->type==LIB3DS_OBJECT_NODE) { int i; Lib3dsMesh *mesh=NULL; Lib3dsVector *normals=NULL; Lib3dsMatrix M; if(strcmp(node->name,"$$$DUMMY")==0) return; mesh=lib3ds_file_mesh_by_name(file,node->name); if(!mesh) return; /* apply mesh transformation */ lib3ds_matrix_copy(M,mesh->matrix); lib3ds_matrix_inv(M); glMultMatrixf(&M[0][0]); /* calculate normals */ normals=malloc(3*sizeof(Lib3dsVector)*mesh->faces); lib3ds_mesh_calculate_normals(mesh,normals); for(i=0;i<mesh->faces;i++) { Lib3dsFace *face=&mesh->faceL[i]; Lib3dsMaterial *mat=NULL; /* materials */ if(face->material[0]) mat=lib3ds_file_material_by_name(file,face->material); if(mat) { float shine; glMaterialfv(GL_FRONT,GL_AMBIENT,mat->ambient); glMaterialfv(GL_FRONT,GL_DIFFUSE,mat->diffuse); glMaterialfv(GL_FRONT,GL_SPECULAR,mat->specular); shine=pow(2.0,10.0*mat->shininess); if(shine>128.0) shine=128.0; glMaterialf(GL_FRONT,GL_SHININESS,shine); } else { static GLfloat amb[4]={0.2,0.2,0.2,1.0}; static GLfloat diff[4]={0.8,0.8,0.8,1.0}; static GLfloat spec[4]={0.0,0.0,0.0,1.0}; glMaterialfv(GL_FRONT,GL_AMBIENT,amb); glMaterialfv(GL_FRONT,GL_DIFFUSE,diff); glMaterialfv(GL_FRONT,GL_SPECULAR,spec); } /* vertices */ srelBegin(GL_TRIANGLES); srelNormal3fv(normals[3*i]); srelVertex3fv(mesh->pointL[face->points[0]].pos); srelNormal3fv(normals[3*i+1]); srelVertex3fv(mesh->pointL[face->points[1]].pos); srelNormal3fv(normals[3*i+2]); srelVertex3fv(mesh->pointL[face->points[2]].pos); srelEnd(); } free(normals); } }
static Lib3dsBool point_array_write(Lib3dsMesh *mesh, Lib3dsIo *io) { Lib3dsChunk c; unsigned i; if (!mesh->points || !mesh->pointL) { return(LIB3DS_TRUE); } ASSERT(mesh->points<0x10000); c.chunk=LIB3DS_POINT_ARRAY; c.size=8+12*mesh->points; lib3ds_chunk_write(&c, io); lib3ds_io_write_word(io, (Lib3dsWord)mesh->points); if (lib3ds_matrix_det(mesh->matrix) >= 0.0f) { for (i=0; i<mesh->points; ++i) { lib3ds_io_write_vector(io, mesh->pointL[i].pos); } } else { /* Flip X coordinate of vertices if mesh matrix has negative determinant */ Lib3dsMatrix inv_matrix, M; Lib3dsVector tmp; lib3ds_matrix_copy(inv_matrix, mesh->matrix); lib3ds_matrix_inv(inv_matrix); lib3ds_matrix_copy(M, mesh->matrix); lib3ds_matrix_scale_xyz(M, -1.0f, 1.0f, 1.0f); lib3ds_matrix_mult(M, inv_matrix); for (i=0; i<mesh->points; ++i) { lib3ds_vector_transform(tmp, M, mesh->pointL[i].pos); lib3ds_io_write_vector(io, tmp); } } return(LIB3DS_TRUE); }
/*! * \internal * * The objects created as children of \p parent will \em not be rotated or * translated correctly. Instead the required transformations are stored and * provided to the user, see \ref Loader3ds::getTransformationNodes */ bool Loader3dsInternal::loadNode(dcollide::World* world, dcollide::Proxy* parent, Lib3dsNode* node, Lib3dsMatrix* parentTranslateRotateMatrix) { if (!parent || !node) { return false; } if (node->type != LIB3DS_OBJECT_NODE) { return false; } Lib3dsObjectData* data = &node->data.object; Lib3dsMatrix translateRotateMatrix; lib3ds_matrix_copy(translateRotateMatrix, *parentTranslateRotateMatrix); lib3ds_matrix_translate(translateRotateMatrix, data->pos); lib3ds_matrix_rotate(translateRotateMatrix, data->rot); dcollide::Shape* shape = createShape(node, &translateRotateMatrix); dcollide::Proxy* object = world->createProxy(shape); mData->mProxy2TextureInformation.insert(std::make_pair(object, loadTextureInformation(node))); dcollide::Vector3 scale(data->scl[0], data->scl[1], data->scl[2]); dcollide::Vector3 translation(data->pos[0], data->pos[1], data->pos[2]); Lib3dsMatrix lib3dsRotationMatrix; lib3ds_matrix_identity(lib3dsRotationMatrix); lib3ds_matrix_rotate(lib3dsRotationMatrix, data->rot); dcollide::Matrix rotation(&lib3dsRotationMatrix[0][0]); Loader3ds::TransformationNode transformation; transformation.translation = translation; transformation.rotation = rotation; mData->mProxy2Transformation.insert(std::make_pair(object, transformation)); for (Lib3dsNode* n = node->childs; n; n = n->next) { if (!loadNode(world, object, n, &translateRotateMatrix)) { std::cerr << "Failed loading node " << n->name << std::endl; // TODO: delete object->getProxy() ? delete object; return false; } } parent->addChild(object); return true; }
void lib3ds_file_bounding_box_of_nodes(Lib3dsFile *file, int include_meshes, int include_cameras,int include_lights, float bmin[3], float bmax[3], float matrix[4][4]) { Lib3dsNode *p; float M[4][4]; if (matrix) { lib3ds_matrix_copy(M, matrix); } else { lib3ds_matrix_identity(M); } bmin[0] = bmin[1] = bmin[2] = FLT_MAX; bmax[0] = bmax[1] = bmax[2] = -FLT_MAX; p = file->nodes; while (p) { file_bounding_box_of_nodes_impl(p, file, include_meshes, include_cameras, include_lights, bmin, bmax, M); p = p->next; } }
void x3ds_instance::create_mesh_list(Lib3dsMesh* mesh) { Lib3dsVector* normalL = (Lib3dsVector*) malloc(3 * sizeof(Lib3dsVector) * mesh->faces); Lib3dsMatrix m; lib3ds_matrix_copy(m, mesh->matrix); lib3ds_matrix_inv(m); glMultMatrixf(&m[0][0]); lib3ds_mesh_calculate_normals(mesh, normalL); Lib3dsMaterial* prev_mat = NULL; for (Uint32 p = 0; p < mesh->faces; ++p) { Lib3dsFace* f = &mesh->faceL[p]; Lib3dsMaterial* mat = f->material[0] ? lib3ds_file_material_by_name(m_def->m_file, f->material) : NULL; if (prev_mat != mat) { set_material(mat); } glBegin(GL_TRIANGLES); glNormal3fv(f->normal); for (int i = 0; i < 3; ++i) { glNormal3fv(normalL[3 * p + i]); if (mesh->texelL) { bind_material(mat, mesh->texelL[f->points[i]][1], mesh->texelL[f->points[i]][0]); } glVertex3fv(mesh->pointL[f->points[i]].pos); } glEnd(); glDisable(GL_TEXTURE_2D); } free(normalL); }
/*! * Evaluate an animation node. * * Recursively sets node and its children to their appropriate values * for this point in the animation. * * \param node Node to be evaluated. * \param t time value, between 0. and file->frames */ void lib3ds_node_eval(Lib3dsNode *node, float t) { assert(node); switch (node->type) { case LIB3DS_NODE_AMBIENT_COLOR: { Lib3dsAmbientColorNode *n = (Lib3dsAmbientColorNode*)node; if (node->parent) { lib3ds_matrix_copy(node->matrix, node->parent->matrix); } else { lib3ds_matrix_identity(node->matrix); } lib3ds_track_eval_vector(&n->color_track, n->color, t); break; } case LIB3DS_NODE_MESH_INSTANCE: { float M[4][4]; Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; lib3ds_track_eval_vector(&n->pos_track, n->pos, t); lib3ds_track_eval_quat(&n->rot_track, n->rot, t); if (n->scl_track.nkeys) { lib3ds_track_eval_vector(&n->scl_track, n->scl, t); } else { n->scl[0] = n->scl[1] = n->scl[2] = 1.0f; } lib3ds_track_eval_bool(&n->hide_track, &n->hide, t); lib3ds_matrix_identity(M); lib3ds_matrix_translate(M, n->pos[0], n->pos[1], n->pos[2]); lib3ds_matrix_rotate_quat(M, n->rot); lib3ds_matrix_scale(M, n->scl[0], n->scl[1], n->scl[2]); if (node->parent) { lib3ds_matrix_mult(node->matrix, node->parent->matrix, M); } else { lib3ds_matrix_copy(node->matrix, M); } break; } case LIB3DS_NODE_CAMERA: { Lib3dsCameraNode *n = (Lib3dsCameraNode*)node; lib3ds_track_eval_vector(&n->pos_track, n->pos, t); lib3ds_track_eval_float(&n->fov_track, &n->fov, t); lib3ds_track_eval_float(&n->roll_track, &n->roll, t); if (node->parent) { lib3ds_matrix_copy(node->matrix, node->parent->matrix); } else { lib3ds_matrix_identity(node->matrix); } lib3ds_matrix_translate(node->matrix, n->pos[0], n->pos[1], n->pos[2]); break; } case LIB3DS_NODE_CAMERA_TARGET: { Lib3dsTargetNode *n = (Lib3dsTargetNode*)node; lib3ds_track_eval_vector(&n->pos_track, n->pos, t); if (node->parent) { lib3ds_matrix_copy(node->matrix, node->parent->matrix); } else { lib3ds_matrix_identity(node->matrix); } lib3ds_matrix_translate(node->matrix, n->pos[0], n->pos[1], n->pos[2]); break; } case LIB3DS_NODE_OMNILIGHT: { Lib3dsOmnilightNode *n = (Lib3dsOmnilightNode*)node; lib3ds_track_eval_vector(&n->pos_track, n->pos, t); lib3ds_track_eval_vector(&n->color_track, n->color, t); if (node->parent) { lib3ds_matrix_copy(node->matrix, node->parent->matrix); } else { lib3ds_matrix_identity(node->matrix); } lib3ds_matrix_translate(node->matrix, n->pos[0], n->pos[1], n->pos[2]); break; } case LIB3DS_NODE_SPOTLIGHT: { Lib3dsSpotlightNode *n = (Lib3dsSpotlightNode*)node; lib3ds_track_eval_vector(&n->pos_track, n->pos, t); lib3ds_track_eval_vector(&n->color_track, n->color, t); lib3ds_track_eval_float(&n->hotspot_track, &n->hotspot, t); lib3ds_track_eval_float(&n->falloff_track, &n->falloff, t); lib3ds_track_eval_float(&n->roll_track, &n->roll, t); if (node->parent) { lib3ds_matrix_copy(node->matrix, node->parent->matrix); } else { lib3ds_matrix_identity(node->matrix); } lib3ds_matrix_translate(node->matrix, n->pos[0], n->pos[1], n->pos[2]); break; } case LIB3DS_NODE_SPOTLIGHT_TARGET: { Lib3dsTargetNode *n = (Lib3dsTargetNode*)node; lib3ds_track_eval_vector(&n->pos_track, n->pos, t); if (node->parent) { lib3ds_matrix_copy(node->matrix, node->parent->matrix); } else { lib3ds_matrix_identity(node->matrix); } lib3ds_matrix_translate(node->matrix, n->pos[0], n->pos[1], n->pos[2]); break; } } { Lib3dsNode *p; for (p = node->childs; p != 0; p = p->next) { lib3ds_node_eval(p, t); } } }
/*! * See \ref Loader3ds::loadFromFileToOneMesh */ dcollide::Mesh* Loader3dsInternal::loadFromFileToOneMesh(const char* fileName, TextureInformation* textureInformation) { // AB: // we cannot load texture information here, because we are merging all // meshes into a single one. // -> adjusting the texels may still be possible, however if the model // uses > 1 texture, we can't change that. mData->mProxy2Transformation.clear(); mData->mProxy2TextureInformation.clear(); if (!fileName) { throw dcollide::NullPointerException("fileName"); } mFile = lib3ds_file_load(fileName); if (!mFile) { std::cout << dc_funcinfo << "unable to load " << fileName << std::endl; return 0; } // AB: some files don't store nodes and just want exactly one node per mesh. // atm we don't support that. if (!mFile->nodes) { std::cout << dc_funcinfo << "File " << fileName << " does not contain any nodes. mesh-only files not supported currently." << std::endl; lib3ds_file_free(mFile); mFile = 0; return 0; } // 3ds stores several frames, we want the first lib3ds_file_eval(mFile, 0); std::list<Lib3dsNode*> nodes; Lib3dsNode* node = mFile->nodes; while (node) { nodes.push_back(node); node = node->next; } bool texelLoadError = false; std::vector<dcollide::Vector3> texels; std::vector<dcollide::Vertex*> vertices; std::vector<dcollide::Triangle*> triangles; std::vector<int> indices; while (!nodes.empty()) { Lib3dsNode* node = nodes.front(); nodes.pop_front(); for (Lib3dsNode* n = node->childs; n; n = n->next) { nodes.push_back(n); } // node->type can be object, light, camera, ... // -> only object nodes are relevant to us if (node->type != LIB3DS_OBJECT_NODE) { continue; } if (strcmp(node->name, "$$$DUMMY") == 0) { // AB: nodes with this name are only transformation nodes, i.e. they // don't have a mesh, only a matrix. continue; } unsigned int pointOffset = vertices.size(); Lib3dsMesh* mesh = lib3ds_file_mesh_by_name(mFile, node->name); Lib3dsMatrix origMeshMatrix; lib3ds_matrix_copy(origMeshMatrix, mesh->matrix); lib3ds_matrix_inv(origMeshMatrix); // 3ds stores inverted mesh matrix dcollide::Matrix meshMatrix(&origMeshMatrix[0][0]); dcollide::Matrix nodeMatrix(&node->matrix[0][0]); Lib3dsObjectData* data = &node->data.object; nodeMatrix.translate(dcollide::Vector3(-data->pivot[0], -data->pivot[1], -data->pivot[2])); dcollide::Matrix matrix = nodeMatrix; matrix.multiply(&meshMatrix); for (unsigned int i = 0; i < mesh->points; i++) { Lib3dsPoint* p = &mesh->pointL[i]; dcollide::Vector3 pos; matrix.transform(&pos, dcollide::Vector3( p->pos[0], p->pos[1], p->pos[2] )); vertices.push_back(new dcollide::Vertex(pos)); } for (unsigned int i = 0; i < mesh->faces; i++) { Lib3dsFace* f = &mesh->faceL[i]; indices.push_back(f->points[0] + pointOffset); indices.push_back(f->points[1] + pointOffset); indices.push_back(f->points[2] + pointOffset); } if (textureInformation) { TextureInformation t = loadTextureInformation(node); const std::vector<dcollide::Vector3>& nodeTexels = t.getTexels(); if (mesh->texelL && nodeTexels.size() != mesh->texels) { dcollide::warning() << "texturing problem in " << fileName; dcollide::warning() << "invalid texel count loaded: have=" << nodeTexels.size() << " expected=" << mesh->texels; dcollide::warning() << "adding dummy texels..."; for (unsigned int i = 0; i < mesh->texels; i++) { texels.push_back(dcollide::Vector3(0.0, 0.0, 0.0)); } // texelLoadError = true; } else { for (unsigned int i = 0; i < nodeTexels.size(); i++) { texels.push_back(nodeTexels[i]); } } } } if (textureInformation) { if (!texelLoadError) { textureInformation->setTextured(true); textureInformation->setTextureFileName("deformable.tga"); textureInformation->setTexels(texels); } else { textureInformation->setTextured(false); } } lib3ds_file_free(mFile); mFile = 0; dcollide::Mesh* mesh = new dcollide::Mesh(vertices, indices); return mesh; }
/*! * \internal * * \return A new mesh object containing the mesh in \p node, or NULL if no such * mesh can be found. */ dcollide::Shape* Loader3dsInternal::createShape(Lib3dsNode* node, Lib3dsMatrix* translateRotateMatrix) { if (!node) { return 0; } if (node->type != LIB3DS_OBJECT_NODE) { return 0; } if (strcmp(node->name, "$$$DUMMY") == 0) { // AB: nodes with this name are only transformation nodes, i.e. they // don't have a mesh, only a matrix. return 0; } Lib3dsMesh* mesh = lib3ds_file_mesh_by_name(mFile, node->name); if (!mesh) { std::cout << "Cannot find mesh " << node->name << " in 3ds file" << std::endl; return 0; } if (mesh->faces < 1) { std::cerr << "No faces in mesh " << node->name << std::endl; return 0; } if (mesh->points < 3) { std::cerr << "Less than 3 points in mesh " << node->name << std::endl; return 0; } Lib3dsMatrix origMeshMatrix; lib3ds_matrix_copy(origMeshMatrix, mesh->matrix); lib3ds_matrix_inv(origMeshMatrix); // 3ds stores inverted mesh matrix dcollide::Matrix meshMatrix(&origMeshMatrix[0][0]); // AB: Ogre does not apply "scale" values to child nodes, lib3ds does. // so to display the model correctly we remove the scale completely // (we integrate it directly into the vertices). // to do this: // let M:=the lib3ds matrix the point is normally transformed by // (i.e. including the parent-node matrix) // let M':=the matrix d-collide will use (i.e. // translation+rotation only, no scale) // then for every vertex v the correct transformed position p is: // Mv=p // we search for a vertex v' so that: // M'v'=p // since we have M and v (and thus p) and M' we can do this like // this: // v'=(M'^-1)p // which equals: // v'=(M'^-1)Mv dcollide::Matrix nodeMatrix(&node->matrix[0][0]); // M Lib3dsMatrix invertedTranslateRotate3ds; lib3ds_matrix_copy(invertedTranslateRotate3ds, *translateRotateMatrix); lib3ds_matrix_inv(invertedTranslateRotate3ds); dcollide::Matrix invertedTranslateRotate(&invertedTranslateRotate3ds[0][0]); // M'^-1 dcollide::Matrix removeScaleMatrix(invertedTranslateRotate); removeScaleMatrix.multiply(&nodeMatrix); Lib3dsObjectData* data = &node->data.object; std::vector<dcollide::Vertex*> vertices(mesh->points); for (unsigned int i = 0; i < mesh->points; i++) { Lib3dsPoint* p = &mesh->pointL[i]; dcollide::Vector3 meshPos; meshMatrix.transform(&meshPos, dcollide::Vector3( p->pos[0] - data->pivot[0], p->pos[1] - data->pivot[1], p->pos[2] - data->pivot[2])); dcollide::Vector3 pos; removeScaleMatrix.transform(&pos, meshPos); vertices[i] = new dcollide::Vertex(pos); } std::vector<int> indices(mesh->faces * 3); for (unsigned int i = 0; i < mesh->faces; i++) { Lib3dsFace* f = &mesh->faceL[i]; indices[i * 3 + 0] = f->points[0]; indices[i * 3 + 1] = f->points[1]; indices[i * 3 + 2] = f->points[2]; } dcollide::Mesh* newMesh = new dcollide::Mesh(vertices, indices); return newMesh; }
// this code is rewritten from player.c example that came with lib3ds // what it does is render a node from our model void Model::renderNode(Lib3dsNode *node) { ASSERT(file); //this is for debugging { Lib3dsNode *tmp; for(tmp = node->childs;tmp != 0;tmp = tmp->next) renderNode(tmp); //render all child nodes of this note } if(node->type == LIB3DS_OBJECT_NODE) //check wheter the node is a 3ds node { if(! node->user.d) //Wheter we have a list or not, if not we're gonna create one { Lib3dsMesh *mesh = lib3ds_file_mesh_by_name(file, node->name); //get all the meshes of the current node ASSERT(mesh); //for debugging in case we don't have a mesh if(! mesh) return; node->user.d = glGenLists(1); //alocate memory for one list ///////////////////////////////////////////////////////////// if(glGetError() != GL_NO_ERROR) { cout << "ERROR!\n"; exit(0); } ///////////////////////////////////////////////////////////// glNewList(node->user.d, GL_COMPILE); //here we create our list { unsigned p; Lib3dsVector *normals; normals = static_cast<float(*)[3]> (std::malloc (3*sizeof(Lib3dsVector)*mesh->faces)); //alocate memory for our normals { Lib3dsMatrix m; lib3ds_matrix_copy(m, mesh->matrix); //copy the matrix of the mesh in our temporary matrix lib3ds_matrix_inv(m); glMultMatrixf(&m[0][0]); //adjust our current matrix to the matrix of the mesh } lib3ds_mesh_calculate_normals(mesh, normals); //calculate the normals of the mesh int j = 0; for(p = 0;p < mesh->faces;p++) { Lib3dsFace *f = &mesh->faceL[p]; Lib3dsMaterial *mat=0; if(f->material[0]) //if the face of the mesh has material properties mat = lib3ds_file_material_by_name(file, f->material); //read material properties from file if(mat) //if we have material { static GLfloat ambient[4] = { 0.0, 0.0, 0.0, 1.0 }; glMaterialfv(GL_FRONT, GL_AMBIENT, ambient); // Ambient color glMaterialfv(GL_FRONT, GL_DIFFUSE, mat->diffuse); //diffuse color glMaterialfv(GL_FRONT, GL_SPECULAR, mat->specular); //specular color float shine; shine = pow(2, 10.0 * mat->shininess); if(shine > 128.0) shine = 128.0; glMaterialf(GL_FRONT, GL_SHININESS, shine); } else // if we do not have material properties, we have to set them manually { GLfloat diff[4] = { 0.75, 0.75, 0.75, 1.0 }; // color: white/grey GLfloat amb[4] = { 0.25, 0.25, 0.25, 1.0 }; //color: black/dark gray GLfloat spec[4] = { 0.0, 0.0, 0.0, 1.0 }; //color: completly black glMaterialfv(GL_FRONT, GL_DIFFUSE, diff); glMaterialfv(GL_FRONT, GL_AMBIENT, amb); glMaterialfv(GL_FRONT, GL_AMBIENT, spec); } { if(mesh->texels) { glBindTexture(GL_TEXTURE_2D, textureIndices.at(j)); j++; } glBegin(GL_TRIANGLES); for(int i = 0;i < 3;i++) { glNormal3fv(normals[3*p+i]); //set normal vector of that point if(mesh->texels) glTexCoord2f(mesh->texelL[f->points[i]][0], mesh->texelL[f->points[i]][1]); glVertex3fv(mesh->pointL[f->points[i]].pos); //Draw the damn triangle } glEnd(); } } free(normals); //free up memory } glEndList(); // end of list } if(node->user.d) // if we have created a link list(with glNewList) { Lib3dsObjectData *tmpdat; glPushMatrix(); //save transformation values tmpdat = &node->data.object; // get the position data glMultMatrixf(&node->matrix[0][0]); //adjust matrix according to the node glTranslatef(-tmpdat->pivot[0], -tmpdat->pivot[1], -tmpdat->pivot[2]); //move to the right place; glCallList(node->user.d); //render node glPopMatrix(); //return transformation original values } } }
static void file_bounding_box_of_nodes_impl(Lib3dsNode *node, Lib3dsFile *file, int include_meshes, int include_cameras, int include_lights, float bmin[3], float bmax[3], float matrix[4][4]) { switch (node->type) { case LIB3DS_NODE_MESH_INSTANCE: if (include_meshes) { int index; Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node; 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) { Lib3dsMesh *mesh; float inv_matrix[4][4], M[4][4]; float v[3]; int i; mesh = file->meshes[index]; lib3ds_matrix_copy(inv_matrix, mesh->matrix); lib3ds_matrix_inv(inv_matrix); lib3ds_matrix_mult(M, matrix, node->matrix); lib3ds_matrix_translate(M, -n->pivot[0], -n->pivot[1], -n->pivot[2]); lib3ds_matrix_mult(M, M, inv_matrix); for (i = 0; i < mesh->nvertices; ++i) { lib3ds_vector_transform(v, M, mesh->vertices[i]); lib3ds_vector_min(bmin, v); lib3ds_vector_max(bmax, v); } } } break; case LIB3DS_NODE_CAMERA: case LIB3DS_NODE_CAMERA_TARGET: if (include_cameras) { float z[3], v[3]; float M[4][4]; lib3ds_matrix_mult(M, matrix, node->matrix); lib3ds_vector_zero(z); lib3ds_vector_transform(v, M, z); lib3ds_vector_min(bmin, v); lib3ds_vector_max(bmax, v); } break; case LIB3DS_NODE_OMNILIGHT: case LIB3DS_NODE_SPOTLIGHT: case LIB3DS_NODE_SPOTLIGHT_TARGET: if (include_lights) { float z[3], v[3]; float M[4][4]; lib3ds_matrix_mult(M, matrix, node->matrix); lib3ds_vector_zero(z); lib3ds_vector_transform(v, M, z); lib3ds_vector_min(bmin, v); lib3ds_vector_max(bmax, v); } break; } { Lib3dsNode *p = node->childs; while (p) { file_bounding_box_of_nodes_impl(p, file, include_meshes, include_cameras, include_lights, bmin, bmax, matrix); p = p->next; } } }
/*! * \ingroup mesh */ Lib3dsBool lib3ds_mesh_read(Lib3dsMesh *mesh, Lib3dsIo *io) { Lib3dsChunk c; Lib3dsWord chunk; if (!lib3ds_chunk_read_start(&c, LIB3DS_N_TRI_OBJECT, io)) { return(LIB3DS_FALSE); } while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) { switch (chunk) { case LIB3DS_MESH_MATRIX: { int i,j; lib3ds_matrix_identity(mesh->matrix); for (i=0; i<4; i++) { for (j=0; j<3; j++) { mesh->matrix[i][j]=lib3ds_io_read_float(io); } } } break; case LIB3DS_MESH_COLOR: { mesh->color=lib3ds_io_read_byte(io); } break; case LIB3DS_POINT_ARRAY: { unsigned i,j; unsigned points; lib3ds_mesh_free_point_list(mesh); points=lib3ds_io_read_word(io); if (points) { if (!lib3ds_mesh_new_point_list(mesh, points)) { LIB3DS_ERROR_LOG; return(LIB3DS_FALSE); } for (i=0; i<mesh->points; ++i) { for (j=0; j<3; ++j) { mesh->pointL[i].pos[j]=lib3ds_io_read_float(io); } } ASSERT((!mesh->flags) || (mesh->points==mesh->flags)); ASSERT((!mesh->texels) || (mesh->points==mesh->texels)); } } break; case LIB3DS_POINT_FLAG_ARRAY: { unsigned i; unsigned flags; lib3ds_mesh_free_flag_list(mesh); flags=lib3ds_io_read_word(io); if (flags) { if (!lib3ds_mesh_new_flag_list(mesh, flags)) { LIB3DS_ERROR_LOG; return(LIB3DS_FALSE); } for (i=0; i<mesh->flags; ++i) { mesh->flagL[i]=lib3ds_io_read_word(io); } ASSERT((!mesh->points) || (mesh->flags==mesh->points)); ASSERT((!mesh->texels) || (mesh->flags==mesh->texels)); } } break; case LIB3DS_FACE_ARRAY: { lib3ds_chunk_read_reset(&c, io); if (!face_array_read(mesh, io)) { return(LIB3DS_FALSE); } } break; case LIB3DS_MESH_TEXTURE_INFO: { int i,j; for (i=0; i<2; ++i) { mesh->map_data.tile[i]=lib3ds_io_read_float(io); } for (i=0; i<3; ++i) { mesh->map_data.pos[i]=lib3ds_io_read_float(io); } mesh->map_data.scale=lib3ds_io_read_float(io); lib3ds_matrix_identity(mesh->map_data.matrix); for (i=0; i<4; i++) { for (j=0; j<3; j++) { mesh->map_data.matrix[i][j]=lib3ds_io_read_float(io); } } for (i=0; i<2; ++i) { mesh->map_data.planar_size[i]=lib3ds_io_read_float(io); } mesh->map_data.cylinder_height=lib3ds_io_read_float(io); } break; case LIB3DS_TEX_VERTS: { unsigned i; unsigned texels; lib3ds_mesh_free_texel_list(mesh); texels=lib3ds_io_read_word(io); if (texels) { if (!lib3ds_mesh_new_texel_list(mesh, texels)) { LIB3DS_ERROR_LOG; return(LIB3DS_FALSE); } for (i=0; i<mesh->texels; ++i) { mesh->texelL[i][0]=lib3ds_io_read_float(io); mesh->texelL[i][1]=lib3ds_io_read_float(io); } ASSERT((!mesh->points) || (mesh->texels==mesh->points)); ASSERT((!mesh->flags) || (mesh->texels==mesh->flags)); } } break; default: lib3ds_chunk_unknown(chunk); } } { unsigned j; for (j=0; j<mesh->faces; ++j) { ASSERT(mesh->faceL[j].points[0]<mesh->points); ASSERT(mesh->faceL[j].points[1]<mesh->points); ASSERT(mesh->faceL[j].points[2]<mesh->points); lib3ds_vector_normal( mesh->faceL[j].normal, mesh->pointL[mesh->faceL[j].points[0]].pos, mesh->pointL[mesh->faceL[j].points[1]].pos, mesh->pointL[mesh->faceL[j].points[2]].pos ); } } if (lib3ds_matrix_det(mesh->matrix) < 0.0) { /* Flip X coordinate of vertices if mesh matrix has negative determinant */ Lib3dsMatrix inv_matrix, M; Lib3dsVector tmp; unsigned i; lib3ds_matrix_copy(inv_matrix, mesh->matrix); lib3ds_matrix_inv(inv_matrix); lib3ds_matrix_copy(M, mesh->matrix); lib3ds_matrix_scale_xyz(M, -1.0f, 1.0f, 1.0f); lib3ds_matrix_mult(M, inv_matrix); for (i=0; i<mesh->points; ++i) { lib3ds_vector_transform(tmp, M, mesh->pointL[i].pos); lib3ds_vector_copy(mesh->pointL[i].pos, tmp); } } lib3ds_chunk_read_end(&c, io); return(LIB3DS_TRUE); }
void lib3ds_mesh_read(Lib3dsFile *file, Lib3dsMesh *mesh, Lib3dsIo *io) { Lib3dsChunk c; uint16_t chunk; lib3ds_chunk_read_start(&c, CHK_N_TRI_OBJECT, io); while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) { switch (chunk) { case CHK_MESH_MATRIX: { int i, j; lib3ds_matrix_identity(mesh->matrix); for (i = 0; i < 4; i++) { for (j = 0; j < 3; j++) { mesh->matrix[i][j] = lib3ds_io_read_float(io); } } break; } case CHK_MESH_COLOR: { mesh->color = lib3ds_io_read_byte(io); break; } case CHK_POINT_ARRAY: { int i; uint16_t nvertices = lib3ds_io_read_word(io); lib3ds_mesh_resize_vertices(mesh, nvertices, mesh->texcos != NULL, mesh->vflags != NULL); for (i = 0; i < mesh->nvertices; ++i) { lib3ds_io_read_vector(io, mesh->vertices[i]); } break; } case CHK_POINT_FLAG_ARRAY: { int i; uint16_t nflags = lib3ds_io_read_word(io); uint16_t nvertices = (mesh->nvertices >= nflags)? mesh->nvertices : nflags; lib3ds_mesh_resize_vertices(mesh, nvertices, mesh->texcos != NULL, 1); for (i = 0; i < nflags; ++i) { mesh->vflags[i] = lib3ds_io_read_word(io); } break; } case CHK_FACE_ARRAY: { lib3ds_chunk_read_reset(&c, io); face_array_read(file, mesh, io); break; } case CHK_MESH_TEXTURE_INFO: { int i, j; //FIXME: mesh->map_type = lib3ds_io_read_word(io); for (i = 0; i < 2; ++i) { mesh->map_tile[i] = lib3ds_io_read_float(io); } for (i = 0; i < 3; ++i) { mesh->map_pos[i] = lib3ds_io_read_float(io); } mesh->map_scale = lib3ds_io_read_float(io); lib3ds_matrix_identity(mesh->map_matrix); for (i = 0; i < 4; i++) { for (j = 0; j < 3; j++) { mesh->map_matrix[i][j] = lib3ds_io_read_float(io); } } for (i = 0; i < 2; ++i) { mesh->map_planar_size[i] = lib3ds_io_read_float(io); } mesh->map_cylinder_height = lib3ds_io_read_float(io); break; } case CHK_TEX_VERTS: { int i; uint16_t ntexcos = lib3ds_io_read_word(io); uint16_t nvertices = (mesh->nvertices >= ntexcos)? mesh->nvertices : ntexcos;; if (!mesh->texcos) { lib3ds_mesh_resize_vertices(mesh, nvertices, 1, mesh->vflags != NULL); } for (i = 0; i < ntexcos; ++i) { mesh->texcos[i][0] = lib3ds_io_read_float(io); mesh->texcos[i][1] = lib3ds_io_read_float(io); } break; } default: lib3ds_chunk_unknown(chunk, io); } } if (lib3ds_matrix_det(mesh->matrix) < 0.0) { /* Flip X coordinate of vertices if mesh matrix has negative determinant */ float inv_matrix[4][4], M[4][4]; float tmp[3]; int i; lib3ds_matrix_copy(inv_matrix, mesh->matrix); lib3ds_matrix_inv(inv_matrix); lib3ds_matrix_copy(M, mesh->matrix); lib3ds_matrix_scale(M, -1.0f, 1.0f, 1.0f); lib3ds_matrix_mult(M, M, inv_matrix); for (i = 0; i < mesh->nvertices; ++i) { lib3ds_vector_transform(tmp, M, mesh->vertices[i]); lib3ds_vector_copy(mesh->vertices[i], tmp); } } lib3ds_chunk_read_end(&c, io); }
/*! * */ 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) { if (strcmp(node->name,"$$$DUMMY")==0) { return; } if (!node->user.d) { Lib3dsMesh *mesh=lib3ds_file_mesh_by_name(file, node->name); ASSERT(mesh); if (!mesh) { return; } node->user.d=glGenLists(1); glNewList(node->user.d, GL_COMPILE); { unsigned p; Lib3dsVector *normalL=malloc(3*sizeof(Lib3dsVector)*mesh->faces); { 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; if (f->material[0]) { mat=lib3ds_file_material_by_name(file, f->material); } if (mat) { float s[1]; s[0]=1.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, 11.0-0.2*mat->shininess); } else { Lib3dsRgba a={0.2, 0.2, 0.2, 1.0}; Lib3dsRgba d={0.8, 0.8, 0.8, 1.0}; Lib3dsRgba s={0.0, 0.0, 0.0, 1.0}; glMaterialfv(GL_FRONT, GL_AMBIENT, a); glMaterialfv(GL_FRONT, GL_DIFFUSE, d); glMaterialfv(GL_FRONT, GL_SPECULAR, s); } { int i; glBegin(GL_TRIANGLES); glNormal3fv(f->normal); for (i=0; i<3; ++i) { glNormal3fv(normalL[3*p+i]); glVertex3fv(mesh->pointL[f->points[i]].pos); } glEnd(); } } free(normalL); } glEndList(); } if (node->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(node->user.d); /*glutSolidSphere(50.0, 20,20);*/ glPopMatrix(); } } }
/*! * 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(); } } }
static void create_node(Lib3dsFile *f, Lib3dsNode *node, FILE *o) { Lib3dsMesh *mesh; if ((node->type==LIB3DS_OBJECT_NODE) && (strcmp(node->name,"$$$DUMMY")!=0)) { mesh=lib3ds_file_mesh_by_name(f, node->name); ASSERT(mesh); if (mesh) { Lib3dsObjectData *d=&node->data.object; fprintf(o, "AttributeBegin\n"); fprintf(o, "Surface \"matte\" \"Kd\" [0.75]\n"); fprintf(o, "Color 1 1 1\n"); { Lib3dsMatrix N,M,X; lib3ds_matrix_copy(N, node->matrix); lib3ds_matrix_translate_xyz(N, -d->pivot[0], -d->pivot[1], -d->pivot[2]); lib3ds_matrix_copy(M, mesh->matrix); lib3ds_matrix_inv(M); lib3ds_matrix_mul(X,N,M); rib_concat_transform(o, X); } { unsigned p; Lib3dsVector *normalL=malloc(3*sizeof(Lib3dsVector)*mesh->faces); lib3ds_mesh_calculate_normals(mesh, normalL); for (p=0; p<mesh->faces; ++p) { Lib3dsFace *face=&mesh->faceL[p]; Lib3dsMaterial *mat=lib3ds_file_material_by_name(f, face->material); if (mat) { fprintf(o, "Color [%f %f %f]\n", mat->diffuse[0], mat->diffuse[1], mat->diffuse[2] ); fprintf(o, "Surface " "\"lib3dsmaterial\" " "\"color specularcolor\" [%f %f %f] " "\"float shininess \" [%f] " "\"float shin_stength \" [%f] " "\n", mat->specular[0], mat->specular[1], mat->specular[2], mat->shininess, mat->shin_strength ); } fprintf(o, "Polygon \"P\" [%f %f %f %f %f %f %f %f %f] ", mesh->pointL[face->points[0]].pos[0], mesh->pointL[face->points[0]].pos[1], mesh->pointL[face->points[0]].pos[2], mesh->pointL[face->points[1]].pos[0], mesh->pointL[face->points[1]].pos[1], mesh->pointL[face->points[1]].pos[2], mesh->pointL[face->points[2]].pos[0], mesh->pointL[face->points[2]].pos[1], mesh->pointL[face->points[2]].pos[2] ); fprintf(o, "\"N\" [%f %f %f %f %f %f %f %f %f] ", normalL[3*p+0][0], normalL[3*p+0][1], normalL[3*p+0][2], normalL[3*p+1][0], normalL[3*p+1][1], normalL[3*p+1][2], normalL[3*p+2][0], normalL[3*p+2][1], normalL[3*p+2][2] ); } free(normalL); } fprintf(o, "AttributeEnd\n"); } } { Lib3dsNode *n; for (n=node->childs; n; n=n->next) { create_node(f,n,o); } } }
void write_mesh(FILE *o, Lib3dsFile *f, Lib3dsMeshInstanceNode *node) { float (*orig_vertices)[3]; int export_texcos; int export_normals; int i, j; Lib3dsMesh *mesh; mesh = lib3ds_file_mesh_for_node(f, (Lib3dsNode*)node); if (!mesh || !mesh->vertices) return; fprintf(o, "# object %s\n", node->base.name); fprintf(o, "g %s\n", node->instance_name[0]? node->instance_name : node->base.name); orig_vertices = (float(*)[3])malloc(sizeof(float) * 3 * mesh->nvertices); memcpy(orig_vertices, mesh->vertices, sizeof(float) * 3 * mesh->nvertices); { float inv_matrix[4][4], M[4][4]; float tmp[3]; int i; lib3ds_matrix_copy(M, node->base.matrix); lib3ds_matrix_translate(M, -node->pivot[0], -node->pivot[1], -node->pivot[2]); lib3ds_matrix_copy(inv_matrix, mesh->matrix); lib3ds_matrix_inv(inv_matrix); lib3ds_matrix_mult(M, M, inv_matrix); for (i = 0; i < mesh->nvertices; ++i) { lib3ds_vector_transform(tmp, M, mesh->vertices[i]); lib3ds_vector_copy(mesh->vertices[i], tmp); } } export_texcos = (mesh->texcos != 0); export_normals = (mesh->faces != 0); for (i = 0; i < mesh->nvertices; ++i) { fprintf(o, "v %f %f %f\n", mesh->vertices[i][0], mesh->vertices[i][1], mesh->vertices[i][2]); } fprintf(o, "# %d vertices\n", mesh->nvertices); if (export_texcos) { for (i = 0; i < mesh->nvertices; ++i) { fprintf(o, "vt %f %f\n", mesh->texcos[i][0], mesh->texcos[i][1]); } fprintf(o, "# %d texture vertices\n", mesh->nvertices); } if (export_normals) { float (*normals)[3] = (float(*)[3])malloc(sizeof(float) * 9 * mesh->nfaces); lib3ds_mesh_calculate_vertex_normals(mesh, normals); for (i = 0; i < 3 * mesh->nfaces; ++i) { fprintf(o, "vn %f %f %f\n", normals[i][0], normals[i][1], normals[i][2]); } free(normals); fprintf(o, "# %d normals\n", 3 * mesh->nfaces); } { int mat_index = -1; for (i = 0; i < mesh->nfaces; ++i) { if (mat_index != mesh->faces[i].material) { mat_index = mesh->faces[i].material; if (mat_index != -1) { fprintf(o, "usemtl %s\n", f->materials[mat_index]->name); } } fprintf(o, "f "); for (j = 0; j < 3; ++j) { fprintf(o, "%d", mesh->faces[i].index[j] + max_vertices + 1); if (export_texcos) { fprintf(o, "/%d", mesh->faces[i].index[j] + max_texcos + 1); } else if (export_normals) { fprintf(o, "/"); } if (export_normals) { fprintf(o, "/%d", 3 * i + j + max_normals + 1); } if (j < 3) { fprintf(o, " "); } } fprintf(o, "\n"); } } max_vertices += mesh->nvertices; if (export_texcos) max_texcos += mesh->nvertices; if (export_normals) max_normals += 3 * mesh->nfaces; memcpy(mesh->vertices, orig_vertices, sizeof(float) * 3 * mesh->nvertices); free(orig_vertices); }
static void create_node(Lib3dsFile *f, Lib3dsNode *node, FILE *o) { Lib3dsMesh *mesh; if ((node->type==LIB3DS_OBJECT_NODE) && (strcmp(node->name,"$$$DUMMY")!=0)) { mesh=lib3ds_file_mesh_by_name(f, node->name); ASSERT(mesh); if (mesh) { Lib3dsObjectData *d=&node->data.object; fprintf(o, "\n\n##\n## Object: %s\n##\n", node->name); fprintf(o, "AttributeBegin\n"); { Lib3dsMatrix N,M,X; lib3ds_matrix_copy(N, node->matrix); lib3ds_matrix_translate_xyz(N, -d->pivot[0], -d->pivot[1], -d->pivot[2]); lib3ds_matrix_copy(M, mesh->matrix); lib3ds_matrix_inv(M); lib3ds_matrix_mul(X,N,M); rib_concat_transform(o, X); } { unsigned p; int i, j; Lib3dsVector *normalL=malloc(3*sizeof(Lib3dsVector)*mesh->faces); lib3ds_mesh_calculate_normals(mesh, normalL); Lib3dsMaterial *lastmat = NULL; int nalloc = 256, nfaces = 0; float *P = (float *)malloc(nalloc*9*sizeof(float)); float *N = (float *)malloc(nalloc*9*sizeof(float)); float *uv = (float *)malloc(nalloc*6*sizeof(float)); for (p=0; p<mesh->faces; ++p) { Lib3dsFace *face=&mesh->faceL[p]; Lib3dsMaterial *mat=lib3ds_file_material_by_name(f, face->material); if (mat && mat != lastmat) { char *Kdmap = NULL, *Omap = NULL; flushpp(o, P, N, uv, nfaces); nfaces = 0; lastmat = mat; if (mat->texture1_map.name[0]) { Kdmap = GetTexture(o, mat->texture1_map.name, mat->texture1_mask.name, 0); char *scale = malloc(strlen(Kdmap)+20); strcpy(scale, Kdmap); strcat(scale, "-scale"); fprintf(o, "Texture \"%s\" \"color\" \"scale\" \"texture tex1\" \"%s\" " "\"color tex2\" [.8 .8 .8]\n", scale, Kdmap); Kdmap = scale; } if (mat->opacity_map.name[0]) Omap = GetTexture(o, mat->opacity_map.name, mat->opacity_mask.name, 0); char *bumpScale = NULL; if (mat->bump_map.name[0]) { char *Bmap = GetTexture(o, mat->bump_map.name, mat->bump_mask.name, 1); bumpScale = malloc(strlen(Bmap)+20); strcpy(bumpScale, Bmap); strcat(bumpScale, "-scale"); fprintf(o, "Texture \"%s\" \"float\" \"scale\" \"texture tex1\" \"%s\" " "\"float tex2\" [.05]\n", bumpScale, Bmap); } fprintf(o, "Material \"uber\" "); if (Kdmap) fprintf(o, "\"texture Kd\" \"%s\" ", Kdmap); else fprintf(o, "\"color Kd\" [%f %f %f] ", mat->diffuse[0], mat->diffuse[1], mat->diffuse[2]); if (Omap) fprintf(o, "\"texture opacity\" \"%s\" ", Omap); else fprintf(o, "\"color opacity\" [%f %f %f] ", 1.f - mat->transparency, 1.f - mat->transparency, 1.f - mat->transparency); fprintf(o, "\"color Ks\" [%f %f %f] " "\"float roughness\" [%f] ", mat->specular[0]*mat->shin_strength, mat->specular[1]*mat->shin_strength, mat->specular[2]*mat->shin_strength, mat->shininess ); //CO dumptex(o, "tex2", &mat->texture2_map); //CO dumptex(o, "tex2mask", &mat->texture2_mask); //CO dumptex(o, "specular", &mat->specular_map); //CO dumptex(o, "specularmask", &mat->specular_mask); //CO dumptex(o, "shininess", &mat->shininess_map); //CO dumptex(o, "shininessmask", &mat->shininess_mask); //CO dumptex(o, "reflection", &mat->reflection_map); //CO dumptex(o, "reflectionmask", &mat->reflection_mask); fprintf(o, "\n"); if (bumpScale) fprintf(o, "\"float bumpmap\" \"%s\"\n", bumpScale); } if (nfaces+1 == nalloc) { nalloc *= 2; P = (float *)realloc(P, nalloc*9*sizeof(float)); N = (float *)realloc(N, nalloc*9*sizeof(float)); uv = (float *)realloc(uv, nalloc*6*sizeof(float)); } for (i = 0; i < 3; ++i) { for (j = 0; j < 3; ++j) { P[9*nfaces+3*i+j] = mesh->pointL[face->points[i]].pos[j]; N[9*nfaces+3*i+j] = normalL[3*p+i][j]; if (j != 2 && mesh->texelL) uv[6*nfaces+2*i+j] = mesh->texelL[face->points[i]][j]; } if (!mesh->texelL) { uv[6*nfaces+0] = 0; uv[6*nfaces+1] = 0; uv[6*nfaces+2] = 0; uv[6*nfaces+3] = 1; uv[6*nfaces+4] = 1; uv[6*nfaces+5] = 0; } } ++nfaces; } flushpp(o, P, N, uv, nfaces); free(P); free(N); free(uv); free(normalL); } nTextures = 0; fprintf(o, "AttributeEnd\n"); } } { Lib3dsNode *n; for (n=node->childs; n; n=n->next) { create_node(f,n,o); } } }
/*! * Evaluate an animation node. * * Recursively sets node and its children to their appropriate values * for this point in the animation. * * \param node Node to be evaluated. * \param t time value, between 0. and file->frames * * \ingroup node */ void lib3ds_node_eval(Lib3dsNode *node, Lib3dsFloat t) { ASSERT(node); switch (node->type) { case LIB3DS_UNKNOWN_NODE: { ASSERT(LIB3DS_FALSE); } break; case LIB3DS_AMBIENT_NODE: { Lib3dsAmbientData *n=&node->data.ambient; if (node->parent) { lib3ds_matrix_copy(node->matrix, node->parent->matrix); } else { lib3ds_matrix_identity(node->matrix); } lib3ds_lin3_track_eval(&n->col_track, n->col, t); } break; case LIB3DS_OBJECT_NODE: { Lib3dsMatrix M; Lib3dsObjectData *n=&node->data.object; lib3ds_lin3_track_eval(&n->pos_track, n->pos, t); lib3ds_quat_track_eval(&n->rot_track, n->rot, t); if (n->scl_track.keyL) { lib3ds_lin3_track_eval(&n->scl_track, n->scl, t); } else { n->scl[0] = n->scl[1] = n->scl[2] = 1.0f; } lib3ds_bool_track_eval(&n->hide_track, &n->hide, t); lib3ds_morph_track_eval(&n->morph_track, n->morph, t); lib3ds_matrix_identity(M); lib3ds_matrix_translate(M, n->pos); lib3ds_matrix_rotate(M, n->rot); lib3ds_matrix_scale(M, n->scl); if (node->parent) { lib3ds_matrix_copy(node->matrix, node->parent->matrix); lib3ds_matrix_mult(node->matrix, M); } else { lib3ds_matrix_copy(node->matrix, M); } } break; case LIB3DS_CAMERA_NODE: { Lib3dsCameraData *n=&node->data.camera; lib3ds_lin3_track_eval(&n->pos_track, n->pos, t); lib3ds_lin1_track_eval(&n->fov_track, &n->fov, t); lib3ds_lin1_track_eval(&n->roll_track, &n->roll, t); if (node->parent) { lib3ds_matrix_copy(node->matrix, node->parent->matrix); } else { lib3ds_matrix_identity(node->matrix); } lib3ds_matrix_translate(node->matrix, n->pos); } break; case LIB3DS_TARGET_NODE: { Lib3dsTargetData *n=&node->data.target; lib3ds_lin3_track_eval(&n->pos_track, n->pos, t); if (node->parent) { lib3ds_matrix_copy(node->matrix, node->parent->matrix); } else { lib3ds_matrix_identity(node->matrix); } lib3ds_matrix_translate(node->matrix, n->pos); } break; case LIB3DS_LIGHT_NODE: { Lib3dsLightData *n=&node->data.light; lib3ds_lin3_track_eval(&n->pos_track, n->pos, t); lib3ds_lin3_track_eval(&n->col_track, n->col, t); lib3ds_lin1_track_eval(&n->hotspot_track, &n->hotspot, t); lib3ds_lin1_track_eval(&n->falloff_track, &n->falloff, t); lib3ds_lin1_track_eval(&n->roll_track, &n->roll, t); if (node->parent) { lib3ds_matrix_copy(node->matrix, node->parent->matrix); } else { lib3ds_matrix_identity(node->matrix); } lib3ds_matrix_translate(node->matrix, n->pos); } break; case LIB3DS_SPOT_NODE: { Lib3dsSpotData *n=&node->data.spot; lib3ds_lin3_track_eval(&n->pos_track, n->pos, t); if (node->parent) { lib3ds_matrix_copy(node->matrix, node->parent->matrix); } else { lib3ds_matrix_identity(node->matrix); } lib3ds_matrix_translate(node->matrix, n->pos); } break; } { Lib3dsNode *p; for (p=node->childs; p!=0; p=p->next) { lib3ds_node_eval(p, t); } } }
void m3ds::render_node(Lib3dsNode* node) { assert(m_file); { Lib3dsNode* p; for (p = node->childs; p != 0; p = p->next) render_node(p); } if (node->type == LIB3DS_OBJECT_NODE) { if (!strcmp(node->name, "$$$DUMMY")) return; if (!node->user.d) { Lib3dsMesh* mesh = lib3ds_file_mesh_by_name(m_file, node->name); assert(mesh); if (!mesh) return; node->user.d = glGenLists(1); glNewList(node->user.d, GL_COMPILE); { unsigned int p; Lib3dsVector* normalL = new Lib3dsVector[3 * mesh->faces]; { 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; if (f->material[0]) { mat = lib3ds_file_material_by_name(m_file, f->material); if (mat->texture1_map.name[0]) { std::string str = mat->texture1_map.name; std::map<std::string, texture*>::iterator ite; ite = texlib::instance()->find(str); if (ite == texlib::instance()->end()) { texture* pt = NULL; char str2[512]; memset(str2, 0, 512); sprintf(str2, "%s%s", s_prefix, str.c_str()); char* ext = &str2[strlen(str2) - 3]; ext[0] = tolower(ext[0]); ext[1] = tolower(ext[1]); ext[2] = tolower(ext[2]); if (!strcmp(ext, "tga")) { tga_tex* tex = new tga_tex(str2); if (tex->get_tex_id() != -1) { pt = tex; texlib::instance()->insert(texlib::value_type(str, pt)); } } else if (!strcmp(ext, "bmp")) { bmp_tex* tex = new bmp_tex(str2); if (tex->get_tex_id() != -1) { pt = tex; texlib::instance()->insert(texlib::value_type(str, pt)); } } else if (!strcmp(ext, "pcx")) { pcx_tex* tex = new pcx_tex(str2); if (tex->get_tex_id() != -1) { pt = tex; texlib::instance()->insert(texlib::value_type(str, pt)); } } else { ext[0] = 't'; ext[1] = 'g'; ext[2] = 'a'; tga_tex* tex = new tga_tex(str2); // str = str2; if (tex->get_tex_id() != -1) { pt = tex; } else { pt = texlib::instance()->operator[]("default.tga"); } texlib::instance()->insert(texlib::value_type(str, pt)); } glBindTexture(GL_TEXTURE_2D, (pt) ? pt->get_tex_id() : ((*texlib::instance())["default.tga"])->get_tex_id()); } else { glBindTexture(GL_TEXTURE_2D, (ite->second)->get_tex_id()); } } } if (mat) { static GLfloat a[4] = {0.0f, 0.0f, 0.0f, 1.0f}; float s; glMaterialfv(GL_FRONT, GL_AMBIENT, a); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat->diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat->specular); s = pow(2.0f, 10.0f * mat->shininess); if (s > 128.0) s = 128.0; glMaterialf(GL_FRONT, GL_SHININESS, s); } else { Lib3dsRgba a = {0.2f, 0.2f, 0.2f, 1.0f}; Lib3dsRgba d = {0.8f, 0.8f, 0.8f, 1.0f}; Lib3dsRgba s = {0.0f, 0.0f, 0.0f, 1.0f}; glMaterialfv(GL_FRONT, GL_AMBIENT, a); glMaterialfv(GL_FRONT, GL_DIFFUSE, d); glMaterialfv(GL_FRONT, GL_SPECULAR, s); } glBegin(GL_TRIANGLES); glNormal3fv(f->normal); for (int i = 0; i < 3; ++i) { assert(mesh); if (mesh->texelL) glTexCoord2fv(mesh->texelL[f->points[i]]); glNormal3fv(normalL[3 * p + i]); glVertex3fv(mesh->pointL[f->points[i]].pos); } glEnd(); } delete [] normalL; } glEndList(); } if (node->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(node->user.d); glPopMatrix(); } } }
static void file_bounding_box_of_nodes_impl(Lib3dsNode *node, Lib3dsFile *file, Lib3dsBool include_meshes, Lib3dsBool include_cameras, Lib3dsBool include_lights, Lib3dsVector bmin, Lib3dsVector bmax) { switch (node->type) { case LIB3DS_OBJECT_NODE: if (include_meshes) { Lib3dsMesh *mesh; mesh = lib3ds_file_mesh_by_name(file, node->data.object.instance); if (!mesh) mesh = lib3ds_file_mesh_by_name(file, node->name); if (mesh) { Lib3dsMatrix inv_matrix, M; Lib3dsVector v; unsigned i; lib3ds_matrix_copy(inv_matrix, mesh->matrix); lib3ds_matrix_inv(inv_matrix); lib3ds_matrix_copy(M, node->matrix); lib3ds_matrix_translate_xyz(M, -node->data.object.pivot[0], -node->data.object.pivot[1], -node->data.object.pivot[2]); lib3ds_matrix_mult(M, inv_matrix); for (i=0; i<mesh->points; ++i) { lib3ds_vector_transform(v, M, mesh->pointL[i].pos); lib3ds_vector_min(bmin, v); lib3ds_vector_max(bmax, v); } } } break; /* case LIB3DS_CAMERA_NODE: case LIB3DS_TARGET_NODE: if (include_cameras) { Lib3dsVector z,v; lib3ds_vector_zero(z); lib3ds_vector_transform(v, node->matrix, z); lib3ds_vector_min(bmin, v); lib3ds_vector_max(bmax, v); } break; case LIB3DS_LIGHT_NODE: case LIB3DS_SPOT_NODE: if (include_lights) { Lib3dsVector z,v; lib3ds_vector_zero(z); lib3ds_vector_transform(v, node->matrix, z); lib3ds_vector_min(bmin, v); lib3ds_vector_max(bmax, v); } break; */ } { Lib3dsNode *p=node->childs; while (p) { file_bounding_box_of_nodes_impl(p, file, include_meshes, include_cameras, include_lights, bmin, bmax); p=p->next; } } }
void Object_3DS::renderNode(Lib3dsNode *node) { #ifdef HAS_LIB3DS for (Lib3dsNode* p=node->childs; p!=0; p=p->next) renderNode(p); if (node->type == LIB3DS_OBJECT_NODE) { if (strcmp(node->name,"$$$DUMMY")==0) return; if (!node->user.d) { Lib3dsMesh *mesh=lib3ds_file_mesh_by_name(file, node->name); if (!mesh) return; MSG_INFO("Rendering node %s",node->name); MSG_INFO("Face number: %d",mesh->faces); // return ; node->user.d = glGenLists(1); glNewList(node->user.d, GL_COMPILE); Lib3dsVector *normalL = new Lib3dsVector[3*mesh->faces]; Lib3dsMatrix M; lib3ds_matrix_copy(M, mesh->matrix); lib3ds_matrix_inv(M); glMultMatrixf(&M[0][0]); lib3ds_mesh_calculate_normals(mesh, normalL); for (unsigned int p=0; p<mesh->faces; ++p) { Lib3dsFace *f=&mesh->faceL[p]; Lib3dsMaterial *mat=0; if (f->material[0]) mat=lib3ds_file_material_by_name(file, f->material); if (mat) { static GLfloat a[4]={0,0,0,1}; float s; glMaterialfv(GL_FRONT, GL_AMBIENT, a); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat->diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat->specular); s = pow(2, 10.0*mat->shininess); if (s>128.0) s=128.0; glMaterialf(GL_FRONT, GL_SHININESS, s); } else { Lib3dsRgba a={0.2, 0.2, 0.2, 1.0}; Lib3dsRgba d={0.8, 0.8, 0.8, 1.0}; Lib3dsRgba s={0.0, 0.0, 0.0, 1.0}; glMaterialfv(GL_FRONT, GL_AMBIENT, a); glMaterialfv(GL_FRONT, GL_DIFFUSE, d); glMaterialfv(GL_FRONT, GL_SPECULAR, s); } glBegin(GL_TRIANGLES); glNormal3fv(f->normal); for (int i=0; i<3; ++i) { glNormal3fv(normalL[3*p+i]); glVertex3fv(mesh->pointL[f->points[i]].pos); } glEnd(); } delete[] normalL; glEndList(); } if (node->user.d) { glPushMatrix(); Lib3dsObjectData* d = &node->data.object; glMultMatrixf(&node->matrix[0][0]); glTranslatef(-d->pivot[0], -d->pivot[1], -d->pivot[2]); glCallList(node->user.d); glPopMatrix(); } } #endif }
/*! * 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(); } } }
std::vector<CL_Lib3dsMesh> CL_Lib3dsFile::export_meshes(Lib3dsNode *node) { if (node == 0) { lib3ds_file_eval(file, 0.0f); node = file->nodes; } std::vector<CL_Lib3dsMesh> meshes; for (; node; node = node->next) { if (node->type == LIB3DS_NODE_MESH_INSTANCE) { Lib3dsMeshInstanceNode *instance_node = (Lib3dsMeshInstanceNode *) node; Lib3dsMesh *mesh = lib3ds_file_mesh_for_node(file, (Lib3dsNode*)node); if (mesh && mesh->vertices) { float inv_matrix[4][4], M[4][4]; lib3ds_matrix_copy(M, instance_node->base.matrix); lib3ds_matrix_translate(M, -instance_node->pivot[0], -instance_node->pivot[1], -instance_node->pivot[2]); lib3ds_matrix_copy(inv_matrix, mesh->matrix); lib3ds_matrix_inv(inv_matrix); lib3ds_matrix_mult(M, M, inv_matrix); std::vector<CL_Vec3f> positions; for (int i = 0; i < mesh->nvertices; ++i) { float position[3]; lib3ds_vector_transform(position, M, mesh->vertices[i]); positions.push_back(CL_Vec3f(position[0], position[1], position[2])); } std::vector<CL_Vec2f> texcoords; if (mesh->texcos) { for (int i = 0; i < mesh->nvertices; ++i) { float tx = mesh->texcos[i][0]; float ty = mesh->texcos[i][1]; texcoords.push_back(CL_Vec2f(tx, ty)); } } std::vector<CL_Vec3f> normals; if (mesh->faces && mesh->nfaces > 0) { float (*normals_array)[3] = (float(*)[3])malloc(sizeof(float) * 9 * mesh->nfaces); lib3ds_mesh_calculate_vertex_normals(mesh, normals_array); for (int i = 0; i < 3 * mesh->nfaces; ++i) { normals.push_back(CL_Vec3f(normals_array[i][0], normals_array[i][1], normals_array[i][2])); } free(normals_array); } CL_Lib3dsMesh mesh_object; for (int i = 0; i < mesh->nfaces; ++i) { int material_index = mesh->faces[i].material; mesh_object.face_materials.push_back(material_index); for (int j = 0; j < 3; ++j) { int vertex_index = mesh->faces[i].index[j]; mesh_object.positions.push_back(positions[vertex_index]); if (!texcoords.empty()) mesh_object.texcooords.push_back(texcoords[vertex_index]); if (!normals.empty()) mesh_object.normals.push_back(normals[i*3+j]); } } meshes.push_back(mesh_object); } if (node->childs) { std::vector<CL_Lib3dsMesh> child_meshes = export_meshes(node->childs); meshes.insert(meshes.end(), child_meshes.begin(), child_meshes.end()); } } } return meshes; }