Merge pull request #660 from eliotbyte/fix/custom-model-variants
Fix/custom model variants
This commit is contained in:
commit
debd28ba55
@ -98,6 +98,32 @@ Properties available for variance:
|
|||||||
|
|
||||||
Variants are managed via `block.set_variant(x, y, z, index)`.
|
Variants are managed via `block.set_variant(x, y, z, index)`.
|
||||||
|
|
||||||
|
### Custom model variants (geometry switching)
|
||||||
|
|
||||||
|
You can use different custom models for different variants. Provide a separate `model-name` for each variant that needs different geometry. The renderer caches geometry per (block id, variant).
|
||||||
|
|
||||||
|
The base model (specified in root) becomes variant 0. The variants array maps to indices 1+.
|
||||||
|
|
||||||
|
Example (default + two custom variants):
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"model": "custom",
|
||||||
|
"model-name": "stairs_middle",
|
||||||
|
"state-based": {
|
||||||
|
"bits": 4,
|
||||||
|
"variants": [
|
||||||
|
{ "model": "custom", "model-name": "stairs_left" },
|
||||||
|
{ "model": "custom", "model-name": "stairs_right" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example:
|
||||||
|
- Variant 0 = `stairs_middle` (from root)
|
||||||
|
- Variant 1 = `stairs_left` (from variants[0])
|
||||||
|
- Variant 2 = `stairs_right` (from variants[1])
|
||||||
|
|
||||||
## Lighting
|
## Lighting
|
||||||
|
|
||||||
### *emission*
|
### *emission*
|
||||||
|
|||||||
@ -106,6 +106,32 @@
|
|||||||
|
|
||||||
Управление состоянием производится через `block.set_variant(x, y, z, index)`.
|
Управление состоянием производится через `block.set_variant(x, y, z, index)`.
|
||||||
|
|
||||||
|
### Кастомные модели по вариантам (переключение геометрии)
|
||||||
|
|
||||||
|
Для custom-моделей можно переключать геометрию по варианту. Укажите отдельный `model-name` в нужных вариантах — рендерер кэширует геометрию по паре (id блока, вариант).
|
||||||
|
|
||||||
|
Базовая модель (из корня) становится вариантом 0. Массив variants соответствует индексам 1+.
|
||||||
|
|
||||||
|
Пример (база + два кастомных варианта):
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"model": "custom",
|
||||||
|
"model-name": "stairs_middle",
|
||||||
|
"state-based": {
|
||||||
|
"bits": 4,
|
||||||
|
"variants": [
|
||||||
|
{ "model": "custom", "model-name": "stairs_left" },
|
||||||
|
{ "model": "custom", "model-name": "stairs_right" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
В этом примере:
|
||||||
|
- Вариант 0 = `stairs_middle` (из корня)
|
||||||
|
- Вариант 1 = `stairs_left` (из variants[0])
|
||||||
|
- Вариант 2 = `stairs_right` (из variants[1])
|
||||||
|
|
||||||
## Освещение
|
## Освещение
|
||||||
|
|
||||||
### Излучение - *emission*:
|
### Излучение - *emission*:
|
||||||
|
|||||||
@ -62,7 +62,7 @@ void ContentGfxCache::refreshVariant(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
models[def.rt.id] = std::move(model);
|
models[modelKey(def.rt.id, variantIndex)] = std::move(model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,8 +94,8 @@ void ContentGfxCache::refresh() {
|
|||||||
|
|
||||||
ContentGfxCache::~ContentGfxCache() = default;
|
ContentGfxCache::~ContentGfxCache() = default;
|
||||||
|
|
||||||
const model::Model& ContentGfxCache::getModel(blockid_t id) const {
|
const model::Model& ContentGfxCache::getModel(blockid_t id, uint8_t variant) const {
|
||||||
const auto& found = models.find(id);
|
const auto& found = models.find(modelKey(id, variant));
|
||||||
if (found == models.end()) {
|
if (found == models.end()) {
|
||||||
throw std::runtime_error("model not found");
|
throw std::runtime_error("model not found");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,7 +27,11 @@ class ContentGfxCache {
|
|||||||
|
|
||||||
// array of block sides uv regions (6 per block)
|
// array of block sides uv regions (6 per block)
|
||||||
std::unique_ptr<UVRegion[]> sideregions;
|
std::unique_ptr<UVRegion[]> sideregions;
|
||||||
std::unordered_map<blockid_t, model::Model> models;
|
std::unordered_map<uint64_t, model::Model> models;
|
||||||
|
|
||||||
|
static inline uint64_t modelKey(blockid_t id, uint8_t variant) {
|
||||||
|
return (uint64_t(id) << 8) | uint64_t(variant & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
void refreshVariant(
|
void refreshVariant(
|
||||||
const Block& def,
|
const Block& def,
|
||||||
@ -53,7 +57,7 @@ public:
|
|||||||
return sideregions[getRegionIndex(id, variant, side, !dense)];
|
return sideregions[getRegionIndex(id, variant, side, !dense)];
|
||||||
}
|
}
|
||||||
|
|
||||||
const model::Model& getModel(blockid_t id) const;
|
const model::Model& getModel(blockid_t id, uint8_t variant) const;
|
||||||
|
|
||||||
void refresh(const Block& block, const Atlas& atlas);
|
void refresh(const Block& block, const Atlas& atlas);
|
||||||
|
|
||||||
|
|||||||
@ -67,7 +67,7 @@ std::unique_ptr<ImageData> BlocksPreview::draw(
|
|||||||
glm::vec3 poff = glm::vec3(0.0f, 0.0f, 1.0f);
|
glm::vec3 poff = glm::vec3(0.0f, 0.0f, 1.0f);
|
||||||
offset.y += (1.0f - hitbox).y * 0.5f;
|
offset.y += (1.0f - hitbox).y * 0.5f;
|
||||||
shader.uniformMatrix("u_apply", glm::translate(glm::mat4(1.0f), offset));
|
shader.uniformMatrix("u_apply", glm::translate(glm::mat4(1.0f), offset));
|
||||||
const auto& model = cache.getModel(def.rt.id);
|
const auto& model = cache.getModel(def.rt.id, 0);
|
||||||
|
|
||||||
for (const auto& mesh : model.meshes) {
|
for (const auto& mesh : model.meshes) {
|
||||||
for (const auto& vertex : mesh.vertices) {
|
for (const auto& vertex : mesh.vertices) {
|
||||||
|
|||||||
@ -308,7 +308,7 @@ void BlocksRenderer::blockCustomModel(
|
|||||||
Z = orient.axes[2];
|
Z = orient.axes[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& model = cache.getModel(block.rt.id);
|
const auto& model = cache.getModel(block.rt.id, block.getVariantIndex(states.userbits));
|
||||||
for (const auto& mesh : model.meshes) {
|
for (const auto& mesh : model.meshes) {
|
||||||
if (vertexCount + mesh.vertices.size() >= capacity) {
|
if (vertexCount + mesh.vertices.size() >= capacity) {
|
||||||
overflow = true;
|
overflow = true;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user