[3235] | 1 | #include "VisibilitySolutionConverter.h"
|
---|
[3241] | 2 | #include "Triangle3.h"
|
---|
| 3 | #include "Vector3.h"
|
---|
[3234] | 4 | #include "gzstream.h"
|
---|
| 5 | #include <iostream>
|
---|
[3239] | 6 | #include <queue>
|
---|
[3234] | 7 |
|
---|
| 8 |
|
---|
| 9 | using namespace std;
|
---|
| 10 |
|
---|
[3235] | 11 | // MAGIC of all bin exports
|
---|
| 12 | #ifndef MAGIC
|
---|
| 13 | #define MAGIC 0x827923
|
---|
| 14 | #endif
|
---|
[3234] | 15 |
|
---|
[3235] | 16 | #define BVH_VERSION 2.1
|
---|
[3234] | 17 |
|
---|
[3239] | 18 | #define TYPE_INTERIOR -2
|
---|
| 19 | #define TYPE_LEAF -3
|
---|
[3235] | 20 |
|
---|
[3239] | 21 | //const int maxVertices = 20000000;
|
---|
[3238] | 22 |
|
---|
| 23 |
|
---|
[3239] | 24 |
|
---|
[3238] | 25 | static string ReplaceSuffix(const string &str,
|
---|
| 26 | const string &a,
|
---|
| 27 | const string &b)
|
---|
| 28 | {
|
---|
| 29 | string result = str;
|
---|
| 30 |
|
---|
| 31 | int pos = (int)str.rfind(a, (int)str.size() - 1);
|
---|
| 32 | if (pos == str.size() - a.size())
|
---|
| 33 | {
|
---|
| 34 | result.replace(pos, a.size(), b);
|
---|
| 35 | }
|
---|
| 36 |
|
---|
| 37 | return result;
|
---|
| 38 | }
|
---|
| 39 |
|
---|
| 40 |
|
---|
[3234] | 41 | static void LoadIndices(char *str,
|
---|
| 42 | const VertexArray &vertices,
|
---|
| 43 | const VertexArray &normals,
|
---|
[3235] | 44 | const vector<pair<float, float> > &texCoords,
|
---|
[3234] | 45 | VertexArray &faceVertices,
|
---|
| 46 | VertexArray &faceNormals,
|
---|
[3235] | 47 | vector<TexCoord> &faceTexCoords
|
---|
[3234] | 48 | )
|
---|
| 49 | {
|
---|
| 50 | vector<string> triples;
|
---|
| 51 |
|
---|
| 52 | char *next_token;
|
---|
| 53 |
|
---|
| 54 | // extract the triples of the form v/t/n v/t/n ...
|
---|
| 55 | char *pch = strtok_s(str + 1, " ", &next_token);
|
---|
| 56 |
|
---|
| 57 | while (pch)
|
---|
| 58 | {
|
---|
| 59 | string s(pch);
|
---|
| 60 | //s += "\n",
|
---|
| 61 | triples.push_back(s);
|
---|
| 62 |
|
---|
| 63 | pch = strtok_s(NULL, " ", &next_token);
|
---|
| 64 | }
|
---|
| 65 |
|
---|
| 66 | vector<int> indices;
|
---|
| 67 | vector<int> nIndices;
|
---|
| 68 | vector<int> tIndices;
|
---|
| 69 |
|
---|
| 70 | char seps[] = " /\t\n";
|
---|
| 71 |
|
---|
| 72 | for (size_t i = 0; i < triples.size(); ++ i)
|
---|
| 73 | {
|
---|
| 74 | static int dummy = 0;
|
---|
| 75 |
|
---|
| 76 | size_t found;
|
---|
| 77 | found = triples[i].find_first_of(seps);
|
---|
| 78 | size_t prevfound = 0;
|
---|
| 79 | // vertex, normal, texture indices
|
---|
| 80 | string str = triples[i].substr(prevfound, found);
|
---|
| 81 |
|
---|
| 82 | int index = (int)strtol(str.c_str(), NULL, 10) - 1;
|
---|
| 83 |
|
---|
| 84 | int tIndex = index;
|
---|
| 85 | int nIndex = index;
|
---|
| 86 |
|
---|
| 87 | prevfound = found;
|
---|
| 88 | found = triples[i].find_first_of(seps, found + 1);
|
---|
| 89 |
|
---|
| 90 | if (found != string::npos)
|
---|
| 91 | {
|
---|
| 92 | str = triples[i].substr(prevfound, found);
|
---|
| 93 |
|
---|
| 94 | int idx = (int)strtol(str.c_str(), NULL, 10) - 1;
|
---|
| 95 | if (idx > 0) tIndex = idx;
|
---|
| 96 | }
|
---|
| 97 |
|
---|
| 98 | if ((found + 1) < triples[i].size())
|
---|
| 99 | {
|
---|
| 100 | str = triples[i].substr(found + 1);
|
---|
| 101 |
|
---|
| 102 | int idx = (int)strtol(str.c_str(), NULL, 10) - 1;
|
---|
| 103 | if (idx > 0) nIndex = idx;
|
---|
| 104 | }
|
---|
| 105 |
|
---|
| 106 | // store indices
|
---|
| 107 | if (index >= 0)
|
---|
| 108 | {
|
---|
| 109 | indices.push_back(index);
|
---|
| 110 | nIndices.push_back(nIndex);
|
---|
| 111 | tIndices.push_back(tIndex);
|
---|
| 112 | }
|
---|
| 113 |
|
---|
| 114 | // new triangle found
|
---|
| 115 | if (indices.size() > 2)
|
---|
| 116 | {
|
---|
| 117 | int idx1 = 0;
|
---|
| 118 | int idx2 = (int)indices.size() - 2;
|
---|
| 119 | int idx3 = (int)indices.size() - 1;
|
---|
[3238] | 120 |
|
---|
[3234] | 121 | faceVertices.push_back(vertices[indices[idx1]]);
|
---|
| 122 | faceVertices.push_back(vertices[indices[idx2]]);
|
---|
| 123 | faceVertices.push_back(vertices[indices[idx3]]);
|
---|
| 124 |
|
---|
| 125 |
|
---|
| 126 | if (!normals.empty())
|
---|
| 127 | {
|
---|
| 128 | faceNormals.push_back(normals[nIndices[idx1]]);
|
---|
| 129 | faceNormals.push_back(normals[nIndices[idx2]]);
|
---|
| 130 | faceNormals.push_back(normals[nIndices[idx3]]);
|
---|
| 131 | }
|
---|
| 132 | else
|
---|
| 133 | {
|
---|
| 134 | // no face normals? => create normals
|
---|
[3241] | 135 | const CHCDemoEngine::Triangle3
|
---|
| 136 | tri(vertices[indices[idx1]],
|
---|
| 137 | vertices[indices[idx2]],
|
---|
| 138 | vertices[indices[idx3]]);
|
---|
[3235] | 139 |
|
---|
[3241] | 140 | const CHCDemoEngine::Vector3 n = tri.GetNormal();
|
---|
[3234] | 141 |
|
---|
| 142 | faceNormals.push_back(n);
|
---|
| 143 | faceNormals.push_back(n);
|
---|
| 144 | faceNormals.push_back(n);
|
---|
| 145 | }
|
---|
| 146 |
|
---|
[3235] | 147 | if (!texCoords.empty())
|
---|
[3234] | 148 | {
|
---|
[3235] | 149 | faceTexCoords.push_back(texCoords[tIndices[idx1]]);
|
---|
| 150 | faceTexCoords.push_back(texCoords[tIndices[idx2]]);
|
---|
| 151 | faceTexCoords.push_back(texCoords[tIndices[idx3]]);
|
---|
[3234] | 152 | }
|
---|
| 153 | }
|
---|
| 154 | }
|
---|
| 155 | }
|
---|
| 156 |
|
---|
| 157 |
|
---|
[3235] | 158 | VisibilitySolutionConverter::VisibilitySolutionConverter()
|
---|
[3234] | 159 | {}
|
---|
| 160 |
|
---|
| 161 |
|
---|
[3235] | 162 | VisibilitySolutionConverter::~VisibilitySolutionConverter()
|
---|
[3234] | 163 | {
|
---|
| 164 | for (size_t i = 0; i < mGeometry.size(); ++ i)
|
---|
| 165 | {
|
---|
| 166 | delete [] mGeometry[i]->mVertices;
|
---|
| 167 | delete [] mGeometry[i]->mNormals;
|
---|
[3235] | 168 | delete [] mGeometry[i]->mTexCoords;
|
---|
[3234] | 169 |
|
---|
| 170 | delete mGeometry[i];
|
---|
| 171 | }
|
---|
| 172 |
|
---|
| 173 | mGeometry.clear();
|
---|
| 174 | }
|
---|
| 175 |
|
---|
| 176 |
|
---|
[3235] | 177 | void VisibilitySolutionConverter::LoadShape(const VertexArray &vertices,
|
---|
| 178 | const VertexArray &normals,
|
---|
| 179 | const vector<TexCoord> &texCoords)
|
---|
[3234] | 180 | {
|
---|
[3235] | 181 | int numElements = (int)vertices.size();
|
---|
[3234] | 182 | Geometry *geom = new Geometry();
|
---|
| 183 |
|
---|
| 184 | // convert the triangles to geometry
|
---|
[3241] | 185 | geom->mVertices = new CHCDemoEngine::Vector3[numElements];
|
---|
| 186 | geom->mNormals = new CHCDemoEngine::Vector3[numElements];
|
---|
[3235] | 187 | geom->mTexCoords = new TexCoord[numElements];
|
---|
[3234] | 188 |
|
---|
| 189 | geom->mVertexCount = numElements;
|
---|
[3235] | 190 | geom->mTexcoordCount = (int)texCoords.size();
|
---|
[3234] | 191 |
|
---|
[3238] | 192 | //cout << "number of vertices=" << numElements << endl;
|
---|
[3234] | 193 |
|
---|
| 194 | for (int i = 0; i < numElements; ++ i)
|
---|
| 195 | {
|
---|
| 196 | // convert to our camera system: change y and z
|
---|
[3235] | 197 | geom->mVertices[i].x = vertices[i].x;
|
---|
| 198 | geom->mVertices[i].y = -vertices[i].z;
|
---|
| 199 | geom->mVertices[i].z = vertices[i].y;
|
---|
[3234] | 200 |
|
---|
[3235] | 201 | geom->mNormals[i].x = normals[i].x;
|
---|
| 202 | geom->mNormals[i].y = -normals[i].z;
|
---|
| 203 | geom->mNormals[i].z = normals[i].y;
|
---|
[3234] | 204 |
|
---|
| 205 | if (i < geom->mTexcoordCount)
|
---|
| 206 | {
|
---|
[3235] | 207 | geom->mTexCoords[i].first = texCoords[i].first;
|
---|
| 208 | geom->mTexCoords[i].second = texCoords[i].second;
|
---|
[3234] | 209 | }
|
---|
| 210 | }
|
---|
| 211 |
|
---|
| 212 | mGeometry.push_back(geom);
|
---|
| 213 | }
|
---|
| 214 |
|
---|
| 215 |
|
---|
[3235] | 216 | bool VisibilitySolutionConverter::Convert(const std::string &sceneInputFilename,
|
---|
| 217 | const std::string &sceneOutputFilename,
|
---|
| 218 | const std::string &bvhInputFilename,
|
---|
| 219 | const std::string &bvhOutputFilename)
|
---|
[3234] | 220 | {
|
---|
| 221 | mNumShapes = 0;
|
---|
| 222 |
|
---|
[3235] | 223 | // delete previous geometry
|
---|
[3234] | 224 | for (size_t i = 0; i < mGeometry.size(); ++ i)
|
---|
| 225 | {
|
---|
| 226 | delete [] mGeometry[i]->mVertices;
|
---|
| 227 | delete [] mGeometry[i]->mNormals;
|
---|
[3235] | 228 | delete [] mGeometry[i]->mTexCoords;
|
---|
[3234] | 229 |
|
---|
| 230 | delete mGeometry[i];
|
---|
| 231 | }
|
---|
| 232 |
|
---|
| 233 | mGeometry.clear();
|
---|
| 234 |
|
---|
[3235] | 235 | if (!LoadSolution(bvhInputFilename))
|
---|
[3234] | 236 | {
|
---|
[3238] | 237 | cerr << "could not read solution file" << endl;
|
---|
[3234] | 238 | return false;
|
---|
| 239 | }
|
---|
| 240 |
|
---|
[3235] | 241 | if (!ReadScene(sceneInputFilename))
|
---|
[3234] | 242 | {
|
---|
[3235] | 243 | cerr << "could not read file" << endl;
|
---|
| 244 | return false;
|
---|
| 245 | }
|
---|
| 246 |
|
---|
[3241] | 247 | // update bvh bounding boxes with loaded geometry
|
---|
| 248 | UpdateNodeBox(mRoot);
|
---|
| 249 |
|
---|
| 250 | cout << "writing scene" << endl;
|
---|
| 251 |
|
---|
[3235] | 252 | if (!WriteScene(sceneOutputFilename))
|
---|
| 253 | {
|
---|
[3234] | 254 | cerr << "could not write file" << endl;
|
---|
| 255 | return false;
|
---|
| 256 | }
|
---|
| 257 |
|
---|
[3241] | 258 | cout << "writing bvh" << endl;
|
---|
| 259 |
|
---|
[3239] | 260 | if (!WriteBvh(bvhOutputFilename))
|
---|
[3235] | 261 | {
|
---|
[3239] | 262 | cerr << "could not write bvh!" << endl;
|
---|
[3235] | 263 | return false;
|
---|
[3239] | 264 | }
|
---|
[3234] | 265 |
|
---|
| 266 | return true;
|
---|
| 267 | }
|
---|
| 268 |
|
---|
| 269 |
|
---|
[3238] | 270 | bool VisibilitySolutionConverter::ReadScene(const string &filename)
|
---|
[3234] | 271 | {
|
---|
[3238] | 272 | VertexArray vertices;
|
---|
| 273 | VertexArray normals;
|
---|
| 274 | vector<TexCoord> texCoords;
|
---|
| 275 |
|
---|
| 276 | if (ReadSimpleObj(filename, vertices, normals, texCoords))
|
---|
| 277 | //if (ReadObj(filename, vertices, normals, texCoords))
|
---|
| 278 | {
|
---|
| 279 | ConstructBvhObjects(vertices, normals, texCoords);
|
---|
| 280 | return true;
|
---|
| 281 | }
|
---|
| 282 |
|
---|
| 283 | return false;
|
---|
| 284 | }
|
---|
| 285 |
|
---|
| 286 |
|
---|
| 287 | bool VisibilitySolutionConverter::ReadObj(const string &filename,
|
---|
| 288 | VertexArray &vertices,
|
---|
| 289 | VertexArray &normals,
|
---|
| 290 | vector<TexCoord> &texcoords)
|
---|
| 291 | {
|
---|
[3234] | 292 | FILE *file;
|
---|
| 293 |
|
---|
[3238] | 294 | if ((file = fopen(filename.c_str(), "r")) == NULL) return false;
|
---|
[3234] | 295 |
|
---|
[3238] | 296 | VertexArray tempVertices;
|
---|
| 297 | VertexArray tempNormals;
|
---|
| 298 | vector<TexCoord> tempTexcoords;
|
---|
[3234] | 299 |
|
---|
| 300 | vector<int> indices;
|
---|
| 301 |
|
---|
| 302 | int line = 0;
|
---|
| 303 | const int len = 10000;
|
---|
| 304 | char str[len];
|
---|
| 305 |
|
---|
| 306 | while (fgets(str, len, file) != NULL)
|
---|
| 307 | {
|
---|
[3238] | 308 | if (line % 500000 == 0)
|
---|
[3235] | 309 | cout << line << " " << str << endl;
|
---|
| 310 |
|
---|
| 311 | ++ line;
|
---|
| 312 |
|
---|
[3234] | 313 | switch (str[0])
|
---|
| 314 | {
|
---|
| 315 | case 'v': // vertex or normal
|
---|
| 316 | {
|
---|
| 317 | float x, y, z;
|
---|
| 318 |
|
---|
[3238] | 319 | //if (tempVertices.size() >= maxVertices * 3) continue;
|
---|
[3235] | 320 |
|
---|
[3234] | 321 | switch (str[1])
|
---|
| 322 | {
|
---|
| 323 | case 'n' :
|
---|
| 324 | sscanf(str + 2, "%f %f %f", &x, &y, &z);
|
---|
[3241] | 325 | tempNormals.push_back(CHCDemoEngine::Vector3(x, y, z));
|
---|
[3234] | 326 | break;
|
---|
| 327 | case 't':
|
---|
| 328 | sscanf(str + 2, "%f %f", &x, &y);
|
---|
[3238] | 329 | tempTexcoords.push_back(pair<float, float>(x, y));
|
---|
[3234] | 330 | break;
|
---|
| 331 | default:
|
---|
| 332 | sscanf(str + 1, "%f %f %f", &x, &y, &z);
|
---|
| 333 | //const float scale = 5e-3f;
|
---|
[3235] | 334 | const float scale = 0.1f;
|
---|
[3241] | 335 | tempVertices.push_back(CHCDemoEngine::Vector3(x * scale, y * scale, z * scale));
|
---|
[3234] | 336 | //cout <<"v " << x << " " << y << " "<< z << " ";
|
---|
| 337 | }
|
---|
| 338 | break;
|
---|
| 339 | }
|
---|
| 340 | case 'f':
|
---|
| 341 | {
|
---|
| 342 | //////////
|
---|
| 343 | //-- indices in the current line
|
---|
| 344 |
|
---|
[3238] | 345 | //if (tempVertices.size() >= maxVertices * 3) continue;
|
---|
[3234] | 346 | LoadIndices(str,
|
---|
[3238] | 347 | tempVertices, tempNormals, tempTexcoords,
|
---|
| 348 | vertices, normals, texcoords);
|
---|
[3234] | 349 |
|
---|
| 350 | break;
|
---|
[3235] | 351 | }
|
---|
[3234] | 352 | break;
|
---|
| 353 | default:
|
---|
| 354 | // throw away line
|
---|
| 355 | break;
|
---|
| 356 | }
|
---|
| 357 | }
|
---|
| 358 |
|
---|
[3238] | 359 | fclose(file);
|
---|
| 360 |
|
---|
| 361 | return !vertices.empty();
|
---|
| 362 | }
|
---|
| 363 |
|
---|
| 364 |
|
---|
| 365 | bool VisibilitySolutionConverter::ReadSimpleObj(const string &filename,
|
---|
| 366 | VertexArray &vertices,
|
---|
| 367 | VertexArray &normals,
|
---|
| 368 | vector<TexCoord> &texcoords)
|
---|
| 369 | {
|
---|
| 370 | const string binFilename = ReplaceSuffix(filename, ".obj", ".bn");
|
---|
| 371 |
|
---|
| 372 | if (!ReadBinObj(binFilename, vertices, 1))
|
---|
[3234] | 373 | {
|
---|
[3238] | 374 | cout << "binary dump " << binFilename << " not available, loading ascii obj" << endl;
|
---|
[3234] | 375 |
|
---|
[3238] | 376 | FILE *file;
|
---|
| 377 | if ((file = fopen(filename.c_str(), "r")) == NULL) return false;
|
---|
[3234] | 378 |
|
---|
[3238] | 379 | int line = 0;
|
---|
| 380 | const int len = 10000;
|
---|
| 381 | char str[len];
|
---|
| 382 |
|
---|
| 383 | while (fgets(str, len, file) != NULL)
|
---|
| 384 | {
|
---|
| 385 | if (line % 500000 == 0)
|
---|
| 386 | cout << line << " " << str << endl;
|
---|
| 387 |
|
---|
| 388 | ++ line;
|
---|
| 389 |
|
---|
| 390 | switch (str[0])
|
---|
| 391 | {
|
---|
| 392 | case 'v': // vertex or normal
|
---|
| 393 | {
|
---|
| 394 | float x, y, z;
|
---|
| 395 |
|
---|
| 396 | sscanf(str + 1, "%f %f %f", &x, &y, &z);
|
---|
| 397 | const float scale = 0.1f;
|
---|
[3241] | 398 | vertices.push_back(CHCDemoEngine::Vector3(x * scale, y * scale, z * scale));
|
---|
[3238] | 399 | break;
|
---|
| 400 | }
|
---|
| 401 | default:
|
---|
| 402 | // throw away line
|
---|
| 403 | break;
|
---|
| 404 | }
|
---|
| 405 | }
|
---|
| 406 |
|
---|
| 407 | fclose(file);
|
---|
| 408 |
|
---|
| 409 | cout << "dumping " << vertices.size() << " to binary " << binFilename << endl;
|
---|
| 410 | ExportBinObj(binFilename, vertices);
|
---|
[3234] | 411 | }
|
---|
| 412 |
|
---|
[3238] | 413 | for (size_t i = 0; i < vertices.size(); i += 3)
|
---|
| 414 | {
|
---|
| 415 | // no face normals? => create normals
|
---|
[3241] | 416 | const CHCDemoEngine::Triangle3 tri(vertices[i + 0],
|
---|
| 417 | vertices[i + 1],
|
---|
| 418 | vertices[i + 2]);
|
---|
[3238] | 419 |
|
---|
[3241] | 420 | const CHCDemoEngine::Vector3 n = tri.GetNormal();
|
---|
[3238] | 421 |
|
---|
| 422 | normals.push_back(n);
|
---|
| 423 | normals.push_back(n);
|
---|
| 424 | normals.push_back(n);
|
---|
| 425 | }
|
---|
| 426 |
|
---|
| 427 | return !vertices.empty();
|
---|
[3234] | 428 | }
|
---|
| 429 |
|
---|
| 430 |
|
---|
[3238] | 431 |
|
---|
[3235] | 432 | static inline float RandomColor(float x)
|
---|
[3234] | 433 | {
|
---|
[3235] | 434 | return x + (1.0f - x) * (float)rand() / RAND_MAX;
|
---|
| 435 | }
|
---|
| 436 |
|
---|
| 437 |
|
---|
| 438 | void VisibilitySolutionConverter::WriteGeometry(ogzstream &str, Geometry *geom)
|
---|
| 439 | {
|
---|
[3234] | 440 | int vertexCount = geom->mVertexCount;
|
---|
| 441 | str.write(reinterpret_cast<char *>(&vertexCount), sizeof(int));
|
---|
| 442 |
|
---|
[3241] | 443 | str.write(reinterpret_cast<char *>(geom->mVertices), sizeof(CHCDemoEngine::Vector3) * vertexCount);
|
---|
| 444 | str.write(reinterpret_cast<char *>(geom->mNormals), sizeof(CHCDemoEngine::Vector3) * vertexCount);
|
---|
[3234] | 445 |
|
---|
[3236] | 446 | int texCoordCount = 0;//geom->mTexcoordCount;
|
---|
[3234] | 447 | str.write(reinterpret_cast<char *>(&texCoordCount), sizeof(int));
|
---|
| 448 |
|
---|
| 449 | if (texCoordCount)
|
---|
[3235] | 450 | {
|
---|
| 451 | str.write(reinterpret_cast<char *>(geom->mTexCoords), sizeof(float) * texCoordCount * 2);
|
---|
| 452 | }
|
---|
[3234] | 453 |
|
---|
| 454 | ///////
|
---|
| 455 | //-- texture
|
---|
| 456 |
|
---|
| 457 | int texId = -1;
|
---|
| 458 | str.write(reinterpret_cast<char *>(&texId), sizeof(int));
|
---|
| 459 |
|
---|
| 460 | bool alphaTestEnabled = false;
|
---|
| 461 | bool cullFaceEnabled = true;
|
---|
| 462 |
|
---|
| 463 | str.write(reinterpret_cast<char *>(&alphaTestEnabled), sizeof(bool));
|
---|
| 464 | str.write(reinterpret_cast<char *>(&cullFaceEnabled), sizeof(bool));
|
---|
| 465 |
|
---|
| 466 | // material
|
---|
| 467 | bool hasMaterial = true;
|
---|
[3236] | 468 |
|
---|
[3234] | 469 | str.write(reinterpret_cast<char *>(&hasMaterial), sizeof(bool));
|
---|
| 470 |
|
---|
| 471 | if (hasMaterial)
|
---|
| 472 | {
|
---|
[3241] | 473 | CHCDemoEngine::Vector3 ambient, diffuse, spec, emm;
|
---|
[3234] | 474 |
|
---|
| 475 | ambient.x = ambient.y = ambient.z = 0.2f;
|
---|
| 476 | //diffuse.x = diffuse.y = diffuse.z = 1.0f;
|
---|
[3235] | 477 |
|
---|
| 478 | diffuse.x = RandomColor(0.5f);
|
---|
| 479 | diffuse.y = RandomColor(0.5f);
|
---|
| 480 | diffuse.z = RandomColor(0.5f);
|
---|
| 481 |
|
---|
[3241] | 482 | spec.x = spec.y = spec.z = .0f;
|
---|
[3234] | 483 | emm = spec;
|
---|
| 484 |
|
---|
| 485 | // only write rgb part of the material
|
---|
[3241] | 486 | str.write(reinterpret_cast<char *>(&ambient), sizeof(CHCDemoEngine::Vector3));
|
---|
| 487 | str.write(reinterpret_cast<char *>(&diffuse), sizeof(CHCDemoEngine::Vector3));
|
---|
| 488 | str.write(reinterpret_cast<char *>(&spec), sizeof(CHCDemoEngine::Vector3));
|
---|
| 489 | str.write(reinterpret_cast<char *>(&emm), sizeof(CHCDemoEngine::Vector3));
|
---|
[3234] | 490 | }
|
---|
| 491 | }
|
---|
| 492 |
|
---|
| 493 |
|
---|
[3235] | 494 | bool VisibilitySolutionConverter::WriteScene(const string &filename)
|
---|
[3234] | 495 | {
|
---|
| 496 | ogzstream ofile(filename.c_str());
|
---|
| 497 |
|
---|
| 498 | if (!ofile.is_open())
|
---|
| 499 | return false;
|
---|
| 500 |
|
---|
| 501 |
|
---|
| 502 | int textureCount = 0;
|
---|
| 503 | ofile.write(reinterpret_cast<char *>(&textureCount), sizeof(int));
|
---|
| 504 |
|
---|
| 505 |
|
---|
| 506 | ///////////
|
---|
| 507 | //-- write shapes
|
---|
| 508 |
|
---|
[3236] | 509 | int numShapes = (int)mGeometry.size();
|
---|
| 510 | ofile.write(reinterpret_cast<char *>(&numShapes), sizeof(int));
|
---|
[3234] | 511 |
|
---|
| 512 | vector<Geometry *>::const_iterator it, it_end = mGeometry.end();
|
---|
| 513 |
|
---|
| 514 | for (it = mGeometry.begin(); it != it_end; ++ it)
|
---|
| 515 | {
|
---|
| 516 | WriteGeometry(ofile, *it);
|
---|
| 517 | }
|
---|
| 518 |
|
---|
| 519 |
|
---|
[3236] | 520 | int entityCount = numShapes;
|
---|
[3234] | 521 | ofile.write(reinterpret_cast<char *>(&entityCount), sizeof(int));
|
---|
| 522 |
|
---|
| 523 |
|
---|
| 524 | //////////
|
---|
[3236] | 525 | //-- write single scene entity for each shape
|
---|
[3234] | 526 |
|
---|
[3236] | 527 | // all shapes belong to this scene entity
|
---|
| 528 | for (int i = 0; i < numShapes; ++ i)
|
---|
| 529 | {
|
---|
| 530 | // no transformation
|
---|
| 531 | bool hasTrafo = false;
|
---|
| 532 | ofile.write(reinterpret_cast<char *>(&hasTrafo), sizeof(bool));
|
---|
[3234] | 533 |
|
---|
[3236] | 534 | // a dummy lod
|
---|
| 535 | int numLODs = 1;
|
---|
| 536 | ofile.write(reinterpret_cast<char *>(&numLODs), sizeof(int));
|
---|
[3234] | 537 |
|
---|
[3236] | 538 | float dist = 0;
|
---|
| 539 | ofile.write(reinterpret_cast<char *>(&dist), sizeof(float));
|
---|
[3234] | 540 |
|
---|
[3236] | 541 | int shapesPerEnt = 1;
|
---|
| 542 | ofile.write(reinterpret_cast<char *>(&shapesPerEnt), sizeof(int));
|
---|
[3234] | 543 |
|
---|
| 544 | int shapeId = i;
|
---|
| 545 | ofile.write(reinterpret_cast<char *>(&shapeId), sizeof(int));
|
---|
| 546 | }
|
---|
| 547 |
|
---|
| 548 | return true;
|
---|
[3235] | 549 | }
|
---|
| 550 |
|
---|
| 551 |
|
---|
| 552 | void VisibilitySolutionConverter::ConstructBvhObjects(const VertexArray &vertices,
|
---|
| 553 | const VertexArray &normals,
|
---|
| 554 | const vector<TexCoord> &texCoords)
|
---|
| 555 | {
|
---|
[3238] | 556 | VertexArray _vertices;
|
---|
| 557 | VertexArray _normals;
|
---|
| 558 | vector<TexCoord> _texCoords;
|
---|
[3235] | 559 |
|
---|
[3241] | 560 | mGeometry.reserve(mBvhLeaves.size());
|
---|
| 561 |
|
---|
| 562 | mNumShapes = (int)mBvhLeaves.size();
|
---|
| 563 |
|
---|
| 564 | for (size_t i = 0; i < mBvhLeaves.size(); ++ i)
|
---|
[3235] | 565 | {
|
---|
[3241] | 566 | BvhLeaf *node = mBvhLeaves[i];
|
---|
[3235] | 567 |
|
---|
[3238] | 568 | for (int j = node->first; j <= node->last; ++ j)
|
---|
[3235] | 569 | {
|
---|
| 570 | const int idx = 3 * mGlobalTriangleIds[j];
|
---|
| 571 |
|
---|
[3238] | 572 | for (int k = 0; k < 3; ++ k)
|
---|
[3235] | 573 | {
|
---|
[3238] | 574 | _vertices.push_back(vertices[idx + k]);
|
---|
| 575 | _normals.push_back(normals[idx + k]);
|
---|
| 576 | //_texCoords.push_back(texCoords[idx + k]);
|
---|
[3235] | 577 | }
|
---|
| 578 | }
|
---|
| 579 |
|
---|
[3241] | 580 | LoadShape(_vertices, _normals, _texCoords);
|
---|
| 581 |
|
---|
| 582 | node->geometry = mGeometry.back();
|
---|
[3238] | 583 |
|
---|
| 584 | _vertices.clear();
|
---|
| 585 | _normals.clear();
|
---|
| 586 | _texCoords.clear();
|
---|
[3235] | 587 | }
|
---|
| 588 | }
|
---|
| 589 |
|
---|
| 590 |
|
---|
| 591 | bool VisibilitySolutionConverter::ReadBvh(FILE *fr)
|
---|
| 592 | {
|
---|
| 593 | int buffer[6];
|
---|
| 594 | fread(buffer, sizeof(int), 6, fr);
|
---|
| 595 |
|
---|
| 596 | if (buffer[0] != MAGIC)
|
---|
| 597 | {
|
---|
| 598 | cerr << "Error: Wrong file type" << endl;
|
---|
| 599 | return false;
|
---|
| 600 | }
|
---|
| 601 |
|
---|
| 602 | if (buffer[1] != (int)(1000 * BVH_VERSION))
|
---|
| 603 | {
|
---|
| 604 | cerr << "Error: Wrong BVH version" << endl;
|
---|
| 605 | return false;
|
---|
| 606 | }
|
---|
| 607 |
|
---|
| 608 | // load triangle ids
|
---|
| 609 | size_t numTriangles = buffer[2];
|
---|
| 610 |
|
---|
| 611 | for (size_t i = 0; i < numTriangles; ++i)
|
---|
| 612 | {
|
---|
| 613 | int id;
|
---|
| 614 | fread(&id, sizeof(int), 1, fr);
|
---|
[3236] | 615 | mGlobalTriangleIds.push_back(id);
|
---|
[3235] | 616 | //triangles[i] = scene->triangles[id];
|
---|
| 617 | }
|
---|
| 618 |
|
---|
[3241] | 619 | const size_t numNodes = buffer[5];
|
---|
[3235] | 620 |
|
---|
| 621 | mNumNodes = 0; // this was set to 1 in constructor!
|
---|
| 622 |
|
---|
| 623 | mRoot = LoadNode(fr, 0);
|
---|
| 624 |
|
---|
[3241] | 625 | if (mNumNodes != numNodes)
|
---|
[3235] | 626 | {
|
---|
| 627 | cerr << "Warning: Loaded " << mNumNodes <<
|
---|
| 628 | " bvh nodes instead of " << buffer[5] << endl;
|
---|
| 629 | }
|
---|
| 630 |
|
---|
| 631 | fclose(fr);
|
---|
| 632 |
|
---|
| 633 | return true;
|
---|
| 634 | }
|
---|
| 635 |
|
---|
| 636 |
|
---|
[3241] | 637 | void VisibilitySolutionConverter::UpdateLeafBox(BvhLeaf *leaf)
|
---|
| 638 | {
|
---|
| 639 | leaf->box.Initialize();
|
---|
| 640 |
|
---|
| 641 | Geometry *geom = leaf->geometry;
|
---|
| 642 |
|
---|
| 643 | for (size_t i = 0; i < geom->mVertexCount; ++ i)
|
---|
| 644 | {
|
---|
| 645 | CHCDemoEngine::Vector3 v = geom->mVertices[i];
|
---|
| 646 | leaf->box.Include(v);
|
---|
| 647 | }
|
---|
| 648 | }
|
---|
| 649 |
|
---|
| 650 |
|
---|
[3235] | 651 | BvhNode *VisibilitySolutionConverter::LoadNode(FILE *fr, int depth)
|
---|
| 652 | {
|
---|
| 653 | ++ mNumNodes;
|
---|
| 654 |
|
---|
| 655 | int buffer[4];
|
---|
| 656 | fread(buffer, sizeof(int), 4, fr);
|
---|
| 657 |
|
---|
| 658 | if (buffer[2] != -1)
|
---|
| 659 | {
|
---|
| 660 | BvhInterior *interior = new BvhInterior();
|
---|
| 661 |
|
---|
| 662 | interior->first = buffer[0];
|
---|
| 663 | interior->last = buffer[1];
|
---|
| 664 | interior->axis = buffer[2];
|
---|
| 665 | interior->id = buffer[3];
|
---|
| 666 | interior->depth = depth;
|
---|
| 667 |
|
---|
| 668 | BvhNode *front, *back;
|
---|
| 669 |
|
---|
| 670 | front = LoadNode(fr, depth + 1);
|
---|
| 671 | back = LoadNode(fr, depth + 1);
|
---|
| 672 |
|
---|
[3239] | 673 | front->parent = interior;
|
---|
| 674 | back->parent = interior;
|
---|
| 675 |
|
---|
[3235] | 676 | interior->front = front;
|
---|
| 677 | interior->back = back;
|
---|
| 678 |
|
---|
| 679 | return (BvhNode *)interior;
|
---|
| 680 | }
|
---|
| 681 | else
|
---|
| 682 | {
|
---|
| 683 | // leaf
|
---|
| 684 | BvhLeaf *leaf = new BvhLeaf();
|
---|
[3239] | 685 |
|
---|
[3235] | 686 | leaf->first = buffer[0];
|
---|
| 687 | leaf->last = buffer[1];
|
---|
| 688 | leaf->axis = buffer[2];
|
---|
[3239] | 689 | leaf->id = buffer[3];
|
---|
[3235] | 690 |
|
---|
| 691 | leaf->depth = depth;
|
---|
| 692 |
|
---|
[3241] | 693 | mBvhLeaves.push_back(leaf);
|
---|
[3239] | 694 |
|
---|
[3235] | 695 | return (BvhNode *)leaf;
|
---|
| 696 | }
|
---|
| 697 | }
|
---|
| 698 |
|
---|
| 699 |
|
---|
| 700 | bool VisibilitySolutionConverter::ReadDummyTree(FILE *fr)
|
---|
| 701 | {
|
---|
| 702 | int buffer[256];
|
---|
| 703 | fread(buffer, sizeof(int), 3, fr);
|
---|
| 704 |
|
---|
| 705 | // read dummy bounding box
|
---|
| 706 | float dummy[6];
|
---|
| 707 | fread(dummy, sizeof(float) * 6, 1, fr);
|
---|
| 708 |
|
---|
| 709 | int stack = 1;
|
---|
| 710 |
|
---|
| 711 | // read dummy tree
|
---|
| 712 | while (stack)
|
---|
| 713 | {
|
---|
| 714 | int axis;
|
---|
| 715 | fread(&axis, sizeof(int), 1, fr);
|
---|
| 716 | -- stack;
|
---|
| 717 |
|
---|
| 718 | if (axis != - 1)
|
---|
| 719 | {
|
---|
| 720 | float dummy;
|
---|
| 721 | fread(&dummy, sizeof(float), 1, fr);
|
---|
| 722 |
|
---|
| 723 | stack += 2;
|
---|
| 724 | }
|
---|
| 725 | }
|
---|
| 726 |
|
---|
| 727 | return true;
|
---|
| 728 | }
|
---|
| 729 |
|
---|
| 730 |
|
---|
| 731 |
|
---|
| 732 | bool VisibilitySolutionConverter::LoadSolution(const string &filename)
|
---|
| 733 | {
|
---|
| 734 | FILE *fr = fopen(filename.c_str(), "rb");
|
---|
| 735 |
|
---|
| 736 | cerr << "Info: Loading visibility solution from file '" + filename + "'" << endl;
|
---|
| 737 |
|
---|
| 738 | if (fr == NULL)
|
---|
| 739 | {
|
---|
| 740 | cerr << "Error: Cannot open file for reading" << endl;
|
---|
| 741 | return false;
|
---|
| 742 | }
|
---|
| 743 |
|
---|
| 744 | float totalSamples, totalTime;
|
---|
| 745 |
|
---|
| 746 | fread(&totalSamples, sizeof(float), 1, fr);
|
---|
| 747 | fread(&totalTime, sizeof(float), 1, fr);
|
---|
| 748 |
|
---|
[3238] | 749 | // just need to convert objects => read dummy visibility tree
|
---|
[3235] | 750 | bool ok = ReadDummyTree(fr);
|
---|
| 751 |
|
---|
[3238] | 752 | // read bvh to optain objects (= the leaves of the bvh)
|
---|
| 753 | if (ok) ok = ReadBvh(fr);
|
---|
[3235] | 754 |
|
---|
| 755 | fclose(fr);
|
---|
| 756 |
|
---|
| 757 | if (ok)
|
---|
| 758 | cout << "Info: visibility solution loaded" << endl;
|
---|
| 759 | else
|
---|
| 760 | cout << "Info: loading visibility solution failed" << endl;
|
---|
| 761 |
|
---|
| 762 | return true;
|
---|
| 763 | }
|
---|
| 764 |
|
---|
| 765 |
|
---|
[3238] | 766 | bool VisibilitySolutionConverter::ReadBinObj(const string &filename,
|
---|
| 767 | VertexArray &vertices,
|
---|
| 768 | float scale)
|
---|
| 769 | {
|
---|
| 770 | igzstream inStream(filename.c_str());
|
---|
| 771 |
|
---|
| 772 | if (!inStream.is_open()) return false;
|
---|
[3235] | 773 |
|
---|
[3238] | 774 | cout << "binary obj dump available, loading " << filename.c_str() << endl;
|
---|
| 775 |
|
---|
| 776 | // read in triangle size
|
---|
| 777 | int numTriangles;
|
---|
[3235] | 778 |
|
---|
[3238] | 779 | const int t = 500000;
|
---|
| 780 | inStream.read(reinterpret_cast<char *>(&numTriangles), sizeof(int));
|
---|
| 781 | vertices.reserve(numTriangles * 3);
|
---|
| 782 | cout << "loading " << numTriangles * 3 << " vertices ("
|
---|
[3241] | 783 | << numTriangles * 3 * sizeof(CHCDemoEngine::Vector3) / (1024 * 1024) << " MB)" << endl;
|
---|
[3235] | 784 |
|
---|
[3238] | 785 | int i = 0;
|
---|
| 786 |
|
---|
| 787 | while (1)
|
---|
[3235] | 788 | {
|
---|
[3241] | 789 | CHCDemoEngine::Vector3 v;
|
---|
| 790 | inStream.read(reinterpret_cast<char *>(&v), sizeof(CHCDemoEngine::Vector3));
|
---|
[3238] | 791 |
|
---|
| 792 | // end of file reached
|
---|
| 793 | if (inStream.eof()) break;
|
---|
| 794 |
|
---|
| 795 | //v *= scale;
|
---|
| 796 | vertices.push_back(v);
|
---|
| 797 |
|
---|
| 798 | if (((i ++) % t) == 0)
|
---|
| 799 | cout << "\r" << i << "/" << numTriangles * 3 << "\r";
|
---|
[3235] | 800 | }
|
---|
[3238] | 801 |
|
---|
| 802 | cout << "finished loading vertices" << endl;
|
---|
| 803 |
|
---|
| 804 | if (i != numTriangles * 3)
|
---|
| 805 | cerr << "warning: " << numTriangles * 3 << " != " << i << endl;
|
---|
| 806 |
|
---|
| 807 | inStream.close();
|
---|
| 808 |
|
---|
[3235] | 809 | return true;
|
---|
| 810 | }
|
---|
| 811 |
|
---|
| 812 |
|
---|
[3238] | 813 | bool VisibilitySolutionConverter::ExportBinObj(const string &filename,
|
---|
| 814 | const VertexArray &vertices)
|
---|
| 815 | {
|
---|
| 816 | ogzstream ofile(filename.c_str());
|
---|
| 817 | if (!ofile.is_open()) return false;
|
---|
[3235] | 818 |
|
---|
[3238] | 819 | int numTriangles = (int)vertices.size() / 3;
|
---|
[3235] | 820 |
|
---|
[3238] | 821 | ofile.write(reinterpret_cast<char *>(&numTriangles), sizeof(int));
|
---|
| 822 |
|
---|
| 823 | VertexArray::const_iterator it, it_end = vertices.end();
|
---|
| 824 |
|
---|
| 825 | for (it = vertices.begin(); it != it_end; ++ it)
|
---|
[3235] | 826 | {
|
---|
[3241] | 827 | CHCDemoEngine::Vector3 v = *it;
|
---|
| 828 | ofile.write(reinterpret_cast<char *>(&v), sizeof(CHCDemoEngine::Vector3));
|
---|
[3235] | 829 | }
|
---|
| 830 |
|
---|
[3238] | 831 | cout << "exported " << numTriangles * 3 << " vertices" << endl;
|
---|
[3235] | 832 |
|
---|
[3238] | 833 | ofile.close();
|
---|
[3235] | 834 |
|
---|
| 835 | return true;
|
---|
[3239] | 836 | }
|
---|
| 837 |
|
---|
| 838 |
|
---|
| 839 | void VisibilitySolutionConverter::WriteNextNode(ogzstream &stream,
|
---|
| 840 | BvhNode *node)
|
---|
| 841 | {
|
---|
| 842 | int nodeType;
|
---|
| 843 |
|
---|
| 844 | if (!node->IsLeaf())
|
---|
| 845 | nodeType = TYPE_LEAF;
|
---|
| 846 | else
|
---|
| 847 | nodeType = TYPE_INTERIOR;
|
---|
| 848 |
|
---|
| 849 | stream.write(reinterpret_cast<char *>(&nodeType), sizeof(int));
|
---|
| 850 |
|
---|
[3241] | 851 | CHCDemoEngine::Vector3 bMin = node->box.Min();
|
---|
| 852 | CHCDemoEngine::Vector3 bMax = node->box.Max();
|
---|
[3239] | 853 |
|
---|
| 854 | stream.write(reinterpret_cast<char *>(&(node->first)), sizeof(int));
|
---|
| 855 | stream.write(reinterpret_cast<char *>(&(node->last)), sizeof(int));
|
---|
| 856 |
|
---|
[3241] | 857 | stream.write(reinterpret_cast<char *>(&bMin), sizeof(CHCDemoEngine::Vector3));
|
---|
| 858 | stream.write(reinterpret_cast<char *>(&bMin), sizeof(CHCDemoEngine::Vector3));
|
---|
[3239] | 859 | }
|
---|
| 860 |
|
---|
| 861 |
|
---|
[3241] | 862 | void VisibilitySolutionConverter::UpdateNodeBox(BvhNode *node)
|
---|
| 863 | {
|
---|
| 864 | if (!node->IsLeaf())
|
---|
| 865 | {
|
---|
| 866 | BvhInterior *interior = (BvhInterior *)node;
|
---|
| 867 | node->box = Union(interior->front->box, interior->back->box);
|
---|
| 868 |
|
---|
| 869 | UpdateNodeBox(interior->front);
|
---|
| 870 | UpdateNodeBox(interior->back);
|
---|
| 871 | }
|
---|
| 872 | else
|
---|
| 873 | {
|
---|
| 874 | UpdateLeafBox((BvhLeaf *)node);
|
---|
| 875 | }
|
---|
| 876 | }
|
---|
| 877 |
|
---|
| 878 |
|
---|
[3239] | 879 | bool VisibilitySolutionConverter::WriteBvh(const string &filename)
|
---|
| 880 | {
|
---|
| 881 | std::queue<BvhNode *> tQueue;
|
---|
| 882 | ogzstream stream(filename.c_str());
|
---|
| 883 |
|
---|
| 884 | if (!stream.is_open()) return NULL;
|
---|
| 885 |
|
---|
| 886 | cout << "loading bvh" << endl;
|
---|
| 887 |
|
---|
| 888 | WriteNextNode(stream, mRoot);
|
---|
| 889 |
|
---|
| 890 | tQueue.push(mRoot);
|
---|
| 891 |
|
---|
| 892 | while (!tQueue.empty())
|
---|
| 893 | {
|
---|
| 894 | BvhNode *node = tQueue.front();
|
---|
| 895 | tQueue.pop();
|
---|
| 896 |
|
---|
| 897 | if (!node->IsLeaf())
|
---|
| 898 | {
|
---|
| 899 | BvhInterior *interior = static_cast<BvhInterior *>(node);
|
---|
| 900 |
|
---|
| 901 | BvhNode *front = interior->front;
|
---|
| 902 | BvhNode *back = interior->back;
|
---|
| 903 |
|
---|
| 904 | WriteNextNode(stream, front);
|
---|
| 905 | WriteNextNode(stream, back);
|
---|
| 906 |
|
---|
| 907 | tQueue.push(front);
|
---|
| 908 | tQueue.push(back);
|
---|
| 909 | }
|
---|
| 910 | }
|
---|
| 911 |
|
---|
| 912 | return true;
|
---|
[3238] | 913 | } |
---|