- convert mesh_modifier to return deformed verts instead of
leaving in a DL_VERTS type displist (and modifying mesh) - removed DL_VERTS displist type (woot woot) - makeDispListMesh now puts deformed verts in object->derivedDeform - switch over other system parts to new deformed vert storage, still kinda hacky and maybe some inconsistencies... will be sorted out soon enough. - moved build_particle_system to makeDispListMesh... this may have adverse side effects, needs to be sorted out with depgraph system
This commit is contained in:
@@ -45,6 +45,7 @@
|
|||||||
* conversion to DLM.
|
* conversion to DLM.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
struct MVert;
|
||||||
struct Object;
|
struct Object;
|
||||||
struct EditMesh;
|
struct EditMesh;
|
||||||
struct EditVert;
|
struct EditVert;
|
||||||
@@ -142,8 +143,9 @@ struct DerivedMesh {
|
|||||||
void (*release)(DerivedMesh *dm);
|
void (*release)(DerivedMesh *dm);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Internal function, just temporarily exposed */
|
/* Internal functions, just temporarily exposed */
|
||||||
DerivedMesh *derivedmesh_from_displistmesh(struct DispListMesh *dlm);
|
DerivedMesh *derivedmesh_from_displistmesh(struct DispListMesh *dlm);
|
||||||
|
DerivedMesh *derivedmesh_from_mesh(struct Object *ob, struct MVert *deformedVerts);
|
||||||
|
|
||||||
DerivedMesh *mesh_get_derived(struct Object *ob);
|
DerivedMesh *mesh_get_derived(struct Object *ob);
|
||||||
DerivedMesh *mesh_get_derived_final(struct Object *ob, int *needsFree_r);
|
DerivedMesh *mesh_get_derived_final(struct Object *ob, int *needsFree_r);
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
|
|
||||||
struct Object;
|
struct Object;
|
||||||
struct ListBase;
|
struct ListBase;
|
||||||
|
struct MVert;
|
||||||
struct bDeformGroup;
|
struct bDeformGroup;
|
||||||
|
|
||||||
void copy_defgroups (struct ListBase *lb1, struct ListBase *lb2);
|
void copy_defgroups (struct ListBase *lb1, struct ListBase *lb2);
|
||||||
@@ -50,7 +51,7 @@ int get_defgroup_num (struct Object *ob, struct bDeformGroup *dg);
|
|||||||
void hook_object_deform(struct Object *ob, int index, float *vec);
|
void hook_object_deform(struct Object *ob, int index, float *vec);
|
||||||
|
|
||||||
int curve_modifier(struct Object *ob, char mode);
|
int curve_modifier(struct Object *ob, char mode);
|
||||||
int mesh_modifier(struct Object *ob, char mode);
|
void mesh_modifier(struct Object *ob, struct MVert **mvert_r);
|
||||||
int lattice_modifier(struct Object *ob, char mode);
|
int lattice_modifier(struct Object *ob, char mode);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ struct DerivedMesh;
|
|||||||
struct EditMesh;
|
struct EditMesh;
|
||||||
|
|
||||||
struct DerivedMesh *subsurf_make_derived_from_editmesh(struct EditMesh *em, int subdivLevels, short type, struct DerivedMesh *oldDerived);
|
struct DerivedMesh *subsurf_make_derived_from_editmesh(struct EditMesh *em, int subdivLevels, short type, struct DerivedMesh *oldDerived);
|
||||||
struct DerivedMesh *subsurf_make_derived_from_mesh(struct Mesh *me, int subdivLevels);
|
struct DerivedMesh *subsurf_make_derived_from_mesh(struct Object *ob, int subdivLevels, int useDeformVerts);
|
||||||
|
|
||||||
void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3]);
|
void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3]);
|
||||||
|
|
||||||
|
|||||||
@@ -445,9 +445,17 @@ static int meshDM_getNumFaces(DerivedMesh *dm)
|
|||||||
return me->totface;
|
return me->totface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void meshDM_release(DerivedMesh *dm)
|
||||||
|
{
|
||||||
|
MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
|
||||||
|
|
||||||
|
if (mdm->extverts) MEM_freeN(mdm->extverts);
|
||||||
|
MEM_freeN(mdm);
|
||||||
|
}
|
||||||
|
|
||||||
static DerivedMesh *getMeshDerivedMesh(Object *ob, float *extverts, float *nors)
|
static DerivedMesh *getMeshDerivedMesh(Object *ob, float *extverts, float *nors)
|
||||||
{
|
{
|
||||||
MeshDerivedMesh *mdm = MEM_callocN(sizeof(*mdm), "dm");
|
MeshDerivedMesh *mdm = MEM_callocN(sizeof(*mdm), "mdm");
|
||||||
|
|
||||||
mdm->dm.getMinMax = meshDM_getMinMax;
|
mdm->dm.getMinMax = meshDM_getMinMax;
|
||||||
|
|
||||||
@@ -468,7 +476,7 @@ static DerivedMesh *getMeshDerivedMesh(Object *ob, float *extverts, float *nors)
|
|||||||
mdm->dm.drawFacesColored = meshDM_drawFacesColored;
|
mdm->dm.drawFacesColored = meshDM_drawFacesColored;
|
||||||
mdm->dm.drawFacesTex = meshDM_drawFacesTex;
|
mdm->dm.drawFacesTex = meshDM_drawFacesTex;
|
||||||
|
|
||||||
mdm->dm.release = (void(*)(DerivedMesh*)) MEM_freeN;
|
mdm->dm.release = meshDM_release;
|
||||||
|
|
||||||
mdm->ob = ob;
|
mdm->ob = ob;
|
||||||
mdm->extverts = extverts;
|
mdm->extverts = extverts;
|
||||||
@@ -604,7 +612,7 @@ static int emDM_getNumFaces(DerivedMesh *dm)
|
|||||||
|
|
||||||
static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em)
|
static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em)
|
||||||
{
|
{
|
||||||
EditMeshDerivedMesh *emdm = MEM_callocN(sizeof(*emdm), "dm");
|
EditMeshDerivedMesh *emdm = MEM_callocN(sizeof(*emdm), "emdm");
|
||||||
|
|
||||||
emdm->dm.getMinMax = emDM_getMinMax;
|
emdm->dm.getMinMax = emDM_getMinMax;
|
||||||
|
|
||||||
@@ -881,6 +889,7 @@ static void ssDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
|
|||||||
DO_MINMAX(ssdm->dlm->mvert[i].co, min_r, max_r);
|
DO_MINMAX(ssdm->dlm->mvert[i].co, min_r, max_r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ssDM_getNumVerts(DerivedMesh *dm)
|
static int ssDM_getNumVerts(DerivedMesh *dm)
|
||||||
{
|
{
|
||||||
SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
|
SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
|
||||||
@@ -912,7 +921,7 @@ static void ssDM_release(DerivedMesh *dm)
|
|||||||
|
|
||||||
DerivedMesh *derivedmesh_from_displistmesh(DispListMesh *dlm)
|
DerivedMesh *derivedmesh_from_displistmesh(DispListMesh *dlm)
|
||||||
{
|
{
|
||||||
SSDerivedMesh *ssdm = MEM_callocN(sizeof(*ssdm), "dm");
|
SSDerivedMesh *ssdm = MEM_callocN(sizeof(*ssdm), "ssdm");
|
||||||
|
|
||||||
ssdm->dm.getMinMax = ssDM_getMinMax;
|
ssdm->dm.getMinMax = ssDM_getMinMax;
|
||||||
|
|
||||||
@@ -988,31 +997,26 @@ DerivedMesh *mesh_get_derived_final(Object *ob, int *needsFree_r)
|
|||||||
return me->derived;
|
return me->derived;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DispList *dl;
|
return mesh_get_derived_deform(ob, needsFree_r);
|
||||||
DispList *meDL;
|
|
||||||
|
|
||||||
*needsFree_r = 1;
|
|
||||||
dl = find_displist(&ob->disp, DL_VERTS);
|
|
||||||
meDL = me->disp.first;
|
|
||||||
return getMeshDerivedMesh(ob, dl?dl->verts:NULL, meDL?meDL->nors:NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DerivedMesh *mesh_get_derived_deform(Object *ob, int *needsFree_r)
|
DerivedMesh *mesh_get_derived_deform(Object *ob, int *needsFree_r)
|
||||||
{
|
{
|
||||||
Mesh *me = ob->data;
|
if (ob->derivedDeform) {
|
||||||
DispList *dl;
|
*needsFree_r = 0;
|
||||||
DispList *meDL;
|
return ob->derivedDeform;
|
||||||
|
} else {
|
||||||
|
Mesh *me = ob->data;
|
||||||
|
DispList *meDL;
|
||||||
|
|
||||||
build_mesh_data(ob, G.obedit && me==G.obedit->data);
|
build_mesh_data(ob, G.obedit && me==G.obedit->data);
|
||||||
|
|
||||||
*needsFree_r = 1;
|
*needsFree_r = 1;
|
||||||
dl = find_displist(&ob->disp, DL_VERTS);
|
meDL = me->disp.first;
|
||||||
meDL = me->disp.first;
|
|
||||||
|
|
||||||
return getMeshDerivedMesh(ob, dl?dl->verts:NULL, meDL?meDL->nors:NULL);
|
return getMeshDerivedMesh(ob, NULL, meDL?meDL->nors:NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DerivedMesh *mesh_get_derived_render(Object *ob, int *needsFree_r)
|
DerivedMesh *mesh_get_derived_render(Object *ob, int *needsFree_r)
|
||||||
@@ -1035,16 +1039,10 @@ DerivedMesh *mesh_get_derived_render(Object *ob, int *needsFree_r)
|
|||||||
if(G.obedit && me==G.obedit->data) {
|
if(G.obedit && me==G.obedit->data) {
|
||||||
return subsurf_make_derived_from_editmesh(G.editMesh, me->subdivr, me->subsurftype, NULL);
|
return subsurf_make_derived_from_editmesh(G.editMesh, me->subdivr, me->subsurftype, NULL);
|
||||||
} else {
|
} else {
|
||||||
return subsurf_make_derived_from_mesh(me, me->subdivr);
|
return subsurf_make_derived_from_mesh(ob, me->subdivr, 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DispList *dl;
|
return mesh_get_derived_deform(ob, needsFree_r);
|
||||||
DispList *meDL;
|
|
||||||
|
|
||||||
*needsFree_r = 1;
|
|
||||||
dl = find_displist(&ob->disp, DL_VERTS);
|
|
||||||
meDL = me->disp.first;
|
|
||||||
return getMeshDerivedMesh(ob, dl?dl->verts:NULL, meDL?meDL->nors:NULL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1058,10 +1056,9 @@ DerivedMesh *mesh_get_base_derived(Object *ob)
|
|||||||
if (G.obedit && me==G.obedit->data) {
|
if (G.obedit && me==G.obedit->data) {
|
||||||
return getEditMeshDerivedMesh(G.editMesh);
|
return getEditMeshDerivedMesh(G.editMesh);
|
||||||
} else {
|
} else {
|
||||||
DispList *dl = find_displist(&ob->disp, DL_VERTS);
|
|
||||||
DispList *meDL = me->disp.first;
|
DispList *meDL = me->disp.first;
|
||||||
|
|
||||||
return getMeshDerivedMesh(ob, dl?dl->verts:NULL, meDL?meDL->nors:NULL);
|
return getMeshDerivedMesh(ob, NULL, meDL?meDL->nors:NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1082,3 +1079,20 @@ DerivedMesh *mesh_get_cage_derived(struct Object *ob, int *needsFree_r)
|
|||||||
|
|
||||||
return dm;
|
return dm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DerivedMesh *derivedmesh_from_mesh(Object *ob, MVert *deformedVerts)
|
||||||
|
{
|
||||||
|
Mesh *me = ob->data;
|
||||||
|
float *extverts = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (deformedVerts) {
|
||||||
|
extverts = MEM_mallocN(sizeof(float)*3*me->totvert, "extverts");
|
||||||
|
for (i=0; i<me->totvert; i++) {
|
||||||
|
VECCOPY(&extverts[i*3], deformedVerts[i].co);
|
||||||
|
}
|
||||||
|
MEM_freeN(deformedVerts);
|
||||||
|
}
|
||||||
|
|
||||||
|
return getMeshDerivedMesh(ob, extverts, NULL);
|
||||||
|
}
|
||||||
|
|||||||
@@ -227,16 +227,14 @@ void hook_object_deform(Object *ob, int index, float *vec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* modifiers: hooks, deform, softbody
|
void mesh_modifier(Object *ob, MVert **mvert_r)
|
||||||
mode=='s' is start, 'e' is end , 'a' is apply
|
|
||||||
*/
|
|
||||||
|
|
||||||
int mesh_modifier(Object *ob, char mode)
|
|
||||||
{
|
{
|
||||||
static MVert *mvert=NULL;
|
MVert *origMVert=NULL;
|
||||||
Mesh *me= ob->data;
|
Mesh *me= ob->data;
|
||||||
MVert *mv;
|
MVert *mv;
|
||||||
int a, done=0;
|
int a, done=0;
|
||||||
|
|
||||||
|
*mvert_r = NULL;
|
||||||
|
|
||||||
do_mesh_key(me);
|
do_mesh_key(me);
|
||||||
|
|
||||||
@@ -246,70 +244,43 @@ int mesh_modifier(Object *ob, char mode)
|
|||||||
else if(ob->parent && ob->parent->type==OB_LATTICE);
|
else if(ob->parent && ob->parent->type==OB_LATTICE);
|
||||||
else if(ob->parent && ob->partype==PARSKEL);
|
else if(ob->parent && ob->partype==PARSKEL);
|
||||||
else if(ob->softflag & OB_SB_ENABLE);
|
else if(ob->softflag & OB_SB_ENABLE);
|
||||||
else return 0;
|
else return;
|
||||||
|
|
||||||
if(me->totvert==0) return 0;
|
if(me->totvert==0) return;
|
||||||
|
|
||||||
if(mode=='s') { // "start"
|
origMVert= MEM_dupallocN(me->mvert);
|
||||||
/* copy */
|
|
||||||
mvert= MEM_dupallocN(me->mvert);
|
|
||||||
|
|
||||||
/* hooks */
|
/* hooks */
|
||||||
if(ob->hooks.first) {
|
if(ob->hooks.first) {
|
||||||
done= 1;
|
done= 1;
|
||||||
|
|
||||||
/* NULL signals initialize */
|
|
||||||
hook_object_deform(ob, 0, NULL);
|
|
||||||
|
|
||||||
for(a=0, mv= me->mvert; a<me->totvert; a++, mv++) {
|
|
||||||
hook_object_deform(ob, a, mv->co);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ob->effect.first) done |= object_wave(ob);
|
/* NULL signals initialize */
|
||||||
|
hook_object_deform(ob, 0, NULL);
|
||||||
if((ob->softflag & OB_SB_ENABLE) && !(ob->softflag & OB_SB_POSTDEF)) {
|
|
||||||
done= 1;
|
|
||||||
sbObjectStep(ob, (float)G.scene->r.cfra);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* object_deform: output for mesh is in mesh->mvert */
|
|
||||||
done |= object_deform(ob);
|
|
||||||
|
|
||||||
if((ob->softflag & OB_SB_ENABLE) && (ob->softflag & OB_SB_POSTDEF)) {
|
|
||||||
done= 1;
|
|
||||||
sbObjectStep(ob, (float)G.scene->r.cfra);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* put deformed vertices in dl->verts, optional subsurf will replace that */
|
for(a=0, mv= me->mvert; a<me->totvert; a++, mv++) {
|
||||||
if(done) {
|
hook_object_deform(ob, a, mv->co);
|
||||||
DispList *dl= find_displist_create(&ob->disp, DL_VERTS); // removed after switchover
|
|
||||||
float *fp;
|
|
||||||
|
|
||||||
if(dl->verts) MEM_freeN(dl->verts);
|
|
||||||
if(dl->nors) MEM_freeN(dl->nors);
|
|
||||||
dl->nr= me->totvert;
|
|
||||||
if(dl->nr) {
|
|
||||||
|
|
||||||
/* make disp array */
|
|
||||||
dl->verts= fp= MEM_mallocN(3*sizeof(float)*me->totvert, "deform1");
|
|
||||||
mv= me->mvert;
|
|
||||||
for(a=0; a<me->totvert; a++, mv++, fp+=3) {
|
|
||||||
VECCOPY(fp, mv->co);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else if(mode=='e') { // end
|
|
||||||
if(mvert) {
|
|
||||||
if(me->mvert) MEM_freeN(me->mvert);
|
|
||||||
me->mvert= mvert;
|
|
||||||
mvert= NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return done;
|
if(ob->effect.first) done |= object_wave(ob);
|
||||||
|
|
||||||
|
if((ob->softflag & OB_SB_ENABLE) && !(ob->softflag & OB_SB_POSTDEF)) {
|
||||||
|
done= 1;
|
||||||
|
sbObjectStep(ob, (float)G.scene->r.cfra);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* object_deform: output for mesh is in mesh->mvert */
|
||||||
|
done |= object_deform(ob);
|
||||||
|
|
||||||
|
if((ob->softflag & OB_SB_ENABLE) && (ob->softflag & OB_SB_POSTDEF)) {
|
||||||
|
done= 1;
|
||||||
|
sbObjectStep(ob, (float)G.scene->r.cfra);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (done) {
|
||||||
|
*mvert_r = me->mvert;
|
||||||
|
me->mvert = origMVert;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int curve_modifier(Object *ob, char mode)
|
int curve_modifier(Object *ob, char mode)
|
||||||
|
|||||||
@@ -1166,7 +1166,6 @@ void shadeDispList(Object *ob)
|
|||||||
|
|
||||||
void reshadeall_displist(void)
|
void reshadeall_displist(void)
|
||||||
{
|
{
|
||||||
DispList *dldeform;
|
|
||||||
Base *base;
|
Base *base;
|
||||||
Object *ob;
|
Object *ob;
|
||||||
|
|
||||||
@@ -1175,17 +1174,11 @@ void reshadeall_displist(void)
|
|||||||
base= G.scene->base.first;
|
base= G.scene->base.first;
|
||||||
while(base) {
|
while(base) {
|
||||||
if(base->lay & G.scene->lay) {
|
if(base->lay & G.scene->lay) {
|
||||||
|
|
||||||
ob= base->object;
|
ob= base->object;
|
||||||
|
|
||||||
dldeform= find_displist(&ob->disp, DL_VERTS); // removed after switchover
|
|
||||||
if(dldeform) BLI_remlink(&ob->disp, dldeform);
|
|
||||||
|
|
||||||
/* Metaballs have standard displist at the Object */
|
/* Metaballs have standard displist at the Object */
|
||||||
if(ob->type==OB_MBALL) shadeDispList(ob);
|
if(ob->type==OB_MBALL) shadeDispList(ob);
|
||||||
else freedisplist(&ob->disp);
|
else freedisplist(&ob->disp);
|
||||||
|
|
||||||
if(dldeform) BLI_addtail(&ob->disp, dldeform);
|
|
||||||
}
|
}
|
||||||
base= base->next;
|
base= base->next;
|
||||||
}
|
}
|
||||||
@@ -1600,12 +1593,12 @@ float calc_taper(Object *taperobj, int cur, int tot)
|
|||||||
|
|
||||||
void makeDispListMesh(Object *ob)
|
void makeDispListMesh(Object *ob)
|
||||||
{
|
{
|
||||||
|
MVert *deformedMVerts = NULL;
|
||||||
Mesh *me;
|
Mesh *me;
|
||||||
|
|
||||||
if(!ob || (ob->flag&OB_FROMDUPLI) || ob->type!=OB_MESH) return;
|
if(!ob || (ob->flag&OB_FROMDUPLI) || ob->type!=OB_MESH) return;
|
||||||
me= ob->data;
|
me= ob->data;
|
||||||
|
|
||||||
|
|
||||||
/* also serves as signal to remake texspace */
|
/* also serves as signal to remake texspace */
|
||||||
if (me->bb) {
|
if (me->bb) {
|
||||||
MEM_freeN(me->bb);
|
MEM_freeN(me->bb);
|
||||||
@@ -1619,20 +1612,54 @@ void makeDispListMesh(Object *ob)
|
|||||||
me->derived->release(me->derived);
|
me->derived->release(me->derived);
|
||||||
me->derived= NULL;
|
me->derived= NULL;
|
||||||
}
|
}
|
||||||
|
if (ob->derivedDeform) {
|
||||||
|
ob->derivedDeform->release(ob->derivedDeform);
|
||||||
|
ob->derivedDeform= NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (ob!=G.obedit) mesh_modifier(ob, 's');
|
if (ob!=G.obedit) {
|
||||||
|
mesh_modifier(ob, &deformedMVerts);
|
||||||
|
|
||||||
|
if (deformedMVerts) {
|
||||||
|
ob->derivedDeform = derivedmesh_from_mesh(ob, deformedMVerts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (mesh_uses_displist(me)) { /* subsurf */
|
if (mesh_uses_displist(me)) { /* subsurf */
|
||||||
if (ob==G.obedit) {
|
if (ob==G.obedit) {
|
||||||
G.editMesh->derived= subsurf_make_derived_from_editmesh(G.editMesh, me->subdiv, me->subsurftype, G.editMesh->derived);
|
G.editMesh->derived= subsurf_make_derived_from_editmesh(G.editMesh, me->subdiv, me->subsurftype, G.editMesh->derived);
|
||||||
} else {
|
} else {
|
||||||
me->derived= subsurf_make_derived_from_mesh(me, me->subdiv);
|
me->derived= subsurf_make_derived_from_mesh(ob, me->subdiv, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
BoundBox *bb=0;
|
||||||
|
float min[3], max[3];
|
||||||
|
|
||||||
|
INIT_MINMAX(min, max);
|
||||||
|
|
||||||
|
bb= mesh_get_bb(ob->data);
|
||||||
|
|
||||||
|
if (me->derived) {
|
||||||
|
me->derived->getMinMax(me->derived, min, max);
|
||||||
|
} else if (ob->derivedDeform) {
|
||||||
|
ob->derivedDeform->getMinMax(ob->derivedDeform, min, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bb) {
|
||||||
|
bb->vec[0][0]=bb->vec[1][0]=bb->vec[2][0]=bb->vec[3][0]= min[0];
|
||||||
|
bb->vec[4][0]=bb->vec[5][0]=bb->vec[6][0]=bb->vec[7][0]= max[0];
|
||||||
|
|
||||||
|
bb->vec[0][1]=bb->vec[1][1]=bb->vec[4][1]=bb->vec[5][1]= min[1];
|
||||||
|
bb->vec[2][1]=bb->vec[3][1]=bb->vec[6][1]=bb->vec[7][1]= max[1];
|
||||||
|
|
||||||
|
bb->vec[0][2]=bb->vec[3][2]=bb->vec[4][2]=bb->vec[7][2]= min[2];
|
||||||
|
bb->vec[1][2]=bb->vec[2][2]=bb->vec[5][2]=bb->vec[6][2]= max[2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ob!=G.obedit) mesh_modifier(ob, 'e');
|
build_particle_system(ob);
|
||||||
|
|
||||||
boundbox_displist(ob);
|
|
||||||
}
|
}
|
||||||
void makeDispListMBall(Object *ob)
|
void makeDispListMBall(Object *ob)
|
||||||
{
|
{
|
||||||
@@ -2219,17 +2246,7 @@ static void boundbox_displist(Object *ob)
|
|||||||
|
|
||||||
INIT_MINMAX(min, max);
|
INIT_MINMAX(min, max);
|
||||||
|
|
||||||
if(ob->type==OB_MESH) {
|
if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
|
||||||
bb= mesh_get_bb(ob->data);
|
|
||||||
dl= find_displist(&ob->disp, DL_VERTS);
|
|
||||||
if(!dl) return;
|
|
||||||
|
|
||||||
vert= dl->verts;
|
|
||||||
for(a=0; a<dl->nr; a++, vert+=3) {
|
|
||||||
DO_MINMAX(vert, min, max);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
|
|
||||||
Curve *cu= ob->data;
|
Curve *cu= ob->data;
|
||||||
|
|
||||||
if(cu->bb==0) cu->bb= MEM_callocN(sizeof(BoundBox), "boundbox");
|
if(cu->bb==0) cu->bb= MEM_callocN(sizeof(BoundBox), "boundbox");
|
||||||
|
|||||||
@@ -456,7 +456,7 @@ void make_orco_displist_mesh(Object *ob, int subdivlvl)
|
|||||||
cp_key(0, me->totvert, me->totvert, (char*) me->mvert->co, me->key, me->key->refkey, 0);
|
cp_key(0, me->totvert, me->totvert, (char*) me->mvert->co, me->key, me->key->refkey, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
dm= subsurf_make_derived_from_mesh(me, subdivlvl);
|
dm= subsurf_make_derived_from_mesh(ob, subdivlvl, 0);
|
||||||
dlm= dm->convertToDispListMesh(dm);
|
dlm= dm->convertToDispListMesh(dm);
|
||||||
dm->release(dm);
|
dm->release(dm);
|
||||||
|
|
||||||
|
|||||||
@@ -71,6 +71,8 @@ typedef struct _SubSurf {
|
|||||||
|
|
||||||
/* used by mesh control type */
|
/* used by mesh control type */
|
||||||
Mesh *me;
|
Mesh *me;
|
||||||
|
|
||||||
|
Object *deformOb;
|
||||||
} SubSurf;
|
} SubSurf;
|
||||||
|
|
||||||
typedef struct _VertData {
|
typedef struct _VertData {
|
||||||
@@ -132,7 +134,7 @@ static CCGSubSurf *_getSubSurf(SubSurf *ss, int subdivLevels, int useArena) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static SubSurf *subSurf_fromEditmesh(EditMesh *em, int subdivLevels, int useAging, int useArena) {
|
static SubSurf *subSurf_fromEditmesh(EditMesh *em, int subdivLevels, int useAging, int useArena) {
|
||||||
SubSurf *ss = MEM_mallocN(sizeof(*ss), "ss");
|
SubSurf *ss = MEM_mallocN(sizeof(*ss), "ss_em");
|
||||||
|
|
||||||
ss->useAging = useAging;
|
ss->useAging = useAging;
|
||||||
ss->controlType = SUBSURF_CONTROLTYPE_EDITMESH;
|
ss->controlType = SUBSURF_CONTROLTYPE_EDITMESH;
|
||||||
@@ -142,13 +144,14 @@ static SubSurf *subSurf_fromEditmesh(EditMesh *em, int subdivLevels, int useAgin
|
|||||||
return ss;
|
return ss;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SubSurf *subSurf_fromMesh(Mesh *me, int useFlatSubdiv, int subdivLevels) {
|
static SubSurf *subSurf_fromMesh(Mesh *me, int useFlatSubdiv, int subdivLevels, Object *deformOb) {
|
||||||
SubSurf *ss = MEM_mallocN(sizeof(*ss), "ss");
|
SubSurf *ss = MEM_mallocN(sizeof(*ss), "ss_m");
|
||||||
|
|
||||||
ss->controlType = SUBSURF_CONTROLTYPE_MESH;
|
ss->controlType = SUBSURF_CONTROLTYPE_MESH;
|
||||||
ss->useAging=0;
|
ss->useAging=0;
|
||||||
ss->subSurf = _getSubSurf(ss, subdivLevels, 1);
|
ss->subSurf = _getSubSurf(ss, subdivLevels, 1);
|
||||||
ss->me = me;
|
ss->me = me;
|
||||||
|
ss->deformOb = deformOb;
|
||||||
|
|
||||||
ccgSubSurf_setAllowEdgeCreation(ss->subSurf, 1, useFlatSubdiv?subdivLevels:0.0f);
|
ccgSubSurf_setAllowEdgeCreation(ss->subSurf, 1, useFlatSubdiv?subdivLevels:0.0f);
|
||||||
|
|
||||||
@@ -504,8 +507,18 @@ static void subSurf_sync(SubSurf *ss, int useFlatSubdiv) {
|
|||||||
CCGVertHDL fVerts[4];
|
CCGVertHDL fVerts[4];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i=0; i<ss->me->totvert; i++) {
|
if (ss->deformOb && ss->deformOb->derivedDeform) {
|
||||||
ccgSubSurf_syncVert(ss->subSurf, (CCGVertHDL) i, ss->me->mvert[i].co);
|
DispListMesh *dlm = ss->deformOb->derivedDeform->convertToDispListMesh(ss->deformOb->derivedDeform);
|
||||||
|
|
||||||
|
for (i=0; i<ss->me->totvert; i++) {
|
||||||
|
ccgSubSurf_syncVert(ss->subSurf, (CCGVertHDL) i, dlm->mvert[i].co);
|
||||||
|
}
|
||||||
|
|
||||||
|
displistmesh_free(dlm);
|
||||||
|
} else {
|
||||||
|
for (i=0; i<ss->me->totvert; i++) {
|
||||||
|
ccgSubSurf_syncVert(ss->subSurf, (CCGVertHDL) i, ss->me->mvert[i].co);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ss->me->medge) {
|
if (ss->me->medge) {
|
||||||
@@ -954,7 +967,7 @@ static void ccgDM_release(DerivedMesh *dm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static CCGDerivedMesh *getCCGDerivedMesh(SubSurf *ss) {
|
static CCGDerivedMesh *getCCGDerivedMesh(SubSurf *ss) {
|
||||||
CCGDerivedMesh *ccgdm = MEM_mallocN(sizeof(*ccgdm), "dm");
|
CCGDerivedMesh *ccgdm = MEM_mallocN(sizeof(*ccgdm), "ccgdm");
|
||||||
|
|
||||||
ccgdm->dm.getMinMax = ccgDM_getMinMax;
|
ccgdm->dm.getMinMax = ccgDM_getMinMax;
|
||||||
ccgdm->dm.getNumVerts = ccgDM_getNumVerts;
|
ccgdm->dm.getNumVerts = ccgDM_getNumVerts;
|
||||||
@@ -1001,9 +1014,10 @@ DerivedMesh *subsurf_make_derived_from_editmesh(EditMesh *em, int subdivLevels,
|
|||||||
return (DerivedMesh*) ccgdm;
|
return (DerivedMesh*) ccgdm;
|
||||||
}
|
}
|
||||||
|
|
||||||
DerivedMesh *subsurf_make_derived_from_mesh(Mesh *me, int subdivLevels) {
|
DerivedMesh *subsurf_make_derived_from_mesh(Object *ob, int subdivLevels, int useDeformVerts) {
|
||||||
|
Mesh *me = ob->data;
|
||||||
int useFlatSubdiv = me->subsurftype==ME_SIMPLE_SUBSURF;
|
int useFlatSubdiv = me->subsurftype==ME_SIMPLE_SUBSURF;
|
||||||
SubSurf *ss = subSurf_fromMesh(me, useFlatSubdiv, subdivLevels);
|
SubSurf *ss = subSurf_fromMesh(me, useFlatSubdiv, subdivLevels, useDeformVerts?ob:NULL);
|
||||||
DispListMesh *dlm;
|
DispListMesh *dlm;
|
||||||
|
|
||||||
subSurf_sync(ss, useFlatSubdiv);
|
subSurf_sync(ss, useFlatSubdiv);
|
||||||
@@ -1022,7 +1036,7 @@ void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3])
|
|||||||
* calculated vert positions is incorrect for the verts
|
* calculated vert positions is incorrect for the verts
|
||||||
* on the boundary of the mesh.
|
* on the boundary of the mesh.
|
||||||
*/
|
*/
|
||||||
SubSurf *ss = subSurf_fromMesh(me, 0, 1);
|
SubSurf *ss = subSurf_fromMesh(me, 0, 1, NULL);
|
||||||
float edge_sum[3], face_sum[3];
|
float edge_sum[3], face_sum[3];
|
||||||
CCGVertIterator *vi;
|
CCGVertIterator *vi;
|
||||||
|
|
||||||
|
|||||||
@@ -1211,13 +1211,6 @@ void do_curvebuts(unsigned short event)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case B_SUBSURFTYPE:
|
case B_SUBSURFTYPE:
|
||||||
/* Icky, find better system */
|
|
||||||
//if(ob->type==OB_MESH && G.obedit && ob->data==G.obedit->data) {
|
|
||||||
// if(G.editMesh->derived) {
|
|
||||||
// G.editMesh->derived->release(G.editMesh->derived);
|
|
||||||
// G.editMesh->derived= NULL;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
case B_MAKEDISP:
|
case B_MAKEDISP:
|
||||||
if(G.vd) {
|
if(G.vd) {
|
||||||
|
|||||||
@@ -885,9 +885,10 @@ void draw_tface_mesh(Object *ob, Mesh *me, int dt)
|
|||||||
dm = mesh_get_derived(ob);
|
dm = mesh_get_derived(ob);
|
||||||
dm->drawFacesTex(dm, draw_tface_mesh__set_draw);
|
dm->drawFacesTex(dm, draw_tface_mesh__set_draw);
|
||||||
} else {
|
} else {
|
||||||
dm = mesh_get_base_derived(ob);
|
int dmNeedsFree;
|
||||||
|
dm = mesh_get_derived_deform(ob, &dmNeedsFree);
|
||||||
dm->drawFacesTex(dm, draw_tface_mesh__set_draw);
|
dm->drawFacesTex(dm, draw_tface_mesh__set_draw);
|
||||||
dm->release(dm);
|
if (dmNeedsFree) dm->release(dm);
|
||||||
}
|
}
|
||||||
|
|
||||||
start = 0;
|
start = 0;
|
||||||
|
|||||||
@@ -1931,13 +1931,14 @@ static void draw_mesh_object(Base *base, int dt)
|
|||||||
BoundBox *bb = mesh_get_bb(me);
|
BoundBox *bb = mesh_get_bb(me);
|
||||||
|
|
||||||
if(me->totface<=4 || boundbox_clip(ob->obmat, bb)) {
|
if(me->totface<=4 || boundbox_clip(ob->obmat, bb)) {
|
||||||
DerivedMesh *baseDM = mesh_get_base_derived(ob);
|
int baseDMneedsFree;
|
||||||
|
DerivedMesh *baseDM = mesh_get_derived_deform(ob, &baseDMneedsFree);
|
||||||
DerivedMesh *realDM = mesh_get_derived(ob);
|
DerivedMesh *realDM = mesh_get_derived(ob);
|
||||||
|
|
||||||
if(dt==OB_SOLID) has_alpha= init_gl_materials(ob);
|
if(dt==OB_SOLID) has_alpha= init_gl_materials(ob);
|
||||||
draw_mesh_fancy(ob, baseDM, realDM, dt);
|
draw_mesh_fancy(ob, baseDM, realDM, dt);
|
||||||
|
|
||||||
baseDM->release(baseDM);
|
if (baseDMneedsFree) baseDM->release(baseDM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3965,88 +3966,81 @@ static int bbs_mesh_solid__setDrawOptions(void *userData, EditFace *efa)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* two options, facecolors or black */
|
/* two options, facecolors or black */
|
||||||
static int bbs_mesh_solid(Object *ob, DerivedMesh *dm, int facecol)
|
static int bbs_mesh_solid_EM(DerivedMesh *dm, int facecol)
|
||||||
{
|
{
|
||||||
int glmode, a;
|
cpack(0);
|
||||||
|
|
||||||
|
if (facecol) {
|
||||||
|
EditFace *efa, *prevefa;
|
||||||
|
int a, b;
|
||||||
|
|
||||||
|
// tuck original indices in efa->prev
|
||||||
|
for(b=1, efa= G.editMesh->faces.first; efa; efa= efa->next, b++)
|
||||||
|
efa->prev= (EditFace *)(b);
|
||||||
|
a = b;
|
||||||
|
|
||||||
|
dm->drawMappedFacesEM(dm, bbs_mesh_solid__setDrawOptions, (void*) 1);
|
||||||
|
|
||||||
|
if(G.scene->selectmode & SCE_SELECT_FACE) {
|
||||||
|
glPointSize(BIF_GetThemeValuef(TH_FACEDOT_SIZE));
|
||||||
|
|
||||||
|
bglBegin(GL_POINTS);
|
||||||
|
for(efa= G.editMesh->faces.first; efa; efa= efa->next) {
|
||||||
|
if(efa->h==0 && efa->fgonf!=EM_FGON) {
|
||||||
|
set_framebuffer_index_color((int)efa->prev);
|
||||||
|
bglVertex3fv(efa->cent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bglEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (prevefa= NULL, efa= G.editMesh->faces.first; efa; prevefa= efa, efa= efa->next)
|
||||||
|
efa->prev= prevefa;
|
||||||
|
return a;
|
||||||
|
} else {
|
||||||
|
dm->drawMappedFacesEM(dm, bbs_mesh_solid__setDrawOptions, (void*) 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bbs_mesh_solid(Object *ob)
|
||||||
|
{
|
||||||
|
Mesh *me= ob->data;
|
||||||
|
MFace *mface= me->mface;
|
||||||
|
TFace *tface= me->tface;
|
||||||
|
float co[3];
|
||||||
|
int a, glmode, dmNeedsFree;
|
||||||
|
DerivedMesh *dm = mesh_get_derived_deform(ob, &dmNeedsFree);
|
||||||
|
|
||||||
cpack(0);
|
cpack(0);
|
||||||
|
|
||||||
if(ob==G.obedit) {
|
glBegin(glmode=GL_QUADS);
|
||||||
if (facecol) {
|
for(a=0; a<me->totface; a++, mface++, tface++) {
|
||||||
EditFace *efa, *prevefa;
|
if(mface->v3 && (!me->tface || !(tface->flag&TF_HIDE))) {
|
||||||
int b;
|
int newmode = mface->v4?GL_QUADS:GL_TRIANGLES;
|
||||||
|
|
||||||
// tuck original indices in efa->prev
|
set_framebuffer_index_color(a+1);
|
||||||
for(b=1, efa= G.editMesh->faces.first; efa; efa= efa->next, b++)
|
|
||||||
efa->prev= (EditFace *)(b);
|
|
||||||
a = b;
|
|
||||||
|
|
||||||
dm->drawMappedFacesEM(dm, bbs_mesh_solid__setDrawOptions, (void*) 1);
|
if (newmode!=glmode) {
|
||||||
|
glEnd();
|
||||||
if(G.scene->selectmode & SCE_SELECT_FACE) {
|
glBegin(glmode=newmode);
|
||||||
glPointSize(BIF_GetThemeValuef(TH_FACEDOT_SIZE));
|
|
||||||
|
|
||||||
bglBegin(GL_POINTS);
|
|
||||||
for(efa= G.editMesh->faces.first; efa; efa= efa->next) {
|
|
||||||
if(efa->h==0 && efa->fgonf!=EM_FGON) {
|
|
||||||
set_framebuffer_index_color((int)efa->prev);
|
|
||||||
bglVertex3fv(efa->cent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bglEnd();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (prevefa= NULL, efa= G.editMesh->faces.first; efa; prevefa= efa, efa= efa->next)
|
glVertex3fv( (dm->getVertCo(dm, mface->v1, co),co) );
|
||||||
efa->prev= prevefa;
|
glVertex3fv( (dm->getVertCo(dm, mface->v2, co),co) );
|
||||||
return a;
|
glVertex3fv( (dm->getVertCo(dm, mface->v3, co),co) );
|
||||||
} else {
|
if(mface->v4) glVertex3fv( (dm->getVertCo(dm, mface->v4, co),co) );
|
||||||
dm->drawMappedFacesEM(dm, bbs_mesh_solid__setDrawOptions, (void*) 0);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
glEnd();
|
||||||
Mesh *me= ob->data;
|
|
||||||
MFace *mface;
|
|
||||||
TFace *tface;
|
|
||||||
float co[3];
|
|
||||||
int a, dmNeedsFree;
|
|
||||||
DerivedMesh *dm = mesh_get_derived_deform(ob, &dmNeedsFree);
|
|
||||||
|
|
||||||
mface= me->mface;
|
|
||||||
tface= me->tface;
|
|
||||||
|
|
||||||
glBegin(glmode=GL_QUADS);
|
if (dmNeedsFree) {
|
||||||
for(a=0; a<me->totface; a++, mface++, tface++) {
|
dm->release(dm);
|
||||||
if(mface->v3 && (!me->tface || !(tface->flag&TF_HIDE))) {
|
|
||||||
int newmode = mface->v4?GL_QUADS:GL_TRIANGLES;
|
|
||||||
|
|
||||||
set_framebuffer_index_color(a+1);
|
|
||||||
|
|
||||||
if (newmode!=glmode) {
|
|
||||||
glEnd();
|
|
||||||
glBegin(glmode=newmode);
|
|
||||||
}
|
|
||||||
|
|
||||||
glVertex3fv( (dm->getVertCo(dm, mface->v1, co),co) );
|
|
||||||
glVertex3fv( (dm->getVertCo(dm, mface->v2, co),co) );
|
|
||||||
glVertex3fv( (dm->getVertCo(dm, mface->v3, co),co) );
|
|
||||||
if(mface->v4) glVertex3fv( (dm->getVertCo(dm, mface->v4, co),co) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
glEnd();
|
|
||||||
|
|
||||||
if (dmNeedsFree) {
|
|
||||||
dm->release(dm);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_object_backbufsel(Object *ob)
|
void draw_object_backbufsel(Object *ob)
|
||||||
{
|
{
|
||||||
int dmNeedsFree;
|
|
||||||
DerivedMesh *dm;
|
|
||||||
|
|
||||||
mymultmatrix(ob->obmat);
|
mymultmatrix(ob->obmat);
|
||||||
|
|
||||||
@@ -4055,10 +4049,11 @@ void draw_object_backbufsel(Object *ob)
|
|||||||
|
|
||||||
switch( ob->type) {
|
switch( ob->type) {
|
||||||
case OB_MESH:
|
case OB_MESH:
|
||||||
dm = mesh_get_cage_derived(ob, &dmNeedsFree);
|
if(ob==G.obedit) {
|
||||||
|
int dmNeedsFree;
|
||||||
|
DerivedMesh *dm = mesh_get_cage_derived(ob, &dmNeedsFree);
|
||||||
|
|
||||||
if(G.obedit) {
|
em_solidoffs= bbs_mesh_solid_EM(dm, G.scene->selectmode & SCE_SELECT_FACE);
|
||||||
em_solidoffs= bbs_mesh_solid(ob, dm, G.scene->selectmode & SCE_SELECT_FACE);
|
|
||||||
|
|
||||||
bglPolygonOffset(1.0);
|
bglPolygonOffset(1.0);
|
||||||
|
|
||||||
@@ -4070,12 +4065,13 @@ void draw_object_backbufsel(Object *ob)
|
|||||||
else em_vertoffs= em_wireoffs;
|
else em_vertoffs= em_wireoffs;
|
||||||
|
|
||||||
bglPolygonOffset(0.0);
|
bglPolygonOffset(0.0);
|
||||||
}
|
|
||||||
else bbs_mesh_solid(ob, dm, 1); // 1= facecol, faceselect
|
|
||||||
|
|
||||||
if (dmNeedsFree) {
|
if (dmNeedsFree) {
|
||||||
dm->release(dm);
|
dm->release(dm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else bbs_mesh_solid(ob);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case OB_CURVE:
|
case OB_CURVE:
|
||||||
case OB_SURF:
|
case OB_SURF:
|
||||||
|
|||||||
@@ -1479,8 +1479,6 @@ void exit_editmode(int freedata) /* freedata==0 at render, 1= freedata, 2= do un
|
|||||||
set_seamtface();
|
set_seamtface();
|
||||||
allqueue(REDRAWIMAGE, 0);
|
allqueue(REDRAWIMAGE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
build_particle_system(G.obedit);
|
|
||||||
}
|
}
|
||||||
else if (G.obedit->type==OB_ARMATURE){
|
else if (G.obedit->type==OB_ARMATURE){
|
||||||
load_editArmature();
|
load_editArmature();
|
||||||
@@ -2213,7 +2211,7 @@ void convertmenu(void)
|
|||||||
for(a=0; a<ob1->totcol; a++) id_us_plus((ID *)me->mat[a]);
|
for(a=0; a<ob1->totcol; a++) id_us_plus((ID *)me->mat[a]);
|
||||||
}
|
}
|
||||||
|
|
||||||
dm= subsurf_make_derived_from_mesh(oldme, oldme->subdiv);
|
dm= subsurf_make_derived_from_mesh(ob, oldme->subdiv, 0);
|
||||||
dlm= dm->convertToDispListMesh(dm);
|
dlm= dm->convertToDispListMesh(dm);
|
||||||
dm->release(dm);
|
dm->release(dm);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user