📄 radprim.cpp
字号:
if (newUPatches == uPatches() && newVPatches == vPatches()) return false;
RadPatchArray newPatches;
fstl::intArray newPatchesCount;
RadPatch defaultPatch;
defaultPatch.area() = 0;
defaultPatch.energy() = geom::Color3(0,0,0);
defaultPatch.origin() = geom::Point3(0,0,0);
defaultPatch.plane() = plane();
newPatches.populate(defaultPatch, newUPatches * newVPatches);
newPatchesCount.populate(0, newUPatches * newVPatches);
for(unsigned int v = 0; v < vPatches(); ++v)
{
for(unsigned int u = 0; u < uPatches(); ++u)
{
unsigned int idx = v * uPatches() + u;
unsigned int newIdx = v/2 * newUPatches + u/2;
// Skip unused patches
if (!patches()[idx].area()) continue;
newPatches[newIdx].area() += patches()[idx].area();
newPatches[newIdx].energy() += patches()[idx].energy();
newPatches[newIdx].origin() += patches()[idx].origin();
newPatchesCount[newIdx]++;
}
}
// Get the origin as the average of the other centers
for (unsigned int j = 0; j < newPatches.size(); ++j)
{
if (newPatchesCount[j]) newPatches[j].origin() /= static_cast<float>(newPatchesCount[j]);
}
patches() = newPatches;
uPatches() = newUPatches;
vPatches() = newVPatches;
return true;
}
// ---------------------------------------------------------------------------------------------------------------------------------
// Hacked from the one in fsgl::Primitive...
// ---------------------------------------------------------------------------------------------------------------------------------
bool RadPrim::localBisect(const geom::Plane3 & clipPlane, RadPrim & back)
{
// First, classify all points. This allows us to avoid any bisection if possible
fstl::floatArray classifications;
classifications.reserve(xyz().size());
{
bool pos = false;
bool neg = false;
for (unsigned int i = 0; i < xyz().size(); ++i)
{
// Get the distance from the plane to the vertex
float dist = clipPlane.distance(xyz()[i]);
// Classify the point
if (dist > -EPSILON && dist < EPSILON) dist = 0.0f;
else if (dist > 0) pos = true;
else neg = true;
// Keep track
classifications += dist;
}
// Special (and necessary) case:
//
// If the polygon rests on the plane, it could be associated with either side (or neither side)... so we pick one.
// The only criteria we have for this choice is to use the normals....
//
// The specific case ("dot product > 0 == associate with front") was chosen for cases in the octree -- a polygon facing
// the interior of a node, but resting on an outer-most-node boundary. We want it associated with the node, not thrown
// out completely.
if (!pos && !neg)
{
// Associate with front
if ((plane().vector() ^ clipPlane.vector()) > 0)
{
pos = true;
}
// Associate with back
else
{
neg = true;
}
}
// If no negative points, return an empty negative polygon
if (!neg)
{
back.xyz().erase();
back.uv().erase();
back.texuv().erase();
return true;
}
// If no positive points, return self as negative polygon
else if (!pos)
{
back.xyz() = xyz();
back.uv() = uv();
back.texuv() = texuv();
back.plane() = plane();
xyz().erase();
uv().erase();
texuv().erase();
return true;
}
}
// Our result is stored here
back.xyz() = xyz();
back.uv() = uv();
back.texuv() = texuv();
back.plane() = plane();
geom::Point3Array & negXYZ = back.xyz();
geom::Point2Array & negUV = back.uv();
geom::Point2Array & negTUV = back.texuv();
negXYZ.erase();
negXYZ.reserve(xyz().size());
negUV.erase();
negUV.reserve(xyz().size());
negTUV.erase();
negTUV.reserve(xyz().size());
geom::Point3Array posXYZ;
geom::Point2Array posUV;
geom::Point2Array posTUV;
posXYZ.reserve(xyz().size());
posUV.reserve(xyz().size());
posTUV.reserve(xyz().size());
// Visit all points in the list, adding points that are on the front-side of the current plane. If an edge bisects the plane,
// add the bisection point.
unsigned int v0 = xyz().size() - 1;
for (unsigned int v1 = 0; v1 < xyz().size(); ++v1)
{
const geom::Point3 & p0 = xyz()[v0];
const geom::Point3 & p1 = xyz()[v1];
const geom::Point2 & l0 = uv()[v0];
const geom::Point2 & l1 = uv()[v1];
const geom::Point2 & t0 = texuv()[v0];
const geom::Point2 & t1 = texuv()[v1];
float d0 = classifications[v0];
float d1 = classifications[v1];
// neg->neg non-crossover?
if (d0 < 0 && d1 < 0)
{
negXYZ += p1;
negUV += l1;
negTUV += t1;
}
// neg->zed crossover?
else if (d0 < 0 && d1 == 0)
{
negXYZ += p1;
posXYZ += p1;
negUV += l1;
posUV += l1;
negTUV += t1;
posTUV += t1;
}
// neg->pos crossover?
else if (d0 < 0 && d1 > 0)
{
float delta = d0 / (d1-d0);
geom::Point3 bisectionXYZ = p0 - (p1 - p0) * delta;
negXYZ += bisectionXYZ;
posXYZ += bisectionXYZ;
posXYZ += p1;
geom::Point2 bisectionUV = l0 - (l1 - l0) * delta;
negUV += bisectionUV;
posUV += bisectionUV;
posUV += l1;
geom::Point2 bisectionTUV = t0 - (t1 - t0) * delta;
negTUV += bisectionTUV;
posTUV += bisectionTUV;
posTUV += t1;
}
// zed->pos crossover?
else if (d0 == 0 && d1 > 0)
{
posXYZ += p1;
posUV += l1;
posTUV += t1;
}
// zed->neg crossover?
else if (d0 == 0 && d1 < 0)
{
negXYZ += p1;
negUV += l1;
negTUV += t1;
}
// pos->pos non-crossover?
else if (d0 > 0 && d1 > 0)
{
posXYZ += p1;
posUV += l1;
posTUV += t1;
}
// pos->neg crossover?
else if (d0 > 0 && d1 < 0)
{
float delta = d1 / (d0-d1);
geom::Point3 bisectionXYZ = p1 - (p0 - p1) * delta;
posXYZ += bisectionXYZ;
negXYZ += bisectionXYZ;
negXYZ += p1;
geom::Point2 bisectionUV = l1 - (l0 - l1) * delta;
posUV += bisectionUV;
negUV += bisectionUV;
negUV += l1;
geom::Point2 bisectionTUV = t1 - (t0 - t1) * delta;
posTUV += bisectionTUV;
negTUV += bisectionTUV;
negTUV += t1;
}
// pos->zed crossover?
else if (d0 > 0 && d1 == 0)
{
posXYZ += p1;
negXYZ += p1;
posUV += l1;
negUV += l1;
posTUV += t1;
negTUV += t1;
}
// If the edge rests completely on the plane, then we've got a concave polygon. How's that, you say? Well...
// This really shouldn't ever happen since an edge that rests on the plane means it can never cross the plane
// without going concave, but inaccuracy issues do happen...
//
// Chances are (and we're guessing here!) that p0 and p1 are nearly (or completely) identical, in which case
// we'll just ignore this, and it'll skip the extra vertex.
else if (d0 == 0 && d1 == 0)
{
// Do nothing!
}
// Next vertex, please!
v0 = v1;
}
// Replace the vertices with just those found on the postiive side
xyz() = posXYZ;
uv() = posUV;
texuv() = posTUV;
// Done
return true;
}
// ---------------------------------------------------------------------------------------------------------------------------------
bool RadPrim::bisectNoTextures(const geom::Plane3 & clipPlane, RadPrim & back)
{
// First, classify all points. This allows us to avoid any bisection if possible
fstl::floatArray classifications;
classifications.reserve(xyz().size());
{
bool pos = false;
bool neg = false;
for (unsigned int i = 0; i < xyz().size(); ++i)
{
// Get the distance from the plane to the vertex
float dist = clipPlane.distance(xyz()[i]);
// Classify the point
if (dist > -EPSILON && dist < EPSILON) dist = 0.0f;
else if (dist > 0) pos = true;
else neg = true;
// Keep track
classifications += dist;
}
// Special (and necessary) case:
//
// If the polygon rests on the plane, it could be associated with either side (or neither side)... so we pick one.
// The only criteria we have for this choice is to use the normals....
//
// The specific case ("dot product > 0 == associate with front") was chosen for cases in the octree -- a polygon facing
// the interior of a node, but resting on an outer-most-node boundary. We want it associated with the node, not thrown
// out completely.
if (!pos && !neg)
{
// Associate with front
if ((plane().vector() ^ clipPlane.vector()) > 0)
{
pos = true;
}
// Associate with back
else
{
neg = true;
}
}
// If no negative points, return an empty negative polygon
if (!neg)
{
back.xyz().erase();
return true;
}
// If no positive points, return self as negative polygon
else if (!pos)
{
back.xyz() = xyz();
back.plane() = plane();
xyz().erase();
return true;
}
}
// Our result is stored here
back.xyz() = xyz();
back.plane() = plane();
geom::Point3Array & negXYZ = back.xyz();
negXYZ.erase();
negXYZ.reserve(xyz().size());
geom::Point3Array posXYZ;
posXYZ.reserve(xyz().size());
// Visit all points in the list, adding points that are on the front-side of the current plane. If an edge bisects the plane,
// add the bisection point.
unsigned int v0 = xyz().size() - 1;
for (unsigned int v1 = 0; v1 < xyz().size(); ++v1)
{
const geom::Point3 & p0 = xyz()[v0];
const geom::Point3 & p1 = xyz()[v1];
float d0 = classifications[v0];
float d1 = classifications[v1];
// neg->neg non-crossover?
if (d0 < 0 && d1 < 0)
{
negXYZ += p1;
}
// neg->zed crossover?
else if (d0 < 0 && d1 == 0)
{
negXYZ += p1;
posXYZ += p1;
}
// neg->pos crossover?
else if (d0 < 0 && d1 > 0)
{
float delta = d0 / (d1-d0);
geom::Point3 bisectionXYZ = p0 - (p1 - p0) * delta;
negXYZ += bisectionXYZ;
posXYZ += bisectionXYZ;
posXYZ += p1;
}
// zed->pos crossover?
else if (d0 == 0 && d1 > 0)
{
posXYZ += p1;
}
// zed->neg crossover?
else if (d0 == 0 && d1 < 0)
{
negXYZ += p1;
}
// pos->pos non-crossover?
else if (d0 > 0 && d1 > 0)
{
posXYZ += p1;
}
// pos->neg crossover?
else if (d0 > 0 && d1 < 0)
{
float delta = d1 / (d0-d1);
geom::Point3 bisectionXYZ = p1 - (p0 - p1) * delta;
posXYZ += bisectionXYZ;
negXYZ += bisectionXYZ;
negXYZ += p1;
}
// pos->zed crossover?
else if (d0 > 0 && d1 == 0)
{
posXYZ += p1;
negXYZ += p1;
}
// If the edge rests completely on the plane, then we've got a concave polygon. How's that, you say? Well...
// This really shouldn't ever happen since an edge that rests on the plane means it can never cross the plane
// without going concave, but inaccuracy issues do happen...
//
// Chances are (and we're guessing here!) that p0 and p1 are nearly (or completely) identical, in which case
// we'll just ignore this, and it'll skip the extra vertex.
else if (d0 == 0 && d1 == 0)
{
// Do nothing!
}
// Next vertex, please!
v0 = v1;
}
// Replace the vertices with just those found on the postiive side
xyz() = posXYZ;
// Done
return true;
}
// ---------------------------------------------------------------------------------------------------------------------------------
// RadPrim.cpp - End of file
// ---------------------------------------------------------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -