// Generate.cpp: implementation of the Generate class. // ////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include "generate.h" #include "msLib.h" #define INDENT " " #define EOL "\r\n" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// Generate::Generate(msModel *model) : m_model(model), m_cogx(0), m_cogy(0), m_cogz(0), m_appcogx(0), m_appcogy(0), m_appcogz(0), m_max_x(FLT_MIN), m_min_x(FLT_MAX), m_max_y(FLT_MIN), m_min_y(FLT_MAX), m_max_z(FLT_MIN), m_min_z(FLT_MAX), m_blitzMax(false), m_normals(false), m_indent(0) { CalcModelBounds(); } Generate::~Generate() { } ////////////////////////////////////////////////////////////////////// // Public members ////////////////////////////////////////////////////////////////////// std::string Generate::Info() { std::ostringstream str; str << "Create files : " << EOL; if (m_blitzMax) { str << "\t" << m_dir << "\\" << m_funcName << ".bmx" << EOL << EOL; } else { str << "\t" << m_dir << "\\" << m_funcName << ".c" << EOL << "\t" << m_dir << "\\" << m_funcName << ".h" << EOL << EOL; } str << "Centre of gravity : " << (m_cogx-m_appcogx) << "," << (m_cogy-m_appcogy) << "," << (m_cogz-m_appcogz) << EOL << "Lowest X co-ord : " << m_min_x-m_appcogx << EOL << "Highest X co-ord : " << m_max_x-m_appcogx << EOL << "Lowest Y co-ord : " << m_min_y-m_appcogx << EOL << "Highest Y co-ord : " << m_max_y-m_appcogx << EOL << "Lowest Z co-ord : " << m_min_z-m_appcogx << EOL << "Highest Z co-ord : " << m_max_z-m_appcogx << EOL; return str.str(); } void Generate::MakeFiles(HWND parent) { if (m_normals) { for(int m=0;mnNumMeshes;m++) { msMesh *mesh=m_model->pMeshes+m; if (mesh->nMaterialIndex<0) { W32DLib::Common::Error (parent,0, "Materials must be assigned if the object is to be lit"); return; } } } if (m_blitzMax) { GenerateBlitzMax(parent); } else { GenerateC(parent); } } void Generate::Setup(const std::string& dir, const std::string& funcname, bool texture, bool info, bool forceCOG, bool blitzMax, bool vertex_normals) { m_dir=dir; m_funcName=funcname; m_useTexture=texture; m_useInfo=info; m_forceCOG=forceCOG; m_blitzMax=blitzMax; m_normals=vertex_normals; if (m_forceCOG) { m_appcogx=m_cogx; m_appcogy=m_cogy; m_appcogz=m_cogz; } else { m_appcogx=0; m_appcogy=0; m_appcogz=0; } } std::string Generate::GenerateFuncname() { std::string fn; char *name; msMesh *mesh=msModel_GetMeshAt(m_model,0); name=mesh->szName; for(int f=0;name[f];f++) { if (std::isalnum(name[f]) || (f && name[f]=='_')) { fn+=name[f]; } } if (fn=="") { fn="object"; } return fn; } ////////////////////////////////////////////////////////////////////// // Private members ////////////////////////////////////////////////////////////////////// const char *Generate::Space(int len) { static int cyc=0; static char buff[10][128]; int f; cyc=(cyc+1)%10; for(f=0;fnNumMeshes;m++) { msMesh *mesh; mesh=m_model->pMeshes+m; for(int t=0;tnNumTriangles;t++) { msTriangle *tri; tri=mesh->pTriangles+t; if (!(tri->nFlags&eHidden)) { for(int i=0;i<3;i++) { msVertex *v=mesh->pVertices+tri->nVertexIndices[i]; m_min_x=std::min(m_min_x,v->Vertex[0]); m_max_x=std::max(m_max_x,v->Vertex[0]); m_min_y=std::min(m_min_y,v->Vertex[1]); m_max_y=std::max(m_max_y,v->Vertex[1]); m_min_z=std::min(m_min_z,v->Vertex[2]); m_max_z=std::max(m_max_z,v->Vertex[2]); } } } } m_cogx=m_min_x+(m_max_x-m_min_x)/2; m_cogy=m_min_y+(m_max_y-m_min_y)/2; m_cogz=m_min_z+(m_max_z-m_min_z)/2; } void Generate::GenerateC(HWND parent) { int len; std::string fname_c; std::string fname_h; std::string def; std::string missing; m_indent=0; len=m_funcName.length()+6; fname_c=m_dir+"\\"+m_funcName; fname_h=fname_c+".h"; fname_c+=".c"; for(std::string::const_iterator i=m_funcName.begin(); i!=m_funcName.end();++i) { def+=std::toupper(*i); } // Generate header // if (!(m_fp=fopen(fname_h.c_str(),"w"))) { W32DLib::Common::Error(parent,0,"Couldn't create header file"); return; } Output("%s","/* Code generated with Milkshape Export OpenGL plugin\n*/\n"); Output("\n"); Output("#ifndef %s_H\n#define %s_H\n\n", def.c_str(),def.c_str()); Output("%s","#ifdef _cplusplus\nextern \"C\" {\n#endif\n\n"); Output("void %s(GLfloat x, GLfloat y, GLfloat z,\n", m_funcName.c_str()); Output("%sGLfloat rot_x, GLfloat rot_y, GLfloat rot_z", Space(len)); if (m_useTexture) { Output(",\n%sGLint texture_id);\n\n", Space(len)); } else { Output(");\n\n"); } Output("/* Returns true if a display list " "could be created for the model */\n"); Output("int %s_CreateList(void);\n\n",m_funcName.c_str()); if (m_useInfo) { Output("#define %s_COG_X %f\n",def.c_str(),m_cogx-m_appcogx); Output("#define %s_COG_Y %f\n",def.c_str(),m_cogy-m_appcogy); Output("#define %s_COG_Z %f\n\n",def.c_str(),m_cogz-m_appcogz); Output("#define %s_MIN_X %f\n",def.c_str(),m_min_x-m_appcogx); Output("#define %s_MAX_X %f\n",def.c_str(),m_max_x-m_appcogx); Output("#define %s_MIN_Y %f\n",def.c_str(),m_min_y-m_appcogy); Output("#define %s_MAX_Y %f\n",def.c_str(),m_max_y-m_appcogy); Output("#define %s_MIN_Z %f\n",def.c_str(),m_min_z-m_appcogz); Output("#define %s_MAX_Z %f\n\n",def.c_str(),m_max_z-m_appcogz); float sx=m_max_x-m_min_x; float sy=m_max_y-m_min_y; float sz=m_max_z-m_min_z; Output("#define %s_SIZE_X %f\n",def.c_str(),sx); Output("#define %s_SIZE_Y %f\n",def.c_str(),sy); Output("#define %s_SIZE_Z %f\n\n",def.c_str(),sz); } Output("#define %s_TEXTURED %d\n\n",def.c_str(),m_useTexture?1:0); Output("#define %s_MATERIALS %d\n\n",def.c_str(),m_normals?1:0); Output("%s","#ifdef _cplusplus\n}\n#endif\n\n"); Output("#endif /* %s_H */\n\n",def.c_str()); Output("%s","/* END OF FILE */\n"); std::fclose(m_fp); // Generate C source // if (!(m_fp=fopen(fname_c.c_str(),"w"))) { W32DLib::Common::Error(parent,0,"Couldn't create source file"); return; } Output("%s","/* Code generated with Milkshape Export OpenGL plugin\n*/\n"); Output("%s","#include \n\n"); Output("static GLuint list_id=GL_INVALID_VALUE;\n\n"); Output("static void Geometry(void)\n"); Output("{\n"); m_indent++; if (m_normals) { Output("GLfloat ambient[4];\n"); Output("GLfloat diffuse[4];\n"); Output("GLfloat specular[4];\n"); Output("GLfloat emission[4];\n"); Output("\n"); } GenerateCommon(missing,";","/*","*/"); m_indent--; Output("}\n\n"); Output("int %s_CreateList(void)\n",m_funcName.c_str()); Output("{\n"); m_indent++; Output("list_id=glGenLists(1);\n"); Output("if (list_id==GL_INVALID_VALUE) return 0;\n"); Output("glNewList(list_id,GL_COMPILE);\n"); Output("Geometry();\n"); Output("glEndList();\n"); Output("return 1;\n"); m_indent--; Output("}\n\n"); Output("void %s(GLfloat x, GLfloat y, GLfloat z,\n", m_funcName.c_str()); Output("%sGLfloat rot_x, GLfloat rot_y, GLfloat rot_z", Space(len)); if (m_useTexture) { Output(",\n%sGLint texture_id)\n", Space(len)); } else { Output(")\n"); } Output("{\n"); m_indent++; Output("glPushMatrix();\n"); Output("glTranslatef(x,y,z);\n"); Output("glRotatef(rot_x,1,0,0);\n"); Output("glRotatef(rot_y,0,1,0);\n"); Output("glRotatef(rot_z,0,0,1);\n"); if (m_useTexture) { Output("glBindTexture(GL_TEXTURE_2D,texture_id);\n"); } Output("\n"); Output("if (list_id==GL_INVALID_VALUE)\n"); Output("{\n"); m_indent++; Output("Geometry();\n"); m_indent--; Output("}\n"); Output("else\n"); Output("{\n"); m_indent++; Output("glCallList(list_id);\n"); m_indent--; Output("}\n"); Output("\n"); Output("glPopMatrix();\n"); m_indent--; Output("}\n"); std::fclose(m_fp); if (missing.length()>0) { missing="The following meshes had no material:\n\n"+missing; missing+="\n\nThey were given the colour white."; W32DLib::Common::Message(parent,0,missing); } } void Generate::GenerateBlitzMax(HWND parent) { std::string fname_bmx; std::string missing; fname_bmx=m_dir+"\\"+m_funcName+".bmx"; m_indent=0; // Generate class // if (!(m_fp=fopen(fname_bmx.c_str(),"w"))) { W32DLib::Common::Error(parent,0,"Couldn't create source file"); return; } Output("%s","' Code generated with Milkshape Export OpenGL plugin\n'\n"); Output("\n"); Output("Type %s\n",m_funcName.c_str()); Output("\n"); m_indent++; if (m_useInfo) { Output("' Consts relating to the model's size and centre of gravity\n"); Output("'\n"); Output("Const COG_X:Float=%f\n",m_cogx-m_appcogx); Output("Const COG_Y:Float=%f\n",m_cogy-m_appcogy); Output("Const COG_Z:Float=%f\n\n",m_cogz-m_appcogz); Output("Const MIN_X:Float=%f\n",m_min_x-m_appcogx); Output("Const MAX_X:Float=%f\n",m_max_x-m_appcogx); Output("Const MIN_Y:Float=%f\n",m_min_y-m_appcogy); Output("Const MAX_Y:Float=%f\n",m_max_y-m_appcogy); Output("Const MIN_Z:Float=%f\n",m_min_z-m_appcogz); Output("Const MAX_Z:Float=%f\n\n",m_max_z-m_appcogz); float sx=m_max_x-m_min_x; float sy=m_max_y-m_min_y; float sz=m_max_z-m_min_z; Output("Const SIZE_X:Float=%f\n",sx); Output("Const SIZE_Y:Float=%f\n",sy); Output("Const SIZE_Z:Float=%f\n\n",sz); Output("const TEXTURED:Int=%s\n",m_useTexture ? "true":"false"); Output("const MATERIALS:Int=%s\n",m_normals ? "true":"false"); Output("\n"); } Output("' These fields control the position/orientation of the object\n"); Output("'\n"); Output("Field x:Float\n"); Output("Field y:Float\n"); Output("Field z:Float\n"); Output("Field rot_x:Float\n"); Output("Field rot_y:Float\n"); Output("Field rot_z:Float\n"); Output("\n"); Output("' This field should be considered private\n"); Output("'\n"); Output("Global list_id:Int=GL_INVALID_VALUE\n"); Output("\n"); Output("' Use this function to create an instance\n"); Output("'\n"); Output("Function Create:%s()\n",m_funcName.c_str()); m_indent++; Output("Local o:%s = New %s\n",m_funcName.c_str(),m_funcName.c_str()); Output("o.x=0\n"); Output("o.y=0\n"); Output("o.z=0\n"); Output("o.rot_x=0\n"); Output("o.rot_y=0\n"); Output("o.rot_z=0\n"); Output("return o\n"); m_indent--; Output("End Function\n"); Output("\n"); Output("' Use this function to setup a display list.\n"); Output("' Returns True it the display list is created.\n"); Output("'\n"); Output("Function CreateDisplayList:Int()\n"); m_indent++; Output("list_id=glGenLists(1)\n"); Output("if (list_id=GL_INVALID_VALUE) then return False\n"); Output("glNewList(list_id,GL_COMPILE)\n"); Output("Geometry()\n"); Output("glEndList()\n"); Output("return True\n"); m_indent--; Output("End Function\n"); Output("\n"); Output("' Use this member to draw the object\n"); Output("'\n"); if (m_useTexture) { Output("Method Render(texture_id:Int)\n"); } else { Output("Method Render()\n"); } m_indent++; Output("glPushMatrix()\n"); Output("glTranslatef(x,y,z)\n"); Output("glRotatef(rot_x,1,0,0)\n"); Output("glRotatef(rot_y,0,1,0)\n"); Output("glRotatef(rot_z,0,0,1)\n"); if (m_useTexture) { Output("glBindTexture(GL_TEXTURE_2D,texture_id)\n"); } Output("\n"); Output("If (list_id=GL_INVALID_VALUE)\n"); m_indent++; Output("Geometry()\n"); m_indent--; Output("Else\n"); m_indent++; Output("glCallList(list_id)\n"); m_indent--; Output("End If\n"); Output("\n"); Output("glPopMatrix()\n"); m_indent--; Output("End Method\n"); Output("\n"); Output("' This function should be considered private.\n"); Output("'\n"); Output("Function Geometry()\n"); m_indent++; if (m_normals) { Output("Local ambient:Float[4]\n"); Output("Local diffuse:Float[4]\n"); Output("Local specular:Float[4]\n"); Output("Local emission:Float[4]\n"); Output("\n"); } GenerateCommon(missing,"","'",""); m_indent--; Output("End Function\n"); m_indent--; Output("End Type\n"); std::fclose(m_fp); if (missing.length()>0) { missing="The following meshes had no material:\n\n"+missing; missing+="\n\nThey were given the colour white."; W32DLib::Common::Message(parent,0,missing); } } void Generate::GenerateCommon(std::string& missing, const char *term, const char *start_comment, const char *end_comment) { int last_mat=-1; Output("glBegin(GL_TRIANGLES)%s\n",term); Output("\n"); for(int m=0;mnNumMeshes;m++) { msMesh *mesh=m_model->pMeshes+m; Output("%s Mesh %d - %s %s\n", start_comment,m+1,mesh->szName,end_comment); Output("\n"); if (mesh->nMaterialIndex<0) { missing+=mesh->szName; missing+="\n"; Output("glColor3f(1.0f,1.0f,1.0f)%s\n",term); last_mat=-1; } else { if (mesh->nMaterialIndex!=last_mat) { msMaterial *mat=m_model->pMaterials+mesh->nMaterialIndex; GenerateMaterial(mat,missing,term); last_mat=mesh->nMaterialIndex; } } for(int t=0;tnNumTriangles;t++) { msTriangle *tri; tri=mesh->pTriangles+t; if (!(tri->nFlags&eHidden)) { // To allow vertex order to be tweaked... // static int order[3]={0,1,2}; for(int i=0;i<3;i++) { msVertex *v=mesh->pVertices+tri->nVertexIndices[order[i]]; if (m_useTexture) { Output("glTexCoord2f(%f,%f)%s\n",v->u,v->v,term); } if (m_normals) { msVec3 n; msMesh_GetVertexNormalAt(mesh, tri->nNormalIndices[order[i]], n); Output("glNormal3f(%f,%f,%f)%s\n", n[0], n[1], n[2], term); } Output("glVertex3f(%f,%f,%f)%s\n", v->Vertex[0]-m_appcogx, v->Vertex[1]-m_appcogy, v->Vertex[2]-m_appcogz, term); } } } Output("\n"); } Output("glEnd()%s\n",term); } void Generate::GenerateMaterial(msMaterial *mat, std::string& missing, const char *term) { if (m_normals) { int f; for(f=0;f<4;f++) { Output("ambient[%d]=%f%s\n",f,mat->Ambient[f],term); Output("diffuse[%d]=%f%s\n",f,mat->Diffuse[f],term); Output("specular[%d]=%f%s\n",f,mat->Specular[f],term); Output("emission[%d]=%f%s\n",f,mat->Emissive[f],term); } Output("glMaterialf(GL_FRONT,GL_SHININESS,%f)%s\n", mat->fShininess,term); Output("glMaterialfv(GL_FRONT,GL_AMBIENT,ambient)%s\n",term); Output("glMaterialfv(GL_FRONT,GL_DIFFUSE,diffuse)%s\n",term); Output("glMaterialfv(GL_FRONT,GL_SPECULAR,specular)%s\n",term); Output("glMaterialfv(GL_FRONT,GL_EMISSION,emission)%s\n",term); } else { Output("glColor3f(%f,%f,%f)%s\n", mat->Diffuse[0], mat->Diffuse[1], mat->Diffuse[2], term); } } // END OF FILE