support for curve orco uv's as UV's in cycles.
authorCampbell Barton <ideasman42@gmail.com>
Tue, 31 Jul 2012 13:43:26 +0000 (13:43 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 31 Jul 2012 13:43:26 +0000 (13:43 +0000)
ideally these would be used as generated coordinates, but this is tricly because cycles calculates its own orco's and doesnt know about curve settings.

source/blender/blenkernel/BKE_cdderivedmesh.h
source/blender/blenkernel/BKE_mesh.h
source/blender/blenkernel/intern/cdderivedmesh.c
source/blender/blenkernel/intern/displist.c
source/blender/blenkernel/intern/mesh.c
source/blender/makesrna/intern/rna_object_api.c

index eeebcdafe487abfea11a8998a83b5f7e4aa1ddf7..d7882d8e7eceb54784f94670081472851286f11f 100644 (file)
@@ -61,12 +61,14 @@ DerivedMesh *CDDM_from_BMEditMesh(struct BMEditMesh *em, struct Mesh *me, int us
 /* merge verts  */
 DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap);
 
+DerivedMesh *CDDM_from_curve_orco(struct Scene *scene, struct Object *ob);
+
 /* creates a CDDerivedMesh from the given curve object */
 struct DerivedMesh *CDDM_from_curve(struct Object *ob);
 
 /* creates a CDDerivedMesh from the given curve object and specified dispbase */
 /* useful for OrcoDM creation for curves with constructive modifiers */
-DerivedMesh *CDDM_from_curve_displist(struct Object *ob, struct ListBase *dispbase);
+DerivedMesh *CDDM_from_curve_displist(struct Object *ob, struct ListBase *dispbase, int **orco_index_ptr);
 
 /* Copies the given DerivedMesh with verts, faces & edges stored as
  * custom element data.
index 6fac915d520437fd0fac573076a7adc0c5f1867e..b635a37e4f625021f7a707c27a18cb9bb2d4ad50 100644 (file)
@@ -143,9 +143,13 @@ int  BKE_mesh_nurbs_to_mdata(struct Object *ob, struct MVert **allvert, int *tot
                              int *totloop, int *totpoly);
 int BKE_mesh_nurbs_displist_to_mdata(struct Object *ob, struct ListBase *dispbase, struct MVert **allvert, int *_totvert,
                                      struct MEdge **alledge, int *_totedge, struct MLoop **allloop, struct MPoly **allpoly,
-                                     int *_totloop, int *_totpoly);
+                                     int *_totloop, int *_totpoly, int **orco_index_ptr);
+void BKE_mesh_nurbs_to_mdata_orco(struct MPoly *mpoly, int totpoly,
+                                  struct MLoop *mloops, struct MLoopUV *mloopuvs,
+                                  float (*orco)[3], int (*orco_index)[4]);
 void BKE_mesh_from_nurbs(struct Object *ob);
-void BKE_mesh_from_nurbs_displist(struct Object *ob, struct ListBase *dispbase);
+void BKE_mesh_from_nurbs_displist(struct Object *ob, struct ListBase *dispbase,
+                                  int **orco_index_ptr);
 void BKE_mesh_from_curve(struct Scene *scene, struct Object *ob);
 void free_dverts(struct MDeformVert *dvert, int totvert);
 void copy_dverts(struct MDeformVert *dst, struct MDeformVert *src, int totvert); /* __NLA */
index b19b9db874916d3a6e1010602d6a451933c0510b..641033a2ec951e16f68ad43831cf10d929eb4600 100644 (file)
@@ -52,6 +52,7 @@
 #include "BKE_paint.h"
 #include "BKE_utildefines.h"
 #include "BKE_tessmesh.h"
+#include "BKE_curve.h"
 
 #include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h"
@@ -1709,11 +1710,51 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob))
 
 DerivedMesh *CDDM_from_curve(Object *ob)
 {
-       return CDDM_from_curve_displist(ob, &ob->disp);
+       return CDDM_from_curve_displist(ob, &ob->disp, NULL);
 }
 
-DerivedMesh *CDDM_from_curve_displist(Object *ob, ListBase *dispbase)
+DerivedMesh *CDDM_from_curve_orco(struct Scene *scene, Object *ob)
 {
+       int *orco_index_ptr = NULL;
+       int (*orco_index)[4] = NULL;
+       float (*orco)[3] = NULL;
+       DerivedMesh *dm = CDDM_from_curve_displist(ob, &ob->disp, &orco_index_ptr);
+
+       if (orco_index_ptr) {
+               orco = (float (*)[3])BKE_curve_make_orco(scene, ob);
+       }
+
+       if (orco && orco_index_ptr) {
+               const char *uvname = "Orco";
+
+               int totpoly = dm->getNumPolys(dm);
+
+               MPoly *mpolys = dm->getPolyArray(dm);
+               MLoop *mloops = dm->getLoopArray(dm);
+
+               MLoopUV *mloopuvs;
+
+               CustomData_add_layer_named(&dm->polyData, CD_MTEXPOLY, CD_DEFAULT, NULL, dm->numPolyData, uvname);
+               mloopuvs = CustomData_add_layer_named(&dm->loopData, CD_MLOOPUV,  CD_DEFAULT, NULL, dm->numLoopData, uvname);
+
+               BKE_mesh_nurbs_to_mdata_orco(mpolys, totpoly,
+                                            mloops, mloopuvs,
+                                            orco, orco_index);
+       }
+
+       if (orco_index) {
+               MEM_freeN(orco_index);
+       }
+       if (orco) {
+               MEM_freeN(orco);
+       }
+
+       return dm;
+}
+
+DerivedMesh *CDDM_from_curve_displist(Object *ob, ListBase *dispbase, int **orco_index_ptr)
+{
+       const short do_orco_as_uv= 1;
        DerivedMesh *dm;
        CDDerivedMesh *cddm;
        MVert *allvert;
@@ -1723,7 +1764,7 @@ DerivedMesh *CDDM_from_curve_displist(Object *ob, ListBase *dispbase)
        int totvert, totedge, totloop, totpoly;
 
        if (BKE_mesh_nurbs_displist_to_mdata(ob, dispbase, &allvert, &totvert, &alledge,
-                                            &totedge, &allloop, &allpoly, &totloop, &totpoly) != 0)
+                                            &totedge, &allloop, &allpoly, &totloop, &totpoly, orco_index_ptr) != 0)
        {
                /* Error initializing mdata. This often happens when curve is empty */
                return CDDM_new(0, 0, 0, 0, 0);
@@ -1746,6 +1787,10 @@ DerivedMesh *CDDM_from_curve_displist(Object *ob, ListBase *dispbase)
 
        CDDM_calc_edges(dm);
 
+       if (do_orco_as_uv ) {
+               BKE_curve_make_orco(NULL, ob);
+       }
+
        return dm;
 }
 
index 8011efebaac5b905cb84dbae17b18ef10acf4054..00a76e87d8377a831355904ec086be337f5f1735 100644 (file)
@@ -948,7 +948,7 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba
                                        curve_to_filledpoly(cu, nurb, dispbase);
                                }
 
-                               dm = CDDM_from_curve_displist(ob, dispbase);
+                               dm = CDDM_from_curve_displist(ob, dispbase, NULL);
 
                                CDDM_calc_normals_mapping(dm);
                        }
@@ -1038,7 +1038,7 @@ static DerivedMesh *create_orco_dm(Scene *scene, Object *ob)
 
        /* OrcoDM should be created from underformed disp lists */
        BKE_displist_make_curveTypes_forOrco(scene, ob, &disp);
-       dm = CDDM_from_curve_displist(ob, &disp);
+       dm = CDDM_from_curve_displist(ob, &disp, NULL);
 
        BKE_displist_free(&disp);
 
index a65c202479e9c6db77754c6fdd0be8e1e0d76204..77cd127e6ea6c77bff40969d9d3b6b2e78aaba8d 100644 (file)
@@ -394,6 +394,7 @@ void BKE_mesh_unlink(Mesh *me)
        
        if (me == NULL) return;
        
+       if (me->mat)
        for (a = 0; a < me->totcol; a++) {
                if (me->mat[a]) me->mat[a]->id.us--;
                me->mat[a] = NULL;
@@ -1234,19 +1235,21 @@ int BKE_mesh_nurbs_to_mdata(Object *ob, MVert **allvert, int *totvert,
                                                allvert, totvert,
                                                alledge, totedge,
                                                allloop, allpoly,
-                                               totloop, totpoly);
+                                               totloop, totpoly, NULL);
 }
 
 /* BMESH: this doesn't calculate all edges from polygons,
  * only free standing edges are calculated */
 
 /* Initialize mverts, medges and, faces for converting nurbs to mesh and derived mesh */
-/* use specified dispbase  */
+/* use specified dispbase */
+/* TODO: orco values for non DL_SURF types */
 int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase,
                                      MVert **allvert, int *_totvert,
                                      MEdge **alledge, int *_totedge,
                                      MLoop **allloop, MPoly **allpoly,
-                                     int *_totloop, int *_totpoly)
+                                     int *_totloop, int *_totpoly,
+                                     int **orco_index_ptr)
 {
        DispList *dl;
        Curve *cu;
@@ -1258,6 +1261,7 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase,
        int a, b, ofs, vertcount, startvert, totvert = 0, totedge = 0, totloop = 0, totvlak = 0;
        int p1, p2, p3, p4, *index;
        int conv_polys = 0;
+       int (*orco_index)[4] = NULL;
 
        cu = ob->data;
 
@@ -1308,6 +1312,11 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase,
        /* verts and faces */
        vertcount = 0;
 
+       if (orco_index_ptr) {
+               *orco_index_ptr = MEM_callocN(sizeof(int) * totvlak * 4, "nurbs_init orco");
+               orco_index = (int (*)[4]) *orco_index_ptr;
+       }
+
        dl = dispbase->first;
        while (dl) {
                int smooth = dl->rt & CU_SMOOTH ? 1 : 0;
@@ -1385,8 +1394,6 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase,
                                mloop += 3;
                                index += 3;
                        }
-
-
                }
                else if (dl->type == DL_SURF) {
                        startvert = vertcount;
@@ -1431,6 +1438,15 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase,
                                        mpoly->totloop = 4;
                                        mpoly->mat_nr = dl->col;
 
+                                       if (orco_index) {
+                                               const int poly_index = mpoly - *allpoly;
+                                               const int p_orco_base = startvert + ((dl->nr + 1) * a) + b;
+                                               orco_index[poly_index][0] = p_orco_base + 1;
+                                               orco_index[poly_index][1] = p_orco_base + dl->nr + 2;
+                                               orco_index[poly_index][2] = p_orco_base + dl->nr + 1;
+                                               orco_index[poly_index][3] = p_orco_base;
+                                       }
+
                                        if (smooth) mpoly->flag |= ME_SMOOTH;
                                        mpoly++;
                                        mloop += 4;
@@ -1461,8 +1477,34 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase,
        return 0;
 }
 
+
+MINLINE void copy_uv_orco_v2_v2(float r[2], const float a[2])
+{
+       r[0] = 0.5f + a[0] * 0.5f;
+       r[1] = 0.5f + a[1] * 0.5f;
+}
+
+/**
+ * orco is normally from #BKE_curve_make_orco
+ */
+void BKE_mesh_nurbs_to_mdata_orco(MPoly *mpoly, int totpoly,
+                                  MLoop *mloops, MLoopUV *mloopuvs,
+                                  float (*orco)[3], int (*orco_index)[4])
+{
+       MPoly *mp;
+
+       int i, j;
+       for (i = 0, mp = mpoly; i < totpoly; i++, mp++) {
+               MLoop *ml = mloops + mp->loopstart;
+               MLoopUV *mluv = mloopuvs + mp->loopstart;
+               for (j = 0; j < mp->totloop; j++, ml++, mluv++) {
+                       copy_uv_orco_v2_v2(mluv->uv, orco[orco_index[i][j]]);
+               }
+       }
+}
+
 /* this may fail replacing ob->data, be sure to check ob->type */
-void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase)
+void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, int **orco_index_ptr)
 {
        Main *bmain = G.main;
        Object *ob1;
@@ -1480,7 +1522,7 @@ void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase)
        if (dm == NULL) {
                if (BKE_mesh_nurbs_displist_to_mdata(ob, dispbase, &allvert, &totvert,
                                                     &alledge, &totedge, &allloop,
-                                                    &allpoly, &totloop, &totpoly) != 0)
+                                                    &allpoly, &totloop, &totpoly, orco_index_ptr) != 0)
                {
                        /* Error initializing */
                        return;
@@ -1536,7 +1578,7 @@ void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase)
 
 void BKE_mesh_from_nurbs(Object *ob)
 {
-       BKE_mesh_from_nurbs_displist(ob, &ob->disp);
+       BKE_mesh_from_nurbs_displist(ob, &ob->disp, NULL);
 }
 
 typedef struct EdgeLink {
index ae8c331bf1ea1686df7df016969abbfb67e24dd1..0fefc4c89fb14e910f3652df356312c3a6443944 100644 (file)
@@ -87,6 +87,10 @@ Mesh *rna_Object_to_mesh(Object *ob, ReportList *reports, Scene *sce, int apply_
                case OB_SURF: {
                        ListBase dispbase = {NULL, NULL};
                        DerivedMesh *derivedFinal = NULL;
+                       int uv_from_orco;
+
+                       int (*orco_index)[4] = NULL;
+                       float (*orco)[3] = NULL;
 
                        /* copies object and modifiers (but not the data) */
                        tmpobj = BKE_object_copy(ob);
@@ -114,7 +118,37 @@ Mesh *rna_Object_to_mesh(Object *ob, ReportList *reports, Scene *sce, int apply_
 
                        tmpobj->derivedFinal = derivedFinal;
 
-                       BKE_mesh_from_nurbs_displist(tmpobj, &dispbase);
+                       uv_from_orco = (tmpcu->flag & CU_UV_ORCO) != 0;
+
+                       if (uv_from_orco) {
+                               /* before curve conversion */
+                               orco = (float (*)[3])BKE_curve_make_orco(sce, tmpobj);
+                       }
+
+                       /* convert object type to mesh */
+                       BKE_mesh_from_nurbs_displist(tmpobj, &dispbase, uv_from_orco ? &orco_index : NULL);
+
+                       tmpmesh = tmpobj->data;
+
+                       if (uv_from_orco && orco && orco_index) {
+                               const char *uvname = "Orco";
+                               /* add UV's */
+                               MTexPoly *mtpoly  = CustomData_add_layer_named(&tmpmesh->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, tmpmesh->totpoly, uvname);
+                               MLoopUV *mloopuvs = CustomData_add_layer_named(&tmpmesh->ldata, CD_MLOOPUV,  CD_DEFAULT, NULL, tmpmesh->totloop, uvname);
+
+                               BKE_mesh_nurbs_to_mdata_orco(tmpmesh->mpoly, tmpmesh->totpoly,
+                                                            tmpmesh->mloop, mloopuvs,
+                                                            orco, orco_index);
+
+                               (void)mtpoly;
+                       }
+
+                       if (orco_index) {
+                               MEM_freeN(orco_index);
+                       }
+                       if (orco) {
+                               MEM_freeN(orco);
+                       }
 
                        BKE_displist_free(&dispbase);
 
@@ -124,7 +158,7 @@ Mesh *rna_Object_to_mesh(Object *ob, ReportList *reports, Scene *sce, int apply_
                                BKE_report(reports, RPT_ERROR, "cant convert curve to mesh. Does the curve have any segments?");
                                return NULL;
                        }
-                       tmpmesh = tmpobj->data;
+
                        BKE_libblock_free_us(&G.main->object, tmpobj);
                        break;
                }