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 ©) : 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 ¶ms) { 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 }