323 lines
7.7 KiB
C++
323 lines
7.7 KiB
C++
#include "dl_model_data.h"
|
||
|
||
#ifndef DL_DISABLE_RENDER
|
||
#include "vk/dl_vk.h"
|
||
#include "dl_graphics.h"
|
||
|
||
namespace dl
|
||
{
|
||
|
||
void ModelNodeRt::Save(StreamOutput& s)
|
||
{
|
||
s.Write(&_index);
|
||
s.Write(&_indexSkin);
|
||
s.Write(&_indexParent);
|
||
s.Write(&_trans2Parent);
|
||
s.Write(&_aabb);
|
||
}
|
||
|
||
void ModelNodeRt::Load(StreamInput& s)
|
||
{
|
||
s.Read(&_index);
|
||
s.Read(&_indexSkin);
|
||
s.Read(&_indexParent);
|
||
s.Read(&_trans2Parent);
|
||
s.Read(&_aabb);
|
||
}
|
||
|
||
dl::Matrix4 ModelNodeRt::GetMatrixLocal()
|
||
{
|
||
if (_bNeedUpdateMatrixLocal)
|
||
{
|
||
_matLocal = _trans2Parent.GetMatrix();
|
||
}
|
||
return _matLocal;
|
||
}
|
||
|
||
dl::Matrix4 ModelNodeRt::GetMatrixWorld(ModelAnimationInstance* instance)
|
||
{
|
||
if (_bNeedUpdateMatrixWorld)
|
||
{
|
||
Matrix4 mat = GetMatrixLocal();
|
||
ModelNodeRt* parent = instance->GetNode(_indexParent);
|
||
while (parent)
|
||
{
|
||
mat = parent->GetMatrixLocal() * mat;
|
||
parent = instance->GetNode(parent->_indexParent);
|
||
}
|
||
_matWorld = mat;
|
||
_bNeedUpdateMatrixWorld = false;
|
||
return _matWorld;
|
||
}
|
||
else
|
||
{
|
||
return _matWorld;
|
||
}
|
||
}
|
||
|
||
void ModelNodeRt::Update(const std::vector<ModelSkin>& all_skin,
|
||
ModelAnimationInstance* instance)
|
||
{
|
||
_bNeedUpdateMatrixWorld = true;
|
||
|
||
Matrix4 mat = GetMatrixWorld(instance);
|
||
|
||
if (_indexSkin != -1)
|
||
{
|
||
Matrix4 mat_inv = Mat::GetInverse(mat);
|
||
const ModelSkin& skin = all_skin[_indexSkin];
|
||
// 处理所有影响的节点
|
||
size_t num_joint = std::min(skin._allJoint.size(), NUM_MAX_BONE);
|
||
if (instance->_finalTrans.empty())
|
||
{
|
||
if (skin._allJoint.size() >= NUM_MAX_JOINT)
|
||
log_warn("骨骼数超过上限:{}/{}", skin._allJoint.size(), NUM_MAX_JOINT);
|
||
instance->_finalTrans.resize(num_joint);
|
||
}
|
||
for (size_t i = 0; i < num_joint; ++i)
|
||
{
|
||
int index = skin._allJoint[i];
|
||
ModelNodeRt* node_joint = instance->GetNode(index);
|
||
|
||
Matrix4 mat_joint =
|
||
/*mat_inv **/ node_joint->GetMatrixWorld(instance) * skin._allOffsetMatrix[i];
|
||
|
||
instance->_finalTrans[i] = mat_joint;
|
||
}
|
||
}
|
||
|
||
// Offset Matrix = 骨骼在绑定姿势下的世界矩阵的逆矩阵
|
||
// 1.模型空间(T-pose) -> 骨骼空间
|
||
// 2.骨骼空间 -> 世界空间
|
||
}
|
||
|
||
void BoundingBox::Add(const BoundingBox& b)
|
||
{
|
||
if (!b._vaild)
|
||
return;
|
||
if (!_vaild)
|
||
{
|
||
_min = b._min;
|
||
_max = b._max;
|
||
_vaild = b._vaild;
|
||
}
|
||
else
|
||
{
|
||
_min = Each::Min(_min, b._min);
|
||
_max = Each::Max(_max, b._max);
|
||
}
|
||
}
|
||
|
||
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) const
|
||
{
|
||
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, ModelNodeRt* node) const
|
||
{
|
||
switch (interpolation)
|
||
{
|
||
case ModelAnimationSampler::InterpolationType::LINEAR:
|
||
{
|
||
float u = std::max(0.0f, time - inputs[index]) / (inputs[index + 1] - inputs[index]);
|
||
node->_trans2Parent._t = toShorter(
|
||
Each::Lerp(outputsVec4[index], outputsVec4[index + 1], u));
|
||
node->_bNeedUpdateMatrixLocal;
|
||
break;
|
||
}
|
||
case ModelAnimationSampler::InterpolationType::STEP:
|
||
{
|
||
node->_trans2Parent._t = toShorter(outputsVec4[index]);
|
||
node->_bNeedUpdateMatrixLocal;
|
||
break;
|
||
}
|
||
case ModelAnimationSampler::InterpolationType::CUBICSPLINE:
|
||
{
|
||
node->_trans2Parent._t = toShorter(cubicSplineInterpolation(index, time, 3));
|
||
node->_bNeedUpdateMatrixLocal;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
void ModelAnimationSampler::scale(size_t index, float time, ModelNodeRt* node) const
|
||
{
|
||
switch (interpolation)
|
||
{
|
||
case ModelAnimationSampler::InterpolationType::LINEAR:
|
||
{
|
||
float u = std::max(0.0f, time - inputs[index]) / (inputs[index + 1] - inputs[index]);
|
||
node->_trans2Parent._s = toShorter(
|
||
Each::Lerp(outputsVec4[index], outputsVec4[index + 1], u));
|
||
node->_bNeedUpdateMatrixLocal;
|
||
break;
|
||
}
|
||
case ModelAnimationSampler::InterpolationType::STEP:
|
||
{
|
||
node->_trans2Parent._s = toShorter(outputsVec4[index]);
|
||
node->_bNeedUpdateMatrixLocal;
|
||
break;
|
||
}
|
||
case ModelAnimationSampler::InterpolationType::CUBICSPLINE:
|
||
{
|
||
node->_trans2Parent._s = toShorter(cubicSplineInterpolation(index, time, 3));
|
||
node->_bNeedUpdateMatrixLocal;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
void ModelAnimationSampler::rotate(size_t index, float time, ModelNodeRt* node) const
|
||
{
|
||
switch (interpolation)
|
||
{
|
||
case ModelAnimationSampler::InterpolationType::LINEAR:
|
||
{
|
||
float u = std::max(0.0f, time - inputs[index]) / (inputs[index + 1] - inputs[index]);
|
||
Position4 q1 = outputsVec4[index];
|
||
Position4 q2 = outputsVec4[index + 1];
|
||
node->_trans2Parent._r = Math::Normalize(Math::Slerp(q1, q2, u));
|
||
node->_bNeedUpdateMatrixLocal;
|
||
break;
|
||
}
|
||
case ModelAnimationSampler::InterpolationType::STEP:
|
||
{
|
||
Position4 q1 = outputsVec4[index];
|
||
node->_trans2Parent._r = q1;
|
||
node->_bNeedUpdateMatrixLocal;
|
||
break;
|
||
}
|
||
case ModelAnimationSampler::InterpolationType::CUBICSPLINE:
|
||
{
|
||
Position4 rot = cubicSplineInterpolation(index, time, 4);
|
||
Position4 q = rot;
|
||
node->_trans2Parent._r = Math::Normalize(dl::as_const(q));
|
||
node->_bNeedUpdateMatrixLocal;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
void ModelAnimationSampler::Save(StreamOutput& s)
|
||
{
|
||
s.Write(&interpolation);
|
||
s.Write(&inputs);
|
||
s.Write(&outputsVec4);
|
||
s.Write(&outputs);
|
||
}
|
||
|
||
void ModelAnimationSampler::Load(StreamInput& s)
|
||
{
|
||
s.Read(&interpolation);
|
||
s.Read(&inputs);
|
||
s.Read(&outputsVec4);
|
||
s.Read(&outputs);
|
||
}
|
||
|
||
void ModelMaterial::Save(StreamOutput& s)
|
||
{
|
||
s.Write(&_material);
|
||
s.Write(&_materialName);
|
||
s.Write(&_pathTexDiffuse);
|
||
s.Write(&_pathTexPhysical);
|
||
s.Write(&_pathTexNormal);
|
||
s.Write(&_pathTexAo);
|
||
s.Write(&_pathTexEmissvie);
|
||
}
|
||
|
||
void ModelMaterial::Load(StreamInput& s)
|
||
{
|
||
s.Read(&_material);
|
||
s.Read(&_materialName);
|
||
s.Read(&_pathTexDiffuse);
|
||
s.Read(&_pathTexPhysical);
|
||
s.Read(&_pathTexNormal);
|
||
s.Read(&_pathTexAo);
|
||
s.Read(&_pathTexEmissvie);
|
||
}
|
||
|
||
void ModelSkin::Save(StreamOutput& s)
|
||
{
|
||
s.Write(&name);
|
||
s.Write(&skeletonRoot);
|
||
s.Write(&_allOffsetMatrix);
|
||
s.Write(&_allJoint);
|
||
}
|
||
|
||
void ModelSkin::Load(StreamInput& s)
|
||
{
|
||
s.Read(&name);
|
||
s.Read(&skeletonRoot);
|
||
s.Read(&_allOffsetMatrix);
|
||
s.Read(&_allJoint);
|
||
}
|
||
|
||
void ModelAnimation::Save(StreamOutput& s)
|
||
{
|
||
s.Write(&_name);
|
||
s.WriteSize(&_allSampler);
|
||
for (auto& iter : _allSampler)
|
||
iter.Save(s);
|
||
s.Write(&_allChannel);
|
||
s.Write(&start);
|
||
s.Write(&end);
|
||
}
|
||
|
||
void ModelAnimation::Load(StreamInput& s)
|
||
{
|
||
s.Read(&_name);
|
||
s.ReadSize(&_allSampler);
|
||
for (auto& iter : _allSampler)
|
||
iter.Load(s);
|
||
s.Read(&_allChannel);
|
||
s.Read(&start);
|
||
s.Read(&end);
|
||
}
|
||
|
||
}
|
||
#endif |