static void Do_Average_Pigments (COLOUR Colour, PIGMENT *Pigment, VECTOR EPoint, INTERSECTION *Intersect) { int i; COLOUR LC; BLEND_MAP *Map = Pigment->Blend_Map; SNGL Value; SNGL Total = 0.0; Make_Colour (Colour, 0.0, 0.0, 0.0); for (i = 0; i < Map->Number_Of_Entries; i++) { Value = Map->Blend_Map_Entries[i].value; Compute_Pigment (LC,Map->Blend_Map_Entries[i].Vals.Pigment,EPoint,Intersect); Colour[pRED] += LC[pRED] *Value; Colour[pGREEN] += LC[pGREEN] *Value; Colour[pBLUE] += LC[pBLUE] *Value; Colour[pFILTER]+= LC[pFILTER]*Value; Colour[pTRANSM]+= LC[pTRANSM]*Value; Total += Value; } Colour[pRED] /= Total; Colour[pGREEN] /= Total; Colour[pBLUE] /= Total; Colour[pFILTER]/= Total; Colour[pTRANSM]/= Total; }
bool PigmentBlendMap::Compute(TransColour& colour, DBL value, const Vector3d& TPoint, const Intersection *Intersect, const Ray *ray, TraceThreadData *Thread) { const BlendMapEntry<PIGMENT*>* Prev; const BlendMapEntry<PIGMENT*>* Cur; DBL prevWeight; DBL curWeight; bool found = false; Search (value, Prev, Cur, prevWeight, curWeight); if (Compute_Pigment(colour, Cur->Vals, TPoint, Intersect, ray, Thread)) found = true; if (Prev != Cur) { TransColour Temp_Colour; if (Compute_Pigment(Temp_Colour, Prev->Vals, TPoint, Intersect, ray, Thread)) found = true; Blend(colour, Temp_Colour, prevWeight, colour, curWeight, Thread); } return found; }
bool PigmentBlendMap::ComputeUVMapped(TransColour& colour, const Intersection *Intersect, const Ray *ray, TraceThreadData *Thread) { Vector2d UV_Coords; Vector3d TPoint; const BlendMapEntry<PIGMENT*>* Cur = &(Blend_Map_Entries[0]); /* Don't bother warping, simply get the UV vect of the intersection */ Intersect->Object->UVCoord(UV_Coords, Intersect, Thread); TPoint[X] = UV_Coords[U]; TPoint[Y] = UV_Coords[V]; TPoint[Z] = 0; return Compute_Pigment(colour, Cur->Vals, TPoint, Intersect, ray, Thread); }
void PigmentBlendMap::ComputeAverage(TransColour& colour, const Vector3d& EPoint, const Intersection *Intersect, const Ray *ray, TraceThreadData *Thread) { SNGL Total = 0.0; TransColour tempColour; colour.Clear(); for(vector<PigmentBlendMapEntry>::const_iterator i = Blend_Map_Entries.begin(); i != Blend_Map_Entries.end(); i++) { Compute_Pigment (tempColour, i->Vals, EPoint, Intersect, ray, Thread); colour += i->value * tempColour; Total += i->value; } colour /= Total; }
void Evaluate_Density_Pigment(vector<PIGMENT*>& Density, const Vector3d& p, MathColour& c, TraceThreadData *ttd) { TransColour lc; c.Set(1.0); // TODO - Reverse iterator may be less performant than forward iterator; we might want to // compare performance with using forward iterators and decrement, or using random access. // Alternatively, reversing the vector after parsing might be another option. for (vector<PIGMENT*>::reverse_iterator i = Density.rbegin(); i != Density.rend(); ++ i) { lc.Clear(); Compute_Pigment(lc, *i, p, NULL, NULL, ttd); c *= lc.colour(); } }
void Evaluate_Density_Pigment(const PIGMENT *pigm, const Vector3d& p, RGBColour& c, TraceThreadData *ttd) { Colour lc; c.set(1.0); while(pigm != NULL) { lc.clear(); Compute_Pigment(lc, pigm, *p, NULL, NULL, ttd); c.red() *= lc.red(); c.green() *= lc.green(); c.blue() *= lc.blue(); pigm = reinterpret_cast<const PIGMENT *>(pigm->Next); } }
static void Do_Average_Pigments (Colour& colour, const PIGMENT *Pigment, const VECTOR EPoint, const Intersection *Intersect, const Ray *ray, TraceThreadData *Thread) { int i; Colour LC; BLEND_MAP *Map = Pigment->Blend_Map; SNGL Value; SNGL Total = 0.0; colour.clear(); for (i = 0; i < Map->Number_Of_Entries; i++) { Value = Map->Blend_Map_Entries[i].value; Compute_Pigment (LC, Map->Blend_Map_Entries[i].Vals.Pigment, EPoint, Intersect, ray, Thread); colour += LC * Value; Total += Value; } colour /= Total; }
bool Compute_Pigment (Colour& colour, const PIGMENT *Pigment, const VECTOR EPoint, const Intersection *Intersect, const Ray *ray, TraceThreadData *Thread) { int Colour_Found; VECTOR TPoint; DBL value; register DBL fraction; const BLEND_MAP_ENTRY *Cur, *Prev; Colour Temp_Colour; const BLEND_MAP *Blend_Map = Pigment->Blend_Map; UV_VECT UV_Coords; if ((Thread->qualityFlags & Q_QUICKC) != 0 && Pigment->Quick_Colour[pRED] != -1.0 && Pigment->Quick_Colour[pGREEN] != -1.0 && Pigment->Quick_Colour[pBLUE] != -1.0) { colour = Pigment->Quick_Colour; return (true); } if (Pigment->Type <= LAST_SPECIAL_PATTERN) { Colour_Found = true; switch (Pigment->Type) { case NO_PATTERN: colour.clear(); break; case PLAIN_PATTERN: colour = Pigment->colour; break; case AVERAGE_PATTERN: Warp_EPoint (TPoint, EPoint, reinterpret_cast<const TPATTERN *>(Pigment)); Do_Average_Pigments(colour, Pigment, TPoint, Intersect, ray, Thread); break; case UV_MAP_PATTERN: if(Intersect == NULL) throw POV_EXCEPTION_STRING("The 'uv_mapping' pattern cannot be used as part of a pigment function!"); Cur = &(Pigment->Blend_Map->Blend_Map_Entries[0]); if (Blend_Map->Type == COLOUR_TYPE) { Colour_Found = true; Assign_Colour(*colour, Cur->Vals.colour); } else { /* Don't bother warping, simply get the UV vect of the intersection */ Intersect->Object->UVCoord(UV_Coords, Intersect, Thread); TPoint[X] = UV_Coords[U]; TPoint[Y] = UV_Coords[V]; TPoint[Z] = 0; if (Compute_Pigment(colour, Cur->Vals.Pigment,TPoint,Intersect, ray, Thread)) Colour_Found = true; } break; case BITMAP_PATTERN: Warp_EPoint (TPoint, EPoint, reinterpret_cast<const TPATTERN *>(Pigment)); colour.clear(); Colour_Found = image_map (TPoint, Pigment, colour); break; default: throw POV_EXCEPTION_STRING("Pigment type not yet implemented."); } return(Colour_Found); } Colour_Found = false; /* NK 19 Nov 1999 added Warp_EPoint */ Warp_EPoint (TPoint, EPoint, reinterpret_cast<const TPATTERN *>(Pigment)); value = Evaluate_TPat (reinterpret_cast<const TPATTERN *>(Pigment),TPoint,Intersect, ray, Thread); Search_Blend_Map (value, Blend_Map, &Prev, &Cur); if (Blend_Map->Type == COLOUR_TYPE) { Colour_Found = true; Assign_Colour(*colour, Cur->Vals.colour); } else { Warp_EPoint (TPoint, EPoint, reinterpret_cast<const TPATTERN *>(Pigment)); if (Compute_Pigment(colour, Cur->Vals.Pigment,TPoint,Intersect, ray, Thread)) Colour_Found = true; } if (Prev != Cur) { if (Blend_Map->Type == COLOUR_TYPE) { Colour_Found = true; Assign_Colour(*Temp_Colour, Prev->Vals.colour); } else { if (Compute_Pigment(Temp_Colour, Prev->Vals.Pigment, TPoint, Intersect, ray, Thread)) Colour_Found = true; } fraction = (value - Prev->value) / (Cur->value - Prev->value); colour = Temp_Colour + fraction * (colour - Temp_Colour); } return(Colour_Found); }
int Compute_Pigment (COLOUR Colour, PIGMENT *Pigment, VECTOR EPoint, INTERSECTION *Intersect) { int Colour_Found; VECTOR TPoint; DBL value; register DBL fraction; BLEND_MAP_ENTRY *Cur, *Prev; COLOUR Temp_Colour; BLEND_MAP *Blend_Map = Pigment->Blend_Map; UV_VECT UV_Coords; if (Pigment->Type <= LAST_SPECIAL_PATTERN) { Colour_Found = true; switch (Pigment->Type) { case NO_PATTERN: Make_Colour(Colour, 0.0, 0.0, 0.0); break; case PLAIN_PATTERN: Assign_Colour(Colour,Pigment->Colour); break; case AVERAGE_PATTERN: Warp_EPoint (TPoint, EPoint, (TPATTERN *)Pigment); Do_Average_Pigments(Colour,Pigment,TPoint,Intersect); break; case UV_MAP_PATTERN: if(Intersect == NULL) Error("The 'uv_mapping' pattern cannot be used as part of a pigment function!"); Cur = &(Pigment->Blend_Map->Blend_Map_Entries[0]); if (Blend_Map->Type == COLOUR_TYPE) { Colour_Found = true; Assign_Colour(Colour, Cur->Vals.Colour); } else { /* Don't bother warping, simply get the UV vect of the intersection */ UVCoord(UV_Coords, Intersect->Object, Intersect); TPoint[X] = UV_Coords[U]; TPoint[Y] = UV_Coords[V]; TPoint[Z] = 0; if (Compute_Pigment(Colour, Cur->Vals.Pigment,TPoint,Intersect)) { Colour_Found = true; } } break; case BITMAP_PATTERN: Warp_EPoint (TPoint, EPoint, (TPATTERN *)Pigment); Make_Colour(Colour, 0.0, 0.0, 0.0); Colour_Found = image_map (TPoint, Pigment, Colour); break; default: Error("Pigment type %d not yet implemented",Pigment->Type); } return(Colour_Found); } Colour_Found = false; /* NK 19 Nov 1999 added Warp_EPoint */ Warp_EPoint (TPoint, EPoint, (TPATTERN *)Pigment); value = Evaluate_TPat ((TPATTERN *)Pigment,TPoint,Intersect); Search_Blend_Map (value, Blend_Map, &Prev, &Cur); if (Blend_Map->Type == COLOUR_TYPE) { Colour_Found = true; Assign_Colour(Colour, Cur->Vals.Colour); } else { Warp_EPoint (TPoint, EPoint, (TPATTERN *)Pigment); if (Compute_Pigment(Colour, Cur->Vals.Pigment,TPoint,Intersect)) { Colour_Found = true; } } if (Prev != Cur) { if (Blend_Map->Type == COLOUR_TYPE) { Colour_Found = true; Assign_Colour(Temp_Colour, Prev->Vals.Colour); } else { if (Compute_Pigment(Temp_Colour, Prev->Vals.Pigment, TPoint,Intersect)) { Colour_Found = true; } } fraction = (value - Prev->value) / (Cur->value - Prev->value); Colour[pRED] = Temp_Colour[pRED] + fraction * (Colour[pRED] - Temp_Colour[pRED]); Colour[pGREEN] = Temp_Colour[pGREEN] + fraction * (Colour[pGREEN] - Temp_Colour[pGREEN]); Colour[pBLUE] = Temp_Colour[pBLUE] + fraction * (Colour[pBLUE] - Temp_Colour[pBLUE]); Colour[pFILTER] = Temp_Colour[pFILTER] + fraction * (Colour[pFILTER] - Temp_Colour[pFILTER]); Colour[pTRANSM] = Temp_Colour[pTRANSM] + fraction * (Colour[pTRANSM] - Temp_Colour[pTRANSM]); } return(Colour_Found); }
static void do_skysphere(RAY *Ray, COLOUR Colour) { int i; DBL att, trans; COLOUR Col, Col_Temp, Filter; VECTOR P; SKYSPHERE *Skysphere; /* Why are we here. */ if (Frame.Skysphere == NULL) { return; } Make_Colour(Col, 0.0, 0.0, 0.0); if (((Skysphere = Frame.Skysphere) != NULL) && (Skysphere->Pigments != NULL)) { Make_ColourA(Filter, 1.0, 1.0, 1.0, 1.0, 1.0); trans = 1.0; /* Transform point on unit sphere. */ if (Skysphere->Trans != NULL) { MInvTransPoint(P, Ray->Direction, Skysphere->Trans); } else { Assign_Vector(P, Ray->Direction); } for (i = Skysphere->Count-1; i >= 0; i--) { /* Compute sky colour from colour map. */ /* NK 1998 - added NULL as final parameter */ Compute_Pigment(Col_Temp, Skysphere->Pigments[i], P, NULL); /* NK ---- */ att = trans * (1.0 - Col_Temp[pFILTER] - Col_Temp[pTRANSM]); CRGBAddScaledEq(Col, att, Col_Temp); Filter[pRED] *= Col_Temp[pRED]; Filter[pGREEN] *= Col_Temp[pGREEN]; Filter[pBLUE] *= Col_Temp[pBLUE]; Filter[pFILTER] *= Col_Temp[pFILTER]; Filter[pTRANSM] *= Col_Temp[pTRANSM]; trans = fabs(Filter[pFILTER]) + fabs(Filter[pTRANSM]); } Colour[pRED] = Col[pRED] + Colour[pRED] * (Filter[pRED] * Filter[pFILTER] + Filter[pTRANSM]); Colour[pGREEN] = Col[pGREEN] + Colour[pGREEN] * (Filter[pGREEN] * Filter[pFILTER] + Filter[pTRANSM]); Colour[pBLUE] = Col[pBLUE] + Colour[pBLUE] * (Filter[pBLUE] * Filter[pFILTER] + Filter[pTRANSM]); Colour[pFILTER] = Colour[pFILTER] * Filter[pFILTER]; Colour[pTRANSM] = Colour[pTRANSM] * Filter[pTRANSM]; } }
static void do_rainbow(RAY *Ray, INTERSECTION *Intersection, COLOUR Colour) { int n; DBL dot, k, ki, index, x, y, l, angle, fade, f; VECTOR Temp; COLOUR Cr, Ct; RAINBOW *Rainbow; /* Why are we here. */ if (Frame.Rainbow == NULL) { return; } Make_ColourA(Ct, 0.0, 0.0, 0.0, 1.0, 1.0); n = 0; for (Rainbow = Frame.Rainbow; Rainbow != NULL; Rainbow = Rainbow->Next) { if ((Rainbow->Pigment != NULL) && (Rainbow->Distance != 0.0) && (Rainbow->Width != 0.0)) { /* Get angle between ray direction and rainbow's up vector. */ VDot(x, Ray->Direction, Rainbow->Right_Vector); VDot(y, Ray->Direction, Rainbow->Up_Vector); l = Sqr(x) + Sqr(y); if (l > 0.0) { l = sqrt(l); y /= l; } angle = fabs(acos(y)); if (angle <= Rainbow->Arc_Angle) { /* Get dot product between ray direction and antisolar vector. */ VDot(dot, Ray->Direction, Rainbow->Antisolar_Vector); if (dot >= 0.0) { /* Get index ([0;1]) into rainbow's colour map. */ index = (acos(dot) - Rainbow->Angle) / Rainbow->Width; /* Jitter index. */ if (Rainbow->Jitter > 0.0) { index += (2.0 * FRAND() - 1.0) * Rainbow->Jitter; } if ((index >= 0.0) && (index <= 1.0 - EPSILON)) { /* Get colour from rainbow's colour map. */ Make_Vector(Temp, index, 0.0, 0.0); Compute_Pigment(Cr, Rainbow->Pigment, Temp, Intersection); /* Get fading value for falloff. */ if ((Rainbow->Falloff_Width > 0.0) && (angle > Rainbow->Falloff_Angle)) { fade = (angle - Rainbow->Falloff_Angle) / Rainbow->Falloff_Width; fade = (3.0 - 2.0 * fade) * fade * fade; } else { fade = 0.0; } /* Get attenuation factor due to distance. */ k = exp(-Intersection->Depth / Rainbow->Distance); /* Colour's transm value is used as minimum attenuation value. */ k = max(k, fade * (1.0 - Cr[pTRANSM]) + Cr[pTRANSM]); /* Now interpolate the colours. */ ki = 1.0 - k; /* Attenuate filter value. */ f = Cr[pFILTER] * ki; Ct[pRED] += k * Colour[pRED] * ((1.0 - f) + f * Cr[pRED]) + ki * Cr[pRED]; Ct[pGREEN] += k * Colour[pGREEN] * ((1.0 - f) + f * Cr[pGREEN]) + ki * Cr[pGREEN]; Ct[pBLUE] += k * Colour[pBLUE] * ((1.0 - f) + f * Cr[pBLUE]) + ki * Cr[pBLUE]; Ct[pFILTER] *= k * Cr[pFILTER]; Ct[pTRANSM] *= k * Cr[pTRANSM]; n++; } } } } } if (n > 0) { COLC tmp = 1.0 / n; Colour[pRED] = Ct[pRED] * tmp; Colour[pGREEN] = Ct[pGREEN] * tmp; Colour[pBLUE] = Ct[pBLUE] * tmp; Colour[pFILTER] *= Ct[pFILTER]; Colour[pTRANSM] *= Ct[pTRANSM]; } }