/* * 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; }
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); }
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); } } }
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; } }
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(¢ers[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] }
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 }
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); } }
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); } }