KiCad PCB EDA Suite
opengl_utils.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2015-2016 Mario Luzeiro <[email protected]>
5 * Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include "../../common_ogl/openGL_includes.h"
26#include "opengl_utils.h"
27#include <trigo.h>
28#include <wx/debug.h> // For the wxASSERT
29
30#define RADPERDEG 0.0174533
31
32void DrawRoundArrow( SFVEC3F aPosition, SFVEC3F aTargetPos, float aSize )
33{
34 wxASSERT( aSize > 0.0f );
35
36 SFVEC3F vec = aTargetPos - aPosition;
37 float length = glm::length( vec );
38
39 GLUquadricObj *quadObj;
40
41 glPushMatrix ();
42
43 glTranslatef( aPosition.x, aPosition.y, aPosition.z );
44
45 if( ( vec.x != 0.0f ) || ( vec.y != 0.0f ) )
46 {
47 glRotatef( atan2( vec.y, vec.x ) / RADPERDEG, 0.0f, 0.0f, 1.0f );
48 glRotatef( atan2( sqrt( vec.x * vec.x + vec.y * vec.y ), vec.z ) / RADPERDEG,
49 0.0f, 1.0f, 0.0f );
50
51 }
52 else if( vec.z < 0.0f )
53 {
54 glRotatef( 180.0f, 1.0f, 0.0f, 0.0f );
55 }
56
57 glTranslatef( 0.0f, 0.0f, length - 4.0f * aSize );
58
59 quadObj = gluNewQuadric();
60 gluQuadricDrawStyle( quadObj, GLU_FILL );
61 gluQuadricNormals( quadObj, GLU_SMOOTH );
62 gluCylinder( quadObj, 2.0 * aSize, 0.0, 4.0 * aSize, 12, 1 );
63 gluDeleteQuadric( quadObj );
64
65 quadObj = gluNewQuadric();
66 gluQuadricDrawStyle( quadObj, GLU_FILL );
67 gluQuadricNormals( quadObj, GLU_SMOOTH );
68 gluDisk( quadObj, 0.0, 2.0 * aSize, 12, 1 );
69 gluDeleteQuadric( quadObj );
70
71 quadObj = gluNewQuadric();
72 gluQuadricDrawStyle( quadObj, GLU_FILL );
73 gluQuadricNormals( quadObj, GLU_SMOOTH );
74 gluDisk( quadObj, 0.0, aSize, 12, 1 );
75 gluDeleteQuadric( quadObj );
76
77
78 quadObj = gluNewQuadric();
79 gluQuadricDrawStyle( quadObj, GLU_FILL );
80 gluQuadricNormals( quadObj, GLU_SMOOTH );
81 gluSphere( quadObj, aSize, 24, 24 );
82 gluDeleteQuadric( quadObj );
83
84 glTranslatef( 0.0f , 0.0f ,-length + 4.0f * aSize );
85
86 quadObj = gluNewQuadric();
87 gluQuadricDrawStyle( quadObj, GLU_FILL );
88 gluQuadricNormals( quadObj, GLU_SMOOTH );
89 gluCylinder( quadObj, aSize, aSize, length - 4.0 * aSize, 12, 1 );
90 gluDeleteQuadric( quadObj );
91
92 quadObj = gluNewQuadric();
93 gluQuadricDrawStyle( quadObj, GLU_FILL );
94 gluQuadricNormals( quadObj, GLU_SMOOTH );
95 gluDisk( quadObj, 0.0, aSize, 12, 1 );
96 gluDeleteQuadric( quadObj );
97
98 glPopMatrix ();
99}
100
101
102void DrawBoundingBox( const BBOX_3D& aBBox )
103{
104 wxASSERT( aBBox.IsInitialized() );
105
106 glBegin( GL_LINE_LOOP );
107 glVertex3f( aBBox.Min().x, aBBox.Min().y, aBBox.Min().z );
108 glVertex3f( aBBox.Max().x, aBBox.Min().y, aBBox.Min().z );
109 glVertex3f( aBBox.Max().x, aBBox.Max().y, aBBox.Min().z );
110 glVertex3f( aBBox.Min().x, aBBox.Max().y, aBBox.Min().z );
111 glEnd();
112
113 glBegin( GL_LINE_LOOP );
114 glVertex3f( aBBox.Min().x, aBBox.Min().y, aBBox.Max().z );
115 glVertex3f( aBBox.Max().x, aBBox.Min().y, aBBox.Max().z );
116 glVertex3f( aBBox.Max().x, aBBox.Max().y, aBBox.Max().z );
117 glVertex3f( aBBox.Min().x, aBBox.Max().y, aBBox.Max().z );
118 glEnd();
119
120 glBegin( GL_LINE_STRIP );
121 glVertex3f( aBBox.Min().x, aBBox.Min().y, aBBox.Min().z );
122 glVertex3f( aBBox.Min().x, aBBox.Min().y, aBBox.Max().z );
123 glEnd();
124
125 glBegin( GL_LINE_STRIP );
126 glVertex3f( aBBox.Max().x, aBBox.Min().y, aBBox.Min().z );
127 glVertex3f( aBBox.Max().x, aBBox.Min().y, aBBox.Max().z );
128 glEnd();
129
130 glBegin( GL_LINE_STRIP );
131 glVertex3f( aBBox.Max().x, aBBox.Max().y, aBBox.Min().z );
132 glVertex3f( aBBox.Max().x, aBBox.Max().y, aBBox.Max().z );
133 glEnd();
134
135 glBegin( GL_LINE_STRIP );
136 glVertex3f( aBBox.Min().x, aBBox.Max().y, aBBox.Min().z );
137 glVertex3f( aBBox.Min().x, aBBox.Max().y, aBBox.Max().z );
138 glEnd();
139}
140
141
142void DrawHalfOpenCylinder( unsigned int aNrSidesPerCircle )
143{
144 if( aNrSidesPerCircle > 1 )
145 {
146 const float radius = 0.5f;
147 const EDA_ANGLE delta = ANGLE_360 / aNrSidesPerCircle;
148
149 // Generate bottom
150 glNormal3f( 0.0f, 0.0f,-1.0f );
151 glBegin( GL_TRIANGLE_FAN );
152 glVertex3f( 0.0, 0.0, 0.0 ); // This is the V0 of the FAN
153
154 for( EDA_ANGLE ii = ANGLE_0; ii < ANGLE_180; ii += delta )
155 {
156 SFVEC2D corner = SFVEC2D( 0.0, radius );
157 RotatePoint( &corner.x, &corner.y, ii );
158 glVertex3f( corner.x, corner.y, 0.0 );
159 }
160
161 glVertex3d( 0.0, -radius, 0.0 );
162 glEnd();
163
164 // Generate top
165 glNormal3f( 0.0f, 0.0f, 1.0f );
166 glBegin( GL_TRIANGLE_FAN );
167 glVertex3f( 0.0, 0.0, 1.0 ); // This is the V0 of the FAN
168
169 for( EDA_ANGLE ii = ANGLE_180; ii > ANGLE_0; ii -= delta )
170 {
171 SFVEC2D corner = SFVEC2D( 0.0, radius );
172
173 RotatePoint( &corner.x, &corner.y, ii );
174 glVertex3f( corner.x, corner.y, 1.0 );
175 }
176
177 glVertex3f( 0.0, radius, 1.0 );
178 glEnd();
179
180 // Generate contours
181 glBegin( GL_QUAD_STRIP );
182
183 for( EDA_ANGLE ii = ANGLE_180; ii > ANGLE_0; ii -= delta )
184 {
185 SFVEC2D corner = SFVEC2D( 0.0, radius );
186
187 RotatePoint( &corner.x, &corner.y, ii );
188 glNormal3f( corner.x * 2.0f, corner.y * 2.0f, 0.0f );
189 glVertex3f( corner.x, corner.y, 1.0 );
190 glVertex3f( corner.x, corner.y, 0.0 );
191 }
192
193 glNormal3f( 0.0, 1.0f, 0.0f );
194 glVertex3d( 0.0, radius, 1.0 );
195 glVertex3d( 0.0, radius, 0.0 );
196 glEnd();
197 }
198}
199
200
201void DrawSegment( const ROUND_SEGMENT_2D& aSegment, unsigned int aNrSidesPerCircle )
202{
203 glPushMatrix();
204
205 const SFVEC2F& start = aSegment.GetStart();
206 const SFVEC2F& end_minus_start = aSegment.GetEnd_minus_Start();
207 const float radius = aSegment.GetRadius();
208 const float width = aSegment.GetWidth();
209 const float length = aSegment.GetLength();
210
211 glTranslatef( start.x, start.y, 0.0f );
212
213 if( ( end_minus_start.x != 0.0f ) || ( end_minus_start.y != 0.0f ) )
214 {
215 glRotatef( atan2( end_minus_start.y, end_minus_start.x ) / RADPERDEG, 0.0f, 0.0f, 1.0f );
216 }
217
218 glPushMatrix();
219 glTranslatef( length, 0.0, 0.0f );
220 glScalef( width, width, 1.0f );
221 DrawHalfOpenCylinder( aNrSidesPerCircle );
222 glPopMatrix();
223
224 glBegin( GL_QUADS );
225 glNormal3f( 0.0,-1.0, 0.0 );
226 glVertex3f( length,-radius, 1.0 );
227 glVertex3f( 0.0, -radius, 1.0 );
228 glVertex3f( 0.0, -radius, 0.0 );
229 glVertex3f( length,-radius, 0.0 );
230 glEnd();
231
232 glBegin( GL_QUADS );
233 glNormal3f( 0.0, 1.0, 0.0 );
234 glVertex3f( length, radius, 0.0 );
235 glVertex3f( 0.0, radius, 0.0 );
236 glVertex3f( 0.0, radius, 1.0 );
237 glVertex3f( length, radius, 1.0 );
238 glEnd();
239
240 glBegin( GL_QUADS );
241 glNormal3f( 0.0, 0.0, 1.0 );
242 glVertex3f( length, radius, 1.0 );
243 glVertex3f( 0.0, radius, 1.0 );
244 glVertex3f( 0.0, -radius, 1.0 );
245 glVertex3f( length,-radius, 1.0 );
246 glEnd();
247
248 glBegin( GL_QUADS );
249 glNormal3f( 0.0, 0.0,-1.0 );
250 glVertex3f( length,-radius, 0.0 );
251 glVertex3f( 0.0, -radius, 0.0 );
252 glVertex3f( 0.0, radius, 0.0 );
253 glVertex3f( length, radius, 0.0 );
254 glEnd();
255
256 glScalef( width, width, 1.0f );
257 glRotatef( 180, 0.0, 0.0, 1.0 );
258 DrawHalfOpenCylinder( aNrSidesPerCircle );
259
260 glPopMatrix ();
261}
float GetRadius() const
float GetWidth() const
float GetLength() const
const SFVEC2F & GetStart() const
const SFVEC2F & GetEnd_minus_Start() const
static constexpr EDA_ANGLE & ANGLE_180
Definition: eda_angle.h:427
static constexpr EDA_ANGLE & ANGLE_360
Definition: eda_angle.h:429
static constexpr EDA_ANGLE & ANGLE_0
Definition: eda_angle.h:423
void DrawSegment(const ROUND_SEGMENT_2D &aSegment, unsigned int aNrSidesPerCircle)
Draw a thick line segment with rounded ends.
void DrawHalfOpenCylinder(unsigned int aNrSidesPerCircle)
Draw a half open cylinder with diameter 1.0f and height 1.0f.
void DrawRoundArrow(SFVEC3F aPosition, SFVEC3F aTargetPos, float aSize)
Draw a round arrow.
#define RADPERDEG
void DrawBoundingBox(const BBOX_3D &aBBox)
Draw the bounding box lines.
Manage a bounding box defined by two SFVEC3F min max points.
Definition: bbox_3d.h:42
const SFVEC3F & Min() const
Return the minimum vertex pointer.
Definition: bbox_3d.h:183
const SFVEC3F & Max() const
Return the maximum vertex pointer.
Definition: bbox_3d.h:190
bool IsInitialized() const
Check if this bounding box is already initialized.
Definition: bbox_3d.cpp:88
constexpr int delta
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Definition: trigo.cpp:183
glm::vec2 SFVEC2F
Definition: xv3d_types.h:42
glm::dvec2 SFVEC2D
Definition: xv3d_types.h:43
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44