Mantid
Loading...
Searching...
No Matches
RenderingHelpersOpenGL.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
19#include "MantidKernel/Quat.h"
21#include <climits>
22
23#ifdef ENABLE_OPENCASCADE
24// Squash a warning coming out of an OpenCascade header
25#ifdef __INTEL_COMPILER
26#pragma warning disable 191
27#endif
28// Opencascade defines _USE_MATH_DEFINES without checking whether it is already
29// used.
30// Undefine it here before we include the headers to avoid a warning
31#ifdef _MSC_VER
32#undef _USE_MATH_DEFINES
33#ifdef M_SQRT1_2
34#undef M_SQRT1_2
35#endif
36#endif
37
38GNU_DIAG_OFF("conversion")
39GNU_DIAG_OFF("cast-qual")
40
41#include <BRep_Tool.hxx>
42#include <Poly_Array1OfTriangle.hxx>
43#include <Poly_Triangulation.hxx>
44#include <Standard_Version.hxx>
45#include <TColgp_Array1OfPnt.hxx>
46#include <TopExp_Explorer.hxx>
47#include <TopoDS.hxx>
48#include <TopoDS_Face.hxx>
49#include <TopoDS_Shape.hxx>
50#include <gp_Pnt.hxx>
51GNU_DIAG_ON("conversion")
52GNU_DIAG_ON("cast-qual")
53
54#ifdef __INTEL_COMPILER
55#pragma warning enable 191
56#endif
57
58namespace {
59auto getNode(const Handle(Poly_Triangulation) facing, Standard_Integer i) {
60#if OCC_VERSION_MAJOR >= 7 && OCC_VERSION_MINOR >= 6
61 return facing->Node(i);
62#else
63 // Compat shim to support OCCT 7.5 and below
64 TColgp_Array1OfPnt tab(1, (facing->NbNodes()));
65 tab = facing->Nodes();
66 return tab.Value(i);
67
68#endif
69}
70
71auto getTriangle(const Handle(Poly_Triangulation) facing, Standard_Integer i) {
72#if OCC_VERSION_MAJOR >= 7 && OCC_VERSION_MINOR >= 6
73 return facing->Triangle(i);
74#else
75 // Compat shim to support OCCT 7.5 and below
76 Poly_Array1OfTriangle tri(1, facing->NbTriangles());
77 tri = facing->Triangles();
78 return tri.Value(i);
79
80#endif
81}
82} // namespace
83#endif // ENABLE_OPENCASCADE
84
85namespace Mantid::Geometry {
86using Kernel::Quat;
87using Kernel::V3D;
88
89namespace {
90// Render IObjectComponent
91void render(const IObjComponent &ObjComp) {
92 glPushMatrix();
93 V3D pos = ObjComp.getPos();
94 Quat rot = ObjComp.getRotation();
95 double rotGL[16];
96 rot.GLMatrix(&rotGL[0]);
97 glTranslated(pos[0], pos[1], pos[2]);
98 glMultMatrixd(rotGL);
99 V3D scaleFactor = ObjComp.getScaleFactor();
100 glScaled(scaleFactor[0], scaleFactor[1], scaleFactor[2]);
101 ObjComp.drawObject();
102 glPopMatrix();
103}
104
105// Render triangulated surface
106void render(detail::GeometryTriangulator &triangulator) {
107 const auto &faces = triangulator.getTriangleFaces();
108 const auto &points = triangulator.getTriangleVertices();
109 glBegin(GL_TRIANGLES);
110 for (size_t i = 0; i < triangulator.numTriangleFaces(); i++) {
111 auto index2 = static_cast<size_t>(faces[i * 3 + 1] * 3);
112 auto index3 = static_cast<size_t>(faces[i * 3 + 2] * 3);
113 auto index1 = static_cast<size_t>(faces[i * 3] * 3);
114 // Calculate normal and normalize
115 const V3D v1(points[index1], points[index1 + 1], points[index1 + 2]);
116 const V3D v2(points[index2], points[index2 + 1], points[index2 + 2]);
117 const V3D v3(points[index3], points[index3 + 1], points[index3 + 2]);
118 const auto normal = normalize((v1 - v2).cross_prod(v2 - v3));
119 glNormal3d(normal[0], normal[1], normal[2]);
120 glVertex3dv(&points[index1]);
121 glVertex3dv(&points[index2]);
122 glVertex3dv(&points[index3]);
123 }
124 glEnd();
125}
126
127#ifdef ENABLE_OPENCASCADE
128// Render OpenCascade Shape
129void render(const TopoDS_Shape &ObjSurf) {
130 glBegin(GL_TRIANGLES);
131 if (!ObjSurf.IsNull()) {
132 TopExp_Explorer Ex;
133 for (Ex.Init(ObjSurf, TopAbs_FACE); Ex.More(); Ex.Next()) {
134 TopoDS_Face F = TopoDS::Face(Ex.Current());
135 TopLoc_Location L;
136 Handle(Poly_Triangulation) facing = BRep_Tool::Triangulation(F, L);
137
138 for (Standard_Integer i = 1; i <= (facing->NbTriangles()); i++) {
139 const Poly_Triangle trian = getTriangle(facing, i);
140 Standard_Integer index1, index2, index3;
141 trian.Get(index1, index2, index3);
142 gp_Pnt point1 = getNode(facing, index1);
143 gp_Pnt point2 = getNode(facing, index2);
144 gp_Pnt point3 = getNode(facing, index3);
145 gp_XYZ pt1 = point1.XYZ();
146 gp_XYZ pt2 = point2.XYZ();
147 gp_XYZ pt3 = point3.XYZ();
148
149 gp_XYZ v1 = pt2 - pt1;
150 gp_XYZ v2 = pt3 - pt2;
151
152 gp_XYZ normal = v1 ^ v2;
153 normal.Normalize();
154 glNormal3d(normal.X(), normal.Y(), normal.Z());
155 glVertex3d(point1.X(), point1.Y(), point1.Z());
156 glVertex3d(point2.X(), point2.Y(), point2.Z());
157 glVertex3d(point3.X(), point3.Y(), point3.Z());
158 }
159 }
160 }
161 glEnd();
162}
163#endif
164
165void renderSphere(const detail::ShapeInfo &shapeInfo) {
166 // create glu sphere
167 GLUquadricObj *qobj = gluNewQuadric();
168 gluQuadricDrawStyle(qobj, GLU_FILL);
169 gluQuadricNormals(qobj, GL_SMOOTH);
170 glPushMatrix();
171 auto center = shapeInfo.points()[0];
172 glTranslated(center[0], center[1], center[2]);
173 gluSphere(qobj, shapeInfo.radius(), Sphere::g_NSLICES, Sphere::g_NSTACKS);
174 glPopMatrix();
175 gluDeleteQuadric(qobj);
176}
177
178void renderCuboid(const detail::ShapeInfo &shapeInfo) {
179 const auto &points = shapeInfo.points();
180 V3D vec0 = points[0];
181 V3D vec1 = points[1] - points[0];
182 V3D vec2 = points[2] - points[0];
183 V3D vec3 = points[3] - points[0];
184 V3D vertex[8];
185 vertex[0] = vec0;
186 vertex[1] = vec0 + vec3;
187 vertex[2] = vec0 + vec3 + vec1;
188 vertex[3] = vec0 + vec1;
189 vertex[4] = vec0 + vec2;
190 vertex[5] = vec0 + vec2 + vec3;
191 vertex[6] = vec0 + vec2 + vec3 + vec1;
192 vertex[7] = vec0 + vec1 + vec2;
193
194 int faceindex[6][4] = {
195 {0, 1, 2, 3}, // top
196 {0, 3, 7, 4}, // left
197 {3, 2, 6, 7}, // back
198 {2, 1, 5, 6}, // right
199 {0, 4, 5, 1}, // front
200 {4, 7, 6, 5}, // bottom
201 };
202 // first face
203 glBegin(GL_QUADS);
204 for (auto &row : faceindex) {
205 const auto normal = normalize((vertex[row[0]] - vertex[row[1]]).cross_prod((vertex[row[0]] - vertex[row[2]])));
206 glNormal3d(normal[0], normal[1], normal[2]);
207 for (const int ij : row) {
208 if (ij == 0)
209 glTexCoord2i(0, 0);
210 if (ij == 1)
211 glTexCoord2i(1, 0);
212 if (ij == 2)
213 glTexCoord2i(1, 1);
214 if (ij == 3)
215 glTexCoord2i(0, 1);
216 if (ij == 4)
217 glTexCoord2i(0, 0);
218 if (ij == 5)
219 glTexCoord2i(1, 0);
220 if (ij == 6)
221 glTexCoord2i(1, 1);
222 if (ij == 7)
223 glTexCoord2i(0, 1);
224 glVertex3d(vertex[ij][0], vertex[ij][1], vertex[ij][2]);
225 }
226 }
227 glEnd();
228}
229
230void renderHexahedron(const detail::ShapeInfo &shapeInfo) {
231 glBegin(GL_QUADS);
232 const auto &points = shapeInfo.points();
233 // bottom
234 glVertex3d(points[0].X(), points[0].Y(), points[0].Z());
235 glVertex3d(points[1].X(), points[1].Y(), points[1].Z());
236 glVertex3d(points[2].X(), points[2].Y(), points[2].Z());
237 glVertex3d(points[3].X(), points[3].Y(), points[3].Z());
238 // front
239 glVertex3d(points[1].X(), points[1].Y(), points[1].Z());
240 glVertex3d(points[5].X(), points[5].Y(), points[5].Z());
241 glVertex3d(points[6].X(), points[6].Y(), points[6].Z());
242 glVertex3d(points[2].X(), points[2].Y(), points[2].Z());
243 // right
244 glVertex3d(points[2].X(), points[2].Y(), points[2].Z());
245 glVertex3d(points[6].X(), points[6].Y(), points[6].Z());
246 glVertex3d(points[7].X(), points[7].Y(), points[7].Z());
247 glVertex3d(points[3].X(), points[3].Y(), points[3].Z());
248 // back
249 glVertex3d(points[3].X(), points[3].Y(), points[3].Z());
250 glVertex3d(points[7].X(), points[7].Y(), points[7].Z());
251 glVertex3d(points[4].X(), points[4].Y(), points[4].Z());
252 glVertex3d(points[0].X(), points[0].Y(), points[0].Z());
253 // left
254 glVertex3d(points[0].X(), points[0].Y(), points[0].Z());
255 glVertex3d(points[4].X(), points[4].Y(), points[4].Z());
256 glVertex3d(points[5].X(), points[5].Y(), points[5].Z());
257 glVertex3d(points[1].X(), points[1].Y(), points[1].Z());
258 // top
259 glVertex3d(points[4].X(), points[4].Y(), points[4].Z());
260 glVertex3d(points[5].X(), points[5].Y(), points[5].Z());
261 glVertex3d(points[6].X(), points[6].Y(), points[6].Z());
262 glVertex3d(points[7].X(), points[7].Y(), points[7].Z());
263
264 glEnd();
265}
266
267void renderCone(const detail::ShapeInfo &shapeInfo) {
268 glPushMatrix();
269 GLUquadricObj *qobj = gluNewQuadric();
270 gluQuadricDrawStyle(qobj, GLU_FILL);
271 gluQuadricNormals(qobj, GL_SMOOTH);
272 auto center = shapeInfo.points()[0];
273 glTranslated(center[0], center[1], center[2]);
274 GLdouble mat[16];
275 V3D unit(0, 0, 1);
276 auto axis = shapeInfo.points()[1];
277 Quat rot(unit, axis);
278 rot.GLMatrix(&mat[0]);
279 glMultMatrixd(mat);
280 auto radius = shapeInfo.radius();
281 auto height = shapeInfo.height();
283 glTranslated(0.0, 0.0, height);
284 gluDisk(qobj, 0, radius, Geometry::Cone::g_NSLICES, 1);
285 glPopMatrix();
286}
287
288void renderCylinder(const detail::ShapeInfo &shapeInfo) {
289 GLUquadricObj *qobj = gluNewQuadric();
290 gluQuadricDrawStyle(qobj, GLU_FILL);
291 gluQuadricNormals(qobj, GL_SMOOTH);
292 gluQuadricTexture(qobj, true);
293 glPushMatrix();
294 auto center = shapeInfo.points()[0];
295 glTranslated(center[0], center[1], center[2]);
296 GLdouble mat[16];
297 V3D unit(0, 0, 1);
298 auto axis = shapeInfo.points()[1];
299 Quat rot(unit, axis);
300 rot.GLMatrix(&mat[0]);
301 glMultMatrixd(mat);
302 auto radius = shapeInfo.radius();
303 auto height = shapeInfo.height();
305 gluQuadricTexture(qobj, false);
306 gluDisk(qobj, 0, radius, Cylinder::g_NSLICES, 1);
307 glTranslated(0.0, 0.0, height);
308 gluDisk(qobj, 0, radius, Cylinder::g_NSLICES, 1);
309 glPopMatrix();
310}
311} // namespace
312
313namespace RenderingHelpers {
314void renderIObjComponent(const IObjComponent &objComp) { render(objComp); }
315
317#ifdef ENABLE_OPENCASCADE
318 if (triangulator.hasOCSurface() && !triangulator.getOCSurface().IsNull())
319 render(triangulator.getOCSurface());
320 else
321 render(triangulator);
322#else
323 render(triangulator);
324#endif
325}
326
327void renderShape(const detail::ShapeInfo &shapeInfo) {
328 switch (shapeInfo.shape()) {
330 renderCuboid(shapeInfo);
331 break;
333 renderSphere(shapeInfo);
334 break;
336 renderHexahedron(shapeInfo);
337 break;
339 renderCone(shapeInfo);
340 break;
342 renderCylinder(shapeInfo);
343 break;
344 default:
345 return;
346 }
347}
348} // namespace RenderingHelpers
349} // namespace Mantid::Geometry
double height
Definition: GetAllEi.cpp:155
double radius
Definition: Rasterize.cpp:31
#define GNU_DIAG_ON(x)
#define GNU_DIAG_OFF(x)
This is a collection of macros for turning compiler warnings off in a controlled manner.
static constexpr int g_NSLICES
The number of slices to approximate a cone.
Definition: Cone.h:88
static constexpr int g_NSTACKS
The number of stacks to approximate a cone.
Definition: Cone.h:90
static constexpr int g_NSTACKS
The number of stacks to approximate a cylinder.
Definition: Cylinder.h:91
static constexpr int g_NSLICES
The number of slices to approximate a cylinder.
Definition: Cylinder.h:89
Object Component class, this class brings together the physical attributes of the component to the po...
Definition: IObjComponent.h:37
static constexpr int g_NSLICES
The number of slices to approximate a sphere.
Definition: Sphere.h:78
static constexpr int g_NSTACKS
The number of stacks to approximate a sphere.
Definition: Sphere.h:80
GeometryTriangulator : Triangulates object surfaces.
GeometryShape shape() const
Definition: ShapeInfo.cpp:27
boost::python::handle< T > Handle
Definition: Object.h:34
MANTID_GEOMETRY_DLL void renderIObjComponent(const IObjComponent &objComp)
Render IObjComponent.
MANTID_GEOMETRY_DLL void renderTriangulated(detail::GeometryTriangulator &triangulator)
Render Traingulated Surface.
MANTID_GEOMETRY_DLL void renderShape(const detail::ShapeInfo &shapeInfo)
Renders a sphere, cuboid, hexahedron, cone or cylinder.
MANTID_KERNEL_DLL V3D normalize(V3D v)
Normalizes a V3D.
Definition: V3D.h:341