1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
|
void OctreeAccelerator::build()
{
BoundingBox bb = Composite::getBoundingBox();
//construct octree bounding box by the largest direction in the composite bb
double wx = bb.p2.x - bb.p1.x;
double wy = bb.p2.y - bb.p1.y;
double wz = bb.p2.z - bb.p1.z;
double nw = max(wx, max(wy, wz)) / 2;
Vector3 center(bb.p1.x+wx/2, bb.p1.y+wy/2, bb.p1.z+wz/2);
Vector3 p1(center.x-nw, center.y-nw, center.z-nw);
Vector3 p2(center.x+nw, center.y+nw, center.z+nw);
std::shared_ptr<BoundingBox> nb(new BoundingBox(p1, p2));
root = buildOctree(objects, nb, 20);
objects.erase(objects.begin(), objects.end());
}
std::shared_ptr<OctreeNode> OctreeAccelerator::buildOctree(std::vector<std::shared_ptr<Object> > obj, std::shared_ptr<BoundingBox> bb, int depth)
{
if (depth < 0 || obj.size() < 3)
return nullptr;
std::vector<std::shared_ptr<BoundingBox> >boxes = bb->splitToEight();
//Create node and attach objects
std::shared_ptr<OctreeNode> node(new OctreeNode(bb));
node->leaves = std::vector<std::shared_ptr<Object> >(obj);
std::vector<std::shared_ptr<Object> > boxObjects[8];
for(unsigned long i = 0; i < obj.size(); i++)
{
std::shared_ptr<Object> g = objects.at(i);
for(int box = 0; box < 8; box++)
{
if (g->geometry->overlaps(boxes[box]))
{
boxObjects[box].push_back(obj[i]);
}
}
}
for(int i = 0; i < 8; i++)
{
size_t size = boxObjects[i].size();
if (size)
node->childNodes[i] = buildOctree(boxObjects[i], boxes[i], depth-1);
}
return node;
}
...
std::vector<std::shared_ptr<BoundingBox> > BoundingBox::splitToEight() {
std::vector<std::shared_ptr<BoundingBox> > boxes;
for(int i = 0; i < 8; i++)
{
Vector3 newOrigin = getCenter();
float halfDimX = (p2.x - p1.x) / 4;
float halfDimY = (p2.y - p1.y) / 4;
float halfDimZ = (p2.z - p1.z) / 4;
newOrigin.x += halfDimX*2 * (i&4 ? 0.5f : -0.5f);
newOrigin.y += halfDimY*2 * (i&2 ? 0.5f : -0.5f);
newOrigin.z += halfDimZ*2 * (i&1 ? 0.5f : -0.5f);
Vector3 p1(newOrigin.x - halfDimX, newOrigin.y - halfDimY, newOrigin.z - halfDimZ);
Vector3 p2(newOrigin.x + halfDimX, newOrigin.y + halfDimY, newOrigin.z + halfDimZ);
std::shared_ptr<BoundingBox> nb(new BoundingBox(p1, p2));
boxes.push_back(nb);
}
return boxes;
}
|