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