/// draw a cone
void RenderManDisplayDevice::cone(float *a, float *b, float r) {
  float axis[3], vec1[3], vec2[3];
  float R, phi, rxy, theta;
  float radius;

  // Transform the world coordinates
  (transMat.top()).multpoint3d(a, vec1);
  (transMat.top()).multpoint3d(b, vec2);
  radius = scale_radius(r);
  if (radius < DEFAULT_RADIUS) {
    radius = (float) DEFAULT_RADIUS;
  }

  // RenderMan's cylinders always run along the z axis, and must
  // be transformed to the proper position and rotation. This
  // code is taken from OpenGLRenderer.C.
  axis[0] = vec2[0] - vec1[0];
  axis[1] = vec2[1] - vec1[1];
  axis[2] = vec2[2] - vec1[2];

  R = axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2];
  if (R <= 0) return;

  R = sqrtf(R); // evaluation of sqrt() _after_ early exit

  // determine phi rotation angle, amount to rotate about y
  phi = acosf(axis[2] / R);

  // determine theta rotation, amount to rotate about z
  rxy = sqrtf(axis[0] * axis[0] + axis[1] * axis[1]);
  if (rxy <= 0) {
    theta = 0;
  } else {
    theta = acosf(axis[0] / rxy);
    if (axis[1] < 0) theta = (float) (2.0 * VMD_PI) - theta;
  }

  // Write the cone
  fprintf(outfile, "TransformBegin\n");
  write_materials(1);
  fprintf(outfile, "  Translate %g %g %g\n", vec1[0], vec1[1], vec1[2]);
  if (theta) 
    fprintf(outfile, "  Rotate %g 0 0 1\n", (theta / VMD_PI) * 180);
  if (phi) 
    fprintf(outfile, "  Rotate %g 0 1 0\n", (phi / VMD_PI) * 180);
  fprintf(outfile, "  Cone %g %g 360\n", R, radius);
  fprintf(outfile, "TransformEnd\n");
}
Esempio n. 2
0
/// draw a sphere
void GelatoDisplayDevice::sphere(float * spdata) {
  float vec[3];
  float radius;

  // Transform the world coordinates
  (transMat.top()).multpoint3d(spdata, vec);
  radius = scale_radius(spdata[3]);
  if (radius < DEFAULT_RADIUS) {
    radius = (float) DEFAULT_RADIUS;
  }

  // Draw the sphere
  fprintf(outfile, "PushTransform()\n");
  write_materials(1);
  fprintf(outfile, "Translate(%g, %g, %g)\n", vec[0], vec[1], vec[2]);
  fprintf(outfile, "Sphere(%g, %g, %g, 360)\n", radius, -radius, radius);
  fprintf(outfile, "PopTransform()\n");
}
/// draw a sphere
void RenderManDisplayDevice::sphere(float * spdata) {
  float vec[3];
  float radius;

  // Transform the world coordinates
  (transMat.top()).multpoint3d(spdata, vec);
  radius = scale_radius(spdata[3]);
  if (radius < DEFAULT_RADIUS) {
    radius = (float) DEFAULT_RADIUS;
  }

  // Draw the sphere
  fprintf(outfile, "TransformBegin\n");
  write_materials(1);
  fprintf(outfile, "  Translate %g %g %g\n", vec[0], vec[1], vec[2]);
  fprintf(outfile, "  Sphere %g %g %g 360\n", radius, -radius, radius);
  fprintf(outfile, "TransformEnd\n");
}
Esempio n. 4
0
void GelatoDisplayDevice::trimesh_c4n3v3(int numverts, float * cnv,
                                         int numfacets, int * facets) {
  float vec1[3];
  float norm1[3];
  int i;

  write_materials(0);
  fprintf(outfile, "Mesh(\"linear\", (");
 
  for (i=0; i<numfacets; i++) {
    fprintf(outfile, "3,");
  }
  fprintf(outfile, "), (");

  for (i=0; i<numfacets; i++) {
    fprintf(outfile, "%d, %d, %d,", facets[i*3], facets[i*3+1], facets[i*3+2]);
  }
  fprintf(outfile, "), ");

  fprintf(outfile, "\n\"vertex point P\", (");
  for (i=0; i<numverts; i++) {
    (transMat.top()).multpoint3d(cnv + i*10 + 7, vec1);
    fprintf(outfile, "%g, %g, %g,", vec1[0], vec1[1], vec1[2]);
  }
  fprintf(outfile, "), ");
  
  fprintf(outfile,  "\n\"vertex normal N\", (");
  for (i=0; i<numverts; i++) {
    (transMat.top()).multnorm3d(cnv + i*10 + 4, norm1);
    fprintf(outfile, "%g, %g, %g,", norm1[0], norm1[1], norm1[2]);
  }
  fprintf(outfile, "), ");

  fprintf(outfile,  "\n\"vertex color C\", (");
  for (i=0; i<numverts; i++) {
    float *c = cnv + i*10;
    fprintf(outfile, "%g, %g, %g,", c[0], c[1], c[2]);
  }
  fprintf(outfile, "))\n");
}
// draw a triangle
void RenderManDisplayDevice::triangle(const float *a, const float *b, const float *c, const float *n1, const float *n2, const float *n3) {
  float vec1[3], vec2[3], vec3[3];
  float norm1[3], norm2[3], norm3[3];

  // Transform the world coordinates
  (transMat.top()).multpoint3d(a, vec1);
  (transMat.top()).multpoint3d(b, vec2);
  (transMat.top()).multpoint3d(c, vec3);
  (transMat.top()).multnorm3d(n1, norm1);
  (transMat.top()).multnorm3d(n2, norm2);
  (transMat.top()).multnorm3d(n3, norm3);

  // Write the triangle
  write_materials(1);
  fprintf(outfile, "Polygon \"P\" [ %g %g %g %g %g %g %g %g %g ] ",
          vec1[0], vec1[1], vec1[2],
          vec2[0], vec2[1], vec2[2],
          vec3[0], vec3[1], vec3[2]);
  fprintf(outfile, "\"N\" [ %g %g %g %g %g %g %g %g %g ]\n",
          norm1[0], norm1[1], norm1[2],
          norm2[0], norm2[1], norm2[2],
          norm3[0], norm3[1], norm3[2]);
}
Esempio n. 6
0
// draw a triangle
void GelatoDisplayDevice::triangle(const float *a, const float *b, const float *c, const float *n1, const float *n2, const float *n3) {
  float vec1[3], vec2[3], vec3[3];
  float norm1[3], norm2[3], norm3[3];

  // Transform the world coordinates
  (transMat.top()).multpoint3d(a, vec1);
  (transMat.top()).multpoint3d(b, vec2);
  (transMat.top()).multpoint3d(c, vec3);
  (transMat.top()).multnorm3d(n1, norm1);
  (transMat.top()).multnorm3d(n2, norm2);
  (transMat.top()).multnorm3d(n3, norm3);

  // Write the triangle
  write_materials(1);
  fprintf(outfile, "Mesh(\"linear\", (3,), (0, 1, 2), "
          "\"vertex point P\", (%g, %g, %g, %g, %g, %g, %g, %g, %g), "
          "\"vertex normal N\", (%g, %g, %g, %g, %g, %g, %g, %g, %g))\n",
          vec1[0], vec1[1], vec1[2],
          vec2[0], vec2[1], vec2[2],
          vec3[0], vec3[1], vec3[2],
          norm1[0], norm1[1], norm1[2],
          norm2[0], norm2[1], norm2[2],
          norm3[0], norm3[1], norm3[2]);
}
// draw a square
void RenderManDisplayDevice::square(float *n, float *a, float *b, float *c, float *d) {
  float vec1[3], vec2[3], vec3[3], vec4[3];
  float norm[3];

  // Transform the world coordinates
  (transMat.top()).multpoint3d(a, vec1);
  (transMat.top()).multpoint3d(b, vec2);
  (transMat.top()).multpoint3d(c, vec3);
  (transMat.top()).multpoint3d(d, vec4);
  (transMat.top()).multnorm3d(n, norm);

  // Write the square
  write_materials(1);
  fprintf(outfile, "Polygon \"P\" [ %g %g %g %g %g %g %g %g %g %g %g %g ] ",
          vec1[0], vec1[1], vec1[2],
          vec2[0], vec2[1], vec2[2],
          vec3[0], vec3[1], vec3[2],
          vec4[0], vec4[1], vec4[2]);
  fprintf(outfile, "\"N\" [ %g %g %g %g %g %g %g %g %g %g %g %g ]\n",
          norm[0], norm[1], norm[2],
          norm[0], norm[1], norm[2],
          norm[0], norm[1], norm[2],
          norm[0], norm[1], norm[2]);
}
Esempio n. 8
0
/// draw a NURBS cylinder, no transform, must be in world coords already
void GelatoDisplayDevice::cylinder_nurb_noxfrm(float *vec1, float *vec2, 
                                               float radius, int filled) {
  float axis[3];
  float R, phi, rxy, theta;

  // safety check to prevent overly-tiny cylinders
  if (radius < DEFAULT_RADIUS) {
    radius = (float) DEFAULT_RADIUS;
  }

  // Gelato's cylinders always run along the z axis, and must
  // be transformed to the proper position and rotation. This
  // code is taken from OpenGLRenderer.C.
  axis[0] = vec2[0] - vec1[0];
  axis[1] = vec2[1] - vec1[1];
  axis[2] = vec2[2] - vec1[2];

  R = axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2];
  if (R <= 0) return;

  R = sqrtf(R); // evaluation of sqrt() _after_ early exit

  // determine phi rotation angle, amount to rotate about y
  phi = acosf(axis[2] / R);

  // determine theta rotation, amount to rotate about z
  rxy = sqrtf(axis[0] * axis[0] + axis[1] * axis[1]);
  if (rxy <= 0) {
    theta = 0;
  } else {
    theta = acosf(axis[0] / rxy);
    if (axis[1] < 0) theta = (float) (2.0 * VMD_PI) - theta;
  }

  // Write the cylinder, reorienting and translating it to the correct location
  fprintf(outfile, "PushTransform()\n");
  write_materials(1);
  fprintf(outfile, "Translate(%g,%g,%g)\n", vec1[0], vec1[1], vec1[2]);
  if (theta) 
    fprintf(outfile, "Rotate(%g,0,0,1)\n", (theta / VMD_PI) * 180);
  if (phi) 
    fprintf(outfile, "Rotate(%g,0,1,0)\n", (phi / VMD_PI) * 180);

  // Calculate the NURBS parameters for Cylinder(radius, 0, R, 360) 
  // on the Z axis.  This is mostly hard-coded for speed.
  int A, i;
  float zmin = 0.0;
  float zmax = R;
  float circcv[9*4];
  float uknotv[9+4]; 
  float vknotv[4] = {0.0f,0.0f,1.0f,1.0f};
  float controlv[9*2*4];

  fullcirclearc(radius, uknotv, circcv); // generate full circle arc
  memcpy(controlv, circcv, 9*4*sizeof(float));
  A=0;
  for(i=0; i<9; i++) {
    controlv[A+2] = zmin * controlv[A+3];
    A+=4;
  }
  A=9*4;
  memcpy(&(controlv[A]), circcv, 9*4*sizeof(float));
  for(i = 0; i < 9; i++) {
    controlv[A+2] = zmax * controlv[A+3];
    A += 4;
  }

  // draw the NURBS Cylinder using the Gelato Patch primitive
  fprintf(outfile, "Patch(%d,3,(", 9);
  for (i=0; i<9+3; i++) {
    fprintf(outfile, "%g,", uknotv[i]);
  }
  fprintf(outfile, "),0,1,2,2,(");
  for (i=0; i<4; i++) {
    fprintf(outfile, "%g,", vknotv[i]);
  }
  fprintf(outfile, "),0,1,\"vertex hpoint Pw\", (");
  for (i=0; i<9*2*4; i++) {
    fprintf(outfile, "%g,", controlv[i]);
  }
  fprintf(outfile, "))\n");

  fprintf(outfile, "PopTransform()\n");
}
Esempio n. 9
0
void GelatoDisplayDevice::text(float *pos, float size, float thickness,
                               const char *str) {
  float textpos[3];
  float textsize, textthickness;
  hersheyhandle hh;

  // transform the world coordinates
  (transMat.top()).multpoint3d(pos, textpos);
  textsize = size * 1.5f;
  textthickness = thickness*DEFAULT_RADIUS;

  while (*str != '\0') {
    float lm, rm, x, y, ox, oy;
    int draw, odraw;
    ox=oy=x=y=0.0f;
    draw=odraw=0;

    hersheyDrawInitLetter(&hh, *str, &lm, &rm);
    textpos[0] -= lm * textsize;

    while (!hersheyDrawNextLine(&hh, &draw, &x, &y)) {
      float oldpt[3], newpt[3];
      if (draw) {
        newpt[0] = textpos[0] + textsize * x;
        newpt[1] = textpos[1] + textsize * y;
        newpt[2] = textpos[2];

        if (odraw) {
          // if we have both previous and next points, connect them...
          oldpt[0] = textpos[0] + textsize * ox;
          oldpt[1] = textpos[1] + textsize * oy;
          oldpt[2] = textpos[2];

          cylinder_nurb_noxfrm(oldpt, newpt, textthickness, 0); 

          fprintf(outfile, "PushTransform()\n");
          write_materials(1);
          fprintf(outfile, "Translate(%g, %g, %g)\n", 
                  newpt[0], newpt[1], newpt[2]);
          fprintf(outfile, "Sphere(%g, %g, %g, 360)\n", 
                  textthickness, -textthickness, textthickness);
          fprintf(outfile, "PopTransform()\n");
        } else {
          // ...otherwise, just draw the next point
          fprintf(outfile, "PushTransform()\n");
          write_materials(1);
          fprintf(outfile, "Translate(%g, %g, %g)\n", 
                  newpt[0], newpt[1], newpt[2]);
          fprintf(outfile, "Sphere(%g, %g, %g, 360)\n", 
                  textthickness, -textthickness, textthickness);
          fprintf(outfile, "PopTransform()\n");
        }
      }

      ox=x;
      oy=y;
      odraw=draw;
    }
    textpos[0] += rm * textsize;

    str++;
  }
}
Esempio n. 10
0
void POV3DisplayDevice::start_clipgroup(void) {
  int i, num_clipplanes[3], mode;
  float pov_clip_center[3], pov_clip_distance[VMD_MAX_CLIP_PLANE];
  float pov_clip_normal[VMD_MAX_CLIP_PLANE][3];

  write_materials();

  memset(num_clipplanes, 0, 3*sizeof(int));
  for (i = 0; i < VMD_MAX_CLIP_PLANE; i++) {
    if (clip_mode[i] != 0) {
      // Count the number of clipping planes for each clip mode
      num_clipplanes[clip_mode[i]]++;

      // Translate the plane center
      (transMat.top()).multpoint3d(clip_center[i], pov_clip_center);

      // and the normal
      (transMat.top()).multnorm3d(clip_normal[i], pov_clip_normal[i]);
      vec_negate(pov_clip_normal[i], pov_clip_normal[i]);

      // POV-Ray uses the distance from the origin to the plane for its
      // representation, instead of the plane center
      pov_clip_distance[i] = dot_prod(pov_clip_normal[i], pov_clip_center);
    }
  }

  // Define the clip object for each clip mode
  for (mode = 1; mode < 3; mode++) {
    if (num_clipplanes[mode] > 0) {
      // This flag is used within VMD to determine if clipping information
      // should be written to the scene file
      clip_on[mode] = 1;

      // This flag is used within POV to determine if clipping should be done
      // within macros
      fprintf(outfile, "#declare VMD_clip_on[%d]=1;\n", mode);

      if (num_clipplanes[mode] == 1) {
        for (i = 0; i < VMD_MAX_CLIP_PLANE; i++) {
          if (clip_mode[i] == mode) {
            if (mode == 2) {
              // Textured plane for CSG clipping
              fprintf(outfile, "#declare VMD_clip[%d] = plane { <%.4f, %.4f, %.4f>, %.4f texture { pigment { rgbt<%.3f, %.3f, %.3f, %.3f> } } }\n",
                      mode, pov_clip_normal[i][0], pov_clip_normal[i][1], 
                      -pov_clip_normal[i][2], pov_clip_distance[i],
                      clip_color[i][0], clip_color[i][1], clip_color[i][2],
                      1 - mat_opacity);
            } else {
              // Non-textured plane for non-CSG clipping
              fprintf(outfile, "#declare VMD_clip[%d] = plane { <%.4f, %.4f, %.4f>, %.4f }\n",
                      mode, pov_clip_normal[i][0], pov_clip_normal[i][1], 
                      -pov_clip_normal[i][2], pov_clip_distance[i]);

#if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND)
              // Non-textured plane for non-CSG clipping, but scaled for use
              // when emitting meshes with the scaling hack.
              fprintf(outfile, "#declare VMD_scaledclip[%d] = plane { <%.4f, %.4f, %.4f>, %.4f }\n",
                      mode, pov_clip_normal[i][0], pov_clip_normal[i][1], -pov_clip_normal[i][2], 
                      pov_clip_distance[i] * POVRAY_SCALEHACK);
#endif
            }
          }
        }
      }

      // Declare the clipping object to be an intersection of planes
      else {
        fprintf(outfile, "#declare VMD_clip[%d] = intersection {\n", mode);
        for (i = 0; i < VMD_MAX_CLIP_PLANE; i++) {
          if (clip_mode[i] == mode) {
            if (mode == 2) {
              // Textured plane for CSG clipping
              fprintf(outfile, "  plane { <%.4f, %.4f, %.4f>, %.4f texture { pigment { rgbt<%.3f, %.3f, %.3f, %.3f> } } }\n",
                      pov_clip_normal[i][0], pov_clip_normal[i][1], 
                      -pov_clip_normal[i][2], pov_clip_distance[i],
                      clip_color[i][0], clip_color[i][1], clip_color[i][2],
                      1 - mat_opacity);
            } else {
              // Non-textured plane for non-CSG clipping
              fprintf(outfile, "  plane { <%.4f, %.4f, %.4f>, %.4f }\n",
                    pov_clip_normal[i][0], pov_clip_normal[i][1], 
                    -pov_clip_normal[i][2], pov_clip_distance[i]);
            }
          }
        }
        fprintf(outfile, "}\n");

#if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND)
        fprintf(outfile, "#declare VMD_scaledclip[%d] = intersection {\n", mode);
        for (i = 0; i < VMD_MAX_CLIP_PLANE; i++) {
          if (clip_mode[i] == mode) {
            if (mode == 2) {
              // Textured plane for CSG clipping
              fprintf(outfile, "  plane { <%.4f, %.4f, %.4f>, %.4f texture { pigment { rgbt<%.3f, %.3f, %.3f, %.3f> } } }\n",
                      pov_clip_normal[i][0], pov_clip_normal[i][1], 
                      -pov_clip_normal[i][2], pov_clip_distance[i] * POVRAY_SCALEHACK,
                      clip_color[i][0], clip_color[i][1], clip_color[i][2],
                      1 - mat_opacity);
            } else {
              // Non-textured plane for non-CSG clipping
              fprintf(outfile, "  plane { <%.4f, %.4f, %.4f>, %.4f }\n",
                    pov_clip_normal[i][0], pov_clip_normal[i][1], 
                    -pov_clip_normal[i][2], pov_clip_distance[i] * POVRAY_SCALEHACK);
            }
          }
        }
        fprintf(outfile, "}\n");
#endif


      }

    }
  }
}