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
/*
   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_NODE_H_
#define _SCENE_NODE_H_

#include "SceneNodeRenderState.h"
#include "Rendering/Camera/Headers/Frustum.h"
#include "Core/Resources/Headers/Resource.h"
#include "Core/Math/BoundingVolumes/Headers/BoundingBox.h"
#include "Core/Math/BoundingVolumes/Headers/BoundingSphere.h"
#include "Platform/Video/Headers/RenderAPIWrapper.h"

namespace Divide {
class Scene;
class Camera;
class SceneState;
class SceneRenderState;
enum class RenderStage : U32;

FWD_DECLARE_MANAGED_CLASS(SceneGraphNode);
FWD_DECLARE_MANAGED_CLASS(Material);
namespace Attorney {
    class SceneNodeSceneGraph;
};

enum class SceneNodeType : U32 {
    TYPE_ROOT = toBit(1),       //< root node
    TYPE_OBJECT3D = toBit(2),   //< 3d objects in the scene
    TYPE_TRANSFORM = toBit(3),  //< dummy node to stack multiple transforms
    TYPE_WATER = toBit(4),      //< water node
    TYPE_LIGHT = toBit(5),      //< a scene light
    TYPE_TRIGGER = toBit(6),    //< a scene trigger (perform action on contact)
    TYPE_PARTICLE_EMITTER = toBit(7),   //< a particle emitter
    TYPE_SKY = toBit(8),                //< sky node
    TYPE_VEGETATION_GRASS = toBit(9),   //< grass node
    TYPE_VEGETATION_TREES = toBit(10),  //< trees node (to do later)
    COUNT                               //< Place types above
                                        
};

class NOINITVTABLE SceneNode : public Resource {
    friend class Attorney::SceneNodeSceneGraph;
   public:
      enum class UpdateFlag : U32 {
        BOUNDS_CHANGED = 0,
        COUNT
      };

   protected:
    class SGNParentData {
    public:
        explicit SGNParentData(I64 sgnGUID) : _GUID(sgnGUID)
        {
            _updateFlags.fill(true);
        }

        inline I64 sgnGUID() const { return _GUID; }

        inline bool getFlag(UpdateFlag flag) const { return _updateFlags[to_uint(flag)]; }
        inline void clearFlag(UpdateFlag flag) { _updateFlags[to_uint(flag)] = false; }
        inline void setFlag(UpdateFlag flag) { _updateFlags[to_uint(flag)] = true; }

    private:
        I64 _GUID;
        std::array<bool, to_const_uint(UpdateFlag::COUNT)> _updateFlags;
    };

   public:
    explicit SceneNode(ResourceCache& parentCache, const stringImpl& name, const SceneNodeType& type);
    explicit SceneNode(ResourceCache& parentCache, const stringImpl& name, const stringImpl& resourceLocation, const SceneNodeType& type);
    virtual ~SceneNode();

    /// Perform any pre-draw operations (this is after sort and transform updates)
    /// If the node isn't ready for rendering and should be skipped this frame,
    /// the return value is false
    virtual bool onRender(RenderStage currentStage) = 0;
    virtual bool getDrawState() const { return _renderState.getDrawState(); }
    /// Some SceneNodes may need special case handling. I.E. water shouldn't
    /// render itself in REFLECTION
    virtual bool getDrawState(RenderStage currentStage);

    virtual void initialiseDrawCommands(SceneGraphNode& sgn,
                                        RenderStage renderStage,
                                        GenericDrawCommands& drawCommandsInOut);
    virtual void updateDrawCommands(SceneGraphNode& sgn,
                                    RenderStage renderStage,
                                    const SceneRenderState& sceneRenderState,
                                    GenericDrawCommands& drawCommandsInOut);
    /*//Rendering/Processing*/

    virtual bool unload();
    virtual void setMaterialTpl(const Material_ptr& material);
    const Material_ptr& getMaterialTpl();

    inline void setType(const SceneNodeType& type) { _type = type; }
    inline const SceneNodeType& getType() const { return _type; }

    inline SceneNodeRenderState& renderState() { return _renderState; }

    inline void incLODcount() { _LODcount++; }
    inline void decLODcount() { _LODcount--; }
    inline U8   getLODcount() const { return _LODcount; }

    ResourceCache& parentResourceCache() { return _parentCache; }
    const ResourceCache& parentResourceCache() const { return _parentCache; }

   protected:
    /// Called from SceneGraph "sceneUpdate"
    virtual void sceneUpdate(const U64 deltaTime, SceneGraphNode& sgn,
                             SceneState& sceneState);
    /// Called as a second pass after sceneUpdate
    virtual void sgnUpdate(const U64 deltaTime, SceneGraphNode& sgn,
                           SceneState& sceneState);
    // Post insertion calls (Use this to setup child objects during creation)
    virtual void postLoad(SceneGraphNode& sgn);
    virtual void updateBoundsInternal(SceneGraphNode& sgn);

    inline void setFlag(UpdateFlag flag) {
        for (SGNParentData& data : _sgnParents) {
            data.setFlag(flag);
        }
    }

    inline vectorImpl<SceneNode::SGNParentData>::iterator getSGNData(I64 sgnGUID) {
        vectorImpl<SceneNode::SGNParentData>::iterator it;
        it = std::find_if(std::begin(_sgnParents), std::end(_sgnParents),
            [&sgnGUID](SceneNode::SGNParentData sgnIter) {
                return (sgnIter.sgnGUID() == sgnGUID);
            });
        return it;
    }

    inline vectorImpl<SceneNode::SGNParentData>::const_iterator getSGNData(I64 sgnGUID) const {
        return getSGNData(sgnGUID);
    }

    virtual void onCameraUpdate(SceneGraphNode& sgn,
                                const I64 cameraGUID,
                                const vec3<F32>& posOffset,
                                const mat4<F32>& rotationOffset);
    virtual void onCameraChange(SceneGraphNode& sgn,
                                const Camera& cam);
   protected:
    ResourceCache& _parentCache;
    /// The various states needed for rendering
    SceneNodeRenderState _renderState;
    /// Maximum available LOD levels
    U8 _LODcount;
    /// The initial bounding box as it was at object's creation (i.e. no transforms applied)
    BoundingBox _boundingBox;

   private:
    SceneNodeType _type;
    Material_ptr _materialTemplate;

    vectorImpl<SGNParentData> _sgnParents;
};

TYPEDEF_SMART_POINTERS_FOR_CLASS(SceneNode);

namespace Attorney {
class SceneNodeSceneGraph {
   private:
    static void postLoad(SceneNode& node, SceneGraphNode& sgn) {
        node.postLoad(sgn);
    }
    
    static void sceneUpdate(SceneNode& node, const U64 deltaTime,
                            SceneGraphNode& sgn, SceneState& sceneState) {
        node.sceneUpdate(deltaTime, sgn, sceneState);
    }

    static void sgnUpdate(SceneNode& node, const U64 deltaTime,
                          SceneGraphNode& sgn, SceneState& sceneState) {
        node.sgnUpdate(deltaTime, sgn, sceneState);
    }
    
    static void registerSGNParent(SceneNode& node, I64 sgnGUID) {
        // prevent double add
        vectorImpl<SceneNode::SGNParentData>::const_iterator it;
        it = node.getSGNData(sgnGUID);
        assert(it == std::cend(node._sgnParents));

        node._sgnParents.push_back(SceneNode::SGNParentData(sgnGUID));
    }

    static void unregisterSGNParent(SceneNode& node, I64 sgnGUID) {
        // prevent double remove
        vectorImpl<SceneNode::SGNParentData>::const_iterator it;
        it = node.getSGNData(sgnGUID);
        assert(it != std::cend(node._sgnParents));

        node._sgnParents.erase(it);
    }

    static size_t parentCount(const SceneNode& node) {
        return node._sgnParents.size();
    }


    static void onCameraUpdate(SceneGraphNode& sgn,
                               SceneNode& node,
                               const I64 cameraGUID,
                               const vec3<F32>& posOffset,
                               const mat4<F32>& rotationOffset) {
        node.onCameraUpdate(sgn, cameraGUID, posOffset, rotationOffset);
    }

    static void onCameraChange(SceneGraphNode& sgn,
                               SceneNode& node,
                               const Camera& cam) {
        node.onCameraChange(sgn, cam);
    }

    friend class Divide::SceneGraphNode;
};
};  // namespace Attorney
};  // namespace Divide
#endif

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

Diff revisions: vs.
Revision Author Commited Message
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

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)
777 Diff Diff IonutCava picture IonutCava Fri 07 Oct, 2016 16:14:48 +0000

[IonutCava]
- Continue to implement CommandBuffer / RenderPass / RenderSubPass system.
— Rendering artefacts are still present.

773 Diff Diff 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

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

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)

710 Diff Diff IonutCava picture IonutCava Fri 20 May, 2016 16:24:40 +0000

[IonutCava]
- Code cleanup
- Initial work on Scene loading and unloading with and without unloading assets:
— Need to change AIManager from a Singleton to a per-scene component

709 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)