Patched POV-ray Version: smooth_color_triangle
Step 1: added color capabilities to mesh object (mesh.h),
added another object type COLOR_MESH_OBJECT (objects.h)
to identify mesh.
Step 2: added token (tokenize.c) and object SMOOTH_COLOR_TRIANGLE
to mesh (mesh.c) and parsing (parse.[c,h])
Step 3: implement a catch-point during rendering, This was done in lighting.c
in the routine Determine_Apparent_Colour: <
void Determine_Apparent_Colour(INTERSECTION *Ray_Intersection, COLOUR Colour, RAY *Ray, DBL Weight)
{
int i, Texture_Count;
size_t savelights_size, save_tw_size;
DBL *save_Weights = NULL;
DBL Normal_Direction;
COLOUR C1;
VECTOR Raw_Normal;
VECTOR IPoint;
TEXTURE *Texture, **save_Textures = NULL;
TEXTURE Temp_Texture; /* AP */
LIGHT_TESTED *savelights = NULL;
- - - some lines omitted - - -
Texture_Count = create_texture_list (Ray_Intersection);
/*
* Now, we perform the lighting calculations by stepping through
* the list of textures and summing the weighted color.
*/
for (i = 0; i < Texture_Count; i++)
{
/* If contribution of this texture is neglectable skip ahead. */
if (Weight_List[i] < BLACK_LEVEL)
{
continue;
}
Texture = Texture_List[i];
/* AP */
if (Ray_Intersection->Object->Type & COLOR_MESH_OBJECT) {
/*
Mesh_Interpolate will only return TRUE - and hence override
the current texture - if the triangle is a colored triangle
*/
if(Mesh_Interpolate(C1,IPoint,
(MESH *)Ray_Intersection->Object,
(MESH_TRIANGLE *)Ray_Intersection->Pointer)==TRUE) {
/*
save a copy of the current texture - in case it is shared among
objects - then force the texture to type plain and the
interpolated color
*/
memcpy(&Temp_Texture,Texture,sizeof(TEXTURE));
Texture=&Temp_Texture;
Texture->Pigment->Type=PLAIN_PATTERN;
Texture->Pigment->Colour[0]=C1[0];
Texture->Pigment->Colour[1]=C1[1];
Texture->Pigment->Colour[2]=C1[2];
Texture->Pigment->Colour[3]=C1[3];
Texture->Pigment->Colour[4]=C1[4];
}
}
do_texture_map(C1, Texture, IPoint, Raw_Normal, Ray, Weight, Ray_Intersection, FALSE);
Colour[RED] += Weight_List[i] * C1[RED];
Colour[GREEN] += Weight_List[i] * C1[GREEN];
Colour[BLUE] += Weight_List[i] * C1[BLUE];
During texture parsing, if the current object is a COLOR_MESH_OBJECT,
branch to Mesh_Interpolate to calculate the interpolated color
at position IPoint, using the intersected mesh triangle. If interpolation
is successful, force the current texture pigment to this color.
Following is the interpolation function, implemented in mesh.c
and triangle.c:
/* AP */
/*
Interpolate the three vertice colors of mesh-triangle tri to a single color
at position IPoint. If mesh-triangle is not a smooth_color_triange, ignore
interpolation and return FALSE
*/
int Mesh_Interpolate(COLOUR Col, VECTOR IPoint, MESH *m, MESH_TRIANGLE *tri)
{
VECTOR P1,P2,P3;
COLOUR NCol;
if(tri->Color) {
if(tri->C1==-1 ||
tri->C2==-1 ||
tri->C3==-1)
return FALSE;
P1[0]=m->Data->Vertices[tri->P1][0];
P1[1]=m->Data->Vertices[tri->P1][1];
P1[2]=m->Data->Vertices[tri->P1][2];
P2[0]=m->Data->Vertices[tri->P2][0];
P2[1]=m->Data->Vertices[tri->P2][1];
P2[2]=m->Data->Vertices[tri->P2][2];
P3[0]=m->Data->Vertices[tri->P3][0];
P3[1]=m->Data->Vertices[tri->P3][1];
P3[2]=m->Data->Vertices[tri->P3][2];
Interpolate_Smooth_Color(NCol, IPoint,
P1,P2,P3,
m->Data->Colors[tri->C1],
m->Data->Colors[tri->C2],
m->Data->Colors[tri->C3]);
Col[0]=NCol[0];
Col[1]=NCol[1];
Col[2]=NCol[2];
Col[3]=NCol[3];
Col[4]=NCol[4];
return TRUE;
} else {
return FALSE;
}
}
int Interpolate_Smooth_Color(COLOUR Col, VECTOR IPoint, VECTOR P1, VECTOR P2, VECTOR P3, COLOUR C1, COLOUR C2, COLOUR C3)
{
int i;
DBL t1,t2,t3,tsum;
COLOUR CInt;
t1=Calculate_Smooth_T(IPoint, P1, P2, P3);
t2=Calculate_Smooth_T(IPoint, P2, P3, P1);
t3=Calculate_Smooth_T(IPoint, P3, P1, P2);
tsum=(1.0-t1)+(1.0-t2)+(1.0-t3);
for(i=0;i<5;i++)
Col[i]=((1.0-t1)*C1[i]+(1.0-t2)*C2[i]+(1.0-t3)*C3[i])/tsum;
return TRUE;
}
DBL Calculate_Smooth_T(VECTOR IPoint, VECTOR P1, VECTOR P2, VECTOR P3)
{
DBL a,b,c,d,e,f,g,h,i;
DBL dm1,dm2,dm3,r,s,t;
VECTOR Q;
a=IPoint[0]-P1[0];
b=P2[0]-P3[0];
c=P2[0]-P1[0];
d=IPoint[1]-P1[1];
e=P2[1]-P3[1];
f=P2[1]-P1[1];
g=IPoint[2]-P1[2];
h=P2[2]-P3[2];
i=P2[2]-P1[2];
dm1=a*e-d*b;
dm2=a*h-g*b;
dm3=d*h-g*e;
if(dm1*dm1 < EPSILON) {
if(dm2*dm2 < EPSILON) {
if(dm3*dm3 < EPSILON) {
fprintf(stderr,"all determinants too small\n");
return FALSE;
} else {
/* use dm3 */
r=(f*h-i*e)/dm3;
s=(d*i-g*f)/dm3;
}
} else {
/* use dm2 */
r=(c*h-b*i)/dm2;
s=(a*i-g*c)/dm2;
}
} else {
/* use dm1 */
r=(c*e-f*b)/dm1;
s=(a*f-d*c)/dm1;
}
Q[0]=P2[0]+s*(P3[0]-P2[0]);
Q[1]=P2[1]+s*(P3[1]-P2[1]);
Q[2]=P2[2]+s*(P3[2]-P2[2]);
/*
t=(M-A)/(Q-A)
*/
a=Q[0]-P1[0];
b=Q[1]-P1[1];
c=Q[2]-P1[2];
if(a*a < EPSILON) {
if(b*b < EPSILON) {
if(c*c < EPSILON) {
t=0;
} else {
t=(IPoint[2]-P1[2])/c;
}
} else {
t=(IPoint[1]-P1[1])/b;
}
} else {
t=(IPoint[0]-P1[0])/a;
}
return t;
}
(c) 2001-2005 Ansgar Philippsen
|