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

Oleksy_Adam

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>

<font name="Courier New">
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 </span>

<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

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

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

powinno być

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

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

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

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