static double squaredDistanceToAABB(const QVector3D& point, const AxisAlignedBox& box) { const QVector3D center = (box.Max() + box.Min()) / 2; const QVector3D half_sz = (box.Max() - box.Min()) / 2; const QVector3D vec(max(0.0, fabs(center.x() - point.x()) - half_sz.x()), max(0.0, fabs(center.y() - point.y()) - half_sz.y()), max(0.0, fabs(center.z() - point.z()) - half_sz.z())); return vec.lengthSquared(); }
bool SelectionQuery::Intersection(const AxisAlignedBox& box, const QVector3D& ray_start, const QVector3D& ray_dir, double* result) { const QVector3D& bmin = box.Min(); const QVector3D& bmax = box.Max(); const double inv_x = 1 / ray_dir.x(); const double inv_y = 1 / ray_dir.y(); const double inv_z = 1 / ray_dir.z(); const double tx1 = (bmin.x() - ray_start.x()) * inv_x; const double tx2 = (bmax.x() - ray_start.x()) * inv_x; double tmin = std::min(tx1, tx2); double tmax = std::max(tx1, tx2); const double ty1 = (bmin.y() - ray_start.y()) * inv_y; const double ty2 = (bmax.y() - ray_start.y()) * inv_y; tmin = std::max(tmin, std::min(ty1, ty2)); tmax = std::min(tmax, std::max(ty1, ty2)); const double tz1 = (bmin.z() - ray_start.z()) * inv_z; const double tz2 = (bmax.z() - ray_start.z()) * inv_z; tmin = std::max(tmin, std::min(tz1, tz2)); tmax = std::min(tmax, std::max(tz1, tz2)); if (tmax >= tmin && tmax > 0) { *result = std::max(0.0, std::min(tmin, tmax)); return true; } return false; }
void DrawContext::DrawBoundingBox(const AxisAlignedBox& box) { if (!bounding_box_node_) { StockResources stock(resources_); ShaderResource::Ptr shader = stock.Shader(StockResources::kUniformColorNoLighting); MaterialResource::Ptr material = resources_->MakeMaterial(shader); material->SetParam("color", 0.0f, 1.0f, 0.0f, 1.0f); GeometryResource::Ptr geometry = resources_->MakeGeometry(); GeometryData gdata; gdata.gl_mode = GL_LINES; gdata.vertices = { { QVector3D(0, 0, 0) }, { QVector3D(0, 1, 0) }, { QVector3D(1, 1, 0) }, { QVector3D(1, 0, 0) }, { QVector3D(0, 0, 1) }, { QVector3D(0, 1, 1) }, { QVector3D(1, 1, 1) }, { QVector3D(1, 0, 1) }, }; gdata.indices = { 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 }; geometry->Load(gdata); bounding_box_node_ = scene_->MakeDrawNode(nullptr); bounding_box_node_->Add(geometry, material); // hack to prevent the bounding box to appear during normal rendering bounding_box_node_->SetVisible(false); } bounding_box_node_->SetScale(box.Max() - box.Min()); bounding_box_node_->SetTranslation(box.Min()); model_mat_ = bounding_box_node_->WorldTransform(); DrawDrawNode(bounding_box_node_); }
bool Frustum::Intersects(const AxisAlignedBox& box) { const QVector3D& bmin = box.Min(); const QVector3D& bmax = box.Max(); for (const Plane& plane : planes_) { const QVector3D& normal = plane.Normal(); const QVector3D test_point( normal.x() > 0 ? bmax.x() : bmin.x(), normal.y() > 0 ? bmax.y() : bmin.y(), normal.z() > 0 ? bmax.z() : bmin.z()); if (plane.SignedDistance(test_point) < 0) { return false; } } return true; }
void AxisAlignedBox::IncludeBox(const AxisAlignedBox& other) { IncludePoint(other.Min()); IncludePoint(other.Max()); }