- Main Page
- Packages
- Classes
- Files

- File List
- File Members

# D:/guillaume/guillara/3D/DXGfx/DXGfxLib/ArticulatedModel.cs

Go to the documentation of this file.

    00001 //BSD License
    00002 //DXGfx® - http://www.eteractions.com
    00003 //Copyright (c) 2005
    00004 //by Guillaume Randon
    00005 //Permission is hereby granted, free of charge, to any person obtaining a copy of this software
    00006 //and associated documentation files (the "Software"), to deal in the Software without restriction,
    00007 //including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
    00008 //and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
    00009 //subject to the following conditions:
    00010 //The above copyright notice and this permission notice shall be included in all copies or substantial
    00011 //portions of the Software.
    00012 //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
    00013 //INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
    00014 //AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
    00015 //DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    00016 //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    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             // meshData
    00144             container.MeshData = meshData;
    00145
    00146
    00147             container.oriMesh = meshData.Mesh;
    00148             container.localBoundingBox = AABBox.CalculateLocalBBox(container.oriMesh);
    00149
    00150
    00151             // materials
    00152             if (materials != null)
    00153                 container.SetMaterials(materials);
    00154
    00155             // skinInfo
    00156             if (skinInfo != null)
    00157                 container.SkinInformation = skinInfo;
    00158
    00159             // effectIntances
    00160             if (effectInstances != null)
    00161                 container.EffectInstances = effectInstances;
    00162
    00163             // adjacency
    00164             if (adjacency != null)
    00165                 container.SetAdjacency(adjacency);
    00166             else
    00167             {
    00168                 throw new NullReferenceException("adjancy null!");
    00169             }
    00170
    00171             // materials and textures
    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                     // Copy the material
    00181                     container.materials[i] = materials[i].Material3D;
    00182
    00183                     // Set the ambient color for the material (D3DX does not do this)
    00184                     container.materials[i].Ambient = container.materials[i].Diffuse;
    00185
    00186                     // Create the texture
    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             // This will be used to populate fields used by SceneObject code (intersections and everything which at the moment
    00282             // have not been overriden (yet)).
    00283             //Attach(new FrameworkMesh(d3ddevice, fileName));
    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             // If this frame has a mesh container, store pointers to all frames (bones) that affect this mesh.
    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             // Perform this operation recursively
    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             // Check if this is a mesh frame
    00421             if (frame.MeshContainer != null)
    00422             {
    00423                 EnhancedMeshContainer meshContainer = (EnhancedMeshContainer)frame.MeshContainer;
    00424
    00425                 // Standard mesh. Draw it the simple way.
    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                 // Animated mesh.
    00439                 else
    00440                 {
    00441                     // Loop all mesh subsets (bone combinations)
    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                         // Set the matrices for this subset
    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                         // Set vertex blend count
    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                         // If the material is different than the last subset, update the device material
    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                         // Render the mesh
    00487                         meshContainer.BlendedMesh.DrawSubset(j);
    00488                     }
    00489
    00490                     // Rendering is finished, set the vertex blending back to disabled mode
    00491                     d3ddevice.RenderState.VertexBlend = VertexBlend.Disable;
    00492                 }
    00493             }
    00494
    00495             // Do this recursively on all child Frames and all Frames at the same level.
    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 }