Skip to content

Commit 3d30fb3

Browse files
committed
Fix bulk of GitHub issue #147 sphere sweep artifacts for good.
1 parent 36b2a15 commit 3d30fb3

File tree

3 files changed

+80
-80
lines changed

3 files changed

+80
-80
lines changed

changes.txt

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ Notes:
1313
For example, to read FS#270, visit:
1414
http://bugs.povray.org/270
1515

16+
(Note: As of 3.7.1-beta.8 our flyspray bug tracker is officially mothballed,
17+
and we no longer refer to it in the changelog. Any flyspray reports that
18+
were still open at that point have been duplicated as GitHub issues titled
19+
"Port of FSxxx - ...")
20+
1621
- To view a referenced newsgroup posting (<[email protected]>), prefix
1722
the message ID with the URL http://news.povray.org/.
1823
The '<' and '>' are optional (if using a shell you may want to omit them).
@@ -27,7 +32,15 @@ should be located in the same directory as this file is.
2732
Changes between 3.7.1-beta.7 and 3.7.1-TBD
2833
==========================================
2934

30-
Miscellaneous:
35+
Fixed or Mitigated Bugs
36+
-----------------------
37+
38+
Reported via GitHub:
39+
40+
- #147 ("Port of FS81 - sphere_sweep generating artifacts")
41+
42+
Other Noteworthy
43+
----------------
3144

3245
- Minor updates to the documentation.
3346

revision.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,22 @@ Notes:
1919
For example, to read FS#270, visit:
2020
http://bugs.povray.org/270
2121

22+
(Note: As of 3.7.1-beta.8 our flyspray bug tracker is officially mothballed,
23+
and we no longer refer to it in the changelog. Any flyspray reports that
24+
were still open at that point have been duplicated as GitHub issues titled
25+
"Port of FSxxx - ...")
26+
2227
- To view a referenced newsgroup posting (<[email protected]>), prefix
2328
the message ID with the URL http://news.povray.org/.
2429
The '<' and '>' are optional (if using a shell you may want to omit them).
2530
For example, to read <[email protected]>, visit:
2631
http://news.povray.org/[email protected]
2732
------------------------------------------------------------------------------
2833

34+
------------------------------------------------------------------------------
35+
POV-Ray v3.7.1-beta.TBD
36+
------------------------------------------------------------------------------
37+
2938
------------------------------------------------------------------------------
3039
POV-Ray v3.7.1-beta.7
3140
------------------------------------------------------------------------------

source/core/shape/spheresweep.cpp

Lines changed: 57 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ namespace pov
101101

102102
const DBL DEPTH_TOLERANCE = 1.0e-6;
103103
const DBL ZERO_TOLERANCE = 1.0e-4;
104+
const DBL RADIUS_TOLERANCE = 1.0e-6;
104105

105106
// TODO - Technically this should be `(Num_Spheres + Num_Segments * order) * 2` [CLi]
106107
#define SPHSWEEP_MAX_ISECT ((Num_Spheres + Num_Segments) * 2 + 64)
@@ -408,7 +409,6 @@ int SphereSweep::Intersect_Segment(const BasicRay &ray, const SPHSWEEP_SEG *Segm
408409
DBL fp0, fp1;
409410
DBL t;
410411
SPHSWEEP_SPH Temp_Sphere;
411-
Vector3d Center;
412412

413413
Isect_Count = 0;
414414

@@ -617,51 +617,31 @@ int SphereSweep::Intersect_Segment(const BasicRay &ray, const SPHSWEEP_SEG *Segm
617617
m++;
618618
}
619619

620-
switch(Segment->Num_Coefs)
620+
for (m = 0; m < Num_Poly_Roots; m++)
621621
{
622-
case 2:
623-
for(m = 0; m < Num_Poly_Roots; m++)
624-
{
625-
fp0 = 2.0 * d * Root[m]
626-
+ e;
627-
fp1 = b;
628-
629-
if(fabs(fp1) > ZERO_TOLERANCE)
630-
{
631-
t = -fp0 / fp1;
632-
633-
if((t > -MAX_DISTANCE) && (t < MAX_DISTANCE))
634-
{
635-
// Add intersection
636-
Isect[Isect_Count].t = t;
622+
// Calculate center and radius of sphere at root
637623

638-
// Calculate point
639-
Isect[Isect_Count].Point = ray.Evaluate(t);
624+
DBL rootPwr = 1;
625+
Temp_Sphere.Center = Segment->Center_Coef[0];
626+
Temp_Sphere.Radius = Segment->Radius_Coef[0];
627+
for (n = 1; n < Segment->Num_Coefs; ++n)
628+
{
629+
rootPwr *= Root[m];
630+
Temp_Sphere.Center += Segment->Center_Coef[n] * rootPwr;
631+
Temp_Sphere.Radius += Segment->Radius_Coef[n] * rootPwr;
632+
}
640633

641-
// Calculate normal
642-
Center = Segment->Center_Coef[0] + Root[m] * Segment->Center_Coef[1];
643-
Isect[Isect_Count].Normal = (Isect[Isect_Count].Point - Center).normalized();
634+
switch (Segment->Num_Coefs)
635+
{
636+
case 2:
644637

645-
Isect_Count++;
646-
}
647-
}
648-
else
649-
{
650-
// Calculate center of single sphere
651-
Temp_Sphere.Center = Segment->Center_Coef[1] * Root[m] + Segment->Center_Coef[0];
638+
fp0 = 2.0 * d * Root[m]
639+
+ e;
640+
fp1 = b;
641+
break;
652642

653-
// Calculate radius of single sphere
654-
Temp_Sphere.Radius = Segment->Radius_Coef[1] * Root[m] + Segment->Radius_Coef[0];
643+
case 4:
655644

656-
// Calculate intersections
657-
if(Intersect_Sphere(ray, &Temp_Sphere, Isect + Isect_Count))
658-
Isect_Count += 2;
659-
}
660-
}
661-
break;
662-
case 4:
663-
for (m = 0; m < Num_Poly_Roots; m++)
664-
{
665645
fp0 = 6.0 * f * Root[m] * Root[m] * Root[m] * Root[m] * Root[m]
666646
+ 5.0 * g * Root[m] * Root[m] * Root[m] * Root[m]
667647
+ 4.0 * h * Root[m] * Root[m] * Root[m]
@@ -671,49 +651,49 @@ int SphereSweep::Intersect_Segment(const BasicRay &ray, const SPHSWEEP_SEG *Segm
671651
fp1 = 3.0 * b * Root[m] * Root[m]
672652
+ 2.0 * c * Root[m]
673653
+ d;
654+
break;
674655

675-
if(fabs(fp1) > ZERO_TOLERANCE)
676-
{
677-
t = -fp0 / fp1;
656+
default:
657+
POV_SHAPE_ASSERT(false);
658+
break;
659+
}
678660

679-
if((t > -MAX_DISTANCE) && (t < MAX_DISTANCE))
680-
{
681-
// Add intersection
682-
Isect[Isect_Count].t = t;
661+
bool doubleIsect = (fabs(fp1) < ZERO_TOLERANCE);
662+
if (!doubleIsect)
663+
{
664+
// Looks like a single-intersection root at first glance
683665

684-
// Calculate point
685-
Isect[Isect_Count].Point = ray.Evaluate(t);
666+
t = -fp0 / fp1;
686667

687-
// Calculate normal
688-
Center = Segment->Center_Coef[3] * (Root[m] * Root[m] * Root[m])
689-
+ Segment->Center_Coef[2] * (Root[m] * Root[m])
690-
+ Segment->Center_Coef[1] * Root[m]
691-
+ Segment->Center_Coef[0];
692-
Isect[Isect_Count].Normal = (Isect[Isect_Count].Point - Center).normalized();
668+
if ((t > -MAX_DISTANCE) && (t < MAX_DISTANCE))
669+
{
670+
// Calculate intersection point
671+
Isect[Isect_Count].Point = ray.Evaluate(t);
693672

694-
Isect_Count++;
695-
}
696-
}
697-
else
673+
// Calculate normal
674+
Isect[Isect_Count].Normal = (Isect[Isect_Count].Point - Temp_Sphere.Center).normalized();
675+
676+
// Sanity-check intersection point for proper radius
677+
DBL rIsect = (Isect[Isect_Count].Point - Temp_Sphere.Center).length();
678+
DBL rRoot = Temp_Sphere.Radius;
679+
680+
// Check for numeric instability; this may (only?) happen if the root corresponds to two intersections
681+
doubleIsect = fabs(rIsect - rRoot) > RADIUS_TOLERANCE;
682+
if (!doubleIsect)
698683
{
699-
// Calculate center of single sphere
700-
Temp_Sphere.Center = Segment->Center_Coef[3] * (Root[m] * Root[m] * Root[m])
701-
+ Segment->Center_Coef[2] * (Root[m] * Root[m])
702-
+ Segment->Center_Coef[1] * Root[m]
703-
+ Segment->Center_Coef[0];
704-
705-
// Calculate radius of single sphere
706-
Temp_Sphere.Radius = Segment->Radius_Coef[3] * Root[m] * Root[m] * Root[m]
707-
+ Segment->Radius_Coef[2] * Root[m] * Root[m]
708-
+ Segment->Radius_Coef[1] * Root[m]
709-
+ Segment->Radius_Coef[0];
710-
711-
// Calculate intersections
712-
if (Intersect_Sphere(ray, &Temp_Sphere, Isect + Isect_Count))
713-
Isect_Count += 2;
684+
// Add intersection
685+
Isect[Isect_Count].t = t;
686+
Isect_Count++;
714687
}
715688
}
716-
break;
689+
}
690+
691+
if (doubleIsect)
692+
{
693+
// Calculate intersections
694+
if(Intersect_Sphere(ray, &Temp_Sphere, Isect + Isect_Count))
695+
Isect_Count += 2;
696+
}
717697
}
718698

719699
return Isect_Count;
@@ -1353,10 +1333,8 @@ void SphereSweep::Compute_BBox()
13531333
{
13541334
for (i = 0; i < Num_Modeling_Spheres; i++)
13551335
{
1356-
{
1357-
mins = min(mins, Modeling_Sphere[i].Center - Vector3d(fabs(Modeling_Sphere[i].Radius)));
1358-
maxs = max(maxs, Modeling_Sphere[i].Center + Vector3d(fabs(Modeling_Sphere[i].Radius)));
1359-
}
1336+
mins = min(mins, Modeling_Sphere[i].Center - Vector3d(fabs(Modeling_Sphere[i].Radius)));
1337+
maxs = max(maxs, Modeling_Sphere[i].Center + Vector3d(fabs(Modeling_Sphere[i].Radius)));
13601338
}
13611339
}
13621340

0 commit comments

Comments
 (0)