Eksportowanie geometrii z Blender-a
Ostatnio przerabiałem eksporter geometrii z blendera. aktualny skrypt był bardzo stary i potrzebował natychmiastowej przeróbki, wiec napisałem nowy. Przedstawię kilka porad na podstawie moich ostatnich doświadczeń na tym polu. Używam Blendera 2.49
Najwazniejsze to określić co będziemy eksportować. Czy to będzie jedna siatka, czy cały model (model składa się z x siatek (mesh))?, czy format będzie 'końcowy' czy przetwarzany?, jakie dane eksportować? jak i czy eksportować animacje? jak eksportować materiały? czy to będzie format binarny czy tekstowy? postaram się pomoc w odpowiedzi na niektóre z nich
- Format końcowy vs format pośredni - moim zdaniem format końcowy jest lepszy, bo nie musimy tracić czasu na konwersje i bawienie się z zewnętrznymi konwerterami. Poza tym mamy dostęp do całej masy funkcji Blendera modyfikującymi siatkę.
- Jakie dane eksportować - najlepiej mieć wybór które z nich w opcji eksportera, ja używam: vertex + opcjonalnie: normal, vertex color, tangent i uv. Można zrobić odpowiedni interfejs wyboru w skrypcie. Jak zrobić takie okienko wyboru? Wpisujemy np. takie coś na początek naszej głównej funkcji:
# definiujemy zmienne - 1-zaznaczone, 0-nie zaznaczone EXPORT_NORMALS=Blender.Draw.Create(1) EXPORT_COLORS=Blender.Draw.Create(0) EXPORT_UV=Blender.Draw.Create(1) EXPORT_TANGENTS=Blender.Draw.Create(0) # definiujemy krotki z opisem pup_block=[\ ('Dane wierzcholka'),('Normalne',EXPORT_NORMALS,'Eksportuje normalne'), ('Kolory',EXPORT_COLORS,'Eksportuje kolory wierzcholkow'),('UV',EXPORT_UV,"Eksportuje koordynaty tekstur"),('Tangenty',EXPORT_TANGENTS,'Eksportuje tangenty (styczne) wierzcholka')] # wyswietlamy i... if not Blender.Draw.PupBlock('Moj eksporter 1.0',pup_block): return # ...mamy zapisane wartosci: if EXPORT_NORMALS.val: # eksportuje normalne if EXPORT_UV.val: # eksportuje koordynaty tekstur # itd.
- Format tekstowy vs format binarny - zdecydowanie format binarny, jeśli zależy nam na szybkości ładowania modelu i łatwości odczytu, tekstowy jeśli chcemy mieć możliwość edytowania, czy debugowania poprawności danych.
- Trzeba zwrócić uwagę na układ współrzędnych Blendera. Blender używa układu współrzędnych 'right-handed'. W zależności od potrzeb należny odpowiednio przetransformować model funkcja mesh.transform(matrix) podając macierz przekształceń. Dodatkowo jeśli chcemy zastosować przekształcenia modelu jakie były wykonane przy edycji modelu (skala, rotacja, transformacja) należy do funkcji transform podać macierz object.getMatrix(). Tu trzeba uważać, bo modyfikujemy obiekt mesh. żeby nie 'zniszczyć' sobie modelu w projekcie, trzeba skopiować: albo mesh-e, albo cala scenę np. tak:
# poczatek eksportu - kopiujemy scene old_scene=Blender.Scene.GetCurrent() scene=old_scene.copy(2) # czytamy dane ze sceny 'scene'/modyfikujemy dane wg. potrzeb # ... # usuwamy kopie sceny old_scene.makeCurrent() Blender.Scene.Unlink(scene) # koniec eksportu
- Siatka może być złożona z trójkątów lub czworokątów, jeśli chcemy eksportować tylko trójkąty możemy użyć funkcji mesh.quadToTriangle(0) lub ręcznie dzielić czworokąty na trójkąty. Należy również pamiętać o stworzeniu kopii mesha przy tej pierwszej opcji(chyba ze nie zależy nam jakich wielokątów używamy).
- Przy eksportowaniu normalnych i koordynatów tekstur trzeba zwrócić uwagę czy dla jednego wierzchołka nie przypada więcej niż jedna normalna, czy współrzędną tekstury. Jeśli interesują nas tylko normalne 'gładkie', a nie 'per-face' mamy pewność ze dla jednego wierzchołka jest odpowiedni mu jeden wektor normalny. Przy koordynatach tekstur wierzchołki na szwach (seams) będą musiały być zdublowane. Najłatwiej to zrobić za pomocą 'pythonowej' mapy/słownika.
- Należy zwalniać całą za-alokowaną pamięć, zwłaszcza (głownie) tablice, mapy czy słowniki (których w eksporterze geometrii jest dużo), a także dane obiekty blendera (object, mesh, scene,...). Z moich obserwacji wynika ze Blender nie zwalnia pamięci (w tym przypadku) po wyeksportowaniu modelu i po kilku 'eksportach' większych modeli zaczyna brakować pamięci... I tu zaczyna się problem, bo nie da się tak łatwo zwolnic pamięci w blenderze. Na przykład jeśli kopiujemy mesh-a, czy scenę i je zwalniamy to pamięć nie będzie oddana systemowi, aż do momentu gdy blender tego zechce. Nie znam dobrego rozwiązania tego problemu. W najlepszym przypadku przybywa 30-40MB (240000 wierzchołków w 180 siatkach) po każdym eksporcie. dopiero po przeładowaniu całego projektu pamięć się zwalnia...
to mniej - więcej tyle. resztę informacji można znaleźć w dokumentacji Blendera, czy w źródłach innych eksporterów dołączonych do programu.
//~
Tagi: Programowanie Engine Blender Python
Komentarze:
Jak eksportować wartości typu 'float' w formacie binarnym?
do zapisu binarnego w pythonie używam struct.pack np. cos w tym rodzaju dla zapisu 3 floatow:
plik.write(struct.pack("<fff",float1,float2,float3))
http://docs.python.org/library/struct.html