コード例 #1
0
// draw a cylinder
void RayShadeDisplayDevice::cylinder(float *a, float *b, float r,int /*filled*/) {
  float from[3], to[3];
  float radius;
  
  // transform the world coordinates
  (transMat.top()).multpoint3d(a, from);
  (transMat.top()).multpoint3d(b, to);
  radius = scale_radius(r);
    
  write_cindexmaterial(colorIndex, materialIndex);
  fprintf(outfile, "cylinder %5f %5f %5f %5f %5f %5f %5f\n",
          scale_fix(radius),
          scale_fix(from[0]), scale_fix(from[1]), scale_fix(from[2]),
          scale_fix(to[0]), scale_fix(to[1]), scale_fix(to[2])); 

  // put disks on the ends
  fprintf(outfile, "disc %5f %5f %5f %5f %5f %5f %5f\n",
	  scale_fix(radius),
	  scale_fix(from[0]), scale_fix(from[1]), scale_fix(from[2]),
	  scale_fix(from[0]-to[0]), scale_fix(from[1]-to[1]), 
	  scale_fix(from[2]-to[2]));
  fprintf(outfile, "disc %5f %5f %5f %5f %5f %5f %5f\n",
	  scale_fix(radius),
	  scale_fix(to[0]), scale_fix(to[1]), scale_fix(to[2]),
	  scale_fix(to[0]-from[0]), scale_fix(to[1]-from[1]), 
	  scale_fix(to[2]-from[2]));
}
コード例 #2
0
ファイル: POV3DisplayDevice.C プロジェクト: tmd-gpat/MOLding
// draw a cone
void POV3DisplayDevice::cone(float *a, float *b, float r, int /* resolution */) {
  float from[3], to[3];
  float radius;
  
  // transform the world coordinates
  (transMat.top()).multpoint3d(a, from);
  (transMat.top()).multpoint3d(b, to);
  radius = scale_radius(r);

  // check for degenerate cylinders
  if ( ((from[0]-to[0])*(from[0]-to[0]) +
        (from[1]-to[1])*(from[1]-to[1]) +
        (from[2]-to[2])*(from[2]-to[2])) < 1e-20 ) {
    degenerate_cones++;
    return;
  }

//  write_materials();

  // Draw the cone
  fprintf(outfile, "VMD_cone (<%g,%g,%g>,<%g,%g,%g>,%.4f,",
          from[0], from[1], -from[2], to[0], to[1], -to[2], radius);
  fprintf(outfile, "rgbt<%.3f,%.3f,%.3f,%.3f>)\n",
          matData[colorIndex][0], matData[colorIndex][1], matData[colorIndex][2],
          1 - mat_opacity);
}
コード例 #3
0
ファイル: X3DDisplayDevice.C プロジェクト: quolc/VMDLeap
// draw a cylinder
void X3DDisplayDevice::cylinder(float *a, float *b, float r, int filled) {
  float ta[3], tb[3], radius;

  // transform the coordinates
  (transMat.top()).multpoint3d(a, ta);
  (transMat.top()).multpoint3d(b, tb);
  radius = scale_radius(r);

  cylinder_noxfrm(ta, tb, radius, filled);
}
コード例 #4
0
// draw a sphere
void RayShadeDisplayDevice::sphere(float * spdata) {
  float vec[3];
  float radius;
    
  // transform the world coordinates
  (transMat.top()).multpoint3d(spdata, vec);
  radius = scale_radius(spdata[3]);
  
  write_cindexmaterial(colorIndex, materialIndex);
  // draw the sphere
  fprintf(outfile, "sphere %5f %5f %5f %5f\n", scale_fix(radius), 
          scale_fix(vec[0]), scale_fix(vec[1]), scale_fix(vec[2]));
}
コード例 #5
0
/***********************************************************************//**
 * @brief Update precomputation cache
 *
 * Computes the mass_radius calculation, determining the radius around
 * the halo that contains 99.99% of the mass. For an Burket halo profile,
 * this is just 80.0 * scale_radius.
 ***************************************************************************/
void GModelSpatialRadialProfileDMBurkert::update() const
{
    // Update if scale radius has changed
    if (m_last_scale_radius  != scale_radius() ||
        m_last_scale_density != scale_density() ) {
    
        // Store last values
        m_last_scale_radius  = scale_radius();
        m_last_scale_density = scale_density();

        // perform precomputations
        // set the mass radius to 80*scale_radius, meaning
        // 99.99% of the mass is contained within the mass radius,
        // and integration only needs to worry about whats inside this radius.
        m_mass_radius           = 80.0 * scale_radius();
        m_scale_density_squared = scale_density() * scale_density() ;

    }

    // Return
    return;
}
コード例 #6
0
// draw a sphere
void TachyonDisplayDevice::sphere(float * spdata) {
  float vec[3];
  float radius;
    
  // transform the world coordinates
  (transMat.top()).multpoint3d(spdata, vec);
  radius = scale_radius(spdata[3]);
   
  // draw the sphere
  fprintf(outfile, "Sphere \n");  // sphere
  fprintf(outfile, "  Center %g %g %g \n ", vec[0], vec[1], -vec[2]);
  fprintf(outfile, "  Rad %g \n", radius ); 
  write_cindexmaterial(colorIndex, materialIndex);
}
コード例 #7
0
/// draw a cylinder
void RenderManDisplayDevice::cylinder(float *a, float *b, float r, 
                              int /* filled */ ) {
  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 cylinder
  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, "  Cylinder %g 0 %g 360\n", radius, R);
  fprintf(outfile, "TransformEnd\n");
}
コード例 #8
0
/// draw a cylinder
void GelatoDisplayDevice::cylinder(float *a, float *b, float r, int filled) {
  float vec1[3], vec2[3], radius;
   
  if (filled) {
    FileRenderer::cylinder(a, b, r, filled);
    return;
  }

  // Transform the world coordinates
  (transMat.top()).multpoint3d(a, vec1);
  (transMat.top()).multpoint3d(b, vec2);
  radius = scale_radius(r);

  cylinder_nurb_noxfrm(vec1, vec2, radius, filled);
}
コード例 #9
0
// draw a cylinder
void TachyonDisplayDevice::cylinder(float *a, float *b, float r, int filled) {
  float from[3], to[3], norm[3];
  float radius;
  filled = filled;  

  // transform the world coordinates
  (transMat.top()).multpoint3d(a, from);
  (transMat.top()).multpoint3d(b, to);
  radius = scale_radius(r);
   
 
  // draw the cylinder
  fprintf(outfile, "FCylinder\n"); // flat-ended cylinder
  fprintf(outfile, "  Base %g %g %g\n", from[0], from[1], -from[2]); 
  fprintf(outfile, "  Apex %g %g %g\n", to[0], to[1], -to[2]);
  fprintf(outfile, "  Rad %g\n", radius);
  write_cindexmaterial(colorIndex, materialIndex);

  // Cylinder caps?
  if (filled) {
    float div;

    norm[0] = to[0] - from[0];
    norm[1] = to[1] - from[1];
    norm[2] = to[2] - from[2];

    div = 1.0f / sqrtf(norm[0]*norm[0] + norm[1]*norm[1] + norm[2]*norm[2]);
    norm[0] *= div;
    norm[1] *= div;
    norm[2] *= div;

    if (filled & CYLINDER_TRAILINGCAP) {
      fprintf(outfile, "Ring\n");
      fprintf(outfile, "Center %g %g %g \n", from[0], from[1], -from[2]);
      fprintf(outfile, "Normal %g %g %g \n", norm[0], norm[1], -norm[2]); 
      fprintf(outfile, "Inner 0.0  Outer %g \n", radius);
      write_cindexmaterial(colorIndex, materialIndex);
    }
  
    if (filled & CYLINDER_LEADINGCAP) {
      fprintf(outfile, "Ring\n");
      fprintf(outfile, "Center %g %g %g \n", to[0], to[1], -to[2]);
      fprintf(outfile, "Normal %g %g %g \n", -norm[0], -norm[1], norm[2]); 
      fprintf(outfile, "Inner 0.0  Outer %g \n", radius);
      write_cindexmaterial(colorIndex, materialIndex);
    }
  }
}
コード例 #10
0
// draw a cone
void RayShadeDisplayDevice::cone(float *a, float *b, float r) {
  float from[3], to[3];
  float radius;
  
  // transform the world coordinates
  (transMat.top()).multpoint3d(a, from);
  (transMat.top()).multpoint3d(b, to);
  radius = scale_radius(r);
    
  write_cindexmaterial(colorIndex, materialIndex);
  fprintf(outfile, "cone %5f %5f %5f %5f %5f %5f %5f %5f\n",
          scale_fix(radius), 
          scale_fix(from[0]), scale_fix(from[1]), scale_fix(from[2]), 
          scale_fix(float(lineWidth)*DEFAULT_RADIUS), 
          scale_fix(to[0]), scale_fix(to[1]), scale_fix(to[2]));
}
コード例 #11
0
ファイル: X3DDisplayDevice.C プロジェクト: quolc/VMDLeap
// draw a sphere
void X3DDisplayDevice::sphere(float *xyzr) {
  float cent[3], radius;

  // transform the coordinates
  (transMat.top()).multpoint3d(xyzr, cent);
  radius = scale_radius(xyzr[3]);

  fprintf(outfile, "<Transform translation='%g %g %g'>\n",
          cent[0], cent[1], cent[2]);
  fprintf(outfile, "  <Shape>\n");
  fprintf(outfile, "  ");
  write_cindexmaterial(colorIndex, materialIndex);
  fprintf(outfile, "  <Sphere radius='%g'/>\n", radius);
  fprintf(outfile, "  </Shape>\n");
  fprintf(outfile, "</Transform>\n");
}
コード例 #12
0
ファイル: X3DDisplayDevice.C プロジェクト: quolc/VMDLeap
void X3DDisplayDevice::cone(float *a, float *b, float r) {
  float ta[3], tb[3], radius;

  if (a[0] == b[0] && a[1] == b[1] && a[2] == b[2]) {
    return;  // we don't serve your kind here
  }

  // transform the coordinates
  (transMat.top()).multpoint3d(a, ta);
  (transMat.top()).multpoint3d(b, tb);
  radius = scale_radius(r);

  float height = distance(a, b);

  fprintf(outfile, "<Transform translation='%g %g %g' ", 
          ta[0], ta[1] + (height / 2.0), ta[2]);

  float rotaxis[3];
  float cylaxdir[3];
  float yaxis[3] = {0.0, 1.0, 0.0};

  vec_sub(cylaxdir, tb, ta);
  vec_normalize(cylaxdir);
  float dp = dot_prod(yaxis, cylaxdir);

  cross_prod(rotaxis, cylaxdir, yaxis);
  vec_normalize(rotaxis);

  if ((rotaxis[0]*rotaxis[0] + 
      rotaxis[1]*rotaxis[1] + 
      rotaxis[2]*rotaxis[2]) > 0.5) { 
    fprintf(outfile, "center='0.0 %g 0.0' ", -(height / 2.0));
    fprintf(outfile, "rotation='%g %g %g  %g'", 
            rotaxis[0], rotaxis[1], rotaxis[2], -acos(dp));
  }
  fprintf(outfile, ">\n");  
          
  fprintf(outfile, "  <Shape>\n");
  fprintf(outfile, "  ");
  write_cindexmaterial(colorIndex, materialIndex);

  // draw the cone
  fprintf(outfile, "  <Cone bottomRadius='%g' height='%g'/>\n", radius, height);

  fprintf(outfile, "  </Shape>\n");
  fprintf(outfile, "</Transform>\n");
}
コード例 #13
0
// draw a sphere
void ArtDisplayDevice::sphere(float * spdata) {
  float vec[3];
  float radius;
    
  // transform the world coordinates
  (transMat.top()).multpoint3d(spdata, vec);
  radius = scale_radius(spdata[3]);
   
  // draw the sphere
  fprintf(outfile, "sphere {\ncolour %f,%f,%f\n",
	  matData[colorIndex][0],
	  matData[colorIndex][1],
	  matData[colorIndex][2]);

  fprintf(outfile, "radius %f\n", radius);
  fprintf(outfile, "center (%f,%f,%f)\n}\n", ORDER(vec[0], vec[1], vec[2]));
}
コード例 #14
0
ファイル: POV3DisplayDevice.C プロジェクト: tmd-gpat/MOLding
// draw a sphere
void POV3DisplayDevice::sphere(float * spdata) {
  float vec[3];
  float radius;
    
  // transform the world coordinates
  (transMat.top()).multpoint3d(spdata, vec);
  radius = scale_radius(spdata[3]);

//  write_materials();

  // Draw the sphere
  fprintf(outfile, "VMD_sphere(<%.4f,%.4f,%.4f>,%.4f,",
    vec[0], vec[1], -vec[2], radius);
  fprintf(outfile, "rgbt<%.3f,%.3f,%.3f,%.3f>)\n",
    matData[colorIndex][0], matData[colorIndex][1], matData[colorIndex][2],
    1 - mat_opacity);
}
コード例 #15
0
/// 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");
}
コード例 #16
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");
}
コード例 #17
0
// draw a sphere
void MayaDisplayDevice::sphere(float * spdata) {
  float vec[3];
  float radius;
   
  // transform the world coordinates
  (transMat.top()).multpoint3d(spdata, vec);
  radius = scale_radius(spdata[3]);
  
  // draw the sphere
  fprintf(outfile, "createNode transform -n \"vmd%d\";\n", objnameindex);
  fprintf(outfile, "  setAttr \".s\" -type \"double3\" %f %f %f;\n", radius, radius, radius);
  fprintf(outfile, "  setAttr \".t\" -type \"double3\" %f %f %f;\n", vec[0], vec[1], vec[2]);
  fprintf(outfile, "parent -s -nc -r -add \"|VMDNurbSphere|nurbsSphereShape1\" \"vmd%d\";\n", objnameindex);

  char strbuf[1024];
  sprintf(strbuf, "|vmd%d|nurbsSphereShape1", objnameindex);
  write_cindexmaterial(strbuf, colorIndex, materialIndex);

  // increment object name counter
  objnameindex++;
}
コード例 #18
0
// draw a cone
void ArtDisplayDevice::cone(float *a, float *b, float r) {

  float vec1[3], vec2[3];
  
  // transform the world coordinates
  (transMat.top()).multpoint3d(a, vec1);
  (transMat.top()).multpoint3d(b, vec2);
    
  fprintf(outfile, "cone {\n");
  fprintf(outfile, "colour %f,%f,%f\n",
	  matData[colorIndex][0],
	  matData[colorIndex][1],
	  matData[colorIndex][2]);
  // second point
  fprintf(outfile, "vertex(%f,%f,%f)\n", 
	  ORDER(vec2[0], vec2[1], vec2[2])); 
  // first point
  fprintf(outfile, "center(%f,%f,%f)\n", 
	  ORDER(vec1[0], vec1[1], vec1[2]));
  // radius
  fprintf(outfile, "radius %f\n}\n", scale_radius(r));
}
コード例 #19
0
// draw a sphere array
void TachyonDisplayDevice::sphere_array(int spnum, int spres, float *centers, float *radii, float *colors) {
  float vec[3];
  float radius;
  int i, ind;

  ind = 0;
  for (i=0; i<spnum; i++) {
    // transform the world coordinates
    (transMat.top()).multpoint3d(&centers[ind], vec);
    radius = scale_radius(radii[i]);

    // draw the sphere
    fprintf(outfile, "Sphere \n");  // sphere
    fprintf(outfile, "  Center %g %g %g \n ", vec[0], vec[1], -vec[2]);
    fprintf(outfile, "  Rad %g \n", radius );
    write_colormaterial(&colors[ind], materialIndex);
    ind += 3; // next sphere
  }

  // set final color state after array has been drawn
  ind=(spnum-1)*3;
  super_set_color(nearest_index(colors[ind], colors[ind+1], colors[ind+2]));
}
コード例 #20
0
// XXX ignores material parameter, may need to improve this..
void TachyonDisplayDevice::write_colormaterial(float *rgb, int /* material */) {
  fprintf(outfile, "Texture\n");
  if (materials_on) {
    fprintf(outfile, "  Ambient %g Diffuse %g Specular %g Opacity %g\n",
            mat_ambient, mat_diffuse, mat_mirror, mat_opacity);
  } else {
    fprintf(outfile, "  Ambient %g Diffuse %g Specular %g Opacity %g\n",
            1.0, 0.0, 0.0, mat_opacity);
  }
  
  if (mat_transmode != 0) {
    fprintf(outfile, "  TransMode R3D ");
  }
  if (mat_outline > 0.0) {
    fprintf(outfile, "  Outline %g Outline_Width %g ", 
            mat_outline, mat_outlinewidth);
  }
  fprintf(outfile, "  Phong Plastic %g Phong_size %g ", mat_specular, 
          mat_shininess);
  fprintf(outfile, "Color %g %g %g ", rgb[0], rgb[1], rgb[2]);

  /// generate volume texture definition, if necessary
  if (!involtex) {
    /// no volume texture, so we use a solid color
    fprintf(outfile, "TexFunc 0\n\n");
  } else {
    /// Perform coordinate system transformations and emit volume texture
    float voluaxs[3];           ///< volume texture coordinate generation
    float volvaxs[3];           ///< parameters in world coordinates
    float volwaxs[3];
    float volcent[3];

    // transform the y/v/w texture coordinate axes from molecule
    // coordinates into world coordinates
    (transMat.top()).multplaneeq3d(xplaneeq, voluaxs);
    (transMat.top()).multplaneeq3d(yplaneeq, volvaxs);
    (transMat.top()).multplaneeq3d(zplaneeq, volwaxs);

    // undo the scaling operation applied by the transformation
    float invscale = 1.0f / scale_radius(1.0f); 
    int i;
    for (i=0; i<3; i++) {
      voluaxs[i] *= invscale;
      volvaxs[i] *= invscale;
      volwaxs[i] *= invscale;
    }

    // compute the volume origin in molecule coordinates by 
    // reverting the scaling factor that was previously applied
    // to the texture plane equation
    float volorgmol[3] = {0,0,0};
    volorgmol[0] = -xplaneeq[3] / norm(xplaneeq);
    volorgmol[1] = -yplaneeq[3] / norm(yplaneeq);
    volorgmol[2] = -zplaneeq[3] / norm(zplaneeq);

    // transform the volume origin into world coordinates
    (transMat.top()).multpoint3d(volorgmol, volcent);

    // emit the texture to the scene file
    fprintf(outfile, "\n  TexFunc  10  ::VMDVolTex%d\n", voltexID);
    fprintf(outfile, "  Center %g %g %g\n", volcent[0], volcent[1], -volcent[2]);
    fprintf(outfile, "  Rotate 0 0 0\n");
    fprintf(outfile, "  Scale  1 1 1\n");
    fprintf(outfile, "  Uaxis %g %g %g\n", voluaxs[0], voluaxs[1], -voluaxs[2]);
    fprintf(outfile, "  Vaxis %g %g %g\n", volvaxs[0], volvaxs[1], -volvaxs[2]);
    fprintf(outfile, "  Waxis %g %g %g\n", volwaxs[0], volwaxs[1], -volwaxs[2]);
    fprintf(outfile, "\n");
  }
}
コード例 #21
0
ファイル: PSDisplayDevice.C プロジェクト: quolc/VMDLeap
void PSDisplayDevice::render(const VMDDisplayList *display_list) {
   DepthSortObject depth_obj;
   char *cmd_ptr;
   int draw;
   int tok;
   int nc;
   float a[3], b[3], c[3], d[3];
   float cent[3];
   float r;
   Matrix4 ident;
   float textsize=1.0f; // default text size

   // first we want to clear the transformation matrix stack
   while (transMat.num())
      transMat.pop();

   // push on the identity matrix
   transMat.push(ident);

   // load the display list's transformation matrix
   super_multmatrix(display_list->mat.mat);

   // Now we need to calculate the normalized position of the light
   // so we can compute angles of surfaces to that light for shading
   norm_light[0] = lightState[0].pos[0];
   norm_light[1] = lightState[0].pos[1];
   norm_light[2] = lightState[0].pos[2];
   if (norm_light[0] || norm_light[1] || norm_light[2])
      vec_normalize(norm_light);

   // Computer periodic images
   ResizeArray<Matrix4> pbcImages;
   find_pbc_images(display_list, pbcImages);
   int nimages = pbcImages.num();

   for (int pbcimage = 0; pbcimage < nimages; pbcimage++) {
     transMat.dup();
     super_multmatrix(pbcImages[pbcimage].mat);

   // Loop through the display list and add each object to our
   // depth-sort list for final rendering.
   VMDDisplayList::VMDLinkIter cmditer;
   display_list->first(&cmditer);
   while ((tok = display_list->next(&cmditer, cmd_ptr)) != DLASTCOMMAND) {
      draw = 0;
      nc = -1;

      switch (tok) {
         case DPOINT:
            // allocate memory
            depth_obj.points = (float *) malloc(sizeof(float) * 2);
            if (!depth_obj.points) {
               // memory error
               if (!memerror) {
                  memerror = 1;
                  msgErr << "PSDisplayDevice: Out of memory. Some " <<
                     "objects were not drawn." << sendmsg;
               }
               break;
            }

            // copy data
            depth_obj.npoints = 1;
            depth_obj.color = colorIndex;
            (transMat.top()).multpoint3d(((DispCmdPoint *) cmd_ptr)->pos, a);
            memcpy(depth_obj.points, a, sizeof(float) * 2);

            // compute the distance to the eye
            depth_obj.dist = compute_dist(a);

            // valid object to depth sort
            draw = 1;
            break;

         case DSPHERE:
         {
            (transMat.top()).multpoint3d(((DispCmdSphere *) cmd_ptr)->pos_r, c);
            r = scale_radius(((DispCmdSphere *) cmd_ptr)->pos_r[3]);

            sphere_approx(c, r);
            break;
         }

         case DSPHEREARRAY:
         {
            DispCmdSphereArray *sa = (DispCmdSphereArray *) cmd_ptr;
            int cIndex, rIndex; // cIndex: index of colors & centers
                                // rIndex: index of radii.
            float * centers;
            float * radii;
            float * colors;
            sa->getpointers(centers, radii, colors);

            set_sphere_res(sa->sphereres);

            for (cIndex = 0, rIndex=0; rIndex < sa->numspheres; 
                 cIndex+=3, rIndex++)
            {
                colorIndex = nearest_index(colors[cIndex],
                                           colors[cIndex+1],
                                           colors[cIndex+2]);
                (transMat.top()).multpoint3d(&centers[cIndex] , c);
                r = scale_radius(radii[rIndex]);

                sphere_approx(c, r);
            }

            break;
         }   

         case DLINE:
            // check for zero-length line (degenerate)
            if (!memcmp(((DispCmdLine *) cmd_ptr)->pos1,
                        ((DispCmdLine *) cmd_ptr)->pos2,
                        sizeof(float) * 3)) {
               // degenerate line
               break;
            }

            // allocate memory
            depth_obj.points = (float *) malloc(sizeof(float) * 4);
            if (!depth_obj.points) {
               // memory error
               if (!memerror) {
                  memerror = 1;
                  msgErr << "PSDisplayDevice: Out of memory. Some " <<
                     "objects were not drawn." << sendmsg;
               }
               break;
            }

            // copy data
            depth_obj.npoints = 2;
            depth_obj.color = colorIndex;
            (transMat.top()).multpoint3d(((DispCmdLine *) cmd_ptr)->pos1, a);
            (transMat.top()).multpoint3d(((DispCmdLine *) cmd_ptr)->pos2, b);
            memcpy(depth_obj.points, a, sizeof(float) * 2);
            memcpy(&depth_obj.points[2], b, sizeof(float) * 2);

            // compute the centerpoint of the object
            cent[0] = (a[0] + b[0]) / 2;
            cent[1] = (a[1] + b[1]) / 2;
            cent[2] = (a[2] + b[2]) / 2;

            // compute the distance to the eye
            depth_obj.dist = compute_dist(cent);

            // valid object to depth sort
            draw = 1;
            break;

         case DLINEARRAY:
           {
            // XXX much replicated code from DLINE
            float *v = (float *)cmd_ptr;
            int nlines = (int)v[0];
            v++;
            for (int i=0; i<nlines; i++) {
              // check for degenerate line
              if (!memcmp(v,v+3,3*sizeof(float)))
                break;

              // allocate memory
              depth_obj.points = (float *) malloc(sizeof(float) * 4);
              if (!depth_obj.points) {
                 // memory error
                 if (!memerror) {
                    memerror = 1;
                    msgErr << "PSDisplayDevice: Out of memory. Some " <<
                       "objects were not drawn." << sendmsg;
                 }
                 break;
              }

              // copy data
              depth_obj.npoints = 2;
              depth_obj.color = colorIndex;
              (transMat.top()).multpoint3d(v, a);
              (transMat.top()).multpoint3d(v+3, b);
              memcpy(depth_obj.points, a, sizeof(float) * 2);
              memcpy(&depth_obj.points[2], b, sizeof(float) * 2);
  
              // compute the centerpoint of the object
              cent[0] = (a[0] + b[0]) / 2;
              cent[1] = (a[1] + b[1]) / 2;
              cent[2] = (a[2] + b[2]) / 2;
  
              // compute the distance to the eye
              depth_obj.dist = compute_dist(cent);
 
              // we'll add the object here, since we have multiple objects 
              draw = 0;
              memusage += sizeof(float) * 2 * depth_obj.npoints;
              points += depth_obj.npoints;
              objects++;
              depth_list.append(depth_obj);

              v += 6;
            } 
           }
           break;           

         case DPOLYLINEARRAY:
           {
            // XXX much replicated code from DLINE / DLINEARRAY
            float *v = (float *)cmd_ptr;
            int nverts = (int)v[0];
            v++;
            for (int i=0; i<nverts-1; i++) {
              // check for degenerate line
              if (!memcmp(v,v+3,3*sizeof(float)))
                break;

              // allocate memory
              depth_obj.points = (float *) malloc(sizeof(float) * 4);
              if (!depth_obj.points) {
                 // memory error
                 if (!memerror) {
                    memerror = 1;
                    msgErr << "PSDisplayDevice: Out of memory. Some " <<
                       "objects were not drawn." << sendmsg;
                 }
                 break;
              }

              // copy data
              depth_obj.npoints = 2;
              depth_obj.color = colorIndex;
              (transMat.top()).multpoint3d(v, a);
              (transMat.top()).multpoint3d(v+3, b);
              memcpy(depth_obj.points, a, sizeof(float) * 2);
              memcpy(&depth_obj.points[2], b, sizeof(float) * 2);
  
              // compute the centerpoint of the object
              cent[0] = (a[0] + b[0]) / 2;
              cent[1] = (a[1] + b[1]) / 2;
              cent[2] = (a[2] + b[2]) / 2;
  
              // compute the distance to the eye
              depth_obj.dist = compute_dist(cent);
 
              // we'll add the object here, since we have multiple objects 
              draw = 0;
              memusage += sizeof(float) * 2 * depth_obj.npoints;
              points += depth_obj.npoints;
              objects++;
              depth_list.append(depth_obj);

              v += 3;
            } 
           }
           break;           
 
         case DCYLINDER:
         {
            int res;

            (transMat.top()).multpoint3d((float *) cmd_ptr, a);
            (transMat.top()).multpoint3d(&((float *) cmd_ptr)[3], b);
            r = scale_radius(((float *) cmd_ptr)[6]);
            res = (int) ((float *) cmd_ptr)[7];

            cylinder_approx(a, b, r, res, (int) ((float *) cmd_ptr)[8]);
            break;
         }

         case DCONE:
         {
            (transMat.top()).multpoint3d(((DispCmdCone *) cmd_ptr)->pos1, a);
            (transMat.top()).multpoint3d(((DispCmdCone *) cmd_ptr)->pos2, b);
            float r1 = scale_radius(((DispCmdCone *) cmd_ptr)->radius);
            float r2 = scale_radius(((DispCmdCone *) cmd_ptr)->radius2);

            // XXX current implementation can't draw truncated cones.
            if (r2 > 0.0f) {
              msgWarn << "PSDisplayDevice) can't draw truncated cones" 
                      << sendmsg;
            }
            cone_approx(a, b, r1);
            break;
         }

        case DTEXTSIZE:
          textsize = ((DispCmdTextSize *)cmd_ptr)->size;
          break;

        case DTEXT:
        {
            float* pos = (float *)cmd_ptr;
#if 0
            // thickness not implemented yet
            float thickness = pos[3];    // thickness is stored in 4th slot
#endif
            char* txt = (char *)(pos+4);
            int   txtlen = strlen(txt);
            // allocate memory
            depth_obj.points = (float *) malloc(sizeof(float) * 2);
            depth_obj.text   = (char  *) malloc(sizeof(char) * (txtlen+1));
            if ( !(depth_obj.points || depth_obj.text) ) {
              // memory error
              if (!memerror) {
                 memerror = 1;
                 msgErr << "PSDisplayDevice: Out of memory. Some " <<
                    "objects were not drawn." << sendmsg;
              }
              break;
           }

            // copy data
            depth_obj.npoints = 1;
            depth_obj.color = colorIndex;
            (transMat.top()).multpoint3d(((DispCmdPoint *) cmd_ptr)->pos, a);
            memcpy(depth_obj.points, a, sizeof(float) * 2);
            strcpy(depth_obj.text , txt);

            // note scale factor, stored into "light_scale", so we didn't
            // have to add a new structure member just for this.
            depth_obj.light_scale = textsize * 15;

            // compute the distance to the eye
            depth_obj.dist = compute_dist(a);

            // valid object to depth sort
            draw = 1;
            break;
         }

         case DTRIANGLE:
            // check for degenerate triangle
            if (!memcmp(((DispCmdTriangle *) cmd_ptr)->pos1,
                        ((DispCmdTriangle *) cmd_ptr)->pos2,
                        sizeof(float) * 3) ||
                !memcmp(((DispCmdTriangle *) cmd_ptr)->pos2,
                        ((DispCmdTriangle *) cmd_ptr)->pos3,
                        sizeof(float) * 3) ||
                !memcmp(((DispCmdTriangle *) cmd_ptr)->pos2,
                        ((DispCmdTriangle *) cmd_ptr)->pos3,
                        sizeof(float) * 3)) {
               // degenerate triangle
               break;
            }

            // allocate memory
            depth_obj.points = (float *) malloc(sizeof(float) * 6);
            if (!depth_obj.points) {
               // memory error
               if (!memerror) {
                  memerror = 1;
                  msgErr << "PSDisplayDevice: Out of memory. Some " <<
                     "objects were not drawn." << sendmsg;
               }
               break;
            }

            // copy data
            depth_obj.npoints = 3;
            depth_obj.color = (nc >= 0) ? nc : colorIndex;
            (transMat.top()).multpoint3d(((DispCmdTriangle *) cmd_ptr)->pos1, a);
            (transMat.top()).multpoint3d(((DispCmdTriangle *) cmd_ptr)->pos2, b);
            (transMat.top()).multpoint3d(((DispCmdTriangle *) cmd_ptr)->pos3, c);
            memcpy(depth_obj.points, a, sizeof(float) * 2);
            memcpy(&depth_obj.points[2], b, sizeof(float) * 2);
            memcpy(&depth_obj.points[4], c, sizeof(float) * 2);

            // compute the centerpoint of the object
            cent[0] = (a[0] + b[0] + c[0]) / 3;
            cent[1] = (a[1] + b[1] + c[1]) / 3;
            cent[2] = (a[2] + b[2] + c[2]) / 3;

            // compute the distance to the eye for depth sorting
            depth_obj.dist = compute_dist(cent);

            // compute a light shading factor
            depth_obj.light_scale = compute_light(a, b, c);

            // valid object to depth sort
            draw = 1;
            break;

         case DTRIMESH_C4F_N3F_V3F:
            // call a separate routine to break up the mesh into
            // its component triangles
            decompose_mesh((DispCmdTriMesh *) cmd_ptr);
            break;

         case DTRISTRIP:
            // call a separate routine to break up the strip into
            // its component triangles
            decompose_tristrip((DispCmdTriStrips *) cmd_ptr);
            break;

         case DSQUARE:
            // check for degenerate quadrilateral
            if (!memcmp(((DispCmdSquare *) cmd_ptr)->pos1,
                        ((DispCmdSquare *) cmd_ptr)->pos2,
                        sizeof(float) * 3) ||
                !memcmp(((DispCmdSquare *) cmd_ptr)->pos1,
                        ((DispCmdSquare *) cmd_ptr)->pos3,
                        sizeof(float) * 3) ||
                !memcmp(((DispCmdSquare *) cmd_ptr)->pos1,
                        ((DispCmdSquare *) cmd_ptr)->pos4,
                        sizeof(float) * 3) ||
                !memcmp(((DispCmdSquare *) cmd_ptr)->pos2,
                        ((DispCmdSquare *) cmd_ptr)->pos3,
                        sizeof(float) * 3) ||
                !memcmp(((DispCmdSquare *) cmd_ptr)->pos2,
                        ((DispCmdSquare *) cmd_ptr)->pos4,
                        sizeof(float) * 3) ||
                !memcmp(((DispCmdSquare *) cmd_ptr)->pos3,
                        ((DispCmdSquare *) cmd_ptr)->pos4,
                        sizeof(float) * 3)) {
               // degenerate quadrilateral
               break;
            }

            // allocate memory
            depth_obj.points = (float *) malloc(sizeof(float) * 8);
            if (!depth_obj.points) {
               // memory error
               if (!memerror) {
                  memerror = 1;
                  msgErr << "PSDisplayDevice: Out of memory. Some " <<
                     "objects were not drawn." << sendmsg;
               }
               break;
            }

            // copy data
            depth_obj.npoints = 4;
            depth_obj.color = colorIndex;
            (transMat.top()).multpoint3d(((DispCmdSquare *) cmd_ptr)->pos1, a);
            (transMat.top()).multpoint3d(((DispCmdSquare *) cmd_ptr)->pos2, b);
            (transMat.top()).multpoint3d(((DispCmdSquare *) cmd_ptr)->pos3, c);
            (transMat.top()).multpoint3d(((DispCmdSquare *) cmd_ptr)->pos4, d);
            memcpy(depth_obj.points, a, sizeof(float) * 2);
            memcpy(&depth_obj.points[2], b, sizeof(float) * 2);
            memcpy(&depth_obj.points[4], c, sizeof(float) * 2);
            memcpy(&depth_obj.points[6], d, sizeof(float) * 2);

            // compute the centerpoint of the object
            cent[0] = (a[0] + b[0] + c[0] + d[0]) / 4;
            cent[1] = (a[1] + b[1] + c[1] + d[1]) / 4;
            cent[2] = (a[2] + b[2] + c[2] + d[2]) / 4;

            // compute the distance to the eye for depth sorting
            depth_obj.dist = compute_dist(cent);

            // compute a light shading factor
            depth_obj.light_scale = compute_light(a, b, c);

            // valid object to depth sort
            draw = 1;
            break;

         case DCOLORINDEX:
            colorIndex = ((DispCmdColorIndex *) cmd_ptr)->color;
            break;

         case DSPHERERES:
            set_sphere_res(((int *) cmd_ptr)[0]);
            break;

         default:
            // unknown object, so just skip it
            break;
      }

      // if we have a valid object to add to the depth sort list
      if (draw && depth_obj.npoints) {
         memusage += sizeof(float) * 2 * depth_obj.npoints;
         if ( depth_obj.text )
           memusage += sizeof(char) * (1+strlen(depth_obj.text));
         points += depth_obj.npoints;
         objects++;
         depth_list.append(depth_obj);
      }

      depth_obj.npoints = 0;
      depth_obj.points = NULL;

   } // while (tok != DLASTCOMMAND)

     transMat.pop();
   } // end for() [periodic images]
}