00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "triboxoverlap.h"
00038
00039 #include <cmath>
00040
00041 using namespace sheep;
00042 using namespace toxic;
00043
00044 #define FINDMINMAX(x0, x1, x2, min, max) \
00045 min = max = x0; \
00046 if(x1 < min) min = x1; \
00047 if(x1 > max) max = x1; \
00048 if(x2 < min) min = x2; \
00049 if(x2 > max) max = x2;
00050
00051 namespace {
00052 bool plane_box_overlap(const Vector3 &normal, Real d, const Vector3 &maxbox) {
00053 Vector3 vmin, vmax;
00054
00055 if(normal.m_x > 0.0) {
00056 vmin.m_x = -maxbox.m_x;
00057 vmax.m_x = maxbox.m_x;
00058 } else {
00059 vmin.m_x = maxbox.m_x;
00060 vmax.m_x = -maxbox.m_x;
00061 }
00062
00063 if(normal.m_y > 0.0) {
00064 vmin.m_y = -maxbox.m_y;
00065 vmax.m_y = maxbox.m_y;
00066 } else {
00067 vmin.m_y = maxbox.m_y;
00068 vmax.m_y = -maxbox.m_y;
00069 }
00070
00071 if(normal.m_z > 0.0) {
00072 vmin.m_z = -maxbox.m_z;
00073 vmax.m_z = maxbox.m_z;
00074 } else {
00075 vmin.m_z = maxbox.m_z;
00076 vmax.m_z = -maxbox.m_z;
00077 }
00078
00079 if(normal * vmin + d > 0.0) return false;
00080 if(normal * vmax + d >= 0.0) return true;
00081
00082 return false;
00083 }
00084 }
00085
00086
00087
00088 #define AXISTEST_X01(a, b, fa, fb) \
00089 p0 = a * v0.m_y - b * v0.m_z; \
00090 p2 = a * v2.m_y - b * v2.m_z; \
00091 if(p0 < p2) { min = p0; max = p2; } else { min = p2; max = p0; } \
00092 rad = fa * boxhalfsize.m_y + fb * boxhalfsize.m_z; \
00093 if(min > rad || max < -rad) return false;
00094
00095 #define AXISTEST_X2(a, b, fa, fb) \
00096 p0 = a * v0.m_y - b * v0.m_z; \
00097 p1 = a * v1.m_y - b * v1.m_z; \
00098 if(p0 < p1) { min = p0; max = p1; } else { min = p1; max = p0; } \
00099 rad = fa * boxhalfsize.m_y + fb * boxhalfsize.m_z; \
00100 if(min > rad || max < -rad) return false;
00101
00102
00103
00104 #define AXISTEST_Y02(a, b, fa, fb) \
00105 p0 = -a * v0.m_x + b * v0.m_z; \
00106 p2 = -a * v2.m_x + b * v2.m_z; \
00107 if(p0 < p2) { min = p0; max = p2; } else { min = p2; max = p0; } \
00108 rad = fa * boxhalfsize.m_x + fb * boxhalfsize.m_z; \
00109 if(min > rad || max < -rad) return false;
00110
00111 #define AXISTEST_Y1(a, b, fa, fb) \
00112 p0 = -a * v0.m_x + b * v0.m_z; \
00113 p1 = -a * v1.m_x + b * v1.m_z; \
00114 if(p0 < p1) { min = p0; max = p1; } else { min = p1; max = p0; } \
00115 rad = fa * boxhalfsize.m_x + fb * boxhalfsize.m_z; \
00116 if(min > rad || max < -rad) return false;
00117
00118
00119
00120 #define AXISTEST_Z12(a, b, fa, fb) \
00121 p1 = a * v1.m_x - b * v1.m_y; \
00122 p2 = a * v2.m_x - b * v2.m_y; \
00123 if(p2 < p1) { min = p2; max = p1; } else { min = p1; max = p2; } \
00124 rad = fa * boxhalfsize.m_x + fb * boxhalfsize.m_y; \
00125 if(min > rad || max < -rad) return false;
00126
00127 #define AXISTEST_Z0(a, b, fa, fb) \
00128 p0 = a * v0.m_x - b * v0.m_y; \
00129 p1 = a * v1.m_x - b * v1.m_y; \
00130 if(p0 < p1) { min = p0; max = p1; } else { min = p1; max = p0; } \
00131 rad = fa * boxhalfsize.m_x + fb * boxhalfsize.m_y; \
00132 if(min > rad || max < -rad) return false;
00133
00134 bool toxic::tri_box_overlap(const Point3 &boxcenter,
00135 const Vector3 &boxhalfsize,
00136 const Point3 &vert0,
00137 const Point3 &vert1,
00138 const Point3 &vert2)
00139 {
00140
00141
00142
00143
00144
00145
00146
00147 Real min, max, p0, p1, p2, rad, fex, fey, fez;
00148
00149
00150
00151 const Vector3 v0 = vert0 - boxcenter;
00152 const Vector3 v1 = vert1 - boxcenter;
00153 const Vector3 v2 = vert2 - boxcenter;
00154
00155
00156 const Vector3 e0 = v1 - v0;
00157 const Vector3 e1 = v2 - v1;
00158 const Vector3 e2 = v0 - v2;
00159
00160
00161
00162 fex = fabs(e0.m_x);
00163 fey = fabs(e0.m_y);
00164 fez = fabs(e0.m_z);
00165 AXISTEST_X01(e0.m_z, e0.m_y, fez, fey);
00166 AXISTEST_Y02(e0.m_z, e0.m_x, fez, fex);
00167 AXISTEST_Z12(e0.m_y, e0.m_x, fey, fex);
00168
00169 fex = fabs(e1.m_x);
00170 fey = fabs(e1.m_y);
00171 fez = fabs(e1.m_z);
00172 AXISTEST_X01(e1.m_z, e1.m_y, fez, fey);
00173 AXISTEST_Y02(e1.m_z, e1.m_x, fez, fex);
00174 AXISTEST_Z0(e1.m_y, e1.m_x, fey, fex);
00175
00176 fex = fabs(e2.m_x);
00177 fey = fabs(e2.m_y);
00178 fez = fabs(e2.m_z);
00179 AXISTEST_X2(e2.m_z, e2.m_y, fez, fey);
00180 AXISTEST_Y1(e2.m_z, e2.m_x, fez, fex);
00181 AXISTEST_Z12(e2.m_y, e2.m_x, fey, fex);
00182
00183
00184
00185
00186
00187
00188
00189
00190 FINDMINMAX(v0.m_x, v1.m_x, v2.m_x, min, max);
00191 if(min > boxhalfsize.m_x || max < -boxhalfsize.m_x)
00192 return false;
00193
00194
00195 FINDMINMAX(v0.m_y, v1.m_y, v2.m_y, min, max);
00196 if(min > boxhalfsize.m_y || max < -boxhalfsize.m_y)
00197 return false;
00198
00199
00200 FINDMINMAX(v0.m_z, v1.m_z, v2.m_z, min, max);
00201 if(min > boxhalfsize.m_z || max < -boxhalfsize.m_z)
00202 return false;
00203
00204
00205
00206
00207 const Vector3 normal = e0 ^ e1;
00208 const Real d = -(normal * v0);
00209 if(!plane_box_overlap(normal, d, boxhalfsize))
00210 return false;
00211
00212 return true;
00213 }