ATLAS Offline Software
Loading...
Searching...
No Matches
SoTessellated.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7#include <Inventor/SbBox.h>
8#include <Inventor/actions/SoPickAction.h>
9#include <Inventor/nodes/SoSeparator.h>
10#include <Inventor/nodes/SoIndexedFaceSet.h>
11#include <Inventor/nodes/SoIndexedLineSet.h>
12#include <Inventor/SoPrimitiveVertex.h>
13#include <Inventor/C/glue/gl.h>
14#include <Inventor/elements/SoGLCacheContextElement.h>
15
16SO_NODE_SOURCE(SoTessellated)
17
18//____________________________________________________________________
20{
21 [[maybe_unused]] static const bool didInit = [&]() {
22 SO_NODE_INIT_CLASS(SoTessellated, SoShape, "Shape");
23 return true;
24 }();
25}
26
27//____________________________________________________________________
29{
30 SO_NODE_CONSTRUCTOR(SoTessellated);
31 SO_NODE_ADD_FIELD(drawEdgeLines, (false));
32 SO_NODE_ADD_FIELD(forceEdgeLinesInBaseColour, (true));
33 SO_NODE_ADD_FIELD(alternateRep,(NULL));
34 setNodeType(EXTENSION);
35}
36
37//____________________________________________________________________
41
42//____________________________________________________________________
43void SoTessellated::addTriangularFacet(double x1, double y1, double z1,
44 double x2, double y2, double z2,
45 double x3, double y3, double z3)
46{
47 m_points.push_back(x1);
48 m_points.push_back(y1);
49 m_points.push_back(z1);
50 m_points.push_back(x2);
51 m_points.push_back(y2);
52 m_points.push_back(z2);
53 m_points.push_back(x3);
54 m_points.push_back(y3);
55 m_points.push_back(z3);
56
57 // Normal (v2-v1)(x)(v3-v1)
58 const double edge1X(x2-x1), edge1Y(y2-y1), edge1Z(z2-z1);
59 const double edge2X(x3-x1), edge2Y(y3-y1), edge2Z(z3-z1);
60 double nx(edge1Y*edge2Z-edge1Z*edge2Y);
61 double ny(edge1Z*edge2X-edge1X*edge2Z);
62 double nz(edge1X*edge2Y-edge1Y*edge2X);
63 double nl(nx*nx+ny*ny+nz*nz);
64 const double s(1.0/sqrt(nl));
65 m_normals.push_back(nx*s);
66 m_normals.push_back(ny*s);
67 m_normals.push_back(nz*s);
68}
69
70//____________________________________________________________________
71void SoTessellated::addQuadrangularFacet(double x1, double y1, double z1,
72 double x2, double y2, double z2,
73 double x3, double y3, double z3,
74 double x4, double y4, double z4)
75{
76 addTriangularFacet(x1,y1,z1,x2,y2,z2,x3,y3,z3);
77 addTriangularFacet(x3,y3,z3,x4,y4,z4,x1,y1,z1);
78}
79
80//____________________________________________________________________
82{
83 if(m_points.size()==0)
85
86 //Bounding Box and Center
87 float xmin(m_points[0]), ymin(m_points[1]), zmin(m_points[2]);
88 float xmax(xmin), ymax(ymin), zmax(zmin);
89
90 int nVertices = m_points.size()/3;
91 for (int i=1;i<nVertices;i++) {
92 xmin = std::min(xmin,m_points[i*3]);
93 xmax = std::max(xmax,m_points[i*3]);
94 ymin = std::min(ymin,m_points[i*3+1]);
95 ymax = std::max(ymax,m_points[i*3+1]);
96 zmin = std::min(zmin,m_points[i*3+2]);
97 zmax = std::max(zmax,m_points[i*3+2]);
98 }
99
100 m_bbox.setBounds (xmin, ymin, zmin, xmax, ymax, zmax);
101 m_center.setValue(0.5*(xmin+xmax),0.5*(ymin+ymax),0.5*(zmin+zmax));
102
103 drawEdgeLines.touch();
104}
105
106
107//____________________________________________________________________
109{
110 if(m_points.size()==0)
112
113 // Access the state from the action
114 SoState *state = action->getState();
115
116 if(action->getTypeId().isDerivedFrom(SoPickAction::getClassTypeId())) {
117
118 //For picking:
119 SoPrimitiveVertex vertex;
120 beginShape(action,TRIANGLES);
121 for(size_t i=0;i<m_points.size();i+=3) {
122 vertex.setPoint(SbVec3f(m_points[i],m_points[i+1],m_points[i+2]));
123 shapeVertex(&vertex);
124 }
125 endShape();
126
127 }else{
128
129 // Draw the shape itself
130 glBegin(GL_TRIANGLES);
131 int nFaces = m_normals.size()/3;
132 for (int i=0;i<nFaces;i++) {
133 glNormal3fv(static_cast<const GLfloat*>(&m_normals[i*3]));
134 for (int j = 0; j < 3; j++)
135 glVertex3fv(static_cast<const GLfloat*>(&m_points[i*9+j*3]));
136 }
137 glEnd();
138
139 // Draw edges if required
140 //
141 // -- ToDo: this can be optimizid. We are currently drawing edges twice
142 // -- and we could also eliminate 'diagonal' lines coming from
143 // -- quadrangular shapes
144 //
145 if(drawEdgeLines.getValue()){
146 const bool disableLighting(forceEdgeLinesInBaseColour.getValue()&&glIsEnabled(GL_LIGHTING));
147 const bool transparencyOn = glIsEnabled(GL_BLEND);
148
149 if (disableLighting) glDisable(GL_LIGHTING);
150 if (transparencyOn) glDisable(GL_BLEND);
151
152 for(size_t i=0;i<m_points.size()-9;i+=9) {
153 glBegin(GL_LINE_STRIP);
154 glVertex3fv(static_cast<const GLfloat*>(&m_points[i]));
155 glVertex3fv(static_cast<const GLfloat*>(&m_points[i+3]));
156 glVertex3fv(static_cast<const GLfloat*>(&m_points[i+6]));
157 glVertex3fv(static_cast<const GLfloat*>(&m_points[i]));
158 glEnd();
159 }
160
161 if (disableLighting) glEnable(GL_LIGHTING);
162 if (transparencyOn) glEnable(GL_BLEND);
163 }
164 }
165
166 if (state&&state->isElementEnabled(SoGLCacheContextElement::getClassStackIndex())) {
167 //Encourage auto caching
168 SoGLCacheContextElement::shouldAutoCache(state, SoGLCacheContextElement::DO_AUTO_CACHE);
169#if ((COIN_MAJOR_VERSION>=3)||((COIN_MAJOR_VERSION==2)&&(COIN_MINOR_VERSION>=5)))
170 SoGLCacheContextElement::incNumShapes(state);
171#endif
172 }
173
174}
175
176//____________________________________________________________________
178{
179 double targetSize = 100.;
180 addTriangularFacet(-targetSize,-targetSize,0.,targetSize,-targetSize,0.,0.,0.,targetSize);
181 addTriangularFacet(targetSize,-targetSize,0.,targetSize,targetSize,0.,0.,0.,targetSize);
182 addTriangularFacet(targetSize,targetSize,0.,-targetSize,targetSize,0.,0.,0.,targetSize);
183 addTriangularFacet(-targetSize,targetSize,0.,-targetSize,-targetSize,0.,0.,0.,targetSize);
184 addQuadrangularFacet(-targetSize,-targetSize,0.,-targetSize,targetSize,0.,targetSize,targetSize,0.,targetSize,-targetSize,0.);
185}
186
187//____________________________________________________________________
188void SoTessellated::computeBBox(SoAction *, SbBox3f &box, SbVec3f &center ){
189 if(m_points.size()==0)
191 box = m_bbox;
192 center = m_center;
193}
194
195//____________________________________________________________________
197{
198 if(m_points.size()==0)
200 if (alternateRep.getValue())
202
203 SoSeparator * sep = new SoSeparator;
204
205 // Faceset representing the shape
206 SoVertexProperty* vertices = new SoVertexProperty();
207 for(size_t i=0;i<m_normals.size();++i)
208 vertices->vertex.set1Value(i,m_points[i*3+0],m_points[i*3+1],m_points[i*3+2]);
209 SoIndexedFaceSet* faceset = new SoIndexedFaceSet;
210 int j=0;
211 for(size_t i=0;i<m_normals.size();++i) {
212 faceset->coordIndex.set1Value(j++,i);
213 if((i>1) && ((i-2)%3==0)) {
214 faceset->coordIndex.set1Value(j++,SO_END_FACE_INDEX);
215 }
216 }
217
218 faceset->vertexProperty = vertices;
219 sep->addChild(faceset);
220
221 // Lineset representing the outline
222 //
223 // -- ToDo: this can be optimizid. We are currently drawing edges twice
224 // -- and we could also eliminate 'diagonal' lines coming from
225 // -- quadrangular shapes
226 //
227 if (drawEdgeLines.getValue()) {
228 SoVertexProperty* verticesL = new SoVertexProperty();
229 SoIndexedLineSet* lineset = new SoIndexedLineSet;
230 int kk=0, jj=0;
231 for(size_t i=0;i<m_points.size()-9;i+=9) {
232 verticesL->vertex.set1Value(kk,m_points[i],m_points[i+1],m_points[i+2]);
233 lineset->coordIndex.set1Value(jj++,kk++);
234 verticesL->vertex.set1Value(kk,m_points[i+3],m_points[i+4],m_points[i+5]);
235 lineset->coordIndex.set1Value(jj++,kk++);
236 verticesL->vertex.set1Value(kk,m_points[i+6],m_points[i+7],m_points[i+8]);
237 lineset->coordIndex.set1Value(jj++,kk++);
238 verticesL->vertex.set1Value(kk,m_points[i],m_points[i+1],m_points[i+2]);
239 lineset->coordIndex.set1Value(jj++,kk++);
240 lineset->coordIndex.set1Value(jj++,SO_END_LINE_INDEX);
241 }
242 lineset->vertexProperty = verticesL;
243 sep->addChild(lineset);
244 }
245
246 alternateRep.setValue(sep);
247}
248
249//____________________________________________________________________
251{
252 alternateRep.setValue(NULL);
253}
254
virtual void clearAlternateRep()
SoSFBool forceEdgeLinesInBaseColour
std::vector< float > m_points
virtual ~SoTessellated()
void setupDefaultPoints()
static void initClass()
virtual void generateAlternateRep()
void addTriangularFacet(double x1, double y1, double z1, double x2, double y2, double z2, double x3, double y3, double z3)
void addQuadrangularFacet(double x1, double y1, double z1, double x2, double y2, double z2, double x3, double y3, double z3, double x4, double y4, double z4)
virtual void computeBBox(SoAction *action, SbBox3f &box, SbVec3f &center)
SoSFNode alternateRep
SoSFBool drawEdgeLines
virtual void generatePrimitives(SoAction *action)
std::vector< float > m_normals
double xmax
Definition listroot.cxx:61
double ymin
Definition listroot.cxx:63
double xmin
Definition listroot.cxx:60
double ymax
Definition listroot.cxx:64