00001
00002 #include <stdexcept>
00003 #include <fstream>
00004 #include <sstream>
00005
00006 #include "OBJObject.h"
00007 #include "Triangle.h"
00008
00009 #include "SAHKDTree.h"
00010 #include "defines.h"
00011
00012
00015 struct FaceIdcs
00016 {
00017 int v[4];
00018 int vn[4];
00019 int vt[4];
00020
00021 FaceIdcs()
00022 {
00023 for (int i=0; i<4; i++)
00024 v[i] = vn[i] = vt[i] = 0;
00025 }
00026
00027 FaceIdcs(std::istream & aStream)
00028 {
00029 for (int i=0; i<4; i++)
00030 v[i] = vn[i] = vt[i] = 0;
00031
00032 char c;
00033 for(int i = 0; i < 3; i++)
00034 {
00035 aStream >> std::ws >> v[i] >> std::ws;
00036 if (aStream.peek() != '/')
00037 continue;
00038 aStream >> c >> std::ws;
00039 if (aStream.peek() == '/')
00040 {
00041 aStream >> c >> std::ws >> vn[i];
00042 continue;
00043 }
00044 else
00045 aStream >> vt[i];
00046 if (aStream.peek() != '/')
00047 continue;
00048 aStream >> c >> vn[i];
00049 }
00050 }
00051 };
00052
00053
00056 static Vec3f vec3fFromStream(std::istream & aStream)
00057 {
00058 float x, y, z;
00059 aStream >> x >> std::ws >> y >> std::ws >> z;
00060 return Vec3f(x, y, z);
00061 }
00062
00063
00066 static TexCoordinate texCoordinateFromStream(std::istream & aStream)
00067 {
00068 float x, y;
00069 aStream >> x >> std::ws >> y;
00070 return TexCoordinate(x, y);
00071 }
00072
00073
00074
00075
00076
00081 OBJObject::OBJObject(const std::string & fileName)
00082 : Object(false),
00083 mPrimitives(NULL),
00084 mKdTree(NULL)
00085 {
00086 LOG("Creating OBJ Object");
00087 mPrimitives = new std::vector<Primitive *>;
00088 read(fileName);
00089 }
00090
00091
00097 OBJObject::OBJObject(const OBJObject & other)
00098 : Object(other),
00099 mPrimitives(other.mPrimitives),
00100 mKdTree(other.mKdTree)
00101 {
00102 }
00103
00104
00107 OBJObject::~OBJObject()
00108 {
00109 if (*mRefCounter <= 1)
00110 {
00111
00112 std::vector<Primitive *>::iterator it = mPrimitives->begin();
00113 for (; it != mPrimitives->end(); ++it)
00114 delete *it;
00115 delete mPrimitives;
00116
00117
00118 delete mKdTree;
00119 }
00120 }
00121
00122
00125 void OBJObject::setShader(Shader * sh)
00126 {
00127 std::vector<Primitive *>::iterator it = mPrimitives->begin();
00128 for (; it != mPrimitives->end(); ++it)
00129 (*it)->setShader(sh);
00130 }
00131
00132
00135 void OBJObject::setCastShadows(bool b)
00136 {
00137 Object::setCastShadows(b);
00138
00139
00140 std::vector<Primitive *>::iterator it = mPrimitives->begin();
00141 for (; it != mPrimitives->end(); ++it)
00142 (*it)->setCastShadows(b);
00143 }
00144
00145
00151 void OBJObject::read(const std::string & fileName, const PrimitiveFactory & factory)
00152 {
00153 LOG("Parsing OBJFile : " << fileName);
00154
00155 std::ifstream ifile(fileName.c_str());
00156 std::vector<FaceIdcs> faces;
00157 std::vector<Vec3f> vert;
00158 std::vector<Vec3f> norm;
00159 std::vector<TexCoordinate> text;
00160
00161 if (!ifile)
00162 {
00163 LOG("Could not open file");
00164 throw ObjectFileOpenException(fileName);
00165 }
00166
00167
00168 while (!ifile.eof())
00169 {
00170
00171 std::string curLine;
00172 std::getline(ifile, curLine);
00173
00174
00175 std::istringstream issLine(curLine);
00176 std::string lineType;
00177 issLine >> std::ws >> lineType;
00178
00179
00180 if (lineType == "v")
00181 vert.push_back(vec3fFromStream(issLine));
00182 else if (lineType == "vn")
00183 norm.push_back(vec3fFromStream(issLine).normal());
00184 else if (lineType == "vt")
00185 text.push_back(texCoordinateFromStream(issLine));
00186 else if (lineType == "f")
00187 faces.push_back(issLine);
00188 else if (lineType == "#" || lineType == "")
00189 {
00190
00191 }
00192 else if (lineType == "o")
00193 {
00194 std::string data;
00195 issLine >> std::ws >> data;
00196 LOG("Reading object \"" << data << "\"");
00197 }
00198 else if (lineType == "g")
00199 {
00200 std::string data;
00201 issLine >> std::ws >> data;
00202 LOG("Found type \"" << lineType << "\" : sub-object group \"" << data << "\" : NOT USED YET");
00203 }
00204 else if (lineType == "usemtl")
00205 {
00206 std::string data;
00207 issLine >> std::ws >> data;
00208 LOG("Found type \"" << lineType << "\" : use material \"" << data << "\" : NOT USED YET");
00209 }
00210 else if (lineType == "mtllib")
00211 {
00212 std::string data;
00213 issLine >> std::ws >> data;
00214 LOG("Found type \"" << lineType << "\" : material file \"" << data << "\" : NOT USED YET");
00215 }
00216 else
00217 {
00218 LOG("Found unknown line Type \"" << lineType << "\"");
00219 }
00220 }
00221
00222
00223 for (std::vector<FaceIdcs>::iterator it = faces.begin(); it != faces.end(); ++it)
00224 {
00225 Vec3f v[3];
00226 Vec3f vn[3];
00227 TexCoordinate vt[3];
00228 for (int i = 0; i < 3; i++)
00229 {
00230 v[i] = vert[it->v[i] - 1];
00231 if (it->vn[i] >= 1 && it->vn[i] <= static_cast<int>(norm.size()))
00232 vn[i] = norm[it->vn[i] - 1];
00233 else if (it->vn[i] == 0)
00234 vn[i] = Vec3f();
00235 else
00236 {
00237 LOG("FUCK normal: it->vn[" << i << "] = " << it->vn[i] << " , norm.size() = " << norm.size());
00238 }
00239 if (it->vt[i] >= 1 && it->vt[i] <= static_cast<int>(text.size()))
00240 vt[i] = text[it->vt[i] - 1];
00241 else if (it->vt[i] == 0)
00242 vt[i] = TexCoordinate();
00243 else
00244 {
00245 LOG("FUCK texture: it->vt[" << i << "] = " << it->vt[i] << " , text.size() = " << text.size());
00246 }
00247 }
00248
00249
00250 mPrimitives->push_back(factory.create( Triangle(v[0], v[1], v[2]),
00251 vn[0], vn[1], vn[2],
00252 vt[0], vt[1], vt[2] ));
00253 }
00254
00255 buildAccelStructure();
00256
00257 LOG("Number of Vertices: " << (vert.size()) );
00258 LOG("Number of Triangles: " << mPrimitives->size() );
00259 LOG("Number of Faces: " << faces.size() );
00260 LOG("Number of Normals: " << norm.size() );
00261 LOG("Number of TexCoordinates: " << text.size() );
00262 LOG("Finished Parsing");
00263 }
00264
00265
00268 void OBJObject::calcBounds()
00269 {
00270 mBoundingBox.clear();
00271
00272 std::vector<Primitive *>::const_iterator it = mPrimitives->begin();
00273 for (; it != mPrimitives->end(); ++it)
00274 mBoundingBox.extend((*it)->bounds());
00275
00276 LOG("bb.min: " << mBoundingBox.minVertex() << " , bb.max: " << mBoundingBox.maxVertex());
00277 }
00278
00279
00282 void OBJObject::buildAccelStructure()
00283 {
00284
00285 calcBounds();
00286
00287
00288 delete mKdTree;
00289
00290 mKdTree = new SAHKDTree();
00291
00292
00293 mKdTree->buildTree(*mPrimitives, mBoundingBox);
00294 }
00295
00296