Panda3D
Loading...
Searching...
No Matches
texProjectorEffect.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file texProjectorEffect.cxx
10 * @author drose
11 * @date 2004-07-25
12 */
13
14#include "texProjectorEffect.h"
15#include "cullTraverserData.h"
16#include "texMatrixAttrib.h"
17#include "lensNode.h"
18#include "config_pgraph.h"
19#include "nodePath.h"
20#include "bamReader.h"
21#include "bamWriter.h"
22#include "datagram.h"
23#include "datagramIterator.h"
24
25CPT(RenderEffect) TexProjectorEffect::_empty_effect;
26TypeHandle TexProjectorEffect::_type_handle;
27
28/**
29 *
30 */
31TexProjectorEffect::
32~TexProjectorEffect() {
33}
34
35/**
36 * Constructs a TexProjectorEffect that modifies no stages at all.
37 */
38CPT(RenderEffect) TexProjectorEffect::
39make() {
40 // We make it a special case and store a pointer to the empty effect forever
41 // once we find it the first time, as an optimization.
42 if (_empty_effect == nullptr) {
43 _empty_effect = return_new(new TexProjectorEffect);
44 }
45
46 return _empty_effect;
47}
48
49/**
50 * Returns a new TexProjectorEffect just like this one, with the indicated
51 * projection for the given stage. If this stage already exists, its
52 * projection definition is replaced.
53 *
54 * The relative transform between the "from" and the "to" nodes is
55 * automatically applied to the texture transform each frame.
56 *
57 * Furthermore, if the "to" node is a LensNode, its projection matrix is also
58 * applied to the texture transform. In this case, the lens_index may be used
59 * to select the particular lens that should be used.
60 */
61CPT(RenderEffect) TexProjectorEffect::
62add_stage(TextureStage *stage, const NodePath &from, const NodePath &to, int lens_index) const {
63 TexProjectorEffect *effect = new TexProjectorEffect(*this);
64 StageDef &def = effect->_stages[stage];
65 def.set_from(from);
66 def.set_to(to);
67 def.set_lens_index(lens_index);
68 return return_new(effect);
69}
70
71/**
72 * Returns a new TexProjectorEffect just like this one, with the indicated
73 * stage removed.
74 */
75CPT(RenderEffect) TexProjectorEffect::
76remove_stage(TextureStage *stage) const {
77 TexProjectorEffect *effect = new TexProjectorEffect(*this);
78 effect->_stages.erase(stage);
79 return return_new(effect);
80}
81
82/**
83 * Returns true if no stages are defined in the TexProjectorEffect, false if
84 * at least one is.
85 */
86bool TexProjectorEffect::
87is_empty() const {
88 return _stages.empty();
89}
90
91/**
92 * Returns true if there is a transform associated with the indicated stage,
93 * or false otherwise (in which case get_transform(stage) will return the
94 * identity transform).
95 */
96bool TexProjectorEffect::
97has_stage(TextureStage *stage) const {
98 Stages::const_iterator mi = _stages.find(stage);
99 return (mi != _stages.end());
100}
101
102/**
103 * Returns the "from" node associated with the TexProjectorEffect on the
104 * indicated stage. The relative transform between the "from" and the "to"
105 * nodes is automatically applied to the texture transform each frame.
106 */
107NodePath TexProjectorEffect::
108get_from(TextureStage *stage) const {
109 Stages::const_iterator mi = _stages.find(stage);
110 nassertr(mi != _stages.end(), NodePath::fail());
111 return (*mi).second._from;
112}
113
114/**
115 * Returns the "to" node associated with the TexProjectorEffect on the
116 * indicated stage. The relative transform between the "from" and the "to"
117 * nodes is automatically applied to the texture transform each frame.
118 *
119 * Furthermore, if the "to" node is a LensNode, its projection matrix is also
120 * applied to the texture transform.
121 */
122NodePath TexProjectorEffect::
123get_to(TextureStage *stage) const {
124 Stages::const_iterator mi = _stages.find(stage);
125 nassertr(mi != _stages.end(), NodePath::fail());
126 return (*mi).second._to;
127}
128
129/**
130 * Returns the lens_index associated with the TexProjectorEffect on the
131 * indicated stage. This is only used if the "to" node is a LensNode, in
132 * which case it specifies the particular lens that should be used.
133 */
134int TexProjectorEffect::
135get_lens_index(TextureStage *stage) const {
136 Stages::const_iterator mi = _stages.find(stage);
137 nassertr(mi != _stages.end(), 0);
138 return (*mi).second._lens_index;
139}
140
141/**
142 *
143 */
144void TexProjectorEffect::
145output(std::ostream &out) const {
146 out << get_type() << ":";
147
148 Stages::const_iterator mi;
149 for (mi = _stages.begin(); mi != _stages.end(); ++mi) {
150 TextureStage *stage = (*mi).first;
151 const StageDef &def = (*mi).second;
152 out << " " << stage->get_name() << "(" << def._to
153 << ", " << def._from << ", " << def._lens_index << ")";
154 }
155}
156
157/**
158 * Should be overridden by derived classes to return true if cull_callback()
159 * has been defined. Otherwise, returns false to indicate cull_callback()
160 * does not need to be called for this effect during the cull traversal.
161 */
162bool TexProjectorEffect::
163has_cull_callback() const {
164 return !_stages.empty();
165}
166
167/**
168 * If has_cull_callback() returns true, this function will be called during
169 * the cull traversal to perform any additional operations that should be
170 * performed at cull time. This may include additional manipulation of render
171 * state or additional visible/invisible decisions, or any other arbitrary
172 * operation.
173 *
174 * At the time this function is called, the current node's transform and state
175 * have not yet been applied to the net_transform and net_state. This
176 * callback may modify the node_transform and node_state to apply an effective
177 * change to the render state at this level.
178 */
179void TexProjectorEffect::
180cull_callback(CullTraverser *trav, CullTraverserData &data,
181 CPT(TransformState) &node_transform,
182 CPT(RenderState) &node_state) const {
183 CPT(TexMatrixAttrib) tex_matrix = DCAST(TexMatrixAttrib, TexMatrixAttrib::make());
184
185 Stages::const_iterator mi;
186 for (mi = _stages.begin(); mi != _stages.end(); ++mi) {
187 TextureStage *stage = (*mi).first;
188 const StageDef &def = (*mi).second;
189
190 CPT(TransformState) transform = def._from.get_transform(def._to);
191
192 if (def._to_lens_node != nullptr &&
193 def._to_lens_node->get_lens() != nullptr) {
194
195 // Get the lens's projection matrix, as a TransformState.
196 Lens *lens = def._to_lens_node->get_lens(def._lens_index);
197 if (lens != nullptr) {
198 CPT(TransformState) projmat = TransformState::make_mat(lens->get_projection_mat());
199
200 // We need a special transform to convert the -0.5, 0.5 centering of
201 // the lens's projection matrix to UV's in the range of (0, 1).
202 static CPT(TransformState) fixmat;
203 if (fixmat == nullptr) {
204 fixmat = TransformState::make_pos_hpr_scale
205 (LVecBase3(0.5f, 0.5f, 0.0f),
206 LVecBase3(0.0f, 0.0f, 0.0f),
207 LVecBase3(0.5f, 0.5f, 1.0f));
208 }
209
210 // Now apply both to the current transform.
211 transform = fixmat->compose(projmat)->compose(transform);
212 }
213 }
214
215 if (!transform->is_identity()) {
216 tex_matrix = DCAST(TexMatrixAttrib,
217 tex_matrix->add_stage(stage, transform));
218 }
219 }
220
221 if (!tex_matrix->is_empty()) {
222 node_state = node_state->compose(RenderState::make(tex_matrix));
223 }
224}
225
226/**
227 * Intended to be overridden by derived TexProjectorEffect types to return a
228 * unique number indicating whether this TexProjectorEffect is equivalent to
229 * the other one.
230 *
231 * This should return 0 if the two TexProjectorEffect objects are equivalent,
232 * a number less than zero if this one should be sorted before the other one,
233 * and a number greater than zero otherwise.
234 *
235 * This will only be called with two TexProjectorEffect objects whose
236 * get_type() functions return the same.
237 */
238int TexProjectorEffect::
239compare_to_impl(const RenderEffect *other) const {
240 const TexProjectorEffect *ta;
241 DCAST_INTO_R(ta, other, 0);
242
243 Stages::const_iterator ai, bi;
244 ai = _stages.begin();
245 bi = ta->_stages.begin();
246 while (ai != _stages.end() && bi != ta->_stages.end()) {
247 if ((*ai).first < (*bi).first) {
248 // This stage is in a but not in b.
249 return -1;
250
251 } else if ((*bi).first < (*ai).first) {
252 // This stage is in b but not in a.
253 return 1;
254
255 } else {
256 // This stage is in both; compare the stages.
257 int compare = (*ai).second.compare_to((*bi).second);
258 if (compare != 0) {
259 return compare;
260 }
261 ++ai;
262 ++bi;
263 }
264 }
265
266 if (bi != ta->_stages.end()) {
267 // a ran out first; b was longer.
268 return -1;
269 }
270
271 if (ai != _stages.end()) {
272 // b ran out first; a was longer.
273 return 1;
274 }
275
276 return 0;
277}
278
279/**
280 * Tells the BamReader how to create objects of type TexProjectorEffect.
281 */
282void TexProjectorEffect::
283register_with_read_factory() {
284 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
285}
286
287/**
288 * Writes the contents of this object to the datagram for shipping out to a
289 * Bam file.
290 */
292write_datagram(BamWriter *manager, Datagram &dg) {
293 RenderEffect::write_datagram(manager, dg);
294
295 // For now, we don't write anything to the bam file for a
296 // TexProjectorEffect, except a bogus 0 "size" which may one day indicate
297 // the number of stages in the map that we might write out.
298 dg.add_uint16(0);
299
300 // One day we will write the whole map out. We don't do this yet, because
301 // (a) we don't have an interface for writing out NodePaths to a bam file,
302 // and (b) it won't matter until we have the Panda-monium system in place,
303 // since you can't load a TexProjectorEffect from an egg file.
304}
305
306/**
307 * Receives an array of pointers, one for each time manager->read_pointer()
308 * was called in fillin(). Returns the number of pointers processed.
309 */
311complete_pointers(TypedWritable **p_list, BamReader *manager) {
312 int pi = RenderEffect::complete_pointers(p_list, manager);
313
314 return pi;
315}
316
317/**
318 * This function is called by the BamReader's factory when a new object of
319 * type TexProjectorEffect is encountered in the Bam file. It should create
320 * the TexProjectorEffect and extract its information from the file.
321 */
322TypedWritable *TexProjectorEffect::
323make_from_bam(const FactoryParams &params) {
325 DatagramIterator scan;
326 BamReader *manager;
327
328 parse_params(params, scan, manager);
329 effect->fillin(scan, manager);
330
331 return effect;
332}
333
334/**
335 * This internal function is called by make_from_bam to read in all of the
336 * relevant data from the BamFile for the new TexProjectorEffect.
337 */
338void TexProjectorEffect::
339fillin(DatagramIterator &scan, BamReader *manager) {
340 RenderEffect::fillin(scan, manager);
341
342 size_t num_stages = scan.get_uint16();
343
344 // Since we don't support full reading and writing of TexProjectorEffects
345 // yet, this value had better be zero. If it's not, maybe we're trying to
346 // read a bam file that was generated by some future version of Panda that
347 // does support these things.
348 nassertv(num_stages == 0);
349}
350
351/**
352 *
353 */
354void TexProjectorEffect::StageDef::
355set_to(const NodePath &to) {
356 _to = to;
357 if (!_to.is_empty() && _to.node()->is_of_type(LensNode::get_class_type())) {
358 DCAST_INTO_V(_to_lens_node, _to.node());
359 } else {
360 _to_lens_node = nullptr;
361 }
362}
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void parse_params(const FactoryParams &params, DatagramIterator &scan, BamReader *&manager)
Takes in a FactoryParams, passed from a WritableFactory into any TypedWritable's make function,...
Definition bamReader.I:275
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition bamReader.h:110
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition bamReader.I:177
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition bamWriter.h:63
This collects together the pieces of data that are accumulated for each node while walking the scene ...
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
A class to retrieve the individual data elements previously stored in a Datagram.
uint16_t get_uint16()
Extracts an unsigned 16-bit integer.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition datagram.h:38
void add_uint16(uint16_t value)
Adds an unsigned 16-bit integer to the datagram.
Definition datagram.I:85
An instance of this class is passed to the Factory when requesting it to do its business and construc...
void register_factory(TypeHandle handle, CreateFunc *func, void *user_data=nullptr)
Registers a new kind of thing the Factory will be able to create.
Definition factory.I:73
A base class for any number of different kinds of lenses, linear and otherwise.
Definition lens.h:41
const LMatrix4 & get_projection_mat(StereoChannel channel=SC_mono) const
Returns the complete transformation matrix from a 3-d point in space to a point on the film,...
Definition lens.I:563
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition nodePath.h:159
bool is_empty() const
Returns true if the NodePath contains no nodes.
Definition nodePath.I:188
PandaNode * node() const
Returns the referenced node of the path.
Definition nodePath.I:227
static NodePath fail()
Creates a NodePath with the ET_fail error type set.
Definition nodePath.I:149
This is the base class for a number of special render effects that may be set on scene graph nodes to...
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition renderState.h:47
Applies a transform matrix to UV's before they are rendered.
This effect automatically applies a computed texture matrix to the specified texture stage,...
virtual int complete_pointers(TypedWritable **plist, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin().
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
Defines the properties of a named stage of the multitexture pipeline.
get_name
Returns the name of this texture stage.
Indicates a coordinate-system transform on vertices.
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition typedObject.I:28
Base class for objects that can be written to and read from Bam files.
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin().
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.