├── .gitignore ├── Cargo.toml ├── LICENSE ├── README.md ├── assets ├── arm_twist.dae ├── assets.json ├── brown_eye.png ├── classicshoes_texture_diffuse.png ├── classicshoes_texture_normals.png ├── eyebrow009.png ├── eyelashes01.png ├── head_look_down.dae ├── head_look_left.dae ├── head_look_right.dae ├── head_look_up.dae ├── male02_diffuse_black.png ├── run.dae ├── standing_idle.dae ├── suit01_normals.png ├── suit01lres_diffuse.png ├── suit_guy.blend ├── suit_guy.dae ├── t_pose.dae ├── test.blend ├── test.dae ├── walk.dae ├── walk_backward.dae ├── walk_left.dae ├── walk_right.dae └── young_lightskinned_male_diffuse.png ├── screenshot.png └── src ├── demo.rs └── main.rs /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled files 2 | *.o 3 | *.so 4 | *.rlib 5 | *.dll 6 | 7 | # Executables 8 | *.exe 9 | 10 | # Generated by Cargo 11 | target 12 | Cargo.lock 13 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | 3 | name = "skeletal_animation_demo" 4 | version = "0.0.1" 5 | authors = ["Steve Jahns "] 6 | 7 | [[bin]] 8 | name = "demo" 9 | path = "src/main.rs" 10 | 11 | [dependencies] 12 | skeletal_animation = "0.47.0" 13 | gfx_gl = "0.5.0" 14 | env_logger = "0.6.0" 15 | collada = "0.15.0" 16 | vecmath = "1.0.0" 17 | quaternion = "1.0.0" 18 | dual_quaternion = "0.2.0" 19 | gfx = "0.18.1" 20 | gfx_device_gl = "0.16.2" 21 | piston-gfx_texture = "0.44.0" 22 | interpolation = "0.3.0" 23 | piston-float = "1.0.0" 24 | shader_version = "0.7.0" 25 | sdl2 = "0.35.2" 26 | pistoncore-sdl2_window = "0.69.0" 27 | camera_controllers = "0.34.0" 28 | piston = "0.55.0" 29 | piston_window = "0.131.0" 30 | gfx_text = "0.33.0" 31 | gfx_debug_draw = "0.33.0" 32 | dev_menu = "0.41.0" 33 | 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Steve Jahns 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # skeletal_animation_demo 2 | Demo project for [PistonDevelopers/skeletal_animation](https://github.com/PistonDevelopers/skeletal_animation). 3 | 4 | ![screenshot](./screenshot.png) 5 | 6 | Rigged mesh was generated with [MakeHuman](http://www.makehuman.org/). 7 | Animations were adapted from motion capture sequences from [CMU Graphics Lab Motion Capture Database](http://mocap.cs.cmu.edu/) 8 | which were converted to a BVH format [here](https://sites.google.com/a/cgspeed.com/cgspeed/motion-capture/cmu-bvh-conversion) and loaded 9 | into [Blender](http://www.blender.org/) and retargeted for the MakeHuman rig using [MakeWalk](http://www.makehuman.org/doc/node/mhblendertools_makewalk_basic_workflow.html). 10 | -------------------------------------------------------------------------------- /assets/assets.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | "animation_clips": [{ 4 | "name": "walk-forward", 5 | "source": "walk.dae", 6 | "looping": true 7 | }, { 8 | "name": "run-forward", 9 | "source": "run.dae", 10 | "looping": true 11 | }, { 12 | "name": "walk-left", 13 | "source": "walk_left.dae", 14 | "looping": true, 15 | "rotate_z": 180 16 | }, { 17 | "name": "walk-right", 18 | "source": "walk_right.dae", 19 | "looping": true, 20 | "rotate_z": 180 21 | }, { 22 | "name": "stand-idle", 23 | "source": "standing_idle.dae", 24 | "looping": true, 25 | "rotate_z": 90 26 | }, { 27 | "name": "reference-pose", 28 | "source": "t_pose.dae", 29 | "looping": true 30 | }, { 31 | "name": "head-look-right", 32 | "source": "head_look_right.dae", 33 | "looping": true 34 | }, { 35 | "name": "head-look-left", 36 | "source": "head_look_left.dae", 37 | "looping": true 38 | }, { 39 | "name": "head-look-down", 40 | "source": "head_look_down.dae", 41 | "looping": true 42 | }, { 43 | "name": "head-look-up", 44 | "source": "head_look_up.dae", 45 | "looping": true 46 | }, { 47 | "name": "arm-twist", 48 | "source": "arm_twist.dae", 49 | "looping": true 50 | }], 51 | 52 | "difference_clips": [{ 53 | "name": "head-look-left-additive", 54 | "source_clip": "head-look-left", 55 | "reference_clip": "reference-pose" 56 | }, { 57 | "name": "head-look-right-additive", 58 | "source_clip": "head-look-right", 59 | "reference_clip": "reference-pose" 60 | }, { 61 | "name": "head-look-down-additive", 62 | "source_clip": "head-look-down", 63 | "reference_clip": "reference-pose" 64 | }, { 65 | "name": "head-look-up-additive", 66 | "source_clip": "head-look-up", 67 | "reference_clip": "reference-pose" 68 | }, { 69 | "name": "arm-twist-additive", 70 | "source_clip": "arm-twist", 71 | "reference_clip": "reference-pose" 72 | }], 73 | 74 | "animation_controllers": [{ 75 | 76 | "name": "human-controller", 77 | 78 | "parameters": [ 79 | "arm-twist", 80 | "forward-speed", 81 | "forward-to-strafe", 82 | "walk-to-run", 83 | "head-left-to-right", 84 | "head-down-to-up", 85 | "head-look-level", 86 | "head-look-sideways-level", 87 | "ik-blend-level", 88 | "target-x", 89 | "target-y", 90 | "target-z", 91 | "bend-dir-x", 92 | "bend-dir-y", 93 | "bend-dir-z" 94 | ], 95 | 96 | "states": [ { 97 | "name": "walking-forward", 98 | 99 | "blend_tree": { 100 | "type": "IKNode", 101 | "blend_param": "ik-blend-level", 102 | "effector": "hand_R", 103 | "target_x_param": "target-x", 104 | "target_y_param": "target-y", 105 | "target_z_param": "target-z", 106 | "bend_x_param": "bend-dir-x", 107 | "bend_y_param": "bend-dir-y", 108 | "bend_z_param": "bend-dir-z", 109 | "input": { 110 | "type": "AdditiveNode", 111 | "param": "head-look-level", 112 | "inputs": [ { 113 | "type": "LerpNode", 114 | "param": "walk-to-run", 115 | "inputs": [{ 116 | "type": "ClipNode", 117 | "clip_source": "walk-forward" 118 | }, { 119 | "type": "ClipNode", 120 | "clip_source": "run-forward" 121 | }] 122 | }, { 123 | 124 | "type": "AdditiveNode", 125 | "param": "head-look-sideways-level", 126 | "inputs": [{ 127 | "type": "LerpNode", 128 | "param": "head-left-to-right", 129 | "inputs": [{ 130 | "type": "ClipNode", 131 | "clip_source": "head-look-left-additive" 132 | }, { 133 | "type": "ClipNode", 134 | "clip_source": "head-look-right-additive" 135 | }] 136 | }, { 137 | "type": "LerpNode", 138 | "param": "head-down-to-up", 139 | "inputs": [{ 140 | "type": "ClipNode", 141 | "clip_source": "head-look-down-additive" 142 | }, { 143 | "type": "ClipNode", 144 | "clip_source": "head-look-up-additive" 145 | }] 146 | }] 147 | }] 148 | } 149 | }, 150 | 151 | "transitions": [ { 152 | "target_state": "stand-idle", 153 | "duration": 0.5, 154 | "condition": { 155 | "parameter": "forward-speed", 156 | "operator": "<", 157 | "value": 0.1 158 | } 159 | }] 160 | 161 | }, { 162 | "name": "stand-idle", 163 | "blend_tree": { 164 | "type": "IKNode", 165 | "blend_param": "ik-blend-level", 166 | "effector": "foot_R", 167 | "target_x_param": "target-x", 168 | "target_y_param": "target-y", 169 | "target_z_param": "target-z", 170 | "bend_x_param": "bend-dir-x", 171 | "bend_y_param": "bend-dir-y", 172 | "bend_z_param": "bend-dir-z", 173 | "input": { 174 | "type": "AdditiveNode", 175 | "param": "head-look-level", 176 | "inputs": [{ 177 | "type": "ClipNode", 178 | "clip_source": "stand-idle" 179 | 180 | }, { 181 | "type": "AdditiveNode", 182 | "param": "head-look-sideways-level", 183 | "inputs": [{ 184 | "type": "LerpNode", 185 | "param": "head-left-to-right", 186 | "inputs": [{ 187 | "type": "ClipNode", 188 | "clip_source": "head-look-left-additive" 189 | }, { 190 | "type": "ClipNode", 191 | "clip_source": "head-look-right-additive" 192 | }] 193 | }, { 194 | "type": "LerpNode", 195 | "param": "head-down-to-up", 196 | "inputs": [{ 197 | "type": "ClipNode", 198 | "clip_source": "head-look-down-additive" 199 | }, { 200 | "type": "ClipNode", 201 | "clip_source": "head-look-up-additive" 202 | }] 203 | }] 204 | }] 205 | } 206 | }, 207 | "transitions": [{ 208 | "target_state": "walking-forward", 209 | "duration": 0.5, 210 | "condition": { 211 | "parameter": "forward-speed", 212 | "operator": ">", 213 | "value": 0.1 214 | } 215 | }, { 216 | "target_state": "arm-twist-demo", 217 | "duration": 0.5, 218 | "condition": { 219 | "parameter": "arm-twist", 220 | "operator": ">", 221 | "value": 0.01 222 | } 223 | }] 224 | }, { 225 | "name": "arm-twist-demo", 226 | "blend_tree": { 227 | "type": "AdditiveNode", 228 | "param": "arm-twist", 229 | "inputs": [{ 230 | "type": "ClipNode", 231 | "clip_source": "reference-pose" 232 | }, { 233 | "type": "ClipNode", 234 | "clip_source": "arm-twist-additive" 235 | }] 236 | }, 237 | "transitions": [{ 238 | "target_state": "stand-idle", 239 | "duration": 0.5, 240 | "condition": { 241 | "parameter": "arm-twist", 242 | "operator": "<", 243 | "value": 0.01 244 | } 245 | }] 246 | } ], 247 | 248 | "initial_state": "stand-idle" 249 | }] 250 | 251 | } 252 | -------------------------------------------------------------------------------- /assets/brown_eye.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PistonDevelopers/skeletal_animation_demo/bff5cf3989a59766339da4d17313f96e910c332f/assets/brown_eye.png -------------------------------------------------------------------------------- /assets/classicshoes_texture_diffuse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PistonDevelopers/skeletal_animation_demo/bff5cf3989a59766339da4d17313f96e910c332f/assets/classicshoes_texture_diffuse.png -------------------------------------------------------------------------------- /assets/classicshoes_texture_normals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PistonDevelopers/skeletal_animation_demo/bff5cf3989a59766339da4d17313f96e910c332f/assets/classicshoes_texture_normals.png -------------------------------------------------------------------------------- /assets/eyebrow009.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PistonDevelopers/skeletal_animation_demo/bff5cf3989a59766339da4d17313f96e910c332f/assets/eyebrow009.png -------------------------------------------------------------------------------- /assets/eyelashes01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PistonDevelopers/skeletal_animation_demo/bff5cf3989a59766339da4d17313f96e910c332f/assets/eyelashes01.png -------------------------------------------------------------------------------- /assets/male02_diffuse_black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PistonDevelopers/skeletal_animation_demo/bff5cf3989a59766339da4d17313f96e910c332f/assets/male02_diffuse_black.png -------------------------------------------------------------------------------- /assets/suit01_normals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PistonDevelopers/skeletal_animation_demo/bff5cf3989a59766339da4d17313f96e910c332f/assets/suit01_normals.png -------------------------------------------------------------------------------- /assets/suit01lres_diffuse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PistonDevelopers/skeletal_animation_demo/bff5cf3989a59766339da4d17313f96e910c332f/assets/suit01lres_diffuse.png -------------------------------------------------------------------------------- /assets/suit_guy.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PistonDevelopers/skeletal_animation_demo/bff5cf3989a59766339da4d17313f96e910c332f/assets/suit_guy.blend -------------------------------------------------------------------------------- /assets/test.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PistonDevelopers/skeletal_animation_demo/bff5cf3989a59766339da4d17313f96e910c332f/assets/test.blend -------------------------------------------------------------------------------- /assets/test.dae: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Blender User 6 | Blender 2.73.0 commit date:2015-01-20, commit time:18:16, hash:bbf09d9 7 | 8 | 2015-03-31T18:01:53 9 | 2015-03-31T18:01:53 10 | 11 | Z_UP 12 | 13 | 14 | 15 | 16 | 17 | 18 | -1 -1 -1 -1 1 -1 1 1 -1 1 -1 -1 -1 -1 1 -1 1 1 1 1 1 1 -1 1 -1 -1 3 -1 1 3 1 1 3 1 -1 3 -1 -1 5 -1 1 5 1 1 5 1 -1 5 -1 -1 7 -1 1 7 1 1 7 1 -1 7 -1 -1 9 -1 1 9 1 1 9 1 -1 9 -1 -1 11 -1 1 11 1 1 11 1 -1 11 -1 -1 13 -1 1 13 1 1 13 1 -1 13 -1 -1 15 -1 1 15 1 1 15 1 -1 15 -1 -1 17 -1 1 17 1 1 17 1 -1 17 -1 -1 19 -1 1 19 1 1 19 1 -1 19 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -1 0 0 0 1 0 1 0 0 0 -1 0 0 0 -1 0 -1 0 0 -1 0 1 0 0 0 1 0 -1 0 0 0 -1 0 1 0 0 0 1 0 -1 0 0 0 -1 0 1 0 0 0 1 0 -1 0 0 0 -1 0 1 0 0 0 1 0 -1 0 0 0 -1 0 1 0 0 0 1 0 -1 0 0 0 -1 0 1 0 0 0 1 0 -1 0 0 0 -1 0 1 0 0 0 1 0 -1 0 0 0 -1 0 1 0 0 0 1 0 -1 0 0 0 0 1 1 0 0 0 1 0 -1 0 0 -1 0 0 0 1 0 1 0 0 0 -1 0 0 0 -1 0 -1 0 0 -1 0 1 0 0 0 1 0 -1 0 0 0 -1 0 1 0 0 0 1 0 -1 0 0 0 -1 0 1 0 0 0 1 0 -1 0 0 0 -1 0 1 0 0 0 1 0 -1 0 0 0 -1 0 1 0 0 0 1 0 -1 0 0 0 -1 0 1 0 0 0 1 0 -1 0 0 0 -1 0 1 0 0 0 1 0 -1 0 0 0 -1 0 1 0 0 0 1 0 -1 0 0 0 0 1 1 0 0 0 1 0 -1 0 0 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 44 |

5 0 1 0 0 0 6 1 2 1 1 1 7 2 3 2 2 2 4 3 0 3 3 3 1 4 2 4 3 4 7 5 11 5 8 5 11 6 15 6 12 6 6 7 10 7 11 7 5 8 9 8 10 8 4 9 8 9 9 9 15 10 19 10 16 10 10 11 14 11 15 11 9 12 13 12 14 12 8 13 12 13 13 13 19 14 23 14 20 14 14 15 18 15 19 15 13 16 17 16 18 16 12 17 16 17 17 17 23 18 27 18 24 18 18 19 22 19 23 19 17 20 21 20 22 20 16 21 20 21 21 21 27 22 31 22 28 22 22 23 26 23 27 23 21 24 25 24 26 24 20 25 24 25 25 25 31 26 35 26 32 26 26 27 30 27 31 27 25 28 29 28 30 28 24 29 28 29 29 29 35 30 39 30 36 30 30 31 34 31 35 31 29 32 33 32 34 32 28 33 32 33 33 33 39 34 43 34 40 34 34 35 38 35 39 35 33 36 37 36 38 36 32 37 36 37 37 37 42 38 41 38 40 38 38 39 42 39 43 39 37 40 41 40 42 40 36 41 40 41 41 41 4 42 5 42 0 42 5 43 6 43 1 43 6 44 7 44 2 44 7 45 4 45 3 45 0 46 1 46 3 46 4 47 7 47 8 47 8 48 11 48 12 48 7 49 6 49 11 49 6 50 5 50 10 50 5 51 4 51 9 51 12 52 15 52 16 52 11 53 10 53 15 53 10 54 9 54 14 54 9 55 8 55 13 55 16 56 19 56 20 56 15 57 14 57 19 57 14 58 13 58 18 58 13 59 12 59 17 59 20 60 23 60 24 60 19 61 18 61 23 61 18 62 17 62 22 62 17 63 16 63 21 63 24 64 27 64 28 64 23 65 22 65 27 65 22 66 21 66 26 66 21 67 20 67 25 67 28 68 31 68 32 68 27 69 26 69 31 69 26 70 25 70 30 70 25 71 24 71 29 71 32 72 35 72 36 72 31 73 30 73 35 73 30 74 29 74 34 74 29 75 28 75 33 75 36 76 39 76 40 76 35 77 34 77 39 77 34 78 33 78 38 78 33 79 32 79 37 79 43 80 42 80 40 80 39 81 38 81 43 81 38 82 37 82 42 82 37 83 36 83 41 83

45 |
46 |
47 |
48 |
49 | 50 | 51 | 52 | 0 1.25 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 1 0 0 0 0 0 -1 0 0 1 0 0 0 0 0 1 1 0 0 0 0 0 -1 0 0 1 0 0 0 0 0 1 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | LINEAR LINEAR 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 0 1.25 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 1 0 0 0 0 1 0 5 0 0 1 0 0 0 0 1 -2.22045e-16 0 -1 0 1 -2.22045e-16 0 5 0 -1 -2.22045e-16 0 0 0 0 1 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | LINEAR LINEAR 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 0 1.25 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 1 0 0 0 0 1 0 6 0 0 1 0 0 0 0 1 1 0 0 0 0 1 0 6 0 0 1 0 0 0 0 1 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | LINEAR LINEAR 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 151 | 152 | Bone Bone_001 Bone_002 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 1 0 0 0 0 0 1 0 0 -1 0 0 0 0 0 1 1 0 0 0 0 0 1 -5 0 -1 0 0 0 0 0 1 1 0 0 0 0 0 1 -11 0 -1 0 0 0 0 0 1 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 1 1 1 1 1 1 1 1 0.9495525 0.05044752 0.9495525 0.05044758 0.9495525 0.05044752 0.9495525 0.05044758 0.5001411 0.4998589 0.5001411 0.4998589 0.5001411 0.4998589 0.5001411 0.4998589 0.05072385 0.9492762 0.05072385 0.9492762 0.05072385 0.9492762 0.05072385 0.9492762 0.9492761 0.05072391 0.9492761 0.05072391 0.9492761 0.05072391 0.9492761 0.05072391 0.4998586 0.5001415 0.4998586 0.5001415 0.4998586 0.5001415 0.4998586 0.5001415 0.05044198 0.9495581 0.05044198 0.9495581 0.05044198 0.9495581 0.05044198 0.9495581 1 1 1 1 1 1 1 1 1 1 1 1 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 183 | 0 0 0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 1 9 0 10 1 11 0 12 1 13 0 14 1 15 0 16 1 17 0 18 1 19 0 20 1 21 0 22 1 23 0 24 1 25 0 26 1 27 0 28 1 29 0 30 1 31 1 32 2 33 1 34 2 35 1 36 2 37 1 38 2 39 1 40 2 41 1 42 2 43 1 44 2 45 1 46 2 47 1 48 2 49 1 50 2 51 1 52 2 53 1 54 2 55 2 56 2 57 2 58 2 59 2 60 2 61 2 62 2 63 2 64 2 65 2 66 2 67 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 0 0 0 192 | 0 0 1 0 193 | 0 1 0 0 194 | 1 0 0 0 195 | 1 1 1 196 | 197 | 1 0 0 0 0 0 -1 0 0 1 0 0 0 0 0 1 198 | 199 | 1 0 0 0 0 1 0 5 0 0 1 0 0 0 0 1 200 | 201 | 1 0 0 0 0 1 0 6 0 0 1 0 0 0 0 1 202 | 203 | 204 | 205 | 206 | 207 | 0 0 0 208 | 0 0 1 0 209 | 0 1 0 0 210 | 1 0 0 0 211 | 1 1 1 212 | 213 | #Bone 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 |
-------------------------------------------------------------------------------- /assets/young_lightskinned_male_diffuse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PistonDevelopers/skeletal_animation_demo/bff5cf3989a59766339da4d17313f96e910c332f/assets/young_lightskinned_male_diffuse.png -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PistonDevelopers/skeletal_animation_demo/bff5cf3989a59766339da4d17313f96e910c332f/screenshot.png -------------------------------------------------------------------------------- /src/demo.rs: -------------------------------------------------------------------------------- 1 | use std::path::Path; 2 | 3 | use std::rc::Rc; 4 | use std::collections::HashMap; 5 | 6 | use collada::document::ColladaDocument; 7 | use gfx; 8 | use gfx_debug_draw; 9 | use vecmath::Matrix4; 10 | use gfx_texture::TextureContext; 11 | 12 | use skeletal_animation::math::DualQuaternion; 13 | use skeletal_animation::*; 14 | 15 | pub fn lbs_demo, R: gfx::Resources, C: gfx::CommandBuffer>( 16 | tcx: &mut TextureContext 17 | ) -> Demo> 18 | where R: gfx::Resources { 19 | Demo::new(tcx) 20 | } 21 | 22 | pub fn dlb_demo, R: gfx::Resources, C: gfx::CommandBuffer>( 23 | tcx: &mut TextureContext 24 | ) -> Demo, DualQuaternion> 25 | where R: gfx::Resources { 26 | Demo::new(tcx) 27 | } 28 | pub struct Settings { 29 | pub use_dlb: bool, 30 | pub draw_skeleton: bool, 31 | pub draw_labels: bool, 32 | pub draw_mesh: bool, 33 | pub playback_speed: f32, 34 | 35 | pub params: HashMap, 36 | } 37 | 38 | pub struct Demo + HasShaderSources<'static>> { 39 | pub asset_manager: AssetManager, 40 | pub controller: AnimationController, 41 | pub skinned_renderer: SkinnedRenderer, 42 | pub skeleton: Rc, 43 | } 44 | 45 | impl + HasShaderSources<'static>> Demo { 46 | 47 | pub fn new, C: gfx::CommandBuffer>(tcx: &mut TextureContext) -> Demo { 48 | 49 | let collada_document = ColladaDocument::from_path(&Path::new("assets/suit_guy.dae")).unwrap(); 50 | 51 | let texture_paths = vec![ 52 | "assets/young_lightskinned_male_diffuse.png", 53 | "assets/suit01lres_diffuse.png", 54 | "assets/male02_diffuse_black.png", 55 | "assets/brown_eye.png", 56 | "assets/eyebrow009.png", 57 | "assets/eyelashes01.png", 58 | ]; 59 | 60 | // TODO better.. we keep reloading the same document over and over for different things... 61 | let skeleton = { 62 | let skeleton_set = collada_document.get_skeletons().unwrap(); 63 | Skeleton::from_collada(&skeleton_set[0]) 64 | }; 65 | 66 | let skeleton = Rc::new(skeleton); 67 | 68 | let mut asset_manager = AssetManager::::new(); 69 | 70 | asset_manager.load_assets("assets/assets.json").unwrap(); 71 | 72 | let controller_def = asset_manager.controller_defs["human-controller"].clone(); 73 | 74 | let controller = AnimationController::new(controller_def, skeleton.clone(), &asset_manager.animation_clips); 75 | 76 | let skinned_renderer = SkinnedRenderer::::from_collada(tcx, collada_document, texture_paths).unwrap(); 77 | 78 | Demo { 79 | asset_manager: asset_manager, 80 | controller: controller, 81 | skinned_renderer: skinned_renderer, 82 | skeleton: skeleton, 83 | } 84 | } 85 | 86 | pub fn update(&mut self, settings: &Settings, dt: f64) { 87 | self.controller.set_playback_speed(settings.playback_speed as f64); 88 | 89 | for (param, &value) in settings.params.iter() { 90 | self.controller.set_param_value(param, value); 91 | } 92 | 93 | self.controller.update(dt); 94 | } 95 | 96 | pub fn render, C: gfx::CommandBuffer, Rf: gfx::format::RenderFormat>( 97 | &mut self, 98 | settings: &Settings, 99 | debug_renderer: &mut gfx_debug_draw::DebugRenderer, 100 | encoder: &mut gfx::Encoder, 101 | out_color: &gfx::handle::RenderTargetView, 102 | out_depth: &gfx::handle::DepthStencilView, 103 | camera_view: [[f32; 4]; 4], 104 | camera_projection: [[f32; 4]; 4], 105 | ext_dt: f64, 106 | should_draw: bool 107 | ) 108 | where TSkinning: gfx::traits::Pod 109 | { 110 | let mut global_poses = [ TSkinning::identity(); 64 ]; 111 | 112 | self.controller.get_output_pose(ext_dt, &mut global_poses[0 .. self.skeleton.joints.len()]); 113 | if should_draw { 114 | if settings.draw_mesh { 115 | self.skinned_renderer.render(encoder, out_color, out_depth, camera_view, camera_projection, &global_poses); 116 | } 117 | 118 | if settings.draw_skeleton { 119 | self.skeleton.draw(&global_poses, debug_renderer, settings.draw_labels); 120 | } 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate camera_controllers; 2 | extern crate collada; 3 | extern crate dev_menu; 4 | extern crate env_logger; 5 | extern crate gfx; 6 | extern crate gfx_text; 7 | extern crate gfx_debug_draw; 8 | extern crate gfx_texture; 9 | extern crate piston; 10 | extern crate piston_window; 11 | extern crate sdl2_window; 12 | extern crate shader_version; 13 | extern crate skeletal_animation; 14 | extern crate vecmath; 15 | 16 | use std::collections::HashMap; 17 | use piston_window::PistonWindow; 18 | 19 | use gfx_debug_draw::DebugRenderer; 20 | 21 | use piston::window::{ 22 | WindowSettings, 23 | }; 24 | 25 | use piston::input::*; 26 | use vecmath::{mat4_id}; 27 | 28 | use sdl2_window::Sdl2Window; 29 | 30 | use camera_controllers::{ 31 | OrbitZoomCamera, 32 | OrbitZoomCameraSettings, 33 | CameraPerspective, 34 | model_view_projection 35 | }; 36 | 37 | mod demo; 38 | use demo::Settings; 39 | 40 | fn main() { 41 | 42 | env_logger::init(); 43 | 44 | let (win_width, win_height) = (640, 480); 45 | let mut window: PistonWindow = 46 | WindowSettings::new("Skeletal Animation Demo", [win_width, win_height]) 47 | .exit_on_esc(true) 48 | .graphics_api(shader_version::OpenGL::V3_2) 49 | .build() 50 | .unwrap(); 51 | 52 | let mut debug_renderer = { 53 | let text_renderer = { 54 | gfx_text::new(window.factory.clone()).unwrap() 55 | }; 56 | DebugRenderer::new(window.factory.clone(), text_renderer, 64).ok().unwrap() 57 | }; 58 | 59 | let model = mat4_id(); 60 | let mut projection = CameraPerspective { 61 | fov: 90.0f32, 62 | near_clip: 0.1, 63 | far_clip: 1000.0, 64 | aspect_ratio: (win_width as f32) / (win_height as f32) 65 | }.projection(); 66 | 67 | let mut orbit_zoom_camera: OrbitZoomCamera = OrbitZoomCamera::new( 68 | [0.0, 0.0, 0.0], 69 | OrbitZoomCameraSettings::default() 70 | ); 71 | 72 | // Start event loop 73 | 74 | let mut settings = Settings { 75 | 76 | use_dlb: true, 77 | draw_skeleton: true, 78 | draw_labels: false, 79 | draw_mesh: true, 80 | playback_speed: 1.0, 81 | 82 | params: HashMap::new(), 83 | }; 84 | 85 | let mut menu = dev_menu::Menu::::new(); 86 | 87 | menu.add_item(dev_menu::MenuItem::action_item( 88 | "Toggle DLB/LBS Skinning", 89 | Box::new( |ref mut settings| { 90 | settings.use_dlb = !settings.use_dlb; 91 | }) 92 | )); 93 | 94 | menu.add_item(dev_menu::MenuItem::action_item( 95 | "Toggle Skeleton", 96 | Box::new( |ref mut settings| { settings.draw_skeleton = !settings.draw_skeleton; }) 97 | )); 98 | 99 | menu.add_item(dev_menu::MenuItem::action_item( 100 | "Toggle Joint Labels", 101 | Box::new( |ref mut settings| { settings.draw_labels = !settings.draw_labels; }) 102 | )); 103 | 104 | menu.add_item(dev_menu::MenuItem::action_item( 105 | "Toggle Mesh", 106 | Box::new( |ref mut settings| { settings.draw_mesh = !settings.draw_mesh; }) 107 | )); 108 | 109 | menu.add_item(dev_menu::MenuItem::slider_item( 110 | "Playback Speed = ", 111 | [-5.0, 5.0], 112 | 0.01, 113 | Box::new( |ref settings| { settings.playback_speed }), 114 | Box::new( |ref mut settings, value| { settings.playback_speed = value }), 115 | )); 116 | 117 | let mut lbs_demo = { 118 | demo::lbs_demo(&mut window.create_texture_context()) 119 | }; 120 | 121 | let mut dlb_demo = { 122 | demo::dlb_demo(&mut window.create_texture_context()) 123 | }; 124 | 125 | for (param, &value) in dlb_demo.controller.get_parameters().iter() { 126 | settings.params.insert(param.clone(), value); 127 | 128 | // Apparently need to make our own string copies to move into each closure.. 129 | let param_copy_1 = param.clone(); 130 | let param_copy_2 = param.clone(); 131 | 132 | let range = if param == "target-x" || param == "target-y" || param == "target-z" { 133 | [-100.0, 100.0] 134 | } else { 135 | [0.0, 1.0] 136 | }; 137 | 138 | let rate = if param == "target-x" || param == "target-y" || param == "target-z" { 139 | 0.1 140 | } else { 141 | 0.01 142 | }; 143 | 144 | menu.add_item(dev_menu::MenuItem::slider_item( 145 | &format!("Param[{}] = ", param)[..], 146 | range, 147 | rate, 148 | Box::new( move |ref settings| { 149 | settings.params[¶m_copy_1[..]] 150 | }), 151 | Box::new( move |ref mut settings, value| { 152 | settings.params.insert(param_copy_2.clone(), value); 153 | }), 154 | )); 155 | } 156 | 157 | // set head look controller params to nice initial values.. 158 | settings.params.insert("head-look-level".to_string(), 1.0); 159 | settings.params.insert("head-look-sideways-level".to_string(), 1.0); 160 | settings.params.insert("head-down-to-up".to_string(), 0.5); 161 | settings.params.insert("head-left-to-right".to_string(), 0.5); 162 | 163 | while let Some(e) = window.next() { 164 | 165 | orbit_zoom_camera.event(&e); 166 | menu.event(&e, &mut settings); 167 | 168 | e.resize(|args| { 169 | // Update projection matrix 170 | projection = CameraPerspective { 171 | fov: 90.0f32, 172 | near_clip: 0.1, 173 | far_clip: 1000.0, 174 | aspect_ratio: (args.window_size[0] as f32) / (args.window_size[1] as f32) 175 | }.projection(); 176 | }); 177 | 178 | e.update(|args| { 179 | dlb_demo.update(&settings, args.dt); 180 | lbs_demo.update(&settings, args.dt); 181 | }); 182 | 183 | window.draw_3d(&e, |window| { 184 | let args = e.render_args().unwrap(); 185 | 186 | window.encoder.clear(&window.output_color, [0.3, 0.3, 0.3, 1.0]); 187 | window.encoder.clear_depth(&window.output_stencil, 1.0); 188 | 189 | let camera_view = orbit_zoom_camera.camera(args.ext_dt).orthogonal(); 190 | 191 | let camera_projection = model_view_projection( 192 | model, 193 | camera_view, 194 | projection 195 | ); 196 | 197 | // Draw IK target... 198 | let target = [settings.params["target-x"], 199 | settings.params["target-y"], 200 | settings.params["target-z"]]; 201 | 202 | debug_renderer.draw_line(vecmath::vec3_sub(target, [1.0, 0.0, 0.0]), vecmath::vec3_add(target, [1.0, 0.0, 0.0]), [1.0, 1.0, 1.0, 1.0]); 203 | debug_renderer.draw_line(vecmath::vec3_sub(target, [0.0, 1.0, 0.0]), vecmath::vec3_add(target, [0.0, 1.0, 0.0]), [1.0, 1.0, 1.0, 1.0]); 204 | debug_renderer.draw_line(vecmath::vec3_sub(target, [0.0, 0.0, 1.0]), vecmath::vec3_add(target, [0.0, 0.0, 1.0]), [1.0, 1.0, 1.0, 1.0]); 205 | 206 | // Draw axes 207 | debug_renderer.draw_line([0.0, 0.0, 0.0], [5.0, 0.0, 0.0], [1.0, 0.0, 0.0, 1.0]); 208 | debug_renderer.draw_line([0.0, 0.0, 0.0], [0.0, 5.0, 0.0], [0.0, 1.0, 0.0, 1.0]); 209 | debug_renderer.draw_line([0.0, 0.0, 0.0], [0.0, 0.0, 5.0], [0.0, 0.0, 1.0, 1.0]); 210 | 211 | debug_renderer.draw_text_at_position( 212 | "X", 213 | [6.0, 0.0, 0.0], 214 | [1.0, 0.0, 0.0, 1.0], 215 | ); 216 | 217 | debug_renderer.draw_text_at_position( 218 | "Y", 219 | [0.0, 6.0, 0.0], 220 | [0.0, 1.0, 0.0, 1.0], 221 | ); 222 | 223 | debug_renderer.draw_text_at_position( 224 | "Z", 225 | [0.0, 0.0, 6.0], 226 | [0.0, 0.0, 1.0, 1.0], 227 | ); 228 | 229 | dlb_demo.render(&settings, &mut debug_renderer, 230 | &mut window.encoder, &window.output_color, &window.output_stencil, 231 | camera_view, camera_projection, args.ext_dt, settings.use_dlb); 232 | 233 | lbs_demo.render(&settings, &mut debug_renderer, 234 | &mut window.encoder, &window.output_color, &window.output_stencil, 235 | camera_view, camera_projection, args.ext_dt, !settings.use_dlb); 236 | 237 | menu.draw(&settings, &mut debug_renderer); 238 | 239 | if let Err(e) = debug_renderer.render(&mut window.encoder, &window.output_color, &window.output_stencil, camera_projection) { 240 | println!("{:?}", e); 241 | } 242 | }); 243 | } 244 | } 245 | --------------------------------------------------------------------------------