View Javadoc

1   package org.textensor.vis;
2   
3   import java.awt.Color;
4   import java.util.ArrayList;
5   import java.util.HashMap;
6   import java.util.Random;
7   
8   import javax.media.j3d.Appearance;
9   import javax.media.j3d.BranchGroup;
10  import javax.media.j3d.GeometryArray;
11  import javax.media.j3d.Material;
12  import javax.media.j3d.Shape3D;
13  import javax.media.j3d.Transform3D;
14  import javax.media.j3d.TransformGroup;
15  import javax.media.j3d.TransparencyAttributes;
16  import javax.media.j3d.TriangleStripArray;
17  import javax.vecmath.Color3f;
18  import javax.vecmath.Vector3d;
19  
20  
21  public class SceneGraphBuilder {
22  
23  
24      BranchGroup baseGroup = null;
25  
26      HashMap<Color, Appearance> appHM = new HashMap<Color, Appearance>();
27  
28      Appearance defaultAppearance;
29  
30      Appearance[] randomAppearances;
31  
32      ArrayList<Shape3D> shapes;
33  
34  
35      public SceneGraphBuilder() {
36          defaultAppearance = makeDefaultAppearance();
37          randomAppearances = makeRandomAppearances(20);
38      }
39  
40  
41      private Appearance makeDefaultAppearance() {
42          Color3f aColor  = new Color3f(0.3f, 0.3f, 0.3f); // ambient
43          Color3f eColor  = new Color3f(0.0f, 0.0f, 0.0f); // emmissive
44          Color3f dColor  = new Color3f(0.6f, 0.6f, 0.6f); // diffuse
45          Color3f sColor  = new Color3f(0.8f, 0.8f, 0.8f); // specular
46  
47          Material m = new Material(aColor, eColor, dColor, sColor, 70.0f);
48          // specularity is on a range form 0 to 128
49          Appearance a = new Appearance();
50          m.setLightingEnable(true);
51          a.setMaterial(m);
52          return a;
53      }
54  
55      private Appearance[] makeRandomAppearances(int n) {
56          Random random = new Random();
57          ArrayList<Appearance> ala = new ArrayList<Appearance>();
58          for (int i = 0; i < n; i++) {
59              Color3f aColor  = randomColor(random, 0.3); // ambient
60              Color3f eColor  = new Color3f(0.0f, 0.0f, 0.0f);  // emmissive
61              Color3f dColor  =  rescale(aColor, 0.6); //randomColor(random, 0.6);// diffuse
62              Color3f sColor  = rescale(aColor, 0.8); // randomColor(random, 0.8); // specular
63  
64              Material m = new Material(aColor, eColor, dColor, sColor, 70.0f);
65              // specularity is on a range form 0 to 128
66              Appearance a = new Appearance();
67              m.setLightingEnable(true);
68              a.setMaterial(m);
69              /*
70              TransparencyAttributes ta = new TransparencyAttributes();
71              ta.setTransparencyMode (TransparencyAttributes.SCREEN_DOOR);
72              ta.setTransparency(0.1f);
73              a.setTransparencyAttributes(ta);
74               */
75              ala.add(a);
76          }
77          return ala.toArray(new Appearance[ala.size()]);
78      }
79  
80  
81      private Color3f rescale(Color3f c, double d) {
82          Color col = c.get();
83          double fr = col.getRed() / 256.;
84          double fg = col.getGreen() / 256.;
85          double fb = col.getBlue() / 256.;
86          double f = (fr + fg + fb) / 3;
87          Color3f ret = new Color3f(flimit(d * fr / f), flimit(d * fg / f), flimit(d * fb / f));
88          return ret;
89      }
90  
91      private float flimit(double x) {
92          double y = x;
93          if (y < 0.) {
94              y = 0.;
95          }
96          if (y > 1.) {
97              y = 1;
98          }
99          return (float)y;
100     }
101 
102     private Color3f randomColor(Random r, double d) {
103         double red = rcol(r, d);
104         double green = rcol(r, 1.5 * d);
105         double blue = rcol(r, d);
106 
107         Color3f ret  = new Color3f((float)red, (float)green, (float)blue);
108         return ret;
109     }
110 
111 
112     private double rcol(Random r, double d) {
113         double v = d + 0.15 * r.nextGaussian();
114         if (v > 1.0) {
115             v = 1.0;
116         }
117         if (v < 0.0) {
118             v = 0.0;
119         }
120         return v;
121     }
122 
123 
124 
125     private Appearance getAppearance(Color c) {
126         Appearance ret = null;
127         if (appHM.containsKey(c)) {
128             ret = appHM.get(c);
129 
130         } else {
131             Color3f aColor  = new Color3f(c.darker());
132             Color3f eColor  = new Color3f(0.0f, 0.0f, 0.0f); // emmissive
133             Color3f dColor  = new Color3f(c);
134             Color3f sColor  = new Color3f(c.brighter());
135 
136             Material m = new Material(aColor, eColor, dColor, sColor, 70.0f);
137             // specularity is on a range form 0 to 128
138             ret = new Appearance();
139             m.setLightingEnable(true);
140             ret.setMaterial(m);
141             appHM.put(c, ret);
142         }
143 
144         return ret;
145     }
146 
147 
148 
149 
150     public void buildTree(IcingPoint[] points, int res, double fac) {
151         // Timer t = new Timer();
152         buildFlatTree(points, res, fac);
153         // t.show("building base tree");
154     }
155 
156     private void buildFlatTree(IcingPoint[] points, int res, double fac) {
157         baseGroup = new BranchGroup();
158 
159         for (IcingPoint p : points) {
160             double x = p.getX();
161             double y = p.getY();
162             double z = p.getZ();
163             double r = p.getR();
164 
165             IcingPoint ppar = p.getParent();
166 
167             if (ppar == null) {
168                 // may or may not need a ball for it
169                 if (p.isBall()) {
170                     TransformGroup ctrans = new TransformGroup();
171                     Transform3D cpos = new Transform3D();
172                     cpos.setTranslation(new Vector3d(fac * x, fac * y, fac * z));
173                     ctrans.setTransform(cpos);
174 
175                     Shape3D s = new Shape3D();
176                     if (p.isColored3d()) {
177                         s.setAppearance(getAppearance(p.getColor()));
178                     } else {
179                         s.setAppearance(defaultAppearance);
180                     }
181                     TriangleStripArray tsa = mkSphereTriangles(fac * r, 5);
182                     s.setGeometry(tsa);
183 
184                     ctrans.addChild(s);
185 
186                     baseGroup.addChild(ctrans);
187 
188                 }
189 
190 
191             } else {
192                 double dx = ppar.getX() - x;
193                 double dy = ppar.getY() - y;
194                 double dz = ppar.getZ() - z;
195                 double lxy = Math.sqrt(dx * dx + dy * dy);
196 
197                 double d = Math.sqrt(dx*dx + dy*dy + dz*dz);
198 
199                 double ex = Math.atan2(dz, lxy);
200                 double ey = 0.;
201                 double ez = -Math.atan2(dx, dy);
202                 Vector3d veuler = new Vector3d(ex, ey, ez);
203 
204                 TransformGroup ctrans = new TransformGroup();
205                 Transform3D cpos = new Transform3D();
206                 cpos.setEuler(veuler);
207                 cpos.setTranslation(new Vector3d(fac * x, fac * y, fac * z));
208                 ctrans.setTransform(cpos);
209 
210                 Shape3D s = new Shape3D();
211                 if (p.isColored3d()) {
212                     s.setAppearance(getAppearance(p.getColor()));
213                 } else {
214                     s.setAppearance(defaultAppearance);
215                 }
216 
217 
218                 double pr = ppar.getR();
219                 if (p.isMinor() || p.uniform()) {
220                     pr = p.getR();
221                 }
222 
223 
224 
225                 if (res == Visualizer.LOW) {
226                     TriangleStripArray tsa = mkCarrotoidTriangles(fac * r, fac * pr, fac * d, 8, 1, 1);
227                     s.setGeometry(tsa);
228 
229                 } else if (res == Visualizer.MEDIUM) {
230                     TriangleStripArray tsa = mkCarrotoidTriangles(fac * r, fac * pr, fac * d, 16,
231                                              (p.ball ? 3 : 1), (ppar.ball ? 3 : 1));
232                     s.setGeometry(tsa);
233 
234                 } else if (res == Visualizer.HIGH) {
235                     TriangleStripArray tsa = mkCarrotoidTriangles(fac * r, fac * pr, fac * d, 22,
236                                              (p.ball ? 5 : 1), (ppar.ball ? 5 : 1));
237                     s.setGeometry(tsa);
238                 }
239 
240 
241                 ctrans.addChild(s);
242 
243                 baseGroup.addChild(ctrans);
244             }
245         }
246 
247 
248     }
249 
250 
251 
252 
253     private TriangleStripArray mkCarrotoidTriangles(double ra, double rb, double d,
254             int nside, int ncapa, int ncapb) {
255 
256         int nstrip = 1 + ncapa + ncapb;
257         int nvert = 2 * nside * nstrip;
258 
259         int[] svc = new int[nstrip];
260         for (int i = 0; i < nstrip; i++) {
261             svc[i] = 2 * nside;
262         }
263 
264         float[] datv = new float[3 * nvert];
265         float[] datn = new float[3 * nvert];
266 
267 
268         double dtheta = 2. * Math.PI / (nside-1);
269         double[][] csas = new double[nside][2];
270         double[][] csbs = new double[nside][2];
271         for (int i = 0; i <  nside; i++) {
272             double tha = i * dtheta;
273             double thb = (i + 0.5) * dtheta;
274             csas[i][0] = Math.cos(tha);
275             csas[i][1] = Math.sin(tha);
276 
277             csbs[i][0] = Math.cos(thb);
278             csbs[i][1] = Math.sin(thb);
279         }
280 
281         double dr = ra - rb;
282         double znorm = dr / Math.sqrt(dr*dr + d*d);
283         double zr = Math.sqrt(1. - znorm*znorm);
284         vnStrip(datv, datn, 0, nside, ra, rb, 0., d, znorm, zr, znorm, zr,  csas, csbs);
285 
286         int koff = 0;
287         koff += 6 * nside;
288 
289         double frad = 1.;
290         if (ncapa == 1) {
291             frad = 0.;
292         }
293 
294         for (int ic = 0; ic < ncapa; ic++) {
295             double[][] incs = (ic % 2 == 0 ? csbs : csas);
296             double[][] outcs = (ic % 2 == 0 ? csas : csbs);
297 
298             double t0 = ic * (0.5 * Math.PI / (ncapa + 0.1));
299             double t1 = (ic + 1) * (0.5 * Math.PI / (ncapa + 0.1));
300             double s0 = Math.sin(t0);
301             double c0 = Math.cos(t0);
302             double s1 = Math.sin(t1);
303             double c1 = Math.cos(t1);
304             vnStrip(datv, datn, koff, nside, c1 * ra, c0 * ra, -frad * s1 * ra, -frad * s0 * ra, -s1, c1, -s0, c0, incs, outcs);
305             koff += 6 * nside;
306         }
307 
308         frad = 1.;
309         if (ncapb == 1) {
310             frad = 0.;
311         }
312         for (int ic = 0; ic < ncapb; ic++) {
313             double[][] incs = (ic % 2 == 0 ? csbs : csas);
314             double[][] outcs = (ic % 2 == 0 ? csas : csbs);
315             double t0 = ic * (0.5 * Math.PI / (ncapb + 0.1));
316             double t1 = (ic + 1) * (0.5 * Math.PI / (ncapb + 0.1));
317             double s0 = Math.sin(t0);
318             double c0 = Math.cos(t0);
319             double s1 = Math.sin(t1);
320             double c1 = Math.cos(t1);
321             vnStrip(datv, datn, koff, nside, c0 * rb, c1 * rb, d + frad * s0 * rb, d + frad * s1 * rb, s0, c0, s1, c1, incs, outcs);
322             koff += 6 * nside;
323         }
324 
325         TriangleStripArray ret = new TriangleStripArray(nvert,
326                 GeometryArray.COORDINATES | GeometryArray.NORMALS, svc);
327         ret.setCoordinates(0, datv);
328         ret.setNormals(0, datn);
329         return ret;
330     }
331 
332 
333 
334 
335 
336 
337     private TriangleStripArray mkSphereTriangles(double ra, int ncap) {
338         int nside = 15;
339 
340         int nstrip = 2 * ncap;
341         int nvert = 2 * nside * nstrip;
342 
343         int[] svc = new int[nstrip];
344         for (int i = 0; i < nstrip; i++) {
345             svc[i] = 2 * nside;
346         }
347 
348         float[] datv = new float[3 * nvert];
349         float[] datn = new float[3 * nvert];
350 
351 
352         double dtheta = 2. * Math.PI / (nside-1);
353         double[][] csas = new double[nside][2];
354         double[][] csbs = new double[nside][2];
355         for (int i = 0; i <  nside; i++) {
356             double tha = i * dtheta;
357             double thb = (i + 0.5) * dtheta;
358             csas[i][0] = Math.cos(tha);
359             csas[i][1] = Math.sin(tha);
360 
361             csbs[i][0] = Math.cos(thb);
362             csbs[i][1] = Math.sin(thb);
363         }
364 
365         int koff = 0;
366 
367         for (int ic = 0; ic < ncap; ic++) {
368             double[][] incs = (ic % 2 == 0 ? csbs : csas);
369             double[][] outcs = (ic % 2 == 0 ? csas : csbs);
370 
371             double t0 = ic * (0.5 * Math.PI / (ncap + 0.1));
372             double t1 = (ic + 1) * (0.5 * Math.PI / (ncap + 0.1));
373             double s0 = Math.sin(t0);
374             double c0 = Math.cos(t0);
375             double s1 = Math.sin(t1);
376             double c1 = Math.cos(t1);
377             vnStrip(datv, datn, koff, nside, c1 * ra, c0 * ra, -1 * s1 * ra, -1 * s0 * ra, -s1, c1, -s0, c0, incs, outcs);
378             koff += 6 * nside;
379         }
380 
381 
382         for (int ic = 0; ic < ncap; ic++) {
383             double[][] incs = (ic % 2 == 0 ? csbs : csas);
384             double[][] outcs = (ic % 2 == 0 ? csas : csbs);
385             double t0 = ic * (0.5 * Math.PI / (ncap + 0.1));
386             double t1 = (ic + 1) * (0.5 * Math.PI / (ncap + 0.1));
387             double s0 = Math.sin(t0);
388             double c0 = Math.cos(t0);
389             double s1 = Math.sin(t1);
390             double c1 = Math.cos(t1);
391             vnStrip(datv, datn, koff, nside, c0 * ra, c1 * ra,  s0 * ra,  s1 * ra, s0, c0, s1, c1, incs, outcs);
392             koff += 6 * nside;
393         }
394 
395         TriangleStripArray ret = new TriangleStripArray(nvert,
396                 GeometryArray.COORDINATES | GeometryArray.NORMALS, svc);
397         ret.setCoordinates(0, datv);
398         ret.setNormals(0, datn);
399         return ret;
400     }
401 
402 
403 
404 
405     private void vnStrip(float[] datv, float[] datn, int koff, int nside, double ra, double rb, double da, double db, double s0, double c0, double s1, double c1, double[][] incs, double[][] outcs) {
406 
407         for (int i = 0; i < nside; i++) {
408             int k = koff + 6 * i;
409             datv[k] = (float)(ra * incs[i][0]);
410             datv[k+1] = (float)da;
411             datv[k+2] = (float)(ra * incs[i][1]);
412             datv[k+3] = (float)(rb * outcs[i][0]);
413             datv[k+4] = (float)db;
414             datv[k+5] = (float)(rb * outcs[i][1]);
415 
416             datn[k] = (float)(c0 * incs[i][0]);
417             datn[k+1] = (float)s0;
418             datn[k+2] = (float)(c0 * incs[i][1]);
419             datn[k+3] = (float)(c1 * outcs[i][0]);
420             datn[k+4] = (float)s1;
421             datn[k+5] = (float)(c1 * outcs[i][1]);
422         }
423     }
424 
425 
426     public  BranchGroup getSceneGraph() {
427         return baseGroup;
428     }
429 
430 
431     public void loadElements(ArrayList<VolElt> elements) {
432         baseGroup = new BranchGroup();
433 
434         shapes = new ArrayList<Shape3D>();
435 
436         int iel = 0;
437         for (VolElt ve : elements) {
438 
439             ve.centroidize();
440 
441             TransformGroup ctrans = new TransformGroup();
442             Transform3D cpos = new Transform3D();
443             cpos.setTranslation(new Vector3d(ve.getCX(), ve.getCY(), ve.getCZ()));
444             ctrans.setTransform(cpos);
445 
446             Shape3D s = new Shape3D();
447             shapes.add(s);
448 
449             s.setAppearance(defaultAppearance);
450 
451             int ira = (int)(Math.random() * (randomAppearances.length - 0.01));
452             Appearance app = randomAppearances[ira];
453             Appearance apc = (Appearance)(app.cloneNodeComponent(true));
454             apc.setCapability(Appearance.ALLOW_RENDERING_ATTRIBUTES_WRITE);
455             s.setAppearance(apc);
456 
457 
458             TriangleStripArray tsa = new TriangleStripArray(ve.getNvert(),
459                     GeometryArray.COORDINATES | GeometryArray.NORMALS, ve.getLens());
460             tsa.setCoordinates(0, ve.getVerts());
461             tsa.setNormals(0, ve.getNorms());
462 
463 
464             s.setGeometry(tsa);
465 
466             ctrans.addChild(s);
467 
468             baseGroup.addChild(ctrans);
469 
470             iel += 1;
471 
472         }
473     }
474 
475 
476     public ArrayList<Shape3D> getShapes() {
477         return shapes;
478     }
479 
480 }