Merge branch 'main' into physics-upgrade

This commit is contained in:
MihailRis 2026-02-23 17:31:30 +03:00
commit 3cd6ce1df2
13 changed files with 93 additions and 26 deletions

View file

@ -30,7 +30,11 @@ assets.parse_model(
-- Contents of the model file -- Contents of the model file
content: str, content: str,
-- Model name after loading -- Model name after loading
name: str name: str,
-- The skeleton name after loading. May be the same as the model name.
-- The model will be split by the named bones.
[optional]
skeleton_name: string
) )
-- Creates a Canvas from a loaded texture. -- Creates a Canvas from a loaded texture.

View file

@ -31,7 +31,11 @@ assets.parse_model(
-- Содержимое файла модели -- Содержимое файла модели
content: string, content: string,
-- Имя модели после загрузки -- Имя модели после загрузки
name: string name: string,
-- Имя скелета после загрузки. Может совпадать с именем модели.
-- Модель будет разделена по именованным костям.
[опционально]
skeleton_name: string
) )
-- Создаёт холст (Canvas) из загруженной текстуры -- Создаёт холст (Canvas) из загруженной текстуры

View file

@ -1,3 +1,3 @@
<panel size='400' color='#00000080' padding='8'> <panel size='400' color='#00000080' padding='8' max-length='400'>
<!-- content is generated in script --> <!-- content is generated in script -->
</panel> </panel>

View file

@ -803,8 +803,10 @@ void ALAudio::setAcoustics(Acoustics acoustics) {
AL_CHECK(alEffectf( AL_CHECK(alEffectf(
reverbEffect, reverbEffect,
AL_REVERB_GAIN, AL_REVERB_GAIN,
glm::max(0.1f, glm::min(acoustics.reverbGain, 0.8f) * glm::clamp(glm::min(acoustics.reverbGain, 0.8f) *
(1.0f - glm::min(1.0f, acoustics.reverbAbsorption))) (1.0f - glm::min(1.0f, acoustics.reverbAbsorption)),
AL_REVERB_MIN_GAIN,
AL_REVERB_MAX_GAIN)
)); ));
AL_CHECK(alEffectf( AL_CHECK(alEffectf(
reverbEffect, reverbEffect,

View file

@ -251,6 +251,10 @@ void BlocksRenderer::blockAABB(
Z = orient.axes[2]; Z = orient.axes[2];
orient.transform(hitbox); orient.transform(hitbox);
} }
if (block->rt.extended) {
meshAABB.addPoint(coord + hitbox.max());
meshAABB.addPoint(coord + hitbox.min());
}
coord -= glm::vec3(0.5f) - hitbox.center(); coord -= glm::vec3(0.5f) - hitbox.center();
if (ao) { if (ao) {
@ -306,6 +310,12 @@ void BlocksRenderer::blockCustomModel(
if (culled) { if (culled) {
return; return;
} }
} else {
meshAABB.addPoint(
coord + X * glm::vec3(block.size.x) +
Y * glm::vec3(block.size.y) +
Z * glm::vec3(block.size.z)
);
} }
const auto& model = cache.getModel(block.rt.id, block.getVariantIndex(states.userbits)); const auto& model = cache.getModel(block.rt.id, block.getVariantIndex(states.userbits));
@ -687,6 +697,7 @@ SortingMeshData BlocksRenderer::renderTranslucent(
void BlocksRenderer::build( void BlocksRenderer::build(
const Chunk* chunk, const VoxelsRenderVolume& volume const Chunk* chunk, const VoxelsRenderVolume& volume
) { ) {
meshAABB = AABB(glm::vec3(CHUNK_W, CHUNK_H, CHUNK_D));
this->chunk = chunk; this->chunk = chunk;
this->voxelsBuffer = &volume; this->voxelsBuffer = &volume;
if (voxelsBuffer->pickBlockId( if (voxelsBuffer->pickBlockId(
@ -767,7 +778,8 @@ ChunkMeshData BlocksRenderer::createMesh() {
sizeof(ChunkVertex::ATTRIBUTES) / sizeof(VertexAttribute) sizeof(ChunkVertex::ATTRIBUTES) / sizeof(VertexAttribute)
) )
), ),
std::move(sortingMesh) std::move(sortingMesh),
std::move(meshAABB)
}; };
} }
@ -786,7 +798,7 @@ ChunkMesh BlocksRenderer::render(
IndexBufferData {indexBuffer.get(), indexCount}, IndexBufferData {indexBuffer.get(), indexCount},
IndexBufferData {denseIndexBuffer.get(), denseIndexCount}, IndexBufferData {denseIndexBuffer.get(), denseIndexCount},
} }
), std::move(sortingMesh), nullptr}; ), std::move(sortingMesh), nullptr, std::move(meshAABB)};
} }
size_t BlocksRenderer::getMemoryConsumption() const { size_t BlocksRenderer::getMemoryConsumption() const {

View file

@ -6,6 +6,7 @@
#include "voxels/Chunk.hpp" #include "voxels/Chunk.hpp"
#include "voxels/VoxelsVolume.hpp" #include "voxels/VoxelsVolume.hpp"
#include "maths/util.hpp" #include "maths/util.hpp"
#include "maths/aabb.hpp"
#include "commons.hpp" #include "commons.hpp"
#include "settings.hpp" #include "settings.hpp"
@ -56,6 +57,7 @@ private:
bool cancelled = false; bool cancelled = false;
bool densePass = false; bool densePass = false;
bool denseRender = false; bool denseRender = false;
AABB meshAABB {};
const Chunk* chunk = nullptr; const Chunk* chunk = nullptr;
const VoxelsRenderVolume* voxelsBuffer = nullptr; const VoxelsRenderVolume* voxelsBuffer = nullptr;

View file

@ -81,7 +81,9 @@ ChunksRenderer::ChunksRenderer(
meshes[result.key] = ChunkMesh { meshes[result.key] = ChunkMesh {
std::move(chunk), std::move(chunk),
std::move(meshData.sortingMesh), std::move(meshData.sortingMesh),
nullptr}; nullptr,
std::move(meshData.meshAABB)
};
} }
inwork.erase(result.key); inwork.erase(result.key);
}, },
@ -120,7 +122,7 @@ std::shared_ptr<VoxelsRenderVolume> ChunksRenderer::prepareVoxelsVolume(
return voxelsBuffer; return voxelsBuffer;
} }
const Mesh<ChunkVertex>* ChunksRenderer::render( const ChunkMesh* ChunksRenderer::render(
const std::shared_ptr<Chunk>& chunk, bool important, bool lowPriority const std::shared_ptr<Chunk>& chunk, bool important, bool lowPriority
) { ) {
glm::ivec2 key(chunk->x, chunk->z); glm::ivec2 key(chunk->x, chunk->z);
@ -130,7 +132,7 @@ const Mesh<ChunkVertex>* ChunksRenderer::render(
auto voxelsBuffer = prepareVoxelsVolume(*chunk); auto voxelsBuffer = prepareVoxelsVolume(*chunk);
mesh = renderer->render(chunk.get(), *voxelsBuffer); mesh = renderer->render(chunk.get(), *voxelsBuffer);
meshes[key] = std::move(mesh); meshes[key] = std::move(mesh);
return meshes[key].mesh.get(); return &meshes[key];
} }
if (inwork.find(key) != inwork.end() || if (inwork.find(key) != inwork.end() ||
((inwork.size() >= threadPool.getWorkersCount() || ((inwork.size() >= threadPool.getWorkersCount() ||
@ -158,7 +160,7 @@ void ChunksRenderer::clear() {
threadPool.clearQueue(); threadPool.clearQueue();
} }
const Mesh<ChunkVertex>* ChunksRenderer::getOrRender( const ChunkMesh* ChunksRenderer::getOrRender(
const std::shared_ptr<Chunk>& chunk, bool important, bool lowPriority const std::shared_ptr<Chunk>& chunk, bool important, bool lowPriority
) { ) {
auto found = meshes.find(glm::ivec2(chunk->x, chunk->z)); auto found = meshes.find(glm::ivec2(chunk->x, chunk->z));
@ -168,7 +170,7 @@ const Mesh<ChunkVertex>* ChunksRenderer::getOrRender(
if (chunk->flags.modified && chunk->flags.lighted) { if (chunk->flags.modified && chunk->flags.lighted) {
render(chunk, important, lowPriority); render(chunk, important, lowPriority);
} }
return found->second.mesh.get(); return &found->second;
} }
void ChunksRenderer::update() { void ChunksRenderer::update() {
@ -211,16 +213,23 @@ const Mesh<ChunkVertex>* ChunksRenderer::retrieveChunk(
chunk->updateHeights(); chunk->updateHeights();
} }
if (culling) { if (culling) {
glm::vec3 min(chunk->x * CHUNK_W, chunk->bottom, chunk->z * CHUNK_D); const auto& meshAABB = mesh->meshAABB;
auto aabbMin = meshAABB.min();
auto aabbMax = meshAABB.max();
glm::vec3 min(
chunk->x * CHUNK_W + std::min(0.0f, aabbMin.x),
chunk->bottom,
chunk->z * CHUNK_D + std::min(0.0f, aabbMin.z)
);
glm::vec3 max( glm::vec3 max(
chunk->x * CHUNK_W + CHUNK_W, chunk->x * CHUNK_W + aabbMax.x,
chunk->top, chunk->top,
chunk->z * CHUNK_D + CHUNK_D chunk->z * CHUNK_D + aabbMax.z
); );
if (!frustum.isBoxVisible(min, max)) return nullptr; if (!frustum.isBoxVisible(min, max)) return nullptr;
} }
return mesh; return mesh->mesh.get();
} }
void ChunksRenderer::drawShadowsPass( void ChunksRenderer::drawShadowsPass(

View file

@ -71,13 +71,13 @@ public:
); );
virtual ~ChunksRenderer(); virtual ~ChunksRenderer();
const Mesh<ChunkVertex>* render( const ChunkMesh* render(
const std::shared_ptr<Chunk>& chunk, bool important, bool lowPriority const std::shared_ptr<Chunk>& chunk, bool important, bool lowPriority
); );
void unload(const Chunk* chunk); void unload(const Chunk* chunk);
void clear(); void clear();
const Mesh<ChunkVertex>* getOrRender( const ChunkMesh* getOrRender(
const std::shared_ptr<Chunk>& chunk, bool important, bool lowPriority const std::shared_ptr<Chunk>& chunk, bool important, bool lowPriority
); );

View file

@ -2,6 +2,7 @@
#include "constants.hpp" #include "constants.hpp"
#include "graphics/core/MeshData.hpp" #include "graphics/core/MeshData.hpp"
#include "maths/aabb.hpp"
#include "util/Buffer.hpp" #include "util/Buffer.hpp"
#include <vector> #include <vector>
@ -45,12 +46,14 @@ struct SortingMeshData {
struct ChunkMeshData { struct ChunkMeshData {
MeshData<ChunkVertex> mesh; MeshData<ChunkVertex> mesh;
SortingMeshData sortingMesh; SortingMeshData sortingMesh;
AABB meshAABB;
}; };
struct ChunkMesh { struct ChunkMesh {
std::unique_ptr<Mesh<ChunkVertex>> mesh; std::unique_ptr<Mesh<ChunkVertex>> mesh;
SortingMeshData sortingMeshData; SortingMeshData sortingMeshData;
std::unique_ptr<Mesh<ChunkVertex> > sortedMesh; std::unique_ptr<Mesh<ChunkVertex> > sortedMesh;
AABB meshAABB;
}; };
inline constexpr int VOXELS_BUFFER_PADDING = 2; inline constexpr int VOXELS_BUFFER_PADDING = 2;

View file

@ -70,17 +70,46 @@ static int l_parse_model(lua::State* L) {
auto format = lua::require_lstring(L, 1); auto format = lua::require_lstring(L, 1);
auto string = lua::require_lstring(L, 2); auto string = lua::require_lstring(L, 2);
auto name = lua::require_string(L, 3); std::string name = lua::require_string(L, 3);
std::string skeletonName;
if (lua::isstring(L, 4)) {
skeletonName = lua::require_string(L, 4);
}
if (format == "xml" || format == "vcm") { if (format != "xml" && format != "vcm") {
auto vcmModel = vcm::parse(name, string, format == "xml"); throw std::runtime_error(
"unknown format " + util::quote(std::string(format))
);
}
auto vcmModel = vcm::parse(name, string, format == "xml");
if (skeletonName.empty()) {
assets.store( assets.store(
std::make_unique<model::Model>(std::move(vcmModel.squash())), name std::make_unique<model::Model>(std::move(vcmModel.squash())), name
); );
} else { } else {
throw std::runtime_error( auto skeleton = std::make_unique<rigging::SkeletonConfig>(
"unknown format " + util::quote(std::string(format)) std::move(*vcmModel.skeleton)
); );
if (vcmModel.parts.size() > 1) {
for (auto& [partName, model] : vcmModel.parts) {
assets.store(
std::make_unique<model::Model>(std::move(model)),
name + "." + partName
);
}
for (auto& bone : skeleton->getBones()) {
bone->setModel(name + "." + bone->model.name);
}
} else {
assets.store(
std::make_unique<model::Model>(
std::move(vcmModel.parts["root"])), name
);
skeleton->getRoot()->setModel(name);
}
assets.store(std::move(skeleton), skeletonName);
} }
return 0; return 0;
} }

View file

@ -1,13 +1,13 @@
#include "Chunk.hpp" #include "Chunk.hpp"
#include <utility>
#include "content/ContentReport.hpp" #include "content/ContentReport.hpp"
#include "items/Inventory.hpp" #include "items/Inventory.hpp"
#include "lighting/Lightmap.hpp" #include "lighting/Lightmap.hpp"
#include "util/data_io.hpp" #include "util/data_io.hpp"
#include "voxel.hpp" #include "voxel.hpp"
#include <utility>
Chunk::Chunk(int xpos, int zpos, std::shared_ptr<Lightmap> lightmap) Chunk::Chunk(int xpos, int zpos, std::shared_ptr<Lightmap> lightmap)
: x(xpos), z(zpos), lightmap(std::move(lightmap)) { : x(xpos), z(zpos), lightmap(std::move(lightmap)) {
bottom = 0; bottom = 0;
@ -40,6 +40,7 @@ void Chunk::addBlockInventory(
void Chunk::removeBlockInventory(uint x, uint y, uint z) { void Chunk::removeBlockInventory(uint x, uint y, uint z) {
if (inventories.erase(vox_index(x, y, z))) { if (inventories.erase(vox_index(x, y, z))) {
flags.unsaved = true; flags.unsaved = true;
flags.inventoriesRemoved = true;
} }
} }

View file

@ -38,6 +38,7 @@ public:
bool entities : 1; bool entities : 1;
bool blocksData : 1; bool blocksData : 1;
bool dirtyHeights : 1; bool dirtyHeights : 1;
bool inventoriesRemoved : 1;
} flags {}; } flags {};
uint64_t lastRandomTickId = -1; uint64_t lastRandomTickId = -1;

View file

@ -183,7 +183,7 @@ void WorldRegions::put(Chunk* chunk, std::vector<ubyte> entitiesData) {
LIGHTMAP_DATA_LEN); LIGHTMAP_DATA_LEN);
} }
// Writing block inventories // Writing block inventories
if (!chunk->inventories.empty()) { if (!chunk->inventories.empty() || chunk->flags.inventoriesRemoved) {
uint datasize; uint datasize;
auto data = write_inventories(chunk->inventories, datasize); auto data = write_inventories(chunk->inventories, datasize);
put(chunk->x, put(chunk->x,