home *** CD-ROM | disk | FTP | other *** search
- /*!
- \file ac3dloader.cpp
- \author Karsten Schwenk
- \version 1.0
-
- See header for describtion (ac3dloader.h).
- */
-
- #include "Ac3dLoader.h"
- #include "Tokenizer.h"
- #include "TextureHandler.h"
-
- #include <math.h>
-
- #include "vectormath.h"
- #include "matrixmath.h"
-
- #include "log.h"
-
- static int getTokens(char *s, int *argc, char *argv[]){
- char *p = s;
- char *st;
- char c;
- //int n;
- int tc;
-
- tc = 0;
- while ((c=*p) != 0){
- if ((c != ' ') && (c != '\t') && (c != '\n') && ( c != 13)){
- if (c == '"'){
- c = *p++;
- st = p;
- while ((c = *p) && ((c != '"')&&(c != '\n')&& ( c != 13)) ){
- if (c == '\\')
- strcpy(p, p+1);
- p++;
- }
- *p=0;
- argv[tc++] = st;
- }else{
- st = p;
- while ((c = *p) && ((c != ' ') && (c != '\t') && (c != '\n') && ( c != 13)) )
- p++;
- *p=0;
- argv[tc++] = st;
- }
- }
- p++;
- }
-
- *argc = tc;
- return(tc);
- }
-
- /*
-
- Ac3dSurface
-
- */
-
- Ac3dSurface::Ac3dSurface(Ac3dObject *object){
- ob=object;
- }
-
- void Ac3dSurface::calcNormal(){
- float len;
-
- normal[0] = (ob->v[indices[1]*3+1] - ob->v[indices[0]*3+1]/*v2->y-v1->y*/)*
- (ob->v[indices[2]*3+2] - ob->v[indices[0]*3+2]/*v3->z-v1->z*/)-
- (ob->v[indices[2]*3+1] - ob->v[indices[0]*3+1]/*v3->y-v1->y*/)*
- (ob->v[indices[1]*3+2] - ob->v[indices[0]*3+2]/*v2->z-v1->z*/);
- normal[1] = (ob->v[indices[1]*3+2] - ob->v[indices[0]*3+2]/*v2->z-v1->z*/)*
- (ob->v[indices[2]*3+0] - ob->v[indices[0]*3+0]/*v3->x-v1->x*/)-
-
- (ob->v[indices[2]*3+2] - ob->v[indices[0]*3+2]/*v3->z-v1->z*/)*
- (ob->v[indices[1]*3+0] - ob->v[indices[0]*3+0]/*v2->x-v1->x*/);
- normal[2] = (ob->v[indices[1]*3+0] - ob->v[indices[0]*3+0]/*v2->x-v1->x*/)*
- (ob->v[indices[2]*3+1] - ob->v[indices[0]*3+1]/*v3->y-v1->y*/)-
- (ob->v[indices[2]*3+0] - ob->v[indices[0]*3+0]/*v3->x-v1->x*/)*
- (ob->v[indices[1]*3+1] - ob->v[indices[0]*3+1]/*v2->y-v1->y*/);
-
- len = (float)sqrt(normal[0]*normal[0] + normal[1]*normal[1] + normal[2]*normal[2]);
-
- if (len > 0){
- normal[0] /= len;
- normal[1] /= len;
- normal[2] /= len;
- }
- }
-
-
- /*
-
- Ac3dMaterial
-
- */
-
- Ac3dMaterial::Ac3dMaterial(char *buff){
- if (getTokens(buff, &tokc, tokv) != 22){
- warn("(in A3dMaterial::Ac3dMaterial()): Expected 21 params after \"MATERIAL\". Ignoring values.\n\n");
- }else{
- shininess = (GLfloat)atof(tokv[19]);
- transparency = (GLfloat)atof(tokv[21]);
-
- name = newString(tokv[1]);
-
- diffuse[0] = (GLfloat)atof(tokv[3]);
- diffuse[1] = (GLfloat)atof(tokv[4]);
- diffuse[2] = (GLfloat)atof(tokv[5]);
- diffuse[3] = 1.0f - transparency;
-
- ambient[0] = (GLfloat)atof(tokv[7]);
- ambient[1] = (GLfloat)atof(tokv[8]);
- ambient[2] = (GLfloat)atof(tokv[9]);
- ambient[3] = 1.0f - transparency;
-
- emissive[0] = (GLfloat)atof(tokv[11]);
- emissive[1] = (GLfloat)atof(tokv[12]);
- emissive[2] = (GLfloat)atof(tokv[13]);
- emissive[3] = 1.0f;
-
- specular[0] = (GLfloat)atof(tokv[15]);
- specular[1] = (GLfloat)atof(tokv[16]);
- specular[2] = (GLfloat)atof(tokv[17]);
- specular[3] = 1.0f;
-
- /* ????
- shi = (float)atof(tokv[6]);
- tran = (float)atof(tokv[7]);
- */
- }
- }
-
-
-
- /*
-
- Ac3dObject
-
- */
-
- void Ac3dObject::clearObject(){
- name="unnamed";
-
- mat=NULL;
- surf=NULL;
- kids=NULL;
- v=NULL;
- n=NULL;
- texCoords=NULL;
-
- nMat=0;
- nV=0;
- nN=0;
- nSurf=0;
- nIndices=0;
- nKids=0;
- type=-1;
-
- v=NULL;
- n=NULL;
- indices=NULL;
- texCoords=NULL;
-
- loc[0]=0;
- loc[1]=0;
- loc[2]=0;
-
- matrixCopy(id3x3, rotMatrix, 3);
-
- line=0;
-
- // isTriangulation=false;
- hasTextures=false;
-
- if(texture!=NULL){
- //delete texture;
- }
- texture=NULL;
- texOffsX=texOffsY=0.0;
- texRepeatX=texRepeatY=1.0;
- }
-
-
- Ac3dObject::Ac3dObject(const char *filename){
-
- clearObject();
- FILE *f = fopen(filename, "r");
-
- if (f == NULL){
- warn("(in Ac3dObject::Ac3dObject()): Couldn't open %s - Object unchanged\n\n", filename);
- }else{
- readLine(f);
-
- if (strncmp(buff, "AC3D", 4)){
- warn("(in Ac3dObject::Ac3dObject()): '%s' seems not to be a valid AC3D file - Object unchanged.\n\n", filename);
- fclose(f);
- return;
- }
-
- line=0;
- readFromFile(f);
- calcNormals();
- fclose(f);
- // printf("%s loaded: %i Vertices, %i Surfaces, %i kids, isTriangulation: %b\n", filename, nV, nSurf, nKids, isTriangulation);
- }
- }
-
- Ac3dObject::Ac3dObject(FILE *f, int *l, Ac3dObject *parent){
- clearObject();
-
- line=*l;
-
- mat = parent->mat;
- nMat = parent->nMat;
- readFromFile(f);
- calcNormals();
- // fclose(f);
- }
-
-
-
- Ac3dSurface *Ac3dObject::readSurface(FILE *f){
-
- char t[20];
-
- Ac3dSurface *ret = new Ac3dSurface(this);
-
- while(!feof(f)){
- readLine(f);
- sscanf(buff, "%s", t);
-
- if (streq(t, "SURF")){
- int flgs;
-
- if (getTokens(buff, &tokc, tokv) != 2){
- warn("(in Ac3dObject::readSurface()): SURF should be followed by one flags argument. Ignoring flag.\n\n");
- }else{
- flgs = strtol(tokv[1], NULL, 0);
- ret->flags = flgs;
- }
- }else if (streq(t, "mat")){
- int mindx;
-
- sscanf(buff, "%s %d", t, &mindx);
- ret->mat = mindx;//+startmatindex;
- }
- else if (streq(t, "refs")){
- int num, n;
- int ind;
- float tx, ty;
-
- sscanf(buff, "%s %d", t, &num);
-
-
- ret->nIndices = num;
- ret->indices = new unsigned int[num];
- ret->texCoords = new float[num*2];
- // ret->tOffs[1] = new float[num];
-
- for (n = 0; n < num; n++){
- fscanf(f, "%d %f %f\n", &ind, &tx, &ty); line++;
- ret->indices[n] = ind;
-
- tx = texOffsX + tx * texRepeatX; // texOffs/Repeat vom object einrechnen
- ty = texOffsY + ty * texRepeatY;
-
- ret->texCoords[n*2+0] = tx;
- ret->texCoords[n*2+1] = ty;
- }
-
- if (ret->nIndices >= 3)
- ret->calcNormal();
-
- return(ret);
- }else
- warn("(in Ac3dObejct::readSurface()): Unexpected token '%s'. Ignoring.\n", t);
-
- }
- return NULL;
- }
-
-
- void Ac3dObject::readLine(FILE *f){
- fgets(buff, 255, f);
- line++;
- }
-
- void Ac3dObject::addMaterial(Ac3dMaterial *m){
- nMat++;
- Ac3dMaterial **newMat = new Ac3dMaterial*[nMat];
- for(int i=0; i<nMat-1; i++)
- newMat[i]=mat[i];
-
- delete[] mat;
- newMat[nMat-1]=m;
- mat=newMat;
- // printf("addMaterial: nMat: %i\n", nMat);
- }
-
- void Ac3dObject::calcNormals(){
- int i, j, k;
-
- nN=nV;
- n = new float[nN*3];
-
- for (i = 0; i < nV; i++){
- n[i*3+0]=0.0;
- n[i*3+1]=0.0;
- n[i*3+2]=0.0;
- int found = 0;
-
- for (j = 0; j < nSurf; j++){
- for (k = 0; k < surf[j]->nIndices; k++)
- if (surf[j]->indices[k] == (unsigned int)i){
- n[i*3+0]+=surf[j]->normal[0];
- n[i*3+1]+=surf[j]->normal[1];
- n[i*3+2]+=surf[j]->normal[2];
- found++;
- }
- }
- if (found > 0){
- n[i*3+0] /= found;
- n[i*3+1] /= found;
- n[i*3+2] /= found;
- }
- }
-
- }
-
-
-
-
- bool Ac3dObject::readFromFile(FILE *f){
-
-
- // Hier geht's ab
- char t[20]; //token
- while(!feof(f)){
- readLine(f);
- sscanf(buff, "%s", t);
-
- if (streq(t, "MATERIAL")){
- // float shi, tran;
- // printf("adding Material %i\n", nMat);
- addMaterial(new Ac3dMaterial(buff));
-
- }else if (streq(t, "OBJECT")){
- char tpe[20];
- char str[20];
- // ob = new_object();
-
- sscanf(buff, "%s %s", str, tpe);
-
- if (streq("world", tpe))
- type=OBJECT_WORLD;
- else if (streq("group", tpe))
- type=OBJECT_GROUP;
- else if (streq("light", tpe))
- type=OBJECT_LIGHT;
- else if (streq("poly", tpe))
- type=OBJECT_NORMAL;
- else
- type=OBJECT_NORMAL;
- // printf("reading Object type: %s\n",tpe);
-
- // type = string_to_objecttype(type);
- /* }else if (streq(t, "data")){ // ??????????
- if (getTokens(buff, &tokc, tokv) != 2){
- printToLogFile("expected 'data <number>' at line %d\n", line);
- }else{
- char *str;
- int len;
-
- len = atoi(tokv[1]);
- if (len > 0){
- str = (char *)myalloc(len+1);
- fread(str, len, 1, f);
- str[len] = 0;
- fscanf(f, "\n"); line++;
- ob->data = STRING(str);
- myfree(str);
- }
- }
-
- */ }else if(streq(t, "name")){
- int numtok = getTokens(buff, &tokc, tokv);
- if (numtok != 2){
- warn("(in Ac3dObject::readFromFile()): Expected quoted name at line %d (got %d tokens). Ignoring name statement\n\n", line, numtok);
- return false;
- }else{
- name = newString(tokv[1]);
- }
- // printf("reading name: %s \n",name);
-
-
- }else if(streq(t, "texture")){
- if (getTokens(buff, &tokc, tokv) != 2){
- warn("(in Ac3dObject::readFronFile()): Expected quoted texture name at line %d. Ignoring texture statement.\n\n", line);
- return false;
- }else{
- texture = TextureHandler::getTexture(tokv[1]);
- hasTextures=true;
- }
-
- }else if(streq(t, "texrep")){
- if (getTokens(buff, &tokc, tokv) != 3)
- warn("(in Ac3dObject::readFronFile()): Expected 'texrep <float> <float>' at line %d.\n\n", line);
- else{
- texRepeatX = (float)atof(tokv[1]);
- texRepeatY = (float)atof(tokv[2]);
- }
-
- }else if(streq(t, "texoff")){
- if (getTokens(buff, &tokc, tokv) != 3)
- warn("(Ac3dObject::readFromFile()): Expected 'texoff <float> <float>' at line %d.\n\n", line);
- else{
- texOffsX = (float)atof(tokv[1]);
- texOffsY = (float)atof(tokv[2]);
- }
-
- }else if(streq(t, "rot")){
- // printf("reading rot\n");
- float r[9];
- char str2[5];
- int n;
-
- sscanf(buff, "%s %f %f %f %f %f %f %f %f %f", str2, &r[0], &r[1], &r[2], &r[3], &r[4], &r[5], &r[6], &r[7], &r[8] );
-
- for (n = 0; n < 9; n++)
- rotMatrix[n] = r[n];
-
- }else if(streq(t, "loc")){
- // printf("reading loc\n");
- char str[5];
- float tmp[3];
- sscanf(buff, "%s %f %f %f", str,
-
- &tmp[0], &tmp[1], &tmp[2]);
- loc[0]=tmp[0];
- loc[1]=tmp[1];
- loc[2]=tmp[2];
- /* }else if (streq(t, "url")){ // scheiss drauf
- */ }else if(streq(t, "numvert")){
-
- int num, n;
- char str[10];
-
- sscanf(buff, "%s %d", str, &num);
-
- // printf("reading vertex array: %i vertices\n",num);
- if (num > 0){
- nV = num;
- v = new float[3*num];//(ACVertex *)myalloc(sizeof(ACVertex)*num);
- float tmp[3];
-
- for (n = 0; n < num; n++){
- fscanf(f, "%f %f %f\n", &tmp[0], &tmp[1], &tmp[2]);
- v[n*3+0]=tmp[0];
- v[n*3+1]=tmp[1];
- v[n*3+2]=tmp[2];
- line++;
- // vertices[n] = p;
- }
- }
- }else if (streq(t, "numsurf")){
- int num, n;
- char str[10];
-
- sscanf(buff, "%s %d", str, &num);
- // printf("reading surfaces: %i surfaces\n",num);
-
- if (num > 0){
- nSurf = num;
- surf = new Ac3dSurface *[num];
-
- for (n = 0; n < num; n++){
- surf[n] = readSurface(f);
- }
- }
- }else if(streq(t, "kids")){
-
- int num, n;
-
- sscanf(buff, "%s %d", t, &num);
-
- // printf("reading kids: %i kids\n", num);
- if (num != 0){
- nKids = num;
- kids = new Ac3dObject *[num];
-
- for (n = 0; n < num; n++){
- kids[n] = new Ac3dObject(f, &line, this);
- }
-
- }
- break; // THINKABOUTME: h÷rt's von aleine auf? return(ob);
- }
- }
- return true;
- }
-
-
- void Ac3dObject::dumpObject(){
- int i;
-
- if(name!=NULL)
- printf("OBJECT %s: nV: %i, nN:%i, nSurf:%i\n", name, nV, nN, nSurf);
-
- printf("loc: %f %f %f rot: ", loc[0],loc[1],loc[2]);
- matrixPrint(rotMatrix, 3);
- /*
- for(i=0; i<nMat; i++){
- printf("Material %i: amb: %f %f %f diff: %f %f %f spec: %f %f %f emi: %f %f %f shi: %f trans: %f\n",
- i,
- mat[i]->ambient[0], mat[i]->ambient[1], mat[i]->ambient[2],
- mat[i]->diffuse[0], mat[i]->diffuse[1], mat[i]->diffuse[2],
- mat[i]->specular[0], mat[i]->specular[1], mat[i]->specular[2],
- mat[i]->emissive[0], mat[i]->emissive[1], mat[i]->emissive[2],
- mat[i]->shininess, mat[i]->transparency
- );
- }
-
- printf("loc: %f %f %f\n", loc[0], loc[1], loc[2]);
-
- for(i=0; i<nV; i++){
- printf("vertex array[%i]: %f %f %f \n", i, (float)v[i*3+0], (float)v[i*3+1], (float)v[i*3+2]);
- }
-
- for(i=0; i<nN; i++){
- printf("normal array[%i]: %f %f %f \n", i, (float)n[i*3+0], (float)n[i*3+1], (float)n[i*3+2]);
- }
-
- for(i=0; i<nSurf; i++){
- printf("surface[%i]: nIndices: %i mat: %i \n", i, surf[i]->nIndices, surf[i]->mat);
- }
- */
- for(i=0; i<nKids; i++){
- printf("\n\n-- kid %i\n\n", i);
- kids[i]->dumpObject();
- }
-
- }
-
-
-
-
-
-
-
- Mesh* Ac3dLoader::Ac3dObjectToMesh(Ac3dObject* o){
- int i, j;
- Mesh* ret=new Mesh();
- int *materialLookUp=new int[o->nMat];
-
- if(o->name!=NULL)
- ret->name=newString(o->name);
-
- //printf("\n\nadding mats for %s\n", ret->name);
- for(i=0;i<o->nMat;i++){
- for(j=0;j<o->nSurf;j++){
- if(o->surf[j]->mat==i){
- Material* mat=new Material();
- /*
- vectorCopy4d(o->mat[i]->ambient, mat->ambient);
- vectorCopy4d(o->mat[i]->diffuse, mat->diffuse);
- vectorCopy4d(o->mat[i]->specular, mat->specular);
- vectorCopy4d(o->mat[i]->emissive, mat->emissive);
- mat->shininess=o->mat[i]->shininess;
- */
- vectorCopy4d(o->mat[i]->diffuse, mat->color);
-
- if(o->hasTextures){
- mat->addTexture(o->texture);
- }
- mat->setAttribs();
- materialLookUp[i]=ret->addMaterial(mat);
- //printf("mat %i added -> %i.\n",i,materialLookUp[i]);
- break;
- }
- }
- //printf("asd");
- }
-
-
- for(i=0;i<o->nSurf;i++){
- Face* face=new Face();
-
- face->material=ret->materials[materialLookUp[o->surf[i]->mat]];
- //printf("face->mat: %i\n",materialLookUp[o->surf[i]->mat]);
-
- face->vertices=new GLfloat[o->surf[i]->nIndices*3];
- face->colors=new GLfloat[o->surf[i]->nIndices*3];
- face->normals=new GLfloat[o->surf[i]->nIndices*3];
- face->texCoords1=new GLfloat[o->surf[i]->nIndices*2];
- face->texCoords2=new GLfloat[o->surf[i]->nIndices*2];
- face->numIndices=face->numNormals=face->numColors=face->numVertices=face->numTexCoords= o->surf[i]->nIndices;
-
- for(j=0;j<o->surf[i]->nIndices;j++){
- vectorCopy3d(&o->v[o->surf[i]->indices[j]*3], &face->vertices[j*3]);
- vectorCopy3d(face->material->color, &face->colors[j*3]);
- if(o->surf[i]->flags & SURFACE_SHADED)
- vectorCopy3d(&o->n[o->surf[i]->indices[j]*3], &face->normals[j*3]);
- else
- vectorCopy3d(o->surf[i]->normal, &face->normals[j*3]);
-
- vectorCopy2d(&o->surf[i]->texCoords[j*2], &face->texCoords1[j*2]);
- vectorCopy2d(&o->surf[i]->texCoords[j*2], &face->texCoords2[j*2]);
- }
-
- face->calcNormal();
- ret->addFace(face);
- }
-
-
- GLfloat mat[16]={
- o->rotMatrix[0], o->rotMatrix[1], o->rotMatrix[2], 0,
- o->rotMatrix[3], o->rotMatrix[4], o->rotMatrix[5], 0,
- o->rotMatrix[6], o->rotMatrix[7], o->rotMatrix[8], 0,
- o->loc[0], o->loc[1], o->loc[2], 1
- };
-
- matrixCopy(mat, ret->transformationMatrix, 4);
-
- ret->numChilds=o->nKids;
- ret->childs=new Mesh*[ret->numChilds];
- for(i=0;i<o->nKids;i++){
- ret->childs[i]=Ac3dObjectToMesh(o->kids[i]);
- ret->childs[i]->parent=ret;
- }
-
- ret->setRenderMode();
-
- delete[] materialLookUp;
- return ret;
- }
-
- /*!
- This function loads an ac3d file into a #Model object (that can be rendered instantly with #renderModel()).
- This is usually called from within the #Model constructor.
- \return \c true on success \c false on errors
- */
- bool Ac3dLoader::loadAC3D(const char* filename, Model* model){
-
- Ac3dObject* o=new Ac3dObject(filename);
-
-
- // o->dumpObject();
-
- model->addMesh(Ac3dObjectToMesh(o));
- model->numKeyframes=1;
- // model->dump();
-
- delete o;
- return true;
- }
-
-
-
-