9using namespace Tempest;
22 for(
size_t r=0;r<att.sub.size();++r) {
23 if(att.sub[r].material.tex==
nullptr) {
24 if(!att.sub[r].texName.empty())
25 Tempest::Log::e(
"no texture: ",att.sub[r].texName);
35 nodes.back().attachId = 0;
36 nodes.back().submeshIdB = 0;
38 nodes.back().transform.identity();
40 bbox[0] = pm.bbox().first;
41 bbox[1] = pm.bbox().second;
48 Log::d(
"skip animations for: ",
fname);
52 const size_t indexSz =
sizeof(int32_t[4])*((pm.verticesId.size()+3)/4);
53 size_t samplesCnt = 0;
55 for(
auto& i:aniList) {
56 samplesCnt += i.samples.size();
62 std::vector<int32_t> remapId;
63 std::vector<Vec4> samples;
66 morph.resize(aniList.size());
67 for(
size_t i=0; i<aniList.size(); ++i) {
68 remap(aniList[i],pm.verticesId,remapId,samples,samplesCnt);
70 morphIndex .update(remapId.data(), i*indexSz, remapId.size()*
sizeof(remapId[0]));
71 morphSamples.update(samples.data(), samplesCnt*
sizeof(Vec4), samples.size()*
sizeof(Vec4) );
73 morph[i] = mkAnimation(aniList[i]);
74 morph[i].index = (i*indexSz)/
sizeof(int32_t);
76 samplesCnt += samples.size();
81 a.morph.anim = &
morph;
89 :skeleton(std::move(sk)), fname(fname) {
90 for(
auto& m:library.mesh.attachments) {
99 for(
size_t i=0;i<
nodes.size();++i) {
102 for(
size_t r=0;r<
attach.size();++r)
103 if(
attach[r].name==src.name){
112 if(i.parentId<
nodes.size())
113 nodes[i.parentId].hasChild=
true;
117 if(i.attachId<
attach.size()) {
118 attach[i.attachId].hasNode =
true;
119 subCount+=
attach[i.attachId].sub.size();
123 subCount+=a.sub.size();
128 i.submeshIdB = subCount;
129 if(i.attachId<
attach.size()) {
130 auto& att =
attach[i.attachId];
131 for(
size_t r=0;r<att.sub.size();++r){
132 if(att.sub[r].material.tex==
nullptr) {
133 if(!att.sub[r].texName.empty())
134 Tempest::Log::e(
"no texture: ",att.sub[r].texName);
142 i.submeshIdE = subCount;
146 for(
size_t i=0;i<library.mesh.meshes.size();++i){
147 auto& mesh = library.mesh.meshes[i];
153 for(
size_t i=0;i<
skeleton->nodes.size();++i) {
155 if(n.name.find(
"ZS_POS")==0){
167ProtoMesh::ProtoMesh(
const zenkit::ModelHierarchy& library, std::unique_ptr<Skeleton>&& sk, std::string_view fname)
168 :skeleton(std::move(sk)), fname(fname) {
170 for(
size_t i = 0; i <
nodes.size(); ++i) {
178 if(i.parentId <
nodes.size())
179 nodes[i.parentId].hasChild =
true;
182 for(
auto& i :
nodes) {
183 i.submeshIdB = subCount;
184 i.submeshIdE = subCount;
189 for(
size_t i = 0; i <
skeleton->nodes.size(); ++i) {
191 if(n.name.find(
"ZS_POS") == 0) {
204 :skeleton(std::move(sk)), fname(fname){
205 for(
auto& m:library.attachments) {
207 attach.emplace_back(pack);
208 auto& att =
attach.back();
214 for(
size_t i=0;i<
nodes.size();++i) {
217 for(
size_t r=0;r<
attach.size();++r)
218 if(
attach[r].name==src.name){
227 if(i.parentId<
nodes.size())
228 nodes[i.parentId].hasChild=
true;
232 if(i.attachId<
attach.size()) {
233 attach[i.attachId].hasNode =
true;
234 subCount+=
attach[i.attachId].sub.size();
238 subCount+=a.sub.size();
243 i.submeshIdB = subCount;
244 if(i.attachId<
attach.size()) {
245 auto& att =
attach[i.attachId];
246 for(
size_t r=0;r<att.sub.size();++r){
247 if(att.sub[r].material.tex==
nullptr) {
248 if(!att.sub[r].texName.empty())
249 Tempest::Log::e(
"no texture: ",att.sub[r].texName);
257 i.submeshIdE = subCount;
261 for(
const auto &i : library.meshes) {
262 if(i.weights.size()<i.mesh.positions.size()){
263 Log::e(
"Vertex stream for skin-mesh \"",
fname,
"\" is too small");
270 for(
size_t i=0;i<
skeleton->nodes.size();++i) {
272 if(n.name.find(
"ZS_POS")==0){
285 attach.emplace_back(mat,std::move(vbo),std::move(ibo));
290 for(
size_t r=0;r<att.sub.size();++r) {
291 if(att.sub[r].material.tex==
nullptr) {
292 if(!att.sub[r].texName.empty())
293 Tempest::Log::e(
"no texture: ",att.sub[r].texName);
302 nodes.emplace_back();
303 nodes.back().attachId = 0;
304 nodes.back().submeshIdB = 0;
306 nodes.back().transform.identity();
322 Tempest::Matrix4x4 m;
325 while(n<
nodes.size()) {
327 auto mx = nx.transform;
338 return skeleton->findNode(name,def);
341void ProtoMesh::setupScheme(std::string_view s) {
342 auto sep = s.find(
"_");
343 if(sep!=std::string::npos) {
348 if(sep!=std::string::npos) {
355void ProtoMesh::remap(
const zenkit::MorphAnimation& a,
356 const std::vector<uint32_t>& vertId,
357 std::vector<int32_t>& remap,
358 std::vector<Tempest::Vec4>& samples,
360 size_t indexSz = ((vertId.size()+3)/4)*4;
361 remap.resize(indexSz);
364 for(
size_t i=0; i<vertId.size(); ++i) {
365 const uint32_t
id = vertId[i];
366 for(
size_t r=0; r<a.vertices.size(); ++r)
367 if(a.vertices[r]==
id) {
368 remap[i] = int(r+idOffset);
373 samples.resize(a.samples.size());
374 for(
size_t i=0; i<a.samples.size(); ++i) {
375 auto& s = a.samples[i];
376 samples[i] = Tempest::Vec4(s.x,s.y,s.z,0);
383 ret.numFrames = a.frame_count;
384 ret.samplesPerFrame = a.samples.size()/a.frame_count;
386 ret.duration = uint64_t(a.duration>0 ? a.duration : 0);
388 if(a.flags&0x2 || a.duration<=0)
389 ret.tickPerFrame = size_t(1.f/a.speed);
else
390 ret.tickPerFrame = size_t(a.duration/
float(a.frame_count));
392 if(ret.tickPerFrame==0)
393 ret.tickPerFrame = 1;
static PhysicMeshShape * load(PackedMesh &&packed)
std::unique_ptr< Skeleton > skeleton
std::vector< AnimMesh > skined
Tempest::StorageBuffer morphSamples
std::vector< Attach > attach
std::vector< Node > nodes
std::vector< Morph > morph
ProtoMesh(PackedMesh &&pm, std::string_view fname)
size_t skinedNodesCount() const
std::vector< SubMeshId > submeshId
Tempest::StorageBuffer morphIndex
size_t findNode(std::string_view name, size_t def=size_t(-1)) const
Tempest::Matrix4x4 mapToRoot(size_t node) const
static Tempest::StorageBuffer ssbo(const void *data, size_t size)
Tempest::Matrix4x4 transform
Tempest::Matrix4x4 transform