# API für 3d-Programmierung? OpenGL?



## Guest (18. Dez 2008)

Hallo,

ich muss für eine Software verschiedene geometrische Körper
im 3D darstellen. 

Kann mir da wer eine API empfehlen? 

Ich dachte schon an JOGL...


Gruß


----------



## Landei (18. Dez 2008)

OpenGL ist sehr "low-level", und JOGL (und auch lwjgl) ist bloß eine javataugliche Schnittstelle zu den OpenGL-Funktionen. Wenn du mit geometrischen Körpern hantieren willst, bietet sich Java3D an. Man kann aber auch 3D-Engines für soetwas "missbrauchen". Habe gute Erfahrungen mit JMonkeyEngine (und ihrer Community) gemacht, aber es gibt auch andere...


----------



## Fancy (18. Dez 2008)

Moin,

wie jede API bzw. Bibliothek hat auch jede verfügbare Grafik- API bzw. Bibliothek Anwendungs- und Plattformspezifische Vor- und Nachteile. Um Dir eine sinnvolle Empfehlung geben zu können, wäre es hilfreich wenn Du etwas mehr zu Deinen Zielen und Anforderungen schreiben würdest. 

Es ist eben ein nicht unerheblicher Unterschied ob Du Space Invaders fürs IPhone willst oder Ergebnisse von Differentialgleichungen einer Computertomographie visuell so aufbereiten willst, das ein Arzt effizient eine Behandlungsmöglichkeit empfehlen kann. 




			
				Anonymous hat gesagt.:
			
		

> verschiedene geometrische Körper im 3D darstellen.



Also, was genau meinst Du mit "verschiedene geometrische Körper"?
Primitive im weitesten Sinne (Kugel, Würfel, …) oder komplexere Objekte mit spezifischen Anforderungen (wenn ja, wie liegen diese vor? Punktwolken, Gitternetze, Formeln, ...?)   

Wie ist Quantität und Qualität der darzustellenden Daten (wie viele Vertices, wie gut ist die Triangulierung)? 

Sind die darzustellenden Daten statisch (die darzustellenden Daten ändern sich nicht, sondern nur z.B. die Ansicht) oder dynamisch (die Objekte ändern Ihre Hülle abhängig von weiten Faktoren)?

Welche Interaktion soll mit den dargestellten Daten möglich sein ("drehbar", "begehbar", "zerstörbar", ...)?

Was sind die Minimalanforderungen der Hartware (wenn OpenGL, alte Möre oder sollen Berechnungen mit der Karte beschleunigt werden)? 


Du siehst, je mehr Informationen von Dir kommen, je größer ist die Wahrscheinlichkeit, dass Dir jemand eine konkrete Empfehlung geben kann.

Gruß,
Michael


----------



## Guest (18. Dez 2008)

Also...


Das ganze soll eine CNC-Fräs-Simulation werden. Soll heißen, es wird von einem Ausgangskörper (wohl nur Quader) 
durch bestimmte Befehle Material weggeschnitten. 

Sollte dann drehbar sein. Das reicht. 

Qualität mittelmäßig, oder durch Schalter verstellbar. 

Genauigkeit...ergibt sich mit dem Rechenaufwand...


----------



## Fancy (19. Dez 2008)

Moin,

ok, immer noch nicht viel, aber ich würde folgendes vermuten:

1.: Die visuelle Darstellung ist im Verhältnis zur Simulation wie Peanuts:
Die physikalisch korrekte Simulation der Spanabhebung im Werkstück und das Zusammenspiel von Maschine, Werkzeug und Werkstück während der einzelnen Arbeitsphasen Gegenlauf-, Gleichlauf-, Plan-, Profil-, Rund-, Formfräsen dürfte sich alles andere als trivial erweisen. Immerhin hat die Bewegung des Werkzeugkopfes nur relativ was mit dem späteren Aussehen des Werkstücks zu tun.
Die Preisgestaltung für CNC Software hat schon seine Berechtigung.

2.: Du hast lediglich nach der visuellen Darstellung gefragt:
Da die eigentliche Simulation den Kern des Programms darstellt, wäre es interessant zu wissen wie diese ihr aktuelles Ergebnis weitergibt. Ich würde vermuten, dass dies Gitternetze oder Punktwolken sein werden.

3. Wahl der API zur visuellen Darstellung:
Punktwolken und Gitternetze können vermutlich letztendlich durch alle oben bereits erwähnten APIs dargestellt werden. Allerdings nützen Dir die ganzen Game-APIs vermutlich nichts. Meine subjektive Empfehlung wäre JoGL. Konkret: GLJPanel und dann die jeweils aktuellen Daten als Vertex Array übergeben. Der Aufwand zur Programmierung der Darstellung dürfte bei < 250 Zeilen und ungeübtem JoGL Nutzer < 1 Stunde liegen.
(Im Gegensatz zur Simulation, das dürfte ehr im Bereich mehrerer Mannjahre liegen)      
Drehen der Ansicht ist kein Problem, Rotationsmatrizen müssen Dir ja was sagen.

4. Persönliche Meinung:
Entweder Du arbeitest bei einem CNC Hersteller und hast selbst Erfahrung in der computergestützten Simulation physikalischer Prozesse... dann hau rein in die Tasten (bei Fragen zu JoGL einfach melden). 
Oder Du hast dies nicht, dann würde ich ein Beratungsgespräch beim CNC Händler Deines Vertrauens und den anschließenden Kauf der Software empfehlen.

Gruß,
Michael


----------



## Landei (20. Dez 2008)

Anzumerken wäre noch, dass man eine "Punktwolke" mit dem Algorithmus "Marching Cubes" oder der Variante "Marching Tetrahedrons" darstellen kann. Letzteren habe ich für die JMonkeyEngine implementiert, befindet sich dort im Wiki ("Metaballs" Beispiel). Die "Game-APIs" nützen dir also u.U. schon etwas (ich kenne viele Beispiele, wo sie erfolgreich für andere Dinge als Spiele eingesetzt werden)


----------



## Horschie (12. Jan 2009)

Hallo,

soweit vielen Dank die Herren! 

Simulation, also von einem beliebigen Werkstück das Programm zu erzeugen, spielt für diese Projekt keine Rolle. Dafür ist es in der Tat besser etwas zu kaufen. 


Habe mich mal mit der ganzen Sache befasst. Also es wird dann wohl auf JOGL rauslaufen. 
Es wurde auch schon mit dem drum herum angefangen...Import/Export, Grundgerüst, etc. 


Ich bräuchte nur mal ein wenig NAchhilfe für die 3D-Grafik (also reine Visualiserung):

Also die Eckpunkte des Körpers müsste ich berechnen können (noch nicht bearbeitet): P_n (x, y, z)


Dann bekomme ich quasi eine Punktwolke. Nur wie mache ich aus dieser Punktwolke einen Körper? 
Soll heißen ich bräuchte da mal ein paar Grundlagen. 
Es gibt ja Vertexarrays und VBOs. Sollen ja recht ähnlich sein...

Auch müsste mir jemand erklären, wie ich die Flächen aus den Punkten definiere... also Fläche_1(P_1, P_2, P_3)
und das ganze dann ausgebe...


Durch die versch. Tutorials habe ich mich schon "gewühlt"...nur irgendwie fehlt mir da ein einfaches Beispiel, bei dem ich restlos durchsteige. 

Danke!
Christoph


----------



## Marco13 (12. Jan 2009)

Aus einer Punktwolke ein Objekt (im Sinne eines Dreiecksnetzes) zu machen, ist eine Kunst für sich... D.h. das kann (oder sollte) man nicht "mal schnell hinschreiben". Wenn man die dann erstmal hat, kann man die Entweder "direkt" Rendern (wenn man die Indizes der Punkte kennt, die jeweils ein Dreieck beschreiben), oder mit VertexArrays oder VBOs - WIE man das macht, hat dann auch Einfluß darauf, wie die Farbewerte an den Eckpunkten definiert oder verwendet werden...


----------



## Fancy (12. Jan 2009)

Moin,

evtl. wäre es interessant zu wissen wie dicht die Punktwolke ist.

Wenn die einzelnen Koordinaten der Vertices ursprünglich aus einer Simulation stammen, kann es unter Umständen schnell passieren, dass die resultierenden Dreiecke kleiner als ein Pixel des Monitors werden (dann schreit die Grafikkarte schon mal gerne). In diesem Fall müssten zusätzlich zur Oberflächenfindung noch Detailstufen berechnet werden um ggf. die Komplexität des Gitternetzes reduzieren zu können.

Wenn die Punktwolke allerdings richtig schön dicht ist, fände ich es persönlich wesentlich eleganter auf Triangulierung und LOD zu verzichten und die Daten direkt als Volumen anzusehen (Stichwort: volume rendering). Die eigentliche Darstellung reicht dann von ray casting bis zu 3D Texturen (jeweils über / durch Shader).

Also, meine Empfehlung:

- wenn die Punktwolke dicht ist (Abstand der Verticies nach der Projektion kleiner gleich einem Pixel): volume rendering

- wenn die Punktwolke nicht dicht ist: Z.B. marching thetraedons, LOD, VBO/VA
(ich würde vermuten, dass sich aus der Reihenfolge der einzelnen Punkte innerhalb der Punktwolke evtl. Rückschlüsse auf die Oberfläche ziehen lassen. Evtl. lässt sich dann das marching* sparen / beschleunigen?)


Also, wie genau sehen die Daten, die dargestellt werden, den aus?

Gruß,
Michael

(P.S.: Vertex Array und Vertex Buffer Objects sind sich in der Tat relativ ähnlich. Technisch unterscheiden sie sich nur durch ein einen minimal anderem API Aufruf und einem etwas modifiziertem Caching-Algorithmus des Grafikkartentreibers (worüber sich dann beeinflussen läst in welchem Adressbereich die eigentlichen Daten der Vertices dann bereit gehalten werden). Beispiele zu VA und VBO kann ich bei Bedarf gerne posten.)


----------



## Horschie (12. Jan 2009)

Habe euch mal ein *ganz einfach Beispiel gemalt...das ihr die Größenordnung seht von der ich rede. 
Dargestellt als Drahtgitter, aber sollte schon Seitenflächen haben. 







Die Punkte kann ich als (X, Y, Z) Koordinate berechnen. Auch kann ich auf dem Weg die FLächen definieren. 

Dann müsste ich nur noch wissen wie mans darstellt.


----------



## 0x7F800000 (13. Jan 2009)

@Fancy Bei dem Anblick muss du dir selbst jetzt äußerst bescheuert vorkommen und sich fragen "was hab ich denn von einer Anfängerfrage in einem java-forum erwartet" 

@OP: dafür brauchst du keine marching cubes und mit volume rendering kommst du da auch nicht weit, was du brauchst sind einfach nur 'n dutzend vertices, ein paar dreiecke und grundlegendste kenntnisse in jogl  mach dir also um die ganzen oben genannten algorithmen erstmal keine gedanken, sondern bring dir erstmal basics bei. wenn du ein dreieck zeichnen kannst, dann kannst du auch ein solchen werkstück zeichnen.


----------



## Horschie (14. Jan 2009)

Ja okee, vlt bin ich wirklich etwas zu kompliziert an die Sache rangegangen. Im folgenden mal ein Beispiel Quelltext. 

Gezeichnet werden soll ein Koordinatenkreuz,  Gitterlinien und Pfeilspitzen. 
Jedoch wird bei mir nur das Koordinatenkreuz in blau auf schwarzem Hintergrund gezeichnet. 

Jogl ist JSR-231


```
package ui.opengl;

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCanvas;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLJPanel;

import javax.media.opengl.glu.GLU;

import javax.swing.JPanel;

import com.sun.opengl.util.GLUT;

public class MyOpenGLPanel extends GLCanvas implements MouseMotionListener, MouseListener, GLEventListener
{
	private boolean showEdges = true; 
	private boolean showFaces = true; 
	
	FloatBuffer points; // 3D-Punkte
	FloatBuffer lines;  // Linien aus 2x 3D-Punkt
	
	public MyOpenGLPanel()
	{
		this.addGLEventListener(this); 
	}

	@Override
	public void mouseDragged(MouseEvent arg0)
	{
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseMoved(MouseEvent arg0)
	{
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseClicked(MouseEvent arg0)
	{
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseEntered(MouseEvent arg0)
	{
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseExited(MouseEvent arg0)
	{
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mousePressed(MouseEvent arg0)
	{
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseReleased(MouseEvent arg0)
	{
		// TODO Auto-generated method stub
		
	}

	@Override
	public void display(GLAutoDrawable arg0)
	{
		GL gl = arg0.getGL(); 
		
		gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

		float red;
		float green;
		float blue;
		

		////////////////////
		//drawing the grid
		red = 0.2f;
		green = 0.2f;
		blue = 0.2f;
		
		gl.glColor3f(red, green, blue);
		
		//You may notice I'm using GL_LINES here.
		//Details of glBegin() will be discussed later.
		gl.glBegin(GL.GL_LINES);
		
		//draw the vertical lines
		for (int x=-250; x<=250; x+=10) {
			gl.glVertex2f(x, -150);
			gl.glVertex2f(x, 150);
		}
		
		//draw the horizontal lines
		for (int y=-150; y<=150; y+=10) {
			gl.glVertex2f(-250, y);
			gl.glVertex2f(250, y);
		}
		
		gl.glEnd();
		gl.glFlush(); 
		//////////////////////////////
		// draw the x-axis and y-axis
		red = 0.0f;
		green = 0.2f;
		blue = 0.4f;
		
		gl.glColor3f(red, green, blue);
		
		gl.glBegin(GL.GL_LINES);
		
		//line for y-axis
		gl.glVertex2d(0, 140);
		gl.glVertex2d(0, -140);
		
		//line for x-axis
		gl.glVertex2d(240, 0);
		gl.glVertex2d(-240, 0);
		
		gl.glEnd();
		gl.glFlush();
		/////////////////////
		// draw arrow heads
		gl.glBegin(GL.GL_TRIANGLES);
		
		gl.glVertex2d( 0, 150);
		gl.glVertex2d(-5, 140);
		gl.glVertex2d( 5, 140);
		
		gl.glVertex2d( 0, -150);
		gl.glVertex2d(-5, -140);
		gl.glVertex2d( 5, -140);
		
		gl.glVertex2d(250, 0);
		gl.glVertex2d(240,-5);
		gl.glVertex2d(240, 5);
		
		gl.glVertex2d(-250, 0);
		gl.glVertex2d(-240,-5);
		gl.glVertex2d(-240, 5);
		
		gl.glEnd();
		gl.glFlush();
	}

	@Override
	public void displayChanged(GLAutoDrawable arg0, boolean arg1, boolean arg2)
	{
		// TODO Auto-generated method stub
		
	}

	@Override
	public void init(GLAutoDrawable arg0)
	{
	      GL gl = arg0.getGL();
	}

	@Override
	public void reshape(GLAutoDrawable arg0, int arg1, int arg2, int arg3,
			int arg4)
	{
   
	}

}
```


Danke 
Christoph


----------



## Horschie (14. Jan 2009)

hat sich geklärt. Jetzt muss ichs nur noch für 3D hinbekommen...


----------

