Пример #1
0
/*
 * Ok, one step up in the complexity scale, this function
 * computes the net effect of all lights on a single vertex
 * given that vertex and a normal to use as the vertex normal.
 * A note for later:
 *	Perhaps the correct thing to do is add all light sources
 *	and then divide by the total, that would average the light
 *	in the scene. But then again, that would make ambient light
 *	contribute "less" based on the number of lights. Needs more
 *	thought. This will do for now.
 */
static void
light_vertex(p3dc_VRTX *v, p3dc_PNT4 *light, p3dc_PNT3 *nrm) {
	p3dc_NODE *ll;
	p3dc_PNT3 shade;

	light->x = light->y = light->z = 0; /* reset the point's light value */
	for (ll = lights.head; ll != NULL; ll = ll->nxt) {
		compute_light((p3dc_LIGHT *)(ll->data.p), &(v->v), nrm, &shade);
		light->x += shade.x;
		light->y += shade.y;
		light->z += shade.z;
	}
	PNT3_CLIP(light, 1.0);
	return;
}
Пример #2
0
double			compute_ray(int x, int y, t_env *e)
{
	t_vec		pixel;

	pixel = vec_int(MUL, e->right, (e->indent.x * (double)x));
	pixel = vec_vec(SUB, pixel, vec_int(MUL, e->up, (e->indent.y * (double)y)));
	pixel = vec_vec(ADD, vec_vec(SUB, e->view_upleft, e->ray.pos), pixel);
	e->ray.dir = norm(pixel);
	e->ray.t = compute_intersect(e, e->ray);
	if (e->ray.t)
	{
		if (compute_light(e))
			return (0);
		return (1);
	}
	return (0);
}
Пример #3
0
void PSDisplayDevice::cylinder_approx(float *a, float *b, float r, int res, 
                                      int filled) {

   float axis[3];
   float perp1[3], perp2[3];
   float pt1[3], pt2[3];
   float cent[3];
   float theta, theta_inc;
   float my_sin, my_cos;
   float w[3], x[3], y[3], z[3];
   int n;

   DepthSortObject cyl_body, cyl_trailcap, cyl_leadcap;

   // check against degenerate cylinder
   if (a[0] == b[0] && a[1] == b[1] && a[2] == b[2]) return;
   if (r <= 0) return;

   // first we compute the axis of the cylinder
   axis[0] = b[0] - a[0];
   axis[1] = b[1] - a[1];
   axis[2] = b[2] - a[2];
   vec_normalize(axis);

   // now we compute some arbitrary perpendicular to that axis
   if ((ABS(axis[0]) < ABS(axis[1])) &&
       (ABS(axis[0]) < ABS(axis[2]))) {
      perp1[0] = 0;
      perp1[1] = axis[2];
      perp1[2] = -axis[1];
   }
   else if ((ABS(axis[1]) < ABS(axis[2]))) {
      perp1[0] = -axis[2];
      perp1[1] = 0;
      perp1[2] = axis[0];
   }
   else {
      perp1[0] = axis[1];
      perp1[1] = -axis[0];
      perp1[2] = 0;
   }
   vec_normalize(perp1);

   // now we compute another vector perpendicular both to the
   // cylinder's axis and to the perpendicular we just found.
   cross_prod(perp2, axis, perp1);

   // initialize some stuff in the depth sort objects
   cyl_body.npoints = 4;
   cyl_body.color = colorIndex;

   if (filled & CYLINDER_TRAILINGCAP) {
      cyl_trailcap.npoints = 3;
      cyl_trailcap.color = colorIndex;
   }

   if (filled & CYLINDER_LEADINGCAP) {
      cyl_leadcap.npoints = 3;
      cyl_leadcap.color = colorIndex;
   }

   // we will start out with the point defined by perp2
   pt1[0] = r * perp2[0];
   pt1[1] = r * perp2[1];
   pt1[2] = r * perp2[2];
   theta = 0;
   theta_inc = (float) (VMD_TWOPI / res);
   for (n = 1; n <= res; n++) {
      // save the last point
      memcpy(pt2, pt1, sizeof(float) * 3);

      // increment the angle and compute new points
      theta += theta_inc;
      my_sin = (float) sin(theta);
      my_cos = (float) cos(theta);

      // compute the new points
      pt1[0] = r * (perp2[0] * my_cos + perp1[0] * my_sin);
      pt1[1] = r * (perp2[1] * my_cos + perp1[1] * my_sin);
      pt1[2] = r * (perp2[2] * my_cos + perp1[2] * my_sin);

      cyl_body.points = (float *) malloc(sizeof(float) * 8);
      cyl_trailcap.points = (float *) malloc(sizeof(float) * 6);
      cyl_leadcap.points = (float *) malloc(sizeof(float) * 6);
      if (!(cyl_body.points && cyl_trailcap.points && cyl_leadcap.points)) {
         // memory error
         if (!memerror) {
            memerror = 1;
            msgErr << "PSDisplayDevice: Out of memory. Some " <<
               "objects were not drawn." << sendmsg;
         }
         continue;
      }

      // we have to translate them back to their original point...
      w[0] = pt1[0] + a[0];
      w[1] = pt1[1] + a[1];
      w[2] = pt1[2] + a[2];
      x[0] = pt2[0] + a[0];
      x[1] = pt2[1] + a[1];
      x[2] = pt2[2] + a[2];
      y[0] = pt2[0] + b[0];
      y[1] = pt2[1] + b[1];
      y[2] = pt2[2] + b[2];
      z[0] = pt1[0] + b[0];
      z[1] = pt1[1] + b[1];
      z[2] = pt1[2] + b[2];

      memcpy(cyl_body.points, w, sizeof(float) * 2);
      memcpy(&cyl_body.points[2], x, sizeof(float) * 2);
      memcpy(&cyl_body.points[4], y, sizeof(float) * 2);
      memcpy(&cyl_body.points[6], z, sizeof(float) * 2);

      // finally, we have to compute the centerpoint of this cylinder...
      // we can make a slight optimization here since we know the
      // cylinder will be a parellelogram. we only need to average
      // 2 corner points to find the center.
      cent[0] = (w[0] + y[0]) / 2;
      cent[1] = (w[1] + y[1]) / 2;
      cent[2] = (w[2] + y[2]) / 2;
      cyl_body.dist = compute_dist(cent);

      // and finally the light scale
      cyl_body.light_scale = compute_light(w, x, y);

      // go ahead and add this to our depth-sort list
      memusage += sizeof(float) * 2 * cyl_body.npoints;
      points += cyl_body.npoints;
      objects++;
      depth_list.append(cyl_body);

      // Now do the same thing for the trailing end cap...
      if (filled & CYLINDER_TRAILINGCAP) {
        memcpy(&cyl_trailcap.points[0], x, sizeof(float) * 2);
        memcpy(&cyl_trailcap.points[2], w, sizeof(float) * 2);
        memcpy(&cyl_trailcap.points[4], a, sizeof(float) * 2);
      
        // finally, we have to compute the centerpoint of the triangle
        cent[0] = (x[0] + w[0] + a[0]) / 3;
        cent[1] = (x[1] + w[1] + a[1]) / 3;
        cent[2] = (x[2] + w[2] + a[2]) / 3;
        cyl_trailcap.dist = compute_dist(cent);

        // and finally the light scale
        cyl_trailcap.light_scale = compute_light(x, w, a);

        memusage += sizeof(float) * 2 * cyl_trailcap.npoints;
        points += cyl_trailcap.npoints;
        objects++;
        depth_list.append(cyl_trailcap);
      }

      // ...and the leading end cap.
      if (filled & CYLINDER_LEADINGCAP) {
        memcpy(cyl_leadcap.points, z, sizeof(float) * 2);
        memcpy(&cyl_leadcap.points[2], y, sizeof(float) * 2);
        memcpy(&cyl_leadcap.points[4], b, sizeof(float) * 2);

        // finally, we have to compute the centerpoint of the triangle
        cent[0] = (z[0] + y[0] + b[0]) / 3;
        cent[1] = (z[1] + y[1] + b[1]) / 3;
        cent[2] = (z[2] + y[2] + b[2]) / 3;
        cyl_leadcap.dist = compute_dist(cent);

        // and finally the light scale
        cyl_leadcap.light_scale = compute_light(z, y, b);

        memusage += sizeof(float) * 2 * cyl_leadcap.npoints;
        points += cyl_leadcap.npoints;
        objects++;
        depth_list.append(cyl_leadcap);
      }
   }
}
Пример #4
0
void PSDisplayDevice::sphere_approx(float *c, float r) {
   DepthSortObject depth_obj;
   float x[3], y[3], z[3];
   float cent[3];
   int pi, ni;
   int i;

   // first we need to determine if a recalculation of the cached
   // unit sphere is necessary. this is necessary if the number
   // of desired iterations has changed.
   if (!sph_verts || !sph_nverts || sph_iter != sph_desired_iter) {
      float a[3], b[3], c[3];
      float *newverts;
      float *oldverts;
      int nverts, ntris;
      int level;

      // remove old cached copy
      if (sph_verts && sph_nverts) free(sph_verts);

      // XXX TODO it should be possible here to use the old
      // sphere as an aid in calculating the new sphere. in
      // this manner we can save calculations during resolution
      // changes.

      newverts = (float *) malloc(sizeof(float) * 36);
      nverts = 12;
      ntris = 4;

      // start with half of a unit octahedron (front, convex half)

      // top left triangle
      newverts[0] = -1;    newverts[1] = 0;     newverts[2] = 0;
      newverts[3] = 0;     newverts[4] = 1;     newverts[5] = 0;
      newverts[6] = 0;     newverts[7] = 0;     newverts[8] = 1;

      // top right triangle
      newverts[9] = 0;     newverts[10] = 0;    newverts[11] = 1;
      newverts[12] = 0;    newverts[13] = 1;    newverts[14] = 0;
      newverts[15] = 1;    newverts[16] = 0;    newverts[17] = 0;

      // bottom right triangle
      newverts[18] = 0;    newverts[19] = 0;    newverts[20] = 1;
      newverts[21] = 1;    newverts[22] = 0;    newverts[23] = 0;
      newverts[24] = 0;    newverts[25] = -1;   newverts[26] = 0;

      // bottom left triangle
      newverts[27] = 0;    newverts[28] = 0;    newverts[29] = 1;
      newverts[30] = 0;    newverts[31] = -1;   newverts[32] = 0;
      newverts[33] = -1;   newverts[34] = 0;    newverts[35] = 0;

      for (level = 1; level < sph_desired_iter; level++) {
         oldverts = newverts;

         // allocate memory for the next iteration: we will need
         // four times the current number of vertices
         newverts = (float *) malloc(sizeof(float) * 12 * nverts);
         if (!newverts) {
            // memory error
            sph_iter = -1;
            sph_nverts = 0;
            sph_verts = NULL;
            free(oldverts);

            if (!memerror) {
               memerror = 1;
               msgErr << "PSDisplayDevice: Out of memory. Some " 
                      << "objects were not drawn." << sendmsg;
            }

            return;
         }

         pi = 0;
         ni = 0;
         for (i = 0; i < ntris; i++) {
            // compute intermediate vertices
            a[0] = (oldverts[pi    ] + oldverts[pi + 6]) / 2;
            a[1] = (oldverts[pi + 1] + oldverts[pi + 7]) / 2;
            a[2] = (oldverts[pi + 2] + oldverts[pi + 8]) / 2;
            vec_normalize(a);
            b[0] = (oldverts[pi    ] + oldverts[pi + 3]) / 2;
            b[1] = (oldverts[pi + 1] + oldverts[pi + 4]) / 2;
            b[2] = (oldverts[pi + 2] + oldverts[pi + 5]) / 2;
            vec_normalize(b);
            c[0] = (oldverts[pi + 3] + oldverts[pi + 6]) / 2;
            c[1] = (oldverts[pi + 4] + oldverts[pi + 7]) / 2;
            c[2] = (oldverts[pi + 5] + oldverts[pi + 8]) / 2;
            vec_normalize(c);

            // build triangles
            memcpy(&newverts[ni     ], &oldverts[pi], sizeof(float) * 3);
            memcpy(&newverts[ni + 3 ], b, sizeof(float) * 3);
            memcpy(&newverts[ni + 6 ], a, sizeof(float) * 3);

            memcpy(&newverts[ni + 9 ], b, sizeof(float) * 3);
            memcpy(&newverts[ni + 12], &oldverts[pi + 3], sizeof(float) * 3);
            memcpy(&newverts[ni + 15], c, sizeof(float) * 3);

            memcpy(&newverts[ni + 18], a, sizeof(float) * 3);
            memcpy(&newverts[ni + 21], b, sizeof(float) * 3);
            memcpy(&newverts[ni + 24], c, sizeof(float) * 3);

            memcpy(&newverts[ni + 27], a, sizeof(float) * 3);
            memcpy(&newverts[ni + 30], c, sizeof(float) * 3);
            memcpy(&newverts[ni + 33], &oldverts[pi + 6], sizeof(float) * 3);

            pi += 9;
            ni += 36;
         }

         free(oldverts);

         nverts *= 4;
         ntris *= 4;
      }

      sph_iter = sph_desired_iter;
      sph_nverts = nverts;
      sph_verts = newverts;
   }

   // now we're guaranteed to have a valid cached unit sphere, so
   // all we need to do is translate each coordinate based on the
   // desired position and radius, and add the triangles to the
   // depth sort list.
#if 0
   if (!points) {
      // memory error
      if (!memerror) {
         memerror = 1;
         msgErr << "PSDisplayDevice: Out of memory. Some " <<
            "objects were not drawn." << sendmsg;
      }
      return;
   }
#endif

   // perform the desired translations and scalings on each
   // vertex, then add each triangle to the depth sort list
   depth_obj.npoints = 3;
   depth_obj.color = colorIndex;

   pi = 0;
   for (i = 0; i < sph_nverts / 3; i++) {
      // allocate memory for the triangle
      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;
         }
         return;
      }

      // translations and scalings
      x[0] = r * sph_verts[pi] + c[0];
      x[1] = r * sph_verts[pi + 1] + c[1];
      x[2] = r * sph_verts[pi + 2] + c[2];
      y[0] = r * sph_verts[pi + 3] + c[0];
      y[1] = r * sph_verts[pi + 4] + c[1];
      y[2] = r * sph_verts[pi + 5] + c[2];
      z[0] = r * sph_verts[pi + 6] + c[0];
      z[1] = r * sph_verts[pi + 7] + c[1];
      z[2] = r * sph_verts[pi + 8] + c[2];

      memcpy(depth_obj.points, x, sizeof(float) * 2);
      memcpy(&depth_obj.points[2], y, sizeof(float) * 2);
      memcpy(&depth_obj.points[4], z, sizeof(float) * 2);

      // now need to compute centerpoint and distance to eye
      cent[0] = (x[0] + y[0] + z[0]) / 3;
      cent[1] = (x[1] + y[1] + z[1]) / 3;
      cent[2] = (x[2] + y[2] + z[2]) / 3;
      depth_obj.dist = compute_dist(cent);
      depth_obj.light_scale = compute_light(x, y, z);

      // and add to the depth sort list
      memusage += sizeof(float) * 2 * depth_obj.npoints;
      points += depth_obj.npoints;
      objects++;
      depth_list.append(depth_obj);

      pi += 9;
   }
}
Пример #5
0
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]
}
Пример #6
0
void PSDisplayDevice::decompose_tristrip(DispCmdTriStrips *strip)
{
    int s, t, v = 0;
    int v0, v1, v2;
    float r, g, b;
    float x[3], y[3], z[3], cent[3];
    DepthSortObject depth_obj;

    depth_obj.npoints = 3;

    // lookup table for winding order
    const int stripaddr[2][3] = { {0, 1, 2}, {1, 0, 2} };

    float *cnv;
    int *f;
    int *vertsperstrip;
    strip->getpointers(cnv, f, vertsperstrip);

    // loop over all of the triangle strips
    for (s = 0; s < strip->numstrips; s++)
    {
        // loop over all triangles in this triangle strip
        for (t = 0; t < vertsperstrip[s] - 2; t++)
        {
            v0 = f[v + (stripaddr[t & 0x01][0])] * 10;
            v1 = f[v + (stripaddr[t & 0x01][1])] * 10;
            v2 = f[v + (stripaddr[t & 0x01][2])] * 10;

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

            // average the three colors and use that average as the color for
            // this triangle
            r = (cnv[v0+0] + cnv[v1+0] + cnv[v2+0]) / 3; 
            g = (cnv[v0+1] + cnv[v1+1] + cnv[v2+1]) / 3; 
            b = (cnv[v0+2] + cnv[v1+2] + cnv[v2+2]) / 3; 
            depth_obj.color = nearest_index(r, g, b);

            // transform from world coordinates to screen coordinates and copy
            // each point to the depth sort structure in one fell swoop
            (transMat.top()).multpoint3d(&cnv[v0 + 7], x);
            (transMat.top()).multpoint3d(&cnv[v1 + 7], y);
            (transMat.top()).multpoint3d(&cnv[v2 + 7], z);
            memcpy(depth_obj.points, x, sizeof(float) * 2);
            memcpy(&depth_obj.points[2], y, sizeof(float) * 2);
            memcpy(&depth_obj.points[4], z, sizeof(float) * 2);

            // compute the centerpoint of the object
            cent[0] = (x[0] + y[0] + z[0]) / 3;
            cent[1] = (x[1] + y[1] + z[1]) / 3;
            cent[2] = (x[2] + y[2] + z[2]) / 3;

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

            // light shading factor
            depth_obj.light_scale = compute_light(x, y, z);

            // done ... add the object to the list
            memusage += sizeof(float) * 2 * depth_obj.npoints;
            points += depth_obj.npoints;
            objects++;
            depth_list.append(depth_obj);

            v++; // move on to next vertex
        } // triangles
    v+=2; // last two vertices are already used by last triangle
    } // strips  
}
Пример #7
0
void PSDisplayDevice::decompose_mesh(DispCmdTriMesh *mesh) {
   int i;
   int fi;
   int f1, f2, f3;
   float r, g, b;
   float x[3], y[3], z[3], cent[3];
   float *cnv;
   int *f;
   mesh->getpointers(cnv, f);
   DepthSortObject depth_obj;

   depth_obj.npoints = 3;

   fi = -3;
   for (i = 0; i < mesh->numfacets; i++) {
      fi += 3;
      f1 = f[fi    ] * 10;
      f2 = f[fi + 1] * 10;
      f3 = f[fi + 2] * 10;

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

      // average the three colors and use that average as the color for
      // this triangle
      r = (cnv[f1] + cnv[f2] + cnv[f3]) / 3;
      g = (cnv[f1 + 1] + cnv[f2 + 1] + cnv[f3 + 1]) / 3;
      b = (cnv[f1 + 2] + cnv[f2 + 2] + cnv[f3 + 2]) / 3;
      depth_obj.color = nearest_index(r, g, b);

      // transform from world coordinates to screen coordinates and copy
      // each point to the depth sort structure in one fell swoop
      (transMat.top()).multpoint3d(&cnv[f1 + 7], x);
      (transMat.top()).multpoint3d(&cnv[f2 + 7], y);
      (transMat.top()).multpoint3d(&cnv[f3 + 7], z);
      memcpy(depth_obj.points, x, sizeof(float) * 2);
      memcpy(&depth_obj.points[2], y, sizeof(float) * 2);
      memcpy(&depth_obj.points[4], z, sizeof(float) * 2);

      // compute the centerpoint of the object
      cent[0] = (x[0] + y[0] + z[0]) / 3;
      cent[1] = (x[1] + y[1] + z[1]) / 3;
      cent[2] = (x[2] + y[2] + z[2]) / 3;

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

      // light shading factor
      depth_obj.light_scale = compute_light(x, y, z);

      // done ... add the object to the list
      memusage += sizeof(float) * 2 * depth_obj.npoints;
      points += depth_obj.npoints;
      objects++;
      depth_list.append(depth_obj);
   }

}
Пример #8
0
void PSDisplayDevice::cone_approx(float *a, float *b, float r) {
   // XXX add ability to change number of triangles
   const int tris = 20;

   float axis[3];
   float perp1[3], perp2[3];
   float pt1[3], pt2[3];
   float cent[3];
   float x[3], y[3], z[3];
   float theta, theta_inc;
   float my_sin, my_cos;
   int n;

   DepthSortObject depth_obj;

   // check against degenerate cone
   if (a[0] == b[0] && a[1] == b[1] && a[2] == b[2]) return;
   if (r <= 0) return;

   // first we compute the axis of the cone
   axis[0] = b[0] - a[0];
   axis[1] = b[1] - a[1];
   axis[2] = b[2] - a[2];
   vec_normalize(axis);

   // now we compute some arbitrary perpendicular to that axis
   if ((ABS(axis[0]) < ABS(axis[1])) &&
       (ABS(axis[0]) < ABS(axis[2]))) {
      perp1[0] = 0;
      perp1[1] = axis[2];
      perp1[2] = -axis[1];
   }
   else if ((ABS(axis[1]) < ABS(axis[2]))) {
      perp1[0] = -axis[2];
      perp1[1] = 0;
      perp1[2] = axis[0];
   }
   else {
      perp1[0] = axis[1];
      perp1[1] = -axis[0];
      perp1[2] = 0;
   }
   vec_normalize(perp1);

   // now we compute another vector perpendicular both to the
   // cone's axis and to the perpendicular we just found.
   cross_prod(perp2, axis, perp1);

   // initialize some stuff in the depth sort object
   depth_obj.npoints = 3;
   depth_obj.color = colorIndex;

   // we will start out with the point defined by perp2
   pt1[0] = r * perp2[0];
   pt1[1] = r * perp2[1];
   pt1[2] = r * perp2[2];
   theta = 0;
   theta_inc = (float) (VMD_TWOPI / tris);
   for (n = 1; n <= tris; n++) {
      // save the last point
      memcpy(pt2, pt1, sizeof(float) * 3);

      // increment the angle and compute new points
      theta += theta_inc;
      my_sin = (float) sin(theta);
      my_cos = (float) cos(theta);

      // compute the new points
      pt1[0] = r * (perp2[0] * my_cos + perp1[0] * my_sin);
      pt1[1] = r * (perp2[1] * my_cos + perp1[1] * my_sin);
      pt1[2] = r * (perp2[2] * my_cos + perp1[2] * my_sin);

      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;
         }
         continue;
      }

      // we have to translate them back to their original point...
      x[0] = pt1[0] + a[0];
      x[1] = pt1[1] + a[1];
      x[2] = pt1[2] + a[2];
      y[0] = pt2[0] + a[0];
      y[1] = pt2[1] + a[1];
      y[2] = pt2[2] + a[2];

      // now we use the apex of the cone as the third point
      z[0] = b[0];
      z[1] = b[1];
      z[2] = b[2];

      memcpy(depth_obj.points, x, sizeof(float) * 2);
      memcpy(&depth_obj.points[2], y, sizeof(float) * 2);
      memcpy(&depth_obj.points[4], z, sizeof(float) * 2);

      // finally, we have to compute the centerpoint of this
      // triangle...
      cent[0] = (x[0] + y[0] + z[0]) / 3;
      cent[1] = (x[1] + y[1] + z[1]) / 3;
      cent[2] = (x[2] + y[2] + z[2]) / 3;
      depth_obj.dist = compute_dist(cent);

      // and the light shading factor
      depth_obj.light_scale = compute_light(x, y, z);

      // go ahead and add this to our depth-sort list
      memusage += sizeof(float) * 2 * depth_obj.npoints;
      points += depth_obj.npoints;
      objects++;
      depth_list.append(depth_obj);
   }
}