// draw a line (cylinder) from a to b void TachyonDisplayDevice::line(float *a, float*b) { int i, j, test; float dirvec[3], unitdirvec[3]; float from[3], to[3], tmp1[3], tmp2[3]; if (lineStyle == ::SOLIDLINE) { // transform the world coordinates (transMat.top()).multpoint3d(a, from); (transMat.top()).multpoint3d(b, to); // 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", float(lineWidth)*DEFAULT_RADIUS); write_cindexmaterial(colorIndex, materialIndex); } else if (lineStyle == ::DASHEDLINE) { // transform the world coordinates (transMat.top()).multpoint3d(a, tmp1); (transMat.top()).multpoint3d(b, tmp2); // how to create a dashed line vec_sub(dirvec, tmp2, tmp1); // vector from a to b vec_copy(unitdirvec, dirvec); vec_normalize(unitdirvec); // unit vector from a to b test = 1; i = 0; while (test == 1) { for (j=0; j<3; j++) { from[j] = (float) (tmp1[j] + (2*i )*DASH_LENGTH*unitdirvec[j]); to[j] = (float) (tmp1[j] + (2*i + 1)*DASH_LENGTH*unitdirvec[j]); } if (fabsf(tmp1[0] - to[0]) >= fabsf(dirvec[0])) { vec_copy(to, tmp2); test = 0; } // 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", float(lineWidth)*DEFAULT_RADIUS); write_cindexmaterial(colorIndex, materialIndex); i++; } } else { msgErr << "TachyonDisplayDevice: Unknown line style " << lineStyle << sendmsg; } }
// 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); } } }
// draw a triangle void RayShadeDisplayDevice::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); // and the normals (transMat.top()).multnorm3d(n1, norm1); (transMat.top()).multnorm3d(n2, norm2); (transMat.top()).multnorm3d(n3, norm3); write_cindexmaterial(colorIndex, materialIndex); fprintf(outfile, "triangle %5f %5f %5f %5f %5f %5f ", scale_fix(vec1[0]), scale_fix(vec1[1]), scale_fix(vec1[2]), scale_fix(norm1[0]), scale_fix(norm1[1]), scale_fix(norm1[2])); fprintf(outfile, "%5f %5f %5f %5f %5f %5f ", scale_fix(vec2[0]), scale_fix(vec2[1]), scale_fix(vec2[2]), scale_fix(norm2[0]), scale_fix(norm2[1]), scale_fix(norm2[2])); fprintf(outfile, "%5f %5f %5f %5f %5f %5f\n", scale_fix(vec3[0]), scale_fix(vec3[1]), scale_fix(vec3[2]), scale_fix(norm3[0]), scale_fix(norm3[1]), scale_fix(norm3[2])); }
// draw a triangle void TachyonDisplayDevice::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); // and the normals (transMat.top()).multnorm3d(n1, norm1); (transMat.top()).multnorm3d(n2, norm2); (transMat.top()).multnorm3d(n3, norm3); // draw the triangle fprintf(outfile, "STri\n"); // triangle fprintf(outfile, " V0 %g %g %g\n", vec1[0], vec1[1], -vec1[2]); fprintf(outfile, " V1 %g %g %g\n", vec2[0], vec2[1], -vec2[2]); fprintf(outfile, " V2 %g %g %g\n", vec3[0], vec3[1], -vec3[2]); fprintf(outfile, " N0 %.3f %.3f %.3f\n", -norm1[0], -norm1[1], norm1[2]); fprintf(outfile, " N1 %.3f %.3f %.3f\n", -norm2[0], -norm2[1], norm2[2]); fprintf(outfile, " N2 %.3f %.3f %.3f\n", -norm3[0], -norm3[1], norm3[2]); write_cindexmaterial(colorIndex, materialIndex); }
// use an efficient mesh primitve rather than individual triangles // when possible. void TachyonDisplayDevice::trimesh_c4u_n3b_v3f(unsigned char *c, char *n, float *v, int numfacets) { int i; float vec1[3]; float norm1[3]; int numverts = 3*numfacets; const float ci2f = 1.0f / 255.0f; // used for uchar2float and normal conv const float cn2f = 1.0f / 127.5f; fprintf(outfile, "VertexArray"); fprintf(outfile, " Numverts %d\n", numverts); fprintf(outfile, "\nCoords\n"); for (i=0; i<numverts; i++) { int idx = i * 3; (transMat.top()).multpoint3d(v + idx, vec1); fprintf(outfile, "%g %g %g\n", vec1[0], vec1[1], -vec1[2]); } fprintf(outfile, "\nNormals\n"); for (i=0; i<numverts; i++) { float ntmp[3]; int idx = i * 3; // conversion from GLbyte format, Table 2.6, p. 44 of OpenGL spec 1.2.1 // float = (2c+1)/(2^8-1) ntmp[0] = n[idx ] * cn2f + ci2f; ntmp[1] = n[idx+1] * cn2f + ci2f; ntmp[2] = n[idx+2] * cn2f + ci2f; (transMat.top()).multnorm3d(ntmp, norm1); fprintf(outfile, "%.3f %.3f %.3f\n", -norm1[0], -norm1[1], norm1[2]); } // don't emit per-vertex colors when volumetric texturing is enabled if (!involtex) { fprintf(outfile, "\nColors\n"); for (i=0; i<numverts; i++) { int idx = i * 4; // conversion from GLubyte format, Table 2.6, p. 44 of OpenGL spec 1.2.1 // float = c/(2^8-1) fprintf(outfile, "%.3f %.3f %.3f\n", c[idx ] * ci2f, c[idx+1] * ci2f, c[idx+2] * ci2f); } } // emit the texture to be used by the geometry that follows write_cindexmaterial(colorIndex, materialIndex); // loop over all of the facets in the mesh fprintf(outfile, "\nTriMesh %d\n", numfacets); for (i=0; i<numfacets*3; i+=3) { fprintf(outfile, "%d %d %d\n", i, i+1, i+2); } // terminate vertex array fprintf(outfile, "\nEnd_VertexArray\n"); }
// 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])); }
// draw a color-per-vertex triangle void X3DDisplayDevice::tricolor(const float * a, const float * b, const float * c, const float * n1, const float * n2, const float * n3, const float *c1, const float *c2, const float *c3) { float ta[3], tb[3], tc[3], tn1[3], tn2[3], tn3[3]; // transform the world coordinates (transMat.top()).multpoint3d(a, ta); (transMat.top()).multpoint3d(b, tb); (transMat.top()).multpoint3d(c, tc); // and the normals (transMat.top()).multnorm3d(n1, tn1); (transMat.top()).multnorm3d(n2, tn2); (transMat.top()).multnorm3d(n3, tn3); // ugly and wasteful, but it will work fprintf(outfile, "<Shape>\n"); fprintf(outfile, " "); write_cindexmaterial(colorIndex, materialIndex); fprintf(outfile, " <IndexedFaceSet solid='false' coordIndex='0 1 2 -1'>\n"); fprintf(outfile, " <Coordinate point='%g %g %g, %g %g %g, %g %g %g'/>\n", ta[0], ta[1], ta[2], tb[0], tb[1], tb[2], tc[0], tc[1], tc[2]); fprintf(outfile, " <Normal vector='%g %g %g, %g %g %g, %g %g %g'/>\n", tn1[0], tn1[1], tn1[2], tn2[0], tn2[1], tn2[2], tn3[0], tn3[1], tn3[2]); fprintf(outfile, " <Color color='%g %g %g, %g %g %g, %g %g %g'/>\n", c1[0], c1[1], c1[2], c2[0], c2[1], c2[2], c3[0], c3[1], c3[2]); fprintf(outfile, " </IndexedFaceSet>\n"); fprintf(outfile, "</Shape>\n"); }
void WavefrontDisplayDevice::triangle(const float *v1, const float *v2, const float *v3, const float *n1, const float *n2, const float *n3) { float a[3], b[3], c[3]; float norm1[3], norm2[3], norm3[3]; // transform the world coordinates (transMat.top()).multpoint3d(v1, a); (transMat.top()).multpoint3d(v2, b); (transMat.top()).multpoint3d(v3, c); // and the normals (transMat.top()).multnorm3d(n1, norm1); (transMat.top()).multnorm3d(n2, norm2); (transMat.top()).multnorm3d(n3, norm3); #ifdef VMDGENMTLFILE // set colors write_cindexmaterial(colorIndex, materialIndex); #endif // draw the triangle fprintf(outfile,"v %f %f %f\n", a[0], a[1], a[2]); fprintf(outfile,"v %f %f %f\n", b[0], b[1], b[2]); fprintf(outfile,"v %f %f %f\n", c[0], c[1], c[2]); fprintf(outfile,"vn %f %f %f\n", norm1[0], norm1[1], norm1[2]); fprintf(outfile,"vn %f %f %f\n", norm2[0], norm2[1], norm2[2]); fprintf(outfile,"vn %f %f %f\n", norm3[0], norm3[1], norm3[2]); fprintf(outfile,"f -3//-3 -2//-2 -1//-1\n"); }
void WavefrontDisplayDevice::tristrip(int numverts, const float * cnv, int numstrips, const int *vertsperstrip, const int *facets) { int i, strip, t, v = 0; int stripaddr[2][3] = { {0, 1, 2}, {1, 0, 2} }; float vec1[3]; float norm1[3]; const float onethird = (1.0f / 3.0f); // write out list of vertices and normals for (i=0; i<numverts; i++) { int idx = i*10; (transMat.top()).multpoint3d(cnv + idx + 7, vec1); fprintf(outfile, "v %f %f %f\n", vec1[0], vec1[1], vec1[2]); (transMat.top()).multnorm3d(cnv + idx + 4, norm1); fprintf(outfile, "vn %f %f %f\n", norm1[0], norm1[1], norm1[2]); } // render triangle strips one triangle at a time // triangle winding order is: // v0, v1, v2, then v2, v1, v3, then v2, v3, v4, etc. // loop over all of the triangle strips for (strip=0; strip < numstrips; strip++) { // loop over all triangles in this triangle strip for (t = 0; t < (vertsperstrip[strip] - 2); t++) { // render one triangle, using lookup table to fix winding order int v0 = facets[v + (stripaddr[t & 0x01][0])]; int v1 = facets[v + (stripaddr[t & 0x01][1])]; int v2 = facets[v + (stripaddr[t & 0x01][2])]; #ifdef VMDGENMTLFILE // The Wavefront format does not allow per-vertex colors/materials, // so we use per-facet coloring, averaging the three vertex colors and // selecting the closest color from the VMD color table. const float *c1 = cnv + v0 * 10; const float *c2 = cnv + v1 * 10; const float *c3 = cnv + v2 * 10; float r, g, b; r = (c1[0] + c2[0] + c3[0]) * onethird; // average three vertex colors g = (c1[1] + c2[1] + c3[1]) * onethird; b = (c1[2] + c2[2] + c3[2]) * onethird; int cindex = nearest_index(r, g, b); write_cindexmaterial(cindex, materialIndex); #endif // use negative relative indices required for wavefront obj format v0 -= numverts; v1 -= numverts; v2 -= numverts; fprintf(outfile, "f %d//%d %d//%d %d//%d\n", v0, v0, v1, v1, v2, v2); v++; // move on to next vertex } v+=2; // last two vertices are already used by last triangle } }
// use an efficient mesh primitve rather than individual triangles // when possible. void X3DDisplayDevice::tristrip(int numverts, const float * cnv, int numstrips, const int *vertsperstrip, const int *facets) { // render directly using the IndexedTriangleStripSet primitive int i, strip, v = 0; fprintf(outfile, "<Shape>\n"); fprintf(outfile, " "); write_cindexmaterial(colorIndex, materialIndex); // loop over all of the facets in the mesh // emit vertex indices for each facet fprintf(outfile, " <IndexedTriangleStripSet solid='false' index='"); for (strip=0; strip < numstrips; strip++) { for (i=0; i<vertsperstrip[strip]; i++) { fprintf(outfile, "%d ", facets[v]); v++; // move on to next vertex } fprintf(outfile, "-1 "); // mark end of strip with a -1 index } fprintf(outfile, "'>\n"); // loop over all of the vertices fprintf(outfile, " <Coordinate point='"); for (i=0; i<numverts; i++) { const float *v = cnv + i*10 + 7; float tv[3]; (transMat.top()).multpoint3d(v, tv); fprintf(outfile, "%c %g %g %g", (i==0) ? ' ' : ',', tv[0], tv[1], tv[2]); } fprintf(outfile, "'/>\n"); // loop over all of the colors fprintf(outfile, " <Color color='"); for (i=0; i<numverts; i++) { const float *c = cnv + i*10; fprintf(outfile, "%c %g %g %g", (i==0) ? ' ' : ',', c[0], c[1], c[2]); } fprintf(outfile, "'/>\n"); // loop over all of the normals fprintf(outfile, " <Normal vector='"); for (i=0; i<numverts; i++) { const float *n = cnv + i*10 + 4; float tn[3]; (transMat.top()).multnorm3d(n, tn); #if 1 // reduce precision of surface normals to reduce X3D file size fprintf(outfile, "%c %.2f %.2f %.2f", (i==0) ? ' ' : ',', tn[0], tn[1], tn[2]); #else // full precision surface normals fprintf(outfile, "%c %g %g %g", (i==0) ? ' ' : ',', tn[0], tn[1], tn[2]); #endif } fprintf(outfile, "'/>\n"); fprintf(outfile, " </IndexedTriangleStripSet>\n"); fprintf(outfile, "</Shape>\n"); }
// draw a point void TachyonDisplayDevice::point(float * spdata) { float vec[3]; // transform the world coordinates (transMat.top()).multpoint3d(spdata, vec); // draw a sphere to represent the point, since we can't really draw points fprintf(outfile, "Sphere \n"); // sphere fprintf(outfile, " Center %g %g %g \n ", vec[0], vec[1], -vec[2]); fprintf(outfile, " Rad %g \n", float(lineWidth)*DEFAULT_RADIUS); write_cindexmaterial(colorIndex, materialIndex); }
// draw a cylinder void X3DDisplayDevice::cylinder_noxfrm(float *ta, float *tb, float radius, int filled) { if (ta[0] == tb[0] && ta[1] == tb[1] && ta[2] == tb[2]) { return; // we don't serve your kind here } float height = distance(ta, tb); 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 we have decent rotation vector, use it 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)); } else if (dp < -0.98) { // if we have denormalized rotation vector, we can assume it is // caused by a cylinder axis that is nearly coaxial with the Y axis. // If this is the case, we either perform no rotation in the case of a // angle cosine near 1.0, or a 180 degree rotation for a cosine near -1. fprintf(outfile, "center='0.0 %g 0.0' ", -(height / 2.0)); fprintf(outfile, "rotation='0 0 -1 -3.14159'"); } fprintf(outfile, ">\n"); fprintf(outfile, " <Shape>\n"); fprintf(outfile, " "); write_cindexmaterial(colorIndex, materialIndex); // draw the cylinder fprintf(outfile, " <Cylinder " "bottom='%s' height='%g' radius='%g' side='%s' top='%s' />\n", filled ? "true" : "false", height, radius, "true", filled ? "true" : "false"); fprintf(outfile, " </Shape>\n"); fprintf(outfile, "</Transform>\n"); }
// draw a point void RayShadeDisplayDevice::point(float * spdata) { float vec[3]; // transform the world coordinates (transMat.top()).multpoint3d(spdata, vec); write_cindexmaterial(colorIndex, materialIndex); // draw the sphere fprintf(outfile, "sphere %5f %5f %5f %5f\n", scale_fix(float(lineWidth)*DEFAULT_RADIUS), scale_fix(vec[0]), scale_fix(vec[1]), scale_fix(vec[2])); }
// use an efficient mesh primitve rather than individual triangles // when possible. void X3DDisplayDevice::trimesh_c4n3v3(int numverts, float * cnv, int numfacets, int * facets) { int i; fprintf(outfile, "<Shape>\n"); fprintf(outfile, " "); write_cindexmaterial(colorIndex, materialIndex); // loop over all of the facets in the mesh fprintf(outfile, " <IndexedTriangleSet solid='false' index='"); for (i=0; i<numfacets*3; i+=3) { fprintf(outfile, "%d %d %d ", facets[i], facets[i+1], facets[i+2]); } fprintf(outfile, "'>\n"); // loop over all of the vertices fprintf(outfile, " <Coordinate point='"); for (i=0; i<numverts; i++) { const float *v = cnv + i*10 + 7; float tv[3]; (transMat.top()).multpoint3d(v, tv); fprintf(outfile, "%c %g %g %g", (i==0) ? ' ' : ',', tv[0], tv[1], tv[2]); } fprintf(outfile, "'/>\n"); // loop over all of the colors fprintf(outfile, " <Color color='"); for (i=0; i<numverts; i++) { const float *c = cnv + i*10; fprintf(outfile, "%c %g %g %g", (i==0) ? ' ' : ',', c[0], c[1], c[2]); } fprintf(outfile, "'/>\n"); // loop over all of the normals fprintf(outfile, " <Normal vector='"); for (i=0; i<numverts; i++) { const float *n = cnv + i*10 + 4; float tn[3]; (transMat.top()).multnorm3d(n, tn); #if 1 // reduce precision of surface normals to reduce X3D file size fprintf(outfile, "%c %.2f %.2f %.2f", (i==0) ? ' ' : ',', tn[0], tn[1], tn[2]); #else // full precision surface normals fprintf(outfile, "%c %g %g %g", (i==0) ? ' ' : ',', tn[0], tn[1], tn[2]); #endif } fprintf(outfile, "'/>\n"); fprintf(outfile, " </IndexedTriangleSet>\n"); fprintf(outfile, "</Shape>\n"); }
// 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])); }
// 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); }
void TachyonDisplayDevice::tristrip(int numverts, const float * cnv, int numstrips, const int *vertsperstrip, const int *facets) { int i, strip, v=0; float vec1[3]; float norm1[3]; fprintf(outfile, "VertexArray"); fprintf(outfile, " Numverts %d\n", numverts); fprintf(outfile, "\nCoords\n"); for (i=0; i<numverts; i++) { (transMat.top()).multpoint3d(cnv + i*10 + 7, vec1); fprintf(outfile, "%g %g %g\n", vec1[0], vec1[1], -vec1[2]); } fprintf(outfile, "\nNormals\n"); for (i=0; i<numverts; i++) { (transMat.top()).multnorm3d(cnv + i*10 + 4, norm1); fprintf(outfile, "%.3f %.3f %.3f\n", -norm1[0], -norm1[1], norm1[2]); } // don't emit per-vertex colors when volumetric texturing is enabled if (!involtex) { fprintf(outfile, "\nColors\n"); for (i=0; i<numverts; i++) { int idx = i * 10; fprintf(outfile, "%.3f %.3f %.3f\n", cnv[idx], cnv[idx+1], cnv[idx+2]); } } // emit the texture to be used by the geometry that follows write_cindexmaterial(colorIndex, materialIndex); // loop over all of the triangle strips v=0; for (strip=0; strip < numstrips; strip++) { fprintf(outfile, "\nTriStrip %d\n", vertsperstrip[strip]); // loop over all triangles in this triangle strip for (i = 0; i < vertsperstrip[strip]; i++) { fprintf(outfile, "%d ", facets[v]); v++; // move on to the next triangle } } // terminate vertex array fprintf(outfile, "\nEnd_VertexArray\n"); }
void MayaDisplayDevice::triangle(const float *v1, const float *v2, const float *v3, const float *n1, const float *n2, const float *n3) { float a[3], b[3], c[3]; float norm1[3], norm2[3], norm3[3]; // transform the world coordinates (transMat.top()).multpoint3d(v1, a); (transMat.top()).multpoint3d(v2, b); (transMat.top()).multpoint3d(v3, c); // and the normals (transMat.top()).multnorm3d(n1, norm1); (transMat.top()).multnorm3d(n2, norm2); (transMat.top()).multnorm3d(n3, norm3); // draw the triangle fprintf(outfile, "createNode transform -n \"vmd%d\";\n", objnameindex); fprintf(outfile, "createNode mesh -n \"vmd%dShape\" -p \"vmd%d\";\n", objnameindex, objnameindex); fprintf(outfile, " setAttr -k off \".v\";\n"); fprintf(outfile, " setAttr -s 1 \".iog[0].og\";\n"); fprintf(outfile, " setAttr \".iog[0].og[0].gcl\" -type \"componentList\" 1 \"f[0]\";\n"); fprintf(outfile, " setAttr \".uvst[0].uvsn\" -type \"string\" \"map1\";\n"); fprintf(outfile, " setAttr \".cuvs\" -type \"string\" \"map1\";\n"); fprintf(outfile, " setAttr \".dcc\" -type \"string\" \"Ambient+Diffuse\";\n"); fprintf(outfile, " setAttr -s 3 \".vt[0:2]\" \n"); fprintf(outfile, " %f %f %f\n", a[0], a[1], a[2]); fprintf(outfile, " %f %f %f\n", b[0], b[1], b[2]); fprintf(outfile, " %f %f %f ;\n", c[0], c[1], c[2]); fprintf(outfile, " setAttr -s 3 \".ed[0:2]\" \n"); fprintf(outfile, " 0 1 0\n"); fprintf(outfile, " 1 2 0\n"); fprintf(outfile, " 2 0 0 ;\n"); fprintf(outfile, " setAttr -s 3 \".n[0:2]\" -type \"float3\" \n"); fprintf(outfile, " %f %f %f\n", norm1[0], norm1[1], norm1[2]); fprintf(outfile, " %f %f %f\n", norm2[0], norm2[1], norm2[2]); fprintf(outfile, " %f %f %f ;\n", norm3[0], norm3[1], norm3[2]); fprintf(outfile, " setAttr -s 1 \".fc[0]\" -type \"polyFaces\"\n"); fprintf(outfile, " f 3 0 1 2 ;\n"); fprintf(outfile, " setAttr \".cd\" -type \"dataPolyComponent\" Index_Data Edge 0 ;\n"); fprintf(outfile, " setAttr \".cvd\" -type \"dataPolyComponent\" Index_Data Vertex 0 ;\n"); char strbuf[1024]; sprintf(strbuf, "|vmd%d|vmd%dShape", objnameindex, objnameindex); write_cindexmaterial(strbuf, colorIndex, materialIndex); // increment object name counter objnameindex++; }
// 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])); }
// 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"); }
// use an efficient mesh primitve rather than individual triangles // when possible. void WavefrontDisplayDevice::trimesh_c4n3v3(int numverts, float * cnv, int numfacets, int * facets) { int i; float vec1[3]; float norm1[3]; const float onethird = (1.0f / 3.0f); // write out list of vertices and normals for (i=0; i<numverts; i++) { int idx = i*10; (transMat.top()).multpoint3d(cnv + idx + 7, vec1); fprintf(outfile, "v %f %f %f\n", vec1[0], vec1[1], vec1[2]); (transMat.top()).multnorm3d(cnv + idx + 4, norm1); fprintf(outfile, "vn %f %f %f\n", norm1[0], norm1[1], norm1[2]); } // loop over all of the facets in the mesh for (i=0; i<numfacets*3; i+=3) { int v0 = facets[i ]; int v1 = facets[i + 1]; int v2 = facets[i + 2]; #ifdef VMDGENMTLFILE // The Wavefront format does not allow per-vertex colors/materials, // so we use per-facet coloring, averaging the three vertex colors and // selecting the closest color from the VMD color table. const float *c1 = cnv + v0 * 10; const float *c2 = cnv + v1 * 10; const float *c3 = cnv + v2 * 10; float r, g, b; r = (c1[0] + c2[0] + c3[0]) * onethird; // average three vertex colors g = (c1[1] + c2[1] + c3[1]) * onethird; b = (c1[2] + c2[2] + c3[2]) * onethird; int cindex = nearest_index(r, g, b); write_cindexmaterial(cindex, materialIndex); #endif // use negative relative indices required for wavefront obj format v0 -= numverts; v1 -= numverts; v2 -= numverts; fprintf(outfile, "f %d//%d %d//%d %d//%d\n", v0, v0, v1, v1, v2, v2); } }
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"); }
// use an efficient mesh primitve rather than individual triangles // when possible. void TachyonDisplayDevice::trimesh_c4n3v3(int numverts, float * cnv, int numfacets, int * facets) { int i; float vec1[3]; float norm1[3]; fprintf(outfile, "VertexArray"); fprintf(outfile, " Numverts %d\n", numverts); fprintf(outfile, "\nCoords\n"); for (i=0; i<numverts; i++) { (transMat.top()).multpoint3d(cnv + i*10 + 7, vec1); fprintf(outfile, "%g %g %g\n", vec1[0], vec1[1], -vec1[2]); } fprintf(outfile, "\nNormals\n"); for (i=0; i<numverts; i++) { (transMat.top()).multnorm3d(cnv + i*10 + 4, norm1); fprintf(outfile, "%.3f %.3f %.3f\n", -norm1[0], -norm1[1], norm1[2]); } // don't emit per-vertex colors when volumetric texturing is enabled if (!involtex) { fprintf(outfile, "\nColors\n"); for (i=0; i<numverts; i++) { int idx = i * 10; fprintf(outfile, "%.3f %.3f %.3f\n", cnv[idx], cnv[idx+1], cnv[idx+2]); } } // emit the texture to be used by the geometry that follows write_cindexmaterial(colorIndex, materialIndex); // loop over all of the facets in the mesh fprintf(outfile, "\nTriMesh %d\n", numfacets); for (i=0; i<numfacets*3; i+=3) { fprintf(outfile, "%d %d %d\n", facets[i], facets[i+1], facets[i+2]); } // terminate vertex array fprintf(outfile, "\nEnd_VertexArray\n"); }
// 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++; }
///////////////////////// protected nonvirtual routines void X3DDisplayDevice::set_color(int mycolorIndex) { #if 0 write_cindexmaterial(mycolorIndex, materialIndex); #endif }
// Use a less-efficient, but X3DOM-compatible // IndexedTriangleSet primitve rather than triangle strips. void X3DOMDisplayDevice::tristrip(int numverts, const float * cnv, int numstrips, const int *vertsperstrip, const int *facets) { // render triangle strips one triangle at a time // triangle winding order is: // v0, v1, v2, then v2, v1, v3, then v2, v3, v4, etc. int i, strip, v = 0; int stripaddr[2][3] = { {0, 1, 2}, {1, 0, 2} }; fprintf(outfile, "<Shape>\n"); fprintf(outfile, " "); write_cindexmaterial(colorIndex, materialIndex); // loop over all of the facets in the mesh // emit vertex indices for each facet fprintf(outfile, " <IndexedTriangleSet solid='false' index='"); for (strip=0; strip < numstrips; strip++) { for (i=0; i<(vertsperstrip[strip] - 2); i++) { // render one triangle, using lookup table to fix winding order fprintf(outfile, "%d %d %d ", facets[v + (stripaddr[i & 0x01][0])], facets[v + (stripaddr[i & 0x01][1])], facets[v + (stripaddr[i & 0x01][2])]); v++; // move on to next vertex } v+=2; // last two vertices are already used by last triangle } fprintf(outfile, "'>\n"); // loop over all of the vertices fprintf(outfile, " <Coordinate point='"); for (i=0; i<numverts; i++) { const float *v = cnv + i*10 + 7; float tv[3]; (transMat.top()).multpoint3d(v, tv); fprintf(outfile, "%c %g %g %g", (i==0) ? ' ' : ',', tv[0], tv[1], tv[2]); } fprintf(outfile, "'/>\n"); // loop over all of the colors fprintf(outfile, " <Color color='"); for (i=0; i<numverts; i++) { const float *c = cnv + i*10; fprintf(outfile, "%c %g %g %g", (i==0) ? ' ' : ',', c[0], c[1], c[2]); } fprintf(outfile, "'/>\n"); // loop over all of the normals fprintf(outfile, " <Normal vector='"); for (i=0; i<numverts; i++) { const float *n = cnv + i*10 + 4; float tn[3]; (transMat.top()).multnorm3d(n, tn); #if 1 // reduce precision of surface normals to reduce X3D file size fprintf(outfile, "%c %.2f %.2f %.2f", (i==0) ? ' ' : ',', tn[0], tn[1], tn[2]); #else // full precision surface normals fprintf(outfile, "%c %g %g %g", (i==0) ? ' ' : ',', tn[0], tn[1], tn[2]); #endif } fprintf(outfile, "'/>\n"); fprintf(outfile, " </IndexedTriangleSet>\n"); fprintf(outfile, "</Shape>\n"); }
void MayaDisplayDevice::tricolor(const float *v1, const float *v2, const float *v3, const float *n1, const float *n2, const float *n3, const float *c1, const float *c2, const float *c3) { float a[3], b[3], c[3]; float norm1[3], norm2[3], norm3[3]; // transform the world coordinates (transMat.top()).multpoint3d(v1, a); (transMat.top()).multpoint3d(v2, b); (transMat.top()).multpoint3d(v3, c); // and the normals (transMat.top()).multnorm3d(n1, norm1); (transMat.top()).multnorm3d(n2, norm2); (transMat.top()).multnorm3d(n3, norm3); // draw the triangle fprintf(outfile, "createNode transform -n \"vmd%d\";\n", objnameindex); fprintf(outfile, "createNode mesh -n \"vmd%dShape\" -p \"vmd%d\";\n", objnameindex, objnameindex); fprintf(outfile, " setAttr -k off \".v\";\n"); fprintf(outfile, " setAttr -s 1 \".iog[0].og\";\n"); fprintf(outfile, " setAttr \".iog[0].og[0].gcl\" -type \"componentList\" 1 \"f[0]\";\n"); fprintf(outfile, " setAttr \".uvst[0].uvsn\" -type \"string\" \"map1\";\n"); fprintf(outfile, " setAttr \".cuvs\" -type \"string\" \"map1\";\n"); fprintf(outfile, " setAttr \".dcol\" yes;\n"); fprintf(outfile, " setAttr \".dcc\" -type \"string\" \"Ambient+Diffuse\";\n"); // ???? fprintf(outfile, " setAttr \".ccls\" -type \"string\" \"colorSet1\";\n"); fprintf(outfile, " setAttr \".clst[0].clsn\" -type \"string\" \"colorSet1\";\n"); #if 0 fprintf(outfile, " setAttr -s 3 \".clst[0].clsp[0:2]\" -type \"colorSet1\" \n"); fprintf(outfile, " %f %f %f 1.0\n", c1[0], c1[1], c1[2]); fprintf(outfile, " %f %f %f 1.0\n", c2[0], c2[1], c2[2]); fprintf(outfile, " %f %f %f 1.0 ;\n", c3[0], c3[1], c3[2]); #elif 0 fprintf(outfile, " setAttr -s 3 \".vclr[0].vfcl\";\n"); fprintf(outfile, " setAttr \".vclr[0].vfcl[0].frgb\" -type \"float3\" %f %f %f ;\n", c1[0], c1[1], c1[2]); fprintf(outfile, " setAttr \".vclr[0].vfcl[1].frgb\" -type \"float3\" %f %f %f ;\n", c2[0], c2[1], c2[2]); fprintf(outfile, " setAttr \".vclr[0].vfcl[2].frgb\" -type \"float3\" %f %f %f ;\n", c3[0], c3[1], c3[2]); #elif 0 fprintf(outfile, " setAttr \".vclr[0].vrgb\" -type \"float3\" "); fprintf(outfile, " %f %f %f ;\n", c1[0], c1[1], c1[2]); fprintf(outfile, " setAttr \".vclr[1].vrgb\" -type \"float3\" "); fprintf(outfile, " %f %f %f ;\n", c2[0], c2[1], c2[2]); fprintf(outfile, " setAttr \".vclr[2].vrgb\" -type \"float3\" "); fprintf(outfile, " %f %f %f ;\n", c3[0], c3[1], c3[2]); #endif fprintf(outfile, " setAttr -s 3 \".vt[0:2]\" \n"); fprintf(outfile, " %f %f %f\n", a[0], a[1], a[2]); fprintf(outfile, " %f %f %f\n", b[0], b[1], b[2]); fprintf(outfile, " %f %f %f ;\n", c[0], c[1], c[2]); #if 1 fprintf(outfile, " setAttr -s 3 \".clr[0:2]\" \n"); fprintf(outfile, " %f %f %f 1\n", c1[0], c1[1], c1[2]); fprintf(outfile, " %f %f %f 1\n", c2[0], c2[1], c2[2]); fprintf(outfile, " %f %f %f 1 ;\n", c3[0], c3[1], c3[2]); #endif fprintf(outfile, " setAttr -s 3 \".ed[0:2]\" \n"); fprintf(outfile, " 0 1 0\n"); fprintf(outfile, " 1 2 0\n"); fprintf(outfile, " 2 0 0 ;\n"); fprintf(outfile, " setAttr -s 3 \".n[0:2]\" -type \"float3\" \n"); fprintf(outfile, " %f %f %f\n", norm1[0], norm1[1], norm1[2]); fprintf(outfile, " %f %f %f\n", norm2[0], norm2[1], norm2[2]); fprintf(outfile, " %f %f %f ;\n", norm3[0], norm3[1], norm3[2]); fprintf(outfile, " setAttr -s 1 \".fc[0]\" -type \"polyFaces\"\n"); fprintf(outfile, " f 3 0 1 2 ;\n"); fprintf(outfile, " setAttr \".cd\" -type \"dataPolyComponent\" Index_Data Edge 0 ;\n"); fprintf(outfile, " setAttr \".cvd\" -type \"dataPolyComponent\" Index_Data Vertex 0 ;\n"); #if 0 fprintf(outfile, "createNode polyColorPerVertex -n \"polyColorPerVertex%d\";\n", objnameindex); fprintf(outfile, " setAttr \".uopa\" yes;\n"); fprintf(outfile, " setAttr -s 3 \".vclr\";\n"); fprintf(outfile, " setAttr -s 1 \".vclr[0].vfcl\";\n"); fprintf(outfile, " setAttr \".vclr[0].vfcl[0].frgb\" -type \"float3\" %f %f %f ;\n", c1[0], c1[1], c1[2]); fprintf(outfile, " setAttr \".vclr[1].vfcl[0].frgb\" -type \"float3\" %f %f %f ;\n", c2[0], c2[1], c2[2]); fprintf(outfile, " setAttr \".vclr[1].vfcl[0].frgb\" -type \"float3\" %f %f %f ;\n", c3[0], c3[1], c3[2]); fprintf(outfile, " setAttr \".cn\" -type \"string\" \"colorSet1\";\n"); fprintf(outfile, " setAttr \".clam\" no;\n"); // fprintf(outfile, " connectAttr \"polyColorPerVertex%d.out\" \"vmd%dShape.i\";\n", objnameindex, objnameindex); // fprintf(outfile, " connectAttr \"vmd%d.out\" \"polyColorPerVertex%d.ip\";\n", objnameindex, objnameindex); #endif char strbuf[1024]; sprintf(strbuf, "|vmd%d|vmd%dShape", objnameindex, objnameindex); write_cindexmaterial(strbuf, colorIndex, materialIndex); // increment object name counter objnameindex++; }
void TachyonDisplayDevice::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]; fprintf(outfile, "FCylinder\n"); // flat-ended cylinder fprintf(outfile, " Base %g %g %g\n", oldpt[0], oldpt[1], -oldpt[2]); fprintf(outfile, " Apex %g %g %g\n", newpt[0], newpt[1], -newpt[2]); fprintf(outfile, " Rad %g \n", textthickness); write_cindexmaterial(colorIndex, materialIndex); fprintf(outfile, "Sphere \n"); // sphere fprintf(outfile, " Center %g %g %g \n", newpt[0], newpt[1], -newpt[2]); fprintf(outfile, " Rad %g \n", textthickness); write_cindexmaterial(colorIndex, materialIndex); } else { // ...otherwise, just draw the next point fprintf(outfile, "Sphere \n"); // sphere fprintf(outfile, " Center %g %g %g \n", newpt[0], newpt[1], -newpt[2]); fprintf(outfile, " Rad %g \n", textthickness); write_cindexmaterial(colorIndex, materialIndex); } } ox=x; oy=y; odraw=draw; } textpos[0] += rm * textsize; str++; } }
///////////////////////// protected nonvirtual routines void VrmlDisplayDevice::set_color(int mycolorIndex) { write_cindexmaterial(mycolorIndex, materialIndex); }
/// draw a line from a to b void X3DDisplayDevice::line(float *a, float*b) { float ta[3], tb[3]; if (lineStyle == ::SOLIDLINE) { // transform the coordinates (transMat.top()).multpoint3d(a, ta); (transMat.top()).multpoint3d(b, tb); // ugly and wasteful, but it will work fprintf(outfile, "<Shape>\n"); fprintf(outfile, " "); write_cindexmaterial(colorIndex, materialIndex); fprintf(outfile, " <IndexedLineSet coordIndex='0 1 -1'>\n"); fprintf(outfile, " <Coordinate point='%g %g %g, %g %g %g'/>\n", ta[0], ta[1], ta[2], tb[0], tb[1], tb[2]); float col[3]; vec_copy(col, matData[colorIndex]); fprintf(outfile, " <Color color='%g %g %g, %g %g %g'/>\n", col[0], col[1], col[2], col[0], col[1], col[2]); fprintf(outfile, " </IndexedLineSet>\n"); fprintf(outfile, "</Shape>\n"); } else if (lineStyle == ::DASHEDLINE) { float dirvec[3], unitdirvec[3], tmp1[3], tmp2[3]; int i, j, test; // transform the world coordinates (transMat.top()).multpoint3d(a, tmp1); (transMat.top()).multpoint3d(b, tmp2); // how to create a dashed line vec_sub(dirvec, tmp2, tmp1); // vector from a to b vec_copy(unitdirvec, dirvec); vec_normalize(unitdirvec); // unit vector from a to b test = 1; i = 0; while (test == 1) { for (j=0; j<3; j++) { ta[j] = (float) (tmp1[j] + (2*i )*DASH_LENGTH*unitdirvec[j]); tb[j] = (float) (tmp1[j] + (2*i + 1)*DASH_LENGTH*unitdirvec[j]); } if (fabsf(tmp1[0] - tb[0]) >= fabsf(dirvec[0])) { vec_copy(tb, tmp2); test = 0; } // ugly and wasteful, but it will work fprintf(outfile, "<Shape>\n"); fprintf(outfile, " "); write_cindexmaterial(colorIndex, materialIndex); fprintf(outfile, " <IndexedLineSet coordIndex='0 1 -1'>\n"); fprintf(outfile, " <Coordinate point='%g %g %g, %g %g %g'/>\n", ta[0], ta[1], ta[2], tb[0], tb[1], tb[2]); float col[3]; vec_copy(col, matData[colorIndex]); fprintf(outfile, " <Color color='%g %g %g, %g %g %g'/>\n", col[0], col[1], col[2], col[0], col[1], col[2]); fprintf(outfile, " </IndexedLineSet>\n"); fprintf(outfile, "</Shape>\n"); i++; } } else { msgErr << "X3DDisplayDevice: Unknown line style " << lineStyle << sendmsg; } }