Panda3D
spotlight.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 spotlight.cxx
10  * @author mike
11  * @date 1997-01-09
12  */
13 
14 #include "spotlight.h"
16 #include "bamWriter.h"
17 #include "bamReader.h"
18 #include "datagram.h"
19 #include "datagramIterator.h"
20 #include "colorAttrib.h"
21 #include "texture.h"
22 #include "config_pgraph.h"
23 #include "pnmImage.h"
24 
25 TypeHandle Spotlight::_type_handle;
26 
27 /**
28  *
29  */
30 CycleData *Spotlight::CData::
31 make_copy() const {
32  return new CData(*this);
33 }
34 
35 /**
36  * Writes the contents of this object to the datagram for shipping out to a
37  * Bam file.
38  */
39 void Spotlight::CData::
40 write_datagram(BamWriter *manager, Datagram &dg) const {
41  dg.add_stdfloat(_exponent);
42  _specular_color.write_datagram(dg);
43  _attenuation.write_datagram(dg);
44  if (manager->get_file_minor_ver() >= 41) {
45  dg.add_stdfloat(_max_distance);
46  }
47 }
48 
49 /**
50  * This internal function is called by make_from_bam to read in all of the
51  * relevant data from the BamFile for the new Light.
52  */
53 void Spotlight::CData::
54 fillin(DatagramIterator &scan, BamReader *manager) {
55  _exponent = scan.get_stdfloat();
56  _specular_color.read_datagram(scan);
57  _attenuation.read_datagram(scan);
58  if (manager->get_file_minor_ver() >= 41) {
59  _max_distance = scan.get_stdfloat();
60  }
61 }
62 
63 /**
64  *
65  */
66 Spotlight::
67 Spotlight(const std::string &name) :
68  LightLensNode(name) {
69  _lenses[0]._lens->set_interocular_distance(0);
70 }
71 
72 /**
73  * Do not call the copy constructor directly; instead, use make_copy() or
74  * copy_subgraph() to make a copy of a node.
75  */
76 Spotlight::
77 Spotlight(const Spotlight &copy) :
78  LightLensNode(copy),
79  _cycler(copy._cycler)
80 {
81 }
82 
83 /**
84  * Returns a newly-allocated PandaNode that is a shallow copy of this one. It
85  * will be a different pointer, but its internal data may or may not be shared
86  * with that of the original PandaNode. No children will be copied.
87  */
89 make_copy() const {
90  return new Spotlight(*this);
91 }
92 
93 /**
94  * Transforms the contents of this PandaNode by the indicated matrix, if it
95  * means anything to do so. For most kinds of PandaNodes, this does nothing.
96  */
97 void Spotlight::
98 xform(const LMatrix4 &mat) {
100  mark_viz_stale();
101 }
102 
103 /**
104  *
105  */
106 void Spotlight::
107 write(std::ostream &out, int indent_level) const {
108  indent(out, indent_level) << *this << ":\n";
109  indent(out, indent_level + 2)
110  << "color " << get_color() << "\n";
111  if (_has_specular_color) {
112  indent(out, indent_level + 2)
113  << "specular color " << get_specular_color() << "\n";
114  }
115  indent(out, indent_level + 2)
116  << "attenuation " << get_attenuation() << "\n";
117  indent(out, indent_level + 2)
118  << "exponent " << get_exponent() << "\n";
119 
120  if (!cinf(get_max_distance())) {
121  indent(out, indent_level + 2)
122  << "max distance " << get_max_distance() << "\n";
123  }
124 
125  Lens *lens = get_lens();
126  if (lens != nullptr) {
127  lens->write(out, indent_level + 2);
128  }
129 }
130 
131 /**
132  * Computes the vector from a particular vertex to this light. The exact
133  * vector depends on the type of light (e.g. point lights return a different
134  * result than directional lights).
135  *
136  * The input parameters are the vertex position in question, expressed in
137  * object space, and the matrix which converts from light space to object
138  * space. The result is expressed in object space.
139  *
140  * The return value is true if the result is successful, or false if it cannot
141  * be computed (e.g. for an ambient light).
142  */
143 bool Spotlight::
144 get_vector_to_light(LVector3 &result, const LPoint3 &from_object_point,
145  const LMatrix4 &to_object_space) {
146  return false;
147 }
148 
149 /**
150  * Returns a newly-generated Texture that renders a circular spot image as
151  * might be cast from the spotlight. This may be projected onto target
152  * geometry (for instance, via NodePath::project_texture()) instead of
153  * actually enabling the light itself, as a cheesy way to make a high-
154  * resolution spot appear on the geometry.
155  *
156  * pixel_width specifies the height and width of the new texture in pixels,
157  * full_radius is a value in the range 0..1 that indicates the relative size
158  * of the fully bright center spot, and fg and bg are the colors of the
159  * interior and exterior of the spot, respectively.
160  */
161 PT(Texture) Spotlight::
162 make_spot(int pixel_width, PN_stdfloat full_radius, LColor &fg, LColor &bg) {
163  int num_channels;
164  if (fg[0] == fg[1] && fg[1] == fg[2] &&
165  bg[0] == bg[1] && bg[1] == bg[2]) {
166  // grayscale
167  num_channels = 1;
168  } else {
169  // color
170  num_channels = 3;
171  }
172  if (fg[3] != 1.0f || bg[3] != 1.0f) {
173  // with alpha.
174  ++num_channels;
175  }
176  PNMImage image(pixel_width, pixel_width, num_channels);
177  image.render_spot(LCAST(float, fg), LCAST(float, bg), full_radius, 1.0);
178 
179  PT(Texture) tex = new Texture("spot");
180  tex->load(image);
181  tex->set_border_color(bg);
182  tex->set_wrap_u(SamplerState::WM_border_color);
183  tex->set_wrap_v(SamplerState::WM_border_color);
184 
185  tex->set_minfilter(SamplerState::FT_linear);
186  tex->set_magfilter(SamplerState::FT_linear);
187 
188  return tex;
189 }
190 
191 /**
192  * Returns the relative priority associated with all lights of this class.
193  * This priority is used to order lights whose instance priority
194  * (get_priority()) is the same--the idea is that other things being equal,
195  * AmbientLights (for instance) are less important than DirectionalLights.
196  */
197 int Spotlight::
199  return (int)CP_spot_priority;
200 }
201 
202 /**
203  *
204  */
205 void Spotlight::
206 bind(GraphicsStateGuardianBase *gsg, const NodePath &light, int light_id) {
207  gsg->bind_light(this, light, light_id);
208 }
209 
210 /**
211  * Fills the indicated GeomNode up with Geoms suitable for rendering this
212  * light.
213  */
214 void Spotlight::
215 fill_viz_geom(GeomNode *viz_geom) {
216  Lens *lens = get_lens();
217  if (lens == nullptr) {
218  return;
219  }
220 
221  PT(Geom) geom = lens->make_geometry();
222  if (geom == nullptr) {
223  return;
224  }
225 
226  viz_geom->add_geom(geom, get_viz_state());
227 }
228 
229 /**
230  * Returns a RenderState for rendering the spotlight visualization.
231  */
232 CPT(RenderState) Spotlight::
233 get_viz_state() {
234  return RenderState::make
235  (ColorAttrib::make_flat(get_color()));
236 }
237 
238 /**
239  * Tells the BamReader how to create objects of type Spotlight.
240  */
241 void Spotlight::
243  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
244 }
245 
246 /**
247  * Writes the contents of this object to the datagram for shipping out to a
248  * Bam file.
249  */
250 void Spotlight::
252  LightLensNode::write_datagram(manager, dg);
253  if (manager->get_file_minor_ver() >= 39) {
254  dg.add_bool(_has_specular_color);
255  }
256  manager->write_cdata(dg, _cycler);
257 }
258 
259 /**
260  * This function is called by the BamReader's factory when a new object of
261  * type Spotlight is encountered in the Bam file. It should create the
262  * Spotlight and extract its information from the file.
263  */
264 TypedWritable *Spotlight::
265 make_from_bam(const FactoryParams &params) {
266  Spotlight *node = new Spotlight("");
267  DatagramIterator scan;
268  BamReader *manager;
269 
270  parse_params(params, scan, manager);
271  node->fillin(scan, manager);
272 
273  return node;
274 }
275 
276 /**
277  * This internal function is called by make_from_bam to read in all of the
278  * relevant data from the BamFile for the new Spotlight.
279  */
280 void Spotlight::
281 fillin(DatagramIterator &scan, BamReader *manager) {
282  LightLensNode::fillin(scan, manager);
283 
284  if (manager->get_file_minor_ver() >= 39) {
285  _has_specular_color = scan.get_bool();
286  } else {
287  _has_specular_color = true;
288  }
289 
290  manager->read_cdata(scan, _cycler);
291 }
virtual void xform(const LMatrix4 &mat)
Transforms the contents of this PandaNode by the indicated matrix, if it means anything to do so.
Definition: spotlight.cxx:98
A basic node of the scene graph or data graph.
Definition: pandaNode.h:64
PT(Texture) Spotlight
Returns a newly-generated Texture that renders a circular spot image as might be cast from the spotli...
Definition: spotlight.cxx:161
virtual int get_class_priority() const
Returns the relative priority associated with all lights of this class.
Definition: spotlight.cxx:198
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool get_bool()
Extracts a boolean value.
PN_stdfloat get_stdfloat()
Extracts either a 32-bit or a 64-bit floating-point number, according to Datagram::set_stdfloat_doubl...
The name of this class derives from the fact that we originally implemented it as a layer on top of t...
Definition: pnmImage.h:58
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A base class for any number of different kinds of lenses, linear and otherwise.
Definition: lens.h:41
CPT(RenderState) Spotlight
Returns a RenderState for rendering the spotlight visualization.
Definition: spotlight.cxx:232
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
void read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler)
Reads in the indicated CycleData object.
Definition: bamReader.cxx:695
PN_stdfloat get_exponent() const final
For spotlights, returns the exponent that controls the amount of light falloff from the center of the...
virtual PandaNode * make_copy() const
Returns a newly-allocated PandaNode that is a shallow copy of this one.
Definition: spotlight.cxx:89
A single page of data maintained by a PipelineCycler.
Definition: cycleData.h:47
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
Definition: spotlight.cxx:251
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
Definition: texture.h:71
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
void write_cdata(Datagram &packet, const PipelineCyclerBase &cycler)
Writes out the indicated CycleData object.
Definition: bamWriter.cxx:425
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being written.
Definition: bamWriter.I:59
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:63
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
Definition: bamReader.I:83
Lens * get_lens(int index=0) const
Returns a pointer to the particular Lens associated with this LensNode, or NULL if there is not yet a...
Definition: lensNode.I:47
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void add_stdfloat(PN_stdfloat value)
Adds either a 32-bit or a 64-bit floating-point number, according to set_stdfloat_double().
Definition: datagram.I:133
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
void add_bool(bool value)
Adds a boolean value to the datagram.
Definition: datagram.I:34
get_max_distance
Returns the maximum distance at which the light has any effect, as previously specified by set_max_di...
Definition: spotlight.h:64
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Definition: indent.cxx:20
A container for geometry primitives.
Definition: geom.h:54
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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 light originating from a single point in space, and shining in a particular direction,...
Definition: spotlight.h:32
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:47
static void register_with_read_factory()
Tells the BamReader how to create objects of type Spotlight.
Definition: spotlight.cxx:242
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
virtual bool get_vector_to_light(LVector3 &result, const LPoint3 &from_object_point, const LMatrix4 &to_object_space)
Computes the vector from a particular vertex to this light.
Definition: spotlight.cxx:144
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:177
virtual void xform(const LMatrix4 &mat)
Transforms the contents of this PandaNode by the indicated matrix, if it means anything to do so.
Definition: lensNode.cxx:53
A derivative of Light and of Camera.
Definition: lightLensNode.h:33
void render_spot(const LColorf &fg, const LColorf &bg, float min_radius, float max_radius)
Renders a solid-color circle, with a fuzzy edge, into the center of the PNMImage.
Definition: pnmImage.cxx:1789
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
A class to retrieve the individual data elements previously stored in a Datagram.
const LVecBase3 & get_attenuation() const final
Returns the terms of the attenuation equation for the light.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:161
const LColor & get_specular_color() const final
Returns the color of specular highlights generated by the light.
A node that holds Geom objects, renderable pieces of geometry.
Definition: geomNode.h:34
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void add_geom(Geom *geom, const RenderState *state=RenderState::make_empty())
Adds a new Geom to the node.
Definition: geomNode.cxx:584