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: Vrml2DisplayDevice.C,v $ 00012 * $Author: johns $ $Locker: $ $State: Exp $ 00013 * $Revision: 1.47 $ $Date: 2020年07月01日 06:09:05 $ 00014 * 00015 ***************************************************************************/ 00027 #include <math.h> 00028 #include <stdlib.h> 00029 #include <stdio.h> 00030 #include <string.h> 00031 #include "Vrml2DisplayDevice.h" 00032 #include "Matrix4.h" 00033 #include "utilities.h" 00034 #include "DispCmds.h" // needed for line styles 00035 #include "Hershey.h" // needed for Hershey font rendering fctns 00036 00037 // The default radius for points and lines (which are displayed 00038 // as small spheres or cylinders, respectively) 00039 #define DEFAULT_RADIUS 0.002f 00040 #define DASH_LENGTH 0.02f 00041 00043 00044 // constructor ... initialize some variables 00045 Vrml2DisplayDevice::Vrml2DisplayDevice(void) : 00046 FileRenderer("VRML-2", "VRML 2.0 (VRML97)", "vmdscene.wrl", "true") { 00047 } 00048 00050 void Vrml2DisplayDevice::set_color(int mycolorIndex) { 00051 #if 0 00052 write_cindexmaterial(mycolorIndex, materialIndex); 00053 #endif 00054 } 00055 00056 00057 void Vrml2DisplayDevice::text(float *pos, float size, float thickness, 00058 const char *str) { 00059 float textpos[3]; 00060 hersheyhandle hh; 00061 00062 // transform the world coordinates 00063 (transMat.top()).multpoint3d(pos, textpos); 00064 float textsize = size * 1.5f; 00065 // XXX text thickness not usable with VRML2 since we don't have a line 00066 // thickness parameter when drawing indexed line sets, apparently... 00067 // float textthickness = thickness*DEFAULT_RADIUS; 00068 00069 while (*str != '0円') { 00070 float lm, rm, x, y, ox, oy; 00071 int draw, odraw; 00072 ox=oy=x=y=0.0f; 00073 draw=odraw=0; 00074 00075 hersheyDrawInitLetter(&hh, *str, &lm, &rm); 00076 textpos[0] -= lm * textsize; 00077 00078 while (!hersheyDrawNextLine(&hh, &draw, &x, &y)) { 00079 float oldpt[3], newpt[3]; 00080 if (draw) { 00081 newpt[0] = textpos[0] + textsize * x; 00082 newpt[1] = textpos[1] + textsize * y; 00083 newpt[2] = textpos[2]; 00084 00085 if (odraw) { 00086 // if we have both previous and next points, connect them... 00087 oldpt[0] = textpos[0] + textsize * ox; 00088 oldpt[1] = textpos[1] + textsize * oy; 00089 oldpt[2] = textpos[2]; 00090 00091 // ugly and wasteful, but it will work 00092 fprintf(outfile, "Shape {\n"); 00093 fprintf(outfile, " "); 00094 write_cindexmaterial(colorIndex, materialIndex); 00095 fprintf(outfile, " geometry IndexedLineSet { \n"); 00096 fprintf(outfile, " coordIndex [ 0, 1, -1 ]\n"); 00097 fprintf(outfile, " coord Coordinate { point [ %g %g %g, %g %g %g ] }\n", 00098 oldpt[0], oldpt[1], oldpt[2], newpt[0], newpt[1], newpt[2]); 00099 00100 float col[3]; 00101 vec_copy(col, matData[colorIndex]); 00102 fprintf(outfile, " color Color { color [ %.3f %.3f %.3f, %.3f %.3f %.3f ] }\n", 00103 col[0], col[1], col[2], col[0], col[1], col[2]); 00104 fprintf(outfile, " }\n"); 00105 fprintf(outfile, "}\n"); 00106 } 00107 } 00108 00109 ox=x; 00110 oy=y; 00111 odraw=draw; 00112 } 00113 textpos[0] += rm * textsize; 00114 00115 str++; 00116 } 00117 } 00118 00119 00120 // draw a sphere 00121 void Vrml2DisplayDevice::sphere(float *xyzr) { 00122 float cent[3], radius; 00123 00124 // transform the coordinates 00125 (transMat.top()).multpoint3d(xyzr, cent); 00126 radius = scale_radius(xyzr[3]); 00127 00128 fprintf(outfile, "Transform {\n"); 00129 fprintf(outfile, " translation %g %g %g\n", cent[0], cent[1], cent[2]); 00130 fprintf(outfile, " children [ Shape {\n"); 00131 fprintf(outfile, " "); 00132 write_cindexmaterial(colorIndex, materialIndex); 00133 fprintf(outfile, " geometry Sphere { radius %g }\n", radius); 00134 fprintf(outfile, " }]\n"); 00135 fprintf(outfile, "}\n"); 00136 } 00137 00138 00139 // draw a point 00140 void Vrml2DisplayDevice::point(float * xyz) { 00141 float txyz[3]; 00142 00143 // transform the coordinates 00144 (transMat.top()).multpoint3d(xyz, txyz); 00145 00146 // ugly and wasteful, but it will work 00147 fprintf(outfile, "Shape {\n"); 00148 fprintf(outfile, " "); 00149 write_cindexmaterial(colorIndex, materialIndex); 00150 00151 fprintf(outfile, " geometry PointSet { \n"); 00152 fprintf(outfile, " coord Coordinate { point [%g %g %g] }\n", 00153 txyz[0], txyz[1], txyz[2]); 00154 00155 float col[3]; 00156 vec_copy(col, matData[colorIndex]); 00157 fprintf(outfile, " color Color { color [%.3f %.3f %.3f] }\n", 00158 col[0], col[1], col[2]); 00159 fprintf(outfile, " }\n"); 00160 fprintf(outfile, "}\n"); 00161 } 00162 00163 00166 void Vrml2DisplayDevice::line(float *a, float*b) { 00167 float ta[3], tb[3]; 00168 00169 if (lineStyle == ::SOLIDLINE) { 00170 // transform the coordinates 00171 (transMat.top()).multpoint3d(a, ta); 00172 (transMat.top()).multpoint3d(b, tb); 00173 00174 // ugly and wasteful, but it will work 00175 fprintf(outfile, "Shape {\n"); 00176 fprintf(outfile, " "); 00177 write_cindexmaterial(colorIndex, materialIndex); 00178 fprintf(outfile, " geometry IndexedLineSet { \n"); 00179 fprintf(outfile, " coordIndex [ 0, 1, -1 ]\n"); 00180 fprintf(outfile, " coord Coordinate { point [ %g %g %g, %g %g %g ] }\n", 00181 ta[0], ta[1], ta[2], tb[0], tb[1], tb[2]); 00182 00183 float col[3]; 00184 vec_copy(col, matData[colorIndex]); 00185 fprintf(outfile, " color Color { color [ %.3f %.3f %.3f, %.3f %.3f %.3f ] }\n", 00186 col[0], col[1], col[2], col[0], col[1], col[2]); 00187 00188 fprintf(outfile, " }\n"); 00189 fprintf(outfile, "}\n"); 00190 } else if (lineStyle == ::DASHEDLINE) { 00191 float dirvec[3], unitdirvec[3], tmp1[3], tmp2[3]; 00192 int i, j, test; 00193 00194 // transform the world coordinates 00195 (transMat.top()).multpoint3d(a, tmp1); 00196 (transMat.top()).multpoint3d(b, tmp2); 00197 00198 // how to create a dashed line 00199 vec_sub(dirvec, tmp2, tmp1); // vector from a to b 00200 vec_copy(unitdirvec, dirvec); 00201 vec_normalize(unitdirvec); // unit vector from a to b 00202 test = 1; 00203 i = 0; 00204 while (test == 1) { 00205 for (j=0; j<3; j++) { 00206 ta[j] = (float) (tmp1[j] + (2*i )*DASH_LENGTH*unitdirvec[j]); 00207 tb[j] = (float) (tmp1[j] + (2*i + 1)*DASH_LENGTH*unitdirvec[j]); 00208 } 00209 if (fabsf(tmp1[0] - tb[0]) >= fabsf(dirvec[0])) { 00210 vec_copy(tb, tmp2); 00211 test = 0; 00212 } 00213 00214 // ugly and wasteful, but it will work 00215 fprintf(outfile, "Shape {\n"); 00216 fprintf(outfile, " "); 00217 write_cindexmaterial(colorIndex, materialIndex); 00218 fprintf(outfile, " geometry IndexedLineSet { \n"); 00219 fprintf(outfile, " coordIndex [ 0, 1, -1 ]\n"); 00220 fprintf(outfile, " coord Coordinate { point [ %g %g %g, %g %g %g ] }\n", 00221 ta[0], ta[1], ta[2], tb[0], tb[1], tb[2]); 00222 00223 float col[3]; 00224 vec_copy(col, matData[colorIndex]); 00225 fprintf(outfile, " color Color { color [ %.3f %.3f %.3f, %.3f %.3f %.3f ] }\n", 00226 col[0], col[1], col[2], col[0], col[1], col[2]); 00227 00228 fprintf(outfile, " }\n"); 00229 fprintf(outfile, "}\n"); 00230 i++; 00231 } 00232 } else { 00233 msgErr << "Vrml2DisplayDevice: Unknown line style " 00234 << lineStyle << sendmsg; 00235 } 00236 } 00237 00238 00239 // draw a cylinder 00240 void Vrml2DisplayDevice::cylinder(float *a, float *b, float r, int filled) { 00241 float ta[3], tb[3], radius; 00242 00243 // transform the coordinates 00244 (transMat.top()).multpoint3d(a, ta); 00245 (transMat.top()).multpoint3d(b, tb); 00246 radius = scale_radius(r); 00247 00248 cylinder_noxfrm(ta, tb, radius, filled); 00249 } 00250 00251 00252 void Vrml2DisplayDevice::cylinder_noxfrm(float *ta, float *tb, float radius, int filled) { 00253 if (ta[0] == tb[0] && ta[1] == tb[1] && ta[2] == tb[2]) { 00254 return; // we don't serve your kind here 00255 } 00256 00257 float height = distance(ta, tb); 00258 00259 fprintf(outfile, "Transform {\n"); 00260 fprintf(outfile, " translation %g %g %g\n", 00261 ta[0], ta[1] + (height / 2.0), ta[2]); 00262 00263 float rotaxis[3]; 00264 float cylaxdir[3]; 00265 float yaxis[3] = {0.0, 1.0, 0.0}; 00266 00267 vec_sub(cylaxdir, tb, ta); 00268 vec_normalize(cylaxdir); 00269 float dp = dot_prod(yaxis, cylaxdir); 00270 00271 cross_prod(rotaxis, cylaxdir, yaxis); 00272 vec_normalize(rotaxis); 00273 00274 // if we have decent rotation vector, use it 00275 if ((rotaxis[0]*rotaxis[0] + 00276 rotaxis[1]*rotaxis[1] + 00277 rotaxis[2]*rotaxis[2]) > 0.5) { 00278 fprintf(outfile, " center 0.0 %g 0.0\n", -(height / 2.0)); 00279 fprintf(outfile, " rotation %g %g %g %g\n", 00280 rotaxis[0], rotaxis[1], rotaxis[2], -acosf(dp)); 00281 } else if (dp < -0.98) { 00282 // if we have denormalized rotation vector, we can assume it is 00283 // caused by a cylinder axis that is nearly coaxial with the Y axis. 00284 // If this is the case, we either perform no rotation in the case of a 00285 // angle cosine near 1.0, or a 180 degree rotation for a cosine near -1. 00286 fprintf(outfile, " center 0.0 %g 0.0\n", -(height / 2.0)); 00287 fprintf(outfile, " rotation 0 0 -1 -3.14159\n"); 00288 } 00289 00290 fprintf(outfile, " children [ Shape {\n"); 00291 fprintf(outfile, " "); 00292 write_cindexmaterial(colorIndex, materialIndex); 00293 00294 #if 0 00295 // draw the cylinder 00296 fprintf(outfile, " geometry Cylinder { " 00297 "bottom %s height %g radius %g side %s top %s }\n", 00298 filled ? "TRUE" : "FALSE", 00299 height, 00300 radius, 00301 "TRUE", 00302 filled ? "TRUE" : "FALSE"); 00303 #else 00304 if (filled) { 00305 fprintf(outfile, " geometry Cylinder { " 00306 "height %g radius %g }\n", height, radius); 00307 } else { 00308 fprintf(outfile, " geometry VMDCyl { " 00309 "h %g r %g }\n", height, radius); 00310 } 00311 #endif 00312 00313 fprintf(outfile, " }]\n"); 00314 fprintf(outfile, "}\n"); 00315 } 00316 00317 00318 void Vrml2DisplayDevice::cone(float *a, float *b, float r, int /* resolution */) { 00319 float ta[3], tb[3], radius; 00320 00321 if (a[0] == b[0] && a[1] == b[1] && a[2] == b[2]) { 00322 return; // we don't serve your kind here 00323 } 00324 00325 // transform the coordinates 00326 (transMat.top()).multpoint3d(a, ta); 00327 (transMat.top()).multpoint3d(b, tb); 00328 radius = scale_radius(r); 00329 00330 float height = distance(ta, tb); 00331 00332 fprintf(outfile, "Transform {\n"); 00333 fprintf(outfile, " translation %g %g %g\n", 00334 ta[0], ta[1] + (height / 2.0), ta[2]); 00335 00336 float rotaxis[3]; 00337 float cylaxdir[3]; 00338 float yaxis[3] = {0.0, 1.0, 0.0}; 00339 00340 vec_sub(cylaxdir, tb, ta); 00341 vec_normalize(cylaxdir); 00342 float dp = dot_prod(yaxis, cylaxdir); 00343 00344 cross_prod(rotaxis, cylaxdir, yaxis); 00345 vec_normalize(rotaxis); 00346 00347 if ((rotaxis[0]*rotaxis[0] + 00348 rotaxis[1]*rotaxis[1] + 00349 rotaxis[2]*rotaxis[2]) > 0.5) { 00350 fprintf(outfile, " center 0.0 %g 0.0\n", -(height / 2.0)); 00351 fprintf(outfile, " rotation %g %g %g %g\n", 00352 rotaxis[0], rotaxis[1], rotaxis[2], -acosf(dp)); 00353 } 00354 00355 fprintf(outfile, " children [ Shape {\n"); 00356 fprintf(outfile, " "); 00357 write_cindexmaterial(colorIndex, materialIndex); 00358 00359 // draw the cone 00360 fprintf(outfile, " geometry Cone { bottomRadius %g height %g }\n", 00361 radius, height); 00362 00363 fprintf(outfile, " }]\n"); 00364 fprintf(outfile, "}\n"); 00365 } 00366 00367 00368 // draw a triangle 00369 void Vrml2DisplayDevice::triangle(const float *a, const float *b, const float *c, 00370 const float *n1, const float *n2, const float *n3) { 00371 float ta[3], tb[3], tc[3], tn1[3], tn2[3], tn3[3]; 00372 00373 // transform the world coordinates 00374 (transMat.top()).multpoint3d(a, ta); 00375 (transMat.top()).multpoint3d(b, tb); 00376 (transMat.top()).multpoint3d(c, tc); 00377 00378 // and the normals 00379 (transMat.top()).multnorm3d(n1, tn1); 00380 (transMat.top()).multnorm3d(n2, tn2); 00381 (transMat.top()).multnorm3d(n3, tn3); 00382 00383 // ugly and wasteful, but it will work 00384 fprintf(outfile, "Shape {\n"); 00385 fprintf(outfile, " "); 00386 write_cindexmaterial(colorIndex, materialIndex); 00387 fprintf(outfile, " geometry IndexedFaceSet { \n"); 00388 fprintf(outfile, " solid FALSE coordIndex [ 0, 1, 2, -1 ]\n"); 00389 fprintf(outfile, " coord Coordinate { point [ %g %g %g, %g %g %g, %g %g %g ] }\n", 00390 ta[0], ta[1], ta[2], tb[0], tb[1], tb[2], tc[0], tc[1], tc[2]); 00391 00392 fprintf(outfile, " normal Normal { vector [ %g %g %g, %g %g %g, %g %g %g ] }\n", 00393 tn1[0], tn1[1], tn1[2], tn2[0], tn2[1], tn2[2], tn3[0], tn3[1], tn3[2]); 00394 00395 fprintf(outfile, " }\n"); 00396 fprintf(outfile, "}\n"); 00397 } 00398 00399 00400 // draw a color-per-vertex triangle 00401 void Vrml2DisplayDevice::tricolor(const float * a, const float * b, const float * c, 00402 const float * n1, const float * n2, const float * n3, 00403 const float *c1, const float *c2, const float *c3) { 00404 float ta[3], tb[3], tc[3], tn1[3], tn2[3], tn3[3]; 00405 00406 // transform the world coordinates 00407 (transMat.top()).multpoint3d(a, ta); 00408 (transMat.top()).multpoint3d(b, tb); 00409 (transMat.top()).multpoint3d(c, tc); 00410 00411 // and the normals 00412 (transMat.top()).multnorm3d(n1, tn1); 00413 (transMat.top()).multnorm3d(n2, tn2); 00414 (transMat.top()).multnorm3d(n3, tn3); 00415 00416 // ugly and wasteful, but it will work 00417 fprintf(outfile, "Shape {\n"); 00418 fprintf(outfile, " "); 00419 write_cindexmaterial(colorIndex, materialIndex); 00420 fprintf(outfile, " geometry IndexedFaceSet { \n"); 00421 fprintf(outfile, " solid FALSE coordIndex [ 0, 1, 2, -1 ]\n"); 00422 fprintf(outfile, " coord Coordinate { point [ %g %g %g, %g %g %g, %g %g %g ] }\n", 00423 ta[0], ta[1], ta[2], tb[0], tb[1], tb[2], tc[0], tc[1], tc[2]); 00424 00425 fprintf(outfile, " color Color { color [ %.3f %.3f %.3f, %.3f %.3f %.3f, %.3f %.3f %.3f ] }\n", 00426 c1[0], c1[1], c1[2], c2[0], c2[1], c2[2], c3[0], c3[1], c3[2]); 00427 00428 fprintf(outfile, " normal Normal { vector [ %.3f %.3f %.3f, %.3f %.3f %.3f, %.3f %.3f %.3f ] }\n", 00429 tn1[0], tn1[1], tn1[2], tn2[0], tn2[1], tn2[2], tn3[0], tn3[1], tn3[2]); 00430 00431 fprintf(outfile, " }\n"); 00432 fprintf(outfile, "}\n"); 00433 } 00434 00435 00436 // use an efficient mesh primitve rather than individual triangles 00437 // when possible. 00438 void Vrml2DisplayDevice::trimesh_c4n3v3(int numverts, float * cnv, 00439 int numfacets, int * facets) { 00440 int i; 00441 00442 fprintf(outfile, "Shape {\n"); 00443 fprintf(outfile, " "); 00444 write_cindexmaterial(colorIndex, materialIndex); 00445 fprintf(outfile, " geometry IndexedFaceSet { \n"); 00446 00447 // loop over all of the facets in the mesh 00448 fprintf(outfile, " coordIndex [ "); 00449 for (i=0; i<numfacets*3; i+=3) { 00450 fprintf(outfile, "%c %d, %d, %d, -1", (i==0) ? ' ' : ',', 00451 facets[i], facets[i+1], facets[i+2]); 00452 } 00453 fprintf(outfile, " ]\n"); 00454 00455 // loop over all of the vertices 00456 fprintf(outfile, " coord Coordinate { point [ "); 00457 for (i=0; i<numverts; i++) { 00458 const float *v = cnv + i*10 + 7; 00459 float tv[3]; 00460 (transMat.top()).multpoint3d(v, tv); 00461 fprintf(outfile, "%c %g %g %g", (i==0) ? ' ' : ',', tv[0], tv[1], tv[2]); 00462 } 00463 fprintf(outfile, " ] }\n"); 00464 00465 // loop over all of the colors 00466 fprintf(outfile, " color Color { color [ "); 00467 for (i=0; i<numverts; i++) { 00468 const float *c = cnv + i*10; 00469 fprintf(outfile, "%c %.3f %.3f %.3f", (i==0) ? ' ' : ',', c[0], c[1], c[2]); 00470 } 00471 fprintf(outfile, " ] }\n"); 00472 00473 // loop over all of the normals 00474 fprintf(outfile, " normal Normal { vector [ "); 00475 for (i=0; i<numverts; i++) { 00476 const float *n = cnv + i*10 + 4; 00477 float tn[3]; 00478 (transMat.top()).multnorm3d(n, tn); 00479 fprintf(outfile, "%c %.3f %.3f %.3f", (i==0) ? ' ' : ',', tn[0], tn[1], tn[2]); 00480 } 00481 fprintf(outfile, " ] }\n"); 00482 00483 // close the IndexedFaceSet node 00484 fprintf(outfile, " }\n"); 00485 00486 // close the shape node 00487 fprintf(outfile, "}\n"); 00488 } 00489 00490 00491 // use an efficient mesh primitve rather than individual triangles 00492 // when possible. 00493 void Vrml2DisplayDevice::trimesh_c4u_n3b_v3f(unsigned char *c, 00494 signed char *n, 00495 float *v, int numfacets) { 00496 int i; 00497 int numverts = 3*numfacets; 00498 00499 const float ci2f = 1.0f / 255.0f; // used for uchar2float and normal conv 00500 const float cn2f = 1.0f / 127.5f; 00501 00502 fprintf(outfile, "Shape {\n"); 00503 fprintf(outfile, " "); 00504 write_cindexmaterial(colorIndex, materialIndex); 00505 fprintf(outfile, " geometry IndexedFaceSet { \n"); 00506 00507 // loop over all of the facets in the mesh 00508 fprintf(outfile, " coordIndex [ "); 00509 for (i=0; i<numfacets*3; i+=3) { 00510 fprintf(outfile, "%c %d, %d, %d, -1", (i==0) ? ' ' : ',', i, i+1, i+2); 00511 } 00512 fprintf(outfile, " ]\n"); 00513 00514 // loop over all of the vertices 00515 fprintf(outfile, " coord Coordinate { point [ "); 00516 for (i=0; i<numverts; i++) { 00517 float tv[3]; 00518 int idx = i * 3; 00519 (transMat.top()).multpoint3d(&v[idx], tv); 00520 fprintf(outfile, "%c %g %g %g", (i==0) ? ' ' : ',', tv[0], tv[1], tv[2]); 00521 } 00522 fprintf(outfile, " ] }\n"); 00523 00524 // loop over all of the colors 00525 fprintf(outfile, " color Color { color [ "); 00526 for (i=0; i<numverts; i++) { 00527 int idx = i * 4; 00528 00529 // conversion from GLubyte format, Table 2.6, p. 44 of OpenGL spec 1.2.1 00530 // float = c/(2^8-1) 00531 fprintf(outfile, "%c %.3f %.3f %.3f", 00532 (i==0) ? ' ' : ',', 00533 c[idx ] * ci2f, 00534 c[idx+1] * ci2f, 00535 c[idx+2] * ci2f); 00536 } 00537 fprintf(outfile, " ] }\n"); 00538 00539 // loop over all of the normals 00540 fprintf(outfile, " normal Normal { vector [ "); 00541 for (i=0; i<numverts; i++) { 00542 float tn[3], ntmp[3]; 00543 int idx = i * 3; 00544 00545 // conversion from GLbyte format, Table 2.6, p. 44 of OpenGL spec 1.2.1 00546 // float = (2c+1)/(2^8-1) 00547 ntmp[0] = n[idx ] * cn2f + ci2f; 00548 ntmp[1] = n[idx+1] * cn2f + ci2f; 00549 ntmp[2] = n[idx+2] * cn2f + ci2f; 00550 00551 (transMat.top()).multnorm3d(ntmp, tn); 00552 fprintf(outfile, "%c %.2f %.2f %.2f", (i==0) ? ' ' : ',', tn[0], tn[1], tn[2]); 00553 } 00554 fprintf(outfile, " ] }\n"); 00555 00556 // close the IndexedFaceSet node 00557 fprintf(outfile, " }\n"); 00558 00559 // close the shape node 00560 fprintf(outfile, "}\n"); 00561 } 00562 00563 00564 // use an efficient mesh primitve rather than individual triangles 00565 // when possible. 00566 void Vrml2DisplayDevice::tristrip(int numverts, const float * cnv, 00567 int numstrips, const int *vertsperstrip, 00568 const int *facets) { 00569 int i; 00570 // render triangle strips one triangle at a time 00571 // triangle winding order is: 00572 // v0, v1, v2, then v2, v1, v3, then v2, v3, v4, etc. 00573 int strip, v = 0; 00574 int stripaddr[2][3] = { {0, 1, 2}, {1, 0, 2} }; 00575 00576 fprintf(outfile, "Shape {\n"); 00577 fprintf(outfile, " "); 00578 write_cindexmaterial(colorIndex, materialIndex); 00579 fprintf(outfile, " geometry IndexedFaceSet { \n"); 00580 00581 // loop over all of the facets in the mesh 00582 // emit vertex indices for each facet 00583 fprintf(outfile, " coordIndex [ "); 00584 for (strip=0; strip < numstrips; strip++) { 00585 for (i=0; i<(vertsperstrip[strip] - 2); i++) { 00586 // render one triangle, using lookup table to fix winding order 00587 fprintf(outfile, "%c %d, %d, %d, -1", (i==0) ? ' ' : ',', 00588 facets[v + (stripaddr[i & 0x01][0])], 00589 facets[v + (stripaddr[i & 0x01][1])], 00590 facets[v + (stripaddr[i & 0x01][2])]); 00591 v++; // move on to next vertex 00592 } 00593 v+=2; // last two vertices are already used by last triangle 00594 } 00595 fprintf(outfile, " ]\n"); 00596 00597 // loop over all of the vertices 00598 fprintf(outfile, " coord Coordinate { point [ "); 00599 for (i=0; i<numverts; i++) { 00600 const float *v = cnv + i*10 + 7; 00601 float tv[3]; 00602 (transMat.top()).multpoint3d(v, tv); 00603 fprintf(outfile, "%c %g %g %g", (i==0) ? ' ' : ',', tv[0], tv[1], tv[2]); 00604 } 00605 fprintf(outfile, " ] }\n"); 00606 00607 // loop over all of the colors 00608 fprintf(outfile, " color Color { color [ "); 00609 for (i=0; i<numverts; i++) { 00610 const float *c = cnv + i*10; 00611 fprintf(outfile, "%c %.3f %.3f %.3f", (i==0) ? ' ' : ',', c[0], c[1], c[2]); 00612 } 00613 fprintf(outfile, " ] }\n"); 00614 00615 // loop over all of the normals 00616 fprintf(outfile, " normal Normal { vector [ "); 00617 for (i=0; i<numverts; i++) { 00618 const float *n = cnv + i*10 + 4; 00619 float tn[3]; 00620 (transMat.top()).multnorm3d(n, tn); 00621 fprintf(outfile, "%c %.3f %.3f %.3f", (i==0) ? ' ' : ',', tn[0], tn[1], tn[2]); 00622 } 00623 fprintf(outfile, " ] }\n"); 00624 00625 // close the IndexedFaceSet node 00626 fprintf(outfile, " }\n"); 00627 00628 // close the shape node 00629 fprintf(outfile, "}\n"); 00630 } 00631 00632 00633 void Vrml2DisplayDevice::multmatrix(const Matrix4 &mat) { 00634 } 00635 00636 00637 void Vrml2DisplayDevice::load(const Matrix4 &mat) { 00638 } 00639 00640 00641 void Vrml2DisplayDevice::comment(const char *s) { 00642 fprintf (outfile, "# %s\n", s); 00643 } 00644 00646 00647 // initialize the file for output 00648 void Vrml2DisplayDevice::write_header(void) { 00649 fprintf(outfile, "#VRML V2.0 utf8\n"); 00650 fprintf(outfile, "# Created with VMD: " 00651 "http://www.ks.uiuc.edu/Research/vmd/\n"); 00652 00653 // define our special node types 00654 fprintf(outfile, "# Define some custom nodes VMD to decrease file size\n"); 00655 fprintf(outfile, "# custom VMD cylinder node\n"); 00656 fprintf(outfile, "PROTO VMDCyl [\n"); 00657 fprintf(outfile, " field SFBool bottom FALSE\n"); 00658 fprintf(outfile, " field SFFloat h 2 \n"); 00659 fprintf(outfile, " field SFFloat r 1 \n"); 00660 fprintf(outfile, " field SFBool side TRUE \n"); 00661 fprintf(outfile, " field SFBool top FALSE\n"); 00662 fprintf(outfile, " ] {\n"); 00663 fprintf(outfile, " Cylinder {\n"); 00664 fprintf(outfile, " bottom IS bottom\n"); 00665 fprintf(outfile, " height IS h \n"); 00666 fprintf(outfile, " radius IS r \n"); 00667 fprintf(outfile, " top IS top \n"); 00668 fprintf(outfile, " }\n"); 00669 fprintf(outfile, "}\n\n"); 00670 00671 fprintf(outfile, "# custom VMD materials node\n"); 00672 fprintf(outfile, "PROTO VMDMat [\n"); 00673 fprintf(outfile, " field SFFloat Ka 0.0\n"); 00674 fprintf(outfile, " field SFColor Kd 0.8 0.8 0.8\n"); 00675 fprintf(outfile, " field SFColor emissiveColor 0.0 0.0 0.0\n"); 00676 fprintf(outfile, " field SFFloat Ksx 0.0\n"); 00677 fprintf(outfile, " field SFColor Ks 0.0 0.0 0.0\n"); 00678 fprintf(outfile, " field SFFloat Kt 0.0\n"); 00679 fprintf(outfile, " ] {\n"); 00680 fprintf(outfile, " Appearance {\n"); 00681 fprintf(outfile, " material Material {\n"); 00682 fprintf(outfile, " ambientIntensity IS Ka \n"); 00683 fprintf(outfile, " diffuseColor IS Kd \n"); 00684 fprintf(outfile, " emissiveColor IS emissiveColor\n"); 00685 fprintf(outfile, " shininess IS Ksx \n"); 00686 fprintf(outfile, " specularColor IS Ks \n"); 00687 fprintf(outfile, " transparency IS Kt \n"); 00688 fprintf(outfile, " }\n"); 00689 fprintf(outfile, " }\n"); 00690 fprintf(outfile, "}\n\n"); 00691 00692 fprintf(outfile, "\n"); 00693 fprintf(outfile, "# begin the actual scene\n"); 00694 fprintf(outfile, "Group {\n"); 00695 fprintf(outfile, " children [\n"); 00696 00697 if (backgroundmode == 1) { 00698 // emit background sky color gradient 00699 fprintf(outfile, "Background { skyColor [%g %g %g, %g %g %g, %g %g %g] ", 00700 backgradienttopcolor[0], // top pole 00701 backgradienttopcolor[1], 00702 backgradienttopcolor[2], 00703 (backgradienttopcolor[0]+backgradientbotcolor[0])/2.0f, // horizon 00704 (backgradientbotcolor[1]+backgradienttopcolor[1])/2.0f, 00705 (backgradienttopcolor[2]+backgradientbotcolor[2])/2.0f, 00706 backgradientbotcolor[0], // bottom pole 00707 backgradientbotcolor[1], 00708 backgradientbotcolor[2]); 00709 fprintf(outfile, "skyAngle [ 1.5, 3.0] }"); 00710 } else { 00711 // otherwise emit constant color background sky 00712 fprintf(outfile, "Background { skyColor [ %g %g %g ] }", 00713 backColor[0], backColor[1], backColor[2]); 00714 } 00715 fprintf(outfile, "\n"); 00716 } 00717 00718 void Vrml2DisplayDevice::write_trailer(void) { 00719 fprintf(outfile, " ]\n"); 00720 fprintf(outfile, "}\n"); 00721 } 00722 00723 void Vrml2DisplayDevice::write_cindexmaterial(int cindex, int material) { 00724 write_colormaterial((float *) &matData[cindex], material); 00725 } 00726 00727 void Vrml2DisplayDevice::write_colormaterial(float *rgb, int) { 00728 00729 #if 0 00730 // use the current material definition 00731 fprintf(outfile, " appearance Appearance {\n"); 00732 fprintf(outfile, " material Material {\n"); 00733 fprintf(outfile, " ambientIntensity %g\n", mat_ambient); 00734 fprintf(outfile, " diffuseColor %g %g %g\n", 00735 mat_diffuse * rgb[0], 00736 mat_diffuse * rgb[1], 00737 mat_diffuse * rgb[2]); 00738 fprintf(outfile, " shininess %g\n", mat_shininess); 00739 fprintf(outfile, " specularColor %g %g %g\n", 00740 mat_specular, 00741 mat_specular, 00742 mat_specular); 00743 fprintf(outfile, " transparency %g\n", 1.0 - mat_opacity); 00744 fprintf(outfile, " }\n"); 00745 fprintf(outfile, " }\n"); 00746 #else 00747 // use the current material definition 00748 fprintf(outfile, "appearance VMDMat { "); 00749 if (mat_ambient > 0.0) { 00750 fprintf(outfile, "Ka %g ", mat_ambient); 00751 } 00752 00753 fprintf(outfile, "Kd %g %g %g ", 00754 mat_diffuse * rgb[0], 00755 mat_diffuse * rgb[1], 00756 mat_diffuse * rgb[2]); 00757 00758 if (mat_specular > 0.0) { 00759 fprintf(outfile, "Ksx %g ", mat_shininess); 00760 fprintf(outfile, "Ks %g %g %g ", mat_specular, mat_specular, mat_specular); 00761 } 00762 00763 if (mat_opacity < 1.0) { 00764 fprintf(outfile, "Kt %g ", 1.0 - mat_opacity); 00765 } 00766 fprintf(outfile, " }\n"); 00767 #endif 00768 } 00769 00770 00771