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 Thu Mar 28 02:43:06 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002