1 #include "float_math.h"
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <assert.h>
6 #include <float.h>
7 #include <math.h>
8 
9 /*----------------------------------------------------------------------
10 		Copyright (c) 2004 Open Dynamics Framework Group
11 					www.physicstools.org
12 		All rights reserved.
13 
14 		Redistribution and use in source and binary forms, with or without modification, are permitted provided
15 		that the following conditions are met:
16 
17 		Redistributions of source code must retain the above copyright notice, this list of conditions
18 		and the following disclaimer.
19 
20 		Redistributions in binary form must reproduce the above copyright notice,
21 		this list of conditions and the following disclaimer in the documentation
22 		and/or other materials provided with the distribution.
23 
24 		Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
25 		be used to endorse or promote products derived from this software without specific prior written permission.
26 
27 		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
28 		INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29 		DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 		LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
32 		IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 -----------------------------------------------------------------------*/
35 
36 // http://codesuppository.blogspot.com
37 //
38 // mailto: jratcliff@infiniplex.net
39 //
40 // http://www.amillionpixels.us
41 //
42 
43 #include "splitplane.h"
44 #include "ConvexDecomposition.h"
45 #include "cd_vector.h"
46 #include "cd_hull.h"
47 #include "cd_wavefront.h"
48 #include "bestfit.h"
49 #include "planetri.h"
50 #include "vlookup.h"
51 #include "meshvolume.h"
52 
53 namespace ConvexDecomposition
54 {
computePlane(const float * A,const float * B,const float * C,float * plane)55 static void computePlane(const float *A, const float *B, const float *C, float *plane)
56 {
57 	float vx = (B[0] - C[0]);
58 	float vy = (B[1] - C[1]);
59 	float vz = (B[2] - C[2]);
60 
61 	float wx = (A[0] - B[0]);
62 	float wy = (A[1] - B[1]);
63 	float wz = (A[2] - B[2]);
64 
65 	float vw_x = vy * wz - vz * wy;
66 	float vw_y = vz * wx - vx * wz;
67 	float vw_z = vx * wy - vy * wx;
68 
69 	float mag = sqrtf((vw_x * vw_x) + (vw_y * vw_y) + (vw_z * vw_z));
70 
71 	if (mag < 0.000001f)
72 	{
73 		mag = 0;
74 	}
75 	else
76 	{
77 		mag = 1.0f / mag;
78 	}
79 
80 	float x = vw_x * mag;
81 	float y = vw_y * mag;
82 	float z = vw_z * mag;
83 
84 	float D = 0.0f - ((x * A[0]) + (y * A[1]) + (z * A[2]));
85 
86 	plane[0] = x;
87 	plane[1] = y;
88 	plane[2] = z;
89 	plane[3] = D;
90 }
91 
92 class Rect3d
93 {
94 public:
Rect3d(void)95 	Rect3d(void){};
96 
Rect3d(const float * bmin,const float * bmax)97 	Rect3d(const float *bmin, const float *bmax)
98 	{
99 		mMin[0] = bmin[0];
100 		mMin[1] = bmin[1];
101 		mMin[2] = bmin[2];
102 
103 		mMax[0] = bmax[0];
104 		mMax[1] = bmax[1];
105 		mMax[2] = bmax[2];
106 	}
107 
SetMin(const float * bmin)108 	void SetMin(const float *bmin)
109 	{
110 		mMin[0] = bmin[0];
111 		mMin[1] = bmin[1];
112 		mMin[2] = bmin[2];
113 	}
114 
SetMax(const float * bmax)115 	void SetMax(const float *bmax)
116 	{
117 		mMax[0] = bmax[0];
118 		mMax[1] = bmax[1];
119 		mMax[2] = bmax[2];
120 	}
121 
SetMin(float x,float y,float z)122 	void SetMin(float x, float y, float z)
123 	{
124 		mMin[0] = x;
125 		mMin[1] = y;
126 		mMin[2] = z;
127 	}
128 
SetMax(float x,float y,float z)129 	void SetMax(float x, float y, float z)
130 	{
131 		mMax[0] = x;
132 		mMax[1] = y;
133 		mMax[2] = z;
134 	}
135 
136 	float mMin[3];
137 	float mMax[3];
138 };
139 
splitRect(unsigned int axis,const Rect3d & source,Rect3d & b1,Rect3d & b2,const float * midpoint)140 void splitRect(unsigned int axis,
141 			   const Rect3d &source,
142 			   Rect3d &b1,
143 			   Rect3d &b2,
144 			   const float *midpoint)
145 {
146 	switch (axis)
147 	{
148 		case 0:
149 			b1.SetMin(source.mMin);
150 			b1.SetMax(midpoint[0], source.mMax[1], source.mMax[2]);
151 
152 			b2.SetMin(midpoint[0], source.mMin[1], source.mMin[2]);
153 			b2.SetMax(source.mMax);
154 
155 			break;
156 		case 1:
157 			b1.SetMin(source.mMin);
158 			b1.SetMax(source.mMax[0], midpoint[1], source.mMax[2]);
159 
160 			b2.SetMin(source.mMin[0], midpoint[1], source.mMin[2]);
161 			b2.SetMax(source.mMax);
162 
163 			break;
164 		case 2:
165 			b1.SetMin(source.mMin);
166 			b1.SetMax(source.mMax[0], source.mMax[1], midpoint[2]);
167 
168 			b2.SetMin(source.mMin[0], source.mMin[1], midpoint[2]);
169 			b2.SetMax(source.mMax);
170 
171 			break;
172 	}
173 }
174 
computeSplitPlane(unsigned int vcount,const float * vertices,unsigned int tcount,const unsigned int * indices,ConvexDecompInterface * callback,float * plane)175 bool computeSplitPlane(unsigned int vcount,
176 					   const float *vertices,
177 					   unsigned int tcount,
178 					   const unsigned int *indices,
179 					   ConvexDecompInterface *callback,
180 					   float *plane)
181 {
182 	float bmin[3] = {1e9, 1e9, 1e9};
183 	float bmax[3] = {-1e9, -1e9, -1e9};
184 
185 	for (unsigned int i = 0; i < vcount; i++)
186 	{
187 		const float *p = &vertices[i * 3];
188 
189 		if (p[0] < bmin[0]) bmin[0] = p[0];
190 		if (p[1] < bmin[1]) bmin[1] = p[1];
191 		if (p[2] < bmin[2]) bmin[2] = p[2];
192 
193 		if (p[0] > bmax[0]) bmax[0] = p[0];
194 		if (p[1] > bmax[1]) bmax[1] = p[1];
195 		if (p[2] > bmax[2]) bmax[2] = p[2];
196 	}
197 
198 	float dx = bmax[0] - bmin[0];
199 	float dy = bmax[1] - bmin[1];
200 	float dz = bmax[2] - bmin[2];
201 
202 	float laxis = dx;
203 
204 	unsigned int axis = 0;
205 
206 	if (dy > dx)
207 	{
208 		axis = 1;
209 		laxis = dy;
210 	}
211 
212 	if (dz > dx && dz > dy)
213 	{
214 		axis = 2;
215 		laxis = dz;
216 	}
217 
218 	float p1[3];
219 	float p2[3];
220 	float p3[3];
221 
222 	p3[0] = p2[0] = p1[0] = bmin[0] + dx * 0.5f;
223 	p3[1] = p2[1] = p1[1] = bmin[1] + dy * 0.5f;
224 	p3[2] = p2[2] = p1[2] = bmin[2] + dz * 0.5f;
225 
226 	Rect3d b(bmin, bmax);
227 
228 	Rect3d b1, b2;
229 
230 	splitRect(axis, b, b1, b2, p1);
231 
232 	//  callback->ConvexDebugBound(b1.mMin,b1.mMax,0x00FF00);
233 	//  callback->ConvexDebugBound(b2.mMin,b2.mMax,0xFFFF00);
234 
235 	switch (axis)
236 	{
237 		case 0:
238 			p2[1] = bmin[1];
239 			p2[2] = bmin[2];
240 
241 			if (dz > dy)
242 			{
243 				p3[1] = bmax[1];
244 				p3[2] = bmin[2];
245 			}
246 			else
247 			{
248 				p3[1] = bmin[1];
249 				p3[2] = bmax[2];
250 			}
251 
252 			break;
253 		case 1:
254 			p2[0] = bmin[0];
255 			p2[2] = bmin[2];
256 
257 			if (dx > dz)
258 			{
259 				p3[0] = bmax[0];
260 				p3[2] = bmin[2];
261 			}
262 			else
263 			{
264 				p3[0] = bmin[0];
265 				p3[2] = bmax[2];
266 			}
267 
268 			break;
269 		case 2:
270 			p2[0] = bmin[0];
271 			p2[1] = bmin[1];
272 
273 			if (dx > dy)
274 			{
275 				p3[0] = bmax[0];
276 				p3[1] = bmin[1];
277 			}
278 			else
279 			{
280 				p3[0] = bmin[0];
281 				p3[1] = bmax[1];
282 			}
283 
284 			break;
285 	}
286 
287 	//  callback->ConvexDebugTri(p1,p2,p3,0xFF0000);
288 
289 	computePlane(p1, p2, p3, plane);
290 
291 	return true;
292 }
293 
294 }  // namespace ConvexDecomposition
295