#include "PlyConverter.h" #include "SimpleTri.h" #include "SimpleVec.h" #include "gzstream.h" #include #include "rply.h" using namespace std; static int sGlobalIndex = 0; VertexArray sVertices; VertexArray sNormals; FaceArray sFaces; PlyConverter::~PlyConverter() { for (size_t i = 0; i < mGeometry.size(); ++ i) delete mGeometry[i]; mGeometry.clear(); } void PlyConverter::LoadShape(const VertexArray &vertices, const VertexArray &normals, const TexcoordArray &texcoords, const FaceArray &faces ) { Geometry *geom = new Geometry(); size_t idx = 0; for (size_t i = 0; i < faces.size(); ++ i) { if (i % 1000 == 0) cout << "converted " << i << " lines" << endl; Face face = faces[i]; if (faces[i].indices.empty()) cout << "error!!" << endl; //cout << "size: " << face.indices.size() << endl; for (int j = (int)face.indices.size() - 1; j >= 0; -- j) { //cout << "h " << j << " " << face.indices.size() << endl; SimpleVec h = vertices[face.indices[j]]; SimpleVec v; v.x = -h.x * 14; v.y = h.z * 14; v.z = h.y * 14; geom->mVertices.push_back(v); /*if (!normals.empty()) { for (int j = 0; j < 3; ++ j) faceNormals.push_back(Normalize(normals[nIndices[idx[j]]])); } else { // no face normals? => create normals const SimpleTri tri(vertices[indices[idx[0]]], vertices[indices[idx[1]]], vertices[indices[idx[2]]]); const SimpleVec n = tri.GetNormal(); faceNormals.push_back(n); faceNormals.push_back(n); faceNormals.push_back(n); }*/ } //cout << "idx: " << idx << " " << geom->mVertices.size() << endl; // no face normals? => create normals const SimpleTri tri(geom->mVertices[idx + 0], geom->mVertices[idx + 1], geom->mVertices[idx + 2]); const SimpleVec n = tri.GetNormal(); geom->mNormals.push_back(n); geom->mNormals.push_back(n); geom->mNormals.push_back(n); idx += faces[i].indices.size(); } mGeometry.push_back(geom); mNumShapes = 1; } bool PlyConverter::Convert(const string &filename, const std::string &outputFilename) { mNumShapes = 0; for (size_t i = 0; i < mGeometry.size(); ++ i) delete mGeometry[i]; mGeometry.clear(); if (!ReadFile(filename)) { cerr << "could not read file" << endl; return false; } if (!WriteFile(outputFilename)) { cerr << "could not write file" << endl; return false; } return true; } static int vertex_cb(p_ply_argument argument) { long eol; ply_get_argument_user_data(argument, NULL, &eol); static SimpleVec v; static int i = 0; v[i ++] = (float)ply_get_argument_value(argument); //printf("%g", ply_get_argument_value(argument)); if (eol) { sVertices.push_back(v); if (sVertices.size() % 10000 == 0) cout << "read in " << sVertices.size() << " vertices" << endl; i = 0; } return 1; } static int face_cb(p_ply_argument argument) { long length, value_index; ply_get_argument_property(argument, NULL, &length, &value_index); static Face face; switch (value_index) { case 0: case 1: //printf("here4 %g ", ply_get_argument_value(argument)); face.indices.push_back((int)ply_get_argument_value(argument)); break; case 2: //printf("here5 %g\n", ply_get_argument_value(argument)); face.indices.push_back((int)ply_get_argument_value(argument)); sFaces.push_back(face); if (sFaces.size() % 10000 == 0) cout << "read in " << sFaces.size() << " faces" << endl; face.indices.clear(); break; default: break; } return 1; } bool PlyConverter::ReadFile(const string &filename) { long nvertices, ntriangles; p_ply ply = ply_open(filename.c_str(), NULL); if (!ply) return 1; if (!ply_read_header(ply)) return 1; nvertices = ply_set_read_cb(ply, "vertex", "x", vertex_cb, NULL, 0); ply_set_read_cb(ply, "vertex", "y", vertex_cb, NULL, 0); ply_set_read_cb(ply, "vertex", "z", vertex_cb, NULL, 1); ntriangles = ply_set_read_cb(ply, "face", "vertex_indices", face_cb, NULL, 0); cout << "vertices: " << nvertices << endl; cout << "triangles: " << ntriangles << endl; if (!ply_read(ply)) return false; ply_close(ply); TexcoordArray texCoords; LoadShape(sVertices, sNormals, texCoords, sFaces); return true; } void PlyConverter::WriteGeometry(ogzstream &str, Geometry *geom) { size_t vertexCount = (int)geom->mVertices.size(); str.write(reinterpret_cast(&vertexCount), sizeof(int)); cout << "writing geometry" << endl; //SimpleVec vertices = new SimpleVec[vertexCount]; //for (size_t i = 0; i < vertexCount; ++ i) vertices[i] = geom->mVertices[i]; //for (size_t i = 0; i < vertexCount; ++ i) vertices[i] = geom->mNormals[i]; for (size_t i = 0; i < vertexCount; ++ i) str.write(reinterpret_cast(&geom->mVertices[i]), sizeof(SimpleVec)); for (size_t i = 0; i < vertexCount; ++ i) str.write(reinterpret_cast(&geom->mNormals[i]), sizeof(SimpleVec)); cout << "finished writing geometry" << endl; //if (texCoordCount) str.write(reinterpret_cast(geom->mTexcoords), sizeof(float) * texCoordCount * 2); int texCoordCount = 0; str.write(reinterpret_cast(&texCoordCount), sizeof(int)); //if (texCoordCount) str.write(reinterpret_cast(geom->mTexcoords), sizeof(float) * texCoordCount * 2); } bool PlyConverter::WriteFile(const string &filename) { ogzstream ofile(filename.c_str()); if (!ofile.is_open()) return false; mNumShapes = (int)mGeometry.size(); ///////// //-- write textures #ifdef USE_TEXTURE int textureCount = 1; #else int textureCount = 0; #endif ofile.write(reinterpret_cast(&textureCount), sizeof(int)); if (textureCount > 0) { // hack const string texName("wood.jpg"); int texnameSize = (int)texName.length() + 1; ofile.write(reinterpret_cast(&texnameSize), sizeof(int)); ofile.write(texName.c_str(), sizeof(char) * texnameSize); int boundS = 1, boundT = 1; ofile.write(reinterpret_cast(&boundS), sizeof(int)); ofile.write(reinterpret_cast(&boundT), sizeof(int)); } /////////// //-- write shapes ofile.write(reinterpret_cast(&mNumShapes), sizeof(int)); vector::const_iterator it, it_end = mGeometry.end(); for (it = mGeometry.begin(); it != it_end; ++ it) { WriteGeometry(ofile, *it); /////// //-- texture int texId = 0; ofile.write(reinterpret_cast(&texId), sizeof(int)); bool alphaTestEnabled = false; //bool cullFaceEnabled = false; bool cullFaceEnabled = true; ofile.write(reinterpret_cast(&alphaTestEnabled), sizeof(bool)); ofile.write(reinterpret_cast(&cullFaceEnabled), sizeof(bool)); // material bool hasMaterial = false; ofile.write(reinterpret_cast(&hasMaterial), sizeof(bool)); } int entityCount = 1; ofile.write(reinterpret_cast(&entityCount), sizeof(int)); ////////// //-- write single scene entity // no transformation bool hasTrafo = false; ofile.write(reinterpret_cast(&hasTrafo), sizeof(bool)); // a dummy lod int numLODs = 1; ofile.write(reinterpret_cast(&numLODs), sizeof(int)); float dist = 0; ofile.write(reinterpret_cast(&dist), sizeof(float)); ofile.write(reinterpret_cast(&mNumShapes), sizeof(int)); // all shapes belong to this scene entity for (int i = 0; i < mNumShapes; ++ i) { int shapeId = i; ofile.write(reinterpret_cast(&shapeId), sizeof(int)); } return true; }