Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2007-02-10 00:46:08 +0300
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2007-02-10 00:46:08 +0300
commit298ee9d3dc18fbedaaaf9cb0c033c821730b35fa (patch)
treecc2e48c3184691d8d4bfea3c1aabc34d6add8aa9 /source/blender/blenlib
parentc7c0e7bf808dbbe93bb3d659eb1c27bcc496fadc (diff)
Fix for bug #5891:
Knife cut didn't always subdivide UVs properly with degenerate triangles.
Diffstat (limited to 'source/blender/blenlib')
-rw-r--r--source/blender/blenlib/intern/arithb.c52
1 files changed, 32 insertions, 20 deletions
diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c
index 97d40fbb95b..e19ffa29b28 100644
--- a/source/blender/blenlib/intern/arithb.c
+++ b/source/blender/blenlib/intern/arithb.c
@@ -2139,9 +2139,14 @@ void MinMax3(float *min, float *max, float *vec)
if(max[2]<vec[2]) max[2]= vec[2];
}
-static void BarycentricWeights(float *v1, float *v2, float *v3, float *co, float *n, float *w)
+static float TriSignedArea(float *v1, float *v2, float *v3, int i, int j)
{
- float t00, t01, t10, t11, det, detinv, xn, yn, zn;
+ return 0.5f*((v1[i]-v2[i])*(v2[j]-v3[j]) + (v1[j]-v2[j])*(v3[i]-v2[i]));
+}
+
+static int BarycentricWeights(float *v1, float *v2, float *v3, float *co, float *n, float *w)
+{
+ float xn, yn, zn, a1, a2, a3, asum;
short i, j;
/* find best projection of face XY, XZ or YZ: barycentric weights of
@@ -2153,28 +2158,30 @@ static void BarycentricWeights(float *v1, float *v2, float *v3, float *co, float
else if(yn>=xn && yn>=zn) {i= 0; j= 2;}
else {i= 1; j= 2;}
- /* compute determinant */
- t00= v3[i]-v1[i]; t01= v3[j]-v1[j];
- t10= v3[i]-v2[i]; t11= v3[j]-v2[j];
+ a1= TriSignedArea(v2, v3, co, i, j);
+ a2= TriSignedArea(v3, v1, co, i, j);
+ a3= TriSignedArea(v1, v2, co, i, j);
- det= t00*t11 - t10*t01;
+ asum= a1 + a2 + a3;
- if(det == 0.0f) {
+ if (fabs(asum) < FLT_EPSILON) {
/* zero area triangle */
w[0]= w[1]= w[2]= 1.0f/3.0f;
- return;
+ return 1;
}
- /* compute weights */
- detinv= 1.0/det;
+ asum= 1.0f/asum;
+ w[0]= a1*asum;
+ w[1]= a2*asum;
+ w[2]= a3*asum;
- w[0]= ((co[j]-v3[j])*t10 - (co[i]-v3[i])*t11)*detinv;
- w[1]= ((co[i]-v3[i])*t01 - (co[j]-v3[j])*t00)*detinv;
- w[2]= 1.0f - w[0] - w[1];
+ return 0;
}
void InterpWeightsQ3Dfl(float *v1, float *v2, float *v3, float *v4, float *co, float *w)
{
+ float w2[3];
+
w[0]= w[1]= w[2]= w[3]= 0.0f;
/* first check for exact match */
@@ -2189,6 +2196,7 @@ void InterpWeightsQ3Dfl(float *v1, float *v2, float *v3, float *v4, float *co, f
else {
/* otherwise compute barycentric interpolation weights */
float n1[3], n2[3], n[3];
+ int degenerate;
VecSubf(n1, v1, v3);
if (v4) {
@@ -2201,16 +2209,20 @@ void InterpWeightsQ3Dfl(float *v1, float *v2, float *v3, float *v4, float *co, f
/* OpenGL seems to split this way, so we do too */
if (v4) {
- BarycentricWeights(v1, v2, v4, co, n, w);
+ degenerate= BarycentricWeights(v1, v2, v4, co, n, w);
+ SWAP(float, w[2], w[3]);
- if(w[0] < 0.0f) {
+ if(degenerate || (w[0] < 0.0f)) {
/* if w[1] is negative, co is on the other side of the v1-v3 edge,
so we interpolate using the other triangle */
- w[0]= 0.0f;
- BarycentricWeights(v2, v3, v4, co, n, w+1);
- }
- else {
- SWAP(float, w[2], w[3]);
+ degenerate= BarycentricWeights(v2, v3, v4, co, n, w2);
+
+ if(!degenerate) {
+ w[0]= 0.0f;
+ w[1]= w2[0];
+ w[2]= w2[1];
+ w[3]= w2[2];
+ }
}
}
else