www.pudn.com > zfxcengine-0.1.0.zip > ceAABB.cpp
// $Id: ceAABB.cpp,v 1.10 2005/08/10 20:13:08 kimmi Exp $ #include "Math/ceMath.h" #includenamespace ZFXCE { //------------------------------------------------------------------------------ ceAABB::ceAABB(ceVec3f vMin, ceVec3f vMax) { SetLimits(vMin, vMax); } //------------------------------------------------------------------------------ ceAABB::ceAABB(ceAABB &AABB) { ceVec3f vMin, vMax; AABB.GetLimits(vMin, vMax); m_vMin = vMin; m_vMax = vMax; } //------------------------------------------------------------------------------ void ceAABB::SetLimits(ceVec3f &vMin, ceVec3f &vMax) { m_vMin = vMin; m_vMax = vMax; m_vCenter = (vMax - vMin) * 0.5f; } //------------------------------------------------------------------------------ void ceAABB::GetLimits(ceVec3f &vMin, ceVec3f &vMax) { vMin = m_vMin; vMax = m_vMax; } //------------------------------------------------------------------------------ void ceAABB::ConstructFromOBB(const ceOBB& OBB) { ceVec3f vAxis0, vAxis1, vAxis2; vAxis0 = OBB.m_vAxis0 * OBB.m_fAxis0; vAxis1 = OBB.m_vAxis1 * OBB.m_fAxis1; vAxis2 = OBB.m_vAxis2 * OBB.m_fAxis2; // Computate extrem values if (vAxis0.x > vAxis1.x) { if(vAxis0.x > vAxis2.x) { m_vMax.x = vAxis0.x; m_vMin.x = -vAxis0.x; } else { m_vMax.x = vAxis2.x; m_vMin.x = -vAxis2.x; } } else { if(vAxis1.x > vAxis2.x) { m_vMax.x = vAxis1.x; m_vMin.x = -vAxis1.x; } else { m_vMax.x = vAxis2.x; m_vMin.x = -vAxis2.x; } } if (vAxis0.y > vAxis1.y) { if(vAxis0.y > vAxis2.y) { m_vMax.y = vAxis0.y; m_vMin.y = -vAxis0.y; } else { m_vMax.y = vAxis2.y; m_vMin.y = -vAxis2.y; } } else { if(vAxis1.y > vAxis2.y) { m_vMax.y = vAxis1.y; m_vMin.y = -vAxis1.y; } else { m_vMax.y = vAxis2.y; m_vMin.y = -vAxis2.y; } } if (vAxis0.z > vAxis1.z) { if (vAxis0.z > vAxis2.z) { m_vMax.z = vAxis0.z; m_vMin.z = -vAxis0.z; } else { m_vMax.z = vAxis2.z; m_vMin.z = -vAxis2.z; } } else { if(vAxis1.z > vAxis2.z) { m_vMax.z = vAxis1.z; m_vMin.z = -vAxis1.z; } else { m_vMax.z = vAxis2.z; m_vMin.z = -vAxis2.z; } } } //------------------------------------------------------------------------------ INT ceAABB::Cull(const cePlane* pPlanes, UINT uiNumOfPlanes) { ceVec3f vMin, vMax; bool bIntersects = false; // Berechnen und testen der Extrempunkte for (UINT i=0; i < uiNumOfPlanes; i++) { if(pPlanes[i].m_vNormal.x >= 0.0f) { vMin.x = m_vMin.x; vMax.x = m_vMax.x; } else { vMin.x = m_vMax.x; vMax.x = m_vMin.x; } if (pPlanes[i].m_vNormal.y >= 0.0f) { vMin.y = m_vMin.y; vMax.y = m_vMax.y; } else { vMin.y = m_vMax.y; vMax.y = m_vMin.y; } if(pPlanes[i].m_vNormal.z >= 0.0f) { vMin.z = m_vMin.z; vMax.z = m_vMax.z; } else { vMin.z = m_vMax.z; vMax.z = m_vMin.z; } if (((pPlanes[i].m_vNormal * vMin) + pPlanes[i].m_fDistance) > 0.0f) return ceCulled; if (((pPlanes[i].m_vNormal * vMax) + pPlanes[i].m_fDistance) >= 0.0f) bIntersects = true; } if (bIntersects) return ceClipped; return ceVisible; } //------------------------------------------------------------------------------ void ceAABB::GetPlanes(cePlane* pPlanes) const { ceVec3f vNormal; if (!pPlanes) return; // Rechts vNormal.Set(1.0f, 0.0f, 0.0f); pPlanes[0].Set(vNormal, m_vMax); // links vNormal.x = -1.0f; pPlanes[1].Set(vNormal, m_vMin); // vorne vNormal.x = 0.0f; vNormal.z = -1.0f; pPlanes[2].Set(vNormal,m_vMin); // hinten vNormal.z = 1.0f; pPlanes[3].Set(vNormal, m_vMax); // oben vNormal.y = 1.0f; vNormal.z = 0.0f; pPlanes[4].Set(vNormal, m_vMax); // unten vNormal.y = -1.0f; pPlanes[5].Set(vNormal, m_vMin); } //------------------------------------------------------------------------------ void ceAABB::GetVertices(std::vector &Vertices) { PUSH_FUNCTION; // 8 7 // x -- x // 5 / | 6/ | // x | x | // | x |- x // | / 4 | /3 // x --- x // 1 2 // Vertice 1 m_Edges[0].x = m_vMin.x; //Vertices[0].x = m_vMin.x; m_Edges[0].y = m_vMin.y; //Vertices[0].y = m_vMin.y; m_Edges[0].z = m_vMin.z; //Vertices[0].z = m_vMin.z; Vertices.push_back(m_Edges[0]); // Vertice 2 m_Edges[1].x = m_vMax.x; //Vertices[1].x = m_vMax.x; m_Edges[1].y = m_vMin.y; //Vertices[1].y = m_vMin.y; m_Edges[1].z = m_vMin.z; //Vertices[1].z = m_vMin.z; Vertices.push_back(m_Edges[1]); // Vertice 3 m_Edges[2].x = m_vMax.x; //Vertices[2].x = m_vMax.x; m_Edges[2].y = m_vMax.y; //Vertices[2].y = m_vMax.y; m_Edges[2].z = m_vMin.z; //Vertices[2].z = m_vMin.z; Vertices.push_back(m_Edges[2]); // Vertice 4 m_Edges[3].x = m_vMin.x; //Vertices[3].x = m_vMin.x; m_Edges[3].y = m_vMax.y; //Vertices[3].y = m_vMax.y; m_Edges[3].z = m_vMin.z; //Vertices[3].z = m_vMin.z; Vertices.push_back(m_Edges[3]); // Vertice 5 m_Edges[4].x = m_vMin.x; //Vertices[0].x = m_vMin.x; m_Edges[4].y = m_vMin.y; //Vertices[0].y = m_vMin.y; m_Edges[4].z = m_vMax.z; //Vertices[0].z = m_vMax.z; Vertices.push_back(m_Edges[4]); // Vertice 6 m_Edges[5].x = m_vMax.x; //Vertices[1].x = m_vMax.x; m_Edges[5].y = m_vMin.y; //Vertices[1].y = m_vMin.y; m_Edges[5].z = m_vMax.z; //Vertices[1].z = m_vMax.z; Vertices.push_back(m_Edges[5]); // Vertice 7 m_Edges[6].x = m_vMax.x; //Vertices[2].x = m_vMax.x; m_Edges[6].y = m_vMax.y; //Vertices[2].y = m_vMax.y; m_Edges[6].z = m_vMax.z; //Vertices[2].z = m_vMax.z; Vertices.push_back(m_Edges[6]); // Vertice 8 m_Edges[7].x = m_vMin.x; //Vertices[3].x = m_vMin.x; m_Edges[7].y = m_vMax.y; //Vertices[3].y = m_vMax.y; m_Edges[7].z = m_vMax.z; //Vertices[3].z = m_vMax.z; Vertices.push_back(m_Edges[7]); } //------------------------------------------------------------------------------ bool ceAABB::Contains(const ceRay& Ray, FLOAT fL) const { const ceVec3f vEnd = Ray.m_vOrigin + (Ray.m_vDir * fL); return ( Intersects(Ray.m_vOrigin) && Intersects(vEnd) ); } //------------------------------------------------------------------------------ bool ceAABB::Intersects(const ceRay& Ray, FLOAT* pF) const { FLOAT fT0, fT1, fTmp; FLOAT fNear = -999999.9f; FLOAT fFar = 999999.9f; FLOAT fEpsilon = 0.00001f; // Die ersten beiden Ebenen if(_fabs(Ray.m_vDir.x) < fEpsilon) if( Ray.m_vOrigin.x < m_vMin.x || Ray.m_vOrigin.x > m_vMax.x ) return FALSE; fT0 = (m_vMin.x - Ray.m_vOrigin.x) / Ray.m_vDir.x; fT1 = (m_vMax.x - Ray.m_vOrigin.x) / Ray.m_vDir.x; if (fT0 > fT1) { fTmp = fT0; fT0 = fT1; fT1 = fTmp; } if(fT0 > fNear) fNear = fT0; if(fT1 < fFar) fFar = fT1; if(fNear > fFar) return FALSE; if(fFar < 0) return FALSE; // Die nächsten beiden if(_fabs(Ray.m_vDir.y) < fEpsilon) if( Ray.m_vOrigin.y < m_vMin.y || Ray.m_vOrigin.y > m_vMax.y ) return FALSE; fT0 = (m_vMin.y - Ray.m_vOrigin.y) / Ray.m_vDir.y; fT1 = (m_vMax.y - Ray.m_vOrigin.y) / Ray.m_vDir.y; if(fT0 > fT1) { fTmp = fT0; fT0 = fT1; fT1 = fTmp; } if(fT0 > fNear) fNear = fT0; if(fT1 < fFar) fFar = fT1; if(fNear > fFar) return false; if(fFar < 0) return false; // und die letzten beiden if(_fabs(Ray.m_vDir.z) < fEpsilon) if( Ray.m_vOrigin.z < m_vMin.z || Ray.m_vOrigin.z > m_vMax.z ) return false; fT0 = (m_vMin.z - Ray.m_vOrigin.z) / Ray.m_vDir.z; fT1 = (m_vMax.z - Ray.m_vOrigin.z) / Ray.m_vDir.z; if(fT0 > fT1) { fTmp = fT0; fT0 = fT1; fT1 = fTmp; } if (fT0 > fNear) fNear = fT0; if (fT1 < fFar) fFar = fT1; if (fNear > fFar) return false; if (fFar < 0) return false; if (fNear > 0) { if(pF) (*pF) = fNear; } else { if(pF) (*pF) = fFar; } return true; } //------------------------------------------------------------------------------ bool ceAABB::Intersects(const ceRay& Ray, FLOAT fL, FLOAT* pF) const { FLOAT fT0, fT1, fTmp; FLOAT fNear = -999999.9f; FLOAT fFar = 999999.9f; FLOAT fEpsilon = 0.00001f; // Die ersten beiden Ebenen if(_fabs(Ray.m_vDir.x) < fEpsilon) if( Ray.m_vOrigin.x < m_vMin.x || Ray.m_vOrigin.x > m_vMax.x ) return FALSE; const FLOAT fXVal = 1 / Ray.m_vDir.x; fT0 = (m_vMin.x - Ray.m_vOrigin.x) * fXVal; fT1 = (m_vMax.x - Ray.m_vOrigin.x) * fXVal; if(fT0 > fT1) { fTmp = fT0; fT0 = fT1; fT1 = fTmp; } if(fT0 > fNear) fNear = fT0; if(fT1 < fFar) fFar = fT1; if(fNear > fFar) return false; if(fFar < 0) return false; // Die nächsten beiden if(_fabs(Ray.m_vDir.y) < fEpsilon) if( Ray.m_vOrigin.y < m_vMin.y || Ray.m_vOrigin.y > m_vMax.y ) return false; const FLOAT fYVal = 1 / Ray.m_vDir.y; fT0 = (m_vMin.y - Ray.m_vOrigin.y) * fYVal; fT1 = (m_vMax.y - Ray.m_vOrigin.y) * fYVal; if(fT0 > fT1) { fTmp = fT0; fT0 = fT1; fT1 = fTmp; } if(fT0 > fNear) fNear = fT0; if(fT1 < fFar) fFar = fT1; if(fNear > fFar) return false; if(fFar < 0) return false; // und die letzten beiden if(_fabs(Ray.m_vDir.z) < fEpsilon) if( Ray.m_vOrigin.z < m_vMin.z || Ray.m_vOrigin.z > m_vMax.z ) return false; const FLOAT fZVal = 1 / Ray.m_vDir.z; fT0 = (m_vMin.z - Ray.m_vOrigin.z) * fZVal; fT1 = (m_vMax.z - Ray.m_vOrigin.z) * fZVal; if (fT0 > fT1) { fTmp = fT0; fT0 = fT1; fT1 = fTmp; } if(fT0 > fNear) fNear = fT0; if(fT1 < fFar) fFar = fT1; if(fNear > fFar) return false; if(fFar < 0) return false; FLOAT fFinal = 0.0f; if(fNear > 0) fFinal = fNear; else fFinal = fFar; if(fFinal > fL) return false; if (NULL != pF) (*pF) = fFinal; return true; } //------------------------------------------------------------------------------ bool ceAABB::Intersects(const ceAABB& AABB) const { if( m_vMin.x > AABB.m_vMax.x || AABB.m_vMin.x > m_vMax.x) return false; if( m_vMin.y > AABB.m_vMax.y || AABB.m_vMin.y > m_vMax.y) return false; if( m_vMin.z > AABB.m_vMax.z || AABB.m_vMin.z > m_vMax.z) return false; return true; } //------------------------------------------------------------------------------ bool ceAABB::Intersects(const ceVec3f& v) const { if(v.x > m_vMax.x) return false; if(v.y > m_vMax.y) return false; if(v.z > m_vMax.z) return false; if(v.x < m_vMin.x) return false; if(v.y < m_vMin.y) return false; if(v.z < m_vMin.z) return false; return true; } //------------------------------------------------------------------------------ bool ceAABB::Merge(ceAABB &AABB) { ceVec3f vMin, vMax; AABB.GetLimits(vMin, vMax); if (m_vMin.x > vMin.x) m_vMin.x = vMin.x; if (m_vMin.y > vMin.y) m_vMin.y = vMin.y; if (m_vMin.z > vMin.z) m_vMin.z = vMin.z; if (m_vMax.x < vMax.x) m_vMax.x = vMax.x; if (m_vMax.y < vMax.y) m_vMax.y = vMax.y; if (m_vMax.z < vMax.z) m_vMax.z = vMax.z; return true; } //------------------------------------------------------------------------------ bool ceAABB::Merge(ceOBB &OBB) { return false; } //------------------------------------------------------------------------------ void ceAABB::Transform(ceMatrix &Transform) { ceVec3f vNew; for (size_t i=0; i<8; ++i) { vNew = Transform * this->m_Edges[i]; if (m_vMin.x > vNew.x) m_vMin.x = vNew.x; if (m_vMin.y > vNew.y) m_vMin.y = vNew.y; if (m_vMin.z > vNew.z) m_vMin.z = vNew.z; if (m_vMax.x < vNew.x) m_vMax.x = vNew.x; if (m_vMax.y < vNew.y) m_vMax.y = vNew.y; if (m_vMax.z < vNew.z) m_vMax.z = vNew.z; } } //------------------------------------------------------------------------------ ceAABB& ceAABB::operator = (const ceAABB& AABB) { m_vMin = AABB.m_vMin; m_vMax = AABB.m_vMax; m_bUpdate = AABB.m_bUpdate; for (int i=0; i<8; ++i) { this->m_Edges[i] = AABB.m_Edges[i]; } return *this; } //------------------------------------------------------------------------------ } // Namespace ZFXCE