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 SmoothTriangle::Transform(const TRANSFORM *tr) { if(!Test_Flag(this, DEGENERATE_FLAG)) { MTransPoint(P1, P1, tr); MTransPoint(P2, P2, tr); MTransPoint(P3, P3, tr); MTransNormal(N1, N1, tr); MTransNormal(N2, N2, tr); MTransNormal(N3, N3, tr); Compute_Triangle(); } }
void UnWarp_Normal (VECTOR TNorm, VECTOR ENorm, TPATTERN *TPat, int DontScaleBumps) { WARP *Warp = NULL; if(!DontScaleBumps) VNormalize(TNorm,ENorm); else Assign_Vector(TNorm,ENorm); if(TPat->Warps != NULL) { // go to the last entry for(Warp = TPat->Warps; Warp->Next_Warp != NULL; Warp = Warp->Next_Warp) ; // walk backwards from the last entry for(; Warp != NULL; Warp = Warp->Prev_Warp) { if(Warp->Warp_Type == TRANSFORM_WARP) MTransNormal(TNorm, TNorm, &(((TRANS *)Warp)->Trans)); } } if(!DontScaleBumps) VNormalizeEq(TNorm); }
void Torus::Normal(Vector3d& Result, Intersection *Inter, TraceThreadData *Thread) const { DBL dist; Vector3d P, N, M; /* Transform the point into the torus space. */ MInvTransPoint(P, Inter->IPoint, Trans); /* Get normal from derivatives. */ dist = sqrt(P[X] * P[X] + P[Z] * P[Z]); if (dist > EPSILON) { M[X] = MajorRadius * P[X] / dist; M[Y] = 0.0; M[Z] = MajorRadius * P[Z] / dist; } else { M = Vector3d(0.0, 0.0, 0.0); } N = P - M; /* Transform the normalt out of the torus space. */ MTransNormal(Result, N, Trans); Result.normalize(); }
void SpindleTorus::Normal(Vector3d& Result, Intersection *Inter, TraceThreadData *Thread) const { DBL dist; Vector3d P, N, M; bool spindle = false; // The point has already been transformed into the torus space. P = Inter->LocalIPoint; // Get normal from derivatives. dist = sqrt(P[X] * P[X] + P[Z] * P[Z]); if (dist > EPSILON) { M[X] = MajorRadius * P[X] / dist; M[Y] = 0.0; M[Z] = MajorRadius * P[Z] / dist; } else { M = Vector3d(0.0, 0.0, 0.0); } if (Inter->b1) // Inter->b1 indicates whether the point is on the spindle (true) or not (false) N = P + M; else N = P - M; // Transform the normalt out of the torus space. MTransNormal(Result, N, Trans); Result.normalize(); }
void Parametric_Normal(VECTOR Result, OBJECT* Object, INTERSECTION* Inter) { VECTOR RU, RV; PARAMETRIC * Par = (PARAMETRIC *)Object; VECTOR * IPoint = &(Inter->IPoint); UV_VECT uv_vect; uv_vect[U] = Par->last_u; uv_vect[V] = Par->last_v; RU[X] = RV[X] = -Evaluate_Function_UV(*(Par->Function[X]), uv_vect); RU[Y] = RV[Y] = -Evaluate_Function_UV(*(Par->Function[Y]), uv_vect); RU[Z] = RV[Z] = -Evaluate_Function_UV(*(Par->Function[Z]), uv_vect); uv_vect[U] += Par->accuracy; RU[X] += Evaluate_Function_UV(*(Par->Function[X]), uv_vect); RU[Y] += Evaluate_Function_UV(*(Par->Function[Y]), uv_vect); RU[Z] += Evaluate_Function_UV(*(Par->Function[Z]), uv_vect); uv_vect[U] = Par->last_u; uv_vect[V] += Par->accuracy; RV[X] += Evaluate_Function_UV(*(Par->Function[X]), uv_vect); RV[Y] += Evaluate_Function_UV(*(Par->Function[Y]), uv_vect); RV[Z] += Evaluate_Function_UV(*(Par->Function[Z]), uv_vect); VCross(Result, RU, RV); if (Par->Trans != NULL) MTransNormal(Result, Result, Par->Trans); VNormalize(Result, Result); }
void ContainedByBox::Normal(const Vector3d& point, const TRANSFORM* pTrans, int side, Vector3d& rNormal) const { switch (side) { case Box::kSideHit_X0: rNormal = Vector3d(-1.0, 0.0, 0.0); break; case Box::kSideHit_X1: rNormal = Vector3d( 1.0, 0.0, 0.0); break; case Box::kSideHit_Y0: rNormal = Vector3d( 0.0,-1.0, 0.0); break; case Box::kSideHit_Y1: rNormal = Vector3d( 0.0, 1.0, 0.0); break; case Box::kSideHit_Z0: rNormal = Vector3d( 0.0, 0.0,-1.0); break; case Box::kSideHit_Z1: rNormal = Vector3d( 0.0, 0.0, 1.0); break; default: POV_SHAPE_ASSERT(false); } /* Transform the normal into the world space. */ if(pTrans != NULL) { MTransNormal(rNormal, rNormal, pTrans); rNormal.normalize(); } }
void Torus::Normal(VECTOR Result, Intersection *Inter, TraceThreadData *Thread) const { DBL dist; VECTOR P, N, M; /* Transform the point into the torus space. */ MInvTransPoint(P, Inter->IPoint, Trans); /* Get normal from derivatives. */ dist = sqrt(P[X] * P[X] + P[Z] * P[Z]); if (dist > EPSILON) { M[X] = MajorRadius * P[X] / dist; M[Y] = 0.0; M[Z] = MajorRadius * P[Z] / dist; } else { Make_Vector(M, 0.0, 0.0, 0.0); } VSub(N, P, M); /* Transform the normalt out of the torus space. */ MTransNormal(Result, N, Trans); VNormalize(Result, Result); }
void Parametric::Normal(VECTOR Result, Intersection *Inter, TraceThreadData *Thread) const { VECTOR RU, RV; UV_VECT uv_vect; uv_vect[U] = Inter->Iuv[U]; uv_vect[V] = Inter->Iuv[V]; RU[X] = RV[X] = -Evaluate_Function_UV(Thread->functionContext, *(Function[X]), uv_vect); RU[Y] = RV[Y] = -Evaluate_Function_UV(Thread->functionContext, *(Function[Y]), uv_vect); RU[Z] = RV[Z] = -Evaluate_Function_UV(Thread->functionContext, *(Function[Z]), uv_vect); uv_vect[U] += accuracy; RU[X] += Evaluate_Function_UV(Thread->functionContext, *(Function[X]), uv_vect); RU[Y] += Evaluate_Function_UV(Thread->functionContext, *(Function[Y]), uv_vect); RU[Z] += Evaluate_Function_UV(Thread->functionContext, *(Function[Z]), uv_vect); uv_vect[U] = Inter->Iuv[U]; uv_vect[V] += accuracy; RV[X] += Evaluate_Function_UV(Thread->functionContext, *(Function[X]), uv_vect); RV[Y] += Evaluate_Function_UV(Thread->functionContext, *(Function[Y]), uv_vect); RV[Z] += Evaluate_Function_UV(Thread->functionContext, *(Function[Z]), uv_vect); VCross(Result, RU, RV); if (Trans != NULL) MTransNormal(Result, Result, Trans); VNormalize(Result, Result); }
void Plane::Normal(VECTOR Result, Intersection *, TraceThreadData *) const { Assign_Vector(Result, Normal_Vector); if(Trans != NULL) { MTransNormal(Result, Result, Trans); VNormalize(Result, Result); } }
void Plane::Normal(Vector3d& Result, Intersection *, TraceThreadData *) const { Result = Normal_Vector; if(Trans != NULL) { MTransNormal(Result, Result, Trans); Result.normalize(); } }
static void Plane_Normal (VECTOR Result, OBJECT *Object, INTERSECTION *) { Assign_Vector(Result,((PLANE *)Object)->Normal_Vector); if (((PLANE *)Object)->Trans != NULL) { MTransNormal(Result, Result, ((PLANE *)Object)->Trans); VNormalize(Result, Result); } }
void Disc::Transform(const TRANSFORM *tr) { MTransNormal(normal, normal, tr); normal.normalize(); Compose_Transforms(Trans, tr); /* Recalculate the bounds */ Compute_BBox(); }
static void Transform_Polygon(OBJECT *Object, TRANSFORM *Trans) { VECTOR N; POLYGON *Polyg = (POLYGON *)Object; Compose_Transforms(Polyg->Trans, Trans); Make_Vector(N, 0.0, 0.0, 1.0); MTransNormal(Polyg->S_Normal, N, Polyg->Trans); VNormalizeEq(Polyg->S_Normal); Compute_Polygon_BBox(Polyg); }
static void Transform_Disc (OBJECT *Object, TRANSFORM *Trans) { DISC *Disc = (DISC *)Object; MTransNormal(((DISC *)Object)->normal, ((DISC *)Object)->normal, Trans); VNormalize(((DISC *)Object)->normal, ((DISC *)Object)->normal); Compose_Transforms(Disc->Trans, Trans); /* Recalculate the bounds */ Compute_Disc_BBox(Disc); }
void Polygon::Transform(const TRANSFORM *tr) { Vector3d N; if(Trans == NULL) Trans = Create_Transform(); Compose_Transforms(Trans, tr); N = Vector3d(0.0, 0.0, 1.0); MTransNormal(S_Normal, N, Trans); S_Normal.normalize(); Compute_BBox(); }
void Sphere::Normal(Vector3d& Result, Intersection *Inter, TraceThreadData *Thread) const { if(Do_Ellipsoid) { Vector3d New_Point; // Transform the point into the sphere's space MInvTransPoint(New_Point, Inter->IPoint, Trans); Result = New_Point - Center; MTransNormal(Result, Result, Trans); Result.normalize(); } else { Result = (Inter->IPoint - Center) / Radius; } }
void IsoSurface::Normal(Vector3d& Result, Intersection *Inter, TraceThreadData *Thread) const { Vector3d New_Point, TPoint; DBL funct; bool containerHit = Inter->i1; if (containerHit) { container->Normal(Inter->IPoint, Trans, Inter->i2, Result); } else { /* Transform the point into the isosurface space */ if(Trans != NULL) MInvTransPoint(New_Point, Inter->IPoint, Trans); else New_Point = Inter->IPoint; TPoint = New_Point; funct = Evaluate_Function(Function, Thread->functionContext, TPoint); TPoint = New_Point; TPoint[X] += accuracy; Result[X] = Evaluate_Function(Function, Thread->functionContext, TPoint) - funct; TPoint = New_Point; TPoint[Y] += accuracy; Result[Y] = Evaluate_Function(Function, Thread->functionContext, TPoint) - funct; TPoint = New_Point; TPoint[Z] += accuracy; Result[Z] = Evaluate_Function(Function, Thread->functionContext, TPoint) - funct; if((Result[X] == 0) && (Result[Y] == 0) && (Result[Z] == 0)) Result[X] = 1.0; Result.normalize(); /* Transform the point into the boxes space. */ if(Trans != NULL) { MTransNormal(Result, Result, Trans); Result.normalize(); } } }
void Sor::Normal(Vector3d& Result, Intersection *Inter, TraceThreadData *Thread) const { DBL k; Vector3d P; SOR_SPLINE_ENTRY *Entry; Vector3d N; switch (Inter->i1) { case CURVE: /* Transform the intersection point into the surface of revolution space. */ MInvTransPoint(P, Inter->IPoint, Trans); Entry = &Spline->Entry[Inter->i2]; k = 0.5 * (P[Y] * (3.0 * Entry->A * P[Y] + 2.0 * Entry->B) + Entry->C); N[X] = P[X]; N[Y] = -k; N[Z] = P[Z]; break; case BASE_PLANE: N = Vector3d(0.0, -1.0, 0.0); break; case CAP_PLANE: N = Vector3d(0.0, 1.0, 0.0); break; } /* Transform the normal out of the surface of revolution space. */ MTransNormal(Result, N, Trans); Result.normalize(); }
static void Cone_Normal(VECTOR Result, OBJECT *Object, INTERSECTION *Inter) { CONE *Cone = (CONE *)Object; /* Transform the point into the cones space */ MInvTransPoint(Result, Inter->IPoint, Cone->Trans); /* Calculating the normal is real simple in canonical cone space */ switch (Inter->i1) { case SIDE_HIT: if (Test_Flag(Cone, CYLINDER_FLAG)) { Result[Z] = 0.0; } else { Result[Z] = -Result[Z]; } break; case BASE_HIT: Make_Vector(Result, 0.0, 0.0, -1.0); break; case CAP_HIT: Make_Vector(Result, 0.0, 0.0, 1.0); break; } /* Transform the point out of the cones space */ MTransNormal(Result, Result, Cone->Trans); VNormalize(Result, Result); }
void Lathe::Normal(Vector3d& Result, Intersection *Inter, TraceThreadData *Thread) const { DBL r, dx, dy; Vector3d P, N; LATHE_SPLINE_ENTRY *Entry; Entry = &Spline->Entry[Inter->i1]; /* Transform the point into the lathe space. */ MInvTransPoint(P, Inter->IPoint, Trans); /* Get distance from rotation axis. */ r = P[X] * P[X] + P[Z] * P[Z]; if (r > EPSILON) { r = sqrt(r); /* Get derivatives. */ dx = Inter->d1 * (3.0 * Entry->A[X] * Inter->d1 + 2.0 * Entry->B[X]) + Entry->C[X]; dy = Inter->d1 * (3.0 * Entry->A[Y] * Inter->d1 + 2.0 * Entry->B[Y]) + Entry->C[Y]; /* Get normal by rotation. */ N[X] = dy * P[X]; N[Y] = -dx * r; N[Z] = dy * P[Z]; } else { N[X] = N[Z] = 0.0; N[Y] = 1.0; } /* Transform the normalt out of the lathe space. */ MTransNormal(Result, N, Trans); Result.normalize(); }
void Cone::Normal(Vector3d& Result, Intersection *Inter, TraceThreadData *Thread) const { /* Transform the point into the cones space */ MInvTransPoint(Result, Inter->IPoint, Trans); /* Calculating the normal is real simple in canonical cone space */ switch (Inter->i1) { case SIDE_HIT: if (Test_Flag(this, CYLINDER_FLAG)) { Result[Z] = 0.0; } else { Result[Z] = -Result[Z]; } break; case BASE_HIT: Result = Vector3d(0.0, 0.0, -1.0); break; case CAP_HIT: Result = Vector3d(0.0, 0.0, 1.0); break; } /* Transform the point out of the cones space */ MTransNormal(Result, Result, Trans); Result.normalize(); }
void ContainedBySphere::Normal(const Vector3d& point, const TRANSFORM* pTrans, int side, Vector3d& rNormal) const { Vector3d newPoint; /* Transform the point into the isosurface space */ if(pTrans != NULL) MInvTransPoint(newPoint, point, pTrans); else newPoint = point; rNormal = (newPoint - center) / radius; /* Transform the normal into the world space. */ if(pTrans != NULL) { MTransNormal(rNormal, rNormal, pTrans); rNormal.normalize(); } }
bool Lemon::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread) { bool Intersection_Found; int cnt, i; Vector3d Real_Normal; Vector3d Real_Pt,INormal; LEMON_INT I[4]; Vector3d P,D; DBL len; Thread->Stats()[Ray_Lemon_Tests]++; MInvTransPoint(P, ray.Origin, Trans); MInvTransDirection(D, ray.Direction, Trans); len = D.length(); D /= len; Intersection_Found = false; if ((cnt = Intersect(P, D, I, Thread)) != 0) { for (i = 0; i < cnt; i++) { Real_Pt = ray.Origin + I[i].d/len * ray.Direction; if (Clip.empty() || Point_In_Clip(Real_Pt, Clip, Thread)) { INormal = I[i].n; MTransNormal(Real_Normal, INormal, Trans); Real_Normal.normalize(); Depth_Stack->push(Intersection(I[i].d/len,Real_Pt,Real_Normal,this)); Intersection_Found = true; } } } if(Intersection_Found) { Thread->Stats()[Ray_Lemon_Tests_Succeeded]++; } return (Intersection_Found); }
static void Box_Normal(VECTOR Result, OBJECT *Object, INTERSECTION *Inter) { switch (Inter->i1) { case SIDE_X_0: Make_Vector(Result, -1.0, 0.0, 0.0); break; case SIDE_X_1: Make_Vector(Result, 1.0, 0.0, 0.0); break; case SIDE_Y_0: Make_Vector(Result, 0.0, -1.0, 0.0); break; case SIDE_Y_1: Make_Vector(Result, 0.0, 1.0, 0.0); break; case SIDE_Z_0: Make_Vector(Result, 0.0, 0.0, -1.0); break; case SIDE_Z_1: Make_Vector(Result, 0.0, 0.0, 1.0); break; default: Error("Unknown box side in Box_Normal()."); } /* Transform the point into the boxes space. */ if (((BOX *)Object)->Trans != NULL) { MTransNormal(Result, Result, ((BOX *)Object)->Trans); VNormalize(Result, Result); } }
void Superellipsoid::Normal(Vector3d& Result, Intersection *Inter, TraceThreadData *Thread) const { Vector3d const& E = Power; Vector3d P; /* Transform the point into the superellipsoid space. */ MInvTransPoint(P, Inter->IPoint, Trans); DBL r, z2n = 0; if (P[Z] != 0) { z2n = power(fabs(P[Z]), E[Z]); P[Z] = z2n / P[Z]; } if (fabs(P[X]) > fabs(P[Y])) { r = power(fabs(P[Y] / P[X]), E[X]); P[X] = (1-z2n) / P[X]; P[Y] = P[Y] ? (1-z2n) * r / P[Y] : 0; } else if (P[Y] != 0) { r = power(fabs(P[X] / P[Y]), E[X]); P[X] = P[X] ? (1-z2n) * r / P[X] : 0; P[Y] = (1-z2n) / P[Y]; } if(P[Z]) P[Z] *= (1 + r); /* Transform the normalt out of the superellipsoid space. */ MTransNormal(Result, P, Trans); Result.normalize(); }
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); }
void Polygon::Compute_Polygon(int number, Vector3d *points) { int i; DBL x, y, z, d; Vector3d o, u, v, w, N; MATRIX a, b; /* Create polygon data. */ if (Data == NULL) { Data = reinterpret_cast<POLYGON_DATA *>(POV_MALLOC(sizeof(POLYGON_DATA), "polygon points")); Data->References = 1; Data->Number = number; Data->Points = reinterpret_cast<Vector2d *>(POV_MALLOC(number*sizeof(Vector2d), "polygon points")); } else { throw POV_EXCEPTION_STRING("Polygon data already computed."); } /* Get polygon's coordinate system (one of the many possible) */ o = points[0]; /* Find valid, i.e. non-zero u vector. */ for (i = 1; i < number; i++) { u = points[i] - o; if (u.lengthSqr() > EPSILON) { break; } } if (i == number) { Set_Flag(this, DEGENERATE_FLAG); ;// TODO MESSAGE Warning("Points in polygon are co-linear. Ignoring polygon."); } /* Find valid, i.e. non-zero v and w vectors. */ for (i++; i < number; i++) { v = points[i] - o; w = cross(u, v); if ((v.lengthSqr() > EPSILON) && (w.lengthSqr() > EPSILON)) { break; } } if (i == number) { Set_Flag(this, DEGENERATE_FLAG); ;// TODO MESSAGE Warning("Points in polygon are co-linear. Ignoring polygon."); } u = cross(v, w); v = cross(w, u); u.normalize(); v.normalize(); w.normalize(); MIdentity(a); MIdentity(b); a[3][0] = -o[X]; a[3][1] = -o[Y]; a[3][2] = -o[Z]; b[0][0] = u[X]; b[1][0] = u[Y]; b[2][0] = u[Z]; b[0][1] = v[X]; b[1][1] = v[Y]; b[2][1] = v[Z]; b[0][2] = w[X]; b[1][2] = w[Y]; b[2][2] = w[Z]; MTimesC(Trans->inverse, a, b); MInvers(Trans->matrix, Trans->inverse); /* Project points onto the u,v-plane (3D --> 2D) */ for (i = 0; i < number; i++) { x = points[i][X] - o[X]; y = points[i][Y] - o[Y]; z = points[i][Z] - o[Z]; d = x * w[X] + y * w[Y] + z * w[Z]; if (fabs(d) > ZERO_TOLERANCE) { Set_Flag(this, DEGENERATE_FLAG); ;// TODO MESSAGE Warning("Points in polygon are not co-planar. Ignoring polygons."); } Data->Points[i][X] = x * u[X] + y * u[Y] + z * u[Z]; Data->Points[i][Y] = x * v[X] + y * v[Y] + z * v[Z]; } N = Vector3d(0.0, 0.0, 1.0); MTransNormal(S_Normal, N, Trans); S_Normal.normalize(); Compute_BBox(); }
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); }
bool TransformWarp::UnwarpNormal(Vector3d& TNorm) const { MTransNormal(TNorm, TNorm, &Trans); return true; }