Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Fr Jul 04, 2025 11:05

Foren-Übersicht » Programmierung » Mathematik-Forum
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 10 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: Schnelle Vertexnormalen
BeitragVerfasst: Do Mär 20, 2008 11:03 
Offline
DGL Member

Registriert: Di Mai 24, 2005 16:43
Beiträge: 710
hi ;)

Ich habe ein Raster, ein array der größe n*n, sprich: 0..n-1, 0..n-1
Diese beinhaltet Vertexkoordinaten, diese werden als einzelne Dreiecke gezeichnet. (Hier wäre zum Beispiel schon eine Optimierung mit LineStrip möglich)
Jetzt möchte ich die Normalen pro Vertex statt pro Fläche berechnen. Ich habe es versucht, in dem ich die benachbarten Dreiecke auf gemeinsame Punkte untersuche.
Das hat soweit auch funktioniert, nur passiert dies durch die Doppelbelegung bis zu 6 mal pro Vertex. Außerdem finde ich diese Bruteforce Variante nicht gerade elegant.
bei n=50, sprich 50*50*2 = 5000 dreiecken also 3*5000 = 15000 vertices braucht das Teil ganz schon lange ;)
Deshalb möchte ich nun zunächst einmal auf LINE_STRIP umsteigen und brauche dann gleich eine Funktion dir mir möglichst schnell die anliegenden Flächennormalen liefert. (diese müssen dann halt vorher gescheit berechnet und gespeichert werden)

Momentan ist das ganze sehr unschön (noch ohne Glättung)

Code:
  1.     for i := 0 to n-2 do
  2.       for j := 0 to n-2 do
  3.       begin
  4.         triangle[0] := particles[i, j+1].new;
  5.         triangle[1] := particles[i+1, j].new;
  6.         triangle[2] := particles[i,j].new;
  7.         normal := v3f_normalize(v3f_crossproduct(v3f_sub(triangle[1], triangle[0]), v3f_sub(triangle[2], triangle[0])));
  8.         glNormal3f(normal.x, normal.y, normal.z);
  9.         glBegin(GL_TRIANGLES);
  10.           glVertex3f(triangle[0].x, triangle[0].y, triangle[0].z);
  11.           glVertex3f(triangle[1].x, triangle[1].y, triangle[1].z);
  12.           glVertex3f(triangle[2].x, triangle[2].y, triangle[2].z);
  13.         glEnd;
  14.         triangle[0] := particles[i, j+1].new;
  15.         triangle[1] := particles[i+1, j+1].new;
  16.         triangle[2] := particles[i+1,j].new;
  17.         normal := v3f_normalize(v3f_crossproduct(v3f_sub(triangle[1], triangle[0]), v3f_sub(triangle[2], triangle[0])));
  18.         glNormal3f(normal.x, normal.y, normal.z);
  19.         glBegin(GL_TRIANGLES);
  20.           glVertex3f(triangle[0].x, triangle[0].y, triangle[0].z);
  21.           glVertex3f(triangle[1].x, triangle[1].y, triangle[1].z);
  22.           glVertex3f(triangle[2].x, triangle[2].y, triangle[2].z);
  23.         glEnd;
  24.       end;


Wie stelle ich das nun am besten an ?
Was ich so über die SUFU gefunden hab, entspricht mehr oder minder dem was ich vorher probiert habe.

mfg


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Mär 20, 2008 11:41 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Aug 18, 2007 18:47
Beiträge: 694
Wohnort: Köln
Programmiersprache: Java
IMHO kannst du schonmal glBegin und glEnd ausserhalb der Schleife platzieren. Sind schonmal 2397 Aufrufe weniger (bei n=50).

ich tippe mal darauf, dass du eine landschaft zeichnen willst? bzw: wozu vertexnormalen wenn du Linien zeichnest?

hast du mal ein bild davon?

[edit]wieso suchst du den nachbarn? liegen die koordinaten nicht nebeneinander? dann wird auch das zeichnen als STRIP nicht so richtig funktionieren. IMHO[/edit]

_________________
Es werde Licht.
glEnable(GL_LIGHTING);
Und es ward Licht.


Zitat aus einem Java Buch: "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off"

on error goto next


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Mär 20, 2008 11:53 
Offline
DGL Member

Registriert: Di Mai 24, 2005 16:43
Beiträge: 710
hi, mir ist leider ein Schreibfehler passiert, ich meinte TRIANGLE_STRIP ;)
Ich kann ja erstmal den Code auf TRIANGLE_STRIP umschreiben, beim letzten Versuch sah das allerdings nicht so ganz richtig aus.

EDIT:

das wäre die TRIANGLE_STRIP Variante:

Code:
  1.     for i := 0 to n-2 do
  2.     begin
  3.       glBegin(GL_TRIANGLE_STRIP);
  4.       for j := 0 to n-2 do
  5.       begin
  6.         triangle[0] := particles[i, j+1].new;
  7.         triangle[1] := particles[i+1, j].new;
  8.         triangle[2] := particles[i,j].new;
  9.         normal := v3f_normalize(v3f_crossproduct(v3f_sub(triangle[1], triangle[0]), v3f_sub(triangle[2], triangle[0])));
  10.         glNormal3f(normal.x, normal.y, normal.z);
  11.         glVertex3f(triangle[1].x, triangle[1].y, triangle[1].z);
  12.         glVertex3f(triangle[2].x, triangle[2].y, triangle[2].z);
  13.       end;
  14.       glEnd;
  15.     end;

Die sieht allerdings leicht anders aus, liegt wahrscheinlich daran, dass immer 2 Vertices eine Normale zugewiesen bekommen.
Die einzelnen Reihen wirken dadurch ja schon recht geglättet.

mfg


Zuletzt geändert von Seth am Do Mär 20, 2008 12:46, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Mär 20, 2008 12:41 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Aug 18, 2007 18:47
Beiträge: 694
Wohnort: Köln
Programmiersprache: Java
ich würde wohl die normalen in einem vorbereitenden schritt berechnen und gleich in einem array ablegen, dass man auch ohne weiteres für vertexarrays benutzen könnte.

die normale dabei aus dem normalisierten durchschnitt zwischen den flächennormalen der 4 anliegenden dreiecke bilden (a-d) und in o.g. array speichern.


Dateianhänge:
vertexnormalen.jpg
vertexnormalen.jpg [ 10.68 KiB | 8932-mal betrachtet ]

_________________
Es werde Licht.
glEnable(GL_LIGHTING);
Und es ward Licht.


Zitat aus einem Java Buch: "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off"

on error goto next
Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Mär 20, 2008 12:57 
Offline
DGL Member

Registriert: Di Mai 24, 2005 16:43
Beiträge: 710
hi,

aus deiner skizze wird allerdings schon deutlich dass die 4 anliegenden nicht den 4 vorher berechneten entsprechen.
Man könnte auch mehr nehmen, aber das sieht vielleicht nicht unbedingt gut aus.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Mär 20, 2008 16:47 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Aug 18, 2007 18:47
Beiträge: 694
Wohnort: Köln
Programmiersprache: Java
abgeleitet habe ich das von einem normalgenerator, der aus einer heightmap eine normalmap macht.
da gibt es noch andere methoden um den durchschnitt zu berechnen. 3x3, 5x5, gauss, etc.

4 berechnete?

aus den 4 blauen und der roten vertexkoordinaten wird die normale für die rote koordinate berechnet.

_________________
Es werde Licht.
glEnable(GL_LIGHTING);
Und es ward Licht.


Zitat aus einem Java Buch: "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off"

on error goto next


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Mär 20, 2008 19:13 
Offline
DGL Member

Registriert: Di Mai 24, 2005 16:43
Beiträge: 710
ah, danke jetzt hab ichs ;)

Code:
  1.   function CalculateNormal(i0, j0: integer): TVector3f;
  2.   var
  3.     i, j: integer;
  4.     tr: array[0..4] of TVector3f;
  5.   begin
  6.     tr[0] := particles[i0, j0].new;
  7.     // unten
  8.     tr[1] := particles[i0, j0+1].new;
  9.     // rechts
  10.     tr[2] := particles[i0+1, j0].new;
  11.     // oben
  12.     tr[3] := particles[i0, j0-1].new;
  13.     //links
  14.     tr[4] := particles[i0-1, j0].new;
  15.     result := to_v3f(0, 0, 0);
  16.     for i := 0 to 3 do
  17.     begin
  18.       j := i+1;
  19.       if j > 3 then
  20.         j := 0;
  21.       result := v3f_add(result, v3f_crossproduct(v3f_sub(tr[i+1], tr[0]), v3f_sub(tr[j+1], tr[0])));
  22.      end;
  23.     result := v3f_normalize(v3f_scale(result, 1/4));
  24.   end;


Allerdings gibt es am Rand weiße Stellen, ich denke mal weil auf Array Elemente zugegriffen wird, die nicht existieren (komisch, dass keine AV kommt), wie vermeide ich das am besten ?

mfg


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Mär 20, 2008 22:08 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Aug 18, 2007 18:47
Beiträge: 694
Wohnort: Köln
Programmiersprache: Java
evtl liest er ja irgendeinen müll aus dem speicher. das sollte dann durch einen vector ala (0,1,0) ersetzt werden. also für die betroffenen flächennormalen.

_________________
Es werde Licht.
glEnable(GL_LIGHTING);
Und es ward Licht.


Zitat aus einem Java Buch: "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off"

on error goto next


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Mär 21, 2008 15:56 
Offline
DGL Member

Registriert: Di Mai 24, 2005 16:43
Beiträge: 710
wobei das doch eher die weniger elegante lösung sein dürfte, aber ich hab da ne idee.

mfg


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Mär 21, 2008 16:11 
Offline
DGL Member

Registriert: Di Mai 24, 2005 16:43
Beiträge: 710
So gehts:
Code:
  1. function CalculateNormal(i0, j0: integer): TVector3f;
  2. const
  3.   nMatrix: array[0..4, 0..1] of integer = ((0, 0), (0, 1), (1, 0), (0, -1), (-1, 0));
  4. var
  5.   i, j,
  6.   i1, j1,
  7.   c: integer;
  8.   tr: array[0..4] of TVector3f;
  9.   trb: array[0..3] of boolean;
  10. begin
  11.   for i := 0 to 4 do
  12.   begin
  13.     i1 := i0 + nMatrix[i, 0];
  14.     j1 := j0 + nMatrix[i, 1];
  15.     if (i1 <= (n-1)) and (j1 <= (n-1)) and (i1 >= 0) and (j1 >= 0)  then
  16.     begin
  17.       tr[i] := particles[i1, j1].new;
  18.       if i > 0 then
  19.         trb[i-1] := true;
  20.     end else
  21.       trb[i] := false;
  22.   end;
  23.   result := to_v3f(0, 0, 0);
  24.   c := 0;
  25.   for i := 0 to 3 do
  26.   begin
  27.     j := i+1;
  28.     if j > 3 then
  29.       j := 0;
  30.     if trb[i] then
  31.     begin
  32.       result := v3f_add(result, v3f_crossproduct(v3f_sub(tr[i+1], tr[0]), v3f_sub(tr[j+1], tr[0])));
  33.       inc(c);
  34.     end;
  35.   end;
  36.   if c > 0 then
  37.     result := v3f_normalize(v3f_scale(result, 1/c)) else
  38.       result := to_v3f(0, 0, 0);
  39. end;

Ist vielleicht noch nicht die superelegante Methode, aber es ist schnell genug ;) und sieht recht gut aus.


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 10 Beiträge ] 
Foren-Übersicht » Programmierung » Mathematik-Forum


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 2 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.010s | 16 Queries | GZIP : On ]