Files
2023-06-30 00:55:04 +08:00

314 lines
8.2 KiB
C++

//
// Copyright(c) 2016-2017 benikabocha.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//
#ifndef SABA_MODEL_MMD_PMXMODEL_H_
#define SABA_MODEL_MMD_PMXMODEL_H_
#include "MMDMaterial.h"
#include "MMDModel.h"
#include "MMDIkSolver.h"
#include "PMXFile.h"
#include <glm/vec2.hpp>
#include <glm/vec3.hpp>
#include <glm/gtc/quaternion.hpp>
#include <vector>
#include <string>
#include <algorithm>
#include <future>
namespace saba
{
class PMXNode : public MMDNode
{
public:
PMXNode();
void SetDeformDepth(int32_t depth) { m_deformDepth = depth; }
int32_t GetDeformdepth() const { return m_deformDepth; }
void EnableDeformAfterPhysics(bool enable) { m_isDeformAfterPhysics = enable; }
bool IsDeformAfterPhysics() { return m_isDeformAfterPhysics; }
void SetAppendNode(PMXNode* node) { m_appendNode = node; }
PMXNode* GetAppendNode() const { return m_appendNode; }
void EnableAppendRotate(bool enable) { m_isAppendRotate = enable; }
void EnableAppendTranslate(bool enable) { m_isAppendTranslate = enable; }
void EnableAppendLocal(bool enable) { m_isAppendLocal = enable; }
void SetAppendWeight(float weight) { m_appendWeight = weight; }
float GetAppendWeight() const { return m_appendWeight; }
const glm::vec3& GetAppendTranslate() const { return m_appendTranslate; }
const glm::quat& GetAppendRotate() const { return m_appendRotate; }
void SetIKSolver(MMDIkSolver* ik) { m_ikSolver = ik; }
MMDIkSolver* GetIKSolver() const { return m_ikSolver; }
void UpdateAppendTransform();
protected:
void OnBeginUpdateTransform() override;
void OnEndUpdateTransfrom() override;
void OnUpdateLocalTransform() override;
private:
int32_t m_deformDepth;
bool m_isDeformAfterPhysics;
PMXNode* m_appendNode;
bool m_isAppendRotate;
bool m_isAppendTranslate;
bool m_isAppendLocal;
float m_appendWeight;
glm::vec3 m_appendTranslate;
glm::quat m_appendRotate;
MMDIkSolver* m_ikSolver;
};
class PMXModel : public MMDModel
{
public:
PMXModel();
~PMXModel();
MMDNodeManager* GetNodeManager() override { return &m_nodeMan; }
MMDIKManager* GetIKManager() override { return &m_ikSolverMan; }
MMDMorphManager* GetMorphManager() override { return &m_morphMan; };
MMDPhysicsManager* GetPhysicsManager() override { return &m_physicsMan; }
size_t GetVertexCount() const override { return m_positions.size(); }
const glm::vec3* GetPositions() const override { return m_positions.data(); }
const glm::vec3* GetNormals() const override { return m_normals.data(); }
const glm::vec2* GetUVs() const override { return m_uvs.data(); }
const glm::vec3* GetUpdatePositions() const override { return m_updatePositions.data(); }
const glm::vec3* GetUpdateNormals() const override { return m_updateNormals.data(); }
const glm::vec2* GetUpdateUVs() const override { return m_updateUVs.data(); }
size_t GetIndexElementSize() const override { return m_indexElementSize; }
size_t GetIndexCount() const override { return m_indexCount; }
const void* GetIndices() const override { return &m_indices[0]; }
size_t GetMaterialCount() const override { return m_materials.size(); }
const MMDMaterial* GetMaterials() const override { return &m_materials[0]; }
size_t GetSubMeshCount() const override { return m_subMeshes.size(); }
const MMDSubMesh* GetSubMeshes() const override { return &m_subMeshes[0]; }
MMDPhysics* GetMMDPhysics() override { return m_physicsMan.GetMMDPhysics(); }
virtual std::vector<glm::vec3> getUpdatePositions() const override { return m_updatePositions; }
virtual std::vector<glm::vec3> getUpdateSmoothNormals() const override { return m_smoothNormals; }
void InitializeAnimation() override;
// アニメーションの前後で呼ぶ (VMDアニメーションの前後)
void BeginAnimation() override;
void EndAnimation() override;
// Morph
void UpdateMorphAnimation() override;
// ノードを更新する
void UpdateNodeAnimation(bool afterPhysicsAnim) override;
// Physicsを更新する
void ResetPhysics() override;
void UpdatePhysicsAnimation(float elapsed) override;
// 頂点データーを更新する
void Update() override;
void SetParallelUpdateHint(uint32_t parallelCount) override;
bool Load(const std::string& filepath, const std::string& mmdDataDir);
void Destroy();
const glm::vec3& GetBBoxMin() const { return m_bboxMin; }
const glm::vec3& GetBBoxMax() const { return m_bboxMax; }
public:
enum class SkinningType
{
Weight1,
Weight2,
Weight4,
SDEF,
DualQuaternion,
};
struct VertexBoneInfo
{
SkinningType m_skinningType;
union
{
struct
{
int32_t m_boneIndex[4];
float m_boneWeight[4];
};
struct
{
int32_t m_boneIndex[2];
float m_boneWeight;
glm::vec3 m_sdefC;
glm::vec3 m_sdefR0;
glm::vec3 m_sdefR1;
} m_sdef;
};
};
private:
struct PositionMorph
{
uint32_t m_index;
glm::vec3 m_position;
};
struct PositionMorphData
{
std::vector<PositionMorph> m_morphVertices;
};
struct UVMorph
{
uint32_t m_index;
glm::vec4 m_uv;
};
struct UVMorphData
{
std::vector<UVMorph> m_morphUVs;
};
struct MaterialFactor
{
MaterialFactor() = default;
MaterialFactor(const saba::PMXMorph::MaterialMorph& pmxMat);
void Mul(const MaterialFactor& val, float weight);
void Add(const MaterialFactor& val, float weight);
glm::vec3 m_diffuse;
float m_alpha;
glm::vec3 m_specular;
float m_specularPower;
glm::vec3 m_ambient;
glm::vec4 m_edgeColor;
float m_edgeSize;
glm::vec4 m_textureFactor;
glm::vec4 m_spTextureFactor;
glm::vec4 m_toonTextureFactor;
};
struct MaterialMorphData
{
std::vector<saba::PMXMorph::MaterialMorph> m_materialMorphs;
};
struct BoneMorphElement
{
MMDNode* m_node;
glm::vec3 m_position;
glm::quat m_rotate;
};
struct BoneMorphData
{
std::vector<BoneMorphElement> m_boneMorphs;
};
struct GroupMorphData
{
std::vector<saba::PMXMorph::GroupMorph> m_groupMorphs;
};
enum class MorphType
{
None,
Position,
UV,
Material,
Bone,
Group,
};
class PMXMorph : public MMDMorph
{
public:
MorphType m_morphType;
size_t m_dataIndex;
};
struct UpdateRange
{
size_t m_vertexOffset;
size_t m_vertexCount;
};
private:
void SetupParallelUpdate();
void Update(const UpdateRange& range);
void Morph(PMXMorph* morph, float weight);
void MorphPosition(const PositionMorphData& morphData, float weight);
void MorphUV(const UVMorphData& morphData, float weight);
void BeginMorphMaterial();
void EndMorphMaterial();
void MorphMaterial(const MaterialMorphData& morphData, float weight);
void MorphBone(const BoneMorphData& morphData, float weight);
private:
std::vector<glm::vec3> m_positions;
std::vector<glm::vec3> m_normals;
std::vector<glm::vec3> m_smoothNormals;
std::vector<glm::vec2> m_uvs;
std::vector<VertexBoneInfo> m_vertexBoneInfos;
std::vector<glm::vec3> m_updatePositions;
std::vector<glm::vec3> m_updateNormals;
std::vector<glm::vec2> m_updateUVs;
std::vector<glm::mat4> m_transforms;
std::vector<char> m_indices;
size_t m_indexCount;
size_t m_indexElementSize;
std::vector<PositionMorphData> m_positionMorphDatas;
std::vector<UVMorphData> m_uvMorphDatas;
std::vector<MaterialMorphData> m_materialMorphDatas;
std::vector<BoneMorphData> m_boneMorphDatas;
std::vector<GroupMorphData> m_groupMorphDatas;
// PositionMorph用
std::vector<glm::vec3> m_morphPositions;
std::vector<glm::vec4> m_morphUVs;
// マテリアルMorph用
std::vector<MMDMaterial> m_initMaterials;
std::vector<MaterialFactor> m_mulMaterialFactors;
std::vector<MaterialFactor> m_addMaterialFactors;
glm::vec3 m_bboxMin;
glm::vec3 m_bboxMax;
std::vector<MMDMaterial> m_materials;
std::vector<MMDSubMesh> m_subMeshes;
std::vector<PMXNode*> m_sortedNodes;
MMDNodeManagerT<PMXNode> m_nodeMan;
MMDIKManagerT<MMDIkSolver> m_ikSolverMan;
MMDMorphManagerT<PMXMorph> m_morphMan;
MMDPhysicsManager m_physicsMan;
uint32_t m_parallelUpdateCount;
std::vector<UpdateRange> m_updateRanges;
std::vector<std::future<void>> m_parallelUpdateFutures;
};
}
#endif // !SABA_MODEL_MMD_PMXMODEL_H_