BEGIN_POV_NAMESPACE /***************************************************************************** * Local preprocessor defines ******************************************************************************/ /***************************************************************************** * Local typedefs ******************************************************************************/ /***************************************************************************** * Local variables ******************************************************************************/ /***************************************************************************** * Static functions ******************************************************************************/ /***************************************************************************** * * FUNCTION * * INPUT * * OUTPUT * * RETURNS * * AUTHOR * * POV-Ray Team * * DESCRIPTION * * - * * CHANGES * * - * ******************************************************************************/ COLOUR *Create_Colour () { COLOUR *New; New = (COLOUR *)POV_MALLOC(sizeof (COLOUR), "color"); Make_ColourA (*New, 0.0, 0.0, 0.0, 0.0, 0.0); return (New); }
COLOUR *Create_Colour () { COLOUR *New; New = reinterpret_cast<COLOUR *>(POV_MALLOC(sizeof (COLOUR), "color")); Make_ColourA (*New, 0.0, 0.0, 0.0, 0.0, 0.0); return (New); }
DBL image_pattern(VECTOR EPoint, TPATTERN *TPattern) { DBL xcoor = 0.0, ycoor = 0.0; int index; COLOUR colour; IMAGE *Image = TPattern->Vals.Image; DBL Value; Make_ColourA(colour, 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 *) TPattern, &xcoor, &ycoor)) { return 0.0; } else { image_colour_at(Image, xcoor, ycoor, colour, &index); } if (Image->Colour_Map == NULL || Image->Use_Colour_Flag) { if (Image->Use_Colour_Flag == USE_ALPHA) { /* use alpha channel or red channel */ if ((Image->Image_Type & IS16BITIMAGE) == IS16BITIMAGE) { if (Image->data.rgb16_lines[0].transm != NULL) Value = colour[pTRANSM]; else Value = colour[pRED]; /* otherwise, just use the red channel */ } else { if (Image->data.rgb8_lines[0].transm != NULL) Value = colour[pTRANSM]; else Value = colour[pRED]; /* otherwise, just use the red channel */ } } else /* use grey-scaled version of the color */ Value = GREY_SCALE(colour); } else Value = index / 255.0; if (Value<0) Value = 0; else if (Value>1.0) Value = 1.0; return Value; }
TEXTURE *material_map(VECTOR EPoint, TEXTURE *Texture) { int reg_number = 0; int Material_Number; int numtex; DBL xcoor = 0.0, ycoor = 0.0; COLOUR colour; TEXTURE *Temp_Tex; /* * Now we have transformed x, y, z we use image mapping routine to determine * texture index. */ if (map(EPoint, ((TPATTERN *) Texture), &xcoor, &ycoor)) { Material_Number = 0; } else { Make_ColourA(colour, 0.0, 0.0, 0.0, 0.0, 0.0); image_colour_at(Texture->Vals.Image, xcoor, ycoor, colour, ®_number); if (Texture->Vals.Image->Colour_Map == NULL) { Material_Number = (int)(colour[pRED] * 255.0); } else { Material_Number = reg_number; } } if (Material_Number > Texture->Num_Of_Mats) { Material_Number %= Texture->Num_Of_Mats; } for (numtex = 0, Temp_Tex = Texture->Materials; (Temp_Tex->Next_Material != NULL) && (numtex < Material_Number); Temp_Tex = Temp_Tex->Next_Material, numtex++) { /* do nothing */ } return (Temp_Tex); }
int image_map(VECTOR EPoint, PIGMENT *Pigment, COLOUR colour) { int reg_number; DBL xcoor = 0.0, ycoor = 0.0; /* If outside map coverage area, return clear */ if (map(EPoint, ((TPATTERN *) Pigment), &xcoor, &ycoor)) { Make_ColourA(colour, 1.0, 1.0, 1.0, 0.0, 1.0); return(false); } else { image_colour_at(Pigment->Vals.Image, xcoor, ycoor, colour, ®_number); } return(true); }
FOG *Create_Fog() { FOG *New; New = (FOG *)POV_MALLOC(sizeof(FOG), "fog"); New->Type = ORIG_FOG; New->Distance = 0.0; New->Alt = 0.0; New->Offset = 0.0; Make_ColourA(New->Colour, 0.0, 0.0, 0.0, 0.0, 0.0); Make_Vector(New->Up, 0.0, 1.0, 0.0); New->Turb = NULL; New->Turb_Depth = 0.5; New->Next = NULL; return (New); }
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); }
static void Interp(IMAGE *Image, DBL xcoor, DBL ycoor, COLOUR colour, int *index) { int iycoor, ixcoor, i; int Corners_Index[4]; DBL Index_Crn[4]; COLOUR Corner_Colour[4]; DBL Red_Crn[4]; DBL Green_Crn[4]; DBL Blue_Crn[4]; DBL Filter_Crn[4]; DBL Transm_Crn[4]; DBL val1, val2, val3, val4, val5; val1 = val2 = val3 = val4 = val5 = 0.0; iycoor = (int)ycoor; ixcoor = (int)xcoor; for (i = 0; i < 4; i++) { Make_ColourA(Corner_Colour[i], 0.0, 0.0, 0.0, 0.0, 0.0); } /* OK, now that you have the corners, what are you going to do with them? */ if (Image->Interpolation_Type == BILINEAR) { no_interpolation(Image, (DBL)ixcoor + 1, (DBL)iycoor, Corner_Colour[0], &Corners_Index[0]); no_interpolation(Image, (DBL)ixcoor, (DBL)iycoor, Corner_Colour[1], &Corners_Index[1]); no_interpolation(Image, (DBL)ixcoor + 1, (DBL)iycoor - 1, Corner_Colour[2], &Corners_Index[2]); no_interpolation(Image, (DBL)ixcoor, (DBL)iycoor - 1, Corner_Colour[3], &Corners_Index[3]); for (i = 0; i < 4; i++) { Red_Crn[i] = Corner_Colour[i][pRED]; Green_Crn[i] = Corner_Colour[i][pGREEN]; Blue_Crn[i] = Corner_Colour[i][pBLUE]; Filter_Crn[i] = Corner_Colour[i][pFILTER]; Transm_Crn[i] = Corner_Colour[i][pTRANSM]; // Debug_Info("Crn %d = %lf %lf %lf\n",i,Red_Crn[i],Blue_Crn[i],Green_Crn[i]); } val1 = bilinear(Red_Crn, xcoor, ycoor); val2 = bilinear(Green_Crn, xcoor, ycoor); val3 = bilinear(Blue_Crn, xcoor, ycoor); val4 = bilinear(Filter_Crn, xcoor, ycoor); val5 = bilinear(Transm_Crn, xcoor, ycoor); } if (Image->Interpolation_Type == NORMALIZED_DIST) { no_interpolation(Image, (DBL)ixcoor, (DBL)iycoor - 1, Corner_Colour[0], &Corners_Index[0]); no_interpolation(Image, (DBL)ixcoor + 1, (DBL)iycoor - 1, Corner_Colour[1], &Corners_Index[1]); no_interpolation(Image, (DBL)ixcoor, (DBL)iycoor, Corner_Colour[2], &Corners_Index[2]); no_interpolation(Image, (DBL)ixcoor + 1, (DBL)iycoor, Corner_Colour[3], &Corners_Index[3]); for (i = 0; i < 4; i++) { Red_Crn[i] = Corner_Colour[i][pRED]; Green_Crn[i] = Corner_Colour[i][pGREEN]; Blue_Crn[i] = Corner_Colour[i][pBLUE]; Filter_Crn[i] = Corner_Colour[i][pFILTER]; Transm_Crn[i] = Corner_Colour[i][pTRANSM]; // Debug_Info("Crn %d = %lf %lf %lf\n",i,Red_Crn[i],Blue_Crn[i],Green_Crn[i]); } val1 = norm_dist(Red_Crn, xcoor, ycoor); val2 = norm_dist(Green_Crn, xcoor, ycoor); val3 = norm_dist(Blue_Crn, xcoor, ycoor); val4 = norm_dist(Filter_Crn, xcoor, ycoor); val5 = norm_dist(Transm_Crn, xcoor, ycoor); } colour[pRED] += val1; colour[pGREEN] += val2; colour[pBLUE] += val3; colour[pFILTER] += val4; colour[pTRANSM] += val5; // Debug_Info("Final = %lf %lf %lf\n",val1,val2,val3); // use bilinear for index try average later for (i = 0; i < 4; i++) { Index_Crn[i] = (DBL)Corners_Index[i]; } if (Image->Interpolation_Type == BILINEAR) { *index = (int)(bilinear(Index_Crn, xcoor, ycoor) + 0.5); } if (Image->Interpolation_Type == NORMALIZED_DIST) { *index = (int)(norm_dist(Index_Crn, xcoor, ycoor) + 0.5); } }
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]; } }
static void do_fog(RAY *Ray, INTERSECTION *Intersection, COLOUR Colour, int Light_Ray_Flag) { DBL att, att_inv, width; COLOUR Col_Fog; COLOUR sum_att; /* total attenuation. */ COLOUR sum_col; /* total color. */ FOG *Fog; /* Why are we here. */ if (Frame.Fog == NULL) { return; } /* Init total attenuation and total color. */ Make_ColourA(sum_att, 1.0, 1.0, 1.0, 1.0, 1.0); Make_ColourA(sum_col, 0.0, 0.0, 0.0, 0.0, 0.0); /* Loop over all fogs. */ for (Fog = Frame.Fog; Fog != NULL; Fog = Fog->Next) { /* Don't care about fogs with zero distance. */ if (fabs(Fog->Distance) > EPSILON) { width = Intersection->Depth; switch (Fog->Type) { case GROUND_MIST: att = ground_fog(Ray, 0.0, width, Fog, Col_Fog); break; default: att = constant_fog(Ray, 0.0, width, Fog, Col_Fog); break; } /* Check for minimum transmittance. */ if (att < Col_Fog[pTRANSM]) { att = Col_Fog[pTRANSM]; } /* Get attenuation sum due to filtered/unfiltered translucency. */ sum_att[pRED] *= att * ((1.0 - Col_Fog[pFILTER]) + Col_Fog[pFILTER] * Col_Fog[pRED]); sum_att[pGREEN] *= att * ((1.0 - Col_Fog[pFILTER]) + Col_Fog[pFILTER] * Col_Fog[pGREEN]); sum_att[pBLUE] *= att * ((1.0 - Col_Fog[pFILTER]) + Col_Fog[pFILTER] * Col_Fog[pBLUE]); sum_att[pFILTER] *= att * Col_Fog[pFILTER]; sum_att[pTRANSM] *= att * Col_Fog[pTRANSM]; if (!Light_Ray_Flag) { att_inv = 1.0 - att; CRGBAddScaledEq(sum_col, att_inv, Col_Fog); } } } /* Add light coming from background. */ Colour[pRED] = sum_col[pRED] + sum_att[pRED] * Colour[pRED]; Colour[pGREEN] = sum_col[pGREEN] + sum_att[pGREEN] * Colour[pGREEN]; Colour[pBLUE] = sum_col[pBLUE] + sum_att[pBLUE] * Colour[pBLUE]; Colour[pTRANSM] *= GREY_SCALE(sum_att); }