diff --git a/release/scripts/bpymodules/BPyMesh.py b/release/scripts/bpymodules/BPyMesh.py index 81a81e98f3f..ec580c00125 100644 --- a/release/scripts/bpymodules/BPyMesh.py +++ b/release/scripts/bpymodules/BPyMesh.py @@ -288,8 +288,7 @@ print len(indices) me.faces.extend([[me.verts[ii] for ii in i] for i in indices]) ''' - -def meshPrettyNormals(me): +def meshCalcNormals(me): ''' takes a mesh and returns very high quality normals 1 normal per vertex. The normals should be correct, indipendant of topology @@ -329,7 +328,6 @@ def meshPrettyNormals(me): # print totAngDiff if totAngDiff > SMALL_NUM: - ''' average_no= Vector() for no in fnos: @@ -337,17 +335,16 @@ def meshPrettyNormals(me): ''' average_no= reduce(lambda a,b: a+b, fnos, Vector()) fnos.append(average_no*totAngDiff) # average no * total angle diff - else: - fnos[0] - else: + #else: + # fnos[0] + else: fnos.append(fnos[0]) for ed, v in edges.iteritems(): vertNormals[ed[0]]+= v[-1] vertNormals[ed[1]]+= v[-1] - for v in vertNormals: - v.normalize() - return vertNormals + for i, v in enumerate(vertNormals): + me.verts[i].no= v diff --git a/release/scripts/vertexpaint_selfshadow_ao.py b/release/scripts/vertexpaint_selfshadow_ao.py index 576e8fced7f..7f1dea1c761 100644 --- a/release/scripts/vertexpaint_selfshadow_ao.py +++ b/release/scripts/vertexpaint_selfshadow_ao.py @@ -40,7 +40,7 @@ It removes very low weighted verts from the current group with a weight option. from Blender import * import BPyMesh -reload(BPyMesh) +# reload(BPyMesh) def vertexFakeAO(me, PREF_BLUR_ITERATIONS, PREF_BLUR_SCALE, PREF_CLAMP_CONCAVE, PREF_CLAMP_CONVEX, PREF_SHADOW_ONLY, PREF_SEL_ONLY): @@ -48,11 +48,13 @@ def vertexFakeAO(me, PREF_BLUR_ITERATIONS, PREF_BLUR_SCALE, PREF_CLAMP_CONCAVE, V=Mathutils.Vector M=Mathutils.Matrix Ang= Mathutils.AngleBetweenVecs - - nos= BPyMesh.meshPrettyNormals(me) + + BPyMesh.meshCalcNormals(me) + vert_tone= [0.0] * len(me.verts) - vert_tone_list= [ [] for i in xrange(len(me.verts)) ] + vert_tone_count= [0] * len(me.verts) + ed_face_users = [ [] for i in xrange(len(me.edges)) ] fcent= [BPyMesh.faceCent(f) for f in me.faces] @@ -64,42 +66,36 @@ def vertexFakeAO(me, PREF_BLUR_ITERATIONS, PREF_BLUR_SCALE, PREF_CLAMP_CONCAVE, c= fcent[i] fno = f.no*0.0001 for v in f.v: - #vno=v.no # ugly normal - vno= nos[v.index]*0.0001 # pretty notrmal + #vno=v.no*0.001 # get a scaled down normal. + vno=v.no # get a scaled down normal. - l1= (c-v.co).length - l2= ((c+fno) - (v.co+vno)).length + l1= (c-(v.co-vno)).length + l2= (c-(v.co+vno)).length + #l2= ((c+fno) - (v.co+vno)).length + vert_tone_count[v.index]+=1 if abs(l1-l2) < 0.0000001: - vert_tone_list[v.index].append(0) + pass else: - try: a= Ang(vno, fno) - except: a=0 + try: + a= Ang(vno, fno) + except: + continue + # Convex if l1size != 3 ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected vector argument of size 3" ); + + + for( i=0; i<3 ; ++i) + normal[i] = value->vec[i]; + + Normalise(normal); + + for( i=0; i<3 ; ++i) + v->no[i] = (short)(normal[i]*32767.0); + + return 0; +} + + /* * get a vertex's select status */ @@ -1218,7 +1249,7 @@ static PyGetSetDef BPy_MVert_getseters[] = { "vertex's index", NULL}, {"no", - (getter)MVert_getNormal, (setter)NULL, + (getter)MVert_getNormal, (setter)MVert_setNormal, "vertex's normal", NULL}, {"sel", @@ -1238,7 +1269,7 @@ static PyGetSetDef BPy_PVert_getseters[] = { "vertex's coordinate", NULL}, {"no", - (getter)MVert_getNormal, (setter)NULL, + (getter)MVert_getNormal, (setter)MVert_setNormal, "vertex's normal", NULL}, {"sel", @@ -3101,6 +3132,189 @@ static PyObject *MEdgeSeq_delete( BPy_MEdgeSeq * self, PyObject *args ) Py_RETURN_NONE; } +static PyObject *MEdgeSeq_collapse( BPy_MEdgeSeq * self, PyObject *args ) +{ + MEdge *srcedge; + unsigned int *edge_table; + float (*vert_list)[3]; + int i, len; + Base *base, *basact; + Mesh *mesh = self->mesh; + Object *object = NULL; + PyObject *tmp; + + /* + * when using removedoublesflag(), we need to switch to editmode, so + * nobody else can be using it + */ + + if( G.obedit ) + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "can't use collapse() while in edit mode" ); + + /* make sure we get a tuple of sequences of something */ + switch( PySequence_Size( args ) ) { + case 1: + /* if a sequence... */ + tmp = PyTuple_GET_ITEM( args, 0 ); + if( PySequence_Check( tmp ) ) { + PyObject *tmp2; + + /* ignore empty sequences */ + if( !PySequence_Size( tmp ) ) { + Py_RETURN_NONE; + } + + /* if another sequence, use it */ + tmp2 = PySequence_ITEM( tmp, 0 ); + if( PySequence_Check( tmp2 ) ) + args = tmp; + Py_INCREF( args ); + Py_DECREF( tmp2 ); + } else + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected a sequence of sequence pairs" ); + break; + case 2: /* two args may be individual edges/verts */ + tmp = PyTuple_GET_ITEM( args, 0 ); + /* + * if first item isn't a sequence, then assume it's a bunch of MVerts + * and wrap inside a tuple + */ + if( !PySequence_Check( tmp ) ) { + args = Py_BuildValue( "(O)", args ); + if( !args ) + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Py_BuildValue() failed" ); + /* + * otherwise, assume it already a bunch of sequences so use as-is + */ + } else { + Py_INCREF( args ); /* so we can safely DECREF later */ + } + break; + default: /* anything else is definitely wrong */ + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected a sequence of sequence pairs" ); + } + + /* if sequence is empty, do nothing */ + len = PySequence_Size( args ); + if( len == 0 ) { + Py_RETURN_NONE; + } + + /* allocate table of edge indices and new vertex values */ + + edge_table = (unsigned int *)MEM_callocN( len*sizeof( unsigned int ), + "edge_table" ); + vert_list = (float (*)[3])MEM_callocN( 3*len*sizeof( float ), + "vert_list" ); + + /* get the indices of edges to be collapsed and new vert locations */ + for( i = len; i--; ) { + PyObject *tmp1; + PyObject *tmp2; + + tmp = PySequence_GetItem( args, i ); + + /* if item isn't sequence of size 2, error */ + if( !PySequence_Check( tmp ) || PySequence_Size( tmp ) != 2 ) { + MEM_freeN( edge_table ); + MEM_freeN( vert_list ); + Py_DECREF( tmp ); + Py_DECREF( args ); + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected a sequence of (MEdges, vector)" ); + } + + /* if items aren't a MEdge/int and vector, error */ + tmp1 = PySequence_GetItem( tmp, 0 ); + tmp2 = PySequence_GetItem( tmp, 1 ); + Py_DECREF( tmp ); + if( !(BPy_MEdge_Check( tmp1 ) || PyInt_CheckExact( tmp1 )) || + !VectorObject_Check ( tmp2 ) ) { + MEM_freeN( edge_table ); + MEM_freeN( vert_list ); + Py_DECREF( tmp1 ); + Py_DECREF( tmp2 ); + Py_DECREF( args ); + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected a sequence of (MEdges, vector)" ); + } + + /* store edge index, new vertex location */ + if( PyInt_CheckExact( tmp1 ) ) + edge_table[i] = PyInt_AsLong ( tmp1 ); + else + edge_table[i] = ((BPy_MEdge *)tmp1)->index; + memcpy( vert_list[i], ((VectorObject *)tmp2)->vec, + 3*sizeof( float ) ); + Py_DECREF( tmp1 ); + Py_DECREF( tmp2 ); + + /* if index out-of-range, throw exception */ + if( edge_table[i] >= (unsigned int)mesh->totedge ) { + MEM_freeN( edge_table ); + MEM_freeN( vert_list ); + return EXPP_ReturnPyObjError( PyExc_ValueError, + "edge index out of range" ); + } + } + + /* + * simple algorithm: + * (1) deselect all verts + * (2) for each edge + * (2a) replace both verts with the new vert + * (2b) select both verts + * (3) call removedoublesflag() + */ + + /* (1) deselect all verts */ + for( i = mesh->totvert; i--; ) + mesh->mvert[i].flag &= ~SELECT; + + /* (2) replace edge's verts and select them */ + for( i = len; i--; ) { + srcedge = &mesh->medge[edge_table[i]]; + memcpy( &mesh->mvert[srcedge->v1].co, vert_list[i], 3*sizeof( float ) ); + memcpy( &mesh->mvert[srcedge->v2].co, vert_list[i], 3*sizeof( float ) ); + mesh->mvert[srcedge->v1].flag |= SELECT; + mesh->mvert[srcedge->v2].flag |= SELECT; + } + + /* (3) call removedoublesflag() */ + for( base = FIRSTBASE; base; base = base->next ) { + if( base->object->type == OB_MESH && + base->object->data == self->mesh ) { + object = base->object; + break; + } + } + + basact = BASACT; + BASACT = base; + + removedoublesflag( 1, 0.0 ); + /* make mesh's object active, enter mesh edit mode */ + G.obedit = object; + + /* exit edit mode, free edit mesh */ + load_editMesh(); + free_editMesh(G.editMesh); + + BASACT = basact; + + /* clean up and exit */ + Py_DECREF( args ); + MEM_freeN( vert_list ); + MEM_freeN( edge_table ); + mesh_update ( mesh ); + Py_RETURN_NONE; +} + + static PyObject *MEdgeSeq_selected( BPy_MEdgeSeq * self ) { int i, count; @@ -3147,6 +3361,8 @@ static struct PyMethodDef BPy_MEdgeSeq_methods[] = { "delete edges from mesh"}, {"selected", (PyCFunction)MEdgeSeq_selected, METH_NOARGS, "returns a list containing indices of selected edges"}, + {"collapse", (PyCFunction)MEdgeSeq_collapse, METH_VARARGS, + "collapse one or more edges to a vertex"}, {NULL, NULL, 0, NULL} };