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; }