# Frage zu 3D Funktionsplotter



## Plotter (2. Mrz 2010)

Hallo,

ich habe im Internet (irgenwo in den Sun-Foren) einen 3D-Funktionsplotter gefunden (source unten), der 3D Funktionen in 2D plottet.

Meine Frage ist keine technische sondern eine logische: wie macht der das? Also wie plottet man in 2D eine 3D Funktion ohne eine 3D Engine?

Ich hoffe, dass Ihr mir helfen könnt - das ist sehr wichtig für mich!
Gruß,
Gast


=========
EDIT: Hier gefunden: Index of /~simonbr/applets/fplot

FPlot3D:

```
package fplot;

// 
// 3D-Darstellung von Funktionen f(x,y)
//
// Simon Bruderer, Mai 2002
//
import java.applet.Applet;
import java.awt.event.*;
import java.awt.*;

//////////////////////////////////////////////////////////////
//
// Class Fplot: Benutzeroberfl?che, Generierung der Daten, Applet
//
//////////////////////////////////////////////////////////////

public class Fplot3D extends Applet implements ItemListener, ActionListener {

	String[] ColBez = { "Weiss", "Hellgrau", "Grau", "Dunkelgrau", "Schwarz",
			"Rot", "Blau", "Gr?n", "Gelb", "Magenta", "Cyan", "Orange", "Pink" };

	Color[] ColCol = { Color.white, Color.lightGray, Color.gray,
			Color.darkGray, Color.black, Color.red, Color.blue, Color.green,
			Color.yellow, Color.magenta, Color.cyan, Color.orange, Color.pink };

	Panel EinstellungsPanel1 = new Panel();
	Panel EinstellungsPanel2 = new Panel();
	Panel AusdruckPanel = new Panel();
	Panel OptionenPanel = new Panel();
	Panel ControlPanel = new Panel();
	Panel StatusPanel = new Panel();

	Ansicht3D MeineAnsicht3D = new Ansicht3D(10, 10);

	Choice C_Color = new Choice();
	Checkbox Cb_Schatten = new Checkbox("Schatten", true);
	Checkbox Cb_Rand = new Checkbox("Rand", false);
	Checkbox Cb_Backsurf = new Checkbox("R?ckseite", false);
	TextField Tf_Minx = new TextField("-3");
	TextField Tf_Maxx = new TextField("3");
	TextField Tf_Miny = new TextField("-3");
	TextField Tf_Maxy = new TextField("3");
	TextField Tf_XStep = new TextField("30");
	TextField Tf_YStep = new TextField("30");
	TextField Tf_ZFakt = new TextField("0.5");
	TextField Tf_Expr = new TextField("2*(x^3+3*y^2+x-y)*exp(-x^2-y^2)");
	Label Lb_Status = new Label();
	Button Bt_Zeichnen = new Button("Zeichnen");

	public void init() {
		setBackground(Color.white);
		OptionenPanel.add(new Label("Farbe", Label.RIGHT));
		OptionenPanel.add(C_Color);
		C_Color.addItemListener(this);
		OptionenPanel.add(Cb_Schatten);
		Cb_Schatten.addItemListener(this);
		OptionenPanel.add(Cb_Rand);
		Cb_Rand.addItemListener(this);
		OptionenPanel.add(Cb_Backsurf);
		Cb_Backsurf.addItemListener(this);
		OptionenPanel.add(Bt_Zeichnen);
		Bt_Zeichnen.addActionListener(this);
		OptionenPanel.setLayout(new GridLayout(1, 6));
		AusdruckPanel.add(new Label("f(x,y)=", Label.RIGHT));
		AusdruckPanel.add(Tf_Expr);
		AusdruckPanel.setLayout(new GridLayout(1, 2));
		EinstellungsPanel1.add(new Label("Min-x", Label.RIGHT));
		EinstellungsPanel1.add(Tf_Minx);
		EinstellungsPanel1.add(new Label("Max-x", Label.RIGHT));
		EinstellungsPanel1.add(Tf_Maxx);
		EinstellungsPanel1.add(new Label("Min-y", Label.RIGHT));
		EinstellungsPanel1.add(Tf_Miny);
		EinstellungsPanel1.add(new Label("Max-y", Label.RIGHT));
		EinstellungsPanel1.add(Tf_Maxy);
		EinstellungsPanel1.setLayout(new GridLayout(1, 8));
		EinstellungsPanel2.add(new Label("x-Step", Label.RIGHT));
		EinstellungsPanel2.add(Tf_XStep);
		EinstellungsPanel2.add(new Label("y-Step", Label.RIGHT));
		EinstellungsPanel2.add(Tf_YStep);
		EinstellungsPanel2.add(new Label("z-Faktor", Label.RIGHT));
		EinstellungsPanel2.add(Tf_ZFakt);
		EinstellungsPanel2.add(new Label(""));
		EinstellungsPanel2.add(new Label(""));

		EinstellungsPanel2.setLayout(new GridLayout(1, 8));
		StatusPanel.add(Lb_Status);
		StatusPanel.setLayout(new GridLayout(1, 1));
		ControlPanel.add(AusdruckPanel);
		ControlPanel.add(EinstellungsPanel1);
		ControlPanel.add(EinstellungsPanel2);
		ControlPanel.add(OptionenPanel);
		ControlPanel.add(StatusPanel);
		ControlPanel.setLayout(new GridLayout(5, 1));
		setLayout(new BorderLayout(5, 5));
		add(ControlPanel, BorderLayout.SOUTH);
		add(MeineAnsicht3D, BorderLayout.CENTER);
		for (int i = 0; i < ColBez.length; i++)
			C_Color.add(ColBez[i]);
	}

	public void start() {
		initplot();
	}

	public void itemStateChanged(ItemEvent event) {
		MeineAnsicht3D.schatten = Cb_Schatten.getState();
		MeineAnsicht3D.rand = Cb_Rand.getState();
		MeineAnsicht3D.backsurf = Cb_Backsurf.getState();
		MeineAnsicht3D.setCol(ColCol[C_Color.getSelectedIndex()]);
		MeineAnsicht3D.zeichnen();
	}

	public void actionPerformed(ActionEvent event) {
		if (event.getActionCommand().equals("Zeichnen")) {
			initplot();
		}
	}

	private double trytodouble(String Zahl) {
		double dbzahl = 0;
		try {
			dbzahl = Double.valueOf(Zahl).doubleValue();
		} catch (NumberFormatException nfe) {
			dbzahl = 0;
		}
		return dbzahl;
	}

	public void initplot() {
		Lb_Status.setText("");
		double xmin = trytodouble(Tf_Minx.getText());
		double xmax = trytodouble(Tf_Maxx.getText());
		if (xmax <= xmin) {
			Lb_Status.setText("Fehler: Max-x<=Min-x");
			return;
		}
		double ymin = trytodouble(Tf_Miny.getText());
		double ymax = trytodouble(Tf_Maxy.getText());
		if (ymax <= ymin) {
			Lb_Status.setText("Fehler: Max-y<=Min-y");
			return;
		}
		int xstep = (int) trytodouble(Tf_XStep.getText()) + 1;
		if (xstep < 3 || xstep > 101) {
			Lb_Status.setText("Fehler: x-Step muss in [2..100] sein");
			return;
		}
		int ystep = (int) trytodouble(Tf_YStep.getText()) + 1;
		if (ystep < 3 || ystep > 101) {
			Lb_Status.setText("Fehler: y-Step muss in [2..100] sein");
			return;
		}
		double zfaktor = trytodouble(Tf_ZFakt.getText());
		if (zfaktor == 0) {
			Lb_Status.setText("Fehler: z-Faktor darf nicht null sein");
			return;
		}

		String Ausdr = Tf_Expr.getText();
		MyParser p = new MyParser(Ausdr);
		try {
			p.newvar("x", xmin);
			p.newvar("y", ymin);
			double fxy = p.parse();
		} catch (SyntaxException err) {
			String Aus = err.getMessage();
			Lb_Status.setText("Syntax-Fehler: " + Aus);
			return;
		}
		plot3d(xmin, xmax, ymin, ymax, xstep, ystep, zfaktor, Ausdr);
		Lb_Status.setText("f(x,y)=" + p.getinput() + "                     ("
				+ xmin + "," + ymin + ")-(" + xmax + "," + ymax + ")");
	}

	public void plot3d(double xmin, double xmax, double ymin, double ymax,
			int xstep, int ystep, double zfaktor, String Ausdr) {
		MeineAnsicht3D.reset(xstep * ystep + 2 * (xstep + ystep), xstep * ystep
				* 2 + 10);
		MeineAnsicht3D.schatten = Cb_Schatten.getState();
		MeineAnsicht3D.rand = Cb_Rand.getState();
		MeineAnsicht3D.backsurf = Cb_Backsurf.getState();
		MeineAnsicht3D.setCol(ColCol[C_Color.getSelectedIndex()]);
		double xdiff = (xmax - xmin) / (xstep - 1);
		double ydiff = (ymax - ymin) / (ystep - 1);

		double[][] werte = new double[xstep][ystep];

		MyParser p = new MyParser(Ausdr);
		try {
			p.newvar("x", 0.0);
			p.newvar("y", 0.0);
		} catch (SyntaxException err) {
			System.out.println(err.getMessage());
		}

		for (int xi = 0; xi < xstep; xi++) {
			double x = xmin + xi * xdiff;
			for (int yi = 0; yi < ystep; yi++) {
				double y = ymin + yi * ydiff;
				werte[xi][yi] = 0;
				try {
					p.setvar("x", x);
					p.setvar("y", y);
					werte[xi][yi] = p.parse();
					if (Double.isInfinite(werte[xi][yi])
							|| Double.isNaN(werte[xi][yi])) {
						werte[xi][yi] = 0;
					}
				} catch (SyntaxException err) {
					System.out.println(err.getMessage());
				}
			}
		}

		double xdiff2 = 2.0 / (double) (xstep - 1);
		double ydiff2 = 2.0 / (double) (ystep - 1);
		for (int xi = 0; xi < xstep; xi++) {
			double x = -1 + xdiff2 * xi;
			for (int yi = 0; yi < ystep; yi++) {
				double y = -1 + ydiff2 * yi;
				MeineAnsicht3D.addPoint(1.5 * x, 1.5 * y, werte[xi][yi]
						* zfaktor);
			}
		}

		for (int xi = 0; xi < xstep - 1; xi++) {
			for (int yi = 0; yi < ystep - 1; yi++) {
				int xo = xi * ystep + yi;
				MeineAnsicht3D.addTriangle(xo + 1, xo, xo + ystep);
				MeineAnsicht3D.addTriangle(xo + ystep, xo + ystep + 1, xo + 1);
			}
		}
		MeineAnsicht3D.zeichnen();
	}

}
```
Ansicht3D.java

```
package fplot;
import java.awt.event.*;
import java.awt.*;

//////////////////////////////////////////////////////////////
//
// Class Ansicht3D: 3D-Darstellung von Dreiecken-mit simpler Schattierung
//
// Simon Bruderer, M?rz 2002, ?berarbeitet im Mai 2002
//
//////////////////////////////////////////////////////////////

class Ansicht3D extends Panel implements MouseListener,MouseMotionListener{

public int phi=0;
public int rho=0;

public double xbetrachter=20;
public double xschirm=1500;

public int maxpoint;
public int maxtriangle;
public double[][] point;
public int[][] triangle;
public int anzpoint=0;
public int anztriangle=0;

public boolean schatten=false;
public boolean rand=false;
public boolean backsurf=false;

private double[][] drehpoint;
private int[][] projpoint;
private double[] xabstand;
private int[] xreihenfolge;

private int xgedrueckt=0;
private int ygedrueckt=0;
private int phi0=0;
private int rho0=0;
private boolean gedrueckt=false;

private Image puffer;
private Graphics pufferg;

private Color Grundfarbe;
private float[] GrundfarbeHSB=new float[3];			

public Ansicht3D(int setmaxpoint,int setmaxtriangle){
	super();	
	addMouseListener(this);
	addMouseMotionListener(this);		
	
	maxpoint=setmaxpoint;
	maxtriangle=setmaxtriangle;
	point=new double[maxpoint][3];
 	triangle=new int[maxtriangle][3];
	drehpoint=new double[maxpoint][3];
 	projpoint=new int[maxpoint][2];
 	xabstand=new double[maxtriangle];
	xreihenfolge=new int[maxtriangle];
}

public void reset(int setmaxpoint,int setmaxtriangle){
	maxpoint=setmaxpoint;
	maxtriangle=setmaxtriangle;
	point=new double[maxpoint][3];
 	triangle=new int[maxtriangle][3];
	drehpoint=new double[maxpoint][3];
 	projpoint=new int[maxpoint][2];
 	xabstand=new double[maxtriangle];
	xreihenfolge=new int[maxtriangle];
	anzpoint=0;
	anztriangle=0;
	phi=0;
	rho=0;
	xbetrachter=20;
	xschirm=1500;
}

public void addPoint(double x, double y, double z){
	point[anzpoint][0]=x;
	point[anzpoint][1]=y;
	point[anzpoint][2]=z;
	anzpoint++;		
}

public void addTriangle(int p1,int p2,int p3){
	triangle[anztriangle][0]=p1;
	triangle[anztriangle][1]=p2;	
	triangle[anztriangle][2]=p3;	
	anztriangle++;
}

public void setCol(Color c){
	Grundfarbe=c;	
	Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), GrundfarbeHSB);	
}

private void quickSort(int l, int r){
// Quicksort-Algorithmus
// Habe ich ?bernommen von R. St?rk, Vorlesung Informatik I f?r
// Mathematiker und Physiker an der ETH-Z?rich
	if (l < r){
		int m = partition(l, r);
		quickSort(m + 1, r);
		quickSort(l, m);
	}
}

private void swap(int i,int j){
	double xa=xabstand[i];
	int xr=xreihenfolge[i];
	xabstand[i]=xabstand[j];
	xreihenfolge[i]=xreihenfolge[j];
	xabstand[j]=xa;
	xreihenfolge[j]=xr;
}
	
private int partition(int l, int r) {
	double x=xabstand[(l+r)/2];
	while (l<=r) {
		while (x<xabstand[r]) r--;		
		while (xabstand[l]<x ) l++;
		if (l<r){
			swap(l++,r--);
		}
		else{
			return r;
		}
	}
	return r;
}

double[] licht={1.0/Math.sqrt(3),1.0/Math.sqrt(3),1.0/Math.sqrt(3)};

private double winkelschatten(int i){
	// 1. Normalenvektor n des Dreiecks berechnen
	// 2. n normieren auf L?nge 1
	// 3. Skalarprodukt mit normiertem Lichtvektor berechnen	
	double p0[]=drehpoint[triangle[i][0]];
	double p1[]=drehpoint[triangle[i][1]];
	double p2[]=drehpoint[triangle[i][2]];
	double[] n1={p1[0]-p0[0],p1[1]-p0[1],p1[2]-p0[2]};
	double[] n2={p2[0]-p0[0],p2[1]-p0[1],p2[2]-p0[2]};
	double[] n={n1[1]*n2[2]-n1[2]*n2[1],n1[2]*n2[0]-n1[0]*n2[2],n1[0]*n2[1]-n1[1]*n2[0]};
	double nnorm=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);	
	double sp=(n[0]*licht[0]+n[1]*licht[1]+n[2]*licht[2])/(nnorm);
	return sp;
}

private boolean winkelsichtbar(int i){
	// Hier wird berechnet, ob der Normalenvektor des Dreiecks nach
	// vorne oder nach hinten zeigt.
	// Eigentlich die gleiche Funktion wie "winkelschatten", jedoch
	// optimiert, da der Sichtvektor immer in Richtung der x-Achse zeigt
	double n11=drehpoint[triangle[i][1]][1]-drehpoint[triangle[i][0]][1];
	double n12=drehpoint[triangle[i][1]][2]-drehpoint[triangle[i][0]][2];
	double n21=drehpoint[triangle[i][2]][1]-drehpoint[triangle[i][0]][1];
	double n22=drehpoint[triangle[i][2]][2]-drehpoint[triangle[i][0]][2];	
	double n=n11*n22-n12*n21;
	return n>0?true:false;
}

public void zeichnen(){
	int breit=getSize().width;
	int hoch=getSize().height;		
	if(puffer==null){
		puffer=createImage(getSize().width,getSize().height);				
		pufferg=puffer.getGraphics();				
	}
	if(puffer.getWidth(this)!=breit || puffer.getHeight(this)!=hoch){ 
		puffer=createImage(getSize().width,getSize().height);				
		pufferg=puffer.getGraphics();		
	}	
	pufferg.setColor(Color.white);
	pufferg.fillRect(0,0,this.getSize().width,this.getSize().height);
	
	// Vorbereitung: Winkel und Trigonometrische Funktionen berechnen
	phi=phi%360;
	if(rho>90) rho=90;
	if(rho<-90) rho=-90;	
	if(phi<0) phi=360+phi;	
	double phirad=((phi*Math.PI)/180);
	double rhorad=((rho*Math.PI)/180);
	double cosrotphi=Math.cos(phirad);
	double sinrotphi=Math.sin(phirad);	
	double cosrotrho=Math.cos(rhorad);
	double sinrotrho=Math.sin(rhorad);
	int breit2=(int)(breit/2.0);
	int hoch2=(int)(hoch/2.0);
	double zstrich;
	double ystrich;
	int anztrianglebacksurf=0;	

	// Punkte drehen, gleichzeitig Projektion in Bildschirmkoordinaten
	for(int i=0;i<anzpoint;i++){
		drehpoint[i][0]=cosrotrho*cosrotphi*point[i][0]-cosrotrho*sinrotphi*point[i][1]-sinrotrho*point[i][2];
		drehpoint[i][1]=sinrotphi*point[i][0]+cosrotphi*point[i][1];
		drehpoint[i][2]=sinrotrho*cosrotphi*point[i][0]-sinrotrho*sinrotphi*point[i][1]+cosrotrho*point[i][2];		
		zstrich=xschirm*drehpoint[i][2]/(xbetrachter-drehpoint[i][0]);
		ystrich=xschirm*drehpoint[i][1]/(xbetrachter-drehpoint[i][0]);		
		projpoint[i][0]=(int)ystrich+breit2;
		projpoint[i][1]=-(int)zstrich+hoch2;
	}	
	
	// Mittlerer x-Abstand pro Dreieck berechnen
	// und Dreiecke ausscheiden, deren Normalenvektor nach hinten zeigt.
	if(backsurf){
		for(int i=0;i<anztriangle;i++){	
			if(winkelsichtbar(i)){
				double x1=drehpoint[triangle[i][0]][0];
				double x2=drehpoint[triangle[i][1]][0];
				double x3=drehpoint[triangle[i][2]][0];		
				double xm=(x1+x2+x3)/3;
								
				xabstand[anztrianglebacksurf]=xm;
				xreihenfolge[anztrianglebacksurf]=i;
				anztrianglebacksurf++;
			}
		}				
	}
	else{
		for(int i=0;i<anztriangle;i++){	
			double x1=drehpoint[triangle[i][0]][0];
			double x2=drehpoint[triangle[i][1]][0];
			double x3=drehpoint[triangle[i][2]][0];		
			xabstand[i]=(x1+x2+x3)/3;
			xreihenfolge[i]=i;
		}
		anztrianglebacksurf=anztriangle;
	}	
	
	// Zeichnungsreihenfolge sortieren nach mittlerem x-Abstand	
	quickSort(0,anztrianglebacksurf-1);	
	// Zeichnen!
	for(int i=0;i<anztrianglebacksurf;i++){	
		int j=xreihenfolge[i];
		int[] arx={projpoint[triangle[j][0]][0],
				   projpoint[triangle[j][1]][0],
				   projpoint[triangle[j][2]][0]};
		int[] ary={projpoint[triangle[j][0]][1],
				   projpoint[triangle[j][1]][1],
				   projpoint[triangle[j][2]][1]};				
		if(schatten){			
			double w=winkelschatten(j);
			w=w/2.0+0.5;									
			pufferg.setColor(Color.getHSBColor(GrundfarbeHSB[0],GrundfarbeHSB[1],(float)w));			
		}
		else{
			pufferg.setColor(Grundfarbe);
		}
		pufferg.fillPolygon(arx,ary,3);			
		if(rand){
			pufferg.setColor(Color.black);
			pufferg.drawPolygon(arx,ary,3);		
		}		
	}	
	pufferg.setColor(Color.black);
	pufferg.drawString("Phi:"+Double.toString(phi),10,20);
	pufferg.drawString("Rho:"+Double.toString(rho),10,35);		
	paint(getGraphics());
	//repaint();			
}

public void paint(Graphics g){	
	if(puffer!=null) g.drawImage(puffer,0,0,this);	
}

public void update(Graphics g){   
	paint(g);
}

public void mousePressed(MouseEvent e){
	phi0=phi; 
	rho0=rho;
	xgedrueckt=e.getX(); 
	ygedrueckt=e.getY();
	gedrueckt=true;
}

public void mouseReleased(MouseEvent e){		
	phi=phi0-(int)((xgedrueckt-e.getX())/2); 
	rho=rho0+(int)((ygedrueckt-e.getY())/2);		
	zeichnen();
	gedrueckt=false;
}

public void mouseDragged(MouseEvent e){	
	if(gedrueckt==true){		
		phi=phi0-(int)((xgedrueckt-e.getX())/2); 
		rho=rho0+(int)((ygedrueckt-e.getY())/2);	
		zeichnen();
	}	
}

public void mouseMoved(MouseEvent e){}
public void mouseExited(MouseEvent e){}   
public void mouseEntered(MouseEvent e){}
public void mouseClicked(MouseEvent e){}

}
```


----------



## FArt (2. Mrz 2010)

> ohne eine 3D Engine


Wenn er eine 3D-Funktion in 2D umsetzt, enthält er eine (wenn auch einfache) 3D-Engine.


----------



## MQue (2. Mrz 2010)

eine nicht ganz ernst gemeinte Antwort, auch das ist ein 3D Plotter:

YouTube - 3D Drucker ZPrinter 450 www.zprinter.de


----------



## Plotter (2. Mrz 2010)

Hallo,

okay, dass da eine einfache 3D-Engine hinterliegt habe ich mir auch gedacht (wie soll es sonst gehen?). Aber meine Frage war, wie ich eine solche Engine umsetze: selber programmieren!

Gruße,
Gast


----------



## FArt (3. Mrz 2010)

> Aber meine Frage war, wie ich eine solche Engine umsetze: selber programmieren!


Wenn das deine Frage war, hättest du sie so stellen sollen.

Vorher solltest du dir etwas Theorie antun. Schlagwörter für Google wären z.B. Perspektive oder perspektivische Darstellung. Danach wirst du auch einiges an Mathe brauche... Raumkoordinaten, Transformationen. Da könnte diese Suche helfen: transformation 3d in 2d - Google-Suche.
Je nach Anspruch geht es dann noch weiter... das Prinzip ist aber erst mal: giyf


----------



## Plotter (3. Mrz 2010)

Also mit den mathematischen Grundlagen (Vektorrechnung; Parallelprojektion entlang eines Richtungsvektors auf eine Ebene) kenne ich mich aus! Doch ich kann es irgendwie nicht angehen. 

Also, um es näher zu beschreiben: das Bild was später raus kommt, soll so aussehen:
	

	
	
		
		

		
			





 (also der Funktionsgraph soll auf so einer "Raute" - Grundfläche gezeichnet werden, die sich mitten im Bild befindet)

Wenn ich eine Parallelprojektion mache, dann wird ja der Raum auf eine Ebene projeziert, die sich auch im Raum befindet. Doch ich will es ja so haben, dass die Projektion außerhalb des Raums geschieht. Und die Drehung des Koordinatensystems kann man ja durch die Drehung der Ebene und des Vektors - der die Abbildungsrichtung angibt - erreicht werden, oder? Außerdem: der Abbildungsvektor, ist doch einfach der Normalenvektor nur -1-Mal, oder?

Wie baue ich mir daraus nun ein Beispiel, dass funktioniert? Irgendwie habe ich gewisse Startschwierigkeiten ...
Gast


----------



## JanHH (5. Mrz 2010)

Naja, das ist schon bissi kompliziert. Bei dem Bild handelt es sich ausserdem nicht um Parallelprojektion, sondern um Fluchtpunktperspektive.

Letzten Endes.. Resultat der Funktion ist ein 3D-Modell, hier bestehend aus dem Skalen-Raster, den Vierecken, die die gebogene Fläche ergeben (was an sich ziemlich unsauber sind, man würde eher Dreiecke verwenden), und den diversen Punkten, die da so rumschwirren.

Du musst die Raum-Koordinanten der Bestandteile dieses Modells halt transformieren, so dass sie, vom gewünschten Blickwinkel aus, in Fluchtpunktperspektive auf dem Bildschirm erscheinen.. Wenn ich das programmieren sollte, würde ich die gewünschte Blickrichtung wohl so realisieren, dass die Punkte des Modells entsprechend gedreht werden (in diesem Fall wohl um zwei Achsen), das Resultat dann so verschieben, dass der Mittelpunkt des ganzen bei 0/0/0 liegt (sofern das nicht eh schon der Fall ist), dann das Modell nach hinten in den Raum verschieben (also die z-Koordinate mit einem Offset addieren), und das dann als Fluchtpunktperspektive projiizieren (was, grob gesagt, so aussieht: Je weiter ein Punkt vom Betrachter weg, destso näher am Mittelpunkt liegt er, was dadurch erreicht wird, dass die  x- und y- Koordinate jeweils durch die z-Koordinate geteilt wird. Da man danach nur recht kleine Werte hat, das ganze noch mit einem "korrekturfaktor" multiplizieren, um wieder ein vernünftig grosses Bild zu erreichen). Danach muss man noch jeweils die Hälfte der Bildschirm x- und y-Auflösung addieren, da der Nullpunkt ja links oben liegt, und nicht in der Mitte des Bildschirms.

Das ist die mathematisch etwas brutale Methode, funktioniert aber. Oder Du benutzt irgendein 3D-Framework.. gibts sicherlich auch in Java.


----------



## FArt (5. Mrz 2010)

Noch mal die Erinnerung an giyf. Da findet man mit bereits genannten suchbegriffen so was: http://www-gs.informatik.tu-cottbus.de/cg_v06b.pdf


----------

