Skip to content

Commit

Permalink
UPBGE: Replace display array modification flag by update client/server.
Browse files Browse the repository at this point in the history
Previously the display array was notify for an update thanks to a modification
flag, but different user were reading this flag and one user was setting clearing
it. This caused to not notify some user that the display array was modified.

To fix this issue the new CM_Update[Server/Client] utilities are used,
display array inherit from CM_UpdateServer and the users RAS_MeshBoundingBox,
RAS_Deformer and RAS_DisplayArrayBucket are owning a update client registered
into a display array.

But before using the update client/server mechanism, CM_UpdateClient needed
to be modified to track a integer for the update flag and not only a boolean,
thsi is used in DAB to catch any update from the DA but after a call to
GetInvalidAndClear make a check of what is modified actually.

RAS_MeshBoundingBox wans't really designed to handle update client as not
struct was used to represent and used DA in the bounding box. Similar to
RAS_Deformer, RAS_MeshBoundingBox use a DisplayArraySLot struct, this
struct store the tracked DA and it's update client.
  • Loading branch information
panzergame committed Dec 8, 2017
1 parent 39ae7f9 commit 87a7e65
Show file tree
Hide file tree
Showing 21 changed files with 160 additions and 159 deletions.
17 changes: 8 additions & 9 deletions source/gameengine/Common/CM_Update.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ class CM_UpdateClient
friend class CM_UpdateServer<Category>;

private:
bool m_invalid;
unsigned int m_invalid;
unsigned int m_filter;
CM_UpdateServer<Category> *m_server;

public:
CM_UpdateClient(unsigned int filter, bool invalid)
CM_UpdateClient(unsigned int filter, unsigned int invalid)
:m_invalid(invalid),
m_filter(filter),
m_server(nullptr)
Expand All @@ -31,28 +31,27 @@ friend class CM_UpdateServer<Category>;
{
}


~CM_UpdateClient()
{
if (m_server) {
m_server->RemoveUpdateClient(this);
}
}

bool GetInvalid() const
unsigned int GetInvalid() const
{
return m_invalid;
}

void ClearInvalid()
{
m_invalid = false;
m_invalid = 0;
}

bool GetInvalidAndClear()
unsigned int GetInvalidAndClear()
{
const bool invalid = m_invalid;
m_invalid = false;
const unsigned int invalid = m_invalid;
m_invalid = 0;
return invalid;
}
};
Expand Down Expand Up @@ -100,7 +99,7 @@ class CM_UpdateServer
void NotifyUpdate(unsigned int flag)
{
for (ClientType *client : m_clients) {
client->m_invalid |= (bool)(flag & client->m_filter);
client->m_invalid |= (flag & client->m_filter);
}
}
};
Expand Down
7 changes: 2 additions & 5 deletions source/gameengine/Converter/BL_MeshDeformer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,13 @@
#include <string>
#include "BLI_math.h"

void BL_MeshDeformer::Apply(RAS_MeshMaterial *UNUSED(meshmat), RAS_IDisplayArray *UNUSED(array))
void BL_MeshDeformer::Apply(RAS_IDisplayArray *UNUSED(array))
{
// only apply once per frame if the mesh is actually modified
if (m_lastDeformUpdate != m_gameobj->GetLastFrame()) {
// For each display array
for (const DisplayArraySlot& slot : m_slots) {
RAS_IDisplayArray *array = slot.m_displayArray;
if (array->GetModifiedFlag() == RAS_IDisplayArray::NONE_MODIFIED) {
continue;
}

// For each vertex
for (unsigned int i = 0, size = array->GetVertexCount(); i < size; ++i) {
Expand All @@ -67,7 +64,7 @@ void BL_MeshDeformer::Apply(RAS_MeshMaterial *UNUSED(meshmat), RAS_IDisplayArray
v.SetXYZ(m_bmesh->mvert[vinfo.GetOrigIndex()].co);
}

array->AppendModifiedFlag(RAS_IDisplayArray::POSITION_MODIFIED);
array->NotifyUpdate(RAS_IDisplayArray::POSITION_MODIFIED);
}

m_lastDeformUpdate = m_gameobj->GetLastFrame();
Expand Down
2 changes: 1 addition & 1 deletion source/gameengine/Converter/BL_MeshDeformer.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class BL_MeshDeformer : public RAS_Deformer

BL_MeshDeformer(BL_DeformableGameObject *gameobj, Object *obj, RAS_MeshObject *meshobj);
virtual ~BL_MeshDeformer();
virtual void Apply(RAS_MeshMaterial *meshmat, RAS_IDisplayArray *array);
virtual void Apply(RAS_IDisplayArray *array);
virtual bool Update()
{
return false;
Expand Down
4 changes: 2 additions & 2 deletions source/gameengine/Converter/BL_ModifierDeformer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ void BL_ModifierDeformer::UpdateTransverts()

for (const DisplayArraySlot& slot : m_slots) {
RAS_IDisplayArray *array = slot.m_displayArray;
array->AppendModifiedFlag(RAS_IDisplayArray::SIZE_MODIFIED);
array->NotifyUpdate(RAS_IDisplayArray::SIZE_MODIFIED);
array->UpdateCache();
}

Expand All @@ -216,7 +216,7 @@ void BL_ModifierDeformer::UpdateTransverts()
}
}

void BL_ModifierDeformer::Apply(RAS_MeshMaterial *meshmat, RAS_IDisplayArray *array)
void BL_ModifierDeformer::Apply(RAS_IDisplayArray *array)
{
Update();
}
2 changes: 1 addition & 1 deletion source/gameengine/Converter/BL_ModifierDeformer.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class BL_ModifierDeformer : public BL_ShapeDeformer
virtual ~BL_ModifierDeformer();

bool Update();
virtual void Apply(RAS_MeshMaterial *meshmat, RAS_IDisplayArray *array);
virtual void Apply(RAS_IDisplayArray *array);
void ForceUpdate()
{
m_lastModifierUpdate = -1.0;
Expand Down
32 changes: 14 additions & 18 deletions source/gameengine/Converter/BL_SkinDeformer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,25 +113,19 @@ void BL_SkinDeformer::Relink(std::map<SCA_IObject *, SCA_IObject *>& map)
BL_MeshDeformer::Relink(map);
}

void BL_SkinDeformer::Apply(RAS_MeshMaterial *meshmat, RAS_IDisplayArray *array)
void BL_SkinDeformer::Apply(RAS_IDisplayArray *array)
{
if (!meshmat) {
return;
}

RAS_IDisplayArray *origarray = meshmat->GetDisplayArray();
for (DisplayArraySlot& slot : m_slots) {
if (slot.m_displayArray == array) {
const short modifiedFlag = slot.m_arrayUpdateClient.GetInvalidAndClear();
if (modifiedFlag != RAS_IDisplayArray::NONE_MODIFIED) {
/// Update vertex data from the original mesh.
array->UpdateFrom(slot.m_origDisplayArray, modifiedFlag);
}

const short modifiedFlag = origarray->GetModifiedFlag();
// No modifications ?
if (modifiedFlag == RAS_IDisplayArray::NONE_MODIFIED) {
return;
break;
}
}

/// Update vertex data from the original mesh.
array->UpdateFrom(origarray, modifiedFlag &
(RAS_IDisplayArray::TANGENT_MODIFIED |
RAS_IDisplayArray::UVS_MODIFIED |
RAS_IDisplayArray::COLORS_MODIFIED));
}

RAS_Deformer *BL_SkinDeformer::GetReplica()
Expand Down Expand Up @@ -266,6 +260,8 @@ void BL_SkinDeformer::UpdateTransverts()
mt::vec3 aabbMin(FLT_MAX);
mt::vec3 aabbMax(-FLT_MAX);

const bool autoUpdate = m_gameobj->GetAutoUpdateBounds();

// the vertex cache is unique to this deformer, no need to update it
// if it wasn't updated! We must update all the materials at once
// because we will not get here again for the other material
Expand All @@ -281,14 +277,14 @@ void BL_SkinDeformer::UpdateTransverts()
v.SetNormal(m_transnors[vinfo.GetOrigIndex()].data());
}

if (m_gameobj->GetAutoUpdateBounds()) {
if (autoUpdate) {
const mt::vec3 vertpos = v.xyz();
aabbMin = mt::vec3::Min(aabbMin, vertpos);
aabbMax = mt::vec3::Max(aabbMax, vertpos);
}
}

array->AppendModifiedFlag(RAS_IDisplayArray::POSITION_MODIFIED | RAS_IDisplayArray::NORMAL_MODIFIED);
array->NotifyUpdate(RAS_IDisplayArray::POSITION_MODIFIED | RAS_IDisplayArray::NORMAL_MODIFIED);
}

m_boundingBox->SetAabb(aabbMin, aabbMax);
Expand Down
4 changes: 2 additions & 2 deletions source/gameengine/Converter/BL_SkinDeformer.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,11 @@ class BL_SkinDeformer : public BL_MeshDeformer
virtual ~BL_SkinDeformer();
bool Update();
bool UpdateInternal(bool shape_applied);
virtual void Apply(RAS_MeshMaterial *meshmat, RAS_IDisplayArray *array);
virtual void Apply(RAS_IDisplayArray *array);
virtual void UpdateBuckets()
{
// update the deformer and all the mesh slots; Apply() does it well, so just call it.
Apply(nullptr, nullptr);
Apply(nullptr);
}
bool PoseUpdated()
{
Expand Down
4 changes: 2 additions & 2 deletions source/gameengine/Ketsji/BL_Shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ bool BL_Shader::LinkProgram()
{
// Can be null in case of filter shaders.
if (m_materialUpdateServer) {
// Notify all clients tracking this shader that shader is recompiled.
m_materialUpdateServer->NotifyUpdate(RAS_IPolyMaterial::SHADER_MODIFIED);
// Notify all clients tracking this shader that shader is recompiled and attributes are invalidated.
m_materialUpdateServer->NotifyUpdate(RAS_IPolyMaterial::SHADER_MODIFIED | RAS_IPolyMaterial::ATTRIBUTES_MODIFIED);
}

return RAS_Shader::LinkProgram();
Expand Down
8 changes: 4 additions & 4 deletions source/gameengine/Ketsji/KX_MeshProxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,9 +230,9 @@ PyObject *KX_MeshProxy::PyTransform(PyObject *args, PyObject *kwds)
vert.Transform(transform, ntransform);
}

array->AppendModifiedFlag(RAS_IDisplayArray::POSITION_MODIFIED |
RAS_IDisplayArray::NORMAL_MODIFIED |
RAS_IDisplayArray::TANGENT_MODIFIED);
array->NotifyUpdate(RAS_IDisplayArray::POSITION_MODIFIED |
RAS_IDisplayArray::NORMAL_MODIFIED |
RAS_IDisplayArray::TANGENT_MODIFIED);

/* if we set a material index, quit when done */
if (matindex != -1) {
Expand Down Expand Up @@ -310,7 +310,7 @@ PyObject *KX_MeshProxy::PyTransformUV(PyObject *args, PyObject *kwds)
}
}

array->AppendModifiedFlag(RAS_IDisplayArray::UVS_MODIFIED);
array->NotifyUpdate(RAS_IDisplayArray::UVS_MODIFIED);

/* if we set a material index, quit when done */
if (matindex != -1) {
Expand Down
23 changes: 14 additions & 9 deletions source/gameengine/Ketsji/KX_SoftBodyDeformer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ void KX_SoftBodyDeformer::Relink(std::map<SCA_IObject *, SCA_IObject *>& map)
}
}

void KX_SoftBodyDeformer::Apply(RAS_MeshMaterial *meshmat, RAS_IDisplayArray *array)
void KX_SoftBodyDeformer::Apply(RAS_IDisplayArray *array)
{
CcdPhysicsController *ctrl = (CcdPhysicsController *)m_gameobj->GetPhysicsController();
if (!ctrl)
Expand All @@ -92,8 +92,6 @@ void KX_SoftBodyDeformer::Apply(RAS_MeshMaterial *meshmat, RAS_IDisplayArray *ar
// update the vertex in m_transverts
Update();

RAS_IDisplayArray *origarray = meshmat->GetDisplayArray();

btSoftBody::tNodeArray& nodes(softBody->m_nodes);
const std::vector<unsigned int>& indices = ctrl->GetSoftBodyIndices();

Expand Down Expand Up @@ -128,16 +126,23 @@ void KX_SoftBodyDeformer::Apply(RAS_MeshMaterial *meshmat, RAS_IDisplayArray *ar
}
}

array->UpdateFrom(origarray, origarray->GetModifiedFlag() &
(RAS_IDisplayArray::TANGENT_MODIFIED |
RAS_IDisplayArray::UVS_MODIFIED |
RAS_IDisplayArray::COLORS_MODIFIED));
for (DisplayArraySlot& slot : m_slots) {
if (slot.m_displayArray == array) {
const short modifiedFlag = slot.m_arrayUpdateClient.GetInvalidAndClear();
if (modifiedFlag != RAS_IDisplayArray::NONE_MODIFIED) {
/// Update vertex data from the original mesh.
array->UpdateFrom(slot.m_origDisplayArray, modifiedFlag);
}

break;
}
}

array->NotifyUpdate(RAS_IDisplayArray::POSITION_MODIFIED | RAS_IDisplayArray::NORMAL_MODIFIED);

if (autoUpdate) {
m_boundingBox->ExtendAabb(aabbMin, aabbMax);
}

array->AppendModifiedFlag(RAS_IDisplayArray::POSITION_MODIFIED | RAS_IDisplayArray::NORMAL_MODIFIED);
}

#endif
2 changes: 1 addition & 1 deletion source/gameengine/Ketsji/KX_SoftBodyDeformer.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class KX_SoftBodyDeformer : public RAS_Deformer
virtual ~KX_SoftBodyDeformer();

virtual void Relink(std::map<SCA_IObject *, SCA_IObject *>& map);
virtual void Apply(RAS_MeshMaterial *meshmat, RAS_IDisplayArray *array);
virtual void Apply(RAS_IDisplayArray *array);
virtual bool Update()
{
m_bDynamic = true;
Expand Down
Loading

0 comments on commit 87a7e65

Please sign in to comment.