void DrawBackground() { VertexP3fT2fC4b[] vertices = game.ModelCache.vertices; int index = 0, atlasIndex = 0; int drawnY = 0, height = game.Height; int col = new FastColour(64, 64, 64).Pack(); int texLoc = BlockInfo.GetTextureLoc(Block.Dirt, Side.Top); Texture tex = new Texture(0, 0, 0, game.Width, 64, TerrainAtlas1D.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); }
public void DrawBatch( byte block, float size, float x, float y ) { BlockInfo info = game.BlockInfo; atlas = game.TerrainAtlas1D; minBB = info.MinBB[block]; maxBB = info.MaxBB[block]; fullBright = info.FullBright[block]; if( info.IsSprite[block] ) { minBB = Vector3.Zero; maxBB = Vector3.One; } if( info.IsAir[block] ) return; // isometric coords size: cosY * -scale - sinY * scale // we need to divide by (2 * cosY), as the calling function expects size to be in pixels. scale = size / (2 * cosY); // screen to isometric coords (cos(-x) = cos(x), sin(-x) = -sin(x)) pos.X = x; pos.Y = y; pos.Z = 0; Utils.RotateX( ref pos.Y, ref pos.Z, cosX, -sinX ); Utils.RotateY( ref pos.X, ref pos.Z, cosY, -sinY ); if( info.IsSprite[block] ) { SpriteXQuad( block, Side.Right, false ); SpriteZQuad( block, Side.Back, false ); SpriteZQuad( block, Side.Back, true ); SpriteXQuad( block, Side.Right, true ); } else { XQuad( block, maxBB.X, Side.Left ); ZQuad( block, minBB.Z, Side.Back ); YQuad( block, maxBB.Y, Side.Top ); } }
public virtual void RenderHotbarItems() { Model.ModelCache cache = game.ModelCache; for (int i = 0; i < Inventory.BlocksPerRow; i++) { BlockID block = game.Inventory[i]; if (BlockInfo.Draw[block] != DrawType.Sprite) { continue; } int x = (int)(X + barXOffset + (elemSize + borderSize) * i + elemSize / 2); int y = (int)(Y + (Height - barHeight)); int lower = (int)(3 * game.GuiHotbarScale); int side = (int)(8 * game.GuiHotbarScale); int outer = (int)(16 * game.GuiHotbarScale); y += lower; x -= side; if (BlockInfo.Draw[block] == DrawType.Sprite) { int texLoc = BlockInfo.GetTextureLoc(block, Side.Right); TextureRec rec = TerrainAtlas1D.GetTexRec(texLoc, 1, out texIndex); Texture tex = new Texture(0, (int)x, (int)y, outer, outer, rec); IGraphicsApi.Make2DQuad(ref tex, FastColour.WhitePacked, cache.vertices, ref index); game.Graphics.BindTexture(TerrainAtlas1D.TexIds[texIndex]); game.Graphics.UpdateDynamicVb_IndexedTris(cache.vb, cache.vertices, index); } } index = 0; texIndex = 0; }
protected override void DrawModel(Player p) { // TODO: using 'is' is ugly, but means we can avoid creating // a string every single time held block changes. if (p is FakePlayer) { Player realP = game.LocalPlayer; col = game.World.IsLit(realP.EyePosition) ? game.World.Env.Sunlight : game.World.Env.Shadowlight; // Adjust pitch so angle when looking straight down is 0. float adjPitch = realP.PitchDegrees - 90; if (adjPitch < 0) { adjPitch += 360; } // Adjust colour so held block is brighter when looking straght up float t = Math.Abs(adjPitch - 180) / 180; float colScale = Utils.Lerp(0.9f, 0.7f, t); col = FastColour.Scale(col, colScale); block = ((FakePlayer)p).Block; } else { block = Utils.FastByte(p.ModelName); } CalcState(block); colPacked = col.Pack(); if (game.BlockInfo.IsAir[block]) { return; } lastTexId = -1; atlas = game.TerrainAtlas1D; bool sprite = game.BlockInfo.IsSprite[block]; DrawParts(sprite); if (index == 0) { return; } IGraphicsApi api = game.Graphics; api.BindTexture(lastTexId); TransformVertices(); if (sprite) { api.FaceCulling = true; } UpdateVB(); if (sprite) { api.FaceCulling = false; } }
protected override void DrawModel(Player p) { // TODO: using 'is' is ugly, but means we can avoid creating // a string every single time held block changes. if (p is FakePlayer) { Vector3I eyePos = Vector3I.Floor(game.LocalPlayer.EyePosition); FastColour baseCol = game.Map.IsLit(eyePos) ? game.Map.Sunlight : game.Map.Shadowlight; col = FastColour.Scale(baseCol, 0.8f); block = ((FakePlayer)p).Block; } else { block = Byte.Parse(p.ModelName); } CalcState(block); if (game.BlockInfo.IsAir[block]) { return; } lastTexId = -1; atlas = game.TerrainAtlas1D; if (game.BlockInfo.IsSprite[block]) { SpriteXQuad(TileSide.Right, false); SpriteZQuad(TileSide.Back, false); SpriteZQuad(TileSide.Back, true); SpriteXQuad(TileSide.Right, true); } else { YQuad(0, TileSide.Bottom, FastColour.ShadeYBottom); XQuad(maxBB.X - 0.5f, TileSide.Right, true, FastColour.ShadeX); ZQuad(minBB.Z - 0.5f, TileSide.Front, true, FastColour.ShadeZ); ZQuad(maxBB.Z - 0.5f, TileSide.Back, false, FastColour.ShadeZ); YQuad(height, TileSide.Top, 1.0f); XQuad(minBB.X - 0.5f, TileSide.Left, false, FastColour.ShadeX); } if (index == 0) { return; } graphics.BindTexture(lastTexId); TransformVertices(); graphics.UpdateDynamicIndexedVb(DrawMode.Triangles, cache.vb, cache.vertices, index, index * 6 / 4); }
void SpriteXQuad(bool firstPart, bool mirror) { int texLoc = BlockInfo.GetTextureLoc(block, Side.Right); TextureRec rec = TerrainAtlas1D.GetTexRec(texLoc, 1, out texIndex); if (lastTexIndex != texIndex) { Flush(); } int col = cols[0]; if (BlockInfo.Tinted[block]) { col = Utils.Tint(col, BlockInfo.FogColour[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 = TerrainAtlas1D.GetTexRec(texLoc, 1, out texIndex); if (lastTexIndex != texIndex) { Flush(); } int col = cols[0]; if (BlockInfo.Tinted[block]) { col = Utils.Tint(col, BlockInfo.FogColour[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); }
public static void Draw( Game game, byte block, float size, float x, float y ) { info = game.BlockInfo; cache = game.ModelCache; atlas = game.TerrainAtlas1D; minBB = info.MinBB[block]; maxBB = info.MaxBB[block]; fullBright = info.FullBright[block]; if( info.IsSprite[block] ) { minBB = Vector3.Zero; maxBB = Vector3.One; } if( info.IsAir[block] ) return; index = 0; api = game.Graphics; // isometric coords size: cosY * -scale - sinY * scale // we need to divide by (2 * cosY), as the calling function expects size to be in pixels. scale = size / (2 * cosY); // screen to isometric coords (cos(-x) = cos(x), sin(-x) = -sin(x)) pos.X = x; pos.Y = y; pos.Z = 0; Utils.RotateX( ref pos.Y, ref pos.Z, cosX, -sinX ); Utils.RotateY( ref pos.X, ref pos.Z, cosY, -sinY ); if( info.IsSprite[block] ) { SpriteXQuad( block, Side.Right, false ); SpriteZQuad( block, Side.Back, false ); SpriteZQuad( block, Side.Back, true ); SpriteXQuad( block, Side.Right, true ); } else { XQuad( block, Make( maxBB.X ), Side.Left ); ZQuad( block, Make( minBB.Z ), Side.Back ); YQuad( block, Make( maxBB.Y ), Side.Top ); } if( index == 0 ) return; if( atlas.TexIds[texIndex] != lastTexId ) { lastTexId = atlas.TexIds[texIndex]; api.BindTexture( lastTexId ); } for( int i = 0; i < index; i++ ) TransformVertex( ref cache.vertices[i] ); api.UpdateDynamicIndexedVb( DrawMode.Triangles, cache.vb, cache.vertices, index, index * 6 / 4 ); }
void TerrainAtlasChanged(object sender, EventArgs e) { if (renderer._1DUsed == -1) { renderer.normalPartsCount = new int[TerrainAtlas1D.TexIds.Length]; renderer.translucentPartsCount = new int[TerrainAtlas1D.TexIds.Length]; } else { bool refreshRequired = elementsPerBitmap != TerrainAtlas1D.elementsPerBitmap; if (refreshRequired) { Refresh(); } } renderer._1DUsed = TerrainAtlas1D.UsedAtlasesCount(); elementsPerBitmap = TerrainAtlas1D.elementsPerBitmap; ResetUsedFlags(); }
public override void DrawModel(Entity p) { block = p.ModelBlock; RecalcProperties(p); if (BlockInfo.Draw[block] == DrawType.Gas) { return; } if (BlockInfo.FullBright[block]) { for (int i = 0; i < cols.Length; i++) { cols[i] = FastColour.WhitePacked; } } lastTexIndex = -1; atlas = game.TerrainAtlas1D; bool sprite = BlockInfo.Draw[block] == DrawType.Sprite; DrawParts(sprite); if (index == 0) { return; } if (sprite) { game.Graphics.FaceCulling = true; } lastTexIndex = texIndex; Flush(); if (sprite) { game.Graphics.FaceCulling = false; } }
void DrawBackground() { VertexP3fT2fC4b[] vertices = game.ModelCache.vertices; int index = 0, atlasIndex = 0; int drawnY = 0, height = game.Height; FastColour col = new FastColour(64, 64, 64); int texLoc = game.BlockInfo.GetTextureLoc(Block.Dirt, Side.Top); TerrainAtlas1D atlas = game.TerrainAtlas1D; TextureRec tex = atlas.GetTexRec(texLoc, 1, out atlasIndex); tex.U2 = (float)game.Width / 64; bool bound = false; while (drawnY < height) { float x1 = 0, x2 = game.Width; float y1 = drawnY, y2 = drawnY + 64; #if USE_DX // NOTE: see "https://msdn.microsoft.com/en-us/library/windows/desktop/bb219690(v=vs.85).aspx", // i.e. the msdn article called "Directly Mapping Texels to Pixels (Direct3D 9)" for why we have to do this. x1 -= 0.5f; x2 -= 0.5f; y1 -= 0.5f; y2 -= 0.5f; #endif vertices[index++] = new VertexP3fT2fC4b(x1, y1, 0, tex.U1, tex.V1, col); vertices[index++] = new VertexP3fT2fC4b(x2, y1, 0, tex.U2, tex.V1, col); vertices[index++] = new VertexP3fT2fC4b(x2, y2, 0, tex.U2, tex.V2, col); vertices[index++] = new VertexP3fT2fC4b(x1, y2, 0, tex.U1, tex.V2, col); if (index >= vertices.Length) { DrawBackgroundVertices(ref index, atlasIndex, ref bound); } drawnY += 64; } DrawBackgroundVertices(ref index, atlasIndex, ref bound); }
void RenderTerrain() { int elementsPerAtlas = TerrainAtlas1D.elementsPerAtlas1D; for (int i = 0; i < TerrainAtlas2D.TilesPerRow * TerrainAtlas2D.RowsCount;) { int index = 0, texIdx = i / elementsPerAtlas, ignored; for (int j = 0; j < elementsPerAtlas; j++) { TextureRec rec = TerrainAtlas1D.GetTexRec(i + j, 1, out ignored); int x = (i + j) % TerrainAtlas2D.TilesPerRow; int y = (i + j) / TerrainAtlas2D.TilesPerRow; Texture tex = new Texture(0, xOffset + x * tileSize, yOffset + y * tileSize, tileSize, tileSize, rec); IGraphicsApi.Make2DQuad(ref tex, FastColour.WhitePacked, vertices, ref index); } i += elementsPerAtlas; game.Graphics.BindTexture(TerrainAtlas1D.TexIds[texIdx]); game.Graphics.UpdateDynamicVb_IndexedTris(dynamicVb, vertices, index); } }
protected override void OnLoad( EventArgs e ) { #if !USE_DX Graphics = new OpenGLApi(); #else Graphics = new Direct3D9Api( this ); #endif try { Options.Load(); } catch( IOException ) { Utils.LogWarning( "Unable to load options.txt" ); } ViewDistance = Options.GetInt( "viewdist", 16, 8192, 512 ); Keys = new KeyMap(); InputHandler = new InputHandler( this ); Chat = new ChatLog( this ); Drawer2D = new GdiPlusDrawer2D( Graphics ); defaultIb = Graphics.MakeDefaultIb(); ModelCache = new ModelCache( this ); ModelCache.InitCache(); AsyncDownloader = new AsyncDownloader( skinServer ); Graphics.PrintGraphicsInfo(); TerrainAtlas1D = new TerrainAtlas1D( Graphics ); TerrainAtlas = new TerrainAtlas2D( Graphics, Drawer2D ); Animations = new Animations( this ); TexturePackExtractor extractor = new TexturePackExtractor(); extractor.Extract( defaultTexPack, this ); Inventory = new Inventory( this ); BlockInfo = new BlockInfo(); BlockInfo.Init(); BlockInfo.SetDefaultBlockPermissions( Inventory.CanPlace, Inventory.CanDelete ); Map = new Map( this ); LocalPlayer = new LocalPlayer( this ); Players[255] = LocalPlayer; width = Width; height = Height; MapRenderer = new MapRenderer( this ); MapEnvRenderer = new MapEnvRenderer( this ); EnvRenderer = new StandardEnvRenderer( this ); if( IPAddress == null ) { Network = new Singleplayer.SinglePlayerServer( this ); } else { Network = new NetworkProcessor( this ); } Graphics.LostContextFunction = Network.Tick; firstPersonCam = new FirstPersonCamera( this ); thirdPersonCam = new ThirdPersonCamera( this ); Camera = firstPersonCam; CommandManager = new CommandManager(); CommandManager.Init( this ); SelectionManager = new SelectionManager( this ); ParticleManager = new ParticleManager( this ); WeatherRenderer = new WeatherRenderer( this ); WeatherRenderer.Init(); Graphics.SetVSync( this, true ); Graphics.DepthTest = true; Graphics.DepthTestFunc( CompareFunc.LessEqual ); //Graphics.DepthWrite = true; Graphics.AlphaBlendFunc( BlendFunc.SourceAlpha, BlendFunc.InvSourceAlpha ); Graphics.AlphaTestFunc( CompareFunc.Greater, 0.5f ); Title = Utils.AppName; fpsScreen = new FpsScreen( this ); fpsScreen.Init(); Culling = new FrustumCulling(); EnvRenderer.Init(); MapEnvRenderer.Init(); Picking = new PickingRenderer( this ); string connectString = "Connecting to " + IPAddress + ":" + Port + ".."; SetNewScreen( new LoadingMapScreen( this, connectString, "Reticulating splines" ) ); Network.Connect( IPAddress, Port ); }
unsafe void RenderTerrainParticles(IGraphicsApi gfx, TerrainParticle[] particles, int elems, double delta, float t) { int count = elems * 4; if (count > vertices.Length) { vertices = new VertexP3fT2fC4bN1v[count]; } Update1DCounts(particles, elems); for (int i = 0; i < elems; i++) { int index = TerrainAtlas1D.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(VertexP3fT2fC4bN1v *ptr = vertices) { gfx.SetDynamicVbData(vb, (IntPtr)ptr, drawCount); int offset = 0; for (int i = 0; i < terrain1DCount.Length; i++) { int partCount = terrain1DCount[i]; if (partCount == 0) { continue; } gfx.BindTexture(TerrainAtlas1D.TexIds[i]); gfx.DrawVb_IndexedTris(partCount, offset); offset += partCount; } } } void Update1DCounts(TerrainParticle[] particles, int elems) { for (int i = 0; i < terrain1DCount.Length; i++) { terrain1DCount[i] = 0; terrain1DIndices[i] = 0; } for (int i = 0; i < elems; i++) { int index = TerrainAtlas1D.Get1DIndex(particles[i].texLoc); terrain1DCount[index] += 4; } for (int i = 1; i < terrain1DCount.Length; 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 VertexP3fT2fC4bN1v[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 BlockDefinitionChanged(object sender, EventArgs e) { renderer._1DUsed = TerrainAtlas1D.UsedAtlasesCount(); ResetUsedFlags(); Refresh(); }
protected override void OnLoad( EventArgs e ) { #if !USE_DX Graphics = new OpenGLApi(); #else Graphics = new Direct3D9Api( this ); #endif Graphics.MakeGraphicsInfo(); Options.Load(); ViewDistance = Options.GetInt( OptionsKey.ViewDist, 16, 4096, 512 ); InputHandler = new InputHandler( this ); Chat = new ChatLog( this ); Chat.FontSize = Options.GetInt( OptionsKey.FontSize, 6, 30, 12 ); defaultIb = Graphics.MakeDefaultIb(); MouseSensitivity = Options.GetInt( OptionsKey.Sensitivity, 1, 100, 30 ); BlockInfo = new BlockInfo(); BlockInfo.Init(); ChatLines = Options.GetInt( OptionsKey.ChatLines, 1, 30, 12 ); ModelCache = new ModelCache( this ); ModelCache.InitCache(); AsyncDownloader = new AsyncDownloader( skinServer ); Drawer2D = new GdiPlusDrawer2D( Graphics ); Drawer2D.UseBitmappedChat = !Options.GetBool( OptionsKey.ArialChatFont, false ); TerrainAtlas1D = new TerrainAtlas1D( Graphics ); TerrainAtlas = new TerrainAtlas2D( Graphics, Drawer2D ); Animations = new Animations( this ); TexturePackExtractor extractor = new TexturePackExtractor(); extractor.Extract( defaultTexPack, this ); Inventory = new Inventory( this ); BlockInfo.SetDefaultBlockPermissions( Inventory.CanPlace, Inventory.CanDelete ); Map = new Map( this ); LocalPlayer = new LocalPlayer( this ); LocalPlayer.SpeedMultiplier = Options.GetInt( OptionsKey.Speed, 1, 50, 10 ); Players[255] = LocalPlayer; width = Width; height = Height; MapRenderer = new MapRenderer( this ); MapEnvRenderer = new MapEnvRenderer( this ); EnvRenderer = new StandardEnvRenderer( this ); if( IPAddress == null ) { Network = new Singleplayer.SinglePlayerServer( this ); } else { Network = new NetworkProcessor( this ); } Graphics.LostContextFunction = Network.Tick; firstPersonCam = new FirstPersonCamera( this ); thirdPersonCam = new ThirdPersonCamera( this ); forwardThirdPersonCam = new ForwardThirdPersonCamera( this ); Camera = firstPersonCam; CommandManager = new CommandManager(); CommandManager.Init( this ); SelectionManager = new SelectionManager( this ); ParticleManager = new ParticleManager( this ); WeatherRenderer = new WeatherRenderer( this ); WeatherRenderer.Init(); bool vsync = Options.GetBool( OptionsKey.VSync, true ); Graphics.SetVSync( this, vsync ); Graphics.DepthTest = true; Graphics.DepthTestFunc( CompareFunc.LessEqual ); //Graphics.DepthWrite = true; Graphics.AlphaBlendFunc( BlendFunc.SourceAlpha, BlendFunc.InvSourceAlpha ); Graphics.AlphaTestFunc( CompareFunc.Greater, 0.5f ); fpsScreen = new FpsScreen( this ); fpsScreen.Init(); Culling = new FrustumCulling(); EnvRenderer.Init(); MapEnvRenderer.Init(); Picking = new PickingRenderer( this ); string connectString = "Connecting to " + IPAddress + ":" + Port + ".."; Graphics.WarnIfNecessary( Chat ); SetNewScreen( new LoadingMapScreen( this, connectString, "Reticulating splines" ) ); Network.Connect( IPAddress, Port ); }
void BreakBlockEffect(object sender, BlockChangedEventArgs e) { if (e.Block != Block.Air || BlockInfo.Draw[e.OldBlock] == DrawType.Gas) { return; } Vector3I position = e.Coords; BlockID block = e.OldBlock; Vector3 worldPos = new Vector3(position.X, position.Y, position.Z); int texLoc = BlockInfo.GetTextureLoc(block, Side.Left), texIndex = 0; TextureRec baseRec = TerrainAtlas1D.GetTexRec(texLoc, 1, out texIndex); float uScale = (1 / 16f), vScale = (1 / 16f) * TerrainAtlas1D.invElementSize; Vector3 minBB = BlockInfo.MinBB[block]; Vector3 maxBB = BlockInfo.MaxBB[block]; 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 = (byte)texLoc; p.block = block; int type = rnd.Next(0, 30); p.Size = (byte)(type >= 28 ? 12 : (type >= 25 ? 10 : 8)); } } } }
void PreStretchTiles( int x1, int y1, int z1 ) { atlas = game.TerrainAtlas1D; invVerElementSize = atlas.invElementSize; elementsPerAtlas1D = atlas.elementsPerAtlas1D; arraysCount = atlas.TexIds.Length; if( drawInfoNormal == null ) { drawInfoNormal = new DrawInfo[arraysCount]; drawInfoTranslucent = new DrawInfo[arraysCount]; for( int i = 0; i < drawInfoNormal.Length; i++ ) { drawInfoNormal[i] = new DrawInfo(); drawInfoTranslucent[i] = new DrawInfo(); } } else { for( int i = 0; i < drawInfoNormal.Length; i++ ) { drawInfoNormal[i].ResetState(); drawInfoTranslucent[i].ResetState(); } } }
protected override void DrawModel(Entity p) { // TODO: using 'is' is ugly, but means we can avoid creating // a string every single time held block changes. if (p is FakePlayer) { Player realP = game.LocalPlayer; Vector3I P = Vector3I.Floor(realP.EyePosition); col = game.World.IsValidPos(P) ? game.Lighting.LightCol(P.X, P.Y, P.Z) : game.Lighting.Outside; // Adjust pitch so angle when looking straight down is 0. float adjHeadX = realP.HeadX - 90; if (adjHeadX < 0) { adjHeadX += 360; } // Adjust colour so held block is brighter when looking straght up float t = Math.Abs(adjHeadX - 180) / 180; float colScale = Utils.Lerp(0.9f, 0.7f, t); col = FastColour.ScalePacked(col, colScale); block = ((FakePlayer)p).Block; } else { block = Utils.FastByte(p.ModelName); } CalcState(block); if (!(p is FakePlayer)) { NoShade = bright; } if (bright) { col = FastColour.WhitePacked; } if (game.BlockInfo.Draw[block] == DrawType.Gas) { return; } lastTexId = -1; atlas = game.TerrainAtlas1D; bool sprite = game.BlockInfo.Draw[block] == DrawType.Sprite; DrawParts(sprite); if (index == 0) { return; } IGraphicsApi gfx = game.Graphics; gfx.BindTexture(lastTexId); TransformVertices(); if (sprite) { gfx.FaceCulling = true; } UpdateVB(); if (sprite) { gfx.FaceCulling = false; } }