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 <IFileSystem.h>
#ifndef SERVER_ONLY
#include <ge_main.hpp>
#include <ge_spm_buffer.hpp>
#include <ge_spm.hpp>
#include <ge_texture.hpp>
#endif
@ -67,7 +70,19 @@ scene::IAnimatedMesh* SPMeshLoader::createMesh(io::IReadFile* f)
m_joint_count = 0;
m_frame_count = 0;
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();
std::string base_path = fs->getFileDir(f->getFileName()).c_str();
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<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
{
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);
}
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
static_cast<scene::CSkinnedMesh*>(m_mesh)->AnimationFrames =
(float)m_frame_count + 1.0f;
cmesh->AnimationFrames = (float)m_frame_count + 1.0f;
}
m_all_armatures.clear();
m_to_bind_pose_matrices.clear();
@ -431,6 +454,118 @@ void SPMeshLoader::decompressSPM(irr::io::IReadFile* spm,
} // 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,
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(indices_count != 0);
scene::SSkinMeshBuffer* mb = m_mesh->addMeshBuffer();
scene::SSkinMeshBuffer* mb =
static_cast<scene::CSkinnedMesh*>(m_mesh)->addMeshBuffer();
if (uv_two)
{
mb->convertTo2TCoords();
@ -603,17 +739,18 @@ void SPMeshLoader::createAnimationData(irr::io::IReadFile* spm)
accumulated_joints += m_all_armatures[i].m_joint_used;
}
scene::ISkinnedMesh* smesh = dynamic_cast<scene::ISkinnedMesh*>(m_mesh);
// Only for legacy device
if (m_joints.empty())
if (!smesh || m_joints.empty())
{
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++)
{
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++)
{
@ -630,15 +767,15 @@ void SPMeshLoader::createAnimationData(irr::io::IReadFile* spm)
core::vector3df cur_pos, cur_nor;
m_to_bind_pose_matrices[m_joints[i][j].first[k]]
.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];
m_to_bind_pose_matrices[m_joints[i][j].first[k]]
.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];
}
m_mesh->getMeshBuffers()[i]->getVertex(j)->Pos = bind_pos;
m_mesh->getMeshBuffers()[i]->getVertex(j)->Normal = bind_nor;
smesh->getMeshBuffers()[i]->getVertex(j)->Pos = bind_pos;
smesh->getMeshBuffers()[i]->getVertex(j)->Normal = bind_nor;
}
}
}
@ -647,8 +784,9 @@ void SPMeshLoader::createAnimationData(irr::io::IReadFile* spm)
// ----------------------------------------------------------------------------
void SPMeshLoader::convertIrrlicht()
{
scene::ISkinnedMesh* smesh = dynamic_cast<scene::ISkinnedMesh*>(m_mesh);
// Only for legacy device
if (m_joints.empty())
if (!smesh || m_joints.empty())
{
return;
}
@ -659,9 +797,9 @@ void SPMeshLoader::convertIrrlicht()
}
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;
used_joints_map.resize(m_joint_count);
total_joints = 0;
@ -723,7 +861,7 @@ void SPMeshLoader::convertIrrlicht()
{
break;
}
scene::ISkinnedMesh::SWeight* w = m_mesh->addWeight
scene::ISkinnedMesh::SWeight* w = smesh->addWeight
(joints[used_joints_map[m_joints[i][j].first[k]]]);
w->buffer_id = (uint16_t)i;
w->vertex_id = j;

View File

@ -53,6 +53,12 @@ private:
bool read_tangent, bool uv_one, bool uv_two,
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,
unsigned indices_count, bool read_normal,
bool read_vcolor, bool read_tangent, bool uv_one,
@ -63,7 +69,7 @@ private:
// ------------------------------------------------------------------------
void convertIrrlicht();
scene::ISkinnedMesh* m_mesh;
scene::IAnimatedMesh* m_mesh;
scene::ISceneManager* m_scene_manager;