#include "dxstdafx.h" #include ".\quad.h" #include "Camera.h" #include "Plane.h" Quad::Quad(void) { this->width = 0; this->height = 0; this->level = -1; for(int i=0;i<4;i++) { q[i] = 0; } this->fullyVisible = false; this->partlyVisible = false; } Quad::~Quad(void) { this->deleteQuadTree(); } void Quad::setPosition(float _x, float _z) { this->position.x = _x; this->position.y = 0; this->position.z = _z; //BBox berechnen this->minBBox.x = this->position.x - this->width/2; this->minBBox.y = 0; this->minBBox.z = this->position.z - this->height/2; this->maxBBox.x = this->position.x + this->width/2; this->maxBBox.y = 0; this->maxBBox.z = this->position.z + this->height/2; } void Quad::setDimension(float _width, float _height) { this->width = _width; this->height = _height; //BBox berechnen this->minBBox.x = this->position.x - this->width/2; this->minBBox.y = 0; this->minBBox.z = this->position.z - this->height/2; this->maxBBox.x = this->position.x + this->width/2; this->maxBBox.y = 0; this->maxBBox.z = this->position.z + this->height/2; } void Quad::buildQuadTree(int _level) { this->level = _level-1; float tx = 0; float tz = 0; for(int i=0;i<4;i++) { q[i] = new Quad(); q[i]->setDimension(this->width/2, this->height/2); //Positionieren switch(i) { case 0: tx = this->position.x - this->width/4; tz = this->position.z - this->height/4; break; case 1: tx = this->position.x + this->width/4; tz = this->position.z - this->height/4; break; case 2: tx = this->position.x - this->width/4; tz = this->position.z + this->height/4; break; case 3: tx = this->position.x + this->width/4; tz = this->position.z + this->height/4; break; } q[i]->setPosition(tx, tz); if(this->level>0) { q[i]->buildQuadTree(this->level); } } } void Quad::clipQuadAgainstCamera(Plane *view)//, std::list &visibleQuadList) { { this->fullyVisible = false; this->partlyVisible = false; switch(getClipType(view)) { case 0: //The Quad is in the Cameras ViewFrustum this->fullyVisible = true; //visibleQuadList.push_back(this); break; case 1: //The Quad is outside the Cameras ViewFrustum break; default: //The Quad is not fully in Cameras ViewFrustum (go down one level) if(this->level>0) { this->partlyVisible = true; for(int i=0;i<4;i++) q[i]->clipQuadAgainstCamera(view);//, visibleQuadList); } else { //Level 0 Quad which is partly visible -> quad is visible this->fullyVisible = true; //visibleQuadList.push_back(this); } break; } } bool Quad::nodeInside(Node* node) { if(!this->fullyVisible && !this->partlyVisible) { return false; } if(this->fullyVisible) { Vector *minNode; Vector *maxNode; minNode = &node->absMinAABBox; maxNode = &node->absMaxAABBox; if(maxNode->x < this->minBBox.x || minNode->x > this->maxBBox.x || maxNode->z < this->minBBox.z || minNode->z > this->maxBBox.z) { return false; } else { return true; } } if(this->partlyVisible) { for(int i=0;i<4;i++) { if(q[i]->nodeInside(node)) { return true; } } return false; } return false; } void Quad::deleteQuadTree() { if(this->level>=0) { for(int i=0;i<4;i++) { delete this->q[i]; } } } Vector Quad::getMinBBox() { return minBBox; } Vector Quad::getMaxBBox() { return maxBBox; } int Quad::getClipType(Plane *view) { bool inSide[6]; Vector corner[4]; corner[0] = this->maxBBox; corner[1].x = this->maxBBox.x; corner[1].z = this->minBBox.z; corner[2] = this->minBBox; corner[3].x = this->minBBox.x; corner[3].z = this->maxBBox.z; //Ueberpruefen ob alle Punkte außerhalb einer Frustumfläche der Kamera liegen -> quad is outside //Ueberprüfung findet fuer front, near, left und right statt da die quads die höhe 0 haben! bool bInFront[16]; for(int i=0;i<16;i+=4) { bInFront[i+0] = view[i/4].inFront(corner[0]); bInFront[i+1] = view[i/4].inFront(corner[1]); bInFront[i+2] = view[i/4].inFront(corner[2]); bInFront[i+3] = view[i/4].inFront(corner[3]); } for(int i=0;i<4;i++) { if(bInFront[i*4+0] == false && bInFront[i*4+1] == false && bInFront[i*4+2] == false && bInFront[i*4+3] == false) { //Quad is behind plane i -> quad is outside of frustum return 1; } } //Ueberpruefen ob alle Punkte innerhalb des Frustums liegen -> quad is inside for(int i=0;i<4;i++) { if(bInFront[i*4+0] == true && bInFront[i*4+1] == true && bInFront[i*4+2] == true && bInFront[i*4+3] == true) { //Quad is behind plane i -> quad is outside of frustum inSide[i] = true; } else { inSide[i] = false; } } if(inSide[0] == true && inSide[1] == true && inSide[2] == true && inSide[3] == true) { //Quad is completely inside frustum return 0; } //sonst Quad schneidet Frustum -> divide & conquer return -1; }