Remove unused mesh code

This commit is contained in:
Benau 2018-01-11 13:38:08 +08:00
parent 68ceceb6e3
commit 7859a00967
14 changed files with 86 additions and 901 deletions

@ -8,8 +8,6 @@
#include "aabbox3d.h"
#include "IMesh.h"
typedef void (*SkinningCallback)(const irr::core::matrix4& m, int joint, int offset);
namespace irr
{
namespace scene

@ -69,11 +69,7 @@ namespace scene
virtual void animateMesh(f32 frame, f32 blend)=0;
//! 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;
//! converts the vertex type of all meshbuffers to tangents.
/** E.g. used for bump mapping. */
virtual void convertMeshToTangents(bool(*predicate)(IMeshBuffer*)) = 0;
virtual void skinMesh(f32 strength=1.f) = 0;
//! Allows to enable hardware skinning.
/* 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)
{
@ -201,7 +201,7 @@ IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame(SkinningCallback sc, int
skinnedMesh->animateMesh(getFrameNr(), 1.0f);
// Update the skinned mesh for the current joint transforms.
skinnedMesh->skinMesh(AnimationStrength, sc, offset);
skinnedMesh->skinMesh(AnimationStrength);
if (JointMode == EJUOR_READ)//read from mesh
{

@ -173,7 +173,7 @@ namespace scene
protected:
//! 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);
virtual void checkJoints();

@ -11,55 +11,6 @@
#include "os.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 scene
@ -72,8 +23,7 @@ CSkinnedMesh::CSkinnedMesh()
LastAnimatedFrame(-1), SkinnedLastFrame(false),
InterpolationMode(EIM_LINEAR),
HasAnimation(false), PreparedForSkinning(false),
AnimateNormals(true), HardwareSkinning(false), m_total_joints(0),
m_current_joint(0)
AnimateNormals(true), HardwareSkinning(false)
{
#ifdef _DEBUG
setDebugName("CSkinnedMesh");
@ -511,7 +461,7 @@ void CSkinnedMesh::getFrameData(f32 frame, SJoint *joint,
//--------------------------------------------------------------------------
//! 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)
return;
@ -522,109 +472,94 @@ void CSkinnedMesh::skinMesh(f32 strength, SkinningCallback sc, int offset)
//-----------------
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
for (i=0; i<AllJoints.size(); ++i)
//Software skin....
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();
}
void CSkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint, f32 strength,
SkinningCallback sc, int offset)
void CSkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint, f32 strength)
{
if (joint->Weights.size())
{
//Find this joints pull on vertices...
core::matrix4 jointVertexPull(core::matrix4::EM4CONST_NOTHING);
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...
for (u32 i=0; i<joint->Weights.size(); ++i)
core::array<scene::SSkinMeshBuffer*> &buffersUsed=*SkinningBuffers;
//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...
jointVertexPull.transformVect(thisVertexMove, weight.StaticPos);
if (! (*(weight.Moved)) )
{
*(weight.Moved) = true;
buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Pos = thisVertexMove * weight.strength;
if (AnimateNormals)
jointVertexPull.rotateVect(thisNormalMove, weight.StaticNormal);
buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Normal = thisNormalMove * weight.strength;
// Apply animation 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();
//*(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();
}
}
//Skin all children
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;
}
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 irr

@ -61,7 +61,7 @@ namespace scene
virtual void animateMesh(f32 frame, f32 blend);
//! 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.
virtual u32 getMeshBufferCount() const;
@ -113,9 +113,6 @@ namespace scene
//! Sets Interpolation 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
virtual bool isStatic();
@ -172,14 +169,12 @@ namespace scene
void convertForSkinning();
void computeWeightInfluence(SJoint *joint, size_t &index, WeightInfluence& wi);
void buildAllGlobalAnimatedMatrices(SJoint *Joint=0, SJoint *ParentJoint=0);
u32 getTotalJoints() const { return m_total_joints; }
void buildAllGlobalAnimatedMatrices(SJoint *Joint=0, SJoint *ParentJoint=0);
f32 AnimationFrames;
core::array<SJoint*> RootJoints;
core::array<SJoint*> RootJoints;
private:
void toStaticPose();
@ -197,8 +192,7 @@ private:
void calculateGlobalMatrices(SJoint *Joint,SJoint *ParentJoint);
void skinJoint(SJoint *Joint, SJoint *ParentJoint, f32 strength=1.f,
SkinningCallback sc = NULL, int offset = -1);
void skinJoint(SJoint *Joint, SJoint *ParentJoint, f32 strength=1.f);
void calculateTangents(core::vector3df& normal,
core::vector3df& tangent, core::vector3df& binormal,
@ -229,8 +223,6 @@ private:
bool PreparedForSkinning;
bool AnimateNormals;
bool HardwareSkinning;
u32 m_total_joints;
u32 m_current_joint;
};
} // end namespace scene

@ -16,21 +16,17 @@
// along with this program; if not, write to the Free Software
// 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/vec3.hpp"
#include <irrlicht.h>
#include <IMesh.h>
#include <IMeshBuffer.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;
*min = Vec3( 999999.9f);
@ -103,407 +99,4 @@ void MeshTools::minMax3D(scene::IMesh* mesh, Vec3 *min, Vec3 *max)
} // for i<getMeshBufferCount
} // minMax3D
// Copied from irrlicht
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);
}
} // namespace MeshTools

@ -21,30 +21,17 @@
namespace irr
{
namespace scene { class IMesh; class IMeshBuffer; class ISkinnedMesh; }
namespace scene { class IMesh; }
}
using namespace irr;
#include "utils/vec3.hpp"
class Vec3;
/**
* \ingroup graphics
*/
namespace MeshTools
{
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*));
void minMax3D(scene::IMesh* mesh, Vec3* min, Vec3* max);
} // MeshTools
#endif

@ -69,8 +69,7 @@ public:
// ------------------------------------------------------------------------
virtual void animateMesh(f32 frame, f32 blend) {}
// ------------------------------------------------------------------------
virtual void skinMesh(f32 strength=1.f, SkinningCallback sc = NULL,
int offset = -1) {}
virtual void skinMesh(f32 strength = 1.0f) {}
// ------------------------------------------------------------------------
virtual u32 getMeshBufferCount() const
{ return (unsigned)m_buffer.size(); }
@ -110,8 +109,6 @@ public:
// ------------------------------------------------------------------------
virtual void setInterpolationMode(E_INTERPOLATION_MODE mode) {}
// ------------------------------------------------------------------------
virtual void convertMeshToTangents(bool(*predicate)(IMeshBuffer*)) {}
// ------------------------------------------------------------------------
virtual bool isStatic() { return m_all_armatures.empty(); }
// ------------------------------------------------------------------------
virtual bool setHardwareSkinning(bool on) { return true; }

@ -149,7 +149,7 @@ void SPMeshNode::OnAnimate(u32 time_ms)
} // OnAnimate
// ----------------------------------------------------------------------------
IMesh* SPMeshNode::getMeshForCurrentFrame(SkinningCallback sc, int offset)
IMesh* SPMeshNode::getMeshForCurrentFrame()
{
if (m_mesh->isStatic() || !m_animated)
{

@ -90,8 +90,7 @@ public:
// ------------------------------------------------------------------------
virtual void animateJoints(bool calculate_absolute_positions = true) {}
// ------------------------------------------------------------------------
virtual irr::scene::IMesh* getMeshForCurrentFrame(SkinningCallback sc = NULL,
int offset = -1);
virtual irr::scene::IMesh* getMeshForCurrentFrame();
// ------------------------------------------------------------------------
virtual IBoneSceneNode* getJointNode(const c8* joint_name);
// ------------------------------------------------------------------------

@ -22,7 +22,6 @@ using namespace irr;
#include "config/user_config.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/lod_node.hpp"
#include "graphics/mesh_tools.hpp"
#include "io/xml_node.hpp"
#include "modes/world.hpp"
#include "tracks/track.hpp"
@ -87,14 +86,6 @@ LODNode* ModelDefinitionLoader::instanciateAsLOD(const XMLNode* node, scene::ISc
continue;
}
scene::ISkinnedMesh* sm =
dynamic_cast<scene::ISkinnedMesh*>(a_mesh);
if (sm)
{
MeshTools::createSkinnedMeshWithTangents(sm,
&MeshTools::isNormalMap);
}
a_mesh->grab();
//cache.push_back(a_mesh);
irr_driver->grabAllTextures(a_mesh);
@ -134,7 +125,6 @@ LODNode* ModelDefinitionLoader::instanciateAsLOD(const XMLNode* node, scene::ISc
continue;
}
a_mesh = MeshTools::createMeshWithTangents(a_mesh, &MeshTools::isNormalMap);
irr_driver->setAllMaterialFlags(a_mesh);
a_mesh->grab();

@ -1181,8 +1181,7 @@ bool Track::loadMainTrack(const XMLNode &root)
merged_mesh->addMesh(mesh);
merged_mesh->finalize();
#ifndef SERVER_ONLY
tangent_mesh = MeshTools::createMeshWithTangents(merged_mesh, &MeshTools::isNormalMap);
tangent_mesh = merged_mesh;
adjustForFog(tangent_mesh, NULL);
#else
tangent_mesh = merged_mesh;
@ -1310,9 +1309,6 @@ bool Track::loadMainTrack(const XMLNode &root)
full_path.c_str());
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
// have to keep track of them in order to properly remove them

@ -27,7 +27,6 @@
#include "graphics/irr_driver.hpp"
#include "graphics/light.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/mesh_tools.hpp"
#include "graphics/particle_emitter.hpp"
#include "graphics/particle_kind_manager.hpp"
#include "graphics/stk_particle.hpp"
@ -433,23 +432,6 @@ TrackObjectPresentationMesh::TrackObjectPresentationMesh(
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);
} // TrackObjectPresentationMesh
@ -494,18 +476,10 @@ TrackObjectPresentationMesh::TrackObjectPresentationMesh(
if (animated)
{
m_mesh = irr_driver->getAnimatedMesh(model_file);
scene::ISkinnedMesh* sm =
dynamic_cast<scene::ISkinnedMesh*>(m_mesh);
if (sm)
{
MeshTools::createSkinnedMeshWithTangents(sm,
&MeshTools::isNormalMap);
}
}
else
{
m_mesh = MeshTools::createMeshWithTangents(
irr_driver->getMesh(model_file), &MeshTools::isNormalMap);
m_mesh = irr_driver->getMesh(model_file);
}
}
#endif