From 838842581cdae1030a0e49a80792a39c303a7a80 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 8 Mar 2010 13:49:13 +0000 Subject: - Fixed trouble with rendering curves with disabled modifiers, which are disabled for realtime displaying but enabled for rendering. - Calculate tex space for curves before modifiers applying. --- source/blender/blenkernel/BKE_cdderivedmesh.h | 4 + source/blender/blenkernel/BKE_displist.h | 6 +- source/blender/blenkernel/BKE_mesh.h | 3 + source/blender/blenkernel/intern/cdderivedmesh.c | 9 +- source/blender/blenkernel/intern/curve.c | 17 +--- source/blender/blenkernel/intern/displist.c | 101 +++++++++++++-------- source/blender/blenkernel/intern/mesh.c | 15 ++- .../blender/render/intern/source/convertblender.c | 47 ++++------ 8 files changed, 116 insertions(+), 86 deletions(-) diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h index 77a8ef518e9..33e8f930c9d 100644 --- a/source/blender/blenkernel/BKE_cdderivedmesh.h +++ b/source/blender/blenkernel/BKE_cdderivedmesh.h @@ -57,6 +57,10 @@ struct DerivedMesh *CDDM_from_editmesh(struct EditMesh *em, struct Mesh *me); /* 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_customDB(struct Object *ob, struct ListBase *dispbase); + /* Copies the given DerivedMesh with verts, faces & edges stored as * custom element data. */ diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h index 2baefc83678..e685dd90223 100644 --- a/source/blender/blenkernel/BKE_displist.h +++ b/source/blender/blenkernel/BKE_displist.h @@ -87,8 +87,10 @@ extern void count_displist(struct ListBase *lb, int *totvert, int *totface); extern void freedisplist(struct ListBase *lb); extern int displist_has_faces(struct ListBase *lb); -extern void makeDispListSurf(struct Scene *scene, struct Object *ob, struct ListBase *dispbase, int forRender, int forOrco); +extern void makeDispListSurf(struct Scene *scene, struct Object *ob, struct ListBase *dispbase, struct DerivedMesh **derivedFinal, int forRender, int forOrco); extern void makeDispListCurveTypes(struct Scene *scene, struct Object *ob, int forOrco); +extern void makeDispListCurveTypes_forRender(struct Scene *scene, struct Object *ob, struct ListBase *dispbase, struct DerivedMesh **derivedFinal, int forOrco); +extern void makeDispListCurveTypes_forOrco(struct Scene *scene, struct Object *ob, struct ListBase *dispbase); extern void makeDispListMBall(struct Scene *scene, struct Object *ob); extern void shadeDispList(struct Scene *scene, struct Base *base); extern void shadeMeshMCol(struct Scene *scene, struct Object *ob, struct Mesh *me); @@ -103,7 +105,7 @@ void fastshade_free_render(void); float calc_taper(struct Scene *scene, struct Object *taperobj, int cur, int tot); /* add Orco layer to the displist object which has got derived mesh and return orco */ -float *makeOrcoDispList(struct Scene *scene, struct Object *ob, int forRender); +float *makeOrcoDispList(struct Scene *scene, struct Object *ob, struct DerivedMesh *derivedFinal, int forRender); #endif diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index a82e3ffe45b..3b6cf8803d8 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -72,6 +72,9 @@ void set_mesh(struct Object *ob, struct Mesh *me); void mball_to_mesh(struct ListBase *lb, struct Mesh *me); int nurbs_to_mdata(struct Object *ob, struct MVert **allvert, int *_totvert, struct MEdge **alledge, int *_totedge, struct MFace **allface, int *_totface); +int nurbs_to_mdata_customdb(struct Object *ob, struct ListBase *dispbase, + struct MVert **allvert, int *_totvert, struct MEdge **alledge, int *_totedge, + struct MFace **allface, int *_totface); void nurbs_to_mesh(struct Object *ob); void mesh_to_curve(struct Scene *scene, struct Object *ob); void free_dverts(struct MDeformVert *dvert, int totvert); diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index d0e50dc97a8..347a501dfcc 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -57,6 +57,7 @@ #include "DNA_object_fluidsim.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "DNA_curve_types.h" /* for Curve */ #include "MEM_guardedalloc.h" @@ -1586,6 +1587,11 @@ DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *me) } DerivedMesh *CDDM_from_curve(Object *ob) +{ + return CDDM_from_curve_customDB(ob, &((Curve *)ob->data)->disp); +} + +DerivedMesh *CDDM_from_curve_customDB(Object *ob, ListBase *dispbase) { DerivedMesh *dm; CDDerivedMesh *cddm; @@ -1594,7 +1600,8 @@ DerivedMesh *CDDM_from_curve(Object *ob) MFace *allface; int totvert, totedge, totface; - if (nurbs_to_mdata (ob, &allvert, &totvert, &alledge, &totedge, &allface, &totface) != 0) { + if (nurbs_to_mdata_customdb(ob, dispbase, &allvert, &totvert, &alledge, + &totedge, &allface, &totface) != 0) { /* Error initializing mdata. This often happens when curve is empty */ return CDDM_new(0, 0, 0); } diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index fb27327c3be..2430e417e51 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -1099,17 +1099,12 @@ float *make_orco_curve(Scene *scene, Object *ob) DispList *dl; int u, v, numVerts; float *fp, *coord_array; - int remakeDisp = 0; + ListBase disp = {NULL, NULL}; - if (!(cu->flag&CU_UV_ORCO) && cu->key && cu->key->block.first) { - makeDispListCurveTypes(scene, ob, 1); - remakeDisp = 1; - } - - /* Assumes displist has been built */ + makeDispListCurveTypes_forOrco(scene, ob, &disp); numVerts = 0; - for (dl=cu->disp.first; dl; dl=dl->next) { + for (dl=disp.first; dl; dl=dl->next) { if (dl->type==DL_INDEX3) { numVerts += dl->nr; } else if (dl->type==DL_SURF) { @@ -1126,7 +1121,7 @@ float *make_orco_curve(Scene *scene, Object *ob) } fp= coord_array= MEM_mallocN(3*sizeof(float)*numVerts, "cu_orco"); - for (dl=cu->disp.first; dl; dl=dl->next) { + for (dl=disp.first; dl; dl=dl->next) { if (dl->type==DL_INDEX3) { for (u=0; unr; u++, fp+=3) { if (cu->flag & CU_UV_ORCO) { @@ -1174,9 +1169,7 @@ float *make_orco_curve(Scene *scene, Object *ob) } } - if (remakeDisp) { - makeDispListCurveTypes(scene, ob, 0); - } + freedisplist(&disp); return coord_array; } diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 3b284b8574b..ee746a4dacd 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -1280,7 +1280,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, fl deformedVerts = curve_getVertexCos(cu, nurb, &numVerts); originalVerts = MEM_dupallocN(deformedVerts); } - + mti->deformVerts(md, ob, NULL, deformedVerts, numVerts, forRender, editmode); if (md==preTesselatePoint) @@ -1292,7 +1292,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, fl curve_applyVertexCos(cu, nurb, deformedVerts); if (keyVerts) /* these are not passed through modifier stack */ curve_applyKeyVertexTilts(cu, nurb, keyVerts); - + if(keyVerts) MEM_freeN(keyVerts); @@ -1301,7 +1301,8 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, fl *numVerts_r = numVerts; } -static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispbase, int forRender, float (*originalVerts)[3], float (*deformedVerts)[3]) +static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispbase, + DerivedMesh **derivedFinal, int forRender, float (*originalVerts)[3], float (*deformedVerts)[3]) { ModifierData *md = modifiers_getVirtualModifierList(ob); ModifierData *preTesselatePoint; @@ -1325,8 +1326,8 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba md = preTesselatePoint->next; } - if (ob->derivedFinal) { - ob->derivedFinal->release (ob->derivedFinal); + if (*derivedFinal) { + (*derivedFinal)->release (*derivedFinal); } for (; md; md=md->next) { @@ -1427,7 +1428,7 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba MEM_freeN(dmDeformedVerts); } - ob->derivedFinal = dm; + (*derivedFinal) = dm; if (deformedVerts) { curve_applyVertexCos(ob->data, nurb, originalVerts); @@ -1469,14 +1470,13 @@ static void displist_surf_indices(DispList *dl) static DerivedMesh *create_orco_dm(Scene *scene, Object *ob) { DerivedMesh *dm; - float (*orco)[3]; + ListBase disp= {NULL, NULL}; - dm= CDDM_from_curve(ob); - orco= (float(*)[3])make_orco_curve(scene, ob); + /* OrcoDM should be created from underformed disp lists */ + makeDispListCurveTypes_forOrco(scene, ob, &disp); + dm= CDDM_from_curve_customDB(ob, &disp); - CDDM_apply_vert_coords(dm, orco); - CDDM_calc_normals(dm); - MEM_freeN(orco); + freedisplist(&disp); return dm; } @@ -1516,7 +1516,7 @@ static void add_orco_dm(Scene *scene, Object *ob, DerivedMesh *dm, DerivedMesh * DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, orco); } -static void curve_calc_orcodm(Scene *scene, Object *ob, int forRender) +static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *derivedFinal, int forRender) { /* this function represents logic of mesh's orcodm calculation */ /* for displist-based objects */ @@ -1526,7 +1526,7 @@ static void curve_calc_orcodm(Scene *scene, Object *ob, int forRender) Curve *cu= ob->data; int required_mode; int editmode = (!forRender && cu->editnurb); - DerivedMesh *dm= ob->derivedFinal, *ndm, *orcodm= NULL; + DerivedMesh *ndm, *orcodm= NULL; if(forRender) required_mode = eModifierMode_Render; else required_mode = eModifierMode_Realtime; @@ -1563,13 +1563,14 @@ static void curve_calc_orcodm(Scene *scene, Object *ob, int forRender) } /* add an orco layer if needed */ - add_orco_dm(scene, ob, dm, orcodm); + add_orco_dm(scene, ob, derivedFinal, orcodm); if(orcodm) orcodm->release(orcodm); } -void makeDispListSurf(Scene *scene, Object *ob, ListBase *dispbase, int forRender, int forOrco) +void makeDispListSurf(Scene *scene, Object *ob, ListBase *dispbase, + DerivedMesh **derivedFinal, int forRender, int forOrco) { ListBase *nubase; Nurb *nu; @@ -1642,23 +1643,20 @@ void makeDispListSurf(Scene *scene, Object *ob, ListBase *dispbase, int forRende } if(!forOrco) - curve_calc_modifiers_post(scene, ob, dispbase, forRender, originalVerts, deformedVerts); + curve_calc_modifiers_post(scene, ob, dispbase, derivedFinal, + forRender, originalVerts, deformedVerts); } -void makeDispListCurveTypes(Scene *scene, Object *ob, int forOrco) +static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispbase, + DerivedMesh **derivedFinal, int forRender, int forOrco) { Curve *cu = ob->data; - ListBase *dispbase; - + /* we do allow duplis... this is only displist on curve level */ if(!ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) return; - freedisplist(&(ob->disp)); - dispbase= &(cu->disp); - freedisplist(dispbase); - if(ob->type==OB_SURF) { - makeDispListSurf(scene, ob, dispbase, 0, forOrco); + makeDispListSurf(scene, ob, dispbase, derivedFinal, forRender, forOrco); } else if (ELEM(ob->type, OB_CURVE, OB_FONT)) { ListBase dlbev; @@ -1671,15 +1669,15 @@ void makeDispListCurveTypes(Scene *scene, Object *ob, int forOrco) nubase= cu->editnurb; else nubase= &cu->nurb; - + BLI_freelistN(&(cu->bev)); - + if(cu->path) free_path(cu->path); cu->path= NULL; - + if(ob->type==OB_FONT) BKE_text_to_curve(scene, ob, 0); - - if(!forOrco) curve_calc_modifiers_pre(scene, ob, 0, &originalVerts, &deformedVerts, &numVerts); + + if(!forOrco) curve_calc_modifiers_pre(scene, ob, forRender, &originalVerts, &deformedVerts, &numVerts); makeBevelList(ob); @@ -1807,9 +1805,24 @@ void makeDispListCurveTypes(Scene *scene, Object *ob, int forOrco) if(cu->flag & CU_PATH) calc_curvepath(ob); - if(!forOrco) curve_calc_modifiers_post(scene, ob, &cu->disp, 0, originalVerts, deformedVerts); - tex_space_curve(cu); + if (!forRender) { + tex_space_curve(cu); + } + + if(!forOrco) curve_calc_modifiers_post(scene, ob, dispbase, derivedFinal, forRender, originalVerts, deformedVerts); } +} + +void makeDispListCurveTypes(Scene *scene, Object *ob, int forOrco) +{ + Curve *cu = ob->data; + ListBase *dispbase; + + freedisplist(&(ob->disp)); + dispbase= &(cu->disp); + freedisplist(dispbase); + + do_makeDispListCurveTypes(scene, ob, dispbase, &ob->derivedFinal, 0, forOrco); if (ob->derivedFinal) { DM_set_object_boundbox (ob, ob->derivedFinal); @@ -1818,17 +1831,29 @@ void makeDispListCurveTypes(Scene *scene, Object *ob, int forOrco) } } +void makeDispListCurveTypes_forRender(Scene *scene, Object *ob, ListBase *dispbase, + DerivedMesh **derivedFinal, int forOrco) +{ + do_makeDispListCurveTypes(scene, ob, dispbase, derivedFinal, 1, forOrco); +} + +void makeDispListCurveTypes_forOrco(struct Scene *scene, struct Object *ob, struct ListBase *dispbase) +{ + do_makeDispListCurveTypes(scene, ob, dispbase, NULL, 1, 1); +} + /* add Orco layer to the displist object which has got derived mesh and return orco */ -/* XXX: is it good place to keep this function here? */ -float *makeOrcoDispList(Scene *scene, Object *ob, int forRender) { +float *makeOrcoDispList(Scene *scene, Object *ob, DerivedMesh *derivedFinal, int forRender) { float *orco; - DerivedMesh *dm= ob->derivedFinal; - if (!dm->getVertDataArray(dm, CD_ORCO)) { - curve_calc_orcodm(scene, ob, forRender); + if (derivedFinal == NULL) + derivedFinal= ob->derivedFinal; + + if (!derivedFinal->getVertDataArray(derivedFinal, CD_ORCO)) { + curve_calc_orcodm(scene, ob, derivedFinal, forRender); } - orco= dm->getVertDataArray(dm, CD_ORCO); + orco= derivedFinal->getVertDataArray(derivedFinal, CD_ORCO); if(orco) { orco= MEM_dupallocN(orco); diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 2a6fc281624..b7efc0c626b 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -746,7 +746,16 @@ void mball_to_mesh(ListBase *lb, Mesh *me) /* Initialize mverts, medges and, faces for converting nurbs to mesh and derived mesh */ /* return non-zero on error */ -int nurbs_to_mdata(Object *ob, MVert **allvert, int *_totvert, +int nurbs_to_mdata(Object *ob, MVert **allvert, int *totvert, + MEdge **alledge, int *totedge, MFace **allface, int *totface) +{ + return nurbs_to_mdata_customdb(ob, &((Curve *)ob->data)->disp, + allvert, totvert, alledge, totedge, allface, totface); +} + +/* Initialize mverts, medges and, faces for converting nurbs to mesh and derived mesh */ +/* use specified dispbase */ +int nurbs_to_mdata_customdb(Object *ob, ListBase *dispbase, MVert **allvert, int *_totvert, MEdge **alledge, int *_totedge, MFace **allface, int *_totface) { DispList *dl; @@ -760,7 +769,7 @@ int nurbs_to_mdata(Object *ob, MVert **allvert, int *_totvert, cu= ob->data; /* count */ - dl= cu->disp.first; + dl= dispbase->first; while(dl) { if(dl->type==DL_SEGM) { totvert+= dl->parts*dl->nr; @@ -796,7 +805,7 @@ int nurbs_to_mdata(Object *ob, MVert **allvert, int *_totvert, /* verts and faces */ vertcount= 0; - dl= cu->disp.first; + dl= dispbase->first; while(dl) { int smooth= dl->rt & CU_SMOOTH ? 1 : 0; diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index df0271d880a..6e098186748 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -2735,12 +2735,12 @@ static void init_render_surf(Render *re, ObjectRen *obr, int timeoffset) Object *ob= obr->ob; Nurb *nu=0; Curve *cu; - ListBase displist; + ListBase displist= {NULL, NULL}; DispList *dl; Material **matar; float *orco=NULL, *orcobase=NULL, mat[4][4]; int a, totmat, need_orco=0; - DerivedMesh *dm; + DerivedMesh *dm= NULL; cu= ob->data; nu= cu->nurb.first; @@ -2762,34 +2762,33 @@ static void init_render_surf(Render *re, ObjectRen *obr, int timeoffset) if(ob->parent && (ob->parent->type==OB_LATTICE)) need_orco= 1; - dm= ob->derivedFinal; - if (ob->derivedFinal) { + makeDispListSurf(re->scene, ob, &displist, &dm, 1, 0); + + if (dm) { if(need_orco) { - orco= makeOrcoDispList(re->scene, ob, 1); + orco= makeOrcoDispList(re->scene, ob, dm, 1); if(orco) { set_object_orco(re, ob, orco); } } init_render_dm(dm, re, obr, timeoffset, orco, mat); + dm->release(dm); } else { if(need_orco) { orcobase= orco= get_object_orco(re, ob); } - displist.first= displist.last= 0; - makeDispListSurf(re->scene, ob, &displist, 1, 0); - /* walk along displaylist and create rendervertices/-faces */ for(dl=displist.first; dl; dl=dl->next) { /* watch out: u ^= y, v ^= x !! */ if(dl->type==DL_SURF) orco+= 3*dl_surf_to_renderdata(obr, dl, matar, orco, mat); } - - freedisplist(&displist); } + freedisplist(&displist); + MEM_freeN(matar); } @@ -2800,8 +2799,8 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset) VertRen *ver; VlakRen *vlr; DispList *dl; - DerivedMesh *dm; - ListBase olddl={NULL, NULL}; + DerivedMesh *dm = NULL; + ListBase disp={NULL, NULL}; Material **matar; float len, *data, *fp, *orco=NULL, *orcobase= NULL; float n[3], mat[4][4]; @@ -2812,16 +2811,9 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset) if(ob->type==OB_FONT && cu->str==NULL) return; else if(ob->type==OB_CURVE && cu->nurb.first==NULL) return; - /* no modifier call here, is in makedisp */ - - if(cu->resolu_ren) - SWAP(ListBase, olddl, cu->disp); - - /* test displist */ - if(cu->disp.first==NULL) - makeDispListCurveTypes(re->scene, ob, 0); - dl= cu->disp.first; - if(cu->disp.first==NULL) return; + makeDispListCurveTypes_forRender(re->scene, ob, &disp, &dm, 0); + dl= disp.first; + if(dl==NULL) return; mul_m4_m4m4(mat, ob->obmat, re->viewmat); invert_m4_m4(ob->imat, mat); @@ -2837,22 +2829,21 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset) need_orco= 1; } - dm= ob->derivedFinal; if (dm) { if(need_orco) { - orco= makeOrcoDispList(re->scene, ob, 1); + orco= makeOrcoDispList(re->scene, ob, dm, 1); if(orco) { set_object_orco(re, ob, orco); } } init_render_dm(dm, re, obr, timeoffset, orco, mat); + dm->release(dm); } else { if(need_orco) { orcobase=orco= get_object_orco(re, ob); } - dl= cu->disp.first; while(dl) { if(dl->type==DL_INDEX3) { int *index; @@ -3021,11 +3012,7 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset) } } - /* not very elegant... but we want original displist in UI */ - if(cu->resolu_ren) { - freedisplist(&cu->disp); - SWAP(ListBase, olddl, cu->disp); - } + freedisplist(&disp); MEM_freeN(matar); } -- cgit v1.2.3