Example #1
0
 /// <summary>
 /// An overload for expanding a list of SerializableSceneNodes.
 /// </summary>
 public static List <T> ExpandNodeInstanceSubtrees <T>(
     this IReadOnlyList <SerializableSceneNode> nodes,
     ExpansionMode expansionMode,
     CreateNewNodeFunc <SerializableSceneNode, T> createNewNodeFunc)
 => ExpandNodeInstanceSubtrees(
     nodes.Select(n => new SerializableSceneNodeInstanceAdapter(n)).ToList(),
     expansionMode,
     createNewNodeFunc);
Example #2
0
        /// <summary>
        /// Collects nodes and expands node instance subtrees. The geometry is assumed to be defined in local space.
        /// </summary>
        private static void CollectNodesFromLocalSpaceGeometry <N, T>(
            IReadOnlyList <Tree <INodeInstance <N> > > flattenedTreeNodes,
            IEnumerable <Tree <INodeInstance <N> > > treeNodesToProcess,
            Matrix4x4 parentBasis,
            CreateNewNodeFunc <N, T> createNewNodeFunc,
            List <T> result)
        {
            // For each instance, check if the source node has children. If so, expand those children locally.
            foreach (var treeNode in treeNodesToProcess)
            {
                var node = treeNode.Value;
                if (node.IsInstance())
                {
                    var sourceTreeNode = flattenedTreeNodes[node.Instance];
                    var sourceNode     = sourceTreeNode.Value;
                    var instanceBasis  = node.Transform * parentBasis;

                    // Add the source node world space info.
                    result.Add(createNewNodeFunc(node.Value, result.Count, instanceBasis, sourceNode.Geometry));

                    // Expand the source node's children (if any) into the local basis.
                    if (sourceTreeNode.Children.Count > 0)
                    {
                        var descendents = sourceTreeNode.AllNodes().Where(tn => tn != sourceTreeNode);

                        // Invert the source node's basis to transform that node hierarchy to the origin, then transform it to the instance basis.
                        if (Matrix4x4.Invert(sourceNode.Transform, out var sourceNodeInverse))
                        {
                            var instanceChildrenBasis = sourceNodeInverse * instanceBasis;
                            CollectNodesFromLocalSpaceGeometry(flattenedTreeNodes, descendents, instanceChildrenBasis, createNewNodeFunc, result);
                        }
                        else
                        {
                            Debug.WriteLine("Failed to invert node");
                        }
                    }
                }
                else
                {
                    result.Add(createNewNodeFunc(node.Value, result.Count, node.Transform * parentBasis, node.Geometry));
                }
            }
        }
Example #3
0
        /// <summary>
        /// [LEGACY - object model 2.0] Collects nodes and expands node instance subtrees. The geometry is assumed to be defined in world space.
        /// </summary>
        private static void CollectNodesFromWorldSpaceGeometry <N, T>(
            IReadOnlyList <Tree <INodeInstance <N> > > flattenedTreeNodes,
            IEnumerable <Tree <INodeInstance <N> > > treeNodesToProcess,
            Matrix4x4 parentBasis,
            CreateNewNodeFunc <N, T> createNewNodeFunc,
            List <T> result)
        {
            // For each instance, check if the source node has children. If so, expand those children locally.
            foreach (var treeNode in treeNodesToProcess)
            {
                var node = treeNode.Value;
                if (node.IsInstance())
                {
                    var sourceTreeNode = flattenedTreeNodes[node.Instance];
                    var sourceNode     = sourceTreeNode.Value;

                    // Can't proceed unless the source node transform can be inverted.
                    if (!Matrix4x4.Invert(sourceNode.Transform, out var sourceNodeInverse))
                    {
                        continue;
                    }

                    var localBasis = sourceNodeInverse * node.Transform * parentBasis;

                    // Add the source node world space info.
                    result.Add(createNewNodeFunc(node.Value, result.Count, localBasis, sourceNode.Geometry));

                    // Expand the source node's children, if any.
                    if (sourceTreeNode.Children.Count > 0)
                    {
                        var descendents = sourceTreeNode.AllNodes().Where(tn => tn != sourceTreeNode);
                        CollectNodesFromWorldSpaceGeometry(flattenedTreeNodes, descendents, localBasis, createNewNodeFunc, result);
                    }
                }
                else
                {
                    // Non-instances are presumed to have their geometry baked in world space.
                    result.Add(createNewNodeFunc(node.Value, result.Count, parentBasis, node.Geometry));
                }
            }
        }
Example #4
0
        /// <summary>
        /// Converts the list of nodes (containing instanced subtrees) into a flattened list of new objects.
        /// </summary>
        public static List <T> ExpandNodeInstanceSubtrees <N, T>(
            this IReadOnlyList <INodeInstance <N> > nodes,
            ExpansionMode expansionMode,
            CreateNewNodeFunc <N, T> createNewNodeFunc)
        {
            // Start with a flat collection of tree nodes.
            var treeNodes = nodes.Select(n => new Tree <INodeInstance <N> > {
                Value = n
            }).ToArray();

            // Establish the parent/child hierarchy.
            foreach (var treeNode in treeNodes)
            {
                var parentIndex = treeNode.Value.Parent;
                if (parentIndex < 0 || parentIndex >= treeNodes.Length)
                {
                    continue;
                }

                treeNodes[parentIndex].AddChild(treeNode);
            }

            var result = new List <T>();

            switch (expansionMode)
            {
            case ExpansionMode.WorldSpaceGeometry:
                // DEPRECATED: This is a legacy stopgap to allow support for objectmodel version 2.
                // objectmodel version 3 and onward expects local space geometry.
                CollectNodesFromWorldSpaceGeometry(treeNodes, treeNodes, Matrix4x4.Identity, createNewNodeFunc, result);
                break;

            case ExpansionMode.LocalGeometry:
                CollectNodesFromLocalSpaceGeometry(treeNodes, treeNodes, Matrix4x4.Identity, createNewNodeFunc, result);
                break;
            }

            return(result);
        }