public override void OnUpdateModelPositions(TerrainChangeParameters parameters) { var center = new Vector2(parameters.Center.X, parameters.Center.Y); foreach (var inst in DoodadInstances) { if (inst == null || inst.RenderInstance == null) { continue; } var pos = mDoodadDefs[inst.MddfIndex].Position; var invZ = 64.0f * Metrics.TileSize - pos.Z; var dist = (new Vector2(pos.X, invZ) - center).Length(); if (dist > parameters.OuterRadius) { continue; } if (WorldFrame.Instance.MapManager.GetLandHeight(pos.X, pos.Z, out pos.Y)) { mDoodadDefs[inst.MddfIndex].Position = pos; inst.RenderInstance.UpdatePosition(new Vector3(pos.X, invZ, pos.Y)); } } }
private bool HandleElevateTerrain(TerrainChangeParameters parameters) { var amount = parameters.Amount * (float)parameters.TimeDiff.TotalSeconds; var changed = false; var radius = parameters.OuterRadius; for (var i = 0; i < 145; ++i) { var p = Vertices[i].Position; var dist = (new Vector2(p.X, p.Y) - new Vector2(parameters.Center.X, parameters.Center.Y)).Length(); if (dist > radius) { continue; } changed = true; var factor = dist / radius; switch (parameters.Algorithm) { case TerrainAlgorithm.Flat: p.Z += amount * (parameters.Inverted ? -1 : 1); break; case TerrainAlgorithm.Linear: p.Z += (amount * (1.0f - factor)) * (parameters.Inverted ? -1 : 1); break; case TerrainAlgorithm.Quadratic: p.Z += (((-amount) / (radius * radius) * (dist * dist)) + amount) * (parameters.Inverted ? -1 : 1); break; case TerrainAlgorithm.Trigonometric: var cs = Math.Cos(factor * Math.PI / 2); p.Z += (amount * (float)cs) * (parameters.Inverted ? -1 : 1); break; } if (p.Z < mMinHeight) { mMinHeight = p.Z; } if (p.Z > mMaxHeight) { mMaxHeight = p.Z; } Vertices[i].Position = p; } return(changed); }
public override bool OnChangeTerrain(TerrainChangeParameters parameters) { var changed = false; foreach (var chunk in mChunks) { if (chunk == null) continue; if (chunk.OnTerrainChange(parameters)) changed = true; } if (changed) mWasChanged = true; return changed; }
public virtual bool OnTerrainChange(TerrainChangeParameters parameters) { var diffVec = new Vector2(mMidPoint.X, mMidPoint.Y) - new Vector2(parameters.Center.X, parameters.Center.Y); var dsquare = Vector2.Dot(diffVec, diffVec); var maxRadius = parameters.OuterRadius + Metrics.ChunkRadius; if (dsquare > maxRadius * maxRadius) { return(false); } // always update the normals if we are closer than ChunkRadius to the modified area // since nearby changes might affect the normals of this chunk even if the positions // them self didn't change mUpdateNormals = true; var changed = false; switch (parameters.Method) { case TerrainChangeType.Elevate: changed = HandleElevateTerrain(parameters); break; case TerrainChangeType.Flatten: changed = HandleFlatten(parameters); break; case TerrainChangeType.Blur: changed = HandleBlur(parameters); break; case TerrainChangeType.Shading: changed = HandleMccvPaint(parameters); break; } return(changed); }
public override bool OnTerrainChange(TerrainChangeParameters parameters) { var changed = base.OnTerrainChange(parameters); if (changed) { MapArea parent; mParent.TryGetTarget(out parent); var omin = BoundingBox.Minimum; var omax = BoundingBox.Maximum; BoundingBox = new BoundingBox(new Vector3(omin.X, omin.Y, mMinHeight), new Vector3(omax.X, omax.Y, mMaxHeight)); if (parent != null) { parent.UpdateBoundingBox(BoundingBox); } } return(changed); }
protected override bool HandleMccvPaint(TerrainChangeParameters parameters) { var amount = (parameters.Amount / 75.0f) * (float)parameters.TimeDiff.TotalSeconds; var changed = false; var destColor = parameters.Shading; if (parameters.Inverted) { destColor.X = 2 - destColor.X; destColor.Y = 2 - destColor.Y; destColor.Z = 2 - destColor.Z; } var radius = parameters.OuterRadius; for (var i = 0; i < 145; ++i) { var p = Vertices[i].Position; var dist = (new Vector2(p.X, p.Y) - new Vector2(parameters.Center.X, parameters.Center.Y)).Length(); if (dist > radius) { continue; } HasMccv = true; changed = true; var factor = dist / radius; if (dist < parameters.InnerRadius) { factor = 1.0f; } var curColor = mShadingFloats[i]; var dr = destColor.X - curColor.Z; var dg = destColor.Y - curColor.Y; var db = destColor.Z - curColor.X; var cr = Math.Min(Math.Abs(dr), amount * factor); var cg = Math.Min(Math.Abs(dg), amount * factor); var cb = Math.Min(Math.Abs(db), amount * factor); if (dr < 0) { curColor.Z -= cr; if (curColor.Z < destColor.X) { curColor.Z = destColor.X; } } else { curColor.Z += cr; if (curColor.Z > destColor.X) { curColor.Z = destColor.X; } } if (dg < 0) { curColor.Y -= cg; if (curColor.Y < destColor.Y) { curColor.Y = destColor.Y; } } else { curColor.Y += cg; if (curColor.Y > destColor.Y) { curColor.Y = destColor.Y; } } if (db < 0) { curColor.X -= cb; if (curColor.X < destColor.Z) { curColor.X = destColor.Z; } } else { curColor.X += cb; if (curColor.X > destColor.Z) { curColor.X = destColor.Z; } } mShadingFloats[i] = curColor; curColor.X = Math.Min(Math.Max(curColor.X, 0), 2); curColor.Y = Math.Min(Math.Max(curColor.Y, 0), 2); curColor.Z = Math.Min(Math.Max(curColor.Z, 0), 2); var r = (byte)((curColor.Z / 2.0f) * 255.0f); var g = (byte)((curColor.Y / 2.0f) * 255.0f); var b = (byte)((curColor.X / 2.0f) * 255.0f); var a = (byte)((curColor.W / 2.0f) * 255.0f); var color = (uint)((a << 24) | (r << 16) | (g << 8) | b); Vertices[i].Color = color; } return(changed); }
private bool HandleFlatten(TerrainChangeParameters parameters) { var radius = parameters.OuterRadius; var amount = parameters.Amount / 550.0f; if (amount > 1) { amount = 1; } amount = 1 - amount; var changed = false; for (var i = 0; i < 145; ++i) { var p = Vertices[i].Position; var dist = (new Vector2(p.X, p.Y) - new Vector2(parameters.Center.X, parameters.Center.Y)).Length(); if (dist > radius) { continue; } changed = true; var factor = dist / radius; switch (parameters.Algorithm) { case TerrainAlgorithm.Flat: p.Z = amount * p.Z + (1 - amount) * parameters.Center.Z; break; case TerrainAlgorithm.Linear: { var nremain = 1 - (1 - amount) * (1 - factor); p.Z = nremain * p.Z + (1 - nremain) * parameters.Center.Z; break; } case TerrainAlgorithm.Quadratic: { var nremain = 1 - (float)Math.Pow(1 - amount, 1 + factor); p.Z = nremain * p.Z + (1 - nremain) * parameters.Center.Z; break; } case TerrainAlgorithm.Trigonometric: { var nremain = 1 - (1 - amount) * (1 - (float)Math.Cos(factor * Math.PI / 2.0f)); p.Z = nremain * p.Z + (1 - nremain) * parameters.Center.Z; break; } } if (p.Z < mMinHeight) { mMinHeight = p.Z; } if (p.Z > mMaxHeight) { mMaxHeight = p.Z; } Vertices[i].Position = p; } return(changed); }
private bool HandleBlur(TerrainChangeParameters parameters) { var radius = parameters.OuterRadius; var amount = parameters.Amount / 550.0f; if (amount > 1) { amount = 1; } amount = 1 - amount; var changed = false; for (var i = 0; i < 145; ++i) { var p = Vertices[i].Position; var dist = (new Vector2(p.X, p.Y) - new Vector2(parameters.Center.X, parameters.Center.Y)).Length(); if (dist > radius) { continue; } changed = true; var totalHeight = 0.0f; var totalWeight = 0.0f; var rad = (int)(radius / Metrics.UnitSize); for (var j = -rad; j <= rad; ++j) { var ty = parameters.Center.Y + j * Metrics.UnitSize; for (var k = -rad; k <= rad; ++k) { var tx = parameters.Center.X + k * Metrics.UnitSize; var xdiff = tx - p.X; var ydiff = ty - p.Y; var diff = xdiff * xdiff + ydiff * ydiff; if (diff > radius * radius) { continue; } float height; if (WorldFrame.Instance.MapManager.GetLandHeight(tx, 64.0f * Metrics.TileSize - ty, out height) == false) { height = p.Z; } var dist2 = (float)Math.Sqrt(diff); totalHeight += (1 - dist2 / radius) * height; totalWeight += (1 - dist2 / radius); } } var h = totalHeight / totalWeight; switch (parameters.Algorithm) { case TerrainAlgorithm.Flat: p.Z = amount * p.Z + (1 - amount) * h; break; case TerrainAlgorithm.Linear: { var nremain = 1 - (1 - amount) * (1 - dist / radius); p.Z = nremain * p.Z + (1 - nremain) * h; } break; case TerrainAlgorithm.Quadratic: { var nremain = 1 - (float)Math.Pow(1 - amount, 1 + dist / radius); p.Z = nremain * p.Z + (1 - nremain) * h; } break; case TerrainAlgorithm.Trigonometric: { var nremain = 1 - (1 - amount) * (float)Math.Cos(dist / radius); p.Z = nremain * p.Z + (1 - nremain) * h; } break; } if (p.Z < mMinHeight) { mMinHeight = p.Z; } if (p.Z > mMaxHeight) { mMaxHeight = p.Z; } Vertices[i].Position = p; } return(changed); }
protected abstract bool HandleMccvPaint(TerrainChangeParameters parameters);