00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00067 #include <string.h>
00068 #include "Displayable.h"
00069 #include "DispCmds.h"
00070 #include "PickList.h"
00071 #include "utilities.h"
00072 #include "VMDApp.h"
00073 #include "DisplayDevice.h"
00074
00075 void *Displayable::operator new(size_t n) {
00076 return vmd_alloc(n);
00077 }
00078
00079 void Displayable::operator delete(void *p, size_t) {
00080 vmd_dealloc(p);
00081 }
00082
00083 Displayable::Displayable(Scene *s) : scene(s) {
00084
00085 parent = NULL;
00086 scale = 1;
00087 globt[0] = globt[1] = globt[2] = 0;
00088 centt[0] = centt[1] = centt[2] = 0;
00089
00090
00091 isOn = TRUE;
00092 doCent = doRot = doGlob = doScale = TRUE;
00093 do_create();
00094 }
00095
00096 Displayable::Displayable(Displayable *pops) : scene(pops->scene) {
00097
00098 _needUpdate = 1;
00099 parent = pops;
00100
00101
00102 vec_copy(centt, parent->centt);
00103 rotm = parent->rotm;
00104 vec_copy(globt, parent->globt);
00105 scale = parent->scale;
00106 tm = parent->tm;
00107
00108 isOn = parent->displayed();
00109 doCent = parent->doCent;
00110 doRot = parent->doRot;
00111 doGlob = parent->doGlob;
00112 doScale = parent->doScale;
00113
00114
00115 do_create();
00116
00117
00118 cmdList->ambient = parent->cmdList->ambient;
00119 cmdList->specular = parent->cmdList->specular;
00120 cmdList->diffuse = parent->cmdList->diffuse;
00121 cmdList->shininess = parent->cmdList->shininess;
00122 cmdList->mirror = parent->cmdList->mirror;
00123 cmdList->opacity = parent->cmdList->opacity;
00124 cmdList->outline = parent->cmdList->outline;
00125 cmdList->outlinewidth = parent->cmdList->outlinewidth;
00126 cmdList->transmode = parent->cmdList->transmode;
00127 cmdList->materialtag = parent->cmdList->materialtag;
00128
00129
00130 cmdList->cacheskip = parent->cmdList->cacheskip;
00131
00132
00133 parent->add_child(this);
00134 }
00135
00136
00137
00138 void Displayable::do_create() {
00139
00140 children = (Displayable **)vmd_alloc(16L*sizeof(Displayable*));
00141 num_children = 0;
00142 max_children = 16;
00143
00144
00145 cmdList = new VMDDisplayList;
00146
00147
00148 needMatrixRecalc = TRUE;
00149 isFixed = FALSE;
00150
00151
00152 cmdList->mat = tm;
00153
00154 }
00155
00156
00157 void Displayable::reset_disp_list(void) {
00158 _needUpdate = 1;
00159
00160
00161
00162 cmdList->reset_and_free(VMDApp::get_repserialnum());
00163 }
00164
00165
00166 Displayable::~Displayable(void) {
00167
00168 while(num_children > 0)
00169
00170
00171 delete child(0);
00172
00173 cmdList->reset_and_free(0);
00174 delete cmdList;
00175
00176
00177 if (parent)
00178 parent->remove_child(this);
00179
00180 vmd_dealloc(children);
00181 }
00182
00183
00185
00186
00187
00188
00189 void Displayable::recalc_mat(void) {
00190 if (needMatrixRecalc) {
00191 _needUpdate = 1;
00192 tm.identity();
00193 tm.translate(globt);
00194 tm.multmatrix(rotm);
00195 tm.scale(scale);
00196 tm.translate(centt);
00197
00198 cmdList->mat = tm;
00199
00200 needMatrixRecalc = FALSE;
00201 }
00202
00203
00204 for (int i=0; i < num_children; i++)
00205 child(i)->recalc_mat();
00206 }
00207
00209
00210
00211 void Displayable::off(void) {
00212 isOn = FALSE;
00213 _needUpdate = 1;
00214 }
00215
00216 void Displayable::on(void) {
00217 isOn = TRUE;
00218 _needUpdate = 1;
00219 }
00220
00221
00222 void Displayable::add_child(Displayable *d) {
00223
00224
00225 children[num_children++] = d;
00226 if (num_children == max_children) {
00227 void *tmp = vmd_alloc(max_children*2L*sizeof(Displayable*));
00228 memcpy(tmp,children,max_children*sizeof(Displayable*));
00229 vmd_dealloc(children);
00230 children = (Displayable **)tmp;
00231 max_children *= 2;
00232 }
00233 }
00234
00235
00236
00237 int Displayable::remove_child(Displayable *d) {
00238
00239 int n = child_index(d);
00240 if (n >= 0) {
00241
00242 for (int i=n; i<num_children-1; i++) {
00243 children[i] = children[i+1];
00244 }
00245 num_children--;
00246 _needUpdate = 1;
00247 return TRUE;
00248 }
00249 return FALSE;
00250 }
00251
00252
00253
00254
00255
00256
00257 void Displayable::prepare() { }
00258
00259
00260 int Displayable::draw_prepare() {
00261 int needupdate;
00262
00263 if (parent == NULL)
00264 recalc_mat();
00265
00266 prepare();
00267
00268 needupdate = _needUpdate;
00269
00270
00271 for (int i=0; i < num_children; i++)
00272 needupdate |= child(i)->draw_prepare();
00273
00274
00275
00276
00277 _needUpdate = 0;
00278 return needupdate;
00279 }
00280
00281
00282 void Displayable::draw(DisplayDevice *d) const {
00283
00284 if (isOn) {
00285 d->render(cmdList);
00286 for (int i=0; i<num_children; i++)
00287 child(i)->draw(d);
00288 }
00289 }
00290
00291
00292
00293
00294
00295
00296
00297 void Displayable::reset_transformation(void) {
00298
00299 if (scaling()) scale=1;
00300 if (rotating()) { rotm.identity(); }
00301 if (glob_translating()) globt[0] = globt[1] = globt[2] = 0;
00302 if (cent_translating()) centt[0] = centt[1] = centt[2] = 0;
00303 need_matrix_recalc();
00304
00305
00306 for (int i=0; i < num_children; i++)
00307 child(i)->reset_transformation();
00308 }
00309
00310 void Displayable::set_scale(float s) {
00311 if (fixed()) return;
00312
00313
00314 for (int i=0; i < num_children; i++)
00315 child(i)->set_scale(s);
00316
00317 if (!scaling()) return;
00318 scale = s;
00319 need_matrix_recalc();
00320 }
00321
00322 void Displayable::mult_scale(float s) {
00323 if (fixed()) return;
00324
00325
00326 for (int i=0; i < num_children; i++)
00327 child(i)->mult_scale(s);
00328
00329 if (!scaling()) return;
00330 scale *= s;
00331 need_matrix_recalc();
00332 }
00333
00334 void Displayable::add_rot(float x, char axis) {
00335 if (fixed()) return;
00336
00337
00338 for (int i=0; i < num_children; i++)
00339 child(i)->add_rot(x, axis);
00340
00341 if (!rotating()) return;
00342
00343
00344 Matrix4 mat;
00345 mat.rot(x, axis);
00346 mat.multmatrix(rotm);
00347 rotm = mat;
00348 need_matrix_recalc();
00349 }
00350
00351 void Displayable::set_rot(float x, char axis) {
00352 if (fixed()) return;
00353
00354
00355 for (int i=0; i < num_children; i++)
00356 child(i)->set_rot(x, axis);
00357
00358 if (!rotating()) return;
00359
00360 rotm.identity();
00361 rotm.rot(x,axis);
00362 need_matrix_recalc();
00363 }
00364
00365 void Displayable::add_rot(const Matrix4 &m) {
00366 if (fixed()) return;
00367
00368
00369 for (int i=0; i < num_children; i++)
00370 child(i)->add_rot(m);
00371
00372 if (!rotating()) return;
00373 Matrix4 mat(m);
00374 mat.multmatrix(rotm);
00375 rotm = mat;
00376 need_matrix_recalc();
00377 }
00378
00379 void Displayable::set_rot(const Matrix4 &m) {
00380 if (fixed()) return;
00381
00382
00383 for (int i=0; i < num_children; i++)
00384 child(i)->set_rot(m);
00385
00386 if (!rotating()) return;
00387 rotm = m;
00388 need_matrix_recalc();
00389 }
00390
00391 void Displayable::set_glob_trans(float x, float y, float z) {
00392 if (fixed()) return;
00393
00394
00395 for (int i=0; i < num_children; i++)
00396 child(i)->set_glob_trans(x, y, z);
00397
00398 if (!glob_translating()) return;
00399 globt[0] = x;
00400 globt[1] = y;
00401 globt[2] = z;
00402 need_matrix_recalc();
00403 }
00404
00405 void Displayable::add_glob_trans(float x, float y, float z) {
00406 if (fixed()) return;
00407
00408
00409 for (int i=0; i < num_children; i++)
00410 child(i)->add_glob_trans(x, y, z);
00411
00412 if (!glob_translating()) return;
00413 globt[0] += x;
00414 globt[1] += y;
00415 globt[2] += z;
00416 need_matrix_recalc();
00417 }
00418
00419 void Displayable::set_cent_trans(float x, float y, float z) {
00420
00421 for (int i=0; i < num_children; i++)
00422 child(i)->set_cent_trans(x, y, z);
00423
00424 if (!cent_translating()) return;
00425 centt[0] = x;
00426 centt[1] = y;
00427 centt[2] = z;
00428 need_matrix_recalc();
00429 }
00430
00431 void Displayable::add_cent_trans(float x, float y, float z) {
00432
00433 for (int i=0; i < num_children; i++)
00434 child(i)->add_cent_trans(x, y, z);
00435
00436 if (!cent_translating()) return;
00437 centt[0] += x;
00438 centt[1] += y;
00439 centt[2] += z;
00440 recalc_mat();
00441 }
00442
00443 void Displayable::change_center(float x, float y, float z)
00444 {
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464 float p[4], g[4], ident[4], m[4];
00465 ident[0]=0.0; ident[1] = 0.0; ident[2]=0.0; ident[3]=1.0;
00466 p[0]=x; p[1]=y; p[2]=z; p[3]=1.0;
00467
00468
00469 tm.multpoint4d(p,g);
00470
00471
00472 Matrix4 M(rotm);
00473 M.scale(scale);
00474 M.multpoint4d(ident, m);
00475
00476
00477 set_cent_trans(-x, -y, -z);
00478
00479
00480 set_glob_trans(g[0]-m[0], g[1]-m[1], g[2]-m[2]);
00481 }
00482
00483 void Displayable::change_material(const Material *mat) {
00484 _needUpdate = 1;
00485 cmdList->ambient = mat->ambient;
00486 cmdList->specular = mat->specular;
00487 cmdList->diffuse = mat->diffuse;
00488 cmdList->shininess = mat->shininess;
00489 cmdList->mirror = mat->mirror;
00490 cmdList->opacity = mat->opacity;
00491 cmdList->outline = mat->outline;
00492 cmdList->outlinewidth = mat->outlinewidth;
00493 cmdList->transmode = mat->transmode;
00494 cmdList->materialtag = mat->ind;
00495 }
00496
00497 void Displayable::cacheskip(int onoff) {
00498 cmdList->cacheskip = onoff;
00499 }
00500
00501 int Displayable::curr_material() const {
00502 return cmdList->materialtag;
00503 }
00504
00505 void Displayable::update_material(const Material *mat) {
00506 if (mat->ind == curr_material()) change_material(mat);
00507 for (int i=0; i<num_children; i++) children[i]->update_material(mat);
00508 }
00509
00510 void Displayable::delete_material(int n, const MaterialList *mlist) {
00511 if (n == curr_material()) {
00512 change_material(mlist->material(0));
00513 }
00514 for (int i=0; i<num_children; i++) children[i]->delete_material(n, mlist);
00515 }
00516
00517
00518
00519
00520
00521
00522 VMDDisplayList *Displayable::pick_cmd_list(void) {
00523 return cmdList;
00524 }
00525
00526
00527 int Displayable::pickable_on(void) {
00528 return displayed();
00529 }
00530
00531 void Displayable::color_changed(int cat) {
00532 do_color_changed(cat);
00533 for (int i=0; i<num_children; i++) child(i)->color_changed(cat);
00534 }
00535
00536 void Displayable::color_rgb_changed(int color) {
00537 do_color_rgb_changed(color);
00538 for (int i=0; i<num_children; i++) child(i)->color_rgb_changed(color);
00539 }
00540
00541 void Displayable::color_scale_changed() {
00542 do_color_scale_changed();
00543 for (int i=0; i<num_children; i++) child(i)->color_scale_changed();
00544 }
00545