#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& 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