void Draw(SplineResult[] points, ref float[,] drawLayer, ref float[,] alphaLayer) { List <SplineResult> selectedPoints = new List <SplineResult>(); Point last = new Point(); //Filter out points that are too close to each other for (int i = 0; i < points.Length; i++) { Point current = ToHeightmapCoords(points[i].position + points[i].normal * offset); if (i == 0 || i == points.Length - 1) { last = new Point(current.x, current.y); selectedPoints.Add(points[i]); } else if (Vector2.Distance(new Vector2(current.x, current.y), new Vector2(last.x, last.y)) >= 1.5f) { selectedPoints.Add(points[i]); last = new Point(current.x, current.y); } } if (selectedPoints.Count <= 1) { return; } TerrainPaintPoint[] paintPoints = new TerrainPaintPoint[selectedPoints.Count]; for (int i = 0; i < selectedPoints.Count; i++) { ConvertToPaintPoint(selectedPoints[i], ref paintPoints[i]); } //Paint the points for (int i = 0; i < paintPoints.Length - 1; i++) { hasChanges = true; PaintSegment(paintPoints[i], paintPoints[i + 1], ref drawLayer, ref alphaLayer); } SplineResult exResult = selectedPoints[0]; exResult.position += exResult.position - selectedPoints[1].position; TerrainPaintPoint exPoint = null; ConvertToPaintPoint(exResult, ref exPoint); PaintSegment(paintPoints[0], exPoint, ref drawLayer, ref alphaLayer, false, false); exResult = selectedPoints[selectedPoints.Count - 1]; exResult.position += exResult.position - selectedPoints[selectedPoints.Count - 2].position; ConvertToPaintPoint(exResult, ref exPoint); PaintSegment(paintPoints[paintPoints.Length - 1], exPoint, ref drawLayer, ref alphaLayer, false, false); //Extrapolate the ending and the begining }
TerrainPaintPoint ConvertToPaintPoint(SplineResult result, ref TerrainPaintPoint paintPoint) { paintPoint = new TerrainPaintPoint(); Vector3 right = -Vector3.Cross(result.direction, result.normal).normalized *size * 0.5f * result.size; Vector3 leftPoint = result.position - right + result.normal * offset; Vector3 rightPoint = result.position + right + result.normal * offset; paintPoint.center = ToHeightmapCoords(result.position + result.normal * offset); paintPoint.leftPoint = ToHeightmapCoords(leftPoint); paintPoint.rightPoint = ToHeightmapCoords(rightPoint); paintPoint.leftHeight = ToHeightmapValue(leftPoint.y); paintPoint.rightHeight = ToHeightmapValue(rightPoint.y); paintPoint.floatDiameter = Vector2.Distance(new Vector2(leftPoint.x, leftPoint.z), new Vector2(rightPoint.x, rightPoint.z)); if (paintPoint.leftHeight > maxDrawHeight) { maxDrawHeight = paintPoint.leftHeight; } if (paintPoint.rightHeight > maxDrawHeight) { maxDrawHeight = paintPoint.rightHeight; } return(paintPoint); }
void PaintSegment(TerrainPaintPoint fromPoint, TerrainPaintPoint toPoint, ref float[,] layer, ref float[,] alphaLayer, bool writeAlpha = true, bool overWriteHeight = true) { //Flip the points if the forward one has a bigger radius so the lerp can work well if (Vector2.Distance(fromPoint.leftPoint.vector, fromPoint.rightPoint.vector) < Vector2.Distance(toPoint.leftPoint.vector, toPoint.rightPoint.vector)) { TerrainPaintPoint temp = fromPoint; fromPoint = toPoint; toPoint = temp; } List <Point> drawn = new List <Point>(); Vector2 currentPosition = fromPoint.leftPoint.vector; Vector2 fromRight = fromPoint.rightPoint.vector; float alphaStartPercent = 0f; float alphaEndPercent = 1f; if (feather > 0) { currentPosition += (fromPoint.leftPoint.vector - fromPoint.center.vector).normalized * feather * 4f; fromRight += (fromPoint.rightPoint.vector - fromPoint.center.vector).normalized * feather * 4f; float span = (fromPoint.leftPoint.vector - fromPoint.rightPoint.vector).magnitude / (fromRight - currentPosition).magnitude; float rest = (1f - span) / 2f; alphaStartPercent = rest; alphaEndPercent = 1f - rest; } float armLength = Vector2.Distance(currentPosition, fromRight); if (armLength < 1f) { return; } while (true) { float armDistance = Vector2.Distance(currentPosition, fromRight); float armPercent = 1f - armDistance / armLength; //This can be optimized, take it outside of the cycle Point fromPos = new Point(currentPosition); Vector2 leftvector = toPoint.leftPoint.vector; Vector2 rightVector = toPoint.rightPoint.vector; if (feather > 0) { leftvector += (toPoint.leftPoint.vector - toPoint.center.vector).normalized * feather * 4f; rightVector += (toPoint.rightPoint.vector - toPoint.center.vector).normalized * feather * 4f; } Vector2 toArm = Vector2.Lerp(leftvector, rightVector, armPercent); Point toPos = new Point(toArm); int dx = Mathf.Abs(toPos.x - fromPos.x), sx = fromPos.x < toPos.x ? 1 : -1; int dy = -Mathf.Abs(toPos.y - fromPos.y), sy = fromPos.y < toPos.y ? 1 : -1; int err = dx + dy, e2; Point current = fromPos; Vector2 target = new Vector2(toPos.x - fromPos.x, toPos.y - fromPos.y); float fromHeight = fromPoint.GetHeight(armPercent); float toHeight = toPoint.GetHeight(armPercent); while (true) { if (current.x >= 0 && current.x < layer.GetLength(0) && current.y >= 0 && current.y < layer.GetLength(1)) { if (overWriteHeight || layer[current.x, current.y] == 0f) { if (!ContainsPoint(ref drawn, current)) { Vector2 currentDist = new Vector2(current.x - fromPos.x, current.y - fromPos.y); float positionPercent = Mathf.Clamp01(currentDist.magnitude / target.magnitude); float height = Mathf.Lerp(fromHeight, toHeight, positionPercent); float alphaValue = 0f; if (armPercent >= alphaStartPercent && armPercent <= alphaEndPercent) { alphaValue = 1f; } if (writeAlpha) { plot(current.x, current.y, height, alphaValue, ref alphaLayer, ref layer); } else { plot(current.x, current.y, height, alphaLayer[current.x, current.y], ref alphaLayer, ref layer); } drawn.Add(current); } } } if (current.x == toPos.x && current.y == toPos.y) { break; } e2 = 2 * err; if (e2 > dy) { err += dy; current.x += sx; } else if (e2 < dx) { err += dx; current.y += sy; } } if (currentPosition == fromRight) { break; } currentPosition = Vector2.MoveTowards(currentPosition, fromRight, 1f); } }