# Java3D Textur Problem



## Developer_X (10. Jan 2009)

Hi, was mache ich im folgenden Quellcode falsch?


```
package Bäume;

import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.GraphicsConfiguration;
import Figuren.Rayman_Body;
import Figuren.Rayman_Feet;
import Figuren.Rayman_Hand_Left;
import Figuren.Rayman_Hand_Right;
import Figuren.Rayman_Head;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.behaviors.vp.*;       
import com.sun.j3d.utils.image.TextureLoader;
	
	public class C_2 extends Applet {       
    
	//Private definierungen
	
        private Appearance blue = new Appearance();
        private Appearance blue2 = new Appearance();

    private SimpleUniverse universe ;
    private Canvas3D canvas;
    private BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 10.0), 1000.0);
    Transform3D translate = new Transform3D();
    
      public void setupView() 
      { 
    	OrbitBehavior orbit = new OrbitBehavior(canvas,
                OrbitBehavior.REVERSE_ALL|OrbitBehavior.STOP_ZOOM);
        orbit.setSchedulingBounds(bounds);
        ViewingPlatform viewingPlatform = universe.getViewingPlatform();
        
        viewingPlatform.setNominalViewingTransform();
        viewingPlatform.setViewPlatformBehavior(orbit);       
        }       
         
        

          
          public BranchGroup createSceneGraph() {
          // Wurzel des Ast-Graphen erstellen
         BranchGroup objRoot = new BranchGroup();       
         // 45°-Rotation um die x-Achse
         translate.rotY(Math.toRadians(45));      
         
         Appearance white = new Appearance();

         Transform3D g1 = new Transform3D();
         g1.setTranslation(new Vector3f(0,1,0));
         TransformGroup G1 = new TransformGroup();
         G1.setTransform(g1);
         G1.addChild(new Rayman_Head().getChild());
         Transform3D g2 = new Transform3D();
         g2.setTranslation(new Vector3f(0,0,0));
         TransformGroup G2 = new TransformGroup();
         G2.setTransform(g2);
         G2.addChild(new Rayman_Body().getChild());
         Transform3D g3 = new Transform3D();
         g3.setTranslation(new Vector3f(-0.5f,0,0));
         TransformGroup G3 = new TransformGroup();
         G3.setTransform(g3);
         G3.addChild(new Rayman_Hand_Left().getChild());
         Transform3D g4 = new Transform3D();
         g4.setTranslation(new Vector3f(0.5f,0,0));
         TransformGroup G4 = new TransformGroup();
         G4.setTransform(g4);
         G4.addChild(new Rayman_Hand_Right().getChild());
         Transform3D g5 = new Transform3D();
         g5.setTranslation(new Vector3f(0.5f,-1f, 1.5f));
         TransformGroup G5 = new TransformGroup();
         G5.setTransform(g5);
         G5.addChild(new Rayman_Feet(blue).getChild1());
         G5.addChild(new Rayman_Feet(blue).getChild2());
         G5.addChild(new Rayman_Feet(blue).getChild3());
         G5.addChild(new Rayman_Feet(blue).getChild4());
         Transform3D g6 = new Transform3D();
         g6.setTranslation(new Vector3f(-0.5f,-1f, 1.5f));
         TransformGroup G6 = new TransformGroup();   
         G6.setTransform(g6);
         G6.addChild(new Rayman_Feet(blue2).getChild1());
         G6.addChild(new Rayman_Feet(blue2).getChild2());
         G6.addChild(new Rayman_Feet(blue2).getChild3());
         G6.addChild(new Rayman_Feet(blue2).getChild4());

         objRoot.addChild(G1);
         objRoot.addChild(G2);
         objRoot.addChild(G3);
         objRoot.addChild(G4);
         objRoot.addChild(G5);
         objRoot.addChild(G6);

       


        
         white.setTexture((new TextureLoader("F:/FUTURE.SYSTEMS/Rayman_Bilder/Rayman_Feet_!!!.jpg",null)).getTexture());
         white.setTextureAttributes(new TextureAttributes(TextureAttributes.MODULATE,new Transform3D(),new Color4f(),TextureAttributes.FASTEST));
        
         blue2.setTexture((new TextureLoader("F:/FUTURE.SYSTEMS/Rayman_Bilder/Rayman_Feet_!.jpg",null)).getTexture());
         blue2.setTextureAttributes(new TextureAttributes(TextureAttributes.MODULATE,new Transform3D(),new Color4f(),TextureAttributes.FASTEST));

         blue.setTexture((new TextureLoader("F:/FUTURE.SYSTEMS/Rayman_Bilder/Rayman_Feet_!!.jpg",null)).getTexture());
         blue.setTextureAttributes(new TextureAttributes(TextureAttributes.MODULATE,new Transform3D(),new Color4f(),TextureAttributes.FASTEST));

        Color3f lightColor = new Color3f(.3f,.3f,.3f);
        AmbientLight ambientLight= new AmbientLight(lightColor);
        ambientLight.setInfluencingBounds(bounds);
        objRoot.addChild(ambientLight);
        DirectionalLight directionalLight = new DirectionalLight();
        directionalLight.setColor(lightColor);
        directionalLight.setInfluencingBounds(bounds);
        objRoot.addChild(directionalLight);       
        return objRoot;       
    }       
     
    public void init() {
         BranchGroup scene = createSceneGraph();       
         setLayout(new BorderLayout());
         
         GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
         canvas = new Canvas3D(config);
         add("Center", canvas);       
        
         universe = new SimpleUniverse(canvas);       
         setupView();       
         universe.addBranchGraph(scene);
    }       
    public void destroy() {universe.removeAllLocales();}       
   
    public static void main(String[] args) {new MainFrame(new C_2(), 256, 256);}
}
```
Die Fehlermeldung ist folgende;

```
java.lang.OutOfMemoryError: Java heap space
	at java.awt.image.DataBufferByte.<init>(Unknown Source)
	at java.awt.image.Raster.createInterleavedRaster(Unknown Source)
	at java.awt.image.BufferedImage.<init>(Unknown Source)
	at com.sun.j3d.utils.image.TextureLoader.getScaledImage(TextureLoader.java:806)
	at com.sun.j3d.utils.image.TextureLoader.getScaledImage(TextureLoader.java:783)
	at com.sun.j3d.utils.image.TextureLoader.getTexture(TextureLoader.java:526)
	at Bäume.C_2.createSceneGraph(C_2.java:106)
	at Bäume.C_2.init(C_2.java:121)
	at sun.applet.AppletPanel.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)
```
[/b]
Kann mir bitte jemand helfen???


----------



## SegFault (10. Jan 2009)

Was ist an der Meldung 


> java.lang.OutOfMemoryError: Java heap space



so missverständlich. Texturen sind typische Speicherfresser. Meist sogar als bmp im Speicher. Dazu kommt noch Power of 2 (Die größe einer Textur wird auf irgendeine 2er potenz gelegt. Also ist deine Textur 513 x 513 Pixel groß wird sie auf 1024x1024 aufgebläht) ob das in java 3d auch so ist weiss ich nicht. Auf jedenfall ist der Speicher deiner jvm voll lass das ganze mal mit -Xms=256m -Xmx=512m laufen, damit gibst du der jvm mehr speicher. Bei Netbeans ist die z.B. bei mir nur auf 128 mb voreingestellt das gab schon mehrfach probleme.


----------



## Developer_X (10. Jan 2009)

Heißt das es ist begrenzt???
Also alle Bilder zusammen sind 50 kb groß, die Figuren Rayman_Hand,_Body usw... verbrauchen auch Texturen, dass macht insgesamt an Texturen 272kb ist das wirklich zu groß?
Das sind alle JPG Dateien falls das wichtig ist, denkst du ich sollte sie in Gifs umwandelN?


----------



## Fu3L (10. Jan 2009)

Developer_X hat gesagt.:
			
		

> Heißt das es ist begrenzt???
> Also alle Bilder zusammen sind 50 kb groß, die Figuren Rayman_Hand,_Body usw... verbrauchen auch Texturen, dass macht insgesamt an Texturen 272kb ist das wirklich zu groß?
> Das sind alle JPG Dateien falls das wichtig ist, denkst du ich sollte sie in Gifs umwandelN?



Ohne besondere Angaben verfügt die VM (meistens) über max. 128 MB Speicher... Und irgendwas in deinem Rayman ( :roll: ) scheint diese 128 MB zu beanspruchen....



> The default value is chosen at runtime based on system configuration. For more information, see HotSpot Ergonomics


----------



## Developer_X (10. Jan 2009)

Die Rayman Figuren sind alle insgesamt 64 kb groß


----------



## Marco13 (11. Jan 2009)

Ein SImpleUniverse ist auch nicht umsonst. Aber nebenbei: Wenn du eine 270kb große JPG-Datei hast, dann sagt das ... fast garnichts aus. Entschiedend ist die Größe des Bildes. Wenn die Textur 1000*1000 Pixel groß ist, dann braucht die schonmal _mindestens_ 4 MB Speicher... Schau einfach mal ob das mit
java -Xmx500m MeinProgramm
funzt


----------



## Developer_X (11. Jan 2009)

Also die Bilder sind 20*20 groß


----------



## Developer_X (11. Jan 2009)

Vielleicht könnte man eclipse entdrosseln, weil ich ein Viedeo Spiel programmiere, und dazu nun mal enorm viel Arbeitsspeicher benötigt, also könnte mir einer sagen wie man in Eclipse den Arbeittspeicher erhöhen könnte?

Ach und auch wenn das nicht geht, kann ich die Probeläufe nun mal nicht mit Texturen machen kann, aber wenn ich das Spiel nun außerhalb von Eclipse, so wie ne Exe datei starte, gibt es da dann auch einen Arbeitsspeicher, und ist dieser dann vom Computer Arbeittspeicher ?


----------



## Fu3L (11. Jan 2009)

Der Arbeitsspeicher hat mit Eclipse und .exe gar nix zu tun...

Die Menge des Arbeitsspeicher, die das Programm zur Verfügung hat richtet sich entweder nach dem Standartwert (meist 128 MB) oder dem was du beim Aufruf festlegst und das geht, wie Marco13 und SegFault schon geschrieben haben halt mit "java *-Xmx500m* MeinProgramm" beim Aufruf. Diese Parameter kann man in Eclipse einstellen, dass die beim Start immer mit übergeben werden. Wenn mich nicht alles täuscht: Rechtsklick auf deine Datei mit der main-methode, dann auf "Run as" ---> "Run..." --> Da gibts auf der rechten Seite den Karteireiter "arguments" und da gibts dann einen Teil der zur VM gehört (habs noch nie benutzt, also ka, ob das die richtige Stelle dafür ist    )


----------



## SegFault (12. Jan 2009)

Developer_X hat gesagt.:
			
		

> Also die Bilder sind 20*20 groß



also wie schon angesprochen sagt das ggf noch nichts aus. 

Sofern Java wirklich mit power of 2 arbeitet wäre das also intern eine 32x32 pixel textur. 
Zugegeben ich glaube kaum das java mit sowas arbeitet ich weiss zumindest das in Grafikkarten Texturen so benutzt werden da ein Zugriff auf solche Größen als gesamter Block weitaus schneller geht. 
Zumindest vermute ich mal das eine Textur aber als Bitmap im Arbeitsspeicher vorliegt. 
d.h. 32x32 = 1024 pixel x 32 bit pro pixel = 32768 Bit (Ich gehe mal davon aus das java Texturen einen Alpha Wert haben können und er diesen einfach mit in den ram legt) 32768 Bit = 4 kb. Ich glaube aber das er für Verwaltung intern noch weitaus mehr verbraucht. 

du kannst ja mal alle textursachen weglassen und den speicherverbrauch ausgeben und das ganze mal mit Texturen anzeigen lassen.

Speicherauslastung kannst du hiermit ausgeben:

Runtime.getRuntime().totalMemory();

P.S:

Zum speicherhandling vom Java. Die Java Runtime hat eben einen gewissen Speicher der ihr zugesichert ist. Die ist im normalfall 128 mb. Dies ist unabhängig vom reinen Arbeitsspeicher, wenn der erschöpft ist wird auf virtuellen Speicher zugegriffen und notfalls brachliegende Programmteile auf der HD ausgelager was aber extrem langsam ist. Diese 128 mb hat die Java Maschine belegt sie aber erst wenn der Speicher wirklich von irgendwas angefordert wird.
Wird mehr speicher als die 128 mb angefordert kommt die von dir gezeigte meldung. 
Falls die Java Maschine noch genügend speicher übrig hat macht sie auch nicht so oft eine Garbage Collection weil die noch unnötig ist. Je voller das ganze wird umso eher räumt die Maschine mal auf. Jedoch wird so wieder geleerter Speicher nicht sofort zurückgegeben sondern weiterhin für die Java Maschine beansprucht.
Kurzum die JVM holt sich ggf immer mehr speicher bis zu der Grenze gibt den einmal reservierten Speicher aber nicht an andere applikationen zurück sondern behält den weiterhin für die JVM


----------

