Created
April 24, 2014 16:33
-
-
Save tgfrerer/11260871 to your computer and use it in GitHub Desktop.
ofMesh::load (modified to deal with more general .ply files)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//-------------------------------------------------------------- | |
void ofMesh::load(string path){ | |
ofFile is(path, ofFile::ReadOnly); | |
ofMesh& data = *this; | |
string line; | |
string error; | |
ofBuffer buffer(is); | |
ofMesh backup = data; | |
int orderVertices=-1; | |
int orderIndices=-1; | |
int vertexCoordsFound=0; | |
int colorCompsFound=0; | |
int texCoordsFound=0; | |
int normalsCoordsFound=0; | |
int currentVertex = 0; | |
int currentFace = 0; | |
bool floatColor = false; | |
enum State{ | |
Header, | |
VertexDef, | |
FaceDef, | |
Vertices, | |
Normals, | |
Faces | |
}; | |
data.clear(); | |
State state = Header; | |
int lineNum = 0; | |
line = buffer.getFirstLine(); | |
lineNum++; | |
if(line!="ply"){ | |
error = "wrong format, expecting 'ply'"; | |
goto clean; | |
} | |
line = buffer.getNextLine(); | |
lineNum++; | |
if(line!="format ascii 1.0"){ | |
error = "wrong format, expecting 'format ascii 1.0'"; | |
goto clean; | |
} | |
while(!buffer.isLastLine()){ | |
line = buffer.getNextLine(); | |
lineNum++; | |
if(line.find("comment")==0){ | |
continue; | |
} | |
if((state==Header || state==FaceDef) && line.find("element vertex")==0){ | |
state = VertexDef; | |
orderVertices = MAX(orderIndices, 0)+1; | |
data.getVertices().resize(ofToInt(line.substr(15))); | |
continue; | |
} | |
if((state==Header || state==VertexDef) && line.find("element face")==0){ | |
state = FaceDef; | |
orderIndices = MAX(orderVertices, 0)+1; | |
data.getIndices().resize(ofToInt(line.substr(13))*3); | |
continue; | |
} | |
if(state==VertexDef && Poco::RegularExpression("^property float [xyzw]$").match(line)){ | |
vertexCoordsFound++; | |
continue; | |
} | |
if(state==VertexDef && Poco::RegularExpression("^property float [rgba]$").match(line)){ | |
colorCompsFound++; | |
data.getColors().resize(data.getVertices().size()); | |
floatColor = true; | |
continue; | |
} | |
if(state==VertexDef && Poco::RegularExpression("^property uchar (red)|(green)|(blue)$").match(line)){ | |
colorCompsFound++; | |
data.getColors().resize(data.getVertices().size()); | |
floatColor = false; | |
continue; | |
} | |
if(state==VertexDef && Poco::RegularExpression("^property float [uv]$").match(line)){ | |
texCoordsFound++; | |
data.getTexCoords().resize(data.getVertices().size()); | |
continue; | |
} | |
if(state==VertexDef && Poco::RegularExpression("^property float n[xyzw]$").match(line)){ | |
normalsCoordsFound++; | |
if (normalsCoordsFound==3) data.getNormals().resize(data.getVertices().size()); | |
continue; | |
} | |
if(state==FaceDef && line.find("property list")!=0 && line!="end_header"){ | |
error = "wrong face definition"; | |
goto clean; | |
} | |
if(line=="end_header"){ | |
if(data.hasColors() && colorCompsFound!=3 && colorCompsFound!=4){ | |
error = "data has color coordiantes but not correct number of components. Found " + ofToString(colorCompsFound) + " expecting 3 or 4"; | |
goto clean; | |
} | |
if(data.hasNormals() && normalsCoordsFound!=3){ | |
error = "data has normal coordiantes but not correct number of components. Found " + ofToString(normalsCoordsFound) + " expecting 3"; | |
goto clean; | |
} | |
if(!data.hasVertices()){ | |
ofLogWarning("ofMesh") << "load(): mesh loaded from \"" << path << "\" has no vertices"; | |
} | |
if(orderVertices==-1) orderVertices=9999; | |
if(orderIndices==-1) orderIndices=9999; | |
if(orderVertices < orderIndices){ | |
state = Vertices; | |
}else { | |
state = Faces; | |
} | |
continue; | |
} | |
if(state==Vertices){ | |
stringstream sline; | |
sline.str(line); | |
ofVec4f v; | |
sline >> v.x; | |
sline >> v.y; | |
if(vertexCoordsFound>2) sline >> v.z; | |
if(vertexCoordsFound==4) sline >> v.w; | |
data.getVertices()[currentVertex] = ofVec3f(v); | |
if(colorCompsFound>0){ | |
if (floatColor){ | |
ofFloatColor c; | |
sline >> c.r; | |
sline >> c.g; | |
sline >> c.b; | |
if(colorCompsFound>3) sline >> c.a; | |
data.getColors()[currentVertex] = c; | |
}else{ | |
int r, g, b, a = 255; | |
sline >> r; | |
sline >> g; | |
sline >> b; | |
if(colorCompsFound>3) sline >> a; | |
data.getColors()[currentVertex] = ofColor(r, g, b, a); | |
} | |
} | |
if(texCoordsFound>0){ | |
ofVec2f uv; | |
sline >> uv.x; | |
sline >> uv.y; | |
float dummy; | |
if (texCoordsFound > 2) sline >> dummy; | |
if (texCoordsFound > 3) sline >> dummy; | |
data.getTexCoords()[currentVertex] = uv; | |
} | |
if (normalsCoordsFound>0){ | |
ofVec3f n; | |
sline >> n.x; | |
sline >> n.y; | |
sline >> n.z; | |
float dummy; | |
if (normalsCoordsFound>3) sline >> dummy; | |
data.getNormals()[currentVertex] = n; | |
} | |
currentVertex++; | |
if(currentVertex==data.getNumVertices()){ | |
if(orderVertices<orderIndices){ | |
state = Faces; | |
}else{ | |
state = Vertices; | |
} | |
} | |
continue; | |
} | |
if(state==Faces){ | |
stringstream sline; | |
sline.str(line); | |
int numV; | |
sline >> numV; | |
if(numV!=3){ | |
error = "face not a triangle"; | |
goto clean; | |
} | |
int i; | |
sline >> i; | |
data.getIndices()[currentFace*3] = i; | |
sline >> i; | |
data.getIndices()[currentFace*3+1] = i; | |
sline >> i; | |
data.getIndices()[currentFace*3+2] = i; | |
currentFace++; | |
if(currentFace==data.getNumIndices()/3){ | |
if(orderVertices<orderIndices){ | |
state = Vertices; | |
}else{ | |
state = Faces; | |
} | |
} | |
continue; | |
} | |
} | |
return; | |
clean: | |
ofLogError("ofMesh") << "load(): " << lineNum << ":" << error; | |
ofLogError("ofMesh") << "load(): \"" << line << "\""; | |
data = backup; | |
} | |
void ofMesh::save(string path, bool useBinary) const{ | |
ofFile os(path, ofFile::WriteOnly); | |
const ofMesh& data = *this; | |
os << "ply" << endl; | |
if(useBinary) { | |
os << "format binary_little_endian 1.0" << endl; | |
} else { | |
os << "format ascii 1.0" << endl; | |
} | |
if(data.getNumVertices()){ | |
os << "element vertex " << data.getNumVertices() << endl; | |
os << "property float x" << endl; | |
os << "property float y" << endl; | |
os << "property float z" << endl; | |
if(data.getNumColors()){ | |
os << "property uchar red" << endl; | |
os << "property uchar green" << endl; | |
os << "property uchar blue" << endl; | |
os << "property uchar alpha" << endl; | |
} | |
if(data.getNumTexCoords()){ | |
os << "property float u" << endl; | |
os << "property float v" << endl; | |
} | |
if(data.getNumNormals()){ | |
os << "property float nx" << endl; | |
os << "property float ny" << endl; | |
os << "property float nz" << endl; | |
} | |
} | |
unsigned char faceSize = 3; | |
if(data.getNumIndices()){ | |
os << "element face " << data.getNumIndices() / faceSize << endl; | |
os << "property list uchar int vertex_indices" << endl; | |
} else if(data.getMode() == OF_PRIMITIVE_TRIANGLES) { | |
os << "element face " << data.getNumVertices() / faceSize << endl; | |
os << "property list uchar int vertex_indices" << endl; | |
} | |
os << "end_header" << endl; | |
for(int i = 0; i < data.getNumVertices(); i++){ | |
if(useBinary) { | |
os.write((char*) &data.getVertices()[i], sizeof(ofVec3f)); | |
} else { | |
os << data.getVertex(i).x << " " << data.getVertex(i).y << " " << data.getVertex(i).z; | |
} | |
if(data.getNumColors()){ | |
// VCG lib / MeshLab don't support float colors, so we have to cast | |
ofColor cur = data.getColors()[i]; | |
if(useBinary) { | |
os.write((char*) &cur, sizeof(ofColor)); | |
} else { | |
os << " " << (int) cur.r << " " << (int) cur.g << " " << (int) cur.b << " " << (int) cur.a; | |
} | |
} | |
if(data.getNumTexCoords()){ | |
if(useBinary) { | |
os.write((char*) &data.getTexCoords()[i], sizeof(ofVec2f)); | |
} else { | |
os << " " << data.getTexCoord(i).x << " " << data.getTexCoord(i).y; | |
} | |
} | |
if(data.getNumNormals()){ | |
if(useBinary) { | |
os.write((char*) &data.getNormals()[i], sizeof(ofVec3f)); | |
} else { | |
os << " " << data.getNormal(i).x << " " << data.getNormal(i).y << " " << data.getNormal(i).z; | |
} | |
} | |
if(!useBinary) { | |
os << endl; | |
} | |
} | |
if(data.getNumIndices()) { | |
for(int i = 0; i < data.getNumIndices(); i += faceSize) { | |
if(useBinary) { | |
os.write((char*) &faceSize, sizeof(unsigned char)); | |
for(int j = 0; j < faceSize; j++) { | |
int curIndex = data.getIndex(i + j); | |
os.write((char*) &curIndex, sizeof(int)); | |
} | |
} else { | |
os << (int) faceSize << " " << data.getIndex(i) << " " << data.getIndex(i+1) << " " << data.getIndex(i+2) << endl; | |
} | |
} | |
} else if(data.getMode() == OF_PRIMITIVE_TRIANGLES) { | |
for(int i = 0; i < data.getNumVertices(); i += faceSize) { | |
int indices[] = {i, i + 1, i + 2}; | |
if(useBinary) { | |
os.write((char*) &faceSize, sizeof(unsigned char)); | |
for(int j = 0; j < faceSize; j++) { | |
os.write((char*) &indices[j], sizeof(int)); | |
} | |
} else { | |
os << (int) faceSize << " " << indices[0] << " " << indices[1] << " " << indices[2] << endl; | |
} | |
} | |
} | |
//TODO: add index generation for other OF_PRIMITIVE cases | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment