OpenGL (7.) - Detekce kolizí, načtení mapy a textury v jpg souboru

Asi jste si už všimli, že tělem i duší žiji v OpenGL. Není to nádhera? Vytvořit aplikaci, poskládat do ní několik trojúhelníků, potáhnout texturou, vypočítat kolize, rotace, posuny a vše, co k tomu patří... dívat se na vytvořený výsledek... a ještě lépe podělit se o výsledek s ostatními...

Pokud jste si nejdříve stáhli zdroják, zjistili jste že jsem v programu mnohé vylepšil. Přidal jsem již zmiňovanou detekci kolizí, možnost načítání jak bmp tak i jpg obrázků, propracoval jsem ovládací panel, možnost změny rozlišení i v průběhu spuštění programu. Mapa je načítána z bmp nebo jpg obrázku podle odstínu šedé, přidal jsem také působení gravitace a možnost skoku (Čím větší výška, tím vyšší rychlost pádu) a několik dalších vylapšení. Vše je samozřejmě renderováno přes glDrawElements.

Detekce kolizí

Pokud jsme mimo mapu, fce načte poslední spravnou hodnotu

  if (x>-1)or(x<-(MapHeight-1)*20+1) then x:=oldx; 
  if (z>-1)or(z<-(MapWidth-1)*20+1) then z:=oldz;

Pokud jsme náhodou vypadli z mapy, ihned ukonči

  if y>20 then application.Terminate;

Načtení pozice kamery:

  kamera.x := -X;                                              
  kamera.y := -(Y+4);
  kamera.z := -Z;

Načtení vrcholů testovaného trojúhelníka

  A := VertexPointer[count][0];  
  B := VertexPointer[count][1]; 
  C := VertexPointer[count][2];

Zjištění vzdáleností bodů trojúhelníka navzájem

  AB:=SQRT(SQR(A.x-B.x)+SQR(A.y-B.y)+SQR(A.z-B.z));
  AC:=SQRT(SQR(A.x-C.x)+SQR(A.y-C.y)+SQR(A.z-C.z));
  BC:=SQRT(SQR(B.x-C.x)+SQR(B.y-C.y)+SQR(B.z-C.z));

Zjištění vzdáleností bodů trojúhelníka a kamery

  Akamera:=SQRT(SQR(A.x-kamera.x)+SQR(A.y-kamera.y)+SQR(A.z-kamera.z));
  Bkamera:=SQRT(SQR(B.x-kamera.x)+SQR(B.y-kamera.y)+SQR(B.z-kamera.z));
  Ckamera:=SQRT(SQR(C.x-kamera.x)+SQR(C.y-kamera.y)+SQR(C.z-kamera.z));

Zjištění velikosti úhlů mezi body trojúhelníka a kamerou

  th[1]:=arccos((-AB*AB + Akamera*Akamera + Bkamera*Bkamera)/(2*Akamera*Bkamera));
  th[2]:=arccos((-AC*AC + Akamera*Akamera + Ckamera*Ckamera)/(2*Akamera*Ckamera));
  th[3]:=arccos((-BC*BC + Bkamera*Bkamera + Ckamera*Ckamera)/(2*Bkamera*Ckamera));

Převedení úhlů na stupně a sečtení těchto úhlů

  th[1]:= th[1]*180/3.14159265;
  th[2]:= th[2]*180/3.14159265;
  th[3]:= th[3]*180/3.14159265;
  theta[count]:=th[1]+th[2]+th[3];

Je-li kamera mazi vrcholy trojuheln9ka (kolize), pak součet uhlů je roven 360

  if theta[count] > 350 then begin
    Y:=Y-0.1;
    kolize:=true;
    gravitace:=0.1;
    JumpDisable:=false;
    end;
  end;

Když nastane kolize, zvýší se y-ová hodnota. Možná tenhle kus zdrojáku vypadá odpudivě, ale věřte mi, že to zase tak hrozné nebude. Vycházíme vlastně z jediné věci: Je-li kolize, nachází se kamera mezi vrcholy A, B, C a součet úhlů alfa, beta a gama mezi kamerou a každými dvěma body trojúhelníka je 360 stupňů. Vím, že existují daleko lepší algoritmy na řešení kolizí, já jsem však jako narazil na tento a ten se mi na první pohled docela zalíbil...

Načtení mapy

Pro každý bod ve scéňě zjistím y-ovou souřadnici podle stupňě šedé v obrázku krajina1b.jpg

procedure TForm1.LoadMap;
var
  i,j:integer;
begin
  LoadTexture('krajina1b.jpg');

  for i:=0 to MapWidth do
    for j:=0 to MapHeight do begin
      body[i,j] := round((buffer[i+1,j+1].red +
               buffer[i+1,j+1].green + buffer[i+1,j+1].blue)/10);
    end;
end;

A z těchto hodnot vypočítám souřadnice trojúhelníků a zároveň nastavím texturové souřadnice.

    VertexPointer[2*(l*MapWidth+k)+2][0].X := 20*k;            //X-ova hodnota bodu
    VertexPointer[2*(l*MapWidth+k)+2][0].Y := body[k,l];       //y-ova hodnota bodu
    VertexPointer[2*(l*MapWidth+k)+2][0].Z := 20*l;            //Z-ova hodnota bodu
    CoordPointer[2*(l*MapWidth+k)+2][0].S := k/MapWidth;      //souradnice textury-S
    CoordPointer[2*(l*MapWidth+k)+2][0].K := l/MapHeight;     //souradnice textury-K
    Indices[2*(l*MapWidth+k)+2][0] := 0;

Načtení obrázku BMP nebo JPG

Nastavím cestu k adresáři s texturami a převedu celou cestu na velká písmena:

  Path := ExtractFilePath(Application.ExeName) + 'GAMEDATA\TEXTURES\' + FileName;
  Path:=uppercase(Path);

Jestli obrázek neexistuje, program nahlásí chybu:

  if findfirst(Path,$3f,searchrec)<>0 then begin
     MessageDlg('Picture '+Path+' not found !!!', mtError, [mbOK], 0);
     halt;
  end;

Vytvoření obrázku:

  Image:=TImage.Create(Self);

Načtení JPG souboru a převedení na TPicture:

  if ExtractFileExt(Path)='.JPG' then begin 
    JPEGImage := TJPEGImage.Create;
    JPEGImage.LoadFromFile(Path);
    Image.Width := JPEGImage.Width;
    Image.Height := JPEGImage.Height;
    Image.Canvas.Draw(0,0,JPEGImage);
    JPEGImage.free;
  end;

Načtení BMP souboru:

  if ExtractFileExt(Path)='.BMP' then Image.Picture.LoadFromFile(Path);

Zbytek procedury zůstává stejný jako v minulých příkladech.

Tady (146 kB) si můžete dnešní stáhnout zdroják i s texturami.

Vyšlo 28.12.2001, v blogu: 0 1 2 3 4 5 6 7 8

Děkuji, že jste se rozhodl(a) přečíst tento článek. Budu rád i za komentář. Pokud Vás tento článek zaujal a rádi byste jej doporučili ostatním, podpořte mně prosím tím, že věnujete minutku svého času a uděláte mi reklamu na linkuj.cz, vybrali.sme.sk či jagg.cz. Přeji příjemné čtení

Poslední články

Diskuse k blogu

Zatím nikdo nevložil komentář. Chcete být první? Přidání příspěvku
©PC-guru.cz 2000-2008 | Optimalizováno pro 1024*768