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<XSIAnimationContent> Animations;
int AnimationIndex = 0;
Matrix world;
float animStart = 0.0f;
float nextAnimation = 0.0f;
float currentAnimLength;
float lastTime = 0.0f;
Matrix[] transforms;
Matrix[] bones;
/// <summary>
///
/// </summary>
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<Model>(sz))
{
}
public RenderEntityModule( Model m)
{
//model = ContentLoader.Load<Model>(sz);
model = m;
Animations
= new List
<XSIAnimationContent
>();
XSIAnimationData l_Animations = model.Tag as XSIAnimationData;
if (l_Animations != null)
{
foreach (KeyValuePair<String, XSIAnimationContent> 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;
}
/// <summary>
/// Sets the animation for the model
/// </summary>
/// <param name="animationIndex">The index of the animation to play</param>
/// <param name="time">The length of the animation</param>
/// <param name="overrideAnim">If set to true, the new animation will play regardless.</param>
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);
}
}
}
}
}