// VplFile _vplFile; public void Initialize() { Logger.Info("Initializing voxel renderer"); _isInit = true; _surface = new DrawingSurface(400, 400, PixelFormat.Format32bppArgb); if (!CreateContext()) { Logger.Error("No graphics context could not be initialized, voxel rendering will be unavailable"); return; } Logger.Debug("GL context created"); try { Logger.Debug("GL functions loaded"); GL.Enable(EnableCap.DepthTest); GL.Enable(EnableCap.ColorMaterial); //_vplFile = VFS.Open<VplFile>("voxels.vpl"); _canRender = SetupFramebuffer(); } catch (Exception exc) { Logger.Error("Voxel rendering will not be available because an exception occurred while initializing OpenGL: {0}", exc.ToString()); } }
public override void Draw(GameObject obj, DrawingSurface ds, bool shadows = true) { if (obj == null || TsEntry == null) return; var tmpFile = TsEntry.GetTmpFile(obj as MapTile); if (tmpFile != null) TmpRenderer.Draw((MapTile)obj, tmpFile, ds); // todo: tile shadows (TS) }
public override void Draw(GameObject obj, DrawingSurface ds, bool omitShadow = false) { if (TransLucency == 0) base.Draw(obj, ds, omitShadow); else { Logger.Debug("Drawing object {0} with {1}% translucency", obj, TransLucency); ShpRenderer.Draw(Shp, obj, this, Props, ds, TransLucency); } if (Props.HasShadow && !omitShadow) ShpRenderer.DrawShadow(obj, Shp, Props, ds); }
public DebugDrawingSurfaceWindow(DrawingSurface ds, TileLayer tiles, Theater t, Map.Map map) : this() { _drawingSurface = ds; _tiles = tiles; _theater = t; _map = map; ds.Unlock(); pictureBox1.Image = ds.Bitmap; }
public override void Draw(GameObject obj, DrawingSurface ds, bool shadows = true) { Size onBridgeOffset = Size.Empty; if (obj is OwnableObject && (obj as OwnableObject).OnBridge) onBridgeOffset = new Size(0, -4 * TileHeight / 2); foreach (var drawable in SubDrawables) { drawable.Props.Offset += onBridgeOffset; drawable.Draw(obj, ds, shadows); drawable.Props.Offset -= onBridgeOffset; } }
public DebugDrawingSurfaceWindow(DrawingSurface ds, TileLayer tiles, Theater t, Map.Map map) : this() { _drawingSurface = ds; _tiles = tiles; _theater = t; _map = map; _cells = (_map.FullSize.Width * 2 - 1) * _map.FullSize.Height; ds.Unlock(); pictureBox1.Image = ds.Bitmap; }
public DebugDrawingSurfaceWindow(DrawingSurface ds, TileLayer tiles, Theater t, Map.Map map) : this() { _drawingSurface = ds; _tiles = tiles; _theater = t; _map = map; _cells = (_map.FullSize.Width * 2 - 1) * _map.FullSize.Height; ds.Unlock(); // map is pre-rendered bitmap, shadow/heightmap are rendered on demand canvasMap.Image = ds.Bitmap; }
private unsafe void BlitVoxelToSurface(DrawingSurface ds, DrawingSurface vxl_ds, GameObject obj, DrawProperties props) { Point d = new Point(obj.Tile.Dx * TileWidth / 2, (obj.Tile.Dy - obj.Tile.Z) * TileHeight / 2); d.Offset(props.GetOffset(obj)); d.Offset(-vxl_ds.BitmapData.Width / 2, -vxl_ds.BitmapData.Height / 2); // rows inverted! var w_low = (byte*)ds.BitmapData.Scan0; byte* w_high = w_low + ds.BitmapData.Stride * ds.BitmapData.Height; var zBuffer = ds.GetZBuffer(); var shadowBufVxl = vxl_ds.GetShadows(); var shadowBuf = ds.GetShadows(); // int rowsTouched = 0; // short firstRowTouched = short.MaxValue; for (int y = 0; y < vxl_ds.Height; y++) { byte* src_row = (byte*)vxl_ds.BitmapData.Scan0 + vxl_ds.BitmapData.Stride * (vxl_ds.Height - y - 1); byte* dst_row = ((byte*)ds.BitmapData.Scan0 + (d.Y + y) * ds.BitmapData.Stride + d.X * 3); int zIdx = (d.Y + y) * ds.Width + d.X; if (dst_row < w_low || dst_row >= w_high) continue; for (int x = 0; x < vxl_ds.Width; x++) { // only non-transparent pixels if (*(src_row + x * 4 + 3) > 0) { *(dst_row + x * 3) = *(src_row + x * 4); *(dst_row + x * 3 + 1) = *(src_row + x * 4 + 1); *(dst_row + x * 3 + 2) = *(src_row + x * 4 + 2); // if (y < firstRowTouched) // firstRowTouched = (short)y; short zBufVal = (short)((obj.Tile.Rx + obj.Tile.Ry + obj.Tile.Z) * TileHeight / 2); if (zBufVal >= zBuffer[zIdx]) zBuffer[zIdx] = zBufVal; } // or shadows else if (shadowBufVxl[x + y * vxl_ds.Height]) { int shadIdx = (d.Y + y) * ds.Width + d.X + x; if (!shadowBuf[shadIdx]) { *(dst_row + x * 3) /= 2; *(dst_row + x * 3 + 1) /= 2; *(dst_row + x * 3 + 2) /= 2; shadowBuf[shadIdx] = true; } } zIdx++; } } }
public void DrawPowerup(GameObject obj, Drawable powerup, int slot, DrawingSurface ds) { if (slot >= _powerupSlots.Count) throw new InvalidOperationException("Building does not have requested slot "); var powerupOffset = new Point(_powerupSlots[slot].X, _powerupSlots[slot].Y); powerup.Props.Offset.Offset(powerupOffset); powerup.Draw(obj, ds); // undo offset powerup.Props.Offset.Offset(-powerupOffset.X, -powerupOffset.Y); }
unsafe public static void Draw(MapTile tile, TmpFile tmp, DrawingSurface ds) { tmp.Initialize(); if (tile.SubTile >= tmp.Images.Count) { return; } TmpFile.TmpImage img = tmp.Images[tile.SubTile]; var zBuffer = ds.GetZBuffer(); var heightBuffer = ds.GetHeightBuffer(); Palette p = tile.Palette; // calculate tile index -> pixel index Point offset = new Point(tile.Dx * tmp.BlockWidth / 2, (tile.Dy - tile.Z) * tmp.BlockHeight / 2); // make touched tiles (used for determining image cutoff) Point center = offset + new Size(tmp.BlockWidth / 2, tmp.BlockHeight / 2); var centerGridTile = tile.Layer.GetTileScreen(center, true, true); if (centerGridTile != null) { tile.Layer.GridTouched[centerGridTile.Dx, centerGridTile.Dy / 2] |= TileLayer.TouchType.ByNormalData; tile.Layer.GridTouchedBy[centerGridTile.Dx, centerGridTile.Dy / 2] = tile; } Logger.Trace("Drawing TMP file {0} (subtile {1}) at ({2},{3})", tmp.FileName, tile.SubTile, offset.X, offset.Y); int stride = ds.BitmapData.Stride; int halfCx = tmp.BlockWidth / 2, halfCy = tmp.BlockHeight / 2; // writing bounds var w_low = (byte *)ds.BitmapData.Scan0; byte *w_high = (byte *)ds.BitmapData.Scan0 + stride * ds.BitmapData.Height; byte *w = (byte *)ds.BitmapData.Scan0 + stride * offset.Y + (offset.X + halfCx - 2) * 3; int rIdx = 0, x, y = 0; int zIdx = offset.Y * ds.Width + offset.X + halfCx - 2; int cx = 0; // Amount of pixel to copy for (; y < halfCy; y++) { cx += 4; for (ushort c = 0; c < cx; c++) { byte paletteValue = img.TileData[rIdx]; short zBufVal = (short)((tile.Rx + tile.Ry) * tmp.BlockHeight / 2 - (img.ZData != null ? img.ZData[rIdx] : 0)); if (paletteValue != 0 && w_low <= w && w < w_high && zBufVal >= zBuffer[zIdx]) { *(w + 0) = p.Colors[paletteValue].B; *(w + 1) = p.Colors[paletteValue].G; *(w + 2) = p.Colors[paletteValue].R; zBuffer[zIdx] = zBufVal; heightBuffer[zIdx] = (short)(tile.Z * Drawable.TileHeight / 2); } w += 3; zIdx++; rIdx++; } w += stride - 3 * (cx + 2); zIdx += ds.Width - (cx + 2); } w += 12; zIdx += 4; for (; y < tmp.BlockHeight; y++) { cx -= 4; for (ushort c = 0; c < cx; c++) { byte paletteValue = img.TileData[rIdx]; short zBufVal = (short)((tile.Rx + tile.Ry) * tmp.BlockHeight / 2 - (img.ZData != null ? img.ZData[rIdx] : 0)); if (paletteValue != 0 && w_low <= w && w < w_high && zBufVal >= zBuffer[zIdx]) { *(w + 0) = p.Colors[paletteValue].B; *(w + 1) = p.Colors[paletteValue].G; *(w + 2) = p.Colors[paletteValue].R; zBuffer[zIdx] = zBufVal; heightBuffer[zIdx] = (short)(tile.Z * Drawable.TileHeight / 2); } w += 3; zIdx++; rIdx++; } w += stride - 3 * (cx - 2); zIdx += ds.Width - (cx - 2); } if (!img.HasExtraData) { return; // we're done now } offset.X += img.ExtraX - img.X; offset.Y += img.ExtraY - img.Y; w = w_low + stride * offset.Y + 3 * offset.X; zIdx = offset.X + offset.Y * ds.Width; rIdx = 0; // identify extra-data affected tiles for cutoff var extraScreenBounds = Rectangle.FromLTRB( Math.Max(0, offset.X), Math.Max(0, offset.Y), Math.Min(offset.X + img.ExtraWidth, ds.Width), Math.Min(offset.Y + img.ExtraHeight, ds.Height)); for (int by = extraScreenBounds.Top; by < extraScreenBounds.Bottom; by += tmp.BlockHeight / 2) { for (int bx = extraScreenBounds.Left; bx < extraScreenBounds.Right; bx += tmp.BlockWidth / 2) { var gridTileNoZ = tile.Layer.GetTileScreen(new Point(bx, by), true, true); if (gridTileNoZ != null) { Logger.Trace("Tile at ({0},{1}) has extradata affecting ({2},{3})", tile.Dx, tile.Dy, gridTileNoZ.Dx, gridTileNoZ.Dy); tile.Layer.GridTouched[gridTileNoZ.Dx, gridTileNoZ.Dy / 2] |= TileLayer.TouchType.ByExtraData; tile.Layer.GridTouchedBy[gridTileNoZ.Dx, gridTileNoZ.Dy / 2] = tile; } } } // Extra graphics are just a square for (y = 0; y < img.ExtraHeight; y++) { for (x = 0; x < img.ExtraWidth; x++) { // Checking per line is required because v needs to be checked every time byte paletteValue = img.ExtraData[rIdx]; short zBufVal = (short)((tile.Rx + tile.Ry) * tmp.BlockHeight / 2 + (img.ExtraZData != null ? img.ExtraZData[rIdx] : 0)); if (paletteValue != 0 && w_low <= w && w < w_high && zBufVal >= zBuffer[zIdx]) { *w++ = p.Colors[paletteValue].B; *w++ = p.Colors[paletteValue].G; *w++ = p.Colors[paletteValue].R; zBuffer[zIdx] = zBufVal; heightBuffer[zIdx] = (short)(img.ExtraHeight - y + tile.Z * Drawable.TileHeight / 2); } else { w += 3; } zIdx++; rIdx++; } w += stride - img.ExtraWidth * 3; zIdx += ds.Width - img.ExtraWidth; } }
public abstract void Draw(GameObject obj, DrawingSurface ds, bool shadow = true);
unsafe public static void Draw(MapTile tile, TmpFile tmp, DrawingSurface ds) { tmp.Initialize(); if (tile.SubTile >= tmp.Images.Count) return; TmpFile.TmpImage img = tmp.Images[tile.SubTile]; var zBuffer = ds.GetZBuffer(); var heightBuffer = ds.GetHeightBuffer(); Palette p = tile.Palette; // calculate tile index -> pixel index Point offset = new Point(tile.Dx * tmp.BlockWidth / 2, (tile.Dy - tile.Z) * tmp.BlockHeight / 2); // make touched tiles (used for determining image cutoff) Point center = offset + new Size(tmp.BlockWidth / 2, tmp.BlockHeight / 2); var centerGridTile = tile.Layer.GetTileScreen(center, true, true); if (centerGridTile != null) { tile.Layer.GridTouched[centerGridTile.Dx, centerGridTile.Dy / 2] |= TileLayer.TouchType.ByNormalData; tile.Layer.GridTouchedBy[centerGridTile.Dx, centerGridTile.Dy / 2] = tile; } Logger.Trace("Drawing TMP file {0} (subtile {1}) at ({2},{3})", tmp.FileName, tile.SubTile, offset.X, offset.Y); int stride = ds.BitmapData.Stride; int halfCx = tmp.BlockWidth / 2, halfCy = tmp.BlockHeight / 2; // writing bounds var w_low = (byte*)ds.BitmapData.Scan0; byte* w_high = (byte*)ds.BitmapData.Scan0 + stride * ds.BitmapData.Height; byte* w = (byte*)ds.BitmapData.Scan0 + stride * offset.Y + (offset.X + halfCx - 2) * 3; int rIdx = 0, x, y = 0; int zIdx = offset.Y * ds.Width + offset.X + halfCx - 2; int cx = 0; // Amount of pixel to copy for (; y < halfCy; y++) { cx += 4; for (ushort c = 0; c < cx; c++) { byte paletteValue = img.TileData[rIdx]; short zBufVal = (short)((tile.Rx + tile.Ry) * tmp.BlockHeight / 2 - (img.ZData != null ? img.ZData[rIdx] : 0)); if (paletteValue != 0 && w_low <= w && w < w_high && zBufVal >= zBuffer[zIdx]) { *(w + 0) = p.Colors[paletteValue].B; *(w + 1) = p.Colors[paletteValue].G; *(w + 2) = p.Colors[paletteValue].R; zBuffer[zIdx] = zBufVal; heightBuffer[zIdx] = (short)(tile.Z * Drawable.TileHeight / 2); } w += 3; zIdx++; rIdx++; } w += stride - 3 * (cx + 2); zIdx += ds.Width - (cx + 2); } w += 12; zIdx += 4; for (; y < tmp.BlockHeight; y++) { cx -= 4; for (ushort c = 0; c < cx; c++) { byte paletteValue = img.TileData[rIdx]; short zBufVal = (short)((tile.Rx + tile.Ry) * tmp.BlockHeight / 2 - (img.ZData != null ? img.ZData[rIdx] : 0)); if (paletteValue != 0 && w_low <= w && w < w_high && zBufVal >= zBuffer[zIdx]) { *(w + 0) = p.Colors[paletteValue].B; *(w + 1) = p.Colors[paletteValue].G; *(w + 2) = p.Colors[paletteValue].R; zBuffer[zIdx] = zBufVal; heightBuffer[zIdx] = (short)(tile.Z * Drawable.TileHeight / 2); } w += 3; zIdx++; rIdx++; } w += stride - 3 * (cx - 2); zIdx += ds.Width - (cx - 2); } if (!img.HasExtraData) return; // we're done now offset.X += img.ExtraX - img.X; offset.Y += img.ExtraY - img.Y; w = w_low + stride * offset.Y + 3 * offset.X; zIdx = offset.X + offset.Y * ds.Width; rIdx = 0; // identify extra-data affected tiles for cutoff var extraScreenBounds = Rectangle.FromLTRB( Math.Max(0, offset.X), Math.Max(0, offset.Y), Math.Min(offset.X + img.ExtraWidth, ds.Width), Math.Min(offset.Y + img.ExtraHeight, ds.Height)); for (int by = extraScreenBounds.Top; by < extraScreenBounds.Bottom; by += tmp.BlockHeight / 2) { for (int bx = extraScreenBounds.Left; bx < extraScreenBounds.Right; bx += tmp.BlockWidth / 2) { var gridTileNoZ = tile.Layer.GetTileScreen(new Point(bx, by), true, true); if (gridTileNoZ != null) { Logger.Trace("Tile at ({0},{1}) has extradata affecting ({2},{3})", tile.Dx, tile.Dy, gridTileNoZ.Dx, gridTileNoZ.Dy); tile.Layer.GridTouched[gridTileNoZ.Dx, gridTileNoZ.Dy / 2] |= TileLayer.TouchType.ByExtraData; tile.Layer.GridTouchedBy[gridTileNoZ.Dx, gridTileNoZ.Dy / 2] = tile; } } } // Extra graphics are just a square for (y = 0; y < img.ExtraHeight; y++) { for (x = 0; x < img.ExtraWidth; x++) { // Checking per line is required because v needs to be checked every time byte paletteValue = img.ExtraData[rIdx]; short zBufVal = (short)((tile.Rx + tile.Ry) * tmp.BlockHeight / 2 + (img.ExtraZData != null ? img.ExtraZData[rIdx] : 0)); if (paletteValue != 0 && w_low <= w && w < w_high && zBufVal >= zBuffer[zIdx]) { *w++ = p.Colors[paletteValue].B; *w++ = p.Colors[paletteValue].G; *w++ = p.Colors[paletteValue].R; zBuffer[zIdx] = zBufVal; heightBuffer[zIdx] = (short)(img.ExtraHeight - y + tile.Z * Drawable.TileHeight / 2); } else w += 3; zIdx++; rIdx++; } w += stride - img.ExtraWidth * 3; zIdx += ds.Width - img.ExtraWidth; } }
public override void Draw(GameObject obj, DrawingSurface ds, bool shadow = true) { ShpRenderer.DrawAlpha(obj, Shp, Props, ds); }
public override void Draw(GameObject obj, DrawingSurface ds, bool shadows = true) { if (InvisibleInGame) return; var drawList = new List<Drawable>(); drawList.Add(_baseShp); if (obj is StructureObject && (obj as StructureObject).Health < 128) { drawList.AddRange(_animsDamaged); drawList.AddRange(_fires); } else drawList.AddRange(_anims); drawList.AddRange(SubDrawables); // bib /* order: ActiveAnims+Flat=yes BibShape ActiveAnims (+ZAdjust=0) Building ActiveAnims+ZAdjust=-32 */ drawList = drawList.OrderBy(d => d.Flat ? -1 : 1).ThenBy(d => d.Props.SortIndex).ToList(); foreach (var d in drawList) d.Draw(obj, ds, false); if (shadows) foreach (var d in drawList) d.DrawShadow(obj, ds); var strObj = obj as StructureObject; if (!strObj.Upgrade1.Equals("None", StringComparison.InvariantCultureIgnoreCase) && _powerupSlots.Count >= 1) { var powerup = OwnerCollection.GetDrawable(strObj.Upgrade1); DrawPowerup(obj, powerup, 0, ds); } if (!strObj.Upgrade2.Equals("None", StringComparison.InvariantCultureIgnoreCase) && _powerupSlots.Count >= 2) { var powerup = OwnerCollection.GetDrawable(strObj.Upgrade2); DrawPowerup(obj, powerup, 1, ds); } if (!strObj.Upgrade3.Equals("None", StringComparison.InvariantCultureIgnoreCase) && _powerupSlots.Count >= 3) { var powerup = OwnerCollection.GetDrawable(strObj.Upgrade3); DrawPowerup(obj, powerup, 2, ds); } }
public virtual void DrawShadow(GameObject obj, DrawingSurface ds) { }
internal void Draw(GameObject obj, DrawingSurface ds) { Logger.Trace("Drawing object {0} @ {1}", obj, obj.Tile); obj.Drawable.Draw(obj, ds); }
public override void DrawShadow(GameObject obj, DrawingSurface ds) { if (InvisibleInGame || Shp == null) return; if (Props.HasShadow) ShpRenderer.DrawShadow(obj, Shp, Props, ds); }
public unsafe void Draw(ShpFile shp, GameObject obj, Drawable dr, DrawProperties props, DrawingSurface ds, int transLucency = 0) { shp.Initialize(); Palette p = props.PaletteOverride ?? obj.Palette; int frameIndex = props.FrameDecider(obj); if (obj.Drawable.IsActualWall) { frameIndex = ((StructureObject)obj).WallBuildingFrame; } frameIndex = DecideFrameIndex(frameIndex, shp.NumImages); if (frameIndex >= shp.Images.Count) { return; } var img = shp.GetImage(frameIndex); var imgData = img.GetImageData(); if (imgData == null || img.Width * img.Height != imgData.Length) { return; } Point offset = props.GetOffset(obj); offset.X += obj.Tile.Dx * _config.TileWidth / 2 - shp.Width / 2 + img.X; offset.Y += (obj.Tile.Dy - obj.Tile.Z) * _config.TileHeight / 2 - shp.Height / 2 + img.Y; Logger.Trace("Drawing SHP file {0} (Frame {1}) at ({2},{3})", shp.FileName, frameIndex, offset.X, offset.Y); int stride = ds.BitmapData.Stride; var heightBuffer = ds.GetHeightBuffer(); var zBuffer = ds.GetZBuffer(); var w_low = (byte *)ds.BitmapData.Scan0; byte *w_high = (byte *)ds.BitmapData.Scan0 + stride * ds.BitmapData.Height; byte *w = (byte *)ds.BitmapData.Scan0 + offset.X * 3 + stride * offset.Y; // clip to 25-50-75-100 transLucency = (transLucency / 25) * 25; float a = transLucency / 100f; float b = 1 - a; int rIdx = 0; // image pixel index int zIdx = offset.X + offset.Y * ds.Width; // z-buffer pixel index short hBufVal = (short)(obj.Tile.Z * _config.TileHeight / 2); short zOffset = (short)((obj.BottomTile.Rx + obj.BottomTile.Ry) * _config.TileHeight / 2 + props.ZAdjust); if (!dr.Flat) { hBufVal += shp.Height; } for (int y = 0; y < img.Height; y++) { if (offset.Y + y < 0) { w += stride; rIdx += img.Width; zIdx += ds.Width; continue; // out of bounds } for (int x = 0; x < img.Width; x++) { byte paletteValue = imgData[rIdx]; short zshapeOffset = obj is StructureObject ? (GetBuildingZ(x, y, shp, img, obj)) : (short)0; if (paletteValue != 0) { short zBufVal = zOffset; if (dr.Flat) { zBufVal += (short)(y - img.Height); } else if (dr.IsBuildingPart) { // nonflat building zBufVal += zshapeOffset; } else { zBufVal += img.Height; } if (w_low <= w && w < w_high /*&& zBufVal >= zBuffer[zIdx]*/) { if (transLucency != 0) { *(w + 0) = (byte)(a * *(w + 0) + b * p.Colors[paletteValue].B); *(w + 1) = (byte)(a * *(w + 1) + b * p.Colors[paletteValue].G); *(w + 2) = (byte)(a * *(w + 2) + b * p.Colors[paletteValue].R); } else { *(w + 0) = p.Colors[paletteValue].B; *(w + 1) = p.Colors[paletteValue].G; *(w + 2) = p.Colors[paletteValue].R; //var pal = Theater.Active.GetPalettes().UnitPalette.Colors; //*(w + 0) = pal[zshapeOffset].R; //*(w + 1) = pal[zshapeOffset].G; //*(w + 2) = pal[zshapeOffset].B; } zBuffer[zIdx] = zBufVal; heightBuffer[zIdx] = hBufVal; } } //else { // *(w + 0) = 0; // *(w + 1) = 0; // *(w + 2) = 255; //} // Up to the next pixel rIdx++; zIdx++; w += 3; } w += stride - 3 * img.Width; zIdx += ds.Width - img.Width; } }
public void Draw() { _drawingSurface = new DrawingSurface(FullSize.Width * TileWidth, FullSize.Height * TileHeight, PixelFormat.Format24bppRgb); #if SORT Logger.Info("Sorting objects map"); var sorter = new ObjectSorter(_theater, _tiles); var orderedObjs = sorter.GetOrderedObjects().ToList(); double lastReported = 0.0; Logger.Info("Drawing map... 0%"); for (int i = 0; i < orderedObjs.Count; i++) { var obj = orderedObjs[i]; _theater.Draw(obj, _drawingSurface); double pct = 100.0 * i / orderedObjs.Count; if (pct > lastReported + 5) { Logger.Info("Drawing map... {0}%", Math.Round(pct, 0)); lastReported = pct; } } #else double lastReported = 0.0; for (int y = 0; y < FullSize.Height; y++) { Logger.Trace("Drawing tiles row {0}", y); for (int x = FullSize.Width * 2 - 2; x >= 0; x -= 2) _theater.Draw(_tiles.GetTile(x, y), _drawingSurface); for (int x = FullSize.Width * 2 - 3; x >= 0; x -= 2) _theater.Draw(_tiles.GetTile(x, y), _drawingSurface); double pct = 50.0 * y / FullSize.Height; if (pct > lastReported + 5) { Logger.Info("Drawing tiles... {0}%", Math.Round(pct, 0)); lastReported = pct; } } Logger.Info("Tiles drawn"); for (int y = 0; y < FullSize.Height; y++) { Logger.Trace("Drawing objects row {0}", y); for (int x = FullSize.Width * 2 - 2; x >= 0; x -= 2) foreach (GameObject o in GetObjectsAt(x, y)) _theater.Draw(o, _drawingSurface); for (int x = FullSize.Width * 2 - 3; x >= 0; x -= 2) foreach (GameObject o in GetObjectsAt(x, y)) _theater.Draw(o, _drawingSurface); double pct = 50 + 50.0 * y / FullSize.Height; if (pct > lastReported + 5) { Logger.Info("Drawing objects... {0}%", Math.Round(pct, 0)); lastReported = pct; } } #endif #if DEBUG && FALSE // test that my bounds make some kind of sense _drawingSurface.Unlock(); using (Graphics gfx = Graphics.FromImage(_drawingSurface.Bitmap)) { foreach (var obj in _tiles.SelectMany(t=>t.AllObjects)) if (obj.Drawable != null) obj.Drawable.DrawBoundingBox(obj, gfx); } #endif Logger.Info("Map drawing completed"); }
public override void Draw(GameObject obj, DrawingSurface ds, bool shadows = true) { if (Vxl == null || Hva == Stream.Null) return; DrawingSurface vxl_ds = VoxelRenderer.Render(Vxl, Hva, obj, Props); if (vxl_ds != null) BlitVoxelToSurface(ds, vxl_ds, obj, Props); }
public unsafe void DrawShadow(GameObject obj, ShpFile shp, DrawProperties props, DrawingSurface ds) { shp.Initialize(); int frameIndex = props.FrameDecider(obj); if (obj.Drawable.IsActualWall) { frameIndex = ((StructureObject)obj).WallBuildingFrame; } frameIndex = DecideFrameIndex(frameIndex, shp.NumImages); frameIndex += shp.Images.Count / 2; // latter half are shadow Images if (frameIndex >= shp.Images.Count) { return; } var img = shp.GetImage(frameIndex); var imgData = img.GetImageData(); if (imgData == null || img.Width * img.Height != imgData.Length) { return; } Point offset = props.GetShadowOffset(obj); offset.X += obj.Tile.Dx * _config.TileWidth / 2 - shp.Width / 2 + img.X; offset.Y += (obj.Tile.Dy - obj.Tile.Z) * _config.TileHeight / 2 - shp.Height / 2 + img.Y; Logger.Trace("Drawing SHP shadow {0} (frame {1}) at ({2},{3})", shp.FileName, frameIndex, offset.X, offset.Y); int stride = ds.BitmapData.Stride; var shadows = ds.GetShadows(); var zBuffer = ds.GetZBuffer(); var heightBuffer = ds.GetHeightBuffer(); var w_low = (byte *)ds.BitmapData.Scan0; byte *w_high = (byte *)ds.BitmapData.Scan0 + stride * ds.BitmapData.Height; byte *w = (byte *)ds.BitmapData.Scan0 + offset.X * 3 + stride * offset.Y; int zIdx = offset.X + offset.Y * ds.Width; int rIdx = 0; short zOffset = (short)((obj.Tile.Rx + obj.Tile.Ry) * _config.TileHeight / 2 - shp.Height / 2 + img.Y); int castHeight = obj.Tile.Z * _config.TileHeight / 2; if (obj.Drawable != null && !obj.Drawable.Flat) { castHeight += shp.Height; castHeight += obj.Drawable.TileElevation * _config.TileHeight / 2; } for (int y = 0; y < img.Height; y++) { if (offset.Y + y < 0) { w += stride; rIdx += img.Width; zIdx += ds.Width; continue; // out of bounds } short zBufVal = zOffset; if (obj.Drawable.Flat) { zBufVal += (short)y; } else { zBufVal += img.Height; } for (int x = 0; x < img.Width; x++) { if (0 <= offset.X + x && offset.X + x < ds.Width && 0 <= y + offset.Y && y + offset.Y < ds.Height && imgData[rIdx] != 0 && !shadows[zIdx] && // zBufVal >= zBuffer[zIdx] && castHeight >= heightBuffer[zIdx]) { *(w + 0) /= 2; *(w + 1) /= 2; *(w + 2) /= 2; shadows[zIdx] = true; } // Up to the next pixel rIdx++; zIdx++; w += 3; } w += stride - 3 * img.Width; // ... and if we're no more on the same row, zIdx += ds.Width - img.Width; // adjust the writing pointer accordingy } }
unsafe public static void Draw(ShpFile shp, GameObject obj, Drawable dr, DrawProperties props, DrawingSurface ds, int transLucency = 0) { shp.Initialize(); int frameIndex = props.FrameDecider(obj); Palette p = props.PaletteOverride ?? obj.Palette; frameIndex = DecideFrameIndex(frameIndex, shp.NumImages); if (frameIndex >= shp.Images.Count) return; var img = shp.GetImage(frameIndex); var imgData = img.GetImageData(); if (imgData == null || img.Width * img.Height != imgData.Length) return; Point offset = props.GetOffset(obj); offset.X += obj.Tile.Dx * Drawable.TileWidth / 2 - shp.Width / 2 + img.X; offset.Y += (obj.Tile.Dy - obj.Tile.Z) * Drawable.TileHeight / 2 - shp.Height / 2 + img.Y; Logger.Trace("Drawing SHP file {0} (Frame {1}) at ({2},{3})", shp.FileName, frameIndex, offset.X, offset.Y); int stride = ds.BitmapData.Stride; var heightBuffer = ds.GetHeightBuffer(); var zBuffer = ds.GetZBuffer(); var w_low = (byte*)ds.BitmapData.Scan0; byte* w_high = (byte*)ds.BitmapData.Scan0 + stride * ds.BitmapData.Height; byte* w = (byte*)ds.BitmapData.Scan0 + offset.X * 3 + stride * offset.Y; // clip to 25-50-75-100 transLucency = (transLucency / 25) * 25; float a = transLucency / 100f; float b = 1 - a; int rIdx = 0; // image pixel index int zIdx = offset.X + offset.Y * ds.Width; // z-buffer pixel index short hBufVal = (short)(obj.Tile.Z * Drawable.TileHeight / 2); short zOffset = (short)((obj.BottomTile.Rx + obj.BottomTile.Ry) * Drawable.TileHeight / 2); if (!dr.Flat) hBufVal += shp.Height; for (int y = 0; y < img.Height; y++) { if (offset.Y + y < 0) { w += stride; rIdx += img.Width; zIdx += ds.Width; continue; // out of bounds } for (int x = 0; x < img.Width; x++) { byte paletteValue = imgData[rIdx]; short zshapeOffset = obj is StructureObject ? (GetBuildingZ(x, y, shp, img, obj)) : (short)0; if (paletteValue != 0) { short zBufVal = zOffset; if (dr.Flat) zBufVal += (short)(y - img.Height); else if (dr.IsBuildingPart) { // nonflat building zBufVal += zshapeOffset; } else zBufVal += img.Height; if (w_low <= w && w < w_high /*&& zBufVal >= zBuffer[zIdx]*/) { if (transLucency != 0) { *(w + 0) = (byte)(a * *(w + 0) + b * p.Colors[paletteValue].B); *(w + 1) = (byte)(a * *(w + 1) + b * p.Colors[paletteValue].G); *(w + 2) = (byte)(a * *(w + 2) + b * p.Colors[paletteValue].R); } else { *(w + 0) = p.Colors[paletteValue].B; *(w + 1) = p.Colors[paletteValue].G; *(w + 2) = p.Colors[paletteValue].R; //var pal = Theater.Active.GetPalettes().UnitPalette.Colors; //*(w + 0) = pal[zshapeOffset].R; //*(w + 1) = pal[zshapeOffset].G; //*(w + 2) = pal[zshapeOffset].B; } zBuffer[zIdx] = zBufVal; heightBuffer[zIdx] = hBufVal; } } //else { // *(w + 0) = 0; // *(w + 1) = 0; // *(w + 2) = 255; //} // Up to the next pixel rIdx++; zIdx++; w += 3; } w += stride - 3 * img.Width; zIdx += ds.Width - img.Width; } }
unsafe public static void DrawAlpha(GameObject obj, ShpFile shp, DrawProperties props, DrawingSurface ds) { shp.Initialize(); // Change originally implemented by Starkku: Ares supports multiframe AlphaImages, based on frame count // the direction the unit it facing. int frameIndex = props.FrameDecider(obj); var img = shp.GetImage(frameIndex); var imgData = img.GetImageData(); var c_px = (uint)(img.Width * img.Height); if (c_px <= 0 || img.Width < 0 || img.Height < 0 || frameIndex > shp.NumImages) return; Point offset = props.GetOffset(obj); offset.X += obj.Tile.Dx * Drawable.TileWidth / 2; offset.Y += (obj.Tile.Dy - obj.Tile.Z) * Drawable.TileHeight / 2; Logger.Trace("Drawing AlphaImage SHP file {0} (frame {1}) at ({2},{3})", shp.FileName, frameIndex, offset.X, offset.Y); int stride = ds.BitmapData.Stride; var w_low = (byte*)ds.BitmapData.Scan0; byte* w_high = (byte*)ds.BitmapData.Scan0 + stride * ds.BitmapData.Height; int dx = offset.X + Drawable.TileWidth / 2 - shp.Width / 2 + img.X, dy = offset.Y - shp.Height / 2 + img.Y; byte* w = (byte*)ds.BitmapData.Scan0 + dx * 3 + stride * dy; short zOffset = (short)((obj.Tile.Rx + obj.Tile.Ry) * Drawable.TileHeight / 2 - shp.Height / 2 + img.Y); int rIdx = 0; for (int y = 0; y < img.Height; y++) { for (int x = 0; x < img.Width; x++) { if (imgData[rIdx] != 0 && w_low <= w && w < w_high) { float mult = imgData[rIdx] / 127.0f; *(w + 0) = limit(mult, *(w + 0)); *(w + 1) = limit(mult, *(w + 1)); *(w + 2) = limit(mult, *(w + 2)); } // Up to the next pixel rIdx++; w += 3; } w += stride - 3 * img.Width; // ... and if we're no more on the same row, // adjust the writing pointer accordingy } }
unsafe public static void DrawShadow(GameObject obj, ShpFile shp, DrawProperties props, DrawingSurface ds) { int frameIndex = props.FrameDecider(obj); frameIndex = DecideFrameIndex(frameIndex, shp.NumImages); frameIndex += shp.Images.Count / 2; // latter half are shadow Images if (frameIndex >= shp.Images.Count) return; var img = shp.GetImage(frameIndex); var imgData = img.GetImageData(); if (imgData == null || img.Width * img.Height != imgData.Length) return; Point offset = props.GetShadowOffset(obj); offset.X += obj.Tile.Dx * Drawable.TileWidth / 2 - shp.Width / 2 + img.X; offset.Y += (obj.Tile.Dy - obj.Tile.Z) * Drawable.TileHeight / 2 - shp.Height / 2 + img.Y; Logger.Trace("Drawing SHP shadow {0} (frame {1}) at ({2},{3})", shp.FileName, frameIndex, offset.X, offset.Y); int stride = ds.BitmapData.Stride; var shadows = ds.GetShadows(); var zBuffer = ds.GetZBuffer(); var heightBuffer = ds.GetHeightBuffer(); var w_low = (byte*)ds.BitmapData.Scan0; byte* w_high = (byte*)ds.BitmapData.Scan0 + stride * ds.BitmapData.Height; byte* w = (byte*)ds.BitmapData.Scan0 + offset.X * 3 + stride * offset.Y; int zIdx = offset.X + offset.Y * ds.Width; int rIdx = 0; short zOffset = (short)((obj.Tile.Rx + obj.Tile.Ry) * Drawable.TileHeight / 2 - shp.Height / 2 + img.Y); int castHeight = obj.Tile.Z * Drawable.TileHeight / 2; if (obj.Drawable != null && !obj.Drawable.Flat) { castHeight += shp.Height; castHeight += obj.Drawable.TileElevation * Drawable.TileHeight / 2; } for (int y = 0; y < img.Height; y++) { if (offset.Y + y < 0) { w += stride; rIdx += img.Width; zIdx += ds.Width; continue; // out of bounds } short zBufVal = zOffset; if (obj.Drawable.Flat) zBufVal += (short)y; else zBufVal += img.Height; for (int x = 0; x < img.Width; x++) { if (w_low <= w && w < w_high && imgData[rIdx] != 0 && !shadows[zIdx] //&& zBufVal >= zBuffer[zIdx] && castHeight >= heightBuffer[zIdx] ) { *(w + 0) /= 2; *(w + 1) /= 2; *(w + 2) /= 2; shadows[zIdx] = true; } // Up to the next pixel rIdx++; zIdx++; w += 3; } w += stride - 3 * img.Width; // ... and if we're no more on the same row, zIdx += ds.Width - img.Width; // adjust the writing pointer accordingy } }
public unsafe void DrawAlpha(GameObject obj, ShpFile shp, DrawProperties props, DrawingSurface ds) { shp.Initialize(); // Ares supports multiframe AlphaImages, based on frame count and the direction the unit it facing. int frameIndex = props.FrameDecider(obj); var img = shp.GetImage(frameIndex); var imgData = img.GetImageData(); var c_px = (uint)(img.Width * img.Height); if (c_px <= 0 || img.Width < 0 || img.Height < 0 || frameIndex > shp.NumImages) { return; } Point offset = props.GetOffset(obj); offset.X += obj.Tile.Dx * _config.TileWidth / 2; offset.Y += (obj.Tile.Dy - obj.Tile.Z) * _config.TileHeight / 2; Logger.Trace("Drawing AlphaImage SHP file {0} (frame {1}) at ({2},{3})", shp.FileName, frameIndex, offset.X, offset.Y); int stride = ds.BitmapData.Stride; var w_low = (byte *)ds.BitmapData.Scan0; byte *w_high = (byte *)ds.BitmapData.Scan0 + stride * ds.BitmapData.Height; int dx = offset.X + _config.TileWidth / 2 - shp.Width / 2 + img.X, dy = offset.Y - shp.Height / 2 + img.Y; byte *w = (byte *)ds.BitmapData.Scan0 + dx * 3 + stride * dy; short zOffset = (short)((obj.Tile.Rx + obj.Tile.Ry) * _config.TileHeight / 2 - shp.Height / 2 + img.Y + props.ZAdjust); int rIdx = 0; for (int y = 0; y < img.Height; y++) { for (int x = 0; x < img.Width; x++) { if (imgData[rIdx] != 0 && w_low <= w && w < w_high) { float mult = imgData[rIdx] / 127.0f; *(w + 0) = limit(mult, *(w + 0)); *(w + 1) = limit(mult, *(w + 1)); *(w + 2) = limit(mult, *(w + 2)); } // Up to the next pixel rIdx++; w += 3; } w += stride - 3 * img.Width; // ... and if we're no more on the same row, // adjust the writing pointer accordingly } }
public override void Draw(GameObject obj, DrawingSurface ds, bool shadow = true) { if (InvisibleInGame || Shp == null) return; ShpRenderer.Draw(Shp, obj, this, Props, ds); if (Props.HasShadow && shadow) ShpRenderer.DrawShadow(obj, Shp, Props, ds); }