194 lines
3.9 KiB
C++
194 lines
3.9 KiB
C++
#include "dl_model_loader.h" // Android dl_concept.h 宏名字冲突需要前置
|
|
|
|
#ifndef DL_DISABLE_RENDER
|
|
|
|
#include "io/dl_log.h"
|
|
#include "render/dl_model.h"
|
|
#include "render/dl_model_object.h"
|
|
|
|
namespace dl
|
|
{
|
|
|
|
std::vector<ModelObject*> ModelObject::Create(std::string_view path_name, std::string_view res_name)
|
|
{
|
|
std::vector<ModelObject*> ret = g_modelLoader->Load(path_name, res_name);
|
|
if (ret.empty())
|
|
{
|
|
log_err("模型加载失败:{}", path_name);
|
|
return {};
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void ModelObject::Load(std::string_view path_name)
|
|
{
|
|
StreamInput s;
|
|
if (!s.LoadFromFile(path_name, true))
|
|
{
|
|
log_warn("文件加载失败:{}", path_name );
|
|
return;
|
|
}
|
|
{
|
|
s.ReadSize(&_treeNode);
|
|
for (size_t i = 0; i < _treeNode.size(); ++i)
|
|
_treeNode[i].Load(s);
|
|
}
|
|
s.Read(&_treeNodeParent);
|
|
s.Read(&_allVertex);
|
|
s.Read(&_allVertexBone);
|
|
s.Read(&_allIndex);
|
|
|
|
{
|
|
s.ReadSize(&_allMaterial);
|
|
for (size_t i = 0; i < _allMaterial.size(); ++i)
|
|
_allMaterial[i].Load(s);
|
|
}
|
|
{
|
|
s.ReadSize(&_allAnimation);
|
|
for (size_t i = 0; i < _allAnimation.size(); ++i)
|
|
_allAnimation[i].Load(s);
|
|
}
|
|
{
|
|
s.ReadSize(&_allSkin);
|
|
for (size_t i = 0; i < _allSkin.size(); ++i)
|
|
_allSkin[i].Load(s);
|
|
}
|
|
s.Read(&_allSub);
|
|
}
|
|
|
|
void ModelObject::SaveToFile(std::string_view path_name)
|
|
{
|
|
StreamOutput s;
|
|
|
|
{
|
|
s.WriteSize(&_treeNode);
|
|
for (size_t i = 0; i < _treeNode.size(); ++i)
|
|
_treeNode[i].Save(s);
|
|
}
|
|
s.Write(&_treeNodeParent);
|
|
s.Write(&_allVertex);
|
|
s.Write(&_allVertexBone);
|
|
s.Write(&_allIndex);
|
|
|
|
{
|
|
s.WriteSize(&_allMaterial);
|
|
for (size_t i = 0; i < _allMaterial.size(); ++i)
|
|
_allMaterial[i].Save(s);
|
|
}
|
|
{
|
|
s.WriteSize(&_allAnimation);
|
|
for (size_t i = 0; i < _allAnimation.size(); ++i)
|
|
_allAnimation[i].Save(s);
|
|
}
|
|
{
|
|
s.WriteSize(&_allSkin);
|
|
for (size_t i = 0; i < _allSkin.size(); ++i)
|
|
_allSkin[i].Save(s);
|
|
}
|
|
s.Write(&_allSub);
|
|
|
|
s.Save(path_name, true);
|
|
}
|
|
|
|
void ModelAnimationInstance::Update(FloatTime dt)
|
|
{
|
|
if (_indexAni >= _model->_allAnimation.size())
|
|
{
|
|
log_warn("动画下标越界!");
|
|
return;
|
|
}
|
|
_t += dt;
|
|
const ModelAnimation& ani = _model->_allAnimation[_indexAni];
|
|
if (_t > ani.end)
|
|
{
|
|
_t = 0;
|
|
}
|
|
|
|
// 动画插值(操作动画控制的节点)
|
|
bool updated = false;
|
|
for (const ModelAnimationChannel& channel : ani._allChannel)
|
|
{
|
|
ModelNodeRt* node = GetNode(channel.indexNode);
|
|
|
|
const ModelAnimationSampler& sampler = ani._allSampler[channel.samplerIndex];
|
|
if (sampler.inputs.size() > sampler.outputsVec4.size())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
float time = _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, node);
|
|
break;
|
|
case ModelAnimationChannel::PathType::SCALE:
|
|
sampler.scale(i, time, node);
|
|
break;
|
|
case ModelAnimationChannel::PathType::ROTATION:
|
|
sampler.rotate(i, time, node);
|
|
break;
|
|
}
|
|
updated = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// 节点树更新
|
|
if (updated)
|
|
{
|
|
UpdateNode();
|
|
}
|
|
}
|
|
|
|
void ModelAnimationInstance::Set(size_t i, float t)
|
|
{
|
|
if (i >= _model->_allAnimation.size())
|
|
{
|
|
log_warn("动画下标越界:{}/{}", i, _model->_allAnimation.size());
|
|
return;
|
|
}
|
|
_indexAni = i;
|
|
_t = t;
|
|
}
|
|
|
|
void ModelAnimationInstance::Set(std::string_view name, float t)
|
|
{
|
|
for (size_t i = 0; i < _model->_allAnimation.size(); ++i)
|
|
{
|
|
if (_model->_allAnimation[i]._name == name)
|
|
{
|
|
_indexAni = i;
|
|
_t = t;
|
|
return;
|
|
}
|
|
}
|
|
log_warn("未找到动画名:{}", name);
|
|
}
|
|
|
|
std::string ModelAnimationInstance::Get()
|
|
{
|
|
return _model->_allAnimation[_indexAni]._name;
|
|
}
|
|
|
|
void ModelAnimationInstance::UpdateNode()
|
|
{
|
|
for (size_t i = 0; i < _treeNode.size(); ++i)
|
|
{
|
|
ModelNodeRt& node = _treeNode[i];
|
|
node.Update(_model->_allSkin, this);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
#endif |