// // // Generated by StarUML(tm) C++ Add-In // // @ Project : MayaMELObjectExport // @ File Name : MayaExp.cpp // @ Date : 2007-2-23 // @ Author : kongfu.yang // @ Company : http://www.play3d.net // @ Copyright : 2007-2, Example source license. By keep this header comment, you may use this source file in your project for non-commicial or commicial purpose. #include "MayaExp.h" #include #include #include void MayaExp::close(void) { if ( objs != 0 ) { free(objs); } } void info(const char * fmt, ...) { va_list args; va_start(args,fmt); vprintf(fmt,args); va_end(args); } void MayaExp::loadFromFile(const char * fname, int verbose) { #define READ_MEL_FLOAT(var) \ fread( &(var), 8, 1, fp ); FILE * fp = fopen(fname, "rb"); // read export header fread( & (header), sizeof(ExpHeader), 1, fp ); info("\nExported Maya Object:\n %d objects\nradius %d\n", this->header.objCount, this->header.objRadius); this->objs = (ExpObj*) malloc( sizeof(ExpObj) * this->header.objCount ); ExpObj *obj = this->objs; long size; for ( int i = 0; i < this->header.objCount; ++ i ) { info("reading object, index=%d\n", i); // read one object: face, vertex, normal, uv // face if ( verbose ) info("offset %d, to face block header\n", ftell(fp)); fread( &(obj->faceBlock.header), sizeof(ExpBlockHeader), 1, fp ); if ( verbose ) info("block readed: type=%x, content=%x\n", obj->faceBlock.header.blockType, obj->faceBlock.header.blockContent ); info("it has %d face.\n", obj->faceBlock.header.elementCount / 3); // the mel script write faces * 3 in elementCount size = sizeof(Vector3i) * obj->faceBlock.header.elementCount / 3; // the mel script write faces * 3 in elementCount obj->faceBlock.faces = (Vector3i *)malloc( size ); info("offset %d, to face block data\n", ftell(fp)); fread( obj->faceBlock.faces, size, 1, fp ); // dump vertex index of each face for ( int j = 0; j < obj->faceBlock.header.elementCount /3; ++j ) { info("face %03d: (%03d, %03d, %03d)\n", j, obj->faceBlock.faces[j].a, obj->faceBlock.faces[j].b, obj->faceBlock.faces[j].c); } // vertex info("offset %d, to vertex block header\n", ftell(fp)); fread( &(obj->vertexBlock.header), sizeof(ExpBlockHeader), 1, fp ); info("block readed: type=%x, content=%x\n", obj->vertexBlock.header.blockType, obj->vertexBlock.header.blockContent ); info("it has %d vertex.\n", obj->vertexBlock.header.elementCount); size = sizeof(Vector3) * obj->vertexBlock.header.elementCount; // vertex has 3 element obj->vertexBlock.vertexs = (Vector3 *)malloc( size ); info("offset %d, to read vertex\n", ftell(fp)); // read and convert for ( int i = 0; i < obj->vertexBlock.header.elementCount ; ++ i ) { info("read %04dth vertex, ", i); READ_MEL_FLOAT( obj->vertexBlock.vertexs[i].x ); READ_MEL_FLOAT( obj->vertexBlock.vertexs[i].y ); READ_MEL_FLOAT( obj->vertexBlock.vertexs[i].z ); if ( verbose ) { info(" => "); info("(%f, %f, %f)\n", obj->vertexBlock.vertexs[i].x,obj->vertexBlock.vertexs[i].y,obj->vertexBlock.vertexs[i].z); } } //fread( &(obj->vertexBlock.vertexs), size, 1, fp ); // normal info("offset %d, to read normal\n", ftell(fp)); fread( &(obj->normalBlock.header), sizeof(ExpBlockHeader), 1, fp ); info("block readed: type=%x, content=%x\n", obj->normalBlock.header.blockType, obj->normalBlock.header.blockContent ); info("it has %d normal.\n", obj->normalBlock.header.elementCount); size = sizeof(Vector3) * obj->normalBlock.header.elementCount; obj->normalBlock.normals = (Vector3*)malloc( size ); // read and convert for ( int i = 0; i < obj->normalBlock.header.elementCount ; ++ i ) { info("read %04dth normal, ", i); READ_MEL_FLOAT( obj->normalBlock.normals[i].x ); READ_MEL_FLOAT( obj->normalBlock.normals[i].y ); READ_MEL_FLOAT( obj->normalBlock.normals[i].z ); if ( verbose ) { info(" => "); info("(%f, %f, %f)\n", obj->normalBlock.normals[i].x,obj->normalBlock.normals[i].y,obj->normalBlock.normals[i].z); } } //fread( &(obj->normalBlock.normals), size, 1, fp ); // uv info("offset %d, to read uv\n", ftell(fp)); fread( &(obj->uvBlock.header), sizeof(ExpBlockHeader), 1, fp ); info("block readed: type=%x, content=%x\n", obj->uvBlock.header.blockType, obj->uvBlock.header.blockContent ); info("it has %d uv.\n", obj->uvBlock.header.elementCount); size = sizeof(Vector2) * obj->uvBlock.header.elementCount; obj->uvBlock.uvs = (Vector2 *)malloc( size ); // read and convert for ( int i = 0; i < obj->uvBlock.header.elementCount ; ++ i ) { info("read %04dth uv, ", i); READ_MEL_FLOAT( obj->uvBlock.uvs[i].x ); READ_MEL_FLOAT( obj->uvBlock.uvs[i].y ); if ( verbose ) { info(" => "); info("(%f, %f)\n", obj->uvBlock.uvs[i].u,obj->uvBlock.uvs[i].v); } } //fread( &(obj->uvBlock.uvs), size, 1, fp ); } // read materials if ( ! feof(fp) ) { info("offset %d, to read material\n", ftell(fp)); fread( & (this->mats.header), sizeof(ExpBlockHeader), 1, fp ); info("block readed: type=%x, content=%x\n", this->mats.header.blockType, this->mats.header.blockContent ); info("exported %d materials.\n", this->mats.header.elementCount); size = sizeof(ExpMaterialBlock) * this->mats.header.elementCount; this->mats.materials = (ExpMaterialBlock *) malloc(size); // we'd better to new [] instead of malloc! ExpMaterialBlock * pbmat; for ( int i = 0; i < this->mats.header.elementCount; ++i ) { pbmat = &(this->mats.materials[i]); // ExpMaterialBlock composite an ExpMaterial member fread( & (pbmat->material.nameLength), sizeof(int), 1, fp ); pbmat->material.name = (char*) malloc( pbmat->material.nameLength + 1 ); fread( pbmat->material.name, pbmat->material.nameLength+1, 1, fp ); // tail 0 as string end flag is written by mel but not count in length. //pbmat->name[pbmat->nameLength] = 0; info("name: %s, length %d\n", pbmat->material.name, pbmat->material.nameLength); // ambient READ_MEL_FLOAT( pbmat->material.ambientColor.r ); READ_MEL_FLOAT( pbmat->material.ambientColor.g ); READ_MEL_FLOAT( pbmat->material.ambientColor.b ); info("ambient color (%f,%f,%f)\n", pbmat->material.ambientColor.r, pbmat->material.ambientColor.g, pbmat->material.ambientColor.b ); // diffuse READ_MEL_FLOAT( pbmat->material.diffuseColor.r ); READ_MEL_FLOAT( pbmat->material.diffuseColor.g ); READ_MEL_FLOAT( pbmat->material.diffuseColor.b ); info("diffuse color (%f,%f,%f)\n", pbmat->material.diffuseColor.r, pbmat->material.diffuseColor.g, pbmat->material.diffuseColor.b ); // specular READ_MEL_FLOAT( pbmat->material.specularColor.r ); READ_MEL_FLOAT( pbmat->material.specularColor.g ); READ_MEL_FLOAT( pbmat->material.specularColor.b ); info("specular color (%f,%f,%f)\n", pbmat->material.specularColor.r, pbmat->material.specularColor.g, pbmat->material.specularColor.b ); // transparency READ_MEL_FLOAT( pbmat->material.transparency); info("transparency: %f\n", pbmat->material.transparency); // cosinePower READ_MEL_FLOAT( pbmat->material.cosinePower ); info("shininess (cosine power): %f\n", pbmat->material.cosinePower); // read the texture related to this material info("offset %d, to read texture\n", ftell(fp)); fread( & (pbmat->texture.blockType), sizeof(unsigned int), 1, fp ); info("texture block type %X", pbmat->texture.blockType); if ( pbmat->texture.blockType == EMPTY_TEXTURE_BLOCK ) { fread( &(pbmat->texture.nameLength), sizeof(unsigned int), 1, fp ); // would be zero pbmat->texture.name = NULL; fread( &(pbmat->texture.u), sizeof(unsigned int), 1, fp ); // would be 1 fread( &(pbmat->texture.v), sizeof(unsigned int), 1, fp ); // would be 1 }else if (pbmat->texture.blockType == FILE_TEXTURE_BLOCK ){ fread( &(pbmat->texture.nameLength), sizeof(unsigned int), 1, fp ); pbmat->texture.name = (char*)malloc( pbmat->texture.nameLength + 1 ); fread( pbmat->texture.name, pbmat->texture.nameLength + 1, 1, fp ); fread( &(pbmat->texture.u), sizeof(unsigned int), 1, fp ); // usually, it is 1 fread( &(pbmat->texture.v), sizeof(unsigned int), 1, fp ); // usually, it is 1 }else{ printf("\n!!!! unreconginzed texture block !!!!\n"); } } } fclose(fp); } void MayaExp::saveAsFloat(const char * fname) { // write into a much simple format // {face count, vertex count} {vertex:3 float}* {normal:3 float}* {uv:2 float}* {face: 3 int index to its vertex}* char buf[1024]; FILE *fp; ExpObj * obj; for ( int i = 0; i < this->header.objCount; ++i ) { sprintf(buf, "%s.%03d", fname, i); printf("\nconverting object %d to float point format and save the result to %s.\n", i, buf); fp = fopen(buf, "wb"); obj = &(this->objs[i]); // head int count = obj->faceBlock.header.elementCount / 3; // MEL script write count of vertex index instead of face, each face has 3 vertex index fwrite( & count, sizeof(int), 1, fp ); fwrite( & obj->vertexBlock.header.elementCount, sizeof(int), 1, fp ); printf("this object has %d faces and %d vertexs.\n", obj->faceBlock.header.elementCount, obj->vertexBlock.header.elementCount ); // vertex for ( int i = 0; i < obj->vertexBlock.header.elementCount; ++i ) { fwrite( & obj->vertexBlock.vertexs[i].x, sizeof(double), 1, fp ); fwrite( & obj->vertexBlock.vertexs[i].y, sizeof(double), 1, fp ); fwrite( & obj->vertexBlock.vertexs[i].z, sizeof(double), 1, fp ); } // normal for ( int i = 0; i < obj->normalBlock.header.elementCount; ++i ) { fwrite( & obj->normalBlock.normals[i].x, sizeof(double), 1, fp ); fwrite( & obj->normalBlock.normals[i].y, sizeof(double), 1, fp ); fwrite( & obj->normalBlock.normals[i].z, sizeof(double), 1, fp ); } // bullet proof if ( obj->normalBlock.header.elementCount != obj->vertexBlock.header.elementCount ) { printf("\n !!! there are %d vertex, but %d normal !!! \n ", obj->vertexBlock.header.elementCount, obj->normalBlock.header.elementCount); // todo : fill 0 or fseek back } // uv for ( int i = 0; i < obj->uvBlock.header.elementCount; ++i ) { fwrite( & obj->uvBlock.uvs[i].u, sizeof(double), 1, fp ); fwrite( & obj->uvBlock.uvs[i].v, sizeof(double), 1, fp ); } // bullet proof if ( obj->uvBlock.header.elementCount != obj->vertexBlock.header.elementCount ) { printf("\n !!! there are %d vertex, but %d uv !!! \n ", obj->vertexBlock.header.elementCount, obj->uvBlock.header.elementCount); // todo : fill 0 or fseek back } // face index for ( int i = 0; i < obj->faceBlock.header.elementCount; ++i ) { fwrite( & obj->faceBlock.faces[i].a, sizeof(int), 1, fp ); fwrite( & obj->faceBlock.faces[i].b, sizeof(int), 1, fp ); fwrite( & obj->faceBlock.faces[i].c, sizeof(int), 1, fp ); } fclose(fp); fp = 0; } } // to avoid to include opengl-es/gl.h typedef int GLfixed; #define Float2Fixed(fl) ((GLfixed)((fl)*65536.0f)) void MayaExp::saveAsFixed(const char * fname) { // write into a much simple format // {face count, vertex count} {vertex:3 fixed}* {normal:3 fixed}* {uv:2 fixed}* {face: 3 int index to its vertex}* char buf[1024]; FILE *fp; ExpObj * obj; GLfixed fixed; for ( int i = 0; i < this->header.objCount; ++i ) { sprintf(buf, "%s.%03d", fname, i); printf("\nconverting object %d to fix point format and save the result to %s.\n", i, buf); fp = fopen(buf, "wb"); obj = &(this->objs[i]); // head int count = obj->faceBlock.header.elementCount / 3; // MEL exported face count is count of vertex index instead of faces fwrite( & count, sizeof(int), 1, fp ); fwrite( & obj->vertexBlock.header.elementCount, sizeof(int), 1, fp ); printf("this object has %d faces and %d vertexs.\n", obj->faceBlock.header.elementCount / 3, obj->vertexBlock.header.elementCount ); // vertex for ( int i = 0; i < obj->vertexBlock.header.elementCount; ++i ) { fixed = Float2Fixed(obj->vertexBlock.vertexs[i].x); fwrite( &fixed, sizeof(GLfixed), 1, fp ); fixed = Float2Fixed(obj->vertexBlock.vertexs[i].y); fwrite( &fixed, sizeof(GLfixed), 1, fp ); fixed = Float2Fixed(obj->vertexBlock.vertexs[i].z); fwrite( &fixed, sizeof(GLfixed), 1, fp ); } // normal for ( int i = 0; i < obj->normalBlock.header.elementCount; ++i ) { fixed = Float2Fixed(obj->normalBlock.normals[i].x); fwrite( &fixed, sizeof(GLfixed), 1, fp ); fixed = Float2Fixed(obj->normalBlock.normals[i].y); fwrite( &fixed, sizeof(GLfixed), 1, fp ); fixed = Float2Fixed(obj->normalBlock.normals[i].z); fwrite( &fixed, sizeof(GLfixed), 1, fp ); } // bullet proof if ( obj->normalBlock.header.elementCount != obj->vertexBlock.header.elementCount ) { printf("\n !!! there are %d vertex, but %d normal !!! \n ", obj->vertexBlock.header.elementCount, obj->normalBlock.header.elementCount); // todo : fill 0 or fseek back } // uv for ( int i = 0; i < obj->uvBlock.header.elementCount; ++i ) { fixed = Float2Fixed(obj->uvBlock.uvs[i].u); fwrite( &fixed, sizeof(GLfixed), 1, fp ); fixed = Float2Fixed(obj->uvBlock.uvs[i].v); fwrite( &fixed, sizeof(GLfixed), 1, fp ); } // bullet proof if ( obj->uvBlock.header.elementCount != obj->vertexBlock.header.elementCount ) { printf("\n !!! there are %d vertex, but %d uv !!! \n ", obj->vertexBlock.header.elementCount, obj->uvBlock.header.elementCount); // todo : fill 0 or fseek back } // face index unsigned short idx; for ( int i = 0; i < obj->faceBlock.header.elementCount / 3; ++i ) { idx = obj->faceBlock.faces[i].a; fwrite( & idx, sizeof(unsigned short), 1, fp ); idx = obj->faceBlock.faces[i].b; fwrite( & idx, sizeof(unsigned short), 1, fp ); idx = obj->faceBlock.faces[i].c; fwrite( & idx, sizeof(unsigned short), 1, fp ); } fclose(fp); fp = 0; } }