00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "vpmeshobject.h"
00026 #include <sstream>
00027 #include <cassert>
00028 #include <fstream>
00029
00030 using namespace std;
00031
00032 VPMeshObject::VPMeshObject()
00033 {
00034 }
00035
00036 VPMeshObject::VPMeshObject(const VPMeshObject& obj)
00037 {
00038 vertVec = obj.vertVec;
00039 vertCoordVec = obj.vertCoordVec;
00040 normVec = obj.normVec;
00041 normCoordVec = obj.normCoordVec;
00042 textCoordVec = obj.textCoordVec;
00043 meshList = obj.meshList;
00044 }
00045
00046 VPMeshObject& VPMeshObject::operator=(const VPMeshObject& obj)
00047 {
00048 vertVec = obj.vertVec;
00049 vertCoordVec = obj.vertCoordVec;
00050 normVec = obj.normVec;
00051 normCoordVec = obj.normCoordVec;
00052 textCoordVec = obj.textCoordVec;
00053 meshList = obj.meshList;
00054 return *this;
00055 }
00056
00057 void VPMeshObject::Clear()
00058 {
00059 vertVec.clear();
00060 vertCoordVec.clear();
00061 normVec.clear();
00062 normCoordVec.clear();
00063 textCoordVec.clear();
00064 meshList.clear();
00065 }
00066
00067 void VPMeshObject::SetMaterial(const VPMaterial& mat)
00068 {
00069 list<VPMesh>::iterator iter;
00070 for (iter = meshList.begin(); iter != meshList.end(); ++iter)
00071 iter->material = mat;
00072 }
00073
00074 void VPMeshObject::SetVertices(const std::vector<VPPoint4D>& vertexVec)
00075 {
00076 vertVec = vertexVec;
00077 meshList.clear();
00078 ComputeBoundingBox();
00079 ComputeRecursiveBoundingBox();
00080 }
00081
00082 void VPMeshObject::SetVertices(const char* vertexStr)
00083 {
00084 string valStr = vertexStr;
00085 istringstream iss(valStr);
00086 double x,y,z,w;
00087 bool notFinished = true;
00088 VPPoint4D point;
00089
00090 vertVec.clear();
00091 do {
00092 if (!(iss >> x >> y >> z))
00093 notFinished = false;
00094 else
00095 {
00096 if (!(iss >> w))
00097 {
00098 w = 1.0;
00099 iss.clear();
00100 }
00101 point.SetXYZW(x,y,z,w);
00102 vertVec.push_back(point);
00103 iss >> ws;
00104 iss.get();
00105 }
00106 } while (notFinished);
00107 meshList.clear();
00108 ComputeBoundingBox();
00109 ComputeRecursiveBoundingBox();
00110 }
00111
00112 void VPMeshObject::AddFace(const char* indexStr)
00113 {
00114 string valStr = indexStr;
00115 istringstream iss(valStr);
00116 unsigned int value;
00117 unsigned int thisFacesNormalIndex = normVec.size();
00118 VPMesh mesh;
00119
00120 mesh.type = VPMesh::POLYGON;
00121 while (iss >> value)
00122 {
00123 mesh.indexVec.push_back(value);
00124 mesh.normIndVec.push_back(thisFacesNormalIndex);
00125 }
00126 meshList.push_back(mesh);
00127
00128
00129
00130 VPPoint4D v1 = vertVec[mesh.indexVec[1]] - vertVec[mesh.indexVec[0]];
00131 VPPoint4D v2 = vertVec[mesh.indexVec[2]] - vertVec[mesh.indexVec[1]];
00132 v1.Normalize();
00133 v2.Normalize();
00134 VPPoint4D normal = v1.CrossProduct(v2);
00135 normVec.push_back(normal);
00136 }
00137
00138 void VPMeshObject::MakeBox(double minX, double maxX, double minY, double maxY, double minZ, double maxZ)
00139 {
00140 assert((minX <= maxX) && (minY <= maxY) && (minZ <= maxZ));
00141
00142
00143 double coordinateArray[] = { minX,minY,minZ,
00144 minX,maxY,minZ,
00145 maxX,maxY,minZ,
00146 maxX,minY,minZ,
00147 minX,minY,maxZ,
00148 minX,maxY,maxZ,
00149 maxX,maxY,maxZ,
00150 maxX,minY,maxZ,
00151 minX,minY,minZ,
00152 minX,maxY,minZ,
00153 maxX,maxY,minZ,
00154 maxX,minY,minZ,
00155 minX,minY,maxZ,
00156 minX,maxY,maxZ,
00157 maxX,maxY,maxZ,
00158 maxX,minY,maxZ,
00159 minX,minY,minZ,
00160 minX,maxY,minZ,
00161 maxX,maxY,minZ,
00162 maxX,minY,minZ,
00163 minX,minY,maxZ,
00164 minX,maxY,maxZ,
00165 maxX,maxY,maxZ,
00166 maxX,minY,maxZ };
00167 double* endOfCoordinateArray = coordinateArray + sizeof(coordinateArray)/sizeof(double);
00168 unsigned int indexArray[] = { 0,1,2,3,
00169 4,7,6,5,
00170 11,10,14,15,
00171 13,9,8,12,
00172 22,18,17,21,
00173 23,20,16,19 };
00174 double normalArray[] = { 0,0,-1, 0,0,-1, 0,0,-1, 0,0,-1,
00175 0,0,1, 0,0,1, 0,0,1, 0,0,1,
00176 -1,0,0, -1,0,0, 1,0,0, 1,0,0,
00177 -1,0,0, -1,0,0, 1,0,0, 1,0,0,
00178 0,-1,0, 0,1,0, 0,1,0, 0,-1,0,
00179 0,-1,0, 0,1,0, 0,1,0, 0,-1,0 };
00180 double* endOfNormalArray = normalArray + sizeof(normalArray)/sizeof(double);
00181 unsigned int* endOfIndexArray = indexArray + sizeof(indexArray)/sizeof(int);
00182 VPMesh mesh;
00183
00184 normCoordVec.clear();
00185 textCoordVec.clear();
00186 meshList.clear();
00187 vertCoordVec.assign(coordinateArray,endOfCoordinateArray);
00188 normCoordVec.assign(normalArray,endOfNormalArray);
00189 mesh.type = VPMesh::QUADS;
00190 mesh.indexVec.assign(indexArray,endOfIndexArray);
00191 mesh.material = VPMaterial::DARK_PLASTIC_GRAY();
00192 meshList.push_back(mesh);
00193 ComputeBoundingBox();
00194 ComputeRecursiveBoundingBox();
00195 }
00196
00197 void VPMeshObject::GetYProjection(std::list<VPPoint4D>* resultPtr, double height) const
00198
00199 {
00200 VPPoint4D point;
00201 resultPtr->clear();
00202 if (vertCoordVec.size() > 6)
00203 {
00204 unsigned int vertexVetEnd = vertCoordVec.size();
00205 for (unsigned int i=0; i < vertexVetEnd; i+=3)
00206 {
00207 point.SetXYZW(vertCoordVec[i],height,vertCoordVec[i+2],1);
00208 resultPtr->push_back(point);
00209 }
00210 }
00211 else
00212 {
00213 unsigned int vertexVetEnd = vertVec.size();
00214 for (unsigned int i=0; i < vertexVetEnd; ++i)
00215 {
00216 point.SetXYZW(vertVec[i].GetX(), height, vertVec[i].GetZ(), 1);
00217 resultPtr->push_back(point);
00218 }
00219 }
00220 }
00221
00222 void VPMeshObject::Optimize()
00223 {
00224
00225
00226 }
00227
00228 void VPMeshObject::ComputeBoundingBox() {
00229 if (vertCoordVec.size() > 0)
00230 {
00231
00232 bBox.SetBoundingBox(vertCoordVec[0], vertCoordVec[1], vertCoordVec[2],
00233 vertCoordVec[0], vertCoordVec[1], vertCoordVec[2]);
00234
00235 for (unsigned int i=3; i < vertCoordVec.size(); i+=3)
00236 bBox.ConditionalUpdate(vertCoordVec[i], vertCoordVec[i+1], vertCoordVec[i+2]);
00237 }
00238 else
00239 {
00240
00241 bBox.SetBoundingBox(vertVec[0].GetX(), vertVec[0].GetY(), vertVec[0].GetZ(),
00242 vertVec[0].GetX(), vertVec[0].GetY(), vertVec[0].GetZ());
00243
00244 for (unsigned int i=1; i < vertVec.size(); ++i)
00245 bBox.ConditionalUpdate(vertVec[i]);
00246 }
00247 }
00248
00249 void VPMeshObject::MergeWith(const VPMeshObject& obj) {
00250
00251 bool bothOptimized = vertVec.empty() && obj.vertVec.empty();
00252 list<VPMesh>::const_iterator iter = obj.meshList.begin();
00253 VPMesh mesh;
00254 unsigned int prevNumVertices;
00255 assert (bothOptimized || (vertCoordVec.empty() && obj.vertCoordVec.empty()));
00256
00257 prevNumVertices = (bothOptimized? (vertCoordVec.size()/3) : vertVec.size());
00258 for (; iter != obj.meshList.end(); ++iter)
00259 {
00260 mesh = *iter;
00261 mesh.IncrementIndices(prevNumVertices);
00262 meshList.push_back(mesh);
00263 }
00264
00265 vertVec.insert(vertVec.end(), obj.vertVec.begin(), obj.vertVec.end());
00266 vertCoordVec.insert(vertCoordVec.end(), obj.vertCoordVec.begin(), obj.vertCoordVec.end());
00267 normVec.insert(normVec.end(), obj.normVec.begin(), obj.normVec.end());
00268 normCoordVec.insert(normCoordVec.end(), obj.normCoordVec.begin(), obj.normCoordVec.end());
00269 textCoordVec.insert(textCoordVec.end(), obj.textCoordVec.begin(), obj.textCoordVec.end());
00270 ComputeBoundingBox();
00271 ComputeRecursiveBoundingBox();
00272 }
00273
00274 void VPMeshObject::Transform(const VPTransform& trans) {
00275 unsigned int i = 0;
00276 unsigned int size;
00277
00278 if (vertCoordVec.empty())
00279 {
00280 for (size = vertVec.size(); i < size; ++i)
00281 {
00282 trans.ApplyTo(&(vertVec[i]));
00283 }
00284 }
00285 else
00286 {
00287 VPPoint4D vertex;
00288 for (size = vertCoordVec.size(); i < size; i+=3)
00289 {
00290 vertex.SetXYZW(vertCoordVec[i],vertCoordVec[i+1],vertCoordVec[i+2],1);
00291 trans.ApplyTo(&vertex);
00292 vertCoordVec[i] = vertex.GetX();
00293 vertCoordVec[i+1] = vertex.GetY();
00294 vertCoordVec[i+2] = vertex.GetZ();
00295 }
00296 }
00297 ComputeBoundingBox();
00298 ComputeRecursiveBoundingBox();
00299 }
00300
00301 void VPMeshObject::ComputeTriangleNormal(const VPPoint4D& v1, const VPPoint4D& v2,
00302 const VPPoint4D& v3, VPPoint4D* resultPtr) {
00303 VPPoint4D edge1 = v2 - v1;
00304 VPPoint4D edge2 = v3 - v2;
00305
00306
00307 *resultPtr = -edge1.CrossProduct(edge2);
00308 resultPtr->Normalize();
00309 }
00310
00311 bool VPMeshObject::DrawInstanceOGL() const {
00312
00313
00314 #ifdef VP_OGL
00315 bool result = true;
00316 list<VPMesh>::const_iterator iter;
00317 if (show)
00318 {
00319 if (vertCoordVec.size() > 0)
00320 {
00321 glVertexPointer(3, GL_DOUBLE, 0, &vertCoordVec[0]);
00322 glNormalPointer(GL_DOUBLE, 0, &normCoordVec[0]);
00323 assert(vertCoordVec.size() == normCoordVec.size());
00324 for (iter = meshList.begin(); iter != meshList.end(); ++iter)
00325 {
00326 result &= iter->DrawInstanceOGL();
00327 }
00328 }
00329 else
00330 {
00331 unsigned int meshSize;
00332 unsigned int i;
00333 for (iter = meshList.begin(); iter != meshList.end(); ++iter)
00334 {
00335 iter->material.DrawOGL();
00336 glBegin(iter->GetOglType());
00337 meshSize = iter->indexVec.size();
00338 assert(meshSize == iter->normIndVec.size());
00339 for (i = 0; i < meshSize; ++i)
00340 {
00341 glNormal3dv(normVec[iter->normIndVec[i]].VetXYZW());
00342 glVertex4dv(vertVec[iter->indexVec[i]].VetXYZW());
00343 }
00344 glEnd();
00345 }
00346 }
00347 }
00348 return result;
00349 #else
00350 return false;
00351 #endif
00352 }
00353
00354 void VPMeshObject::ReadFromOBJ(const string& filename, list<VPMeshObject*>* resultPtr)
00355
00356
00357 {
00358 ifstream file(filename.c_str());
00359 istringstream iss;
00360 string line;
00361 string lineID;
00362 string name;
00363 string materialName;
00364 double x,y,z;
00365 map<string,VPMaterial> materialMap;
00366 vector<double> vertCoordTempVec;
00367 VPMeshObject* meshObjectPtr = NULL;
00368 VPMesh mesh;
00369 char slash;
00370 bool noVertexMemoryAllocated = true;
00371 unsigned int vi, ti, ni;
00372 unsigned int lastNormIndex = 1;
00373 unsigned int lastVertIndex = 1;
00374 unsigned int coordIndex, tempIndex;
00375 unsigned int faceCounter = 0;
00376
00377 cout << "Loading " << filename << "..." << flush;
00378 mesh.type = VPMesh::TRIANGLES;
00379 while (getline(file,line))
00380 {
00381 iss.clear();
00382 iss.str(line);
00383 iss >> lineID;
00384 if (lineID == "v")
00385 {
00386 iss >> x >> y >> z;
00387 vertCoordTempVec.push_back(x);
00388 vertCoordTempVec.push_back(y);
00389 vertCoordTempVec.push_back(z);
00390 }
00391 else if (lineID == "vn")
00392 {
00393 iss >> x >> y >> z;
00394 meshObjectPtr->normCoordVec.push_back(x);
00395 meshObjectPtr->normCoordVec.push_back(y);
00396 meshObjectPtr->normCoordVec.push_back(z);
00397 }
00398 else if (lineID == "f")
00399 {
00400 if (noVertexMemoryAllocated)
00401 {
00402 noVertexMemoryAllocated = false;
00403 meshObjectPtr->vertCoordVec.assign(meshObjectPtr->normCoordVec.size(),0);
00404 }
00405 while (iss >> vi >> slash >> ti >> slash >> ni)
00406 {
00407 coordIndex = 3 * (ni - lastNormIndex);
00408 tempIndex = 3 * (vi - lastVertIndex);
00409 meshObjectPtr->vertCoordVec[coordIndex++] = vertCoordTempVec[tempIndex];
00410 ++tempIndex;
00411 meshObjectPtr->vertCoordVec[coordIndex++] = vertCoordTempVec[tempIndex];
00412 ++tempIndex;
00413 meshObjectPtr->vertCoordVec[coordIndex] = vertCoordTempVec[tempIndex];
00414 mesh.indexVec.push_back(ni - lastNormIndex);
00415 }
00416 ++faceCounter;
00417 }
00418 else if (lineID == "vt")
00419 {
00420 }
00421 else if (lineID == "mtllib")
00422 {
00423 iss >> ws >> name;
00424 ReadMaterialTable(name, &materialMap);
00425 }
00426 else if (lineID == "o")
00427 {
00428
00429 if (mesh.indexVec.size() > 0)
00430 {
00431 meshObjectPtr->meshList.push_back(mesh);
00432 lastNormIndex += (meshObjectPtr->normCoordVec.size()/3);
00433 lastVertIndex += (vertCoordTempVec.size()/3);
00434 mesh.indexVec.clear();
00435 vertCoordTempVec.clear();
00436
00437 noVertexMemoryAllocated = true;
00438 }
00439
00440 iss >> ws >> name;
00441 meshObjectPtr = new VPMeshObject;
00442 meshObjectPtr->autoDelete = true;
00443 meshObjectPtr->SetDescription(name);
00444 resultPtr->push_back(meshObjectPtr);
00445 }
00446 else if (lineID == "usemtl")
00447 {
00448
00449 if (mesh.indexVec.size() > 0)
00450 {
00451 meshObjectPtr->meshList.push_back(mesh);
00452 mesh.indexVec.clear();
00453 mesh.normIndVec.clear();
00454 }
00455
00456 iss >> ws >> materialName;
00457 mesh.material = materialMap[materialName];
00458 }
00459 else if (lineID == "#")
00460 {
00461 }
00462 else
00463 cerr << "Error: unknown line ID: '" << lineID << "'" << endl;
00464 }
00465
00466 if (mesh.indexVec.size() > 0)
00467 {
00468 meshObjectPtr->meshList.push_back(mesh);
00469 }
00470
00471 list<VPMeshObject*>::iterator iter;
00472 for (iter = resultPtr->begin(); iter != resultPtr->end(); ++iter)
00473 {
00474 (*iter)->ComputeBoundingBox();
00475 (*iter)->ComputeRecursiveBoundingBox();
00476 }
00477 cout << " (" << faceCounter << " polygons)" << endl;
00478 }
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513 void VPMeshObject::ReadMaterialTable(const string& filename, map<string,VPMaterial>* matMapPtr)
00514
00515 {
00516 ifstream file(filename.c_str());
00517 istringstream iss;
00518 string line;
00519 string lineID;
00520 string materialName;
00521 VPMaterial material;
00522 float r,g,b;
00523 float value;
00524 unsigned int type;
00525
00526 material.SetEmissiveColor(VPColor::BLACK());
00527 while (getline(file,line))
00528 {
00529 iss.str(line);
00530 iss >> lineID;
00531 if (lineID == "newmtl")
00532 {
00533 if (materialName.size() > 0)
00534 matMapPtr->insert(make_pair(materialName,material));
00535 iss >> ws >> materialName;
00536 }
00537 else if (lineID == "Ns")
00538 {
00539 iss >> value;
00540
00541
00542 material.SetShininess(value*0.128);
00543 }
00544 else if (lineID == "Kd")
00545 {
00546 iss >> r >> g >> b;
00547 material.SetDiffuseColor(VPColor(static_cast<unsigned char>(r*255),
00548 static_cast<unsigned char>(g*255),
00549 static_cast<unsigned char>(b*255)));
00550 }
00551 else if (lineID == "Ka")
00552 {
00553 iss >> r >> g >> b;
00554 material.SetAmbientColor(VPColor(static_cast<unsigned char>(r*255),
00555 static_cast<unsigned char>(g*255),
00556 static_cast<unsigned char>(b*255)));
00557 }
00558 else if (lineID == "Ks")
00559 {
00560 iss >> r >> g >> b;
00561 material.SetSpecularColor(VPColor(static_cast<unsigned char>(r*255),
00562 static_cast<unsigned char>(g*255),
00563 static_cast<unsigned char>(b*255)));
00564 }
00565 else if ((lineID == "d") || (lineID == "Tr"))
00566 {
00567 iss >> value;
00568
00569 }
00570 else if (lineID == "illum")
00571 {
00572 iss >> type;
00573 if (type == 1)
00574 material.SetSpecularColor(VPColor::BLACK());
00575
00576 }
00577 else
00578 {
00579 cerr << "Error: unknown line ID: '" << lineID << "'" << endl;
00580 }
00581 iss.clear();
00582 }
00583
00584 if (materialName.size() > 0)
00585 matMapPtr->insert(make_pair(materialName,material));
00586 }