octreeoptimisation.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /*
  2. * DoRayMe - a quick and dirty Raytracer
  3. * Octree world optimiser implementation
  4. *
  5. * Created by Manoël Trapier
  6. * Copyright (c) 2020 986-Studio.
  7. *
  8. */
  9. #include <worldoptimiser.h>
  10. #include <cube.h>
  11. #include <objfile.h>
  12. #include <transformation.h>
  13. void OctreeOptimisation::makeTree(Group *leaf, int depth)
  14. {
  15. /* Let's take the bounding box of the root */
  16. BoundingBox rootBB = leaf->getBounds();
  17. /* Take the mid value for each axes */
  18. double midX = (rootBB.max.x - rootBB.min.x) / 2.0 + rootBB.min.x;
  19. double midY = (rootBB.max.y - rootBB.min.y) / 2.0 + rootBB.min.y;
  20. double midZ = (rootBB.max.z - rootBB.min.z) / 2.0 + rootBB.min.z;
  21. BoundingBox octantBB[8];
  22. int octantIdx;
  23. Group *octants[8];
  24. int i;
  25. /* Split the main bounding box into 8 boxes */
  26. octantBB[0] | Point(rootBB.min.x, rootBB.min.y, rootBB.min.z);
  27. octantBB[0] | Point(midX, midY, midZ);
  28. octantBB[1] | Point(midX, rootBB.min.y, rootBB.min.z);
  29. octantBB[1] | Point(rootBB.max.x, midY, midZ);
  30. octantBB[2] | Point(rootBB.min.x, midY, rootBB.min.z);
  31. octantBB[2] | Point(midX, rootBB.max.y, midZ);
  32. octantBB[3] | Point(midX, midY, rootBB.min.z);
  33. octantBB[3] | Point(rootBB.max.x, rootBB.max.y, midZ);
  34. octantBB[4] | Point(rootBB.min.x, midY, midZ);
  35. octantBB[4] | Point(midX, rootBB.max.y, rootBB.max.z);
  36. octantBB[5] | Point(midX, midY, midZ);
  37. octantBB[5] | Point(rootBB.max.x, rootBB.max.y, rootBB.max.z);
  38. octantBB[6] | Point(rootBB.min.x, rootBB.min.y, midZ);
  39. octantBB[6] | Point(midX, midY, rootBB.max.z);
  40. octantBB[7] | Point(midX, rootBB.min.y, midZ);
  41. octantBB[7] | Point(rootBB.max.x, midY, rootBB.max.z);
  42. for (octantIdx = 0 ; octantIdx < 8 ; octantIdx++)
  43. {
  44. octants[octantIdx] = nullptr;
  45. }
  46. for (i = 0 ; i < leaf->getObjectCount(); i++)
  47. {
  48. Shape *shp = leaf->getObject(i);
  49. BoundingBox objBB = shp->getBounds();
  50. //if ((shp->getType() != Shape::GROUP) && (shp->getType() != Shape::OBJFILE))
  51. for (octantIdx = 0 ; octantIdx < 8 ; octantIdx++)
  52. {
  53. if (octantBB[octantIdx].fitsIn(objBB))
  54. {
  55. if (octants[octantIdx] == nullptr)
  56. {
  57. char name[32];
  58. snprintf(name, 32, "%d_Quadrant %d", depth, octantIdx);
  59. octants[octantIdx] = new Group(name);
  60. octants[octantIdx]->setBounds(octantBB[octantIdx]);
  61. }
  62. octants[octantIdx]->addObject(shp);
  63. leaf->removeObject(shp);
  64. i -= 1;
  65. break;
  66. }
  67. }
  68. if (shp->getType() == Shape::GROUP)
  69. {
  70. this->makeTree((Group *)shp, depth + 1);
  71. }
  72. if (shp->getType() == Shape::OBJFILE)
  73. {
  74. this->makeTree((Group *)((OBJFile *)shp)->getBaseGroup(), depth + 1);
  75. }
  76. }
  77. /* Now add the quadrant to the root and recurse in it */
  78. for (octantIdx = 0 ; octantIdx < 8 ; octantIdx++)
  79. {
  80. if (octants[octantIdx] != nullptr)
  81. {
  82. this->makeTree(octants[octantIdx], depth + 1);
  83. octants[octantIdx]->updateBoundingBox();
  84. leaf->addObject(octants[octantIdx]);
  85. #if 0
  86. Cube *cb = new Cube();
  87. double sx = octantBB[octantIdx].max.x - octantBB[octantIdx].min.x;
  88. double sy = octantBB[octantIdx].max.y - octantBB[octantIdx].min.y;
  89. double sz = octantBB[octantIdx].max.z - octantBB[octantIdx].min.z;
  90. cb->setTransform(translation(octantBB[octantIdx].min.x, octantBB[octantIdx].min.y,
  91. octantBB[octantIdx].min.z) * scaling(sx, sy, sz));
  92. cb->material.colour = Colour(0.01, 0.01, 0);
  93. cb->materialSet = true;
  94. cb->dropShadow = false;
  95. cb->material.ambient = 0.1;
  96. cb->material.reflective = 0;
  97. cb->material.transparency = 0.95;
  98. cb->material.refractiveIndex = 1;
  99. cb->material.specular = 0;
  100. leaf->addObject(cb);
  101. printf("%s: %d objs\n", octants[octantIdx]->getName(),
  102. octants[octantIdx]->getObjectCount());
  103. #endif
  104. }
  105. }
  106. }
  107. void OctreeOptimisation::run()
  108. {
  109. /* First let's clear our hands */
  110. this->moveInfiniteObjects();
  111. /* Then let's have some fun! */
  112. //this->moveAllObjects();
  113. /* Now.. The fun start ! */
  114. makeTree(this->root, 0);
  115. }