Panda3D
tagStateManager.cxx
1 /**
2  *
3  * RenderPipeline
4  *
5  * Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  *
25  */
26 
27 
28 #include "tagStateManager.h"
29 
30 using std::endl;
31 
32 
33 NotifyCategoryDef(tagstatemgr, "");
34 
35 /**
36  * @brief Constructs a new TagStateManager
37  * @details This constructs a new TagStateManager. The #main_cam_node should
38  * refer to the main scene camera, and will most likely be base.cam.
39  * It is necessary to pass the camera because the C++ code does not have
40  * access to the showbase.
41  *
42  * @param main_cam_node The main scene camera
43  */
45 TagStateManager(NodePath main_cam_node) {
46  nassertv(!main_cam_node.is_empty());
47  nassertv(DCAST(Camera, main_cam_node.node()) != nullptr);
48  _main_cam_node = main_cam_node;
49 
50  // Set default camera mask
51  DCAST(Camera, _main_cam_node.node())->set_camera_mask(BitMask32::bit(1));
52 
53  // Init containers
54  _containers["shadow"] = StateContainer("Shadows", 2, false);
55  _containers["voxelize"] = StateContainer("Voxelize", 3, false);
56  _containers["envmap"] = StateContainer("Envmap", 4, true);
57  _containers["forward"] = StateContainer("Forward", 5, true);
58 }
59 
60 /**
61  * @brief Destructs the TagStateManager
62  * @details This destructs the TagStateManager, and cleans up all resources used.
63  */
67 }
68 
69 /**
70  * @brief Applies a given state to a NodePath
71  * @details This applies a shader to the given NodePath which is used when the
72  * NodePath is rendered by any registered camera of the container.
73  *
74  * @param container The container which is used to store the state
75  * @param np The nodepath to apply the shader to
76  * @param shader A handle to the shader to apply
77  * @param name Name of the state, should be a unique identifier
78  * @param sort Changes the sort with which the shader will be applied.
79  */
81 apply_state(StateContainer& container, NodePath np, Shader* shader,
82  const std::string &name, int sort) {
83  if (tagstatemgr_cat.is_spam()) {
84  tagstatemgr_cat.spam() << "Constructing new state " << name
85  << " with shader " << shader << endl;
86  }
87 
88  // Construct the render state
89  CPT(RenderState) state = RenderState::make_empty();
90 
91  // Disable color write for all stages except the environment container
92  if (!container.write_color) {
93  state = state->set_attrib(ColorWriteAttrib::make(ColorWriteAttrib::C_off), 10000);
94  }
95  state = state->set_attrib(ShaderAttrib::make(shader, sort), sort);
96 
97  // Emit a warning if we override an existing state
98  if (container.tag_states.count(name) != 0) {
99  tagstatemgr_cat.warning() << "Overriding existing state " << name << endl;
100  }
101 
102  // Store the state, this is required whenever we attach a new camera, so
103  // it can also track the existing states
104  container.tag_states[name] = state;
105 
106  // Save the tag on the node path
107  np.set_tag(container.tag_name, name);
108 
109  // Apply the state on all cameras which are attached so far
110  for (size_t i = 0; i < container.cameras.size(); ++i) {
111  container.cameras[i]->set_tag_state(name, state);
112  }
113 }
114 
115 /**
116  * @brief Cleans up all registered states.
117  * @details This cleans up all states which were registered to the TagStateManager.
118  * It also calls Camera::clear_tag_states() on the main_cam_node and all attached
119  * cameras.
120  */
123  if (tagstatemgr_cat.is_info()) {
124  tagstatemgr_cat.info() << "cleaning up states" << endl;
125  }
126 
127  // Clear all tag states of the main camera
128  DCAST(Camera, _main_cam_node.node())->clear_tag_states();
129 
130  // Clear the containers
131  // XXX: Just iterate over the _container map
132  cleanup_container_states(_containers["shadow"]);
133  cleanup_container_states(_containers["voxelize"]);
134  cleanup_container_states(_containers["envmap"]);
135  cleanup_container_states(_containers["forward"]);
136 }
137 
138 /**
139  * @brief Cleans up the states of a given container
140  * @details This cleans all tag states of the given container,
141  * and also calls Camera::clear_tag_states on every assigned camera.
142  *
143  * @param container Container to clear
144  */
145 void TagStateManager::
146 cleanup_container_states(StateContainer& container) {
147  for (size_t i = 0; i < container.cameras.size(); ++i) {
148  container.cameras[i]->clear_tag_states();
149  }
150  container.tag_states.clear();
151 }
152 
153 /**
154  * @brief Registers a new camera to a given container
155  * @details This registers a new camera to a container, and sets its initial
156  * state as well as the camera mask.
157  *
158  * @param container The container to add the camera to
159  * @param source The camera to add
160  */
162 register_camera(StateContainer& container, Camera* source) {
163  source->set_tag_state_key(container.tag_name);
164  source->set_camera_mask(container.mask);
165 
166  // Construct an initial state which also disables color write, additionally
167  // to the ColorWriteAttrib on each unique state.
168  CPT(RenderState) state = RenderState::make_empty();
169 
170  if (!container.write_color) {
171  state = state->set_attrib(ColorWriteAttrib::make(ColorWriteAttrib::C_off), 10000);
172  }
173  source->set_initial_state(state);
174 
175  // Store the camera so we can keep track of it
176  container.cameras.push_back(source);
177 }
178 
179 /**
180  * @brief Unregisters a camera from a container
181  * @details This unregisters a camera from the list of cameras of a given
182  * container. It also resets all tag states of the camera, and also its initial
183  * state.
184  *
185  * @param source Camera to unregister
186  */
188 unregister_camera(StateContainer& container, Camera* source) {
189  CameraList& cameras = container.cameras;
190 
191  // Make sure the camera was attached so far
192  if (std::find(cameras.begin(), cameras.end(), source) == cameras.end()) {
193  tagstatemgr_cat.error()
194  << "Called unregister_camera but camera was never registered!" << endl;
195  return;
196  }
197 
198  // Remove the camera from the list of attached cameras
199  cameras.erase(std::remove(cameras.begin(), cameras.end(), source), cameras.end());
200 
201  // Reset the camera
202  source->clear_tag_states();
203  source->set_initial_state(RenderState::make_empty());
204 }
static BitMask< WType, nbits > bit(int index)
Returns a BitMask with only the indicated bit on.
Definition: bitMask.I:70
void clear_tag_states()
Removes all associations established by previous calls to set_tag_state().
Definition: camera.cxx:123
TagStateManager(NodePath main_cam_node)
Constructs a new TagStateManager.
bool is_empty() const
Returns true if the NodePath contains no nodes.
Definition: nodePath.I:188
set_initial_state
Sets the initial state which is applied to all nodes in the scene, as if it were set at the top of th...
Definition: camera.h:79
void unregister_camera(const std::string &state, Camera *source)
Unregisters a camera from the list of shadow cameras.
~TagStateManager()
Destructs the TagStateManager.
Definition: shader.h:49
void set_tag(const std::string &key, const std::string &value)
Associates a user-defined value with a user-defined key which is stored on the node.
Definition: nodePath.I:1989
void apply_state(const std::string &state, NodePath np, Shader *shader, const std::string &name, int sort)
Applies a given state for a pass to a NodePath.
set_camera_mask
Changes the set of bits that represent the subset of the scene graph the camera will render.
Definition: camera.h:63
void cleanup_states()
Cleans up all registered states.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:47
PandaNode * node() const
Returns the referenced node of the path.
Definition: nodePath.I:227
A node that can be positioned around in the scene graph to represent a point of view for rendering a ...
Definition: camera.h:35
void register_camera(const std::string &state, Camera *source)
RenderPipeline.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:161