# Java3D: Alle Objekte in BranchGroup löschen während Laufzeit



## Scrimau (18. Apr 2010)

Ich bin noch ziemlicher Neuling in Java3D, aber nen bissl hab ich jetz schon kapiert, glaub auch das ich die grundsätzliche Logik verstanden hab mit der Java3D arbeitet (Scenegraph und alles). Aber bei meinem folgenden Programm das ich ma zum Einstieg geschrieben hab, um mich etwas ranzutasten, kommt mir so einiges Spanisch vor:
Ich bekomme folgende Fehlermeldung:

Group: only a BranchGroup node may be removed
        at javax.media.j3d.Group.removeAllChildren(Group.java:403)

das ist der "Übeltäter":

```
public void test() {
        BranchGroup temp=new BranchGroup(); //temporäre BranchGroup
        for (int i=0; i<scene.numChildren();i++)
        {
            
        }
        scene.removeChild(temp);
        TransformGroup test=new TransformGroup();
        Transform3D transf=new Transform3D();
        transf.setTranslation(new Vector3f(1,2,4));
        test.setTransform(transf);
        test.addChild(new ColorCube(3f));
        temp.addChild(test);
        scene.addChild(temp);
    }
```

So eine ähnliche fehlermeldung, hatte ich schon beim Einfügen von neuen Objekten während der Laufzeit, jedoch ließ sich diese durch eine zusätzliche temporäre BranchGroup umgehen, wie löse ich nun dieses Problem?

Hier nochmal der gesamte Code:


```
package helloworldin3d;

import java.util.Vector;
import java.util.ArrayList;
import javax.swing.*;
import java.awt.event.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.behaviors.vp.*;
import com.sun.j3d.utils.universe.*;  //SimpleUniverse
import com.sun.j3d.utils.geometry.ColorCube;  //Ein vorgefertigtes Test-SceneGraphObject, das hier benutzt werden wird.
import com.sun.j3d.utils.geometry.Cylinder; // Ein vorgefertigter Zylinder

/**
 *
 * @author User
 */
public class First3DProgra extends javax.swing.JFrame {

    public static final long serialVersionUID = 121121112l;  //Für Java1.5-Unterstützung
    //Konstruktor

    public First3DProgra() {
        setSize(500, 500);
        setLocationRelativeTo(null);  //zentrieren

        //Jetzt kommt der 3D-Teil
        Canvas3D c3d = new Canvas3D(SimpleUniverse.getPreferredConfiguration());  
        SimpleUniverse simpleU = new SimpleUniverse(c3d);  //Das VirtualUniverse, hier wird auch schon der View hinzugefügt
        trans = new TransformGroup();




        Transform3D t3d_trans = new Transform3D();
        t3d_trans.rotX(-45);
        t3d_trans.rotY(-45);
        t3d_trans.rotZ(-45);


        t3d_trans.setTranslation(new Vector3f(0, 0.3f, 0));  //javax.vecmath.Vector3f, Zahlen in "Meter" (Haupteinheit in Java3d)
        //Wie man sieht, geht die Y-Achse von unten nach oben
        trans.setTransform(t3d_trans);

        TransformGroup trans2 = new TransformGroup();
        Transform3D t3d_trans2 = new Transform3D();
        t3d_trans2.setTranslation(new Vector3f(0, -10f, 0));  //javax.vecmath.Vector3f, Zahlen in "Meter" (Haupteinheit in Java3d)
        //Wie man sieht, geht die Y-Achse von unten nach oben
        trans2.setTransform(t3d_trans2);

        ArrayList<TransformGroup> trans3 = new ArrayList<TransformGroup>();

        for (int i = 0; i < 5; i++) {
            TransformGroup ntg = new TransformGroup();
            Transform3D nt = new Transform3D();
            nt.setTranslation(new Vector3f(0, (2 * i) * 1f, 0));
            ntg.setTransform(nt);
            ntg.addChild(new Cylinder(0.1f, 0.4f, new Appearance()));
            trans3.add(ntg);
        }



        trans.addChild(new Cylinder(0.1f, 7f, new Appearance()/*Größe*/));  //ColorCube wird hinzugefügt
        trans2.addChild(new Cylinder(0.35f, 0.5f/*Größe*/));

        scene.addChild(trans);
        //scene.addChild(trans2);

        for (int i = 0; i < trans3.size(); i++) {
            scene.addChild(trans3.get(i));
        }

        OrbitBehavior orbit = new OrbitBehavior(c3d, OrbitBehavior.REVERSE_ALL);  //OrbitBehavior liegt in dem Paket com.sun.j3d.utils.behaviors.vp
        orbit.setSchedulingBounds(new BoundingSphere());
        simpleU.getViewingPlatform().setViewPlatformBehavior(orbit);
        scene.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE);
        scene.setCapability(BranchGroup.ALLOW_DETACH);
        scene.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
        //trans.setCapability(TransformGroup.ALLOW_CHILDREN_WRITE);
        //trans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        //trans.setCapability(TransformGroup.ALLOW_CHILDREN_EXTEND);
        scene.compile();  //Optimiert das Rendern
        simpleU.addBranchGraph(scene);  //Fügt den SceneGraph hinzu
        simpleU.getViewingPlatform().setNominalViewingTransform();  //Versetzt die Kamera so, dass man gleich etwas sehen kann
        add(c3d);  //Vor 1.5: getContentPane().add
        setVisible(true);
        //Wuerfel();
        test();
    }

    public void test() {
        BranchGroup temp=new BranchGroup(); //temporäre BranchGroup
        for (int i=0; i<scene.numChildren();i++)
        {
            
        }
        scene.removeChild(temp);
        TransformGroup test=new TransformGroup();
        Transform3D transf=new Transform3D();
        transf.setTranslation(new Vector3f(1,2,4));
        test.setTransform(transf);
        test.addChild(new ColorCube(3f));
        temp.addChild(test);
        scene.addChild(temp);
    }

    public void Wuerfel() {
        //objTrans.addChild(new ColorCube(0.1));
        BranchGroup bg = new BranchGroup();
        bg.setCapability(BranchGroup.ALLOW_DETACH);
        bg.addChild(new ColorCube(0.1f));
        trans.addChild(bg);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        setName("Form"); // NOI18N

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 451, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 394, Short.MAX_VALUE)
        );

        pack();
    }// </editor-fold>                        

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        //new First3DProgra();  //An "Insider": Ich werde nicht auf die Klasse MainFrame eingehen.
        }

    ;
    // Variables declaration - do not modify                     
    // End of variables declaration                   
    TransformGroup trans;
    BranchGroup scene = new BranchGroup();
}
```


----------



## Developer_X (18. Apr 2010)

Das ist das Problem an Java, man kann leider während der Laufzeit ein Objekt fasst nicht löschen.

Du kannst nömlich nur die ganzen Branchgroups löschen.

Das heißt:
Adde einen Sphere über eine Transformgroup, oder direkt an eine BranchGroup A.
Adde dann diese Branchgroup A  an eine Hauptbranchgroup B.

Dann kannst du jederzeit A von B removen, und somit den Sphere, Childs aber kann man gar nich entfernen.
Du musst dann aber noch B so setzen: B.setCapabilities(BranchGroup.ALLOW_CHILD_WRITE);
und dann dürfte es funktionieren.

Ich hatte mal nen Code der genau das erfüllt, den kann ich aber leider nicht mehr finden.
Aber so ging es glaub ich.

Hey ich hab den Code gefunden, 2 Jahre innerhalb von 5 minuten durchkämmt lol°!

```
package Main;

import java.awt.GraphicsConfiguration;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3f;
import com.sun.j3d.utils.geometry.Sphere;
import com.sun.j3d.utils.universe.SimpleUniverse;

@SuppressWarnings("serial")
public class KSKB extends JFrame {
	public static BranchGroup A;
	public static BranchGroup X;

	public KSKB() {
		this.setTitle("KSKB=.Kleines.Selbständiges.Kompilirbares.Beispiel.");
		this.setSize(400, 400);
		this.setVisible(true);
		this.setLayout(null);

		// Components
		// 3D World Configuration
		GraphicsConfiguration config = SimpleUniverse
				.getPreferredConfiguration();
		Canvas3D canvas = new Canvas3D(config);
		canvas.setBounds(0, 20, 400, 380);
		SimpleUniverse universe = new SimpleUniverse(canvas);
		universe.addBranchGraph(Universe());
		// Special Button
		JButton b = new JButton("Child_Button");
		b.setBounds(0, 0, 400, 20);
		b.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				b1ActionPerformed(evt);
			}

			private void b1ActionPerformed(ActionEvent evt) {
				

				X.removeChild(A);
			}
		});
		// adds
		this.add(b);
		this.add(canvas);
		// Last Things to do
		this.setVisible(true);
		this.setLayout(null);

	}

	public static BranchGroup Universe() {
		X = new BranchGroup();
		// Universe
		X.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE
				| BranchGroup.ALLOW_CHILDREN_READ
				| BranchGroup.ALLOW_CHILDREN_WRITE );
		A = new BranchGroup();
		X.addChild(A);
		A.setCapability(BranchGroup.ALLOW_DETACH);
		// Here
		Transform3D a = new Transform3D();
		a.setTranslation(new Vector3f(0, 0, -5));
		TransformGroup Parent = new TransformGroup();
		Parent.setTransform(a);

		Sphere s = new Sphere(1, null);
		Parent.addChild(s);
		A.addChild(Parent);

		// Directional Light
		 Color3f light1Color = new Color3f(1.9f, 0.13f, 160000.6f);

		   BoundingSphere bounds = 

		   new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);

		   Vector3f light1Direction = new Vector3f(1.0f, -7.0f, -12.0f);

		   DirectionalLight light2

		      = new DirectionalLight(light1Color, light1Direction);

		   light2.setInfluencingBounds(bounds);

		   X.addChild(light2);
		   
		X.compile();
		return X;
	}

	public static void main(String[] args) {
		new KSKB();
	}
}
```


----------



## Scrimau (21. Apr 2010)

Developer_X hat gesagt.:


> Das ist das Problem an Java, man kann leider während der Laufzeit ein Objekt fasst nicht löschen.
> 
> Du kannst nömlich nur die ganzen Branchgroups löschen.
> 
> ...



Das löst das Problem :toll:, bissl merkwürdig is es aber schon. Irgendwie löst das die ganze schöne Hierarchie auf, die der Szenegraph bietet, schade.


----------



## mattn (1. Jul 2010)

erledigt


----------

