//Loads an OBJ file into this mesh //Does not currently account for textures void Mesh::loadOBJ(std::string fileName) { std::vector<glm::vec3> vertices; std::vector<glm::vec2> uvs; std::vector<glm::vec3> normals; std::ifstream objFile(fileName, std::ios::in); if (!objFile.is_open()) { std::cout << "Failed to open the file " << fileName << std::endl; } std::string line; while (getline(objFile,line)) { if (line.length() == 0) { //Line was empty, for some reason continue; } std::stringstream lineStream(line); //Possible performance issues std::string lineType; lineStream >> lineType; if (lineType == "v") { //We're dealing with a vertex float x,y,z; lineStream >> x >> y >> z; vertices.push_back(glm::vec3(x,y,z)); } else if (lineType == "vt") { //"" UV
void NewAreaDialog::confirm() { name = nameEdit->text(); tile = tileEdit->text(); obj = objEdit->text(); width = widthEdit->text().toInt(); height = heightEdit->text().toInt(); if(name.isEmpty() || name.isNull()) { QMessageBox::information(this, "Error", "Name is invalid"); return; } QFile tileFile(tile); tileFile.open(QFile::ReadOnly); if(!tileFile.exists() || !tileFile.isOpen()) { QMessageBox::information(this, "Error", "Terrain sheet is invalid"); return; } QFile objFile(obj); objFile.open(QFile::ReadOnly); if(!objFile.exists() || !objFile.isOpen()) { QMessageBox::information(this, "Error", "Object sheet is invalid"); return; } accept(); }
void GeometryLoader::loadFromFile(const std::string& filename) { std::ifstream objFile(filename); if (objFile.is_open()) { processFile(objFile); objFile.close(); printStatistics(filename); } else { std::cout << "ERROR: cannot open a file\n"; } }
void Mesh::writeObj(Mesh mesh, string filename) { std::ofstream objFile(filename); for (const auto& v : mesh.vertex) { //objFile << "v " << v.position[0] << " " << v.position[1] << " " << v.position[2] << std::endl; objFile << "v " << v.position[0] << " " << v.position[1] << " " << v.position[2] << " " << v.color[0] << " " << v.color[1] << " " << v.color[2] << " " << std::endl; } for (const auto& v : mesh.tvi) { objFile << "f " << v[0]+1 << " " << v[1]+1 << " " << v[2]+1 << std::endl; } objFile.close(); return; // obj starts counting triangles at 1 }
WaveFrontObj WaveFrontUtils::LoadObj(const char * path) { WaveFrontObj obj; ifstream objFile(path,std::ifstream::in); if(objFile.is_open()){ // Verifica se arquivo esta aberto while(objFile.good() && !objFile.eof()){ string linha; getline(objFile, line); if(linha.front() == 'v'){ // linha de vertex vector<float> vertex = Utils::SplitStringToFloat(' ', linha); obj.addVertex(vertex); } } objFile.close(); } return obj; }
/// Yus. bool Mesh::SaveObj(String path) { if (!path.Contains(".obj")) path = path + ".obj"; File objFile(path); bool ok = objFile.OpenForWritingText(); if (!ok) return false; std::fstream & fstream = objFile.GetStream(); fstream<<"o "<<name; for (int i = 0; i < vertices.Size(); ++i) { Vector3f & v = vertices[i]; fstream<<"\nv "<<v; } for (int i = 0; i < uvs.Size(); ++i) { Vector2f & uv = uvs[i]; fstream<<"\nvt "<<uv; } for (int i = 0; i < normals.Size(); ++i) { Vector3f & n = normals[i]; fstream<<"\nvn "<<n; } for (int i = 0; i < faces.Size(); ++i) { MeshFace & f = faces[i]; fstream<<"\nf"; for (int i = 0; i < f.vertices.Size(); ++i) { fstream<<" "<<(f.vertices[i]+1); if (f.normals.Size() || f.uvs.Size()) fstream<<"/"; if (f.uvs.Size()) fstream<<(f.uvs[i]+1); if (f.normals.Size()) fstream<<"/"<<(f.normals[i]+1); } } objFile.Close(); return true; }
void OBJBaker::bakeOBJ() { // Read the OBJ file QFile objFile(_originalModelFilePath); if (!objFile.open(QIODevice::ReadOnly)) { handleError("Error opening " + _originalModelFilePath + " for reading"); return; } QByteArray objData = objFile.readAll(); bool combineParts = true; // set true so that OBJReader reads material info from material library OBJReader reader; auto geometry = reader.readOBJ(objData, QVariantHash(), combineParts, _modelURL); // Write OBJ Data as FBX tree nodes createFBXNodeTree(_rootNode, *geometry); checkIfTexturesFinished(); }
void ObjModel::ReadFile(string fileName) { Reset(); int t1 = fileName.find_last_of('/'); if (t1 == string::npos) { path = ""; } else { path = fileName.substr(0, t1 + 1); } string temp; char c, buf[256]; ifstream objFile(fileName); if (!objFile.is_open()) { cout << fileName << " couldn't be opened.\n"; system("pause"); exit(1); } c = objFile.peek(); while (c == '#' || c == '\n' || c == ' ') { objFile.getline(buf, 255); c = objFile.peek(); } c = objFile.peek(); if (c == 'm') { objFile >> temp; objFile >> temp; }
int main(int argc, char** argv) { #define MAX_OBJ_FILENAME 500; std::string modelName; if (argc != 2) { std::cerr << "Usage: " << argv[0] << " <model.obj>" << std::endl; #if _DEBUG modelName = std::string("test.obj"); #else return -1; #endif } else { modelName = std::string(argv[1]); } std::cout << "Loading " << modelName << std::endl; std::string modelPath(MODEL_DIRECTORY); modelPath += std::string(DIRECTORY_SEPARATOR) + modelName; std:: ifstream objFile(modelPath.c_str()); #if _MSC_VER std::cerr << "MSVC detected" << std::endl; #else if (false == objFile.is_open()) { std::cerr << "Unable to load " << modelPath << std::endl; return -2; } #endif MyGLApp objViewer(modelName.c_str()); objViewer.start(); SDL_Quit(); return 0; }
Material ModelLoader::loadMaterialFromMTL( string p_materialFileName ) { Material material; MaterialStruct mtrStruct; fstream objFile(p_materialFileName); if(objFile) { string line; string prefix; while(objFile.eof() == false) { prefix = "NULL"; //leave nothing from the previous iteration stringstream lineStream; getline(objFile, line); lineStream << line; lineStream >> prefix; if(prefix == "map_Kd") { string materialTextureName; lineStream >> materialTextureName; wstring name (materialTextureName.begin(), materialTextureName.end()); D3DTexture* texture = new D3DTexture(m_pDevice, m_pDeviceContext); texture->createTexture(&name, NULL, false); material.setTexture(texture); //m_material->m_textureResource = createTexture(materialTextureName); } else if(prefix == "Ns") { int nShininess; lineStream >> nShininess; mtrStruct.m_ambient.w = nShininess; }
int Model_OBJ::Load(std::string filename) { string line; ifstream objFile (filename + ".obj"); if (objFile.is_open()) // If obj file is open, continue { objFile.seekg (0, ios::end); // Go to end of the file, long fileSize = objFile.tellg(); // get file size objFile.seekg (0, ios::beg); // we'll use this to register memory for our 3d model vertexBuffer = (float*) malloc (fileSize); // Allocate memory for the verteces Faces_Triangles = (float*) malloc(fileSize*sizeof(float)); // Allocate memory for the triangles normals = (float*) malloc(fileSize*sizeof(float)); // Allocate memory for the normals int triangle_index = 0; // Set triangle index to zero int normal_index = 0; // Set normal index to zero while (! objFile.eof() ) // Start reading file data { getline (objFile,line); // Get line from file if (line.c_str()[0] == 'v') // The first character is a v: on this line is a vertex stored. { line[0] = ' '; // Set first character to 0. This will allow us to use sscanf sscanf(line.c_str(),"%f %f %f ", // Read floats from the line: v X Y Z &vertexBuffer[TotalConnectedPoints], &vertexBuffer[TotalConnectedPoints+1], &vertexBuffer[TotalConnectedPoints+2]); TotalConnectedPoints += POINTS_PER_VERTEX; // Add 3 to the total connected points } if (line.c_str()[0] == 'f') // The first character is an 'f': on this line is a point stored { line[0] = ' '; // Set first character to 0. This will allow us to use sscanf int vertexNumber[4] = { 0, 0, 0 }; sscanf(line.c_str(),"%i%i%i", // Read integers from the line: f 1 2 3 &vertexNumber[0], // First point of our triangle. This is an &vertexNumber[1], // pointer to our vertexBuffer list &vertexNumber[2] ); // each point represents an X,Y,Z. vertexNumber[0] -= 1; // OBJ file starts counting from 1 vertexNumber[1] -= 1; // OBJ file starts counting from 1 vertexNumber[2] -= 1; // OBJ file starts counting from 1 /******************************************************************** * Create triangles (f 1 2 3) from points: (v X Y Z) (v X Y Z) (v X Y Z). * The vertexBuffer contains all verteces * The triangles will be created using the verteces we read previously */ int tCounter = 0; for (int i = 0; i < POINTS_PER_VERTEX; i++) { Faces_Triangles[triangle_index + tCounter ] = vertexBuffer[3*vertexNumber[i] ]; Faces_Triangles[triangle_index + tCounter +1 ] = vertexBuffer[3*vertexNumber[i]+1 ]; Faces_Triangles[triangle_index + tCounter +2 ] = vertexBuffer[3*vertexNumber[i]+2 ]; tCounter += POINTS_PER_VERTEX; } /********************************************************************* * Calculate all normals, used for lighting */ float coord1[3] = { Faces_Triangles[triangle_index], Faces_Triangles[triangle_index+1],Faces_Triangles[triangle_index+2]}; float coord2[3] = {Faces_Triangles[triangle_index+3],Faces_Triangles[triangle_index+4],Faces_Triangles[triangle_index+5]}; float coord3[3] = {Faces_Triangles[triangle_index+6],Faces_Triangles[triangle_index+7],Faces_Triangles[triangle_index+8]}; float *norm = this->calculateNormal( coord1, coord2, coord3 ); tCounter = 0; for (int i = 0; i < POINTS_PER_VERTEX; i++) { normals[normal_index + tCounter ] = norm[0]; normals[normal_index + tCounter +1] = norm[1]; normals[normal_index + tCounter +2] = norm[2]; tCounter += POINTS_PER_VERTEX; } triangle_index += TOTAL_FLOATS_IN_TRIANGLE; normal_index += TOTAL_FLOATS_IN_TRIANGLE; TotalConnectedTriangles += TOTAL_FLOATS_IN_TRIANGLE; } } objFile.close(); // Close OBJ file } else { cout << "Unable to open file"; } //loads color; ifstream colFile (filename + ".txt"); if (colFile.is_open()) { colFile >> color[0]; colFile >> color[1]; colFile >> color[2]; colFile.close(); }
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(); }
DWORD PE::AddSection(LPBYTE pBuffer,DWORD dwSize,PCHAR pszSectionName) { //修改文件头中的区段数量 m_pNt->FileHeader.NumberOfSections++; //增加区段表项 memset(m_pLastSection,0,sizeof(IMAGE_SECTION_HEADER)); //写入区段名 strcpy_s((char*)m_pLastSection->Name,IMAGE_SIZEOF_SHORT_NAME,pszSectionName); //区段虚拟大小 DWORD dwVirtualSize=0; //区段文件大小 DWORD dwSizeOfRawData=0; //把文件加载到内存所需要的大小 DWORD dwSizeOfImage=m_pNt->OptionalHeader.SizeOfImage; //取余 查看内存是否对齐 if (dwSizeOfImage%m_dwMemAlign) { // 取商再原来基础上+1 比如说dwSizeOfImage=1726 对齐粒度m_dwMemAlign=200 //此时dwSizeOfImage=1800 dwSizeOfImage=(dwSizeOfImage/m_dwMemAlign+1)*m_dwMemAlign; } else { dwSizeOfImage=(dwSizeOfImage/m_dwMemAlign)*m_dwMemAlign; } //区段对齐后的RVA(dwSize) /内存对齐粒度 m_dwMemAlign if (dwSize%m_dwMemAlign) { dwVirtualSize=(dwSize/m_dwMemAlign+1)*m_dwMemAlign; } else { dwVirtualSize=(dwSize/m_dwMemAlign)*m_dwMemAlign; } //区段对齐后的RVA(dwSize) /文件对齐粒度 m_dwMemAlign if (dwSize%m_dwFileAlign) { dwSizeOfRawData=(dwSize/m_dwFileAlign+1)*m_dwFileAlign; } else { dwSizeOfRawData=(dwSize/m_dwFileAlign)*m_dwFileAlign; } //获取到新的相对虚拟地址 RVA m_pLastSection->VirtualAddress=(m_pLastSection[-1].VirtualAddress+(dwSize/m_dwMemAlign)*m_dwMemAlign); //区段在文件中的偏移 m_pLastSection->PointerToRawData=m_dwFileSize; //区段在文件中大小 m_pLastSection->SizeOfRawData=dwSizeOfRawData; //区段在内存中大小 m_pLastSection->Misc.VirtualSize=dwVirtualSize; //区段属性 m_pLastSection->Characteristics=0Xe0000040; //增加 文件大小 创建文件 添加代码段 确定入口点 m_pNt->OptionalHeader.SizeOfImage=dwSizeOfImage+dwVirtualSize; m_pNt->OptionalHeader.AddressOfEntryPoint=m_dwNewOEP+m_pLastSection->VirtualAddress; //生成输出文件路径 CString strPath=m_objFIle.GetFilePath(); TCHAR SzOutPath[MAX_PATH]={0}; //获取文件后缀名 LPWSTR strSuffix=PathFindExtension(strPath); //目标文件路径到SzOutPath wcsncpy_s(SzOutPath,MAX_PATH,strPath,wcslen(strPath)); //移除后缀名 PathRemoveExtension(SzOutPath); // 在路径最后附加“_1” wcscat_s(SzOutPath,MAX_PATH,L"_1"); // 在路径最后附加刚刚保存的后缀名 wcscat_s(SzOutPath, MAX_PATH, strSuffix); //创建文件 CFile objFile(SzOutPath,CFile::modeCreate|CFile::modeReadWrite); objFile.Write(m_pFileBase,(DWORD)m_objFIle.GetLength()); //移到文件尾 objFile.SeekToEnd(); //将pBuffer 按照大小dwSize 写入文件 objFile.Write(pBuffer,dwSize); //返回操作完成后的最后一个区段的相对虚拟地址 RAV return m_pLastSection->VirtualAddress; }
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; }
/** * MyFrame::Compile * This function compiles given src file. It calls MyFrame::GetCompileData to * receave data. * @param index about file from buffer list * @return int 0 on success, 1 on failure */ int MyFrame::Compile ( int index ) { //Safety checks if ( !stc ) return 1; if ( ProcessIsRunning ) return 1; // these are used to get the first error bool isFirstErrorFound = false; wxString strFirstErrorFile; int intFirstErrorLine; // File that we are about to compile wxFileName objFile( bufferList[ index ]->GetFileName() ); objFile.Normalize(); // Get compiler cmdline and check it. if empty return. wxString strCompile( GetCompileData( index ) ); if( !strCompile.Len() ) return 1; // Log compiler output and input strCompilerOutput.Empty(); strCompilerOutput.Add("[bold]Command executed:[/bold]"); strCompilerOutput.Add(strCompile); // If Active path is activated then set current working path // to show to the location of the src file. if( Prefs.ActivePath ) ::wxSetWorkingDirectory( objFile.GetPath() ); // Execute fbc and retreave results. wxArrayString arrOutput, arrErrOutput; int intCompileResult = wxExecute( strCompile, arrOutput, arrErrOutput ); // if there was any output from fbc then get output messages and put them // into console area if ( arrOutput.Count() || arrErrOutput.Count() ) { // define variables wxString strOutput; wxString strTemp; wxFileName objOutputFile; long intOutput; long intLine; int intBraceStart; int intBraceEnd; bool isOutputHeader = false; wxString strDebug; // Becouse fbc returns Outputs via both std and error channels, // we need to join them here. WX_APPEND_ARRAY( arrOutput, arrErrOutput ); // Putput logging: strCompilerOutput.Add( "" ); strCompilerOutput.Add( "[bold]Compiler output:[/bold]" ); // Loop through arrOutput for ( unsigned int cnt = 0; cnt < arrOutput.Count(); cnt++ ) { if ( arrOutput[cnt].IsEmpty() ) continue; // Log compiler output strCompilerOutput.Add( arrOutput[cnt] ); intBraceStart = arrOutput[cnt].First( '(' ); intBraceEnd = arrOutput[cnt].First( ')' ); // if intBraceStart is not -1 then probably line number was found. // as fbc returns things: file(linenumber): Error|Warning nr: Output message // As it might be any message then test if first part is a filename. // colon[:] - win32 // slash[/] -linux #ifdef __WXMSW__ if( intBraceStart != -1 && intBraceEnd != -1 && arrOutput[cnt].GetChar(1) == ':' ) { #else if( intBraceStart != -1 && intBraceEnd != -1 && arrOutput[cnt].GetChar(0) == '/' ) { #endif // Get possible line and error number. strTemp = arrOutput[cnt].Mid( intBraceStart + 1, intBraceEnd - intBraceStart - 1); // if this is a number: if ( strTemp.IsNumber() ) { strTemp.ToLong( &intLine ); // Get possible file name and check if it is indeed a filename objOutputFile = arrOutput[cnt].Left( intBraceStart ); objOutputFile.Normalize(); if ( objOutputFile.IsOk() && objOutputFile.FileExists() ) { //Now that it's indeed is a filename, get line, error/warning number //and Output message on that line strTemp = arrOutput[cnt].Mid( intBraceEnd + 4 ); strTemp = strTemp.Mid( strTemp.Find( ' ' ) + 1 ); strOutput = strTemp.Mid( strTemp.Find( ':' ) + 2 ); strTemp = strTemp.Left( strTemp.Find( ':' ) ); strTemp.ToLong( &intOutput ); isOutputHeader = true; } } } // If is Output header ( includes filename, Output number and line number then // add generated values. Else just add original message. if( isOutputHeader ) { isOutputHeader = false; if ( intOutput == 0 ) intOutput = -1; if ( !isFirstErrorFound ) { strFirstErrorFile = objOutputFile.GetFullPath(); intFirstErrorLine = intLine; isFirstErrorFound = true; } AddListItem(intLine, intOutput, objOutputFile.GetFullPath(), strOutput); } else { // Replace all tabs. arrOutput[cnt].Replace( "\t", " " ); AddListItem(-1, -1, "", arrOutput[cnt]); } } // Open console area if ( !HSplitter->IsSplit() ) { HSplitter->SplitHorizontally( FBCodePanel, FBConsole, ConsoleSize ); FB_View->Check(Menu_Result, true); } } else { // Since there was no output then close console area // -if no error then it is not needed. if ( HSplitter->IsSplit() ) {
sptr(Resource) DecoderOBJ::decode(const std::string &path) { clear(); TextFile objFile(path); std::string line; do { line = objFile.getLine(); if (line == "END_OF_FILE") break; if (line.find("vt") != std::string::npos) { } if (line.find("vn") != std::string::npos) appendNormal(line); if (line.find("vp") != std::string::npos) { } if (line.at(0) == 'v') appendVertex(line); if (line.at(0) == 'f') appendFace(line); line.clear(); } while (line.empty()); if (faces.empty() || vertexList.empty()) { syslog << "Unable to parse .obj file" << path << logwarn; return sptr(Resource)(); } auto newMesh = std::make_shared<rend::Mesh>(); triangulateModel(); rend::VertexBuffer vb; vb.setType(rend::VertexBuffer::INDEXEDTRIANGLELIST); vb.appendVertices(vertexList, resultTrianglesIndices, !normalsList.empty()); auto material = std::make_shared<rend::Material>(); material->plainColor = rend::Color3(255, 255, 255); material->ambientColor = rend::Color3(255, 255, 255); material->diffuseColor = rend::Color3(255, 255, 255); material->shadeMode = rend::Material::SM_FLAT; material->sideType = rend::Material::ONE_SIDE; vb.setMaterial(material); newMesh->appendSubmesh(vb); auto newObject = std::make_shared<rend::SceneObject>(newMesh); std::tr2::sys::path p(path); newObject->setName(p.filename()); syslog << "Decoded obj-model \"" << newObject->getName() << "\". Number of vertices:" << newMesh->numVertices() << ". Number of faces:" << faces.size() << logmess; return newObject; }
int main(int argc, char** argv) { float scale = 0.1f; float scaleTexV = -1.f; std::vector<Object> objects; std::ifstream inputFile(argv[1]); if (!inputFile.is_open()) { printf("Failed to open %s", argv[1]); return -1; } if (argc != 3) { printf("Missing scene name"); return -1; } std::string sceneName = argv[2]; char line[1024]; std::vector<Vec3> positions; std::vector<Vec3> normals; std::vector<Vec2> texcoords; Object* pActiveObj = nullptr; SubObject* pActiveSubObject = nullptr; int lineNum = 0; while (inputFile.getline(line, 1024)) { ++lineNum; char* context = nullptr; char* tok = strtok_s(line, " ", &context); if (!tok) continue; if (strcmp(tok, "v") == 0) { // Position Vec3 pos; pos.x = scale * (float)atof(strtok_s(nullptr, " ", &context)); pos.y = scale * (float)atof(strtok_s(nullptr, " ", &context)); pos.z = scale * (float)atof(strtok_s(nullptr, " ", &context)); positions.push_back(pos); } else if (strcmp(tok, "vn") == 0) { // Normal Vec3 norm; norm.x = (float)atof(strtok_s(nullptr, " ", &context)); norm.y = (float)atof(strtok_s(nullptr, " ", &context)); norm.z = (float)atof(strtok_s(nullptr, " ", &context)); normals.push_back(norm); } else if (strcmp(tok, "vt") == 0) { // Tex coord Vec2 uv; uv.x = (float)atof(strtok_s(nullptr, " ", &context)); uv.y = (float)atof(strtok_s(nullptr, " ", &context)) * scaleTexV; texcoords.push_back(uv); } else if (strcmp(tok, "f") == 0) { // Face Vertex faceVerts[4]; int numVerts = 0; while (context[0] != 0) { Vertex& rVert = faceVerts[numVerts]; rVert.pos = atoi(strtok_s(nullptr, "/ ", &context)) - 1; rVert.uv = atoi(strtok_s(nullptr, "/ ", &context)) - 1; rVert.norm = atoi(strtok_s(nullptr, "/ ", &context)) - 1; ++numVerts; } if (numVerts == 3) { pActiveSubObject->verts.push_back(faceVerts[0]); pActiveSubObject->verts.push_back(faceVerts[1]); pActiveSubObject->verts.push_back(faceVerts[2]); } else if (numVerts == 4) { pActiveSubObject->verts.push_back(faceVerts[0]); pActiveSubObject->verts.push_back(faceVerts[1]); pActiveSubObject->verts.push_back(faceVerts[2]); pActiveSubObject->verts.push_back(faceVerts[0]); pActiveSubObject->verts.push_back(faceVerts[2]); pActiveSubObject->verts.push_back(faceVerts[3]); } else { assert(false); } } else if (strcmp(tok, "g") == 0) { objects.emplace_back(); pActiveObj = &objects.back(); pActiveObj->name = strtok_s(nullptr, " ", &context); } else if (strcmp(tok, "usemtl") == 0) { pActiveObj->subobjects.emplace_back(); pActiveSubObject = &pActiveObj->subobjects.back(); pActiveSubObject->material = strtok_s(nullptr, " ", &context); } } Json::StyledStreamWriter jsonWriter; Json::Value jSceneRoot(Json::objectValue); // Camera { Json::Value jCamera(Json::objectValue); Json::Value jPos(Json::arrayValue); jPos[0] = 0.f; jPos[1] = 5.f; jPos[2] = 0.f; jCamera["position"] = jPos; Json::Value jRot(Json::arrayValue); jRot[0] = 0.f; jRot[1] = 0.f; jRot[2] = 0.f; jCamera["rotation"] = jRot; jSceneRoot["camera"] = jCamera; } jSceneRoot["sky"] = "cloudy"; jSceneRoot["lights"] = Json::Value(Json::arrayValue); Json::Value& jSceneObjects = jSceneRoot["objects"] = Json::Value(Json::arrayValue); int numObjects = (int)objects.size(); for (int i = 0; i < numObjects; ++i) { const Object& obj = objects[i]; Vec3 minExtents = { FLT_MAX, FLT_MAX, FLT_MAX }; Vec3 maxExtents = { -FLT_MAX, -FLT_MAX, -FLT_MAX }; char str[256]; for (unsigned int n = 0; n < obj.subobjects.size(); ++n) { const SubObject& subobj = obj.subobjects[n]; for (unsigned int k = 0; k < subobj.verts.size(); ++k) { const Vertex& vert = subobj.verts[k]; const Vec3& pos = positions[vert.pos]; minExtents.x = min(minExtents.x, pos.x); minExtents.y = min(minExtents.y, pos.y); minExtents.z = min(minExtents.z, pos.z); maxExtents.x = max(maxExtents.x, pos.x); maxExtents.y = max(maxExtents.y, pos.y); maxExtents.z = max(maxExtents.z, pos.z); } } Vec3 center = { (maxExtents.x + minExtents.x) * 0.5f, minExtents.y, (maxExtents.z + minExtents.z) * 0.5f }; std::string objFilename = "output/" + obj.name + ".obj"; createDirectoryTreeForFile(objFilename); std::ofstream objFile(objFilename); assert(objFile.is_open()); int posCount = 0; int uvCount = 0; int normCount = 0; for (unsigned int n = 0; n < obj.subobjects.size(); ++n) { const SubObject& subobj = obj.subobjects[n]; // Build the obj file int posStart = INT_MAX; int posEnd = 0; int uvStart = INT_MAX; int uvEnd = 0; int normStart = INT_MAX; int normEnd = 0; for (unsigned int k = 0; k < subobj.verts.size(); ++k) { const Vertex& vert = subobj.verts[k]; posStart = min(posStart, vert.pos); posEnd = max(posEnd, vert.pos); uvStart = min(uvStart, vert.uv); uvEnd = max(uvEnd, vert.uv); normStart = min(normStart, vert.norm); normEnd = max(normEnd, vert.norm); } // write positions for (int k = posStart; k <= posEnd; ++k) { const Vec3& pos = positions[k]; sprintf_s(str, "v %f %f %f\n", (pos.x - center.x), (pos.y - center.y), (pos.z - center.z)); objFile.write(str, strlen(str)); } // write uvs for (int k = uvStart; k <= uvEnd; ++k) { const Vec2& uv = texcoords[k]; sprintf_s(str, "vt %f %f\n", uv.x, uv.y); objFile.write(str, strlen(str)); } // write normals for (int k = normStart; k <= normEnd; ++k) { const Vec3& normal = normals[k]; sprintf_s(str, "vn %f %f %f\n", normal.x, normal.y, normal.z); objFile.write(str, strlen(str)); } // write material to use for this subobject std::string materialName = sceneName + "/" + subobj.material; sprintf_s(str, "usemtl %s\n", materialName.c_str()); objFile.write(str, strlen(str)); // write faces for (unsigned int k = 0; k < subobj.verts.size(); k += 3) { const Vertex& vert1 = subobj.verts[k + 0]; const Vertex& vert2 = subobj.verts[k + 1]; const Vertex& vert3 = subobj.verts[k + 2]; sprintf_s(str, "f %d/%d/%d %d/%d/%d %d/%d/%d\n", posCount + (vert1.pos - posStart + 1), uvCount + (vert1.uv - uvStart + 1), normCount + (vert1.norm - normStart + 1), posCount + (vert2.pos - posStart + 1), uvCount + (vert2.uv - uvStart + 1), normCount + (vert2.norm - normStart + 1), posCount + (vert3.pos - posStart + 1), uvCount + (vert3.uv - uvStart + 1), normCount + (vert3.norm - normStart + 1)); objFile.write(str, strlen(str)); } posCount += (posEnd - posStart) + 1; uvCount += (uvEnd - uvStart) + 1; normCount += (normEnd - normStart) + 1; } objFile.close(); // Add instance to scene Json::Value& jObj = jSceneObjects.append(Json::objectValue); jObj["model"] = sceneName + "/" + obj.name; Json::Value& jPos = jObj["position"] = Json::arrayValue; jPos[0] = center.x; jPos[1] = center.y; jPos[2] = center.z; Json::Value& jRot = jObj["rotation"] = Json::arrayValue; jRot[0] = 0.f; jRot[1] = 0.f; jRot[2] = 0.f; Json::Value& jScale = jObj["scale"] = Json::arrayValue; jScale[0] = 1.f; jScale[1] = 1.f; jScale[2] = 1.f; } std::ofstream sceneFile("output/" + sceneName + ".scene"); jsonWriter.write(sceneFile, jSceneRoot); }
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" ); } }
bool MeshManager::importObjMesh(const char* filename) { QElapsedTimer timer; timer.start(); QFile objFile(filename); if (!objFile.open(QIODevice::ReadOnly | QIODevice::Text)) { std::cerr << "could not find file: " << filename; return false; } QTextStream stream(&objFile); std::shared_ptr<GenericDataArray<float> > vertices = std::make_shared<GenericDataArray<float> >(); std::shared_ptr<GenericDataArray<unsigned int> > faces = std::make_shared<GenericDataArray<unsigned int> >(); std::shared_ptr<GenericDataArray<float> > uniqueNormals = std::make_shared<GenericDataArray<float> >(); std::vector<int> normalIndices; while (!stream.atEnd()) { QString linePrefix; stream >> linePrefix; QString line(stream.readLine()); if (linePrefix != "#") { QStringList elements = line.split(' ', QString::SkipEmptyParts); //read vertices if (linePrefix == "v") { GenericDataArray<float>::value_type vertexPosition; vertexPosition[0] = elements.takeFirst().toFloat(); vertexPosition[1] = elements.takeFirst().toFloat(); vertexPosition[2] = elements.takeFirst().toFloat(); vertices->push_back(vertexPosition); } //read normals if (linePrefix == "vn") { GenericDataArray<float>::value_type normal; normal[0] = elements.takeFirst().toFloat(); normal[1] = elements.takeFirst().toFloat(); normal[2] = elements.takeFirst().toFloat(); uniqueNormals->push_back(normal); } //read faces else if (linePrefix == "f"){ GenericDataArray<unsigned int>::value_type face; int i = 0; while (!elements.isEmpty() && i < 3) { QStringList faceElements = elements.takeFirst().split('/', QString::SkipEmptyParts); if (faceElements.size() == 2) { face[i] = faceElements.takeFirst().toInt() - 1; normalIndices.push_back(faceElements.takeFirst().toInt() - 1); } else { face[i] = faceElements.takeFirst().toInt() - 1; } ++i; } faces->push_back(face); } } } std::shared_ptr<GenericDataArray<float> > normals; //rearrange normals so that they can be accessed by the same index as vertices if (!uniqueNormals->empty()) { normals = std::make_shared<GenericDataArray<float> >(vertices->length()); for (unsigned int i = 0; i < faces->length(); ++i) { for (unsigned int j = 0; j < 3; ++j) { int vertexIndex = faces->at(i, j); int normalIndex = normalIndices[i * 3 + j]; normals->at(vertexIndex) = uniqueNormals->at(normalIndex); } } } else { normals = generateNormals(vertices, faces); } m_geomRoot = std::make_shared<sg::GroupNode>(); m_geomRoot->addChild(createGeometryNode(vertices, normals, faces)); std::cout << "Time: " << timer.elapsed() / 1000.0 << std::endl; std::cout << "Vertices: " << vertices->length() << std::endl; std::cout << "Faces: " << faces->length() << std::endl; return true; }
// CreateDynamicObjectNode //------------------------------------------------------------------------------ bool ObjectListNode::CreateDynamicObjectNode( NodeGraph & nodeGraph, Node * inputFile, const AString & baseDir, bool isUnityNode, bool isIsolatedFromUnityNode ) { const AString & fileName = inputFile->GetName(); // Transform src file to dst object path // get file name only (no path, no ext) const char * lastSlash = fileName.FindLast( NATIVE_SLASH ); lastSlash = lastSlash ? ( lastSlash + 1 ) : fileName.Get(); const char * lastDot = fileName.FindLast( '.' ); lastDot = lastDot && ( lastDot > lastSlash ) ? lastDot : fileName.GetEnd(); // if source comes from a directory listing, use path relative to dirlist base // to replicate the folder hierearchy in the output AStackString<> subPath; if ( baseDir.IsEmpty() == false ) { ASSERT( NodeGraph::IsCleanPath( baseDir ) ); if ( PathUtils::PathBeginsWith( fileName, baseDir ) ) { // ... use everything after that subPath.Assign( fileName.Get() + baseDir.GetLength(), lastSlash ); // includes last slash } } else { if ( !m_BaseDirectory.IsEmpty() && PathUtils::PathBeginsWith( fileName, m_BaseDirectory ) ) { // ... use everything after that subPath.Assign( fileName.Get() + m_BaseDirectory.GetLength(), lastSlash ); // includes last slash } } AStackString<> fileNameOnly( lastSlash, lastDot ); AStackString<> objFile( m_CompilerOutputPath ); objFile += subPath; objFile += m_CompilerOutputPrefix; objFile += fileNameOnly; objFile += GetObjExtension(); // Create an ObjectNode to compile the above file // and depend on that Node * on = nodeGraph.FindNode( objFile ); if ( on == nullptr ) { // determine flags - TODO:B Move DetermineFlags call out of build-time const bool usingPCH = ( m_PrecompiledHeader != nullptr ); uint32_t flags = ObjectNode::DetermineFlags( m_Compiler, m_CompilerArgs, false, usingPCH ); if ( isUnityNode ) { flags |= ObjectNode::FLAG_UNITY; } if ( isIsolatedFromUnityNode ) { flags |= ObjectNode::FLAG_ISOLATED_FROM_UNITY; } uint32_t preprocessorFlags = 0; if ( m_Preprocessor ) { // determine flags - TODO:B Move DetermineFlags call out of build-time preprocessorFlags = ObjectNode::DetermineFlags( m_Preprocessor, m_PreprocessorArgs, false, usingPCH ); } on = nodeGraph.CreateObjectNode( objFile, inputFile, m_Compiler, m_CompilerArgs, m_CompilerArgsDeoptimized, m_PrecompiledHeader, flags, m_CompilerForceUsing, m_DeoptimizeWritableFiles, m_DeoptimizeWritableFilesWithToken, m_AllowDistribution, m_AllowCaching, m_Preprocessor, m_PreprocessorArgs, preprocessorFlags ); } else if ( on->GetType() != Node::OBJECT_NODE ) { FLOG_ERROR( "Node '%s' is not an ObjectNode (type: %s)", on->GetName().Get(), on->GetTypeName() ); return false; } else { ObjectNode * other = on->CastTo< ObjectNode >(); if ( inputFile != other->GetSourceFile() ) { FLOG_ERROR( "Conflicting objects found:\n" " File A: %s\n" " File B: %s\n" " Both compile to: %s\n", inputFile->GetName().Get(), other->GetSourceFile()->GetName().Get(), objFile.Get() ); return false; } } m_DynamicDependencies.Append( Dependency( on ) ); return true; }
//parse file, send vertices and indices to node's mesh using setVertices and setIndices objLoader::objLoader(string file, Node* node) { ifstream objFile(file); if (!objFile.is_open()) { cout << "Could not open obj file." << endl; } else { //only need to handle the lines starting with v/vn/f while (!objFile.eof()) { std::string line; std::getline(objFile, line); if (line.size() > 0) { // vertices if (line[0] == 'v' && line[1] == ' ') { float vx, vy, vz; sscanf_s(line.c_str() + 2, "%f %f %f", &vx, &vy, &vz); vertices_obj.push_back(glm::vec3(vx, vy, vz)); } // normals if (line[0] == 'v' && line[1] == 'n') { float nx, ny, nz; sscanf_s(line.c_str() + 3, "%f %f %f", &nx, &ny, &nz); normals_obj.push_back(glm::vec3(nx, ny, nz)); } // triangular faces: v/vt, v/vt/vn, or v//vn if (line[0] == 'f') { //f v/vt v/vt v/vt if (count(line.begin(), line.end(), '/') == 3) { int v1, v2, v3; int t1, t2, t3; sscanf_s(line.c_str() + 2, "%i/%i %i/%i %i/%i", &v1, &t1, &v2, &t2, &v3, &t3); indices_obj.push_back(v1-1); indices_obj.push_back(v2-1); indices_obj.push_back(v3-1); } else { std::size_t found = line.find("//"); //f v/vt/vn v/vt/vn v/vt/vn if (found == std::string::npos) { int v1, v2, v3; int t1, t2, t3; int n1, n2, n3; sscanf_s(line.c_str() + 2, "%f/%f/%f %f/%f/%f %f/%f/%f", &v1, &t1, &n1, &v2, &t2, &n2, &v3, &t3, &n3); indices_obj.push_back(v1-1); indices_obj.push_back(v2-1); indices_obj.push_back(v3-1); norm_indices_obj.push_back(n1-1); norm_indices_obj.push_back(n2-1); norm_indices_obj.push_back(n3-1); } //f v//vn v//vn v//vn else { int v1, v2, v3; int n1, n2, n3; sscanf_s(line.c_str() + 2, "%f//%f %f//%f %f//%f", &v1, &n1, &v2, &n2, &v3, &n3); indices_obj.push_back(v1-1); indices_obj.push_back(v2-1); indices_obj.push_back(v3-1); norm_indices_obj.push_back(n1-1); norm_indices_obj.push_back(n2-1); norm_indices_obj.push_back(n3-1); } } } } } } if (node->getGeometry()->getGeometryType() == 3) { Mesh* shape = new Mesh(); shape->setVertices(vertices_obj); shape->setIndices(indices_obj); shape->setNormIndices(norm_indices_obj); shape->buildGeometry(); node->setGeometry(shape); } }