port from perforce

This commit is contained in:
2026-04-18 22:31:51 +02:00
commit 8d0ab5b7cc
8409 changed files with 3972376 additions and 0 deletions

View File

@@ -0,0 +1,104 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{EA73561A-0B57-4FDC-8AF3-52E959BA67E7}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Aiwaz.Resources</RootNamespace>
<AssemblyName>Aiwaz.Resources</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="SlimDX, Version=2.0.8.42, Culture=neutral, PublicKeyToken=b1b0c32fd1ffe4f9, processorArchitecture=x86">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\Extern\SlimDX\x86\SlimDX.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data.DataSetExtensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="WindowsBase">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Attributes\CreationParameters.cs" />
<Compile Include="Attributes\ReadOnly.cs" />
<Compile Include="Attributes\RequiredParameter.cs" />
<Compile Include="BluImporter\BluImporter.cs" />
<Compile Include="Bone.cs" />
<Compile Include="Camera.cs" />
<Compile Include="Commands\CommandBuffer.cs" />
<Compile Include="Commands\CommandUser.cs" />
<Compile Include="CreationParams.cs" />
<Compile Include="GeometryBuffer.cs" />
<Compile Include="PickHull.cs" />
<Compile Include="Prefab\Quad.cs" />
<Compile Include="Prefab\Cube.cs" />
<Compile Include="Prefab\PingPongBuffer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RenderCommandNode.cs" />
<Compile Include="RenderTarget.cs" />
<Compile Include="RenderTargetTexture.cs" />
<Compile Include="Resource.cs" />
<Compile Include="Shader.cs" />
<Compile Include="ShaderParameterSet.cs" />
<Compile Include="SwapChain.cs" />
<Compile Include="Texture.cs" />
<Compile Include="Transformation.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Aiwaz.Common\Aiwaz.Common.csproj">
<Project>{0F7D7168-08C1-45AE-AAE3-80506939D7E6}</Project>
<Name>Aiwaz.Common</Name>
</ProjectReference>
<ProjectReference Include="..\Aiwaz.Contracts\Aiwaz.Contracts.csproj">
<Project>{DE4D6FE6-D1FB-41A1-8ABA-19635B8FFD7A}</Project>
<Name>Aiwaz.Contracts</Name>
</ProjectReference>
<ProjectReference Include="..\Aiwaz.Core\Aiwaz.Core.csproj">
<Project>{B7AB4BB3-6FFC-453E-928D-852A6FF8C508}</Project>
<Name>Aiwaz.Core</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Aiwaz.Resources.Attributes
{
public class CreationParametersAttribute : System.Attribute
{
public string Description { get; protected set; }
public CreationParametersAttribute(string description)
{
this.Description = description;
}
}
}

View File

@@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Aiwaz.Resources.Attributes
{
public class ReadOnlyAttribute : System.Attribute
{
}
}

View File

@@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Aiwaz.Resources.Attributes
{
public class RequiredParameterAttribute : System.Attribute
{
}
}

View File

@@ -0,0 +1,373 @@
using System;
using System.IO;
using System.Linq;
using Aiwaz.Common;
using Aiwaz.Contracts;
using Aiwaz.Core;
using System.Collections.Generic;
using Aiwaz.Resources.Attributes;
using System.Collections.ObjectModel;
using SlimDX;
namespace Aiwaz.Resources
{
public class FileInegrityBroken : Exception
{
public FileInegrityBroken() : base() { }
public FileInegrityBroken(string message) : base(message) { }
}
[CreationParameters("Blu Model from file")]
public class BluModelParams : ICreationParams
{
public string FileName;
public BluModelParams()
{
}
}
[AiwazResource("Blu Model", "A model loaded from a .blu file")]
public class BluModel : Resource
{
private enum BluSectionType
{
Mesh = 0,
Material = 1,
Bone = 2,
Animation = 3,
LastKnownType = 3
};
private class BluImportResult
{
public struct BluImportedGeometryBuffer
{
public IGeometryBuffer GeometryBuffer;
public string MaterialName;
};
public string FileName;
public Dictionary<string, BluImportedGeometryBuffer> GeometryBuffers = new Dictionary<string, BluImportedGeometryBuffer>();
public Dictionary<string, IShaderParameterSet> ShaderParamererSets = new Dictionary<string, IShaderParameterSet>();
public Dictionary<string, IShader> Shaders = new Dictionary<string, IShader>();
//Dictionary<string, BluImportedBone> Bones;
//Dictionary<string, ITransformationAnimation> Animations;
};
public string FileName { get; protected set; }
public RenderCommandNode RootNode { get; protected set; }
public Transformation RootTransformation { get; protected set; }
//IBoneController BoneController;
public BluModel(BluModelParams parameters)
{
creationParams = parameters;
var result = new BluImportResult();
this.FileName = result.FileName = parameters.FileName;
using (var stream = Engine.FileSystem.Open(parameters.FileName))
using (var reader = new BinaryReader(stream))
{
var magic = reader.ReadNullTerminatedString();
if (magic != "BLUF")
throw new FileInegrityBroken();
var fileVersion = reader.ReadInt32();
// sections
while (stream.Position < stream.Length)
{
var objectType = (BluSectionType)reader.ReadInt32();
if (objectType > BluSectionType.LastKnownType)
throw new FileInegrityBroken("Unknown object section detected.");
var objectName = reader.ReadNullTerminatedString();
if (string.IsNullOrEmpty(objectName))
throw new FileInegrityBroken("Object name not set.");
// content
switch (objectType)
{
case BluSectionType.Mesh:
this.ImportMesh(reader, objectName, result);
break;
case BluSectionType.Material:
this.ImportMaterial(reader, objectName, result);
break;
case BluSectionType.Bone:
this.ImportBone(reader, objectName, result);
break;
case BluSectionType.Animation:
this.ImportAnimation(reader, objectName, result);
break;
}
}
}
// build bone hierarchy
//std::map<string8, BluImportedBone>::iterator lk_BonesIter = lr_Result.m_Bones.begin();
//for (; lk_BonesIter != lr_Result.m_Bones.end(); ++lk_BonesIter)
//{
// BluImportedBone lr_Bone = lk_BonesIter->second;
// std::map<string8, BluImportedBone>::iterator lk_Found = lr_Result.m_Bones.find(lr_Bone.m_ParentName);
// if (lk_Found != lr_Result.m_Bones.end())
// lr_Bone.m_Bone->set_Parent(lk_Found->second.m_Bone);
//}
// add bone animations to bones
//std::map<string8, ITransformationAnimation*>::iterator lk_AnimIter = lr_Result.m_Animations.begin();
//for (; lk_AnimIter != lr_Result.m_Animations.end(); ++lk_AnimIter)
//{
// std::map<string8, BluImportedBone>::iterator lk_Found = lr_Result.m_Bones.find(lk_AnimIter->first);
// if (lk_Found != lr_Result.m_Bones.end())
// {
// lk_Found->second.m_Bone->set_TransformationAnimation(lk_AnimIter->second);
// }
//}
// collapse bone map to super parent bones only
//lk_BonesIter = lr_Result.m_Bones.begin();
//for (; lk_BonesIter != lr_Result.m_Bones.end();)
// if (!lk_BonesIter->second.m_ParentName.empty())
// lk_BonesIter = lr_Result.m_Bones.erase(lk_BonesIter);
// else
// {
// // create the boneindexlist structure while we are here
// lk_BonesIter->second.m_Bone->get_BoneIndexList();
// ++lk_BonesIter;
// }
//if (lr_Result.m_Bones.size() > 1)
// throw _T("BLUImporter: Only one bone root allowed!");
// Create a default BoneController
//if (!lr_Result.m_Bones.empty())
//{
// lr_Result.m_BoneController = &m_Engine.get_ResourceFactory().CreateOrFindBoneController();
// lr_Result.m_BoneController->Initialize(*lr_Result.m_Bones.begin()->second.m_Bone);
// float lf_MaxDuration = 0.0f;
// for (lk_AnimIter = lr_Result.m_Animations.begin(); lk_AnimIter != lr_Result.m_Animations.end(); ++lk_AnimIter)
// lf_MaxDuration = lf_MaxDuration < lk_AnimIter->second->get_Duration() ? lk_AnimIter->second->get_Duration() : lf_MaxDuration;
// lr_Result.m_BoneController->RegisterSequence(L"all", 0.0f, lf_MaxDuration, true);
//}
this.RootNode = new RenderCommandNode();
this.RootTransformation = new Transformation(new DefaultTransformationBindings());
//if (!m_Bones.empty())
// m_Bones.begin()->second.m_Bone->GetTransformationAtTime(0.0f, D3DXMATRIX());
//if (m_BoneController != NULL)
//{
// AddToNode(rootNode, m_BoneController);
// m_BoneController->PlaySequence(L"all");
//}
// Create sub nodes
foreach (var geoBufferInfo in result.GeometryBuffers)
{
var meshInfo = geoBufferInfo.Value;
var shader = result.Shaders[meshInfo.MaterialName];
var shaderParameter = result.ShaderParamererSets[meshInfo.MaterialName];
if (shader != null && shaderParameter != null)
{
var subNode = new RenderCommandNode();
subNode.Children.Add((CommandUser)shader);
subNode.Children.Add((CommandUser)this.RootTransformation);
subNode.Children.Add((CommandUser)shaderParameter);
subNode.Children.Add((CommandUser)meshInfo.GeometryBuffer);
this.RootNode.Children.Add(subNode);
}
}
}
private void ImportMesh(BinaryReader reader, string objectName, BluImportResult result)
{
var materialName = reader.ReadNullTerminatedString();
var vertexCount = reader.ReadInt32();
var vertexElementCount = reader.ReadInt32();
var vertexElements = new VertexElement[vertexElementCount];
for (int i = 0; i < vertexElementCount; ++i)
{
int vertexElementOldId = reader.ReadInt32();
switch (vertexElementOldId)
{
case 1: vertexElements[i] = new VertexElement(VertexElement.Format.Position); break;
case 3: vertexElements[i] = new VertexElement(VertexElement.Format.Normal); break;
case 8: vertexElements[i] = new VertexElement(VertexElement.Format.Texture2D); break;
case 11: vertexElements[i] = new VertexElement(VertexElement.Format.Tangent); break;
case 13: vertexElements[i] = new VertexElement(VertexElement.Format.BlendIndices); break;
case 14: vertexElements[i] = new VertexElement(VertexElement.Format.BlendWeight); break;
}
}
var vertexData = reader.ReadBytes(vertexCount * vertexElements.Sum(v => v.Size));
var indexCount = reader.ReadInt32();
var indexRawData = reader.ReadBytes(sizeof(Int32) * indexCount);
int[] indexData = new int[indexCount];
for (int i = 0; i < indexCount; ++i)
indexData[i] = (int)BitConverter.ToInt32(indexRawData, i * sizeof(uint));
string uniqueName = result.FileName + "." + objectName;
var vBuffer = new DataStream(vertexData, true, true);
var iBuffer = new DataStream(indexData, true, true);
var geoBuffer = new GeometryBuffer(
indexCount,
iBuffer,
vertexCount,
vBuffer,
vertexElements,
false);
geoBuffer.IsPickable = true;
//geoBuffer.ConvertToAdjacency();
var mesh = new BluImportResult.BluImportedGeometryBuffer();
mesh.GeometryBuffer = geoBuffer;
mesh.MaterialName = result.FileName + "." + materialName;
result.GeometryBuffers.Add(uniqueName, mesh);
}
private string GetPath(string orignalPath)
{
if (string.IsNullOrEmpty(orignalPath))
return orignalPath;
return Path.Combine(Path.GetDirectoryName(this.FileName), Path.GetFileName(orignalPath));
}
private void ImportMaterial(BinaryReader reader, string objectName, BluImportResult result)
{
string diffuseTexture = this.GetPath(reader.ReadNullTerminatedString());
string specularTexture = this.GetPath(reader.ReadNullTerminatedString());
string normalTexture = this.GetPath(reader.ReadNullTerminatedString());
string glowTexture = this.GetPath(reader.ReadNullTerminatedString());
string reflectionTexture = this.GetPath(reader.ReadNullTerminatedString());
var ambientColor = new SlimDX.Vector4();
ambientColor.X = reader.ReadSingle() / 255.0f;
ambientColor.Y = reader.ReadSingle() / 255.0f;
ambientColor.Z = reader.ReadSingle() / 255.0f;
ambientColor.W = reader.ReadSingle() / 255.0f;
var diffuseColor = new SlimDX.Vector4();
diffuseColor.X = reader.ReadSingle() / 255.0f;
diffuseColor.Y = reader.ReadSingle() / 255.0f;
diffuseColor.Z = reader.ReadSingle() / 255.0f;
diffuseColor.W = reader.ReadSingle() / 255.0f;
var specularColor = new SlimDX.Vector4();
specularColor.X = reader.ReadSingle() / 255.0f;
specularColor.Y = reader.ReadSingle() / 255.0f;
specularColor.Z = reader.ReadSingle() / 255.0f;
specularColor.W = reader.ReadSingle() / 255.0f;
var emissiveColor = new SlimDX.Vector4();
emissiveColor.X = reader.ReadSingle() / 255.0f;
emissiveColor.Y = reader.ReadSingle() / 255.0f;
emissiveColor.Z = reader.ReadSingle() / 255.0f;
emissiveColor.W = reader.ReadSingle() / 255.0f;
var specularlevel = reader.ReadSingle();
var glossiness = reader.ReadSingle();
string uniqueName = result.FileName + "." + objectName;
var material = new ShaderParameterSet();
material.SetParameter("AmbientColor", ambientColor, ParameterBindType.BindBySemantic);
material.SetParameter("DiffuseColor", diffuseColor, ParameterBindType.BindBySemantic);
material.SetParameter("SpecularColor", specularColor * glossiness, ParameterBindType.BindBySemantic);
material.SetParameter("EmissiveColor", emissiveColor, ParameterBindType.BindBySemantic);
material.SetParameter("Shininess", specularlevel, ParameterBindType.BindBySemantic);
var modelShader = new Shader(new ShaderParams() { FileName = "Data/NormalOutput.fx", TechniqueName = "Render" });
result.Shaders.Add(uniqueName, modelShader);
if (!string.IsNullOrEmpty(diffuseTexture))
{
Texture tex = Engine.FindNamedObject(diffuseTexture) as Texture;
if (tex == null)
{
tex = new Texture(new FileTextureParams() { FileName = diffuseTexture });
tex.WellKnownName = diffuseTexture;
}
material.SetParameter("Diffuse", tex, ParameterBindType.BindBySemantic);
}
if (!string.IsNullOrEmpty(specularTexture))
{
Texture tex = Engine.FindNamedObject(specularTexture) as Texture;
if (tex == null)
{
tex = new Texture(new FileTextureParams() { FileName = specularTexture });
tex.WellKnownName = specularTexture;
}
material.SetParameter("Specular", tex, ParameterBindType.BindBySemantic);
}
if (!string.IsNullOrEmpty(normalTexture))
{
Texture tex = Engine.FindNamedObject(normalTexture) as Texture;
if (tex == null)
{
tex = new Texture(new FileTextureParams() { FileName = normalTexture });
tex.WellKnownName = normalTexture;
}
material.SetParameter("Normal", tex, ParameterBindType.BindBySemantic);
}
if (!string.IsNullOrEmpty(glowTexture))
{
Texture tex = Engine.FindNamedObject(glowTexture) as Texture;
if (tex == null)
{
tex = new Texture(new FileTextureParams() { FileName = glowTexture });
tex.WellKnownName = glowTexture;
}
material.SetParameter("Glow", tex, ParameterBindType.BindBySemantic);
}
if (!string.IsNullOrEmpty(reflectionTexture))
{
Texture tex = Engine.FindNamedObject(reflectionTexture) as Texture;
if (tex == null)
{
tex = new Texture(new FileTextureParams() { FileName = reflectionTexture });
tex.WellKnownName = reflectionTexture;
}
material.SetParameter("Reflection", tex, ParameterBindType.BindBySemantic);
}
result.ShaderParamererSets.Add(uniqueName, material);
}
private void ImportBone(BinaryReader reader, string objectName, BluImportResult result)
{
throw new NotImplementedException();
}
private void ImportAnimation(BinaryReader reader, string objectName, BluImportResult result)
{
throw new NotImplementedException();
}
private ICreationParams creationParams;
public override ICreationParams CreationParams
{
get { return creationParams; }
}
private ObservableCollection<IResource> children;
[ReadOnly]
public override ObservableCollection<IResource> Children
{
get
{
if (children == null)
{
children = new ObservableCollection<IResource>();
children.Add(RootNode);
}
return children;
}
}
};
}

View File

@@ -0,0 +1,115 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Aiwaz.Contracts;
namespace Aiwaz.Resources
{
public class Bone : IBone
{
#region IBone Members
private SlimDX.Matrix transformation;
private SlimDX.Matrix invPoseTransformation;
private float lastAnimationTime = float.MinValue;
private IBone parent;
private SlimDX.Matrix[] matrixArray = new SlimDX.Matrix[0];
private ITransformationAnimation transformationAnimation;
private Dictionary<int, IBone> boneIndexList = new Dictionary<int, IBone>();
public Bone(string name, int index, SlimDX.Vector3 poseTranslation, SlimDX.Vector3 poseScale, SlimDX.Quaternion poseRotation)
{
PoseTransformation = SlimDX.Matrix.Transformation(SlimDX.Vector3.Zero, SlimDX.Quaternion.Identity, poseScale, SlimDX.Vector3.Zero, poseRotation, poseTranslation);
invPoseTransformation = this.PoseTransformation;
invPoseTransformation.Invert();
this.Index = index;
this.ChildBones = new List<IBone>();
}
public SlimDX.Matrix GetTransformationAtTime(float time, SlimDX.Matrix rootTransformationMatrix)
{
if (this.TransformationAnimation != null)
{
if (time != lastAnimationTime)
{
if (this.Parent != null)
{
transformation = (this.TransformationAnimation.GetTransformationAtTime(time) * invPoseTransformation) * this.Parent.GetTransformationAtTime(time, rootTransformationMatrix);
transformation = invPoseTransformation * this.TransformationAnimation.GetTransformationAtTime(time);
//m_Transformation = m_Transformation * ( * m_InvPoseTransformation);
}
else
transformation = this.TransformationAnimation.GetTransformationAtTime(time) * invPoseTransformation;
}
}
return transformation;
}
public Dictionary<int, IBone> BoneIndexList
{
get
{
if (parent != null)
return parent.BoneIndexList;
if (boneIndexList.Count == 0)
this.FillBoneIndexList(this);
return boneIndexList;
}
}
public List<IBone> ChildBones { get; protected set; }
public int Index { get; protected set; }
public SlimDX.Matrix[] MatrixArray
{
get
{
if (matrixArray == null)
matrixArray = new SlimDX.Matrix[this.BoneIndexList.Count];
return matrixArray;
}
}
public string Name { get; protected set; }
public SlimDX.Matrix PoseTransformation { get; protected set; }
public IBone Parent
{
get { return parent; }
set
{
if (parent != null)
parent.ChildBones.Remove(this);
parent = value;
if (parent != null)
parent.ChildBones.Add(this);
}
}
public ITransformationAnimation TransformationAnimation
{
get { return transformationAnimation; }
set
{
transformationAnimation = value;
lastAnimationTime = float.MinValue;
transformation = new SlimDX.Matrix();
}
}
internal void FillBoneIndexList(IBone currentBone)
{
boneIndexList[currentBone.Index] = currentBone;
foreach (var childBone in currentBone.ChildBones)
this.FillBoneIndexList(childBone);
}
#endregion
}
}

View File

@@ -0,0 +1,277 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Aiwaz.Contracts;
using Aiwaz.Core;
using Aiwaz.Common.Animations;
using Aiwaz.Resources.Attributes;
namespace Aiwaz.Resources
{
[CreationParameters("Standard orthographic camera")]
public class OrthographicCameraParams
{
public float width;
public float height;
public OrthographicCameraParams()
{
width = 512;
height = 512;
}
}
[AiwazResource("Orthographic Camera", "An orthographic camera for orthogonal views.")]
public class OrthographicCamera : BaseCamera, IOrthographicCamera
{
#region IOrthographicCamera Members
private float width;
private float height;
private OrthographicCamera()
: base()
{
}
public OrthographicCamera(OrthographicCameraParams parameters)
: this()
{
Console.WriteLine(string.Format("Creating OrthographicCamera ({0}x{1})..", parameters.width, parameters.height));
this.Width = parameters.width;
this.Height = parameters.height;
}
public float Width
{
get { return width; }
set
{
width = value;
WantsUpdate = true;
}
}
public float Height
{
get { return height; }
set
{
height = value;
WantsUpdate = true;
}
}
public override void Update(bool forceUpdate)
{
base.Update(forceUpdate);
this.ProjectionMatrix = SlimDX.Matrix.OrthoLH(width, height, this.NearClip, this.FarClip);
this.ViewMatrix = SlimDX.Matrix.LookAtLH(this.WorldPosition, this.WorldPosition + this.WorldDirection, this.WorldUpDirection);
// generate view frustum
var viewProj = this.ViewMatrix * this.ProjectionMatrix;
// Left plane
this.ViewFrustum.Plane[0] = new SlimDX.Plane(viewProj.M14 + viewProj.M11,
viewProj.M24 + viewProj.M21,
viewProj.M34 + viewProj.M31,
viewProj.M44 + viewProj.M41);
// Right plane
this.ViewFrustum.Plane[1] = new SlimDX.Plane(viewProj.M14 - viewProj.M11,
viewProj.M24 - viewProj.M21,
viewProj.M34 - viewProj.M31,
viewProj.M44 - viewProj.M41);
// Top plane
this.ViewFrustum.Plane[2] = new SlimDX.Plane(viewProj.M14 - viewProj.M12,
viewProj.M24 - viewProj.M22,
viewProj.M34 - viewProj.M32,
viewProj.M44 - viewProj.M42);
// Bottom plane
this.ViewFrustum.Plane[3] = new SlimDX.Plane(viewProj.M14 + viewProj.M12,
viewProj.M24 + viewProj.M22,
viewProj.M34 + viewProj.M32,
viewProj.M44 + viewProj.M42);
// Near plane
this.ViewFrustum.Plane[4] = new SlimDX.Plane(viewProj.M13,
viewProj.M23,
viewProj.M33,
viewProj.M43);
// Far plane
this.ViewFrustum.Plane[5] = new SlimDX.Plane(viewProj.M14 - viewProj.M13,
viewProj.M24 - viewProj.M23,
viewProj.M34 - viewProj.M33,
viewProj.M44 - viewProj.M43);
}
#endregion
}
[CreationParameters("Standard orthographic camera")]
public class PerspectiveCameraParams
{
public float fov;
public float aspectRatio;
public PerspectiveCameraParams()
{
fov = 90.0f;
aspectRatio = 1.0f;
}
}
[AiwazResource("Perspective Camera", "An perspective camera for perspective correct views.")]
public class PerspectiveCamera : BaseCamera, IPerspectiveCamera
{
#region IPerspectiveCamera Members
private float fov;
private float aspectRatio;
private PerspectiveCamera()
: base()
{
}
public PerspectiveCamera(PerspectiveCameraParams parameters)
: this()
{
Console.WriteLine(string.Format("Creating PerspectiveCamera (Fov: {0} AspectRatio: {1})..", parameters.fov, parameters.aspectRatio));
this.Fov = parameters.fov;
this.AspectRatio = parameters.aspectRatio;
}
[Animateable]
public float Fov
{
get { return fov; }
set
{
fov = value;
WantsUpdate = true;
}
}
[Animateable]
public float AspectRatio
{
get { return aspectRatio; }
set
{
aspectRatio = value;
WantsUpdate = true;
}
}
public override void Update(bool forceUpdate)
{
base.Update(forceUpdate);
this.ProjectionMatrix = SlimDX.Matrix.PerspectiveFovLH((float)((Math.PI / 180) * fov), this.AspectRatio, this.NearClip, this.FarClip);
this.ViewMatrix = SlimDX.Matrix.LookAtLH(this.WorldPosition, this.WorldPosition + this.WorldDirection, this.WorldUpDirection);
// generate view frustum
var viewProj = this.ViewMatrix * this.ProjectionMatrix;
// Left plane
this.ViewFrustum.Plane[0] = new SlimDX.Plane(
viewProj.M14 + viewProj.M11,
viewProj.M24 + viewProj.M21,
viewProj.M34 + viewProj.M31,
viewProj.M44 + viewProj.M41);
// Right plane
this.ViewFrustum.Plane[1] = new SlimDX.Plane(viewProj.M14 - viewProj.M11,
viewProj.M24 - viewProj.M21,
viewProj.M34 - viewProj.M31,
viewProj.M44 - viewProj.M41);
// Top plane
this.ViewFrustum.Plane[2] = new SlimDX.Plane(viewProj.M14 - viewProj.M12,
viewProj.M24 - viewProj.M22,
viewProj.M34 - viewProj.M32,
viewProj.M44 - viewProj.M42);
// Bottom plane
this.ViewFrustum.Plane[3] = new SlimDX.Plane(viewProj.M14 + viewProj.M12,
viewProj.M24 + viewProj.M22,
viewProj.M34 + viewProj.M32,
viewProj.M44 + viewProj.M42);
// Near plane
this.ViewFrustum.Plane[4] = new SlimDX.Plane(viewProj.M13,
viewProj.M23,
viewProj.M33,
viewProj.M43);
// Far plane
this.ViewFrustum.Plane[5] = new SlimDX.Plane(viewProj.M14 - viewProj.M13,
viewProj.M24 - viewProj.M23,
viewProj.M34 - viewProj.M33,
viewProj.M44 - viewProj.M43);
}
#endregion
}
public abstract class BaseCamera : Transformation, ICamera
{
#region ICamera Members
private float nearClip = 1.0f;
private float farClip = 1000.0f;
Reference projectionMatrix = new Reference(new SlimDX.Matrix());
Reference viewMatrix = new Reference(new SlimDX.Matrix());
public SlimDX.Matrix ProjectionMatrix { get { return (SlimDX.Matrix)projectionMatrix.RawValue; } protected set { projectionMatrix.RawValue = value; } }
public SlimDX.Matrix ViewMatrix { get { return (SlimDX.Matrix)viewMatrix.RawValue; } protected set { viewMatrix.RawValue = value; } }
public BaseCamera()
: base(new CameraTransformationBindings())
{
this.ViewFrustum = new ViewFrustum();
this.IsPreconditionForFollowingShaders = true;
this.RecreateAllShaderParameters();
}
public float FarClip
{
get { return farClip; }
set
{
farClip = value;
WantsUpdate = true;
}
}
public float NearClip
{
get { return nearClip; }
set
{
nearClip = value;
WantsUpdate = true;
}
}
public ViewFrustum ViewFrustum { get; protected set; }
protected override void RecreateAllShaderParameters()
{
this.SetParameter("ViewMatrix", viewMatrix, ParameterBindType.BindBySemantic);
this.SetParameter("ProjectionMatrix", projectionMatrix, ParameterBindType.BindBySemantic);
base.RecreateAllShaderParameters();
}
#endregion
}
}

View File

@@ -0,0 +1,342 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Aiwaz.Contracts;
using Aiwaz.Core;
namespace Aiwaz.Resources
{
public class CommandBuffer
{
private class CommandChainInternal
{
public int Priority = 0;
public List<Command> Chain;
public void UpdatePriority()
{
Priority = -1;
foreach (var command in Chain)
if ((command.Flags & CommandFlags.SubChainStart) != CommandFlags.None)
{
Priority = command.SubPriority;
break;
}
}
public class CommandComparsion : IComparer<Command>
{
public int Compare(Command x, Command y)
{
return x.Priority.CompareTo(y.Priority);
}
}
public class CommandChainComparsion : IComparer<CommandChainInternal>
{
public int Compare(CommandChainInternal x, CommandChainInternal y)
{
if (x.Priority == y.Priority)
return x.Chain.Count.CompareTo(y.Chain.Count);
return x.Priority.CompareTo(y.Priority);
}
}
}
private CommandBuffer optimizedCommandBuffer = null;
private List<CommandChainInternal> gatheredCommandChains = new List<CommandChainInternal>();
public List<Command> BufferedCommands { get; protected set; }
public List<CommandBuffer> ChildCommandBuffers { get; protected set; }
public CommandBuffer ParentBuffer { get; set; }
#region ICommandBuffer Members
public CommandBuffer()
{
BufferedCommands = new List<Command>();
ChildCommandBuffers = new List<CommandBuffer>();
}
public void Clear()
{
BufferedCommands.Clear();
ChildCommandBuffers.Clear();
gatheredCommandChains.Clear();
if (optimizedCommandBuffer != null)
optimizedCommandBuffer.Clear();
}
public void Perform(bool useOptimizedList)
{
if (!useOptimizedList)
{
int subChainStartCommandIndex = -1;
for (int i = 0; i < BufferedCommands.Count;)
{
var command = BufferedCommands[i];
if ((command.Flags & CommandFlags.SubChainStart) != CommandFlags.None)
subChainStartCommandIndex = i;
switch (command.Owner.ExecuteCommand(command.Type, this, i))
{
case CommandExecuteResult.None:
if ((command.Flags & CommandFlags.SubChainEnd) != CommandFlags.None)
subChainStartCommandIndex = -1;
i++;
break;
case CommandExecuteResult.RetrySubChain:
if (subChainStartCommandIndex == -1)
throw new ActionFailedException("Failed to restart sub command chain.");
else
i = subChainStartCommandIndex;
break;
case CommandExecuteResult.RetrySubChainSkipHead:
if (subChainStartCommandIndex == -1)
throw new ActionFailedException("Failed to restart headless sub command chain.");
else
i = subChainStartCommandIndex + 1;
break;
}
}
}
else
{
if (optimizedCommandBuffer != null)
optimizedCommandBuffer.Perform(false);
}
}
public void Optimize()
{
if (optimizedCommandBuffer == null)
optimizedCommandBuffer = new CommandBuffer();
optimizedCommandBuffer.Clear();
List<Command> tempChain = new List<Command>();
this.SearchDrawableCommandChain(this, ref tempChain);
this.FlushGatheredCommandChains();
}
public void AddChildCommandBuffer(CommandBuffer commandBuffer)
{
ChildCommandBuffers.Add(commandBuffer);
commandBuffer.ParentBuffer = this;
}
public void RemoveChildCommandBuffer(CommandBuffer commandBuffer)
{
if (ChildCommandBuffers.Remove(commandBuffer))
commandBuffer.ParentBuffer = null;
}
private void SearchDrawableCommandChain(CommandBuffer incomingBuffer, ref List<Command> currentChain)
{
for (int i = 0; i < incomingBuffer.BufferedCommands.Count;)
{
var currentCommand = incomingBuffer.BufferedCommands[i];
var commandFlags = currentCommand.Flags;
// A command is start AND end of a command chain, this indicates that a serious state change will come,
// so we will need to flush the current command chains.
if ((commandFlags & CommandFlags.FlushChain) != 0)
{
this.FlushGatheredCommandChains();
currentChain.Clear();
}
// Old way commented out due problems with transformations before shaders
// A command was found which does not belong to a build up current chain (due no chain is building herself up..)
// so we drop it, we simply do not care about some run away
/*if (currentChain.empty()
&& (commandFlags & CommandFlags.StartChain) == 0
&& (commandFlags & CommandFlags.EndChain) == 0)
{
++i;
continue;
}*/
// New way is to search the list for a start chain command, then we put this command after the start chain command
if (currentChain.Count == 0
&& (commandFlags & CommandFlags.StartChain) == 0
&& (commandFlags & CommandFlags.EndChain) == 0)
{
var foundPlace = false;
var commands = incomingBuffer.BufferedCommands;
for (int k = i + 1; k < commands.Count; ++k)
if ((commands[k].Flags & CommandFlags.StartChain) != CommandFlags.None)
{
commands.Insert(k + 1, currentCommand);
commands.RemoveAt(i);
foundPlace = true;
break;
}
if (!foundPlace)
++i;
continue;
}
// A new command chain should be initialized, clear our current temp chain and add this command into it.
// All old commands remaining in the chain are already used or where completely useless (SetShader . SetParameter . NextPass).
else if ((commandFlags & CommandFlags.StartChain) != 0 && currentChain.Count > 0)
{
currentChain.Clear();
currentChain.Add(currentCommand);
++i;
}
// We should end our chain, now we need to optimize this chain and add this into the gathered chain list,
// at the next flush command we will put this list into our optimized list, with some more optimizations.
else if ((commandFlags & CommandFlags.EndChain) != 0)
{
// We have a filled chain (at least 1 operation following by this operation)
if (currentChain.Count > 0)
{
var commandChainInternal = new CommandChainInternal();
commandChainInternal.Chain = new List<Command>(currentChain);
commandChainInternal.Chain.Add(currentCommand);
commandChainInternal.Chain.Sort(new CommandChainInternal.CommandComparsion());
//m_OptimizedCommandBuffer.get_BufferedCommands().insert(m_OptimizedCommandBuffer.get_BufferedCommands().end(), chain.begin(), chain.end());
gatheredCommandChains.Add(commandChainInternal);
// Search for the SubChainEnd flagged command , this should be found right after the SubChainStart flagged commands
// both commands will mark the beginning of our chain . delete everything behind this command will ensure
// that we will use a fresh new command chain, only filled with what we need (StartSubChain . EndSubChain)
for (int k = 0; k < currentChain.Count; ++k)
if ((currentChain[k].Flags & CommandFlags.SubChainEnd) != CommandFlags.None)
{
currentChain.RemoveRange(k + 1, currentChain.Count - (k + 1));
break;
}
}
// Our chain was empty, this means a solo command was found, put it into our optimized list and continue,
// there is not much to do here.
else
{
optimizedCommandBuffer.BufferedCommands.Add(currentCommand);
}
++i;
}
// No start and no end of the command chain, just put this command into our chain,
// commands of this type are for example, SetVertexBuffer, SetIndexBuffer, SetTransformation,...
else
{
currentChain.Add(currentCommand);
++i;
}
}
// We may have child buffers, continue our search there.
foreach (var buffer in incomingBuffer.ChildCommandBuffers)
{
var newCurrentChain = new List<Command>(currentChain);
this.SearchDrawableCommandChain(buffer, ref currentChain);
currentChain = newCurrentChain;
}
}
void FlushGatheredCommandChains()
{
var flushedCommands = new List<Command>();
gatheredCommandChains.ForEach(item => item.UpdatePriority());
while (gatheredCommandChains.Count > 0)
{
gatheredCommandChains.Sort(new CommandChainInternal.CommandChainComparsion());
int currentPriority = 0;
List<int> checkables = new List<int>();
for (int i = 0; i < gatheredCommandChains.Count;)
{
if (gatheredCommandChains[i].Chain.Count == 0)
gatheredCommandChains.RemoveAt(i);
else if (checkables.Count == 0 || currentPriority == gatheredCommandChains[i].Priority)
{
currentPriority = gatheredCommandChains[i].Priority;
checkables.Add(i);
++i;
}
else
break;
}
if (checkables.Count == 1)
{
int thisIndex = checkables.First();
flushedCommands.AddRange(gatheredCommandChains[thisIndex].Chain);
gatheredCommandChains.RemoveAt(thisIndex);
if (gatheredCommandChains.Count == 0)
break;
}
List<Command> optimizedCommandChain = new List<Command>();
Command lastCommand = null;
while (checkables.Count > 1)
{
if (checkables.Count > 0 && checkables.First() != 0)
break;
for (int i = 0; i < checkables.Count;)
{
int thisIndex = checkables[i];
var currentCommandChainInternal = gatheredCommandChains[thisIndex];
var thisCommand = currentCommandChainInternal.Chain.First();
if (i == 0 || (thisCommand.CommandInfo.RawValue == lastCommand.CommandInfo.RawValue && thisCommand.Owner == lastCommand.Owner))
{
// we found a similarity (or the first element), put this into our optimized temp list
lastCommand = thisCommand;
if (i == 0 || (thisCommand.Flags & CommandFlags.Unique) != 0)
optimizedCommandChain.Add(thisCommand);
currentCommandChainInternal.Chain.RemoveAt(0);
if (currentCommandChainInternal.Chain.Count == 0)
{
checkables.RemoveAt(i);
break;
}
else
++i;
}
else
{
// do not check this list further, a difference was detected
checkables.RemoveAt(i);
}
}
// resort our gatheredCommandChains so that we could use the remaining content of a list properly, only do that if the checkable list has no direct preceeding elements ({0,2,3} instead {0,1,2})
if (checkables.Count > 0)
for (int i = checkables.First() + 1; i < checkables.Count; ++i)
if (checkables[i] != i)
{
var tmp = gatheredCommandChains[i];
gatheredCommandChains[i] = gatheredCommandChains[checkables[i]];
gatheredCommandChains[checkables[i]] = tmp;
checkables[i] = i;
}
}
flushedCommands.AddRange(optimizedCommandChain);
}
// remove unnecessary SubChainEnd commands
bool openPass = false;
for (int i = flushedCommands.Count - 1; i >= 0; --i)
{
if ((flushedCommands[i].Flags & CommandFlags.SubChainEnd) == CommandFlags.SubChainEnd)
{
if (!openPass)
openPass = true;
else
flushedCommands.RemoveAt(i);
}
else if ((flushedCommands[i].Flags & CommandFlags.SubChainStart) == CommandFlags.SubChainStart)
openPass = false;
}
optimizedCommandBuffer.BufferedCommands.AddRange(flushedCommands);
}
#endregion
}
}

View File

@@ -0,0 +1,137 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Aiwaz.Contracts;
using System.Runtime.InteropServices;
using Aiwaz.Core;
namespace Aiwaz.Resources
{
public enum CommandFlags : byte
{
None = 0x00,
SubChainStart = 0x01, // Command will start a new command chain (UseShader for example)
SubChainEnd = 0x02, // Command will end a command chain (Render)
Unique = 0x04, // Similar commands should not be reduced to one Command
StartChain = 0x08, // Command will generate a new command chain
EndChain = 0x10, // Command will end the command chain (RenderGeometry for example)
FlushChain = 0x20, // Command will end the command chain (RenderGeometry for example)
}
public class Command
{
[StructLayout(LayoutKind.Explicit)]
public struct CommandInfoUnion
{
[FieldOffset(0)]
public uint RawValue;
[FieldOffset(0)]
public byte Priority;
[FieldOffset(1)]
public byte SubPriority;
[FieldOffset(2)]
public CommandFlags Flags;
[FieldOffset(3)]
public byte Type;
}
public Command(CommandUser argOwner, CommandFlags argFlags, byte argType)
: this(argOwner, argFlags, argType, 0, 0)
{
}
public Command(CommandUser argOwner, CommandFlags argFlags, byte argType, byte argPriority)
: this(argOwner, argFlags, argType, argPriority, 0)
{
}
public Command(CommandUser argOwner, CommandFlags argFlags, byte argType, byte argPriority, byte argSubPriority)
{
CommandInfo.RawValue = 0;
Owner = argOwner;
Flags = argFlags;
Priority = argPriority;
SubPriority = argSubPriority;
Type = argType;
}
public CommandInfoUnion CommandInfo;
public byte Priority { get { return CommandInfo.Priority; } set { CommandInfo.Priority = value; } }
public byte SubPriority { get { return CommandInfo.SubPriority; } set { CommandInfo.SubPriority = value; } }
public CommandFlags Flags { get { return CommandInfo.Flags; } set { CommandInfo.Flags = value; } }
public byte Type { get { return CommandInfo.Type; } set { CommandInfo.Type = value; } }
public CommandUser Owner;
};
public enum CommandExecuteResult
{
None, // Execution done, proceed to the next Command
RetrySubChain, // Execution should start from a previous "SubChainStart"-flagged Command
RetrySubChainSkipHead // Equal to the above result but skips the as "SubChainStart"-flagged Command
};
public abstract class CommandUser : Resource, IDisposable
{
private List<RenderCommandNode> assignedRenderCommandNodes = new List<RenderCommandNode>();
public List<Command> Commands { get; private set; }
public bool IsPreconditionForNextCommands { get; set; }
public CommandUser()
{
this.Commands = new List<Command>();
Engine.RegisterEngineDisposable(this);
}
~CommandUser()
{
if (!Engine.Initialized)
return;
if (Engine.UnregisterEngineDisposable(this))
this.Dispose();
}
public abstract CommandExecuteResult ExecuteCommand(byte argCommandType, CommandBuffer argCurrentBuffer, int argCurrentPositon);
public void AssignToRenderCommandNode(RenderCommandNode node)
{
assignedRenderCommandNodes.Add(node);
node.MarkDirty();
}
public void UnassignFromRenderCommandNode(RenderCommandNode node)
{
if (assignedRenderCommandNodes.Remove(node))
node.MarkDirty();
}
protected void UnassignFromSceneNodes()
{
for (var i = 0; i < assignedRenderCommandNodes.Count; ++i )
assignedRenderCommandNodes[i].Children.Remove(this);
assignedRenderCommandNodes.Clear();
}
protected void MarkCommandsAsDirty()
{
foreach (var node in assignedRenderCommandNodes)
node.MarkDirty();
}
public new virtual void Dispose()
{
this.WellKnownName = null;
this.UnassignFromSceneNodes();
Engine.UnregisterEngineDisposable(this);
base.Dispose();
}
}
}

View File

@@ -0,0 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Aiwaz.Resources
{
}

View File

@@ -0,0 +1,551 @@
using System.Collections.Generic;
using Aiwaz.Core;
using Aiwaz.Contracts;
using System;
using System.Linq;
using SlimDX.Direct3D10;
using SlimDX;
using System.Collections.ObjectModel;
namespace Aiwaz.Resources
{
[AiwazResource("Geometry Buffer", "Renderable buffer with vertex or index data.")]
public class GeometryBuffer : CommandUser, IDisposable, IGeometryBuffer
{
#region Constructor
public GeometryBuffer()
: base()
{
Console.WriteLine("Creating GeometryBuffer..");
PrimitiveTopology = PrimitiveTopology.TriangleList;
Commands.Add(new Command(this, CommandFlags.None, SetIndexBufferCommandType, 1));
Commands.Add(new Command(this, CommandFlags.None, SetVertexBufferCommandType, 0));
Commands.Add(new Command(this, CommandFlags.EndChain | CommandFlags.Unique, DrawGeometryCommandType, 6));
}
public GeometryBuffer(IEnumerable<uint> argIndexData, bool argNeedsDynamicAccess)
: this()
{
this.SetIndexData(argIndexData, argNeedsDynamicAccess);
}
public GeometryBuffer(int argIndexCount, SlimDX.DataStream argIndexData, int argVertexCount, SlimDX.DataStream argVertexData, VertexElement[] argVertexElements, bool argNeedsDynamicAccess)
: this()
{
this.SetIndexData(argIndexCount, argIndexData, argNeedsDynamicAccess);
this.SetVertexData(argVertexCount, argVertexData, argVertexElements, argNeedsDynamicAccess);
}
public static GeometryBuffer Create<TVertex>(IEnumerable<TVertex> argVertexData, VertexElement[] argVertexElements, bool argNeedsDynamicAccess) where TVertex : struct
{
var geoBuffer = new GeometryBuffer();
geoBuffer.SetVertexData(argVertexData, argVertexElements, argNeedsDynamicAccess);
return geoBuffer;
}
public static GeometryBuffer Create<TVertex>(IEnumerable<uint> argIndexData, IEnumerable<TVertex> argVertexData, VertexElement[] argVertexElements, bool argNeedsDynamicAccess) where TVertex : struct
{
var geoBuffer = new GeometryBuffer();
geoBuffer.SetIndexData(argIndexData, argNeedsDynamicAccess);
geoBuffer.SetVertexData(argVertexData, argVertexElements, argNeedsDynamicAccess);
return geoBuffer;
}
#endregion
#region Methods
public void SetVertexData(int argVertexCount, DataStream argVertexData, VertexElement[] argVertexElements, bool argNeedsDynamicAccess)
{
Console.WriteLine(string.Format("Vertex data: {0} bytes ({1} elements).", argVertexData.Length, argVertexCount));
var usePickHull = this.IsPickable;
DeleteVertexData();
BufferDescription desc = new BufferDescription((int)argVertexData.Length,
argNeedsDynamicAccess ? ResourceUsage.Dynamic : ResourceUsage.Default,
SlimDX.Direct3D10.BindFlags.VertexBuffer,
argNeedsDynamicAccess ? CpuAccessFlags.Write : 0, ResourceOptionFlags.None);
vertexBuffer = new SlimDX.Direct3D10.Buffer(Engine.Device, argVertexData, desc);
if (vertexBuffer == null)
{
throw new ActionFailedException("GeometryBuffer: Couldn't create vertex buffer!");
}
VertexBufferLength = argVertexCount;
vertexElementSize = (int)argVertexData.Length / argVertexCount;
vertexElements = argVertexElements;
rawVertexData = argVertexData;
if (inputElementDesc == null)
{
if (vertexElements.Length > 0)
{
inputElementDesc = new InputElement[vertexElements.Length];
int i = 0;
foreach (var element in vertexElements)
{
inputElementDesc[i++] = new InputElement(element.SemanticName, element.NameIndex, element.ElementFormat, -1, 0, InputClassification.PerVertexData, 0);
}
}
}
this.IsPickable = usePickHull;
}
public void DeleteVertexData()
{
if (vertexBuffer != null)
Engine.Device.ClearState();
vertexElements = new VertexElement[0];
if (vertexBuffer != null)
vertexBuffer.Dispose();
if (rawVertexData != null)
rawVertexData.Dispose();
vertexBuffer = null;
VertexBufferLength = 0;
vertexElementSize = 0;
rawMappedVertexData = null;
typeMappedVertexData = null;
rawVertexData = null;
inputElementDesc = null;
PickHull = null;
}
public void SetIndexData(int argIndexCount, DataStream argIndexData, bool argNeedsDynamicAccess)
{
Console.WriteLine(string.Format("Index data: {0} bytes ({1} elements).", argIndexData.Length, argIndexCount));
bool usePickHull = this.IsPickable;
DeleteIndexData();
BufferDescription desc = new BufferDescription(
sizeof(uint) * argIndexCount,
ResourceUsage.Default,
SlimDX.Direct3D10.BindFlags.IndexBuffer,
argNeedsDynamicAccess ? CpuAccessFlags.Write : 0, ResourceOptionFlags.None);
indexBuffer = new SlimDX.Direct3D10.Buffer(Engine.Device, argIndexData, desc);
if (indexBuffer == null)
{
throw new ActionFailedException("GeometryBuffer: Couldn't create index buffer!");
}
IndexBufferLength = argIndexCount;
IndexBufferUsableLength = argIndexCount;
IndexBufferOffset = 0;
rawIndexData = argIndexData;
this.IsPickable = usePickHull;
}
public void DeleteIndexData()
{
if (indexBuffer != null)
Engine.Device.ClearState();
if (indexBuffer != null)
indexBuffer.Dispose();
if (rawIndexData != null)
rawIndexData.Dispose();
indexBuffer = null;
rawIndexData = null;
IndexBufferLength = 0;
foreach (var inputLayouts in vertexLayoutsPerShaderAndPass.Values)
foreach (var inputLayout in inputLayouts)
inputLayout.Dispose();
vertexLayoutsPerShaderAndPass.Clear();
PickHull = null;
}
public DataStream MapVertexBufferRaw(MapMode argAccessMode)
{
if (vertexBuffer == null)
throw new NullReferenceException("GeometryBuffer: Access forbidden until resource has been initialized.");
if (rawMappedVertexData != null)
throw new InvalidOperationException("GeometryBuffer: Only one access to the vertex buffer at one time possible.");
try
{
rawMappedVertexData = vertexBuffer.Map(argAccessMode, MapFlags.None);
return rawMappedVertexData;
}
catch (Exception ex)
{
throw new ActionFailedException("GeometryBuffer: Access to the vertex buffer was not successful. " + ex.ToString());
}
}
public void UnmapVertexBuffer()
{
if (vertexBuffer == null)
throw new NullReferenceException("GeometryBuffer: Access forbidden until resource has been initialized.");
if (rawMappedVertexData == null)
throw new InvalidOperationException("GeometryBuffer: No access was done, ending the access to the vertex buffer is not possible.");
if (typeMappedVertexData != null)
{
rawMappedVertexData.Position = 0;
var tmp = (byte[])typeMappedVertexData;
rawMappedVertexData.WriteRange(tmp);
}
vertexBuffer.Unmap();
rawMappedVertexData = null;
typeMappedVertexData = null;
}
public DataStream MapIndexBufferRaw(MapMode argAccessMode)
{
if (indexBuffer == null)
throw new NullReferenceException("GeometryBuffer: Access forbidden until resource has been initialized.");
if (rawMappedIndexData != null)
throw new InvalidOperationException("GeometryBuffer: Only one access to the index buffer at one time possible.");
try
{
rawMappedIndexData = indexBuffer.Map(argAccessMode, MapFlags.None);
return rawMappedIndexData;
}
catch (Exception ex)
{
throw new ActionFailedException("GeometryBuffer: Access to the index buffer was not successful. " + ex.ToString());
}
}
public void UnmapIndexBuffer()
{
if (indexBuffer == null)
throw new NullReferenceException("GeometryBuffer: Access forbidden until resource has been initialized.");
if (rawMappedIndexData == null)
throw new InvalidOperationException("GeometryBuffer: No access was done ending, the access to the index buffer is not possible.");
if (typeMappedIndexData != null)
{
rawMappedIndexData.Position = 0;
rawMappedIndexData.WriteRange(typeMappedIndexData);
}
indexBuffer.Unmap();
rawMappedIndexData = null;
typeMappedIndexData = null;
}
public void ConvertToAdjacency()
{
Console.WriteLine(string.Format("Convert to adjacency."));
switch (PrimitiveTopology)
{
case PrimitiveTopology.LineList:
case PrimitiveTopology.LineStrip:
case PrimitiveTopology.TriangleList:
case PrimitiveTopology.TriangleStrip:
break;
default:
return;
}
InputElement[] inputLayout = new InputElement[2];
inputLayout[0] = new InputElement("POSITION", 0, SlimDX.DXGI.Format.R32G32B32_Float, 0, 0, InputClassification.PerVertexData, 0);
inputLayout[1] = new InputElement("END", 0, SlimDX.DXGI.Format.R8_UInt, vertexElementSize - 1, 0, InputClassification.PerVertexData, 0);
// create the mesh
int numVertices = VertexBufferLength;
int numIndices = IndexBufferLength;
Mesh mesh = null;
try
{
mesh = new Mesh(Engine.Device, inputLayout, inputLayout[0].SemanticName, numVertices, numIndices / 3, MeshFlags.Has32BitIndices);
}
catch (System.Exception ex)
{
throw new ActionFailedException("GeometryBuffer: Unable to create temp. mesh for adjacency data generation. " + ex.ToString());
}
//set the VB
mesh.SetVertexData(0, rawVertexData);
//set the IB
mesh.SetIndexData(rawIndexData, numIndices);
//generate adjacency
const float epsilon = 0.0f;
mesh.GenerateAdjacencyAndPointRepresentation(epsilon);
//generate adjacency indices
mesh.GenerateGeometryShaderAdjacency();
//get the adjacency data out of the mesh
MeshBuffer indexBufferMesh = null;
DataStream adjIndices = null;
try
{
indexBufferMesh = mesh.GetIndexBuffer();
adjIndices = indexBufferMesh.Map();
}
catch (System.Exception ex)
{
throw new ActionFailedException("GeometryBuffer: Unable to retrive indexdata for adjacency data generation. " + ex.ToString());
}
SetIndexData((int)(adjIndices.Length / sizeof(uint)), adjIndices, false);
//cleanup
indexBufferMesh.Unmap();
indexBufferMesh.Dispose();
mesh.Dispose();
switch (this.PrimitiveTopology)
{
case PrimitiveTopology.LineList:
PrimitiveTopology = PrimitiveTopology.LineListWithAdjacency;
break;
case PrimitiveTopology.LineStrip:
PrimitiveTopology = PrimitiveTopology.LineStripWithAdjacency;
break;
case PrimitiveTopology.TriangleList:
PrimitiveTopology = PrimitiveTopology.TriangleListWithAdjacency;
break;
case PrimitiveTopology.TriangleStrip:
PrimitiveTopology = PrimitiveTopology.TriangleStripWithAdjacency;
break;
}
}
private void Render(IShader argShader)
{
if (vertexElements.Length == 0)
return;
int currentPass = argShader.CurrentPass;
EffectPass currentEffectPass = argShader.Technique.GetPassByIndex(currentPass);
InputLayout vertexLayout = null;
List<InputLayout> ilList;
if (vertexLayoutsPerShaderAndPass.TryGetValue(argShader, out ilList) && ilList.Count > currentPass)
{
vertexLayout = ilList[currentPass];
}
else
{
vertexLayout = new InputLayout(Engine.Device, inputElementDesc, currentEffectPass.Description.Signature);
if (vertexLayout != null)
{
if (ilList == null)
{
ilList = new List<InputLayout>();
ilList.Add(vertexLayout);
vertexLayoutsPerShaderAndPass[argShader] = ilList;
}
else
{
ilList.Add(vertexLayout);
}
}
}
if (vertexLayout != null)
{
currentEffectPass.Apply();
Engine.Device.InputAssembler.SetInputLayout(vertexLayout);
if (indexBuffer == null)
Engine.Device.Draw(VertexBufferLength, 0);
else
Engine.Device.DrawIndexed(IndexBufferUsableLength, IndexBufferOffset, 0);
}
}
#endregion
#region Properties
public int IndexBufferOffset { get; set; }
public int IndexBufferUsableLength { get; set; }
public int IndexBufferLength { get; private set; }
public int VertexBufferLength { get; private set; }
public PrimitiveTopology PrimitiveTopology { get; set; }
public bool IsPickable
{
get
{
return this.PickHull != null;
}
set
{
if (this.IsPickable == value)
return;
this.PickHull = new PickHull(rawVertexData, VertexBufferLength, vertexElements, rawIndexData, IndexBufferLength);
}
}
public IPickHull PickHull { get; protected set; }
#endregion
#region Constants
public static byte SetIndexBufferCommandType = 0;
public static byte SetVertexBufferCommandType = 1;
public static byte DrawGeometryCommandType = 2;
#endregion
#region Private members
SlimDX.Direct3D10.Buffer indexBuffer;
DataStream rawIndexData;
uint[] typeMappedIndexData;
DataStream rawMappedIndexData;
int vertexElementSize;
SlimDX.Direct3D10.Buffer vertexBuffer;
DataStream rawVertexData;
object typeMappedVertexData;
Type typeMappedVertexDataType;
DataStream rawMappedVertexData;
VertexElement[] vertexElements;
InputElement[] inputElementDesc;
Dictionary<IShader, List<InputLayout>> vertexLayoutsPerShaderAndPass = new Dictionary<IShader, List<InputLayout>>();
#endregion
#region CommandUser Members
public override CommandExecuteResult ExecuteCommand(byte argCommandType, CommandBuffer argCurrentBuffer, int argCurrentPositon)
{
if (argCommandType == GeometryBuffer.SetIndexBufferCommandType)
{
if (Engine.EngineStates.LastIndexBufferProvider != this)
{
Engine.Device.InputAssembler.SetIndexBuffer(indexBuffer, SlimDX.DXGI.Format.R32_UInt, IndexBufferOffset);
Engine.EngineStates.LastIndexBufferProvider = this;
}
}
else if (argCommandType == GeometryBuffer.SetVertexBufferCommandType)
{
if (Engine.EngineStates.LastVertexBufferProvider != this)
{
Engine.Device.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertexBuffer, vertexElementSize, 0));
Engine.Device.InputAssembler.SetPrimitiveTopology(PrimitiveTopology);
Engine.EngineStates.LastVertexBufferProvider = this;
}
}
else if (argCommandType == GeometryBuffer.DrawGeometryCommandType)
{
if (Engine.EngineStates.LastShader == null)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("GeometryBuffer could not render without a valid shader.");
Console.ForegroundColor = ConsoleColor.White;
}
else if (Engine.EngineStates.LastVertexBufferProvider == null)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("GeometryBuffer could not render without a valid vertex buffer.");
Console.ForegroundColor = ConsoleColor.White;
}
else
{
Render(Engine.EngineStates.LastShader);
}
}
return CommandExecuteResult.None;
}
#endregion
#region IDisposable Members
void IDisposable.Dispose()
{
if (Engine.EngineStates.LastIndexBufferProvider == this)
Engine.EngineStates.LastIndexBufferProvider = null;
if (Engine.EngineStates.LastVertexBufferProvider == this)
Engine.EngineStates.LastVertexBufferProvider = null;
DeleteVertexData();
DeleteIndexData();
base.Dispose();
}
#endregion
public override ICreationParams CreationParams
{
get { return null; }
}
public override ObservableCollection<IResource> Children
{
get { return null; }
}
#region IGeometryBuffer Members
public void SetIndexData(IEnumerable<uint> argIndexData, bool argNeedsDynamicAccess)
{
this.SetIndexData(argIndexData.Count(), new DataStream(argIndexData.ToArray(), true, true), argNeedsDynamicAccess);
}
public uint[] MapIndexBuffer(MapMode argAccessMode)
{
var rawData = this.MapIndexBufferRaw(argAccessMode);
this.typeMappedIndexData = new uint[this.IndexBufferLength];
rawData.Position = 0;
rawData.ReadRange(this.typeMappedIndexData, 0, this.IndexBufferLength);
rawData.Position = 0;
return this.typeMappedIndexData;
}
#endregion
#region IGeometryBuffer<TVertex> Members
public void SetVertexData<TVertex>(IEnumerable<TVertex> argVertexData, VertexElement[] argVertexElements, bool argNeedsDynamicAccess) where TVertex : struct
{
this.SetVertexData(argVertexData.Count(), new DataStream(argVertexData.ToArray(), true, true), argVertexElements, argNeedsDynamicAccess);
}
public TVertex[] MapVertexBuffer<TVertex>(MapMode argAccessMode) where TVertex : struct
{
var rawData = this.MapVertexBufferRaw(argAccessMode);
typeMappedVertexDataType = typeof(TVertex);
var tmp = new TVertex[this.VertexBufferLength];
typeMappedVertexData = tmp;
rawData.Position = 0;
rawData.ReadRange<TVertex>(tmp, 0, this.VertexBufferLength);
rawData.Position = 0;
return tmp;
}
#endregion
};
}

View File

@@ -0,0 +1,106 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Aiwaz.Contracts;
using SlimDX;
namespace Aiwaz.Resources
{
public class PickHull : IPickHull
{
private VertexElement positionElement;
private int strideToPosition;
private DataStream vertexData;
private int vertexCount;
private VertexElement[] vertexElements;
private int vertexElementSize;
private DataStream indexData;
private int indexCount;
private Vector3 boxMaxVector;
private Vector3 boxMinVector;
public PickHull(DataStream vertexData, int vertexCount, VertexElement[] vertexElements, DataStream indexData, int indexCount)
{
this.vertexData = vertexData;
this.vertexCount = vertexCount;
this.vertexElements = vertexElements;
this.indexData = indexData;
this.indexCount = indexCount;
this.vertexElementSize = (int)vertexData.Length / vertexCount;
this.positionElement = vertexElements.First(e => e.WellKnownFormat == VertexElement.Format.Position);
foreach (var element in vertexElements)
{
if (!element.Equals(positionElement))
strideToPosition += element.Size;
else
break;
}
this.Precalculate();
}
public bool TryPick(Ray pickRay, Matrix worldMatrix, out float distance)
{
distance = float.MaxValue;
var boundingSphere = CalcBoundingSphere(worldMatrix);
if (!Ray.Intersects(pickRay, boundingSphere, out distance))
return false;
distance = float.MaxValue;
indexData.Position = 0;
for (var i = 0; i < indexCount / 3; ++i)
{
var triangle = new Vector3[3];
triangle[0] = Vector3.TransformCoordinate(this.GetPositionFromData(indexData.Read<uint>()), worldMatrix);
triangle[1] = Vector3.TransformCoordinate(this.GetPositionFromData(indexData.Read<uint>()), worldMatrix);
triangle[2] = Vector3.TransformCoordinate(this.GetPositionFromData(indexData.Read<uint>()), worldMatrix);
float newDistance;
if (!Ray.Intersects(pickRay, triangle[0], triangle[1], triangle[2], out newDistance)
|| newDistance > distance)
continue;
distance = newDistance;
}
return distance != float.MaxValue;
}
private Vector3 GetPositionFromData(uint index)
{
vertexData.Position = index * vertexElementSize + strideToPosition;
return vertexData.Read<Vector3>();
}
protected void Precalculate()
{
boxMinVector = Vector3.Zero;
boxMaxVector = Vector3.Zero;
for (uint i = 0; i < vertexCount; ++i)
{
boxMinVector = i == 0 ? this.GetPositionFromData(i) : Vector3.Maximize(boxMinVector, this.GetPositionFromData(i));
boxMaxVector = i == 0 ? this.GetPositionFromData(i) : Vector3.Minimize(boxMaxVector, this.GetPositionFromData(i));
}
}
public BoundingSphere CalcBoundingSphere(Matrix worldMatrix)
{
var centerPosition = Vector3.TransformCoordinate(Vector3.Zero, worldMatrix);
var maxVec = Vector3.TransformCoordinate(boxMaxVector, worldMatrix);
return new BoundingSphere(centerPosition, maxVec.Length());
}
public BoundingBox CalcBoundingBox(Matrix worldMatrix)
{
var minVec = Vector3.TransformCoordinate(boxMinVector, worldMatrix);
var maxVec = Vector3.TransformCoordinate(boxMaxVector, worldMatrix);
return new BoundingBox(minVec, maxVec);
}
}
}

View File

@@ -0,0 +1,133 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Aiwaz.Contracts;
using SlimDX;
using Aiwaz.Resources.Attributes;
using System.Collections.ObjectModel;
namespace Aiwaz.Resources.Prefab
{
[CreationParameters("Standard unity-sized non-inverted cube")]
public class CubeParams : ICreationParams
{
public float Width;
public float Height;
public float Depth;
public bool IsInverted;
public CubeParams()
{
Width = 1.0f;
Height = 1.0f;
Depth = 1.0f;
IsInverted = false;
}
}
[AiwazResource("Cube", "A simple non-uniform cube")]
public class Cube : Resource
{
public struct CommonCubeVertex
{
public CommonCubeVertex(SlimDX.Vector3 pos,
SlimDX.Vector3 normal,
SlimDX.Vector3 tangent,
SlimDX.Vector2 tex)
{
this.Pos = pos;
this.Normal = normal;
this.Tangent = tangent;
this.Tex = tex;
}
public SlimDX.Vector3 Pos;
public SlimDX.Vector3 Normal;
public SlimDX.Vector3 Tangent;
public SlimDX.Vector2 Tex;
};
public GeometryBuffer GeometryBuffer { get; protected set; }
public Cube(CubeParams parameters)
{
creationParams = parameters;
float width = parameters.Width * 0.5f;
float height = parameters.Height * 0.5f;
float depth = parameters.Depth * 0.5f;
float normal = parameters.IsInverted ? -1.0f : 1.0f;
float tangent = 1.0f;//isInverted ? -1.0f : 1.0f;
CommonCubeVertex[] vertices = new CommonCubeVertex[]
{
new CommonCubeVertex ( new SlimDX.Vector3( -width, height, -depth ), new SlimDX.Vector3(0.0f, normal, 0.0f), new SlimDX.Vector3(-tangent, 0.0f, 0.0f), new SlimDX.Vector2( 0.0f, 0.0f ) ),
new CommonCubeVertex ( new SlimDX.Vector3( width, height, -depth ), new SlimDX.Vector3(0.0f, normal, 0.0f), new SlimDX.Vector3(-tangent, 0.0f, 0.0f), new SlimDX.Vector2( 1.0f, 0.0f ) ),
new CommonCubeVertex ( new SlimDX.Vector3( width, height, depth ), new SlimDX.Vector3(0.0f, normal, 0.0f), new SlimDX.Vector3(-tangent, 0.0f, 0.0f), new SlimDX.Vector2( 1.0f, 1.0f ) ),
new CommonCubeVertex ( new SlimDX.Vector3( -width, height, depth ), new SlimDX.Vector3(0.0f, normal, 0.0f), new SlimDX.Vector3(-tangent, 0.0f, 0.0f), new SlimDX.Vector2( 0.0f, 1.0f ) ),
new CommonCubeVertex ( new SlimDX.Vector3( -width, -height, -depth ), new SlimDX.Vector3(0.0f, -normal, 0.0f), new SlimDX.Vector3(-tangent, 0.0f, 0.0f), new SlimDX.Vector2( 0.0f, 0.0f ) ),
new CommonCubeVertex ( new SlimDX.Vector3( width, -height, -depth ), new SlimDX.Vector3(0.0f, -normal, 0.0f), new SlimDX.Vector3(-tangent, 0.0f, 0.0f), new SlimDX.Vector2( 1.0f, 0.0f ) ),
new CommonCubeVertex ( new SlimDX.Vector3( width, -height, depth ), new SlimDX.Vector3(0.0f, -normal, 0.0f), new SlimDX.Vector3(-tangent, 0.0f, 0.0f), new SlimDX.Vector2( 1.0f, 1.0f ) ),
new CommonCubeVertex ( new SlimDX.Vector3( -width, -height, depth ), new SlimDX.Vector3(0.0f, -normal, 0.0f), new SlimDX.Vector3(-tangent, 0.0f, 0.0f), new SlimDX.Vector2( 0.0f, 1.0f ) ),
new CommonCubeVertex ( new SlimDX.Vector3( -width, -height, depth ), new SlimDX.Vector3(-normal, 0.0f, 0.0f), new SlimDX.Vector3(0.0f, tangent, 0.0f), new SlimDX.Vector2( 0.0f, 1.0f ) ),
new CommonCubeVertex ( new SlimDX.Vector3( -width, -height, -depth ), new SlimDX.Vector3(-normal, 0.0f, 0.0f), new SlimDX.Vector3(0.0f, tangent, 0.0f), new SlimDX.Vector2( 1.0f, 1.0f ) ),
new CommonCubeVertex ( new SlimDX.Vector3( -width, height, -depth ), new SlimDX.Vector3(-normal, 0.0f, 0.0f), new SlimDX.Vector3(0.0f, tangent, 0.0f), new SlimDX.Vector2( 1.0f, 0.0f ) ),
new CommonCubeVertex ( new SlimDX.Vector3( -width, height, depth ), new SlimDX.Vector3(-normal, 0.0f, 0.0f), new SlimDX.Vector3(0.0f, tangent, 0.0f), new SlimDX.Vector2( 0.0f, 0.0f ) ),
new CommonCubeVertex ( new SlimDX.Vector3( width, -height, depth ), new SlimDX.Vector3(normal, 0.0f, 0.0f), new SlimDX.Vector3(0.0f, -tangent, 0.0f), new SlimDX.Vector2( 1.0f, 1.0f ) ),
new CommonCubeVertex ( new SlimDX.Vector3( width, -height, -depth ), new SlimDX.Vector3(normal, 0.0f, 0.0f), new SlimDX.Vector3(0.0f, -tangent, 0.0f), new SlimDX.Vector2( 0.0f, 1.0f ) ),
new CommonCubeVertex ( new SlimDX.Vector3( width, height, -depth ), new SlimDX.Vector3(normal, 0.0f, 0.0f), new SlimDX.Vector3(0.0f, -tangent, 0.0f), new SlimDX.Vector2( 0.0f, 0.0f ) ),
new CommonCubeVertex ( new SlimDX.Vector3( width, height, depth ), new SlimDX.Vector3(normal, 0.0f, 0.0f), new SlimDX.Vector3(0.0f, -tangent, 0.0f), new SlimDX.Vector2( 1.0f, 0.0f ) ),
new CommonCubeVertex ( new SlimDX.Vector3( -width, -height, -depth ), new SlimDX.Vector3(0.0f, 0.0f, -normal), new SlimDX.Vector3(-tangent, 0.0f, 0.0f), new SlimDX.Vector2( 0.0f, 1.0f ) ),
new CommonCubeVertex ( new SlimDX.Vector3( width, -height, -depth ), new SlimDX.Vector3(0.0f, 0.0f, -normal), new SlimDX.Vector3(-tangent, 0.0f, 0.0f), new SlimDX.Vector2( 1.0f, 1.0f ) ),
new CommonCubeVertex ( new SlimDX.Vector3( width, height, -depth ), new SlimDX.Vector3(0.0f, 0.0f, -normal), new SlimDX.Vector3(-tangent, 0.0f, 0.0f), new SlimDX.Vector2( 1.0f, 0.0f ) ),
new CommonCubeVertex ( new SlimDX.Vector3( -width, height, -depth ), new SlimDX.Vector3(0.0f, 0.0f, -normal), new SlimDX.Vector3(-tangent, 0.0f, 0.0f), new SlimDX.Vector2( 0.0f, 0.0f ) ),
new CommonCubeVertex ( new SlimDX.Vector3( -width, -height, depth ), new SlimDX.Vector3(0.0f, 0.0f, normal), new SlimDX.Vector3(-tangent, 0.0f, 0.0f), new SlimDX.Vector2( 1.0f, 1.0f ) ),
new CommonCubeVertex ( new SlimDX.Vector3( width, -height, depth ), new SlimDX.Vector3(0.0f, 0.0f, normal), new SlimDX.Vector3(-tangent, 0.0f, 0.0f), new SlimDX.Vector2( 0.0f, 1.0f ) ),
new CommonCubeVertex ( new SlimDX.Vector3( width, height, depth ), new SlimDX.Vector3(0.0f, 0.0f, normal), new SlimDX.Vector3(-tangent, 0.0f, 0.0f), new SlimDX.Vector2( 0.0f, 0.0f ) ),
new CommonCubeVertex ( new SlimDX.Vector3( -width, height, depth ), new SlimDX.Vector3(0.0f, 0.0f, normal), new SlimDX.Vector3(-tangent, 0.0f, 0.0f), new SlimDX.Vector2( 1.0f, 0.0f ) ),
};
var vertexElements = new VertexElement[]
{
new VertexElement(VertexElement.Format.Position),
new VertexElement(VertexElement.Format.Normal),
new VertexElement(VertexElement.Format.Tangent),
new VertexElement(VertexElement.Format.Texture2D)
};
var invertedIndices = new uint[] { 0,1,3, 3,1,2, 5,4,6, 6,4,7, 8,9,11, 11,9,10, 13,12,14, 14,12,15, 16,17,19, 19,17,18, 21,20,22, 22,20,23 };
var normalIndices = new uint[] { 3,1,0, 2,1,3, 6,4,5, 7,4,6, 11,9,8, 10,9,11, 14,12,13, 15,12,14, 19,17,16, 18,17,19, 22,20,21, 23,20,22 };
this.GeometryBuffer = GeometryBuffer.Create<CommonCubeVertex>(
parameters.IsInverted ? invertedIndices : normalIndices,
vertices,
vertexElements,
false);
}
private ICreationParams creationParams;
public override ICreationParams CreationParams
{
get { return creationParams; }
}
private ObservableCollection<IResource> children;
[ReadOnly]
public override ObservableCollection<IResource> Children
{
get
{
if (children == null)
{
children = new ObservableCollection<IResource>();
children.Add(GeometryBuffer);
}
return children;
}
}
}
}

View File

@@ -0,0 +1,135 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Aiwaz.Contracts;
using Aiwaz.Resources.Attributes;
using System.Collections.ObjectModel;
namespace Aiwaz.Resources.Prefab
{
public struct PingPongBufferDescription
{
public int LoopCount;
public string ShaderFileName;
public string ShaderTechniqueA;
public string ShaderTechniqueB;
public string PreProcessShaderTechnique;
public int TextureWidth;
public int TextureHeight;
public SlimDX.DXGI.Format TextureFormat;
};
[CreationParameters("Standard ping-pong buffer")]
public class PingPongBufferParams : ICreationParams
{
public PingPongBufferDescription Desc;
public Texture InputTexture;
public PingPongBufferParams()
{
}
}
[AiwazResource("PingPong buffer", "Two buffers that alternate each other")]
public class PingPongBuffer : Resource
{
public Texture InputTexture { get; protected set;}
public Texture OutputTexture { get { return textureB.Texture; } }
public RenderCommandNode RootNode { get; protected set; }
public RenderCommandNode PreProcessNode { get; protected set; }
RenderCommandNode renderTargetNodeA;
RenderCommandNode renderTargetNodeB;
Shader shaderA;
Shader shaderB;
Shader shaderPreProcess;
RenderTargetTexture textureA;
RenderTargetTexture textureB;
GeometryBuffer screenQuad;
ShaderParameterSet shaderParameterA;
ShaderParameterSet shaderParameterB;
ShaderParameterSet shaderParameterPreProcess;
public PingPongBuffer(PingPongBufferParams parameters)
{
creationParams = parameters;
if (string.IsNullOrEmpty(parameters.Desc.ShaderFileName))
throw new ArgumentNullException("ShaderFileName");
shaderA = new Shader(new ShaderParams() { FileName = parameters.Desc.ShaderFileName, TechniqueName = parameters.Desc.ShaderTechniqueA } );
shaderB = new Shader(new ShaderParams() { FileName = parameters.Desc.ShaderFileName, TechniqueName = parameters.Desc.ShaderTechniqueB } );
shaderPreProcess = new Shader(new ShaderParams() { FileName = parameters.Desc.ShaderFileName, TechniqueName = parameters.Desc.PreProcessShaderTechnique });
textureA = new RenderTargetTexture(new RenderTargetTextureParams() { width = parameters.Desc.TextureWidth, height = parameters.Desc.TextureHeight, format = parameters.Desc.TextureFormat } );
textureB = new RenderTargetTexture(new RenderTargetTextureParams() { width = parameters.Desc.TextureWidth, height = parameters.Desc.TextureHeight, format = parameters.Desc.TextureFormat } );
shaderParameterA = new ShaderParameterSet();
shaderParameterA.SetParameter("InputTexture", textureB.Texture, ParameterBindType.BindBySemantic);
shaderParameterB = new ShaderParameterSet();
shaderParameterB.SetParameter("InputTexture", textureA.Texture, ParameterBindType.BindBySemantic);
this.InputTexture = parameters.InputTexture;
shaderParameterPreProcess = new ShaderParameterSet();
shaderParameterPreProcess.SetParameter("InputTexture", this.InputTexture, ParameterBindType.BindBySemantic);
var quad = new Quad(new QuadParams() { Width = 2.0f, Height = 2.0f } );
screenQuad = quad.GeometryBuffer;
renderTargetNodeA = new RenderCommandNode();
renderTargetNodeA.Children.Add(textureA);
renderTargetNodeA.Children.Add(shaderA);
renderTargetNodeA.Children.Add(shaderParameterA);
renderTargetNodeA.Children.Add(screenQuad);
renderTargetNodeB = new RenderCommandNode();
renderTargetNodeB.Children.Add(textureB);
renderTargetNodeB.Children.Add(shaderB);
renderTargetNodeB.Children.Add(shaderParameterB);
renderTargetNodeB.Children.Add(screenQuad);
this.RootNode = new RenderCommandNode();
this.PreProcessNode = new RenderCommandNode();
// preprocessing
this.RootNode.Children.Add(textureB);
this.RootNode.Children.Add(shaderPreProcess);
this.RootNode.Children.Add(shaderParameterPreProcess);
this.RootNode.Children.Add(screenQuad);
this.RootNode.Children.Add(this.PreProcessNode);
// real pingpongs
for (int i = 0; i < parameters.Desc.LoopCount; ++i)
{
this.RootNode.Children.Add(renderTargetNodeA);
this.RootNode.Children.Add(renderTargetNodeB);
}
}
private ICreationParams creationParams;
public override ICreationParams CreationParams
{
get { return creationParams; }
}
private ObservableCollection<IResource> children;
[ReadOnly]
public override ObservableCollection<IResource> Children
{
get
{
if (children == null)
{
children = new ObservableCollection<IResource>();
children.Add(InputTexture);
children.Add(OutputTexture);
children.Add(RootNode);
children.Add(PreProcessNode);
}
return children;
}
}
}
}

View File

@@ -0,0 +1,119 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Aiwaz.Contracts;
using SlimDX;
using Aiwaz.Resources.Attributes;
using System.Collections.ObjectModel;
namespace Aiwaz.Resources.Prefab
{
[CreationParameters("Unity-sized one-sided quad")]
public class QuadParams : ICreationParams
{
public float Width;
public float Height;
public bool IsTwoSided;
public QuadParams()
{
Width = 1.0f;
Height = 1.0f;
IsTwoSided = false;
}
}
[AiwazResource("Quad", "A simple 2d non-uniform Quad")]
public class Quad : Resource
{
public struct CommonQuadVertex
{
public CommonQuadVertex(SlimDX.Vector3 pos,
SlimDX.Vector3 normal,
SlimDX.Vector2 tex)
{
this.Pos = pos;
this.Normal = normal;
this.Tex = tex;
}
public SlimDX.Vector3 Pos;
public SlimDX.Vector3 Normal;
public SlimDX.Vector2 Tex;
};
public GeometryBuffer GeometryBuffer { get; protected set; }
public Quad(QuadParams parameters)
{
this.creationParams = parameters;
float width = parameters.Width * 0.5f;
float height = parameters.Height * 0.5f;
CommonQuadVertex[] quadOneSidedVertices = new CommonQuadVertex[]
{
new CommonQuadVertex( new SlimDX.Vector3( -width, height, 0.0f ), new SlimDX.Vector3(0.0f, 0.0f, -1.0f), new SlimDX.Vector2( 0.0f, 0.0f ) ),
new CommonQuadVertex( new SlimDX.Vector3( width, -height, 0.0f ), new SlimDX.Vector3(0.0f, 0.0f, -1.0f), new SlimDX.Vector2( 1.0f, 1.0f ) ),
new CommonQuadVertex( new SlimDX.Vector3( -width, -height, 0.0f ), new SlimDX.Vector3(0.0f, 0.0f, -1.0f), new SlimDX.Vector2( 0.0f, 1.0f ) ),
new CommonQuadVertex( new SlimDX.Vector3( -width, height, 0.0f ), new SlimDX.Vector3(0.0f, 0.0f, -1.0f), new SlimDX.Vector2( 0.0f, 0.0f ) ),
new CommonQuadVertex( new SlimDX.Vector3( width, height, 0.0f ), new SlimDX.Vector3(0.0f, 0.0f, -1.0f), new SlimDX.Vector2( 1.0f, 0.0f ) ),
new CommonQuadVertex( new SlimDX.Vector3( width, -height, 0.0f ), new SlimDX.Vector3(0.0f, 0.0f, -1.0f), new SlimDX.Vector2( 1.0f, 1.0f ) ),
};
CommonQuadVertex[] quadTwoSidedVertices = new CommonQuadVertex[]
{
new CommonQuadVertex( new SlimDX.Vector3( -width, height, 0.0f ), new SlimDX.Vector3(0.0f, 0.0f, -1.0f), new SlimDX.Vector2( 0.0f, 0.0f ) ),
new CommonQuadVertex( new SlimDX.Vector3( width, -height, 0.0f ), new SlimDX.Vector3(0.0f, 0.0f, -1.0f), new SlimDX.Vector2( 1.0f, 1.0f ) ),
new CommonQuadVertex( new SlimDX.Vector3( -width, -height, 0.0f ), new SlimDX.Vector3(0.0f, 0.0f, -1.0f), new SlimDX.Vector2( 0.0f, 1.0f ) ),
new CommonQuadVertex( new SlimDX.Vector3( -width, height, 0.0f ), new SlimDX.Vector3(0.0f, 0.0f, -1.0f), new SlimDX.Vector2( 0.0f, 0.0f ) ),
new CommonQuadVertex( new SlimDX.Vector3( width, height, 0.0f ), new SlimDX.Vector3(0.0f, 0.0f, -1.0f), new SlimDX.Vector2( 1.0f, 0.0f ) ),
new CommonQuadVertex( new SlimDX.Vector3( width, -height, 0.0f ), new SlimDX.Vector3(0.0f, 0.0f, -1.0f), new SlimDX.Vector2( 1.0f, 1.0f ) ),
new CommonQuadVertex( new SlimDX.Vector3( -width, height, 0.0f ), new SlimDX.Vector3(0.0f, 0.0f, 1.0f), new SlimDX.Vector2( 1.0f, 0.0f ) ),
new CommonQuadVertex( new SlimDX.Vector3( width, -height, 0.0f ), new SlimDX.Vector3(0.0f, 0.0f, 1.0f), new SlimDX.Vector2( 0.0f, 1.0f ) ),
new CommonQuadVertex( new SlimDX.Vector3( -width, -height, 0.0f ), new SlimDX.Vector3(0.0f, 0.0f, 1.0f), new SlimDX.Vector2( 1.0f, 1.0f ) ),
new CommonQuadVertex( new SlimDX.Vector3( -width, height, 0.0f ), new SlimDX.Vector3(0.0f, 0.0f, 1.0f), new SlimDX.Vector2( 1.0f, 0.0f ) ),
new CommonQuadVertex( new SlimDX.Vector3( width, height, 0.0f ), new SlimDX.Vector3(0.0f, 0.0f, 1.0f), new SlimDX.Vector2( 0.0f, 0.0f ) ),
new CommonQuadVertex( new SlimDX.Vector3( width, -height, 0.0f ), new SlimDX.Vector3(0.0f, 0.0f, 1.0f), new SlimDX.Vector2( 0.0f, 1.0f ) ),
};
var vertexElements = new VertexElement[]
{
new VertexElement(VertexElement.Format.Position),
new VertexElement(VertexElement.Format.Normal),
new VertexElement(VertexElement.Format.Texture2D)
};
var oneSidedIndices = new uint[] { 0,1,2, 3,4,5 };
var twoSidedIndices = new uint[] { 0, 1, 2, 3, 4, 5, 11, 10, 9, 8, 7, 6 };
this.GeometryBuffer = GeometryBuffer.Create<CommonQuadVertex>(
parameters.IsTwoSided ? twoSidedIndices : oneSidedIndices,
parameters.IsTwoSided ? quadTwoSidedVertices : quadOneSidedVertices,
vertexElements,
false);
}
private ICreationParams creationParams;
public override ICreationParams CreationParams
{
get { return creationParams; }
}
private ObservableCollection<IResource> children;
[ReadOnly]
public override ObservableCollection<IResource> Children
{
get
{
if (children == null)
{
children = new ObservableCollection<IResource>();
children.Add(GeometryBuffer);
}
return children;
}
}
}
}

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("AiwazResources")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("AiwazResources")]
[assembly: AssemblyCopyright("Copyright © Microsoft 2010")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("db9f92df-997d-4870-b687-8cc93789465e")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,179 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Aiwaz.Contracts;
using Aiwaz.Core;
using Aiwaz.Resources.Attributes;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
namespace Aiwaz.Resources
{
[AiwazResource("RenderCommand Node", "Node to update and perform other nodes.")]
public class RenderCommandNode : CommandUser, IUpdatable
{
#region IRenderCommandNode Members
private ObservableCollection<IResource> children;
public CommandBuffer CommandBuffer { get; protected set; }
public bool IsDirty { get; protected set;}
public RenderCommandNode ParentRenderCommandNode { get; set; }
public RenderCommandNode()
{
Console.WriteLine(string.Format("Creating RenderCommandNode.."));
children = new ObservableCollection<IResource>();
children.CollectionChanged += new NotifyCollectionChangedEventHandler(children_CollectionChanged);
CommandBuffer = new CommandBuffer();
}
void children_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
List<CommandUser> commandUsers = new List<CommandUser>();
if (e.Action == NotifyCollectionChangedAction.Add)
{
foreach (IResource resource in e.NewItems)
GetCommandUsers(resource, ref commandUsers);
foreach (CommandUser user in commandUsers)
{
user.AssignToRenderCommandNode(this);
var node = user as RenderCommandNode;
if (node != null)
node.ParentRenderCommandNode = this;
}
this.MarkDirty();
}
else if (e.Action == NotifyCollectionChangedAction.Remove)
{
foreach (IResource resource in e.OldItems)
GetCommandUsers(resource, ref commandUsers);
foreach (CommandUser user in commandUsers)
{
var node = user as RenderCommandNode;
if (node != null)
node.ParentRenderCommandNode = null;
user.UnassignFromRenderCommandNode(this);
}
this.MarkDirty();
}
}
public void MarkDirty()
{
IsDirty = true;
if (ParentRenderCommandNode != null)
ParentRenderCommandNode.MarkDirty();
}
public void ProcessCommands()
{
if (IsDirty)
{
this.GenerateDeviceCommands();
CommandBuffer.Optimize();
}
CommandBuffer.Perform(true);
}
public void GenerateDeviceCommands()
{
if (!IsDirty)
return;
IsDirty = false;
CommandBuffer.Clear();
List<CommandUser> commandUsers = new List<CommandUser>();
foreach (var child in children)
GetCommandUsers(child, ref commandUsers);
foreach (CommandUser user in commandUsers)
{
// Add the commands all commands
CommandBuffer.BufferedCommands.AddRange(user.Commands);
// Walk further if we found another RenderCommandNode
var node = user as RenderCommandNode;
if (node != null)
{
node.GenerateDeviceCommands();
// Merge the buffers
CommandBuffer.AddChildCommandBuffer(node.CommandBuffer);
}
}
}
private void GetCommandUsers(IResource resource, ref List<CommandUser> commandUsers)
{
if (resource as CommandUser != null)
commandUsers.Add(resource as CommandUser);
else foreach (var child in resource.Children)
GetCommandUsers(child, ref commandUsers);
}
#endregion
public override CommandExecuteResult ExecuteCommand(byte argCommandType, CommandBuffer argCurrentBuffer, int argCurrentPositon)
{
return CommandExecuteResult.None;
}
#region IUpdatable Members
public void Update(bool forceUpdate)
{
List<CommandUser> commandUsers = new List<CommandUser>();
foreach (var child in children)
GetCommandUsers(child, ref commandUsers);
// Walk through all updatables and update them.
foreach (var user in commandUsers)
{
var updatable = user as IUpdatable;
if (updatable != null && (updatable.WantsUpdate || forceUpdate))
updatable.Update(forceUpdate);
}
}
public bool WantsUpdate
{
get { return true; }
}
#endregion
#region IDisposable Members
public override void Dispose()
{
if (ParentRenderCommandNode != null)
ParentRenderCommandNode.Children.Remove(this);
while (Children.Count > 0)
Children.RemoveAt(0);
base.Dispose();
}
#endregion
public override ICreationParams CreationParams
{
get { return null; }
}
public override ObservableCollection<IResource> Children
{
get { return children; }
}
}
}

View File

@@ -0,0 +1,296 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Aiwaz.Contracts;
using Aiwaz.Core;
namespace Aiwaz.Resources
{
public abstract class RenderTarget : CommandUser, IRenderTargetBase, IDisposable
{
public RenderTarget()
: base()
{
Commands.Add(new Command(this, CommandFlags.EndChain | CommandFlags.FlushChain, setRenderTargetCommandType, 0, 0));
this.ClearDepth = 1.0f;
}
~RenderTarget()
{
if (Engine.Initialized)
this.Dispose();
}
#region IRenderTargetBase Members
internal static SlimDX.Direct3D10.ShaderResourceView[] emptyShaderResView = new SlimDX.Direct3D10.ShaderResourceView[128];
private SlimDX.Direct3D10.RenderTargetView[] renderTargetViews;
private List<IRenderTargetBase> additionalRenderTargets = new List<IRenderTargetBase>();
private SlimDX.Direct3D10.Viewport[] viewports;
protected int multiSampleCount = 1;
protected int multiSampleQuality = 0;
private BindFlags lastBindFlags = BindFlags.Default;
public float ClearDepth { get; set; }
public byte ClearStencil { get; set; }
public SlimDX.Color4 ClearColor { get; set; }
private ViewPort viewPort;
public ViewPort ViewPort
{
get { return viewPort; }
set
{
viewPort = value;
this.KillViewPortAndRenderTargetData();
this.BuildViewPortAndRenderTargetData();
}
}
public abstract int RenderTargetWidth { get; }
public abstract int RenderTargetHeight { get; }
public abstract SlimDX.DXGI.Format RenderTargetFormat { get; }
private bool hasDepthStencilBuffer;
public bool HasDepthStencilBuffer
{
get { return hasDepthStencilBuffer; }
set
{
hasDepthStencilBuffer = value;
Engine.Device.ClearState();
if (DX10DepthStencilView != null)
DX10DepthStencilView.Dispose();
DX10DepthStencilView = null;
if (DX10DepthStencilTexture != null)
DX10DepthStencilTexture.Dispose();
DX10DepthStencilTexture = null;
if (!hasDepthStencilBuffer)
return; // no further effort needed here
var depthTextureDesc = new SlimDX.Direct3D10.Texture2DDescription()
{
Width = this.RenderTargetWidth,
Height = this.RenderTargetHeight,
MipLevels = 1,
ArraySize = 1,
Format = SlimDX.DXGI.Format.D24_UNorm_S8_UInt,
SampleDescription = new SlimDX.DXGI.SampleDescription(multiSampleCount == 0 ? 1 : multiSampleCount, multiSampleQuality),
Usage = SlimDX.Direct3D10.ResourceUsage.Default,
BindFlags = SlimDX.Direct3D10.BindFlags.DepthStencil,
CpuAccessFlags = SlimDX.Direct3D10.CpuAccessFlags.None,
OptionFlags = SlimDX.Direct3D10.ResourceOptionFlags.None
};
DX10DepthStencilTexture = new SlimDX.Direct3D10.Texture2D(Engine.Device, depthTextureDesc);
if (DX10DepthStencilTexture == null)
throw new Aiwaz.Core.ActionFailedException("RenderTarget: Unable to create depth stencil texture.");
var depthStencilViewDesc = new SlimDX.Direct3D10.DepthStencilViewDescription()
{
Format = depthTextureDesc.Format,
Dimension = multiSampleCount >= 1 ? SlimDX.Direct3D10.DepthStencilViewDimension.Texture2DMultisampled : SlimDX.Direct3D10.DepthStencilViewDimension.Texture2D,
MipSlice = 0
};
DX10DepthStencilView = new SlimDX.Direct3D10.DepthStencilView(Engine.Device, DX10DepthStencilTexture, depthStencilViewDesc);
if (DX10DepthStencilView == null)
throw new Aiwaz.Core.ActionFailedException("RenderTarget: Unable to create depth stencil view.");
}
}
public SlimDX.Direct3D10.RenderTargetView DX10RenderTargetView { get; protected set; }
public SlimDX.Direct3D10.DepthStencilView DX10DepthStencilView { get; protected set; }
public SlimDX.Direct3D10.Texture2D DX10DepthStencilTexture { get; protected set; }
public void AddAdditionalRenderTarget(IRenderTargetBase target)
{
this.RemoveAdditionalRenderTarget(target);
//if (AdditionalRenderTargets.Count + 1 == D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT)
// throw new Aiwaz.Core.ActionFailedException("RenderTarget: Unable to add an additional rendering target, list is full.");
additionalRenderTargets.Add(target);
this.KillViewPortAndRenderTargetData();
this.BuildViewPortAndRenderTargetData();
}
public void RemoveAdditionalRenderTarget(IRenderTargetBase target)
{
if (additionalRenderTargets.Remove(target))
{
this.KillViewPortAndRenderTargetData();
this.BuildViewPortAndRenderTargetData();
}
}
public void Bind(BindFlags bindFlags)
{
if ((bindFlags & ~ BindFlags.ClearAll) != (lastBindFlags & ~ BindFlags.ClearAll))
{
lastBindFlags = bindFlags;
this.KillViewPortAndRenderTargetData();
this.BuildViewPortAndRenderTargetData();
}
else
lastBindFlags = bindFlags;
this.Clear(bindFlags);
Engine.Device.PixelShader.SetShaderResources(emptyShaderResView, 0, 128);
Engine.Device.OutputMerger.SetTargets(DX10DepthStencilView, renderTargetViews);
Engine.Device.Rasterizer.SetViewports(viewports);
Engine.EngineStates.LastRenderTarget = this;
}
public void UnbindAllRenderTargets()
{
if (Engine.EngineStates.LastRenderTarget == this)
{
Engine.Device.OutputMerger.SetTargets(new SlimDX.Direct3D10.RenderTargetView[0]);
Engine.Device.Rasterizer.SetViewports(new SlimDX.Direct3D10.Viewport[0]);
Engine.EngineStates.LastRenderTarget = null;
}
}
protected void BuildViewPortAndRenderTargetData()
{
// Rebuild render targets
if (renderTargetViews == null && viewports == null)
{
if ((lastBindFlags & BindFlags.BindAllTextures) == BindFlags.BindAllTextures)
{
renderTargetViews = new SlimDX.Direct3D10.RenderTargetView[additionalRenderTargets.Count + 1];
viewports = new SlimDX.Direct3D10.Viewport[additionalRenderTargets.Count + 1];
renderTargetViews[0] = this.DX10RenderTargetView;
viewports[0] = this.ViewPort;
for (int i = 0; i < additionalRenderTargets.Count; ++i)
{
renderTargetViews[i + 1] = additionalRenderTargets[i].DX10RenderTargetView;
viewports[i + 1] = additionalRenderTargets[i].ViewPort;
}
}
else if ((lastBindFlags & BindFlags.BindAllTextures) != BindFlags.None)
{
var activeRenderTargetCount = 0;
if ((lastBindFlags & BindFlags.BindBaseTexture) != BindFlags.None) ++activeRenderTargetCount;
if ((lastBindFlags & BindFlags.BindAdditionalTexture0) != BindFlags.None) ++activeRenderTargetCount;
if ((lastBindFlags & BindFlags.BindAdditionalTexture1) != BindFlags.None) ++activeRenderTargetCount;
if ((lastBindFlags & BindFlags.BindAdditionalTexture2) != BindFlags.None) ++activeRenderTargetCount;
if ((lastBindFlags & BindFlags.BindAdditionalTexture3) != BindFlags.None) ++activeRenderTargetCount;
renderTargetViews = new SlimDX.Direct3D10.RenderTargetView[activeRenderTargetCount];
viewports = new SlimDX.Direct3D10.Viewport[activeRenderTargetCount];
int bufferIndex = 0;
if ((lastBindFlags & BindFlags.BindBaseTexture) != BindFlags.None)
{
renderTargetViews[bufferIndex] = this.DX10RenderTargetView;
viewports[bufferIndex++] = this.ViewPort;
}
if ((lastBindFlags & BindFlags.BindAdditionalTexture0) != BindFlags.None)
{
renderTargetViews[bufferIndex] = additionalRenderTargets[0].DX10RenderTargetView;
viewports[bufferIndex++] = additionalRenderTargets[0].ViewPort;
}
if ((lastBindFlags & BindFlags.BindAdditionalTexture1) != BindFlags.None)
{
renderTargetViews[bufferIndex] = additionalRenderTargets[1].DX10RenderTargetView;
viewports[bufferIndex++] = additionalRenderTargets[1].ViewPort;
}
if ((lastBindFlags & BindFlags.BindAdditionalTexture2) != BindFlags.None)
{
renderTargetViews[bufferIndex] = additionalRenderTargets[2].DX10RenderTargetView;
viewports[bufferIndex++] = additionalRenderTargets[2].ViewPort;
}
if ((lastBindFlags & BindFlags.BindAdditionalTexture3) != BindFlags.None)
{
renderTargetViews[bufferIndex] = additionalRenderTargets[3].DX10RenderTargetView;
viewports[bufferIndex++] = additionalRenderTargets[3].ViewPort;
}
}
else
throw new ActionFailedException("No render target bindable.");
}
}
protected void KillViewPortAndRenderTargetData()
{
renderTargetViews = null;
viewports = null;
if (Engine.EngineStates.LastRenderTarget == this)
Engine.EngineStates.LastRenderTarget = null;
}
#endregion
#region IDisposable Members
protected void DisposeInternal()
{
this.KillViewPortAndRenderTargetData();
this.UnbindAllRenderTargets();
if (DX10RenderTargetView != null)
DX10RenderTargetView.Dispose();
DX10RenderTargetView = null;
if (DX10DepthStencilView != null)
DX10DepthStencilView.Dispose();
DX10DepthStencilView = null;
if (DX10DepthStencilTexture != null)
DX10DepthStencilTexture.Dispose();
DX10DepthStencilTexture = null;
}
public override void Dispose()
{
this.DisposeInternal();
base.Dispose();
}
#endregion
#region CommandUser
const byte setRenderTargetCommandType = 0;
public override CommandExecuteResult ExecuteCommand(byte commandType, CommandBuffer currentBuffer, int currentPositon)
{
if (commandType == setRenderTargetCommandType)
{
if (Engine.EngineStates.LastRenderTarget != this)
{
this.UnbindAllRenderTargets();
this.Bind(BindFlags.Default);
}
else
this.Clear(BindFlags.Default);
}
return CommandExecuteResult.None;
}
protected void Clear(BindFlags bindFlags)
{
if ((bindFlags & BindFlags.ClearColor) != BindFlags.None)
Engine.Device.ClearRenderTargetView(DX10RenderTargetView, ClearColor);
if ((bindFlags & BindFlags.ClearDepthStencil) != BindFlags.None && DX10DepthStencilView != null)
Engine.Device.ClearDepthStencilView(DX10DepthStencilView, SlimDX.Direct3D10.DepthStencilClearFlags.Depth | SlimDX.Direct3D10.DepthStencilClearFlags.Stencil, ClearDepth, ClearStencil);
}
#endregion
}
}

View File

@@ -0,0 +1,147 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Aiwaz.Contracts;
using Aiwaz.Core;
using Aiwaz.Resources.Attributes;
using System.Collections.ObjectModel;
namespace Aiwaz.Resources
{
[CreationParameters("Create an empty RenderTarget texture")]
public class RenderTargetTextureParams : ICreationParams
{
public int width;
public int height;
public SlimDX.DXGI.Format format;
public int multiSampleCount;
public int multiSampleQuality;
public RenderTargetTextureParams()
{
width = 512;
height = 512;
format = SlimDX.DXGI.Format.Unknown;
multiSampleCount = 0;
multiSampleQuality = 0;
}
}
[AiwazResource("RenderTarget texture", "An output target for render operations which could be used as texture input.")]
public class RenderTargetTexture : RenderTarget
{
public RenderTargetTexture(RenderTargetTextureParams parameters)
: base()
{
creationParams = parameters;
Console.WriteLine(string.Format("Creating RenderTargetTexture ({0}x{1} {2})..", parameters.width, parameters.height, parameters.format.ToString()));
this.BuildRenderTargetTexture(parameters.width, parameters.height, parameters.format, parameters.multiSampleCount, parameters.multiSampleQuality);
}
protected void BuildRenderTargetTexture(int width, int height, SlimDX.DXGI.Format format, int multiSampleCount, int multiSampleQuality)
{
if (this.Texture != null &&
width == this.RenderTargetWidth &&
height == this.RenderTargetHeight &&
format == this.RenderTargetFormat &&
this.multiSampleCount == multiSampleCount &&
this.multiSampleQuality == multiSampleQuality)
{
return;
}
this.DisposeInternal();
// get missing information
if (multiSampleCount == 0)
multiSampleCount = 1;
if (width == 0)
width = 1;
if (height == 0)
height = 1;
if (format == SlimDX.DXGI.Format.Unknown)
format = SlimDX.DXGI.Format.R8G8B8A8_UNorm;
this.multiSampleCount = multiSampleCount;
this.multiSampleQuality = multiSampleQuality;
if (this.Texture == null)
this.Texture = new Texture(new EmptyTextureParams()
{
Width = width,
Height = height,
Elements = 1,
MipLevels = 0,
Format = format,
AccessType = SlimDX.Direct3D10.ResourceUsage.Staging,
RenderTarget = true,
MultiSampleCount = multiSampleCount,
MultiSampleQuality = multiSampleQuality
});
else if (this.Texture is Texture)
((Texture)this.Texture).CreateRenderTargetTexture(width, height, format, multiSampleCount, multiSampleQuality);
this.DX10RenderTargetView = new SlimDX.Direct3D10.RenderTargetView(Engine.Device, this.Texture.Texture2D);
this.ViewPort = new ViewPort()
{
Width = width,
Height = height
};
}
public override int RenderTargetWidth
{
get { return Texture.TextureWidth; }
}
public override int RenderTargetHeight
{
get { return Texture.TextureHeight; }
}
public override SlimDX.DXGI.Format RenderTargetFormat
{
get { return Texture.TextureFormat; }
}
#region IRenderTargetTexture Members
public void Resize(int width, int height)
{
if (this.RenderTargetWidth == width || this.RenderTargetHeight == height)
return;
var usedDepthStencilBuffer = this.HasDepthStencilBuffer;
this.BuildRenderTargetTexture(width, height, RenderTargetFormat, multiSampleCount, multiSampleQuality);
this.HasDepthStencilBuffer = usedDepthStencilBuffer;
}
public Texture Texture { get; protected set; }
#endregion
private ICreationParams creationParams;
public override ICreationParams CreationParams
{
get { return creationParams; }
}
private ObservableCollection<IResource> children;
[ReadOnly]
public override ObservableCollection<IResource> Children
{
get
{
if (children == null)
{
children = new ObservableCollection<IResource>();
children.Add(Texture);
}
return children;
}
}
}
}

View File

@@ -0,0 +1,123 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Aiwaz.Contracts;
using Aiwaz.Core;
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace Aiwaz.Resources
{
public abstract class Resource : IResource, INotifyPropertyChanged, IDisposable
{
#region IResource Members
public abstract ICreationParams CreationParams
{
get;
}
protected string wellKnownName;
public string WellKnownName
{
get
{
if (wellKnownName == null)
{
string resourceName = null;
foreach (var attribute in this.GetType().GetCustomAttributes(true))
{
if (attribute.GetType().Equals(typeof(AiwazResourceAttribute)))
{
resourceName = ((AiwazResourceAttribute)attribute).Name;
}
}
if (resourceName == null)
resourceName = "Unknown resource";
int count = 1;
do
{
wellKnownName = string.Format("{0} {1}", resourceName, count++);
} while (Engine.ExistsName(wellKnownName));
Engine.RegisterNamedObject(wellKnownName, this);
}
return wellKnownName;
}
set
{
string newName = value;
if (Engine.ExistsName(newName))
{
int count = 1;
do
{
newName = string.Format("{0} {1}", value, count++);
} while (Engine.ExistsName(newName));
}
if (!string.IsNullOrEmpty(wellKnownName))
Engine.UnregisterNamedObject(wellKnownName);
wellKnownName = newName;
if (!string.IsNullOrEmpty(wellKnownName))
Engine.RegisterNamedObject(wellKnownName, this);
}
}
public IResource Parent
{
get;
set;
}
public abstract ObservableCollection<IResource> Children
{
get;
}
#endregion
#region INotifyPropertyChanged Members
protected void NotifyPropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
#region IDisposable Members
private bool _disposed = false;
protected bool Disposed
{
get { return _disposed; }
}
protected virtual void Dispose(bool disposing)
{
if (!Disposed)
{
_disposed = true;
}
}
public virtual void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~Resource() { Dispose(false); }
#endregion
}
}

View File

@@ -0,0 +1,209 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Aiwaz.Contracts;
using Aiwaz.Common;
using Aiwaz.Core;
using Aiwaz.Resources.Attributes;
using System.Collections.ObjectModel;
namespace Aiwaz.Resources
{
public class TechniqueNotFoundException : Exception { }
public class UnableToLoadShaderException : Exception
{
public UnableToLoadShaderException(string errors)
: base(errors)
{
}
}
[CreationParameters("Load a shader from file")]
public class ShaderParams : ICreationParams
{
[RequiredParameter]
public string FileName;
public string TechniqueName;
public ShaderParams()
{
FileName = null;
TechniqueName = null;
}
}
[AiwazResource("Shader", "A complex shader to perform individual shading operations when rendering geometry buffers.")]
public class Shader : CommandUser, IShader
{
#region IShader Members
const byte applyFirstPassCommandType = 0;
const byte nextPassCommandType = 1;
private InternalShader internalShader;
private string techniqueName;
private byte priority = 0;
public Shader(ShaderParams parameters)
{
creationParams = parameters;
Console.WriteLine(string.Format("Creating Shader ({0} Technique: {1})..", parameters.FileName, parameters.TechniqueName));
internalShader = Engine.FindNamedObject(parameters.FileName) as InternalShader;
if (internalShader == null)
internalShader = new InternalShader(parameters.FileName);
Commands.Add(new Command(this, CommandFlags.StartChain | CommandFlags.SubChainStart, applyFirstPassCommandType, 2, this.Priority));
Commands.Add(new Command(this, CommandFlags.SubChainEnd, nextPassCommandType, byte.MaxValue, this.Priority));
this.TechniqueName = parameters.TechniqueName;
}
public string TechniqueName
{
get { return techniqueName; }
set
{
techniqueName = value;
if (string.IsNullOrEmpty(techniqueName))
{
this.Technique = internalShader.Effect.GetTechniqueByIndex(0);
if (this.Technique != null)
techniqueName = this.Technique.Description.Name;
}
else
this.Technique = internalShader.Effect.GetTechniqueByName(TechniqueName);
if (this.Technique == null)
throw new TechniqueNotFoundException();
CurrentPass = 0;
}
}
public SlimDX.Direct3D10.EffectTechnique Technique { get; protected set; }
public SlimDX.Direct3D10.Effect Effect { get { return internalShader.Effect; } }
public byte Priority
{
get
{
return priority;
}
set
{
priority = value;
foreach (var command in Commands)
if (command.Type == applyFirstPassCommandType)
command.SubPriority = priority;
}
}
public int CurrentPass { get; protected set; }
#endregion
public override CommandExecuteResult ExecuteCommand(byte commandType, CommandBuffer currentBuffer, int currentPositon)
{
if (commandType == applyFirstPassCommandType)
{
CurrentPass = 0;
Engine.EngineStates.LastShader = this;
}
else if (commandType == nextPassCommandType)
{
if (CurrentPass >= this.Technique.Description.PassCount)
CurrentPass = this.Technique.Description.PassCount;
else
CurrentPass++;
if (CurrentPass >= this.Technique.Description.PassCount)
return CommandExecuteResult.None;
return CommandExecuteResult.RetrySubChainSkipHead;
}
return CommandExecuteResult.None;
}
#region IDisposable Members
public override void Dispose()
{
Engine.EngineStates.LastShader = null;
base.Dispose();
}
#endregion
private ICreationParams creationParams;
public override ICreationParams CreationParams
{
get { return creationParams; }
}
public override ObservableCollection<IResource> Children
{
get { return null; }
}
}
internal class InternalShader : IDisposable
{
#region IInternalShader Members
private string fileName;
public InternalShader(string fileName)
{
this.fileName = fileName;
Engine.RegisterNamedObject(fileName, this);
Engine.RegisterEngineDisposable(this);
using (var stream = Engine.FileSystem.Open(fileName))
{
string errors;
Effect = SlimDX.Direct3D10.Effect.FromStream(Engine.Device, stream, "fx_4_0",
#if DEBUG
SlimDX.Direct3D10.ShaderFlags.EnableStrictness | SlimDX.Direct3D10.ShaderFlags.Debug,
#else
SlimDX.Direct3D10.ShaderFlags.EnableStrictness,
#endif
SlimDX.Direct3D10.EffectFlags.None, null, null, out errors);
if (!string.IsNullOrEmpty(errors))
throw new UnableToLoadShaderException(errors);
}
}
~InternalShader()
{
if (!Engine.Initialized)
return;
Engine.UnregisterNamedObject(fileName);
if (Engine.UnregisterEngineDisposable(this))
this.Dispose();
}
public SlimDX.Direct3D10.Effect Effect { get; protected set; }
#endregion
#region IDisposable Members
public void Dispose()
{
if (this.Effect != null)
this.Effect.Dispose();
this.Effect = null;
Engine.UnregisterNamedObject(fileName);
Engine.UnregisterEngineDisposable(this);
}
#endregion
}
}

View File

@@ -0,0 +1,318 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Aiwaz.Contracts;
using Aiwaz.Core;
using Aiwaz.Common;
using System.Collections.ObjectModel;
namespace Aiwaz.Resources
{
public class ShaderNotSetException : Exception {}
public class UnsupportedShaderParameterTypeException : Exception {}
[AiwazResource("Shader parameter set", "A set of parameters for one or more shaders.")]
public class ShaderParameterSet : CommandUser, IShaderParameterSet
{
#region IShaderParameterSet Members
const byte setShaderParameterCollectionCommandType = 0;
const byte setFollowingShaderParameterCollectionCommandType = 1;
private bool isPreconditionForFollowingShaders;
private byte basePriority;
protected BaseShaderParameterSet baseShaderParameterSet = new BaseShaderParameterSet();
public ShaderParameterSet()
: this(4)
{
}
protected ShaderParameterSet(byte basePriority)
{
this.basePriority = basePriority;
this.IsPreconditionForFollowingShaders = false;
}
public bool IsPreconditionForFollowingShaders
{
get
{
return isPreconditionForFollowingShaders;
}
set
{
if (Commands.Count > 0 && value == isPreconditionForFollowingShaders)
return;
isPreconditionForFollowingShaders = value;
Commands.Clear();
if (isPreconditionForFollowingShaders)
Commands.Add(new Command(this, CommandFlags.EndChain | CommandFlags.FlushChain, setFollowingShaderParameterCollectionCommandType, 0, 0));
else
Commands.Add(new Command(this, CommandFlags.None, setShaderParameterCollectionCommandType, basePriority, 0));
this.MarkCommandsAsDirty();
}
}
public void SetParameter(string parameterName, IShaderParameter parameter)
{
baseShaderParameterSet.SetShaderParameter(parameterName, parameter);
}
public void SetParameter(string parameterName, ITexture argParameter, ParameterBindType argParamNameType)
{
this.SetParameter(parameterName, new Reference(argParameter), argParamNameType);
}
public void SetParameter(string parameterName, float argParameter, ParameterBindType argParamNameType)
{
this.SetParameter(parameterName, new Reference(argParameter), argParamNameType);
}
public void SetParameter(string parameterName, SlimDX.Vector3 argParameter, ParameterBindType argParamNameType)
{
this.SetParameter(parameterName, new Reference(argParameter), argParamNameType);
}
public void SetParameter(string parameterName, SlimDX.Vector4 argParameter, ParameterBindType argParamNameType)
{
this.SetParameter(parameterName, new Reference(argParameter), argParamNameType);
}
public void SetParameter(string parameterName, SlimDX.Matrix argParameter, ParameterBindType argParamNameType)
{
this.SetParameter(parameterName, new Reference(argParameter), argParamNameType);
}
public void SetParameter(string parameterName, bool argParameter, ParameterBindType argParamNameType)
{
this.SetParameter(parameterName, new Reference(argParameter), argParamNameType);
}
public void SetParameter(string parameterName, Reference argParameter, ParameterBindType argParamNameType)
{
baseShaderParameterSet.SetShaderParameter(parameterName, new ShaderParameter(argParamNameType, argParameter));
}
public void RemoveParameter(string name)
{
baseShaderParameterSet.RemoveShaderParameter(name);
}
#endregion
public override CommandExecuteResult ExecuteCommand(byte commandType, CommandBuffer currentBuffer, int currentPositon)
{
if (commandType == setShaderParameterCollectionCommandType)
{
if (Engine.EngineStates.LastShader == null)
throw new ShaderNotSetException();
baseShaderParameterSet.UseParametersOnShader(Engine.EngineStates.LastShader);
}
else if (commandType == setFollowingShaderParameterCollectionCommandType)
{
var shaders = currentBuffer.BufferedCommands.Where(c => c.Owner is IShader && c.Type == 0).Select(c => c.Owner as IShader);
foreach (var shader in shaders)
baseShaderParameterSet.UseParametersOnShader(shader);
}
return CommandExecuteResult.None;
}
#region IDisposable Members
public override void Dispose()
{
base.Dispose();
}
#endregion
public override ICreationParams CreationParams
{
get { return null; }
}
public override ObservableCollection<IResource> Children
{
get { return null; }
}
}
public class BaseShaderParameterSet
{
Dictionary<string, IShaderParameter> parameterMap = new Dictionary<string, IShaderParameter>();
Dictionary<WeakReference, List<Pair<IShaderParameter, SlimDX.Direct3D10.EffectVariable>>> shaderToParameterMap = new Dictionary<WeakReference, List<Pair<IShaderParameter, SlimDX.Direct3D10.EffectVariable>>>();
public void UseParametersOnShader(IShader shader)
{
if (parameterMap.Count == 0)
return;
List<Pair<IShaderParameter, SlimDX.Direct3D10.EffectVariable>> shaderParams = null;
var searchedShaderPair = shaderToParameterMap.FirstOrDefault(a => a.Key.IsAlive && a.Key.Target == shader);
if (searchedShaderPair.Key != null)
shaderParams = searchedShaderPair.Value;
if (shaderParams == null)
{
shaderParams = new List<Pair<IShaderParameter, SlimDX.Direct3D10.EffectVariable>>();
// (re)create shader entries
foreach (var parameter in parameterMap)
if (parameter.Value != null)
{
SlimDX.Direct3D10.EffectVariable effectvar = null;
if (parameter.Value.ParameterNameType == ParameterBindType.BindByVariable)
effectvar = shader.Effect.GetVariableByName(parameter.Key);
else if (parameter.Value.ParameterNameType == ParameterBindType.BindBySemantic)
effectvar = shader.Effect.GetVariableBySemantic(parameter.Key);
if (effectvar != null && effectvar.IsValid)
shaderParams.Add(new Pair<IShaderParameter, SlimDX.Direct3D10.EffectVariable>(parameter.Value, effectvar));
}
if (shaderParams.Count == 0)
return;
shaderToParameterMap[new WeakReference(shader)] = shaderParams;
}
foreach (var parameter in shaderParams)
parameter.First.ApplyValue(parameter.Second);
}
public void SetShaderParameter(string name, IShaderParameter parameter)
{
this.RemoveShaderParameter(name);
parameterMap[name] = parameter;
}
public void RemoveShaderParameter(string name)
{
shaderToParameterMap.Clear();
parameterMap.Remove(name);
}
public void RemoveAllShaderParameters()
{
parameterMap.Clear();
shaderToParameterMap.Clear();
}
}
public class ShaderParameter : IShaderParameter
{
private enum ObjectType
{
Int,
IntArray,
Float,
FloatArray,
Bool,
BoolArray,
Vector2,
Vector3,
Vector4,
Vector4Array,
Matrix,
MatrixArray,
Texture
}
private Reference valueObject;
private ObjectType type;
public ShaderParameter(ParameterBindType parameterNameType, Reference valueObject)
{
this.ParameterNameType = parameterNameType;
this.valueObject = valueObject;
if (valueObject.RawValue is bool)
this.type = ObjectType.Bool;
else if (valueObject.RawValue is bool[])
this.type = ObjectType.BoolArray;
else if (valueObject.RawValue is int)
this.type = ObjectType.Int;
else if (valueObject.RawValue is int[])
this.type = ObjectType.IntArray;
else if (valueObject.RawValue is float)
this.type = ObjectType.Float;
else if (valueObject.RawValue is float[])
this.type = ObjectType.FloatArray;
else if (valueObject.RawValue is SlimDX.Matrix)
this.type = ObjectType.Matrix;
else if (valueObject.RawValue is SlimDX.Matrix[])
this.type = ObjectType.MatrixArray;
else if (valueObject.RawValue is SlimDX.Vector2)
this.type = ObjectType.Vector2;
else if (valueObject.RawValue is SlimDX.Vector3)
this.type = ObjectType.Vector3;
else if (valueObject.RawValue is SlimDX.Vector4)
this.type = ObjectType.Vector4;
else if (valueObject.RawValue is SlimDX.Vector4[])
this.type = ObjectType.Vector4Array;
else if (valueObject.RawValue is ITexture)
this.type = ObjectType.Texture;
else
throw new UnsupportedShaderParameterTypeException();
}
#region IShaderParameter Members
public ParameterBindType ParameterNameType { get; protected set; }
public void ApplyValue(SlimDX.Direct3D10.EffectVariable variable)
{
switch (this.type)
{
case ObjectType.Bool:
variable.AsScalar().Set((bool)valueObject.RawValue);
break;
case ObjectType.BoolArray:
variable.AsScalar().Set((bool[])valueObject.RawValue);
break;
case ObjectType.Int:
variable.AsScalar().Set((int)valueObject.RawValue);
break;
case ObjectType.IntArray:
variable.AsScalar().Set((int[])valueObject.RawValue);
break;
case ObjectType.Float:
variable.AsScalar().Set((float)valueObject.RawValue);
break;
case ObjectType.FloatArray:
variable.AsScalar().Set((float[])valueObject.RawValue);
break;
case ObjectType.Vector2:
variable.AsVector().Set((SlimDX.Vector2)valueObject.RawValue);
break;
case ObjectType.Vector3:
variable.AsVector().Set((SlimDX.Vector3)valueObject.RawValue);
break;
case ObjectType.Vector4:
variable.AsVector().Set((SlimDX.Vector4)valueObject.RawValue);
break;
case ObjectType.Vector4Array:
variable.AsVector().Set((SlimDX.Vector4[])valueObject.RawValue);
break;
case ObjectType.Matrix:
variable.AsMatrix().SetMatrix((SlimDX.Matrix)valueObject.RawValue);
break;
case ObjectType.MatrixArray:
variable.AsMatrix().SetMatrix((SlimDX.Matrix[])valueObject.RawValue);
break;
case ObjectType.Texture:
variable.AsResource().SetResource(((ITexture)valueObject.RawValue).ResourceView);
break;
}
}
#endregion
}
}

View File

@@ -0,0 +1,234 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Aiwaz.Contracts;
using System.Runtime.InteropServices;
using Aiwaz.Core;
using System.Collections.ObjectModel;
namespace Aiwaz.Resources
{
[AiwazResource("SwapChain", "An output target for render operations, the output could be displayed directly into a window.")]
public class SwapChain : RenderTarget, ISwapChain
{
[DllImport("user32.dll")]
static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);
[Serializable, StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
public RECT(int left_, int top_, int right_, int bottom_)
{
Left = left_;
Top = top_;
Right = right_;
Bottom = bottom_;
}
public int Height { get { return Bottom - Top; } }
public int Width { get { return Right - Left; } }
}
private SlimDX.DXGI.SwapChainDescription swapChainDescription;
private SlimDX.DXGI.SwapChain swapChain;
public SwapChain(IntPtr windowHandle)
: this(windowHandle, 0, 0, 0, SlimDX.DXGI.Format.Unknown, 0, 0)
{
}
public SwapChain(IntPtr windowHandle, int width, int height, int refreshRate, SlimDX.DXGI.Format format)
: this (windowHandle, width, height, refreshRate, format, 0, 0)
{
}
public SwapChain(IntPtr windowHandle, int width, int height, int refreshRate, SlimDX.DXGI.Format format, int multiSampleCount, int multiSampleQuality)
: base()
{
VSync = true;
// get missing information
if (multiSampleCount <= 0)
multiSampleCount = 1;
if (width == 0 || height == 0)
{
RECT windowRect = new RECT();
GetClientRect(windowHandle, out windowRect);
if (width == 0)
width = windowRect.Right - windowRect.Left;
if (height == 0)
height = windowRect.Bottom - windowRect.Top;
}
if (refreshRate == 0)
refreshRate = 60; // 60Hz
if (format == SlimDX.DXGI.Format.Unknown)
format = SlimDX.DXGI.Format.R8G8B8A8_UNorm; // RGBA(X) 8Bit per channel -> 32Bit
swapChainDescription = new SlimDX.DXGI.SwapChainDescription()
{
BufferCount = 1,
Usage = SlimDX.DXGI.Usage.RenderTargetOutput,
OutputHandle = windowHandle,
IsWindowed = true,
ModeDescription = new SlimDX.DXGI.ModeDescription()
{
Width = width,
Height = height,
Format = (SlimDX.DXGI.Format)format,
RefreshRate = new SlimDX.Rational(refreshRate, 1)
},
SampleDescription = new SlimDX.DXGI.SampleDescription()
{
Count = multiSampleCount,
Quality = multiSampleQuality
}
};
this.multiSampleCount = multiSampleCount;
this.multiSampleQuality = multiSampleQuality;
Console.WriteLine(string.Format("Creating SwapChain ({0}x{1}x{2} {3})..", width, height, refreshRate, format.ToString()));
swapChain = new SlimDX.DXGI.SwapChain(Engine.Factory, Engine.Device, swapChainDescription);
if (swapChain == null)
throw new InitializingFailedException(this.GetType().Name, "Unable to create internal swap chain.");
this.RetriveData();
this.ViewPort = new ViewPort()
{
Width = width,
Height = height
};
}
public override int RenderTargetWidth
{
get { return swapChainDescription.ModeDescription.Width; }
}
public override int RenderTargetHeight
{
get { return swapChainDescription.ModeDescription.Height; }
}
public override SlimDX.DXGI.Format RenderTargetFormat
{
get { return swapChainDescription.ModeDescription.Format; }
}
#region ISwapChain Members
public void Resize(int width, int height)
{
if (width <= 0 || height <= 0)
{
RECT windowRect = new RECT();
GetClientRect(swapChainDescription.OutputHandle, out windowRect);
if (width <= 0)
width = windowRect.Right - windowRect.Left;
if (height <= 0)
height = windowRect.Bottom - windowRect.Top;
}
if (swapChainDescription.ModeDescription.Width == width &&
swapChainDescription.ModeDescription.Height == height)
return;
var depthStencilBuffer = this.HasDepthStencilBuffer;
Engine.Device.ClearState();
this.HasDepthStencilBuffer = false;
if (this.DX10RenderTargetView != null)
this.DX10RenderTargetView.Dispose();
this.DX10RenderTargetView = null;
swapChain.ResizeBuffers(swapChainDescription.BufferCount, width, height, swapChainDescription.ModeDescription.Format, SlimDX.DXGI.SwapChainFlags.AllowModeSwitch);
var desc = swapChainDescription.ModeDescription;
desc.Width = width;
desc.Height = height;
swapChainDescription.ModeDescription = desc;
this.RetriveData();
this.HasDepthStencilBuffer = depthStencilBuffer;
this.ViewPort = new ViewPort()
{
Width = width,
Height = height
};
}
public void Present()
{
swapChain.Present(VSync ? 1 : 0, SlimDX.DXGI.PresentFlags.None);
}
public bool Fullscreen
{
get { return !swapChainDescription.IsWindowed; }
set
{
if (swapChainDescription.IsWindowed == !value)
return;
swapChainDescription.IsWindowed = !value;
var hasDepthStencilBuffer = this.HasDepthStencilBuffer;
Engine.Device.ClearState();
this.HasDepthStencilBuffer = false;
if (this.DX10RenderTargetView != null)
this.DX10RenderTargetView.Dispose();
this.DX10RenderTargetView = null;
swapChain.SetFullScreenState(value, Engine.DeviceEnumerator.FindBestOutput(false).Output);
this.RetriveData();
this.HasDepthStencilBuffer = hasDepthStencilBuffer;
}
}
public bool VSync { get; set; }
private void RetriveData()
{
using (var backbufferTexture = SlimDX.Direct3D10.Texture2D.FromSwapChain<SlimDX.Direct3D10.Texture2D>(swapChain, 0))
{
DX10RenderTargetView = new SlimDX.Direct3D10.RenderTargetView(Engine.Device, backbufferTexture);
}
}
#endregion
#region IDisposable Members
public override void Dispose()
{
if (swapChain != null)
swapChain.Dispose();
swapChain = null;
base.Dispose();
}
#endregion
public override ICreationParams CreationParams
{
get { return null; }
}
public override ObservableCollection<IResource> Children
{
get { return null; }
}
}
}

View File

@@ -0,0 +1,267 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Aiwaz.Contracts;
using Aiwaz.Core;
using SlimDX.Direct3D10;
using Aiwaz.Resources.Attributes;
namespace Aiwaz.Resources
{
[CreationParameters("Create an empty texture")]
public class EmptyTextureParams : ICreationParams
{
public int Width;
public int Height;
public int Elements;
public int MipLevels;
public SlimDX.DXGI.Format Format;
public ResourceUsage AccessType;
public TextureInitialData InitialData;
public bool RenderTarget;
public int MultiSampleCount;
public int MultiSampleQuality;
public EmptyTextureParams()
{
Width = 512;
Height = 512;
Elements = 1;
MipLevels = 1;
Format = SlimDX.DXGI.Format.Unknown;
AccessType = ResourceUsage.Default;
InitialData = null;
RenderTarget = false;
MultiSampleCount = 0;
MultiSampleQuality = 0;
}
}
[CreationParameters("Load a texture from file")]
public class FileTextureParams : ICreationParams
{
[RequiredParameter]
public string FileName;
public SlimDX.Direct3D10.ResourceUsage AccessType;
public FileTextureParams()
{
AccessType = ResourceUsage.Default;
}
}
[AiwazResource("Texture", "A placeholder of multidimensional data")]
public class Texture : ShaderParameterSet, ITexture
{
#region ITexture Members
private string bindingName = "Diffuse";
private SlimDX.Direct3D10.Resource resource;
private int lockedSubResource = 0;
private bool isLocked = false;
private Texture()
: base(3)
{
}
public Texture(FileTextureParams descriptor)
: this()
{
Console.WriteLine(string.Format("Creating Texture ({0})..", descriptor.FileName));
this.LoadFromFile(descriptor.FileName, descriptor.AccessType);
this.WellKnownName = descriptor.FileName;
}
public Texture(EmptyTextureParams descriptor)
: this()
{
this.CreateTexture(descriptor.Width, descriptor.Height, descriptor.MipLevels, descriptor.Elements, descriptor.Format, descriptor.InitialData, descriptor.AccessType, descriptor.RenderTarget, descriptor.MultiSampleCount, descriptor.MultiSampleQuality);
}
public string BindingName
{
get { return bindingName; }
set
{
if (!string.IsNullOrEmpty(bindingName))
this.RemoveParameter(bindingName);
bindingName = value;;
if (!string.IsNullOrEmpty(bindingName))
this.SetParameter(bindingName, this, ParameterBindType.BindBySemantic);
}
}
public int TextureWidth { get; protected set; }
public int TextureHeight { get; protected set; }
public int TextureArraySize { get; protected set; }
public SlimDX.DXGI.Format TextureFormat { get; protected set; }
public SlimDX.Direct3D10.ShaderResourceView ResourceView { get; protected set; }
public SlimDX.Direct3D10.Texture2D Texture2D { get; protected set; }
public SlimDX.DataRectangle MapTextureBuffer(SlimDX.Direct3D10.MapMode mode)
{
return this.MapTextureBuffer(mode, 0);
}
public SlimDX.DataRectangle MapTextureBuffer(SlimDX.Direct3D10.MapMode mode, int arrayElement)
{
if (isLocked)
throw new ActionFailedException("Texture is already locked.");
isLocked = true;
lockedSubResource = arrayElement;
return this.Texture2D.Map(arrayElement, mode, SlimDX.Direct3D10.MapFlags.None);
}
public void UnmapTextureBuffer()
{
if (!isLocked)
return;
isLocked = false;
this.Texture2D.Unmap(lockedSubResource);
}
private void LoadFromFile(string fileName, SlimDX.Direct3D10.ResourceUsage accessType)
{
var loadInfo = SlimDX.Direct3D10.ImageLoadInformation.FromDefaults();
if (accessType == SlimDX.Direct3D10.ResourceUsage.Staging)
{
loadInfo.BindFlags = 0;
loadInfo.Usage = SlimDX.Direct3D10.ResourceUsage.Staging;
loadInfo.CpuAccessFlags = SlimDX.Direct3D10.CpuAccessFlags.Write | SlimDX.Direct3D10.CpuAccessFlags.Read;
}
else if (accessType == SlimDX.Direct3D10.ResourceUsage.Dynamic)
{
loadInfo.Usage = SlimDX.Direct3D10.ResourceUsage.Dynamic;
loadInfo.CpuAccessFlags = SlimDX.Direct3D10.CpuAccessFlags.Write;
}
using (var stream = Engine.FileSystem.Open(fileName))
{
this.Texture2D = SlimDX.Direct3D10.Texture2D.FromStream(Engine.Device, stream, (int)stream.Length, loadInfo);
resource = this.Texture2D;
}
if (accessType != SlimDX.Direct3D10.ResourceUsage.Staging)
{
var texViewDesc = new SlimDX.Direct3D10.ShaderResourceViewDescription();
texViewDesc.Format = this.Texture2D.Description.Format;
texViewDesc.Dimension = SlimDX.Direct3D10.ShaderResourceViewDimension.Texture2D;
texViewDesc.MostDetailedMip = 0;
texViewDesc.MipLevels = this.Texture2D.Description.MipLevels;
this.ResourceView = new SlimDX.Direct3D10.ShaderResourceView(Engine.Device, this.Texture2D, texViewDesc);
}
this.TextureWidth = this.Texture2D.Description.Width;
this.TextureHeight = this.Texture2D.Description.Height;
this.TextureFormat = this.Texture2D.Description.Format;
this.TextureArraySize = 0;
this.BindingName = this.BindingName;
}
internal void CreateRenderTargetTexture(int width, int height, SlimDX.DXGI.Format format, int multiSampleCount, int multiSampleQuality)
{
this.CreateTexture(width, height, 1, 0, format, null, SlimDX.Direct3D10.ResourceUsage.Staging, true, multiSampleCount, multiSampleQuality);
}
private void DisposeInternal()
{
if (this.ResourceView != null)
this.ResourceView.Dispose();
this.ResourceView = null;
if (this.resource != null)
this.resource.Dispose();
this.resource = null;
this.Texture2D = null;
}
private void CreateTexture(int width, int height, int mipLevels, int elements, SlimDX.DXGI.Format format, TextureInitialData initialData, SlimDX.Direct3D10.ResourceUsage accessType, bool renderTarget, int multiSampleCount, int multiSampleQuality)
{
Console.WriteLine(string.Format("Creating Texture ({0}x{1} {2})..", width, height, format.ToString()));
this.DisposeInternal();
// calculate the needed amount of mipmap levels
int mipMapLevels = 1;
for (int tmp = Math.Min(height, width); tmp > 1; tmp /= 2, ++mipMapLevels);
mipMapLevels = Math.Max(1, Math.Min(mipMapLevels, mipLevels == 0 ? mipMapLevels : mipLevels));
// create the resource
var texDesc = new SlimDX.Direct3D10.Texture2DDescription();
texDesc.Width = width;
texDesc.Height = height;
texDesc.MipLevels = mipMapLevels;
texDesc.ArraySize = Math.Max(1, elements);
texDesc.Format = format;
texDesc.SampleDescription = new SlimDX.DXGI.SampleDescription(multiSampleCount, multiSampleQuality);
if (accessType == SlimDX.Direct3D10.ResourceUsage.Dynamic)
{
texDesc.Usage = SlimDX.Direct3D10.ResourceUsage.Dynamic;
texDesc.CpuAccessFlags = SlimDX.Direct3D10.CpuAccessFlags.Write;
}
if (accessType == SlimDX.Direct3D10.ResourceUsage.Staging)
texDesc.BindFlags = ((mipMapLevels > 1 || renderTarget) ? SlimDX.Direct3D10.BindFlags.RenderTarget : SlimDX.Direct3D10.BindFlags.None) | SlimDX.Direct3D10.BindFlags.ShaderResource;
if (mipMapLevels > 1)
texDesc.OptionFlags = SlimDX.Direct3D10.ResourceOptionFlags.GenerateMipMaps;
resource = this.Texture2D = new SlimDX.Direct3D10.Texture2D(Engine.Device, texDesc);
// create the resource view when possible
if (accessType != SlimDX.Direct3D10.ResourceUsage.Staging)
{
var texViewDesc = new SlimDX.Direct3D10.ShaderResourceViewDescription();
texViewDesc.Format = texDesc.Format;
texViewDesc.ElementWidth = elements;
if (elements > 0)
texViewDesc.Dimension = multiSampleCount == 1 ? SlimDX.Direct3D10.ShaderResourceViewDimension.Texture2DArray : SlimDX.Direct3D10.ShaderResourceViewDimension.Texture2DMultisampledArray;
else
texViewDesc.Dimension = multiSampleCount == 1 ? SlimDX.Direct3D10.ShaderResourceViewDimension.Texture2D : SlimDX.Direct3D10.ShaderResourceViewDimension.Texture2DMultisampled;
texViewDesc.MostDetailedMip = 0;
texViewDesc.MipLevels = texDesc.MipLevels;
texViewDesc.ArraySize = elements;
this.ResourceView = new SlimDX.Direct3D10.ShaderResourceView(Engine.Device, resource, texViewDesc);
}
// finalize
this.TextureWidth = width;
this.TextureHeight = height;
this.TextureFormat = format;
this.TextureArraySize = 1;
this.BindingName = this.BindingName;
}
#region IDisposable Members
public override void Dispose()
{
this.DisposeInternal();
base.Dispose();
}
#endregion
#endregion
}
}

View File

@@ -0,0 +1,306 @@
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
}
}