Przyspieszenie procedury

Odpowiedz Nowy wątek
2006-12-15 09:39
kochzg
0

Mam taki problem.
Mam dane obiektu (kształt) który składa się z kilku tysięcy sześcianów. Oczywiście dla każdego szescianu znam numerację węzłów oraz dla każdego węzła posiadam współrzędne.
Gdzie w procedurze użyto zmienne:
numTriangles - ilość sześcianów
Triangles - numery poszczególnych węzłow kolejnego szescianu

Korzystając z biblioteki OpenGL wyświetlam cały obiekt poprzez generowanie tych kilku tysięcy sześcianów. Jednak trochę czasu to zajmuje. Więc pomysłałem aby wyświetlać tylko zewnętrzna powierzchnię. Napisałem procedure która znajduje która ściana każdego sześcianu jest tą zewnętrzną, poprzez sprawdzanie każdej ścianki danego szęscianu (cztery wspólne wierzchołki) z pozostałymi ściankami sześcianów. Jednak długo to trwa (około 25s). Zorientowałem się ze głównie przyczyną jest instrukcja sprawdzająca if. Więc potrzebuję jakiego nowego genalnego pomysłu na rozwiązanie tego problemu, bowiem chyba się sam zapętliłem.

procedure TForm1.Rys_Volume_Vertex;
var
i,j,k:integer;
a1,a2,a3,a4,a5,a6,a7,a8:integer;

begin
k:=0;
 for i:=0 to numTriangles-1 do
   begin
//przypisanie kolejnych wierzchołków do sprawdzania
            a1:=Triangles[i].v1;
            a2:=Triangles[i].v2;
            a3:=Triangles[i].v3;
            a4:=Triangles[i].v4;
            a5:=Triangles[i].v5;
            a6:=Triangles[i].v6;
            a7:=Triangles[i].v7;
            a8:=Triangles[i].v8;
  for j:=0 to numTriangles-1 do
    begin
      if j<>i then //nie sprawdzaj tego samego sześcianu
         begin
     //prawy
            if (a2=Triangles[j].v1) and (a3=Triangles[j].v4) and (a6=Triangles[j].v5) and (a7=Triangles[j].v8) then begin Edges[i,0]:=j; k:=k+1; end;
    //góra
              if (a5=Triangles[j].v1) and (a6=Triangles[j].v2) and (a7=Triangles[j].v3) and (a8=Triangles[j].v4) then begin Edges[i,1]:=j; k:=k+1; end;
   //dol
              if (a1=Triangles[j].v5) and (a2=Triangles[j].v6) and (a3=Triangles[j].v7) and (a4=Triangles[j].v8) then begin Edges[i,2]:=j; k:=k+1; end;
     //lewy
              if (a1=Triangles[j].v2) and (a5=Triangles[j].v6) and (a8=Triangles[j].v7) and (a4=Triangles[j].v3) then begin Edges[i,3]:=j; k:=k+1; end;
     //front
              if (a1=Triangles[j].v4) and (a2=Triangles[j].v3) and (a6=Triangles[j].v7) and (a5=Triangles[j].v8) then  begin Edges[i,4]:=j; k:=k+1; end;
    //back
              if (a4=Triangles[j].v1) and (a3=Triangles[j].v2) and (a7=Triangles[j].v6) and (a8=Triangles[j].v5) then begin Edges[i,5]:=j; k:=k+1; end;

            if k>=6 then break; 
         end; //if
    end;//j
  k:=0;
end;//i

end;

Jeszcze kilka wyjaśnień:
Jezeli znajdzie cztery takie same numeracje wierzchołków to zapisuje do tabliczy Edges[] numer sześcianu z którym ta ścianka się kontaktuje. Dodatkowo jezeli znajdzie ściankę to zwieksza wartość k. Jezeli wszystkie ścianki danego sześcianu mają kontakt czyli k=6 to nie ma sensu dalej sprawdzania i wyjście z petli poprzez break.
Jezeli ktos bedzie chciał przetestować swój pomysł mogę podesłąć plik z danymi.

Zdrówka
Kochgz

Pozostało 580 znaków

2006-12-15 12:59
0

pokaz mi ten kod. Bo to co tam masz to twoja abstrakcja i z niej troche trudno w ogole ci cos pomoc
bo ta funkcja nie powinna byc az tak mocozerna [teraz dodalem - jednak jest za duzo obiektow :} ]w ogole po co ci sprawdzanie jakis takich samych wierzcholkow.
Aha i jeszcze jedno: istnieja jeszcze dwie mozliwosci narysowania tylko tych co widac, jedna to ustawienie dla kazdej sciany wektora normalnego i wlaczenie GLenable(GL_CULL_FACE); glcullface(GL_FRONT lub GL_BACK itp.);

lub testowanie tego tez podobnie za pomoca funkcji:

const
SPECIAL_FEAUTRE = 0.0001;       //wtf ;u
isOnPlane       = 0;
isFront         = 1;
isBack          = -1;

type t3dpoint = record
x : single;
y : single;
z : single;
end;

function dotproduct(v1, v2 : t3dpoint) : single; overload;
begin
Result := (v1.x*v2.x)+(v1.y*v2.y)+(v1.z*v2.z);
end;

function greater(a,b:single):single;
begin
if a =b then exit;
  if a>b then result:=a else result:=b;
end;

function smaller(a,b:single):single;
begin
if a =b then exit;
  if a>b then result:=b else result:=a;
end;

function betweenorequal(x1,x2,x0                                               : single)       : boolean;
begin
result := false;
if smaller(x1,x2) <= x0 then
if greater(x1,x2) >= x0 then result := true else result := false;
end;

function classifyapointagainstaplane(point, normal : t3dpoint; distance : single)
: integer;
//using vn o vx+d=0
var
costam : single;
begin
costam := dotproduct(point,normal)+distance;
if costam > 0 then result := isFront;
if costam < 0 then result := isBack; 
if betweenorequal(-SPECIAL_FEAUTRE,SPECIAL_FEAUTRE,costam) = true then result := isOnPlane;
end;

uzywa sie do tego funkcji classifyapointagainstaplane ktora zwraca czy jestesmy przed czy za sciana

Pozostało 580 znaków

2006-12-15 13:26
kochzg
0

Nie wiem czy wstawianie całego kodu ma sens, bowiem jest trochę długi. Oprócz tej procedury są jeszcze inne, które robią rożne rzeczy, np wyznaczaja iso-powierzchnie, przekroje, itp. Po prostu tworze aplikację do wizualizacji obiektów stworzonych za pomocą sześcianów lub czterościanów. Krótko mówiąc aplikacja prezentująca wyniki obliczeń MES. A co do komendy glcullface to musze zaprotestować. Co z tego ze nie wyswietla tych powierzchni co nie widać. Jak spojrzymy na sześcian w rzucie perspektywistyczny to widać przynajmniej 3 ścianki. A ja na przykład chce widzieć tylko jedną, tą która jest na zewnątrz obiektu. Zaś pozostałe mnie nie interesują.

Kochzg

Pozostało 580 znaków

2006-12-15 13:39
Kochzg
0

Zapomniałem dodać jedna uwagę;

Piszesz, ze " ta funkcja nie powinna byc az tak mocozerna", zrób prosty test. Wstaw dwie petlę na 24000 razy kazda. I uruchom. Bedzie trwała krótko. Następnie w srodkowej pętli wstaw byle jakich 6 warunków if. Czas ci zwiększy sie do kilku sekund. Dlaczego tak się dzieje, bowiem komenda if jest bardzo wolna komendą.

Pozostało 580 znaków

2006-12-15 13:44
0

czyli jak ty chcesz narysowac te kilka tys szescianow? jak to ma wygladac i jak ta bryla wyglada cala

Pozostało 580 znaków

2006-12-15 14:10
kochzg
0

Zobacz.
Pierwszy rysunek jest wykonany za pomoca mojej aplikacji. Rysowane są wszystkie sześciany.
http://republika.pl/kochzg/pict_1.jpg

Drugi rysunek wykonuje to samo aplikacja profesjonalna:
http://republika.pl/kochzg/pict_2.jpg

Inny przykład z przezroczystościa:
http://republika.pl/kochzg/pict_3.jpg - moja aplikacja
http://republika.pl/kochzg/pict_4.jpg - prof

I tutaj jest pies pogrzebany. Bowiem aplikacja profesjonalna wyswietla tylko zewnętrzne powierzchnie zas moja wszystkie.

Pozostało 580 znaków

2006-12-15 14:46
kochzg
0

A może "Drzewa BST" [wstyd]

Pozostało 580 znaków

2006-12-16 07:36
0

a w jaki sposob rysujesz ten obiekt>?

Pozostało 580 znaków

2006-12-18 09:03
kochzg
0

Poniżej umieszczam procedure rysującą ten obiekt (każdy sześcian):

procedure TForm1.DrawMesh;
var
i:integer;
begin

for i:=0 to numTriangles-1 do
begin
 glBegin(GL_QUADS);
 glColor4f(0.5, 0.8, 0.8, ScrollBar11.Position/10);

    glNormal3d(0.0, 0.0, -1.0);
    glVertex3f(Nodes[Triangles[i].v1].X ,Nodes[Triangles[i].v1].Y,Nodes[Triangles[i].v1].Z);
    glVertex3f(Nodes[Triangles[i].v2].X ,Nodes[Triangles[i].v2].Y,Nodes[Triangles[i].v2].Z);
    glVertex3f(Nodes[Triangles[i].v3].X ,Nodes[Triangles[i].v3].Y,Nodes[Triangles[i].v3].Z);
    glVertex3f(Nodes[Triangles[i].v4].X ,Nodes[Triangles[i].v4].Y,Nodes[Triangles[i].v4].Z);

    glNormal3d(0.0, -1.0, 0.0);
    glVertex3f(Nodes[Triangles[i].v1].X ,Nodes[Triangles[i].v1].Y,Nodes[Triangles[i].v1].Z);
    glVertex3f(Nodes[Triangles[i].v2].X ,Nodes[Triangles[i].v2].Y,Nodes[Triangles[i].v2].Z);
    glVertex3f(Nodes[Triangles[i].v6].X ,Nodes[Triangles[i].v6].Y,Nodes[Triangles[i].v6].Z);
    glVertex3f(Nodes[Triangles[i].v5].X ,Nodes[Triangles[i].v5].Y,Nodes[Triangles[i].v5].Z);

    glNormal3d(0.0, 0.0, 1.0);
    glVertex3f(Nodes[Triangles[i].v5].X ,Nodes[Triangles[i].v5].Y,Nodes[Triangles[i].v5].Z);
    glVertex3f(Nodes[Triangles[i].v6].X ,Nodes[Triangles[i].v6].Y,Nodes[Triangles[i].v6].Z);
    glVertex3f(Nodes[Triangles[i].v7].X ,Nodes[Triangles[i].v7].Y,Nodes[Triangles[i].v7].Z);
    glVertex3f(Nodes[Triangles[i].v8].X ,Nodes[Triangles[i].v8].Y,Nodes[Triangles[i].v8].Z);

    glNormal3d(0.0, 1.0, 0.0);
    glVertex3f(Nodes[Triangles[i].v8].X ,Nodes[Triangles[i].v8].Y,Nodes[Triangles[i].v8].Z);
    glVertex3f(Nodes[Triangles[i].v7].X ,Nodes[Triangles[i].v7].Y,Nodes[Triangles[i].v7].Z);
    glVertex3f(Nodes[Triangles[i].v3].X ,Nodes[Triangles[i].v3].Y,Nodes[Triangles[i].v3].Z);
    glVertex3f(Nodes[Triangles[i].v4].X ,Nodes[Triangles[i].v4].Y,Nodes[Triangles[i].v4].Z);

    glNormal3d(1.0, 0.0, 0.0);
    glVertex3f(Nodes[Triangles[i].v1].X ,Nodes[Triangles[i].v1].Y,Nodes[Triangles[i].v1].Z);
    glVertex3f(Nodes[Triangles[i].v5].X ,Nodes[Triangles[i].v5].Y,Nodes[Triangles[i].v5].Z);
    glVertex3f(Nodes[Triangles[i].v8].X ,Nodes[Triangles[i].v8].Y,Nodes[Triangles[i].v8].Z);
    glVertex3f(Nodes[Triangles[i].v4].X ,Nodes[Triangles[i].v4].Y,Nodes[Triangles[i].v4].Z);

    glNormal3d(-1.0, 0.0, 0.0);
    glVertex3f(Nodes[Triangles[i].v2].X ,Nodes[Triangles[i].v2].Y,Nodes[Triangles[i].v2].Z);
    glVertex3f(Nodes[Triangles[i].v6].X ,Nodes[Triangles[i].v6].Y,Nodes[Triangles[i].v6].Z);
    glVertex3f(Nodes[Triangles[i].v7].X ,Nodes[Triangles[i].v7].Y,Nodes[Triangles[i].v7].Z);
    glVertex3f(Nodes[Triangles[i].v3].X ,Nodes[Triangles[i].v3].Y,Nodes[Triangles[i].v3].Z);
 glEnd();
end;

end;

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0