3D Dreiecke Füllen

oska

Mitglied
Ich hab begonnen eine einfache 3D Engine für ein eigenes Spiel zu schreiben. Mein Problem ist nun das ich mit meinem Algorithmus zum Füllen der Polygone auf dem Screen nur noch 2 fps erreiche. Wenn ich "fillPoly(...)" verwende werden daraus 250 fps. Nachfolgend der Code:
Code:
	public void drawCube(Graphics g, cube c)
	{
	  if (c != null)
	  {
		for (i=0; i<6; i++)
		{
		  for (j=0; j<2; j++)
		  {
			if (c.r[i].t[j].visible)
			{

				int arx[] = {
					c.r[i].t[j].p[0].sx,                                               // ScreenX
					c.r[i].t[j].p[1].sx, 
					c.r[i].t[j].p[2].sx };
				int ary[] = {
					c.r[i].t[j].p[0].sy,                                             //ScreenY
					c.r[i].t[j].p[1].sy, 
					c.r[i].t[j].p[2].sy };
				fillTriangle(g, arx, ary, c.r[i].color);
			}
		  }
		} 
	  }
	}

    public void fillTriangle(Graphics g, int x[], int y[], Color color)
    {
		double incshort, inclong, xinc1, xinc2;
		int i, j;
		g.setColor(color);

		for(i=0; i < 3; i++)
		{
			for(j=0; j < 3; j++)
			{
				if(y[i]<y[j])
				{
					int tmp=y[i];
					y[i]=y[j];
					y[j]=tmp;
					tmp=x[i];
					x[i]=x[j];
					x[j]=tmp;
				}
			}
		}

//		if(y[2]>y[1]){
//			swap(y, 2, 1);
//		}else if(y[1]>y[0]){
//			swap(y, 0, 2);
//		}else if(y[0]>y[2]){
//			swap(y, 0, 2);
//		}

		if(x[1]<x[0])
		{
			double dx=x[0]-x[1];
			double dy=y[1]-y[0];
			incshort = (dx/dy)*(-1);	
		}
		else
		{
			double dx=x[1]-x[0];
			double dy=y[1]-y[0];
			incshort = dx/dy;	
		}

		if(x[2]<x[0])
		{
			double dxlong=x[0]-x[2];
			double dylong=y[2]-y[0];
			inclong = (dxlong/dylong)*(-1);
		}
		else
		{
			double dxlong=x[2]-x[0];
			double dylong=y[2]-y[0];
			inclong = dxlong/dylong;
		}

		xinc1=x[0];
		xinc2=x[0];

		for(i=y[0]; i<=y[1]; i++)
		{
			g.drawLine((int)xinc1, i,  (int)xinc2, i);

			xinc1=xinc1+incshort;
			xinc2=xinc2+inclong;
		}
    }

	public void drawHLine(Graphics g, int xs, int ys, int xe, int ye, Color color)
	{
		int i, j;
//		if(xs<xe)
//		{
//			for(i=xs; i<=xe; i++)
//			{
//				plotPixel(g, i, ys, color);
//			}	
//		}
		if(xs>xe)
		{
			for(i=xs; i>=xe; i--)
			{
				plotPixel(g, i, ys, color);
			}	
		}
	}

	public void plotPixel(Graphics g, int x, int y, Color c)
	{
		g.drawLine(x, y, x, y);
	}


Der Teil der Alles auszubremsen scheint ist drawHLine(...) mit plotPixel(...). Wenn ich das einfach durch g.drawLine(...) ersetze erreiche ich immerhin noch 60 fps.

Meine Frage nun: Warum läuft das Prog so langsam? Gibts da bessere Möglichkeiten einzelne Pixel auf dem Bildschirm zu setzten?
 
nun das kommt von der architektur mit der java arbeitet...

java selbst ist relativ langsam, weil es ja vom interpreter in echtzeit abgearbeitet werden muss...
und jetzt rufst du im interpreter die funktion einige male auf... jetzt muss der java interpreter da ja dann da hin und her springen was wertvolle taktzyklen verbraucht, anders wenn du die g. funktionen benutzt

denn g. ist eine klasse die prinziell erstmal gar nicht aus code besteht sondern das sind native methoden..das heißt das deine aufruft g.drawLine in wirklichkeit eigendlich eine vermutlich in C programmierte funktion aus einer DLL datei aufruft, und die sind dadurch das sie direkt zu native code kompiliert werden um einiges schneller, wundert mich net das es sich um ettliche FPS handelt die dir da ab handen kommen....

jedenfalls gibts keine schneller methode, als das native code interface... (siehe thread über NCI)
 
Falls es noch jemanden Interessiert: es gibt doch eine schneller Methode Pixel zu setzten!

Zuerst legt man sich ein Array aus int an, das so groß ist wie die Höhe und Breite des Screens.

public int pixelBuffer[]=new int[h*w];

Dann berechnet man die Position des Pixels den man berarbeiten will.

long pos=y*700+x;

Jetzt kann man aus einem Color Objekt oder von Hand die RGB Werte in das Array eintragen.

int red=c.getRed();
int green=c.getGreen();
int blue=c.getBlue();
int alpha=c.getAlpha();

Die RGB können nun in einen 32 bit Integer umgewandelt werden. Dazu benutzt man bitweise Operatoren.

int rgba = (alpha << 24) | (red << 16) | (green << 8) | blue;

Jetzt wieder ins Array eintragen.

pixelBuffer[(int)pos]=rgba;

Aus diesem Array kann man nun ein Image erzeugen, welches bedeutend schneller auf den Screen geschrieben werden kann als jeden Pixel mit g.drawLine zu setzen.

Image img = createImage(new MemoryImageSource (w, h, pixelBuffer, 0, w));

Zum Schluß zum Beispiel g.drawImage(img, 0, 0, this); zum zeichnen.

Eigentlich ganz einfach und richtig effektiv. Ich erreich jetzt zumindest wieder 25 FPS.

Ahoioioi......................................................................................................................................
 
Zurück