1 #ifndef GIM_CLIP_POLYGON_H_INCLUDED
2 #define GIM_CLIP_POLYGON_H_INCLUDED
3 
4 /*! \file gim_tri_collision.h
5 \author Francisco Leon Najera
6 */
7 /*
8 -----------------------------------------------------------------------------
9 This source file is part of GIMPACT Library.
10 
11 For the latest info, see http://gimpact.sourceforge.net/
12 
13 Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
14 email: projectileman@yahoo.com
15 
16  This library is free software; you can redistribute it and/or
17  modify it under the terms of EITHER:
18    (1) The GNU Lesser General Public License as published by the Free
19        Software Foundation; either version 2.1 of the License, or (at
20        your option) any later version. The text of the GNU Lesser
21        General Public License is included with this library in the
22        file GIMPACT-LICENSE-LGPL.TXT.
23    (2) The BSD-style license that is included with this library in
24        the file GIMPACT-LICENSE-BSD.TXT.
25    (3) The zlib/libpng license that is included with this library in
26        the file GIMPACT-LICENSE-ZLIB.TXT.
27 
28  This library is distributed in the hope that it will be useful,
29  but WITHOUT ANY WARRANTY; without even the implied warranty of
30  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
31  GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
32 
33 -----------------------------------------------------------------------------
34 */
35 
36 //! This function calcs the distance from a 3D plane
37 class DISTANCE_PLANE_3D_FUNC
38 {
39 public:
40 	template <typename CLASS_POINT, typename CLASS_PLANE>
operator()41 	inline GREAL operator()(const CLASS_PLANE& plane, const CLASS_POINT& point)
42 	{
43 		return DISTANCE_PLANE_POINT(plane, point);
44 	}
45 };
46 
47 template <typename CLASS_POINT>
PLANE_CLIP_POLYGON_COLLECT(const CLASS_POINT & point0,const CLASS_POINT & point1,GREAL dist0,GREAL dist1,CLASS_POINT * clipped,GUINT & clipped_count)48 SIMD_FORCE_INLINE void PLANE_CLIP_POLYGON_COLLECT(
49 	const CLASS_POINT& point0,
50 	const CLASS_POINT& point1,
51 	GREAL dist0,
52 	GREAL dist1,
53 	CLASS_POINT* clipped,
54 	GUINT& clipped_count)
55 {
56 	GUINT _prevclassif = (dist0 > G_EPSILON);
57 	GUINT _classif = (dist1 > G_EPSILON);
58 	if (_classif != _prevclassif)
59 	{
60 		GREAL blendfactor = -dist0 / (dist1 - dist0);
61 		VEC_BLEND(clipped[clipped_count], point0, point1, blendfactor);
62 		clipped_count++;
63 	}
64 	if (!_classif)
65 	{
66 		VEC_COPY(clipped[clipped_count], point1);
67 		clipped_count++;
68 	}
69 }
70 
71 //! Clips a polygon by a plane
72 /*!
73 *\return The count of the clipped counts
74 */
75 template <typename CLASS_POINT, typename CLASS_PLANE, typename DISTANCE_PLANE_FUNC>
PLANE_CLIP_POLYGON_GENERIC(const CLASS_PLANE & plane,const CLASS_POINT * polygon_points,GUINT polygon_point_count,CLASS_POINT * clipped,DISTANCE_PLANE_FUNC distance_func)76 SIMD_FORCE_INLINE GUINT PLANE_CLIP_POLYGON_GENERIC(
77 	const CLASS_PLANE& plane,
78 	const CLASS_POINT* polygon_points,
79 	GUINT polygon_point_count,
80 	CLASS_POINT* clipped, DISTANCE_PLANE_FUNC distance_func)
81 {
82 	GUINT clipped_count = 0;
83 
84 	//clip first point
85 	GREAL firstdist = distance_func(plane, polygon_points[0]);
86 	;
87 	if (!(firstdist > G_EPSILON))
88 	{
89 		VEC_COPY(clipped[clipped_count], polygon_points[0]);
90 		clipped_count++;
91 	}
92 
93 	GREAL olddist = firstdist;
94 	for (GUINT _i = 1; _i < polygon_point_count; _i++)
95 	{
96 		GREAL dist = distance_func(plane, polygon_points[_i]);
97 
98 		PLANE_CLIP_POLYGON_COLLECT(
99 			polygon_points[_i - 1], polygon_points[_i],
100 			olddist,
101 			dist,
102 			clipped,
103 			clipped_count);
104 
105 		olddist = dist;
106 	}
107 
108 	//RETURN TO FIRST  point
109 
110 	PLANE_CLIP_POLYGON_COLLECT(
111 		polygon_points[polygon_point_count - 1], polygon_points[0],
112 		olddist,
113 		firstdist,
114 		clipped,
115 		clipped_count);
116 
117 	return clipped_count;
118 }
119 
120 //! Clips a polygon by a plane
121 /*!
122 *\return The count of the clipped counts
123 */
124 template <typename CLASS_POINT, typename CLASS_PLANE, typename DISTANCE_PLANE_FUNC>
PLANE_CLIP_TRIANGLE_GENERIC(const CLASS_PLANE & plane,const CLASS_POINT & point0,const CLASS_POINT & point1,const CLASS_POINT & point2,CLASS_POINT * clipped,DISTANCE_PLANE_FUNC distance_func)125 SIMD_FORCE_INLINE GUINT PLANE_CLIP_TRIANGLE_GENERIC(
126 	const CLASS_PLANE& plane,
127 	const CLASS_POINT& point0,
128 	const CLASS_POINT& point1,
129 	const CLASS_POINT& point2,
130 	CLASS_POINT* clipped, DISTANCE_PLANE_FUNC distance_func)
131 {
132 	GUINT clipped_count = 0;
133 
134 	//clip first point
135 	GREAL firstdist = distance_func(plane, point0);
136 	;
137 	if (!(firstdist > G_EPSILON))
138 	{
139 		VEC_COPY(clipped[clipped_count], point0);
140 		clipped_count++;
141 	}
142 
143 	// point 1
144 	GREAL olddist = firstdist;
145 	GREAL dist = distance_func(plane, point1);
146 
147 	PLANE_CLIP_POLYGON_COLLECT(
148 		point0, point1,
149 		olddist,
150 		dist,
151 		clipped,
152 		clipped_count);
153 
154 	olddist = dist;
155 
156 	// point 2
157 	dist = distance_func(plane, point2);
158 
159 	PLANE_CLIP_POLYGON_COLLECT(
160 		point1, point2,
161 		olddist,
162 		dist,
163 		clipped,
164 		clipped_count);
165 	olddist = dist;
166 
167 	//RETURN TO FIRST  point
168 	PLANE_CLIP_POLYGON_COLLECT(
169 		point2, point0,
170 		olddist,
171 		firstdist,
172 		clipped,
173 		clipped_count);
174 
175 	return clipped_count;
176 }
177 
178 template <typename CLASS_POINT, typename CLASS_PLANE>
PLANE_CLIP_POLYGON3D(const CLASS_PLANE & plane,const CLASS_POINT * polygon_points,GUINT polygon_point_count,CLASS_POINT * clipped)179 SIMD_FORCE_INLINE GUINT PLANE_CLIP_POLYGON3D(
180 	const CLASS_PLANE& plane,
181 	const CLASS_POINT* polygon_points,
182 	GUINT polygon_point_count,
183 	CLASS_POINT* clipped)
184 {
185 	return PLANE_CLIP_POLYGON_GENERIC<CLASS_POINT, CLASS_PLANE>(plane, polygon_points, polygon_point_count, clipped, DISTANCE_PLANE_3D_FUNC());
186 }
187 
188 template <typename CLASS_POINT, typename CLASS_PLANE>
PLANE_CLIP_TRIANGLE3D(const CLASS_PLANE & plane,const CLASS_POINT & point0,const CLASS_POINT & point1,const CLASS_POINT & point2,CLASS_POINT * clipped)189 SIMD_FORCE_INLINE GUINT PLANE_CLIP_TRIANGLE3D(
190 	const CLASS_PLANE& plane,
191 	const CLASS_POINT& point0,
192 	const CLASS_POINT& point1,
193 	const CLASS_POINT& point2,
194 	CLASS_POINT* clipped)
195 {
196 	return PLANE_CLIP_TRIANGLE_GENERIC<CLASS_POINT, CLASS_PLANE>(plane, point0, point1, point2, clipped, DISTANCE_PLANE_3D_FUNC());
197 }
198 
199 #endif  // GIM_TRI_COLLISION_H_INCLUDED
200