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
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
/*
   Copyright (c) 2017 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/UnitComponent.h"
#include "Graphs/Components/Headers/BoundsComponent.h"
#include "Graphs/Components/Headers/RagdollComponent.h"
#include "Graphs/Components/Headers/PhysicsComponent.h"
#include "Graphs/Components/Headers/RenderingComponent.h"
#include "Graphs/Components/Headers/AnimationComponent.h"
#include "Graphs/Components/Headers/NavigationComponent.h"
#include "Graphs/Components/Headers/NetworkingComponent.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(ResourceCache& parentCache)
        : SceneNode(parentCache, "root", SceneNodeType::TYPE_ROOT)
    {
        _renderState.useDefaultMaterial(false);
        setState(ResourceState::RES_LOADED);
        _boundingBox.set(VECTOR3_UNIT, -VECTOR3_UNIT);

    }

    bool onRender(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(ResourceCache& parentCache, vec3<F32> extents) 
        : SceneNode(parentCache, "TransformNode", SceneNodeType::TYPE_TRANSFORM),
          _extents(extents)
    {
        _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; }

    inline void updateBoundsInternal(SceneGraphNode& sgn) override {
        _boundingBox.setMin(-_extents * 0.5f);
        _boundingBox.setMax( _extents * 0.5f);
    }

  protected:
    vec3<F32> _extents;
};

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. 
    /// If this function returns true, the node will no longer be part of the scene hierarchy.
    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<void, 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;

    void forEachChild(const DELEGATE_CBK<void, SceneGraphNode&>& callback);
    void forEachChild(const DELEGATE_CBK<void, const SceneGraphNode&>& callback) const;

    //Returns false if the loop was interrupted
    bool forEachChildInterruptible(const DELEGATE_CBK<bool, SceneGraphNode&>& callback);
    //Returns false if the loop was interrupted
    bool forEachChildInterruptible(const DELEGATE_CBK<bool, const SceneGraphNode&>& callback) const;

    void forEachChild(const DELEGATE_CBK<void, SceneGraphNode&, I32>& callback, U32 start, U32 end);
    void forEachChild(const DELEGATE_CBK<void, const SceneGraphNode&, I32>& callback, U32 start, U32 end) const;
    //Returns false if the loop was interrupted
    bool forEachChildInterruptible(const DELEGATE_CBK<bool, SceneGraphNode&, I32>& callback, U32 start, U32 end);
    //Returns false if the loop was interrupted
    bool forEachChildInterruptible(const DELEGATE_CBK<bool, const SceneGraphNode&, I32>& callback, U32 start, U32 end) const;

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

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

    inline const SceneGraphNode& getChild(U32 idx) const {
        ReadLock r_lock(_childLock);
        assert(idx <  getChildCount());
        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);

    void onCameraChange(const Camera& cam);

    void onNetworkSend(U32 frameCount);

    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<void, 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));
}

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

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

};  // namespace Divide
#endif

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

Diff revisions: vs.
Revision Author Commited Message
842 Diff Diff IonutCava picture IonutCava Wed 01 Feb, 2017 17:25:15 +0000

[IonutCava]
- Start to implement scripting support via ChaiScript: http://chaiscript.com/
- Cleanup DELEGATE_CBK alias

838 Diff Diff IonutCava picture IonutCava Mon 30 Jan, 2017 17:28:35 +0000

[IonutCava]
- Added a NetworkingComponent to SGNs
- Started cleaning up Client / Server architecture

836 Diff Diff IonutCava picture IonutCava Fri 27 Jan, 2017 14:59:56 +0000

[IonutCava]
- Update copyright notice

827 Diff Diff IonutCava picture IonutCava Sun 22 Jan, 2017 21:59:36 +0000

[IonutCava]
- ShaderBuffers now decide heuristically if they get persistently mapped or not (depends on size. Current limit is 512Kb for subData calls.
- Separate visible node command generation into 2 steps: onRender and getDrawPackage. onRender allows the creation of parallel tasks that should finish by the time the second call, getDrawPackage reaches the same node
- Update ParticleEmitter to take into account multiple players and increase parallelism at the cost of memory consumption and complexity.
- Add a default bounding box for Players (add extents to SceneTransform nodes)
- All buffers (ShaderBuffer, d3dConstantBuffer, glUniformBuffer, glBufferImpl, glGenericBuffer, etc) use BufferParams for creation.
— Constructor and create calls have been merged together

822 Diff Diff IonutCava picture IonutCava Tue 17 Jan, 2017 22:47:06 +0000

[IonutCava]
- Fix postFX per player rendering
- Fix player remove code (wasn’t removing nodes)

821 Diff Diff IonutCava picture IonutCava Tue 17 Jan, 2017 17:15:45 +0000

[IonutCava]
- Profile guided optimizations

817 Diff Diff IonutCava picture IonutCava Sun 15 Jan, 2017 21:29:59 +0000

[IonutCava]
- Add a new Unit component to SGNs that holds NPC/Player/etc. objects
- Add support for multiple keyboard+mouse combos and joysticks and add mapping between these and players

804 Diff Diff IonutCava picture IonutCava Thu 01 Dec, 2016 17:20:59 +0000

[IonutCava]
- Singleton elimination update Part I: get it to compile
— The following classes are no longer Singletons: GFXDevice, GL_API, DX_API, SFXWrapper, FmodWrapper, SDLWrapper, ALWrapper, PXDevice, InputInterface, RenderPassManager, SceneManager and ResourceManager;
— Refactor system to a Context / Component based implementation (Pass relevant context to objects: e.g. GFXDevice object to Textures, GUI to GUIElements, etc)
— Make devices and managers components of the kernel
— Allow multiple Resource caches to co-exist. This may prove useful for later when a more fragmented memory model is need (per frame / per scene / global caches / etc)

  • next steps: part II – cleanup/refactor new code, part III – optimise code, part IV – remove remaining Singletons (e.g. Application, ParamHandler, FrameListenerManager, Recast, PostFX and DebugInterface)
794 Diff Diff IonutCava picture IonutCava Tue 22 Nov, 2016 16:44:26 +0000

[IonutCava]
- Change SDL_GL_Context management from a pool-based system to a thread_local variable type System
- Reworked SceneGraphNode child access for safer and faster iteration.
— Added a forEachChild with multiple overloads to apply a lambda expression over every child of the target SGN
- Slight optimization to Text rendering by batching all labels due for rendering and submitting them at all at once

773 IonutCava picture IonutCava Tue 04 Oct, 2016 15:53:18 +0000

[IonutCava]
- Split GenericDrawCommand gathering system into Init/Update to facilitate future threading support
- Fix drawCount() == 0 case in submitRenderCommand
- Make _cameraPool (more) threadsafe