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] { | ||||
|             guard size.w > 2 && size.h > 2 else { | ||||
|             guard size.w > 3 && size.h > 3 else { | ||||
|                 return [] | ||||
|             } | ||||
|             let halfSize = size.half | ||||
|  | @ -159,16 +159,21 @@ public class DiamondSquareGenerator: TerrainGenerator { | |||
|                 heightMap[convert(pointToIndex: midpoint)] = midpointValue | ||||
| 
 | ||||
|                 // 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) | ||||
|                     let cornerValues = corners.map { (pt: Point) -> Float in | ||||
|                         let idx = self.convert(pointToIndex: pt) | ||||
|                         return heightMap[idx] | ||||
|                     } | ||||
|                     let ptValue = Float.random(in: spread) + self.average(ofPoints: cornerValues) | ||||
|                     heightMap[convert(pointToIndex: pt)] = ptValue | ||||
| 
 | ||||
|                 func updateHeight(for p: Point, a: Point, b: Point) { | ||||
|                     let aValue = heightMap[convert(pointToIndex: a)] | ||||
|                     let bValue = heightMap[convert(pointToIndex: b)] | ||||
|                     let avg = 0.5 * (aValue + bValue) | ||||
|                     let rand = Float.random(in: spread) | ||||
|                     let value = avg + rand | ||||
|                     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 { | ||||
|                     // Reduce the spread as we recurse down to smaller squares. | ||||
|                     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. | ||||
|         func diamondCorners(forPoint pt: Point, diamondSize: Size) -> [Point] { | ||||
|             let halfSize = diamondSize.half | ||||
|             var corners = [Point(x: pt.x, y: pt.y - halfSize.h), | ||||
|                            Point(x: pt.x - halfSize.w, y: pt.y), | ||||
|                            Point(x: pt.x, y: pt.y + halfSize.h), | ||||
|                            Point(x: pt.x + halfSize.w, y: pt.y)] | ||||
|             for i in 0..<corners.count { | ||||
|                 if corners[i].x < 0 { | ||||
|                     corners[i].x += grid.size.w - 1 | ||||
|                 } else if corners[i].x >= grid.size.w { | ||||
|                     corners[i].x -= grid.size.w - 1 | ||||
|                 } else if corners[i].y < 0 { | ||||
|                     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 diamondCorners(forPoint pt: Point, diamondSize: Size) -> [Point] { | ||||
| //            let halfSize = diamondSize.half | ||||
| // | ||||
| //            func ptIsValid(pt: Point) -> Bool { | ||||
| //                return pt.x >= origin.x && pt.x < size.w && pt.y >= origin.y && pt.y < size.h | ||||
| //            } | ||||
| // | ||||
| //            var corners = [Point(x: pt.x, y: pt.y - halfSize.h), | ||||
| //                           Point(x: pt.x - halfSize.w, y: pt.y), | ||||
| //                           Point(x: pt.x, y: pt.y + halfSize.h), | ||||
| //                           Point(x: pt.x + halfSize.w, y: pt.y)].filter(ptIsValid) | ||||
| //            for i in 0..<corners.count { | ||||
| //                if corners[i].x < 0 { | ||||
| //                    corners[i].x += grid.size.w - 1 | ||||
| //                } else if corners[i].x >= grid.size.w { | ||||
| //                    corners[i].x -= grid.size.w - 1 | ||||
| //                } else if corners[i].y < 0 { | ||||
| //                    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 { | ||||
|             let scale: Float = 1.0 / Float(pts.count) | ||||
|  |  | |||
|  | @ -38,41 +38,41 @@ class DiamondSquareAlgorithmTests: XCTestCase { | |||
| 
 | ||||
|     // MARK: Diamond Corners | ||||
| 
 | ||||
|     func testDiamondCornersNorth() { | ||||
|         let corners = alg.diamondCorners(forPoint: Point(x: 2, y: 0), diamondSize: grid.size) | ||||
|         XCTAssertEqual(corners.count, 4) | ||||
|         XCTAssertEqual(corners[0], Point(x: 2, y: 2)) | ||||
|         XCTAssertEqual(corners[1], Point(x: 0, y: 0)) | ||||
|         XCTAssertEqual(corners[2], Point(x: 2, y: 2)) | ||||
|         XCTAssertEqual(corners[3], Point(x: 4, y: 0)) | ||||
|     } | ||||
| 
 | ||||
|     func testDiamondCornersWest() { | ||||
|         let corners = alg.diamondCorners(forPoint: Point(x: 0, y: 2), diamondSize: grid.size) | ||||
|         XCTAssertEqual(corners.count, 4) | ||||
|         XCTAssertEqual(corners[0], Point(x: 0, y: 0)) | ||||
|         XCTAssertEqual(corners[1], Point(x: 2, y: 2)) | ||||
|         XCTAssertEqual(corners[2], Point(x: 0, y: 4)) | ||||
|         XCTAssertEqual(corners[3], Point(x: 2, y: 2)) | ||||
|     } | ||||
| 
 | ||||
|     func testDiamondCornersSouth() { | ||||
|         let corners = alg.diamondCorners(forPoint: Point(x: 2, y: 4), diamondSize: grid.size) | ||||
|         XCTAssertEqual(corners.count, 4) | ||||
|         XCTAssertEqual(corners[0], Point(x: 2, y: 2)) | ||||
|         XCTAssertEqual(corners[1], Point(x: 0, y: 4)) | ||||
|         XCTAssertEqual(corners[2], Point(x: 2, y: 2)) | ||||
|         XCTAssertEqual(corners[3], Point(x: 4, y: 4)) | ||||
|     } | ||||
| 
 | ||||
|     func testDiamondCornersEast() { | ||||
|         let corners = alg.diamondCorners(forPoint: Point(x: 4, y: 2), diamondSize: grid.size) | ||||
|         XCTAssertEqual(corners.count, 4) | ||||
|         XCTAssertEqual(corners[0], Point(x: 4, y: 0)) | ||||
|         XCTAssertEqual(corners[1], Point(x: 2, y: 2)) | ||||
|         XCTAssertEqual(corners[2], Point(x: 4, y: 4)) | ||||
|         XCTAssertEqual(corners[3], Point(x: 2, y: 2)) | ||||
|     } | ||||
| //    func testDiamondCornersNorth() { | ||||
| //        let corners = alg.diamondCorners(forPoint: Point(x: 2, y: 0), diamondSize: grid.size) | ||||
| //        XCTAssertEqual(corners.count, 4) | ||||
| //        XCTAssertEqual(corners[0], Point(x: 2, y: 2)) | ||||
| //        XCTAssertEqual(corners[1], Point(x: 0, y: 0)) | ||||
| //        XCTAssertEqual(corners[2], Point(x: 2, y: 2)) | ||||
| //        XCTAssertEqual(corners[3], Point(x: 4, y: 0)) | ||||
| //    } | ||||
| // | ||||
| //    func testDiamondCornersWest() { | ||||
| //        let corners = alg.diamondCorners(forPoint: Point(x: 0, y: 2), diamondSize: grid.size) | ||||
| //        XCTAssertEqual(corners.count, 4) | ||||
| //        XCTAssertEqual(corners[0], Point(x: 0, y: 0)) | ||||
| //        XCTAssertEqual(corners[1], Point(x: 2, y: 2)) | ||||
| //        XCTAssertEqual(corners[2], Point(x: 0, y: 4)) | ||||
| //        XCTAssertEqual(corners[3], Point(x: 2, y: 2)) | ||||
| //    } | ||||
| // | ||||
| //    func testDiamondCornersSouth() { | ||||
| //        let corners = alg.diamondCorners(forPoint: Point(x: 2, y: 4), diamondSize: grid.size) | ||||
| //        XCTAssertEqual(corners.count, 4) | ||||
| //        XCTAssertEqual(corners[0], Point(x: 2, y: 2)) | ||||
| //        XCTAssertEqual(corners[1], Point(x: 0, y: 4)) | ||||
| //        XCTAssertEqual(corners[2], Point(x: 2, y: 2)) | ||||
| //        XCTAssertEqual(corners[3], Point(x: 4, y: 4)) | ||||
| //    } | ||||
| // | ||||
| //    func testDiamondCornersEast() { | ||||
| //        let corners = alg.diamondCorners(forPoint: Point(x: 4, y: 2), diamondSize: grid.size) | ||||
| //        XCTAssertEqual(corners.count, 4) | ||||
| //        XCTAssertEqual(corners[0], Point(x: 4, y: 0)) | ||||
| //        XCTAssertEqual(corners[1], Point(x: 2, y: 2)) | ||||
| //        XCTAssertEqual(corners[2], Point(x: 4, y: 4)) | ||||
| //        XCTAssertEqual(corners[3], Point(x: 2, y: 2)) | ||||
| //    } | ||||
| } | ||||
| 
 | ||||
| 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: 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: 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: 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: 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: 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: 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: 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: 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: 3, y: 3), 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: 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: 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: 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: 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: 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: 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: 2, y: 3), size: Size(w: 2, h: 2)), | ||||
| //            Box(origin: Point(x: 3, y: 3), size: Size(w: 2, h: 2)), | ||||
|         ].reversed() | ||||
| 
 | ||||
|         let prog = Progress(totalUnitCount: 1) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue