Wspominałem parę dni temu o tym, że stworzenie systemu materiałów i światła będzie dla mnie czymś nowym – nigdy przedtem nie projektowałem takiego mechanizmu (zawsze wystarczało mi to, co standardowo było oferowane) i tak naprawdę (tak, wiem, wstyd się przyznawać) nigdy nie zastanawiałem się “po co jest taki parametr i dlaczego”. A teraz już wiem.
Tak poważnie, to ważnym problemem było po prostu zdefiniowanie parametrów, jakie wchodzą w skład materiału. To akurat nie było specjalnie skomplikowane – otworzyłem przykłady dotyczące Cg, zobaczyłem, co jest przydatne, zebrałem, pogrupowałem, pomyślałem (tak, nowość) i uznałem, że i tak pewnie potem będę dodawał nowe parametry (co ma być w miarę elastyczne, zgodnie z ideą obiektowości [co i tak do końca nie wyszło]), więc nic nie szkodzi.
Jakie założenia przyjąłem odnośnie materiałoznawstwa w Scavie?
Postudiowałem trochę książkę o Cg, pracę magisterską Regedita (pozdrawiam), tutoriale Ogre’a (choć tutaj bardziej już o światło zahaczałem), powypytywałem mojego glonojada (gdzieś tu obok się kręci – nie był zbyt zainteresowany rozmową) i o to, co mi wyszło.
- Jeden obiekt w grze (mesh) może mieć przypisanych więcej niż jeden materiał
- Jeden materiał oznacza jedną teksturę wraz z przyległościami (reakcja na odpowiednie światło, zdolność do odbijania itd.)
- Programista korzystający z silnika nie może aż tak bardzo przejmować się tym, jak zarządzane są materiały wewnątrz mesha (choć oczywiście powinien mieć możliwość przypisania “tak, chcę aby ta część miała taki materiał”)
- Obsługa materiałów powinna być prosta – jako wzór powinna służyć struktura pliku OBJ (po nazwie materiału wszystkie dane korzystają właśnie z tego materiału)
W sumie to tyle. Jak widać, idea szczytna (i dosyć standardowa), ale w trzeba było to jakoś sprytnie zaimplementować. Cóż, sprytnie nie wyszło, ale za to skutecznie.
Otóż, dla każdego mesha generowane są bufory VBO, żeby rendering przebiegał szybciej, a wszystko wygląda bardzo profesjonalnie. Dlatego trzeba było coś zrobić z tymi buforami, aby można wyświetlać obiekt partiami. Czy najprostsze rozwiązanie już Wam przyszło do głowy? Owszem, stwórzmy więcej buforów.
W tej chwili informacje o wierzchołkach, zamiast w wektorach, są zapisywanie w mapach wektorów.
1: std::map<std::string, std::vector<CVertex*> > dane;
Gdzie std::string określa nazwę materiału, dla którego mamy dane informacje. Co ciekawe, przy wydobywaniu informacji o współrzędnych z wektorów użytkownik tak naprawdę nie wie, do którego materiału należy dany punkt – według mojego toku myślenia nie powinno go to interesować, gdyż raczej nie będzie chciał zmieniać umiejscowienia materiałów w locie.
Owszem, rozwiązanie to jest nieco mniej efektywne niż można by było przypuszczać, ale wada nie jest potworna, a elastyczność i wygoda korzystania – znaczna. Spójrzmy bowiem na dodawanie informacji o danym meshu do węzła sceny o nazwie scene_node.
2: float tex[] = { 0, 0, 1, 0, 1, 1, 0, 1 };
3: float norm[] = { 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1 };
4: 5: CStaticMesh* mesh = scene_node->AddMesh("kwadrat");
6: CMaterial* mat = mesh->AddMaterial("drewno");
7: mat->SetTexture(texture); // gdzie texture to wskaźnik do obiektu tekstury
8: // te informacje, które teraz podajemy, odnoszą się do aktualnie
9: // ustanowionego materiału o nazwie "drewno"
10: mesh->AddVertex(vert, 4); 11: mesh->AddTexCoord(tex, 4); 12: mesh->AddNormal(norm, 4); 13: mesh->SetMeshType(MT_QUADS);A teraz zróbmy to samo wczytując mesha z pliku tekstowego (taką formę reprezentacji wybrałem na razie, pewnie potem ulegnie to modyfikacji).
1: CStaticMesh* mesh = scene_node->AddMesh("kwadrat");
2: mesh->Import("kwadrat.mesh"); // gdzie kwadrat.mesh to wcześniej wyeksportowany
3: // plik z danymi, które wcześniej podaliśmy w sposób jawny w kodzie
Jak widać, przypomina to nieco inne silniki, a jednocześnie jest w miarę intuicyjne – pobieramy sobie wskaźnik na nowo utworzony obiekt i modyfikujemy go według potrzeb. W drugim przypadku nie musimy nawet zajmować się materiałem, gdyż informacja o nim znajduje się w pliku .mesh, a importer sam próbuje znaleźć plik o nazwie [nazwa_materiału].material w bieżącym katalogu i go wczytać. Jeżeli mu się nie uda – musimy sami zadbać o dostarczenie danych, ale przy dobrej organizacji nie powinno być problemu.
A co, jeżeli nie chce nam się dla mesha definiować osobno materiału? Wtedy zawsze pozostanie utworzony materiał o nazwie “default_material” (zdefiniowany pod makrem DEFAULT_MATERIAL), do którego również możemy się normalnie odwoływać.
Podsumowując, wprowadzenie materiałów troszeczkę zagmatwało sytuację z meshami, ale szczęśliwie, po wielu krzykach, nawoływaniach i różnego rodzaju motywowaniu się (i męczeniu kolegów) udało się wszystko pogodzić, żeby działało.
Teraz pozostaje implementacja światła. Czy również będzie tak “prosto” jak w przypadku materiałów? Zobaczymy.
Pozdrawiam i dziękuję - SceNtriC
0 komentarze:
Prześlij komentarz