-
Notifications
You must be signed in to change notification settings - Fork 355
/
Tank.cs
executable file
·252 lines (205 loc) · 9.2 KB
/
Tank.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
#region File Description
//-----------------------------------------------------------------------------
// Tank.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion
#region Using Statements
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using XnaGraphicsDemo;
using System;
#endregion
namespace SimpleAnimation
{
/// <summary>
/// Helper class for drawing a tank model with animated wheels and turret.
/// </summary>
public class Tank
{
#region Fields
// The XNA framework Model object that we are going to display.
Model tankModel;
// Shortcut references to the bones that we are going to animate.
// We could just look these up inside the Draw method, but it is more
// efficient to do the lookups while loading and cache the results.
ModelBone leftBackWheelBone;
ModelBone rightBackWheelBone;
ModelBone leftFrontWheelBone;
ModelBone rightFrontWheelBone;
ModelBone leftSteerBone;
ModelBone rightSteerBone;
ModelBone turretBone;
ModelBone cannonBone;
ModelBone hatchBone;
// Store the original transform matrix for each animating bone.
Matrix leftBackWheelTransform;
Matrix rightBackWheelTransform;
Matrix leftFrontWheelTransform;
Matrix rightFrontWheelTransform;
Matrix leftSteerTransform;
Matrix rightSteerTransform;
Matrix turretTransform;
Matrix cannonTransform;
Matrix hatchTransform;
// Array holding all the bone transform matrices for the entire model.
// We could just allocate this locally inside the Draw method, but it
// is more efficient to reuse a single array, as this avoids creating
// unnecessary garbage.
Matrix[] boneTransforms;
// Current animation positions.
float wheelRotationValue;
float steerRotationValue;
float turretRotationValue;
float cannonRotationValue;
float hatchRotationValue;
#endregion
#region Properties
/// <summary>
/// Gets or sets the wheel rotation amount.
/// </summary>
public float WheelRotation
{
get { return wheelRotationValue; }
set { wheelRotationValue = value; }
}
/// <summary>
/// Gets or sets the steering rotation amount.
/// </summary>
public float SteerRotation
{
get { return steerRotationValue; }
set { steerRotationValue = value; }
}
/// <summary>
/// Gets or sets the turret rotation amount.
/// </summary>
public float TurretRotation
{
get { return turretRotationValue; }
set { turretRotationValue = value; }
}
/// <summary>
/// Gets or sets the cannon rotation amount.
/// </summary>
public float CannonRotation
{
get { return cannonRotationValue; }
set { cannonRotationValue = value; }
}
/// <summary>
/// Gets or sets the entry hatch rotation amount.
/// </summary>
public float HatchRotation
{
get { return hatchRotationValue; }
set { hatchRotationValue = value; }
}
#endregion
/// <summary>
/// Loads the tank model.
/// </summary>
public void Load(ContentManager content)
{
// Load the tank model from the ContentManager.
tankModel = content.Load<Model>("tank");
// Look up shortcut references to the bones we are going to animate.
leftBackWheelBone = tankModel.Bones["l_back_wheel_geo"];
rightBackWheelBone = tankModel.Bones["r_back_wheel_geo"];
leftFrontWheelBone = tankModel.Bones["l_front_wheel_geo"];
rightFrontWheelBone = tankModel.Bones["r_front_wheel_geo"];
leftSteerBone = tankModel.Bones["l_steer_geo"];
rightSteerBone = tankModel.Bones["r_steer_geo"];
turretBone = tankModel.Bones["turret_geo"];
cannonBone = tankModel.Bones["canon_geo"];
hatchBone = tankModel.Bones["hatch_geo"];
// Store the original transform matrix for each animating bone.
leftBackWheelTransform = leftBackWheelBone.Transform;
rightBackWheelTransform = rightBackWheelBone.Transform;
leftFrontWheelTransform = leftFrontWheelBone.Transform;
rightFrontWheelTransform = rightFrontWheelBone.Transform;
leftSteerTransform = leftSteerBone.Transform;
rightSteerTransform = rightSteerBone.Transform;
turretTransform = turretBone.Transform;
cannonTransform = cannonBone.Transform;
hatchTransform = hatchBone.Transform;
// Allocate the transform matrix array.
boneTransforms = new Matrix[tankModel.Bones.Count];
}
/// <summary>
/// Animates the tank model.
/// </summary>
/// <param name="gameTime"></param>
public void Animate(GameTime gameTime)
{
float time = (float)gameTime.TotalGameTime.TotalSeconds;
SteerRotation = (float)Math.Sin(time * 0.75f) * 0.5f;
TurretRotation = (float)Math.Sin(time * 0.333f) * 1.25f;
CannonRotation = (float)Math.Sin(time * 0.25f) * 0.333f - 0.333f;
HatchRotation = MathHelper.Clamp((float)Math.Sin(time * 2) * 2, -1, 0);
}
/// <summary>
/// Draws the tank model, using the current animation settings.
/// </summary>
public void Draw(Matrix world, Matrix view, Matrix projection, LightingMode lightMode, bool textureEnable)
{
// Set the world matrix as the root transform of the model.
tankModel.Root.Transform = world;
// Calculate matrices based on the current animation position.
Matrix wheelRotation = Matrix.CreateRotationX(wheelRotationValue);
Matrix steerRotation = Matrix.CreateRotationY(steerRotationValue);
Matrix turretRotation = Matrix.CreateRotationY(turretRotationValue);
Matrix cannonRotation = Matrix.CreateRotationX(cannonRotationValue);
Matrix hatchRotation = Matrix.CreateRotationX(hatchRotationValue);
// Apply matrices to the relevant bones.
leftBackWheelBone.Transform = wheelRotation * leftBackWheelTransform;
rightBackWheelBone.Transform = wheelRotation * rightBackWheelTransform;
leftFrontWheelBone.Transform = wheelRotation * leftFrontWheelTransform;
rightFrontWheelBone.Transform = wheelRotation * rightFrontWheelTransform;
leftSteerBone.Transform = steerRotation * leftSteerTransform;
rightSteerBone.Transform = steerRotation * rightSteerTransform;
turretBone.Transform = turretRotation * turretTransform;
cannonBone.Transform = cannonRotation * cannonTransform;
hatchBone.Transform = hatchRotation * hatchTransform;
// Look up combined bone matrices for the entire model.
tankModel.CopyAbsoluteBoneTransformsTo(boneTransforms);
// Draw the model.
foreach (ModelMesh mesh in tankModel.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.World = boneTransforms[mesh.ParentBone.Index];
effect.View = view;
effect.Projection = projection;
switch (lightMode)
{
case LightingMode.NoLighting:
effect.LightingEnabled = false;
break;
case LightingMode.OneVertexLight:
effect.EnableDefaultLighting();
effect.PreferPerPixelLighting = false;
effect.DirectionalLight1.Enabled = false;
effect.DirectionalLight2.Enabled = false;
break;
case LightingMode.ThreeVertexLights:
effect.EnableDefaultLighting();
effect.PreferPerPixelLighting = false;
break;
case LightingMode.ThreePixelLights:
effect.EnableDefaultLighting();
effect.PreferPerPixelLighting = true;
break;
}
effect.SpecularColor = new Vector3(0.8f, 0.8f, 0.6f);
effect.SpecularPower = 16;
effect.TextureEnabled = textureEnable;
}
mesh.Draw();
}
}
}
}