Main Page Namespace List Class Hierarchy Alphabetical List Compound List File List Namespace Members Compound Members File Members Related Pages

Displayable.C

Go to the documentation of this file.
00001 /***************************************************************************
00002 *cr 
00003 *cr (C) Copyright 1995-2019 The Board of Trustees of the 
00004 *cr University of Illinois 
00005 *cr All Rights Reserved 
00006 *cr 
00007 ***************************************************************************/
00008 /***************************************************************************
00009 * RCS INFORMATION:
00010 *
00011 * $RCSfile: Displayable.C,v $
00012 * $Author: johns $ $Locker: $ $State: Exp $
00013 * $Revision: 1.119 $ $Date: 2020年02月26日 03:51:30 $
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 // Initialize scaling and other transformations, since we're a parent 
00085 parent = NULL;
00086 scale = 1;
00087 globt[0] = globt[1] = globt[2] = 0;
00088 centt[0] = centt[1] = centt[2] = 0;
00089 
00090 // get values for this items as default values
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; // default to needing an update
00099 parent = pops;
00100 
00101 // get copies of all of parents tranformation matrices from parent
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 // do common creation action
00115 do_create();
00116 
00117 // take initial material settings from parent
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 // inherit cacheability from parent
00130 cmdList->cacheskip = parent->cmdList->cacheskip;
00131 
00132 // finally, add this Displayable as a child to the parent
00133 parent->add_child(this);
00134 }
00135 
00136 
00137 // does all the creation work after variables have been initialized
00138 void Displayable::do_create() {
00139 
00140 children = (Displayable **)vmd_alloc(16L*sizeof(Displayable*));
00141 num_children = 0;
00142 max_children = 16;
00143 
00144 // initialize the display command list 
00145 cmdList = new VMDDisplayList;
00146 
00147 // initialize flags and scalar settings
00148 needMatrixRecalc = TRUE;
00149 isFixed = FALSE;
00150 
00151 // initialize display list
00152 cmdList->mat = tm;
00153 
00154 }
00155 
00156 // reset the display command list; remove all current commands
00157 void Displayable::reset_disp_list(void) {
00158 _needUpdate = 1;
00159 
00160 // Must use a unique rep serial number, so that display list caching
00161 // works correctly in the rendering code
00162 cmdList->reset_and_free(VMDApp::get_repserialnum()); 
00163 }
00164 
00165 // destructor; free up allocated space
00166 Displayable::~Displayable(void) {
00167 // delete all children still around; also unregistered them
00168 while(num_children > 0)
00169 // delete first child object, the child destructor then removes the
00170 // child from this parent's list, until there are no more
00171 delete child(0);
00172 
00173 cmdList->reset_and_free(0); // free space allocated for disp storage
00174 delete cmdList; // free the cmdList itself back to scene memory
00175 
00176 // if this is a child, remove it from it's parent's list of children
00177 if (parent)
00178 parent->remove_child(this);
00179 
00180 vmd_dealloc(children);
00181 }
00182 
00183 
00185 
00186 // recalculate the transformation matrix, and replace matrix in cmdList
00187 // This is composed of these operations (applied as R to L):
00188 // TM = GlobalTrans * Scale * Rotation * CenterTrans
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 // reload this matrix in the display command list
00198 cmdList->mat = tm;
00199 
00200 needMatrixRecalc = FALSE;
00201 }
00202 
00203 // recalc matrix for all children
00204 for (int i=0; i < num_children; i++)
00205 child(i)->recalc_mat();
00206 }
00207 
00209 
00210 // turn this object on or off
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 // add the given Displayable as a child (assuming it is one)
00222 void Displayable::add_child(Displayable *d) {
00223 
00224 // append child to list of children
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 // remove the given Displayable as a child. return success.
00237 int Displayable::remove_child(Displayable *d) {
00238 // remove first child that matches the pointer, if available.
00239 int n = child_index(d);
00240 if (n >= 0) {
00241 // copy the entries from children+n+1 
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 // prepare/update routines
00254 //
00255 
00256 // prepare for drawing, called by draw_prepare, supplied by derived class.
00257 void Displayable::prepare() { }
00258 
00259 // prepare to draw; possibly recalc the trans matrix, and do particular preps
00260 int Displayable::draw_prepare() {
00261 int needupdate;
00262 
00263 if (parent == NULL)
00264 recalc_mat(); // update matrix if this is a parent Displayable
00265 
00266 prepare(); // do derived class preparations for this object
00267 
00268 needupdate = _needUpdate; // cache update state before we clear it
00269 
00270 // prepare child displayables; done after the parent has been prepared.
00271 for (int i=0; i < num_children; i++)
00272 needupdate |= child(i)->draw_prepare();
00273 
00274 // set the _needUpdate flag to zero _after_ all children have been updated
00275 // so that they can check (through needUpdate() if their parent has been
00276 // updated. DrawForce currently uses this to determine whether to redraw. 
00277 _needUpdate = 0; // once we've been prepared, we're ready to draw
00278 return needupdate; // return whether this or child displayables need updating
00279 }
00280 
00281 // do the actual drawing
00282 void Displayable::draw(DisplayDevice *d) const {
00283 // only render myself and my children if parent is turned on
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 // commands to change transformation
00294 //
00295 
00296 // reset the transformation to the identity matrix
00297 void Displayable::reset_transformation(void) {
00298 // only reset if we're not fixed and given operations are allowed
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 // do reset for all children as well
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; // only transform unfixed objects
00312 
00313 // do trans for all children as well
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; // only transform unfixed objects
00324 
00325 // do trans for all children as well
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; // only transform unfixed objects
00336 
00337 // do trans for all children as well
00338 for (int i=0; i < num_children; i++)
00339 child(i)->add_rot(x, axis);
00340 
00341 if (!rotating()) return;
00342 
00343 // Need to apply the new rotation first
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; // only transform unfixed objects
00353 
00354 // do trans for all children as well
00355 for (int i=0; i < num_children; i++)
00356 child(i)->set_rot(x, axis);
00357 
00358 if (!rotating()) return;
00359 // apply rotation to identity, and then multiply this by old rot matrix
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; // only transform unfixed objects
00367 
00368 // do trans for all children as well
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; // only transform unfixed objects
00381 
00382 // do trans for all children as well
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; // only transform unfixed objects
00393 
00394 // do trans for all children as well
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; // only transform unfixed objects
00407 
00408 // do trans for all children as well
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 // do trans for all children as well
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 // do trans for all children as well
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 // Here's the math:
00446 // T = global translation (offset) matrix
00447 // M = scaling*rotation matrix
00448 // C = centering (offset) matrix
00449 // p = picked point
00450 // x = any point
00451 // and let G = T*M*C, the global transformation
00452 
00453 // the current transformation is: T*M*C * p
00454 // I want a new T', C' such that
00455 // C' * p = {0 0 0 1}
00456 // and
00457 // T'*M*C' * x = T M C x
00458 
00459 // JRG: Here's my new math:
00460 // C' * p = {0 0 0 1} so T' M C' p = G p = T' M {0 0 0 1}
00461 // Hence T' = translate( G*p - M*{0 0 0 1} )
00462 // and we don't need any inverses
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 // Set g = G * p
00469 tm.multpoint4d(p,g);
00470 
00471 // Set m = M * {0 0 0 1}
00472 Matrix4 M(rotm);
00473 M.scale(scale);
00474 M.multpoint4d(ident, m);
00475 
00476 // and apply the result
00477 set_cent_trans(-x, -y, -z);
00478 
00479 // Set Tprime = translate(g - m)
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)); // 0th material can't be deleted 
00513 }
00514 for (int i=0; i<num_children; i++) children[i]->delete_material(n, mlist);
00515 }
00516 
00517 //
00518 // routines for working as a Pickable
00519 //
00520 
00521 // return our list of draw commands with picking draw commands in them
00522 VMDDisplayList *Displayable::pick_cmd_list(void) {
00523 return cmdList;
00524 }
00525 
00526 // return whether the pickable object is being displayed
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 

Generated on Mon Nov 17 02:46:05 2025 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002

AltStyle によって変換されたページ (->オリジナル) /