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 Warp_Normal (VECTOR TNorm, VECTOR ENorm, TPATTERN *TPat, int DontScaleBumps) { WARP *Warp=TPat->Warps; TRANS *Tr; if(!DontScaleBumps) VNormalize(TNorm,ENorm); else Assign_Vector(TNorm,ENorm); while(Warp != NULL) { switch(Warp->Warp_Type) { default: case NO_WARP: break; case TRANSFORM_WARP: Tr=(TRANS *)Warp; MInvTransNormal(TNorm, TNorm, &(Tr->Trans)); break; /* default: Error("Warp type %d not yet implemented",Warp->Warp_Type); */ } Warp=Warp->Next_Warp; } if(!DontScaleBumps) VNormalizeEq(TNorm); }
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); }
void Perturb_Normal(VECTOR Layer_Normal, const TNORMAL *Tnormal, const VECTOR EPoint, Intersection *Intersection, const Ray *ray, TraceThreadData *Thread) { VECTOR TPoint,P1; DBL value1,value2,Amount; int i; BLEND_MAP *Blend_Map; BLEND_MAP_ENTRY *Prev, *Cur; if (Tnormal==NULL) { return; } /* If normal_map present, use it and return */ if ((Blend_Map=Tnormal->Blend_Map) != NULL) { if ((Blend_Map->Type == NORMAL_TYPE) && (Tnormal->Type == UV_MAP_PATTERN)) { UV_VECT UV_Coords; Cur = &(Tnormal->Blend_Map->Blend_Map_Entries[0]); /* Don't bother warping, simply get the UV vect of the intersection */ Intersection->Object->UVCoord(UV_Coords, Intersection, Thread); TPoint[X] = UV_Coords[U]; TPoint[Y] = UV_Coords[V]; TPoint[Z] = 0; Perturb_Normal(Layer_Normal,Cur->Vals.Tnormal,TPoint,Intersection,ray,Thread); VNormalizeEq(Layer_Normal); Assign_Vector(Intersection->PNormal, Layer_Normal); /* -hdf- June 98 */ return; } else if ((Blend_Map->Type == NORMAL_TYPE) && (Tnormal->Type != AVERAGE_PATTERN)) { /* NK 19 Nov 1999 added Warp_EPoint */ Warp_EPoint (TPoint, EPoint, (TPATTERN *)Tnormal); value1 = Evaluate_TPat((TPATTERN *)Tnormal,TPoint,Intersection,ray,Thread); Search_Blend_Map (value1,Blend_Map,&Prev,&Cur); Warp_Normal(Layer_Normal,Layer_Normal, (TPATTERN *)Tnormal, Test_Flag(Tnormal,DONT_SCALE_BUMPS_FLAG)); Assign_Vector(P1,Layer_Normal); Warp_EPoint (TPoint, EPoint, (TPATTERN *)Tnormal); Perturb_Normal(Layer_Normal,Cur->Vals.Tnormal,TPoint,Intersection,ray,Thread); if (Prev != Cur) { Perturb_Normal(P1,Prev->Vals.Tnormal,TPoint,Intersection,ray,Thread); value2 = (value1-Prev->value)/(Cur->value-Prev->value); value1 = 1.0-value2; VLinComb2(Layer_Normal,value1,P1,value2,Layer_Normal); } UnWarp_Normal(Layer_Normal,Layer_Normal,(TPATTERN *)Tnormal, Test_Flag(Tnormal,DONT_SCALE_BUMPS_FLAG)); VNormalizeEq(Layer_Normal); Assign_Vector(Intersection->PNormal, Layer_Normal); /* -hdf- June 98 */ return; } } /* No normal_map. */ if (Tnormal->Type <= LAST_NORM_ONLY_PATTERN) { Warp_Normal(Layer_Normal,Layer_Normal, (TPATTERN *)Tnormal, Test_Flag(Tnormal,DONT_SCALE_BUMPS_FLAG)); Warp_EPoint (TPoint, EPoint, (TPATTERN *)Tnormal); switch (Tnormal->Type) { case BITMAP_PATTERN: bump_map (TPoint, Tnormal, Layer_Normal); break; case BUMPS_PATTERN: bumps (TPoint, Tnormal, Layer_Normal); break; case DENTS_PATTERN: dents (TPoint, Tnormal, Layer_Normal, Thread); break; case RIPPLES_PATTERN: ripples (TPoint, Tnormal, Layer_Normal, Thread); break; case WAVES_PATTERN: waves (TPoint, Tnormal, Layer_Normal, Thread); break; case WRINKLES_PATTERN: wrinkles (TPoint, Tnormal, Layer_Normal); break; case QUILTED_PATTERN: quilted (TPoint, Tnormal, Layer_Normal); break; case FACETS_PATTERN: facets (TPoint, Tnormal, Layer_Normal, Thread); break; case AVERAGE_PATTERN: Do_Average_Normals (TPoint, Tnormal, Layer_Normal, Intersection, ray, Thread); break; default: throw POV_EXCEPTION_STRING("Normal pattern not yet implemented."); } UnWarp_Normal(Layer_Normal,Layer_Normal, (TPATTERN *)Tnormal, Test_Flag(Tnormal,DONT_SCALE_BUMPS_FLAG)); } else { Warp_Normal(Layer_Normal,Layer_Normal, (TPATTERN *)Tnormal, Test_Flag(Tnormal,DONT_SCALE_BUMPS_FLAG)); Amount=Tnormal->Amount * -5.0; /*fudge factor*/ Amount*=0.02/Tnormal->Delta; /* NK delta */ /* warp the center point first - this is the last warp */ Warp_EPoint(TPoint,EPoint,(TPATTERN *)Tnormal); for(i=0; i<=3; i++) { VAddScaled(P1,TPoint,Tnormal->Delta,Pyramid_Vect[i]); /* NK delta */ value1 = Do_Slope_Map(Evaluate_TPat((TPATTERN *)Tnormal,P1,Intersection,ray,Thread),Blend_Map); VAddScaledEq(Layer_Normal,value1*Amount,Pyramid_Vect[i]); } UnWarp_Normal(Layer_Normal,Layer_Normal,(TPATTERN *)Tnormal, Test_Flag(Tnormal,DONT_SCALE_BUMPS_FLAG)); } if ( Intersection ) Assign_Vector(Intersection->PNormal, Layer_Normal); /* -hdf- June 98 */ }
void bump_map(VECTOR EPoint, TNORMAL *Tnormal, VECTOR normal) { DBL xcoor = 0.0, ycoor = 0.0; int index, index2, index3; COLOUR colour1, colour2, colour3; VECTOR p1, p2, p3; VECTOR bump_normal; VECTOR xprime, yprime, zprime, Temp; DBL Length; DBL Amount = Tnormal->Amount; IMAGE *Image = Tnormal->Vals.Image; Make_ColourA(colour1, 0.0, 0.0, 0.0, 0.0, 0.0); Make_ColourA(colour2, 0.0, 0.0, 0.0, 0.0, 0.0); Make_ColourA(colour3, 0.0, 0.0, 0.0, 0.0, 0.0); /* going to have to change this */ /* need to know if bump point is off of image for all 3 points */ if (map(EPoint, (TPATTERN *) Tnormal, &xcoor, &ycoor)) { return; } else { image_colour_at(Image, xcoor, ycoor, colour1, &index); } xcoor--; ycoor++; if (xcoor < 0.0) { xcoor += (DBL)Image->iwidth; } else { if (xcoor >= Image->iwidth) { xcoor -= (DBL)Image->iwidth; } } if (ycoor < 0.0) { ycoor += (DBL)Image->iheight; } else { if (ycoor >= (DBL)Image->iheight) { ycoor -= (DBL)Image->iheight; } } image_colour_at(Image, xcoor, ycoor, colour2, &index2); xcoor += 2.0; if (xcoor < 0.0) { xcoor += (DBL)Image->iwidth; } else { if (xcoor >= Image->iwidth) { xcoor -= (DBL)Image->iwidth; } } image_colour_at(Image, xcoor, ycoor, colour3, &index3); if (Image->Colour_Map == NULL || Image->Use_Colour_Flag) { p1[X] = 0; p1[Y] = Amount * (GREY_SCALE( colour1 )); p1[Z] = 0; p2[X] = -1; p2[Y] = Amount * (GREY_SCALE( colour2 )); p2[Z] = 1; p3[X] = 1; p3[Y] = Amount * (GREY_SCALE( colour3 )); p3[Z] = 1; } else { p1[X] = 0; p1[Y] = Amount * index; p1[Z] = 0; p2[X] = -1; p2[Y] = Amount * index2; p2[Z] = 1; p3[X] = 1; p3[Y] = Amount * index3; p3[Z] = 1; } /* we have points 1,2,3 for a triangle now we need the surface normal for it */ VSub(xprime, p1, p2); VSub(yprime, p3, p2); VCross(bump_normal, yprime, xprime); VNormalize(bump_normal, bump_normal); Assign_Vector(yprime, normal); Make_Vector(Temp, 0.0, 1.0, 0.0); VCross(xprime, yprime, Temp); VLength(Length, xprime); if (Length < EPSILON) { if (fabs(normal[Y] - 1.0) < Small_Tolerance) { Make_Vector(yprime, 0.0, 1.0, 0.0); Make_Vector(xprime, 1.0, 0.0, 0.0); Length = 1.0; } else { Make_Vector(yprime, 0.0, -1.0, 0.0); Make_Vector(xprime, 1.0, 0.0, 0.0); Length = 1.0; } } VScaleEq(xprime, 1.0 / Length); VCross(zprime, xprime, yprime); VNormalizeEq(zprime); VScaleEq(xprime, bump_normal[X]); VScaleEq(yprime, bump_normal[Y]); VScaleEq(zprime, bump_normal[Z]); VAdd(Temp, xprime, yprime); VScaleEq(zprime, -1); VAdd(normal, Temp, zprime); }
void Compute_Polygon(POLYGON *Polyg, int Number, VECTOR *Points) { int i; DBL x, y, z, d; VECTOR o, u, v, w, N; MATRIX a, b; /* Create polygon data. */ if (Polyg->Data == NULL) { Polyg->Data = (POLYGON_DATA *)POV_MALLOC(sizeof(POLYGON_DATA), "polygon points"); Polyg->Data->References = 1; Polyg->Data->Number = Number; Polyg->Data->Points = (UV_VECT *)POV_MALLOC(Number*sizeof(UV_VECT), "polygon points"); } else { Error("Polygon data already computed."); } /* Get polygon's coordinate system (one of the many possible) */ Assign_Vector(o, Points[0]); /* Find valid, i.e. non-zero u vector. */ for (i = 1; i < Number; i++) { VSub(u, Points[i], o); if (VSumSqr(u) > EPSILON) { break; } } if (i == Number) { Set_Flag(Polyg, DEGENERATE_FLAG); Warning(0, "Points in polygon are co-linear. Ignoring polygon."); } /* Find valid, i.e. non-zero v and w vectors. */ for (i++; i < Number; i++) { VSub(v, Points[i], o); VCross(w, u, v); if ((VSumSqr(v) > EPSILON) && (VSumSqr(w) > EPSILON)) { break; } } if (i == Number) { Set_Flag(Polyg, DEGENERATE_FLAG); Warning(0, "Points in polygon are co-linear. Ignoring polygon."); } VCross(u, v, w); VCross(v, w, u); VNormalize(u, u); VNormalize(v, v); VNormalize(w, w); 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(Polyg->Trans->inverse, a, b); MInvers(Polyg->Trans->matrix, Polyg->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(Polyg, DEGENERATE_FLAG); Warning(0, "Points in polygon are not co-planar. Ignoring polygons."); } Polyg->Data->Points[i][X] = x * u[X] + y * u[Y] + z * u[Z]; Polyg->Data->Points[i][Y] = x * v[X] + y * v[Y] + z * v[Z]; } Make_Vector(N, 0.0, 0.0, 1.0); MTransNormal(Polyg->S_Normal, N, Polyg->Trans); VNormalizeEq(Polyg->S_Normal); Compute_Polygon_BBox(Polyg); }