Bounds3f Curve::ObjectBound() const { // Compute object-space control points for curve segment, _cpObj_ Point3f cpObj[4]; cpObj[0] = BlossomBezier(common->cpObj, uMin, uMin, uMin); cpObj[1] = BlossomBezier(common->cpObj, uMin, uMin, uMax); cpObj[2] = BlossomBezier(common->cpObj, uMin, uMax, uMax); cpObj[3] = BlossomBezier(common->cpObj, uMax, uMax, uMax); Bounds3f b = Union(Bounds3f(cpObj[0], cpObj[1]), Bounds3f(cpObj[2], cpObj[3])); Float width[2] = {Lerp(uMin, common->width[0], common->width[1]), Lerp(uMax, common->width[0], common->width[1])}; return Expand(b, std::max(width[0], width[1]) * 0.5f); }
void KdTreeAccel::update() { int np = primitives.size(); //Initialize bouding box for all primitives in stack treeBound = Bounds3f(); for (int i = 0; i < np; ++i) { treeBound.Union(primitives[i]->ObjBound); } //Allocate bound edge info BoundEdge* edges[3]; for (int i = 0; i < 3; ++i) { edges[i] = new BoundEdge[np * 2]; } //Create stack to record primitive indices vector<int> primNum(np); for (int i = 0; i < np; ++i) { primNum[i] = i; } //Start recursively build the tree buildTree(root, treeBound, primNum, maxDepth, edges); //Clean data for (int i = 0; i < 3; ++i) { delete[] edges[i]; // edges[i] = nullptr; } }
Bounds3f Triangle::WorldBound() const { // Get triangle vertices in _p0_, _p1_, and _p2_ const Point3f &p0 = mesh->p[v[0]]; const Point3f &p1 = mesh->p[v[1]]; const Point3f &p2 = mesh->p[v[2]]; return Union(Bounds3f(p0, p1), p2); }
Bounds3f Triangle::ObjectBound() const { // Get triangle vertices in _p0_, _p1_, and _p2_ const Point3f &p0 = mesh->p[v[0]]; const Point3f &p1 = mesh->p[v[1]]; const Point3f &p2 = mesh->p[v[2]]; return Union(Bounds3f((*WorldToObject)(p0), (*WorldToObject)(p1)), (*WorldToObject)(p2)); }
// Cylinder Method Definitions Bounds3f Cylinder::ObjectBound() const { return Bounds3f(Point3f(-radius, -radius, zMin), Point3f(radius, radius, zMax)); }
bool Curve::recursiveIntersect(const Ray &ray, Float *tHit, SurfaceInteraction *isect, const Point3f cp[4], const Transform &rayToObject, Float u0, Float u1, int depth) const { // Try to cull curve segment versus ray // Compute bounding box of curve segment, _curveBounds_ Bounds3f curveBounds = Union(Bounds3f(cp[0], cp[1]), Bounds3f(cp[2], cp[3])); Float maxWidth = std::max(Lerp(u0, common->width[0], common->width[1]), Lerp(u1, common->width[0], common->width[1])); curveBounds = Expand(curveBounds, 0.5 * maxWidth); // Compute bounding box of ray, _rayBounds_ Float rayLength = ray.d.Length(); Float zMax = rayLength * ray.tMax; Bounds3f rayBounds(Point3f(0, 0, 0), Point3f(0, 0, zMax)); if (Overlaps(curveBounds, rayBounds) == false) return false; if (depth > 0) { // Split curve segment into sub-segments and test for intersection Float uMid = 0.5f * (u0 + u1); Point3f cpSplit[7]; SubdivideBezier(cp, cpSplit); return (recursiveIntersect(ray, tHit, isect, &cpSplit[0], rayToObject, u0, uMid, depth - 1) || recursiveIntersect(ray, tHit, isect, &cpSplit[3], rayToObject, uMid, u1, depth - 1)); } else { // Intersect ray with curve segment // Test ray against segment endpoint boundaries Vector2f segmentDirection = Point2f(cp[3]) - Point2f(cp[0]); // Test sample point against tangent perpendicular at curve start Float edge = (cp[1].y - cp[0].y) * -cp[0].y + cp[0].x * (cp[0].x - cp[1].x); if (edge < 0) return false; // Test sample point against tangent perpendicular at curve end // TODO: update to match the starting test. Vector2f endTangent = Point2f(cp[2]) - Point2f(cp[3]); if (Dot(segmentDirection, endTangent) < 0) endTangent = -endTangent; if (Dot(endTangent, Vector2f(cp[3])) < 0) return false; // Compute line $w$ that gives minimum distance to sample point Float denom = Dot(segmentDirection, segmentDirection); if (denom == 0) return false; Float w = Dot(-Vector2f(cp[0]), segmentDirection) / denom; // Compute $u$ coordinate of curve intersection point and _hitWidth_ Float u = Clamp(Lerp(w, u0, u1), u0, u1); Float hitWidth = Lerp(u, common->width[0], common->width[1]); Normal3f nHit; if (common->type == CurveType::Ribbon) { // Scale _hitWidth_ based on ribbon orientation Float sin0 = std::sin((1 - u) * common->normalAngle) * common->invSinNormalAngle; Float sin1 = std::sin(u * common->normalAngle) * common->invSinNormalAngle; nHit = sin0 * common->n[0] + sin1 * common->n[1]; hitWidth *= AbsDot(nHit, -ray.d / rayLength); } // Test intersection point against curve width Vector3f dpcdw; Point3f pc = EvalBezier(cp, Clamp(w, 0, 1), &dpcdw); Float ptCurveDist2 = pc.x * pc.x + pc.y * pc.y; if (ptCurveDist2 > hitWidth * hitWidth * .25) return false; if (pc.z < 0 || pc.z > zMax) return false; // Compute $v$ coordinate of curve intersection point Float ptCurveDist = std::sqrt(ptCurveDist2); Float edgeFunc = dpcdw.x * -pc.y + pc.x * dpcdw.y; Float v = (edgeFunc > 0.) ? 0.5f + ptCurveDist / hitWidth : 0.5f - ptCurveDist / hitWidth; // Compute hit _t_ and partial derivatives for curve intersection if (tHit != nullptr) { // FIXME: this tHit isn't quite right for ribbons... *tHit = pc.z / rayLength; // Compute error bounds for curve intersection Vector3f pError(2 * hitWidth, 2 * hitWidth, 2 * hitWidth); // Compute $\dpdu$ and $\dpdv$ for curve intersection Vector3f dpdu, dpdv; EvalBezier(common->cpObj, u, &dpdu); if (common->type == CurveType::Ribbon) dpdv = Normalize(Cross(nHit, dpdu)) * hitWidth; else { // Compute curve $\dpdv$ for flat and cylinder curves Vector3f dpduPlane = (Inverse(rayToObject))(dpdu); Vector3f dpdvPlane = Normalize(Vector3f(-dpduPlane.y, dpduPlane.x, 0)) * hitWidth; if (common->type == CurveType::Cylinder) { // Rotate _dpdvPlane_ to give cylindrical appearance Float theta = Lerp(v, -90., 90.); Transform rot = Rotate(-theta, dpduPlane); dpdvPlane = rot(dpdvPlane); } dpdv = rayToObject(dpdvPlane); } *isect = (*ObjectToWorld)(SurfaceInteraction( ray(pc.z), pError, Point2f(u, v), -ray.d, dpdu, dpdv, Normal3f(0, 0, 0), Normal3f(0, 0, 0), ray.time, this)); } ++nHits; return true; } }
Bounds3f Hyperboloid::ObjectBound() const { Point3f p1 = Point3f(-rMax, -rMax, zMin); Point3f p2 = Point3f(rMax, rMax, zMax); return Bounds3f(p1, p2); }
Bounds3f OvrSceneView::GetBounds() const { return ( WorldModel.Definition == NULL ) ? Bounds3f( Vector3f( 0, 0, 0 ), Vector3f( 0, 0, 0 ) ) : WorldModel.Definition->GetBounds(); }
// Disk Method Definitions Bounds3f Disk::ObjectBound() const { return Bounds3f(Point3f(-radius, -radius, height), Point3f(radius, radius, height)); }
Bounds3f BVHAccel::WorldBound() const { return nodes ? nodes[0].bounds : Bounds3f(); }
Bounds3f Paraboloid::ObjectBound() const { Point3f p1 = Point3f(-radius, -radius, zMin); Point3f p2 = Point3f(radius, radius, zMax); return Bounds3f(p1, p2); }
//---------------------------------------------------------------------------------------------- void IDrawInterface::DoBuildWorldTransform_(const Matrix &WTM) { m_WorldMatrixTransform = GetLTM_() * WTM * GetSTM_(); m_Bounds.SetUnvalid(); // invalidate std::vector<IRenderInterface*> &vecRenderEntities = const_cast<CActor*>(m_pNode->m_pKey)->m_VecRenderEntities; for (std::vector<IRenderInterface*>::const_iterator iter = vecRenderEntities.begin(); iter != vecRenderEntities.end(); ++iter) { (*iter)->SetRWTM(m_WorldMatrixTransform); Bounds3f BBox = (*iter)->GetRBounds_(); if (BBox.IsValid()) { const unsigned int BBOX_POINTS = 8; Vector BoxPoints[BBOX_POINTS] = { /*Vector(BBox.bound_min.x, BBox.bound_min.y, BBox.bound_min.z), Vector(BBox.bound_min.x, BBox.bound_min.y, BBox.bound_max.z), Vector(BBox.bound_max.x, BBox.bound_min.y, BBox.bound_max.z), Vector(BBox.bound_max.x, BBox.bound_min.y, BBox.bound_min.z), Vector(BBox.bound_min.x, BBox.bound_max.y, BBox.bound_min.z), Vector(BBox.bound_min.x, BBox.bound_max.y, BBox.bound_max.z), Vector(BBox.bound_max.x, BBox.bound_max.y, BBox.bound_max.z), Vector(BBox.bound_max.x, BBox.bound_max.y, BBox.bound_min.z),*/ // TODO make homogeneous with exporter tool Vector(BBox.bound_min.z, BBox.bound_min.y, BBox.bound_min.x), Vector(BBox.bound_max.z, BBox.bound_min.y, BBox.bound_min.x), Vector(BBox.bound_max.z, BBox.bound_min.y, BBox.bound_max.x), Vector(BBox.bound_min.z, BBox.bound_min.y, BBox.bound_max.x), Vector(BBox.bound_min.z, BBox.bound_max.y, BBox.bound_min.x), Vector(BBox.bound_max.z, BBox.bound_max.y, BBox.bound_min.x), Vector(BBox.bound_max.z, BBox.bound_max.y, BBox.bound_max.x), Vector(BBox.bound_min.z, BBox.bound_max.y, BBox.bound_max.x), }; Matrix MT = m_WorldMatrixTransform; MT.t = Vector(0.f, 0.f, 0.f); Bounds3f tmpBound; for (int Index = 0; Index < BBOX_POINTS; ++Index) { Vector point = transform_coord(BoxPoints[Index], MT); if (Index == 0) { tmpBound.SetBounds(point, point); continue; } tmpBound.Add(point); } const Vector bound_min = m_WorldMatrixTransform.t + tmpBound.bound_min; const Vector bound_max = m_WorldMatrixTransform.t + tmpBound.bound_max; (*iter)->SetWBounds(Bounds3f(bound_min, bound_max)); if (iter == vecRenderEntities.begin()) { m_Bounds.SetBounds(bound_min, bound_max); continue; } else { m_Bounds.Add(bound_min); m_Bounds.Add(bound_max); } } } // invalidate composite bounds m_CompositeBounds = m_Bounds; }
// Sphere Method Definitions Bounds3f Sphere::ObjectBound() const { return Bounds3f(Point3f(-radius, -radius, zMin), Point3f(radius, radius, zMax)); }