You are on page 1of 7

‫كلية الهندسة – قسم المعلوماتيّة ‪IT‬‬

‫الجزء العملي‬
‫‪3‬‬ ‫بيانيات‬

‫هدف الجلسة‬
‫ّ‬
‫والتعرف عىل طريقة رسم المنحنيات مثل الدائرة‪ ،‬وإضافة نماذج ملء إىل المضلعات‪.‬‬ ‫ثنائ األبعاد‪،‬‬ ‫ّ‬
‫إجراء التحويالت الهندسية يف الفضاء ي‬

‫منطقة التقليم ونافذة العرض ‪Clipping-Area & Viewport‬‬


‫الكاميا) ‪ ،‬مقاسة بإحداثيات‬
‫ر‬ ‫الت تم التقاطها بواسطة‬
‫الت يمكن رؤيتها (أي ي‬ ‫منطقة التقليم أو القص ‪ :Clipping Area‬ت ر‬
‫شي إىل المنطقة ي‬
‫‪.OpenGL‬‬
‫والت يتم قياسها بالبكسل يف إحداثيات الشاشة‪.‬‬ ‫منفذ العرض ‪ :Viewport‬ي ر‬
‫شي إىل منطقة العرض عىل النافذة (الشاشة) ‪ ،‬ي‬
‫ّ‬
‫تتشوه‪ .‬يمكن معالجة هذا‬ ‫تصغيها يف أمثلة الجلسات السابقة نالحظ أن جميع األشكال سوف‬ ‫لتكبيها أو‬ ‫لو حاولنا سحب زاوية نافذة العرض‬
‫ر‬ ‫ر‬
‫تغيي الحجم (‪ ،)callback handler for re-sizing event‬والذي يمكن برمجته‬ ‫تعيي تابع اإلستجابة لحدث ر‬
‫التغيي يف حجم النوافذ عي ر‬
‫ر‬
‫لضبط منطقة التقليم ‪ (clipping) OpenGL‬لتكون متناسبة مع نسبة العرض إىل االرتفاع يف نافذة العرض )‪.(viewport‬‬

‫شكل ‪1‬‬

‫ثنائ األبعاد‪ .‬سيتم قطع الكائنات الموجودة خارج منطقة التقليم ولن‬
‫لتعيي منطقة التقليم أو القص يف الفضاء ي‬
‫ر‬ ‫يستخدم التابع ‪gluOrtho2D‬‬
‫يمكن رؤيتها‪.‬‬
‫)‪void gluOrtho2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top‬‬
‫‪// The default clipping area is (-1.0, 1.0, -1.0, 1.0) in OpenGL coordinates,‬‬
‫‪// i.e., 2x2 square centered at the origin.‬‬

‫التاىل‪:‬‬
‫لتعيي منطقة التقليم‪ ،‬نحتاج إىل سلسلة من األوامر عىل النحو ي‬
‫ر‬
‫ً‬
‫‪ -‬نختار أوال مصفوفة اإلسقاط‪glMatrixMode(GL_PROJECTION) ،‬‬
‫ّ‬
‫تعيي مصفوفة اإلسقاط إىل المصفوفة الواحدية‪glLoadIdentity() ،‬‬ ‫‪ -‬إعادة ر‬
‫ثنائ األبعاد مع منطقة القطع المرغوبة ‪ ،‬عيالتابع ‪.gluOrtho2D‬‬
‫‪ -‬ثم نختار النمط ي‬
// Set to 2D orthographic projection with the specified clipping area
glMatrixMode(GL_PROJECTION); // Select the Projection matrix for operation
glLoadIdentity(); // Reset Projection matrix
gluOrtho2D(-1.0, 1.0, -1.0, 1.0); // Set clipping area's left, right, bottom, top

‫ لتحديد أبعاد‬glViewport ‫ ويستخدم التابع‬،1‫ كما يف الشكل‬viewport ‫ عىل منفذ العرض‬clipping-area ‫يتم إسقاط منطقة التقليم‬
.‫منفذ العرض‬
void glViewport(GLint xTopLeft, GLint yTopLeft, GLsizei width, GLsizei height)

‫الكاميا مثل ضبط منطقة التقليم) ومصفوفة‬ ‫ر‬ ‫(الت تتعامل مع إسقاط‬
‫ ي‬projection ‫ مصفوفة اإلسقاط‬،‫مصفوفتي‬ ‫ر‬ ‫ عىل‬OpenGL ‫يحتوي‬
‫ ومن الواضح أنه إذا لم تكن نسبة العرض إىل االرتفاع‬،)‫المحىل إىل فضاء العالم‬
‫ي‬ ‫ (لتحويل الكائنات من الفضاء‬model-view ‫عرض النموذج‬
.‫ فستتشوه األشكال‬،‫لمنطقة التقليم وإطار العرض متطابقة‬

‫ لضمان تناسق نسبة العرض إىل االرتفاع ربي منطقة التقليم‬،‫ والذي يتم استدعاؤه كلما تغ رّي حجم النافذة‬،reshape ‫يمكن استخدام تابع‬
.‫ كما هو موضح يف المثال أعاله‬، ‫وإطار العرض‬

/* Handler for window re-size event. Called back when the window first appears and
whenever the window is re-sized with its new width and height */
void reshape(GLsizei width, GLsizei height) { // GLsizei for non-negative integer
// Compute aspect ratio of the new window
if (height == 0) height = 1; // To prevent divide by 0
GLfloat aspect = (GLfloat)width / (GLfloat)height;

// Set the viewport to cover the new window


glViewport(0, 0, width, height);
// try: glViewport(0, 0, width/2, height/2).

// Set the aspect ratio of the clipping area to match the viewport
glMatrixMode(GL_PROJECTION); // To operate on the Projection matrix
glLoadIdentity(); // Reset the projection matrix
if (width >= height) {
// aspect >= 1, set the height from -1 to 1, with larger width
gluOrtho2D(-1.0 * aspect, 1.0 * aspect, -1.0, 1.0);
} else {
// aspect < 1, set the width to -1 to 1, with larger height
gluOrtho2D(-1.0, 1.0, -1.0 / aspect, 1.0 / aspect);
}
}
:‫تغيي حجم نافذة العرض‬ ّ
‫ كتابع إستجابة لحدث ر‬reshape ‫عي التابع‬
‫ ن ر‬main ‫ضمن التابع‬
glutReshapeFunc(reshape); // Register callback handler for window re-size event

2
2 ‫شكل‬

‫ثنائ األبعاد‬
‫التحويالت يف الفضاء ي‬
Translation & Rotation ‫اإلزاحة والدوران‬
ّ
‫بتعيي كل شكل من األشكال عن طريق تحديد اإلحداثيات المطلقة للنقاط المشكلة لها ضمن إحداثيات فضاء‬ ‫ر‬ ‫يف األمثلة السابقة قمنا‬
.World-coordinate ‫العالم‬
ً
local-‫المحىل‬
‫ي‬ ‫ يمكن تعي ري كل شكل من األشكال عن طريق تحديد إحداثيات النقاط بما يتناسب مع مركزها ضمن الفضاء‬،‫بدال من ذلك‬
ّ
.‫الهندسية مثل اإلزاحة أو التدوير لوضع األشكال يف المواقع المطلوبة يف فضاء العالم‬ ‫ بعد ذلك يمكن استخدام التحويالت‬.coordinate
:‫المحىل‬
‫ي‬ ‫ وتحديد اإلحداثيات وفق الفضاء‬display ‫سوف نقوم بتعديل تابع الرسم‬
void display() {
glClear(GL_COLOR_BUFFER_BIT); // Clear the color buffer
glMatrixMode(GL_MODELVIEW); // To operate on Model-View matrix
glLoadIdentity(); // Reset the model-view matrix

glTranslatef(-0.5f, 0.4f, 0.0f); // Translate left and up


glBegin(GL_QUADS); // Each set of 4 vertices form a quad
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex2f(-0.3f, -0.3f); // Define vertices in counter-clockwise (CCW) order
glVertex2f( 0.3f, -0.3f); // so that the normal (front-face) is facing you
glVertex2f( 0.3f, 0.3f);
glVertex2f(-0.3f, 0.3f);
glEnd();

glTranslatef(0.1f, -0.7f, 0.0f); // Translate right and down


glBegin(GL_QUADS); // Each set of 4 vertices form a quad
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex2f(-0.3f, -0.3f);
glVertex2f( 0.3f, -0.3f);
glVertex2f( 0.3f, 0.3f);
glVertex2f(-0.3f, 0.3f);
glEnd();

glTranslatef(-0.3f, -0.2f, 0.0f); // Translate left and down


glBegin(GL_QUADS); // Each set of 4 vertices form a quad
glColor3f(0.2f, 0.2f, 0.2f); // Dark Gray
glVertex2f(-0.2f, -0.2f);
glColor3f(1.0f, 1.0f, 1.0f); // White
glVertex2f( 0.2f, -0.2f);

3
glColor3f(0.2f, 0.2f, 0.2f); // Dark Gray
glVertex2f( 0.2f, 0.2f);
glColor3f(1.0f, 1.0f, 1.0f); // White
glVertex2f(-0.2f, 0.2f);
glEnd();

glTranslatef(1.1f, 0.2f, 0.0f); // Translate right and up


glBegin(GL_TRIANGLES); // Each set of 3 vertices form a triangle
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex2f(-0.3f, -0.2f);
glVertex2f( 0.3f, -0.2f);
glVertex2f( 0.0f, 0.3f);
glEnd();

glTranslatef(0.2f, -0.3f, 0.0f); // Translate right and down


glRotatef(180.0f, 0.0f, 0.0f, 1.0f); // Rotate 180 degree
glBegin(GL_TRIANGLES); // Each set of 3 vertices form a triangle
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex2f(-0.3f, -0.2f);
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex2f( 0.3f, -0.2f);
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex2f( 0.0f, 0.3f);
glEnd();

glRotatef(-180.0f, 0.0f, 0.0f, 1.0f); // Undo previous rotate


glTranslatef(-0.1f, 1.0f, 0.0f); // Translate right and down
glBegin(GL_POLYGON); // The vertices form one closed polygon
glColor3f(1.0f, 1.0f, 0.0f); // Yellow
glVertex2f(-0.1f, -0.2f);
glVertex2f( 0.1f, -0.2f);
glVertex2f( 0.2f, 0.0f);
glVertex2f( 0.1f, 0.2f);
glVertex2f(-0.1f, 0.2f);
glVertex2f(-0.2f, 0.0f);
glEnd();

glFlush(); // Render now


}

model-space ( ‫المحىل‬ ّ ‫ والذي ي‬،model-transform ‫جزءا من تحويل النموذج‬


‫حول الكائنات من الفضاء‬ ً ‫تعتي تحويالت اإلزاحة والدوران‬
‫ي‬
model-view ‫بتعيي نمط المصفوفة إىل‬ ‫ر‬ ‫ نقوم‬،‫ إلجراء تحويل النموذج‬.world-space ‫) إىل فضاء العالم‬or local space
.)GL_MODELVIEW(

‫ ستستند‬،‫ أي بمجرد إزاحة اإلحداثيات أو تدويرها‬.‫تغييها‬


‫ تستمر قيمة الحالة حت يتم ر‬،‫تعيي حالة ما‬
‫ فبمجرد ر‬،‫ يعمل كآلة حالة‬OpenGL
.‫جميع العمليات الالحقة إىل هذه اإلحداثيات‬
:‫تابع اإلزاحة‬
void gltranslatef (GLfloat x, GLfloat y, GLfloat z)
// where (x, y, z) is the translational vector

.glBegin/glEnd ‫مت‬
‫ويجب أن يستدىع تابع اإلزاحة خارج تعلي ي‬
:‫تابع الدوران‬
void glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
// where angle specifies the rotation in degree, (x, y, z) forms the axis of rotation.

.OpenGl ‫تقاس الزوايا بالدرجات يف‬

4
‫المنحنيات ‪Curves‬‬
‫التاىل‪:‬‬ ‫ّ‬
‫الخطية كلما زادت دقة اإلنحناء‪ ،‬كما يف الشكل‬ ‫صغية‪ ،‬كلما زادت عدد المقاطع‬
‫ر‬ ‫المنحت بتجميع مقاطع خطوط‬ ‫ينتج الخط‬
‫ي‬ ‫ي‬

‫مثال رسم دائرة‪:‬‬

‫لتضمي مكتبة >‪#include <math.h‬‬


‫ر‬ ‫ّ‬
‫المثلثية ‪ ،sin/cos‬لذلك بحاجة‬ ‫القواني‬
‫ر‬ ‫سنقوم برسم دائرة باإلعتماد عىل عالقة ريا ّ‬
‫ضية تعتمد‬

‫{ )(‪void drawCircle‬‬
‫‪#define PI 3.14159265‬‬
‫‪#define EDGES 30 // try to increase and decrease the EDGES‬‬
‫‪#define factor 1‬‬

‫;)‪glClear(GL_COLOR_BUFFER_BIT‬‬

‫‪glColor3f(1.0f, 0.0f, 0.0f); // Red‬‬

‫{ )‪for (int i = 0; i < EDGES; i++‬‬


‫;)‪glBegin(GL_LINE_LOOP‬‬
‫;))‪glVertex2f(factor*cos((2*PI*i)/EDGES),factor*sin((2 * PI*i) / EDGES‬‬
‫;))‪glVertex2f(factor*cos((2 * PI*(i+1)) / EDGES), factor*sin((2 * PI*(i+1)) / EDGES‬‬
‫;)(‪glEnd‬‬
‫}‬

‫};)(‪glFlush‬‬

‫التاىل قبل البدء برسم الدائرة‪:‬‬


‫يمكن زيادة عرض الخط المستخدم لرسم الدائرة‪ ،‬بتفعيل األمر ي‬
‫;)‪glLineWidth(5.0‬‬

‫نماذج ملء المضلعات‬


‫ً‬ ‫ً‬
‫ترسم المضلعات افياضيا مليئة بنماذج مصمتة‪ ،‬لكن يمكن مثل استخدام نماذج ملء عبارة عن إطارات ‪.32bit * 32bit‬‬
‫التاىل لتحديد نموذج ملء‬
‫يستخدم األمر ي‬
‫;)‪void glPolygonStipple (const GLubyte * mask‬‬
‫ّ‬
‫الوسيط ‪ mask‬عبارة عن مؤ ّش إىل صورة بأبعاد ‪ 32*32 bit‬بقيم من األصفار والواحدات‪ ،‬القيمة ‪ 1‬تظهر كبكسل عىل الشاشة‪ ،‬أما القيمة ‪0‬‬
‫فال تعكس أي أثر عىل الشاشة‪.‬‬
‫عطل باستخدام األمر‪:‬‬‫ٌ ّ‬ ‫ي ّ‬
‫فعل نموذج الملء وي‬
‫)‪.glEnable(GL_POLYGON_STIPPLE)/ glDisable(GL_POLYGON_STIPPLE‬‬
‫التاىل كيفية بناء نموذج فراشة الستخدامه كقناع ملء‪:‬‬
‫ي‬ ‫ي ّربي الشكل‬

‫‪5‬‬
ً ّ ّ ‫ حيث يتم ملء عنارص المصفوفة اعتبا ًرا من الزاوية اليس‬،‫لتعريف القناع يتم بناء مصفوفة تقابل النموذج‬
‫السفلية للنموذج (يؤخذ سطرا‬ ‫ارية‬
ّ
.)‫العملية حت إنتهاء األسطر‬ ّ ً
‫التاىل وهكذا تتكرر‬
‫كامل من المربعات وبعد اإلنتهاء من السطر تتم العودة إىل بداية الزاوية اليسارية يف السطر ي‬
:‫الت تقابل نموذج الفراشة السابق‬
‫المصفوفة ي‬
GLubyte fly[] = { 0X00,0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00,
0X03,0X80, 0X01, 0XC0, 0X06, 0XC0, 0X03, 0X60,
0X04, 0X60, 0X06, 0X20, 0X04, 0X30, 0X0C, 0X20,
0X04, 0X18, 0X18, 0X20, 0X04, 0X0c, 0X30, 0X20,
0X04, 0X06, 0X60, 0X20, 0X44, 0X03, 0Xc0, 0X22,
0X44, 0X01, 0X80, 0X22, 0X44, 0X01, 0X80, 0X22,
0X44, 0X01, 0X80, 0X22, 0X44, 0X01, 0X80, 0X22,
0X44, 0X01, 0X80, 0X22, 0X44, 0X01, 0X80, 0X22,
0X66, 0X01, 0X80, 0X66, 0X33, 0X01, 0X80, 0Xcc,
0X19, 0X81, 0X81, 0X98, 0X0c, 0Xc1, 0X83, 0X30 };

‫مثال ملء مضلع بقناع الفراشة‬


ّ
:‫سنعرف تابع الرسم‬
static void drawRect(void)
{
GLubyte fly[] = { 0X00,0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00,
0X03,0X80, 0X01, 0XC0, 0X06, 0XC0, 0X03, 0X60,
0X04, 0X60, 0X06, 0X20, 0X04, 0X30, 0X0C, 0X20,
0X04, 0X18, 0X18, 0X20, 0X04, 0X0c, 0X30, 0X20,
0X04, 0X06, 0X60, 0X20, 0X44, 0X03, 0Xc0, 0X22,
0X44, 0X01, 0X80, 0X22, 0X44, 0X01, 0X80, 0X22,
0X44, 0X01, 0X80, 0X22, 0X44, 0X01, 0X80, 0X22,
0X44, 0X01, 0X80, 0X22, 0X44, 0X01, 0X80, 0X22,
0X66, 0X01, 0X80, 0X66, 0X33, 0X01, 0X80, 0Xcc,
0X19, 0X81, 0X81, 0X98, 0X0c, 0Xc1, 0X83, 0X30 };

GLubyte halftone[] = { 0XAA,0XAA, 0XAA, 0XAA, 0X55, 0X55, 0X55, 0X55,


0XAA,0XAA, 0XAA, 0XAA, 0X55, 0X55, 0X55, 0X55,
0XAA,0XAA, 0XAA, 0XAA, 0X55, 0X55, 0X55, 0X55,
0XAA,0XAA, 0XAA, 0XAA, 0X55, 0X55, 0X55, 0X55,

6
0XAA,0XAA, 0XAA, 0XAA, 0X55, 0X55, 0X55, 0X55,
0XAA,0XAA, 0XAA, 0XAA, 0X55, 0X55, 0X55, 0X55,
0XAA,0XAA, 0XAA, 0XAA, 0X55, 0X55, 0X55, 0X55,
0XAA,0XAA, 0XAA, 0XAA, 0X55, 0X55, 0X55, 0X55,
0XAA,0XAA, 0XAA, 0XAA, 0X55, 0X55, 0X55, 0X55,
0XAA,0XAA, 0XAA, 0XAA, 0X55, 0X55, 0X55, 0X55,
0XAA,0XAA, 0XAA, 0XAA, 0X55, 0X55, 0X55, 0X55,
0XAA,0XAA, 0XAA, 0XAA, 0X55, 0X55, 0X55, 0X55,
0XAA,0XAA, 0XAA, 0XAA, 0X55, 0X55, 0X55, 0X55

};

glClearColor(1.0, 1.0, 1.0, 0.0);


glClear(GL_COLOR_BUFFER_BIT );
glLoadIdentity();
glColor3f(0.0, 0.0, 0.0);
glTranslatef(5.0, 15.0, -40.0);
glRectf(-20.0, -20.0, -10.0, -10.0);

glEnable(GL_POLYGON_STIPPLE);
glPolygonStipple(fly);
glRectf(-10.0, -20.0, 0.0, -10.0);

glPolygonStipple(halftone);
glRectf(0.0, -20.0, 10.0, -10.0);

glDisable(GL_POLYGON_STIPPLE);
glFlush();
}

int main(int argc, char** argv)


{
glutInit(&argc, argv);
glutInitWindowPosition(100, 100);
glutInitWindowSize(400, 400);
glutCreateWindow("Draw rect");
glutDisplayFunc(drawRect);
glMatrixMode(GL_PROJECTION);
gluPerspective(45, 1.0, 10.0, 200.0);
glMatrixMode(GL_MODELVIEW);
glutMainLoop();
return 0;
}

... 3 ‫نهاية الجلسة‬

You might also like