// 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--);
                }
            }
        }
        private void PrepareRenderMeshes(RenderModel renderModel, List<Mesh> meshes, ref FastListStruct<RenderMesh> renderMeshes, RenderItemCollection opaqueList, RenderItemCollection transparentList)
        {
            // Add new render meshes
            for (int i = renderMeshes.Count; i < meshes.Count; i++)
            {
                var renderMesh = new RenderMesh(renderModel, meshes[i]);
                renderMeshes.Add(renderMesh);
            }

            // Create the bounding frustum locally on the stack, so that frustum.Contains is performed with boundingBox that is also on the stack
            var frustum = new BoundingFrustum(ref ViewProjectionMatrix);

            for (int i = 0; i < renderMeshes.Count; i++)
            {
                var renderMesh = renderMeshes[i];
                // Update the model hierarchy
                var modelViewHierarchy = renderModel.ModelComponent.ModelViewHierarchy;
                modelViewHierarchy.UpdateRenderMesh(renderMesh);

                if (!renderMesh.Enabled)
                {
                    continue;
                }

                // Upload skinning blend matrices
                BoundingBoxExt boundingBox;
                skinningUpdater.Update(modelViewHierarchy, renderMesh, out boundingBox);

                // Fast AABB transform: http://zeuxcg.org/2010/10/17/aabb-from-obb-with-component-wise-abs/
                // Compute transformed AABB (by world)
                // TODO: CullingMode should be pluggable
                // TODO: This should not be necessary. Add proper bounding boxes to gizmos etc.
                if (CullingMode == CullingMode.Frustum && boundingBox.Extent != Vector3.Zero && !frustum.Contains(ref boundingBox))
                {
                    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(renderMesh.WorldMatrix.TranslationVector, 1.0f);
                Vector4 projectedPosition;
                Vector4.Transform(ref worldPosition, ref ViewProjectionMatrix, out projectedPosition);
                var projectedZ = projectedPosition.Z / projectedPosition.W;

                renderMesh.RasterizerState = renderMesh.IsGeometryInverted ? RasterizerStateForInvertedGeometry : RasterizerState;

                renderMesh.UpdateMaterial();

                var list = renderMesh.HasTransparency ? transparentList : opaqueList;
                list.Add(new RenderItem(this, renderMesh, projectedZ));
            }
        }