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