static void rna_Mesh_normals_split_custom_do(Mesh *mesh, float (*custom_loopnors)[3], const bool use_vertices)
{
	float (*polynors)[3];
	short (*clnors)[2];
	const int numloops = mesh->totloop;
	bool free_polynors = false;

	clnors = CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL);
	if (clnors) {
		memset(clnors, 0, sizeof(*clnors) * numloops);
	}
	else {
		clnors = CustomData_add_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL, CD_DEFAULT, NULL, numloops);
	}

	if (CustomData_has_layer(&mesh->pdata, CD_NORMAL)) {
		polynors = CustomData_get_layer(&mesh->pdata, CD_NORMAL);
	}
	else {
		polynors = MEM_mallocN(sizeof(float[3]) * mesh->totpoly, __func__);
		BKE_mesh_calc_normals_poly(
		            mesh->mvert, NULL, mesh->totvert,
		            mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly, polynors, false);
		free_polynors = true;
	}

	if (use_vertices) {
		BKE_mesh_normals_loop_custom_from_vertices_set(
		        mesh->mvert, custom_loopnors, mesh->totvert, mesh->medge, mesh->totedge, mesh->mloop, mesh->totloop,
		        mesh->mpoly, (const float (*)[3])polynors, mesh->totpoly, clnors);
	}
	else {
		BKE_mesh_normals_loop_custom_set(
		        mesh->mvert, mesh->totvert, mesh->medge, mesh->totedge, mesh->mloop, custom_loopnors, mesh->totloop,
		        mesh->mpoly, (const float (*)[3])polynors, mesh->totpoly, clnors);
	}

	if (free_polynors) {
		MEM_freeN(polynors);
	}
}
static void data_transfer_dtdata_type_postprocess(
        Object *UNUSED(ob_src), Object *UNUSED(ob_dst), DerivedMesh *UNUSED(dm_src), DerivedMesh *dm_dst, Mesh *me_dst,
        const int dtdata_type, const bool changed)
{
	if (dtdata_type == DT_TYPE_LNOR) {
		/* Bake edited destination loop normals into custom normals again. */
		MVert *verts_dst = dm_dst ? dm_dst->getVertArray(dm_dst) : me_dst->mvert;
		const int num_verts_dst = dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert;
		MEdge *edges_dst = dm_dst ? dm_dst->getEdgeArray(dm_dst) : me_dst->medge;
		const int num_edges_dst = dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge;
		MPoly *polys_dst = dm_dst ? dm_dst->getPolyArray(dm_dst) : me_dst->mpoly;
		const int num_polys_dst = dm_dst ? dm_dst->getNumPolys(dm_dst) : me_dst->totpoly;
		MLoop *loops_dst = dm_dst ? dm_dst->getLoopArray(dm_dst) : me_dst->mloop;
		const int num_loops_dst = dm_dst ? dm_dst->getNumLoops(dm_dst) : me_dst->totloop;
		CustomData *pdata_dst = dm_dst ? dm_dst->getPolyDataLayout(dm_dst) : &me_dst->pdata;
		CustomData *ldata_dst = dm_dst ? dm_dst->getLoopDataLayout(dm_dst) : &me_dst->ldata;

		const float (*poly_nors_dst)[3] = CustomData_get_layer(pdata_dst, CD_NORMAL);
		float (*loop_nors_dst)[3] = CustomData_get_layer(ldata_dst, CD_NORMAL);
		short (*custom_nors_dst)[2] = CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL);

		BLI_assert(poly_nors_dst);

		if (!changed) {
			return;
		}

		if (!custom_nors_dst) {
			custom_nors_dst = CustomData_add_layer(ldata_dst, CD_CUSTOMLOOPNORMAL, CD_CALLOC, NULL, num_loops_dst);
		}

		/* Note loop_nors_dst contains our custom normals as transferred from source... */
		BKE_mesh_normals_loop_custom_set(verts_dst, num_verts_dst, edges_dst, num_edges_dst,
		                                 loops_dst, loop_nors_dst, num_loops_dst,
		                                 polys_dst, poly_nors_dst, num_polys_dst,
		                                 custom_nors_dst);
	}
}
Exemple #3
0
static void normalEditModifier_do_directional(
        NormalEditModifierData *enmd, Object *ob, DerivedMesh *dm,
        short (*clnors)[2], float (*loopnors)[3], float (*polynors)[3],
        const short mix_mode, const float mix_factor, const float mix_limit,
        MDeformVert *dvert, const int defgrp_index, const bool use_invert_vgroup,
        MVert *mvert, const int num_verts, MEdge *medge, const int num_edges,
        MLoop *mloop, const int num_loops, MPoly *mpoly, const int num_polys)
{
	const bool use_parallel_normals = (enmd->flag & MOD_NORMALEDIT_USE_DIRECTION_PARALLEL) != 0;

	float (*cos)[3] = MEM_malloc_arrayN((size_t)num_verts, sizeof(*cos), __func__);
	float (*nos)[3] = MEM_malloc_arrayN((size_t)num_loops, sizeof(*nos), __func__);

	float target_co[3];
	int i;

	dm->getVertCos(dm, cos);

	/* Get target's center coordinates in ob local coordinates. */
	{
		float mat[4][4];

		invert_m4_m4(mat, ob->obmat);
		mul_m4_m4m4(mat, mat, enmd->target->obmat);
		copy_v3_v3(target_co, mat[3]);
	}

	if (use_parallel_normals) {
		float no[3];

		sub_v3_v3v3(no, target_co, enmd->offset);
		normalize_v3(no);

		for (i = num_loops; i--; ) {
			copy_v3_v3(nos[i], no);
		}
	}
	else {
		BLI_bitmap *done_verts = BLI_BITMAP_NEW((size_t)num_verts, __func__);
		MLoop *ml;
		float (*no)[3];

		/* We reuse cos to now store the 'to target' normal of the verts! */
		for (i = num_loops, no = nos, ml = mloop; i--; no++, ml++) {
			const int vidx = ml->v;
			float *co = cos[vidx];

			if (!BLI_BITMAP_TEST(done_verts, vidx)) {
				sub_v3_v3v3(co, target_co, co);
				normalize_v3(co);

				BLI_BITMAP_ENABLE(done_verts, vidx);
			}

			copy_v3_v3(*no, co);
		}

		MEM_freeN(done_verts);
	}

	if (loopnors) {
		mix_normals(mix_factor, dvert, defgrp_index, use_invert_vgroup,
		            mix_limit, mix_mode, num_verts, mloop, loopnors, nos, num_loops);
	}

	if (polygons_check_flip(mloop, nos, dm->getLoopDataLayout(dm), mpoly, polynors, num_polys)) {
		dm->dirty |= DM_DIRTY_TESS_CDLAYERS;
	}

	BKE_mesh_normals_loop_custom_set(mvert, num_verts, medge, num_edges, mloop, nos, num_loops,
	                                 mpoly, (const float(*)[3])polynors, num_polys, clnors);

	MEM_freeN(cos);
	MEM_freeN(nos);
}
Exemple #4
0
static void normalEditModifier_do_radial(
        NormalEditModifierData *enmd, Object *ob, DerivedMesh *dm,
        short (*clnors)[2], float (*loopnors)[3], float (*polynors)[3],
        const short mix_mode, const float mix_factor, const float mix_limit,
        MDeformVert *dvert, const int defgrp_index, const bool use_invert_vgroup,
        MVert *mvert, const int num_verts, MEdge *medge, const int num_edges,
        MLoop *mloop, const int num_loops, MPoly *mpoly, const int num_polys)
{
	int i;

	float (*cos)[3] = MEM_malloc_arrayN((size_t)num_verts, sizeof(*cos), __func__);
	float (*nos)[3] = MEM_malloc_arrayN((size_t)num_loops, sizeof(*nos), __func__);
	float size[3];

	BLI_bitmap *done_verts = BLI_BITMAP_NEW((size_t)num_verts, __func__);

	generate_vert_coordinates(dm, ob, enmd->target, enmd->offset, num_verts, cos, size);

	/**
	 * size gives us our spheroid coefficients ``(A, B, C)``.
	 * Then, we want to find out for each vert its (a, b, c) triple (proportional to (A, B, C) one).
	 *
	 * Ellipsoid basic equation: ``(x^2/a^2) + (y^2/b^2) + (z^2/c^2) = 1.``
	 * Since we want to find (a, b, c) matching this equation and proportional to (A, B, C), we can do:
	 * <pre>
	 *     m = B / A
	 *     n = C / A
	 * </pre>
	 *
	 * hence:
	 * <pre>
	 *     (x^2/a^2) + (y^2/b^2) + (z^2/c^2) = 1
	 *  -> b^2*c^2*x^2 + a^2*c^2*y^2 + a^2*b^2*z^2 = a^2*b^2*c^2
	 *     b = ma
	 *     c = na
	 *  -> m^2*a^2*n^2*a^2*x^2 + a^2*n^2*a^2*y^2 + a^2*m^2*a^2*z^2 = a^2*m^2*a^2*n^2*a^2
	 *  -> m^2*n^2*a^4*x^2 + n^2*a^4*y^2 + m^2*a^4*z^2 = m^2*n^2*a^6
	 *  -> a^2 = (m^2*n^2*x^2 + n^2y^2 + m^2z^2) / (m^2*n^2) = x^2 + (y^2 / m^2) + (z^2 / n^2)
	 *  -> b^2 = (m^2*n^2*x^2 + n^2y^2 + m^2z^2) / (n^2)     = (m^2 * x^2) + y^2 + (m^2 * z^2 / n^2)
	 *  -> c^2 = (m^2*n^2*x^2 + n^2y^2 + m^2z^2) / (m^2)     = (n^2 * x^2) + (n^2 * y^2 / m^2) + z^2
	 * </pre>
	 *
	 * All we have to do now is compute normal of the spheroid at that point:
	 * <pre>
	 *     n = (x / a^2, y / b^2, z / c^2)
	 * </pre>
	 * And we are done!
	 */
	{
		const float a = size[0], b = size[1], c = size[2];
		const float m2 = (b * b) / (a * a);
		const float n2 = (c * c) / (a * a);

		MLoop *ml;
		float (*no)[3];

		/* We reuse cos to now store the ellipsoid-normal of the verts! */
		for (i = num_loops, ml = mloop, no = nos; i-- ; ml++, no++) {
			const int vidx = ml->v;
			float *co = cos[vidx];

			if (!BLI_BITMAP_TEST(done_verts, vidx)) {
				const float x2 = co[0] * co[0];
				const float y2 = co[1] * co[1];
				const float z2 = co[2] * co[2];
				const float a2 = x2 + (y2 / m2) + (z2 / n2);
				const float b2 = (m2 * x2) + y2 + (m2 * z2 / n2);
				const float c2 = (n2 * x2) + (n2 * y2 / m2) + z2;

				co[0] /= a2;
				co[1] /= b2;
				co[2] /= c2;
				normalize_v3(co);

				BLI_BITMAP_ENABLE(done_verts, vidx);
			}
			copy_v3_v3(*no, co);
		}
	}

	if (loopnors) {
		mix_normals(mix_factor, dvert, defgrp_index, use_invert_vgroup,
		            mix_limit, mix_mode, num_verts, mloop, loopnors, nos, num_loops);
	}

	if (polygons_check_flip(mloop, nos, dm->getLoopDataLayout(dm), mpoly, polynors, num_polys)) {
		dm->dirty |= DM_DIRTY_TESS_CDLAYERS;
		/* We need to recompute vertex normals! */
		dm->calcNormals(dm);
	}

	BKE_mesh_normals_loop_custom_set(mvert, num_verts, medge, num_edges, mloop, nos, num_loops,
	                                 mpoly, (const float(*)[3])polynors, num_polys, clnors);

	MEM_freeN(cos);
	MEM_freeN(nos);
	MEM_freeN(done_verts);
}