void NormalBlendMap::ComputeAverage (const Vector3d& EPoint, Vector3d& normal, Intersection *Inter, const Ray *ray, TraceThreadData *Thread) { SNGL Value; SNGL Total = 0.0; Vector3d V1,V2; POV_BLEND_MAP_ASSERT(Type == kBlendMapType_Normal); V1 = Vector3d(0.0, 0.0, 0.0); for(Vector::const_iterator i = Blend_Map_Entries.begin(); i != Blend_Map_Entries.end(); i++) { Value = i->value; V2 = normal; Perturb_Normal(V2,i->Vals,EPoint,Inter,ray,Thread); V1 += (DBL)Value * V2; Total += Value; } normal = V1 / Total; }
static void Do_Average_Normals (const VECTOR EPoint, const TNORMAL *Tnormal, VECTOR normal, Intersection *Inter, const Ray *ray, TraceThreadData *Thread) { int i; BLEND_MAP *Map = Tnormal->Blend_Map; SNGL Value; SNGL Total = 0.0; VECTOR V1,V2; Make_Vector (V1, 0.0, 0.0, 0.0); for (i = 0; i < Map->Number_Of_Entries; i++) { Value = Map->Blend_Map_Entries[i].value; Assign_Vector(V2,normal); Perturb_Normal(V2,Map->Blend_Map_Entries[i].Vals.Tnormal,EPoint,Inter,ray,Thread); VAddScaledEq(V1,Value,V2); Total += Value; } VInverseScale(normal,V1,Total); }
void Perturb_Normal(Vector3d& Layer_Normal, const TNORMAL *Tnormal, const Vector3d& EPoint, Intersection *Intersection, const Ray *ray, TraceThreadData *Thread) { Vector3d TPoint,P1; DBL value1,Amount; int i; shared_ptr<NormalBlendMap> Blend_Map; if (Tnormal==NULL) { return; } /* If normal_map present, use it and return */ Blend_Map = std::tr1::dynamic_pointer_cast<NormalBlendMap>(Tnormal->Blend_Map); if (Blend_Map != NULL) { if (Tnormal->Type == UV_MAP_PATTERN) { Vector2d UV_Coords; /* 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,Blend_Map->Blend_Map_Entries[0].Vals,TPoint,Intersection,ray,Thread); Layer_Normal.normalize(); Intersection->PNormal = Layer_Normal; /* -hdf- June 98 */ return; } else if (Tnormal->Type != AVERAGE_PATTERN) { const NormalBlendMapEntry *Prev, *Cur; DBL prevWeight, curWeight; /* NK 19 Nov 1999 added Warp_EPoint */ Warp_EPoint (TPoint, EPoint, Tnormal); value1 = Evaluate_TPat(Tnormal, TPoint, Intersection, ray, Thread); Blend_Map->Search (value1,Prev,Cur,prevWeight,curWeight); Warp_Normal(Layer_Normal,Layer_Normal, Tnormal, Test_Flag(Tnormal,DONT_SCALE_BUMPS_FLAG)); P1 = Layer_Normal; Warp_EPoint (TPoint, EPoint, Tnormal); Perturb_Normal(Layer_Normal,Cur->Vals,TPoint,Intersection,ray,Thread); if (Prev != Cur) { Perturb_Normal(P1,Prev->Vals,TPoint,Intersection,ray,Thread); Layer_Normal = prevWeight * P1 + curWeight * Layer_Normal; } UnWarp_Normal(Layer_Normal,Layer_Normal, Tnormal, Test_Flag(Tnormal,DONT_SCALE_BUMPS_FLAG)); Layer_Normal.normalize(); Intersection->PNormal = Layer_Normal; /* -hdf- June 98 */ return; } // TODO - what if Tnormal->Type == AVERAGE_PATTERN? } /* No normal_map. */ if (Tnormal->Type <= LAST_NORM_ONLY_PATTERN) { Warp_Normal(Layer_Normal,Layer_Normal, Tnormal, Test_Flag(Tnormal,DONT_SCALE_BUMPS_FLAG)); Warp_EPoint (TPoint, EPoint, 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, Tnormal, Test_Flag(Tnormal,DONT_SCALE_BUMPS_FLAG)); } else { shared_ptr<SlopeBlendMap> slopeMap = std::tr1::dynamic_pointer_cast<SlopeBlendMap>(Tnormal->Blend_Map); Warp_Normal(Layer_Normal,Layer_Normal, Tnormal, Test_Flag(Tnormal,DONT_SCALE_BUMPS_FLAG)); // TODO FIXME - two magic fudge factors 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,Tnormal); for(i=0; i<=3; i++) { P1 = TPoint + (DBL)Tnormal->Delta * Pyramid_Vect[i]; /* NK delta */ value1 = Do_Slope_Map(Evaluate_TPat(Tnormal, P1, Intersection, ray, Thread), slopeMap.get()); Layer_Normal += (value1*Amount) * Pyramid_Vect[i]; } UnWarp_Normal(Layer_Normal,Layer_Normal,Tnormal, Test_Flag(Tnormal,DONT_SCALE_BUMPS_FLAG)); } if ( Intersection ) Intersection->PNormal = Layer_Normal; /* -hdf- June 98 */ }
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 */ }