[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