forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			547 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			547 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								#ifndef GIM_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
							 | 
						||
| 
								 | 
							
								#define GIM_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*! \file gim_basic_geometry_operations.h
							 | 
						||
| 
								 | 
							
								*\author Francisco Leon Najera
							 | 
						||
| 
								 | 
							
								type independant geometry routines
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								-----------------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								This source file is part of GIMPACT Library.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								For the latest info, see http://gimpact.sourceforge.net/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
							 | 
						||
| 
								 | 
							
								email: projectileman@yahoo.com
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								 This library is free software; you can redistribute it and/or
							 | 
						||
| 
								 | 
							
								 modify it under the terms of EITHER:
							 | 
						||
| 
								 | 
							
								   (1) The GNU Lesser General Public License as published by the Free
							 | 
						||
| 
								 | 
							
								       Software Foundation; either version 2.1 of the License, or (at
							 | 
						||
| 
								 | 
							
								       your option) any later version. The text of the GNU Lesser
							 | 
						||
| 
								 | 
							
								       General Public License is included with this library in the
							 | 
						||
| 
								 | 
							
								       file GIMPACT-LICENSE-LGPL.TXT.
							 | 
						||
| 
								 | 
							
								   (2) The BSD-style license that is included with this library in
							 | 
						||
| 
								 | 
							
								       the file GIMPACT-LICENSE-BSD.TXT.
							 | 
						||
| 
								 | 
							
								   (3) The zlib/libpng license that is included with this library in
							 | 
						||
| 
								 | 
							
								       the file GIMPACT-LICENSE-ZLIB.TXT.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								 This library is distributed in the hope that it will be useful,
							 | 
						||
| 
								 | 
							
								 but WITHOUT ANY WARRANTY; without even the implied warranty of
							 | 
						||
| 
								 | 
							
								 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
							 | 
						||
| 
								 | 
							
								 GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								-----------------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "gim_linear_math.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef PLANEDIREPSILON
							 | 
						||
| 
								 | 
							
								#define PLANEDIREPSILON 0.0000001f
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef PARALELENORMALS
							 | 
						||
| 
								 | 
							
								#define PARALELENORMALS 0.000001f
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define TRIANGLE_NORMAL(v1,v2,v3,n)\
							 | 
						||
| 
								 | 
							
								{\
							 | 
						||
| 
								 | 
							
									vec3f _dif1,_dif2;\
							 | 
						||
| 
								 | 
							
								    VEC_DIFF(_dif1,v2,v1);\
							 | 
						||
| 
								 | 
							
								    VEC_DIFF(_dif2,v3,v1);\
							 | 
						||
| 
								 | 
							
								    VEC_CROSS(n,_dif1,_dif2);\
							 | 
						||
| 
								 | 
							
								    VEC_NORMALIZE(n);\
							 | 
						||
| 
								 | 
							
								}\
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define TRIANGLE_NORMAL_FAST(v1,v2,v3,n){\
							 | 
						||
| 
								 | 
							
								    vec3f _dif1,_dif2; \
							 | 
						||
| 
								 | 
							
								    VEC_DIFF(_dif1,v2,v1); \
							 | 
						||
| 
								 | 
							
								    VEC_DIFF(_dif2,v3,v1); \
							 | 
						||
| 
								 | 
							
								    VEC_CROSS(n,_dif1,_dif2); \
							 | 
						||
| 
								 | 
							
								}\
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/// plane is a vec4f
							 | 
						||
| 
								 | 
							
								#define TRIANGLE_PLANE(v1,v2,v3,plane) {\
							 | 
						||
| 
								 | 
							
								    TRIANGLE_NORMAL(v1,v2,v3,plane);\
							 | 
						||
| 
								 | 
							
								    plane[3] = VEC_DOT(v1,plane);\
							 | 
						||
| 
								 | 
							
								}\
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/// plane is a vec4f
							 | 
						||
| 
								 | 
							
								#define TRIANGLE_PLANE_FAST(v1,v2,v3,plane) {\
							 | 
						||
| 
								 | 
							
								    TRIANGLE_NORMAL_FAST(v1,v2,v3,plane);\
							 | 
						||
| 
								 | 
							
								    plane[3] = VEC_DOT(v1,plane);\
							 | 
						||
| 
								 | 
							
								}\
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/// Calc a plane from an edge an a normal. plane is a vec4f
							 | 
						||
| 
								 | 
							
								#define EDGE_PLANE(e1,e2,n,plane) {\
							 | 
						||
| 
								 | 
							
								    vec3f _dif; \
							 | 
						||
| 
								 | 
							
								    VEC_DIFF(_dif,e2,e1); \
							 | 
						||
| 
								 | 
							
								    VEC_CROSS(plane,_dif,n); \
							 | 
						||
| 
								 | 
							
								    VEC_NORMALIZE(plane); \
							 | 
						||
| 
								 | 
							
								    plane[3] = VEC_DOT(e1,plane);\
							 | 
						||
| 
								 | 
							
								}\
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define DISTANCE_PLANE_POINT(plane,point) (VEC_DOT(plane,point) - plane[3])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define PROJECT_POINT_PLANE(point,plane,projected) {\
							 | 
						||
| 
								 | 
							
									GREAL _dis;\
							 | 
						||
| 
								 | 
							
									_dis = DISTANCE_PLANE_POINT(plane,point);\
							 | 
						||
| 
								 | 
							
									VEC_SCALE(projected,-_dis,plane);\
							 | 
						||
| 
								 | 
							
									VEC_SUM(projected,projected,point);	\
							 | 
						||
| 
								 | 
							
								}\
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//! Verifies if a point is in the plane hull
							 | 
						||
| 
								 | 
							
								template<typename CLASS_POINT,typename CLASS_PLANE>
							 | 
						||
| 
								 | 
							
								SIMD_FORCE_INLINE bool POINT_IN_HULL(
							 | 
						||
| 
								 | 
							
									const CLASS_POINT& point,const CLASS_PLANE * planes,GUINT plane_count)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									GREAL _dis;
							 | 
						||
| 
								 | 
							
									for (GUINT _i = 0;_i< plane_count;++_i)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										_dis = DISTANCE_PLANE_POINT(planes[_i],point);
							 | 
						||
| 
								 | 
							
									    if(_dis>0.0f) return false;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template<typename CLASS_POINT,typename CLASS_PLANE>
							 | 
						||
| 
								 | 
							
								SIMD_FORCE_INLINE void PLANE_CLIP_SEGMENT(
							 | 
						||
| 
								 | 
							
									const CLASS_POINT& s1,
							 | 
						||
| 
								 | 
							
									const CLASS_POINT &s2,const CLASS_PLANE &plane,CLASS_POINT &clipped)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									GREAL _dis1,_dis2;
							 | 
						||
| 
								 | 
							
									_dis1 = DISTANCE_PLANE_POINT(plane,s1);
							 | 
						||
| 
								 | 
							
									VEC_DIFF(clipped,s2,s1);
							 | 
						||
| 
								 | 
							
									_dis2 = VEC_DOT(clipped,plane);
							 | 
						||
| 
								 | 
							
									VEC_SCALE(clipped,-_dis1/_dis2,clipped);
							 | 
						||
| 
								 | 
							
									VEC_SUM(clipped,clipped,s1);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								enum ePLANE_INTERSECTION_TYPE
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									G_BACK_PLANE = 0,
							 | 
						||
| 
								 | 
							
									G_COLLIDE_PLANE,
							 | 
						||
| 
								 | 
							
									G_FRONT_PLANE
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								enum eLINE_PLANE_INTERSECTION_TYPE
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									G_FRONT_PLANE_S1 = 0,
							 | 
						||
| 
								 | 
							
									G_FRONT_PLANE_S2,
							 | 
						||
| 
								 | 
							
									G_BACK_PLANE_S1,
							 | 
						||
| 
								 | 
							
									G_BACK_PLANE_S2,
							 | 
						||
| 
								 | 
							
									G_COLLIDE_PLANE_S1,
							 | 
						||
| 
								 | 
							
									G_COLLIDE_PLANE_S2
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//! Confirms if the plane intersect the edge or nor
							 | 
						||
| 
								 | 
							
								/*!
							 | 
						||
| 
								 | 
							
								intersection type must have the following values
							 | 
						||
| 
								 | 
							
								<ul>
							 | 
						||
| 
								 | 
							
								<li> 0 : Segment in front of plane, s1 closest
							 | 
						||
| 
								 | 
							
								<li> 1 : Segment in front of plane, s2 closest
							 | 
						||
| 
								 | 
							
								<li> 2 : Segment in back of plane, s1 closest
							 | 
						||
| 
								 | 
							
								<li> 3 : Segment in back of plane, s2 closest
							 | 
						||
| 
								 | 
							
								<li> 4 : Segment collides plane, s1 in back
							 | 
						||
| 
								 | 
							
								<li> 5 : Segment collides plane, s2 in back
							 | 
						||
| 
								 | 
							
								</ul>
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template<typename CLASS_POINT,typename CLASS_PLANE>
							 | 
						||
| 
								 | 
							
								SIMD_FORCE_INLINE eLINE_PLANE_INTERSECTION_TYPE PLANE_CLIP_SEGMENT2(
							 | 
						||
| 
								 | 
							
									const CLASS_POINT& s1,
							 | 
						||
| 
								 | 
							
									const CLASS_POINT &s2,
							 | 
						||
| 
								 | 
							
									const CLASS_PLANE &plane,CLASS_POINT &clipped)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									GREAL _dis1 = DISTANCE_PLANE_POINT(plane,s1);
							 | 
						||
| 
								 | 
							
									GREAL _dis2 = DISTANCE_PLANE_POINT(plane,s2);
							 | 
						||
| 
								 | 
							
									if(_dis1 >-G_EPSILON && _dis2 >-G_EPSILON)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
									    if(_dis1<_dis2) return G_FRONT_PLANE_S1;
							 | 
						||
| 
								 | 
							
									    return G_FRONT_PLANE_S2;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else if(_dis1 <G_EPSILON && _dis2 <G_EPSILON)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
									    if(_dis1>_dis2) return G_BACK_PLANE_S1;
							 | 
						||
| 
								 | 
							
									    return G_BACK_PLANE_S2;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									VEC_DIFF(clipped,s2,s1);
							 | 
						||
| 
								 | 
							
									_dis2 = VEC_DOT(clipped,plane);
							 | 
						||
| 
								 | 
							
									VEC_SCALE(clipped,-_dis1/_dis2,clipped);
							 | 
						||
| 
								 | 
							
									VEC_SUM(clipped,clipped,s1);
							 | 
						||
| 
								 | 
							
									if(_dis1<_dis2) return G_COLLIDE_PLANE_S1;
							 | 
						||
| 
								 | 
							
									return G_COLLIDE_PLANE_S2;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//! Confirms if the plane intersect the edge or not
							 | 
						||
| 
								 | 
							
								/*!
							 | 
						||
| 
								 | 
							
								clipped1 and clipped2 are the vertices behind the plane.
							 | 
						||
| 
								 | 
							
								clipped1 is the closest
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								intersection_type must have the following values
							 | 
						||
| 
								 | 
							
								<ul>
							 | 
						||
| 
								 | 
							
								<li> 0 : Segment in front of plane, s1 closest
							 | 
						||
| 
								 | 
							
								<li> 1 : Segment in front of plane, s2 closest
							 | 
						||
| 
								 | 
							
								<li> 2 : Segment in back of plane, s1 closest
							 | 
						||
| 
								 | 
							
								<li> 3 : Segment in back of plane, s2 closest
							 | 
						||
| 
								 | 
							
								<li> 4 : Segment collides plane, s1 in back
							 | 
						||
| 
								 | 
							
								<li> 5 : Segment collides plane, s2 in back
							 | 
						||
| 
								 | 
							
								</ul>
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								template<typename CLASS_POINT,typename CLASS_PLANE>
							 | 
						||
| 
								 | 
							
								SIMD_FORCE_INLINE eLINE_PLANE_INTERSECTION_TYPE PLANE_CLIP_SEGMENT_CLOSEST(
							 | 
						||
| 
								 | 
							
									const CLASS_POINT& s1,
							 | 
						||
| 
								 | 
							
									const CLASS_POINT &s2,
							 | 
						||
| 
								 | 
							
									const CLASS_PLANE &plane,
							 | 
						||
| 
								 | 
							
									CLASS_POINT &clipped1,CLASS_POINT &clipped2)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									eLINE_PLANE_INTERSECTION_TYPE intersection_type = PLANE_CLIP_SEGMENT2(s1,s2,plane,clipped1);
							 | 
						||
| 
								 | 
							
									switch(intersection_type)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
									case G_FRONT_PLANE_S1:
							 | 
						||
| 
								 | 
							
										VEC_COPY(clipped1,s1);
							 | 
						||
| 
								 | 
							
									    VEC_COPY(clipped2,s2);
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case G_FRONT_PLANE_S2:
							 | 
						||
| 
								 | 
							
										VEC_COPY(clipped1,s2);
							 | 
						||
| 
								 | 
							
									    VEC_COPY(clipped2,s1);
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case G_BACK_PLANE_S1:
							 | 
						||
| 
								 | 
							
										VEC_COPY(clipped1,s1);
							 | 
						||
| 
								 | 
							
									    VEC_COPY(clipped2,s2);
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case G_BACK_PLANE_S2:
							 | 
						||
| 
								 | 
							
										VEC_COPY(clipped1,s2);
							 | 
						||
| 
								 | 
							
									    VEC_COPY(clipped2,s1);
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case G_COLLIDE_PLANE_S1:
							 | 
						||
| 
								 | 
							
										VEC_COPY(clipped2,s1);
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case G_COLLIDE_PLANE_S2:
							 | 
						||
| 
								 | 
							
										VEC_COPY(clipped2,s2);
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return intersection_type;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//! Finds the 2 smallest cartesian coordinates of a plane normal
							 | 
						||
| 
								 | 
							
								#define PLANE_MINOR_AXES(plane, i0, i1) VEC_MINOR_AXES(plane, i0, i1)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//! Ray plane collision in one way
							 | 
						||
| 
								 | 
							
								/*!
							 | 
						||
| 
								 | 
							
								Intersects plane in one way only. The ray must face the plane (normals must be in opossite directions).<br/>
							 | 
						||
| 
								 | 
							
								It uses the PLANEDIREPSILON constant.
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								template<typename T,typename CLASS_POINT,typename CLASS_PLANE>
							 | 
						||
| 
								 | 
							
								SIMD_FORCE_INLINE bool RAY_PLANE_COLLISION(
							 | 
						||
| 
								 | 
							
									const CLASS_PLANE & plane,
							 | 
						||
| 
								 | 
							
									const CLASS_POINT & vDir,
							 | 
						||
| 
								 | 
							
									const CLASS_POINT & vPoint,
							 | 
						||
| 
								 | 
							
									CLASS_POINT & pout,T &tparam)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									GREAL _dis,_dotdir;
							 | 
						||
| 
								 | 
							
									_dotdir = VEC_DOT(plane,vDir);
							 | 
						||
| 
								 | 
							
									if(_dotdir<PLANEDIREPSILON)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
									    return false;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									_dis = DISTANCE_PLANE_POINT(plane,vPoint);
							 | 
						||
| 
								 | 
							
									tparam = -_dis/_dotdir;
							 | 
						||
| 
								 | 
							
									VEC_SCALE(pout,tparam,vDir);
							 | 
						||
| 
								 | 
							
									VEC_SUM(pout,vPoint,pout);
							 | 
						||
| 
								 | 
							
									return true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//! line collision
							 | 
						||
| 
								 | 
							
								/*!
							 | 
						||
| 
								 | 
							
								*\return
							 | 
						||
| 
								 | 
							
									-0  if the ray never intersects
							 | 
						||
| 
								 | 
							
									-1 if the ray collides in front
							 | 
						||
| 
								 | 
							
									-2 if the ray collides in back
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								template<typename T,typename CLASS_POINT,typename CLASS_PLANE>
							 | 
						||
| 
								 | 
							
								SIMD_FORCE_INLINE GUINT LINE_PLANE_COLLISION(
							 | 
						||
| 
								 | 
							
									const CLASS_PLANE & plane,
							 | 
						||
| 
								 | 
							
									const CLASS_POINT & vDir,
							 | 
						||
| 
								 | 
							
									const CLASS_POINT & vPoint,
							 | 
						||
| 
								 | 
							
									CLASS_POINT & pout,
							 | 
						||
| 
								 | 
							
									T &tparam,
							 | 
						||
| 
								 | 
							
									T tmin, T tmax)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									GREAL _dis,_dotdir;
							 | 
						||
| 
								 | 
							
									_dotdir = VEC_DOT(plane,vDir);
							 | 
						||
| 
								 | 
							
									if(btFabs(_dotdir)<PLANEDIREPSILON)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										tparam = tmax;
							 | 
						||
| 
								 | 
							
									    return 0;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									_dis = DISTANCE_PLANE_POINT(plane,vPoint);
							 | 
						||
| 
								 | 
							
									char returnvalue = _dis<0.0f?2:1;
							 | 
						||
| 
								 | 
							
									tparam = -_dis/_dotdir;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if(tparam<tmin)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										returnvalue = 0;
							 | 
						||
| 
								 | 
							
										tparam = tmin;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else if(tparam>tmax)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										returnvalue = 0;
							 | 
						||
| 
								 | 
							
										tparam = tmax;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									VEC_SCALE(pout,tparam,vDir);
							 | 
						||
| 
								 | 
							
									VEC_SUM(pout,vPoint,pout);
							 | 
						||
| 
								 | 
							
									return returnvalue;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*! \brief Returns the Ray on which 2 planes intersect if they do.
							 | 
						||
| 
								 | 
							
								    Written by Rodrigo Hernandez on ODE convex collision
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  \param p1 Plane 1
							 | 
						||
| 
								 | 
							
								  \param p2 Plane 2
							 | 
						||
| 
								 | 
							
								  \param p Contains the origin of the ray upon returning if planes intersect
							 | 
						||
| 
								 | 
							
								  \param d Contains the direction of the ray upon returning if planes intersect
							 | 
						||
| 
								 | 
							
								  \return true if the planes intersect, 0 if paralell.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								template<typename CLASS_POINT,typename CLASS_PLANE>
							 | 
						||
| 
								 | 
							
								SIMD_FORCE_INLINE bool INTERSECT_PLANES(
							 | 
						||
| 
								 | 
							
										const CLASS_PLANE &p1,
							 | 
						||
| 
								 | 
							
										const CLASS_PLANE &p2,
							 | 
						||
| 
								 | 
							
										CLASS_POINT &p,
							 | 
						||
| 
								 | 
							
										CLASS_POINT &d)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									VEC_CROSS(d,p1,p2);
							 | 
						||
| 
								 | 
							
								  	GREAL denom = VEC_DOT(d, d);
							 | 
						||
| 
								 | 
							
								  	if(GIM_IS_ZERO(denom)) return false;
							 | 
						||
| 
								 | 
							
									vec3f _n;
							 | 
						||
| 
								 | 
							
									_n[0]=p1[3]*p2[0] - p2[3]*p1[0];
							 | 
						||
| 
								 | 
							
									_n[1]=p1[3]*p2[1] - p2[3]*p1[1];
							 | 
						||
| 
								 | 
							
									_n[2]=p1[3]*p2[2] - p2[3]*p1[2];
							 | 
						||
| 
								 | 
							
									VEC_CROSS(p,_n,d);
							 | 
						||
| 
								 | 
							
									p[0]/=denom;
							 | 
						||
| 
								 | 
							
									p[1]/=denom;
							 | 
						||
| 
								 | 
							
									p[2]/=denom;
							 | 
						||
| 
								 | 
							
									return true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//***************** SEGMENT and LINE FUNCTIONS **********************************///
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*! Finds the closest point(cp) to (v) on a segment (e1,e2)
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								template<typename CLASS_POINT>
							 | 
						||
| 
								 | 
							
								SIMD_FORCE_INLINE void CLOSEST_POINT_ON_SEGMENT(
							 | 
						||
| 
								 | 
							
									CLASS_POINT & cp, const CLASS_POINT & v,
							 | 
						||
| 
								 | 
							
									const CLASS_POINT &e1,const CLASS_POINT &e2)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    vec3f _n;
							 | 
						||
| 
								 | 
							
								    VEC_DIFF(_n,e2,e1);
							 | 
						||
| 
								 | 
							
								    VEC_DIFF(cp,v,e1);
							 | 
						||
| 
								 | 
							
									GREAL _scalar = VEC_DOT(cp, _n);
							 | 
						||
| 
								 | 
							
									_scalar/= VEC_DOT(_n, _n);
							 | 
						||
| 
								 | 
							
									if(_scalar <0.0f)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
									    VEC_COPY(cp,e1);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else if(_scalar >1.0f)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
									    VEC_COPY(cp,e2);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
								        VEC_SCALE(cp,_scalar,_n);
							 | 
						||
| 
								 | 
							
								        VEC_SUM(cp,cp,e1);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*! \brief Finds the line params where these lines intersect.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								\param dir1 Direction of line 1
							 | 
						||
| 
								 | 
							
								\param point1 Point of line 1
							 | 
						||
| 
								 | 
							
								\param dir2 Direction of line 2
							 | 
						||
| 
								 | 
							
								\param point2 Point of line 2
							 | 
						||
| 
								 | 
							
								\param t1 Result Parameter for line 1
							 | 
						||
| 
								 | 
							
								\param t2 Result Parameter for line 2
							 | 
						||
| 
								 | 
							
								\param dointersect  0  if the lines won't intersect, else 1
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								template<typename T,typename CLASS_POINT>
							 | 
						||
| 
								 | 
							
								SIMD_FORCE_INLINE bool LINE_INTERSECTION_PARAMS(
							 | 
						||
| 
								 | 
							
									const CLASS_POINT & dir1,
							 | 
						||
| 
								 | 
							
									CLASS_POINT & point1,
							 | 
						||
| 
								 | 
							
									const CLASS_POINT & dir2,
							 | 
						||
| 
								 | 
							
									CLASS_POINT &  point2,
							 | 
						||
| 
								 | 
							
									T& t1,T& t2)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    GREAL det;
							 | 
						||
| 
								 | 
							
									GREAL e1e1 = VEC_DOT(dir1,dir1);
							 | 
						||
| 
								 | 
							
									GREAL e1e2 = VEC_DOT(dir1,dir2);
							 | 
						||
| 
								 | 
							
									GREAL e2e2 = VEC_DOT(dir2,dir2);
							 | 
						||
| 
								 | 
							
									vec3f p1p2;
							 | 
						||
| 
								 | 
							
								    VEC_DIFF(p1p2,point1,point2);
							 | 
						||
| 
								 | 
							
								    GREAL p1p2e1 = VEC_DOT(p1p2,dir1);
							 | 
						||
| 
								 | 
							
									GREAL p1p2e2 = VEC_DOT(p1p2,dir2);
							 | 
						||
| 
								 | 
							
									det = e1e2*e1e2 - e1e1*e2e2;
							 | 
						||
| 
								 | 
							
									if(GIM_IS_ZERO(det)) return false;
							 | 
						||
| 
								 | 
							
									t1 = (e1e2*p1p2e2 - e2e2*p1p2e1)/det;
							 | 
						||
| 
								 | 
							
									t2 = (e1e1*p1p2e2 - e1e2*p1p2e1)/det;
							 | 
						||
| 
								 | 
							
									return true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//! Find closest points on segments
							 | 
						||
| 
								 | 
							
								template<typename CLASS_POINT>
							 | 
						||
| 
								 | 
							
								SIMD_FORCE_INLINE void SEGMENT_COLLISION(
							 | 
						||
| 
								 | 
							
									const CLASS_POINT & vA1,
							 | 
						||
| 
								 | 
							
									const CLASS_POINT & vA2,
							 | 
						||
| 
								 | 
							
									const CLASS_POINT & vB1,
							 | 
						||
| 
								 | 
							
									const CLASS_POINT & vB2,
							 | 
						||
| 
								 | 
							
									CLASS_POINT & vPointA,
							 | 
						||
| 
								 | 
							
									CLASS_POINT & vPointB)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    CLASS_POINT _AD,_BD,n;
							 | 
						||
| 
								 | 
							
								    vec4f _M;//plane
							 | 
						||
| 
								 | 
							
								    VEC_DIFF(_AD,vA2,vA1);
							 | 
						||
| 
								 | 
							
								    VEC_DIFF(_BD,vB2,vB1);
							 | 
						||
| 
								 | 
							
								    VEC_CROSS(n,_AD,_BD);
							 | 
						||
| 
								 | 
							
								    GREAL _tp = VEC_DOT(n,n);
							 | 
						||
| 
								 | 
							
								    if(_tp<G_EPSILON)//ARE PARALELE
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    	//project B over A
							 | 
						||
| 
								 | 
							
								    	bool invert_b_order = false;
							 | 
						||
| 
								 | 
							
								    	_M[0] = VEC_DOT(vB1,_AD);
							 | 
						||
| 
								 | 
							
								    	_M[1] = VEC_DOT(vB2,_AD);
							 | 
						||
| 
								 | 
							
								    	if(_M[0]>_M[1])
							 | 
						||
| 
								 | 
							
								    	{
							 | 
						||
| 
								 | 
							
								    		invert_b_order  = true;
							 | 
						||
| 
								 | 
							
								    		GIM_SWAP_NUMBERS(_M[0],_M[1]);
							 | 
						||
| 
								 | 
							
								    	}
							 | 
						||
| 
								 | 
							
								    	_M[2] = VEC_DOT(vA1,_AD);
							 | 
						||
| 
								 | 
							
								    	_M[3] = VEC_DOT(vA2,_AD);
							 | 
						||
| 
								 | 
							
								    	//mid points
							 | 
						||
| 
								 | 
							
								    	n[0] = (_M[0]+_M[1])*0.5f;
							 | 
						||
| 
								 | 
							
								    	n[1] = (_M[2]+_M[3])*0.5f;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    	if(n[0]<n[1])
							 | 
						||
| 
								 | 
							
								    	{
							 | 
						||
| 
								 | 
							
								    		if(_M[1]<_M[2])
							 | 
						||
| 
								 | 
							
								    		{
							 | 
						||
| 
								 | 
							
								    			vPointB = invert_b_order?vB1:vB2;
							 | 
						||
| 
								 | 
							
								    			vPointA = vA1;
							 | 
						||
| 
								 | 
							
								    		}
							 | 
						||
| 
								 | 
							
								    		else if(_M[1]<_M[3])
							 | 
						||
| 
								 | 
							
								    		{
							 | 
						||
| 
								 | 
							
								    			vPointB = invert_b_order?vB1:vB2;
							 | 
						||
| 
								 | 
							
								    			CLOSEST_POINT_ON_SEGMENT(vPointA,vPointB,vA1,vA2);
							 | 
						||
| 
								 | 
							
								    		}
							 | 
						||
| 
								 | 
							
								    		else
							 | 
						||
| 
								 | 
							
								    		{
							 | 
						||
| 
								 | 
							
								    			vPointA = vA2;
							 | 
						||
| 
								 | 
							
								    			CLOSEST_POINT_ON_SEGMENT(vPointB,vPointA,vB1,vB2);
							 | 
						||
| 
								 | 
							
								    		}
							 | 
						||
| 
								 | 
							
								    	}
							 | 
						||
| 
								 | 
							
								    	else
							 | 
						||
| 
								 | 
							
								    	{
							 | 
						||
| 
								 | 
							
								    		if(_M[3]<_M[0])
							 | 
						||
| 
								 | 
							
								    		{
							 | 
						||
| 
								 | 
							
								    			vPointB = invert_b_order?vB2:vB1;
							 | 
						||
| 
								 | 
							
								    			vPointA = vA2;
							 | 
						||
| 
								 | 
							
								    		}
							 | 
						||
| 
								 | 
							
								    		else if(_M[3]<_M[1])
							 | 
						||
| 
								 | 
							
								    		{
							 | 
						||
| 
								 | 
							
								    			vPointA = vA2;
							 | 
						||
| 
								 | 
							
								    			CLOSEST_POINT_ON_SEGMENT(vPointB,vPointA,vB1,vB2);
							 | 
						||
| 
								 | 
							
								    		}
							 | 
						||
| 
								 | 
							
								    		else
							 | 
						||
| 
								 | 
							
								    		{
							 | 
						||
| 
								 | 
							
								    			vPointB = invert_b_order?vB1:vB2;
							 | 
						||
| 
								 | 
							
								    			CLOSEST_POINT_ON_SEGMENT(vPointA,vPointB,vA1,vA2);
							 | 
						||
| 
								 | 
							
								    		}
							 | 
						||
| 
								 | 
							
								    	}
							 | 
						||
| 
								 | 
							
								    	return;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    VEC_CROSS(_M,n,_BD);
							 | 
						||
| 
								 | 
							
								    _M[3] = VEC_DOT(_M,vB1);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    LINE_PLANE_COLLISION(_M,_AD,vA1,vPointA,_tp,btScalar(0), btScalar(1));
							 | 
						||
| 
								 | 
							
								    /*Closest point on segment*/
							 | 
						||
| 
								 | 
							
								    VEC_DIFF(vPointB,vPointA,vB1);
							 | 
						||
| 
								 | 
							
									_tp = VEC_DOT(vPointB, _BD);
							 | 
						||
| 
								 | 
							
									_tp/= VEC_DOT(_BD, _BD);
							 | 
						||
| 
								 | 
							
									_tp = GIM_CLAMP(_tp,0.0f,1.0f);
							 | 
						||
| 
								 | 
							
								    VEC_SCALE(vPointB,_tp,_BD);
							 | 
						||
| 
								 | 
							
								    VEC_SUM(vPointB,vPointB,vB1);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//! Line box intersection in one dimension
							 | 
						||
| 
								 | 
							
								/*!
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								*\param pos Position of the ray
							 | 
						||
| 
								 | 
							
								*\param dir Projection of the Direction of the ray
							 | 
						||
| 
								 | 
							
								*\param bmin Minimum bound of the box
							 | 
						||
| 
								 | 
							
								*\param bmax Maximum bound of the box
							 | 
						||
| 
								 | 
							
								*\param tfirst the minimum projection. Assign to 0 at first.
							 | 
						||
| 
								 | 
							
								*\param tlast the maximum projection. Assign to INFINITY at first.
							 | 
						||
| 
								 | 
							
								*\return true if there is an intersection.
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								template<typename T>
							 | 
						||
| 
								 | 
							
								SIMD_FORCE_INLINE bool BOX_AXIS_INTERSECT(T pos, T dir,T bmin, T bmax, T & tfirst, T & tlast)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if(GIM_IS_ZERO(dir))
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
								        return !(pos < bmin || pos > bmax);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									GREAL a0 = (bmin - pos) / dir;
							 | 
						||
| 
								 | 
							
									GREAL a1 = (bmax - pos) / dir;
							 | 
						||
| 
								 | 
							
									if(a0 > a1)   GIM_SWAP_NUMBERS(a0, a1);
							 | 
						||
| 
								 | 
							
									tfirst = GIM_MAX(a0, tfirst);
							 | 
						||
| 
								 | 
							
									tlast = GIM_MIN(a1, tlast);
							 | 
						||
| 
								 | 
							
									if (tlast < tfirst) return false;
							 | 
						||
| 
								 | 
							
									return true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//! Sorts 3 componets
							 | 
						||
| 
								 | 
							
								template<typename T>
							 | 
						||
| 
								 | 
							
								SIMD_FORCE_INLINE void SORT_3_INDICES(
							 | 
						||
| 
								 | 
							
										const T * values,
							 | 
						||
| 
								 | 
							
										GUINT * order_indices)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									//get minimum
							 | 
						||
| 
								 | 
							
									order_indices[0] = values[0] < values[1] ? (values[0] < values[2] ? 0 : 2) : (values[1] < values[2] ? 1 : 2);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									//get second and third
							 | 
						||
| 
								 | 
							
									GUINT i0 = (order_indices[0] + 1)%3;
							 | 
						||
| 
								 | 
							
									GUINT i1 = (i0 + 1)%3;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if(values[i0] < values[i1])
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										order_indices[1] = i0;
							 | 
						||
| 
								 | 
							
										order_indices[2] = i1;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										order_indices[1] = i1;
							 | 
						||
| 
								 | 
							
										order_indices[2] = i0;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif // GIM_VECTOR_H_INCLUDED
							 |