Commit: e490bfc37e233b89c51ffdbe9811fe28a45081e7
Author: Lukas Tönne
Date:   Tue Dec 2 17:26:25 2014 +0100
Branches: hair_immediate_fixes
https://developer.blender.org/rBe490bfc37e233b89c51ffdbe9811fe28a45081e7

Constrain hair root vertices to their mesh location after applying tools.

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

M       source/blender/blenkernel/BKE_edithair.h
M       source/blender/blenkernel/intern/edithair.c
M       source/blender/bmesh/intern/bmesh_interp.c
M       source/blender/bmesh/intern/bmesh_interp.h
M       source/blender/bmesh/intern/bmesh_strands_conv.c
M       source/blender/editors/hair/hair_edit.c
M       source/blender/editors/hair/hair_stroke.c

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

diff --git a/source/blender/blenkernel/BKE_edithair.h 
b/source/blender/blenkernel/BKE_edithair.h
index 3c78021..5653047 100644
--- a/source/blender/blenkernel/BKE_edithair.h
+++ b/source/blender/blenkernel/BKE_edithair.h
@@ -40,6 +40,7 @@
 #include "bmesh.h"
 
 struct BMesh;
+struct DerivedMesh;
 struct Object;
 
 typedef struct BMEditStrands {
@@ -54,12 +55,13 @@ typedef struct BMEditStrands {
        
        /* Object this editmesh came from (if it came from one) */
        struct Object *ob;
+       struct DerivedMesh *root_dm;
        
        unsigned int vertex_glbuf;
        unsigned int elem_glbuf;
 } BMEditStrands;
 
-struct BMEditStrands *BKE_editstrands_create(struct BMesh *bm);
+struct BMEditStrands *BKE_editstrands_create(struct BMesh *bm, struct 
DerivedMesh *root_dm);
 struct BMEditStrands *BKE_editstrands_copy(struct BMEditStrands *es);
 struct BMEditStrands *BKE_editstrands_from_object(struct Object *ob);
 void BKE_editstrands_update_linked_customdata(struct BMEditStrands *es);
diff --git a/source/blender/blenkernel/intern/edithair.c 
b/source/blender/blenkernel/intern/edithair.c
index 6beb5f5..e1064d9 100644
--- a/source/blender/blenkernel/intern/edithair.c
+++ b/source/blender/blenkernel/intern/edithair.c
@@ -41,17 +41,20 @@
 
 #include "BKE_bvhutils.h"
 #include "BKE_customdata.h"
+#include "BKE_cdderivedmesh.h"
 #include "BKE_edithair.h"
 #include "BKE_DerivedMesh.h"
+#include "BKE_mesh_sample.h"
 #include "BKE_particle.h"
 
 #include "intern/bmesh_strands_conv.h"
 
-BMEditStrands *BKE_editstrands_create(BMesh *bm)
+BMEditStrands *BKE_editstrands_create(BMesh *bm, DerivedMesh *root_dm)
 {
        BMEditStrands *es = MEM_callocN(sizeof(BMEditStrands), __func__);
        
        es->bm = bm;
+       es->root_dm = CDDM_copy(root_dm);
        
        return es;
 }
@@ -62,6 +65,7 @@ BMEditStrands *BKE_editstrands_copy(BMEditStrands *es)
        *es_copy = *es;
        
        es_copy->bm = BM_mesh_copy(es->bm);
+       es_copy->root_dm = CDDM_copy(es->root_dm);
        
        return es_copy;
 }
@@ -91,6 +95,8 @@ void BKE_editstrands_free(BMEditStrands *es)
 {
        if (es->bm)
                BM_mesh_free(es->bm);
+       if (es->root_dm)
+               es->root_dm->release(es->root_dm);
 }
 
 /* === constraints === */
@@ -112,19 +118,36 @@ void BKE_editstrands_calc_segment_lengths(BMesh *bm)
        }
 }
 
-void BKE_editstrands_solve_constraints(BMEditStrands *es)
+static void editstrands_apply_root_locations(BMesh *bm, DerivedMesh *root_dm)
 {
-       /* XXX Simplistic implementation from particles:
-        * adjust segment lengths starting from the root.
-        * This should be replaced by a more advanced method using a 
least-squares
-        * error metric with length and root location constraints
-        */
+       BMVert *root;
+       BMIter iter;
        
-       BMesh *bm = es->bm;
+       if (!root_dm)
+               return;
+       
+       BM_ITER_STRANDS(root, &iter, bm, BM_STRANDS_OF_MESH) {
+               MSurfaceSample root_sample;
+               float loc[3], nor[3];
+               
+               BM_elem_meshsample_data_named_get(&bm->vdata, root, 
CD_MSURFACE_SAMPLE, CD_HAIR_ROOT_LOCATION, &root_sample);
+               if (BKE_mesh_sample_eval(root_dm, &root_sample, loc, nor)) {
+                       copy_v3_v3(root->co, loc);
+               }
+       }
+}
+
+static void editstrands_solve_segment_lengths(BMesh *bm)
+{
        BMVert *root, *v, *vprev;
        BMIter iter, iter_strand;
        int k;
        
+       /* XXX Simplistic implementation from particles:
+        * adjust segment lengths starting from the root.
+        * This should be replaced by a more advanced method using a 
least-squares
+        * error metric with length and root location constraints
+        */
        BM_ITER_STRANDS(root, &iter, bm, BM_STRANDS_OF_MESH) {
                BM_ITER_STRANDS_ELEM_INDEX(v, &iter_strand, root, 
BM_VERTS_OF_STRAND, k) {
                        if (k > 0) {
@@ -142,6 +165,12 @@ void BKE_editstrands_solve_constraints(BMEditStrands *es)
        }
 }
 
+void BKE_editstrands_solve_constraints(BMEditStrands *es)
+{
+       editstrands_apply_root_locations(es->bm, es->root_dm);
+       editstrands_solve_segment_lengths(es->bm);
+}
+
 
 /* === particle conversion === */
 
diff --git a/source/blender/bmesh/intern/bmesh_interp.c 
b/source/blender/bmesh/intern/bmesh_interp.c
index f93675f..98444de 100644
--- a/source/blender/bmesh/intern/bmesh_interp.c
+++ b/source/blender/bmesh/intern/bmesh_interp.c
@@ -905,3 +905,19 @@ void BM_elem_float_data_named_set(CustomData *cd, void 
*element, int type, const
        float *f = CustomData_bmesh_get_named(cd, ((BMHeader *)element)->data, 
type, name);
        if (f) *f = val;
 }
+
+void BM_elem_meshsample_data_named_get(CustomData *cd, void *element, int 
type, const char *name, MSurfaceSample *val)
+{
+       const MSurfaceSample *s = CustomData_bmesh_get_named(cd, ((BMHeader 
*)element)->data, type, name);
+       if (s)
+               memcpy(val, s, sizeof(MSurfaceSample));
+       else
+               memset(val, 0, sizeof(MSurfaceSample));
+}
+
+void BM_elem_meshsample_data_named_set(CustomData *cd, void *element, int 
type, const char *name, const MSurfaceSample *val)
+{
+       MSurfaceSample *s = CustomData_bmesh_get_named(cd, ((BMHeader 
*)element)->data, type, name);
+       if (s)
+               memcpy(s, val, sizeof(MSurfaceSample));
+}
diff --git a/source/blender/bmesh/intern/bmesh_interp.h 
b/source/blender/bmesh/intern/bmesh_interp.h
index 0315702..0930295 100644
--- a/source/blender/bmesh/intern/bmesh_interp.h
+++ b/source/blender/bmesh/intern/bmesh_interp.h
@@ -27,6 +27,8 @@
  *  \ingroup bmesh
  */
 
+struct MSurfaceSample;
+
 void  BM_loop_interp_multires(BMesh *bm, BMLoop *target, BMFace *source);
 void  BM_vert_interp_from_face(BMesh *bm, BMVert *v, BMFace *source);
 
@@ -43,6 +45,8 @@ float BM_elem_float_data_get(CustomData *cd, void *element, 
int type);
 void  BM_elem_float_data_set(CustomData *cd, void *element, int type, const 
float val);
 float BM_elem_float_data_named_get(CustomData *cd, void *element, int type, 
const char *name);
 void BM_elem_float_data_named_set(CustomData *cd, void *element, int type, 
const char *name, const float val);
+void BM_elem_meshsample_data_named_get(CustomData *cd, void *element, int 
type, const char *name, struct MSurfaceSample *val);
+void BM_elem_meshsample_data_named_set(CustomData *cd, void *element, int 
type, const char *name, const struct MSurfaceSample *val);
 
 void BM_face_interp_from_face_ex(BMesh *bm, BMFace *target, BMFace *source, 
const bool do_vertex,
                                  void **blocks, void **blocks_v, float 
(*cos_2d)[2], float axis_mat[3][3]);
diff --git a/source/blender/bmesh/intern/bmesh_strands_conv.c 
b/source/blender/bmesh/intern/bmesh_strands_conv.c
index 0dfb89c..786b35b 100644
--- a/source/blender/bmesh/intern/bmesh_strands_conv.c
+++ b/source/blender/bmesh/intern/bmesh_strands_conv.c
@@ -50,22 +50,6 @@ const char *CD_HAIR_MASS = "HAIR_MASS";
 const char *CD_HAIR_WEIGHT = "HAIR_WEIGHT";
 const char *CD_HAIR_ROOT_LOCATION = "HAIR_ROOT_LOCATION";
 
-static void BM_elem_msample_data_named_get(CustomData *cd, void *element, int 
type, const char *name, MSurfaceSample *val)
-{
-       const MSurfaceSample *s = CustomData_bmesh_get_named(cd, ((BMHeader 
*)element)->data, type, name);
-       if (s)
-               memcpy(val, s, sizeof(MSurfaceSample));
-       else
-               memset(val, 0, sizeof(MSurfaceSample));
-}
-
-static void BM_elem_msample_data_named_set(CustomData *cd, void *element, int 
type, const char *name, const MSurfaceSample *val)
-{
-       MSurfaceSample *s = CustomData_bmesh_get_named(cd, ((BMHeader 
*)element)->data, type, name);
-       if (s)
-               memcpy(s, val, sizeof(MSurfaceSample));
-}
-
 /* ------------------------------------------------------------------------- */
 
 int BM_strands_count_psys_keys(ParticleSystem *psys)
@@ -229,7 +213,7 @@ static void bm_make_particles(BMesh *bm, Object *ob, 
ParticleSystem *psys, struc
                        if (k == 0) {
                                MSurfaceSample root_loc;
                                if (BKE_mesh_sample_from_particle(&root_loc, 
psys, emitter_dm, pa)) {
-                                       
BM_elem_msample_data_named_set(&bm->vdata, v, CD_MSURFACE_SAMPLE, 
CD_HAIR_ROOT_LOCATION, &root_loc);
+                                       
BM_elem_meshsample_data_named_set(&bm->vdata, v, CD_MSURFACE_SAMPLE, 
CD_HAIR_ROOT_LOCATION, &root_loc);
                                }
                        }
                        
@@ -478,7 +462,7 @@ static void make_particle_hair(BMesh *bm, BMVert *root, 
Object *ob, ParticleSyst
                /* root */
                if (k == 0) {
                        MSurfaceSample root_loc;
-                       BM_elem_msample_data_named_get(&bm->vdata, v, 
CD_MSURFACE_SAMPLE, CD_HAIR_ROOT_LOCATION, &root_loc);
+                       BM_elem_meshsample_data_named_get(&bm->vdata, v, 
CD_MSURFACE_SAMPLE, CD_HAIR_ROOT_LOCATION, &root_loc);
                        if (!BKE_mesh_sample_to_particle(&root_loc, psys, 
emitter_dm, emitter_bvhtree, pa)) {
                                pa->num = 0;
                                pa->num_dmcache = DMCACHE_NOTFOUND;
diff --git a/source/blender/editors/hair/hair_edit.c 
b/source/blender/editors/hair/hair_edit.c
index 90884f5..6b3bff3 100644
--- a/source/blender/editors/hair/hair_edit.c
+++ b/source/blender/editors/hair/hair_edit.c
@@ -43,8 +43,10 @@
 #include "DNA_screen_types.h"
 
 #include "BKE_brush.h"
+#include "BKE_cdderivedmesh.h"
 #include "BKE_context.h"
 #include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
 #include "BKE_edithair.h"
 #include "BKE_paint.h"
 #include "BKE_particle.h"
@@ -73,13 +75,22 @@ static bool has_hair_data(Object *ob)
        return false;
 }
 
-static bool init_hair_edit(Object *ob)
+static bool init_hair_edit(Scene *scene, Object *ob)
 {
        ParticleSystem *psys = psys_get_current(ob);
-       if (psys->part->type == PART_HAIR) {
+       BMesh *bm;
+       DerivedMesh *dm;
+       
+       if (psys && psys->part->type == PART_HAIR) {
                if (!psys->hairedit) {
-                       BMesh *bm = BKE_particles_to_bmesh(ob, psys);
-                       psys->hairedit = BKE_editstrands_create(bm);
+                       bm = BKE_particles_to_bmesh(ob, psys);
+                       
+                       if (ob->type == OB_MESH || ob->derivedFinal)
+                               dm = ob->derivedFinal ? ob->derivedFinal : 
mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+                       else
+                               dm = NULL;
+                       
+                       psys->hairedit = BKE_editstrands_create(bm, dm);
                }
                return true;
        }
@@ -146,6 +157,7 @@ int hair_edit_toggle_poll(bContext *C)
 
 static int hair_edit_toggle_exec(bContext *C, wmOperator *op)
 {
+       Scene *scene = CTX_data_scene(C);
        Object *ob = CTX_data_active_object(C);
        const int mode_flag = OB_MODE_HAIR_EDIT;
        const bool is_mode_set = (ob->mode & mode_flag) != 0;
@@ -157,7 +169,7 @@ static int hair_edit_toggle_exec(bContext *C, wmOperator 
*op)
        }
 
        if (!is_mode_set) {
-               init_hair_edit(ob);
+               init_hair_edit(scene, ob);
                ob->mode |= mode_flag;
                
 //             toggle_particle_cursor(C, 1);
diff --git a/source/blender/editors/hair/hair_stroke.c 
b/source/blender/editors/hai

@@ Diff output truncated at 10240 characters. @@

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

Reply via email to