Scene& GlassModelExample::createScene(Scene& scene, const double aspectRatio) { scene = createMaterials(scene); std::cout << "Creating scene..." << std::endl; Background* background = new GradientBackground(Color(1, 1, 1), Color(0.0, 0.0, 0.0)); scene.setBackground(background); Transform Tcam = Transform::Translate(0,-3,2) * Transform::RotateXdeg(80); Camera* camera = new PinholeCamera(aspectRatio); SimpleCameraMount* mount = new SimpleCameraMount(Tcam, camera); scene.setCameraMount(mount); scene.addElement(new Object(Transform::Translate(0,0,-1), GeoPtr(new Plane()), "white")); TriangleMesh *mesh = LoadASC("nudobult.asc", 0.02); if (mesh) { GeoPtr pMesh(mesh); scene.addElement(new Object(Transform::Translate(0,4,0.5) *Transform::RotateZdeg(15), pMesh, "glass")); } SkyLight* skyLight = new SkyLight(0.5, Color(0.800, 0.930, 1)); skyLight->setSampling(4,16,0.05); scene.addElement(skyLight); SphereAreaLight *areaLight = NULL; areaLight = new SphereAreaLight(Transform::Translate(-6,-2,7),1.0, Color(0.8,0.7,0.6), 1, true, SphereAreaLight::ATT_NONE); areaLight->setSampling(4,16); scene.addElement(areaLight); return scene; }
int main(int argc, char *argv[]) { # include "setRootCase.H" # include "createTime.H" # include "createMesh.H" pointMesh pMesh(mesh); pointVectorField U ( IOobject ( "U", runTime.timeName(), mesh, IOobject::NO_READ, IOobject::AUTO_WRITE ), pMesh, dimensionedVector("fvmU", dimLength, vector::zero), pointPatchVectorField::calculatedType() ); pointVectorField V(U + 2*U); Info<< "End\n" << endl; return 0; }
void LoadMeshes(FbxNode* pFbxNode, packed_freelist<Mesh>& sceneMeshes) { // Material const uint32_t materialCount = pFbxNode->GetMaterialCount(); for (uint32_t i = 0; i < materialCount; ++i) { FbxSurfaceMaterial* pFbxMaterial = pFbxNode->GetMaterial(i); if (pFbxMaterial && !pFbxMaterial->GetUserDataPtr()) { FbxAutoPtr<Material> pMaterial(new Material); if (pMaterial->init(pFbxMaterial)) { pFbxMaterial->SetUserDataPtr(pMaterial.Release()); } } } FbxNodeAttribute* nodeAttribute = pFbxNode->GetNodeAttribute(); if (nodeAttribute) { // Mesh if (nodeAttribute->GetAttributeType() == FbxNodeAttribute::eMesh) { FbxMesh* pFbxMesh = pFbxNode->GetMesh(); if (pFbxMesh && !pFbxMesh->GetUserDataPtr()) { Mesh mesh; if (mesh.init(pFbxMesh)) { sceneMeshes.insert(mesh); } // TODO: FbxAutoPtr<Mesh> pMesh(new Mesh); if (pMesh->init(pFbxMesh)) { pFbxMesh->SetUserDataPtr(pMesh.Release()); } } } // Light else if (nodeAttribute->GetAttributeType() == FbxNodeAttribute::eLight) { FbxLight* pFbxLight = pFbxNode->GetLight(); if (pFbxLight && !pFbxLight->GetUserDataPtr()) { FbxAutoPtr<Light> pLight(new Light); if (pLight->init(pFbxLight)) { pFbxLight->SetUserDataPtr(pLight.Release()); } } } } const int childCount = pFbxNode->GetChildCount(); for (int i = 0; i < childCount; ++i) { LoadMeshes(pFbxNode->GetChild(i), sceneMeshes); } }
MeshWeakPtr CMeshManager::CreateMesh(xst_castring& strName, const IInputLayout* pIL, xst_castring& strGroupName) { bool bCreated = true; ResourceWeakPtr pRes; { //XSTSimpleProfiler2( "--GetOrCreateResource" ); pRes = this->GetOrCreateResource( strName, strGroupName, &bCreated );//this->CreateResource( strName, strGroupName ); } if( pRes.IsNull() ) { return MeshWeakPtr(); } MeshWeakPtr pMesh( pRes ); pMesh->SetInputLayout( pIL ); if( !bCreated ) { return this->CloneMesh( pMesh, strGroupName ); } return pMesh; }
void Foam::Cloud<ParticleType>::calcCellWallFaces() const { cellWallFacesPtr_.reset(new PackedBoolList(pMesh().nCells(), false)); PackedBoolList& cellWallFaces = cellWallFacesPtr_(); const polyBoundaryMesh& patches = polyMesh_.boundaryMesh(); forAll(patches, patchi) { if (isA<wallPolyPatch>(patches[patchi])) { const polyPatch& patch = patches[patchi]; const labelList& pFaceCells = patch.faceCells(); forAll(pFaceCells, pFCI) { cellWallFaces[pFaceCells[pFCI]] = true; } } } }
MeshWeakPtr CMeshManager::CreateMesh(xst_castring& strName, GroupWeakPtr pGroup) { //XSTSimpleProfiler(); xst_assert( pGroup != xst_null, "(CMeshManager::CreateMesh)" ); bool bCreated = true; ResourceWeakPtr pRes; //{ XSTSimpleProfiler2( "CMeshManager: get or create resource" ); pRes = this->GetOrCreateResource( strName, pGroup, &bCreated ); //} if( pRes.IsNull() ) { return MeshWeakPtr(); } MeshWeakPtr pMesh( pRes ); if( !bCreated ) { return this->CloneMesh( pMesh ); } return pMesh; }
void starMesh::writeMesh() { if (isShapeMesh_) { Info<< "This is a shapeMesh." << endl; Info<< "Default patch type set to empty" << endl; clearExtraStorage(); polyMesh pShapeMesh ( IOobject ( polyMesh::defaultRegion, runTime_.constant(), runTime_ ), xferCopy(points_), // we could probably re-use the data cellShapes_, boundary_, patchNames_, patchTypes_, defaultFacesName_, defaultFacesType_, patchPhysicalTypes_ ); Info<< "Writing polyMesh" << endl; pShapeMesh.write(); } else { // This is a polyMesh. createPolyMeshData(); Info<< "This is a polyMesh" << endl; clearExtraStorage(); polyMesh pMesh ( IOobject ( polyMesh::defaultRegion, runTime_.constant(), runTime_ ), xferCopy(points_), // we could probably re-use the data xferCopy(meshFaces_), xferCopy(cellPolys_) ); // adding patches also checks the mesh pMesh.addPatches(polyBoundaryPatches(pMesh)); Info<< "Writing polyMesh" << endl; pMesh.write(); } }
void uniformInterpolatedDisplacementPointPatchVectorField::updateCoeffs() { if (this->updated()) { return; } if (!interpolatorPtr_.valid()) { interpolatorPtr_ = interpolationWeights::New ( interpolationScheme_, timeVals_ ); } const pointMesh& pMesh = this->dimensionedInternalField().mesh(); const Time& t = pMesh().time(); // Update indices of times and weights bool timesChanged = interpolatorPtr_->valueWeights ( t.timeOutputValue(), currentIndices_, currentWeights_ ); const wordList currentTimeNames ( UIndirectList<word>(timeNames_, currentIndices_) ); // Load if necessary fields for this interpolation if (timesChanged) { objectRegistry& fieldsCache = const_cast<objectRegistry&> ( pMesh.thisDb().subRegistry("fieldsCache", true) ); // Save old times so we now which ones have been loaded and need // 'correctBoundaryConditions'. Bit messy. HashSet<word> oldTimes(fieldsCache.toc()); ReadFields<pointVectorField> ( fieldName_, pMesh, currentTimeNames ); forAllConstIter(objectRegistry, fieldsCache, fieldsCacheIter) { if (!oldTimes.found(fieldsCacheIter.key())) { // Newly loaded fields. Make sure the internal // values are consistent with the boundary conditions. // This is quite often not the case since these // fields typically are constructed 'by hand' const objectRegistry& timeCache = dynamic_cast < const objectRegistry& >(*fieldsCacheIter()); pointVectorField& d = const_cast<pointVectorField&> ( timeCache.lookupObject<pointVectorField> ( fieldName_ ) ); d.correctBoundaryConditions(); } } } // Interpolate the whole field pointVectorField result ( uniformInterpolate<pointVectorField> ( IOobject ( word("uniformInterpolate(") + this->dimensionedInternalField().name() + ')', pMesh.time().timeName(), pMesh.thisDb(), IOobject::NO_READ, IOobject::AUTO_WRITE ), fieldName_, currentTimeNames, currentWeights_ ) ); // Extract back from the internal field this->operator== ( this->patchInternalField(result.dimensionedInternalField()) ); fixedValuePointPatchField<vector>::updateCoeffs(); }
int main ( int argc, char* argv[] ) { const bool verbose = false; const int procRank = 0; const int numProcs = 1; const OutputMessage::priority loggingLevel = OutputMessage::debugPriority; Logger* exeLog = Logger::Instance(loggingLevel, procRank, numProcs); const double maxR = 1.0; double nInv[7]; double interpMaxErr[7]; double interpAvgErr[7]; double gradMaxErr[7]; double gradAvgErr[7]; double lapMaxErr[7]; double lapAvgErr[7]; const int scalarDim = 1; const int vectorDim = 2; std::stringstream ss; std::string s; for ( int iNest = 1; iNest < 8; ++iNest ) { // // construct a mesh to use for testing // PolyMesh2d pMesh( iNest, PolyMesh2d::triHexSeed, maxR, procRank, numProcs); std::cout << "iNest = " << iNest << ", nParticles = " << pMesh.nParticles() << ", nFaces = " << pMesh.nFaces() << std::endl; if ( verbose ) { LongMessage meshStatus("planar mesh built", OutputMessage::tracePriority, "main", pMesh.getInfo() ); exeLog->logMessage(meshStatus); } nInv[iNest-1] = 1.0/pMesh.nFaces(); // // construct scalar field to use for testing // Field gaussScalar("Gaussian", "n/a", scalarDim, pMesh.nParticles() ); Field exactGradient( "grad Gaussian", "n/a", vectorDim, pMesh.nParticles() ); Field exactLaplacian( "laplacian Gaussian", "n/a", scalarDim, pMesh.nParticles() ); Particles* pp = pMesh.getParticles(); const double b = 8.0; for (int i = 0; i < pMesh.nParticles(); ++i) { double x = pp->x[i]; double y = pp->y[i]; double expPart = exp(- b*b * ( x*x + y*y ) ); gaussScalar.insertScalarToField( i, expPart ); exactGradient.insertVectorToField( i, -2.0 * b * b * x * expPart, - 2.0 * b * b * y * expPart ); exactLaplacian.insertScalarToField(i, 4.0 * b * b * expPart * (-1.0 + b*b * ( x*x + y*y )) ); } std::cout << "exact Fields defined... " << std::endl; ss.str(s); ss << "gaussScalar_nest_" << iNest << ".m"; gaussScalar.outputForMatlab( ss.str(), *pp ); std::cout << "source data output complete... " << std::endl; // // initialize interpolation // TriCubicHermite gaussScalarInterp( &pMesh, &gaussScalar); // // compute gradient estimates for Hermite interpolation, set interpolation coefficients // const double w1 = 2.0; const double w2 = 1.0; Field gaussGrad = gaussScalarInterp.estimateScalarGradientAtVertices(w1, w2); gaussScalarInterp.findAllCoefficientsScalar( gaussGrad ); std::cout << "interpolation coefficients set... " << std::endl; // // interpolate // Field interpolatedScalar("GaussInterp", "n/a", scalarDim, pMesh.nParticles() ); Field interpolatedGradient("GaussInterpGrad", "n/a", vectorDim, pMesh.nParticles() ); Field interpolatedLaplacian("GaussInterpLaplacian", "n/a", scalarDim, pMesh.nParticles() ); for ( int i = 0; i < pMesh.nParticles(); ++i) { xyzVector loc( pp->x[i], pp->y[i] ); interpolatedScalar.insertScalarToField( i, gaussScalarInterp.interpolateScalar( loc ) ); interpolatedGradient.insertVectorToField(i, gaussScalarInterp.scalarGradient( loc ) ); interpolatedLaplacian.insertScalarToField( i, gaussScalarInterp.scalarLaplacian( loc ) ); } std::cout << "interpolation complete... calculating error ..." << std::endl; Field interpError("interpolation error", "n/a", scalarDim, pMesh.nParticles() ); Field gradError( "gradient estimation error", "n/a", vectorDim, pMesh.nParticles() ); Field lapError("laplacian error", "n/a", scalarDim, pMesh.nParticles() ); interpMaxErr[iNest-1] = 0.0; interpAvgErr[iNest-1] = 0.0; gradMaxErr[iNest-1] = 0.0; gradAvgErr[iNest-1] = 0.0; lapMaxErr[iNest-1] = 0.0; lapAvgErr[iNest-1] = 0.0; double interpDenom = 0.0; double gradDenom = 0.0; double lapDenom = 0.0; double sMax = 0.0; double gMax = 0.0; double lMax = 0.0; for ( int i = 0; i < pMesh.nParticles(); ++i) { interpError.scalar[i] = interpolatedScalar.scalar[i] - gaussScalar.scalar[i]; double errI = std::abs(interpError.scalar[i]); interpAvgErr[iNest-1] += errI * errI * pp->area[i]; interpDenom += gaussScalar.scalar[i] * gaussScalar.scalar[i] * pp->area[i]; if ( gaussScalar.scalar[i] > sMax ) sMax = gaussScalar.scalar[i]; if ( errI > interpMaxErr[iNest-1] ) interpMaxErr[iNest-1] = errI; gradError.xComp[i] = interpolatedGradient.xComp[i] - exactGradient.xComp[i]; gradError.yComp[i] = interpolatedGradient.yComp[i] - exactGradient.yComp[i]; double errG = std::sqrt( gradError.xComp[i]*gradError.xComp[i] + gradError.yComp[i]*gradError.yComp[i] ); gradAvgErr[iNest-1] += errG * errG * pp->area[i]; gradDenom += ( exactGradient.xComp[i]*exactGradient.xComp[i] + exactGradient.yComp[i]*exactGradient.yComp[i]) * pp->area[i]; if ( std::sqrt( exactGradient.xComp[i]*exactGradient.xComp[i] + exactGradient.yComp[i]*exactGradient.yComp[i]) > gMax ) gMax = std::sqrt( exactGradient.xComp[i]*exactGradient.xComp[i] + exactGradient.yComp[i]*exactGradient.yComp[i]); if ( errG > gradMaxErr[iNest-1] ) gradMaxErr[iNest-1] = errG; lapError.scalar[i] = interpolatedLaplacian.scalar[i] - exactLaplacian.scalar[i]; double errL = std::abs( lapError.scalar[i] ); lapAvgErr[iNest-1] += errL * errL * pp->area[i]; lapDenom += exactLaplacian.scalar[i] * exactLaplacian.scalar[i] * pp->area[i]; if ( exactLaplacian.scalar[i] > lMax ) lMax = exactLaplacian.scalar[i]; if ( errL > lapMaxErr[iNest-1] ) lapMaxErr[iNest-1] = errL; } interpMaxErr[iNest-1] /= sMax; gradMaxErr[iNest-1] /= gMax; lapMaxErr[iNest-1] /= lMax; interpAvgErr[iNest-1] /= interpDenom; gradAvgErr[iNest-1] /= gradDenom; lapAvgErr[iNest-1] /= lapDenom; interpAvgErr[iNest-1] = std::sqrt( interpAvgErr[iNest-1] ); gradAvgErr[iNest-1] = std::sqrt( gradAvgErr[iNest-1] ); lapAvgErr[iNest-1] = std::sqrt( lapAvgErr[iNest-1] ); std::cout << "error complete ..." << std::endl; } std::cout << "--- 1/N --- " << " --- interp max err ---- " << " --- interp avg err ---- " << " --- grad max err --- " << " --- grad avg err --- " << " --- lap max err --- " << " --- lap avg err --- " << std::endl; for ( int i = 0; i < 7; ++i ) std::cout << nInv[i] << " , " << interpMaxErr[i] << " , " << interpAvgErr[i] << " , " << gradMaxErr[i] << " , " << gradAvgErr[i] << " , " << lapMaxErr[i] << " , " << lapAvgErr[i] << std::endl; return 0; };
int main(int argc, char ** argv) { //int numTargetSE; std::vector<int> numTargetByLayers; std::string numTargetByLayersStr; std::string catalog, indName, crdName, mtrName, levelBase; po::options_description desc("Program options"); bool verbouse = false; std::vector<double> maxImbalance; std::string maxImbalanceStr; desc.add_options() ("help,h", "print help message") ("num-se,n", po::value<std::string>(&numTargetByLayersStr)->default_value("16"), "target numbers of SE by layers i.e. '64,8,2'") ("work-dir,w", po::value<std::string>(&catalog)->default_value(""), "work catalog") ("ind-file,i", po::value<std::string>(&indName)->default_value("ind.sba"), "ind file") ("crd-file,c", po::value<std::string>(&crdName)->default_value("crd.sba"), "crd file") ("mtr-file,m", po::value<std::string>(&mtrName)->default_value("mtr001.sba"), "mtr file") ("level-base,l", po::value<std::string>(&levelBase)->default_value("level"), "level files base name") ("verbouse,v", "make verbouse output") ("max-imbalance", po::value<std::string>(&maxImbalanceStr)->default_value("1.3"), "target maximum imbalance in SE layers i.e. '1.4,1.3,1.3'. Low values of this parameters can couse program to fail.") ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); po::notify(vm); if (vm.count("help") || vm.count("h")) { std::cout << desc << "\n"; return 1; } if (vm.count("verbouse") || vm.count("v")) verbouse = true; //extract number of SE by layers from cmd string std::stringstream sstr(numTargetByLayersStr); std::string entry; while(getline(sstr, entry, ',')) numTargetByLayers.push_back(std::stoi(entry)); //extract max imbalance of SE by layers from cmd string { std::stringstream sstr(maxImbalanceStr); while(getline(sstr, entry, ',')) maxImbalance.push_back(std::stod(entry)); } std::stringstream iName, cName, mName, lName/*, oiName, ocName, omName*/; iName << catalog << indName; cName << catalog << crdName; mName << catalog << mtrName; lName << catalog << levelBase; //Creating mesh std::unique_ptr<sbfMesh> pMesh(new sbfMesh()); if(pMesh->readMeshFromFiles(iName.str().c_str(), cName.str().c_str(), mName.str().c_str())) {std::cout << "error while mesh reading" << std::endl; return 1;} int numElems = pMesh->numElements(); //Prepare zero level of SE - each SE contains only one regular element std::vector<int> regIndex; regIndex.resize(1); std::vector< std::vector<sbfSElement *> > selevels; selevels.resize(numTargetByLayers.size() + 1); selevels[0].reserve(numElems*10); for(int ct = 0; ct < numElems; ct++) selevels[0].push_back( new sbfSElement(pMesh.get(), ct)); for(size_t ct = 0; ct < numTargetByLayers.size(); ct++){ selevels[ct+1].reserve(numTargetByLayers[ct]*100); for(int ct1 = 0; ct1 < numTargetByLayers[ct]; ct1++) selevels[ct+1].push_back( new sbfSElement(pMesh.get(), ct1)); } for(int ct = 0; ct < numElems; ct++){ regIndex[0] = ct; selevels[0][ct]->setRegElemIndexes(regIndex); } generateLevels(selevels, numTargetByLayers, maxImbalance, verbouse); for(size_t ct = 0; ct < numTargetByLayers.size(); ct++){ std::cout << "Level " << ct+1 << " contains " << selevels[ct+1].size() << std::endl; sbfSELevel level; level.setSize(selevels[ct].size()); level.setLevelIndex(ct+1); for(size_t ctSE = 0; ctSE < selevels[ct].size(); ctSE++) level.setIndex(ctSE, selevels[ct][ctSE]->parent()->index()); level.writeToFile(lName.str().c_str(), ct+1); } std::cout << "DONE" << std::endl; return 0; }
////////////////////////////////////////////////////////////////////////// // buildBindPose void MD5MeshLoader::buildBindPose( MdlNode* pNode, BcU32 iMesh ) { // Skin the mesh. MD5_Joint* pJoints = pJoint( 0 ); MD5_Mesh* pMeshes = pMesh( iMesh ); // This node is a mesh if we have 1 joint, skin if we have more. MdlMesh* pMesh = NULL; if( nJoints_ == 1 ) { pNode->type( eNT_MESH ); pMesh = pNode->pMeshObject(); } else { pNode->type( eNT_SKIN ); pMesh = pNode->pSkinObject(); } // Add material. MdlMaterial Material; Material.default3d(); Material.Name_ = pMeshes->Shader_; BcU32 iMaterial = pMesh->addMaterial( Material ); // Add indices. for( BcU32 i = 0; i < pMeshes->nIndices_; ++i ) { MdlIndex Index; Index.iMaterial_ = iMaterial; Index.iVertex_ = pMeshes->pIndices_[ i ]; pMesh->addIndex( Index ); } BcVec3d WeightPos; for ( BcU32 i = 0; i < pMeshes->nVerts_; ++i ) { MD5_Vert* pMD5Vert = &pMeshes->pVerts_[ i ]; BcVec3d Position( 0.0f, 0.0f, 0.0f ); // Setup vertex. MdlVertex Vert; Vert.bUV_ = BcTrue; Vert.UV_.x( pMD5Vert->U_ ); Vert.UV_.y( pMD5Vert->V_ ); for ( BcU32 j = 0; j < 4; ++j ) { Vert.Weights_[ j ] = 0.0f; Vert.iJoints_[ j ] = 0; } // Get bind pose vertex. Vert.nWeights_ = 0; for ( BcU32 j = 0; j < pMD5Vert->nWeights_; ++j ) { if ( j > 4 ) { break; } BcU32 WeightIndex = pMD5Vert->WeightIndex_ + j; MD5_Weight* pMD5Weight = &pMeshes->pWeights_[ WeightIndex ]; // Fix up a joint. MD5_Joint* pJoint = &pJoints[ pMD5Weight->JointID_ ]; BcVec3d JointTran( pJoint->TX_, pJoint->TY_, pJoint->TZ_ ); BcQuat JointRot( pJoint->QX_, pJoint->QY_, pJoint->QZ_, 0.0f ); JointRot.calcFromXYZ(); // const BcReal WeightVal = pMD5Weight->Weight_; WeightPos.set( pMD5Weight->X_, pMD5Weight->Y_, pMD5Weight->Z_ ); JointRot.rotateVector( WeightPos ); Position += ( WeightPos + JointTran ) * WeightVal; // Setup vertex indices and weights: Vert.iJoints_[ j ] = pMD5Weight->JointID_; Vert.Weights_[ j ] = WeightVal; Vert.nWeights_++; } // Correct weights. BcReal WeightTotal = 0.0f; for( BcU32 j = 0; j < Vert.nWeights_; ++j ) { WeightTotal += Vert.Weights_[ j ]; } for( BcU32 j = 0; j < Vert.nWeights_; ++j ) { Vert.Weights_[ j ] = Vert.Weights_[ j ] / WeightTotal; } Vert.bPosition_ = BcTrue; Vert.Position_ = Position; pMesh->addVertex( Vert ); } pMesh->sortIndicesByMaterial(); pMesh->buildNormals(); pMesh->buildTangents(); // Setup AABB to be larger than the skin to account for motion. BcAABB AABB = pMesh->findAABB(); AABB.min( AABB.min() * 1.5f ); AABB.max( AABB.max() * 1.5f ); pNode->aabb( AABB ); // TODO: Refine into bone palettes properly. }
std::shared_ptr<Surface> LoadMesh(const char *file_name, float scale, const Vector3f& offset) { std::shared_ptr<Group> pMesh(new Group()); FILE *fp; errno_t err = fopen_s(&fp, file_name, "r"); char line[MESH_LINE_MAX]; char delims[] = " "; char *type = NULL; char *param1 = NULL; char *param2 = NULL; char *param3 = NULL; char *next = NULL; float minX = std::numeric_limits<float>::infinity(); float maxX = -std::numeric_limits<float>::infinity(); float minY = std::numeric_limits<float>::infinity(); float maxY = -std::numeric_limits<float>::infinity(); float minZ = std::numeric_limits<float>::infinity(); float maxZ = -std::numeric_limits<float>::infinity(); if (err == 0) { std::vector<Point3f> positionList; while (fgets(line, MESH_LINE_MAX, fp) != NULL) { if (strlen(line) == 0 || line[0] == '#') { continue; } type = strtok_s(line, delims, &next); param1 = strtok_s(NULL, delims, &next); param2 = strtok_s(NULL, delims, &next); param3 = strtok_s(NULL, delims, &next); if (strcmp(type, "v") == 0) { // A vertex float p1 = static_cast<float>(atof(param1)) * scale; float p2 = static_cast<float>(atof(param2)) * scale; float p3 = static_cast<float>(atof(param3)) * scale; p1 += offset.x; p2 += offset.y; p3 += offset.z; if (p1 < minX) minX = p1; if (p1 > maxX) maxX = p1; if (p2 < minY) minY = p2; if (p2 > maxY) maxY = p2; if (p3 < minZ) minZ = p3; if (p3 > maxZ) maxZ = p3; Point3f point(p1, p2, p3); positionList.push_back(point); } else if (strcmp(type, "f") == 0) { // A face std::string face_str_1(param1); std::string face_str_2(param2); std::string face_str_3(param3); int vertexIndex1 = GetVertexIndexFromString(face_str_1); int vertexIndex2 = GetVertexIndexFromString(face_str_2); int vertexIndex3 = GetVertexIndexFromString(face_str_3); std::shared_ptr<Triangle> tri(new Triangle(positionList[vertexIndex1], positionList[vertexIndex2], positionList[vertexIndex3])); pMesh->AddObject(tri); } else { // Just ignore. } } // End of the file has been reached. fclose(fp); } else { perror("Error opening the mesh file"); return nullptr; } Point3f center((minX + maxX) / 2.0f, (minY + maxY) / 2.0f, (minZ + maxZ) / 2.0f); float radius = (maxX - minX) > (maxY - minY) && (maxX - minX) > (maxZ - minZ) ? (maxX - minX) / 2.0f : (maxY - minY) > (maxZ - minZ) ? (maxY - minY) / 2.0f : (maxZ - minZ) / 2.0f; radius += 0.001f; pMesh->SetEnclosingSphere(center, radius); return pMesh; }