1 #include <QvElement.h>
2 #include <QvNodes.h>
3 #include <QvState.h>
4 #include <QvToWebOOGL.h>
5 #include <QvMaterialBinding.h>
6 #include <QvNormalBinding.h>
7 #include <QvUnknownNode.h>
8 #include <QvInfo.h>
9 
10 extern "C" {
11 #include <unistd.h>
12 }
13 
14 //////////////////////////////////////////////////////////////////////////////
15 //
16 // ToWebOOGL will traverse and convert any vrml object to WebOOGL!
17 // Because ToWebOOGL() is defined in the header for ALL node
18 // classes, each one has an implementation here.
19 //
20 //////////////////////////////////////////////////////////////////////////////
21 
22 // For debugging
23 static int indent = 0;
24 static int oogldepth = 0, unique = 0, mypid = 0;
25 static char out[5000];
26 static char colstr[100];
27 enum Binding {
28         DEFAULT,
29         OVERALL,
30         PER_PART,
31         PER_PART_INDEXED,
32         PER_FACE,
33         PER_FACE_INDEXED,
34         PER_VERTEX,
35         PER_VERTEX_INDEXED,
36 };
37 
38 
39 static void
OOGLannounce(const char * className)40 OOGLannounce(const char *className)
41 {
42 /*
43     for (int i = 0; i < indent; i++)
44 	fprintf(stderr,"\t");
45     fprintf(stderr,"Converting a %s to WebOOGL - depth: %d\n", className, oogldepth);
46 */
47 }
48 #define ANNOUNCE(className) OOGLannounce(QV__QUOTE(className))
49 
50 static FILE *OOGLfout = (FILE *)NULL;
51 static char *OOGLhand = NULL;
52 static char *urls[100];
53 
OOGLnumuniq()54 int OOGLnumuniq()
55 {
56   return unique;
57 }
58 
59 char *
OOGLgeturls(int i)60 OOGLgeturls(int i)
61 {
62   return urls[i];
63 }
64 
65 int
OOGLhandle(char * handle)66 OOGLhandle(char *handle)
67 {
68   OOGLhand = handle;
69   return 1;
70 }
71 
72 int
OOGLfile(FILE * fout)73 OOGLfile(FILE *fout)
74 {
75   OOGLfout = fout;
76   mypid = (int) getpid();
77   return 1;
78 }
79 
80 static void
OOGLout(const char * text)81 OOGLout(const char *text)
82 {
83     if (OOGLfout == NULL) return;
84 
85     for (int i = 1; i < indent; i++)
86 	fprintf(OOGLfout, " ");
87     fprintf(OOGLfout, "%s\n", text);
88 }
89 
90 static void
OOGLflush()91 OOGLflush()
92 {
93     if(OOGLfout != NULL)
94 	fflush(OOGLfout);
95 }
96 
97 static void
OOGLoutindent()98 OOGLoutindent()
99 {
100     if (OOGLfout == NULL) return;
101 
102     for (int i = 1; i < indent; i++)
103 	fprintf(OOGLfout, " ");
104 }
105 
106 static void
OOGLoutraw(const char * text)107 OOGLoutraw(const char *text)
108 {
109     if (OOGLfout == NULL) return;
110 
111     fprintf(OOGLfout, "%s", text);
112 }
113 
114 
115 static void
OOGLgetcolor(QvMaterial * mt,QvMaterialBinding * mtb,int mtnum)116 OOGLgetcolor(QvMaterial *mt, QvMaterialBinding *mtb, int mtnum)
117 {
118    // float *amb;
119    float *em, *dif;
120    float a;
121 
122    if (mt == NULL || mtnum < 0) { sprintf(colstr, "1 1 1 1"); return; }
123 
124    a = 1 - (mt->transparency).values[mtnum % (mt->transparency).num];
125    em = &mt->emissiveColor.values[3 * (mtnum % mt->emissiveColor.num)];
126    dif = &mt->diffuseColor.values[3 * (mtnum % mt->diffuseColor.num)];
127    if (em[0] != 0.0 || em[1] != 0.0 || em[2] != 0.0) {
128       // Funky calculations to simulate emissive color
129       float r, g, b, ln;
130       r = em[0];
131       g = em[1];
132       b = em[2];
133       ln = (3.0 - sqrt(r*r + g*g + b*b)) / 6.0;
134       r += (1.0 - r)*ln; g += (1.0 - g)*ln; b += (1.0 - b)*ln;
135       sprintf(colstr, "%.3f %.3f %.3f %.3f", r, g, b, a);
136     }
137     else
138       sprintf(colstr, "%.3f %.3f %.3f %.3f", dif[0], dif[1], dif[2], a);
139 
140 }
141 
142 static void
OOGLappearance(QvMaterial * mt)143 OOGLappearance(QvMaterial *mt)
144 {
145 
146     if (mt == NULL) return;
147 
148     OOGLout("appearance { material {");
149     sprintf(out, "ambient %f %f %f", (mt->ambientColor).values[0],
150                 (mt->ambientColor).values[1], (mt->ambientColor).values[2]);
151     OOGLout(out);
152 
153     float r, g, b, ln;
154 
155     if (!((mt->emissiveColor).values[0]==0.0 &&
156 	(mt->emissiveColor).values[1]==0.0 &&
157                 (mt->emissiveColor).values[2]==0.0))
158     {
159       // Funky calculations to simulate emissive color
160       r = (mt->emissiveColor).values[0];
161       g = (mt->emissiveColor).values[1];
162       b = (mt->emissiveColor).values[2];
163       ln = (3.0 - sqrt(r*r + g*g + b*b)) / 6.0;
164       r += (1.0 - r)*ln; g += (1.0 - g)*ln; b += (1.0 - b)*ln;
165     }
166     else {
167 	r = mt->diffuseColor.values[0];
168 	g = mt->diffuseColor.values[1];
169 	b = mt->diffuseColor.values[2];
170     }
171     sprintf(out, "diffuse %.3f %.3f %.3f  edgecolor %.3f %.3f %.3f", r, g, b, r, g, b);
172     OOGLout(out);
173 
174     sprintf(out, "specular %.3f %.3f %.3f", (mt->specularColor).values[0],
175                 (mt->specularColor).values[1], (mt->specularColor).values[2]);
176     OOGLout(out);
177     sprintf(out, "shininess %.3f", (mt->shininess).values[0]);
178     OOGLout(out);
179     sprintf(out, "alpha %.3f", 1.0 - (mt->transparency).values[0]);
180     OOGLout(out);
181 //  Doesn't work with Geomview right now
182 //  sprintf(out, "emission %f %f %f", (mt->emissiveColor).values[0],
183 //              (mt->emissiveColor).values[1], (mt->emissiveColor).values[2]);
184 
185     OOGLout(out);
186     OOGLout("}}");
187 }
188 
189 #define DEFAULT_TRAVERSE(className)					      \
190 void									      \
191 className::ToWebOOGL(QvState *)						      \
192 {									      \
193     ANNOUNCE(className);						      \
194 }
195 
196 //////////////////////////////////////////////////////////////////////////////
197 //
198 // Groups.
199 //
200 //////////////////////////////////////////////////////////////////////////////
201 
202 void
ToWebOOGL(QvState * state)203 QvGroup::ToWebOOGL(QvState *state)
204 {
205     int savedepth, i;
206 
207     ANNOUNCE(QvGroup);
208     OOGLout("{ = LIST");
209     OOGLout("# Group");
210 
211     savedepth = oogldepth;
212 
213     indent++;
214     for (i = 0; i < getNumChildren(); i++)
215 	getChild(i)->ToWebOOGL(state);
216     indent--;
217 
218     savedepth = oogldepth - savedepth; /* How deep did we get ? :-)*/
219 
220     for (i = 0; i < savedepth; i++)  { /* Do the equivalent OOGL pop */
221       out[i*2] = '}';		   /* pop the LIST */
222       out[i*2+1] = '}';		   /* pop the INST */
223     }
224 
225     out[savedepth*2] = '\0';
226     OOGLout(out);
227     OOGLout("}			# End Group");
228     oogldepth = oogldepth - savedepth;
229 }
230 
231 void
ToWebOOGL(QvState * state)232 QvLOD::ToWebOOGL(QvState *state)
233 {
234     int savedepth, i;
235 
236     ANNOUNCE(QvLOD);
237     savedepth = oogldepth;
238 
239     indent++;
240 
241     // ??? In a real implementation, this would choose a child based
242     // ??? on the projected screen areas.
243     // WebOOGL punts on this one
244 
245     if (getNumChildren() > 0)
246 	getChild(0)->ToWebOOGL(state);
247 
248     indent--;
249 
250     savedepth = oogldepth - savedepth; /* How deep did we get ? :-) */
251 
252     for (i = 0; i < savedepth; i++)  { /* Do the equivalent OOGL pop */
253       out[i*2] = '}';		   /* pop the LIST */
254       out[i*2+1] = '}';		   /* pop the INST */
255     }
256 
257     out[savedepth*2] = '\0';
258     OOGLout(out);
259     oogldepth = oogldepth - savedepth;
260 }
261 
262 void
ToWebOOGL(QvState * state)263 QvSeparator::ToWebOOGL(QvState *state)
264 {
265     int savedepth, i;
266 
267     ANNOUNCE(QvSeparator);
268 
269     OOGLout("{ = LIST		# Separator");
270     savedepth = oogldepth;
271 
272     state->push();
273     indent++;
274     for (i = 0; i < getNumChildren(); i++)
275 	getChild(i)->ToWebOOGL(state);
276     indent--;
277     state->pop();
278 
279     savedepth = oogldepth - savedepth; /* How deep did we get ? :-)*/
280 
281     for (i = 0; i < savedepth; i++)  { /* Do the equivalent OOGL pop */
282       out[i*2] = '}';		   /* pop the LIST */
283       out[i*2+1] = '}';		   /* pop the INST */
284     }
285     out[savedepth*2] = '\0';
286     OOGLout(out);
287     OOGLout("}			# End Separator");
288     oogldepth = oogldepth - savedepth;
289 }
290 
291 void
ToWebOOGL(QvState * state)292 QvSwitch::ToWebOOGL(QvState *state)
293 {
294   int savedepth, i;
295 
296 
297     ANNOUNCE(QvSwitch);
298     indent++;
299 
300     int which = (int) whichChild.value;
301 
302     savedepth = oogldepth;
303 
304     if (which == QV_SWITCH_NONE)
305 	;
306 
307     else if (which == QV_SWITCH_ALL)
308 	for (i = 0; i < getNumChildren(); i++)
309 	    getChild(i)->ToWebOOGL(state);
310 
311     else
312 	if (which < getNumChildren())
313 	    getChild(which)->ToWebOOGL(state);
314 
315     indent--;
316     savedepth = oogldepth - savedepth; /* How deep did we get ? :-)*/
317 
318     for (i = 0; i < savedepth; i++)  { /* Do the equivalent OOGL pop */
319       out[i*2] = '}';		   /* pop the LIST */
320       out[i*2+1] = '}';		   /* pop the INST */
321     }
322     out[savedepth*2] = '\0';
323     OOGLout(out);
324     oogldepth = oogldepth - savedepth;
325 }
326 
327 void
ToWebOOGL(QvState * state)328 QvTransformSeparator::ToWebOOGL(QvState *state)
329 {
330     int savedepth, i;
331 
332     ANNOUNCE(QvTransformSeparator);
333 
334     // We need to "push" just the transformation stack. We'll
335     // accomplish this by just pushing a no-op transformation onto
336     // that stack. When we "pop", we'll restore that stack to its
337     // previous state.
338 
339     QvElement *markerElt = new QvElement;
340     markerElt->data = this;
341     markerElt->type = QvElement::NoOpTransform;
342     state->addElement(QvState::TransformationIndex, markerElt);
343 
344     savedepth = oogldepth;
345 
346     indent++;
347     for (i = 0; i < getNumChildren(); i++)
348 	getChild(i)->ToWebOOGL(state);
349     indent--;
350 
351     // Now do the "pop"
352     while (state->getTopElement(QvState::TransformationIndex) != markerElt)
353 	state->popElement(QvState::TransformationIndex);
354 
355     savedepth = oogldepth - savedepth; /* How deep did we get ? :-)*/
356 
357     for (i = 0; i < savedepth; i++)  { /* Do the equivalent OOGL pop */
358       out[i*2] = '}';		   /* pop the LIST */
359       out[i*2+1] = '}';		   /* pop the INST */
360     }
361     out[savedepth*2] = '\0';
362     OOGLout(out);
363     oogldepth = oogldepth - savedepth;
364 }
365 
366 //////////////////////////////////////////////////////////////////////////////
367 //
368 // Properties.
369 //
370 //////////////////////////////////////////////////////////////////////////////
371 
372 void
ToWebOOGL(QvState * state)373 QvMaterial::ToWebOOGL(QvState *state)
374 {
375     oogldepth++;
376     ANNOUNCE(QvMaterial);
377     QvElement *elt = new QvElement;
378     elt->data = this;
379     state->addElement(QvState::MaterialIndex, elt);
380     OOGLout("{ = INST");
381     OOGLout("geom {");
382     OOGLappearance(this);
383     OOGLout("= LIST");
384 }
385 
386 #define DO_PROPERTY(className, stackIndex)				      \
387 void									      \
388 className::ToWebOOGL(QvState *state)					      \
389 {									      \
390     ANNOUNCE(className);						      \
391     QvElement *elt = new QvElement;					      \
392     elt->data = this;							      \
393     state->addElement(QvState::stackIndex, elt);			      \
394 }
395 
DO_PROPERTY(QvCoordinate3,Coordinate3Index)396 DO_PROPERTY(QvCoordinate3,		Coordinate3Index)
397 DO_PROPERTY(QvMaterialBinding,		MaterialBindingIndex)
398 DO_PROPERTY(QvNormal,			NormalIndex)
399 DO_PROPERTY(QvNormalBinding,		NormalBindingIndex)
400 DO_PROPERTY(QvShapeHints,		ShapeHintsIndex)
401 DO_PROPERTY(QvFontStyle,		FontStyleIndex)
402 
403 // WebOOGL punts on these ... (no support for texture mapping)
404 DO_PROPERTY(QvTextureCoordinate2,	TextureCoordinate2Index)
405 DO_PROPERTY(QvTexture2,			Texture2Index)
406 DO_PROPERTY(QvTexture2Transform,	Texture2TransformationIndex)
407 
408 
409 #define DO_TYPED_PROPERTY(className, stackIndex, eltType)		      \
410 void									      \
411 className::ToWebOOGL(QvState *state)					      \
412 {									      \
413     ANNOUNCE(className);						      \
414     QvElement *elt = new QvElement;					      \
415     elt->data = this;							      \
416     elt->type = QvElement::eltType;					      \
417     state->addElement(QvState::stackIndex, elt);			      \
418 }
419 
420 void
421 QvMatrixTransform::ToWebOOGL(QvState *state)
422 {
423     oogldepth++;
424     ANNOUNCE(QvMatrixTransform);
425     QvElement *elt = new QvElement;
426     elt->data = this;
427     elt->type = QvElement::MatrixTransform;
428     state->addElement(QvState::TransformationIndex, elt);
429     OOGLout("{ = INST");
430     OOGLout("transform {");
431     sprintf(out, "%f %f %f %f", matrix.value[0][0], matrix.value[0][1],
432 				matrix.value[0][2], matrix.value[0][3]);
433     OOGLout(out);
434     sprintf(out, "%f %f %f %f", matrix.value[1][0], matrix.value[1][1],
435 				matrix.value[1][2], matrix.value[1][3]);
436     OOGLout(out);
437     sprintf(out, "%f %f %f %f", matrix.value[2][0], matrix.value[2][1],
438 				matrix.value[2][2], matrix.value[2][3]);
439     OOGLout(out);
440     sprintf(out, "%f %f %f %f", matrix.value[3][0], matrix.value[3][1],
441 				matrix.value[3][2], matrix.value[3][3]);
442     OOGLout(out);
443     OOGLout("} geom");
444     OOGLout("{ = LIST");
445 }
446 
OOGLoutmat(QvSFMatrix * mat1)447 static void OOGLoutmat(QvSFMatrix *mat1)
448 {
449   int y;
450 
451   for (y = 0; y < 4; y++) {
452     sprintf(out, "%f %f %f %f", mat1->value[0][y], mat1->value[1][y],
453 	    mat1->value[2][y], mat1->value[3][y]);
454     OOGLout(out);
455   }
456 }
457 
OOGLmat_init(QvSFMatrix * mat1)458 static void OOGLmat_init(QvSFMatrix *mat1)
459 {
460   int x, y;
461 
462   for (x = 0; x < 4; x++)
463     for (y = 0; y < 4; y++) {
464       if (x == y)
465 	mat1->value[x][y] = 1.0;
466       else
467 	mat1->value[x][y] = 0.0;
468     }
469 }
470 
OOGLmat_mult(QvSFMatrix * mat1,QvSFMatrix * mat2,QvSFMatrix * result)471 static void OOGLmat_mult(QvSFMatrix *mat1, QvSFMatrix *mat2,
472 				QvSFMatrix *result)
473 {
474   int x,y;
475 
476   for (y = 0; y < 4; y++) {
477     for (x = 0; x < 4; x++) {
478       result->value[x][y] = mat1->value[0][y] * mat2->value[x][0]
479       + mat1->value[1][y] * mat2->value[x][1]
480       + mat1->value[2][y] * mat2->value[x][2]
481       + mat1->value[3][y] * mat2->value[x][3];
482 
483     }
484   }
485 }
486 
OOGLmat_scale(QvSFMatrix * mat1,float xt,float yt,float zt)487 static void OOGLmat_scale(QvSFMatrix *mat1, float xt, float yt, float zt)
488 {
489   int x, y;
490 
491   for (x = 0; x < 4; x++)
492     for (y = 0; y < 4; y++) {
493       if (x == y)
494 	mat1->value[x][y] = 1.0;
495       else
496 	mat1->value[x][y] = 0.0;
497     }
498   mat1->value[0][0] = xt; mat1->value[1][1] = yt; mat1->value[2][2] = zt;
499 
500 }
501 
OOGLmat_trans(QvSFMatrix * mat1,float xt,float yt,float zt)502 static void OOGLmat_trans(QvSFMatrix *mat1, float xt, float yt, float zt)
503 {
504   int x, y;
505 
506   for (x = 0; x < 4; x++)
507     for (y = 0; y < 4; y++) {
508       if (x == y)
509 	mat1->value[x][y] = 1.0;
510       else
511 	mat1->value[x][y] = 0.0;
512     }
513 
514    mat1->value[0][3] = xt;
515    mat1->value[1][3] = yt;
516    mat1->value[2][3] = zt;
517 }
518 
OOGLmat_rot(QvSFMatrix * mat1,float angle,float * rotaxis)519 static void OOGLmat_rot(QvSFMatrix *mat1, float angle, float *rotaxis)
520 {
521     float csA, snA, vsA, s;
522     float axis[3];
523 
524     OOGLmat_init(mat1);
525     s = rotaxis[0]*rotaxis[0] + rotaxis[1]*rotaxis[1] + rotaxis[2]*rotaxis[2];
526     if(s == 0. || angle == 0.)
527 	return;
528 
529     s = 1/sqrt(s);
530     axis[0] = rotaxis[0]*s;
531     axis[1] = rotaxis[1]*s;
532     axis[2] = rotaxis[2]*s;
533     csA = cos(angle); snA = -sin(angle); vsA = 1 - csA;
534 
535     mat1->value[0][0] = axis[0]*axis[0]*vsA + csA;
536     mat1->value[1][0] = axis[0]*axis[1]*vsA - axis[2]*snA;
537     mat1->value[2][0] = axis[0]*axis[2]*vsA + axis[1]*snA;
538 
539     mat1->value[0][1] = axis[1]*axis[0]*vsA + axis[2]*snA;
540     mat1->value[1][1] = axis[1]*axis[1]*vsA + csA;
541     mat1->value[2][1] = axis[1]*axis[2]*vsA - axis[0]*snA;
542 
543     mat1->value[0][2] = axis[2]*axis[0]*vsA - axis[1]*snA;
544     mat1->value[1][2] = axis[2]*axis[1]*vsA + axis[0]*snA;
545     mat1->value[2][2] = axis[2]*axis[2]*vsA + csA;
546 }
547 
548 void
ToWebOOGL(QvState * state)549 QvTransform::ToWebOOGL(QvState *state) // NOT RIGHT YET
550 {
551     QvSFMatrix mat1, mat2, mat3;
552 
553     OOGLmat_init(&mat1); OOGLmat_init(&mat2); OOGLmat_init(&mat3);
554 
555     OOGLmat_trans(&mat2, -center.value[0], -center.value[1], -center.value[2]);
556     OOGLmat_mult(&mat1, &mat2, &mat3);
557     OOGLmat_rot(&mat2, scaleOrientation.angle, scaleOrientation.axis);
558     OOGLmat_mult(&mat3, &mat2, &mat1);
559     OOGLmat_scale(&mat2, scaleFactor.value[0], scaleFactor.value[1],
560 		  scaleFactor.value[2]);
561     OOGLmat_mult(&mat1, &mat2, &mat3);
562     OOGLmat_rot(&mat2, -scaleOrientation.angle, scaleOrientation.axis);
563     OOGLmat_mult(&mat3, &mat2, &mat1);
564     OOGLmat_rot(&mat2, rotation.angle, rotation.axis);
565     OOGLmat_mult(&mat1, &mat2, &mat3);
566     OOGLmat_trans(&mat2, center.value[0], center.value[1], center.value[2]);
567     OOGLmat_mult(&mat3, &mat2, &mat1);
568     OOGLmat_trans(&mat2, translation.value[0], translation.value[1],
569 		  translation.value[2]);
570     OOGLmat_mult(&mat1, &mat2, &mat3);
571 
572     oogldepth++;
573     ANNOUNCE(QvTransform);
574     QvElement *elt = new QvElement;
575     elt->data = this;
576     elt->type = QvElement::Transform;
577     state->addElement(QvState::TransformationIndex, elt);
578     OOGLout("{ = INST");
579     OOGLout("transform {\t# VRML Transform");
580     OOGLoutmat(&mat3);
581     OOGLout("} geom");
582     OOGLout("{ = LIST");
583 }
584 
585 void
ToWebOOGL(QvState * state)586 QvRotation::ToWebOOGL(QvState *state)
587 {
588     QvElement *elt = new QvElement;
589     QvSFMatrix mat1;
590 
591     oogldepth++;
592     ANNOUNCE(QvRotation);
593 
594     OOGLmat_init(&mat1);
595     OOGLmat_rot(&mat1, rotation.angle, rotation.axis);
596 
597     elt->data = this;
598     elt->type = QvElement::Rotation;
599     state->addElement(QvState::TransformationIndex, elt);
600 
601     OOGLout("{ = INST");
602     OOGLout("transform {");
603     OOGLoutmat(&mat1);
604     OOGLout("} geom");
605     OOGLout("{ = LIST");
606 }
607 
608 void
ToWebOOGL(QvState * state)609 QvTranslation::ToWebOOGL(QvState *state)
610 {
611     QvSFMatrix mat1;
612 
613     oogldepth++;
614     ANNOUNCE(QvTranslation);
615     QvElement *elt = new QvElement;
616     elt->data = this;
617     elt->type = QvElement::Translation;
618     state->addElement(QvState::TransformationIndex, elt);
619 
620     OOGLmat_trans(&mat1, translation.value[0], translation.value[1],
621 		  translation.value[2]);
622     OOGLout("{ = INST");
623     OOGLout("transform {");
624     OOGLoutmat(&mat1);
625     OOGLout("} geom");
626     OOGLout("{ = LIST");
627 }
628 
629 void
ToWebOOGL(QvState * state)630 QvScale::ToWebOOGL(QvState *state)
631 {
632     oogldepth++;
633     ANNOUNCE(QvScale);
634     QvElement *elt = new QvElement;
635     elt->data = this;
636     elt->type = QvElement::Scale;
637     state->addElement(QvState::TransformationIndex, elt);
638     OOGLout("{ = INST");
639     OOGLout("transform {");
640     sprintf(out, "%f 0 0 0", scaleFactor.value[0]);
641     OOGLout(out);
642     sprintf(out, "0 %f 0 0", scaleFactor.value[1]);
643     OOGLout(out);
644     sprintf(out, "0 0 %f 0", scaleFactor.value[2]);
645     OOGLout(out);
646     OOGLout("0 0 0 1");
647     OOGLout("} geom");
648     OOGLout("{ = LIST");
649 }
650 
DO_TYPED_PROPERTY(QvDirectionalLight,LightIndex,DirectionalLight)651 DO_TYPED_PROPERTY(QvDirectionalLight,	LightIndex, DirectionalLight)
652 DO_TYPED_PROPERTY(QvPointLight,		LightIndex, PointLight)
653 DO_TYPED_PROPERTY(QvSpotLight,		LightIndex, SpotLight)
654 
655 DO_TYPED_PROPERTY(QvOrthographicCamera,	CameraIndex, OrthographicCamera)
656 DO_TYPED_PROPERTY(QvPerspectiveCamera,	CameraIndex, PerspectiveCamera)
657 
658 //////////////////////////////////////////////////////////////////////////////
659 //
660 // Shapes.
661 //
662 //////////////////////////////////////////////////////////////////////////////
663 
664 static void
665 OOGLprintProperties(QvState *state)
666 {
667 //  printf("--------------------------------------------------------------\n");
668 //  state->print();
669 //  printf("--------------------------------------------------------------\n");
670 }
671 
672 void
ToWebOOGL(QvState * state)673 QvCone::ToWebOOGL(QvState *state)
674 {
675     ANNOUNCE(QvCone);
676     OOGLout("# VRML Cone");
677     OOGLout("{ = BEZ224");
678     if (parts.value == ALL || parts.value == SIDES)
679     {
680       sprintf(out, "0 %f 0 1\t0 0 0 0\t0 %f 0 1", height.value/2.0,
681 	height.value/2.0);
682       OOGLout(out);
683       sprintf(out, "%f 0 0 1\t0 0 %f 0\t%f 0 0 1", -bottomRadius.value/2.0,
684         bottomRadius.value/2.0, bottomRadius.value/2.0);
685       OOGLout(out);
686       sprintf(out, "%f %f 0 1\t0 0 %f 0\t%f %f 0 1\n", -bottomRadius.value,
687         -height.value/2.0, bottomRadius.value, bottomRadius.value,
688 	-height.value/2.0);
689       OOGLout(out);
690 
691       sprintf(out, "%f %f 0 1\t0 0 %f 0\t%f %f 0 1", -bottomRadius.value,
692         -height.value/2.0, -bottomRadius.value, bottomRadius.value,
693 	-height.value/2.0);
694       OOGLout(out);
695       sprintf(out, "%f 0 0 1\t0 0 %f 0\t%f 0 0 1", -bottomRadius.value/2.0,
696         -bottomRadius.value/2.0, bottomRadius.value/2.0);
697       OOGLout(out);
698       sprintf(out, "0 %f 0 1\t0 0 0 0\t0 %f 0 1\n", height.value/2.0,
699 	height.value/2.0);
700       OOGLout(out);
701     }
702     if (parts.value == ALL || parts.value == BOTTOM)
703     {
704       sprintf(out, "0 %f 0 1\t0 0 0 0\t0 %f 0 1", -height.value/2.0,
705         -height.value/2.0);
706       OOGLout(out);
707       sprintf(out, "%f %f 0 1\t0 0 %f 0\t%f %f 0 1", -bottomRadius.value/2.0,
708         -height.value/2.0, bottomRadius.value/2.0,
709         bottomRadius.value/2.0, -height.value/2.0);
710       OOGLout(out);
711       sprintf(out, "%f %f 0 1\t0 0 %f 0\t%f %f 0 1\n", -bottomRadius.value,
712         -height.value/2.0, bottomRadius.value, bottomRadius.value,
713 	-height.value/2.0);
714       OOGLout(out);
715 
716       sprintf(out, "%f %f 0 1\t0 0 %f 0\t%f %f 0 1", -bottomRadius.value,
717         -height.value/2.0, -bottomRadius.value, bottomRadius.value,
718 	-height.value/2.0);
719       OOGLout(out);
720       sprintf(out, "%f %f 0 1\t0 0 %f 0\t%f %f 0 1", -bottomRadius.value/2.0,
721         -height.value/2.0, -bottomRadius.value/2.0,
722         bottomRadius.value/2.0, -height.value/2.0);
723       OOGLout(out);
724       sprintf(out, "0 %f 0 1\t0 0 0 0\t0 %f 0 1\n", -height.value/2.0,
725         -height.value/2.0);
726       OOGLout(out);
727     }
728     OOGLout("}");
729 }
730 
731 void
ToWebOOGL(QvState * state)732 QvCube::ToWebOOGL(QvState *state)
733 {
734     float x = width.value / 2.0, y = height.value / 2.0, z = depth.value / 2.0;
735     int i;
736 
737     ANNOUNCE(QvCube);
738     OOGLout("# VRML Cube");
739     OOGLout("{ = OFF");
740     OOGLout("8 6 12");
741     for(i = 0; i < 8; i++) {
742 	sprintf(out, "%g %g %g", i&1 ? -x : x, i&2 ? -y : y, i&4 ? -z : z);
743 	OOGLout(out);
744     }
745     OOGLout("4  3 2 1 0");
746     OOGLout("4  4 5 6 7");
747     OOGLout("4  2 3 7 6");
748     OOGLout("4  0 1 5 4");
749     OOGLout("4  0 4 7 3");
750     OOGLout("4  1 2 6 5");
751     OOGLout("}");
752 }
753 
754 void
ToWebOOGL(QvState * state)755 QvCylinder::ToWebOOGL(QvState *state)
756 {
757     QvElement *elt = NULL;
758     QvMaterial *qv_material = NULL;
759     QvMaterialBinding *qv_materialb = NULL;
760     Binding mb_val;
761 
762     elt = state->getTopElement(QvState::MaterialIndex);
763     if (elt) { qv_material = (QvMaterial *)elt->data;}
764     elt = state->getTopElement(QvState::MaterialBindingIndex);
765     if (elt) { qv_materialb = (QvMaterialBinding *)elt->data; }
766 
767     if (qv_materialb) { mb_val = (Binding) qv_materialb->value.value; }
768     else { mb_val = DEFAULT; }
769 
770     ANNOUNCE(QvCylinder);
771     OOGLout("# VRML Cylinder");
772     OOGLout("{");
773     if (mb_val != PER_PART && mb_val != PER_PART_INDEXED)
774     {
775 	OOGLappearance(qv_material);
776 	OOGLout("= BEZ224");
777     } else {
778 	OOGLout("= CBEZ224");
779     }
780 
781     colstr[0] = '\0';
782     if (parts.value == ALL || parts.value == SIDES)
783     {
784       sprintf(out, "%f %f 0 1\t0 0 %f 0\t%f %f 0 1", -radius.value,
785 	height.value/2.0, radius.value, radius.value, height.value/2.0);
786       OOGLout(out);
787       sprintf(out, "%f 0 0 1\t0 0 %f 0\t%f 0 0 1", -radius.value,
788 	radius.value, radius.value);
789       OOGLout(out);
790       sprintf(out, "%f %f 0 1\t0 0 %f 0\t%f %f 0 1\n", -radius.value,
791 	-height.value/2.0, radius.value, radius.value, -height.value/2.0);
792       OOGLout(out);
793 
794       sprintf(out, "%f %f 0 1\t0 0 %f 0\t%f %f 0 1", -radius.value,
795 	-height.value/2.0, -radius.value, radius.value, -height.value/2.0);
796       OOGLout(out);
797       sprintf(out, "%f 0 0 1\t0 0 %f 0\t%f 0 0 1", -radius.value,
798 	-radius.value, radius.value);
799       OOGLout(out);
800       sprintf(out, "%f %f 0 1\t0 0 %f 0\t%f %f 0 1", -radius.value,
801 	height.value/2.0, -radius.value, radius.value, height.value/2.0);
802       OOGLout(out);
803 
804       if (mb_val == PER_PART || mb_val == PER_PART_INDEXED) {
805         OOGLgetcolor(qv_material, qv_materialb, 0);
806 	sprintf(out, "%s %s %s %s\n", colstr, colstr, colstr, colstr);
807 	OOGLout(out);
808       }
809 
810     }
811     if (parts.value == TOP || parts.value == ALL)
812     {
813       sprintf(out, "0 %f 0 1\t0 0 0 0\t0 %f 0 1", height.value/2.0,
814 	height.value/2.0);
815       OOGLout(out);
816       sprintf(out, "%f %f 0 1\t0 0 %f 0\t%f %f 0 1", -radius.value/2.0,
817 	height.value/2.0, radius.value/2.0,
818 	radius.value/2.0, height.value/2.0);
819       OOGLout(out);
820       sprintf(out, "%f %f 0 1\t0 0 %f 0\t%f %f 0 1\n", -radius.value,
821 	height.value/2.0, radius.value, radius.value, height.value/2.0);
822       OOGLout(out);
823 
824       sprintf(out, "%f %f 0 1\t0 0 %f 0\t%f %f 0 1", -radius.value,
825 	height.value/2.0, -radius.value, radius.value, height.value/2.0);
826       OOGLout(out);
827       sprintf(out, "%f %f 0 1\t0 0 %f 0\t%f %f 0 1", -radius.value/2.0,
828 	height.value/2.0, -radius.value/2.0,
829 	radius.value/2.0, height.value/2.0);
830       OOGLout(out);
831       sprintf(out, "0 %f 0 1\t0 0 0 0\t0 %f 0 1", height.value/2.0,
832 	height.value/2.0);
833       OOGLout(out);
834 
835       if (mb_val == PER_PART || mb_val == PER_PART_INDEXED) {
836         OOGLgetcolor(qv_material, qv_materialb, 1);
837 	sprintf(out, "%s %s %s %s\n", colstr, colstr, colstr, colstr);
838 	OOGLout(out);
839       }
840     }
841 
842     if (parts.value == BOTTOM || parts.value == ALL)
843     {
844       sprintf(out, "0 %f 0 1\t0 0 0 0\t0 %f 0 1", -height.value/2.0,
845         -height.value/2.0);
846       OOGLout(out);
847       sprintf(out, "%f %f 0 1\t0 0 %f 0\t%f %f 0 1", -radius.value/2.0,
848         -height.value/2.0, radius.value/2.0,
849         radius.value/2.0, -height.value/2.0);
850       OOGLout(out);
851       sprintf(out, "%f %f 0 1\t0 0 %f 0\t%f %f 0 1\n", -radius.value,
852         -height.value/2.0, radius.value, radius.value, -height.value/2.0);
853       OOGLout(out);
854 
855       sprintf(out, "%f %f 0 1\t0 0 %f 0\t%f %f 0 1", -radius.value,
856         -height.value/2.0, -radius.value, radius.value, -height.value/2.0);
857       OOGLout(out);
858       sprintf(out, "%f %f 0 1\t0 0 %f 0\t%f %f 0 1", -radius.value/2.0,
859         -height.value/2.0, -radius.value/2.0,
860         radius.value/2.0, -height.value/2.0);
861       OOGLout(out);
862       sprintf(out, "0 %f 0 1\t0 0 0 0\t0 %f 0 1\n", -height.value/2.0,
863         -height.value/2.0);
864       OOGLout(out);
865       if (mb_val == PER_PART || mb_val == PER_PART_INDEXED) {
866         OOGLgetcolor(qv_material, qv_materialb, 2);
867         sprintf(out, "%s %s %s %s\n", colstr, colstr, colstr, colstr);
868        OOGLout(out);
869       }
870 
871     }
872 
873     OOGLout("}");
874 }
875 
876 void
ToWebOOGL(QvState * state)877 QvSphere::ToWebOOGL(QvState *state)
878 {
879     QvElement *elt = NULL;
880     QvMaterial *qv_material = NULL;
881     // QvMaterialBinding *qv_materialb = NULL;
882 
883     elt = state->getTopElement(QvState::MaterialIndex);
884     if (elt) { qv_material = (QvMaterial *)elt->data;}
885     elt = state->getTopElement(QvState::MaterialBindingIndex);
886     // if (elt) { qv_materialb = (QvMaterialBinding *)elt->data; }
887 
888     ANNOUNCE(QvSphere);
889     OOGLout("# VRML Sphere");
890     OOGLout("{");
891     OOGLappearance(qv_material);
892     OOGLout("= SPHERE");
893     sprintf(out, "  %f", radius.value);
894     OOGLout(out);
895     OOGLout("  0 0 0");
896     OOGLout("}");
897 }
898 
899 void
ToWebOOGL(QvState * state)900 QvIndexedFaceSet::ToWebOOGL(QvState *state)
901 {
902     QvElement *elt = NULL;
903     QvCoordinate3 *qv_coord = NULL;
904     QvMaterial *qv_material = NULL;
905     // QvMaterialBinding *qv_materialb = NULL;
906     QvNormal *qv_normal = NULL;
907     QvNormalBinding *qv_normalb = NULL;
908     float *coords;
909     // float *vects;
910     long  *firstindex;
911     // Binding mb_val;
912     Binding nb_val;
913     int   count, numfaces, bad, numverts, numcoords, numnormals;
914 
915     elt = state->getTopElement(QvState::Coordinate3Index);
916     if (elt) { qv_coord = (QvCoordinate3 *)elt->data;}
917     elt = state->getTopElement(QvState::MaterialIndex);
918     if (elt) { qv_material = (QvMaterial *)elt->data;}
919     elt = state->getTopElement(QvState::MaterialBindingIndex);
920     // if (elt) { qv_materialb = (QvMaterialBinding *)elt->data; }
921     elt = state->getTopElement(QvState::NormalIndex);
922     if (elt) { qv_normal = (QvNormal *)elt->data; }
923     elt = state->getTopElement(QvState::NormalBindingIndex);
924     if (elt) { qv_normalb = (QvNormalBinding *)elt->data; }
925 
926     // if (qv_materialb) { mb_val = (Binding) qv_materialb->value.value; }
927     // else { mb_val = DEFAULT; }
928     if (qv_normalb) { nb_val = (Binding) qv_normalb->value.value; }
929     else { nb_val = DEFAULT; }
930 
931     if (qv_coord) {
932 	numcoords = qv_coord->point.num;
933 	coords = qv_coord->point.values;
934     } else { numcoords = 0; coords = NULL; }
935     if (qv_normal) {
936 	numnormals = qv_normal->vector.num;
937 	// vects = qv_normal->vector.values;
938     } else {
939 	numnormals = 0;
940 	// vects = NULL;
941     }
942     if (qv_material) {
943     }
944 
945     firstindex = coordIndex.values;
946     numverts = coordIndex.num,
947 
948     ANNOUNCE(QvIndexedFaceSet);
949 
950     numfaces = 0; bad = 0;
951     for (count = 0; count < numverts; count++)
952     {
953       if (firstindex[count] < 0 && !bad) { numfaces++; bad = 1; }
954 	else bad = 0; /* bad handles case of two consecutive delimeters */
955       if (firstindex[count] > (numcoords - 1)) return;
956     }
957     for (count = 0; count < numnormals; count++) {
958 
959     }
960 
961     OOGLout("# IndexedFaceSet");
962     if (coords == NULL) { OOGLout("# Bad Values"); return; }
963     if (nb_val) { }
964     OOGLout("{ = OFF");
965     sprintf(out, "%d %d 0\n", numcoords, numfaces);
966     OOGLout(out);
967 
968     for (count = 0; count < numcoords; count++)
969     {
970       float x = coords[count*3], y = coords[count*3+1], z = coords[count*3+2];
971       sprintf(out, "%f %f %f", x, y, z);
972       OOGLout(out);
973     }
974     OOGLout("");
975 
976     count = 0;
977     while (count < numverts) {
978       int numvts, start;
979       numvts = 0;
980       start = count;
981       while (firstindex[count] > -1 && count < numverts) {
982 	count++; numvts++;
983       }
984       if (count > start)
985       {
986 	OOGLoutindent();
987 	sprintf(out, "%d", numvts);
988 	OOGLoutraw(out);
989 	for(int i=start;i<count;i++) {
990 	 sprintf(out, " %ld", firstindex[i]);
991 	 OOGLoutraw(out);
992 	}
993 	OOGLoutraw("\n");
994       }
995       count++;
996     }
997     OOGLout("}");
998 
999 }
1000 
1001 void
ToWebOOGL(QvState * state)1002 QvIndexedLineSet::ToWebOOGL(QvState *state)
1003 {
1004     QvElement *elt = NULL;
1005     QvCoordinate3 *qv_coord = NULL;
1006     QvMaterial *qv_material = NULL;
1007     QvMaterialBinding *qv_materialb = NULL;
1008     float *coords;
1009     long  *firstindex, *matindex;
1010     Binding mb_val;
1011     int   numvts, points, numsegs;
1012     int   count, numlines, numverts, numcoords, nummats;
1013 
1014     elt = state->getTopElement(QvState::Coordinate3Index);
1015     if (elt) { qv_coord = (QvCoordinate3 *)elt->data;}
1016     elt = state->getTopElement(QvState::MaterialIndex);
1017     if (elt) { qv_material = (QvMaterial *)elt->data;}
1018     elt = state->getTopElement(QvState::MaterialBindingIndex);
1019     if (elt) { qv_materialb = (QvMaterialBinding *)elt->data; }
1020 
1021     if (qv_materialb) { mb_val = (Binding) qv_materialb->value.value; }
1022     else { mb_val = DEFAULT; }
1023 
1024     if (qv_coord) {
1025       numcoords = qv_coord->point.num;
1026       coords = qv_coord->point.values;
1027     } else { numcoords = 0; coords = NULL; }
1028 
1029     nummats = materialIndex.num;
1030     matindex = materialIndex.values;
1031     firstindex = coordIndex.values;
1032     numverts = coordIndex.num,
1033 
1034     ANNOUNCE(QvIndexedLineSet);
1035 
1036     count = 0; numlines = 0; numvts = 0; points = 0; numsegs = 0;
1037     while (count < numverts) {
1038       int x;
1039 
1040       x = 0;
1041       while (firstindex[count] < 0 && count < numverts) count++;
1042       while (firstindex[count] > -1 && count < numverts) {
1043 	count++; x++;
1044       }
1045       if (x == 1) {
1046 	numvts++; numlines++; points++;
1047       } else if (x > 1) {
1048 	numvts += x; numlines++; numsegs += x - 1;
1049       }
1050     }
1051 
1052     OOGLout("# IndexedLineSet");
1053     if (coords == NULL || numvts < 1 || numlines < 1) {
1054       OOGLout("# Bad Values");
1055       return;
1056     }
1057 
1058     OOGLout("{ = VECT");
1059     if (mb_val == DEFAULT || mb_val == OVERALL) {
1060       sprintf(out, "%d %d 1\n", numlines, numvts);
1061     } else if (mb_val == PER_FACE || mb_val == PER_FACE_INDEXED) {
1062       sprintf(out, "%d %d %d\n", numlines, numvts, numlines);
1063     } else if (mb_val == PER_PART || mb_val == PER_PART_INDEXED) {
1064       sprintf(out, "%d %d %d\n", numsegs + points, numvts, numsegs + points);
1065     } else if (mb_val == PER_VERTEX || mb_val == PER_VERTEX_INDEXED) {
1066       sprintf(out, "%d %d %d\n", numlines, numvts, numvts);
1067     }
1068     OOGLout(out);
1069 
1070     /* number of vertices in each poly line */
1071 
1072     OOGLoutindent();
1073     count = 0;
1074     while (count < numverts) {
1075       int x;
1076 
1077       x = 0;
1078       while (firstindex[count] < 0 && count < numverts) count++;
1079       while (firstindex[count] > -1 && count < numverts) {
1080 	count++; x++;
1081       }
1082       if (mb_val == PER_PART || mb_val == PER_PART_INDEXED) {
1083 	/* Here, we divide our poly lines into segments... */
1084 	if (x == 1) {
1085 	  sprintf(out,"1 ");
1086 	  OOGLoutraw(out);
1087 	} else if (x > 1) {
1088 	  while (x > 1) {
1089 	    sprintf(out,"2 ");
1090 	    OOGLoutraw(out);
1091 	    x--;
1092 	  }
1093 	  sprintf(out,"%d ", x - 1);
1094 	  OOGLoutraw(out);
1095 	}
1096       } else if (x > 0) {
1097 	sprintf(out,"%d ", x);
1098 	OOGLoutraw(out);
1099       }
1100     }
1101     OOGLoutraw("\n");
1102 
1103     /*  number of colors in each poly line */
1104 
1105     OOGLoutindent();
1106     if (mb_val == DEFAULT || mb_val == OVERALL) {
1107       count = 1;
1108       OOGLoutraw("1 ");
1109       while (count < numlines) {
1110 	sprintf(out,"0 ");
1111 	OOGLoutraw(out);
1112 	count++;
1113       }
1114       OOGLoutraw("\n");
1115     } else if (mb_val == PER_FACE || mb_val == PER_FACE_INDEXED) {
1116       count = 0;
1117       while (count < numlines) {
1118 	OOGLoutraw("1 "); count++;
1119       }
1120     } else if (mb_val == PER_PART || mb_val == PER_PART_INDEXED) {
1121       count = 0;
1122       while (count < (numsegs + points)) {
1123 	OOGLoutraw("1 "); count++;
1124       }
1125     } else if (mb_val == PER_VERTEX || mb_val == PER_VERTEX_INDEXED) {
1126       count = 0;
1127       while (count < numverts) {
1128 	int x;
1129 
1130 	x = 0;
1131 	while (firstindex[count] < 0 && count < numverts) count++;
1132 	while (firstindex[count] > -1 && count < numverts) {
1133 	  count++; x++;
1134 	}
1135 	if (x > 0) {
1136 	  sprintf(out,"%d ", x);
1137 	  OOGLoutraw(out);
1138 	}
1139       }
1140     }
1141     OOGLout("");
1142 
1143     count = 0;
1144     while (count < numverts) {
1145       long num;
1146 
1147       while (firstindex[count] < 0 && count < numverts) count++;
1148       while (firstindex[count] > -1 && count < numverts) {
1149 	float x, y, z;
1150 
1151 	num = firstindex[count]; count++;
1152 	if (num > -1 && num < numcoords) {
1153 	  x = coords[num * 3];
1154 	  y = coords[num * 3 + 1];
1155 	  z = coords[num * 3 + 2];
1156 	  sprintf(out,"%f %f %f", x, y, z);
1157 	  OOGLout(out);
1158 	} else sprintf(out,"%f %f %f", x, y, z);
1159       }
1160     }
1161     OOGLout("");
1162 
1163     OOGLoutindent();
1164     if (mb_val == DEFAULT || mb_val == OVERALL) {
1165       OOGLgetcolor(qv_material, qv_materialb, 0);
1166       OOGLout(colstr);
1167     } else if (mb_val == PER_FACE || mb_val == PER_PART ||
1168 	       mb_val == PER_VERTEX) {
1169       int numpieces;
1170 
1171       if (mb_val == PER_FACE) numpieces = numlines;
1172       else if (mb_val == PER_PART) numpieces = numsegs + points;
1173       else if (mb_val == PER_VERTEX) numpieces = numvts;
1174 
1175       count = 0;
1176       while (count < numpieces) {
1177 	OOGLgetcolor(qv_material, qv_materialb, count);
1178 	OOGLout(colstr);
1179 	count++;
1180       }
1181     } else if (mb_val == PER_FACE_INDEXED || mb_val == PER_PART_INDEXED ||
1182 	       mb_val == PER_VERTEX_INDEXED) {
1183       int numpieces, x;
1184 
1185       if (mb_val == PER_FACE_INDEXED) numpieces = numlines;
1186       else if (mb_val == PER_PART_INDEXED) numpieces = numsegs + points;
1187       else if (mb_val == PER_VERTEX_INDEXED) numpieces = numvts;
1188 
1189       count = 0; x = 0;
1190       while (count < numpieces) {
1191 	int num;
1192 
1193 	if (nummats > 0) {
1194 	  num = (int) matindex[x % nummats];
1195 	  if (num >= 0) {
1196 	    OOGLgetcolor(qv_material, qv_materialb, num);
1197 	    OOGLout(colstr);
1198 	    count++; x++;
1199 	  } else x++;
1200 	} else {
1201 	  OOGLgetcolor(qv_material, qv_materialb, 0);
1202 	  OOGLout(colstr); count++;
1203 	}
1204       }
1205     }
1206     OOGLout("}");
1207 
1208 }
1209 
1210 void
ToWebOOGL(QvState * state)1211 QvPointSet::ToWebOOGL(QvState *state)
1212 {
1213     QvElement *elt = NULL;
1214     QvCoordinate3 *qv_coord = NULL;
1215     QvMaterial *qv_material = NULL;
1216     QvMaterialBinding *qv_materialb = NULL;
1217     float *coords;
1218     // Binding mb_val;
1219     int   count, numcoords;
1220     long numverts;
1221 
1222     elt = state->getTopElement(QvState::Coordinate3Index);
1223     if (elt) { qv_coord = (QvCoordinate3 *)elt->data;}
1224     elt = state->getTopElement(QvState::MaterialIndex);
1225     if (elt) { qv_material = (QvMaterial *)elt->data;}
1226     elt = state->getTopElement(QvState::MaterialBindingIndex);
1227     if (elt) { qv_materialb = (QvMaterialBinding *)elt->data; }
1228 
1229     // if (qv_materialb) { mb_val = (Binding) qv_materialb->value.value; }
1230     // else { mb_val = DEFAULT; }
1231 
1232     if (qv_coord) {
1233       numcoords = qv_coord->point.num;
1234       coords = qv_coord->point.values;
1235     } else { numcoords = 0; coords = NULL; }
1236 
1237     if (qv_material) {
1238     }
1239 
1240     if (startIndex.value > numcoords) {
1241       OOGLout("# Bad Values");
1242       return;
1243     }
1244 
1245     if (numPoints.value == (-1)) {
1246       numverts = numcoords - startIndex.value;
1247     } else if ((numPoints.value - startIndex.value) > numcoords) {
1248       OOGLout("# Bad Values");
1249       return;
1250     } else {
1251       numverts = numPoints.value - startIndex.value;
1252     }
1253 
1254     ANNOUNCE(QvPointSet);
1255 
1256     OOGLout("# PointSet");
1257     if (coords == NULL) {
1258       OOGLout("# Bad Values");
1259       return;
1260     }
1261     OOGLout("{ = VECT");
1262     sprintf(out, "%ld %ld %ld\n", numverts, numverts, numverts);
1263     OOGLout(out);
1264 
1265     /* number of vertices in each poly line */
1266 
1267     OOGLoutindent();
1268     for (count = 0; count < numverts; count++) {
1269       OOGLoutraw("1 ");
1270     }
1271     OOGLoutraw("\n");
1272 
1273     /*  number of colors in each poly line */
1274 
1275     OOGLoutindent();
1276     for (count = 0; count < numverts; count++) {
1277       OOGLoutraw("1 ");
1278     }
1279     OOGLoutraw("\n");
1280 
1281     for (count = 0; count < numverts; count++)
1282     {
1283       float x = coords[(count+startIndex.value)*3],
1284       y = coords[(count+startIndex.value)*3+1],
1285       z = coords[(count+startIndex.value)*3+2];
1286 
1287       sprintf(out, "%f %f %f", x, y, z);
1288       OOGLout(out);
1289     }
1290     OOGLout("");
1291 
1292     for (count = 0; count < numverts; count++) {
1293       OOGLgetcolor(qv_material, qv_materialb, count);
1294       OOGLout(colstr);
1295     }
1296     OOGLout("}");
1297 
1298 }
1299 
knowngsfont(char * str)1300 static int knowngsfont(char *str)
1301 {
1302   if(str == NULL)
1303     return 0;
1304   if(access(str, 0) >= 0)
1305     return 1;
1306 
1307   char buf[2048];
1308   const char *p, *tail;
1309   const char *gsfontpath = getenv("GS_FONTPATH");
1310 
1311   if(gsfontpath == NULL)
1312     gsfontpath = "/usr/local/lib/ghostscript/fonts";
1313   for(p = tail = gsfontpath; tail && *p != '\0'; p = tail+1) {
1314     tail = strchr(p, ':');
1315     int len = tail ? tail - p : strlen(p);
1316     if(len > 1024) len = 1024;
1317     memcpy(buf, p, len);
1318     buf[len] = '/';
1319     strncpy(buf+len+1, str, 2046-len);
1320     if(access(buf, 0) >= 0)
1321 	return 1;
1322   }
1323   return 0;
1324 }
1325 
ToWebOOGL(QvState * state)1326 void QvAsciiText::ToWebOOGL(QvState *state)
1327 {
1328 
1329   float fontsize = 1.0;
1330   // float linespace = 1.0;
1331   char *font = NULL;
1332   // int bold = 0, italic = 0;
1333 
1334   QvElement *elt = state->getTopElement(QvState::FontStyleIndex);
1335   if(elt && elt->data) {
1336     QvFontStyle *fs = (QvFontStyle *)elt->data;
1337     fontsize = fs->size.value;
1338     // if(fs->style.value & (1<<QvFontStyle::BOLD))
1339     //	bold = 1;
1340     switch(fs->family.value) {
1341     case QvFontStyle::SERIF:	  font = "hrpl_t.gsf";		 break;
1342     case QvFontStyle::TYPEWRITER: /* sorry, can't do that now */ break;
1343     }
1344   }
1345 
1346   int i, c;
1347   float y = 0;
1348   char buf[2048], *q;
1349   const char *p;
1350   char *just = "sw";
1351   FILE *f;
1352 
1353   switch(justification.value) {
1354     case QvAsciiText::LEFT: just = "sw"; break;
1355     case QvAsciiText::RIGHT: just = "se"; break;
1356     case QvAsciiText::CENTER: just = "s"; break;
1357   }
1358   OOGLout(string.num > 1 ? "{ = LIST # VRML AsciiText" : "# VRML AsciiText");
1359   for(i = 0; i < string.num; i++) {
1360     float wid = width.values[ (i<width.num) ? i : width.num-1 ];
1361     sprintf(buf, "hvectext -s %g -align %s -plane xy -at 0 %g 0 ",
1362 		fontsize, just, y);
1363     if(wid > 0)
1364 	sprintf(buf + strlen(buf), "-w %g ", wid);
1365     if(font && knowngsfont(font))
1366 	sprintf(buf + strlen(buf), "-hershey %s ", font);
1367 
1368     q = buf + strlen(buf);
1369     *q++ = '\'';
1370     for(p = string.values[i].getString(); p && *p != '\0' && q < &buf[2048-3]; ) {
1371 	if(*p == '\'' || *p == '\\') *q++ = '\\';
1372 	*q++ = *p++;
1373     }
1374     *q++ = '\'';
1375     *q = '\0';
1376     f = popen(buf, "r");
1377     for(q = buf; (c = getc(f)) != EOF; ) {
1378 	if(c == '\n') {
1379 	   *q = '\0';
1380 	   OOGLout(buf);
1381 	   q = buf;
1382 	} else {
1383 	    *q++ = c;
1384 	}
1385     }
1386     pclose(f);
1387     y -= spacing.value * fontsize;
1388   }
1389   if(string.num > 1)
1390     OOGLout("} # End AsciiText");
1391 }
1392 
1393 //////////////////////////////////////////////////////////////////////////////
1394 //
1395 // WWW-specific nodes.
1396 //
1397 //////////////////////////////////////////////////////////////////////////////
1398 
1399 void
ToWebOOGL(QvState *)1400 QvWWWInline::ToWebOOGL(QvState *)
1401 {
1402   int notuniq = 0;
1403   int i;
1404 
1405     ANNOUNCE(QvWWWInline);
1406 
1407     if (OOGLhand) {
1408       sprintf(out, "{ : %s }", name.value.getString());
1409       for (i = 0; i < unique && !notuniq; i++) {
1410 	if (!strcmp(urls[i], name.value.getString())) notuniq = 1;
1411       }
1412       if (!notuniq) {
1413 	urls[unique++] = (char *)name.value.getString();
1414       }
1415     } else {
1416       sprintf(out, "{ COMMENT url.%d WWWInline { \"%s\" }}",
1417 	      unique++, name.value.getString());
1418     }
1419     OOGLout(out);
1420 }
1421 
1422 void
ToWebOOGL(QvState * state)1423 QvWWWAnchor::ToWebOOGL(QvState *state)
1424 {
1425     int savedepth, i;
1426 
1427     ANNOUNCE(QvWWWAnchor);
1428 
1429     OOGLout("{ = LIST           # Anchor");
1430     OOGLoutindent();
1431     OOGLoutraw("{ COMMENT ");
1432     sprintf(out, "wwwanchor.%d HREF { \"%s\" } }\n", mypid,
1433 	    name.value.getString());
1434     OOGLoutraw(out);
1435 
1436     savedepth = oogldepth;
1437 
1438     indent++;
1439     for (i = 0; i < getNumChildren(); i++)
1440 	getChild(i)->ToWebOOGL(state);
1441     indent--;
1442 
1443     savedepth = oogldepth - savedepth; /* How deep did we get ? :-)*/
1444 
1445     for (i = 0; i < savedepth; i++)  { /* Do the equivalent OOGL pop */
1446       out[i*2] = '}';		   /* pop the LIST */
1447       out[i*2+1] = '}';		   /* pop the INST */
1448     }
1449 
1450     out[savedepth*2] = '\0';
1451     OOGLout(out);
1452     OOGLout("}			# End Anchor");
1453     oogldepth = oogldepth - savedepth;
1454 
1455 }
1456 
1457 //////////////////////////////////////////////////////////////////////////////
1458 //
1459 // Default traversal methods. These nodes have no effects during traversal.
1460 //
1461 //////////////////////////////////////////////////////////////////////////////
1462 
1463 DEFAULT_TRAVERSE(QvInfo)
1464 DEFAULT_TRAVERSE(QvUnknownNode)
1465 
1466 //////////////////////////////////////////////////////////////////////////////
1467 
1468 #undef ANNOUNCE
1469 #undef DEFAULT_TRAVERSE
1470 #undef DO_PROPERTY
1471 #undef DO_SHAPE
1472 #undef DO_TYPED_PROPERTY
1473