ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SoTrap.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file SoTrap.cc
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 //
27 //
28 //
29 /*-----------------------------HEPVis----------------------------------------*/
30 /* */
31 /* Node: SoTrap */
32 /* Description: Represents the G4Trap Geant Geometry entity */
33 /* Author: Joe Boudreau Nov 11 1996 */
34 /* */
35 /* */
36 /*---------------------------------------------------------------------------*/
37 
38 #ifdef G4VIS_BUILD_OI_DRIVER
39 
40 // this :
41 #include "HEPVis/nodes/SoTrap.h"
42 
43 #include <assert.h>
44 #include <cmath>
45 #include <Inventor/SbBox.h>
46 #include <Inventor/actions/SoGLRenderAction.h>
47 #include <Inventor/actions/SoAction.h>
48 #include <Inventor/fields/SoSFFloat.h>
49 #include <Inventor/misc/SoChildList.h>
50 #include <Inventor/nodes/SoSeparator.h>
51 #include <Inventor/nodes/SoIndexedFaceSet.h>
52 #include <Inventor/nodes/SoNormal.h>
53 #include <Inventor/nodes/SoCoordinate3.h>
54 #include <Inventor/nodes/SoNormalBinding.h>
55 #include <Inventor/SoPrimitiveVertex.h>
56 #include <Inventor/elements/SoTextureCoordinateElement.h>
57 
58 #include "HEPVis/SbMath.h"
59 
60 // This statement is required
61 SO_NODE_SOURCE(SoTrap)
62 
63 // Constructor
64 SoTrap::SoTrap() {
65  // This statement is required
66  SO_NODE_CONSTRUCTOR(SoTrap);
67 
68  // Data fields are initialized like this:
69  SO_NODE_ADD_FIELD(pDz, (1.0));
70  SO_NODE_ADD_FIELD(pTheta, (0.0));
71  SO_NODE_ADD_FIELD(pPhi, (0.0));
72  SO_NODE_ADD_FIELD(pDy1, (1.0));
73  SO_NODE_ADD_FIELD(pDx1, (1.0));
74  SO_NODE_ADD_FIELD(pDx2, (1.0));
75  SO_NODE_ADD_FIELD(pDy2, (1.0));
76  SO_NODE_ADD_FIELD(pDx3, (1.0));
77  SO_NODE_ADD_FIELD(pDx4, (1.0));
78  SO_NODE_ADD_FIELD(pAlp1, (0.0));
79  SO_NODE_ADD_FIELD(pAlp2, (0.0));
80  SO_NODE_ADD_FIELD(alternateRep, (NULL));
81  children = new SoChildList(this);
82 }
83 
84 // Destructor
86  delete children;
87 }
88 
89 
90 // initClass
91 void SoTrap::initClass(){
92  // This statement is required.
93  SO_NODE_INIT_CLASS(SoTrap,SoShape,"Shape");
94 }
95 
96 
97 // generatePrimitives
98 void SoTrap::generatePrimitives(SoAction *action) {
99  // This variable is used to store each vertex
100  SoPrimitiveVertex pv;
101 
102  // Access the stat from the action
103  SoState *state = action->getState();
104 
105  // See if we have to use a texture coordinate function,
106  // rather than generating explicit texture coordinates.
107  SbBool useTexFunction=
108  (SoTextureCoordinateElement::getType(state) ==
109  SoTextureCoordinateElement::FUNCTION);
110 
111  // If we need to generate texture coordinates with a function,
112  // we'll need an SoGLTextureCoordinateElement. Otherwise, we'll
113  // set up the coordinates directly.
114  const SoTextureCoordinateElement *tce = NULL;
115  SbVec4f texCoord;
116  if (useTexFunction) {
117  tce = SoTextureCoordinateElement::getInstance(state);
118  }
119  else {
120  texCoord[2] = 0.0;
121  texCoord[3] = 1.0;
122  }
123  SbVec3f point, normal;
124 
125 
127  //----------------------------------------
128 #define GEN_VERTEX(pv,x,y,z,s,t,nx,ny,nz) \
129  point.setValue(x,y,z); \
130  normal.setValue(nx,ny,nz); \
131  if (useTexFunction) { \
132  texCoord=tce->get(point,normal); \
133  } \
134  else { \
135  texCoord[0]=s; \
136  texCoord[1]=t; \
137  } \
138  pv.setPoint(point); \
139  pv.setNormal(normal); \
140  pv.setTextureCoords(texCoord); \
141  shapeVertex(&pv);
142  //----------------------------------------
144 
145  const int NPOINTS=8, NFACES=6, NINDICES = NFACES*5;
146  int indices[NINDICES] = {3,2,1,0, SO_END_FACE_INDEX, //z back.
147  4,5,6,7, SO_END_FACE_INDEX, //z front.
148  0,1,5,4, SO_END_FACE_INDEX, //y up.
149  1,2,6,5, SO_END_FACE_INDEX, //x left.
150  2,3,7,6, SO_END_FACE_INDEX, //y down.
151  3,0,4,7, SO_END_FACE_INDEX}; //x right.
152 
153  // points for the eight vertices
154  float TthetaCphi = FTAN(pTheta.getValue())*FCOS(pPhi.getValue());
155  float TthetaSphi = FTAN(pTheta.getValue())*FSIN(pPhi.getValue());
156  float Talp1 = FTAN(pAlp1.getValue());
157  float Talp2 = FTAN(pAlp2.getValue());
158 
159  float points[NPOINTS][3];
160  points[0][0] = pDx2.getValue()+pDy1.getValue()*Talp1;
161  points[0][1] = pDy1.getValue();
162  points[0][2] = -pDz.getValue();
163 
164  points[1][0] = -pDx2.getValue()+pDy1.getValue()*Talp1;
165  points[1][1] = pDy1.getValue();
166  points[1][2] = -pDz.getValue();
167 
168  points[2][0] = -pDx1.getValue()-pDy1.getValue()*Talp1;
169  points[2][1] = -pDy1.getValue();
170  points[2][2] = -pDz.getValue();
171 
172  points[3][0] = pDx1.getValue()-pDy1.getValue()*Talp1;
173  points[3][1] = -pDy1.getValue();
174  points[3][2] = -pDz.getValue();
175 
176  points[4][0] = pDx4.getValue()+pDy2.getValue()*Talp2;
177  points[4][1] = pDy2.getValue();
178  points[4][2] = pDz.getValue();
179 
180  points[5][0] = -pDx4.getValue()+pDy2.getValue()*Talp2;
181  points[5][1] = pDy2.getValue();
182  points[5][2] = pDz.getValue();
183 
184  points[6][0] = -pDx3.getValue()-pDy2.getValue()*Talp2;
185  points[6][1] = -pDy2.getValue();
186  points[6][2] = pDz.getValue();
187 
188  points[7][0] = pDx3.getValue()-pDy2.getValue()*Talp2;
189  points[7][1] = -pDy2.getValue();
190  points[7][2] = pDz.getValue();
191 
192  int i;
193  for (i=0;i<4;i++) {
194  points[i][0] -= pDz.getValue()*TthetaCphi;
195  points[i][1] -= pDz.getValue()*TthetaSphi;
196  }
197  for (i=4;i<8;i++) {
198  points[i][0] += pDz.getValue()*TthetaCphi;
199  points[i][1] += pDz.getValue()*TthetaSphi;
200  }
201 
202  SbVec3f normals[NFACES];
203  int nf;
204  for (nf=0;nf<NFACES;nf++) {
205  int j0 = indices[5*nf + 0];
206  int j1 = indices[5*nf + 1];
207  int j2 = indices[5*nf + 2];
208  SbVec3f p0(points[j0][0],points[j0][1],points[j0][2]);
209  SbVec3f p1(points[j1][0],points[j1][1],points[j1][2]);
210  SbVec3f p2(points[j2][0],points[j2][1],points[j2][2]);
211  normals[nf] = (p1-p0).cross(p2-p0);
212  normals[nf].normalize();
213  }
214 
215  float x,y,z;
216  int index;
217  for (nf=0;nf<NFACES;nf++) {
218  beginShape(action,TRIANGLE_FAN);
219  index = indices[nf * 5];
220  x = points[index][0];
221  y = points[index][1];
222  z = points[index][2];
223  GEN_VERTEX(pv,x,y,z,0.0,0.0,normals[nf][0],normals[nf][1],normals[nf][2]);
224  index = indices[nf * 5 + 1];
225  x = points[index][0];
226  y = points[index][1];
227  z = points[index][2];
228  GEN_VERTEX(pv,x,y,z,0.0,0.0,normals[nf][0],normals[nf][1],normals[nf][2]);
229  index = indices[nf * 5 + 2];
230  x = points[index][0];
231  y = points[index][1];
232  z = points[index][2];
233  GEN_VERTEX(pv,x,y,z,0.0,0.0,normals[nf][0],normals[nf][1],normals[nf][2]);
234  index = indices[nf * 5 + 3];
235  x = points[index][0];
236  y = points[index][1];
237  z = points[index][2];
238  GEN_VERTEX(pv,x,y,z,0.0,0.0,normals[nf][0],normals[nf][1],normals[nf][2]);
239  endShape();
240  }
241 }
242 
243 // getChildren
244 SoChildList *SoTrap::getChildren() const {
245  return children;
246 }
247 
248 
249 // computeBBox
250 void SoTrap::computeBBox(SoAction *, SbBox3f &box, SbVec3f &center ){
251  float pDx= pDx1.getValue(),pDy=pDy1.getValue();
252 
253  if (pDx2.getValue() > pDx) pDx = pDx2.getValue();
254  if (pDx3.getValue() > pDx) pDx = pDx3.getValue();
255  if (pDx4.getValue() > pDx) pDx = pDx4.getValue();
256  if (pDy2.getValue() > pDy) pDy = pDy2.getValue();
257  float TthetaCphi = FTAN(pTheta.getValue())*FCOS(pPhi.getValue());
258  float TthetaSphi = FTAN(pTheta.getValue())*FSIN(pPhi.getValue());
259  float Xalp = FFABS(std::tan(pAlp1.getValue())*pDy1.getValue());
260  float Xalp2 = FFABS(std::tan(pAlp2.getValue())*pDy2.getValue());
261  if (Xalp< Xalp2) Xalp=Xalp2;
262  pDx += FFABS(TthetaCphi*pDz.getValue());
263  pDx += Xalp;
264  pDy += FFABS(TthetaSphi*pDz.getValue());
265 
266 
267  center.setValue(0,0,0);
268  box.setBounds(SbVec3f(-pDx,-pDy,-pDz.getValue()),
269  SbVec3f( pDx, pDy, pDz.getValue()));
270 }
271 
272 
273 
274 
275 // updateChildren
276 void SoTrap::updateChildren() {
277 
278 
279  // Redraw the G4Trap....
280 
281  assert(children->getLength()==1);
282  SoSeparator *sep = (SoSeparator *) ( *children)[0];
283  SoCoordinate3 *theCoordinates = (SoCoordinate3 *) ( sep->getChild(0));
284  SoNormal *theNormals = (SoNormal *) ( sep->getChild(1));
285  SoNormalBinding *theNormalBinding = (SoNormalBinding *) ( sep->getChild(2));
286  SoIndexedFaceSet *theFaceSet = (SoIndexedFaceSet *) ( sep->getChild(3));
287 
288  const int NPOINTS=8, NFACES=6, NINDICES = NFACES*5;
289  float points[NPOINTS][3];
290  // Indices for the eight faces
291 #ifdef INVENTOR2_0
292  static long
293 #else
294  static int32_t
295 #endif
296  indices[NINDICES] = {3,2,1,0, SO_END_FACE_INDEX, // bottom
297  4,5,6,7, SO_END_FACE_INDEX, // top
298  0,1,5,4, SO_END_FACE_INDEX,
299  1,2,6,5, SO_END_FACE_INDEX,
300  2,3,7,6, SO_END_FACE_INDEX,
301  3,0,4,7, SO_END_FACE_INDEX};
302 
303 
304  // points for the eight vertices
305  float TthetaCphi = FTAN(pTheta.getValue())*FCOS(pPhi.getValue());
306  float TthetaSphi = FTAN(pTheta.getValue())*FSIN(pPhi.getValue());
307  float Talp1 = FTAN(pAlp1.getValue());
308  float Talp2 = FTAN(pAlp2.getValue());
309 
310  points[0][0] = pDx2.getValue()+pDy1.getValue()*Talp1;
311  points[0][1] = pDy1.getValue();
312  points[0][2] = -pDz.getValue();
313 
314  points[1][0] = -pDx2.getValue()+pDy1.getValue()*Talp1;
315  points[1][1] = pDy1.getValue();
316  points[1][2] = -pDz.getValue();
317 
318  points[2][0] = -pDx1.getValue()-pDy1.getValue()*Talp1;
319  points[2][1] = -pDy1.getValue();
320  points[2][2] = -pDz.getValue();
321 
322  points[3][0] = pDx1.getValue()-pDy1.getValue()*Talp1;
323  points[3][1] = -pDy1.getValue();
324  points[3][2] = -pDz.getValue();
325 
326  points[4][0] = pDx4.getValue()+pDy2.getValue()*Talp2;
327  points[4][1] = pDy2.getValue();
328  points[4][2] = pDz.getValue();
329 
330  points[5][0] = -pDx4.getValue()+pDy2.getValue()*Talp2;
331  points[5][1] = pDy2.getValue();
332  points[5][2] = pDz.getValue();
333 
334  points[6][0] = -pDx3.getValue()-pDy2.getValue()*Talp2;
335  points[6][1] = -pDy2.getValue();
336  points[6][2] = pDz.getValue();
337 
338  points[7][0] = pDx3.getValue()-pDy2.getValue()*Talp2;
339  points[7][1] = -pDy2.getValue();
340  points[7][2] = pDz.getValue();
341 
342  int i;
343  for (i=0;i<4;i++) {
344  points[i][0] -= pDz.getValue()*TthetaCphi;
345  points[i][1] -= pDz.getValue()*TthetaSphi;
346  }
347  for (i=4;i<8;i++) {
348  points[i][0] += pDz.getValue()*TthetaCphi;
349  points[i][1] += pDz.getValue()*TthetaSphi;
350  }
351 
352  for (int np=0;np<NPOINTS;np++) theCoordinates->point.set1Value(np,points[np][0],points[np][1],points[np][2]);
353  theFaceSet->coordIndex.setValues(0,NINDICES,indices);
354  theNormals->vector.deleteValues(0);
355  theNormals->vector.insertSpace(0,6);
356  for (int n=0;n<6;n++) {
357  int i0 = 5*n+0,i1=5*n+1,i2=5*n+2;
358  int j0 = theFaceSet->coordIndex[i0];
359  int j1 = theFaceSet->coordIndex[i1];
360  int j2 = theFaceSet->coordIndex[i2];
361  SbVec3f p0= theCoordinates->point[j0];
362  SbVec3f p1= theCoordinates->point[j1];
363  SbVec3f p2= theCoordinates->point[j2];
364  SbVec3f normal = (p1-p0).cross(p2-p0);
365  normal.normalize();
366  theNormals->vector.set1Value(n,normal);
367  }
368  theNormalBinding->value=SoNormalBinding::PER_FACE;
369 }
370 
371 // generateChildren
373 
374  // This routines creates one SoSeparator, one SoCoordinate3, and
375  // one SoLineSet, and puts it in the child list. This is done only
376  // once, whereas redrawing the position of the coordinates occurs each
377  // time an update is necessary, in the updateChildren routine.
378 
379  assert(children->getLength() ==0);
380  SoSeparator *sep = new SoSeparator();
381  SoCoordinate3 *theCoordinates = new SoCoordinate3();
382  SoNormal *theNormals = new SoNormal();
383  SoNormalBinding *theNormalBinding = new SoNormalBinding();
384  SoIndexedFaceSet *theFaceSet = new SoIndexedFaceSet();
385  //
386  // This line costs some in render quality! but gives speed.
387  //
388  sep->addChild(theCoordinates);
389  sep->addChild(theNormals);
390  sep->addChild(theNormalBinding);
391  sep->addChild(theFaceSet);
392  children->append(sep);
393 }
394 
395 // generateAlternateRep
397 
398  // This routine sets the alternate representation to the child
399  // list of this mode.
400 
401  if (children->getLength() == 0) generateChildren();
402  updateChildren();
403  alternateRep.setValue((SoSeparator *) ( *children)[0]);
404 }
405 
406 // clearAlternateRep
408  alternateRep.setValue(NULL);
409 }
410 
411 #endif