00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "billboardEffect.h"
00020 #include "nodePath.h"
00021 #include "look_at.h"
00022 #include "bamReader.h"
00023 #include "bamWriter.h"
00024 #include "datagram.h"
00025 #include "datagramIterator.h"
00026
00027 TypeHandle BillboardEffect::_type_handle;
00028
00029
00030
00031
00032
00033
00034
00035 CPT(RenderEffect) BillboardEffect::
00036 make(const LVector3f &up_vector, bool eye_relative,
00037 bool axial_rotate, float offset, const NodePath &look_at,
00038 const LPoint3f &look_at_point) {
00039 BillboardEffect *effect = new BillboardEffect;
00040 effect->_up_vector = up_vector;
00041 effect->_eye_relative = eye_relative;
00042 effect->_axial_rotate = axial_rotate;
00043 effect->_offset = offset;
00044 effect->_look_at = look_at;
00045 effect->_look_at_point = look_at_point;
00046 effect->_off = false;
00047 return return_new(effect);
00048 }
00049
00050
00051
00052
00053
00054
00055
00056
00057 bool BillboardEffect::
00058 safe_to_transform() const {
00059 return false;
00060 }
00061
00062
00063
00064
00065
00066
00067 void BillboardEffect::
00068 output(ostream &out) const {
00069 out << get_type() << ":";
00070 if (is_off()) {
00071 out << "(off)";
00072 } else {
00073 if (_axial_rotate) {
00074 out << "(axis";
00075 } else {
00076 out << "(point";
00077 }
00078 if (!_up_vector.almost_equal(LVector3f::up())) {
00079 out << " up " << _up_vector;
00080 }
00081 if (_eye_relative) {
00082 out << " eye";
00083 }
00084 if (_offset != 0.0f) {
00085 out << " offset " << _offset;
00086 }
00087 if (!_look_at.is_empty()) {
00088 out << " look at " << _look_at;
00089 }
00090 if (!_look_at_point.almost_equal(LPoint3f(0.0f, 0.0f, 0.0f))) {
00091 out << " look at point " << _look_at_point;
00092 }
00093 out << ")";
00094 }
00095 }
00096
00097
00098
00099
00100
00101
00102
00103
00104 CPT(TransformState) BillboardEffect::
00105 do_billboard(const TransformState *net_transform,
00106 const TransformState *camera_transform) const {
00107
00108
00109 if (!_look_at.is_empty()) {
00110 camera_transform = _look_at.get_net_transform();
00111 }
00112
00113 CPT(TransformState) rel_transform =
00114 net_transform->invert_compose(camera_transform);
00115 const LMatrix4f &rel_mat = rel_transform->get_mat();
00116
00117
00118 LVector3f camera_pos, up;
00119
00120
00121
00122
00123
00124
00125
00126 if (_eye_relative) {
00127 up = _up_vector * rel_mat;
00128 camera_pos = LVector3f::forward() * rel_mat;
00129
00130 } else {
00131 up = _up_vector;
00132 camera_pos = -(_look_at_point * rel_mat);
00133 }
00134
00135
00136 LMatrix4f rotate;
00137 if (_axial_rotate) {
00138 heads_up(rotate, camera_pos, up);
00139 } else {
00140 look_at(rotate, camera_pos, up);
00141 }
00142
00143
00144
00145 if (_offset != 0.0f) {
00146 LVector3f translate(rel_mat(3, 0), rel_mat(3, 1), rel_mat(3, 2));
00147 translate.normalize();
00148 translate *= _offset;
00149 rotate.set_row(3, translate);
00150 }
00151
00152 return TransformState::make_mat(rotate);
00153 }
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 int BillboardEffect::
00171 compare_to_impl(const RenderEffect *other) const {
00172 const BillboardEffect *ta;
00173 DCAST_INTO_R(ta, other, 0);
00174
00175 if (_axial_rotate != ta->_axial_rotate) {
00176 return _axial_rotate - ta->_axial_rotate;
00177 }
00178 if (_eye_relative != ta->_eye_relative) {
00179 return _eye_relative - ta->_eye_relative;
00180 }
00181 if (_offset != ta->_offset) {
00182 return _offset < ta->_offset ? -1 : 1;
00183 }
00184 int compare = _up_vector.compare_to(ta->_up_vector);
00185 if (compare != 0) {
00186 return compare;
00187 }
00188 compare = _look_at.compare_to(ta->_look_at);
00189 if (compare != 0) {
00190 return compare;
00191 }
00192 compare = _look_at_point.compare_to(ta->_look_at_point);
00193 if (compare != 0) {
00194 return compare;
00195 }
00196 return 0;
00197 }
00198
00199
00200
00201
00202
00203
00204
00205 void BillboardEffect::
00206 register_with_read_factory() {
00207 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00208 }
00209
00210
00211
00212
00213
00214
00215
00216 void BillboardEffect::
00217 write_datagram(BamWriter *manager, Datagram &dg) {
00218 RenderEffect::write_datagram(manager, dg);
00219
00220 dg.add_bool(_off);
00221 _up_vector.write_datagram(dg);
00222 dg.add_bool(_eye_relative);
00223 dg.add_bool(_axial_rotate);
00224 dg.add_float32(_offset);
00225 _look_at_point.write_datagram(dg);
00226
00227
00228
00229 }
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239 TypedWritable *BillboardEffect::
00240 make_from_bam(const FactoryParams ¶ms) {
00241 BillboardEffect *effect = new BillboardEffect;
00242 DatagramIterator scan;
00243 BamReader *manager;
00244
00245 parse_params(params, scan, manager);
00246 effect->fillin(scan, manager);
00247
00248 return effect;
00249 }
00250
00251
00252
00253
00254
00255
00256
00257
00258 void BillboardEffect::
00259 fillin(DatagramIterator &scan, BamReader *manager) {
00260 RenderEffect::fillin(scan, manager);
00261
00262 _off = scan.get_bool();
00263 _up_vector.read_datagram(scan);
00264 _eye_relative = scan.get_bool();
00265 _axial_rotate = scan.get_bool();
00266 _offset = scan.get_float32();
00267 _look_at_point.read_datagram(scan);
00268 }