Entwickler-Ecke

Multimedia / Grafik - Polygon mit Canvas/OpenGL mit einem Muster füllen?


Passi077 - Mo 11.07.05 15:35
Titel: Polygon mit Canvas/OpenGL mit einem Muster füllen?
Hi,

folgendes Problem:

Ich hab ein Polygon mit beliebig vielen Punkten gegeben, und dieses möchte ich nun mit einem frei wählbaren Muster, also einem Bitmap mit z.B. der Größe 32x32 Pixel, füllen.

Kann man das irgendwie hinkriegen?

Edit: Wenns eine Möglichkeit gibt, ein 2D Polygon mit OpenGL mit der Textur drauf zu zeichnen, ist auch ok ;)

Danke + Grüße
Passi


maxk - Mo 11.07.05 16:04

Hmm, das ist jetzt nur so ne Idee, aber vllt. klappt's ja. Du könntest dein Bitmap erstellen, dass die Maße deiner Figur hat. Die ganze Fläche füllst du mit dem Muster, das du verwenden möchtest. Dann zeichnest du ein Polygon drum und füllst die Fläche drumherum mit einer Farbe, die du dann als Transparent definierst. Dann noch auf das eigentliche Bild kopieren. Wie man bzw. ob man überhaupt um ein Polygon drumherum füllen kann, weiss ich nicht. Aber vllt. hilft die Idee ja bei einer anderen Idee :D

Gruß,
maxk


F34r0fTh3D4rk - Mo 11.07.05 16:19

mit opengl sehe ich da kein problem :?


BenBE - Mo 11.07.05 16:20

Welcher Art ist die Musterung zu verstehen? Tiled \ Strechted? Ist das Polygon Clipping Mask?

Davon hängt das ab.

Wenn das Polygon clipping mask ist, empfielt sich die Nutzung des Stencil-Puffers (Polygon rein und zum Clippen eines Quads mit den Eckpunkten der Textur nutzen).


Passi077 - Mo 11.07.05 16:22

Das hab ich mir auch überlegt, aber da gibts eben das Problem mit dem da drumrum füllen... mit Floodfill kann man ja leider keine Tolerance einstellen - und selbst wenn man das könnte gäbe es dann noch das Problem wenn PenColor und Texturhintergrund die selbe Farbe haben... dann wird mein Polygon einfach mit gefüllt.


Passi077 - Mo 11.07.05 16:25

Zitat:

Welcher Art ist die Musterung zu verstehen? Tiled \ Strechted? Ist das Polygon Clipping Mask?


Also die Musterung soll tiled sein..

Zur 2. Frage hab ich leider keine Antwort, weil ich keine Ahnung hab wie man in OpenGL Polygone zeichnet :?:

Ich hab bisher nur Vierecke hinbekommen :oops:

Aber schon mal schön zu hören, dass es mit OpenGL funktioniert :)


BenBE - Mo 11.07.05 17:02

Clipping Mask: Heißt, dass alles was vom Polygon auf dem Bildschirm zu sehen ist hat die Musterung. Da wo das Polygon nicht ist fängt die Musterung zwar schon an, aber wird nicht gezeichnet.

hmmm. Bei Tiled muss ich leider die Experten ran lassen.


Passi077 - Mo 11.07.05 17:07

K Thx,

naja dann is wohl nicht clipped Performanceschonender..

aber das ist grad mal nicht ganz so wichtig, ich könnte schon viel weitermachen, wenn ich wüsste wie ich aus den mir gegebenen Punkten (Array of TPoint) ein Polygon in OpenGL zeichnen kann, 2D? Textur ist vorerst nicht ganz so wichtig..

Hab vorhin mal Google bemüht, aber irgendwie finde ich da kaum was was mir hilft, weil die Kombination "OpenGL" und "Polygon" blöderweise ziemlich oft vorkommt...


BenBE - Mo 11.07.05 17:21


Delphi-Quelltext
1:
2:
3:
glBegin(GL_POLYGON);
glVertex2f(x,y); //für jeden Punkt)
glEnd;


Passi077 - Mo 11.07.05 20:00

Danke nochmal, funktioniert wunderbar :) !

Wenn mir nun hoffentlich noch jemand sagen kann, wie ich da ne Textur gekachelt drauflegen kann, wär's super !


F34r0fTh3D4rk - Mo 11.07.05 20:01

hast du denn schon ne textur drauf ?


Passi077 - Mo 11.07.05 20:14

Ne, meine Versuche dazu sind kläglich gescheitert :roll:


Passi077 - Mo 11.07.05 20:37

Mhh Noch was:

Ich hab mir gerade mal einen Editor für Polygone gemacht der die Koordinaten dann in eine Datei speichert, die das andere Programm dann ausliest und anhand derer das Polygon zeichnet.

Leider ist da eine extreme Ungenauigkeit zu erkennen, wenn sich mehrere Y-Werte Überlagern. Um das mal zu veranschaulichen, hier 2 Bilder, das erste aus dem Editor, das 2. ist das gezeichnete Polygon:

http://www.chris-tec.net/POL.jpg
http://www.chris-tec.net/POL2.jpg

Woran liegt das und vor allem, wie kann ich das ändern?

Der Code zum Zeichnen des Polygons ist folgender:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
glBegin(GL_POLYGON);

  for i := 0 to high(coords)-1 do
  begin

    glVertex2f(coords[i].X, coords[i].y); //für jeden Punkt)

  end;

glEnd;


Coords ist das Array of TPoint in dem folgende Werte drinstehen (jeweils erst X, dann Y):

109,245
93,231
75,208
74,191
77,172
99,139
111,131
144,118
184,117
228,131
243,155
245,175
238,195
232,203
224,220
232,231
247,236
256,234
278,216
284,193
289,167
288,140
286,124
287,106
293,96
304,89
330,90
362,102
369,122
371,159
369,183
361,211
350,230
333,253
323,266
298,298
283,308
256,326
239,330

Danke und Grüße
Passi

Moderiert von user profile iconraziel: Code- durch Delphi-Tags ersetzt.


Alstar - Mo 11.07.05 20:39

WOOOOOOW :shock:

Würde es dir was ausmachen deinen Post zu editieren und entwder Zeilenumbrüche oder Leerzeichen einzufügen, weil so wird der Post recht breit ...

Alstar

//EDIT: Zu spät gepostet ... :oops:


delfiphan - Mo 11.07.05 21:14

OpenGl zeichnet mit GL_POLYGON nur konvexe Polygone. Es funktioniert teils auch für nicht-konvexe Polygone (deswegen kommt's halbwegs richtig; aber nur halbwegs), du kannst aber nicht Gift draufnehmen, dass es klappen wird. Willst du sicher gehen, dass es klappt, musst du das Polygon zuerst "tesselieren" (siehe gluTessBeginPolygon, u.a.). Auch aus Performancegründen macht es Sinn, das Polygon zuerst in Dreiecke aufzuteilen.
(Ein konvexes Polygon ist ein Polygon ohne "Einbuchtungen". D.h. wenn du eine gespannte Schnur drumherum wickelst berührt diese den ganzen Rand)


Passi077 - Mo 11.07.05 21:35

Puh das Ganze wird so langsam doch recht kompliziert ^^

Also, erst mal: hab ich das richtig verstanden, dass ich nun statt dem bisherigen Code einfach folgenden nehmen könnte:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
gluTessBeginPolygon(tobj, NULL);
  gluTessBeginContour(tobj);

  for i := 0 to high(coords)-1 do  
  begin  

    gluTessVertex(tobj, coords[i].X, coords[i].y);

  end;

  gluTessEndContour(tobj);
gluTessEndPolygon(tobj);


? Wenn ja, hab ich nur ein Problem mit dem tobj bzw mit


Delphi-Quelltext
1:
function gluNewTess : PGLUtesselator;                    


Das ist ja anscheinend wieder so ein seltsamer Pointer ^^ mit dem ich nix anfangen kann.. ausserdem weiß ich nicht wie ich mein Polygon da reinladen kann, weil das braucht man ja anscheinend nur für die Tesselierung und kann es danach wieder aus diesem Pointer rauswerfen.. ?


delfiphan - Mo 11.07.05 21:42

Ne, so einfach geht das nicht. Du musst mit der Aktion eine glNewList erzeugen: Mit glNewList startest du quasi eine "Aufzeichnung". In einer Schleife führst du dann gluTessVertex aus (Parameter => Eckpunkte des Polygons). Wenn du damit fertig bist werden eine Reihe von Befehlen mit glBegin/glEnd/glVertex3fv (damit das klappt musst du einige Callbacks definieren). Diese Befehle werden dann durch die Callbacks in die Display-List geschrieben. Zum Zeichnen des Polygons führst du dann einfach die Displayliste per glCallList aus.


Passi077 - Mi 13.07.05 10:47

Hi nochmal

erst mal Danke :)!

Aber ich krieg es einfach nicht hin, liegt wahrscheinlich daran, dass ich jetzt eben kaum Zeit hatte um mich in OepnGL einzuarbeiten.

Ich versteh einfach leider nicht, wie das funktioniert.

Also mein Versuch ist blöderweise schon am ersten Schritt gescheitert ^^


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
 
      tess := gluNewTess();

      // Callbacks festlegen 
      gluTessCallback (tess, GLU_TESS_BEGIN, tcbBegin);   // <- alles undefiniert, was muss tcbBegin etc. sein?
      gluTessCallback (tess, GLU_TESS_VERTEX, tcbVertex);
      gluTessCallback (tess, GLU_TESS_END, tcbEnd);


Dann muss ich anscheinend die Daten des Polygons senden, worauf dann die Tesselierung stattfindet, und dann kann ich das Polygon über die Callbacks zeichnen.

So. Jetzt frag ich echt etwas, was ich normal nie fragen würde ^^, aber könnte mir jemand einfach den kompletten Code für ein konkaves Polygon in OpenGL geben? Wie gesagt, normal guck ich schon das ich das alles selber hinkriege, aber in diesem Fall ist es besonders wegen dem zeitdruck blöd, da das Projekt bis Freitag fertig sein muss.

Es wäre soweit fast alles fertig, wenn ich ne einfache Procedure zum Zeichnen der Polygone hätte...

Ich hoffe es erbarmt sich jemand, sonst müsste mein Game mit hässlichen konvexen Polygonen auskommen :(

Grüße
Passi

Moderiert von user profile iconraziel: Code- durch Delphi-Tags ersetzt.


delfiphan - Mi 13.07.05 17:23


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
const
 N = 100;
var
 GLArrayd3: TGLArrayd3;
 GluObj: PGLUtesselator;
 myPolygon: TGLUInt;
 myPointList: array of TGLArrayf3;
 I: Integer;
begin
  // Definition eines nicht-konvexen Objektes
  SetLength(myPointList, N);
  for I := 0 to N-1 do
  begin
    myPointList[I][0] := cos(2*pi*I/N)*(1+cos(2*pi*I/N*8)/4);
    myPointList[I][1] := sin(2*pi*I/N)*(1+cos(2*pi*I/N*8)/4);
    myPointList[I][2] := 0;
  end;

  // Display-List erstellen
  myPolygon := glGenLists(1); 
  glNewList(myPolygon, GL_COMPILE);

  // Tesselierung in konkave Polygone
  GluObj := gluNewTess;
  gluTessCallback(GluObj, GLU_TESS_VERTEX, @glVertex3fv);
  gluTessCallback(GluObj, GLU_TESS_BEGIN, @glBegin);
  gluTessCallback(GluObj, GLU_TESS_END, @glEnd);

  gluTessBeginPolygon(GluObj, nil);
  gluTessBeginContour(GluObj);
  for I := 0 to length(myPointList)-1 do
  begin
    GLArrayd3[0] := myPointList[I][0];
    GLArrayd3[1] := myPointList[I][1];
    GLArrayd3[2] := myPointList[I][2];
    gluTessVertex(GluObj, GLArrayd3, @myPointList[I]);
  end;
  gluTessEndContour(GluObj);
  gluTessEndPolygon(GluObj);
  glEndList;
  gluDeleteTess(GluObj);

  // Das Objekt zeichnen...
  glCallList(myPolygon);


Passi077 - Do 14.07.05 15:41

Hi,

vielen vielen Dank für den Code :) !!

Funktioniert wunderbar.. aber ist das normal, dass da wahnsinnig viel Leistung gebraucht wird?

Mein Game läuft ohne die Polygone mit 600 FPS, aber wenn ich nur 3 Polygone mit je etwa 20 Koordinaten zeichnen lasse, fällt die Framerate auf nur noch knapp 200 FPS ab.. :?:

Und dann noch die Sache mit der Textur.. ich hab mit glvertex3f rumprobiert aber ich krieg immer nur den ersten Pixel der Textur der auf das komplette Polygon gezeichnet wird.. ?


Und nochmal Danke euch allen, find ich super das ihr mir so helf :) !


BenBE - Do 14.07.05 17:21

Für eine Textur musst Du 4 Koordinaten angeben (glTexCoord).


delfiphan - Do 14.07.05 21:31

Die Tesselierung führst du natürlich nur einmal durch (in der Initialisierungsphase). Nach der Tesselierung brauchst du dann nur noch den letzten Befehl, um das Objekt zeichnen zu lassen. Das sollte relativ schnell gehn.


Passi077 - Sa 16.07.05 11:06

Hi,

ah jo mit Tesselierung nur einmal geht's wunderbar schnell :).. Danke!


Aber ist das irgendwie begrenzt von der Anzahl der Koordinaten her? Wenn ich mehr als etwa 25 Koordinaten für ein Polygon angebe, wird das und ein paar andere Polygone die vorher noch funktionierten gar nicht mehr gezeichnet..

Und mit der Textur.. so wie ich das verstanden hab muss ich für die 4 Punkte ja glTexCoord2f nehmen.


Quelltext
1:
2:
3:
4:
 glTexCoord2f(0,0);
 glTexCoord2f(1,0);
 glTexCoord2f(1,1);
 glTexCoord2f(0,1);


Funktioniert aber leider nicht, auch wenn ich da Pixelangaben reinschreibe..

Grüße
Passi


PS: Wurde glücklicherweise bis Montag verlängert, die Projektarbeit..


delfiphan - Sa 16.07.05 20:02

Möglicherweise musst du die Punkte im Uhrzeigersinn angeben, oder im Gegenuhrzeigersinn. Siehe Dokumentation. Vielleicht kreuzen sich bei dir auch irgendwelche Linien.


Passi077 - Sa 16.07.05 20:26

Hm ich habe gerade eben bemerkt, dass das Problem wohl woanders liegt:

Ich hab ein 2dimensionales dynamisches Array.. da setze ich die Länge z.b. auf


Delphi-Quelltext
1:
SetLength(Polygons,10,20);                    


.. ich kann aber dann trotzdem ohne Fehler auf Polygon[5, 250] zugreifen - und da stehen dann verrückte Werte drin (z.B. 290349121)!

Was kann man dagegen tun oder wie setze ich die Länge eines mehrdimensionalen Feldes richtig?


Passi077 - Sa 16.07.05 21:28

Ok das hat sich erledigt mit den Polygonen...


Alles was ich jetzt noch brauche ist ne gekachelte Textur da drauf! Könnt ihr mir da bitte bitte noch helfen?

Wie schon oben beschrieben hat das mit den 4 Punkten nicht geklappt :(