This commit is contained in:
hiker 2016-10-27 21:36:17 +11:00
commit 9f4c842b6c
11 changed files with 92 additions and 169 deletions

View File

@ -1474,77 +1474,6 @@ void CSkinnedMesh::calculateTangents(
}
}
// ----------------------------------------------------------------------------
/** Copies a mesh.
*/
CSkinnedMesh *CSkinnedMesh::clone()
{
CSkinnedMesh* skinned_mesh = new CSkinnedMesh();
for (u32 i = 0; i < getMeshBuffers().size(); i++)
{
SSkinMeshBuffer * buffer = skinned_mesh->addMeshBuffer();
*buffer = *(getMeshBuffers()[i]);
}
for (u32 j = 0; j < getAllJoints().size(); ++j)
{
ISkinnedMesh::SJoint *joint = skinned_mesh->addJoint();
*joint = *(getAllJoints()[j]);
}
// fix children pointers (they still have old pointers)
core::array<ISkinnedMesh::SJoint*> & new_joints = skinned_mesh->getAllJoints();
for (u32 i = 0; i < new_joints.size(); ++i)
{
ISkinnedMesh::SJoint * joint = new_joints[i];
for (u32 c = 0; c < joint->Children.size(); ++c)
{
// the child is one of the oldJoints and must be replaced by the newjoint on the same index
bool found = false;
for (u32 k = 0; k < AllJoints.size(); ++k)
{
if (joint->Children[c] == AllJoints[k])
{
joint->Children[c] = new_joints[k];
found = true;
break;
}
} // k < old_joints.size
if (!found)
found = true;
} // c < joint->Children.size()
} // i < new_joints.size()
// In finalize the values from LocalBuffers are copied into
// Weights[].StaticPos. Since skinned_mesh already has the correct
// values in Weights, we have to copy the values from Weights
// into LocalBuffer (so that in the copy from LocalBuffer to weights
// no values are overwritten).
// FIXME: Not ideal, better would be not to copy the values in
// finalize().
for (unsigned int i = 0; i<AllJoints.size(); ++i)
{
SJoint *joint = AllJoints[i];
for (unsigned int j = 0; j<joint->Weights.size(); ++j)
{
const u16 buffer_id = joint->Weights[j].buffer_id;
const u32 vertex_id = joint->Weights[j].vertex_id;
skinned_mesh->LocalBuffers[buffer_id]->getVertex(vertex_id)->Pos = joint->Weights[j].StaticPos;
skinned_mesh->LocalBuffers[buffer_id]->getVertex(vertex_id)->Normal = joint->Weights[j].StaticNormal;
}
}
skinned_mesh->finalize();
return skinned_mesh;
} // clone
} // end namespace scene
} // end namespace irr

View File

@ -159,7 +159,6 @@ namespace scene
void addJoints(core::array<IBoneSceneNode*> &jointChildSceneNodes,
IAnimatedMeshSceneNode* node,
ISceneManager* smgr);
CSkinnedMesh *clone();
private:
void checkForAnimation();

View File

@ -1069,28 +1069,6 @@ scene::IMesh *IrrDriver::getMesh(const std::string &filename)
return am->getMesh(0);
} // getMesh
// ----------------------------------------------------------------------------
/** Create a skinned mesh which has copied all meshbuffers and joints of the
* original mesh. Note, that this will not copy any other information like
* joints data.
* \param mesh Original mesh
* \return Newly created skinned mesh. You should call drop() when you don't
* need it anymore.
*/
scene::IAnimatedMesh *IrrDriver::copyAnimatedMesh(scene::IAnimatedMesh *orig)
{
using namespace scene;
CSkinnedMesh *mesh = dynamic_cast<CSkinnedMesh*>(orig);
if (!mesh)
{
Log::error("copyAnimatedMesh", "Given mesh was not a skinned mesh.");
return NULL;
}
scene::IAnimatedMesh* out = mesh->clone();
return out;
} // copyAnimatedMesh
// ----------------------------------------------------------------------------
/** Sets the material flags in this mesh depending on the settings in
* material_manager.
@ -1236,7 +1214,8 @@ scene::IMeshSceneNode *IrrDriver::addMesh(scene::IMesh *mesh,
const std::string& debug_name,
scene::ISceneNode *parent,
RenderInfo* render_info,
bool all_parts_colorized)
bool all_parts_colorized,
int frame_for_mesh)
{
if (!CVS->isGLSL())
return m_scene_manager->addMeshSceneNode(mesh, parent);
@ -1251,7 +1230,8 @@ scene::IMeshSceneNode *IrrDriver::addMesh(scene::IMesh *mesh,
core::vector3df(0, 0, 0),
core::vector3df(1.0f, 1.0f, 1.0f),
true, render_info,
all_parts_colorized);
all_parts_colorized,
frame_for_mesh);
node->drop();
return node;

View File

@ -358,7 +358,6 @@ public:
void setAllMaterialFlags(scene::IMesh *mesh) const;
scene::IAnimatedMesh *getAnimatedMesh(const std::string &name);
scene::IMesh *getMesh(const std::string &name);
scene::IAnimatedMesh *copyAnimatedMesh(scene::IAnimatedMesh *orig);
video::ITexture *applyMask(video::ITexture* texture,
const std::string& mask_path);
void displayFPS();
@ -393,7 +392,8 @@ public:
const std::string& debug_name,
scene::ISceneNode *parent = NULL,
RenderInfo* render_info = NULL,
bool all_parts_colorized = false);
bool all_parts_colorized = false,
int frame_for_mesh = -1);
PerCameraNode *addPerCameraNode(scene::ISceneNode* node,
scene::ICameraSceneNode* cam,
scene::ISceneNode *parent = NULL);

View File

@ -99,6 +99,16 @@ void STKAnimatedMesh::updateNoGL()
if (!isMaterialInitialized)
{
// Use a default render info to distinguish same mesh buffer created by
// different animated mesh node in vao manager when using instanced
// rendering
RenderInfo* default_ri = NULL;
if (CVS->isARBBaseInstanceUsable())
{
default_ri = new RenderInfo();
m_static_render_info.push_back(default_ri);
}
video::IVideoDriver* driver = SceneManager->getVideoDriver();
const u32 mb_count = m->getMeshBufferCount();
for (u32 i = 0; i < mb_count; ++i)
@ -121,7 +131,7 @@ void STKAnimatedMesh::updateNoGL()
}
else
{
cur_ri = NULL;
cur_ri = default_ri;
}
}
else
@ -137,7 +147,7 @@ void STKAnimatedMesh::updateNoGL()
assert(cur_ri ? cur_ri->isStatic() : true);
GLmeshes.push_back(allocateMeshBuffer(mb, m_debug_name,
affected || m_all_parts_colorized || (cur_ri
&& cur_ri->isTransparent()) ? cur_ri : NULL));
&& cur_ri->isTransparent()) ? cur_ri : default_ri));
}
for (u32 i = 0; i < m->getMeshBufferCount(); ++i)
@ -221,7 +231,7 @@ void STKAnimatedMesh::updateGL()
if (CVS->isARBBaseInstanceUsable())
{
std::pair<unsigned, unsigned> p = VAOManager::getInstance()->getBase(mb);
std::pair<unsigned, unsigned> p = VAOManager::getInstance()->getBase(mb, GLmeshes[i].m_render_info);
mesh.vaoBaseVertex = p.first;
mesh.vaoOffset = p.second;
}

View File

@ -32,8 +32,8 @@
#include "utils/helpers.hpp"
#include "utils/tuple.hpp"
#include <ISceneManager.h>
#include <IMaterialRenderer.h>
#include <ISceneManager.h>
// ============================================================================
class ColorizeShader : public Shader<ColorizeShader, core::matrix4,
@ -54,12 +54,14 @@ STKMeshSceneNode::STKMeshSceneNode(irr::scene::IMesh* mesh, ISceneNode* parent,
irr::s32 id, const std::string& debug_name,
const irr::core::vector3df& position,
const irr::core::vector3df& rotation,
const irr::core::vector3df& scale, bool createGLMeshes, RenderInfo* render_info, bool all_parts_colorized) :
const irr::core::vector3df& scale, bool createGLMeshes, RenderInfo* render_info, bool all_parts_colorized,
int frame_for_mesh) :
CMeshSceneNode(mesh, parent, mgr, id, position, rotation, scale)
{
isDisplacement = false;
immediate_draw = false;
update_each_frame = false;
m_frame_for_mesh = frame_for_mesh;
isGlow = false;
m_debug_name = debug_name;
@ -250,9 +252,18 @@ void STKMeshSceneNode::updateGL()
{
if (isGLInitialized)
return;
for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i)
scene::IAnimatedMesh* am = dynamic_cast<scene::IAnimatedMesh*>(Mesh);
scene::IMesh* m = Mesh;
if (am && m_frame_for_mesh > -1)
{
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
// Get the correct frame of animation for animated mesh
m = am->getMesh(m_frame_for_mesh);
}
for (u32 i = 0; i < m->getMeshBufferCount(); ++i)
{
scene::IMeshBuffer* mb = m->getMeshBuffer(i);
if (!mb)
continue;
GLMesh &mesh = GLmeshes[i];

View File

@ -29,6 +29,7 @@ class STKMeshSceneNode : public irr::scene::CMeshSceneNode, public STKMeshCommon
{
protected:
PtrVector<RenderInfo> m_static_render_info;
int m_frame_for_mesh;
std::vector<GLMesh> GLmeshes;
core::matrix4 ModelViewProjectionMatrix;
core::vector3df windDir;
@ -58,7 +59,8 @@ public:
const irr::core::vector3df& rotation = irr::core::vector3df(0, 0, 0),
const irr::core::vector3df& scale = irr::core::vector3df(1.0f, 1.0f, 1.0f),
bool createGLMeshes = true,
RenderInfo* render_info = NULL, bool all_parts_colorized = false);
RenderInfo* render_info = NULL, bool all_parts_colorized = false,
int frame_for_mesh = -1);
virtual void render();
virtual void setMesh(irr::scene::IMesh* mesh);
virtual void OnRegisterSceneNode();

View File

@ -41,7 +41,6 @@
#include <unordered_map>
#include <SViewFrustum.h>
#include <functional>
template<typename T>
struct InstanceFiller
@ -156,28 +155,6 @@ FillInstances_impl(std::vector<std::pair<GLMesh *, scene::ISceneNode *> > Instan
PolyCount += (InstanceBufferOffset - InitialOffset) * mesh->IndexCount / 3;
}
class MeshRenderInfoHash
{
public:
size_t operator() (const std::pair<scene::IMeshBuffer*, RenderInfo*> &p) const
{
return (std::hash<scene::IMeshBuffer*>()(p.first) ^
(std::hash<RenderInfo*>()(p.second) << 1));
}
};
struct MeshRenderInfoEquals : std::binary_function
<const std::pair<scene::IMeshBuffer*, RenderInfo*>&,
const std::pair<scene::IMeshBuffer*, RenderInfo*>&, bool>
{
result_type operator() (first_argument_type lhs,
second_argument_type rhs) const
{
return (lhs.first == rhs.first) &&
(lhs.second == rhs.second);
}
};
template<typename T>
static
void FillInstances(const std::unordered_map<std::pair<scene::IMeshBuffer*, RenderInfo*>, std::vector<std::pair<GLMesh *, scene::ISceneNode*> >, MeshRenderInfoHash, MeshRenderInfoEquals> &GatheredGLMesh, std::vector<GLMesh *> &InstancedList,

View File

@ -287,7 +287,7 @@ irr::video::E_VERTEX_TYPE VAOManager::getVertexType(enum VTXTYPE tp)
}
}
void VAOManager::append(scene::IMeshBuffer *mb, VTXTYPE tp)
void VAOManager::append(scene::IMeshBuffer *mb, VTXTYPE tp, RenderInfo* ri)
{
size_t old_vtx_cnt = last_vertex[tp];
size_t old_idx_cnt = last_index[tp];
@ -318,26 +318,28 @@ void VAOManager::append(scene::IMeshBuffer *mb, VTXTYPE tp)
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, old_idx_cnt * sizeof(u16), mb->getIndexCount() * sizeof(u16), mb->getIndices());
}
mappedBaseVertex[tp][mb] = old_vtx_cnt;
mappedBaseIndex[tp][mb] = old_idx_cnt * sizeof(u16);
std::pair<scene::IMeshBuffer*, RenderInfo*> key(mb, ri);
mappedBaseVertex[tp][key] = old_vtx_cnt;
mappedBaseIndex[tp][key] = old_idx_cnt * sizeof(u16);
}
std::pair<unsigned, unsigned> VAOManager::getBase(scene::IMeshBuffer *mb)
std::pair<unsigned, unsigned> VAOManager::getBase(scene::IMeshBuffer *mb, RenderInfo* ri)
{
VTXTYPE tp = getVTXTYPE(mb->getVertexType());
if (mappedBaseVertex[tp].find(mb) == mappedBaseVertex[tp].end())
std::pair<scene::IMeshBuffer*, RenderInfo*> key(mb, ri);
if (mappedBaseVertex[tp].find(key) == mappedBaseVertex[tp].end())
{
assert(mappedBaseIndex[tp].find(mb) == mappedBaseIndex[tp].end());
append(mb, tp);
assert(mappedBaseIndex[tp].find(key) == mappedBaseIndex[tp].end());
append(mb, tp, ri);
regenerateVAO(tp);
regenerateInstancedVAO();
}
std::unordered_map<scene::IMeshBuffer*, unsigned>::iterator It;
It = mappedBaseVertex[tp].find(mb);
std::unordered_map<std::pair<scene::IMeshBuffer*, RenderInfo*>, unsigned, MeshRenderInfoHash, MeshRenderInfoEquals>::iterator It;
It = mappedBaseVertex[tp].find(key);
assert(It != mappedBaseVertex[tp].end());
unsigned vtx = It->second;
It = mappedBaseIndex[tp].find(mb);
It = mappedBaseIndex[tp].find(key);
assert(It != mappedBaseIndex[tp].end());
return std::pair<unsigned, unsigned>(vtx, It->second);
}

View File

@ -26,6 +26,8 @@
#include <map>
#include <unordered_map>
class RenderInfo;
enum InstanceType
{
InstanceTypeDualTex,
@ -153,6 +155,30 @@ struct GlowInstanceData
#pragma pack(pop)
#endif
#include <functional>
class MeshRenderInfoHash
{
public:
size_t operator() (const std::pair<irr::scene::IMeshBuffer*, RenderInfo*> &p) const
{
return (std::hash<irr::scene::IMeshBuffer*>()(p.first) ^
(std::hash<RenderInfo*>()(p.second) << 1));
}
};
struct MeshRenderInfoEquals : std::binary_function
<const std::pair<irr::scene::IMeshBuffer*, RenderInfo*>&,
const std::pair<irr::scene::IMeshBuffer*, RenderInfo*>&, bool>
{
result_type operator() (first_argument_type lhs,
second_argument_type rhs) const
{
return (lhs.first == rhs.first) &&
(lhs.second == rhs.second);
}
};
class VAOManager : public Singleton<VAOManager>
{
enum VTXTYPE { VTXTYPE_STANDARD, VTXTYPE_TCOORD, VTXTYPE_TANGENT, VTXTYPE_COUNT };
@ -162,7 +188,7 @@ class VAOManager : public Singleton<VAOManager>
void *VBOPtr[VTXTYPE_COUNT], *IBOPtr[VTXTYPE_COUNT];
size_t RealVBOSize[VTXTYPE_COUNT], RealIBOSize[VTXTYPE_COUNT];
size_t last_vertex[VTXTYPE_COUNT], last_index[VTXTYPE_COUNT];
std::unordered_map<irr::scene::IMeshBuffer*, unsigned> mappedBaseVertex[VTXTYPE_COUNT], mappedBaseIndex[VTXTYPE_COUNT];
std::unordered_map <std::pair<irr::scene::IMeshBuffer*, RenderInfo*>, unsigned, MeshRenderInfoHash, MeshRenderInfoEquals> mappedBaseVertex[VTXTYPE_COUNT], mappedBaseIndex[VTXTYPE_COUNT];
std::map<std::pair<irr::video::E_VERTEX_TYPE, InstanceType>, GLuint> InstanceVAO;
void cleanInstanceVAOs();
@ -172,10 +198,10 @@ class VAOManager : public Singleton<VAOManager>
size_t getVertexPitch(enum VTXTYPE) const;
VTXTYPE getVTXTYPE(irr::video::E_VERTEX_TYPE type);
irr::video::E_VERTEX_TYPE getVertexType(enum VTXTYPE tp);
void append(irr::scene::IMeshBuffer *, VTXTYPE tp);
void append(irr::scene::IMeshBuffer *, VTXTYPE tp, RenderInfo* ri = NULL);
public:
VAOManager();
std::pair<unsigned, unsigned> getBase(irr::scene::IMeshBuffer *);
std::pair<unsigned, unsigned> getBase(irr::scene::IMeshBuffer *, RenderInfo* ri = NULL);
GLuint getInstanceBuffer(InstanceType it) { return instance_vbo[it]; }
void *getInstanceBufferPtr(InstanceType it) { return Ptr[it]; }
unsigned getVBO(irr::video::E_VERTEX_TYPE type) { return vbo[getVTXTYPE(type)]; }

View File

@ -247,12 +247,6 @@ KartModel::~KartModel()
{
// Master KartModels should never have a speed weighted object attached.
assert(!m_is_master);
// Drop the cloned transparent model if created
if (m_krt == KRT_TRANSPARENT)
{
m_speed_weighted_objects[i].m_model->drop();
}
m_speed_weighted_objects[i].m_node->drop();
}
if(m_is_master && m_speed_weighted_objects[i].m_model)
@ -262,20 +256,15 @@ KartModel::~KartModel()
}
}
// In case of the master, the mesh must be dropped. A non-master KartModel
// has a copy of the master's mesh, so it needs to be dropped, too.
if (m_mesh)
if (m_is_master && m_mesh)
{
m_mesh->drop();
if (m_is_master)
// If there is only one copy left, it's the copy in irrlicht's
// mesh cache, so it can be removed.
if (m_mesh && m_mesh->getReferenceCount() == 1)
{
// If there is only one copy left, it's the copy in irrlicht's
// mesh cache, so it can be removed.
if (m_mesh && m_mesh->getReferenceCount() == 1)
{
irr_driver->dropAllTextures(m_mesh);
irr_driver->removeMeshFromCache(m_mesh);
}
irr_driver->dropAllTextures(m_mesh);
irr_driver->removeMeshFromCache(m_mesh);
}
}
@ -308,7 +297,7 @@ KartModel* KartModel::makeCopy(KartRenderType krt)
km->m_kart_height = m_kart_height;
km->m_kart_highest_point = m_kart_highest_point;
km->m_kart_lowest_point = m_kart_lowest_point;
km->m_mesh = irr_driver->copyAnimatedMesh(m_mesh);
km->m_mesh = m_mesh;
km->m_model_filename = m_model_filename;
km->m_animation_speed = m_animation_speed;
km->m_current_animation = AF_DEFAULT;
@ -343,12 +332,6 @@ KartModel* KartModel::makeCopy(KartRenderType krt)
// Master should not have any speed weighted nodes.
assert(!m_speed_weighted_objects[i].m_node);
km->m_speed_weighted_objects[i] = m_speed_weighted_objects[i];
if (krt == KRT_TRANSPARENT)
{
// Only clone the mesh if transparent type is used, see #2445
km->m_speed_weighted_objects[i].m_model = irr_driver
->copyAnimatedMesh(m_speed_weighted_objects[i].m_model);
}
}
for(unsigned int i=AF_BEGIN; i<=AF_END; i++)
@ -444,8 +427,12 @@ scene::ISceneNode* KartModel::attachModel(bool animated_models, bool always_anim
? m_animation_frame[AF_STRAIGHT]
: 0;
scene::IMesh* main_frame = m_mesh->getMesh(straight_frame);
main_frame->setHardwareMappingHint(scene::EHM_STATIC);
scene::IMesh* main_frame = m_mesh;
if (!CVS->isGLSL())
{
main_frame = m_mesh->getMesh(straight_frame);
main_frame->setHardwareMappingHint(scene::EHM_STATIC);
}
std::string debug_name;
@ -454,7 +441,7 @@ scene::ISceneNode* KartModel::attachModel(bool animated_models, bool always_anim
#endif
node = irr_driver->addMesh(main_frame, debug_name,
NULL /*parent*/, getRenderInfo());
NULL /*parent*/, getRenderInfo(), false, straight_frame);
#ifdef DEBUG
node->setName(debug_name.c_str());