Skip to content

Commit 50f20db

Browse files
committed
Fixed bug in transformed spheres introduced with commit 53f0ebd.
1 parent 6418cd0 commit 50f20db

File tree

4 files changed

+80
-50
lines changed

4 files changed

+80
-50
lines changed

source/base/version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
#define OFFICIAL_VERSION_STRING "3.7.1"
4646
#define OFFICIAL_VERSION_NUMBER 371
4747

48-
#define POV_RAY_PRERELEASE "alpha.8736312"
48+
#define POV_RAY_PRERELEASE "alpha.8737777"
4949

5050
#if (POV_RAY_IS_AUTOBUILD == 1) && ((POV_RAY_IS_OFFICIAL == 1) || (POV_RAY_IS_SEMI_OFFICIAL == 1))
5151
#ifdef POV_RAY_PRERELEASE

source/core/shape/sphere.cpp

Lines changed: 64 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ bool Sphere::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadD
100100

101101
Intersection_Found = false;
102102

103-
if(Intersect(New_Ray, Center, Sqr(Radius), &Depth1, &Depth2))
103+
if(Intersect(New_Ray, Vector3d(0.0), 1.0, &Depth1, &Depth2))
104104
{
105105
Thread->Stats()[Ray_Sphere_Tests_Succeeded]++;
106106
if((Depth1 > DEPTH_TOLERANCE) && (Depth1 < MAX_DISTANCE))
@@ -273,9 +273,7 @@ bool Sphere::Inside(const Vector3d& IPoint, TraceThreadData *Thread) const
273273

274274
MInvTransPoint(New_Point, IPoint, Trans);
275275

276-
Origin_To_Center = Center - New_Point;
277-
278-
OCSquared = Origin_To_Center.lengthSqr();
276+
OCSquared = New_Point.lengthSqr();
279277

280278
if (Test_Flag(this, INVERTED_FLAG))
281279
return(OCSquared > Sqr(Radius));
@@ -328,9 +326,15 @@ void Sphere::Normal(Vector3d& Result, Intersection *Inter, TraceThreadData *Thre
328326
if(Do_Ellipsoid)
329327
{
330328
Vector3d New_Point;
329+
331330
// Transform the point into the sphere's space
332331
MInvTransPoint(New_Point, Inter->IPoint, Trans);
333-
Result = New_Point - Center;
332+
333+
// Compute the result in the sphere's space
334+
// (this is trivial since ellipsoidal mode is based on the unity sphere)
335+
Result = New_Point;
336+
337+
// Transform the result back into regular space
334338
MTransNormal(Result, Result, Trans);
335339
Result.normalize();
336340
}
@@ -407,16 +411,15 @@ ObjectPtr Sphere::Copy()
407411

408412
void Sphere::Translate(const Vector3d& Vector, const TRANSFORM *tr)
409413
{
410-
if(!Do_Ellipsoid)
414+
if (Do_Ellipsoid)
411415
{
412-
Center += Vector;
416+
Transform(tr);
413417
}
414418
else
415419
{
416-
Compose_Transforms(Trans, tr);
420+
Center += Vector;
421+
Compute_BBox();
417422
}
418-
419-
Compute_BBox();
420423
}
421424

422425

@@ -449,14 +452,19 @@ void Sphere::Translate(const Vector3d& Vector, const TRANSFORM *tr)
449452

450453
void Sphere::Rotate(const Vector3d&, const TRANSFORM *tr)
451454
{
452-
if (Trans == NULL)
453-
Trans = Create_Transform();
454-
Compose_Transforms(Trans, tr);
455+
if (Do_Ellipsoid)
456+
{
457+
Transform(tr);
458+
}
459+
else
460+
{
461+
if (Trans == NULL)
462+
Trans = Create_Transform();
463+
Compose_Transforms(Trans, tr);
455464

456-
if(!Do_Ellipsoid)
457465
MTransPoint(Center, Center, tr);
458-
459-
Compute_BBox();
466+
Compute_BBox();
467+
}
460468
}
461469

462470

@@ -489,26 +497,15 @@ void Sphere::Rotate(const Vector3d&, const TRANSFORM *tr)
489497

490498
void Sphere::Scale(const Vector3d& Vector, const TRANSFORM *tr)
491499
{
492-
if ((Vector[X] != Vector[Y]) || (Vector[X] != Vector[Z]))
500+
if (Do_Ellipsoid || (Vector[X] != Vector[Y]) || (Vector[X] != Vector[Z]))
493501
{
494-
if (!Do_Ellipsoid)
495-
{
496-
// treat sphere as ellipsoid as it's unevenly scaled
497-
Do_Ellipsoid = true;
498-
if (Trans == NULL)
499-
Trans = Create_Transform();
500-
}
502+
Transform(tr);
501503
}
502-
503-
if (!Do_Ellipsoid)
504+
else
504505
{
505506
Center *= Vector[X];
506507
Radius *= fabs(Vector[X]);
507508
}
508-
else
509-
{
510-
Compose_Transforms(Trans, tr);
511-
}
512509

513510
Compute_BBox();
514511
}
@@ -545,7 +542,7 @@ Sphere::Sphere() :
545542
ObjectBase(SPHERE_OBJECT),
546543
Center(0.0, 0.0, 0.0),
547544
Radius(1.0),
548-
Do_Ellipsoid(false) // FIXME
545+
Do_Ellipsoid(false)
549546
{}
550547

551548
/*****************************************************************************
@@ -576,10 +573,30 @@ Sphere::Sphere() :
576573

577574
void Sphere::Transform(const TRANSFORM *tr)
578575
{
579-
Do_Ellipsoid = true;
576+
// Arbitrary transformations can only be tracked in ellipsoidal mode,
577+
// so we need to switch to that mode now if we're still in spherical mode.
578+
if (!Do_Ellipsoid)
579+
{
580+
Do_Ellipsoid = true;
581+
582+
// We always have a transformation in ellipsoidal mode.
583+
if (!Trans)
584+
Trans = Create_Transform();
585+
586+
// Ellipsoidal mode is based on the unity sphere, so we need to convert
587+
// center and radius into corresponding transformations.
588+
589+
TRANSFORM temp;
590+
591+
Compute_Scaling_Transform(&temp, Vector3d(Radius));
592+
Compose_Transforms(Trans, &temp);
593+
Radius = 1.0; // not really necessary, but avoids confusion when debugging
594+
595+
Compute_Translation_Transform(&temp, Center);
596+
Compose_Transforms(Trans, &temp);
597+
Center = Vector3d(0.0); // not really necessary, but avoids confusion when debugging
598+
}
580599

581-
if(Trans == NULL)
582-
Trans = Create_Transform();
583600
Compose_Transforms(Trans, tr);
584601

585602
Compute_BBox();
@@ -661,12 +678,16 @@ Sphere::~Sphere()
661678

662679
void Sphere::Compute_BBox()
663680
{
664-
Make_BBox(BBox, Center[X] - Radius, Center[Y] - Radius, Center[Z] - Radius, 2.0 * Radius, 2.0 * Radius, 2.0 * Radius);
665-
666681
if(Do_Ellipsoid)
667682
{
683+
// Ellipsoidal mode is based on the unity sphere.
684+
Make_BBox(BBox, -1.0,-1.0,-1.0, 2.0,2.0,2.0);
668685
Recompute_BBox(&BBox, Trans);
669686
}
687+
else
688+
{
689+
Make_BBox(BBox, Center[X] - Radius, Center[Y] - Radius, Center[Z] - Radius, 2.0 * Radius, 2.0 * Radius, 2.0 * Radius);
690+
}
670691
}
671692

672693
/*****************************************************************************
@@ -704,24 +725,19 @@ void Sphere::UVCoord(Vector2d& Result, const Intersection *Inter, TraceThreadDat
704725
Vector3d New_Point, New_Center;
705726

706727
/* Transform the point into the sphere's space */
707-
if (Trans != NULL)
728+
if (Do_Ellipsoid)
708729
{
709-
710730
MInvTransPoint(New_Point, Inter->IPoint, Trans);
711-
712-
if (Do_Ellipsoid)
713-
New_Center = Center;
714-
else
715-
MInvTransPoint(New_Center, Center, Trans);
716731
}
717732
else
718733
{
719-
New_Point = Inter->IPoint;
720-
New_Center = Center;
734+
New_Point = Inter->IPoint - Center;
735+
if (Trans != NULL)
736+
MInvTransPoint(New_Point, New_Point, Trans);
721737
}
722-
x = New_Point[X]-New_Center[X];
723-
y = New_Point[Y]-New_Center[Y];
724-
z = New_Point[Z]-New_Center[Z];
738+
x = New_Point[X];
739+
y = New_Point[Y];
740+
z = New_Point[Z];
725741

726742
len = sqrt(x * x + y * y + z * z);
727743

source/core/shape/sphere.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,21 @@ class Sphere : public ObjectBase
7878
virtual bool Intersect_BBox(BBoxDirection, const BBoxVector3d&, const BBoxVector3d&, BBoxScalar) const;
7979

8080
static bool Intersect(const BasicRay& ray, const Vector3d& Center, DBL Radius2, DBL *Depth1, DBL *Depth2);
81+
8182
private:
83+
84+
/// Ellipsoid mode flag.
85+
///
86+
/// A value of `false` indicates that the primitive is in _spherical_ mode, while a value of `true` indicates
87+
/// _ellipsoidal_ mode.
88+
///
89+
/// **Spherical mode** uses the @ref Center and @ref Radius members to track all transformations to the
90+
/// primitive, while the @ref Trans member only tracks rotations and is used exclusively for UV mapping.
91+
/// If a transformation cannot be tracked in this manner, the primitive is switched to _ellipsoidal mode_.
92+
///
93+
/// **Ellipsoidal mode** uses the @ref Trans member to track center, radius and all transformations, while the
94+
/// @ref Center is pegged to the coordinate origin and the @radius to unity.
95+
///
8296
bool Do_Ellipsoid;
8397
};
8498

unix/VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.7.1-alpha.8736312
1+
3.7.1-alpha.8737777

0 commit comments

Comments
 (0)