PDA

View Full Version : ماتریس ها در OpenGL



Vahid_Nasiri
پنج شنبه 12 تیر 1382, 00:57 صبح
با استفاده از ماتریس ها می توان یک سری از اعمال مانند دوران و انتقال و غیره را انجام داد. خوشبختانه OpenGL برای کار با این مفاهیم توابعی را ارائه داده است .

توابعی که در مثال این مقاله مورد استفاده قرار می گیرند به صورت زیر هستند :


glViewport(), glMatrixMode(), glLoadIdentity(), gluPerspective(), glClear(), gluLookAt(), glBegin(), glEnd()



در ابتدا آماده سازی تکراری کار که در مورد آن در مقالات پیشین صحبت شد انجام می شود :



unit ex03;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs , OpenGL , SPF;

type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormPaint(Sender: TObject);
procedure FormResize(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

var f_Hdc : HDC;


procedure InitGL; // All Setup For OpenGL Goes Here
begin
// select clearing color
glClearColor( 1.0, 1.0, 1.0, 0);
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
end;




تنها تغییری که در کد فوق ایجاد شده استفاده از فعال سازی Depth testing می باشد . بدین وسیله مطمئن خواهیم شد که در فضای سه بعدی قرار داریم و اجسامی با فواصل مختلف در عمق کاملا به وضوح مشاهده خواهند شد .

سپس به کد اصلی این برنامه می رسیم. برای سهولت کار رسم مثلث را به صورت یک تابع در آورده ایم . سپس در تابع رسم صحنه ی خود از تابع استاندارد glTranslatef برای انتقال مثلث ها استفاده می نماییم و در این مثال سه مثلث با فواصلی معین نسیت به هم ترسیم شده اند . هنگام انتقال و استفاده از تابع ماتریسی فوق کل محورهای مختصات ما نیز با آن حرکت خواهد کرد و اگر رسم مثلث بعدی را شروع کنیم از مبدا مختصات جدید کار رسم شروع می شود که معمولا گیج کننده و ناکارآمد است. برای رفع این معضل از توابع glPushMatrix و glPopMatrix برای محصور کردن انتقالات خود بهره می بریم . بدین ترتیب پس از رسم مثلث و انتقال آن با بکار بردن این محصور کننده ها دوباره در مبدا مختصات اول قرار می گیریم و به سادگی می توان کار رسم را ارائه داد.
کتاب OpenGL Red Book نامهای جالبی را برای این دو تابع اخیر بکار برده است. glPushMatrix به OpenGL می گوید به خاطر داشته باش کجا بودی! و سپس glPopMatrix به OpenGL می گوید که برگرد به جای قبلی .




///////////////////////////// DRAW TRIANGLE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This function draws a colored triangle centered around (x, y, z).
///// The size of this triangle depends on the width and height passed in
/////
///////////////////////////// DRAW TRIANGLE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*

procedure DrawTriangle( x , y, z, width, height :single);
begin
// Below we say that we want to draw triangles
glBegin (GL_TRIANGLES); // This is our BEGIN to draw

glColor3ub(255, 0, 0); // Make the top vertex RED
glVertex3f(x, y + height, z); // Here is the top point of the triangle

glColor3ub(0, 255, 0); // Make the left vertex GREEN
// Here is the right point of the triangle
glVertex3f(x + width, y - height, z);

glColor3ub(0, 0, 255); // Make the right vertex BLUE
// Here is the left point of the triangle
glVertex3f(x - width, y - height, z);
glEnd(); // This is the END of drawing

end;

///////////////////////////////// RENDER SCENE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This function renders the entire scene.
/////
///////////////////////////////// RENDER SCENE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*

procedure DrawGLScene();
begin

// Clear The Screen And The Depth Buffer
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glLoadIdentity(); // Reset The matrix

// Position View Up Vector
gluLookAt(0, 0, 6, 0, 0, 0, 0, 1, 0);
// This determines where the camera's position and view is

///// * NEW * /////// * /////////// * /////////// * ///////


//This draws a triangle
// centered around the origin at (0, 0, 0)
//with a width and height of (1, 1).
DrawTriangle( 0, 0, 0, 1, 1);

//
glPushMatrix(); // Push on another matrix to use
// This moves everything draw afterwards to (1, 0, -1)
glTranslatef(1, 0, -1);
DrawTriangle( 0, 0, 0, 1, 1);
glPopMatrix(); // Pop off this matrix and go back to the previous one

glPushMatrix(); // Here we push on a new matrix to manipulate
glTranslatef(-1, 0, -1);
DrawTriangle( 0, 0, 0, 1, 1);
glPopMatrix(); // Pop this matrix off the stack.

SwapBuffers(f_Hdc); // Swap the backbuffers to the foreground
end;



مرحله ی آخر کار هم عموما تکراری می باشد که در مثالهای قبل در مورد آن توضیح داده شد:




procedure TForm1.FormCreate(Sender: TObject);
begin
// Create a rendering context.
f_Hdc := GetDC(handle);
SetDCPixelFormat(f_Hdc,16,16);
InitGL;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
CleanUp(f_Hdc);// Clean up and terminate.
end;

procedure TForm1.FormPaint(Sender: TObject);
begin
wglMakeCurrent(f_Hdc,hrc); //activate the RC
DrawGLScene;// Draw the scene.
end;

procedure TForm1.FormResize(Sender: TObject);
begin
if (height=0) then

height:=1;

glViewport(0,0,width,height);
// The glViewport takes (x, y, width, height)
// This basically means, what our our drawing boundries

glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
glLoadIdentity(); // Reset The Projection Matrix

// Calculate The Aspect Ratio Of The Window
// The parameters are:
// (view angle, aspect ration of the width to the height,
// The closest distance to the camera before it clips,
// FOV // Ratio // The farthest distance before it stops drawing)
gluPerspective(45.0,width/height, 1 ,150.0);

glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
glLoadIdentity(); // Reset The Modelview Matrix

end;