~ubuntu-branches/ubuntu/utopic/sweethome3d/utopic-proposed

« back to all changes in this revision

Viewing changes to src/com/eteks/sweethome3d/j3d/PhotoRenderer.java

  • Committer: Bazaar Package Importer
  • Author(s): Gabriele Giacone
  • Date: 2010-05-29 13:17:46 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20100529131746-mix5l902gjywddob
Tags: 2.4+dfsg-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
39
39
import javax.media.j3d.ColoringAttributes;
40
40
import javax.media.j3d.Geometry;
41
41
import javax.media.j3d.GeometryArray;
 
42
import javax.media.j3d.GeometryStripArray;
42
43
import javax.media.j3d.Group;
43
44
import javax.media.j3d.ImageComponent2D;
44
45
import javax.media.j3d.IndexedGeometryArray;
 
46
import javax.media.j3d.IndexedGeometryStripArray;
 
47
import javax.media.j3d.IndexedLineArray;
 
48
import javax.media.j3d.IndexedLineStripArray;
45
49
import javax.media.j3d.IndexedQuadArray;
46
50
import javax.media.j3d.IndexedTriangleArray;
47
51
import javax.media.j3d.IndexedTriangleFanArray;
48
52
import javax.media.j3d.IndexedTriangleStripArray;
 
53
import javax.media.j3d.LineArray;
 
54
import javax.media.j3d.LineStripArray;
 
55
import javax.media.j3d.Link;
49
56
import javax.media.j3d.Material;
50
57
import javax.media.j3d.Node;
 
58
import javax.media.j3d.PolygonAttributes;
51
59
import javax.media.j3d.QuadArray;
52
60
import javax.media.j3d.RenderingAttributes;
53
61
import javax.media.j3d.Shape3D;
293
301
   * Exports the given Java 3D <code>node</code> and its children to Sunflow API.  
294
302
   */
295
303
  private void exportNode(Node node, boolean noConstantShader) throws IOException {
296
 
    exportNode(node, node, noConstantShader);
 
304
    exportNode(node, noConstantShader, new Transform3D());
297
305
  }
298
306
 
299
307
  /**
300
308
   * Exports all the 3D shapes children of <code>node</code> at OBJ format.
301
309
   */ 
302
 
  private void exportNode(Node parent, Node node, 
303
 
                          boolean noConstantShader) throws IOException {
 
310
  private void exportNode(Node node, 
 
311
                          boolean noConstantShader,
 
312
                          Transform3D parentTransformations) throws IOException {
304
313
    if (node instanceof Group) {
 
314
      if (node instanceof TransformGroup) {
 
315
        parentTransformations = new Transform3D(parentTransformations);
 
316
        Transform3D transform = new Transform3D();
 
317
        ((TransformGroup)node).getTransform(transform);
 
318
        parentTransformations.mul(transform);
 
319
      }
305
320
      // Export all children
306
321
      Enumeration<?> enumeration = ((Group)node).getAllChildren(); 
307
322
      while (enumeration.hasMoreElements()) {
308
 
        exportNode(parent, (Node)enumeration.nextElement(), noConstantShader);
 
323
        exportNode((Node)enumeration.nextElement(), noConstantShader, parentTransformations);
309
324
      }
 
325
    } else if (node instanceof Link) {
 
326
      exportNode(((Link)node).getSharedGroup(), noConstantShader, parentTransformations);
310
327
    } else if (node instanceof Shape3D) {
311
328
      Shape3D shape = (Shape3D)node;
312
329
      Appearance appearance = shape.getAppearance();
315
332
          || renderingAttributes.getVisible()) {
316
333
        String shapeName = (String)shape.getUserData();
317
334
        
318
 
        // Retrieve transformation needed to be applied to vertices
319
 
        Transform3D transformationToParent = getTransformationToParent(parent, node);
320
 
  
321
335
        // Build a unique object name
322
336
        String uuid = UUID.randomUUID().toString();
323
337
  
330
344
              && shapeName.startsWith(ModelManager.MIRROR_SHAPE_PREFIX);
331
345
          exportAppearance(appearance, appearanceName, mirror, noConstantShader);
332
346
        }
333
 
  
 
347
 
 
348
        int cullFace = PolygonAttributes.CULL_BACK;
 
349
        boolean backFaceNormalFlip = false;
 
350
        if (appearance != null) {
 
351
          PolygonAttributes polygonAttributes = appearance.getPolygonAttributes();
 
352
          if (polygonAttributes != null) {
 
353
            cullFace = polygonAttributes.getCullFace();
 
354
            backFaceNormalFlip = polygonAttributes.getBackFaceNormalFlip();
 
355
          }
 
356
        }
 
357
 
334
358
        // Export object geometries
335
359
        for (int i = 0, n = shape.numGeometries(); i < n; i++) {
336
 
          String objectName = "object" + uuid + "-" + i;
 
360
          String objectNameBase = "object" + uuid + "-" + i;
337
361
          // Always ignore normals on walls
338
 
          exportNodeGeometry(shape.getGeometry(i), transformationToParent, texCoordGeneration, objectName);
339
 
          if (appearanceName != null) {
340
 
            this.sunflow.parameter("shaders", new String [] {appearanceName});
 
362
          String [] objectsName = exportNodeGeometry(shape.getGeometry(i), parentTransformations, texCoordGeneration, 
 
363
              objectNameBase, cullFace, backFaceNormalFlip);
 
364
          if (objectsName != null) {
 
365
            for (String objectName : objectsName) {
 
366
              if (appearanceName != null) {
 
367
                this.sunflow.parameter("shaders", new String [] {appearanceName});
 
368
              }
 
369
              this.sunflow.instance(objectName + ".instance", objectName);
 
370
            }
341
371
          }
342
 
          this.sunflow.instance(objectName + ".instance", objectName);
343
372
        }
344
373
      }
345
374
    }    
346
375
  }
347
376
  
348
377
  /**
349
 
   * Returns the transformation applied to a <code>child</code> 
350
 
   * on the path to <code>parent</code>. 
351
 
   */
352
 
  private Transform3D getTransformationToParent(Node parent, Node child) {
353
 
    Transform3D transform = new Transform3D();
354
 
    if (child instanceof TransformGroup) {
355
 
      ((TransformGroup)child).getTransform(transform);
356
 
    }
357
 
    if (child != parent) {
358
 
      Transform3D parentTransform = getTransformationToParent(parent, child.getParent());
359
 
      parentTransform.mul(transform);
360
 
      return parentTransform;
361
 
    } else {
362
 
      return transform;
363
 
    }
364
 
  }
365
 
  
366
 
  /**
367
 
   * Exports a 3D geometry in Sunflow API.
368
 
   */
369
 
  private void exportNodeGeometry(Geometry geometry, Transform3D transformationToParent, 
370
 
                                  TexCoordGeneration texCoordGeneration, 
371
 
                                  String objectName) {
 
378
   * Returns the names of the exported 3D geometries in Sunflow API.
 
379
   */
 
380
  private String [] exportNodeGeometry(Geometry geometry, 
 
381
                                       Transform3D parentTransformations, 
 
382
                                       TexCoordGeneration texCoordGeneration, 
 
383
                                       String objectNameBase, 
 
384
                                       int cullFace, 
 
385
                                       boolean backFaceNormalFlip) {
372
386
    if (geometry instanceof GeometryArray) {
373
387
      GeometryArray geometryArray = (GeometryArray)geometry;
374
388
      
375
389
      // Create vertices indices array depending on geometry class
376
390
      int [] verticesIndices = null;
377
391
      int [] stripVertexCount = null;
 
392
      int cullFaceMultiplier = cullFace == PolygonAttributes.CULL_NONE ? 2 : 1;
378
393
      if (geometryArray instanceof IndexedGeometryArray) {
379
 
        if (geometryArray instanceof IndexedTriangleArray) {
380
 
          verticesIndices = new int [((IndexedTriangleArray)geometryArray).getIndexCount()];
 
394
        if (geometryArray instanceof IndexedLineArray) {
 
395
          verticesIndices = new int [((IndexedGeometryArray)geometryArray).getIndexCount()];
 
396
        } else if (geometryArray instanceof IndexedTriangleArray) {
 
397
          verticesIndices = new int [((IndexedGeometryArray)geometryArray).getIndexCount() * cullFaceMultiplier];
381
398
        } else if (geometryArray instanceof IndexedQuadArray) {
382
 
          verticesIndices = new int [((IndexedQuadArray)geometryArray).getIndexCount() * 3 / 2];
383
 
        } else if (geometryArray instanceof IndexedTriangleStripArray) {
384
 
          IndexedTriangleStripArray triangleStripArray = (IndexedTriangleStripArray)geometryArray;
385
 
          stripVertexCount = new int [triangleStripArray.getNumStrips()];
386
 
          triangleStripArray.getStripIndexCounts(stripVertexCount);
387
 
          verticesIndices = new int [getTriangleCount(stripVertexCount) * 3];
388
 
        } else if (geometryArray instanceof IndexedTriangleFanArray) {
389
 
          IndexedTriangleFanArray triangleFanArray = (IndexedTriangleFanArray)geometryArray;
390
 
          stripVertexCount = new int [triangleFanArray.getNumStrips()];
391
 
          triangleFanArray.getStripIndexCounts(stripVertexCount);
392
 
          verticesIndices = new int [getTriangleCount(stripVertexCount) * 3];
393
 
        } 
 
399
          verticesIndices = new int [((IndexedQuadArray)geometryArray).getIndexCount() * 3 / 2 * cullFaceMultiplier];
 
400
        } else if (geometryArray instanceof IndexedGeometryStripArray) {
 
401
          IndexedTriangleStripArray geometryStripArray = (IndexedTriangleStripArray)geometryArray;
 
402
          stripVertexCount = new int [geometryStripArray.getNumStrips()];
 
403
          geometryStripArray.getStripIndexCounts(stripVertexCount);          
 
404
          if (geometryArray instanceof IndexedLineStripArray) {
 
405
            verticesIndices = new int [getLineCount(stripVertexCount) * 2];
 
406
          } else {
 
407
            verticesIndices = new int [getTriangleCount(stripVertexCount) * 3 * cullFaceMultiplier];
 
408
          } 
 
409
        }
394
410
      } else {
395
 
        if (geometryArray instanceof TriangleArray) {
396
 
          verticesIndices = new int [((TriangleArray)geometryArray).getVertexCount()];
 
411
        if (geometryArray instanceof LineArray) {
 
412
          verticesIndices = new int [((GeometryArray)geometryArray).getVertexCount()];
 
413
        } else if (geometryArray instanceof TriangleArray) {
 
414
          verticesIndices = new int [((GeometryArray)geometryArray).getVertexCount() * cullFaceMultiplier];
397
415
        } else if (geometryArray instanceof QuadArray) {
398
 
          verticesIndices = new int [((QuadArray)geometryArray).getVertexCount() * 3 / 2];
399
 
        } else if (geometryArray instanceof TriangleStripArray) {
400
 
          TriangleStripArray triangleStripArray = (TriangleStripArray)geometryArray;
401
 
          stripVertexCount = new int [triangleStripArray.getNumStrips()];
402
 
          triangleStripArray.getStripVertexCounts(stripVertexCount);
403
 
          verticesIndices = new int [getTriangleCount(stripVertexCount) * 3];
404
 
        } else if (geometryArray instanceof TriangleFanArray) {
405
 
          TriangleFanArray triangleFanArray = (TriangleFanArray)geometryArray;
406
 
          stripVertexCount = new int [triangleFanArray.getNumStrips()];
407
 
          triangleFanArray.getStripVertexCounts(stripVertexCount);
408
 
          verticesIndices = new int [getTriangleCount(stripVertexCount) * 3];
 
416
          verticesIndices = new int [((QuadArray)geometryArray).getVertexCount() * 3 / 2 * cullFaceMultiplier];
 
417
        } else if (geometryArray instanceof GeometryStripArray) {
 
418
          GeometryStripArray geometryStripArray = (GeometryStripArray)geometryArray;
 
419
          stripVertexCount = new int [geometryStripArray.getNumStrips() * cullFaceMultiplier];
 
420
          geometryStripArray.getStripVertexCounts(stripVertexCount);
 
421
          if (geometryArray instanceof LineStripArray) {
 
422
            verticesIndices = new int [getLineCount(stripVertexCount) * 2];
 
423
          } else {
 
424
            verticesIndices = new int [getTriangleCount(stripVertexCount) * 3 * cullFaceMultiplier];
 
425
          }       
409
426
        }
410
427
      }
411
428
 
412
429
      if (verticesIndices != null) {
 
430
        boolean line = geometryArray instanceof IndexedLineArray
 
431
            || geometryArray instanceof IndexedLineStripArray
 
432
            || geometryArray instanceof LineArray
 
433
            || geometryArray instanceof LineStripArray;
413
434
        float [] vertices = new float [geometryArray.getVertexCount() * 3];
414
 
        
415
 
        float [] normals = (geometryArray.getVertexFormat() & GeometryArray.NORMALS) != 0
416
 
            ? new float [geometryArray.getVertexCount() * 3]
417
 
            : null;
 
435
        float [] normals = !line && (geometryArray.getVertexFormat() & GeometryArray.NORMALS) != 0
 
436
            ? new float [geometryArray.getVertexCount() * 3 * cullFaceMultiplier]
 
437
            : null;        
418
438
        
419
439
        boolean uvsGenerated = false;
420
440
        Vector4f planeS = null;
421
441
        Vector4f planeT = null;
422
 
        if (texCoordGeneration != null) {
 
442
        if (!line && texCoordGeneration != null) {
423
443
          uvsGenerated = texCoordGeneration.getGenMode() == TexCoordGeneration.OBJECT_LINEAR
424
444
              && texCoordGeneration.getEnable();
425
445
          if (uvsGenerated) {
446
466
            for (int index = 0, i = vertexSize - 3, n = geometryArray.getVertexCount(); 
447
467
                 index < n; index++, i += vertexSize) {
448
468
              Point3f vertex = new Point3f(vertexData [i], vertexData [i + 1], vertexData [i + 2]);
449
 
              exportVertex(transformationToParent, vertex, index, vertices);
 
469
              exportVertex(parentTransformations, vertex, index, vertices);
450
470
            }
451
471
            // Export normals
452
472
            if (normals != null) {
453
473
              for (int index = 0, i = vertexSize - 6, n = geometryArray.getVertexCount(); 
454
474
                   index < n; index++, i += vertexSize) {
455
475
                Vector3f normal = new Vector3f(vertexData [i], vertexData [i + 1], vertexData [i + 2]);
456
 
                exportNormal(transformationToParent, normal, index, normals);
 
476
                exportNormal(parentTransformations, normal, index, normals, cullFace, backFaceNormalFlip);
457
477
              }
458
478
            }
459
479
            // Export texture coordinates
478
498
            float [] vertexCoordinates = geometryArray.getCoordRefFloat();
479
499
            for (int index = 0, i = 0, n = geometryArray.getVertexCount(); index < n; index++, i += 3) {
480
500
              Point3f vertex = new Point3f(vertexCoordinates [i], vertexCoordinates [i + 1], vertexCoordinates [i + 2]);
481
 
              exportVertex(transformationToParent, vertex, index, vertices);
 
501
              exportVertex(parentTransformations, vertex, index, vertices);
482
502
            }
483
503
            // Export normals
484
504
            if (normals != null) {
485
505
              float [] normalCoordinates = geometryArray.getNormalRefFloat();
486
506
              for (int index = 0, i = 0, n = geometryArray.getVertexCount(); index < n; index++, i += 3) {
487
507
                Vector3f normal = new Vector3f(normalCoordinates [i], normalCoordinates [i + 1], normalCoordinates [i + 2]);
488
 
                exportNormal(transformationToParent, normal, index, normals);
 
508
                exportNormal(parentTransformations, normal, index, normals, cullFace, backFaceNormalFlip);
489
509
              }
490
510
            }
491
511
            // Export texture coordinates
510
530
          for (int index = 0, n = geometryArray.getVertexCount(); index < n; index++) {
511
531
            Point3f vertex = new Point3f();
512
532
            geometryArray.getCoordinate(index, vertex);
513
 
            exportVertex(transformationToParent, vertex, index, vertices);
 
533
            exportVertex(parentTransformations, vertex, index, vertices);
514
534
          }
515
535
          // Export normals
516
536
          if (normals != null) {
517
537
            for (int index = 0, n = geometryArray.getVertexCount(); index < n; index++) {
518
538
              Vector3f normal = new Vector3f();
519
539
              geometryArray.getNormal(index, normal);
520
 
              exportNormal(transformationToParent, normal, index, normals);
 
540
              exportNormal(parentTransformations, normal, index, normals, cullFace, backFaceNormalFlip);
521
541
            }
522
542
          }
523
543
          // Export texture coordinates
540
560
          }
541
561
        }
542
562
 
543
 
        // Export triangles or quadrilaterals depending on the geometry
 
563
        // Export lines, triangles or quadrilaterals depending on the geometry
544
564
        if (geometryArray instanceof IndexedGeometryArray) {
545
565
          int [] normalsIndices = normals != null
546
566
              ? new int [verticesIndices.length]
549
569
              ? new int [verticesIndices.length]
550
570
              : null;
551
571
              
552
 
          if (geometryArray instanceof IndexedTriangleArray) {
 
572
          if (geometryArray instanceof IndexedLineArray) {
 
573
            IndexedLineArray lineArray = (IndexedLineArray)geometryArray;
 
574
            for (int i = 0, n = lineArray.getIndexCount(); i < n; i += 2) {
 
575
              exportIndexedLine(lineArray, i, i + 1, verticesIndices, i);
 
576
            }
 
577
          } else if (geometryArray instanceof IndexedTriangleArray) {
553
578
            IndexedTriangleArray triangleArray = (IndexedTriangleArray)geometryArray;
554
579
            for (int i = 0, n = triangleArray.getIndexCount(); i < n; i += 3) {
555
580
              exportIndexedTriangle(triangleArray, i, i + 1, i + 2, 
556
 
                  verticesIndices, normalsIndices, uvsIndices, i);
 
581
                  verticesIndices, normalsIndices, uvsIndices, i, 0, cullFace);
557
582
            }
558
583
          } else if (geometryArray instanceof IndexedQuadArray) {
559
584
            IndexedQuadArray quadArray = (IndexedQuadArray)geometryArray;
560
585
            for (int i = 0, n = quadArray.getIndexCount(); i < n; i += 4) {
561
586
              exportIndexedTriangle(quadArray, i, i + 1, i + 2, 
562
 
                  verticesIndices, normalsIndices, uvsIndices, i * 3 / 2);
 
587
                  verticesIndices, normalsIndices, uvsIndices, i * 3 / 2, 0, cullFace);
563
588
              exportIndexedTriangle(quadArray, i, i + 2, i + 3, 
564
 
                  verticesIndices, normalsIndices, uvsIndices, i * 3 / 2 + 3);
 
589
                  verticesIndices, normalsIndices, uvsIndices, i * 3 / 2 + 3, 0, cullFace);
 
590
            }
 
591
          } else if (geometryArray instanceof IndexedLineStripArray) {
 
592
            IndexedLineStripArray lineStripArray = (IndexedLineStripArray)geometryArray;
 
593
            for (int initialIndex = 0, lineIndex = 0, strip = 0; strip < stripVertexCount.length; strip++) {
 
594
              for (int i = initialIndex, n = initialIndex + stripVertexCount [strip] - 1; 
 
595
                   i < n; i++, lineIndex += 2) {
 
596
                 exportIndexedLine(lineStripArray, i, i + 1, verticesIndices, lineIndex);
 
597
              }
 
598
              initialIndex += stripVertexCount [strip];
565
599
            }
566
600
          } else if (geometryArray instanceof IndexedTriangleStripArray) {
567
601
            IndexedTriangleStripArray triangleStripArray = (IndexedTriangleStripArray)geometryArray;
570
604
                   i < n; i++, j++, triangleIndex += 3) {
571
605
                if (j % 2 == 0) {
572
606
                  exportIndexedTriangle(triangleStripArray, i, i + 1, i + 2, 
573
 
                      verticesIndices, normalsIndices, uvsIndices, triangleIndex);
 
607
                      verticesIndices, normalsIndices, uvsIndices, triangleIndex, 0, cullFace);
574
608
                } else { // Vertices of odd triangles are in reverse order               
575
609
                  exportIndexedTriangle(triangleStripArray, i, i + 2, i + 1, 
576
 
                      verticesIndices, normalsIndices, uvsIndices, triangleIndex);
 
610
                      verticesIndices, normalsIndices, uvsIndices, triangleIndex, 0, cullFace);
577
611
                }
578
612
              }
579
613
              initialIndex += stripVertexCount [strip];
584
618
              for (int i = initialIndex, n = initialIndex + stripVertexCount [strip] - 2; 
585
619
                   i < n; i++, triangleIndex += 3) {
586
620
                exportIndexedTriangle(triangleFanArray, initialIndex, i + 1, i + 2, 
587
 
                    verticesIndices, normalsIndices, uvsIndices, triangleIndex);
 
621
                    verticesIndices, normalsIndices, uvsIndices, triangleIndex, 0, cullFace);
588
622
              }
589
623
              initialIndex += stripVertexCount [strip];
590
624
            }
627
661
            uvs = directUvs;
628
662
          }
629
663
        } else {
630
 
          if (geometryArray instanceof TriangleArray) {
 
664
          if (geometryArray instanceof LineArray) {
 
665
            LineArray lineArray = (LineArray)geometryArray;
 
666
            for (int i = 0, n = lineArray.getVertexCount(); i < n; i += 2) {
 
667
              exportLine(lineArray, i, i + 1, verticesIndices, i);
 
668
            }
 
669
          } else if (geometryArray instanceof TriangleArray) {
631
670
            TriangleArray triangleArray = (TriangleArray)geometryArray;
632
671
            for (int i = 0, n = triangleArray.getVertexCount(); i < n; i += 3) {
633
 
              exportTriangle(triangleArray, i, i + 1, i + 2, verticesIndices, i);
 
672
              exportTriangle(triangleArray, i, i + 1, i + 2, verticesIndices, i, cullFace);
634
673
            }
635
674
          } else if (geometryArray instanceof QuadArray) {
636
675
            QuadArray quadArray = (QuadArray)geometryArray;
637
676
            for (int i = 0, n = quadArray.getVertexCount(); i < n; i += 4) {
638
 
              exportTriangle(quadArray, i, i + 1, i + 2, verticesIndices, i * 3 / 2);
639
 
              exportTriangle(quadArray, i + 2, i + 3, i, verticesIndices, i * 3 / 2 + 3);
 
677
              exportTriangle(quadArray, i, i + 1, i + 2, verticesIndices, i * 3 / 2, cullFace);
 
678
              exportTriangle(quadArray, i + 2, i + 3, i, verticesIndices, i * 3 / 2 + 3, cullFace);
 
679
            }
 
680
          } else if (geometryArray instanceof LineStripArray) {
 
681
            LineStripArray lineStripArray = (LineStripArray)geometryArray;
 
682
            for (int initialIndex = 0, lineIndex = 0, strip = 0; strip < stripVertexCount.length; strip++) {
 
683
              for (int i = initialIndex, n = initialIndex + stripVertexCount [strip] - 1; 
 
684
                   i < n; i++, lineIndex += 2) {
 
685
                exportLine(lineStripArray, i, i + 1, verticesIndices, lineIndex);
 
686
              }
 
687
              initialIndex += stripVertexCount [strip];
640
688
            }
641
689
          } else if (geometryArray instanceof TriangleStripArray) {
642
690
            TriangleStripArray triangleStripArray = (TriangleStripArray)geometryArray;
644
692
              for (int i = initialIndex, n = initialIndex + stripVertexCount [strip] - 2, j = 0; 
645
693
                   i < n; i++, j++, triangleIndex += 3) {
646
694
                if (j % 2 == 0) {
647
 
                  exportTriangle(triangleStripArray, i, i + 1, i + 2, verticesIndices, triangleIndex);
 
695
                  exportTriangle(triangleStripArray, i, i + 1, i + 2, verticesIndices, triangleIndex, cullFace);
648
696
                } else { // Vertices of odd triangles are in reverse order               
649
 
                  exportTriangle(triangleStripArray, i, i + 2, i + 1, verticesIndices, triangleIndex);
 
697
                  exportTriangle(triangleStripArray, i, i + 2, i + 1, verticesIndices, triangleIndex, cullFace);
650
698
                }
651
699
              }
652
700
              initialIndex += stripVertexCount [strip];
656
704
            for (int initialIndex = 0, triangleIndex = 0, strip = 0; strip < stripVertexCount.length; strip++) {
657
705
              for (int i = initialIndex, n = initialIndex + stripVertexCount [strip] - 2; 
658
706
                   i < n; i++, triangleIndex += 3) {
659
 
                exportTriangle(triangleFanArray, initialIndex, i + 1, i + 2, verticesIndices, triangleIndex);
 
707
                exportTriangle(triangleFanArray, initialIndex, i + 1, i + 2, verticesIndices, triangleIndex, cullFace);
660
708
              }
661
709
              initialIndex += stripVertexCount [strip];
662
710
            }
663
711
          }
664
712
        }
665
713
      
666
 
        this.sunflow.parameter("triangles", verticesIndices);
667
 
        this.sunflow.parameter("points", "point", "vertex", vertices);
668
 
        if (normals != null) {
669
 
          this.sunflow.parameter("normals", "vector", "vertex", normals);
670
 
        }
671
 
        if (uvs != null) {
672
 
          this.sunflow.parameter("uvs", "texcoord", "vertex", uvs);
673
 
        }
674
 
        this.sunflow.geometry(objectName, "triangle_mesh");
 
714
        if (line) {
 
715
          String [] objectNames = new String [verticesIndices.length / 2];
 
716
          for (int startIndex = 0; startIndex < verticesIndices.length; startIndex += 2) {
 
717
            String objectName = objectNameBase + "-" + startIndex;
 
718
            objectNames [startIndex / 2] = objectName;
 
719
            
 
720
            // Get points coordinates of a segment
 
721
            float [] points = new float [6];
 
722
            int pointIndex = 0;
 
723
            for (int i = startIndex; i <= startIndex + 1; i++) {
 
724
              int indirectIndex = verticesIndices [i] * 3;
 
725
              points [pointIndex++] = vertices [indirectIndex++];
 
726
              points [pointIndex++] = vertices [indirectIndex++];
 
727
              points [pointIndex++] = vertices [indirectIndex];
 
728
            }
 
729
            
 
730
            // Create as many hairs as segments otherwise long hairs become invisible
 
731
            this.sunflow.parameter("segments", 1);
 
732
            this.sunflow.parameter("widths", 0.15f);
 
733
            this.sunflow.parameter("points", "point", "vertex", points);
 
734
            this.sunflow.geometry(objectName, "hair");
 
735
          }
 
736
          return objectNames;
 
737
        } else {
 
738
          this.sunflow.parameter("triangles", verticesIndices);
 
739
          this.sunflow.parameter("points", "point", "vertex", vertices);
 
740
          if (normals != null) {
 
741
            this.sunflow.parameter("normals", "vector", "vertex", normals);
 
742
          }
 
743
          if (uvs != null) {
 
744
            this.sunflow.parameter("uvs", "texcoord", "vertex", uvs);
 
745
          }
 
746
          this.sunflow.geometry(objectNameBase, "triangle_mesh");
 
747
          return new String [] {objectNameBase};
 
748
        }
675
749
      }
676
750
    } 
 
751
    return null;
677
752
  }
678
753
  
679
754
  /**
688
763
  }
689
764
 
690
765
  /**
691
 
   * Returns the sum of the integers in <code>stripVertexCount</code> array.
 
766
   * Returns the sum of line integers in <code>stripVertexCount</code> array.
 
767
   */
 
768
  private int getLineCount(int [] stripVertexCount) {
 
769
    int lineCount = 0;
 
770
    for (int strip = 0; strip < stripVertexCount.length; strip++) {
 
771
      lineCount += stripVertexCount [strip] - 1;
 
772
    }
 
773
    return lineCount;
 
774
  }
 
775
 
 
776
  /**
 
777
   * Returns the sum of triangle integers in <code>stripVertexCount</code> array.
692
778
   */
693
779
  private int getTriangleCount(int [] stripVertexCount) {
694
780
    int triangleCount = 0;
716
802
   */
717
803
  private void exportNormal(Transform3D transformationToParent,
718
804
                            Vector3f normal, int index,
719
 
                            float [] normals) {
 
805
                            float [] normals, 
 
806
                            int cullFace, 
 
807
                            boolean backFaceNormalFlip) {
 
808
    if (backFaceNormalFlip) {
 
809
      normal.negate();
 
810
    }
 
811
    
720
812
    transformationToParent.transform(normal);
721
 
    index *= 3;
722
 
    normals [index++] = normal.x;
723
 
    normals [index++] = normal.y;
724
 
    normals [index] = normal.z;
 
813
    int i = index * 3;
 
814
    normals [i++] = normal.x;
 
815
    normals [i++] = normal.y;
 
816
    normals [i] = normal.z;
 
817
    
 
818
    if (cullFace == PolygonAttributes.CULL_NONE) {
 
819
      Vector3f oppositeNormal = new Vector3f(); 
 
820
      oppositeNormal.negate(normal);
 
821
      exportNormal(transformationToParent, oppositeNormal, index + normals.length / 6, normals, 
 
822
          PolygonAttributes.CULL_FRONT, false);
 
823
    }
725
824
  }
726
825
 
727
826
  /**
735
834
  }
736
835
 
737
836
  /**
738
 
   * Stores in <code>triangles</code> the indices given at vertexIndex1, vertexIndex2, vertexIndex3. 
 
837
   * Stores in <code>verticesIndices</code> the indices given at vertexIndex1, vertexIndex2. 
 
838
   */
 
839
  private void exportIndexedLine(IndexedGeometryArray geometryArray, 
 
840
                                 int vertexIndex1, int vertexIndex2,
 
841
                                 int [] verticesIndices, 
 
842
                                 int index) {
 
843
    verticesIndices [index++] = geometryArray.getCoordinateIndex(vertexIndex1);
 
844
    verticesIndices [index] = geometryArray.getCoordinateIndex(vertexIndex2);
 
845
  }
 
846
    
 
847
  /**
 
848
   * Stores in <code>verticesIndices</code> the indices given at vertexIndex1, vertexIndex2, vertexIndex3. 
739
849
   */
740
850
  private void exportIndexedTriangle(IndexedGeometryArray geometryArray, 
741
851
                                     int vertexIndex1, int vertexIndex2, int vertexIndex3,
742
852
                                     int [] verticesIndices, int [] normalsIndices, int [] textureCoordinatesIndices, 
743
 
                                     int index) {
 
853
                                     int index,
 
854
                                     int normalIndexOffset,
 
855
                                     int cullFace) {
 
856
    if (cullFace == PolygonAttributes.CULL_FRONT) {
 
857
      // Reverse vertex order
 
858
      int tmp = vertexIndex1;
 
859
      vertexIndex1 = vertexIndex3;
 
860
      vertexIndex3 = tmp;
 
861
    }
 
862
    
744
863
    verticesIndices [index] = geometryArray.getCoordinateIndex(vertexIndex1);
745
864
    verticesIndices [index + 1] = geometryArray.getCoordinateIndex(vertexIndex2);
746
865
    verticesIndices [index + 2] = geometryArray.getCoordinateIndex(vertexIndex3);
747
866
    if (normalsIndices != null) {
748
 
      normalsIndices [index] = geometryArray.getNormalIndex(vertexIndex1);
749
 
      normalsIndices [index + 1] = geometryArray.getNormalIndex(vertexIndex2);
750
 
      normalsIndices [index + 2] = geometryArray.getNormalIndex(vertexIndex3);
 
867
      normalsIndices [index] = normalIndexOffset + geometryArray.getNormalIndex(vertexIndex1);
 
868
      normalsIndices [index + 1] = normalIndexOffset + geometryArray.getNormalIndex(vertexIndex2);
 
869
      normalsIndices [index + 2] = normalIndexOffset + geometryArray.getNormalIndex(vertexIndex3);
751
870
    }
752
871
    if (textureCoordinatesIndices != null) {
753
872
      textureCoordinatesIndices [index] = geometryArray.getTextureCoordinateIndex(0, vertexIndex1);
754
873
      textureCoordinatesIndices [index + 1] = geometryArray.getTextureCoordinateIndex(0, vertexIndex2);
755
874
      textureCoordinatesIndices [index + 2] = geometryArray.getTextureCoordinateIndex(0, vertexIndex3);
756
875
    }
757
 
  }
758
 
    
759
 
  /**
760
 
   * Stores in <code>triangles</code> the indices vertexIndex1, vertexIndex2, vertexIndex3. 
 
876
    
 
877
    if (cullFace == PolygonAttributes.CULL_NONE) {   
 
878
      exportIndexedTriangle(geometryArray, vertexIndex1, vertexIndex2, vertexIndex3, 
 
879
          verticesIndices, normalsIndices, textureCoordinatesIndices,  
 
880
          index + verticesIndices.length / 2, normalsIndices != null ? normalsIndices.length / 2 : 0, 
 
881
          PolygonAttributes.CULL_FRONT);
 
882
    }
 
883
  }
 
884
    
 
885
  /**
 
886
   * Stores in <code>verticesIndices</code> the indices vertexIndex1, vertexIndex2, vertexIndex3. 
 
887
   */
 
888
  private void exportLine(GeometryArray geometryArray, 
 
889
                          int vertexIndex1, int vertexIndex2, 
 
890
                          int [] verticesIndices, int index) {
 
891
    verticesIndices [index++] = vertexIndex1;
 
892
    verticesIndices [index] = vertexIndex2;
 
893
  }
 
894
    
 
895
  /**
 
896
   * Stores in <code>verticesIndices</code> the indices vertexIndex1, vertexIndex2, vertexIndex3. 
761
897
   */
762
898
  private void exportTriangle(GeometryArray geometryArray, 
763
899
                              int vertexIndex1, int vertexIndex2, int vertexIndex3,
764
 
                              int [] verticesIndices, int index) {
765
 
    verticesIndices [index++] = vertexIndex1;
766
 
    verticesIndices [index++] = vertexIndex2;
767
 
    verticesIndices [index] = vertexIndex3;
 
900
                              int [] verticesIndices, int index,
 
901
                              int cullFace) {
 
902
    if (cullFace == PolygonAttributes.CULL_FRONT) {
 
903
      // Reverse vertex order
 
904
      int tmp = vertexIndex1;
 
905
      vertexIndex1 = vertexIndex3;
 
906
      vertexIndex3 = tmp;
 
907
    }
 
908
    
 
909
    verticesIndices [index] = vertexIndex1;
 
910
    verticesIndices [index + 1] = vertexIndex2;
 
911
    verticesIndices [index + 2] = vertexIndex3;
 
912
    
 
913
    if (cullFace == PolygonAttributes.CULL_NONE) {   
 
914
      exportTriangle(geometryArray, vertexIndex1, vertexIndex2, vertexIndex3, 
 
915
          verticesIndices, index + verticesIndices.length / 2, PolygonAttributes.CULL_FRONT);
 
916
    }
768
917
  }
769
918
    
770
919
  /**
788
937
      if (imageFile == null) {
789
938
        ImageComponent2D imageComponent = (ImageComponent2D)texture.getImage(0);
790
939
        RenderedImage image = imageComponent.getRenderedImage();
791
 
        imageFile = File.createTempFile("texture", ".jpg");
 
940
        String fileFormat = texture.getFormat() == Texture.RGBA 
 
941
            ? "png"
 
942
            : "jpg";
 
943
        imageFile = File.createTempFile("texture", "." + fileFormat);
792
944
        imageFile.deleteOnExit();
793
 
        ImageIO.write(image, "JPEG", imageFile);
 
945
        ImageIO.write(image, fileFormat, imageFile);
794
946
        this.textureImageFilesCache.put(texture, imageFile);
795
947
      }
796
948
      this.sunflow.parameter("texture", imageFile.getAbsolutePath());