final cleanup removal of the old convexDecomp library
ADDDED: library for the floatmath from v-hacd resource, required for fit sphere/capsule/box functions
- virtual bool cancelCompute(void) // cause background thread computation to abort early. Will return no results. Use 'isComputeComplete' to confirm the thread is done.
- virtual bool addTriangle(const NxF32 *p1,const NxF32 *p2,const NxF32 *p3) = 0; // add the input mesh one triangle at a time.
-
- virtual NxU32 computeConvexDecomposition(NxF32 skinWidth=0, // Skin width on the convex hulls generated
- NxU32 decompositionDepth=8, // recursion depth for convex decomposition.
- NxU32 maxHullVertices=64, // maximum number of vertices in output convex hulls.
- NxF32 concavityThresholdPercent=0.1f, // The percentage of concavity allowed without causing a split to occur.
- NxF32 mergeThresholdPercent=30.0f, // The percentage of volume difference allowed to merge two convex hulls.
- NxF32 volumeSplitThresholdPercent=0.1f, // The percentage of the total volume of the object above which splits will still occur.
- bool useInitialIslandGeneration=true, // whether or not to perform initial island generation on the input mesh.
- bool useIslandGeneration=false, // Whether or not to perform island generation at each split. Currently disabled due to bug in RemoveTjunctions
- bool useBackgroundThread=true) = 0; // Whether or not to compute the convex decomposition in a background thread, the default is true.
-
- virtual bool isComputeComplete(void) = 0; // if building the convex hulls in a background thread, this returns true if it is complete.
-
- virtual bool cancelCompute(void) = 0; // cause background thread computation to abort early. Will return no results. Use 'isComputeComplete' to confirm the thread is done.
-
-
- virtual NxU32 getHullCount(void) = 0; // returns the number of convex hulls produced.
-bool fm_colinear(const NxF32 a1[3],const NxF32 a2[3],const NxF32 b1[3],const NxF32 b2[3],NxF32 epsilon=0.999f); // true if these two line segments are co-linear.
-bool fm_colinear(const NxF64 a1[3],const NxF64 a2[3],const NxF64 b1[3],const NxF64 b2[3],NxF64 epsilon=0.999); // true if these two line segments are co-linear.
-bool fm_isMeshCoplanar(NxU32 tcount,const NxU32 *indices,const NxF32 *vertices,bool doubleSided); // returns true if this collection of indexed triangles are co-planar!
-bool fm_isMeshCoplanar(NxU32 tcount,const NxU32 *indices,const NxF64 *vertices,bool doubleSided); // returns true if this collection of indexed triangles are co-planar!
-
-bool fm_samePlane(const NxF32 p1[4],const NxF32 p2[4],NxF32 normalEpsilon=0.01f,NxF32 dEpsilon=0.001f,bool doubleSided=false); // returns true if these two plane equations are identical within an epsilon
-bool fm_insideAABB(const REAL *obmin,const REAL *obmax,const REAL *tbmin,const REAL *tbmax) // test if bounding box tbmin/tmbax is fully inside obmin/obmax
-{
- bool ret = false;
-
- if ( tbmax[0] <= obmax[0] &&
- tbmax[1] <= obmax[1] &&
- tbmax[2] <= obmax[2] &&
- tbmin[0] >= obmin[0] &&
- tbmin[1] >= obmin[1] &&
- tbmin[2] >= obmin[2] ) ret = true;
-
- return ret;
-}
-
-
-// Reference, from Stan Melax in Game Gems I
-// Quaternion q;
-// vector3 c = CrossProduct(v0,v1);
-// REAL d = DotProduct(v0,v1);
-// REAL s = (REAL)sqrt((1+d)*2);
-// q.x = c.x / s;
-// q.y = c.y / s;
-// q.z = c.z / s;
-// q.w = s /2.0f;
-// return q;
-void fm_rotationArc(const REAL *v0,const REAL *v1,REAL *quat)
-{
- REAL cross[3];
-
- fm_cross(cross,v0,v1);
- REAL d = fm_dot(v0,v1);
- REAL s = sqrt((1+d)*2);
- REAL recip = 1.0f / s;
-
- quat[0] = cross[0] * recip;
- quat[1] = cross[1] * recip;
- quat[2] = cross[2] * recip;
- quat[3] = s * 0.5f;
-
-}
-
-
-REAL fm_distancePointLineSegment(const REAL *Point,const REAL *LineStart,const REAL *LineEnd,REAL *intersection,LineSegmentType &type,REAL epsilon)
-{
- REAL ret;
-
- REAL LineMag = fm_distance( LineEnd, LineStart );
-bool fm_isMeshCoplanar(NxU32 tcount,const NxU32 *indices,const REAL *vertices,bool doubleSided) // returns true if this collection of indexed triangles are co-planar!
-{
- bool ret = true;
-
- if ( tcount > 0 )
- {
- NxU32 i1 = indices[0];
- NxU32 i2 = indices[1];
- NxU32 i3 = indices[2];
- const REAL *p1 = &vertices[i1*3];
- const REAL *p2 = &vertices[i2*3];
- const REAL *p3 = &vertices[i3*3];
- REAL plane[4];
- plane[3] = fm_computePlane(p1,p2,p3,plane);
- const NxU32 *scan = &indices[3];
- for (NxU32 i=1; i<tcount; i++)
- {
- i1 = *scan++;
- i2 = *scan++;
- i3 = *scan++;
- p1 = &vertices[i1*3];
- p2 = &vertices[i2*3];
- p3 = &vertices[i3*3];
- REAL _plane[4];
- _plane[3] = fm_computePlane(p1,p2,p3,_plane);
- if ( !fm_samePlane(plane,_plane,0.01f,0.001f,doubleSided) )
- {
- ret = false;
- break;
- }
- }
- }
- return ret;
-}
-
-
-bool fm_samePlane(const REAL p1[4],const REAL p2[4],REAL normalEpsilon,REAL dEpsilon,bool doubleSided)
-{
- bool ret = false;
-
- REAL diff = (REAL) fabs(p1[3]-p2[3]);
- if ( diff < dEpsilon ) // if the plane -d co-efficient is within our epsilon
- {
- REAL dot = fm_dot(p1,p2); // compute the dot-product of the vector normals.
- if ( doubleSided ) dot = (REAL)fabs(dot);
- REAL dmin = 1 - normalEpsilon;
- REAL dmax = 1 + normalEpsilon;
- if ( dot >= dmin && dot <= dmax )
- {
- ret = true; // then the plane equation is for practical purposes identical.
- // Triangulation happens in 2d. We could inverse transform the polygon around the normal direction, or we just use the two most signficant axes
- // Here we find the two longest axes and use them to triangulate. Inverse transforming them would introduce more doubleing point error and isn't worth it.
-NvRayCast.cpp : A code snippet to cast a ray against a triangle mesh. This implementation does not use any acceleration data structures. That is a 'to do' item.
-NvRayCast.h : A code snippet to cast a ray against a triangle mesh. This implementation does not use any acceleration data structures. That is a 'to do' item.
-** copies of the Software, and to permit persons to whom the Software is furnished
-** to do so, subject to the following conditions:
-**
-** The above copyright notice and this permission notice shall be included in all
-** copies or substantial portions of the Software.
-
-** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-** WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-*/
-
-namespace CONVEX_DECOMPOSITION
-{
-
-class RemoveTjunctionsDesc
-{
-public:
- RemoveTjunctionsDesc(void)
- {
- mVcount = 0;
- mVertices = 0;
- mTcount = 0;
- mIndices = 0;
- mIds = 0;
- mTcountOut = 0;
- mIndicesOut = 0;
- mIdsOut = 0;
- mEpsilon = 0.00000001f;
- }
-
-// input
- NxF32 mEpsilon;
- NxF32 mDistanceEpsilon;
- NxU32 mVcount; // input vertice count.
- const NxF32 *mVertices; // input vertices as NxF32s or...
- NxU32 mTcount; // number of input triangles.
- const NxU32 *mIndices; // triangle indices.
- const NxU32 *mIds; // optional triangle Id numbers.
-// output..
- NxU32 mTcountOut; // number of output triangles.
- const NxU32 *mIndicesOut; // output triangle indices
- const NxU32 *mIdsOut; // output retained id numbers.
-};
-
-// Removes t-junctions from an input mesh. Does not generate any new data points, but may possible produce additional triangles and new indices.
-class RemoveTjunctions
-{
-public:
-
- virtual NxU32 removeTjunctions(RemoveTjunctionsDesc &desc) =0; // returns number of triangles output and the descriptor is filled with the appropriate results.
- tris.count = 0; //bad place to do the tris.SetSize(0) fix, this line is executed many times, and will result in a whole lot of allocations if the array is totally cleared here
-NxU32 WavefrontObj::loadObj(const char *fname, bool textured) // load a wavefront obj returns number of triangles that were loaded. Data is persists until the class is destructed.
-** copies of the Software, and to permit persons to whom the Software is furnished
-** to do so, subject to the following conditions:
-**
-** The above copyright notice and this permission notice shall be included in all
-** copies or substantial portions of the Software.
-
-** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-** WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-*/
-
-#include "NvUserMemAlloc.h"
-
-class WavefrontObj
-{
-public:
-
- WavefrontObj(void);
- ~WavefrontObj(void);
-
- NxU32 loadObj(const char *fname, bool textured); // load a wavefront obj returns number of triangles that were loaded. Data is persists until the class is destructed.
+bool fm_colinear(const float a1[3],const float a2[3],const float b1[3],const float b2[3],float epsilon=0.999f); // true if these two line segments are co-linear.
+bool fm_colinear(const double a1[3],const double a2[3],const double b1[3],const double b2[3],double epsilon=0.999); // true if these two line segments are co-linear.
+bool fm_isMeshCoplanar(uint32_t tcount,const uint32_t *indices,const float *vertices,bool doubleSided); // returns true if this collection of indexed triangles are co-planar!
+bool fm_isMeshCoplanar(uint32_t tcount,const uint32_t *indices,const double *vertices,bool doubleSided); // returns true if this collection of indexed triangles are co-planar!
+
+bool fm_samePlane(const float p1[4],const float p2[4],float normalEpsilon=0.01f,float dEpsilon=0.001f,bool doubleSided=false); // returns true if these two plane equations are identical within an epsilon
+bool fm_insideAABB(const REAL *obmin,const REAL *obmax,const REAL *tbmin,const REAL *tbmax) // test if bounding box tbmin/tmbax is fully inside obmin/obmax
+{
+ bool ret = false;
+
+ if ( tbmax[0] <= obmax[0] &&
+ tbmax[1] <= obmax[1] &&
+ tbmax[2] <= obmax[2] &&
+ tbmin[0] >= obmin[0] &&
+ tbmin[1] >= obmin[1] &&
+ tbmin[2] >= obmin[2] ) ret = true;
+
+ return ret;
+}
+
+
+// Reference, from Stan Melax in Game Gems I
+// Quaternion q;
+// vector3 c = CrossProduct(v0,v1);
+// REAL d = DotProduct(v0,v1);
+// REAL s = (REAL)sqrt((1+d)*2);
+// q.x = c.x / s;
+// q.y = c.y / s;
+// q.z = c.z / s;
+// q.w = s /2.0f;
+// return q;
+void fm_rotationArc(const REAL *v0,const REAL *v1,REAL *quat)
+bool fm_isMeshCoplanar(uint32_t tcount,const uint32_t *indices,const REAL *vertices,bool doubleSided) // returns true if this collection of indexed triangles are co-planar!
+{
+ bool ret = true;
+
+ if ( tcount > 0 )
+ {
+ uint32_t i1 = indices[0];
+ uint32_t i2 = indices[1];
+ uint32_t i3 = indices[2];
+ const REAL *p1 = &vertices[i1*3];
+ const REAL *p2 = &vertices[i2*3];
+ const REAL *p3 = &vertices[i3*3];
+ REAL plane[4];
+ plane[3] = fm_computePlane(p1,p2,p3,plane);
+ const uint32_t *scan = &indices[3];
+ for (uint32_t i=1; i<tcount; i++)
+ {
+ i1 = *scan++;
+ i2 = *scan++;
+ i3 = *scan++;
+ p1 = &vertices[i1*3];
+ p2 = &vertices[i2*3];
+ p3 = &vertices[i3*3];
+ REAL _plane[4];
+ _plane[3] = fm_computePlane(p1,p2,p3,_plane);
+ if ( !fm_samePlane(plane,_plane,0.01f,0.001f,doubleSided) )
+ {
+ ret = false;
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
+
+bool fm_samePlane(const REAL p1[4],const REAL p2[4],REAL normalEpsilon,REAL dEpsilon,bool doubleSided)
+{
+ bool ret = false;
+
+#if 0
+ if (p1[0] == p2[0] &&
+ p1[1] == p2[1] &&
+ p1[2] == p2[2] &&
+ p1[3] == p2[3])
+ {
+ ret = true;
+ }
+#else
+ REAL diff = (REAL) fabs(p1[3]-p2[3]);
+ if ( diff < dEpsilon ) // if the plane -d co-efficient is within our epsilon
+ {
+ REAL dot = fm_dot(p1,p2); // compute the dot-product of the vector normals.
+ if ( doubleSided ) dot = (REAL)fabs(dot);
+ REAL dmin = 1 - normalEpsilon;
+ REAL dmax = 1 + normalEpsilon;
+ if ( dot >= dmin && dot <= dmax )
+ {
+ ret = true; // then the plane equation is for practical purposes identical.
+ }
+ }
+#endif
+ return ret;
+}
+
+
+void fm_initMinMax(REAL bmin[3],REAL bmax[3])
+{
+ bmin[0] = FLT_MAX;
+ bmin[1] = FLT_MAX;
+ bmin[2] = FLT_MAX;
+
+ bmax[0] = -FLT_MAX;
+ bmax[1] = -FLT_MAX;
+ bmax[2] = -FLT_MAX;
+}
+
+void fm_inflateMinMax(REAL bmin[3], REAL bmax[3], REAL ratio)
+{
+ REAL inflate = fm_distance(bmin, bmax)*0.5f*ratio;
+ // Triangulation happens in 2d. We could inverse transform the polygon around the normal direction, or we just use the two most significant axes
+ // Here we find the two longest axes and use them to triangulate. Inverse transforming them would introduce more doubling point error and isn't worth it.