Skip to content

Commit

Permalink
Fixed bug in transformed spheres introduced with commit 53f0ebd.
Browse files Browse the repository at this point in the history
  • Loading branch information
c-lipka committed Aug 11, 2016
1 parent 6418cd0 commit 50f20db
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 50 deletions.
2 changes: 1 addition & 1 deletion source/base/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
#define OFFICIAL_VERSION_STRING "3.7.1"
#define OFFICIAL_VERSION_NUMBER 371

#define POV_RAY_PRERELEASE "alpha.8736312"
#define POV_RAY_PRERELEASE "alpha.8737777"

#if (POV_RAY_IS_AUTOBUILD == 1) && ((POV_RAY_IS_OFFICIAL == 1) || (POV_RAY_IS_SEMI_OFFICIAL == 1))
#ifdef POV_RAY_PRERELEASE
Expand Down
112 changes: 64 additions & 48 deletions source/core/shape/sphere.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ bool Sphere::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadD

Intersection_Found = false;

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

MInvTransPoint(New_Point, IPoint, Trans);

Origin_To_Center = Center - New_Point;

OCSquared = Origin_To_Center.lengthSqr();
OCSquared = New_Point.lengthSqr();

if (Test_Flag(this, INVERTED_FLAG))
return(OCSquared > Sqr(Radius));
Expand Down Expand Up @@ -328,9 +326,15 @@ void Sphere::Normal(Vector3d& Result, Intersection *Inter, TraceThreadData *Thre
if(Do_Ellipsoid)
{
Vector3d New_Point;

// Transform the point into the sphere's space
MInvTransPoint(New_Point, Inter->IPoint, Trans);
Result = New_Point - Center;

// Compute the result in the sphere's space
// (this is trivial since ellipsoidal mode is based on the unity sphere)
Result = New_Point;

// Transform the result back into regular space
MTransNormal(Result, Result, Trans);
Result.normalize();
}
Expand Down Expand Up @@ -407,16 +411,15 @@ ObjectPtr Sphere::Copy()

void Sphere::Translate(const Vector3d& Vector, const TRANSFORM *tr)
{
if(!Do_Ellipsoid)
if (Do_Ellipsoid)
{
Center += Vector;
Transform(tr);
}
else
{
Compose_Transforms(Trans, tr);
Center += Vector;
Compute_BBox();
}

Compute_BBox();
}


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

void Sphere::Rotate(const Vector3d&, const TRANSFORM *tr)
{
if (Trans == NULL)
Trans = Create_Transform();
Compose_Transforms(Trans, tr);
if (Do_Ellipsoid)
{
Transform(tr);
}
else
{
if (Trans == NULL)
Trans = Create_Transform();
Compose_Transforms(Trans, tr);

if(!Do_Ellipsoid)
MTransPoint(Center, Center, tr);

Compute_BBox();
Compute_BBox();
}
}


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

void Sphere::Scale(const Vector3d& Vector, const TRANSFORM *tr)
{
if ((Vector[X] != Vector[Y]) || (Vector[X] != Vector[Z]))
if (Do_Ellipsoid || (Vector[X] != Vector[Y]) || (Vector[X] != Vector[Z]))
{
if (!Do_Ellipsoid)
{
// treat sphere as ellipsoid as it's unevenly scaled
Do_Ellipsoid = true;
if (Trans == NULL)
Trans = Create_Transform();
}
Transform(tr);
}

if (!Do_Ellipsoid)
else
{
Center *= Vector[X];
Radius *= fabs(Vector[X]);
}
else
{
Compose_Transforms(Trans, tr);
}

Compute_BBox();
}
Expand Down Expand Up @@ -545,7 +542,7 @@ Sphere::Sphere() :
ObjectBase(SPHERE_OBJECT),
Center(0.0, 0.0, 0.0),
Radius(1.0),
Do_Ellipsoid(false) // FIXME
Do_Ellipsoid(false)
{}

/*****************************************************************************
Expand Down Expand Up @@ -576,10 +573,30 @@ Sphere::Sphere() :

void Sphere::Transform(const TRANSFORM *tr)
{
Do_Ellipsoid = true;
// Arbitrary transformations can only be tracked in ellipsoidal mode,
// so we need to switch to that mode now if we're still in spherical mode.
if (!Do_Ellipsoid)
{
Do_Ellipsoid = true;

// We always have a transformation in ellipsoidal mode.
if (!Trans)
Trans = Create_Transform();

// Ellipsoidal mode is based on the unity sphere, so we need to convert
// center and radius into corresponding transformations.

TRANSFORM temp;

Compute_Scaling_Transform(&temp, Vector3d(Radius));
Compose_Transforms(Trans, &temp);
Radius = 1.0; // not really necessary, but avoids confusion when debugging

Compute_Translation_Transform(&temp, Center);
Compose_Transforms(Trans, &temp);
Center = Vector3d(0.0); // not really necessary, but avoids confusion when debugging
}

if(Trans == NULL)
Trans = Create_Transform();
Compose_Transforms(Trans, tr);

Compute_BBox();
Expand Down Expand Up @@ -661,12 +678,16 @@ Sphere::~Sphere()

void Sphere::Compute_BBox()
{
Make_BBox(BBox, Center[X] - Radius, Center[Y] - Radius, Center[Z] - Radius, 2.0 * Radius, 2.0 * Radius, 2.0 * Radius);

if(Do_Ellipsoid)
{
// Ellipsoidal mode is based on the unity sphere.
Make_BBox(BBox, -1.0,-1.0,-1.0, 2.0,2.0,2.0);
Recompute_BBox(&BBox, Trans);
}
else
{
Make_BBox(BBox, Center[X] - Radius, Center[Y] - Radius, Center[Z] - Radius, 2.0 * Radius, 2.0 * Radius, 2.0 * Radius);
}
}

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

/* Transform the point into the sphere's space */
if (Trans != NULL)
if (Do_Ellipsoid)
{

MInvTransPoint(New_Point, Inter->IPoint, Trans);

if (Do_Ellipsoid)
New_Center = Center;
else
MInvTransPoint(New_Center, Center, Trans);
}
else
{
New_Point = Inter->IPoint;
New_Center = Center;
New_Point = Inter->IPoint - Center;
if (Trans != NULL)
MInvTransPoint(New_Point, New_Point, Trans);
}
x = New_Point[X]-New_Center[X];
y = New_Point[Y]-New_Center[Y];
z = New_Point[Z]-New_Center[Z];
x = New_Point[X];
y = New_Point[Y];
z = New_Point[Z];

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

Expand Down
14 changes: 14 additions & 0 deletions source/core/shape/sphere.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,21 @@ class Sphere : public ObjectBase
virtual bool Intersect_BBox(BBoxDirection, const BBoxVector3d&, const BBoxVector3d&, BBoxScalar) const;

static bool Intersect(const BasicRay& ray, const Vector3d& Center, DBL Radius2, DBL *Depth1, DBL *Depth2);

private:

/// Ellipsoid mode flag.
///
/// A value of `false` indicates that the primitive is in _spherical_ mode, while a value of `true` indicates
/// _ellipsoidal_ mode.
///
/// **Spherical mode** uses the @ref Center and @ref Radius members to track all transformations to the
/// primitive, while the @ref Trans member only tracks rotations and is used exclusively for UV mapping.
/// If a transformation cannot be tracked in this manner, the primitive is switched to _ellipsoidal mode_.
///
/// **Ellipsoidal mode** uses the @ref Trans member to track center, radius and all transformations, while the
/// @ref Center is pegged to the coordinate origin and the @radius to unity.
///
bool Do_Ellipsoid;
};

Expand Down
2 changes: 1 addition & 1 deletion unix/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.7.1-alpha.8736312
3.7.1-alpha.8737777

0 comments on commit 50f20db

Please sign in to comment.