From d0c70ad1d581d69f650d604293c006b2e0023310 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 5 Mar 2010 16:47:52 +0000 Subject: Constructive modifiers for curves and surfaces Used approach with creating DerivedMesh for curves whet they've got such modifiers. Available modifiers are: array, edge split, mirror, solidify, subsurf. --- source/blender/blenkernel/BKE_DerivedMesh.h | 3 + source/blender/blenkernel/BKE_cdderivedmesh.h | 3 + source/blender/blenkernel/BKE_displist.h | 3 + source/blender/blenkernel/BKE_mesh.h | 2 + source/blender/blenkernel/intern/DerivedMesh.c | 36 +- source/blender/blenkernel/intern/cdderivedmesh.c | 30 ++ source/blender/blenkernel/intern/displist.c | 239 ++++++++-- source/blender/blenkernel/intern/mesh.c | 166 ++++--- source/blender/blenkernel/intern/modifier.c | 30 +- source/blender/blenkernel/intern/object.c | 2 +- source/blender/editors/object/object_modifier.c | 17 +- source/blender/editors/space_view3d/drawobject.c | 67 ++- .../blender/render/intern/source/convertblender.c | 483 +++++++++++++-------- 13 files changed, 773 insertions(+), 308 deletions(-) diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 883a3809b30..154c6347f50 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -538,5 +538,8 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, void DM_add_tangent_layer(DerivedMesh *dm); +/* Set object's bounding box based on DerivedMesh min/max data */ +void DM_set_object_boundbox(struct Object *ob, DerivedMesh *dm); + #endif diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h index 269dcbb4141..77a8ef518e9 100644 --- a/source/blender/blenkernel/BKE_cdderivedmesh.h +++ b/source/blender/blenkernel/BKE_cdderivedmesh.h @@ -54,6 +54,9 @@ struct DerivedMesh *CDDM_from_mesh(struct Mesh *mesh, struct Object *ob); /* creates a CDDerivedMesh from the given EditMesh */ 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); + /* 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 a250456f5c1..2baefc83678 100644 --- a/source/blender/blenkernel/BKE_displist.h +++ b/source/blender/blenkernel/BKE_displist.h @@ -102,5 +102,8 @@ 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); + #endif diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 0952871e28a..a82e3ffe45b 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -70,6 +70,8 @@ int test_index_face(struct MFace *mface, struct CustomData *mfdata, int mfindex, struct Mesh *get_mesh(struct Object *ob); 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); 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/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index fa6c2f333ee..28b093cd693 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -2126,7 +2126,6 @@ static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask) int editing = paint_facesel_test(ob); /* weight paint and face select need original indicies because of selection buffer drawing */ int needMapping = (ob==obact) && (editing || (ob->mode & OB_MODE_WEIGHT_PAINT) || editing); - float min[3], max[3]; clear_mesh_caches(ob); @@ -2134,13 +2133,7 @@ static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask) &ob->derivedFinal, 0, 1, needMapping, dataMask, -1, 1); - INIT_MINMAX(min, max); - - ob->derivedFinal->getMinMax(ob->derivedFinal, min, max); - - if(!ob->bb) - ob->bb= MEM_callocN(sizeof(BoundBox), "bb"); - boundbox_set_from_min_max(ob->bb, min, max); + DM_set_object_boundbox (ob, ob->derivedFinal); ob->derivedFinal->needsFree = 0; ob->derivedDeform->needsFree = 0; @@ -2149,8 +2142,6 @@ static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask) static void editmesh_build_data(Scene *scene, Object *obedit, EditMesh *em, CustomDataMask dataMask) { - float min[3], max[3]; - clear_mesh_caches(obedit); if (em->derivedFinal) { @@ -2167,16 +2158,9 @@ static void editmesh_build_data(Scene *scene, Object *obedit, EditMesh *em, Cust } editmesh_calc_modifiers(scene, obedit, em, &em->derivedCage, &em->derivedFinal, dataMask); - em->lastDataMask = dataMask; - - INIT_MINMAX(min, max); - - em->derivedFinal->getMinMax(em->derivedFinal, min, max); - - if(!obedit->bb) - obedit->bb= MEM_callocN(sizeof(BoundBox), "bb"); - boundbox_set_from_min_max(obedit->bb, min, max); + DM_set_object_boundbox (obedit, em->derivedFinal); + em->lastDataMask = dataMask; em->derivedFinal->needsFree = 0; em->derivedCage->needsFree = 0; } @@ -2624,3 +2608,17 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, } } +/* Set object's bounding box based on DerivedMesh min/max data */ +void DM_set_object_boundbox(Object *ob, DerivedMesh *dm) +{ + float min[3], max[3]; + + INIT_MINMAX(min, max); + + dm->getMinMax(dm, min, max); + + if(!ob->bb) + ob->bb= MEM_callocN(sizeof(BoundBox), "bb"); + + boundbox_set_from_min_max(ob->bb, min, max); +} diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index a3924e6c1ed..d0e50dc97a8 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -1585,6 +1585,36 @@ DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *me) return dm; } +DerivedMesh *CDDM_from_curve(Object *ob) +{ + DerivedMesh *dm; + CDDerivedMesh *cddm; + MVert *allvert; + MEdge *alledge; + MFace *allface; + int totvert, totedge, totface; + + if (nurbs_to_mdata (ob, &allvert, &totvert, &alledge, &totedge, &allface, &totface) != 0) { + /* Error initializing mdata. This often happens when curve is empty */ + return CDDM_new(0, 0, 0); + } + + dm = CDDM_new(totvert, totedge, totface); + dm->deformedOnly = 1; + + cddm = (CDDerivedMesh*)dm; + + memcpy(cddm->mvert, allvert, totvert*sizeof(MVert)); + memcpy(cddm->medge, alledge, totedge*sizeof(MEdge)); + memcpy(cddm->mface, allface, totface*sizeof(MFace)); + + MEM_freeN(allvert); + MEM_freeN(alledge); + MEM_freeN(allface); + + return dm; +} + DerivedMesh *CDDM_copy(DerivedMesh *source) { CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm"); diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 91716ce7266..b8b5ae300d9 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -65,6 +65,7 @@ #include "BKE_displist.h" #include "BKE_deform.h" #include "BKE_DerivedMesh.h" +#include "BKE_cdderivedmesh.h" #include "BKE_object.h" #include "BKE_world.h" #include "BKE_mesh.h" @@ -1209,7 +1210,7 @@ void makeDispListMBall(Scene *scene, Object *ob) boundbox_displist(ob); } -static ModifierData *curve_get_tesselate_point(Object *ob, int forRender, int editmode) +static ModifierData *curve_get_tesselate_point(Scene *scene, Object *ob, int forRender, int editmode) { ModifierData *md = modifiers_getVirtualModifierList(ob); ModifierData *preTesselatePoint; @@ -1222,10 +1223,7 @@ static ModifierData *curve_get_tesselate_point(Object *ob, int forRender, int ed preTesselatePoint = NULL; for (; md; md=md->next) { - ModifierTypeInfo *mti = modifierType_getInfo(md->type); - - if ((md->mode & required_mode) != required_mode) continue; - if (mti->isDisabled && mti->isDisabled(md, forRender)) continue; + if (!modifier_isEnabled(scene, md, required_mode)) continue; if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) { preTesselatePoint = md; @@ -1251,7 +1249,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, fl if(forRender) required_mode = eModifierMode_Render; else required_mode = eModifierMode_Realtime; - preTesselatePoint = curve_get_tesselate_point(ob, forRender, editmode); + preTesselatePoint = curve_get_tesselate_point(scene, ob, forRender, editmode); if(editmode) required_mode |= eModifierMode_Editmode; @@ -1312,11 +1310,12 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba DispList *dl; int required_mode; int editmode = (!forRender && cu->editnurb); + DerivedMesh *dm= NULL, *ndm; if(forRender) required_mode = eModifierMode_Render; else required_mode = eModifierMode_Realtime; - preTesselatePoint = curve_get_tesselate_point(ob, forRender, editmode); + preTesselatePoint = curve_get_tesselate_point(scene, ob, forRender, editmode); if(editmode) required_mode |= eModifierMode_Editmode; @@ -1324,6 +1323,10 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba md = preTesselatePoint->next; } + if (ob->derivedFinal) { + ob->derivedFinal->release (ob->derivedFinal); + } + for (; md; md=md->next) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); @@ -1331,40 +1334,84 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba if ((md->mode & required_mode) != required_mode) continue; if (mti->isDisabled && mti->isDisabled(md, forRender)) continue; - if (mti->type!=eModifierTypeType_OnlyDeform && mti->type!=eModifierTypeType_DeformOrConstruct) continue; + if (mti->type!=eModifierTypeType_OnlyDeform && + mti->type!=eModifierTypeType_DeformOrConstruct && + mti->type!=eModifierTypeType_Constructive) continue; /* need to put all verts in 1 block for curve deform */ - if(md->type==eModifierType_Curve) { - float *allverts, *fp; + /* we also need all verts in 1 block for derived mesh creation when handling constructive modifiers */ + if(md->type==eModifierType_Curve || mti->type==eModifierTypeType_Constructive) { + float *allverts = NULL, *fp; int totvert= 0; - - for (dl=dispbase->first; dl; dl=dl->next) - totvert+= (dl->type==DL_INDEX3)?dl->nr:dl->parts*dl->nr; - - fp= allverts= MEM_mallocN(totvert*sizeof(float)*3, "temp vert"); - for (dl=dispbase->first; dl; dl=dl->next) { - int offs= 3 * ((dl->type==DL_INDEX3)?dl->nr:dl->parts*dl->nr); - memcpy(fp, dl->verts, sizeof(float) * offs); - fp+= offs; + + if (md->type==eModifierType_Curve || + (mti->type==eModifierTypeType_Constructive && !dm)) { + for (dl=dispbase->first; dl; dl=dl->next) + totvert+= (dl->type==DL_INDEX3)?dl->nr:dl->parts*dl->nr; + + fp= allverts= MEM_mallocN(totvert*sizeof(float)*3, "temp vert"); + for (dl=dispbase->first; dl; dl=dl->next) { + int offs= 3 * ((dl->type==DL_INDEX3)?dl->nr:dl->parts*dl->nr); + memcpy(fp, dl->verts, sizeof(float) * offs); + fp+= offs; + } } - - mti->deformVerts(md, ob, NULL, (float(*)[3]) allverts, totvert, forRender, editmode); - - fp= allverts; - for (dl=dispbase->first; dl; dl=dl->next) { - int offs= 3 * ((dl->type==DL_INDEX3)?dl->nr:dl->parts*dl->nr); - memcpy(dl->verts, fp, sizeof(float) * offs); - fp+= offs; + + if (mti->type==eModifierTypeType_Constructive) { + if (!dm) { + dm= CDDM_from_curve(ob); + /* + * TODO: Maybe we should apply deformedVerts? + * But for now it causes invalid working of SoftBody modifier + */ + CDDM_apply_vert_coords(dm, (float(*)[3]) allverts); + CDDM_calc_normals(dm); + } + + ndm = mti->applyModifier(md, ob, dm, forRender, editmode); + + if (dm && dm != ndm) /* Modifier */ + dm->release (dm); + dm = ndm; + } else { + mti->deformVerts(md, ob, NULL, (float(*)[3]) allverts, totvert, forRender, editmode); + } + + if (allverts) { + fp= allverts; + for (dl=dispbase->first; dl; dl=dl->next) { + int offs= 3 * ((dl->type==DL_INDEX3)?dl->nr:dl->parts*dl->nr); + memcpy(dl->verts, fp, sizeof(float) * offs); + fp+= offs; + } + MEM_freeN(allverts); } - MEM_freeN(allverts); } else { - for (dl=dispbase->first; dl; dl=dl->next) { - mti->deformVerts(md, ob, NULL, (float(*)[3]) dl->verts, (dl->type==DL_INDEX3)?dl->nr:dl->parts*dl->nr, forRender, editmode); + if (dm) { + float (*deformedVerts)[3] = NULL; + int numVerts; + + numVerts = dm->getNumVerts(dm); + deformedVerts = + MEM_mallocN(sizeof(*deformedVerts) * numVerts, "dfmv"); + dm->getVertCos(dm, deformedVerts); + + mti->deformVerts(md, ob, dm, deformedVerts, numVerts, forRender, editmode); + + CDDM_apply_vert_coords(dm, deformedVerts); + + MEM_freeN(deformedVerts); + } else { + for (dl=dispbase->first; dl; dl=dl->next) { + mti->deformVerts(md, ob, dm, (float(*)[3]) dl->verts, (dl->type==DL_INDEX3)?dl->nr:dl->parts*dl->nr, forRender, editmode); + } } } } + ob->derivedFinal = dm; + if (deformedVerts) { curve_applyVertexCos(ob->data, nurb, originalVerts); MEM_freeN(originalVerts); @@ -1402,6 +1449,109 @@ static void displist_surf_indices(DispList *dl) } +static DerivedMesh *create_orco_dm(Scene *scene, Object *ob) +{ + DerivedMesh *dm; + float (*orco)[3]; + + dm= CDDM_from_curve(ob); + orco= (float(*)[3])make_orco_curve(scene, ob); + + CDDM_apply_vert_coords(dm, orco); + CDDM_calc_normals(dm); + MEM_freeN(orco); + + return dm; +} + +static void add_orco_dm(Scene *scene, Object *ob, DerivedMesh *dm, DerivedMesh *orcodm) +{ + float (*orco)[3], (*layerorco)[3]; + int totvert, a; + Curve *cu= ob->data; + + totvert= dm->getNumVerts(dm); + + if(orcodm) { + orco= MEM_callocN(sizeof(float)*3*totvert, "dm orco"); + + if(orcodm->getNumVerts(orcodm) == totvert) + orcodm->getVertCos(orcodm, orco); + else + dm->getVertCos(dm, orco); + } + else { + orco= (float(*)[3])make_orco_curve(scene, ob); + } + + for(a=0; aloc[0])/cu->size[0]; + co[1] = (co[1]-cu->loc[1])/cu->size[1]; + co[2] = (co[2]-cu->loc[2])/cu->size[2]; + } + + if((layerorco = DM_get_vert_data_layer(dm, CD_ORCO))) { + memcpy(layerorco, orco, sizeof(float)*totvert); + MEM_freeN(orco); + } + else + DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, orco); +} + +static void curve_calc_orcodm(Scene *scene, Object *ob, int forRender) +{ + /* this function represents logic of mesh's orcodm calculation */ + /* for displist-based objects */ + + ModifierData *md = modifiers_getVirtualModifierList(ob); + ModifierData *preTesselatePoint; + Curve *cu= ob->data; + int required_mode; + int editmode = (!forRender && cu->editnurb); + DerivedMesh *dm= ob->derivedFinal, *ndm, *orcodm= NULL; + + if(forRender) required_mode = eModifierMode_Render; + else required_mode = eModifierMode_Realtime; + + preTesselatePoint = curve_get_tesselate_point(scene, ob, forRender, editmode); + + if(editmode) required_mode |= eModifierMode_Editmode; + + if (preTesselatePoint) { + md = preTesselatePoint->next; + } + + for (; md; md=md->next) { + ModifierTypeInfo *mti = modifierType_getInfo(md->type); + + md->scene= scene; + + if ((md->mode & required_mode) != required_mode) continue; + if (mti->isDisabled && mti->isDisabled(md, forRender)) continue; + if (mti->type!=eModifierTypeType_Constructive) continue; + + if(!orcodm) + orcodm= create_orco_dm(scene, ob); + + ndm = mti->applyModifier(md, ob, orcodm, forRender, 0); + + if(ndm) { + /* if the modifier returned a new dm, release the old one */ + if(orcodm && orcodm != ndm) { + orcodm->release(orcodm); + } + orcodm = ndm; + } + } + + /* add an orco layer if needed */ + add_orco_dm(scene, ob, dm, orcodm); + + if(orcodm) + orcodm->release(orcodm); +} + void makeDispListSurf(Scene *scene, Object *ob, ListBase *dispbase, int forRender, int forOrco) { ListBase *nubase; @@ -1643,8 +1793,31 @@ void makeDispListCurveTypes(Scene *scene, Object *ob, int forOrco) if(!forOrco) curve_calc_modifiers_post(scene, ob, &cu->disp, 0, originalVerts, deformedVerts); tex_space_curve(cu); } - - boundbox_displist(ob); + + if (ob->derivedFinal) { + DM_set_object_boundbox (ob, ob->derivedFinal); + } else { + boundbox_displist (ob); + } +} + +/* 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 *orco; + DerivedMesh *dm= ob->derivedFinal; + + if (!dm->getVertDataArray(dm, CD_ORCO)) { + curve_calc_orcodm(scene, ob, forRender); + } + + orco= dm->getVertDataArray(dm, CD_ORCO); + + if(orco) { + orco= MEM_dupallocN(orco); + } + + return orco; } void imagestodisplist(void) @@ -1667,7 +1840,7 @@ static void boundbox_displist(Object *ob) Curve *cu= ob->data; int doit= 0; - if(cu->bb==0) cu->bb= MEM_callocN(sizeof(BoundBox), "boundbox"); + if(cu->bb==0) cu->bb= MEM_callocN(sizeof(BoundBox), "boundbox"); bb= cu->bb; dl= cu->disp.first; diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index d629acf8747..c0dd3c7e43a 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -563,31 +563,49 @@ static int vergedgesort(const void *v1, const void *v2) return 0; } -void make_edges(Mesh *me, int old) +static void mfaces_strip_loose(MFace *mface, int *totface) +{ + int a,b; + + for (a=b=0; a<*totface; a++) { + if (mface[a].v3) { + if (a!=b) { + memcpy(&mface[b],&mface[a],sizeof(mface[b])); + } + b++; + } + } + + *totface= b; +} + +/* Create edges based on known verts and faces */ +static void make_edges_mdata(MVert *allvert, MFace *allface, int totvert, int totface, + int old, MEdge **alledge, int *_totedge) { MFace *mface; MEdge *medge; struct edgesort *edsort, *ed; int a, totedge=0, final=0; - + /* we put all edges in array, sort them, and detect doubles that way */ - - for(a= me->totface, mface= me->mface; a>0; a--, mface++) { + + for(a= totface, mface= allface; a>0; a--, mface++) { if(mface->v4) totedge+=4; else if(mface->v3) totedge+=3; else totedge+=1; } - + if(totedge==0) { /* flag that mesh has edges */ - me->medge = MEM_callocN(0, "make mesh edges"); - me->totedge = 0; + (*alledge)= MEM_callocN(0, "make mesh edges"); + (*_totedge) = 0; return; } - + ed= edsort= MEM_mallocN(totedge*sizeof(struct edgesort), "edgesort"); - - for(a= me->totface, mface= me->mface; a>0; a--, mface++) { + + for(a= totface, mface= allface; a>0; a--, mface++) { to_edgesort(ed++, mface->v1, mface->v2, !mface->v3, mface->edcode & ME_V1V2); if(mface->v4) { to_edgesort(ed++, mface->v2, mface->v3, 0, mface->edcode & ME_V2V3); @@ -599,21 +617,19 @@ void make_edges(Mesh *me, int old) to_edgesort(ed++, mface->v3, mface->v1, 0, mface->edcode & ME_V3V1); } } - + qsort(edsort, totedge, sizeof(struct edgesort), vergedgesort); - + /* count final amount */ for(a=totedge, ed=edsort; a>1; a--, ed++) { /* edge is unique when it differs from next edge, or is last */ if(ed->v1 != (ed+1)->v1 || ed->v2 != (ed+1)->v2) final++; } final++; - - medge= CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, final); - me->medge= medge; - me->totedge= final; - + (*alledge)= medge= MEM_callocN(sizeof (MEdge) * final, "make_edges mdge"); + (*_totedge)= final; + for(a=totedge, ed=edsort; a>1; a--, ed++) { /* edge is unique when it differs from next edge, or is last */ if(ed->v1 != (ed+1)->v1 || ed->v2 != (ed+1)->v2) { @@ -636,6 +652,24 @@ void make_edges(Mesh *me, int old) medge->flag |= ME_EDGERENDER; MEM_freeN(edsort); +} + +void make_edges(Mesh *me, int old) +{ + MEdge *medge; + int totedge=0; + + make_edges_mdata(me->mvert, me->mface, me->totvert, me->totface, old, &medge, &totedge); + if(totedge==0) { + /* flag that mesh has edges */ + me->medge = medge; + me->totedge = 0; + return; + } + + medge= CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, totedge); + me->medge= medge; + me->totedge= totedge; mesh_strip_loose_faces(me); } @@ -657,7 +691,6 @@ void mesh_strip_loose_faces(Mesh *me) me->totface = b; } - void mball_to_mesh(ListBase *lb, Mesh *me) { DispList *dl; @@ -711,12 +744,12 @@ void mball_to_mesh(ListBase *lb, Mesh *me) } } -/* this may fail replacing ob->data, be sure to check ob->type */ -void nurbs_to_mesh(Object *ob) +/* 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, + MEdge **alledge, int *_totedge, MFace **allface, int *_totface) { - Object *ob1; DispList *dl; - Mesh *me; Curve *cu; MVert *mvert; MFace *mface; @@ -750,26 +783,15 @@ void nurbs_to_mesh(Object *ob) } dl= dl->next; } + if(totvert==0) { /* error("can't convert"); */ /* Make Sure you check ob->data is a curve */ - return; + return -1; } - /* make mesh */ - me= add_mesh("Mesh"); - me->totvert= totvert; - me->totface= totvlak; - - me->totcol= cu->totcol; - me->mat= cu->mat; - cu->mat= 0; - cu->totcol= 0; - - mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, me->totvert); - mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, me->totface); - me->mvert= mvert; - me->mface= mface; + *allvert= mvert= MEM_callocN(sizeof (MVert) * totvert, "nurbs_init mvert"); + *allface= mface= MEM_callocN(sizeof (MVert) * totvert, "nurbs_init mface"); /* verts and faces */ vertcount= 0; @@ -777,7 +799,7 @@ void nurbs_to_mesh(Object *ob) dl= cu->disp.first; while(dl) { int smooth= dl->rt & CU_SMOOTH ? 1 : 0; - + if(dl->type==DL_SEGM) { startvert= vertcount; a= dl->parts*dl->nr; @@ -812,7 +834,7 @@ void nurbs_to_mesh(Object *ob) vertcount++; mvert++; } - + for(a=0; aparts; a++) { ofs= a*dl->nr; for(b=0; bnr; b++) { @@ -844,13 +866,13 @@ void nurbs_to_mesh(Object *ob) mface->v3= startvert+index[1]; mface->v4= 0; test_index_face(mface, NULL, 0, 3); - + if(smooth) mface->flag |= ME_SMOOTH; mface++; index+= 3; } - - + + } else if(dl->type==DL_SURF) { startvert= vertcount; @@ -893,13 +915,13 @@ void nurbs_to_mesh(Object *ob) mface->v4= p2; mface->mat_nr= (unsigned char)dl->col; test_index_face(mface, NULL, 0, 4); - + if(smooth) mface->flag |= ME_SMOOTH; mface++; - p4= p3; + p4= p3; p3++; - p2= p1; + p2= p1; p1++; } } @@ -909,15 +931,62 @@ void nurbs_to_mesh(Object *ob) dl= dl->next; } - make_edges(me, 0); // all edges - mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL); + *_totvert= totvert; + *_totface= totvlak; + + make_edges_mdata(*allvert, *allface, totvert, totvlak, 0, alledge, _totedge); + mfaces_strip_loose(*allface, _totface); + + return 0; +} + +/* this may fail replacing ob->data, be sure to check ob->type */ +void nurbs_to_mesh(Object *ob) +{ + Object *ob1; + DerivedMesh *dm= ob->derivedFinal; + Mesh *me; + Curve *cu; + MVert *allvert= NULL; + MEdge *alledge= NULL; + MFace *allface= NULL; + int totvert, totedge, totface; + + cu= ob->data; + + if (dm == NULL) { + if (nurbs_to_mdata (ob, &allvert, &totvert, &alledge, &totedge, &allface, &totface) != 0) { + /* Error initializing */ + return; + } + + /* make mesh */ + me= add_mesh("Mesh"); + me->totvert= totvert; + me->totface= totface; + me->totedge= totedge; + + me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_REFERENCE, allvert, me->totvert); + me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_REFERENCE, allface, me->totface); + me->medge= CustomData_add_layer(&me->edata, CD_MEDGE, CD_REFERENCE, alledge, me->totedge); + + mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL); + } else { + me= add_mesh("Mesh"); + DM_to_mesh(dm, me); + } + + me->totcol= cu->totcol; + me->mat= cu->mat; + cu->mat= 0; + cu->totcol= 0; if(ob->data) { free_libblock(&G.main->curve, ob->data); } ob->data= me; ob->type= OB_MESH; - + /* other users */ ob1= G.main->object.first; while(ob1) { @@ -929,7 +998,6 @@ void nurbs_to_mesh(Object *ob) } ob1= ob1->id.next; } - } typedef struct EdgeLink { diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 146701f2976..0c3c1e2e041 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -163,25 +163,8 @@ static DerivedMesh *get_dm(Scene *scene, Object *ob, EditMesh *em, DerivedMesh * DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, get_mesh_orco_verts(ob)); } else if(ELEM3(ob->type,OB_FONT,OB_CURVE,OB_SURF)) { - Object *tmpobj; - Curve *tmpcu; - if(is_last_displist(ob)) { - /* copies object and modifiers (but not the data) */ - tmpobj= copy_object(ob); - tmpcu = (Curve *)tmpobj->data; - tmpcu->id.us--; - - /* copies the data */ - tmpobj->data = copy_curve((Curve *) ob->data); - - makeDispListCurveTypes(scene, tmpobj, 1); - nurbs_to_mesh(tmpobj); - - dm = CDDM_from_mesh((Mesh*)(tmpobj->data), tmpobj); - //CDDM_calc_normals(dm); - - free_libblock_us(&G.main->object, tmpobj); + dm= CDDM_from_curve(ob); } } @@ -8605,7 +8588,8 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->flags = eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode - | eModifierTypeFlag_EnableInEditmode; + | eModifierTypeFlag_EnableInEditmode + | eModifierTypeFlag_AcceptsCVs; mti->initData = subsurfModifier_initData; mti->copyData = subsurfModifier_copyData; mti->freeData = subsurfModifier_freeData; @@ -8635,7 +8619,8 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->flags = eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode - | eModifierTypeFlag_EnableInEditmode; + | eModifierTypeFlag_EnableInEditmode + | eModifierTypeFlag_AcceptsCVs; mti->initData = arrayModifier_initData; mti->copyData = arrayModifier_copyData; mti->foreachObjectLink = arrayModifier_foreachObjectLink; @@ -8648,7 +8633,8 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->flags = eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode - | eModifierTypeFlag_EnableInEditmode; + | eModifierTypeFlag_EnableInEditmode + | eModifierTypeFlag_AcceptsCVs; mti->initData = mirrorModifier_initData; mti->copyData = mirrorModifier_copyData; mti->foreachObjectLink = mirrorModifier_foreachObjectLink; @@ -8659,6 +8645,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti = INIT_TYPE(EdgeSplit); mti->type = eModifierTypeType_Constructive; mti->flags = eModifierTypeFlag_AcceptsMesh + | eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode; @@ -8956,6 +8943,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti = INIT_TYPE(Solidify); mti->type = eModifierTypeType_Constructive; mti->flags = eModifierTypeFlag_AcceptsMesh + | eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode; diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 2d7fc08aa74..cfebe91365e 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -2289,7 +2289,7 @@ BoundBox *object_get_boundbox(Object *ob) bb = mesh_get_bb(ob); } else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { - bb= ( (Curve *)ob->data )->bb; + bb= ob->bb ? ob->bb : ( (Curve *)ob->data )->bb; } else if(ob->type==OB_MBALL) { bb= ob->bb; diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index ded9004d9c6..4ab55affe44 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -418,24 +418,29 @@ static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob, } else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); - Curve *cu = ob->data; + Curve *cu; int numVerts; float (*vertexCos)[3]; - - + + if (mti->type==eModifierTypeType_Constructive) { + BKE_report(reports, RPT_ERROR, "Cannot apply constructive modifiers on curve"); + return 0; + } + + cu = ob->data; BKE_report(reports, RPT_INFO, "Applied modifier only changed CV points, not tesselated/bevel vertices"); - + if (!(md->mode&eModifierMode_Realtime) || (mti->isDisabled && mti->isDisabled(md, 0))) { BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply"); return 0; } - + vertexCos = curve_getVertexCos(cu, &cu->nurb, &numVerts); mti->deformVerts(md, ob, NULL, vertexCos, numVerts, 0, 0); curve_applyVertexCos(cu, &cu->nurb, vertexCos); MEM_freeN(vertexCos); - + DAG_id_flush_update(&ob->id, OB_RECALC_DATA); } else { diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 052edc66ed0..ac1e13a6510 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -2977,6 +2977,41 @@ static void drawDispListshaded(ListBase *lb, Object *ob) glDisableClientState(GL_COLOR_ARRAY); } +static void drawCurveDMWired(Object *ob) +{ + DerivedMesh *dm = ob->derivedFinal; + dm->drawEdges (dm, 1); +} + +/* return 1 when nothing was drawn */ +static int drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt) +{ + Object *ob= base->object; + DerivedMesh *dm = ob->derivedFinal; + Curve *cu= ob->data; + + if (!dm) { + return 1; + } + + if(dt>OB_WIRE && displist_has_faces(&cu->disp)!=0) { + int glsl = draw_glsl_material(scene, ob, v3d, dt); + GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL); + + if (!glsl) + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0); + + glEnable(GL_LIGHTING); + dm->drawFacesSolid(dm, NULL, 0, GPU_enable_material); + glDisable(GL_LIGHTING); + GPU_end_object_materials(); + } else { + drawCurveDMWired (ob); + } + + return 0; +} + /* returns 1 when nothing was drawn */ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, int dt) { @@ -2988,6 +3023,10 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas solid= (dt > OB_WIRE); + if (drawCurveDerivedMesh(scene, v3d, rv3d, base, dt) == 0) { + return 0; + } + switch(ob->type) { case OB_FONT: case OB_CURVE: @@ -5037,7 +5076,7 @@ static void draw_bounding_volume(Scene *scene, Object *ob) bb= mesh_get_bb(ob); } else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) { - bb= ( (Curve *)ob->data )->bb; + bb= ob->bb ? ob->bb : ( (Curve *)ob->data )->bb; } else if(ob->type==OB_MBALL) { bb= ob->bb; @@ -5104,9 +5143,15 @@ static void drawSolidSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base) if(ELEM3(ob->type, OB_FONT,OB_CURVE, OB_SURF)) { Curve *cu = ob->data; - if (displist_has_faces(&cu->disp) && boundbox_clip(rv3d, ob->obmat, cu->bb)) { + DerivedMesh *dm = ob->derivedFinal; + + if (displist_has_faces(&cu->disp) && boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) { draw_index_wire= 0; - drawDispListwire(&cu->disp); + if (dm) { + draw_mesh_object_outline(v3d, ob, dm); + } else { + drawDispListwire(&cu->disp); + } draw_index_wire= 1; } } else if (ob->type==OB_MBALL) { @@ -5151,10 +5196,16 @@ static void drawWireExtra(Scene *scene, RegionView3D *rv3d, Object *ob) if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) { Curve *cu = ob->data; - if (boundbox_clip(rv3d, ob->obmat, cu->bb)) { + if (boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) { if (ob->type==OB_CURVE) draw_index_wire= 0; - drawDispListwire(&cu->disp); + + if (ob->derivedFinal) { + drawCurveDMWired(ob); + } else { + drawDispListwire(&cu->disp); + } + if (ob->type==OB_CURVE) draw_index_wire= 1; } @@ -5574,7 +5625,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) } else if(dt==OB_BOUNDBOX) draw_bounding_volume(scene, ob); - else if(boundbox_clip(rv3d, ob->obmat, cu->bb)) + else if(boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) empty_object= drawDispList(scene, v3d, rv3d, base, dt); break; @@ -5587,12 +5638,12 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) } else if(dt==OB_BOUNDBOX) draw_bounding_volume(scene, ob); - else if(boundbox_clip(rv3d, ob->obmat, cu->bb)) { + else if(boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) { empty_object= drawDispList(scene, v3d, rv3d, base, dt); if(cu->path) curve_draw_speed(scene, ob); - } + } break; case OB_MBALL: { diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 0a292c7acd5..61fcb7e08f2 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -2620,7 +2620,117 @@ static int dl_surf_to_renderdata(ObjectRen *obr, DispList *dl, Material **matar, return orcoret; } -static void init_render_surf(Render *re, ObjectRen *obr) +static void init_render_dm(DerivedMesh *dm, Render *re, ObjectRen *obr, + int timeoffset, float *orco, float mat[4][4]) +{ + Object *ob= obr->ob; + int a, a1, end, totvert, vertofs; + VertRen *ver; + VlakRen *vlr; + Curve *cu; + MVert *mvert = NULL; + MFace *mface; + Material *ma; + + mvert= dm->getVertArray(dm); + totvert= dm->getNumVerts(dm); + + if ELEM(ob->type, OB_FONT, OB_CURVE) { + cu= ob->data; + } + + for(a=0; atotvert++); + VECCOPY(ver->co, mvert->co); + mul_m4_v3(mat, ver->co); + + if(orco) { + ver->orco= orco; + orco+=3; + } + } + + if(!timeoffset) { + /* store customdata names, because DerivedMesh is freed */ + RE_set_customdata_names(obr, &dm->faceData); + + /* still to do for keys: the correct local texture coordinate */ + + /* faces in order of color blocks */ + vertofs= obr->totvert - totvert; + for(a1=0; (a1totcol || (a1==0 && ob->totcol==0)); a1++) { + + ma= give_render_material(re, ob, a1+1); + end= dm->getNumFaces(dm); + mface= dm->getFaceArray(dm); + + for(a=0; amat_nr==a1 ) { + float len; + + v1= mface->v1; + v2= mface->v2; + v3= mface->v3; + v4= mface->v4; + flag= mface->flag & ME_SMOOTH; + + vlr= RE_findOrAddVlak(obr, obr->totvlak++); + vlr->v1= RE_findOrAddVert(obr, vertofs+v1); + vlr->v2= RE_findOrAddVert(obr, vertofs+v2); + vlr->v3= RE_findOrAddVert(obr, vertofs+v3); + if(v4) vlr->v4= RE_findOrAddVert(obr, vertofs+v4); + else vlr->v4= 0; + + /* render normals are inverted in render */ + if(vlr->v4) + len= normal_quad_v3( vlr->n,vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co); + else + len= normal_tri_v3( vlr->n,vlr->v3->co, vlr->v2->co, vlr->v1->co); + + vlr->mat= ma; + vlr->flag= flag; + if(cu &&(cu->flag & ME_NOPUNOFLIP)) { + vlr->flag |= R_NOPUNOFLIP; + } + vlr->ec= 0; /* mesh edges rendered separately */ + + if(len==0) obr->totvlak--; + else { + CustomDataLayer *layer; + MTFace *mtface, *mtf; + MCol *mcol, *mc; + int index, mtfn= 0, mcn= 0; + char *name; + + for(index=0; indexfaceData.totlayer; index++) { + layer= &dm->faceData.layers[index]; + name= layer->name; + + if(layer->type == CD_MTFACE && mtfn < MAX_MTFACE) { + mtf= RE_vlakren_get_tface(obr, vlr, mtfn++, &name, 1); + mtface= (MTFace*)layer->data; + *mtf= mtface[a]; + } + else if(layer->type == CD_MCOL && mcn < MAX_MCOL) { + mc= RE_vlakren_get_mcol(obr, vlr, mcn++, &name, 1); + mcol= (MCol*)layer->data; + memcpy(mc, &mcol[a*4], sizeof(MCol)*4); + } + } + } + } + } + } + + /* Normals */ + calc_vertexnormals(re, obr, 0, 0); + } + +} + +static void init_render_surf(Render *re, ObjectRen *obr, int timeoffset) { Object *ob= obr->ob; Nurb *nu=0; @@ -2630,6 +2740,7 @@ static void init_render_surf(Render *re, ObjectRen *obr) Material **matar; float *orco=NULL, *orcobase=NULL, mat[4][4]; int a, totmat, need_orco=0; + DerivedMesh *dm; cu= ob->data; nu= cu->nurb.first; @@ -2651,19 +2762,34 @@ static void init_render_surf(Render *re, ObjectRen *obr) if(ob->parent && (ob->parent->type==OB_LATTICE)) need_orco= 1; - if(need_orco) orcobase= orco= get_object_orco(re, ob); + dm= ob->derivedFinal; + if (ob->derivedFinal) { + if(need_orco) { + orco= makeOrcoDispList(re->scene, ob, 1); + if(orco) { + set_object_orco(re, ob, orco); + } + } + + init_render_dm(dm, re, obr, timeoffset, orco, mat); + } else { + if(need_orco) { + orcobase= orco= get_object_orco(re, ob); + } + + displist.first= displist.last= 0; + makeDispListSurf(re->scene, ob, &displist, 1, 0); - 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); + } - /* 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); } @@ -2674,6 +2800,7 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset) VertRen *ver; VlakRen *vlr; DispList *dl; + DerivedMesh *dm; ListBase olddl={NULL, NULL}; Material **matar; float len, *data, *fp, *orco=NULL, *orcobase= NULL; @@ -2687,11 +2814,11 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset) /* no modifier call here, is in makedisp */ - if(cu->resolu_ren) + if(cu->resolu_ren) SWAP(ListBase, olddl, cu->disp); /* test displist */ - if(cu->disp.first==NULL) + if(cu->disp.first==NULL) makeDispListCurveTypes(re->scene, ob, 0); dl= cu->disp.first; if(cu->disp.first==NULL) return; @@ -2710,89 +2837,49 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset) need_orco= 1; } - if(need_orco) orcobase=orco= get_object_orco(re, ob); - - dl= cu->disp.first; - while(dl) { - if(dl->type==DL_INDEX3) { - int *index; - - startvert= obr->totvert; - data= dl->verts; - - n[0]= ob->imat[0][2]; - n[1]= ob->imat[1][2]; - n[2]= ob->imat[2][2]; - normalize_v3(n); - - for(a=0; anr; a++, data+=3) { - ver= RE_findOrAddVert(obr, obr->totvert++); - VECCOPY(ver->co, data); - - /* flip normal if face is backfacing, also used in face loop below */ - if(ver->co[2] < 0.0) { - VECCOPY(ver->n, n); - ver->flag = 1; - } - else { - ver->n[0]= -n[0]; ver->n[1]= -n[1]; ver->n[2]= -n[2]; - ver->flag = 0; - } - - mul_m4_v3(mat, ver->co); - - if (orco) { - ver->orco = orco; - orco += 3; - } + dm= ob->derivedFinal; + if (dm) { + if(need_orco) { + orco= makeOrcoDispList(re->scene, ob, 1); + if(orco) { + set_object_orco(re, ob, orco); } - - if(timeoffset==0) { - startvlak= obr->totvlak; - index= dl->index; - for(a=0; aparts; a++, index+=3) { + } - vlr= RE_findOrAddVlak(obr, obr->totvlak++); - vlr->v1= RE_findOrAddVert(obr, startvert+index[0]); - vlr->v2= RE_findOrAddVert(obr, startvert+index[1]); - vlr->v3= RE_findOrAddVert(obr, startvert+index[2]); - vlr->v4= NULL; - - if(vlr->v1->flag) { - VECCOPY(vlr->n, n); - } - else { - vlr->n[0]= -n[0]; vlr->n[1]= -n[1]; vlr->n[2]= -n[2]; - } - - vlr->mat= matar[ dl->col ]; - vlr->flag= 0; - if( (cu->flag & CU_NOPUNOFLIP) ) { - vlr->flag |= R_NOPUNOFLIP; - } - vlr->ec= 0; - } - } + init_render_dm(dm, re, obr, timeoffset, orco, mat); + } else { + if(need_orco) { + orcobase=orco= get_object_orco(re, ob); } - else if (dl->type==DL_SURF) { - - /* cyclic U means an extruded full circular curve, we skip bevel splitting then */ - if (dl->flag & DL_CYCL_U) { - orco+= 3*dl_surf_to_renderdata(obr, dl, matar, orco, mat); - } - else { - int p1,p2,p3,p4; - fp= dl->verts; + dl= cu->disp.first; + while(dl) { + if(dl->type==DL_INDEX3) { + int *index; + startvert= obr->totvert; - nr= dl->nr*dl->parts; + data= dl->verts; + + n[0]= ob->imat[0][2]; + n[1]= ob->imat[1][2]; + n[2]= ob->imat[2][2]; + normalize_v3(n); - while(nr--) { + for(a=0; anr; a++, data+=3) { ver= RE_findOrAddVert(obr, obr->totvert++); - - VECCOPY(ver->co, fp); + VECCOPY(ver->co, data); + + /* flip normal if face is backfacing, also used in face loop below */ + if(ver->co[2] < 0.0) { + VECCOPY(ver->n, n); + ver->flag = 1; + } + else { + ver->n[0]= -n[0]; ver->n[1]= -n[1]; ver->n[2]= -n[2]; + ver->flag = 0; + } + mul_m4_v3(mat, ver->co); - fp+= 3; if (orco) { ver->orco = orco; @@ -2800,86 +2887,140 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset) } } - if(dl->bevelSplitFlag || timeoffset==0) { + if(timeoffset==0) { startvlak= obr->totvlak; + index= dl->index; + for(a=0; aparts; a++, index+=3) { - for(a=0; aparts; a++) { + vlr= RE_findOrAddVlak(obr, obr->totvlak++); + vlr->v1= RE_findOrAddVert(obr, startvert+index[0]); + vlr->v2= RE_findOrAddVert(obr, startvert+index[1]); + vlr->v3= RE_findOrAddVert(obr, startvert+index[2]); + vlr->v4= NULL; - frontside= (a >= dl->nr/2); - - if (surfindex_displist(dl, a, &b, &p1, &p2, &p3, &p4)==0) - break; - - p1+= startvert; - p2+= startvert; - p3+= startvert; - p4+= startvert; + if(vlr->v1->flag) { + VECCOPY(vlr->n, n); + } + else { + vlr->n[0]= -n[0]; vlr->n[1]= -n[1]; vlr->n[2]= -n[2]; + } - for(; bnr; b++) { - vlr= RE_findOrAddVlak(obr, obr->totvlak++); - vlr->v1= RE_findOrAddVert(obr, p2); - vlr->v2= RE_findOrAddVert(obr, p1); - vlr->v3= RE_findOrAddVert(obr, p3); - vlr->v4= RE_findOrAddVert(obr, p4); - vlr->ec= ME_V2V3+ME_V3V4; - if(a==0) vlr->ec+= ME_V1V2; - - vlr->flag= dl->rt; - - /* this is not really scientific: the vertices - * 2, 3 en 4 seem to give better vertexnormals than 1 2 3: - * front and backside treated different!! - */ - - if(frontside) - normal_tri_v3( vlr->n,vlr->v2->co, vlr->v3->co, vlr->v4->co); - else - normal_tri_v3( vlr->n,vlr->v1->co, vlr->v2->co, vlr->v3->co); - - vlr->mat= matar[ dl->col ]; - - p4= p3; - p3++; - p2= p1; - p1++; + vlr->mat= matar[ dl->col ]; + vlr->flag= 0; + if( (cu->flag & CU_NOPUNOFLIP) ) { + vlr->flag |= R_NOPUNOFLIP; } + vlr->ec= 0; } + } + } + else if (dl->type==DL_SURF) { - if (dl->bevelSplitFlag) { - for(a=0; aparts-1+!!(dl->flag&DL_CYCL_V); a++) - if(dl->bevelSplitFlag[a>>5]&(1<<(a&0x1F))) - split_v_renderfaces(obr, startvlak, startvert, dl->parts, dl->nr, a, dl->flag&DL_CYCL_V, dl->flag&DL_CYCL_U); - } + /* cyclic U means an extruded full circular curve, we skip bevel splitting then */ + if (dl->flag & DL_CYCL_U) { + orco+= 3*dl_surf_to_renderdata(obr, dl, matar, orco, mat); + } + else { + int p1,p2,p3,p4; - /* vertex normals */ - for(a= startvlak; atotvlak; a++) { - vlr= RE_findOrAddVlak(obr, a); + fp= dl->verts; + startvert= obr->totvert; + nr= dl->nr*dl->parts; - add_v3_v3v3(vlr->v1->n, vlr->v1->n, vlr->n); - add_v3_v3v3(vlr->v3->n, vlr->v3->n, vlr->n); - add_v3_v3v3(vlr->v2->n, vlr->v2->n, vlr->n); - add_v3_v3v3(vlr->v4->n, vlr->v4->n, vlr->n); - } - for(a=startvert; atotvert; a++) { - ver= RE_findOrAddVert(obr, a); - len= normalize_v3(ver->n); - if(len==0.0) ver->flag= 1; /* flag abuse, its only used in zbuf now */ - else ver->flag= 0; + while(nr--) { + ver= RE_findOrAddVert(obr, obr->totvert++); + + VECCOPY(ver->co, fp); + mul_m4_v3(mat, ver->co); + fp+= 3; + + if (orco) { + ver->orco = orco; + orco += 3; + } } - for(a= startvlak; atotvlak; a++) { - vlr= RE_findOrAddVlak(obr, a); - if(vlr->v1->flag) VECCOPY(vlr->v1->n, vlr->n); - if(vlr->v2->flag) VECCOPY(vlr->v2->n, vlr->n); - if(vlr->v3->flag) VECCOPY(vlr->v3->n, vlr->n); - if(vlr->v4->flag) VECCOPY(vlr->v4->n, vlr->n); + + if(dl->bevelSplitFlag || timeoffset==0) { + startvlak= obr->totvlak; + + for(a=0; aparts; a++) { + + frontside= (a >= dl->nr/2); + + if (surfindex_displist(dl, a, &b, &p1, &p2, &p3, &p4)==0) + break; + + p1+= startvert; + p2+= startvert; + p3+= startvert; + p4+= startvert; + + for(; bnr; b++) { + vlr= RE_findOrAddVlak(obr, obr->totvlak++); + vlr->v1= RE_findOrAddVert(obr, p2); + vlr->v2= RE_findOrAddVert(obr, p1); + vlr->v3= RE_findOrAddVert(obr, p3); + vlr->v4= RE_findOrAddVert(obr, p4); + vlr->ec= ME_V2V3+ME_V3V4; + if(a==0) vlr->ec+= ME_V1V2; + + vlr->flag= dl->rt; + + /* this is not really scientific: the vertices + * 2, 3 en 4 seem to give better vertexnormals than 1 2 3: + * front and backside treated different!! + */ + + if(frontside) + normal_tri_v3( vlr->n,vlr->v2->co, vlr->v3->co, vlr->v4->co); + else + normal_tri_v3( vlr->n,vlr->v1->co, vlr->v2->co, vlr->v3->co); + + vlr->mat= matar[ dl->col ]; + + p4= p3; + p3++; + p2= p1; + p1++; + } + } + + if (dl->bevelSplitFlag) { + for(a=0; aparts-1+!!(dl->flag&DL_CYCL_V); a++) + if(dl->bevelSplitFlag[a>>5]&(1<<(a&0x1F))) + split_v_renderfaces(obr, startvlak, startvert, dl->parts, dl->nr, a, dl->flag&DL_CYCL_V, dl->flag&DL_CYCL_U); + } + + /* vertex normals */ + for(a= startvlak; atotvlak; a++) { + vlr= RE_findOrAddVlak(obr, a); + + add_v3_v3v3(vlr->v1->n, vlr->v1->n, vlr->n); + add_v3_v3v3(vlr->v3->n, vlr->v3->n, vlr->n); + add_v3_v3v3(vlr->v2->n, vlr->v2->n, vlr->n); + add_v3_v3v3(vlr->v4->n, vlr->v4->n, vlr->n); + } + for(a=startvert; atotvert; a++) { + ver= RE_findOrAddVert(obr, a); + len= normalize_v3(ver->n); + if(len==0.0) ver->flag= 1; /* flag abuse, its only used in zbuf now */ + else ver->flag= 0; + } + for(a= startvlak; atotvlak; a++) { + vlr= RE_findOrAddVlak(obr, a); + if(vlr->v1->flag) VECCOPY(vlr->v1->n, vlr->n); + if(vlr->v2->flag) VECCOPY(vlr->v2->n, vlr->n); + if(vlr->v3->flag) VECCOPY(vlr->v3->n, vlr->n); + if(vlr->v4->flag) VECCOPY(vlr->v4->n, vlr->n); + } } } } - } - dl= dl->next; + dl= dl->next; + } } - + /* not very elegant... but we want original displist in UI */ if(cu->resolu_ren) { freedisplist(&cu->disp); @@ -2917,12 +3058,12 @@ static void to_edgesort(struct edgesort *ed, int i1, int i2, int v1, int v2, int static int vergedgesort(const void *v1, const void *v2) { const struct edgesort *x1=v1, *x2=v2; - + if( x1->v1 > x2->v1) return 1; else if( x1->v1 < x2->v1) return -1; else if( x1->v2 > x2->v2) return 1; else if( x1->v2 < x2->v2) return -1; - + return 0; } @@ -2933,14 +3074,14 @@ static struct edgesort *make_mesh_edge_lookup(DerivedMesh *dm, int *totedgesort) struct edgesort *edsort, *ed; unsigned int *mcol=NULL; int a, totedge=0, totface; - + mface= dm->getFaceArray(dm); totface= dm->getNumFaces(dm); tface= dm->getFaceDataArray(dm, CD_MTFACE); mcol= dm->getFaceDataArray(dm, CD_MCOL); - + if(mcol==NULL && tface==NULL) return NULL; - + /* make sorted table with edges and face indices in it */ for(a= totface, mf= mface; a>0; a--, mf++) { if(mf->v4) totedge+=4; @@ -2949,9 +3090,9 @@ static struct edgesort *make_mesh_edge_lookup(DerivedMesh *dm, int *totedgesort) if(totedge==0) return NULL; - + ed= edsort= MEM_callocN(totedge*sizeof(struct edgesort), "edgesort"); - + for(a=0, mf=mface; av1, mf->v2, a); to_edgesort(ed++, 1, 2, mf->v2, mf->v3, a); @@ -2962,9 +3103,9 @@ static struct edgesort *make_mesh_edge_lookup(DerivedMesh *dm, int *totedgesort) else if(mf->v3) to_edgesort(ed++, 2, 3, mf->v3, mf->v1, a); } - + qsort(edsort, totedge, sizeof(struct edgesort), vergedgesort); - + *totedgesort= totedge; return edsort; @@ -2978,7 +3119,7 @@ static void use_mesh_edge_lookup(ObjectRen *obr, DerivedMesh *dm, MEdge *medge, MCol *mcol, *mc; int index, mtfn, mcn; char *name; - + if(medge->v1 < medge->v2) { ed.v1= medge->v1; ed.v2= medge->v2; @@ -2987,7 +3128,7 @@ static void use_mesh_edge_lookup(ObjectRen *obr, DerivedMesh *dm, MEdge *medge, ed.v1= medge->v2; ed.v2= medge->v1; } - + edp= bsearch(&ed, edgetable, totedge, sizeof(struct edgesort), vergedgesort); /* since edges have different index ordering, we have to duplicate mcol and tface */ @@ -3036,17 +3177,17 @@ static void init_camera_inside_volumes(Render *re) if (obi->obr == vo->obr) { if (point_inside_volume_objectinstance(re, obi, co)) { MatInside *mi; - + mi = MEM_mallocN(sizeof(MatInside), "camera inside material"); mi->ma = vo->ma; mi->obi = obi; - + BLI_addtail(&(re->render_volumes_inside), mi); } } } } - + /* debug { MatInside *m; for (m=re->render_volumes_inside.first; m; m=m->next) { @@ -3058,12 +3199,12 @@ static void init_camera_inside_volumes(Render *re) static void add_volume(Render *re, ObjectRen *obr, Material *ma) { struct VolumeOb *vo; - + vo = MEM_mallocN(sizeof(VolumeOb), "volume object"); - + vo->ma = ma; vo->obr = obr; - + BLI_addtail(&re->volumes, vo); } @@ -4291,7 +4432,7 @@ static void init_render_object_data(Render *re, ObjectRen *obr, int timeoffset) if ELEM(ob->type, OB_FONT, OB_CURVE) init_render_curve(re, obr, timeoffset); else if(ob->type==OB_SURF) - init_render_surf(re, obr); + init_render_surf(re, obr, timeoffset); else if(ob->type==OB_MESH) init_render_mesh(re, obr, timeoffset); else if(ob->type==OB_MBALL) @@ -4299,7 +4440,7 @@ static void init_render_object_data(Render *re, ObjectRen *obr, int timeoffset) } finalize_render_object(re, obr, timeoffset); - + re->totvert += obr->totvert; re->totvlak += obr->totvlak; re->tothalo += obr->tothalo; -- cgit v1.2.3