Skip to content

Commit

Permalink
refactor(biomes): conf preprocess + renaming
Browse files Browse the repository at this point in the history
  • Loading branch information
etienne-85 committed Jan 14, 2025
1 parent 1c2d83a commit 49ebe2d
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 78 deletions.
10 changes: 5 additions & 5 deletions src/factory/ChunksFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,19 @@ export class GroundChunk extends ChunkContainer {
const undegroundDepth = 4
const bedrock = this.dataEncoder(BlockType.BEDROCK)
const bedrockIce = this.dataEncoder(BlockType.ICE)
const { biome, landscapeIndex, flags } = block.data
const { biome, landIndex, flags } = block.data
const blockLocalPos = block.localPos as Vector3
const landscapeConf = Biome.instance.mappings[biome].nth(landscapeIndex)
const groundConf = landscapeConf.data
const biomeLand = Biome.instance.mappings[biome].nth(landIndex)
const landConf = biomeLand.data
const groundFlags = parseGroundFlags(flags)
const blockType =
highlightPatchBorders(blockLocalPos, groundConf.type) || groundConf.type
highlightPatchBorders(blockLocalPos, landConf.type) || landConf.type
const blockMode = groundFlags.boardMode
? BlockMode.CHECKERBOARD
: BlockMode.REGULAR
const groundSurface = this.dataEncoder(blockType, blockMode)
const undergroundLayer = this.dataEncoder(
groundConf.subtype || BlockType.BEDROCK,
landConf.subtype || BlockType.BEDROCK,
)
// generate ground buffer
const buffSize = MathUtils.clamp(block.data.level - ymin, 0, ymax - ymin)
Expand Down
2 changes: 1 addition & 1 deletion src/processing/BlocksProcessing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ export class BlocksProcessing extends ProcessingTask {
override async process(processingParams = defaultProcessingParams) {
const { recipe } = processingParams
const pendingBlocks = this.input.map(async pos => {
const groundPatch = this.getGroundPatch(pos)
const groundPatch = this.getGroundPatch(asVect2(pos))
const blockProcessor = new BlockProcessor(pos, groundPatch)
const block = await blockProcessor.bakeRecipe(recipe)
return block as Block<BlockData>
Expand Down
26 changes: 13 additions & 13 deletions src/processing/GroundPatch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Box2, Vector2, Vector3 } from 'three'

import {
GroundBlock,
LandscapesConf,
BiomeLands,
PatchBlock,
PatchBoundId,
PatchKey,
Expand Down Expand Up @@ -31,7 +31,8 @@ export type GroundBlockData = {
// rawVal: number,
level: number
biome: BiomeType
landscapeIndex: number
landIndex: number
landId?: string
flags: number
}

Expand All @@ -44,7 +45,7 @@ export type GroundPatchStub = PatchStub & {
const BitAllocation = {
level: 9, // level values ranging from 0 to 512
biome: 4, // 16 biomes
landscapeIndex: 5, // 32 landscapes per biome
landIndex: 5, // 32 landscapes per biome
flags: 3, // 8 additional flags
}

Expand Down Expand Up @@ -93,30 +94,28 @@ export class GroundPatch
decodeBlockData(rawData: number) {
const shift = BitAllocation
const level =
(rawData >> (shift.biome + shift.landscapeIndex + shift.flags)) &
(rawData >> (shift.biome + shift.landIndex + shift.flags)) &
((1 << shift.level) - 1)
const biomeNum =
(rawData >> (shift.landscapeIndex + shift.flags)) &
((1 << shift.biome) - 1)
(rawData >> (shift.landIndex + shift.flags)) & ((1 << shift.biome) - 1)
const biome = ReverseBiomeNumericType[biomeNum] || BiomeType.Temperate
const landscapeIndex =
(rawData >> shift.flags) & ((1 << shift.landscapeIndex) - 1)
const landIndex = (rawData >> shift.flags) & ((1 << shift.landIndex) - 1)
const flags = rawData & ((1 << shift.flags) - 1)
const blockData: GroundBlockData = {
level,
biome,
landscapeIndex,
landIndex,
flags,
}
return blockData
}

encodeBlockData(groundData: GroundBlockData): number {
const { level, biome, landscapeIndex, flags } = groundData
const { level, biome, landIndex, flags } = groundData
const shift = BitAllocation
let blockRawVal = level
blockRawVal = (blockRawVal << shift.biome) | BiomeNumericType[biome]
blockRawVal = (blockRawVal << shift.landscapeIndex) | landscapeIndex
blockRawVal = (blockRawVal << shift.landIndex) | landIndex
blockRawVal = (blockRawVal << shift.flags) | (flags || BlockMode.REGULAR)
return blockRawVal
}
Expand Down Expand Up @@ -277,7 +276,7 @@ export class GroundPatch
const nominalConf = Biome.instance.getBiomeConf(
rawVal,
biomeType,
) as LandscapesConf
) as BiomeLands
// const confIndex = Biome.instance.getConfIndex(currLevelConf.key)
// const confData = Biome.instance.indexedConf.get(confIndex)
const level = Heightmap.instance.getGroundLevel(
Expand Down Expand Up @@ -320,7 +319,8 @@ export class GroundPatch
const groundBlockData: GroundBlockData = {
level,
biome: biomeType,
landscapeIndex: usedConf.index,
landIndex: usedConf.index,
landId: usedConf.data.key,
flags,
}
return groundBlockData
Expand Down
25 changes: 10 additions & 15 deletions src/processing/ItemsProcessing.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Box2, Box3, Vector2, Vector3 } from 'three'
import { Box2, Box3, Vector3 } from 'three'

import { ChunkContainer, ChunkStub } from '../datacontainers/ChunkContainer'
import {
Expand Down Expand Up @@ -47,10 +47,10 @@ const getPatchBounds = (boundsOrPatchKey: Box2 | PatchKey) => {

// takes
const adjustHeight = async (itemChunk: ChunkContainer) => {
const chunkBottomBlocks: Vector2[] = []
const chunkBottomBlocks: Vector3[] = []
// iter slice blocks
for (const heightBuff of itemChunk.iterChunkSlice()) {
if (heightBuff.data[0]) chunkBottomBlocks.push(heightBuff.pos)
if (heightBuff.data[0]) chunkBottomBlocks.push(asVect3(heightBuff.pos, 0))
}
// compute blocks batch to find lowest element
const blocksBatch = new BlocksProcessing(chunkBottomBlocks)
Expand All @@ -71,28 +71,23 @@ export const retrieveOvergroundItems = (patchBounds: Box2) => {
const groundPatch = new GroundPatch(patchBounds)
groundPatch.preprocess()

// take approximative item dimension until item type is known
const spawnedItems: Record<ItemType, Vector3[]> = {}
const spawnPlaces = defaultSpawnMap.querySpawnLocations(
patchBounds,
asVect2(defaultItemDims),
)
for (const pos of spawnPlaces) {
const { level, biome, landscapeIndex } = groundPatch.computeGroundBlock(
// console.log(pos)
const { level, biome, landId } = groundPatch.computeGroundBlock(
asVect3(pos),
)
const weightedTypes =
Biome.instance.mappings[biome]?.nth(landscapeIndex)?.data?.flora
if (weightedTypes) {
const spawnableTypes: ItemType[] = []
Object.entries(weightedTypes).forEach(([itemType, typeWeight]) => {
while (typeWeight > 0) {
spawnableTypes.push(itemType)
typeWeight--
}
})
const { floraItems } =
Biome.instance.getBiomeLandConf(biome, landId as string) || {}
if (floraItems && floraItems?.length > 0) {
const itemType = defaultSpawnMap.getSpawnedItem(
pos,
spawnableTypes,
floraItems,
) as ItemType
if (itemType) {
spawnedItems[itemType] = spawnedItems[itemType] || []
Expand Down
6 changes: 3 additions & 3 deletions src/processing/TaskProcessing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ export class ProcessingTask {
? ProcessingState.Done
: this.processingState
// this.pendingTask = null
this.onTaskProcessed(taskRes)
// this.onTaskProcessed(taskRes)
this.resolveDeferredPromise(taskRes)
return taskRes // this.reconcile(stubs)
}
Expand Down Expand Up @@ -214,9 +214,9 @@ export class ProcessingTask {
console.log(processingParams)
}

onTaskProcessed(taskRes: any) {
// onTaskProcessed(taskRes: any) {

}
// }

// toStub(): any {
// const { stubs } = this
Expand Down
100 changes: 71 additions & 29 deletions src/procgen/Biome.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import { smoothstep } from 'three/src/math/MathUtils'

import { LinkedList } from '../datacontainers/LinkedList'
import {
BiomeLandscapeKey,
BiomeLandKey,
BiomesConf,
BiomesRawConf,
LandscapeFields,
LandscapesConf,
LandConfigFields,
BiomeLands,
} from '../utils/types'
import { WorldEnv } from '../index'
import { clamp, roundToDec } from '../utils/math'
Expand All @@ -18,6 +18,7 @@ import {
typesNumbering,
} from '../utils/misc'
import { asVect3 } from '../utils/convert'
import { ItemType } from '../factory/ItemsFactory'

import { ProcLayer } from './ProcLayer'

Expand Down Expand Up @@ -135,6 +136,29 @@ const BiomesMapping: Record<HeatLevel, Record<RainLevel, BiomeType>> = {
},
}

/**
* weightedFloraTypes: weighted item types which are supposed to spawn
* at given location
*/
const expandWeightedFloraTypes = (
weightedFloraTypes: Record<ItemType, number>,
) => {
const floraTypes: ItemType[] = []
if (weightedFloraTypes) {
Object.entries(weightedFloraTypes).forEach(([itemType, typeWeight]) => {
while (typeWeight > 0) {
floraTypes.push(itemType)
typeWeight--
}
})
}
return floraTypes
}

type PreprocessedLandConf = {
floraItems: ItemType[]
}

/**
* assign block types: water, sand, grass, mud, rock, snow, ..
*/
Expand Down Expand Up @@ -166,7 +190,7 @@ export class Biome {
high: 0.7,
}

indexedConf = new Map<BiomeLandscapeKey, LandscapesConf>()
preprocessed = new Map<BiomeLandKey, PreprocessedLandConf>()

constructor() {
this.heatmap = new ProcLayer('heatmap')
Expand Down Expand Up @@ -289,68 +313,80 @@ export class Biome {
return biomeContribs
}

preprocessLandConfig(
biomeType: BiomeType,
biomeConfig: LinkedList<LandConfigFields>,
) {
const configs = biomeConfig.first().forwardIter()
for (const conf of configs) {
const landConf = conf.data
const confKey = biomeType + '_' + landConf.key
// console.log(confKey)
const floraItems = landConf.flora
? expandWeightedFloraTypes(landConf.flora)
: []
this.preprocessed.set(confKey, {
floraItems,
})
// this.indexedConf.set(conf.data.key, conf)
}
}

parseBiomesConfig(biomesRawConf: BiomesRawConf) {
// Object.entries(biomeConfigs).forEach(([biomeType, biomeConf]) => {
// complete missing data
for (const [biomeType, biomeConf] of Object.entries(biomesRawConf)) {
// for (const [landId, landConf] of Object.entries(biomeConf)) {
// landConf.key = biomeType + '_' + landId
// }

const configItems = Object.values(biomeConf) as LandscapeFields[]
for (const [biomeType, biomeLands] of Object.entries(biomesRawConf)) {
for (const [landId, landConf] of Object.entries(biomeLands)) {
landConf.key = landId
}
const configItems = Object.values(biomeLands) as LandConfigFields[]
const mappingRanges = LinkedList.fromArrayAfterSorting(
configItems,
MappingRangeSorter,
)
this.mappings[biomeType as BiomeType] = mappingRanges
// index configs
// const confIter = mappingRanges.first().forwardIter()
// for (const conf of confIter) {
// this.indexedConf.set(conf.data.key, conf)
// }
this.preprocessLandConfig(biomeType as BiomeType, mappingRanges)
}
// })
}

landscapeTransition = (
groundPos: Vector2,
baseHeight: number,
landscapeConf: LandscapesConf,
biomeLands: BiomeLands,
) => {
const period = 0.005 * Math.pow(2, 2)
const mapCoords = groundPos.clone().multiplyScalar(period)
const posRandomizerVal = this.posRandomizer.eval(asVect3(mapCoords))
// add some height variations to break painting monotony
const { amplitude }: any = landscapeConf.data
const { amplitude }: any = biomeLands.data
const bounds = {
lower: landscapeConf.data.x,
upper: landscapeConf.next?.data.x || 1,
lower: biomeLands.data.x,
upper: biomeLands.next?.data.x || 1,
}
let blockType
// randomize on lower side
if (
landscapeConf.prev &&
biomeLands.prev &&
baseHeight - bounds.lower <= bounds.upper - baseHeight &&
baseHeight - amplitude.low < bounds.lower
) {
const heightVariation = posRandomizerVal * amplitude.low
const varyingHeight = baseHeight - heightVariation
blockType =
varyingHeight < landscapeConf.data.x
? landscapeConf.prev?.data.type
: landscapeConf.data.type
varyingHeight < biomeLands.data.x
? biomeLands.prev?.data.type
: biomeLands.data.type
}
// randomize on upper side
else if (landscapeConf.next && baseHeight + amplitude.high > bounds.upper) {
else if (biomeLands.next && baseHeight + amplitude.high > bounds.upper) {
// let heightVariation =
// Utils.clamp(this.paintingRandomness.eval(groundPos), 0.5, 1) * randomness.high
// heightVariation = heightVariation > 0 ? (heightVariation - 0.5) * 2 : 0
const heightVariation = posRandomizerVal * amplitude.high
const varyingHeight = baseHeight + heightVariation
blockType =
varyingHeight > landscapeConf.next.data.x
? landscapeConf.next.data.type
: landscapeConf.data.type
varyingHeight > biomeLands.next.data.x
? biomeLands.next.data.type
: biomeLands.data.type
}
return blockType
}
Expand Down Expand Up @@ -387,6 +423,12 @@ export class Biome {
return blockLevel
}

getBiomeLandConf = (biomeType: BiomeType, landId: string) => {
const confKey = biomeType + '_' + landId
const biomeConf = this.preprocessed.get(confKey)
return biomeConf
}

getBiomeConf = (rawVal: number, biomeType: BiomeType) => {
const firstItem = this.mappings[biomeType]
const confId = findMatchingRange(rawVal as number, firstItem)
Expand Down
8 changes: 4 additions & 4 deletions src/utils/misc.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { LandscapeFields, LandscapesConf } from './types'
import { BiomeLands, LandConfigFields } from './types'

// const MappingRangeFinder = (item: LinkedList<MappingData>, inputVal: number) => item.next && inputVal > (item.next.data as MappingData).x
export const MappingRangeSorter = (
item1: LandscapeFields,
item2: LandscapeFields,
item1: LandConfigFields,
item2: LandConfigFields,
) => item1.x - item2.x

/**
Expand All @@ -13,7 +13,7 @@ export const MappingRangeSorter = (
*/
export const findMatchingRange = (
inputVal: number,
noiseMappings: LandscapesConf,
noiseMappings: BiomeLands,
) => {
let match = noiseMappings.first()
let i = 1
Expand Down
Loading

0 comments on commit 49ebe2d

Please sign in to comment.