140 likes | 241 Views
1. Charakteranimation 2. PlugIns schreiben und laden. Universität zu Köln Institut für Historisch-Kulturwissenschaftliche Informationsverarbeitung WS 2010/2011 Prof. Dr. Manfred Thaller AM 3 Übung: Softwaretechnologie II Teil 1: Simulation und 3D-Programmierung Referent: Martin Kolodziej.
E N D
1. Charakteranimation2. PlugInsschreiben und laden Universität zu Köln Institut für Historisch-Kulturwissenschaftliche Informationsverarbeitung WS 2010/2011 Prof. Dr. Manfred Thaller AM 3 Übung: Softwaretechnologie II Teil 1: Simulation und 3D-Programmierung Referent: Martin Kolodziej
Charakteranimation - Grundprinzip • das eigentlich Modell wird als Skin (Haut) betrachtet • unter der Haut befinden sich Bones (Knochen), die hierarchisch angeordnet sind und ein Skelett bilden (Knochen der Hände sind denen im Arm untergeordnet) • eigentliche Animation besteht aus Key-Frames • Bewegung eines Bones wird in Form einer Matrix beschrieben • Berechnung für jeden Vertex, wie stark dieser vom Bone beeinflusst wird (Bone-Weight, Faktor liegt zwischen [0; 1], 1 = 100%) • je näher ein Vertex an einem Bone liegt, desto stärker wird er von diesem beeinflusst • um Rechenkapazitäten zu sparen, werden nur die Bones berechnet, die den Vertex am meisten beeinflussen und speichert deren Index mit
Charakteranimation - Transformation des Vertex: • Jeder Vertex wird mit der Matrix des Bones transformiert, die ihn beeinflussen • die Matrizen der Bones mit einem höheren Bone-Weight-Faktor haben einen stärkeren Einfluss auf den Vertex, daher wird jede Matrix mit dem Faktor multipliziert • somit wird nur eine Transformation benötigt: die Summe der einzelnen Matrizen, multipliziert mit ihrem Faktor, ergibt eine Matrix, die alle in sich vereint
// Struktur für einen Vertex struct SVertex { tbVector3 vPosition; // Position tbVector3 vNormal; // Normalenvektor // Weitere Angaben ... // In diesem Beispiel soll jeder Vertex von maximal vier Bones beeinflusst werden. // Wir speichern also vier Bone-Weights und die Indizes der vier Bones, auf die sie // sich beziehen. float afBoneWeight[4]; int aiBoneIndex[4]; }; // Funktion zum Transformieren eines Vertex zu einem bestimmten Zeitpunkt (Animation!) SVertex TransformVertex(const SVertex& Vertex, const float fTime) { tbMatrix amBoneMatrix[4]; // Die folgende Funktion soll die Matrix eines Bones zu einem gewissen Zeitpunkt in // der Animation liefern. Dabei müssen auch hierarchische Beziehungen im Skelett // beachtet werden. for(int i = 0; i < 4; i++) { // Fertige Matrix dieses Bones abfragen amBoneMatrix[i] = GetBoneMatrix(Vertex.aiBoneIndex[i], fTime); } // Nun haben wir die Matrizen der vier Bones, die den Vertex beeinflussen. // Jede Matrix wird mit dem dazugehörigen Bone-Weight-Faktor multipliziert. // Danach addieren wir alle Matrizen. tbMatrix mTranformation = amBoneMatrix[0] * Vertex.afBoneWeight[0] + amBoneMatrix[1] * Vertex.afBoneWeight[1] + amBoneMatrix[2] * Vertex.afBoneWeight[2] + amBoneMatrix[3] * Vertex.afBoneWeight[3]; // Vertex transformieren SVertex Result = Vertex; Result.vPosition = tbVector3TransformCoords(Vertex.vPosition, mTransformation); Result.vNormal = tbVector3TransformNormal(Vertex.vNormal, mTransformation); return Result; }
Charakteranimation - Skinning mit D3DX: • Geometry-Blending • Indexed Vertex Blending
PlugIns schreiben und laden DLL-Dateien -> dynamische Bibliotheken Problem: • Ein Programm, das durch PlugIns erweitert werden soll, weiß natürlich zur Kompilierzeit nichts von diesen PlugIns. Darum benötigen wir eine Methode, wie wir DLL-Dateien zur Laufzeit explizit laden können.
DLL-Dateien explizit laden // DLL-Datei von Direct3D 9 laden HMODULE hDLL = LoadLibrary("D3D9.dll"); if(!hDLL) { // Fehler! // Wahrscheinlich ist DirectX 9 nicht installiert ... // ... } // ... // DLL-Datei wieder freigeben FreeLibrary(hDLL);
Adresse einer Funktion abfragen // DLL-Datei "WinMM.dll" laden HMODULE hDLL = LoadLibrary("WinMM.dll"); if(!hDLL) { // Fehler! ... } // Die Funktion "sndPlaySoundA" aus der DLL-Datei laden BOOL (__stdcall* pFunc)(LPCSTR, UINT); pFunc = (BOOL (__stdcall*)(LPCSTR, UINT))(GetProcAddress(hDLL, "sndPlaySoundA")); if(!pFunc) { // Fehler! ... } // Jetzt rufen wir die geladene Funktion auf. pFunc("C:\\Windows\\Media\\Ding.wav", SND_SYNC); // DLL-Datei wieder freigeben FreeLibrary(hDLL);
DLL-Dateien erzeugen // DLL-Hauptfunktion BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReasonForCall, LPVOID pvReserved) { switch(dwReasonForCall) { case DLL_PROCESS_ATTACH: // Die DLL-Datei wird geladen und einem Prozess zugewiesen. break; case DLL_PROCESS_DETACH: // Die DLL-Datei wird entladen. break; } return TRUE; }
Funktionen und Klassen extern "C" { // Erste Version ohne Parameter __declspec(dllexport) void Test() { MessageBox(NULL, "Hallo! Ich bin Test ohne Parameter!", "Hallo", MB_OK); } // Zweite Version mit einem int-Parameter __declspec(dllexport) void Test(int i) { MessageBox(NULL, "Hallo! Ich bin aber auch Test, mit Parameter!", "Hallo", MB_OK); } }
Zugriff auf Variablen int g_iTest = 19850903; extern "C" { // Funktion zum Liefern eines Zeigers auf die Variable g_iTest __declspec(dllexport) int* GetTest() { return &g_iTest; } }
Kommunikation zwischen Anwendung und PlugIn • Beim Start des Programms wird der PlugIns-Ordner durchsucht mit FindFirstFile() und FindNextFile() • Jede DLL wird mit LoadLibrary() geladenHMODULE-Werte werden in einer globalen Tabelle gespeichert, sofern keine Fehler auftreten • Jedes Plugin muss mehrere Funktionen mit festem Namen definieren: • Init für die Initialisierung • Exit für das Herunterfahren • GetInfo, um Informationen wie Name, Autor und Version abzufragen • Setup, um dem PlugIn wichtige Variablen des Programms mitzuteilen, wie zum Beispiel den Handle des Fensters und Zeiger auf wichtige Funktionen des Programms • Wenn das PlugIn beispielsweise einen neuen Menüeintrag erzeugt hat, muss das Programm einen Klick darauf an das PlugIn weiterleiten. • Am Ende werden alle DLLs entladen, nachdem Exit aufgerufen wurde.