00001 #include "ObjectLoader.h"
00002 #include "../objects/DynamicObject.h"
00003 #include "../objects/AffineObject.h"
00004 #include "../materials/DebugMaterial.h"
00005
00006 using namespace std;
00007
00008 namespace rcrt
00009 {
00010
00011 ObjectLoader::ObjectLoader(string path, MaterialLoader* mats):
00012 XMLLoader(path),materials(mats),material("debug"),initialised(false)
00013 {
00014 }
00015
00016 ObjectLoader::~ObjectLoader()
00017 {
00018 delete object;
00019 }
00020
00021 void ObjectLoader::init()
00022 {
00023 initialised = true;
00024
00025 nextStartTag("object");
00026 name = parser.getAttributeValue("","name");
00027 string animT = parser.getAttributeValue("","type");
00028 if(animT == "static")
00029 aType = STATIC;
00030 else if (animT == "affine")
00031 aType = AFFINE;
00032 else if (animT == "dynamic")
00033 aType = DYNAMIC;
00034 else{
00035 cout << "[ObjectLoader]: Object " << name <<" does not have a valid(static|affine|other) type: " << animT << endl;
00036 throw exception();
00037 }
00038
00039 initMaterials();
00040
00041
00042 switch(aType){
00043 case STATIC: initAffine(); break;
00044 case AFFINE: initAffine(); break;
00045 default:
00046 initDynamic();
00047 }
00048
00049 if(material == "debug" || materials == 0)
00050 object->setMaterial(new DebugMaterial());
00051 else{
00052 Material* mat = materials->getMaterial(material);
00053 if(mat)
00054 object->setMaterial(mat);
00055 else
00056 throw runtime_error(
00057 "[ObjectLoader]: Not a valid object file, material does not exist: "
00058 + material);
00059 }
00060
00061 }
00062
00063 void ObjectLoader::initMaterials()
00064 {
00065
00066
00067 string tagName = parser.getName();
00068 if(tagName != "object"){
00069 cout << "[ObjectLoader]: Logic error somewhere in ObjectLoader," <<
00070 " could not initialize materials: not on <object> tag" << endl;
00071 throw exception();
00072 }
00073 nextStartTag("");
00074 tagName = parser.getName();
00075 while(tagName == "mat"){
00076 material = parser.getAttributeValue("","name");
00077
00078 nextStartTag("");
00079 tagName = parser.getName();
00080 }
00081 }
00082
00083 void ObjectLoader::updateMesh()
00084 {
00085
00086 string tagName = parser.getName();
00087 if(tagName != "frame"){
00088 cout << "[ObjectLoader]: Either a logic error somewhere in ObjectLoader," <<
00089 " or not a valid object file: could not parse mesh: " <<
00090 "not on <frame> tag: " << tagName << endl;
00091 throw exception();
00092 }
00093
00094 nextStartTag("mesh");
00095 string mType = parser.getAttributeValue("","type");
00096 if(mType == "sphere"){
00097 nextStartTag("sph");
00098 float radius = convertTo<float>(parser.getAttributeValue("","r"));
00099 Point3D loc(convertTo<float>(parser.getAttributeValue("","x")),
00100 convertTo<float>(parser.getAttributeValue("","y")),
00101 convertTo<float>(parser.getAttributeValue("","z")));
00102 primitives.push_back(new Sphere(loc, radius, object));
00103 nextStartTag("");
00104 } else {
00105 nextStartTag("verts");
00106 nextStartTag("v");
00107 tagName = parser.getName();
00108 unsigned int i = 0;
00109 while(tagName == "v"){
00110 Point3D loc(convertTo<float>(parser.getAttributeValue("","x")),
00111 convertTo<float>(parser.getAttributeValue("","y")),
00112 convertTo<float>(parser.getAttributeValue("","z")));
00113 if(i < vertices.size())
00114 vertices.at(i).setPos(loc);
00115 else
00116 vertices.push_back(Vertex(loc));
00117 nextStartTag("");
00118 tagName = parser.getName();
00119 if(tagName == "no"){
00120 Vec3D vec(convertTo<float>(parser.getAttributeValue("","x")),
00121 convertTo<float>(parser.getAttributeValue("","y")),
00122 convertTo<float>(parser.getAttributeValue("","z")));
00123 vertices.at(i).setNormal(vec);
00124 nextStartTag("");
00125 tagName = parser.getName();
00126 }
00127 if(tagName == "uv"){
00128 Point2D uv(convertTo<float>(parser.getAttributeValue("","u")),
00129 convertTo<float>(parser.getAttributeValue("","v")));
00130 vertices.at(i).setUV(uv);
00131 nextStartTag("");
00132 tagName = parser.getName();
00133 }
00134 i++;
00135 }
00136 if(tagName != "faces"){
00137 cout << "[ObjectLoader]: Either a logic error somewhere in ObjectLoader," <<
00138 " or not a valid object file: could not parse mesh: " <<
00139 "no <faces> tag in frame: "<< currentFrame << endl;
00140 throw exception();
00141 }
00142 nextStartTag("tri");
00143 tagName = parser.getName();
00144 i = 0;
00145 while(tagName == "tri" && !eof){
00146 bool smooth = true;
00147 int sm = convertTo<int>(parser.getAttributeValue("","s"));
00148 if(sm == 0)
00149 smooth = false;
00150
00151
00152 int verts[3];
00153 nextStartTag("");
00154 tagName = parser.getName();
00155 for(int vertex = 0; vertex < 3; vertex++){
00156 if(tagName != "v"){
00157 cout << "[ObjectLoader]: Not a valid object file: could not parse mesh: " <<
00158 "not enough <v> tags in a tri in frame: "<< currentFrame << endl;
00159 throw exception();
00160 }
00161 int index = convertTo<int>(parser.getAttributeValue("","i"));
00162 if(i < tris.size())
00163 (*tris.at(i))[vertex] = &vertices.at(index);
00164 else
00165 verts[vertex] = index;
00166
00167 eof = !nextStartTag("");
00168 if(!eof) tagName = parser.getName();
00169 else break;
00170
00171 if(tagName == "uv"){
00172 Point2D uv(convertTo<float>(parser.getAttributeValue("","u")),
00173 convertTo<float>(parser.getAttributeValue("","v")));
00174 vertices.at(index).setUV(uv);
00175
00176 eof = !nextStartTag("");
00177 if(!eof) tagName = parser.getName();
00178 else break;
00179
00180 }
00181 }
00182 if(i >= tris.size()){
00183 tris.push_back(new Triangle(&vertices.at(verts[0]),
00184 &vertices.at(verts[1]),
00185 &vertices.at(verts[2]),object,smooth));
00186 primitives.push_back(tris.at(i));
00187 }
00188 i++;
00189 }
00190 }
00191
00192
00193 object->setPrimitives(&primitives);
00194 }
00195
00196 void ObjectLoader::updateMatrix()
00197 {
00198
00199 string tagName = parser.getName();
00200 if(tagName != "worldmatrix"){
00201 throw runtime_error(
00202 "[ObjectLoader]: Not a valid object file "+name+" : could not parse mesh: " +
00203 ("no <worldmatrix> tag in line: " + toString(parser.getLineNumber()) +
00204 " current tag: " + tagName));
00205 }
00206 float matrix[4][4];
00207 nextStartTag("");
00208 tagName = parser.getName();
00209 for(int r = 0; r < 4; r++){
00210 if(tagName != "matrow"){
00211 throw runtime_error(
00212 "[ObjectLoader]: Not a valid object file: could not parse mesh: " +
00213 ("not enough <matrow> tags in line: " + toString(parser.getLineNumber())));
00214 }
00215 nextStartTag("");
00216 tagName = parser.getName();
00217 for(int c = 0; c < 4; c++){
00218 if(tagName != "entry"){
00219 throw runtime_error(
00220 "[ObjectLoader]: Not a valid object file: could not parse mesh: " +
00221 ("not enough <entry> tags in line: " + toString(parser.getLineNumber())));
00222 }
00223 matrix[r][c] = convertTo<float>(parser.getAttributeValue("","val"));
00224
00225 eof = !nextStartTag("");
00226 if(!eof) tagName = parser.getName();
00227 else break;
00228 }
00229 }
00230 Matrix4D m;
00231 m = matrix;
00232 object->setWorldMatrix(m);
00233 }
00234
00235 void ObjectLoader::initAffine()
00236 {
00237 object = new AffineObject(name);
00238 updateMesh();
00239 updateMatrix();
00240 }
00241
00242 void ObjectLoader::initDynamic()
00243 {
00244 object = new DynamicObject(name);
00245 }
00246
00247 bool ObjectLoader::nextFrame()
00248 {
00249 if(!initialised)
00250 init();
00251
00252 int eventType = parser.getEventType();
00253 string tagName = parser.getName();
00254 if(eventType != XmlPullParser::START_TAG ||
00255 tagName != "frame"){
00256 eof = !nextStartTag("frame");
00257 }
00258 if(!eof) {
00259 currentFrame = convertTo<int>(parser.getAttributeValue("","no"));
00260 updateMesh();
00261 return true;
00262 } else {
00263 return false;
00264 }
00265
00266 }
00267
00268 bool ObjectLoader::goToFrame(const int& n)
00269 {
00270 if(!initialised)
00271 init();
00272
00273 switch(aType){
00274 case STATIC: currentFrame = n; return true;
00275 default:
00276 if(n < currentFrame)
00277 return false;
00278 if(n == currentFrame){
00279 return true;
00280 }
00281 string tagName = parser.getName();
00282 if(tagName == "frame")
00283 currentFrame = convertTo<int>(parser.getAttributeValue("","no"));
00284 while(currentFrame < n && !eof){
00285 eof = !nextStartTag("frame");
00286 currentFrame = convertTo<int>(parser.getAttributeValue("","no"));
00287 }
00288 if(!eof) {
00289 switch(aType){
00290 case DYNAMIC: updateMesh(); break;
00291 case AFFINE: nextStartTag("worldmatrix"); updateMatrix(); break;
00292 case STATIC: return true;
00293 }
00294 return true;
00295 } else {
00296 return false;
00297 }
00298 }
00299 }
00300
00301 Object* ObjectLoader::getObject()
00302 {
00303 return object;
00304 }
00305
00306 vector<Triangle*>* ObjectLoader::getTriangles()
00307 {
00308 return &tris;
00309 }
00310
00311 }