#include "cBoundingBox.h"
#include "cColor.h"
#include "OGLPlatformSpecific.h"

#include "tmtriboxtest.c"

cBoundingBox::cBoundingBox() : color_(1,1,1) {/* No guaruntees on the values!*/}

cBoundingBox::cBoundingBox(const cBoundingBox& toCopy)
{
    xmin_ = toCopy.xmin_;
    ymin_ = toCopy.ymin_;
    zmin_ = toCopy.zmin_;
    
    xmax_ = toCopy.xmax_;
    ymax_ = toCopy.ymax_;
    zmax_ = toCopy.zmax_;
}

cBoundingBox::cBoundingBox(float xmin, float xmax, float  ymin, float ymax, float zmin, float zmax)
: xmin_(xmin), xmax_(xmax), ymin_(ymin), ymax_(ymax), zmin_(zmin), zmax_(zmax), color_(cColor(1,1,1)) {}

bool cBoundingBox::pointIsInMe(cVector &point)
{
    return 	(point.x_ >= xmin_ && point.x_ <= xmax_) &&
                (point.y_ >= ymin_ && point.y_ <= ymax_) &&
                (point.z_ >= zmin_ && point.z_ <= zmax_);
}


bool cBoundingBox::pointsAreInMe(vector<cVector>& points)
{
    for(int i = 0; i < points.size(); ++i)
        if(!pointIsInMe(points[i])) return false;
        
    return true;
}

bool cBoundingBox::anyPointIsInMe(vector<cVector>& points)
{
    for(int i = 0; i < points.size(); ++i)
        if(pointIsInMe(points[i])) return true;
        
    return false;
}

bool cBoundingBox::boxIntersectsMe(cBoundingBox &otherBox)
{
    vector<cVector> myVertices;
    getMyVertices(myVertices);
    vector<cVector> otherVertices;
    otherBox.getMyVertices(otherVertices);
    return anyPointIsInMe(otherVertices) || otherBox.anyPointIsInMe(myVertices);
}

void cBoundingBox::getMyVertices(vector<cVector>& vertices)
{
    cVector center((xmax_ + xmin_)/2.0, (ymax_ + ymin_)/2.0, (zmax_ + zmin_)/2.0);
    float halfWidth = (xmax_ - xmin_)/2.0;
    vertices.push_back( center + halfWidth * cVector(-1,	-1,	-1) );
    vertices.push_back( center + halfWidth * cVector(-1,	-1,	1) );
    vertices.push_back( center + halfWidth * cVector(-1,	1,	-1) );
    vertices.push_back( center + halfWidth * cVector(-1,	1,	1) );
    vertices.push_back( center + halfWidth * cVector(1,		-1,	-1) );
    vertices.push_back( center + halfWidth * cVector(1,		-1,	1) );
    vertices.push_back( center + halfWidth * cVector(1,		1,	-1) );
    vertices.push_back( center + halfWidth * cVector(1,		1,	1) );
}

bool cBoundingBox::triangleIntersects(cTriangle& triangle)
{
    float boxcenter[3];
    boxcenter[0] = (xmin_ + xmax_)/2.0;
    boxcenter[1] = (ymin_ + ymax_)/2.0;
    boxcenter[2] = (zmin_ + zmax_)/2.0;
    
    float boxhalfsize[3];
    boxhalfsize[0] = (xmax_ - xmin_)/2.0;
    boxhalfsize[1] = (ymax_ - ymin_)/2.0;
    boxhalfsize[2] = (zmax_ - zmin_)/2.0;
    
    float triverts[3][3];
    triverts[0][0] = triangle.v0_->x_;
    triverts[0][1] = triangle.v0_->y_;
    triverts[0][2] = triangle.v0_->z_;
    
    triverts[1][0] = triangle.v1_->x_;
    triverts[1][1] = triangle.v1_->y_;
    triverts[1][2] = triangle.v1_->z_;
    
    triverts[2][0] = triangle.v2_->x_;
    triverts[2][1] = triangle.v2_->y_;
    triverts[2][2] = triangle.v2_->z_;
    
    return triBoxOverlap(boxcenter, boxhalfsize, triverts) == 1;
} 

void cBoundingBox::draw()
{
    color_.setGLColor();
    
    glBegin(GL_LINES);
        glVertex3f(xmin_,ymax_,zmin_);
        glVertex3f(xmax_,ymax_,zmin_);
    glEnd();
    
    glBegin(GL_LINES);
        glVertex3f(xmin_,ymax_,zmin_);
        glVertex3f(xmin_,ymax_,zmax_);
    glEnd();
    
    glBegin(GL_LINES);
        glVertex3f(xmin_,ymax_,zmin_);
        glVertex3f(xmin_,ymin_,zmin_);
    glEnd();
    
    glBegin(GL_LINES);
        glVertex3f(xmin_,ymax_,zmax_);
        glVertex3f(xmin_,ymin_,zmax_);
    glEnd();
    
    glBegin(GL_LINES);
        glVertex3f(xmin_,ymax_,zmax_);
        glVertex3f(xmax_,ymax_,zmax_);
    glEnd();
    
    glBegin(GL_LINES);
        glVertex3f(xmin_,ymin_,zmax_);
        glVertex3f(xmin_,ymin_,zmin_);
    glEnd();
    
    glBegin(GL_LINES);
        glVertex3f(xmin_,ymin_,zmax_);
        glVertex3f(xmax_,ymin_,zmax_);
    glEnd();
    
    glBegin(GL_LINES);
        glVertex3f(xmin_,ymin_,zmin_);
        glVertex3f(xmax_,ymin_,zmin_);
    glEnd();
    
    glBegin(GL_LINES);
        glVertex3f(xmax_,ymax_,zmax_);
        glVertex3f(xmax_,ymax_,zmin_);
    glEnd();
    
    glBegin(GL_LINES);
        glVertex3f(xmax_,ymax_,zmax_);
        glVertex3f(xmax_,ymin_,zmax_);
    glEnd();
    
    glBegin(GL_LINES);
        glVertex3f(xmax_,ymin_,zmin_);
        glVertex3f(xmax_,ymax_,zmin_);
    glEnd();
    
    glBegin(GL_LINES);
        glVertex3f(xmax_,ymin_,zmin_);
        glVertex3f(xmax_,ymin_,zmax_);
    glEnd();
}