public void UpdateNode() { LocalToWorld = /*Matrix4x4d.ToMatrix4x4d(transform.localToWorldMatrix) * */ FaceToLocal; Matrix4x4d localToCamera = View.WorldToCamera * LocalToWorld; Matrix4x4d localToScreen = View.CameraToScreen * localToCamera; Matrix4x4d invLocalToCamera = localToCamera.Inverse; DeformedCameraPos = invLocalToCamera * (new Vector3d(0)); Frustum3d.SetPlanes(DeformedFrustumPlanes, localToScreen); LocalCameraPos = Deform.DeformedToLocal(DeformedCameraPos); Matrix4x4d m = Deform.LocalToDeformedDifferential(LocalCameraPos, true); DistFactor = (float)Math.Max((new Vector3d(m[0, 0], m[1, 0], m[2, 0])).Magnitude, (new Vector3d(m[0, 1], m[1, 1], m[2, 1])).Magnitude); Vector3d left = DeformedFrustumPlanes[0].xyz.Normalized; Vector3d right = DeformedFrustumPlanes[1].xyz.Normalized; float fov = (float)MathUtility.Safe_Acos(-Vector3d.Dot(left, right)); float width = (float)Screen.width; SplitDist = m_splitFactor * width / 1024.0f * Mathf.Tan(40.0f * Mathf.Deg2Rad) / Mathf.Tan(fov / 2.0f); if (SplitDist < 1.1f || !MathUtility.IsFinite(SplitDist)) { SplitDist = 1.1f; } // initializes data structures for horizon occlusion culling if (HorizonCulling && LocalCameraPos.z <= Root.ZMax) { Vector3d deformedDir = invLocalToCamera * (new Vector3d(0, 0, 1)); Vector2d localDir = (Deform.DeformedToLocal(deformedDir) - LocalCameraPos).xy.Normalized; LocalCameraDir = new Matrix2x2d(localDir.y, -localDir.x, -localDir.x, -localDir.y); for (int i = 0; i < HORIZON_SIZE; ++i) { m_horizon[i] = float.NegativeInfinity; } } Root.Update(); World.SkyNode.SetUniforms(m_terrainMaterial); World.SunNode.SetUniforms(m_terrainMaterial); World.SetUniforms(m_terrainMaterial); Deform.SetUniforms(this, m_terrainMaterial); if (World.OceanNode != null) { World.OceanNode.SetUniforms(m_terrainMaterial); } else { m_terrainMaterial.SetFloat("_Ocean_DrawBRDF", 0.0f); } }
public List <Model3d> CullByFrustum(Frustum3d frustum) { List <Model3d> result = new List <Model3d>(); foreach (var iter in m_modleList) { iter.m_cullFlag = false; } if (m_octree == null) { foreach (var iter in m_modleList) { OBB3d bounds = iter.GetOBB(); if (IntersectionTest3D.Frustum3dWithOBB3d(frustum, bounds)) { result.Add(iter); } } } else { List <OctreeNode> nodes = new List <OctreeNode>(); nodes.Add(m_octree); while (nodes.Count > 0) { OctreeNode active = nodes[0]; nodes.RemoveAt(0); if (active.m_children != null) { // Has child nodes for (int i = 0; i < 8; ++i) { AABB3d bounds = active.m_children[i].m_bounds; if (IntersectionTest3D.Frustum3dWithAABB3d(frustum, bounds)) { nodes.Add(active.m_children[i]); } } } else { // Is leaf node for (int i = 0; i < active.m_models.Count; ++i) { if (!active.m_models[i].m_cullFlag) { OBB3d bounds = active.m_models[i].GetOBB(); if (IntersectionTest3D.Frustum3dWithOBB3d(frustum, bounds)) { active.m_models[i].m_cullFlag = true; result.Add(active.m_models[i]); } } } } } } return(result); }
/// <summary> /// Returns the visibility of a bounding box in local space, in a view /// frustum defined in deformed space. /// </summary> /// <param name="node">This is node is used to get the camera position /// in local and deformed space with TerrainNode::GetLocalCamera and /// TerrainNode::GetDeformedCamera, as well as the view frustum planes /// in deformed space with TerrainNode::GetDeformedFrustumPlanes. </param> /// <param name="localBox">a bounding box in local space.</param> /// <returns>the visibility of the bounding box in the view frustum.</returns> public virtual FRUSTUM_VISIBILTY GetVisibility(TerrainNode node, Box3d localBox) { // localBox = deformedBox, so we can compare the deformed frustum with it return(Frustum3d.GetVisibility(node.DeformedFrustumPlanes, localBox)); }
public override void UpdateNode() { TerrainMaterial.renderQueue = (int)ParentBody.RenderQueue + ParentBody.RenderQueueOffset; // NOTE : Body shape dependent... LocalToWorld = Matrix4x4d.ToMatrix4x4d(ParentBody.transform.localToWorldMatrix) * FaceToLocal; TangentFrameToWorld = new Matrix3x3d(LocalToWorld.m[0, 0], LocalToWorld.m[0, 1], LocalToWorld.m[0, 2], LocalToWorld.m[1, 0], LocalToWorld.m[1, 1], LocalToWorld.m[1, 2], LocalToWorld.m[2, 0], LocalToWorld.m[2, 1], LocalToWorld.m[2, 2]); LocalToCamera = GodManager.Instance.View.WorldToCameraMatrix * LocalToWorld; LocalToScreen = GodManager.Instance.View.CameraToScreenMatrix * LocalToCamera; var invLocalToCamera = LocalToCamera.Inverse(); DeformedCameraPosition = invLocalToCamera * Vector3d.zero; DeformedFrustumPlanes = Frustum3d.GetFrustumPlanes(LocalToScreen); // NOTE : Extract frustum planes from LocalToScreen matrix... LocalCameraPosition = Deformation.DeformedToLocal(DeformedCameraPosition); DeformedLocalToTangent = Deformation.DeformedToTangentFrame(GodManager.Instance.View.WorldCameraPosition) * LocalToWorld * Deformation.LocalToDeformedDifferential(LocalCameraPosition); var m = Deformation.LocalToDeformedDifferential(LocalCameraPosition, true); var left = DeformedFrustumPlanes[0].xyz.Normalized(); var right = DeformedFrustumPlanes[1].xyz.Normalized(); var fov = (float)Functions.Safe_Acos(-left.Dot(right)); SplitDistance = SplitFactor * Screen.width / 1024.0f * Mathf.Tan(40.0f * Mathf.Deg2Rad) / Mathf.Tan(fov / 2.0f); DistanceFactor = (float)Math.Max(new Vector3d(m.m[0, 0], m.m[1, 0], m.m[2, 0]).Magnitude(), new Vector3d(m.m[0, 1], m.m[1, 1], m.m[2, 1]).Magnitude()); if (SplitDistance < 1.1f || SplitDistance > 128.0f || !Functions.IsFinite(SplitDistance)) { SplitDistance = 1.1f; } var splitDistanceBlending = SplitDistance + 1.0f; DistanceBlending = new Vector2(splitDistanceBlending, 2.0f * SplitDistance - splitDistanceBlending); // Initializes data structures for horizon occlusion culling if (UseHorizonCulling && LocalCameraPosition.z <= TerrainQuadRoot.ZMax) { var deformedDirection = invLocalToCamera * Vector3d.forward; var localDirection = (Deformation.DeformedToLocal(deformedDirection) - LocalCameraPosition).Normalized(); LocalCameraDirection = new Matrix2x2d(localDirection.y, -localDirection.x, -localDirection.x, -localDirection.y); for (var i = 0; i < HORIZON_SIZE; ++i) { Horizon[i] = float.NegativeInfinity; } } if (ParentBody.UpdateLOD) { TerrainQuadRoot.UpdateLOD(); } SetUniforms(TerrainMaterial); }