Remove unused mesh code
This commit is contained in:
parent
68ceceb6e3
commit
7859a00967
@ -8,8 +8,6 @@
|
|||||||
#include "aabbox3d.h"
|
#include "aabbox3d.h"
|
||||||
#include "IMesh.h"
|
#include "IMesh.h"
|
||||||
|
|
||||||
typedef void (*SkinningCallback)(const irr::core::matrix4& m, int joint, int offset);
|
|
||||||
|
|
||||||
namespace irr
|
namespace irr
|
||||||
{
|
{
|
||||||
namespace scene
|
namespace scene
|
||||||
|
@ -69,11 +69,7 @@ namespace scene
|
|||||||
virtual void animateMesh(f32 frame, f32 blend)=0;
|
virtual void animateMesh(f32 frame, f32 blend)=0;
|
||||||
|
|
||||||
//! Preforms a software skin on this mesh based of joint positions
|
//! Preforms a software skin on this mesh based of joint positions
|
||||||
virtual void skinMesh(f32 strength=1.f, SkinningCallback sc = NULL, int offset = -1) = 0;
|
virtual void skinMesh(f32 strength=1.f) = 0;
|
||||||
|
|
||||||
//! converts the vertex type of all meshbuffers to tangents.
|
|
||||||
/** E.g. used for bump mapping. */
|
|
||||||
virtual void convertMeshToTangents(bool(*predicate)(IMeshBuffer*)) = 0;
|
|
||||||
|
|
||||||
//! Allows to enable hardware skinning.
|
//! Allows to enable hardware skinning.
|
||||||
/* This feature is not implementated in Irrlicht yet */
|
/* This feature is not implementated in Irrlicht yet */
|
||||||
|
@ -176,7 +176,7 @@ void CAnimatedMeshSceneNode::OnRegisterSceneNode()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame(SkinningCallback sc, int offset)
|
IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame()
|
||||||
{
|
{
|
||||||
if(Mesh->getMeshType() != EAMT_SKINNED)
|
if(Mesh->getMeshType() != EAMT_SKINNED)
|
||||||
{
|
{
|
||||||
@ -201,7 +201,7 @@ IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame(SkinningCallback sc, int
|
|||||||
skinnedMesh->animateMesh(getFrameNr(), 1.0f);
|
skinnedMesh->animateMesh(getFrameNr(), 1.0f);
|
||||||
|
|
||||||
// Update the skinned mesh for the current joint transforms.
|
// Update the skinned mesh for the current joint transforms.
|
||||||
skinnedMesh->skinMesh(AnimationStrength, sc, offset);
|
skinnedMesh->skinMesh(AnimationStrength);
|
||||||
|
|
||||||
if (JointMode == EJUOR_READ)//read from mesh
|
if (JointMode == EJUOR_READ)//read from mesh
|
||||||
{
|
{
|
||||||
|
@ -173,7 +173,7 @@ namespace scene
|
|||||||
protected:
|
protected:
|
||||||
|
|
||||||
//! Get a static mesh for the current frame of this animated mesh
|
//! Get a static mesh for the current frame of this animated mesh
|
||||||
virtual IMesh* getMeshForCurrentFrame(SkinningCallback sc = NULL, int offset = -1);
|
virtual IMesh* getMeshForCurrentFrame();
|
||||||
|
|
||||||
void buildFrameNr(u32 timeMs);
|
void buildFrameNr(u32 timeMs);
|
||||||
virtual void checkJoints();
|
virtual void checkJoints();
|
||||||
|
@ -11,55 +11,6 @@
|
|||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "irrMap.h"
|
#include "irrMap.h"
|
||||||
|
|
||||||
inline irr::s16 float_16(irr::f32 in)
|
|
||||||
{
|
|
||||||
irr::s32 i;
|
|
||||||
memcpy(&i, &in, 4);
|
|
||||||
irr::s32 s = (i >> 16) & 0x00008000;
|
|
||||||
irr::s32 e = ((i >> 23) & 0x000000ff) - (127 - 15);
|
|
||||||
irr::s32 m = i & 0x007fffff;
|
|
||||||
if (e <= 0)
|
|
||||||
{
|
|
||||||
if (e < -10)
|
|
||||||
{
|
|
||||||
return irr::s16(s);
|
|
||||||
}
|
|
||||||
m = (m | 0x00800000) >> (1 - e);
|
|
||||||
if (m & 0x00001000)
|
|
||||||
m += 0x00002000;
|
|
||||||
return irr::s16(s | (m >> 13));
|
|
||||||
}
|
|
||||||
else if (e == 0xff - (127 - 15))
|
|
||||||
{
|
|
||||||
if (m == 0)
|
|
||||||
{
|
|
||||||
return irr::s16(s | 0x7c00);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m >>= 13;
|
|
||||||
return irr::s16(s | 0x7c00 | m | (m == 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (m & 0x00001000)
|
|
||||||
{
|
|
||||||
m += 0x00002000;
|
|
||||||
if (m & 0x00800000)
|
|
||||||
{
|
|
||||||
m = 0; // overflow in significand,
|
|
||||||
e += 1; // adjust exponent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (e > 30)
|
|
||||||
{
|
|
||||||
return irr::s16(s | 0x7c00);
|
|
||||||
}
|
|
||||||
return irr::s16(s | (e << 10) | (m >> 13));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace irr
|
namespace irr
|
||||||
{
|
{
|
||||||
namespace scene
|
namespace scene
|
||||||
@ -72,8 +23,7 @@ CSkinnedMesh::CSkinnedMesh()
|
|||||||
LastAnimatedFrame(-1), SkinnedLastFrame(false),
|
LastAnimatedFrame(-1), SkinnedLastFrame(false),
|
||||||
InterpolationMode(EIM_LINEAR),
|
InterpolationMode(EIM_LINEAR),
|
||||||
HasAnimation(false), PreparedForSkinning(false),
|
HasAnimation(false), PreparedForSkinning(false),
|
||||||
AnimateNormals(true), HardwareSkinning(false), m_total_joints(0),
|
AnimateNormals(true), HardwareSkinning(false)
|
||||||
m_current_joint(0)
|
|
||||||
{
|
{
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
setDebugName("CSkinnedMesh");
|
setDebugName("CSkinnedMesh");
|
||||||
@ -511,7 +461,7 @@ void CSkinnedMesh::getFrameData(f32 frame, SJoint *joint,
|
|||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
//! Preforms a software skin on this mesh based of joint positions
|
//! Preforms a software skin on this mesh based of joint positions
|
||||||
void CSkinnedMesh::skinMesh(f32 strength, SkinningCallback sc, int offset)
|
void CSkinnedMesh::skinMesh(f32 strength)
|
||||||
{
|
{
|
||||||
if (!HasAnimation || SkinnedLastFrame)
|
if (!HasAnimation || SkinnedLastFrame)
|
||||||
return;
|
return;
|
||||||
@ -522,109 +472,94 @@ void CSkinnedMesh::skinMesh(f32 strength, SkinningCallback sc, int offset)
|
|||||||
//-----------------
|
//-----------------
|
||||||
|
|
||||||
SkinnedLastFrame=true;
|
SkinnedLastFrame=true;
|
||||||
m_current_joint = 0;
|
|
||||||
if (HardwareSkinning)
|
|
||||||
{
|
|
||||||
for (u32 i = 0; i < RootJoints.size(); i++)
|
|
||||||
skinJoint(RootJoints[i], 0, strength, sc, offset);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//Software skin....
|
|
||||||
u32 i;
|
|
||||||
|
|
||||||
//rigid animation
|
//Software skin....
|
||||||
for (i=0; i<AllJoints.size(); ++i)
|
u32 i;
|
||||||
|
|
||||||
|
//rigid animation
|
||||||
|
for (i=0; i<AllJoints.size(); ++i)
|
||||||
|
{
|
||||||
|
for (u32 j=0; j<AllJoints[i]->AttachedMeshes.size(); ++j)
|
||||||
{
|
{
|
||||||
for (u32 j=0; j<AllJoints[i]->AttachedMeshes.size(); ++j)
|
SSkinMeshBuffer* Buffer=(*SkinningBuffers)[ AllJoints[i]->AttachedMeshes[j] ];
|
||||||
{
|
Buffer->Transformation=AllJoints[i]->GlobalAnimatedMatrix;
|
||||||
SSkinMeshBuffer* Buffer=(*SkinningBuffers)[ AllJoints[i]->AttachedMeshes[j] ];
|
|
||||||
Buffer->Transformation=AllJoints[i]->GlobalAnimatedMatrix;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//clear skinning helper array
|
|
||||||
for (i=0; i<Vertices_Moved.size(); ++i)
|
|
||||||
for (u32 j=0; j<Vertices_Moved[i].size(); ++j)
|
|
||||||
Vertices_Moved[i][j]=false;
|
|
||||||
|
|
||||||
//skin starting with the root joints
|
|
||||||
for (i=0; i<RootJoints.size(); ++i)
|
|
||||||
skinJoint(RootJoints[i], 0, strength);
|
|
||||||
|
|
||||||
for (i=0; i<SkinningBuffers->size(); ++i)
|
|
||||||
(*SkinningBuffers)[i]->setDirty(EBT_VERTEX);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//clear skinning helper array
|
||||||
|
for (i=0; i<Vertices_Moved.size(); ++i)
|
||||||
|
for (u32 j=0; j<Vertices_Moved[i].size(); ++j)
|
||||||
|
Vertices_Moved[i][j]=false;
|
||||||
|
|
||||||
|
//skin starting with the root joints
|
||||||
|
for (i=0; i<RootJoints.size(); ++i)
|
||||||
|
skinJoint(RootJoints[i], 0, strength);
|
||||||
|
|
||||||
|
for (i=0; i<SkinningBuffers->size(); ++i)
|
||||||
|
(*SkinningBuffers)[i]->setDirty(EBT_VERTEX);
|
||||||
|
|
||||||
updateBoundingBox();
|
updateBoundingBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint, f32 strength,
|
void CSkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint, f32 strength)
|
||||||
SkinningCallback sc, int offset)
|
|
||||||
{
|
{
|
||||||
if (joint->Weights.size())
|
if (joint->Weights.size())
|
||||||
{
|
{
|
||||||
//Find this joints pull on vertices...
|
//Find this joints pull on vertices...
|
||||||
core::matrix4 jointVertexPull(core::matrix4::EM4CONST_NOTHING);
|
core::matrix4 jointVertexPull(core::matrix4::EM4CONST_NOTHING);
|
||||||
jointVertexPull.setbyproduct(joint->GlobalAnimatedMatrix, joint->GlobalInversedMatrix);
|
jointVertexPull.setbyproduct(joint->GlobalAnimatedMatrix, joint->GlobalInversedMatrix);
|
||||||
if (HardwareSkinning)
|
|
||||||
{
|
|
||||||
if (sc != NULL) sc(jointVertexPull, m_current_joint, offset);
|
|
||||||
m_current_joint++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
core::vector3df thisVertexMove, thisNormalMove;
|
|
||||||
|
|
||||||
core::array<scene::SSkinMeshBuffer*> &buffersUsed=*SkinningBuffers;
|
core::vector3df thisVertexMove, thisNormalMove;
|
||||||
|
|
||||||
//Skin Vertices Positions and Normals...
|
core::array<scene::SSkinMeshBuffer*> &buffersUsed=*SkinningBuffers;
|
||||||
for (u32 i=0; i<joint->Weights.size(); ++i)
|
|
||||||
|
//Skin Vertices Positions and Normals...
|
||||||
|
for (u32 i=0; i<joint->Weights.size(); ++i)
|
||||||
|
{
|
||||||
|
SWeight& weight = joint->Weights[i];
|
||||||
|
|
||||||
|
// Pull this vertex...
|
||||||
|
jointVertexPull.transformVect(thisVertexMove, weight.StaticPos);
|
||||||
|
|
||||||
|
if (AnimateNormals)
|
||||||
|
jointVertexPull.rotateVect(thisNormalMove, weight.StaticNormal);
|
||||||
|
|
||||||
|
// Apply animation strength
|
||||||
|
if(strength != 1.f)
|
||||||
{
|
{
|
||||||
SWeight& weight = joint->Weights[i];
|
thisVertexMove = core::lerp(weight.StaticPos, thisVertexMove, strength);
|
||||||
|
if(AnimateNormals)
|
||||||
|
thisNormalMove = core::lerp(weight.StaticNormal, thisNormalMove, strength);
|
||||||
|
}
|
||||||
|
|
||||||
// Pull this vertex...
|
if (! (*(weight.Moved)) )
|
||||||
jointVertexPull.transformVect(thisVertexMove, weight.StaticPos);
|
{
|
||||||
|
*(weight.Moved) = true;
|
||||||
|
|
||||||
|
buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Pos = thisVertexMove * weight.strength;
|
||||||
|
|
||||||
if (AnimateNormals)
|
if (AnimateNormals)
|
||||||
jointVertexPull.rotateVect(thisNormalMove, weight.StaticNormal);
|
buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Normal = thisNormalMove * weight.strength;
|
||||||
|
|
||||||
// Apply animation strength
|
//*(weight._Pos) = thisVertexMove * weight.strength;
|
||||||
if(strength != 1.f)
|
|
||||||
{
|
|
||||||
thisVertexMove = core::lerp(weight.StaticPos, thisVertexMove, strength);
|
|
||||||
if(AnimateNormals)
|
|
||||||
thisNormalMove = core::lerp(weight.StaticNormal, thisNormalMove, strength);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! (*(weight.Moved)) )
|
|
||||||
{
|
|
||||||
*(weight.Moved) = true;
|
|
||||||
|
|
||||||
buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Pos = thisVertexMove * weight.strength;
|
|
||||||
|
|
||||||
if (AnimateNormals)
|
|
||||||
buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Normal = thisNormalMove * weight.strength;
|
|
||||||
|
|
||||||
//*(weight._Pos) = thisVertexMove * weight.strength;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Pos += thisVertexMove * weight.strength;
|
|
||||||
|
|
||||||
if (AnimateNormals)
|
|
||||||
buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Normal += thisNormalMove * weight.strength;
|
|
||||||
|
|
||||||
//*(weight._Pos) += thisVertexMove * weight.strength;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffersUsed[weight.buffer_id]->boundingBoxNeedsRecalculated();
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Pos += thisVertexMove * weight.strength;
|
||||||
|
|
||||||
|
if (AnimateNormals)
|
||||||
|
buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Normal += thisNormalMove * weight.strength;
|
||||||
|
|
||||||
|
//*(weight._Pos) += thisVertexMove * weight.strength;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffersUsed[weight.buffer_id]->boundingBoxNeedsRecalculated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Skin all children
|
//Skin all children
|
||||||
for (u32 j=0; j<joint->Children.size(); ++j)
|
for (u32 j=0; j<joint->Children.size(); ++j)
|
||||||
skinJoint(joint->Children[j], joint, strength, sc, offset);
|
skinJoint(joint->Children[j], joint, strength);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1462,278 +1397,6 @@ void CSkinnedMesh::addJoints(core::array<IBoneSceneNode*> &jointChildSceneNodes,
|
|||||||
SkinnedLastFrame=false;
|
SkinnedLastFrame=false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CSkinnedMesh::sortJointInfluenceFunc(const JointInfluence& a,
|
|
||||||
const JointInfluence& b)
|
|
||||||
{
|
|
||||||
return a.weight > b.weight;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSkinnedMesh::convertForSkinning()
|
|
||||||
{
|
|
||||||
/* if (HardwareSkinning) return;
|
|
||||||
|
|
||||||
setHardwareSkinning(true);
|
|
||||||
WeightInfluence wi;
|
|
||||||
for (u32 b = 0; b < LocalBuffers.size(); b++)
|
|
||||||
{
|
|
||||||
if (LocalBuffers[b])
|
|
||||||
LocalBuffers[b]->convertForSkinning();
|
|
||||||
|
|
||||||
wi.push_back(core::array<core::array<JointInfluence> > ());
|
|
||||||
for (u32 i = 0; i < LocalBuffers[b]->getVertexCount(); i++)
|
|
||||||
wi[b].push_back(core::array<JointInfluence>());
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t idx = 0;
|
|
||||||
for (u32 i = 0; i < RootJoints.size(); i++)
|
|
||||||
computeWeightInfluence(RootJoints[i], idx, wi);
|
|
||||||
|
|
||||||
for (u32 b = 0; b < LocalBuffers.size(); b++)
|
|
||||||
{
|
|
||||||
if (LocalBuffers[b])
|
|
||||||
{
|
|
||||||
const u32 total = wi[b].size();
|
|
||||||
_IRR_DEBUG_BREAK_IF(LocalBuffers[b]->getVertexCount() != total);
|
|
||||||
for (u32 i = 0; i < total; i++)
|
|
||||||
{
|
|
||||||
core::array<JointInfluence> this_influence;
|
|
||||||
core::array<JointInfluence> reported_weight = wi[b][i];
|
|
||||||
reported_weight.sort(sortJointInfluenceFunc);
|
|
||||||
for (u32 j = 0; j < 4; j++)
|
|
||||||
{
|
|
||||||
JointInfluence influence;
|
|
||||||
influence.joint_idx = -32768;
|
|
||||||
influence.weight = j == 0 ? 1.0f : 0.0f;
|
|
||||||
this_influence.push_back(influence);
|
|
||||||
}
|
|
||||||
float total_weight = 0.0f;
|
|
||||||
const unsigned max_weight =
|
|
||||||
reported_weight.size() > 4 ? 4 : reported_weight.size();
|
|
||||||
for (u32 j = 0; j < max_weight; j++)
|
|
||||||
{
|
|
||||||
total_weight += reported_weight[j].weight;
|
|
||||||
this_influence[j].joint_idx = reported_weight[j].joint_idx;
|
|
||||||
this_influence[j].weight = reported_weight[j].weight;
|
|
||||||
}
|
|
||||||
if (total_weight != 0.0f)
|
|
||||||
{
|
|
||||||
for (u32 j = 0; j < max_weight; j++)
|
|
||||||
{
|
|
||||||
this_influence[j].weight =
|
|
||||||
this_influence[j].weight / total_weight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int j = 0; j < 4; j++)
|
|
||||||
{
|
|
||||||
LocalBuffers[b]->Vertices_SkinnedMesh[i].m_joint_idx[j] = (s16)this_influence[j].joint_idx;
|
|
||||||
LocalBuffers[b]->Vertices_SkinnedMesh[i].m_weight[j] = float_16
|
|
||||||
(this_influence[j].weight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SkinnedLastFrame = false;
|
|
||||||
skinMesh();
|
|
||||||
m_total_joints = m_current_joint;*/
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSkinnedMesh::computeWeightInfluence(SJoint *joint, size_t &index, WeightInfluence& wi)
|
|
||||||
{
|
|
||||||
if (!joint->Weights.empty())
|
|
||||||
{
|
|
||||||
for (u32 i = 0; i < joint->Weights.size(); i++)
|
|
||||||
{
|
|
||||||
SWeight& weight = joint->Weights[i];
|
|
||||||
JointInfluence tmp;
|
|
||||||
tmp.joint_idx = (int)index;
|
|
||||||
tmp.weight = weight.strength;
|
|
||||||
wi[weight.buffer_id][weight.vertex_id].push_back(tmp);
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u32 j = 0; j < joint->Children.size(); j++)
|
|
||||||
computeWeightInfluence(joint->Children[j], index, wi);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSkinnedMesh::convertMeshToTangents(bool(*predicate)(IMeshBuffer*))
|
|
||||||
{
|
|
||||||
/* bool recalculate_animation = false;
|
|
||||||
toStaticPose();
|
|
||||||
for (u32 b = 0; b < LocalBuffers.size(); b++)
|
|
||||||
{
|
|
||||||
bool recalculate_joints = false;
|
|
||||||
core::map<u32, u32> vert_loc_map;
|
|
||||||
SSkinMeshBuffer* ssmb = LocalBuffers[b];
|
|
||||||
if (ssmb)
|
|
||||||
{
|
|
||||||
if (!predicate(ssmb)) continue;
|
|
||||||
ssmb->Vertices_Tangents.set_used(ssmb->Vertices_Standard.size());
|
|
||||||
for (unsigned i = 0; i < ssmb->Vertices_Tangents.size(); i++)
|
|
||||||
{
|
|
||||||
ssmb->Vertices_Tangents[i] = video::S3DVertexTangents(ssmb->Vertices_Standard[i].Pos,
|
|
||||||
ssmb->Vertices_Standard[i].Normal,ssmb->Vertices_Standard[i].Color,
|
|
||||||
ssmb->Vertices_Standard[i].TCoords);
|
|
||||||
if (!ssmb->m_tangents_map.empty())
|
|
||||||
{
|
|
||||||
ssmb->Vertices_Tangents[i].Tangent = ssmb->m_tangents_map.find(i)->getValue().first;
|
|
||||||
ssmb->Vertices_Tangents[i].Binormal = ssmb->m_tangents_map.find(i)->getValue().second.first;
|
|
||||||
ssmb->Vertices_Tangents[i].m_bitangent_sign = ssmb->m_tangents_map.find(i)->getValue().second.second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
recalculate_joints = true;
|
|
||||||
recalculate_animation = true;
|
|
||||||
core::map<video::S3DVertexTangents, u32> vert_map;
|
|
||||||
core::array<u16> tmp_indices;
|
|
||||||
for (u32 i = 0; i < ssmb->Indices.size(); i++)
|
|
||||||
{
|
|
||||||
u32 vert_location = 0;
|
|
||||||
const u32 cur_ver_loc = ssmb->Indices[i];
|
|
||||||
const video::S3DVertex& v_old = ssmb->Vertices_Standard[cur_ver_loc];
|
|
||||||
video::S3DVertexTangents v(v_old.Pos, v_old.Normal, v_old.Color, v_old.TCoords);
|
|
||||||
core::map<video::S3DVertexTangents, u32>::Node *n = vert_map.find(v);
|
|
||||||
if (n)
|
|
||||||
{
|
|
||||||
vert_location = n->getValue();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
vert_location = ssmb->Vertices_Tangents.size();
|
|
||||||
ssmb->Vertices_Tangents.push_back(v);
|
|
||||||
vert_map.insert(v, vert_location);
|
|
||||||
}
|
|
||||||
vert_loc_map[cur_ver_loc] = vert_location;
|
|
||||||
tmp_indices.push_back(vert_location);
|
|
||||||
}
|
|
||||||
const s32 index_count = tmp_indices.size();
|
|
||||||
u16* idx = tmp_indices.pointer();
|
|
||||||
video::S3DVertexTangents* v = ssmb->Vertices_Tangents.pointer();
|
|
||||||
core::vector3df local_normal;
|
|
||||||
if (!ssmb->m_tangents_map.empty())
|
|
||||||
{
|
|
||||||
for (unsigned i = 0; i < ssmb->Vertices_Tangents.size(); i++)
|
|
||||||
{
|
|
||||||
auto a = ssmb->m_tangents_map.find(v[i].Pos);
|
|
||||||
if (a)
|
|
||||||
{
|
|
||||||
v[i].Tangent = a->getValue().first;
|
|
||||||
v[i].Binormal = a->getValue().second.first;
|
|
||||||
v[i].m_bitangent_sign = a->getValue().second.second;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("ddd\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (s32 i = 0; i < index_count; i += 3)
|
|
||||||
{
|
|
||||||
calculateTangents(
|
|
||||||
local_normal,
|
|
||||||
v[idx[i+0]].Tangent,
|
|
||||||
v[idx[i+0]].Binormal,
|
|
||||||
v[idx[i+0]].Pos,
|
|
||||||
v[idx[i+1]].Pos,
|
|
||||||
v[idx[i+2]].Pos,
|
|
||||||
v[idx[i+0]].TCoords,
|
|
||||||
v[idx[i+1]].TCoords,
|
|
||||||
v[idx[i+2]].TCoords);
|
|
||||||
|
|
||||||
calculateTangents(
|
|
||||||
local_normal,
|
|
||||||
v[idx[i+1]].Tangent,
|
|
||||||
v[idx[i+1]].Binormal,
|
|
||||||
v[idx[i+1]].Pos,
|
|
||||||
v[idx[i+2]].Pos,
|
|
||||||
v[idx[i+0]].Pos,
|
|
||||||
v[idx[i+1]].TCoords,
|
|
||||||
v[idx[i+2]].TCoords,
|
|
||||||
v[idx[i+0]].TCoords);
|
|
||||||
|
|
||||||
calculateTangents(
|
|
||||||
local_normal,
|
|
||||||
v[idx[i+2]].Tangent,
|
|
||||||
v[idx[i+2]].Binormal,
|
|
||||||
v[idx[i+2]].Pos,
|
|
||||||
v[idx[i+0]].Pos,
|
|
||||||
v[idx[i+1]].Pos,
|
|
||||||
v[idx[i+2]].TCoords,
|
|
||||||
v[idx[i+0]].TCoords,
|
|
||||||
v[idx[i+1]].TCoords);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssmb->Vertices_Standard.clear();
|
|
||||||
ssmb->VertexType = video::EVT_TANGENTS;
|
|
||||||
}
|
|
||||||
if (recalculate_joints)
|
|
||||||
{
|
|
||||||
Vertices_Moved[b].set_used(ssmb->getVertexCount());
|
|
||||||
for (u32 i = 0; i < AllJoints.size(); i++)
|
|
||||||
{
|
|
||||||
SJoint *joint = AllJoints[i];
|
|
||||||
for (u32 j = 0; j <joint->Weights.size(); j++)
|
|
||||||
{
|
|
||||||
if (joint->Weights[j].buffer_id == b)
|
|
||||||
{
|
|
||||||
core::map<u32, u32>::Node *n =
|
|
||||||
vert_loc_map.find(joint->Weights[j].vertex_id);
|
|
||||||
if (n)
|
|
||||||
{
|
|
||||||
joint->Weights[j].vertex_id = n->getValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (recalculate_animation)
|
|
||||||
{
|
|
||||||
PreparedForSkinning = false;
|
|
||||||
checkForAnimation();
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSkinnedMesh::calculateTangents(
|
|
||||||
core::vector3df& normal,
|
|
||||||
core::vector3df& tangent,
|
|
||||||
core::vector3df& binormal,
|
|
||||||
core::vector3df& vt1, core::vector3df& vt2, core::vector3df& vt3, // vertices
|
|
||||||
core::vector2df& tc1, core::vector2df& tc2, core::vector2df& tc3) // texture coords
|
|
||||||
{
|
|
||||||
core::vector3df v1 = vt1 - vt2;
|
|
||||||
core::vector3df v2 = vt3 - vt1;
|
|
||||||
normal = v2.crossProduct(v1);
|
|
||||||
normal.normalize();
|
|
||||||
|
|
||||||
// binormal
|
|
||||||
|
|
||||||
f32 deltaX1 = tc1.X - tc2.X;
|
|
||||||
f32 deltaX2 = tc3.X - tc1.X;
|
|
||||||
binormal = (v1 * deltaX2) - (v2 * deltaX1);
|
|
||||||
binormal.normalize();
|
|
||||||
|
|
||||||
// tangent
|
|
||||||
|
|
||||||
f32 deltaY1 = tc1.Y - tc2.Y;
|
|
||||||
f32 deltaY2 = tc3.Y - tc1.Y;
|
|
||||||
tangent = (v1 * deltaY2) - (v2 * deltaY1);
|
|
||||||
tangent.normalize();
|
|
||||||
|
|
||||||
// adjust
|
|
||||||
|
|
||||||
core::vector3df txb = tangent.crossProduct(binormal);
|
|
||||||
if (txb.dotProduct(normal) < 0.0f)
|
|
||||||
{
|
|
||||||
tangent *= -1.0f;
|
|
||||||
binormal *= -1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end namespace scene
|
} // end namespace scene
|
||||||
} // end namespace irr
|
} // end namespace irr
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ namespace scene
|
|||||||
virtual void animateMesh(f32 frame, f32 blend);
|
virtual void animateMesh(f32 frame, f32 blend);
|
||||||
|
|
||||||
//! Preforms a software skin on this mesh based of joint positions
|
//! Preforms a software skin on this mesh based of joint positions
|
||||||
virtual void skinMesh(f32 strength=1.f, SkinningCallback sc = NULL, int offset = -1);
|
virtual void skinMesh(f32 strength=1.f);
|
||||||
|
|
||||||
//! returns amount of mesh buffers.
|
//! returns amount of mesh buffers.
|
||||||
virtual u32 getMeshBufferCount() const;
|
virtual u32 getMeshBufferCount() const;
|
||||||
@ -113,9 +113,6 @@ namespace scene
|
|||||||
//! Sets Interpolation Mode
|
//! Sets Interpolation Mode
|
||||||
virtual void setInterpolationMode(E_INTERPOLATION_MODE mode);
|
virtual void setInterpolationMode(E_INTERPOLATION_MODE mode);
|
||||||
|
|
||||||
//! Convertes the mesh to contain tangent information
|
|
||||||
virtual void convertMeshToTangents(bool(*predicate)(IMeshBuffer*));
|
|
||||||
|
|
||||||
//! Does the mesh have no animation
|
//! Does the mesh have no animation
|
||||||
virtual bool isStatic();
|
virtual bool isStatic();
|
||||||
|
|
||||||
@ -175,8 +172,6 @@ namespace scene
|
|||||||
|
|
||||||
void buildAllGlobalAnimatedMatrices(SJoint *Joint=0, SJoint *ParentJoint=0);
|
void buildAllGlobalAnimatedMatrices(SJoint *Joint=0, SJoint *ParentJoint=0);
|
||||||
|
|
||||||
u32 getTotalJoints() const { return m_total_joints; }
|
|
||||||
|
|
||||||
f32 AnimationFrames;
|
f32 AnimationFrames;
|
||||||
|
|
||||||
core::array<SJoint*> RootJoints;
|
core::array<SJoint*> RootJoints;
|
||||||
@ -197,8 +192,7 @@ private:
|
|||||||
|
|
||||||
void calculateGlobalMatrices(SJoint *Joint,SJoint *ParentJoint);
|
void calculateGlobalMatrices(SJoint *Joint,SJoint *ParentJoint);
|
||||||
|
|
||||||
void skinJoint(SJoint *Joint, SJoint *ParentJoint, f32 strength=1.f,
|
void skinJoint(SJoint *Joint, SJoint *ParentJoint, f32 strength=1.f);
|
||||||
SkinningCallback sc = NULL, int offset = -1);
|
|
||||||
|
|
||||||
void calculateTangents(core::vector3df& normal,
|
void calculateTangents(core::vector3df& normal,
|
||||||
core::vector3df& tangent, core::vector3df& binormal,
|
core::vector3df& tangent, core::vector3df& binormal,
|
||||||
@ -229,8 +223,6 @@ private:
|
|||||||
bool PreparedForSkinning;
|
bool PreparedForSkinning;
|
||||||
bool AnimateNormals;
|
bool AnimateNormals;
|
||||||
bool HardwareSkinning;
|
bool HardwareSkinning;
|
||||||
u32 m_total_joints;
|
|
||||||
u32 m_current_joint;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace scene
|
} // end namespace scene
|
||||||
|
@ -16,21 +16,17 @@
|
|||||||
// along with this program; if not, write to the Free Software
|
// along with this program; if not, write to the Free Software
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
#include "graphics/mesh_tools.hpp"
|
|
||||||
|
|
||||||
#include "graphics/central_settings.hpp"
|
|
||||||
#include "graphics/irr_driver.hpp"
|
|
||||||
#include "graphics/shaders.hpp"
|
|
||||||
#include "modes/world.hpp"
|
|
||||||
#include "tracks/track.hpp"
|
|
||||||
#include "utils/log.hpp"
|
#include "utils/log.hpp"
|
||||||
|
#include "utils/vec3.hpp"
|
||||||
|
|
||||||
#include <irrlicht.h>
|
#include <irrlicht.h>
|
||||||
#include <IMesh.h>
|
#include <IMesh.h>
|
||||||
#include <IMeshBuffer.h>
|
#include <IMeshBuffer.h>
|
||||||
#include <SSkinMeshBuffer.h>
|
#include <SSkinMeshBuffer.h>
|
||||||
|
|
||||||
void MeshTools::minMax3D(scene::IMesh* mesh, Vec3 *min, Vec3 *max)
|
namespace MeshTools
|
||||||
|
{
|
||||||
|
void minMax3D(scene::IMesh* mesh, Vec3 *min, Vec3 *max)
|
||||||
{
|
{
|
||||||
Vec3 extend;
|
Vec3 extend;
|
||||||
*min = Vec3( 999999.9f);
|
*min = Vec3( 999999.9f);
|
||||||
@ -103,407 +99,4 @@ void MeshTools::minMax3D(scene::IMesh* mesh, Vec3 *min, Vec3 *max)
|
|||||||
} // for i<getMeshBufferCount
|
} // for i<getMeshBufferCount
|
||||||
} // minMax3D
|
} // minMax3D
|
||||||
|
|
||||||
// Copied from irrlicht
|
} // namespace MeshTools
|
||||||
void calculateTangents(
|
|
||||||
core::vector3df& normal,
|
|
||||||
core::vector3df& tangent,
|
|
||||||
core::vector3df& binormal,
|
|
||||||
const core::vector3df& vt1, const core::vector3df& vt2, const core::vector3df& vt3, // vertices
|
|
||||||
const core::vector2df& tc1, const core::vector2df& tc2, const core::vector2df& tc3) // texture coords
|
|
||||||
{
|
|
||||||
core::vector3df v1 = vt1 - vt2;
|
|
||||||
core::vector3df v2 = vt3 - vt1;
|
|
||||||
normal = v2.crossProduct(v1);
|
|
||||||
normal.normalize();
|
|
||||||
|
|
||||||
// binormal
|
|
||||||
|
|
||||||
f32 deltaX1 = tc1.X - tc2.X;
|
|
||||||
f32 deltaX2 = tc3.X - tc1.X;
|
|
||||||
binormal = (v1 * deltaX2) - (v2 * deltaX1);
|
|
||||||
binormal.normalize();
|
|
||||||
|
|
||||||
// tangent
|
|
||||||
|
|
||||||
f32 deltaY1 = tc1.Y - tc2.Y;
|
|
||||||
f32 deltaY2 = tc3.Y - tc1.Y;
|
|
||||||
tangent = (v1 * deltaY2) - (v2 * deltaY1);
|
|
||||||
tangent.normalize();
|
|
||||||
|
|
||||||
// adjust
|
|
||||||
|
|
||||||
core::vector3df txb = tangent.crossProduct(binormal);
|
|
||||||
if (txb.dotProduct(normal) < 0.0f)
|
|
||||||
{
|
|
||||||
tangent *= -1.0f;
|
|
||||||
binormal *= -1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copied from irrlicht
|
|
||||||
static inline core::vector3df getAngleWeight(const core::vector3df& v1,
|
|
||||||
const core::vector3df& v2,
|
|
||||||
const core::vector3df& v3)
|
|
||||||
{
|
|
||||||
// Calculate this triangle's weight for each of its three vertices
|
|
||||||
// start by calculating the lengths of its sides
|
|
||||||
const f32 a = v2.getDistanceFromSQ(v3);
|
|
||||||
const f32 asqrt = sqrtf(a);
|
|
||||||
const f32 b = v1.getDistanceFromSQ(v3);
|
|
||||||
const f32 bsqrt = sqrtf(b);
|
|
||||||
const f32 c = v1.getDistanceFromSQ(v2);
|
|
||||||
const f32 csqrt = sqrtf(c);
|
|
||||||
|
|
||||||
// use them to find the angle at each vertex
|
|
||||||
return core::vector3df(
|
|
||||||
acosf((b + c - a) / (2.f * bsqrt * csqrt)),
|
|
||||||
acosf((-b + c + a) / (2.f * asqrt * csqrt)),
|
|
||||||
acosf((b - c + a) / (2.f * bsqrt * asqrt)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copied from irrlicht
|
|
||||||
template <typename T>
|
|
||||||
void recalculateTangentsT(scene::IMeshBuffer* buffer, bool recalculate_normals, bool smooth, bool angle_weighted)
|
|
||||||
{
|
|
||||||
if (!buffer || (buffer->getVertexType() != video::EVT_TANGENTS))
|
|
||||||
return;
|
|
||||||
|
|
||||||
const u32 vtxCnt = buffer->getVertexCount();
|
|
||||||
const u32 idxCnt = buffer->getIndexCount();
|
|
||||||
|
|
||||||
T* idx = reinterpret_cast<T*>(buffer->getIndices());
|
|
||||||
video::S3DVertexTangents* v =
|
|
||||||
(video::S3DVertexTangents*)buffer->getVertices();
|
|
||||||
|
|
||||||
if (smooth)
|
|
||||||
{
|
|
||||||
u32 i;
|
|
||||||
|
|
||||||
for (i = 0; i != vtxCnt; ++i)
|
|
||||||
{
|
|
||||||
if (recalculate_normals)
|
|
||||||
v[i].Normal.set(0.f, 0.f, 0.f);
|
|
||||||
v[i].Tangent.set(0.f, 0.f, 0.f);
|
|
||||||
v[i].Binormal.set(0.f, 0.f, 0.f);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Each vertex gets the sum of the tangents and binormals from the faces around it
|
|
||||||
for (i = 0; i<idxCnt; i += 3)
|
|
||||||
{
|
|
||||||
// if this triangle is degenerate, skip it!
|
|
||||||
if (v[idx[i + 0]].Pos == v[idx[i + 1]].Pos ||
|
|
||||||
v[idx[i + 0]].Pos == v[idx[i + 2]].Pos ||
|
|
||||||
v[idx[i + 1]].Pos == v[idx[i + 2]].Pos
|
|
||||||
/*||
|
|
||||||
v[idx[i+0]].TCoords == v[idx[i+1]].TCoords ||
|
|
||||||
v[idx[i+0]].TCoords == v[idx[i+2]].TCoords ||
|
|
||||||
v[idx[i+1]].TCoords == v[idx[i+2]].TCoords */
|
|
||||||
)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
//Angle-weighted normals look better, but are slightly more CPU intensive to calculate
|
|
||||||
core::vector3df weight(1.f, 1.f, 1.f);
|
|
||||||
if (angle_weighted)
|
|
||||||
weight = getAngleWeight(v[i + 0].Pos, v[i + 1].Pos, v[i + 2].Pos);
|
|
||||||
core::vector3df localNormal;
|
|
||||||
core::vector3df localTangent;
|
|
||||||
core::vector3df localBinormal;
|
|
||||||
|
|
||||||
calculateTangents(
|
|
||||||
localNormal,
|
|
||||||
localTangent,
|
|
||||||
localBinormal,
|
|
||||||
v[idx[i + 0]].Pos,
|
|
||||||
v[idx[i + 1]].Pos,
|
|
||||||
v[idx[i + 2]].Pos,
|
|
||||||
v[idx[i + 0]].TCoords,
|
|
||||||
v[idx[i + 1]].TCoords,
|
|
||||||
v[idx[i + 2]].TCoords);
|
|
||||||
|
|
||||||
if (recalculate_normals)
|
|
||||||
v[idx[i + 0]].Normal += localNormal * weight.X;
|
|
||||||
v[idx[i + 0]].Tangent += localTangent * weight.X;
|
|
||||||
v[idx[i + 0]].Binormal += localBinormal * weight.X;
|
|
||||||
|
|
||||||
calculateTangents(
|
|
||||||
localNormal,
|
|
||||||
localTangent,
|
|
||||||
localBinormal,
|
|
||||||
v[idx[i + 1]].Pos,
|
|
||||||
v[idx[i + 2]].Pos,
|
|
||||||
v[idx[i + 0]].Pos,
|
|
||||||
v[idx[i + 1]].TCoords,
|
|
||||||
v[idx[i + 2]].TCoords,
|
|
||||||
v[idx[i + 0]].TCoords);
|
|
||||||
|
|
||||||
if (recalculate_normals)
|
|
||||||
v[idx[i + 1]].Normal += localNormal * weight.Y;
|
|
||||||
v[idx[i + 1]].Tangent += localTangent * weight.Y;
|
|
||||||
v[idx[i + 1]].Binormal += localBinormal * weight.Y;
|
|
||||||
|
|
||||||
calculateTangents(
|
|
||||||
localNormal,
|
|
||||||
localTangent,
|
|
||||||
localBinormal,
|
|
||||||
v[idx[i + 2]].Pos,
|
|
||||||
v[idx[i + 0]].Pos,
|
|
||||||
v[idx[i + 1]].Pos,
|
|
||||||
v[idx[i + 2]].TCoords,
|
|
||||||
v[idx[i + 0]].TCoords,
|
|
||||||
v[idx[i + 1]].TCoords);
|
|
||||||
|
|
||||||
if (recalculate_normals)
|
|
||||||
v[idx[i + 2]].Normal += localNormal * weight.Z;
|
|
||||||
v[idx[i + 2]].Tangent += localTangent * weight.Z;
|
|
||||||
v[idx[i + 2]].Binormal += localBinormal * weight.Z;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Normalize the tangents and binormals
|
|
||||||
if (recalculate_normals)
|
|
||||||
{
|
|
||||||
for (i = 0; i != vtxCnt; ++i)
|
|
||||||
v[i].Normal.normalize();
|
|
||||||
}
|
|
||||||
for (i = 0; i != vtxCnt; ++i)
|
|
||||||
{
|
|
||||||
v[i].Tangent.normalize();
|
|
||||||
v[i].Binormal.normalize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
core::vector3df localNormal;
|
|
||||||
for (u32 i = 0; i<idxCnt; i += 3)
|
|
||||||
{
|
|
||||||
calculateTangents(
|
|
||||||
localNormal,
|
|
||||||
v[idx[i + 0]].Tangent,
|
|
||||||
v[idx[i + 0]].Binormal,
|
|
||||||
v[idx[i + 0]].Pos,
|
|
||||||
v[idx[i + 1]].Pos,
|
|
||||||
v[idx[i + 2]].Pos,
|
|
||||||
v[idx[i + 0]].TCoords,
|
|
||||||
v[idx[i + 1]].TCoords,
|
|
||||||
v[idx[i + 2]].TCoords);
|
|
||||||
if (recalculate_normals)
|
|
||||||
v[idx[i + 0]].Normal = localNormal;
|
|
||||||
|
|
||||||
calculateTangents(
|
|
||||||
localNormal,
|
|
||||||
v[idx[i + 1]].Tangent,
|
|
||||||
v[idx[i + 1]].Binormal,
|
|
||||||
v[idx[i + 1]].Pos,
|
|
||||||
v[idx[i + 2]].Pos,
|
|
||||||
v[idx[i + 0]].Pos,
|
|
||||||
v[idx[i + 1]].TCoords,
|
|
||||||
v[idx[i + 2]].TCoords,
|
|
||||||
v[idx[i + 0]].TCoords);
|
|
||||||
if (recalculate_normals)
|
|
||||||
v[idx[i + 1]].Normal = localNormal;
|
|
||||||
|
|
||||||
calculateTangents(
|
|
||||||
localNormal,
|
|
||||||
v[idx[i + 2]].Tangent,
|
|
||||||
v[idx[i + 2]].Binormal,
|
|
||||||
v[idx[i + 2]].Pos,
|
|
||||||
v[idx[i + 0]].Pos,
|
|
||||||
v[idx[i + 1]].Pos,
|
|
||||||
v[idx[i + 2]].TCoords,
|
|
||||||
v[idx[i + 0]].TCoords,
|
|
||||||
v[idx[i + 1]].TCoords);
|
|
||||||
if (recalculate_normals)
|
|
||||||
v[idx[i + 2]].Normal = localNormal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copied from irrlicht
|
|
||||||
void recalculateTangents(scene::IMeshBuffer* buffer, bool recalculate_normals, bool smooth, bool angle_weighted)
|
|
||||||
{
|
|
||||||
if (buffer && (buffer->getVertexType() == video::EVT_TANGENTS))
|
|
||||||
{
|
|
||||||
if (buffer->getIndexType() == video::EIT_16BIT)
|
|
||||||
recalculateTangentsT<u16>(buffer, recalculate_normals, smooth, angle_weighted);
|
|
||||||
else
|
|
||||||
recalculateTangentsT<u32>(buffer, recalculate_normals, smooth, angle_weighted);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copied from irrlicht
|
|
||||||
void recalculateTangents(scene::IMesh* mesh, bool recalculate_normals, bool smooth, bool angle_weighted)
|
|
||||||
{
|
|
||||||
if (!mesh)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const u32 mesh_buffer_count = mesh->getMeshBufferCount();
|
|
||||||
for (u32 b = 0; b<mesh_buffer_count; ++b)
|
|
||||||
{
|
|
||||||
recalculateTangents(mesh->getMeshBuffer(b), recalculate_normals, smooth, angle_weighted);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef SERVER_ONLY
|
|
||||||
bool MeshTools::isNormalMap(scene::IMeshBuffer* mb)
|
|
||||||
{
|
|
||||||
if (!CVS->isGLSL())
|
|
||||||
return false;
|
|
||||||
return (mb->getMaterial().MaterialType == Shaders::getShader(ES_NORMAL_MAP) &&
|
|
||||||
mb->getVertexType() != video::EVT_TANGENTS);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Copied from irrlicht
|
|
||||||
scene::IMesh* MeshTools::createMeshWithTangents(scene::IMesh* mesh,
|
|
||||||
bool(*predicate)(scene::IMeshBuffer*),
|
|
||||||
bool recalculate_normals, bool smooth,
|
|
||||||
bool angle_weighted,
|
|
||||||
bool calculate_tangents)
|
|
||||||
{
|
|
||||||
return mesh;
|
|
||||||
if (!mesh)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
scene::ISkinnedMesh* sm = dynamic_cast<scene::ISkinnedMesh*>(mesh);
|
|
||||||
if (sm)
|
|
||||||
{
|
|
||||||
createSkinnedMeshWithTangents(sm, predicate);
|
|
||||||
return sm;
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy mesh and fill data into SMeshBufferTangents
|
|
||||||
|
|
||||||
const u32 mesh_buffer_count = mesh->getMeshBufferCount();
|
|
||||||
|
|
||||||
bool needs_normal_map = false;
|
|
||||||
for (u32 b = 0; b < mesh_buffer_count; ++b)
|
|
||||||
{
|
|
||||||
scene::IMeshBuffer* original = mesh->getMeshBuffer(b);
|
|
||||||
if (predicate(original))
|
|
||||||
{
|
|
||||||
needs_normal_map = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!needs_normal_map)
|
|
||||||
{
|
|
||||||
return mesh;
|
|
||||||
}
|
|
||||||
scene::SMesh* clone = new scene::SMesh();
|
|
||||||
|
|
||||||
for (u32 b = 0; b<mesh_buffer_count; ++b)
|
|
||||||
{
|
|
||||||
scene::IMeshBuffer* original = mesh->getMeshBuffer(b);
|
|
||||||
const u32 idxCnt = original->getIndexCount();
|
|
||||||
const u16* idx = original->getIndices();
|
|
||||||
|
|
||||||
if (!predicate(original))
|
|
||||||
{
|
|
||||||
clone->addMeshBuffer(original);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
scene::SMeshBufferTangents* buffer = new scene::SMeshBufferTangents();
|
|
||||||
|
|
||||||
buffer->Material = original->getMaterial();
|
|
||||||
buffer->Vertices.reallocate(idxCnt);
|
|
||||||
buffer->Indices.reallocate(idxCnt);
|
|
||||||
|
|
||||||
core::map<video::S3DVertexTangents, int> vertMap;
|
|
||||||
int vertLocation;
|
|
||||||
|
|
||||||
// copy vertices
|
|
||||||
|
|
||||||
const video::E_VERTEX_TYPE vType = original->getVertexType();
|
|
||||||
video::S3DVertexTangents vNew;
|
|
||||||
for (u32 i = 0; i<idxCnt; ++i)
|
|
||||||
{
|
|
||||||
switch (vType)
|
|
||||||
{
|
|
||||||
case video::EVT_STANDARD:
|
|
||||||
{
|
|
||||||
const video::S3DVertex* v =
|
|
||||||
(const video::S3DVertex*)original->getVertices();
|
|
||||||
vNew = video::S3DVertexTangents(
|
|
||||||
v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case video::EVT_2TCOORDS:
|
|
||||||
{
|
|
||||||
const video::S3DVertex2TCoords* v =
|
|
||||||
(const video::S3DVertex2TCoords*)original->getVertices();
|
|
||||||
vNew = video::S3DVertexTangents(
|
|
||||||
v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case video::EVT_TANGENTS:
|
|
||||||
{
|
|
||||||
const video::S3DVertexTangents* v =
|
|
||||||
(const video::S3DVertexTangents*)original->getVertices();
|
|
||||||
vNew = v[idx[i]];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
core::map<video::S3DVertexTangents, int>::Node* n = vertMap.find(vNew);
|
|
||||||
if (n)
|
|
||||||
{
|
|
||||||
vertLocation = n->getValue();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
vertLocation = buffer->Vertices.size();
|
|
||||||
buffer->Vertices.push_back(vNew);
|
|
||||||
vertMap.insert(vNew, vertLocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
// create new indices
|
|
||||||
buffer->Indices.push_back(vertLocation);
|
|
||||||
}
|
|
||||||
buffer->recalculateBoundingBox();
|
|
||||||
|
|
||||||
// add new buffer
|
|
||||||
clone->addMeshBuffer(buffer);
|
|
||||||
buffer->drop();
|
|
||||||
}
|
|
||||||
|
|
||||||
clone->recalculateBoundingBox();
|
|
||||||
if (calculate_tangents)
|
|
||||||
recalculateTangents(clone, recalculate_normals, smooth, angle_weighted);
|
|
||||||
|
|
||||||
scene::IMeshCache* meshCache = irr_driver->getSceneManager()->getMeshCache();
|
|
||||||
io::SNamedPath path = meshCache->getMeshName(mesh);
|
|
||||||
if (path.getPath() == "")
|
|
||||||
{
|
|
||||||
// This mesh is not in irrlicht cache, drop it directly
|
|
||||||
assert(mesh->getReferenceCount() == 1);
|
|
||||||
mesh->drop();
|
|
||||||
return clone;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Cache the calcuated tangent mesh with path
|
|
||||||
irr_driver->removeMeshFromCache(mesh);
|
|
||||||
scene::SAnimatedMesh* amesh = new scene::SAnimatedMesh(clone);
|
|
||||||
clone->drop();
|
|
||||||
meshCache->addMesh(path, amesh);
|
|
||||||
Track* track = Track::getCurrentTrack();
|
|
||||||
if (track)
|
|
||||||
{
|
|
||||||
irr_driver->grabAllTextures(amesh);
|
|
||||||
track->addCachedMesh(amesh);
|
|
||||||
return amesh;
|
|
||||||
}
|
|
||||||
amesh->drop();
|
|
||||||
return amesh;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void MeshTools::createSkinnedMeshWithTangents(scene::ISkinnedMesh* mesh,
|
|
||||||
bool(*predicate)(scene::IMeshBuffer*))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
mesh->convertMeshToTangents(predicate);
|
|
||||||
}
|
|
||||||
|
@ -21,30 +21,17 @@
|
|||||||
|
|
||||||
namespace irr
|
namespace irr
|
||||||
{
|
{
|
||||||
namespace scene { class IMesh; class IMeshBuffer; class ISkinnedMesh; }
|
namespace scene { class IMesh; }
|
||||||
}
|
}
|
||||||
using namespace irr;
|
using namespace irr;
|
||||||
|
class Vec3;
|
||||||
#include "utils/vec3.hpp"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \ingroup graphics
|
* \ingroup graphics
|
||||||
*/
|
*/
|
||||||
namespace MeshTools
|
namespace MeshTools
|
||||||
{
|
{
|
||||||
void minMax3D(scene::IMesh* mesh, Vec3 *min, Vec3 *max);
|
void minMax3D(scene::IMesh* mesh, Vec3* min, Vec3* max);
|
||||||
|
|
||||||
bool isNormalMap(scene::IMeshBuffer* mb);
|
|
||||||
|
|
||||||
// Copied from irrlicht
|
|
||||||
scene::IMesh* createMeshWithTangents(scene::IMesh* mesh,
|
|
||||||
bool(*predicate)(scene::IMeshBuffer*), bool recalculateNormals = false,
|
|
||||||
bool smooth = false, bool angleWeighted = false,
|
|
||||||
bool calculateTangents = true);
|
|
||||||
|
|
||||||
void createSkinnedMeshWithTangents(scene::ISkinnedMesh* mesh,
|
|
||||||
bool(*predicate)(scene::IMeshBuffer*));
|
|
||||||
|
|
||||||
} // MeshTools
|
} // MeshTools
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -69,8 +69,7 @@ public:
|
|||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
virtual void animateMesh(f32 frame, f32 blend) {}
|
virtual void animateMesh(f32 frame, f32 blend) {}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
virtual void skinMesh(f32 strength=1.f, SkinningCallback sc = NULL,
|
virtual void skinMesh(f32 strength = 1.0f) {}
|
||||||
int offset = -1) {}
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
virtual u32 getMeshBufferCount() const
|
virtual u32 getMeshBufferCount() const
|
||||||
{ return (unsigned)m_buffer.size(); }
|
{ return (unsigned)m_buffer.size(); }
|
||||||
@ -110,8 +109,6 @@ public:
|
|||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
virtual void setInterpolationMode(E_INTERPOLATION_MODE mode) {}
|
virtual void setInterpolationMode(E_INTERPOLATION_MODE mode) {}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
virtual void convertMeshToTangents(bool(*predicate)(IMeshBuffer*)) {}
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
virtual bool isStatic() { return m_all_armatures.empty(); }
|
virtual bool isStatic() { return m_all_armatures.empty(); }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
virtual bool setHardwareSkinning(bool on) { return true; }
|
virtual bool setHardwareSkinning(bool on) { return true; }
|
||||||
|
@ -149,7 +149,7 @@ void SPMeshNode::OnAnimate(u32 time_ms)
|
|||||||
} // OnAnimate
|
} // OnAnimate
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
IMesh* SPMeshNode::getMeshForCurrentFrame(SkinningCallback sc, int offset)
|
IMesh* SPMeshNode::getMeshForCurrentFrame()
|
||||||
{
|
{
|
||||||
if (m_mesh->isStatic() || !m_animated)
|
if (m_mesh->isStatic() || !m_animated)
|
||||||
{
|
{
|
||||||
|
@ -90,8 +90,7 @@ public:
|
|||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
virtual void animateJoints(bool calculate_absolute_positions = true) {}
|
virtual void animateJoints(bool calculate_absolute_positions = true) {}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
virtual irr::scene::IMesh* getMeshForCurrentFrame(SkinningCallback sc = NULL,
|
virtual irr::scene::IMesh* getMeshForCurrentFrame();
|
||||||
int offset = -1);
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
virtual IBoneSceneNode* getJointNode(const c8* joint_name);
|
virtual IBoneSceneNode* getJointNode(const c8* joint_name);
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -22,7 +22,6 @@ using namespace irr;
|
|||||||
#include "config/user_config.hpp"
|
#include "config/user_config.hpp"
|
||||||
#include "graphics/irr_driver.hpp"
|
#include "graphics/irr_driver.hpp"
|
||||||
#include "graphics/lod_node.hpp"
|
#include "graphics/lod_node.hpp"
|
||||||
#include "graphics/mesh_tools.hpp"
|
|
||||||
#include "io/xml_node.hpp"
|
#include "io/xml_node.hpp"
|
||||||
#include "modes/world.hpp"
|
#include "modes/world.hpp"
|
||||||
#include "tracks/track.hpp"
|
#include "tracks/track.hpp"
|
||||||
@ -87,14 +86,6 @@ LODNode* ModelDefinitionLoader::instanciateAsLOD(const XMLNode* node, scene::ISc
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
scene::ISkinnedMesh* sm =
|
|
||||||
dynamic_cast<scene::ISkinnedMesh*>(a_mesh);
|
|
||||||
if (sm)
|
|
||||||
{
|
|
||||||
MeshTools::createSkinnedMeshWithTangents(sm,
|
|
||||||
&MeshTools::isNormalMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
a_mesh->grab();
|
a_mesh->grab();
|
||||||
//cache.push_back(a_mesh);
|
//cache.push_back(a_mesh);
|
||||||
irr_driver->grabAllTextures(a_mesh);
|
irr_driver->grabAllTextures(a_mesh);
|
||||||
@ -134,7 +125,6 @@ LODNode* ModelDefinitionLoader::instanciateAsLOD(const XMLNode* node, scene::ISc
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
a_mesh = MeshTools::createMeshWithTangents(a_mesh, &MeshTools::isNormalMap);
|
|
||||||
irr_driver->setAllMaterialFlags(a_mesh);
|
irr_driver->setAllMaterialFlags(a_mesh);
|
||||||
|
|
||||||
a_mesh->grab();
|
a_mesh->grab();
|
||||||
|
@ -1181,8 +1181,7 @@ bool Track::loadMainTrack(const XMLNode &root)
|
|||||||
merged_mesh->addMesh(mesh);
|
merged_mesh->addMesh(mesh);
|
||||||
merged_mesh->finalize();
|
merged_mesh->finalize();
|
||||||
#ifndef SERVER_ONLY
|
#ifndef SERVER_ONLY
|
||||||
tangent_mesh = MeshTools::createMeshWithTangents(merged_mesh, &MeshTools::isNormalMap);
|
tangent_mesh = merged_mesh;
|
||||||
|
|
||||||
adjustForFog(tangent_mesh, NULL);
|
adjustForFog(tangent_mesh, NULL);
|
||||||
#else
|
#else
|
||||||
tangent_mesh = merged_mesh;
|
tangent_mesh = merged_mesh;
|
||||||
@ -1310,9 +1309,6 @@ bool Track::loadMainTrack(const XMLNode &root)
|
|||||||
full_path.c_str());
|
full_path.c_str());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#ifndef SERVER_ONLY
|
|
||||||
a_mesh = MeshTools::createMeshWithTangents(a_mesh, &MeshTools::isNormalMap);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// The meshes loaded here are in irrlicht's mesh cache. So we
|
// The meshes loaded here are in irrlicht's mesh cache. So we
|
||||||
// have to keep track of them in order to properly remove them
|
// have to keep track of them in order to properly remove them
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
#include "graphics/irr_driver.hpp"
|
#include "graphics/irr_driver.hpp"
|
||||||
#include "graphics/light.hpp"
|
#include "graphics/light.hpp"
|
||||||
#include "graphics/material_manager.hpp"
|
#include "graphics/material_manager.hpp"
|
||||||
#include "graphics/mesh_tools.hpp"
|
|
||||||
#include "graphics/particle_emitter.hpp"
|
#include "graphics/particle_emitter.hpp"
|
||||||
#include "graphics/particle_kind_manager.hpp"
|
#include "graphics/particle_kind_manager.hpp"
|
||||||
#include "graphics/stk_particle.hpp"
|
#include "graphics/stk_particle.hpp"
|
||||||
@ -433,23 +432,6 @@ TrackObjectPresentationMesh::TrackObjectPresentationMesh(
|
|||||||
throw std::runtime_error("Model '" + model_name + "' cannot be found");
|
throw std::runtime_error("Model '" + model_name + "' cannot be found");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SERVER_ONLY
|
|
||||||
if (!animated)
|
|
||||||
{
|
|
||||||
m_mesh = MeshTools::createMeshWithTangents(m_mesh,
|
|
||||||
&MeshTools::isNormalMap);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
scene::ISkinnedMesh* sm =
|
|
||||||
dynamic_cast<scene::ISkinnedMesh*>(m_mesh);
|
|
||||||
if (sm)
|
|
||||||
{
|
|
||||||
MeshTools::createSkinnedMeshWithTangents(sm,
|
|
||||||
&MeshTools::isNormalMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
init(&xml_node, parent, enabled);
|
init(&xml_node, parent, enabled);
|
||||||
} // TrackObjectPresentationMesh
|
} // TrackObjectPresentationMesh
|
||||||
|
|
||||||
@ -494,18 +476,10 @@ TrackObjectPresentationMesh::TrackObjectPresentationMesh(
|
|||||||
if (animated)
|
if (animated)
|
||||||
{
|
{
|
||||||
m_mesh = irr_driver->getAnimatedMesh(model_file);
|
m_mesh = irr_driver->getAnimatedMesh(model_file);
|
||||||
scene::ISkinnedMesh* sm =
|
|
||||||
dynamic_cast<scene::ISkinnedMesh*>(m_mesh);
|
|
||||||
if (sm)
|
|
||||||
{
|
|
||||||
MeshTools::createSkinnedMeshWithTangents(sm,
|
|
||||||
&MeshTools::isNormalMap);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_mesh = MeshTools::createMeshWithTangents(
|
m_mesh = irr_driver->getMesh(model_file);
|
||||||
irr_driver->getMesh(model_file), &MeshTools::isNormalMap);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user