Python API: add loop triangles access, remove tessfaces.
Loop triangles are tessellated triangles create from polygons, for renderers or exporters that need to match Blender's polygon tesselation exactly. These are a read-only runtime cache. Tessfaces are a legacy data structure from before Blender supported n-gons, and were already mostly removed from the C code. Details on porting code to loop triangles is in the release notes. Differential Revision: https://developer.blender.org/D3539
This commit is contained in:
		@@ -83,7 +83,7 @@ When writing scripts that operate on editmode data you will normally want to re-
 | 
				
			|||||||
running the  script, this needs to be called explicitly.
 | 
					running the  script, this needs to be called explicitly.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The BMesh its self does not store the triangulated faces, they are stored in the :class:`bpy.types.Mesh`,
 | 
					The BMesh its self does not store the triangulated faces, they are stored in the :class:`bpy.types.Mesh`,
 | 
				
			||||||
to refresh tessellation faces call :class:`bpy.types.Mesh.calc_tessface`.
 | 
					to refresh tessellation triangles call :class:`bpy.types.Mesh.calc_loop_triangles`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CustomData Access
 | 
					CustomData Access
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -164,26 +164,26 @@ for list removal, but these are slower.
 | 
				
			|||||||
Sometimes its faster (but more memory hungry) to just rebuild the list.
 | 
					Sometimes its faster (but more memory hungry) to just rebuild the list.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Say you want to remove all triangular faces in a list.
 | 
					Say you want to remove all triangular polygons in a list.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Rather than...
 | 
					Rather than...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. code-block:: python
 | 
					.. code-block:: python
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   faces = mesh.tessfaces[:]  # make a list copy of the meshes faces
 | 
					   polygons = mesh.polygons[:]  # make a list copy of the meshes polygons
 | 
				
			||||||
   f_idx = len(faces)     # Loop backwards
 | 
					   p_idx = len(polygons)     # Loop backwards
 | 
				
			||||||
   while f_idx:           # while the value is not 0
 | 
					   while p_idx:           # while the value is not 0
 | 
				
			||||||
       f_idx -= 1
 | 
					       p_idx -= 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
       if len(faces[f_idx].vertices) == 3:
 | 
					       if len(polygons[p_idx].vertices) == 3:
 | 
				
			||||||
           faces.pop(f_idx)  # remove the triangle
 | 
					           polygons.pop(p_idx)  # remove the triangle
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
It's faster to build a new list with list comprehension.
 | 
					It's faster to build a new list with list comprehension.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. code-block:: python
 | 
					.. code-block:: python
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   faces = [f for f in mesh.tessfaces if len(f.vertices) != 3]
 | 
					   polygons = [p for p in mesh.polygons if len(p.vertices) != 3]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Adding List Items
 | 
					Adding List Items
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -173,25 +173,25 @@ In this situation you can...
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
.. _info_gotcha_mesh_faces:
 | 
					.. _info_gotcha_mesh_faces:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
N-Gons and Tessellation Faces
 | 
					N-Gons and Tessellation
 | 
				
			||||||
=============================
 | 
					=======================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Since 2.63 NGons are supported, this adds some complexity
 | 
					Since 2.63 NGons are supported, this adds some complexity
 | 
				
			||||||
since in some cases you need to access triangles/quads still (some exporters for example).
 | 
					since in some cases you need to access triangles still (some exporters for example).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
There are now 3 ways to access faces:
 | 
					There are now 3 ways to access faces:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- :class:`bpy.types.MeshPolygon` -
 | 
					- :class:`bpy.types.MeshPolygon` -
 | 
				
			||||||
  this is the data structure which now stores faces in object mode
 | 
					  this is the data structure which now stores faces in object mode
 | 
				
			||||||
  (access as ``mesh.polygons`` rather than ``mesh.faces``).
 | 
					  (access as ``mesh.polygons`` rather than ``mesh.faces``).
 | 
				
			||||||
- :class:`bpy.types.MeshTessFace` -
 | 
					- :class:`bpy.types.MeshLoopTriangle` -
 | 
				
			||||||
  the result of triangulating (tessellated) polygons,
 | 
					  the result of tessellating polygons into triangles
 | 
				
			||||||
  the main method of face access in 2.62 or older (access as ``mesh.tessfaces``).
 | 
					  (access as ``mesh.loop_triangles``).
 | 
				
			||||||
- :class:`bmesh.types.BMFace` -
 | 
					- :class:`bmesh.types.BMFace` -
 | 
				
			||||||
  the polygons as used in editmode.
 | 
					  the polygons as used in editmode.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
For the purpose of the following documentation,
 | 
					For the purpose of the following documentation,
 | 
				
			||||||
these will be referred to as polygons, tessfaces and bmesh-faces respectively.
 | 
					these will be referred to as polygons, loop triangles and bmesh-faces respectively.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
5+ sided faces will be referred to as ``ngons``.
 | 
					5+ sided faces will be referred to as ``ngons``.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -234,13 +234,8 @@ 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,
 | 
					- 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.
 | 
					  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),
 | 
					  This is further complicated by the fact that each polygon does not store its own verts,
 | 
				
			||||||
  rather they reference an index and size in :class:`bpy.types.Mesh.loops` which are a fixed array too.
 | 
					  rather they reference an index and size in :class:`bpy.types.Mesh.loops` which are a fixed array too.
 | 
				
			||||||
- 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 can't be created this way.
 | 
					 | 
				
			||||||
- bmesh-faces are most likely the easiest way for new scripts to create faces,
 | 
					- 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.
 | 
					  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.
 | 
					  While :class:`bmesh.types.BMesh` uses more memory it can be managed by only operating on one mesh at a time.
 | 
				
			||||||
@@ -271,30 +266,6 @@ the choice mostly depends on whether the target format supports ngons or not.
 | 
				
			|||||||
  since using bmesh gives some overhead because its not the native storage format in object mode.
 | 
					  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 attribute.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
- 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:`bpy.types.Mesh.update` ``(calc_tessface=True)``.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
EditBones, PoseBones, Bone... Bones
 | 
					EditBones, PoseBones, Bone... Bones
 | 
				
			||||||
===================================
 | 
					===================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -247,11 +247,11 @@ static bool ObtainCacheParticleUV(Mesh *mesh,
 | 
				
			|||||||
				b_psys.particles.begin(b_pa);
 | 
									b_psys.particles.begin(b_pa);
 | 
				
			||||||
				for(; pa_no < totparts+totchild; pa_no++) {
 | 
									for(; pa_no < totparts+totchild; pa_no++) {
 | 
				
			||||||
					/* Add UVs */
 | 
										/* Add UVs */
 | 
				
			||||||
					BL::Mesh::tessface_uv_textures_iterator l;
 | 
										BL::Mesh::uv_layers_iterator l;
 | 
				
			||||||
					b_mesh->tessface_uv_textures.begin(l);
 | 
										b_mesh->uv_layers.begin(l);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					float3 uv = make_float3(0.0f, 0.0f, 0.0f);
 | 
										float3 uv = make_float3(0.0f, 0.0f, 0.0f);
 | 
				
			||||||
					if(b_mesh->tessface_uv_textures.length())
 | 
										if(b_mesh->uv_layers.length())
 | 
				
			||||||
						b_psys.uv_on_emitter(psmd, *b_pa, pa_no, uv_num, &uv.x);
 | 
											b_psys.uv_on_emitter(psmd, *b_pa, pa_no, uv_num, &uv.x);
 | 
				
			||||||
					CData->curve_uv.push_back_slow(uv);
 | 
										CData->curve_uv.push_back_slow(uv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -306,11 +306,11 @@ static bool ObtainCacheParticleVcol(Mesh *mesh,
 | 
				
			|||||||
				b_psys.particles.begin(b_pa);
 | 
									b_psys.particles.begin(b_pa);
 | 
				
			||||||
				for(; pa_no < totparts+totchild; pa_no++) {
 | 
									for(; pa_no < totparts+totchild; pa_no++) {
 | 
				
			||||||
					/* Add vertex colors */
 | 
										/* Add vertex colors */
 | 
				
			||||||
					BL::Mesh::tessface_vertex_colors_iterator l;
 | 
										BL::Mesh::vertex_colors_iterator l;
 | 
				
			||||||
					b_mesh->tessface_vertex_colors.begin(l);
 | 
										b_mesh->vertex_colors.begin(l);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					float3 vcol = make_float3(0.0f, 0.0f, 0.0f);
 | 
										float3 vcol = make_float3(0.0f, 0.0f, 0.0f);
 | 
				
			||||||
					if(b_mesh->tessface_vertex_colors.length())
 | 
										if(b_mesh->vertex_colors.length())
 | 
				
			||||||
						b_psys.mcol_on_emitter(psmd, *b_pa, pa_no, vcol_num, &vcol.x);
 | 
											b_psys.mcol_on_emitter(psmd, *b_pa, pa_no, vcol_num, &vcol.x);
 | 
				
			||||||
					CData->curve_vcol.push_back_slow(vcol);
 | 
										CData->curve_vcol.push_back_slow(vcol);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -968,10 +968,10 @@ void BlenderSync::sync_curves(Mesh *mesh,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	/* create vertex color attributes */
 | 
						/* create vertex color attributes */
 | 
				
			||||||
	if(!motion) {
 | 
						if(!motion) {
 | 
				
			||||||
		BL::Mesh::tessface_vertex_colors_iterator l;
 | 
							BL::Mesh::vertex_colors_iterator l;
 | 
				
			||||||
		int vcol_num = 0;
 | 
							int vcol_num = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for(b_mesh.tessface_vertex_colors.begin(l); l != b_mesh.tessface_vertex_colors.end(); ++l, vcol_num++) {
 | 
							for(b_mesh.vertex_colors.begin(l); l != b_mesh.vertex_colors.end(); ++l, vcol_num++) {
 | 
				
			||||||
			if(!mesh->need_attribute(scene, ustring(l->name().c_str())))
 | 
								if(!mesh->need_attribute(scene, ustring(l->name().c_str())))
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1005,10 +1005,10 @@ void BlenderSync::sync_curves(Mesh *mesh,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	/* create UV attributes */
 | 
						/* create UV attributes */
 | 
				
			||||||
	if(!motion) {
 | 
						if(!motion) {
 | 
				
			||||||
		BL::Mesh::tessface_uv_textures_iterator l;
 | 
							BL::Mesh::uv_layers_iterator l;
 | 
				
			||||||
		int uv_num = 0;
 | 
							int uv_num = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l, uv_num++) {
 | 
							for(b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l, uv_num++) {
 | 
				
			||||||
			bool active_render = l->active_render();
 | 
								bool active_render = l->active_render();
 | 
				
			||||||
			AttributeStandard std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE;
 | 
								AttributeStandard std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE;
 | 
				
			||||||
			ustring name = ustring(l->name().c_str());
 | 
								ustring name = ustring(l->name().c_str());
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,46 +35,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
CCL_NAMESPACE_BEGIN
 | 
					CCL_NAMESPACE_BEGIN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Per-face bit flags. */
 | 
					 | 
				
			||||||
enum {
 | 
					 | 
				
			||||||
	/* Face has no special flags. */
 | 
					 | 
				
			||||||
	FACE_FLAG_NONE      = (0 << 0),
 | 
					 | 
				
			||||||
	/* Quad face was split using 1-3 diagonal. */
 | 
					 | 
				
			||||||
	FACE_FLAG_DIVIDE_13 = (1 << 0),
 | 
					 | 
				
			||||||
	/* Quad face was split using 2-4 diagonal. */
 | 
					 | 
				
			||||||
	FACE_FLAG_DIVIDE_24 = (1 << 1),
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Get vertex indices to create triangles from a given face.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Two triangles has vertex indices in the original Blender-side face.
 | 
					 | 
				
			||||||
 * If face is already a quad tri_b will not be initialized.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
inline void face_split_tri_indices(const int face_flag,
 | 
					 | 
				
			||||||
                                   int tri_a[3],
 | 
					 | 
				
			||||||
                                   int tri_b[3])
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if(face_flag & FACE_FLAG_DIVIDE_24) {
 | 
					 | 
				
			||||||
		tri_a[0] = 0;
 | 
					 | 
				
			||||||
		tri_a[1] = 1;
 | 
					 | 
				
			||||||
		tri_a[2] = 3;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		tri_b[0] = 2;
 | 
					 | 
				
			||||||
		tri_b[1] = 3;
 | 
					 | 
				
			||||||
		tri_b[2] = 1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else {
 | 
					 | 
				
			||||||
		/* Quad with FACE_FLAG_DIVIDE_13 or single triangle. */
 | 
					 | 
				
			||||||
		tri_a[0] = 0;
 | 
					 | 
				
			||||||
		tri_a[1] = 1;
 | 
					 | 
				
			||||||
		tri_a[2] = 2;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		tri_b[0] = 0;
 | 
					 | 
				
			||||||
		tri_b[1] = 2;
 | 
					 | 
				
			||||||
		tri_b[2] = 3;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Tangent Space */
 | 
					/* Tangent Space */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct MikkUserData {
 | 
					struct MikkUserData {
 | 
				
			||||||
@@ -379,8 +339,6 @@ static void create_mesh_volume_attributes(Scene *scene,
 | 
				
			|||||||
static void attr_create_vertex_color(Scene *scene,
 | 
					static void attr_create_vertex_color(Scene *scene,
 | 
				
			||||||
                                     Mesh *mesh,
 | 
					                                     Mesh *mesh,
 | 
				
			||||||
                                     BL::Mesh& b_mesh,
 | 
					                                     BL::Mesh& b_mesh,
 | 
				
			||||||
                                     const vector<int>& nverts,
 | 
					 | 
				
			||||||
                                     const vector<int>& face_flags,
 | 
					 | 
				
			||||||
                                     bool subdivision)
 | 
					                                     bool subdivision)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if(subdivision) {
 | 
						if(subdivision) {
 | 
				
			||||||
@@ -401,15 +359,15 @@ static void attr_create_vertex_color(Scene *scene,
 | 
				
			|||||||
				int n = p->loop_total();
 | 
									int n = p->loop_total();
 | 
				
			||||||
				for(int i = 0; i < n; i++) {
 | 
									for(int i = 0; i < n; i++) {
 | 
				
			||||||
					float3 color = get_float3(l->data[p->loop_start() + i].color());
 | 
										float3 color = get_float3(l->data[p->loop_start() + i].color());
 | 
				
			||||||
					/* Encode vertex color using the sRGB curve. */
 | 
										/* Compress/encode vertex color using the sRGB curve. */
 | 
				
			||||||
					*(cdata++) = color_float_to_byte(color_srgb_to_linear_v3(color));
 | 
										*(cdata++) = color_float_to_byte(color_srgb_to_linear_v3(color));
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
		BL::Mesh::tessface_vertex_colors_iterator l;
 | 
							BL::Mesh::vertex_colors_iterator l;
 | 
				
			||||||
		for(b_mesh.tessface_vertex_colors.begin(l); l != b_mesh.tessface_vertex_colors.end(); ++l) {
 | 
							for(b_mesh.vertex_colors.begin(l); l != b_mesh.vertex_colors.end(); ++l) {
 | 
				
			||||||
			if(!mesh->need_attribute(scene, ustring(l->name().c_str())))
 | 
								if(!mesh->need_attribute(scene, ustring(l->name().c_str())))
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -417,34 +375,19 @@ static void attr_create_vertex_color(Scene *scene,
 | 
				
			|||||||
			                                       TypeDesc::TypeColor,
 | 
								                                       TypeDesc::TypeColor,
 | 
				
			||||||
			                                       ATTR_ELEMENT_CORNER_BYTE);
 | 
								                                       ATTR_ELEMENT_CORNER_BYTE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			BL::MeshColorLayer::data_iterator c;
 | 
								BL::Mesh::loop_triangles_iterator t;
 | 
				
			||||||
			uchar4 *cdata = attr->data_uchar4();
 | 
								uchar4 *cdata = attr->data_uchar4();
 | 
				
			||||||
			size_t i = 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			for(l->data.begin(c); c != l->data.end(); ++c, ++i) {
 | 
								for(b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) {
 | 
				
			||||||
				int tri_a[3], tri_b[3];
 | 
									int3 li = get_int3(t->loops());
 | 
				
			||||||
				face_split_tri_indices(face_flags[i], tri_a, tri_b);
 | 
									float3 c1 = get_float3(l->data[li[0]].color());
 | 
				
			||||||
 | 
									float3 c2 = get_float3(l->data[li[1]].color());
 | 
				
			||||||
 | 
									float3 c3 = get_float3(l->data[li[2]].color());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				/* Encode vertex color using the sRGB curve. */
 | 
									/* Compress/encode vertex color using the sRGB curve. */
 | 
				
			||||||
				uchar4 colors[4];
 | 
									cdata[0] = color_float_to_byte(color_srgb_to_linear_v3(c1));
 | 
				
			||||||
				colors[0] = color_float_to_byte(color_srgb_to_linear_v3(get_float3(c->color1())));
 | 
									cdata[1] = color_float_to_byte(color_srgb_to_linear_v3(c2));
 | 
				
			||||||
				colors[1] = color_float_to_byte(color_srgb_to_linear_v3(get_float3(c->color2())));
 | 
									cdata[2] = color_float_to_byte(color_srgb_to_linear_v3(c3));
 | 
				
			||||||
				colors[2] = color_float_to_byte(color_srgb_to_linear_v3(get_float3(c->color3())));
 | 
					 | 
				
			||||||
				if(nverts[i] == 4) {
 | 
					 | 
				
			||||||
					colors[3] = color_float_to_byte(color_srgb_to_linear_v3(get_float3(c->color4())));
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				cdata[0] = colors[tri_a[0]];
 | 
					 | 
				
			||||||
				cdata[1] = colors[tri_a[1]];
 | 
					 | 
				
			||||||
				cdata[2] = colors[tri_a[2]];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				if(nverts[i] == 4) {
 | 
					 | 
				
			||||||
					cdata[3] = colors[tri_b[0]];
 | 
					 | 
				
			||||||
					cdata[4] = colors[tri_b[1]];
 | 
					 | 
				
			||||||
					cdata[5] = colors[tri_b[2]];
 | 
					 | 
				
			||||||
					cdata += 6;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				else
 | 
					 | 
				
			||||||
				cdata += 3;
 | 
									cdata += 3;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -454,14 +397,12 @@ static void attr_create_vertex_color(Scene *scene,
 | 
				
			|||||||
/* Create uv map attributes. */
 | 
					/* Create uv map attributes. */
 | 
				
			||||||
static void attr_create_uv_map(Scene *scene,
 | 
					static void attr_create_uv_map(Scene *scene,
 | 
				
			||||||
                               Mesh *mesh,
 | 
					                               Mesh *mesh,
 | 
				
			||||||
                               BL::Mesh& b_mesh,
 | 
					                               BL::Mesh& b_mesh)
 | 
				
			||||||
                               const vector<int>& nverts,
 | 
					 | 
				
			||||||
                               const vector<int>& face_flags)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if(b_mesh.tessface_uv_textures.length() != 0) {
 | 
						if(b_mesh.uv_layers.length() != 0) {
 | 
				
			||||||
		BL::Mesh::tessface_uv_textures_iterator l;
 | 
							BL::Mesh::uv_layers_iterator l;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) {
 | 
							for(b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l) {
 | 
				
			||||||
			const bool active_render = l->active_render();
 | 
								const bool active_render = l->active_render();
 | 
				
			||||||
			AttributeStandard uv_std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE;
 | 
								AttributeStandard uv_std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE;
 | 
				
			||||||
			ustring uv_name = ustring(l->name().c_str());
 | 
								ustring uv_name = ustring(l->name().c_str());
 | 
				
			||||||
@@ -493,33 +434,15 @@ static void attr_create_uv_map(Scene *scene,
 | 
				
			|||||||
					                               ATTR_ELEMENT_CORNER);
 | 
										                               ATTR_ELEMENT_CORNER);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				BL::MeshTextureFaceLayer::data_iterator t;
 | 
									BL::Mesh::loop_triangles_iterator t;
 | 
				
			||||||
				float3 *fdata = uv_attr->data_float3();
 | 
									float3 *fdata = uv_attr->data_float3();
 | 
				
			||||||
				size_t i = 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
				for(l->data.begin(t); t != l->data.end(); ++t, ++i) {
 | 
									for(b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) {
 | 
				
			||||||
					int tri_a[3], tri_b[3];
 | 
										int3 li = get_int3(t->loops());
 | 
				
			||||||
					face_split_tri_indices(face_flags[i], tri_a, tri_b);
 | 
										fdata[0] = get_float3(l->data[li[0]].uv());
 | 
				
			||||||
 | 
										fdata[1] = get_float3(l->data[li[1]].uv());
 | 
				
			||||||
					float3 uvs[4];
 | 
										fdata[2] = get_float3(l->data[li[2]].uv());
 | 
				
			||||||
					uvs[0] = get_float3(t->uv1());
 | 
					 | 
				
			||||||
					uvs[1] = get_float3(t->uv2());
 | 
					 | 
				
			||||||
					uvs[2] = get_float3(t->uv3());
 | 
					 | 
				
			||||||
					if(nverts[i] == 4) {
 | 
					 | 
				
			||||||
						uvs[3] = get_float3(t->uv4());
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					fdata[0] = uvs[tri_a[0]];
 | 
					 | 
				
			||||||
					fdata[1] = uvs[tri_a[1]];
 | 
					 | 
				
			||||||
					fdata[2] = uvs[tri_a[2]];
 | 
					 | 
				
			||||||
					fdata += 3;
 | 
										fdata += 3;
 | 
				
			||||||
 | 
					 | 
				
			||||||
					if(nverts[i] == 4) {
 | 
					 | 
				
			||||||
						fdata[0] = uvs[tri_b[0]];
 | 
					 | 
				
			||||||
						fdata[1] = uvs[tri_b[1]];
 | 
					 | 
				
			||||||
						fdata[2] = uvs[tri_b[2]];
 | 
					 | 
				
			||||||
						fdata += 3;
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -822,7 +745,7 @@ static void create_mesh(Scene *scene,
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	/* count vertices and faces */
 | 
						/* count vertices and faces */
 | 
				
			||||||
	int numverts = b_mesh.vertices.length();
 | 
						int numverts = b_mesh.vertices.length();
 | 
				
			||||||
	int numfaces = (!subdivision) ? b_mesh.tessfaces.length() : b_mesh.polygons.length();
 | 
						int numfaces = (!subdivision) ? b_mesh.loop_triangles.length() : b_mesh.polygons.length();
 | 
				
			||||||
	int numtris = 0;
 | 
						int numtris = 0;
 | 
				
			||||||
	int numcorners = 0;
 | 
						int numcorners = 0;
 | 
				
			||||||
	int numngons = 0;
 | 
						int numngons = 0;
 | 
				
			||||||
@@ -834,14 +757,10 @@ static void create_mesh(Scene *scene,
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	BL::Mesh::vertices_iterator v;
 | 
						BL::Mesh::vertices_iterator v;
 | 
				
			||||||
	BL::Mesh::tessfaces_iterator f;
 | 
					 | 
				
			||||||
	BL::Mesh::polygons_iterator p;
 | 
						BL::Mesh::polygons_iterator p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(!subdivision) {
 | 
						if(!subdivision) {
 | 
				
			||||||
		for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f) {
 | 
							numtris = numfaces;
 | 
				
			||||||
			int4 vi = get_int4(f->vertices_raw());
 | 
					 | 
				
			||||||
			numtris += (vi[3] == 0)? 1: 2;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
		for(b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
 | 
							for(b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
 | 
				
			||||||
@@ -869,7 +788,7 @@ static void create_mesh(Scene *scene,
 | 
				
			|||||||
	/* create generated coordinates from undeformed coordinates */
 | 
						/* create generated coordinates from undeformed coordinates */
 | 
				
			||||||
	const bool need_default_tangent =
 | 
						const bool need_default_tangent =
 | 
				
			||||||
	        (subdivision == false) &&
 | 
						        (subdivision == false) &&
 | 
				
			||||||
	        (b_mesh.tessface_uv_textures.length() == 0) &&
 | 
						        (b_mesh.uv_layers.length() == 0) &&
 | 
				
			||||||
	        (mesh->need_attribute(scene, ATTR_STD_UV_TANGENT));
 | 
						        (mesh->need_attribute(scene, ATTR_STD_UV_TANGENT));
 | 
				
			||||||
	if(mesh->need_attribute(scene, ATTR_STD_GENERATED) ||
 | 
						if(mesh->need_attribute(scene, ATTR_STD_GENERATED) ||
 | 
				
			||||||
	   need_default_tangent)
 | 
						   need_default_tangent)
 | 
				
			||||||
@@ -890,19 +809,21 @@ static void create_mesh(Scene *scene,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	/* create faces */
 | 
						/* create faces */
 | 
				
			||||||
	vector<int> nverts(numfaces);
 | 
						vector<int> nverts(numfaces);
 | 
				
			||||||
	vector<int> face_flags(numfaces, FACE_FLAG_NONE);
 | 
					 | 
				
			||||||
	int fi = 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(!subdivision) {
 | 
						if(!subdivision) {
 | 
				
			||||||
		for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f, ++fi) {
 | 
							BL::Mesh::loop_triangles_iterator t;
 | 
				
			||||||
			int4 vi = get_int4(f->vertices_raw());
 | 
							int ti = 0;
 | 
				
			||||||
			int n = (vi[3] == 0)? 3: 4;
 | 
					
 | 
				
			||||||
			int shader = clamp(f->material_index(), 0, used_shaders.size()-1);
 | 
							for(b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t, ++ti) {
 | 
				
			||||||
			bool smooth = f->use_smooth() || use_loop_normals;
 | 
								BL::MeshPolygon p = b_mesh.polygons[t->polygon_index()];
 | 
				
			||||||
 | 
								int3 vi = get_int3(t->vertices());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								int shader = clamp(p.material_index(), 0, used_shaders.size()-1);
 | 
				
			||||||
 | 
								bool smooth = p.use_smooth() || use_loop_normals;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if(use_loop_normals) {
 | 
								if(use_loop_normals) {
 | 
				
			||||||
				BL::Array<float, 12> loop_normals = f->split_normals();
 | 
									BL::Array<float, 9> loop_normals = t->split_normals();
 | 
				
			||||||
				for(int i = 0; i < n; i++) {
 | 
									for(int i = 0; i < 3; i++) {
 | 
				
			||||||
					N[vi[i]] = make_float3(loop_normals[i * 3],
 | 
										N[vi[i]] = make_float3(loop_normals[i * 3],
 | 
				
			||||||
					                       loop_normals[i * 3 + 1],
 | 
										                       loop_normals[i * 3 + 1],
 | 
				
			||||||
					                       loop_normals[i * 3 + 2]);
 | 
										                       loop_normals[i * 3 + 2]);
 | 
				
			||||||
@@ -913,25 +834,8 @@ static void create_mesh(Scene *scene,
 | 
				
			|||||||
			 *
 | 
								 *
 | 
				
			||||||
			 * NOTE: Autosmooth is already taken care about.
 | 
								 * NOTE: Autosmooth is already taken care about.
 | 
				
			||||||
			 */
 | 
								 */
 | 
				
			||||||
			if(n == 4) {
 | 
					 | 
				
			||||||
				if(is_zero(cross(mesh->verts[vi[1]] - mesh->verts[vi[0]], mesh->verts[vi[2]] - mesh->verts[vi[0]])) ||
 | 
					 | 
				
			||||||
				   is_zero(cross(mesh->verts[vi[2]] - mesh->verts[vi[0]], mesh->verts[vi[3]] - mesh->verts[vi[0]])))
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					mesh->add_triangle(vi[0], vi[1], vi[3], shader, smooth);
 | 
					 | 
				
			||||||
					mesh->add_triangle(vi[2], vi[3], vi[1], shader, smooth);
 | 
					 | 
				
			||||||
					face_flags[fi] |= FACE_FLAG_DIVIDE_24;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				else {
 | 
					 | 
				
			||||||
			mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
 | 
								mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
 | 
				
			||||||
					mesh->add_triangle(vi[0], vi[2], vi[3], shader, smooth);
 | 
								nverts[ti] = 3;
 | 
				
			||||||
					face_flags[fi] |= FACE_FLAG_DIVIDE_13;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			else {
 | 
					 | 
				
			||||||
				mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			nverts[fi] = n;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
@@ -957,13 +861,13 @@ static void create_mesh(Scene *scene,
 | 
				
			|||||||
	 * The calculate functions will check whether they're needed or not.
 | 
						 * The calculate functions will check whether they're needed or not.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	attr_create_pointiness(scene, mesh, b_mesh, subdivision);
 | 
						attr_create_pointiness(scene, mesh, b_mesh, subdivision);
 | 
				
			||||||
	attr_create_vertex_color(scene, mesh, b_mesh, nverts, face_flags, subdivision);
 | 
						attr_create_vertex_color(scene, mesh, b_mesh, subdivision);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(subdivision) {
 | 
						if(subdivision) {
 | 
				
			||||||
		attr_create_subd_uv_map(scene, mesh, b_mesh, subdivide_uvs);
 | 
							attr_create_subd_uv_map(scene, mesh, b_mesh, subdivide_uvs);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
		attr_create_uv_map(scene, mesh, b_mesh, nverts, face_flags);
 | 
							attr_create_uv_map(scene, mesh, b_mesh);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* for volume objects, create a matrix to transform from object space to
 | 
						/* for volume objects, create a matrix to transform from object space to
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -83,7 +83,7 @@ static inline BL::Mesh object_to_mesh(BL::BlendData& data,
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if(subdivision_type == Mesh::SUBDIVISION_NONE) {
 | 
							if(subdivision_type == Mesh::SUBDIVISION_NONE) {
 | 
				
			||||||
			me.calc_tessface(true);
 | 
								me.calc_loop_triangles();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return me;
 | 
						return me;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,13 +20,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
__all__ = (
 | 
					__all__ = (
 | 
				
			||||||
    "mesh_linked_uv_islands",
 | 
					    "mesh_linked_uv_islands",
 | 
				
			||||||
    "mesh_linked_tessfaces",
 | 
					    "mesh_linked_triangles",
 | 
				
			||||||
    "edge_face_count_dict",
 | 
					    "edge_face_count_dict",
 | 
				
			||||||
    "edge_face_count",
 | 
					    "edge_face_count",
 | 
				
			||||||
    "edge_loops_from_tessfaces",
 | 
					 | 
				
			||||||
    "edge_loops_from_edges",
 | 
					    "edge_loops_from_edges",
 | 
				
			||||||
    "ngon_tessellate",
 | 
					    "ngon_tessellate",
 | 
				
			||||||
    "face_random_points",
 | 
					    "triangle_random_points",
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -90,41 +89,41 @@ def mesh_linked_uv_islands(mesh):
 | 
				
			|||||||
    return poly_islands
 | 
					    return poly_islands
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def mesh_linked_tessfaces(mesh):
 | 
					def mesh_linked_triangles(mesh):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Splits the mesh into connected faces, use this for separating cubes from
 | 
					    Splits the mesh into connected triangles, use this for separating cubes from
 | 
				
			||||||
    other mesh elements within 1 mesh datablock.
 | 
					    other mesh elements within 1 mesh datablock.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    :arg mesh: the mesh used to group with.
 | 
					    :arg mesh: the mesh used to group with.
 | 
				
			||||||
    :type mesh: :class:`bpy.types.Mesh`
 | 
					    :type mesh: :class:`bpy.types.Mesh`
 | 
				
			||||||
    :return: lists of lists containing faces.
 | 
					    :return: lists of lists containing triangles.
 | 
				
			||||||
    :rtype: list
 | 
					    :rtype: list
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Build vert face connectivity
 | 
					    # Build vert face connectivity
 | 
				
			||||||
    vert_faces = [[] for i in range(len(mesh.vertices))]
 | 
					    vert_tris = [[] for i in range(len(mesh.vertices))]
 | 
				
			||||||
    for f in mesh.tessfaces:
 | 
					    for t in mesh.loop_triangles:
 | 
				
			||||||
        for v in f.vertices:
 | 
					        for v in t.vertices:
 | 
				
			||||||
            vert_faces[v].append(f)
 | 
					            vert_tris[v].append(t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # sort faces into connectivity groups
 | 
					    # sort triangles into connectivity groups
 | 
				
			||||||
    face_groups = [[f] for f in mesh.tessfaces]
 | 
					    tri_groups = [[t] for t in mesh.loop_triangles]
 | 
				
			||||||
    # map old, new face location
 | 
					    # map old, new tri location
 | 
				
			||||||
    face_mapping = list(range(len(mesh.tessfaces)))
 | 
					    tri_mapping = list(range(len(mesh.loop_triangles)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Now clump faces iteratively
 | 
					    # Now clump triangles iteratively
 | 
				
			||||||
    ok = True
 | 
					    ok = True
 | 
				
			||||||
    while ok:
 | 
					    while ok:
 | 
				
			||||||
        ok = False
 | 
					        ok = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for i, f in enumerate(mesh.tessfaces):
 | 
					        for i, t in enumerate(mesh.loop_triangles):
 | 
				
			||||||
            mapped_index = face_mapping[f.index]
 | 
					            mapped_index = tri_mapping[t.index]
 | 
				
			||||||
            mapped_group = face_groups[mapped_index]
 | 
					            mapped_group = tri_groups[mapped_index]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            for v in f.vertices:
 | 
					            for v in t.vertices:
 | 
				
			||||||
                for nxt_f in vert_faces[v]:
 | 
					                for nxt_t in vert_tris[v]:
 | 
				
			||||||
                    if nxt_f != f:
 | 
					                    if nxt_t != t:
 | 
				
			||||||
                        nxt_mapped_index = face_mapping[nxt_f.index]
 | 
					                        nxt_mapped_index = tri_mapping[nxt_t.index]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        # We are not a part of the same group
 | 
					                        # We are not a part of the same group
 | 
				
			||||||
                        if mapped_index != nxt_mapped_index:
 | 
					                        if mapped_index != nxt_mapped_index:
 | 
				
			||||||
@@ -132,18 +131,18 @@ def mesh_linked_tessfaces(mesh):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                            # Assign mapping to this group so they
 | 
					                            # Assign mapping to this group so they
 | 
				
			||||||
                            # all map to this group
 | 
					                            # all map to this group
 | 
				
			||||||
                            for grp_f in face_groups[nxt_mapped_index]:
 | 
					                            for grp_t in tri_groups[nxt_mapped_index]:
 | 
				
			||||||
                                face_mapping[grp_f.index] = mapped_index
 | 
					                                tri_mapping[grp_t.index] = mapped_index
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                            # Move faces into this group
 | 
					                            # Move triangles into this group
 | 
				
			||||||
                            mapped_group.extend(face_groups[nxt_mapped_index])
 | 
					                            mapped_group.extend(tri_groups[nxt_mapped_index])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                            # remove reference to the list
 | 
					                            # remove reference to the list
 | 
				
			||||||
                            face_groups[nxt_mapped_index] = None
 | 
					                            tri_groups[nxt_mapped_index] = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # return all face groups that are not null
 | 
					    # return all tri groups that are not null
 | 
				
			||||||
    # this is all the faces that are connected in their own lists.
 | 
					    # this is all the triangles that are connected in their own lists.
 | 
				
			||||||
    return [fg for fg in face_groups if fg]
 | 
					    return [tg for tg in tri_groups if tg]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def edge_face_count_dict(mesh):
 | 
					def edge_face_count_dict(mesh):
 | 
				
			||||||
@@ -177,87 +176,6 @@ def edge_face_count(mesh):
 | 
				
			|||||||
    return [get(edge_face_count, ed.key, 0) for ed in mesh.edges]
 | 
					    return [get(edge_face_count, ed.key, 0) for ed in mesh.edges]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def edge_loops_from_tessfaces(mesh, tessfaces=None, seams=()):
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    Edge loops defined by faces
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Takes me.tessfaces or a list of faces and returns the edge loops
 | 
					 | 
				
			||||||
    These edge loops are the edges that sit between quads, so they don't touch
 | 
					 | 
				
			||||||
    1 quad, note: not connected will make 2 edge loops,
 | 
					 | 
				
			||||||
    both only containing 2 edges.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return a list of edge key lists
 | 
					 | 
				
			||||||
    [[(0, 1), (4, 8), (3, 8)], ...]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    :arg mesh: the mesh used to get edge loops from.
 | 
					 | 
				
			||||||
    :type mesh: :class:`bpy.types.Mesh`
 | 
					 | 
				
			||||||
    :arg tessfaces: optional face list to only use some of the meshes faces.
 | 
					 | 
				
			||||||
    :type tessfaces: :class:`bpy.types.MeshTessFace`, sequence or or NoneType
 | 
					 | 
				
			||||||
    :return: return a list of edge vertex index lists.
 | 
					 | 
				
			||||||
    :rtype: list
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    OTHER_INDEX = 2, 3, 0, 1  # opposite face index
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if tessfaces is None:
 | 
					 | 
				
			||||||
        tessfaces = mesh.tessfaces
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    edges = {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for f in tessfaces:
 | 
					 | 
				
			||||||
        if len(f.vertices) == 4:
 | 
					 | 
				
			||||||
            edge_keys = f.edge_keys
 | 
					 | 
				
			||||||
            for i, edkey in enumerate(f.edge_keys):
 | 
					 | 
				
			||||||
                edges.setdefault(edkey, []).append(edge_keys[OTHER_INDEX[i]])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for edkey in seams:
 | 
					 | 
				
			||||||
        edges[edkey] = []
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Collect edge loops here
 | 
					 | 
				
			||||||
    edge_loops = []
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for edkey, ed_adj in edges.items():
 | 
					 | 
				
			||||||
        if 0 < len(ed_adj) < 3:  # 1 or 2
 | 
					 | 
				
			||||||
            # Seek the first edge
 | 
					 | 
				
			||||||
            context_loop = [edkey, ed_adj[0]]
 | 
					 | 
				
			||||||
            edge_loops.append(context_loop)
 | 
					 | 
				
			||||||
            if len(ed_adj) == 2:
 | 
					 | 
				
			||||||
                other_dir = ed_adj[1]
 | 
					 | 
				
			||||||
            else:
 | 
					 | 
				
			||||||
                other_dir = None
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            del ed_adj[:]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            flipped = False
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            while 1:
 | 
					 | 
				
			||||||
                # from knowing the last 2, look for the next.
 | 
					 | 
				
			||||||
                ed_adj = edges[context_loop[-1]]
 | 
					 | 
				
			||||||
                if len(ed_adj) != 2:
 | 
					 | 
				
			||||||
                    # the original edge had 2 other edges
 | 
					 | 
				
			||||||
                    if other_dir and flipped is False:
 | 
					 | 
				
			||||||
                        flipped = True  # only flip the list once
 | 
					 | 
				
			||||||
                        context_loop.reverse()
 | 
					 | 
				
			||||||
                        del ed_adj[:]
 | 
					 | 
				
			||||||
                        context_loop.append(other_dir)  # save 1 look-up
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        ed_adj = edges[context_loop[-1]]
 | 
					 | 
				
			||||||
                        if len(ed_adj) != 2:
 | 
					 | 
				
			||||||
                            del ed_adj[:]
 | 
					 | 
				
			||||||
                            break
 | 
					 | 
				
			||||||
                    else:
 | 
					 | 
				
			||||||
                        del ed_adj[:]
 | 
					 | 
				
			||||||
                        break
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                i = ed_adj.index(context_loop[-2])
 | 
					 | 
				
			||||||
                context_loop.append(ed_adj[not i])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                # Don't look at this again
 | 
					 | 
				
			||||||
                del ed_adj[:]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return edge_loops
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def edge_loops_from_edges(mesh, edges=None):
 | 
					def edge_loops_from_edges(mesh, edges=None):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Edge loops defined by edges
 | 
					    Edge loops defined by edges
 | 
				
			||||||
@@ -511,54 +429,42 @@ def ngon_tessellate(from_data, indices, fix_loops=True):
 | 
				
			|||||||
    return fill
 | 
					    return fill
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def face_random_points(num_points, tessfaces):
 | 
					def triangle_random_points(num_points, loop_triangles):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Generates a list of random points over mesh tessfaces.
 | 
					    Generates a list of random points over mesh loop triangles.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    :arg num_points: the number of random points to generate on each face.
 | 
					    :arg num_points: the number of random points to generate on each triangle.
 | 
				
			||||||
    :type int:
 | 
					    :type int:
 | 
				
			||||||
    :arg tessfaces: list of the faces to generate points on.
 | 
					    :arg loop_triangles: list of the triangles to generate points on.
 | 
				
			||||||
    :type tessfaces: :class:`bpy.types.MeshTessFace`, sequence
 | 
					    :type loop_triangles: :class:`bpy.types.MeshLoopTriangle`, sequence
 | 
				
			||||||
    :return: list of random points over all faces.
 | 
					    :return: list of random points over all triangles.
 | 
				
			||||||
    :rtype: list
 | 
					    :rtype: list
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    from random import random
 | 
					    from random import random
 | 
				
			||||||
    from mathutils.geometry import area_tri
 | 
					    from mathutils.geometry import area_tri
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Split all quads into 2 tris, tris remain unchanged
 | 
					    # For each triangle, generate the required number of random points
 | 
				
			||||||
    tri_faces = []
 | 
					    sampled_points = [None] * (num_points * len(loop_triangles))
 | 
				
			||||||
    for f in tessfaces:
 | 
					    for i, lt in enumerate(loop_triangles):
 | 
				
			||||||
        tris = []
 | 
					        # Get triangle vertex coordinates
 | 
				
			||||||
        verts = f.id_data.vertices
 | 
					        verts = lt.id_data.vertices
 | 
				
			||||||
        fv = f.vertices[:]
 | 
					        ltv = lt.vertices[:]
 | 
				
			||||||
        tris.append((verts[fv[0]].co,
 | 
					        tv = (verts[ltv[0]].co, verts[ltv[1]].co, verts[ltv[2]].co)
 | 
				
			||||||
                     verts[fv[1]].co,
 | 
					 | 
				
			||||||
                     verts[fv[2]].co,
 | 
					 | 
				
			||||||
                     ))
 | 
					 | 
				
			||||||
        if len(fv) == 4:
 | 
					 | 
				
			||||||
            tris.append((verts[fv[0]].co,
 | 
					 | 
				
			||||||
                         verts[fv[3]].co,
 | 
					 | 
				
			||||||
                         verts[fv[2]].co,
 | 
					 | 
				
			||||||
                         ))
 | 
					 | 
				
			||||||
        tri_faces.append(tris)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # For each face, generate the required number of random points
 | 
					 | 
				
			||||||
    sampled_points = [None] * (num_points * len(tessfaces))
 | 
					 | 
				
			||||||
    for i, tf in enumerate(tri_faces):
 | 
					 | 
				
			||||||
        for k in range(num_points):
 | 
					        for k in range(num_points):
 | 
				
			||||||
            # If this is a quad, we need to weight its 2 tris by their area
 | 
					            # If this is a quad, we need to weight its 2 tris by their area
 | 
				
			||||||
            if len(tf) != 1:
 | 
					            if len(tv) != 1:
 | 
				
			||||||
                area1 = area_tri(*tf[0])
 | 
					                area1 = area_tri(*tv[0])
 | 
				
			||||||
                area2 = area_tri(*tf[1])
 | 
					                area2 = area_tri(*tv[1])
 | 
				
			||||||
                area_tot = area1 + area2
 | 
					                area_tot = area1 + area2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                area1 = area1 / area_tot
 | 
					                area1 = area1 / area_tot
 | 
				
			||||||
                area2 = area2 / area_tot
 | 
					                area2 = area2 / area_tot
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                vecs = tf[0 if (random() < area1) else 1]
 | 
					                vecs = tv[0 if (random() < area1) else 1]
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                vecs = tf[0]
 | 
					                vecs = tv[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            u1 = random()
 | 
					            u1 = random()
 | 
				
			||||||
            u2 = random()
 | 
					            u2 = random()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -468,7 +468,7 @@ class MeshEdge(StructRNA):
 | 
				
			|||||||
        return ord_ind(*tuple(self.vertices))
 | 
					        return ord_ind(*tuple(self.vertices))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class MeshTessFace(StructRNA):
 | 
					class MeshLoopTriangle(StructRNA):
 | 
				
			||||||
    __slots__ = ()
 | 
					    __slots__ = ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
@@ -476,32 +476,18 @@ class MeshTessFace(StructRNA):
 | 
				
			|||||||
        """The midpoint of the face."""
 | 
					        """The midpoint of the face."""
 | 
				
			||||||
        face_verts = self.vertices[:]
 | 
					        face_verts = self.vertices[:]
 | 
				
			||||||
        mesh_verts = self.id_data.vertices
 | 
					        mesh_verts = self.id_data.vertices
 | 
				
			||||||
        if len(face_verts) == 3:
 | 
					 | 
				
			||||||
        return (mesh_verts[face_verts[0]].co +
 | 
					        return (mesh_verts[face_verts[0]].co +
 | 
				
			||||||
                mesh_verts[face_verts[1]].co +
 | 
					                mesh_verts[face_verts[1]].co +
 | 
				
			||||||
                mesh_verts[face_verts[2]].co
 | 
					                mesh_verts[face_verts[2]].co
 | 
				
			||||||
                ) / 3.0
 | 
					                ) / 3.0
 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            return (mesh_verts[face_verts[0]].co +
 | 
					 | 
				
			||||||
                    mesh_verts[face_verts[1]].co +
 | 
					 | 
				
			||||||
                    mesh_verts[face_verts[2]].co +
 | 
					 | 
				
			||||||
                    mesh_verts[face_verts[3]].co
 | 
					 | 
				
			||||||
                    ) / 4.0
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def edge_keys(self):
 | 
					    def edge_keys(self):
 | 
				
			||||||
        verts = self.vertices[:]
 | 
					        verts = self.vertices[:]
 | 
				
			||||||
        if len(verts) == 3:
 | 
					 | 
				
			||||||
        return (ord_ind(verts[0], verts[1]),
 | 
					        return (ord_ind(verts[0], verts[1]),
 | 
				
			||||||
                ord_ind(verts[1], verts[2]),
 | 
					                ord_ind(verts[1], verts[2]),
 | 
				
			||||||
                ord_ind(verts[2], verts[0]),
 | 
					                ord_ind(verts[2], verts[0]),
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            return (ord_ind(verts[0], verts[1]),
 | 
					 | 
				
			||||||
                    ord_ind(verts[1], verts[2]),
 | 
					 | 
				
			||||||
                    ord_ind(verts[2], verts[3]),
 | 
					 | 
				
			||||||
                    ord_ind(verts[3], verts[0]),
 | 
					 | 
				
			||||||
                    )
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class MeshPolygon(StructRNA):
 | 
					class MeshPolygon(StructRNA):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -179,7 +179,7 @@ void BKE_mesh_split_faces(struct Mesh *mesh, bool free_loop_normals);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
struct Mesh *BKE_mesh_new_from_object(
 | 
					struct Mesh *BKE_mesh_new_from_object(
 | 
				
			||||||
        struct Depsgraph *depsgraph, struct Main *bmain, struct Scene *sce, struct Object *ob,
 | 
					        struct Depsgraph *depsgraph, struct Main *bmain, struct Scene *sce, struct Object *ob,
 | 
				
			||||||
        const bool apply_modifiers, const bool calc_tessface, const bool calc_undeformed);
 | 
					        const bool apply_modifiers, const bool calc_loop_triangles, const bool calc_undeformed);
 | 
				
			||||||
struct Mesh *BKE_mesh_create_derived_for_modifier(
 | 
					struct Mesh *BKE_mesh_create_derived_for_modifier(
 | 
				
			||||||
        struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob,
 | 
					        struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob,
 | 
				
			||||||
        struct ModifierData *md, int build_shapekey_layers);
 | 
					        struct ModifierData *md, int build_shapekey_layers);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -840,7 +840,7 @@ void BKE_mesh_to_curve(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *
 | 
				
			|||||||
/* settings: 1 - preview, 2 - render */
 | 
					/* settings: 1 - preview, 2 - render */
 | 
				
			||||||
Mesh *BKE_mesh_new_from_object(
 | 
					Mesh *BKE_mesh_new_from_object(
 | 
				
			||||||
        Depsgraph *depsgraph, Main *bmain, Scene *sce, Object *ob,
 | 
					        Depsgraph *depsgraph, Main *bmain, Scene *sce, Object *ob,
 | 
				
			||||||
        const bool apply_modifiers, const bool calc_tessface, const bool calc_undeformed)
 | 
					        const bool apply_modifiers, const bool calc_loop_triangles, const bool calc_undeformed)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	Mesh *tmpmesh;
 | 
						Mesh *tmpmesh;
 | 
				
			||||||
	Curve *tmpcu = NULL, *copycu;
 | 
						Curve *tmpcu = NULL, *copycu;
 | 
				
			||||||
@@ -1069,9 +1069,9 @@ Mesh *BKE_mesh_new_from_object(
 | 
				
			|||||||
			break;
 | 
								break;
 | 
				
			||||||
	} /* end copy materials */
 | 
						} /* end copy materials */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (calc_tessface) {
 | 
						if (calc_loop_triangles) {
 | 
				
			||||||
		/* cycles and exporters rely on this still */
 | 
							/* cycles and exporters rely on this still */
 | 
				
			||||||
		BKE_mesh_tessface_ensure(tmpmesh);
 | 
							BKE_mesh_runtime_looptri_ensure(tmpmesh);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return tmpmesh;
 | 
						return tmpmesh;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -107,13 +107,13 @@ NodeGroup *BlenderFileLoader::Load()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		bool apply_modifiers = false;
 | 
							bool apply_modifiers = false;
 | 
				
			||||||
		bool calc_undeformed = false;
 | 
							bool calc_undeformed = false;
 | 
				
			||||||
		bool calc_tessface = false;
 | 
							bool calc_loop_triangles = false;
 | 
				
			||||||
		Mesh *mesh = BKE_mesh_new_from_object(depsgraph,
 | 
							Mesh *mesh = BKE_mesh_new_from_object(depsgraph,
 | 
				
			||||||
		                                      _re->main,
 | 
							                                      _re->main,
 | 
				
			||||||
		                                      _re->scene,
 | 
							                                      _re->scene,
 | 
				
			||||||
		                                      ob,
 | 
							                                      ob,
 | 
				
			||||||
		                                      apply_modifiers,
 | 
							                                      apply_modifiers,
 | 
				
			||||||
		                                      calc_tessface,
 | 
							                                      calc_loop_triangles,
 | 
				
			||||||
		                                      calc_undeformed);
 | 
							                                      calc_undeformed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (mesh) {
 | 
							if (mesh) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -174,8 +174,6 @@ typedef struct MLoop {
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 * \note A #MLoopTri may be in the middle of an ngon and not reference **any** edges.
 | 
					 * \note A #MLoopTri may be in the middle of an ngon and not reference **any** edges.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#
 | 
					 | 
				
			||||||
#
 | 
					 | 
				
			||||||
typedef struct MLoopTri {
 | 
					typedef struct MLoopTri {
 | 
				
			||||||
	unsigned int tri[3];
 | 
						unsigned int tri[3];
 | 
				
			||||||
	unsigned int poly;
 | 
						unsigned int poly;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -390,7 +390,7 @@ extern StructRNA RNA_MeshLoopColorLayer;
 | 
				
			|||||||
extern StructRNA RNA_MeshDeformModifier;
 | 
					extern StructRNA RNA_MeshDeformModifier;
 | 
				
			||||||
extern StructRNA RNA_MeshEdge;
 | 
					extern StructRNA RNA_MeshEdge;
 | 
				
			||||||
extern StructRNA RNA_MeshPolygon;
 | 
					extern StructRNA RNA_MeshPolygon;
 | 
				
			||||||
extern StructRNA RNA_MeshTessFace;
 | 
					extern StructRNA RNA_MeshLoopTriangle;
 | 
				
			||||||
extern StructRNA RNA_MeshLoop;
 | 
					extern StructRNA RNA_MeshLoop;
 | 
				
			||||||
extern StructRNA RNA_MeshFloatProperty;
 | 
					extern StructRNA RNA_MeshFloatProperty;
 | 
				
			||||||
extern StructRNA RNA_MeshFloatPropertyLayer;
 | 
					extern StructRNA RNA_MeshFloatPropertyLayer;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -490,7 +490,7 @@ int rna_parameter_size(struct PropertyRNA *parm);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
struct Mesh *rna_Main_meshes_new_from_object(
 | 
					struct Mesh *rna_Main_meshes_new_from_object(
 | 
				
			||||||
        struct Main *bmain, struct ReportList *reports, struct Depsgraph *depsgraph,
 | 
					        struct Main *bmain, struct ReportList *reports, struct Depsgraph *depsgraph,
 | 
				
			||||||
        struct Object *ob, bool apply_modifiers, bool calc_tessface, bool calc_undeformed);
 | 
					        struct Object *ob, bool apply_modifiers, bool calc_loop_triangles, bool calc_undeformed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* XXX, these should not need to be defined here~! */
 | 
					/* XXX, these should not need to be defined here~! */
 | 
				
			||||||
struct MTex *rna_mtex_texture_slots_add(struct ID *self, struct bContext *C, struct ReportList *reports);
 | 
					struct MTex *rna_mtex_texture_slots_add(struct ID *self, struct bContext *C, struct ReportList *reports);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -310,7 +310,7 @@ static Mesh *rna_Main_meshes_new(Main *bmain, const char *name)
 | 
				
			|||||||
/* copied from Mesh_getFromObject and adapted to RNA interface */
 | 
					/* copied from Mesh_getFromObject and adapted to RNA interface */
 | 
				
			||||||
Mesh *rna_Main_meshes_new_from_object(
 | 
					Mesh *rna_Main_meshes_new_from_object(
 | 
				
			||||||
        Main *bmain, ReportList *reports, Depsgraph *depsgraph,
 | 
					        Main *bmain, ReportList *reports, Depsgraph *depsgraph,
 | 
				
			||||||
        Object *ob, bool apply_modifiers, bool calc_tessface, bool calc_undeformed)
 | 
					        Object *ob, bool apply_modifiers, bool calc_loop_triangles, bool calc_undeformed)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	Scene *sce = DEG_get_evaluated_scene(depsgraph);
 | 
						Scene *sce = DEG_get_evaluated_scene(depsgraph);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -326,7 +326,7 @@ Mesh *rna_Main_meshes_new_from_object(
 | 
				
			|||||||
			return NULL;
 | 
								return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return BKE_mesh_new_from_object(depsgraph, bmain, sce, ob, apply_modifiers, calc_tessface, calc_undeformed);
 | 
						return BKE_mesh_new_from_object(depsgraph, bmain, sce, ob, apply_modifiers, calc_loop_triangles, calc_undeformed);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static Lamp *rna_Main_lights_new(Main *bmain, const char *name, int type)
 | 
					static Lamp *rna_Main_lights_new(Main *bmain, const char *name, int type)
 | 
				
			||||||
@@ -893,7 +893,7 @@ void RNA_def_main_meshes(BlenderRNA *brna, PropertyRNA *cprop)
 | 
				
			|||||||
	RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
 | 
						RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
 | 
				
			||||||
	parm = RNA_def_boolean(func, "apply_modifiers", 0, "", "Apply modifiers");
 | 
						parm = RNA_def_boolean(func, "apply_modifiers", 0, "", "Apply modifiers");
 | 
				
			||||||
	RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
 | 
						RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
 | 
				
			||||||
	RNA_def_boolean(func, "calc_tessface", true, "Calculate Tessellation", "Calculate tessellation faces");
 | 
						RNA_def_boolean(func, "calc_loop_triangles", true, "Calculate Triangles", "Calculate tesselated triangles");
 | 
				
			||||||
	RNA_def_boolean(func, "calc_undeformed", false, "Calculate Undeformed", "Calculate undeformed vertex coordinates");
 | 
						RNA_def_boolean(func, "calc_undeformed", false, "Calculate Undeformed", "Calculate undeformed vertex coordinates");
 | 
				
			||||||
	parm = RNA_def_pointer(func, "mesh", "Mesh", "",
 | 
						parm = RNA_def_pointer(func, "mesh", "Mesh", "",
 | 
				
			||||||
	                       "Mesh created from object, remove it if it is only used for export");
 | 
						                       "Mesh created from object, remove it if it is only used for export");
 | 
				
			||||||
 
 | 
				
			|||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -50,6 +50,7 @@
 | 
				
			|||||||
#include "BKE_mesh.h"
 | 
					#include "BKE_mesh.h"
 | 
				
			||||||
#include "BKE_mesh_tangent.h"
 | 
					#include "BKE_mesh_tangent.h"
 | 
				
			||||||
#include "BKE_mesh_mapping.h"
 | 
					#include "BKE_mesh_mapping.h"
 | 
				
			||||||
 | 
					#include "BKE_mesh_runtime.h"
 | 
				
			||||||
#include "ED_mesh.h"
 | 
					#include "ED_mesh.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char *rna_Mesh_unit_test_compare(struct Mesh *mesh, struct Mesh *mesh2)
 | 
					static const char *rna_Mesh_unit_test_compare(struct Mesh *mesh, struct Mesh *mesh2)
 | 
				
			||||||
@@ -101,9 +102,9 @@ static void rna_Mesh_free_tangents(Mesh *mesh)
 | 
				
			|||||||
	CustomData_free_layers(&mesh->ldata, CD_MLOOPTANGENT, mesh->totloop);
 | 
						CustomData_free_layers(&mesh->ldata, CD_MLOOPTANGENT, mesh->totloop);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void rna_Mesh_calc_tessface(Mesh *mesh, bool free_mpoly)
 | 
					static void rna_Mesh_calc_looptri(Mesh *mesh)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	ED_mesh_calc_tessface(mesh, free_mpoly != 0);
 | 
						BKE_mesh_runtime_looptri_ensure(mesh);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void rna_Mesh_calc_smooth_groups(Mesh *mesh, bool use_bitflags, int *r_poly_group_len,
 | 
					static void rna_Mesh_calc_smooth_groups(Mesh *mesh, bool use_bitflags, int *r_poly_group_len,
 | 
				
			||||||
@@ -206,6 +207,7 @@ static void rna_Mesh_flip_normals(Mesh *mesh)
 | 
				
			|||||||
	BKE_mesh_polygons_flip(mesh->mpoly, mesh->mloop, &mesh->ldata, mesh->totpoly);
 | 
						BKE_mesh_polygons_flip(mesh->mpoly, mesh->mloop, &mesh->ldata, mesh->totpoly);
 | 
				
			||||||
	BKE_mesh_tessface_clear(mesh);
 | 
						BKE_mesh_tessface_clear(mesh);
 | 
				
			||||||
	BKE_mesh_calc_normals(mesh);
 | 
						BKE_mesh_calc_normals(mesh);
 | 
				
			||||||
 | 
						BKE_mesh_runtime_clear_geometry(mesh);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	DEG_id_tag_update(&mesh->id, 0);
 | 
						DEG_id_tag_update(&mesh->id, 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -269,12 +271,8 @@ void RNA_api_mesh(StructRNA *srna)
 | 
				
			|||||||
	func = RNA_def_function(srna, "free_tangents", "rna_Mesh_free_tangents");
 | 
						func = RNA_def_function(srna, "free_tangents", "rna_Mesh_free_tangents");
 | 
				
			||||||
	RNA_def_function_ui_description(func, "Free tangents");
 | 
						RNA_def_function_ui_description(func, "Free tangents");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	func = RNA_def_function(srna, "calc_tessface", "rna_Mesh_calc_tessface");
 | 
						func = RNA_def_function(srna, "calc_loop_triangles", "rna_Mesh_calc_looptri");
 | 
				
			||||||
	RNA_def_function_ui_description(func, "Calculate face tessellation (supports editmode too)");
 | 
						RNA_def_function_ui_description(func, "Calculate loop triangle tessellation (supports editmode too)");
 | 
				
			||||||
	RNA_def_boolean(func, "free_mpoly", 0, "Free MPoly", "Free data used by polygons and loops. "
 | 
					 | 
				
			||||||
	                "WARNING: This destructive operation removes regular faces, "
 | 
					 | 
				
			||||||
	                "only used on temporary mesh data-blocks to reduce memory footprint of render "
 | 
					 | 
				
			||||||
	                "engines and export scripts");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	func = RNA_def_function(srna, "calc_smooth_groups", "rna_Mesh_calc_smooth_groups");
 | 
						func = RNA_def_function(srna, "calc_smooth_groups", "rna_Mesh_calc_smooth_groups");
 | 
				
			||||||
	RNA_def_function_ui_description(func, "Calculate smooth groups from sharp edges");
 | 
						RNA_def_function_ui_description(func, "Calculate smooth groups from sharp edges");
 | 
				
			||||||
@@ -308,7 +306,7 @@ void RNA_api_mesh(StructRNA *srna)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	func = RNA_def_function(srna, "update", "ED_mesh_update");
 | 
						func = RNA_def_function(srna, "update", "ED_mesh_update");
 | 
				
			||||||
	RNA_def_boolean(func, "calc_edges", 0, "Calculate Edges", "Force recalculation of edges");
 | 
						RNA_def_boolean(func, "calc_edges", 0, "Calculate Edges", "Force recalculation of edges");
 | 
				
			||||||
	RNA_def_boolean(func, "calc_tessface", 0, "Calculate Tessellation", "Force recalculation of tessellation faces");
 | 
						RNA_def_boolean(func, "calc_loop_triangles", 0, "Calculate Triangules", "Force recalculation of triangle tessellation");
 | 
				
			||||||
	RNA_def_function_flag(func, FUNC_USE_CONTEXT);
 | 
						RNA_def_function_flag(func, FUNC_USE_CONTEXT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	RNA_def_function(srna, "update_gpu_tag", "rna_Mesh_update_gpu_tag");
 | 
						RNA_def_function(srna, "update_gpu_tag", "rna_Mesh_update_gpu_tag");
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -224,11 +224,11 @@ static void rna_Object_camera_fit_coords(
 | 
				
			|||||||
/* settings: 0 - preview, 1 - render */
 | 
					/* settings: 0 - preview, 1 - render */
 | 
				
			||||||
static Mesh *rna_Object_to_mesh(
 | 
					static Mesh *rna_Object_to_mesh(
 | 
				
			||||||
        Object *ob, bContext *C, ReportList *reports, Depsgraph *depsgraph,
 | 
					        Object *ob, bContext *C, ReportList *reports, Depsgraph *depsgraph,
 | 
				
			||||||
        bool apply_modifiers, bool calc_tessface, bool calc_undeformed)
 | 
					        bool apply_modifiers, bool calc_loop_triangles, bool calc_undeformed)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	Main *bmain = CTX_data_main(C);
 | 
						Main *bmain = CTX_data_main(C);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return rna_Main_meshes_new_from_object(bmain, reports, depsgraph, ob, apply_modifiers, calc_tessface, calc_undeformed);
 | 
						return rna_Main_meshes_new_from_object(bmain, reports, depsgraph, ob, apply_modifiers, calc_loop_triangles, calc_undeformed);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static PointerRNA rna_Object_shape_key_add(Object *ob, bContext *C, ReportList *reports,
 | 
					static PointerRNA rna_Object_shape_key_add(Object *ob, bContext *C, ReportList *reports,
 | 
				
			||||||
@@ -594,7 +594,7 @@ void RNA_api_object(StructRNA *srna)
 | 
				
			|||||||
	RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
 | 
						RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
 | 
				
			||||||
	parm = RNA_def_boolean(func, "apply_modifiers", 0, "", "Apply modifiers");
 | 
						parm = RNA_def_boolean(func, "apply_modifiers", 0, "", "Apply modifiers");
 | 
				
			||||||
	RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
 | 
						RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
 | 
				
			||||||
	RNA_def_boolean(func, "calc_tessface", true, "Calculate Tessellation", "Calculate tessellation faces");
 | 
						RNA_def_boolean(func, "calc_loop_triangles", true, "Calculate Loop Triangles", "Calculate triangle tessellation");
 | 
				
			||||||
	RNA_def_boolean(func, "calc_undeformed", false, "Calculate Undeformed", "Calculate undeformed vertex coordinates");
 | 
						RNA_def_boolean(func, "calc_undeformed", false, "Calculate Undeformed", "Calculate undeformed vertex coordinates");
 | 
				
			||||||
	parm = RNA_def_pointer(func, "mesh", "Mesh", "",
 | 
						parm = RNA_def_pointer(func, "mesh", "Mesh", "",
 | 
				
			||||||
	                       "Mesh created from object, remove it if it is only used for export");
 | 
						                       "Mesh created from object, remove it if it is only used for export");
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -113,30 +113,30 @@ static PyObject *bpy_bm_from_edit_mesh(PyObject *UNUSED(self), PyObject *value)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PyDoc_STRVAR(bpy_bm_update_edit_mesh_doc,
 | 
					PyDoc_STRVAR(bpy_bm_update_edit_mesh_doc,
 | 
				
			||||||
".. method:: update_edit_mesh(mesh, tessface=True, destructive=True)\n"
 | 
					".. method:: update_edit_mesh(mesh, loop_triangles=True, destructive=True)\n"
 | 
				
			||||||
"\n"
 | 
					"\n"
 | 
				
			||||||
"   Update the mesh after changes to the BMesh in editmode, \n"
 | 
					"   Update the mesh after changes to the BMesh in editmode, \n"
 | 
				
			||||||
"   optionally recalculating n-gon tessellation.\n"
 | 
					"   optionally recalculating n-gon tessellation.\n"
 | 
				
			||||||
"\n"
 | 
					"\n"
 | 
				
			||||||
"   :arg mesh: The editmode mesh.\n"
 | 
					"   :arg mesh: The editmode mesh.\n"
 | 
				
			||||||
"   :type mesh: :class:`bpy.types.Mesh`\n"
 | 
					"   :type mesh: :class:`bpy.types.Mesh`\n"
 | 
				
			||||||
"   :arg tessface: Option to recalculate n-gon tessellation.\n"
 | 
					"   :arg loop_triangles: Option to recalculate n-gon tessellation.\n"
 | 
				
			||||||
"   :type tessface: boolean\n"
 | 
					"   :type loop_triangles: boolean\n"
 | 
				
			||||||
"   :arg destructive: Use when geometry has been added or removed.\n"
 | 
					"   :arg destructive: Use when geometry has been added or removed.\n"
 | 
				
			||||||
"   :type destructive: boolean\n"
 | 
					"   :type destructive: boolean\n"
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
static PyObject *bpy_bm_update_edit_mesh(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
 | 
					static PyObject *bpy_bm_update_edit_mesh(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	static const char *kwlist[] = {"mesh", "tessface", "destructive", NULL};
 | 
						static const char *kwlist[] = {"mesh", "loop_triangles", "destructive", NULL};
 | 
				
			||||||
	PyObject *py_me;
 | 
						PyObject *py_me;
 | 
				
			||||||
	Mesh *me;
 | 
						Mesh *me;
 | 
				
			||||||
	bool do_tessface = true;
 | 
						bool do_loop_triangles = true;
 | 
				
			||||||
	bool is_destructive = true;
 | 
						bool is_destructive = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!PyArg_ParseTupleAndKeywords(
 | 
						if (!PyArg_ParseTupleAndKeywords(
 | 
				
			||||||
	        args, kw, "O|O&O&:update_edit_mesh", (char **)kwlist,
 | 
						        args, kw, "O|O&O&:update_edit_mesh", (char **)kwlist,
 | 
				
			||||||
	        &py_me,
 | 
						        &py_me,
 | 
				
			||||||
	        PyC_ParseBool, &do_tessface,
 | 
						        PyC_ParseBool, &do_loop_triangles,
 | 
				
			||||||
	        PyC_ParseBool, &is_destructive))
 | 
						        PyC_ParseBool, &is_destructive))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
@@ -157,7 +157,7 @@ static PyObject *bpy_bm_update_edit_mesh(PyObject *UNUSED(self), PyObject *args,
 | 
				
			|||||||
	{
 | 
						{
 | 
				
			||||||
		extern void EDBM_update_generic(BMEditMesh *em, const bool do_tessface, const bool is_destructive);
 | 
							extern void EDBM_update_generic(BMEditMesh *em, const bool do_tessface, const bool is_destructive);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		EDBM_update_generic(me->edit_btmesh, do_tessface, is_destructive);
 | 
							EDBM_update_generic(me->edit_btmesh, do_loop_triangles, is_destructive);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Py_RETURN_NONE;
 | 
						Py_RETURN_NONE;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1246,15 +1246,15 @@ static PyObject *bpy_bmesh_calc_volume(BPy_BMElem *self, PyObject *args, PyObjec
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PyDoc_STRVAR(bpy_bmesh_calc_tessface_doc,
 | 
					PyDoc_STRVAR(bpy_bmesh_calc_loop_triangles_doc,
 | 
				
			||||||
".. method:: calc_tessface()\n"
 | 
					".. method:: calc_loop_triangles()\n"
 | 
				
			||||||
"\n"
 | 
					"\n"
 | 
				
			||||||
"   Calculate triangle tessellation from quads/ngons.\n"
 | 
					"   Calculate triangle tessellation from quads/ngons.\n"
 | 
				
			||||||
"\n"
 | 
					"\n"
 | 
				
			||||||
"   :return: The triangulated faces.\n"
 | 
					"   :return: The triangulated faces.\n"
 | 
				
			||||||
"   :rtype: list of :class:`BMLoop` tuples\n"
 | 
					"   :rtype: list of :class:`BMLoop` tuples\n"
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
static PyObject *bpy_bmesh_calc_tessface(BPy_BMElem *self)
 | 
					static PyObject *bpy_bmesh_calc_loop_triangles(BPy_BMElem *self)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	BMesh *bm;
 | 
						BMesh *bm;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2733,7 +2733,7 @@ static struct PyMethodDef bpy_bmesh_methods[] = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	/* calculations */
 | 
						/* calculations */
 | 
				
			||||||
	{"calc_volume", (PyCFunction)bpy_bmesh_calc_volume, METH_VARARGS | METH_KEYWORDS, bpy_bmesh_calc_volume_doc},
 | 
						{"calc_volume", (PyCFunction)bpy_bmesh_calc_volume, METH_VARARGS | METH_KEYWORDS, bpy_bmesh_calc_volume_doc},
 | 
				
			||||||
	{"calc_tessface", (PyCFunction)bpy_bmesh_calc_tessface, METH_NOARGS, bpy_bmesh_calc_tessface_doc},
 | 
						{"calc_loop_triangles", (PyCFunction)bpy_bmesh_calc_loop_triangles, METH_NOARGS, bpy_bmesh_calc_loop_triangles_doc},
 | 
				
			||||||
	{NULL, NULL, 0, NULL}
 | 
						{NULL, NULL, 0, NULL}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -86,9 +86,6 @@
 | 
				
			|||||||
#include "render_types.h"
 | 
					#include "render_types.h"
 | 
				
			||||||
#include "zbuf.h"
 | 
					#include "zbuf.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Remove when Cycles moves from MFace to MLoopTri */
 | 
					 | 
				
			||||||
#define USE_MFACE_WORKAROUND
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef struct BakeDataZSpan {
 | 
					typedef struct BakeDataZSpan {
 | 
				
			||||||
	BakePixel *pixel_array;
 | 
						BakePixel *pixel_array;
 | 
				
			||||||
	int primitive_id;
 | 
						int primitive_id;
 | 
				
			||||||
@@ -393,27 +390,6 @@ static bool cast_ray_highpoly(
 | 
				
			|||||||
	return hit_mesh != -1;
 | 
						return hit_mesh != -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef USE_MFACE_WORKAROUND
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Until cycles moves to #MLoopTri, we need to keep face-rotation in sync with #test_index_face
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * We only need to consider quads since #BKE_mesh_recalc_tessellation doesn't execute this on triangles.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static void test_index_face_looptri(const MPoly *mp, MLoop *mloop, MLoopTri *lt)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (mp->totloop == 4) {
 | 
					 | 
				
			||||||
		if (UNLIKELY((mloop[mp->loopstart + 2].v == 0) ||
 | 
					 | 
				
			||||||
		             (mloop[mp->loopstart + 3].v == 0)))
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			/* remap: (2, 3, 0, 1) */
 | 
					 | 
				
			||||||
			unsigned int l = mp->loopstart;
 | 
					 | 
				
			||||||
			ARRAY_SET_ITEMS(lt[0].tri, l + 2, l + 3, l + 0);
 | 
					 | 
				
			||||||
			ARRAY_SET_ITEMS(lt[1].tri, l + 2, l + 0, l + 1);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * This function populates an array of verts for the triangles of a mesh
 | 
					 * This function populates an array of verts for the triangles of a mesh
 | 
				
			||||||
 * Tangent and Normals are also stored
 | 
					 * Tangent and Normals are also stored
 | 
				
			||||||
@@ -433,10 +409,6 @@ static TriTessFace *mesh_calc_tri_tessface(
 | 
				
			|||||||
	unsigned int mpoly_prev = UINT_MAX;
 | 
						unsigned int mpoly_prev = UINT_MAX;
 | 
				
			||||||
	float no[3];
 | 
						float no[3];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef USE_MFACE_WORKAROUND
 | 
					 | 
				
			||||||
	unsigned int mpoly_prev_testindex = UINT_MAX;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	mvert = CustomData_get_layer(&me->vdata, CD_MVERT);
 | 
						mvert = CustomData_get_layer(&me->vdata, CD_MVERT);
 | 
				
			||||||
	looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__);
 | 
						looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__);
 | 
				
			||||||
	triangles = MEM_mallocN(sizeof(TriTessFace) * tottri, __func__);
 | 
						triangles = MEM_mallocN(sizeof(TriTessFace) * tottri, __func__);
 | 
				
			||||||
@@ -463,13 +435,6 @@ static TriTessFace *mesh_calc_tri_tessface(
 | 
				
			|||||||
		const MLoopTri *lt = &looptri[i];
 | 
							const MLoopTri *lt = &looptri[i];
 | 
				
			||||||
		const MPoly *mp = &me->mpoly[lt->poly];
 | 
							const MPoly *mp = &me->mpoly[lt->poly];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef USE_MFACE_WORKAROUND
 | 
					 | 
				
			||||||
		if (lt->poly != mpoly_prev_testindex) {
 | 
					 | 
				
			||||||
			test_index_face_looptri(mp, me->mloop, &looptri[i]);
 | 
					 | 
				
			||||||
			mpoly_prev_testindex = lt->poly;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		triangles[i].mverts[0] = &mvert[me->mloop[lt->tri[0]].v];
 | 
							triangles[i].mverts[0] = &mvert[me->mloop[lt->tri[0]].v];
 | 
				
			||||||
		triangles[i].mverts[1] = &mvert[me->mloop[lt->tri[1]].v];
 | 
							triangles[i].mverts[1] = &mvert[me->mloop[lt->tri[1]].v];
 | 
				
			||||||
		triangles[i].mverts[2] = &mvert[me->mloop[lt->tri[2]].v];
 | 
							triangles[i].mverts[2] = &mvert[me->mloop[lt->tri[2]].v];
 | 
				
			||||||
@@ -662,9 +627,6 @@ void RE_bake_pixels_populate(
 | 
				
			|||||||
	const MLoopUV *mloopuv;
 | 
						const MLoopUV *mloopuv;
 | 
				
			||||||
	const int tottri = poly_to_tri_count(me->totpoly, me->totloop);
 | 
						const int tottri = poly_to_tri_count(me->totpoly, me->totloop);
 | 
				
			||||||
	MLoopTri *looptri;
 | 
						MLoopTri *looptri;
 | 
				
			||||||
#ifdef USE_MFACE_WORKAROUND
 | 
					 | 
				
			||||||
	unsigned int mpoly_prev_testindex = UINT_MAX;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((uv_layer == NULL) || (uv_layer[0] == '\0')) {
 | 
						if ((uv_layer == NULL) || (uv_layer[0] == '\0')) {
 | 
				
			||||||
		mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV);
 | 
							mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV);
 | 
				
			||||||
@@ -714,13 +676,6 @@ void RE_bake_pixels_populate(
 | 
				
			|||||||
		bd.bk_image = &bake_images->data[image_id];
 | 
							bd.bk_image = &bake_images->data[image_id];
 | 
				
			||||||
		bd.primitive_id = ++p_id;
 | 
							bd.primitive_id = ++p_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef USE_MFACE_WORKAROUND
 | 
					 | 
				
			||||||
		if (lt->poly != mpoly_prev_testindex) {
 | 
					 | 
				
			||||||
			test_index_face_looptri(mp, me->mloop, &looptri[i]);
 | 
					 | 
				
			||||||
			mpoly_prev_testindex = lt->poly;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		for (a = 0; a < 3; a++) {
 | 
							for (a = 0; a < 3; a++) {
 | 
				
			||||||
			const float *uv = mloopuv[lt->tri[a]].uv;
 | 
								const float *uv = mloopuv[lt->tri[a]].uv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user