مشكلة في إنشاء واجهة ثنائية الأبعاد في عالم OpenGL ثلاثي الأبعاد

StackOverflow https://stackoverflow.com/questions/4289095

  •  28-09-2019
  •  | 
  •  

سؤال

أنا أعمل في مشروع يتطلب إنشاء واجهة ثنائية الأبعاد تم تقديمها "في الأعلى" أو عالم ثلاثي الأبعاد. في بعض المنتديات الأخرى ، قرأت أنه يمكنك استخدام "Gluortho2d ()" للوظيفة ، والعودة إلى Gluperseptive () بمجرد الانتهاء من ذلك. الشيء الوحيد هو ، رمز الاختبار الذي كتبته من أجله يعرض العالم ثلاثي الأبعاد فقط ، وليس الربع ثنائي الأبعاد. عندما أقوم بتعطيل رمز العرض ثلاثي الأبعاد ، يظهر الربع حيث كان من المفترض أن يكون. قمت بتقليص الكود إلى OpenGL فقط عبارات ، والتي كتبت أدناه. الكود مكتوب في Python باستخدام مكتبة Pyglet.


رمز تهيئة المشهد:

glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(60.0, float(width)/height, .1, 10000.)
glMatrixMode(GL_MODELVIEW)
glClearDepth(1.0)
glShadeModel(GL_FLAT)
glEnable(GL_DEPTH_TEST)
glDepthFunc(GL_LEQUAL) 
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)

رمز تقديم الإطار. إن الدعوة إلى Builder.buildMap () تنشئ المشهد ثلاثي الأبعاد ، وزوج Glbegin-Glend يرسم رباعيًا ثنائي الأبعاد:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
stage.set3DMode(window.width, window.height)
builder.buildMap()
stage.set2DMode(window.width, window.height)
glBegin (GL_QUADS)
glVertex2i(0, 0)
glVertex2i(0, 200)
glVertex2i(200, 200)
glVertex2i(200, 0) 
glEnd()

وظيفة stage.set3dmode:

glDisable(GL_DEPTH_TEST) 
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluOrtho2D(0, width, 0, height)
glMatrixMode(GL_MODELVIEW)

و stage.set3dmode وظيفة:

glEnable(GL_DEPTH_TEST) 
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(60.0, float(width)/float(height), .1, 10000.)
glMatrixMode(GL_MODELVIEW)

آمل حقًا أن يتمكن شخص ما من الإشارة إلى خطأي! وشكرا لمساعدتي :)

هل كانت مفيدة؟

المحلول

يبدو أنك لا تتصل glLoadIdentity() بعد التبديل إلى gl_modelview. أبسط طريقة للتذكر هي الاتصال به في كل مرة تقوم فيها بتغيير مصفوفة الإسقاط ، والتبديل إلى GL_MODELVIEW و CALL glLoadIdentity() (إلا إذا كنت تريد حقًا الاحتفاظ بالمرض القديم).

نصائح أخرى

الكثير من الناس يخطئون في كيفية استخدام glviewport وما شابه. إنهم دائمًا يضعونه في رد الاتصال الذي يعتبر خطأ.

أنت دائمًا إلى الإعداد الكامل في وظيفة التقديم الخاصة بك ، قبل أن تحتاج إلى تلك الإعدادات مباشرة. لذلك يجب أن يكون الكود الخاص بك (Pesudocode):

render_scene():
    // first clear the whole window
    glViewport(0, 0, window.width, window.height)
    glClearDepth(1.0)
    glClearColor(1., 1., 1., 1.);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)

    glViewport(3Dstuff.x, 3Dstuff.y, 3Dstuff.w, 3Dstuff.h)
    // maybe also set scissor to clip
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(60.0, float(width)/height, .1, 10000.)
    glMatrixMode(GL_MODELVIEW)
    setup3DstuffModelview()
    glDepthFunc(...)
    glEnable(GL_DEPTH_TEST)
    // other state stuff
    render3Dstuff()

    // now the 2D stuff
    glViewport(2Dstuff.x, 2Dstuff.y, 2Dstuff.w, 2Dstuff.h)
    // clear depth and stencil -- if you need parts of the 3D depth / stencil
    // for some algorithm retain it or save and restore by FBO renderbuffers or
    // glReadPixels, glDrawPixels
    glClearDepth(1.0)
    glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)

    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    glOrtho(...)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()
    setup2DstuffModelview()
    glDepthFunc(...)
    glDisable(GL_DEPTH_TEST)
    // other state stuff
    render2Dstuff()

    // repeat for all the layers you need

هذا مهم حقًا: OpenGL هو آلة الدولة. ما لم تتمكن من إثبات عدم حدوث أي تغييرات غير محددة في حالة ، فأنت دائمًا ما تعيد/تعيد تعيين جميع الحالات التي تحتاجها قبل تقديم هندسة معينة.

أستخدم المصفوفات التالية لتقديم ثنائي الأبعاد:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, w, h, 0, 0, 1);
glViewport(0, 0, w, h);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.375f, 0.375f, 0);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top