Download presentation
Presentation is loading. Please wait.
Published byAlex Frome Modified over 9 years ago
1
Karakter-animáció fizikai alapon Szécsi László
2
xmlParser.h upgrade NxQuat readNxQuat(XMLCSTR name); std::string readString(XMLCSTR name); double readDouble(XMLCSTR name, double defaultValue=0.0 );
3
xmlParser.cpp upgrade std::string XMLNode::readString(XMLCSTR name) { XMLCSTR wideString = getAttribute(name); if(wideString == NULL) return "Not specified in XML."; unsigned int nChars = 0; nChars = WideCharToMultiByte(CP_ACP, 0, wideString, -1, NULL, 0, false, false); char* mbString = new char[nChars]; WideCharToMultiByte(CP_ACP, 0, wideString, -1, mbString, nChars, false, false); std::string& ret = std::string(mbString); delete [] mbString; return ret; }
4
xmlParser.cpp upgrade NxQuat XMLNode::readNxQuat(XMLCSTR name) { NxQuat v; v.id(); size_t nameLength = wcslen(name); XMLSTR nameWithChannel = new XMLCHAR[nameLength+3]; wcscpy(nameWithChannel, name); wcscat(nameWithChannel, L".x"); v.x = readDouble(nameWithChannel, v.x); nameWithChannel[nameLength] = L'\0'; wcscat(nameWithChannel, L".y"); v.y = readDouble(nameWithChannel, v.y); nameWithChannel[nameLength] = L'\0'; wcscat(nameWithChannel, L".z"); v.z = readDouble(nameWithChannel, v.z); nameWithChannel[nameLength] = L'\0'; wcscat(nameWithChannel, L".w"); v.w = readDouble(nameWithChannel, v.w); nameWithChannel[nameLength] = L'\0'; delete nameWithChannel; v.normalize(); return v; }
5
Directory class CharacterModel; typedef std::map CharacterModelDirectory; class CharacterBone; typedef std::map CharacterBoneDirectory; typedef std::vector CharacterBoneList; typedef std::vector PhysicsActorList; typedef std::vector PhysicsJointList;
6
Letöltendő média fileok orc^CharacterModel.xml orc^NXU.xml orc.x www.iit.bme.hu/~szecsi/GraphGame/*.* www.iit.bme.hu/~szecsi/GraphGame/Nwww.iit.bme.hu/~szecsi/GraphGame/NXU. ZIP
7
NXU kibontani a forráskönyvtárba minden egy NXU nevű alkönyvtárban van solution explorer: add new filter "NXU" job klikk az NXU folderen: add existing item összes hozzáadás.cpp-k kiválasztása jobb klikk, properties, not using precompiled headers
8
CharacterBone letöltendő kód: www.iit.bme.hu/~szecsi/GraphGame/ AnimationFiles.zip add existing item: CharacterBone.h CharacterBone.cpp
9
CharacterModel add existing item: CharacterModel.h CharacterModel.cpp
10
EngineCore CharacterModelDirectory characterModelDirectory; void loadCharacterModels(XMLNode& xMainNode);
11
EngineCore.cpp #include "CharacterModel.h"
12
EngineCore.cpp void EngineCore::loadCharacterModels(XMLNode& xMainNode){ int iCharacterModel = 0; XMLNode characterModelNode; while( !(characterModelNode = xMainNode.getChildNode(L"CharacterModel", iCharacterModel)).isEmpty() ) { const wchar_t* name = characterModelNode|L"name"; const wchar_t* file = characterModelNode|L"file"; if(file) { XMLNode modelNode = XMLNode::openFileHelper(file); if(name && !modelNode.isEmpty()) characterModelDirectory[name] = new CharacterModel(modelNode, this); } iCharacterModel++; }
13
EngineCore::loadLevel loadPhysicsModels(xMainNode); loadCharacterModels(xMainNode);
14
EngineCore:: releaseManagedResources { CharacterModelDirectory::iterator i = characterModelDirectory.begin(); while(i != characterModelDirectory.end()) { delete i->second; i++; }
15
DualQuaternion add existing item: DualQuaternion.h DualQuaternion.cpp
16
PhysicsCharacter add existing item: PhysicsCharacter.h PhysicsCharacter.cpp
17
EngineCore void loadPhysicsCharacters(XMLNode& groupNode, NodeGroup* group);
18
EngineCore.cpp #include "PhysicsCharacter.h"
19
EngineCore::loadGroup loadPhysicsEntities(groupNode, group); loadPhysicsCharacters(groupNode, group);
20
EngineCore.cpp void EngineCore::loadPhysicsCharacters( XMLNode& groupNode, NodeGroup* group) { int iPhysicsCharacter = 0; XMLNode physicsCharacterNode; while( !(physicsCharacterNode = groupNode.getChildNode(L"PhysicsCharacter", iPhysicsCharacter)).isEmpty() ){ // ide jön a következő dia iPhysicsCharacter++; }
21
előző bele const wchar_t* shadedMeshName = physicsCharacterNode|L"shadedMesh"; ShadedMeshDirectory::iterator iShadedMesh = shadedMeshDirectory.find(shadedMeshName); const wchar_t* characterModelName = physicsCharacterNode|L"characterModel"; CharacterModelDirectory::iterator iCharacterModel = characterModelDirectory.find(characterModelName); if(iShadedMesh != shadedMeshDirectory.end() && iCharacterModel != characterModelDirectory.end()) { D3DXVECTOR3 position = physicsCharacterNode.readVector(L"position"); PhysicsCharacter* physicsCharacter = new PhysicsCharacter( iShadedMesh->second, iCharacterModel->second, nxScene, position); group->add(physicsCharacter); const wchar_t* entityName = physicsCharacterNode|L"name"; if(entityName) entityDirectory[entityName] = physicsCharacter; }
22
XML
23
EngineCore::loadMeshes if(xFileName != NULL){ HRESULT hr = E_FAIL; if(meshNode|L"skinned") hr = D3DCreateSkinnedMeshFromX( device, xFileName, &mesh); else hr = D3DXLoadMeshFromX( xFileName, D3DXMESH_MANAGED, device, NULL, &materialBuffer, NULL, (DWORD*)&nSubmeshes, &mesh);
24
SkinnedMesh Add existing item: SkinnedMesh.h SkinnedMesh.cpp EngineCore.h: #include "SkinnedMesh.h"
25
jöhet a vertex blending új file: skinning.fx engineCore.fx: #include "skinning.fx" PhysicsCharacter: csont trafók beállítása
26
PhysicsCharacter::render DualQuaternion boneTransforms[128]; for(int iBone=0; iBone<128; iBone++) { NxMat34& dePose = characterModel-> getRiggingBonePoseInverse(boneActors[iBone]); NxMat34 actorPose = physicsActorList.at( boneActors[iBone])->getGlobalPose(); NxMat34 pose = actorPose * dePose ; NxVec3 p = pose.t; NxQuat q(pose.M); boneTransforms[iBone].set( D3DXQUATERNION(q.w, q.x, q.y, q.z), D3DXVECTOR3(p.x, p.y, p.z)); } HRESULT hr = context.effect->SetValue("bones", (void*)boneTransforms, sizeof(boneTransforms)); shadedMesh->render(context); }
27
skinning.fx struct Bone { float4 orientation; float4 dualTranslation; }; Bone bones[100];
28
skinning.fx struct SkinningInput { float4 pos: POSITION; float3 normal: NORMAL; float2 tex: TEXCOORD0; float4 blendWeights: BLENDWEIGHT; float4 blendIndices: BLENDINDICES; };
29
skinning.fx struct SkinningOutput { float4 pos: POSITION; float3 normal: TEXCOORD2; float2 tex: TEXCOORD0; float4 worldPos: TEXCOORD1; float4 color: TEXCOORD3; };
30
vertex shader eleje SkinningOutput vsSkinning(SkinningInput input) { SkinningOutput output = (SkinningOutput)0; float4 blendIndices = D3DCOLORtoUBYTE4( input.blendIndices); input.blendWeights.w = 1 – dot(input.blendWeights.xyz, float3(1, 1, 1));
31
vertex shader: bone trafók float2x4 qe0 = float2x4(bones[blendIndices.x].orientation, bones[blendIndices.x].dualTranslation); float2x4 qe1 = float2x4(bones[blendIndices.y].orientation, bones[blendIndices.y].dualTranslation); float2x4 qe2 = float2x4(bones[blendIndices.z].orientation, bones[blendIndices.z].dualTranslation); float2x4 qe3 = float2x4(bones[blendIndices.w].orientation, bones[blendIndices.w].dualTranslation);
32
vertex shader: podality float3 podality = float3( dot(qe0[0], qe1[0]), dot(qe0[0], qe2[0]), dot(qe0[0], qe3[0])); input.blendWeights.yzw *= (podality >= 0)?1:-1;
33
vertex shader: trafó keverés float2x4 qe = input.blendWeights.x * qe0; qe += input.blendWeights.y * qe1; qe += input.blendWeights.z * qe2; qe += input.blendWeights.w * qe3; float len = length(qe[0]); qe /= len;
34
vertex shader: trafó végrehajtás float3 blendedPos = input.pos.xyz + 2 * cross(qe[0].yzw, cross(qe[0].yzw, input.pos.xyz) + qe[0].x * input.pos.xyz); float3 trans = 2.0*(qe[0].x*qe[1].yzw - qe[1].x*qe[0].yzw + cross(qe[0].yzw, qe[1].yzw)); blendedPos += trans;
35
vertex shader vége output.pos = mul(float4(blendedPos, 1), modelViewProjMatrix); output.normal = input.normal.xyz + 2.0*cross(qe[0].yzw, cross(qe[0].yzw, input.normal.xyz) + qe[0].x*input.normal.xyz); output.tex = input.tex; output.color = blendIndices * 0.01; return output; }
36
pixel shader float4 psSkinning(SkinningOutput input) : COLOR0 { return abs(input.normal.y); }
37
technique technique skinning { pass ExamplePass { VertexShader = compile vs_3_0 vsSkinning(); PixelShader = compile ps_3_0 psSkinning(); }
38
próba ragdoll ork, gerincénél felfüggesztve orc^NXU.xml: … false próba: összeeső ragdoll ork
39
animáció orc^CharacterAnimation.xml
40
CharacterModel class CharacterAnimation; class CharacterModel{ CharacterAnimation* characterAnimation; public: unsigned int getBoneCount(); const std::wstring& getBoneNameByBoneIndex(unsigned int iBone); CharacterAnimation* getCharacterAnimation();
41
CharacterModel.cpp const std::wstring& CharacterModel:: getBoneNameByBoneIndex( unsigned int iBone) { return characterBoneList.at(iBone) ->getName(); }
42
CharacterModel.cpp unsigned int CharacterModel:: getParentIndexByBoneIndex(unsigned int boneIndex) { if(boneIndex >= characterBoneList.size()) return 0; return getBoneIndexByBoneName( characterBoneList.at(boneIndex) ->getParent()->getName()); }
43
CharacterModel.cpp CharacterAnimation* CharacterModel::getCharacterAnimation() { return characterAnimation; } unsigned int CharacterModel::getBoneCount() { return characterBoneList.size(); }
44
CharacterAnimation add existing item: CharacterAnimation.h CharacterAnimation.cpp
45
Átszervezés Rigging-pose-os dolgokat rakjuk át az animation-be (már benne van csak a CharacterModel- ből szedjük ki)
46
törlés a CharacterModel-ből bool initialized; std::vector riggingBonePoseInverses; void setInitialized(); bool isInitialized(); NxMat34& getRiggingBonePoseInverse(unsigned int iBone); void addRiggingBonePoseInverse(NxMat34& dePose);
47
CharacterModel::CharacterModel Animáció betöltése #include "CharacterAnimation.h" CharacterModel::CharacterModel(XMLNode& modelNode){ actorsAndJointsCollection = NULL; loadSerializedScene(modelNode); const wchar_t* animFile = modelNode|L"characterAnimation"; if(animFile){ XMLNode& animNode = XMLNode::openFileHelper(animFile, L"CharacterAnimation"); characterAnimation = new CharacterAnimation(animNode, this); } else characterAnimation = NULL; }
48
CharacterAnimation (már megvan) unsigned char boneActors[128]; unsigned char jointBones[128];
49
Directory.h class Clip; typedef std::map< const std::wstring, Clip*, CompareStringsW>ClipDirectory;
50
Clip, Key add existing item Clip.h, Clip.cpp, Key.h, Key.cpp Animation: Clip gyűjtemény Clip: Key gyűjtemény Key: bone orientációk gyűjteménye
51
Clip void getKeyTimes(unsigned int iKey, double& keyTime, double& nextKeyTime); void getNextKey(unsigned int& iKey, double& keyTime, double& nextKeyTime); NxQuat slerpBoneOrientation(unsigned int iKey, unsigned int iBone, double a);
52
Key NxQuat getBoneOrientation(unsigned int iJoint);
53
AnimationState add existing: CharacterAnimationState.h CharacterAnimationPlayer.h CharacterAnimationPlayer.cpp
54
CharacterAnimationState virtual void advance(double dt)=0; virtual NxQuat getJointOrientation(unsigned int iJoint)=0;
55
CharacterAnimationPlayer iterátor-szerűség egy animáció felett hol tartunk épp most egy bone orientációját lekérhetjük
56
CharacterAnimationPlayer class CharacterAnimationPlayer : public CharacterAnimationState { ClipDirectory::iterator currentClip; unsigned int iKey; double keyTime; double nextKeyTime; double time;
57
PhysicsCharacter na ezt most nagyon át kell írni (vagy kivenni az új verziót a zip fileból)
58
ez nem kell (Animation-ben van): unsigned char boneActors[128];
59
CharacterModel* characterModel; helyett CharacterAnimation* characterAnimation; CharacterAnimationState* characterAnimationState;
60
ActorBinder módosítás friend class ActorBinder; class ActorBinder : public NXU_userNotify { PhysicsCharacter* owner; CharacterModel* characterModel; public: void NXU_notifyActor (NxActor *actor, const char *userProperties); void NXU_notifyJoint (NxJoint *joint, const char *userProperties); ActorBinder(PhysicsCharacter* owner, CharacterModel* characterModel); };
61
PhysicsCharacter::PhysicsCharacter törölni: this->characterModel = characterModel; for(int y=0; y<128; y++) boneActors[y] = 0xff; berakni: characterAnimation = characterModel ->getCharacterAnimation();
62
characterModel->instantiate(nxScene, &pose, ActorBinder(this, characterModel)); PhysicsCharacter::ActorBinder:: ActorBinder(PhysicsCharacter* owner, CharacterModel* characterModel) { this->owner = owner; this->characterModel = characterModel; }
63
Jointok betöltése PhysicsCharacter-ben tároljuk PhysicsJointList physicsJointList;
64
NXU_notifyActor eleje void PhysicsCharacter::ActorBinder:: NXU_notifyActor (NxActor *actor, const char *userProperties) { if(actor->isDynamic() && !actor-> readBodyFlag(NX_BF_KINEMATIC)) { NxVec3 zero; zero.zero(); actor->setAngularVelocity(zero); actor->setLinearVelocity(zero); }
65
NXU_notifyActor vége owner->physicsActorList.push_back(actor); if(!owner->characterAnimation->isInitialized()) { NxMat34 dePose; actor->getGlobalPose().getInverse(dePose); owner->characterAnimation ->addRiggingActorPoseInverse(dePose); const char* actorName = actor->getName(); unsigned int nChars = 0; nChars = MultiByteToWideChar(CP_ACP, 0, actorName, -1, NULL, 0); wchar_t* wcString = new wchar_t[nChars]; MultiByteToWideChar(CP_ACP, 0, actorName, -1, wcString, nChars); wcString[nChars-10] = L'\0'; // cut "RigidBody" postfix owner->characterAnimation->setBoneActor( characterModel->getBoneIndexByBoneName(wcString), owner->physicsActorList.size() - 1); delete wcString; }
66
NXU_notifyJoint eleje void PhysicsCharacter::ActorBinder ::NXU_notifyJoint ( NxJoint *joint, const char *userProperties) {
67
NXU_notifyJoint folyt if(!owner->characterAnimation->isInitialized()){ NxActor* actor0; NxActor* actor1; joint->getActors(&actor0, &actor1); const char* jointName = actor1->getName(); unsigned int nChars = 0; nChars = MultiByteToWideChar(CP_ACP, 0, jointName, -1, NULL, 0); wchar_t* wcString = new wchar_t[nChars]; MultiByteToWideChar(CP_ACP, 0, jointName, -1, wcString, nChars); wcString[nChars-10] = L'\0'; // cut "RigidBody" postfix unsigned int boneIndex = characterModel ->getBoneIndexByBoneName(wcString); owner->characterAnimation->setJointBone( owner->physicsJointList.size(), boneIndex); delete wcString; }
68
NXU_notifyJoint folyt NxD6Joint* j = (NxD6Joint*)joint->isD6Joint(); if(j) { NxD6JointDesc desc; j->saveToDesc(desc);
69
NXU_notifyJoint folyt if(desc.swing1Motion == NX_D6JOINT_MOTION_LIMITED || desc.swing2Motion == NX_D6JOINT_MOTION_LIMITED || desc.twistMotion == NX_D6JOINT_MOTION_LIMITED|| desc.swing1Motion == NX_D6JOINT_MOTION_FREE || desc.swing2Motion == NX_D6JOINT_MOTION_FREE || desc.twistMotion == NX_D6JOINT_MOTION_FREE) { desc.swing1Motion = NX_D6JOINT_MOTION_FREE; desc.swing2Motion = NX_D6JOINT_MOTION_FREE; desc.twistMotion = NX_D6JOINT_MOTION_FREE;
70
NXU_notifyJoint folyt desc.swingDrive.driveType = NX_D6JOINT_DRIVE_POSITION; desc.twistDrive.driveType = NX_D6JOINT_DRIVE_POSITION; desc.swingDrive.spring = 10000.0; desc.swingDrive.forceLimit = FLT_MAX; desc.swingDrive.damping = 10.0f; desc.twistDrive.spring = 10000.0; desc.twistDrive.forceLimit = FLT_MAX; desc.twistDrive.damping = 10.0f;
71
NXU_notifyJoint vége } j->loadFromDesc(desc); } owner-> physicsJointList.push_back(joint); }
72
PhysicsCharacter::PhysicsCharacter törölni: for(int y=0; y<127; y++){ int referred = y; while(boneActors[referred] == 0xff) referred = characterModel- >getParentIndexByBoneIndex(referred); boneActors[y] = boneActors[referred]; } berakni: characterAnimation ->setInitialized(characterModel); characterAnimationState = new CharacterAnimationPlayer( characterAnimation);
73
~PhysicsCharacter PhysicsCharacter::~PhysicsCharacter() { delete characterAnimationState; }
74
render for(int iBone=0; iBone<128; iBone++){ unsigned int iActor; NxMat34& dePose = characterAnimation ->getRiggingActorPoseInverse( iBone, iActor); NxMat34 actorPose = physicsActorList.at(iActor) ->getGlobalPose(); NxMat34 pose = actorPose * dePose ;
75
PhysicsCharacter::animate void PhysicsCharacter::animate(double dt){ characterAnimationState->advance(dt); PhysicsJointList::iterator pi = physicsJointList.begin(); unsigned int iJoint=0; while(pi != physicsJointList.end()) { NxQuat xq; NxD6Joint* j = (*pi)->isD6Joint(); if(j){ xq = characterAnimationState ->getJointOrientation(iJoint); j->setDriveOrientation( xq ); } pi++; iJoint++; }
76
Próba valami furcsa gond: a fizikai modell nem pont ugyanott van, mint a vertexek!
77
Hibakeresés PhysicsCharacter::render-be NxMat34 pose = /* actorPose * */ dePose; NxVec3 p = pose.t; NxQuat q(pose.M);
78
Hibakeresés skinning.fx-be VS: input.blendWeights = float4(1, 0, 0, 0); // merev skinning output.color = length(blendedPos) / 4.0; PS: return input.color;
79
Próba eredmény: kis helyre becsomagolva minden és az origó nem a közepén van!
80
Gyorsjavítás vsSkinning(SkinningInput input) { input.pos.z -= 2; és csináljunk vissza mindent: - actorPose * dePose; - vertex blending - pixel shader színezés
Similar presentations
© 2024 SlidePlayer.com Inc.
All rights reserved.