[Bf-python] New Patch Mesh.transform(mat), Docs included
Campbell Barton
cbarton at metavr.com
Fri Mar 4 12:14:24 CET 2005
Hi, just wondering if there is anything that needs fixing with the
transform patch.
- Cam
Campbell Barton wrote:
> Hi All, just updated my mesh.transfrom function. as well as docs. I
> think its stable.
>
> Works like this.
> loc_only = 0
> mesh.transform(mat_4x4, loc_only)
>
> If the 2nd parm is 0 then vertex normals are transformed and
> normalized (default behavior)
> so you can just do-
> mesh.transform(mat_4x4)
> if you want normals transformed too.
> -
> If loc_only is 1 then only vert locations will be tx'd.
>
>
> There is realy no resion to do a full vertex recalculation, this may
> even be bad for sombody who sets the vert normals, then wantes to TX
> THEIR normal and not have blender re-apply normals.
>
> Also- moving a vert in a mesh does not modify the verts normal, I
> tested this, transforming should only transform existing normals, not
> recalculate them.
>
> The default behavior is good- You do a GetRawFromObject(ob), then
> transform by the objects matrix - in1 line.
> Then export the mesh- verts and vert normals are correct.
>
> I have a test blend file that uses DupliVerts with Rot enabled to see
> the matrix applied- You can see the normal direction from teh
> dupliverts. (Proof it works :) )
>
> Patch- Docs included.
> + Test Blendfile
>
> - Cam
>
>------------------------------------------------------------------------
>
>Index: source/blender/python/api2_2x/NMesh.c
>===================================================================
>RCS file: /cvsroot/bf-blender/blender/source/blender/python/api2_2x/NMesh.c,v
>retrieving revision 1.57
>diff -u -p -u -r1.57 NMesh.c
>--- source/blender/python/api2_2x/NMesh.c 1 Mar 2005 02:37:19 -0000 1.57
>+++ source/blender/python/api2_2x/NMesh.c 2 Mar 2005 06:13:36 -0000
>@@ -251,6 +251,15 @@ Optional arguments: if given and nonzero
> 'store_edges': edges data is stored.\n\
> 'vertex_shade': vertex colors are added based on the current lamp setup.";
>
>+static char NMesh_recalcNormals_doc[] = \
>+"(recalc_normals = 0, store_edges = 0, vertex_shade = 0) - Updates the Mesh.\n\
>+Optional arguments: if given and nonzero:\n\
>+'recalc_normals': normal vectors are recalculated;\n\
>+'store_edges': edges data is stored.\n\
>+'vertex_shade': vertex colors are added based on the current lamp setup.";
>+
>+
>+
> static char NMesh_getMode_doc[] =
> "() - get the mode flags of this nmesh as an or'ed int value.";
>
>@@ -272,6 +281,10 @@ static char NMesh_setSubDivLevels_doc[]
> "([int, int]) - set the subdivision levels for [display, render] -- they are\n\
> clamped to the range [0,6].";
>
>+static char NMesh_transform_doc[] =
>+ "(matrix, loc_only) - Transform the mesh by the supplied 4x4 matrix.\n\
>+(loc_only) - Optional, If set to 1, transforming the vertex normals is skipped";
>+
> static char M_NMesh_New_doc[] =
> "() - returns a new, empty NMesh mesh object\n";
>
>@@ -1346,6 +1359,71 @@ static PyObject *NMesh_update( PyObject
> return PyInt_FromLong( 1 );
> }
>
>+static PyObject *NMesh_recalcNormals( PyObject *self, PyObject *a, PyObject *kwd )
>+{
>+ BPy_NMesh *nmesh = ( BPy_NMesh * ) self;
>+ Mesh *mesh = nmesh->mesh;
>+ int recalc_normals = 0, store_edges = 0, vertex_shade = 0;
>+ static char *kwlist[] = {"recalc_normals", "store_edges",
>+ "vertex_shade", NULL};
>+ int needs_redraw = 1;
>+
>+ if (!PyArg_ParseTupleAndKeywords(a, kwd, "|iii", kwlist, &recalc_normals,
>+ &store_edges, &vertex_shade ) )
>+ return EXPP_ReturnPyObjError( PyExc_AttributeError,
>+ "expected nothing or one to three bool(s) (0 or 1) as argument" );
>+
>+ if( mesh ) {
>+ unlink_existingMeshData( mesh );
>+ convert_NMeshToMesh( mesh, nmesh, store_edges );
>+ } else {
>+ nmesh->mesh = Mesh_fromNMesh( nmesh, store_edges );
>+ mesh = nmesh->mesh;
>+ }
>+
>+ if( recalc_normals )
>+ vertexnormals_mesh( mesh, 0 );
>+
>+ mesh_update( mesh );
>+
>+ nmesh_updateMaterials( nmesh );
>+
>+ if( nmesh->name && nmesh->name != Py_None )
>+ new_id( &( G.main->mesh ), &mesh->id,
>+ PyString_AsString( nmesh->name ) );
>+
>+ if (vertex_shade) {
>+ Base *base = FIRSTBASE;
>+
>+ if (!nmesh->object)
>+ return EXPP_ReturnPyObjError(PyExc_RuntimeError,
>+ "link this mesh to an object first with ob.link(mesh)" );
>+
>+ if (G.obedit)
>+ return EXPP_ReturnPyObjError(PyExc_RuntimeError,
>+ "can't shade vertices while in edit mode" );
>+
>+ while (base) {
>+ if (base->object == nmesh->object) {
>+ base->flag |= SELECT;
>+ nmesh->object->flag = base->flag;
>+ set_active_base (base);
>+ needs_redraw = 0; /* already done in make_vertexcol */
>+ break;
>+ }
>+ base = base->next;
>+ }
>+ make_vertexcol();
>+
>+ countall();
>+ }
>+
>+ if( !during_script( ) && needs_redraw)
>+ allqueue( REDRAWVIEW3D, 0 );
>+
>+ return PyInt_FromLong( 1 );
>+}
>+
> /** Implementation of the python method getVertexInfluence for an NMesh object.
> * This method returns a list of pairs (string,float) with bone names and
> * influences that this vertex receives.
>@@ -1493,6 +1571,55 @@ static PyObject *NMesh_setSubDivLevels(
> return Py_None;
> }
>
>+static PyObject *NMesh_transform( PyObject * self, PyObject * args )
>+{
>+ BPy_NMesh *nmesh = ( BPy_NMesh * ) self;
>+ BPy_NMVert *mv;
>+ PyObject *ob1 = NULL;
>+ MatrixObject *mat;
>+ float vx, vy, vz;
>+ int i;
>+ int loc_only = 0;
>+
>+ if( !PyArg_ParseTuple( args, "O!|i", &matrix_Type, &ob1, &loc_only ) )
>+ return ( EXPP_ReturnPyObjError( PyExc_TypeError,
>+ "expected matrix\n" ) );
>+
>+ mat = ( MatrixObject * ) ob1;
>+
>+ if( mat->colSize != 4 || mat->rowSize != 4 )
>+ return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
>+ "matrix must be a 4x4 transformation matrix as returned by object.getMatrix()\n" ) );
>+
>+ /* Loop through all the verts and transform locations by the supplied matrix */
>+ for( i = 0; i < PySequence_Length(nmesh->verts); i++ ) {
>+ mv = ( BPy_NMVert * ) PySequence_GetItem( nmesh->verts, i );
>+ vx = mv->co[0];
>+ vy = mv->co[1];
>+ vz = mv->co[2];
>+ mv->co[0] = vx*mat->matrix[0][0] + vy*mat->matrix[1][0] + vz*mat->matrix[2][0] + mat->matrix[3][0];
>+ mv->co[1] = vx*mat->matrix[0][1] + vy*mat->matrix[1][1] + vz*mat->matrix[2][1] + mat->matrix[3][1];
>+ mv->co[2] = vx*mat->matrix[0][2] + vy*mat->matrix[1][2] + vz*mat->matrix[2][2] + mat->matrix[3][2];
>+ }
>+ if ( ! loc_only ) {
>+ /* Loop through all the verts and transform normals by the supplied matrix */
>+ for( i = 0; i < PySequence_Length(nmesh->verts); i++ ) {
>+ mv = ( BPy_NMVert * ) PySequence_GetItem( nmesh->verts, i );
>+ vx = mv->no[0];
>+ vy = mv->no[1];
>+ vz = mv->no[2];
>+ mv->no[0] = vx*mat->matrix[0][0] + vy*mat->matrix[1][0] + vz*mat->matrix[2][0];
>+ mv->no[1] = vx*mat->matrix[0][1] + vy*mat->matrix[1][1] + vz*mat->matrix[2][1];
>+ mv->no[2] = vx*mat->matrix[0][2] + vy*mat->matrix[1][2] + vz*mat->matrix[2][2];
>+ Normalise(mv->no);
>+ }
>+ }
>+
>+ Py_DECREF( mv );
>+ Py_INCREF( Py_None );
>+ return Py_None;
>+}
>+
> static PyObject *NMesh_getMode( BPy_NMesh * self )
> {
> PyObject *attr = PyInt_FromLong( self->mode );
>@@ -1579,6 +1706,7 @@ static struct PyMethodDef NMesh_methods[
> MethodDef( setMode ),
> MethodDef( setMaxSmoothAngle ),
> MethodDef( setSubDivLevels ),
>+ MethodDef( transform ),
>
> /* METH_NOARGS: function(PyObject *self) */
> #undef MethodDef
>Index: source/blender/python/api2_2x/doc/NMesh.py
>===================================================================
>RCS file: /cvsroot/bf-blender/blender/source/blender/python/api2_2x/doc/NMesh.py,v
>retrieving revision 1.30
>diff -u -p -u -r1.30 NMesh.py
>--- source/blender/python/api2_2x/doc/NMesh.py 1 Mar 2005 02:37:19 -0000 1.30
>+++ source/blender/python/api2_2x/doc/NMesh.py 2 Mar 2005 06:13:36 -0000
>@@ -568,6 +568,35 @@ class NMesh:
> L{setMode}) need their display lists updated, too.
> """
>
>+ def transform(matrix, loc_only = 0):
>+ """
>+ Transforms the mesh by the spesified 4x4 matrix, as returned by object.matrix
>+ though this will work with any 4x4 matrix type.
>+ Ideal Useage for this is exporting to an external file, where global vertex
>+ locations are required for each object.
>+ Somtimes external renderers/file formats do not use vertex normals,
>+ In this case you can skip transforming teh vertex normals by setting
>+ the optional parm (loc_only) to 1
>+
>+ Example::
>+ # This script outputs deformed meshes worldspace vertex locations
>+ # for a selected object
>+ import Blender
>+ from Blender NMesh, Object
>+
>+ ob = Object.GetSelected()[0] # Get the first selected object
>+ me = NMesh.GetRawFromObject(ob) # Get the objects deformed mesh data
>+ me.transform(ob.matrix)
>+
>+ for v in me.verts:
>+ print 'worldspace vert', v.co
>+
>+ @type matrix: Py_Matrix
>+ @param matrix: 4x4 Matrix which can contain location, scale and rotation.
>+ @type loc_only: int (bool)
>+ @param loc_only: if 1, will only transform vertex locations.
>+ """
>+
> def getMode():
> """
> Get this mesh's mode flags.
>
>
>------------------------------------------------------------------------
>
>_______________________________________________
>Bf-python mailing list
>Bf-python at projects.blender.org
>http://projects.blender.org/mailman/listinfo/bf-python
>
>
--
Campbell J Barton
133 Hope Street
Geelong West, Victoria 3218 Australia
URL: http://www.metavr.com
e-mail: cbarton at metavr.com
phone: AU (03) 5229 0241
More information about the Bf-python
mailing list