static void Translate_Box(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans) { if (((BOX *)Object)->Trans == NULL) { VAddEq(((BOX *)Object)->bounds[0], Vector); VAddEq(((BOX *)Object)->bounds[1], Vector); Compute_Box_BBox((BOX *)Object); } else { Transform_Box(Object, Trans); } }
BEGIN_POV_NAMESPACE /***************************************************************************** * * FUNCTION * * Translate_Camera * * INPUT * * OUTPUT * * RETURNS * * AUTHOR * * POV-Ray Team * * DESCRIPTION * * - * * CHANGES * * - * ******************************************************************************/ void Translate_Camera(CAMERA *Camera, VECTOR Vector) { VAddEq(((CAMERA *)Camera)->Location, Vector); }
static void Translate_Triangle(OBJECT *Object, VECTOR Vector, TRANSFORM * /*Trans*/) { TRIANGLE *Triangle = (TRIANGLE *)Object; /*VECTOR Translation;*/ if (!Test_Flag(Triangle, DEGENERATE_FLAG)) { /* BEG ROSE this is useless, because Compute_Triangle recalculates this anyway: VEvaluate(Translation, Triangle->Normal_Vector, Vector); Triangle->Distance -= Translation[X] + Translation[Y] + Translation[Z]; END ROSE */ VAddEq(Triangle->P1, Vector); VAddEq(Triangle->P2, Vector); VAddEq(Triangle->P3, Vector); Compute_Triangle(Triangle, false); } }
void Compute_Triangle_BBox(TRIANGLE *Triangle) { VECTOR Min, Max, Epsilon; Make_Vector(Epsilon, EPSILON, EPSILON, EPSILON); Min[X] = min3(Triangle->P1[X], Triangle->P2[X], Triangle->P3[X]); Min[Y] = min3(Triangle->P1[Y], Triangle->P2[Y], Triangle->P3[Y]); Min[Z] = min3(Triangle->P1[Z], Triangle->P2[Z], Triangle->P3[Z]); Max[X] = max3(Triangle->P1[X], Triangle->P2[X], Triangle->P3[X]); Max[Y] = max3(Triangle->P1[Y], Triangle->P2[Y], Triangle->P3[Y]); Max[Z] = max3(Triangle->P1[Z], Triangle->P2[Z], Triangle->P3[Z]); VSubEq(Min, Epsilon); VAddEq(Max, Epsilon); Make_BBox_from_min_max(Triangle->BBox, Min, Max); }
void Warp_EPoint (VECTOR TPoint, VECTOR EPoint, TPATTERN *TPat) { VECTOR PTurbulence,RP; int Axis,i,temp_rand; int blockX = 0, blockY = 0, blockZ = 0 ; SNGL BlkNum; DBL Length; DBL Strength; WARP *Warp=TPat->Warps; TURB *Turb; TRANS *Tr; REPEAT *Repeat; BLACK_HOLE *Black_Hole; VECTOR Delta, Center; Assign_Vector(TPoint, EPoint); while (Warp != NULL) { switch(Warp->Warp_Type) { case CLASSIC_TURB_WARP: if ((TPat->Type == MARBLE_PATTERN) || (TPat->Type == NO_PATTERN) || (TPat->Type == WOOD_PATTERN)) { break; } /* If not a special type, fall through to next case */ case EXTRA_TURB_WARP: Turb=(TURB *)Warp; DTurbulence (PTurbulence, TPoint, Turb); TPoint[X] += PTurbulence[X] * Turb->Turbulence[X]; TPoint[Y] += PTurbulence[Y] * Turb->Turbulence[Y]; TPoint[Z] += PTurbulence[Z] * Turb->Turbulence[Z]; break; case NO_WARP: break; case TRANSFORM_WARP: Tr=(TRANS *)Warp; MInvTransPoint(TPoint, TPoint, &(Tr->Trans)); break; case REPEAT_WARP: Repeat=(REPEAT *)Warp; Assign_Vector(RP,TPoint); Axis=Repeat->Axis; BlkNum=(SNGL)floor(TPoint[Axis]/Repeat->Width); RP[Axis]=TPoint[Axis]-BlkNum*Repeat->Width; if (((int)BlkNum) & 1) { VEvaluateEq(RP,Repeat->Flip); if ( Repeat->Flip[Axis] < 0 ) { RP[Axis] = Repeat->Width+RP[Axis]; } } VAddScaledEq(RP,BlkNum,Repeat->Offset); Assign_Vector(TPoint,RP); break; case BLACK_HOLE_WARP: Black_Hole = (BLACK_HOLE *) Warp ; Assign_Vector (Center, Black_Hole->Center) ; if (Black_Hole->Repeat) { /* first, get the block number we're in for each dimension */ /* block numbers are (currently) calculated relative to 0 */ /* we use floor () since it correctly returns -1 for the first block below 0 in each axis */ /* one final point - we could run into overflow problems if the repeat vector was small and the scene very large. */ if (Black_Hole->Repeat_Vector [X] >= Small_Tolerance) blockX = (int) floor (TPoint [X] / Black_Hole->Repeat_Vector [X]) ; if (Black_Hole->Repeat_Vector [Y] >= Small_Tolerance) blockY = (int) floor (TPoint [Y] / Black_Hole->Repeat_Vector [Y]) ; if (Black_Hole->Repeat_Vector [Z] >= Small_Tolerance) blockZ = (int) floor (TPoint [Z] / Black_Hole->Repeat_Vector [Z]) ; if (Black_Hole->Uncertain) { /* if the position is uncertain calculate the new one first */ /* this will allow the same numbers to be returned by frand */ temp_rand = POV_GET_OLD_RAND(); /*protect seed*/ POV_SRAND (Hash3d (blockX, blockY, blockZ)) ; Center [X] += FRAND () * Black_Hole->Uncertainty_Vector [X] ; Center [Y] += FRAND () * Black_Hole->Uncertainty_Vector [Y] ; Center [Z] += FRAND () * Black_Hole->Uncertainty_Vector [Z] ; POV_SRAND (temp_rand) ; /*restore*/ } Center [X] += Black_Hole->Repeat_Vector [X] * blockX ; Center [Y] += Black_Hole->Repeat_Vector [Y] * blockY ; Center [Z] += Black_Hole->Repeat_Vector [Z] * blockZ ; } VSub (Delta, TPoint, Center) ; VLength (Length, Delta) ; /* Length is the distance from the centre of the black hole */ if (Length >= Black_Hole->Radius) break ; if (Black_Hole->Type == 0) { /* now convert the length to a proportion (0 to 1) that the point is from the edge of the black hole. a point on the perimeter of the black hole will be 0.0 ; a point at the centre will be 1.0 ; a point exactly halfway will be 0.5, and so forth. */ Length = (Black_Hole->Radius - Length) / Black_Hole->Radius ; /* Strength is the magnitude of the transformation effect. firstly, apply the Power variable to Length. this is meant to provide a means of controlling how fast the power of the Black Hole falls off from its centre. if Power is 2.0, then the effect is inverse square. increasing power will cause the Black Hole to be a lot weaker in its effect towards its perimeter. finally we multiply Strength with the Black Hole's Strength variable. if the resultant value exceeds 1.0 we clip it to 1.0. this means a point will never be transformed by more than its original distance from the centre. the result of this clipping is that you will have an 'exclusion' area near the centre of the black hole where all points whose final value exceeded or equalled 1.0 were moved by a fixed amount. this only happens if the Strength value of the Black Hole was greater than one. */ Strength = pow (Length, Black_Hole->Power) * Black_Hole->Strength ; if (Strength > 1.0) Strength = 1.0 ; /* if the Black Hole is inverted, it gives the impression of 'push- ing' the pattern away from its centre. otherwise it sucks. */ VScaleEq (Delta, Black_Hole->Inverted ? -Strength : Strength) ; /* add the scaled Delta to the input point to end up with TPoint. */ VAddEq (TPoint, Delta) ; } break; /* 10/23/1998 Talious added SPherical Cylindrical and toroidal warps */ case CYLINDRICAL_WARP: warp_cylindrical(TPoint, (CYLW *)Warp); break; case PLANAR_WARP: warp_planar(TPoint, (PLANARW *)Warp); break; case SPHERICAL_WARP: warp_spherical(TPoint, (SPHEREW *)Warp); break; case TOROIDAL_WARP: warp_toroidal(TPoint, (TOROIDAL *) Warp); break; default: Error("Warp type %d not yet implemented",Warp->Warp_Type); } Warp=Warp->Next_Warp; } for (i=X; i<=Z; i++) if (TPoint[i] > COORDINATE_LIMIT) TPoint[i]= COORDINATE_LIMIT; else if (TPoint[i] < -COORDINATE_LIMIT) TPoint[i] = -COORDINATE_LIMIT; }
void Compute_Quadric_BBox(QUADRIC *Quadric, VECTOR ClipMin, VECTOR ClipMax) { DBL A, B, C, D, E, F, G, H, I, J; DBL a, b, c, d; DBL rx, ry, rz, rx1, rx2, ry1, ry2, rz1, rz2, x, y, z; DBL New_Volume, Old_Volume; VECTOR Min, Max, TmpMin, TmpMax, NewMin, NewMax, T1; BBOX Old; OBJECT *Sib; /* * Check for 'normal' form. If the quadric isn't in it's normal form * we can't do anything (we could, but that would be to tedious! * Diagonalising the quadric's 4x4 matrix, i.e. finding its eigenvalues * and eigenvectors -> solving a 4th order polynom). */ /* Get quadrics coefficients. */ A = Quadric->Square_Terms[X]; E = Quadric->Square_Terms[Y]; H = Quadric->Square_Terms[Z]; B = Quadric->Mixed_Terms[X] / 2.0; C = Quadric->Mixed_Terms[Y] / 2.0; F = Quadric->Mixed_Terms[Z] / 2.0; D = Quadric->Terms[X] / 2.0; G = Quadric->Terms[Y] / 2.0; I = Quadric->Terms[Z] / 2.0; J = Quadric->Constant; /* Set small values to 0. */ if (fabs(A) < EPSILON) A = 0.0; if (fabs(B) < EPSILON) B = 0.0; if (fabs(C) < EPSILON) C = 0.0; if (fabs(D) < EPSILON) D = 0.0; if (fabs(E) < EPSILON) E = 0.0; if (fabs(F) < EPSILON) F = 0.0; if (fabs(G) < EPSILON) G = 0.0; if (fabs(H) < EPSILON) H = 0.0; if (fabs(I) < EPSILON) I = 0.0; if (fabs(J) < EPSILON) J = 0.0; /* Non-zero mixed terms --> return */ if ((B != 0.0) || (C != 0.0) || (F != 0.0)) { return; } /* Non-zero linear terms --> get translation vector */ if ((D != 0.0) || (G != 0.0) || (I != 0.0)) { if (A != 0.0) { T1[X] = -D / A; } else { if (D != 0.0) { T1[X] = J / (2.0 * D); } else { T1[X] = 0.0; } } if (E != 0.0) { T1[Y] = -G / E; } else { if (G != 0.0) { T1[Y] = J / (2.0 * G); } else { T1[Y] = 0.0; } } if (H != 0.0) { T1[Z] = -I / H; } else { if (I != 0.0) { T1[Z] = J / (2.0 * I); } else { T1[Z] = 0.0; } } /* Recalculate coefficients. */ D += A * T1[X]; G += E * T1[Y]; I += H * T1[Z]; J -= T1[X]*(A*T1[X] + 2.0*D) + T1[Y]*(E*T1[Y] + 2.0*G) + T1[Z]*(H*T1[Z] + 2.0*I); } else { Make_Vector(T1, 0.0, 0.0, 0.0); } /* Get old bounding box. */ Old = Quadric->BBox; /* Init new bounding box. */ NewMin[X] = NewMin[Y] = NewMin[Z] = -BOUND_HUGE/2; NewMax[X] = NewMax[Y] = NewMax[Z] = BOUND_HUGE/2; /* Get the bounding box of the clipping object. */ if (Quadric->Clip != NULL) { Min[X] = Min[Y] = Min[Z] = -BOUND_HUGE; Max[X] = Max[Y] = Max[Z] = BOUND_HUGE; /* Intersect the members bounding boxes. */ for (Sib = Quadric->Clip; Sib != NULL; Sib = Sib->Sibling) { if (!Test_Flag(Sib, INVERTED_FLAG)) { if (Sib->Methods == &Plane_Methods) { Compute_Plane_Min_Max((PLANE *)Sib, TmpMin, TmpMax); } else { Make_min_max_from_BBox(TmpMin, TmpMax, Sib->BBox); } Min[X] = max(Min[X], TmpMin[X]); Min[Y] = max(Min[Y], TmpMin[Y]); Min[Z] = max(Min[Z], TmpMin[Z]); Max[X] = min(Max[X], TmpMax[X]); Max[Y] = min(Max[Y], TmpMax[Y]); Max[Z] = min(Max[Z], TmpMax[Z]); } } Assign_Vector(ClipMin, Min); Assign_Vector(ClipMax, Max); } /* Translate clipping box. */ VSubEq(ClipMin, T1); VSubEq(ClipMax, T1); /* We want A to be non-negative. */ if (A < 0.0) { A = -A; D = -D; E = -E; G = -G; H = -H; I = -I; J = -J; } /* * * Check for ellipsoid. * * x*x y*y z*z * ----- + ----- + ----- - 1 = 0 * a*a b*b c*c * */ if ((A > 0.0) && (E > 0.0) && (H > 0.0) && (J < 0.0)) { a = sqrt(-J/A); b = sqrt(-J/E); c = sqrt(-J/H); NewMin[X] = -a; NewMin[Y] = -b; NewMin[Z] = -c; NewMax[X] = a; NewMax[Y] = b; NewMax[Z] = c; } /* * * Check for cylinder (x-axis). * * y*y z*z * ----- + ----- - 1 = 0 * b*b c*c * */ if ((A == 0.0) && (E > 0.0) && (H > 0.0) && (J < 0.0)) { b = sqrt(-J/E); c = sqrt(-J/H); NewMin[Y] = -b; NewMin[Z] = -c; NewMax[Y] = b; NewMax[Z] = c; } /* * * Check for cylinder (y-axis). * * x*x z*z * ----- + ----- - 1 = 0 * a*a c*c * */ if ((A > 0.0) && (E == 0.0) && (H > 0.0) && (J < 0.0)) { a = sqrt(-J/A); c = sqrt(-J/H); NewMin[X] = -a; NewMin[Z] = -c; NewMax[X] = a; NewMax[Z] = c; } /* * * Check for cylinder (z-axis). * * x*x y*y * ----- + ----- - 1 = 0 * a*a b*b * */ if ((A > 0.0) && (E > 0.0) && (H == 0.0) && (J < 0.0)) { a = sqrt(-J/A); b = sqrt(-J/E); NewMin[X] = -a; NewMin[Y] = -b; NewMax[X] = a; NewMax[Y] = b; } /* * * Check for cone (x-axis). * * x*x y*y z*z * ----- - ----- - ----- = 0 * a*a b*b c*c * */ if ((A > 0.0) && (E < 0.0) && (H < 0.0) && (J == 0.0)) { a = sqrt(1.0/A); b = sqrt(-1.0/E); c = sqrt(-1.0/H); /* Get radii for lower x value. */ x = ClipMin[X]; ry1 = fabs(x * b / a); rz1 = fabs(x * c / a); /* Get radii for upper x value. */ x = ClipMax[X]; ry2 = fabs(x * b / a); rz2 = fabs(x * c / a); ry = max(ry1, ry2); rz = max(rz1, rz2); NewMin[Y] = -ry; NewMin[Z] = -rz; NewMax[Y] = ry; NewMax[Z] = rz; } /* * * Check for cone (y-axis). * * x*x y*y z*z * ----- - ----- + ----- = 0 * a*a b*b c*c * */ if ((A > 0.0) && (E < 0.0) && (H > 0.0) && (J == 0.0)) { a = sqrt(1.0/A); b = sqrt(-1.0/E); c = sqrt(1.0/H); /* Get radii for lower y value. */ y = ClipMin[Y]; rx1 = fabs(y * a / b); rz1 = fabs(y * c / b); /* Get radii for upper y value. */ y = ClipMax[Y]; rx2 = fabs(y * a / b); rz2 = fabs(y * c / b); rx = max(rx1, rx2); rz = max(rz1, rz2); NewMin[X] = -rx; NewMin[Z] = -rz; NewMax[X] = rx; NewMax[Z] = rz; } /* * * Check for cone (z-axis). * * x*x y*y z*z * ----- + ----- - ----- = 0 * a*a b*b c*c * */ if ((A > 0.0) && (E > 0.0) && (H < 0.0) && (J == 0.0)) { a = sqrt(1.0/A); b = sqrt(1.0/E); c = sqrt(-1.0/H); /* Get radii for lower z value. */ z = ClipMin[Z]; rx1 = fabs(z * a / c); ry1 = fabs(z * b / c); /* Get radii for upper z value. */ z = ClipMax[Z]; rx2 = fabs(z * a / c); ry2 = fabs(z * b / c); rx = max(rx1, rx2); ry = max(ry1, ry2); NewMin[X] = -rx; NewMin[Y] = -ry; NewMax[X] = rx; NewMax[Y] = ry; } /* * * Check for hyperboloid (x-axis). * * x*x y*y z*z * ----- - ----- - ----- + 1 = 0 * a*a b*b c*c * */ if ((A > 0.0) && (E < 0.0) && (H < 0.0) && (J > 0.0)) { /* Get radii for lower x value. */ x = ClipMin[X]; d = 1.0 + A * Sqr(x); ry1 = sqrt(-d / E); rz1 = sqrt(-d / H); /* Get radii for upper x value. */ x = ClipMax[X]; d = 1.0 + A * Sqr(x); ry2 = sqrt(-d / E); rz2 = sqrt(-d / H); ry = max(ry1, ry2); rz = max(rz1, rz2); NewMin[Y] = -ry; NewMin[Z] = -rz; NewMax[Y] = ry; NewMax[Z] = rz; } /* * * Check for hyperboloid (y-axis). * * x*x y*y z*z * ----- - ----- + ----- - 1 = 0 * a*a b*b c*c * */ if ((A > 0.0) && (E < 0.0) && (H > 0.0) && (J < 0.0)) { /* Get radii for lower y value. */ y = ClipMin[Y]; d = 1.0 - E * Sqr(y); rx1 = sqrt(d / A); rz1 = sqrt(d / H); /* Get radii for upper y value. */ y = ClipMax[Y]; d = 1.0 - E * Sqr(y); rx2 = sqrt(d / A); rz2 = sqrt(d / H); rx = max(rx1, rx2); rz = max(rz1, rz2); NewMin[X] = -rx; NewMin[Z] = -rz; NewMax[X] = rx; NewMax[Z] = rz; } /* * * Check for hyperboloid (z-axis). * * x*x y*y z*z * ----- + ----- - ----- - 1 = 0 * a*a b*b c*c * */ if ((A > 0.0) && (E > 0.0) && (H < 0.0) && (J < 0.0)) { /* Get radii for lower z value. */ z = ClipMin[Z]; d = 1.0 - H * Sqr(z); rx1 = sqrt(d / A); ry1 = sqrt(d / E); /* Get radii for upper z value. */ z = ClipMax[Z]; d = 1.0 - H * Sqr(z); rx2 = sqrt(d / A); ry2 = sqrt(d / E); rx = max(rx1, rx2); ry = max(ry1, ry2); NewMin[X] = -rx; NewMin[Y] = -ry; NewMax[X] = rx; NewMax[Y] = ry; } /* * * Check for paraboloid (x-axis). * * y*y z*z * x - ----- - ----- = 0 * b*b c*c * */ if ((A == 0.0) && (D != 0.0) && (E != 0.0) && (H != 0.0) && (J == 0.0)) { /* Get radii for lower x value. */ x = ClipMin[X]; ry1 = sqrt(fabs(2.0 * D * x / E)); rz1 = sqrt(fabs(2.0 * D * x / H)); /* Get radii for upper x value. */ x = ClipMax[X]; ry2 = sqrt(fabs(2.0 * D * x / E)); rz2 = sqrt(fabs(2.0 * D * x / H)); ry = max(ry1, ry2); rz = max(rz1, rz2); NewMin[Y] = -ry; NewMin[Z] = -rz; NewMax[Y] = ry; NewMax[Z] = rz; } /* * * Check for paraboloid (y-axis). * * x*x z*z * y - ----- - ----- = 0 * a*a c*c * */ if ((E == 0.0) && (G != 0.0) && (A != 0.0) && (H != 0.0) && (J == 0.0)) { /* Get radii for lower y-value. */ y = ClipMin[Y]; rx1 = sqrt(fabs(2.0 * G * y / A)); rz1 = sqrt(fabs(2.0 * G * y / H)); /* Get radii for upper y value. */ y = ClipMax[Y]; rx2 = sqrt(fabs(2.0 * G * y / A)); rz2 = sqrt(fabs(2.0 * G * y / H)); rx = max(rx1, rx2); rz = max(rz1, rz2); NewMin[X] = -rx; NewMin[Z] = -rz; NewMax[X] = rx; NewMax[Z] = rz; } /* * * Check for paraboloid (z-axis). * * x*x y*y * z - ----- - ----- = 0 * a*a b*b * */ if ((H == 0.0) && (I != 0.0) && (A != 0.0) && (E != 0.0) && (J == 0.0)) { /* Get radii for lower z-value. */ z = ClipMin[Z]; rx1 = sqrt(fabs(2.0 * I * z / A)); ry1 = sqrt(fabs(2.0 * I * z / E)); /* Get radii for upper z value. */ z = ClipMax[Z]; rx2 = sqrt(fabs(2.0 * I * z / A)); ry2 = sqrt(fabs(2.0 * I * z / E)); rx = max(rx1, rx2); ry = max(ry1, ry2); NewMin[X] = -rx; NewMin[Y] = -ry; NewMax[X] = rx; NewMax[Y] = ry; } /* Intersect clipping object's and quadric's bounding boxes */ NewMin[X] = max(NewMin[X], ClipMin[X]); NewMin[Y] = max(NewMin[Y], ClipMin[Y]); NewMin[Z] = max(NewMin[Z], ClipMin[Z]); NewMax[X] = min(NewMax[X], ClipMax[X]); NewMax[Y] = min(NewMax[Y], ClipMax[Y]); NewMax[Z] = min(NewMax[Z], ClipMax[Z]); /* Use old or new bounding box? */ New_Volume = (NewMax[X] - NewMin[X]) * (NewMax[Y] - NewMin[Y]) * (NewMax[Z] - NewMin[Z]); BOUNDS_VOLUME(Old_Volume, Old); if (New_Volume < Old_Volume) { /* Add translation. */ Quadric->Automatic_Bounds = true; VAddEq(NewMin, T1); VAddEq(NewMax, T1); Make_BBox_from_min_max(Quadric->BBox, NewMin, NewMax); /* Beware of bounding boxes to large. */ if ((Quadric->BBox.Lengths[X] > CRITICAL_LENGTH) || (Quadric->BBox.Lengths[Y] > CRITICAL_LENGTH) || (Quadric->BBox.Lengths[Z] > CRITICAL_LENGTH)) { Make_BBox(Quadric->BBox, -BOUND_HUGE/2, -BOUND_HUGE/2, -BOUND_HUGE/2, BOUND_HUGE, BOUND_HUGE, BOUND_HUGE); } } }
bool Parametric::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread) { VECTOR P, D, IPoint; UV_VECT low_vect, hi_vect, uv; Ray New_Ray; DBL XRayMin, XRayMax, YRayMin, YRayMax, ZRayMin, ZRayMax, TPotRes, TLen; DBL Depth1, Depth2, temp, Len, TResult = HUGE_VAL; DBL low, hi, len; int MaxPrecompX, MaxPrecompY, MaxPrecompZ; int split, i = 0, Side1, Side2; int parX, parY; int i_flg; DBL Intervals_Low[2][32]; DBL Intervals_Hi[2][32]; int SectorNum[32]; Thread->Stats()[Ray_Par_Bound_Tests]++; if(container_shape) { if(Trans != NULL) { MInvTransPoint(New_Ray.Origin, ray.Origin, Trans); MInvTransDirection(New_Ray.Direction, ray.Direction, Trans); VLength(len, New_Ray.Direction); VInverseScaleEq(New_Ray.Direction, len); i_flg = Sphere::Intersect(New_Ray, container.sphere.center, (container.sphere.radius) * (container.sphere.radius), &Depth1, &Depth2); Depth1 = Depth1 / len; Depth2 = Depth2 / len; } else { i_flg = Sphere::Intersect(ray, container.sphere.center, (container.sphere.radius) * (container.sphere.radius), &Depth1, &Depth2); } Thread->Stats()[Ray_Sphere_Tests]--; if(i_flg) Thread->Stats()[Ray_Sphere_Tests_Succeeded]--; } else { i_flg = Box::Intersect(ray, Trans, container.box.corner1, container.box.corner2, &Depth1, &Depth2, &Side1, &Side2); } if(!i_flg) return false; Thread->Stats()[Ray_Par_Bound_Tests_Succeeded]++; Thread->Stats()[Ray_Parametric_Tests]++; if (Trans != NULL) { MInvTransPoint(P, ray.Origin, Trans); MInvTransDirection(D, ray.Direction, Trans); } else { P[X] = ray.Origin[X]; P[Y] = ray.Origin[Y]; P[Z] = ray.Origin[Z]; D[X] = ray.Direction[X]; D[Y] = ray.Direction[Y]; D[Z] = ray.Direction[Z]; } if (Depth1 == Depth2) Depth1 = 0; if ((Depth1 += 4 * accuracy) > Depth2) return false; Intervals_Low[INDEX_U][0] = umin; Intervals_Hi[INDEX_U][0] = umax; Intervals_Low[INDEX_V][0] = vmin; Intervals_Hi[INDEX_V][0] = vmax; /* Fri 09-27-1996 0. */ SectorNum[0] = 1; MaxPrecompX = MaxPrecompY = MaxPrecompZ = 0; if (PData != NULL) { if (((PData->flags) & OK_X) != 0) MaxPrecompX = 1 << (PData->depth); if (((PData->flags) & OK_Y) != 0) MaxPrecompY = 1 << (PData->depth); if (((PData->flags) & OK_Z) != 0) MaxPrecompZ = 1 << (PData->depth); } /* 0 */ while (i >= 0) { low_vect[U] = Intervals_Low[INDEX_U][i]; hi_vect[U] = Intervals_Hi[INDEX_U][i]; Len = hi_vect[U] - low_vect[U]; split = INDEX_U; low_vect[V] = Intervals_Low[INDEX_V][i]; hi_vect[V] = Intervals_Hi[INDEX_V][i]; temp = hi_vect[V] - low_vect[V]; if (temp > Len) { Len = temp; split = INDEX_V; } parX = parY = 0; TLen = 0; /* X */ if (SectorNum[i] < MaxPrecompX) { low = PData->Low[0][SectorNum[i]]; hi = PData->Hi[0][SectorNum[i]]; } else Evaluate_Function_Interval_UV(Thread->functionContext, *(Function[0]), accuracy, low_vect, hi_vect, max_gradient, low, hi); /* fabs(D[X] *(T2-T1)) is not OK with new method */ if (close(D[0], 0)) { parX = 1; if ((hi < P[0]) || (low > P[0])) { i--; continue; } } else { XRayMin = (hi - P[0]) / D[0]; XRayMax = (low - P[0]) / D[0]; if (XRayMin > XRayMax) { temp = XRayMin; XRayMin = XRayMax; XRayMax = temp; } if ((XRayMin > Depth2) || (XRayMax < Depth1)) { i--; continue; } if ((TPotRes = XRayMin) > TResult) { i--; continue; } TLen = XRayMax - XRayMin; } /* Y */ if (SectorNum[i] < MaxPrecompY) { low = PData->Low[1][SectorNum[i]]; hi = PData->Hi[1][SectorNum[i]]; } else Evaluate_Function_Interval_UV(Thread->functionContext, *(Function[1]), accuracy, low_vect, hi_vect, max_gradient, low, hi); if (close(D[1], 0)) { parY = 1; if ((hi < P[1]) || (low > P[1])) { i--; continue; } } else { YRayMin = (hi - P[1]) / D[1]; YRayMax = (low - P[1]) / D[1]; if (YRayMin > YRayMax) { temp = YRayMin; YRayMin = YRayMax; YRayMax = temp; } if ((YRayMin > Depth2) || (YRayMax < Depth1)) { i--; continue; } if ((TPotRes = YRayMin) > TResult) { i--; continue; } if (parX == 0) { if ((YRayMin > XRayMax) || (YRayMax < XRayMin)) { i--; continue; } } if ((temp = YRayMax - YRayMin) > TLen) TLen = temp; } /* Z */ if ((SectorNum[i] < MaxPrecompZ) && (0 < SectorNum[i])) { low = PData->Low[2][SectorNum[i]]; hi = PData->Hi[2][SectorNum[i]]; } else Evaluate_Function_Interval_UV(Thread->functionContext, *(Function[2]), accuracy, low_vect, hi_vect, max_gradient, low, hi); if (close(D[2], 0)) { if ((hi < P[2]) || (low > P[2])) { i--; continue; } } else { ZRayMin = (hi - P[2]) / D[2]; ZRayMax = (low - P[2]) / D[2]; if (ZRayMin > ZRayMax) { temp = ZRayMin; ZRayMin = ZRayMax; ZRayMax = temp; } if ((ZRayMin > Depth2) || (ZRayMax < Depth1)) { i--; continue; } if ((TPotRes = ZRayMin) > TResult) { i--; continue; } if (parX == 0) { if ((ZRayMin > XRayMax) || (ZRayMax < XRayMin)) { i--; continue; } } if (parY == 0) { if ((ZRayMin > YRayMax) || (ZRayMax < YRayMin)) { i--; continue; } } if ((temp = ZRayMax - ZRayMin) > TLen) TLen = temp; } if (Len > TLen) Len = TLen; if (Len < accuracy) { if ((TResult > TPotRes) && (TPotRes > Depth1)) { TResult = TPotRes; Assign_UV_Vect(uv, low_vect); } i--; } else { /* 1 copy */ if ((SectorNum[i] *= 2) >= Max_intNumber) SectorNum[i] = Max_intNumber; SectorNum[i + 1] = SectorNum[i]; SectorNum[i]++; i++; Intervals_Low[INDEX_U][i] = low_vect[U]; Intervals_Hi[INDEX_U][i] = hi_vect[U]; Intervals_Low[INDEX_V][i] = low_vect[V]; Intervals_Hi[INDEX_V][i] = hi_vect[V]; /* 2 split */ temp = (Intervals_Hi[split][i] + Intervals_Low[split][i]) / 2.0; Intervals_Hi[split][i] = temp; Intervals_Low[split][i - 1] = temp; } } if (TResult < Depth2) { Thread->Stats()[Ray_Parametric_Tests_Succeeded]++; VScale(IPoint, ray.Direction, TResult); VAddEq(IPoint, ray.Origin); if (Clip.empty() || Point_In_Clip(IPoint, Clip, Thread)) { /* compute_param_normal( Par, UResult, VResult , &N); push_normal_entry( TResult ,IPoint, N, (ObjectPtr ) Object, Depth_Stack); */ Depth_Stack->push(Intersection(TResult, IPoint, uv, this)); return true; } } return false; }
int All_Parametric_Intersections(OBJECT* Object, RAY* Ray, ISTACK* Depth_Stack) { PARAMETRIC * Par = (PARAMETRIC *)Object; PRECOMP_PAR_DATA * PData = ((PARAMETRIC *)Object)->PData; VECTOR P, D, IPoint; UV_VECT low_vect, hi_vect; RAY New_Ray; DBL XRayMin, XRayMax, YRayMin, YRayMax, ZRayMin, ZRayMax, TPotRes, TLen; DBL Depth1, Depth2, temp, Len, UResult, VResult, TResult = HUGE_VAL; DBL low, hi, len; int MaxPrecompX, MaxPrecompY, MaxPrecompZ; int split, i = 0, Side1, Side2; int parX, parY; int i_flg; Increase_Counter(stats[Ray_Par_Bound_Tests]); if(Par->container_shape) { if(Par->Trans != NULL) { MInvTransPoint(New_Ray.Initial, Ray->Initial, Par->Trans); MInvTransDirection(New_Ray.Direction, Ray->Direction, Par->Trans); VLength(len, New_Ray.Direction); VInverseScaleEq(New_Ray.Direction, len); i_flg = Intersect_Sphere(&New_Ray, Par->container.sphere.center, (Par->container.sphere.radius) * (Par->container.sphere.radius), &Depth1, &Depth2); Depth1 = Depth1 / len; Depth2 = Depth2 / len; } else { i_flg = Intersect_Sphere(Ray, Par->container.sphere.center, (Par->container.sphere.radius) * (Par->container.sphere.radius), &Depth1, &Depth2); } Decrease_Counter(stats[Ray_Sphere_Tests]); if(i_flg) Decrease_Counter(stats[Ray_Sphere_Tests_Succeeded]); } else { i_flg = Intersect_Box(Ray, Par->Trans, Par->container.box.corner1, Par->container.box.corner2, &Depth1, &Depth2, &Side1, &Side2); } if(!i_flg) return false; Increase_Counter(stats[Ray_Par_Bound_Tests_Succeeded]); Increase_Counter(stats[Ray_Parametric_Tests]); if (Par->Trans != NULL) { MInvTransPoint(P, Ray->Initial, Par->Trans); MInvTransDirection(D, Ray->Direction, Par->Trans); } else { P[X] = Ray->Initial[X]; P[Y] = Ray->Initial[Y]; P[Z] = Ray->Initial[Z]; D[X] = Ray->Direction[X]; D[Y] = Ray->Direction[Y]; D[Z] = Ray->Direction[Z]; } if (Depth1 == Depth2) Depth1 = 0; if ((Depth1 += 4 * Par->accuracy) > Depth2) return false; Intervals_Low[INDEX_U][0] = Par->umin; Intervals_Hi[INDEX_U][0] = Par->umax; Intervals_Low[INDEX_V][0] = Par->vmin; Intervals_Hi[INDEX_V][0] = Par->vmax; /* Fri 09-27-1996 0. */ SectorNum[0] = 1; MaxPrecompX = MaxPrecompY = MaxPrecompZ = 0; if (PData != NULL) { if (((PData->flags) & OK_X) != 0) MaxPrecompX = 1 << (PData->depth); if (((PData->flags) & OK_Y) != 0) MaxPrecompY = 1 << (PData->depth); if (((PData->flags) & OK_Z) != 0) MaxPrecompZ = 1 << (PData->depth); } /* 0 */ while (i >= 0) { low_vect[U] = Intervals_Low[INDEX_U][i]; hi_vect[U] = Intervals_Hi[INDEX_U][i]; Len = hi_vect[U] - low_vect[U]; split = INDEX_U; low_vect[V] = Intervals_Low[INDEX_V][i]; hi_vect[V] = Intervals_Hi[INDEX_V][i]; temp = hi_vect[V] - low_vect[V]; if (temp > Len) { Len = temp; split = INDEX_V; } parX = parY = 0; TLen = 0; /* X */ if (SectorNum[i] < MaxPrecompX) { low = PData->Low[0][SectorNum[i]]; hi = PData->Hi[0][SectorNum[i]]; } else Evaluate_Function_Interval_UV(*(Par->Function[0]), Par->accuracy, low_vect, hi_vect, Par->max_gradient, low, hi); /* fabs(D[X] *(T2-T1)) is not OK with new method */ if (close(D[0], 0)) { parX = 1; if ((hi < P[0]) || (low > P[0])) { i--; continue; } } else { XRayMin = (hi - P[0]) / D[0]; XRayMax = (low - P[0]) / D[0]; if (XRayMin > XRayMax) { temp = XRayMin; XRayMin = XRayMax; XRayMax = temp; } if ((XRayMin > Depth2) || (XRayMax < Depth1)) { i--; continue; } if ((TPotRes = XRayMin) > TResult) { i--; continue; } TLen = XRayMax - XRayMin; } /* Y */ if (SectorNum[i] < MaxPrecompY) { low = PData->Low[1][SectorNum[i]]; hi = PData->Hi[1][SectorNum[i]]; } else Evaluate_Function_Interval_UV(*(Par->Function[1]), Par->accuracy, low_vect, hi_vect, Par->max_gradient, low, hi); if (close(D[1], 0)) { parY = 1; if ((hi < P[1]) || (low > P[1])) { i--; continue; } } else { YRayMin = (hi - P[1]) / D[1]; YRayMax = (low - P[1]) / D[1]; if (YRayMin > YRayMax) { temp = YRayMin; YRayMin = YRayMax; YRayMax = temp; } if ((YRayMin > Depth2) || (YRayMax < Depth1)) { i--; continue; } if ((TPotRes = YRayMin) > TResult) { i--; continue; } if (parX == 0) { if ((YRayMin > XRayMax) || (YRayMax < XRayMin)) { i--; continue; } } if ((temp = YRayMax - YRayMin) > TLen) TLen = temp; } /* Z */ if ((SectorNum[i] < MaxPrecompZ) && (0 < SectorNum[i])) { low = PData->Low[2][SectorNum[i]]; hi = PData->Hi[2][SectorNum[i]]; } else Evaluate_Function_Interval_UV(*(Par->Function[2]), Par->accuracy, low_vect, hi_vect, Par->max_gradient, low, hi); if (close(D[2], 0)) { if ((hi < P[2]) || (low > P[2])) { i--; continue; } } else { ZRayMin = (hi - P[2]) / D[2]; ZRayMax = (low - P[2]) / D[2]; if (ZRayMin > ZRayMax) { temp = ZRayMin; ZRayMin = ZRayMax; ZRayMax = temp; } if ((ZRayMin > Depth2) || (ZRayMax < Depth1)) { i--; continue; } if ((TPotRes = ZRayMin) > TResult) { i--; continue; } if (parX == 0) { if ((ZRayMin > XRayMax) || (ZRayMax < XRayMin)) { i--; continue; } } if (parY == 0) { if ((ZRayMin > YRayMax) || (ZRayMax < YRayMin)) { i--; continue; } } if ((temp = ZRayMax - ZRayMin) > TLen) TLen = temp; } if (Len > TLen) Len = TLen; if (Len < Par->accuracy) { if ((TResult > TPotRes) && (TPotRes > Depth1)) { TResult = TPotRes; Par->last_u = UResult = low_vect[U]; Par->last_v = VResult = low_vect[V]; } i--; } else { /* 1 copy */ if ((SectorNum[i] *= 2) >= Max_intNumber) SectorNum[i] = Max_intNumber; SectorNum[i + 1] = SectorNum[i]; SectorNum[i]++; i++; Intervals_Low[INDEX_U][i] = low_vect[U]; Intervals_Hi[INDEX_U][i] = hi_vect[U]; Intervals_Low[INDEX_V][i] = low_vect[V]; Intervals_Hi[INDEX_V][i] = hi_vect[V]; /* 2 split */ temp = (Intervals_Hi[split][i] + Intervals_Low[split][i]) / 2.0; Intervals_Hi[split][i] = temp; Intervals_Low[split][i - 1] = temp; } } if (TResult < Depth2) { Increase_Counter(stats[Ray_Parametric_Tests_Succeeded]); VScale(IPoint, Ray->Direction, TResult); VAddEq(IPoint, Ray->Initial); if (Point_In_Clip(IPoint, Par->Clip)) { /* compute_param_normal( Par, UResult, VResult , &N); push_normal_entry( TResult ,IPoint, N, (OBJECT *) Object, Depth_Stack); */ // UV_VECT uv; // Make_UV_Vector(uv, UResult, VResult); // push_uv_entry(TResult, IPoint, uv, (OBJECT *)Object, Depth_Stack); push_entry(TResult, IPoint, (OBJECT *)Object, Depth_Stack); return true; } } return false; }
void Camera::Translate(const VECTOR Vector) { VAddEq(Location, Vector); }
static int intersect_subpatch(BICUBIC_PATCH *Shape, RAY *ray, VECTOR V1[3], DBL uu[3], DBL vv[3], DBL *Depth, VECTOR P, VECTOR N, DBL *u, DBL *v) { DBL squared_b0, squared_b1; DBL d, n, a, b, r; VECTOR Q, T1; VECTOR B[3], IB[3], NN[3]; VSub(B[0], V1[1], V1[0]); VSub(B[1], V1[2], V1[0]); VCross(B[2], B[0], B[1]); VDot(d, B[2], B[2]); squared_b0 = VSumSqr(B[0]); squared_b1 = VSumSqr(B[1]); if (d <= (BEZIER_EPSILON * squared_b1 * squared_b0)) { return (0); } d = 1.0 / sqrt(d); VScaleEq(B[2], d); /* Degenerate triangle. */ if (!MInvers3(B, IB)) { return (0); } VDot(d, ray->Direction, IB[2]); if (fabs(d) < BEZIER_EPSILON) { return (0); } VSub(Q, V1[0], ray->Initial); VDot(n, Q, IB[2]); *Depth = n / d; if (*Depth < BEZIER_TOLERANCE) { return (0); } VScale(T1, ray->Direction, *Depth); VAdd(P, ray->Initial, T1); VSub(Q, P, V1[0]); VDot(a, Q, IB[0]); VDot(b, Q, IB[1]); if ((a < 0.0) || (b < 0.0) || (a + b > 1.0)) { return (0); } r = 1.0 - a - b; Make_Vector(N, 0.0, 0.0, 0.0); bezier_value((VECTOR(*)[4][4])&Shape->Control_Points, uu[0], vv[0], T1, NN[0]); bezier_value((VECTOR(*)[4][4])&Shape->Control_Points, uu[1], vv[1], T1, NN[1]); bezier_value((VECTOR(*)[4][4])&Shape->Control_Points, uu[2], vv[2], T1, NN[2]); VScale(T1, NN[0], r); VAddEq(N, T1); VScale(T1, NN[1], a); VAddEq(N, T1); VScale(T1, NN[2], b); VAddEq(N, T1); *u = r * uu[0] + a * uu[1] + b * uu[2]; *v = r * vv[0] + a * vv[1] + b * vv[2]; VDot(d, N, N); if (d > BEZIER_EPSILON) { d = 1.0 / sqrt(d); VScaleEq(N, d); } else { Make_Vector(N, 1, 0, 0); } return (1); }