1 /* $RCSfile$
2  * $Author: hansonr $
3  * $Date: 2007-10-07 20:10:15 -0500 (Sun, 07 Oct 2007) $
4  * $Revision: 8384 $
5  *
6  * Copyright (C) 2003-2006  Miguel, Jmol Development, www.jmol.org
7  *
8  * Contact: jmol-developers@lists.sf.net
9  *
10  *  This library is free software; you can redistribute it and/or
11  *  modify it under the terms of the GNU Lesser General Public
12  *  License as published by the Free Software Foundation; either
13  *  version 2.1 of the License, or (at your option) any later version.
14  *
15  *  This library is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  *  Lesser General Public License for more details.
19  *
20  *  You should have received a copy of the GNU Lesser General Public
21  *  License along with this library; if not, write to the Free Software
22  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24 package org.jmol.export;
25 
26 import java.util.Map;
27 
28 import javajs.util.M3;
29 import javajs.util.M4;
30 import javajs.util.P3;
31 import javajs.util.P3i;
32 import javajs.util.T3;
33 
34 import org.jmol.api.Interface;
35 import org.jmol.api.JmolRendererInterface;
36 import org.jmol.g3d.HermiteRenderer;
37 import org.jmol.modelset.Atom;
38 import org.jmol.script.T;
39 import org.jmol.util.Font;
40 import org.jmol.util.GData;
41 import org.jmol.util.MeshSurface;
42 import org.jmol.viewer.Viewer;
43 
44 public class Export3D implements JmolRendererInterface {
45 
46   protected ___Exporter exporter;
47 
48   private double privateKey;
49 
50   private GData gdata;
51   private short colix;
52   private HermiteRenderer hermite3d;
53   private int width;
54   private int height;
55   private int slab, depth;
56 
57   String exportName;
58 
59   private boolean webGL;
60 
61   @Override
isWebGL()62   public boolean isWebGL() {
63     return webGL;
64   }
65 
66   private boolean isCartesian;
67 
Export3D()68   public Export3D() {
69     // by reflection
70   }
71 
72   @Override
initializeExporter(Viewer vwr, double privateKey, GData gdata, Map<String, Object> params)73   public Object initializeExporter(Viewer vwr, double privateKey,
74                                    GData gdata, Map<String, Object> params) {
75     exportName = (String) params.get("type");
76     webGL = exportName.equals("JS");
77     if ((exporter = (___Exporter) Interface.getOption("export." + (webGL ? "" : "_") + exportName + "Exporter", vwr, "export")) == null)
78       return null;
79     exporter.export3D = this;
80     isCartesian = (exporter.exportType == GData.EXPORT_CARTESIAN);
81     this.gdata = gdata;
82     gdata.setNewWindowParametersForExport();
83     slab = gdata.slab;
84     width = gdata.width;
85     height = gdata.height;
86     this.privateKey = privateKey;
87     return (initializeOutput(vwr, privateKey, params) ? exporter : null);
88   }
89 
90   @Override
initializeOutput(Viewer vwr, double privateKey, Map<String, Object> params)91   public boolean initializeOutput(Viewer vwr, double privateKey,
92                                   Map<String, Object> params) {
93     return exporter.initializeOutput(vwr, privateKey, gdata, params);
94   }
95 
96   @Override
getExportType()97   public int getExportType() {
98     return exporter.exportType;
99   }
100 
101   @Override
getExportName()102   public String getExportName() {
103     return exportName;
104   }
105 
106   @Override
finalizeOutput()107   public String finalizeOutput() {
108     return exporter.finalizeOutput();
109   }
110 
111   @Override
setSlab(int slabValue)112   public void setSlab(int slabValue) {
113     gdata.setSlab(slabValue);
114     slab = gdata.slab;
115   }
116   @Override
setSlabAndZShade(int slabValue, int depthValue, int zSlab, int zDepth, int zPower)117   public void setSlabAndZShade(int slabValue, int depthValue, int zSlab, int zDepth, int zPower) {
118     gdata.setSlab(slabValue);
119     slab = gdata.slab;
120     gdata.setDepth(depthValue);
121     depth = gdata.depth; // not implemented
122     // zShade??
123     // see Graphics3D; could be implemented in an Exporter as well;
124   }
125 
126   @Override
renderBackground(JmolRendererInterface me)127   public void renderBackground(JmolRendererInterface me) {
128     if (!isCartesian)
129       gdata.renderBackground(me);
130   }
131 
132   @Override
drawAtom(Atom atom, float radius)133   public void drawAtom(Atom atom, float radius) {
134     exporter.drawAtom(atom, radius);
135   }
136 
137   /**
138    * draws a rectangle
139    *
140    * @param x
141    *        upper left x
142    * @param y
143    *        upper left y
144    * @param z
145    *        upper left z
146    * @param zSlab
147    *        z for slab check (for set labelsFront)
148    * @param rWidth
149    *        pixel count
150    * @param rHeight
151    *        pixel count
152    */
153   @Override
drawRect(int x, int y, int z, int zSlab, int rWidth, int rHeight)154   public void drawRect(int x, int y, int z, int zSlab, int rWidth, int rHeight) {
155     if (webGL) {
156       //TODO
157       return;
158     }
159     // labels (and rubberband, not implemented) and navigation cursor
160     if (zSlab != 0 && gdata.isClippedZ(zSlab))
161       return;
162     int w = rWidth - 1;
163     int h = rHeight - 1;
164     int xRight = x + w;
165     int yBottom = y + h;
166     if (y >= 0 && y < height)
167       drawHLine(x, y, z, w);
168     if (yBottom >= 0 && yBottom < height)
169       drawHLine(x, yBottom, z, w);
170     if (x >= 0 && x < width)
171       drawVLine(x, y, z, h);
172     if (xRight >= 0 && xRight < width)
173       drawVLine(xRight, y, z, h);
174   }
175 
176   /**
177    * @param x
178    * @param y
179    * @param z
180    * @param w
181    */
182 
drawHLine(int x, int y, int z, int w)183   private void drawHLine(int x, int y, int z, int w) {
184     // hover, labels only
185     int argbCurrent = gdata.getColorArgbOrGray(colix);
186     if (w < 0) {
187       x += w;
188       w = -w;
189     }
190     for (int i = 0; i <= w; i++) {
191       exporter.drawTextPixel(argbCurrent, x + i, y, z);
192     }
193   }
194 
195   /**
196    * @param x
197    * @param y
198    * @param z
199    * @param h
200    */
drawVLine(int x, int y, int z, int h)201   private void drawVLine(int x, int y, int z, int h) {
202     // hover, labels only
203     int argbCurrent = gdata.getColorArgbOrGray(colix);
204     if (h < 0) {
205       y += h;
206       h = -h;
207     }
208     for (int i = 0; i <= h; i++) {
209       exporter.drawTextPixel(argbCurrent, x, y + i, z);
210     }
211   }
212 
213   /**
214    * draws a screened circle ... every other dot is turned on
215    *
216    * @param colixRing
217    * @param colixFill
218    * @param diameter
219    * @param x
220    *        center x
221    * @param y
222    *        center y
223    * @param z
224    *        center z
225    */
226 
227   @Override
drawFilledCircle(short colixRing, short colixFill, int diameter, int x, int y, int z)228   public void drawFilledCircle(short colixRing, short colixFill, int diameter,
229                                int x, int y, int z) {
230     // halos, draw
231     if (!gdata.isClippedZ(z))
232       exporter.drawFilledCircle(colixRing, colixFill, diameter, x, y, z);
233   }
234 
235   /**
236    * draws a simple circle (draw circle)
237    *
238    * @param colix
239    *        the color index
240    * @param diameter
241    *        the pixel diameter
242    * @param x
243    *        center x
244    * @param y
245    *        center y
246    * @param z
247    *        center z
248    * @param doFill
249    *        (not implemented in exporters)
250    */
251 
drawCircle(short colix, int diameter, int x, int y, int z, boolean doFill)252   public void drawCircle(short colix, int diameter, int x, int y, int z,
253                          boolean doFill) {
254     // halos, draw
255     if (!gdata.isClippedZ(z))
256       exporter.drawCircle(x, y, z, diameter, colix, doFill);
257   }
258 
259   private P3 ptA = new P3();
260   private P3 ptB = new P3();
261   private P3 ptC = new P3();
262   private P3 ptD = new P3();
263   /*
264    * private Point3f ptE = new Point3f(); private Point3f ptF = new Point3f();
265    * private Point3f ptG = new Point3f(); private Point3f ptH = new Point3f();
266    */
267 
268   /**
269    * fills a solid sphere
270    *
271    * @param diameter
272    *        pixel count
273    * @param x
274    *        center x
275    * @param y
276    *        center y
277    * @param z
278    *        center z
279    */
280   @Override
fillSphereXYZ(int diameter, int x, int y, int z)281   public void fillSphereXYZ(int diameter, int x, int y, int z) {
282     ptA.set(x, y, z);
283     fillSphereBits(diameter, ptA);
284   }
285 
286   /**
287    * fills a solid sphere
288    *
289    * @param diameter
290    *        pixel count
291    * @param center
292    *        javax.vecmath.Point3i defining the center
293    */
294 
295   @Override
fillSphereI(int diameter, P3i center)296   public void fillSphereI(int diameter, P3i center) {
297     // dashed line; mesh line; render mesh points; lone pair; renderTriangles
298     ptA.set(center.x, center.y, center.z);
299     fillSphereBits(diameter, ptA);
300   }
301 
302   /**
303    * fills a solid sphere
304    *
305    * @param diameter
306    *        pixel count
307    * @param center
308    *        a javax.vecmath.Point3f ... floats are casted to ints
309    */
310   @Override
fillSphereBits(int diameter, P3 center)311   public void fillSphereBits(int diameter, P3 center) {
312     if (diameter != 0)
313       exporter.fillSphere(colix, diameter, center);
314   }
315 
316   /**
317    * fills background rectangle for label
318    * <p>
319    *
320    * @param x
321    *        upper left x
322    * @param y
323    *        upper left y
324    * @param z
325    *        upper left z
326    * @param zSlab
327    *        z value for slabbing
328    * @param widthFill
329    *        pixel count
330    * @param heightFill
331    *        pixel count
332    */
333   @Override
fillTextRect(int x, int y, int z, int zSlab, int widthFill, int heightFill)334   public void fillTextRect(int x, int y, int z, int zSlab, int widthFill,
335                        int heightFill) {
336     // hover and labels only -- slab at atom or front -- simple Z/window clip
337     if (isCartesian || gdata.isClippedZ(zSlab))
338       return;
339     z = exporter.fixScreenZ(z);
340     ptA.set(x, y, z);
341     ptB.set(x + widthFill, y, z);
342     ptC.set(x + widthFill, y + heightFill, z);
343     ptD.set(x, y + heightFill, z);
344     fillQuadrilateral(ptA, ptB, ptC, ptD, false);
345   }
346 
347   /**
348    * draws the specified string in the current font. no line wrapping -- axis,
349    * labels, measures
350    *
351    * @param str
352    *        the String
353    * @param font3d
354    *        the Font3D
355    * @param xBaseline
356    *        baseline x
357    * @param yBaseline
358    *        baseline y
359    * @param z
360    *        baseline z
361    * @param zSlab
362    *        z for slab calculation
363    * @param bgcolix
364    */
365 
366   @Override
drawString(String str, Font font3d, int xBaseline, int yBaseline, int z, int zSlab, short bgcolix)367   public void drawString(String str, Font font3d, int xBaseline, int yBaseline,
368                          int z, int zSlab, short bgcolix) {
369     // axis, labels, measures
370     if (str != null && !gdata.isClippedZ(zSlab))
371       drawStringNoSlab(str, font3d, xBaseline, yBaseline, z, bgcolix);
372   }
373 
374   /**
375    * draws the specified string in the current font. no line wrapping -- echo,
376    * frank, hover, molecularOrbital, uccage
377    *
378    * @param str
379    *        the String
380    * @param font3d
381    *        the Font3D
382    * @param xBaseline
383    *        baseline x
384    * @param yBaseline
385    *        baseline y
386    * @param z
387    *        baseline z
388    * @param bgcolix
389    */
390 
391   @Override
drawStringNoSlab(String str, Font font3d, int xBaseline, int yBaseline, int z, short bgcolix)392   public void drawStringNoSlab(String str, Font font3d, int xBaseline,
393                                int yBaseline, int z, short bgcolix) {
394     // echo, frank, hover, molecularOrbital, uccage
395     if (str == null)
396       return;
397     z = Math.max(slab, z);
398     if (font3d == null)
399       font3d = gdata.getFont3DCurrent();
400     else
401       gdata.setFont(font3d);
402     exporter.plotText(xBaseline, yBaseline, z, colix, str, font3d);
403   }
404 
405   @Override
drawImage(Object objImage, int x, int y, int z, int zSlab, short bgcolix, int width, int height)406   public void drawImage(Object objImage, int x, int y, int z, int zSlab,
407                         short bgcolix, int width, int height) {
408     if (isCartesian || objImage == null || width == 0 || height == 0 || gdata.isClippedZ(zSlab))
409       return;
410     z = Math.max(slab, z);
411     exporter.plotImage(x, y, z, objImage, bgcolix, width, height);
412   }
413 
414   // mostly public drawing methods -- add "public" if you need to
415 
416   /*
417    * *************************************************************** points
418    * **************************************************************
419    */
420 
421   @Override
drawPixel(int x, int y, int z)422   public void drawPixel(int x, int y, int z) {
423     // measures - render angle
424     plotPixelClipped(x, y, z);
425   }
426 
plotPixelClipped(int x, int y, int z)427   void plotPixelClipped(int x, int y, int z) {
428     // circle3D, drawPixel, plotPixelClipped(point3)
429     if (isClipped(x, y, z))
430       return;
431     exporter.drawPixel(colix, x, y, z, 1);
432   }
433 
434   @Override
plotPixelClippedP3i(P3i screen)435   public void plotPixelClippedP3i(P3i screen) {
436     if (isClipped(screen.x, screen.y, screen.z))
437       return;
438     // circle3D, drawPixel, plotPixelClipped(point3)
439     exporter.drawPixel(colix, screen.x, screen.y, screen.z, 1);
440   }
441 
442   @Override
drawPoints(int count, int[] coordinates, int scale)443   public void drawPoints(int count, int[] coordinates, int scale) {
444     for (int i = count * 3; i > 0;) {
445       int z = coordinates[--i];
446       int y = coordinates[--i];
447       int x = coordinates[--i];
448       if (isClipped(x, y, z))
449         continue;
450       exporter.drawPixel(colix, x, y, z, scale);
451     }
452   }
453 
454   /*
455    * *************************************************************** lines and
456    * cylinders **************************************************************
457    */
458 
459   @Override
drawDashedLineBits(int run, int rise, P3 pointA, P3 pointB)460   public void drawDashedLineBits(int run, int rise, P3 pointA, P3 pointB) {
461     // axes and such -- ignored dashed for exporters
462     // axes, bbcage only
463     exporter.fillCylinderScreenMad(colix, GData.ENDCAPS_FLAT,
464         exporter.lineWidthMad, pointA, pointB);
465     // ptA.set(pointA.x, pointA.y, pointA.z);
466     // ptB.set(pointB.x, pointB.y, pointB.z);
467     // exporter.drawDashedLine(colix, run, rise, ptA, ptB);
468   }
469 
470   @Override
drawLineXYZ(int x1, int y1, int z1, int x2, int y2, int z2)471   public void drawLineXYZ(int x1, int y1, int z1, int x2, int y2, int z2) {
472     // stars
473     ptA.set(x1, y1, z1);
474     ptB.set(x2, y2, z2);
475     exporter.fillCylinderScreenMad(colix, GData.ENDCAPS_FLAT,
476         exporter.lineWidthMad, ptA, ptB);
477   }
478 
479   @Override
drawLine(short colixA, short colixB, int xA, int yA, int zA, int xB, int yB, int zB)480   public void drawLine(short colixA, short colixB, int xA, int yA, int zA,
481                        int xB, int yB, int zB) {
482     // line bonds, line backbone, drawTriangle
483     fillCylinderXYZ(colixA, colixB, GData.ENDCAPS_FLAT, exporter.lineWidthMad,
484         xA, yA, zA, xB, yB, zB);
485   }
486 
487   @Override
drawLineBits(short colixA, short colixB, P3 pointA, P3 pointB)488   public void drawLineBits(short colixA, short colixB, P3 pointA, P3 pointB) {
489     fillCylinderBits2(colixA, colixB, GData.ENDCAPS_FLAT,
490         exporter.lineWidthMad, pointA, pointB);
491   }
492 
493   @Override
drawLineAB(P3 pointA, P3 pointB)494   public void drawLineAB(P3 pointA, P3 pointB) {
495     // draw quadrilateral and hermite, stars
496     exporter.fillCylinderScreenMad(colix, GData.ENDCAPS_FLAT,
497         exporter.lineWidthMad, pointA, pointB);
498   }
499 
500   @Override
drawBond(P3 atomA, P3 atomB, short colixA, short colixB, byte endcaps, short mad, int bondOrder)501   public void drawBond(P3 atomA, P3 atomB, short colixA, short colixB,
502                        byte endcaps, short mad, int bondOrder) {
503     // from SticksRenderer to allow for a direct
504     // writing of single bonds -- just for efficiency here
505     // bondOrder == -1 indicates we have cartesian coordinates and we want to draw endcaps
506     if (mad == 1)
507       mad = exporter.lineWidthMad;
508     exporter
509         .drawCylinder(atomA, atomB, colixA, colixB, endcaps, mad, bondOrder);
510   }
511 
512   @Override
fillCylinderXYZ(short colixA, short colixB, byte endcaps, int mad, int xA, int yA, int zA, int xB, int yB, int zB)513   public void fillCylinderXYZ(short colixA, short colixB, byte endcaps,
514                               int mad, int xA, int yA, int zA, int xB, int yB,
515                               int zB) {
516     /*
517      * from drawLine, Sticks, fillCylinder, backbone
518      *
519      */
520     ptA.set(xA, yA, zA);
521     ptB.set(xB, yB, zB);
522     // bond order 1 here indicates that we have screen coordinates
523     exporter.drawCylinder(ptA, ptB, colixA, colixB, endcaps, mad, 1);
524   }
525 
526   @Override
fillCylinderScreen3I(byte endcaps, int diameter, P3 pointA, P3 pointB, P3 pt0f, P3 pt1f, float radius)527   public void fillCylinderScreen3I(byte endcaps, int diameter, P3 pointA,
528                                    P3 pointB, P3 pt0f, P3 pt1f, float radius) {
529     // from Draw arrow and NucleicMonomer
530     if (diameter <= 0)
531       return;
532     exporter.fillCylinderScreen(colix, endcaps, diameter, pointA, pointB, pt0f, pt1f,
533         radius);
534   }
535 
536   /*
537    * *************************************************************** triangles
538    * **************************************************************
539    */
540 
541   @Override
fillCylinder(byte endcaps, int diameter, P3i pointA, P3i pointB)542   public void fillCylinder(byte endcaps, int diameter, P3i pointA, P3i pointB) {
543     if (diameter <= 0)
544       return;
545     ptA.set(pointA.x, pointA.y, pointA.z);
546     ptB.set(pointB.x, pointB.y, pointB.z);
547     exporter.fillCylinderScreenMad(colix, endcaps, diameter, ptA, ptB);
548   }
549 
550 //  @Override
551 //  public void fillCylinderScreen(byte endcaps, int screenDiameter, int xA,
552 //                                 int yA, int zA, int xB, int yB, int zB) {
553 //    // vectors, polyhedra
554 //    ptA.set(xA, yA, zA);
555 //    ptB.set(xB, yB, zB);
556 //    exporter.fillCylinderScreen(colix, endcaps, screenDiameter, ptA, ptB, null,
557 //        null, 0);
558 //  }
559 
560   @Override
fillCylinderBits(byte endcaps, int diameter, P3 pointA, P3 pointB)561   public void fillCylinderBits(byte endcaps, int diameter, P3 pointA, P3 pointB) {
562     if (diameter <= 0)
563       return;
564     // diameter is in screen coordinates.
565     if (isCartesian) {
566       exporter.fillCylinderScreen(colix, endcaps, diameter, pointA, pointB, null, null, 0);
567     } else {
568       exporter.fillCylinderScreenMad(colix, endcaps, diameter, pointA, pointB);
569     }
570   }
571 
572   @Override
fillConeScreen3f(byte endcap, int screenDiameter, P3 pointBase, P3 screenTip, boolean isBarb)573   public void fillConeScreen3f(byte endcap, int screenDiameter, P3 pointBase,
574                               P3 screenTip, boolean isBarb) {
575     // cartoons, rockets
576     exporter.fillConeScreen(colix, endcap, screenDiameter, pointBase,
577         screenTip, isBarb);
578   }
579 
580   @Override
drawHermite4(int tension, P3 s0, P3 s1, P3 s2, P3 s3)581   public void drawHermite4(int tension, P3 s0, P3 s1, P3 s2, P3 s3) {
582     // strands
583     hermite3d.renderHermiteRope(false, tension, 0, 0, 0, s0, s1, s2, s3);
584   }
585 
586   @Override
fillHermite(int tension, int diameterBeg, int diameterMid, int diameterEnd, P3 s0, P3 s1, P3 s2, P3 s3)587   public void fillHermite(int tension, int diameterBeg, int diameterMid,
588                           int diameterEnd, P3 s0, P3 s1, P3 s2, P3 s3) {
589     hermite3d.renderHermiteRope(true, tension, diameterBeg, diameterMid,
590         diameterEnd, s0, s1, s2, s3);
591   }
592 
593   @Override
drawTriangle3C(P3i screenA, short colixA, P3i screenB, short colixB, P3i screenC, short colixC, int check)594   public void drawTriangle3C(P3i screenA, short colixA, P3i screenB,
595                              short colixB, P3i screenC, short colixC, int check) {
596     // primary method for mapped Mesh
597     if ((check & 1) == 1)
598       drawLine(colixA, colixB, screenA.x, screenA.y, screenA.z, screenB.x,
599           screenB.y, screenB.z);
600     if ((check & 2) == 2)
601       drawLine(colixB, colixC, screenB.x, screenB.y, screenB.z, screenC.x,
602           screenC.y, screenC.z);
603     if ((check & 4) == 4)
604       drawLine(colixA, colixC, screenA.x, screenA.y, screenA.z, screenC.x,
605           screenC.y, screenC.z);
606   }
607 
drawLineBits(P3 screenA, P3 screenB, short colixA, short colixB)608   public void drawLineBits(P3 screenA, P3 screenB, short colixA, short colixB) {
609     exporter.drawCylinder(screenA, screenB, colixA, colixB, GData.ENDCAPS_FLAT, exporter.lineWidthMad, 1);
610   }
611 
612   @Override
fillCylinderBits2(short colixA, short colixB, byte endcaps, int mad, P3 screenA, P3 screenB)613   public void fillCylinderBits2(short colixA, short colixB, byte endcaps,
614                                 int mad, P3 screenA, P3 screenB) {
615     exporter.drawCylinder(screenA, screenB, colixA, colixB, endcaps, mad, 1);
616   }
617 
618   @Override
fillTriangle3CNBits(P3 pA, short colixA, short nA, P3 pB, short colixB, short nB, P3 pC, short colixC, short nC, boolean twoSided)619   public void fillTriangle3CNBits(P3 pA, short colixA, short nA, P3 pB,
620                                   short colixB, short nB, P3 pC, short colixC,
621                                   short nC, boolean twoSided) {
622     // draw polygon, polyhedron, geosurface
623     if (colixA != colixB || colixB != colixC) {
624       // shouldn't be here, because that uses renderIsosurface
625       return;
626     }
627     exporter.fillTriangle(colixA, pA, pB, pC, twoSided);
628   }
629 
630   @Override
fillTriangle3CN(P3i pointA, short colixA, short normixA, P3i pointB, short colixB, short normixB, P3i pointC, short colixC, short normixC)631   public void fillTriangle3CN(P3i pointA, short colixA, short normixA,
632                               P3i pointB, short colixB, short normixB,
633                               P3i pointC, short colixC, short normixC) {
634 //    // (isosourface irrelevant)
635 //    if (colixA != colixB || colixB != colixC) {
636 //      // shouldn't be here, because that uses renderIsosurface
637 //      return;
638 //    }
639 //    ptA.set(pointA.x, pointA.y, pointA.z);
640 //    ptB.set(pointB.x, pointB.y, pointB.z);
641 //    ptC.set(pointC.x, pointC.y, pointC.z);
642 //    exporter.fillTriangle(colixA, ptA, ptB, ptC, false);
643   }
644 
645   @Override
fillTriangleTwoSided(short normix, P3 a, P3 b, P3 c)646   public void fillTriangleTwoSided(short normix, P3 a, P3 b, P3 c) {
647     // polyhedra (collapsed)
648     exporter.fillTriangle(colix, a, b, c, true);
649   }
650 
651   @Override
fillTriangle3f(P3 pointA, P3 pointB, P3 pointC, boolean setNoisy)652   public void fillTriangle3f(P3 pointA, P3 pointB, P3 pointC, boolean setNoisy) {
653     // rockets (not cartesian)
654     exporter.fillTriangle(colix, pointA, pointB, pointC, false);
655   }
656 
657   @Override
fillTriangle3i(P3 screenA, P3 screenB, P3 screenC, T3 ptA0, T3 ptB0, T3 ptC0, boolean doShade)658   public void fillTriangle3i(P3 screenA, P3 screenB, P3 screenC, T3 ptA0,
659                              T3 ptB0, T3 ptC0, boolean doShade) {
660     // cartoon only, for nucleic acid bases
661       exporter.fillTriangle(colix, screenA, screenB, screenC, true);
662   }
663 
664   /*
665    * ***************************************************************
666    * quadrilaterals
667    * **************************************************************
668    */
669 
670   @Override
fillQuadrilateral(P3 pointA, P3 pointB, P3 pointC, P3 pointD, boolean isSolid)671   public void fillQuadrilateral(P3 pointA, P3 pointB, P3 pointC, P3 pointD, boolean isSolid) {
672     // fillTextRect
673     // hermite, rockets, cartoons, labels
674     exporter.fillTriangle(colix, pointA, pointB, pointC, false);
675     exporter.fillTriangle(colix, pointA, pointC, pointD, false);
676   }
677 
678   @Override
drawSurface(MeshSurface meshSurface, short colix)679   public void drawSurface(MeshSurface meshSurface, short colix) {
680     exporter.drawSurface(meshSurface, colix);
681   }
682 
683   @Override
fillEllipsoid(P3 center, P3[] points, int x, int y, int z, int diameter, M3 mToEllipsoidal, double[] coef, M4 mDeriv, int selectedOctant, P3[] octantPoints)684   public void fillEllipsoid(P3 center, P3[] points, int x, int y, int z,
685                             int diameter, M3 mToEllipsoidal, double[] coef,
686                             M4 mDeriv, int selectedOctant, P3[] octantPoints) {
687     exporter.fillEllipsoid(center, points, colix, x, y, z, diameter,
688         mToEllipsoidal, coef, mDeriv, octantPoints);
689   }
690 
691   @Override
drawEllipse(P3 ptAtom, P3 ptX, P3 ptY, boolean fillArc, boolean wireframeOnly)692   public boolean drawEllipse(P3 ptAtom, P3 ptX, P3 ptY, boolean fillArc,
693                              boolean wireframeOnly) {
694     return exporter.drawEllipse(ptAtom, ptX, ptY, colix, fillArc);
695   }
696 
697   /*
698    * *************************************************************** g3d-relayed
699    * info specifically needed for the renderers
700    * **************************************************************
701    */
702 
703   /**
704    * is full scene / oversampling antialiasing in effect
705    *
706    * @return the answer
707    */
708   @Override
isAntialiased()709   public boolean isAntialiased() {
710     return false;
711   }
712 
713   @Override
checkTranslucent(boolean isAlphaTranslucent)714   public boolean checkTranslucent(boolean isAlphaTranslucent) {
715     return true;
716   }
717 
718   @Override
haveTranslucentObjects()719   public boolean haveTranslucentObjects() {
720     return true;
721   }
722 
723   /**
724    * sets current color from colix color index
725    *
726    * @param colix
727    *        the color index
728    * @return true or false if this is the right pass
729    */
730   @Override
setC(short colix)731   public boolean setC(short colix) {
732     this.colix = colix;
733     gdata.setC(colix);
734     return true;
735   }
736 
737   @Override
isInDisplayRange(int x, int y)738   public boolean isInDisplayRange(int x, int y) {
739     return (isCartesian || gdata.isInDisplayRange(x, y));
740   }
741 
clipCode(int x, int y, int z)742   public int clipCode(int x, int y, int z) {
743     return (isCartesian ? gdata.clipCode(z)
744         : gdata.clipCode3(x, y, z));
745   }
746 
747   @Override
isClippedXY(int diameter, int x, int y)748   public boolean isClippedXY(int diameter, int x, int y) {
749     return (!isCartesian && gdata.isClippedXY(diameter, x, y));
750   }
751 
isClipped(int x, int y, int z)752   public boolean isClipped(int x, int y, int z) {
753     return (gdata.isClippedZ(z) || isClipped(x, y));
754   }
755 
isClipped(int x, int y)756   protected boolean isClipped(int x, int y) {
757     return (!isCartesian && gdata.isClipped(x, y));
758   }
759 
getPrivateKey()760   public double getPrivateKey() {
761     return privateKey;
762   }
763 
764   @Override
volumeRender4(int diam, int x, int y, int z)765   public void volumeRender4(int diam, int x, int y, int z) {
766     fillSphereXYZ(diam, x, y, z);
767   }
768 
769   @Override
renderCrossHairs(int[] minMax, int screenWidth, int screenHeight, P3 navigationOffset, float navigationDepthPercent)770   public void renderCrossHairs(int[] minMax, int screenWidth, int screenHeight,
771                                P3 navigationOffset, float navigationDepthPercent) {
772   }
773 
774   @Override
volumeRender(boolean TF)775   public void volumeRender(boolean TF) {
776     // TODO
777 
778   }
779 
780   @Override
addRenderer(int tok)781   public void addRenderer(int tok) {
782     if (tok == T.hermitelevel)
783       hermite3d = (HermiteRenderer) new HermiteRenderer().set(this, gdata);
784   }
785 
786   @Override
plotImagePixel(int argb, int x, int y, int z, byte shade, int bgargb, int width, int height, int[] pbuf, Object p, int transpLog)787   public void plotImagePixel(int argb, int x, int y, int z, byte shade,
788                              int bgargb, int width, int height, int[] pbuf, Object p, int transpLog) {
789     // from Text3D
790     if (webGL)
791       return;
792     z = Math.max(slab, z);
793     if (shade != 0) {
794       // so shade 1 ==> 0xEE (almost opaque)
795       //    shade 7 ==> 0x11 (almost transparent)
796       int a = (shade == 8 ? 0xFF : ((8 - shade) << 4) + (8 - shade));
797       argb = (argb & 0xFFFFFF) | (a << 24);
798     }
799     exporter.drawTextPixel(argb, x, y, z);
800   }
801 
802   @Override
drawHermite7(boolean fill, boolean border, int tension, P3 s0, P3 s1, P3 s2, P3 s3, P3 s4, P3 s5, P3 s6, P3 s7, int aspectRatio, short colixBack)803   public void drawHermite7(boolean fill, boolean border, int tension, P3 s0,
804                            P3 s1, P3 s2, P3 s3, P3 s4, P3 s5, P3 s6,
805                            P3 s7, int aspectRatio, short colixBack) {
806     if (colixBack == 0 || webGL) {
807       hermite3d.renderHermiteRibbon(fill, border, tension, s0, s1, s2, s3, s4,
808           s5, s6, s7, aspectRatio, 0);
809       return;
810     }
811     hermite3d.renderHermiteRibbon(fill, border, tension, s0, s1, s2, s3, s4,
812         s5, s6, s7, aspectRatio, 1);
813     short colix = this.colix;
814     setC(colixBack);
815     hermite3d.renderHermiteRibbon(fill, border, tension, s0, s1, s2, s3, s4,
816         s5, s6, s7, aspectRatio, -1);
817     setC(colix);
818   }
819 
820   @Override
renderAllStrings(Object jr)821   public void renderAllStrings(Object jr) {
822     if (webGL) {
823       // TODO
824       return;
825     }
826     gdata.renderAllStrings(this);
827   }
828 
829 }
830