using System; using System.Collections.Generic; using System.Text; using Engine.Source.Client.Content; using Engine.Source.Client; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Engine.Source.Client.BatchRendering; using Engine.Source.Client.Cubemaps; using Engine.Source.Client.Lighting; using XSIXNARuntime; namespace Engine.Source.Shared.Entities { public class RenderEntityModule : IBatchRenderObject { Model model; public Model Model { get { return model; } } List Animations; int AnimationIndex = 0; Matrix world; float animStart = 0.0f; float nextAnimation = 0.0f; float currentAnimLength; float lastTime = 0.0f; Matrix[] transforms; Matrix[] bones; /// /// /// public bool OverrideView = false; public float animSpeed = 32f; public bool refreshWorld = false; Vector3 scale = Vector3.One; Vector3 rotation = Vector3.Zero; Vector3 translation = Vector3.Zero; IBatchRenderService BatchRender; ICubeMapService CubeMaps; ILightingService Lighting; Vector3 forceRenderPosition = Vector3.Zero; Vector3 forceAmbient = Vector3.Zero; public Vector3 Scale { get { return scale; } set { scale = value; refreshWorld = true; } } public Vector3 Rotation { get { return rotation; } set { rotation = value; refreshWorld = true; } } public Vector3 Translation { get { return translation; } set { translation = value; refreshWorld = true; } } public float Speed { get { return animSpeed; } set { animSpeed = value; } } public Matrix World { get { return world; } set { world = value; } } public void ForceRenderPosition(Vector3 pos) { forceRenderPosition = pos; } public void ForceAmbient(Vector3 ambientColor) { forceAmbient = ambientColor; } public RenderEntityModule(string sz) : this(ContentLoader.Load(sz)) { } public RenderEntityModule( Model m) { //model = ContentLoader.Load(sz); model = m; Animations = new List(); XSIAnimationData l_Animations = model.Tag as XSIAnimationData; if (l_Animations != null) { foreach (KeyValuePair AnimationClip in l_Animations.RuntimeAnimationContentDictionary) { AnimationClip.Value.BindModelBones(model); Animations.Add(AnimationClip.Value); } //model.CopyAbsoluteBoneTransformsTo(transforms); //l_Animations.ComputeBoneTransforms(transforms); } l_Animations.ResolveBones(model); transforms = new Matrix[model.Bones.Count]; BatchRender = (IBatchRenderService)(GameManager.Game.Services.GetService(typeof(IBatchRenderService))); CubeMaps = (ICubeMapService)(GameManager.Game.Services.GetService(typeof(ICubeMapService))); Lighting = (ILightingService)(GameManager.Game.Services.GetService(typeof(ILightingService))); } public int GetBoneIndex(string sz) { return model.Bones[sz].Index; } public Matrix GetTransform(int index) { return Matrix.CreateTranslation(this.transforms[index].Translation) * this.World; } /// /// Sets the animation for the model /// /// The index of the animation to play /// The length of the animation /// If set to true, the new animation will play regardless. public void SetAnimation(int animationIndex, float time, bool overrideAnim) { if (overrideAnim || nextAnimation <= lastTime) { AnimationIndex = animationIndex; Animations[AnimationIndex].Reset(); currentAnimLength = time; nextAnimation = lastTime + time; animStart = lastTime; } //Animations[AnimationIndex]. } public void StopAnimation(bool overrideAnim) { if (overrideAnim || nextAnimation <= lastTime) { AnimationIndex = -1; } } public void Update(double gameTime) { lastTime = (float)gameTime; if (CubeMaps == null) CubeMaps = (ICubeMapService)(GameManager.Game.Services.GetService(typeof(ICubeMapService))); } void AnimationUpdate() { if (AnimationIndex == -1) return; Animations[AnimationIndex].PlayBack(TimeSpan.FromSeconds((lastTime - animStart) / animSpeed ), 1.0f); if (Animations[AnimationIndex].Loop == true && nextAnimation < lastTime) { Animations[AnimationIndex].Reset(); nextAnimation = lastTime + currentAnimLength; animStart = lastTime; } } public void RenderCallback(Effect effect, int i) { AnimationUpdate(); XSIAnimationData l_Animations = model.Tag as XSIAnimationData; model.CopyAbsoluteBoneTransformsTo(transforms); l_Animations.ComputeBoneTransforms(transforms); bones = l_Animations.BoneTransforms; bool isSkinned = (bones.GetLength(0) > 0); if ((effect.Parameters["Bones"] != null) && isSkinned) effect.Parameters["Bones"].SetValue(bones); //Matrix world = Matrix.CreateTranslation(Vector3.Zero) * Matrix.CreateScale(0.25f); effect.Parameters["Model"].SetValue(transforms[model.Meshes[i].ParentBone.Index] * world); Vector3 renderPos = this.world.Translation; if (forceRenderPosition != Vector3.Zero) renderPos = forceRenderPosition; if (CubeMaps != null) { TextureCube tc = CubeMaps.GetNearestCubeMap(renderPos); //tc = CubeMaps.GetCubeMapByIndex(0); if (tc != null) effect.Parameters["EnvironmentMap"].SetValue(tc); } if (OverrideView) effect.Parameters["View"].SetValue(Matrix.Identity); Vector4 lightPos0 = Vector4.Zero + Vector4.UnitY * 10.0f; Vector4 lightPos1 = Vector4.UnitX * 10.0f; Vector4 lightPos2 = Vector4.UnitZ * 10.0f; Vector4 Color1 = new Vector4(Vector3.One, 0.25f); Vector4 Color2 = new Vector4(Vector3.One, 0.2f); Vector4 Color0 = new Vector4(Vector3.One, 0.2f); Vector3 ambientColor = new Vector3(0.5f); if (Lighting.AmbientLighting != null) { AmbientLightData ald = Lighting.AmbientLighting.GetAmbientLighting(renderPos); ambientColor = ald.AmbientColor; if (forceAmbient != Vector3.Zero) ambientColor = forceAmbient; } effect.Parameters["AmbientColor"].SetValue(ambientColor); //effect.Parameters["lightpos0"].SetValue(lightPos0); //effect.Parameters["lightpos1"].SetValue(lightPos1); //effect.Parameters["lightpos2"].SetValue(lightPos2); //effect.Parameters["lightcol0"].SetValue(Color0); //effect.Parameters["lightcol1"].SetValue(Color1); //effect.Parameters["lightcol2"].SetValue(Color2); effect.CommitChanges(); ModelMesh mesh = model.Meshes[i]; effect.GraphicsDevice.Indices = mesh.IndexBuffer; for (int j = 0; j < mesh.MeshParts.Count; j++) { ModelMeshPart part = mesh.MeshParts[j]; effect.GraphicsDevice.Vertices[0].SetSource(mesh.VertexBuffer, part.StreamOffset, part.VertexStride); effect.GraphicsDevice.VertexDeclaration = part.VertexDeclaration; effect.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, part.BaseVertex, 0, part.NumVertices, part.StartIndex, part.PrimitiveCount); } } public void Render() { if (refreshWorld) world = Matrix.CreateScale(scale) * Matrix.CreateFromYawPitchRoll(rotation.X, rotation.Y, rotation.Z) * Matrix.CreateTranslation(translation); AnimationUpdate(); XSIAnimationData l_Animations = model.Tag as XSIAnimationData; model.CopyAbsoluteBoneTransformsTo(transforms); l_Animations.ComputeBoneTransforms(transforms); bones = l_Animations.BoneTransforms; bool isSkinned = (bones.GetLength(0) > 0); for(int i = 0; i < model.Meshes.Count; i++) { foreach (Effect effect in model.Meshes[i].Effects) { EffectTechnique tech; if (isSkinned) tech = effect.Techniques["Skinned"]; else tech = effect.Techniques["Static"]; BatchRender.BatchRender(effect, tech, i, this); } } } } }