Commit: 5f6d9e301efc5f9627941c71ba0f464901e71a4e
Author: Lukas Tönne
Date:   Fri Aug 21 15:13:17 2015 +0200
Branches: strand_gpu
https://developer.blender.org/rB5f6d9e301efc5f9627941c71ba0f464901e71a4e

Implementation of Volume Sampling on meshes.

Based on the ray casting technique described here: http://www.joesfer.com/?p=84

Volume samples currently are not bound to mesh deformation in any way, they are
simple object-space locations. Potentially a harmonic weight approach as in
mesh cages could be used.

===================================================================

M       source/blender/blenkernel/BKE_mesh_sample.h
M       source/blender/blenkernel/intern/mesh_sample.c
M       source/blender/makesdna/DNA_meshdata_types.h
M       source/blender/makesrna/intern/CMakeLists.txt
M       source/blender/makesrna/intern/makesrna.c
M       source/blender/makesrna/intern/rna_internal.h
D       source/blender/makesrna/intern/rna_mesh_sample.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_mesh_sample.h 
b/source/blender/blenkernel/BKE_mesh_sample.h
index 9e34441..3b2e1e1 100644
--- a/source/blender/blenkernel/BKE_mesh_sample.h
+++ b/source/blender/blenkernel/BKE_mesh_sample.h
@@ -28,32 +28,37 @@
 struct DerivedMesh;
 struct Key;
 struct KeyBlock;
+struct MFace;
+struct MVert;
 
-struct MSurfaceSample;
+struct MeshSample;
+struct MeshSampleGenerator;
+
+typedef struct MeshSampleGenerator MeshSampleGenerator;
+typedef float (*MeshSampleVertexWeightFp)(struct DerivedMesh *dm, struct MVert 
*vert, unsigned int index, void *userdata);
+typedef bool (*MeshSampleRayFp)(void *userdata, float ray_start[3], float 
ray_end[3]);
 
 /* ==== Evaluate ==== */
 
-bool BKE_mesh_sample_eval(struct DerivedMesh *dm, const struct MSurfaceSample 
*sample, float loc[3], float nor[3]);
-bool BKE_mesh_sample_shapekey(struct Key *key, struct KeyBlock *kb, const 
struct MSurfaceSample *sample, float loc[3]);
+bool BKE_mesh_sample_is_volume_sample(const struct MeshSample *sample);
+
+bool BKE_mesh_sample_eval(struct DerivedMesh *dm, const struct MeshSample 
*sample, float loc[3], float nor[3], float tang[3]);
+bool BKE_mesh_sample_shapekey(struct Key *key, struct KeyBlock *kb, const 
struct MeshSample *sample, float loc[3]);
 
 
 /* ==== Sampling ==== */
 
-/* Storage descriptor to allow generic data storage by arbitrary algorithms */
-typedef struct MSurfaceSampleStorage {
-       bool (*store_sample)(void *data, int capacity, int index, const struct 
MSurfaceSample *sample);
-       void *data;
-       int capacity;
-       int free_data;
-} MSurfaceSampleStorage;
+/* face_weights is optional */
+struct MeshSampleGenerator *BKE_mesh_sample_gen_surface_random(struct 
DerivedMesh *dm, unsigned int seed);
+struct MeshSampleGenerator *BKE_mesh_sample_gen_surface_random_ex(struct 
DerivedMesh *dm, unsigned int seed,
+                                                                      
MeshSampleVertexWeightFp vertex_weight_cb, void *userdata, bool use_facearea);
+
+struct MeshSampleGenerator *BKE_mesh_sample_gen_surface_raycast(struct 
DerivedMesh *dm, MeshSampleRayFp ray_cb, void *userdata);
 
-void BKE_mesh_sample_storage_single(struct MSurfaceSampleStorage *storage, 
struct MSurfaceSample *sample);
-void BKE_mesh_sample_storage_array(struct MSurfaceSampleStorage *storage, 
struct MSurfaceSample *samples, int capacity);
-void BKE_mesh_sample_storage_release(struct MSurfaceSampleStorage *storage);
+struct MeshSampleGenerator *BKE_mesh_sample_gen_volume_random_bbray(struct 
DerivedMesh *dm, unsigned int seed, float density);
 
-int BKE_mesh_sample_generate_random(struct MSurfaceSampleStorage *dst, struct 
DerivedMesh *dm, unsigned int seed, int totsample);
+void BKE_mesh_sample_free_generator(struct MeshSampleGenerator *gen);
 
-typedef bool (*MeshSampleRayCallback)(void *userdata, float ray_start[3], 
float ray_end[3]);
-int BKE_mesh_sample_generate_raycast(struct MSurfaceSampleStorage *dst, struct 
DerivedMesh *dm, MeshSampleRayCallback ray_cb, void *userdata, int totsample);
+bool BKE_mesh_sample_generate(struct MeshSampleGenerator *gen, struct 
MeshSample *sample);
 
 #endif  /* __BKE_MESH_SAMPLE_H__ */
diff --git a/source/blender/blenkernel/intern/mesh_sample.c 
b/source/blender/blenkernel/intern/mesh_sample.c
index ae49668..537b565 100644
--- a/source/blender/blenkernel/intern/mesh_sample.c
+++ b/source/blender/blenkernel/intern/mesh_sample.c
@@ -43,45 +43,80 @@
 
 /* ==== Evaluate ==== */
 
-bool BKE_mesh_sample_eval(DerivedMesh *dm, const MSurfaceSample *sample, float 
loc[3], float nor[3])
+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;
-       float vnor[3];
        
        zero_v3(loc);
        zero_v3(nor);
+       zero_v3(tang);
        
-       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]];
-       
-       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_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);
+       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 MSurfaceSample 
*sample, float loc[3])
+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);
@@ -103,7 +138,7 @@ bool BKE_mesh_sample_shapekey(Key *key, KeyBlock *kb, const 
MSurfaceSample *samp
 
 /* ==== Sampling Utilities ==== */
 
-BLI_INLINE void mesh_sample_weights_from_loc(MSurfaceSample *sample, 
DerivedMesh *dm, int face_index, const float loc[3])
+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 };
@@ -128,108 +163,278 @@ BLI_INLINE void 
mesh_sample_weights_from_loc(MSurfaceSample *sample, DerivedMesh
 
 /* ==== Sampling ==== */
 
-static bool mesh_sample_store_array_sample(void *vdata, int capacity, int 
index, const MSurfaceSample *sample)
+typedef void (*GeneratorFreeFp)(struct MeshSampleGenerator *gen);
+typedef bool (*GeneratorMakeSampleFp)(struct MeshSampleGenerator *gen, struct 
MeshSample *sample);
+
+typedef struct MeshSampleGenerator
 {
-       MSurfaceSample *data = vdata;
-       if (index >= capacity)
-               return false;
-       
-       data[index] = *sample;
-       return true;
-}
+       GeneratorFreeFp free;
+       GeneratorMakeSampleFp make_sample;
+} MeshSampleGenerator;
 
-void BKE_mesh_sample_storage_single(MSurfaceSampleStorage *storage, 
MSurfaceSample *sample)
+static void sample_generator_init(MeshSampleGenerator *gen, GeneratorFreeFp 
free, GeneratorMakeSampleFp make_sample)
 {
-       /* handled as just a special array case with capacity = 1 */
-       storage->store_sample = mesh_sample_store_array_sample;
-       storage->capacity = 1;
-       storage->data = sample;
-       storage->free_data = false;
+       gen->free = free;
+       gen->make_sample = make_sample;
 }
 
-void BKE_mesh_sample_storage_array(MSurfaceSampleStorage *storage, 
MSurfaceSample *samples, int capacity)
+/* ------------------------------------------------------------------------- */
+
+//#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)
 {
-       storage->store_sample = mesh_sample_store_array_sample;
-       storage->capacity = capacity;
-       storage->data = samples;
-       storage->free_data = false;
+#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);
 }
 
-void BKE_mesh_sample_storage_release(MSurfaceSampleStorage *storage)
+/* Find the index in "sum" array before "value" is crossed. */
+BLI_INLINE int weight_array_binary_search(const float *sum, int size, float 
value)
 {
-       if (storage->free_data)
-               MEM_freeN(storage->data);
+       int mid, low = 0, high = size - 1;
+       
+       if (value <= 0.0f)
+               return 0;
+       
+       while (low < high) {
+               mid =

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to