Don't recurse to size 2; only average corner of particular side you're on
The former makes things so much faster. omg.
This commit is contained in:
parent
240499ced8
commit
1a32b8e085
2 changed files with 92 additions and 82 deletions
|
@ -85,7 +85,7 @@ public class DiamondSquareGenerator: TerrainGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
var subdivisions: [Box] {
|
var subdivisions: [Box] {
|
||||||
guard size.w > 2 && size.h > 2 else {
|
guard size.w > 3 && size.h > 3 else {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
let halfSize = size.half
|
let halfSize = size.half
|
||||||
|
@ -159,16 +159,21 @@ public class DiamondSquareGenerator: TerrainGenerator {
|
||||||
heightMap[convert(pointToIndex: midpoint)] = midpointValue
|
heightMap[convert(pointToIndex: midpoint)] = midpointValue
|
||||||
|
|
||||||
// 2. Square step. For each of the side midpoints of this box, compute its value.
|
// 2. Square step. For each of the side midpoints of this box, compute its value.
|
||||||
for pt in box.sideMidpoints {
|
|
||||||
let corners = diamondCorners(forPoint: pt, diamondSize: box.size)
|
func updateHeight(for p: Point, a: Point, b: Point) {
|
||||||
let cornerValues = corners.map { (pt: Point) -> Float in
|
let aValue = heightMap[convert(pointToIndex: a)]
|
||||||
let idx = self.convert(pointToIndex: pt)
|
let bValue = heightMap[convert(pointToIndex: b)]
|
||||||
return heightMap[idx]
|
let avg = 0.5 * (aValue + bValue)
|
||||||
}
|
let rand = Float.random(in: spread)
|
||||||
let ptValue = Float.random(in: spread) + self.average(ofPoints: cornerValues)
|
let value = avg + rand
|
||||||
heightMap[convert(pointToIndex: pt)] = ptValue
|
heightMap[convert(pointToIndex: p)] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateHeight(for: box.north, a: box.northeast, b: box.northwest)
|
||||||
|
updateHeight(for: box.west, a: box.northwest, b: box.southwest)
|
||||||
|
updateHeight(for: box.south, a: box.southwest, b: box.southeast)
|
||||||
|
updateHeight(for: box.east, a: box.southeast, b: box.northeast)
|
||||||
|
|
||||||
if box.size != boxSize {
|
if box.size != boxSize {
|
||||||
// Reduce the spread as we recurse down to smaller squares.
|
// Reduce the spread as we recurse down to smaller squares.
|
||||||
spread = -(spread.lowerBound * 0.5)...(spread.upperBound * 0.5)
|
spread = -(spread.lowerBound * 0.5)...(spread.upperBound * 0.5)
|
||||||
|
@ -182,25 +187,30 @@ public class DiamondSquareGenerator: TerrainGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find our diamond's corners, wrapping around the grid if needed.
|
/// Find our diamond's corners, wrapping around the grid if needed.
|
||||||
func diamondCorners(forPoint pt: Point, diamondSize: Size) -> [Point] {
|
// func diamondCorners(forPoint pt: Point, diamondSize: Size) -> [Point] {
|
||||||
let halfSize = diamondSize.half
|
// let halfSize = diamondSize.half
|
||||||
var corners = [Point(x: pt.x, y: pt.y - halfSize.h),
|
//
|
||||||
Point(x: pt.x - halfSize.w, y: pt.y),
|
// func ptIsValid(pt: Point) -> Bool {
|
||||||
Point(x: pt.x, y: pt.y + halfSize.h),
|
// return pt.x >= origin.x && pt.x < size.w && pt.y >= origin.y && pt.y < size.h
|
||||||
Point(x: pt.x + halfSize.w, y: pt.y)]
|
// }
|
||||||
for i in 0..<corners.count {
|
//
|
||||||
if corners[i].x < 0 {
|
// var corners = [Point(x: pt.x, y: pt.y - halfSize.h),
|
||||||
corners[i].x += grid.size.w - 1
|
// Point(x: pt.x - halfSize.w, y: pt.y),
|
||||||
} else if corners[i].x >= grid.size.w {
|
// Point(x: pt.x, y: pt.y + halfSize.h),
|
||||||
corners[i].x -= grid.size.w - 1
|
// Point(x: pt.x + halfSize.w, y: pt.y)].filter(ptIsValid)
|
||||||
} else if corners[i].y < 0 {
|
// for i in 0..<corners.count {
|
||||||
corners[i].y += grid.size.h - 1
|
// if corners[i].x < 0 {
|
||||||
} else if corners[i].y >= grid.size.h {
|
// corners[i].x += grid.size.w - 1
|
||||||
corners[i].y -= grid.size.h - 1
|
// } else if corners[i].x >= grid.size.w {
|
||||||
}
|
// corners[i].x -= grid.size.w - 1
|
||||||
}
|
// } else if corners[i].y < 0 {
|
||||||
return corners
|
// corners[i].y += grid.size.h - 1
|
||||||
}
|
// } else if corners[i].y >= grid.size.h {
|
||||||
|
// corners[i].y -= grid.size.h - 1
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return corners
|
||||||
|
// }
|
||||||
|
|
||||||
func average(ofPoints pts: [Float]) -> Float {
|
func average(ofPoints pts: [Float]) -> Float {
|
||||||
let scale: Float = 1.0 / Float(pts.count)
|
let scale: Float = 1.0 / Float(pts.count)
|
||||||
|
|
|
@ -38,41 +38,41 @@ class DiamondSquareAlgorithmTests: XCTestCase {
|
||||||
|
|
||||||
// MARK: Diamond Corners
|
// MARK: Diamond Corners
|
||||||
|
|
||||||
func testDiamondCornersNorth() {
|
// func testDiamondCornersNorth() {
|
||||||
let corners = alg.diamondCorners(forPoint: Point(x: 2, y: 0), diamondSize: grid.size)
|
// let corners = alg.diamondCorners(forPoint: Point(x: 2, y: 0), diamondSize: grid.size)
|
||||||
XCTAssertEqual(corners.count, 4)
|
// XCTAssertEqual(corners.count, 4)
|
||||||
XCTAssertEqual(corners[0], Point(x: 2, y: 2))
|
// XCTAssertEqual(corners[0], Point(x: 2, y: 2))
|
||||||
XCTAssertEqual(corners[1], Point(x: 0, y: 0))
|
// XCTAssertEqual(corners[1], Point(x: 0, y: 0))
|
||||||
XCTAssertEqual(corners[2], Point(x: 2, y: 2))
|
// XCTAssertEqual(corners[2], Point(x: 2, y: 2))
|
||||||
XCTAssertEqual(corners[3], Point(x: 4, y: 0))
|
// XCTAssertEqual(corners[3], Point(x: 4, y: 0))
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
func testDiamondCornersWest() {
|
// func testDiamondCornersWest() {
|
||||||
let corners = alg.diamondCorners(forPoint: Point(x: 0, y: 2), diamondSize: grid.size)
|
// let corners = alg.diamondCorners(forPoint: Point(x: 0, y: 2), diamondSize: grid.size)
|
||||||
XCTAssertEqual(corners.count, 4)
|
// XCTAssertEqual(corners.count, 4)
|
||||||
XCTAssertEqual(corners[0], Point(x: 0, y: 0))
|
// XCTAssertEqual(corners[0], Point(x: 0, y: 0))
|
||||||
XCTAssertEqual(corners[1], Point(x: 2, y: 2))
|
// XCTAssertEqual(corners[1], Point(x: 2, y: 2))
|
||||||
XCTAssertEqual(corners[2], Point(x: 0, y: 4))
|
// XCTAssertEqual(corners[2], Point(x: 0, y: 4))
|
||||||
XCTAssertEqual(corners[3], Point(x: 2, y: 2))
|
// XCTAssertEqual(corners[3], Point(x: 2, y: 2))
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
func testDiamondCornersSouth() {
|
// func testDiamondCornersSouth() {
|
||||||
let corners = alg.diamondCorners(forPoint: Point(x: 2, y: 4), diamondSize: grid.size)
|
// let corners = alg.diamondCorners(forPoint: Point(x: 2, y: 4), diamondSize: grid.size)
|
||||||
XCTAssertEqual(corners.count, 4)
|
// XCTAssertEqual(corners.count, 4)
|
||||||
XCTAssertEqual(corners[0], Point(x: 2, y: 2))
|
// XCTAssertEqual(corners[0], Point(x: 2, y: 2))
|
||||||
XCTAssertEqual(corners[1], Point(x: 0, y: 4))
|
// XCTAssertEqual(corners[1], Point(x: 0, y: 4))
|
||||||
XCTAssertEqual(corners[2], Point(x: 2, y: 2))
|
// XCTAssertEqual(corners[2], Point(x: 2, y: 2))
|
||||||
XCTAssertEqual(corners[3], Point(x: 4, y: 4))
|
// XCTAssertEqual(corners[3], Point(x: 4, y: 4))
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
func testDiamondCornersEast() {
|
// func testDiamondCornersEast() {
|
||||||
let corners = alg.diamondCorners(forPoint: Point(x: 4, y: 2), diamondSize: grid.size)
|
// let corners = alg.diamondCorners(forPoint: Point(x: 4, y: 2), diamondSize: grid.size)
|
||||||
XCTAssertEqual(corners.count, 4)
|
// XCTAssertEqual(corners.count, 4)
|
||||||
XCTAssertEqual(corners[0], Point(x: 4, y: 0))
|
// XCTAssertEqual(corners[0], Point(x: 4, y: 0))
|
||||||
XCTAssertEqual(corners[1], Point(x: 2, y: 2))
|
// XCTAssertEqual(corners[1], Point(x: 2, y: 2))
|
||||||
XCTAssertEqual(corners[2], Point(x: 4, y: 4))
|
// XCTAssertEqual(corners[2], Point(x: 4, y: 4))
|
||||||
XCTAssertEqual(corners[3], Point(x: 2, y: 2))
|
// XCTAssertEqual(corners[3], Point(x: 2, y: 2))
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
class DiamondSquareBoxTests: XCTestCase {
|
class DiamondSquareBoxTests: XCTestCase {
|
||||||
|
@ -102,25 +102,25 @@ class DiamondSquareBoxTests: XCTestCase {
|
||||||
Box(origin: Point(x: 0, y: 2), size: Size(w: 3, h: 3)),
|
Box(origin: Point(x: 0, y: 2), size: Size(w: 3, h: 3)),
|
||||||
Box(origin: Point(x: 2, y: 2), size: Size(w: 3, h: 3)),
|
Box(origin: Point(x: 2, y: 2), size: Size(w: 3, h: 3)),
|
||||||
|
|
||||||
Box(origin: Point(x: 0, y: 0), size: Size(w: 2, h: 2)),
|
// Box(origin: Point(x: 0, y: 0), size: Size(w: 2, h: 2)),
|
||||||
Box(origin: Point(x: 1, y: 0), size: Size(w: 2, h: 2)),
|
// Box(origin: Point(x: 1, y: 0), size: Size(w: 2, h: 2)),
|
||||||
Box(origin: Point(x: 0, y: 1), size: Size(w: 2, h: 2)),
|
// Box(origin: Point(x: 0, y: 1), size: Size(w: 2, h: 2)),
|
||||||
Box(origin: Point(x: 1, y: 1), size: Size(w: 2, h: 2)),
|
// Box(origin: Point(x: 1, y: 1), size: Size(w: 2, h: 2)),
|
||||||
|
//
|
||||||
Box(origin: Point(x: 2, y: 0), size: Size(w: 2, h: 2)),
|
// Box(origin: Point(x: 2, y: 0), size: Size(w: 2, h: 2)),
|
||||||
Box(origin: Point(x: 3, y: 0), size: Size(w: 2, h: 2)),
|
// Box(origin: Point(x: 3, y: 0), size: Size(w: 2, h: 2)),
|
||||||
Box(origin: Point(x: 2, y: 1), size: Size(w: 2, h: 2)),
|
// Box(origin: Point(x: 2, y: 1), size: Size(w: 2, h: 2)),
|
||||||
Box(origin: Point(x: 3, y: 1), size: Size(w: 2, h: 2)),
|
// Box(origin: Point(x: 3, y: 1), size: Size(w: 2, h: 2)),
|
||||||
|
//
|
||||||
Box(origin: Point(x: 0, y: 2), size: Size(w: 2, h: 2)),
|
// Box(origin: Point(x: 0, y: 2), size: Size(w: 2, h: 2)),
|
||||||
Box(origin: Point(x: 1, y: 2), size: Size(w: 2, h: 2)),
|
// Box(origin: Point(x: 1, y: 2), size: Size(w: 2, h: 2)),
|
||||||
Box(origin: Point(x: 0, y: 3), size: Size(w: 2, h: 2)),
|
// Box(origin: Point(x: 0, y: 3), size: Size(w: 2, h: 2)),
|
||||||
Box(origin: Point(x: 1, y: 3), size: Size(w: 2, h: 2)),
|
// Box(origin: Point(x: 1, y: 3), size: Size(w: 2, h: 2)),
|
||||||
|
//
|
||||||
Box(origin: Point(x: 2, y: 2), size: Size(w: 2, h: 2)),
|
// Box(origin: Point(x: 2, y: 2), size: Size(w: 2, h: 2)),
|
||||||
Box(origin: Point(x: 3, y: 2), size: Size(w: 2, h: 2)),
|
// Box(origin: Point(x: 3, y: 2), size: Size(w: 2, h: 2)),
|
||||||
Box(origin: Point(x: 2, y: 3), size: Size(w: 2, h: 2)),
|
// Box(origin: Point(x: 2, y: 3), size: Size(w: 2, h: 2)),
|
||||||
Box(origin: Point(x: 3, y: 3), size: Size(w: 2, h: 2)),
|
// Box(origin: Point(x: 3, y: 3), size: Size(w: 2, h: 2)),
|
||||||
].reversed()
|
].reversed()
|
||||||
|
|
||||||
let prog = Progress(totalUnitCount: 1)
|
let prog = Progress(totalUnitCount: 1)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue