private Shape BuildBoundingShape(DRMeshNodeContent meshNode)
        {
            Shape boundingShape = Shape.Empty;

            var mesh = meshNode.InputMesh;

            if (mesh.Positions.Count > 0)
            {
                if (_modelDescription != null && _modelDescription.AabbEnabled)
                {
                    // We assume that the AABB is given in the local space.
                    Vector3F aabbMinimum = (Vector3F)_modelDescription.AabbMinimum;
                    Vector3F aabbMaximum = (Vector3F)_modelDescription.AabbMaximum;
                    Vector3F center      = (aabbMaximum + aabbMinimum) / 2;
                    Vector3F extent      = aabbMaximum - aabbMinimum;
                    if (center.IsNumericallyZero)
                    {
                        boundingShape = new BoxShape(extent);
                    }
                    else
                    {
                        boundingShape = new TransformedShape(new GeometricObject(new BoxShape(extent), new Pose(center)));
                    }
                }
                else
                {
                    // Best fit bounding shape.
                    //boundingShape = ComputeBestFitBoundingShape(mesh);

                    // Non-rotated bounding shape. This is usually larger but contains no rotations.
                    // (TransformedShapes with rotated children cannot be used with non-uniform scaling.)
                    boundingShape = ComputeAxisAlignedBoundingShape(mesh);
                }
            }

            return(boundingShape);
        }
        private static DRSceneNodeContent BuildSceneGraph(NodeContent node, DRSceneNodeContent parent)
        {
            CheckForCyclicReferences(node);

            DRSceneNodeContent sceneNode;

            if (node is BoneContent)
            {
                // ----- BoneContent
                // Bones do not show up in the scene graph.
                sceneNode = null;
            }
            else if (node is MeshContent)
            {
                // ----- MeshContent
                var    mesh = (MeshContent)node;
                string morphTargetName;
                if (ContentHelper.IsMorphTarget(mesh, out morphTargetName))
                {
                    // ----- Morph Targets
                    // Morph targets are stored in the parent mesh, they do not show up in
                    // the scene graph. Children of morph targets are ignored!
                    mesh.Name = morphTargetName;
                    AddMorphTarget(parent, mesh);
                    sceneNode = null;
                }
                else if (ContentHelper.IsOccluder(mesh))
                {
                    // ----- OccluderNode
                    sceneNode = new DROccluderNodeContent {
                        InputMesh = mesh
                    };
                }
                else
                {
                    // ----- MeshNode
                    sceneNode = new DRMeshNodeContent {
                        InputMesh = mesh
                    };
                }
            }
            else
            {
                // ----- Empty/unsupported node
                sceneNode = new DRSceneNodeContent();
            }

            if (sceneNode != null)
            {
                sceneNode.Name = node.Name;
                Pose     pose;
                Vector3F scale;
                DecomposeTransform(node, out pose, out scale);
                sceneNode.PoseLocal  = pose;
                sceneNode.ScaleLocal = scale;
                if (node.Children.Count > 0)
                {
                    // Process children.
                    sceneNode.Children = new List <DRSceneNodeContent>();

                    // Recursively add children.
                    foreach (var childNode in node.Children)
                    {
                        var childSceneNode = BuildSceneGraph(childNode, sceneNode);
                        if (childSceneNode != null)
                        {
                            childSceneNode.Parent = sceneNode;
                            sceneNode.Children.Add(childSceneNode);
                        }
                    }
                }
            }

            return(sceneNode);
        }
        private void BuildMesh(DRMeshNodeContent meshNode)
        {
            var mesh            = meshNode.InputMesh;
            var meshDescription = (_modelDescription != null) ? _modelDescription.GetMeshDescription(mesh.Name) : null;

            // Before modifying the base mesh: Prepare morph targets.
            bool hasMorphTargets = (meshNode.InputMorphTargets != null && meshNode.InputMorphTargets.Count > 0);

            if (hasMorphTargets)
            {
                // Convert absolute morph targets to relative morph targets ("delta blend shapes").
                MakeRelativeMorphTargets(mesh, meshNode.InputMorphTargets);

                // Add "VertexReorder" channel to base mesh.
                AddVertexReorderChannel(mesh);
            }

            if (meshDescription != null)
            {
                meshNode.MaxDistance = meshDescription.MaxDistance;
                meshNode.LodDistance = meshDescription.LodDistance;
            }
            else if (_modelDescription != null)
            {
                meshNode.MaxDistance = _modelDescription.MaxDistance;
                meshNode.LodDistance = 0;
            }

            // Ensure that model has tangents and binormals if required.
            AddTangentFrames(mesh, _modelDescription, meshDescription);

            // Process vertex colors, bone weights and bone indices.
            ProcessVertexChannels(mesh);

            if (_modelDescription != null && _modelDescription.SwapWindingOrder)
            {
                MeshHelper.SwapWindingOrder(mesh);
            }

            OptimizeForCache(mesh);

            if (hasMorphTargets)
            {
                // Get the vertex reorder maps for matching the morph targets with the
                // base mesh. (Removes the "VertexReorder" channel from the geometry.)
                _vertexReorderMaps = GetVertexReorderMaps(mesh);
            }

            var submeshInfos = BuildSubmeshInfos(mesh, meshNode.InputMorphTargets);

            // Sort submeshes by vertex declaration, material, and original index.
            Array.Sort(submeshInfos, SubmeshInfoComparer.Instance);

            // Build submeshes (including materials).
            var submeshes = BuildSubmeshes(mesh, submeshInfos);

            // Calculate a bounding shape for the whole mesh.
            var boundingShape = BuildBoundingShape(meshNode);

            meshNode.Mesh = new DRMeshContent
            {
                Name          = mesh.Name,
                BoundingShape = boundingShape,
                Submeshes     = submeshes,
#if ANIMATION
                Skeleton   = _skeleton,
                Animations = _animations,
#endif
            };
        }
        private static DRSceneNodeContent BuildSceneGraph(NodeContent node, DRSceneNodeContent parent)
        {
            CheckForCyclicReferences(node);

              DRSceneNodeContent sceneNode;
              if (node is BoneContent)
              {
            // ----- BoneContent
            // Bones do not show up in the scene graph.
            sceneNode = null;
              }
              else if (node is MeshContent)
              {
            // ----- MeshContent
            var mesh = (MeshContent)node;
            string morphTargetName;
            if (ContentHelper.IsMorphTarget(mesh, out morphTargetName))
            {
              // ----- Morph Targets
              // Morph targets are stored in the parent mesh, they do not show up in
              // the scene graph. Children of morph targets are ignored!
              mesh.Name = morphTargetName;
              AddMorphTarget(parent, mesh);
              sceneNode = null;
            }
            else if (ContentHelper.IsOccluder(mesh))
            {
              // ----- OccluderNode
              sceneNode = new DROccluderNodeContent { InputMesh = mesh };
            }
            else
            {
              // ----- MeshNode
              sceneNode = new DRMeshNodeContent { InputMesh = mesh };
            }
              }
              else
              {
            // ----- Empty/unsupported node
            sceneNode = new DRSceneNodeContent();
              }

              if (sceneNode != null)
              {
            sceneNode.Name = node.Name;
            Pose pose;
            Vector3F scale;
            DecomposeTransform(node, out pose, out scale);
            sceneNode.PoseLocal = pose;
            sceneNode.ScaleLocal = scale;
            if (node.Children.Count > 0)
            {
              // Process children.
              sceneNode.Children = new List<DRSceneNodeContent>();

              // Recursively add children.
              foreach (var childNode in node.Children)
              {
            var childSceneNode = BuildSceneGraph(childNode, sceneNode);
            if (childSceneNode != null)
            {
              childSceneNode.Parent = sceneNode;
              sceneNode.Children.Add(childSceneNode);
            }
              }
            }
              }

              return sceneNode;
        }