void Update() { // Rotation if (Input.GetMouseButton(1)) { rot = new Vector2( rot.x + Input.GetAxis("Mouse X") * 3, rot.y + Input.GetAxis("Mouse Y") * 3 ); cam.transform.localRotation = Quaternion.AngleAxis(rot.x, Vector3.up); cam.transform.localRotation *= Quaternion.AngleAxis(rot.y, Vector3.left); } //Movement bool turbo = Input.GetKeyDown(KeyCode.LeftShift) || Input.GetKeyDown(KeyCode.RightShift); cam.transform.position += cam.transform.forward * 40 * (turbo ? 3 : 1) * Input.GetAxis("Vertical") * Time.deltaTime; cam.transform.position += cam.transform.right * 40 * (turbo ? 3 : 1) * Input.GetAxis("Horizontal") * Time.deltaTime; if (objRenderer != null && txt != null) { Planes.CalculateFrustumPlanes(cam, planes); Bounds b = objRenderer.bounds; Planes.TestPlanesResult res = Planes.TestPlanesAABB2(planes, ref b); switch (res) { case Planes.TestPlanesResult.Outside: txt.text = "Outside"; break; case Planes.TestPlanesResult.Inside: txt.text = "Inside"; break; default: txt.text = "PartialyInside"; break; } } }
protected override void UpdateVisibility(int x, int y, int z, int rangeX, int rangeY, int rangeZ) { if (rangeX == 0 || rangeY == 0 || rangeZ == 0) { return; } Profiler.BeginSample("Cull"); bool isLast = rangeX == 1 && rangeY == 1 && rangeZ == 1; int wx = x * Env.CHUNK_SIZE; int wy = y * Env.CHUNK_SIZE; int wz = z * Env.CHUNK_SIZE; // Stop if there is no further subdivision possible if (isLast) { Profiler.BeginSample("CullLast"); // Update chunk's visibility information Vector3Int chunkPos = new Vector3Int(wx, wy, wz); Chunk chunk = world.GetChunk(ref chunkPos); if (chunk != null) { int tx = clipmap.TransformX(x); int ty = clipmap.TransformY(y); int tz = clipmap.TransformZ(z); // Skip chunks which are too far away if (clipmap.IsInsideBounds_Transformed(tx, ty, tz)) { // Update visibility information ClipmapItem item = clipmap.Get_Transformed(tx, ty, tz); bool isVisible = Planes.TestPlanesAABB(cameraPlanes, ref chunk.worldBounds); chunk.NeedsRenderGeometry = isVisible && item.isInVisibleRange; chunk.PossiblyVisible = isVisible; } } Profiler.EndSample(); // CullLast Profiler.EndSample(); // Cull return; } int rx = rangeX * Env.CHUNK_SIZE; int ry = rangeY * Env.CHUNK_SIZE; int rz = rangeZ * Env.CHUNK_SIZE; // Check whether the bouding box lies inside the camera's frustum AABB bounds2 = new AABB(wx, wy, wz, wx + rx, wy + ry, wz + rz); Planes.TestPlanesResult res = Planes.TestPlanesAABB2(cameraPlanes, ref bounds2); #region Full invisibility // Everything is invisible by default if (res == Planes.TestPlanesResult.Outside) { Profiler.EndSample(); // Cull return; } #endregion #region Full visibility if (res == Planes.TestPlanesResult.Inside) { Profiler.BeginSample("CullFullInside"); // Full visibility. All chunks in this area need to be made visible for (int cy = wy; cy < wy + ry; cy += Env.CHUNK_SIZE) { for (int cz = wz; cz < wz + rz; cz += Env.CHUNK_SIZE) { for (int cx = wx; cx < wx + rx; cx += Env.CHUNK_SIZE) { // Update chunk's visibility information Vector3Int chunkPos = new Vector3Int(cx, cy, cz); Chunk chunk = world.GetChunk(ref chunkPos); if (chunk == null) { continue; } int tx = clipmap.TransformX(x); int ty = clipmap.TransformY(y); int tz = clipmap.TransformZ(z); // Update visibility information ClipmapItem item = clipmap.Get_Transformed(tx, ty, tz); chunk.NeedsRenderGeometry = item.isInVisibleRange; chunk.PossiblyVisible = true; } } } Profiler.EndSample(); // CullLast Profiler.EndSample(); // Cull return; } #endregion #region Partial visibility int offX = rangeX; if (rangeX > 1) { offX = rangeX >> 1; rangeX -= offX; } int offY = rangeY; if (rangeY > 1) { offY = rangeY >> 1; rangeY -= offY; } int offZ = rangeZ; if (rangeZ > 1) { offZ = rangeZ >> 1; rangeZ -= offZ; } Profiler.EndSample(); // Subdivide if possible // TODO: Avoid the recursion UpdateVisibility(x, y, z, offX, offY, offZ); UpdateVisibility(x + offX, y, z, rangeX, offY, offZ); UpdateVisibility(x, y, z + offZ, offX, offY, rangeZ); UpdateVisibility(x + offX, y, z + offZ, rangeX, offY, rangeZ); UpdateVisibility(x, y + offY, z, offX, rangeY, offZ); UpdateVisibility(x + offX, y + offY, z, rangeX, rangeY, offZ); UpdateVisibility(x, y + offY, z + offZ, offX, rangeY, rangeZ); UpdateVisibility(x + offX, y + offY, z + offZ, rangeX, rangeY, rangeZ); #endregion }