00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 using System;
00018 using System.Collections.Generic;
00019 using System.Text;
00020 using System.IO;
00021 using Microsoft.DirectX;
00022 using Microsoft.DirectX.Direct3D;
00023 using Microsoft.Samples.DirectX.UtilityToolkit;
00024
00025 namespace DXGfxLib
00026 {
00032 internal class EnhancedFrame : Frame
00033 {
00038 public Matrix frameWorldMat;
00039
00044 public AABBox boundingBox;
00045
00050 public EnhancedFrame()
00051 {
00052 frameWorldMat = Matrix.Identity;
00053 }
00054 }
00055
00061 internal class EnhancedMeshContainer : MeshContainer
00062 {
00066 public Mesh oriMesh = null;
00067
00071 public bool hasSkin = false;
00072
00076 public Mesh BlendedMesh;
00077
00082 public BoneCombination[] BoneCombinations;
00083
00084 public int numMaterials = 0;
00088 public Microsoft.DirectX.Direct3D.Material[] materials;
00089
00093 public Texture[] textures;
00094
00098 public int MaxFaceInfluences = 0;
00099
00104 public Matrix[] BoneOffsetMatrices;
00105
00110 public EnhancedFrame[] AffectingBones;
00111
00115 public EffectInstance[] EffectInstances;
00116
00120 public AABBox localBoundingBox;
00121 }
00122
00127 internal class EnhancedAllocateHierarchy : AllocateHierarchy
00128 {
00129 public override Frame CreateFrame(string name)
00130 {
00131 EnhancedFrame frame = new EnhancedFrame();
00132 frame.Name = name;
00133
00134 return frame;
00135 }
00136
00137 public override MeshContainer CreateMeshContainer(string name, MeshData meshData, ExtendedMaterial[] materials, EffectInstance[] effectInstances, GraphicsStream adjacency, SkinInformation skinInfo)
00138 {
00139 EnhancedMeshContainer container = new EnhancedMeshContainer();
00140
00141 container.Name = name;
00142
00143
00144 container.MeshData = meshData;
00145
00146
00147 container.oriMesh = meshData.Mesh;
00148 container.localBoundingBox = AABBox.CalculateLocalBBox(container.oriMesh);
00149
00150
00151
00152 if (materials != null)
00153 container.SetMaterials(materials);
00154
00155
00156 if (skinInfo != null)
00157 container.SkinInformation = skinInfo;
00158
00159
00160 if (effectInstances != null)
00161 container.EffectInstances = effectInstances;
00162
00163
00164 if (adjacency != null)
00165 container.SetAdjacency(adjacency);
00166 else
00167 {
00168 throw new NullReferenceException("adjancy null!");
00169 }
00170
00171
00172 if (materials != null)
00173 {
00174 container.materials = new Microsoft.DirectX.Direct3D.Material[materials.Length];
00175 container.textures = new Texture[materials.Length];
00176 container.numMaterials = materials.Length;
00177
00178 for (int i = 0; i < materials.Length; i++)
00179 {
00180
00181 container.materials[i] = materials[i].Material3D;
00182
00183
00184 container.materials[i].Ambient = container.materials[i].Diffuse;
00185
00186
00187 if (materials[i].TextureFilename != null)
00188 {
00189 if (File.Exists(materials[i].TextureFilename))
00190 container.textures[i] = ResourceCache.GetGlobalInstance().CreateTextureFromFile(ArticulatedModel.currentDevice, materials[i].TextureFilename);
00191 else
00192 {
00193 throw new Exception("Texture file for material not found!");
00194 }
00195 }
00196 }
00197 }
00198
00199 if (skinInfo != null)
00200 {
00201 container.BoneOffsetMatrices = new Matrix[skinInfo.NumberBones];
00202
00203 for (int i = 0; i < skinInfo.NumberBones; i++)
00204 container.BoneOffsetMatrices[i] = skinInfo.GetBoneOffsetMatrix(i);
00205
00206 container.BlendedMesh = skinInfo.ConvertToBlendedMesh(
00207 container.MeshData.Mesh, MeshFlags.Managed, container.GetAdjacencyStream(),
00208 out container.MaxFaceInfluences, out container.BoneCombinations);
00209 }
00210
00211 return container;
00212 }
00213 }
00214
00220 public class ArticulatedModel : MeshObject
00221 {
00226 public static Device currentDevice = null;
00227
00232 protected AnimationRootFrame rootFrame;
00233
00238 public bool HasSkin = false;
00239
00243 private int currentAnimationTrack = 1;
00244
00249 public float animationTransitionTime = 0.5f;
00250
00257 public double currentTime;
00258
00266 public ArticulatedModel()
00267 {
00268 }
00269
00279 public override void LoadFromFile(Device d3ddevice, string fileName)
00280 {
00281
00282
00283
00284
00285 currentDevice = d3ddevice;
00286 rootFrame = Mesh.LoadHierarchyFromFile(fileName, MeshFlags.Managed, d3ddevice, new EnhancedAllocateHierarchy(), null);
00287
00288 SetupBonePointersOnMesh(rootFrame.FrameHierarchy);
00289 }
00290
00297 protected void SetupBonePointersOnMesh(Frame frame)
00298 {
00299
00300 if (frame.MeshContainer != null)
00301 {
00302 EnhancedMeshContainer meshContainer = (EnhancedMeshContainer)frame.MeshContainer;
00303 SkinInformation skinInformation = meshContainer.SkinInformation;
00304
00305 if (skinInformation != null)
00306 {
00307 HasSkin = true;
00308 meshContainer.AffectingBones = new EnhancedFrame[skinInformation.NumberBones];
00309
00310 for (int i = 0; i < skinInformation.NumberBones; i++)
00311 {
00312 EnhancedFrame affectingBone = (EnhancedFrame)Frame.Find(rootFrame.FrameHierarchy,
00313 skinInformation.GetBoneName(i));
00314 meshContainer.AffectingBones[i] = affectingBone;
00315 }
00316 }
00317 }
00318
00319
00320 if (frame.FrameSibling != null) SetupBonePointersOnMesh(frame.FrameSibling);
00321
00322 if (frame.FrameFirstChild != null) SetupBonePointersOnMesh(frame.FrameFirstChild);
00323 }
00324
00335 public override void Update(Frustrum frustrum, double appTime, float elapsedTime)
00336 {
00337 base.Update(frustrum, appTime, elapsedTime);
00338
00339 rootFrame.AnimationController.AdvanceTime(elapsedTime, null);
00340 UpdateFrameMatrices(rootFrame.FrameHierarchy, WorldMat);
00341 }
00342
00349 protected void UpdateFrameMatrices(Frame frame, Matrix parentMat)
00350 {
00351 BBox framebbox = null;
00352
00353 EnhancedFrame enhancedFrame = frame as EnhancedFrame;
00354 if (enhancedFrame != null)
00355 {
00356 enhancedFrame.frameWorldMat = Matrix.Multiply(frame.TransformationMatrix, parentMat);
00357 if (enhancedFrame.MeshContainer != null)
00358 {
00359 EnhancedMeshContainer enMeshCont = enhancedFrame.MeshContainer as EnhancedMeshContainer;
00360 if (enMeshCont != null)
00361 {
00362 framebbox = enMeshCont.localBoundingBox.Transform(enhancedFrame.frameWorldMat);
00363 }
00364 }
00365 }
00366
00367 if (frame.FrameSibling != null)
00368 {
00369 UpdateFrameMatrices(frame.FrameSibling, parentMat);
00370 EnhancedFrame enFrame = frame.FrameSibling as EnhancedFrame;
00371 if (enFrame != null)
00372 {
00373 if (framebbox != null)
00374 {
00375 framebbox = AABBox.BoxFromBoxes(new AABBox(framebbox), enFrame.boundingBox);
00376 }
00377 else
00378 {
00379 framebbox = enFrame.boundingBox;
00380 }
00381 }
00382 }
00383
00384 if ((frame.FrameFirstChild != null) && (enhancedFrame != null))
00385 {
00386 UpdateFrameMatrices(frame.FrameFirstChild, enhancedFrame.frameWorldMat);
00387 EnhancedFrame enFrame = frame.FrameFirstChild as EnhancedFrame;
00388 if (enFrame != null)
00389 {
00390 if (framebbox != null)
00391 {
00392 framebbox = AABBox.BoxFromBoxes(new AABBox(framebbox), enFrame.boundingBox);
00393 }
00394 else
00395 {
00396 framebbox = enFrame.boundingBox;
00397 }
00398 }
00399 }
00400
00401 if (enhancedFrame != null)
00402 {
00403 if (framebbox == null)
00404 {
00405 framebbox = new BBox();
00406 }
00407 enhancedFrame.boundingBox = new AABBox(framebbox);
00408 }
00409 }
00410
00418 protected void RenderFrame(Device d3ddevice, Frame frame)
00419 {
00420
00421 if (frame.MeshContainer != null)
00422 {
00423 EnhancedMeshContainer meshContainer = (EnhancedMeshContainer)frame.MeshContainer;
00424
00425
00426 if (meshContainer.SkinInformation == null)
00427 {
00428 EnhancedFrame frameDerived = (EnhancedFrame)frame;
00429 d3ddevice.SetTransform(TransformType.World, frameDerived.frameWorldMat);
00430 for (int i = 0; i < meshContainer.materials.Length; i++)
00431 {
00432 d3ddevice.Material = meshContainer.materials[i];
00433 if (meshContainer.textures[i] != null)
00434 d3ddevice.SetTexture(0, meshContainer.textures[i]);
00435 meshContainer.MeshData.Mesh.DrawSubset(i);
00436 }
00437 }
00438
00439 else
00440 {
00441
00442 int lastAttribId = -1;
00443 for (int j = 0; j < meshContainer.BoneCombinations.Length; j++)
00444 {
00445 BoneCombination boneCombination = meshContainer.BoneCombinations[j];
00446
00447 d3ddevice.SetTransform(TransformType.World, Matrix.Identity);
00448 d3ddevice.SetTransform(TransformType.World1, Matrix.Identity);
00449 d3ddevice.SetTransform(TransformType.World2, Matrix.Identity);
00450 d3ddevice.SetTransform(TransformType.World3, Matrix.Identity);
00451
00452
00453 int blendCount = 0;
00454 for (int i = 0; i < meshContainer.MaxFaceInfluences; i++)
00455 {
00456 int boneMatrixId = boneCombination.BoneId[i];
00457
00458 if (boneMatrixId != -1)
00459 {
00460 blendCount = i;
00461
00462 Matrix transformMatrix = Matrix.Multiply(meshContainer.BoneOffsetMatrices[boneMatrixId],
00463 meshContainer.AffectingBones[boneMatrixId].frameWorldMat);
00464
00465 if (i == 0) d3ddevice.SetTransform(TransformType.World, transformMatrix);
00466 else if (i == 1) d3ddevice.SetTransform(TransformType.World1, transformMatrix);
00467 else if (i == 2) d3ddevice.SetTransform(TransformType.World2, transformMatrix);
00468 else if (i == 3) d3ddevice.SetTransform(TransformType.World3, transformMatrix);
00469 }
00470 }
00471
00472
00473 if (blendCount == 1) d3ddevice.RenderState.VertexBlend = VertexBlend.OneWeights;
00474 else if (blendCount == 2) d3ddevice.RenderState.VertexBlend = VertexBlend.TwoWeights;
00475 else if (blendCount == 3) d3ddevice.RenderState.VertexBlend = VertexBlend.ThreeWeights;
00476 else d3ddevice.RenderState.VertexBlend = VertexBlend.Disable;
00477
00478
00479 if (lastAttribId != boneCombination.AttributeId)
00480 {
00481 lastAttribId = boneCombination.AttributeId;
00482 d3ddevice.Material = meshContainer.materials[lastAttribId];
00483 d3ddevice.SetTexture(0, meshContainer.textures[lastAttribId]);
00484 }
00485
00486
00487 meshContainer.BlendedMesh.DrawSubset(j);
00488 }
00489
00490
00491 d3ddevice.RenderState.VertexBlend = VertexBlend.Disable;
00492 }
00493 }
00494
00495
00496 if (frame.FrameSibling != null) RenderFrame(d3ddevice, frame.FrameSibling);
00497 if (frame.FrameFirstChild != null) RenderFrame(d3ddevice, frame.FrameFirstChild);
00498 }
00499
00504 public override void Draw(Device device)
00505 {
00506 device.SetTransform(TransformType.World, worldMat);
00507 RenderFrame(device, rootFrame.FrameHierarchy);
00508 }
00509
00514 public List<String> GetAnimationList()
00515 {
00516 List<String> animations = new List<string>();
00517 for (int i = 0; i < rootFrame.AnimationController.MaxNumberAnimationSets; i++)
00518 {
00519 animations.Add(rootFrame.AnimationController.GetAnimationSet(i).Name);
00520 }
00521 return animations;
00522 }
00523
00531 public void StartAnimation(string animationName)
00532 {
00533 AnimationSet animSet = rootFrame.AnimationController.GetAnimationSet(animationName);
00534
00535 if (animSet == null)
00536 {
00537 return;
00538 }
00539
00540 int newAnimationTrack = (currentAnimationTrack == 0 ? 1 : 0);
00541
00542 rootFrame.AnimationController.SetTrackAnimationSet(newAnimationTrack, animSet);
00543
00544 rootFrame.AnimationController.UnkeyAllTrackEvents(currentAnimationTrack);
00545 rootFrame.AnimationController.UnkeyAllTrackEvents(newAnimationTrack);
00546
00547 rootFrame.AnimationController.KeyTrackEnable(currentAnimationTrack, false, currentTime + animationTransitionTime);
00548 rootFrame.AnimationController.KeyTrackSpeed(currentAnimationTrack, 0.0f, currentTime, animationTransitionTime, TransitionType.Linear);
00549 rootFrame.AnimationController.KeyTrackWeight(currentAnimationTrack, 0.0f, currentTime, animationTransitionTime, TransitionType.Linear);
00550
00551 rootFrame.AnimationController.KeyTrackEnable(newAnimationTrack, true, currentTime + animationTransitionTime);
00552 rootFrame.AnimationController.KeyTrackSpeed(newAnimationTrack, 1.0f, currentTime, animationTransitionTime, TransitionType.Linear);
00553 rootFrame.AnimationController.KeyTrackWeight(newAnimationTrack, 1.0f, currentTime, animationTransitionTime, TransitionType.Linear);
00554
00555 currentAnimationTrack = newAnimationTrack;
00556
00557 }
00558
00564 public void StopAll()
00565 {
00566 rootFrame.AnimationController.UnkeyAllTrackEvents(currentAnimationTrack);
00567
00568 rootFrame.AnimationController.KeyTrackEnable(currentAnimationTrack, false, currentTime + animationTransitionTime);
00569 rootFrame.AnimationController.KeyTrackSpeed(currentAnimationTrack, 0.0f, currentTime, animationTransitionTime, TransitionType.Linear);
00570 rootFrame.AnimationController.KeyTrackWeight(currentAnimationTrack, 0.0f, currentTime, animationTransitionTime, TransitionType.Linear);
00571 }
00572 }
00573 }