Skip to content

Commit

Permalink
#5584: Skeleton renderable migrated to derive from RenderableGeometry
Browse files Browse the repository at this point in the history
  • Loading branch information
codereader committed Jan 16, 2022
1 parent 5034bb1 commit c7646ec
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 82 deletions.
3 changes: 3 additions & 0 deletions install/user.xml
Expand Up @@ -54,6 +54,9 @@
<hideDistantAreas value="0" />
<hideDistance value="800" />
</aasViewer>
<md5>
<renderSkeleton value="0" />
</md5>
<showAllLightRadii value="0"/>
<alwaysShowLightVertices value="1"/>
<rotateObjectsIndependently value="0" />
Expand Down
6 changes: 2 additions & 4 deletions radiantcore/model/md5/MD5Model.cpp
Expand Up @@ -13,8 +13,7 @@ namespace md5 {

MD5Model::MD5Model() :
_polyCount(0),
_vertexCount(0),
_renderableSkeleton(_skeleton)
_vertexCount(0)
{}

MD5Model::MD5Model(const MD5Model& other) :
Expand All @@ -24,8 +23,7 @@ MD5Model::MD5Model(const MD5Model& other) :
_polyCount(other._polyCount),
_vertexCount(other._vertexCount),
_filename(other._filename),
_modelPath(other._modelPath),
_renderableSkeleton(_skeleton)
_modelPath(other._modelPath)
{
// Copy-construct the other model's surfaces, but not its shaders, revert to default
for (std::size_t i = 0; i < other._surfaces.size(); ++i)
Expand Down
13 changes: 5 additions & 8 deletions radiantcore/model/md5/MD5Model.h
Expand Up @@ -7,7 +7,7 @@
#include "parser/DefTokeniser.h"

#include "MD5Surface.h"
#include "RenderableMD5Skeleton.h"
#include "MD5Skeleton.h"

namespace md5
{
Expand Down Expand Up @@ -65,9 +65,6 @@ class MD5Model :
// The current state of our animated skeleton
MD5Skeleton _skeleton;

// The OpenGLRenderable visualising the MD5Skeleton
RenderableMD5Skeleton _renderableSkeleton;

// We need to keep a reference for skin swapping
RenderSystemWeakPtr _renderSystem;

Expand All @@ -87,10 +84,10 @@ class MD5Model :
*/
void parseFromTokens(parser::DefTokeniser& tok);

RenderableMD5Skeleton& getRenderableSkeleton()
{
return _renderableSkeleton;
}
const MD5Skeleton& getSkeleton() const
{
return _skeleton;
}

void updateAABB();

Expand Down
23 changes: 13 additions & 10 deletions radiantcore/model/md5/MD5ModelNode.cpp
Expand Up @@ -11,7 +11,9 @@ namespace md5

MD5ModelNode::MD5ModelNode(const MD5ModelPtr& model) :
_model(new MD5Model(*model)), // create a copy of the incoming model, we need our own instance
_attachedToShaders(false)
_attachedToShaders(false),
_showSkeleton(RKEY_RENDER_SKELETON),
_renderableSkeleton(_model->getSkeleton(), localToWorld())
{
_animationUpdateConnection = _model->signal_ModelAnimationUpdated().connect(
sigc::mem_fun(this, &MD5ModelNode::onModelAnimationUpdated)
Expand Down Expand Up @@ -105,29 +107,30 @@ void MD5ModelNode::onPreRender(const VolumeTest& volume)

// Attach renderables (or do nothing if everything is up to date)
attachToShaders();

if (_showSkeleton.get())
{
_renderableSkeleton.queueUpdate();
_renderableSkeleton.update(_renderEntity->getColourShader());
}
else
{
_renderableSkeleton.clear();
}
}

void MD5ModelNode::renderSolid(IRenderableCollector& collector, const VolumeTest& volume) const
{
assert(_renderEntity);
#if 0
render(collector, volume, localToWorld(), *_renderEntity);
#endif
}

void MD5ModelNode::renderWireframe(IRenderableCollector& collector, const VolumeTest& volume) const
{
assert(_renderEntity);
#if 0
render(collector, volume, localToWorld(), *_renderEntity);
#endif
}

void MD5ModelNode::renderHighlights(IRenderableCollector& collector, const VolumeTest& volume)
{
#if 0
render(collector, volume, localToWorld(), *_renderEntity);
#endif
auto identity = Matrix4::getIdentity();

for (const auto& surface : _renderableSurfaces)
Expand Down
11 changes: 10 additions & 1 deletion radiantcore/model/md5/MD5ModelNode.h
Expand Up @@ -7,8 +7,13 @@
#include "scene/Node.h"
#include "render/VectorLightList.h"
#include "../RenderableModelSurface.h"
#include "registry/CachedKey.h"
#include "RenderableMD5Skeleton.h"

namespace md5 {
namespace md5
{

constexpr const char* const RKEY_RENDER_SKELETON = "user/ui/md5/renderSkeleton";

class MD5ModelNode :
public scene::Node,
Expand All @@ -29,6 +34,10 @@ class MD5ModelNode :

sigc::connection _animationUpdateConnection;

registry::CachedKey<bool> _showSkeleton;

RenderableMD5Skeleton _renderableSkeleton;

public:
MD5ModelNode(const MD5ModelPtr& model);
virtual ~MD5ModelNode();
Expand Down
163 changes: 104 additions & 59 deletions radiantcore/model/md5/RenderableMD5Skeleton.h
Expand Up @@ -2,77 +2,122 @@

#include "irender.h"
#include "MD5Skeleton.h"
#include "render/RenderableGeometry.h"

namespace md5
{

class RenderableMD5Skeleton :
public OpenGLRenderable
public render::RenderableGeometry
{
private:
const MD5Skeleton& _skeleton;
const Matrix4& _localToWorld;

bool _updateNeeded;

public:
RenderableMD5Skeleton(const MD5Skeleton& skeleton) :
_skeleton(skeleton)
RenderableMD5Skeleton(const MD5Skeleton& skeleton, const Matrix4& localToWorld) :
_skeleton(skeleton),
_localToWorld(localToWorld),
_updateNeeded(true)
{}

void render(const RenderInfo& info) const
{
if (_skeleton.size() == 0) return;

glBegin(GL_LINES);

std::size_t numJoints = _skeleton.size();

for (std::size_t i = 0; i < _skeleton.size(); ++i)
{
const IMD5Anim::Key& bone = _skeleton.getKey(i);
const Joint& joint = _skeleton.getJoint(i);

if (joint.parentId != -1)
{
const IMD5Anim::Key& parentBone = _skeleton.getKey(joint.parentId);

glVertex3dv(parentBone.origin);
glVertex3dv(bone.origin);
}
else
{
glVertex3d(0, 0, 0);
glVertex3dv(bone.origin);
}
}

for (std::size_t i = 0; i < numJoints; ++i)
{
const IMD5Anim::Key& joint = _skeleton.getKey(i);

Vector3 x(2,0,0);
Vector3 y(0,2,0);
Vector3 z(0,0,2);

x = joint.orientation.transformPoint(x);
y = joint.orientation.transformPoint(y);
z = joint.orientation.transformPoint(z);

Vector3 origin(joint.origin);

glColor3f(1, 0, 0);
glVertex3dv(origin);
glVertex3dv(origin + x);

glColor3f(0, 1, 0);
glVertex3dv(origin);
glVertex3dv(origin + y);

glColor3f(0, 0, 1);
glVertex3dv(origin);
glVertex3dv(origin + z);
}

glEnd();
}
void queueUpdate()
{
_updateNeeded = true;
}

protected:
void updateGeometry() override
{
if (!_updateNeeded) return;

_updateNeeded = false;

if (_skeleton.size() == 0)
{
clear();
return;
}

std::vector<ArbitraryMeshVertex> vertices;
std::vector<unsigned int> indices;

auto numJoints = _skeleton.size();

for (auto i = 0; i < numJoints; ++i)
{
const auto& bone = _skeleton.getKey(i);
const auto& joint = _skeleton.getJoint(i);

if (joint.parentId != -1)
{
const auto& parentBone = _skeleton.getKey(joint.parentId);

indices.push_back(static_cast<unsigned int>(vertices.size()));
vertices.push_back(toVertex(parentBone.origin));

indices.push_back(static_cast<unsigned int>(vertices.size()));
vertices.push_back(toVertex(bone.origin));
}
else
{
indices.push_back(static_cast<unsigned int>(vertices.size()));
vertices.push_back(toVertex({ 0, 0, 0 }));

indices.push_back(static_cast<unsigned int>(vertices.size()));
vertices.push_back(toVertex(bone.origin));
}
}

for (auto i = 0; i < numJoints; ++i)
{
const auto& joint = _skeleton.getKey(i);

Vector3 x(2, 0, 0);
Vector3 y(0, 2, 0);
Vector3 z(0, 0, 2);

x = joint.orientation.transformPoint(x);
y = joint.orientation.transformPoint(y);
z = joint.orientation.transformPoint(z);

Vector3 origin(joint.origin);

// x axis
indices.push_back(static_cast<unsigned int>(vertices.size()));
vertices.push_back(toVertex(origin, { 1, 0, 0, 1 }));
indices.push_back(static_cast<unsigned int>(vertices.size()));
vertices.push_back(toVertex(origin + x, { 1, 0, 0, 1 }));

// y axis
indices.push_back(static_cast<unsigned int>(vertices.size()));
vertices.push_back(toVertex(origin, { 0, 1, 0, 1 }));
indices.push_back(static_cast<unsigned int>(vertices.size()));
vertices.push_back(toVertex(origin + y, { 0, 1, 0, 1 }));

// z axis
indices.push_back(static_cast<unsigned int>(vertices.size()));
vertices.push_back(toVertex(origin, { 0, 0, 1, 1 }));
indices.push_back(static_cast<unsigned int>(vertices.size()));
vertices.push_back(toVertex(origin + z, { 0, 0, 1, 1 }));
}

// Move the skeleton to world space
for (auto& v : vertices)
{
v.vertex = _localToWorld * v.vertex;
}

RenderableGeometry::updateGeometry(render::GeometryType::Lines, vertices, indices);
}

private:
ArbitraryMeshVertex toVertex(const Vector3& vertex, const Vector4& colour = { 1, 1, 1, 1 })
{
return { vertex, {0, 0, 0}, {1, 0}, colour };
}
};

} // namespace

0 comments on commit c7646ec

Please sign in to comment.