diff options
-rw-r--r-- | doc/python_api/rst/info_gotcha.rst | 80 | ||||
-rw-r--r-- | doc/python_api/sphinx_doc_gen.py | 3 | ||||
-rw-r--r-- | release/scripts/modules/bpy_extras/mesh_utils.py | 4 | ||||
-rw-r--r-- | release/scripts/modules/bpy_types.py | 2 | ||||
-rw-r--r-- | source/blender/makesrna/RNA_access.h | 2 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_mesh.c | 53 |
6 files changed, 113 insertions, 31 deletions
diff --git a/doc/python_api/rst/info_gotcha.rst b/doc/python_api/rst/info_gotcha.rst index be11e88b2fa..0a2918ca43c 100644 --- a/doc/python_api/rst/info_gotcha.rst +++ b/doc/python_api/rst/info_gotcha.rst @@ -132,6 +132,86 @@ write useful tools in python which are also fast to execute while in edit-mode. For the time being this limitation just has to be worked around but we're aware its frustrating needs to be addressed. +NGons and Tessellation Faces +============================ + +Since 2.63 NGons are supported, this adds some complexity since in some cases you need to access triangles still (some exporters for example). + +There are now 3 ways to access faces: + +* :class:`bpy.types.MeshPolygon` - this is the data stricture which now stores faces in object mode (access as ``mesh.polygons`` rather then ``mesh.faces``). +* :class:`bpy.types.MeshTessFace` - the result of triangulating (tessellated) polygons, the main method of face access in 2.62 or older. +* :class:`bmesh.types.BMFace` - the polygons as used in editmode. + +For the purpose of the following documentation, these will be referred to as polygons, tessfaces and bmesh-faces respectively. + +5+ sided faces will be referred to as ``ngons``. + +Support Overview +---------------- + ++--------------+------------------------------+--------------------------------+--------------------------------+ +|Usage |:class:`bpy.types.MeshPolygon`|:class:`bpy.types.MeshTessFace` |:class:`bmesh.types.BMFace` | ++==============+==============================+================================+================================+ +|Import/Create |Bad (inflexible) |Fine (supported as upgrade path)|Best | ++--------------+------------------------------+--------------------------------+--------------------------------+ +|Manipulate |Bad (inflexible) |Bad (looses ngons) |Best | ++--------------+------------------------------+--------------------------------+--------------------------------+ +|Export/Output |Good (ngons) |Good (When ngons can't be used) |Good (ngons, memory overhead) | ++--------------+------------------------------+--------------------------------+--------------------------------+ + + +Creating +-------- + +All 3 datatypes can be used for face creation. + +* polygons are the most efficient way to create faces but the data structure is _very_ rigid and inflexible, you must have all your vertes and faces ready and create them all at once. This is further complicated by the fact that each polygon does not store its own verts (as with tessfaces), rather they reference an index and size in :class:`bpy.types.Mesh.loops` which in-turn is a fixed array. +* tessfaces ideally should not be used for creating faces since they are really only tessellation cache of polygons, however for scripts upgrading from 2.62 this is by far the most straightforward option. This works by creating tessfaces and when finished - they can be converted into polygons by calling :class:`bpy.types.Mesh.update`. The obvious limitation is ngons cant be created this way. +* bmesh-faces are most likely the easiest way for new scripts to create faces, since faces can be added one by one and the api has features intended for mesh manipulation. While :class:`bmesh.types.BMesh` uses more memory it can be managed by only operating on one mesh at a time. + + +Editing +------- + +Editing is where the 3 data types vary most. + +* polygons are very limited for editing, changing materials and options like smooth works but for anything else they are too inflexible and are only intended for storage. +* tessfaces should not be used for editing geometry because doing so will cause existing ngons to be tessellated. +* bmesh-faces are by far the best way to manipulate geometry. + +Exporting +--------- + +All 3 data types can be used for exporting, the choice mostly depends on weather the target format supports ngons or not. + +* polygons are the most direct & efficient way to export providing they convert into the output format easily enough. +* tessfaces work well for exporting to formats which dont support ngons, in fact this is the only place where their use is encouraged. +* bmesh-faces can work for exporting too but may not be necessary if polygons can be used since using bmesh gives some overhead because its not the native storage format in object mode. + + +Upgrading Importers from 2.62 +----------------------------- + +Importers can be upgraded to work with only minor changes. + +The main change to be made is used the tessellation versions of each function. + +* mesh.faces --> :class:`bpy.types.Mesh.tessfaces` +* mesh.uv_textures --> :class:`bpy.types.Mesh.tessface_uv_textures` +* mesh.vertex_colors --> :class:`bpy.types.Mesh.tessface_vertex_colors` + +Once the data is created call :class:`bpy.types.Mesh.update` to convert the tessfaces into polygons. + + +Upgrading Exporters from 2.62 +----------------------------- + +For exporters the most direct way to upgrade is to use tessfaces as with importing however its important to know that tessfaces may **not** exist for a mesh, the array will be empty as if there are no faces. + +So before accessing tessface data call: :class:`bmesh.types.BMesh.update` ``(calc_tessface=True)``. + + EditBones, PoseBones, Bone... Bones =================================== diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py index e88c7f5e074..9ff82e8fd16 100644 --- a/doc/python_api/sphinx_doc_gen.py +++ b/doc/python_api/sphinx_doc_gen.py @@ -270,6 +270,9 @@ else: import fnmatch m = None EXCLUDE_MODULES = tuple([m for m in EXCLUDE_MODULES if not fnmatch.fnmatchcase(m, ARGS.partial)]) + + EXCLUDE_INFO_DOCS = (not fnmatch.fnmatchcase("info", ARGS.partial)) + del m del fnmatch diff --git a/release/scripts/modules/bpy_extras/mesh_utils.py b/release/scripts/modules/bpy_extras/mesh_utils.py index eccc799775c..01e4b248858 100644 --- a/release/scripts/modules/bpy_extras/mesh_utils.py +++ b/release/scripts/modules/bpy_extras/mesh_utils.py @@ -127,7 +127,7 @@ def edge_loops_from_faces(mesh, faces=None, seams=()): :arg mesh: the mesh used to get edge loops from. :type mesh: :class:`bpy.types.Mesh` :arg faces: optional face list to only use some of the meshes faces. - :type faces: :class:`bpy.types.MeshFaces`, sequence or or NoneType + :type faces: :class:`bpy.types.MeshTessFace`, sequence or or NoneType :return: return a list of edge vertex index lists. :rtype: list """ @@ -449,7 +449,7 @@ def face_random_points(num_points, faces): :arg num_points: the number of random points to generate on each face. :type int: :arg faces: list of the faces to generate points on. - :type faces: :class:`bpy.types.MeshFaces`, sequence + :type faces: :class:`bpy.types.MeshTessFace`, sequence :return: list of random points over all faces. :rtype: list """ diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py index 8c02e845071..933e77ce2e3 100644 --- a/release/scripts/modules/bpy_types.py +++ b/release/scripts/modules/bpy_types.py @@ -411,7 +411,7 @@ class MeshEdge(StructRNA): return ord_ind(*tuple(self.vertices)) -class MeshFace(StructRNA): +class MeshTessFace(StructRNA): __slots__ = () @property diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 7d7629f8eef..84301c8000f 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -311,8 +311,8 @@ extern StructRNA RNA_MeshColorLayer; extern StructRNA RNA_MeshLoopColorLayer; extern StructRNA RNA_MeshDeformModifier; extern StructRNA RNA_MeshEdge; -extern StructRNA RNA_MeshFace; extern StructRNA RNA_MeshPolygon; +extern StructRNA RNA_MeshTessFace; extern StructRNA RNA_MeshLoop; extern StructRNA RNA_MeshFloatProperty; extern StructRNA RNA_MeshFloatPropertyLayer; diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 802f103d417..6aa77d8c8d7 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -225,7 +225,7 @@ static float rna_MeshPolygon_area_get(PointerRNA *ptr) return mesh_calc_poly_area(mp, me->mloop+mp->loopstart, me->mvert, NULL); } -static void rna_MeshFace_normal_get(PointerRNA *ptr, float *values) +static void rna_MeshTessFace_normal_get(PointerRNA *ptr, float *values) { Mesh *me = rna_mesh(ptr); MFace *mface = (MFace*)ptr->data; @@ -237,7 +237,7 @@ static void rna_MeshFace_normal_get(PointerRNA *ptr, float *values) normal_tri_v3(values, me->mvert[mface->v1].co, me->mvert[mface->v2].co, me->mvert[mface->v3].co); } -static float rna_MeshFace_area_get(PointerRNA *ptr) +static float rna_MeshTessFace_area_get(PointerRNA *ptr) { Mesh *me = rna_mesh(ptr); MFace *mface = (MFace*)ptr->data; @@ -466,14 +466,6 @@ static void rna_MeshVertex_groups_begin(CollectionPropertyIterator *iter, Pointe rna_iterator_array_begin(iter, NULL, 0, 0, 0, NULL); } -static void rna_MeshFace_material_index_range(PointerRNA *ptr, int *min, int *max) -{ - Mesh *me = rna_mesh(ptr); - *min = 0; - *max = me->totcol-1; - *max = MAX2(0, *max); -} - static int rna_CustomDataLayer_active_get(PointerRNA *ptr, CustomData *data, int type, int render) { int n = ((CustomDataLayer*)ptr->data) - data->layers; @@ -884,7 +876,7 @@ static float rna_Mesh_auto_smooth_angle_get(PointerRNA *ptr) return DEG2RADF((float)me->smoothresh); } -static int rna_MeshFace_verts_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION]) +static int rna_MeshTessFace_verts_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION]) { MFace *face = (MFace*)ptr->data; @@ -896,13 +888,13 @@ static int rna_MeshFace_verts_get_length(PointerRNA *ptr, int length[RNA_MAX_ARR return length[0]; } -static void rna_MeshFace_verts_get(PointerRNA *ptr, int *values) +static void rna_MeshTessFace_verts_get(PointerRNA *ptr, int *values) { MFace *face = (MFace*)ptr->data; memcpy(values, &face->v1, (face->v4 ? 4 : 3) * sizeof(int)); } -static void rna_MeshFace_verts_set(PointerRNA *ptr, const int *values) +static void rna_MeshTessFace_verts_set(PointerRNA *ptr, const int *values) { MFace *face = (MFace*)ptr->data; memcpy(&face->v1, values, (face->v4 ? 4 : 3) * sizeof(int)); @@ -938,6 +930,13 @@ static void rna_MeshPoly_vertices_set(PointerRNA *ptr, const int *values) } } +static void rna_MeshPoly_material_index_range(PointerRNA *ptr, int *min, int *max) +{ + Mesh *me = rna_mesh(ptr); + *min = 0; + *max = me->totcol-1; + *max = MAX2(0, *max); +} static int rna_MeshVertex_index_get(PointerRNA *ptr) { @@ -953,7 +952,7 @@ static int rna_MeshEdge_index_get(PointerRNA *ptr) return (int)(edge - me->medge); } -static int rna_MeshFace_index_get(PointerRNA *ptr) +static int rna_MeshTessFace_index_get(PointerRNA *ptr) { Mesh *me = rna_mesh(ptr); MFace *face = (MFace*)ptr->data; @@ -996,9 +995,9 @@ static char *rna_MeshPolygon_path(PointerRNA *ptr) return BLI_sprintfN("polygons[%d]", (int)((MPoly*)ptr->data - rna_mesh(ptr)->mpoly)); } -static char *rna_MeshFace_path(PointerRNA *ptr) +static char *rna_MeshTessFace_path(PointerRNA *ptr) { - return BLI_sprintfN("faces[%d]", (int)((MFace*)ptr->data - rna_mesh(ptr)->mface)); + return BLI_sprintfN("tessfaces[%d]", (int)((MFace *)ptr->data - rna_mesh(ptr)->mface)); } static char *rna_MeshEdge_path(PointerRNA *ptr) @@ -1442,18 +1441,18 @@ static void rna_def_mface(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; - srna = RNA_def_struct(brna, "MeshFace", NULL); + srna = RNA_def_struct(brna, "MeshTessFace", NULL); RNA_def_struct_sdna(srna, "MFace"); RNA_def_struct_ui_text(srna, "Mesh Face", "Face in a Mesh datablock"); - RNA_def_struct_path_func(srna, "rna_MeshFace_path"); + RNA_def_struct_path_func(srna, "rna_MeshTessFace_path"); RNA_def_struct_ui_icon(srna, ICON_FACESEL); /* XXX allows creating invalid meshes */ prop = RNA_def_property(srna, "vertices", PROP_INT, PROP_UNSIGNED); RNA_def_property_array(prop, 4); RNA_def_property_flag(prop, PROP_DYNAMIC); - RNA_def_property_dynamic_array_funcs(prop, "rna_MeshFace_verts_get_length"); - RNA_def_property_int_funcs(prop, "rna_MeshFace_verts_get", "rna_MeshFace_verts_set", NULL); + RNA_def_property_dynamic_array_funcs(prop, "rna_MeshTessFace_verts_get_length"); + RNA_def_property_int_funcs(prop, "rna_MeshTessFace_verts_get", "rna_MeshTessFace_verts_set", NULL); RNA_def_property_ui_text(prop, "Vertices", "Vertex indices"); /* leaving this fixed size array for foreach_set used in import scripts */ @@ -1465,7 +1464,7 @@ static void rna_def_mface(BlenderRNA *brna) prop = RNA_def_property(srna, "material_index", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "mat_nr"); RNA_def_property_ui_text(prop, "Material Index", ""); - RNA_def_property_int_funcs(prop, NULL, NULL, "rna_MeshFace_material_index_range"); + RNA_def_property_int_funcs(prop, NULL, NULL, "rna_MeshPoly_material_index_range"); /* reuse for tessface is ok */ RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); @@ -1487,17 +1486,17 @@ static void rna_def_mface(BlenderRNA *brna) RNA_def_property_array(prop, 3); RNA_def_property_range(prop, -1.0f, 1.0f); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_float_funcs(prop, "rna_MeshFace_normal_get", NULL, NULL); + RNA_def_property_float_funcs(prop, "rna_MeshTessFace_normal_get", NULL, NULL); RNA_def_property_ui_text(prop, "Face normal", "Local space unit length normal vector for this face"); prop = RNA_def_property(srna, "area", PROP_FLOAT, PROP_UNSIGNED); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_float_funcs(prop, "rna_MeshFace_area_get", NULL, NULL); + RNA_def_property_float_funcs(prop, "rna_MeshTessFace_area_get", NULL, NULL); RNA_def_property_ui_text(prop, "Face area", "Read only area of the face"); prop = RNA_def_property(srna, "index", PROP_INT, PROP_UNSIGNED); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_int_funcs(prop, "rna_MeshFace_index_get", NULL, NULL); + RNA_def_property_int_funcs(prop, "rna_MeshTessFace_index_get", NULL, NULL); RNA_def_property_ui_text(prop, "Index", "Index number of the vertex"); } @@ -1562,7 +1561,7 @@ static void rna_def_mpolygon(BlenderRNA *brna) prop = RNA_def_property(srna, "material_index", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "mat_nr"); RNA_def_property_ui_text(prop, "Material Index", ""); - RNA_def_property_int_funcs(prop, NULL, NULL, "rna_MeshFace_material_index_range"); + RNA_def_property_int_funcs(prop, NULL, NULL, "rna_MeshPoly_material_index_range"); RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); @@ -2492,9 +2491,9 @@ static void rna_def_mesh(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Edges", "Edges of the mesh"); rna_def_mesh_edges(brna, prop); - prop = RNA_def_property(srna, "faces", PROP_COLLECTION, PROP_NONE); + prop = RNA_def_property(srna, "tessfaces", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "mface", "totface"); - RNA_def_property_struct_type(prop, "MeshFace"); + RNA_def_property_struct_type(prop, "MeshTessFace"); RNA_def_property_ui_text(prop, "Faces", "Faces of the mesh"); rna_def_mesh_faces(brna, prop); |