bool GetBlocks(Vector3I *coords, ref int posCount, float x, float z, int posY, ShadowData *data, ref int index) { int blockX = Utils.Floor(x), blockZ = Utils.Floor(z); Vector3I p = new Vector3I(blockX, 0, blockZ); BlockInfo info = game.BlockInfo; Vector3 Position = entity.Position; index = 0; // Check we have not processed this particular block already. if (Position.Y < 0) { return(false); } for (int i = 0; i < 4; i++) { if (coords[i] == p) { return(false); } data[i] = new ShadowData(); } coords[posCount] = p; posCount++; while (posY >= 0 && index < 4) { BlockID block = GetShadowBlock(blockX, posY, blockZ); posY--; byte draw = info.Draw[block]; if (draw == DrawType.Gas || draw == DrawType.Sprite || info.IsLiquid(block)) { continue; } float blockY = posY + 1 + info.MaxBB[block].Y; if (blockY >= Position.Y + 0.01f) { continue; } data[index].Block = block; data[index].Y = blockY; CalcAlpha(Position.Y, ref data[index]); index++; // Check if the casted shadow will continue on further down. if (info.MinBB[block].X == 0 && info.MaxBB[block].X == 1 && info.MinBB[block].Z == 0 && info.MaxBB[block].Z == 1) { return(true); } } if (index < 4) { data[index].Block = game.World.Env.EdgeBlock; data[index].Y = 0; CalcAlpha(Position.Y, ref data[index]); index++; } return(true); }
static bool GetBlocks(int x, int y, int z, ShadowData *data, ref int index) { float posY = entity.Position.Y; index = 0; bool outside = x < 0 || z < 0 || x >= game.World.Width || z >= game.World.Length; while (y >= 0 && index < 4) { BlockID block; if (!outside) { block = game.World.GetBlock(x, y, z); } else if (y == game.World.Env.EdgeHeight - 1) { block = BlockInfo.Draw[game.World.Env.EdgeBlock] == DrawType.Gas ? Block.Air : Block.Bedrock; } else if (y == game.World.Env.SidesHeight - 1) { block = BlockInfo.Draw[game.World.Env.SidesBlock] == DrawType.Gas ? Block.Air : Block.Bedrock; } else { block = Block.Air; } y--; byte draw = BlockInfo.Draw[block]; if (draw == DrawType.Gas || draw == DrawType.Sprite || BlockInfo.IsLiquid[block]) { continue; } float blockY = (y + 1) + BlockInfo.MaxBB[block].Y; if (blockY >= posY + 0.01f) { continue; } data[index].Block = block; data[index].Y = blockY; CalcAlpha(posY, ref data[index]); index++; // Check if the casted shadow will continue on further down. if (BlockInfo.MinBB[block].X == 0 && BlockInfo.MaxBB[block].X == 1 && BlockInfo.MinBB[block].Z == 0 && BlockInfo.MaxBB[block].Z == 1) { return(true); } } if (index < 4) { data[index].Block = game.World.Env.EdgeBlock; data[index].Y = 0; CalcAlpha(posY, ref data[index]); index++; } return(true); }
public static unsafe FakeStruct LoadFromObject(Component com, DataBuffer buffer) { var img = com as Shadow; if (img == null) { return(null); } FakeStruct fake = new FakeStruct(buffer, ShadowData.ElementSize); ShadowData *data = (ShadowData *)fake.ip; data->effectColor = img.effectColor; data->effectDistance = img.effectDistance; data->useGraphicAlpha = img.useGraphicAlpha; return(fake); }
static void DrawCircle(VertexP3fT2fC4b[] verts, ref int index, ShadowData *data, int dataCount, float x, float z) { Vector3 min = BlockInfo.MinBB[data[0].Block], max = BlockInfo.MaxBB[data[0].Block]; DrawCoords(verts, ref index, data[0], x + min.X, z + min.Z, x + max.X, z + max.Z); for (int i = 1; i < dataCount; i++) { Vector3 nMin = BlockInfo.MinBB[data[i].Block], nMax = BlockInfo.MaxBB[data[i].Block]; DrawCoords(verts, ref index, data[i], x + min.X, z + nMin.Z, x + max.X, z + min.Z); DrawCoords(verts, ref index, data[i], x + min.X, z + max.Z, x + max.X, z + nMax.Z); DrawCoords(verts, ref index, data[i], x + nMin.X, z + nMin.Z, x + min.X, z + nMax.Z); DrawCoords(verts, ref index, data[i], x + max.X, z + nMin.Z, x + nMax.X, z + nMax.Z); min = nMin; max = nMax; } }
void DrawCircle(VertexPos3fTex2fCol4b[] verts, ref int index, ShadowData *data, int dataCount, float x, float z) { x = Utils.Floor(x); z = Utils.Floor(z); BlockInfo info = game.BlockInfo; Vector3 min = info.MinBB[data[0].Block], max = info.MaxBB[data[0].Block]; DrawCoords(verts, ref index, data[0], x + min.X, z + min.Z, x + max.X, z + max.Z); for (int i = 1; i < dataCount; i++) { Vector3 nMin = info.MinBB[data[i].Block], nMax = info.MaxBB[data[i].Block]; DrawCoords(verts, ref index, data[i], x + min.X, z + nMin.Z, x + max.X, z + min.Z); DrawCoords(verts, ref index, data[i], x + min.X, z + max.Z, x + max.X, z + nMax.Z); DrawCoords(verts, ref index, data[i], x + nMin.X, z + nMin.Z, x + min.X, z + nMax.Z); DrawCoords(verts, ref index, data[i], x + max.X, z + nMin.Z, x + nMax.X, z + nMax.Z); min = nMin; max = nMax; } }
internal void Draw() { EntityShadow mode = game.Entities.ShadowMode; Vector3 Position = entity.Position; float posX = Position.X, posZ = Position.Z; int posY = Math.Min((int)Position.Y, game.World.Height - 1); int index = 0, vb = 0; radius = 7f * Math.Min(entity.ModelScale, 1) * entity.Model.ShadowScale; VertexP3fT2fC4b[] verts = null; int posCount = 0, dataCount = 0; Vector3I * coords = stackalloc Vector3I[4]; ShadowData *data = stackalloc ShadowData[4]; for (int i = 0; i < 4; i++) { coords[i] = new Vector3I(int.MinValue); data[i] = new ShadowData(); } if (mode == EntityShadow.SnapToBlock) { vb = game.Graphics.texVb; verts = game.Graphics.texVerts; if (!GetBlocks(coords, ref posCount, posX, posZ, posY, data, ref dataCount)) { return; } float x1 = Utils.Floor(posX), z1 = Utils.Floor(posZ); DraqSquareShadow(verts, ref index, data[0].Y, 220, x1, z1); } else { vb = game.ModelCache.vb; verts = game.ModelCache.vertices; float x = posX - radius / 16f, z = posZ - radius / 16f; if (GetBlocks(coords, ref posCount, x, z, posY, data, ref dataCount) && data[0].A > 0) { DrawCircle(verts, ref index, data, dataCount, x, z); } x = Math.Max(posX - radius / 16f, Utils.Floor(posX + radius / 16f)); if (GetBlocks(coords, ref posCount, x, z, posY, data, ref dataCount) && data[0].A > 0) { DrawCircle(verts, ref index, data, dataCount, x, z); } z = Math.Max(posZ - radius / 16f, Utils.Floor(posZ + radius / 16f)); if (GetBlocks(coords, ref posCount, x, z, posY, data, ref dataCount) && data[0].A > 0) { DrawCircle(verts, ref index, data, dataCount, x, z); } x = posX - radius / 16f; if (GetBlocks(coords, ref posCount, x, z, posY, data, ref dataCount) && data[0].A > 0) { DrawCircle(verts, ref index, data, dataCount, x, z); } } if (index == 0) { return; } CheckShadowTexture(game.Graphics); if (!boundShadowTex) { game.Graphics.BindTexture(shadowTex); boundShadowTex = true; } game.Graphics.UpdateDynamicIndexedVb(DrawMode.Triangles, vb, verts, index); }
internal static void Draw(Game game, Entity entity) { ShadowComponent.game = game; ShadowComponent.entity = entity; Vector3 Position = entity.Position; if (Position.Y < 0) { return; } float posX = Position.X, posZ = Position.Z; int posY = Math.Min((int)Position.Y, game.World.MaxY); int index = 0, vb = 0; float baseRadius = 7f * Math.Min(entity.ModelScale.Y, 1) * entity.Model.ShadowScale; radius = baseRadius / 16.0f; uvScale = 16.0f / (baseRadius * 2); VertexP3fT2fC4b[] verts = null; int dataCount = 0; ShadowData *data = stackalloc ShadowData[4]; if (game.Entities.ShadowMode == EntityShadow.SnapToBlock) { vb = game.Graphics.texVb; verts = game.Graphics.texVerts; int x1 = Utils.Floor(posX), z1 = Utils.Floor(posZ); if (!GetBlocks(x1, posY, z1, data, ref dataCount)) { return; } DrawSquareShadow(verts, ref index, data[0].Y, x1, z1); } else { vb = game.ModelCache.vb; verts = game.ModelCache.vertices; int x1 = Utils.Floor(posX - radius), z1 = Utils.Floor(posZ - radius); int x2 = Utils.Floor(posX + radius), z2 = Utils.Floor(posZ + radius); if (GetBlocks(x1, posY, z1, data, ref dataCount) && data[0].A > 0) { DrawCircle(verts, ref index, data, dataCount, x1, z1); } if (x1 != x2 && GetBlocks(x2, posY, z1, data, ref dataCount) && data[0].A > 0) { DrawCircle(verts, ref index, data, dataCount, x2, z1); } if (z1 != z2 && GetBlocks(x1, posY, z2, data, ref dataCount) && data[0].A > 0) { DrawCircle(verts, ref index, data, dataCount, x1, z2); } if (x1 != x2 && z1 != z2 && GetBlocks(x2, posY, z2, data, ref dataCount) && data[0].A > 0) { DrawCircle(verts, ref index, data, dataCount, x2, z2); } } if (index == 0) { return; } CheckShadowTexture(game.Graphics); if (!boundShadowTex) { game.Graphics.BindTexture(shadowTex); boundShadowTex = true; } game.Graphics.UpdateDynamicVb_IndexedTris(vb, verts, index); }