00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "spotlight.h"
00020 #include "graphicsStateGuardianBase.h"
00021 #include "bamWriter.h"
00022 #include "bamReader.h"
00023 #include "datagram.h"
00024 #include "datagramIterator.h"
00025 #include "colorAttrib.h"
00026 #include "config_pgraph.h"
00027
00028 TypeHandle Spotlight::_type_handle;
00029
00030
00031
00032
00033
00034
00035 CycleData *Spotlight::CData::
00036 make_copy() const {
00037 return new CData(*this);
00038 }
00039
00040
00041
00042
00043
00044
00045
00046 void Spotlight::CData::
00047 write_datagram(BamWriter *, Datagram &dg) const {
00048 dg.add_float32(_exponent);
00049 _specular_color.write_datagram(dg);
00050 _attenuation.write_datagram(dg);
00051 }
00052
00053
00054
00055
00056
00057
00058
00059
00060 void Spotlight::CData::
00061 fillin(DatagramIterator &scan, BamReader *) {
00062 _exponent = scan.get_float32();
00063 _specular_color.read_datagram(scan);
00064 _attenuation.read_datagram(scan);
00065 }
00066
00067
00068
00069
00070
00071
00072 Spotlight::
00073 Spotlight(const string &name) :
00074 LightLensNode(name)
00075 {
00076 }
00077
00078
00079
00080
00081
00082
00083
00084
00085 Spotlight::
00086 Spotlight(const Spotlight ©) :
00087 LightLensNode(copy),
00088 _cycler(copy._cycler)
00089 {
00090 }
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 PandaNode *Spotlight::
00102 make_copy() const {
00103 return new Spotlight(*this);
00104 }
00105
00106
00107
00108
00109
00110
00111
00112
00113 void Spotlight::
00114 xform(const LMatrix4f &mat) {
00115 LightLensNode::xform(mat);
00116 mark_viz_stale();
00117 }
00118
00119
00120
00121
00122
00123
00124 void Spotlight::
00125 write(ostream &out, int indent_level) const {
00126 indent(out, indent_level) << *this << ":\n";
00127 indent(out, indent_level + 2)
00128 << "color " << get_color() << "\n";
00129 indent(out, indent_level + 2)
00130 << "specular color " << get_specular_color() << "\n";
00131 indent(out, indent_level + 2)
00132 << "attenuation " << get_attenuation() << "\n";
00133 indent(out, indent_level + 2)
00134 << "exponent " << get_exponent() << "\n";
00135
00136 Lens *lens = get_lens();
00137 if (lens != (Lens *)NULL) {
00138 lens->write(out, indent_level + 2);
00139 }
00140 }
00141
00142
00143
00144
00145
00146
00147 void Spotlight::
00148 bind(GraphicsStateGuardianBase *gsg, int light_id) {
00149 gsg->bind_light(this, light_id);
00150 }
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 bool Spotlight::
00167 make_image(Texture *texture, float radius) {
00168 if (texture == NULL) {
00169 pgraph_cat.error()
00170 << "Spotlight::make_image() - NULL texture" << endl;
00171 return false;
00172 }
00173 PixelBuffer *pb = texture->_pbuffer;
00174 int size = pb->get_xsize();
00175 if (size == 0) {
00176 pgraph_cat.error()
00177 << "Spotlight::make_image() - pixel buffer has size == 0" << endl;
00178 return false;
00179 }
00180
00181 const Colorf &color = get_color();
00182
00183 RGBColorf scaled_color;
00184 scaled_color[0] = (color[0] * 255.0f);
00185 scaled_color[1] = (color[1] * 255.0f);
00186 scaled_color[2] = (color[2] * 255.0f);
00187
00188 int half_width = (size - 2) / 2;
00189 float dXY = 1 / (float)half_width;
00190 float Y = dXY + dXY;
00191 float X, YY, dist_from_center, intensity;
00192 uchar C[3];
00193 int tx, ty, tx2, ty2;
00194
00195 for (int y = 0; y < half_width; y++, Y += dXY) {
00196 X = dXY * y + dXY;
00197 YY = Y * Y;
00198 ty = y + half_width;
00199
00200 for (int x = y; x < half_width; x++, X += dXY) {
00201 dist_from_center = (float)sqrt(X * X + YY);
00202 float D = dist_from_center;
00203 if (D <= radius)
00204 intensity = 1.0f;
00205 else if (D < 1.0f)
00206 intensity = pow(cos((D-radius) /
00207 (1.0f-radius) * (MathNumbers::pi_f*0.5f)), get_exponent());
00208 else
00209 intensity = 0;
00210
00211 C[0] = (uchar)(intensity * scaled_color[0]);
00212 C[1] = (uchar)(intensity * scaled_color[1]);
00213 C[2] = (uchar)(intensity * scaled_color[2]);
00214
00215 tx = x + half_width;
00216
00217 pb->set_uchar_rgb_texel(C, tx, ty, size);
00218 pb->set_uchar_rgb_texel(C, tx, size - ty - 1, size);
00219 pb->set_uchar_rgb_texel(C, size - tx - 1, ty, size);
00220 pb->set_uchar_rgb_texel(C, size - tx - 1, size - ty - 1, size);
00221
00222 tx2 = ty; ty2 = tx;
00223
00224 pb->set_uchar_rgb_texel(C, tx2, ty2, size);
00225 pb->set_uchar_rgb_texel(C, tx2, size - ty2 - 1, size);
00226 pb->set_uchar_rgb_texel(C, size - tx2 - 1, ty2, size);
00227 pb->set_uchar_rgb_texel(C, size - tx2 - 1, size - ty2 - 1, size);
00228 }
00229 }
00230 texture->unprepare();
00231
00232 return true;
00233 }
00234
00235
00236
00237
00238
00239
00240
00241 void Spotlight::
00242 fill_viz_geom(GeomNode *viz_geom) {
00243 Lens *lens = get_lens();
00244 if (lens == (Lens *)NULL) {
00245 return;
00246 }
00247
00248 PT(Geom) geom = lens->make_geometry();
00249 if (geom == (Geom *)NULL) {
00250 return;
00251 }
00252
00253 viz_geom->add_geom(geom, get_viz_state());
00254 }
00255
00256
00257
00258
00259
00260
00261
00262 CPT(RenderState) Spotlight::
00263 get_viz_state() {
00264 return RenderState::make
00265 (ColorAttrib::make_flat(get_color()));
00266 }
00267
00268
00269
00270
00271
00272
00273
00274 void Spotlight::
00275 register_with_read_factory() {
00276 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00277 }
00278
00279
00280
00281
00282
00283
00284
00285 void Spotlight::
00286 write_datagram(BamWriter *manager, Datagram &dg) {
00287 LightLensNode::write_datagram(manager, dg);
00288 manager->write_cdata(dg, _cycler);
00289 }
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 TypedWritable *Spotlight::
00300 make_from_bam(const FactoryParams ¶ms) {
00301 Spotlight *node = new Spotlight("");
00302 DatagramIterator scan;
00303 BamReader *manager;
00304
00305 parse_params(params, scan, manager);
00306 node->fillin(scan, manager);
00307
00308 return node;
00309 }
00310
00311
00312
00313
00314
00315
00316
00317
00318 void Spotlight::
00319 fillin(DatagramIterator &scan, BamReader *manager) {
00320 LightLensNode::fillin(scan, manager);
00321 manager->read_cdata(scan, _cycler);
00322 }