3D-Grafik Grafikprogramm mit Java3D

stevey

Aktives Mitglied
Hi Leute,
ich bin gerade dabei mich in Java3D einzuarbeiten. ich will ein sehr einfaches Grafikprogramm schreiben, bei dem man mit der Maus Objekte (Quadrate, Kugeln usw.) in die Welt setzen kann. Doch genau hier liegt schon mein Problem und zwar die Umrechnung von 2D Koordinaten in 3D Koordinaten. Außerdem bin ich mir nicht sicher ob das richtig ist, für jedes neue Objekt eine neue BranchGroup zu erstellen, denn in mehreren utorials kam es so rüber, als sollte es immer nur eine BranchGroup geben, die für alle anderen die Wurzel darstellt.

Hier ist mal der Code von dem, was ich schon hab:

Java:
package graphics3D;

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.universe.SimpleUniverse;
import javax.media.j3d.*;

import javax.vecmath.*;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GraphicsConfiguration;
import java.awt.Label;

import javax.swing.JFrame;
import javax.swing.JPanel;
@SuppressWarnings("restriction")

public class MyPanel extends JPanel implements MouseListener{
	final int WIDTH = 600, HEIGHT = 800;
	SimpleUniverse universe;
	BranchGroup bGroup;
	Canvas3D canvas;
	GraphicsConfiguration config;
	
	public MyPanel() {
		JFrame frame = new JFrame();
		frame.setPreferredSize(new Dimension(WIDTH, HEIGHT));
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setResizable(false);
		frame.setVisible(true);
		frame.pack();
		frame.add(this);
		addMouseListener(this);
		setLayout(new BorderLayout());
		
		bGroup = new BranchGroup();
		config = SimpleUniverse.getPreferredConfiguration();
		canvas = new Canvas3D(config);
		canvas.addMouseListener(this);
		add(canvas, BorderLayout.CENTER);
		
		Color3f light1Color = new Color3f(1, 1, 10);
		BoundingSphere bounds = new BoundingSphere(new Point3d(0,0,0), 100);
		Vector3f light1Direction = new Vector3f(10.0f, 10.0f, -15.0f);
		DirectionalLight light1 = new DirectionalLight(light1Color, light1Direction);
		light1.setInfluencingBounds(bounds);
		bGroup.addChild(light1);
		Color3f ambientColor = new Color3f(1.0f, 1.0f, 1.0f);
		AmbientLight ambientLightNode = new AmbientLight(ambientColor);
		ambientLightNode.setInfluencingBounds(bounds);
		bGroup.addChild(ambientLightNode);
		
		universe = new SimpleUniverse(canvas);
		universe.getViewingPlatform().setNominalViewingTransform();
	    universe.addBranchGraph(bGroup);
	}
	public static void main(String args[]) {
		new MyPanel();
	}
	
	@Override
	public void mouseClicked(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void mousePressed(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void mouseReleased(MouseEvent e) {
		TransformGroup transGroup = new TransformGroup();
		Transform3D trans = new Transform3D();
		Sphere sphere = new Sphere(0.05f);
		
		if(e.getX() < WIDTH/2 && e.getY() < HEIGHT/2) {
			trans.setTranslation(new Vector3f(-((1f/WIDTH)*(WIDTH-e.getX())), ((1f/HEIGHT)*(HEIGHT-e.getY())), 0.0f));
		}
		if(e.getX() > WIDTH/2 && e.getY() < HEIGHT/2) {
			trans.setTranslation(new Vector3f(((1f/WIDTH)*(e.getX()-WIDTH/2)), ((1f/HEIGHT)*(HEIGHT-e.getY())), 0.0f));
		}
		if(e.getX() > WIDTH/2 && e.getY() > HEIGHT/2) {
			trans.setTranslation(new Vector3f(((1f/WIDTH)*(e.getX()-WIDTH/2)), -((1f/HEIGHT)*(e.getY()-HEIGHT/2)), 0.0f));
		}
		if(e.getX() < WIDTH/2 && e.getY() > HEIGHT/2) {
			trans.setTranslation(new Vector3f(-((1f/WIDTH)*(WIDTH-e.getX())), -((1f/HEIGHT)*(e.getY()-HEIGHT/2)), 0.0f));
		}
		transGroup.setTransform(trans);
		transGroup.addChild(sphere);
		BranchGroup g = new BranchGroup();
		g.addChild(transGroup);
		universe.addBranchGraph(g);
		revalidate();	
	}
}

danke, euer stevey :)
 

stevey

Aktives Mitglied
jap, das wusste ich schon, aber ich kenne eig. nur Java3D. Was gäbe es denn für Alternativen und ist Java3D wirklich schon so veraltet im Vergleich zu diesen?
 

Marco13

Top Contributor
Naja, es ist nicht ganz tot... der letzte Commit ist 8 Monate her, und es bietet schon ziemlich viel. Aber erfordert auch eine Menge Einarbeitungszeit, und ist an manchen Stellen vielleicht... sehr gewöhnungsbedürftig. Mit sowas wie jMonkeyEngine 3.0 | Java OpenGL Game Engine hat man sicher schneller Erfolgserlebnisse, und es dürfte für die meisten ... "zugänglicher" sein (mehr Dokus, Beispiele, aktivere Community...). Zur eigentlichen Frage... da müßte ich mir den Code mal genauer ansehen. Evtl. wäre das, was du vorhast, mit Behaviors einfacher, aber man müßte vielleicht auch das "größere" Ziel kennen, um besser Planen zu können.
Zumindest so viel: BranchGroups sind kein Problem. Es geht ja gerade um einen Szenegraph, wäre schlimm wenn man sich da bei jeder BG überlegen müßte, ob man sie wirklich verwenden sollte ;)
 

stevey

Aktives Mitglied
da hast recht, is für mich alles ziemlich gewöhnungsbedürftig, kann aber auch daran liegen, dass es das erste mal ist, dass ich mich beim Programmieren mit 3D auseinandersetze. also was ich so von jMonkey gehört habe ist das ja schon eine fertige "game engine" und soetwas will ich nur ungerne verwenden, weil ich immer alles, so gut es geht selbst schreiben will. ich fühle mich dadurch einfach nicht so abhängig.
Behaviors, hmm noch nie gehört :D
joa, das größere Ziel gibt es so gar nicht, das ganze soll nur eine kleine übung sein, aber was auf jeden fall noch im programm sein soll, ist, dass man die Szene mit der maus drehen kann, um so auch wirklich alle 3 Achsen komplett ausnutzen zu können.
 

twseitex

Mitglied
Hi,

wie wärs mit Introduction to Java 3D

und eventuell mal .... Flash oder Microsoft Net Framework :)

Moral der Geschichte: Markt oder Hobby. Wer Geld machen will, nutzt Java Enterprise,
oder Flash oder Net Framework.

Ich habe mir, um Java im 2D-Bereich mit Audio mal kennenzulernen, einen Java-SE-Player geschrieben
(ansehbar per audio, flash and java). Als Pendant auch einen Flashplayer geschrieben, um etwas
vergleichen zu können. .... Der Flashplayer hat nur einen Bruchteil der Programmierungszeit
von Java gekostet, obwohl Flash ebenfalls das Konzept vordefinierter Pakete hat. Den Wechsel
von Java 6 auf 7 hat mein Javaplayer überstanden (laut Eclipse) ... DREI KREUZE !!!

Ergebnis: Java 3D würde ich niemals angehen, wenn das Paket nicht permanent gepflegt wird.

Das Risiko der Inkompatibilitäten ist irgendwann nicht mehr ertragbar, besonders
wenn man gegen Entgelt Support liefern will bzw. muss.

Prägnantes Beispiel: SAP nutzt auch Java .... man braucht nicht zu raten, ob das ein
altes oder neues Java ist ...
 
K

killersponge

Gast
hey, also wenn du 3d Koordinaten auf die bildfläche projezierst benutzt man normalerweise diese Formel:

sy=wy/wz* U
sx=wx/wz* U

wobei sy, sx die bildschirm koordinaten sind
wx,wy,wz die 3d koordinaten der welt sind
und U die Strecke des bBetrachters zum Bildschirm ist
alle Werte in Pixel

was U ist kann ich dir allerdings nicht sagen weil das irgendwo in java3d festgelegt wird weis auch nicht wie du dran kommst, aber theoretisch kann man da ein paar Werte ausprobieren zb 100 , oder sogar 1000
das variert zwischen den Auflösungen

außerdem gilt das nur wenn die Kamera im Ursprung liegt und geradeaus gerichtet ist.

ich hoffe das dir das iwie weiterhilft...
 

Marco13

Top Contributor
Ja, solche Hardverdrahteten Sachen helfen einem ja nicht, wenn man die Kamera umherbewegt und so.

Ich hatte das vor etlichen Jahren mal implementiert, grob(!) aus dem Hinterkopf war das AFAIR so:

Mit getPixelLocationInImagePlate den Pixel (d.h. das, was man mit getX()/getY() vom MouseEvent bekommt) umrechnen in einen 3D-Punkt auf der Bildebene.
Mit getImagePlateToVworld die Matrix holen, mit der man einen Punkt aus der Bildebene in die Weltkoordinaten Umrechnen kann.
Den zuerst berechneten Punkt mit der danach bestimmten Transform3D transformieren.

Das sollte für jeden Punkt auf dem Bildschirm einen passenden 3D-Punkt liefern. Die Entfernung vom Auge des Betrachters ist dabei natürlich noch offen, aber den Strahl vom Auge durch den Punkt auf der Bildebene kann man sich wohl aus der Differenz zwischen dem Punkt getCenterEyeInImagePlate und dem zuerst berechneten Punkt bestimmen (um den Strahl in Weltkoordinaten zu erhalten müssen die natürlich beide noch mit der getImagePlateToVworld-Transform transformiert werden!). Entlang dieses Strahls kann man den Punkt dann verschieben.
 

stevey

Aktives Mitglied
uiuiu, das klingt schon alles recht aufwändig und kompliziert, hab mir das iwie leichter vorgestellt. ich werd mal schaun wie und ob ich das noch mache.

auf jeden Fall Danke an alle, euer stevey
 

Marco13

Top Contributor
Neenaja, eigentlich ist das schon recht bequem und gar nicht so kompliziert wie es im ersten Moment klingt. Das Viewing in Java3D ist zwar auch ein bißchen Gewöhnungsbedürftig, aber wenn man sich klar macht, welche Arbeit es einem abnimmt und welche Möglichkeiten bietet, merkt man, dass es vergleichsweise einfach ist. Was auch immer du machst, und wie auch immer die Alternative aussieht: Man wird irgendwie von den Screen-Koordinaten in die Weltkoordinaten umrechnen. In Java3D geht das mit den zwei besagten Funktionen. Wenn man das "von Hand" machen wollte, müßte man erstmal für eine Kamera eine View- und Projection-Matrix berechnen, die multiplizieren, invertieren, dann den Viewport (wie in deiner mouseReleased im Moment) in irgendwelche normierten Koordinaten umrechnen und mit der invertierten Matrix in die Weltkoordinaten transformieren... Hui, so drei Zeilen mit magischen Methoden aus dem Canvas3D sind da doch bequemer ;)
 

stevey

Aktives Mitglied
hehe, stimmt auch wieder :D

Edit: irgendwie verstehe ich das Verfahren von oben noch nicht so genau. Könntest du mir da vielleicht mal ein konkretes Codebeispiel geben, weil wie kann ich einen Point3d transformieren und was bringt mir der dann, um z.b eine Sphere an dieser position zu erzeugen.
 
Zuletzt bearbeitet:

Marco13

Top Contributor
Man kann den Punkt dann in einen Vector3f verwandeln, der die Translation einer TransformGroup ist, an der die Sphere hängt
Java:
// Based on [url=http://www.java2s.com/Code/Java/3D/HelloJava3Dbrendersasinglerotatedcube.htm]HelloJava3Db renders a single, rotated cube : 3D Basics3DJava[/url]

import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.GraphicsConfiguration;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3f;

import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.behaviors.keyboard.KeyNavigatorBehavior;
import com.sun.j3d.utils.behaviors.mouse.MouseRotate;
import com.sun.j3d.utils.geometry.ColorCube;
import com.sun.j3d.utils.universe.SimpleUniverse;

public class ClickingHelloJava3Db extends Applet {
	public BranchGroup createSceneGraph() {
		// Create the root of the branch graph
		BranchGroup objRoot = new BranchGroup();
		objRoot.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);

		Transform3D rotate = new Transform3D();
		Transform3D tempRotate = new Transform3D();

		rotate.rotX(Math.PI / 4.0d);
		tempRotate.rotY(Math.PI / 5.0d);
		rotate.mul(tempRotate);

		TransformGroup objRotate = new TransformGroup(rotate);

		objRoot.addChild(objRotate);
		objRotate.addChild(new ColorCube(0.4));

		return objRoot;
	}

	public ClickingHelloJava3Db() {
		setLayout(new BorderLayout());
		GraphicsConfiguration config = SimpleUniverse
				.getPreferredConfiguration();
		Canvas3D canvas3D = new Canvas3D(config);
		add("Center", canvas3D);

		BranchGroup scene = createSceneGraph();
		SimpleUniverse simpleU = new SimpleUniverse(canvas3D);
		simpleU.getViewingPlatform().setNominalViewingTransform();

		TransformGroup viewTransformGroup =
			simpleU.getViewingPlatform().getViewPlatformTransform();

		KeyNavigatorBehavior keyInteractor =
			new KeyNavigatorBehavior(viewTransformGroup);

		BoundingSphere movingBounds = new BoundingSphere(
				new Point3d(0.0, 0.0, 0.0), 100.0);
		keyInteractor.setSchedulingBounds(movingBounds);
		scene.addChild(keyInteractor);

		MouseRotate behavior = new MouseRotate();
		behavior.setTransformGroup(viewTransformGroup);
		scene.addChild(behavior);
		behavior.setSchedulingBounds(movingBounds);
		
		simpleU.addBranchGraph(scene);
		
		initPickingTest(scene, canvas3D);
	}
	
	private void initPickingTest(final BranchGroup scene, final Canvas3D canvas)
	{
		canvas.addMouseListener(new MouseAdapter() {
			
			@Override
			public void mouseReleased(MouseEvent e) {
				System.out.println("Screen "+e.getPoint());

				Point3d point = new Point3d();
				canvas.getPixelLocationInImagePlate(e.getX(), e.getY(),point);
				
				System.out.println("Image plate "+point);
				
				Transform3D transform = new Transform3D();
				canvas.getImagePlateToVworld(transform);
				transform.transform(point);
				
				System.out.println("World "+point);
				
				TransformGroup tg = new TransformGroup();
				Transform3D t = new Transform3D();
				Vector3f translation = new Vector3f(
					(float)point.x, (float)point.y, (float)point.z);
				t.setTranslation(translation);
				tg.setTransform(t);
				tg.addChild(new ColorCube(0.1));
				BranchGroup bg = new BranchGroup();
				bg.addChild(tg);
				scene.addChild(bg);
			}
		});
	}
	
	
	
	public static void main(String[] args) {
		Frame frame = new MainFrame(new ClickingHelloJava3Db(), 512, 512);
	}

}
 

stevey

Aktives Mitglied
boa, genau so wollt ichs, danke :)
aber eins verstehe ich immer noch nicht und zwar folgendes:
Java:
Transform3D transform = new Transform3D();
        canvas.getImagePlateToVworld(transform);
        transform.transform(point);
wozu brauch ich das? wenn ichs auskommentiere, dann sehe ich den unterschied natürlich, aber ich sehe nicht, was der codeteil genau ändert.
 

Marco13

Top Contributor
Die Koordinaten, die der Punkt vorher hat, sind im Lokalen Koordinatensystem der ImagePlate angegeben. Der Versuch zwischen Präzision und Verständlichkeit abzuwägen: Das kann man sich (nur kurz gesucht) ungefähr so vorstellen:
ImagePlaneConcept.png

Der Ursprung des Image-Plate-Koordinatensystems wäre da z.B. in der unteren, linken Ecke der dort gezeigten Ebene. Die Ebene selbst wäre dann die X-Y-Ebene, und die Z-Achse in diesem Koordinatensystem würde senkrecht auf der Ebene stehen - in Richtung der Kamera zeigend. Die Koordinaten der Kamera in diesem Bild, angegeben in Image-Plate-Koordinaten, wären dann z.B. (0.5, 0.6, 0.7),
- x=0.5: Horizontal in der Mitte der Ebene
- y=0.6: Vertikal ein Stück höher als die Mitte (sieht zumindest so aus)
- z=0.7: ca. 0.7 Meter von der Ebene entfernt.

Gleichzeitig kann die gesamte Konstruktion (also alles, was auf dem Bild zu sehen ist) in Weltkoordinaten aber "irgendwo" liegen oder auch gedreht sein. Die besagte 'transform' rechnet dann den Punkt in die Weltkoordinaten um.

Ich hoffe das war nicht zuuu ungenau oder falsch, ist schon eine Weile her, seit ich mir das The Java 3D View Model näher angesehen hatte.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
D Suche Framework um Grafikprogramm zu schreiben. AWT, Swing, JavaFX & SWT 36
H Java3D, ViewP Translattform soll sich nach einerformgroup richten. AWT, Swing, JavaFX & SWT 5
S Java3D: Ikosaeder mit unterschiedlich gefärbten Flächen AWT, Swing, JavaFX & SWT 3
K Fullscreen Java3D AWT, Swing, JavaFX & SWT 5
T 3D-Grafik (Java3D) Aus einem Objekt einer Szene (Würfel, Ebene) die wichtigen Randkoordinaten auslesen AWT, Swing, JavaFX & SWT 3
T Erstellung einer ShadowMap mit Java3D AWT, Swing, JavaFX & SWT 6
S Hilfe beim Lernprozess von java3d AWT, Swing, JavaFX & SWT 20
K 3D-Grafik Textur Java3d AWT, Swing, JavaFX & SWT 5
B 3D-Grafik Punkt in JAVA3D darstellen AWT, Swing, JavaFX & SWT 2
B Java3D Szenegraph Export als VRML, .X3D, .OBJ, .POV, U3D oder PLY AWT, Swing, JavaFX & SWT 4
E Java3D im FSEM AWT, Swing, JavaFX & SWT 5
K Java3D - Startposition ? AWT, Swing, JavaFX & SWT 5
M 3D-Grafik Java3D-Application als executable .jar exportieren (Eclipse) AWT, Swing, JavaFX & SWT 5
I 3D-Grafik Java3D RAM AWT, Swing, JavaFX & SWT 3
S 3D-Grafik Java3D und was noch? AWT, Swing, JavaFX & SWT 3
E 3D-Grafik Java3D AWT, Swing, JavaFX & SWT 5
T Java3D - Picking AWT, Swing, JavaFX & SWT 12
L 3D-Grafik Java3D - Alle SceneGraphObjects geordnet erhalten AWT, Swing, JavaFX & SWT 2
S Java3D in ein JPanel integrieren mit Netbeans 6.8 AWT, Swing, JavaFX & SWT 4
S Java3D: Alle Objekte in BranchGroup löschen während Laufzeit AWT, Swing, JavaFX & SWT 3
C java3D - sichtbare Kanten eines Shape3D AWT, Swing, JavaFX & SWT 2

Ähnliche Java Themen


Oben