
#include <WFX/scene/BoundingCubeFinder.h>

using namespace WFX::scene;
using namespace WFX::math;

BoundingCubeFinder::BoundingCubeFinder() {
    VertexCount = 0;
}

BoundingCubeFinder::~BoundingCubeFinder() {
}

void BoundingCubeFinder::visitNode(Node& n) {
    std::list<Spatial*>::iterator it;
    for (it = n.Children.begin(); it != n.Children.end(); it++) {
        (*it)->accept(*this);
    }
}

void BoundingCubeFinder::visitTriMesh(TriMesh& m) {
    //iterate over vertices
    for (UInt i=0; i<m.getVertexCount(); i++) {
        //add vertex to center
        BoundingCube.getCenter() += m.getVertices()[i];
        VertexCount++;
    }
    //add vertices to visited list
    VisitedNodes.push_back(&m);
}

void BoundingCubeFinder::visitOctreeNode(OctreeNode& o) {
    THROW("not yet implemented: visitOctreeNode");
}

WFX::math::Cube BoundingCubeFinder::getBoundingCube() {
    //find average Center
    BoundingCube.getCenter() /= VertexCount;
    
    //iterate over visited Vertices again
    Vector3 maxDims;
    std::list<WFX::scene::GeometryNode*>::iterator it;
    for (it = VisitedNodes.begin(); it != VisitedNodes.end(); it++) {
        for (UInt i=0; i<(*it)->getVertexCount(); i++) {
            //determine distance to Center
            Vector3 currDims = (*it)->getVertices()[i] - BoundingCube.getCenter();
            //use absolute Values
            currDims.abs();
            //check whether any of the current dimensions
            //is larger than the max dimensions
            maxDims.X = (maxDims.X > currDims.X)?maxDims.X:currDims.X;
            maxDims.Y = (maxDims.Y > currDims.Y)?maxDims.Y:currDims.Y;
            maxDims.Z = (maxDims.Z > currDims.Z)?maxDims.Z:currDims.Z;

        }
    }

    //set real width
    maxDims *= 2;

    //determine max dimension
    Real w = (maxDims.X > maxDims.Y)?maxDims.X:maxDims.Y;
    w = (w > maxDims.Z)?w:maxDims.Z;
    BoundingCube.setWidth(w);

    return BoundingCube;
}

