static DerivedMesh *create_orco_dm(Scene *scene, Object *ob) { DerivedMesh *dm; ListBase disp= {NULL, NULL}; /* OrcoDM should be created from underformed disp lists */ makeDispListCurveTypes_forOrco(scene, ob, &disp); dm= CDDM_from_curve_customDB(ob, &disp); freedisplist(&disp); return dm; }
void makeDispListMBall(Scene *scene, Object *ob) { if(!ob || ob->type!=OB_MBALL) return; // XXX: mball stuff uses plenty of global variables // while this is unchanged updating during render is unsafe if(G.rendering) return; freedisplist(&(ob->disp)); if(ob->type==OB_MBALL) { if(ob==find_basis_mball(scene, ob)) { metaball_polygonize(scene, ob, &ob->disp); tex_space_mball(ob); object_deform_mball(ob, &ob->disp); } } boundbox_displist(ob); }
static void rna_ID_update_tag(ID *id, ReportList *reports, int flag) { /* XXX, new function for this! */ #if 0 if (ob->type == OB_FONT) { Curve *cu = ob->data; freedisplist(&cu->disp); BKE_vfont_to_curve(bmain, sce, ob, FO_EDIT, NULL); } #endif if (flag == 0) { /* pass */ } else { /* ensure flag us correct for the type */ switch (GS(id->name)) { case ID_OB: if (flag & ~(OB_RECALC_ALL)) { BKE_report(reports, RPT_ERROR, "'Refresh' incompatible with Object ID type"); return; } break; /* Could add particle updates later */ #if 0 case ID_PA: if (flag & ~(OB_RECALC_ALL | PSYS_RECALC)) { BKE_report(reports, RPT_ERROR, "'Refresh' incompatible with ParticleSettings ID type"); return; } break; #endif default: BKE_report(reports, RPT_ERROR, "This ID type is not compatible with any 'refresh' options"); return; } } DAG_id_tag_update(id, flag); }
void copy_displist(ListBase *lbn, ListBase *lb) { DispList *dln, *dl; freedisplist(lbn); dl= lb->first; while(dl) { dln= MEM_dupallocN(dl); BLI_addtail(lbn, dln); dln->verts= MEM_dupallocN(dl->verts); dln->nors= MEM_dupallocN(dl->nors); dln->index= MEM_dupallocN(dl->index); dln->col1= MEM_dupallocN(dl->col1); dln->col2= MEM_dupallocN(dl->col2); if(dl->bevelSplitFlag) dln->bevelSplitFlag= MEM_dupallocN(dl->bevelSplitFlag); dl= dl->next; } }
void lattice_calc_modifiers(Scene *scene, Object *ob) { Lattice *lt= ob->data; ModifierData *md = modifiers_getVirtualModifierList(ob); float (*vertexCos)[3] = NULL; int numVerts, editmode = (lt->editlatt!=NULL); freedisplist(&ob->disp); for (; md; md=md->next) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); md->scene= scene; if (!(md->mode&eModifierMode_Realtime)) continue; if (editmode && !(md->mode&eModifierMode_Editmode)) continue; if (mti->isDisabled && mti->isDisabled(md, 0)) continue; if (mti->type!=eModifierTypeType_OnlyDeform) continue; if (!vertexCos) vertexCos = lattice_getVertexCos(ob, &numVerts); mti->deformVerts(md, ob, NULL, vertexCos, numVerts, 0, 0); } /* always displist to make this work like derivedmesh */ if (!vertexCos) vertexCos = lattice_getVertexCos(ob, &numVerts); { DispList *dl = MEM_callocN(sizeof(*dl), "lt_dl"); dl->type = DL_VERTS; dl->parts = 1; dl->nr = numVerts; dl->verts = (float*) vertexCos; BLI_addtail(&ob->disp, dl); } }
static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase) { ListBase front, back; DispList *dl, *dlnew; float *fp, *fp1; int a, dpoly; front.first= front.last= back.first= back.last= NULL; dl= dispbase->first; while(dl) { if(dl->type==DL_SURF) { if( (dl->flag & DL_CYCL_V) && (dl->flag & DL_CYCL_U)==0 ) { if( (cu->flag & CU_BACK) && (dl->flag & DL_BACK_CURVE) ) { dlnew= MEM_callocN(sizeof(DispList), "filldisp"); BLI_addtail(&front, dlnew); dlnew->verts= fp1= MEM_mallocN(sizeof(float)*3*dl->parts, "filldisp1"); dlnew->nr= dl->parts; dlnew->parts= 1; dlnew->type= DL_POLY; dlnew->col= dl->col; dlnew->charidx = dl->charidx; fp= dl->verts; dpoly= 3*dl->nr; a= dl->parts; while(a--) { VECCOPY(fp1, fp); fp1+= 3; fp+= dpoly; } } if( (cu->flag & CU_FRONT) && (dl->flag & DL_FRONT_CURVE) ) { dlnew= MEM_callocN(sizeof(DispList), "filldisp"); BLI_addtail(&back, dlnew); dlnew->verts= fp1= MEM_mallocN(sizeof(float)*3*dl->parts, "filldisp1"); dlnew->nr= dl->parts; dlnew->parts= 1; dlnew->type= DL_POLY; dlnew->col= dl->col; dlnew->charidx= dl->charidx; fp= dl->verts+3*(dl->nr-1); dpoly= 3*dl->nr; a= dl->parts; while(a--) { VECCOPY(fp1, fp); fp1+= 3; fp+= dpoly; } } } } dl= dl->next; } filldisplist(&front, dispbase, 1); filldisplist(&back, dispbase, 0); freedisplist(&front); freedisplist(&back); filldisplist(dispbase, dispbase, 0); }
static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispbase, DerivedMesh **derivedFinal, int forRender, int forOrco) { Curve *cu = ob->data; /* we do allow duplis... this is only displist on curve level */ if(!ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) return; if(ob->type==OB_SURF) { makeDispListSurf(scene, ob, dispbase, derivedFinal, forRender, forOrco); } else if (ELEM(ob->type, OB_CURVE, OB_FONT)) { ListBase dlbev; ListBase *nubase; float (*originalVerts)[3]; float (*deformedVerts)[3]; int numVerts; nubase= BKE_curve_nurbs(cu); 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, forRender, &originalVerts, &deformedVerts, &numVerts); makeBevelList(ob); /* If curve has no bevel will return nothing */ makebevelcurve(scene, ob, &dlbev, forRender); /* no bevel or extrude, and no width correction? */ if (!dlbev.first && cu->width==1.0f) { curve_to_displist(cu, nubase, dispbase, forRender); } else { float widfac= cu->width - 1.0f; BevList *bl= cu->bev.first; Nurb *nu= nubase->first; for (; bl && nu; bl=bl->next,nu=nu->next) { DispList *dl; float *fp1, *data; BevPoint *bevp; int a,b; if (bl->nr) { /* blank bevel lists can happen */ /* exception handling; curve without bevel or extrude, with width correction */ if(dlbev.first==NULL) { dl= MEM_callocN(sizeof(DispList), "makeDispListbev"); dl->verts= MEM_callocN(3*sizeof(float)*bl->nr, "dlverts"); BLI_addtail(dispbase, dl); if(bl->poly!= -1) dl->type= DL_POLY; else dl->type= DL_SEGM; if(dl->type==DL_SEGM) dl->flag = (DL_FRONT_CURVE|DL_BACK_CURVE); dl->parts= 1; dl->nr= bl->nr; dl->col= nu->mat_nr; dl->charidx= nu->charidx; /* dl->rt will be used as flag for render face and */ /* CU_2D conflicts with R_NOPUNOFLIP */ dl->rt= nu->flag & ~CU_2D; a= dl->nr; bevp= (BevPoint *)(bl+1); data= dl->verts; while(a--) { data[0]= bevp->vec[0]+widfac*bevp->sina; data[1]= bevp->vec[1]+widfac*bevp->cosa; data[2]= bevp->vec[2]; bevp++; data+=3; } } else { DispList *dlb; for (dlb=dlbev.first; dlb; dlb=dlb->next) { /* for each part of the bevel use a separate displblock */ dl= MEM_callocN(sizeof(DispList), "makeDispListbev1"); dl->verts= data= MEM_callocN(3*sizeof(float)*dlb->nr*bl->nr, "dlverts"); BLI_addtail(dispbase, dl); dl->type= DL_SURF; dl->flag= dlb->flag & (DL_FRONT_CURVE|DL_BACK_CURVE); if(dlb->type==DL_POLY) dl->flag |= DL_CYCL_U; if(bl->poly>=0) dl->flag |= DL_CYCL_V; dl->parts= bl->nr; dl->nr= dlb->nr; dl->col= nu->mat_nr; dl->charidx= nu->charidx; /* dl->rt will be used as flag for render face and */ /* CU_2D conflicts with R_NOPUNOFLIP */ dl->rt= nu->flag & ~CU_2D; dl->bevelSplitFlag= MEM_callocN(sizeof(*dl->col2)*((bl->nr+0x1F)>>5), "bevelSplitFlag"); /* for each point of poly make a bevel piece */ bevp= (BevPoint *)(bl+1); for(a=0; a<bl->nr; a++,bevp++) { float fac=1.0; if (cu->taperobj==NULL) { if ( (cu->bevobj!=NULL) || !((cu->flag & CU_FRONT) || (cu->flag & CU_BACK)) ) fac = bevp->radius; } else { fac = calc_taper(scene, cu->taperobj, a, bl->nr); } if (bevp->split_tag) { dl->bevelSplitFlag[a>>5] |= 1<<(a&0x1F); } /* rotate bevel piece and write in data */ fp1= dlb->verts; for (b=0; b<dlb->nr; b++,fp1+=3,data+=3) { if(cu->flag & CU_3D) { float vec[3]; vec[0]= fp1[1]+widfac; vec[1]= fp1[2]; vec[2]= 0.0; mul_qt_v3(bevp->quat, vec); data[0]= bevp->vec[0] + fac*vec[0]; data[1]= bevp->vec[1] + fac*vec[1]; data[2]= bevp->vec[2] + fac*vec[2]; } else { data[0]= bevp->vec[0] + fac*(widfac+fp1[1])*bevp->sina; data[1]= bevp->vec[1] + fac*(widfac+fp1[1])*bevp->cosa; data[2]= bevp->vec[2] + fac*fp1[2]; } } } /* gl array drawing: using indices */ displist_surf_indices(dl); } } } } freedisplist(&dlbev); }
/* PolyFill function, uses Blenders scanfill to fill multiple poly lines */ static PyObject *M_Geometry_PolyFill( PyObject * self, PyObject * polyLineSeq ) { PyObject *tri_list; /*return this list of tri's */ PyObject *polyLine, *polyVec; int i, len_polylines, len_polypoints, ls_error = 0; /* display listbase */ ListBase dispbase={NULL, NULL}; DispList *dl; float *fp; /*pointer to the array of malloced dl->verts to set the points from the vectors */ int index, *dl_face, totpoints=0; dispbase.first= dispbase.last= NULL; if(!PySequence_Check(polyLineSeq)) { PyErr_SetString( PyExc_TypeError, "expected a sequence of poly lines" ); return NULL; } len_polylines = PySequence_Size( polyLineSeq ); for( i = 0; i < len_polylines; ++i ) { polyLine= PySequence_GetItem( polyLineSeq, i ); if (!PySequence_Check(polyLine)) { freedisplist(&dispbase); Py_XDECREF(polyLine); /* may be null so use Py_XDECREF*/ PyErr_SetString( PyExc_TypeError, "One or more of the polylines is not a sequence of Mathutils.Vector's" ); return NULL; } len_polypoints= PySequence_Size( polyLine ); if (len_polypoints>0) { /* dont bother adding edges as polylines */ #if 0 if (EXPP_check_sequence_consistency( polyLine, &vector_Type ) != 1) { freedisplist(&dispbase); Py_DECREF(polyLine); PyErr_SetString( PyExc_TypeError, "A point in one of the polylines is not a Mathutils.Vector type" ); return NULL; } #endif dl= MEM_callocN(sizeof(DispList), "poly disp"); BLI_addtail(&dispbase, dl); dl->type= DL_INDEX3; dl->nr= len_polypoints; dl->type= DL_POLY; dl->parts= 1; /* no faces, 1 edge loop */ dl->col= 0; /* no material */ dl->verts= fp= MEM_callocN( sizeof(float)*3*len_polypoints, "dl verts"); dl->index= MEM_callocN(sizeof(int)*3*len_polypoints, "dl index"); for( index = 0; index<len_polypoints; ++index, fp+=3) { polyVec= PySequence_GetItem( polyLine, index ); if(VectorObject_Check(polyVec)) { if(!BaseMath_ReadCallback((VectorObject *)polyVec)) ls_error= 1; fp[0] = ((VectorObject *)polyVec)->vec[0]; fp[1] = ((VectorObject *)polyVec)->vec[1]; if( ((VectorObject *)polyVec)->size > 2 ) fp[2] = ((VectorObject *)polyVec)->vec[2]; else fp[2]= 0.0f; /* if its a 2d vector then set the z to be zero */ } else { ls_error= 1; } totpoints++; Py_DECREF(polyVec); } } Py_DECREF(polyLine); } if(ls_error) { freedisplist(&dispbase); /* possible some dl was allocated */ PyErr_SetString( PyExc_TypeError, "A point in one of the polylines is not a Mathutils.Vector type" ); return NULL; } else if (totpoints) { /* now make the list to return */ filldisplist(&dispbase, &dispbase); /* The faces are stored in a new DisplayList thats added to the head of the listbase */ dl= dispbase.first; tri_list= PyList_New(dl->parts); if( !tri_list ) { freedisplist(&dispbase); PyErr_SetString( PyExc_RuntimeError, "Geometry.PolyFill failed to make a new list" ); return NULL; } index= 0; dl_face= dl->index; while(index < dl->parts) { PyList_SetItem(tri_list, index, Py_BuildValue("iii", dl_face[0], dl_face[1], dl_face[2]) ); dl_face+= 3; index++; } freedisplist(&dispbase); } else { /* no points, do this so scripts dont barf */ freedisplist(&dispbase); /* possible some dl was allocated */ tri_list= PyList_New(0); } return tri_list; }
/* settings: 0 - preview, 1 - render */ Mesh *rna_Object_to_mesh(Object *ob, ReportList *reports, Scene *sce, int apply_modifiers, int settings) { Mesh *tmpmesh; Curve *tmpcu = NULL; Object *tmpobj = NULL; int render = settings == eModifierMode_Render, i; int cage = !apply_modifiers; /* perform the mesh extraction based on type */ switch (ob->type) { case OB_FONT: case OB_CURVE: case OB_SURF: /* copies object and modifiers (but not the data) */ tmpobj= copy_object(ob); tmpcu = (Curve *)tmpobj->data; tmpcu->id.us--; /* if getting the original caged mesh, delete object modifiers */ if( cage ) object_free_modifiers(tmpobj); /* copies the data */ tmpobj->data = copy_curve( (Curve *) ob->data ); #if 0 /* copy_curve() sets disp.first null, so currently not need */ { Curve *cu; cu = (Curve *)tmpobj->data; if( cu->disp.first ) MEM_freeN( cu->disp.first ); cu->disp.first = NULL; } #endif /* get updated display list, and convert to a mesh */ makeDispListCurveTypes( sce, tmpobj, 0 ); nurbs_to_mesh( tmpobj ); /* nurbs_to_mesh changes the type to a mesh, check it worked */ if (tmpobj->type != OB_MESH) { free_libblock_us( &(G.main->object), tmpobj ); BKE_report(reports, RPT_ERROR, "cant convert curve to mesh. Does the curve have any segments?"); return NULL; } tmpmesh = tmpobj->data; free_libblock_us( &G.main->object, tmpobj ); break; case OB_MBALL: { /* metaballs don't have modifiers, so just convert to mesh */ Object *basis_ob = find_basis_mball(sce, ob); /* todo, re-generatre for render-res */ /* metaball_polygonize(scene, ob) */ if(ob != basis_ob) return NULL; /* only do basis metaball */ tmpmesh = add_mesh("Mesh"); if(render) { ListBase disp = {NULL, NULL}; makeDispListMBall_forRender(sce, ob, &disp); mball_to_mesh(&disp, tmpmesh); freedisplist(&disp); } else mball_to_mesh(&ob->disp, tmpmesh); break; } case OB_MESH: /* copies object and modifiers (but not the data) */ if (cage) { /* copies the data */ tmpmesh = copy_mesh( ob->data ); /* if not getting the original caged mesh, get final derived mesh */ } else { /* Make a dummy mesh, saves copying */ DerivedMesh *dm; /* CustomDataMask mask = CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL; */ CustomDataMask mask = CD_MASK_MESH; /* this seems more suitable, exporter, for example, needs CD_MASK_MDEFORMVERT */ /* Write the display mesh into the dummy mesh */ if (render) dm = mesh_create_derived_render( sce, ob, mask ); else dm = mesh_create_derived_view( sce, ob, mask ); tmpmesh = add_mesh( "Mesh" ); DM_to_mesh( dm, tmpmesh ); dm->release( dm ); } break; default: BKE_report(reports, RPT_ERROR, "Object does not have geometry data"); return NULL; } /* Copy materials to new mesh */ switch (ob->type) { case OB_SURF: case OB_FONT: case OB_CURVE: tmpmesh->totcol = tmpcu->totcol; /* free old material list (if it exists) and adjust user counts */ if( tmpcu->mat ) { for( i = tmpcu->totcol; i-- > 0; ) { /* are we an object material or data based? */ tmpmesh->mat[i] = ob->matbits[i] ? ob->mat[i] : tmpcu->mat[i]; if (tmpmesh->mat[i]) { tmpmesh->mat[i]->id.us++; } } } break; #if 0 /* Crashes when assigning the new material, not sure why */ case OB_MBALL: tmpmb = (MetaBall *)ob->data; tmpmesh->totcol = tmpmb->totcol; /* free old material list (if it exists) and adjust user counts */ if( tmpmb->mat ) { for( i = tmpmb->totcol; i-- > 0; ) { tmpmesh->mat[i] = tmpmb->mat[i]; /* CRASH HERE ??? */ if (tmpmesh->mat[i]) { tmpmb->mat[i]->id.us++; } } } break; #endif case OB_MESH: if (!cage) { Mesh *origmesh= ob->data; tmpmesh->flag= origmesh->flag; tmpmesh->mat = MEM_dupallocN(origmesh->mat); tmpmesh->totcol = origmesh->totcol; tmpmesh->smoothresh= origmesh->smoothresh; if( origmesh->mat ) { for( i = origmesh->totcol; i-- > 0; ) { /* are we an object material or data based? */ tmpmesh->mat[i] = ob->matbits[i] ? ob->mat[i] : origmesh->mat[i]; if (tmpmesh->mat[i]) { tmpmesh->mat[i]->id.us++; } } } } break; } /* end copy materials */ /* we don't assign it to anything */ tmpmesh->id.us--; /* make sure materials get updated in objects */ test_object_materials( ( ID * ) tmpmesh ); return tmpmesh; }
void resizelattice(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb) { BPoint *bp; int i, u, v, w; float fu, fv, fw, uc, vc, wc, du=0.0, dv=0.0, dw=0.0; float *co, (*vertexCos)[3] = NULL; /* vertex weight groups are just freed all for now */ if(lt->dvert) { free_dverts(lt->dvert, lt->pntsu*lt->pntsv*lt->pntsw); lt->dvert= NULL; } while(uNew*vNew*wNew > 32000) { if( uNew>=vNew && uNew>=wNew) uNew--; else if( vNew>=uNew && vNew>=wNew) vNew--; else wNew--; } vertexCos = MEM_mallocN(sizeof(*vertexCos)*uNew*vNew*wNew, "tmp_vcos"); calc_lat_fudu(lt->flag, uNew, &fu, &du); calc_lat_fudu(lt->flag, vNew, &fv, &dv); calc_lat_fudu(lt->flag, wNew, &fw, &dw); /* If old size is different then resolution changed in interface, * try to do clever reinit of points. Pretty simply idea, we just * deform new verts by old lattice, but scaling them to match old * size first. */ if (ltOb) { if (uNew!=1 && lt->pntsu!=1) { fu = lt->fu; du = (lt->pntsu-1)*lt->du/(uNew-1); } if (vNew!=1 && lt->pntsv!=1) { fv = lt->fv; dv = (lt->pntsv-1)*lt->dv/(vNew-1); } if (wNew!=1 && lt->pntsw!=1) { fw = lt->fw; dw = (lt->pntsw-1)*lt->dw/(wNew-1); } } co = vertexCos[0]; for(w=0,wc=fw; w<wNew; w++,wc+=dw) { for(v=0,vc=fv; v<vNew; v++,vc+=dv) { for(u=0,uc=fu; u<uNew; u++,co+=3,uc+=du) { co[0] = uc; co[1] = vc; co[2] = wc; } } } if (ltOb) { float mat[4][4]; int typeu = lt->typeu, typev = lt->typev, typew = lt->typew; /* works best if we force to linear type (endpoints match) */ lt->typeu = lt->typev = lt->typew = KEY_LINEAR; /* prevent using deformed locations */ freedisplist(<Ob->disp); copy_m4_m4(mat, ltOb->obmat); unit_m4(ltOb->obmat); lattice_deform_verts(ltOb, NULL, NULL, vertexCos, uNew*vNew*wNew, NULL); copy_m4_m4(ltOb->obmat, mat); lt->typeu = typeu; lt->typev = typev; lt->typew = typew; } lt->fu = fu; lt->fv = fv; lt->fw = fw; lt->du = du; lt->dv = dv; lt->dw = dw; lt->pntsu = uNew; lt->pntsv = vNew; lt->pntsw = wNew; MEM_freeN(lt->def); lt->def= MEM_callocN(lt->pntsu*lt->pntsv*lt->pntsw*sizeof(BPoint), "lattice bp"); bp= lt->def; for (i=0; i<lt->pntsu*lt->pntsv*lt->pntsw; i++,bp++) { copy_v3_v3(bp->vec, vertexCos[i]); } MEM_freeN(vertexCos); }