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