You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

193 lines
6.2 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
  5. * Copyright (C) 1992-2016 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. * @file 3d_math.h
  26. * @brief Defines math related functions
  27. */
  28. #ifndef _3D_MATH_H
  29. #define _3D_MATH_H
  30. #include <plugins/3dapi/xv3d_types.h>
  31. #include "3d_fastmath.h"
  32. // https://en.wikipedia.org/wiki/Spherical_coordinate_system
  33. /**
  34. * @brief SphericalToCartesian
  35. * @param aInclination θ [0, π]
  36. * @param aAzimuth φ [0, 2π]
  37. * @return Cartesian cordinates
  38. */
  39. inline SFVEC3F SphericalToCartesian( float aInclination, float aAzimuth )
  40. {
  41. float sinInc = glm::sin( aInclination );
  42. return SFVEC3F( sinInc * glm::cos( aAzimuth ),
  43. sinInc * glm::sin( aAzimuth ),
  44. glm::cos( aInclination ) );
  45. }
  46. // https://pathtracing.wordpress.com/2011/03/03/cosine-weighted-hemisphere/
  47. // !TODO: this is not correct because it is not a gaussian random
  48. inline SFVEC3F UniformRandomHemisphereDirection( )
  49. {
  50. // It was experienced that this function is slow! do not use it :/
  51. // SFVEC3F b( (rand()/(float)RAND_MAX) - 0.5f,
  52. // (rand()/(float)RAND_MAX) - 0.5f,
  53. // (rand()/(float)RAND_MAX) - 0.5f );
  54. SFVEC3F b( Fast_RandFloat() * 0.5f,
  55. Fast_RandFloat() * 0.5f,
  56. Fast_RandFloat() * 0.5f );
  57. return b;
  58. }
  59. // https://pathtracing.wordpress.com/2011/03/03/cosine-weighted-hemisphere/
  60. inline SFVEC3F CosWeightedRandomHemisphereDirection( const SFVEC3F &n )
  61. {
  62. const float Xi1 = (float)rand() / (float)RAND_MAX;
  63. const float Xi2 = (float)rand() / (float)RAND_MAX;
  64. const float theta = acos( sqrt( 1.0f - Xi1 ) );
  65. const float phi = 2.0f * glm::pi<float>() * Xi2;
  66. const float xs = sinf( theta ) * cosf( phi );
  67. const float ys = cosf( theta );
  68. const float zs = sinf( theta ) * sinf( phi );
  69. const SFVEC3F y( n.x, n.y, n.z );
  70. SFVEC3F h = y;
  71. if( fabs( h.x ) <= fabs( h.y ) && fabs( h.x ) <= fabs( h.z ) )
  72. h.x= 1.0f;
  73. else if( fabs( h.y ) <= fabs( h.x ) && fabs( h.y ) <= fabs( h.z ) )
  74. h.y= 1.0f;
  75. else
  76. h.z= 1.0f;
  77. const SFVEC3F x = glm::normalize( glm::cross( h, y ) );
  78. const SFVEC3F z = glm::normalize( glm::cross( x, y ) );
  79. SFVEC3F direction = xs * x + ys * y + zs * z;
  80. return glm::normalize( direction );
  81. }
  82. /**
  83. * @brief Refract
  84. * Based on:
  85. * https://github.com/mmp/pbrt-v3/blob/master/src/core/reflection.h
  86. * See also:
  87. * http://www.flipcode.com/archives/Raytracing_Topics_Techniques-Part_3_Refractions_and_Beers_Law.shtml
  88. * @param aInVector incoming vector
  89. * @param aNormal normal in the intersection point
  90. * @param aRin_over_Rout incoming refraction index / out refraction index
  91. * @param aOutVector the refracted vector
  92. * @return true
  93. */
  94. inline bool Refract( const SFVEC3F &aInVector,
  95. const SFVEC3F &aNormal,
  96. float aRin_over_Rout,
  97. SFVEC3F &aOutVector )
  98. {
  99. float cosThetaI = -glm::dot( aNormal, aInVector );
  100. float sin2ThetaI = glm::max( 0.0f, 1.0f - cosThetaI * cosThetaI );
  101. float sin2ThetaT = aRin_over_Rout * aRin_over_Rout * sin2ThetaI;
  102. // Handle total internal reflection for transmission
  103. if( sin2ThetaT >= 1.0f )
  104. return false;
  105. float cosThetaT = sqrtf( 1.0f - sin2ThetaT );
  106. aOutVector = glm::normalize( aRin_over_Rout * aInVector +
  107. ( aRin_over_Rout * cosThetaI - cosThetaT ) *
  108. aNormal );
  109. return true;
  110. }
  111. inline float mapf( float x,
  112. float in_min,
  113. float in_max,
  114. float out_min,
  115. float out_max)
  116. {
  117. x = glm::clamp( x, in_min, in_max );
  118. return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
  119. }
  120. inline float RGBtoGray( const SFVEC3F &aColor )
  121. {
  122. return (aColor.r * 0.2126f +
  123. aColor.g * 0.7152f +
  124. aColor.b * 0.0722f);
  125. }
  126. inline SFVEC3F MaterialDiffuseToColorCAD( const SFVEC3F &aDiffuseColor )
  127. {
  128. // convert to a discret scale of grays
  129. const float luminance = glm::min( (((float)((unsigned int) ( 4.0f *
  130. RGBtoGray( aDiffuseColor ) ) ) + 0.5f) /
  131. 4.0f) * 1.0f,
  132. 1.0f );
  133. const float maxValue = glm::max( glm::max( glm::max( aDiffuseColor.r,
  134. aDiffuseColor.g),
  135. aDiffuseColor.b ),
  136. FLT_EPSILON );
  137. return (aDiffuseColor / SFVEC3F(maxValue) ) * 0.125f + luminance* 0.875f;
  138. }
  139. // http://fooplot.com/#W3sidHlwZSI6MCwiZXEiOiJ4KngqMiIsImNvbG9yIjoiIzAwMDAwMCJ9LHsidHlwZSI6MCwiZXEiOiItKCh4LTEpXjIpKjIrMSIsImNvbG9yIjoiIzAwMDAwMCJ9LHsidHlwZSI6MTAwMCwid2luZG93IjpbIi0xLjM4NzUwMDAwMDAwMDAwMDIiLCIxLjg2MjQ5OTk5OTk5OTk5OTgiLCItMC43IiwiMS4zIl19XQ--
  140. inline float QuadricEasingInOut( float t )
  141. {
  142. if( t <= 0.5f )
  143. {
  144. return t * t * 2.0f;
  145. }
  146. else
  147. {
  148. t = t - 1.0f;
  149. return -2.0f * (t * t) + 1.0f;
  150. }
  151. }
  152. // http://www.wolframalpha.com/input/?i=t%5E2(3-2t)
  153. inline float BezierBlend( float t )
  154. {
  155. return t * t * ( 3.0f - 2.0f * t );
  156. }
  157. #endif // 3D_MATH_H