void ofxObjLoader::save(string path, ofMesh& mesh){ path = ofToDataPath(path); GLuint writeMode = GLM_NONE; GLMmodel* m = new GLMmodel(); if(mesh.getNumVertices() > 0){ m->numvertices = mesh.getNumVertices(); m->vertices = new GLfloat[m->numvertices*3+1]; memcpy(&m->vertices[3], &mesh.getVertices()[0].x, sizeof(ofVec3f) * mesh.getNumVertices()); } else { ofLogError("ofxObjLoader::save -- No vertices to save!"); return; } if(mesh.getNumNormals() > 0){ m->numnormals = mesh.getNumNormals(); m->normals = new GLfloat[m->numnormals*3+1]; memcpy(&m->normals[3], &mesh.getNormals()[0].x, sizeof(ofVec3f)*mesh.getNumNormals()); writeMode |= GLM_SMOOTH; } if(mesh.getNumTexCoords() > 0){ m->numtexcoords = mesh.getNumTexCoords(); m->texcoords = new GLfloat[m->numtexcoords*2+1]; memcpy(&m->texcoords[2], &mesh.getTexCoords()[0].x, sizeof(ofVec2f)*mesh.getNumTexCoords()); writeMode |= GLM_TEXTURE; } if(mesh.getNumIndices() > 0){ //create triangles m->numtriangles = mesh.getNumIndices()/3; m->triangles = new GLMtriangle[m->numtriangles]; //add them all to one group m->groups = new GLMgroup(); m->groups->next = NULL; m->groups->material = NULL; string name = "ofMesh"; m->groups->name = (char*)malloc(sizeof(char) * name.length()+1); strcpy(m->groups->name, name.c_str()); m->groups->numtriangles = mesh.getNumIndices()/3; m->groups->triangles = new GLuint[m->groups->numtriangles]; m->numgroups = 1; for(int i = 0; i < mesh.getNumIndices()/3; i++){ memcpy(m->triangles[i].vindices, &mesh.getIndices()[i*3], sizeof(GLuint)*3); memcpy(m->triangles[i].nindices, &mesh.getIndices()[i*3], sizeof(GLuint)*3); memcpy(m->triangles[i].tindices, &mesh.getIndices()[i*3], sizeof(GLuint)*3); m->groups->triangles[i] = i; } } glmWriteOBJ(m, (char*)path.c_str(), writeMode); glmDelete(m); }
void saveGroup(string path, const vector<ofMesh> & meshGroup, bool flipFace, bool flipNormals) { path = ofToDataPath(path); ofFilePath::createEnclosingDirectory(path); GLuint writeMode = GLM_NONE; GLMmodel * m = new GLMmodel(); GLMgroup * group = NULL; int numOfVerticesTotal = 0; int numOfNormalsTotal = 0; int numOfTexCoordsTotal = 0; int numOfIndicesTotal = 0; int numOfTrianglesTotal = 0; for(int i=0; i<meshGroup.size(); i++) { const ofMesh & mesh = meshGroup[i]; numOfVerticesTotal += mesh.getNumVertices(); numOfNormalsTotal += mesh.getNumNormals(); numOfTexCoordsTotal += mesh.getNumTexCoords(); if(mesh.getNumIndices() > 0) { numOfIndicesTotal += mesh.getNumIndices(); } else { numOfIndicesTotal += mesh.getNumVertices(); } } // glm skips the first array element when exporting. // not sure why? // but it means everything needs to be padded by 1. numOfVerticesTotal += 1; numOfNormalsTotal += 1; numOfTexCoordsTotal += 1; if(numOfVerticesTotal > 0) { m->numvertices = numOfVerticesTotal; m->vertices = new GLfloat[m->numvertices * 3]; } if(numOfNormalsTotal > 0) { m->numnormals = numOfNormalsTotal; m->normals = new GLfloat[m->numnormals * 3]; } if(numOfTexCoordsTotal > 0) { m->numtexcoords = numOfTexCoordsTotal; m->texcoords = new GLfloat[m->numtexcoords * 2]; } if(numOfIndicesTotal > 0) { numOfTrianglesTotal = numOfIndicesTotal / 3; m->numtriangles = numOfTrianglesTotal; m->triangles = new GLMtriangle[m->numtriangles]; } int numOfVertices = 0; int numOfNormals = 0; int numOfTexCoords = 0; int numOfIndices = 0; int numOfTriangles = 0; int indexVertices = 1; int indexNormals = 1; int indexTexCoords = 1; int indexIndices = 0; int indexTriangles = 0; for(int k=0; k<meshGroup.size(); k++) { const ofMesh & mesh = meshGroup[k]; if(numOfVerticesTotal > 0) { numOfVertices = mesh.getNumVertices(); memcpy(&m->vertices[indexVertices * 3], &mesh.getVertices()[0].x, sizeof(ofVec3f) * numOfVertices); indexVertices += numOfVertices; } else { ofLogError("ofxObjLoader::save -- No vertices to save!"); return; } if(numOfNormalsTotal > 0) { numOfNormals = mesh.getNumNormals(); vector<ofVec3f> normals = mesh.getNormals(); if(flipNormals) { for(int i = 0; i < normals.size(); i++) { normals[i] *= -1; } } memcpy(&m->normals[indexNormals * 3], &normals[0].x, sizeof(ofVec3f) * numOfNormals); indexNormals += numOfNormals; writeMode |= GLM_SMOOTH; } if(numOfTexCoordsTotal > 0) { numOfTexCoords = mesh.getNumTexCoords(); memcpy(&m->texcoords[indexTexCoords * 2], &mesh.getTexCoords()[0].x, sizeof(ofVec2f) * numOfTexCoords); indexTexCoords += numOfTexCoords; writeMode |= GLM_TEXTURE; } numOfIndices = mesh.getNumIndices(); if(numOfIndices > 0) { numOfTriangles = numOfIndices / 3; } else { numOfTriangles = numOfVertices / 3; } GLMgroup * groupPrev = group; group = new GLMgroup(); group->next = NULL; group->material = NULL; if(m->groups == NULL) { m->groups = group; m->numgroups = 1; } if(groupPrev != NULL) { groupPrev->next = group; m->numgroups += 1; } string name = "ofMesh_" + ofToString(k); group->name = (char*)malloc(sizeof(char) * name.length() + 1); strcpy(group->name, name.c_str()); group->numtriangles = numOfTriangles; group->triangles = new GLuint[group->numtriangles]; const vector<ofIndexType> & indices = mesh.getIndices(); int index = 0; for(int i=0; i<numOfTriangles; i++) { int t = i + indexTriangles; for(int j=0; j<3; j++) { int idx = i * 3 + j; if(numOfIndices > 0) { index = indices[idx]; } else { index = idx; } index += (indexIndices + 1); m->triangles[t].vindices[j] = index; m->triangles[t].nindices[j] = index; m->triangles[t].tindices[j] = index; } group->triangles[i] = t; } indexIndices += numOfVertices; indexTriangles += numOfTriangles; } if(flipFace == true) { glmReverseWinding(m); } glmWriteOBJ(m, (char*)path.c_str(), writeMode); glmDelete(m); }
void save(string path, const ofMesh& mesh_, const ofPixels& tex, string imgext) { ofMesh mesh = mesh_; path = ofToDataPath(path); ofFilePath::createEnclosingDirectory(path); GLuint writeMode = GLM_NONE; GLMmodel* m = new GLMmodel(); { ofFile file(path); string base_path = file.getEnclosingDirectory(); string material_name = file.getBaseName(); string image_name = material_name + "." + imgext; ofPixels pix = tex; // flip save texture pix.mirror(true, false); ofSaveImage(pix, ofFilePath::join(base_path, image_name)); string mtl_filename = material_name + ".mtl"; writeMode |= GLM_MATERIAL; m->mtllibname = (char*)malloc(mtl_filename.size()); strcpy(m->mtllibname, mtl_filename.c_str()); m->nummaterials = 1; m->materials = (GLMmaterial*)malloc(sizeof(GLMmaterial)); GLMmaterial *mat = &m->materials[0]; memset(mat, 0, sizeof(GLMmaterial)); for (int i = 0; i < 4; i++) { mat->diffuse[i] = 1; mat->ambient[i] = 1; mat->specular[i] = 1; mat->emmissive[i] = 1; } mat->shininess = 1; mat->name = (char*)malloc(material_name.size()); strcpy(mat->name, material_name.c_str()); mat->texture_path = (char*)malloc(image_name.size()); strcpy(mat->texture_path, image_name.c_str()); } if (mesh.getNumVertices() > 0) { m->numvertices = mesh.getNumVertices(); m->vertices = new GLfloat[(m->numvertices + 1) * 3]; memcpy(&m->vertices[3], &mesh.getVertices()[0].x, sizeof(ofVec3f) * mesh.getNumVertices()); } else { ofLogError("ofxObjLoader::save -- No vertices to save!"); return; } if (mesh.getNumNormals() > 0) { m->numnormals = mesh.getNumNormals(); m->normals = new GLfloat[(m->numnormals + 1) * 3]; vector<ofVec3f> normals = mesh.getNormals(); memcpy(&m->normals[3], &normals[0].x, sizeof(ofVec3f) * normals.size()); writeMode |= GLM_SMOOTH; } if (mesh.getNumTexCoords() > 0) { m->numtexcoords = mesh.getNumTexCoords(); m->texcoords = new GLfloat[(m->numtexcoords + 1) * 2]; memcpy(&m->texcoords[2], &mesh.getTexCoords()[0].x, sizeof(ofVec2f) * mesh.getNumTexCoords()); writeMode |= GLM_TEXTURE; } if (mesh.getNumIndices() > 0) { m->numtriangles = mesh.getNumIndices() / 3; m->triangles = new GLMtriangle[m->numtriangles]; m->groups = new GLMgroup(); m->groups->next = NULL; m->groups->material = NULL; string name = "ofMesh"; m->groups->name = (char*)malloc(sizeof(char) * name.length() + 1); strcpy(m->groups->name, name.c_str()); m->groups->numtriangles = mesh.getNumIndices() / 3; m->groups->triangles = new GLuint[m->groups->numtriangles]; m->numgroups = 1; for (int i = 0; i < mesh.getNumIndices(); i += 3) { int idx = i / 3; for (int j = 0; j < 3; j++) { m->triangles[idx].vindices[j] = mesh.getIndices()[i + j] + 1; m->triangles[idx].nindices[j] = mesh.getIndices()[i + j] + 1; m->triangles[idx].tindices[j] = mesh.getIndices()[i + j] + 1; } m->groups->triangles[idx] = idx; } } else { m->numtriangles = mesh.getNumVertices() / 3; m->triangles = new GLMtriangle[m->numtriangles]; m->groups = new GLMgroup(); m->groups->next = NULL; m->groups->material = NULL; string name = "ofMesh"; m->groups->name = (char*)malloc(sizeof(char) * name.length() + 1); strcpy(m->groups->name, name.c_str()); m->groups->numtriangles = mesh.getNumVertices() / 3; m->groups->triangles = new GLuint[m->groups->numtriangles]; m->numgroups = 1; for (int i = 0; i < mesh.getNumVertices(); i += 3) { int idx = i / 3; for (int j = 0; j < 3; j++) { m->triangles[idx].vindices[j] = i + j + 1; m->triangles[idx].nindices[j] = i + j + 1; m->triangles[idx].tindices[j] = i + j + 1; } m->groups->triangles[idx] = idx; } } glmWriteOBJ(m, (char*)path.c_str(), writeMode); glmDelete(m); }
void keyboard(unsigned char key, int x, int y) { GLint params[2]; switch (key) { case 'h': printf("help\n\n"); printf("w - Toggle wireframe/filled\n"); printf("c - Toggle culling\n"); printf("n - Toggle facet/smooth normal\n"); printf("b - Toggle bounding box\n"); printf("r - Reverse polygon winding\n"); printf("m - Toggle color/material/none mode\n"); printf("p - Toggle performance indicator\n"); printf("s/S - Scale model smaller/larger\n"); printf("t - Show model stats\n"); printf("o - Weld vertices in model\n"); printf("+/- - Increase/decrease smoothing angle\n"); printf("W - Write model to file (out.obj)\n"); printf("q/escape - Quit\n\n"); break; case 't': stats = !stats; break; case 'p': performance = !performance; break; case 'm': material_mode++; if (material_mode > 2) material_mode = 0; printf("material_mode = %d\n", material_mode); lists(); break; case 'd': glmDelete(model); init(); lists(); break; case 'w': glGetIntegerv(GL_POLYGON_MODE, params); if (params[0] == GL_FILL) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); else glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break; case 'c': if (glIsEnabled(GL_CULL_FACE)) glDisable(GL_CULL_FACE); else glEnable(GL_CULL_FACE); break; case 'b': bounding_box = !bounding_box; break; case 'n': facet_normal = !facet_normal; lists(); break; case 'r': glmReverseWinding(model); lists(); break; case 's': glmScale(model, 0.8); lists(); break; case 'S': glmScale(model, 1.25); lists(); break; case 'o': //printf("Welded %d\n", glmWeld(model, weld_distance)); glmVertexNormals(model, smoothing_angle); lists(); break; case 'O': weld_distance += 0.01; printf("Weld distance: %.2f\n", weld_distance); glmWeld(model, weld_distance); glmFacetNormals(model); glmVertexNormals(model, smoothing_angle); lists(); break; case '-': smoothing_angle -= 1.0; printf("Smoothing angle: %.1f\n", smoothing_angle); glmVertexNormals(model, smoothing_angle); lists(); break; case '+': smoothing_angle += 1.0; printf("Smoothing angle: %.1f\n", smoothing_angle); glmVertexNormals(model, smoothing_angle); lists(); break; case 'W': glmScale(model, 1.0/scale); glmWriteOBJ(model, "out.obj", GLM_SMOOTH | GLM_MATERIAL); break; case 'R': { GLuint i; GLfloat swap; for (i = 1; i <= model->numvertices; i++) { swap = model->vertices[3 * i + 1]; model->vertices[3 * i + 1] = model->vertices[3 * i + 2]; model->vertices[3 * i + 2] = -swap; } glmFacetNormals(model); lists(); break; } case 27: exit(0); break; } glutPostRedisplay(); }