public static void AccessorSpaceToAccessorSpacePosition(this IWorldRAccessor self, IWorldRAccessor accessor, ref int x, ref int y, ref int z) { Vector3Int origin = self.WorldSpaceOrigin - accessor.WorldSpaceOrigin; x += origin.x; y += origin.y; z += origin.z; }
protected bool ClipFace(Vector3Int pos, BlockData block, BlockFace face, IWorldRAccessor accessor) { switch (face) { case BlockFace.PositiveX: pos.x++; break; case BlockFace.PositiveY: pos.y++; break; case BlockFace.PositiveZ: pos.z++; break; case BlockFace.NegativeX: pos.x--; break; case BlockFace.NegativeY: pos.y--; break; case BlockFace.NegativeZ: pos.z--; break; default: throw new NotSupportedException("Unknown BlockFace."); } BlockData neighbor = accessor.GetBlock(pos.x, pos.y, pos.z); if (neighbor == null) { return(AggressiveBlockFaceClipping); } BlockMesh mesh = accessor.World.BlockDataTable.GetMesh(neighbor.Mesh.Value); Vector3 size = mesh.BoundingBox.Size; if (size.x < 1 || size.y < 1 || size.z < 1) { return(false); } switch (block.PhysicState) { case PhysicState.Fluid: return((block == neighbor) || neighbor.IsOpaqueBlock()); case PhysicState.Solid: return(neighbor.IsOpaqueBlock()); default: throw new NotSupportedException("Unknown BlockPhysicalState"); } }
public static void AccessorSpaceToWorldSpacePosition(this IWorldRAccessor accessor, ref int x, ref int y, ref int z) { AccessorSpaceToWorldSpacePosition(accessor.WorldSpaceOrigin, ref x, ref y, ref z); }
public static Vector2 AmbientOcclusion(Vector3Int pos, BlockFace face, BlockFaceCorner corner, IWorldRAccessor accessor, bool fastMode) { if (fastMode) { float skyLight = MapLight01(accessor.GetSkyLight(pos.x, pos.y, pos.z)); float ambient = MapLight01(accessor.GetAmbientLight(pos.x, pos.y, pos.z)); return(new Vector2(skyLight, ambient)); } int faceIndex = (int)face; int cornerIndex = (int)corner; Vector2 lights = Vector2Int.zero; for (int i = 0; i < AmbientLightSampleCount; i++) { Vector3Int p = pos + AmbientLightSampleDirections[faceIndex, cornerIndex, i]; lights.x += accessor.GetSkyLight(p.x, p.y, p.z); lights.y += accessor.GetAmbientLight(p.x, p.y, p.z); } return(MapLight01(lights / AmbientLightSampleCount)); }
public void AddBlock(Vector3Int pos, Vector3Int renderOffset, BlockData block, IWorldRAccessor accessor) { Quaternion rotation = accessor.GetBlockRotation(pos.x, pos.y, pos.z, Quaternion.identity); BlockMesh mesh = accessor.World.BlockDataTable.GetMesh(block.Mesh.Value); for (int i = 0; i < mesh.Faces.Length; i++) { BlockMesh.FaceData face = mesh.Faces[i]; BlockFace faceDir = RotateFace(face.Face, rotation); if (EnableFaceClipping) { // 没有撑满一格的方块所有的面都渲染 Vector3 size = mesh.BoundingBox.Size; bool neverClip = face.NeverClip | size.x < 1 | size.y < 1 | size.z < 1; if (!neverClip && ClipFace(pos, block, faceDir, accessor)) { continue; } } int?[] texIndices = block.Textures[i]; // !!! must add indices first for (int j = 0; j < face.Indices.Length; j++) { AddIndex(face.Indices[j], block.Material.Value); } for (int j = 0; j < face.Vertices.Length; j++) { BlockVertexData vertex = face.Vertices[j]; vertex.Position = MathUtility.RotatePoint(vertex.Position, rotation, mesh.Pivot); float emission = block.GetEmissionValue(); Vector2 ambient = LightingUtility.AmbientOcclusion(pos, faceDir, vertex.CornerInFace, accessor, !EnableAmbientOcclusion); Vector3 posWS = WriteBlockWSPosToVertexData ? (pos + accessor.WorldSpaceOrigin) : Vector3.down; AddVertex(new BlockMeshVertexData { PositionOS = vertex.Position + pos + renderOffset, UV = vertex.UV, TexIndices = new Vector3Int(texIndices[0].Value, texIndices[1].Value, texIndices[2].Value), Lights = new Vector3(emission, ambient.x, ambient.y), BlockPositionWS = posWS }); } } }