43#include <Inventor/SbBox.h>
44#include <Inventor/actions/SoGLRenderAction.h>
45#include <Inventor/fields/SoSFFloat.h>
46#include <Inventor/misc/SoChildList.h>
47#include <Inventor/nodes/SoSeparator.h>
48#include <Inventor/nodes/SoIndexedFaceSet.h>
49#include <Inventor/nodes/SoNormal.h>
50#include <Inventor/nodes/SoCoordinate3.h>
51#include <Inventor/nodes/SoNormalBinding.h>
52#include <Inventor/SoPrimitiveVertex.h>
53#include <Inventor/elements/SoTextureCoordinateElement.h>
65 SO_NODE_CONSTRUCTOR(
SoTubs);
68 SO_NODE_ADD_FIELD(pRMin, (0));
69 SO_NODE_ADD_FIELD(pRMax, (1));
70 SO_NODE_ADD_FIELD(pDz, (10));
71 SO_NODE_ADD_FIELD(pSPhi, (0));
72 SO_NODE_ADD_FIELD(pDPhi, ((
float)(2*
M_PI)));
73 SO_NODE_ADD_FIELD(alternateRep, (NULL));
74 children =
new SoChildList(
this);
86 static bool first =
true;
89 SO_NODE_INIT_CLASS(
SoTubs,SoShape,
"Shape");
99 SoState *state =
action->getState();
103 SbBool useTexFunction=
104 (SoTextureCoordinateElement::getType(state) ==
105 SoTextureCoordinateElement::FUNCTION);
110 const SoTextureCoordinateElement* tce = NULL;
112 if (useTexFunction) {
113 tce = SoTextureCoordinateElement::getInstance(state);
124#define GEN_VERTEX(pv,x,y,z,s,t,nx,ny,nz) \
125 point.setValue((float)(x),(float)(y),(float)(z)); \
126 normal.setValue((float)(nx),(float)(ny),(float)(nz)); \
127 if (useTexFunction) { \
128 texCoord=tce->get(point,normal); \
130 texCoord[0]=(float)(s); \
131 texCoord[1]=(float)(t); \
133 pv.setPoint(point); \
134 pv.setNormal(normal); \
135 pv.setTextureCoords(texCoord); \
140 int NPHI = (int)(2+22*std::fabs(
pDPhi.getValue()/(2.0*
M_PI)));
141 double deltaPhi =
pDPhi.getValue()/NPHI, phi0 =
pSPhi.getValue(),phi1=phi0+
pDPhi.getValue();
142 double rMax=
pRMax.getValue(),rMin=
pRMin.getValue();
143 double zMax=
pDz.getValue(),zMin=-zMax;
144 double cosPhi0=std::cos(phi0), sinPhi0=std::sin(phi0);
145 double cosPhi1=std::cos(phi1), sinPhi1=std::sin(phi1);
146 double cosDeltaPhi=std::cos(deltaPhi),sinDeltaPhi=std::sin(deltaPhi);
151 double sinPhi,cosPhi;
152 beginShape(
action,TRIANGLE_STRIP);
155 for (i = 0; i<=NPHI; i++) {
156 GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi,zMax,0.0,0.0,cosPhi,sinPhi,0);
157 GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi,zMin,1.0,1.0,cosPhi,sinPhi,0);
158 inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);
165 beginShape(
action,TRIANGLE_STRIP);
168 for (i = 0; i<=NPHI; i++) {
169 GEN_VERTEX(pv,rMin*cosPhi,rMin*sinPhi,zMax,0.0,0.0,-cosPhi,-sinPhi,0);
170 GEN_VERTEX(pv,rMin*cosPhi,rMin*sinPhi,zMin,1.0,1.0,-cosPhi,-sinPhi,0);
171 inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);
175 if (std::fabs(deltaPhi)<2.0*
M_PI) {
179 beginShape(
action,TRIANGLE_STRIP);
182 GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi,zMax,0.0,0.0,sinPhi,-cosPhi,0);
183 GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi,zMin,1.0,1.0,sinPhi,-cosPhi,0);
184 GEN_VERTEX(pv,rMin*cosPhi,rMin*sinPhi,zMax,1.0,0.0,sinPhi,-cosPhi,0);
185 GEN_VERTEX(pv,rMin*cosPhi,rMin*sinPhi,zMin,0.0,1.0,sinPhi,-cosPhi,0);
190 beginShape(
action,TRIANGLE_STRIP);
193 GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi, zMax,0.0,0.0,-sinPhi,+cosPhi,0);
194 GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi, zMin,1.0,1.0,-sinPhi,+cosPhi,0);
195 GEN_VERTEX(pv,rMin*cosPhi,rMin*sinPhi, zMax,1.0,0.0,-sinPhi,+cosPhi,0);
196 GEN_VERTEX(pv,rMin*cosPhi,rMin*sinPhi, zMin,0.0,1.0,-sinPhi,+cosPhi,0);
203 beginShape(
action,TRIANGLE_FAN);
207 for (i = 0; i<=NPHI; i++) {
208 GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi,zMax,1.0,1.0,0,0,1);
209 inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);
215 beginShape(
action,TRIANGLE_FAN);
219 for (i = 0; i<=NPHI; i++) {
220 GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi,zMin,1.0,1.0,0,0,-1);
221 inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);
225 beginShape(
action,TRIANGLE_STRIP);
228 for (i = 0; i<=NPHI; i++) {
229 GEN_VERTEX(pv,rMin*cosPhi,rMin*sinPhi,zMax,0.0,0.0,0,0,1);
230 GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi,zMax,1.0,1.0,0,0,1);
231 inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);
237 beginShape(
action,TRIANGLE_STRIP);
240 for (i = 0; i<=NPHI; i++) {
241 GEN_VERTEX(pv,rMin*cosPhi,rMin*sinPhi,zMin,0.0,0.0,0,0,-1);
242 GEN_VERTEX(pv,rMax*cosPhi,rMax*sinPhi,zMin,1.0,1.0,0,0,-1);
243 inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);
257 SbVec3f vmin(-
pRMax.getValue(),-
pRMax.getValue(),-
pDz.getValue()),
259 center.setValue(0,0,0);
260 box.setBounds(vmin,vmax);
270 SoSeparator *sep = (SoSeparator *) ( *
children)[0];
271 SoCoordinate3 *theCoordinates = (SoCoordinate3 *) ( sep->getChild(0));
272 SoNormal *theNormals = (SoNormal *) ( sep->getChild(1));
273 SoNormalBinding *theNormalBinding = (SoNormalBinding *) ( sep->getChild(2));
274 SoIndexedFaceSet *theFaceSet = (SoIndexedFaceSet *) ( sep->getChild(3));
277 const int NPHI=24, NPOINTS=2*(2*NPHI+2), NFACES=4*NPHI+2, NINDICES = NFACES*5;
278 float points[NPOINTS][3],normals[NFACES][3];
280 static long indices[NINDICES];
282 static int32_t indices[NINDICES];
286 double phi,
pp, DeltaPhi;
295 for (i = 0; i< NPHI; i++) {
297 indices[5*i+0] = 2*i+0;
298 indices[5*i+1] = 2*i+1;
299 indices[5*i+2] = 2*i+3;
300 indices[5*i+3] = 2*i+2;
301 indices[5*i+4] = SO_END_FACE_INDEX;
304 for (i=0;i<NPHI;i++) {
305 indices[5*1*NPHI + 5*i+0] = 2*NPHI+2 + 2*i+0;
306 indices[5*1*NPHI + 5*i+1] = 2*NPHI+2 + 2*i+1;
307 indices[5*1*NPHI + 5*i+2] = 2*NPHI+2 + 2*i+3;
308 indices[5*1*NPHI + 5*i+3] = 2*NPHI+2 + 2*i+2;
309 indices[5*1*NPHI + 5*i+4] = SO_END_FACE_INDEX;
312 for (i=0;i<NPHI;i++) {
313 indices[5*2*NPHI + 5*i+0] = 2*i+0;
314 indices[5*2*NPHI + 5*i+1] = 2*i+2;
315 indices[5*2*NPHI + 5*i+2] = NPOINTS - (2*i+4);
316 indices[5*2*NPHI + 5*i+3] = NPOINTS - (2*i+2);
317 indices[5*2*NPHI + 5*i+4] = SO_END_FACE_INDEX;
320 for (i=0;i<NPHI;i++) {
321 indices[5*3*NPHI + 5*i+0] = 2*i+1;
322 indices[5*3*NPHI + 5*i+1] = NPOINTS - (2*i+1);
323 indices[5*3*NPHI + 5*i+2] = NPOINTS - (2*i+3);
324 indices[5*3*NPHI + 5*i+3] = 2*i+3;
325 indices[5*3*NPHI + 5*i+4] = SO_END_FACE_INDEX;
328 indices[5*4*NPHI +0] = 2*NPHI;
329 indices[5*4*NPHI +1] = 2*NPHI+1;
330 indices[5*4*NPHI +2] = 2*NPHI+3;
331 indices[5*4*NPHI +3] = 2*NPHI+2;
332 indices[5*4*NPHI +4] = SO_END_FACE_INDEX;
334 indices[5*4*NPHI +5 +0] = 0;
335 indices[5*4*NPHI +5 +1] = NPOINTS-2;
336 indices[5*4*NPHI +5 +2] = NPOINTS-1;
337 indices[5*4*NPHI +5 +3] = 1;
338 indices[5*4*NPHI +5 +4] = SO_END_FACE_INDEX;
343 indices[5*4*NPHI +0] = 2*NPHI;
344 indices[5*4*NPHI +1] = 2*NPHI+1;
345 indices[5*4*NPHI +2] = 2*NPHI+3;
346 indices[5*4*NPHI +3] = 2*NPHI+2;
347 indices[5*4*NPHI +4] = SO_END_FACE_INDEX;
349 indices[5*4*NPHI +5 +0] = 0;
350 indices[5*4*NPHI +5 +1] = NPOINTS-2;
351 indices[5*4*NPHI +5 +2] = NPOINTS-1;
352 indices[5*4*NPHI +5 +3] = 1;
353 indices[5*4*NPHI +5 +4] = SO_END_FACE_INDEX;
357 indices[5*4*NPHI +0] = SO_END_FACE_INDEX;
358 indices[5*4*NPHI +1] = SO_END_FACE_INDEX;
359 indices[5*4*NPHI +2] = SO_END_FACE_INDEX;
360 indices[5*4*NPHI +3] = SO_END_FACE_INDEX;
361 indices[5*4*NPHI +4] = SO_END_FACE_INDEX;
363 indices[5*4*NPHI +5 +0] = SO_END_FACE_INDEX;
364 indices[5*4*NPHI +5 +1] = SO_END_FACE_INDEX;
365 indices[5*4*NPHI +5 +2] = SO_END_FACE_INDEX;
366 indices[5*4*NPHI +5 +3] = SO_END_FACE_INDEX;
367 indices[5*4*NPHI +5 +4] = SO_END_FACE_INDEX;
370 DeltaPhi =
pDPhi.getValue()/NPHI, phi =
pSPhi.getValue();
371 for (i = 0; i<=NPHI; i++) {
372 points[2*i+0][0] =
pRMax.getValue()*
FCOS(phi);
373 points[2*i+0][1]=
pRMax.getValue()*
FSIN(phi);
374 points[2*i+0][2] = +
pDz.getValue();
376 points[2*i+1][0] =
pRMax.getValue()*
FCOS(phi);
377 points[2*i+1][1]=
pRMax.getValue()*
FSIN(phi);
378 points[2*i+1][2] = -
pDz.getValue();
380 pp = phi+DeltaPhi/2.0;
390 for (i = 0; i<=NPHI; i++) {
391 points[2*NPHI+2+2*i+0][0] =
pRMin.getValue()*
FCOS(phi);
392 points[2*NPHI+2+2*i+0][1] =
pRMin.getValue()*
FSIN(phi);
393 points[2*NPHI+2+2*i+0][2] = +
pDz.getValue();
394 points[2*NPHI+2+2*i+1][0] =
pRMin.getValue()*
FCOS(phi);
395 points[2*NPHI+2+2*i+1][1] =
pRMin.getValue()*
FSIN(phi);
396 points[2*NPHI+2+2*i+1][2] = -
pDz.getValue();
397 pp = phi-DeltaPhi/2.0;
399 normals[NPHI+i][0] = -
FCOS(
pp);
400 normals[NPHI+i][1] = -
FSIN(
pp);
401 normals[NPHI+i][2] = 0;
406 for (i=0;i<NPHI;i++) {
407 normals[2*NPHI+i][0]=normals[2*NPHI+i][1]=0;
408 normals[2*NPHI+i][2]= 1.0;
411 for (i=0;i<NPHI;i++) {
412 normals[3*NPHI+i][0]=normals[3*NPHI+i][1]=0;
413 normals[3*NPHI+i][2]= -1.0;
416 phi =
pSPhi.getValue();
417 normals[4*NPHI+0][0]=
FSIN(phi);
418 normals[4*NPHI+0][1]= -
FCOS(phi);
419 normals[4*NPHI+0][2]=0;
423 normals[4*NPHI+1][0]= -
FSIN(phi);
424 normals[4*NPHI+1][1]= +
FCOS(phi);
425 normals[4*NPHI+1][2]=0;
427 for (
int np=0;np<NPOINTS; np++) theCoordinates->point.set1Value(np,points[np][0],points[np][1],points[np][2]);
428 for (
int ni=0;ni<NINDICES;ni++) theFaceSet->coordIndex.set1Value(ni,indices[ni]);
429 for (
int nf=0;nf<NFACES;nf++) theNormals->vector.set1Value(nf,normals[nf][0],normals[nf][1],normals[nf][2]);
430 theNormalBinding->value=SoNormalBinding::PER_FACE;
442 SoSeparator *sep =
new SoSeparator();
443 SoCoordinate3 *theCoordinates =
new SoCoordinate3();
444 SoNormal *theNormals =
new SoNormal();
445 SoNormalBinding *theNormalBinding =
new SoNormalBinding();
446 SoIndexedFaceSet *theFaceSet =
new SoIndexedFaceSet();
450 sep->addChild(theCoordinates);
451 sep->addChild(theNormals);
452 sep->addChild(theNormalBinding);
453 sep->addChild(theFaceSet);
#define GEN_VERTEX(pv, x, y, z, s, t, nx, ny, nz)
virtual SoChildList * getChildren() const
GetChildList, required whenever the class has hidden children.
virtual ~SoTubs()
Destructor, required.
virtual void computeBBox(SoAction *action, SbBox3f &box, SbVec3f ¢er)
compute bounding Box, required
SoSFFloat pDz
Half-length in Z.
virtual void clearAlternateRep()
We better be able to clear it, too!
SoSFNode alternateRep
Alternate rep - required.
virtual void generatePrimitives(SoAction *action)
Generate Primitives, required.
SoChildList * children
ChildList. Required whenever the class has hidden children.
SoSFFloat pDPhi
Delta-angle, in radians.
void inc(double &sinPhi, double &cosPhi, double sinDeltaPhi, double cosDeltaPhi) const
help with trigonometry. increments sines an cosines by an angle.
virtual void generateAlternateRep()
SoSFFloat pSPhi
Starting angle, in radians.
static void initClass()
Class Initializer, required.
SoSFFloat pRMin
Inside radius of the tube.
SoSFFloat pRMax
Outside radius of the tube.
static double normal(HepRandomEngine *eptr)