/** * DecoModels — воксельные модели декораций (цветы, грибы, кустики травы). * * Каждая модель — массив мини-вокселей размером DECO_VOXEL_SIZE метров. * Координаты voxel'ов в локальной системе модели (0..N в каждом измерении). * * Цвет хранится как [r, g, b] в 0..1 (Babylon.Color3). * * Применение: DecoManager берёт модель + позицию в мире + поворот, добавляет * voxel'и как thin-instances одной геометрии (один куб 0.05м). */ /** Размер одного deco-voxel'а в мире (метров). */ export const DECO_VOXEL_SIZE = 0.05; // ============================================================================ // Палитра цветов для декораций // Каждый цвет — Color3-совместимый массив [r, g, b] в [0..1]. // ============================================================================ export const DECO_PALETTE = { // Стебли и листва stemGreen: [0.20, 0.50, 0.15], stemLight: [0.40, 0.65, 0.20], leafDark: [0.15, 0.40, 0.12], leafGrass: [0.35, 0.70, 0.25], // Палитра травы — 4 оттенка зелёного для разнообразия grass1: [0.32, 0.62, 0.20], // основной grass2: [0.22, 0.52, 0.15], // тёмный grass3: [0.45, 0.72, 0.25], // светлый grass4: [0.38, 0.65, 0.18], // желтоватый grassYellow: [0.55, 0.65, 0.20], // сухой grassRed: [0.40, 0.45, 0.15], // увядший // Цветы — лепестки petalRed: [0.85, 0.20, 0.20], petalPink: [1.00, 0.55, 0.70], petalYellow: [1.00, 0.85, 0.20], petalWhite: [0.95, 0.95, 0.90], petalBlue: [0.30, 0.50, 0.85], petalPurple: [0.65, 0.30, 0.80], petalOrange: [1.00, 0.55, 0.15], // Центры цветов (тычинки) centerYellow: [0.95, 0.75, 0.10], centerOrange: [0.90, 0.55, 0.10], centerBlack: [0.15, 0.10, 0.05], // Грибы capRed: [0.80, 0.15, 0.15], capWhite: [0.95, 0.95, 0.90], capBrown: [0.55, 0.35, 0.20], capDots: [0.95, 0.95, 0.90], mushroomStem: [0.92, 0.88, 0.75], }; // ============================================================================ // Воксельные модели декораций // // Формат: voxels[] = [{ x, y, z, c }] // - x, y, z — целые координаты в локальной системе модели (0..) // - c — ключ из DECO_PALETTE // - y = 0 — основание (касается земли) // // При размере 0.05м, модель 10 voxel = 0.5м реального мира. // ============================================================================ /** * Ромашка — стебель 5 voxel + шапка 3×3 белых лепестка с жёлтым центром. * Высота ~10 voxel = 50см. */ export const FLOWER_DAISY = { name: 'daisy', voxels: [ // Стебель — 5 voxel вверх по центру (x=2, z=2 в 5x5 модели) { x: 2, y: 0, z: 2, c: 'stemGreen' }, { x: 2, y: 1, z: 2, c: 'stemGreen' }, { x: 2, y: 2, z: 2, c: 'stemGreen' }, { x: 2, y: 3, z: 2, c: 'stemGreen' }, { x: 2, y: 4, z: 2, c: 'stemLight' }, // Лист сбоку на высоте 2 { x: 3, y: 2, z: 2, c: 'leafGrass' }, // Шапка на Y=5: лепестки 3×3 крест { x: 1, y: 5, z: 2, c: 'petalWhite' }, { x: 3, y: 5, z: 2, c: 'petalWhite' }, { x: 2, y: 5, z: 1, c: 'petalWhite' }, { x: 2, y: 5, z: 3, c: 'petalWhite' }, // Центр — жёлтый { x: 2, y: 5, z: 2, c: 'centerYellow' }, // Верхушка { x: 2, y: 6, z: 2, c: 'centerYellow' }, ], }; /** * Василёк — синий объёмный цветок-шар. * Лепестки расходятся в стороны и вверх — как настоящий бутон. */ export const FLOWER_CORNFLOWER = { name: 'cornflower', voxels: [ // Стебель 5 voxel { x: 2, y: 0, z: 2, c: 'stemGreen' }, { x: 2, y: 1, z: 2, c: 'stemGreen' }, { x: 2, y: 2, z: 2, c: 'stemGreen' }, { x: 2, y: 3, z: 2, c: 'stemGreen' }, // Лист сбоку { x: 3, y: 2, z: 2, c: 'leafGrass' }, // Объёмный бутон на Y=4..6 // Нижний слой (Y=4) — 4 «нижних» лепестка крестом { x: 1, y: 4, z: 2, c: 'petalBlue' }, { x: 3, y: 4, z: 2, c: 'petalBlue' }, { x: 2, y: 4, z: 1, c: 'petalBlue' }, { x: 2, y: 4, z: 3, c: 'petalBlue' }, // Средний слой (Y=5) — заполненный 3×3 квадрат { x: 1, y: 5, z: 1, c: 'petalBlue' }, { x: 2, y: 5, z: 1, c: 'petalBlue' }, { x: 3, y: 5, z: 1, c: 'petalBlue' }, { x: 1, y: 5, z: 2, c: 'petalBlue' }, { x: 2, y: 5, z: 2, c: 'centerYellow' }, // центр (тычинки) { x: 3, y: 5, z: 2, c: 'petalBlue' }, { x: 1, y: 5, z: 3, c: 'petalBlue' }, { x: 2, y: 5, z: 3, c: 'petalBlue' }, { x: 3, y: 5, z: 3, c: 'petalBlue' }, // Верхний слой (Y=6) — пирамидка крестом { x: 2, y: 6, z: 1, c: 'petalBlue' }, { x: 1, y: 6, z: 2, c: 'petalBlue' }, { x: 2, y: 6, z: 2, c: 'petalBlue' }, { x: 3, y: 6, z: 2, c: 'petalBlue' }, { x: 2, y: 6, z: 3, c: 'petalBlue' }, ], }; /** * Красный мак — крупные красные лепестки. */ export const FLOWER_POPPY = { name: 'poppy', voxels: [ { x: 2, y: 0, z: 2, c: 'stemGreen' }, { x: 2, y: 1, z: 2, c: 'stemGreen' }, { x: 2, y: 2, z: 2, c: 'stemGreen' }, { x: 2, y: 3, z: 2, c: 'stemGreen' }, // Большой бутон 3×3 { x: 1, y: 4, z: 1, c: 'petalRed' }, { x: 2, y: 4, z: 1, c: 'petalRed' }, { x: 3, y: 4, z: 1, c: 'petalRed' }, { x: 1, y: 4, z: 2, c: 'petalRed' }, { x: 2, y: 4, z: 2, c: 'centerBlack' }, { x: 3, y: 4, z: 2, c: 'petalRed' }, { x: 1, y: 4, z: 3, c: 'petalRed' }, { x: 2, y: 4, z: 3, c: 'petalRed' }, { x: 3, y: 4, z: 3, c: 'petalRed' }, ], }; /** * Жёлтый одуванчик — объёмный пушистый шар (как реальный цветок). */ export const FLOWER_DANDELION = { name: 'dandelion', voxels: [ // Стебель { x: 2, y: 0, z: 2, c: 'stemGreen' }, { x: 2, y: 1, z: 2, c: 'stemGreen' }, { x: 2, y: 2, z: 2, c: 'stemGreen' }, { x: 2, y: 3, z: 2, c: 'stemGreen' }, // Лист { x: 1, y: 1, z: 2, c: 'leafGrass' }, // Объёмный пушистый бутон на Y=4..6 // Нижний слой Y=4 — нижние лепестки крест { x: 1, y: 4, z: 2, c: 'petalYellow' }, { x: 3, y: 4, z: 2, c: 'petalYellow' }, { x: 2, y: 4, z: 1, c: 'petalYellow' }, { x: 2, y: 4, z: 3, c: 'petalYellow' }, // Средний слой Y=5 — 3×3 квадрат { x: 1, y: 5, z: 1, c: 'petalYellow' }, { x: 2, y: 5, z: 1, c: 'petalYellow' }, { x: 3, y: 5, z: 1, c: 'petalYellow' }, { x: 1, y: 5, z: 2, c: 'petalYellow' }, { x: 2, y: 5, z: 2, c: 'centerOrange' }, { x: 3, y: 5, z: 2, c: 'petalYellow' }, { x: 1, y: 5, z: 3, c: 'petalYellow' }, { x: 2, y: 5, z: 3, c: 'petalYellow' }, { x: 3, y: 5, z: 3, c: 'petalYellow' }, // Верхний слой Y=6 — пирамидка { x: 2, y: 6, z: 1, c: 'petalYellow' }, { x: 1, y: 6, z: 2, c: 'petalYellow' }, { x: 2, y: 6, z: 2, c: 'petalYellow' }, { x: 3, y: 6, z: 2, c: 'petalYellow' }, { x: 2, y: 6, z: 3, c: 'petalYellow' }, // Верхушка { x: 2, y: 7, z: 2, c: 'petalYellow' }, ], }; /** * Мухомор — красная шляпка с белыми точками + белая ножка. */ export const MUSHROOM_FLY = { name: 'fly_mushroom', voxels: [ // Белая ножка 3 voxel { x: 2, y: 0, z: 2, c: 'mushroomStem' }, { x: 2, y: 1, z: 2, c: 'mushroomStem' }, { x: 2, y: 2, z: 2, c: 'mushroomStem' }, // Красная шляпка 3×3 { x: 1, y: 3, z: 1, c: 'capRed' }, { x: 2, y: 3, z: 1, c: 'capDots' }, // белая точка { x: 3, y: 3, z: 1, c: 'capRed' }, { x: 1, y: 3, z: 2, c: 'capDots' }, // белая точка { x: 2, y: 3, z: 2, c: 'capRed' }, { x: 3, y: 3, z: 2, c: 'capDots' }, // белая точка { x: 1, y: 3, z: 3, c: 'capRed' }, { x: 2, y: 3, z: 3, c: 'capRed' }, { x: 3, y: 3, z: 3, c: 'capDots' }, // белая точка // Верхушка шляпки { x: 2, y: 4, z: 2, c: 'capRed' }, ], }; /** * Коричневый гриб — простая шляпка. */ export const MUSHROOM_BROWN = { name: 'brown_mushroom', voxels: [ { x: 2, y: 0, z: 2, c: 'mushroomStem' }, { x: 2, y: 1, z: 2, c: 'mushroomStem' }, // Шляпка { x: 1, y: 2, z: 1, c: 'capBrown' }, { x: 2, y: 2, z: 1, c: 'capBrown' }, { x: 3, y: 2, z: 1, c: 'capBrown' }, { x: 1, y: 2, z: 2, c: 'capBrown' }, { x: 2, y: 2, z: 2, c: 'capBrown' }, { x: 3, y: 2, z: 2, c: 'capBrown' }, { x: 1, y: 2, z: 3, c: 'capBrown' }, { x: 2, y: 2, z: 3, c: 'capBrown' }, { x: 3, y: 2, z: 3, c: 'capBrown' }, ], }; /** * Трава — 7 РАЗНЫХ моделей. WorldGenerator выбирает случайно при размещении, * + случайный scale и rotation. Это даёт хаотичный, естественный вид: * * grass_short — короткие отростки (2-3 voxel'а высотой, маленький пучок) * grass_tuft — обычный пучок (5-7 voxel'ов крестом) * grass_tall — высокая трава (5+ voxel'ов вверх стеблем) * grass_wide — широкий пучок (расходится в стороны) * grass_clump — кустистый клумб * grass_blade — отдельная травинка с листом * grass_dry — сухая, желтоватая * * Все используют разные оттенки grass1..4 + редкий grassYellow для разнообразия. */ /** Короткие отростки — самая мелкая трава, чаще всего. */ export const GRASS_SHORT = { name: 'grass_short', voxels: [ { x: 2, y: 0, z: 2, c: 'grass1' }, { x: 2, y: 1, z: 2, c: 'grass1' }, { x: 1, y: 0, z: 2, c: 'grass3' }, { x: 3, y: 0, z: 2, c: 'grass2' }, ], }; /** Обычный пучок — крестом, средняя высота. */ export const GRASS_TUFT = { name: 'grass_tuft', voxels: [ { x: 2, y: 0, z: 2, c: 'grass1' }, { x: 2, y: 1, z: 2, c: 'grass1' }, { x: 1, y: 1, z: 2, c: 'grass2' }, { x: 3, y: 1, z: 2, c: 'grass3' }, { x: 2, y: 2, z: 2, c: 'grass2' }, ], }; /** Высокая трава — столбик 4 voxel + 1 ветка. */ export const GRASS_TALL = { name: 'grass_tall', voxels: [ { x: 2, y: 0, z: 2, c: 'grass2' }, { x: 2, y: 1, z: 2, c: 'grass1' }, { x: 2, y: 2, z: 2, c: 'grass3' }, { x: 2, y: 3, z: 2, c: 'grass4' }, { x: 3, y: 2, z: 2, c: 'grass3' }, ], }; /** Широкий пучок — расходится в стороны, низкий. */ export const GRASS_WIDE = { name: 'grass_wide', voxels: [ { x: 2, y: 0, z: 2, c: 'grass2' }, { x: 1, y: 0, z: 2, c: 'grass1' }, { x: 3, y: 0, z: 2, c: 'grass1' }, { x: 2, y: 0, z: 1, c: 'grass1' }, { x: 2, y: 0, z: 3, c: 'grass1' }, { x: 2, y: 1, z: 2, c: 'grass3' }, ], }; /** Кустистый клумб — компактный куст. */ export const GRASS_CLUMP = { name: 'grass_clump', voxels: [ { x: 2, y: 0, z: 2, c: 'grass2' }, { x: 1, y: 0, z: 2, c: 'grass2' }, { x: 3, y: 0, z: 2, c: 'grass2' }, { x: 2, y: 0, z: 1, c: 'grass2' }, { x: 2, y: 0, z: 3, c: 'grass2' }, { x: 2, y: 1, z: 2, c: 'grass1' }, { x: 2, y: 2, z: 2, c: 'grass3' }, ], }; /** Отдельная травинка с листом — тонкая. */ export const GRASS_BLADE = { name: 'grass_blade', voxels: [ { x: 2, y: 0, z: 2, c: 'grass2' }, { x: 2, y: 1, z: 2, c: 'grass1' }, { x: 2, y: 2, z: 2, c: 'grass3' }, ], }; /** Сухая трава — желтовато-зелёная, низкая. */ export const GRASS_DRY = { name: 'grass_dry', voxels: [ { x: 2, y: 0, z: 2, c: 'grassYellow' }, { x: 1, y: 0, z: 2, c: 'grassYellow' }, { x: 3, y: 0, z: 2, c: 'grassRed' }, { x: 2, y: 1, z: 2, c: 'grassYellow' }, ], }; /** * Все доступные модели — упорядоченный список. */ export const DECO_MODELS = { daisy: FLOWER_DAISY, cornflower: FLOWER_CORNFLOWER, poppy: FLOWER_POPPY, dandelion: FLOWER_DANDELION, fly_mushroom: MUSHROOM_FLY, brown_mushroom: MUSHROOM_BROWN, // 7 разных моделей травы — генератор выбирает случайно grass_short: GRASS_SHORT, grass_tuft: GRASS_TUFT, grass_tall: GRASS_TALL, grass_wide: GRASS_WIDE, grass_clump: GRASS_CLUMP, grass_blade: GRASS_BLADE, grass_dry: GRASS_DRY, }; /** * Пул моделей травы для генератора — с весами для частоты появления. * Чем больше повторений, тем чаще встречается. */ export const GRASS_MODELS_POOL = [ // Самые дешёвые модели (3-4 voxel) — основная масса травы 'grass_short', 'grass_short', 'grass_short', 'grass_short', 'grass_short', 'grass_short', // ×6 'grass_blade', 'grass_blade', 'grass_blade', 'grass_blade', // ×4 // Средние (5-6 voxel) — для разнообразия 'grass_tuft', 'grass_tuft', // ×2 'grass_wide', // ×1 'grass_tall', // ×1 'grass_clump', // ×1 'grass_dry', // ×1 ]; /** * Группы декораций по биому. Используется при процедурном размещении. */ export const DECO_BY_BIOME = { grass: ['daisy', 'cornflower', 'poppy', 'dandelion', 'grass_tuft', 'grass_tuft', 'grass_tuft'], forest: ['daisy', 'fly_mushroom', 'brown_mushroom', 'grass_tuft', 'grass_tuft'], plain: ['dandelion', 'cornflower', 'grass_tuft', 'grass_tuft'], desert: [], // в пустыне декораций нет snow: [], mountain: [], };