Ejemplo n.º 1
0
/**
 * \brief Compute the covariance matrix of given set of nD coordinates.
 *
 * \param n the dimension of the vectors (and hence, of the covariance matrix to compute).
 * \param cos_vn the nD points to compute covariance from.
 * \param nbr_cos_vn the number of nD coordinates in cos_vn.
 * \param center the center (or mean point) of cos_vn. If NULL, it is assumed cos_vn is already centered.
 * \param use_sample_correction whether to apply sample correction
 *                              (i.e. get 'sample varince' instead of 'population variance').
 * \return r_covmat the computed covariance matrix.
 */
void BLI_covariance_m_vn_ex(
        const int n, const float *cos_vn, const int nbr_cos_vn, const float *center, const bool use_sample_correction,
        float *r_covmat)
{
	/* Note about that division: see https://en.wikipedia.org/wiki/Bessel%27s_correction.
	 * In a nutshell, it must be 1 / (n - 1) for 'sample data', and 1 / n for 'population data'...
	 */
	const float covfac = 1.0f / (float)(use_sample_correction ? nbr_cos_vn - 1 : nbr_cos_vn);

	memset(r_covmat, 0, sizeof(*r_covmat) * (size_t)(n * n));

	CovarianceData data = {
		.cos_vn = cos_vn, .center = center, .r_covmat = r_covmat,
	    .covfac = covfac, .n = n, .nbr_cos_vn = nbr_cos_vn,
	};

	if ((nbr_cos_vn * n * n) >= 10000) {
		BLI_task_parallel_range_ex(0, n * n, &data, NULL, 0, covariance_m_vn_ex_task_cb, 0, false);
	}
	else {
		for (int k = 0; k < n * n; k++) {
			covariance_m_vn_ex_task_cb(&data, NULL, k);
		}
	}
}
Ejemplo n.º 2
0
/**
 * Find nearest vertex and/or edge and/or face, for each vertex (adapted from shrinkwrap.c).
 */
static void get_vert2geom_distance(int numVerts, float (*v_cos)[3],
                                   float *dist_v, float *dist_e, float *dist_f,
                                   DerivedMesh *target, const SpaceTransform *loc2trgt)
{
	Vert2GeomData data = {0};
	Vert2GeomDataChunk data_chunk = {{{0}}};

	BVHTreeFromMesh treeData_v = {NULL};
	BVHTreeFromMesh treeData_e = {NULL};
	BVHTreeFromMesh treeData_f = {NULL};

	if (dist_v) {
		/* Create a bvh-tree of the given target's verts. */
		bvhtree_from_mesh_verts(&treeData_v, target, 0.0, 2, 6);
		if (treeData_v.tree == NULL) {
			OUT_OF_MEMORY();
			return;
		}
	}
	if (dist_e) {
		/* Create a bvh-tree of the given target's edges. */
		bvhtree_from_mesh_edges(&treeData_e, target, 0.0, 2, 6);
		if (treeData_e.tree == NULL) {
			OUT_OF_MEMORY();
			return;
		}
	}
	if (dist_f) {
		/* Create a bvh-tree of the given target's faces. */
		bvhtree_from_mesh_looptri(&treeData_f, target, 0.0, 2, 6);
		if (treeData_f.tree == NULL) {
			OUT_OF_MEMORY();
			return;
		}
	}

	data.v_cos = v_cos;
	data.loc2trgt = loc2trgt;
	data.treeData[0] = &treeData_v;
	data.treeData[1] = &treeData_e;
	data.treeData[2] = &treeData_f;
	data.dist[0] = dist_v;
	data.dist[1] = dist_e;
	data.dist[2] = dist_f;

	BLI_task_parallel_range_ex(
	            0, numVerts, &data, &data_chunk, sizeof(data_chunk), vert2geom_task_cb, numVerts > 10000, false);

	if (dist_v)
		free_bvhtree_from_mesh(&treeData_v);
	if (dist_e)
		free_bvhtree_from_mesh(&treeData_e);
	if (dist_f)
		free_bvhtree_from_mesh(&treeData_f);
}
Ejemplo n.º 3
0
static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
                                  DerivedMesh *dm,
                                  ModifierApplyFlag UNUSED(flag))
{
	UVWarpModifierData *umd = (UVWarpModifierData *) md;
	int numPolys, numLoops;
	MPoly *mpoly;
	MLoop *mloop;
	MLoopUV *mloopuv;
	MDeformVert *dvert;
	int defgrp_index;
	char uvname[MAX_CUSTOMDATA_LAYER_NAME];
	float mat_src[4][4];
	float mat_dst[4][4];
	float imat_dst[4][4];
	float warp_mat[4][4];
	const int axis_u = umd->axis_u;
	const int axis_v = umd->axis_v;

	/* make sure there are UV Maps available */
	if (!CustomData_has_layer(&dm->loopData, CD_MLOOPUV)) {
		return dm;
	}
	else if (ELEM(NULL, umd->object_src, umd->object_dst)) {
		modifier_setError(md, "From/To objects must be set");
		return dm;
	}

	/* make sure anything moving UVs is available */
	matrix_from_obj_pchan(mat_src, umd->object_src, umd->bone_src);
	matrix_from_obj_pchan(mat_dst, umd->object_dst, umd->bone_dst);

	invert_m4_m4(imat_dst, mat_dst);
	mul_m4_m4m4(warp_mat, imat_dst, mat_src);

	/* apply warp */
	if (!is_zero_v2(umd->center)) {
		float mat_cent[4][4];
		float imat_cent[4][4];

		unit_m4(mat_cent);
		mat_cent[3][axis_u] = umd->center[0];
		mat_cent[3][axis_v] = umd->center[1];

		invert_m4_m4(imat_cent, mat_cent);

		mul_m4_m4m4(warp_mat, warp_mat, imat_cent);
		mul_m4_m4m4(warp_mat, mat_cent, warp_mat);
	}

	/* make sure we're using an existing layer */
	CustomData_validate_layer_name(&dm->loopData, CD_MLOOPUV, umd->uvlayer_name, uvname);

	numPolys = dm->getNumPolys(dm);
	numLoops = dm->getNumLoops(dm);

	mpoly = dm->getPolyArray(dm);
	mloop = dm->getLoopArray(dm);
	/* make sure we are not modifying the original UV map */
	mloopuv = CustomData_duplicate_referenced_layer_named(&dm->loopData, CD_MLOOPUV, uvname, numLoops);
	modifier_get_vgroup(ob, dm, umd->vgroup_name, &dvert, &defgrp_index);

	UVWarpData data = {.mpoly = mpoly, .mloop = mloop, .mloopuv = mloopuv,
	                   .dvert = dvert, .defgrp_index = defgrp_index,
	                   .warp_mat = warp_mat, .axis_u = axis_u, .axis_v = axis_v};
	BLI_task_parallel_range_ex(0, numPolys, &data, NULL, 0, uv_warp_compute, numPolys > 1000, false);

	dm->dirty |= DM_DIRTY_TESS_CDLAYERS;

	return dm;
}