# 2 Texturen & transparenz



## DeziBell (12. Mai 2006)

Hallo nochmal !!

Ich hab jetzt einige Java3D Textur Tutorials durch, doch keins konnte mir erklären wie ich 
Alphablending realisiere. Transparente Objekte geht, klar! Textur krieg ich auch geladen und 
aufs Objekt gemappt.

Ich will nun eine zweite (Schwarz-Weiß) Textur laden, und diese so mit der ersten verknüpfen, 
das nur die Teile der esten Textur sichtbar werden, an denen die zweite weiss ist. Alles andere 
transparent.

Aus DirectX kenn ich es so, und hoffe das geht ähnlich einfach in J3D. 

Versteht mich jemand ??*g
Kann mir jemand Tipps/Anregungen geben?
Kann mir jemand helfen???

DeziBell sagt danke


----------



## DeziBell (13. Mai 2006)

Hier das erste konkrete Problem. Ich habe ein Image (Bild) als Hintergrund (Weltraum,Sternenhimmel etc). Auf diesen Hintergrund lege ich ein weiteres Image (Bild eines Raumschiffs). die schwarzen Stellen auf dem Bild des Raumschiffs  sollen Transparent werden. (Sieht nicht schön aus wenn Quadrate über den Bildschirm fliegen).

Hab hier  Beispiel-Code. damit erzeuge ich 2 texturierte Ebenen. In der if/else Anweisung sollte jetzt nur noch die Transparenz so eingestellt werden das die richtigen Stellen des Bildes transparent werden.


```
public BranchGroup createSceneGraph()
    {
       BranchGroup scene = new BranchGroup();
       // Hintergrund Ebene erzeugen
       scene.addChild(new Shape3D(makeGeometry(10.0f,-10.0f), makeAppearance("Background.jpg",false))); // HINTERGRUND
       // Teil-Transparente Ebene erzeugen
       scene.addChild(new Shape3D(makeGeometry(1.0f, -6.0f),  makeAppearance("Raumschiff.jpg",true)));  // VORDERGRUND
       
       scene.compile();
       return scene;
    }

    
    private TriangleArray makeGeometry(float scale, float z)
    {

       TriangleArray tri= new TriangleArray (6,TriangleArray.COORDINATES|TriangleArray.TEXTURE_COORDINATE_2);
       
       tri.setCoordinate(0, new Point3f(-1.0f*scale,  1.0f*scale, z)); // oben  Links
       tri.setCoordinate(1, new Point3f(-1.0f*scale, -1.0f*scale, z)); // unten Links
       tri.setCoordinate(2, new Point3f( 1.0f*scale,  1.0f*scale, z)); // oben  Rechts
       
       tri.setCoordinate(3, new Point3f( 1.0f*scale,  1.0f*scale, z)); // oben  Rechts
       tri.setCoordinate(4, new Point3f(-1.0f*scale, -1.0f*scale, z)); // unten Links
       tri.setCoordinate(5, new Point3f( 1.0f*scale, -1.0f*scale, z)); // unten Rechts
       
       float [] tex = new float[2];
       
       tex[0] = 0.0f; tex[1] = 1.0f;        // oben  Links
       tri.setTextureCoordinates(0,0,tex);  
       tex[0] = 0.0f; tex[1] = 0.0f;        // unten Links
       tri.setTextureCoordinates(0,1,tex);
       tex[0] = 1.0f; tex[1] = 1.0f;        // oben  Rechts
       tri.setTextureCoordinates(0,2,tex);
               
       tex[0] = 1.0f; tex[1] = 1.0f;        // oben  Rechts
       tri.setTextureCoordinates(0,3,tex);  
       tex[0] = 0.0f; tex[1] = 0.0f;        // unten Links
       tri.setTextureCoordinates(0,4,tex);
       tex[0] = 1.0f; tex[1] = 0.0f;        // unten Rechts
       tri.setTextureCoordinates(0,5,tex);
               
       return tri;
    }
    
    
    private Appearance makeAppearance(String fname, boolean transparency)
    { 
        Appearance app = new Appearance();
      
        TransparencyAttributes ta = new TransparencyAttributes();
        if(transparency==true)
        {
            ta.setTransparencyMode(TransparencyAttributes.BLEND_SRC_ALPHA);
            ta.setTransparency(1.0f); //Tranzparenzstarke wird gesetzt
        }
        else
        {
            ta.setTransparencyMode(TransparencyAttributes.BLENDED);
            ta.setTransparency(0.0f); //Tranzparenzstarke wird gesetzt
        }
        app.setTransparencyAttributes(ta);
            
        TextureLoader loader = new TextureLoader( fname, null );
        Texture2D texture = ( Texture2D ) loader.getTexture();   
        app.setTexture( texture );
        
        return app;
    }
```

Vielleicht kann mir jemand sagen wie ich die schwarzen Bereiche meines Raumschiffs Transparent machen kann


----------



## Illuvatar (13. Mai 2006)

Soll das ganze Ding zweidimensional werden oder verstehe ich das falsch? Dann bietet sich Java2D oder von mir aus noch JOGL aber viel eher an als Java3D.


----------



## DeziBell (13. Mai 2006)

Ich hab das nur als Beispiel-Code benutzt um das ganze so einfach wie möglich zu machen.


----------



## DeziBell (13. Mai 2006)

Ich habs geschafft. Wenn ich folgende Code einsetze/austausche funktioniert alles.
Schwarze Bereiche werden transparent.


```
if(transparency==true)
   {
        ta.setTransparencyMode(TransparencyAttributes.BLENDED);
        ta.setSrcBlendFunction(TransparencyAttributes.BLEND_ONE );
        ta.setDstBlendFunction(TransparencyAttributes.BLEND_SRC_ALPHA  );
        ta.setTransparency(1.0f); //Tranzparenzstärke wird gesetzt
   }
```

Da Ich bestimmt noch weitere Fragen Betreffs Textur und Transparenz habe, lasse ich den 
Thread erstmal offen.


----------



## DeziBell (13. Mai 2006)

Hier ersteinmal ein 3Dimensionales Anwendung-Beispiel für die Transparenz: 
Der Planet Erde wird von eine Wolkenschicht eingehüllt. Man sieht die Wolken, und die Erde schimmert durch.
Vorrausgesetzt man hat vernünftige Texturen (Erde oder andere Planeten-Oberfläche, und Wolken-Textur -> schwarz-weisse Wolken) sieht das ganze doch ganz gut aus 


```
public BranchGroup createSceneGraph()
    { 
        BranchGroup objWurzel = new BranchGroup();
        
        // PLANET
        objWurzel.addChild(
        new Sphere(0.46f,Sphere.GENERATE_TEXTURE_COORDS, makeAppearance("Earth.jpg", false)) );
        
        // WOLKEN
        objWurzel.addChild(
        new Sphere(0.5f,Sphere.GENERATE_TEXTURE_COORDS, makeAppearance("Wolken.jpg", true)) );
       
        return objWurzel; 
    } 

    private Appearance makeAppearance(java.lang.String str, boolean transparency)
    { 
        Appearance a = new Appearance();
        TextureLoader loader = new TextureLoader( str, null );
        Texture2D texture = ( Texture2D ) loader.getTexture();
        a.setTexture( texture );
        
        TransparencyAttributes ta = new TransparencyAttributes();
        ta.setTransparencyMode(TransparencyAttributes.BLENDED);
        ta.setSrcBlendFunction(TransparencyAttributes.BLEND_ONE );
        ta.setDstBlendFunction(TransparencyAttributes.BLEND_SRC_ALPHA  );
        if(transparency == true)
            ta.setTransparency(1.0f); //Tranzparenzstärke wird gesetztp
        else
            ta.setTransparency(0.0f); //Tranzparenzstärke wird gesetztp
        
        a.setTransparencyAttributes(ta);
        
        return a;
    }
```


----------



## DeziBell (13. Mai 2006)

Die mit Sphere aus der utility Klasse erzeugte Kugel sieht bei mir ziemlich eckig aus. Muss ich um eine perfektere Kugel zu bekommen eine eigene Geometrie erzeugen, oder kann man die standard Sphere irgendwie abrunden ???


----------



## Illuvatar (13. Mai 2006)

1. Könntest du vielleicht mal ein Bsp. für "vernünftige" Texturen hochladen? Würde mich mal interessieren wie das aussieht.

2. Du kannst das der Sphere im Konstruktor ausgeben. Ich kenn leider keine komplette API-Dokumentation mehr, die Sphere beinhaltet, aber ich hab irgendwann mal den Code hier geschrieben:

```
Sphere s = new Sphere(1, Sphere.ENABLE_GEOMETRY_PICKING | Sphere.GENERATE_NORMALS, 70, new Appearance());
```
Ich glaube die 70 steht dafür, dass das aus 70 Polygonen bestehen soll. Default ist was um die 20.


----------



## DeziBell (13. Mai 2006)

Danke Illuvater  Das hat tatsächlich geklappt !!! 

Mit den vernünftigen Texturen meinte ich nicht das ich "besonders tolle" hätte. Sie sollten halt nur ohne Nahtstelle drauf passen. Ich hab noch kein Webspace, aber wenn du mir sagst wo ich Gratis Space herkrieg, lad ich die hoch


----------



## Illuvatar (13. Mai 2006)

Naja ich hab eben beispielsweise nicht mal irgendein Bild von der Erde 
Arcor zum Bleistift. Oder schicks mir per Email, dann lad ichs auf den Moderatorenwebspace


----------



## DeziBell (13. Mai 2006)

Ich machs uns einfach und setz einen Link.
Planeten Maps gibts hier:
maps.jpl.nasa.gov/
Zumindest eine WolkenTextur gibts hier:
www.kuffner.org/james/gallery/raytracing/earth_from_space/index.html

Und hier noch der veränderte Code damit sich das ganze noch dreht 


```
public BranchGroup createSceneGraph()
{ 
        BranchGroup objWurzel = new BranchGroup();
        
        // Erde *****************************************
        TransformGroup tgObjekt = new TransformGroup(); 
        TransformGroup tgRotationObjekt = new TransformGroup(); 
        TransformGroup tgPositionObjekt = new TransformGroup(); 

        tgRotationObjekt.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        tgPositionObjekt.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
      
        Alpha alpha = new Alpha(-1, 10000);
        
        RotationInterpolator p =
        new RotationInterpolator(alpha, tgRotationObjekt); 
	
        tgRotationObjekt.addChild(p);
               
        tgObjekt.addChild(tgPositionObjekt);
        tgPositionObjekt.addChild(tgRotationObjekt);
        tgRotationObjekt.addChild(new Sphere(0.46f,Sphere.GENERATE_TEXTURE_COORDS, 40, makeAppearance("Earth.jpg", false)) );
        
        objWurzel.addChild(tgObjekt);
        
        // WOLKEN ***************************************
        TransformGroup tgObjekt2 = new TransformGroup(); 
        TransformGroup tgRotationObjekt2 = new TransformGroup(); 
        TransformGroup tgPositionObjekt2 = new TransformGroup(); 

        tgRotationObjekt2.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        tgPositionObjekt2.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
      
        Alpha alpha2 = new Alpha(-1, 20000);
        
        RotationInterpolator p2 =
        new RotationInterpolator(alpha2, tgRotationObjekt2); 
  
        tgRotationObjekt.addChild(p2);
               
        tgObjekt2.addChild(tgPositionObjekt2);
        tgPositionObjekt2.addChild(tgRotationObjekt2);
        tgRotationObjekt2.addChild(new Sphere(0.48f,Sphere.GENERATE_TEXTURE_COORDS, 40, makeAppearance("Clouds.jpg", false)) );

        objWurzel.addChild(tgObjekt2);
        // ****************************************************************
        
        BoundingSphere bounds =
	     new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
        
        p.setSchedulingBounds(bounds);
        p2.setSchedulingBounds(bounds);
        
        return objWurzel; 
    } 

    private Appearance makeAppearance(java.lang.String str, boolean transparency)
    { 
        Appearance a = new Appearance();
        TextureLoader loader = new TextureLoader( str, null );
        Texture2D texture = ( Texture2D ) loader.getTexture();
        a.setTexture( texture );
        
        TransparencyAttributes ta = new TransparencyAttributes();
        ta.setTransparencyMode(TransparencyAttributes.BLENDED);
        ta.setSrcBlendFunction(TransparencyAttributes.BLEND_ONE );
        ta.setDstBlendFunction(TransparencyAttributes.BLEND_SRC_ALPHA  );
        if(transparency == true)
            ta.setTransparency(0.6f); //Tranzparenzstärke wird gesetztp
        else
            ta.setTransparency(0.0f); //Tranzparenzstärke wird gesetztp
        
        a.setTransparencyAttributes(ta);
        
        return a;
    }
```

Sieht zwar schön aus, aber ruckelt manchmal unangenehm. Kann mir jemand sagen
wie ich das Ruckeln weiter minimieren kann ??


----------



## Illuvatar (13. Mai 2006)

Also bei mir ruckelt das gar nicht... aber sieht schön aus, ja


----------



## DeziBell (14. Mai 2006)

Naja, richtig ruckeln tuts bei mir auch nicht, aber irgendwie hab ich so ein Gefühl...

Damit Spiele in DirectX auf jedem Rechner gleich schnell und ruckelfrei laufen, wird einmal vor dem Rendern und einmal nach dem Rendern(incl. KI und ander Zeitaufwändiger Dinge) die Zeit gestoppt. Die Differenz ergibt eben die Zeit, die dieser Computer gebraucht hat, die Szene zu Rendern.  Nun bewegt man die Szene auf schnelleren Rechnern eben entsprechend häufiger, in kürzeren Abständen (flüssigere Animation), auf langsameren Rechnern eben in weniger Schritten. Als Faktor dafür dient die gemessene Zeit.

Ich kann das ganze auch gar nicht mehr richtig wiedergeben, frage mich nur ob man sowas in Java3D auch macht.
Das arbeiten mit Threads macht das vielleicht überflüssig.

Hab mir auch etwas Webspace zugelegt. Wer möchte kann sich das Beispiel mit dem Planeten und der Wolkentextur hier anschauen. (Hab noch keine Hompage gebastelt, kommt aber noch, hoffentlich 3D  Der Anbieter hat auch
seltsame Werbung drin, naja was solls, zum testen muss das mal reichen....).

stonebreaker.angelcities.com/Planet.html


----------



## Illuvatar (14. Mai 2006)

Also so ein RotationInterpolator wird, soweit ich weiß, pro Frame einmal durchgeführt und berechnet anhand des Alpha, und damit anhand des Unterschiedes Startzeit der Animation - Systemzeit, wie das jetzt gedreht sein muss. Also kommt das aufs gleiche raus...

Edit: Bei deinem Applet kommt bei mir


> java.lang.ClassFormatError: Incompatible magic value 1008807213 in class file javax/media/j3d/Texture


Ich hab Java3d aber nur 1.3.1 aufm PC, vielleicht liegts da dran.


----------



## DeziBell (14. Mai 2006)

Schade, ich kanns mir ganz normal anschauen. 
Ich hab allerdings die DirectX Version von Java3D SDK installiert.
Die meisten benutzen OpenGL. Vielleicht liegt auch da das Problem... ka.... Hab jedenfalls auch nur die 1.3.1 Version - 
java3d-1_3_1-windows-i586-directx-sdk.exe - drauf.

Wenns sich jemand anschauen kann, bitte bescheid sagen 
Will ja nicht alles nur für mich da hochladen ; )


----------



## DeziBell (14. Mai 2006)

Also ! Ich habs jetzt auch nochmal getestet, aber wenn ich die nötigen Texturen nicht auf meinem Desktop liegen habe, bekomme ich zwar keine Fehlermeldung,  aber Kugeln bleiben
untexturiert (weiss). Da ist noch der Wurm drin. Ich poste aber bald was funktionierendes


----------



## DeziBell (15. Mai 2006)

Sooo... jetzt klappts aber....hoffentlich 
Dieses mal mit Sternenfeld und Licht.
http://people.freenet.de/Stoned3D/Planet3D/Planet2.html


----------

