// TODO: Find a way to replug this

        /// <summary>
        /// Adds a default frustum culling for rendering only meshes that are only inside the frustum/
        /// </summary>
        /// <param name="modelRenderer">The model renderer.</param>
        /// <returns>ModelRenderer.</returns>
        //public static ModelComponentRenderer AddDefaultFrustumCulling(this ModelComponentRenderer modelRenderer)
        //{
        //    modelRenderer.UpdateMeshes = FrustumCulling;
        //    return modelRenderer;
        //}

        private static void FrustumCulling(RenderContext context, FastList<RenderMesh> meshes)
        {
            Matrix viewProjection, mat1, mat2;

            // Compute view * projection
            context.Parameters.Get(TransformationKeys.View, out mat1);
            context.Parameters.Get(TransformationKeys.Projection, out mat2);
            Matrix.Multiply(ref mat1, ref mat2, out viewProjection);

            var frustum = new BoundingFrustum(ref viewProjection);

            for (var i = 0; i < meshes.Count; ++i)
            {
                var renderMesh = meshes[i];

                // Fast AABB transform: http://zeuxcg.org/2010/10/17/aabb-from-obb-with-component-wise-abs/
                // Get world matrix
                renderMesh.Mesh.Parameters.Get(TransformationKeys.World, out mat1);

                // Compute transformed AABB (by world)
                var boundingBoxExt = new BoundingBoxExt(renderMesh.Mesh.BoundingBox);
                boundingBoxExt.Transform(mat1);

                // Perform frustum culling
                if (!frustum.Contains(ref boundingBoxExt))
                {
                    meshes.SwapRemoveAt(i--);
                }
            }
        }
        // TODO: Find a way to replug this

        /// <summary>
        /// Adds a default frustum culling for rendering only meshes that are only inside the frustum/
        /// </summary>
        /// <param name="modelRenderer">The model renderer.</param>
        /// <returns>ModelRenderer.</returns>
        //public static ModelComponentRenderer AddDefaultFrustumCulling(this ModelComponentRenderer modelRenderer)
        //{
        //    modelRenderer.UpdateMeshes = FrustumCulling;
        //    return modelRenderer;
        //}

        private static void FrustumCulling(RenderContext context, FastList <RenderMesh> meshes)
        {
            Matrix viewProjection, mat1, mat2;

            // Compute view * projection
            context.Parameters.Get(TransformationKeys.View, out mat1);
            context.Parameters.Get(TransformationKeys.Projection, out mat2);
            Matrix.Multiply(ref mat1, ref mat2, out viewProjection);

            var frustum = new BoundingFrustum(ref viewProjection);

            for (var i = 0; i < meshes.Count; ++i)
            {
                var renderMesh = meshes[i];

                // Fast AABB transform: http://zeuxcg.org/2010/10/17/aabb-from-obb-with-component-wise-abs/
                // Get world matrix
                renderMesh.Mesh.Parameters.Get(TransformationKeys.World, out mat1);

                // Compute transformed AABB (by world)
                var boundingBoxExt = new BoundingBoxExt(renderMesh.Mesh.BoundingBox);
                boundingBoxExt.Transform(mat1);

                // Perform frustum culling
                if (!frustum.Contains(ref boundingBoxExt))
                {
                    meshes.SwapRemoveAt(i--);
                }
            }
        }
Example #3
0
        internal void Update(TransformComponent transformComponent, ref Matrix worldMatrix)
        {
            if (!Enabled || ModelViewHierarchy == null || model == null)
            {
                return;
            }

            // Check if scaling is negative
            bool isScalingNegative = false;

            {
                Vector3 scale, translation;
                Matrix  rotation;
                if (worldMatrix.Decompose(out scale, out rotation, out translation))
                {
                    isScalingNegative = scale.X * scale.Y * scale.Z < 0.0f;
                }
            }

            // Update model view hierarchy node matrices
            modelViewHierarchy.NodeTransformations[0].LocalMatrix       = worldMatrix;
            modelViewHierarchy.NodeTransformations[0].IsScalingNegative = isScalingNegative;
            modelViewHierarchy.UpdateMatrices();

            // Update the bounding sphere / bounding box in world space
            var    meshes = Model.Meshes;
            var    modelBoundingSphere = BoundingSphere.Empty;
            var    modelBoundingBox    = BoundingBox.Empty;
            bool   hasBoundingBox      = false;
            Matrix world;

            foreach (var mesh in meshes)
            {
                var meshBoundingSphere = mesh.BoundingSphere;

                modelViewHierarchy.GetWorldMatrix(mesh.NodeIndex, out world);
                Vector3.TransformCoordinate(ref meshBoundingSphere.Center, ref world, out meshBoundingSphere.Center);
                BoundingSphere.Merge(ref modelBoundingSphere, ref meshBoundingSphere, out modelBoundingSphere);

                var boxExt = new BoundingBoxExt(mesh.BoundingBox);
                boxExt.Transform(world);
                var meshBox = (BoundingBox)boxExt;

                if (hasBoundingBox)
                {
                    BoundingBox.Merge(ref modelBoundingBox, ref meshBox, out modelBoundingBox);
                }
                else
                {
                    modelBoundingBox = meshBox;
                }

                hasBoundingBox = true;
            }

            // Update the bounds
            BoundingBox    = modelBoundingBox;
            BoundingSphere = modelBoundingSphere;
        }
Example #4
0
        internal void Update(ref Matrix worldMatrix, bool isScalingNegative)
        {
            // Update model view hierarchy node matrices
            modelViewHierarchy.NodeTransformations[0].LocalMatrix       = worldMatrix;
            modelViewHierarchy.NodeTransformations[0].IsScalingNegative = isScalingNegative;
            modelViewHierarchy.UpdateMatrices();

            // Update the bounding sphere / bounding box in world space
            var    meshes = Model.Meshes;
            var    modelBoundingSphere = BoundingSphere.Empty;
            var    modelBoundingBox    = BoundingBox.Empty;
            bool   hasBoundingBox      = false;
            Matrix world;

            foreach (var mesh in meshes)
            {
                var meshBoundingSphere = mesh.BoundingSphere;

                modelViewHierarchy.GetWorldMatrix(mesh.NodeIndex, out world);
                Vector3.TransformCoordinate(ref meshBoundingSphere.Center, ref world, out meshBoundingSphere.Center);
                BoundingSphere.Merge(ref modelBoundingSphere, ref meshBoundingSphere, out modelBoundingSphere);

                var boxExt = new BoundingBoxExt(mesh.BoundingBox);
                boxExt.Transform(world);
                var meshBox = (BoundingBox)boxExt;

                if (hasBoundingBox)
                {
                    BoundingBox.Merge(ref modelBoundingBox, ref meshBox, out modelBoundingBox);
                }
                else
                {
                    modelBoundingBox = meshBox;
                }

                hasBoundingBox = true;
            }

            // Update the bounds
            BoundingBox    = modelBoundingBox;
            BoundingSphere = modelBoundingSphere;
        }
Example #5
0
        internal void Update(TransformComponent transformComponent, ref Matrix worldMatrix)
        {
            if (!Enabled || model == null)
                return;

            // Check if scaling is negative
            bool isScalingNegative = false;
            {
                Vector3 scale, translation;
                Matrix rotation;
                if (worldMatrix.Decompose(out scale, out rotation, out translation))
                    isScalingNegative = scale.X*scale.Y*scale.Z < 0.0f;
            }

            // Make sure skeleton is up to date
            CheckSkeleton();

            if (skeleton != null)
            {
                // Update model view hierarchy node matrices
                skeleton.NodeTransformations[0].LocalMatrix = worldMatrix;
                skeleton.NodeTransformations[0].IsScalingNegative = isScalingNegative;
                skeleton.UpdateMatrices();
            }

            // Update the bounding sphere / bounding box in world space
            var meshes = Model.Meshes;
            var modelBoundingSphere = BoundingSphere.Empty;
            var modelBoundingBox = BoundingBox.Empty;
            bool hasBoundingBox = false;
            Matrix world;
            foreach (var mesh in meshes)
            {
                var meshBoundingSphere = mesh.BoundingSphere;

                if (skeleton != null)
                    skeleton.GetWorldMatrix(mesh.NodeIndex, out world);
                else
                    world = worldMatrix;
                Vector3.TransformCoordinate(ref meshBoundingSphere.Center, ref world, out meshBoundingSphere.Center);
                BoundingSphere.Merge(ref modelBoundingSphere, ref meshBoundingSphere, out modelBoundingSphere);

                var boxExt = new BoundingBoxExt(mesh.BoundingBox);
                boxExt.Transform(world);
                var meshBox = (BoundingBox)boxExt;

                if (hasBoundingBox)
                {
                    BoundingBox.Merge(ref modelBoundingBox, ref meshBox, out modelBoundingBox);
                }
                else
                {
                    modelBoundingBox = meshBox;
                }

                hasBoundingBox = true;
            }

            // Update the bounds
            BoundingBox = modelBoundingBox;
            BoundingSphere = modelBoundingSphere;
        }
        private void PrepareModels(RenderContext context, List <RenderModel> renderModels, RenderItemCollection opaqueList, RenderItemCollection transparentList)
        {
            // If no camera, early exit
            var camera = context.GetCurrentCamera();

            if (camera == null)
            {
                return;
            }

            var viewProjectionMatrix = camera.ViewProjectionMatrix;
            var preRenderModel       = Callbacks.PreRenderModel;

            var sceneCameraRenderer = context.Tags.Get(SceneCameraRenderer.Current);
            var cullingMode         = sceneCameraRenderer != null ? sceneCameraRenderer.CullingMode : CullingMode.None;
            var frustum             = new BoundingFrustum(ref viewProjectionMatrix);

            var cameraRenderMode = sceneCameraRenderer != null ? sceneCameraRenderer.Mode : null;

            foreach (var renderModel in renderModels)
            {
                // If Model is null, then skip it
                if (renderModel.Model == null)
                {
                    continue;
                }

                if (preRenderModel != null)
                {
                    if (!preRenderModel(context, renderModel))
                    {
                        continue;
                    }
                }

                // Always prepare the slot for the render meshes even if they are not used.
                EnsureRenderMeshes(renderModel);

                var meshes = PrepareModelForRendering(context, renderModel);

                foreach (var renderMesh in meshes)
                {
                    if (!renderMesh.Enabled)
                    {
                        continue;
                    }

                    var worldMatrix = renderMesh.WorldMatrix;

                    // Perform frustum culling
                    if (cullingMode == CullingMode.Frustum)
                    {
                        // Always render meshes with unspecified bounds
                        // TODO: This should not be necessary. Add proper bounding boxes to gizmos etc.
                        var boundingBox = renderMesh.Mesh.BoundingBox;
                        if (boundingBox.Extent != Vector3.Zero)
                        {
                            // Fast AABB transform: http://zeuxcg.org/2010/10/17/aabb-from-obb-with-component-wise-abs/
                            // Compute transformed AABB (by world)
                            var boundingBoxExt = new BoundingBoxExt(boundingBox);
                            boundingBoxExt.Transform(worldMatrix);

                            if (!frustum.Contains(ref boundingBoxExt))
                            {
                                continue;
                            }
                        }
                    }

                    // Project the position
                    // TODO: This could be done in a SIMD batch, but we need to figure-out how to plugin in with RenderMesh object
                    var     worldPosition = new Vector4(worldMatrix.TranslationVector, 1.0f);
                    Vector4 projectedPosition;
                    Vector4.Transform(ref worldPosition, ref viewProjectionMatrix, out projectedPosition);
                    var projectedZ = projectedPosition.Z / projectedPosition.W;

                    // TODO: Should this be set somewhere else?
                    var rasterizerState = cameraRenderMode != null?cameraRenderMode.GetDefaultRasterizerState(renderMesh.RenderModel.IsGeometryInverted) : null;

                    renderMesh.RasterizerState = RasterizerState ?? rasterizerState;

                    renderMesh.UpdateMaterial();
                    var list = renderMesh.HasTransparency ? transparentList : opaqueList;
                    list.Add(new RenderItem(this, renderMesh, projectedZ));
                }
            }
        }
Example #7
0
        internal void Update(ref Matrix worldMatrix)
        {
            // Update model view hierarchy node matrices
            modelViewHierarchy.NodeTransformations[0].LocalMatrix = worldMatrix;
            modelViewHierarchy.UpdateMatrices();

            // Update the bounding sphere / bounding box in world space
            var meshes = Model.Meshes;
            var modelBoundingSphere = BoundingSphere.Empty;
            var modelBoundingBox = BoundingBox.Empty;
            bool hasBoundingBox = false;
            Matrix world;
            foreach (var mesh in meshes)
            {
                var meshBoundingSphere = mesh.BoundingSphere;

                modelViewHierarchy.GetWorldMatrix(mesh.NodeIndex, out world);
                Vector3.TransformCoordinate(ref meshBoundingSphere.Center, ref world, out meshBoundingSphere.Center);
                BoundingSphere.Merge(ref modelBoundingSphere, ref meshBoundingSphere, out modelBoundingSphere);

                var boxExt = new BoundingBoxExt(mesh.BoundingBox);
                boxExt.Transform(world);
                var meshBox = (BoundingBox)boxExt;

                if (hasBoundingBox)
                {
                    BoundingBox.Merge(ref modelBoundingBox, ref meshBox, out modelBoundingBox);
                }
                else
                {
                    modelBoundingBox = meshBox;
                }

                hasBoundingBox = true;
            }

            // Update the bounds
            BoundingBox = modelBoundingBox;
            BoundingSphere = modelBoundingSphere;
        }