@@ -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
408412void 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
450453void 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
490498void 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
577574void 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
662679void 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
0 commit comments