Convert spm to GE spm

This commit is contained in:
Benau 2022-05-23 13:46:03 +08:00
parent 096b408b9c
commit 92accb352e
2 changed files with 161 additions and 17 deletions

View File

@ -37,6 +37,9 @@ const uint8_t VERSION_NOW = 1;
#include <IVideoDriver.h> #include <IVideoDriver.h>
#include <IFileSystem.h> #include <IFileSystem.h>
#ifndef SERVER_ONLY #ifndef SERVER_ONLY
#include <ge_main.hpp>
#include <ge_spm_buffer.hpp>
#include <ge_spm.hpp>
#include <ge_texture.hpp> #include <ge_texture.hpp>
#endif #endif
@ -67,7 +70,19 @@ scene::IAnimatedMesh* SPMeshLoader::createMesh(io::IReadFile* f)
m_joint_count = 0; m_joint_count = 0;
m_frame_count = 0; m_frame_count = 0;
m_mesh = NULL; m_mesh = NULL;
m_mesh = real_spm ? new SP::SPMesh() : m_scene_manager->createSkinnedMesh(); bool ge_spm = false;
#ifndef SERVER_ONLY
if (GE::getVKDriver())
{
ge_spm = true;
m_mesh = new GE::GESPM();
}
#endif
if (!m_mesh)
{
m_mesh = real_spm ?
new SP::SPMesh() : m_scene_manager->createSkinnedMesh();
}
io::IFileSystem* fs = m_scene_manager->getFileSystem(); io::IFileSystem* fs = m_scene_manager->getFileSystem();
std::string base_path = fs->getFileDir(f->getFileName()).c_str(); std::string base_path = fs->getFileDir(f->getFileName()).c_str();
std::string header; std::string header;
@ -257,6 +272,14 @@ scene::IAnimatedMesh* SPMeshLoader::createMesh(io::IReadFile* f)
std::get<2>(sp_mat_map[mat_id]), vt, std::get<2>(sp_mat_map[mat_id]), vt,
std::get<0>(sp_mat_map[mat_id])); std::get<0>(sp_mat_map[mat_id]));
} }
else if (ge_spm)
{
assert(mat_id < mat_map.size());
decompressGESPM(f, vertices_count, indices_count, read_normal,
read_vcolor, read_tangent, std::get<1>(mat_map[mat_id]),
std::get<2>(mat_map[mat_id]), vt,
std::get<0>(mat_map[mat_id]));
}
else else
{ {
assert(mat_id < mat_map.size()); assert(mat_id < mat_map.size());
@ -313,11 +336,11 @@ scene::IAnimatedMesh* SPMeshLoader::createMesh(io::IReadFile* f)
spm->m_all_armatures = std::move(m_all_armatures); spm->m_all_armatures = std::move(m_all_armatures);
} }
m_mesh->finalize(); m_mesh->finalize();
if (!real_spm && has_armature) scene::CSkinnedMesh* cmesh = dynamic_cast<scene::CSkinnedMesh*>(m_mesh);
if (cmesh && !real_spm && has_armature)
{ {
// Because the last frame in spm is usable // Because the last frame in spm is usable
static_cast<scene::CSkinnedMesh*>(m_mesh)->AnimationFrames = cmesh->AnimationFrames = (float)m_frame_count + 1.0f;
(float)m_frame_count + 1.0f;
} }
m_all_armatures.clear(); m_all_armatures.clear();
m_to_bind_pose_matrices.clear(); m_to_bind_pose_matrices.clear();
@ -431,6 +454,118 @@ void SPMeshLoader::decompressSPM(irr::io::IReadFile* spm,
} // decompressSPM } // decompressSPM
// ----------------------------------------------------------------------------
void SPMeshLoader::decompressGESPM(irr::io::IReadFile* spm,
unsigned vertices_count,
unsigned indices_count, bool read_normal,
bool read_vcolor, bool read_tangent,
bool uv_one, bool uv_two, SPVertexType vt,
const video::SMaterial& m)
{
#ifndef SERVER_ONLY
assert(vertices_count != 0);
assert(indices_count != 0);
GE::GESPMBuffer* mb = new GE::GESPMBuffer();
static_cast<GE::GESPM*>(m_mesh)->m_buffer.push_back(mb);
std::vector<video::S3DVertexSkinnedMesh> vertices;
const unsigned idx_size = vertices_count > 255 ? 2 : 1;
for (unsigned i = 0; i < vertices_count; i++)
{
video::S3DVertexSkinnedMesh vertex = {};
// 3 * float position
spm->read(&vertex.m_position, 12);
if (read_normal)
{
spm->read(&vertex.m_normal, 4);
}
else
{
// 0, 1, 0
vertex.m_normal = 0x1FF << 10;
}
if (read_vcolor)
{
// Color identifier
uint8_t ci;
spm->read(&ci, 1);
if (ci == 128)
{
// All white
vertex.m_color = video::SColor(255, 255, 255, 255);
}
else
{
uint8_t r, g, b;
spm->read(&r, 1);
spm->read(&g, 1);
spm->read(&b, 1);
vertex.m_color = video::SColor(255, r, g, b);
}
}
else
{
vertex.m_color = video::SColor(255, 255, 255, 255);
}
if (uv_one)
{
spm->read(&vertex.m_all_uvs[0], 4);
if (uv_two)
{
spm->read(&vertex.m_all_uvs[2], 4);
}
if (read_tangent)
{
spm->read(&vertex.m_tangent, 4);
}
else
{
vertex.m_tangent = MiniGLM::quickTangent(vertex.m_normal);
}
}
if (vt == SPVT_SKINNED)
{
spm->read(&vertex.m_joint_idx[0], 16);
if (vertex.m_joint_idx[0] == -1 ||
vertex.m_weight[0] == 0 ||
// -0.0 in half float (16bit)
vertex.m_weight[0] == -32768)
{
// For the skinned mesh shader
vertex.m_joint_idx[0] = -32767;
// 1.0 in half float (16bit)
vertex.m_weight[0] = 15360;
}
}
vertices.push_back(vertex);
}
std::vector<uint16_t> indices;
indices.resize(indices_count);
if (idx_size == 2)
{
spm->read(indices.data(), indices_count * 2);
}
else
{
std::vector<uint8_t> tmp_idx;
tmp_idx.resize(indices_count);
spm->read(tmp_idx.data(), indices_count);
for (unsigned i = 0; i < indices_count; i++)
{
indices[i] = tmp_idx[i];
}
}
std::swap(mb->m_vertices, vertices);
std::swap(mb->m_indices, indices);
if (m.TextureLayer[0].Texture != NULL)
{
mb->m_material = m;
}
mb->recalculateBoundingBox();
#endif
} // decompressGESPM
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void SPMeshLoader::decompress(irr::io::IReadFile* spm, unsigned vertices_count, void SPMeshLoader::decompress(irr::io::IReadFile* spm, unsigned vertices_count,
unsigned indices_count, bool read_normal, unsigned indices_count, bool read_normal,
@ -440,7 +575,8 @@ void SPMeshLoader::decompress(irr::io::IReadFile* spm, unsigned vertices_count,
{ {
assert(vertices_count != 0); assert(vertices_count != 0);
assert(indices_count != 0); assert(indices_count != 0);
scene::SSkinMeshBuffer* mb = m_mesh->addMeshBuffer(); scene::SSkinMeshBuffer* mb =
static_cast<scene::CSkinnedMesh*>(m_mesh)->addMeshBuffer();
if (uv_two) if (uv_two)
{ {
mb->convertTo2TCoords(); mb->convertTo2TCoords();
@ -603,17 +739,18 @@ void SPMeshLoader::createAnimationData(irr::io::IReadFile* spm)
accumulated_joints += m_all_armatures[i].m_joint_used; accumulated_joints += m_all_armatures[i].m_joint_used;
} }
scene::ISkinnedMesh* smesh = dynamic_cast<scene::ISkinnedMesh*>(m_mesh);
// Only for legacy device // Only for legacy device
if (m_joints.empty()) if (!smesh || m_joints.empty())
{ {
return; return;
} }
assert(m_joints.size() == m_mesh->getMeshBufferCount()); assert(m_joints.size() == smesh->getMeshBufferCount());
for (unsigned i = 0; i < m_to_bind_pose_matrices.size(); i++) for (unsigned i = 0; i < m_to_bind_pose_matrices.size(); i++)
{ {
m_to_bind_pose_matrices[i].makeInverse(); m_to_bind_pose_matrices[i].makeInverse();
} }
for (unsigned i = 0; i < m_mesh->getMeshBufferCount(); i++) for (unsigned i = 0; i < smesh->getMeshBufferCount(); i++)
{ {
for (unsigned j = 0; j < m_joints[i].size(); j++) for (unsigned j = 0; j < m_joints[i].size(); j++)
{ {
@ -630,15 +767,15 @@ void SPMeshLoader::createAnimationData(irr::io::IReadFile* spm)
core::vector3df cur_pos, cur_nor; core::vector3df cur_pos, cur_nor;
m_to_bind_pose_matrices[m_joints[i][j].first[k]] m_to_bind_pose_matrices[m_joints[i][j].first[k]]
.transformVect(cur_pos, .transformVect(cur_pos,
m_mesh->getMeshBuffers()[i]->getVertex(j)->Pos); smesh->getMeshBuffers()[i]->getVertex(j)->Pos);
bind_pos += cur_pos * m_joints[i][j].second[k]; bind_pos += cur_pos * m_joints[i][j].second[k];
m_to_bind_pose_matrices[m_joints[i][j].first[k]] m_to_bind_pose_matrices[m_joints[i][j].first[k]]
.rotateVect(cur_nor, .rotateVect(cur_nor,
m_mesh->getMeshBuffers()[i]->getVertex(j)->Normal); smesh->getMeshBuffers()[i]->getVertex(j)->Normal);
bind_nor += cur_nor * m_joints[i][j].second[k]; bind_nor += cur_nor * m_joints[i][j].second[k];
} }
m_mesh->getMeshBuffers()[i]->getVertex(j)->Pos = bind_pos; smesh->getMeshBuffers()[i]->getVertex(j)->Pos = bind_pos;
m_mesh->getMeshBuffers()[i]->getVertex(j)->Normal = bind_nor; smesh->getMeshBuffers()[i]->getVertex(j)->Normal = bind_nor;
} }
} }
} }
@ -647,8 +784,9 @@ void SPMeshLoader::createAnimationData(irr::io::IReadFile* spm)
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void SPMeshLoader::convertIrrlicht() void SPMeshLoader::convertIrrlicht()
{ {
scene::ISkinnedMesh* smesh = dynamic_cast<scene::ISkinnedMesh*>(m_mesh);
// Only for legacy device // Only for legacy device
if (m_joints.empty()) if (!smesh || m_joints.empty())
{ {
return; return;
} }
@ -659,9 +797,9 @@ void SPMeshLoader::convertIrrlicht()
} }
for (unsigned i = 0; i < total_joints; i++) for (unsigned i = 0; i < total_joints; i++)
{ {
m_mesh->addJoint(NULL); smesh->addJoint(NULL);
} }
core::array<scene::ISkinnedMesh::SJoint*>& joints = m_mesh->getAllJoints(); core::array<scene::ISkinnedMesh::SJoint*>& joints = smesh->getAllJoints();
std::vector<int> used_joints_map; std::vector<int> used_joints_map;
used_joints_map.resize(m_joint_count); used_joints_map.resize(m_joint_count);
total_joints = 0; total_joints = 0;
@ -723,7 +861,7 @@ void SPMeshLoader::convertIrrlicht()
{ {
break; break;
} }
scene::ISkinnedMesh::SWeight* w = m_mesh->addWeight scene::ISkinnedMesh::SWeight* w = smesh->addWeight
(joints[used_joints_map[m_joints[i][j].first[k]]]); (joints[used_joints_map[m_joints[i][j].first[k]]]);
w->buffer_id = (uint16_t)i; w->buffer_id = (uint16_t)i;
w->vertex_id = j; w->vertex_id = j;

View File

@ -53,6 +53,12 @@ private:
bool read_tangent, bool uv_one, bool uv_two, bool read_tangent, bool uv_one, bool uv_two,
SPVertexType vt, const video::SMaterial& m); SPVertexType vt, const video::SMaterial& m);
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void decompressGESPM(irr::io::IReadFile* spm, unsigned vertices_count,
unsigned indices_count, bool read_normal,
bool read_vcolor, bool read_tangent, bool uv_one,
bool uv_two, SPVertexType vt,
const video::SMaterial& m);
// ------------------------------------------------------------------------
void decompressSPM(irr::io::IReadFile* spm, unsigned vertices_count, void decompressSPM(irr::io::IReadFile* spm, unsigned vertices_count,
unsigned indices_count, bool read_normal, unsigned indices_count, bool read_normal,
bool read_vcolor, bool read_tangent, bool uv_one, bool read_vcolor, bool read_tangent, bool uv_one,
@ -63,7 +69,7 @@ private:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void convertIrrlicht(); void convertIrrlicht();
scene::ISkinnedMesh* m_mesh; scene::IAnimatedMesh* m_mesh;
scene::ISceneManager* m_scene_manager; scene::ISceneManager* m_scene_manager;