Initial commit
This commit is contained in:
@@ -0,0 +1,556 @@
|
||||
/* Copyright (c) <2003-2011> <Julio Jerez, Newton Game Dynamics>
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "dgMeshEffectSolidTree.h"
|
||||
#include "dgMeshEffect.h"
|
||||
#include "hpl1/engine/libraries/newton/core/dg.h"
|
||||
|
||||
|
||||
#define DG_CLIPPER_TOL dgFloat64(1.0e-12)
|
||||
|
||||
dgMeshTreeCSGFace::dgMeshTreeCSGFace(const dgMeshEffect &mesh,
|
||||
dgEdge *const face) : dgList<dgHugeVector>(mesh.GetAllocator()), m_side(dgMeshEffectSolidTree::m_divider) {
|
||||
const dgEdge *ptr = face;
|
||||
const dgMeshEffect::dgVertexAtribute *const attib = mesh.m_attib;
|
||||
do {
|
||||
Append(attib[ptr->m_userData].m_vertex);
|
||||
ptr = ptr->m_next;
|
||||
} while (ptr != face);
|
||||
}
|
||||
|
||||
dgMeshTreeCSGFace::dgMeshTreeCSGFace(dgMemoryAllocator *const allocator,
|
||||
dgInt32 count, const dgHugeVector *const points) : dgList<dgHugeVector>(allocator), m_side(dgMeshEffectSolidTree::m_divider) {
|
||||
for (dgInt32 i = 0; i < count; i++) {
|
||||
Append(points[i]);
|
||||
}
|
||||
}
|
||||
|
||||
bool dgMeshTreeCSGFace::IsPointOnEdge(const dgHugeVector &p0,
|
||||
const dgHugeVector &p1, const dgHugeVector &q0) const {
|
||||
dgHugeVector p1p0(p1 - p0);
|
||||
dgGoogol den(p1p0 % p1p0);
|
||||
|
||||
dgHugeVector q0p0(q0 - p0);
|
||||
dgGoogol num(q0p0 % p1p0);
|
||||
|
||||
dgFloat64 numf = num.GetAproximateValue();
|
||||
if (numf > (DG_CLIPPER_TOL * dgFloat64(1.0e3))) {
|
||||
if (numf < den.GetAproximateValue() * dgFloat64(1.0 - (DG_CLIPPER_TOL * dgFloat64(1.0e3)))) {
|
||||
dgGoogol t = num / den;
|
||||
NEWTON_ASSERT(t.GetAproximateValue() > dgFloat64(0.0f));
|
||||
NEWTON_ASSERT(t.GetAproximateValue() < dgFloat64(1.0f));
|
||||
dgHugeVector q1(p0 + p1p0.Scale(t));
|
||||
dgHugeVector dist(q1 - q0);
|
||||
dgGoogol dist2 = dist % dist;
|
||||
if (dist2.GetAproximateValue() < DG_CLIPPER_TOL) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dgMeshTreeCSGFace::CheckConvex(const dgHugeVector &normal) const {
|
||||
dgHugeVector p1(GetLast()->GetInfo());
|
||||
dgHugeVector p0(GetLast()->GetPrev()->GetInfo());
|
||||
dgHugeVector e0(p0 - p1);
|
||||
for (dgListNode *node = GetFirst(); node; node = node->GetNext()) {
|
||||
dgHugeVector p2(node->GetInfo());
|
||||
dgHugeVector e1(p2 - p1);
|
||||
|
||||
dgHugeVector n(e1 * e0);
|
||||
dgGoogol convex = n % normal;
|
||||
if (convex.GetAproximateValue() < dgFloat64(-1.0e10f)) {
|
||||
return false;
|
||||
}
|
||||
p1 = p2;
|
||||
e0 = e1.Scale(dgGoogol(-1.0f));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void dgMeshTreeCSGFace::MergeMissingVertex(const dgMeshTreeCSGFace *const face) {
|
||||
for (dgMeshTreeCSGFace::dgListNode *outNode = GetFirst();
|
||||
outNode != GetLast(); outNode = outNode->GetNext()) {
|
||||
dgHugeVector p0(outNode->GetInfo());
|
||||
for (dgMeshTreeCSGFace::dgListNode *node = face->GetFirst(); node; node =
|
||||
node->GetNext()) {
|
||||
if (IsPointOnEdge(p0, outNode->GetNext()->GetInfo(), node->GetInfo())) {
|
||||
dgMeshTreeCSGFace::dgListNode *const insertNode = Append(
|
||||
node->GetInfo());
|
||||
InsertAfter(outNode, insertNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RotateToBegin(GetLast());
|
||||
dgListNode *const last = GetFirst()->GetNext();
|
||||
for (dgMeshTreeCSGFace::dgListNode *outNode = GetFirst(); outNode != last;
|
||||
outNode = outNode->GetNext()) {
|
||||
dgHugeVector p0(outNode->GetInfo());
|
||||
dgHugeVector p1(outNode->GetNext()->GetInfo());
|
||||
|
||||
for (dgMeshTreeCSGFace::dgListNode *node = face->GetFirst(); node; node =
|
||||
node->GetNext()) {
|
||||
if (IsPointOnEdge(p0, outNode->GetNext()->GetInfo(), node->GetInfo())) {
|
||||
dgMeshTreeCSGFace::dgListNode *const insertNode = Append(
|
||||
node->GetInfo());
|
||||
InsertAfter(outNode, insertNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dgInt32 dgMeshTreeCSGFace::RemoveDuplicates(dgInt32 count,
|
||||
dgHugeVector *const points) const {
|
||||
dgInt32 index[256];
|
||||
for (dgInt32 i = 0; i < count; i++) {
|
||||
index[i] = i + 1;
|
||||
}
|
||||
index[count - 1] = 0;
|
||||
|
||||
dgInt32 originalCount = count;
|
||||
dgInt32 start = index[0];
|
||||
for (dgInt32 count1 = 0; (count1 != count) && (count >= 3);) {
|
||||
count1 = 0;
|
||||
for (dgInt32 i = 0; i < count; i++) {
|
||||
dgInt32 next = index[start];
|
||||
dgHugeVector err(points[start] - points[next]);
|
||||
dgGoogol dist2 = err % err;
|
||||
dgFloat64 val = dist2.GetAproximateValue();
|
||||
if (val < dgFloat64(1.0e-12f)) {
|
||||
index[start] = index[index[start]];
|
||||
count1 = 0;
|
||||
count--;
|
||||
break;
|
||||
}
|
||||
|
||||
count1++;
|
||||
start = index[start];
|
||||
}
|
||||
}
|
||||
|
||||
if ((count != originalCount) && (count >= 3)) {
|
||||
dgHugeVector tmp[256];
|
||||
for (dgInt32 i = 0; i < count; i++) {
|
||||
tmp[i] = points[start];
|
||||
start = index[start];
|
||||
}
|
||||
|
||||
for (dgInt32 i = 0; i < count; i++) {
|
||||
points[i] = tmp[i];
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
dgMatrix dgMeshTreeCSGFace::DebugMatrix() const {
|
||||
dgMatrix matrix(dgGetIdentityMatrix());
|
||||
dgHugeVector e0(GetFirst()->GetNext()->GetInfo() - GetFirst()->GetInfo());
|
||||
dgHugeVector e1(
|
||||
GetFirst()->GetNext()->GetNext()->GetInfo() - GetFirst()->GetInfo());
|
||||
dgHugeVector aaa(e0 * e1);
|
||||
dgVector aaaa(dgFloat32(aaa.m_x.GetAproximateValue()),
|
||||
dgFloat32(aaa.m_y.GetAproximateValue()),
|
||||
dgFloat32(aaa.m_z.GetAproximateValue()), 0.0f);
|
||||
aaaa = aaaa.Scale(dgFloat32(1.0) / dgSqrt(aaaa % aaaa));
|
||||
|
||||
dgVector bbbb(dgFloat32(e0.m_x.GetAproximateValue()),
|
||||
dgFloat32(e0.m_y.GetAproximateValue()),
|
||||
dgFloat32(e0.m_z.GetAproximateValue()), 0.0f);
|
||||
bbbb = bbbb.Scale(dgFloat32(1.0) / dgSqrt(bbbb % bbbb));
|
||||
|
||||
matrix.m_up = bbbb;
|
||||
matrix.m_right = aaaa;
|
||||
matrix.m_front = bbbb * aaaa;
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
||||
void dgMeshTreeCSGFace::Trace(const dgMatrix &matrix) const {
|
||||
for (dgMeshTreeCSGFace::dgListNode *node = GetFirst(); node;
|
||||
node = node->GetNext()) {
|
||||
const dgHugeVector &bbb = node->GetInfo();
|
||||
dgVector bbbb(dgFloat32(bbb.m_x.GetAproximateValue()),
|
||||
dgFloat32(bbb.m_y.GetAproximateValue()),
|
||||
dgFloat32(bbb.m_z.GetAproximateValue()), 0.0f);
|
||||
bbbb = matrix.UnrotateVector(bbbb);
|
||||
bbbb.Trace();
|
||||
}
|
||||
dgTrace(("\n"));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
dgHugeVector dgMeshTreeCSGFace::FaceNormal() const {
|
||||
dgHugeVector area(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
dgHugeVector e0(GetFirst()->GetNext()->GetInfo() - GetFirst()->GetInfo());
|
||||
for (dgListNode *node = GetFirst()->GetNext()->GetNext(); node;
|
||||
node = node->GetNext()) {
|
||||
dgHugeVector e1(node->GetInfo() - GetFirst()->GetInfo());
|
||||
area += e0 * e1;
|
||||
e0 = e1;
|
||||
}
|
||||
return area;
|
||||
}
|
||||
|
||||
bool dgMeshTreeCSGFace::CheckFaceArea(dgInt32 count,
|
||||
const dgHugeVector *const points) const {
|
||||
dgHugeVector area(dgFloat64(0.0), dgFloat64(0.0), dgFloat64(0.0),
|
||||
dgFloat64(0.0));
|
||||
dgHugeVector e0(points[1] - points[0]);
|
||||
for (dgInt32 i = 2; i < count; i++) {
|
||||
dgHugeVector e1(points[i] - points[0]);
|
||||
area += e0 * e1;
|
||||
e0 = e1;
|
||||
}
|
||||
|
||||
dgFloat64 val = (area % area).GetAproximateValue();
|
||||
return (val > dgFloat64(1.0e-12f)) ? true : false;
|
||||
}
|
||||
|
||||
/*
|
||||
//dgGoogol xxx1(dgGoogol v)
|
||||
dgGoogol xxx1(dgInt32 x)
|
||||
{
|
||||
dgGoogol old (0);
|
||||
dgGoogol ans (1);
|
||||
while (x > 1) {
|
||||
dgGoogol n (ans + old);
|
||||
old = ans;
|
||||
ans = n;
|
||||
x = x - 1;
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
||||
dgGoogol xxx2(dgInt32 x)
|
||||
{
|
||||
dgGoogol one (1);
|
||||
dgGoogol n (x);
|
||||
dgGoogol a (1);
|
||||
for (int i = x; i >= 1; i --) {
|
||||
a = a * n;
|
||||
n -= one;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
void xxxx()
|
||||
{
|
||||
char text[256];
|
||||
// dgGoogol a (xxx1(100));
|
||||
// dgGoogol a (1.05);
|
||||
dgGoogol a (xxx2 (60));
|
||||
a.ToString(text);
|
||||
// dgFloat64 xxxxx = a.GetAproximateValue();
|
||||
}
|
||||
*/
|
||||
|
||||
void dgMeshTreeCSGFace::Clip(const dgHugeVector &plane,
|
||||
dgMeshTreeCSGFace **leftOut, dgMeshTreeCSGFace **rightOut) {
|
||||
// xxxx ();
|
||||
|
||||
dgInt8 pointSide[256];
|
||||
|
||||
dgInt32 count = 0;
|
||||
dgInt32 rightPCount = 0;
|
||||
dgInt32 leftPCount = 0;
|
||||
for (dgMeshTreeCSGFace::dgListNode *ptr = GetFirst(); ptr; ptr =
|
||||
ptr->GetNext()) {
|
||||
const dgHugeVector &p = ptr->GetInfo();
|
||||
|
||||
dgGoogol test = plane.EvaluePlane(p);
|
||||
dgFloat64 val = test.GetAproximateValue();
|
||||
if (fabs(val) < DG_CLIPPER_TOL) {
|
||||
val = dgFloat64(0.0f);
|
||||
}
|
||||
|
||||
if (val > dgFloat64(0.0f)) {
|
||||
pointSide[count] = 1;
|
||||
rightPCount++;
|
||||
} else if (val < dgFloat64(0.0f)) {
|
||||
pointSide[count] = -1;
|
||||
leftPCount++;
|
||||
} else {
|
||||
pointSide[count] = 0;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
*leftOut = NULL;
|
||||
*rightOut = NULL;
|
||||
if ((leftPCount && !rightPCount) || (!leftPCount && rightPCount)) {
|
||||
if (leftPCount) {
|
||||
NEWTON_ASSERT(!rightPCount);
|
||||
AddRef();
|
||||
*leftOut = this;
|
||||
} else {
|
||||
NEWTON_ASSERT(!leftPCount);
|
||||
*rightOut = this;
|
||||
AddRef();
|
||||
}
|
||||
} else if (!(leftPCount || rightPCount)) {
|
||||
NEWTON_ASSERT(!leftPCount);
|
||||
NEWTON_ASSERT(!rightPCount);
|
||||
AddRef();
|
||||
// AddRef();
|
||||
} else {
|
||||
dgInt32 leftCount = 0;
|
||||
dgInt32 rightCount = 0;
|
||||
dgHugeVector leftFace[256];
|
||||
dgHugeVector rightFace[256];
|
||||
|
||||
dgInt32 i1 = 0;
|
||||
dgInt32 i0 = count - 1;
|
||||
dgHugeVector p0(GetLast()->GetInfo());
|
||||
for (dgMeshTreeCSGFace::dgListNode *ptr = GetFirst(); ptr;
|
||||
ptr = ptr->GetNext()) {
|
||||
const dgHugeVector &p1(ptr->GetInfo());
|
||||
|
||||
dgHugeVector inter;
|
||||
if (((pointSide[i0] == -1) && (pointSide[i1] == 1)) || ((pointSide[i0] == 1) && (pointSide[i1] == -1))) {
|
||||
// inter = Interpolate (plane, p0, p1);
|
||||
dgHugeVector dp(p1 - p0);
|
||||
dgGoogol den(plane % dp);
|
||||
dgGoogol num = plane.EvaluePlane(p0);
|
||||
NEWTON_ASSERT(fabs(num.GetAproximateValue()) > dgFloat64(0.0f));
|
||||
dgGoogol ti(num / den);
|
||||
inter = p0 - dp.Scale(num / den);
|
||||
}
|
||||
|
||||
if (pointSide[i1] == -1) {
|
||||
if (pointSide[i0] == 1) {
|
||||
rightFace[rightCount] = inter;
|
||||
rightCount++;
|
||||
}
|
||||
} else {
|
||||
if ((pointSide[i1] == 1) && (pointSide[i0] == -1)) {
|
||||
rightFace[rightCount] = inter;
|
||||
rightCount++;
|
||||
}
|
||||
rightFace[rightCount] = p1;
|
||||
rightCount++;
|
||||
}
|
||||
|
||||
if (pointSide[i1] == 1) {
|
||||
if (pointSide[i0] == -1) {
|
||||
leftFace[leftCount] = inter;
|
||||
leftCount++;
|
||||
}
|
||||
} else {
|
||||
if ((pointSide[i1] == -1) && (pointSide[i0] == 1)) {
|
||||
leftFace[leftCount] = inter;
|
||||
leftCount++;
|
||||
}
|
||||
leftFace[leftCount] = p1;
|
||||
leftCount++;
|
||||
}
|
||||
NEWTON_ASSERT(leftCount < dgInt32((sizeof(leftFace) / sizeof(leftFace[0])) - 1));
|
||||
NEWTON_ASSERT(rightCount < dgInt32((sizeof(rightFace) / sizeof(rightFace[0])) - 1));
|
||||
|
||||
i0 = i1;
|
||||
i1++;
|
||||
p0 = p1;
|
||||
}
|
||||
|
||||
leftCount = RemoveDuplicates(leftCount, leftFace);
|
||||
rightCount = RemoveDuplicates(rightCount, rightFace);
|
||||
if ((leftCount >= 3) && CheckFaceArea(leftCount, leftFace)) {
|
||||
*leftOut = new (GetAllocator()) dgMeshTreeCSGFace(GetAllocator(),
|
||||
leftCount, leftFace);
|
||||
}
|
||||
|
||||
if ((rightCount >= 3) && CheckFaceArea(rightCount, rightFace)) {
|
||||
*rightOut = new (GetAllocator()) dgMeshTreeCSGFace(GetAllocator(),
|
||||
rightCount, rightFace);
|
||||
}
|
||||
NEWTON_ASSERT(*leftOut || *rightOut);
|
||||
}
|
||||
}
|
||||
|
||||
dgMeshEffectSolidTree::dgMeshEffectSolidTree(dgPlaneType type) : m_planeType(type), m_back(NULL), m_front(NULL), m_plane(0.0, 0.0, 0.0, 0.0) {
|
||||
}
|
||||
|
||||
dgMeshEffectSolidTree::dgMeshEffectSolidTree(const dgMeshEffect &mesh,
|
||||
dgEdge *const face) : m_planeType(m_divider), m_back(new (mesh.GetAllocator()) dgMeshEffectSolidTree(m_solid)), m_front(new (mesh.GetAllocator()) dgMeshEffectSolidTree(m_empty)), m_plane(BuildPlane(mesh, face)) {
|
||||
}
|
||||
|
||||
dgMeshEffectSolidTree::dgMeshEffectSolidTree(const dgHugeVector &plane,
|
||||
dgMemoryAllocator *const allocator) : m_planeType(m_divider), m_back(new (allocator) dgMeshEffectSolidTree(m_solid)), m_front(new (allocator) dgMeshEffectSolidTree(m_empty)), m_plane(plane) {
|
||||
}
|
||||
|
||||
dgMeshEffectSolidTree::~dgMeshEffectSolidTree() {
|
||||
if (m_front) {
|
||||
delete m_front;
|
||||
}
|
||||
|
||||
if (m_back) {
|
||||
delete m_back;
|
||||
}
|
||||
}
|
||||
|
||||
dgHugeVector dgMeshEffectSolidTree::BuildPlane(const dgMeshEffect &mesh,
|
||||
dgEdge *const face) const {
|
||||
dgEdge *edge = face;
|
||||
dgHugeVector plane(dgFloat32(0.0f), dgFloat32(0.0f), dgFloat32(0.0f),
|
||||
dgFloat32(0.0f));
|
||||
|
||||
dgHugeVector p0(mesh.m_points[edge->m_incidentVertex]);
|
||||
|
||||
edge = edge->m_next;
|
||||
dgHugeVector p1(mesh.m_points[edge->m_incidentVertex]);
|
||||
|
||||
dgHugeVector e1(p1 - p0);
|
||||
for (edge = edge->m_next; edge != face; edge = edge->m_next) {
|
||||
dgHugeVector p2(mesh.m_points[edge->m_incidentVertex]);
|
||||
dgHugeVector e2(p2 - p0);
|
||||
plane += e1 * e2;
|
||||
e1 = e2;
|
||||
}
|
||||
|
||||
plane.m_w = (p0 % plane) * dgGoogol(-1.0);
|
||||
return plane;
|
||||
}
|
||||
|
||||
void dgMeshEffectSolidTree::AddFace(const dgMeshEffect &mesh,
|
||||
dgEdge *const face) {
|
||||
dgBigVector normal(
|
||||
mesh.FaceNormal(face, &mesh.m_points[0][0], sizeof(dgBigVector)));
|
||||
dgFloat64 mag2 = normal % normal;
|
||||
|
||||
if (mag2 > dgFloat32(1.0e-14f)) {
|
||||
dgMeshTreeCSGFace *faces[DG_MESH_EFFECT_BOLLEAN_STACK];
|
||||
dgMeshEffectSolidTree *pool[DG_MESH_EFFECT_BOLLEAN_STACK];
|
||||
|
||||
dgHugeVector plane(BuildPlane(mesh, face));
|
||||
|
||||
dgInt32 stack = 1;
|
||||
pool[0] = this;
|
||||
faces[0] = new (mesh.GetAllocator()) dgMeshTreeCSGFace(mesh, face);
|
||||
|
||||
while (stack) {
|
||||
|
||||
stack--;
|
||||
dgMeshEffectSolidTree *const root = pool[stack];
|
||||
NEWTON_ASSERT(root->m_planeType == m_divider);
|
||||
|
||||
dgMeshTreeCSGFace *const curve = faces[stack];
|
||||
NEWTON_ASSERT(curve->CheckConvex(plane));
|
||||
|
||||
dgMeshTreeCSGFace *backOut;
|
||||
dgMeshTreeCSGFace *frontOut;
|
||||
curve->Clip(root->m_plane, &backOut, &frontOut);
|
||||
|
||||
if ((backOut == NULL) && (frontOut == NULL)) {
|
||||
curve->Release();
|
||||
} else {
|
||||
if (backOut && frontOut) {
|
||||
dgHugeVector backArea(backOut->FaceNormal());
|
||||
dgHugeVector frontArea(frontOut->FaceNormal());
|
||||
|
||||
dgFloat64 backMag = (backArea % backArea).GetAproximateValue();
|
||||
dgFloat64 frontMag = (frontArea % frontArea).GetAproximateValue();
|
||||
if (backMag > frontMag) {
|
||||
if (backMag > (frontMag * dgFloat64(1.0e6))) {
|
||||
frontOut->Release();
|
||||
frontOut = NULL;
|
||||
}
|
||||
} else {
|
||||
if (frontMag > (backMag * dgFloat64(1.0e6))) {
|
||||
backOut->Release();
|
||||
backOut = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (backOut) {
|
||||
if (root->m_back->m_planeType != m_divider) {
|
||||
backOut->Release();
|
||||
delete root->m_back;
|
||||
root->m_back = new (mesh.GetAllocator()) dgMeshEffectSolidTree(
|
||||
plane, mesh.GetAllocator());
|
||||
} else {
|
||||
faces[stack] = backOut;
|
||||
pool[stack] = root->m_back;
|
||||
stack++;
|
||||
NEWTON_ASSERT(stack < dgInt32(sizeof(pool) / sizeof(pool[0])));
|
||||
}
|
||||
}
|
||||
|
||||
if (frontOut) {
|
||||
if (root->m_front->m_planeType != m_divider) {
|
||||
frontOut->Release();
|
||||
delete root->m_front;
|
||||
root->m_front = new (mesh.GetAllocator()) dgMeshEffectSolidTree(
|
||||
plane, mesh.GetAllocator());
|
||||
} else {
|
||||
faces[stack] = frontOut;
|
||||
pool[stack] = root->m_front;
|
||||
stack++;
|
||||
NEWTON_ASSERT(stack < dgInt32(sizeof(pool) / sizeof(pool[0])));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
curve->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dgMeshEffectSolidTree::dgPlaneType dgMeshEffectSolidTree::GetPointSide(
|
||||
const dgHugeVector &point) const {
|
||||
const dgMeshEffectSolidTree *root = this;
|
||||
|
||||
NEWTON_ASSERT(root);
|
||||
while (root->m_planeType == dgMeshEffectSolidTree::m_divider) {
|
||||
dgGoogol test = root->m_plane.EvaluePlane(point);
|
||||
dgFloat64 dist = test.GetAproximateValue();
|
||||
|
||||
if (fabs(dist) < dgFloat64(1.0e-16f)) {
|
||||
dgPlaneType isBackSide = root->m_back->GetPointSide(point);
|
||||
dgPlaneType isFrontSide = root->m_front->GetPointSide(point);
|
||||
return (isBackSide == isFrontSide) ? isFrontSide : m_divider;
|
||||
|
||||
} else if (dist > dgFloat64(0.0f)) {
|
||||
root = root->m_front;
|
||||
} else {
|
||||
NEWTON_ASSERT(dist < dgFloat64(0.0f));
|
||||
root = root->m_back;
|
||||
}
|
||||
}
|
||||
return root->m_planeType;
|
||||
}
|
||||
|
||||
dgMeshEffectSolidTree::dgPlaneType dgMeshEffectSolidTree::GetFaceSide(
|
||||
const dgMeshTreeCSGFace *const face) const {
|
||||
dgHugeVector center(0.0, 0.0, 0.0, 0.0);
|
||||
for (dgMeshTreeCSGFace::dgListNode *node = face->GetFirst(); node;
|
||||
node = node->GetNext()) {
|
||||
const dgHugeVector &point = node->GetInfo();
|
||||
center += point;
|
||||
}
|
||||
center = center.Scale(dgGoogol(1.0) / dgGoogol(face->GetCount()));
|
||||
dgPlaneType faceSide(GetPointSide(center));
|
||||
return faceSide;
|
||||
}
|
||||
Reference in New Issue
Block a user