الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

الازاحة - التحجيم - التدوير .. في opengl

مغلق
بدأه Abdullah.Alshammeri في 19 ديسمبر 2005 · 6 رد · 10,013 مشاهدة · في OpenGL
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم ..

الازاحة :

كيف نحرك مجسم من موقع إلى آخر

glTranslatef

تؤدي المهمة على أكمل وجه ....

صيغتها

glTranslatef(Glfloat x , Glfloat y , Glfloat z );

اذا اردت البارمترات float

او

glTranslated (GLdouble x, GLdouble y, GLdouble z);

اذا اردت البارمترات من نوع double

البارمتر الاول : الاحداثي السيني .

البارمتر الثاني : الاحداثي الصادي .

البارمتر الثالث : الاحداثي العيني .. العمق .. Z .

سنفرض هنا .. اننا نتعامل مع بيئة احداثية شبية بالتالي :

c0984cdf3b.jpg

اذا .. يمين المنتصف الاحداثي السيني x .. موجب .

يسار المنتصف .. الاحداثي السيني X سالب .

أعلى المنتصف الاحداثي الصادي موجب Y

اسفل المنتصف الاحداثي الصادي سالب Y

خارج الشاشة ( قل العمق ) z موجب .

(داخل الشاشة ) قيمة الاحداثي Z سالب .

عندما أقول داخل الشاشة وخارجها .... فانا اقصد التقريب في المعنى ..

انما الشاشة في الحقيقة ليست ثلاثية الابعاد كما تعلم ...

الجمل السابقة تبدو بديهية .. وتذكرنا بثالث ابتدائي ..

لكن معظم اسئلة طلبة بعض الكليات .. التي رأيت ... تدور حول تلك المحاور  ,,, يعني كأننا ابتدائي .. مع كامل احترامي ... لاتزعلون علينا ياطلبة الكلية .. : ) ,,

دعونا نأخذ مثال :/

glLoadIdentity(); 
  glTranslatef(2,0,-4.0);
   
  glBegin(GL_POINTS);
    glVertex3f(0,0,0); 
                   glEnd();

من المفترض ظهور النقطة منتصف الشاشة ..

وذلك لاننا كتبنا

glVertex3f(0,0,0);

لكن الحقيقة هي ان النقطة ستتحرك خطوتين الى اليمين .

glTranslatef(2,0,-4.0);

جعلنا الاحداثي السيني 2 ..

اعتقد الامر سهل وواضح .

لكن لماذا كتبنا في البارمتر الثالث -4 ..

لسبب واحد .. حتى يظهر الرسم .

فالرسم لن يظهر هنا .. الا اذا كانت الشاشة ممكن ان تحويه..

جرب ان تغير الرقم -4 باي عدد ... ابتداء من -5 فما دون ..

و -4 فما فوق .. وصدقني رح تفهم : ) ,,, باذن الله .

دعنا نرسم شكل مربع

  glLoadIdentity(); 


  glTranslatef(1,0,-8.0);

  glColor3f(1,1,0);
     	 glRectf(0,0,0.5,0.5);


  glTranslatef(-1,0,0.0);

  glColor3f(1,0,0);
  glRectf(0,0,0.5,0.5);

رسمنا مربعين :

الاول لونه اصفر ويقع في الاحداثي السيني " 1 "

الثاني لونه احمر ويقع في الاحداثي السيني "-1 "

يعني المربع الاول يمين نقطة المنتصف .. المربع الثاني يسار منطقة المنتصف .

لكن المفاجأة .. أن الرسم سيظهر هكذا :

d236ff7230.gif

لماذا المربع الاحمر لم يظهر يسار نقطة المنتصف كما أردنا ::::

glTranslatef(-1,0,0.0);

  glColor3f(1,0,0);
  glRectf(0,0,0.5,0.5);

الجواب :

نحن تحركنا خظة الى اليسار ( -1 ) .. بالنسبة لمقعنا السابق وهو " 1 "

كان

X =1 Y=0 Z=-8 موقع المربع السابق

X=-1 Y=0 Z=0 موقع المربع الحالي

--------------------------------------

X=0 Y=0 Z=-8 موقع المربع الحالي الذي تأثر بموقع المربع السابق

وكما تلاحظ .. في الصورة .. الموقع الحالي هو المنتصف ,

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

لكن ألا تتفق معي ان هذا أمر مزعج ..

انا اريد ان لا يتأثر أي شكل بالشكل السابق المرسوم .

مالحل :

لاحظ

	glLoadIdentity(); 


  glTranslatef(1,0,-8.0);

  glColor3f(1,1,0);
     	 glRectf(0,0,0.5,0.5);

  glLoadIdentity(); 
  glTranslatef(-1,0,-8.0);

  glColor3f(1,0,0);
  glRectf(0,0,0.5,0.5);

اضفنا glLoadIdentity قبل ان نزيح الجسم الثاني والنتيجة :

d8a096370b.gif

ستلاحظ ان المربع الاصفر يمين نقطة المنتصف .. والاحمر يسارها ..

أي لم يتأثر أي شكل بالشكل الذي قبله .

من هذا المثال نعرف أن فائدة الدالة glLoadIdentity هي تصفير مصفوفة الازاحة .

أي تعيدنا الى نقطة الاصل .

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

ستعرف ذلك لاحقا بعون الله .. لكن راجع الدالة glOrtho

بهذا نختم درسنا هذا ..

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

اذا ضغط الزر الايمن .. يتحرك المربع لليمين .. وهكذا .

مافعلنا أي شيء جديد ..

وضعنا متغيرين

x y z . ..

الاسهم تحرك الشكل يمين ويسار وفوق وتحت .. و مفتاح End يقرب الشكل .. و مفتاح Home يبعد الشكل ..

حمل اما تطبيق Opengl /glut

او

OpenGL/API

اللي يعجبك .

درسنا القادم عن التدوير باذن الله تعالى .

1_trans_glut.zip

1_trans_wnd.zip

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#2

التدوير :

نستخدم الدالة glRotatef

  glLoadIdentity(); 

  glTranslatef(-1,0,-8.0);
  glRotatef(45,0,1,0);
  glRectf(0,0,0.5,0.5);

اول بارمتر ... زاوية التدوير ..

ثاني بارمتر ... نضع رقم واحد فما فوق اذا اردناه يدور على الاحداثي السيني X

ثالث بارمتر ... نضع واحد فما فوق ... اذا اردناه يدور على الاحداثي الصادي . Y

رابع بارمتر ... نضع واحد فما فوق اذا اردناه يدور على الاحداثي العيني (العمق) Z

مثال :

static int a = 0;
 void Render()
{
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

  glLoadIdentity(); 



  a++;

  glTranslatef(0,0,-8.0);
  glRotatef(a,1,3,1);


  glRectf(0,0,0.5,0.5);
   


}

الان سيدور المربع .. كل loop بزاوية مقدارها a .. و a ايضا تزداد .

لاحظ ايضا اننا نريده يدور على جميع المحاور .. لكن وضعنا المحور الصادي 3 وبالتالي سيدور المربع بشكل اكبر حول المحور الصادي ..

  glRotatef(a,1,3,1);

ما رأيك بمثال شامل لهذا الموضوع ...

static int a = 0;
static int b = 0;
 void Render()
{
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );


  a++;
  b--;



  glLoadIdentity(); 
  glTranslatef(3,3,-12.0);
  glRotatef(a,0,1,0);
  glRectf(0,0,1.1,0.5);
/*****************************/

  glLoadIdentity(); 
  glTranslatef(-3,3,-12.0);
  glRotatef(a,0,0,1);

  glBegin(GL_QUADS);
  glVertex3f(0,0,0);
  glVertex3f(1,0,0);
  glVertex3f(1,1,0);
  glVertex3f(0,1,0);
  glEnd();

/*****************************/

  glLoadIdentity(); 
  glTranslatef(-3,-3,-12.0);
  glRotatef(b,1,3,1);

  glBegin(GL_QUADS);
  glVertex3f(0,0,0);
  glVertex3f(1,0,0);
  glVertex3f(1,1,0);
  glVertex3f(0,1,0);
  glEnd();

/*****************************/
  glLoadIdentity(); 
  glTranslatef(3,-3,-12.0);
  glRotatef(b,1,1,1);

  glBegin(GL_QUADS);
  glVertex3f(-1,-1,0);
  glVertex3f(1,-1,0);
  glVertex3f(1,1,0);
  glVertex3f(-1,1,0);
  glEnd();



}

ملاحظات :

مالفرق بين

glBegin(GL_QUADS);
  glVertex3f(-1,-1,0);
  glVertex3f(1,-1,0);
  glVertex3f(1,1,0);
  glVertex3f(-1,1,0);
  glEnd();

و

glBegin(GL_QUADS);
  glVertex3f(0,0,0);
  glVertex3f(1,0,0);
  glVertex3f(1,1,0);
  glVertex3f(0,1,0);
  glEnd();

عند التدوير ...؟؟؟

ستجد الاول يدور دورة حرة ( حول منطقة (منتصف الاضلاع ) )

الثاني يدور ولكن النقطة الثابتة .. الجهة اليسرى السفلية ..

اتمنى تكون عرفت السبب : ) ,,,

ثانيا :

دائما ضع دالة الازاحة قبل دالة التدوير .. والا لاتلومن الا نفسك : )

glTranslatef(3,-3,-12.0);
glRotatef(b,1,1,1);

اذا أحد مو فاهم شيء .. يسأل الله يرحم والديه .

الامثلة في المرفقات ..

2_rotate_glut.zip

2_rotate_wnd.zip

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#3

ثالثا :

دالة التحجيم.

فائدتها تغيير حجم شكل ما .

glScalef(x,y,z);

اعتقد بارمتراتها واضحة ..

لكن أي جسم .. حجمه الاصلي كذا ..

	glScalef(1,1,1);

ونحن ننقص من قيمة احد البارمترات الى الصفر .. لتصغير الجسم .

ونزيد كما نريد .. لزيادة حجم الجسم

مثال :

  glLoadIdentity(); 
  glTranslatef(0,0,-12.0);
    glScalef(2,4,1);

  glBegin(GL_TRIANGLES);
  glVertex3f(-1,0,0);
  glVertex3f(1,0,0);
  glVertex3f(0,1,0);
  glEnd();

عرض الجسم ( الاحداثي السيني ) زاد . . كذلك الطول . .. (الاحداثي الصادي ) .

اذا اردنا ان نعيده لحجمه الاصلي فقط نكتب

glScalef(1,1,1);

من الامور المسلية والمفيده ..

مايلي :

  glLoadIdentity(); 
  glTranslatef(0,0,-12.0);
    glScalef(1,-1,1);

  glBegin(GL_TRIANGLES);
  glVertex3f(-1,0,0);
  glVertex3f(1,0,0);
  glVertex3f(0,1,0);
  glEnd();

هنا سينقلب المثلث رأسا على عقب .. ليش ,, لاننا وضعنا قيمة الاحداثي الصادي في دالة التحجيم = -1 .

جرب ايضا على الاحداثي السيني ..

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

ايضا التطبيق في المرفقات . .

الدالتين

  glPushMatrix();

  glPopMatrix();

لنفرض انك قمت برسم مجسمين ... تريد الاول يدور .. والاخر لايدور .. والاول يكبر حجمه والاخر لايكبر .

static int a = 0;
 void Render()
{
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

  glLoadIdentity(); 



  a++;

  glTranslatef(-2,0,-8.0);
  glRotatef(a,1,3,1);
  glScalef(3,1,1);
  glRectf(0,0,0.5,0.5);


  glLoadIdentity(); 
  glTranslatef(1,0,-8.0);
  glRectf(0,0,0.5,0.5);


}

استطعنا ان نؤدي ما نريد .. لكن حقيقة .. الطريقة السابقة ليست هي المجدية .. تقول ليش .. اقول احساسي يقول كذا ... :P

الافضل نستخدم الدالتين

glPushMatrix();

glPopMatrix();

هاتين الدالتين .. تحفظان قيم المصفوفة .. وبالتالي لاتتأثر بهما الاشكال الاخرى ..

static int a = 0;
 void Render()
{
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );




  a++;

glPushMatrix();
  glTranslatef(-2,0,-8.0);
  glRotatef(a,1,3,1);
  glScalef(3,1,1);
  glRectf(0,0,0.5,0.5);
glPopMatrix();


glPushMatrix();


  glTranslatef(1,0,-8.0);
  glRectf(0,0,0.5,0.5);

glPopMatrix();

}

نكتب glPushMatrix ثم ازاحة .. او تدوير او تحجيم .... ثم نغلق تلك الحلقة بـ glPopMatrix

هذه الطريقة افضل واكثر وضوحا ...

3_scale_glut.zip

3_scale_wnd.zip

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#4

وضعت مثال بسيط ...

تحرك الجسم لاي جهة تريد .

تكبير الجسم وتصغيره ,

ادوات التحكم ... الاسهم + END + HOME +f1 + f2

بهذا الموضوع ننتهي من اهم مواضيع OpenGL وأمتعها ...وأسهلها ..

بحمدالله ....

ننتظر منكم دعوة لي (وليست علي : ) ) في ظهر الغيب .

exe___matrix.zip

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#5

يا سلام عليك!

أول مرة اعرف فائدة glTranslatef .. كنت دائما استغرب انها فقط تاخذ الازاحة و لكنها لا تاخذ شي آخر .. فاستغرب كيف تستخدمها لتدوير شي ما اذا لم تكن ترسل لها هذا الشي .. بس الان الصورة وضحت.

اول شي تستدعيها و بعدين ترسم .. و راح يظهر الرسم مزاح!

تقريبا مثل glRasterPos2D .. تستدعيها بعدين تعمل تشاء و سترى التأثير على اي ترسمه بعد استدعائها.

اتصور انها تغير شي بالـ projection matrix او اشياء من هذا القبيل ..

اني ما اعرف الكثير عن الماتركسات و علاقتها بالثريدي و التودي ..ما اعرف الا الشي القليل ..

#6

بمانسبة الحديث عن glRasterPos ..

من يعرف الفرق بينها وبين glTranslate ..

اعتقد الفرق ... ان glRasterPos .. للبيكسل .. اشاهدها مع الخطوط .. مع glDrawPixel .

لست متأكدا بالظبط ,,, احد يعرف .؟؟؟

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#7

السلام عليكم

اخي الشمري شكرا على الدروووس

والله يقويك

بالنسبة لاخر مثال اللي هو مثلث ويتم التحكم به بواسطه الكيبورد

الرجاء وضع الكود

وشكرا

هذا الموضوع مغلق.

مواضيع مشابهة