[Bf-extensions-cvs] [2b3fbd9] master: Barycentric weight calculation for face interpolation.
Lukas Tönne
noreply at git.blender.org
Wed Dec 10 10:52:24 CET 2014
Commit: 2b3fbd9f7fe899c0bc8fbc7d17e3f8d78a258558
Author: Lukas Tönne
Date: Wed Dec 10 10:19:10 2014 +0100
Branches: master
https://developer.blender.org/rBAC2b3fbd9f7fe899c0bc8fbc7d17e3f8d78a258558
Barycentric weight calculation for face interpolation.
Ported over from C code in BLI_math_geom.
===================================================================
M object_physics_meadow/blob.py
M object_physics_meadow/duplimesh.py
===================================================================
diff --git a/object_physics_meadow/blob.py b/object_physics_meadow/blob.py
index 463ed63..e4d7605 100644
--- a/object_physics_meadow/blob.py
+++ b/object_physics_meadow/blob.py
@@ -28,7 +28,7 @@ import random
from object_physics_meadow import settings as _settings
from object_physics_meadow import duplimesh
-from object_physics_meadow.duplimesh import project_on_ground
+from object_physics_meadow.duplimesh import project_on_ground, interp_weights_face
from object_physics_meadow.util import *
_blob_object_name = "__MeadowBlob__"
@@ -213,12 +213,13 @@ def assign_sample_patches(groundob, blob):
vgroup_samples[""] = [] # samples for unassigned patches
for loc, nor, face_index in blob.samples:
face = faces[face_index]
- # XXX this throws an exception if testing for vertex outside the group
- # but there seems to be no nice way to test beforehand ...
- #weights = [ [vg.weight(i) for i in face.vertices] for vg in vgroups ]
+ verts = [vertices[i] for i in face.vertices]
+ assert(len(verts) in {3, 4})
+
+ fweight, findex = interp_weights_face(tuple(v.co for v in verts[0:4]), loc)
+
weights = [ 0.0 for vg in vgroups ]
- for i in face.vertices:
- v = vertices[i]
+ for v in verts:
for vg in v.groups:
weights[vg.group] += 0.25 * vg.weight # TODO
diff --git a/object_physics_meadow/duplimesh.py b/object_physics_meadow/duplimesh.py
index 499e1c7..c6e4f37 100644
--- a/object_physics_meadow/duplimesh.py
+++ b/object_physics_meadow/duplimesh.py
@@ -18,9 +18,67 @@
# <pep8 compliant>
-import bpy
+import bpy, sys
+from math import *
from mathutils import *
+def tri_signed_area(v1, v2, v3, i, j):
+ return 0.5 * ((v1[i] - v2[i]) * (v2[j] - v3[j]) + (v1[j] - v2[j]) * (v3[i] - v2[i]))
+
+# get the 2 dominant axis values, 0==X, 1==Y, 2==Z
+def axis_dominant(axis):
+ xn = fabs(axis[0])
+ yn = fabs(axis[1])
+ zn = fabs(axis[2])
+ if zn >= xn and zn >= yn:
+ return 0, 1
+ elif yn >= xn and yn >= zn:
+ return 0, 2
+ else:
+ return 1, 2
+
+def barycentric_weights(v1, v2, v3, co, n):
+ i, j = axis_dominant(n)
+
+ w = (tri_signed_area(v2, v3, co, i, j),
+ tri_signed_area(v3, v1, co, i, j),
+ tri_signed_area(v1, v2, co, i, j))
+ wtot = w[0] + w[1] + w[2]
+
+ if fabs(wtot) > sys.float_info.epsilon:
+ inv_w = 1.0 / wtot
+ return True, tuple(x*inv_w for x in w)
+ else:
+ return False, tuple(1.0/3.0 for x in w)
+
+def interp_weights_face(verts, co):
+ w = (0.0, 0.0, 0.0, 0.0)
+
+ # OpenGL seems to split this way, so we do too
+ if len(verts) > 3:
+ n = (verts[0] - verts[2]).cross(verts[1] - verts[3])
+
+ ok, w3 = barycentric_weights(verts[0], verts[1], verts[3], co, n)
+ w = (w3[0], w3[1], 0.0, w3[2])
+ idx = (0, 1, 3)
+
+ if not ok or w[0] < 0.0:
+ # if w[1] is negative, co is on the other side of the v1-v3 edge,
+ # so we interpolate using the other triangle
+ ok, w3 = barycentric_weights(verts[1], verts[2], verts[3], co, n)
+ w = (0.0, w3[0], w3[1], w3[2])
+ idx = (1, 2, 3)
+
+ else:
+ n = (verts[0] - verts[2]).cross(verts[1] - verts[2])
+
+ ok, w3 = barycentric_weights(verts[0], verts[1], verts[2], co, n)
+ w = (w3[0], w3[1], w3[2], 0.0)
+ idx = (0, 1, 2)
+
+ return w, idx
+
+
def project_on_ground(groundob, co):
groundmat4 = groundob.matrix_world
groundmat3 = groundmat4.to_3x3()
More information about the Bf-extensions-cvs
mailing list