带动画的骨骼动画怎么做.x用MeshConvert转sdkmesh用不了?

  本文由zhangbaochong原创,转载请注明出处:http://www.cnblogs.com/zhangbaochong/p/5788482.html  现在directx已经不再支持.x文件了,意味着D3DXLoadMeshFromX加载mesh的方法已经不能用了。要加载mesh除了自己解析文件外,最简单的方法是利用微软开源的工具DirectXTK中的Model类或者DXUT中的CDXUTSDKMesh类。这里以DirectXTK为例,看看如何加载的吧!1.格式转化  DirectXTK中的Model类支持.sdkmesh和.cmo格式,所以下载的.obj、.fbx等格式的文件必须转化成支持的格式才行。利用vs2015中的content pipeline可以很方便的转化成.cmo,下面是具体步骤:  首先,右键项目->生成依赖项->生成自定义->勾上MeshContentTask->点击ok    添加模型文件到项目工程中,这里以.fbx文件为例,右键模型文件,在常规中选择Mesh Content Pipeline,然后确定。    最后,右键模型选择编译,然后就可以在Debug目录下(如果没改生成目录)找到.cmo以及贴图等相关文件了,是不是很简单呢?2.加载Mesh  首先要去下载DirectXTK,然后在工程中添加引用。  用DirectXTK加载mesh其实很简单,主要就是两个步骤:加载和绘制。  加载需要调用Model类的一个方法,针对sdkmesh是CreateFromSDKMESH方法,针对cmo就是CreateFromCMO了。这里以sdkmesh格式为例,cmo与此类似不再说明了。  CreateFromSDKMESH函数参数如下:std::unique_ptr<Model> DirectX::Model::CreateFromSDKMESH( ID3D11Device* d3dDevice,
const wchar_t* szFileName,
IEffectFactory& fxFactory,
bool ccw,
bool pmalpha )  第一个参数是一个设备指针,第二个参数是模型路径,第三个参数是一个IEffectFactory,后面两个参数设为true。  绘制时需要调用Model::Draw方法,参数如下:1 Model::Draw(
2 ID3D11DeviceContext* deviceContext,
3 CommonStates& states,
4 FXMMATRIX world,
5
CXMMATRIX view,
6 CXMMATRIX projection,
7
bool wireframe,
8 std::function<void()> setCustomState )  第一个参数是设备上下文指针,第二个参数是CommonStates对象,接下来三个参数是world view proj矩阵,下个参数是是否采用线框模式绘制默认为false,最后一个参数默认为nullptr。  下面是全部代码,其中使用了上个教程实现的Camera:MeshDemo.h 1 #pragma once
2 #include <memory>
3 #include "Dx11Base.h"
4 #include "CommonStates.h"
5 #include "Model.h"
6 #include "Effects.h"
7 #include "Camera.h"
8
9 class MeshDemo : public Dx11Base
10 {
11 public:
12
MeshDemo(HINSTANCE hInst, std::wstring title = L"BlendDemo", int width = 800, int height = 640);
13
~MeshDemo();
14
15
bool Init() override;
16
void Update(float dt);
17
void Render();
18
19
bool OnResize() override;
20
21
void OnMouseDown(WPARAM btnState, int x, int y);
22
void OnMouseUp(WPARAM btnState, int x, int y);
23
void OnMouseMove(WPARAM btnState, int x, int y);
24
25 private:
26
bool BuildModels();
//创建mesh对象
27 private:
28
std::unique_ptr<Model>
m_model;
29
std::unique_ptr<EffectFactory>
m_fxFactory;
30
std::unique_ptr<CommonStates>
m_states;
31
32
Camera
m_camera;
33
34
XMFLOAT4X4
m_world;
35
XMFLOAT4X4
m_view;
36
XMFLOAT4X4
m_proj;
37
38
//鼠标控制参数
39
POINT
m_lastMousePos;
40 };MeshDemo.cpp
1 #include "MeshDemo.h"
2 #include "Utility.h"
3 using namespace DirectX;
4
5 MeshDemo::MeshDemo(HINSTANCE hInst, std::wstring title, int width, int height)
6
:Dx11Base(hInst,title,width,height)
7 {
8
XMVECTOR Eye = XMVectorSet(0.0f, 3.0f, -10.0f, 0.0f);
9
XMVECTOR At = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f);
10
XMVECTOR Up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
11
m_camera.LookAtXM(Eye, At, Up);
12
//设置投影矩阵
13
m_camera.SetLens(XM_PIDIV4, AspectRatio(), 0.1f, 1000.f);
14
15
XMStoreFloat4x4(&m_world, XMMatrixIdentity());
16 }
17
18 MeshDemo::~MeshDemo()
19 {
20 }
21
22
23 bool MeshDemo::Init()
24 {
25
if (!Dx11Base::Init())
26
return false;
27
if (!BuildModels())
28
return false;
29
return true;
30 }
31
32 void MeshDemo::Update(float dt)
33 {
34
//前后左右行走
35
if (KeyDown('A'))
36
{
37
m_camera.Strafe(-6.f*dt);
38
}
39
else if (KeyDown('D'))
40
{
41
m_camera.Strafe(6.f*dt);
42
}
43
if (KeyDown('W'))
44
{
45
m_camera.Walk(6.f*dt);
46
}
47
else if (KeyDown('S'))
48
{
49
m_camera.Walk(-6.f*dt);
50
}
51
m_camera.UpdateViewMatrix();
52
53
XMStoreFloat4x4(&m_view, m_camera.GetView());
54
XMStoreFloat4x4(&m_proj, m_camera.GetProj());
55 }
56
57 void MeshDemo::Render()
58 {
59
m_pImmediateContext->ClearRenderTargetView(m_pRenderTargetView, Colors::Silver);
60
m_pImmediateContext->ClearDepthStencilView(m_pDepthStencilView, D3D11_CLEAR_DEPTH
D3D11_CLEAR_STENCIL, 1.0f, 0);
61
62
XMVECTOR qid = XMQuaternionIdentity();
63
const XMVECTORF32 scale = { 0.01f, 0.01f, 0.01f };
64
const XMVECTORF32 translate = { 0.f, 0.f, 0.f };
65
XMMATRIX world = XMLoadFloat4x4(&m_world);
66
XMVECTOR rotate = XMQuaternionRotationRollPitchYaw(0, XM_PI / 2.f, XM_PI / 2.f);
67
rotate = XMQuaternionRotationRollPitchYaw(0, XM_PI / 2.f, XM_PI / 2.f);
68
XMMATRIX local = XMMatrixMultiply(world, XMMatrixTransformation(
69
g_XMZero, qid, scale, g_XMZero, rotate, translate));
70
local *= XMMatrixRotationZ(XM_PIDIV2);
71
m_model->Draw(m_pImmediateContext, *m_states, local, XMLoadFloat4x4(&m_view),
72
XMLoadFloat4x4(&m_proj));
73
74
m_pSwapChain->Present(0, 0);
75 }
76
77 bool MeshDemo::OnResize()
78 {
79
if (!Dx11Base::OnResize())
80
return false;
81
//更新camera参数
82
m_camera.SetLens(XM_PIDIV4, AspectRatio(), 1.f, 1000.f);
83
84
return true;
85 }
86
87 void MeshDemo::OnMouseDown(WPARAM btnState, int x, int y)
88 {
89
m_lastMousePos.x = x;
90
m_lastMousePos.y = y;
91
SetCapture(m_hWnd);
92 }
93
94 void MeshDemo::OnMouseUp(WPARAM btnState, int x, int y)
95 {
96
ReleaseCapture();
97 }
98
99 void MeshDemo::OnMouseMove(WPARAM btnState, int x, int y)
100 {
101
if ((btnState & MK_LBUTTON) != 0)
102
{
103
float dx = XMConvertToRadians(0.25f*(x - m_lastMousePos.x));
104
float dy = XMConvertToRadians(0.25f*(y - m_lastMousePos.y));
105
106
m_camera.Pitch(dy);
107
m_camera.RotateY(dx);
108
}
109
110
m_lastMousePos.x = x;
111
m_lastMousePos.y = y;
112 }
113
114 bool MeshDemo::BuildModels()
115 {
116
m_fxFactory.reset(new EffectFactory(m_pd3dDevice));
117
m_states.reset(new CommonStates(m_pd3dDevice));
118
m_model = Model::CreateFromSDKMESH(m_pd3dDevice, L"tiny.sdkmesh", *m_fxFactory,true,true);
119
return true;
120 }
121
122 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdLine, int cmdShow)
123 {
124
std::shared_ptr<Dx11Base> bd(new MeshDemo(hInstance));
125
if (!bd->Init())
126
return -1;
127
return bd->Run();
128 }3.效果截图  
在上次那篇文章中实现的骨骼动画采用的是传统的计算方式。实际上就我个人而言我不太喜欢那种方式。之前我实现的是另外一种,由于从3DSMAX中要得到相应的数据比较麻烦所以暂时放弃了而改用传统的方法。在这里我想把它记录下来。关于那种方法,其动画数据只需要旋转就足够了,舍弃了平移和缩放,实际上对大多数情况而言旋转已经足够了。传统的方法只将骨头看做是矩阵,但是这种做法会使得有些功能变的难以实现,比如IK动画。这里我们就是要将骨头看做实际的骨头——他具有长度,延伸方向。在导出的时候我们可以根据骨头节点的位置及其层级关系算出长度以及延伸,有了这些后,只需要旋转就能算出偏移量等等,简单的讲就是让骨骼自己去计算平移,而不是从动画数据中提供。这样动画数据只剩下旋转了,除了能减小动画文件的体积外,很多之前难以解决的问题也变得现对简单了。不过像前面讲的那样数据来源是个大问题,3DSMAX没有这么想问题,使得取的传统方式的数据很容易,这种方法相对复杂。现在我还没取到正确的数据。

我要回帖

更多关于 骨骼动画怎么做 的文章

 

随机推荐