OpenSceneGraph: إدارة Windows و أوضاع العرض

الصورة

مقدمة


قلنا بالفعل أن فئة osg :: Camera تدير سياق رسومات OpenGL المرتبط. يحتوي سياق الرسومات على معلومات حول كيفية ومكان رسم الكائنات وسمات الحالة التي يتم تطبيقها عليها. يتم فهم السياق على أنه نافذة رسومية ، أو بالأحرى منطقة العميل الخاصة به ، أو مخزن OpenGL بكسل ، والذي يخزن بيانات البكسل دون نقلها إلى المخزن المؤقت للإطار.

يستخدم OSG فئة osg :: GraphicsContext لتمثيل سياق رسومات مجردة ، وفئة osg :: GraphicsWindow لتمثيل نافذة رسومات مجردة. لدى الأخير أسلوب getEventQueue () لإدارة الأحداث من عناصر واجهة المستخدم الرسومية. بشكل عام ، يعد السياق الرسومي مفهومًا خاصًا بالنظام الأساسي ، لذلك يهتم OSG بمعظم أعمال إنشاء نافذة وربط سياقها بسياق OpenGL. عند استدعاء الأسلوب createGraphicsContext () للفئة osg :: GraphicsContext () ، سيتم إنشاء التعليمات البرمجية المطلوبة (وهناك الكثير منها ، صدقني!) تلقائيًا بواسطة المعالج الأولي ، وفقًا للنظام الأساسي. كل ما هو مطلوب منا هو تمرير وسيطة من نوع osg :: GraphicsContex :: Traits إلى هذه الطريقة تحتوي على وصف للإطار الذي نريد استلامه.

1. فئة osg :: DisplaySettings


يسمح OSG للمطور بإدارة إعدادات العرض العالمية ، على أساسها يتم تقديم الكاميرات والمشاهدين وعناصر المشهد. لهذا الغرض ، يتم استخدام النمط المفرد ، أي كائن فريد يحتوي على هذه الإعدادات ، ويتم تنفيذه في شكل فئة osg :: DisplaySettings ، والتي يمكن الوصول إليها من أي مكان في البرنامج. لذلك ، من تطبيقنا ، يمكننا تغيير هذه الإعدادات في أي وقت.

osg::DisplaySettings *ds = osg::DisplaySettings::instance(); 

يحتوي Singleton osg :: DisplaySettings على الإعدادات التي تنطبق على أجهزة التقديم التي تم إنشاؤها حديثًا ، وهي سياق OpenGL لإطار الرسومات. يمكنك تغيير المعلمات التالية:

  1. setDoubleBuffer () - تمكين / تعطيل التخزين المؤقت المزدوج. تمكين افتراضيا.
  2. setDepthBuffer () - تمكين / تعطيل المخزن المؤقت للعمق. تمكين افتراضيا.
  3. قم بتعيين عرض المخزن المؤقت ألفا ، المخزن المؤقت الاستنسل ، المخزن المؤقت التراكم باستخدام أساليب مثل setMinimumNumAlphaBits (). بشكل افتراضي ، كل المعلمات هي 0.
  4. إذن لاستخدام مكافحة التعرج وعمقها باستخدام طريقة setNumMultiSamples (). الافتراضي هو 0.
  5. قم بتشغيل وضع الاستريو. قبالة افتراضيا.

النظر في استخدام هذا المفردة على سبيل المثال من تجانس

Osg سبيل المثال: :: DisplaySettings
الرئيسية

 #ifndef MAIN_H #define MAIN_H #include <osgDB/ReadFile> #include <osgViewer/Viewer> #endif 

main.cpp

 #include "main.h" int main(int argc, char *argv[]) { (void) argc; (void) argv; osg::DisplaySettings::instance()->setNumMultiSamples(6); osg::ref_ptr<osg::Node> model = osgDB::readNodeFile("../data/cessna.osg"); osgViewer::Viewer viewer; viewer.setSceneData(model.get()); return viewer.run(); } 


أساسي هنا هو تحد واحد فقط.

 osg::DisplaySettings::instance()->setNumMultiSamples(6); 

- تعيين معلمة التجانس ، والتي يمكن أن تأخذ القيم 2 و 4 و 6 ، اعتمادًا على جهاز الرسوم المستخدم. انتبه إلى الشكل الذي تبدو به شفرة cessna بدون تطبيق التنعيم



وبعد تطبيقها



2. التبديل إلى وضع النافذة


يمكن إعادة تكوين فئة osgViewer :: Viewer بسرعة كبيرة لعرضها في وضع إطارات. كما لاحظت ، تم عرض جميع الأمثلة السابقة في وضع ملء الشاشة. لتبديل العارض إلى وضع الإطار ، هناك طريقة setUpViewInWindow () ، والتي تأخذ كمعلمات إحداثيات الزاوية العليا اليسرى من النافذة وعرضها وارتفاعها بالبكسل

 viewer.setUpViewInWindow(50, 50, 800, 600); 

اختيارياً ، تقبل هذه الطريقة المعلمة الخامسة - رقم الشاشة التي يجب أن يتم عرض النافذة عليها ، في حالة وجود أكثر من شاشة واحدة. من المؤكد أنك تعمل مع شاشات متعددة في Windows ، لاحظت أن المشهد ينتشر على جميع الشاشات في وضع ملء الشاشة (لا يتم ملاحظة ذلك في Linux).

بالإضافة إلى ذلك ، في إعدادات المشروع ، يمكنك تعيين متغير البيئة OSG_WINDOW بهذه الطريقة



والتي ستكون مكافئة لاستدعاء setUpViewInWindow () ، والتي في هذه الحالة قد لا يتم تنفيذها.



لتحديد الشاشة التي يجب على العارض عرضها في وضع ملء الشاشة بشكل صريح ، يمكنك استخدام طريقة setUpViewOnSingleScreen () عن طريق تحديد رقم الشاشة كمعلمة (0 افتراضيًا).

يدعم OSG أيضًا العروض التوضيحية الكروية. يمكنك استخدام طريقة setUpViewFor3DSphericalDisplay () لتخصيص العرض على مثل هذا العرض.

3. المشاهد مركب


يتحكم فئة osgViewer :: Viewer في طريقة عرض واحدة تعرض رسمًا بيانيًا فرديًا. بالإضافة إلى ذلك ، هناك فئة osgViewer :: CompositeViewer والتي تدعم العديد من المشاهدات والعديد من المشاهد. يحتوي على نفس أساليب التشغيل () و frame () و done () للتحكم في عملية التقديم ، لكنه يسمح لك بإضافة طرق عرض مستقلة وإزالتها باستخدام أساليب addView () و removeView () ، وكذلك الحصول على طرق العرض بواسطة فهرسهم باستخدام طريقة getView (). يتم وصف كائن العرض بواسطة فئة osgViewer :: View.

الفئة osgViewer :: View هي الفئة الأساسية لفئة osgViewer :: Viewer. يسمح لك بإضافة عقدة الجذر مع بيانات المشهد ومعالج الكاميرا ومعالجات الأحداث. يتمثل الاختلاف الرئيسي بين هذه الفئة (العرض) وفئة العارض في أنها لا تسمح بعرض المشهد باستخدام مكالمات التشغيل () أو الإطار (). وجهة نظر نموذجية مضيفا يبدو مثل هذا

 osgViewer::CompositeViewer multiviewer; multiviewer.addView( view ); 

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

مثال مركب
الرئيسية

 #ifndef MAIN_H #define MAIN_H #include <osgDB/ReadFile> #include <osgViewer/CompositeViewer> #endif 

main.cpp

 #include "main.h" //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ osgViewer::View *createView(int x, int y, int w, int h, osg::Node *scene) { osg::ref_ptr<osgViewer::View> view = new osgViewer::View; view->setSceneData(scene); view->setUpViewInWindow(x, y, w, h); return view.release(); } //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ int main(int argc, char *argv[]) { (void) argc; (void) argv; osg::ref_ptr<osg::Node> model1 = osgDB::readNodeFile("../data/cessna.osg"); osg::ref_ptr<osg::Node> model2 = osgDB::readNodeFile("../data/cow.osg"); osg::ref_ptr<osg::Node> model3 = osgDB::readNodeFile("../data/glider.osg"); osgViewer::View *view1 = createView(50, 50, 320, 240, model1); osgViewer::View *view2 = createView(380, 50, 320, 240, model2); osgViewer::View *view3 = createView(185, 330, 320, 240, model3); osgViewer::CompositeViewer viewer; viewer.addView(view1); viewer.addView(view2); viewer.addView(view3); return viewer.run(); } 


سنضع إنشاء طريقة عرض منفصلة في وظيفة تأخذ كموقع لموضع الإطار وحجمه ، وكذلك المشهد كمؤشر لعقدة الجذر الخاصة به

 osgViewer::View *createView(int x, int y, int w, int h, osg::Node *scene) { osg::ref_ptr<osgViewer::View> view = new osgViewer::View; view->setSceneData(scene); view->setUpViewInWindow(x, y, w, h); return view.release(); } 

هنا نقوم بإنشاء طريقة عرض يتحكم فيها مؤشر ذكي لكائن osgViewer :: View

 osg::ref_ptr<osgViewer::View> view = new osgViewer::View; 

اضبط بيانات المشهد المعروض ووضع عرض النافذة في النافذة مع الموضع والحجم المحددين

 view->setSceneData(scene); view->setUpViewInWindow(x, y, w, h); 

نرجع العرض من الوظيفة وفقًا لقواعد إرجاع المؤشرات الذكية

 return view.release(); 

الآن في البرنامج الرئيسي نقوم بتحميل ثلاثة نماذج مختلفة

 osgViewer::View *view1 = createView(50, 50, 320, 240, model1); osgViewer::View *view2 = createView(380, 50, 320, 240, model2); osgViewer::View *view3 = createView(185, 330, 320, 240, model3); 

إنشاء ثلاثة أنواع مختلفة

 osgViewer::View *view1 = createView(50, 50, 320, 240, model1); osgViewer::View *view2 = createView(380, 50, 320, 240, model2); osgViewer::View *view3 = createView(185, 330, 320, 240, model3); 

إنشاء عارض مركب وإضافة طرق عرض تم إنشاؤها مسبقًا إليه

 osgViewer::CompositeViewer viewer; viewer.addView(view1); viewer.addView(view2); viewer.addView(view3); 

وقم بتشغيل العرض بنفس الطريقة تمامًا كما فعلنا في حالة مشهد واحد

 return viewer.run(); 

هذا كل شئ! عندما يبدأ البرنامج ، نحصل على ثلاثة نوافذ مختلفة. يمكن التحكم في محتويات كل نافذة بشكل مستقل. يمكن إغلاق أي من النوافذ بالطريقة القياسية ، والخروج تمامًا من التطبيق عن طريق الضغط على Esc.



3. فئة osg :: GraphicsContext :: Traits


كلمة "سمات" في الترجمة من اللغة الإنجليزية تعني "ميزات". لذلك ، تصف الفئة المذكورة أعلاه ميزات الإطار المستقبلي ، وتحتوي على جميع الخصائص لوصف سياق الرسوم. إنه يختلف عن فئة osg :: DisplaySettings ، التي تتحكم في خصائص جميع سياقات الرسومات للكاميرات المنشأة حديثًا. الخصائص العامة الرئيسية لهذه الفئة مدرجة في الجدول أدناه.

سمة الطبقةاكتبالقيمة الافتراضيةالوصف
سكثافة العمليات0الموضع الأفقي الأولي للنافذة
ذكثافة العمليات0الموقف الرأسي الأولي للنافذة
العرضكثافة العمليات0عرض النافذة
ارتفاعكثافة العمليات0ارتفاع النافذة
windowNameالأمراض المنقولة جنسيا :: سلسلة""عنوان النافذة
windowDecorationمنطقيخطأنافذة عرض عنوان العلم
احمركثافة العمليات غير الموقعة8عدد وحدات البت باللون الأحمر في مخزن الألوان OpenGL
الأخضركثافة العمليات غير الموقعة8عدد وحدات البت باللون الأخضر في مخزن الألوان OpenGL
الأزرقكثافة العمليات غير الموقعة8عدد بتات اللون الأزرق في مخزن الألوان OpenGL
ألفاكثافة العمليات غير الموقعة8عدد البتات في المخزن المؤقت alpha OpenGL
عمقكثافة العمليات غير الموقعة24عدد البتات في المخزن المؤقت لعمق OpenGL
استنسلكثافة العمليات غير الموقعة0عدد البتات في مخزن OpenGL الاستنسل
doubleBufferمنطقيخطأاستخدام العازلة مزدوجة
عيناتكثافة العمليات غير الموقعة0عدد تجانس البدائية
quadBufferStereoمنطقيخطأاستخدام المخزن المؤقت ستيريو رباعي (لمعدات NVidia)
وراثةويندو داتاosg :: ref_ptrلاغيةنافذة البيانات المرتبطة واصف

لتهيئة كائن السمات ، قم بتنفيذ التعليمات البرمجية التالية

 osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits; traits->x = 50; traits->y = 100; ... 

4. قم بإعداد نافذة تطبيق OSG


لإنشاء نافذة مع الخصائص المحددة ، يجب عليك القيام بالخطوات التالية:

  1. تكوين كائن من النوع osg :: GraphicsContext :: Traits
  2. إنشاء سياق نافذة رسومية
  3. ربط سياق الرسومات هذا بالكاميرا
  4. اجعل الكاميرا العارض الرئيسي

مثال الصفات
الرئيسية

 #ifndef MAIN_H #define MAIN_H #include <osg/GraphicsContext> #include <osgDB/ReadFile> #include <osgViewer/Viewer> #endif 

main.cpp

 #include "main.h" int main(int argc, char *argv[]) { (void) argc; (void) argv; osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits; traits->x = 50; traits->y = 50; traits->width = 800; traits->height = 600; traits->windowName = "OSG application"; traits->windowDecoration = true; traits->doubleBuffer = true; traits->samples = 4; osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get()); osg::ref_ptr<osg::Camera> camera = new osg::Camera; camera->setGraphicsContext(gc); camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) ); camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); camera->setClearColor( osg::Vec4(0.2f, 0.2f, 0.4f, 1.0f) ); double aspect = static_cast<double>(traits->width) / static_cast<double>(traits->height); camera->setProjectionMatrixAsPerspective(30.0, aspect, 1.0, 1000.0); camera->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON); osg::ref_ptr<osg::Node> root = osgDB::readNodeFile("../data/cessna.osg"); osgViewer::Viewer viewer; viewer.setCamera(camera.get()); viewer.setSceneData(root.get()); return viewer.run(); } 


لتعيين تفضيلات النافذة ، قم بإنشاء مثيل لفئة osg :: GraphicsContext :: Traits وقم بتهيئته باستخدام المعلمات التي نحتاجها

 osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits; traits->x = 50; traits->y = 50; traits->width = 800; traits->height = 600; traits->windowName = "OSG application"; traits->windowDecoration = true; traits->doubleBuffer = true; traits->samples = 4; 

بعد ذلك ، نقوم بإنشاء سياق رسومي بتمرير مؤشر إلى السمات كإعدادات

 osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get()); 

اصنع كاميرا

 osg::ref_ptr<osg::Camera> camera = new osg::Camera; 

نحن نربط الكاميرا مع سياق الرسم الذي تم إنشاؤه

 camera->setGraphicsContext(gc); 

قم بإعداد منفذ العرض ، واضبط قناع التنظيف المؤقت ، واضبط لون التنظيف

 camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) ); camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); camera->setClearColor( osg::Vec4(0.2f, 0.2f, 0.4f, 1.0f) ); 

قم بإعداد مصفوفة عرض منظور

 double aspect = static_cast<double>(traits->width) / static_cast<double>(traits->height); camera->setProjectionMatrixAsPerspective(30.0, aspect, 1.0, 1000.0); 

لا تنس تمكين اختبار العمق ، للعرض الصحيح للوجوه

 camera->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON); 

تحميل نموذج الطائرة

 osg::ref_ptr<osg::Node> root = osgDB::readNodeFile("../data/cessna.osg"); 

نقوم بتهيئة المشاهد وإطلاقه ، مع الإشارة إلى الكاميرا التي قمنا بتكوينها بجودة الكاميرا الرئيسية

 osgViewer::Viewer viewer; viewer.setCamera(camera.get()); viewer.setSceneData(root.get()); return viewer.run(); 

عند الخروج لدينا نافذة مع المعلمات المطلوبة



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

أن تستمر ...

Source: https://habr.com/ru/post/ar437764/


All Articles