307 lines
13 KiB
C#
307 lines
13 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using Aiwaz.Contracts;
|
|
using Aiwaz.Resources.Attributes;
|
|
|
|
namespace Aiwaz.Resources
|
|
{
|
|
public class TransformationBindings : ICreationParams
|
|
{
|
|
public string WorldMatrixSemanticName;
|
|
public string LocalMatrixSemanticName;
|
|
|
|
public string WorldPositionSemanticName;
|
|
public string LocalPositionSemanticName;
|
|
|
|
public string WorldDirectionSemanticName;
|
|
public string LocalDirectionSemanticName;
|
|
|
|
public string WorldUpDirectionSemanticName;
|
|
public string LocalUpDirectionSemanticName;
|
|
|
|
public string WorldRightDirectionSemanticName;
|
|
public string LocalRightDirectionSemanticName;
|
|
}
|
|
|
|
[CreationParameters("Default transformation")]
|
|
public class DefaultTransformationBindings : TransformationBindings
|
|
{
|
|
public DefaultTransformationBindings()
|
|
{
|
|
WorldMatrixSemanticName = "WorldMatrix";
|
|
LocalMatrixSemanticName = "LocalMatrix";
|
|
WorldPositionSemanticName = "WorldPosition";
|
|
LocalPositionSemanticName = "LocalPosition";
|
|
WorldDirectionSemanticName = "WorldDirection";
|
|
LocalDirectionSemanticName = "LocalDirection";
|
|
WorldUpDirectionSemanticName = "WorldUpDirection";
|
|
LocalUpDirectionSemanticName = "LocalUpDirection";
|
|
WorldRightDirectionSemanticName = "WorldUpDirection";
|
|
LocalRightDirectionSemanticName = "LocalUpDirection";
|
|
}
|
|
}
|
|
|
|
[CreationParameters("Camera transformation")]
|
|
public class CameraTransformationBindings : TransformationBindings
|
|
{
|
|
public CameraTransformationBindings()
|
|
{
|
|
WorldPositionSemanticName = "CamPos";
|
|
WorldDirectionSemanticName = "CamDir";
|
|
}
|
|
}
|
|
|
|
[AiwazResource("Transformation", "Common transformations for a shader and geometry buffers like position, scale and rotation.")]
|
|
public class Transformation : ShaderParameterSet, IUpdatable
|
|
{
|
|
#region ITransformation Members
|
|
|
|
Reference worldMatrixRef = new Reference(new SlimDX.Matrix());
|
|
Reference worldPositionRef = new Reference(new SlimDX.Vector3());
|
|
Reference worldDirectionRef = new Reference(new SlimDX.Vector3());
|
|
Reference worldUpDirectionRef = new Reference(new SlimDX.Vector3());
|
|
Reference worldRightDirectionRef = new Reference(new SlimDX.Vector3());
|
|
|
|
Reference localMatrixRef = new Reference(new SlimDX.Matrix());
|
|
Reference localPositionRef = new Reference(new SlimDX.Vector3());
|
|
Reference localDirectionRef = new Reference(new SlimDX.Vector3());
|
|
Reference localUpDirectionRef = new Reference(new SlimDX.Vector3());
|
|
Reference localRightDirectionRef = new Reference(new SlimDX.Vector3());
|
|
|
|
private TransformationBindings transformationBindings;
|
|
private SlimDX.Vector3 lastKnownYawPitchRoll;
|
|
private SlimDX.Quaternion localRotation;
|
|
private SlimDX.Vector3 localScale;
|
|
private Transformation transformationParent;
|
|
private List<Transformation> transformations = new List<Transformation>();
|
|
|
|
private Transformation()
|
|
: base(5)
|
|
{
|
|
}
|
|
|
|
private Transformation(TransformationBindings transformationBindings)
|
|
: this()
|
|
{
|
|
this.WorldScale = this.LocalScale = new SlimDX.Vector3(1.0f, 1.0f, 1.0f);
|
|
this.LocalDirection = this.WorldDirection = new SlimDX.Vector3(0.0f, 0.0f, 1.0f);
|
|
this.LocalUpDirection = this.WorldUpDirection = new SlimDX.Vector3(0.0f, 1.0f, 0.0f);
|
|
this.LocalRightDirection = this.WorldRightDirection = new SlimDX.Vector3(1.0f, 0.0f, 0.0f);
|
|
this.TransformationBindings = transformationBindings;
|
|
}
|
|
|
|
public Transformation(DefaultTransformationBindings transformationBindings)
|
|
: this((TransformationBindings)transformationBindings)
|
|
{
|
|
}
|
|
|
|
public Transformation(CameraTransformationBindings transformationBindings)
|
|
: this((TransformationBindings)transformationBindings)
|
|
{
|
|
}
|
|
|
|
public TransformationBindings TransformationBindings
|
|
{
|
|
get { return transformationBindings; }
|
|
set
|
|
{
|
|
transformationBindings = value;
|
|
|
|
baseShaderParameterSet.RemoveAllShaderParameters();
|
|
this.RecreateAllShaderParameters();
|
|
}
|
|
}
|
|
|
|
|
|
public SlimDX.Vector3 LocalPosition
|
|
{
|
|
get { return (SlimDX.Vector3)localPositionRef.RawValue; }
|
|
set
|
|
{
|
|
localPositionRef.RawValue = value;
|
|
WantsUpdate = true;
|
|
}
|
|
}
|
|
|
|
public SlimDX.Vector3 WorldPosition { get { return (SlimDX.Vector3)worldPositionRef.RawValue; } protected set { worldPositionRef.RawValue = value; } }
|
|
|
|
public SlimDX.Vector3 LocalRotationYPR
|
|
{
|
|
get
|
|
{
|
|
return lastKnownYawPitchRoll;
|
|
}
|
|
set
|
|
{
|
|
lastKnownYawPitchRoll = value;
|
|
LocalRotation = SlimDX.Quaternion.RotationYawPitchRoll(value.X, value.Y, value.Z);
|
|
|
|
WantsUpdate = true;
|
|
}
|
|
}
|
|
|
|
public SlimDX.Quaternion LocalRotation
|
|
{
|
|
get { return localRotation; }
|
|
set
|
|
{
|
|
localRotation = value;
|
|
WantsUpdate = true;
|
|
}
|
|
}
|
|
|
|
public SlimDX.Quaternion WorldRotation { get; protected set; }
|
|
|
|
public SlimDX.Vector3 LocalDirection { get { return (SlimDX.Vector3)localDirectionRef.RawValue; } protected set { localDirectionRef.RawValue = value; } }
|
|
|
|
public SlimDX.Vector3 WorldDirection { get { return (SlimDX.Vector3)worldDirectionRef.RawValue; } protected set { worldDirectionRef.RawValue = value; } }
|
|
|
|
public SlimDX.Vector3 LocalUpDirection { get { return (SlimDX.Vector3)localUpDirectionRef.RawValue; } protected set { localUpDirectionRef.RawValue = value; } }
|
|
|
|
public SlimDX.Vector3 WorldUpDirection { get { return (SlimDX.Vector3)worldUpDirectionRef.RawValue; } protected set { worldUpDirectionRef.RawValue = value; } }
|
|
|
|
public SlimDX.Vector3 LocalRightDirection { get { return (SlimDX.Vector3)localRightDirectionRef.RawValue; } protected set { localRightDirectionRef.RawValue = value; } }
|
|
|
|
public SlimDX.Vector3 WorldRightDirection { get { return (SlimDX.Vector3)worldRightDirectionRef.RawValue; } protected set { worldRightDirectionRef.RawValue = value; } }
|
|
|
|
public SlimDX.Vector3 LocalScale
|
|
{
|
|
get { return localScale; }
|
|
set
|
|
{
|
|
localScale = value;
|
|
WantsUpdate = true;
|
|
}
|
|
}
|
|
|
|
public SlimDX.Vector3 WorldScale { get; protected set; }
|
|
|
|
public SlimDX.Matrix WorldMatrix { get { return (SlimDX.Matrix)worldMatrixRef.RawValue; } protected set { worldMatrixRef.RawValue = value; } }
|
|
|
|
public SlimDX.Matrix LocalMatrix { get { return (SlimDX.Matrix)localMatrixRef.RawValue; } protected set { localMatrixRef.RawValue = value; } }
|
|
|
|
public Transformation TransformationParent
|
|
{
|
|
get { return transformationParent; }
|
|
set
|
|
{
|
|
var oldTransformationParent = transformationParent;
|
|
transformationParent = value;
|
|
WantsUpdate = true;
|
|
|
|
if (oldTransformationParent != null)
|
|
oldTransformationParent.RemoveTransformation(this);
|
|
}
|
|
}
|
|
|
|
|
|
public IEnumerable<Transformation> Transformations { get { return transformations; } }
|
|
|
|
public void AddTransformation(Transformation transformation)
|
|
{
|
|
if (!transformations.Contains(transformation))
|
|
{
|
|
transformation.TransformationParent = this;
|
|
transformations.Add(transformation);
|
|
WantsUpdate = true;
|
|
}
|
|
}
|
|
|
|
public void RemoveTransformation(Transformation transformation)
|
|
{
|
|
if (transformations.Remove(transformation))
|
|
transformation.TransformationParent = null;
|
|
}
|
|
|
|
protected virtual void RecreateAllShaderParameters()
|
|
{
|
|
if (transformationBindings == null)
|
|
return;
|
|
if (!string.IsNullOrEmpty(transformationBindings.WorldMatrixSemanticName))
|
|
this.SetParameter(transformationBindings.WorldMatrixSemanticName, worldMatrixRef, ParameterBindType.BindBySemantic);
|
|
if (!string.IsNullOrEmpty(transformationBindings.LocalMatrixSemanticName))
|
|
this.SetParameter(transformationBindings.LocalMatrixSemanticName, localMatrixRef, ParameterBindType.BindBySemantic);
|
|
|
|
if (!string.IsNullOrEmpty(transformationBindings.WorldPositionSemanticName))
|
|
this.SetParameter(transformationBindings.WorldPositionSemanticName, worldPositionRef, ParameterBindType.BindBySemantic);
|
|
if (!string.IsNullOrEmpty(transformationBindings.LocalPositionSemanticName))
|
|
this.SetParameter(transformationBindings.LocalPositionSemanticName, localPositionRef, ParameterBindType.BindBySemantic);
|
|
|
|
if (!string.IsNullOrEmpty(transformationBindings.WorldDirectionSemanticName))
|
|
this.SetParameter(transformationBindings.WorldDirectionSemanticName, worldDirectionRef, ParameterBindType.BindBySemantic);
|
|
if (!string.IsNullOrEmpty(transformationBindings.LocalDirectionSemanticName))
|
|
this.SetParameter(transformationBindings.LocalDirectionSemanticName, localDirectionRef, ParameterBindType.BindBySemantic);
|
|
|
|
if (!string.IsNullOrEmpty(transformationBindings.WorldUpDirectionSemanticName))
|
|
this.SetParameter(transformationBindings.WorldUpDirectionSemanticName, worldUpDirectionRef, ParameterBindType.BindBySemantic);
|
|
if (!string.IsNullOrEmpty(transformationBindings.LocalUpDirectionSemanticName))
|
|
this.SetParameter(transformationBindings.LocalUpDirectionSemanticName, localUpDirectionRef, ParameterBindType.BindBySemantic);
|
|
|
|
if (!string.IsNullOrEmpty(transformationBindings.WorldRightDirectionSemanticName))
|
|
this.SetParameter(transformationBindings.WorldRightDirectionSemanticName, worldRightDirectionRef, ParameterBindType.BindBySemantic);
|
|
if (!string.IsNullOrEmpty(transformationBindings.LocalRightDirectionSemanticName))
|
|
this.SetParameter(transformationBindings.LocalRightDirectionSemanticName, localRightDirectionRef, ParameterBindType.BindBySemantic);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region IUpdatable Members
|
|
|
|
public virtual void Update(bool forceUpdate)
|
|
{
|
|
if (!WantsUpdate && !forceUpdate)
|
|
return;
|
|
|
|
WantsUpdate = false;
|
|
|
|
var localMatrix = SlimDX.Matrix.Transformation(SlimDX.Vector3.Zero, SlimDX.Quaternion.Identity, localScale, SlimDX.Vector3.Zero, localRotation, this.LocalPosition);
|
|
|
|
var direction = new SlimDX.Vector3(0.0f, 0.0f, 1.0f);
|
|
var upDirection = new SlimDX.Vector3(0.0f, 1.0f, 0.0f);
|
|
var rightDirection = new SlimDX.Vector3(1.0f, 0.0f, 0.0f);
|
|
|
|
{
|
|
var rotMat = SlimDX.Matrix.RotationQuaternion(localRotation);
|
|
LocalDirection = SlimDX.Vector3.TransformNormal(direction, rotMat);
|
|
LocalUpDirection = SlimDX.Vector3.TransformNormal(upDirection, rotMat);
|
|
LocalRightDirection = SlimDX.Vector3.TransformNormal(rightDirection, rotMat);
|
|
}
|
|
|
|
WorldMatrix = localMatrix;
|
|
// stack parent matrix
|
|
if (transformationParent != null)
|
|
WorldMatrix = localMatrix * transformationParent.WorldMatrix;
|
|
|
|
// extract world related data
|
|
SlimDX.Vector3 tmpScale;
|
|
SlimDX.Vector3 tmpPos;
|
|
SlimDX.Quaternion tmpRot;
|
|
WorldMatrix.Decompose(out tmpScale, out tmpRot, out tmpPos);
|
|
WorldPosition = tmpPos;
|
|
WorldRotation = tmpRot;
|
|
WorldScale = tmpScale;
|
|
{
|
|
var rotMat = SlimDX.Matrix.RotationQuaternion(WorldRotation);
|
|
WorldDirection = SlimDX.Vector3.TransformNormal(direction, rotMat);
|
|
WorldUpDirection = SlimDX.Vector3.TransformNormal(upDirection, rotMat);
|
|
WorldRightDirection = SlimDX.Vector3.TransformNormal(rightDirection, rotMat);
|
|
}
|
|
|
|
// update following transformations
|
|
foreach (var transformation in transformations)
|
|
if (transformation is IUpdatable)
|
|
{
|
|
var updatable = transformation as IUpdatable;
|
|
if (updatable != null && (updatable.WantsUpdate || forceUpdate))
|
|
updatable.Update(forceUpdate);
|
|
}
|
|
}
|
|
|
|
public bool WantsUpdate { get; protected set; }
|
|
|
|
#endregion
|
|
}
|
|
}
|