Presentation is loading. Please wait.

Presentation is loading. Please wait.

Karakter-animáció fizikai alapon Szécsi László. xmlParser.h upgrade NxQuat readNxQuat(XMLCSTR name); std::string readString(XMLCSTR name); double readDouble(XMLCSTR.

Similar presentations


Presentation on theme: "Karakter-animáció fizikai alapon Szécsi László. xmlParser.h upgrade NxQuat readNxQuat(XMLCSTR name); std::string readString(XMLCSTR name); double readDouble(XMLCSTR."— Presentation transcript:

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


Download ppt "Karakter-animáció fizikai alapon Szécsi László. xmlParser.h upgrade NxQuat readNxQuat(XMLCSTR name); std::string readString(XMLCSTR name); double readDouble(XMLCSTR."

Similar presentations


Ads by Google