// Workaround to avoid invisible objects due to wrong clipping planes // all scenes are scaled to a radius of 5 void AbstractNavigation::rescaleScene( Group * scene ) { AxisAlignedBoundingBox bb = scene->boundingBox(); glm::mat4 scale_matrix = glm::scale(glm::vec3(5.0f / bb.radius())); m_sceneTransform = scale_matrix * scene->transform(); scene->setTransform(m_sceneTransform); }
void AxisAlignedBoundingBox< T >::merge( const AxisAlignedBoundingBox< T >& aabb ) { if ( aabb._empty ) return; // nothing to do if ( _empty ) { // copy non-empty aabb _min = aabb._min; _max = aabb._max; _empty = _dirty = false; return; } // else merge the two aabbs const vector< 3, T >& min = aabb.getMin(); const vector< 3, T >& max = aabb.getMax(); if ( min.x() < _min.x() ) _min.x() = min.x(); if ( min.y() < _min.y() ) _min.y() = min.y(); if ( min.z() < _min.z() ) _min.z() = min.z(); if ( max.x() > _max.x() ) _max.x() = max.x(); if ( max.y() > _max.y() ) _max.y() = max.y(); if ( max.z() > _max.z() ) _max.z() = max.z(); }
//------------------------------------------------------------------------ float KdTreeNode::cost(const AxisAlignedBoundingBox& aabb, unsigned int lowerCount, unsigned int greaterCount, float distance, Vector3::AXIS direction) const { float lowerSurfaceArea = aabb.getLowerSubAABB(distance, direction).getSurfaceArea(); float greaterSurfaceArea = aabb.getGreaterSubAABB(distance, direction).getSurfaceArea(); return 2.f + 10.f * (lowerSurfaceArea * lowerCount + greaterSurfaceArea * greaterCount); }
const AxisAlignedBoundingBox PolygonalDrawable::boundingBox(glm::mat4 transform) const { AxisAlignedBoundingBox aabb = AxisAlignedBoundingBox(); glm::mat4 newTransform; if( m_geometry == nullptr ) { return aabb; } if (m_rf == RF_Absolute) { newTransform = transform; } else { newTransform = this->transform() * transform; } t_VertexListP myVList = m_geometry->vertices(); myVList->foreachVertexAttribute<glm::vec3>(0, myVList->size(), "position", nullptr, [&aabb, &newTransform](int i, const glm::vec3 & pos) { aabb.extend( glm::vec3(newTransform * glm::vec4(pos, 1.0f)) ); } ); return aabb; }
bool BoundingSphere::encloses(const AxisAlignedBoundingBox& axisAlignedBox) const { float halfDiagonal = glusMathLengthf(axisAlignedBox.getHalfWidth(), axisAlignedBox.getHalfHeight(), axisAlignedBox.getHalfDepth()); float distance = center.distance(axisAlignedBox.getCenter()); return distance + halfDiagonal <= radius; }
// gets called at every program start and when a new file is opened in the viewer void AbstractNavigation::sceneChanged(Group * scene) { AxisAlignedBoundingBox bb = scene->boundingBox(); m_BBRadius = bb.radius(); m_frontView = glm::lookAt(bb.center() + glm::vec3(0.f, 0.f, bb.radius()*2.5), bb.center(), glm::vec3(0.f, 1.f, 0.f)); setFromMatrix(topRightView()); updateCamera(); }
TEST(AxisAlignedBoundingBox, setExtents) { Vector3 min(-1, -1, -1); Vector3 max(1, 1, 1); AxisAlignedBoundingBox aabb; aabb.setExtents(min, max); ASSERT_EQ(min, aabb.getMinimum()); ASSERT_EQ(max, aabb.getMaximum()); }
void LightSourcePass::sceneChanged(Group * scene) { if(m_scene) m_lightcam->remove(m_scene); m_lightcam->append(scene); AxisAlignedBoundingBox bb = scene->boundingBox(); m_lightcam->setView(glm::lookAt(glm::vec3(4.0f, 5.5f, 6.0f) + bb.center(), bb.center(), glm::vec3(0.0f,1.0f,0.0f))); m_scene = scene; }
IntersectionTest::Result IntersectionTest::plane_aabb(const Vec4f &plane, const AxisAlignedBoundingBox &aabb) { Vec3f center = aabb.center(); Vec3f extents = aabb.extents(); float e = extents.x * std::abs(plane.x) + extents.y * std::abs(plane.y) + extents.z * std::abs(plane.z); float s = center.x * plane.x + center.y * plane.y + center.z * plane.z + plane.w; if (s - e > 0) return inside; else if (s + e < 0) return outside; else return intersecting; }
void PlayableEmotion::updatePos(Vec2 center) { centerPos = center; //update axis aligned bouding box AxisAlignedBoundingBox *box = (AxisAlignedBoundingBox *) collisionVolume; box->setLeftTopCorner(centerPos + center_LT_displacement); //update auxliar collision circles const Vec2 &aux = Vec2::getVec2FromPolar(box->axisAlignedRectangle.h / 4, (float) M_PI_2); auxCollisionVolume[0].setCenter(centerPos + aux); auxCollisionVolume[1].setCenter(centerPos); auxCollisionVolume[2].setCenter(centerPos + aux * (-1.0)); }
void SimObject::expandAxisAlignedBoundingBox(AxisAlignedBoundingBox& box) { updateLocalBoundingBox(); ObjectList::iterator pos; for(pos = childNodes.begin(); pos != childNodes.end(); ++pos) { (*pos)->expandAxisAlignedBoundingBox(boundingBox); } box.expand(boundingBox); }
const AxisAlignedBoundingBox TriangleObject::boundingBox(glm::mat4 transform) const { AxisAlignedBoundingBox aabb = AxisAlignedBoundingBox(); glm::mat4 newTransform; if ( m_triangles->size() == 0 ) return aabb; if (m_rf == RF_Absolute) { newTransform = transform; } else { newTransform = this->transform() * transform; } for ( auto vertex : *m_triangles ) { glm::vec4 transformedVertex = newTransform * glm::vec4(vertex, 1.0f); aabb.extend( transformedVertex.xyz * (1.0f / transformedVertex.w) ); } return aabb; }
IntersectionTest::OverlapResult IntersectionTest::ray_aabb(const Vec3f &ray_start, const Vec3f &ray_end, const AxisAlignedBoundingBox &aabb) { Vec3f c = (ray_start + ray_end) * 0.5f; Vec3f w = ray_end - c; Vec3f h = aabb.extents(); c -= aabb.center(); Vec3f v(std::abs(w.x), std::abs(w.y), std::abs(w.z)); if (std::abs(c.x) > v.x + h.x || std::abs(c.y) > v.y + h.y || std::abs(c.z) > v.z + h.z) return disjoint; if (std::abs(c.y * w.z - c.z * w.y) > h.y * v.z + h.z * v.y || std::abs(c.x * w.z - c.z * w.x) > h.x * v.z + h.z * v.x || std::abs(c.x * w.y - c.y * w.x) > h.x * v.y + h.y * v.x) return disjoint; return overlap; }
AxisAlignedBoundingBox AssimpScene::retrieveAxisAlignedBoundingBox(const aiScene * scene) { AxisAlignedBoundingBox aabb; for (unsigned int m = 0; m < scene->mNumMeshes; ++m) { aiMesh * mesh = scene->mMeshes[m]; for (unsigned int v = 0; v < mesh->mNumVertices; ++v) { const QVector3D vec3( mesh->mVertices[v].x , mesh->mVertices[v].y , mesh->mVertices[v].z); aabb.extend(vec3); } } return aabb; }
TEST(AxisAlignedBoundingBox, Merge) { AxisAlignedBoundingBox aabb; { Vector3 min(-1, -1, -1); Vector3 max(0, 0, 0); AxisAlignedBoundingBox aabbComponent(min, max); aabb.merge(aabbComponent); } { Vector3 min(0, 0, 0); Vector3 max(1, 1, 1); AxisAlignedBoundingBox aabbComponent(min, max); aabb.merge(aabbComponent); } Vector3 expectedMin(-1, -1, -1); Vector3 expectedMax(1, 1, 1); ASSERT_EQ(expectedMin, aabb.getMinimum()); ASSERT_EQ(expectedMax, aabb.getMaximum()); }
void PathTracingBVH::addToGeometry(Node *node) { AxisAlignedBoundingBox aabb = node->boundingBox(); int aabbIndex = m_geometry->size(); m_geometry->push_back(glm::vec4()); //llf dummy m_geometry->push_back(glm::vec4()); //urb dummy //add triangles for (auto child : node->children()) { if (child->children().size() == 0) { //the current child is a leaf ==> it is a triangle object TriangleObject *triangleObject = dynamic_cast<TriangleObject *>(child); if (triangleObject == nullptr) { //we have to be safe because it could also be an empty Group qDebug() << "PathTracingBVH : addToGeometry(Node *) : dynamic cast to TriangleObject * failed"; continue; } p_TriangleList triangles = triangleObject->triangles(); for (int i = 2; i < triangles->size(); i += 3) { m_geometry->push_back(glm::vec4(triangles->at(i - 2), 3.0f)); // data1 m_geometry->push_back(glm::vec4(triangles->at(i - 1), 0.0f)); // data2 m_geometry->push_back(glm::vec4(triangles->at(i ), 0.0f)); // data3 } } else { //internal node addToGeometry(child); } } glm::vec3 aabbEnlargement = aabb.radius() * glm::vec3(0.000001f, 0.000001f, 0.000001f); m_geometry->at(aabbIndex) = glm::vec4( aabb.llf() - aabbEnlargement, //llf 0.0f //we are a bounding box ); //data1 m_geometry->at(aabbIndex + 1) = glm::vec4( aabb.urb() + aabbEnlargement, //urb float(m_geometry->size()) // points to one behind the last entry in geometry list, // that is the next object on the same hierarchy level (or a higher hierarchy level // if there is none on the same) ); //data2 }
RelativeLocation Plane::TestAABB(const AxisAlignedBoundingBox& aabb) const { bool bFront = false;; bool bBack = false; vector<Vector3F> vCorners; aabb.GetCorners(vCorners); unsigned int NumOfCorners = vCorners.size(); for(unsigned int i = 0; i < NumOfCorners; ++i) { RelativeLocation rl = TestPoint(vCorners[i]); switch(rl) { case RL_FRONT: bFront = true; if(bBack) { return RL_SPLIT; } break; case RL_BACK: bBack = true; if(bFront) { return RL_SPLIT; } break; default: break; } } return bFront? RL_FRONT: RL_BACK; }
void TextEngineRenderer::DrawAxisAlignedBoundingBox(AxisAlignedBoundingBox aabb) { DrawRectangle(aabb.center(), aabb.extent()); }
bool NavigationMath::boundaryVisible( const QMatrix4x4 & mvp , const AxisAlignedBoundingBox & b) { const QVector3D box[8] = { // front QVector3D(b.llf().x(), b.llf().y(), b.urb().z()) , QVector3D(b.urb().x(), b.llf().y(), b.urb().z()) , QVector3D(b.urb().x(), b.urb().y(), b.urb().z()) , QVector3D(b.llf().x(), b.urb().y(), b.urb().z()) // back , QVector3D(b.llf().x(), b.llf().y(), b.llf().z()) , QVector3D(b.urb().x(), b.llf().y(), b.llf().z()) , QVector3D(b.urb().x(), b.urb().y(), b.llf().z()) , QVector3D(b.llf().x(), b.urb().y(), b.llf().z()) }; // transform bounds and check if any point is outside NDC (Normalized Device // Coordinates) space for(int i = 0; i < 8; ++i) { const QVector3D t = mvp * box[i]; if(qAbs<float>(t.x()) > 1.0 || qAbs<float>(t.y()) > 1.0) return false; } return true; }
bool BoundingSphere::inside(const AxisAlignedBoundingBox& axisAlignedBox) const { return axisAlignedBox.encloses(*this); }
//------------------------------------------------------------------------ void KdTreeNode::build(KdTree* tree, const AxisAlignedBoundingBox& aabb, unsigned int depth) { if (hasToStopBuilding(depth)) { return; } float subcost = std::numeric_limits<float>::max(); float distance = std::numeric_limits<float>::max(); Vector3::AXIS axis = aabb.getDirection(); float lowerDistance = aabb.getLowerCorner().get(axis); float greaterDistance = aabb.getGreaterCorner().get(axis); // m_Spheres are sorted along axis to simplify the splitplane research std::sort(m_Spheres->begin(), m_Spheres->end(), [&](const Sphere* s1, const Sphere* s2) { return s1->getCenter().get(axis) < s2->getCenter().get(axis); }); unsigned int greaterCount = unsigned int(m_Spheres->size()); unsigned int lowerCount = 0; /////////////////////////// // Find best split plane // /////////////////////////// for (auto it = m_Spheres->begin(); it != m_Spheres->end(); it++) { const Sphere* pSphere = *it; const AxisAlignedBoundingBox& sphereAABB = pSphere->getAABB(); float newDistance; float newSubcost; newDistance = sphereAABB.getLowerCorner().get(axis); if (lowerDistance < newDistance && newDistance < greaterDistance) { newSubcost = cost(aabb, lowerCount, greaterCount, newDistance, axis); if (newSubcost < subcost) { distance = newDistance; subcost = newSubcost; } } greaterCount--; lowerCount++; newDistance = sphereAABB.getGreaterCorner().get(axis); if (lowerDistance < newDistance && newDistance < greaterDistance) { newSubcost = cost(aabb, lowerCount, greaterCount, newDistance, axis); if (newSubcost < subcost) { distance = newDistance; subcost = newSubcost; } } } // if there is no interesting split if (distance <= lowerDistance || greaterDistance <= distance) { return; } //////////////////// // Split the Node // //////////////////// m_Axis = axis; m_SplitDistance = distance; AxisAlignedBoundingBox boxA = aabb.getLowerSubAABB(distance, axis); AxisAlignedBoundingBox boxB = aabb.getGreaterSubAABB(distance, axis); m_Nodes = tree->getNextNode(); tree->getNextNode(); // we allocate a pair, they are next to each other in memory for (auto it = m_Spheres->begin(); it != m_Spheres->end(); it++) { const Sphere* pSphere = *it; if (boxA.intersect(*pSphere)) { getA()->add(pSphere); } if (boxB.intersect(*pSphere)) { getB()->add(pSphere); } } getA()->build(tree, boxA, depth + 1); getB()->build(tree, boxB, depth + 1); delete m_Spheres; m_Spheres = nullptr; }
Component *ComponentFactory::createComponent(int type, std::map<std::string,std::string> params) { switch (type) { case COMPONENT_TYPE_DATA_BOUNDINGBOX: { printf("adding component BOUNDINGBOX\n"); //AxisAlignedBoundingBox *bb = new AxisAlignedBoundingBox(id_ref++); //parse parameters //parameters for Location: // int {x, y, z} int type = -1; for (std::map<std::string,std::string>::iterator it = params.begin(); it != params.end(); it++) { if (it->first.compare("bb_type") == 0) type = atoi(it->second.c_str()); else continue; } if (type != -1) { switch (type) { case BOUNDINGBOX_TYPE_AXISALIGNED: { AxisAlignedBoundingBox *bb = new AxisAlignedBoundingBox(id_ref++); for (std::map<std::string,std::string>::iterator it = params.begin(); it != params.end(); it++) { if (it->first.compare("half_x") == 0) bb->halfVectors.x = strtof(it->second.c_str(), NULL); else if (it->first.compare("half_y") == 0) bb->halfVectors.y = strtof(it->second.c_str(), NULL); else if (it->first.compare("offset_x") == 0) bb->offsetVectors.x = atoi(it->second.c_str()); else if (it->first.compare("offset_y") == 0) bb->offsetVectors.y = atoi(it->second.c_str()); else if (it->first.compare("r") == 0) bb->zeroAxis = strtof(it->second.c_str(), NULL); } bb->certifyParams(); return bb; break; } } } else { return NULL; } break; } case COMPONENT_TYPE_DATA_TRANSFORM: { printf("adding component TRANSFORM\n"); Transform *t = new Transform(id_ref++); for (std::map<std::string,std::string>::iterator it = params.begin(); it != params.end(); it++) { if (it->first.compare("x") == 0) t->xyz.x = atoi(it->second.c_str()); else if (it->first.compare("y") == 0) t->xyz.y = atoi(it->second.c_str()); else if (it->first.compare("z") == 0) t->xyz.z = atoi(it->second.c_str()); else if (it->first.compare("w") == 0) t->wh.x = strtof(it->second.c_str(), NULL); else if (it->first.compare("h") == 0) t->wh.y = strtof(it->second.c_str(), NULL); else if (it->first.compare("r") == 0) t->r = strtof(it->second.c_str(), NULL); } t->certifyParams(); return t; break; } /*case COMPONENT_TYPE_DATA_LOCATION: { Location *l = new Location(id_ref++); //parse parameters //parameters for Location: // int {x, y, z} for (std::map<std::string,std::string>::iterator it = params.begin(); it != params.end(); it++) { if (it->first.compare("x") == 0) l->xyz.x = atoi(it->second.c_str()); else if (it->first.compare("y") == 0) l->xyz.y = atoi(it->second.c_str()); else if (it->first.compare("z") == 0) l->xyz.z = atoi(it->second.c_str()); } return l; break; }*/ case COMPONENT_TYPE_EVENT_PHYSICAL: { printf("adding component PHYSICAL\n"); Physical *p = new Physical(id_ref++); for (std::map<std::string, std::string>::iterator it = params.begin(); it != params.end(); it++) { if (it->first.compare("fps") == 0) p->setFPS(atoi(it->second.c_str())); else if (it->first.compare("vMax")) p->setMaxSpeed(atoi(it->second.c_str())); else if (it->first.compare("vX")) p->setXVelocity(atof(it->second.c_str())); else if (it->first.compare("vY")) p->setYVelocity(atof(it->second.c_str())); else if (it->first.compare("pX")) p->setX(strtof(it->second.c_str(), NULL)); else if (it->first.compare("pY")) p->setY(strtof(it->second.c_str(), NULL)); else if (it->first.compare("pZ")) p->setZ(strtof(it->second.c_str(), NULL)); } break; } case COMPONENT_TYPE_RENDERABLE_TEXTURE: { printf("adding component TEXTURERENDER\n"); Renderable *r = new Renderable(id_ref++, type); //parse parameters //parameters for Renderable Texture: // string {filename} // int {w, h} for (std::map<std::string,std::string>::iterator it = params.begin(); it != params.end(); it++) { if (it->first.compare("filename") == 0) r->filename = it->second; else if (it->first.compare("w") == 0) r->w = atoi(it->second.c_str()); else if (it->first.compare("h") == 0) r->h = atoi(it->second.c_str()); } r->certifyParams(); return r; break; } case COMPONENT_TYPE_RENDERABLE_COLOR: { printf("adding component COLORRENDER\n"); Renderable *r = new Renderable(id_ref++, type); //parse parameters //parameters for Renderable Color: // int {r, g, b, a, w, h} for (std::map<std::string,std::string>::iterator it = params.begin(); it != params.end(); ++it) { if (it->first.compare("r")) r->col.r = atoi(it->second.c_str()); else if (it->first.compare("g")) r->col.g = atoi(it->second.c_str()); else if (it->first.compare("b")) r->col.b = atoi(it->second.c_str()); else if (it->first.compare("a")) r->col.a = atoi(it->second.c_str()); else if (it->first.compare("w")) r->w = atoi(it->second.c_str()); else if (it->first.compare("h")) r->h = atoi(it->second.c_str()); } r->certifyParams(); return r; break; } default: return NULL; } }