private void ApplyBrush(ViewControl vc, System.Drawing.Point scrPt) { TerrainGob terrain = m_terrainEditor.TerrainEditorControl.SelectedTerrain; TerrainBrush brush = m_terrainEditor.TerrainEditorControl.SelectedBrush; TerrainMap terrainMap = m_terrainEditor.TerrainEditorControl.SelectedTerrainMap; if (brush == null || (!brush.CanApplyTo(terrain) && !brush.CanApplyTo(terrainMap))) { return; } Ray3F rayw = vc.GetWorldRay(scrPt); TerrainGob.RayPickRetVal retval; if (terrain.RayPick(rayw, out retval)) { TerrainOp op = null; if (brush.CanApplyTo(terrain)) { Point pt = terrain.WorldToSurfaceSpace(retval.hitpos); brush.Apply(terrain, pt.X, pt.Y, out op); } else if (brush.CanApplyTo(terrainMap)) { Point pt = terrainMap.WorldToSurfaceSpace(retval.hitpos); brush.Apply(terrainMap, pt.X, pt.Y, out op); } m_tmpOps.Add(op); m_terrainOpList.Add(new WeakReference(op)); m_memUsage += op.SizeInBytes; } }
public override void Apply(ITerrainSurface target, int x, int y, out TerrainOp op) { op = null; if (!CanApplyTo(target)) { return; } Bound2di outRect; TerrainGob terrain = target.As <TerrainGob>(); ImageData hmImg = terrain.GetSurface(); ComputeBound(hmImg, x, y, out outRect); if (!outRect.isValid || hmImg.Format != ImageDataFORMAT.R32_FLOAT) { return; } op = new TerrainOp(target, outRect); var brushOp = GetBrushOp(); Func <float, float, float> ops = null; if (brushOp == BrushOps.Add) { ops = (a, b) => a + b; } else if (brushOp == BrushOps.Sub) { ops = (a, b) => a - b; } if (ops == null) { throw new ArgumentException("brushOp"); } // start point in kernel space. int bx0 = x - Radius; int by0 = y - Radius; int size = 2 * Radius + 1; for (int cy = outRect.y1; cy < outRect.y2; cy++) { int by = cy - by0; for (int cx = outRect.x1; cx < outRect.x2; cx++) { int bx = cx - bx0; float scrPixel = Kernel[size * by + bx] * m_height; float *destPixel = (float *)hmImg.GetPixel(cx, cy); * destPixel = ops(*destPixel, scrPixel); } } terrain.ApplyDirtyRegion(outRect); }
public override void Apply(ITerrainSurface target, int x, int y, out TerrainOp op) { op = null; if (!CanApplyTo(target)) { return; } Bound2di outRect; TerrainGob terrain = target.As <TerrainGob>(); ImageData hmImg = terrain.GetSurface(); ComputeBound(hmImg, x, y, out outRect); if (!outRect.isValid || hmImg.Format != ImageDataFORMAT.R32_FLOAT) { return; } op = new TerrainOp(target, outRect); // start point in kernel space. int bx0 = x - Radius; int by0 = y - Radius; int size = 2 * Radius + 1; for (int cy = outRect.y1; cy < outRect.y2; cy++) { int by = cy - by0; for (int cx = outRect.x1; cx < outRect.x2; cx++) { int bx = cx - bx0; float k = Kernel[size * by + bx] * m_noise[bx, by] * m_scale; float *destPixel = (float *)hmImg.GetPixel(cx, cy); * destPixel = *destPixel + k; } } terrain.ApplyDirtyRegion(outRect); }
void IManipulator.OnEndDrag(ViewControl vc, Point scrPt) { if (!dragged) { ApplyBrush(vc, scrPt); } dragged = false; if (m_tmpOps.Count > 0) { TerrainBrush brush = m_terrainEditor.TerrainEditorControl.SelectedBrush; string transName = string.Format("Apply {0} brush", brush.Name); GameContext context = m_designView.Context.As <GameContext>(); context.DoTransaction( delegate { foreach (var op in m_tmpOps) { context.TransactionOperations.Add(op); } }, transName); m_tmpOps.Clear(); } if (m_memUsage > MemoryQuota) { m_memUsage = 0; // removed all the TerrainOps that been GC-ed // and re-compute current memory usage. List <WeakReference> tmplist = new List <WeakReference>(); foreach (WeakReference wkref in m_terrainOpList) { if (!wkref.IsAlive) { tmplist.Add(wkref); } else { m_memUsage += ((TerrainOp)wkref.Target).SizeInBytes; } } if (m_memUsage == 0) { m_terrainOpList.Clear(); } else { foreach (WeakReference wkref in tmplist) { m_terrainOpList.Remove(wkref); } } // disable oldest terrainOP to free memory. int limit = MemoryQuota - MemoryQuota / 5; foreach (WeakReference wkref in m_terrainOpList) { if (m_memUsage < limit) { break; } TerrainOp op = (TerrainOp)wkref.Target; m_memUsage -= op.SizeInBytes; op.FreeData(); } } }
/// <summary> /// Apply this brush to target at the given coordinate /// output TerrainOp for undo/redo /// </summary> public abstract void Apply(ITerrainSurface target, int x, int y, out TerrainOp op);
public override void Apply(ITerrainSurface target, int x, int y, out TerrainOp op) { op = null; if (!CanApplyTo(target)) return; Bound2di outRect; TerrainGob terrain = target.As<TerrainGob>(); ImageData hmImg = terrain.GetSurface(); ComputeBound(hmImg, x, y, out outRect); if (!outRect.isValid || hmImg.Format != ImageDataFORMAT.R32_FLOAT) return; op = new TerrainOp(target, outRect); // start point in kernel space. int bx0 = x - Radius; int by0 = y - Radius; int size = 2 * Radius + 1; for (int cy = outRect.y1; cy < outRect.y2; cy++) { int by = cy - by0; for (int cx = outRect.x1; cx < outRect.x2; cx++) { int bx = cx - bx0; float k = Kernel[size * by + bx] * m_noise[bx, by] * m_scale; float* destPixel = (float*)hmImg.GetPixel(cx, cy); *destPixel = *destPixel + k; } } terrain.ApplyDirtyRegion(outRect); }
public override void Apply(ITerrainSurface target, int x, int y, out TerrainOp op) { op = null; if (!CanApplyTo(target)) return; Bound2di outRect; TerrainGob terrain = target.As<TerrainGob>(); ImageData hmImg = terrain.GetSurface(); ComputeBound(hmImg, x, y, out outRect); if (!outRect.isValid || hmImg.Format != ImageDataFORMAT.R32_FLOAT) return; op = new TerrainOp(target, outRect); var brushOp = GetBrushOp(); Func<float, float, float> ops = null; if (brushOp == BrushOps.Add) ops = (a, b) => a + b; else if (brushOp == BrushOps.Sub) ops = (a, b) => a - b; if (ops == null) throw new ArgumentException("brushOp"); // start point in kernel space. int bx0 = x - Radius; int by0 = y - Radius; int size = 2 * Radius + 1; for (int cy = outRect.y1; cy < outRect.y2; cy++) { int by = cy - by0; for (int cx = outRect.x1; cx < outRect.x2; cx++) { int bx = cx - bx0; float scrPixel = Kernel[size * by + bx] * m_height; float* destPixel = (float*)hmImg.GetPixel(cx, cy); *destPixel = ops(*destPixel, scrPixel); } } terrain.ApplyDirtyRegion(outRect); }
public override void Apply(ITerrainSurface target, int x, int y, out TerrainOp op) { //todo: optimze this function. op = null; if (!CanApplyTo(target)) return; TerrainGob terrain = target.As<TerrainGob>(); ImageData hmImg = terrain.GetSurface(); Bound2di outRect; ComputeBound(hmImg, x, y, out outRect); if (!outRect.isValid || hmImg.Format != ImageDataFORMAT.R32_FLOAT) return; op = new TerrainOp(target, outRect); Func<int,int,float> getPixel = (px, py) => { px = MathUtil.Clamp(px, 0, hmImg.Width - 1); py = MathUtil.Clamp(py, 0, hmImg.Height - 1); float pixel = *(float*)hmImg.GetPixel(px, py); return pixel; }; Func<int, int, float> getSmoothPixel = (px, py) => { float r1 = getPixel(px - 1, py - 1) + 2.0f * getPixel(px, py - 1) + getPixel(px + 1, py - 1); float r2 = 2.0f * getPixel(px - 1, py) + 4.0f * getPixel(px, py) + 2.0f * getPixel(px + 1, py); float r3 = getPixel(px - 1, py + 1) + 2.0f * getPixel(px, py + 1) + getPixel(px + 1, py + 1); return ((r1 + r2 + r3) / 16.0f); }; m_templist.Clear(); for (int cy = outRect.y1; cy < outRect.y2; cy++) { for (int cx = outRect.x1; cx < outRect.x2; cx++) { m_templist.Add(getSmoothPixel(cx, cy)); } } // start point in kernel space. int bx0 = x - Radius; int by0 = y - Radius; int k = 0; int size = 2 * Radius + 1; for (int cy = outRect.y1; cy < outRect.y2; cy++) { int by = cy - by0; for (int cx = outRect.x1; cx < outRect.x2; cx++) { int bx = cx - bx0; float scrPixel = m_templist[k++]; float lerp = Kernel[size * by + bx]; float* destPixel = (float*)hmImg.GetPixel(cx, cy); *destPixel = Sce.Atf.MathUtil.Interp(lerp, *destPixel, scrPixel); } } terrain.ApplyDirtyRegion(outRect); }
public override void Apply(ITerrainSurface target, int x, int y, out TerrainOp op) { op = null; if (!CanApplyTo(target)) return; Bound2di outRect; TerrainMap tmap = target.As<TerrainMap>(); ImageData mask = tmap.GetSurface(); ComputeBound(mask, x, y, out outRect); bool validArgs = outRect.isValid && mask.Format == ImageDataFORMAT.R8_UNORM; System.Diagnostics.Debug.Assert(validArgs); if (validArgs == false) return; op = new TerrainOp(target, outRect); var brushOp = GetBrushOp(); float minheight = tmap.MinHeight; float maxheight = tmap.MaxHeight; float minslope = tmap.MinSlope; float maxslope = tmap.MaxSlope; ImageData hmImg = tmap.Parent.GetSurface(); float dx = (float)hmImg.Width / (float)mask.Width; float dy = (float)hmImg.Height / (float)mask.Height; int pixelstrength = (int)Math.Round(255.0f * Strength); Func<int, int, byte> ops = null; if (brushOp == BrushOps.Paint) { ops = (px, py) => { if (px >= pixelstrength) return (byte)px; else return (byte)Math.Min(pixelstrength, px + py); }; } else { ops = (px, py) => (byte)MathUtil.Clamp<int>(px - py, 0, 255); } // start point in kernel space. int bx0 = x - Radius; int by0 = y - Radius; float run = 2.0f * tmap.Parent.CellSize; int size = 2 * Radius + 1; for (int cy = outRect.y1; cy < outRect.y2; cy++) { int by = cy - by0; for (int cx = outRect.x1; cx < outRect.x2; cx++) { int bx = cx - bx0; // test for height and slope. // xform px and py to heightmap space hx, hy. if (brushOp == BrushOps.Paint) { int hx = (int)Math.Round(cx * dx); int hy = (int)Math.Round(cy * dy); float height = hmImg.GetPixelFloat(hx, hy); if (height < minheight || height > maxheight) { continue; } // check slope float slopex = hmImg.GetPixelFloat(hx + 1, hy) - hmImg.GetPixelFloat(hx - 1, hy); float slopeY = hmImg.GetPixelFloat(hx, hy + 1) - hmImg.GetPixelFloat(hx, hy - 1); float slope = Math.Max(Math.Abs(slopex), Math.Abs(slopeY)) / run; float deg = MathHelper.ToDegree((float)Math.Atan(slope)); if (deg < minslope || deg > maxslope) { continue; } } float scrPixel = Kernel[size * by + bx]; byte* destPixel = mask.GetPixel(cx, cy); *destPixel = ops(*destPixel, (int)Math.Round(scrPixel * 255.0f)); } } tmap.ApplyDirtyRegion(outRect); }
/// <summary> /// Apply this brush to target at the given coordinate /// output TerrainOp for undo/redo /// </summary> public abstract void Apply(ITerrainSurface target, int x, int y, out TerrainOp op);
public override void Apply(ITerrainSurface target, int x, int y, out TerrainOp op) { //todo: optimze this function. op = null; if (!CanApplyTo(target)) { return; } TerrainGob terrain = target.As <TerrainGob>(); ImageData hmImg = terrain.GetSurface(); Bound2di outRect; ComputeBound(hmImg, x, y, out outRect); if (!outRect.isValid || hmImg.Format != ImageDataFORMAT.R32_FLOAT) { return; } op = new TerrainOp(target, outRect); Func <int, int, float> getPixel = (px, py) => { px = MathUtil.Clamp(px, 0, hmImg.Width - 1); py = MathUtil.Clamp(py, 0, hmImg.Height - 1); float pixel = *(float *)hmImg.GetPixel(px, py); return(pixel); }; Func <int, int, float> getSmoothPixel = (px, py) => { float r1 = getPixel(px - 1, py - 1) + 2.0f * getPixel(px, py - 1) + getPixel(px + 1, py - 1); float r2 = 2.0f * getPixel(px - 1, py) + 4.0f * getPixel(px, py) + 2.0f * getPixel(px + 1, py); float r3 = getPixel(px - 1, py + 1) + 2.0f * getPixel(px, py + 1) + getPixel(px + 1, py + 1); return((r1 + r2 + r3) / 16.0f); }; m_templist.Clear(); for (int cy = outRect.y1; cy < outRect.y2; cy++) { for (int cx = outRect.x1; cx < outRect.x2; cx++) { m_templist.Add(getSmoothPixel(cx, cy)); } } // start point in kernel space. int bx0 = x - Radius; int by0 = y - Radius; int k = 0; int size = 2 * Radius + 1; for (int cy = outRect.y1; cy < outRect.y2; cy++) { int by = cy - by0; for (int cx = outRect.x1; cx < outRect.x2; cx++) { int bx = cx - bx0; float scrPixel = m_templist[k++]; float lerp = Kernel[size * by + bx]; float *destPixel = (float *)hmImg.GetPixel(cx, cy); * destPixel = Sce.Atf.MathUtil.Interp(lerp, *destPixel, scrPixel); } } terrain.ApplyDirtyRegion(outRect); }
public override void Apply(ITerrainSurface target, int x, int y, out TerrainOp op) { op = null; if (!CanApplyTo(target)) { return; } Bound2di outRect; TerrainMap tmap = target.As <TerrainMap>(); ImageData mask = tmap.GetSurface(); ComputeBound(mask, x, y, out outRect); bool validArgs = outRect.isValid && mask.Format == ImageDataFORMAT.R8_UNORM; System.Diagnostics.Debug.Assert(validArgs); if (validArgs == false) { return; } op = new TerrainOp(target, outRect); var brushOp = GetBrushOp(); float minheight = tmap.MinHeight; float maxheight = tmap.MaxHeight; float minslope = tmap.MinSlope; float maxslope = tmap.MaxSlope; ImageData hmImg = tmap.Parent.GetSurface(); float dx = (float)hmImg.Width / (float)mask.Width; float dy = (float)hmImg.Height / (float)mask.Height; int pixelstrength = (int)Math.Round(255.0f * Strength); Func <int, int, byte> ops = null; if (brushOp == BrushOps.Paint) { ops = (px, py) => { if (px >= pixelstrength) { return((byte)px); } else { return((byte)Math.Min(pixelstrength, px + py)); } }; } else { ops = (px, py) => (byte)MathUtil.Clamp <int>(px - py, 0, 255); } // start point in kernel space. int bx0 = x - Radius; int by0 = y - Radius; float run = 2.0f * tmap.Parent.CellSize; int size = 2 * Radius + 1; for (int cy = outRect.y1; cy < outRect.y2; cy++) { int by = cy - by0; for (int cx = outRect.x1; cx < outRect.x2; cx++) { int bx = cx - bx0; // test for height and slope. // xform px and py to heightmap space hx, hy. if (brushOp == BrushOps.Paint) { int hx = (int)Math.Round(cx * dx); int hy = (int)Math.Round(cy * dy); float height = hmImg.GetPixelFloat(hx, hy); if (height < minheight || height > maxheight) { continue; } // check slope float slopex = hmImg.GetPixelFloat(hx + 1, hy) - hmImg.GetPixelFloat(hx - 1, hy); float slopeY = hmImg.GetPixelFloat(hx, hy + 1) - hmImg.GetPixelFloat(hx, hy - 1); float slope = Math.Max(Math.Abs(slopex), Math.Abs(slopeY)) / run; float deg = MathHelper.ToDegree((float)Math.Atan(slope)); if (deg < minslope || deg > maxslope) { continue; } } float scrPixel = Kernel[size * by + bx]; byte *destPixel = mask.GetPixel(cx, cy); * destPixel = ops(*destPixel, (int)Math.Round(scrPixel * 255.0f)); } } tmap.ApplyDirtyRegion(outRect); }