NGL  6.5
The NCCA Graphics Library
Util.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 Jon Macey
3 
4  This program is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17 #include "Types.h"
18 #include "Mat4.h"
19 #include "Vec4.h"
20 #include <cmath>
21 #include <iostream>
22 #include <string>
23 //----------------------------------------------------------------------------------------------------------------------
26 //----------------------------------------------------------------------------------------------------------------------
27 namespace ngl
28 {
29 
30 //----------------------------------------------------------------------------------------------------------------------
31 NGL_DLLEXPORT Vec3 calcNormal(const Vec4 &_p1, const Vec4 &_p2, const Vec4 &_p3 ) noexcept
32 {
33 
34  Real coa, cob, coc ;
35  Real px1, py1, pz1 ;
36  Real px2, py2, pz2 ;
37  Real px3, py3, pz3 ;
38  Real absvec;
39  Vec3 norm;
40  px1 = _p1.m_x; py1 = _p1.m_y; pz1 = _p1.m_z;
41  px2 = _p2.m_x; py2 = _p2.m_y; pz2 = _p2.m_z;
42  px3 = _p3.m_x; py3 = _p3.m_y; pz3 = _p3.m_z;
43 
44  // generate cross product
45 
46  coa = -(py1 * (pz2-pz3) + py2*(pz3-pz1) + py3*(pz1-pz2)) ;
47  cob = -(pz1 * (px2-px3) + pz2*(px3-px1) + pz3*(px1-px2)) ;
48  coc = -(px1 * (py2-py3) + px2*(py3-py1) + px3*(py1-py2)) ;
49 
50  // normalise the results to get unit length normal
51  absvec = sqrtf ( ((coa*coa) + (cob*cob) + (coc*coc))) ;
52  norm.m_x = coa/absvec ;
53  norm.m_y = cob/absvec ;
54  norm.m_z = coc/absvec ;
55 
56  return norm;
57 }
58 
59 
60 //----------------------------------------------------------------------------------------------------------------------
61 NGL_DLLEXPORT Vec3 calcNormal (const Vec3 &_p1, const Vec3 &_p2, const Vec3 &_p3 ) noexcept
62 {
63 
64  Real coa, cob, coc ;
65  Real px1, py1, pz1 ;
66  Real px2, py2, pz2 ;
67  Real px3, py3, pz3 ;
68  Real absvec;
69  Vec3 norm;
70  px1 = _p1.m_x; py1 = _p1.m_y; pz1 = _p1.m_z;
71  px2 = _p2.m_x; py2 = _p2.m_y; pz2 = _p2.m_z;
72  px3 = _p3.m_x; py3 = _p3.m_y; pz3 = _p3.m_z;
73 
74  // generate cross product
75 
76  coa = -(py1 * (pz2-pz3) + py2*(pz3-pz1) + py3*(pz1-pz2)) ;
77  cob = -(pz1 * (px2-px3) + pz2*(px3-px1) + pz3*(px1-px2)) ;
78  coc = -(px1 * (py2-py3) + px2*(py3-py1) + px3*(py1-py2)) ;
79 
80  // normalise the results to get unit length normal
81  absvec = sqrtf ( ((coa*coa) + (cob*cob) + (coc*coc))) ;
82  norm.m_x = coa/absvec ;
83  norm.m_y = cob/absvec ;
84  norm.m_z = coc/absvec ;
85 
86  return norm;
87 }
88 
90 {
91  return (_deg/180.0f) * static_cast<Real>(M_PI);
92 }
93 
94 //----------------------------------------------------------------------------------------------------------------------
95 NGL_DLLEXPORT Real degrees( const Real _rad ) noexcept
96 {
97  return (_rad / static_cast<Real>(M_PI)) * 180.0f;
98 }
99 
100 
101 NGL_DLLEXPORT void NGLCheckGLError( const std::string &_file, const int _line ) noexcept
102 {
103  //std::cout<<"NGLCheckGLError Called ______________________\n";
104  auto errNum = glGetError();
105  while (errNum != GL_NO_ERROR)
106  {
107  // std::cout<<errNum<<"\n";
108  std::string str;
109  switch(errNum)
110  {
111  case GL_INVALID_ENUM : str="GL_INVALID_ENUM error"; break;
112  case GL_INVALID_VALUE : str="GL_INVALID_VALUE error"; break;
113  case GL_INVALID_OPERATION : str="GL_INVALID_OPERATION error"; break;
114  case GL_OUT_OF_MEMORY : str="GL_OUT_OF_MEMORY error"; break;
115  case GL_INVALID_FRAMEBUFFER_OPERATION : str="GL_INVALID_FRAMEBUFFER_OPERATION error"; break;
116  #ifndef USINGIOS_
117  case GL_STACK_UNDERFLOW : str= "GL_STACK_UNDERFLOW error"; break;
118  case GL_STACK_OVERFLOW : str= "GL_STACK_OVERFLOW error"; break;
119  #endif
120  // this should be in the spec but it's not on the mac! will check linux
121  default : break;
122  }
123  if(errNum !=GL_NO_ERROR)
124  {
125  std::cerr<<"GL error "<< str<<" line : "<<_line<<" file : "<<_file<<"\n";
126  }
127  errNum = glGetError();
128 
129  }
130 }
131 
132 
133 NGL_DLLEXPORT Mat4 perspective(Real _fovy,Real _aspect, Real _zNear, Real _zFar) noexcept
134 {
135  Mat4 result;
136  //glm usues a zero matrix and we are copying their funcs (see my unit tests here
137  // https://github.com/NCCA/VectorGLM)
138 
139  result.null();
140 // Real tanHalfFovy = tan(radians(_fovy) / 2.0f);
141 
142 // result.m_00 = 1.0f / (_aspect * tanHalfFovy);
143 // result.m_11 = 1.0f / (tanHalfFovy);
144 // result.m_22 = - (_zFar + _zNear) / (_zFar - _zNear);
145 // result.m_23 = - 1.0;
146 // result.m_32 = - (2.0f * _zFar * _zNear) / (_zFar - _zNear);
147 
148  Real range = tanf(radians(_fovy / 2.0f)) * _zNear;
149  Real left = -range * _aspect;
150  Real right = range * _aspect;
151  Real bottom = -range;
152  Real top = range;
153  result.m_00 = (2.0f * _zNear) / (right - left);
154  result.m_11 = (2.0f * _zNear) / (top - bottom);
155  result.m_22 = - (_zFar + _zNear) / (_zFar - _zNear);
156  result.m_23 = - 1.0f;
157  result.m_32 = - (2.0f* _zFar * _zNear) / (_zFar - _zNear);
158  return result;
159 }
160 
161 
162 NGL_DLLEXPORT Mat4 perspectiveFov(Real const & _fov, Real const & _width, Real const & _height, Real const & _zNear, Real const & _zFar) noexcept
163 {
164  Real rad = radians(_fov);
165  Real h = cosf(0.5f * rad) / sinf(0.5f * rad);
166  Real w = h * _height / _width;
167  Mat4 result;
168  //glm usues a zero matrix and we are copying their funcs (see my unit tests here
169  // https://github.com/NCCA/VectorGLM)
170  result.null();
171  result.m_00 = w;
172  result.m_11 = h;
173  result.m_22 = - (_zFar + _zNear) / (_zFar - _zNear);
174  result.m_23 = - 1.0f;
175  result.m_32 = - (2.0f* _zFar * _zNear) / (_zFar - _zNear);
176  return result;
177 }
178 
179 
180 NGL_DLLEXPORT Mat4 infinitePerspective(Real _fovy, Real _aspect, Real _zNear) noexcept
181 {
182  Real const range = tanf(radians(_fovy / 2.0f)) * _zNear;
183  Real left = -range * _aspect;
184  Real right = range * _aspect;
185  Real bottom = -range;
186  Real top = range;
187 
188  Mat4 result;
189  //glm usues a zero matrix and we are copying their funcs (see my unit tests here
190  // https://github.com/NCCA/VectorGLM)
191  result.null();
192  result.m_00 = (2.0f * _zNear) / (right - left);
193  result.m_11 = (2.0f * _zNear) / (top - bottom);
194  result.m_22 = - 1.0f;
195  result.m_23 = - 1.0f;
196  result.m_32 = - 2.0f * _zNear;
197  return result;
198 }
199 
200 
201 NGL_DLLEXPORT Mat4 lookAt(const Vec3 & _eye,const Vec3 & _center,const Vec3 & _up) noexcept
202 {
203 
204  Vec3 n = _center-_eye;
205  Vec3 u = _up;
206  Vec3 v = n.cross(u);
207  u = v.cross(n);
208  n.normalize();
209  v.normalize();
210  u.normalize();
211 
212  Mat4 result(1.0f);
213  result.m_00= v.m_x;
214  result.m_10= v.m_y;
215  result.m_20= v.m_z;
216  result.m_01= u.m_x;
217  result.m_11= u.m_y;
218  result.m_21= u.m_z;
219  result.m_02=-n.m_x;
220  result.m_12=-n.m_y;
221  result.m_22=-n.m_z;
222  result.m_30=-_eye.dot(v);
223  result.m_31=-_eye.dot(u);
224  result.m_32= _eye.dot(n);
225  return result;
226 }
227 
228 NGL_DLLEXPORT Mat4 ortho(Real _left, Real _right, Real _bottom, Real _top, Real _zNear, Real _zFar) noexcept
229 {
230  Mat4 result(1.0f);
231  result.m_00= 2.0f / (_right - _left);
232  result.m_11= 2.0f / (_top - _bottom);
233  result.m_22= - 2.0f / (_zFar - _zNear);
234  result.m_30= - (_right + _left) / (_right - _left);
235  result.m_31= - (_top + _bottom) / (_top - _bottom);
236  result.m_32= - (_zFar + _zNear) / (_zFar - _zNear);
237  return result;
238 }
239 
240 NGL_DLLEXPORT Mat4 ortho(Real _left, Real _right, Real _bottom, Real _top) noexcept
241 {
242  Mat4 result(1);
243  result.m_00= Real(2) / (_right - _left);
244  result.m_11= Real(2) / (_top - _bottom);
245  result.m_22= - Real(1);
246  result.m_30= - (_right + _left) / (_right - _left);
247  result.m_31= - (_top + _bottom) / (_top - _bottom);
248  return result;
249 }
250 
251 NGL_DLLEXPORT Mat4 frustum(Real _left, Real _right, Real _bottom, Real _top, Real _nearVal, Real _farVal) noexcept
252 {
253  Mat4 result;
254  result.null();
255  result.m_00 = (2.0f * _nearVal) / (_right - _left);
256  result.m_11 = (2.0f * _nearVal) / (_top - _bottom);
257  result.m_20 = (_right + _left) / (_right - _left);
258  result.m_21 = (_top + _bottom) / (_top - _bottom);
259  result.m_22 = -(_farVal + _nearVal) / (_farVal - _nearVal);
260  result.m_23 = -1.0f;
261  result.m_32 = -(2.0f * _farVal * _nearVal) / (_farVal - _nearVal);
262  return result;
263 }
264 
265 NGL_DLLEXPORT Vec3 unProject(const Vec3 &_win, const Mat4 &_model, const Mat4 &_project, const Vec4 &_viewport ) noexcept
266 {
267  ngl::Mat4 p,m;
268  p=_project;
269  m=_model;
270 
271  Mat4 inverse=( p.transpose()*m.transpose()).inverse();
272 
273  Vec4 tmp(0,0,_win.m_z,1.0f);
274  // convert into NDC
275  tmp.m_x=(2.0f * _win.m_x) / _viewport.m_openGL[2] - 1.0f;
276  tmp.m_y=1.0f - (2.0f * _win.m_y) / _viewport.m_openGL[3];
277  // scale by inverse MV * Project transform
278  Vec4 obj=inverse*tmp;
279  // Scale by w
280  obj/=obj.m_w;
281  return obj.toVec3();
282 }
283 
284 NGL_DLLEXPORT Vec3 project(const Vec3 &_pos, const Mat4 &_model, const Mat4 &_project, const Vec4 &_viewport ) noexcept
285 {
286  Vec4 tmp(_pos, 1.0);
287 // tmp = tmp*_model;
288 // tmp = tmp * _project;
289  tmp = _model*_project*tmp;
290  tmp /= tmp.m_w;
291  tmp = tmp * float(0.5);// + float(0.5);
292  tmp+=ngl::Vec3(0.5,0.5,0.5);
293  tmp[0] = tmp[0] * float(_viewport[2]) + float(_viewport[0]);
294  tmp[1] = tmp[1] * float(_viewport[3]) + float(_viewport[1]);
295 
296  return tmp.toVec3();
297 }
298 
299 // for more details see this site some greate stuff here (this code was modified from it)
300 // http://www.exploringbinary.com/ten-ways-to-check-if-an-integer-is-a-power-of-two-in-c/
301 NGL_DLLEXPORT bool isPowerOfTwo (unsigned int _x) noexcept
302 {
303  while (((_x % 2) == 0) && _x > 1) /* While x is even and > 1 */
304  {
305  _x /= 2;
306  }
307  return (_x == 1);
308 }
309 
310 // from http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
311 
312 NGL_DLLEXPORT unsigned int nextPow2(unsigned int _x) noexcept
313 {
314  _x -= 1;
315  _x |= _x >> 1;
316  _x |= _x >> 2;
317  _x |= _x >> 4;
318  _x |= _x >> 8;
319  _x |= _x >> 16;
320  return _x + 1;
321 }
322 
323 
324 } // end of namespace
325 
326 //----------------------------------------------------------------------------------------------------------------------
327 
328 
329 
GLfloat GLfloat GLfloat top
Definition: glew.h:15523
Real m_11
individual matrix element maps to m_m[1][1] or m_openGL[5]
Definition: Mat4.h:316
Real m_21
individual matrix element maps to m_m[2][1] or m_openGL[9]
Definition: Mat4.h:320
simple Vector class for OpenGL graphics, contains overloaded operators for most math functions...
Definition: Vec4.h:57
const Mat4 & null() noexcept
clear the matrix to all 0
Definition: Mat4.cpp:108
main definition of types and namespace
GLenum GLint * range
Definition: glew.h:3512
NGL_DLLEXPORT Vec3 calcNormal(const Vec4 &_p1, const Vec4 &_p2, const Vec4 &_p3) noexcept
calculates the normal from 3 points and return the new normal as a Vector
Definition: Util.cpp:31
#define GL_INVALID_OPERATION
Definition: glew.h:381
Real m_22
individual matrix element maps to m_m[2][2] or m_openGL[10]
Definition: Mat4.h:321
const Mat4 & transpose() noexcept
method to transpose the matrix
Definition: Mat4.cpp:389
#define NGL_DLLEXPORT
Definition: Types.h:65
Real m_12
individual matrix element maps to m_m[1][2] or m_openGL[6]
Definition: Mat4.h:317
#define GL_STACK_OVERFLOW
Definition: glew.h:12084
Vec3 toVec3() const noexcept
get as a Vec3 for glsl etc
Definition: Vec4.h:128
Real m_31
individual matrix element maps to m_m[3][1] or m_openGL[13]
Definition: Mat4.h:324
NGL_DLLEXPORT Mat4 perspectiveFov(Real const &_fov, Real const &_width, Real const &_height, Real const &_zNear, Real const &_zFar) noexcept
computer a perspective projection matrix similar to the one from the GLM library this is to help make...
Definition: Util.cpp:162
GLfloat right
Definition: glew.h:15523
simple Vec3 encapsulates a 3 float object like glsl vec3 but not maths use the Vec3 class for maths a...
Definition: Vec3.h:51
NGL_DLLEXPORT Mat4 frustum(Real _left, Real _right, Real _bottom, Real _top, Real _nearVal, Real _farVal) noexcept
calculate frustum matrix similar to the one from the GLM library this is to help make porting glm cod...
Definition: Util.cpp:251
NGL_DLLEXPORT bool isPowerOfTwo(unsigned int _x) noexcept
returns if value is a power of 2
Definition: Util.cpp:301
implementation files for RibExport class
Definition: AABB.cpp:22
Real m_30
individual matrix element maps to m_m[3][0] or m_openGL[12]
Definition: Mat4.h:323
#define GL_INVALID_VALUE
Definition: glew.h:380
#define GL_STACK_UNDERFLOW
Definition: glew.h:12085
PRECISION Real
create a variable called Real which is the main data type we use (GLfloat for most cases) ...
Definition: Types.h:127
encapsulates a 4d Homogenous Point / Vector object
Real m_02
individual matrix element maps to m_m[0][2] or m_openGL[2]
Definition: Mat4.h:313
NGL_DLLEXPORT Mat4 lookAt(const Vec3 &_eye, const Vec3 &_center, const Vec3 &_up) noexcept
calculate a look at matrix similar to the one from the GLM library this is to help make porting glm c...
Definition: Util.cpp:201
NGL_DLLEXPORT Mat4 ortho(Real _left, Real _right, Real _bottom, Real _top, Real _zNear, Real _zFar) noexcept
calculate an ortho graphic projection at matrix similar to the one from the GLM library this is to he...
Definition: Util.cpp:228
Real m_y
y component
Definition: Vec3.h:311
GLuint64EXT * result
Definition: glew.h:14309
NGL_DLLEXPORT Vec3 project(const Vec3 &_pos, const Mat4 &_model, const Mat4 &_project, const Vec4 &_viewport) noexcept
Definition: Util.cpp:284
GLubyte GLubyte GLubyte GLubyte w
Definition: glew.h:1893
const GLdouble * v
Definition: glew.h:1394
Real m_01
individual matrix element maps to m_m[0][1] or m_openGL[1]
Definition: Mat4.h:312
Real m_00
individual matrix element maps to m_m[0][0] or m_openGL[0]
Definition: Mat4.h:311
GLhandleARB obj
Definition: glew.h:6264
Real m_x
x component
Definition: Vec3.h:310
Real m_10
individual matrix element maps to m_m[1][0] or m_openGL[4]
Definition: Mat4.h:315
GLfloat GLfloat p
Definition: glew.h:16654
#define GL_OUT_OF_MEMORY
Definition: glew.h:384
Real m_23
individual matrix element maps to m_m[2][3] or m_openGL[11]
Definition: Mat4.h:322
GLint left
Definition: glew.h:8036
Real m_x
x component
Definition: Vec4.h:321
GLint GLint bottom
Definition: glew.h:8036
#define GL_NO_ERROR
Definition: glew.h:318
NGL_DLLEXPORT Real degrees(const Real _rad) noexcept
converts Radians to Degrees
Definition: Util.cpp:95
GLfloat GLfloat GLfloat GLfloat h
Definition: glew.h:8039
#define GL_INVALID_ENUM
Definition: glew.h:379
GLAPI GLenum GLAPIENTRY glGetError(void)
GLsizei n
Definition: glew.h:4052
Real m_32
individual matrix element maps to m_m[3][2] or m_openGL[14]
Definition: Mat4.h:325
NGL_DLLEXPORT Real radians(const Real _deg)
converts Degrees to Radians
Definition: Util.cpp:89
const GLdouble * m
Definition: glew.h:9164
Matrix Class to do simple matrix operations included operator overloaded functions for maths and matr...
Definition: Mat4.h:58
Real m_20
individual matrix element maps to m_m[2][0] or m_openGL[8]
Definition: Mat4.h:319
Real m_w
w component 0 for vector 1 for point
Definition: Vec4.h:324
NGL_DLLEXPORT Mat4 perspective(Real _fovy, Real _aspect, Real _zNear, Real _zFar) noexcept
computer a perspective projection matrix similar to the one from the GLM library this is to help make...
Definition: Util.cpp:133
Real m_y
y component
Definition: Vec4.h:322
void normalize() noexcept
Normalize the vector using .
Definition: Vec3.cpp:206
NGL_DLLEXPORT Vec3 unProject(const Vec3 &_win, const Mat4 &_model, const Mat4 &_project, const Vec4 &_viewport) noexcept
unproject points similar to the one from the GLM library this is to help make porting glm code easier...
Definition: Util.cpp:265
NGL_DLLEXPORT void NGLCheckGLError(const std::string &_file, const int _line) noexcept
check for openGL errors and print out.
Definition: Util.cpp:101
GLsizei const GLchar *const * string
Definition: glew.h:1847
NGL_DLLEXPORT Mat4 infinitePerspective(Real _fovy, Real _aspect, Real _zNear) noexcept
computer a perspective projection matrix similar to the one from the GLM library this is to help make...
Definition: Util.cpp:180
NGL_DLLEXPORT unsigned int nextPow2(unsigned int _x) noexcept
rounds up the value to next power of 2
Definition: Util.cpp:312
void cross(const Vec3 &_v1, const Vec3 &_v2) noexcept
set the Vec3 as the cross product from 2 other Vec3
Definition: Vec3.cpp:187
Real m_z
z component
Definition: Vec3.h:312
#define GL_INVALID_FRAMEBUFFER_OPERATION
Definition: glew.h:4470
GLclampf f
Definition: glew.h:3511