42#include <Inventor/SbBox.h>
43#include <Inventor/actions/SoAction.h>
44#include <Inventor/fields/SoSFFloat.h>
45#include <Inventor/misc/SoChildList.h>
46#include <Inventor/nodes/SoSeparator.h>
47#include <Inventor/nodes/SoIndexedFaceSet.h>
48#include <Inventor/nodes/SoNormal.h>
49#include <Inventor/nodes/SoCoordinate3.h>
50#include <Inventor/nodes/SoNormalBinding.h>
51#include <Inventor/SoPrimitiveVertex.h>
52#include <Inventor/elements/SoTextureCoordinateElement.h>
62 SO_NODE_CONSTRUCTOR(
SoCons);
65 SO_NODE_ADD_FIELD(fRmin1, (0.0));
66 SO_NODE_ADD_FIELD(fRmin2, (0.0));
67 SO_NODE_ADD_FIELD(fRmax1, (1.0));
68 SO_NODE_ADD_FIELD(fRmax2, (1.0));
69 SO_NODE_ADD_FIELD(fDz, (10.0));
70 SO_NODE_ADD_FIELD(fSPhi, (0.0));
71 SO_NODE_ADD_FIELD(fDPhi, ((
float)(2*
M_PI)));
72 SO_NODE_ADD_FIELD(smoothDraw, (
TRUE));
73 SO_NODE_ADD_FIELD(alternateRep, (NULL));
74 children =
new SoChildList(
this);
86 static bool first =
true;
89 SO_NODE_INIT_CLASS(
SoCons,SoShape,
"Shape");
100 SoState *state = action->getState();
104 SbBool useTexFunction=
105 (SoTextureCoordinateElement::getType(state) ==
106 SoTextureCoordinateElement::FUNCTION);
111 const SoTextureCoordinateElement *tce = NULL;
113 if (useTexFunction) {
114 tce = SoTextureCoordinateElement::getInstance(state);
119 SbVec3f point, normal;
123#define GEN_VERTEX(pv,x,y,z,s,t,nx,ny,nz) \
124 point.setValue((float)(x),(float)(y),(float)(z)); \
125 normal.setValue((float)(nx),(float)(ny),(float)(nz)); \
126 if (useTexFunction) { \
127 texCoord=tce->get(point,normal); \
129 texCoord[0]=(float)(s); \
130 texCoord[1]=(float)(t); \
132 pv.setPoint(point); \
133 pv.setNormal(normal); \
134 pv.setTextureCoords(texCoord); \
140 int NPHI = (int)(2+22*std::fabs(
fDPhi.getValue()/(2.0*
M_PI)));
141 double deltaPhi =
fDPhi.getValue()/NPHI;
142 double phi0 =
fSPhi.getValue();
143 double phi1 = phi0 +
fDPhi.getValue();
144 double rMax1 =
fRmax1.getValue();
145 double rMin1 =
fRmin1.getValue();
146 double rMax2 =
fRmax2.getValue();
147 double rMin2 =
fRmin2.getValue();
148 double zMax =
fDz.getValue();
150 double cosPhi0 = std::cos(phi0);
151 double sinPhi0 = std::sin(phi0);
152 double cosPhi1 = std::cos(phi1);
153 double sinPhi1 = std::sin(phi1);
154 double cosDeltaPhi = std::cos(deltaPhi);
155 double sinDeltaPhi = std::sin(deltaPhi);
159 beginShape(action,TRIANGLE_STRIP);
161 double sinPhi=sinPhi0;
162 double cosPhi=cosPhi0;
163 for (i = 0; i<=NPHI; i++) {
164 GEN_VERTEX(pv,rMax2*cosPhi,rMax2*sinPhi,zMax,0.0,0.0,cosPhi,sinPhi,0);
165 GEN_VERTEX(pv,rMax1*cosPhi,rMax1*sinPhi,zMin,1.0,1.0,cosPhi,sinPhi,0);
166 inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);
172 beginShape(action,TRIANGLE_STRIP);
175 for (i = 0; i<=NPHI; i++) {
176 GEN_VERTEX(pv,rMin2*cosPhi,rMin2*sinPhi,zMax,0.0,0.0,-cosPhi,-sinPhi,0);
177 GEN_VERTEX(pv,rMin1*cosPhi,rMin1*sinPhi,zMin,1.0,1.0,-cosPhi,-sinPhi,0);
178 inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);
181 if (std::fabs(deltaPhi)<2.0*
M_PI) {
185 beginShape(action,TRIANGLE_STRIP);
188 GEN_VERTEX(pv,rMax2*cosPhi,rMax2*sinPhi,zMax,0.0,0.0,sinPhi,-cosPhi,0);
189 GEN_VERTEX(pv,rMax1*cosPhi,rMax1*sinPhi,zMin,1.0,1.0,sinPhi,-cosPhi,0);
190 GEN_VERTEX(pv,rMin2*cosPhi,rMin2*sinPhi,zMax,1.0,0.0,sinPhi,-cosPhi,0);
191 GEN_VERTEX(pv,rMin1*cosPhi,rMin1*sinPhi,zMin,0.0,1.0,sinPhi,-cosPhi,0);
196 beginShape(action,TRIANGLE_STRIP);
199 GEN_VERTEX(pv,rMax2*cosPhi,rMax2*sinPhi, zMax,0.0,0.0,-sinPhi,+cosPhi,0);
200 GEN_VERTEX(pv,rMax1*cosPhi,rMax1*sinPhi, zMin,1.0,1.0,-sinPhi,+cosPhi,0);
201 GEN_VERTEX(pv,rMin2*cosPhi,rMin2*sinPhi, zMax,1.0,0.0,-sinPhi,+cosPhi,0);
202 GEN_VERTEX(pv,rMin1*cosPhi,rMin1*sinPhi, zMin,0.0,1.0,-sinPhi,+cosPhi,0);
209 beginShape(action,TRIANGLE_STRIP);
212 for (i = 0; i<=NPHI; i++) {
213 GEN_VERTEX(pv,rMin2*cosPhi,rMin2*sinPhi,zMax,0.0,0.0,0,0,1);
214 GEN_VERTEX(pv,rMax2*cosPhi,rMax2*sinPhi,zMax,1.0,1.0,0,0,1);
215 inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);
221 beginShape(action,TRIANGLE_STRIP);
224 for (i = 0; i<=NPHI; i++) {
225 GEN_VERTEX(pv,rMin1*cosPhi,rMin1*sinPhi,zMin,0.0,0.0,0,0,-1);
226 GEN_VERTEX(pv,rMax1*cosPhi,rMax1*sinPhi,zMin,1.0,1.0,0,0,-1);
227 inc(sinPhi, cosPhi, sinDeltaPhi, cosDeltaPhi);
241 float fRmax=
fRmax1.getValue();
242 if (
fRmax2.getValue() > fRmax) fRmax =
fRmax2.getValue();
244 SbVec3f vmin(-fRmax,-fRmax,-
fDz.getValue()),
245 vmax( fRmax, fRmax,
fDz.getValue());
246 center.setValue(0,0,0);
247 box.setBounds(vmin,vmax);
254void SoCons::updateChildren() {
259 assert(children->getLength()==1);
260 SoSeparator *sep = (SoSeparator *) ( *children)[0];
261 SoCoordinate3 *theCoordinates = (SoCoordinate3 *) ( sep->getChild(0));
262 SoNormal *theNormals = (SoNormal *) ( sep->getChild(1));
263 SoNormalBinding *theNormalBinding = (SoNormalBinding *) ( sep->getChild(2));
264 SoIndexedFaceSet *theFaceSet = (SoIndexedFaceSet *) ( sep->getChild(3));
266 const int NPHI=24, NPOINTS=2*(2*NPHI+2), NFACES=4*NPHI+2, NINDICES = NFACES*5;
267 float points[NPOINTS][3], normals[NFACES][3];
269 static long indices[NINDICES];
271 static int32_t indices[NINDICES];
274 double phi, pp, DeltaPhi;
283 for (i = 0; i< NPHI; i++) {
285 indices[5*i+0] = 2*i+0;
286 indices[5*i+1] = 2*i+1;
287 indices[5*i+2] = 2*i+3;
288 indices[5*i+3] = 2*i+2;
289 indices[5*i+4] = SO_END_FACE_INDEX;
292 for (i=0;i<NPHI;i++) {
293 indices[5*1*NPHI + 5*i+0] = 2*NPHI+2 + 2*i+0;
294 indices[5*1*NPHI + 5*i+1] = 2*NPHI+2 + 2*i+1;
295 indices[5*1*NPHI + 5*i+2] = 2*NPHI+2 + 2*i+3;
296 indices[5*1*NPHI + 5*i+3] = 2*NPHI+2 + 2*i+2;
297 indices[5*1*NPHI + 5*i+4] = SO_END_FACE_INDEX;
300 for (i=0;i<NPHI;i++) {
301 indices[5*2*NPHI + 5*i+0] = 2*i+0;
302 indices[5*2*NPHI + 5*i+1] = 2*i+2;
303 indices[5*2*NPHI + 5*i+2] = NPOINTS - (2*i+4);
304 indices[5*2*NPHI + 5*i+3] = NPOINTS - (2*i+2);
305 indices[5*2*NPHI + 5*i+4] = SO_END_FACE_INDEX;
308 for (i=0;i<NPHI;i++) {
309 indices[5*3*NPHI + 5*i+0] = 2*i+1;
310 indices[5*3*NPHI + 5*i+1] = NPOINTS - (2*i+1);
311 indices[5*3*NPHI + 5*i+2] = NPOINTS - (2*i+3);
312 indices[5*3*NPHI + 5*i+3] = 2*i+3;
313 indices[5*3*NPHI + 5*i+4] = SO_END_FACE_INDEX;
316 indices[5*4*NPHI +0] = 2*NPHI;
317 indices[5*4*NPHI +1] = 2*NPHI+1;
318 indices[5*4*NPHI +2] = 2*NPHI+3;
319 indices[5*4*NPHI +3] = 2*NPHI+2;
320 indices[5*4*NPHI +4] = SO_END_FACE_INDEX;
322 indices[5*4*NPHI +5 +0] = 0;
323 indices[5*4*NPHI +5 +1] = NPOINTS-2;
324 indices[5*4*NPHI +5 +2] = NPOINTS-1;
325 indices[5*4*NPHI +5 +3] = 1;
326 indices[5*4*NPHI +5 +4] = SO_END_FACE_INDEX;
330 DeltaPhi =
fDPhi.getValue()/NPHI, phi =
fSPhi.getValue();
335 for (i = 0; i<=NPHI; i++) {
336 points[2*i+0][0] =
fRmax2.getValue()*
FCOS(phi);
337 points[2*i+0][1] =
fRmax2.getValue()*
FSIN(phi);
338 points[2*i+0][2] = +
fDz.getValue();
339 points[2*i+1][0] =
fRmax1.getValue()*
FCOS(phi);
340 points[2*i+1][1] =
fRmax1.getValue()*
FSIN(phi);
341 points[2*i+1][2] = -
fDz.getValue();
342 pp = phi+DeltaPhi/2.0;
344 normals[i][0] = ct *
FCOS(pp);
345 normals[i][1] = ct *
FSIN(pp);
355 for (i = 0; i<=NPHI; i++) {
356 points[2*NPHI+2+2*i+0][0] =
fRmin2.getValue()*
FCOS(phi);
357 points[2*NPHI+2+2*i+0][1] =
fRmin2.getValue()*
FSIN(phi);
358 points[2*NPHI+2+2*i+0][2] = +
fDz.getValue();
359 points[2*NPHI+2+2*i+1][0] =
fRmin1.getValue()*
FCOS(phi);
360 points[2*NPHI+2+2*i+1][1] =
fRmin1.getValue()*
FSIN(phi);
361 points[2*NPHI+2+2*i+1][2] = -
fDz.getValue();
362 pp = phi-DeltaPhi/2.0;
364 normals[NPHI+i][0] = -ct*
FCOS(pp);
365 normals[NPHI+i][1] = -ct*
FSIN(pp);
366 normals[NPHI+i][2] = st;
371 for (i=0;i<NPHI;i++) {
372 normals[2*NPHI+i][0]=normals[2*NPHI+i][1]=0;
373 normals[2*NPHI+i][2]= 1.0;
376 for (i=0;i<NPHI;i++) {
377 normals[3*NPHI+i][0]=normals[3*NPHI+i][1]=0;
378 normals[3*NPHI+i][2]= -1.0;
381 phi =
fSPhi.getValue();
382 normals[4*NPHI+0][0]=
FSIN(phi);
383 normals[4*NPHI+0][1]= -
FCOS(phi);
384 normals[4*NPHI+0][2]= 0;
388 normals[4*NPHI+1][0]= -
FSIN(phi);
389 normals[4*NPHI+1][1]= +
FCOS(phi);
390 normals[4*NPHI+1][2]=0;
392 for (
int np=0;np<NPOINTS;np++) theCoordinates->point.set1Value(np,points[np][0],points[np][1],points[np][2]);
393 theFaceSet->coordIndex.setValues(0,NINDICES,indices);
397 for (
int nf=0;nf<NFACES;nf++) theNormals->vector.set1Value(nf,normals[nf][0],normals[nf][1],normals[nf][2]);
398 theNormalBinding->value=SoNormalBinding::PER_FACE;
401 for (
int nf=0;nf<NFACES;nf++) theNormals->vector.set1Value(nf,normals[nf][0],normals[nf][1],normals[nf][2]);
402 theNormalBinding->value=SoNormalBinding::PER_FACE;
407void SoCons::generateChildren() {
414 assert(children->getLength() ==0);
415 SoSeparator *sep =
new SoSeparator();
416 SoCoordinate3 *theCoordinates =
new SoCoordinate3();
417 SoNormal *theNormals =
new SoNormal();
418 SoNormalBinding *theNormalBinding =
new SoNormalBinding();
419 SoIndexedFaceSet *theFaceSet =
new SoIndexedFaceSet();
423 sep->addChild(theCoordinates);
424 sep->addChild(theNormals);
425 sep->addChild(theNormalBinding);
426 sep->addChild(theFaceSet);
427 children->append(sep);
436 if (children->getLength() == 0) generateChildren();
#define GEN_VERTEX(pv, x, y, z, s, t, nx, ny, nz)
virtual void computeBBox(SoAction *action, SbBox3f &box, SbVec3f ¢er)
compute bounding Box, required
SoSFFloat fDPhi
Delta-angle, in radians.
virtual void generateAlternateRep()
virtual void clearAlternateRep()
We better be able to clear it, too!
static void initClass()
Class Initializer, required.
SoSFFloat fSPhi
Starting angle, in radians.
SoSFFloat fRmax2
Outside radius at +fDz.
virtual void generatePrimitives(SoAction *action)
Generate Primitives, required.
SoSFFloat fRmax1
Outside radius at -fDz.
SoSFFloat fRmin1
Inside radius at -fDz.
SoSFFloat fRmin2
Inside radius at +fDz.
SoSFNode alternateRep
Alternate rep required - for use by users without HEPVis shared objects.
SoSFFloat fDz
Half-length along Z.
virtual SoChildList * getChildren() const
GetChildList, required whenever the class has hidden children.
virtual ~SoCons()
Destructor, required.
SoSFBool smoothDraw
An Inventor option - slightly better render, worse performance.