在上一节D3D11教程四十二上之SkeletalAnimation(骨骼动画)的原理 我大致阐述了骨骼动画的原理。
这一节开始介绍3D动画文件:M3D。我们这一节是读取M3D文件的数据然后进行动画的渲染。其实M3D的读取方式和读取OBJ差不多
详细参考教程:D3D11教程四十之加载OBJ模型
一,M3D格式介绍
在介绍M3D格式前,先看一看我们这次加载的模型Soldier.m3d,如下图所示:
下面用VS2015打开M3D格式
选取M3D中每一部分内容进说明:
(1)m3d-File-Header(头文件)
#Materials 5
#Vertices 13748
#Triangles 22507
#Bones 58
#AnimationClips 1
上面Materials说明了本人物的材质存在5种,顶点有13748个,三角形片元有22507个,骨骼数量为58个,动画片段为1
(2)Materials(材质)
Ambient: 1 1 1
Diffuse: 1 1 1
Specular: 0.5 0.5 0.5
SpecPower: 1.245731
Reflectivity: 0 0 0
AlphaClip: 0
Effect: Basic
DiffuseMap: head_diff.dds
NormalMap: head_norm.dds
Ambient: 1 1 1
Diffuse: 1 1 1
Specular: 0.5 0.5 0.5
SpecPower: 1.245731
Reflectivity: 0 0 0
AlphaClip: 0
Effect: Basic
DiffuseMap: jacket_diff.dds
NormalMap: jacket_norm.dds
Ambient: 0.8 0.8 0.8
Diffuse: 0.8 0.8 0.8
Specular: 0.5 0.5 0.5
SpecPower: 1.245731
Reflectivity: 0 0 0
AlphaClip: 0
Effect: Basic
DiffuseMap: pants_diff.dds
NormalMap: pants_norm.dds
Ambient: 1 1 1
Diffuse: 1 1 1
Specular: 0.5 0.5 0.5
SpecPower: 1.19372
Reflectivity: 0 0 0
AlphaClip: 0
Effect: Basic
DiffuseMap: upBody_diff.dds
NormalMap: upBody_norm.dds
Ambient: 1 1 1
Diffuse: 1 1 1
Specular: 0.5 0.5 0.5
SpecPower: 65.986
Reflectivity: 0 0 0
AlphaClip: 0
Effect: Basic
DiffuseMap: upBody_diff.dds
NormalMap: upBody_norm.dds
刚好是5种材质,对应了"m3d-File-Header",其中
Ambient:对环境光的反射率
Diffuse:对漫反射光的反射率
Specular:对镜面光的反射率
SpePower:镜面指数
DiffuseMap:漫反射贴图文件名
NormalMap:法线贴图文件名
(3)Vertices(顶点,这里有13748个,仅选取部分)
Position: -0.9983482 67.88861 4.354969
Tangent: -0.257403 0.5351538 -0.8045831 1
Normal: 0.5368453 0.7715151 0.3414111
Tex-Coords: 0.695366 0.9909569
BlendWeights: 0.7470379 0.2529621 0 0
BlendIndices: 7 9 0 0
Position: -0.8930981 67.9022 4.388191
Tangent: 0.6117722 0.7648141 -0.2019754 1
Normal: -0.4419364 0.542224 0.7146226
Tex-Coords: 0.69473 0.983095
BlendWeights: 0.7382242 0.2617758 0 0
BlendIndices: 7 9 0 0
Position: -0.8581216 67.91822 4.400497
Tangent: 0.6824488 0.4463287 -0.5788387 1
Normal: -0.3219064 0.8945094 0.3102083
Tex-Coords: 0.6975865 0.9826471
BlendWeights: 0.8141912 0.1858088 0 0
BlendIndices: 7 9 0 0
Position: 2.582659 67.64816 4.430204
Tangent: 0.6606092 -0.7491146 0.04921906 1
Normal: 0.4133166 0.4176488 0.8091593
Tex-Coords: 0.4479464 0.9792339
BlendWeights: 0.8719152 0.1280848 0 0
BlendIndices: 7 8 0 0
Position: 2.638376 67.65693 4.353904
Tangent: 0.8832982 -0.3362601 -0.3266701 1
Normal: 0.4633923 0.7318738 0.4996283
Tex-Coords: 0.4515448 0.9797229
BlendWeights: 0.8563569 0.1436431 0 0
BlendIndices: 7 8 0 0
Position: 2.630948 67.66495 4.379224
Tangent: 0.3198906 -0.2130183 -0.9231973 -1
Normal: 0.123842 0.9754387 -0.1821608
Tex-Coords: 0.4490667 0.9818488
BlendWeights: 0.8819465 0.1180535 0 0
BlendIndices: 7 8 0 0
Position: -0.3673872 64.9672 4.654578
Tangent: -0.7582458 -0.4920451 -0.4277322 1
Normal: 0.2430476 -0.822101 0.5148571
Tex-Coords: 0.4486689 0.5660419
BlendWeights: 1 0 0 0
BlendIndices: 7 0 0 0
Position: -0.3765188 64.94299 4.59083
Tangent: 0.3351268 0.08348028 -0.9384674 -1
Normal: 0.7599718 -0.6127025 0.2168837
Tex-Coords: 0.4491635 0.5671679
BlendWeights: 1 0 0 0
BlendIndices: 7 0 0 0
Position: -0.3641641 64.92722 4.624424
Tangent: -0.09240538 0.1430964 -0.9853855 -1
Normal: 0.3361744 0.9359955 0.104399
Tex-Coords: 0.4486025 0.5691844
BlendWeights: 1 0 0 0
BlendIndices: 7 0 0 0
Position: 0.3959809 65.30785 4.995087
Tangent: 0.1721453 -0.9635375 0.2048447 1
Normal: -0.07237195 -0.2197579 -0.9728663
Tex-Coords: 0.454216 0.9827818
BlendWeights: 1 0 0 0
BlendIndices: 7 0 0 0
Position: 0.5345122 65.28894 4.978922
Tangent: 0.1865638 -0.9667714 0.1747766 1
Normal: -0.08253627 -0.1926946 -0.9777815
Tex-Coords: 0.454353 0.9811453
BlendWeights: 1 0 0 0
BlendIndices: 7 0 0 0
Position: 0.6340098 65.28118 4.972228
Tangent: 0.1306942 -0.957974 0.2553524 1
Normal: -0.03623798 -0.2620054 -0.9643858
Tex-Coords: 0.4543436 0.9798943
BlendWeights: 1 0 0 0
BlendIndices: 7 0 0 0
Position: 1.057504 66.2238 5.775998
Tangent: -0.9753975 -0.07795022 0.2062124 1
Normal: -0.05241289 -0.8265812 -0.5603716
Tex-Coords: 0.5196502 0.501359
BlendWeights: 1 0 0 0
BlendIndices: 7 0 0 0
Position: 1.077244 66.21403 5.789873
Tangent: -0.9712722 -0.1858875 -0.1485805 1
Normal: 0.215188 -0.9526484 -0.2148375
Tex-Coords: 0.5200013 0.499379
BlendWeights: 1 0 0 0
BlendIndices: 7 0 0 0
Position: 0.8836966 66.28783 5.668534
Tangent: -0.5832838 -0.6901796 -0.4282896 1
Normal: 0.7249501 -0.6801605 0.1087612
Tex-Coords: 0.5196291 0.5041814
BlendWeights: 1 0 0 0
BlendIndices: 7 0 0 0
Position: 0.3673774 66.26884 5.802074
Tangent: -0.9256424 0.3324787 0.1806767 1
Normal: -0.3660435 -0.907773 -0.2048423
Tex-Coords: 0.4824339 0.499379
BlendWeights: 1 0 0 0
BlendIndices: 7 0 0 0
Tangent:顶点的切向量
Normal:顶点的法向量
TextCoord:顶点的纹理坐标
BlendIndices:四个影响顶点的骨骼的索引
BlendWeights:四个骨骼影响顶点的加权百分比
(4)Triangle(三角形片元,这里有22507个,仅选取部分)
0 1 2
3 4 5
6 7 8
9 10 11
12 13 14
15 16 17
18 19 20
19 18 21
21 22 19
23 19 22
24 19 23
19 24 25
21 18 26
26 27 21
21 27 28
28 29 21
22 21 29
29 30 22
31 22 30
22 31 23
26 18 32
32 33 26
26 33 34
35 26 34
26 35 36
36 27 26
28 27 36
32 18 37
38 39 40
41 39 38
39 41 42
42 43 39
44 39 43
38 45 41
41 45 46
46 47 41
41 47 48
48 42 41
42 48 49
49 50 42
42 50 43
51 45 38
46 45 51
51 52 46
46 52 53
53 54 46
每一行的三个数字为构成一个三角形片元的顶点数组的索引数
(5)Subtable(子集表)
SubsetID: 0 VertexStart: 0 VertexCount: 3915 FaceStart: 0 FaceCount: 7230
SubsetID: 1 VertexStart: 3915 VertexCount: 2984 FaceStart: 7230 FaceCount: 4449
SubsetID: 2 VertexStart: 6899 VertexCount: 4270 FaceStart: 11679 FaceCount: 6579
SubsetID: 3 VertexStart: 11169 VertexCount: 2305 FaceStart: 18258 FaceCount: 3807
SubsetID: 4 VertexStart: 13474 VertexCount: 274 FaceStart: 22065 FaceCount: 442
这里每一个子集代表了人格3D网格(Mesh)的一部分,这里有5部分的,也就是人物由5个3D网格的子集构成,也刚好说明了“(1)Materials”存在5种材质的事实。
VertexStart:构成这个3D网格子集的所有三角形片元的顶点在“(3)Vertices数组”开始的位置
VertxCount:构成这个3D网格子集的所有三角形片元的顶点总的数量
FaceStart:构成这个3D网格子集的所有三角形片元的开始位置
FaceCount:构成这个3D网格子集的所有三角形片元的总数量
这里用DX11进行3D网格的绘制,也就是:
deviceContext->DrawIndexed(mSubsetTable[subsetId].FaceCount * 3, mSubsetTable[subsetId].FaceStart * 3, 0);
(6)BoneOffsets(骨骼位移,用Offset矩阵表示)
BoneOffset0 1.331581E-06 1 4.16881E-11 0 -5.551115E-17 -4.16881E-11 1 0 1 -1.331581E-06 8.412415E-23 0 -2.230549 -0.03756041 -37.46099 1
BoneOffset1 4.16881E-11 2.757707E-06 1 0 1 -2.25986E-16 -4.16881E-11 0 2.220447E-16 1 -2.757707E-06 0 -37.46099 -1.274681 -0.03755855 1
BoneOffset2 1.240504E-06 -1.274266E-06 1 0 0.9954989 0.09477358 -1.114154E-06 0 -0.09477358 0.9954989 1.386098E-06 0 -40.94087 -5.174486 -0.03752297 1
BoneOffset3 1.039812E-06 -1.164522E-06 1 0 0.9807496 0.1952691 -7.924001E-07 0 -0.1952691 0.9807496 1.345148E-06 0 -44.72502 -9.758175 -0.03753753 1
BoneOffset4 1.157876E-06 -1.285339E-06 1 0 0.9952906 0.09693625 -1.027826E-06 0 -0.09693625 0.9952906 1.391526E-06 0 -49.99409 -4.814983 -0.03752576 1
BoneOffset5 0.0267457 0.06956523 0.9972188 0 0.9972219 0.06751715 -0.03145573 0 -0.06951758 0.9952898 -0.06756619 0 -54.63113 -3.202576 1.650944 1
BoneOffset6 0.05248683 0.05291385 0.9972187 0 0.9400386 -0.339614 -0.03145685 0 0.337005 0.9390752 -0.06756633 0 -56.36541 21.29063 1.651012 1
BoneOffset7 0.04131818 0.06202829 0.9972187 0 0.9878342 -0.1522952 -0.03145639 0 0.1499205 0.9863866 -0.06756623 0 -63.28969 9.280344 1.650982 1
BoneOffset8 0.9933316 0.1076336 -0.04131818 0 -0.02444861 -0.153576 -0.9878342 0 -0.1126697 0.9822573 -0.1499205 0 -0.1047576 7.877761 67.51039 1
BoneOffset9 0.9933316 0.1076336 -0.04131818 0 -0.02444861 -0.153576 -0.9878342 0 -0.1126697 0.9822573 -0.1499205 0 2.350262 8.06325 67.58595 1
BoneOffset10 0.04133678 0.1246633 0.9913375 0 0.9877884 -0.1542688 -0.02178906 0 0.1502163 0.9801326 -0.129518 0 -67.77048 6.064418 -0.005347772 1
BoneOffset11 0.03878755 0.1000283 0.9942282 0 0.9852359 -0.1698648 -0.02134681 0 0.1667491 0.9803776 -0.1051402 0 -67.76292 7.411295 2.329966 1
BoneOffset12 0.978469 -0.06958929 0.1943081 0 -0.1989971 -0.06831119 0.9776163 0 -0.0547582 -0.9952341 -0.08068843 0 10.56226 2.418257 -59.26136 1
BoneOffset13 0.6745355 -0.005724293 0.7382201 0 -0.7348453 -0.101025 0.6706683 0 0.07073959 -0.9948674 -0.0723514 0 37.96533 3.830146 -45.55817 1
BoneOffset14 0.6622269 0.1283993 0.7382202 0 -0.7001266 -0.2450024 0.6706684 0 0.2669792 -0.9609824 -0.0723514 0 23.56741 8.685397 -45.55817 1
BoneOffset15 0.5252452 -0.7902383 0.3156593 0 -0.8194563 -0.5697035 -0.06268121 0 0.2293654 -0.2257461 -0.9467999 0 21.06672 43.10165 -3.432135 1
BoneOffset16 -0.2414951 0.7488238 0.6172057 0 -0.6232057 -0.6072122 0.4928565 0 0.7438377 -0.2656237 0.6133102 0 28.13352 7.319732 -36.60744 1
BoneOffset17 -0.1351558 0.7751064 0.6172057 0 -0.7014976 -0.5147749 0.4928566 0 0.6997383 -0.3663558 0.6133102 0 27.74807 3.499911 -36.60744 1
BoneOffset18 -0.1503163 0.7723094 0.6172058 0 -0.691277 -0.5284204 0.4928565 0 0.706782 -0.3525758 0.61331 0 26.29197 4.015827 -36.60743 1
BoneOffset19 0.4761869 -0.7141994 0.5129962 0 -0.8261923 -0.5631288 -0.01708459 0 0.3010849 -0.4156981 -0.8582208 0 17.94779 41.65127 -9.076902 1
BoneOffset20 0.3412979 -0.7876234 0.5129963 0 -0.9133165 -0.4068916 -0.01708454 0 0.2221901 -0.4626971 -0.8582208 0 23.63254 38.04902 -9.076903 1
BoneOffset21 0.3412978 -0.7876234 0.5129963 0 -0.9133165 -0.4068916 -0.01708454 0 0.2221901 -0.4626971 -0.8582208 0 22.56969 38.04902 -9.076904 1
BoneOffset22 0.5703186 -0.7738118 0.2755937 0 -0.809442 -0.58652 0.02824389 0 0.1397858 -0.2391852 -0.9608591 0 15.41071 43.35088 -5.431334 1
BoneOffset23 0.4997598 -0.8211505 0.2755937 0 -0.8580722 -0.5127515 0.02824383 0 0.1181187 -0.2505945 -0.9608591 0 17.65543 41.95573 -5.431333 1
BoneOffset24 0.4441492 -0.8525136 0.2755938 0 -0.8902162 -0.4546614 0.0282439 0 0.1012236 -0.2578826 -0.9608591 0 18.87577 40.79272 -5.431336 1
BoneOffset25 0.5828857 -0.8108719 0.05225927 0 -0.8120676 -0.5791055 0.07199102 0 -0.02811177 -0.08440062 -0.9960352 0 15.44037 43.83731 -2.251421 1
BoneOffset26 0.387237 -0.920498 0.05225931 0 -0.9208199 -0.3832853 0.07199102 0 -0.04623728 -0.07599906 -0.9960352 0 23.46557 39.59944 -2.251423 1
BoneOffset27 0.387237 -0.920498 0.05225932 0 -0.9208199 -0.3832853 0.07199102 0 -0.04623728 -0.07599907 -0.9960353 0 22.07731 39.59944 -2.251423 1
BoneOffset28 0.4671389 -0.86391 -0.1882568 0 -0.865407 -0.4903808 0.102942 0 -0.1812501 0.1148305 -0.9767098 0 20.74013 41.51764 1.912001 1
BoneOffset29 0.4671389 -0.86391 -0.1882568 0 -0.865407 -0.4903808 0.102942 0 -0.1812501 0.1148305 -0.9767099 0 19.60834 41.51763 1.912001 1
BoneOffset30 0.4077609 -0.8934709 -0.1882568 0 -0.8965333 -0.4308487 0.1029419 0 -0.1730858 0.1268028 -0.97671 0 21.50901 40.15739 1.912003 1
BoneOffset31 -0.9874619 -0.06958928 0.1416905 0 -0.1369845 -0.06831115 -0.9882149 0 0.0784482 -0.9952341 0.05792203 0 7.307545 2.418255 59.81763 1
BoneOffset32 -0.7036101 -0.1347479 0.697693 0 -0.6913735 -0.09695508 -0.7159624 0 0.1641193 -0.9861251 -0.0249425 0 35.68373 3.616536 47.93541 1
BoneOffset33 -0.6628146 -0.2718477 0.697693 0 -0.65833 -0.2323772 -0.7159624 0 0.3567607 -0.9338628 -0.02494249 0 21.37372 8.022764 47.93541 1
BoneOffset34 -0.53991 0.7152952 0.4436775 0 -0.7858574 -0.6171935 0.03872896 0 0.3015375 -0.3277572 0.8953492 0 19.30329 45.59414 4.689261 1
BoneOffset35 0.2999553 -0.8143949 0.4967771 0 -0.640285 -0.5579026 -0.5279956 0 0.7071503 -0.159704 -0.6887909 0 29.02991 4.731728 38.4517 1
BoneOffset36 0.1839428 -0.8481611 0.4967772 0 -0.7115631 -0.4635711 -0.5279956 0 0.678117 -0.2563675 -0.6887909 0 28.27636 0.8124946 38.4517 1
BoneOffset37 0.2005254 -0.8443943 0.4967771 0 -0.7023438 -0.4774236 -0.5279957 0 0.6830097 -0.243032 -0.6887909 0 26.87281 1.339265 38.45171 1
BoneOffset38 -0.4821542 0.6149151 0.6240243 0 -0.7959627 -0.605054 -0.01878123 0 0.3660195 -0.5057555 0.7811791 0 16.3612 43.8517 10.95931 1
BoneOffset39 -0.3648617 0.6909916 0.6240242 0 -0.8910417 -0.4535323 -0.01878121 0 0.2700375 -0.5628842 0.7811791 0 22.46345 40.49694 10.95931 1
BoneOffset40 -0.3648617 0.6909917 0.6240242 0 -0.8910417 -0.4535323 -0.01878123 0 0.2700375 -0.5628842 0.7811792 0 21.4006 40.49695 10.95931 1
BoneOffset41 -0.5959262 0.6961851 0.4002474 0 -0.7726544 -0.632889 -0.04956242 0 0.2188075 -0.3387884 0.9150658 0 13.47992 45.78455 6.550231 1
BoneOffset42 -0.5321221 0.7460883 0.4002474 0 -0.8255228 -0.5621879 -0.04956234 0 0.1880363 -0.3567866 0.9150658 0 15.94708 44.55038 6.550227 1
BoneOffset43 -0.4814227 0.7797652 0.4002475 0 -0.8610203 -0.5061493 -0.04956235 0 0.1639379 -0.3684817 0.9150658 0 17.34343 43.49505 6.550231 1
BoneOffset44 -0.6311445 0.7541577 0.1813901 0 -0.7737727 -0.6284722 -0.07936123 0 0.05414766 -0.1904431 0.9802036 0 13.43047 46.42831 2.638246 1
BoneOffset45 -0.446935 0.8759831 0.1813902 0 -0.8945071 -0.4399529 -0.07936122 0 0.01028392 -0.197724 0.9802037 0 22.08455 42.57361 2.638246 1
BoneOffset46 -0.446935 0.8759831 0.1813901 0 -0.8945071 -0.4399529 -0.07936121 0 0.01028392 -0.197724 0.9802037 0 20.69629 42.57361 2.638245 1
BoneOffset47 -0.5406674 0.8390217 -0.06099986 0 -0.8336171 -0.5440974 -0.09507957 0 -0.1129638 -0.0005558565 0.9935988 0 19.07165 44.33694 -2.324657 1
BoneOffset48 -0.5406673 0.8390217 -0.06099987 0 -0.833617 -0.5440974 -0.09507956 0 -0.1129638 -0.0005558282 0.9935988 0 17.93986 44.33694 -2.324658 1
BoneOffset49 -0.4828016 0.8736025 -0.06099987 0 -0.8684416 -0.4865887 -0.09507956 0 -0.1127437 0.007070327 0.9935988 0 20.03463 43.08289 -2.324658 1
BoneOffset50 0.2109852 0.1779936 -0.961147 0 -0.9752536 0.1047943 -0.1946751 0 0.06607183 0.9784357 0.195699 0 35.7044 -5.801689 10.43872 1
BoneOffset51 0.1409229 0.2373545 -0.9611471 0 -0.9556655 -0.2209187 -0.194675 0 -0.2585423 0.9459692 0.195699 0 18.38493 0.2425776 10.43872 1
BoneOffset52 -0.009744409 0.2615748 -0.965134 0 -0.9980836 -0.06152766 -0.00659844 0 -0.06110845 0.9632201 0.261673 0 4.903169 -0.7457907 9.652552 1
BoneOffset53 0.2555898 -0.05648153 -0.965134 0 0.1919541 0.9813816 -0.006598534 0 0.9475376 -0.1835749 0.261673 0 -6.705683 2.104658 9.652553 1
BoneOffset54 -0.2109876 -0.1779905 -0.961147 0 -0.975253 0.1047948 0.1946776 0 0.06607245 0.9784362 -0.1956962 0 35.72023 -5.788335 -10.36661 1
BoneOffset55 -0.1409264 -0.2373523 -0.961147 0 -0.9556651 -0.220918 0.1946776 0 -0.2585419 0.9459698 -0.1956961 0 18.3955 0.2603853 -10.36661 1
BoneOffset56 0.00974141 -0.2615723 -0.9651347 0 -0.9980835 -0.06152691 0.006601164 0 -0.06110846 0.9632207 -0.2616704 0 4.902436 -0.7261673 -9.58015 1
BoneOffset57 -0.2555867 0.05648369 -0.9651347 0 0.1919549 0.9813814 0.006601127 0 0.9475382 -0.1835751 -0.2616703 0 -6.686508 2.100421 -9.58015 1
这里读取的每行为相应骨骼的OffsetMatrix(平移矩阵),对应于上节教程
D3D11教程四十二上之SkeletalAnimation(骨骼动画)的原理的平移变换.
(7)BoneHierarchy(骨骼层级关系图---数组表示的树)
ParentIndexOfBone0: -1
ParentIndexOfBone1: 0
ParentIndexOfBone2: 1
ParentIndexOfBone3: 2
ParentIndexOfBone4: 3
ParentIndexOfBone5: 4
ParentIndexOfBone6: 5
ParentIndexOfBone7: 6
ParentIndexOfBone8: 7
ParentIndexOfBone9: 7
ParentIndexOfBone10: 7
ParentIndexOfBone11: 7
ParentIndexOfBone12: 6
ParentIndexOfBone13: 12
ParentIndexOfBone14: 13
ParentIndexOfBone15: 14
ParentIndexOfBone16: 15
ParentIndexOfBone17: 16
ParentIndexOfBone18: 17
ParentIndexOfBone19: 15
ParentIndexOfBone20: 19
ParentIndexOfBone21: 20
ParentIndexOfBone22: 15
ParentIndexOfBone23: 22
ParentIndexOfBone24: 23
ParentIndexOfBone25: 15
ParentIndexOfBone26: 25
ParentIndexOfBone27: 26
ParentIndexOfBone28: 15
ParentIndexOfBone29: 28
ParentIndexOfBone30: 29
ParentIndexOfBone31: 6
ParentIndexOfBone32: 31
ParentIndexOfBone33: 32
ParentIndexOfBone34: 33
ParentIndexOfBone35: 34
ParentIndexOfBone36: 35
ParentIndexOfBone37: 36
ParentIndexOfBone38: 34
ParentIndexOfBone39: 38
ParentIndexOfBone40: 39
ParentIndexOfBone41: 34
ParentIndexOfBone42: 41
ParentIndexOfBone43: 42
ParentIndexOfBone44: 34
ParentIndexOfBone45: 44
ParentIndexOfBone46: 45
ParentIndexOfBone47: 34
ParentIndexOfBone48: 47
ParentIndexOfBone49: 48
ParentIndexOfBone50: 2
ParentIndexOfBone51: 50
ParentIndexOfBone52: 51
ParentIndexOfBone53: 52
ParentIndexOfBone54: 2
ParentIndexOfBone55: 54
ParentIndexOfBone56: 55
ParentIndexOfBone57: 56
除了根节点没有母节点之外,其它的节点都存在母节点,因此根节点的母节点在数组中的下标为-1
(8)AnimationClip
AnimationClip Take1
{
Bone0 #Keyframes: 76
{
Time: 0 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.0166666 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.0333333 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.05 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.0666666 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.0833333 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.0999999 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.1166666 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.1333333 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.15 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.1666666 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.1833333 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.1999999 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.2166666 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.2333333 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.2499999 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.2666666 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.2833333 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.3 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.3166666 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.3333333 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.35 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.3666666 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.3833333 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.3999999 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.4166666 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.4333333 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.45 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.4666666 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.4833333 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.4999999 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.5166666 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.5333333 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.55 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.5666666 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.5833333 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.6 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.6166666 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.6333333 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.65 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.6666666 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.6833333 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.7 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.7166666 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.7333333 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.75 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.7666666 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.7833333 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.8 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.8166666 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.8333333 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.85 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.8666666 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.8833333 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.9 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.9166666 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.9333333 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.95 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.9666666 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 0.9833333 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 1 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 1.0166666 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 1.0333333 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 1.05 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 1.0666666 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 1.0833333 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 1.1 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 1.1166666 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 1.1333333 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 1.15 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 1.1666666 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 1.1833333 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 1.2 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 1.2166666 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 1.2333333 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
Time: 1.25 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004
}
Bone1 #Keyframes: 76
{
Time: 0 Pos: -0.5862113 -0.06803528 -0.06857681 Scale: 1 1 1 Quat: 0.4598411 -0.5545887 0.4610625 0.5180722
Time: 0.0166666 Pos: -0.5728644 -0.276429 -0.06752014 Scale: 0.9999999 1 1 Quat: 0.4572482 -0.5526819 0.4629614 0.520705
Time: 0.0333333 Pos: -0.5844057 -0.4848228 -0.06646347 Scale: 1 1 1 Quat: 0.4552799 -0.5505438 0.4642273 0.5235596
Time: 0.05 Pos: -0.5983974 -0.6908427 -0.06014633 Scale: 0.9999999 1 1 Quat: 0.4547104 -0.5482643 0.4657928 0.5250542
Animation Take1表示这个动画片段名为“Take1”,大括号内包含了这个动画片段所有骨骼的所有动画帧下的局部变换矩阵(Pos,Scale,Quat)。拿“Bone0 #Keyframes: 76”来解释,就是骨骼Bone0在动画片段“Take1”存在76帧的变换,
"Time: 0 Pos: 0.03756343 37.46099 2.230549 Scale: 1 1 1 Quat: -0.5000003 -0.4999996 -0.4999996 0.5000004"代表了Bone0在第一帧动画中,时间点为0,
Pos为 0.03756343 37.46099 2.230549,Scale为“1 1 1”,Quat为-0.5000003 -0.4999996 -0.4999996 0.5000004
二,定义相关的类和接口
(1)SkinnedDataClass.h(用于存储M3D格式的与骨骼相关的数据)
#pragma once
#ifndef SKIN_DATA_CLASS_H
#define SKIN_DATA_CLASS_H
#include<Windows.h>
#include<xnamath.h>
#include<iostream>
#include<map>
#include<vector>
using std::map;
using std::vector;
using std::string;
//KeyFrame定义了在某个时间点某个骨头到母骨头的变换
struct KeyFrame
{
KeyFrame();
~KeyFrame();
float TimePos;
XMFLOAT3 Translation;
XMFLOAT3 Scale;
XMFLOAT4 RotationQuat;
};
//BoneAnimation定义了一系列帧数构成的某个骨头动画。在两帧之间的时间值,我们对两个最近的帧进行插值
struct BoneAnimation
{
float GetStartTime()const;
float GetEndTime()const;
void Interpolate(float t, XMFLOAT4X4& M)const;
vector<KeyFrame> keyFrames;
};
//这里动画片段的样例为"Walk","Run","Attack","Defend".
//一个动画片段由所有骨头的骨头动画组成。
struct AnimationClip
{
float GetClipStartTime()const;
float GetClipEndTime()const;
void Interpolate(float t, vector<XMFLOAT4X4>& boneTransform)const;
vector<BoneAnimation> BoneAnimations;
};
class SkinnedDataClass
{
private:
//以数组形式表示的树,a[i]=j,代表第i根骨头的母骨头下标为j
vector<int> mBoneHierarchy;
vector<XMFLOAT4X4> mBoneOffsets;
map<string, AnimationClip> mAnimations;
public:
UINT BoneCount()const;
float GetClipStartTime(const string& AnimationClipName)const;
float GetClipEndTime(const string& AnimationClipName)const;
void Set(vector<int>& bongHierarchy, vector<XMFLOAT4X4>& boneOffsets, map<string, AnimationClip>& animations);
//获取某一时间点的某一个动画片段的所有骨头的变换矩阵
void GetFinalTransforms(const string& AnimationClipName,float TimePos,vector<XMFLOAT4X4>& finalTransforms)const;
};
#include"SkinnedDataClass.h"
KeyFrame::KeyFrame():TimePos(0.0f), Translation(0.0f, 0.0f, 0.0f),Scale(1.0f,1.0f,1.0f),RotationQuat(0.0f,0.0f,0.0f,1.0f)
{
}
KeyFrame::~KeyFrame()
{
}
float BoneAnimation::GetStartTime()const
{
//第一帧的时间点为开始时间
return keyFrames.front().TimePos;
}
float BoneAnimation::GetEndTime()const
{
//最后一帧的时间点为结束时间
return keyFrames.back().TimePos;
}
//得到某个骨头在时间t的变换矩阵
void BoneAnimation::Interpolate(float t, XMFLOAT4X4& M)const
{
if (t < keyFrames.front().TimePos)
{
XMVECTOR S = XMLoadFloat3(&keyFrames.front().Scale); //缩放矩阵
XMVECTOR P = XMLoadFloat3(&keyFrames.front().Translation); //平移矩阵
XMVECTOR Q = XMLoadFloat4(&keyFrames.front().RotationQuat); //旋转四元素
XMVECTOR zero = XMVectorSet(0.0f,0.0f,0.0f,1.0f);
// XMMatrixAffineTransformation的第二个参数为旋转中心
XMStoreFloat4x4(&M, XMMatrixAffineTransformation(S, zero, Q, P));
}
else if (t >= keyFrames.back().TimePos)
{
XMVECTOR S = XMLoadFloat3(&keyFrames.back().Scale); //缩放矩阵
XMVECTOR P = XMLoadFloat3(&keyFrames.back().Translation); //平移矩阵
XMVECTOR Q = XMLoadFloat4(&keyFrames.back().RotationQuat); //旋转四元素
XMVECTOR zero = XMVectorSet(0.0f, 0.0f, 0.0f, 1.0f);
// XMMatrixAffineTransformation的第二个参数为旋转中心
XMStoreFloat4x4(&M, XMMatrixAffineTransformation(S, zero, Q, P));
}
else
{
for (UINT i = 0; i < keyFrames.size() - 1; ++i)
{
if (t > keyFrames[i].TimePos&&t < keyFrames[i + 1].TimePos)
{
float lerpPercent = (t - keyFrames[i].TimePos) / (keyFrames[i+1].TimePos - keyFrames[i].TimePos);
XMVECTOR S0 = XMLoadFloat3(&keyFrames[i].Scale);
XMVECTOR S1 = XMLoadFloat3(&keyFrames[i+1].Scale);
XMVECTOR P0 = XMLoadFloat3(&keyFrames[i].Translation);
XMVECTOR P1 = XMLoadFloat3(&keyFrames[i + 1].Translation);
XMVECTOR Q0 = XMLoadFloat4(&keyFrames[i].RotationQuat);
XMVECTOR Q1 = XMLoadFloat4(&keyFrames[i + 1].RotationQuat);
//对相邻两个帧数的动画的相应变化量进行插值
//缩放量进行插值
XMVECTOR S = XMVectorLerp(S0,S1,lerpPercent);
//移动量进行插值
XMVECTOR P = XMVectorLerp(P0, P1, lerpPercent);
//对旋转量进行插值
XMVECTOR Q = XMVectorLerp(Q0, Q1, lerpPercent);
XMVECTOR zero = XMVectorSet(0.0f, 0.0f, 0.0f, 1.0f);
XMStoreFloat4x4(&M, XMMatrixAffineTransformation(S, zero, Q, P));
}
}
}
}
float AnimationClip::GetClipStartTime()const
{
//找到在一个动画片段所有骨头的开始时间的最小值
float t = 10000000.0f;
for (UINT i = 0; i < BoneAnimations.size(); ++i)
{
t = min(t, BoneAnimations[i].GetStartTime());
}
return t;
}
float AnimationClip::GetClipEndTime()const
{
//找到在一个动画片段所有骨头的结束时间的最大值
float t =0.0f;
for (UINT i = 0; i < BoneAnimations.size(); ++i)
{
t = max(t, BoneAnimations[i].GetEndTime());
}
return t;
}
//得到所有骨头在时间t的变换矩阵数组,boneTransform[i]代表第i根骨头在时间t的变换矩阵
void AnimationClip::Interpolate(float t, vector<XMFLOAT4X4>& boneTransform)const
{
for (UINT i = 0; i < BoneAnimations.size(); ++i)
{
BoneAnimations[i].Interpolate(t, boneTransform[i]);
}
}
float SkinnedDataClass::GetClipStartTime(const string& AnimationClipName)const
{
auto AniClip= mAnimations.find(AnimationClipName);
return AniClip->second.GetClipStartTime();
}
float SkinnedDataClass::GetClipEndTime(const string&AnimationClipName)const
{
auto AniClip = mAnimations.find(AnimationClipName);
return AniClip->second.GetClipEndTime();
}
UINT SkinnedDataClass::BoneCount()const
{
return mBoneHierarchy.size();
}
void SkinnedDataClass::Set(vector<int>& boneHierarchy, vector<XMFLOAT4X4>& boneOffsets, map<string, AnimationClip>& animations)
{
mBoneHierarchy = boneHierarchy;
mBoneOffsets = boneOffsets;
mAnimations = animations;
}
//获取某一时间点的某一个动画片段的所有骨头的变换矩阵
void SkinnedDataClass::GetFinalTransforms(const string& AnimationClipName, float TimePos, vector<XMFLOAT4X4>& finalTransforms) const
{
UINT numBones = mBoneOffsets.size();
//插值得到某个动画片段在某个时间点所有骨头到母骨头的变换矩阵
vector<XMFLOAT4X4> toParentTransform(numBones);
auto AniClip = mAnimations.find(AnimationClipName);
//求出某个时间点所有骨头到相应的母骨头的变换矩阵,其实M3D各骨头存储的Scale,Translation,Quat为变换到母骨头的变换属性
AniClip->second.Interpolate(TimePos, toParentTransform);
//遍历所有层级,变换所有骨头到根节点空间
vector<XMFLOAT4X4> toRootTransforms(numBones);
//根骨头的下标为0,根骨头没有母骨头,因此它的根空间变换也就是根节点的局部空间变换
toRootTransforms[0] = toParentTransform[0];
//现在找到每根骨头到根空间的变换(自顶向下,复杂度为O(n),如果自底向上,则复杂度为O(n*n))
for (UINT i = 1; i < numBones; ++i)
{
XMMATRIX toParent = XMLoadFloat4x4(&toParentTransform[i]);
int parentIndex = mBoneHierarchy[i];
XMMATRIX parentToRoot= XMLoadFloat4x4(&toRootTransforms[parentIndex]);
XMMATRIX toRoot = XMMatrixMultiply(toParent, parentToRoot);
XMStoreFloat4x4(&toRootTransforms[i], toRoot);
}
//得到动画片段所有骨头在某个时间点的最后变换(先平移,在进行根空间变化)
for (UINT i = 0; i < numBones; ++i)
{
XMMATRIX offset = XMLoadFloat4x4(&mBoneOffsets[i]);
XMMATRIX ToRoot= XMLoadFloat4x4(&toRootTransforms[i]);
XMStoreFloat4x4(&finalTransforms[i], XMMatrixMultiply(offset,ToRoot));
}
}
(2)LoadM3DClass.h(用于加载M3D文件的骨骼,顶点,索引,材质,Subset等数据)
#pragma once
#ifndef _LOAD_M3D_CLASS_H
#define _LOAD_M3D_CLASS_H
#include"MeshGeometryClass.h"
#include"SkinnedDataClass.h"
#include"CommonVertexFormat.h"
#include<iostream>
#include<fstream>
#include<istream>
#include <sstream>
using std::string;
using std::wstring;
using std::ifstream;
using std::istringstream;
//M3d网格模型的材质属性
struct M3dMaterial
{
Material Mat;
bool AlphaClip;
string EffectTypeName;
wstring DiffuseMapName;
wstring NormalMapName;
};
//M3d网格模型的加载器
class M3dLoaderClass
{
private:
//读取材质
void ReadMaterials(ifstream& FileIn, UINT numMaterials, vector<M3dMaterial>& mats);
//读取子集表
void ReadSubsetTable(ifstream& FileIn, UINT numSubsets, vector<MeshGeometryClass::Subset>& subsets);
//读取顶点的属性集合
void ReadVertices(ifstream& FileIn, UINT numVertices, vector<PosNormalTexTanVertex>& vertices);
//读取蒙皮顶点属性
void ReadSkinnedVertices(ifstream& FileIn, UINT numVertices, vector<PosNormalTexTanSkinnedVertex>& vertices);
//读取三角形索引
void ReadTriangles(ifstream& FileIn, UINT numTriangles, vector<unsigned long>& indices);
//读取骨骼位移
void ReadBoneOffets(ifstream& FileIn, UINT numBones, vector<XMFLOAT4X4>& boneOffsets);
//读取骨骼层级(以数组形式呈现的骨骼树关系)
void ReadBoneHierarchy(ifstream& FileIn, UINT numBones, vector<int>& boneIndexToParentIndex);
//读取动画片段
void ReadAnimationClips(ifstream& FileIn, UINT numBones, UINT numAnimationClips, map<string,AnimationClip>& animations);
//读取骨头关键帧
void ReadBoneKeyFrame(ifstream& FileIn, UINT numBones,BoneAnimation& boneAnimation);
public:
bool LoadM3d(const string&FileName, vector<PosNormalTexTanVertex>& vertices, vector<unsigned long>& indices, vector<MeshGeometryClass::Subset>& subsets, vector<M3dMaterial>& mats);
bool LoadM3d(const string&FileName, vector<PosNormalTexTanSkinnedVertex>& vertices, vector<unsigned long>& indices, vector<MeshGeometryClass::Subset>& subsets, vector<M3dMaterial>& mats,SkinnedDataClass& skinInfo);
};
#endif // !_LOAD_M3D_CLASS_H
#include"LoadM3DClass.h"
//仅仅是读取相应的网格数据,并未有骨骼动画
bool M3dLoaderClass::LoadM3d(const string&FileName, vector<PosNormalTexTanVertex>& vertices, vector<unsigned long>& indices, vector<MeshGeometryClass::Subset>& subsets, vector<M3dMaterial>& mats)
{
//打开M3d.文件格式
ifstream fin(FileName);
UINT numMaterials = 0;
UINT numVertices = 0;
UINT numTriangles = 0;
UINT numBones = 0;
UINT numAnimationsClips = 0;
string ignore;
if (fin)
{
fin >> ignore;//跳过一行
fin >> ignore >> numMaterials;
fin >> ignore >> numVertices;
fin >> ignore >> numTriangles;
fin >> ignore >> numBones;
fin >> ignore >> numAnimationsClips;
ReadMaterials(fin, numMaterials, mats);
ReadSubsetTable(fin, numMaterials, subsets);
ReadVertices(fin,numVertices,vertices);
ReadTriangles(fin, numTriangles,indices);
return true;
}
return false;
}
//读取相应的网格数据和动画数据
bool M3dLoaderClass::LoadM3d(const string&FileName, vector<PosNormalTexTanSkinnedVertex>& vertices, vector<unsigned long>& indices, vector<MeshGeometryClass::Subset>& subsets, vector<M3dMaterial>& mats, SkinnedDataClass& skinInfo)
{
//打开M3d.文件格式
ifstream fin(FileName);
UINT numMaterials = 0;
UINT numVertices = 0;
UINT numTriangles = 0;
UINT numBones = 0;
UINT numAnimationsClips = 0;
string ignore;
if (fin)
{
fin >> ignore;//跳过一行
fin >> ignore >> numMaterials;
fin >> ignore >> numVertices;
fin >> ignore >> numTriangles;
fin >> ignore >> numBones;
fin >> ignore >> numAnimationsClips;
vector<XMFLOAT4X4> boneOffets;
vector<int> boneToParentIndex;
map<string, AnimationClip> animations;
ReadMaterials(fin,numMaterials,mats);
ReadSubsetTable(fin, numMaterials, subsets);
ReadSkinnedVertices(fin, numVertices, vertices);
ReadTriangles(fin, numTriangles, indices);
ReadBoneOffets(fin, numBones, boneOffets);
ReadBoneHierarchy(fin,numBones,boneToParentIndex);
ReadAnimationClips(fin, numBones, numAnimationsClips, animations);
skinInfo.Set(boneToParentIndex, boneOffets, animations);
return true;
}
return false;
}
//读取材质
void M3dLoaderClass::ReadMaterials(ifstream& FileIn, UINT numMaterials, vector<M3dMaterial>& mats)
{
string ignore;
mats.resize(numMaterials);
string DiffuseMapName;
string NormalMapName;
FileIn>> ignore; //跳过文件头一行
for (UINT i = 0; i < numMaterials; ++i)
{
FileIn >> ignore >> mats[i].Mat.Ambient.x >> mats[i].Mat.Ambient.y >> mats[i].Mat.Ambient.z;
FileIn >> ignore >> mats[i].Mat.Diffuse.x >> mats[i].Mat.Diffuse.y >> mats[i].Mat.Diffuse.z;
FileIn >> ignore >> mats[i].Mat.Specular.x >> mats[i].Mat.Specular.y >> mats[i].Mat.Specular.z;
FileIn >> ignore >> mats[i].Mat.Specular.w;
FileIn >> ignore >> mats[i].Mat.Reflect.x >> mats[i].Mat.Reflect.y >> mats[i].Mat.Reflect.z;
FileIn >> ignore >> mats[i].AlphaClip;
FileIn >> ignore >> mats[i].EffectTypeName;
FileIn >> ignore >> DiffuseMapName;
FileIn >> ignore >> NormalMapName;
//将DiffuseMapName和NormalMapName从string变为wstring格式
mats[i].DiffuseMapName.resize(DiffuseMapName.size(), ' ');
mats[i].NormalMapName.resize(NormalMapName.size(), ' ');
std::copy(DiffuseMapName.begin(), DiffuseMapName.end(), mats[i].DiffuseMapName.begin());
std::copy(NormalMapName.begin(), NormalMapName.end(), mats[i].NormalMapName.begin());
}
}
//读取子集表
void M3dLoaderClass::ReadSubsetTable(ifstream& FileIn, UINT numSubsets, vector<MeshGeometryClass::Subset>& subsets)
{
string ignore;
subsets.resize(numSubsets);
FileIn >> ignore; //跳过头一行
for (UINT i = 0; i < numSubsets; ++i)
{
FileIn >> ignore >> subsets[i].Id;
FileIn >> ignore >> subsets[i].VertexStart;
FileIn >> ignore >> subsets[i].VertexCount;
FileIn >> ignore >> subsets[i].FaceStart;
FileIn >> ignore >> subsets[i].FaceCount;
}
}
//读取顶点的属性集合
void M3dLoaderClass::ReadVertices(ifstream& FileIn, UINT numVertices, vector<PosNormalTexTanVertex>& vertices)
{
string ignore;
vertices.resize(numVertices);
FileIn >> ignore; //跳过头一行
for (UINT i = 0; i < numVertices; ++i)
{
FileIn >> ignore >> vertices[i].Pos.x >> vertices[i].Pos.y >> vertices[i].Pos.z;
FileIn >> ignore >> vertices[i].TangentU.x >> vertices[i].TangentU.y >> vertices[i].TangentU.z >> vertices[i].TangentU.w;
FileIn >> ignore >> vertices[i].Normal.x >> vertices[i].Normal.y >> vertices[i].Normal.z;
FileIn >> ignore >> vertices[i].Tex.x >> vertices[i].Tex.y;
}
}
// 读取蒙皮顶点属性
void M3dLoaderClass::ReadSkinnedVertices(ifstream& FileIn, UINT numVertices, vector<PosNormalTexTanSkinnedVertex>& vertices)
{
string ignore;
vertices.resize(numVertices);
FileIn >> ignore; //跳过头一行
int boneIndices[4];
for (UINT i = 0; i < numVertices; ++i)
{
FileIn >> ignore >> vertices[i].Pos.x >> vertices[i].Pos.y >> vertices[i].Pos.z;
FileIn >> ignore >> vertices[i].TangentU.x >> vertices[i].TangentU.y >> vertices[i].TangentU.z >> vertices[i].TangentU.w;
FileIn >> ignore >> vertices[i].Normal.x >> vertices[i].Normal.y >> vertices[i].Normal.z;
FileIn >> ignore >> vertices[i].Tex.x >> vertices[i].Tex.y;
FileIn >> ignore >> vertices[i].Weights.x >> vertices[i].Weights.y >> vertices[i].Weights.z>>ignore;
FileIn >> ignore >> boneIndices[0] >> boneIndices[1] >> boneIndices[2] >> boneIndices[3];
vertices[i].BoneIndices[0] = (BYTE)boneIndices[0];
vertices[i].BoneIndices[1] = (BYTE)boneIndices[1];
vertices[i].BoneIndices[2] = (BYTE)boneIndices[2];
vertices[i].BoneIndices[3] = (BYTE)boneIndices[3];
}
}
//读取三角形索引
void M3dLoaderClass::ReadTriangles(ifstream& FileIn, UINT numTriangles, vector<unsigned long>& indices)
{
string ignore;
//numTriangles*3个索引数目
indices.resize(numTriangles*3);
FileIn >> ignore; //跳过头一行
for (UINT i = 0; i < numTriangles; ++i)
{
FileIn >> indices[i*3+0]>> indices[i * 3 + 1]>> indices[i * 3 + 2];
}
}
//读取骨骼位移
void M3dLoaderClass::ReadBoneOffets(ifstream& FileIn, UINT numBones, vector<XMFLOAT4X4>& boneOffsets)
{
string ignore;
boneOffsets.resize(numBones);
FileIn >> ignore; //跳过头一行
for (UINT i = 0; i < numBones; ++i)
{
FileIn >> ignore >> boneOffsets[i](0, 0) >> boneOffsets[i](0, 1) >> boneOffsets[i](0, 2) >> boneOffsets[i](0, 3) >>
boneOffsets[i](1, 0) >> boneOffsets[i](1, 1) >> boneOffsets[i](1, 2) >> boneOffsets[i](1, 3) >>
boneOffsets[i](2, 0) >> boneOffsets[i](2, 1) >> boneOffsets[i](2, 2) >> boneOffsets[i](2, 3) >>
boneOffsets[i](3, 0) >> boneOffsets[i](3, 1) >> boneOffsets[i](3, 2) >> boneOffsets[i](3, 3);
}
}
//读取骨骼层级(以数组形式呈现的骨骼树关系)
void M3dLoaderClass::ReadBoneHierarchy(ifstream& FileIn, UINT numBones, vector<int>& boneIndexToParentIndex)
{
string ignore;
boneIndexToParentIndex.resize(numBones);
FileIn >> ignore; //跳过头一行
for (UINT i = 0; i < numBones; ++i)
{
FileIn >> ignore >> boneIndexToParentIndex[i];
}
}
//读取动画片段
void M3dLoaderClass::ReadAnimationClips(ifstream& FileIn, UINT numBones, UINT numAnimationClips, map<string, AnimationClip>& animations)
{
string ignore;
FileIn >> ignore; //跳过头一行
for (UINT clipIndex = 0; clipIndex < numAnimationClips; ++clipIndex)
{
string clipName;
//获取动画片段名
FileIn >> ignore >> clipName;
FileIn >> ignore; //跳过"{"
AnimationClip clip;
clip.BoneAnimations.resize(numBones);
for (UINT boneIndex = 0; boneIndex < numBones; ++boneIndex)
{
ReadBoneKeyFrame(FileIn, numBones, clip.BoneAnimations[boneIndex]);
}
FileIn >> ignore; //跳过"}"
animations[clipName] = clip;
}
}
//读取骨头关键帧
void M3dLoaderClass::ReadBoneKeyFrame(ifstream& FileIn, UINT numBones, BoneAnimation& boneAnimation)
{
string ignore;
UINT numKeyframes = 0;
FileIn >> ignore >> ignore >> numKeyframes;
FileIn >> ignore; //跳过“{”
boneAnimation.keyFrames.resize(numKeyframes);
for (UINT KeyFrameIndex = 0; KeyFrameIndex < numKeyframes; ++KeyFrameIndex)
{
XMFLOAT3 Translation;
XMFLOAT3 Scale;
XMFLOAT4 Quat;
FileIn >> ignore >> boneAnimation.keyFrames[KeyFrameIndex].TimePos;
FileIn >> ignore >> Translation.x >> Translation.y >> Translation.z;
FileIn >> ignore >> Scale.x >> Scale.y >> Scale.z;
FileIn >> ignore >> Quat.x >> Quat.y >> Quat.z >> Quat.w;
boneAnimation.keyFrames[KeyFrameIndex].Translation = Translation;
boneAnimation.keyFrames[KeyFrameIndex].Scale = Scale;
boneAnimation.keyFrames[KeyFrameIndex].RotationQuat = Quat;
}
FileIn >> ignore; //跳过“}”
}
(3)MeshGeometryClass.h(用于设置VertexBuffer,IndexBuffer进行DrawIndexd)
#pragma once
#ifndef MESH_GEOMETRY_CLASS
#define MESH_GEOMETRY_CLASS
#include<Windows.h>
#include<iostream>
#include<vector>
#include<d3d11.h>
#include<D3Dcommon.h> //???
#include<D3DX11.h>
#include"Macro.h"
using std::vector;
class MeshGeometryClass
{
public:
//分组
struct Subset
{
UINT Id;
UINT VertexStart;
UINT VertexCount;
UINT FaceStart;
UINT FaceCount;
Subset() :Id(-1), VertexStart(0), VertexCount(0), FaceStart(0), FaceCount(0)
{
}
};
private:
ID3D11Buffer* mVertexBuffer;
ID3D11Buffer* mIndexBuffer;
DXGI_FORMAT mIndexBufferFormat; //32位 对应于unsigned long
UINT mVertexStride; //顶点跨度
vector<Subset> mSubsetTable;
private:
MeshGeometryClass(const MeshGeometryClass& rhs);
//MeshGeometryClass& operator=(const MeshGeometryClass& rhs);
public:
MeshGeometryClass();
~MeshGeometryClass();
public:
template<typename VertexTypeA>
bool SetVertices(ID3D11Device* device, const VertexTypeA*vertices, UINT count);
bool SetIndices(ID3D11Device* device, const unsigned long* indices, UINT count);
void SetSubsetTable(vector<Subset>& SubsetTable);
void Draw(ID3D11DeviceContext* deviceContext, UINT subsetId);
};
template<typename VertexTypeA>
bool MeshGeometryClass::SetVertices(ID3D11Device* device, const VertexTypeA*vertices, UINT count)
{
//释放顶点缓存
ReleaseCOM(mVertexBuffer);
mVertexStride = sizeof(VertexTypeA);
//填充(顶点)缓存形容结构体和子资源数据结构体,并创建顶点缓存
D3D11_BUFFER_DESC vertexBufferDesc;
vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
vertexBufferDesc.ByteWidth = sizeof(VertexTypeA) * count;
vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexBufferDesc.CPUAccessFlags = 0;
vertexBufferDesc.MiscFlags = 0;
vertexBufferDesc.StructureByteStride = 0;
D3D11_SUBRESOURCE_DATA vertexData;
vertexData.pSysMem = vertices;
vertexData.SysMemPitch = 0;
vertexData.SysMemSlicePitch = 0;
HR(device->CreateBuffer(&vertexBufferDesc, &vertexData, &mVertexBuffer));
return true;
}
#endif // ! MESH_GEOMETRY_CLASS
#include"MeshGeometryClass.h"
MeshGeometryClass::MeshGeometryClass():mVertexBuffer(NULL),mIndexBuffer(NULL),mIndexBufferFormat(DXGI_FORMAT_R32_UINT),mVertexStride(0)
{
}
MeshGeometryClass::~MeshGeometryClass()
{
ReleaseCOM(mVertexBuffer);
ReleaseCOM(mIndexBuffer);
}
bool MeshGeometryClass::SetIndices(ID3D11Device* device, const unsigned long* indices, UINT count)
{
D3D11_BUFFER_DESC indexBufferDesc;
indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
indexBufferDesc.ByteWidth = sizeof(unsigned long) * count;
indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
indexBufferDesc.CPUAccessFlags = 0;
indexBufferDesc.MiscFlags = 0;
indexBufferDesc.StructureByteStride = 0;
D3D11_SUBRESOURCE_DATA indexData;
indexData.pSysMem = indices;
indexData.SysMemPitch = 0;
indexData.SysMemSlicePitch = 0;
HR(device->CreateBuffer(&indexBufferDesc, &indexData, &mIndexBuffer));
return true;
}
void MeshGeometryClass::SetSubsetTable(vector<Subset>& SubsetTable)
{
mSubsetTable = SubsetTable;
}
void MeshGeometryClass::Draw(ID3D11DeviceContext* deviceContext, UINT subsetId)
{
UINT offset=0;
//设置拓扑方式
deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &mVertexStride, &offset);
deviceContext->IASetIndexBuffer(mIndexBuffer, mIndexBufferFormat,0);
deviceContext->DrawIndexed(mSubsetTable[subsetId].FaceCount * 3, mSubsetTable[subsetId].FaceStart * 3, 0);
}
(3)SkinnedMeshClass..h(封装的人物网格的各种数据)
#pragma once
#ifndef _SKINNED_MODEL_CLASS
#define _SKINNED_MODEL_CLASS
#include"MeshGeometryClass.h"
#include"SkinnedDataClass.h"
#include"TextureMgrClass.h"
#include"CommonVertexFormat.h"
#include<D3Dcommon.h>
#include<D3DX11.h>
class SkinnedModelClass
{
public:
UINT SubsetCount;
vector<Material> Mat; //材质
vector<ID3D11ShaderResourceView*> DiffuseMapSRV; //漫反射
vector<ID3D11ShaderResourceView*> NormalMapSRV; //法线贴图
//骨骼顶点数据
vector<PosNormalTexTanSkinnedVertex> Vertices;
vector<unsigned long> Indices;
vector<MeshGeometryClass::Subset> Subsets;
SkinnedDataClass SkinnedData;
MeshGeometryClass ModelMesh;
public:
SkinnedModelClass(ID3D11Device* device, TextureMgrClass& texMgr, const string& modelFileName, wstring texturePath);
~SkinnedModelClass();
};
struct SkinnedModelInstance
{
SkinnedModelClass* Model;
float TimePos;
std::string ClipName;
XMFLOAT4X4 World;
std::vector<XMFLOAT4X4> FinalTransforms;
void Update(float dt);
};
#endif // !_SKINNED_MODEL_CLASS
SkinnedMeshClass.CPP
#include"SkinnedModelClass.h"
#include"LoadM3DClass.h"
SkinnedModelClass::SkinnedModelClass(ID3D11Device* device, TextureMgrClass& texMgr, const string& modelFileName, wstring texturePath)
{
bool result;
vector<M3dMaterial> mats;
M3dLoaderClass m3dLoader;
m3dLoader.LoadM3d(modelFileName, Vertices, Indices, Subsets, mats,SkinnedData);
result=ModelMesh.SetVertices(device,&Vertices[0],Vertices.size());
if (!result)
{
MessageBox(NULL, L"ModelMesh.SetVertices failure", NULL, MB_OK);
}
result=ModelMesh.SetIndices(device,&Indices[0],Indices.size());
if (!result)
{
MessageBox(NULL, L"ModelMesh.SetIndices failure", NULL, MB_OK);
}
ModelMesh.SetSubsetTable(Subsets);
SubsetCount = mats.size();
for (UINT i = 0; i < SubsetCount; ++i)
{
Mat.push_back(mats[i].Mat);
ID3D11ShaderResourceView* diffuseMapSRV = texMgr.CreateTexture(texturePath + mats[i].DiffuseMapName);
DiffuseMapSRV.push_back(diffuseMapSRV);
ID3D11ShaderResourceView* normalMapSRV= texMgr.CreateTexture(texturePath + mats[i].NormalMapName);
NormalMapSRV.push_back(normalMapSRV);
}
}
SkinnedModelClass::~SkinnedModelClass()
{
}
void SkinnedModelInstance::Update(float dt)
{
TimePos += dt;
Model->SkinnedData.GetFinalTransforms(ClipName, TimePos, FinalTransforms);
//循环动画
if (TimePos > Model->SkinnedData.GetClipEndTime(ClipName))
TimePos = 0.0f;
}
下一篇博客链接:D3D11教程四十二下之进行骨骼动画的渲染