home *** CD-ROM | disk | FTP | other *** search
- /*!
- \file l3dsloader.cpp
- \author Karsten Schwenk
- \version 1.0
-
- See header for describtion (l3dsloader.h).
-
- Important is the #load3DS() function - all the other functions are just dirty-coded helpers.
- */
-
- #include "L3dsLoader.h"
-
-
- #include <stdlib.h>
- #include <string.h>
- //#include <config.h>
- #ifdef WITH_DMALLOC
- #include <dmalloc.h>
- #endif
- #include <math.h>
-
- #include "Model.h"
- #include "matrixmath.h"
- #include "vectormath.h"
- //#include "light.h"
- //#include "File.h"
- #include "log.h"
- #include "TextureHandler.h"
- #include "ShaderHandler.h"
-
-
-
- static mat4x4_t stdMatrix={ 1,0,0,0,
- 0,1,0,0,
- 0,0,1,0,
- 0,0,0,1 };
-
- static mat4x4_t flipMatrix={1,0,0,0,
- 0,0,-1,0,
- 0,1,0,0,
- 0,0,0,1 };
-
- static mat4x4_t invFlipMatrix={ 1,0,0,0,
- 0,0,1,0,
- 0,-1,0,0,
- 0,0,0,1 };
-
-
- char* L3dsLoader::path=NULL;
-
- /*
- static void rib_concat_transform(FILE *o, Lib3dsMatrix m){
- int i,j;
-
- fprintf(o, "ConcatTransform [");
- for (i=0; i<4; ++i) {
- for (j=0; j<4; ++j) {
- fprintf(o, "%f ", m[i][j]);
- }
- }
- fprintf(o, "]\n");
- }
-
-
- static void rib_camera(FILE *o, Lib3dsFile *f, Lib3dsMatrix M){
- Lib3dsNode *c;
- Lib3dsNode *t;
- const char *name=camera;
-
- ASSERT(f);
- if (!name) {
- if (f->cameras) {
- name=f->cameras->name;
- }
- }
- if (!name) {
- fprintf(stderr, "***ERROR*** No camera found!\n");
- exit(1);
- }
- c=lib3ds_file_node_by_name(f, name, LIB3DS_CAMERA_NODE);
- t=lib3ds_file_node_by_name(f, name, LIB3DS_TARGET_NODE);
- if (!c || !t) {
- fprintf(stderr, "***ERROR*** Invalid camera/target!\n");
- exit(1);
- }
-
- lib3ds_matrix_camera(M, c->data.camera.pos, t->data.target.pos, c->data.camera.roll);
- rib_concat_transform(o, M);
- fprintf(o, "Projection \"perspective\" \"fov\" [%f]\n", c->data.camera.fov);
- }
-
- */
- void L3dsLoader::setupLights(Lib3dsFile *f){
- /*
- Lib3dsLight *light;
- Lib3dsNode *l;
- Lib3dsNode *s;
- int lightId=LIGHT1;
-
- for(int i=lightId;i<NUM_LIGHTS;i++){
- lights[i]->switchOff();
- }
-
- for (light=f->lights; light; light=light->next) {
- if(lightId>=NUM_LIGHTS){
- warn("in l3dsloader::setupLights()): Too many lights in scene. Aborting.\n\n");
- break;
- }
-
- l=lib3ds_file_node_by_name(f, light->name, LIB3DS_LIGHT_NODE);
- s=lib3ds_file_node_by_name(f, light->name, LIB3DS_SPOT_NODE);
- if(!l){
- warn("(in l3dsloader::setupLights()): Invalid light.\n\n");
- }else{
- vec4_t pos;
- vectorInit4d(l->data.light.pos[0], l->data.light.pos[2], -l->data.light.pos[1], 1.0f, pos);
- lights[lightId]->setPosition(pos);
- vec4_t col;
- vectorInit4d(l->data.light.col[0], l->data.light.col[1], l->data.light.col[2], 1.0f, col);
- lights[lightId]->setColor(col);
- lights[lightId]->setAttenuation(1.0f, 0.1f, 0.0f);
- if(s){ // spotlight
- vec3_t dir;
- vec3_t spotPos;
- vectorInit3d(s->data.spot.pos[0], s->data.spot.pos[2], -s->data.spot.pos[1], spotPos);
- vectorSub3d(spotPos, pos, dir);
- vectorNormalize3d(dir, dir);
- lights[lightId]->setupSpotLight(30.0f, 5.0f, dir); // FIXME: richtige werte einsetzen!
- log("processed spotlight %i; col: %.1f %.1f %.1f; pos: %.1f %.1f %.1f; dir: %.1f %.1f %.1f.\n", lightId, col[0], col[1], col[2], pos[0], pos[1], pos[2], dir[0], dir[1], dir[2]);
- }else{
- vec3_t dir;
- vectorInit3d(0.0f, 0.0f, 0.0f, dir);
- lights[lightId]->setupSpotLight(180.0f, 1.0f, dir);
- log("processed pointlight %i; col: %.1f %.1f %.1f; pos: %.1f %.1f %.1f.\n", lightId, col[0], col[1], col[2], pos[0], pos[1], pos[2]);
- }
-
- lights[lightId]->switchOn();
- lightId++;
- }
- }
- */
- }
-
- Mesh* L3dsLoader::nodeToMesh(Lib3dsFile *f, Lib3dsNode *node/*, Model* m*/){
- //log("processing node %s\n", node->name);
-
- int i;
-
- Lib3dsMesh *mesh;
- Mesh* newMesh=new Mesh();
-
- if ((node->type==LIB3DS_OBJECT_NODE) && (strcmp(node->name,"$$$DUMMY")!=0)) {
- //log("converting node: %s\n", node->name);
- mesh=lib3ds_file_mesh_by_name(f, node->name);
- ASSERT(mesh);
- if (mesh) {
- Lib3dsMaterial* materialLookUp[128];
- Material* newMaterials[128];
- for(i=0;i<128;i++){
- materialLookUp[i]=NULL;
- newMaterials[i]=NULL;
- }
- Material* stdMat=new Material();
- // vectorInit4d(0.2f, 0.2f, 0.2f, 1.0f, stdMat->ambient);
- // vectorInit4d(0.8f, 0.8f, 0.8f, 1.0f, stdMat->diffuse);
- // vectorInit4d(1.0f, 1.0f, 1.0f, 1.0f, stdMat->specular);
- // stdMat->shininess=1.0;
- vectorInit4d(1.0f, 1.0f, 1.0f, 1.0f, stdMat->color);
- stdMat->setAttribs();
-
-
- Lib3dsObjectData *d=&node->data.object;
-
- 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_translate_xyz(N, -d->pivot[0], -d->pivot[2], d->pivot[1]);
- lib3ds_matrix_copy(M, mesh->matrix);
- lib3ds_matrix_inv(M);
- lib3ds_matrix_mul(X,N,M);
-
- mat4x4_t m;
- matrixMultMatrix(flipMatrix, (float*)X, 4, m);
- matrixMultMatrix(m, invFlipMatrix, 4, m);
- matrixCopy(m, newMesh->transformationMatrix, 4);
- // printf("processing matrix: \n");
- // matrixPrint(newMesh->transformationMatrix, 4);
-
- unsigned p;
- Lib3dsVector *normalL=(Lib3dsVector*)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);
-
- Face* newFace=new Face();
- if (mat) {
- // printf("processing material\n");
- for(i=0;i<128;i++){
- if(materialLookUp[i]==mat){
- newFace->material=newMaterials[i];
- // printf("found mat in lut: %i\n", i);
- break;
- }
- }
-
- if(i==128){ // material not yet in array -> add new one
- Material* newMat=new Material();
- //printf("ASDF trans: %f (%f %f)\n",mat->transparency, mat->ambient[3], mat->diffuse[3]);
- // vectorInit4d(mat->ambient[0], mat->ambient[1], mat->ambient[2], 1.0f-mat->transparency/*mat->ambient[3]*/, newMat->ambient);
- // vectorInit4d(mat->diffuse[0], mat->diffuse[1], mat->diffuse[2], 1.0f-mat->transparency/*mat->diffuse[3]*/, newMat->diffuse);
- // vectorInit4d(mat->specular[0], mat->specular[1], mat->specular[2], 1.0f-mat->transparency/*mat->specular[3]*/, newMat->specular);
- // vectorInit4d(0.0f, 0.0f, 0.0f, 1.0f, newMat->emissive);
- // newMat->shininess=(float)(mat->shininess*100.0);
-
- vectorInit4d(mat->diffuse[0], mat->diffuse[1], mat->diffuse[2], 1.0f-mat->transparency/*mat->diffuse[3]*/, newMat->color);
-
- if(*mat->texture1_map.name!='\0'){
- char buff[256];
- strcpy(buff, path);
- strcat(buff, mat->texture1_map.name);
- //strlwr(buff); // convert everything to lower case
- if(ShaderHandler::hasShaderForImageFile(buff))
- newMat->addShader(ShaderHandler::getShader(buff));
- else
- newMat->addTexture(TextureHandler::getTexture(buff));
- }
-
- if(*mat->self_illum_map.name!='\0'){ // this serves as lightmap
- char buff[256];
- strcpy(buff, path);
- strcat(buff, mat->self_illum_map.name);
- //strlwr(buff); // convert everything to lower case
- newMat->addLightmap(TextureHandler::getTexture(buff));
- }
- //log("mat.name: %s, %s, %s, %s\n", mat->name, mat->texture1_map.name, mat->texture2_map.name, mat->self_illum_map.name );
-
- newMat->setAttribs();
-
- for(i=0;i<128;i++){
- if(materialLookUp[i]==NULL){
- materialLookUp[i]=mat;
- newMaterials[i]=newMat;
- // newMesh->addMaterial(newMat);
- newFace->material=newMat;
- // printf("generated new material: %i\n", i);
- break;
- }
- }
- }
- }else{ // no mat
- newFace->material=stdMat;
- // newMesh->addMaterial(stdMat);
- // printf("added stdMat\n");
- }
-
- newFace->vertices=new GLfloat[9];
- newFace->colors=new GLfloat[9];
- newFace->normals=new GLfloat[9];
- newFace->texCoords1=new GLfloat[6];
- newFace->texCoords2=new GLfloat[6];
- newFace->numVertices=3;
- newFace->numNormals=3;
- newFace->numTexCoords=3;
- newFace->numIndices=3; // THINKABOUTME: Punkte wirklich vertauschen (F▄R NORMALE!)??
- /*
- vectorInit3d(mesh->pointL[face->points[0]].pos[0], mesh->pointL[face->points[0]].pos[1], mesh->pointL[face->points[0]].pos[2], &newFace->vertices[0]);
- vectorInit3d(mesh->pointL[face->points[1]].pos[0], mesh->pointL[face->points[1]].pos[1], mesh->pointL[face->points[1]].pos[2], &newFace->vertices[3]);
- vectorInit3d(mesh->pointL[face->points[2]].pos[0], mesh->pointL[face->points[2]].pos[1], mesh->pointL[face->points[2]].pos[2], &newFace->vertices[6]);
-
- vectorInit3d(normalL[3*p+0][0], normalL[3*p+0][1], normalL[3*p+0][2], &newFace->normals[0]);
- vectorInit3d(normalL[3*p+1][0], normalL[3*p+1][1], normalL[3*p+1][2], &newFace->normals[3]);
- vectorInit3d(normalL[3*p+2][0], normalL[3*p+2][1], normalL[3*p+2][2], &newFace->normals[6]);
-
- //newFace->calcNormal();
- vectorCopy3d(face->normal, newFace->normal); // FIXME: warum geht calcnormal nicht?!
- */
- vectorInit3d(mesh->pointL[face->points[0]].pos[0], mesh->pointL[face->points[0]].pos[2], -mesh->pointL[face->points[0]].pos[1], &newFace->vertices[0]);
- vectorInit3d(mesh->pointL[face->points[1]].pos[0], mesh->pointL[face->points[1]].pos[2], -mesh->pointL[face->points[1]].pos[1], &newFace->vertices[3]);
- vectorInit3d(mesh->pointL[face->points[2]].pos[0], mesh->pointL[face->points[2]].pos[2], -mesh->pointL[face->points[2]].pos[1], &newFace->vertices[6]);
-
- vectorInit3d(normalL[3*p+0][0], normalL[3*p+0][2], -normalL[3*p+0][1], &newFace->normals[0]);
- vectorInit3d(normalL[3*p+1][0], normalL[3*p+1][2], -normalL[3*p+1][1], &newFace->normals[3]);
- vectorInit3d(normalL[3*p+2][0], normalL[3*p+2][2], -normalL[3*p+2][1], &newFace->normals[6]);
-
- vectorCopy3d(newFace->material->color, &newFace->colors[0]);
- vectorCopy3d(newFace->material->color, &newFace->colors[3]);
- vectorCopy3d(newFace->material->color, &newFace->colors[6]);
-
- //newFace->calcNormal();
- vectorInit3d(face->normal[0], face->normal[2], -face->normal[1], newFace->normal);
-
- if(mesh->texels>0){
- vec2_t t0, t1, t2;
-
- vectorCopy2d(mesh->texelL[face->points[0]], t0);
- vectorCopy2d(mesh->texelL[face->points[1]], t1);
- vectorCopy2d(mesh->texelL[face->points[2]], t2);
-
- /* if(mat){
- t0[0]=mat->texture1_map.offset[0]+ mat->texture1_map.scale[0]*mesh->texelL[0][0];
- t0[1]=mat->texture1_map.offset[1]+ mat->texture1_map.scale[1]*mesh->texelL[0][1];
- }else{
- vectorCopy2d(mesh->texelL[face->points[0]], t0);
- }
- */// printf("have texels\n");
- vectorCopy2d(t0, &newFace->texCoords1[0]);
- vectorCopy2d(t1, &newFace->texCoords1[2]);
- vectorCopy2d(t2, &newFace->texCoords1[4]);
-
- vectorCopy2d(t0, &newFace->texCoords2[0]);
- vectorCopy2d(t1, &newFace->texCoords2[2]);
- vectorCopy2d(t2, &newFace->texCoords2[4]);
- }else{
- // printf("have NO texels\n");
- vectorInit2d(0.0, 0.0, &newFace->texCoords1[0]);
- vectorInit2d(0.0, 0.0, &newFace->texCoords1[2]);
- vectorInit2d(0.0, 0.0, &newFace->texCoords1[4]);
-
- vectorInit2d(0.0, 0.0, &newFace->texCoords2[0]);
- vectorInit2d(0.0, 0.0, &newFace->texCoords2[2]);
- vectorInit2d(0.0, 0.0, &newFace->texCoords2[4]);
- }
-
- // if(mat->two_sided){
- // newFace->flags |= FACE_FLAG_TWO_SIDED;
- // } // FIXME: oben machen!!
-
- newMesh->addFace(newFace);
- // printf("processing face xy\n");
-
- } //for
-
- free(normalL);
-
- newMesh->name=strcpy(new char[strlen(mesh->name)+1], mesh->name);
- } //mesh
-
- }else{ //dummy
- newMesh->name="DUMMY";
-
- // Lib3dsObjectData *d=&node->data.object;
-
- //Lib3dsMatrix N; // FIXME: was is'n das fⁿr ein matrix-scheiss???!!!! ich nehm' einfach die identitΣt
- //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);
- matrixCopy(stdMatrix, newMesh->transformationMatrix, 4);
- // printf("processing matrix: \n");
- // matrixPrint(newMesh->transformationMatrix, 4);
- }
-
- node->user.d=(unsigned long)newMesh; // damit wir's bei genMatrix wiederfinden
-
- Lib3dsNode *n;
- newMesh->numChilds=0;
- for (n=node->childs; n; n=n->next) {
- newMesh->addChild(nodeToMesh(f,n/*,m*/));
- }
-
- newMesh->setRenderMode();
-
- return newMesh;
- }
-
-
- void L3dsLoader::lib3dsFileToModel(Lib3dsFile *f, Model* m/*, int current*/){
-
-
- Lib3dsNode *n;
- Mesh* mesh;
- for (n=f->nodes; n; n=n->next) {
- //printf("node %s of file %s\n", n->name, f->name);
- mesh=nodeToMesh(f,n/*,m*/);
- matrixMultMatrix(stdMatrix, mesh->transformationMatrix, 4, mesh->transformationMatrix);
- m->addMesh(mesh);
- }
- m->numFrames=1;
-
- }
-
- void L3dsLoader::generateNodeMatrix(Lib3dsFile* f, Model* m, Lib3dsNode* node, int frame, mat4x4_t matParent){
- mat4x4_t mat;
-
- matrixCopy(stdMatrix, mat, 4);
-
-
- if ((node->type==LIB3DS_OBJECT_NODE) && (strcmp(node->name,"$$$DUMMY")!=0)){
- Lib3dsMesh* mesh=lib3ds_file_mesh_by_name(f, node->name);
- ASSERT(mesh);
- Lib3dsObjectData *d=&node->data.object;
-
- 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);
-
- matrixMultMatrix(matParent, &X[0][0], 4, mat);
- }else{
- // Lib3dsMesh* mesh=lib3ds_file_mesh_by_name(f, node->name);
- // ASSERT(mesh);
- Lib3dsObjectData *d=&node->data.object;
-
- Lib3dsMatrix N;
- 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);
-
- matrixMultMatrix(matParent, &N[0][0], 4, mat);
- }
- // printf("processing matrix: \n");
- // matrixPrint(newMesh->transformationMatrix, 4);
-
- //printf("MAT user.d: %d\n", mesh->user.d);
- int id=m->getMeshId((Mesh*)node->user.d);
- if(id==-1){
- //printf("NEW MESH??\n"); // THINKABOUTME:
- warn("(in 3dsLoader::generateNodeMatrix()): Unknown mesh id. Aborting tree.\n\n");
- return;
- }
- //printf("adding matrix: id: %i, frame: %i\n", id, frame);
- m->addMatrix(frame, id, mat);
-
- Lib3dsNode *n;
- for (n=node->childs; n; n=n->next) {
- // printf("node %s od file %s\n", n->name, f->name);
- generateNodeMatrix(f, m, n, frame, mat);
- }
-
- }
-
- /*!
- This function loads a 3ds file into a #Model object. You can also specify whether or not you like the keyframe and light information to be extracted.
- \param filename the name of the 3ds file
- \param model pointer to the #Model object
- \param generateMatrices should matrices for the keyframes be generated? (for animated player models)
- \param setupLights should the OpenGL lights be setup according to the lights in the scene? (for arenas)
- \return \c true on success \c false on errors
- */
- bool L3dsLoader::load3DS(const char* filename, Model* model, bool generateMatrices, bool setupLights){
- Lib3dsFile *f=0;
- // printf("loading file... ");
- f=lib3ds_file_load(filename);
- // printf("done.\n");
- if (!f) {
- // warn("(in load3DS()): Couldn't load file '%s'.\n", filename);
- return false;
- }
-
- path=File::extractPath(filename);
-
- int i=f->segment_from;
- lib3ds_file_eval(f,1.0f*i);
- lib3dsFileToModel(f,model);
-
- delete[] path;
-
- if(setupLights){
- log("extracting lights.\n");
- L3dsLoader::setupLights(f);
- }
-
- if(generateMatrices){
- model->numFrames=f->frames+1;//f->segment_to - f->segment_from +1;
- log("generating matrices for %i frames.\n", f->frames);
- for (i=f->segment_from+1; i<=f->segment_to; ++i) {
- //printf("frame %i", i);
- lib3ds_file_eval(f,1.0f*i);
-
- Lib3dsNode *n;
- for (n=f->nodes; n; n=n->next) {
- generateNodeMatrix(f, model, n, i, stdMatrix);
- }
- }
- }
- // model->dump();
- lib3ds_file_free(f);
- return true;
- }
-
-
-
-
-
-
-