private static void BuildVoxelGeometry( RawPrimitive Into, int X, int Y, int Z, VoxelChunk Chunk, //BoxPrimitive BedrockModel, Cache Cache, DesignationSet Designations, WorldManager World) { var v = VoxelHandle.UnsafeCreateLocalHandle(Chunk, new LocalVoxelCoordinate(X, Y, Z)); if (!v.IsValid || !v.IsVisible) { return; // How did this even get called then?? } BuildDesignationGeometry(Into, Chunk, Cache, Designations, World, v); if ((v.IsExplored && v.IsEmpty)) { return; } if (!v.IsExplored && v.Sunlight) { return; } if (Library.GetVoxelPrimitive(v.Type).HasValue(out BoxPrimitive primitive)) { BuildVoxelGeometryFromPrimitive(Into, Chunk, Cache, v, primitive); } }
private static void BuildDesignationGeometry(RawPrimitive Into, VoxelChunk Chunk, Cache Cache, DesignationSet Designations, WorldManager World, VoxelHandle v) { // Todo: Store designations per chunk. foreach (var designation in Designations == null ? new List <DesignationSet.VoxelDesignation>() : Designations.EnumerateDesignations(v).ToList()) { if ((designation.Type & World.Renderer.PersistentSettings.VisibleTypes) != designation.Type) // If hidden by player, do not draw. { return; } var designationProperties = Library.GetDesignationTypeProperties(designation.Type).Value; var designationVisible = false; if (designation.Type == DesignationType.Put) { designationVisible = v.Coordinate.Y < World.Renderer.PersistentSettings.MaxViewingLevel; } else { designationVisible = VoxelHelpers.DoesVoxelHaveVisibleSurface(World, v); } if (designationVisible && Library.GetVoxelPrimitive(Library.DesignationVoxelType).HasValue(out BoxPrimitive designationPrimitive)) { switch (designationProperties.DrawType) { case DesignationDrawType.FullBox: for (int i = 0; i < 6; i++) { BuildVoxelFaceGeometry(Into, Chunk, Cache, designationPrimitive, v, designationProperties.Color, designationPrimitive.UVs, DesignationTransform, (BoxFace)i, false); } break; case DesignationDrawType.TopBox: BuildVoxelFaceGeometry(Into, Chunk, Cache, designationPrimitive, v, designationProperties.Color, designationPrimitive.UVs, DesignationTransform, 0, false); break; case DesignationDrawType.PreviewVoxel: { if (Library.GetVoxelType(designation.Tag.ToString()).HasValue(out VoxelType voxelType) && Library.GetVoxelPrimitive(voxelType).HasValue(out BoxPrimitive previewPrimitive)) { var offsetMatrix = Matrix.Identity; if (!v.IsEmpty) { offsetMatrix = Matrix.CreateTranslation(0.0f, 0.1f, 0.0f); } for (int i = 0; i < 6; i++) { BuildVoxelFaceGeometry(Into, Chunk, Cache, previewPrimitive, v, designationProperties.Color, previewPrimitive.UVs, offsetMatrix, (BoxFace)i, false); } } } break; } } } }
private static void BuildVoxelGeometry( RawPrimitive Into, int X, int Y, int Z, VoxelChunk Chunk, BoxPrimitive BedrockModel, Cache Cache, DesignationSet Designations, WorldManager World) { var v = VoxelHandle.UnsafeCreateLocalHandle(Chunk, new LocalVoxelCoordinate(X, Y, Z)); if (!v.IsValid || !v.IsVisible) { return; // How did this even get called then?? } BuildDesignationGeometry(Into, Chunk, Cache, Designations, World, v); if ((v.IsExplored && v.IsEmpty)) { return; } var primitive = Library.GetVoxelPrimitive(v.Type); if (v.IsExplored && primitive == null) { return; } if (!v.IsExplored && v.Sunlight) { return; } if (primitive == null) { primitive = BedrockModel; } var tint = v.Type.Tint; var uvs = primitive.UVs; if (v.Type.HasTransitionTextures && v.IsExplored) { uvs = ComputeTransitionTexture(new VoxelHandle(v.Chunk.Manager, v.Coordinate)); } BuildVoxelTopFaceGeometry(Into, Chunk, Cache, primitive, v, uvs, 0); for (int i = 1; i < 6; i++) { BuildVoxelFaceGeometry(Into, Chunk, Cache, primitive, v, tint, uvs, Matrix.Identity, i, true); } }
private static void BuildDesignationGeometry(RawPrimitive Into, VoxelChunk Chunk, Cache Cache, DesignationSet Designations, WorldManager World, VoxelHandle v) { var designations = Designations == null ? new List <DesignationSet.VoxelDesignation>() : Designations.EnumerateDesignations(v).ToList(); int maxViewingLevel = World.Renderer.PersistentSettings.MaxViewingLevel; foreach (var designation in designations) { if ((designation.Type & World.Renderer.PersistentSettings.VisibleTypes) == designation.Type) { var props = Library.GetDesignationTypeProperties(designation.Type); var designationVisible = false; if (designation.Type == DesignationType.Put) { designationVisible = v.Coordinate.Y < maxViewingLevel; } else { designationVisible = VoxelHelpers.DoesVoxelHaveVisibleSurface(World, v); } if (designationVisible) { var desPrim = Library.GetVoxelPrimitive(Library.DesignationVoxelType); switch (props.DrawType) { case DrawBoxType.FullBox: for (int i = 0; i < 6; i++) { BuildVoxelFaceGeometry(Into, Chunk, Cache, desPrim, v, props.Color, desPrim.UVs, DesignationTransform, i, false); } break; case DrawBoxType.TopBox: BuildVoxelFaceGeometry(Into, Chunk, Cache, desPrim, v, props.Color, desPrim.UVs, DesignationTransform, 0, false); break; case DrawBoxType.PreviewVoxel: { var previewPrim = Library.GetVoxelPrimitive(Library.GetVoxelType(designation.Tag.ToString())); var offsetMatrix = Matrix.Identity; if (!v.IsEmpty) { offsetMatrix = Matrix.CreateTranslation(0.0f, 0.1f, 0.0f); } for (int i = 0; i < 6; i++) { BuildVoxelFaceGeometry(Into, Chunk, Cache, previewPrim, v, props.Color, previewPrim.UVs, offsetMatrix, i, false); } } break; } } } } }
public MeshComponent( ComponentManager Manager, Matrix localTransform, Vector3 boundingBoxExtents, Vector3 boundingBoxPos, RawPrimitive Mesh, String Asset) : base(Manager, "primitive", localTransform, boundingBoxExtents, boundingBoxPos) { this.Mesh = Mesh; this.Asset = Asset; }
private static void AddDecalGeometry( RawPrimitive Into, int[] AmbientScratchSpace, BoxPrimitive Primitive, VoxelHandle V, BoxPrimitive.FaceDescriptor faceDescriptor, int exploredVerts, Vector3[] VertexPositions, VertexColorInfo[] VertexColors, Color[] VertexTints, DecalType Decal, byte Orientation) { var indexOffset = Into.VertexCount; var UV = new Vector2(Decal.Tile.X * (1.0f / 16.0f), Decal.Tile.Y * (1.0f / 16.0f)); var UVBounds = new Vector4(UV.X + 0.001f, UV.Y + 0.001f, UV.X + (1.0f / 16.0f) - 0.001f, UV.Y + (1.0f / 16.0f) - 0.001f); var UVs = new Vector2[faceDescriptor.VertexCount]; for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++) { var vertex = Primitive.Vertices[faceDescriptor.VertexOffset + faceVertex]; UVs[faceVertex] = UV + new Vector2(vertex.Position.X / 16.0f, vertex.Position.Z / 16.0f); } for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++) { var vertex = Primitive.Vertices[faceDescriptor.VertexOffset + faceVertex]; AmbientScratchSpace[faceVertex] = VertexColors[faceVertex].AmbientColor; var uv = faceVertex + Orientation; uv %= faceDescriptor.VertexCount; // This will only work if the face has 4 verts... Into.AddVertex(new ExtendedVertex( VertexPositions[faceVertex] + VertexNoise.GetNoiseVectorFromRepeatingTexture(VertexPositions[faceVertex]), VertexColors[faceVertex].AsColor(), VertexTints[faceVertex], UVs[uv], UVBounds)); } bool flippedQuad = AmbientScratchSpace[0] + AmbientScratchSpace[2] > AmbientScratchSpace[1] + AmbientScratchSpace[3]; for (int idx = faceDescriptor.IndexOffset; idx < faceDescriptor.IndexCount + faceDescriptor.IndexOffset; idx++) { ushort offset = flippedQuad ? Primitive.FlippedIndexes[idx] : Primitive.Indexes[idx]; ushort offset0 = flippedQuad ? Primitive.FlippedIndexes[faceDescriptor.IndexOffset] : Primitive.Indexes[faceDescriptor.IndexOffset]; Into.AddIndex((short)(indexOffset + offset - offset0)); } }
private static void BuildSliceGeometry( VoxelChunk chunk, BoxPrimitive bedrockModel, Cache Cache, int y, RawPrimitive sliceGeometry) { for (var x = 0; x < VoxelConstants.ChunkSizeX; ++x) { for (var z = 0; z < VoxelConstants.ChunkSizeZ; ++z) { BuildVoxelGeometry(sliceGeometry, x, y, z, chunk, bedrockModel, Cache); } } }
private static void BuildVoxelGeometryFromPrimitive(RawPrimitive Into, VoxelChunk Chunk, Cache Cache, VoxelHandle v, BoxPrimitive primitive) { var tint = v.Type.Tint; var uvs = primitive.UVs; if (v.Type.HasTransitionTextures && v.IsExplored) { uvs = ComputeTransitionTexture(new VoxelHandle(v.Chunk.Manager, v.Coordinate)); } BuildVoxelTopFaceGeometry(Into, Chunk, Cache, primitive, v, uvs); for (int i = 1; i < 6; i++) { BuildVoxelFaceGeometry(Into, Chunk, Cache, primitive, v, tint, uvs, Matrix.Identity, (BoxFace)i, true); } }
private static void BuildSliceGeometry( VoxelChunk chunk, BoxPrimitive bedrockModel, Cache Cache, int LocalY, RawPrimitive sliceGeometry, DesignationSet DesignationSet, WorldManager World) { for (var x = 0; x < VoxelConstants.ChunkSizeX; ++x) { for (var z = 0; z < VoxelConstants.ChunkSizeZ; ++z) { BuildVoxelGeometry(sliceGeometry, x, LocalY, z, chunk, bedrockModel, Cache, DesignationSet, World); } } }
private static void BuildVoxelGeometry( RawPrimitive Into, int X, int Y, int Z, VoxelChunk Chunk, BoxPrimitive BedrockModel, Cache Cache) { var v = new VoxelHandle(Chunk, new LocalVoxelCoordinate(X, Y, Z)); if ((v.IsExplored && v.IsEmpty) || !v.IsVisible) { return; } var primitive = VoxelLibrary.GetPrimitive(v.Type); if (v.IsExplored && primitive == null) { return; } if (primitive == null) { primitive = BedrockModel; } var tint = v.Type.Tint; var uvs = primitive.UVs; if (v.Type.HasTransitionTextures && v.IsExplored) { uvs = ComputeTransitionTexture(new VoxelHandle(v.Chunk.Manager.ChunkData, v.Coordinate)); } BuildVoxelTopFaceGeometry(Into, Chunk, Cache, primitive, v, uvs, 0); for (int i = 1; i < 6; i++) { BuildVoxelFaceGeometry(Into, Chunk, Cache, primitive, v, tint, uvs, i); } }
public override void CreateCosmeticChildren(ComponentManager Manager) { base.CreateCosmeticChildren(Manager); if (SharedMesh == null) { SharedMesh = AssetManager.GetContentMesh("Entities/Furniture/sm_anvil"); } AddChild(new MeshComponent(Manager, Matrix.CreateRotationY(0.25f), new Vector3(1.0f, 1.0f, 1.0f), new Vector3(0.0f, 0.0f, 0.0f), SharedMesh, "Entities/Furniture/tx_anvil")) .SetFlag(Flag.ShouldSerialize, false) .SetFlag(Flag.RotateBoundingBox, true); }
private static void BuildDecalGeometry( RawPrimitive Into, VoxelChunk Chunk, Cache Cache, BoxPrimitive Primitive, VoxelHandle V, VertexColorInfo[] VertexColors, Color[] VertexTint, Vector3[] VertexPositions, BoxPrimitive.FaceDescriptor Face, int ExploredVerts) { if (V.DecalType == 0) { return; } var decalType = Library.GetDecalType(V.DecalType); AddDecalGeometry(Into, Cache.AmbientValues, Primitive, Face, ExploredVerts, VertexPositions, VertexColors, VertexTint, decalType); }
private static void AddGrassGeometry( RawPrimitive Into, int[] AmbientScratchSpace, BoxPrimitive Primitive, BoxPrimitive.FaceDescriptor faceDescriptor, Vector3[] VertexPositions, VertexColorInfo[] VertexColors, Color[] VertexTints, GrassType Decal) { var indexOffset = Into.VertexCount; var UV = new Vector2(Decal.Tile.X * (1.0f / 16.0f), Decal.Tile.Y * (1.0f / 16.0f)); var UVBounds = new Vector4(UV.X + 0.001f, UV.Y + 0.001f, UV.X + (1.0f / 16.0f) - 0.001f, UV.Y + (1.0f / 16.0f) - 0.001f); for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++) { var vertex = Primitive.Vertices[faceDescriptor.VertexOffset + faceVertex]; AmbientScratchSpace[faceVertex] = VertexColors[faceVertex].AmbientColor; Into.AddVertex(new ExtendedVertex( VertexPositions[faceVertex] + VertexNoise.GetNoiseVectorFromRepeatingTexture(VertexPositions[faceVertex]), VertexColors[faceVertex].AsColor(), VertexTints[faceVertex], UV + new Vector2(vertex.Position.X / 16.0f, vertex.Position.Z / 16.0f), UVBounds)); } bool flippedQuad = (AmbientScratchSpace[0] + AmbientScratchSpace[2]) > (AmbientScratchSpace[1] + AmbientScratchSpace[3]); for (int idx = faceDescriptor.IndexOffset; idx < faceDescriptor.IndexCount + faceDescriptor.IndexOffset; ++idx) { ushort offset = flippedQuad ? Primitive.FlippedIndexes[idx] : Primitive.Indexes[idx]; ushort offset0 = flippedQuad ? Primitive.FlippedIndexes[faceDescriptor.IndexOffset] : Primitive.Indexes[faceDescriptor.IndexOffset]; Into.AddIndex((short)(indexOffset + offset - offset0)); } }
private static void BuildVoxelFaceGeometry( RawPrimitive Into, VoxelChunk Chunk, Cache Cache, BoxPrimitive Primitive, VoxelHandle V, Color Tint, BoxPrimitive.BoxTextureCoords UVs, Matrix VertexTransform, int i, bool ApplyLighting) { var face = (BoxFace)i; var delta = FaceDeltas[i]; var faceVoxel = new VoxelHandle(Chunk.Manager, V.Coordinate + GlobalVoxelOffset.FromVector3(delta)); if (!IsFaceVisible(V, faceVoxel, face)) { return; } var faceDescriptor = Primitive.GetFace(face); var indexOffset = Into.VertexCount; for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++) { var vertex = Primitive.Vertices[faceDescriptor.VertexOffset + faceVertex]; var voxelVertex = Primitive.Deltas[faceDescriptor.VertexOffset + faceVertex]; var vertexColor = new VertexColorInfo { SunColor = 255, AmbientColor = 255, DynamicColor = 255, }; if (ApplyLighting) { var cacheKey = GetCacheKey(V, voxelVertex); if (!Cache.LightCache.TryGetValue(cacheKey, out vertexColor)) { vertexColor = CalculateVertexLight(V, voxelVertex, Chunk.Manager); Cache.LightCache.Add(cacheKey, vertexColor); } Cache.AmbientValues[faceVertex] = vertexColor.AmbientColor; } var rampOffset = Vector3.Zero; if (V.IsExplored && V.Type.CanRamp && ShouldRamp(voxelVertex, V.RampType)) { rampOffset = new Vector3(0, -V.Type.RampSize, 0); } var baseWorldPosition = V.WorldPosition + vertex.Position + rampOffset; var noise = VertexNoise.GetNoiseVectorFromRepeatingTexture(baseWorldPosition); var localPosition = Vector3.Transform(vertex.Position + rampOffset + noise, VertexTransform); Into.AddVertex(new ExtendedVertex( V.WorldPosition + localPosition, vertexColor.AsColor(), Tint, UVs.Uvs[faceDescriptor.VertexOffset + faceVertex], UVs.Bounds[faceDescriptor.IndexOffset / 6])); } bool flippedQuad = ApplyLighting && (Cache.AmbientValues[0] + Cache.AmbientValues[2] > Cache.AmbientValues[1] + Cache.AmbientValues[3]); for (int idx = faceDescriptor.IndexOffset; idx < faceDescriptor.IndexCount + faceDescriptor.IndexOffset; idx++) { ushort offset = flippedQuad ? Primitive.FlippedIndexes[idx] : Primitive.Indexes[idx]; ushort offset0 = flippedQuad ? Primitive.FlippedIndexes[faceDescriptor.IndexOffset] : Primitive.Indexes[faceDescriptor.IndexOffset]; Into.AddIndex((short)(indexOffset + offset - offset0)); } }
private static void BuildVoxelTopFaceGeometry( RawPrimitive Into, VoxelChunk Chunk, Cache Cache, BoxPrimitive Primitive, VoxelHandle V, BoxPrimitive.BoxTextureCoords UVs, int i) { var face = (BoxFace)i; var delta = FaceDeltas[i]; var faceVoxel = new VoxelHandle(Chunk.Manager, V.Coordinate + GlobalVoxelOffset.FromVector3(delta)); if (!IsFaceVisible(V, faceVoxel, face)) { return; } var faceDescriptor = Primitive.GetFace(face); int exploredVerts = 0; var vertexColors = new VertexColorInfo[4]; var vertexTint = new Color[4]; // Find all verticies to use for geometry later, and for the fringe var vertexPositions = new Vector3[4]; for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++) { var vertex = Primitive.Vertices[faceDescriptor.VertexOffset + faceVertex]; var voxelVertex = Primitive.Deltas[faceDescriptor.VertexOffset + faceVertex]; var rampOffset = Vector3.Zero; if (V.IsExplored && V.Type.CanRamp && ShouldRamp(voxelVertex, V.RampType)) { rampOffset = new Vector3(0, -V.Type.RampSize, 0); } var worldPosition = V.WorldPosition + vertex.Position + rampOffset; //worldPosition += VertexNoise.GetNoiseVectorFromRepeatingTexture(worldPosition); vertexPositions[faceVertex] = worldPosition; } if (V.IsExplored) { exploredVerts = 4; } else { for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; ++faceVertex) { var voxelVertex = Primitive.Deltas[faceDescriptor.VertexOffset + faceVertex]; var cacheKey = GetCacheKey(V, voxelVertex); bool anyNeighborExplored = true; if (!Cache.ExploredCache.TryGetValue(cacheKey, out anyNeighborExplored)) { anyNeighborExplored = VoxelHelpers.EnumerateVertexNeighbors2D(V.Coordinate, voxelVertex) .Select(c => new VoxelHandle(V.Chunk.Manager, c)) .Any(n => n.IsValid && n.IsExplored); Cache.ExploredCache.Add(cacheKey, anyNeighborExplored); } if (anyNeighborExplored) { exploredVerts += 1; } } } for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; ++faceVertex) { var voxelVertex = Primitive.Deltas[faceDescriptor.VertexOffset + faceVertex]; var cacheKey = GetCacheKey(V, voxelVertex); VertexColorInfo vertexColor; if (!Cache.LightCache.TryGetValue(cacheKey, out vertexColor)) { vertexColor = CalculateVertexLight(V, voxelVertex, Chunk.Manager); Cache.LightCache.Add(cacheKey, vertexColor); } vertexColors[faceVertex] = vertexColor; vertexTint[faceVertex] = new Color(1.0f, 1.0f, 1.0f, 1.0f); if (exploredVerts != 4) { bool anyNeighborExplored = true; if (!Cache.ExploredCache.TryGetValue(cacheKey, out anyNeighborExplored)) { throw new InvalidProgramException("Failed cache lookup"); } if (!anyNeighborExplored) { vertexTint[faceVertex] = new Color(0.0f, 0.0f, 0.0f, 1.0f); } } vertexTint[faceVertex] = new Color(vertexTint[faceVertex].ToVector4() * V.Type.Tint.ToVector4()); } if (exploredVerts != 0) { var baseUVs = UVs.Uvs[11]; // EW var baseUVBounds = new Vector4(baseUVs.X + 0.001f, baseUVs.Y + 0.001f, baseUVs.X + (1.0f / 16.0f) - 0.001f, baseUVs.Y + (1.0f / 16.0f) - 0.001f); // Draw central top tile. AddTopFaceGeometry(Into, Cache.AmbientValues, Primitive, faceDescriptor, vertexPositions, vertexColors, vertexTint, Vector2.One, baseUVs, baseUVBounds); if (V.GrassType != 0) { BuildGrassFringeGeometry(Into, Chunk, Cache, Primitive, V, vertexColors, vertexTint, vertexPositions, faceDescriptor, exploredVerts); } } else { if (!Debugger.Switches.HideSliceTop) { var indexOffset = Into.VertexCount; for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++) { Into.AddVertex(new ExtendedVertex( vertexPositions[faceVertex] + VertexNoise.GetNoiseVectorFromRepeatingTexture(vertexPositions[faceVertex]), new Color(0, 0, 0, 255), new Color(0, 0, 0, 255), new Vector2(12.5f / 16.0f, 0.5f / 16.0f), new Vector4(12.0f / 16.0f, 0.0f, 13.0f / 16.0f, 1.0f / 16.0f))); } for (int idx = faceDescriptor.IndexOffset; idx < faceDescriptor.IndexCount + faceDescriptor.IndexOffset; idx++) { ushort offset = Primitive.Indexes[idx]; ushort offset0 = Primitive.Indexes[faceDescriptor.IndexOffset]; Into.AddIndex((short)(indexOffset + offset - offset0)); } } } }
private static void BuildVoxelFaceGeometry( RawPrimitive Into, VoxelChunk Chunk, Cache Cache, BoxPrimitive Primitive, VoxelHandle V, Color Tint, BoxPrimitive.BoxTextureCoords UVs, Matrix VertexTransform, BoxFace BoxFace, bool ApplyLighting) { if (!IsFaceVisible(V, BoxFace, Chunk.Manager, out var neighbor)) { return; } var faceDescriptor = Primitive.GetFace(BoxFace); var indexOffset = Into.VertexCount; for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++) { var vertex = Primitive.Vertices[faceDescriptor.VertexOffset + faceVertex]; var voxelVertex = Primitive.VertexClassifications[faceDescriptor.VertexOffset + faceVertex]; var vertexColor = new VertexColorInfo { SunColor = 255, AmbientColor = 255, DynamicColor = 255, }; if (ApplyLighting) { var cacheKey = GetCacheKey(V, voxelVertex); if (!Cache.LightCache.TryGetValue(cacheKey, out vertexColor)) { vertexColor = CalculateVertexLight(V, voxelVertex, Chunk.Manager); Cache.LightCache.Add(cacheKey, vertexColor); } Cache.AmbientValues[faceVertex] = vertexColor.AmbientColor; if (!V.IsExplored && !neighbor.IsValid) // Turns the outside of the world black when it's not explored. { Tint = new Color(0.0f, 0.0f, 0.0f, 1.0f); } } var rampOffset = Vector3.Zero; if (V.IsExplored && V.Type.CanRamp && ShouldRamp(voxelVertex, V.RampType)) { rampOffset = new Vector3(0, -0.5f, 0); } var baseWorldPosition = V.WorldPosition + vertex.Position + rampOffset; var noise = VertexNoise.GetNoiseVectorFromRepeatingTexture(baseWorldPosition); var localPosition = Vector3.Transform(vertex.Position + rampOffset + noise, VertexTransform); Into.AddVertex(new ExtendedVertex( V.WorldPosition + localPosition, vertexColor.AsColor(), Tint, UVs.Uvs[faceDescriptor.VertexOffset + faceVertex], UVs.Bounds[faceDescriptor.IndexOffset / 6])); } // Sometimes flip the quad to smooth out lighting. bool flippedQuad = ApplyLighting && (Cache.AmbientValues[0] + Cache.AmbientValues[2] > Cache.AmbientValues[1] + Cache.AmbientValues[3]); for (int idx = faceDescriptor.IndexOffset; idx < faceDescriptor.IndexCount + faceDescriptor.IndexOffset; idx++) { ushort offset = flippedQuad ? Primitive.FlippedIndexes[idx] : Primitive.Indexes[idx]; ushort offset0 = flippedQuad ? Primitive.FlippedIndexes[faceDescriptor.IndexOffset] : Primitive.Indexes[faceDescriptor.IndexOffset]; Into.AddIndex((short)(indexOffset + offset - offset0)); } }
private static void BuildVoxelTopFaceGeometry( RawPrimitive Into, VoxelChunk Chunk, Cache Cache, BoxPrimitive Primitive, VoxelHandle V, BoxPrimitive.BoxTextureCoords UVs) { if (!IsFaceVisible(V, BoxFace.Top, Chunk.Manager, out var _)) { return; } var faceDescriptor = Primitive.GetFace(BoxFace.Top); int exploredVerts = 0; var vertexColors = new VertexColorInfo[4]; var vertexTint = new Color[4]; // Find all verticies to use for geometry later, and for the fringe var vertexPositions = new Vector3[4]; for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++) { var vertex = Primitive.Vertices[faceDescriptor.VertexOffset + faceVertex]; var voxelVertex = Primitive.VertexClassifications[faceDescriptor.VertexOffset + faceVertex]; var rampOffset = Vector3.Zero; if (V.IsExplored && V.Type.CanRamp && ShouldRamp(voxelVertex, V.RampType)) { rampOffset = new Vector3(0, -0.5f, 0); } var worldPosition = V.WorldPosition + vertex.Position + rampOffset; //worldPosition += VertexNoise.GetNoiseVectorFromRepeatingTexture(worldPosition); vertexPositions[faceVertex] = worldPosition; } // Figure out if this vertex is adjacent to any explored voxel. if (V.IsExplored) { exploredVerts = 4; } else { for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; ++faceVertex) { var voxelVertex = Primitive.VertexClassifications[faceDescriptor.VertexOffset + faceVertex]; var cacheKey = GetCacheKey(V, voxelVertex); var anyNeighborExplored = true; if (!Cache.ExploredCache.TryGetValue(cacheKey, out anyNeighborExplored)) { anyNeighborExplored = VoxelHelpers.EnumerateVertexNeighbors2D(V.Coordinate, voxelVertex) .Select(c => new VoxelHandle(V.Chunk.Manager, c)) .Any(n => n.IsValid && n.IsExplored); Cache.ExploredCache.Add(cacheKey, anyNeighborExplored); } if (anyNeighborExplored) { exploredVerts += 1; } } } for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; ++faceVertex) { var voxelVertex = Primitive.VertexClassifications[faceDescriptor.VertexOffset + faceVertex]; var cacheKey = GetCacheKey(V, voxelVertex); VertexColorInfo vertexColor; if (!Cache.LightCache.TryGetValue(cacheKey, out vertexColor)) { vertexColor = CalculateVertexLight(V, voxelVertex, Chunk.Manager); Cache.LightCache.Add(cacheKey, vertexColor); } vertexColors[faceVertex] = vertexColor; vertexTint[faceVertex] = new Color(1.0f, 1.0f, 1.0f, 1.0f); // Turn face solid black if there are no explored neighbors - this is an optimization; it means we do not need to apply a solid black decal. if (exploredVerts != 4) { var anyNeighborExplored = true; if (!Cache.ExploredCache.TryGetValue(cacheKey, out anyNeighborExplored)) { throw new InvalidProgramException("Failed cache lookup"); } if (!anyNeighborExplored) { vertexTint[faceVertex] = new Color(0.0f, 0.0f, 0.0f, 1.0f); } } vertexTint[faceVertex] = new Color(vertexTint[faceVertex].ToVector4() * V.Type.Tint.ToVector4()); } if (exploredVerts != 0) { var baseUVs = UVs.Uvs[11]; // EW var baseUVBounds = new Vector4(baseUVs.X + 0.001f, baseUVs.Y + 0.001f, baseUVs.X + (1.0f / 16.0f) - 0.001f, baseUVs.Y + (1.0f / 16.0f) - 0.001f); // Draw the base voxel AddTopFaceGeometry(Into, Cache.AmbientValues, Primitive, faceDescriptor, vertexPositions, vertexColors, vertexTint, Vector2.One, baseUVs, baseUVBounds); if (V.GrassType != 0) { BuildGrassFringeGeometry(Into, Chunk, Cache, Primitive, V, vertexColors, vertexTint, vertexPositions, faceDescriptor); } if (V.DecalType != 0) { BuildDecalGeometry(Into, Chunk, Cache, Primitive, V, vertexColors, vertexTint, vertexPositions, faceDescriptor, exploredVerts); } } else { // Apparently being unexplored hides all grass and decals. Is that the behavior we actually want? if (!Debugger.Switches.HideSliceTop) { var indexOffset = Into.VertexCount; for (int faceVertex = 0; faceVertex < faceDescriptor.VertexCount; faceVertex++) { Into.AddVertex(new ExtendedVertex( vertexPositions[faceVertex] + VertexNoise.GetNoiseVectorFromRepeatingTexture(vertexPositions[faceVertex]), new Color(0, 0, 0, 255), new Color(0, 0, 0, 255), new Vector2(12.5f / 16.0f, 0.5f / 16.0f), new Vector4(12.0f / 16.0f, 0.0f, 13.0f / 16.0f, 1.0f / 16.0f))); } for (int idx = faceDescriptor.IndexOffset; idx < faceDescriptor.IndexCount + faceDescriptor.IndexOffset; idx++) { ushort offset = Primitive.Indexes[idx]; ushort offset0 = Primitive.Indexes[faceDescriptor.IndexOffset]; Into.AddIndex((short)(indexOffset + offset - offset0)); } } } }
public void InitializeFromChunk(VoxelChunk chunk) { if (chunk == null) { return; } BoxPrimitive bedrockModel = VoxelLibrary.GetPrimitive("Bedrock"); var sliceStack = new List <RawPrimitive>(); var cache = new Cache(); for (var y = 0; y < chunk.Manager.ChunkData.MaxViewingLevel; ++y) { RawPrimitive sliceGeometry = null; lock (chunk.Data.SliceCache) { var cachedSlice = chunk.Data.SliceCache[y]; if (chunk.Data.VoxelsPresentInSlice[y] == 0) { cache.Clear(); if (cachedSlice != null) { chunk.Data.SliceCache[y] = null; } continue; } if (cachedSlice != null) { cache.Clear(); sliceStack.Add(cachedSlice); if (GameSettings.Default.GrassMotes) { chunk.RebuildMoteLayerIfNull(y); } continue; } sliceGeometry = new RawPrimitive { Vertices = new ExtendedVertex[128], Indexes = new short[128] }; chunk.Data.SliceCache[y] = sliceGeometry; } if (GameSettings.Default.CalculateRamps) { UpdateCornerRamps(chunk, y); UpdateNeighborEdgeRamps(chunk, y); } if (GameSettings.Default.GrassMotes) { chunk.RebuildMoteLayer(y); } BuildSliceGeometry(chunk, bedrockModel, cache, y, sliceGeometry); sliceStack.Add(sliceGeometry); } var combinedGeometry = RawPrimitive.Concat(sliceStack); Vertices = combinedGeometry.Vertices; VertexCount = combinedGeometry.VertexCount; Indexes = combinedGeometry.Indexes.Select(s => (ushort)s).ToArray(); IndexCount = combinedGeometry.IndexCount; chunk.PrimitiveMutex.WaitOne(); chunk.NewPrimitive = this; chunk.NewPrimitiveReceived = true; chunk.PrimitiveMutex.ReleaseMutex(); }
public void InitializeFromChunk(VoxelChunk chunk, DesignationSet DesignationSet, WorldManager World) { DebugHelper.AssertNotNull(chunk); DebugHelper.AssertNotNull(DesignationSet); DebugHelper.AssertNotNull(World); BoxPrimitive bedrockModel = Library.GetVoxelPrimitive("Bedrock"); var sliceStack = new List <RawPrimitive>(); var cache = new Cache(); int maxViewingLevel = World.Renderer.PersistentSettings.MaxViewingLevel; for (var localY = 0; localY < maxViewingLevel - chunk.Origin.Y && localY < VoxelConstants.ChunkSizeY; ++localY) // Todo: Only iterate inside the chunk. { RawPrimitive sliceGeometry = null; lock (chunk.Data.SliceCache) { var cachedSlice = chunk.Data.SliceCache[localY]; if (cachedSlice != null) { cache.Clear(); sliceStack.Add(cachedSlice); if (GameSettings.Default.GrassMotes) { chunk.RebuildMoteLayerIfNull(localY); } continue; } sliceGeometry = new RawPrimitive { Vertices = null, Indexes = null }; chunk.Data.SliceCache[localY] = sliceGeometry; } if (GameSettings.Default.CalculateRamps) { UpdateCornerRamps(World.ChunkManager, chunk, localY); UpdateNeighborEdgeRamps(World.ChunkManager, chunk, localY); } if (GameSettings.Default.GrassMotes) { chunk.RebuildMoteLayer(localY); } DebugHelper.AssertNotNull(sliceGeometry); BuildSliceGeometry(chunk, bedrockModel, cache, localY, sliceGeometry, DesignationSet, World); sliceStack.Add(sliceGeometry); } var combinedGeometry = RawPrimitive.Concat(sliceStack); Vertices = combinedGeometry.Vertices; VertexCount = combinedGeometry.VertexCount; Indexes = combinedGeometry.Indexes.Select(s => (ushort)s).ToArray(); IndexCount = combinedGeometry.IndexCount; }
public static RawPrimitive LoadObject(string[] File) { var parser = new ObjLineGrammar(); var verticies = new List <Vector3>(); var texCoords = new List <Vector2>(); var faces = new List <Face>(); foreach (var line in File) { if (String.IsNullOrEmpty(line)) { continue; } if (line.StartsWith("#")) { continue; } var result = parser.ParseString(line); if (result.ResultType != Ancora.ResultType.Success) { continue; } switch (result.Node.Children[0].Value.ToString()) { case "v": verticies.Add(new Vector3((float)result.Node.Children[1].Value, (float)result.Node.Children[2].Value, (float)result.Node.Children[3].Value)); break; case "vt": texCoords.Add(new Vector2((float)result.Node.Children[1].Value, 1.0f - (float)result.Node.Children[2].Value)); break; case "f": { var f = new Face(); for (var i = 1; i < result.Node.Children.Count; i += 3) { f.Add(new Corner { Vertex = (int)(float)result.Node.Children[i].Value, TexCoord = (int)(float)result.Node.Children[i + 2].Value }); } faces.Add(f); } break; default: break; } } var r = new RawPrimitive(); foreach (var face in faces) { for (var i = 2; i < face.Count; ++i) { r.AddTriangle( new ExtendedVertex(verticies[face[0].Vertex - 1], Color.White, Color.White, texCoords[face[0].TexCoord - 1], new Vector4(0, 0, 1, 1)), new ExtendedVertex(verticies[face[i - 1].Vertex - 1], Color.White, Color.White, texCoords[face[i - 1].TexCoord - 1], new Vector4(0, 0, 1, 1)), new ExtendedVertex(verticies[face[i].Vertex - 1], Color.White, Color.White, texCoords[face[i].TexCoord - 1], new Vector4(0, 0, 1, 1))); } } return(r); }