00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "movingPartMatrix.h"
00017 #include "animChannelMatrixDynamic.h"
00018 #include "animChannelMatrixFixed.h"
00019 #include "compose_matrix.h"
00020 #include "datagram.h"
00021 #include "datagramIterator.h"
00022 #include "bamReader.h"
00023 #include "bamWriter.h"
00024
00025
00026 #ifdef __GNUC__
00027 #pragma implementation
00028 #endif
00029
00030 TypeHandle MovingPartMatrix::_type_handle;
00031
00032
00033
00034
00035
00036
00037 MovingPartMatrix::
00038 ~MovingPartMatrix() {
00039 }
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 AnimChannelBase *MovingPartMatrix::
00050 make_default_channel() const {
00051 LVecBase3 pos, hpr, scale, shear;
00052 decompose_matrix(_default_value, pos, hpr, scale, shear);
00053 return new AnimChannelMatrixFixed(get_name(), pos, hpr, scale);
00054 }
00055
00056
00057
00058
00059
00060
00061
00062
00063 void MovingPartMatrix::
00064 get_blend_value(const PartBundle *root) {
00065
00066
00067
00068 if (_forced_channel != (AnimChannelBase *)NULL) {
00069 ChannelType *channel = DCAST(ChannelType, _forced_channel);
00070 channel->get_value(0, _value);
00071 return;
00072 }
00073
00074 PartBundle::CDReader cdata(root->_cycler);
00075
00076 if (cdata->_blend.empty()) {
00077
00078 if (restore_initial_pose) {
00079 _value = _default_value;
00080 }
00081
00082 } else if (_effective_control != (AnimControl *)NULL &&
00083 !cdata->_frame_blend_flag) {
00084
00085 ChannelType *channel = DCAST(ChannelType, _effective_channel);
00086 channel->get_value(_effective_control->get_frame(), _value);
00087
00088 } else {
00089
00090
00091
00092 switch (cdata->_blend_type) {
00093 case PartBundle::BT_linear:
00094 {
00095
00096 LMatrix4 net_value = LMatrix4::zeros_mat();
00097 PN_stdfloat net_effect = 0.0f;
00098
00099 PartBundle::ChannelBlend::const_iterator cbi;
00100 for (cbi = cdata->_blend.begin(); cbi != cdata->_blend.end(); ++cbi) {
00101 AnimControl *control = (*cbi).first;
00102 PN_stdfloat effect = (*cbi).second;
00103 nassertv(effect != 0.0f);
00104
00105 int channel_index = control->get_channel_index();
00106 nassertv(channel_index >= 0 && channel_index < (int)_channels.size());
00107 ChannelType *channel = DCAST(ChannelType, _channels[channel_index]);
00108 if (channel != (ChannelType *)NULL) {
00109 ValueType v;
00110 channel->get_value(control->get_frame(), v);
00111
00112 if (!cdata->_frame_blend_flag) {
00113
00114 net_value += v * effect;
00115 } else {
00116
00117 PN_stdfloat frac = (PN_stdfloat)control->get_frac();
00118 net_value += v * (effect * (1.0f - frac));
00119
00120 channel->get_value(control->get_next_frame(), v);
00121 net_value += v * (effect * frac);
00122 }
00123 net_effect += effect;
00124 }
00125 }
00126
00127 if (net_effect == 0.0f) {
00128 if (restore_initial_pose) {
00129 _value = _default_value;
00130 }
00131 } else {
00132 _value = net_value / net_effect;
00133 }
00134 }
00135 break;
00136
00137 case PartBundle::BT_normalized_linear:
00138 {
00139
00140
00141
00142
00143
00144
00145 LMatrix4 net_value = LMatrix4::zeros_mat();
00146 LVecBase3 scale(0.0f, 0.0f, 0.0f);
00147 LVecBase3 shear(0.0f, 0.0f, 0.0f);
00148 PN_stdfloat net_effect = 0.0f;
00149
00150 PartBundle::ChannelBlend::const_iterator cbi;
00151 for (cbi = cdata->_blend.begin(); cbi != cdata->_blend.end(); ++cbi) {
00152 AnimControl *control = (*cbi).first;
00153 PN_stdfloat effect = (*cbi).second;
00154 nassertv(effect != 0.0f);
00155
00156 ChannelType *channel = NULL;
00157 int channel_index = control->get_channel_index();
00158 if (channel_index >= 0 && channel_index < (int)_channels.size()) {
00159 channel = DCAST(ChannelType, _channels[channel_index]);
00160 }
00161 if (channel != (ChannelType *)NULL) {
00162 int frame = control->get_frame();
00163 ValueType v;
00164 LVecBase3 iscale, ishear;
00165 channel->get_value_no_scale_shear(frame, v);
00166 channel->get_scale(frame, iscale);
00167 channel->get_shear(frame, ishear);
00168
00169 if (!cdata->_frame_blend_flag) {
00170
00171 net_value += v * effect;
00172 scale += iscale * effect;
00173 shear += ishear * effect;
00174 } else {
00175
00176 PN_stdfloat frac = (PN_stdfloat)control->get_frac();
00177 PN_stdfloat e0 = effect * (1.0f - frac);
00178 net_value += v * e0;
00179 scale += iscale * e0;
00180 shear += ishear * e0;
00181
00182 int next_frame = control->get_next_frame();
00183 channel->get_value_no_scale_shear(next_frame, v);
00184 channel->get_scale(next_frame, iscale);
00185 channel->get_shear(next_frame, ishear);
00186 PN_stdfloat e1 = effect * frac;
00187 net_value += v * e1;
00188 scale += iscale * e1;
00189 shear += ishear * e1;
00190 }
00191 net_effect += effect;
00192 }
00193 }
00194
00195 if (net_effect == 0.0f) {
00196 if (restore_initial_pose) {
00197 _value = _default_value;
00198 }
00199
00200 } else {
00201 net_value /= net_effect;
00202 scale /= net_effect;
00203 shear /= net_effect;
00204
00205
00206
00207 LVector3 false_scale, false_shear, hpr, translate;
00208 decompose_matrix(net_value, false_scale, false_shear, hpr, translate);
00209 compose_matrix(_value, scale, shear, hpr, translate);
00210 }
00211 }
00212 break;
00213
00214 case PartBundle::BT_componentwise:
00215 {
00216
00217 LVecBase3 scale(0.0f, 0.0f, 0.0f);
00218 LVecBase3 hpr(0.0f, 0.0f, 0.0f);
00219 LVecBase3 pos(0.0f, 0.0f, 0.0f);
00220 LVecBase3 shear(0.0f, 0.0f, 0.0f);
00221 PN_stdfloat net_effect = 0.0f;
00222
00223 PartBundle::ChannelBlend::const_iterator cbi;
00224 for (cbi = cdata->_blend.begin(); cbi != cdata->_blend.end(); ++cbi) {
00225 AnimControl *control = (*cbi).first;
00226 PN_stdfloat effect = (*cbi).second;
00227 nassertv(effect != 0.0f);
00228
00229 ChannelType *channel = NULL;
00230 int channel_index = control->get_channel_index();
00231 if (channel_index >= 0 && channel_index < (int)_channels.size()) {
00232 channel = DCAST(ChannelType, _channels[channel_index]);
00233 }
00234 if (channel != (ChannelType *)NULL) {
00235 int frame = control->get_frame();
00236 LVecBase3 iscale, ihpr, ipos, ishear;
00237 channel->get_scale(frame, iscale);
00238 channel->get_hpr(frame, ihpr);
00239 channel->get_pos(frame, ipos);
00240 channel->get_shear(frame, ishear);
00241
00242 if (!cdata->_frame_blend_flag) {
00243
00244 scale += iscale * effect;
00245 hpr += ihpr * effect;
00246 pos += ipos * effect;
00247 shear += ishear * effect;
00248 } else {
00249
00250 PN_stdfloat frac = (PN_stdfloat)control->get_frac();
00251 PN_stdfloat e0 = effect * (1.0f - frac);
00252
00253 scale += iscale * e0;
00254 hpr += ihpr * e0;
00255 pos += ipos * e0;
00256 shear += ishear * e0;
00257
00258 int next_frame = control->get_next_frame();
00259 channel->get_scale(next_frame, iscale);
00260 channel->get_hpr(next_frame, ihpr);
00261 channel->get_pos(next_frame, ipos);
00262 channel->get_shear(next_frame, ishear);
00263 PN_stdfloat e1 = effect * frac;
00264
00265 scale += iscale * e1;
00266 hpr += ihpr * e1;
00267 pos += ipos * e1;
00268 shear += ishear * e1;
00269 }
00270 net_effect += effect;
00271 }
00272 }
00273
00274 if (net_effect == 0.0f) {
00275 if (restore_initial_pose) {
00276 _value = _default_value;
00277 }
00278
00279 } else {
00280 scale /= net_effect;
00281 hpr /= net_effect;
00282 pos /= net_effect;
00283 shear /= net_effect;
00284
00285 compose_matrix(_value, scale, shear, hpr, pos);
00286 }
00287 }
00288 break;
00289
00290 case PartBundle::BT_componentwise_quat:
00291 {
00292
00293
00294 LVecBase3 scale(0.0f, 0.0f, 0.0f);
00295 LQuaternion quat(0.0f, 0.0f, 0.0f, 0.0f);
00296 LVecBase3 pos(0.0f, 0.0f, 0.0f);
00297 LVecBase3 shear(0.0f, 0.0f, 0.0f);
00298 PN_stdfloat net_effect = 0.0f;
00299
00300 PartBundle::ChannelBlend::const_iterator cbi;
00301 for (cbi = cdata->_blend.begin(); cbi != cdata->_blend.end(); ++cbi) {
00302 AnimControl *control = (*cbi).first;
00303 PN_stdfloat effect = (*cbi).second;
00304 nassertv(effect != 0.0f);
00305
00306 ChannelType *channel = NULL;
00307 int channel_index = control->get_channel_index();
00308 if (channel_index >= 0 && channel_index < (int)_channels.size()) {
00309 channel = DCAST(ChannelType, _channels[channel_index]);
00310 }
00311 if (channel != (ChannelType *)NULL) {
00312 int frame = control->get_frame();
00313 LVecBase3 iscale, ipos, ishear;
00314 LQuaternion iquat;
00315 channel->get_scale(frame, iscale);
00316 channel->get_quat(frame, iquat);
00317 channel->get_pos(frame, ipos);
00318 channel->get_shear(frame, ishear);
00319
00320 if (!cdata->_frame_blend_flag) {
00321
00322 scale += iscale * effect;
00323 quat += iquat * effect;
00324 pos += ipos * effect;
00325 shear += ishear * effect;
00326
00327 } else {
00328
00329 PN_stdfloat frac = (PN_stdfloat)control->get_frac();
00330 PN_stdfloat e0 = effect * (1.0f - frac);
00331
00332 scale += iscale * e0;
00333 quat += iquat * e0;
00334 pos += ipos * e0;
00335 shear += ishear * e0;
00336
00337 int next_frame = control->get_next_frame();
00338 channel->get_scale(next_frame, iscale);
00339 channel->get_quat(next_frame, iquat);
00340 channel->get_pos(next_frame, ipos);
00341 channel->get_shear(next_frame, ishear);
00342 PN_stdfloat e1 = effect * frac;
00343
00344 scale += iscale * e1;
00345 quat += iquat * e1;
00346 pos += ipos * e1;
00347 shear += ishear * e1;
00348 }
00349 net_effect += effect;
00350 }
00351 }
00352
00353 if (net_effect == 0.0f) {
00354 if (restore_initial_pose) {
00355 _value = _default_value;
00356 }
00357
00358 } else {
00359 scale /= net_effect;
00360 quat /= net_effect;
00361 pos /= net_effect;
00362 shear /= net_effect;
00363
00364
00365
00366
00367
00368 _value = LMatrix4::scale_shear_mat(scale, shear) * quat;
00369 _value.set_row(3, pos);
00370 }
00371 }
00372 break;
00373 }
00374 }
00375 }
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386 bool MovingPartMatrix::
00387 apply_freeze_matrix(const LVecBase3 &pos, const LVecBase3 &hpr, const LVecBase3 &scale) {
00388 _forced_channel = new AnimChannelMatrixFixed(get_name(), pos, hpr, scale);
00389 return true;
00390 }
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401 bool MovingPartMatrix::
00402 apply_control(PandaNode *node) {
00403 AnimChannelMatrixDynamic *chan = new AnimChannelMatrixDynamic(get_name());
00404 chan->set_value_node(node);
00405 _forced_channel = chan;
00406 return true;
00407 }
00408
00409
00410
00411
00412
00413
00414 TypedWritable* MovingPartMatrix::
00415 make_MovingPartMatrix(const FactoryParams ¶ms) {
00416 MovingPartMatrix *me = new MovingPartMatrix;
00417 DatagramIterator scan;
00418 BamReader *manager;
00419
00420 parse_params(params, scan, manager);
00421 me->fillin(scan, manager);
00422 return me;
00423 }
00424
00425
00426
00427
00428
00429
00430 void MovingPartMatrix::
00431 register_with_read_factory() {
00432 BamReader::get_factory()->register_factory(get_class_type(), make_MovingPartMatrix);
00433 }