Dev:Ref/Requests/SubDivImprovements
目次
Adding a more controlled subdiv.
Basic subdiv still means tons of editing and fractal subdiv is very random. The basic idea here is to create a subdiv menu that allows very good control over what and how it will be subdivided. I think this will be most useful for natural formations (rocks, cliffs, etc.) because you will be better able to control how the object is formed but still have enough randomness to make it effective. The basic idea is to create a way to manipulate x, y and z planes independantly.
Edits needed to create this...
Anything I am not sure what needs to be done is in ***** Stuff *****
This section shows what I think will need to be changed. I am not very sure on the UI stuff or if/how any of the changes must take place. Allowing others to suggest the best way to implement this is my best idea right now.
I believe most of this is actually worked out. I was also wondering if the FULL switch should be added, to force the selected points to be raised or lowered at the full amount. I am not sure if this would be useful, since it seems except perhaps in amking some sort of grating.
Looking for comments, suggestions and someone to help with the UI and
finish the coding for this.
buttons_editing.c
void do_meshbuts(unsigned short event)
current
=
float fac;
short randfac;
=
new
float fac, fax, fay, faz;
short randfac, randfax, randfay, randfaz;
case B_CONTROLSUBDIV:
randfax = 10;
randfay = 10;
randfaz = 10;
***** Menu Check *****
waitcursor(1);
fax = -((float)randfax ) / 100;
fay = -((float)randfay ) / 100;
faz = -((float)randfaz ) / 100;
***** subdivideflag handling *****
countall();
waitcursor(0);
allqueue(REDRAWVIEW3D, 0);
BIF_undo_push("Controlled Subdivide");
break;
static void editing_panel_mesh_tools(Object *ob, Mesh *me)
=
new
uiDefBut(block, BUT,B_CONTROLSUBDIV, "Ctrld Subd", 170,195,85,19, 0, 0, 0, 0, 0, "Subdivides selected faces with a controlled factor");
- Not sure on the changes here, just copied fracsub line *****
editobject.c
void special_editmenu(void)
current
=
else if(G.obedit->type==OB_MESH) {
nr= pupmenu("Specials%t|Subdivide%x1|
Subdivide Fractal%x2|Subdivide Smooth%x3|
Merge%x4|Remove Doubles%x5|Hide%x6|Reveal%x7|
Select Swap%x8|Flip Normals %x9|Smooth %x10|Bevel %x11");
if(nr>0) waitcursor(1);
switch(nr) {
case 1:
subdivideflag(1, 0.0, editbutflag);
BIF_undo_push("Subdivide");
break;
case 2:
randfac= 10;
if(button(&randfac, 1, 100, "Rand fac:")==0) return;
fac= -( (float)randfac )/100;
subdivideflag(1, fac, editbutflag);
BIF_undo_push("Subdivide Fractal");
break;
case 3:
subdivideflag(1, 0.0, editbutflag | B_SMOOTH);
BIF_undo_push("Subdivide Smooth");
break;
case 4:
mergemenu();
break;
case 5:
notice("Removed %d Vertices", removedoublesflag(1, doublimit));
BIF_undo_push("Remove Doubles");
break;
case 6:
hide_mesh(0);
break;
case 7:
reveal_mesh();
break;
case 8:
selectswap_mesh();
break;
case 9:
flip_editnormals();
BIF_undo_push("Flip Normals");
break;
case 10:
vertexsmooth();
break;
case 11:
bevel_menu();
break;
}
makeDispList(G.obedit);
if(nr>0) waitcursor(0);
}
=
new
else if(G.obedit->type==OB_MESH) {
nr= pupmenu("Specials%t|Subdivide%x1|
Subdivide Fractal%x2|Subdivide Controlled%x3|
Subdivide Smooth%x4|Merge%x5|Remove Doubles%x6|
Hide%x7|Reveal%x8|Select Swap%x9|
Flip Normals %x10|Smooth %x11|Bevel %x12");
if(nr>0) waitcursor(1);
switch(nr) {
case 1:
subdivideflag(1, 0.0, editbutflag);
BIF_undo_push("Subdivide");
break;
case 2:
randfac= 10;
if(button(&randfac, 1, 100, "Rand fac:")==0) return;
fac= -( (float)randfac )/100;
subdivideflag(1, fac, editbutflag);
BIF_undo_push("Subdivide Fractal");
break;
case 3:
***** subdivideflag handling *****
BIF_undo_push("Subdivide Controlled");
break;
case 4:
subdivideflag(1, 0.0, editbutflag | B_SMOOTH);
BIF_undo_push("Subdivide Smooth");
break;
case 5:
mergemenu();
break;
case 6:
notice("Removed %d Vertices", removedoublesflag(1, doublimit));
BIF_undo_push("Remove Doubles");
break;
case 7:
hide_mesh(0);
break;
case 8:
reveal_mesh();
break;
case 9:
selectswap_mesh();
break;
case 10:
flip_editnormals();
BIF_undo_push("Flip Normals");
break;
case 11:
vertexsmooth();
break;
case 12:
bevel_menu();
break;
}
makeDispList(G.obedit);
if(nr>0) waitcursor(0);
}
header_view3d.c
void do_view3d_edit_mesh_edgesmenu(void *arg, int event)
current
=
extern short editbutflag;
float fac;
short randfac;
switch(event) {
case 0: /* subdivide smooth */
subdivideflag(1, 0.0, editbutflag | B_SMOOTH);
BIF_undo_push("Subdivide Smooth");
break;
case 1: /*subdivide fractal */
randfac= 10;
if(button(&randfac, 1, 100, "Rand fac:")==0) return;
fac= -( (float)randfac )/100;
subdivideflag(1, fac, editbutflag);
BIF_undo_push("Subdivide Fractal");
break;
case 2: /* subdivide */
subdivideflag(1, 0.0, editbutflag);
BIF_undo_push("Subdivide");
break;
case 3: /* knife subdivide */
KnifeSubdivide(KNIFE_PROMPT);
break;
case 4: /* Loop subdivide */
loopoperations(LOOP_CUT);
break;
case 5: /* Make Edge/Face */
addedgeface_mesh();
break;
case 6:
bevel_menu();
break;
case 7: /* Mark Seam */
editmesh_mark_seam(0);
break;
case 8: /* Clear Seam */
editmesh_mark_seam(1);
break;
case 9: /* Cease SubSurf */
transform('e');
break;
case 10: /* Rotate Edges */
edge_rotate_selected();
break;
}
allqueue(REDRAWVIEW3D, 0);
}
=
new
extern short editbutflag;
float fac, fax, fay, faz;
short randfac, randfax, randfay, randfaz;
switch(event) {
case 0: /* subdivide smooth */
subdivideflag(1, 0.0, editbutflag | B_SMOOTH);
BIF_undo_push("Subdivide Smooth");
break;
case 1: /*subdivide fractal */
randfac= 10;
if(button(&randfac, 1, 100, "Rand fac:")==0) return;
fac= -( (float)randfac )/100;
subdivideflag(1, fac, editbutflag);
BIF_undo_push("Subdivide Fractal");
break;
case 2: /* controlled subdivide */
randfax = 10;
randfay = 10;
randfaz = 10;
***** Menu Check *****
waitcursor(1);
fax = -((float)randfax ) / 100;
fay = -((float)randfay ) / 100;
faz = -((float)randfaz ) / 100;
***** subdivideflag handling *****
countall();
waitcursor(0);
allqueue(REDRAWVIEW3D, 0);
BIF_undo_push("Controlled Subdivide");
break;
case 3: /* subdivide */
subdivideflag(1, 0.0, editbutflag);
BIF_undo_push("Subdivide");
break;
case 4: /* knife subdivide */
KnifeSubdivide(KNIFE_PROMPT);
break;
case 5: /* Loop subdivide */
loopoperations(LOOP_CUT);
break;
case 6: /* Make Edge/Face */
addedgeface_mesh();
break;
case 7:
bevel_menu();
break;
case 8: /* Mark Seam */
editmesh_mark_seam(0);
break;
case 9: /* Clear Seam */
editmesh_mark_seam(1);
break;
case 10: /* Cease SubSurf */
transform('e');
break;
case 11: /* Rotate Edges */
edge_rotate_selected();
break;
}
allqueue(REDRAWVIEW3D, 0);
}
static uiBlock *view3d_edit_mesh_edgesmenu(void *arg_unused)
current
=
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Subdivide|W, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Subdivide Fractal|W, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Subdivide Smooth|W, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
=
new
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Subdivide|W, 1", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Subdivide Fractal|W, 2", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Subdivide Controlled|W, 3", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Subdivide Smooth|W, 4", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
toolbox.c
static TBitem tb_mesh_edit_edge[]=
current
=
{ 0, "Subdivide|W, 1", 2, NULL},
{ 0, "Subdivide Fractal|W, 2", 1, NULL},
{ 0, "Subdivide Smooth|W, 3", 0, NULL},
=
new
{ 0, "Subdivide|W, 1", 2, NULL},
{ 0, "Subdivide Fractal|W, 2", 1, NULL},
{ 0, "Subdivide Controlled|W, 3", 1, NULL},
{ 0, "Subdivide Smooth|W, 4", 0, NULL},
The subdivide code is the other place of modification, however the
modifications to that must be done at the end, once you understand how
the implementation would work should this be added.
Controlled subdivide would call for a menu rather than just a single modification factor. The layout is below, and each [] set is a button or slider needer to get the settings // default settings...
| X : | + || - || full || 10-100 | // X : | Yes || Yes || No || 10 | | | Y : | + || - || full || 10-100 | // Y : | Yes || Yes || No || 10 | | | Z : | + || - || full || 10-100 | // Z : | Yes || Yes || No || 10 | | | OK | // | No |
This allows you to make manipulations to any texture in one or more directions and even control if it is just a positive bumping or a positive and negative adjustment.
Six new flags would be needed to cover x,y, and z XPLUS, XMINUS, YPLUS, YMINUS, ZPLUS, ZMINUS
If the Full setting was used XFULL, YFULL and ZFULL would be needed too.
These would also have to be transferred to the subdiv code.
Which brings up the subdiv code....
current
=
void subdivideflag(int flag, float rad, int beauty)
new
=
void subdivideflag(int flag, float rad, int beauty, int controlled, float radx, float rady, float radz)
current
=
/* make new normal and put in edge, clear flag! needed for face creation part below */
eed= em->edges.first;
while(eed) {
if(eed->f2 & flag) {
/* for now */
eed->h &= ~EM_FGON;
/* Subdivide percentage is stored in 1/32768ths in eed->f1 */
if (beauty & B_PERCENTSUBD) percent=(float)(eed->f1)/32768.0;
else percent=0.5;
vec[0]= (1-percent)*eed->v1->co[0] + percent*eed->v2->co[0];
vec[1]= (1-percent)*eed->v1->co[1] + percent*eed->v2->co[1];
vec[2]= (1-percent)*eed->v1->co[2] + percent*eed->v2->co[2];
if(rad > 0.0) { /* subdivide sphere */
Normalise(vec);
vec[0]*= rad;
vec[1]*= rad;
vec[2]*= rad;
}
else if(rad< 0.0) { /* fractal subdivide */
fac= rad* VecLenf(eed->v1->co, eed->v2->co);
vec1[0]= fac*(0.5-BLI_drand());
vec1[1]= fac*(0.5-BLI_drand());
vec1[2]= fac*(0.5-BLI_drand());
VecAddf(vec, vec, vec1);
}
if(beauty & B_SMOOTH) {
smooth_subdiv_vec(eed->v1->co, eed->v2->co, eed->v1->no, eed->v2->no, vec1);
VecAddf(vec, vec, vec1);
}
eed->vn= addvertlist(vec);
eed->vn->f= eed->v1->f;
}
else eed->vn= 0;
eed->f2= 0; /* needed! */
eed= eed->next;
}
=
new
/* make new normal and put in edge, clear flag! needed for face creation part below */
eed= em->edges.first;
while(eed) {
if(eed->f2 & flag) {
/* for now */
eed->h &= ~EM_FGON;
/* Subdivide percentage is stored in 1/32768ths in eed->f1 */
if (beauty & B_PERCENTSUBD) percent=(float)(eed->f1)/32768.0;
else percent=0.5;
vec[0]= (1-percent)*eed->v1->co[0] + percent*eed->v2->co[0];
vec[1]= (1-percent)*eed->v1->co[1] + percent*eed->v2->co[1];
vec[2]= (1-percent)*eed->v1->co[2] + percent*eed->v2->co[2];
if(rad > 0.0) { /* subdivide sphere */
Normalise(vec);
vec[0]*= rad;
vec[1]*= rad;
vec[2]*= rad;
}
else if(rad< 0.0) { /* fractal subdivide */
fac= rad* VecLenf(eed->v1->co, eed->v2->co);
vec1[0]= fac*(0.5-BLI_drand());
vec1[1]= fac*(0.5-BLI_drand());
vec1[2]= fac*(0.5-BLI_drand());
VecAddf(vec, vec, vec1);
}
else if(rad == 0.0) { /* controlled subdiv */
/***** Here's where the flags come in *****/
/* X Check */
fac= radx* VecLenf(eed->v1->co, eed->v2->co);
mod= (0.5-BLI_drand());
if ((controlled & SD_XPLUS) && mod > 0.0) {
vec1[0]= fac*mod;
}
else
if ((controlled & SD_XMINUS) && mod < 0.0) {
vec1[0]= fac*mod;
}
else
vec1[0]= fac;
/* Y Check */
fac= rady* VecLenf(eed->v1->co, eed->v2->co);
mod= (0.5-BLI_drand());
if ((controlled & SD_YPLUS) && mod > 0.0) {
vec1[1]= fac*mod;
}
else
if ((controlled & SD_YMINUS) && mod < 0.0) {
vec1[1]= fac*mod;
}
else
vec1[1]= fac;
/* Z Check */
fac= radz* VecLenf(eed->v1->co, eed->v2->co);
mod= (0.5-BLI_drand());
if ((controlled & SD_ZPLUS) && mod > 0.0) {
vec1[2]= fac*mod;
}
else
if ((controlled & SD_ZMINUS) && mod < 0.0) {
vec1[2]= fac*mod;
}
else
vec1[2]= fac;
}
if(beauty & B_SMOOTH) {
smooth_subdiv_vec(eed->v1->co, eed->v2->co, eed->v1->no, eed->v2->no, vec1);
VecAddf(vec, vec, vec1);
}
eed->vn= addvertlist(vec);
eed->vn->f= eed->v1->f;
}
else eed->vn= 0;
eed->f2= 0; /* needed! */
eed= eed->next;
}
-- %MAINWEB%.KennethStrom - 27 Oct 2004
Chopped the long menu lines, so the page fits better - don't forget to make them in one line when copy&pasting this into your own code... -- %MAINWEB%.NathanLetwory - 27 Oct 2004