[Bf-blender-cvs] [548dfdb] strand_gpu: Merge branch 'master' into mesh_samples
Lukas Tönne
noreply at git.blender.org
Tue Jul 5 09:56:48 CEST 2016
Commit: 548dfdbd315b3a27b3c21fe877e115fbf8cd7215
Author: Lukas Tönne
Date: Tue Jun 28 11:08:46 2016 +0200
Branches: strand_gpu
https://developer.blender.org/rB548dfdbd315b3a27b3c21fe877e115fbf8cd7215
Merge branch 'master' into mesh_samples
===================================================================
===================================================================
diff --cc source/blender/blenkernel/intern/mesh_sample.c
index 537b565,0000000..07ddc42
mode 100644,000000..100644
--- a/source/blender/blenkernel/intern/mesh_sample.c
+++ b/source/blender/blenkernel/intern/mesh_sample.c
@@@ -1,684 -1,0 +1,684 @@@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/mesh_sample.c
+ * \ingroup bke
+ *
+ * Sample a mesh surface or volume and evaluate samples on deformed meshes.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_key_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+#include "BLI_rand.h"
+
+#include "BKE_bvhutils.h"
+#include "BKE_mesh_sample.h"
+#include "BKE_customdata.h"
+#include "BKE_DerivedMesh.h"
+
+#include "BLI_strict_flags.h"
+
+/* ==== Evaluate ==== */
+
+bool BKE_mesh_sample_is_volume_sample(const MeshSample *sample)
+{
+ return sample->orig_verts[0] == 0 && sample->orig_verts[1] == 0;
+}
+
+bool BKE_mesh_sample_eval(DerivedMesh *dm, const MeshSample *sample, float loc[3], float nor[3], float tang[3])
+{
+ MVert *mverts = dm->getVertArray(dm);
+ unsigned int totverts = (unsigned int)dm->getNumVerts(dm);
+ MVert *v1, *v2, *v3;
+
+ zero_v3(loc);
+ zero_v3(nor);
+ zero_v3(tang);
+
+ if (BKE_mesh_sample_is_volume_sample(sample)) {
+ /* VOLUME SAMPLE */
+ copy_v3_v3(loc, sample->orig_weights);
+ }
+ else {
+ /* SURFACE SAMPLE */
+ if (sample->orig_verts[0] >= totverts ||
+ sample->orig_verts[1] >= totverts ||
+ sample->orig_verts[2] >= totverts)
+ return false;
+
+ v1 = &mverts[sample->orig_verts[0]];
+ v2 = &mverts[sample->orig_verts[1]];
+ v3 = &mverts[sample->orig_verts[2]];
+
+ { /* location */
+ madd_v3_v3fl(loc, v1->co, sample->orig_weights[0]);
+ madd_v3_v3fl(loc, v2->co, sample->orig_weights[1]);
+ madd_v3_v3fl(loc, v3->co, sample->orig_weights[2]);
+ }
+
+ { /* normal */
+ float vnor[3];
+
+ normal_short_to_float_v3(vnor, v1->no);
+ madd_v3_v3fl(nor, vnor, sample->orig_weights[0]);
+ normal_short_to_float_v3(vnor, v2->no);
+ madd_v3_v3fl(nor, vnor, sample->orig_weights[1]);
+ normal_short_to_float_v3(vnor, v3->no);
+ madd_v3_v3fl(nor, vnor, sample->orig_weights[2]);
+
+ normalize_v3(nor);
+ }
+
+ { /* tangent */
+ float edge[3];
+
+ /* XXX simply using the v1-v2 edge as a tangent vector for now ...
+ * Eventually mikktspace generated tangents (CD_TANGENT tessface layer)
+ * should be used for consistency, but requires well-defined tessface
+ * indices for the mesh surface samples.
+ */
+
+ sub_v3_v3v3(edge, v2->co, v1->co);
+ /* make edge orthogonal to nor */
+ madd_v3_v3fl(edge, nor, -dot_v3v3(edge, nor));
+ normalize_v3_v3(tang, edge);
+ }
+ }
+
+ return true;
+}
+
+bool BKE_mesh_sample_shapekey(Key *key, KeyBlock *kb, const MeshSample *sample, float loc[3])
+{
+ float *v1, *v2, *v3;
+
+ (void)key; /* Unused in release builds. */
+
+ BLI_assert(key->elemsize == 3 * sizeof(float));
+ BLI_assert(sample->orig_verts[0] < (unsigned int)kb->totelem);
+ BLI_assert(sample->orig_verts[1] < (unsigned int)kb->totelem);
+ BLI_assert(sample->orig_verts[2] < (unsigned int)kb->totelem);
+
+ v1 = (float *)kb->data + sample->orig_verts[0] * 3;
+ v2 = (float *)kb->data + sample->orig_verts[1] * 3;
+ v3 = (float *)kb->data + sample->orig_verts[2] * 3;
+
+ zero_v3(loc);
+ madd_v3_v3fl(loc, v1, sample->orig_weights[0]);
+ madd_v3_v3fl(loc, v2, sample->orig_weights[1]);
+ madd_v3_v3fl(loc, v3, sample->orig_weights[2]);
+
+ /* TODO use optional vgroup weights to determine if a shapeky actually affects the sample */
+ return true;
+}
+
+
+/* ==== Sampling Utilities ==== */
+
+BLI_INLINE void mesh_sample_weights_from_loc(MeshSample *sample, DerivedMesh *dm, int face_index, const float loc[3])
+{
+ MFace *face = &dm->getTessFaceArray(dm)[face_index];
+ unsigned int index[4] = { face->v1, face->v2, face->v3, face->v4 };
+ MVert *mverts = dm->getVertArray(dm);
+
+ float *v1 = mverts[face->v1].co;
+ float *v2 = mverts[face->v2].co;
+ float *v3 = mverts[face->v3].co;
+ float *v4 = face->v4 ? mverts[face->v4].co : NULL;
+ float w[4];
+ int tri[3];
+
+ interp_weights_face_v3_index(tri, w, v1, v2, v3, v4, loc);
+
+ sample->orig_verts[0] = index[tri[0]];
+ sample->orig_verts[1] = index[tri[1]];
+ sample->orig_verts[2] = index[tri[2]];
+ sample->orig_weights[0] = w[tri[0]];
+ sample->orig_weights[1] = w[tri[1]];
+ sample->orig_weights[2] = w[tri[2]];
+}
+
+/* ==== Sampling ==== */
+
+typedef void (*GeneratorFreeFp)(struct MeshSampleGenerator *gen);
+typedef bool (*GeneratorMakeSampleFp)(struct MeshSampleGenerator *gen, struct MeshSample *sample);
+
+typedef struct MeshSampleGenerator
+{
+ GeneratorFreeFp free;
+ GeneratorMakeSampleFp make_sample;
+} MeshSampleGenerator;
+
+static void sample_generator_init(MeshSampleGenerator *gen, GeneratorFreeFp free, GeneratorMakeSampleFp make_sample)
+{
+ gen->free = free;
+ gen->make_sample = make_sample;
+}
+
+/* ------------------------------------------------------------------------- */
+
+//#define USE_DEBUG_COUNT
+
+typedef struct MSurfaceSampleGenerator_Random {
+ MeshSampleGenerator base;
+
+ DerivedMesh *dm;
+ RNG *rng;
+ float *face_weights;
+ float *vertex_weights;
+
+#ifdef USE_DEBUG_COUNT
+ int *debug_count;
+#endif
+} MSurfaceSampleGenerator_Random;
+
+static void generator_random_free(MSurfaceSampleGenerator_Random *gen)
+{
+#ifdef USE_DEBUG_COUNT
+ if (gen->debug_count) {
+ if (gen->face_weights) {
+ int num = gen->dm->getNumTessFaces(gen->dm);
+ int i;
+ int totsamples = 0;
+
+ printf("Surface Sampling (n=%d):\n", num);
+ for (i = 0; i < num; ++i)
+ totsamples += gen->debug_count[i];
+
+ for (i = 0; i < num; ++i) {
+ float weight = i > 0 ? gen->face_weights[i] - gen->face_weights[i-1] : gen->face_weights[i];
+ int samples = gen->debug_count[i];
+ printf(" %d: W = %f, N = %d/%d = %f\n", i, weight, samples, totsamples, (float)samples / (float)totsamples);
+ }
+ }
+ MEM_freeN(gen->debug_count);
+ }
+#endif
+ if (gen->face_weights)
+ MEM_freeN(gen->face_weights);
+ if (gen->vertex_weights)
+ MEM_freeN(gen->vertex_weights);
+ if (gen->rng)
+ BLI_rng_free(gen->rng);
+ MEM_freeN(gen);
+}
+
+/* Find the index in "sum" array before "value" is crossed. */
+BLI_INLINE int weight_array_binary_search(const float *sum, int size, float value)
+{
+ int mid, low = 0, high = size - 1;
+
+ if (value <= 0.0f)
+ return 0;
+
+ while (low < high) {
+ mid = (low + high) >> 1;
+
+ if (sum[mid] < value && value <= sum[mid+1])
+ return mid;
+
+ if (sum[mid] >= value)
+ high = mid - 1;
+ else if (sum[mid] < value)
+ low = mid + 1;
+ else
+ return mid;
+ }
+
+ return low;
+}
+
+static bool generator_random_make_sample(MSurfaceSampleGenerator_Random *gen, MeshSample *sample)
+{
+ DerivedMesh *dm = gen->dm;
+ RNG *rng = gen->rng;
+ MFace *mfaces = dm->getTessFaceArray(dm);
+ int totfaces = dm->getNumTessFaces(dm);
+ int totweights = totfaces * 2;
+
+ int faceindex, triindex, tri;
+ float a, b;
+ MFace *mface;
+
+ if (gen->face_weights)
+ triindex = weight_array_binary_search(gen->face_weights, totweights, BLI_rng_get_float(rng));
+ else
+ triindex = BLI_rng_get_int(rng) % totweights;
+ faceindex = triindex >> 1;
+#ifdef USE_DEBUG_COUNT
+ if (gen->debug_count)
+ gen->debug_count[faceindex] += 1;
+#endif
+ tri = triindex % 2;
+ a = BLI_rng_get_float(rng);
+ b = BLI_rng_get_float(rng);
+
+ mface = &mfaces[faceindex];
+
+ if (tri == 0) {
+ sample->orig_verts[0] = mface->v1;
+ sample->orig_verts[1] = mface->v2;
+ sample->orig_verts[2] = mface->v3;
+ }
+ else {
+ sample->orig_verts[0] = mface->v1;
+ sample->orig_verts[1] = mface->v3;
+ sample->orig_verts[2] = mface->v4;
+ }
+
+ if (a + b > 1.0f) {
+ a = 1.0f - a;
+ b = 1.0f - b;
+ }
+ sample->orig_weights[0] = 1.0f - (a + b);
+ sample->orig_weights[1] = a;
+ sample->orig_weights[2] = b;
+
+ return true;
+}
+
+BLI_INLINE void face_weight(DerivedMesh *dm, MFace *face, MeshSampleVertexWeightFp vertex_weight_cb, void *userdata, float weight[2])
+{
+ MVert *mverts = dm->getVertArray(dm);
+ MVert *v1 = &mverts[face->v1];
+ MVert *v2 = &mverts[face->v2];
+ MVert *v3 = &mverts[face->v3];
+ MVert *v4 = NULL;
+
+ weight[0] = area_tri_v3(v1->co, v2->co, v3->co);
+
+ if (face->v4) {
+ v4 = &mverts[face->v4];
+ weight[1] = area_tri_v3(v1->co, v3->co, v4->co);
+ }
+ else
+ weight[1] = 0.0f;
+
+ if (vertex_weight_cb) {
+ float w1 = vertex_weight_cb(dm, v1, face->v1, userdata);
+ float w2 = vertex_weight_cb(dm, v2, face->v2, userdata);
+ float w3 = vertex_weight_cb(dm, v3, face->v3, userdata);
+
+ weight[0] *= (w1 + w2 + w3) / 3.0f;
+
+ if (v4) {
+ float w4 = vertex_weight_cb(dm, v4, face->v4, userdata);
+ weight[1] *= (w1 + w3 + w4) / 3.0f;
+ }
+ }
+}
+
+MeshSampleGenerator *BKE_mesh_sample_gen_surface_random_ex(DerivedMesh *dm, unsigned int seed,
+ MeshSampleVertexWeightFp vertex_weight_cb, void *userdata, bool use_facearea)
+{
+ MSurfaceSampleGenerator_Random *gen;
+
+ DM_ensure_normals(dm);
+ DM_ens
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list