mirror of
https://github.com/luanti-org/luanti.git
synced 2025-06-27 16:36:03 +00:00
boxes
This commit is contained in:
parent
d73b86c16a
commit
6892a5e332
3 changed files with 111 additions and 54 deletions
|
@ -98,12 +98,13 @@ public:
|
||||||
|
|
||||||
//! returns an axis aligned bounding box
|
//! returns an axis aligned bounding box
|
||||||
const core::aabbox3d<f32> &getBoundingBox() const override {
|
const core::aabbox3d<f32> &getBoundingBox() const override {
|
||||||
return BoundingBox;
|
// assert(false); // TODO refactor IMesh so that we don't have to implement this
|
||||||
|
return StaticBoundingBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! set user axis aligned bounding box
|
//! set user axis aligned bounding box
|
||||||
void setBoundingBox(const core::aabbox3df &box) override {
|
void setBoundingBox(const core::aabbox3df &box) override {
|
||||||
BoundingBox = box;
|
// assert(false); // TODO refactor
|
||||||
}
|
}
|
||||||
|
|
||||||
//! set the hardware mapping hint, for driver
|
//! set the hardware mapping hint, for driver
|
||||||
|
@ -153,8 +154,6 @@ public:
|
||||||
//! Moves the mesh into static position.
|
//! Moves the mesh into static position.
|
||||||
void resetAnimation();
|
void resetAnimation();
|
||||||
|
|
||||||
void updateBoundingBox();
|
|
||||||
|
|
||||||
//! Creates an array of joints from this mesh as children of node
|
//! Creates an array of joints from this mesh as children of node
|
||||||
std::vector<IBoneSceneNode *> addJoints(
|
std::vector<IBoneSceneNode *> addJoints(
|
||||||
IAnimatedMeshSceneNode *node, ISceneManager *smgr);
|
IAnimatedMeshSceneNode *node, ISceneManager *smgr);
|
||||||
|
@ -339,6 +338,9 @@ public:
|
||||||
//! Skin weights
|
//! Skin weights
|
||||||
std::vector<SWeight> Weights;
|
std::vector<SWeight> Weights;
|
||||||
|
|
||||||
|
//! Bounding box of all affected vertices, in local space
|
||||||
|
core::aabbox3df LocalBoundingBox{{0, 0, 0}};
|
||||||
|
|
||||||
//! Unnecessary for loaders, will be overwritten on finalize
|
//! Unnecessary for loaders, will be overwritten on finalize
|
||||||
core::matrix4 GlobalMatrix; // loaders may still choose to set this (temporarily) to calculate absolute vertex data.
|
core::matrix4 GlobalMatrix; // loaders may still choose to set this (temporarily) to calculate absolute vertex data.
|
||||||
|
|
||||||
|
@ -353,9 +355,10 @@ public:
|
||||||
//! Animates joints based on frame input
|
//! Animates joints based on frame input
|
||||||
std::vector<SJoint::VariantTransform> animateMesh(f32 frame);
|
std::vector<SJoint::VariantTransform> animateMesh(f32 frame);
|
||||||
|
|
||||||
//! TODO
|
|
||||||
core::aabbox3df calculateBoundingBox(
|
core::aabbox3df calculateBoundingBox(
|
||||||
const std::vector<SJoint::VariantTransform> &transforms);
|
const std::vector<core::matrix4> &global_transforms);
|
||||||
|
|
||||||
|
void recalculateBaseBoundingBoxes();
|
||||||
|
|
||||||
const std::vector<SJoint *> &getAllJoints() const {
|
const std::vector<SJoint *> &getAllJoints() const {
|
||||||
return AllJoints;
|
return AllJoints;
|
||||||
|
@ -368,6 +371,10 @@ protected:
|
||||||
|
|
||||||
void prepareForSkinning();
|
void prepareForSkinning();
|
||||||
|
|
||||||
|
void calculateStaticBoundingBox();
|
||||||
|
void calculateJointBoundingBoxes();
|
||||||
|
void calculateBufferBoundingBoxes();
|
||||||
|
|
||||||
void normalizeWeights();
|
void normalizeWeights();
|
||||||
|
|
||||||
void calculateTangents(core::vector3df &normal,
|
void calculateTangents(core::vector3df &normal,
|
||||||
|
@ -388,7 +395,8 @@ protected:
|
||||||
// doesn't allow taking a reference to individual elements.
|
// doesn't allow taking a reference to individual elements.
|
||||||
std::vector<std::vector<char>> Vertices_Moved;
|
std::vector<std::vector<char>> Vertices_Moved;
|
||||||
|
|
||||||
core::aabbox3d<f32> BoundingBox{{0, 0, 0}};
|
//! Bounding box of just the static parts of the mesh
|
||||||
|
core::aabbox3d<f32> StaticBoundingBox{{0, 0, 0}};
|
||||||
|
|
||||||
f32 EndFrame;
|
f32 EndFrame;
|
||||||
f32 FramesPerSecond;
|
f32 FramesPerSecond;
|
||||||
|
|
|
@ -148,8 +148,11 @@ void CAnimatedMeshSceneNode::OnRegisterSceneNode()
|
||||||
|
|
||||||
IMesh *CAnimatedMeshSceneNode::getMeshForCurrentFrame()
|
IMesh *CAnimatedMeshSceneNode::getMeshForCurrentFrame()
|
||||||
{
|
{
|
||||||
if (Mesh->getMeshType() != EAMT_SKINNED)
|
if (Mesh->getMeshType() != EAMT_SKINNED) {
|
||||||
return Mesh->getMesh(getFrameNr());
|
auto *res = Mesh->getMesh(getFrameNr());
|
||||||
|
Box = res->getBoundingBox();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
// As multiple scene nodes may be sharing the same skinned mesh, we have to
|
// As multiple scene nodes may be sharing the same skinned mesh, we have to
|
||||||
// re-animate it every frame to ensure that this node gets the mesh that it needs.
|
// re-animate it every frame to ensure that this node gets the mesh that it needs.
|
||||||
|
@ -164,9 +167,9 @@ IMesh *CAnimatedMeshSceneNode::getMeshForCurrentFrame()
|
||||||
|
|
||||||
skinnedMesh->skinMesh(matrices);
|
skinnedMesh->skinMesh(matrices);
|
||||||
|
|
||||||
skinnedMesh->updateBoundingBox();
|
// TODO this should have happened *before* the skinning in OnAnimate;
|
||||||
|
// we should thus probably store the global matrices.
|
||||||
Box = skinnedMesh->getBoundingBox();
|
Box = skinnedMesh->calculateBoundingBox(matrices);
|
||||||
|
|
||||||
return skinnedMesh;
|
return skinnedMesh;
|
||||||
}
|
}
|
||||||
|
@ -206,7 +209,6 @@ void CAnimatedMeshSceneNode::render()
|
||||||
|
|
||||||
scene::IMesh *m = getMeshForCurrentFrame();
|
scene::IMesh *m = getMeshForCurrentFrame();
|
||||||
_IRR_DEBUG_BREAK_IF(!m);
|
_IRR_DEBUG_BREAK_IF(!m);
|
||||||
Box = m->getBoundingBox(); // HACK
|
|
||||||
|
|
||||||
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
|
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "MatrixBoneSceneNode.h"
|
#include "MatrixBoneSceneNode.h"
|
||||||
#include "SSkinMeshBuffer.h"
|
#include "SSkinMeshBuffer.h"
|
||||||
#include "Transform.h"
|
#include "Transform.h"
|
||||||
|
#include "aabbox3d.h"
|
||||||
#include "irrMath.h"
|
#include "irrMath.h"
|
||||||
#include "matrix4.h"
|
#include "matrix4.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
|
@ -70,6 +71,28 @@ std::vector<VariantTransform> SkinnedMesh::animateMesh(f32 frame)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
core::aabbox3df SkinnedMesh::calculateBoundingBox(
|
||||||
|
const std::vector<core::matrix4> &global_transforms)
|
||||||
|
{
|
||||||
|
assert(global_transforms.size() == AllJoints.size());
|
||||||
|
core::aabbox3df result = StaticBoundingBox;
|
||||||
|
// skeletal animation
|
||||||
|
for (u16 i = 0; i < AllJoints.size(); ++i) {
|
||||||
|
auto box = AllJoints[i]->LocalBoundingBox;
|
||||||
|
global_transforms[i].transformBoxEx(box);
|
||||||
|
result.addInternalBox(box);
|
||||||
|
}
|
||||||
|
// rigid animation
|
||||||
|
for (u16 i = 0; i < AllJoints.size(); ++i) {
|
||||||
|
for (u32 j : AllJoints[i]->AttachedMeshes) {
|
||||||
|
auto box = (*SkinningBuffers)[j]->BoundingBox;
|
||||||
|
global_transforms[i].transformBoxEx(box);
|
||||||
|
result.addInternalBox(box);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// Software Skinning
|
// Software Skinning
|
||||||
|
|
||||||
void SkinnedMesh::skinMesh(const std::vector<core::matrix4> &global_matrices)
|
void SkinnedMesh::skinMesh(const std::vector<core::matrix4> &global_matrices)
|
||||||
|
@ -131,8 +154,6 @@ void SkinnedMesh::skinMesh(const std::vector<core::matrix4> &global_matrices)
|
||||||
|
|
||||||
//*(weight._Pos) += thisVertexMove * weight.strength;
|
//*(weight._Pos) += thisVertexMove * weight.strength;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffersUsed[weight.buffer_id]->boundingBoxNeedsRecalculated();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -314,8 +335,6 @@ void SkinnedMesh::prepareForSkinning()
|
||||||
weight.Moved = &Vertices_Moved[buffer_id][vertex_id];
|
weight.Moved = &Vertices_Moved[buffer_id][vertex_id];
|
||||||
weight.StaticPos = LocalBuffers[buffer_id]->getVertex(vertex_id)->Pos;
|
weight.StaticPos = LocalBuffers[buffer_id]->getVertex(vertex_id)->Pos;
|
||||||
weight.StaticNormal = LocalBuffers[buffer_id]->getVertex(vertex_id)->Normal;
|
weight.StaticNormal = LocalBuffers[buffer_id]->getVertex(vertex_id)->Normal;
|
||||||
|
|
||||||
// weight._Pos=&Buffers[buffer_id]->getVertex(vertex_id)->Pos;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,6 +345,70 @@ void SkinnedMesh::prepareForSkinning()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkinnedMesh::calculateStaticBoundingBox()
|
||||||
|
{
|
||||||
|
std::vector<std::vector<bool>> animated(getMeshBufferCount());
|
||||||
|
for (u32 mb = 0; mb < getMeshBufferCount(); mb++)
|
||||||
|
animated[mb] = std::vector<bool>(getMeshBuffer(mb)->getVertexCount());
|
||||||
|
|
||||||
|
for (auto *joint : AllJoints) {
|
||||||
|
for (auto &weight : joint->Weights) {
|
||||||
|
const u16 buffer_id = weight.buffer_id;
|
||||||
|
const u32 vertex_id = weight.vertex_id;
|
||||||
|
animated[buffer_id][vertex_id] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool first = true;
|
||||||
|
for (u16 mb = 0; mb < getMeshBufferCount(); mb++) {
|
||||||
|
for (u32 v = 0; v < getMeshBuffer(mb)->getVertexCount(); v++) {
|
||||||
|
if (!animated[mb][v]) {
|
||||||
|
auto pos = getMeshBuffer(mb)->getVertexBuffer()->getPosition(v);
|
||||||
|
if (!first) {
|
||||||
|
StaticBoundingBox.addInternalPoint(pos);
|
||||||
|
} else {
|
||||||
|
StaticBoundingBox.reset(pos);
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkinnedMesh::calculateJointBoundingBoxes()
|
||||||
|
{
|
||||||
|
for (auto *joint : AllJoints) {
|
||||||
|
bool first = true;
|
||||||
|
for (auto &weight : joint->Weights) {
|
||||||
|
if (weight.strength < 1e-6)
|
||||||
|
continue;
|
||||||
|
auto pos = weight.StaticPos;
|
||||||
|
joint->GlobalInversedMatrix.value().transformVect(pos);
|
||||||
|
if (!first) {
|
||||||
|
joint->LocalBoundingBox.addInternalPoint(pos);
|
||||||
|
} else {
|
||||||
|
joint->LocalBoundingBox.reset(pos);
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkinnedMesh::calculateBufferBoundingBoxes()
|
||||||
|
{
|
||||||
|
for (u32 j = 0; j < LocalBuffers.size(); ++j) {
|
||||||
|
// If we use skeletal animation, this will just be a bounding box of the static pose;
|
||||||
|
// if we use rigid animation, this will correctly transform the points first.
|
||||||
|
LocalBuffers[j]->recalculateBoundingBox();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkinnedMesh::recalculateBaseBoundingBoxes() {
|
||||||
|
calculateStaticBoundingBox();
|
||||||
|
calculateJointBoundingBoxes();
|
||||||
|
calculateBufferBoundingBoxes();
|
||||||
|
}
|
||||||
|
|
||||||
void SkinnedMesh::topoSortJoints()
|
void SkinnedMesh::topoSortJoints()
|
||||||
{
|
{
|
||||||
size_t n = AllJoints.size();
|
size_t n = AllJoints.size();
|
||||||
|
@ -368,11 +451,6 @@ SkinnedMesh *SkinnedMeshBuilder::finalize()
|
||||||
|
|
||||||
topoSortJoints();
|
topoSortJoints();
|
||||||
|
|
||||||
// Calculate bounding box
|
|
||||||
for (auto *buffer : LocalBuffers) {
|
|
||||||
buffer->recalculateBoundingBox();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set array sizes
|
// Set array sizes
|
||||||
for (u32 i = 0; i < LocalBuffers.size(); ++i) {
|
for (u32 i = 0; i < LocalBuffers.size(); ++i) {
|
||||||
Vertices_Moved.emplace_back(LocalBuffers[i]->getVertexCount());
|
Vertices_Moved.emplace_back(LocalBuffers[i]->getVertexCount());
|
||||||
|
@ -382,7 +460,6 @@ SkinnedMesh *SkinnedMeshBuilder::finalize()
|
||||||
|
|
||||||
std::vector<core::matrix4> matrices;
|
std::vector<core::matrix4> matrices;
|
||||||
matrices.reserve(AllJoints.size());
|
matrices.reserve(AllJoints.size());
|
||||||
// TODO populate with local matrices
|
|
||||||
for (auto *joint : AllJoints) {
|
for (auto *joint : AllJoints) {
|
||||||
if (const auto *matrix = std::get_if<core::matrix4>(&joint->transform))
|
if (const auto *matrix = std::get_if<core::matrix4>(&joint->transform))
|
||||||
matrices.push_back(*matrix);
|
matrices.push_back(*matrix);
|
||||||
|
@ -403,41 +480,11 @@ SkinnedMesh *SkinnedMeshBuilder::finalize()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate bounding box
|
recalculateBaseBoundingBoxes();
|
||||||
if (LocalBuffers.empty())
|
|
||||||
BoundingBox.reset(0, 0, 0);
|
|
||||||
else {
|
|
||||||
irr::core::aabbox3df bb(LocalBuffers[0]->BoundingBox);
|
|
||||||
LocalBuffers[0]->Transformation.transformBoxEx(bb);
|
|
||||||
BoundingBox.reset(bb);
|
|
||||||
|
|
||||||
for (u32 j = 1; j < LocalBuffers.size(); ++j) {
|
|
||||||
bb = LocalBuffers[j]->BoundingBox;
|
|
||||||
LocalBuffers[j]->Transformation.transformBoxEx(bb);
|
|
||||||
|
|
||||||
BoundingBox.addInternalBox(bb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkinnedMesh::updateBoundingBox()
|
|
||||||
{
|
|
||||||
if (!SkinningBuffers)
|
|
||||||
return;
|
|
||||||
|
|
||||||
BoundingBox.reset(0, 0, 0);
|
|
||||||
|
|
||||||
for (auto *buffer : *SkinningBuffers) {
|
|
||||||
buffer->recalculateBoundingBox();
|
|
||||||
core::aabbox3df bb = buffer->BoundingBox;
|
|
||||||
buffer->Transformation.transformBoxEx(bb);
|
|
||||||
|
|
||||||
BoundingBox.addInternalBox(bb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
scene::SSkinMeshBuffer *SkinnedMeshBuilder::addMeshBuffer()
|
scene::SSkinMeshBuffer *SkinnedMeshBuilder::addMeshBuffer()
|
||||||
{
|
{
|
||||||
scene::SSkinMeshBuffer *buffer = new scene::SSkinMeshBuffer();
|
scene::SSkinMeshBuffer *buffer = new scene::SSkinMeshBuffer();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue