next up previous contents index
Next: Resource file .graperc Up: Graphic Devices Previous: Methods on GraphicDevice

An Example Low-Level Display Method

 

TRIANG2D *triang2d_example_disp (void)
/* this method is not optimized in any way. */
{
  TRIANG2D *self;
  GRAPHICDEVICE *grdev;
  MANAGER *mgr;
  static int own_colors = 0;
  static CHECKBOX *checkbox = NULL;
  
  self = (TRIANG2D *) START_METHOD (G_INSTANCE);
  ASSURE (self, "", END_METHOD (NULL));

  mgr = (MANAGER *) GRAPE (Manager, "get-stdmgr")();
  ASSURE (mgr, "triang2d_example_disp: can't get manager",
          END_METHOD (NULL));


  /* we have a switch: "own_colors".
   * to let the user choose a value we use a Checkbox.
   */
  if (!checkbox) {
    /* no checkbox yet: create it */
    checkbox = (CHECKBOX *) GRAPE (Checkbox, "new-instance")
      ("example: colors", &own_colors);
    GRAPE (checkbox, "set-pref-size")(6.0, 1.0);
  }

  /* insert the checkbox into menu "opt 0" if not already there.
   * it will be removed when this method is not used any more
   */
  if (GRAPE (mgr, "new-handle")(triang2d_example_disp, 1)) {
    GRAPE (mgr, "add-inter")(checkbox);
  }



  /* get standard graphic device.
   * create error message when fail.
   */
  grdev = (GRAPHICDEVICE *) GRAPE (GraphicDevice, "get-stddev")();
  ASSURE (grdev, "triang2d_example_disp: can't get GraphicDevice",
          END_METHOD (NULL));



  if (grdev->grid_patch == G_GRID) {
    /* Device is switched to grid mode. We MUST NOT draw patches
     * here (it may work on your device, but not on others, e.g.
     * X11, PostScript ...; to have patch-only and mixed modes
     * alternatively you have to use patch mode and extra
     * selfmade switches).
     */
    if (!own_colors) {
      /* normally use the preset line color */
      int i, j;
      VEC3 point[3];
      for (i = 0; i < self->number_of_elements; i++) {
        for (j = 0; j < 3; j++) {
          point[j][0] = self->x[self->vertex[i][j]];
          point[j][1] = self->y[self->vertex[i][j]];
          point[j][2] = self->z[self->vertex[i][j]];
        }
        grdev->move (point[0]);
        for (j = 0; j < 3; j++)
          grdev->draw (point[2 - j]);
      }
    }
    
    else {
      /* special: we use our own line color: Red */
      int i, j;
      VEC3 point[3], linecolor;
      static VEC3 Red = { 1.0, 0.0, 0.0};

      /* preserve the previously set line color */
      grdev->attribute (G_MODE_GET, G_LINE_COLOR, linecolor);
      grdev->attribute (G_MODE_SET, G_LINE_COLOR, Red);
      for (i = 0; i < self->number_of_elements; i++) {
        for (j = 0; j < 3; j++) {
          point[j][0] = self->x[self->vertex[i][j]];
          point[j][1] = self->y[self->vertex[i][j]];
          point[j][2] = self->z[self->vertex[i][j]];
        }
        grdev->move (point[0]);
        for (j = 0; j < 3; j++)
          grdev->draw (point[2 - j]);
      }
      /* set the previously set line color */
      grdev->attribute (G_MODE_SET, G_LINE_COLOR, linecolor);
    }

  }



  else /* (grdev->grid_patch == G_PATCH) */ {
    /* Device is switched to patch mode. We can draw patches or
     * grids and mix it.
     */

    /* In this example we always use patches here. Normally we
     * want them to be colored automatically with respect to
     * the lightsources.
     * here another type of display is shown as well: selfmade colors
     */
    if (!own_colors) {
      int i, j;
      VEC3 point, normal;
      
      /* we use the lightsources */

      for (i = 0; i < self->number_of_elements; i++) {
        grdev->begin_patch();
        for (j = 0; j < 3; j++) {
          point[0] = self->x[self->vertex[i][j]];
          point[1] = self->y[self->vertex[i][j]];
          point[2] = self->z[self->vertex[i][j]];
          
          /* calculate the patch normal in this vertex from your data
             normal = my_normal (self->vertex[i][j]);
             
             the default display method takes the average normal of the
             triangles using this vertex
             
             we take a very stupid formula here */
          normal[0] = g_sin (point[2]);
          normal[1] = g_cos (point[2]);
          normal[2] = point[2];
          g_vec3_normalize (normal);
          
          grdev->patch_normal (normal);
          grdev->patch_vertex (point);
        }
        grdev->end_patch();
      }
    }
    
    
    else {
      int i, j;
      int light_model, off = 0;
      VEC3 point, color;
      
      /* we use selfmade colors. switch off the light-model, but
       * save previous state to restore afterwards
       */
      grdev->attribute (G_MODE_GET, G_LIGHT_MODEL, &light_model);
      grdev->attribute (G_MODE_SET, G_LIGHT_MODEL, &off);

      for (i = 0; i < self->number_of_elements; i++) {
        grdev->begin_patch();
        for (j = 0; j < 3; j++) {
          point[0] = self->x[self->vertex[i][j]];
          point[1] = self->y[self->vertex[i][j]];
          point[2] = self->z[self->vertex[i][j]];
          
          /* calculate the color for this vertex from your data
             color = my_color (self->vertex[i][j]);
             
             we take a very stupid formula here */
          color[0] = g_sin (10. * point[2]);
          color[1] = g_cos (10. * point[1]);
          color[2] = g_sin (10. * point[0]);
          
          grdev->patch_color (color);
          grdev->patch_vertex (point);
        }
        grdev->end_patch();
      }
      grdev->attribute (G_MODE_SET, G_LIGHT_MODEL, &light_model);
    }

  }

  END_METHOD (self);
}



SFB 256 Universität Bonn and IAM Universität Freiburg

Copyright © by the Sonderforschungsbereich 256 at the Institut für Angewandte Mathematik, Universität Bonn.