SoTrap.cc

Go to the documentation of this file.
00001 //
00002 // ********************************************************************
00003 // * License and Disclaimer                                           *
00004 // *                                                                  *
00005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
00006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
00007 // * conditions of the Geant4 Software License,  included in the file *
00008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
00009 // * include a list of copyright holders.                             *
00010 // *                                                                  *
00011 // * Neither the authors of this software system, nor their employing *
00012 // * institutes,nor the agencies providing financial support for this *
00013 // * work  make  any representation or  warranty, express or implied, *
00014 // * regarding  this  software system or assume any liability for its *
00015 // * use.  Please see the license in the file  LICENSE  and URL above *
00016 // * for the full disclaimer and the limitation of liability.         *
00017 // *                                                                  *
00018 // * This  code  implementation is the result of  the  scientific and *
00019 // * technical work of the GEANT4 collaboration.                      *
00020 // * By using,  copying,  modifying or  distributing the software (or *
00021 // * any work based  on the software)  you  agree  to acknowledge its *
00022 // * use  in  resulting  scientific  publications,  and indicate your *
00023 // * acceptance of all terms of the Geant4 Software license.          *
00024 // ********************************************************************
00025 //
00026 //
00027 //
00028 // $Id$
00029 //
00030 /*-----------------------------HEPVis----------------------------------------*/
00031 /*                                                                           */
00032 /* Node:             SoTrap                                                  */
00033 /* Description:      Represents the G4Trap Geant Geometry entity             */
00034 /* Author:           Joe Boudreau Nov 11 1996                                */
00035 /*                                                                           */
00036 /*                                                                           */
00037 /*---------------------------------------------------------------------------*/
00038 
00039 #ifdef G4VIS_BUILD_OI_DRIVER
00040 
00041 // this :
00042 #include "HEPVis/nodes/SoTrap.h"
00043 
00044 #include <assert.h>
00045 #include <cmath>
00046 #include <Inventor/SbBox.h>
00047 #include <Inventor/actions/SoGLRenderAction.h>
00048 #include <Inventor/actions/SoAction.h>
00049 #include <Inventor/fields/SoSFFloat.h>
00050 #include <Inventor/misc/SoChildList.h>
00051 #include <Inventor/nodes/SoSeparator.h>
00052 #include <Inventor/nodes/SoIndexedFaceSet.h>
00053 #include <Inventor/nodes/SoNormal.h>
00054 #include <Inventor/nodes/SoCoordinate3.h>
00055 #include <Inventor/nodes/SoNormalBinding.h>
00056 #include <Inventor/SoPrimitiveVertex.h>
00057 #include <Inventor/elements/SoTextureCoordinateElement.h>
00058 
00059 #include "HEPVis/SbMath.h"
00060 
00061 // This statement is required
00062 SO_NODE_SOURCE(SoTrap)
00063 
00064 // Constructor
00065 SoTrap::SoTrap() {
00066   // This statement is required
00067   SO_NODE_CONSTRUCTOR(SoTrap);
00068 
00069   // Data fields are initialized like this:
00070   SO_NODE_ADD_FIELD(pDz,                 (1.0));
00071   SO_NODE_ADD_FIELD(pTheta,              (0.0));
00072   SO_NODE_ADD_FIELD(pPhi,                (0.0));
00073   SO_NODE_ADD_FIELD(pDy1,                (1.0));
00074   SO_NODE_ADD_FIELD(pDx1,                (1.0));
00075   SO_NODE_ADD_FIELD(pDx2,                (1.0));
00076   SO_NODE_ADD_FIELD(pDy2,                (1.0));
00077   SO_NODE_ADD_FIELD(pDx3,                (1.0));
00078   SO_NODE_ADD_FIELD(pDx4,                (1.0));
00079   SO_NODE_ADD_FIELD(pAlp1,               (0.0));
00080   SO_NODE_ADD_FIELD(pAlp2,               (0.0));
00081   SO_NODE_ADD_FIELD(alternateRep,        (NULL));
00082   children = new SoChildList(this);
00083 }
00084 
00085 // Destructor
00086 SoTrap::~SoTrap() {
00087  delete children;
00088 }
00089 
00090 
00091 // initClass
00092 void SoTrap::initClass(){
00093   // This statement is required.
00094   SO_NODE_INIT_CLASS(SoTrap,SoShape,"Shape");
00095 }
00096 
00097 
00098 // generatePrimitives
00099 void SoTrap::generatePrimitives(SoAction *action) {
00100   // This variable is used to store each vertex
00101   SoPrimitiveVertex pv;
00102 
00103   // Access the stat from the action
00104   SoState *state = action->getState();
00105 
00106   // See if we have to use a texture coordinate function,
00107   // rather than generating explicit texture coordinates.
00108   SbBool useTexFunction=
00109     (SoTextureCoordinateElement::getType(state) == 
00110      SoTextureCoordinateElement::FUNCTION);
00111 
00112   // If we need to generate texture coordinates with a function,
00113   // we'll need an SoGLTextureCoordinateElement.  Otherwise, we'll
00114   // set up the coordinates directly.
00115   const SoTextureCoordinateElement *tce = NULL;
00116   SbVec4f texCoord;
00117   if (useTexFunction) {
00118     tce = SoTextureCoordinateElement::getInstance(state);
00119   }
00120   else {
00121     texCoord[2] = 0.0;
00122     texCoord[3] = 1.0;
00123   }
00124   SbVec3f point, normal;
00125 
00126 
00128   //----------------------------------------
00129 #define GEN_VERTEX(pv,x,y,z,s,t,nx,ny,nz)  \
00130   point.setValue(x,y,z);                   \
00131   normal.setValue(nx,ny,nz);               \
00132   if (useTexFunction) {                    \
00133     texCoord=tce->get(point,normal);       \
00134   }                                        \
00135   else {                                   \
00136     texCoord[0]=s;                         \
00137     texCoord[1]=t;                         \
00138   }                                        \
00139   pv.setPoint(point);                      \
00140   pv.setNormal(normal);                    \
00141   pv.setTextureCoords(texCoord);           \
00142   shapeVertex(&pv);
00143   //----------------------------------------
00145 
00146   const int NPOINTS=8, NFACES=6, NINDICES = NFACES*5;
00147   int indices[NINDICES] = {3,2,1,0, SO_END_FACE_INDEX,  //z back.
00148                            4,5,6,7, SO_END_FACE_INDEX,  //z front.
00149                            0,1,5,4, SO_END_FACE_INDEX,  //y up.
00150                            1,2,6,5, SO_END_FACE_INDEX,  //x left.
00151                            2,3,7,6, SO_END_FACE_INDEX,  //y down.
00152                            3,0,4,7, SO_END_FACE_INDEX}; //x right.
00153 
00154   // points for the eight vertices
00155   float TthetaCphi = FTAN(pTheta.getValue())*FCOS(pPhi.getValue());
00156   float TthetaSphi = FTAN(pTheta.getValue())*FSIN(pPhi.getValue());
00157   float Talp1 = FTAN(pAlp1.getValue()); 
00158   float Talp2 = FTAN(pAlp2.getValue());
00159 
00160   float points[NPOINTS][3];
00161   points[0][0] =  pDx2.getValue()+pDy1.getValue()*Talp1;
00162   points[0][1] =  pDy1.getValue();
00163   points[0][2] = -pDz.getValue();
00164 
00165   points[1][0] = -pDx2.getValue()+pDy1.getValue()*Talp1;
00166   points[1][1] =  pDy1.getValue();
00167   points[1][2] = -pDz.getValue();
00168 
00169   points[2][0] = -pDx1.getValue()-pDy1.getValue()*Talp1;
00170   points[2][1] = -pDy1.getValue();
00171   points[2][2] = -pDz.getValue();
00172 
00173   points[3][0] =  pDx1.getValue()-pDy1.getValue()*Talp1;
00174   points[3][1] = -pDy1.getValue();
00175   points[3][2] = -pDz.getValue();
00176 
00177   points[4][0] =  pDx4.getValue()+pDy2.getValue()*Talp2;
00178   points[4][1] =  pDy2.getValue();
00179   points[4][2] =  pDz.getValue();
00180 
00181   points[5][0] = -pDx4.getValue()+pDy2.getValue()*Talp2;
00182   points[5][1] =  pDy2.getValue();
00183   points[5][2] =  pDz.getValue();
00184 
00185   points[6][0] = -pDx3.getValue()-pDy2.getValue()*Talp2;
00186   points[6][1] = -pDy2.getValue();
00187   points[6][2] =  pDz.getValue();
00188 
00189   points[7][0] =  pDx3.getValue()-pDy2.getValue()*Talp2;
00190   points[7][1] = -pDy2.getValue();
00191   points[7][2] =  pDz.getValue();
00192 
00193   int i;
00194   for (i=0;i<4;i++) {
00195     points[i][0] -= pDz.getValue()*TthetaCphi;
00196     points[i][1] -= pDz.getValue()*TthetaSphi;
00197   }
00198   for (i=4;i<8;i++) {
00199     points[i][0] += pDz.getValue()*TthetaCphi;
00200     points[i][1] += pDz.getValue()*TthetaSphi;
00201   }
00202 
00203   SbVec3f normals[NFACES];
00204   int nf;
00205   for (nf=0;nf<NFACES;nf++) {
00206     int j0 = indices[5*nf + 0];
00207     int j1 = indices[5*nf + 1];
00208     int j2 = indices[5*nf + 2];
00209     SbVec3f p0(points[j0][0],points[j0][1],points[j0][2]); 
00210     SbVec3f p1(points[j1][0],points[j1][1],points[j1][2]); 
00211     SbVec3f p2(points[j2][0],points[j2][1],points[j2][2]); 
00212     normals[nf] = (p1-p0).cross(p2-p0);
00213     normals[nf].normalize();
00214   }
00215 
00216   float x,y,z;
00217   int   index;
00218   for (nf=0;nf<NFACES;nf++) {
00219     beginShape(action,TRIANGLE_FAN);
00220     index = indices[nf * 5];   
00221     x = points[index][0];
00222     y = points[index][1];
00223     z = points[index][2];
00224     GEN_VERTEX(pv,x,y,z,0.0,0.0,normals[nf][0],normals[nf][1],normals[nf][2]);   
00225     index = indices[nf * 5 + 1];   
00226     x = points[index][0];
00227     y = points[index][1];
00228     z = points[index][2];
00229     GEN_VERTEX(pv,x,y,z,0.0,0.0,normals[nf][0],normals[nf][1],normals[nf][2]);   
00230     index = indices[nf * 5 + 2];   
00231     x = points[index][0];
00232     y = points[index][1];
00233     z = points[index][2];
00234     GEN_VERTEX(pv,x,y,z,0.0,0.0,normals[nf][0],normals[nf][1],normals[nf][2]);   
00235     index = indices[nf * 5 + 3];   
00236     x = points[index][0];
00237     y = points[index][1];
00238     z = points[index][2];
00239     GEN_VERTEX(pv,x,y,z,0.0,0.0,normals[nf][0],normals[nf][1],normals[nf][2]);   
00240     endShape();
00241   }
00242 }
00243 
00244 // getChildren
00245 SoChildList *SoTrap::getChildren() const {
00246   return children;
00247 }
00248 
00249 
00250 // computeBBox
00251 void SoTrap::computeBBox(SoAction *, SbBox3f &box, SbVec3f &center ){
00252   float pDx= pDx1.getValue(),pDy=pDy1.getValue();
00253   
00254   if (pDx2.getValue() > pDx) pDx = pDx2.getValue(); 
00255   if (pDx3.getValue() > pDx) pDx = pDx3.getValue(); 
00256   if (pDx4.getValue() > pDx) pDx = pDx4.getValue(); 
00257   if (pDy2.getValue() > pDy) pDy = pDy2.getValue(); 
00258   float TthetaCphi = FTAN(pTheta.getValue())*FCOS(pPhi.getValue());
00259   float TthetaSphi = FTAN(pTheta.getValue())*FSIN(pPhi.getValue());
00260   float Xalp = FFABS(std::tan(pAlp1.getValue())*pDy1.getValue());
00261   float Xalp2 = FFABS(std::tan(pAlp2.getValue())*pDy2.getValue());
00262   if (Xalp< Xalp2) Xalp=Xalp2;
00263   pDx += FFABS(TthetaCphi*pDz.getValue());
00264   pDx += Xalp;
00265   pDy += FFABS(TthetaSphi*pDz.getValue());  
00266 
00267 
00268   center.setValue(0,0,0);
00269   box.setBounds(SbVec3f(-pDx,-pDy,-pDz.getValue()),
00270           SbVec3f( pDx, pDy, pDz.getValue()));
00271 }
00272 
00273 
00274 
00275 
00276 // updateChildren
00277 void SoTrap::updateChildren() {
00278 
00279 
00280   // Redraw the G4Trap....
00281 
00282   assert(children->getLength()==1);
00283   SoSeparator       *sep                = (SoSeparator *)  ( *children)[0];
00284   SoCoordinate3     *theCoordinates     = (SoCoordinate3 *)      ( sep->getChild(0));
00285   SoNormal          *theNormals         = (SoNormal *)           ( sep->getChild(1)); 
00286   SoNormalBinding   *theNormalBinding   = (SoNormalBinding *)    ( sep->getChild(2));
00287   SoIndexedFaceSet  *theFaceSet         = (SoIndexedFaceSet *)   ( sep->getChild(3));
00288 
00289   const int NPOINTS=8, NFACES=6, NINDICES = NFACES*5;
00290   float points[NPOINTS][3];
00291   // Indices for the eight faces
00292 #ifdef INVENTOR2_0
00293   static long  
00294 #else 
00295   static int32_t
00296 #endif
00297   indices[NINDICES] = {3,2,1,0, SO_END_FACE_INDEX, // bottom
00298                      4,5,6,7, SO_END_FACE_INDEX, // top
00299                      0,1,5,4, SO_END_FACE_INDEX, 
00300                      1,2,6,5, SO_END_FACE_INDEX,
00301                      2,3,7,6, SO_END_FACE_INDEX,
00302                      3,0,4,7, SO_END_FACE_INDEX};
00303 
00304   
00305   // points for the eight vertices
00306   float TthetaCphi = FTAN(pTheta.getValue())*FCOS(pPhi.getValue());
00307   float TthetaSphi = FTAN(pTheta.getValue())*FSIN(pPhi.getValue());
00308   float Talp1 = FTAN(pAlp1.getValue()); 
00309   float Talp2 = FTAN(pAlp2.getValue());
00310 
00311   points[0][0] =  pDx2.getValue()+pDy1.getValue()*Talp1;
00312   points[0][1] =  pDy1.getValue();
00313   points[0][2] = -pDz.getValue();
00314 
00315   points[1][0] = -pDx2.getValue()+pDy1.getValue()*Talp1;
00316   points[1][1] =  pDy1.getValue();
00317   points[1][2] = -pDz.getValue();
00318 
00319   points[2][0] = -pDx1.getValue()-pDy1.getValue()*Talp1;
00320   points[2][1] = -pDy1.getValue();
00321   points[2][2] = -pDz.getValue();
00322 
00323   points[3][0] =  pDx1.getValue()-pDy1.getValue()*Talp1;
00324   points[3][1] = -pDy1.getValue();
00325   points[3][2] = -pDz.getValue();
00326 
00327   points[4][0] =  pDx4.getValue()+pDy2.getValue()*Talp2;
00328   points[4][1] =  pDy2.getValue();
00329   points[4][2] =  pDz.getValue();
00330 
00331   points[5][0] = -pDx4.getValue()+pDy2.getValue()*Talp2;
00332   points[5][1] =  pDy2.getValue();
00333   points[5][2] =  pDz.getValue();
00334 
00335   points[6][0] = -pDx3.getValue()-pDy2.getValue()*Talp2;
00336   points[6][1] = -pDy2.getValue();
00337   points[6][2] =  pDz.getValue();
00338 
00339   points[7][0] =  pDx3.getValue()-pDy2.getValue()*Talp2;
00340   points[7][1] = -pDy2.getValue();
00341   points[7][2] =  pDz.getValue();
00342 
00343   int i;
00344   for (i=0;i<4;i++) {
00345     points[i][0] -= pDz.getValue()*TthetaCphi;
00346     points[i][1] -= pDz.getValue()*TthetaSphi;
00347   }
00348   for (i=4;i<8;i++) {
00349     points[i][0] += pDz.getValue()*TthetaCphi;
00350     points[i][1] += pDz.getValue()*TthetaSphi;
00351   }
00352 
00353   for (int np=0;np<NPOINTS;np++) theCoordinates->point.set1Value(np,points[np][0],points[np][1],points[np][2]);
00354   theFaceSet->coordIndex.setValues(0,NINDICES,indices);
00355   theNormals->vector.deleteValues(0);
00356   theNormals->vector.insertSpace(0,6);
00357   for (int n=0;n<6;n++) {
00358     int i0 = 5*n+0,i1=5*n+1,i2=5*n+2;
00359     int j0 = theFaceSet->coordIndex[i0];
00360     int j1 = theFaceSet->coordIndex[i1];
00361     int j2 = theFaceSet->coordIndex[i2];
00362     SbVec3f p0= theCoordinates->point[j0]; 
00363     SbVec3f p1= theCoordinates->point[j1]; 
00364     SbVec3f p2= theCoordinates->point[j2]; 
00365     SbVec3f normal = (p1-p0).cross(p2-p0);
00366     normal.normalize();
00367     theNormals->vector.set1Value(n,normal);
00368   }
00369   theNormalBinding->value=SoNormalBinding::PER_FACE;
00370 }
00371 
00372 // generateChildren
00373 void SoTrap::generateChildren() {
00374 
00375   // This routines creates one SoSeparator, one SoCoordinate3, and
00376   // one SoLineSet, and puts it in the child list.  This is done only
00377   // once, whereas redrawing the position of the coordinates occurs each
00378   // time an update is necessary, in the updateChildren routine. 
00379 
00380   assert(children->getLength() ==0);
00381   SoSeparator      *sep              = new SoSeparator(); 
00382   SoCoordinate3    *theCoordinates   = new SoCoordinate3();
00383   SoNormal         *theNormals       = new SoNormal(); 
00384   SoNormalBinding  *theNormalBinding = new SoNormalBinding();
00385   SoIndexedFaceSet *theFaceSet       = new SoIndexedFaceSet();
00386   // 
00387   // This line costs some in render quality! but gives speed.
00388   // 
00389   sep->addChild(theCoordinates);
00390   sep->addChild(theNormals);
00391   sep->addChild(theNormalBinding);
00392   sep->addChild(theFaceSet);
00393   children->append(sep);
00394 }
00395 
00396 // generateAlternateRep
00397 void SoTrap::generateAlternateRep() {
00398 
00399   // This routine sets the alternate representation to the child
00400   // list of this mode.  
00401 
00402   if (children->getLength() == 0) generateChildren();
00403   updateChildren();
00404   alternateRep.setValue((SoSeparator *)  ( *children)[0]);
00405 }
00406 
00407 // clearAlternateRep
00408 void SoTrap::clearAlternateRep() {
00409   alternateRep.setValue(NULL);
00410 }
00411 
00412 #endif

Generated on Mon May 27 17:50:34 2013 for Geant4 by  doxygen 1.4.7