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:
Diffstat (limited to 'source/blender/blenkernel/intern/mesh_evaluate.c')
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c119
1 files changed, 119 insertions, 0 deletions
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index cb0386b1203..7e547ec4c25 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -1096,6 +1096,125 @@ bool BKE_mesh_center_centroid(Mesh *me, float cent[3])
/* -------------------------------------------------------------------- */
+/** \name Mesh Volume Calculation
+ * \{ */
+
+static bool mesh_calc_center_centroid_ex(MVert *mverts, int UNUSED(numVerts),
+ MFace *mfaces, int numFaces,
+ float center[3])
+{
+ float totweight;
+ int f;
+
+ zero_v3(center);
+
+ if (numFaces == 0)
+ return false;
+
+ totweight = 0.0f;
+ for (f = 0; f < numFaces; ++f) {
+ MFace *face = &mfaces[f];
+ MVert *v1 = &mverts[face->v1];
+ MVert *v2 = &mverts[face->v2];
+ MVert *v3 = &mverts[face->v3];
+ MVert *v4 = &mverts[face->v4];
+ float area;
+
+ area = area_tri_v3(v1->co, v2->co, v3->co);
+ madd_v3_v3fl(center, v1->co, area);
+ madd_v3_v3fl(center, v2->co, area);
+ madd_v3_v3fl(center, v3->co, area);
+ totweight += area;
+
+ if (face->v4) {
+ area = area_tri_v3(v3->co, v4->co, v1->co);
+ madd_v3_v3fl(center, v3->co, area);
+ madd_v3_v3fl(center, v4->co, area);
+ madd_v3_v3fl(center, v1->co, area);
+ totweight += area;
+ }
+ }
+ if (totweight == 0.0f)
+ return false;
+
+ mul_v3_fl(center, 1.0f / (3.0f * totweight));
+
+ return true;
+}
+
+void BKE_mesh_calc_volume(MVert *mverts, int numVerts,
+ MFace *mfaces, int numFaces,
+ float *r_vol, float *r_com)
+{
+ float center[3];
+ float totvol;
+ int f;
+
+ if (r_vol) *r_vol = 0.0f;
+ if (r_com) zero_v3(r_com);
+
+ if (numFaces == 0)
+ return;
+
+ if (!mesh_calc_center_centroid_ex(mverts, numVerts, mfaces, numFaces, center))
+ return;
+
+ totvol = 0.0f;
+ for (f = 0; f < numFaces; ++f) {
+ MFace *face = &mfaces[f];
+ MVert *v1 = &mverts[face->v1];
+ MVert *v2 = &mverts[face->v2];
+ MVert *v3 = &mverts[face->v3];
+ MVert *v4 = &mverts[face->v4];
+ float vol;
+
+ vol = volume_tetrahedron_signed_v3(center, v1->co, v2->co, v3->co);
+ if (r_vol) {
+ totvol += vol;
+ }
+ if (r_com) {
+ /* averaging factor 1/4 is applied in the end */
+ madd_v3_v3fl(r_com, center, vol); // XXX could extract this
+ madd_v3_v3fl(r_com, v1->co, vol);
+ madd_v3_v3fl(r_com, v2->co, vol);
+ madd_v3_v3fl(r_com, v3->co, vol);
+ }
+
+ if (face->v4) {
+ vol = volume_tetrahedron_signed_v3(center, v3->co, v4->co, v1->co);
+
+ if (r_vol) {
+ totvol += vol;
+ }
+ if (r_com) {
+ /* averaging factor 1/4 is applied in the end */
+ madd_v3_v3fl(r_com, center, vol); // XXX could extract this
+ madd_v3_v3fl(r_com, v3->co, vol);
+ madd_v3_v3fl(r_com, v4->co, vol);
+ madd_v3_v3fl(r_com, v1->co, vol);
+ }
+ }
+ }
+
+ /* Note: Depending on arbitrary centroid position,
+ * totvol can become negative even for a valid mesh.
+ * The true value is always the positive value.
+ */
+ if (r_vol) {
+ *r_vol = fabsf(totvol);
+ }
+ if (r_com) {
+ /* Note: Factor 1/4 is applied once for all vertices here.
+ * This also automatically negates the vector if totvol is negative.
+ */
+ if (totvol != 0.0f)
+ mul_v3_fl(r_com, 0.25f / totvol);
+ }
+}
+
+
+/* -------------------------------------------------------------------- */
+
/** \name NGon Tessellation (NGon/Tessface Conversion)
* \{ */