Match vanilla ore sphere math
This commit is contained in:
parent
c68c5c2744
commit
cb60050801
5 changed files with 110 additions and 114 deletions
|
|
@ -108,12 +108,37 @@ func flattenBlockTag(set *worldgen.FeatureSet, tag string, visiting map[string]b
|
|||
}
|
||||
|
||||
func placeOreEllipsoid(c *Chunk, random worldgen.RandomSource, originX, originY, originZ, size int, discard float64, targets []resolvedOreTarget) {
|
||||
spheres := buildOreSpheres(random, originX, originY, originZ, size)
|
||||
walkOreBlocks(spheres, func(x, y, z int) {
|
||||
localX := x - int(c.X)*16
|
||||
if localX < 0 || localX >= 16 {
|
||||
return
|
||||
}
|
||||
if y < MinY || y >= MinY+WorldHeight {
|
||||
return
|
||||
}
|
||||
localZ := z - int(c.Z)*16
|
||||
if localZ < 0 || localZ >= 16 {
|
||||
return
|
||||
}
|
||||
current := c.GetBlock(localX, y, localZ)
|
||||
for _, target := range targets {
|
||||
if !target.replaceables[current] || discard > 0 && random.NextFloat() < float32(discard) && exposedToAir(c, localX, y, localZ) {
|
||||
continue
|
||||
}
|
||||
c.SetBlock(localX, y, localZ, target.state)
|
||||
break
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func buildOreSpheres(random worldgen.RandomSource, originX, originY, originZ, size int) []oreSphere {
|
||||
angle := random.NextFloat() * float32(math.Pi)
|
||||
extent := float32(size) / 8.0
|
||||
x0 := float64(originX) + math.Sin(float64(angle))*float64(extent)
|
||||
x1 := float64(originX) - math.Sin(float64(angle))*float64(extent)
|
||||
z0 := float64(originZ) + math.Cos(float64(angle))*float64(extent)
|
||||
z1 := float64(originZ) - math.Cos(float64(angle))*float64(extent)
|
||||
x0 := float64(originX) + float64(worldgen.MthSin(float64(angle))*extent)
|
||||
x1 := float64(originX) - float64(worldgen.MthSin(float64(angle))*extent)
|
||||
z0 := float64(originZ) + float64(worldgen.MthCos(float64(angle))*extent)
|
||||
z1 := float64(originZ) - float64(worldgen.MthCos(float64(angle))*extent)
|
||||
y0 := float64(originY + int(random.NextIntN(3)) - 2)
|
||||
y1 := float64(originY + int(random.NextIntN(3)) - 2)
|
||||
|
||||
|
|
@ -121,7 +146,8 @@ func placeOreEllipsoid(c *Chunk, random worldgen.RandomSource, originX, originY,
|
|||
for i := 0; i < size; i++ {
|
||||
t := float32(i) / float32(size)
|
||||
randomScale := random.NextDouble() * float64(size) / 16.0
|
||||
radius := ((float64(worldgen.MthSin(float64(float32(math.Pi)*t)))+1.0)*randomScale + 1.0) / 2.0
|
||||
wave := worldgen.MthSin(float64(float32(math.Pi)*t)) + float32(1.0)
|
||||
radius := (float64(wave)*randomScale + 1.0) / 2.0
|
||||
spheres[i] = oreSphere{
|
||||
x: x0 + (x1-x0)*float64(t),
|
||||
y: y0 + (y1-y0)*float64(t),
|
||||
|
|
@ -149,35 +175,35 @@ func placeOreEllipsoid(c *Chunk, random worldgen.RandomSource, originX, originY,
|
|||
}
|
||||
}
|
||||
}
|
||||
walkOreBlocks(spheres, func(x, y, z int) {
|
||||
localX := x - int(c.X)*16
|
||||
if localX < 0 || localX >= 16 {
|
||||
return
|
||||
}
|
||||
if y < MinY || y >= MinY+WorldHeight {
|
||||
return
|
||||
}
|
||||
localZ := z - int(c.Z)*16
|
||||
if localZ < 0 || localZ >= 16 {
|
||||
return
|
||||
}
|
||||
current := c.GetBlock(localX, y, localZ)
|
||||
for _, target := range targets {
|
||||
if !target.replaceables[current] || discard > 0 && random.NextFloat() < float32(discard) && exposedToAir(c, localX, y, localZ) {
|
||||
continue
|
||||
}
|
||||
c.SetBlock(localX, y, localZ, target.state)
|
||||
break
|
||||
}
|
||||
})
|
||||
return spheres
|
||||
}
|
||||
|
||||
func walkOreBlocks(spheres []oreSphere, visit func(x, y, z int)) {
|
||||
minX, maxX, minY, maxY, minZ, maxZ := oreBounds(spheres)
|
||||
for x := minX; x <= maxX; x++ {
|
||||
for y := minY; y <= maxY; y++ {
|
||||
for z := minZ; z <= maxZ; z++ {
|
||||
if oreContains(spheres, x, y, z) {
|
||||
visited := make(map[[3]int]bool)
|
||||
for _, sphere := range spheres {
|
||||
if sphere.radius < 0 {
|
||||
continue
|
||||
}
|
||||
minX, maxX := int(math.Floor(sphere.x-sphere.radius)), int(math.Floor(sphere.x+sphere.radius))
|
||||
minY, maxY := int(math.Floor(sphere.y-sphere.radius)), int(math.Floor(sphere.y+sphere.radius))
|
||||
minZ, maxZ := int(math.Floor(sphere.z-sphere.radius)), int(math.Floor(sphere.z+sphere.radius))
|
||||
for x := minX; x <= maxX; x++ {
|
||||
dx := (float64(x) + 0.5 - sphere.x) / sphere.radius
|
||||
if dx*dx >= 1 {
|
||||
continue
|
||||
}
|
||||
for y := minY; y <= maxY; y++ {
|
||||
dy := (float64(y) + 0.5 - sphere.y) / sphere.radius
|
||||
if dx*dx+dy*dy >= 1 {
|
||||
continue
|
||||
}
|
||||
for z := minZ; z <= maxZ; z++ {
|
||||
dz := (float64(z) + 0.5 - sphere.z) / sphere.radius
|
||||
position := [3]int{x, y, z}
|
||||
if dx*dx+dy*dy+dz*dz >= 1 || visited[position] {
|
||||
continue
|
||||
}
|
||||
visited[position] = true
|
||||
visit(x, y, z)
|
||||
}
|
||||
}
|
||||
|
|
@ -185,42 +211,6 @@ func walkOreBlocks(spheres []oreSphere, visit func(x, y, z int)) {
|
|||
}
|
||||
}
|
||||
|
||||
func oreBounds(spheres []oreSphere) (minX, maxX, minY, maxY, minZ, maxZ int) {
|
||||
found := false
|
||||
for _, sphere := range spheres {
|
||||
if sphere.radius < 0 {
|
||||
continue
|
||||
}
|
||||
loX, hiX := int(math.Floor(sphere.x-sphere.radius)), int(math.Floor(sphere.x+sphere.radius))
|
||||
loY, hiY := int(math.Floor(sphere.y-sphere.radius)), int(math.Floor(sphere.y+sphere.radius))
|
||||
loZ, hiZ := int(math.Floor(sphere.z-sphere.radius)), int(math.Floor(sphere.z+sphere.radius))
|
||||
if !found {
|
||||
minX, maxX, minY, maxY, minZ, maxZ = loX, hiX, loY, hiY, loZ, hiZ
|
||||
found = true
|
||||
continue
|
||||
}
|
||||
minX, maxX = min(minX, loX), max(maxX, hiX)
|
||||
minY, maxY = min(minY, loY), max(maxY, hiY)
|
||||
minZ, maxZ = min(minZ, loZ), max(maxZ, hiZ)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func oreContains(spheres []oreSphere, x, y, z int) bool {
|
||||
for _, sphere := range spheres {
|
||||
if sphere.radius < 0 {
|
||||
continue
|
||||
}
|
||||
dx := (float64(x) + 0.5 - sphere.x) / sphere.radius
|
||||
dy := (float64(y) + 0.5 - sphere.y) / sphere.radius
|
||||
dz := (float64(z) + 0.5 - sphere.z) / sphere.radius
|
||||
if dx*dx+dy*dy+dz*dz < 1 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func exposedToAir(c *Chunk, x, y, z int) bool {
|
||||
for _, offset := range [][3]int{{1, 0, 0}, {-1, 0, 0}, {0, 1, 0}, {0, -1, 0}, {0, 0, 1}, {0, 0, -1}} {
|
||||
nx, ny, nz := x+offset[0], y+offset[1], z+offset[2]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue