Namangan muhandislik-pedagogika


Download 1.94 Mb.
bet7/7
Sana14.08.2020
Hajmi1.94 Mb.
#126302
1   2   3   4   5   6   7
Bog'liq
3D маъруза матни




12- Ma`ruza: IdirectDraw Ob`yekti.
DirectDraw interfeyslar ichida eng soddasi hisoblanadi. Uning tarkibida yagona DirectDrawCreate funksiya mavjud. Bu funksiyadan biz API funksiyalardan foydalanishga yo`l ochuvchi IDirectDraw - COM ob`yektini yaratamiz.

DirectDraw `ni yaratish dasturi quyidagicha (formaning OnCreate xodisasida yaratib, OnDestory xodisasida yo`q qilish):


unit Unit1;
interface
uses

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, DDraw;


type

TForm1 = class(TForm)



procedure FormCreate(Sender: TObject);

procedure FormDestroy(Sender: TObject);

private

DirectDraw: IDirectDraw; // DirectDraw bosh ob`yekti



end;
var

Form1: TForm1;


implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);

begin

{ COM-ob`yekti bo`lgan DirectDraw `ni yaratish}

if DirectDrawCreate( nil, DirectDraw, nil ) <> DD_OK then

raise Exception.Create ('Failed to create IDirectDraw object');

end;
procedure TForm1.FormDestroy(Sender: TObject);

begin

{ Release uslubini chaqirish uchun

COM-ob`yekti bo`lgan DirectDraw `ni yaratish }

if Assigned ( DirectDraw ) then

DirectDraw.Release ;



end;
end.
DirectDraw `dan foydalanishda u HResult nomli butun tipdagi kod qaytaradi bu kod xatoliklarning tartob raqami hisoblanadi. Agarda uning qiymati DD_OK (0) bo`lsa demak xatolik yo`q.

Endi esa ekran turini o`zgartiruvchi SetCooperativeLavel funksiyasi bulan tanishamiz. Yuqoridagi dastur kodiga OnShow xodisasini qo`shamiz va uni quyidagicha o`zgartiramiz:


procedure TForm1.FormShow(Sender: TObject);

begin

if DirectDraw.SetCooperativeLevel(Handle,

DDSCL_EXCLUSIVE or DDSCL_FULLSCREEN ) <> DD_OK then



raise Exception.Create('Unable to acquire exclusive full-screen access');
if DirectDraw.SetDisplayMode(640, 480, 8) <> DD_OK then

raise Exception.Create('Unable to set new display mode');

end;
Natijada dastur ishga yuklanganidan so`ng forma k`osatilgan rejim bo`yicha ekranni to`la qoplaydi. SetDisplayMode funksiyasi esa ekran turini o`zgartirish. raise hizmatchi so`zi esa xatolikni namoish etiash uchun hizmat qiladi.

Lekin shunday hollar ham bo`ladiki DirectDraw ekran holatiga o`tilganidan so`n ro`y beradigan xatoliklar oyna ortida korinmay qoladi. Natijada dasturdagi muammoni xal etish murakkablashadi. Buning oldini olish uchun IDE terkibidagi OnException xodisasini dasturga bog`lash lozim. Buning uchun OnCreate prosedurasi ichiga

Application.OnException := ExceptionHandler;

satrini qo`shish kerak. So`ngra quyidagi prosedura dasturga qo`shiladi:


procedure TForm1.ExceptionHandler(Sender: TObject; E: Exception);

begin


if Assigned(DirectDraw) then

DirectDraw.FlipToGDISurface;

MessageDlg(E.message, mtError, [mbOK], 0);

end;
Yana bir muammo dastur o`z ishini yakunlayotganida (OnDestry) uning tarkibiga

Application.OnException := Nil;

satrini qo`shb qo`yish lozim.


Dasturning umumiy ko`rinishi bilan tanishamiz:
unit Unit1;
interface
uses

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,

Dialogs, DDraw, StdCtrls;
type

TForm1 = class(TForm)

Label1: TLabel;

procedure FormCreate(Sender: TObject);

procedure FormDestroy(Sender: TObject);

procedure FormShow(Sender: TObject);

procedure ExceptionHandler(Sender: TObject; E: Exception);

private


DirectDraw : IDirectDraw ;

end;
var

Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.ExceptionHandler(Sender: TObject; E: Exception);

begin


if Assigned(DirectDraw) then

DirectDraw.FlipToGDISurface;

MessageDlg(E.message, mtError, [mbOK], 0);

end;


procedure TForm1.FormCreate(Sender: TObject);

begin


{ COM-ob`yekti bo`lgan DirectDraw `ni yaratish}

if DirectDrawCreate( nil, DirectDraw, nil ) <> DD_OK then

raise Exception.Create('Failed to create IDirectDraw object' );

Application.OnException := ExceptionHandler;

end;
procedure TForm1.FormDestroy(Sender: TObject);

begin


{ Release uslubini chaqirish uchun

COM-ob`yekti bo`lgan DirectDraw `ni yaratish }

if Assigned ( DirectDraw ) then

DirectDraw.Release ;

Application.OnException := Nil;

end;
procedure TForm1.FormShow(Sender: TObject);

begin

if DirectDraw.SetCooperativeLevel(Handle,



DDSCL_EXCLUSIVE or DDSCL_FULLSCREEN) <> DD_OK then

raise Exception.Create('Unable to acquire exclusive full-screen access');


if DirectDraw.SetDisplayMode(640, 480, 8) <> DD_OK then

raise Exception.Create('Unable to set new display mode');

end;
end.
13- Ma`ruza: OpenGL ga kirish.

Yuqoridagi ma`ruzalarda ikki va uch o`lchovli tasvirlar bilan ishlashning turli yo`llarini ko`rib o`tdik. Bu ma`ruzada esa OpenGL kutubxonasi bilan tanishamiz.

OpenGL – o`yin va CAD sistamalarni yaratishda ikki va ych o`lchovli tasvirlarni hosil qilishni yolga qo`yuvchi quyi darajadagi funksiyalarni o`z ichiga olgan standart kutibxonadir.

Bu kutibxona Windows operasion sistemasiga o`rnatilgan bo`lib, opengl32.dll va glu32.dll kutibxona fayllari tarkibida bo`ladi. Birinchi kutibxona ichida OpenGL ning acociy funksiyalari mavjud. Ikkinchi kutibxona ichida qo`shimcha funksiyalar mavjud.

Delphi `ning uchinchi versiyasidan boshlab OpenGL kutibxonasidan foydalanish uchun opengl.pas fayli yaratilgan bo`lib uning yordamida OpenGL kutibxonasi imkoniyatidan foydalaniladi.

OpenGL `da kichik bir dastur tuzish uchun ham maxsus kodlar ketma-ketligi yoziladi bu albatta dastlabki dastur tuzuvchilarni qo`rqitib yuborishi mumkin.




Xodisa, xabar va kontekst.
Dastlab xodisa va xabar tushunchasi bilan tanishamiz. Har ikki jumla ham Windos operasion sistemasida qo`llaniladi. Masalan Delphi`da OnCreate xodisasi qachonki Windows `dan WM_CREATE xabarini olgandagina bagariladi. Yoki WM_PAINT xabarining Delphi `ga kelishi OnPaint xodisasini bajarilishiga olib keladi. Bu xodisa va xabarlar xar bir oyna uchun bajariladi.

Ma`lumki Windows operasion sistemasi ko`p oynali muhitni boshqaradi. Endi esa savol tug`iladi. Windows qanday qilib oynalarni bir-biridan ajrarib oladi?

Bu savolga quyidagicha javob beramiz: Xar bir oyna yaratilayotgan vaqtda Windows uni ro`yxatga oladi va u qayerda turgani ko`rsatib qo`yiladi. Delphi `da bu ko`rsatgich - HWND (Window Handle – oynani ko`rsatish) tipi bilan aniqlanadi.

Oynalarni boshqarishni nafaqat Windows operasion sistemasi bajaradi balki, uni dasturlar yordamida ham boshqarish mumkin.

Delphi yordamida oynaning mavjud yoki mavjud emasligini tekshiramiz.

Dastlab Delphi `da yani proekt hosil qilamiz. Formaning nomini Form2 `ga o`zgartiramiz. Button tugmasini o`rnatamiz va uning OnClick xodisasiga quyidagi kodni kiritamiz:


procedure TForm2.Button1Click(Sender: TObject);

var


   H : HWND;

begin


   H := FindWindow ('TForm1', 'Form1');

   If H <> 0 then ShowMessage ('Form1 mavjud!')

         else ShowMessage ('Form1 mavjud emas!')

end;
Natijada 'Form1 mavjud emas!' xabari beriladi. Agarda forma nomini Form1 ga o`zgartirilsa 'Form1 mavjud!' xabari beriladi.

Biz yuqoridagi dastuda Windows API kutibxonasining FindWindow funksiyasidan foydalandik. Bu funksiya HWND tipiga mos bo`lga oyna ko`rsatkichini (aniqroq qilib aytadigan bo`lsak oynaning tartib raqami) qaytaradi. Aks xolda esa funksiya qiymati 0 ga teng boladi.

Oynaga ko`rsatgich qo`yish bu, oynani aniqlash demakdir. Handle oynaga qo`yilgan ko`rsatgich bo`lib u oyna yaratilayotgan vaqta Windows API tomonidan qo`yiladi.

Onaning ko`rastkihi bo`yicha uni bamalol boshqarishimiz mumkin. Masalan:
procedure TForm2.Button1Click(Sender: TObject);

var


   H : HWND;

begin


   H := FindWindow ('TForm1', 'Form1');

   If H <> 0 then SendMessage (H, WM_CLOSE, 0, 0)

end;
Yuqoridagi dastur yordamida biz ikkinchi formadan turib birinchi formani yopiladi. Natijada dastur o`z ishini to`xtatadi.

Boshqa oynaga tasvir chizish uchun ham dastlab oyna izlanadi va unga chiziladi.

Tushuncha xosil qilish maqsadida joriy oynaga rasm chizish dasturini ko`rib o`tamiz:

Oynaga yana bir Button qo`shamiz va quyidagi kodni kiritamiz:


procedure TForm2.Button2Click(Sender: TObject);

var


dc : HDC;

begin


dc := GetDC (Handle);

Rectangle (dc, 10, 10, 110, 110);

ReleaseDC (Handle, dc);

end;
Dasturni ishga yuklab ikkinchi Button `ni bosilsa joriy onaga to`g`ri to`rtburchak chiziladi.

Endi esa boshqa oynaga chizishni ko`rib o`taylik:

procedure TForm2.Button2Click(Sender: TObject);

var

   dc : HDC;



   Window : HWND;

begin


   Window := FindWindow ('TForm1', 'Form1');

   If Window <> 0 then begin

    dc := GetDC (Window);

    Rectangle (dc, 10, 10, 110, 110);

    ReleaseDC (Handle, dc);

   end


end;
OpenGL grafik tizimi Windows `ning boshqa dasturlari kabidir, uning yordamida tasvir hosil qilish uchun ko`rsatilgan oyna (HDC) va kontekst(HGLRC)dan foydalaniladi. Shuning uchun OpenGL dan foydalanishda kodlar oynasining Private bo`limiga quyidagi o`zgaruvchilar e`lon qilinadi:

   DC: HDC;

   hrc: HGLRC;
Formaning OnCreate xodisasiga quyidagi satirlar kiritiladi:
DC := GetDC(Handle);

SetDCPixelFormat;

hrc := wglCreateContext(DC);

wglMakeCurrent(DC, hrc);


Yuqoridagi dastur yordamida forma aktivlashtirildi, pikselning ixtiyoriy formati o`rnatildi, yangi kontekst yaratildi va aktivlashtirildi.

OpenGL yordamida formaga chiqarish esa quyidagi dasturda qo`llanilgan:


dc := BeginPaint(Window, ps);

wglMakeCurrent(DC, hrc);


wglMakeCurrent(0, 0);

EndPaint (Window,ps);

ReleaseDC (Window, dc);
14- Ma`ruza: Nuqta formati. OpenGL da kichik dasturlar yaratish. Tasvirni komponent sirtiga chiqarish.
Kontekst qurilmaga bog`lanilgandan so`ng biz birir rangli qalam yoki mo`yqalamdan foydalaniladi. OpenGL serveri ham qaysi qorilmani boshqarishi lozimligini aniqlashi lozim. Bu oddiy persanal bo`lishi ham yoki yuqori darajadagi garafik sistema ham bo`lishi mumkin. OpenGL tasvir hosil qilishdan oldin boshqariluvchi qurilma haqida ma`lumotga ega bo`lishi lozim. Bu ma`lumot quyidagi tip orqali aniqlanadi: TPixelFormatDescriptor (piksel formatini aniqlash). Piksel formati buferdagi ranglar konfigurasiyasini va yordamchi buferni aniqlaydi. Bu tipdan foydalanish quyidagi dastur yordamida yo`lga qo`yilgan:
program OpenGL_min;

{**************** OpenGL da kichik dastur *********************}

{* OpenGL buyrug`I yordamida dastur yangi oyna yaratadi. *}

{* Quyidagi satrlarga etibor berish lozim: *}

{* 1. OpenGL oynasinu hisil qilish uchun *}

{* ws_OverLappedWindow or ws_ClipChildren or ws_ClipSiBlings *}

{* usullaridan foydalaniladi *}

{* 2. OpenGL namoish etish kontekstidan foydalanadi (rendering *}

{* context). Dastur namoish etish kontekstini yaratishi va uni *}

{* joriylashtirishi lozim. *}

{* 3. Kontekstni yaratishdan avval piksel formatini o`rnatish lozim *}

{***********************************************************************}

uses

Messages, Windows, OpenGL;


const

AppName = 'OpenGL_Min';


Var

Window : HWnd;

Message : TMsg;

WindowClass : TWndClass;

dc : HDC;

hrc : HGLRC; // OpenGL `ni namoish etuvchi kontekst

MyPaint : TPaintStruct;
// PIXELFORMATDESCRIPTOR mayonini to`ldirish prosedurasi

procedure SetDCPixelFormat (hdc : HDC);

var

pfd : TPixelFormatDescriptor; // piksel formatinining ma`lumotlari



nPixelFormat : Integer;

Begin


With pfd do begin

nSize := sizeof (TPixelFormatDescriptor); // struktura xajmi

nVersion := 1; // versiya raqami

dwFlags := PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL; // qurilma va interfeyslarni aniqlovchi bitlar to`plami

iPixelType := PFD_TYPE_RGBA; // ranglarni hosil qiluvchi muhit

cColorBits := 16; // ranglarning xar bir buferdagi soni

cRedBits := 0; // har bir RGBA buferidagi qizil rangli bitlar soni

cRedShift := 0; // har bir RGBA buferidagi qizil rangli bitlarni surish

cGreenBits := 0; // har bir RGBA buferidagi yashil rangli bitlar soni

cGreenShift := 0; //har bir RGBA buferidagi yashil rangli bitlarni surish

cBlueBits := 0; // har bir RGBA buferidagi ko`k rangli bitlar soni

cBlueShift := 0; // har bir RGBA buferidagi ko`k rangli bitlarni surish

cAlphaBits := 0; // har bir RGBA buferidagi alfa rangli bitlar soni

cAlphaShift := 0; // har bir RGBA buferidagi alfa rangli bitlarni surish

cAccumBits := 0; // akkumlyator buferidagi umumiy bitlar soni

cAccumRedBits := 0; // akkumlyator buferidagi qizil rangli bitlar soni

cAccumGreenBits:=0; // akkumlyator buferidagi yashil rangli bitlar soni

cAccumBlueBits:=0; // akkumlyator buferidagi ko`k rangli bitlar soni

cAccumAlphaBits:=0; // akkumlyator buferidagi alfa rangli bitlar soni

cDepthBits := 32; // fazo buferining xajmi (z o`qi)

cStencilBits := 0; // trafert buferining xajmi

cAuxBuffers := 0; // yordamchi buferlar soni

iLayerType := PFD_MAIN_PLANE;// sirt turi

bReserved := 0; // oldingi va keyingi sirtlar soni

dwLayerMask := 0; // игнорируется

dwVisibleMask := 0; // keyingi sirtning raqami yoki shaffof rangi

dwDamageMask := 0; // игнорируется

end;
// tanlangan pikselning o`rinliligini sistemadan so`rash

nPixelFormat := ChoosePixelFormat (hdc, @pfd);

// o`rnatilayotgan piksel formatini kontekst qurilmasiga joylash

SetPixelFormat (hdc, nPixelFormat, @pfd);

End;
function WindowProc (Window : HWnd; Message, WParam : Word;

LParam : LongInt) : LongInt; stdcall;

Begin


WindowProc := 0;

case Message of

wm_Create:

begin


dc := GetDC (Window);

SetDCPixelFormat (dc); // piksel formatini o`rnatish

hrc := wglCreateContext (dc); // OpenGL konteksti yaratilmoqda

end;


wm_Paint:

begin


BeginPaint (Window, MyPaint);

// joriy namoish etuvchi kontekst o`rnatilmoqda

wglMakeCurrent (dc, hrc);
{************ OpenGL `da namoish etish boyruqlari **************}
glClearColor (0.85, 0.75, 0.5, 1.0); // fon rangibi aniqlash

glClear (GL_COLOR_BUFFER_BIT); // fon rangini o`rnatish


{************************************************************************}
wglMakeCurrent (dc, 0); // ish yakunlanganidan so`ng kontekstni

// uzish
EndPaint (Window, MyPaint);

end;

wm_Destroy :



begin

wglDeleteContext (hrc); // namoish etuvchi kontekstni uzish

PostQuitMessage (0);

Exit;


end;
end; // case

WindowProc := DefWindowProc (Window, Message, WParam, LParam);

End;
Begin

With WindowClass do

begin

Style := cs_HRedraw or cs_VRedraw;



lpfnWndProc := @WindowProc;

cbClsExtra := 0;

cbWndExtra := 0;

hInstance := 0;

hCursor := LoadCursor (0, idc_Arrow);

lpszClassName := AppName;

end;

RegisterClass (WindowClass);



Window := CreateWindow (AppName, AppName,

ws_OverLappedWindow or ws_ClipChildren

or ws_ClipSiBlings,

cw_UseDefault, cw_UseDefault,

cw_UseDefault, cw_UseDefault,

HWND_DESKTOP, 0, HInstance, nil);

ShowWindow (Window, CmdShow);

UpdateWindow (Window);

While GetMessage (Message, 0, 0, 0) do begin

TranslateMessage (Message);

DispatchMessage (Message);

end;


Halt (Message.wParam);

end.


Tasvirni komponent sirtiga chiqarish.
OpenGL yordamida nafaqat oyna sirtiga balik, komponent sitiga tasvir xosil qilish mumkin (agarda unda Canvas.Handle bo`lsa). Buning uchun esa kontekst qurilmaga tanlangan komponent k`orsatib qo`yiladi. Masalan Image1.Canvas.Handle.

Misol sifatida Penael komponentiga tasvi chizib k`oramiz:


unit Unit1;

interface

uses

Windows, Messages, Forms, Dialogs, OpenGL, Classes, Controls, ExtCtrls,



StdCtrls;

type


TForm1 = class(TForm)

Panel1: TPanel;

procedure FormPaint(Sender: TObject);

procedure FormDestroy(Sender: TObject);

procedure FormCreate(Sender: TObject);
private

dc : HDC;

hrc: HGLRC;

end;
var

Form1: TForm1;

implementation

{$R *.DFM}

{=======================================================================

Oyna xosil qilish}

procedure TForm1.FormPaint(Sender: TObject);

var

ps : TPaintStruct;



begin

BeginPaint (Panel1.Handle, ps); // Pane1 `ga chizish

wglMakeCurrent(dc, hrc);

glClearColor (1.0, 0.0, 0.0, 1.0);

glClear (GL_COLOR_BUFFER_BIT);

wglMakeCurrent(dc, 0);

EndPaint (Panel1.Handle, ps);

end;
{=======================================================================

piksel formati}

procedure SetDCPixelFormat (hdc : HDC);

var

pfd : TPIXELFORMATDESCRIPTOR;



nPixelFormat : Integer;

begin


FillChar(pfd, SizeOf(pfd), 0);

nPixelFormat := ChoosePixelFormat (hdc, @pfd);

SetPixelFormat (hdc, nPixelFormat, @pfd);

end;
{=======================================================================

Formani yaratish}

procedure TForm1.FormCreate(Sender: TObject);

begin

dc := GetDC (Panel1.Handle);



SetDCPixelFormat(dc);

hrc := wglCreateContext(dc);

end;
{=======================================================================

Forma ishini yakunlash}

procedure TForm1.FormDestroy(Sender: TObject);

begin


wglDeleteContext(hrc);

end;
end.


Yuqoridagi dastur Panel1 komponenti sirtini qizil rang bilan bo`yaydi.

15- Ma`ruza: GMS faylining tuzilishi. GMS faylini Delphi ga yuklash.
Ikki o`lchovli tasvirlarni xosil qilish va uni xarakatlantirish u darajada murakkablik tug`dirmaydi. Masalan ikki o`lchovli tasvirni xarakatga kelrirish uchun undan nusxa olinadi va u suriladi (x, y). Qolgan tasvir fon rangi bilan tozalanadi. Uch o`lchovli tasvitlarni xosil qilish ham, xarakatga keltirish ham murakkab jarayon hisoblanadi (x, y, z). Uch o`lchovli tasvirlarni dastur tuzish yo`li bilan hosil qilish juda ham qiyin. Lekin tasvir hosil qiluvchi dasturlar yordamida amalga oshirilsa bu jarayon ancha ochon kechadi. Bunday dasturlardan biri 3D Max Studio dasturidir. Uning yordamida ko`p o`lchovli tasvirlar yaratish va ularni xarakatga keltirish mumkin.

MEGA utiliti bilan tanishish
Bu utilit (Meshes Export for Games and Animation- MEGA) bilan tanishish uchun 3D-Max Studio 3.0 dasturi kerak bo`ladi. MEGA utilitidan quyidagicha foydalaniladi:

  1. 3D Max Studio dasturini ishga tushirasiz va oddiy sfera yaratasiz;

  2. Sfera sirtida sichqonchaning o`ng tugmasini bosasiz. Natijada menyu hosil bo`ladi. U erdan Convert to Editable Mesh (tahrirlash uchun setka holiga o`tkazish) satri tanlanadi;

  3. Buyruqlar panelidan bolg`acha rasmini tanlanadi;

  4. Hosil bo`lgan utilit menyusidan MAXScript tugmasi bosiladi. Natijada faylni o`qish oynasi hosil boladi;

  5. MEGA.ms fayli ishga yuklanadi va hosil bo`lgan MEGA oynasining From maydoniga 1, To maydoniga 100, Step maydoniga ham 100 kiritiladi;

  6. Save As… tugmachasi bosiladi lozim bo`lgan papkaga istalgan nom bilan saqlqnadi. Natijada *.GMS fayli hosil bo`ladi.



GMS Faylining formati
GMS fayli matnil fayl bo`lib u quyidagicha ko`rinishga ega:
// Yangi Ob`yektning boshanishi

New object

// Ob`yekt tipi



TriMesh() // Ob`yekt - setka
numverts numfaces

// Keyingi qator Ob`yektning qirra va burcharlar sonini o`zida saqlashini bildiradi
Mesh vertices: // Здесь располагается блок вершин объекта в виде координат X Y Z
end

verticesMesh faces:// Здесь располагается блок граней объекта в виде индексов 1 2 3, где каждый индекс - индекс в массиве вершин, указывает на вершину грани


end

faces Faset normals:// Здесь располагается блок фасетных нормалей в виде координат X Y Z. Их количество равно количеству граней



end faset normals

Smooth normals:// Здесь располагается блок сглаживающих нормалей в виде координат X Y Z. Их количество равно количеству вершин.


end smooth normals

end mesh // Конец описания объекта Tri Mesh

end of file // Конец файла

Примерно так выглядит файл, когда мы экспортируем сетчатый объект. Если объект не сетчатый, то файл будет выглядеть следующим образом:

New object // Указывает на начало нового объекта, следующая строка указывает тип объекта
<Тип объекта>, например:
Box
// Здесь идут параметры, зависящие от типа объекта (Поверхности Безье и NURBS - поверхности не поддерживаются)
end <
Тип объекта> // Конец описания объектаe
end of file // Конец файла
GMS fayllarni Delphi `da ochish
GMS fayllar bilan ishlsash uchun dastlab tip yaratib olish zarur. Buning uchun quyidagicha kodlar ketma-ketligi kiritiladi:
Type // Tiplarni e`lon qilish
PGLVertex = ^TGLVertex; // Указатель на вершину
TGLVertex = record
  x,y,z : GLFloat; // Вершина, как три значения с плавающей точкой
end;PGLVector = ^TGLVector; // Указатель на вектор
TGLVector = array[0..2] of GLFloat; // Вектор, как массив из трех элементов с плавающей точкой
PGLFace = ^TGLFace; // Указатель на грань
TGLFace = array[0..2] of GLInt; // Грань, как массив из трех целочисленных значений
PGLVertexArray = ^TGLVertexArray; // Указатель на массив вершин
TGLVertexArray = array[Word] of TGLVertex; // Массив вершин
PGLFacesArray = ^TGLFacesArray; // Указатель на массив граней
TGLFacesArray = array[word] of TGLFace; // Массив граней
Здесь требуется небольшое пояснение. Как вы заметили, грань объявлена, как массив из трех целочисленных чисел. Дело в том, что граней почти всегда больше чем вершин. Поэтому все вершины запоминаются в отдельном массиве, а грань - это три индекса в этом массиве, указывающие на вершины принадлежащие грани. Одна вершина может принадлежать нескольким граням.

Теперь рассмотрим описание объекта сетка:



TGLMesh = class
  
Vertices : PGLVertexArray; // Массив вершин объекта - сетка
  Faces : PGLFacesArray; // Массив граней
  FasetNormals : PGLVertexArray; // Массив фасетных нормалей
  VertexCount : Integer; // Количество вершин
  FacesCount : Integer; // Количество граней
  fExtent : GLFloat; // Коэффициент масштабирования
  Extent : GLBoolean; // Флаг масштабирования
public
  procedure
LoadFromFile( const FileName : String ); // Загрузка
  procedure CalcNormals; // Расчет нормалей
  procedure Draw; // Отрисовка
  destructor Destroy; override; // Уничтожение с очисткой массивов
end;

Здесь пояснений практически не требуется. Можно лишь отметить, что Extent служит для того, чтобы объект загнать в размеры в пределах (-1, 1), я сделал это для того, чтобы объект любого размера не мог вылезти за пределы окна. Вообще говоря, в 3D Studio Max не сложно масштабировать объект так, чтобы координаты вершин попали в интервал (-1, 1), но на этапе создания модели думать об этом совсем не хочется.

procedure TGLMesh.LoadFromFile; // Загрузка файла
var
  
f : TextFile;
  S : String;
  i : Integer;
  Vertex : TGLVertex;
  Face : TGLFace;
  MaxVertex : GLFloat;
begin
  AssignFile(f,FileName);
  Reset(f);

  // Пропускаем строки, пока не попадется 'numverts numfaces'


  repeat
   
ReadLn(f, S);
  until (S = 'numverts numfaces') or eof(f);  // Читаем количество вершин и граней
  Readln(f,VertexCount,FacesCount);  // Выделяем память для хранения сетки
  GetMem(Vertices,VertexCount*SizeOf(TGLVertex));
  GetMem(Faces,FacesCount*SizeOf(TGLFace));
  GetMem(FasetNormals,FacesCount*SizeOf(TGLVector));  ReadLn(f, S); // Пропускаем строку "Mesh vertices"  // Считываем вершины
  for i := 0 to VertexCount - 1 do
  begin
    
Readln(f,Vertex.x,Vertex.y,Vertex.z);
    Vertices[i] := Vertex;
  end;
  ReadLn(f, S); // Пропускаем строку "end vertices"
  ReadLn(f, S); // Пропускаем строку "Mesh faces"  // Считываем грани
  for i := 0 to FacesCount - 1 do
  begin
   
Readln(f,Face[0],Face[1],Face[2]);
    Face[0] := Face[0] - 1;
    Face[1] := Face[1] - 1;
    Face[2] := Face[2] - 1;
    Faces[i] := Face;
  end;
  CloseFile(f);  // Рассчитываем масштаб
  MaxVertex := 0;
  for i := 0 to VertexCount - 1 do
  begin
   
MaxVertex := Max(MaxVertex,Vertices[i].x);
    MaxVertex := Max(MaxVertex,Vertices[i].y);
    MaxVertex := Max(MaxVertex,Vertices[i].z);
  end;
 
fExtent := 1/MaxVertex;
  CalcNormals;

end;


Здесь могут быть непонятны следующие моменты: В блоке считывания граней я вычитаю единицу из каждого индекса вершины, считанного из файла. Делается это потому, что в программе индексы нумеруются, начиная с нуля, а в файле GMS - начиная с единицы. Процедура CalcNormals служит для расчета нормалей и взята из книги "OpenGL графика в проектах Delphi" Михаила Краснова. О том, что такое нормали и зачем они нужны я расскажу в разделах "Фасетные нормали" и "Сглаживающие нормали".

procedure TGLMesh.Draw;
var
 
i : Integer;
  Face : TGLFace;
begin
  if
Extent then glScalef(fExtent,fExtent,fExtent);  
  for
i := 0 to FacesCount - 1 do
  begin

    glBegin(GL_TRIANGLES);
    Face := Faces[i];
    glNormal3fv(@FasetNormals[i]);
    glVertex3fv(@Vertices[Face[0]]);
    glVertex3fv(@Vertices[Face[1]]);
    glVertex3fv(@Vertices[Face[2]]);
    glEnd;
  end;
end;

Здесь все понятно. Сначала, если установлен флаг масштабирования, устанавливается масштаб одинаковый по всем осям, затем в цикле рисуются треугольники. Перед началом рисования треугольника объявляется нормаль к нему. В качестве параметров передаются не конкретные значения, а указатели на них.

Destructor TGLMesh.Destroy;
begin
  
FreeMem(Vertices,VertexCount*SizeOf(TGLVertex));
  FreeMem(Faces,FacesCount*SizeOf(TGLFace));
  FreeMem(FasetNormals,FacesCount*SizeOf(TGLVector));
end;

Здесь тоже все понятно, просто освобождается память, занятая объектом. Вызовы процедур загрузки и отрисовки объекта находятся в модуле frmMain и не представляют ничего интересного.

16- Ma`ruza: Xarakatlanuvchi tasvirni xosil qilish va ekranga chiqarish.

GMS tipidagi tasvirlarni xarakatlantirish uchun 3D Studio MAX dasturi ishga tushiriladi va xarakatlanuvchi Ob`yekt yaratiladi yoki uni BodyRun.max faylidan chaqirib olinadi. MEGA utiliti ishga tushiriladi. From maydoniga 0, To maydoniga oxirigi kadr raqami qo`yiladi. Agarda BodyRun.max chaqrilgan bo`lsa u holda To maydoniga 11 qo`yiladi. Setup maydoniga 1 raqami qo`yiladi. Ob`yekt setkasi belgilanadi. Select Only maydoni belgilab qo`yiladi (16.1-rasm).







16-rasm.

Yuqoridagi amallarning barchasi amalga oshirilganidan so`ng. Ob`yektni GMS fayl qilib eksport qilinadi. Ob`yektni eksport qilish vaqtida siz har bir kadr o`tishini kuzatishingiz mumkin.

Ob`yektni xosil qilish formasi:


Ob`yektni xarakatga keltirish dasturi quyidagicha:
unit frmMain;

interface

uses

Windows, Messages, Classes, Graphics, Forms, ExtCtrls, Menus,



Controls, Dialogs, SysUtils, OpenGL, Mesh;

type


Vector = record

x, y, z : GLfloat;

end;

type


TfrmGL = class(TForm)

MainMenu1: TMainMenu;

N1: TMenuItem;

OpenDialog: TOpenDialog;

N2: TMenuItem;

procedure FormCreate(Sender: TObject);

procedure FormResize(Sender: TObject);

procedure FormDestroy(Sender: TObject);

procedure FormKeyDown(Sender: TObject; var Key: Word;

Shift: TShiftState);

procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,

Y: Integer);

procedure FormMouseUp(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer);

procedure FormMouseDown(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer);

procedure N1Click(Sender: TObject);

procedure N2Click(Sender: TObject);

private

DC: HDC;


hrc: HGLRC;

lastx, down : Integer;

procedure Init;

procedure SetDCPixelFormat;

protected

procedure WMPaint(var Msg: TWMPaint); message WM_PAINT;

end;
var

frmGL: TfrmGL;

Angle : GLfloat = 0;

Step : GLfloat = 1;

wrkStep : GLfloat = 1;

wrkTime : longint;

wrkX, wrkY : Integer;

MyMesh : TGLMultyMesh;


implementation
{$R *.DFM}
{=======================================================================

Instalyasiya}

procedure TfrmGL.Init;

begin


glEnable(GL_DEPTH_TEST);

glEnable(GL_LIGHTING);

glEnable(GL_LIGHT0);

glEnable (GL_COLOR_MATERIAL);

glEnable (GL_NORMALIZE);

glColor3f (0.4, 0.6, 0.6);

end;
{=======================================================================

Oynani chizish}

procedure TfrmGL.WMPaint(var Msg: TWMPaint);

var


ps : TPaintStruct;

begin


BeginPaint (Handle, ps);

glClear (GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

glPushMatrix;

glRotatef (-90.0, 1.0, 0.0, 0.0);

glRotatef (2 * Angle, 0.0,0.0 , 1.0);

MyMesh.Draw;

glPopMatrix;

SwapBuffers (DC);

EndPaint (Handle, ps);

Angle := Angle + Step;

If Angle >= 360.0 then Angle := 0.0;

InvalidateRect(Handle, nil, False);

end;
{=======================================================================

Oynani yaratish}

procedure TfrmGL.FormCreate(Sender: TObject);

begin


DC := GetDC(Handle);

SetDCPixelFormat;


hrc := wglCreateContext(DC);

wglMakeCurrent(DC, hrc);

glClearColor (1.0, 0.5, 0.5, 1.0);

down := 0;


Init;
MyMesh := TGLMultyMesh.Create;

MyMesh.LoadFromFile( '..\GMS\ManRun.gms' );

MyMesh.Extent := true;
if MyMesh.Meshes.Count <= 1 then N2.Enabled := False

else N2.Enabled := True;

end;
{=======================================================================

Oyna xajmini o`zgartirish}

procedure TfrmGL.FormResize(Sender: TObject);

begin


glViewPort (0, 0, ClientWidth, ClientHeight);

glMatrixMode(GL_PROJECTION);


glLoadIdentity;
gluPerspective(40.0, ClientWidth / ClientHeight, 3.0, 13.0);

glMatrixMode(GL_MODELVIEW);


glLoadIdentity;
glTranslatef(0.0, 0.0, -5.0);

InvalidateRect(Handle, nil, False);

end;
{=======================================================================

Dastur ishini yakunlash}

procedure TfrmGL.FormDestroy(Sender: TObject);

begin


wglMakeCurrent(0, 0);

wglDeleteContext(hrc);


ReleaseDC(Handle, DC);
DeleteDC (DC);

end;
{=======================================================================

Tugmacha bosilishi}

procedure TfrmGL.FormKeyDown(Sender: TObject; var Key: Word;

Shift: TShiftState);

begin


If Key = VK_ESCAPE then Close;

If Key = VK_SPACE then begin

If step = 0

then step := wrkStep

else begin

wrkStep := step;

step := 0;

end


end;

end;
{=======================================================================

Sichqoncha xarakati}

procedure TfrmGL.FormMouseMove(Sender: TObject; Shift: TShiftState; X,

Y: Integer);

begin


If down <> 0 then begin

glRotatef (lastx - x, 1, 0, 1); lastx := x;

InvalidateRect(Handle, nil, False);

end;


end;
{=======================================================================

Sichqoncha tugmasining ko`tarilishi}

procedure TfrmGL.FormMouseUp(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer);

begin

down := 0;



end;
{=======================================================================

Sichqoncha tugmasining bosilisi}

procedure TfrmGL.FormMouseDown(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer);

begin

If button = mbLeft then begin



lastx := X;

wrkX := X;

wrkY := Y;

down := 1;

wrkTime := GetTickCount;

end;


end;
{=======================================================================

Piksel formatini O`rnatish}

procedure TfrmGL.SetDCPixelFormat;

var


nPixelFormat: Integer;

pfd: TPixelFormatDescriptor;

begin

FillChar(pfd, SizeOf(pfd), 0);


pfd.dwFlags := PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or

PFD_DOUBLEBUFFER;

nPixelFormat := ChoosePixelFormat(DC, @pfd);

SetPixelFormat(DC, nPixelFormat, @pfd);

end;
procedure TfrmGL.N1Click(Sender: TObject);

begin


if OpenDialog.Execute then

begin


MyMesh.Destroy;

Mymesh := TGLMultyMesh.Create;

MyMesh.LoadFromFile( OpenDialog.FileName );

MyMesh.Extent := true;

if MyMesh.Meshes.Count <= 1 then N2.Enabled := False

else N2.Enabled := True;

end;

end;
procedure TfrmGL.N2Click(Sender: TObject);



begin

MyMesh.Action := not MyMesh.Action;

N2.Checked := not N2.Checked;

end;
end.


17- Ma`ruza: DirectDraw da shaffof tasvirlarni xosil qilish.

18- Ma`ruza: 3D STUDIO MAX 3.0 muhiti va unda ishlash.


19- Ma`ruza: 3D STUDIO MAX 3.0 muxitida uch o`lchovli tasvirlar xosil qilish.
20- Ma`ruza: 3D tasvirlarni 3D STUDIO MAX 3.0 dasturidan DirectX va OpenGL ga o`tkazish. MEGA utiliti bilan tanishish.

1 Dyuym taхminan 2,5 sm ga tyeng.

Download 1.94 Mb.

Do'stlaringiz bilan baham:
1   2   3   4   5   6   7




Ma'lumotlar bazasi mualliflik huquqi bilan himoyalangan ©fayllar.org 2024
ma'muriyatiga murojaat qiling