Skip to content

Commit 83aaef6

Browse files
committed
WIP HW skinning!
1 parent b27d84b commit 83aaef6

22 files changed

+180
-34
lines changed

client/shaders/object_shader/opengl_vertex.glsl

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ VARYING_ float nightRatio;
3232
const vec3 artificialLight = vec3(1.04, 1.04, 1.04);
3333
VARYING_ float vIDiff;
3434

35+
#ifdef USE_SKINNING
36+
// TODO compute reasonable value in C++
37+
layout (std140) uniform JointMatrices {
38+
mat4 joints[128];
39+
};
40+
#endif
41+
3542
#ifdef ENABLE_DYNAMIC_SHADOWS
3643

3744
uniform float xyPerspectiveBias0;
@@ -89,16 +96,35 @@ float directional_ambient(vec3 normal)
8996

9097
void main(void)
9198
{
99+
#ifdef USE_SKINNING
100+
uvec4 jids = inVertexJointIDs;
101+
vec4 skinPos = inVertexPosition;
102+
vec3 skinNormal = inVertexNormal;
103+
// Alternatively: Introduce neutral bone at index 0 with identity matrix
104+
if (inVertexWeights != vec4(0.0)) {
105+
mat4 mSkin =
106+
inVertexWeights.x * joints[jids.x] +
107+
inVertexWeights.y * joints[jids.y] +
108+
inVertexWeights.z * joints[jids.z] +
109+
inVertexWeights.w * joints[jids.w];
110+
skinPos = vec4((mSkin * vec4(inVertexPosition.xyz, 1.0)).xyz, 1.0);
111+
skinNormal = (mSkin * vec4(inVertexNormal, 0.0)).xyz;
112+
}
113+
#else
114+
vec4 skinPos = inVertexPosition;
115+
vec3 skinNormal = inVertexNormal;
116+
#endif
117+
92118
#ifdef USE_ARRAY_TEXTURE
93119
varTexLayer = inVertexAux;
94120
#endif
95121
varTexCoord = (mTexture * vec4(inTexCoord0.xy, 1.0, 1.0)).st;
96122

97-
gl_Position = mWorldViewProj * inVertexPosition;
123+
gl_Position = mWorldViewProj * skinPos;
98124

99-
vNormal = (mWorld * vec4(inVertexNormal, 0.0)).xyz;
100-
worldPosition = (mWorld * inVertexPosition).xyz;
101-
eyeVec = -(mWorldView * inVertexPosition).xyz;
125+
vNormal = (mWorld * vec4(skinNormal, 0.0)).xyz;
126+
worldPosition = (mWorld * skinPos).xyz;
127+
eyeVec = -(mWorldView * skinPos).xyz;
102128

103129
#if (MATERIAL_TYPE == TILE_MATERIAL_PLAIN) || (MATERIAL_TYPE == TILE_MATERIAL_PLAIN_ALPHA)
104130
vIDiff = 1.0;

irr/include/CVertexBuffer.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <vector>
99
#include "IVertexBuffer.h"
1010
#include "WeightBuffer.h"
11+
#include "irr_ptr.h"
1112

1213
namespace scene
1314
{
@@ -74,11 +75,16 @@ struct CVertexBuffer final : public IVertexBuffer
7475
return Data[i].TCoords;
7576
}
7677

78+
const WeightBuffer *getWeightBuffer() const override
79+
{
80+
return Weights.get();
81+
}
82+
7783
//! Vertices of this buffer
7884
std::vector<T> Data;
7985

8086
//! Optional weights for skinning
81-
std::unique_ptr<WeightBuffer> Weights;
87+
irr_ptr<WeightBuffer> Weights;
8288
};
8389

8490
//! Standard buffer

irr/include/EVertexAttributes.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ enum E_VERTEX_ATTRIBUTES
1414
EVA_TCOORD1,
1515
EVA_TANGENT,
1616
EVA_BINORMAL,
17+
EVA_WEIGHTS,
18+
EVA_JOINT_IDS,
1719
EVA_COUNT
1820
};
1921

@@ -27,6 +29,8 @@ const char *const sBuiltInVertexAttributeNames[] = {
2729
"inTexCoord1",
2830
"inVertexTangent",
2931
"inVertexBinormal",
32+
"inVertexWeights",
33+
"inVertexJointIDs",
3034
0,
3135
};
3236

irr/include/IVertexBuffer.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
namespace scene
1212
{
1313

14-
struct WeightBuffer;
14+
class WeightBuffer;
1515

1616
class IVertexBuffer : public virtual IReferenceCounted, public IHWBuffer
1717
{
@@ -49,6 +49,9 @@ class IVertexBuffer : public virtual IReferenceCounted, public IHWBuffer
4949

5050
//! returns texture coord of vertex i
5151
virtual core::vector2df &getTCoords(u32 i) = 0;
52+
53+
//! Get weight buffer associated with this vertex buffer, if any
54+
virtual const WeightBuffer *getWeightBuffer() const = 0;
5255
};
5356

5457
} // end namespace scene

irr/include/IVideoDriver.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,10 @@ class IVideoDriver : public virtual IReferenceCounted
142142
\param mat Matrix describing the transformation. */
143143
virtual void setTransform(E_TRANSFORMATION_STATE state, const core::matrix4 &mat) = 0;
144144

145+
//! Sets joint transformation matrices for skinned meshes.
146+
// FIXME only implemented for OGL 3
147+
virtual void setJointTransforms(const std::vector<core::matrix4> &jointMatrices) { assert(false); };
148+
145149
//! Returns the transformation set by setTransform
146150
/** \param state Transformation type to query
147151
\return Matrix describing the transformation. */

irr/include/SSkinMeshBuffer.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -234,17 +234,17 @@ struct SSkinMeshBuffer final : public IMeshBuffer
234234
}
235235
}
236236

237-
void setWeights(WeightBuffer &&weights)
237+
void addWeightBuffer()
238238
{
239239
switch (VertexType) {
240240
case video::EVT_STANDARD:
241-
Vertices_Standard->Weights = std::make_unique<WeightBuffer>(std::move(weights));
241+
Vertices_Standard->Weights.reset(new WeightBuffer(getVertexCount()));
242242
break;
243243
case video::EVT_2TCOORDS:
244-
Vertices_2TCoords->Weights = std::make_unique<WeightBuffer>(std::move(weights));
244+
Vertices_2TCoords->Weights.reset(new WeightBuffer(getVertexCount()));
245245
break;
246246
case video::EVT_TANGENTS:
247-
Vertices_Tangents->Weights = std::make_unique<WeightBuffer>(std::move(weights));
247+
Vertices_Tangents->Weights.reset(new WeightBuffer(getVertexCount()));
248248
break;
249249
default:
250250
IRR_CODE_UNREACHABLE();

irr/include/SkinnedMesh.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ class SkinnedMesh : public IAnimatedMesh
6363
//! by multiplying with respective parent matrices.
6464
void calculateGlobalMatrices(std::vector<core::matrix4> &matrices) const;
6565

66+
std::vector<core::matrix4> calculateSkinMatrices(const std::vector<core::matrix4> &global_matrices) const;
67+
68+
void rigidAnimation(const std::vector<core::matrix4> &global_matrices);
69+
6670
//! Performs a software skin on this mesh based on the given joint matrices
6771
void skinMesh(const std::vector<core::matrix4> &animated_transforms);
6872

irr/include/WeightBuffer.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
#pragma once
55

6+
#include "EHardwareBufferFlags.h"
7+
#include "IHWBuffer.h"
68
#include "vector3d.h"
79
#include "matrix4.h"
810
#include "IVertexBuffer.h"
@@ -15,7 +17,7 @@
1517
namespace scene
1618
{
1719

18-
struct WeightBuffer
20+
struct WeightBuffer final : public IHWBuffer
1921
{
2022
constexpr static u16 MAX_WEIGHTS_PER_VERTEX = 4;
2123
// ID-weight pairs for a joint
@@ -36,17 +38,24 @@ struct WeightBuffer
3638
std::unique_ptr<core::vector3df[]> static_positions;
3739
std::unique_ptr<core::vector3df[]> static_normals;
3840

39-
WeightBuffer(size_t n_verts) : weights(n_verts) {}
41+
WeightBuffer(size_t n_verts) : weights(n_verts)
42+
{ MappingHint = scene::EHM_STATIC; }
4043

4144
const std::array<u16, MAX_WEIGHTS_PER_VERTEX> &getJointIds(u32 vertex_id) const
4245
{ return weights[vertex_id].joint_ids; }
4346

4447
const std::array<f32, MAX_WEIGHTS_PER_VERTEX> &getWeights(u32 vertex_id) const
4548
{ return weights[vertex_id].weights; }
4649

47-
size_t size() const
50+
u32 getCount() const override
4851
{ return weights.size(); }
4952

53+
size_t getElementSize() const override
54+
{ return sizeof(VertexWeights); }
55+
56+
const void *getData() const override
57+
{ return weights.data(); }
58+
5059
void addWeight(u32 vertex_id, u16 joint_id, f32 weight);
5160

5261
/// Transform position and normal using the weights of the given vertex

irr/src/AnimatedMeshSceneNode.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ IMesh *AnimatedMeshSceneNode::getMeshForCurrentFrame()
159159
auto *skinnedMesh = static_cast<SkinnedMesh *>(Mesh);
160160

161161
// Matrices have already been calculated in OnAnimate
162-
skinnedMesh->skinMesh(PerJoint.GlobalMatrices);
162+
// TODO skinnedMesh->skinMesh(PerJoint.GlobalMatrices);
163163

164164
return skinnedMesh;
165165
}
@@ -216,6 +216,11 @@ void AnimatedMeshSceneNode::render()
216216
scene::IMesh *m = getMeshForCurrentFrame();
217217
assert(m);
218218

219+
if (auto *sm = dynamic_cast<SkinnedMesh *>(Mesh)) {
220+
// TODO check whether there are any weights to make use of these joint transforms
221+
driver->setJointTransforms(sm->calculateSkinMatrices(PerJoint.GlobalMatrices));
222+
sm->rigidAnimation(PerJoint.GlobalMatrices);
223+
}
219224
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
220225

221226
for (u32 i = 0; i < m->getMeshBufferCount(); ++i) {

irr/src/CNullDriver.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -969,8 +969,8 @@ CNullDriver::SHWBufferLink *CNullDriver::getBufferLink(const scene::IHWBuffer *b
969969
return nullptr;
970970

971971
// search for hardware links
972-
if (auto *HWBuffer = reinterpret_cast<SHWBufferLink *>(buf->Link))
973-
return HWBuffer;
972+
if (auto *link = reinterpret_cast<SHWBufferLink *>(buf->Link))
973+
return link;
974974

975975
return createHardwareBuffer(buf);
976976
}
@@ -1039,7 +1039,7 @@ void CNullDriver::removeAllHardwareBuffers()
10391039

10401040
bool CNullDriver::isHardwareBufferRecommend(const scene::IHWBuffer *buf)
10411041
{
1042-
if (!buf || buf->MappingHint == scene::EHM_NEVER)
1042+
if (buf->MappingHint == scene::EHM_NEVER)
10431043
return false;
10441044

10451045
if (dynamic_cast<const scene::IVertexBuffer *>(buf)) {

0 commit comments

Comments
 (0)