ObjMesh * ObjMeshOrientable::GenerateOrientedMesh() { ObjMesh * outputObjMesh = new ObjMesh(*objMesh); for(unsigned int i=0; i < outputObjMesh->getNumGroups(); i++) // over all groups { ObjMesh::Group * groupHandle = (ObjMesh::Group*) outputObjMesh->getGroupHandle(i); for (unsigned int j=0; j < groupHandle->getNumFaces(); j++) // over all faces { const ObjMesh::Face * face = groupHandle->getFaceHandle(j); if (face->getNumVertices() < 3) { printf("Warning: encountered a face with fewer than 3 vertices.\n"); continue; } HalfEdge edge = edgeAtFace(i, j); // loop until edge is first edge unsigned int startPosition = face->getVertex(0).getPositionIndex(); while (edgeStartVertex(edge).getPositionIndex() != startPosition) edge = edgeNext(edge); // reverse the face if not correctly oriented if (edgeEndVertex(edge).getPositionIndex() != face->getVertex(1).getPositionIndex()) groupHandle->reverseFace(j); } } return outputObjMesh; }
void World::SetupAnimalScene() { // Create the objects in the scene NxSoftBodyDesc softBodyDesc; softBodyDesc.globalPose.t = NxVec3(0.0f, 3.0f, 0.0f); softBodyDesc.particleRadius = 0.2f; softBodyDesc.volumeStiffness = 0.5f; softBodyDesc.stretchingStiffness= 1.0f; softBodyDesc.friction = 1.0f; softBodyDesc.attachmentResponseCoefficient = 0.1f; softBodyDesc.solverIterations = 5; char *fileName = "froggyNormalized"; char tetFileName[256], objFileName[256], s[256]; sprintf(tetFileName, "%s.tet", fileName); sprintf(objFileName, "%s.obj", fileName); ObjMesh *objMesh = new ObjMesh(); objMesh->loadFromObjFile(FindMediaFile(objFileName, s)); gObjMeshes.pushBack(objMesh); if(objMesh == NULL) { printf("objMesh %s\n"); } NxMat33 rot; rot.rotX(NxHalfPiF32); for (int i = 0; i < 5; i++) { softBodyDesc.globalPose.t = NxVec3(0, 3+i*3, 0); MySoftBody *softBody = new MySoftBody(gScene, softBodyDesc, FindMediaFile(tetFileName, s), objMesh); assert(softBody); if (!softBody->getNxSoftBody()) { printf("Error: unable to create the softbody for the current scene.\n"); delete softBody; } else { gSoftBodies.pushBack(softBody); NxActor *caps = MyCreateCapsule(NxVec3(0.0f, 3.0f + i*3.0f, -0.3f), 1.0f, 0.73f, 1.0f); caps->userData = (void*)&gInvisible; caps->setGlobalOrientation(rot); softBody->getNxSoftBody()->attachToShape(caps->getShapes()[0], NX_SOFTBODY_ATTACHMENT_TWOWAY); } } }
void Mesh::loadOBJ(const std::string& filename) { ObjMesh* pRawObjMesh = ObjMesh::LoadFromFile(filename); if (!pRawObjMesh) { std::cerr << "Mesh::loadObj: error loading file " << filename << "." << std::endl; return; } // Makes sure we have an indexed face set ObjMesh* pObjMesh = pRawObjMesh->createIndexedFaceSet(Obj::Options(Obj::AllAttribs|Obj::Triangulate)); delete pRawObjMesh; pRawObjMesh = 0; // copy vertices mVertices.resize(pObjMesh->positions.size()); for (int i=0 ; i<pObjMesh->positions.size() ; ++i) { mVertices[i] = Vertex(Vector3f(pObjMesh->positions[i])); if(!pObjMesh->texcoords.empty()) mVertices[i].texcoord = Vector2f(pObjMesh->texcoords[i]); if(!pObjMesh->normals.empty()) mVertices[i].normal = Vector3f(pObjMesh->normals[i]); } // copy faces for (int smi=0 ; smi<pObjMesh->getNofSubMeshes() ; ++smi) { const ObjSubMesh* pSrcSubMesh = pObjMesh->getSubMesh(smi); mFaces.reserve(pSrcSubMesh->getNofFaces()); for (uint fid = 0 ; fid<pSrcSubMesh->getNofFaces() ; ++fid) { ObjConstFaceHandle srcFace = pSrcSubMesh->getFace(fid); mFaces.push_back(Vector3i(srcFace.vPositionId(0), srcFace.vPositionId(1), srcFace.vPositionId(2))); } } if(pObjMesh->normals.empty()) { std::cout << "compute normals\n"; computeNormals(); } }
//ImplicitFuncMesh3DAccurate ImplicitFuncMesh3DAccurate::ImplicitFuncMesh3DAccurate(const ObjMesh& mesh,const scalar& cellSz,const BBox<scalar>& bb):_cellSz(cellSz) { const vector<Vec3,Eigen::aligned_allocator<Vec3> >& vv=mesh.getV(); const vector<Vec3i,Eigen::aligned_allocator<Vec3i> >& vi=mesh.getI(); const vector<Vec3,Eigen::aligned_allocator<Vec3> >& tnor=mesh.getTN(); const vector<Vec3,Eigen::aligned_allocator<Vec3> >& nor=mesh.getN(); _bb=bb; _mesh.reset(new MeshSLC()); //copy verts _mesh->_verts.resize(vv.size()); for(sizeType i=0; i<(sizeType)vv.size(); i++) _mesh->_verts[i]=Vec3SLC(vv[i].x(),vv[i].y(),vv[i].z()); //copy inds _mesh->_inds.resize(vi.size()); for(sizeType i=0; i<(sizeType)vi.size(); i++) _mesh->_inds[i]=Vec3i(vi[i].x(),vi[i].y(),vi[i].z()); //copy nors _mesh->_nors.resize(nor.size()); for(sizeType i=0; i<(sizeType)nor.size(); i++) _mesh->_nors[i]=Vec3SLC(nor[i].x(),nor[i].y(),nor[i].z()); //copy tnors _mesh->_tnors.resize(tnor.size()); for(sizeType i=0; i<(sizeType)tnor.size(); i++) _mesh->_tnors[i]=Vec3SLC(tnor[i].x(),tnor[i].y(),tnor[i].z()); _mesh->searchNeigh(); //initialize BVH _bvh.reset(new AABBvh(_mesh.get())); //initialize octree BBox<scalarD> bbD; bbD.copy(_bb); const Vec3SLC cellSzD(cellSz,cellSz,cellSz); sizeType level=0; { const sizeType maxCellDim=(sizeType)std::ceil(_bb.getExtent().maxCoeff()/cellSz); while((((sizeType)1)<<level) < maxCellDim) level++; } INFO("Building Distance Octree"); _octree.reset(new OctreeDistance(bbD,cellSzD,level,_helper)); if(!_octree->buildFromAABBvhTopDown(_bvh.get(),false)){ NOTIFY_MSG("Fail Building OctDistanceTree, Check Your Mesh!") } INFO("Built"); }
//ImplicitFuncMesh3D ImplicitFuncMesh3D::ImplicitFuncMesh3D(const ObjMesh& mesh,const scalar& cellSz,const BBox<scalar>& bb):_cellSz(cellSz) { const vector<Vec3,Eigen::aligned_allocator<Vec3> >& vv=mesh.getV(); const vector<Vec3i,Eigen::aligned_allocator<Vec3i> >& vi=mesh.getI(); _bb=bb; _mesh.reset(new MeshSLC()); //copy verts _mesh->_verts.resize(vv.size()); for(sizeType i=0; i<(sizeType)vv.size(); i++) _mesh->_verts[i]=Vec3SLC(vv[i].x(),vv[i].y(),vv[i].z()); //copy inds _mesh->_inds.resize(vi.size()); for(sizeType i=0; i<(sizeType)vi.size(); i++) _mesh->_inds[i]=Vec3i(vi[i].x(),vi[i].y(),vi[i].z()); //initialize BVH _bvh.reset(new AABBvh(_mesh.get())); }
void World::SetupBunnyScene() { NxSoftBodyDesc softBodyDesc; softBodyDesc.globalPose.t = NxVec3(0,35,-1); softBodyDesc.particleRadius = 0.2f; softBodyDesc.volumeStiffness = 1.0f; softBodyDesc.stretchingStiffness = 0.07f; softBodyDesc.friction = 1.0f; char *fileName = "bunny"; char tetFileName[256], objFileName[256], s[256]; sprintf(tetFileName, "%s.tet", fileName); sprintf(objFileName, "%s.obj", fileName); ObjMesh *objMesh = new ObjMesh(); // it is for mesh surface rendering objMesh->loadFromObjFile(FindMediaFile(objFileName, s)); MySoftBody *softBody = new MySoftBody(gScene, softBodyDesc, FindMediaFile(tetFileName,s), objMesh); if (!softBody->getNxSoftBody()) { printf("Error: Unable to create the SoftBody for the current scene.\n"); delete softBody; } else { gSoftBodies.push_back(softBody); // soft body is pushed to list. gObjMeshes.push_back(objMesh); // surface mesh is pushed to list. } NxMat33 rot; NxActor *plate0 = CreateBox(NxVec3(-2.5,10,0), NxVec3(20.0f, 1.0f, 10.0f), 0,0.0f); rot.rotZ(1.5f); plate0->setGlobalOrientation(rot); NxActor *plate1 = CreateBox(NxVec3(2.5,10,0), NxVec3(20.0f, 1.0f, 10.0f), 0,0.0f); rot.rotZ(1.5f); plate1->setGlobalOrientation(rot); // set camera position and direction gCameraPos.set(-5.0f, 40.0f, 35.0f); gCameraForward.set(0.2,-1.1,-2); gCameraForward.normalize(); }
//ImplicitFuncMesh2D ImplicitFuncMesh2D::ImplicitFuncMesh2D(const ObjMesh& mesh,const scalar& cellSz,const BBox<scalar>& bb):_cellSz(cellSz) { const vector<Vec3,Eigen::aligned_allocator<Vec3> >& vv=mesh.getV(); const vector<Vec3i,Eigen::aligned_allocator<Vec3i> >& vi=mesh.getI(); const BBoxf meshBB=mesh.getBB(); const scalarF ext=(scalarF)bb.getExtent().maxCoeff(); _bb=bb; _mesh.reset(new MeshSLC()); //copy verts _mesh->_verts.resize(vv.size()); for(sizeType i=0; i<(sizeType)vv.size(); i++) _mesh->_verts[i]=Vec3SLC(vv[i].x(),vv[i].y(),vv[i].z()); //copy inds _mesh->_inds.resize(vi.size()); for(sizeType i=0; i<(sizeType)vi.size(); i++) _mesh->_inds[i]=Vec3i(vi[i].x(),vi[i].y(),vi[i].z()); //initialize BVH _bvh.reset(new AABBvh(_mesh.get())); //copy to grid Vec3i nrCell=ceil((Vec3)(bb.getExtent()/cellSz)); BBox<scalar> bbLs(Vec3(bb._minC.x()-ext*0.1f,bb._minC.y()-ext*0.1f,0.0f), Vec3(bb._maxC.x()+ext*0.1f,bb._maxC.y()+ext*0.1f,0.0f)); _ls.reset(nrCell,bbLs,0.0f); for(sizeType x=0; x<nrCell.x(); x++) { //INFOV("X: %d",x) for(sizeType y=0; y<nrCell.y(); y++) { const Vec3 pos=_ls.getPt(Vec3i(x,y,0)); Vec3SLC a(pos.x(),pos.y(),pos.z()); a.z()=meshBB._minC.z()-cellSz; Vec3SLC b(pos.x(),pos.y(),pos.z()); b.z()=meshBB._maxC.z()+cellSz; _ls.get(Vec3i(x,y,0))=_bvh->intersectLineSeg3D(a,b,0) ? -_cellSz : _cellSz; } } GridOp<scalar,scalar>::reinitialize(_ls); GridOp<scalar,scalar>::write2DScalarGridVTK("./levelSet.vtk",_ls); }
void World::SetupPalmScene() { NxSoftBodyDesc softBodyDesc; softBodyDesc.globalPose.t = NxVec3(0,3,0); softBodyDesc.particleRadius = 0.2f; softBodyDesc.volumeStiffness = 0.5; softBodyDesc.stretchingStiffness = 1.0f; softBodyDesc.friction = 1.0f; softBodyDesc.flags |= NX_SBF_COLLISION_TWOWAY; char* fileName = "palm"; char tetFileName[256], objFileName[256], s[256]; //sprintf(tetFileName, "%s.tet", fileName); sprintf(objFileName, "%s.obj", fileName); ObjMesh *objMesh = new ObjMesh(); objMesh->loadFromObjFile(FindMediaFile(objFileName, s)); MySoftBody *softBody = new MySoftBody(gScene, softBodyDesc, FindMediaFile(tetFileName,s), objMesh); if (!softBody->getNxSoftBody()) { printf("Error: Unable to create the SoftBody for the current scene.\n"); delete softBody; } else { gSoftBodies.push_back(softBody); gObjMeshes.push_back(objMesh); softBody->getNxSoftBody()->setExternalAcceleration(NxVec3(5,0,0)); NxActor *caps0 = CreateCompoundCapsule(NxVec3(-0.46f, -0.15f, 0.68f), 1.7f, 0.21f, 2.0f, 0.18f); caps0->userData = (void*)&gInvisible; CreateRopeSphericalJoint(NULL, caps0, NxVec3(-0.46f, -0.0f, 0.68f), NxVec3(0,0,1)); softBody->getNxSoftBody()->attachToCollidingShapes(0); } }
int main( int argc, char** argv ) { if ( argc < 3 ) { std::cout << "Usage: " << argv[0] << " [volumetric mesh file] [output obj file] [-t]" << std::endl; std::cout << "Generates the surface mesh of the given volumetric mesh." << std::endl; std::cout << "-t: (this option only applies with cubic meshes) Triangulates each quad face. Default: faces are left as quads." << std::endl; return 1; } char * meshFile = argv[1]; char * outputFile = argv[2]; bool outputTriangleMesh = false; opt_t opttable[] = { { (char*)"t", OPTBOOL, &outputTriangleMesh }, { NULL, 0, NULL } }; argv += 1; argc -= 1; getopts(argc,argv,opttable); if (outputTriangleMesh) printf("Triangle mesh will be triangulated (if needed).\n"); VolumetricMesh * mesh = VolumetricMeshLoader::load(meshFile); GenerateSurfaceMesh generateSurfaceMesh; ObjMesh * objMesh = generateSurfaceMesh.ComputeMesh(mesh, outputTriangleMesh); objMesh->save(outputFile); return 0; }
void MeshAnimation::Part::Draw(const ObjMesh& mesh, double ticks, int tickCount) const { if (ticks > 1) ticks = ticks; double angle = ::Lerp(ticks, tickCount, angles); Vec3 offset = ::Lerp(ticks, tickCount, offsets); glPushMatrix(); GL::Translate(offset); GL::Translate(pivot); GL::Rotate(angle, axis); GL::Translate(-pivot); mesh.DrawObject(name); for (auto& part : parts) part.Draw(mesh, ticks, tickCount); glPopMatrix(); }
void World::SetupSoftWheelCarScene() { NxSoftBodyDesc softBodyDesc; softBodyDesc.particleRadius = 0.2f; softBodyDesc.volumeStiffness = 1.0f; softBodyDesc.stretchingStiffness = 1.0f; softBodyDesc.friction = 1.0f; softBodyDesc.attachmentResponseCoefficient = 0.8f; softBodyDesc.tearFactor = 10.1; // should be more than 1.0, the less, the easier to tear with flag NX_SBF_TEARABLE softBodyDesc.flags |= NX_SBF_HARDWARE | NX_SBF_VOLUME_CONSERVATION | NX_SBF_TEARABLE; char *fileName = "wheel"; char tetFileName[256], objFileName[256], s[256]; sprintf(tetFileName, "%s.tet", fileName); sprintf(objFileName, "%s.obj", fileName); MySoftBody *softBody; NxReal carHeight = 7.5f; NxReal stiffness = 0.9f; NxMat34 capsulePose = NxMat34(NxMat33(NX_IDENTITY_MATRIX), NxVec3(-4, carHeight, -5.0f)); printf("capsulePose %f %f %f\n", capsulePose.t.x, capsulePose.t.y, capsulePose.t.z); capsulePose.M.rotX(NxHalfPiF32); NxActor *caps1 = CreateOrientedCapsule(capsulePose, 7.1f, 1.3f, 1.0f); capsulePose.t = NxVec3(4, carHeight, -5.0f); NxActor *caps2 = CreateOrientedCapsule(capsulePose, 7.1f, 1.3f, 1.0f); ObjMesh *objMesh = new ObjMesh(); objMesh->loadFromObjFile(FindMediaFile(objFileName, s)); NxMat33 rot; rot.rotX(NxPiF32); softBodyDesc.globalPose.t = NxVec3(4.0f, carHeight, 3.4f); softBodyDesc.globalPose.M = rot; softBodyDesc.stretchingStiffness = stiffness; softBody = new MySoftBody(gScene, softBodyDesc, FindMediaFile(tetFileName,s), objMesh); if (!softBody->getNxSoftBody()) { printf("Error: Unable to create Softbody for the current scene.\n"); delete softBody; } else { gObjMeshes.push_back(objMesh); // wheel 1 softBody->getNxSoftBody()->attachToCollidingShapes(NX_SOFTBODY_ATTACHMENT_TWOWAY); gSoftBodies.push_back(softBody); softBodyDesc.globalPose.t = NxVec3(-4.0f ,carHeight, 3.4f); softBodyDesc.globalPose.M = rot; softBodyDesc.stretchingStiffness = stiffness; softBody = new MySoftBody(gScene, softBodyDesc, FindMediaFile(tetFileName,s), objMesh); softBody->getNxSoftBody()->attachToCollidingShapes(NX_SOFTBODY_ATTACHMENT_TWOWAY); gSoftBodies.push_back(softBody); softBodyDesc.globalPose.t = NxVec3(4.0f, carHeight, -3.4f); softBodyDesc.globalPose.M.id(); softBodyDesc.stretchingStiffness = stiffness; softBody = new MySoftBody(gScene, softBodyDesc, FindMediaFile(tetFileName,s), objMesh); softBody->getNxSoftBody()->attachToCollidingShapes(NX_SOFTBODY_ATTACHMENT_TWOWAY); gSoftBodies.push_back(softBody); softBodyDesc.globalPose.t = NxVec3(-4.0f, carHeight, -3.4f); softBodyDesc.globalPose.M.id(); softBodyDesc.stretchingStiffness = stiffness; softBody = new MySoftBody(gScene, softBodyDesc, FindMediaFile(tetFileName,s), objMesh); softBody->getNxSoftBody()->attachToCollidingShapes(NX_SOFTBODY_ATTACHMENT_TWOWAY); // bind soft wheel with capsule colliding with it gSoftBodies.push_back(softBody); NxActor *box = CreateBox(NxVec3(0,carHeight,0), NxVec3(4.6f, 0.5f, 1.0f), 0,1.0f); CreateRevoluteJoint(box, caps1, NxVec3(-4,carHeight,-3.5f), NxVec3(0,0,1), false); CreateRevoluteJoint(box, caps2, NxVec3( 4,carHeight,-3.5f), NxVec3(0,0,1), false); } gSelectedActor = caps1; }
bool LoadFromObjMesh(const std::string& path, RenderDevice* device, TextureManager* texManater, Matrix4x4 posMatrix, Matrix4x4 texcoordMatrix, std::vector<Primitive* >& primList) { ObjMesh objMesh; bool success = objMesh.Load(path); std::string folderPath = PathRemoveFileName(objMesh.path); for(size_t i = 0; i < objMesh.geomList.size(); i++) { std::vector<ObjMesh::FusedVertex> vertices; std::vector<int> indices; objMesh.CreateVertexIndexBuffer(i, vertices, indices); for(size_t v = 0; v < vertices.size(); v++) { Vector4 pos = posMatrix * Vector4(vertices[v].position.x, vertices[v].position.y, vertices[v].position.z, 1.f); vertices[v].position = Vector3(pos.x, pos.y, pos.z); Vector4 normal = posMatrix * Vector4(vertices[v].normal.x, vertices[v].normal.y, vertices[v].normal.z, 1.f); vertices[v].normal = Vector3(normal.x, normal.y, normal.z); Vector4 texcoord(vertices[v].texcoord.x, vertices[v].texcoord.y, 0.f, 1.f); texcoord = texcoordMatrix * texcoord; vertices[v].texcoord.x = texcoord.x; vertices[v].texcoord.y = texcoord.y; } HWVertexBuffer* vertexBuffer; HWIndexBuffer* indexBuffer; device->CreateVertexBuffer(sizeof(ObjMesh::FusedVertex) * vertices.size(), &vertices[0], &vertexBuffer); device->CreateIndexBuffer(sizeof(int) * indices.size(), &indices[0], &indexBuffer); Mesh* mesh = new Mesh(); mesh->vertexBuffer = vertexBuffer; mesh->indexBuffer = indexBuffer; mesh->numVertices = vertices.size(); mesh->numIndices = indices.size(); mesh->positionList = new Vector3[vertices.size()]; mesh->normalList = new Vector3[vertices.size()]; mesh->texcoordList = new Vector2[vertices.size()]; mesh->vertices = new VertexP3N3T2[vertices.size()]; for(size_t v = 0; v < vertices.size(); v++) { mesh->vertices[v].position = mesh->positionList[v] = vertices[v].position; mesh->vertices[v].normal = mesh->normalList[v] = vertices[v].normal; mesh->vertices[v].texcoord = mesh->texcoordList[v] = vertices[v].texcoord; } Primitive* prim = new Primitive(); Material* material = new Material(); ObjMesh::Material& mat = objMesh.matList[objMesh.geomList[i].matIndex]; material->ambient = mat.ka; material->diffuse = mat.kd; material->specular = mat.ks; material->roughness = mat.ns; if(!mat.mapKd.empty()) material->diffuseMap = texManater->Load(folderPath + "\\" + mat.mapKd ); if(!mat.mapKs.empty() ) material->specularMap = texManater->Load(folderPath + "\\" + mat.mapKs ); if(!mat.mapBump.empty()) material->normalMap = texManater->Load(folderPath + "\\" + mat.mapBump); if(!mat.mapD.empty()) material->dissolveMask = texManater->Load(folderPath + "\\" + mat.mapD); prim->mesh = mesh; prim->material = material; primList.push_back(prim); } return success; }
/* Pour chaque objet, construire une liste unique de sommets et de triangles, récupérer le matériau et appeler un callback pour mettre l'objet dans la scène. */ void ObjLoader::getObjects (std::vector<loaders::Mesh *> &meshes) { { // add geometries for (std::map<std::string, Group *>::iterator group = allgroups.begin(); group != allgroups.end(); ++group) { Group *theGroup = group->second; if (!theGroup->empty) { ObjMesh *theMesh; theMesh = new ObjMesh (theGroup->name); for (std::map<int, FaceList>::iterator sg = theGroup->faces.begin(); sg != theGroup->faces.end(); ++sg) { std::vector<Face *>::iterator it = sg->second.begin(); if (it != sg->second.end()) { // le groupe n'est pas vide ! int type = faceType (*it); switch (type) { case 0: // group with complete faces if (sg->first == 0) { // pas de lissage sur ce smoothgroup // ajout des sommets sans reorganisation addRawVerticeNormalTexturePart (theMesh, sg->second, sg->first); } else { addVerticeNormalTexturePart (theMesh, sg->second, sg->first); } break; case 1: // groupe avec faces vertex+normales if (sg->first == 0) { // pas de lissage sur ce smoothgroup // ajout des sommets sans reorganisation addRawVerticeNormalPart (theMesh, sg->second, sg->first); } else { addVerticeNormalPart (theMesh, sg->second, sg->first); } break; case 2: // groupe avec faces vertex+textures if (sg->first == 0) { // pas de lissage sur ce smoothgroup // ajout des sommets sans reorganisation addRawVerticeTexturePart (theMesh, sg->second, sg->first); } else { addVerticeTexturePart (theMesh, sg->second, sg->first); } break; case 3: // groupe avec faces vertex uniquement if (sg->first == 0) { // pas de lissage sur ce smoothgroup // ajout des sommets sans reorganisation addRawVerticePart (theMesh, sg->second, sg->first); } else { addVerticePart (theMesh, sg->second, sg->first); } break; default : std::cerr << "Cas normalement impossible !" << std::endl; } } } meshes.push_back( theMesh->compile() ); delete theMesh; } delete theGroup; } } }
bool ofxOBJModel::load(string path) { bHasNormals = false; bHasTexCoords = false; filePath = path; path = ofToDataPath(path, true); string line; for(int i = 0; i < meshes.size(); i++) { delete meshes[i]; } meshes.clear(); ObjMesh *currMesh = NULL; // this is a list of all points // that we can drop after parsing vector<ofPoint> points; vector<ofPoint> normals; vector<ofPoint> texCoords; // obj file format vertexes are 1-indexed points.push_back(ofPoint()); normals.push_back(ofPoint()); texCoords.push_back(ofPoint()); ifstream myfile (path.c_str()); if (myfile.is_open()) { while (! myfile.eof()) { getline (myfile,line); // parse the obj format here. // // the only things we're interested in is // lines beginning with 'g' - this says start of new object // lines beginning with 'v ' - coordinate of a vertex // lines beginning with 'vn ' - vertex normals -- todo // lines beginning with 'vt ' - texcoords (either 2 or 3 values) -- todo // lines beginning with 'f ' - specifies a face of a shape // we take each number before the slash as the index // of the vertex to join up to create a face. if(line.find("g ")==0) { // new object definition currMesh = new ObjMesh(line.substr(2)); meshes.push_back(currMesh); } else if(line.find("v ")==0) { // new vertex points.push_back(parseCoords(line)); } else if(line.find("vn ")==0) { bHasNormals = true; normals.push_back(parseCoords(line)); } else if(line.find("vt ")==0) { bHasTexCoords = true; texCoords.push_back(parseCoords(line)); } else if(line.find("f ")==0) { // face definition if(currMesh!=NULL) { line = line.substr(2); // lop off "f " vector<string> indices = split(line, ' '); // remove any texcoords (/xxx's) ObjFace *face = new ObjFace(); for(int i = 0; i < indices.size(); i++) { vector<string> parts = ofSplitString(indices[i], "/"); // first index is always a point face->points.push_back(points[atoi(parts[0].c_str())]); if(parts.size()==2) { face->texCoords.push_back(texCoords[atoi(parts[1].c_str())]); } else if(parts.size()==3) { face->normals.push_back(normals[atoi(parts[2].c_str())]); if(parts[1]!="") { face->texCoords.push_back(texCoords[atoi(parts[1].c_str())]); } } } currMesh->addFace(face); } } } myfile.close(); //#define NORMALIZE_TEXCOORDS #ifdef NORMALIZE_TEXCOORDS ofPoint pmin(FLT_MAX, FLT_MAX); ofPoint pmax(FLT_MIN, FLT_MIN); for(int i = 0; i < texCoords.size(); i++) { if(texCoords[i].x<pmin.x) pmin.x = texCoords[i].x; if(texCoords[i].y<pmin.y) pmin.y = texCoords[i].y; if(texCoords[i].x>pmax.x) pmax.x = texCoords[i].x; if(texCoords[i].y>pmax.y) pmax.y = texCoords[i].y; } for(int k = 0; k < meshes.size(); k++) for(int i = 0; i < meshes[k]->faces.size(); i++) for(int j = 0; j < meshes[k]->faces[i]->texCoords.size(); j++) { ofPoint p = meshes[k]->faces[i]->texCoords[j]; p.x = ofMap(p.x, pmin.x, pmax.x, 0, 1); p.y = ofMap(p.y, pmin.y, pmax.y, 0, 1); meshes[k]->faces[i]->texCoords[j] = p; } #endif loadVbo(); ofLog(OF_LOG_NOTICE, "Successfully loaded %s\n-----\nVertices: %d\nMeshes: %d\nNormals: %d\nTexCoords: %d\n", path.c_str(), points.size(), meshes.size(), normals.size(), texCoords.size()); return true; } else { ofLog(OF_LOG_ERROR, "Couldn't find the OBJ file %s\n", path.c_str()); return false; } }
bool ofxOBJModel::load(string path) { filePath = path; path = ofToDataPath(path, true); string line; for(int i = 0; i < meshes.size(); i++) { delete meshes[i]; } meshes.clear(); ObjMesh *currMesh = NULL; // this is a list of all points // that we can drop after parsing vector<ofPoint> points; // obj file format vertexes are 1-indexed points.push_back(ofPoint()); ifstream myfile (path.c_str()); if (myfile.is_open()) { while (! myfile.eof()) { getline (myfile,line); // parse the obj format here. // // the only things we're interested in is // lines beginning with 'g' - this says start of new object // lines beginning with 'v ' - coordinate of a vertex // lines beginning with 'f ' - specifies a face of a shape // we take each number before the slash as the index // of the vertex to join up to create a face. if(line.find("g ")==0) { // new object definition currMesh = new ObjMesh(line.substr(2)); meshes.push_back(currMesh); } else if(line.find("v ")==0) { // new vertex points.push_back(parseVertex(line)); } else if(line.find("f ")==0) { // face definition if(currMesh!=NULL) { line = line.substr(2); // lop off "f " vector<string> indices = split(line, ' '); // remove any texcoords (/xxx's) for(int i = 0; i < indices.size(); i++) { int slashPos = indices[i].find("/"); if(slashPos!=-1) { indices[i] = indices[i].substr(0, slashPos); } } ObjFace *face = new ObjFace(); for(int i = 0; i < indices.size(); i++) { face->points.push_back(points[atoi(indices[i].c_str())]); } currMesh->addFace(face); } } } myfile.close(); printf("Successfully loaded %s\n-----\nVertices: %d\nMeshes: %d\n", path.c_str(), points.size(), meshes.size()); return true; } else { printf("Couldn't find the OBJ file %s\n", path.c_str()); return false; } }
int main( int argc, char** argv ) { const int numFixedArguments = 3; if( argc < numFixedArguments ) { std::cout << "Merges several obj meshes into one. This routine uses the \"objMesh\" class to load the meshes. It can also merge materials." << std::endl; std::cout << "Usage: " << argv[0] << " [list of obj files] [output file] [-m]" << std::endl; std::cout << " -m : also output materials" << std::endl; std::cout << " -d : (if -m) also remove duplicate materials" << std::endl; return 1; } bool outputMaterials = false; bool removeDuplicatedMaterials = false; char * objListFilename = argv[1]; char * objMeshname = argv[2]; opt_t opttable[] = { { (char*)"m", OPTBOOL, &outputMaterials }, { (char*)"d", OPTBOOL, &removeDuplicatedMaterials }, { NULL, 0, NULL } }; argv += numFixedArguments-1; argc -= numFixedArguments-1; int optup = getopts(argc,argv,opttable); if (optup != argc) { printf("Error parsing options. Error at option %s.\n",argv[optup]); return 1; } ObjMesh outputObjMesh; char s[4096]; FILE * fin; char fileMode[96] = "r"; OpenFile_(objListFilename, &fin, fileMode); while(fgets(s,4096,fin) != 0) { if(s[strlen(s)-1] == '\n') s[strlen(s)-1] = '\0'; printf("%s\n",s); ObjMesh * objMesh = new ObjMesh(s); // add vertices int numVerticesCurrent = outputObjMesh.getNumVertices(); for(unsigned int i=0; i<objMesh->getNumVertices(); i++) outputObjMesh.addVertexPosition(objMesh->getPosition(i)); // add normals int numNormalsCurrent = outputObjMesh.getNumNormals(); for(unsigned int i=0; i<objMesh->getNumNormals(); i++) outputObjMesh.addVertexNormal(objMesh->getNormal(i)); // add texture coordinates int numTextureCoordinatesCurrent = outputObjMesh.getNumTextureCoordinates(); for(unsigned int i=0; i<objMesh->getNumTextureCoordinates(); i++) outputObjMesh.addTextureCoordinate(objMesh->getTextureCoordinate(i)); // add materials int numMaterialsCurrent = outputObjMesh.getNumMaterials(); for(unsigned int i=0; i<objMesh->getNumMaterials(); i++) outputObjMesh.addMaterial(objMesh->getMaterial(i)); for(unsigned int i=0; i<objMesh->getNumGroups(); i++) { const ObjMesh::Group * group = objMesh->getGroupHandle(i); outputObjMesh.addGroup(group->getName()); unsigned int newGroupID = outputObjMesh.getNumGroups() - 1; ObjMesh::Group * newGroup = (ObjMesh::Group*) outputObjMesh.getGroupHandle(newGroupID); newGroup->setMaterialIndex(numMaterialsCurrent + group->getMaterialIndex()); // over all faces in the group of the current obj file for(unsigned int j=0; j<group->getNumFaces(); j++) { const ObjMesh::Face * face = group->getFaceHandle(j); for(unsigned int k=0; k<face->getNumVertices(); k++) { ObjMesh::Vertex * vertex = (ObjMesh::Vertex*) face->getVertexHandle(k); vertex->setPositionIndex(vertex->getPositionIndex() + numVerticesCurrent); if (vertex->hasNormalIndex()) vertex->setNormalIndex(vertex->getNormalIndex() + numNormalsCurrent); if (vertex->hasTextureCoordinateIndex()) vertex->setTextureCoordinateIndex(vertex->getTextureCoordinateIndex() + numTextureCoordinatesCurrent); } outputObjMesh.addFaceToGroup(*face,newGroupID); } } delete(objMesh); } fclose(fin); if (outputMaterials) { if (removeDuplicatedMaterials) { printf("Removing duplicated materials..."); fflush(NULL); int numNewMaterials = outputObjMesh.removeDuplicatedMaterials(); printf(" retained %d materials.\n", numNewMaterials); } outputObjMesh.save(objMeshname, 1); } else { outputObjMesh.save(objMeshname); } return(0); }
int main(int argc, char ** argv) { if (argc < 4) { printf("Generates an interpolant between a given volumetric mesh and a surface obj mesh.\n"); printf("Usage: %s <volumetric mesh file> <target obj file> <output interpolant file> [-s volumetric mesh element list output filename] [-z threshold] [-S] [-T]\n",argv[0]); printf("-s : output list of (1-indexed) volumetric mesh elements that contain at least one obj mesh vertex\n"); printf("-z : assign zero interpolation to vertices too far away from the volumetric mesh\n"); return 0; } char * meshFile = argv[1]; char * objMeshname = argv[2]; char * outputFilename = argv[3]; char outputElementFilename[4096] = "__none"; char zeroThresholdString[4096] = "__none"; opt_t opttable[] = { { (char*)"s", OPTSTR, &outputElementFilename }, { (char*)"z", OPTSTR, &zeroThresholdString }, { NULL, 0, NULL } }; argv += 3; argc -= 3; int optup = getopts(argc,argv,opttable); if (optup != argc) { printf("Error parsing options. Error at option %s.\n",argv[optup]); return 1; } double threshold; if (strcmp(zeroThresholdString,"__none") == 0) threshold = -1; else threshold = strtod(zeroThresholdString, NULL); VolumetricMesh * volumetricMesh = VolumetricMeshLoader::load(meshFile); if (volumetricMesh == NULL) { printf("Error: unable to load the volumetric mesh from %s.\n", meshFile); exit(1); } int n = volumetricMesh->getNumVertices(); int nel = volumetricMesh->getNumElements(); printf("Info on %s:\n", meshFile); printf("Num vertices: %d\n", n); printf("Num elements: %d\n", nel); ObjMesh * objMesh = new ObjMesh(objMeshname); int numInterpolationLocations = objMesh->getNumVertices(); double * interpolationLocations = (double*) malloc (sizeof(double) * 3 * numInterpolationLocations); for(int i=0; i< numInterpolationLocations; i++) { Vec3d pos = objMesh->getPosition(i); interpolationLocations[3*i+0] = pos[0]; interpolationLocations[3*i+1] = pos[1]; interpolationLocations[3*i+2] = pos[2]; } int * vertices; double * weights; int * elementList; int ** elementListp = NULL; if (strcmp(outputElementFilename, "__none") != 0) { elementListp = &elementList; } int verbose = 1; int numExternalVertices; numExternalVertices = volumetricMesh->generateInterpolationWeights(numInterpolationLocations, interpolationLocations, &vertices, &weights, threshold, elementListp, verbose); printf("Saving weights to %s...\n", outputFilename); fflush(NULL); volumetricMesh->saveInterpolationWeights(outputFilename, numInterpolationLocations, volumetricMesh->getNumElementVertices(), vertices, weights); if (strcmp(outputElementFilename, "__none") != 0) { set<int> uniqueElementSet; for(unsigned int i=0; i<numInterpolationLocations; i++) uniqueElementSet.insert(elementList[i]); vector<int> uniqueElementList; for(set<int>::iterator iter = uniqueElementSet.begin(); iter != uniqueElementSet.end(); iter++) uniqueElementList.push_back(*iter); LoadList saveList; sort(uniqueElementList.begin(), uniqueElementList.end()); int oneIndexed = 1; saveList.save(outputElementFilename, uniqueElementList.size(), &uniqueElementList[0], oneIndexed); } printf("\n"); return 0; }