Subversion Repository Public Repository

Divide-Framework

This repository has no backups
This repository's network speed is throttled to 100KB/sec

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
/*
   Copyright (c) 2016 DIVIDE-Studio
   Copyright (c) 2009 Ionut Cava

   This file is part of DIVIDE Framework.

   Permission is hereby granted, free of charge, to any person obtaining a copy
   of this software
   and associated documentation files (the "Software"), to deal in the Software
   without restriction,
   including without limitation the rights to use, copy, modify, merge, publish,
   distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so,
   subject to the following conditions:

   The above copyright notice and this permission notice shall be included in
   all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED,
   INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
   PARTICULAR PURPOSE AND NONINFRINGEMENT.
   IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
   DAMAGES OR OTHER LIABILITY,
   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
   IN CONNECTION WITH THE SOFTWARE
   OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

   */

#ifndef _SCENE_GRAPH_NODE_H_
#define _SCENE_GRAPH_NODE_H_

#include "SceneNode.h"
#include "SGNRelationshipCache.h"
#include "Utility/Headers/StateTracker.h"
#include "Graphs/Components/Headers/IKComponent.h"
#include "Graphs/Components/Headers/BoundsComponent.h"
#include "Graphs/Components/Headers/RagdollComponent.h"
#include "Graphs/Components/Headers/PhysicsComponent.h"
#include "Graphs/Components/Headers/AnimationComponent.h"
#include "Graphs/Components/Headers/NavigationComponent.h"
#include "Graphs/Components/Headers/RenderingComponent.h"

namespace Divide {
class Transform;
class SceneGraph;
class SceneState;

// This is the scene root node. All scene node's are added to it as child nodes
class SceneRoot : public SceneNode {
   public:
    SceneRoot() : SceneNode("root", SceneNodeType::TYPE_ROOT)
    {
        _renderState.useDefaultMaterial(false);
        setState(ResourceState::RES_LOADED);
        _boundingBox.set(VECTOR3_UNIT, -VECTOR3_UNIT);

    }

    bool onRender(SceneGraphNode& sgn, RenderStage currentStage) {
        return true;
    }

    bool unload() { return true; }
    bool load() override {
        return true; 
    }

   protected:
    friend class SceneGraph;
    void postLoad(SceneGraphNode& sgn) { SceneNode::postLoad(sgn); }
};
TYPEDEF_SMART_POINTERS_FOR_CLASS(SceneRoot);
// Add as many SceneTransform nodes are needed as parent nodes for any scenenode
// to create complex transforms in the scene
class SceneTransform : public SceneNode {
   public:
    SceneTransform() : SceneNode("TransformNode", SceneNodeType::TYPE_TRANSFORM) {
        _renderState.useDefaultMaterial(false);
        setState(ResourceState::RES_LOADED);
    }

    bool onRender(RenderStage currentStage) { return true; }

    void postLoad(SceneGraphNode& sgn) { return; }
    bool unload() { return true; }
    bool load() override { return true; }
};

TYPEDEF_SMART_POINTERS_FOR_CLASS(SceneTransform);
TYPEDEF_SMART_POINTERS_FOR_CLASS(SceneGraphNode);

class SceneGraphNode : public GUIDWrapper,
                       private NonCopyable,
                       public std::enable_shared_from_this<SceneGraphNode> {
    static const size_t INITIAL_CHILD_COUNT = 128;
   public:
    /// Usage context affects lighting, navigation, physics, etc
    enum class UsageContext : U32 {
        NODE_DYNAMIC = 0,
        NODE_STATIC 
    };

    enum class SelectionFlag : U32 {
        SELECTION_NONE = 0,
        SELECTION_HOVER,
        SELECTION_SELECTED,
        SELECTION_COUNT
    };

    enum class UpdateFlag : U32 {
        SPATIAL_PARTITION = 0,
        COUNT
    };

    /// Called from SceneGraph "sceneUpdate"
    void sceneUpdate(const U64 deltaTime, SceneState& sceneState);
    /*Node Management*/
    /// Always use the level of redirection needed to reduce virtual function
    /// overhead
    /// Use getNode<SceneNode> if you need material properties for ex. or
    /// getNode<SubMesh> for animation transforms
    template <typename T = SceneNode>
    inline std::shared_ptr<T> getNode() const {
        static_assert(std::is_base_of<SceneNode, T>::value,
                      "SceneGraphNode::getNode error: Invalid target node type!");
        return std::static_pointer_cast<T>(_node);
    }
    /// Add node increments the node's ref counter if the node was already added
    /// to the scene graph
    SceneGraphNode_ptr addNode(const SceneNode_ptr& node, U32 componentMask, PhysicsGroup physicsGroup, const stringImpl& name = "");
    SceneGraphNode_ptr registerNode(SceneGraphNode_ptr node);
    /// If recursive is true, this stops on the first node match
    bool removeNode(SceneGraphNode& node, bool recursive = true);
    
    /// Find a node in the graph based on the SceneGraphNode's name
    /// If sceneNodeName = true, find a node in the graph based on the
    /// SceneNode's name
    SceneGraphNode_wptr findNode(const stringImpl& name, bool sceneNodeName = false);
    /// Find a child Node using the given name (either SGN name or SceneNode name)
    SceneGraphNode_wptr findChild(const stringImpl& name, bool sceneNodeName = false, bool recursive = false);
    /// Find a child using the give GUID
    SceneGraphNode_wptr findChild(I64 GUID, bool recursive = false);
    /// Find the graph nodes whom's bounding boxes intersects the given ray
    void intersect(const Ray& ray, F32 start, F32 end,
                   vectorImpl<SceneGraphNode_cwptr>& selectionHits,
                   bool recursive = true) const;

    inline void onCollisionCbk(const DELEGATE_CBK_PARAM<SceneGraphNode_cptr>& cbk) {
        _collisionCbk = cbk;
    }

    /// Selection helper functions
    void setSelectionFlag(SelectionFlag flag);
    inline SelectionFlag getSelectionFlag() const { return _selectionFlag; }

    void setSelectable(const bool state);
    inline bool isSelectable() const { return _isSelectable; }

    void lockVisibility(const bool state);
    inline bool visibilityLocked() const { return _visibilityLocked; }

    const stringImpl& getName() const { return _name; }
    /*Node Management*/

    /*Parent <-> Children*/
    inline SceneGraphNode_wptr getParent() const {
        return _parent;
    }

    void setParent(SceneGraphNode& parent);

    /*Node State*/
    void setActive(const bool state);
    inline bool isActive() const { return _active; }

    inline const UsageContext& usageContext() const { return _usageContext; }
    void usageContext(const UsageContext& newContext);

    inline U64 getElapsedTime() const { return _elapsedTime; }

    template <typename T>
    inline T* get() const {
        static_assert(false, "INVALID COMPONENT");
        return nullptr;
    }

    inline StateTracker<bool>& getTrackedBools() { return _trackedBools; }

    bool isChildOfType(U32 typeMask, bool ignoreRoot) const;
    bool isRelated(const SceneGraphNode& target) const;
    bool isChild(const SceneGraphNode& target, bool recursive) const;

    inline bool hasChildren() const {
        return getChildCount() > 0;
    }

    inline SceneGraphNode& getChild(U32 idx, U32& updatedChildCount) {
        ReadLock r_lock(_childLock);
        updatedChildCount = getChildCount();
        assert(idx < updatedChildCount);
        const SceneGraphNode_ptr& child = _children.at(idx);
        assert(child);
        return *child;
    }

    inline const SceneGraphNode& getChild(U32 idx, U32& updatedChildCount) const {
        ReadLock r_lock(_childLock);
        updatedChildCount = getChildCount();
        assert(idx < updatedChildCount);
        const SceneGraphNode_ptr& child = _children.at(idx);
        assert(child);
        return *child;
    }

    inline U32 getChildCount() const {
        return _childCount;
    }

    inline bool getFlag(UpdateFlag flag) const {
        return _updateFlags[to_uint(flag)];
    }

    inline void clearUpdateFlag(UpdateFlag flag) {
        _updateFlags[to_uint(flag)] = false;
    }

    bool operator==(const SceneGraphNode_ptr& other) const {
        return this->getGUID() == other->getGUID();
    }

    bool operator!=(const SceneGraphNode_ptr& other) const {
        return this->getGUID() != other->getGUID();
    }

   /*protected:
    SET_DELETE_FRIEND
    SET_SAFE_UPDATE_FRIEND
    SET_DELETE_VECTOR_FRIEND
    SET_DELETE_HASHMAP_FRIEND

    friend class SceneGraph;
    friend class std::shared_ptr<SceneGraphNode> ;*/
    explicit SceneGraphNode(SceneGraph& sceneGraph,
                            PhysicsGroup physicsGroup,
                            const SceneNode_ptr& node,
                            const stringImpl& name,
                            U32 componentMask);
    ~SceneGraphNode();

    bool operator==(const SceneGraphNode& rhs) const {
        return getGUID() == rhs.getGUID();
    }

    bool operator!=(const SceneGraphNode& rhs) const {
        return getGUID() != rhs.getGUID();
    }

    void postLoad();

    inline SceneGraph& parentGraph() {
        return _sceneGraph;
    }

    inline const SceneGraph& parentGraph() const {
        return _sceneGraph;
    }

   protected:
    friend class RenderPassCuller;
    // Returns true if the node should be culled (is not visible for the current stage)
    bool cullNode(const Camera& currentCamera,
                  F32 maxDistanceFromCamera,
                  RenderStage currentStage,
                  Frustum::FrustCollision& collisionTypeOut) const;

   protected:
    friend class RenderingComponent;
    bool prepareDraw(const SceneRenderState& sceneRenderState,
                     RenderStage renderStage);

   protected:
    friend class SceneGraph;
    void frameEnded();
    void onCameraUpdate(const I64 cameraGUID,
                        const vec3<F32>& posOffset,
                        const mat4<F32>& rotationOffset);

    inline void setUpdateFlag(UpdateFlag flag) {
        _updateFlags[to_uint(flag)] = true;
    }

    void sgnUpdate(const U64 deltaTime, SceneState& sceneState);

    void getOrderedNodeList(vectorImpl<SceneGraphNode*>& nodeList);

   protected:
    friend class Octree;
    void onCollision(SceneGraphNode_cwptr collider);

   private:
    void onTransform();
    bool filterCollission(const SceneGraphNode& node);
    inline void setName(const stringImpl& name) { 
        _name = name;
    }

    void setComponent(SGNComponent::ComponentType type, SGNComponent* component);

    inline U32 getComponentIdx(SGNComponent::ComponentType type) const {
        return powerOfTwo(to_uint(type)) - 1;
    }

    inline SGNComponent* getComponent(SGNComponent::ComponentType type) const {
        return _components[getComponentIdx(type)];
    }
   private:
    friend class SGNRelationshipCache;
    inline const SGNRelationshipCache& relationshipCache() const {
        return _relationshipCache;
    }
    void invalidateRelationshipCache();

    inline bool isHelperNode(const SceneNode& node) const {
        return node.getType() == SceneNodeType::TYPE_ROOT ||
               node.getType() == SceneNodeType::TYPE_TRANSFORM;
    }

   private:
    // An SGN doesn't exist outside of a scene graph
    SceneGraph& _sceneGraph;

    D64 _updateTimer;
    U64 _elapsedTime;
    stringImpl _name;
    SceneNode_ptr _node;
    SceneGraphNode_wptr _parent;
    vectorImpl<SceneGraphNode_ptr> _children;
    std::atomic_uint _childCount;
    mutable SharedLock _childLock;
    std::atomic<bool> _active;
    std::atomic<bool> _visibilityLocked;
    std::array<std::atomic<bool>, to_const_uint(UpdateFlag::COUNT)> _updateFlags;

    bool _isSelectable;
    SelectionFlag _selectionFlag;

    UsageContext _usageContext;

    StateTracker<bool> _trackedBools;

    DELEGATE_CBK_PARAM<SceneGraphNode_cptr> _collisionCbk;

    std::array<SGNComponent*, to_const_uint(SGNComponent::ComponentType::COUNT)> _components;
    SGNRelationshipCache _relationshipCache;
};

template <>
inline AnimationComponent* SceneGraphNode::get() const {
    return static_cast<AnimationComponent*>(getComponent(SGNComponent::ComponentType::ANIMATION));
}

template <>
inline IKComponent* SceneGraphNode::get() const {
    return static_cast<IKComponent*>(getComponent(SGNComponent::ComponentType::INVERSE_KINEMATICS));
}

template <>
inline RagdollComponent* SceneGraphNode::get() const {
    return static_cast<RagdollComponent*>(getComponent(SGNComponent::ComponentType::RAGDOLL));
}

template <>
inline BoundsComponent* SceneGraphNode::get() const {
    return static_cast<BoundsComponent*>(getComponent(SGNComponent::ComponentType::BOUNDS));
}

template <>
inline NavigationComponent* SceneGraphNode::get() const {
    return static_cast<NavigationComponent*>(getComponent(SGNComponent::ComponentType::NAVIGATION));
}

template <>
inline PhysicsComponent* SceneGraphNode::get() const {
    return static_cast<PhysicsComponent*>(getComponent(SGNComponent::ComponentType::PHYSICS));
}

template <>
inline RenderingComponent* SceneGraphNode::get() const {
    return static_cast<RenderingComponent*>(getComponent(SGNComponent::ComponentType::RENDERING));
}

};  // namespace Divide
#endif

Commits for Divide-Framework/trunk/Source Code/Graphs/Headers/SceneGraphNode.h

Diff revisions: vs.
Revision Author Commited Message
750 Diff Diff IonutCava picture IonutCava Thu 07 Jul, 2016 16:02:03 +0000

[IonutCava]
- Static analysis based fixes and improvements

742 Diff Diff IonutCava picture IonutCava Mon 27 Jun, 2016 16:16:12 +0000

[IonutCava]
- Small performance tweaks

741 Diff Diff IonutCava picture IonutCava Sun 26 Jun, 2016 18:01:25 +0000

[IonutCava]
- Properly wait for all pending tasks to finish before shutdown
- Add a reset method to the FrameRateHandler
- Rework glQuery system.
- Avoid mipmap generation on the current luma render target

738 Diff Diff IonutCava picture IonutCava Fri 24 Jun, 2016 16:06:04 +0000

[IonutCava]
- Performance improvement: Create linear list of ordered SGNs for update and split update step in two to allow parallel tasks in the first step to finish before moving to second step
- Performance improvement: Remove glFlush calls for lock manager. Drivers should be up to the task now
- Performance improvement: Re-enabled round robin buffer system for ParticleEmitter

727 Diff Diff IonutCava picture IonutCava Tue 14 Jun, 2016 16:01:38 +0000

[IonutCava]
- Remove node and cmd buffers from GFXDevice and add them as a new BufferData struct to RenderPass class.
— Each render pass holds its own buffers
- Improvements / fixes to the CSM code
- Added a global toggle to enable/disable custom memory allocators

720 Diff Diff IonutCava picture IonutCava Mon 06 Jun, 2016 15:51:06 +0000

[IonutCava]
- PVS-Studio guided static analysis fixes and optimizations
- Added a flag to SceneState to bypass the Save/Load system not needed for certain types of scenes (menus, cinematics, etc)

713 Diff Diff IonutCava picture IonutCava Wed 25 May, 2016 15:43:38 +0000

[IonutCava]
- Removed all unique_ptr’s from the code with classic new/delete pairs. They were seriously not needed.
- Added the concept of SceneComponent to scene specific classes: aiManager, lightPool, sceneGraph, physicsInterface etc
— This allowed the removal of the global GET_ACTIVE_SCENEGRAPH call;

709 Diff Diff IonutCava picture IonutCava Thu 19 May, 2016 16:21:46 +0000

[IonutCava]
- Massive rewrite of the resource system:
— ResourceCache now uses a map of weak pointers and passes shared pointers to the call point of CreateResource
— RemoveResource is no longer needed, but resource based smart pointers use a custom deleter that calls unload()
— Keep a shared_ptr of the resource in the entity that needs it and pass shared_ptr references from getter methods
-— All of this removed the need for calls to RemoveResource, REGISTER_TRACKED_DEPENDENCY and UNREGISTER_TRACKED_DEPENDENCY reducing the number of mutex locks and atomic exchanges
- Singleton cleanup:
— Removed ShaderManager singleton and merged it’s data and responsibilities in static methods in both ShaderProgram and Shader classes.
Explanation: Due to the complex interdependency chains in the system, copying, updating, tracking the cache in a thread safe way became a lot more slower than a straight forward smart pointer based implementation. (e.g. scene graph nodes have 3d objects and material instances, 3d objects have materials, materials have textures and shaders, etc)

708 Diff Diff IonutCava picture IonutCava Tue 17 May, 2016 14:06:13 +0000

[IonutCava]
- Fixed reference counter getting out of sync between multiple scene graphs and the ResourceCache
- Added per SGN update flags for SceneNodes
- Fixed some memory leaks (caught by the ResourceCache)

705 IonutCava picture IonutCava Thu 12 May, 2016 20:27:20 +0000

[IonutCava]
- Decouple asset loading from the active scene
— completely remove GET_ACTIVE_SCENE() method