DINO and POVray Tutorial

DINO & POVray

Patch: Detail

DINO Homepage

General
- Introduction
- Exporting from DINO
- File contents
- Rendering the scene
Scene Settings
- Camera
- Light Sources
- Background
- Depth Effect
Material Settings
- Overview
- Finish modifiers
- Normal modifiers
- Finish + Normal
- Transparency
- Predefined Textures
Patch
- Overview
- Detail

last updated 14 Sep 2016
dino-biozentrum@unibas.ch

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