/** * Split the bounding box in several bounding boxes at limitSize. * If original box doesn't exceed limit size, the original box is returned. */ std::vector<AABBox<float>> SplitBoundingBox::split(const AABBox<float> &aabbox) const { std::vector<float> axisSplits[3]; for(unsigned int axis=0; axis<3; ++axis) { float size = aabbox.getHalfSize(axis) * 2.0f; axisSplits[axis].push_back(aabbox.getMin()[axis]); auto nbSplits = static_cast<int>(std::ceil(size/limitSize)); float maxValue = aabbox.getMax()[axis]; for(int split = 0; split < nbSplits; ++split) { float splitValue = std::min(aabbox.getMin()[axis] + limitSize*(split+1), maxValue); axisSplits[axis].push_back(splitValue); } } std::vector<AABBox<float>> splittedBoundingBox; for(unsigned int x=1; x<axisSplits[0].size(); ++x) { for(unsigned int y=1; y<axisSplits[1].size(); ++y) { for(unsigned int z=1; z<axisSplits[2].size(); ++z) { Point3<float> minPoint(axisSplits[0][x-1], axisSplits[1][y-1], axisSplits[2][z-1]); Point3<float> maxPoint(axisSplits[0][x], axisSplits[1][y], axisSplits[2][z]); splittedBoundingBox.emplace_back(AABBox<float>(minPoint, maxPoint)); } } } return splittedBoundingBox; }
bool FrustumShadowData::areIdenticalAABBox(const AABBox<float> &shadowCasterReceiverBox1, const AABBox<float> &shadowCasterReceiverBox2) const { constexpr float SQUARE_EPSILON = 0.0001f * 0.0001f; return shadowCasterReceiverBox1.getMin().squareDistance(shadowCasterReceiverBox2.getMin())<SQUARE_EPSILON && shadowCasterReceiverBox1.getMax().squareDistance(shadowCasterReceiverBox2.getMax())<SQUARE_EPSILON; }
/** * @return True if the bounding box collides or is inside this frustum */ template<class T> bool Frustum<T>::collideWithAABBox(const AABBox<T> &bbox) const { for (auto &plane : planes) { const Vector3<T> &normal = plane.getNormal(); Point3<T> nVertex(bbox.getMax()); if(normal.X >= 0.0) { nVertex.X = bbox.getMin().X; } if(normal.Y >= 0.0) { nVertex.Y = bbox.getMin().Y; } if(normal.Z >= 0.0) { nVertex.Z = bbox.getMin().Z; } if (plane.distance(nVertex) > 0.0) { return false; } } return true; }
/** * @return Box in light space containing shadow caster and receiver (scene dependent) */ AABBox<float> ShadowManager::createSceneDependentBox(const AABBox<float> &aabboxSceneIndependent, const OBBox<float> &obboxSceneIndependentViewSpace, const std::set<Model *> &models, const Matrix4<float> &lightViewMatrix) const { AABBox<float> aabboxSceneDependent; bool boxInitialized = false; AABBox<float> aabboxSceneIndependentViewSpace = obboxSceneIndependentViewSpace.toAABBox(); for(std::set<Model *>::iterator it = models.begin(); it!=models.end(); ++it) { const Model* model = *it; if(model->isProduceShadow()) { const std::vector<AABBox<float>> &splittedAABBox = model->getSplittedAABBox(); for(unsigned int i=0; i<splittedAABBox.size(); ++i) { if(splittedAABBox.size()==1 || obboxSceneIndependentViewSpace.collideWithAABBox(splittedAABBox[i])) { if(boxInitialized) { aabboxSceneDependent = aabboxSceneDependent.merge(lightViewMatrix * splittedAABBox[i]); }else { aabboxSceneDependent = lightViewMatrix * splittedAABBox[i]; boxInitialized = true; } } } } } Point3<float> cutMin( aabboxSceneDependent.getMin().X<aabboxSceneIndependent.getMin().X ? aabboxSceneIndependent.getMin().X : aabboxSceneDependent.getMin().X, aabboxSceneDependent.getMin().Y<aabboxSceneIndependent.getMin().Y ? aabboxSceneIndependent.getMin().Y : aabboxSceneDependent.getMin().Y, aabboxSceneIndependent.getMin().Z); //shadow can be projected outside the box: value cannot be capped Point3<float> cutMax( aabboxSceneDependent.getMax().X>aabboxSceneIndependent.getMax().X ? aabboxSceneIndependent.getMax().X : aabboxSceneDependent.getMax().X, aabboxSceneDependent.getMax().Y>aabboxSceneIndependent.getMax().Y ? aabboxSceneIndependent.getMax().Y : aabboxSceneDependent.getMax().Y, aabboxSceneDependent.getMax().Z>aabboxSceneIndependent.getMax().Z ? aabboxSceneIndependent.getMax().Z : aabboxSceneDependent.getMax().Z); cutMin.X = (cutMin.X<0.0f) ? cutMin.X-(lightViewOverflowStepSize+fmod(cutMin.X, lightViewOverflowStepSize)) : cutMin.X-fmod(cutMin.X, lightViewOverflowStepSize); cutMin.Y = (cutMin.Y<0.0f) ? cutMin.Y-(lightViewOverflowStepSize+fmod(cutMin.Y, lightViewOverflowStepSize)) : cutMin.Y-fmod(cutMin.Y, lightViewOverflowStepSize); cutMin.Z = (cutMin.Z<0.0f) ? cutMin.Z-(lightViewOverflowStepSize+fmod(cutMin.Z, lightViewOverflowStepSize)) : cutMin.Z-fmod(cutMin.Z, lightViewOverflowStepSize); cutMax.X = (cutMax.X<0.0f) ? cutMax.X-fmod(cutMax.X, lightViewOverflowStepSize) : cutMax.X+(lightViewOverflowStepSize-fmod(cutMax.X, lightViewOverflowStepSize)); cutMax.Y = (cutMax.Y<0.0f) ? cutMax.Y-fmod(cutMax.Y, lightViewOverflowStepSize) : cutMax.Y+(lightViewOverflowStepSize-fmod(cutMax.Y, lightViewOverflowStepSize)); cutMax.Z = (cutMax.Z<0.0f) ? cutMax.Z-fmod(cutMax.Z, lightViewOverflowStepSize) : cutMax.Z+(lightViewOverflowStepSize-fmod(cutMax.Z, lightViewOverflowStepSize)); return AABBox<float>(cutMin, cutMax); }
void AABBNode::updateAABBox(float fatMargin) { if (isLeaf()) { Point3<float> fatMargin3(fatMargin, fatMargin, fatMargin); AABBox<float> bodyBox = bodyNodeData->retrieveBodyAABBox(); aabbox = AABBox<float>(bodyBox.getMin()-fatMargin3, bodyBox.getMax()+fatMargin3); }else { aabbox = children[0]->getAABBox().merge(children[1]->getAABBox()); } }
void ShapeToAABBoxTest::boxConversion() { CollisionBoxShape collisionBox(Vector3<float>(1.0, 2.0, 1.0)); //box 1x2x1 PhysicsTransform transform(urchin::Point3<float>(0.0, 0.0, 0.0), //move 0 unit on X, Y and Z axis urchin::Quaternion<float>(urchin::Vector3<float>(0.0, 0.0, 1.0), 3.14159265358979/4)); //rotate 45° on Z axis AABBox<float> box = collisionBox.toAABBox(transform); AssertHelper::assertFloatEquals(box.getHalfSize(0), 2.12132034356); AssertHelper::assertFloatEquals(box.getHalfSize(1), 2.12132034356); AssertHelper::assertFloatEquals(box.getHalfSize(2), 1.0); AssertHelper::assertPoint3FloatEquals(box.getMin(), Point3<float>(-2.12132034356, -2.12132034356, -1.0)); AssertHelper::assertPoint3FloatEquals(box.getMax(), Point3<float>(2.12132034356, 2.12132034356, 1.0)); }
void ShapeToAABBoxTest::convexHullConversion() { Point3<float> boxPointsTab[] = { Point3<float>(-1.0, -2.0, 1.0), Point3<float>(1.0, -2.0, 1.0), Point3<float>(1.0, 2.0, 1.0), Point3<float>(-1.0, 2.0, 1.0), Point3<float>(-1.0, -2.0, -1.0), Point3<float>(1.0, -2.0, -1.0), Point3<float>(1.0, 2.0, -1.0), Point3<float>(-1.0, 2.0, -1.0), }; std::vector<Point3<float>> boxPoints(boxPointsTab, boxPointsTab+sizeof(boxPointsTab)/sizeof(Point3<float>)); CollisionConvexHullShape collisionConvexHull(0.0, boxPoints); PhysicsTransform transform(urchin::Point3<float>(0.0, 0.0, 0.0), //move 0 unit on X, Y and Z axis urchin::Quaternion<float>(urchin::Vector3<float>(0.0, 0.0, 1.0), -3.14159265358979/4)); //rotate 45° on Z axis AABBox<float> box = collisionConvexHull.toAABBox(transform); AssertHelper::assertFloatEquals(box.getHalfSize(0), 2.12132034356); AssertHelper::assertFloatEquals(box.getHalfSize(1), 2.12132034356); AssertHelper::assertFloatEquals(box.getHalfSize(2), 1.0); AssertHelper::assertPoint3FloatEquals(box.getMin(), Point3<float>(-2.12132034356, -2.12132034356, -1.0)); AssertHelper::assertPoint3FloatEquals(box.getMax(), Point3<float>(2.12132034356, 2.12132034356, 1.0)); }