Home | History | Annotate | Download | only in detail
      1 ///////////////////////////////////////////////////////////////////////////////////
      2 /// OpenGL Mathematics (glm.g-truc.net)
      3 ///
      4 /// Copyright (c) 2005 - 2014 G-Truc Creation (www.g-truc.net)
      5 /// Permission is hereby granted, free of charge, to any person obtaining a copy
      6 /// of this software and associated documentation files (the "Software"), to deal
      7 /// in the Software without restriction, including without limitation the rights
      8 /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      9 /// copies of the Software, and to permit persons to whom the Software is
     10 /// furnished to do so, subject to the following conditions:
     11 /// 
     12 /// The above copyright notice and this permission notice shall be included in
     13 /// all copies or substantial portions of the Software.
     14 /// 
     15 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16 /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17 /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     18 /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19 /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     20 /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     21 /// THE SOFTWARE.
     22 ///
     23 /// @ref core
     24 /// @file glm/core/func_geometric.inl
     25 /// @date 2008-08-03 / 2011-06-15
     26 /// @author Christophe Riccio
     27 ///////////////////////////////////////////////////////////////////////////////////
     28 
     29 #include "func_exponential.hpp"
     30 #include "func_common.hpp"
     31 #include "type_vec2.hpp"
     32 #include "type_vec4.hpp"
     33 #include "type_float.hpp"
     34 
     35 namespace glm{
     36 namespace detail
     37 {
     38 	template <template <class, precision> class vecType, typename T, precision P>
     39 	struct compute_dot{};
     40 
     41 	template <typename T, precision P>
     42 	struct compute_dot<detail::tvec1, T, P>
     43 	{
     44 		GLM_FUNC_QUALIFIER static T call(detail::tvec1<T, P> const & x, detail::tvec1<T, P> const & y)
     45 		{
     46 #			ifdef __CUDACC__ // Wordaround for a CUDA compiler bug up to CUDA6
     47 				detail::tvec1<T, P> tmp(x * y);
     48 				return tmp.x;
     49 #			else
     50 				return detail::tvec1<T, P>(x * y).x;
     51 #			endif
     52 		}
     53 	};
     54 
     55 	template <typename T, precision P>
     56 	struct compute_dot<detail::tvec2, T, P>
     57 	{
     58 		GLM_FUNC_QUALIFIER static T call(detail::tvec2<T, P> const & x, detail::tvec2<T, P> const & y)
     59 		{
     60 			detail::tvec2<T, P> tmp(x * y);
     61 			return tmp.x + tmp.y;
     62 		}
     63 	};
     64 
     65 	template <typename T, precision P>
     66 	struct compute_dot<detail::tvec3, T, P>
     67 	{
     68 		GLM_FUNC_QUALIFIER static T call(detail::tvec3<T, P> const & x, detail::tvec3<T, P> const & y)
     69 		{
     70 			detail::tvec3<T, P> tmp(x * y);
     71 			return tmp.x + tmp.y + tmp.z;
     72 		}
     73 	};
     74 
     75 	template <typename T, precision P>
     76 	struct compute_dot<detail::tvec4, T, P>
     77 	{
     78 		GLM_FUNC_QUALIFIER static T call(detail::tvec4<T, P> const & x, detail::tvec4<T, P> const & y)
     79 		{
     80 			detail::tvec4<T, P> tmp(x * y);
     81 			return (tmp.x + tmp.y) + (tmp.z + tmp.w);
     82 		}
     83 	};
     84 }//namespace detail
     85 
     86 	// length
     87 	template <typename genType>
     88 	GLM_FUNC_QUALIFIER genType length
     89 	(
     90 		genType const & x
     91 	)
     92 	{
     93 		GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'length' only accept floating-point inputs");
     94 
     95 		genType sqr = x * x;
     96 		return sqrt(sqr);
     97 	}
     98 
     99 	template <typename T, precision P>
    100 	GLM_FUNC_QUALIFIER T length(detail::tvec2<T, P> const & v)
    101 	{
    102 		GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'length' only accept floating-point inputs");
    103 
    104 		T sqr = v.x * v.x + v.y * v.y;
    105 		return sqrt(sqr);
    106 	}
    107 
    108 	template <typename T, precision P>
    109 	GLM_FUNC_QUALIFIER T length(detail::tvec3<T, P> const & v)
    110 	{
    111 		GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'length' only accept floating-point inputs");
    112 
    113 		T sqr = v.x * v.x + v.y * v.y + v.z * v.z;
    114 		return sqrt(sqr);
    115 	}
    116 
    117 	template <typename T, precision P>
    118 	GLM_FUNC_QUALIFIER T length(detail::tvec4<T, P> const & v)
    119 	{
    120 		GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'length' only accept floating-point inputs");
    121 
    122 		T sqr = v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w;
    123 		return sqrt(sqr);
    124 	}
    125 
    126 	// distance
    127 	template <typename genType>
    128 	GLM_FUNC_QUALIFIER genType distance
    129 	(
    130 		genType const & p0,
    131 		genType const & p1
    132 	)
    133 	{
    134 		GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'distance' only accept floating-point inputs");
    135 
    136 		return length(p1 - p0);
    137 	}
    138 
    139 	template <typename T, precision P>
    140 	GLM_FUNC_QUALIFIER T distance
    141 	(
    142 		detail::tvec2<T, P> const & p0,
    143 		detail::tvec2<T, P> const & p1
    144 	)
    145 	{
    146 		GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'distance' only accept floating-point inputs");
    147 
    148 		return length(p1 - p0);
    149 	}
    150 
    151 	template <typename T, precision P>
    152 	GLM_FUNC_QUALIFIER T distance
    153 	(
    154 		detail::tvec3<T, P> const & p0,
    155 		detail::tvec3<T, P> const & p1
    156 	)
    157 	{
    158 		GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'distance' only accept floating-point inputs");
    159 
    160 		return length(p1 - p0);
    161 	}
    162 
    163 	template <typename T, precision P>
    164 	GLM_FUNC_QUALIFIER T distance
    165 	(
    166 		detail::tvec4<T, P> const & p0,
    167 		detail::tvec4<T, P> const & p1
    168 	)
    169 	{
    170 		GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'distance' only accept floating-point inputs");
    171 
    172 		return length(p1 - p0);
    173 	}
    174 
    175 	// dot
    176 	template <typename T>
    177 	GLM_FUNC_QUALIFIER T dot
    178 	(
    179 		T const & x,
    180 		T const & y
    181 	)
    182 	{
    183 		GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'dot' only accept floating-point inputs");
    184 		return detail::compute_dot<detail::tvec1, T, highp>::call(x, y);
    185 	}
    186 
    187 	template <typename T, precision P, template <typename, precision> class vecType>
    188 	GLM_FUNC_QUALIFIER T dot
    189 	(
    190 		vecType<T, P> const & x,
    191 		vecType<T, P> const & y
    192 	)
    193 	{
    194 		GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'dot' only accept floating-point inputs");
    195 		return detail::compute_dot<vecType, T, P>::call(x, y);
    196 	}
    197 
    198 /* // SSE3
    199 	GLM_FUNC_QUALIFIER float dot(const tvec4<float>& x, const tvec4<float>& y)
    200 	{
    201 		float Result;
    202 		__asm
    203 		{
    204 			mov		esi, x
    205 			mov		edi, y
    206 			movaps	xmm0, [esi]
    207 			mulps	xmm0, [edi]
    208 			haddps(	_xmm0, _xmm0 )
    209 			haddps(	_xmm0, _xmm0 )
    210 			movss	Result, xmm0
    211 		}
    212 		return Result;
    213 	}
    214 */
    215 	// cross
    216 	template <typename T, precision P>
    217 	GLM_FUNC_QUALIFIER detail::tvec3<T, P> cross
    218 	(
    219 		detail::tvec3<T, P> const & x,
    220 		detail::tvec3<T, P> const & y
    221 	)
    222 	{
    223 		GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'cross' only accept floating-point inputs");
    224 
    225 		return detail::tvec3<T, P>(
    226 			x.y * y.z - y.y * x.z,
    227 			x.z * y.x - y.z * x.x,
    228 			x.x * y.y - y.x * x.y);
    229 	}
    230 
    231 	// normalize
    232 	template <typename genType>
    233 	GLM_FUNC_QUALIFIER genType normalize
    234 	(
    235 		genType const & x
    236 	)
    237 	{
    238 		GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'normalize' only accept floating-point inputs");
    239 
    240 		return x < genType(0) ? genType(-1) : genType(1);
    241 	}
    242 
    243 	// According to issue 10 GLSL 1.10 specification, if length(x) == 0 then result is undefine and generate an error
    244 	template <typename T, precision P>
    245 	GLM_FUNC_QUALIFIER detail::tvec2<T, P> normalize
    246 	(
    247 		detail::tvec2<T, P> const & x
    248 	)
    249 	{
    250 		GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'normalize' only accept floating-point inputs");
    251 		
    252 		T sqr = x.x * x.x + x.y * x.y;
    253 		return x * inversesqrt(sqr);
    254 	}
    255 
    256 	template <typename T, precision P>
    257 	GLM_FUNC_QUALIFIER detail::tvec3<T, P> normalize
    258 	(
    259 		detail::tvec3<T, P> const & x
    260 	)
    261 	{
    262 		GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'normalize' only accept floating-point inputs");
    263 
    264 		T sqr = x.x * x.x + x.y * x.y + x.z * x.z;
    265 		return x * inversesqrt(sqr);
    266 	}
    267 
    268 	template <typename T, precision P>
    269 	GLM_FUNC_QUALIFIER detail::tvec4<T, P> normalize
    270 	(
    271 		detail::tvec4<T, P> const & x
    272 	)
    273 	{
    274 		GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'normalize' only accept floating-point inputs");
    275 		
    276 		T sqr = x.x * x.x + x.y * x.y + x.z * x.z + x.w * x.w;
    277 		return x * inversesqrt(sqr);
    278 	}
    279 
    280 	// faceforward
    281 	template <typename genType>
    282 	GLM_FUNC_QUALIFIER genType faceforward
    283 	(
    284 		genType const & N,
    285 		genType const & I,
    286 		genType const & Nref
    287 	)
    288 	{
    289 		return dot(Nref, I) < 0 ? N : -N;
    290 	}
    291 
    292 	// reflect
    293 	template <typename genType>
    294 	GLM_FUNC_QUALIFIER genType reflect
    295 	(
    296 		genType const & I,
    297 		genType const & N
    298 	)
    299 	{
    300 		return I - N * dot(N, I) * genType(2);
    301 	}
    302 
    303 	// refract
    304 	template <typename genType>
    305 	GLM_FUNC_QUALIFIER genType refract
    306 	(
    307 		genType const & I,
    308 		genType const & N,
    309 		genType const & eta
    310 	)
    311 	{
    312 		GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'refract' only accept floating-point inputs");
    313 
    314 		genType dotValue = dot(N, I);
    315 		genType k = genType(1) - eta * eta * (genType(1) - dotValue * dotValue);
    316 		if(k < genType(0))
    317 			return genType(0);
    318 		else
    319 			return eta * I - (eta * dotValue + sqrt(k)) * N;
    320 	}
    321 
    322 	template <typename T, precision P, template <typename, precision> class vecType>
    323 	GLM_FUNC_QUALIFIER vecType<T, P> refract
    324 	(
    325 		vecType<T, P> const & I,
    326 		vecType<T, P> const & N,
    327 		T const & eta
    328 	)
    329 	{
    330 		GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'refract' only accept floating-point inputs");
    331 
    332 		T dotValue = dot(N, I);
    333 		T k = T(1) - eta * eta * (T(1) - dotValue * dotValue);
    334 		if(k < T(0))
    335 			return vecType<T, P>(0);
    336 		else
    337 			return eta * I - (eta * dotValue + std::sqrt(k)) * N;
    338 	}
    339 
    340 }//namespace glm
    341