ﺔﺠﻤﺭﺒﻠﻟ ﻲﺒﺭﻌﻟﺍ ﻕﻴﺭﻔﻟﺍ ﺕﺎﻴﺩﺘﻨﻤ ﻲﻓ ﺔﻤﺩﻘﻤ OpenGL ﺎﻴﻨﺍﺩ ﺔﺴﺩﻨﻬﻤ : ﻟﺍ ﺩﺍﺩﻋﺇ - ٢٠٠٥ ﺹ - ﻤﺤ ﺎﻴﺭﻭﺴ

Σχετικά έγγραφα
OpenGL. Εισαγωγή στην OpenGL Βασικά Γεωμετρικά Σχήματα Παράλληλη (ορθογραφική) προβολή. Μάθημα: Γραφικά Υπολογιστών και Εικονική Πραγματικότητα

Εμπορική αλληλογραφία Παραγγελία

Ακαδημαϊκός Λόγος Εισαγωγή

( ) ( ) ( ) ( ) ( )( ) z : = 4 = 1+ و C. z z a z b z c B ; A و و B ; A B', A' z B ' i 3

( D) .( ) ( ) ( ) ( ) ( ) ( ) الا سقاط M ( ) ( ) M على ( D) النقطة تعريف مع المستقيم الموازي للمستقيم على M ملاحظة: إذا آانت على أ- تعريف المستقيم ) (

( ) [ ] الدوران. M يحول r B و A ABC. 0 2 α فان C ABC ABC. r O α دورانا أو بالرمز. بالدوران r نكتب -* النقطة ' M إلى مثال لتكن أنشي 'A الجواب و 'B

قوانين التشكيل 9 الةي ر السام ظزري 11/12/2016 د. أسمهان خضور سنستعمل الرمز (T,E) عوضا عن قولنا إن T قانون تشكيل داخلي يعرف على المجموعة E

تصميم الدرس الدرس الخلاصة.

( ) ( ) ( ) ( ) v n ( ) ( ) ( ) = 2. 1 فان p. + r بحيث r = 2 M بحيث. n n u M. m بحيث. n n u = u q. 1 un A- تذآير. حسابية خاصية r

١٤ أغسطس ٢٠١٧ العمليات الحسابية الا ساسية مع الا شع ة ٢ ٥

( ) / ( ) ( ) على. لتكن F دالة أصلية للدالة f على. I الدالة الا صلية للدالة f على I والتي تنعدم في I a حيث و G دالة أصلية للدالة حيث F ملاحظات ملاحظات

Le travail et l'énergie potentielle.

X 1, X 2, X 3 0 ½ -1/4 55 X 3 S 3. PDF created with pdffactory Pro trial version

تمارين توازن جسم خاضع لقوتين الحل

Προγραμματισμός γραφικών

بحيث ان فانه عندما x x 0 < δ لدينا فان

با نها خماسية حيث: Q q الدخل. (Finite Automaton)

مادة الرياضيات 3AC أهم فقرات الدرس (1 تعريف : نعتبر لدينا. x y إذن

Εισαγωγή στην OpenGL

[ ] [ ] ( ) ( ) ( ) ( ) ( ) I و O B بالنسبة ل AC) ( IO) ( بالنسبة C و S M M 1 -أنشطة: ليكن ABCD معين مرآزه O و I و J منتصفي

-1 المعادلة x. cosx. x = 2 M. و π. π π. π π. π π. حيث π. cos x = إذن حيث. 5π π π 5π. ] [ 0;π حيث { } { }

أسئلة استرشادية لنهاية الفصل الدراسي الثاني في مادة الميكانيكا للصف الثاني الثانوي العلمي للعام الدراسي

() 1. ( t) ( ) U du RC RC dt. t A Be E Ee E e U = E = 12V ن ن = + =A ن 1 RC. τ = RC = ن

Tronc CS Calcul trigonométrique Cours complet : Cr1A Page : 1/6

- سلسلة -2. f ( x)= 2+ln x ثم اعط تأويل هندسيا لهاتين النتيجتين. ) 2 ثم استنتج تغيرات الدالة مع محور الفاصيل. ) 0,5

الموافقة : v = 100m v(t)

( ) ( ) ( ) - I أنشطة تمرين 4. و لتكن f تمرين 2 لتكن 1- زوجية دالة لكل تمرين 3 لتكن. g g. = x+ x مصغورة بالعدد 2 على I تذآير و اضافات دالة زوجية

Εισαγωγή στην OpenGL

ﻉﻭﻨ ﻥﻤ ﺔﺠﻤﺩﻤﻟﺍ ﺎﻴﺠﻭﻟﻭﺒﻭﺘﻟﺍ

( ) تعريف. الزوج α أنشطة. لتكن ) α ملاحظة خاصية 4 -الصمود ليكن خاصية. تمرين حدد α و β حيث G مرجح

ءﺎﺼﺣﻹا ﻒﻳرﺎﻌﺗ و تﺎﺤﻠﻄﺼﻣ - I

1/ الزوايا: المتت امة المتكاملة المتجاورة

( ) ( ) ( ) = ( 1)( 2)( 3)( 4) ( ) C f. f x = x+ A الا نشطة تمرين 1 تمرين تمرين = f x x x د - تمرين 4. نعتبر f x x x x x تعريف.

- سلسلة -3 ترين : 1 حل التمرين : 1 [ 0,+ [ f ( x)=ln( x+1+ x 2 +2 x) بما يلي : وليكن (C) منحناها في معلم متعامد ممنظم

المواضيع ذات أهمية بالغة في بعض فروع الهندسة كالهندسة الكهربائية و الميكانيكية. (كالصواريخ و الطائرات و السفن و غيرها) يحافظ على إستقرار

حركة دوران جسم صلب حول محور ثابت

الا شتقاق و تطبيقاته

األستاذ: بنموسى محمد ثانوية: عمر بن عبد العزيز المستوى: 1 علوم رياضية

( ) ( ) ( ) ( ) تمرين 03 : أ- أنشيء. ب- أحسب ) x f ( بدلالة. ب- أحسب ) x g ( تعريف : 1 = x. 1 = x = + x 2 = + من x بحيث : لتكن لكل. لكل x من.

تمرين 1. f و. 2 f x الجواب. ليكن x إذن. 2 2x + 1 لدينا 4 = 1 2 أ - نتمم الجدول. g( x) ليكن إذن

أسئلة استرشادية لنهاية الفصل الدراسي الثاني في مادة الحاسوب للصف السابع للعام الدراسي

Business عزيزي السيد الري يس سيدي المحترم سيدتي المحترمة سيدي المحترم \ سيدتي المحترمة السادة المحترمون ا لى م ن يهم ه الا مر عزيزي السيد ا حمد

Η Βιβλιοθήκη Γραφικών OpenGl Με Χρήση C/C++, JAVA και PYTHON

ﺔﻴﻭﻀﻌﻟﺍ ﺕﺎﺒﻜﺭﻤﻟﺍ ﻥﻴﺒ ﺕﻼﻴﻭﺤﺘﻟﺍ لﻭﺤ ﺔﻴﺯﻴﺯﻌﺘ ﺔﻗﺎﻁﺒ

)الجزء األول( محتوى الدرس الددراتالمنتظرة

بحيث = x k إذن : a إذن : أي : أي :

( ) ( ) [ [ ( ) ( ) ( ) =sin2xcosx ( ) lim. lim. α; ] x حيث. = x. x x نشاط 3 أ- تعريف لتكن. x نهاية l في x 0 ونرمز لها ب ب- خاصية نهاية على اليمين في

تصحيح تمارين تطبيقات توازن جسم صلب خاضع لقوتين

يط... األعداد المركبة هذه التمارين مقترحة من دورات البكالوريا من 8002 إلى التمرين 0: دورة جوان 8009 الموضوع األول التمرين 8: دورة جوان

Samer-3. قياس المسافات الافقية :Measurements of Horizontal Distances. .3 التاكيومتري :Tacheometry ا. stadia الستيديا. D δ = δ


الوحدة 02. GUEZOURI A. Lycée Maraval - Oran الدرس 2 الطاقة الحرآي ة. F r ( ) W F = F ABcosθ عمل. F r محر ك عمل مقاوم

المادة المستوى المو سسة والكيمياء الفيزياء تمارة = C ت.ع : éq éq ] éq ph

**********************************************************************************

Plus DVB-T ا و DVB-C HDTV Satellite Receiver TEST REPORT وحدة التحكم فى اليد كما يوجد عدد 2 فتحة لا دخال الكامات بمختلف

( ) ( ) ( OPMQ) ( ) المستقيم في المستوى 1- معلم إحداثيتا نقطة و و ( ) أفصول و. y أآتب الشكل مسقط M على ) OI (

Εισαγωγή στην OpenGL: μέρος 1ο

********************************************************************************** A B

א א א א א توافق الزاوية 1 و 2 توافقها اللحظة.

Contents مقدمة. iii. vii. xxi

Προσωπική Αλληλογραφία Επιστολή

Γραφικά Υπολογιστών: OpenGL

Εισαγωγή στην OpenGL: μέρος 2ο

Immigration Studying ا ود التسجيل في الجامعة. ا ود التقدم لحضور مقرر. ما قبل التخرج ما بعد التخرج دكتوراه بدوام كامل بدوام جزي ي على الا نترنت

التمرين الثاني )3 2-( نعتبر في المستوى المنسوب إلى معلم متعامد ممنظم التي معادلتها : 3-( بين أن المستوى مماس للفلكة في النقطة.

dθ dt ds dt θ θ v a N dv a T dv dt v = rθ ɺ

الجزء الثاني: "جسد المسيح الواحد" "الجسد الواحد )الكنيسة(" = "جماعة المؤمنين".

مثال: إذا كان لديك الجدول التالي والذي يوضح ثلاث منحنيات سواء مختلفة من سلعتين X و Yوالتي تعطي المستهلك نفس القدر من الا شباع

الوحدة 04 الدرس الشكل - 2. E pp. E : Energie, p : potentielle, p : (de) pesanteur. P r. F r. r P. z A إلى. z B. cb ca AB AB

التاسعة أساسي رياضيات

التفسير الهندسي للمشتقة

عرض المنشأة في األجل القصير الفصل العاشر

( ) ( ) 27,5.10 1,35.10 = 5, = 0,3. n C V mol ( ) M NaHCO max. n( CO ) n CO. 2 exp 2. Page 1

الوحدة 05. uuur dog dt. r v= uuur r r r الدرس الا ول. uuur. uuur. r j. G (t) المسار. GUEZOURI Aek lycée Maraval - Oran

Isomorphism-invariants and their applications in testing for isomorphism between finitely presented groups

Μετανάστευση Έγγραφα ا ين يمكنني ا يجاد استمارة ل ا ين تم ا صدار [مستند] الخاص متى تنتهي صلاحية هويتك هل يمكنك مساعدتي في ملء الاستمارة

رباعيات األضالع سابعة أساسي. [

Personal عزيزي فادي ا بي العزيز \ ا مي العزيزة خالي \ عمي كمال العزيز مرحبا يا فادي ا هلا يا فادي فادي عزيزي \ عزيزتي

OpenGL. Εισαγωγή. Εξάμηνο: 2014Β. Διδάσκουσα: Κανελλοπούλου Χριστίνα_ΠΕ19 Πληροφορικής Ηλεκτρονική Τάξη:

Γραφικά Υπολογιστών. Τμήμα Μηχανικών Πληροφορικής ΤΕΙ Ανατολικής Μακεδονίας και Θράκης. Γραφικά Υπολογιστών ΣΤ Εξάμηνο. Δρ Κωνσταντίνος Δεμερτζής

PDF created with pdffactory Pro trial version

ﻩﺫﻴﻔﻨﺘﻭ S RM (6/8) ﺓ ﺭ ﻤ ﻴﻐﺘ ﺔﻴﺴ ﺎ ﻴﻁ ﻨﻐﻤ ﺔﻤ ﻭﺎﻘﻤ ﻱﺫ ﻙﺭﺤﻤ ﺓﺩﺎﻴﻘﻟ ﻡﺎﻅﻨ ﻡﻴﻤﺼﺘ ﺏﻭﺴﺎﺤﻟﺍ ﻡﺍﺩﺨﺘﺴﺎﺒ

ثناي ي القطبRL (V ) I (A) 0,1 0,2 0,3 0,4 0,5 0,6

إفراد الكانات المربعة والمستطيلة والدائرية بدايته شكل 1.تستعمل الكانات في حديد التسليح للمنشآت الخرسانية والا بنية.

نصيحة لك أخي الطالب كما يمكنك تحميل النسخة بدون حلول "اضغط هنا" ملاحظة هامة

المتغير الربيعي التباين نسبي والتفرطح المعياري

2,9 3,5 اختبار الثلاثي الثاني في مادة مدینة علي منجلي - قسنطینة I- دراسة عملیة الشحن :

البرنامج هو سلسلة متتالية من التعليمات يمكننا تشبيهها بوصفة إعداد وجبة غذائية, نوتة موسيقية أو

الكتاب الثاني الوحدة 07. q q (t) dq R dq q الدرس الثاني : الاهتزازات الكهرباي ية الدرس حالة تفريغ المكث فة. (2) عند. t = 0 اللحظة.

مقدمة: التحليل الخاص باإلنتاج والتكاليف يجيب عن األسئلة المتعلقة باإلنتاج الكميات المنتجة واألرباح وما إلى ذلك.

: : 03 التطورات . ( u BD. 5 τ u ( V ) t ( s ) t ( s ) C ) 0.2. t ( ms )

du R d uc L dt إذن: u L duc d u dt dt d q q o O 2 tc

Κεφάλαιο 2 ο Είσοδος/Έξοδος ιαχείριση γεγονότων - Αποκοπή στις δύο διαστάσεις

المستوى المادة مسلك والكيمياء الفيزياء المو سسة تمارة + + éq 3 éq= xéq. x m. m = CV x. Q r [ RCOOH] RCOOH

الميكانيك. d t. v m = **********************************************************************************

تصحيح موضوع العلوم الفيزياي ية : شعبة العلوم التجريبية والعلوم والتكنولوجيات الكيمياء : المحلول الماي ي لحمض الميثامويك العمود قصدير فضة

PDF created with pdffactory Pro trial version

OH H O CH 3 CH 2 O C 2 H a = - 2 m/s 2. 2 gr(1 cos θ) max 1/5

أولا: ضع إشارة ) ( أمام اإلجابة األنسب فيما يلي:

استثمار تسجيلات لحساب السرعة اللحظية. التعبير عن الحركة المستقيمية المنتظمة بمعادلة زمنية في شروط بدي ية مختلفة.

Transcript:

منتديات الفريق العربي للبرمجة مقدمة في OpenGL ا عداد : المهندسة دانيا سوريا-حمص- ٢٠٠٥

الفصل الا ول تعريف بمكتبة ال OpenGL مقدمة: لقد شكلت هذه المكتبة قاعدة ضخمة في مجال الرسوميات منذ وقت ليس بالقصير وتعتبر حتى الا ن النواة الا ساسية لبناء مكتبات رسومية ا كثر غنى وتنوعا كما تو من هذه المكتبة الكثير من التوابع الرسومية التي تمكن المبرمج من بناء ا ي تصميم رسومي خاص بتطبيقه البرمجي سواء كان لعبة تحتاج ا لى ا مكانيات بيانية ضخمة ا و برامج هندسية تحتاج ا لى توابع خاصة وهامة. كما ا نها مصممة بحيث يمكنها ا ن تعمل ضمن ا ي عتاد و في ا ي نظام عرض بياني لذلك فهي تمتلك العديد من الخصاي ص التي جعلتها من ا هم وا قوى المكتبات البيانية في العالم. تساعد هذه المكتبة على ا نشاء صور ذات نماذج هندسية بسيطة كما تزود مستخدميها بتوابع غاية في الا همية للتحكم بالا لوان والا ضاءة والظلال والضبابية بالا ضافة ا لى ا مكانية ا خفاء السطوح (عند تراكب الا شكال) و ا ظهار الحواف الناعمة والخشنة في الصورة لا عطاي ها شكلا يشبه شكلها الحقيقي وسندرس هذه المواضيع بشكل مفصل لاحقا. ا ما من الناحية الحركية فهي تمتلك توابع خاصة تستخدم في التطبيقات ثلاثية الا بعاد لا عطاء هذه التطبيقات المظهر الحركي. ولكن ال OpenGL غير قادرة على توفير الا غراض والكاي نات الرسومية ثلاثية الا بعاد كالسيارات جسم الا نسان الجزيي ات...الخ وا نما يتم تمثيل الكاي نات ثلاثية الا بعاد باستخدام خطوط منفصلة تتصل مع بعضها لا نشاء النموذج. كما ا نها غير قادرة على فتح نوافذ في تطبيقاتها ولا ا نشاء تطبيقات تتفاعل بمرونة مع المستخدم Applications) (Interactive بحيث تكون قادرة على الاستجابة للا حداث الخارجية. وقد تم التغلب على هذه المشاكل باستخدام المكتبة الخدمي ة ٢. (GLUT) ١ GLU) ( ومجموعة ا جراي يات مسبقة التعريف المكتبة الخدمية : GLU تستخدم داي ما مع مكتبة ال OpenGL وهي توفر ميزات النمذجة حيث تستخدم العناصر الا ساسية للرسم التي توفرها ال OpenGL كالخطوط المستقيمة والمنحنيات...الخ من الا شكال الهندسية البسيطة ومن ثم تنشي علاقة بين هذه الا جسام في الفراغ ثناي ي البعد ا و ثلاثي البعد كما ا نها توفر بعض الا شكال ثلاثية البعد. مجموعة ا جراي يات مسبقة التعريف : GLUT وهي التي توفر ا مكانية جعل التطبيقات الرسومية تفاعلية مع المستخدم من خلال تقديم ا جراي يات تستجيب لا ي حدث خارجي كا حداث لوحة المفاتيح (ضغط زر المكتبة الخدمیة : Library The OpenGL Utility إجراي یات مسبقة التعریف : Toolkit The OpenGL Utility 1 2

مثلا ) وا حداث الفا رة over,..) (Click,Double Click,Mouse ا ضافة ا لى توفير القدرة على ا نشاء وفتح عدة نوافذ في هذه التطبيقات Forms).(Multi كما تزود مستخدميها بالعديد من الا شكال والكاي نات ثلاثية الا بعاد دون الحاجة ا لى تمثيلها باستخدام الخطوط المستقيمة العديدة وهي الطريقة التي كانت تستخدمها مكتبة ال OpenGL وهي طريقة معقدة وخاصة عندما يكون المشهد يحتوي العديد من الا شكال ثلاثية البعد وسنذكر على سبيل المثال بعض الا شكال التي يمكن استخدامها مباشرة كجسم كروي حلقة ا بريق الشاي...الخ. هذه المكتبة مكتوبة بلغة C مما يعطي هذه المكتبة ميزة ا ضافية تحتاجها ا ي مكتبة رسومية وهي سرعة ا نجاز الرسوم وتحريكها حيث من المعروف ا ن لغة C من اللغات التي تتعامل مع لغة الا لة التي يفهمها ا ي معالج بطريقة سريعة للغاية ولذلك نحتاج عند التعامل معها ا لى تضمين الملفات الخاصة بها وتسمى هذه الملفات بالملفات الرا سية ا و ملفات الترويسة.Header Files الملفات الرا سية الواجب تضمينها في التطبيق: في التطبيقات الرسومية التي تستخدم ال OpenGL يجب ا ن يضم ن الملف الخاص بهذه المكتبة وهو gl.h وبما ا ن المكتبتين GLU و GLUT تستخدمان داي ما مع المكتبة OpenGl فبالتالي يجب تضمين الملفات الرا سية لهما ا يضا و هما glut.h glu.h على الترتيب. مثال ١ : سنعرض الا ن الهيكل العام للتطبيق الذي يستخدم مكتبة ال OpenGL وهذا التطبيق يعرض شكل هندسي بسيط وهو مستطيل باللون الا بيض مع خلفية سوداء. Example 1-1 : White Rectangle on a Black Background #include <whateveryouneed.h> main() ملف الترويسة InitializeAWindowPlease(); glclearcolor (0.0, 0.0, 0.0, 0.0); glclear (GL_COLOR_BUFFER_BIT); glcolor3f (1.0, 1.0, 1.0); glortho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0); glbegin(gl_polygon); glvertex3f (0.25, 0.25, 0.0); glvertex3f (0.75, 0.25, 0.0); glvertex3f (0.75, 0.75, 0.0); glvertex3f (0.25, 0.75, 0.0); glend(); glflush(); UpdateTheWindowAndCheckForEvents();

السطر الا ول من هذا التطبيق هو ال ) main( وهي ترويسة الا جراي ية الري يسية والتي تتضمن استدعاء للا جراي ية InitializeAWindowPlease() المسو ولة عن عملية تهيي ة النافذة من ا نشاء للنافذة الا ساسية والنوافذ الجزي ية و تحديد موقع النافذة على الشاشة وحجم وعنوان للنافذة وسيتم تفصيل كل من هذه التعليمات لاحقا. ا ما التعليمات التي تلي استدعاء هذه الا جراي ية فهي تعليمات ال OpenGl وهي : ١. glclearcolor() : تحديد لون مسح النافذة وهنا تم تحديد اللون الا سود. ٢. glclear() : تنفيذ عملية المسح الفعلية وكلما تستدعى هذه التعليمة يتم مسح النافذة. ٣. glcolor3f() : تحديد لون خط الرسم وفي هذا التطبيق تم اختيار اللون الا بيض. ٤. glortho() : تخصيص نظام ا حداثيات مناسب يستخدم لرسم الشكل وبحسب نظام الا حداثيات تحدد ا حداثيات الرسمة التي ستظهر على النافذة فمثلا في المثال السابق تم تحديد نظام الا حداثيات ضمن المجال [ ٠,٠ ٠,١ ]بالنسبة للX وبالمثل بالنسبة لY ا ما بالنسبة للا حداثيين الا خيرين [-١,٠ ١,٠] فهما خاصين بمجال الا حداثي Z. ٥. glbegin() : glend() يكتب ضمنهما تعليمات رسم الشكل المطلوب وفي هذا المثال تم رسم مضلع با ربع حواف. ٦. glvertex3f() : وهي تعليمة رسم نقطة بشكل عام وقد استخدمت هنا لتحديد الزوايا الا ربعة للمضلع وتمثل البارمترات الممررة لهذه التعليمة الا حداثيات z y x مع ملاحظة ا ن قيم ال y x ضمن المجال [0,1] للتناسب مع نظام الا حداثيات المستخدم والذي تم تحديده سابقا في حين ا ن قيمة البارمتر الثالث والذي يمثل الا حداثي z قيمته = ٠ لا ننا الا ن لا نهتم بالبعد الثالث. ٧. glflush() : وهي التعليمة الا خيرة المسو ولة عن ا ظهار الشكل ضمن النافذة بشكل فعلي لا ن النقاط التي تم تعيينها سابقا وضعت ضمن مخزن مو ق ت دفعة واحدة على النافذة. ٣ ريثما يتم ا ظهارها وا خيرا يتم استدعاء الا جراي ية UpdateTheWindowAndCheckForEvents() وتتضمن العمليات المتعلقة بالا حداث والتي تجعل التطبيق البياني قادر على تلقي الا وامر من المستخدم. ملاحظة: هناك اجراي يتين هما : InitializeAWindowPlease() UpdateTheWindowAndCheckForEvents() 3 مخزن مو قت buffer:

هاتان الا جراي يتان ليستا من مكتبة ال OpenGl لا ننا سبق وذكرنا ا ن ال OpenGl غير قادرة على ا نشاء وتهيي ة نوافذ في التطبيقات الرسومية وكذلك ذكرنا ا نها غير قادرة على جعل التطبيقات تفاعلية بحيث تتلاقى الا حداث من المستخدم و بالتالي فا ن التعليمات التي تتضمنها هاتين الا جراي يتين من مكتبة ال GLUT وهي المسو ولة عن ا نجاز هذه العمليات كما ذكر ا نفا.

القواعد التي تحكم تعليمات مكتبة ال :OpenGL من خلال المثال السابق نلاحظ ما يلي: ١- جميع تعليمات ال OpenGL تبدا بالحرفين gl ثم يكتب الحرف الا ول من التعليمة بحرف كبير. ٢- عندما تتا لف التعليمة من ا كثر من كلمة فا ن كل كلمة تبدا بحرف كبير ا يضا. ٣- ا ما الثوابت فتبدا بالحرفين GL_ ويتبعها المحرف السفلي ) _ ( وغالبا ما تتا لف الثوابت من عدة مقاطع بحيث تكون جميع الا حرف كبيرة ويفصل بين كل المقاطع بالمحرف السفلي كما في الثابت GL_POLYGON الذي يمرر للتعليمة glbegin() لتحديد الشكل الذي سيتم رسمه و في مثالنا هو مضلع GL_COLOR_BUFFER_BIT وهو الثابت الذي يمرر للا جراي ية. glclear() -٤ كما يمكن ملاحظة وجود ا حرف و ا رقام ا ضافية على التعليمات مثل (3f) كما في التعليمة glcolor3f() glvertex3f() حيث من الواضح لدينا ا نه في تعليمة تحديد اللون كان يكفي ا ن تكون التعليمة عبارة عن كلمة color ولكن هناك عدة ا شكال لهذه التعليمة. تتميز كل تعليمة عن الباقي بعدد الوسطاء الممررة لها ونوعها وهو ما يظهر في اسم التعليمة (في مثالنا السابق ٣ ) ففي مثالنا السابق يظهر الحرف f الذي يشير هنا ا لى ا ن الوسطاء الممرة للتابع هي ا رقام ذات فواصل عشرية ) المحرف f اختصار ل (float. تقبل ال OpenGL ثمانية ا نماط لوسطاي ها (متحولات دخل التابع) والتي ستوضح في الجدول : Suffix Data Type Typical Corresponding C- Language Type OpenGL Definition Type b 8-bit integer signed char Glbyte s 16-bit integer Short Glshort i 32-bit integer int or long GLint, Glsizei f 32-bit floatingpoint d 64-bit floatingpoint ub 8-bit unsigned integer Float Double unsigned char GLfloat, Glclampf GLdouble, Glclampd GLubyte, Glboolean

us 16-bit unsigned integer unsigned short Glushort ui 32-bit unsigned integer unsigned int or unsigned long GLuint, GLenum, Glbitfield فمثلا التعليمتين (3 glvertex2i(1, glvertex2f(1.0, (3.0 لهما نفس العمل ولكن ما يختلفان به هو نوع الوسطاء الممررة فالا ولى نوع وسطاي ها هو integer ا ما الثانية فهو. float بالا ضافة ا لى ا نه توجد تعليمات يمكن ا ن تنتهي باللاحقة v حيث يشير هذا المحرف ا ن الوسيط الممرر للتعليمة عبارة عن شعاع ا و مصفوفة. مثال: glcolor3f(1.0, 0.0, 0.0); GLfloat color_array[] = 1.0, 0.0, 0.0; glcolor3fv(color_array); ا دارة النافذة:.١ تقوم مكتبة ال GLUT بعمليات الا دارة التي تتعلق بالنوافذ من ا نشاء وتهيي ة الحجم والموقع وهناك خمسة تعليمات تستخدم بشكل ا ساسي لا تمام هذا العمل وهذه التعليمات هي : : glutinit(int *argc, char **argv) ال GLUT مع الا خذ بعين الاعتبار للوسطاء التي تو خذ من محرر الا وامر تابع يستخدم لتهيي ة مكتبة ٤. mode) : glutinitdisplaymode(unsigned int تابع لا عداد وضع الشاشة الابتداي ي ودقة ال Buffer المستخدم وتحديد نظام الا لوان المستخدم هل RGBA ا و color-index وقد تستدعى هذه التعليمة بالا سلوب التالي: glutinitdisplaymode (GLUT_SINGLE GLUT_RGB) و تتغي ر هذه الثوابت بحسب طبيعة التطبيق الرسومي فا ذا كان التطبيق عبارة عن ا شكال ساكنة وغير متحركة فا ننا نستخدم الثابت GLUT_SINGLE ولكن عندما تكون الا شكال متحركة عندها يتوجب استخدام الثابت. GLUT_DOUBLE.٢ 4 محرر الا وامر: Command Line

y) : glutinitwindowposition(int x, int وهو تابع مسو ول عن تحديد مكان ظهور النافذة ا مام المستخدم عند تشغيل التطبيق. size) glutinitwindowsize(int width, int :وهو تابع مسو ول عن تحديد حجم نافذة التطبيق. *string) int glutcreatewindow(char :وهو تابع مسو ول عن ا نشاء النافذة التي سيظهر ضمنها الا شكال الرسومية وتعيد رقم للنافذة التي تم ا نشاو ها والذي سنستفيد منه لاحقا ا ما الوسيط الممر لها فهو عبارة عن العنوان الذي سيظهر في را س النافذة..٣.٤.٥ ٦. glutmainloop() :وهو تابع للدخول في حلقة معالجة الا حداث في GLUT بعد الانتهاء من التهيي ة. ا ن الا جراي ية InitializeAWindowPlease() التي تم ذكرها سابقا هي التي تضم تعليمات ا دارة النافذة ا ما فيما يتعلق بتعليمات الا جراي ية UpdateTheWindowAndCheckForEvents() فهي التعليمات المسو ولة عن الاستجابة للا حداث التي تصدر عن المستخدم وهذه الا حداث مصدرها الفا رة ا و لوحة المفاتيح...الخ. وسيتم شرح تعليمات هذه الا جراي ية في الفصل القادم. ا جراي ية العرض وا ظهار الا شكال: ذكرنا ا ن المثال السابق يقوم با ظهار مضلع وقد را ينا ا ن تعليمات رسم المضلع توضع ضمن تعليمتي glbegin() و() glend ولكن المكان الذي تم وضع التعليمات فيه غير صحيح حيث تم وضع كتلة التعليمات هذه مباشرة في ا جراي ية ال main الري يسية ولكن تخيل ا نك تريد رسم ا كثر من شكل وا كثر من مشهد فمن غير المنطقي وضع كل تعليمات الرسم مباشرة ضمن الا جراي ية الري يسية وا نما يجب وضعهم ضمن ا جراي ية خاصة بالعرض بحيث يتم استدعاو ها لاحقا. ولكن ستختلف هنا طريقة الاستدعاء عما كنت قد تعلمته في اللغات البرمجية الا خرى حيث لا تستدعى ا جراي ية العرض باسمها مباشرة وا نما تستخدم الا جراي ية التالية لاستدعاء ا جراي ية العرض: glutdisplayfunc(void*func (void)) حيث يمرر له كوسيط اسم ا جراي ية العرض التي تم وضع كتلة الرسم فيها مع ملاحظة ا ن هذه الا جراي ية يجب ا ن تكون بدون وسطاء. وتستدعى هذه التعليمة للمرة الا ولى في ال main ويمكن استدعاو ها عند الحاجة لا عادة الرسم. سنلاحظ لاحقا ا ن هذا الا سلوب سيستخدم كثيرا في استدعاء العديد من الا جراي يات.

ا جراي ية ا عادة رسم شاشة الا ظهار: تستدعى هذه الا جراي ية من ا جل ا عادة رسم شاشة الا ظهار وذلك في عدة حالات هي : ١- بعد ا نشاء نافذة الا ظهار مباشرة وقبل استدعاء ا جراي ية العرض. ٢- عند تغيير حجم النافذة بتكبيرها ا و تصغيرها. ٣- عند تغيير موقع النافذة بتحريكها من مكانها. تستدعى في الا جراي ية main بالشكل التالي : glutreshapefunc(void*func (int h, int w)); حيث تتتبع الا جراي ية glutreshapefunc الحالات السابقة وبمجرد حدوث ا حدها تستدعي ا جراي ية ا عادة الرسم وعلى الرغم من وجود وسيطين لا جراي ية ا عادة الرسم ا لا ا نهما لا يمرران لها عند استدعاي ها بالشكل السابق. فلو اعتبرنا ا ن اسم ا جراي ية ا عادة الرسم Reshape عندها تستدعى في ال main بالشكل التالي : glutreshapefunc(reshape); ا ما جسم الا جراي ية Reshape فيتضمن مجموعة تعليمات متعلقة بنظام الا حداثيات المستخدم ا نواع التحويلات المراد استخدامها في التطبيق والتي سنتعرف عليها لاحقا.

. مثال ٢ : سنعيد كتابة المثال السابق باستخدام الشكل النظامي والصحيح لاستدعاء ا جراي ية العرض وتهيي ة النافذة Example 1-2 : White Rectangle on a Black Background #include <GL/gl.h> #include <GL/glut.h> void display(void) /* clear all pixels */ glclear (GL_COLOR_BUFFER_BIT); /* draw white polygon (rectangle) with corners at * (0.25, 0.25, 0.0) and (0.75, 0.75, 0.0) */ glcolor3f (1.0, 1.0, 1.0); glbegin(gl_polygon); glvertex3f (0.25, 0.25, 0.0); glvertex3f (0.75, 0.25, 0.0); glvertex3f (0.75, 0.75, 0.0); glvertex3f (0.25, 0.75, 0.0); glend(); /* don't wait! * start processing buffered OpenGL routines */ glflush (); void init (void) /* select clearing (background) color */ glclearcolor (0.0, 0.0, 0.0, 0.0); void reshape(int w, int h) glmatrixmode(gl_modelview); glloadidentity(); /* clear the matrix */ glortho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0); /* * Declare initial window size, position, and display mode * (single buffer and RGBA). Open window with "hello" * in its title bar. Call initialization routines. * sets the reshape callback for the current window. * Register callback function to display graphics. * Enter main loop and process events. */ void main(int argc, char** argv) glutinit(&argc, argv); glutinitdisplaymode (GLUT_SINGLE GLUT_RGB); glutinitwindowsize (250, 250); glutinitwindowposition (100, 100); glutcreatewindow ("hello"); init (); glutreshapefunc(reshape); glutdisplayfunc(display); glutmainloop();

مثال عملي: سنقوم الا ن بتنفيذ خوارزمية DDA لرسم الخط المستقيم باستخدام ال : OpenGL Example 1-3 : Algorithim DDA with OpenGL #include "stdafx.h" #include <GL/gl.h> #include <GL/glut.h> void linedda () glcolor3f (1.0, 1.0, 1.0); int xa, int ya, int xb, int yb; xa = 0 ya = 0 xb = 50 yb = 50; int dx = xb - xa, dy = yb ya; int steps, k; float xincr, yincr, x = xa, y = ya; if (abs(dx)>abs(dy)) steps = abs(dx); else steps = abs(dy); xincr = dx / (float) steps; yincr = dy / (float) steps; glbegin(gl_points) ; glvertex2i (x, y);//as drawpixel (ROUND(x), ROUND(y)) for (k=0; k<steps; k++) x += xincr; y += yincr; glvertex2i (x, y);//as drawpixel (ROUND(x), ROUND(y)) glend(); glflush(); void init(void) /* select clearing (background) color */ glclearcolor (0.0, 0.0, 0.0, 0.0); glclear (GL_COLOR_BUFFER_BIT); /* initialize viewing values */ glmatrixmode(gl_projection); glloadidentity(); glortho(0.0, 100, 0.0, 100, -1.0, 1.0); void main(int argc, char** argv) glutinit(&argc, argv); glutinitdisplaymode (GLUT_SINGLE GLUT_RGB); glutinitwindowsize (400, 400); glutinitwindowposition (100, 100); glutcreatewindow ("linedda"); init(); glutdisplayfunc(linedda); glutmainloop();

لاحظ ا ن الثابت الممرر للتعليمة glbegin لم يكن GL_POLYGON وا نما ثابت ا خر هو GL_POINTS وعندها سيتم رسم نقاط فقط ولكن هذه النقاط ستشكل في النهاية خط مستقيم بحسب خوارزمية. DDA هناك العديد من الثوابت التي يمكن ا ن تمرر ا يضا والتي يظهر نتيجة لها ا شكال هندسية مختلفة وهي على سبيل المثال : ماذا يعني ا ظهار مجموعة نقاط منفصلة عن بعضها يتم الوصل بين كل نقطتين متتاليتين لا ظهار خط مستقيم ا ظهار مجموعة خطوط مستقيم متصلة مع بعضها ا ظهار مجموعة خطوط مستقيمة متصلة مع بعضها مع وصل النقطة الا ولى بالا خيرة وا ظهار شكل مغلق. الثابت GL_POINTS GL_LINES GL_LINE_STRIP GL_LINE_LOOP GL_TRIANGLES ا ظهار مثلث ا و ا كثر منفصلة عن بعضها بحيث كل ٣ نقاط تشكل مثلث. GL_TRIANGLE_STRIP ا ظهار مجموعة مثلثات ملتصقة مع بعضها GL_TRIANGLE_FAN GL_QUADS GL_QUAD_STRIP GL_POLYGON ا ظهار مجموعة مثلثات تتصل مع بعضها برا س وضلع ا ظهار شبه منحرف ا و ا كثر منفصلة عن بعضها مجموعة ا شباه منحرفة ملتصقة مع بعضها ا ظهار مضلع ما

وسنستعرض الا شكال الناتجة عن كل ثابت :

الفصل الا ول تعريف بمكتبة ال OpenGL تمرين ١ : لنتذكر معا خوارزمية الرسم التقطيعي fractal (الشجرة )التي تعرفنا عليها في كتاب البرمجة ٢ حيث كنا قد اعتبرنا ا ن الشجرة عبارة عن مجموعة ا غصان تتكرر بشكل مصغر (كفروع) ا كثر من مرة لتعطي الشكل الكلي. وقد كتبنا تطبيق بلغة الباسكال محققين رسم خوارزمية الشجرة :

Program tree_gu; Uses GU; Procedure tree(ng: integer; l,ti: real) Var a,px,py: real; Procedure branch(ox,oy:real; nr: integer; l,t: real); Var Px1,Px2,Py1,Py2 : real; Begin If( (nr <> 0) and (l>0))then Begine Px1 := ox; Py1:= oy; Px2 := ox + l*cos(t); Py2 := oy + l*sin(t); nr := nr l; GLULine(Px1,Py1,Px2,Py2); branch(px2,py2,nr,l-l*0.45,t+ti); branch(px2,py2,nr,l-l*0.15,t); branch(px2,py2,nr,l-l*0.45,t-ti); end; end; (*branch*) begine a: pi/2; px := 0.5; py := 0; branch(px,py,ng,1,a); end; Begine (*******************************************) (*** Graphic Mode Initialisation ***) GUInitGraph; GUWindowView(0,0,1,1,50,50,450,450); tree(8,0.2,pi/8); GUText(0.05,0.9, Fractal Example. ); readln; GUCloseGraph; End. فحصلنا على الخرج التالي :

والمطلوب كتابة تطبيق نحقق فيه خوارزمية الشجرة مستخدمين تعليمات مكتبة ال OpenGL و لغة البرمجة C++. يمكنك الرجوع ا لى كتاب البرمجة ٢ لتذكر وحدات GU التي استخدمناها هنا. ٢: تمرين اكتب تطبيق باستخدام مكتبة ال OpenGL بحيث يظهر في هذا التطبيق كوخ له الشكل التالي: مستفيدا من التعليمات التي ذكرناها. تمرين ٣ : اكتب برنامج لمعرفة الوضع النسبي لقطعتين مستقيمتين ا ذا كانتا متوازيتين ا م متقاطعتين ا م متخالفين وفي حال تقاطعهما نريد معرفة ا حداثيات نقطة التقاطع ووضع نقطة التقاطع (تنتمي ا لى القطعتين تقع على واحدة من القطعتين وحامل القطعة الثانية تقع على حامل القطعتين). تمرين : ٤ اكتب تطبيق يظهر الشكل التالي

مستخدما ا سلوب البرمجة العودي و تعليمات ال OpenGL للرسم.

الفصل الثاني التفاعلية مع المستخدم مقدمة: تستطيع ال OpenGL تقديم تطبيقات رسومي ة راي عة وتجسيد النماذج الواقعية بما توفره لمستخدميها من ا شكال هندسية وكاي نات رسومية جاهزة تلبي كل الاحتياجات التي يتطلبها ا ي نموذج رسومي. ا لا ا ن التطبيقات الرسومية لا تكتسب ا هميتها من قدرتها على رسم مشهد ا و نموذج لمجرد تجسيد صورة فحسب بل تكتسبها عندما تكون قادرة على التفاعل مع المستخدم والاستجابة لا وامره. ويعتبر مجال الا لعاب الحاسوبية مجالا واسعا جدا لاستخدام التطبيقات الرسومية القادرة على الاستجابة لا وامر المستخدمين فا ذا كانت التطبيقات الرسومية التي تقدمها ال OpenGL غير قادرة على دخول هذا المجال فا نها ستبقى بعيدة عن الاستخدام لذلك كان لابد لل OpenGL ا ن تمتلك القدرة على التفاعل مع المستخدمين والاستجابة لا وامرهم التي غالبا ما تصدر من الطرفيات المحيطية للحاسوب كالفا رة ولوحة المفاتيح...الخ. وبالفعل استطاعت ال OpenGL تحقيق ا مر التفاعلية بالاستعانة بالمكتبة الخدمية GLUT التي قدمت تعليمات و ا جراي يات تستجيب للا حداث الصادرة عن الفا رة ولوحة المفاتيح و...الخ. ا ن الاستجابة التي يحققها التطبيق غالبا ما تكون نتيجتها الحركة على اختلاف ا شكالها كالتدوير والانسحاب والتكبير والتصغير فمثلا في التطبيقات الرسومية في مجال الا لعاب (كسباق السيارات) هدف المستخدم من التفاعل مع التطبيق هو تحريك هذه السيارة نحو الا مام ا و العودة فيها نحو الخلف و التفافها...الخ. وتوابع الحركة هذه توفرها مكتبة ال. OpenGL ونلخص فيما مراحل التفاعلية والحركة: - ١ يصدر ا مر من المستخدم باستخدام الطرفيات المحيطية. ٢- يستجيب التطبيق لهذا الا مر (باستخدام التوابع التي توفرها المكتبة الخدمية ( GLUT. ٣- النتيجة حركة ما في ا شكال النموذج الذي يعرضه التطبيق (باستخدام توابع الحركة التي توفرها مكتبة ال (OpenGL. مثال ١ : في هذا المثال سنركز على الاستجابة للا حداث التي تصدر عن الفا رة ولوحة المفاتيح بحيث : عند الضغط على الزر الا يمن للفا رة سيبدا الشكل الظاهر بالدوران. o عند الضغط على الزر الا يسر للفا رة سيتوقف الشكل الظاهر عن الدوران. o عند الضغط على زر ESC في لوحة المفاتيح سيتم ا نهاء التطبيق. o

#include <GL/glut.h> #include <stdlib.h> static GLfloat spin = 0.0; void display(void) glclear(gl_color_buffer_bit); glpushmatrix(); glrotatef(spin, 0.0, 0.0, 1.0); glcolor3f(1.0, 1.0, 1.0); glrectf(-25.0, -25.0, 25.0, 25.0); glpopmatrix(); glutswapbuffers(); void spindisplay(void) spin = spin + 2.0; if (spin > 360.0) spin = spin - 360.0; glutpostredisplay(); void init(void) glclearcolor (0.0, 0.0, 0.0, 0.0); glshademodel (GL_FLAT); void reshape(int w, int h) glviewport (0, 0, (GLsizei) w, (GLsizei) h); glmatrixmode(gl_projection); glloadidentity(); glortho(-50.0, 50.0, -50.0, 50.0, -1.0, 1.0); glmatrixmode(gl_modelview); glloadidentity(); void mouse(int button, int state, int x, int y) switch (button) case GLUT_LEFT_BUTTON: if (state == GLUT_DOWN) glutidlefunc(spindisplay); case GLUT_MIDDLE_BUTTON: case GLUT_RIGHT_BUTTON: if (state == GLUT_DOWN) glutidlefunc(null); default:

void keyboard (unsigned char key, int x, int y) if (key = 27) exit(0); /* * Request double buffer display mode. * Register mouse input callback functions */ int main(int argc, char** argv) glutinit(&argc, argv); glutinitdisplaymode (GLUT_DOUBLE GLUT_RGB); glutinitwindowsize (250, 250); glutinitwindowposition (100, 100); glutcreatewindow (argv[0]); init (); glutdisplayfunc(display); glutreshapefunc(reshape); glutmousefunc(mouse); glutkeyboardfunc(keyboard); glutmainloop(); return 0; /* ANSI C requires main to return int. */ سنبدا بشرح التعليمات المتعلقة بالاستجابة لا حداث الفا رة ولوحة المفاتيح : void mouse(int button,int state,int x,int y) ا جراي ية الاستجابة لحدث الفا رة: بارمتراتها هي : : Button يحدد ا ي زر من ا زرار الفا رة تم ضغطه ويا خذ هذا الوسيط ا حدى قيم الثوابت التالية :.A Button = GLUT_LEFT_BUTTON Button = GLUT_RIGHT_BUTTON Button = GLUT_MIDDLE_BUTTON : State يحدد حالة زر الفا رة هل هو مضغوط ا م لا :.B State = GLUT_UP State = GLUT_DOWN X,Y ا حداثيي الفا رة على الشاشة..C

في الا جراي ية الري يسية الmain يستدعى التابع الذي يلتقط الا حداث التي تصدر عن الفا رة. glutmousefunc(mouse); ا جراي ية الاستجابة لا حداث لوحة المفاتيح: void keyboard (unsigned char key, int x, int y) بارمتراتها هي : : char يحدد ا ي المحرف الذي تم الضغط عليه في لوحة المفاتيح ويمكن ا ن يكون رقم يرمز لل ascii الخاص بهذا المحرف كما في المثال السابق حيث تعاملنا مع ال ascii code code لمحرف ال ESC والذي يساوي القيمة. ٢٧ X,Y ا حداثيي الفا رة على الشاشة عندما تم ضغط المحرف في لوحة المفاتيح..A.B في الا جراي ية الري يسية الmain يستدعى التابع الذي يلتقط الا حداث التي تصدر عن لوحة المفاتيح. glutkeyboardfunc(keyboard); ملاحظة ١ : رغم ا ن للا جراي يتين mouse و keyboard بارمترات ا لا ا نه لا تمرر لها عند استدعاء الا جراي ية. glutmousefunc glutkeyboardfunc ا ن اسم الا جراي ية ليس اسم محجوز بمعنى ا نه يمكن تغيير اسم الا جراي ية كما تريد ولكن الشيء الا ساسي هو عدد بارمترات الا جراي ية و نوعها..١.٢

ا ما فيما يخص الحركة توجد تعليمات ضرورية لتحقيقها: توابع الحركة : وقد استخدمنا هنا ا حد هذه التوابع وهو تابع الدوران ;(1.0 glrotatef(spin,,0.0,0.0 في ا جراي ية العرض والذي سيشرح مع باقي تعليمات التحريك كالانسحاب وغيره في الفصل القادم ولكن ما نركز عليه هنا هو طريقة جعل هذا التابع يعطي مفهوم الحركة بجعل زاوية الدوران والتي تتمثل بالمتحول spin ذو قيمة متغييرة. التابع glutswapbuffers() : تتم عمليات الرسم عادة على السطح الخلفي back buffer وعند استدعاء glutswapbuffers() ينقل المشهد المرسوم ا لى السطح الا مامي front buffer حيث يظهر على الشاشة. والهدف تسريع عمليات الا ظهار على الشاشة ومنع حدوث التضارب. ويتم استدعاء عمليات رسم المشهد في لحظة معينة بين التابعين glclear و glutswapbuffers كما نرى من التابع.display glpushmatrix() : تابع ينسخ المصفوفة الحالية ويضيف النسخة في ا على المكدس فوق المصفوفة السابقة. glpopmatrix() : تابع يتخلص من المصفوفة الحالية..١.٢.٣.٤ سيتم شرح عمل هاتين التعليمتين بالتفصيل في الفصل القادم. ا ظهار الحركة بشكل مستمر: يجب ا جراء تغيير مستمر في قيمة زاوية الدوران spin التي تمرر للتابع. glrotatef ا عادة رسم النافذة الحالية عند كل تغيير لزاوية الدوران..١.٢ يقوم التابع spindisplay بتغيير في قيمة المتحول spin ومن ثم ا عادة رسم النافذة الحالية من جدي د لا خ ذ التغيي ر ف ي قيم ة الزاوي ة. spin ولا ع ادة رس م الناف ذة ن ستخدم الت ابع. glutpostredisplay() glutpostredisplay() : تعمل كاستدعاء عودي لا جراي ية العرض حيث لا يتم استدعاء ا جراي ية العرض - كما تعلمنا في لغات البرمجة باسمها مباشرة. ا ن الا جراي ية spindisplay() تجري تغيير في قيمة المتحول spin مرة واحدة ولتغيير قيمة الزاوية بشكل مستمر يجب استدعاء التابع spindisplay() عوديا. ولتحقيق ذلك نستخدم التابع. glutidlfunc() glutidlfunc() : يستخدم لا ظهار حركة مستمرة دون تدخل من المستخدم يمرر لهذا التابع بارمتر يا خذ ا حدى القيمتين التاليتين : o اسم الا جراي ية التي تجري تغيير في متحولات تابع الحركة والتي تعيد رسم النافذة الحالية وهنا الا جراي ية التي تمرر لهذا التابع هي spindisplay(). o القيمة NULL والتي توقف عمل التابع glutidlfunc() وبالتالي تتوقف الحركة.

ملاحظة ٢ : لو استدعينا التابع spindisplay() مباشرة في ا جراي ية الماوس دون استخدام التابع glutidlfunc() عندها ستظهر الحركة مع كل نقرة ماوس ا ما باستخدام التابع glutidlfunc() فستظهر حركة مستمرة بمجرد النقر مرة واحدة على الماوس ولا يقاف هذه الحركة نضغط الزر الا يسر للماوس فيستدعى التابع glutidlfunc مع البارمتر. NULL GLUT_RGB) : glutinitdisplaymode (GLUT_DOUBLE سبق وذكرنا هذه التعليمة ولكن كان الثابت الذي نستخدمه GLUT_SINGLE حيث كان التطبيق يظهر ا شكال رسومية ساكنة ا ما الا ن فنستخدم الثابت GLUT_DOUBLE لا ن الا شكال المرسومة متحركة والمقصود بالكلمة DOUBLE ا ننا نتعامل مع مخزنين مو قتين للنقط المرسومة.two Buffer حيث يتم ا ظهار النقاط الموجودة في المخزن المو قت الا ول في الوقت الذي تكون النقاط في المخزن الثاني يتم رسمها وحالما يتم الانتهاء من رسم النقاط الموجودة في المخزن المو قت الثاني يتم ا ظهارها والتبديل مع نقاط المخزن الا ول الذي توضع فيه نقاط جديدة للرسم. ا نشاء القواي م: يمكن للمستخدم ا يضا ا ن يتفاعل مع التطبيقات من خلال القواي م المنسدلة حيث يختار عنصر ما من القاي مة ويختار المستخدم ا مر ما ) عنصر ما ( من القاي مة باستخدام الفا رة. كما يمكن التحكم بعدد العناصر في القاي مة و باختلاف الخيارات تختلف النتاي ج. تقدم ال GLUT مجموعة تعليمات لا نشاء القواي م سنشرحها فيما يلي : ا جراي ية ا نشاء القواي م : int glutcreatemenu(void (*func)(int value));.١ تعيد هذه التعليمة رقم يمثل رقم القاي مة ا ما بارمتر هذه الا جراي ية فهو ا جراي ية ا يضا بارمترها value وهو يا خذ قيمة العنصر الذي يختاره المستخدم من القاي مة. ا جراي ية لا ضافة العناصر للقاي مة : void glutaddmenuentry(char *name, int value); تقوم هذه الا جراي ية با ضافة عنصر جديد ا لى القاي مة بارمترات هذه الا جراي ية : : Name اسم العنصر الذي ستتم ا ضافته للقاي مة حيث سيختاره المستخدم من القاي مة. a. :Value رقم العنصر في القاي مة والذي سنستفيد منه لمعرفة الحدث المراد تنفيذه. b. ا جراي ية لربط القاي مة المنسدلة با حد ا زرار الفا رة : void glutattachmenu(int button);.٢.٣

ملاحظة حيث تنسدل القاي مة بمجرد النقر على الزر الذي ارتبطت به القاي مة. يا خذ هذا البارمتر ا حدى القيم التالية : Button = GLUT_LEFT_BUTTON Button = GLUT_RIGHT_BUTTON Button = GLUT_MIDDLE_BUTTON :٣ في حال ربط زر الفا رة مع القواي م المنسدلة و استخدامه لتنفيذ ا حداث تخص ا جراي ية الفا رة فسيلغى تفعيل هذا الحدث المرتبط مع ا جراي ية الق... ويبقى ا ثره فقط في ا جراي ية... لذلك يجب الانتباه على عدم استخدام الزر في الا جراي يتين بنفس الوقت. مثال ٢ : تستدعى جميع الا جراي يات السابقة ضمن جسم الا جراء الا ساسي. main void main(int argc, char** argv)... glutcreatemenu(menu) glutattachmenu(glut_left_button); glutaddmenuentry("draw with red color",1); glutaddmenuentry("draw with blue color",2); glutaddmenuentry("draw with green color",3);... ا نشا نا في هذا الجزء قاي مة منسدلة تحوي ثلاث عناصر مختلفة وتنسدل هذه القاي مة عند النقر على الزر الا يسر للفا رة لا نه الزر الذي ارتبطت معه القاي مة المنسدلة. ا ما بالنسبة لا جراي ية ا نشاء القاي مة فلاحظ البارمتر الممرر لها menu هو عبارة عن اسم ا جراي ية يتم فيها الاستجابة للحدث المرتبط مع العنصر الذي يختاره المستخدم من القاي مة. سنتناول في هذا المثال ا جراي يتي العرض والقاي مة المنسدلة حيث نرسم في ا جراي ية العرض مضلع وباختيار ا حد عناصر القاي مة يتحدد لون خط الرسم فيظهر الشكل باللون الذي تم اختياره.

void display(void) glbegin(gl_polygon); glvertex3f (0.25, 0.25, 0.0); glvertex3f (0.75, 0.25, 0.0); glvertex3f (0.75, 0.75, 0.0); glvertex3f (0.25, 0.75, 0.0); glend(); glflush (); void menu(int value) if (value==1) // the first item is selected, and // the color is red glcolor3f(1.0,0.0,0.0); glclear(gl_color_buffer_bit); glutpostredisplay(); else if (value==1) // the second item is selected, and // the color is blue glcolor3f(0.0,0.0,1.0); glclear(gl_color_buffer_bit); glutpostredisplay(); else if (value==2) // the third item is selected, and // the color is green glcolor3f(0.0,1.0,0.0); glclear(gl_color_buffer_bit); glutpostredisplay();

تعليمات ا خرى خاصة بالقواي م المنسدلة :.١ ا ضافة قاي مة جزي ية : void glutaddsubmenu(char *name, int menu);.٢ بارمتراتها : اسم العنصر الذي ترتبط به القاي مة الجزي ية رقم القاي مة التي تتضمن القاي مة الجزي ية. تغيير اسم العنصر في القاي مة : void glutchangetomenuentry(int entry, char *name, int value); بارمتراتها: رقم العنصر الذي سيتم تغييره في القاي مة الاسم الجديد للعنصر القيمة الجديدة المرتبطة بهذا العنصر. غالبا ما نرى في القواي م المنسدلة تغيير اسم العنصر بمجرد اختياره وذلك عندما يكون لهذين العنصرين ا ثريين متعاكسين ا و ا ذا كان ا ثر العنصر الا ول لا يظهر حتى يتم تنفيذ الحدث المرتبط بالعنصر الثاني والعكس بالعكس. مثال ٣ : ا ذا كنا نريد تكبير وتصغير شكل ما فا ننا لا نضيف ا لى القاي مة عنصرين الا ول للتكبير وا خر للتصغير وا نما نضيف عنصر واحد كالتالي: glutaddmenuentry("zoom out",1); وبا جراي ية ال menu عند اختيار هذا العنصر نغيره ليصبح له الا ثر المعاكس كالتالي: void menu(int value) if (value==1) glutchangetomenuentry(1,"zoom in",2);//change the item //--- add the appropriate response ---- // else if (value==2) glutchangetomenuentry(1,"zoom out",1); //--- add the appropriate response ---- // void glutremovemenuitem(int entry); void glutdetachmenu(int button); void glutdestroymenu(int menu); ا زالة وحذف عنصر من قاي مة: فك الربط مع زر الفا رة : هدم القاي مة المنسدلة :. ٣.٤.٥

تمرين: اكتب تطبيق تستخدم فيه القواي م المنسدلة بحيث يظهر في هذا التطبيق مضلع مرسوم بلون ا بيض ثم يتغي ر لونه بحسب الخيارات في القاي مة وا ضف خيارات جديدة للقاي مة بحيث نختار من القاي مة العنصر مثلث فيظهر لدينا شكل المثلث و غيرها من الا شكال التي تعرفنا عليها سابقا.

الفصل الثالث التحويلات والحركة مقدمة: ا ذا ما نظرنا في ا ية صورة بديعة المنظر وراي عة التصميم نظرة المحلل لوجدناها تتا لف من عدة ا شكال هندسية بسيطة. تستطيع ال OpenGL تجسيد الصور الواقعي ة بما توفره من ا شكال هندسية بسيطة تطبق عليها العديد من العمليات لتظهر بالشكل الملاي م والمشابه للواقع. وهذه العمليات تشبه ا لى حد كبير تلك التي نجريها عندما نريد التقاط صورة ما باستخدام كاميرا التصوير. ويمكن تقسيم هذه العمليات ا لى ثلاث مراحل ا ساسية هي: ١. التحويلات وتتضمن: o تحويلات النمذجة: التي تتحكم بمكان ظهور الا شكال وحجمها. o تحويلات الرو ية: التي تتحكم بمكان توضع عين الناظر ا و كاميرا التصوير و الجهة التي يتم النظر منها. o تحويلات الا سقاط: ومن خلاله يتحدد فيما ا ذا كان النموذج المرسوم ذو مسقط منظوري ا و مسقط متوازي. ٢. نافذة الرو ية: المسو ولة عن ا ظهار الا شكال بما يتناسب مع ا حداثيات نافذة الرو ية. ٣. القص والقطع: التي تحدد الا شكال ا و الا جزاء التي سيتم ا ظهارها ضمن النموذج البياني. ويوضح لنا الشكل التالي المراحل المتلاحقة لتنفيذ هذه العمليات :

مقارنة بين العمليات في الحاسوب لرسم نموذج رسومي وتلك التي ننفذها في كاميرا التصوير: لتحقيق تحويلات النمذجة الرو ية المنظور يجب ا نشاء مصفوفة M ببعد 4X4 ومن ثم ا جراء عملية ضرب لهذه المصفوفة بكل نقطة من نقاط الشكل ) ='v M v. يجب ا ن لا ننسى ا ن العقدة الواحدة تتا لف من ا ربع مركبات (w,x),y,z حيث تا خذ w القيمة واحد عادة عندما تكون الا شكال ذات موقع محدد وقيمة تساوي الصفر عندما تقع الا شكال في اللانهاية وبالنسبة ل Z فتا خذ في البعد الثناي ي القيمة صفر.

طبعا ليس من الضروري ا ن تخضع نقاط الشكل ا لى كل هذه التحويلات وا نما نطبق التحويلات اللازمة لا ظهار الصورة بالشكل المناسب. ولنبدا الا ن بشرح كل نوع من هذه التحويلات.... تحويلات النمذجة :Modeling Transformations تستخدم هذه التحويلات للتحكم بمكان ظهور الا شكال وطريقة توضعها ) ماي لة مستقيمة مقلوبة) بالا ضافة ا لى تحديد حجم الا شكال. ويمكن تطبيق هذه التحويلات على النماذج التي تحتوي ا شكال ثناي ية البعد والنماذج التي تحتوي ا شكال ثلاثية البعد. التحويلات والعلاقات الجبرية الممثلة لها في جملة الا حداثيات ثناي ية البعد :.١ التقييس ا و التحجيم : Scale وفيه نستطيع تكبير ا و تصغير ا ي شكل مهما كان معقدا ا ذا استطعنا تكبير ا و تصغير ا حداثياته وذلك بنفس النسبة. تحيل با نك تقف ا مام برج عالي وتنظر اليه تستطيع من خلال توابع التحويل ا ن تقوم بتقصير البرج ليتلاءم مع الارتفاع والعرض المرغوبين. ا ما المعادلات الناظمة لهذه العملية فهي بسيطة عبارة عن ضرب احداثيات ا ي نقطة بنفس النسبة: x0 = x * sx y0 = y * sy.٢ الدوران : Rotation في هذا التحويل نستطيع ا ن نقوم بتدوير ا ي شكل كما نشاء وفي ا ي جهة نشاء كما نستطيع التحكم بزاوية الدوران فتخيل معي لو ا ننا ننظر ا لى جسم سيارة ما مثبتة على سطح قابل للدوران نستطيع باستخدام توابع الدوران ا ن نقوم بتحريك هذا السطح الدوراني بالزاوية المرغوبة بالتالي نستطيع رو ية هذه السيارة من كافة الجوانب وكا ننا بتطبيق هذه المعادلات نقوم بعرض ا نيق لسيارة فخمة كي يتمكن الراي ي من ا ي مكان يقف فيه من رو ية السيارة بشكل كامل. ا ما التوابع الناظمة لعملية الدوران فهي: x0 = x * cos θ + y * sin θ y0 = y * sin θ + y * cos θ.٣ حيث θ تمثل زاوية الدوران. الانسحاب : Translation تخيل لو ا ن لديك كرة في صندوق وا ردت ا ن تحاكي حركتها بالتالي ما عليك سوى تحريكها على المحاور الثلاثة فا ذا غيرت قيم المحور الا فقي X فقط على سبيل المثال فتستطيع محاكاة تحريك الكرة بشكل ا فقي ا ما ا ذا غيرت قيم الانسحاب على المحاور الثلاثة بنسب عشواي ية بالتالي ترى

الكرة تنتقل من مكان لا خر ضمن هذا الصندوق طبعا مع الا خذ بعين الاعتبار ا ن قيم الانسحاب هذه يجب ا لا تتجاوز حدود الصندوق. ا ما توابع الانسحاب فهي: x0 = x + tx y0 = y + ty وبالنسبة للعلاقات الجبرية في جملة الا حداثيات ثلاثية البعد فا ننا نا خذ بعين الاعتبار قيم الا حداثي z حيث تحسب قيمه كالا حداثيين. y x ا ما التوابع التي تقدمها ال OpenGL لتحقيق هذه التحويلات فهي ثلاث توابع ا ساسية وهي نفسها سواء في جملة الا حداثيات ثناي ية البعد ا و ثلاثية البعد : تابع الانسحاب gltranslatef(x,y,z) : وهو التابع الذي يقوم بعملية الانسحاب حيث تشير البارمترات ا ن عمليات الانسحاب تتم على ا حد المحاور z y x ا و على جميع المحاور في نفس الوقت مع العلم ا ن تا ثير الانسحاب على المحور z في البعد الثناي ي لن يظهر ولذلك تا خذ z هنا القيمة صفر بشكل افتراضي ويمكن ا ن نجري انسحاب نحو اليمين ا و اليسار ولفوق ا و تحت وللا مام ا و الخلف وذلك بالتحكم با شارة القيمة المرتبطة بالبارمترات الممرر ة لهذا التابع بالسالب والموجب وعند جعل جميع القيم المتعلقة بالبارمترات z y x مساوية للصفر عندها لن يظهر ا ي تا ثير لهذا التابع..١ تابع الدوران glrotatef(θ,x,y,z) وهو التابع الذي يقوم بعملية الدوران حيث يشير البارامتر الا ول θا لى زاوية الدوران ا ما البارمترات الثلاثة الا خرى فهي تسبب دوران حول ا حد المحاور و نعطي المحور الذي نريد ا ن يدور حوله الشكل قيمة =١ ا ما باقي المحاور والتي لا نريد ا ن يدور الشكل حولها نعطيها قيمة = ٠ مع العلم ا نه يمكن ا ن نعطي القيمة ١ لا كثر من محور وهذا يعني ا ن الدوران يتم على ا كثر من محور وكذلك يمكن ا جراء دورانات بجميع الاتجاهات وذلك بالتحكم بقيم الزاوية وحتى با شارة الزاوية سالبة ا و موجبة ولكن عند ا عطاء الزاوية القيمة صفر عندها لن يحدث ا ي تا ثير لهذا التابع..٢

الشكل قبل التدوير الشكل بعد التدوير ٣. تابع التقييس :glscalef (x,y,z) وهو تابع يقوم بتكبير ا و تصغير الشكل على ا حد المحاور ا و على ا كثر من محور كما ا ن لهذا التابع تا ثير ا خر حيث يمكنه ا ن يقلب الشكل وذلك بحسب قيم ال z y x التي تمرر للتابع فا ذا ا عطي لا حد هذه البارمترات قيمة ا كبر من ١ فا ن الشكل سيكبر ويزداد حجمه وا ذا ا عطي قيمه ا قل من واحد فينقص حجم الشكل وعند ا عطاء قيم سالبة تسبب قلب للشكل ولكن كما في حالة الانسحاب فا ن التكبير ا و التصغير في الا شكال ثناي ية البعد لا يظهر تا ثيره على المحور. z وبالنسبة لتا ثيرات هذه التوابع على الا شكال ثلاثية البعد نا خذ الا مثلة التالية : يمثل العكس على المحور y والتكبير على المحور x

يمثل الدوران حول المحور z يمثل الانسحاب على المحور z ويمكن تركيب هذه التوابع مع بعضها بحيث نجري عملية انسحاب ثم تكبير ونلحقه بعملية دوران ولكن يجب ا ن ننتبه لموضوع هام جدا هو ا ننا ا ذا ا جرينا تحويل ١ ثم ا جرينا تحويل ٢ من نوع ا خر فا ن عكس هذين التحويلين بحيث نجري التحويل ٢ ثم التحويل ١ لن يعطي نفس التا ثير على الشكل ولنا خذ كمثال الشكل التالي :

لاحظ ا ن ا جراء الانسحاب بالا ول ثم الدوران لا يعطي نفس تا ثير تطبيق الدوران ا ولا ثم الانسحاب. مثال ١ : تطبيق تحويلات النمذجة على الا شكال ثناي ية البعد : دوران الشكل حول نقطة ثابتة لتحقيق دوران الشكل حول نقطة ثابتة يجب تطبيق التحويل التالي : Start with identity matrix: C I Move fixed point to origin: C CT Rotate: C CR Move fixed point back: C CT-1 Result: C = TRT-1 سنا خذ كمثال على الا شكال ثناي ية البعد المضلع والذي سنطبق عليه التحويلات اللازمة لتدوير الشكل حول نقطة ثابتة وطريقة تحقيقها في ال. OpenGL يا خذ المضلع الشكل التالي قبل ا جراء ا ي تحويل باعتبار ا ن ا بعاده كالتالي y2=25) x2=25 y1=0 (x1=0 وسنركز في هذا المثال على التعليمات في ا جراي يتي العرض (display) وا جراي ية التحديث وا عادة الرسم. (reshape)

void display(void) glclear(gl_color_buffer_bit); glcolor3f (1.0, 1.0, 1.0); gltranslatef(1.0,2.0,3.0); /* modeling transformation */ glrotatef(30,0,0,1); /* modeling transformation */ gltranslatef(-1.0,-2.0,-3.0); /* modeling transformation*/ glbegin(gl_polygon); ( 0,0,0.0 ) glvertex3f glvertex3f (25,0, 0.0); glvertex3f (25, 25, 0.0); glvertex3f (0,25, 0.0); glend(); glflush (); void reshape(int w, int h) glmatrixmode(gl_modelview); glloadidentity(); /* clear the matrix */ glortho(-50.0, 50.0, -50.0, 50.0, -50.0, 50.0); وسيكون الخرج كما في الشكل التالي :

تحقق ال OpenGL التمثيل المصفوفي بمجرد استدعاء التعليمات المسو ولة عن تحويلات النمذجة مع العلم ا ن ال OpenGL تقدم نوعين من المصفوفات الا ولى لتحقيق تحويلات النمذجة والثانية لتحقيق تحويلات وهما : المنظور _ التي سنتحدث عنها لاحقا _ Model-View (GL_MODELVIEW) Projection (GL_PROJECTION) ولتحدید نوع التحویل المراد استخدامھ تستدعى تعلیمة واحدة للشكلین السابقین ولكن الذي یختلف ھو الثابت الممرر لھذه التعلیمة التي تا خذ الشكل التالي : reshape بالشكل glmatrixmode(gl_modelview); glmatrixmode(gl_projection); وفي مثالنا السابق تم استدعاء هذه التعليمة في ا جراي ية ا عادة الرسم glmatrixmode(gl_modelview); وبما ا ن الثابت هو GL_MODELVIEW فهذا يعني ا ن التحويل الذي سيتم تطبيقه هو تحويل نمذجة بالا ضافة ا لى ا ن هذا الثابت يستخدم في تحويل الرو ية والذي يستخدم داي ما مع تحويل النمذجة لذلك تم دمج هذين التحويلين بثابت واحد ولكن قبل ا جراء ا ية عملية تحويل يجب تهيي ة مصفوفة التحويلات المصفوفة الواحدية بالقيم الافتراضية ا ي بقيم تساوي الواحد وهذا ما تحققه التعليمة glloadidentity حيث تستدعى من ا جل مسح القيم المسندة لمصفوفة التحويل من جراء تحويلات سابقة قد تكون ا جريت في وقت من الا وقات وتحميل القيم الافتراضية للمصفوفة والتي تكون بشكل افتراضي رباعية (٤X٤). ا ما بالنسبة لتوابع التحويل في ا جراي ية العرض فا ن الترتيب الذي تم استدعاو ها به يحقق التحويل المراد وهو دوران الشكل حول نقطة ثابتة. gltranslatef(1.0,2.0,3.0);/*modeling transformation */ glrotatef(30,0,0,1);/* modeling transformation */ gltranslatef(-1.0,-2.0,-3.0);/* modeling transformation*/ Result: C = TRT-1 ملاحظة ١ :.١ تسمح ال OpenGL با جراء ا ي نوع من التحويلات وذلك بالسماح بتحميل ا ي قيم لمصفوفة التحويلات والتي سبق وذكرنا ا ن قيمها الافتراضية تساوي الواحد بالا ضافة ا لى ا مكانية الضرب بمصفوفات تحويل مختلفة عوضا عن استخدام توابع التحويلات كالانسحاب والدوران والتقييس التي تقدمها ال OpenGL بحيث نحدد قيم هذه المصفوفات بحسب ما نرغب ويتم تحقيق هذا باستخدام التعليمتين التاليتين: ;(m* : void glloadmatrixfd(const TYPE وهي تقوم بنفس عمل التعليمة glloadmatrix ا لا ا ن الاختلاف بينهما ا نه في التعليمة glloadidentity يجب تحديد مصفوفة التحويلات التي نريدها ثم نمررها كبارمتر لهذه التعليمة في حين التعليمة. تحدد فيها مصفوفة التحويلات بشكل افتراضي وببعد 4X4 glloadidentity

*m); : void glmultmatrixfd(const TYPE تستخدم هذه التعليمة لا جراء التحويل الذي نرغب بحيث نعرف مصفوفة تحويل ونعطيها قيم معينة ثم ننمررها كبارمتر لهذه التعليمة التي تقوم بدورها با جراء عملية ضرب لهذه المصفوفة مع مصفوفة التحويل التي تم تعريفها سابقا وبالتالي فا ن هذه التعليمة تنوب عن التعليمات التي تقوم بعمليات الانسحاب والدوران والتقييس. glscalef glrotatef gltranslatef.٢ فعلى سبيل المثال يمكن تحقيق دوران الشكل حول نقطة ثابتة والذي را يناه في المثال السابق بالشكل التالي : ا ولا نعرف مصفوفة التحويل الافتراضية بالبعد الذي نريده والقيم التي نريدها glmatrixmode(gl_modelview); glloadmatrix (M); glmultmatrixf(t); /* translation */ glmultmatrixf(r); /* rotation */ glmultmatrixf(tˉ1); /* translation */ draw_the_object(); وعندما نريد استخدام مصفوفة التحويل الواحدية بدلا من تعريف مصفوفة تحويل خاصة فا ننا نستدعي التعليمة glloadidentity ثم نعرف مصفوفات التحويل الا خرى ونجري عمليات الضرب اللازمة كما في الشكل التالي : glmatrixmode(gl_modelview); glloadidentity(); glmultmatrixf(t); /* translation */ glmultmatrixf(r); /* rotation */ glmultmatrixf(tˉ1); /* translation */ draw_the_object(); مع ملاحظة ا ن R,T هما مصفوفتين يجب تعريفهما لا جراء تحويلي الانسحاب والدوران لجميع نقاط الشكل. كل ما قمنا به حتى الا ن هو تطبيق تحويلات النمذجة على شكل هندسي واحد ولكن عندما نريد رسم نموذج ما يتا لف من عدة ا شكال هندسية متراكبة ومتجاورة عندها يجب تطبيق تحويلات النمذجة على هذه الا شكال لتركيبها مع بعضها البعض بشكل صحيح ومتناسق.

ا ن المبدا العام لتركيب الا شكال مع بعضها يقوم على ربط الجملة الا حداثية لهذه الا شكالcorrdinate object بالجملة الا حداثية العالمية worldcorrdinate بحيث نستطيع عندها تحديد البعد بينها تراكبها حجومها بالنسبة لبعضها وكل ذلك با سقاط ا حداثيات الا شكال على جملة الا حداثيات العالمية. وسنعرض مثال يوضح طريقة الاستفادة من توابع تحويلات النمذجة لتركيب الا شكال مع بعضها والحصول على كاي ن رسومي ما.

الفصل الثالث التحويلات والحركة مثال ٢ : بفرض أن الكاي ن الرسومي عبارة عن ذراع لروبوت وبفرض أن الا شكال المو لفة لھذه الذراع ھي: المكعب جسم كروي جسم أسطواني جسم مخروطي: سنشرح بالتفصيل طريقة تركيب هذه الا شكال مع بعضها لتشكيل ذراع الروبوت : سنبدا الرسم من مبدا الا حداثيات للجملة التي تظهر باللون الا سود الغامق وهي جملة الا حداثيات العالمية بحيث نفترض ا ن جميع الا شكال مرسومة استنادا لهذه الجملة. - نجري انسحاب على المحور y نحو الا سفل :.gltranslate(0,-2,0)

نجري تكبير بنسبة (4,1,4). ثم نرسم المكعب ولكن بما أن عملیة التكبیر لا تناسب باقي الا شكال وإنما فقط من أجل القاعدة لذلك فا ننا نستخدم التعلیمتین glpushmatrix() glpopmatrix() بحیث یتم استدعاء التعلیمة glpushmatrix في البدایة ثم تستدعى بعدھا عملیة التكبیر ثم نرسم الشكل وبعدھا نستدعي التعلیمة ()glpopmatrix للعودة للا حداثیات النظامیة. انسحاب نحو الا على بمقدار 0.5 (نصف ارتفاع المكعب) ثم رسم الجسم الكروي بنصف قطر یساوي. 0.6

والا ن سنقوم برسم الجزء الا ول من الذراع والذي نمثلھ بالاسطوانة وإذا قمنا برسم ھذه الا سطوانة مباشرة دون إجراء أي تحویل فستظھر بالشكل التالي : ولكننا نرید أن تتجھ ھذه الذراع نحو الا على وھذا یتطلب إجراء عملیة دوران حول المحور x بزاویة ولتكن تساوي 90- درجة فتا خذ المحاور الا حداثیة الشكل التالي :

وبرسم الا سطوانة بحسب الا حداثیات الجدیدة تظھر لدینا الذراع بالشكل التالي: ثم نجري انسحاب على المحور y نحو الا على من جدید ونرسم الجسم الكروي الذي یمثل المفصل للذراع و لرسم الجزء الا خر من الذراع بشكل ماي ل نجري دوران بزاویة ما ولتكن تساوي ٤٥ درجة على المحور x ثم نستدعي تعلیمة رسم الا سطوانة فیظھر لدینا الشكل النھاي ي للذراع. وأخیرا سنرسم الشكل المخروطي والذي یمثل المفصل الذي یربط بین الذراع والكتف بحیث نجري انسحاب للمحاور إلى أعلى الذراع وندور بزاویة قدرھا ٣٠ حول المحور x فیكون لدینا الشكل النھاي ي على النحو التالي :

: تحويل الا سقاط Projection Transformations الا سقاط : هو تحويل مجموعة من النقاط من نظام ا حداثيات بالبعد n ا لى نظام ا حداثيات ببعد ا قل من n وهنا سوف نحصر ا نفسنا بالا سقاط من 3d ا لى 2d حيث يستخدم الا سقاط للانتقال من جملة ا حداثيات الرو ية ا لى جملة ا حداثيات جهاز العرض وهي 2d. ينقسم الا سقاط ا لى نوعيين ا ساسيين هما : المتلاشي perspective المطابق.parallel ١. الا سقاط المتلاشي ا و المنظوري : perspective حيث ا ن مجموعة المستقيمات المتوازية من الممكن ا ن تظهر غير متوازية على مستوي الا سقاط وتميل للالتقاء في نقطة واحدة تسمى نقطة التلاشي. ٢. الا سقاط المطابق :parallel حيث يكون مركز الا سقاط في اللانهاية ويكون شعاع الا سقاط موازيا لسطح الا سقاط. بفرض لدينا النموذج التالي : فعند الا سقاط في المستوي المتوازي Orthographic يظهر لدينا النموذج بالشكل التالي: وباستخدام الا سقاط في الفراغ فا ن الا جزاء الداخلية من النموذج ستظهر نوعا ما مما يجعله يبدو بشكل مجس م. ويفيد الا سقاط في تحديد حيز الرو ية الذي نستطيع ا ن نرى كل ما يقع ضمنه ولتوضيح هذا الا مر بشكل ا كبر لنعود ا لى تحويل الرو ية حيث استطعنا باستخدام هذا التحويل التحكم بمكان عين الناظر وتحديد الجهة التي ينظر ا ليها وذلك لمحاكاة ما يقوم به المصو ر عندما يتخذ مكانا مناسبا لالتقاط الصورة بكاميرا التصوير ولكن

هذا ليس كل شيء فالمصور بعد ا ن يحدد المكان الذي يقف به والجهة التي سيصور منها يبدا بالتحكم بعدسة كاميرا التصوير فيزيد من فتحة العدسة ا و ينقصها وذلك لتحديد الحيز الذي يمكن للكاميرا تصويره. هذا الحيز سميناه بحيز الرو ية وهو ما يحدده لنا تحويل الا سقاط..١ وبما ا نه يوجد نوعين من الا سقاط فهذا يعني ا نه يمكن تحديد نوعين من حيز الرو ية. في حالة الا سقاط المنظوري : حيث يكون حيز الرو ية عبارة عن جزع الهرم المحدد بالمستويين الا مامي والخلفي. ٢. في حالة الا سقاط المتوازي: حيث يكون حيز الرو ية عبارة عن متوازي المستطيلات المحدد بالوجهين الا مامي والخلفي. ويظهر الاختلاف بين نوعي الا سقاط السابقيين عندما نقوم بتقريب ا و تبعيد كاميرا التصوير ا ي عندما نقوم با جراء عملية zoom لعدسة الكاميرا ففي الا سقاط المنظوري ا و المتلاشي يسبب ا جراء عملية التقريب تكبير النموذج المصور في حين تسبب عملية التبعيد تصغير النموذج. سنوضح ذلك بالشكل التالي:

مقدمة: تحويل الرو ية :Viewing Transformations ذكرنا سابقا ا ن ما نريد تحقيقه في ال OpenGL هو محاكاة عمل كاميرا التصوير وجعل المشهد يبدو وكا نه قد تم تصويره بالكاميرا واستطعنا باستخدام تحويلات النمذجة التحكم بطريقة ا ظهار الا شكال ضمن المشهد بحيث حددنا موقع كل شكل وحجمه بالا ضافة ا لى تدوير الا شكال التي ا ردنا ا ن تظهر بشكل ماي ل قليلا. والا ن نريد التحكم بطريقة عرض وا ظهار الصورة حيث نريد ا ظهار المشهد بعدة ا شكال ماي ل نحو اليمين ماي ل نحو اليسار مقلوب...الخ. ا و مثلا لنعود ا لى مثال السيارة المثبتة على سطح قابل للدوران حيث استطعنا باستخدام توابع الدوران ا ن نقوم بتحريك هذا السطح الدوراني بالزاوية المرغوبة وبالتالي رو ية هذه السيارة من كافة الجوانب ولكن سنفترض ا ن هذا السطح ثابت وغير قابل للدوران وا ن الناظر هو من يقوم بالدوران حول السيارة والنظر ا ليها من كل الجوانب من الا سفل ومن الخلف ومن فوق والنظر ا ليها عن قرب ا و عن بعد. والسو ال المطروح هنا: هل هنالك ا مكانية تثبيت المشهد ولكن تطبيق تحريك لعين الناظر عادة نتخذ موقع لكاميرا التصوير من ا جل التقاط صور جانبية ا و تصوير المشهد من فوق ا و من الا سفل لا ظهاره بشكل فني جميل ولتحقيق هذا الا مر في ال OpenGL نستخدم نوع من التحويلات التي تدعى تحويلات الرو ية والتي تسمح لنا بالتحكم بطريقة عرض المشهد ككل بحيث نحدد الموقع الذي يتم فيه النظر ا لى المشهد من الا على ا و الا سفل ا و من الجانب مع العلم ا ن تا ثير تحويلات الرو ية لا تظهر ا لا في النماذج ثلاثية البعد على عكس تحويلات النمذجة التي تو ثر في النماذج ثناي ية وثلاثية البعد. يتم تحقيق تحويل الرو ية باستخدام التابع glulookat() حيث يا خذ هذا التابع تسعة بارمترات هي : الثلاثة الا ولى تحدد موقع العين التي تنظر ا لى الشكل. ١- الثلاثة التالية تحدد المكان الذي تقف فيه الكاميرا. ٢- الثلاثة الا خيرة تحدد من ا ين ينظر للشكل من فوق ا و من تحت. ٣-

مثال ١ : بفرض لدينا الشكل التالي : بحيث يحيط المكعب بكاميرا التصوير وفي هذه الحالة لا يظهر المكعب ولجعله مري ي يجب ا جراء تحويل رو ية بحيث نضع الكاميرا في مكان مناسب بالنسبة للمكعب. بتغيير موقع الكاميرا ا و عين الناظر يتغير لدينا مظهر الشكل المعروض ولنا خذ عدة ا مثلة عن المكعب.

مثال ٢ : تطبيق تحويلي النمذجة والرو ية في نفس الوقت على المكعب وسنا خذ من تحويلات النمذجة تحويل التقييس. بفرض لدينا المكعب بالشكل التالي (قبل ا جراء ا ي تحويل) : ولتطبيق تحويلي النمذجة والرو ية يجب اتباع الخطوات التالية : تحديد نوع التحويل المستخدم من خلال مصفوفة التحويلات.glMatrixMode(GL_MODELVIEW); تهيي ة المصفوفة الواحدية بالقيم الافتراضية.glLoadIdentity استدعاء تابع تحويل الرو ية glulookat مع بارمترات مناسبة. استدعاء تابع تحويل النمذجة رسم الشكل المطلوب. glscalef مع بارمترات مناسبة.

void display(void) ( glclear(gl_color_buffer_bit glcolor3f (1.0, 1.0, 1.0); glloadidentity (); /* clear the matrix */ /* viewing transformation */ glulookat (1.0, 1.0, 3.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); glscalef (1.0, 2.0, 1.0); /* modeling transformation */ glutwirecube (1.0); glflush (); void reshape(int w, int h) glmatrixmode (GL_PROJECTION); glloadidentity (); glortho(-5.0, 5.0, -5.0, 5.0, -5.0, 5.0); glmatrixmode(gl_modelview); glloadidentity(); /* clear the matrix */ فيظهر لدينا الخرج التالي :

ملاحظة : لا تقلل بشا ن التابع (GL_PROJECTION) glmatrixmode حيث سنا تي على شرحه لاحقا ولكن ا تينا على ذكره هنا لعرض الشكل النظامي والما لوف للا جراي ية.reshape تمرين ١ : اكتب تطبيق يظهر فيه المكعب السابق بالشكل التالي: ثم قم بتغيير قيم بارمترات التابع glulookat ولاحظ الا شكال المختلفة التي يا خذها هذا المكعب. استخدم لوحة المفاتيح للتحكم بقيم التابع. glulookat تمرین ٢ : ا كتب برنامج تعرض فيه نموذج لسيارة مثبتة على سطح قابل للدوران وباستخدام الفا رة والقواي م ولوحة المفاتيح تتحكم بهذه السيارة بحيث:

١. تقوم بتدویر السطح المثبت علیه السیارة باستخدام تحویلات النمذجة. ٢. تقوم بتثبیت السطح وتحریك السیارة باستخدام تحویلات الرؤیة وإجراء عملیات عرض لها من جمیع الجهات.

: تحويل الا سقاط Projection Transformations الا سقاط : هو تحويل مجموعة من النقاط من نظام ا حداثيات بالبعد n ا لى نظام ا حداثيات ببعد ا قل من n وهنا سوف نحصر ا نفسنا بالا سقاط من 3d ا لى 2d حيث يستخدم الا سقاط للانتقال من جملة ا حداثيات الرو ية ا لى جملة ا حداثيات جهاز العرض وهي 2d. ينقسم الا سقاط ا لى نوعيين ا ساسيين هما : المتلاشي perspective المطابق.parallel ٣. الا سقاط المتلاشي ا و المنظوري : perspective حيث ا ن مجموعة المستقيمات المتوازية من الممكن ا ن تظهر غير متوازية على مستوي الا سقاط وتميل للالتقاء في نقطة واحدة تسمى نقطة التلاشي. ٤. الا سقاط المطابق :parallel حيث يكون مركز الا سقاط في اللانهاية ويكون شعاع الا سقاط موازيا لسطح الا سقاط. بفرض لدينا النموذج التالي : فعند الا سقاط في المستوي المتوازي Orthographic يظهر لدينا النموذج بالشكل التالي: وباستخدام الا سقاط في الفراغ فا ن الا جزاء الداخلية من النموذج ستظهر نوعا ما مما يجعله يبدو بشكل مجس م. ويفيد الا سقاط في تحديد حيز الرو ية الذي نستطيع ا ن نرى كل ما يقع ضمنه ولتوضيح هذا الا مر بشكل ا كبر لنعود ا لى تحويل الرو ية حيث استطعنا باستخدام هذا التحويل التحكم بمكان عين الناظر وتحديد الجهة التي ينظر ا ليها وذلك لمحاكاة ما يقوم به المصو ر عندما يتخذ مكانا مناسبا لالتقاط الصورة بكاميرا التصوير ولكن

هذا ليس كل شيء فالمصور بعد ا ن يحدد المكان الذي يقف به والجهة التي سيصور منها يبدا بالتحكم بعدسة كاميرا التصوير فيزيد من فتحة العدسة ا و ينقصها وذلك لتحديد الحيز الذي يمكن للكاميرا تصويره. هذا الحيز سميناه بحيز الرو ية وهو ما يحدده لنا تحويل الا سقاط..٣ وبما ا نه يوجد نوعين من الا سقاط فهذا يعني ا نه يمكن تحديد نوعين من حيز الرو ية. في حالة الا سقاط المنظوري : حيث يكون حيز الرو ية عبارة عن جزع الهرم المحدد بالمستويين الا مامي والخلفي. ٤. في حالة الا سقاط المتوازي: حيث يكون حيز الرو ية عبارة عن متوازي المستطيلات المحدد بالوجهين الا مامي والخلفي. ويظهر الاختلاف بين نوعي الا سقاط السابقيين عندما نقوم بتقريب ا و تبعيد كاميرا التصوير ا ي عندما نقوم با جراء عملية zoom لعدسة الكاميرا ففي الا سقاط المنظوري ا و المتلاشي يسبب ا جراء عملية التقريب تكبير النموذج المصور في حين تسبب عملية التبعيد تصغير النموذج. سنوضح ذلك بالشكل التالي:

في الا سقاط المنظوري

ا ما في الا سقاط المتوازي فا ن ا ي عملية تقريب ا و تبعيد و ا جراء عملية zoom لعدسة الكاميرا لن يغير من حجم الجسم المعروض كما في الشكل التالي : في الا سقاط المتوازي كما يو ثر تكبير حيز الرو ية في ا ظهار نماذج ا كثر و تصغير حيز الرو ية يسبب ا خفاء بعض الكاي نات التي لا تنتمي لحيز الرو ية.

وقد تسبب عملية التقريب ا و التبعيد بعض الا خطاء ا ذا لم تخضع لقوانين معينة حيث يمكن ا ن تسبب الخروج من حيز الرو ية بحيث يصبح الشكل ا و جزء منه غير مري ي. كما في الشكل التالي: لاحظ كيف ظهر جزء فقط من الشكل.

وقبل ا ن نتعرف على القوانين التي يجب مراعاتها للتجنب بالوقوع بمثل هذه الا خطاء سنتعرف على التوابع التي تقدمها الOpenGL لتحقيق تحويل الا سقاط بنوعيه. ١- استدعاء مصفوفة التحويل الخاصة بتحويل الا سقاط: glmatrixmode (GL_PROJECTION); glloadidentity(); ٢- تهيي تها بالقيم الافتراضية : ٣- تحديد نوع الا سقاط المستخدم : الا سقاط في المستوي المتوازي: عندها نستخدم التعليمة التالية: glortho(left, right, bottom, top, Znear, Zfar); ولتحديد قيم وسطاء هذه التعليمة يجب تحديد المعلومتين التاليتين : ١- حجم حيز الرو ية (البعد بين الوجه الا مامي والوجه الخلفي) الذي نريد ا ن يظهر ضمنه نموذجنا وسنرمز له بالرمز D. ٢- تحديد ا حداثيات مركز الحيز والتي نعبر عنها بالثلاثية التالية: c.z) ). c.x, c.y, عندها تكون قيم وسطاء التابع glortho كالتالي: Znear = 1.0; Zfar = Znear + D; GLdouble left = c.x - D; GLdouble right = c.x + D; GLdouble bottom c.y - D;

GLdouble top = c.y + D; وعندها نكتب في برنامجنا التعليمات التالية: glmatrixmode(gl_projection); glloadidentity(); glortho(left, right, bottom, top, Znear, Zfar); glmatrixmode(gl_modelview); glloadidentity(); الا سقاط في المستوي المتلاشي أو المنظوري: وتقدم الOpenGL تعليمتين من ا جل الا سقاط المتلاشي هما: التعليمة : glfrustum glfrustum (left,right,bottom,top,znear,zfar); وتحدد بارمترات هذه التعليمة تماما كما في التعليمة.glOrtho التعليمة :gluperspective gluperspective (fov, aspect, Znear, Zfar);

ويمثل الوسيط fov فتحة العدسة ا و زاوية الا ظهار ويمثل الوسيط aspect نسبة عرض النافذة على طولها فا ذا كانت النافذة بشكل مربع عندها تكون قيمة ال aspect=1 ولكن عندما تكون غير ذلك عندها نستخدم المعادلات التالية لحساب قيم ال :right left top bottom GLdouble aspect = (GLdouble) windowwidth /windowheight; if ( aspect < 1.0 ) // window taller than wide bottom /= aspect; top /= aspect; else left *= aspect; right *= aspect; ا ن التعليمتين gluperspective glfrustum تقومان بنفس العمل ولكن تعتبر التعليمة glfrustum تخيلية وتعتمد على القيم التجريبية في حين تعتبر التعليمة gluperspective ا كثر استخداما وواقعية. في المثال السابق الذي عرضنا فيه نموذج الوردة استخدمنا تعليمة gluperspective في الا سقاط المتلاشي ومن ا جل تكبير ا و تصغير حيز الرو ية كنا نزيد من قيمة الوسيط fov ا و ننقصه. وبالنسبة لنموذج الوردة في الا سقاط المتوازي فا ننا تحكمنا بقيمة Zfar بالزيادة ا و النقصان. ا ما لمعرفة الا ثر الناتج عن تغيير قيم الوسيط aspect فسنعرض المثال التالي:

وبالنسبة لتحويل الرو ية تستدعى التعليمة glulookat بالشكل التالي: glulookat (0.0, 0.0, D/2,c.x, c.y, c.z,0.0, 1.0, 0.0); حيث ا ن الشعاع z المتعلق بموقع العين يجب ا ن ينتمي لمجال حيز الرو ية بحيث يكون ا كبر من Znear وا صغر من. Zfar وا لا فا ن النموذج سيصبح غير مري ي.

لاحظ كيف عندما بدا ت zeye تتساوى مع zfar بدا النموذج بالاختفاء. والا ن بفرض ا ن المستخدم يريد ا ن يقوم بعملية التكبير ا و التصغير بواسطة متحول وليكن zoomfactor عندها تستدعى التعليمات السابقة كالتالي : glortho (left*zoomfactor, right*zoomfactor, bottom*zoomfactor, top*zoomfactor, znear, zfar); glfrustum(left*zoomfactor, right*zoomfactor, bottom*zoomfactor, top*zoomfactor, znear, zfar); gluperspective (50.0*zoomFactor, (float)width/(float)height, znear, zfar); مع ملاحظة ا ن ا ي خطا بالقيم الممرة قد يتسبب بعدم ظهور النموذج. مثال ١ : glmatrixmode(gl_projection); glloadidentity(); gluperspective(50.0, 1.0, 3.0, 7.0); glmatrixmode(gl_modelview); glloadidentity(); glulookat(0.0, 0.0, 5.0,0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

لاحظ كيف يعمل التحويلين الا سقاط والرو ية مع بعضهما. لدينا في هذا المثال زاوية الرو ية تساوي ٥٠ درجة ال aspect تساوي واحد Znear=3 Zfar=7 عندها يكون حجم حيز الرو ية يساوي ٤. لاحظ الا ن ا ن مكان عين الناظر تقع في (0.0,0.0,5.0) وا ن اتجاه النظر نحو المركز (0.0,0.0,0.0). هذا يعني ا ن عين الناظر تبعد عن النقطة التي ننظر ا ليها بمقدار ٥ وبالتالي فهي تقع ضمن حيز الرو ية الذي يبدا عند Znear=3 وينتهي عند.Zfar=7 ولكن ا ذا وضعنا عين الناظر في الموقع ( 0.0,0.0,1.0 )ا و (0.0,0.0,10.0) عندها لن يظهر ا ي جزء من #include <GL/glut.h> #include <stdlib.h> D GLdouble void init(void) ) (0.0, 0.0, 0.0, 0.0 glclearcolor ) glshademodel (GL_FLAT void display(void) النموذج لا ن موقع العين لم تعد داخل حيز الرو ية. مثال ٢ : بفرض لدينا مكعب نريد تطبيق تحويل الا سقاط عليه : ( glclear(gl_color_buffer_bit glcolor3f (1.0, 1.0, 1.0); /* viewing transformation */ glulookat (0.0, 0.0, D/2, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); glutwirecube (1.0); glflush (); void reshape(int w, int h) 5 = D GLdouble aspect = (GLdouble) w / h 1.0 = Znear GLdouble D GLdouble Zfar = Znear + 0 = cx GLdouble 0 = cy GLdouble D GLdouble left = cx - D GLdouble right = cx + D GLdouble bottom = cy - GLdouble top = cy + D; if ( aspect < 1.0 ) // window taller than wide aspect bottom /= aspect top /= else aspect left *= aspect right *=

عندها سيكون الخرج كالتالي : وباستخدام التعليمة glfrustum نفس قيم الوسطاء سنحصل على الخرج التالي: glfrustum (left, right, bottom, top, Znear, Zfar); لاحظ الاختلاف بالنتاي ج وهذا ما ا شرنا ا ليه با ن ال gluperspective ا قرب للواقع وا ن glfrustum تعتمد على القيم التجريبية. وا ذا استخدمنا التعليمة glortho فسنحصل على النتيجة التالية:

وهذا ما سبق وذكرناه ا يضا با ن الا جزاء الداخلية من الشكل في الا سقاط المتوازي لن تظهر وسنرى فقط الوجه الا مامي.

تحويل نافذة الرو ية : ViewPort Transformation تعريف نافذة الرو ية :عبارة عن مستطيل ي قط ع كل ا ظهار تتجاوز ا حداثياته حدود هذا المستطيل ويطلق عليه اسم بوابة العرض ا يضا. ولنا خذ الشكل التالي كمثال للتوضيح : لاحظ من الشكل المستطيل الملون باللون الا زرق يمثل هذا المستطيل نافذة الرو ية بمعنى ا نه لن يظهر من الشكل ا لا هذا الجزء المحدد بالمستطيل.ولفهم نافذة الرو ية بشكل ا كبر يمكن الرجوع لكاميرا التصوير وتشبيهها بالمربع الذي يظهر ضمن العدسة حيث كلنا يعلم ا ن الا جزاء التي توضع ضمن هذا المربع هي فقط التي ستظهر ضمن الصورة. الھدف من ھذا التحویل : استطعنا سابقا ا ن نظهر العديد من الا شكال دون الحاجة ا لى استدعاء نافذة الرو ية وا ذا كان الهدف الا ساسي هو تحديد الا جزاء التي ستظهر فقط يمكن لا حدنا ا ن يفكر با ن هذا الموضوع يمكن التغلب عليه بعدم رسم هذه الا جزاء في الا ساس ولكن في الواقع ا ن الهدف من استخدام نافذة الرو ية تتمثل بالنقاط التالية : المحافظة على مكان ظهور الشكل على شاشة العرض البياني مهما تغيرت ا بعاد النافذة الري يسية مع المحافظة على الا بعاد النسبية له فمثلا لو اعتبرنا ا ن حجم النافذة الري يسية هو (w=250,h=250).١

وا ن الشكل الذي نريد ا ظهاره هو مضلع ا حداثياته هي (x1=25,y1=25,x2=75,y2=75) فيظهر الشكل كالتالي : الشكل a ولكن ا ذا قمنا بتكبير النافذة باستخدام زر التكبير عندها ستتغير ا حداثيات النافذة ولكن ا حداثيات المضلع وموقعه الا صلي في النافذة لن يتغير وسيظهر عندها بالشكل التالي : الشكل b

وبالمقارنة بين الشكلين a,b نجد ا ن المضلع في الشكل a كان يظهر في منتصف النافذة و في الشكل b ا صبح بعيدا عن المنتصف وا قرب ا لى زاوية النافذة وكذلك فا ن حجمه بدا وكا نه تغي ر مع ا ن موقعه و ا حداثياته لم يطرا عليهما ا ي تغيير ونفسر هذا الا مر بسبب عدم وجود ترابط نسبي بين حجم النافذة وحجم الشكل المعروض فعندما كبر حجم النافذة ولم يترافق هذا بكبر في حجم المضلع بدا الشكل وكا نه قد تغير مكانه وحجمه وقد يسبب هذا في الا شكال والنماذج الا كثر تعقيدا تشوها في الصورة و تحل هذه المشكلة باستدعاء نافذة الرو ية التي توجد علاقة نسبي ة بين حجم النافذة وحجم النموذج المعروض وتحافظ على موقع الا شكال التي تظهر في النافذة سواء ا كانت هذه الا شكال تظهر في منتصف النافذة ا و في ا طرافها ا و في ا ي مكان ا خر ومن ا جل المثال السابق ا ذا استدعينا نافذة الرو ية في ا جراي ية بعد تكبير النافذة كالتالي : ال Reshape فسيظهر الشكل لاحظ كيف بقي الشكل في منتصف النافذة وكيف تغي رت ا بعاده بما يتناسب مع تغ ير ا بعاد النافذة ا ظهار ا كثر من نسخة للنموذج المعروض في النافذة الري يسية وبا حجام مختلفة :قد يحتوي النموذج المعروض على ا شكال متشابهة ولكنها تختلف بحجمها فقط وا ذا فكرنا بكتابة ا جراي ية عرض ترسم كل من هذه الا شكال على حدا فا ن حجم البرمجة سيكون كبير جدا ومرهق للمبرمج وقد ح ل ت هذه المشكلة با نشاء ا كثر من نافذة رو ية ضمن النافذة الري يسية وبتغيير ا حجام هذه النوافذ يتغير حجم الشكل المعروض ضمنها. ولنا خذ على سبيل المثال تطبيق يعرض شجرة واحدة..٢

وا ذا ا ردنا تحويل هذا النموذج لعرض حديقة من الا شجار بحيث نظهر في الحديقة ا شجار كبيرة وا خرى صغيرة فلن نكون مضطرين ا لى كتابة كود من ا جل ا ظهار كل تلك الا شجار وا نما فقط ننشي عدة نوافذ رو ية نظهر ضمنها نفس الشكل باستدعاي ه فقط وسنحصل على حديقة الا شجار التالية.

مثال ٢: ا ظهار النموذج في عدة نوافذ رو ية من عدة جوانب. كما يمكن الاستفادة ا حيانا من نافذة الرو ية بتكبير ا و تصغير النموذج المعروض وذلك بالتحكم با بعاد النافذة وحجمها وكذلك يمكن تغيير مكان النافذة ا ثناء تشغيل التطبيق بالتحكم با حداثيات موقع بداية النافذة وهذا قد يفيدنا ا يضا بتحريك النموذج المعروض..٣ ولا نشاء نافذة الرو ية في ال OpenGL هناك تابع يدعى glviewport و بارامتراته هي الا حداثيي x,y اللذان يمثلان مبدا الا حداثيات للنافذة و h,w اللذان يمثلان عرض وارتفاع النافذة. glviewport (x,y,(glsizei) w,(glsizei) h); وتستدعى هذه التعليمة في ا جراي ية ال Reshape.و تنشا نافذة الرو ية ضمن النافذة الا ساسية التي تمثل شاشة العرض البياني.وتتشابه هاتين النافذتين ا لى حد كبير ا لا ا نه يوجد فرق ا ساسي بينهما مرتبط بمبدا الا حداثيات لكل منهما حيث ا ن مبدا ا حداثيات النافذة الا ساسية في الزاوية العليا اليسارية من الشاشة ومحور السينات موجه من اليسار ا لى اليمين ومحور العينات موجه من الا على ا لى الا سفل ا ما مبدا ا حداثيات نافذة الرو ية في الزاوية السفلى اليسارية من الشاشة ومحور السينات موجه من اليسار نحو اليمين ومحور العينات موجه من الا سفل نحو الا على.

كیفیة تحدید إحداثیات نافذة الرؤیة : ذكرنا ا ن مبدا الا حداثيات لنافذة الرو ية في الزاوية اليسارية السفلى ولا نشاء نافذة الرو ية يجب معرفة ا حداثيي المبدا ( x,y )ومن ثم حساب طول وعرض هذه النافذة حيث : W = x2-x1 H = y2-y1 حساب إحداثیي المبدأ : من الشكل السابق نلاحظ ا ن الا حداثي x x1= ا ما الا حداثي y فيحسب كالتالي : Y = Hw -y2 وذلك لا ن y تمثل البعد عن الحافة السفلى للنافذة الري يسية. مثال:

بفرض ا ن ا بعاد الشاشة الري يسية السابقة( 400,400 ) وبفرض ا ن الا حداثيي (x1=10,y1=260) (x2=100,y2=340). عندها يكون ا حداثيي المبدا لنافذة الرو ية 10,yv=60) = xv )بالنسبة للنافذة الري يسية. قلنا في الفقرة السابقة ا ن ا حدى الفواي د التي نحصل عليها من نافذة الرو ية هو ا ظهار ا كثر من نسخة من الشكل ا و النموذج في النافذة الري يسية الواحدة وا خذنا على سبيل المثال حديقة الا شجار وفي الواقع ا ن عملية ا نشاء مجموعة النوافذ هذه وتشكيل حديقة الا شجار غالبا ما تكون بتدخل من المستخدم وذلك باستخدام الطرفيات المتاحة له مثل لوحة المفاتيح والفا رة. حيث يستعين المستخدم بالفا رة لتحديد مكان الشجرة وحجمها فيتم ا نشاء نافذة رو ية في المكان والحجم الذي حدده المستخدم. و يتحدد مكان نافذة الرو ية ا و الشجرة باختيار نقطة في الزاوية العليا اليسارية من الشاشة واختيار نقطة ثانية في الزاوية السفلى اليمينية من الشاشة وتطبيق طريقة حساب مبدا الا حداثيات السابقة. مقارنة بین نافذة الرؤیة والنوافذ الجزي یة: النوافذ الجزي یة :

يتم ا نشاء نوافذ جزي ية ضمن النافذة الا ساسية ويتم التعامل مع كل نافذة بشكل مستقل عن بقية النوافذ ولكل نافذة جزي ية ا جراي يات تهيي ة وا عادة رسم و ا جراي ية عرض وغيرهامن الا جراي يات المتعلقة بالا حداث (كا جراي ية الفا رة لوحة المفاتيح القواي م) الخاصة بها. نقاط التشابھ: تشبه نافذة الرو ية النوافذ الجزي ية ب: يمكن ا نشاء عدة نوافذ رو ية وعدة نوافذ جزي ية في التطبيق كما يمكن التحكم بحجم النوافذ الجزي ية تماما كنوافذ الرو ية. وتخضع النوافذ الجزي ية لتحويلات النمذجة كنوافذ الرو ية.١.٢.٣ نقاط الاختلاف: تختلف نافذة الرو ية عن النوافذ الجزي ية بعدة نقاط نذكر منها: مبدا الا حداثيات : حيث تتشابه النوافذ الجزي ية بمبدا ا حداثياتها مع النافذة الري يسية حيث يعتبر مبدا الا حداثيات في الزاوية العليا اليسارية في حين مبدا ا حداثيات نافذة الرو ية في الزاوية السفلى اليسارية..١ النماذج الرسومية : في نافذة الرو ية يتكرر نفس الشكل المعروض في النافذة الا ساسية با حجام مختلفة ولكن لا يمكن ا ظهار ا شكل جديدة في نافذة الرو ية على العكس من النوافذ الجزي ية والتي تتمتع باستقلاليه بنماذجها وا شكالها التي ترسمها حيث يمكن ا ظهار ا شكال مختلفة وغير مرسومة في النافذة الا ساسية..٢

ترتبط النوافذ الجزي ية مع النافذة الا ساسية بعلاقة ا ب- ابن. حيث تعتبر النوافذ الجزي ية الموجودة في نفس المستوى ا بناء للنافذة الا ساسية في حين لاتوجد هكذا علاقة بين اوافذ الرو ية والنافذة الري يسية. يمكن ا نشاء عدة نوافذ جزي ية ضمن نافذة جزي ية ما كما يمكن ا نشاء عدة نوافذ رو ية ضمن النافذة الجزي ية ا يضا..٣.٤ بعض التعليمات المتعلقة بالنوافذ الجزي ية :.١ ا نشاء النوافذ الجزي ية: يمكن ا نشاء عدد غير محدد من النوافذ الجزي ية وتعيد هذه الا جراي ية رقم النافذة الجزي ية المولدة و نستفيد من هذا الرقم كثيرا في التطبيقات ا ما بارمتراتها فهي : رقم النافذة الا ب التي ا نشي ت فيها النافذة الجزي ية. وباقي البارمترات فهي تخص ا بعاد النافذة الجزي ية المراد ا نشاو ها. int glutcreatesubwindow(int win,int x, int y, int width, int height);.٢ تفعيل النافذة الجزي ية : حتى نتمكن من التعامل مع النافذة الجزي ية كا نشاء قواي م ا و ا ظهار نموذج رسومي و تفعيل ا حداث الفا رة ولوحة المفاتيح يجب تفعيل النافذة المراد التعامل معها ا ولا ونستخدم لذلك التعليمة التالية: void glutsetwindow(int win); بارمتر هذه التعليمة هو رقم النافذة الجزي ية (الذي تولد عند الا نشاء) المراد تفعيلها. ٣. الحصول على النافذة الجزي ية المفع لة : ولمعرفة النافذة الجزي ية الحالية يمكن استخدام التعليمة: int glutgetwindow(void); حيث تعيد رقم النافذة الجزي ية المفع لة. ٤. هدم النافذة الجزي ية: لتخلص من النافذة الجزي ية يمكن هدمها باستخدام التعليمة التالية: void glutdestroywindow(int win); التي نمرر لها رقم النافذة المراد هدمها. تمرين ١ :

اكتب تطبيق رسومي تظهر فيه الشجرة بحسب الشكل السابق ومن ثم حول هذا التطبيق ليكون تفاعلي بحيث يمكن للمستخدم تحديد نافذة الرو ية وا ظهار شجرة بداخلها باستخدام ا حداث الماوس. تمرين ٢ : اكتب تطبيق يرسم فيه مصور الجمهورية العربية السورية مع تسمية الحدود وبعض المدن الري يسية. تو خذ المعلومات المتعلقة بالحدود من ملف جاهز مسبقا كما يظهر فيه: دليل المصور ا سفل ويسار النافذة الري يسية. ا ظهار نسخ صغيرة للمصور في الزوايا الباقية للنافذة الري يسية ) باستخدام (subwindow كل نسخة تحوي معلومات ا حصاي ية معينة ) ا مطار سكان كثافة مساحة). تو خذ المعلومات من ملف جاهز مسبقا ويتم ا ظهار المعلومة بشكل بياني مناسب. عند الضغط على ا حدى النسخ الموجودة في زوايا النافذة يتم تحريكها باتجاه وسط النافذة مع تكبير مناسب لتحل محل المصور الا صلي. رسم مخططات بيانية للمعلومات الا حصاي ية.(Histograms) رسم علم الجمهورية على ا ية بوابة رو ية يتم تحديدها عن طريق الفا رة. - - - - - ملاحظة: يتم تنفيذ المطلوب باستخدام لوحة المفاتيح والفا رة والقواي م. تمرين ٣ : اكتب تطبيق يظهر حركة الا رض حول الشمس مع ا خذ حركة الا رض حول نفسها بعين الاعتبار مطبقا كل التحويلات اللازمة التي تعلمتها سابقا. تمرين ٤ :

بفرض لدينا كرة موضوعة داخل مكعب وبا عطاء هذه الكرة سرعة ابتداي ية تبدا بالحركة داخل المكعب وعند اصطدامها بحواف المكعب تتخامد سرعة هذه الكرة حتى تتوقف. مستفيدا من قانون الطاقة الحركية ومن التحويلات التي تعلمتها. اكتب تطبيق يظهر حركة الكرة و تخامدها

تحويل القطع : Clipping Transformation تعريف القطع : وهو اقتطاع لجزء من النموذج المرسوم يقع خارج حدود شاشة الا ظهار ا و خارج حواف نافذة معينة تدعى هذه الحواف بحدود القص. وتنجز عملية القص هذه وفق مفهوم الا خفاء لا زالة كل شيء خارج مجال القص. فمثلا في مشهد ما ا ذا غيرنا زاوية الرو ية (تغيير مكان الكاميرا) ستتغير الا جزاء التي ستظهر من النموذج وكذلك الا جزاء التي ستختفي منه. جذع هرم القطع: هو مخروط ناقص له ستة سطوح يتم القطع وفقا لها. وهذه السطوح تكون عادة عمودية على المحاور الا حداثية الخاصة بمجال ا حداثيات العين. كل ما يقع ضمن جذع الهرم يعد مري ي وكل مايقع خارج هذا المجال غير مري ي. استطاعت ال OpenGL ا ن تحقق عمليات القطع والا خفاء وفق هذه السطوح الستة بالا ضافة ا لى ا مكانية تعريف سطوح قطع ا خرى تعرف بالمعادلة التالية: Ax+By+Cz+D = 0. تخضع هذه المعادلة لتحويل يجعلها ضمن مجال هرم الرو ية وهذا التحويل يتم باستخدام معكوس مصفوفة التحويلات modelview matrix وكل نقطة تحقق المتراجحة التالية:

>= 0 we)t (A B C D)M-1 (xe ye ze تقع ضمن مجال الرو ية حيث xe ye ze we نقاط ا حداثيات العين (الرو ية). تابع القطع في ال :OpenGL تحقق الOpenGl عملية القص والا خفاء باستخدام تابع القص الذي يا خذ الشكل التالي : void glclipplane(glenum plane, const GLdouble *equation); بارمتراته : GL_CLIP_PLANEi تحديد السطح الذي سيتم اقتطاعه ويعرف على شكل ثابت يا خذ القيمة : Plane حيث i هو عدد صحيح يتحدد من خلاله رقم السطح الذي سي قتط ع. : equation عبارة عن شعاع من ا ربع معاملات Ax+By+Cz+D = 0 يمثل معادلة سطح القطع الذي يحدده المستخدم. بالا ضافة ا لى هذا التابع فا ننا بحاجة ا لى استخدام تابع لتفعيل عملية القطع وهذا التابع هو : glenable(gl_clip_planei); و بالمقابل يمكن عدم تفعيل القطع بالتابع gldisable(gl_clip_planei); ملاحظة : تعيد ال OpenGL بناء حواف النموذج الذي تم اقتطاعه بشكل ا لي. مثال: بفرض لدينا الشكل التالي : ونريد ا جراء قطع لنصف السفلي

وقطع لنصف اليساري فنحصل على الشكل التالي : void display(void) GLdouble eqn0[4] = 0.0, 1.0, 0.0, 0.0; GLdouble eqn1[4] = 1.0, 0.0, 0.0, 0.0; glclear(gl_color_buffer_bit); glcolor3f (1.0, 1.0, 1.0); glpushmatrix(); glulookat (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); */ clip lower half -- y < 0/* glclipplane (GL_CLIP_PLANE0, eqn0); glenable (GL_CLIP_PLANE0); */ clip left half -- x < 0/* glclipplane (GL_CLIP_PLANE1, eqn1); glenable (GL_CLIP_PLANE1); glrotatef (90.0, 1.0, 0.0, 0.0); glutwiresphere(1.0, 20, 16); glpopmatrix(); glflush (); // end display تمرين : ا عد كتابة المثال السابق بحيث يظهر الشكل التالي :

اجري عملية القطع على المحور z و لاحظ الخرج.

الفصل الخامس السطوح والمنحنيات مقدمة: تتا لف المنحنيات والسطوح من ا غراض ذات خطوط مستقيمة وقد يكون توصيفها بمعادلة رياضية ممكنا ا و غير ممكن ولكن يمكن تصميم ا ي منحني عن طريق استعمال نقاط التحكم. كلما زادت نقاط التحكم كلما زادت نعومة المنحني ودقته. منحني بيزييه :Bezier curve خط مولد رياضيا يمثل منحنيات غير نظامية. وعملية التوليد تتم وفق خوارزميات معينة. وقد كان العالم الفرنسي الرياضي بيير بيزييه ا ول من قدم وصفا لهذه المنحنيات وفق خوارزميات. وتتمتع منحنيات بيزييه با نها لا تحتاج ا لى ا كثر من بضع نقاط لكي تعرف عددا كبيرا من الا شكال غير النظامية. وفي البرامج الرسومية تستخدم منحنيات بيزييه لرسم ا شكال حرة غير نظامية ناعمة (ملساء) وسطوح واصلة بين نقطتين. نستخدم تعليمات ال OpenGL's evaluator لرسم المنحنيات والسطوح. ال :Evaluators توفر طريقة لتحديد النقاط على المنحني ا و السطح ا و على جزء منهما باستخدام نقاط التحكم. ومن ثم يمكن رسم المنحني ا و السطح بشكل واضح ودقيق. يمكن توظيف النقاط التي تولدها عملية ال Evaluator لعدة استخدامات منها :

١- تحديد المكان المطلوب لرسم السطح ٢- رسم نموذج خطي للسطح ٣- وكذلك لرسم سطوح مضيي ة ومظلله. تعطى معادلة المنحني بشكل عام كالتالي: C(u) = [X(u) Y(u) Z(u)] حيث : يا خذ المتحول u قيم مختلفة من مجال ما. تعطى معادلة السطح بشكل عام كالتالي: S(u,v) = [X(u,v) Y(u,v) Z(u,v)] حيث تا خذ كل من u,v قيم مختلفة من مجالات مختلفة. من ا جل كل نقطة u تعطي الصيغة c(u) ا و s(u) نقطة من نقاط المنحني ا و السطح. ولاستخدام ال evaluator يجب في البداية تعريف الصيغتين c(u) ا و s(u) ومن ثم استخدام التعليمة glevalcoord1 ا و glevalcoord2 بدلا من.glVertex ويمكن التعامل مع عقد المنحني ا و السطح كغيرها من العقد vertices حيث يمكن استخدامها لتشكيل نقاط وخطوط. وهناك تعليمات ا خرى مسو ولة عن توليد سلسلة من هذه العقد والتي ينتج عنها في النهاية شبكة منتظمة ضمن مجال u. : One-Dimensional Evaluators.١ تعطى معادلة منحني بزييه بالعلاقة التالية: يعطى تابع الانحناء Bernstein من الدرجة n بالعلاقة التالية: Pi تمثل قيم نقطة التحكم.

مثال ١ : نستخدم فيه one-dimensional evaluators لرسم منحني بيزييه مستخدمين فيه ا ربع نقاط تحكم. Example 11-1 : Drawing a Bézier Curve Using Four Control Points: bezcurve.c #include <GL/gl.h> #include <GL/glu.h> #include "aux.h" GLfloat ctrlpoints[4][3] = -4.0, -4.0, 0.0, -2.0, 4.0, 0.0, 2.0, -4.0, 0.0, 4.0, 4.0, 0.0; void myinit(void) glclearcolor(0.0, 0.0, 0.0, 1.0); glmap1f(gl_map1_vertex_3, 0.0, 1.0, 3, 4,&ctrlpoints[0][0]); glenable(gl_map1_vertex_3); glshademodel(gl_flat); void display(void) int i; glclear(gl_color_buffer_bit GL_DEPTH_BUFFER_BIT); glcolor3f(1.0, 1.0, 1.0); glbegin(gl_line_strip); for (i = 0; i <= 30; i++) glevalcoord1f((glfloat) i/30.0); glend(); /* The following code displays the control points as dots. */ glpointsize(5.0); glcolor3f(1.0, 1.0, 0.0); glbegin(gl_points); for (i = 0; i < 4; i++) glvertex3fv(&ctrlpoints[i][0]); glend(); glflush();

void myreshape(glsizei w, GLsizei h) glviewport(0, 0, w, h); glmatrixmode(gl_projection); glloadidentity(); if (w <= h) glortho(-5.0, 5.0, -5.0*(GLfloat)h/(GLfloat)w, 5.0*(GLfloat)h/(GLfloat)w, -5.0, 5.0); else glortho(-5.0*(glfloat)w/(glfloat)h, 5.0*(GLfloat)w/(GLfloat)h, -5.0, 5.0, -5.0, 5.0); glmatrixmode(gl_modelview); glloadidentity(); void main(int argc, char** argv) glutinit(&argc, argv); glutinitdisplaymode (GLUT_SINGLE GLUT_RGB GLUT_DEPTH); glutinitwindowsize (600, 450); glutcreatewindow(argv[0]); myinit(); glutreshapefunc(reshape); glutdisplayfunc(display); glutmainloop(); يكون الخرج :

في هذا المثال رسمنا منحني بزييه بالاستعانة با ربعة نقاط تحكم تم تعيينها في المصفوفة [][]ctrlpoints واستخدمت هذه المصفوفة كبارمتر للتعليمة glmap1f حيث تا خذ هذه التعليمة البارمترات التالية: GL_MAP1_VERTEX_3 : لتوليد عقد ثلاثية البعد. البارمتر ذو القيمة 0: الحد الا دنى للمجال الذي تنتمي ا ليه قيم المتحول u. البارمتر ذو القيمة ١: الحد الا عظم للمجال الذي تنتمي ا ليه قيم المتحول u. البارمتر ذو القيمة ٣: عدد النقاط المولدة بين كل نقطة تحكم و نقطة التحكم التي تليها حيث تا خذ - - - - النقاط المولدة قيما ذات فواصل عشرية. البارمتر ذو القيمة ٤: يحدد درجة المنحي وتعطى درجة المنحني بالعلاقة degree+1 n= حيث n هنا تساوي 4 فبالتالي درجة المنحي تساوي. ٣ &ctrlpoints[0][0] : مصفوفة نقاط التحكم. - - وتفيد التعليمة glenable في تفعيل one-dimensional evaluator ويتم رسم المنحي ضمن الا جراي ية display() ضمن التعليمتني glend() glbegin(). وبما ا ننا قمنا بتفعيل عملية ال evaluator فا ن التعليمة glevalcoord1f() ستعمل بشكل مشابه تماما لعمل التعليمة glvertex() ويكون بارمتر هذه التعليمة عبارة عن ا حدى قيم المتحول u الذي ينتمي للمجال [0,1]. : Two-Dimensional Evaluators.٢ تتشابه المفاهيم هنا مع تلك التي تعرفنا عليها سابقا في ال One-Dimensional Evaluators باستثناء ا نه هنا سيتم التعامل مع بارمترين هما u,v بدلا من بارمتر واحد. تعطى الصيغة الممثلة لسطوح بيزييه بالعلاقة التالية : حيث : Pij مجموعة قيم نقاط التحكم. : Bi نفس التابع الذي مر معنا سابقا.

نعرف ال evaluator بالتعليمة glmap2*(). ونفعل هذه العملية باستخدام التابع glenable ثم نحقق عملية رسم السطح باستخدام التعليمة glevalcoord2() التي يتم استدعاو ها بين التعليمتين void glevalcoord2fdv(type u, TYPE v);.glend() glbegin() مثال ٢ : نستخدم فيه tow-dimensional evaluators لرسم سطح بيزييه. Example: Drawing a Bézier Surface: bezsurf.c #include <GL/gl.h> #include <GL/glu.h> #include "aux.h" GLfloat ctrlpoints[4][4][3] = -1.5, -1.5, 4.0, -0.5, -1.5, 2.0, 0.5, -1.5, -1.0, 1.5, -1.5, 2.0, -1.5, -0.5, 1.0, -0.5, -0.5, 3.0, 0.5, -0.5, 0.0, 1.5, -0.5, -1.0, -1.5, 0.5, 4.0, -0.5, 0.5, 0.0, 0.5, 0.5, 3.0, 1.5, 0.5, 4.0, -1.5, 1.5, -2.0, -0.5, 1.5, -2.0, 0.5, 1.5, 0.0, 1.5, 1.5, -1.0 ; void display(void) int i, j; glclear(gl_color_buffer_bit GL_DEPTH_BUFFER_BIT); glcolor3f(1.0, 1.0, 1.0); glpushmatrix (); glrotatef(85.0, 1.0, 1.0, 1.0); for (j = 0; j <= 8; j++) glbegin(gl_line_strip);

ويكون الخرج كالتالي: مثال ٣ : وسنعرض في هذا المثال سطح بيزييه بشكل مضاء مستخدمين تعليمتين جديدتين لم نتحث عنهما سابقا هما : ) glmapgrid2,glevalmesh2 تعرف بمفردك على هاتين التعلیمتين (.

Example: Drawing a Lit, Shaded Bézier Surface Using a Mesh: bezmesh.c void initlights(void) GLfloat ambient[] = 0.2, 0.2, 0.2, 1.0 ; GLfloat position[] = 0.0, 0.0, 2.0, 1.0 ; GLfloat mat_diffuse[] = 0.6, 0.6, 0.6, 1.0 ; GLfloat mat_specular[] = 1.0, 1.0, 1.0, 1.0 ; GLfloat mat_shininess[] = 50.0 ; glenable(gl_lighting); glenable(gl_light0); gllightfv(gl_light0, GL_AMBIENT, ambient); gllightfv(gl_light0, GL_POSITION, position); glmaterialfv(gl_front_and_back, GL_DIFFUSE, mat_diffuse); glmaterialfv(gl_front_and_back, GL_SPECULAR, mat_specular); glmaterialfv(gl_front_and_back,gl_shininess, mat_shininess); void display(void) glclear(gl_color_buffer_bit GL_DEPTH_BUFFER_BIT); glpushmatrix(); glrotatef(85.0, 1.0, 1.0, 1.0); glevalmesh2(gl_fill, 0, 8, 0, 8);

تمرين : اكتب تطبيق لرسم منحني بيزييه بحيث يتم تحديد نقاط التحكم من قبل المستخدم بواسطة الماوس ثم يرسم المنحني ولاحظ الا شكال المختلفة لمنحني بيزييه بحسب اختلاف نقاط التحكم وا ليك بعض الا مثلة :

الفصل السادس الشفافية والضبابية مقدمة: قدمت لنا ال OpenGL الكثير من الحلول لرسم الصور وتجسيد المناظر الطبيعية فكانت توابع الحركة التي ساعدت على التحكم بمكان ظهور الا شكال وطريقة توضعها وكانت توابع الرو ية التي حددت الزاوية التي ي نظر من خلالها للمشهد. كما استطعنا التمييز بين نوعيين من الا سقاط (المتوازي والمتلاشي). وعندما تراكبت السطوح مع بعضها وفرت ال OpenGL توابع لاقتطاع وا خفاء السطوح. وهنا سنقف لنتساءل لماذا اقتطعنا الجزء المتراكب من السطح لماذا كانت النتيجة الطبيعية للتراكب هي اقتطاع وا خفاء ذلك الجزء! الجواب : لا ن كل السطوح والا شكال التي تعاملنا معها حتى هذه اللحظة كانت ذات طبيعة مصمتة وغير نفوذه. ولكن في العالم الحقيقي الا مر مختلف حيث تتنوع طبيعة المواد والسطوح فمنها الشفاف ونصف الشفاف والمصمت. فا ذا تراكب سطحان شفافان و ملونان لن يخفي ا حدهما الا خر وا نما سيظهر الجزء المتراكب بلون مركب من لون السطحين. وبما ا ن ال OpenGL تهتم بتجسيد النماذج الواقعية ا لى حد كبير كان لابد لها من تقديم توابع تخدم هذه الفكرة " الشفافية والمزج اللوني للسطوح الشفافة المتراكبة". ا ما من ناحية ا خرى فقد وفرت لنا ال OpenGL توابع لا عطاء المشاهد الطبيعية ا لوان حقيقية وا ضاءة راي عة. فاستطاعت ا ظهارها با لوان زاهية وبا ضاءة براقة ا و با لوان قاتمة وا ضاءة كامدة ا و مظلمة. ولكن ماذا عن الا حوال الجوية ماذا لو كنا نريد تجسيد وتمثيل منظر طبيعي في يوم ضبابي كيف ستعالج ال OpenGL موضوع "الضباب"!. سنناقش فيما يلي هاتين الفكرتين (الشفافية والمزج اللوني الضبابية) وسنرى ما هي التوابع التي تقدمها ال OpenGL لتحقيق ذلك. : الشفافية والمزج اللوني الشفافية:

لنتذكر معا تابع التلوين glcolor*() الذي يا خذ ا ربعة وسطاء RGBA حيث كانت الR تمثل مرك بة اللون الا حمر وال G تمثل مرك بة اللون الا خضر والB تمثل مرك بة اللون الا زرق. ا ما بالنسبة للمركبة الرابعة A فكنا ندعوها ا لفا وكنا نعطيها داي ما قيمة افتراضية = ١,٠ و لكن لم نشرح لماذا هذه القيمة بالذات ولماذا لم نكن نغيرها في كل الا مثلة التي مرت معنا سابقا. كما ا ننا را ينا هذه المركبة عندما درسنا المصادر الضوي ية وعندما حددنا خصاي ص المواد. ولكن ما الفاي دة الحقيقة وراء القيمة ا لفا تحدد قيمة المركبة ا لفا درجة شفافية السطح المرسوم فعندما تكون قيمتها تساوي الواحد هذا يعني ا ن السطح مصمت وغير نفوذ وكلما قلت قيمة المركبة ا لفا كلما زادت شفافية سطح الشكل المرسوم. كما ا نها تلعب دور هام في عملية المزج اللوني. فبفرض لدينا سطحين شفافين الا ول لونه ا حمر والثاني لونه ا زرق فا ذا حصل تراكب بين هذين السطحيين سيظهر الجزء المتراكب بلون بنفسجي مع العلم ا ن شدة لون الجزء المتراكب تختلف بين فاتح وغامق بحسب شفافية السطح الا مامي فا ذا كانت شفافية السطح الا مامي كبيرة فا ن جزءا كبيرا من لون السطح الخلفي سيظهر للعيان. المزج اللوني : تتم عملية المزج اللوني بعد الانتهاء من مسح الصورة وتحويلها ا لى مجموعة بكسلات ولكن قبل تخزينها في المخزن المو قت المسمى " Framebuffer ". مع العلم ا ن كل بكسل من هذه البكسلات تحمل مجموعة من البيانات تتعلق ب لون البكسل ا حداثياته...الخ. وتسمى هذه البكسلات الحاملة للبيانات ب. Fragments حيث تتم عملية مسح نقاط الصورة الا ولى ووضعها في المخزن المو قت ومن ثم مسح نقاط الصورة الثانية و قبل تخزين بكسلات الصورة الثانية نميز بين حالتين : ١. الحالة الا ولى: ا ذا لم يكن لدينا مركبة مثل ا لفا عندها سيتم وضع نقاط الصورة الثانية المشتركة بالا حداثيات مع نقاط الصورة الا ولى فوقها مسببا ا خفاء جزء من الصورة الا ولى. ٢. الحالة الثانية: في حالة وجود المركبة ا لفا فا ن وضع بكسلات من الصورة الثانية فوق بكسلات الصورة الا ولى في المخزن المو قت لن يسبب ا خفاء ا و ضياع لا ي بكسل من ا حدهما وبالتالي عند عرض الصورة على الشاشة ستظهر جميع البكسلات من كلتا الصورتين وبحسب الشفافية التي حددت بالقيمة ا لفا ستظهر بكسلات منطقة التراكب بلون مركب من لوني البكسلات المتوضعة فوق بعضها.

المصدر والوجهة: يستخدم مصطلحي المصدر والوجهة للدلالة على الجسميين المتراكبين حيث يسمي الجسم الذي تم رسمه ا ولا ووضعت بكسلاته في المخزن المو قت بالوجهة Destination ا ما الجسم الذي سيتم رسمه لاحقا والذي ستوضع بعض بكسلاته فوق بكسلات الا ول فيسمى بالمصدر.Source ملاحظة هامة : لا يمكن الاستفادة من القيمة ا لفا عند استخدام نظام الا لوان color-index وا نما يمكن رو ية تا ثير القيمة ا لفا في نظام الا لوان RGBA فقط. لون منطقة تراكب: ا ن المفهوم العام للمزج اللوني يقول: ويعطى بالشكل التالي : با ن لون السطح الناتج عن تراكب شكلين هو تركيب من لون السطحيين O(rgb) = S(rgb) * D(rgb) حيث S(rgb) هو لون المصدر D(rgb) هو لون الوجهة و O(rgb) هو لون الخرج. بحيث تطبق هذه المعادلة كالتالي : O(r) = S(r) * D(r) O(g) = S(g) * D(g) O(b) = S(b) * D(b) ولكن هذا صحيح فقط عندما تشابه الخصاي ص المادية لكلا السطحين في حين عند اختلاف هذه الخصاي ص بحيث يكون ا حد الجسمين شفاف ا كثر من الا خر عندها لن يكون اللون الناتج مجرد مزيج من اللونيين وا نما سيغلب على اللون الناتج لون ا حد السطحيين بحسب نفوذيتهما ولكن هذا لا يتحقق بمجرد ضرب القيميتين ا لفا لكلا الجسمين ببعضهما ا ي لا يمكن الحصول على درجة نفوذية الجزء المتراكب من خلال ضرب القيميتين ا لفا فقط. ا ذا هناك معادلة رابعة يجب ا خذها بعين الاعتبار وهي معادلة تحديد معامل المزج اللوني بحيث نحدد فيها ا ي من السطحين سيغلب لونه على منطقة التراكب. لنرمز لهذا المعامل بالرمز P يا خذ هذا المعامل مجموعة قيم ثابتة هي : Zero One Source Color Source Alpha Inverse Source Color Inverse Source Alpha Destination Color

Destination Alpha Inverse Destination Color Inverse Destination Alpha فمثلا : P(Zero) = P(rgb) = P(000) P(One) = P(rgb) = P(111) حيث يقابل كل ثابت من الثوابت السابقة بالمركبات الثلاثة rgb وهكذا...الخ. وتعطى معادلة اللون النهاي ي بعدة طرق بحسب نوع المزج المستخدم : مزج لوني ناتج عن عملية الجمع تكون معادلة المزج اللوني كالتالي : O(rgba) = (S(rgba) * P0(rgba)) + (D(rgba) * P1(rgba)) مزج لوني ناتج عن عملية الطرح تكون معادلة المزج اللوني كالتالي : O(rgba) = (S(rgba) * P0(rgba)) - (D(rgba) * P1(rgba)) مزج لوني ناتج عن عملية طرح معاكسة تكون معادلة المزج اللوني كالتالي : O(rgba) = (D(rgba) * P1(rgba)) - (S(rgba) * P0(rgba)) حيث يترك للمستخدم اختيار قيمة كل من P0 P1 من مجموعة الثوابت التي عرضناها سابقا مع مراعاة الشرط التالي : لا يمكن ا ن يا خذ المعامل P0 نفس قيمة لون المصدر وكذلك لا يسمح با ن يا خذ المعامل P1 نفس لون الوجهة. ملاحظة: قد يتساءل البعض عن سبب تنوع عمليات المزج اللوني ا ن هذا التنوع يتيح لنا ا ظهار المزج اللوني المماثل للواقع والذي نراه في حياتنا اليومية عند تراكب سطحين نفوذ ين بالا ضافة ا لى ا ظهار ا نواع ا خرى من المزج التي قد تستخدم لا جراء عمليات خداع للبصر ا و ا ظهار بعض اللوحات الفنية الجميلة بحيث نستخدم مزجا يعطي تراكبا لونيا جميلا وغير متوقع. المزج اللوني في ال :OpenGL تستخدم ال OpenGL طريقة الجمع لا جراء عملية المزج اللوني O(rgba) = (S(rgba) * P0(rgba)) + (D(rgba) * P1(rgba))

حيث تستخدم التابع التالي : glblendfunc(glenum sfactor, GLenum dfactor) يمثل الوسيط sfactor قيمة المعامل P0 يمثل الوسيط dfactor قيمة المعامل. P1 وكما سبق وشاهدنا ا ن المعامل P يا خذ مجموعة قيم ثابتة فا ن ال OpenGL تقدم مجموعة الثوابت التالية لهذا المعامل. سنعرضها بالجدول التالي : القیم التي تقابھا الثوابت GL_ZERO (0, 0, 0, 0) GL_ONE (1, 1, 1, 1) GL_DST_COLOR GL_SRC_COLOR GL_ONE_MINUS_DST_COLOR GL_ONE_MINUS_SRC_COLOR GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPH A GL_DST_ALPHA GL_ONE_MINUS_DST_ALPH A GL_SRC_ALPHA_SATURATE (Rd, Gd, Bd, Ad) (Rs, Gs, Bs, As) (1, 1, 1, 1)-(Rd, Gd, Bd, Ad) (1, 1, 1, 1)-(Rs, Gs, Bs, As) (As, As, As, As) (1, 1, 1, 1)-(As, As, As, As) (Ad, Ad, Ad, Ad) (1, 1, 1, 1)-(Ad, Ad, Ad, Ad) (f, f, f, 1); f=min(as, 1-Ad) يكون عادة المعامل P1 متتم للمعامل. P0 فعندما يكون P0 = GL_SRC_ALPHA فا ن P1 = GL_ONE_MINUS_SRC_ALPH A وبالتالي ا ن قيمة ا لفا المختارة في تابع التلوين للكاي ن المصدر تلعب دورا هاما هنا ولكن ا ذا كان = P0 P1 = Zero One عندها مهما كانت قيمة ا لفا المختارة في تابع التلوين لن يكون لها ا ي ا ثر وسيغلب بجميع الا حوال لون المصدر على الوجهة و سيسبب ا خفاء الجزء المتراكب من الوجهة. ولا يوجد ما يمنع المبرمج

من اختيار قيم ل P1 P0 دون ا ن يكون بينهما ا ي علاقة بمعنى دون ا ن يكون P1 متتم ل P0 سوى ا نه قد لا يحصل على النتيجة المرغوبة في حال اتباعه ا سلوب عشواي ي في اختيار قيم. P0 P1 ويكون استدعاء التابع glblendfunc بالشكل التالي : glblendfunc(gl_src_alpha, GL_ONE_MINUS_SRC_ALPHA); glblendfunc(gl_one, GL_ZERO); يجب التنويه ا لى ا ن عملية المزج اللوني لا تتم ما لم نقوم بتفعيلها باستخدام التابع. glenable(gl_blend); والا ن لنا خذ مثال نرى فيه كيف يمكن ا جراء المزج اللوني في ال. OpenGL مثال: بفرض ا نه لدينا سطحين متراكبين ا حدهما لونه ا زرق والا خر لونه ا صفر وبفرض ا ن السطح الا صفر هو الوجهة وا ن السطح الا زرق هو المصدر وبفرض ا ن قيمة ا لفا للمصدر تساوي ٠,٧٥ وبفرض ا ن تابع المزج اللوني يا خذ القيم التالية : glblendfunc (GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA ); عندها سيكون اللون الغالب على منطقة التراكب هو اللون الا زرق. وسيكون الخرج كالتالي : وسنعرض فيما يلي النص البرمجي :

# #include "stdafx.h" #include <GL\glut.h> // Header File For GLUT Library #include <GL\GLAUX.h> // Header File For The Glaux Libra #include <GL\GLU.h> #include <GL\GL.h> */Initialize alpha blending function. /* static void init(void) glenable (GL_BLEND); glblendfunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glshademodel (GL_FLAT); glclearcolor (0.0, 0.0, 0.0, 0.0); static void drawlefttriangle(void) static void drawrighttriangle(void) */ draw yellow triangle on LHS of screen /* */ draw cyan triangle on RHS of screen/* glbegin (GL_TRIANGLES); glbegin (GL_TRIANGLES); glcolor4f(1.0, 1.0, 0.0, 0.75); glcolor4f(0.0, 1.0, 1.0, 0.75); glvertex3f(0.1, 0.9, 0.0); glvertex3f(0.9, 0.9, 0.0 ); glvertex3f(0.1, 0.1, 0.0); glvertex3f(0.3, 0.5, 0.0); glvertex3f(0.7, 0.5, 0.0); glvertex3f(0.9, 0.1, 0.0); glend(); glend(); void display(void) glclear(gl_color_buffer_bit); drawlefttriangle(); drawrighttriangle(); glflush(); void reshape(int w, int h) glviewport(0, 0, (GLsizei) w, (GLsizei) h); glmatrixmode(gl_projection); glloadidentity(); if (w <= h) gluortho2d (0.0, 1.0, 0.0, 1.0*(GLfloat)h/(GLfloat)w); else gluortho2d (0.0, 1.0*(GLfloat)w/(GLfloat)h, 0.0, 1.0); */Main Loop * Open window with initial window size, title bar * RGBA display mode, and handle input events. /* وبفرض لو ا ننا قمنا برسم الكاي ن الا زرق بداية بحيث يكون هو الوجهة ثم رسمنا int main(int argc, char** argv) glutinit(&argc, argv); glutinitdisplaymode (GLUT_SINGLE GLUT_RGB); glutinitwindowsize (200, 200); glutcreatewindow (argv[0]); init(); glutreshapefunc (reshape); glutdisplayfunc (display); glutmainloop(); return 0;

السطح الا صفر بحيث يكون هو المصدر. وا ذا لم نقم بتغيير تابع المزج عندها سيكون اللون الغالب على منطقة المزج هو اللون الا صفر وسيكون الخرج كالتالي : وهذا يعني ا ن ترتيب رسم الا جسام سيسبب اختلاف في لون منطقة التراكب. ولو ا ننا استخدمنا تابع المزج اللوني بالشكل التالي : glblendfunc (GL_ONE, GL_ZERO ); ولو ا ننا عدنا للحالة الا ولى بحيث يكون السطح الا زرق هو المصدر فعندها لن يكون هناك ا ي ا همية لقيمة ا لفا المختارة في تابع التلوين لا للمصدر ولا للوجهة وسيكون الخرج كالتالي : تمرين : ا عد كتابة المثال السابق بحيث نغير المصدر والوجهة عن طريق التحكم بلوحة المفاتيح بحيث يكون السطح الا زرق هو الوجهه والا صفر هو المصدر ثم باستخدام ا حد ا زرار لوحة المفاتيح يصبح السطح الا زرق هو المصدر والا صفر هو الوجهة ولاحظ الفرق في الخرج الناتج.

الضبابية: تعتبر الا حوال الجوية ا حد ا هم المواضيع التي يجب الاهتمام بها عند تجسيد المناظر الطبيعية وقد استطعنا تمثيلها سابقا باستخدام الا لوان والا ضاءة فصورنا الطبيعة في الا يام المشمسة حيث استخدمنا الا لوان الزاهية والا ضاءة البراقة وكذلك في الا يام المعتمة باستخدام ا لوان قاتمة وا ضاءة كامدة. ولكن هناك حالة جوية ا خرى لم نا تي على ذكرها وهي الضباب. حيث يو ثر الضباب على المشاهد الطبيعية فيعطي غشاوة وعدم وضوح للمشهد. كما يمكن استخدام الضباب في حالات ا خرى غير الا حوال الجوية فمثلا يمكن استخدامه في النماذج التي تظهر فيها الكاي نات تدريجيا لتصبح واضحة وبالعكس في النماذج التي تختفي وتتلاشى فيها الكاي نات تدريجيا. وكذلك يعر ف الدخان على ا نه نوع من الضباب عندها نستفيد من الضباب لتصوير حريق ما ا و عندما نريد تصوير مشهد للتلوث الناتج عن دخان السيارات والمصانع. لاحظ من الشكل كيف ا ن الضباب يجعل الا جسام تبدو وكا نها تبتعد عن العين وتندمج مع الخلفية. تقدم ال OpenGL تابع يمكنها من تمثيل الضباب هذا التابع هو : void glfogifv(glenum pname, TYPE param); ولرو ية ا ثر هذا التابع يجب تفعيله في البداية باستخدام التعليمة التالية: glenable(gl_fog); كما تتيح ال OpenGL القدرة على التحكم با لية توليد الضباب باستخدام التابع : void glhint(glenum target, GLenum hint); فا ما ا ن يتم توليده من ا جل كل pixel ا و من ا جل كل vertex حيث يتم اختيار ذلك بحسب ما يتطلبه التطبيق من دقة في الا ظهار ا و سرعة في التنفيذ. فعندما نكون بحاجة لدقة في الا ظهار يكون الوسيط hint مساويا ل GL_NICEST وعندما نكون بحاجة لسرعة في التنفيذ يكو ن الوسيط hint مساويا ل. GL_FASTEST ونعطي هذا الوسيط القيمة GL_DONT_CARE فيما عدا ذلك ا ي عندما لا نكون مهتمين با ي من الحالتين السابقتيين. ا ما فيما يتعلق بالوسيط target فا نه يا خذ القيمة GL_FOG_HINT في الحالات الثلاث السابقة. glhint (GL_FOG_HINT, GL_DONT_CARE);

glhint (GL_FOG_HINT, GL_FASTEST ); glhint (GL_FOG_HINT, GL_NICEST ); كما يمكن اختيار لون ما للضباب حيث سبق وقلنا ا ن الضباب ليس مجرد تعبير عن حالة جوية وا نما يمكن استخدامه في تطبيقات ا خرى. مع العلم ا ن هذا اللون يمكن تحديده سواء عند استخدام نظام الا لوان ال RGBA ا و النظام color-index مع وجود بعض الفروقات. و يجب الانتباه ا لى ا ن استخدام تابع الضباب في التطبيقات الرسومية يتم قبل رسم النموذج وا جراء ا ي عملية تحويل عليه حيث تحدد خصاي صه في ا جراي ية ال init() مثله مثل الا ضاءة التي غالبا ما تضبط خصاي صها في ا جراي ية ال init(). المعادلات الرياضية المتعلقة بحساب كثافة الضباب: يمكن التحكم بكثافة الضباب في المشهد استنادا ا لى ثلاثة معادلات رياضية : حيث: :Start بداية المنطقة الخاضعة للضباب. :End ا بعد نقطة تقع تحت تا ثير الضباب ويمكن رو يتها. :Density درجة ا و معامل كثافة الضباب. : z البعد بين منتصف النقطة المعتبرة من الشكل وعين المراقب. و تنحصر قيم التابع f ضمن المجال [0,1]. يوضح هذا الشكل الاختلاف في كثافة الضباب في كل من المعادلات الثلاثة السابقة.

يتم تحديد نوع المعادلة الرياضية المستخدمة عند تحديد وسطاء التابع void glfogifv(glenum pname, TYPE param); فمثلا : عندما نريد استخدام المعادلة الرياضية الا ولى يا خذ الوسيط pname القيمة GL_FOG_MODE ويا خذ الوسيط param القيمة. GL_EXP فيكون شكل التابع glfog*() كالتالي: glfogi(gl_fog_mode,gl_exp); ولتحديد قيمة المتحول density المستخدم في المعادلة نستخدم ا يضا التابع glfog*() حيث يا خذ الوسيط pname القيمة GL_FOG_DENSITY و بالوسيط param نعطي الكثافة قيمة ما. كما في الشكل التالي: glfogf(gl_fog_density,1.00); وبالمثل يتم استخدام باقي المعادلات حيث سنوضح القيم التي يمكن ا ن يا خذها هذين الوسيطين بالجدول التالي: Pname Param Meaning GL_FOG_MODE GL_EXP, GL_EXP2, GL_LINEAR the fog function GL_FOG_DENSITY density density value in the fog function. GL_FOG_STARET start start distance in the fog function. GL_FOG_END end end distance in the fog function. GL_FOG_INDEX index the fog color ( color-index) تعتبر عملية مزج الا لوان القاعدة الا ساسية التي يتم تطبيقها لا ظهار ا ثر لون الضباب في المشهد حيث يتم ا جراء مزج بين لون الضباب ولون الا جسام المرسومة في النموذج.وذكرنا ا نه يمكن استخدام الضباب في

نظامي الا لوان ال RGBA ال color-index مع بعض الاختلاف المتعلقة بطريقة ا جراء المزج ففي نظام الا لوان ال RGBA يحدد اللون النهاي ي الناتج عن عملية المزج وفق المعادلة التالية: حيث C Final = f * C Current + ( 1 - f ) * C Fog :C Current عبارة عن لون بكسلات المصدر ) ناشي ة عن الا جسام في النموذج ). : C Fog عبارة عن لون بكسلات الوجهة ) ناشي ة عن الضباب في النموذج ). ا ما f فهو عبارة عن ا حدى المعادلات الرياضية الثلاثة التي تحدد كثافة الضباب وبالتالي فا ن لون الضباب يختلف باختلاف كثافته. ا ما في نظام الا لوان color-index فيحسب وفق المعادلة التالية: I = Ii + (1 - f ) If حيث : Ii عبارة عن رقم اللون في جدول الا لوان والمرتبط بالمصدر ) ناشي ة عن الا جسام في النموذج ). : If عبارة عن رقم اللون في جدول الا لوان و المرتبط بالوجهة ) ناشي ة عن الضباب في النموذج ). ولتحديد طريقة الحساب التي يجب اعتمادها في ال OpenGL نستخدم التابع glfogfv(gl_fog_color,color); حيث يكون الوسيط color عبارة عن شعاع مو لف من ا ربع مركبات في نظام الا لوان RGBA كل منها قيمة مركبة من ال RGBA ويعرف كالتالي: GLfloat color[4]= 0.70,0.70,0.70,1.0; ا ما في نظام الا لوان color-index نستخدم التابع glfogfv(gl_fog_index,color); ولكن في هذه الحالة يكون الوسيط color عبارة عن قيمة وحيدة تشير ا لى رقم اللون في جدول الا لوان. ا مثلة : سنعرض بعض الا مثلة التي تبين الفرق بين كل شكل من ا شكال المعادلات مع الا شارة ا لى ا ن نظام الا لوان المستخدم في جميع الا مثلة هو النظام. RGBA بفرض لدينا مشهد يعرض طاي رة في السماء.

مثال ١: مثال ٢ :

مثال ٣ : والا ن سنعرض مثال كامل لطريقة استخدام الضباب في نظام الا لوان. RGBA

مثال ١ : سنرسم في التطبيق الرسومي التالي خمسة ا باريق تخضع لثا ثير الضباب ولكن تختلف درجة كثافة الضباب من ا جل كل ا بريق كما يمكن تغيير تابع الكثافة عن طريق التحكم بلوحة المفاتيح. سيكون خرج التطبيق كما في الشكل التالي :

#include <GL/gl.h> #include <GL/glu.h> #include <math.h> #include "aux.h" GLint fogmode; void cyclefog (AUX_EVENTREC *event) if (fogmode == GL_EXP) fogmode = GL_EXP2; printf ("Fog mode is GL_EXP2\n"); else if (fogmode == GL_EXP2) fogmode = GL_LINEAR; printf ("Fog mode is GL_LINEAR\n"); glfogf (GL_FOG_START, 1.0); glfogf (GL_FOG_END, 5.0); else if (fogmode == GL_LINEAR) fogmode = GL_EXP; printf ("Fog mode is GL_EXP\n"); glfogi (GL_FOG_MODE, fogmode); void myinit(void) GLfloat position[] = 0.0, 3.0, 3.0, 0.0 ; GLfloat local_view[] = 0.0 ; glenable(gl_depth_test); gldepthfunc(gl_lequal); gllightfv(gl_light0, GL_POSITION, position); gllightmodelfv(gl_light_model_local_viewer, local_view); glfrontface (GL_CW); glenable(gl_lighting); glenable(gl_light0); glenable(gl_auto_normal); glenable(gl_normalize); glenable(gl_fog); GLfloat density; GLfloat fogcolor[4] = 0.5, 0.5, 0.5, 1.0; fogmode = GL_EXP; glfogi (GL_FOG_MODE, fogmode); glfogfv (GL_FOG_COLOR, fogcolor); glfogf (GL_FOG_DENSITY, 0.35); glhint (GL_FOG_HINT, GL_DONT_CARE); glclearcolor(0.5, 0.5, 0.5, 1.0);

void renderredteapot (GLfloat x, GLfloat y, GLfloat z) float mat[3]; glpushmatrix(); gltranslatef (x, y, z); mat[0] = 0.1745; mat[1] = 0.01175; mat[2] = 0.01175; glmaterialfv (GL_FRONT, GL_AMBIENT, mat); mat[0] = 0.61424; mat[1] = 0.04136; mat[2] = 0.04136; glmaterialfv (GL_FRONT, GL_DIFFUSE, mat); mat[0] = 0.727811; mat[1] = 0.626959; mat[2] = 0.626959; glmaterialfv (GL_FRONT, GL_SPECULAR, mat); glmaterialf (GL_FRONT, GL_SHININESS, 0.6*128.0); auxsolidteapot(1.0); glpopmatrix(); void display(void) glclear(gl_color_buffer_bit GL_DEPTH_BUFFER_BIT); renderredteapot (-4.0, -0.5, -1.0); renderredteapot (-2.0, -0.5, -2.0); renderredteapot (0.0, -0.5, -3.0); renderredteapot (2.0, -0.5, -4.0); renderredteapot (4.0, -0.5, -5.0); glflush(); void myreshape(glsizei w, GLsizei h) glviewport(0, 0, w, h); glmatrixmode(gl_projection); glloadidentity(); if (w <= (h*3)) glortho (-6.0, 6.0, -2.0*((GLfloat) h*3)/(glfloat) w, 2.0*((GLfloat) h*3)/(glfloat) w, 0.0, 10.0); else glortho (-6.0*(GLfloat) w/((glfloat) h*3), 6.0*(GLfloat) w/((glfloat) h*3), -2.0, 2.0, 0.0, 10.0); glmatrixmode(gl_modelview); glloadidentity (); int main(int argc, char** argv) auxinitdisplaymode (AUX_SINGLE AUX_RGBA AUX_DEPTH); auxinitposition (0, 0, 450, 150); auxinitwindow (argv[0]); auxmousefunc (AUX_LEFTBUTTON, AUX_MOUSEDOWN, cyclefog); myinit(); auxreshapefunc (myreshape); auxmainloop(display);

مثال ٢ : يوضح هذا المثال استخدام الضباب في نظام الا لوان : color-index

include <GL/gl.h> #include <GL/glu.h> #include "aux.h" #define NUMCOLORS 32 #define RAMPSTART 16 void myinit(void) int i; glenable(gl_depth_test); gldepthfunc(gl_lequal); for (i = 0; i < NUMCOLORS; i++) GLfloat shade; shade = (GLfloat) (NUMCOLORS-i)/(GLfloat) NUMCOLORS; auxsetonecolor (16 + i, shade, shade, shade); glenable(gl_fog); glfogi (GL_FOG_MODE, GL_LINEAR); glfogi (GL_FOG_INDEX, NUMCOLORS); glfogf (GL_FOG_START, 0.0); glfogf (GL_FOG_END, 4.0); glhint (GL_FOG_HINT, GL_NICEST); glclearindex((glfloat) (NUMCOLORS+RAMPSTART-1)); void display(void) glclear(gl_color_buffer_bit GL_DEPTH_BUFFER_BIT); glpushmatrix (); gltranslatef (-1.0, -1.0, -1.0); glrotatef (-90.0, 1.0, 0.0, 0.0); glindexi (RAMPSTART); auxsolidcone(1.0, 2.0); glpopmatrix (); glpushmatrix (); gltranslatef (0.0, -1.0, -2.25); glrotatef (-90.0, 1.0, 0.0, 0.0); glindexi (RAMPSTART); auxsolidcone(1.0, 2.0); glpopmatrix (); glpushmatrix (); gltranslatef (1.0, -1.0, -3.5); glrotatef (-90.0, 1.0, 0.0, 0.0); glindexi (RAMPSTART); auxsolidcone(1.0, 2.0); glpopmatrix (); glflush();

void myreshape(glsizei w, GLsizei h) glviewport(0, 0, w, h); glmatrixmode(gl_projection); glloadidentity(); if (w <= h) glortho (-2.0, 2.0, -2.0*(GLfloat)h/(GLfloat)w, 2.0*(GLfloat)h/(GLfloat)w, 0.0, 10.0); else glortho (-2.0*(GLfloat)w/(GLfloat)h, 2.0*(GLfloat)w/(GLfloat)h, -2.0, 2.0, 0.0, 10.0); glmatrixmode(gl_modelview); glloadidentity (); int main(int argc, char** argv) auxinitdisplaymode (AUX_SINGLE AUX_INDEX AUX_DEPTH); auxinitposition (0, 0, 200, 200); auxinitwindow (argv[0]); myinit(); auxreshapefunc (myreshape); auxmainloop(display);

الفصل السابع مواضيع متنوعة مقدمة: سنعرض في هذا الفصل بعض المواضيع المتنوعة والتي يمكن تحقيقها باستخدام تعليمات ال.OpenGL تنعيم الخطوط :Antialiasing غالبا ما تظهر الرسوم في الحاسب بحواف خشنة ومتكسرة حيث كلنا يعلم ا ن الخشونة تنشا ا صلا عن الدقة المنخفضة للا ظهار لذلك فا ن ا ول عامل في ا زلة الخشونة هو رفع دقة الا ظهار. انظر الشكل التالي : يظهر هنا بشكل واضح وجلي الاختلاف بين الشكلين من حيث نعومة وتكسر الخطوط. وبما ا ن ال OpenGL تسعى ا لى ا ظهار ا فضل وا دق النماذج الرسومية كان لابد لها ا ن تهتم بهذا الا مر فقدمت تعليمات خاصة تساعد على التخلص من مشكلة الخطوط المتكسرة. ا ولا : void glhint(glenum target, GLenum hint);