Skip to content

Commit 0aad135

Browse files
committed
UPBGE: Refactor render node system.
The refactor is caused by the following observation: the current system doesn't manage inter-node arguments, for example display array bucket can't pass its member pointer to mesh slots directly, the mesh slot has to get the pointer itself. This restriction is very blocking with the futur work on blender2.8 were the mesh slot will need to know the current shader used to bind the modelview matrix. To do so each node should be allowed to send a structure to its children node in addition to the global data structure. This will add a argument to every node bind/unbind functions, but instead of having all the arguments passed to mesh slot bind/unbind function (global, material, dab), a tuple structure is used, it contains all the arguments which will be passed to a node. This tuple structure is unique per node type and sub node use a tuple based on parent node tuple but with a pointer to node data. For example mesh slot tuple constructor is: RAS_MeshSlotNodeTuple(const RAS_DisplayArrayNodeTuple& displayArrayTuple, RAS_DisplayArrayNodeData *displayArrayData) It uses the DAB tuple of its parent node (which contains only data from materials node) and the parent node data. The type of the tuple, the data passed and the previous template arguments are now put in a info structure containing only aliases. The node data used to construct the tuple is gave to the node construct under a pointer to allow share same node data for different node, for example the instancing and non-instancing nodes in DAB sharing the same data. The building of the tuple is made for the downward and upward tree, the downward tree is the easiest. In this tree each node call its children node and before calling they initialize a tuple of the child tuple type with the tuple passed to the RAS_DownwardNode::Execute functions and the internal node data. On the other hand upward tree required to refactor the iterator used. Firstly the iterator bind the first node at its construction and unbind the last node at its destruction, it makes the tuple passed to node always valid in the iterator. Secondly the iterator use a conditional type as parent iterator, if the parent of parent node type is not RAS_DummyNode then we use RAS_UpwardNodeIterator<ParentNode> else RAS_DummyUpwardNodeIterator<ParentNode>. The last type is a iterator without any member to parent iterator, by this method we avoid using a pointer to avoid iterator recursion. The inter-node data are already used for mesh slot and display array bucket, mainly to get material data and vertex storage (VBO).
1 parent e7ef47b commit 0aad135

19 files changed

+483
-300
lines changed

source/gameengine/Ketsji/KX_BlenderMaterial.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -328,9 +328,9 @@ void KX_BlenderMaterial::DesactivateInstancing()
328328
}
329329
}
330330

331-
bool KX_BlenderMaterial::UsesLighting(RAS_Rasterizer *rasty) const
331+
bool KX_BlenderMaterial::UsesLighting() const
332332
{
333-
if (!RAS_IPolyMaterial::UsesLighting(rasty))
333+
if (!RAS_IPolyMaterial::UsesLighting())
334334
return false;
335335

336336
if (m_shader && m_shader->Ok())
@@ -914,7 +914,7 @@ KX_PYMETHODDEF_DOC(KX_BlenderMaterial, getShader, "getShader()")
914914
if (!m_shader->GetError()) {
915915
// Set the material to use custom shader.
916916
m_flag &= ~RAS_BLENDERGLSL;
917-
m_scene->GetBucketManager()->ReleaseDisplayLists(this);
917+
m_scene->GetBucketManager()->UpdateShaders(this);
918918
}
919919
}
920920

source/gameengine/Ketsji/KX_BlenderMaterial.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class KX_BlenderMaterial : public CValue, public RAS_IPolyMaterial
5151
virtual bool UseInstancing() const;
5252
virtual const std::string GetTextureName() const;
5353
virtual Material *GetBlenderMaterial() const;
54-
virtual bool UsesLighting(RAS_Rasterizer *rasty) const;
54+
virtual bool UsesLighting() const;
5555
virtual void GetRGBAColor(unsigned char *rgba) const;
5656
virtual Scene *GetBlenderScene() const;
5757
virtual SCA_IScene *GetScene() const;

source/gameengine/Ketsji/KX_PythonInit.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1092,7 +1092,7 @@ static PyObject *gPySetGLSLMaterialSetting(PyObject *,
10921092
// temporarily store the glsl settings in the scene for the GLSL materials
10931093
scene->GetBlenderScene()->gm.flag = gs->glslflag;
10941094
if (scene->GetBucketManager()) {
1095-
scene->GetBucketManager()->ReleaseDisplayLists();
1095+
scene->GetBucketManager()->UpdateShaders();
10961096
scene->GetBucketManager()->ReleaseMaterials();
10971097
}
10981098
}

source/gameengine/Rasterizer/Node/RAS_BaseNode.h

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,59 +27,67 @@
2727

2828
/** RAS_BaseNode is a class wrapping a rendering class by simulating it with a
2929
* binding and unbinding function.
30-
* \param InfoType The class to wrap functions from.
31-
* \param Leaf True if the node is a leaf of the tree.
32-
* \param Args The arguments type to pass to the binding and unbinding functions.
30+
* \param NodeInfo The node information.
3331
*/
34-
template <class InfoType, bool Leaf, class Args>
32+
template <class NodeInfo>
3533
class RAS_BaseNode
3634
{
3735
public:
36+
using OwnerType = typename NodeInfo::OwnerType;
37+
using TupleType = typename NodeInfo::TupleType;
38+
using DataType = typename NodeInfo::DataType;
39+
using Leaf = typename NodeInfo::Leaf;
40+
3841
/** The type of function to call for binding and unbinding.
39-
* It takes as arguments the class the node is wrapping and the structure
40-
* containing the arguments.
42+
* It takes as arguments the class the node is wrapping and the tuple
43+
* containing the data of the parent nodes.
4144
*/
42-
typedef std::function<void(InfoType *, const Args&)> Function;
45+
typedef std::function<void(OwnerType *, const TupleType&)> Function;
4346

4447
protected:
4548
/// An instance of the wrapped class.
46-
InfoType *m_info;
49+
OwnerType *m_owner;
50+
DataType *m_data;
4751

4852
Function m_bind;
4953
Function m_unbind;
5054

5155
public:
52-
RAS_BaseNode(InfoType *info, Function bind, Function unbind)
53-
:m_info(info),
56+
RAS_BaseNode(OwnerType *owner, DataType *data, Function bind, Function unbind)
57+
:m_owner(owner),
58+
m_data(data),
5459
m_bind(bind),
5560
m_unbind(unbind)
5661
{
5762
}
5863

59-
RAS_BaseNode()
64+
RAS_BaseNode() = default;
65+
66+
~RAS_BaseNode()
6067
{
6168
}
6269

63-
~RAS_BaseNode()
70+
inline OwnerType *GetOwner() const
6471
{
72+
return m_owner;
6573
}
6674

67-
inline InfoType *GetInfo() const
75+
inline DataType *GetData() const
6876
{
69-
return m_info;
77+
return m_data;
7078
}
7179

72-
inline void Bind(const Args& args)
80+
inline void Bind(const TupleType& tuple)
7381
{
7482
if (m_bind) {
75-
m_bind(m_info, args);
83+
m_bind(m_owner, tuple);
7684
}
7785
}
7886

79-
inline void Unbind(const Args& args)
87+
inline void Unbind(const TupleType& tuple)
8088
{
8189
if (m_unbind) {
82-
m_unbind(m_info, args);
90+
m_unbind(m_owner, tuple);
8391
}
8492
}
8593
};

source/gameengine/Rasterizer/Node/RAS_DownwardNode.h

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#define __RAS_DOWNWARD_NODE_H__
2525

2626
#include "RAS_BaseNode.h"
27+
#include "RAS_DummyNode.h"
2728

2829
#include <vector>
2930

@@ -41,26 +42,28 @@
4142
*
4243
* \param _ChildType The children node type.
4344
*/
44-
template <class _ChildType, class InfoType, bool Leaf, class Args>
45-
class RAS_DownwardNode : public RAS_BaseNode<InfoType, Leaf, Args>
45+
template <class NodeInfo, class _ChildType>
46+
class RAS_DownwardNode : public RAS_BaseNode<NodeInfo>
4647
{
4748
public:
48-
using typename RAS_BaseNode<InfoType, Leaf, Args>::Function;
49+
using typename RAS_BaseNode<NodeInfo>::OwnerType;
50+
using typename RAS_BaseNode<NodeInfo>::DataType;
51+
using typename RAS_BaseNode<NodeInfo>::TupleType;
52+
using typename RAS_BaseNode<NodeInfo>::Leaf;
53+
using typename RAS_BaseNode<NodeInfo>::Function;
4954
typedef _ChildType ChildType;
5055
typedef std::vector<ChildType *> ChildTypeList;
5156

5257
private:
5358
ChildTypeList m_children;
5459

5560
public:
56-
RAS_DownwardNode(InfoType *info, Function bind, Function unbind)
57-
:RAS_BaseNode<InfoType, Leaf, Args>(info, bind, unbind)
61+
RAS_DownwardNode(OwnerType *owner, DataType *data, Function bind, Function unbind)
62+
:RAS_BaseNode<NodeInfo>(owner, data, bind, unbind)
5863
{
5964
}
6065

61-
RAS_DownwardNode()
62-
{
63-
}
66+
RAS_DownwardNode() = default;
6467

6568
~RAS_DownwardNode()
6669
{
@@ -71,7 +74,7 @@ class RAS_DownwardNode : public RAS_BaseNode<InfoType, Leaf, Args>
7174
*/
7275
inline bool GetValid() const
7376
{
74-
if (!Leaf) {
77+
if (!Leaf()) {
7578
return m_children.size() > 0;
7679
}
7780
return true;
@@ -87,37 +90,52 @@ class RAS_DownwardNode : public RAS_BaseNode<InfoType, Leaf, Args>
8790

8891
inline void Clear()
8992
{
90-
if (!Leaf) {
93+
if (!Leaf()) {
9194
m_children.clear();
9295
}
9396
}
9497

9598
/** Recursive function calling the bind function, call itsefl in children nodes
9699
* and calling unbind function.
97-
* \param Args The function arguments to use for binding and unbinding.
100+
* \param tuple The function tuple argument to use for binding and unbinding.
98101
*/
99-
void Execute(const Args& args)
102+
template <class T = ChildType>
103+
inline typename std::enable_if<!std::is_same<T, RAS_DummyNode>::value, void>::type
104+
Execute(const TupleType& tuple)
100105
{
101-
this->Bind(args);
106+
this->Bind(tuple);
102107

108+
typename ChildType::TupleType childTuple(tuple, this->m_data);
103109
for (ChildType *child : m_children) {
104-
child->Execute(args);
110+
child->Execute(childTuple);
105111
}
106112

107-
this->Unbind(args);
113+
this->Unbind(tuple);
108114

109115
// In the same time we can remove the children nodes.
110116
Clear();
111117
}
112118

119+
/// Function override to avoid try creating a RAS_DummyNodeTuple with arguments.
120+
template <class T = ChildType>
121+
inline typename std::enable_if<std::is_same<T, RAS_DummyNode>::value, void>::type
122+
Execute(const TupleType& tuple)
123+
{
124+
this->Bind(tuple);
125+
126+
this->Unbind(tuple);
127+
128+
// No need to clear as dummy node are never instanced.
129+
}
130+
113131
#ifdef DEBUG
114-
void Print(unsigned short level, bool recursive)
132+
void Print(unsigned short level, bool recursive) const
115133
{
116134
for (unsigned short i = 0; i < level; ++i) {
117135
std::cout << "\t";
118136
}
119137

120-
std::cout << boost::typeindex::type_id<InfoType>().pretty_name() << "(" << this->m_info << ") "<< std::endl;
138+
std::cout << boost::typeindex::type_id<OwnerType>().pretty_name() << "(" << this->m_owner << ") "<< std::endl;
121139

122140
if (recursive) {
123141
for (ChildType *child : m_children) {

source/gameengine/Rasterizer/Node/RAS_DummyNode.h

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -23,39 +23,24 @@
2323
#ifndef __RAS_DUMMY_NODE_H__
2424
#define __RAS_DUMMY_NODE_H__
2525

26+
struct RAS_DummyNodeData
27+
{
28+
};
29+
30+
struct RAS_DummyNodeTuple
31+
{
32+
};
33+
2634
class RAS_DummyNode
2735
{
2836
public:
37+
using DataType = RAS_DummyNodeData;
38+
using TupleType = RAS_DummyNodeTuple;
2939
typedef RAS_DummyNode ParentType;
3040

3141
void Print(unsigned short level, bool recursive)
3242
{
3343
}
34-
35-
template <class Args>
36-
void Bind(const Args& args)
37-
{
38-
}
39-
40-
template <class Args>
41-
void Unbind(const Args& args)
42-
{
43-
}
44-
45-
template <class Args>
46-
void Execute(const Args& args)
47-
{
48-
}
49-
50-
ParentType *GetParent()
51-
{
52-
return nullptr;
53-
}
54-
55-
template <class NodeType>
56-
void AddChild(NodeType subNode)
57-
{
58-
}
5944
};
6045

6146
#endif // __RAS_DUMMY_NODE_H__

0 commit comments

Comments
 (0)