Panda3D
 All Classes Functions Variables Enumerations
spotlight.cxx
00001 // Filename: spotlight.cxx
00002 // Created by:  mike (09Jan97)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "spotlight.h"
00016 #include "graphicsStateGuardianBase.h"
00017 #include "bamWriter.h"
00018 #include "bamReader.h"
00019 #include "datagram.h"
00020 #include "datagramIterator.h"
00021 #include "colorAttrib.h"
00022 #include "texture.h"
00023 #include "config_pgraph.h"
00024 #include "pnmImage.h"
00025 
00026 TypeHandle Spotlight::_type_handle;
00027 
00028 ////////////////////////////////////////////////////////////////////
00029 //     Function: Spotlight::CData::make_copy
00030 //       Access: Public, Virtual
00031 //  Description:
00032 ////////////////////////////////////////////////////////////////////
00033 CycleData *Spotlight::CData::
00034 make_copy() const {
00035   return new CData(*this);
00036 }
00037 
00038 ////////////////////////////////////////////////////////////////////
00039 //     Function: Spotlight::CData::write_datagram
00040 //       Access: Public, Virtual
00041 //  Description: Writes the contents of this object to the datagram
00042 //               for shipping out to a Bam file.
00043 ////////////////////////////////////////////////////////////////////
00044 void Spotlight::CData::
00045 write_datagram(BamWriter *, Datagram &dg) const {
00046   dg.add_stdfloat(_exponent);
00047   _specular_color.write_datagram(dg);
00048   _attenuation.write_datagram(dg);
00049 }
00050 
00051 ////////////////////////////////////////////////////////////////////
00052 //     Function: Spotlight::CData::fillin
00053 //       Access: Public, Virtual
00054 //  Description: This internal function is called by make_from_bam to
00055 //               read in all of the relevant data from the BamFile for
00056 //               the new Light.
00057 ////////////////////////////////////////////////////////////////////
00058 void Spotlight::CData::
00059 fillin(DatagramIterator &scan, BamReader *) {
00060   _exponent = scan.get_stdfloat();
00061   _specular_color.read_datagram(scan);
00062   _attenuation.read_datagram(scan);
00063 }
00064 
00065 ////////////////////////////////////////////////////////////////////
00066 //     Function: Spotlight::Constructor
00067 //       Access: Published
00068 //  Description:
00069 ////////////////////////////////////////////////////////////////////
00070 Spotlight::
00071 Spotlight(const string &name) : 
00072   LightLensNode(name) 
00073 {
00074 }
00075 
00076 ////////////////////////////////////////////////////////////////////
00077 //     Function: Spotlight::Copy Constructor
00078 //       Access: Protected
00079 //  Description: Do not call the copy constructor directly; instead,
00080 //               use make_copy() or copy_subgraph() to make a copy of
00081 //               a node.
00082 ////////////////////////////////////////////////////////////////////
00083 Spotlight::
00084 Spotlight(const Spotlight &copy) :
00085   LightLensNode(copy),
00086   _cycler(copy._cycler)
00087 {
00088 }
00089 
00090 ////////////////////////////////////////////////////////////////////
00091 //     Function: Spotlight::make_copy
00092 //       Access: Public, Virtual
00093 //  Description: Returns a newly-allocated PandaNode that is a shallow
00094 //               copy of this one.  It will be a different pointer,
00095 //               but its internal data may or may not be shared with
00096 //               that of the original PandaNode.  No children will be
00097 //               copied.
00098 ////////////////////////////////////////////////////////////////////
00099 PandaNode *Spotlight::
00100 make_copy() const {
00101   return new Spotlight(*this);
00102 }
00103 
00104 ////////////////////////////////////////////////////////////////////
00105 //     Function: Spotlight::xform
00106 //       Access: Public, Virtual
00107 //  Description: Transforms the contents of this PandaNode by the
00108 //               indicated matrix, if it means anything to do so.  For
00109 //               most kinds of PandaNodes, this does nothing.
00110 ////////////////////////////////////////////////////////////////////
00111 void Spotlight::
00112 xform(const LMatrix4 &mat) {
00113   LightLensNode::xform(mat); 
00114   mark_viz_stale();
00115 }
00116 
00117 ////////////////////////////////////////////////////////////////////
00118 //     Function: Spotlight::write
00119 //       Access: Public, Virtual
00120 //  Description:
00121 ////////////////////////////////////////////////////////////////////
00122 void Spotlight::
00123 write(ostream &out, int indent_level) const {
00124   indent(out, indent_level) << *this << ":\n";
00125   indent(out, indent_level + 2)
00126     << "color " << get_color() << "\n";
00127   indent(out, indent_level + 2)
00128     << "specular color " << get_specular_color() << "\n";
00129   indent(out, indent_level + 2)
00130     << "attenuation " << get_attenuation() << "\n";
00131   indent(out, indent_level + 2)
00132     << "exponent " << get_exponent() << "\n";
00133 
00134   Lens *lens = get_lens();
00135   if (lens != (Lens *)NULL) {
00136     lens->write(out, indent_level + 2);
00137   }
00138 }
00139 
00140 ////////////////////////////////////////////////////////////////////
00141 //     Function: Spotlight::get_vector_to_light
00142 //       Access: Public, Virtual
00143 //  Description: Computes the vector from a particular vertex to this
00144 //               light.  The exact vector depends on the type of light
00145 //               (e.g. point lights return a different result than
00146 //               directional lights).
00147 //
00148 //               The input parameters are the vertex position in
00149 //               question, expressed in object space, and the matrix
00150 //               which converts from light space to object space.  The
00151 //               result is expressed in object space.
00152 //
00153 //               The return value is true if the result is successful,
00154 //               or false if it cannot be computed (e.g. for an
00155 //               ambient light).
00156 ////////////////////////////////////////////////////////////////////
00157 bool Spotlight::
00158 get_vector_to_light(LVector3 &result, const LPoint3 &from_object_point, 
00159                     const LMatrix4 &to_object_space) {
00160   return false;
00161 }
00162 
00163 ////////////////////////////////////////////////////////////////////
00164 //     Function: Spotlight::make_spot
00165 //       Access: Published, Static
00166 //  Description: Returns a newly-generated Texture that renders a
00167 //               circular spot image as might be cast from the
00168 //               spotlight.  This may be projected onto target
00169 //               geometry (for instance, via
00170 //               NodePath::project_texture()) instead of actually
00171 //               enabling the light itself, as a cheesy way to make a
00172 //               high-resolution spot appear on the geometry.
00173 //
00174 //               pixel_width specifies the height and width of the new
00175 //               texture in pixels, full_radius is a value in the
00176 //               range 0..1 that indicates the relative size of the
00177 //               fully bright center spot, and fg and bg are the
00178 //               colors of the interior and exterior of the spot,
00179 //               respectively.
00180 ////////////////////////////////////////////////////////////////////
00181 PT(Texture) Spotlight::
00182 make_spot(int pixel_width, PN_stdfloat full_radius, LColor &fg, LColor &bg) {
00183   int num_channels;
00184   if (fg[0] == fg[1] && fg[1] == fg[2] &&
00185       bg[0] == bg[1] && bg[1] == bg[2]) {
00186     // grayscale
00187     num_channels = 1;
00188   } else {
00189     // color
00190     num_channels = 3;
00191   }
00192   if (fg[3] != 1.0f || bg[3] != 1.0f) {
00193     // with alpha.
00194     ++num_channels;
00195   }
00196   PNMImage image(pixel_width, pixel_width, num_channels);
00197   image.render_spot(LCAST(double, fg), LCAST(double, bg), full_radius, 1.0);
00198 
00199   PT(Texture) tex = new Texture("spot");
00200   tex->load(image);
00201   tex->set_border_color(bg);
00202   tex->set_wrap_u(Texture::WM_border_color);
00203   tex->set_wrap_v(Texture::WM_border_color);
00204 
00205   tex->set_minfilter(Texture::FT_linear);
00206   tex->set_magfilter(Texture::FT_linear);
00207 
00208   return tex;
00209 }
00210 
00211 ////////////////////////////////////////////////////////////////////
00212 //     Function: Spotlight::get_class_priority
00213 //       Access: Published, Virtual
00214 //  Description: Returns the relative priority associated with all
00215 //               lights of this class.  This priority is used to order
00216 //               lights whose instance priority (get_priority()) is
00217 //               the same--the idea is that other things being equal,
00218 //               AmbientLights (for instance) are less important than
00219 //               DirectionalLights.
00220 ////////////////////////////////////////////////////////////////////
00221 int Spotlight::
00222 get_class_priority() const {
00223   return (int)CP_spot_priority;
00224 }
00225 
00226 ////////////////////////////////////////////////////////////////////
00227 //     Function: Spotlight::bind
00228 //       Access: Public, Virtual
00229 //  Description:
00230 ////////////////////////////////////////////////////////////////////
00231 void Spotlight::
00232 bind(GraphicsStateGuardianBase *gsg, const NodePath &light, int light_id) {
00233   gsg->bind_light(this, light, light_id);
00234 }
00235 
00236 ////////////////////////////////////////////////////////////////////
00237 //     Function: Spotlight::fill_viz_geom
00238 //       Access: Protected, Virtual
00239 //  Description: Fills the indicated GeomNode up with Geoms suitable
00240 //               for rendering this light.
00241 ////////////////////////////////////////////////////////////////////
00242 void Spotlight::
00243 fill_viz_geom(GeomNode *viz_geom) {
00244   Lens *lens = get_lens();
00245   if (lens == (Lens *)NULL) {
00246     return;
00247   }
00248   
00249   PT(Geom) geom = lens->make_geometry();
00250   if (geom == (Geom *)NULL) {
00251     return;
00252   }
00253 
00254   viz_geom->add_geom(geom, get_viz_state());
00255 }
00256 
00257 ////////////////////////////////////////////////////////////////////
00258 //     Function: Spotlight::get_viz_state
00259 //       Access: Private
00260 //  Description: Returns a RenderState for rendering the spotlight
00261 //               visualization.
00262 ////////////////////////////////////////////////////////////////////
00263 CPT(RenderState) Spotlight::
00264 get_viz_state() {
00265   return RenderState::make
00266     (ColorAttrib::make_flat(get_color()));
00267 }
00268 
00269 ////////////////////////////////////////////////////////////////////
00270 //     Function: Spotlight::register_with_read_factory
00271 //       Access: Public, Static
00272 //  Description: Tells the BamReader how to create objects of type
00273 //               Spotlight.
00274 ////////////////////////////////////////////////////////////////////
00275 void Spotlight::
00276 register_with_read_factory() {
00277   BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00278 }
00279 
00280 ////////////////////////////////////////////////////////////////////
00281 //     Function: Spotlight::write_datagram
00282 //       Access: Public, Virtual
00283 //  Description: Writes the contents of this object to the datagram
00284 //               for shipping out to a Bam file.
00285 ////////////////////////////////////////////////////////////////////
00286 void Spotlight::
00287 write_datagram(BamWriter *manager, Datagram &dg) {
00288   LightLensNode::write_datagram(manager, dg);
00289   manager->write_cdata(dg, _cycler);
00290 }
00291 
00292 ////////////////////////////////////////////////////////////////////
00293 //     Function: Spotlight::make_from_bam
00294 //       Access: Protected, Static
00295 //  Description: This function is called by the BamReader's factory
00296 //               when a new object of type Spotlight is encountered
00297 //               in the Bam file.  It should create the Spotlight
00298 //               and extract its information from the file.
00299 ////////////////////////////////////////////////////////////////////
00300 TypedWritable *Spotlight::
00301 make_from_bam(const FactoryParams &params) {
00302   Spotlight *node = new Spotlight("");
00303   DatagramIterator scan;
00304   BamReader *manager;
00305 
00306   parse_params(params, scan, manager);
00307   node->fillin(scan, manager);
00308 
00309   return node;
00310 }
00311 
00312 ////////////////////////////////////////////////////////////////////
00313 //     Function: Spotlight::fillin
00314 //       Access: Protected
00315 //  Description: This internal function is called by make_from_bam to
00316 //               read in all of the relevant data from the BamFile for
00317 //               the new Spotlight.
00318 ////////////////////////////////////////////////////////////////////
00319 void Spotlight::
00320 fillin(DatagramIterator &scan, BamReader *manager) {
00321   LightLensNode::fillin(scan, manager);
00322   manager->read_cdata(scan, _cycler);
00323 }
 All Classes Functions Variables Enumerations