static void Transform_Smooth_Triangle(OBJECT *Object, TRANSFORM *Trans) { SMOOTH_TRIANGLE *Triangle = (SMOOTH_TRIANGLE *)Object; if (!Test_Flag(Object, DEGENERATE_FLAG)) { /* BEG ROSE This is useless, because Compute_Triange recalculates this anyway: MTransPoint(Triangle->Normal_Vector,Triangle->Normal_Vector, Trans); END ROSE */ MTransPoint(Triangle->P1, Triangle->P1, Trans); MTransPoint(Triangle->P2, Triangle->P2, Trans); MTransPoint(Triangle->P3, Triangle->P3, Trans); /* BEG ROSE This code is definitely wrong: MTransPoint(Triangle->N1, Triangle->N1, Trans); MTransPoint(Triangle->N2, Triangle->N2, Trans); MTransPoint(Triangle->N3, Triangle->N3, Trans); Bug fix for this: */ MTransNormal(Triangle->N1,Triangle->N1,Trans); MTransNormal(Triangle->N2,Triangle->N2,Trans); MTransNormal(Triangle->N3,Triangle->N3,Trans); /* END ROSE */ Compute_Triangle((TRIANGLE *)Triangle, true); } }
void Triangle::Transform(const TRANSFORM *tr) { if(!Test_Flag(this, DEGENERATE_FLAG)) { MTransPoint(P1, P1, tr); MTransPoint(P2, P2, tr); MTransPoint(P3, P3, tr); Compute_Triangle(); } }
void Camera::Transform(const TRANSFORM *Trans) { MTransPoint(Location, Location, Trans); MTransDirection(Direction, Direction, Trans); MTransDirection(Up, Up, Trans); MTransDirection(Right, Right, Trans); }
void Transform_Camera(CAMERA *Camera, TRANSFORM *Trans) { MTransPoint(Camera->Location, Camera->Location, Trans); MTransDirection(Camera->Direction, Camera->Direction, Trans); MTransDirection(Camera->Up, Camera->Up, Trans); MTransDirection(Camera->Right, Camera->Right, Trans); }
static void Transform_Triangle(OBJECT *Object, TRANSFORM *Trans) { TRIANGLE *Triangle = (TRIANGLE *)Object; if (!Test_Flag(Object, DEGENERATE_FLAG)) { /* ROSE BEG this is useless, because Compute_Triangle recalculates this anyway: MTransPoint(Triangle->Normal_Vector,Triangle->Normal_Vector, Trans); END ROSE */ MTransPoint(Triangle->P1, Triangle->P1, Trans); MTransPoint(Triangle->P2, Triangle->P2, Trans); MTransPoint(Triangle->P3, Triangle->P3, Trans); Compute_Triangle(Triangle, false); } }
void Sphere::Rotate(const Vector3d&, const TRANSFORM *tr) { if(Trans == NULL) { MTransPoint(Center, Center, tr); Compute_BBox(); } else { Transform(tr); } }
void LightSource::Transform(const TRANSFORM *tr) { DBL len; MTransPoint(Center, Center, tr); MTransPoint(Points_At, Points_At, tr); MTransDirection(Axis1, Axis1, tr); MTransDirection(Axis2, Axis2, tr); MTransDirection(Direction, Direction, tr); /* Make sure direction has unit length. */ len = Direction.length(); if(len > EPSILON) Direction /= len; if(!children.empty()) Transform_Object(children[0], tr); if(Projected_Through_Object != NULL) Transform_Object(Projected_Through_Object, tr); }
void BicubicPatch::Transform(const TRANSFORM *tr) { int i, j; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { MTransPoint(Control_Points[i][j], Control_Points[i][j], tr); } } Precompute_Patch_Values(); Compute_BBox(); }
void Recompute_BBox(BBOX *bbox, TRANSFORM *trans) { int i; VECTOR lower_left, lengths, corner; VECTOR mins, maxs; if (trans == NULL) { return; } Assign_BBox_Vect(lower_left, bbox->Lower_Left); Assign_BBox_Vect(lengths, bbox->Lengths); Make_Vector(mins, BOUND_HUGE, BOUND_HUGE, BOUND_HUGE); Make_Vector(maxs, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE); for (i = 1; i <= 8; i++) { Assign_Vector(corner, lower_left); corner[X] += ((i & 1) ? lengths[X] : 0.0); corner[Y] += ((i & 2) ? lengths[Y] : 0.0); corner[Z] += ((i & 4) ? lengths[Z] : 0.0); MTransPoint(corner, corner, trans); if (corner[X] < mins[X]) { mins[X] = corner[X]; } if (corner[X] > maxs[X]) { maxs[X] = corner[X]; } if (corner[Y] < mins[Y]) { mins[Y] = corner[Y]; } if (corner[Y] > maxs[Y]) { maxs[Y] = corner[Y]; } if (corner[Z] < mins[Z]) { mins[Z] = corner[Z]; } if (corner[Z] > maxs[Z]) { maxs[Z] = corner[Z]; } } /* Clip bounding box at the largest allowed bounding box. */ if (mins[X] < -BOUND_HUGE / 2) { mins[X] = -BOUND_HUGE / 2; } if (mins[Y] < -BOUND_HUGE / 2) { mins[Y] = -BOUND_HUGE / 2; } if (mins[Z] < -BOUND_HUGE / 2) { mins[Z] = -BOUND_HUGE / 2; } if (maxs[X] > BOUND_HUGE / 2) { maxs[X] = BOUND_HUGE / 2; } if (maxs[Y] > BOUND_HUGE / 2) { maxs[Y] = BOUND_HUGE / 2; } if (maxs[Z] > BOUND_HUGE / 2) { maxs[Z] = BOUND_HUGE / 2; } Make_BBox_from_min_max(*bbox, mins, maxs); }
static void Transform_Bicubic_Patch(OBJECT *Object, TRANSFORM *Trans) { int i, j; BICUBIC_PATCH *Patch = (BICUBIC_PATCH *) Object; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { MTransPoint(Patch->Control_Points[i][j], Patch->Control_Points[i][j], Trans); } } Precompute_Patch_Values(Patch); Compute_Bicubic_Patch_BBox(Patch); }
static void Compute_Polygon_BBox(POLYGON *Polyg) { int i; VECTOR p, Puv, Min, Max; Min[X] = Min[Y] = Min[Z] = BOUND_HUGE; Max[X] = Max[Y] = Max[Z] = -BOUND_HUGE; for (i = 0; i < Polyg->Data->Number; i++) { Puv[X] = Polyg->Data->Points[i][X]; Puv[Y] = Polyg->Data->Points[i][Y]; Puv[Z] = 0.0; MTransPoint(p, Puv, Polyg->Trans); Min[X] = min(Min[X], p[X]); Min[Y] = min(Min[Y], p[Y]); Min[Z] = min(Min[Z], p[Z]); Max[X] = max(Max[X], p[X]); Max[Y] = max(Max[Y], p[Y]); Max[Z] = max(Max[Z], p[Z]); } Make_BBox_from_min_max(Polyg->BBox, Min, Max); if (fabs(Polyg->BBox.Lengths[X]) < Small_Tolerance) { Polyg->BBox.Lower_Left[X] -= Small_Tolerance; Polyg->BBox.Lengths[X] += 2.0 * Small_Tolerance; } if (fabs(Polyg->BBox.Lengths[Y]) < Small_Tolerance) { Polyg->BBox.Lower_Left[Y] -= Small_Tolerance; Polyg->BBox.Lengths[Y] += 2.0 * Small_Tolerance; } if (fabs(Polyg->BBox.Lengths[Z]) < Small_Tolerance) { Polyg->BBox.Lower_Left[Z] -= Small_Tolerance; Polyg->BBox.Lengths[Z] += 2.0 * Small_Tolerance; } }
void Recompute_BBox(BoundingBox *bbox, const TRANSFORM *trans) { int i; Vector3d lower_left, lengths, corner; Vector3d mins, maxs; if(trans == NULL) return; lower_left = Vector3d(bbox->lowerLeft); lengths = Vector3d(bbox->size); mins = Vector3d(BOUND_HUGE); maxs = Vector3d(-BOUND_HUGE); for(i = 1; i <= 8; i++) { corner = lower_left; corner[X] += ((i & 1) ? lengths[X] : 0.0); corner[Y] += ((i & 2) ? lengths[Y] : 0.0); corner[Z] += ((i & 4) ? lengths[Z] : 0.0); MTransPoint(corner, corner, trans); if(corner[X] < mins[X]) { mins[X] = corner[X]; } if(corner[X] > maxs[X]) { maxs[X] = corner[X]; } if(corner[Y] < mins[Y]) { mins[Y] = corner[Y]; } if(corner[Y] > maxs[Y]) { maxs[Y] = corner[Y]; } if(corner[Z] < mins[Z]) { mins[Z] = corner[Z]; } if(corner[Z] > maxs[Z]) { maxs[Z] = corner[Z]; } } // Clip bounding box at the largest allowed bounding box. if(mins[X] < -BOUND_HUGE / 2) { mins[X] = -BOUND_HUGE / 2; } if(mins[Y] < -BOUND_HUGE / 2) { mins[Y] = -BOUND_HUGE / 2; } if(mins[Z] < -BOUND_HUGE / 2) { mins[Z] = -BOUND_HUGE / 2; } if(maxs[X] > BOUND_HUGE / 2) { maxs[X] = BOUND_HUGE / 2; } if(maxs[Y] > BOUND_HUGE / 2) { maxs[Y] = BOUND_HUGE / 2; } if(maxs[Z] > BOUND_HUGE / 2) { maxs[Z] = BOUND_HUGE / 2; } Make_BBox_from_min_max(*bbox, mins, maxs); }
void Polygon::Compute_BBox() { int i; Vector3d p, Puv, Min, Max; Min[X] = Min[Y] = Min[Z] = BOUND_HUGE; Max[X] = Max[Y] = Max[Z] = -BOUND_HUGE; for (i = 0; i < Data->Number; i++) { Puv[X] = Data->Points[i][X]; Puv[Y] = Data->Points[i][Y]; Puv[Z] = 0.0; MTransPoint(p, Puv, Trans); Min = min(Min, p); Max = max(Max, p); } Make_BBox_from_min_max(BBox, Min, Max); if (fabs(BBox.size[X]) < SMALL_TOLERANCE) { BBox.lowerLeft[X] -= SMALL_TOLERANCE; BBox.size[X] += 2.0 * SMALL_TOLERANCE; } if (fabs(BBox.size[Y]) < SMALL_TOLERANCE) { BBox.lowerLeft[Y] -= SMALL_TOLERANCE; BBox.size[Y] += 2.0 * SMALL_TOLERANCE; } if (fabs(BBox.size[Z]) < SMALL_TOLERANCE) { BBox.lowerLeft[Z] -= SMALL_TOLERANCE; BBox.size[Z] += 2.0 * SMALL_TOLERANCE; } }
bool Ovus::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread) { bool Found = false; Vector3d Real_Normal, Real_Pt, INormal, IPoint; DBL Depth1, Depth2, Depth3, Depth4, Depth5, Depth6; DBL len, horizontal; Vector3d P,D; Thread->Stats()[Ray_Ovus_Tests]++; MInvTransPoint(P, ray.Origin, Trans); MInvTransDirection(D, ray.Direction, Trans); len = D.length(); D /= len; Intersect_Ovus_Spheres(P, D, &Depth1, &Depth2, &Depth3, &Depth4, &Depth5, &Depth6, Thread); if (Depth1 > EPSILON) { IPoint = P + Depth1 * D; if (IPoint[Y] < BottomVertical) { MTransPoint(Real_Pt, IPoint, Trans); if (Clip.empty()||(Point_In_Clip(Real_Pt, Clip, Thread))) { INormal = IPoint / BottomRadius; MTransNormal(Real_Normal, INormal, Trans); Real_Normal.normalize(); Depth_Stack->push(Intersection(Depth1/len, Real_Pt, Real_Normal, this)); Found = true; } } } if (Depth2 > EPSILON) { IPoint = P + Depth2 * D; if (IPoint[Y] < BottomVertical) { MTransPoint(Real_Pt, IPoint, Trans); if (Clip.empty()||(Point_In_Clip(Real_Pt, Clip, Thread))) { INormal = IPoint / BottomRadius; MTransNormal(Real_Normal, INormal, Trans); Real_Normal.normalize(); Depth_Stack->push(Intersection(Depth2/len, Real_Pt, Real_Normal, this)); Found = true; } } } if (Depth3 > EPSILON) { IPoint = P + Depth3 * D; if (IPoint[Y] > TopVertical) { MTransPoint(Real_Pt, IPoint, Trans); if (Clip.empty()||(Point_In_Clip(Real_Pt, Clip, Thread))) { INormal = IPoint; INormal[Y] -= BottomRadius; INormal /= TopRadius; MTransNormal(Real_Normal, INormal, Trans); Real_Normal.normalize(); Depth_Stack->push(Intersection(Depth3/len, Real_Pt, Real_Normal, this)); Found = true; } } } if (Depth4 > EPSILON) { IPoint = P + Depth4 * D; if (IPoint[Y] > TopVertical) { MTransPoint(Real_Pt, IPoint, Trans); if (Clip.empty()||(Point_In_Clip(Real_Pt, Clip, Thread))) { INormal = IPoint; INormal[Y] -= BottomRadius; INormal /= TopRadius; MTransNormal(Real_Normal, INormal, Trans); Real_Normal.normalize(); Depth_Stack->push(Intersection(Depth4/len, Real_Pt, Real_Normal, this)); Found = true; } } } if (Depth5 > EPSILON) { IPoint = P + Depth5 * D; MTransPoint(Real_Pt, IPoint, Trans); if (Clip.empty()||(Point_In_Clip(Real_Pt, Clip, Thread))) { INormal = IPoint; INormal[Y] -= VerticalPosition; horizontal = sqrt(Sqr(INormal[X]) + Sqr(INormal[Z])); INormal[X] += (INormal[X] * HorizontalPosition / horizontal); INormal[Z] += (INormal[Z] * HorizontalPosition / horizontal); INormal.normalize(); MTransNormal(Real_Normal, INormal, Trans); Real_Normal.normalize(); Depth_Stack->push(Intersection(Depth5/len, Real_Pt, Real_Normal, this)); Found = true; } } if (Depth6 > EPSILON) { IPoint = P + Depth6 * D; MTransPoint(Real_Pt, IPoint, Trans); if (Clip.empty()||(Point_In_Clip(Real_Pt, Clip, Thread))) { INormal = IPoint; INormal[Y] -= VerticalPosition; horizontal = sqrt(Sqr(INormal[X]) + Sqr(INormal[Z])); INormal[X] += (INormal[X] * HorizontalPosition / horizontal); INormal[Z] += (INormal[Z] * HorizontalPosition / horizontal); INormal.normalize(); MTransNormal(Real_Normal, INormal, Trans); Real_Normal.normalize(); Depth_Stack->push(Intersection(Depth6/len, Real_Pt, Real_Normal, this)); Found = true; } } if (Found) { Thread->Stats()[Ray_Ovus_Tests_Succeeded]++; } return (Found); }
void Sphere::UVCoord(Vector2d& Result, const Intersection *Inter, TraceThreadData *Thread) const { DBL len, phi, theta; DBL x,y,z; Vector3d New_Point, New_Center; /* Transform the point into the sphere's space */ if (UV_Trans != NULL) { MInvTransPoint(New_Point, Inter->IPoint, UV_Trans); if (Trans != NULL) MTransPoint(New_Center, Center, Trans); else New_Center = Center; MInvTransPoint(New_Center, New_Center, UV_Trans); } else { New_Point = Inter->IPoint; New_Center = Center; } x = New_Point[X]-New_Center[X]; y = New_Point[Y]-New_Center[Y]; z = New_Point[Z]-New_Center[Z]; len = sqrt(x * x + y * y + z * z); if (len == 0.0) return; else { x /= len; y /= len; z /= len; } /* Determine its angle from the x-z plane. */ phi = 0.5 + asin(y) / M_PI; /* This will be from 0 to 1 */ /* Determine its angle from the point (1, 0, 0) in the x-z plane. */ len = x * x + z * z; if (len > EPSILON) { len = sqrt(len); if (z == 0.0) { if (x > 0) theta = 0.0; else theta = M_PI; } else { theta = acos(x / len); if (z < 0.0) theta = TWO_M_PI - theta; } theta /= TWO_M_PI; /* This will be from 0 to 1 */ } else /* This point is at one of the poles. Any value of xcoord will be ok... */ theta = 0; Result[U] = theta; Result[V] = phi; }
bool Fractal::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread) { bool Intersection_Found; bool LastIsInside = false; bool CurrentIsInside, NextIsInside; DBL Depth, Depth_Max; DBL Dist, Dist_Next, LenSqr, LenInv; Vector3d IPoint, Mid_Point, Next_Point, Real_Pt; Vector3d Real_Normal, F_Normal; Vector3d Direction; BasicRay New_Ray; Thread->Stats()[Ray_Fractal_Tests]++; Intersection_Found = false; /* Get into Fractal's world. */ if (Trans != NULL) { MInvTransDirection(Direction, ray.Direction, Trans); LenSqr = Direction.lengthSqr(); if (LenSqr == 0.0) { return (false); } if (LenSqr != 1.0) { LenInv = 1.0 / sqrt(LenSqr); Direction *= LenInv; } else LenInv = 1.0; New_Ray.Direction = Direction; MInvTransPoint(New_Ray.Origin, ray.Origin, Trans); } else { Direction = ray.Direction; New_Ray = ray; LenInv = 1.0; } /* Bound fractal. */ if (!F_Bound(New_Ray, this, &Depth, &Depth_Max)) { return (false); } if (Depth_Max < Fractal_Tolerance) { return (false); } if (Depth < Fractal_Tolerance) { Depth = Fractal_Tolerance; } /* Jump to starting point */ Next_Point = New_Ray.Origin + Direction * Depth; CurrentIsInside = D_Iteration(Next_Point, this, Direction, &Dist, Thread->Fractal_IStack); /* Light ray starting inside ? */ if (CurrentIsInside) { Next_Point += (2.0 * Fractal_Tolerance) * Direction; Depth += 2.0 * Fractal_Tolerance; if (Depth > Depth_Max) { return (false); } CurrentIsInside = D_Iteration(Next_Point, this, Direction, &Dist, Thread->Fractal_IStack); } /* Ok. Trace it */ while (Depth < Depth_Max) { /* * Get close to the root: Advance with Next_Point, keeping track of last * position in IPoint... */ while (1) { if (Dist < Precision) Dist = Precision; Depth += Dist; if (Depth > Depth_Max) { if (Intersection_Found) Thread->Stats()[Ray_Fractal_Tests_Succeeded]++; return (Intersection_Found); } IPoint = Next_Point; Next_Point += Dist * Direction; NextIsInside = D_Iteration(Next_Point, this, Direction, &Dist_Next, Thread->Fractal_IStack); if (NextIsInside != CurrentIsInside) { /* Set surface was crossed... */ Depth -= Dist; break; } else { Dist = Dist_Next; /* not reached */ } } /* then, polish the root via bisection method... */ while (Dist > Fractal_Tolerance) { Dist *= 0.5; Mid_Point = IPoint + Dist * Direction; LastIsInside = Iteration(Mid_Point, this, Thread->Fractal_IStack); if (LastIsInside == CurrentIsInside) { IPoint = Mid_Point; Depth += Dist; if (Depth > Depth_Max) { if (Intersection_Found) Thread->Stats()[Ray_Fractal_Tests_Succeeded]++; return (Intersection_Found); } } } if (!CurrentIsInside) /* Mid_Point isn't inside the set */ { IPoint += Dist * Direction; Depth += Dist; Iteration(IPoint, this, Thread->Fractal_IStack); } else { if (LastIsInside != CurrentIsInside) { Iteration(IPoint, this, Thread->Fractal_IStack); } } if (Trans != NULL) { MTransPoint(Real_Pt, IPoint, Trans); Normal_Calc(this, F_Normal, Thread->Fractal_IStack); MTransNormal(Real_Normal, F_Normal, Trans); } else { Real_Pt = IPoint; Normal_Calc(this, Real_Normal, Thread->Fractal_IStack); } if (Clip.empty() || Point_In_Clip(Real_Pt, Clip, Thread)) { Real_Normal.normalize(); Depth_Stack->push(Intersection(Depth * LenInv, Real_Pt, Real_Normal, this)); Intersection_Found = true; /* If fractal isn't used with CSG we can exit now. */ if (!(Type & IS_CHILD_OBJECT)) { break; } } /* Start over where work was left */ IPoint = Next_Point; Dist = Dist_Next; CurrentIsInside = NextIsInside; } if (Intersection_Found) Thread->Stats()[Ray_Fractal_Tests_Succeeded]++; return (Intersection_Found); }
bool Sphere::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread) { Thread->Stats()[Ray_Sphere_Tests]++; if(Do_Ellipsoid) { register int Intersection_Found; DBL Depth1, Depth2, len; Vector3d IPoint; BasicRay New_Ray; // Transform the ray into the ellipsoid's space MInvTransRay(New_Ray, ray, Trans); len = New_Ray.Direction.length(); New_Ray.Direction /= len; Intersection_Found = false; if(Intersect(New_Ray, Center, Sqr(Radius), &Depth1, &Depth2)) { Thread->Stats()[Ray_Sphere_Tests_Succeeded]++; if((Depth1 > DEPTH_TOLERANCE) && (Depth1 < MAX_DISTANCE)) { IPoint = New_Ray.Evaluate(Depth1); MTransPoint(IPoint, IPoint, Trans); if(Clip.empty() || Point_In_Clip(IPoint, Clip, Thread)) { Depth_Stack->push(Intersection(Depth1 / len, IPoint, this)); Intersection_Found = true; } } if((Depth2 > DEPTH_TOLERANCE) && (Depth2 < MAX_DISTANCE)) { IPoint = New_Ray.Evaluate(Depth2); MTransPoint(IPoint, IPoint, Trans); if(Clip.empty() || Point_In_Clip(IPoint, Clip, Thread)) { Depth_Stack->push(Intersection(Depth2 / len, IPoint, this)); Intersection_Found = true; } } } return(Intersection_Found); } else { register int Intersection_Found; DBL Depth1, Depth2; Vector3d IPoint; Intersection_Found = false; if(Intersect(ray, Center, Sqr(Radius), &Depth1, &Depth2)) { Thread->Stats()[Ray_Sphere_Tests_Succeeded]++; if((Depth1 > DEPTH_TOLERANCE) && (Depth1 < MAX_DISTANCE)) { IPoint = ray.Evaluate(Depth1); if(Clip.empty() || Point_In_Clip(IPoint, Clip, Thread)) { Depth_Stack->push(Intersection(Depth1, IPoint, this)); Intersection_Found = true; } } if((Depth2 > DEPTH_TOLERANCE) && (Depth2 < MAX_DISTANCE)) { IPoint = ray.Evaluate(Depth2); if(Clip.empty() || Point_In_Clip(IPoint, Clip, Thread)) { Depth_Stack->push(Intersection(Depth2, IPoint, this)); Intersection_Found = true; } } } return(Intersection_Found); } }