00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifdef G4VIS_BUILD_OI_DRIVER
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "Geant4_SoPolyhedron.h"
00038
00039 #include <Inventor/SbBox.h>
00040 #include <Inventor/actions/SoAction.h>
00041 #include <Inventor/SoPrimitiveVertex.h>
00042 #include <Inventor/elements/SoTextureCoordinateElement.h>
00043 #include <Inventor/nodes/SoSeparator.h>
00044
00045
00046 #define SbMinimum(a,b) ((a)<(b)?a:b)
00047 #define SbMaximum(a,b) ((a)>(b)?a:b)
00048
00049 #include <HEPVis/actions/SoAlternateRepAction.h>
00050
00051 #include "G4Polyhedron.hh"
00052
00053
00054
00055
00056 typedef HepGeom::Point3D<double> HVPoint3D;
00057 typedef HepGeom::Normal3D<double> HVNormal3D;
00058
00059 SO_NODE_SOURCE(Geant4_SoPolyhedron)
00060
00061 void Geant4_SoPolyhedron::initClass(
00062 )
00065 {
00066 SO_NODE_INIT_CLASS(Geant4_SoPolyhedron,SoShape,"Shape");
00067 }
00069 Geant4_SoPolyhedron::Geant4_SoPolyhedron(
00070 )
00071 :fPolyhedron(0)
00074 {
00075 SO_NODE_CONSTRUCTOR(Geant4_SoPolyhedron);
00076 SO_NODE_ADD_FIELD(solid,(TRUE));
00077 SO_NODE_ADD_FIELD(reducedWireFrame,(TRUE));
00078 SO_NODE_ADD_FIELD(alternateRep,(NULL));
00079 }
00081 Geant4_SoPolyhedron::Geant4_SoPolyhedron(
00082 const G4Polyhedron& aPolyhedron
00083 )
00084 :fPolyhedron(0)
00087 {
00088 SO_NODE_CONSTRUCTOR(Geant4_SoPolyhedron);
00089 SO_NODE_ADD_FIELD(solid,(TRUE));
00090 SO_NODE_ADD_FIELD(reducedWireFrame,(TRUE));
00091 SO_NODE_ADD_FIELD(alternateRep,(NULL));
00092
00093 fPolyhedron = new G4Polyhedron(aPolyhedron);
00094 }
00096 Geant4_SoPolyhedron::Geant4_SoPolyhedron(
00097 G4Polyhedron* aPolyhedron
00098 )
00099 :fPolyhedron(aPolyhedron)
00102 {
00103 SO_NODE_CONSTRUCTOR(Geant4_SoPolyhedron);
00104 SO_NODE_ADD_FIELD(solid,(TRUE));
00105 SO_NODE_ADD_FIELD(reducedWireFrame,(TRUE));
00106 SO_NODE_ADD_FIELD(alternateRep,(NULL));
00107 }
00109 Geant4_SoPolyhedron::~Geant4_SoPolyhedron(
00110 )
00113 {
00114 delete fPolyhedron;
00115 }
00117 void Geant4_SoPolyhedron::generatePrimitives(
00118 SoAction* aAction
00119 )
00120
00121
00122 {
00123 if(!fPolyhedron) return;
00124 if(fPolyhedron->GetNoFacets()<=0) return;
00125
00126 SoState *state = aAction->getState();
00127 SbBool useTexFunction =
00128 (SoTextureCoordinateElement::getType(state) ==
00129 SoTextureCoordinateElement::FUNCTION);
00130 const SoTextureCoordinateElement *tce = NULL;
00131 SbVec4f texCoord(0.,0.,0.,0.);
00132 if (useTexFunction) {
00133 tce = SoTextureCoordinateElement::getInstance(state);
00134 } else {
00135 texCoord[2] = 0.0;
00136 texCoord[3] = 1.0;
00137 }
00138
00139 if(solid.getValue()==TRUE) {
00140 SoPrimitiveVertex pv;
00141 SbVec3f point, normal;
00143
00144 #define GEN_VERTEX(pv,x,y,z,s,t,nx,ny,nz) \
00145 point.setValue(x,y,z); \
00146 normal.setValue(nx,ny,nz); \
00147 if (useTexFunction) { \
00148 texCoord=tce->get(point,normal); \
00149 } else { \
00150 texCoord[0]=s; \
00151 texCoord[1]=t; \
00152 } \
00153 pv.setPoint(point); \
00154 pv.setNormal(normal); \
00155 pv.setTextureCoords(texCoord); \
00156 shapeVertex(&pv);
00157
00159
00160
00161 bool notLastFace;
00162 do {
00163 HVNormal3D unitNormal;
00164 notLastFace = fPolyhedron->GetNextUnitNormal(unitNormal);
00165
00166 beginShape(aAction,POLYGON);
00167 bool notLastEdge;
00168 int edgeFlag = 1;
00169 do {
00170 HVPoint3D vertex;
00171 notLastEdge = fPolyhedron->GetNextVertex(vertex,edgeFlag);
00172 GEN_VERTEX(pv,
00173 vertex[0],
00174 vertex[1],
00175 vertex[2],
00176 0.0,0.0,
00177 unitNormal[0],
00178 unitNormal[1],
00179 unitNormal[2]);
00180 } while (notLastEdge);
00181 endShape();
00182 } while (notLastFace);
00183 } else {
00184 SoPrimitiveVertex pvb,pve;
00185 pve.setTextureCoords(texCoord);
00186 pvb.setTextureCoords(texCoord);
00187
00188 #ifdef __COIN__ // To bypass a bug in invokeLineSegment when picking.
00189 beginShape(aAction,POLYGON);
00190 endShape();
00191 #endif
00192
00193 SbVec3f point;
00194 bool notLastFace;
00195 do {
00196 HVNormal3D unitNormal;
00197 notLastFace = fPolyhedron->GetNextUnitNormal(unitNormal);
00198
00199 SbVec3f normal;
00200 normal.setValue(unitNormal[0],unitNormal[1],unitNormal[2]);
00201
00202
00203 int edgeFlag = 1;
00204 int prevEdgeFlag = edgeFlag;
00205 bool notLastEdge;
00206 SbBool firstEdge = TRUE;
00207 do {
00208 HVPoint3D vertex;
00209 notLastEdge = fPolyhedron->GetNextVertex(vertex,edgeFlag);
00210 if(reducedWireFrame.getValue()==FALSE) edgeFlag = 1;
00211 if(firstEdge) {
00212 if(edgeFlag > 0) {
00213 pvb.setNormal(normal);
00214 point.setValue(vertex[0],vertex[1],vertex[2]);
00215 pvb.setPoint(point);
00216 } else {
00217 }
00218 firstEdge = FALSE;
00219 prevEdgeFlag = edgeFlag;
00220 } else {
00221 if(edgeFlag!=prevEdgeFlag) {
00222 if(edgeFlag > 0) {
00223 pvb.setNormal(normal);
00224 point.setValue(vertex[0],vertex[1],vertex[2]);
00225 pvb.setPoint(point);
00226 } else {
00227 pve.setNormal(normal);
00228 point.setValue(vertex[0],vertex[1],vertex[2]);
00229 pve.setPoint(point);
00230 invokeLineSegmentCallbacks(aAction,&pvb,&pve);
00231 }
00232 prevEdgeFlag = edgeFlag;
00233 } else {
00234 if(edgeFlag > 0) {
00235 pve.setNormal(normal);
00236 point.setValue(vertex[0],vertex[1],vertex[2]);
00237 pve.setPoint(point);
00238 invokeLineSegmentCallbacks(aAction,&pvb,&pve);
00239 pvb = pve;
00240 } else {
00241 }
00242 }
00243 }
00244 } while (notLastEdge);
00245 } while (notLastFace);
00246 }
00247
00248 }
00250 void Geant4_SoPolyhedron::computeBBox(
00251 SoAction*
00252 ,SbBox3f& aBox
00253 ,SbVec3f& aCenter
00254 )
00257 {
00258 if(!fPolyhedron) return;
00259 if(fPolyhedron->GetNoFacets()<=0) {
00260 SbVec3f vmin(-1,-1,-1);
00261 SbVec3f vmax( 1, 1, 1);
00262 aBox.setBounds(vmin,vmax);
00263 aCenter.setValue(0,0,0);
00264 } else {
00265 SbBool first = TRUE;
00266 float xmn = 0,ymn = 0,zmn = 0;
00267 float xmx = 0,ymx = 0,zmx = 0;
00268 float xct = 0,yct = 0,zct = 0;
00269 SbVec3f point;
00270 int count = 0;
00271
00272 bool notLastFace;
00273 do {
00274 HVNormal3D unitNormal;
00275 notLastFace = fPolyhedron->GetNextUnitNormal(unitNormal);
00276 bool notLastEdge;
00277 do {
00278 HVPoint3D vertex;
00279 int edgeFlag = 1;
00280 notLastEdge = fPolyhedron->GetNextVertex(vertex,edgeFlag);
00281 point.setValue(vertex[0],vertex[1],vertex[2]);
00282 if(first==TRUE) {
00283 xct = xmx = xmn = point[0];
00284 yct = ymx = ymn = point[1];
00285 zct = zmx = zmn = point[2];
00286 count++;
00287 first = FALSE;
00288 } else {
00289 xmn = SbMinimum(xmn,point[0]);
00290 ymn = SbMinimum(ymn,point[1]);
00291 zmn = SbMinimum(zmn,point[2]);
00292
00293 xmx = SbMaximum(xmx,point[0]);
00294 ymx = SbMaximum(ymx,point[1]);
00295 zmx = SbMaximum(zmx,point[2]);
00296
00297 xct += point[0];
00298 yct += point[1];
00299 zct += point[2];
00300 count++;
00301 }
00302
00303 } while (notLastEdge);
00304 } while (notLastFace);
00305 SbVec3f vmin(xmn,ymn,zmn);
00306 SbVec3f vmax(xmx,ymx,zmx);
00307 aBox.setBounds(vmin,vmax);
00308 if(count==0)
00309 aCenter.setValue(0,0,0);
00310 else
00311 aCenter.setValue(xct/count,yct/count,zct/count);
00312 }
00313 }
00314
00315 #include <Inventor/nodes/SoNormalBinding.h>
00316 #include <Inventor/nodes/SoNormal.h>
00317 #include <Inventor/nodes/SoCoordinate3.h>
00318 #include <Inventor/nodes/SoIndexedFaceSet.h>
00319 #include <Inventor/nodes/SoIndexedLineSet.h>
00321 void Geant4_SoPolyhedron::generateAlternateRep(
00322 )
00323
00324
00325 {
00326 if(!fPolyhedron) return;
00327 if(fPolyhedron->GetNoFacets()<=0) return;
00328 if(fPolyhedron->GetNoVertices()<=0) return;
00329
00330 if(solid.getValue()==TRUE) {
00331
00332 SoSeparator* separator = new SoSeparator;
00333
00334 SoNormalBinding* normalBinding = new SoNormalBinding;
00335 normalBinding->value = SoNormalBinding::PER_FACE;
00336 separator->addChild(normalBinding);
00337
00338 SoCoordinate3* coordinate3 = new SoCoordinate3;
00339 separator->addChild(coordinate3);
00340 SoNormal* normal = new SoNormal;
00341 separator->addChild(normal);
00342 SoIndexedFaceSet* indexedFaceSet = new SoIndexedFaceSet;
00343 separator->addChild(indexedFaceSet);
00344
00345 int nvert = fPolyhedron->GetNoVertices();
00346 int nface = fPolyhedron->GetNoFacets();
00347
00348 SbVec3f* normals = new SbVec3f[nface];
00349
00350 SbVec3f* points = new SbVec3f[nvert];
00351 int32_t* coords = new int32_t[nvert+1];
00352
00353 int inormal = 0;
00354 int icoord = 0;
00355 int iindex = 0;
00356
00357
00358 bool notLastFace;
00359 do {
00360 HVNormal3D unitNormal;
00361 notLastFace = fPolyhedron->GetNextUnitNormal(unitNormal);
00362
00363
00364 int ipoint = 0;
00365
00366 bool notLastEdge;
00367 int edgeFlag = 1;
00368 do {
00369 HVPoint3D vertex;
00370 notLastEdge = fPolyhedron->GetNextVertex(vertex,edgeFlag);
00371 points[ipoint].setValue(vertex[0],vertex[1],vertex[2]);
00372 coords[ipoint] = icoord + ipoint;
00373 ipoint++;
00374 } while (notLastEdge);
00375
00376
00377 coords[ipoint] = SO_END_FACE_INDEX;
00378 coordinate3->point.setValues(icoord,ipoint,points);
00379 icoord += ipoint;
00380
00381 normals[inormal].setValue(unitNormal[0],unitNormal[1],unitNormal[2]);
00382 inormal++;
00383
00384 indexedFaceSet->coordIndex.setValues(iindex,(ipoint+1),coords);
00385 iindex += ipoint+1;
00386
00387 } while (notLastFace);
00388
00389 normal->vector.setValues(0,inormal,normals);
00390
00391 delete [] normals;
00392 delete [] coords;
00393 delete [] points;
00394
00395 alternateRep.setValue(separator);
00396
00397 } else {
00398
00399 SoSeparator* separator = new SoSeparator;
00400
00401 int nvert = fPolyhedron->GetNoVertices();
00402
00403
00404 int nedge = nvert * 3;
00405 int npoint = nedge*2;
00406 SbVec3f* points = new SbVec3f[npoint];
00407 int ncoord = nedge*3;
00408 int32_t* coords = new int32_t[ncoord];
00409
00410 SbVec3f pvb(0.,0.,0.), pve(0.,0.,0.);
00411
00412 SbBool empty = TRUE;
00413 int ipoint = 0;
00414 int icoord = 0;
00415
00416 bool notLastFace;
00417 do {
00418 HVNormal3D unitNormal;
00419 notLastFace = fPolyhedron->GetNextUnitNormal(unitNormal);
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429 int edgeFlag = 1;
00430 int prevEdgeFlag = edgeFlag;
00431 bool notLastEdge;
00432 SbBool firstEdge = TRUE;
00433 do {
00434 HVPoint3D vertex;
00435 notLastEdge = fPolyhedron->GetNextVertex(vertex,edgeFlag);
00436 if(reducedWireFrame.getValue()==FALSE) edgeFlag = 1;
00437 if(firstEdge) {
00438 if(edgeFlag > 0) {
00439 pvb.setValue(vertex[0],vertex[1],vertex[2]);
00440 } else {
00441 }
00442 firstEdge = FALSE;
00443 prevEdgeFlag = edgeFlag;
00444 } else {
00445 if(edgeFlag!=prevEdgeFlag) {
00446 if(edgeFlag > 0) {
00447 pvb.setValue(vertex[0],vertex[1],vertex[2]);
00448 } else {
00449 pve.setValue(vertex[0],vertex[1],vertex[2]);
00450
00451 if((ipoint+1)>=npoint) {
00452 int new_npoint = 2 * npoint;
00453 SbVec3f* new_points = new SbVec3f[new_npoint];
00454 for(int i=0;i<npoint;i++) new_points[i] = points[i];
00455 delete [] points;
00456 npoint = new_npoint;
00457 points = new_points;
00458 }
00459
00460 if((icoord+2)>=ncoord) {
00461 int new_ncoord = 2 * ncoord;
00462 int32_t* new_coords = new int32_t[new_ncoord];
00463 for(int i=0;i<ncoord;i++) new_coords[i] = coords[i];
00464 delete [] coords;
00465 ncoord = new_ncoord;
00466 coords = new_coords;
00467 }
00468
00469 points[ipoint+0] = pvb;
00470 points[ipoint+1] = pve;
00471 coords[icoord+0] = ipoint + 0;
00472 coords[icoord+1] = ipoint + 1;
00473 coords[icoord+2] = SO_END_LINE_INDEX;
00474 ipoint += 2;
00475 icoord += 3;
00476 empty = FALSE;
00477 }
00478 prevEdgeFlag = edgeFlag;
00479 } else {
00480 if(edgeFlag > 0) {
00481 pve.setValue(vertex[0],vertex[1],vertex[2]);
00482
00483 if((ipoint+1)>=npoint) {
00484 int new_npoint = 2 * npoint;
00485 SbVec3f* new_points = new SbVec3f[new_npoint];
00486 for(int i=0;i<npoint;i++) new_points[i] = points[i];
00487 delete [] points;
00488 npoint = new_npoint;
00489 points = new_points;
00490 }
00491
00492 if((icoord+2)>=ncoord) {
00493 int new_ncoord = 2 * ncoord;
00494 int32_t* new_coords = new int32_t[new_ncoord];
00495 for(int i=0;i<ncoord;i++) new_coords[i] = coords[i];
00496 delete [] coords;
00497 ncoord = new_ncoord;
00498 coords = new_coords;
00499 }
00500
00501 points[ipoint+0] = pvb;
00502 points[ipoint+1] = pve;
00503 coords[icoord+0] = ipoint + 0;
00504 coords[icoord+1] = ipoint + 1;
00505 coords[icoord+2] = SO_END_LINE_INDEX;
00506 ipoint += 2;
00507 icoord += 3;
00508 empty = FALSE;
00509
00510 pvb = pve;
00511 } else {
00512 }
00513 }
00514 }
00515 } while (notLastEdge);
00516 } while (notLastFace);
00517
00518 SoCoordinate3* coordinate3 = new SoCoordinate3;
00519 coordinate3->point.setValues(0,ipoint,points);
00520 separator->addChild(coordinate3);
00521
00522 SoIndexedLineSet* indexedLineSet = new SoIndexedLineSet;
00523 indexedLineSet->coordIndex.setValues(0,icoord,coords);
00524 separator->addChild(indexedLineSet);
00525
00526 delete [] coords;
00527 delete [] points;
00528
00529 if(empty==TRUE) {
00530 separator->unref();
00531 } else {
00532 alternateRep.setValue(separator);
00533 }
00534 }
00535 }
00537 void Geant4_SoPolyhedron::clearAlternateRep(
00538 )
00539
00540
00541 {
00542 alternateRep.setValue(NULL);
00543 }
00545 void Geant4_SoPolyhedron::doAction(
00546 SoAction* aAction
00547 )
00550 {
00551 SO_ALTERNATEREP_DO_ACTION(aAction)
00552 SoShape::doAction(aAction);
00553 }
00554
00555 #endif