OpenSceneGraph: Mengelola Windows dan Mode Tampilan

gambar

Pendahuluan


Kami telah mengatakan bahwa kelas osg :: Camera mengelola konteks grafis OpenGL yang terkait. Konteks grafis merangkum informasi tentang bagaimana dan di mana objek digambar dan atribut status apa yang diterapkan padanya. Konteks dipahami sebagai jendela grafis, atau lebih tepatnya area kliennya, atau buffer piksel OpenGL yang menyimpan data piksel tanpa mentransfernya ke frame buffer.

OSG menggunakan kelas osg :: GraphicsContext untuk mewakili konteks grafis abstrak, dan kelas osg :: GraphicsWindow untuk mewakili jendela grafis abstrak. Yang terakhir memiliki metode getEventQueue () untuk mengelola acara dari elemen GUI. Secara umum, konteks grafis adalah konsep platform-spesifik, sehingga OSG menangani sebagian besar pekerjaan membuat jendela dan mengaitkan konteksnya dengan konteks OpenGL. Ketika Anda memanggil metode createGraphicsContext () dari kelas osg :: GraphicsContext (), kode yang diperlukan (dan ada banyak, percayalah!) Akan secara otomatis dihasilkan oleh preprocessor, tergantung pada platform. Yang harus kita lakukan adalah memberikan argumen ke metode tipe osg :: GraphicsContex :: Traits ini, yang berisi deskripsi tentang jendela mana yang ingin kita dapatkan.

1. Kelas osg :: DisplaySettings


OSG memungkinkan pengembang untuk mengelola pengaturan tampilan global, atas dasar yang diberikan kamera, pemirsa dan elemen adegan. Untuk ini, pola singleton digunakan, yaitu, objek unik yang berisi pengaturan ini, diimplementasikan dalam bentuk kelas osg :: DisplaySettings, yang dapat diakses dari mana saja dalam program ini. Karena itu, dari aplikasi kita, kita dapat mengubah pengaturan ini kapan saja.

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

Singleton osg :: DisplaySettings berisi pengaturan yang berlaku untuk perangkat rendering yang baru dibuat, konteks OpenGL dari jendela grafis. Anda dapat memvariasikan parameter berikut:

  1. setDoubleBuffer () - aktifkan / nonaktifkan buffering ganda. Diaktifkan secara default.
  2. setDepthBuffer () - mengaktifkan / menonaktifkan buffer kedalaman. Diaktifkan secara default.
  3. Atur lebar buffer alpha, buffer stensil, buffer akumulasi dengan menggunakan metode seperti setMinimumNumAlphaBits (). Secara default, semua parameter adalah 0.
  4. Izin untuk menggunakan anti-aliasing dan kedalamannya menggunakan metode setNumMultiSamples (). Standarnya adalah 0.
  5. Aktifkan mode stereo. Dinonaktifkan secara default.

Pertimbangkan penggunaan singleton ini pada contoh smoothing

Contoh tunggal :: DisplaySettings
main.h

 #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(); } 


Penting di sini hanya satu tantangan.

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

- mengatur parameter smoothing, yang dapat mengambil nilai 2, 4 dan 6, tergantung pada perangkat grafis yang digunakan. Perhatikan bagaimana bilah sekrup cessna terlihat tanpa menerapkan perataan



dan setelah penerapannya



2. Beralih ke mode jendela


Kelas osgViewer :: Viewer dapat dengan cepat dikonfigurasi ulang untuk ditampilkan dalam mode berjendela. Seperti yang Anda perhatikan, semua contoh kami sebelumnya ditampilkan dalam layar penuh. Untuk mengalihkan penampil ke mode berjendela, ada metode setUpViewInWindow (), yang berfungsi sebagai parameter koordinat sudut kiri atas jendela, lebar dan tinggi pikselnya.

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

Secara opsional, metode ini menerima parameter kelima - jumlah layar tempat jendela ditampilkan, jika Anda memiliki lebih dari satu monitor. Tentunya bekerja dengan beberapa monitor di Windows, Anda mengamati bahwa adegan menyebar ke semua monitor dalam mode layar penuh (ini tidak diamati di Linux).

Selain itu, dalam pengaturan proyek, Anda dapat mengatur variabel lingkungan OSG_WINDOW dengan cara ini



yang akan setara dengan memanggil setUpViewInWindow (), yang dalam hal ini mungkin tidak dieksekusi.



Untuk menentukan secara eksplisit layar tempat pemirsa harus ditampilkan dalam mode layar penuh, Anda dapat menggunakan metode setUpViewOnSingleScreen () dengan menentukan nomor layar sebagai parameter (0 secara default).

OSG juga mendukung tampilan bulat demo. Anda dapat menggunakan metode setUpViewFor3DSphericalDisplay () untuk menyesuaikan tampilan pada tampilan seperti itu.

3. Penampil komposit


Kelas osgViewer :: Viewer mengontrol tampilan tunggal yang menampilkan grafik adegan tunggal. Selain itu ada kelas osgViewer :: CompositeViewer yang mendukung beberapa tampilan dan beberapa adegan. Ini memiliki metode run (), frame () dan done () yang sama untuk mengendalikan proses rendering, tetapi ia memungkinkan Anda untuk menambah dan menghapus tampilan independen menggunakan metode addView () dan removeView (), serta mendapatkan pandangan berdasarkan indeks mereka menggunakan metode getView (). Objek tampilan dijelaskan oleh kelas osgViewer :: View.

Kelas osgViewer :: View adalah kelas dasar untuk kelas osgViewer :: Viewer. Ini memungkinkan Anda untuk menambahkan simpul root dengan data pemandangan, manipulator kamera dan pengendali acara. Perbedaan utama antara kelas ini (tampilan) dan kelas penampil adalah bahwa ia tidak memungkinkan rendering adegan dengan panggilan run () atau frame (). Tampilan menambahkan skenario yang khas terlihat seperti ini

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

Penampil komposit memungkinkan Anda untuk menampilkan satu adegan di sudut yang berbeda, menampilkan sudut ini di jendela yang berbeda. Ini juga memungkinkan Anda untuk menampilkan adegan independen di berbagai jendela. Mari kita menulis contoh sederhana menggunakan penampil komposit

Contoh komposit
main.h

 #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(); } 


Kami akan menempatkan pembuatan tampilan terpisah dalam fungsi yang mengambil parameter posisi dan ukuran jendela, serta adegan sebagai penunjuk ke simpul akar

 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(); } 

Di sini kita membuat tampilan yang dikendalikan oleh penunjuk pintar ke objek osgViewer :: View

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

atur data adegan yang ditampilkan dan mode tampilan jendela di jendela dengan posisi dan ukuran yang ditentukan

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

Kami mengembalikan tampilan dari fungsi sesuai dengan aturan untuk mengembalikan smart pointer

 return view.release(); 

Sekarang di program utama kami memuat tiga model yang berbeda

 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); 

buat tiga tipe berbeda

 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); 

buat penampil komposit dan tambahkan tampilan yang dibuat sebelumnya untuk itu

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

dan menjalankan rendering dengan cara yang persis sama seperti yang kami lakukan dalam kasus satu adegan

 return viewer.run(); 

Itu saja! Ketika program dimulai, kita mendapatkan tiga jendela berbeda. Isi setiap jendela dapat dikontrol secara independen. Setiap jendela dapat ditutup dengan cara standar, dan sepenuhnya keluar dari aplikasi dengan menekan Esc.



3. Kelas osg :: GraphicsContext :: Traits


Kata "traits" dalam terjemahan dari bahasa Inggris berarti "fitur". Jadi, kelas yang disebutkan di atas menggambarkan fitur-fitur jendela masa depan, dan berisi semua properti untuk menggambarkan konteks grafik. Ini berbeda dari kelas osg :: DisplaySettings, yang mengontrol karakteristik semua konteks grafis untuk kamera yang baru dibuat. Properti publik utama dari kelas ini tercantum dalam tabel di bawah ini.

Atribut kelasJenisNilai standarDeskripsi
xint0Posisi horizontal awal jendela
yint0Posisi vertikal awal jendela
lebarint0Lebar jendela
tinggiint0Tinggi jendela
windowNamestd :: string""Judul jendela
windowDekorasiboolsalahJendela Tampilan Layar Bendera
merahunsigned int8Jumlah bit merah di buffer warna OpenGL
hijauunsigned int8Jumlah bit hijau dalam buffer warna OpenGL
biruunsigned int8Jumlah bit biru di buffer warna OpenGL
alfaunsigned int8Jumlah bit dalam buffer alpha OpenGL
mendalamunsigned int24Jumlah bit dalam buffer kedalaman OpenGL
stensilunsigned int0Jumlah bit dalam buffer stensil OpenGL
doubleBufferboolsalahGunakan buffer ganda
sampelunsigned int0Nomor smoothing primitif
quadBufferStereoboolsalahGunakan buffer quad stereo (untuk peralatan NVidia)
mewarisiWindowDataosg :: ref_ptrTidakDeskriptor data terkait jendela

Untuk menginisialisasi objek Traits, jalankan kode berikut

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

4. Atur jendela aplikasi OSG


Untuk membuat jendela dengan karakteristik yang ditentukan, Anda harus melakukan langkah-langkah berikut:

  1. Mengkonfigurasi objek bertipe osg :: GraphicsContext :: Traits
  2. Buat konteks jendela grafis
  3. Tautkan konteks grafik ini ke kamera
  4. Jadikan kamera penampil utama

Contoh sifat
main.h

 #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(); } 


Untuk mengatur preferensi jendela, buat turunan dari kelas osg :: GraphicsContext :: Traits dan inisialisasi dengan parameter yang kita butuhkan

 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; 

Setelah itu, kita membuat konteks grafis dengan melewatkan pointer ke traits sebagai pengaturan

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

Buat kamera

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

Kami mengaitkan kamera dengan konteks grafik yang dibuat

 camera->setGraphicsContext(gc); 

Atur viewport, atur masker pembersih penyangga, atur warna pembersihan

 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) ); 

Siapkan matriks proyeksi perspektif

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

Jangan lupa untuk mengaktifkan tes kedalaman, untuk tampilan wajah yang benar

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

Memuat model pesawat

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

Kami mengonfigurasi dan meluncurkan penampil, yang menunjukkan kamera yang kami konfigurasikan dalam kualitas kamera utama

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

Di pintu keluar kami memiliki jendela dengan parameter yang diperlukan



Judul jendela tidak ditampilkan karena fungsi ini dinonaktifkan pada pengaturan manajer jendela saya. Jika Anda menjalankan contoh di Windows atau Linux dengan pengaturan yang berbeda, header akan berada di tempatnya.

Dilanjutkan ...

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


All Articles