4 using System.Collections.Generic;
6 using SiliconStudio.Core.Mathematics;
7 using SiliconStudio.Paradox.Assets.Materials.Nodes;
8 using SiliconStudio.Paradox.Graphics;
10 namespace SiliconStudio.
Paradox.Assets.Materials.Processor.Visitors
14 #region Private members
19 private readonly Dictionary<string, ReductionStatus> treeReductionStatus;
23 #region Publice members
32 #region Public methods
36 treeReductionStatus = Material.Nodes.ToDictionary(x => x.Key, x => ReductionStatus.None);
37 ReducedTrees =
new Dictionary<string, IMaterialNode>();
45 foreach (var tree
in Material.Nodes)
47 BeginReduction(tree.Key);
57 var resultList =
new List<IMaterialNode>();
58 var criterion =
new ReductionCriteria { TexcoordIndex = TextureCoordinate.TexcoordNone };
59 if (BuildReducibleSubTreesList(node, resultList, out criterion))
60 AddNodeToReduceList(node, resultList);
71 private bool BuildReducibleSubTreesList(
IMaterialNode node, List<IMaterialNode> resultList, out ReductionCriteria criterion)
79 var isSingleReducible = node.IsReducible;
81 isSingleReducible &= (((MaterialFloatNode)node).Key == null);
83 isSingleReducible &= (((MaterialFloat4Node)node).Key == null);
85 isSingleReducible &= (((MaterialColorNode)node).Key == null);
87 return isSingleReducible;
93 return BuildReducibleSubTreesList(Material.FindNode(refNode.Name), resultList, out criterion);
96 criterion.TexcoordIndex = TextureCoordinate.TexcoordNone;
100 bool? checkIsReducible = null;
101 ReductionCriteria? checkCriterion = null;
102 var reducibleNodes =
new List<IMaterialNode>();
104 foreach (var subNodeIt
in node.GetChildren(Material))
106 var subNode = subNodeIt.Node;
107 ReductionCriteria childCriterion;
108 var childIsReducible = BuildReducibleSubTreesList(subNode, resultList, out childCriterion);
109 if (!checkIsReducible.HasValue)
111 checkIsReducible = childIsReducible;
112 checkCriterion = childCriterion;
116 checkIsReducible = checkIsReducible.Value && childIsReducible && CompatibleCriteria(childCriterion, checkCriterion.Value);
117 checkCriterion = MergeCriteria(checkCriterion.Value, childCriterion);
120 if (childIsReducible)
121 reducibleNodes.Add(subNode);
124 if (checkCriterion.HasValue)
126 criterion = checkCriterion.Value;
129 if (checkIsReducible.HasValue && !checkIsReducible.Value)
132 foreach (var reducibleNode
in reducibleNodes)
133 AddNodeToReduceList(reducibleNode, resultList);
138 return node.IsReducible;
143 #region Private methods
149 private void BeginReduction(
string referenceName)
151 if (referenceName == null)
154 if (!treeReductionStatus.ContainsKey(referenceName))
157 var status = treeReductionStatus[referenceName];
159 if (status == ReductionStatus.None)
161 var node = Material.Nodes[referenceName];
162 treeReductionStatus[referenceName] = ReductionStatus.InProgress;
163 var computedNode =
Reduce(node);
164 if (computedNode != null)
165 ReducedTrees[referenceName] = computedNode;
166 treeReductionStatus[referenceName] = ReductionStatus.Completed;
168 else if (status == ReductionStatus.InProgress)
170 treeReductionStatus[referenceName] = ReductionStatus.Completed;
180 private IMaterialNode
Reduce(IMaterialNode node)
183 return Reduce(node as MaterialBinaryNode);
184 if (node is MaterialReferenceNode)
186 var referenceName = (node as MaterialReferenceNode).Name;
187 if (referenceName != null)
189 BeginReduction(referenceName);
191 if (ReducedTrees.ContainsKey(referenceName))
192 return ReducedTrees[referenceName];
205 private IMaterialNode
Reduce(MaterialBinaryNode binaryNode)
210 bool canReduce =
true;
218 if (left is MaterialFloatNode)
220 if (right is MaterialFloatNode)
222 (left as MaterialFloatNode).Value = MaterialReductionUtils.MixFloat((left as MaterialFloatNode).Value, (right as MaterialFloatNode).Value, binaryNode.
Operand);
225 if (right is MaterialFloat4Node)
227 var value = (left as MaterialFloatNode).Value;
228 (right as MaterialFloat4Node).Value = MaterialReductionUtils.MixFloat4(
new Vector4(value, value, value, value), (right as MaterialFloat4Node).Value, binaryNode.
Operand);
233 var value = (left as MaterialFloatNode).Value;
234 (right as MaterialColorNode).Value = MaterialReductionUtils.MixColor(
new Color4(value, value, value, value), (right as MaterialColorNode).Value, binaryNode.
Operand);
238 else if (left is MaterialFloat4Node)
240 if (right is MaterialFloatNode)
242 var value = (right as MaterialFloatNode).Value;
243 (left as MaterialFloat4Node).Value = MaterialReductionUtils.MixFloat4((left as MaterialFloat4Node).Value,
new Vector4(value, value, value, value), binaryNode.
Operand);
246 if (right is MaterialFloat4Node)
248 (left as MaterialFloat4Node).Value = MaterialReductionUtils.MixFloat4((left as MaterialFloat4Node).Value, (right as MaterialFloat4Node).Value, binaryNode.
Operand);
251 if (right is MaterialColorNode)
253 var value = (left as MaterialFloat4Node).Value;
254 (left as MaterialFloat4Node).Value = MaterialReductionUtils.MixFloat4(value, (right as MaterialColorNode).Value.ToVector4(), binaryNode.Operand);
258 else if (left is MaterialColorNode)
260 if (right is MaterialFloatNode)
262 var value = (right as MaterialFloatNode).Value;
263 (left as MaterialColorNode).Value = MaterialReductionUtils.MixColor((left as MaterialColorNode).Value,
new Color4(value, value, value, value), binaryNode.
Operand);
266 if (right is MaterialFloat4Node)
268 (right as MaterialFloat4Node).Value = MaterialReductionUtils.MixFloat4((left as MaterialColorNode).Value.ToVector4(), (right as MaterialFloat4Node).Value, binaryNode.
Operand);
271 if (right is MaterialColorNode)
273 var value = (left as MaterialColorNode).Value;
274 (left as MaterialColorNode).Value = MaterialReductionUtils.MixColor((left as MaterialColorNode).Value, (right as MaterialColorNode).Value, binaryNode.
Operand);
280 binaryNode.LeftChild = left;
281 binaryNode.RightChild = right;
287 #region Private static methods
294 private static void AddNodeToReduceList(IMaterialNode node, List<IMaterialNode> reduceList)
297 reduceList.Add(node);
306 private static bool CompatibleCriteria(ReductionCriteria baseCriteria, ReductionCriteria newCriteria)
308 var result = baseCriteria.TexcoordIndex == TextureCoordinate.TexcoordNone || newCriteria.TexcoordIndex == TextureCoordinate.TexcoordNone || baseCriteria.TexcoordIndex == newCriteria.TexcoordIndex;
309 result = result && (!baseCriteria.AddressModeU.HasValue || !newCriteria.AddressModeU.HasValue || baseCriteria.AddressModeU.Value == newCriteria.AddressModeU.Value);
310 result = result && (!baseCriteria.AddressModeV.HasValue || !newCriteria.AddressModeV.HasValue || baseCriteria.AddressModeV.Value == newCriteria.AddressModeV.Value);
320 private static ReductionCriteria MergeCriteria(ReductionCriteria baseCriteria, ReductionCriteria newCriteria)
322 var result =
new ReductionCriteria
324 TexcoordIndex = baseCriteria.TexcoordIndex == TextureCoordinate.TexcoordNone ? newCriteria.TexcoordIndex : baseCriteria.TexcoordIndex,
325 AddressModeU = baseCriteria.AddressModeU.HasValue ? baseCriteria.AddressModeU : (newCriteria.AddressModeU.HasValue ? newCriteria.AddressModeU.Value : (
TextureAddressMode?)null),
326 AddressModeV = baseCriteria.AddressModeV.HasValue ? baseCriteria.AddressModeV : (newCriteria.AddressModeV.HasValue ? newCriteria.AddressModeV.Value : (
TextureAddressMode?)null)
333 private enum ReductionStatus
340 private struct ReductionCriteria
A node that describe a binary operation between two IMaterialNode
IMaterialNode LeftChild
The left (background) child node.
Description of a material.
TextureAddressMode
Identify a technique for resolving texture coordinates that are outside of the boundaries of a textur...
TextureCoordinate
The texture coordinate.
Represents a color in the form of rgba.
void ReduceTrees()
Reduce all the trees.
Represents a four dimensional mathematical vector.
List< IMaterialNode > GetReducibleSubTrees(IMaterialNode node)
Get the list of all the reducible sub-trees for this tree. If a tree is entirely reducible, only the rootnode will appear
readonly Dictionary< string, IMaterialNode > ReducedTrees
Reduced form of each tree.
MaterialTreeReducer(MaterialDescription mat)
Base interface for all nodes in the material tree
IMaterialNode RightChild
The right (foreground) child node.
MaterialBinaryOperand Operand
The operation to blend the nodes.