بسم الله الرحمن الرحيم و السلام عليكم جاري هذا الموضوع حول مجالات التحكم في عالم الأوبن جي أل , لربما كنت دائما تحاول ربط مؤشر الفأرة بعالم الأوبن جي أل الثلاثي الأبعاد , هذا الموضوع كتبته خصيصا لذلك و سأتطرق إلى كل شيء بإذن الله تعالى. التحديد هناك منهاج يدعى بالتحديد أي selection و هو وسيلة تمكننا من معرفة الكائن أو المجسم المتموضع في عالم الأوبن جي أل بصورة أخرى سأشرح ما يدور خلف كواليس التحديد في عالم الأوبن جي أل: في البداية نقوم برسم المشهد و بطبيعة الحال سيكون في ذاكرة الإيطار framebuffer و بعدها نجعل التطبيق أي البرنامج يقفز من النمط الحالي التصير render و هو الإفتراضي إلى نمط آخر و هو اللتحديد selection ومن ثم نعرض المشهد , هل فهمت ما أقصد , أي أن عملية التحديد لن تحصل إلا في نمط التحديد mode selection , من المنطقي ألا يتغير محتوى ذاكرة الإيطار حيت يتم الخروج من نمط التحديد و الإنتقال إلى نمط التصيير render , عندها سيرجع السيد أوبن جي أل قائمة تحتوي على بيانات ناتجة عن تقاطع الكائنات أو المجسمات المتموضعة في عالم الأوبن جي أل مع حجم الرؤية المحدد viewing folume ( حجم الرؤية هو دليل نحدده نحن وهو معرف بواسطة نمط الرؤية الحالي و مصفوفة الإسقاط و أي إضافات خاصة بمسطحات القص ),كل شكل يتقاطع مع حجم الرؤية سيولد تداخل hit (عموما أعتمد في ترجمة المرادفات حسب الخاصية و ليس المعنى)و بعد ذلك يقوم السيد أوبن جي أل بتمرير المعرفات الخاصة بكل مجسم في مصفوفة من نوع integer تدعى تلك المعرفات بالأسماء names و بعض البيانات المرافقة لها . هذه المراحل تمثل ميكانيزمة التحديد يرجى التقيد بها: 1- تخصيص مصفوفة لتحتفظ بالتداخلات و بياناتها و يتم إنشاء هذه المصفوفة عن طريق إستدعاء الدالة glSelectBuffer . 2- المرور إلى نمط التحديد عن طريق تمرير الدليل GL_SELECT إلى الدالة glRenderMode . 3- إعداد المكدس و تهيئته بأول إسم يحتل القائمة بالدالة glInitNames ثم نقوم بحجز إسم لكل شكل أو مجسم في المكدس عن طريق الدالة glPushName . 4- تعريف حجم رؤية مناسب و حجز و تحرير مصفوفات التحويل الحالية بإستعمال الدالتان glPushMatrix و glPopMatrix . 5- إعداد الأشكال و المجسمات التي ترغب في تحديدها لحظة تنفيذك للبرنامج. 6- الخروج من نمط التحديد و العودة إلى نمط التصير للقيام بمعالجة البيانات التي أرجعها السيد أوبن جي أل hit record .
void glSelectBuffer(GLsizei size, GLuint *buffer);
GLint glRenderMode(GLenum mode);
glInitNames();glPushName(0);glPushMatrix(); /* حجز التحويل الحالي *//* هنا قد ننشئ حجم الرؤية المرغوب فيه */glLoadName(1);drawSomeObject();glLoadName(2);drawAnotherObject();glLoadName(3);drawYetAnotherObject();drawJustOneMoreObject();glPopMatrix(); /* تحرير التحويل المحجوز*/
void glInitNames(void);
void glPushName(GLuint name);
void glPopName(void);
void glLoadName(GLuint name);
void drawTriangle(GLfloat x1, GLfloat y1, GLfloat x2,GLfloat y2, GLfloat x3, GLfloat y3, GLfloat z) { glBegin(GL_TRIANGLES); glVertex3f(x1, y1, z); glVertex3f(x2, y2, z); glVertex3f(x3, y3, z); glEnd();}void drawViewVolume(GLfloat x1, GLfloat x2, GLfloat y1,GLfloat y2, GLfloat z1, GLfloat z2){ glColor3f(1.0, 1.0, 1.0); glBegin(GL_LINE_LOOP); glVertex3f(x1, y1, -z1); glVertex3f(x2, y1, -z1); glVertex3f(x2, y2, -z1); glVertex3f(x1, y2, -z1); glEnd(); glBegin(GL_LINE_LOOP); glVertex3f(x1, y1, -z2); glVertex3f(x2, y1, -z2); glVertex3f(x2, y2, -z2); glVertex3f(x1, y2, -z2); glEnd(); glBegin(GL_LINES); /* 4 lines */ glVertex3f(x1, y1, -z1); glVertex3f(x1, y1, -z2); glVertex3f(x1, y2, -z1); glVertex3f(x1, y2, -z2); glVertex3f(x2, y1, -z1); glVertex3f(x2, y1, -z2); glVertex3f(x2, y2, -z1); glVertex3f(x2, y2, -z2); glEnd();}void drawScene(void){ glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(40.0, 4.0/3.0, 1.0, 100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(7.5, 7.5, 12.5, 2.5, 2.5, -5.0, 0.0, 1.0, 0.0); glColor3f(0.0, 1.0, 0.0); /* green triangle */ drawTriangle(2.0, 2.0, 3.0, 2.0, 2.5, 3.0, -5.0); glColor3f(1.0, 0.0, 0.0); /* red triangle */ drawTriangle(2.0, 7.0, 3.0, 7.0, 2.5, 8.0, -5.0); glColor3f(1.0, 1.0, 0.0); /* yellow triangles */ drawTriangle(2.0, 2.0, 3.0, 2.0, 2.5, 3.0, 0.0); drawTriangle(2.0, 2.0, 3.0, 2.0, 2.5, 3.0, -10.0); drawViewVolume(0.0, 5.0, 0.0, 5.0, 0.0, 10.0);}void processHits(GLint hits, GLuint buffer[]){ unsigned int i, j; GLuint names, *ptr; printf(“hits = %d\n”, hits); ptr = (GLuint *) buffer; for (i = 0; i < hits; i++) { /* for each hit */ names = *ptr; printf(“ number of names for hit = %d\n”, names); ptr++; printf(“ z1 is %g;”, (float) *ptr/0x7fffffff); ptr++; printf(“ z2 is %g\n”, (float) *ptr/0x7fffffff); ptr++; printf(“ the name is “); for (j = 0; j < names; j++) { /* for each name */ printf(“%d “, *ptr); ptr++; } printf(“\n”); }}#define BUFSIZE 512void selectObjects(void){ GLuint selectBuf[BUFSIZE]; GLint hits; glSelectBuffer(BUFSIZE, selectBuf); (void) glRenderMode(GL_SELECT); glInitNames(); glPushName(0); glPushMatrix(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0, 5.0, 0.0, 5.0, 0.0, 10.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glLoadName(1); drawTriangle(2.0, 2.0, 3.0, 2.0, 2.5, 3.0, -5.0); glLoadName(2); drawTriangle(2.0, 7.0, 3.0, 7.0, 2.5, 8.0, -5.0); glLoadName(3); drawTriangle(2.0, 2.0, 3.0, 2.0, 2.5, 3.0, 0.0); drawTriangle(2.0, 2.0, 3.0, 2.0, 2.5, 3.0, -10.0); glPopMatrix(); glFlush(); hits = glRenderMode(GL_RENDER); processHits(hits, selectBuf);}void init(void){ glEnable(GL_DEPTH_TEST); glShadeModel(GL_FLAT);}void display(void){ glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); drawScene(); selectObjects(); glFlush();}int main(int argc, char** argv){ glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(200, 200); glutInitWindowPosition(100, 100); glutCreateWindow(argv[0]); init(); glutDisplayFunc(display); glutMainLoop(); return 0;}
glMatrixMode(GL_PROJECTION); glPushMatrix();glLoadIdentity();gluPickMatrix(...);gluPerspective, glOrtho, gluOrtho2D, or glFrustum/* ... draw scene for picking ; perform picking ... */glPopMatrix();
void gluPickMatrix(GLdouble x, GLdouble y, GLdouble width,GLdouble height, GLint viewport[4]);
glGetIntegerv(GL_VIEWPORT, GLint *viewport);
void init(void){glClearColor(0.0, 0.0, 0.0, 0.0);glEnable(GL_DEPTH_TEST);glShadeModel(GL_FLAT);glDepthRange(0.0, 1.0); /* The default z mapping */}void drawRects(GLenum mode){if (mode == GL_SELECT)glLoadName(1);glBegin(GL_QUADS);glColor3f(1.0, 1.0, 0.0);glVertex3i(2, 0, 0);glVertex3i(2, 6, 0);glVertex3i(6, 6, 0);glVertex3i(6, 0, 0);glEnd();if (mode == GL_SELECT)glLoadName(2);glBegin(GL_QUADS);glColor3f(0.0, 1.0, 1.0);glVertex3i(3, 2, -1);glVertex3i(3, 8, -1);glVertex3i(8, 8, -1);glVertex3i(8, 2, -1);glEnd();if (mode == GL_SELECT)glLoadName(3);glBegin(GL_QUADS);glColor3f(1.0, 0.0, 1.0);glVertex3i(0, 2, -2);glVertex3i(0, 7, -2);glVertex3i(5, 7, -2);glVertex3i(5, 2, -2);glEnd();}void processHits(GLint hits, GLuint buffer[]){unsigned int i, j;GLuint names, *ptr;printf(“hits = %d\n”, hits);ptr = (GLuint *) buffer;for (i = 0; i < hits; i++) { /* for each hit */names = *ptr;printf(“ number of names for hit = %d\n”, names); ptr++;printf(“ z1 is %g;”, (float) *ptr/0x7fffffff); ptr++;printf(“ z2 is %g\n”, (float) *ptr/0x7fffffff); ptr++;printf(“ the name is “);for (j = 0; j < names; j++) { /* for each name */printf(“%d “, *ptr); ptr++;}printf(“\n”);}}#define BUFSIZE 512void pickRects(int button, int state, int x, int y){GLuint selectBuf[BUFSIZE];GLint hits;GLint viewport[4];if (button != GLUT_LEFT_BUTTON || state != GLUT_DOWN)return;glGetIntegerv(GL_VIEWPORT, viewport);glSelectBuffer(BUFSIZE, selectBuf);(void) glRenderMode(GL_SELECT);glInitNames();glPushName(0);glMatrixMode(GL_PROJECTION);glPushMatrix();glLoadIdentity();/* create 5x5 pixel picking region near cursor location */gluPickMatrix((GLdouble) x, (GLdouble) (viewport[3] - y),5.0, 5.0, viewport);glOrtho(0.0, 8.0, 0.0, 8.0, -0.5, 2.5);drawRects(GL_SELECT);glPopMatrix();glFlush();hits = glRenderMode(GL_RENDER);processHits(hits, selectBuf);}void display(void){glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);drawRects(GL_RENDER);glFlush();}void reshape(int w, int h){glViewport(0, 0, (GLsizei) w, (GLsizei) h);glMatrixMode(GL_PROJECTION);glLoadIdentity();glOrtho(0.0, 8.0, 0.0, 8.0, -0.5, 2.5);glMatrixMode(GL_MODELVIEW);glLoadIdentity();}int main(int argc, char **argv){glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);glutInitWindowSize(200, 200);glutInitWindowPosition(100, 100);glutCreateWindow(argv[0]);init();glutMouseFunc(pickRects);glutReshapeFunc(reshape);glutDisplayFunc(display);glutMainLoop();return 0;}
void gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez,GLdouble centerx, GLdouble centery, GLdouble centerz,GLdouble upx, GLdouble upy, GLdouble upz);
int gluUnProject(GLdouble winx, GLdouble winy, GLdouble winz,const GLdouble modelMatrix[16],const GLdouble projMatrix[16],const GLint viewport[4],GLdouble *objx, GLdouble *objy, GLdouble *objz);
#include <windows.h>#include <GL/glut.h>#include <stdio.h>#define RED 1GLdouble wx, wy, wz, Mx, My, Mz, Ax, Ay, Az, t, tab[10][3];int ss = 0;void display(void){ glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.,1.,1.); glPushMatrix(); glTranslatef(0.,0.,-0.2); glutSolidSphere(0.1,10,10); glPopMatrix(); glPushMatrix(); glTranslatef((float)Mx,(float)My,(float)Mz); if (ss == 1) glColor3f(0.,0.,1.); glutSolidSphere(0.01,10,10); glColor3f(1.,1.,1.); glPopMatrix(); glFlush();}void reshape(int w, int h){ glViewport (0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-0.5, 0.5, -0.5, 0.5,1,10); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt (Ax, Ay, Az, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);}void mouse(int button, int state, int x, int y){ GLint viewport[4]; GLdouble mvmatrix[16], projmatrix[16]; GLfloat realy; switch (button) { case GLUT_LEFT_BUTTON: if (state == GLUT_DOWN) { glGetIntegerv (GL_VIEWPORT, viewport); glGetDoublev (GL_MODELVIEW_MATRIX, mvmatrix); glGetDoublev (GL_PROJECTION_MATRIX, projmatrix); realy = viewport[3] - (GLint) y ; printf ("Coordinates at cursor are (%4d, %4d)\n", x, (int)realy); gluUnProject ((GLdouble) x, (GLdouble) realy, (GLdouble) 0,mvmatrix, projmatrix, viewport, &wx, &wy, &wz); t=3; // fix t to 3 Mx = t*(wx-Ax)+Ax; //we calacul position of m with t My = t *(wy-Ay) +Ay; Mz =t*(wz-Az)+Az ; printf ("Coordinates at cursor are (%4f, %4f,%4f)\n", (float)Mx, (float)My, (float)Mz); glutPostRedisplay(); } break; case GLUT_RIGHT_BUTTON: if (state == GLUT_DOWN) exit(0); break; default: break; }}void keyboard(unsigned char key, int x, int y){ switch (key) { case 27: exit(0); break; }}void processMenuEvents(int option) {switch (option) {case RED :ss=1; break;}glutPostRedisplay();} int main(int argc, char** argv){ wx=0; wy=0; wz=0; Ax=2; Ay=2; Az=5.0; glutInit(&argc, argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); glutInitWindowSize (500, 500); glutInitWindowPosition (100, 500); glutCreateWindow (argv[0]); int menu = glutCreateMenu(processMenuEvents); glutAddMenuEntry("Red",RED); glutAttachMenu(GLUT_RIGHT_BUTTON); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc (keyboard); glutMouseFunc(mouse); glutMainLoop(); return 0;}