First version of hardware skinning
Todo: shadow, non-instanced shaders, culling, changeable offset...
This commit is contained in:
parent
23883b83c1
commit
57d9e83ed4
@ -63,5 +63,11 @@ layout (std140) uniform LightingData
|
|||||||
float rL21;
|
float rL21;
|
||||||
float rL22;
|
float rL22;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
layout (std140) uniform SkinningData
|
||||||
|
{
|
||||||
|
mat4 joint_matrices[1000];
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif // HEADER_TXT
|
#endif // HEADER_TXT
|
||||||
|
120
data/shaders/instanced_skinning.vert
Normal file
120
data/shaders/instanced_skinning.vert
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
layout(location = 0) in vec3 Position;
|
||||||
|
layout(location = 1) in vec3 Normal;
|
||||||
|
layout(location = 2) in vec4 Color;
|
||||||
|
layout(location = 3) in vec4 Data1;
|
||||||
|
layout(location = 4) in vec4 Data2;
|
||||||
|
layout(location = 5) in ivec4 Joint;
|
||||||
|
layout(location = 6) in vec4 Weight;
|
||||||
|
|
||||||
|
layout(location = 7) in vec3 Origin;
|
||||||
|
layout(location = 8) in vec3 Orientation;
|
||||||
|
layout(location = 9) in vec3 Scale;
|
||||||
|
layout(location = 10) in vec4 misc_data;
|
||||||
|
#ifdef Use_Bindless_Texture
|
||||||
|
layout(location = 11) in sampler2D Handle;
|
||||||
|
layout(location = 12) in sampler2D SecondHandle;
|
||||||
|
layout(location = 13) in sampler2D ThirdHandle;
|
||||||
|
layout(location = 14) in sampler2D FourthHandle;
|
||||||
|
#endif
|
||||||
|
layout(location = 15) in uint skinning_offset;
|
||||||
|
|
||||||
|
out vec3 nor;
|
||||||
|
out vec3 tangent;
|
||||||
|
out vec3 bitangent;
|
||||||
|
out vec2 uv;
|
||||||
|
out vec4 color;
|
||||||
|
out vec2 color_change;
|
||||||
|
#ifdef Use_Bindless_Texture
|
||||||
|
flat out sampler2D handle;
|
||||||
|
flat out sampler2D secondhandle;
|
||||||
|
flat out sampler2D thirdhandle;
|
||||||
|
flat out sampler2D fourthhandle;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#stk_include "utils/getworldmatrix.vert"
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
mat4 ModelMatrix = getWorldMatrix(Origin, Orientation, Scale);
|
||||||
|
mat4 TransposeInverseModelView = transpose(getInverseWorldMatrix(Origin, Orientation, Scale) * InverseViewMatrix);
|
||||||
|
|
||||||
|
vec4 idle_position = vec4(Position, 1.);
|
||||||
|
vec4 idle_normal = vec4(Normal, 0.);
|
||||||
|
vec4 skinned_position = vec4(0.);
|
||||||
|
vec4 skinned_normal = vec4(0.);
|
||||||
|
// Note : For normal we assume no scale factor in bone (otherwise we'll have to compute inversematrix for each bones...)
|
||||||
|
vec4 single_bone_influenced_position;
|
||||||
|
vec4 single_bone_influenced_normal;
|
||||||
|
if (Joint[0] >= 0)
|
||||||
|
{
|
||||||
|
single_bone_influenced_position = joint_matrices[Joint[0] + skinning_offset] * idle_position;
|
||||||
|
single_bone_influenced_position /= single_bone_influenced_position.w;
|
||||||
|
single_bone_influenced_normal = joint_matrices[Joint[0] + skinning_offset] * idle_normal;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
single_bone_influenced_position = idle_position;
|
||||||
|
single_bone_influenced_normal = idle_normal;
|
||||||
|
}
|
||||||
|
skinned_position += Weight[0] * single_bone_influenced_position;
|
||||||
|
skinned_normal += Weight[0] * single_bone_influenced_normal;
|
||||||
|
|
||||||
|
if (Joint[1] >= 0)
|
||||||
|
{
|
||||||
|
single_bone_influenced_position= joint_matrices[Joint[1] + skinning_offset] * idle_position;
|
||||||
|
single_bone_influenced_position /= single_bone_influenced_position.w;
|
||||||
|
single_bone_influenced_normal = joint_matrices[Joint[1] + skinning_offset] * idle_normal;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
single_bone_influenced_position = idle_position;
|
||||||
|
single_bone_influenced_normal = idle_normal;
|
||||||
|
}
|
||||||
|
skinned_position += Weight[1] * single_bone_influenced_position;
|
||||||
|
skinned_normal += Weight[1] * single_bone_influenced_normal;
|
||||||
|
|
||||||
|
if (Joint[2] >= 0)
|
||||||
|
{
|
||||||
|
single_bone_influenced_position = joint_matrices[Joint[2] + skinning_offset] * idle_position;
|
||||||
|
single_bone_influenced_position /= single_bone_influenced_position.w;
|
||||||
|
single_bone_influenced_normal = joint_matrices[Joint[2] + skinning_offset] * idle_normal;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
single_bone_influenced_position = idle_position;
|
||||||
|
single_bone_influenced_normal = idle_normal;
|
||||||
|
}
|
||||||
|
skinned_position += Weight[2] * single_bone_influenced_position;
|
||||||
|
skinned_normal += Weight[2] * single_bone_influenced_normal;
|
||||||
|
|
||||||
|
if (Joint[3] >= 0)
|
||||||
|
{
|
||||||
|
single_bone_influenced_position = joint_matrices[Joint[3] + skinning_offset] * idle_position;
|
||||||
|
single_bone_influenced_position /= single_bone_influenced_position.w;
|
||||||
|
single_bone_influenced_normal = joint_matrices[Joint[3] + skinning_offset] * idle_normal;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
single_bone_influenced_position = idle_position;
|
||||||
|
single_bone_influenced_normal = idle_normal;
|
||||||
|
}
|
||||||
|
skinned_position += Weight[3] * single_bone_influenced_position;
|
||||||
|
skinned_normal += Weight[3] * single_bone_influenced_normal;
|
||||||
|
|
||||||
|
gl_Position = ProjectionViewMatrix * ModelMatrix * skinned_position;
|
||||||
|
// Keep orthogonality
|
||||||
|
nor = (TransposeInverseModelView * skinned_normal).xyz;
|
||||||
|
// Keep direction
|
||||||
|
tangent = (ViewMatrix * ModelMatrix * vec4(Data1.z, Data1.w, Data2.x, 0.)).xyz;
|
||||||
|
bitangent = (ViewMatrix * ModelMatrix * vec4(Data2.y, Data2.z, Data2.w, 0.)).xyz;
|
||||||
|
|
||||||
|
uv = vec2(Data1.x + misc_data.x, Data1.y + misc_data.y);
|
||||||
|
color = Color.zyxw;
|
||||||
|
color_change = misc_data.zw;
|
||||||
|
#ifdef Use_Bindless_Texture
|
||||||
|
handle = Handle;
|
||||||
|
secondhandle = SecondHandle;
|
||||||
|
thirdhandle = ThirdHandle;
|
||||||
|
fourthhandle = FourthHandle;
|
||||||
|
#endif
|
||||||
|
}
|
@ -116,6 +116,8 @@ namespace scene
|
|||||||
NewVertices=new CSpecificVertexList<video::S3DVertexTangents>;
|
NewVertices=new CSpecificVertexList<video::S3DVertexTangents>;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (Vertices)
|
if (Vertices)
|
||||||
{
|
{
|
||||||
|
@ -371,6 +371,8 @@ protected:
|
|||||||
func(verts[i]);
|
func(verts[i]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (boundingBoxUpdate)
|
if (boundingBoxUpdate)
|
||||||
{
|
{
|
||||||
|
@ -26,7 +26,9 @@ enum E_VERTEX_TYPE
|
|||||||
|
|
||||||
//! Vertex with a tangent and binormal vector, video::S3DVertexTangents.
|
//! Vertex with a tangent and binormal vector, video::S3DVertexTangents.
|
||||||
/** Usually used for tangent space normal mapping. */
|
/** Usually used for tangent space normal mapping. */
|
||||||
EVT_TANGENTS
|
EVT_TANGENTS,
|
||||||
|
|
||||||
|
EVT_SKINNED_MESH
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Array holding the built in vertex type names
|
//! Array holding the built in vertex type names
|
||||||
@ -251,6 +253,22 @@ struct S3DVertexTangents : public S3DVertex
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct S3DVertexSkinnedMesh : public S3DVertexTangents
|
||||||
|
{
|
||||||
|
s32 m_joint_idx1;
|
||||||
|
s32 m_joint_idx2;
|
||||||
|
s32 m_joint_idx3;
|
||||||
|
s32 m_joint_idx4;
|
||||||
|
f32 m_weight1;
|
||||||
|
f32 m_weight2;
|
||||||
|
f32 m_weight3;
|
||||||
|
f32 m_weight4;
|
||||||
|
|
||||||
|
E_VERTEX_TYPE getType() const
|
||||||
|
{
|
||||||
|
return EVT_SKINNED_MESH;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
inline u32 getVertexPitchFromType(E_VERTEX_TYPE vertexType)
|
inline u32 getVertexPitchFromType(E_VERTEX_TYPE vertexType)
|
||||||
@ -261,6 +279,8 @@ inline u32 getVertexPitchFromType(E_VERTEX_TYPE vertexType)
|
|||||||
return sizeof(video::S3DVertex2TCoords);
|
return sizeof(video::S3DVertex2TCoords);
|
||||||
case video::EVT_TANGENTS:
|
case video::EVT_TANGENTS:
|
||||||
return sizeof(video::S3DVertexTangents);
|
return sizeof(video::S3DVertexTangents);
|
||||||
|
case video::EVT_SKINNED_MESH:
|
||||||
|
return sizeof(video::S3DVertexSkinnedMesh);
|
||||||
default:
|
default:
|
||||||
return sizeof(video::S3DVertex);
|
return sizeof(video::S3DVertex);
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,8 @@ struct SSkinMeshBuffer : public IMeshBuffer
|
|||||||
return (video::S3DVertex*)&Vertices_2TCoords[index];
|
return (video::S3DVertex*)&Vertices_2TCoords[index];
|
||||||
case video::EVT_TANGENTS:
|
case video::EVT_TANGENTS:
|
||||||
return (video::S3DVertex*)&Vertices_Tangents[index];
|
return (video::S3DVertex*)&Vertices_Tangents[index];
|
||||||
|
case video::EVT_SKINNED_MESH:
|
||||||
|
return (video::S3DVertex*)&Vertices_SkinnedMesh[index];
|
||||||
default:
|
default:
|
||||||
return &Vertices_Standard[index];
|
return &Vertices_Standard[index];
|
||||||
}
|
}
|
||||||
@ -64,6 +66,8 @@ struct SSkinMeshBuffer : public IMeshBuffer
|
|||||||
return Vertices_2TCoords.const_pointer();
|
return Vertices_2TCoords.const_pointer();
|
||||||
case video::EVT_TANGENTS:
|
case video::EVT_TANGENTS:
|
||||||
return Vertices_Tangents.const_pointer();
|
return Vertices_Tangents.const_pointer();
|
||||||
|
case video::EVT_SKINNED_MESH:
|
||||||
|
return Vertices_SkinnedMesh.const_pointer();
|
||||||
default:
|
default:
|
||||||
return Vertices_Standard.const_pointer();
|
return Vertices_Standard.const_pointer();
|
||||||
}
|
}
|
||||||
@ -78,6 +82,8 @@ struct SSkinMeshBuffer : public IMeshBuffer
|
|||||||
return Vertices_2TCoords.pointer();
|
return Vertices_2TCoords.pointer();
|
||||||
case video::EVT_TANGENTS:
|
case video::EVT_TANGENTS:
|
||||||
return Vertices_Tangents.pointer();
|
return Vertices_Tangents.pointer();
|
||||||
|
case video::EVT_SKINNED_MESH:
|
||||||
|
return Vertices_SkinnedMesh.pointer();
|
||||||
default:
|
default:
|
||||||
return Vertices_Standard.pointer();
|
return Vertices_Standard.pointer();
|
||||||
}
|
}
|
||||||
@ -92,6 +98,8 @@ struct SSkinMeshBuffer : public IMeshBuffer
|
|||||||
return Vertices_2TCoords.size();
|
return Vertices_2TCoords.size();
|
||||||
case video::EVT_TANGENTS:
|
case video::EVT_TANGENTS:
|
||||||
return Vertices_Tangents.size();
|
return Vertices_Tangents.size();
|
||||||
|
case video::EVT_SKINNED_MESH:
|
||||||
|
return Vertices_SkinnedMesh.size();
|
||||||
default:
|
default:
|
||||||
return Vertices_Standard.size();
|
return Vertices_Standard.size();
|
||||||
}
|
}
|
||||||
@ -180,6 +188,20 @@ struct SSkinMeshBuffer : public IMeshBuffer
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case video::EVT_SKINNED_MESH:
|
||||||
|
{
|
||||||
|
if (Vertices_SkinnedMesh.empty())
|
||||||
|
BoundingBox.reset(0,0,0);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BoundingBox.reset(Vertices_SkinnedMesh[0].Pos);
|
||||||
|
for (u32 i=1; i<Vertices_SkinnedMesh.size(); ++i)
|
||||||
|
BoundingBox.addInternalPoint(Vertices_SkinnedMesh[i].Pos);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,6 +230,23 @@ struct SSkinMeshBuffer : public IMeshBuffer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void convertForSkinning()
|
||||||
|
{
|
||||||
|
if (VertexType==video::EVT_STANDARD)
|
||||||
|
{
|
||||||
|
for(u32 n=0;n<Vertices_Standard.size();++n)
|
||||||
|
{
|
||||||
|
video::S3DVertexSkinnedMesh Vertex = {};
|
||||||
|
Vertex.Color=Vertices_Standard[n].Color;
|
||||||
|
Vertex.Pos=Vertices_Standard[n].Pos;
|
||||||
|
Vertex.Normal=Vertices_Standard[n].Normal;
|
||||||
|
Vertex.TCoords=Vertices_Standard[n].TCoords;
|
||||||
|
Vertices_SkinnedMesh.push_back(Vertex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//! Convert to tangents vertex type
|
//! Convert to tangents vertex type
|
||||||
virtual void convertToTangents()
|
virtual void convertToTangents()
|
||||||
{
|
{
|
||||||
@ -250,6 +289,8 @@ struct SSkinMeshBuffer : public IMeshBuffer
|
|||||||
return Vertices_2TCoords[i].Pos;
|
return Vertices_2TCoords[i].Pos;
|
||||||
case video::EVT_TANGENTS:
|
case video::EVT_TANGENTS:
|
||||||
return Vertices_Tangents[i].Pos;
|
return Vertices_Tangents[i].Pos;
|
||||||
|
case video::EVT_SKINNED_MESH:
|
||||||
|
return Vertices_SkinnedMesh[i].Pos;
|
||||||
default:
|
default:
|
||||||
return Vertices_Standard[i].Pos;
|
return Vertices_Standard[i].Pos;
|
||||||
}
|
}
|
||||||
@ -264,6 +305,8 @@ struct SSkinMeshBuffer : public IMeshBuffer
|
|||||||
return Vertices_2TCoords[i].Pos;
|
return Vertices_2TCoords[i].Pos;
|
||||||
case video::EVT_TANGENTS:
|
case video::EVT_TANGENTS:
|
||||||
return Vertices_Tangents[i].Pos;
|
return Vertices_Tangents[i].Pos;
|
||||||
|
case video::EVT_SKINNED_MESH:
|
||||||
|
return Vertices_SkinnedMesh[i].Pos;
|
||||||
default:
|
default:
|
||||||
return Vertices_Standard[i].Pos;
|
return Vertices_Standard[i].Pos;
|
||||||
}
|
}
|
||||||
@ -278,6 +321,8 @@ struct SSkinMeshBuffer : public IMeshBuffer
|
|||||||
return Vertices_2TCoords[i].Normal;
|
return Vertices_2TCoords[i].Normal;
|
||||||
case video::EVT_TANGENTS:
|
case video::EVT_TANGENTS:
|
||||||
return Vertices_Tangents[i].Normal;
|
return Vertices_Tangents[i].Normal;
|
||||||
|
case video::EVT_SKINNED_MESH:
|
||||||
|
return Vertices_SkinnedMesh[i].Normal;
|
||||||
default:
|
default:
|
||||||
return Vertices_Standard[i].Normal;
|
return Vertices_Standard[i].Normal;
|
||||||
}
|
}
|
||||||
@ -292,6 +337,8 @@ struct SSkinMeshBuffer : public IMeshBuffer
|
|||||||
return Vertices_2TCoords[i].Normal;
|
return Vertices_2TCoords[i].Normal;
|
||||||
case video::EVT_TANGENTS:
|
case video::EVT_TANGENTS:
|
||||||
return Vertices_Tangents[i].Normal;
|
return Vertices_Tangents[i].Normal;
|
||||||
|
case video::EVT_SKINNED_MESH:
|
||||||
|
return Vertices_SkinnedMesh[i].Normal;
|
||||||
default:
|
default:
|
||||||
return Vertices_Standard[i].Normal;
|
return Vertices_Standard[i].Normal;
|
||||||
}
|
}
|
||||||
@ -306,6 +353,8 @@ struct SSkinMeshBuffer : public IMeshBuffer
|
|||||||
return Vertices_2TCoords[i].TCoords;
|
return Vertices_2TCoords[i].TCoords;
|
||||||
case video::EVT_TANGENTS:
|
case video::EVT_TANGENTS:
|
||||||
return Vertices_Tangents[i].TCoords;
|
return Vertices_Tangents[i].TCoords;
|
||||||
|
case video::EVT_SKINNED_MESH:
|
||||||
|
return Vertices_SkinnedMesh[i].TCoords;
|
||||||
default:
|
default:
|
||||||
return Vertices_Standard[i].TCoords;
|
return Vertices_Standard[i].TCoords;
|
||||||
}
|
}
|
||||||
@ -320,6 +369,8 @@ struct SSkinMeshBuffer : public IMeshBuffer
|
|||||||
return Vertices_2TCoords[i].TCoords;
|
return Vertices_2TCoords[i].TCoords;
|
||||||
case video::EVT_TANGENTS:
|
case video::EVT_TANGENTS:
|
||||||
return Vertices_Tangents[i].TCoords;
|
return Vertices_Tangents[i].TCoords;
|
||||||
|
case video::EVT_SKINNED_MESH:
|
||||||
|
return Vertices_SkinnedMesh[i].TCoords;
|
||||||
default:
|
default:
|
||||||
return Vertices_Standard[i].TCoords;
|
return Vertices_Standard[i].TCoords;
|
||||||
}
|
}
|
||||||
@ -381,6 +432,7 @@ struct SSkinMeshBuffer : public IMeshBuffer
|
|||||||
|
|
||||||
core::array<video::S3DVertexTangents> Vertices_Tangents;
|
core::array<video::S3DVertexTangents> Vertices_Tangents;
|
||||||
core::array<video::S3DVertex2TCoords> Vertices_2TCoords;
|
core::array<video::S3DVertex2TCoords> Vertices_2TCoords;
|
||||||
|
core::array<video::S3DVertexSkinnedMesh> Vertices_SkinnedMesh;
|
||||||
core::array<video::S3DVertex> Vertices_Standard;
|
core::array<video::S3DVertex> Vertices_Standard;
|
||||||
core::array<u16> Indices;
|
core::array<u16> Indices;
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ namespace scene
|
|||||||
|
|
||||||
//! constructor
|
//! constructor
|
||||||
CSkinnedMesh::CSkinnedMesh()
|
CSkinnedMesh::CSkinnedMesh()
|
||||||
: SkinningBuffers(0), AnimationFrames(0.f), FramesPerSecond(25.f),
|
: m_joint_total_size(0), SkinningBuffers(0), AnimationFrames(0.f), FramesPerSecond(25.f),
|
||||||
LastAnimatedFrame(-1), SkinnedLastFrame(false),
|
LastAnimatedFrame(-1), SkinnedLastFrame(false),
|
||||||
InterpolationMode(EIM_LINEAR),
|
InterpolationMode(EIM_LINEAR),
|
||||||
HasAnimation(false), PreparedForSkinning(false),
|
HasAnimation(false), PreparedForSkinning(false),
|
||||||
@ -27,7 +27,6 @@ CSkinnedMesh::CSkinnedMesh()
|
|||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
setDebugName("CSkinnedMesh");
|
setDebugName("CSkinnedMesh");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SkinningBuffers=&LocalBuffers;
|
SkinningBuffers=&LocalBuffers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,12 +73,19 @@ void CSkinnedMesh::setAnimationSpeed(f32 fps)
|
|||||||
//! returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail. Note, that some Meshes will ignore the detail level.
|
//! returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail. Note, that some Meshes will ignore the detail level.
|
||||||
IMesh* CSkinnedMesh::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop)
|
IMesh* CSkinnedMesh::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop)
|
||||||
{
|
{
|
||||||
|
const bool is_hw_skinning_before = HardwareSkinning;
|
||||||
|
if (is_hw_skinning_before)
|
||||||
|
HardwareSkinning = false;
|
||||||
//animate(frame,startFrameLoop, endFrameLoop);
|
//animate(frame,startFrameLoop, endFrameLoop);
|
||||||
if (frame==-1)
|
if (frame==-1)
|
||||||
return this;
|
return this;
|
||||||
|
|
||||||
animateMesh((f32)frame, 1.0f);
|
animateMesh((f32)frame, 1.0f);
|
||||||
skinMesh();
|
skinMesh();
|
||||||
|
|
||||||
|
if (is_hw_skinning_before)
|
||||||
|
HardwareSkinning = true;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -456,7 +462,13 @@ void CSkinnedMesh::skinMesh(f32 strength)
|
|||||||
//-----------------
|
//-----------------
|
||||||
|
|
||||||
SkinnedLastFrame=true;
|
SkinnedLastFrame=true;
|
||||||
if (!HardwareSkinning)
|
m_joint_matrixes.clear();
|
||||||
|
if (HardwareSkinning)
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < RootJoints.size(); i++)
|
||||||
|
skinJoint(RootJoints[i], 0, strength);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
//Software skin....
|
//Software skin....
|
||||||
u32 i;
|
u32 i;
|
||||||
@ -493,52 +505,58 @@ void CSkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint, f32 strength)
|
|||||||
//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)
|
||||||
core::vector3df thisVertexMove, thisNormalMove;
|
|
||||||
|
|
||||||
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];
|
m_joint_matrixes.push_back(jointVertexPull);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core::vector3df thisVertexMove, thisNormalMove;
|
||||||
|
|
||||||
// Pull this vertex...
|
core::array<scene::SSkinMeshBuffer*> &buffersUsed=*SkinningBuffers;
|
||||||
jointVertexPull.transformVect(thisVertexMove, weight.StaticPos);
|
|
||||||
|
|
||||||
if (AnimateNormals)
|
//Skin Vertices Positions and Normals...
|
||||||
jointVertexPull.rotateVect(thisNormalMove, weight.StaticNormal);
|
for (u32 i=0; i<joint->Weights.size(); ++i)
|
||||||
|
|
||||||
// Apply animation strength
|
|
||||||
if(strength != 1.f)
|
|
||||||
{
|
{
|
||||||
thisVertexMove = core::lerp(weight.StaticPos, thisVertexMove, strength);
|
SWeight& weight = joint->Weights[i];
|
||||||
if(AnimateNormals)
|
|
||||||
thisNormalMove = core::lerp(weight.StaticNormal, thisNormalMove, strength);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! (*(weight.Moved)) )
|
// Pull this vertex...
|
||||||
{
|
jointVertexPull.transformVect(thisVertexMove, weight.StaticPos);
|
||||||
*(weight.Moved) = true;
|
|
||||||
|
|
||||||
buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Pos = thisVertexMove * weight.strength;
|
|
||||||
|
|
||||||
if (AnimateNormals)
|
if (AnimateNormals)
|
||||||
buffersUsed[weight.buffer_id]->getVertex(weight.vertex_id)->Normal = thisNormalMove * weight.strength;
|
jointVertexPull.rotateVect(thisNormalMove, weight.StaticNormal);
|
||||||
|
|
||||||
//*(weight._Pos) = thisVertexMove * 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();
|
||||||
}
|
}
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1382,6 +1400,85 @@ void CSkinnedMesh::addJoints(core::array<IBoneSceneNode*> &jointChildSceneNodes,
|
|||||||
SkinnedLastFrame=false;
|
SkinnedLastFrame=false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
float remaining_weight = 1.0f;
|
||||||
|
for (u32 j = 0; j < 4; j++)
|
||||||
|
{
|
||||||
|
JointInfluence influence;
|
||||||
|
if (reported_weight.size() > j)
|
||||||
|
influence = reported_weight[j];
|
||||||
|
else
|
||||||
|
{
|
||||||
|
influence.joint_idx = -1;
|
||||||
|
influence.weight = remaining_weight;
|
||||||
|
}
|
||||||
|
remaining_weight -= influence.weight;
|
||||||
|
this_influence.push_back(influence);
|
||||||
|
}
|
||||||
|
LocalBuffers[b]->Vertices_SkinnedMesh[i].m_joint_idx1 = this_influence[0].joint_idx;
|
||||||
|
LocalBuffers[b]->Vertices_SkinnedMesh[i].m_joint_idx2 = this_influence[1].joint_idx;
|
||||||
|
LocalBuffers[b]->Vertices_SkinnedMesh[i].m_joint_idx3 = this_influence[2].joint_idx;
|
||||||
|
LocalBuffers[b]->Vertices_SkinnedMesh[i].m_joint_idx4 = this_influence[3].joint_idx;
|
||||||
|
LocalBuffers[b]->Vertices_SkinnedMesh[i].m_weight1 = this_influence[0].weight;
|
||||||
|
LocalBuffers[b]->Vertices_SkinnedMesh[i].m_weight2 = this_influence[1].weight;
|
||||||
|
LocalBuffers[b]->Vertices_SkinnedMesh[i].m_weight3 = this_influence[2].weight;
|
||||||
|
LocalBuffers[b]->Vertices_SkinnedMesh[i].m_weight4 = this_influence[3].weight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SkinnedLastFrame = false;
|
||||||
|
skinMesh();
|
||||||
|
m_joint_total_size = m_joint_matrixes.size() * sizeof(core::matrix4);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = 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()
|
void CSkinnedMesh::convertMeshToTangents()
|
||||||
{
|
{
|
||||||
|
@ -14,6 +14,20 @@
|
|||||||
#include "matrix4.h"
|
#include "matrix4.h"
|
||||||
#include "quaternion.h"
|
#include "quaternion.h"
|
||||||
|
|
||||||
|
class JointInfluence
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int joint_idx;
|
||||||
|
float weight;
|
||||||
|
bool operator < (const JointInfluence& other) const
|
||||||
|
{
|
||||||
|
return weight < other.weight;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef irr::core::array<irr::core::array
|
||||||
|
<irr::core::array<JointInfluence> > > WeightInfluence;
|
||||||
|
|
||||||
namespace irr
|
namespace irr
|
||||||
{
|
{
|
||||||
namespace scene
|
namespace scene
|
||||||
@ -25,7 +39,6 @@ namespace scene
|
|||||||
class CSkinnedMesh: public ISkinnedMesh
|
class CSkinnedMesh: public ISkinnedMesh
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//! constructor
|
//! constructor
|
||||||
CSkinnedMesh();
|
CSkinnedMesh();
|
||||||
|
|
||||||
@ -159,6 +172,19 @@ namespace scene
|
|||||||
void addJoints(core::array<IBoneSceneNode*> &jointChildSceneNodes,
|
void addJoints(core::array<IBoneSceneNode*> &jointChildSceneNodes,
|
||||||
IAnimatedMeshSceneNode* node,
|
IAnimatedMeshSceneNode* node,
|
||||||
ISceneManager* smgr);
|
ISceneManager* smgr);
|
||||||
|
|
||||||
|
void convertForSkinning();
|
||||||
|
|
||||||
|
void computeWeightInfluence(SJoint *joint, size_t &index, WeightInfluence& wi);
|
||||||
|
|
||||||
|
const void* getJointPointer() const { return m_joint_matrixes.const_pointer(); }
|
||||||
|
|
||||||
|
u32 getTotalJointSize() const
|
||||||
|
{
|
||||||
|
_IRR_DEBUG_BREAK_IF(m_joint_total_size == 0);
|
||||||
|
return m_joint_total_size;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void checkForAnimation();
|
void checkForAnimation();
|
||||||
|
|
||||||
@ -204,7 +230,9 @@ private:
|
|||||||
bool HasAnimation;
|
bool HasAnimation;
|
||||||
bool PreparedForSkinning;
|
bool PreparedForSkinning;
|
||||||
bool AnimateNormals;
|
bool AnimateNormals;
|
||||||
bool HardwareSkinning;
|
bool HardwareSkinning;
|
||||||
|
core::array<core::matrix4> m_joint_matrixes;
|
||||||
|
u32 m_joint_total_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace scene
|
} // end namespace scene
|
||||||
|
@ -27,6 +27,7 @@ void InstanceFiller<InstanceDataSingleTex>::add(GLMesh* mesh,
|
|||||||
{
|
{
|
||||||
fillOriginOrientationScale<InstanceDataSingleTex>(STK::tuple_get<0>(is), instance);
|
fillOriginOrientationScale<InstanceDataSingleTex>(STK::tuple_get<0>(is), instance);
|
||||||
instance.Texture = mesh->TextureHandles[0];
|
instance.Texture = mesh->TextureHandles[0];
|
||||||
|
instance.skinning_offset = STK::tuple_get<3>(is);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -60,6 +61,7 @@ void InstanceFiller<InstanceDataFourTex>::add(GLMesh* mesh,
|
|||||||
instance.SecondTexture = mesh->TextureHandles[1];
|
instance.SecondTexture = mesh->TextureHandles[1];
|
||||||
instance.ThirdTexture = mesh->TextureHandles[2];
|
instance.ThirdTexture = mesh->TextureHandles[2];
|
||||||
instance.FourthTexture = mesh->TextureHandles[3];
|
instance.FourthTexture = mesh->TextureHandles[3];
|
||||||
|
instance.skinning_offset = STK::tuple_get<3>(is);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -172,7 +174,8 @@ void SolidCommandBuffer::fill(SolidPassMeshMap *mesh_map)
|
|||||||
|
|
||||||
std::vector<int> four_tex_material_list =
|
std::vector<int> four_tex_material_list =
|
||||||
createVector<int>(Material::SHADERTYPE_DETAIL_MAP,
|
createVector<int>(Material::SHADERTYPE_DETAIL_MAP,
|
||||||
Material::SHADERTYPE_NORMAL_MAP);
|
Material::SHADERTYPE_NORMAL_MAP,
|
||||||
|
Material::SHADERTYPE_SOLID_SKINNED_MESH);
|
||||||
|
|
||||||
fillInstanceData<InstanceDataFourTex, SolidPassMeshMap>
|
fillInstanceData<InstanceDataFourTex, SolidPassMeshMap>
|
||||||
(mesh_map, four_tex_material_list, InstanceTypeFourTex);
|
(mesh_map, four_tex_material_list, InstanceTypeFourTex);
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
typedef STK::Tuple<scene::ISceneNode*, core::vector2df, core::vector2df> InstanceSettings;
|
typedef STK::Tuple<scene::ISceneNode*, core::vector2df, core::vector2df, uint32_t> InstanceSettings;
|
||||||
|
|
||||||
struct InstanceList
|
struct InstanceList
|
||||||
{
|
{
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "graphics/lod_node.hpp"
|
#include "graphics/lod_node.hpp"
|
||||||
#include "graphics/materials.hpp"
|
#include "graphics/materials.hpp"
|
||||||
#include "graphics/shadow_matrices.hpp"
|
#include "graphics/shadow_matrices.hpp"
|
||||||
|
#include "graphics/stk_animated_mesh.hpp"
|
||||||
#include "graphics/stk_billboard.hpp"
|
#include "graphics/stk_billboard.hpp"
|
||||||
#include "graphics/stk_mesh.hpp"
|
#include "graphics/stk_mesh.hpp"
|
||||||
#include "graphics/stk_mesh_scene_node.hpp"
|
#include "graphics/stk_mesh_scene_node.hpp"
|
||||||
@ -30,6 +31,8 @@
|
|||||||
#include "tracks/track.hpp"
|
#include "tracks/track.hpp"
|
||||||
#include "utils/profiler.hpp"
|
#include "utils/profiler.hpp"
|
||||||
|
|
||||||
|
#include <numeric>
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void DrawCalls::clearLists()
|
void DrawCalls::clearLists()
|
||||||
{
|
{
|
||||||
@ -175,6 +178,28 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t skinning_offset = 0;
|
||||||
|
STKAnimatedMesh* am = dynamic_cast<STKAnimatedMesh*>(Node);
|
||||||
|
if (am && am->useHardwareSkinning())
|
||||||
|
{
|
||||||
|
SkinningOffset::const_iterator it = m_skinning_offsets.find(am);
|
||||||
|
if (it != m_skinning_offsets.end())
|
||||||
|
{
|
||||||
|
skinning_offset = am->getSkinningOffset() / sizeof(core::matrix4);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const uint32_t cur_offset =
|
||||||
|
std::accumulate(m_skinning_offsets.begin(),
|
||||||
|
m_skinning_offsets.end(), 0, [] (const size_t previous,
|
||||||
|
const std::pair<STKAnimatedMesh*, uint32_t>& p)
|
||||||
|
{ return previous + p.second; });
|
||||||
|
am->setSkinningOffset(cur_offset);
|
||||||
|
m_skinning_offsets[am] = am->getTotalJointSize();
|
||||||
|
skinning_offset = cur_offset / sizeof(core::matrix4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool culled_for_cams[6] = { true, true, true, true, true, true };
|
bool culled_for_cams[6] = { true, true, true, true, true, true };
|
||||||
culled_for_cams[0] = isCulledPrecise(cam, Node,
|
culled_for_cams[0] = isCulledPrecise(cam, Node,
|
||||||
irr_driver->getBoundingBoxesViz());
|
irr_driver->getBoundingBoxesViz());
|
||||||
@ -255,7 +280,7 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node,
|
|||||||
{
|
{
|
||||||
m_glow_pass_mesh[mesh->mb].m_mesh = mesh;
|
m_glow_pass_mesh[mesh->mb].m_mesh = mesh;
|
||||||
m_glow_pass_mesh[mesh->mb].m_instance_settings
|
m_glow_pass_mesh[mesh->mb].m_instance_settings
|
||||||
.emplace_back(Node, core::vector2df(0.0f, 0.0f), core::vector2df(0.0f, 0.0f));
|
.emplace_back(Node, core::vector2df(0.0f, 0.0f), core::vector2df(0.0f, 0.0f), skinning_offset);
|
||||||
}
|
}
|
||||||
if (Mat == Material::SHADERTYPE_SPLATTING)
|
if (Mat == Material::SHADERTYPE_SPLATTING)
|
||||||
{
|
{
|
||||||
@ -267,15 +292,12 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Only take render info into account if the node is not static (animated)
|
std::pair<scene::IMeshBuffer*, RenderInfo*> mesh_render_info(mesh->mb, NULL);
|
||||||
// So they can have different animation
|
|
||||||
std::pair<scene::IMeshBuffer*, RenderInfo*> mesh_render_info(mesh->mb,
|
|
||||||
dynamic_cast<STKMeshSceneNode*>(Node) == NULL ? mesh->m_render_info : NULL);
|
|
||||||
m_solid_pass_mesh[Mat][mesh_render_info].m_mesh = mesh;
|
m_solid_pass_mesh[Mat][mesh_render_info].m_mesh = mesh;
|
||||||
m_solid_pass_mesh[Mat][mesh_render_info].m_instance_settings.emplace_back(Node, mesh->texture_trans,
|
m_solid_pass_mesh[Mat][mesh_render_info].m_instance_settings.emplace_back(Node, mesh->texture_trans,
|
||||||
(mesh->m_render_info && mesh->m_material ?
|
(mesh->m_render_info && mesh->m_material ?
|
||||||
core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) :
|
core::vector2df(mesh->m_render_info->getHue(), mesh->m_material->getColorizationFactor()) :
|
||||||
core::vector2df(0.0f, 0.0f)));
|
core::vector2df(0.0f, 0.0f)), skinning_offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -351,7 +373,7 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node,
|
|||||||
{
|
{
|
||||||
m_shadow_pass_mesh[cascade * Material::SHADERTYPE_COUNT + Mat][mesh->mb].m_mesh = mesh;
|
m_shadow_pass_mesh[cascade * Material::SHADERTYPE_COUNT + Mat][mesh->mb].m_mesh = mesh;
|
||||||
m_shadow_pass_mesh[cascade * Material::SHADERTYPE_COUNT + Mat][mesh->mb].m_instance_settings
|
m_shadow_pass_mesh[cascade * Material::SHADERTYPE_COUNT + Mat][mesh->mb].m_instance_settings
|
||||||
.emplace_back(Node, core::vector2df(0.0f, 0.0f), core::vector2df(0.0f, 0.0f));
|
.emplace_back(Node, core::vector2df(0.0f, 0.0f), core::vector2df(0.0f, 0.0f), skinning_offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -419,7 +441,7 @@ void DrawCalls::handleSTKCommon(scene::ISceneNode *Node,
|
|||||||
{
|
{
|
||||||
m_reflective_shadow_map_mesh[Mat][mesh->mb].m_mesh = mesh;
|
m_reflective_shadow_map_mesh[Mat][mesh->mb].m_mesh = mesh;
|
||||||
m_reflective_shadow_map_mesh[Mat][mesh->mb].m_instance_settings
|
m_reflective_shadow_map_mesh[Mat][mesh->mb].m_instance_settings
|
||||||
.emplace_back(Node, core::vector2df(0.0f, 0.0f), core::vector2df(0.0f, 0.0f));
|
.emplace_back(Node, core::vector2df(0.0f, 0.0f), core::vector2df(0.0f, 0.0f), skinning_offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -683,6 +705,7 @@ void DrawCalls::drawIndirectSolidFirstPass() const
|
|||||||
{
|
{
|
||||||
m_solid_cmd_buffer->bind();
|
m_solid_cmd_buffer->bind();
|
||||||
m_solid_cmd_buffer->drawIndirectFirstPass<DefaultMaterial>();
|
m_solid_cmd_buffer->drawIndirectFirstPass<DefaultMaterial>();
|
||||||
|
m_solid_cmd_buffer->drawIndirectFirstPass<SkinnedSolid>();
|
||||||
m_solid_cmd_buffer->drawIndirectFirstPass<AlphaRef>();
|
m_solid_cmd_buffer->drawIndirectFirstPass<AlphaRef>();
|
||||||
m_solid_cmd_buffer->drawIndirectFirstPass<UnlitMat>();
|
m_solid_cmd_buffer->drawIndirectFirstPass<UnlitMat>();
|
||||||
m_solid_cmd_buffer->drawIndirectFirstPass<SphereMap>();
|
m_solid_cmd_buffer->drawIndirectFirstPass<SphereMap>();
|
||||||
@ -718,6 +741,7 @@ void DrawCalls::drawIndirectSolidSecondPass(const std::vector<GLuint> &prefilled
|
|||||||
{
|
{
|
||||||
m_solid_cmd_buffer->bind();
|
m_solid_cmd_buffer->bind();
|
||||||
m_solid_cmd_buffer->drawIndirectSecondPass<DefaultMaterial>(prefilled_tex);
|
m_solid_cmd_buffer->drawIndirectSecondPass<DefaultMaterial>(prefilled_tex);
|
||||||
|
m_solid_cmd_buffer->drawIndirectSecondPass<SkinnedSolid>(prefilled_tex);
|
||||||
m_solid_cmd_buffer->drawIndirectSecondPass<AlphaRef>(prefilled_tex);
|
m_solid_cmd_buffer->drawIndirectSecondPass<AlphaRef>(prefilled_tex);
|
||||||
m_solid_cmd_buffer->drawIndirectSecondPass<UnlitMat>(prefilled_tex);
|
m_solid_cmd_buffer->drawIndirectSecondPass<UnlitMat>(prefilled_tex);
|
||||||
m_solid_cmd_buffer->drawIndirectSecondPass<SphereMap>(prefilled_tex);
|
m_solid_cmd_buffer->drawIndirectSecondPass<SphereMap>(prefilled_tex);
|
||||||
|
@ -24,8 +24,11 @@
|
|||||||
|
|
||||||
class ParticleSystemProxy;
|
class ParticleSystemProxy;
|
||||||
class ShadowMatrices;
|
class ShadowMatrices;
|
||||||
|
class STKAnimatedMesh;
|
||||||
class STKBillboard;
|
class STKBillboard;
|
||||||
|
|
||||||
|
typedef std::unordered_map<STKAnimatedMesh*, uint32_t> SkinningOffset;
|
||||||
|
|
||||||
class DrawCalls
|
class DrawCalls
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@ -36,6 +39,7 @@ private:
|
|||||||
std::vector<irr::scene::ISceneNode *> m_immediate_draw_list;
|
std::vector<irr::scene::ISceneNode *> m_immediate_draw_list;
|
||||||
std::vector<STKBillboard *> m_billboard_list;
|
std::vector<STKBillboard *> m_billboard_list;
|
||||||
std::vector<ParticleSystemProxy *> m_particles_list;
|
std::vector<ParticleSystemProxy *> m_particles_list;
|
||||||
|
SkinningOffset m_skinning_offsets;
|
||||||
|
|
||||||
std::vector<float> m_bounding_boxes;
|
std::vector<float> m_bounding_boxes;
|
||||||
|
|
||||||
@ -105,6 +109,7 @@ public:
|
|||||||
void drawIndirectGlow() const;
|
void drawIndirectGlow() const;
|
||||||
void multidrawGlow() const;
|
void multidrawGlow() const;
|
||||||
void renderBoundingBoxes();
|
void renderBoundingBoxes();
|
||||||
|
void resetSkinningOffsets() { m_skinning_offsets.clear(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //HEADER_DRAW_CALLS_HPP
|
#endif //HEADER_DRAW_CALLS_HPP
|
||||||
|
@ -140,6 +140,22 @@ public:
|
|||||||
glEnableVertexAttribArray(6);
|
glEnableVertexAttribArray(6);
|
||||||
glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)48);
|
glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)48);
|
||||||
break;
|
break;
|
||||||
|
case video::EVT_SKINNED_MESH:
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), 0);
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)12);
|
||||||
|
glEnableVertexAttribArray(2);
|
||||||
|
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitchFromType(tp), (GLvoid*)24);
|
||||||
|
glEnableVertexAttribArray(3);
|
||||||
|
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)28);
|
||||||
|
glEnableVertexAttribArray(3);
|
||||||
|
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)44);
|
||||||
|
glEnableVertexAttribArray(5);
|
||||||
|
glVertexAttribIPointer(5, 4, GL_INT, getVertexPitchFromType(tp), (GLvoid*)60);
|
||||||
|
glEnableVertexAttribArray(6);
|
||||||
|
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)76);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -48,6 +48,7 @@ public:
|
|||||||
enum ShaderType
|
enum ShaderType
|
||||||
{
|
{
|
||||||
SHADERTYPE_SOLID = 0,
|
SHADERTYPE_SOLID = 0,
|
||||||
|
SHADERTYPE_SOLID_SKINNED_MESH,
|
||||||
SHADERTYPE_ALPHA_TEST,
|
SHADERTYPE_ALPHA_TEST,
|
||||||
SHADERTYPE_ALPHA_BLEND,
|
SHADERTYPE_ALPHA_BLEND,
|
||||||
SHADERTYPE_ADDITIVE,
|
SHADERTYPE_ADDITIVE,
|
||||||
|
@ -24,6 +24,14 @@ const STK::Tuple<size_t, size_t, size_t> DefaultMaterial::SecondPassTextures
|
|||||||
const STK::Tuple<> DefaultMaterial::ShadowTextures;
|
const STK::Tuple<> DefaultMaterial::ShadowTextures;
|
||||||
const STK::Tuple<size_t> DefaultMaterial::RSMTextures = STK::Tuple<size_t>(0);
|
const STK::Tuple<size_t> DefaultMaterial::RSMTextures = STK::Tuple<size_t>(0);
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
const STK::Tuple<size_t> SkinnedSolid::FirstPassTextures
|
||||||
|
= STK::Tuple<size_t>(1);
|
||||||
|
const STK::Tuple<size_t, size_t, size_t> SkinnedSolid::SecondPassTextures
|
||||||
|
= STK::Tuple<size_t, size_t, size_t>(0, 1, 2);
|
||||||
|
const STK::Tuple<> SkinnedSolid::ShadowTextures;
|
||||||
|
const STK::Tuple<size_t> SkinnedSolid::RSMTextures = STK::Tuple<size_t>(0);
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
const STK::Tuple<size_t, size_t> AlphaRef::FirstPassTextures
|
const STK::Tuple<size_t, size_t> AlphaRef::FirstPassTextures
|
||||||
= STK::Tuple<size_t, size_t>(0, 1);
|
= STK::Tuple<size_t, size_t>(0, 1);
|
||||||
|
@ -616,8 +616,61 @@ public:
|
|||||||
} // InstancedDetailedObjectPass2Shader
|
} // InstancedDetailedObjectPass2Shader
|
||||||
}; // InstancedDetailedObjectPass2Shader
|
}; // InstancedDetailedObjectPass2Shader
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
class InstancedSkinnedMeshPass1Shader : public TextureShader<InstancedSkinnedMeshPass1Shader, 1>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InstancedSkinnedMeshPass1Shader()
|
||||||
|
{
|
||||||
|
loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert",
|
||||||
|
GL_FRAGMENT_SHADER, "instanced_object_pass1.frag");
|
||||||
|
|
||||||
|
assignUniforms();
|
||||||
|
assignSamplerNames(0, "glosstex", ST_TRILINEAR_ANISOTROPIC_FILTERED);
|
||||||
|
} // InstancedSkinnedMeshPass1Shader
|
||||||
|
}; // InstancedSkinnedMeshPass1Shader
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
class InstancedSkinnedMeshPass2Shader : public TextureShader<InstancedSkinnedMeshPass2Shader, 6>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InstancedSkinnedMeshPass2Shader()
|
||||||
|
{
|
||||||
|
loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_skinning.vert",
|
||||||
|
GL_FRAGMENT_SHADER, "instanced_object_pass2.frag");
|
||||||
|
assignUniforms();
|
||||||
|
assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED,
|
||||||
|
1, "SpecularMap", ST_NEAREST_FILTERED,
|
||||||
|
2, "SSAO", ST_BILINEAR_FILTERED,
|
||||||
|
3, "Albedo", ST_TRILINEAR_ANISOTROPIC_FILTERED,
|
||||||
|
4, "SpecMap", ST_TRILINEAR_ANISOTROPIC_FILTERED,
|
||||||
|
5, "colorization_mask", ST_TRILINEAR_ANISOTROPIC_FILTERED);
|
||||||
|
} // InstancedSkinnedMeshPass2Shader
|
||||||
|
}; // InstancedSkinnedMeshPass2Shader
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
struct SkinnedSolid
|
||||||
|
{
|
||||||
|
typedef InstancedSkinnedMeshPass1Shader InstancedFirstPassShader;
|
||||||
|
typedef InstancedSkinnedMeshPass2Shader InstancedSecondPassShader;
|
||||||
|
//typedef InstancedShadowShader InstancedShadowPassShader;
|
||||||
|
//typedef CInstancedRSMShader InstancedRSMShader;
|
||||||
|
//typedef Shaders::ObjectPass1Shader FirstPassShader;
|
||||||
|
//typedef Shaders::ObjectPass2Shader SecondPassShader;
|
||||||
|
//typedef ShadowShader ShadowPassShader;
|
||||||
|
//typedef CRSMShader RSMShader;
|
||||||
|
typedef ListSkinnedSolid List;
|
||||||
|
static const enum video::E_VERTEX_TYPE VertexType = video::EVT_SKINNED_MESH;
|
||||||
|
static const enum Material::ShaderType MaterialType
|
||||||
|
= Material::SHADERTYPE_SOLID_SKINNED_MESH;
|
||||||
|
static const enum InstanceType Instance = InstanceTypeFourTex;
|
||||||
|
static const STK::Tuple<size_t> FirstPassTextures;
|
||||||
|
static const STK::Tuple<size_t, size_t, size_t> SecondPassTextures;
|
||||||
|
static const STK::Tuple<> ShadowTextures;
|
||||||
|
static const STK::Tuple<size_t> RSMTextures;
|
||||||
|
}; // struct DefaultMaterial
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
struct DefaultMaterial
|
struct DefaultMaterial
|
||||||
{
|
{
|
||||||
typedef InstancedObjectPass1Shader InstancedFirstPassShader;
|
typedef InstancedObjectPass1Shader InstancedFirstPassShader;
|
||||||
|
@ -476,7 +476,7 @@ scene::IMesh* MeshTools::createMeshWithTangents(scene::IMesh* mesh,
|
|||||||
|
|
||||||
void MeshTools::createSkinnedMeshWithTangents(scene::ISkinnedMesh* mesh,
|
void MeshTools::createSkinnedMeshWithTangents(scene::ISkinnedMesh* mesh,
|
||||||
bool(*predicate)(scene::IMeshBuffer*))
|
bool(*predicate)(scene::IMeshBuffer*))
|
||||||
{
|
{return;
|
||||||
core::array<scene::SSkinMeshBuffer*>& all_mb = mesh->getMeshBuffers();
|
core::array<scene::SSkinMeshBuffer*>& all_mb = mesh->getMeshBuffers();
|
||||||
const int all_mb_size = all_mb.size();
|
const int all_mb_size = all_mb.size();
|
||||||
for (int i = 0; i < all_mb_size; i++)
|
for (int i = 0; i < all_mb_size; i++)
|
||||||
|
@ -150,6 +150,7 @@ private:
|
|||||||
{
|
{
|
||||||
bindPoint("MatrixData", 0);
|
bindPoint("MatrixData", 0);
|
||||||
bindPoint("LightingData", 1);
|
bindPoint("LightingData", 1);
|
||||||
|
bindPoint("SkinningData", 2);
|
||||||
} // assignUniformsImpl
|
} // assignUniformsImpl
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -270,6 +270,7 @@ void ShaderBasedRenderer::renderScene(scene::ICameraSceneNode * const camnode,
|
|||||||
{
|
{
|
||||||
glBindBufferBase(GL_UNIFORM_BUFFER, 0, SharedGPUObjects::getViewProjectionMatricesUBO());
|
glBindBufferBase(GL_UNIFORM_BUFFER, 0, SharedGPUObjects::getViewProjectionMatricesUBO());
|
||||||
glBindBufferBase(GL_UNIFORM_BUFFER, 1, SharedGPUObjects::getLightingDataUBO());
|
glBindBufferBase(GL_UNIFORM_BUFFER, 1, SharedGPUObjects::getLightingDataUBO());
|
||||||
|
glBindBufferBase(GL_UNIFORM_BUFFER, 2, SharedGPUObjects::getSkinningUBO());
|
||||||
}
|
}
|
||||||
irr_driver->getSceneManager()->setActiveCamera(camnode);
|
irr_driver->getSceneManager()->setActiveCamera(camnode);
|
||||||
|
|
||||||
@ -697,6 +698,7 @@ void ShaderBasedRenderer::onUnloadWorld()
|
|||||||
delete m_rtts;
|
delete m_rtts;
|
||||||
m_rtts = NULL;
|
m_rtts = NULL;
|
||||||
removeSkyBox();
|
removeSkyBox();
|
||||||
|
m_draw_calls.resetSkinningOffsets();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -29,6 +29,7 @@ GLuint SharedGPUObjects::m_full_screen_quad_vao;
|
|||||||
GLuint SharedGPUObjects::m_ui_vao;
|
GLuint SharedGPUObjects::m_ui_vao;
|
||||||
GLuint SharedGPUObjects::m_quad_buffer;
|
GLuint SharedGPUObjects::m_quad_buffer;
|
||||||
GLuint SharedGPUObjects::m_quad_vbo;
|
GLuint SharedGPUObjects::m_quad_vbo;
|
||||||
|
GLuint SharedGPUObjects::m_skinning_ubo;
|
||||||
bool SharedGPUObjects::m_has_been_initialised = false;
|
bool SharedGPUObjects::m_has_been_initialised = false;
|
||||||
|
|
||||||
/** Initialises m_full_screen_quad_vbo.
|
/** Initialises m_full_screen_quad_vbo.
|
||||||
@ -166,6 +167,17 @@ void SharedGPUObjects::initLightingDataUBO()
|
|||||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||||
} // initLightingDataUBO
|
} // initLightingDataUBO
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
void SharedGPUObjects::initSkinningUBO()
|
||||||
|
{
|
||||||
|
assert(CVS->isARBUniformBufferObjectUsable());
|
||||||
|
glGenBuffers(1, &m_skinning_ubo);
|
||||||
|
glBindBuffer(GL_UNIFORM_BUFFER, m_skinning_ubo);
|
||||||
|
glBufferData(GL_UNIFORM_BUFFER, 1000 * 16 * sizeof(float), 0,
|
||||||
|
GL_STREAM_DRAW);
|
||||||
|
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||||
|
} // initSkinningUBO
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void SharedGPUObjects::initParticleQuadVBO()
|
void SharedGPUObjects::initParticleQuadVBO()
|
||||||
{
|
{
|
||||||
@ -198,7 +210,8 @@ void SharedGPUObjects::init()
|
|||||||
if(CVS->isARBUniformBufferObjectUsable())
|
if(CVS->isARBUniformBufferObjectUsable())
|
||||||
{
|
{
|
||||||
initShadowVPMUBO();
|
initShadowVPMUBO();
|
||||||
initLightingDataUBO();
|
initLightingDataUBO();
|
||||||
|
initSkinningUBO();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_has_been_initialised = true;
|
m_has_been_initialised = true;
|
||||||
|
@ -37,6 +37,7 @@ private:
|
|||||||
static GLuint m_ui_vao;
|
static GLuint m_ui_vao;
|
||||||
static GLuint m_quad_buffer;
|
static GLuint m_quad_buffer;
|
||||||
static GLuint m_quad_vbo;
|
static GLuint m_quad_vbo;
|
||||||
|
static GLuint m_skinning_ubo;
|
||||||
|
|
||||||
static void initQuadVBO();
|
static void initQuadVBO();
|
||||||
static void initQuadBuffer();
|
static void initQuadBuffer();
|
||||||
@ -46,6 +47,7 @@ private:
|
|||||||
static void initShadowVPMUBO();
|
static void initShadowVPMUBO();
|
||||||
static void initLightingDataUBO();
|
static void initLightingDataUBO();
|
||||||
static void initParticleQuadVBO();
|
static void initParticleQuadVBO();
|
||||||
|
static void initSkinningUBO();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void init();
|
static void init();
|
||||||
@ -116,6 +118,12 @@ public:
|
|||||||
assert(m_has_been_initialised);
|
assert(m_has_been_initialised);
|
||||||
return m_quad_vbo;
|
return m_quad_vbo;
|
||||||
} // getQuadVBO
|
} // getQuadVBO
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
static GLuint getSkinningUBO()
|
||||||
|
{
|
||||||
|
assert(m_has_been_initialised);
|
||||||
|
return m_skinning_ubo;
|
||||||
|
} // getSkinningUBO
|
||||||
}; // class SharedGPUObjecctS
|
}; // class SharedGPUObjecctS
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,12 +20,13 @@
|
|||||||
#include "graphics/central_settings.hpp"
|
#include "graphics/central_settings.hpp"
|
||||||
#include "graphics/material_manager.hpp"
|
#include "graphics/material_manager.hpp"
|
||||||
#include "graphics/render_info.hpp"
|
#include "graphics/render_info.hpp"
|
||||||
|
#include "graphics/shared_gpu_objects.hpp"
|
||||||
#include "graphics/stk_mesh.hpp"
|
#include "graphics/stk_mesh.hpp"
|
||||||
#include "graphics/vao_manager.hpp"
|
#include "graphics/vao_manager.hpp"
|
||||||
|
|
||||||
#include <IMaterialRenderer.h>
|
#include <IMaterialRenderer.h>
|
||||||
#include <ISceneManager.h>
|
#include <ISceneManager.h>
|
||||||
#include <ISkinnedMesh.h>
|
#include "../../lib/irrlicht/source/Irrlicht/CSkinnedMesh.h"
|
||||||
|
|
||||||
using namespace irr;
|
using namespace irr;
|
||||||
|
|
||||||
@ -34,7 +35,7 @@ irr::scene::ISceneManager* mgr, s32 id, const std::string& debug_name,
|
|||||||
const core::vector3df& position,
|
const core::vector3df& position,
|
||||||
const core::vector3df& rotation,
|
const core::vector3df& rotation,
|
||||||
const core::vector3df& scale, RenderInfo* render_info, bool all_parts_colorized) :
|
const core::vector3df& scale, RenderInfo* render_info, bool all_parts_colorized) :
|
||||||
CAnimatedMeshSceneNode(mesh, parent, mgr, id, position, rotation, scale)
|
CAnimatedMeshSceneNode(mesh, parent, mgr, id, position, rotation, scale), m_skinned_mesh(NULL)
|
||||||
{
|
{
|
||||||
isGLInitialized = false;
|
isGLInitialized = false;
|
||||||
isMaterialInitialized = false;
|
isMaterialInitialized = false;
|
||||||
@ -43,6 +44,10 @@ const core::vector3df& scale, RenderInfo* render_info, bool all_parts_colorized)
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
m_debug_name = debug_name;
|
m_debug_name = debug_name;
|
||||||
#endif
|
#endif
|
||||||
|
m_skinning_offset = -1;
|
||||||
|
m_skinned_mesh = dynamic_cast<scene::CSkinnedMesh*>(Mesh);
|
||||||
|
if (m_skinned_mesh)
|
||||||
|
m_skinned_mesh->convertForSkinning();
|
||||||
}
|
}
|
||||||
|
|
||||||
STKAnimatedMesh::~STKAnimatedMesh()
|
STKAnimatedMesh::~STKAnimatedMesh()
|
||||||
@ -108,6 +113,16 @@ void STKAnimatedMesh::updateNoGL()
|
|||||||
for (u32 i = 0; i < mb_count; ++i)
|
for (u32 i = 0; i < mb_count; ++i)
|
||||||
{
|
{
|
||||||
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
|
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
|
||||||
|
if (!mb)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
scene::SSkinMeshBuffer* ssmb = NULL;
|
||||||
|
if (m_skinned_mesh)
|
||||||
|
{
|
||||||
|
ssmb = dynamic_cast<scene::SSkinMeshBuffer*>(mb);
|
||||||
|
ssmb->VertexType = video::EVT_SKINNED_MESH;
|
||||||
|
}
|
||||||
|
|
||||||
bool affected = false;
|
bool affected = false;
|
||||||
RenderInfo* cur_ri = m_mesh_render_info;
|
RenderInfo* cur_ri = m_mesh_render_info;
|
||||||
if (!m_all_parts_colorized && mb && cur_ri)
|
if (!m_all_parts_colorized && mb && cur_ri)
|
||||||
@ -142,6 +157,8 @@ void STKAnimatedMesh::updateNoGL()
|
|||||||
GLmeshes.push_back(allocateMeshBuffer(mb, m_debug_name,
|
GLmeshes.push_back(allocateMeshBuffer(mb, m_debug_name,
|
||||||
affected || m_all_parts_colorized || (cur_ri
|
affected || m_all_parts_colorized || (cur_ri
|
||||||
&& cur_ri->isTransparent()) ? cur_ri : default_ri));
|
&& cur_ri->isTransparent()) ? cur_ri : default_ri));
|
||||||
|
|
||||||
|
if (m_skinned_mesh) ssmb->VertexType = video::EVT_STANDARD;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u32 i = 0; i < m->getMeshBufferCount(); ++i)
|
for (u32 i = 0; i < m->getMeshBufferCount(); ++i)
|
||||||
@ -162,7 +179,7 @@ void STKAnimatedMesh::updateNoGL()
|
|||||||
GLMesh &mesh = GLmeshes[i];
|
GLMesh &mesh = GLmeshes[i];
|
||||||
Material* material = material_manager->getMaterialFor(mb->getMaterial().getTexture(0), mb);
|
Material* material = material_manager->getMaterialFor(mb->getMaterial().getTexture(0), mb);
|
||||||
|
|
||||||
if (rnd->isTransparent())
|
/*if (rnd->isTransparent())
|
||||||
{
|
{
|
||||||
TransparentMaterial TranspMat = getTransparentMaterialFromType(type, MaterialTypeParam, material);
|
TransparentMaterial TranspMat = getTransparentMaterialFromType(type, MaterialTypeParam, material);
|
||||||
TransparentMesh[TranspMat].push_back(&mesh);
|
TransparentMesh[TranspMat].push_back(&mesh);
|
||||||
@ -174,10 +191,10 @@ void STKAnimatedMesh::updateNoGL()
|
|||||||
else
|
else
|
||||||
TransparentMesh[TM_TRANSLUCENT_STD].push_back(&mesh);
|
TransparentMesh[TM_TRANSLUCENT_STD].push_back(&mesh);
|
||||||
}
|
}
|
||||||
else
|
else*/
|
||||||
{
|
{
|
||||||
Material::ShaderType MatType = getMeshMaterialFromType(type, mb->getVertexType(), material, NULL);
|
Material::ShaderType MatType = getMeshMaterialFromType(type, mb->getVertexType(), material, NULL);
|
||||||
MeshSolidMaterial[MatType].push_back(&mesh);
|
MeshSolidMaterial[m_skinned_mesh ? Material::SHADERTYPE_SOLID_SKINNED_MESH : MatType].push_back(&mesh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
isMaterialInitialized = true;
|
isMaterialInitialized = true;
|
||||||
@ -213,6 +230,13 @@ void STKAnimatedMesh::updateGL()
|
|||||||
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
|
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
|
||||||
if (!mb)
|
if (!mb)
|
||||||
continue;
|
continue;
|
||||||
|
scene::SSkinMeshBuffer* ssmb = NULL;
|
||||||
|
if (m_skinned_mesh)
|
||||||
|
{
|
||||||
|
ssmb = dynamic_cast<scene::SSkinMeshBuffer*>(mb);
|
||||||
|
ssmb->VertexType = video::EVT_SKINNED_MESH;
|
||||||
|
}
|
||||||
|
|
||||||
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||||
video::E_MATERIAL_TYPE type = mb->getMaterial().MaterialType;
|
video::E_MATERIAL_TYPE type = mb->getMaterial().MaterialType;
|
||||||
video::IMaterialRenderer* rnd = driver->getMaterialRenderer(type);
|
video::IMaterialRenderer* rnd = driver->getMaterialRenderer(type);
|
||||||
@ -233,7 +257,7 @@ void STKAnimatedMesh::updateGL()
|
|||||||
|
|
||||||
if (CVS->isARBBaseInstanceUsable())
|
if (CVS->isARBBaseInstanceUsable())
|
||||||
{
|
{
|
||||||
std::pair<unsigned, unsigned> p = VAOManager::getInstance()->getBase(mb, GLmeshes[i].m_render_info);
|
std::pair<unsigned, unsigned> p = VAOManager::getInstance()->getBase(mb,NULL /*GLmeshes[i].m_render_info*/);
|
||||||
mesh.vaoBaseVertex = p.first;
|
mesh.vaoBaseVertex = p.first;
|
||||||
mesh.vaoOffset = p.second;
|
mesh.vaoOffset = p.second;
|
||||||
}
|
}
|
||||||
@ -243,10 +267,20 @@ void STKAnimatedMesh::updateGL()
|
|||||||
mesh.vao = createVAO(mesh.vertex_buffer, mesh.index_buffer, mb->getVertexType());
|
mesh.vao = createVAO(mesh.vertex_buffer, mesh.index_buffer, mb->getVertexType());
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
}
|
}
|
||||||
|
if (m_skinned_mesh) ssmb->VertexType = video::EVT_STANDARD;
|
||||||
}
|
}
|
||||||
isGLInitialized = true;
|
isGLInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_skinned_mesh)
|
||||||
|
{
|
||||||
|
assert(m_skinning_offset != -1);
|
||||||
|
glBindBuffer(GL_UNIFORM_BUFFER, SharedGPUObjects::getSkinningUBO());
|
||||||
|
glBufferSubData(GL_UNIFORM_BUFFER, m_skinning_offset,
|
||||||
|
m_skinned_mesh->getTotalJointSize(), m_skinned_mesh->getJointPointer());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (u32 i = 0; i<m->getMeshBufferCount(); ++i)
|
for (u32 i = 0; i<m->getMeshBufferCount(); ++i)
|
||||||
{
|
{
|
||||||
scene::IMeshBuffer* mb = m->getMeshBuffer(i);
|
scene::IMeshBuffer* mb = m->getMeshBuffer(i);
|
||||||
@ -289,3 +323,8 @@ void STKAnimatedMesh::render()
|
|||||||
updateNoGL();
|
updateNoGL();
|
||||||
updateGL();
|
updateGL();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int STKAnimatedMesh::getTotalJointSize() const
|
||||||
|
{
|
||||||
|
return m_skinned_mesh->getTotalJointSize();
|
||||||
|
}
|
||||||
|
@ -26,6 +26,10 @@
|
|||||||
#include <irrTypes.h>
|
#include <irrTypes.h>
|
||||||
|
|
||||||
class RenderInfo;
|
class RenderInfo;
|
||||||
|
namespace irr
|
||||||
|
{
|
||||||
|
namespace scene { class CSkinnedMesh; }
|
||||||
|
}
|
||||||
|
|
||||||
class STKAnimatedMesh : public irr::scene::CAnimatedMeshSceneNode, public STKMeshCommon
|
class STKAnimatedMesh : public irr::scene::CAnimatedMeshSceneNode, public STKMeshCommon
|
||||||
{
|
{
|
||||||
@ -50,9 +54,15 @@ public:
|
|||||||
virtual void render();
|
virtual void render();
|
||||||
virtual void setMesh(irr::scene::IAnimatedMesh* mesh);
|
virtual void setMesh(irr::scene::IAnimatedMesh* mesh);
|
||||||
virtual bool glow() const { return false; }
|
virtual bool glow() const { return false; }
|
||||||
|
int getTotalJointSize() const;
|
||||||
|
int getSkinningOffset() const { return m_skinning_offset; }
|
||||||
|
void setSkinningOffset(int offset) { m_skinning_offset = offset; }
|
||||||
|
bool useHardwareSkinning() const { return m_skinned_mesh!= NULL; }
|
||||||
private:
|
private:
|
||||||
RenderInfo* m_mesh_render_info;
|
RenderInfo* m_mesh_render_info;
|
||||||
bool m_all_parts_colorized;
|
bool m_all_parts_colorized;
|
||||||
|
irr::scene::CSkinnedMesh* m_skinned_mesh;
|
||||||
|
int m_skinning_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // STKANIMATEDMESH_HPP
|
#endif // STKANIMATEDMESH_HPP
|
||||||
|
@ -155,6 +155,22 @@ GLuint createVAO(GLuint vbo, GLuint idx, video::E_VERTEX_TYPE type)
|
|||||||
glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE,
|
glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE,
|
||||||
getVertexPitchFromType(type), (GLvoid*)48);
|
getVertexPitchFromType(type), (GLvoid*)48);
|
||||||
break;
|
break;
|
||||||
|
case video::EVT_SKINNED_MESH:
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(type), 0);
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(type), (GLvoid*)12);
|
||||||
|
glEnableVertexAttribArray(2);
|
||||||
|
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitchFromType(type), (GLvoid*)24);
|
||||||
|
glEnableVertexAttribArray(3);
|
||||||
|
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, getVertexPitchFromType(type), (GLvoid*)28);
|
||||||
|
glEnableVertexAttribArray(3);
|
||||||
|
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, getVertexPitchFromType(type), (GLvoid*)44);
|
||||||
|
glEnableVertexAttribArray(5);
|
||||||
|
glVertexAttribIPointer(5, 4, GL_INT, getVertexPitchFromType(type), (GLvoid*)60);
|
||||||
|
glEnableVertexAttribArray(6);
|
||||||
|
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, getVertexPitchFromType(type), (GLvoid*)76);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0 && "Wrong vertex type");
|
assert(0 && "Wrong vertex type");
|
||||||
}
|
}
|
||||||
@ -346,8 +362,8 @@ static void setTexture(GLMesh &mesh, unsigned i, bool is_srgb,
|
|||||||
{
|
{
|
||||||
if (!mesh.textures[i])
|
if (!mesh.textures[i])
|
||||||
{
|
{
|
||||||
Log::error("STKMesh", "Missing texture %d for material %s", i,
|
//Log::error("STKMesh", "Missing texture %d for material %s", i,
|
||||||
mat_name.c_str());
|
// mat_name.c_str());
|
||||||
// use unicolor texture to replace missing texture
|
// use unicolor texture to replace missing texture
|
||||||
mesh.textures[i] =
|
mesh.textures[i] =
|
||||||
getUnicolorTexture(video::SColor(255, 127, 127, 127));
|
getUnicolorTexture(video::SColor(255, 127, 127, 127));
|
||||||
@ -413,6 +429,7 @@ void initTextures(GLMesh &mesh, Material::ShaderType mat)
|
|||||||
break;
|
break;
|
||||||
case Material::SHADERTYPE_DETAIL_MAP:
|
case Material::SHADERTYPE_DETAIL_MAP:
|
||||||
case Material::SHADERTYPE_NORMAL_MAP:
|
case Material::SHADERTYPE_NORMAL_MAP:
|
||||||
|
case Material::SHADERTYPE_SOLID_SKINNED_MESH:
|
||||||
setTexture(mesh, 0, true, getShaderTypeName(mat));
|
setTexture(mesh, 0, true, getShaderTypeName(mat));
|
||||||
setTexture(mesh, 1, false, getShaderTypeName(mat));
|
setTexture(mesh, 1, false, getShaderTypeName(mat));
|
||||||
setTexture(mesh, 2, false, getShaderTypeName(mat));
|
setTexture(mesh, 2, false, getShaderTypeName(mat));
|
||||||
|
@ -116,6 +116,12 @@ class ListMatDefault : public MeshList<ListMatDefault, GLMesh *, core::matrix4,
|
|||||||
core::vector2df>
|
core::vector2df>
|
||||||
{};
|
{};
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
class ListSkinnedSolid : public MeshList<ListSkinnedSolid, GLMesh *, core::matrix4,
|
||||||
|
core::matrix4, core::vector2df,
|
||||||
|
core::vector2df>
|
||||||
|
{};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
class ListMatAlphaRef : public MeshList<ListMatAlphaRef, GLMesh *, core::matrix4,
|
class ListMatAlphaRef : public MeshList<ListMatAlphaRef, GLMesh *, core::matrix4,
|
||||||
core::matrix4, core::vector2df,
|
core::matrix4, core::vector2df,
|
||||||
|
@ -161,6 +161,9 @@ void VAOInstanceUtil<InstanceDataSingleTex>::SetVertexAttrib()
|
|||||||
glEnableVertexAttribArray(11);
|
glEnableVertexAttribArray(11);
|
||||||
glVertexAttribIPointer(11, 2, GL_UNSIGNED_INT, sizeof(InstanceDataSingleTex), (GLvoid*)(9 * sizeof(float)));
|
glVertexAttribIPointer(11, 2, GL_UNSIGNED_INT, sizeof(InstanceDataSingleTex), (GLvoid*)(9 * sizeof(float)));
|
||||||
glVertexAttribDivisorARB(11, 1);
|
glVertexAttribDivisorARB(11, 1);
|
||||||
|
glEnableVertexAttribArray(15);
|
||||||
|
glVertexAttribIPointer(15, 1, GL_UNSIGNED_INT, sizeof(InstanceDataSingleTex), (GLvoid*)(11 * sizeof(float)));
|
||||||
|
glVertexAttribDivisorARB(15, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
@ -200,6 +203,9 @@ void VAOInstanceUtil<InstanceDataFourTex>::SetVertexAttrib()
|
|||||||
glEnableVertexAttribArray(14);
|
glEnableVertexAttribArray(14);
|
||||||
glVertexAttribIPointer(14, 2, GL_UNSIGNED_INT, sizeof(InstanceDataFourTex), (GLvoid*)(13 * sizeof(float) + 6 * sizeof(unsigned)));
|
glVertexAttribIPointer(14, 2, GL_UNSIGNED_INT, sizeof(InstanceDataFourTex), (GLvoid*)(13 * sizeof(float) + 6 * sizeof(unsigned)));
|
||||||
glVertexAttribDivisorARB(14, 1);
|
glVertexAttribDivisorARB(14, 1);
|
||||||
|
glEnableVertexAttribArray(15);
|
||||||
|
glVertexAttribIPointer(15, 1, GL_UNSIGNED_INT, sizeof(InstanceDataFourTex), (GLvoid*)(13 * sizeof(float) + 8 * sizeof(unsigned)));
|
||||||
|
glVertexAttribDivisorARB(15, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
@ -216,7 +222,7 @@ void VAOManager::regenerateInstancedVAO()
|
|||||||
{
|
{
|
||||||
cleanInstanceVAOs();
|
cleanInstanceVAOs();
|
||||||
|
|
||||||
enum video::E_VERTEX_TYPE IrrVT[] = { video::EVT_STANDARD, video::EVT_2TCOORDS, video::EVT_TANGENTS };
|
enum video::E_VERTEX_TYPE IrrVT[] = { video::EVT_STANDARD, video::EVT_2TCOORDS, video::EVT_TANGENTS, video::EVT_SKINNED_MESH };
|
||||||
for (unsigned i = 0; i < VTXTYPE_COUNT; i++)
|
for (unsigned i = 0; i < VTXTYPE_COUNT; i++)
|
||||||
{
|
{
|
||||||
video::E_VERTEX_TYPE tp = IrrVT[i];
|
video::E_VERTEX_TYPE tp = IrrVT[i];
|
||||||
@ -264,6 +270,8 @@ size_t VAOManager::getVertexPitch(enum VTXTYPE tp) const
|
|||||||
return getVertexPitchFromType(video::EVT_2TCOORDS);
|
return getVertexPitchFromType(video::EVT_2TCOORDS);
|
||||||
case VTXTYPE_TANGENT:
|
case VTXTYPE_TANGENT:
|
||||||
return getVertexPitchFromType(video::EVT_TANGENTS);
|
return getVertexPitchFromType(video::EVT_TANGENTS);
|
||||||
|
case VTXTYPE_SKINNED_MESH:
|
||||||
|
return getVertexPitchFromType(video::EVT_SKINNED_MESH);
|
||||||
default:
|
default:
|
||||||
assert(0 && "Wrong vtxtype");
|
assert(0 && "Wrong vtxtype");
|
||||||
return -1;
|
return -1;
|
||||||
@ -282,6 +290,8 @@ VAOManager::VTXTYPE VAOManager::getVTXTYPE(video::E_VERTEX_TYPE type)
|
|||||||
return VTXTYPE_TCOORD;
|
return VTXTYPE_TCOORD;
|
||||||
case video::EVT_TANGENTS:
|
case video::EVT_TANGENTS:
|
||||||
return VTXTYPE_TANGENT;
|
return VTXTYPE_TANGENT;
|
||||||
|
case video::EVT_SKINNED_MESH:
|
||||||
|
return VTXTYPE_SKINNED_MESH;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -296,6 +306,8 @@ irr::video::E_VERTEX_TYPE VAOManager::getVertexType(enum VTXTYPE tp)
|
|||||||
return video::EVT_2TCOORDS;
|
return video::EVT_2TCOORDS;
|
||||||
case VTXTYPE_TANGENT:
|
case VTXTYPE_TANGENT:
|
||||||
return video::EVT_TANGENTS;
|
return video::EVT_TANGENTS;
|
||||||
|
case VTXTYPE_SKINNED_MESH:
|
||||||
|
return video::EVT_SKINNED_MESH;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +62,7 @@ struct InstanceDataSingleTex
|
|||||||
float Z;
|
float Z;
|
||||||
} Scale;
|
} Scale;
|
||||||
uint64_t Texture;
|
uint64_t Texture;
|
||||||
|
uint32_t skinning_offset;
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
@ -135,6 +136,7 @@ struct InstanceDataFourTex
|
|||||||
uint64_t SecondTexture;
|
uint64_t SecondTexture;
|
||||||
uint64_t ThirdTexture;
|
uint64_t ThirdTexture;
|
||||||
uint64_t FourthTexture;
|
uint64_t FourthTexture;
|
||||||
|
uint32_t skinning_offset;
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
@ -197,7 +199,7 @@ struct MeshRenderInfoEquals : std::binary_function
|
|||||||
|
|
||||||
class VAOManager : public Singleton<VAOManager>
|
class VAOManager : public Singleton<VAOManager>
|
||||||
{
|
{
|
||||||
enum VTXTYPE { VTXTYPE_STANDARD, VTXTYPE_TCOORD, VTXTYPE_TANGENT, VTXTYPE_COUNT };
|
enum VTXTYPE { VTXTYPE_STANDARD, VTXTYPE_TCOORD, VTXTYPE_TANGENT, VTXTYPE_SKINNED_MESH, VTXTYPE_COUNT };
|
||||||
GLuint vbo[VTXTYPE_COUNT], ibo[VTXTYPE_COUNT], vao[VTXTYPE_COUNT];
|
GLuint vbo[VTXTYPE_COUNT], ibo[VTXTYPE_COUNT], vao[VTXTYPE_COUNT];
|
||||||
GLuint instance_vbo[InstanceTypeCount];
|
GLuint instance_vbo[InstanceTypeCount];
|
||||||
void *Ptr[InstanceTypeCount];
|
void *Ptr[InstanceTypeCount];
|
||||||
|
Loading…
Reference in New Issue
Block a user