public void Dispose() { ChunkUpdater.Dispose(); Atlas2D.Dispose(); Atlas1D.Dispose(); ModelCache.Dispose(); Entities.Dispose(); WorldEvents.OnNewMap -= OnNewMapCore; WorldEvents.OnNewMapLoaded -= OnNewMapLoadedCore; Events.TextureChanged -= TextureChangedCore; for (int i = 0; i < Components.Count; i++) { Components[i].Dispose(); } Drawer2D.DisposeInstance(); Graphics.Dispose(); // TODO: is this needed //window.Dispose(); if (!Options.HasChanged()) { return; } Options.Load(); Options.Save(); }
void SpriteXQuad(BlockID block, bool firstPart) { int texLoc = BlockInfo.GetTextureLoc(block, Side.Right); TextureRec rec = Atlas1D.GetTexRec(texLoc, 1, out texIndex); if (lastTexIndex != texIndex) { Flush(); } VertexP3fT2fC4b v = default(VertexP3fT2fC4b); v.Col = colNormal; if (BlockInfo.Tinted[block]) { v.Col *= BlockInfo.FogCol[block]; } float z1 = firstPart ? 0.5f : -0.1f, z2 = firstPart ? 1.1f : 0.5f; rec.U1 = firstPart ? 0.0f : 0.5f; rec.U2 = (firstPart ? 0.5f : 1.0f) * (15.99f / 16f); float minY = scale * (1 - 0 * 2) + pos.Y, maxY = scale * (1 - 1.1f * 2) + pos.Y; float minZ = scale * (1 - z1 * 2) + pos.Z, maxZ = scale * (1 - z2 * 2) + pos.Z; v.X = pos.X; v.Y = minY; v.Z = minZ; v.U = rec.U2; v.V = rec.V2; vertices[index++] = v; v.Y = maxY; v.V = rec.V1; vertices[index++] = v; v.Z = maxZ; v.U = rec.U1; vertices[index++] = v; v.Y = minY; v.V = rec.V2; vertices[index++] = v; }
public bool ChangeTerrainAtlas(Bitmap atlas) { if (!ValidateBitmap("terrain.png", atlas)) { return(false); } if (atlas.Height < atlas.Width) { Chat.Add("&cUnable to use terrain.png from the texture pack."); Chat.Add("&c Its height is less than its width."); return(false); } if (Graphics.LostContext) { return(false); } Atlas1D.Dispose(); Atlas2D.Dispose(); Atlas2D.UpdateState(atlas); Atlas1D.UpdateState(); Events.RaiseTerrainAtlasChanged(); return(true); }
void AddVertices(BlockID block, int face) { int i = Atlas1D.Get1DIndex(BlockInfo.GetTextureLoc(block, face)); DrawInfo part = BlockInfo.Draw[block] == DrawType.Translucent ? translucentParts[i] : normalParts[i]; part.vCount[face] += 4; }
void DrawBackground() { VertexP3fT2fC4b[] vertices = game.ModelCache.vertices; int index = 0, atlasIndex = 0; int drawnY = 0, height = game.Height; PackedCol col = new PackedCol(64, 64, 64); int texLoc = BlockInfo.GetTextureLoc(Block.Dirt, Side.Top); Texture tex = new Texture(0, 0, 0, game.Width, 64, Atlas1D.GetTexRec(texLoc, 1, out atlasIndex)); tex.U2 = (float)game.Width / 64; bool bound = false; while (drawnY < height) { tex.Y1 = drawnY; IGraphicsApi.Make2DQuad(ref tex, col, vertices, ref index); if (index >= vertices.Length) { DrawBackgroundVertices(ref index, atlasIndex, ref bound); } drawnY += 64; } DrawBackgroundVertices(ref index, atlasIndex, ref bound); }
void AddSpriteVertices(BlockID block) { int i = Atlas1D.Get1DIndex(BlockInfo.GetTextureLoc(block, Side.Left)); DrawInfo part = normalParts[i]; part.spriteCount += 4 * 4; }
void SpriteXQuad(bool firstPart, bool mirror, BlockID block, ref int lastTexIndex, ModelCache cache, float dispX, float dispY, float dispZ, float scale) { int texLoc = BlockInfo.GetTextureLoc(block, Side.Right); TextureRec rec = Atlas1D.GetTexRec(texLoc, 1, out texIndex); if (lastTexIndex != texIndex) { if (lastTexIndex != -1) { game.Graphics.BindTexture(Atlas1D.TexIds[lastTexIndex]); UpdateVB(); } lastTexIndex = texIndex; index = 0; } PackedCol col = cols[0]; if (BlockInfo.Tinted[block]) { col *= BlockInfo.FogCol[block]; } float x1 = 0, x2 = 0, z1 = 0, z2 = 0; if (firstPart) { if (mirror) { rec.U2 = 0.5f; x2 = -5.5f / 16; z2 = 5.5f / 16; } else { rec.U1 = 0.5f; x1 = -5.5f / 16; z1 = 5.5f / 16; } } else { if (mirror) { rec.U1 = 0.5f; x1 = 5.5f / 16; z1 = -5.5f / 16; } else { rec.U2 = 0.5f; x2 = 5.5f / 16; z2 = -5.5f / 16; } } cache.vertices[index++] = new VertexP3fT2fC4b(x1 * scale + dispX, dispY, z1 * scale + dispZ, rec.U2, rec.V2, col); cache.vertices[index++] = new VertexP3fT2fC4b(x1 * scale + dispX, scale + dispY, z1 * scale + dispZ, rec.U2, rec.V1, col); cache.vertices[index++] = new VertexP3fT2fC4b(x2 * scale + dispX, scale + dispY, z2 * scale + dispZ, rec.U1, rec.V1, col); cache.vertices[index++] = new VertexP3fT2fC4b(x2 * scale + dispX, dispY, z2 * scale + dispZ, rec.U1, rec.V2, col); }
void SpriteZQuad(bool firstPart, bool mirror, BlockID block, ref int lastTexIndex, ModelCache cache, float dispX, float dispY, float dispZ, float scale) { int texLoc = BlockInfo.GetTextureLoc(block, Side.Back); TextureRec rec = Atlas1D.GetTexRec(texLoc, 1, out texIndex); if (lastTexIndex != texIndex) { if (lastTexIndex != -1) { game.Graphics.BindTexture(Atlas1D.TexIds[lastTexIndex]); UpdateVB(); } lastTexIndex = texIndex; index = 0; } PackedCol col = cols[0]; if (BlockInfo.Tinted[block]) { col *= BlockInfo.FogCol[block]; } float p1 = 0, p2 = 0; if (firstPart) { // Need to break into two quads for when drawing a sprite model in hand. if (mirror) { rec.U1 = 0.5f; p1 = -5.5f / 16; } else { rec.U2 = 0.5f; p2 = -5.5f / 16; } } else { if (mirror) { rec.U2 = 0.5f; p2 = 5.5f / 16; } else { rec.U1 = 0.5f; p1 = 5.5f / 16; } } cache.vertices[index++] = new VertexP3fT2fC4b(p1 * scale + dispX, dispY, p1 * scale + dispZ, rec.U2, rec.V2, col); cache.vertices[index++] = new VertexP3fT2fC4b(p1 * scale + dispX, scale + dispY, p1 * scale + dispZ, rec.U2, rec.V1, col); cache.vertices[index++] = new VertexP3fT2fC4b(p2 * scale + dispX, scale + dispY, p2 * scale + dispZ, rec.U1, rec.V1, col); cache.vertices[index++] = new VertexP3fT2fC4b(p2 * scale + dispX, dispY, p2 * scale + dispZ, rec.U1, rec.V2, col); }
void TerrainAtlasChanged(object sender, EventArgs e) { if (renderer._1DUsed != -1) { bool refreshRequired = elementsPerBitmap != Atlas1D.TilesPerAtlas; if (refreshRequired) { Refresh(); } } renderer._1DUsed = Atlas1D.UsedAtlasesCount(); elementsPerBitmap = Atlas1D.TilesPerAtlas; ResetUsedFlags(); }
void SpriteXQuad(bool firstPart, bool mirror) { int texLoc = BlockInfo.GetTextureLoc(block, Side.Right); TextureRec rec = Atlas1D.GetTexRec(texLoc, 1, out texIndex); if (lastTexIndex != texIndex) { Flush(); } PackedCol col = cols[0]; if (BlockInfo.Tinted[block]) { col *= BlockInfo.FogCol[block]; } float x1 = 0, x2 = 0, z1 = 0, z2 = 0; if (firstPart) { if (mirror) { rec.U2 = 0.5f; x2 = -5.5f / 16; z2 = 5.5f / 16; } else { rec.U1 = 0.5f; x1 = -5.5f / 16; z1 = 5.5f / 16; } } else { if (mirror) { rec.U1 = 0.5f; x1 = 5.5f / 16; z1 = -5.5f / 16; } else { rec.U2 = 0.5f; x2 = 5.5f / 16; z2 = -5.5f / 16; } } cache.vertices[index++] = new VertexP3fT2fC4b(x1, 0, z1, rec.U2, rec.V2, col); cache.vertices[index++] = new VertexP3fT2fC4b(x1, 1, z1, rec.U2, rec.V1, col); cache.vertices[index++] = new VertexP3fT2fC4b(x2, 1, z2, rec.U1, rec.V1, col); cache.vertices[index++] = new VertexP3fT2fC4b(x2, 0, z2, rec.U1, rec.V2, col); }
void SpriteZQuad(bool firstPart, bool mirror) { int texLoc = BlockInfo.GetTextureLoc(block, Side.Back); TextureRec rec = Atlas1D.GetTexRec(texLoc, 1, out texIndex); if (lastTexIndex != texIndex) { Flush(); } PackedCol col = cols[0]; if (BlockInfo.Tinted[block]) { col *= BlockInfo.FogCol[block]; } float p1 = 0, p2 = 0; if (firstPart) // Need to break into two quads for when drawing a sprite model in hand. { if (mirror) { rec.U1 = 0.5f; p1 = -5.5f / 16; } else { rec.U2 = 0.5f; p2 = -5.5f / 16; } } else { if (mirror) { rec.U2 = 0.5f; p2 = 5.5f / 16; } else { rec.U1 = 0.5f; p1 = 5.5f / 16; } } cache.vertices[index++] = new VertexP3fT2fC4b(p1, 0, p1, rec.U2, rec.V2, col); cache.vertices[index++] = new VertexP3fT2fC4b(p1, 1, p1, rec.U2, rec.V1, col); cache.vertices[index++] = new VertexP3fT2fC4b(p2, 1, p2, rec.U1, rec.V1, col); cache.vertices[index++] = new VertexP3fT2fC4b(p2, 0, p2, rec.U1, rec.V2, col); }
void RenderTerrain() { for (int i = 0; i < Atlas2D.TilesPerRow * Atlas2D.TilesPerRow;) { int index = 0, texIdx = 0, end = i + Atlas1D.TilesPerAtlas; for (; i < end; i++) { TextureRec rec = Atlas1D.GetTexRec(i + baseTexLoc, 1, out texIdx); int x = i % Atlas2D.TilesPerRow, y = i / Atlas2D.TilesPerRow; Texture tex = new Texture(0, xOffset + x * tileSize, yOffset + y * tileSize, tileSize, tileSize, rec); IGraphicsApi.Make2DQuad(ref tex, PackedCol.White, vertices, ref index); } game.Graphics.BindTexture(Atlas1D.TexIds[texIdx]); game.Graphics.UpdateDynamicVb_IndexedTris(dynamicVb, vertices, index); } }
unsafe void RenderTerrainParticles(IGraphicsApi gfx, TerrainParticle[] particles, int elems, double delta, float t) { int count = elems * 4; if (count > vertices.Length) { vertices = new VertexP3fT2fC4b[count]; } Update1DCounts(particles, elems); for (int i = 0; i < elems; i++) { int index = Atlas1D.Get1DIndex(particles[i].texLoc); particles[i].Render(game, t, vertices, ref terrain1DIndices[index]); } int drawCount = Math.Min(count, maxParticles * 4); if (drawCount == 0) { return; fixed(VertexP3fT2fC4b *ptr = vertices) { gfx.SetDynamicVbData(vb, (IntPtr)ptr, drawCount); int offset = 0; for (int i = 0; i < Atlas1D.AtlasesCount; i++) { int partCount = terrain1DCount[i]; if (partCount == 0) { continue; } gfx.BindTexture(Atlas1D.TexIds[i]); gfx.DrawVb_IndexedTris(partCount, offset); offset += partCount; } } } void Update1DCounts(TerrainParticle[] particles, int elems) { for (int i = 0; i < Atlas1D.MaxAtlases; i++) { terrain1DCount[i] = 0; terrain1DIndices[i] = 0; } for (int i = 0; i < elems; i++) { int index = Atlas1D.Get1DIndex(particles[i].texLoc); terrain1DCount[index] += 4; } for (int i = 1; i < Atlas1D.AtlasesCount; i++) { terrain1DIndices[i] = terrain1DIndices[i - 1] + terrain1DCount[i - 1]; } } void RenderRainParticles(IGraphicsApi gfx, RainParticle[] particles, int elems, double delta, float t) { int count = elems * 4; if (count > vertices.Length) { vertices = new VertexP3fT2fC4b[count]; } int index = 0; for (int i = 0; i < elems; i++) { particles[i].Render(game, t, vertices, ref index); } int drawCount = Math.Min(count, maxParticles * 4); if (drawCount == 0) { return; } gfx.BindTexture(ParticlesTexId); gfx.UpdateDynamicVb_IndexedTris(vb, vertices, drawCount); }
void BreakBlockEffect(Vector3I coords, BlockID old, BlockID now) { if (now != Block.Air || BlockInfo.Draw[old] == DrawType.Gas) { return; } Vector3 worldPos = new Vector3(coords.X, coords.Y, coords.Z); int texLoc = BlockInfo.GetTextureLoc(old, Side.Left), texIndex = 0; TextureRec baseRec = Atlas1D.GetTexRec(texLoc, 1, out texIndex); float uScale = (1 / 16f), vScale = (1 / 16f) * Atlas1D.invTileSize; Vector3 minBB = BlockInfo.MinBB[old]; Vector3 maxBB = BlockInfo.MaxBB[old]; int minU = Math.Min((int)(minBB.X * 16), (int)(minBB.Z * 16)); int maxU = Math.Min((int)(maxBB.X * 16), (int)(maxBB.Z * 16)); int minV = (int)(16 - maxBB.Y * 16), maxV = (int)(16 - minBB.Y * 16); int maxUsedU = maxU, maxUsedV = maxV; // This way we can avoid creating particles which outside the bounds and need to be clamped if (minU < 12 && maxU > 12) { maxUsedU = 12; } if (minV < 12 && maxV > 12) { maxUsedV = 12; } const int gridSize = 4; // gridOffset gives the centre of the cell on a grid const float cellCentre = (1f / gridSize) * 0.5f; for (int x = 0; x < gridSize; x++) { for (int y = 0; y < gridSize; y++) { for (int z = 0; z < gridSize; z++) { float cellX = (float)x / gridSize, cellY = (float)y / gridSize, cellZ = (float)z / gridSize; Vector3 cell = new Vector3(cellCentre + cellX, cellCentre / 2 + cellY, cellCentre + cellZ); if (cell.X < minBB.X || cell.X > maxBB.X || cell.Y < minBB.Y || cell.Y > maxBB.Y || cell.Z < minBB.Z || cell.Z > maxBB.Z) { continue; } double velX = cellCentre + (cellX - 0.5f) + (rnd.NextDouble() * 0.4 - 0.2); // centre random offset around [-0.2, 0.2] double velY = cellCentre + (cellY - 0.0f) + (rnd.NextDouble() * 0.4 - 0.2); double velZ = cellCentre + (cellZ - 0.5f) + (rnd.NextDouble() * 0.4 - 0.2); Vector3 velocity = new Vector3((float)velX, (float)velY, (float)velZ); TextureRec rec = baseRec; rec.U1 = baseRec.U1 + rnd.Next(minU, maxUsedU) * uScale; rec.V1 = baseRec.V1 + rnd.Next(minV, maxUsedV) * vScale; rec.U2 = Math.Min(baseRec.U1 + maxU * uScale, rec.U1 + 4 * uScale) - 0.01f * uScale; rec.V2 = Math.Min(baseRec.V1 + maxV * vScale, rec.V1 + 4 * vScale) - 0.01f * vScale; double life = 0.3 + rnd.NextDouble() * 1.2; TerrainParticle p = GetTerrainParticle(); p.ResetState(worldPos + cell, velocity, life); p.rec = rec; p.texLoc = (TexLoc)texLoc; p.block = old; int type = rnd.Next(0, 30); p.Size = (byte)(type >= 28 ? 12 : (type >= 25 ? 10 : 8)); } } } }
void BlockDefinitionChanged(object sender, EventArgs e) { renderer._1DUsed = Atlas1D.UsedAtlasesCount(); ResetUsedFlags(); Refresh(); }
void BlockDefinitionChanged() { renderer._1DUsed = Atlas1D.UsedAtlasesCount(); ResetUsedFlags(); Refresh(); }