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
- Zoner Callisto (2.) - Export do PDF
- OpenGL (11.) - Nová detekce kolizí
- OpenGL (10.) - Nová knihovna geometry.pas
- OpenGL (9.) - Generování textur a vylepšení FarClip Distance
- Zoner Callisto (1.) - Export do GIFu
- 3D Studio MAX (9.) - Vytváření odlesků vodní hladiny
- OpenGL (8.) - Slovníček pojmů v OpenGL
- OpenGL (7.) - Detekce kolizí, načtení mapy a textury v jpg souboru
- OpenGL (6.) - Co je to MiniGL
- OpenGL (5.) - Urychlení pomocí glDrawElements
- Delphi (7.) - Syst. repro a autodestrukce souboru
- OpenGL (4.) - FullScreen
- 3D Studio MAX (8.) - Tvorba hořící zápalky
- 'DOOM' 3D Engine techniques
- OpenGL (3.) - Procházení scénou



