Replace bit-packed cell flags with material ID constants
This commit is contained in:
parent
f5b04f08c6
commit
0f9c1b47f2
3 changed files with 46 additions and 80 deletions
|
|
@ -4,10 +4,12 @@ import type { SceneCollection } from "./App";
|
||||||
import ColonyStats from "./ColonyStats";
|
import ColonyStats from "./ColonyStats";
|
||||||
import Config from "./Config";
|
import Config from "./Config";
|
||||||
import {
|
import {
|
||||||
FOOD_QUALITY_MASK,
|
MAT_AIR,
|
||||||
FOOD_QUALITY_SHIFT,
|
MAT_DIRT,
|
||||||
TERRAIN_TYPE_MASK,
|
MAT_FOOD,
|
||||||
TERRAIN_TYPE_SHIFT,
|
MAT_HOME,
|
||||||
|
MAT_ROCK,
|
||||||
|
MAT_SAND,
|
||||||
} from "./constants";
|
} from "./constants";
|
||||||
import {
|
import {
|
||||||
generateColorData,
|
generateColorData,
|
||||||
|
|
@ -70,8 +72,8 @@ export default class Renderer {
|
||||||
format: THREE.RGBAFormat,
|
format: THREE.RGBAFormat,
|
||||||
type: THREE.FloatType,
|
type: THREE.FloatType,
|
||||||
depthBuffer: false,
|
depthBuffer: false,
|
||||||
magFilter: THREE.LinearFilter,
|
magFilter: THREE.NearestFilter,
|
||||||
minFilter: THREE.LinearFilter,
|
minFilter: THREE.NearestFilter,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
worldRenderTargetCopy: new THREE.WebGLRenderTarget(
|
worldRenderTargetCopy: new THREE.WebGLRenderTarget(
|
||||||
|
|
@ -264,10 +266,12 @@ export default class Renderer {
|
||||||
REPELLENT_THRESHOLD: Renderer.convertNumberToFloatString(
|
REPELLENT_THRESHOLD: Renderer.convertNumberToFloatString(
|
||||||
Config.repellentThreshold,
|
Config.repellentThreshold,
|
||||||
),
|
),
|
||||||
TERRAIN_TYPE_SHIFT: String(TERRAIN_TYPE_SHIFT),
|
MAT_AIR: String(MAT_AIR),
|
||||||
TERRAIN_TYPE_MASK: String(TERRAIN_TYPE_MASK),
|
MAT_SAND: String(MAT_SAND),
|
||||||
FOOD_QUALITY_SHIFT: String(FOOD_QUALITY_SHIFT),
|
MAT_DIRT: String(MAT_DIRT),
|
||||||
FOOD_QUALITY_MASK: String(FOOD_QUALITY_MASK),
|
MAT_ROCK: String(MAT_ROCK),
|
||||||
|
MAT_FOOD: String(MAT_FOOD),
|
||||||
|
MAT_HOME: String(MAT_HOME),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,66 +1,33 @@
|
||||||
import { describe, expect, test } from "bun:test";
|
import { describe, expect, test } from "bun:test";
|
||||||
import {
|
import {
|
||||||
CELL_FOOD_BIT,
|
MAT_AIR,
|
||||||
CELL_HOME_BIT,
|
MAT_DIRT,
|
||||||
CELL_OBSTACLE_BIT,
|
MAT_FOOD,
|
||||||
FOOD_QUALITY_MASK,
|
MAT_HOME,
|
||||||
FOOD_QUALITY_SHIFT,
|
MAT_ROCK,
|
||||||
TERRAIN_TYPE_MASK,
|
MAT_SAND,
|
||||||
TERRAIN_TYPE_SHIFT,
|
|
||||||
} from "../constants";
|
} from "../constants";
|
||||||
|
|
||||||
describe("cell metadata bit layout", () => {
|
describe("material ID constants", () => {
|
||||||
test("bit fields do not overlap", () => {
|
test("IDs match registry order", () => {
|
||||||
// cell flags occupy bits 0-2
|
expect(MAT_AIR).toBe(0);
|
||||||
const cellFlagsBits = (1 << (CELL_OBSTACLE_BIT + 1)) - 1;
|
expect(MAT_SAND).toBe(1);
|
||||||
// terrain occupies bits 3-5
|
expect(MAT_DIRT).toBe(2);
|
||||||
const terrainBits = TERRAIN_TYPE_MASK << TERRAIN_TYPE_SHIFT;
|
expect(MAT_ROCK).toBe(3);
|
||||||
// food quality occupies bits 6-13
|
expect(MAT_FOOD).toBe(4);
|
||||||
const foodQualityBits = FOOD_QUALITY_MASK << FOOD_QUALITY_SHIFT;
|
expect(MAT_HOME).toBe(5);
|
||||||
|
|
||||||
expect(cellFlagsBits & terrainBits).toBe(0);
|
|
||||||
expect(cellFlagsBits & foodQualityBits).toBe(0);
|
|
||||||
expect(terrainBits & foodQualityBits).toBe(0);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("terrain type can encode 8 values", () => {
|
test("IDs are unique", () => {
|
||||||
for (let t = 0; t <= 7; t++) {
|
const ids = [MAT_AIR, MAT_SAND, MAT_DIRT, MAT_ROCK, MAT_FOOD, MAT_HOME];
|
||||||
const packed = t << TERRAIN_TYPE_SHIFT;
|
expect(new Set(ids).size).toBe(ids.length);
|
||||||
const unpacked = (packed >> TERRAIN_TYPE_SHIFT) & TERRAIN_TYPE_MASK;
|
});
|
||||||
expect(unpacked).toBe(t);
|
|
||||||
|
test("IDs fit in a byte", () => {
|
||||||
|
const ids = [MAT_AIR, MAT_SAND, MAT_DIRT, MAT_ROCK, MAT_FOOD, MAT_HOME];
|
||||||
|
for (const id of ids) {
|
||||||
|
expect(id).toBeGreaterThanOrEqual(0);
|
||||||
|
expect(id).toBeLessThanOrEqual(255);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test("food quality can encode 0-255", () => {
|
|
||||||
for (const q of [0, 1, 127, 255]) {
|
|
||||||
const packed = q << FOOD_QUALITY_SHIFT;
|
|
||||||
const unpacked = (packed >> FOOD_QUALITY_SHIFT) & FOOD_QUALITY_MASK;
|
|
||||||
expect(unpacked).toBe(q);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test("all fields round-trip together", () => {
|
|
||||||
const food = 1;
|
|
||||||
const home = 1;
|
|
||||||
const obstacle = 0;
|
|
||||||
const terrain = 5;
|
|
||||||
const quality = 200;
|
|
||||||
|
|
||||||
const packed =
|
|
||||||
food +
|
|
||||||
(home << CELL_HOME_BIT) +
|
|
||||||
(obstacle << CELL_OBSTACLE_BIT) +
|
|
||||||
(terrain << TERRAIN_TYPE_SHIFT) +
|
|
||||||
(quality << FOOD_QUALITY_SHIFT);
|
|
||||||
|
|
||||||
expect((packed >> CELL_FOOD_BIT) & 1).toBe(food);
|
|
||||||
expect((packed >> CELL_HOME_BIT) & 1).toBe(home);
|
|
||||||
expect((packed >> CELL_OBSTACLE_BIT) & 1).toBe(obstacle);
|
|
||||||
expect((packed >> TERRAIN_TYPE_SHIFT) & TERRAIN_TYPE_MASK).toBe(
|
|
||||||
terrain,
|
|
||||||
);
|
|
||||||
expect((packed >> FOOD_QUALITY_SHIFT) & FOOD_QUALITY_MASK).toBe(
|
|
||||||
quality,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,9 @@
|
||||||
// cell metadata bit layout for world texture R channel
|
// material IDs for world texture R channel
|
||||||
|
// must match registration order in materials/registry.ts
|
||||||
|
|
||||||
// bits 0-2: cell type flags
|
export const MAT_AIR = 0;
|
||||||
export const CELL_FOOD_BIT = 0;
|
export const MAT_SAND = 1;
|
||||||
export const CELL_HOME_BIT = 1;
|
export const MAT_DIRT = 2;
|
||||||
export const CELL_OBSTACLE_BIT = 2;
|
export const MAT_ROCK = 3;
|
||||||
|
export const MAT_FOOD = 4;
|
||||||
// bits 3-5: terrain type (0-7)
|
export const MAT_HOME = 5;
|
||||||
export const TERRAIN_TYPE_SHIFT = 3;
|
|
||||||
export const TERRAIN_TYPE_MASK = 0b111; // 3 bits
|
|
||||||
|
|
||||||
// bits 6-13: food quality (0-255)
|
|
||||||
export const FOOD_QUALITY_SHIFT = 6;
|
|
||||||
export const FOOD_QUALITY_MASK = 0xff; // 8 bits
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue