270 lines
6.8 KiB
C++
270 lines
6.8 KiB
C++
#include "dl_model_data.h"
|
|
|
|
#include "vk/dl_vk.h"
|
|
|
|
namespace dl
|
|
{
|
|
|
|
dl::Matrix4 ModelNode::Runtime::GetMatrixLocal()
|
|
{
|
|
if (_bNeedUpdateMatrixLocal)
|
|
{
|
|
_matLocal = _trans2Parent.GetMatrix();
|
|
}
|
|
return _matLocal;
|
|
}
|
|
|
|
dl::Matrix4 ModelNode::Runtime::GetMatrixWorld(ModelNode* node)
|
|
{
|
|
if (_bNeedUpdateMatrixWorld)
|
|
{
|
|
Matrix4 mat = GetMatrixLocal();
|
|
ModelNode* p = node;
|
|
while (p)
|
|
{
|
|
mat = p->_rt.GetMatrixLocal() * mat;
|
|
p = p->_parent;
|
|
}
|
|
_matWorld = mat;
|
|
_bNeedUpdateMatrixWorld = false;
|
|
return mat;
|
|
}
|
|
else
|
|
{
|
|
return _matWorld;
|
|
}
|
|
}
|
|
|
|
void ModelNode::Update()
|
|
{
|
|
_rt._bNeedUpdateMatrixWorld = true;
|
|
if (_mesh)
|
|
{
|
|
ModelMesh::Runtime& rt_mesh = _mesh->_rt;
|
|
Matrix4 mat = GetMatrixWorld();
|
|
if (_skin)
|
|
{
|
|
rt_mesh._mat = mat;
|
|
// Update join matrices
|
|
Matrix4 mat_mesh_inv = Mat::GetInverse(mat);
|
|
|
|
size_t num_joint = std::min(_skin->_allJoint.size(), NUM_MAX_JOINT);
|
|
rt_mesh._allMatJoint.resize(num_joint);
|
|
for (size_t i = 0; i < num_joint; ++i)
|
|
{
|
|
ModelNode* node_joint = _skin->_allJoint[i];
|
|
Matrix4 mat_joint = node_joint->GetMatrixWorld() * _skin->_allOffsetMatrix[i];
|
|
mat_joint = mat_mesh_inv * mat_joint;
|
|
rt_mesh._allMatJoint[i] = mat_joint;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rt_mesh._allMatJoint.resize(1);
|
|
rt_mesh._allMatJoint[0] = mat;
|
|
}
|
|
}
|
|
|
|
for (ModelNode* node : _allChild)
|
|
{
|
|
node->Update();
|
|
}
|
|
}
|
|
|
|
void ModelData::Update()
|
|
{
|
|
if (_allAnimation.empty())
|
|
{
|
|
log_warn("模型没有动画!");
|
|
return;
|
|
}
|
|
ModelAnimation& ani = _allAnimation[_rt._curAni];
|
|
|
|
bool updated = false;
|
|
for (ModelAnimationChannel& channel : ani._allChannel)
|
|
{
|
|
ModelAnimationSampler& sampler = ani._allSampler[channel.samplerIndex];
|
|
if (sampler.inputs.size() > sampler.outputsVec4.size())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
float time = _rt._t;
|
|
for (size_t i = 0; i < sampler.inputs.size() - 1; i++)
|
|
{
|
|
if (time >= sampler.inputs[i]
|
|
&& time <= sampler.inputs[i + 1])
|
|
{
|
|
float u = std::max(0.0f, time - sampler.inputs[i])
|
|
/ (sampler.inputs[i + 1] - sampler.inputs[i]);
|
|
if (u <= 1.0f)
|
|
{
|
|
switch (channel.path)
|
|
{
|
|
case ModelAnimationChannel::PathType::TRANSLATION:
|
|
sampler.translate(i, time, channel.node);
|
|
break;
|
|
case ModelAnimationChannel::PathType::SCALE:
|
|
sampler.scale(i, time, channel.node);
|
|
break;
|
|
case ModelAnimationChannel::PathType::ROTATION:
|
|
sampler.rotate(i, time, channel.node);
|
|
break;
|
|
}
|
|
updated = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (updated)
|
|
{
|
|
for (ModelNode* node : _allNode)
|
|
{
|
|
node->Update();
|
|
}
|
|
}
|
|
}
|
|
|
|
BoundingBox::BoundingBox()
|
|
{
|
|
|
|
}
|
|
|
|
BoundingBox::BoundingBox(Position3 imin, Position3 imax):
|
|
min{imin},
|
|
max{imax}
|
|
{
|
|
|
|
}
|
|
|
|
BoundingBox BoundingBox::getAABB(Matrix4 m)
|
|
{
|
|
Position3 min = toShorter(m[3]);
|
|
Position3 max = min;
|
|
Position3 v0, v1;
|
|
|
|
Position3 right = toShorter(m[0]);
|
|
v0 = right * this->min[0];
|
|
v1 = right * this->max[0];
|
|
min += Each::Min(v0, v1);
|
|
max += Each::Max(v0, v1);
|
|
|
|
Position3 up = toShorter(m[1]);
|
|
v0 = up * this->min[1];
|
|
v1 = up * this->max[1];
|
|
min += Each::Min(v0, v1);
|
|
max += Each::Max(v0, v1);
|
|
|
|
Position3 back = toShorter(m[2]);
|
|
v0 = back * this->min[2];
|
|
v1 = back * this->max[2];
|
|
min += Each::Min(v0, v1);
|
|
max += Each::Max(v0, v1);
|
|
|
|
return BoundingBox(min, max);
|
|
}
|
|
|
|
dl::Position4 ModelAnimationSampler::cubicSplineInterpolation(size_t index, float time, uint32_t stride)
|
|
{
|
|
float delta = inputs[index + 1] - inputs[index];
|
|
float t = (time - inputs[index]) / delta;
|
|
const size_t current = index * stride * 3;
|
|
const size_t next = (index + 1) * stride * 3;
|
|
const size_t A = 0;
|
|
const size_t V = stride * 1;
|
|
const size_t B = stride * 2;
|
|
|
|
float t2 = powf(t, 2);
|
|
float t3 = powf(t, 3);
|
|
Position4 pt{};
|
|
for (uint32_t i = 0; i < stride; i++) {
|
|
float p0 = outputs[current + i + V]; // starting point at t = 0
|
|
float m0 = delta * outputs[current + i + A]; // scaled starting tangent at t = 0
|
|
float p1 = outputs[next + i + V]; // ending point at t = 1
|
|
float m1 = delta * outputs[next + i + B]; // scaled ending tangent at t = 1
|
|
pt[i] = ((2.f * t3 - 3.f * t2 + 1.f) * p0) + ((t3 - 2.f * t2 + t) * m0) + ((-2.f * t3 + 3.f * t2) * p1) + ((t3 - t2) * m0);
|
|
}
|
|
return pt;
|
|
}
|
|
|
|
void ModelAnimationSampler::translate(size_t index, float time, ModelNode* node)
|
|
{
|
|
switch (interpolation) {
|
|
case ModelAnimationSampler::InterpolationType::LINEAR: {
|
|
float u = std::max(0.0f, time - inputs[index]) / (inputs[index + 1] - inputs[index]);
|
|
node->_rt._trans2Parent._t = toShorter(
|
|
Each::Lerp(outputsVec4[index], outputsVec4[index + 1], u));
|
|
break;
|
|
}
|
|
case ModelAnimationSampler::InterpolationType::STEP: {
|
|
node->_rt._trans2Parent._t = toShorter(outputsVec4[index]);
|
|
break;
|
|
}
|
|
case ModelAnimationSampler::InterpolationType::CUBICSPLINE: {
|
|
node->_rt._trans2Parent._t = toShorter(cubicSplineInterpolation(index, time, 3));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ModelAnimationSampler::scale(size_t index, float time, ModelNode* node)
|
|
{
|
|
switch (interpolation) {
|
|
case ModelAnimationSampler::InterpolationType::LINEAR: {
|
|
float u = std::max(0.0f, time - inputs[index]) / (inputs[index + 1] - inputs[index]);
|
|
node->_rt._trans2Parent._s = toShorter(
|
|
Each::Lerp(outputsVec4[index], outputsVec4[index + 1], u));
|
|
break;
|
|
}
|
|
case ModelAnimationSampler::InterpolationType::STEP: {
|
|
node->_rt._trans2Parent._s = toShorter(outputsVec4[index]);
|
|
break;
|
|
}
|
|
case ModelAnimationSampler::InterpolationType::CUBICSPLINE: {
|
|
node->_rt._trans2Parent._s = toShorter(cubicSplineInterpolation(index, time, 3));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ModelAnimationSampler::rotate(size_t index, float time, ModelNode* node)
|
|
{
|
|
switch (interpolation) {
|
|
case ModelAnimationSampler::InterpolationType::LINEAR: {
|
|
float u = std::max(0.0f, time - inputs[index]) / (inputs[index + 1] - inputs[index]);
|
|
Position4 q1;
|
|
q1[0] = outputsVec4[index][0];
|
|
q1[1] = outputsVec4[index][1];
|
|
q1[2] = outputsVec4[index][2];
|
|
q1[3] = outputsVec4[index][3];
|
|
Position4 q2;
|
|
q2[0] = outputsVec4[index + 1][0];
|
|
q2[1] = outputsVec4[index + 1][1];
|
|
q2[2] = outputsVec4[index + 1][2];
|
|
q2[3] = outputsVec4[index + 1][3];
|
|
node->_rt._trans2Parent._r = Math::Normalize(Math::Slerp(q1, q2, u));
|
|
break;
|
|
}
|
|
case ModelAnimationSampler::InterpolationType::STEP: {
|
|
Position4 q1;
|
|
q1[0] = outputsVec4[index][0];
|
|
q1[1] = outputsVec4[index][1];
|
|
q1[2] = outputsVec4[index][2];
|
|
q1[3] = outputsVec4[index][3];
|
|
node->_rt._trans2Parent._r = q1;
|
|
break;
|
|
}
|
|
case ModelAnimationSampler::InterpolationType::CUBICSPLINE: {
|
|
Position4 rot = cubicSplineInterpolation(index, time, 4);
|
|
Position4 q;
|
|
q[0] = rot[0];
|
|
q[1] = rot[1];
|
|
q[2] = rot[2];
|
|
q[3] = rot[3];
|
|
node->_rt._trans2Parent._r = Math::Normalize(std::as_const(q));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
} |