/// draw a cone void RenderManDisplayDevice::cone(float *a, float *b, float r) { float axis[3], vec1[3], vec2[3]; float R, phi, rxy, theta; float radius; // Transform the world coordinates (transMat.top()).multpoint3d(a, vec1); (transMat.top()).multpoint3d(b, vec2); radius = scale_radius(r); if (radius < DEFAULT_RADIUS) { radius = (float) DEFAULT_RADIUS; } // RenderMan's cylinders always run along the z axis, and must // be transformed to the proper position and rotation. This // code is taken from OpenGLRenderer.C. axis[0] = vec2[0] - vec1[0]; axis[1] = vec2[1] - vec1[1]; axis[2] = vec2[2] - vec1[2]; R = axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2]; if (R <= 0) return; R = sqrtf(R); // evaluation of sqrt() _after_ early exit // determine phi rotation angle, amount to rotate about y phi = acosf(axis[2] / R); // determine theta rotation, amount to rotate about z rxy = sqrtf(axis[0] * axis[0] + axis[1] * axis[1]); if (rxy <= 0) { theta = 0; } else { theta = acosf(axis[0] / rxy); if (axis[1] < 0) theta = (float) (2.0 * VMD_PI) - theta; } // Write the cone fprintf(outfile, "TransformBegin\n"); write_materials(1); fprintf(outfile, " Translate %g %g %g\n", vec1[0], vec1[1], vec1[2]); if (theta) fprintf(outfile, " Rotate %g 0 0 1\n", (theta / VMD_PI) * 180); if (phi) fprintf(outfile, " Rotate %g 0 1 0\n", (phi / VMD_PI) * 180); fprintf(outfile, " Cone %g %g 360\n", R, radius); fprintf(outfile, "TransformEnd\n"); }
/// draw a sphere void GelatoDisplayDevice::sphere(float * spdata) { float vec[3]; float radius; // Transform the world coordinates (transMat.top()).multpoint3d(spdata, vec); radius = scale_radius(spdata[3]); if (radius < DEFAULT_RADIUS) { radius = (float) DEFAULT_RADIUS; } // Draw the sphere fprintf(outfile, "PushTransform()\n"); write_materials(1); fprintf(outfile, "Translate(%g, %g, %g)\n", vec[0], vec[1], vec[2]); fprintf(outfile, "Sphere(%g, %g, %g, 360)\n", radius, -radius, radius); fprintf(outfile, "PopTransform()\n"); }
/// draw a sphere void RenderManDisplayDevice::sphere(float * spdata) { float vec[3]; float radius; // Transform the world coordinates (transMat.top()).multpoint3d(spdata, vec); radius = scale_radius(spdata[3]); if (radius < DEFAULT_RADIUS) { radius = (float) DEFAULT_RADIUS; } // Draw the sphere fprintf(outfile, "TransformBegin\n"); write_materials(1); fprintf(outfile, " Translate %g %g %g\n", vec[0], vec[1], vec[2]); fprintf(outfile, " Sphere %g %g %g 360\n", radius, -radius, radius); fprintf(outfile, "TransformEnd\n"); }
void GelatoDisplayDevice::trimesh_c4n3v3(int numverts, float * cnv, int numfacets, int * facets) { float vec1[3]; float norm1[3]; int i; write_materials(0); fprintf(outfile, "Mesh(\"linear\", ("); for (i=0; i<numfacets; i++) { fprintf(outfile, "3,"); } fprintf(outfile, "), ("); for (i=0; i<numfacets; i++) { fprintf(outfile, "%d, %d, %d,", facets[i*3], facets[i*3+1], facets[i*3+2]); } fprintf(outfile, "), "); fprintf(outfile, "\n\"vertex point P\", ("); for (i=0; i<numverts; i++) { (transMat.top()).multpoint3d(cnv + i*10 + 7, vec1); fprintf(outfile, "%g, %g, %g,", vec1[0], vec1[1], vec1[2]); } fprintf(outfile, "), "); fprintf(outfile, "\n\"vertex normal N\", ("); for (i=0; i<numverts; i++) { (transMat.top()).multnorm3d(cnv + i*10 + 4, norm1); fprintf(outfile, "%g, %g, %g,", norm1[0], norm1[1], norm1[2]); } fprintf(outfile, "), "); fprintf(outfile, "\n\"vertex color C\", ("); for (i=0; i<numverts; i++) { float *c = cnv + i*10; fprintf(outfile, "%g, %g, %g,", c[0], c[1], c[2]); } fprintf(outfile, "))\n"); }
// draw a triangle void RenderManDisplayDevice::triangle(const float *a, const float *b, const float *c, const float *n1, const float *n2, const float *n3) { float vec1[3], vec2[3], vec3[3]; float norm1[3], norm2[3], norm3[3]; // Transform the world coordinates (transMat.top()).multpoint3d(a, vec1); (transMat.top()).multpoint3d(b, vec2); (transMat.top()).multpoint3d(c, vec3); (transMat.top()).multnorm3d(n1, norm1); (transMat.top()).multnorm3d(n2, norm2); (transMat.top()).multnorm3d(n3, norm3); // Write the triangle write_materials(1); fprintf(outfile, "Polygon \"P\" [ %g %g %g %g %g %g %g %g %g ] ", vec1[0], vec1[1], vec1[2], vec2[0], vec2[1], vec2[2], vec3[0], vec3[1], vec3[2]); fprintf(outfile, "\"N\" [ %g %g %g %g %g %g %g %g %g ]\n", norm1[0], norm1[1], norm1[2], norm2[0], norm2[1], norm2[2], norm3[0], norm3[1], norm3[2]); }
// draw a triangle void GelatoDisplayDevice::triangle(const float *a, const float *b, const float *c, const float *n1, const float *n2, const float *n3) { float vec1[3], vec2[3], vec3[3]; float norm1[3], norm2[3], norm3[3]; // Transform the world coordinates (transMat.top()).multpoint3d(a, vec1); (transMat.top()).multpoint3d(b, vec2); (transMat.top()).multpoint3d(c, vec3); (transMat.top()).multnorm3d(n1, norm1); (transMat.top()).multnorm3d(n2, norm2); (transMat.top()).multnorm3d(n3, norm3); // Write the triangle write_materials(1); fprintf(outfile, "Mesh(\"linear\", (3,), (0, 1, 2), " "\"vertex point P\", (%g, %g, %g, %g, %g, %g, %g, %g, %g), " "\"vertex normal N\", (%g, %g, %g, %g, %g, %g, %g, %g, %g))\n", vec1[0], vec1[1], vec1[2], vec2[0], vec2[1], vec2[2], vec3[0], vec3[1], vec3[2], norm1[0], norm1[1], norm1[2], norm2[0], norm2[1], norm2[2], norm3[0], norm3[1], norm3[2]); }
// draw a square void RenderManDisplayDevice::square(float *n, float *a, float *b, float *c, float *d) { float vec1[3], vec2[3], vec3[3], vec4[3]; float norm[3]; // Transform the world coordinates (transMat.top()).multpoint3d(a, vec1); (transMat.top()).multpoint3d(b, vec2); (transMat.top()).multpoint3d(c, vec3); (transMat.top()).multpoint3d(d, vec4); (transMat.top()).multnorm3d(n, norm); // Write the square write_materials(1); fprintf(outfile, "Polygon \"P\" [ %g %g %g %g %g %g %g %g %g %g %g %g ] ", vec1[0], vec1[1], vec1[2], vec2[0], vec2[1], vec2[2], vec3[0], vec3[1], vec3[2], vec4[0], vec4[1], vec4[2]); fprintf(outfile, "\"N\" [ %g %g %g %g %g %g %g %g %g %g %g %g ]\n", norm[0], norm[1], norm[2], norm[0], norm[1], norm[2], norm[0], norm[1], norm[2], norm[0], norm[1], norm[2]); }
/// draw a NURBS cylinder, no transform, must be in world coords already void GelatoDisplayDevice::cylinder_nurb_noxfrm(float *vec1, float *vec2, float radius, int filled) { float axis[3]; float R, phi, rxy, theta; // safety check to prevent overly-tiny cylinders if (radius < DEFAULT_RADIUS) { radius = (float) DEFAULT_RADIUS; } // Gelato's cylinders always run along the z axis, and must // be transformed to the proper position and rotation. This // code is taken from OpenGLRenderer.C. axis[0] = vec2[0] - vec1[0]; axis[1] = vec2[1] - vec1[1]; axis[2] = vec2[2] - vec1[2]; R = axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2]; if (R <= 0) return; R = sqrtf(R); // evaluation of sqrt() _after_ early exit // determine phi rotation angle, amount to rotate about y phi = acosf(axis[2] / R); // determine theta rotation, amount to rotate about z rxy = sqrtf(axis[0] * axis[0] + axis[1] * axis[1]); if (rxy <= 0) { theta = 0; } else { theta = acosf(axis[0] / rxy); if (axis[1] < 0) theta = (float) (2.0 * VMD_PI) - theta; } // Write the cylinder, reorienting and translating it to the correct location fprintf(outfile, "PushTransform()\n"); write_materials(1); fprintf(outfile, "Translate(%g,%g,%g)\n", vec1[0], vec1[1], vec1[2]); if (theta) fprintf(outfile, "Rotate(%g,0,0,1)\n", (theta / VMD_PI) * 180); if (phi) fprintf(outfile, "Rotate(%g,0,1,0)\n", (phi / VMD_PI) * 180); // Calculate the NURBS parameters for Cylinder(radius, 0, R, 360) // on the Z axis. This is mostly hard-coded for speed. int A, i; float zmin = 0.0; float zmax = R; float circcv[9*4]; float uknotv[9+4]; float vknotv[4] = {0.0f,0.0f,1.0f,1.0f}; float controlv[9*2*4]; fullcirclearc(radius, uknotv, circcv); // generate full circle arc memcpy(controlv, circcv, 9*4*sizeof(float)); A=0; for(i=0; i<9; i++) { controlv[A+2] = zmin * controlv[A+3]; A+=4; } A=9*4; memcpy(&(controlv[A]), circcv, 9*4*sizeof(float)); for(i = 0; i < 9; i++) { controlv[A+2] = zmax * controlv[A+3]; A += 4; } // draw the NURBS Cylinder using the Gelato Patch primitive fprintf(outfile, "Patch(%d,3,(", 9); for (i=0; i<9+3; i++) { fprintf(outfile, "%g,", uknotv[i]); } fprintf(outfile, "),0,1,2,2,("); for (i=0; i<4; i++) { fprintf(outfile, "%g,", vknotv[i]); } fprintf(outfile, "),0,1,\"vertex hpoint Pw\", ("); for (i=0; i<9*2*4; i++) { fprintf(outfile, "%g,", controlv[i]); } fprintf(outfile, "))\n"); fprintf(outfile, "PopTransform()\n"); }
void GelatoDisplayDevice::text(float *pos, float size, float thickness, const char *str) { float textpos[3]; float textsize, textthickness; hersheyhandle hh; // transform the world coordinates (transMat.top()).multpoint3d(pos, textpos); textsize = size * 1.5f; textthickness = thickness*DEFAULT_RADIUS; while (*str != '\0') { float lm, rm, x, y, ox, oy; int draw, odraw; ox=oy=x=y=0.0f; draw=odraw=0; hersheyDrawInitLetter(&hh, *str, &lm, &rm); textpos[0] -= lm * textsize; while (!hersheyDrawNextLine(&hh, &draw, &x, &y)) { float oldpt[3], newpt[3]; if (draw) { newpt[0] = textpos[0] + textsize * x; newpt[1] = textpos[1] + textsize * y; newpt[2] = textpos[2]; if (odraw) { // if we have both previous and next points, connect them... oldpt[0] = textpos[0] + textsize * ox; oldpt[1] = textpos[1] + textsize * oy; oldpt[2] = textpos[2]; cylinder_nurb_noxfrm(oldpt, newpt, textthickness, 0); fprintf(outfile, "PushTransform()\n"); write_materials(1); fprintf(outfile, "Translate(%g, %g, %g)\n", newpt[0], newpt[1], newpt[2]); fprintf(outfile, "Sphere(%g, %g, %g, 360)\n", textthickness, -textthickness, textthickness); fprintf(outfile, "PopTransform()\n"); } else { // ...otherwise, just draw the next point fprintf(outfile, "PushTransform()\n"); write_materials(1); fprintf(outfile, "Translate(%g, %g, %g)\n", newpt[0], newpt[1], newpt[2]); fprintf(outfile, "Sphere(%g, %g, %g, 360)\n", textthickness, -textthickness, textthickness); fprintf(outfile, "PopTransform()\n"); } } ox=x; oy=y; odraw=draw; } textpos[0] += rm * textsize; str++; } }
void POV3DisplayDevice::start_clipgroup(void) { int i, num_clipplanes[3], mode; float pov_clip_center[3], pov_clip_distance[VMD_MAX_CLIP_PLANE]; float pov_clip_normal[VMD_MAX_CLIP_PLANE][3]; write_materials(); memset(num_clipplanes, 0, 3*sizeof(int)); for (i = 0; i < VMD_MAX_CLIP_PLANE; i++) { if (clip_mode[i] != 0) { // Count the number of clipping planes for each clip mode num_clipplanes[clip_mode[i]]++; // Translate the plane center (transMat.top()).multpoint3d(clip_center[i], pov_clip_center); // and the normal (transMat.top()).multnorm3d(clip_normal[i], pov_clip_normal[i]); vec_negate(pov_clip_normal[i], pov_clip_normal[i]); // POV-Ray uses the distance from the origin to the plane for its // representation, instead of the plane center pov_clip_distance[i] = dot_prod(pov_clip_normal[i], pov_clip_center); } } // Define the clip object for each clip mode for (mode = 1; mode < 3; mode++) { if (num_clipplanes[mode] > 0) { // This flag is used within VMD to determine if clipping information // should be written to the scene file clip_on[mode] = 1; // This flag is used within POV to determine if clipping should be done // within macros fprintf(outfile, "#declare VMD_clip_on[%d]=1;\n", mode); if (num_clipplanes[mode] == 1) { for (i = 0; i < VMD_MAX_CLIP_PLANE; i++) { if (clip_mode[i] == mode) { if (mode == 2) { // Textured plane for CSG clipping fprintf(outfile, "#declare VMD_clip[%d] = plane { <%.4f, %.4f, %.4f>, %.4f texture { pigment { rgbt<%.3f, %.3f, %.3f, %.3f> } } }\n", mode, pov_clip_normal[i][0], pov_clip_normal[i][1], -pov_clip_normal[i][2], pov_clip_distance[i], clip_color[i][0], clip_color[i][1], clip_color[i][2], 1 - mat_opacity); } else { // Non-textured plane for non-CSG clipping fprintf(outfile, "#declare VMD_clip[%d] = plane { <%.4f, %.4f, %.4f>, %.4f }\n", mode, pov_clip_normal[i][0], pov_clip_normal[i][1], -pov_clip_normal[i][2], pov_clip_distance[i]); #if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND) // Non-textured plane for non-CSG clipping, but scaled for use // when emitting meshes with the scaling hack. fprintf(outfile, "#declare VMD_scaledclip[%d] = plane { <%.4f, %.4f, %.4f>, %.4f }\n", mode, pov_clip_normal[i][0], pov_clip_normal[i][1], -pov_clip_normal[i][2], pov_clip_distance[i] * POVRAY_SCALEHACK); #endif } } } } // Declare the clipping object to be an intersection of planes else { fprintf(outfile, "#declare VMD_clip[%d] = intersection {\n", mode); for (i = 0; i < VMD_MAX_CLIP_PLANE; i++) { if (clip_mode[i] == mode) { if (mode == 2) { // Textured plane for CSG clipping fprintf(outfile, " plane { <%.4f, %.4f, %.4f>, %.4f texture { pigment { rgbt<%.3f, %.3f, %.3f, %.3f> } } }\n", pov_clip_normal[i][0], pov_clip_normal[i][1], -pov_clip_normal[i][2], pov_clip_distance[i], clip_color[i][0], clip_color[i][1], clip_color[i][2], 1 - mat_opacity); } else { // Non-textured plane for non-CSG clipping fprintf(outfile, " plane { <%.4f, %.4f, %.4f>, %.4f }\n", pov_clip_normal[i][0], pov_clip_normal[i][1], -pov_clip_normal[i][2], pov_clip_distance[i]); } } } fprintf(outfile, "}\n"); #if defined(POVRAY_BRAIN_DAMAGE_WORKAROUND) fprintf(outfile, "#declare VMD_scaledclip[%d] = intersection {\n", mode); for (i = 0; i < VMD_MAX_CLIP_PLANE; i++) { if (clip_mode[i] == mode) { if (mode == 2) { // Textured plane for CSG clipping fprintf(outfile, " plane { <%.4f, %.4f, %.4f>, %.4f texture { pigment { rgbt<%.3f, %.3f, %.3f, %.3f> } } }\n", pov_clip_normal[i][0], pov_clip_normal[i][1], -pov_clip_normal[i][2], pov_clip_distance[i] * POVRAY_SCALEHACK, clip_color[i][0], clip_color[i][1], clip_color[i][2], 1 - mat_opacity); } else { // Non-textured plane for non-CSG clipping fprintf(outfile, " plane { <%.4f, %.4f, %.4f>, %.4f }\n", pov_clip_normal[i][0], pov_clip_normal[i][1], -pov_clip_normal[i][2], pov_clip_distance[i] * POVRAY_SCALEHACK); } } } fprintf(outfile, "}\n"); #endif } } } }