Programowanie w języku Delphi » Gotowce

Wykorzystanie obiektów z 3dsMax i Solid Works w OpenGL

Wykorzystanie obiektów z 3dsMax i Solid Works w OpenGl

<justify>
    Jest to mój pierwszy artykuł na forum 4programmers i mam nadzieję, że nie ostatni. Będzie on dotyczył wykorzystania złożonych modeli 3d w aplikacji korzystającej z biblioteki OpenGl.
    Wiadomo, że ręczne modelowanie (mam tu na myśli składanie trójkątów) jest bardzo trudne i czasochłonne. Jeżeli chce się być wydajnym grafikiem ? programistą należy używać specjalnych programów przeznaczonych do modelowania obiektów przestrzennych. Większość programów ma możliwość zapisu projektu do pliku tekstowego. Różnice jednak w sposobie zapisu są tak duże, że nie ma możliwości pogodzenia owej metody. Jest jednak obejście tego problemu, a mianowicie pliki StereoLith (*.stl). Są one nazwijmy ?znormalizowane, tak więc nie ma znaczenia który program je wygenerował. Owe pliki mogą występować w postaci binarnej i tekstowej. Dalsze rozważania tyczyć się będą plików w postaci tekstu, tak więc należy podczas zapisu zaznaczyć opcję ASCII. W plikach stl obiekty są opisywane za pomocą płaszczyzn, trójkątów i wierzchołków. Oto przykładowy plik stl opisujący prostopadłościan (aby nie zaciemniać podaję tylko fragment):
</justify>

solid Part1    
   facet normal -1.000000e+000 0.000000e+000 0.000000e+000
      outer loop
         vertex 0.000000e+000 0.000000e+000 5.000000e+001
         vertex 0.000000e+000 7.402906e+001 5.000000e+001
         vertex 0.000000e+000 0.000000e+000 0.000000e+000
      endloop
   endfacet
   facet normal -1.000000e+000 0.000000e+000 0.000000e+000
      outer loop
         vertex 0.000000e+000 0.000000e+000 0.000000e+000
         vertex 0.000000e+000 7.402906e+001 5.000000e+001
         vertex 0.000000e+000 7.402906e+001 0.000000e+000
      endloop
   endfacet
endsolid


<justify>
    Aby możliwe było wykorzystanie owego pliku w aplikacji delphi należy dokonać jego przekształcenia na właściwy format OpnGl?a czyli:</justify>
    ?        Faced normal na glNormal3f()
    ?          Vertex na glVertex3f()
<justify>
Zadanie nie jest trudne do zrealizowania. Poniżej zamieszczam kod programu do konwersji pliku *.stl na plik *.inc, którego efekt działania widać ponizej:
</justify>

glNormal3f( -1.000000e+000,0.000000e+000,0.000000e+000 );
  glVertex3f( 0.000000e+000,0.000000e+000,5.000000e+001 );
  glVertex3f( 0.000000e+000,7.402906e+001,5.000000e+001 );
  glVertex3f( 0.000000e+000,0.000000e+000,0.000000e+000 );
glNormal3f( -1.000000e+000,0.000000e+000,0.000000e+000 );
  glVertex3f( 0.000000e+000,0.000000e+000,0.000000e+000 );
  glVertex3f( 0.000000e+000,7.402906e+001,5.000000e+001 );
  glVertex3f( 0.000000e+000,7.402906e+001,0.000000e+000 );


Oto kod programu (dla czytelności napisany jako aplikacja konsolowa):
program Stl2Inc;
 
{$APPTYPE CONSOLE}
 
uses
  SysUtils;
 
var
 IncFile, StlFile :TextFile;
 IncLine, StlLine :string;
 IncName, StlName :string;
 i, n             :Byte;
 
begin
 if ParamCount = 0 then
    begin
     WriteLn('Złe argumenty');
     WriteLn('STLCONV.EXE plik.stl');
     WriteLn('Naciśnij Enter...');
     ReadLn;
     Halt(1);
    end; // if ParamCount
 StlName := ParamStr(1);
 IncName := Copy(StlName, 1, (Length(StlName)-3))+'inc';
 
 AssignFile(StlFile, StlName);
 Reset(StlFile);
 
 AssignFile(IncFile, IncName);
 Rewrite(IncFile);
 
 while not Eof(StlFile) do
  begin
   ReadLn(StlFile, StlLine);
   n := 1;
   while ((StlLine[n] <> 'v') and (n <= Length(StlLine)-2)) do Inc(n);
   if StlLine[n] = 'v' then
      begin
       IncLine := Copy(StlLine, n+6, Length(StlLine)-n);
       for i := 2 to Length(IncLine)-2 do
        if IncLine[i] = ' ' then IncLine[i] := ',';
       IncLine := '   glVertex3f(' + IncLine + ');';
       WriteLn(IncFile, IncLine);
      end; // if StlLine
 
   n := 1;
   while ((StlLine[n] <> 'n') and (n <= Length(StlLine)-2)) do Inc(n);
   if Copy(StlLine, n, 6) = 'normal' then
      begin
       IncLine := Copy(StlLine, n+6, Length(StlLine)-n);
       for i := 2 to Length(IncLine)-2 do
        if IncLine[i] = '' then IncLine := ',';
        IncLine := ' glNormal3f(' + IncLine + ');';
        WriteLn(IncFile, IncLine);
      end; // if Copy(...
  end; //while not Eof
  CloseFile(StlFile);
  CloseFile(IncFile);
end.


Gdy już mamy przekształcony plik nie pozostaje nam nic innego jak umieścić go w kodzie procedury rysującej w klamrze:
glBegin(GL_TRIANGLES);
  {$I PLIK.INC}
glEnd();

Oto cała metoda na uproszczenie sobie życia podczas pisania aplikacji w OpenGl. Ode mnie już wszystko. Mam nadzieję, że komuś się przyda. Jeżeli coś zostało przeoczone to przepraszam i proszę o dopisanie.

5 komentarzy

Pociech 2009-09-26 01:40

Ten kod "zapomina" wstawiać przecinki w linijkach glNormal3f... Zamiast:

if IncLine[i] = '' then IncLine := ',';

powinno być

if IncLine[i] = ' ' then IncLine[i] := ',';

Marooned 2006-07-21 23:55

Nie slyszalem o plikach .stl natomiast standardem wymiany informacji o obiektach 3D sa pliki .<wiki>dxf</wiki> opracowane przez AutoDesk.

AklimX 2006-07-21 20:03

@Oleksy_Adam: nie chodzi mi o wersję dla C. Edytory mają coś takiego jak eksport do pliku *.c - wygląda to tak, że masz tablice vertices, normals, texturecoord, itd. Np. Anim8or ma coś takiego, zassij to zobaczysz.

Oleksy_Adam 2006-07-21 12:47

Wstępnie nawet nie pomyślałem o generowaniu obiektu do pliku *.c. Oczywiście, że popracuję nad wersją dla C.

AklimX 2006-07-21 11:38

a co z plikami Wavefront(*.obj)? albo *.vtx albo generowaniem do pliku źródłowego (*.c)