void ObjGPUData::loadObject(const char* fileName) { std::string folderName = fileName; for(int i = folderName.size() - 1; i >= 0; i--) { if(folderName[i] == '/' || folderName[i] == '\\') { folderName = folderName.substr(0, i+1); break; } if(i == 0) folderName = ""; } std::string objFileName = fileName; std::string mtlFileName = fileName; objFileName += ".obj"; mtlFileName += ".mtl"; std::ifstream mtlFile(mtlFileName.c_str(), std::ios::in); if(!mtlFile.is_open()) { printf("Failed to open object %s\n", objFileName.c_str()); exit(1); } std::string dataTypeString; float xVal, yVal, zVal; std::string valString; std::stringstream valStream; int iVal; while(mtlFile >> dataTypeString) { mtlDataType mtlDataTypeVal = getMtlDataType(dataTypeString); switch(mtlDataTypeVal) { case mtlDataType::mtlDataNEWMTL: mtlFile >> valString; materials.push_back(Material(valString)); valString.clear(); break; case mtlDataType::mtlDataNS: mtlFile >> xVal; materials.back().shine = xVal; break; case mtlDataType::mtlDataKA: mtlFile >> xVal; mtlFile >> yVal; mtlFile >> zVal; materials.back().Ka = glm::vec3(xVal, yVal, zVal); break; case mtlDataType::mtlDataKD: mtlFile >> xVal; mtlFile >> yVal; mtlFile >> zVal; materials.back().Kd = glm::vec3(xVal, yVal, zVal); break; case mtlDataType::mtlDataKS: mtlFile >> xVal; mtlFile >> yVal; mtlFile >> zVal; materials.back().Ks = glm::vec3(xVal, yVal, zVal); break; case mtlDataType::mtlDataMAP: { if(materials.back().textureSet) break; getline(mtlFile, valString); int fileNameLocation = valString.find_last_of("/\\"); if(fileNameLocation != -1) valString = valString.substr(fileNameLocation + 1); while(valString[0] == ' ' || valString[0] == '\t') valString = valString.substr(1); if(valString.size() < 4 || valString.substr(valString.size() - 4) != ".dds") { valString = valString.substr(0, valString.find_last_of('.') + 1); valString += "dds"; } materials.back().textureName = valString; bool textureExists = false; for(int i = 0; i < materials.size() - 1; i++) { if(materials[i].textureName == valString) { textureExists = true; materials.back().texture = materials[i].texture; break; } } if(textureExists) { valString.clear(); break; } materials.back().texture = loadImage((folderName + valString).c_str()); materials.back().textureSet = true; valString.clear(); break; } case mtlDataType::mtlDataBUMP: { if(materials.back().bumpSet) break; getline(mtlFile, valString); int fileNameLocation = valString.find_last_of("/\\"); if(fileNameLocation != -1) valString = valString.substr(fileNameLocation + 1); while(valString[0] == ' ' || valString[0] == '\t') valString = valString.substr(1); if(valString.size() < 4 || valString.substr(valString.size() - 4) != ".dds") { valString = valString.substr(0, valString.find_last_of('.') + 1); valString += "dds"; } materials.back().bumpName = valString; bool bumpExists = false; for(int i = 0; i < materials.size() - 1; i++) { if(materials[i].bumpName == valString) { bumpExists = true; materials.back().bump = materials[i].bump; break; } } if(bumpExists) { valString.clear(); break; } materials.back().bump = loadImage((folderName + valString).c_str()); materials.back().bumpSet = true; valString.clear(); break; } default: break; } } mtlFile.close(); printf("Loading object %s... ", objFileName.c_str()); std::ifstream objFile(objFileName.c_str(), std::ios::in); if(!objFile.is_open()) { printf("Failed to open object %s\n", objFileName.c_str()); exit(1); } std::vector<glm::vec3> vList_in; std::vector<glm::vec2> vTextureList_in; std::vector<glm::vec3> vNormalList_in; std::vector<GLuint> iVertex; std::vector<GLuint> iTexture; std::vector<GLuint> iNormal; std::vector<unsigned int> materialIndices_in; while(objFile >> dataTypeString) { dataType dataTypeVal = getDataType(dataTypeString); switch(dataTypeVal) { case dataType::dataV: objFile >> xVal; objFile >> yVal; objFile >> zVal; vList_in.push_back(glm::vec3(xVal, yVal, zVal)); break; case dataType::dataVT: objFile >> xVal; objFile >> yVal; vTextureList_in.push_back(glm::vec2(xVal, yVal)); break; case dataType::dataVN: objFile >> xVal; objFile >> yVal; objFile >> zVal; vNormalList_in.push_back(glm::vec3(xVal, yVal, zVal)); break; case dataType::dataUSEMTL: { int index = -1; objFile >> valString; for(int i = 0; i < materials.size(); i++) { if(materials[i].materialName == valString) { index = i; break; } } if(index == -1) exit(1); valString.clear(); materialIndices_in.push_back(iVertex.size()); materialIndices_in.push_back(index); break; } case dataType::dataF: { char lastChar; for(int i = 0; i < 3; i++) { getline(objFile, valString, '/'); valStream << valString; valString.clear(); valStream >> iVal; valStream.str(std::string()); valStream.clear(); iVertex.push_back(iVal); getline(objFile, valString, '/'); valStream << valString; valString.clear(); valStream >> iVal; valStream.str(std::string()); valStream.clear(); iTexture.push_back(iVal); objFile >> iVal; iNormal.push_back(iVal); lastChar = objFile.get(); } if(lastChar != '\n') { while(objFile.peek() == ' ' || objFile.peek() == '\t') { objFile.get(); } if(objFile.peek() == '\n') break; iVertex.push_back(iVertex[iVertex.size() - 3]); iTexture.push_back(iTexture[iTexture.size() - 3]); iNormal.push_back(iNormal[iNormal.size() - 3]); iVertex.push_back(iVertex[iVertex.size() - 2]); iTexture.push_back(iTexture[iTexture.size() - 2]); iNormal.push_back(iNormal[iNormal.size() - 2]); getline(objFile, valString, '/'); valStream << valString; valString.clear(); valStream >> iVal; valStream.str(std::string()); valStream.clear(); iVertex.push_back(iVal); getline(objFile, valString, '/'); valStream << valString; valString.clear(); valStream >> iVal; valStream.str(std::string()); valStream.clear(); iTexture.push_back(iVal); objFile >> iVal; iNormal.push_back(iVal); } break; } default: break; } } objFile.close(); int first, last; std::map<FullVertex,unsigned int> vertexToOutIndex; for(int k = 0; k < materialIndices_in.size()/2; ++k) { first = materialIndices_in[2*k]; if((2*k + 2) > (materialIndices_in.size() - 1)) last = iVertex.size(); else last = materialIndices_in[2*k + 2]; materialIndices.push_back(fList.size()); materialIndices.push_back(materialIndices_in[2*k + 1]); for(int i = first; i < last; i++) { FullVertex nextVertex = {vList_in[iVertex[i] - 1], vTextureList_in[iTexture[i] - 1], vNormalList_in[iNormal[i] - 1]}; std::map<FullVertex,unsigned int>::iterator vLocation = vertexToOutIndex.find(nextVertex); if(vLocation == vertexToOutIndex.end()) { vList.push_back(vList_in[iVertex[i]-1]); vTextureList.push_back(vTextureList_in[iTexture[i]-1]); vNormalList.push_back(vNormalList_in[iNormal[i]-1]); vertexToOutIndex[nextVertex] = vList.size() - 1; fList.push_back(vList.size() - 1); } else { fList.push_back(vLocation->second); } } } // Invert all texture v-coordinates for use with DXT compression textures for(int i = 0; i < vTextureList.size(); i++) { vTextureList[i][1] = 1 - vTextureList[i][1]; } // Generate tangent vectors for normals // Sourced from http://www.terathon.com/code/tangent.html std::vector<glm::vec3> tan1(vList.size()); std::vector<glm::vec3> tan2(vList.size()); for (unsigned int a = 0; a < fList.size(); a+=3) { GLuint i1 = fList[a + 0]; GLuint i2 = fList[a + 1]; GLuint i3 = fList[a + 2]; glm::vec3 v1 = vList[i1]; glm::vec3 v2 = vList[i2]; glm::vec3 v3 = vList[i3]; glm::vec2 w1 = vTextureList[i1]; glm::vec2 w2 = vTextureList[i2]; glm::vec2 w3 = vTextureList[i3]; float x1 = v2.x - v1.x; float x2 = v3.x - v1.x; float y1 = v2.y - v1.y; float y2 = v3.y - v1.y; float z1 = v2.z - v1.z; float z2 = v3.z - v1.z; float s1 = w2.x - w1.x; float s2 = w3.x - w1.x; float t1 = w2.y - w1.y; float t2 = w3.y - w1.y; float r = 1.0f / (s1 * t2 - s2 * t1); glm::vec3 sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r); glm::vec3 tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r); tan1[i1] += sdir; tan1[i2] += sdir; tan1[i3] += sdir; tan2[i1] += tdir; tan2[i2] += tdir; tan2[i3] += tdir; } for (unsigned int a = 0; a < vList.size(); a++) { glm::vec3 n = vNormalList[a]; glm::vec3 t = tan1[a]; // Gram-Schmidt orthogonalize glm::vec4 tangent = glm::vec4(glm::normalize(t - n * glm::dot(n, t)), 0.0f); // Calculate handedness tangent.w = (glm::dot(glm::cross(n, t), tan2[a]) < 0.0f) ? -1.0f : 1.0f; vTangentList.push_back(tangent); } printf("DONE\n"); return; }
void OBJExporter::Write( const char* relativePath, const char* basePath ) { idStrStatic< MAX_OSPATH > convertedFileName = relativePath; convertedFileName.SetFileExtension( ".obj" ); idFileLocal objFile( fileSystem->OpenFileWrite( convertedFileName, basePath ) ); convertedFileName.SetFileExtension( ".mtl" ); idFileLocal mtlFile( fileSystem->OpenFileWrite( convertedFileName, basePath ) ); int totalVerts = 0; for( int g = 0; g < groups.Num(); g++ ) { const OBJGroup& group = groups[g]; objFile->Printf( "g %s\n", group.name.c_str() ); for( int o = 0; o < group.objects.Num(); o++ ) { const OBJObject& geometry = group.objects[o]; //objFile->Printf( "g %s\n", group.name.c_str() ); //objFile->Printf( "o %s\n", geometry.name.c_str() ); for( int i = 0; i < geometry.faces.Num(); i++ ) { const OBJFace& face = geometry.faces[i]; for( int j = 0; j < face.verts.Num(); j++ ) { const idVec3& v = face.verts[j].xyz; objFile->Printf( "v %1.6f %1.6f %1.6f\n", v.x, v.y, v.z ); } for( int j = 0; j < face.verts.Num(); j++ ) { const idVec2& vST = face.verts[j].GetTexCoord(); objFile->Printf( "vt %1.6f %1.6f\n", vST.x, vST.y ); } for( int j = 0; j < face.verts.Num(); j++ ) { const idVec3& n = face.verts[j].GetNormal(); objFile->Printf( "vn %1.6f %1.6f %1.6f\n", n.x, n.y, n.z ); } //objFile->Printf( "g %s\n", group.name.c_str() ); //objFile->Printf( "o %s\n", geometry.name.c_str() ); objFile->Printf( "usemtl %s\n", face.material->GetName() ); objFile->Printf( "f " ); //for( int j = 0; j < face.indexes.Num(); j++ ) // flip order for OBJ for( int j = face.indexes.Num() - 1; j >= 0; j-- ) { objFile->Printf( "%i/%i/%i ", face.indexes[j] + 1 + totalVerts, face.indexes[j] + 1 + totalVerts, face.indexes[j] + 1 + totalVerts ); } objFile->Printf( "\n\n" ); } for( int i = 0; i < geometry.faces.Num(); i++ ) { const OBJFace& face = geometry.faces[i]; totalVerts += face.verts.Num(); } } } for( int i = 0; i < materials.Num(); i++ ) { const idMaterial* material = materials[i]; mtlFile->Printf( "newmtl %s\n", material->GetName() ); if( material->GetFastPathDiffuseImage() ) { idStr path = material->GetFastPathDiffuseImage()->GetName(); path.SlashesToBackSlashes(); path.DefaultFileExtension( ".tga" ); mtlFile->Printf( "\tmap_Kd //..\\..\\..\\%s\n", path.c_str() ); } else if( material->GetEditorImage() ) { idStr path = material->GetEditorImage()->GetName(); path.SlashesToBackSlashes(); path.DefaultFileExtension( ".tga" ); mtlFile->Printf( "\tmap_Kd //..\\..\\..\\%s\n", path.c_str() ); } mtlFile->Printf( "\n" ); } }
void SphereGenerator::output() { // texture = cv::imread(sTexture.toStdString().c_str()); // QDateTime currTime = QDateTime::currentDateTime(); // long long timeStamp = currTime.toMSecsSinceEpoch(); std::ofstream out(sObj.toStdString().c_str()); // for usemtl QString keyWords = "wire_sphere"; out << "# created by h005 SphereGenerator" << std::endl; out << std::endl; // mtl file QFileInfo objFile(sObj); QString mtlFile(objFile.absolutePath()); mtlFile.append("/"); mtlFile.append(objFile.baseName()); mtlFile.append(".mtl"); QFileInfo mtlFileInfo(mtlFile); out << "mtllib "<< mtlFileInfo.fileName().toStdString() <<std::endl; for(int i=0;i<centerList.size();i++) out << "v "<< centerList.at(i).x << " " << centerList.at(i).y << " " << centerList.at(i).z << std::endl; out << "# "<< centerList.size() << " vertices" << std::endl; if(isCircle) sZ++; float uStep = 1.0 / (float)(sX-1); float vStep = 1.0 / (float)(sZ-1); // float u = 1.0f,v = 1.0f; float u = 0.f, v = 1.0f; for(int i=0;i<sX;i++) { v = 1.0f; for(int j=0;j<sZ;j++) { out << "vt " << u << " " << v << std::endl; v -= vStep; if( v < 0.f) v = 0.f; } u += uStep; if(u > 1.f) u = 1.f; } out << "# "<< centerList.size() << " texture coords" << std::endl; out << "g " << "Sphere 001"<< std::endl; // out << "usemtl " << keyWords.toStdString() << std::endl; out << "s 1" << std::endl; if(!isCircle) { for(int i=0;i<sX-1;i++) { for(int j=1;j<sZ;j++) { out << "f " << i * sZ + j << "/" << i * sZ + j << " "; out << (i+1) * sZ + j << "/" << (i+1) * sZ + j << " "; out << (i+1) * sZ + j + 1 << "/" << (i+1) * sZ + j + 1 << " "; out << i * sZ + j + 1 << "/" << i * sZ + j + 1 << std::endl; } } out << "# "<<(sX-1)*(sZ-1)<<" polygons"<<std::endl; } else { // 先完成环的那部分 sZ--; for(int i=0;i<sX-1;i++) { for(int j=1;j<sZ;j++) { out << "f " << i * sZ + j << "/" << i * (sZ + 1) + j << " "; out << (i+1) * sZ + j << "/" << (i+1) * (sZ + 1) + j << " "; out << (i+1) * sZ + j + 1 << "/" << (i+1) * (sZ + 1) + j + 1 << " "; out << i * sZ + j + 1 << "/" << i * (sZ + 1) + j + 1 << std::endl; } } // 将环给衔接起来 for(int i=0;i<sX-1;i++) { out << "f " << i * sZ + 1 << "/" << (i + 1) * (sZ + 1) << " "; out << (i+1) * sZ << "/" << (i+1) * (sZ + 1) - 1 << " "; out << (i+2) * sZ << "/" << (i+2) * (sZ + 1) - 1 << " "; out << (i+1) * sZ + 1 << "/" << (i+2) * (sZ + 1) << std::endl; } out << "# "<<(sX)*(sZ-1)<<" polygons"<<std::endl; } out.close(); std::cout << "mtlFile "<<mtlFile.toStdString() << std::endl; out.open(mtlFile.toStdString().c_str()); out << "# created by h005 SphereGenerator" << std::endl; out << "newmtl wire_plane" << std::endl; out << " Ns 32"<< std::endl; out << " d 1"<< std::endl; out << " Tr 0" << std::endl; out << " Tf 1 1 1"<< std::endl; out << " illum 2" << std::endl; out << " Ka 0.7765 0.8824 0.3412"<< std::endl; out << " Kd 0.7765 0.8824 0.3412"<< std::endl; out << " Ks 0.3500 0.3500 0.3500"<< std::endl; QFileInfo textureInfo(sTexture); out << " map_Ka "<< textureInfo.fileName().toStdString() << std::endl; out << " map_Kd "<< textureInfo.fileName().toStdString() << std::endl; out.close(); }
bool RTRModel::loadMaterialLibraryFromMtlFile(const QString& filePath) { QFile mtlFile(filePath); if (!mtlFile.open(QIODevice::ReadOnly)) { return false; } QTextStream mtlFileStream(&mtlFile); QString currentMaterialName; RTRMaterial* currentMaterial = NULL; while (!mtlFileStream.atEnd()) { QString line = mtlFileStream.readLine().trimmed(); if (line.isEmpty()) continue; if (line[0] == '#') { qDebug() << "Ignoring Comment Line:" << line; continue; } QStringList param = line.split(' ', QString::SkipEmptyParts); QString command = param[0]; command = command.toLower(); param.removeFirst(); if (command == "newmtl") { if (currentMaterial != NULL) { materialLibrary.insert(currentMaterialName, currentMaterial); } currentMaterialName = param[0]; currentMaterial = new RTRMaterial(); } else { if (currentMaterial == NULL) { mtlFile.close(); return false; } if (command == "kd") { currentMaterial->diffuse = RTRColor(param[0].toDouble(), param[1].toDouble(), param[2].toDouble()); currentMaterial->setColorProperty("diffuse", RTRColor(param[0].toDouble(), param[1].toDouble(), param[2].toDouble())); } else if (command == "map_kd") currentMaterial->setTextureProperty("diffuse", modelPath + "/" + param[0]); else if (command == "ka") currentMaterial->setColorProperty("ambient", RTRColor(param[0].toDouble(), param[1].toDouble(), param[2].toDouble())); else if (command == "ks") currentMaterial->setColorProperty("specular", RTRColor(param[0].toDouble(), param[1].toDouble(), param[2].toDouble())); else if (command == "reflection_rate") { currentMaterial->reflectionRate = param[0].toDouble(); currentMaterial->setColorProperty("reflection_rate", RTRColor(param[0].toDouble(), param[0].toDouble(), param[0].toDouble())); } else if (command == "reflection_color") { currentMaterial->reflectionColor = RTRColor(param[0].toDouble(), param[1].toDouble(), param[2].toDouble()); currentMaterial->setColorProperty("reflection_color", RTRColor(param[0].toDouble(), param[1].toDouble(), param[2].toDouble())); } else if (command == "reflection_glossiness") currentMaterial->setColorProperty("reflection_glossiness", RTRColor(param[0].toDouble(), param[0].toDouble(), param[0].toDouble())); else if (command == "refraction_rate") { currentMaterial->refractionRate = param[0].toDouble(); currentMaterial->setColorProperty("refraction_rate", RTRColor(param[0].toDouble(), param[0].toDouble(), param[0].toDouble())); } else if (command == "refraction_index") { currentMaterial->refractionIndex = param[0].toDouble(); currentMaterial->setColorProperty("refraction_index", RTRColor(param[0].toDouble(), param[0].toDouble(), param[0].toDouble())); } else if (command == "refraction_color") { currentMaterial->refractionColor = RTRColor(param[0].toDouble(), param[1].toDouble(), param[2].toDouble()); currentMaterial->setColorProperty("refraction_color", RTRColor(param[0].toDouble(), param[1].toDouble(), param[2].toDouble())); } else if (command == "refraction_glossiness") currentMaterial->setColorProperty("refraction_glossiness", RTRColor(param[0].toDouble(), param[0].toDouble(), param[0].toDouble())); else if (command == "fod_aperture") currentMaterial->setColorProperty("fod_aperture", RTRColor(param[0].toDouble(), param[0].toDouble(), param[0].toDouble())); else if (command == "fod_focus") currentMaterial->setColorProperty("fod_focus", RTRColor(param[0].toDouble(), param[0].toDouble(), param[0].toDouble())); else if (command == "camera_position") currentMaterial->setColorProperty("camera_position", RTRColor(param[0].toDouble(), param[1].toDouble(), param[2].toDouble())); else if (command == "camera_angle") currentMaterial->setColorProperty("camera_angle", RTRColor(param[0].toDouble(), param[1].toDouble(), param[2].toDouble())); else if (command == "image_distance") currentMaterial->setColorProperty("image_distance", RTRColor(param[0].toDouble(), param[0].toDouble(), param[0].toDouble())); else if (command == "emission_strength") currentMaterial->emissionStrength = param[0].toDouble(); } } if (currentMaterial != NULL) { materialLibrary.insert(currentMaterialName, currentMaterial); } mtlFile.close(); return true; }
void testApp::update() { simpl = (int)(abs(fsimpl)); fsimpl = simpl; depthThreshhold = (int)(abs(fdepth)); fdepth = depthThreshhold; if (!fileq.empty()){ filecounter--; //statusText += ("processed " + fileq.back() +"\n"); doneFiles.push_back("processed " + fileq.back() +"\n"); if (doneFiles.size()>=5) doneFiles.pop_front(); kinect.readCompressedPng(fileq.back(), spix); int height = 480; int width = 640; //this section is modified from the ofxRGBDepth renderer so as to not require opencv camera intrinsics. ofFile mtlFile("/tmp/rgbdsharedmaterial.mtl", ofFile::WriteOnly); mtlFile << "newmtl rgbdshared" <<endl; //define shared material. simplifies workflow in blender. mtlFile << "illum 1" <<endl; //no specular. mtlFile.close(); ofFile file("/tmp/rgbd_"+ofToString(filecounter,3)+".obj", ofFile::WriteOnly); float fx = tanf(ofDegToRad(fov.x) / 2) * 2; float fy = tanf(ofDegToRad(fov.y) / 2) * 2; file << "mtllib rgbdsharedmaterial.mtl" << endl; file << "usemtl rgbdshared" << endl; file << "#vertices" << endl; for (int y = 0; y < height; y+=1){ for (int x = 0; x<width; x+=1){ unsigned short z = spix[x+y*width]; float xReal=(((float)x-320) / 640.) * z * fx; float yReal=(((float)y-240) / 480.) * z * fy; //blender coordinates are weird so we invert everything here. //this will orient for a blender camera at 0,0,0 with x rotation at 90. file << "v " << ofToString((float)xReal/32.) << " " << ofToString(-(float)yReal/32.) << " " << ofToString((float)(-spix[x+y*width]/32.)) << endl; } } file << "#faces" << endl; int coordx, coordy=0; for (int y = 0; y<height-simpl; y+=simpl){ for (int x=0; x<width-simpl; x+=simpl){ if ( (spix[x+y*width] > 0) &&(abs(spix[x+y*width] - spix[(x+simpl)+y*width]) <= depthThreshhold) &&(abs(spix[x+y*width] - spix[x+(y+simpl)*width]) <= depthThreshhold) &&(abs(spix[(x+simpl)+y*width] - spix[x+(y+simpl)*width]) <= depthThreshhold) &&(abs(spix[(x+simpl)+y*width] - spix[(x+simpl)+(y+simpl)*width]) <= depthThreshhold) &&(abs(spix[(x+simpl)+y*width] - spix[x+(y+simpl)*width]) <= depthThreshhold) &&(abs(spix[(x+simpl)+(y+simpl)*width] - spix[x+(y+simpl)*width]) <= depthThreshhold) ){ file << "f " << ofToString(1+x+y*width) << " " << ofToString(1+(x+simpl)+y*width)<< " " << ofToString(1+x+(y+simpl)*width) << endl; file << "f " << ofToString(1+(x+simpl)+y*(width))<< " " << ofToString(1+(x+simpl)+(y+simpl)*width)<< " " << ofToString(1+x+(y+simpl)*(width)) << endl; } } } file.close(); if (fileq.size()==1) doneFiles.push_back("done!"); fileq.pop_back(); } }