/*BUG NOTES The standard function calls for inserting vertices don't work anymore. I've fixed points but everything beyond that has to be updated. */ #include "objJedi.h" #include "rtsvector3D.h" #include "rtspoint3D.h" #include //variable for use in global functions rtsOBJ g_OBJ; /********UTILITY METHODS*******************************/ void rtsOBJ::Scale(float scale_x, float scale_y, float scale_z) { vector::iterator i; for(i = v_list.begin(); i!= v_list.end(); i++) { (*i).x *= scale_x; (*i).y *= scale_y; (*i).z *= scale_z; } } void rtsOBJ::Translate(float trans_x, float trans_y, float trans_z) { vector::iterator i; for(i = v_list.begin(); i!= v_list.end(); i++) { (*i).x += trans_x; (*i).y += trans_y; (*i).z += trans_z; } } float rtsOBJ::GetDistance(float x, float y, float z) { //gets the distance between the specified point and the nearest surface of the OBJ //currently only works for lines //cout<<"Primitives: "< p0, p1, p2; double min_dist = 255; double dist, numerator, denominator; int p, l; vector3D v, w; double c1, c2, b; point3D Pb; //for each line for(l=0; l OBJ_POLYGON) return OBJ_ERROR; //otherwise, go ahead and set the mode g_CurrentMode = mode; //set the number of vertices to zero g_NumVertices = 0; //reset the current state primitive state current_primitive_mask = 0x0; return OBJ_OK; } OBJint rtsOBJ::objEnd() { OBJint error = OBJ_OK; //check to make sure the number of rendered vertices is valid for the current mode switch(g_CurrentMode) { case OBJ_NONE: //can't quit if we haven't started error = OBJ_ERROR; break; case OBJ_LINES: //if less than two vertices or an odd number of vertices if(g_NumVertices < 2 || g_NumVertices%2 != 0) { //if there wasn't a vertex at all if(g_NumVertices == 0) error = OBJ_ERROR; //if there was at least one vertex else { //pop the last line off the list primitives.pop_back(); lines.pop_back(); error = OBJ_ERROR; } } break; case OBJ_LINE_STRIP: //if less than two vertices if(g_NumVertices < 2) { //if there wasn't a vertex at all if(g_NumVertices == 0) error = OBJ_ERROR; //if there was at least one vertex else { //pop the last line off the list primitives.pop_back(); lines.pop_back(); error = OBJ_ERROR; } } break; case OBJ_LINE_LOOP: //if less than three vertices if(g_NumVertices < 3) { //pop the last line off the list primitives.pop_back(); lines.pop_back(); error = OBJ_ERROR; } //connect the first and last points else { error = f_TerminateLineLoop(); } break; case OBJ_TRIANGLES: //if less than three vertices or not a power of three if(g_NumVertices < 3 || g_NumVertices%3 !=0) { primitives.pop_back(); faces.pop_back(); error = OBJ_ERROR; } break; case OBJ_TRIANGLE_STRIP: //if less than three vertices if(g_NumVertices < 3) { primitives.pop_back(); faces.pop_back(); error = OBJ_ERROR; } break; case OBJ_TRIANGLE_FAN: //if less than three vertices if(g_NumVertices < 3) { primitives.pop_back(); faces.pop_back(); error = OBJ_ERROR; } break; case OBJ_QUADS: if(g_NumVertices < 4 || g_NumVertices%4 != 0) { primitives.pop_back(); faces.pop_back(); error = OBJ_ERROR; } break; case OBJ_QUAD_STRIP: //has to be at least 4 vertices and an even number if(g_NumVertices < 4 || g_NumVertices%2 != 0) { primitives.pop_back(); faces.pop_back(); error = OBJ_ERROR; } break; case OBJ_POLYGON: //has to be at least three vertices if(g_NumVertices < 3) { primitives.pop_back(); faces.pop_back(); error = OBJ_ERROR; } break; } //reset the attribute mask g_AttributeMask = 0x0; //just for closure, reset the attribute reset mask g_AttributeResetMask = 0x0; //stop rendering g_CurrentMode = OBJ_NONE; return error; } OBJint rtsOBJ::f_InsertVertexf(float x, float y, float z, float w, unsigned char mask) { //make sure we're rendering if(g_CurrentMode == OBJ_NONE) return OBJ_ERROR; //insert the vertex into the vertex vector vertex_position v; v.x = x; v.y = y; v.z=z; v.w=w; v.mask = mask; v_list.push_back(v); f_AdjustExtents(v); //set the bounding box //insert texture coordinate and normal if specified for this primitive if((current_primitive_mask & OBJ_VT) && (vt_changed)) vt_list.push_back(current_vt); if((current_primitive_mask & OBJ_VN) && (vn_changed)) vn_list.push_back(current_vn); //increment the number of vertices inserted g_NumVertices++; //handle each case of the vertex creation individually OBJint error = OBJ_OK; switch(g_CurrentMode) { case OBJ_POINTS: error = f_InsertPointVertex(); break; case OBJ_LINES: error = f_InsertLineVertex(); break; case OBJ_LINE_LOOP: error = f_InsertLineLoopVertex(); break; case OBJ_LINE_STRIP: error = f_InsertLineStripVertex(); break; case OBJ_TRIANGLES: error = f_InsertTriangleVertex(); break; case OBJ_TRIANGLE_STRIP: error = f_InsertTriangleStripVertex(); break; case OBJ_TRIANGLE_FAN: error = f_InsertTriangleFanVertex(); break; case OBJ_QUADS: error = f_InsertQuadVertex(); break; case OBJ_QUAD_STRIP: error = f_InsertQuadStripVertex(); break; case OBJ_POLYGON: error = f_InsertPolygonVertex(); break; } //set the reset mask to zero g_AttributeResetMask = 0x0; //set the attribute mask to include vertex position g_AttributeMask = g_AttributeMask | OBJ_V; //return the result of the insertion return error; } OBJint rtsOBJ::objVertex1f(float x) { return f_InsertVertexf(x, 0.0, 0.0, 0.0, OBJ_V_X); } OBJint rtsOBJ::objVertex2f(float x, float y) { return f_InsertVertexf(x, y, 0.0, 0.0, OBJ_V_X | OBJ_V_Y); } OBJint rtsOBJ::objVertex3f(float x, float y, float z) { return f_InsertVertexf(x, y, z, 0.0, OBJ_V_X | OBJ_V_Y | OBJ_V_Z); } OBJint rtsOBJ::objVertex4f(float x, float y, float z, float w) { return f_InsertVertexf(x, y, z, w, OBJ_V_X | OBJ_V_Y | OBJ_V_Z | OBJ_V_W); } OBJint rtsOBJ::objNormal3f(float i, float j, float k) { return f_InsertNormalf(i, j, k, OBJ_VN_I | OBJ_VN_J | OBJ_VN_K); } OBJint rtsOBJ::objNormal2f(float i, float j) { return f_InsertNormalf(i, j, 0.0, OBJ_VN_I | OBJ_VN_J); } OBJint rtsOBJ::objNormal1f(float i) { return f_InsertNormalf(i, 0.0, 0.0, OBJ_VN_I); } OBJint rtsOBJ::f_InsertNormalf(float i, float j, float k, unsigned char mask) { /*DEPRECATED //if the mode is not rendering faces, there is an error if(g_CurrentMode < OBJ_TRIANGLES) return OBJ_ERROR; //if the normal attribute flag is not set, set it (as long as a vertex hasn't been written) if(!(g_AttributeMask & OBJ_VN)) { //if a vertex has been rendered, then we can't change the attribute, so exit if(g_NumVertices > 0) return OBJ_ERROR; else //otherwise, just set the attribute flag g_AttributeMask = g_AttributeMask | OBJ_VN; } //insert the new normal into the normal list for the file vertex_normal new_vn; new_vn.i = i; new_vn.j = j; new_vn.k = k; new_vn.mask = mask; vn_list.push_back(new_vn); */ current_vn.i = i; //set the current texture state to the given coordinates current_vn.j = j; current_vn.k = k; current_vn.mask = mask; //set the mask as appropriate vn_changed = true; //the texture coordinate state has changed current_primitive_mask = current_primitive_mask | OBJ_VN; //the current primitive now uses texture coordinates (if it didn't previously) return OBJ_OK; } OBJint rtsOBJ::objTexCoord3f(float u, float v, float w) { return f_InsertTexCoordf(u, v, w, OBJ_VT_U | OBJ_VT_V | OBJ_VT_W); } OBJint rtsOBJ::objTexCoord2f(float u, float v) { return f_InsertTexCoordf(u, v, 0.0, OBJ_VT_U | OBJ_VT_V); } OBJint rtsOBJ::objTexCoord1f(float u) { return f_InsertTexCoordf(u, 0.0, 0.0, OBJ_VT_U); } OBJint rtsOBJ::f_InsertTexCoordf(float u, float v, float w, unsigned char mask) { /* DEPRECATED //if the normal attribute flag is not set, set it (as long as a vertex hasn't been written) if(!(g_AttributeMask & OBJ_VT)) { //if a vertex has been rendered, then we can't change the attribute, so exit if(g_NumVertices > 0) return OBJ_ERROR; else //otherwise, just set the attribute flag g_AttributeMask = g_AttributeMask | OBJ_VT; } //insert the new texture coordinate into the list for the file vertex_texture new_vt; new_vt.u = u; new_vt.v = v; new_vt.w = w; new_vt.mask = mask; vt_list.push_back(new_vt); */ current_vt.u = u; //set the current texture state to the given coordinates current_vt.v = v; current_vt.w = w; current_vt.mask = mask; //set the mask as appropriate vt_changed = true; //the texture coordinate state has changed current_primitive_mask = current_primitive_mask | OBJ_VT; //the current primitive now uses texture coordinates (if it didn't previously) return OBJ_OK; } void rtsOBJ::insertVertexPosition(float x, float y, float z, unsigned char mask) { vertex_position v; v.x = x; v.y = y; v.z = z; v.mask = mask; v_list.push_back(v); } void rtsOBJ::insertLine(unsigned int num_points, unsigned int* pointlist, unsigned int* normallist, unsigned int* texturelist) { //create the new primitive primitive line; line.type = OBJ_LINES; line.mask = 0; //set the mask based on the passed data if(pointlist != NULL) line.mask = line.mask | OBJ_V; if(normallist != NULL) line.mask = line.mask | OBJ_VN; if(texturelist != NULL) line.mask = line.mask | OBJ_VT; //insert the line int v; vertex new_vert; for(v=0; v 1) points.push_back(p_index); return OBJ_OK; } OBJint rtsOBJ::f_InsertLineVertex() { //if this is an odd vertex, create a new line if(g_NumVertices%2 == 1) { f_CreateNewLine(); } f_InsertNewLineVertex(); return OBJ_OK; } OBJint rtsOBJ::f_InsertLineLoopVertex() { //technically, this is the same as inserting a line strip vertex f_InsertLineStripVertex(); return OBJ_OK; } OBJint rtsOBJ::f_InsertLineStripVertex() { if(g_NumVertices == 1) { f_CreateNewLine(); } f_InsertNewLineVertex(); return OBJ_OK; } OBJint rtsOBJ::f_InsertTriangleVertex() { //if this is the first vertex in a triangle, create a new triangle if(g_NumVertices%3 == 1) { f_CreateNewFace(); } f_InsertNewFaceVertex(); return OBJ_OK; } OBJint rtsOBJ::f_InsertTriangleStripVertex() { //in the special case of the first three vertices, just create a triangle if(g_NumVertices <4) f_InsertTriangleVertex(); else { //create a new face for the new triangle f_CreateNewFace(); //insert the last two vertices from the previous triangle f_InsertPreviousFaceVertex(1); f_InsertPreviousFaceVertex(2); //insert the new vertex f_InsertNewFaceVertex(); } return OBJ_OK; } OBJint rtsOBJ::f_InsertTriangleFanVertex() { //in the special case of the first three vertices, just create a triangle if(g_NumVertices <4) f_InsertTriangleVertex(); else { //create a new face for the new triangle f_CreateNewFace(); //add the previous vertices to the face f_InsertFirstFaceVertex(0); f_InsertPreviousFaceVertex(2); //insert the current vertex f_InsertNewFaceVertex(); } return OBJ_OK; } OBJint rtsOBJ::f_InsertQuadVertex() { //if this is the first vertex in a quad, create a new quad if(g_NumVertices%4 == 1) { f_CreateNewFace(); } f_InsertNewFaceVertex(); return OBJ_OK; } OBJint rtsOBJ::f_InsertQuadStripVertex() { //in the case of one of the first four vertices, just create a quad if(g_NumVertices < 5) f_InsertQuadVertex(); //if the vertex is odd (it will be the third vertex of a quad) else if(g_NumVertices%2 == 1) { //create a new face for the new quad f_CreateNewFace(); //add the previous two vertices f_InsertPreviousFaceVertex(2); f_InsertPreviousFaceVertex(3); //add the current vertex f_InsertNewFaceVertex(); } else { //if this is the last vertex of the quad, just add it f_InsertNewFaceVertex(); } return OBJ_OK; } OBJint rtsOBJ::f_InsertPolygonVertex() { //if this is the first vertex, create the quad if(g_NumVertices == 1) { f_CreateNewFace(); } f_InsertNewFaceVertex(); return OBJ_OK; } OBJint rtsOBJ::f_InsertPreviousFaceVertex(unsigned int v_index) { /*Finds the vertex used in the previous face with the given index and inserts it into the current face. This limits the redundancy in the file for re-used vertices (in strips and fans). This also transfers texture and normal information.*/ //find the index of the previous face unsigned int prev_f_index = primitives.size() - 2; //find the index of the current face unsigned int f_index = prev_f_index +1; //add the vertex information from the previous face to this face primitives[f_index].p.push_back(primitives[prev_f_index].p[v_index]); return OBJ_OK; } OBJint rtsOBJ::f_InsertFirstFaceVertex(unsigned int v_index) { /*Finds the vertex used in the first face (since the last objBegin()) with the given index and inserts it at the end of the current face. This includes texture and normal information.*/ //The result depends on the type of face being rendered //So far, this function only applies to triangle fans if(g_CurrentMode != OBJ_TRIANGLE_FAN) return OBJ_ERROR; //calculate the number of faces that have been rendered unsigned int num_faces = g_NumVertices - 2; //find the index of the first face unsigned int first_f_index = primitives.size() - num_faces; //find the index of the current face unsigned int f_index = primitives.size() - 1; //transfer the vertex information from the first face to this one primitives[f_index].p.push_back(primitives[first_f_index].p[v_index]); return OBJ_OK; } OBJint rtsOBJ::f_InsertNewFaceVertex() { /*This inserts information about the current vertex into the current face*/ //find the new vertex index vertex p; p.v = v_list.size() -1; p.vt = vt_list.size() - 1; p.vn = vn_list.size() -1; //find the face index unsigned int f_index = primitives.size() -1; //INSERT VERTEX AND ATTRIBUTE DATA //just add the vertex to the face primitives[f_index].p.push_back(p); return OBJ_OK; } OBJint rtsOBJ::f_InsertNewLineVertex() { /*This inserts information about the current vertex into the current line*/ //find the new vertex index vertex p; p.v = v_list.size() -1; p.vt = vt_list.size() - 1; //find the line index unsigned int l_index = primitives.size() -1; //ADD VERTEX AND ATTRIBUTE INFORMATION //add the vertex to the line primitives[l_index].p.push_back(p); return OBJ_OK; } OBJint rtsOBJ::f_CreateNewFace() { primitive new_f; new_f.type = OBJ_FACE; new_f.mask = g_AttributeMask; faces.push_back(primitives.size()); primitives.push_back(new_f); return OBJ_OK; } OBJint rtsOBJ::f_CreateNewLine() { primitive new_l; new_l.type = OBJ_LINES; new_l.mask = g_AttributeMask; lines.push_back(primitives.size()); primitives.push_back(new_l); return OBJ_OK; } OBJint rtsOBJ::f_TerminateLineLoop() { /*This function just terminates the line loop by setting the last vertex to the first vertex.*/ if(g_CurrentMode != OBJ_LINE_LOOP) return OBJ_ERROR; //find the index for the current line unsigned int l_index = lines.size() -1; //insert the first vertex as the last vertex primitives[l_index].p.push_back(primitives[l_index].p[0]); return OBJ_OK; } void rtsOBJ::f_OutputVertices() { //get the number of vertices in the object unsigned int v_num = v_list.size(); for(unsigned int i=0; i>new_vertex.x; new_vertex.mask = OBJ_V_X; if(infile.peek() == ' ') { infile>>new_vertex.y; new_vertex.mask = new_vertex.mask | OBJ_V_Y; } if(infile.peek() == ' ') { infile>>new_vertex.z; new_vertex.mask = new_vertex.mask | OBJ_V_Z; } if(infile.peek() == ' ') { infile>>new_vertex.w; new_vertex.mask = new_vertex.mask | OBJ_V_W; } int c = infile.peek(); //ignore the rest of the line infile.ignore(1000, '\n'); c = infile.peek(); //cout<<"vertex read: "<>new_normal.i; new_normal.mask = OBJ_VN_I; //get every other component if(infile.peek() == ' ') { infile>>new_normal.j; new_normal.mask = new_normal.mask | OBJ_VN_J; } if(infile.peek() == ' ') { infile>>new_normal.k; new_normal.mask = new_normal.mask | OBJ_VN_K; } //ignore the rest of the line infile.ignore(1000, '\n'); //insert the normal vn_list.push_back(new_normal); return OBJ_OK; } OBJint rtsOBJ::f_ReadTexCoord(ifstream &infile) { vertex_texture new_texcoord; infile>>new_texcoord.u; new_texcoord.mask = OBJ_VT_U; //get every other component if(infile.peek() == ' ') { infile>>new_texcoord.v; new_texcoord.mask = new_texcoord.mask | OBJ_VT_V; } if(infile.peek() == ' ') { infile>>new_texcoord.w; new_texcoord.mask = new_texcoord.mask | OBJ_VT_W; } //ignore the rest of the line infile.ignore(1000, '\n'); //insert the texture coordinate vt_list.push_back(new_texcoord); return OBJ_OK; } OBJint rtsOBJ::f_ReadVertex(ifstream &infile, vertex &new_point, unsigned char &mask) { //store the line vertex infile>>new_point.v; new_point.v--; mask = OBJ_V; //new_face.v.push_back(new_v - 1); if(infile.peek() == '/') { infile.get(); //if there actually is a texcoord if(infile.peek() != '/') { infile>>new_point.vt; //get the index new_point.vt--; mask = mask | OBJ_VT; //update the mask //new_face.vt.push_back(new_vt - 1); } } //check for a normal if(infile.peek() == '/') { infile.get(); infile>>new_point.vn; //get the index new_point.vn--; mask = mask | OBJ_VN; //update the mask } return OBJ_OK; } OBJint rtsOBJ::f_ReadPrimitive(ifstream &infile, primitive_type type) { //create a new point list primitive new_primitive; new_primitive.type = type; //until the end of the line while(infile.peek() != '\n') { //read each point if(infile.peek() == ' ') infile.get(); else { vertex new_point; f_ReadVertex(infile, new_point, new_primitive.mask); new_primitive.p.push_back(new_point); } } //ignore the rest of the line infile.ignore(1000, '\n'); //push the id of the primitive into the new list //:DEBUG: if(type == OBJ_POINTS) points.push_back(primitives.size()); else if(type == OBJ_LINES) lines.push_back(primitives.size()); else if(type == OBJ_FACE) faces.push_back(primitives.size()); primitives.push_back(new_primitive); //push the new primitive return OBJ_OK; } OBJint rtsOBJ::f_AdjustExtents(vertex_position v) { if(v.x < m_bounds.min.x) m_bounds.min.x = v.x; if(v.y < m_bounds.min.y) m_bounds.min.y = v.y; if(v.z < m_bounds.min.z) m_bounds.min.z = v.z; if(v.x > m_bounds.max.x) m_bounds.max.x = v.x; if(v.y > m_bounds.max.y) m_bounds.max.y = v.y; if(v.z > m_bounds.max.z) m_bounds.max.z = v.z; return OBJ_OK; } OBJint rtsOBJ::f_LoadOBJ(const char* filename) { f_ClearAll(); //open the file as a stream ifstream infile; infile.open(filename); if(!infile.is_open()) return OBJ_ERROR; unsigned int vertices = 0; string token; infile>>token; while(!infile.eof()) { //if the token is some vertex property if(token == "v") f_ReadPosition(infile); else if(token == "vn") f_ReadNormal(infile); else if(token == "vt") f_ReadTexCoord(infile); else if(token == "p") f_ReadPrimitive(infile, OBJ_POINTS); else if(token == "l") f_ReadPrimitive(infile, OBJ_LINES); else if(token == "f") f_ReadPrimitive(infile, OBJ_FACE); else infile.ignore(9999, '\n'); //vertices++; infile>>token; } } OBJint rtsOBJ::f_LoadSWC(const char* filename) { f_ClearAll(); //open the file as a stream ifstream infile; infile.open(filename); if(!infile.is_open()) return OBJ_ERROR; vector swcVertices; float token; objBegin(OBJ_LINES); while(!infile.eof()) { vertex_position v; infile>>token; //get the id infile>>token; //get the fiber type infile>>v.x; //get the node position infile>>v.y; infile>>v.z; infile>>token; //get the radius infile>>token; //get the parent //insert the node into the swc vector swcVertices.push_back(v); //now draw the line from the parent to the current node if(token != -1) { objVertex3f(swcVertices[token-1].x, swcVertices[token-1].y, swcVertices[token-1].z); objVertex3f(v.x, v.y, v.z); } } objEnd(); return OBJ_OK; } OBJint rtsOBJ::LoadFile(const char* filename) { string strFilename = filename; int length = strFilename.length(); string extension = strFilename.substr(strFilename.length() - 3, 3); if(!extension.compare(string("obj"))) return f_LoadOBJ(filename); else if(!extension.compare(string("swc"))) return f_LoadSWC(filename); else return f_LoadOBJ(filename); } OBJint rtsOBJ::SaveFile(const char* filename) { //open the file as a stream ofstream outfile; outfile.open(filename); if(!outfile.is_open()) return OBJ_ERROR; //output vertex positions vector::iterator v; for(v=v_list.begin(); v!= v_list.end(); v++) { outfile<<"v"; if((*v).mask & OBJ_V_X) { outfile<<' '<<(*v).x; if((*v).mask & OBJ_V_Y) { outfile<<' '<<(*v).y; if((*v).mask & OBJ_V_Z) { outfile<<' '<<(*v).z; if((*v).mask & OBJ_V_W) outfile<<' '<<(*v).w; } } } outfile<<'\n'; } //output vertex texture coordinates vector::iterator vt; for(vt=vt_list.begin(); vt!= vt_list.end(); vt++) { outfile<<"vt"; if((*vt).mask & OBJ_VT_U) { outfile<<' '<<(*vt).u; if((*vt).mask & OBJ_VT_V) { outfile<<' '<<(*vt).v; if((*vt).mask & OBJ_VT_W) outfile<<' '<<(*vt).w; } } outfile<<'\n'; } //output vertex normal coordinates vector::iterator vn; for(vn=vn_list.begin(); vn!= vn_list.end(); vn++) { outfile<<"vn"; if((*vn).mask & OBJ_VN_I) { outfile<<' '<<(*vn).i; if((*vn).mask & OBJ_VN_J) { outfile<<' '<<(*vn).j; if((*vn).mask & OBJ_VN_K) outfile<<' '<<(*vn).k; } } outfile<<'\n'; } //output each primitive vector::iterator p; vector::iterator vert; for(p=primitives.begin(); p!= primitives.end(); p++) { switch((*p).type) { case OBJ_POINTS: outfile<<"p"; //output the points token break; case OBJ_LINES: outfile<<"l"; //output the lines token break; case OBJ_FACE: outfile<<"f"; //output the face token break; } //for each vertex in the list for the primitive for(vert = (*p).p.begin(); vert != (*p).p.end(); vert++) { outfile<<' '<<(*vert).v + 1; if((*p).mask & OBJ_VT) outfile<<'/'<<(*vert).vt + 1; if((*p).mask & OBJ_VN) { if(!((*p).mask & OBJ_VT)) outfile<<'/'; outfile<<'/'<<(*vert).vn + 1; } } outfile<<'\n'; } } //get methods unsigned int rtsOBJ::getNumVertices(){return v_list.size();} unsigned int rtsOBJ::getNumLines(){return lines.size();} unsigned int rtsOBJ::getNumFaces(){return faces.size();} unsigned int rtsOBJ::getNumPointLists(){return points.size();} unsigned int rtsOBJ::getNumTexCoords(){return vt_list.size();} unsigned int rtsOBJ::getNumNormals(){return vn_list.size();} //these functions return the coordinate index as well as the value unsigned int rtsOBJ::getNumFaceVertices(unsigned int face){return primitives[face].p.size();} unsigned int rtsOBJ::getFaceVertex(unsigned int face, unsigned int vertex){return primitives[face].p[vertex].v;} unsigned int rtsOBJ::getFaceNormal(unsigned int face, unsigned int normal){return primitives[face].p[normal].vn;} unsigned int rtsOBJ::getFaceTexCoord(unsigned int face, unsigned int texcoord){return primitives[face].p[texcoord].vt;} unsigned int rtsOBJ::getNumLineVertices(unsigned int line){return primitives[line].p.size();} unsigned int rtsOBJ::getLineVertex(unsigned int line, unsigned int vertex){return primitives[line].p[vertex].v;} unsigned int rtsOBJ::getLineTexCoord(unsigned int line, unsigned int texcoord){return primitives[line].p[texcoord].vt;} point3D rtsOBJ::getVertex3d(unsigned int index) { return point3D(v_list[index].x, v_list[index].y, v_list[index].z); } point3D rtsOBJ::getTexCoord3d(unsigned int index) { return point3D(vt_list[index].u, vt_list[index].v, vt_list[index].w); } point3D rtsOBJ::getNormal3d(unsigned int index) { return point3D(vn_list[index].i, vn_list[index].j, vn_list[index].k); } vertex_position rtsOBJ::getVertex(unsigned int index){return v_list[index];} vertex_texture rtsOBJ::getTexCoord(unsigned int index){return vt_list[index];} vertex_normal rtsOBJ::getNormal(unsigned int index){return vn_list[index];} unsigned int rtsOBJ::getPrimitiveType(unsigned int primitive) { /* switch(primitives[i].type) { case OBJ_POINTS: return OBJ_POINTS; break; case OBJ_LINES: return OBJ_LINES; break; case OBJ_FACE: f_RenderFace(i); break; }*/ return 0; } /****************************************************/ /*******Iterator Methods*****************************/ /****************************************************/ rtsOBJ::iterator rtsOBJ::begin() { //create an iterator that will be returned and assign it to this OBJ iterator result; result.obj = this; result.end_object = false; result.end_primitive = false; //if there are no primitives, return the end iterator if(primitives.size() == 0) return end(); //start at the beginning of the primitive array result.primitive_index = 0; return result; } rtsOBJ::iterator rtsOBJ::end() { //create an end iterator to return iterator result; result.obj = this; result.end_primitive = true; result.primitive_index = result.obj->primitives.size(); return result; } void rtsOBJ::iterator::operator++() { primitive_index++; if(primitive_index >= obj->primitives.size()) (*this) = obj->end(); } bool rtsOBJ::iterator::operator ==(rtsOBJ::iterator operand) { if(operand.primitive_index == primitive_index) return true; else return false; } bool rtsOBJ::iterator::operator !=(rtsOBJ::iterator operand) { if(operand.primitive_index != primitive_index) return true; else return false; } unsigned int rtsOBJ::iterator::operator*() { return primitive_index; } void rtsOBJ::iterator::print() { cout<<"This is a test"<