00001 /*************************************************************************** 00002 *cr 00003 *cr (C) Copyright 1995-2019 The Board of Trustees of the 00004 *cr University of Illinois 00005 *cr All Rights Reserved 00006 *cr 00007 ***************************************************************************/ 00008 /*************************************************************************** 00009 * RCS INFORMATION: 00010 * 00011 * $RCSfile: X3DDisplayDevice.C,v $ 00012 * $Author: johns $ $Locker: $ $State: Exp $ 00013 * $Revision: 1.49 $ $Date: 2020年07月01日 06:09:05 $ 00014 * 00015 ***************************************************************************/ 00033 #include <math.h> 00034 #include <stdlib.h> 00035 #include <stdio.h> 00036 #include <string.h> 00037 #include "X3DDisplayDevice.h" 00038 #include "Matrix4.h" 00039 #include "utilities.h" 00040 #include "DispCmds.h" // needed for line styles 00041 #include "Hershey.h" // needed for Hershey font rendering fctns 00042 00043 // The default radius for points and lines (which are displayed 00044 // as small spheres or cylinders, respectively) 00045 #define DEFAULT_RADIUS 0.002f 00046 #define DASH_LENGTH 0.02f 00047 00048 // 00049 // The full X3D export subclass currently uses the following node types: 00050 // Scene, Background, OrthoViewpoint, Viewpoint, 00051 // Shape, Appearance, Material, Color, Coordinate, Normal, Transform, 00052 // LineProperties, IndexedLineSet, LineSet, 00053 // IndexedFaceSet, IndexedTriangleSet, IndexedTriangleStripSet, 00054 // Cone, Cylinder, PointSet, Sphere 00055 // ClipPlane (not quite yet) 00056 // 00057 00059 00061 X3DDisplayDevice::X3DDisplayDevice( 00062 const char *public_name, 00063 const char *public_pretty_name, 00064 const char *default_file_name, 00065 const char *default_command_line) : 00066 FileRenderer(public_name, public_pretty_name, 00067 default_file_name, default_command_line) { 00068 } 00069 00070 // constructor ... initialize some variables 00071 X3DDisplayDevice::X3DDisplayDevice(void) : 00072 FileRenderer("X3D", "X3D (XML) full specification", "vmdscene.x3d", "true") { 00073 } 00074 00076 void X3DDisplayDevice::set_color(int mycolorIndex) { 00077 #if 0 00078 write_cindexmaterial(mycolorIndex, materialIndex); 00079 #endif 00080 } 00081 00082 00083 void X3DDisplayDevice::text(float *pos, float size, float thickness, 00084 const char *str) { 00085 float textpos[3]; 00086 float textsize; 00087 hersheyhandle hh; 00088 00089 // transform the world coordinates 00090 (transMat.top()).multpoint3d(pos, textpos); 00091 textsize = size * 1.5f; 00092 00093 ResizeArray<int> idxs; 00094 ResizeArray<float> pnts; 00095 idxs.clear(); 00096 pnts.clear(); 00097 00098 int idx=0; 00099 while (*str != '0円') { 00100 float lm, rm, x, y; 00101 int draw; 00102 x=y=0.0f; 00103 draw=0; 00104 00105 hersheyDrawInitLetter(&hh, *str, &lm, &rm); 00106 textpos[0] -= lm * textsize; 00107 00108 while (!hersheyDrawNextLine(&hh, &draw, &x, &y)) { 00109 float pt[3]; 00110 00111 if (draw) { 00112 // add another connected point to the line strip 00113 idxs.append(idx); 00114 00115 pt[0] = textpos[0] + textsize * x; 00116 pt[1] = textpos[1] + textsize * y; 00117 pt[2] = textpos[2]; 00118 00119 pnts.append3(&pt[0]); 00120 00121 idx++; 00122 } else { 00123 idxs.append(-1); // pen-up, end of the line strip 00124 } 00125 } 00126 idxs.append(-1); // pen-up, end of the line strip 00127 textpos[0] += rm * textsize; 00128 str++; 00129 } 00130 00131 fprintf(outfile, "<Shape>\n"); 00132 fprintf(outfile, " "); 00133 00134 // 00135 // Emit the line properties 00136 // 00137 fprintf(outfile, "<Appearance><Material "); 00138 fprintf(outfile, "ambientIntensity='%g' ", mat_ambient); 00139 fprintf(outfile, "diffuseColor='0 0 0' "); 00140 00141 const float *rgb = matData[colorIndex]; 00142 fprintf(outfile, "emissiveColor='%.3f %.3f %.3f' ", 00143 mat_diffuse * rgb[0], mat_diffuse * rgb[1], mat_diffuse * rgb[2]); 00144 fprintf(outfile, "/>"); 00145 00146 // emit a line thickness directive, if needed 00147 if (thickness < 0.99f || thickness > 1.01f) { 00148 fprintf(outfile, " <LineProperties linewidthScaleFactor=\"%g\" " 00149 "containerField=\"lineProperties\"/>\n", 00150 (double) thickness); 00151 } 00152 fprintf(outfile, "</Appearance>\n"); 00153 00154 // 00155 // Emit the line set 00156 // 00157 fprintf(outfile, " <IndexedLineSet coordIndex='"); 00158 int i, cnt; 00159 cnt = idxs.num(); 00160 for (i=0; i<cnt; i++) { 00161 fprintf(outfile, "%d ", idxs[i]); 00162 } 00163 fprintf(outfile, "'>\n"); 00164 00165 fprintf(outfile, " <Coordinate point='"); 00166 cnt = pnts.num(); 00167 for (i=0; i<cnt; i+=3) { 00168 fprintf(outfile, "%c%g %g %g", 00169 (i==0) ? ' ' : ',', 00170 pnts[i], pnts[i+1], pnts[i+2]); 00171 } 00172 fprintf(outfile, "'/>\n"); 00173 fprintf(outfile, " </IndexedLineSet>\n"); 00174 fprintf(outfile, "</Shape>\n"); 00175 } 00176 00177 00178 // draw a sphere 00179 void X3DDisplayDevice::sphere(float *xyzr) { 00180 float cent[3], radius; 00181 00182 // transform the coordinates 00183 (transMat.top()).multpoint3d(xyzr, cent); 00184 radius = scale_radius(xyzr[3]); 00185 00186 fprintf(outfile, "<Transform translation='%g %g %g'>\n", 00187 cent[0], cent[1], cent[2]); 00188 fprintf(outfile, " <Shape>\n"); 00189 fprintf(outfile, " "); 00190 write_cindexmaterial(colorIndex, materialIndex); 00191 fprintf(outfile, " <Sphere radius='%g'/>\n", radius); 00192 fprintf(outfile, " </Shape>\n"); 00193 fprintf(outfile, "</Transform>\n"); 00194 } 00195 00196 00197 // draw a point 00198 void X3DDisplayDevice::point(float * xyz) { 00199 float txyz[3]; 00200 00201 // transform the coordinates 00202 (transMat.top()).multpoint3d(xyz, txyz); 00203 00204 // ugly and wasteful, but it will work 00205 fprintf(outfile, "<Shape>\n"); 00206 fprintf(outfile, " "); 00207 00208 // Emit the point material properties 00209 fprintf(outfile, "<Appearance><Material "); 00210 fprintf(outfile, "ambientIntensity='%g' ", mat_ambient); 00211 fprintf(outfile, "diffuseColor='0 0 0' "); 00212 00213 const float *rgb = matData[colorIndex]; 00214 fprintf(outfile, "emissiveColor='%.3f %.3f %.3f' ", 00215 mat_diffuse * rgb[0], mat_diffuse * rgb[1], mat_diffuse * rgb[2]); 00216 fprintf(outfile, "/>"); 00217 fprintf(outfile, "</Appearance>\n"); 00218 00219 fprintf(outfile, " <PointSet>\n"); 00220 fprintf(outfile, " <Coordinate point='%g %g %g'/>\n", 00221 txyz[0], txyz[1], txyz[2]); 00222 00223 float col[3]; 00224 vec_copy(col, matData[colorIndex]); 00225 fprintf(outfile, " <Color color='%.3f %.3f %.3f'/>\n", 00226 col[0], col[1], col[2]); 00227 fprintf(outfile, " </PointSet>\n"); 00228 fprintf(outfile, "</Shape>\n"); 00229 } 00230 00231 00232 // draw an array of points of the same size 00233 void X3DDisplayDevice::point_array(int num, float size, 00234 float *xyz, float *colors) { 00235 float txyz[3]; 00236 00237 // ugly and wasteful, but it will work 00238 fprintf(outfile, "<Shape>\n"); 00239 fprintf(outfile, " "); 00240 00241 // Emit the point material properties 00242 fprintf(outfile, "<Appearance><Material "); 00243 fprintf(outfile, "ambientIntensity='%g' ", mat_ambient); 00244 fprintf(outfile, "diffuseColor='0 0 0' "); 00245 fprintf(outfile, "emissiveColor='1 1 1' "); 00246 fprintf(outfile, "/>"); 00247 fprintf(outfile, "</Appearance>\n"); 00248 00249 fprintf(outfile, " <PointSet>\n"); 00250 00251 int i; 00252 fprintf(outfile, " <Coordinate point='"); 00253 for (i=0; i<num; i++) { 00254 // transform the coordinates 00255 (transMat.top()).multpoint3d(&xyz[i*3], txyz); 00256 fprintf(outfile, "%c %g %g %g", 00257 (i==0) ? ' ' : ',', 00258 txyz[0], txyz[1], txyz[2]); 00259 } 00260 fprintf(outfile, "'/>\n"); 00261 00262 fprintf(outfile, " <Color color='"); 00263 for (i=0; i<num; i++) { 00264 int cind = i*3; 00265 fprintf(outfile, "%c %.3f %.3f %.3f", 00266 (i==0) ? ' ' : ',', 00267 colors[cind], colors[cind+1], colors[cind+2]); 00268 } 00269 fprintf(outfile, "'/>\n"); 00270 00271 fprintf(outfile, " </PointSet>\n"); 00272 fprintf(outfile, "</Shape>\n"); 00273 } 00274 00275 00277 void X3DDisplayDevice::line(float *a, float*b) { 00278 float ta[3], tb[3]; 00279 00280 if (lineStyle == ::SOLIDLINE) { 00281 // transform the coordinates 00282 (transMat.top()).multpoint3d(a, ta); 00283 (transMat.top()).multpoint3d(b, tb); 00284 00285 // ugly and wasteful, but it will work 00286 fprintf(outfile, "<Shape>\n"); 00287 fprintf(outfile, " "); 00288 write_cindexmaterial(colorIndex, materialIndex); 00289 00290 fprintf(outfile, " <IndexedLineSet coordIndex='0 1 -1'>\n"); 00291 fprintf(outfile, " <Coordinate point='%g %g %g, %g %g %g'/>\n", 00292 ta[0], ta[1], ta[2], tb[0], tb[1], tb[2]); 00293 00294 float col[3]; 00295 vec_copy(col, matData[colorIndex]); 00296 fprintf(outfile, " <Color color='%.3f %.3f %.3f, %.3f %.3f %.3f'/>\n", 00297 col[0], col[1], col[2], col[0], col[1], col[2]); 00298 fprintf(outfile, " </IndexedLineSet>\n"); 00299 fprintf(outfile, "</Shape>\n"); 00300 } else if (lineStyle == ::DASHEDLINE) { 00301 float dirvec[3], unitdirvec[3], tmp1[3], tmp2[3]; 00302 int i, j, test; 00303 00304 // transform the world coordinates 00305 (transMat.top()).multpoint3d(a, tmp1); 00306 (transMat.top()).multpoint3d(b, tmp2); 00307 00308 // how to create a dashed line 00309 vec_sub(dirvec, tmp2, tmp1); // vector from a to b 00310 vec_copy(unitdirvec, dirvec); 00311 vec_normalize(unitdirvec); // unit vector from a to b 00312 test = 1; 00313 i = 0; 00314 while (test == 1) { 00315 for (j=0; j<3; j++) { 00316 ta[j] = (float) (tmp1[j] + (2*i )*DASH_LENGTH*unitdirvec[j]); 00317 tb[j] = (float) (tmp1[j] + (2*i + 1)*DASH_LENGTH*unitdirvec[j]); 00318 } 00319 if (fabsf(tmp1[0] - tb[0]) >= fabsf(dirvec[0])) { 00320 vec_copy(tb, tmp2); 00321 test = 0; 00322 } 00323 00324 // ugly and wasteful, but it will work 00325 fprintf(outfile, "<Shape>\n"); 00326 fprintf(outfile, " "); 00327 write_cindexmaterial(colorIndex, materialIndex); 00328 00329 fprintf(outfile, " <IndexedLineSet coordIndex='0 1 -1'>\n"); 00330 fprintf(outfile, " <Coordinate point='%g %g %g, %g %g %g'/>\n", 00331 ta[0], ta[1], ta[2], tb[0], tb[1], tb[2]); 00332 00333 float col[3]; 00334 vec_copy(col, matData[colorIndex]); 00335 fprintf(outfile, " <Color color='%.3f %.3f %.3f, %.3f %.3f %.3f'/>\n", 00336 col[0], col[1], col[2], col[0], col[1], col[2]); 00337 fprintf(outfile, " </IndexedLineSet>\n"); 00338 fprintf(outfile, "</Shape>\n"); 00339 i++; 00340 } 00341 } else { 00342 msgErr << "X3DDisplayDevice: Unknown line style " 00343 << lineStyle << sendmsg; 00344 } 00345 } 00346 00347 00348 void X3DDisplayDevice::line_array(int num, float thickness, float *points) { 00349 float *v = points; 00350 float txyz[3]; 00351 int i; 00352 00353 fprintf(outfile, "<Shape>\n"); 00354 fprintf(outfile, " "); 00355 00356 // Emit the line properties 00357 fprintf(outfile, "<Appearance><Material "); 00358 fprintf(outfile, "ambientIntensity='%g' ", mat_ambient); 00359 fprintf(outfile, "diffuseColor='0 0 0' "); 00360 00361 const float *rgb = matData[colorIndex]; 00362 fprintf(outfile, "emissiveColor='%g %g %g' ", 00363 mat_diffuse * rgb[0], mat_diffuse * rgb[1], mat_diffuse * rgb[2]); 00364 fprintf(outfile, "/>"); 00365 00366 // emit a line thickness directive, if needed 00367 if (thickness < 0.99f || thickness > 1.01f) { 00368 fprintf(outfile, " <LineProperties linewidthScaleFactor=\"%g\" " 00369 "containerField=\"lineProperties\"/>\n", 00370 (double) thickness); 00371 } 00372 fprintf(outfile, "</Appearance>\n"); 00373 00374 // Emit the line set 00375 fprintf(outfile, " <IndexedLineSet coordIndex='"); 00376 for (i=0; i<num; i++) { 00377 fprintf(outfile, "%d %d -1 ", i*2, i*2+1); 00378 } 00379 fprintf(outfile, "'>\n"); 00380 00381 fprintf(outfile, " <Coordinate point='"); 00382 // write two vertices for each line 00383 for (i=0; i<(num*2); i++) { 00384 // transform the coordinates 00385 (transMat.top()).multpoint3d(v, txyz); 00386 fprintf(outfile, "%c%g %g %g", 00387 (i==0) ? ' ' : ',', 00388 txyz[0], txyz[1], txyz[2]); 00389 v += 3; 00390 } 00391 fprintf(outfile, "'/>\n"); 00392 00393 fprintf(outfile, " </IndexedLineSet>\n"); 00394 fprintf(outfile, "</Shape>\n"); 00395 } 00396 00397 00398 void X3DDisplayDevice::polyline_array(int num, float thickness, float *points) { 00399 float *v = points; 00400 float txyz[3]; 00401 00402 fprintf(outfile, "<Shape>\n"); 00403 fprintf(outfile, " "); 00404 00405 // Emit the line properties 00406 fprintf(outfile, "<Appearance><Material "); 00407 fprintf(outfile, "ambientIntensity='%g' ", mat_ambient); 00408 fprintf(outfile, "diffuseColor='0 0 0' "); 00409 00410 const float *rgb = matData[colorIndex]; 00411 fprintf(outfile, "emissiveColor='%g %g %g' ", 00412 mat_diffuse * rgb[0], mat_diffuse * rgb[1], mat_diffuse * rgb[2]); 00413 fprintf(outfile, "/>"); 00414 00415 // emit a line thickness directive, if needed 00416 if (thickness < 0.99f || thickness > 1.01f) { 00417 fprintf(outfile, " <LineProperties linewidthScaleFactor=\"%g\" " 00418 "containerField=\"lineProperties\"/>\n", 00419 (double) thickness); 00420 } 00421 fprintf(outfile, "</Appearance>\n"); 00422 00423 // Emit the line set 00424 fprintf(outfile, " <LineSet vertexCount='%d'>", num); 00425 00426 fprintf(outfile, " <Coordinate point='"); 00427 for (int i=0; i<num; i++) { 00428 // transform the coordinates 00429 (transMat.top()).multpoint3d(v, txyz); 00430 fprintf(outfile, "%c%g %g %g", 00431 (i==0) ? ' ' : ',', 00432 txyz[0], txyz[1], txyz[2]); 00433 v += 3; 00434 } 00435 fprintf(outfile, "'/>\n"); 00436 00437 fprintf(outfile, " </LineSet>\n"); 00438 fprintf(outfile, "</Shape>\n"); 00439 } 00440 00441 00442 // draw a cylinder 00443 void X3DDisplayDevice::cylinder(float *a, float *b, float r, int filled) { 00444 float ta[3], tb[3], radius; 00445 00446 // transform the coordinates 00447 (transMat.top()).multpoint3d(a, ta); 00448 (transMat.top()).multpoint3d(b, tb); 00449 radius = scale_radius(r); 00450 00451 cylinder_noxfrm(ta, tb, radius, filled); 00452 } 00453 00454 00455 // draw a cylinder 00456 void X3DDisplayDevice::cylinder_noxfrm(float *ta, float *tb, float radius, int filled) { 00457 if (ta[0] == tb[0] && ta[1] == tb[1] && ta[2] == tb[2]) { 00458 return; // we don't serve your kind here 00459 } 00460 00461 float height = distance(ta, tb); 00462 00463 fprintf(outfile, "<Transform translation='%g %g %g' ", 00464 ta[0], ta[1] + (height / 2.0), ta[2]); 00465 00466 float rotaxis[3]; 00467 float cylaxdir[3]; 00468 float yaxis[3] = {0.0, 1.0, 0.0}; 00469 00470 vec_sub(cylaxdir, tb, ta); 00471 vec_normalize(cylaxdir); 00472 float dp = dot_prod(yaxis, cylaxdir); 00473 00474 cross_prod(rotaxis, cylaxdir, yaxis); 00475 vec_normalize(rotaxis); 00476 00477 // if we have decent rotation vector, use it 00478 if ((rotaxis[0]*rotaxis[0] + 00479 rotaxis[1]*rotaxis[1] + 00480 rotaxis[2]*rotaxis[2]) > 0.5) { 00481 fprintf(outfile, "center='0.0 %g 0.0' ", -(height / 2.0)); 00482 fprintf(outfile, "rotation='%g %g %g %g'", 00483 rotaxis[0], rotaxis[1], rotaxis[2], -acosf(dp)); 00484 } else if (dp < -0.98) { 00485 // if we have denormalized rotation vector, we can assume it is 00486 // caused by a cylinder axis that is nearly coaxial with the Y axis. 00487 // If this is the case, we either perform no rotation in the case of a 00488 // angle cosine near 1.0, or a 180 degree rotation for a cosine near -1. 00489 fprintf(outfile, "center='0.0 %g 0.0' ", -(height / 2.0)); 00490 fprintf(outfile, "rotation='0 0 -1 -3.14159'"); 00491 } 00492 fprintf(outfile, ">\n"); 00493 00494 fprintf(outfile, " <Shape>\n"); 00495 fprintf(outfile, " "); 00496 write_cindexmaterial(colorIndex, materialIndex); 00497 00498 // draw the cylinder 00499 fprintf(outfile, " <Cylinder " 00500 "bottom='%s' height='%g' radius='%g' side='%s' top='%s' />\n", 00501 filled ? "true" : "false", 00502 height, 00503 radius, 00504 "true", 00505 filled ? "true" : "false"); 00506 00507 fprintf(outfile, " </Shape>\n"); 00508 fprintf(outfile, "</Transform>\n"); 00509 } 00510 00511 00512 void X3DDisplayDevice::cone(float *a, float *b, float r, int /* resolution */) { 00513 float ta[3], tb[3], radius; 00514 00515 if (a[0] == b[0] && a[1] == b[1] && a[2] == b[2]) { 00516 return; // we don't serve your kind here 00517 } 00518 00519 // transform the coordinates 00520 (transMat.top()).multpoint3d(a, ta); 00521 (transMat.top()).multpoint3d(b, tb); 00522 radius = scale_radius(r); 00523 00524 float height = distance(a, b); 00525 00526 fprintf(outfile, "<Transform translation='%g %g %g' ", 00527 ta[0], ta[1] + (height / 2.0), ta[2]); 00528 00529 float rotaxis[3]; 00530 float cylaxdir[3]; 00531 float yaxis[3] = {0.0, 1.0, 0.0}; 00532 00533 vec_sub(cylaxdir, tb, ta); 00534 vec_normalize(cylaxdir); 00535 float dp = dot_prod(yaxis, cylaxdir); 00536 00537 cross_prod(rotaxis, cylaxdir, yaxis); 00538 vec_normalize(rotaxis); 00539 00540 if ((rotaxis[0]*rotaxis[0] + 00541 rotaxis[1]*rotaxis[1] + 00542 rotaxis[2]*rotaxis[2]) > 0.5) { 00543 fprintf(outfile, "center='0.0 %g 0.0' ", -(height / 2.0)); 00544 fprintf(outfile, "rotation='%g %g %g %g'", 00545 rotaxis[0], rotaxis[1], rotaxis[2], -acosf(dp)); 00546 } 00547 fprintf(outfile, ">\n"); 00548 00549 fprintf(outfile, " <Shape>\n"); 00550 fprintf(outfile, " "); 00551 write_cindexmaterial(colorIndex, materialIndex); 00552 00553 // draw the cone 00554 fprintf(outfile, " <Cone bottomRadius='%g' height='%g'/>\n", radius, height); 00555 00556 fprintf(outfile, " </Shape>\n"); 00557 fprintf(outfile, "</Transform>\n"); 00558 } 00559 00560 00561 // draw a triangle 00562 void X3DDisplayDevice::triangle(const float *a, const float *b, const float *c, 00563 const float *n1, const float *n2, const float *n3) { 00564 float ta[3], tb[3], tc[3], tn1[3], tn2[3], tn3[3]; 00565 00566 // transform the world coordinates 00567 (transMat.top()).multpoint3d(a, ta); 00568 (transMat.top()).multpoint3d(b, tb); 00569 (transMat.top()).multpoint3d(c, tc); 00570 00571 // and the normals 00572 (transMat.top()).multnorm3d(n1, tn1); 00573 (transMat.top()).multnorm3d(n2, tn2); 00574 (transMat.top()).multnorm3d(n3, tn3); 00575 00576 fprintf(outfile, "<Shape>\n"); 00577 fprintf(outfile, " "); 00578 write_cindexmaterial(colorIndex, materialIndex); 00579 fprintf(outfile, " <IndexedFaceSet solid='false' coordIndex='0 1 2 -1'>\n"); 00580 fprintf(outfile, " <Coordinate point='%g %g %g, %g %g %g, %g %g %g'/>\n", 00581 ta[0], ta[1], ta[2], tb[0], tb[1], tb[2], tc[0], tc[1], tc[2]); 00582 00583 fprintf(outfile, " <Normal vector='%g %g %g, %g %g %g, %g %g %g'/>\n", 00584 tn1[0], tn1[1], tn1[2], tn2[0], tn2[1], tn2[2], tn3[0], tn3[1], tn3[2]); 00585 fprintf(outfile, " </IndexedFaceSet>\n"); 00586 fprintf(outfile, "</Shape>\n"); 00587 } 00588 00589 00590 // draw a color-per-vertex triangle 00591 void X3DDisplayDevice::tricolor(const float * a, const float * b, const float * c, 00592 const float * n1, const float * n2, const float * n3, 00593 const float *c1, const float *c2, const float *c3) { 00594 float ta[3], tb[3], tc[3], tn1[3], tn2[3], tn3[3]; 00595 00596 // transform the world coordinates 00597 (transMat.top()).multpoint3d(a, ta); 00598 (transMat.top()).multpoint3d(b, tb); 00599 (transMat.top()).multpoint3d(c, tc); 00600 00601 // and the normals 00602 (transMat.top()).multnorm3d(n1, tn1); 00603 (transMat.top()).multnorm3d(n2, tn2); 00604 (transMat.top()).multnorm3d(n3, tn3); 00605 00606 // ugly and wasteful, but it will work 00607 fprintf(outfile, "<Shape>\n"); 00608 fprintf(outfile, " "); 00609 write_cindexmaterial(colorIndex, materialIndex); 00610 fprintf(outfile, " <IndexedFaceSet solid='false' coordIndex='0 1 2 -1'>\n"); 00611 fprintf(outfile, " <Coordinate point='%g %g %g, %g %g %g, %g %g %g'/>\n", 00612 ta[0], ta[1], ta[2], tb[0], tb[1], tb[2], tc[0], tc[1], tc[2]); 00613 00614 fprintf(outfile, " <Normal vector='%g %g %g, %g %g %g, %g %g %g'/>\n", 00615 tn1[0], tn1[1], tn1[2], tn2[0], tn2[1], tn2[2], tn3[0], tn3[1], tn3[2]); 00616 fprintf(outfile, " <Color color='%.3f %.3f %.3f, %.3f %.3f %.3f, %.3f %.3f %.3f'/>\n", 00617 c1[0], c1[1], c1[2], c2[0], c2[1], c2[2], c3[0], c3[1], c3[2]); 00618 fprintf(outfile, " </IndexedFaceSet>\n"); 00619 fprintf(outfile, "</Shape>\n"); 00620 } 00621 00622 00623 // use an efficient mesh primitve rather than individual triangles 00624 // when possible. 00625 void X3DDisplayDevice::trimesh_c4n3v3(int numverts, float * cnv, 00626 int numfacets, int * facets) { 00627 int i; 00628 00629 fprintf(outfile, "<Shape>\n"); 00630 fprintf(outfile, " "); 00631 write_cindexmaterial(colorIndex, materialIndex); 00632 00633 // loop over all of the facets in the mesh 00634 fprintf(outfile, " <IndexedTriangleSet solid='false' index='"); 00635 for (i=0; i<numfacets*3; i+=3) { 00636 fprintf(outfile, "%d %d %d ", facets[i], facets[i+1], facets[i+2]); 00637 } 00638 fprintf(outfile, "'>\n"); 00639 00640 // loop over all of the vertices 00641 fprintf(outfile, " <Coordinate point='"); 00642 for (i=0; i<numverts; i++) { 00643 const float *v = cnv + i*10 + 7; 00644 float tv[3]; 00645 (transMat.top()).multpoint3d(v, tv); 00646 fprintf(outfile, "%c %g %g %g", (i==0) ? ' ' : ',', tv[0], tv[1], tv[2]); 00647 } 00648 fprintf(outfile, "'/>\n"); 00649 00650 // loop over all of the colors 00651 fprintf(outfile, " <Color color='"); 00652 for (i=0; i<numverts; i++) { 00653 const float *c = cnv + i*10; 00654 fprintf(outfile, "%c %.3f %.3f %.3f", (i==0) ? ' ' : ',', c[0], c[1], c[2]); 00655 } 00656 fprintf(outfile, "'/>\n"); 00657 00658 // loop over all of the normals 00659 fprintf(outfile, " <Normal vector='"); 00660 for (i=0; i<numverts; i++) { 00661 const float *n = cnv + i*10 + 4; 00662 float tn[3]; 00663 (transMat.top()).multnorm3d(n, tn); 00664 00665 // reduce precision of surface normals to reduce X3D file size 00666 fprintf(outfile, "%c %.2f %.2f %.2f", (i==0) ? ' ' : ',', tn[0], tn[1], tn[2]); 00667 } 00668 fprintf(outfile, "'/>\n"); 00669 00670 fprintf(outfile, " </IndexedTriangleSet>\n"); 00671 fprintf(outfile, "</Shape>\n"); 00672 } 00673 00674 00675 // use an efficient mesh primitve rather than individual triangles 00676 // when possible. 00677 void X3DDisplayDevice::trimesh_c4u_n3b_v3f(unsigned char *c, 00678 signed char *n, 00679 float *v, int numfacets) { 00680 int i; 00681 int numverts = 3*numfacets; 00682 00683 const float ci2f = 1.0f / 255.0f; // used for uchar2float and normal conv 00684 const float cn2f = 1.0f / 127.5f; 00685 00686 fprintf(outfile, "<Shape>\n"); 00687 fprintf(outfile, " "); 00688 write_cindexmaterial(colorIndex, materialIndex); 00689 00690 #if 1 00691 fprintf(outfile, " <TriangleSet solid='false'>\n "); 00692 #else 00693 // loop over all of the facets in the mesh 00694 fprintf(outfile, " <IndexedTriangleSet solid='false' index='"); 00695 for (i=0; i<numfacets*3; i+=3) { 00696 fprintf(outfile, "%d %d %d ", i, i+1, i+2); 00697 } 00698 fprintf(outfile, "'>\n"); 00699 #endif 00700 00701 // loop over all of the vertices 00702 fprintf(outfile, " <Coordinate point='"); 00703 for (i=0; i<numverts; i++) { 00704 float tv[3]; 00705 int idx = i * 3; 00706 (transMat.top()).multpoint3d(&v[idx], tv); 00707 fprintf(outfile, "%c %g %g %g", (i==0) ? ' ' : ',', tv[0], tv[1], tv[2]); 00708 } 00709 fprintf(outfile, "'/>\n"); 00710 00711 // loop over all of the colors 00712 fprintf(outfile, " <Color color='"); 00713 for (i=0; i<numverts; i++) { 00714 int idx = i * 4; 00715 00716 // conversion from GLubyte format, Table 2.6, p. 44 of OpenGL spec 1.2.1 00717 // float = c/(2^8-1) 00718 fprintf(outfile, "%c %.3f %.3f %.3f", 00719 (i==0) ? ' ' : ',', 00720 c[idx ] * ci2f, 00721 c[idx+1] * ci2f, 00722 c[idx+2] * ci2f); 00723 } 00724 fprintf(outfile, "'/>\n"); 00725 00726 // loop over all of the normals 00727 fprintf(outfile, " <Normal vector='"); 00728 for (i=0; i<numverts; i++) { 00729 float tn[3], ntmp[3]; 00730 int idx = i * 3; 00731 00732 // conversion from GLbyte format, Table 2.6, p. 44 of OpenGL spec 1.2.1 00733 // float = (2c+1)/(2^8-1) 00734 ntmp[0] = n[idx ] * cn2f + ci2f; 00735 ntmp[1] = n[idx+1] * cn2f + ci2f; 00736 ntmp[2] = n[idx+2] * cn2f + ci2f; 00737 00738 (transMat.top()).multnorm3d(ntmp, tn); 00739 00740 // reduce precision of surface normals to reduce X3D file size 00741 fprintf(outfile, "%c %.2f %.2f %.2f", (i==0) ? ' ' : ',', tn[0], tn[1], tn[2]); 00742 } 00743 fprintf(outfile, "'/>\n"); 00744 00745 #if 1 00746 fprintf(outfile, " </TriangleSet>\n"); 00747 #else 00748 fprintf(outfile, " </IndexedTriangleSet>\n"); 00749 #endif 00750 fprintf(outfile, "</Shape>\n"); 00751 } 00752 00753 00754 00755 // use an efficient mesh primitve rather than individual triangles 00756 // when possible. 00757 void X3DDisplayDevice::tristrip(int numverts, const float * cnv, 00758 int numstrips, const int *vertsperstrip, 00759 const int *facets) { 00760 // render directly using the IndexedTriangleStripSet primitive 00761 int i, strip, v = 0; 00762 fprintf(outfile, "<Shape>\n"); 00763 fprintf(outfile, " "); 00764 write_cindexmaterial(colorIndex, materialIndex); 00765 00766 // loop over all of the facets in the mesh 00767 // emit vertex indices for each facet 00768 fprintf(outfile, " <IndexedTriangleStripSet solid='false' index='"); 00769 for (strip=0; strip < numstrips; strip++) { 00770 for (i=0; i<vertsperstrip[strip]; i++) { 00771 fprintf(outfile, "%d ", facets[v]); 00772 v++; // move on to next vertex 00773 } 00774 fprintf(outfile, "-1 "); // mark end of strip with a -1 index 00775 } 00776 fprintf(outfile, "'>\n"); 00777 00778 // loop over all of the vertices 00779 fprintf(outfile, " <Coordinate point='"); 00780 for (i=0; i<numverts; i++) { 00781 const float *v = cnv + i*10 + 7; 00782 float tv[3]; 00783 (transMat.top()).multpoint3d(v, tv); 00784 fprintf(outfile, "%c %g %g %g", (i==0) ? ' ' : ',', tv[0], tv[1], tv[2]); 00785 } 00786 fprintf(outfile, "'/>\n"); 00787 00788 // loop over all of the colors 00789 fprintf(outfile, " <Color color='"); 00790 for (i=0; i<numverts; i++) { 00791 const float *c = cnv + i*10; 00792 fprintf(outfile, "%c %.3f %.3f %.3f", (i==0) ? ' ' : ',', c[0], c[1], c[2]); 00793 } 00794 fprintf(outfile, "'/>\n"); 00795 00796 // loop over all of the normals 00797 fprintf(outfile, " <Normal vector='"); 00798 for (i=0; i<numverts; i++) { 00799 const float *n = cnv + i*10 + 4; 00800 float tn[3]; 00801 (transMat.top()).multnorm3d(n, tn); 00802 00803 // reduce precision of surface normals to reduce X3D file size 00804 fprintf(outfile, "%c %.2f %.2f %.2f", (i==0) ? ' ' : ',', tn[0], tn[1], tn[2]); 00805 } 00806 fprintf(outfile, "'/>\n"); 00807 00808 fprintf(outfile, " </IndexedTriangleStripSet>\n"); 00809 fprintf(outfile, "</Shape>\n"); 00810 } 00811 00812 00813 void X3DDisplayDevice::multmatrix(const Matrix4 &mat) { 00814 } 00815 00816 00817 void X3DDisplayDevice::load(const Matrix4 &mat) { 00818 } 00819 00820 00821 void X3DDisplayDevice::comment(const char *s) { 00822 fprintf (outfile, "<!-- %s -->\n", s); 00823 } 00824 00826 00827 // initialize the file for output 00828 void X3DDisplayDevice::write_header(void) { 00829 fprintf(outfile, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); 00830 fprintf(outfile, "<!DOCTYPE X3D PUBLIC \"ISO//Web3D//DTD X3D 3.0//EN\"\n"); 00831 fprintf(outfile, " \"http://www.web3d.org/specifications/x3d-3.0.dtd\">\n"); 00832 fprintf(outfile, "\n"); 00833 00834 // check for special features that require newer X3D versions 00835 // At present the features that require the latest X3D spec include: 00836 // - orthographic camera 00837 // - clipping planes 00838 // - various special shaders 00839 if (projection() == PERSPECTIVE) { 00840 // if we use a perspective camera, we are compatible with X3D 3.1 spec 00841 fprintf(outfile, "<X3D version='3.1' profile='Interchange'>\n"); 00842 } else { 00843 // if we use an orthographic camera, need the newest X3D 3.2 spec 00844 fprintf(outfile, "<X3D version='3.2' profile='Interchange'>\n"); 00845 } 00846 00847 fprintf(outfile, "<head>\n"); 00848 fprintf(outfile, " <meta name='description' content='VMD Molecular Graphics'/>\n"); 00849 fprintf(outfile, "</head>\n"); 00850 fprintf(outfile, "<Scene>\n"); 00851 fprintf(outfile, "<!-- Created with VMD: -->\n"); 00852 fprintf(outfile, "<!-- http://www.ks.uiuc.edu/Research/vmd/ -->\n"); 00853 00854 // export camera definition 00855 if (projection() == PERSPECTIVE) { 00856 float vfov = float(2.0*atan2((double) 0.5*vSize, (double) eyePos[2]-zDist)); 00857 if (vfov > VMD_PI) 00858 vfov=float(VMD_PI); // X3D spec disallows FOV over 180 degrees 00859 00860 fprintf(outfile, "<Viewpoint description=\"VMD Perspective View\" fieldOfView=\"%g\" orientation=\"0 0 -1 0\" position=\"%g %g %g\" centerOfRotation=\"0 0 0\" />\n", 00861 vfov, eyePos[0], eyePos[1], eyePos[2]); 00862 } else { 00863 fprintf(outfile, "<OrthoViewpoint description=\"VMD Orthographic View\" fieldOfView=\"%g %g %g %g\" orientation=\"0 0 -1 0\" position=\"%g %g %g\" centerOfRotation=\"0 0 0\" />\n", 00864 -Aspect*vSize/4, -vSize/4, Aspect*vSize/4, vSize/4, 00865 eyePos[0], eyePos[1], eyePos[2]); 00866 } 00867 00868 if (backgroundmode == 1) { 00869 // emit background sky color gradient 00870 fprintf(outfile, "<Background skyColor='%g %g %g, %g %g %g, %g %g %g' ", 00871 backgradienttopcolor[0], // top pole 00872 backgradienttopcolor[1], 00873 backgradienttopcolor[2], 00874 (backgradienttopcolor[0]+backgradientbotcolor[0])/2.0f, // horizon 00875 (backgradientbotcolor[1]+backgradienttopcolor[1])/2.0f, 00876 (backgradienttopcolor[2]+backgradientbotcolor[2])/2.0f, 00877 backgradientbotcolor[0], // bottom pole 00878 backgradientbotcolor[1], 00879 backgradientbotcolor[2]); 00880 fprintf(outfile, "skyAngle='1.5, 3.0' />"); 00881 } else { 00882 // otherwise emit constant color background sky 00883 fprintf(outfile, "<Background skyColor='%g %g %g'/>", 00884 backColor[0], backColor[1], backColor[2]); 00885 } 00886 fprintf(outfile, "\n"); 00887 } 00888 00889 void X3DDisplayDevice::write_trailer(void) { 00890 fprintf(outfile, "</Scene>\n"); 00891 fprintf(outfile, "</X3D>\n"); 00892 } 00893 00894 void X3DDisplayDevice::write_cindexmaterial(int cindex, int material) { 00895 write_colormaterial((float *) &matData[cindex], material); 00896 } 00897 00898 void X3DDisplayDevice::write_colormaterial(float *rgb, int) { 00899 // use the current material definition 00900 fprintf(outfile, "<Appearance><Material "); 00901 fprintf(outfile, "ambientIntensity='%g' ", mat_ambient); 00902 fprintf(outfile, "diffuseColor='%g %g %g' ", 00903 mat_diffuse * rgb[0], mat_diffuse * rgb[1], mat_diffuse * rgb[2]); 00904 fprintf(outfile, "shininess='%g' ", mat_shininess); 00905 fprintf(outfile, "specularColor='%g %g %g' ", 00906 mat_specular, mat_specular, mat_specular); 00907 fprintf(outfile, "transparency='%g' ", 1.0 - mat_opacity); 00908 fprintf(outfile, "/></Appearance>\n"); 00909 } 00910 00911 00912 00913 // 00914 // Export an X3D subset that is compatible with X3DOM v1.1 00915 // 00916 // The X3DOM-compatible X3D subset cannot use a few of the 00917 // nodes that may be used in the full-feature X3D export subclass: 00918 // LineSet, LineProperties, IndexedTriangleStripSet, OrthoViewpoint, 00919 // ClipPlane 00920 // 00921 // The list of nodes implemented in X3DOM v1.1 is available here: 00922 // http://x3dom.org/x3dom/release/dumpNodeTypeTree-v1.1.html 00923 // 00924 00926 00927 // constructor ... initialize some variables 00928 X3DOMDisplayDevice::X3DOMDisplayDevice(void) : 00929 X3DDisplayDevice("X3DOM", "X3D (XML) limited subset for X3DOM v1.1", "vmdscene.x3d", "true") { 00930 } 00931 00932 00933 // To write an X3DOM-compatible scene file, we cannot include 00934 // LineProperties nodes. 00935 void X3DOMDisplayDevice::line_array(int num, float thickness, float *points) { 00936 float *v = points; 00937 float txyz[3]; 00938 int i; 00939 00940 fprintf(outfile, "<Shape>\n"); 00941 fprintf(outfile, " "); 00942 00943 // Emit the line properties 00944 fprintf(outfile, "<Appearance><Material "); 00945 fprintf(outfile, "ambientIntensity='%g' ", mat_ambient); 00946 fprintf(outfile, "diffuseColor='0 0 0' "); 00947 00948 const float *rgb = matData[colorIndex]; 00949 fprintf(outfile, "emissiveColor='%g %g %g' ", 00950 mat_diffuse * rgb[0], mat_diffuse * rgb[1], mat_diffuse * rgb[2]); 00951 fprintf(outfile, "/>"); 00952 00953 #if 0 00954 // XXX X3DOM v1.1 doesn't handle LineProperties nodes 00955 // emit a line thickness directive, if needed 00956 if (thickness < 0.99f || thickness > 1.01f) { 00957 fprintf(outfile, " <LineProperties linewidthScaleFactor=\"%g\" " 00958 "containerField=\"lineProperties\"/>\n", 00959 (double) thickness); 00960 } 00961 #endif 00962 fprintf(outfile, "</Appearance>\n"); 00963 00964 // Emit the line set 00965 fprintf(outfile, " <IndexedLineSet coordIndex='"); 00966 for (i=0; i<num; i++) { 00967 fprintf(outfile, "%d %d -1 ", i*2, i*2+1); 00968 } 00969 fprintf(outfile, "'>\n"); 00970 00971 fprintf(outfile, " <Coordinate point='"); 00972 // write two vertices for each line 00973 for (i=0; i<(num*2); i++) { 00974 // transform the coordinates 00975 (transMat.top()).multpoint3d(v, txyz); 00976 fprintf(outfile, "%c%g %g %g", 00977 (i==0) ? ' ' : ',', 00978 txyz[0], txyz[1], txyz[2]); 00979 v += 3; 00980 } 00981 fprintf(outfile, "'/>\n"); 00982 00983 fprintf(outfile, " </IndexedLineSet>\n"); 00984 fprintf(outfile, "</Shape>\n"); 00985 } 00986 00987 00988 // To write an X3DOM-compatible scene file, we cannot include 00989 // LineProperties or LineSet nodes, so we use an IndexedLineSet instead. 00990 void X3DOMDisplayDevice::polyline_array(int num, float thickness, float *points) { 00991 float *v = points; 00992 float txyz[3]; 00993 int i; 00994 00995 fprintf(outfile, "<Shape>\n"); 00996 fprintf(outfile, " "); 00997 00998 // Emit the line properties 00999 fprintf(outfile, "<Appearance><Material "); 01000 fprintf(outfile, "ambientIntensity='%g' ", mat_ambient); 01001 fprintf(outfile, "diffuseColor='0 0 0' "); 01002 01003 const float *rgb = matData[colorIndex]; 01004 fprintf(outfile, "emissiveColor='%g %g %g' ", 01005 mat_diffuse * rgb[0], mat_diffuse * rgb[1], mat_diffuse * rgb[2]); 01006 fprintf(outfile, "/>"); 01007 01008 #if 0 01009 // XXX X3DOM v1.1 doesn't handle LineProperties nodes 01010 // emit a line thickness directive, if needed 01011 if (thickness < 0.99f || thickness > 1.01f) { 01012 fprintf(outfile, " <LineProperties linewidthScaleFactor=\"%g\" " 01013 "containerField=\"lineProperties\"/>\n", 01014 (double) thickness); 01015 } 01016 #endif 01017 fprintf(outfile, "</Appearance>\n"); 01018 01019 // Emit the line set 01020 // XXX X3DOM v1.1 doesn't handle LineSet nodes, 01021 // so we have to use IndexedLineSet instead 01022 fprintf(outfile, " <IndexedLineSet coordIndex='"); 01023 for (i=0; i<num; i++) { 01024 fprintf(outfile, "%d ", i); 01025 } 01026 fprintf(outfile, "'>\n"); 01027 01028 fprintf(outfile, " <Coordinate point='"); 01029 for (i=0; i<num; i++) { 01030 // transform the coordinates 01031 (transMat.top()).multpoint3d(v, txyz); 01032 fprintf(outfile, "%c%g %g %g", 01033 (i==0) ? ' ' : ',', 01034 txyz[0], txyz[1], txyz[2]); 01035 v += 3; 01036 } 01037 fprintf(outfile, "'/>\n"); 01038 01039 fprintf(outfile, " </IndexedLineSet>\n"); 01040 fprintf(outfile, "</Shape>\n"); 01041 } 01042 01043 01044 // To write an X3DOM-compatible scene file, we cannot include 01045 // LineProperties nodes. 01046 void X3DOMDisplayDevice::text(float *pos, float size, float thickness, 01047 const char *str) { 01048 float textpos[3]; 01049 float textsize; 01050 hersheyhandle hh; 01051 01052 // transform the world coordinates 01053 (transMat.top()).multpoint3d(pos, textpos); 01054 textsize = size * 1.5f; 01055 01056 ResizeArray<int> idxs; 01057 ResizeArray<float> pnts; 01058 idxs.clear(); 01059 pnts.clear(); 01060 01061 int idx=0; 01062 while (*str != '0円') { 01063 float lm, rm, x, y; 01064 int draw; 01065 x=y=0.0f; 01066 draw=0; 01067 01068 hersheyDrawInitLetter(&hh, *str, &lm, &rm); 01069 textpos[0] -= lm * textsize; 01070 01071 while (!hersheyDrawNextLine(&hh, &draw, &x, &y)) { 01072 float pt[3]; 01073 01074 if (draw) { 01075 // add another connected point to the line strip 01076 idxs.append(idx); 01077 01078 pt[0] = textpos[0] + textsize * x; 01079 pt[1] = textpos[1] + textsize * y; 01080 pt[2] = textpos[2]; 01081 01082 pnts.append3(&pt[0]); 01083 01084 idx++; 01085 } else { 01086 idxs.append(-1); // pen-up, end of the line strip 01087 } 01088 } 01089 idxs.append(-1); // pen-up, end of the line strip 01090 textpos[0] += rm * textsize; 01091 str++; 01092 } 01093 01094 fprintf(outfile, "<Shape>\n"); 01095 fprintf(outfile, " "); 01096 01097 // 01098 // Emit the line properties 01099 // 01100 fprintf(outfile, "<Appearance><Material "); 01101 fprintf(outfile, "ambientIntensity='%g' ", mat_ambient); 01102 fprintf(outfile, "diffuseColor='0 0 0' "); 01103 01104 const float *rgb = matData[colorIndex]; 01105 fprintf(outfile, "emissiveColor='%g %g %g' ", 01106 mat_diffuse * rgb[0], mat_diffuse * rgb[1], mat_diffuse * rgb[2]); 01107 fprintf(outfile, "/>"); 01108 01109 #if 0 01110 // XXX X3DOM v1.1 doesn't handle LineProperties nodes 01111 // emit a line thickness directive, if needed 01112 if (thickness < 0.99f || thickness > 1.01f) { 01113 fprintf(outfile, " <LineProperties linewidthScaleFactor=\"%g\" " 01114 "containerField=\"lineProperties\"/>\n", 01115 (double) thickness); 01116 } 01117 #endif 01118 fprintf(outfile, "</Appearance>\n"); 01119 01120 // 01121 // Emit the line set 01122 // 01123 fprintf(outfile, " <IndexedLineSet coordIndex='"); 01124 int i, cnt; 01125 cnt = idxs.num(); 01126 for (i=0; i<cnt; i++) { 01127 fprintf(outfile, "%d ", idxs[i]); 01128 } 01129 fprintf(outfile, "'>\n"); 01130 01131 fprintf(outfile, " <Coordinate point='"); 01132 cnt = pnts.num(); 01133 for (i=0; i<cnt; i+=3) { 01134 fprintf(outfile, "%c%g %g %g", 01135 (i==0) ? ' ' : ',', 01136 pnts[i], pnts[i+1], pnts[i+2]); 01137 } 01138 fprintf(outfile, "'/>\n"); 01139 fprintf(outfile, " </IndexedLineSet>\n"); 01140 fprintf(outfile, "</Shape>\n"); 01141 } 01142 01143 01144 // Use a less-efficient, but X3DOM-compatible 01145 // IndexedTriangleSet primitve rather than triangle strips. 01146 void X3DOMDisplayDevice::tristrip(int numverts, const float * cnv, 01147 int numstrips, const int *vertsperstrip, 01148 const int *facets) { 01149 // render triangle strips one triangle at a time 01150 // triangle winding order is: 01151 // v0, v1, v2, then v2, v1, v3, then v2, v3, v4, etc. 01152 int i, strip, v = 0; 01153 int stripaddr[2][3] = { {0, 1, 2}, {1, 0, 2} }; 01154 01155 fprintf(outfile, "<Shape>\n"); 01156 fprintf(outfile, " "); 01157 write_cindexmaterial(colorIndex, materialIndex); 01158 01159 // loop over all of the facets in the mesh 01160 // emit vertex indices for each facet 01161 fprintf(outfile, " <IndexedTriangleSet solid='false' index='"); 01162 for (strip=0; strip < numstrips; strip++) { 01163 for (i=0; i<(vertsperstrip[strip] - 2); i++) { 01164 // render one triangle, using lookup table to fix winding order 01165 fprintf(outfile, "%d %d %d ", 01166 facets[v + (stripaddr[i & 0x01][0])], 01167 facets[v + (stripaddr[i & 0x01][1])], 01168 facets[v + (stripaddr[i & 0x01][2])]); 01169 v++; // move on to next vertex 01170 } 01171 v+=2; // last two vertices are already used by last triangle 01172 } 01173 fprintf(outfile, "'>\n"); 01174 01175 // loop over all of the vertices 01176 fprintf(outfile, " <Coordinate point='"); 01177 for (i=0; i<numverts; i++) { 01178 const float *v = cnv + i*10 + 7; 01179 float tv[3]; 01180 (transMat.top()).multpoint3d(v, tv); 01181 fprintf(outfile, "%c %g %g %g", (i==0) ? ' ' : ',', tv[0], tv[1], tv[2]); 01182 } 01183 fprintf(outfile, "'/>\n"); 01184 01185 // loop over all of the colors 01186 fprintf(outfile, " <Color color='"); 01187 for (i=0; i<numverts; i++) { 01188 const float *c = cnv + i*10; 01189 fprintf(outfile, "%c %g %g %g", (i==0) ? ' ' : ',', c[0], c[1], c[2]); 01190 } 01191 fprintf(outfile, "'/>\n"); 01192 01193 // loop over all of the normals 01194 fprintf(outfile, " <Normal vector='"); 01195 for (i=0; i<numverts; i++) { 01196 const float *n = cnv + i*10 + 4; 01197 float tn[3]; 01198 (transMat.top()).multnorm3d(n, tn); 01199 01200 // reduce precision of surface normals to reduce X3D file size 01201 fprintf(outfile, "%c %.2f %.2f %.2f", (i==0) ? ' ' : ',', tn[0], tn[1], tn[2]); 01202 } 01203 fprintf(outfile, "'/>\n"); 01204 01205 fprintf(outfile, " </IndexedTriangleSet>\n"); 01206 fprintf(outfile, "</Shape>\n"); 01207 } 01208 01210 01211 01212