[Bf-blender-cvs] [443b117] temp_custom_loop_normals: First basic code for supporting custom loop normals.
Bastien Montagne
noreply at git.blender.org
Wed Aug 6 21:36:31 CEST 2014
Commit: 443b11748865def4343e9ba18dd00db0097ea0f2
Author: Bastien Montagne
Date: Wed Jun 4 19:25:24 2014 +0200
Branches: temp_custom_loop_normals
https://developer.blender.org/rB443b11748865def4343e9ba18dd00db0097ea0f2
First basic code for supporting custom loop normals.
This only affects Object mode currently, and is more proof-of-concept than anything else.
Next step: do same thing for bmesh!
===================================================================
M source/blender/blenkernel/BKE_mesh.h
M source/blender/blenkernel/intern/cdderivedmesh.c
M source/blender/blenkernel/intern/mesh_evaluate.c
M source/blender/makesrna/intern/rna_mesh_api.c
===================================================================
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index d0c268d..6869539 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -36,6 +36,8 @@ struct BoundBox;
struct DispList;
struct EdgeHash;
struct ListBase;
+struct LinkNode;
+struct MemArena;
struct BMEditMesh;
struct BMesh;
struct Main;
@@ -173,10 +175,6 @@ void BKE_mesh_calc_normals_tessface(
struct MVert *mverts, int numVerts,
struct MFace *mfaces, int numFaces,
float (*r_faceNors)[3]);
-void BKE_mesh_normals_loop_split(
- struct MVert *mverts, const int numVerts, struct MEdge *medges, const int numEdges,
- struct MLoop *mloops, float (*r_loopnors)[3], const int numLoops,
- struct MPoly *mpolys, float (*polynors)[3], const int numPolys, float split_angle);
void BKE_mesh_loop_tangents_ex(
struct MVert *mverts, const int numVerts, struct MLoop *mloops, float (*r_looptangent)[4], float (*loopnors)[3],
struct MLoopUV *loopuv, const int numLoops, struct MPoly *mpolys, const int numPolys,
@@ -184,6 +182,29 @@ void BKE_mesh_loop_tangents_ex(
void BKE_mesh_loop_tangents(
struct Mesh *mesh, const char *uvmap, float (*r_looptangents)[4], struct ReportList *reports);
+#include "BLI_linklist.h"
+#include "BLI_memarena.h"
+
+typedef struct MLoopNorSpace {
+ float vec_lnor[3]; /* Automatically computed loop normal. */
+ float vec_ref[3]; /* Reference vector, orthogonal to vec_lnor. */
+ float vec_ortho[3]; /* Third vector, orthogonal to vec_lnor and vec_ref. */
+ float angle; /* Reference angle, around vec_lnor, in ]0, 2pi] range (0.0 marks that space as invalid). */
+ LinkNode *loops; /* All indices (uint_in_ptr) of loops using this lnor space (i.e. smooth fan of loops). */
+} MLoopNorSpace;
+typedef struct MLoopsNorSpaces {
+ MLoopNorSpace **lspaces;
+ MemArena *mem;
+} MLoopsNorSpaces;
+void BKE_init_loops_normal_spaces(MLoopsNorSpaces *lnors_spaces, const int numLoops);
+void BKE_free_loops_normal_spaces(MLoopsNorSpaces *lnors_spaces);
+
+void BKE_mesh_normals_loop_split(
+ struct MVert *mverts, const int numVerts, struct MEdge *medges, const int numEdges,
+ struct MLoop *mloops, float (*r_loopnors)[3], const int numLoops,
+ struct MPoly *mpolys, float (*polynors)[3], const int numPolys, float split_angle,
+ MLoopsNorSpaces *r_lnor_spaces, const float (*clnors_data)[2]);
+
void BKE_mesh_calc_poly_normal(
struct MPoly *mpoly, struct MLoop *loopstart,
struct MVert *mvarray, float no[3]);
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index ca4a4b3..e7af8ef 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -2542,8 +2542,39 @@ void CDDM_calc_loop_normals(DerivedMesh *dm, const float split_angle)
dm->dirty &= ~DM_DIRTY_NORMALS;
- BKE_mesh_normals_loop_split(mverts, numVerts, medges, numEdges, mloops, lnors, numLoops,
- mpolys, pnors, numPolys, split_angle);
+ {
+ MLoopsNorSpaces lnors_spaces = {NULL};
+ int i;
+ float (*clnor_data)[2] = MEM_mallocN(sizeof(*clnor_data) * (size_t)numLoops, __func__);
+
+ for (i = 0; i < numLoops; i++) {
+ clnor_data[i][0] = 0.7f;
+ clnor_data[i][1] = 0.5f;
+ }
+
+ BKE_mesh_normals_loop_split(mverts, numVerts, medges, numEdges, mloops, lnors, numLoops,
+ mpolys, pnors, numPolys, split_angle, &lnors_spaces, clnor_data);
+ for (i = 0; i < numLoops; i++) {
+ if (lnors_spaces.lspaces[i]) {
+ LinkNode *loops = lnors_spaces.lspaces[i]->loops;
+ printf("Loop %d uses lnor space %p:\n", i, lnors_spaces.lspaces[i]);
+ print_v3("\tfinal lnor:", lnors[i]);
+ print_v3("\tauto lnor:", lnors_spaces.lspaces[i]->vec_lnor);
+ print_v3("\tref_vec:", lnors_spaces.lspaces[i]->vec_ref);
+ printf("\tangle: %f\n\tloops: %p\n", lnors_spaces.lspaces[i]->angle, lnors_spaces.lspaces[i]->loops);
+ printf("\t\t(shared with loops");
+ while(loops) {
+ printf(" %d", GET_INT_FROM_POINTER(loops->link));
+ loops = loops->next;
+ }
+ printf(")\n");
+ }
+ else {
+ printf("Loop %d has no lnor space\n", i);
+ }
+ }
+ BKE_free_loops_normal_spaces(&lnors_spaces);
+ }
}
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index d244dcc..01dfffc 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -316,13 +316,155 @@ void BKE_mesh_calc_normals_tessface(MVert *mverts, int numVerts, MFace *mfaces,
MEM_freeN(fnors);
}
+void BKE_init_loops_normal_spaces(MLoopsNorSpaces *lnors_spaces, const int numLoops)
+{
+ MemArena *mem = lnors_spaces->mem = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ lnors_spaces->lspaces = BLI_memarena_calloc(mem, sizeof(MLoopNorSpace *) * (size_t)numLoops);
+}
+
+void BKE_free_loops_normal_spaces(MLoopsNorSpaces *lnors_spaces)
+{
+ BLI_memarena_free(lnors_spaces->mem);
+ lnors_spaces->lspaces = NULL;
+ lnors_spaces->mem = NULL;
+}
+
+static MLoopNorSpace *lnor_space_create(MLoopsNorSpaces *lnors_spaces)
+{
+ return BLI_memarena_calloc(lnors_spaces->mem, sizeof(MLoopNorSpace));
+}
+
+/* Should only be called once.
+ * Beware, this modifies ref_vec and other_vec in place!
+ * Might set *lnor_space to NULL in case no valid space can be generated.
+ */
+static void lnor_space_define(MLoopNorSpace *lnor_space, const float lnor[3], float vec_ref[3], float vec_other[3])
+{
+ float tvec[3], dtp;
+ const float pi2 = (float)M_PI * 2.0f;
+
+ /* Project ref_vec on lnor's ortho plane. */
+ dtp = dot_v3v3(vec_ref, lnor);
+ if (fabsf(dtp) > (1.0f - 1e-8f)) {
+ /* If ref_vec is too much aligned with lnor, we can't build lnor space, tag it as invalid and abort. */
+ lnor_space->angle = 0.0f;
+ return;
+ }
+ mul_v3_v3fl(tvec, lnor, dtp);
+ sub_v3_v3(vec_ref, tvec);
+ normalize_v3_v3(lnor_space->vec_ref, vec_ref);
+
+ copy_v3_v3(lnor_space->vec_lnor, lnor);
+
+ cross_v3_v3v3(tvec, lnor, lnor_space->vec_ref);
+ normalize_v3_v3(lnor_space->vec_ortho, tvec);
+
+ lnor_space->angle = pi2;
+
+ if (vec_other) {
+ /* Project other_vec on lnor's ortho plane. */
+ dtp = dot_v3v3(vec_other, lnor);
+ if (fabsf(dtp) > (1.0f - 1e-8f)) {
+ /* If other_vec is too much aligned with lnor, we can't build lnor space, tag it as invalid and abort. */
+ lnor_space->angle = 0.0f;
+ return;
+ }
+ mul_v3_v3fl(tvec, lnor, dtp);
+ sub_v3_v3(vec_other, tvec);
+ normalize_v3(vec_other);
+
+ /* Angle between ref_vec and other_vec. */
+ dtp = dot_v3v3(vec_ref, vec_other);
+ if (dtp < (1.0f - 1e-8f)) {
+ const float angle = saacos(dtp);
+ lnor_space->angle = (dot_v3v3(lnor_space->vec_ortho, vec_other) < 0.0f) ? pi2 - angle : angle;
+ }
+ }
+}
+
+static void lnor_space_add_loop(MLoopsNorSpaces *lnors_spaces, MLoopNorSpace *lnor_space, MLoop *ml, int ml_index)
+{
+ if (lnor_space == NULL) {
+ return;
+ }
+
+ lnors_spaces->lspaces[ml_index] = lnor_space;
+ if (ml && lnor_space) {
+ BLI_linklist_prepend_arena(&lnor_space->loops, SET_INT_IN_POINTER(ml_index), lnors_spaces->mem);
+ }
+}
+
+static void BKE_lnor_space_custom_data_to_normal(MLoopNorSpace *lnor_space, float r_custom_lnor[3],
+ const float clnor_data[2])
+{
+ /* NOP custom normal data or invalid lnor space, return. */
+ if (clnor_data[0] == 1.0f || lnor_space->angle == 0.0f) {
+ copy_v3_v3(r_custom_lnor, lnor_space->vec_lnor);
+ return;
+ }
+
+ {
+ const float cosfac = clnor_data[0];
+ const float sinfac = sqrtf(1.0f - cosfac * cosfac);
+ const float phifac = clnor_data[1];
+ const float pi2 = (float)M_PI * 2.0f;
+
+ mul_v3_v3fl(r_custom_lnor, lnor_space->vec_lnor, cosfac);
+
+ if (phifac == 0.0f) {
+ madd_v3_v3fl(r_custom_lnor, lnor_space->vec_ref, sinfac);
+ }
+ else {
+ const float phi = phifac * (phifac > 0.0f ? lnor_space->angle : pi2 - lnor_space->angle);
+ madd_v3_v3fl(r_custom_lnor, lnor_space->vec_ref, sinfac * cosf(phi));
+ madd_v3_v3fl(r_custom_lnor, lnor_space->vec_ortho, sinfac * sinf(phi));
+ }
+ }
+}
+
+static void BKE_lnor_space_custom_normal_to_data(MLoopNorSpace *lnor_space, const float custom_lnor[3],
+ float r_custom_data[2])
+{
+ if (equals_v3v3(lnor_space->vec_lnor, custom_lnor)) {
+ r_custom_data[0] = 1.0f;
+ r_custom_data[1] = 0.0f;
+ return;
+ }
+
+ {
+ const float co = dot_v3v3(lnor_space->vec_ref, custom_lnor);
+ const float pi2 = (float)M_PI * 2.0f;
+
+ r_custom_data[0] = dot_v3v3(lnor_space->vec_lnor, custom_lnor);
+
+ if (co > (1.0f - 1e-6f)) {
+ r_custom_data[1] = 0.0f;
+ }
+ else {
+ float phi = saacos(co);
+
+ if (dot_v3v3(lnor_space->vec_ortho, custom_lnor) < 0.0f) {
+ phi = pi2 - phi;
+ }
+
+ if (phi > lnor_space->angle) {
+ r_custom_data[1] = -(pi2 - phi) / (pi2 - lnor_space->angle);
+ }
+ else {
+ r_custom_data[1] = phi / lnor_space->angle;
+ }
+ }
+ }
+}
+
/**
* Compute split normals, i.e. vertex normals associated with each poly (hence 'loop normals').
* Useful to materialize sharp edges (or non-smooth faces) without actually modifying the geometry (splitting edges).
*/
-void BKE_mesh_normals_loop_split(MVert *mverts, const int UNUSED(numVerts), MEdge *medges, const int numEdges,
+void BKE_mesh_normals_loop_split(MVert *mverts, const int numVerts, MEdge *medges, const int numEdges,
MLoop *mloops, float (*r_loopnors)[3], const int numLoops,
- MPoly *mpolys, float (*polynors)[3], const int numPolys, float split_angle)
+ MPoly *mpolys, float (*polynors)[3], const int numPolys, float split_angle,
+ MLoopsNorSpaces *r_lnor_spaces, const float (*clnors_data)[2])
{
#define INDEX_UNSET INT_MIN
#define INDEX_INVALID -1
@@ -344,9 +486,12 @@ void BKE_mesh_normals_loop_split(MVert *mverts, const int UNUSED(numVerts), MEdg
int *loop_to_poly = MEM_mallocN(sizeof(int) * (size_t)numLoops, __func__);
MPoly *mp;
- int mp_index
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list