feat: Started on palette implementation
This commit is contained in:
parent
88100b58ea
commit
255475c77c
26
hashserver.txt
Normal file
26
hashserver.txt
Normal file
@ -0,0 +1,26 @@
|
||||
goos: linux
|
||||
goarch: amd64
|
||||
pkg: git.nicholasnovak.io/nnovak/spatial-db
|
||||
cpu: 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz
|
||||
BenchmarkInsertClusteredPoints-8 7030724 294.0 ns/op 139 B/op 0 allocs/op
|
||||
BenchmarkInsertClusteredPoints-8 5987259 198.1 ns/op 10 B/op 0 allocs/op
|
||||
BenchmarkInsertClusteredPoints-8 5793637 484.0 ns/op 337 B/op 0 allocs/op
|
||||
BenchmarkInsertClusteredPoints-8 5644594 207.5 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkInsertClusteredPoints-8 5815582 211.0 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkInsertClusteredPoints-8 5618958 211.7 ns/op 2 B/op 0 allocs/op
|
||||
BenchmarkInsertClusteredPoints-8 5603455 215.2 ns/op 10 B/op 0 allocs/op
|
||||
BenchmarkInsertClusteredPoints-8 5454136 223.0 ns/op 13 B/op 0 allocs/op
|
||||
BenchmarkInsertClusteredPoints-8 5391891 694.1 ns/op 718 B/op 0 allocs/op
|
||||
BenchmarkInsertClusteredPoints-8 5574357 228.4 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkInsertSparserPoints-8 5355165 218.3 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkInsertSparserPoints-8 5385463 221.0 ns/op 1 B/op 0 allocs/op
|
||||
BenchmarkInsertSparserPoints-8 5265614 224.1 ns/op 2 B/op 0 allocs/op
|
||||
BenchmarkInsertSparserPoints-8 5269447 229.2 ns/op 7 B/op 0 allocs/op
|
||||
BenchmarkInsertSparserPoints-8 5167845 231.7 ns/op 19 B/op 0 allocs/op
|
||||
BenchmarkInsertSparserPoints-8 4997976 240.3 ns/op 23 B/op 0 allocs/op
|
||||
BenchmarkInsertSparserPoints-8 4914524 772.6 ns/op 1584 B/op 0 allocs/op
|
||||
BenchmarkInsertSparserPoints-8 1535679 692.3 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkInsertSparserPoints-8 1852569 617.0 ns/op 0 B/op 0 allocs/op
|
||||
BenchmarkInsertSparserPoints-8 2007783 568.2 ns/op 1 B/op 0 allocs/op
|
||||
PASS
|
||||
ok git.nicholasnovak.io/nnovak/spatial-db 114.742s
|
@ -25,7 +25,7 @@ func (hs *HashServer) SetStorageRoot(path string) {
|
||||
for _, section := range data.Sections {
|
||||
for blockIndex, blockState := range section.BlockStates {
|
||||
pos := data.IndexToBlockPos(blockIndex)
|
||||
hs.blocks[pos] = blockState
|
||||
hs.blocks[pos] = section.Palette.State(blockState)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,15 +16,17 @@ const (
|
||||
// `ChunkData` represents the contents of a "chunk", which is a column of voxels
|
||||
// in world space
|
||||
type ChunkData struct {
|
||||
// The position of the chunk, in world space
|
||||
Pos ChunkPos `json:"pos"`
|
||||
// The column of sections
|
||||
Sections [ChunkSectionCount]ChunkSection `json:"sections"`
|
||||
}
|
||||
|
||||
// `ChunkSection' is a fixed-size cube that stores the data in a chunk
|
||||
type ChunkSection struct {
|
||||
// The count of full blocks in the chunk
|
||||
BlockCount uint `json:"block_count"`
|
||||
BlockStates [16 * 16 * 16]BlockID `json:"block_states"`
|
||||
// A look-up-table of each section index to its value
|
||||
Palette SectionPalette `json:"palette"`
|
||||
BlockStates [16 * 16 * 16]PaletteIndex `json:"block_states"`
|
||||
}
|
||||
|
||||
func rem_euclid(a, b int) int {
|
||||
@ -39,18 +41,12 @@ func IndexOfBlock(pos BlockPos) int {
|
||||
return (baseY * chunkSliceSize) + (baseZ * 16) + baseX
|
||||
}
|
||||
|
||||
func (cs *ChunkSection) UpdateBlockAtIndex(index int, targetState BlockID) {
|
||||
// TODO: Keep track of the block count
|
||||
|
||||
cs.BlockStates[index] = targetState
|
||||
}
|
||||
|
||||
func (cs *ChunkSection) UpdateBlock(pos BlockPos, targetState BlockID) {
|
||||
cs.BlockStates[IndexOfBlock(pos)] = targetState
|
||||
cs.BlockStates[IndexOfBlock(pos)] = cs.Palette.IndexFor(targetState)
|
||||
}
|
||||
|
||||
func (cs *ChunkSection) FetchBlock(pos BlockPos) BlockID {
|
||||
return cs.BlockStates[IndexOfBlock(pos)]
|
||||
return cs.Palette.State(cs.BlockStates[IndexOfBlock(pos)])
|
||||
}
|
||||
|
||||
func (cd *ChunkData) SectionFor(pos BlockPos) *ChunkSection {
|
||||
@ -68,6 +64,8 @@ func (cd *ChunkData) IndexToBlockPos(index int) BlockPos {
|
||||
}
|
||||
}
|
||||
|
||||
// Conversion from Minecraft chunks
|
||||
|
||||
func extractPaletteIndexes(compressed int64) [16]byte {
|
||||
var outputs [16]byte
|
||||
var outputIndex int
|
||||
@ -113,13 +111,12 @@ func (cd *ChunkData) FromMCAChunk(other save.Chunk) {
|
||||
if section.BlockStates.Palette[paletteIndex].Name == "minecraft:air" {
|
||||
state = Empty
|
||||
} else {
|
||||
cd.Sections[sectionIndex].BlockCount += 1
|
||||
state = Generic
|
||||
}
|
||||
|
||||
// TODO: Remove this workaround for larger bit sizes in palettes
|
||||
if blockIndex < 4096 {
|
||||
currentSection.BlockStates[blockIndex] = state
|
||||
currentSection.BlockStates[blockIndex] = currentSection.Palette.IndexFor(state)
|
||||
}
|
||||
}
|
||||
|
||||
|
51
world/palette.go
Normal file
51
world/palette.go
Normal file
@ -0,0 +1,51 @@
|
||||
package world
|
||||
|
||||
// `SectionPalette` is a "palette", which is a sort of look-up-table (LUT) between
|
||||
// an index into the LUT, and the resulting `BlockID`
|
||||
//
|
||||
// This palette is unique to each section, and allows ranges of blocks to be
|
||||
// changed in constant time, with the downside of having to "compact" the palette
|
||||
type SectionPalette []BlockID
|
||||
|
||||
// `Compact` removes all duplicate states from a palette and returns a new palette
|
||||
func (p SectionPalette) Compact() SectionPalette {
|
||||
ids := make(map[BlockID]bool)
|
||||
|
||||
// Filter out the duplicate block ids
|
||||
for _, blockId := range p {
|
||||
ids[blockId] = true
|
||||
}
|
||||
|
||||
var np SectionPalette
|
||||
|
||||
for blockId := range ids {
|
||||
np = append(np, blockId)
|
||||
}
|
||||
|
||||
return np
|
||||
}
|
||||
|
||||
// `IndexFor` returns the palette index for a specified block id
|
||||
//
|
||||
// If the block id does not exist, it is placed in the palette and the index
|
||||
// is returned
|
||||
func (p SectionPalette) IndexFor(state BlockID) PaletteIndex {
|
||||
// If the state is already in the palette, return it
|
||||
for index, blockId := range p {
|
||||
if state == blockId {
|
||||
return PaletteIndex(index)
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, insert it into the palette and return the index
|
||||
p = append(p, state)
|
||||
|
||||
return PaletteIndex(len(p) - 1)
|
||||
}
|
||||
|
||||
// `State` returns the state for a palette's index
|
||||
func (p SectionPalette) State(index PaletteIndex) BlockID {
|
||||
return p[index]
|
||||
}
|
||||
|
||||
type PaletteIndex byte
|
Loading…
Reference in New Issue
Block a user