1. Dean Giberson
  2. blender

Commits

Dean Giberson  committed 73cc744 Merge

Merge branch 'master' into animblend

  • Participants
  • Parent commits 162eb53, 56b22f9
  • Branches animblend

Comments (0)

Files changed (76)

File blender/CMakeLists.txt

View file
  • Ignore whitespace
 
 
 if(APPLE)
+	cmake_minimum_required(VERSION 2.8.8)
+	cmake_policy(VERSION 2.8.8)
+
 	if(NOT CMAKE_OSX_ARCHITECTURES)
 		set(CMAKE_OSX_ARCHITECTURES x86_64 CACHE STRING
 		"Choose the architecture you want to build Blender for: i386, x86_64 or ppc"

File blender/build_files/build_environment/install_deps.sh

View file
  • Ignore whitespace
 
 prepare_opt() {
   INFO "Ensuring $INST exists and is writable by us"
-  sudo mkdir -p $INST
-  sudo chown $USER $INST
-  sudo chmod 775 $INST
+  if [ ! -d  $INST ]; then
+    sudo mkdir -p $INST
+  fi
+
+  if [ ! -w $INST ]; then
+    sudo chown $USER $INST
+    sudo chmod 775 $INST
+  fi
 }
 
 # Check whether the current package needs to be recompiled, based on a dummy file containing a magic number in its name...
     prepare_opt
 
     if [ ! -d $_src ]; then
+      mkdir -p $SRC
       wget -c $OIIO_SOURCE -O "$_src.tar.gz"
 
       INFO "Unpacking OpenImageIO-$OIIO_VERSION"
     cmake_d="$cmake_d -D CMAKE_PREFIX_PATH=$_inst"
     cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst"
     cmake_d="$cmake_d -D BUILDSTATIC=ON"
-    cmake_d="$cmake_d -D LINKSTATIC=ON"
+
+    # linking statically could give issues on Debian/Ubuntu (and probably other distros
+    # which doesn't like static linking) when linking shared oiio library due to missing
+    # text symbols (static libs should be compiled with -fPIC)
+    # cmake_d="$cmake_d -D LINKSTATIC=ON"
 
     if [ -d $INST/boost ]; then
       cmake_d="$cmake_d -D BOOST_ROOT=$INST/boost -D Boost_NO_SYSTEM_PATHS=ON"
       if $ALL_STATIC; then
-        cmake_d="$cmake_d -D Boost_USE_STATIC_LIBS=ON"        
+        cmake_d="$cmake_d -D Boost_USE_STATIC_LIBS=ON"
       fi
     fi
 
     prepare_opt
 
     if [ ! -d $_src -o true ]; then
+      mkdir -p $SRC
       wget -c $LLVM_SOURCE -O "$_src.tar.gz"
       wget -c $LLVM_CLANG_SOURCE -O "$_src_clang.tar.gz"
 
     prepare_opt
 
     if [ ! -d $_src ]; then
+      mkdir -p $SRC
+
       # XXX Using git on my own repo for now, looks like archives are not updated immediately... :/
 #      wget -c $OSL_SOURCE -O "$_src.tar.gz"
 
 
     if [ ! -d $_src ]; then
       INFO "Downloading ffmpeg-$FFMPEG_VERSION"
+      mkdir -p $SRC
       wget -c $FFMPEG_SOURCE -O "$_src.tar.bz2"
 
       INFO "Unpacking ffmpeg-$FFMPEG_VERSION"
   INFO "$COMMON_INFO"
   INFO ""
 
+  if [ ! -z "`cat /etc/debian_version | grep ^6`"  ]; then
+    if [ -z "`cat /etc/apt/sources.list | grep backports.debian.org`"  ]; then
+      INFO "Looks like you're using Debian Squeeze which does have broken CMake"
+      INFO "It is highly recommended to install cmake from backports, otherwise"
+      INFO "compilation of some libraries could fail"
+      INFO ""
+      INFO "You could install newer CMake from debian-backports repository"
+      INFO "Add this this line to your /etc/apt/sources.lixt:"
+      INFO ""
+      INFO "deb http://backports.debian.org/debian-backports squeeze-backports main"
+      INFO ""
+      INFO "and then run:"
+      INFO ""
+      INFO "sudo apt-get update && sudo apt-get install cmake=2.8.7-4~bpo60+1 sudo apt-get install cmake=2.8.7-4~bpo60+1"
+      INFO ""
+      INFO "(you could also add this reporisotry using GUI like synaptic)"
+      INFO ""
+      INFO "Hit Enter to continue running the script, or hit Ctrl-C to abort the script"
+
+      read
+    fi
+  fi
+
   sudo apt-get update
 # XXX Why in hell? Let's let this stuff to the user's responsability!!!
 #  sudo apt-get -y upgrade
     libfreetype6-dev libx11-dev libxi-dev wget libsqlite3-dev libbz2-dev libncurses5-dev \
     libssl-dev liblzma-dev libreadline-dev $OPENJPEG_DEV libopenexr-dev libopenal-dev \
     libglew-dev yasm $SCHRO_DEV $THEORA_DEV $VORBIS_DEV libsdl1.2-dev \
-    libfftw3-dev libjack-dev python-dev patch
+    libfftw3-dev libjack-dev python-dev patch bzip2
 
   OPENJPEG_USE=true
   SCHRO_USE=true

File blender/build_files/buildbot/config/user-config-glibc211-i686.py

View file
  • Ignore whitespace
 
 # Compilation and optimization
 BF_DEBUG = False
-REL_CCFLAGS = ['-O2', '-msse', '-msse2']  # C & C++
+REL_CCFLAGS = ['-DNDEBUG', '-O2', '-msse', '-msse2']  # C & C++
 PLATFORM_LINKFLAGS = ['-lrt']
 BF_PROGRAM_LINKFLAGS = ['-Wl,--whole-archive', '-loslexec', '-Wl,--no-whole-archive', '-Wl,--version-script=source/creator/blender.map']

File blender/build_files/buildbot/config/user-config-glibc211-x86_64.py

View file
  • Ignore whitespace
 
 # Compilation and optimization
 BF_DEBUG = False
-REL_CCFLAGS = ['-O2', '-msse', '-msse2']  # C & C++
+REL_CCFLAGS = ['-DNDEBUG', '-O2', '-msse', '-msse2']  # C & C++
 PLATFORM_LINKFLAGS = ['-lrt']
 BF_PROGRAM_LINKFLAGS = ['-Wl,--whole-archive', '-loslexec', '-Wl,--no-whole-archive', '-Wl,--version-script=source/creator/blender.map']

File blender/build_files/buildbot/config/user-config-glibc27-i686.py

View file
  • Ignore whitespace
 
 # Compilation and optimization
 BF_DEBUG = False
-REL_CCFLAGS = ['-O2']  # C & C++
+REL_CCFLAGS = ['-DNDEBUG', '-DNDEBUG', '-O2']  # C & C++
 PLATFORM_LINKFLAGS = ['-L/home/sources/staticlibs/lib32']
 BF_PROGRAM_LINKFLAGS = ['-Wl,--whole-archive', '-loslexec', '-Wl,--no-whole-archive', '-Wl,--version-script=source/creator/blender.map']

File blender/build_files/buildbot/config/user-config-glibc27-x86_64.py

View file
  • Ignore whitespace
 
 # Compilation and optimization
 BF_DEBUG = False
-REL_CCFLAGS = ['-O2', '-msse', '-msse2']  # C & C++
+REL_CCFLAGS = ['-DNDEBUG', '-O2', '-msse', '-msse2']  # C & C++
 PLATFORM_LINKFLAGS = ['-L/home/sources/staticlibs/lib64']
 BF_PROGRAM_LINKFLAGS = ['-Wl,--whole-archive', '-loslexec', '-Wl,--no-whole-archive', '-Wl,--version-script=source/creator/blender.map']

File blender/build_files/buildbot/config/user-config-player-glibc211-i686.py

View file
  • Ignore whitespace
 
 # Compilation and optimization
 BF_DEBUG = False
-REL_CCFLAGS = ['-O2', '-msse', '-msse2']  # C & C++
+REL_CCFLAGS = ['-DNDEBUG', '-O2', '-msse', '-msse2']  # C & C++
 PLATFORM_LINKFLAGS = ['-lrt']

File blender/build_files/buildbot/config/user-config-player-glibc211-x86_64.py

View file
  • Ignore whitespace
 
 # Compilation and optimization
 BF_DEBUG = False
-REL_CCFLAGS = ['-O2', '-msse', '-msse2']  # C & C++
+REL_CCFLAGS = ['-DNDEBUG', '-O2', '-msse', '-msse2']  # C & C++
 PLATFORM_LINKFLAGS = ['-lrt']

File blender/build_files/buildbot/config/user-config-player-glibc27-i686.py

View file
  • Ignore whitespace
 
 # Compilation and optimization
 BF_DEBUG = False
-REL_CCFLAGS = ['-O2']  # C & C++
+REL_CCFLAGS = ['-DNDEBUG', '-O2']  # C & C++
 PLATFORM_LINKFLAGS = ['-L/home/sources/staticlibs/lib32']

File blender/build_files/buildbot/config/user-config-player-glibc27-x86_64.py

View file
  • Ignore whitespace
 
 # Compilation and optimization
 BF_DEBUG = False
-REL_CCFLAGS = ['-O2', '-msse', '-msse2']  # C & C++
+REL_CCFLAGS = ['-DNDEBUG', '-O2', '-msse', '-msse2']  # C & C++
 PLATFORM_LINKFLAGS = ['-L/home/sources/staticlibs/lib64']

File blender/doc/python_api/examples/bmesh.ops.1.py

View file
  • Ignore whitespace
+# This script uses bmesh operators to make 2 links of a chain.
+
+import bpy
+import bmesh
+import math
+import mathutils
+
+# Make a new BMesh
+bm = bmesh.new()
+
+# Add a circle XXX, should return all geometry created, not just verts.
+bmesh.ops.create_circle(
+        bm,
+        cap_ends=False,
+        diameter=0.2,
+        segments=8)
+
+
+# Spin and deal with geometry on side 'a'
+edges_start_a = bm.edges[:]
+geom_start_a = bm.verts[:] + edges_start_a
+ret = bmesh.ops.spin(
+        bm,
+        geom=geom_start_a,
+        angle=math.radians(180.0),
+        steps=8,
+        axis=(1.0, 0.0, 0.0),
+        cent=(0.0, 1.0, 0.0))
+edges_end_a = [ele for ele in ret["geom_last"]
+               if isinstance(ele, bmesh.types.BMEdge)]
+del ret
+
+
+# Extrude and create geometry on side 'b'
+ret = bmesh.ops.extrude_edge_only(
+        bm,
+        edges=edges_start_a)
+geom_extrude_mid = ret["geom"]
+del ret
+
+
+# Collect the edges to spin XXX, 'extrude_edge_only' could return this.
+verts_extrude_b = [ele for ele in geom_extrude_mid
+                   if isinstance(ele, bmesh.types.BMVert)]
+edges_extrude_b = [ele for ele in geom_extrude_mid
+                   if isinstance(ele, bmesh.types.BMEdge) and ele.is_boundary]
+bmesh.ops.translate(
+        bm,
+        verts=verts_extrude_b,
+        vec=(0.0, 0.0, 1.0))
+
+
+# Create the circle on side 'b'
+ret = bmesh.ops.spin(
+        bm,
+        geom=verts_extrude_b + edges_extrude_b,
+        angle=-math.radians(180.0),
+        steps=8,
+        axis=(1.0, 0.0, 0.0),
+        cent=(0.0, 1.0, 1.0))
+edges_end_b = [ele for ele in ret["geom_last"]
+               if isinstance(ele, bmesh.types.BMEdge)]
+del ret
+
+
+# Bridge the resulting edge loops of both spins 'a & b'
+bmesh.ops.bridge_loops(
+        bm,
+        edges=edges_end_a + edges_end_b)
+
+
+# Now we have made a links of the chain, make a copy and rotate it
+# (so this looks something like a chain)
+
+ret = bmesh.ops.duplicate(
+        bm,
+        geom=bm.verts[:] + bm.edges[:] + bm.faces[:])
+geom_dupe = ret["geom"]
+verts_dupe = [ele for ele in geom_dupe if isinstance(ele, bmesh.types.BMVert)]
+del ret
+
+# position the new link
+bmesh.ops.translate(
+        bm,
+        verts=verts_dupe,
+        vec=(0.0, 0.0, 2.0))
+bmesh.ops.rotate(
+        bm,
+        verts=verts_dupe,
+        cent=(0.0, 1.0, 0.0),
+        matrix=mathutils.Matrix.Rotation(math.radians(90.0), 3, 'Z'))
+
+# Done with creating the mesh, simply link it into the scene so we can see it
+
+# Finish up, write the bmesh into a new mesh
+me = bpy.data.meshes.new("Mesh")
+bm.to_mesh(me)
+
+# Add the mesh to the scene
+scene = bpy.context.scene
+obj = bpy.data.objects.new("Object", me)
+scene.objects.link(obj)
+
+# Select and make active
+scene.objects.active = obj
+obj.select = True

File blender/doc/python_api/rst/bge.types.rst

View file
  • Ignore whitespace
 
          The id is derived from a memory location and will be different each time the game engine starts.
 
+      .. warning::
+
+         The id can't be stored as an integer in game object properties, as those only have a limited range that the id may not be contained in. Instead an id can be stored as a string game property and converted back to an integer for use in from_id lookups.
+
 .. class:: KX_BlenderMaterial(PyObjectPlus)
 
    KX_BlenderMaterial

File blender/doc/python_api/rst_from_bmesh_opdefines.py

View file
  • Ignore whitespace
    This API us new in 2.65 and not yet well tested.
 
 
+Operator Example
+++++++++++++++++
+This script shows how operators can be used to model a link of a chain.
+
+.. literalinclude:: ../examples/bmesh.ops.1.py
 """
 
 

File blender/intern/cycles/CMakeLists.txt

View file
  • Ignore whitespace
 # for OSL
 if(WIN32 AND MSVC)
 	set(RTTI_DISABLE_FLAGS "/GR- -DBOOST_NO_RTTI -DBOOST_NO_TYPEID")
-elseif(CMAKE_COMPILER_IS_GNUCC)
+elseif(CMAKE_COMPILER_IS_GNUCC OR (CMAKE_C_COMPILER_ID MATCHES "Clang"))
 	set(RTTI_DISABLE_FLAGS "-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID")
 endif()
 

File blender/intern/cycles/kernel/closure/bsdf_phong_ramp.h

View file
  • Ignore whitespace
 			}
 		}
 	}
-	return LABEL_REFLECT;
+	return LABEL_REFLECT|LABEL_GLOSSY;
 }
 
 

File blender/intern/cycles/kernel/kernel_camera.h

View file
  • Ignore whitespace
 
 #ifdef __CAMERA_MOTION__
 	if(kernel_data.cam.have_motion)
-		transform_motion_interpolate(&cameratoworld, &kernel_data.cam.motion, ray->time);
+		transform_motion_interpolate(&cameratoworld, (const DecompMotionTransform*)&kernel_data.cam.motion, ray->time);
 #endif
 
 	ray->P = transform_point(&cameratoworld, ray->P);
 
 #ifdef __CAMERA_MOTION__
 	if(kernel_data.cam.have_motion)
-		transform_motion_interpolate(&cameratoworld, &kernel_data.cam.motion, ray->time);
+		transform_motion_interpolate(&cameratoworld, (const DecompMotionTransform*)&kernel_data.cam.motion, ray->time);
 #endif
 
 	ray->P = transform_point(&cameratoworld, ray->P);
 
 #ifdef __CAMERA_MOTION__
 	if(kernel_data.cam.have_motion)
-		transform_motion_interpolate(&cameratoworld, &kernel_data.cam.motion, ray->time);
+		transform_motion_interpolate(&cameratoworld, (const DecompMotionTransform*)&kernel_data.cam.motion, ray->time);
 #endif
 
 	ray->P = transform_point(&cameratoworld, ray->P);

File blender/intern/cycles/kernel/kernel_object.h

View file
  • Ignore whitespace
 	OBJECT_INVERSE_TRANSFORM = 3,
 	OBJECT_PROPERTIES = 6,
 	OBJECT_TRANSFORM_MOTION_PRE = 8,
-	OBJECT_TRANSFORM_MOTION_MID = 12,
-	OBJECT_TRANSFORM_MOTION_POST = 16,
-	OBJECT_DUPLI = 20
+	OBJECT_TRANSFORM_MOTION_POST = 12,
+	OBJECT_DUPLI = 16
 };
 
 __device_inline Transform object_fetch_transform(KernelGlobals *kg, int object, enum ObjectTransform type)
 #ifdef __OBJECT_MOTION__
 __device_inline Transform object_fetch_transform_motion(KernelGlobals *kg, int object, float time)
 {
-	MotionTransform motion;
+	DecompMotionTransform motion;
 
 	int offset = object*OBJECT_SIZE + (int)OBJECT_TRANSFORM_MOTION_PRE;
 
-	motion.pre.x = kernel_tex_fetch(__objects, offset + 0);
-	motion.pre.y = kernel_tex_fetch(__objects, offset + 1);
-	motion.pre.z = kernel_tex_fetch(__objects, offset + 2);
-	motion.pre.w = kernel_tex_fetch(__objects, offset + 3);
+	motion.mid.x = kernel_tex_fetch(__objects, offset + 0);
+	motion.mid.y = kernel_tex_fetch(__objects, offset + 1);
+	motion.mid.z = kernel_tex_fetch(__objects, offset + 2);
+	motion.mid.w = kernel_tex_fetch(__objects, offset + 3);
 
-	motion.mid.x = kernel_tex_fetch(__objects, offset + 4);
-	motion.mid.y = kernel_tex_fetch(__objects, offset + 5);
-	motion.mid.z = kernel_tex_fetch(__objects, offset + 6);
-	motion.mid.w = kernel_tex_fetch(__objects, offset + 7);
-
-	motion.post.x = kernel_tex_fetch(__objects, offset + 8);
-	motion.post.y = kernel_tex_fetch(__objects, offset + 9);
-	motion.post.z = kernel_tex_fetch(__objects, offset + 10);
-	motion.post.w = kernel_tex_fetch(__objects, offset + 11);
+	motion.pre_x = kernel_tex_fetch(__objects, offset + 4);
+	motion.pre_y = kernel_tex_fetch(__objects, offset + 5);
+	motion.post_x = kernel_tex_fetch(__objects, offset + 6);
+	motion.post_y = kernel_tex_fetch(__objects, offset + 7);
 
 	Transform tfm;
 	transform_motion_interpolate(&tfm, &motion, time);

File blender/intern/cycles/kernel/kernel_types.h

View file
  • Ignore whitespace
 CCL_NAMESPACE_BEGIN
 
 /* constants */
-#define OBJECT_SIZE 		22
+#define OBJECT_SIZE 		18
 #define LIGHT_SIZE			4
 #define FILTER_TABLE_SIZE	256
 #define RAMP_TABLE_SIZE		256
 #define __AO__
 #define __CAMERA_MOTION__
 #define __ANISOTROPIC__
-
-#ifndef __KERNEL_CUDA__
 #define __OBJECT_MOTION__
 #endif
 
-#endif
-
 //#define __SOBOL_FULL_SCREEN__
 
 /* Shader Evaluation */

File blender/intern/cycles/kernel/osl/osl_services.cpp

View file
  • Ignore whitespace
 
 		if (object != ~0) {
 #ifdef __OBJECT_MOTION__
-			Transform tfm = object_fetch_transform_motion_test(kg, object, time, NULL);
+			Transform tfm;
+
+			if(time == sd->time)
+				tfm = sd->ob_tfm;
+			else
+				tfm = object_fetch_transform_motion_test(kg, object, time, NULL);
 #else
 			Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
 #endif
 		if (object != ~0) {
 #ifdef __OBJECT_MOTION__
 			Transform itfm;
-			object_fetch_transform_motion_test(kg, object, time, &itfm);
+
+			if(time == sd->time)
+				itfm = sd->ob_itfm;
+			else
+				object_fetch_transform_motion_test(kg, object, time, &itfm);
 #else
 			Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
 #endif

File blender/intern/cycles/kernel/osl/osl_shader.cpp

View file
  • Ignore whitespace
 	globals->dPdu = TO_VEC3(sd->dPdu);
 	globals->dPdv = TO_VEC3(sd->dPdv);
 	globals->surfacearea = (sd->object == ~0) ? 1.0f : object_surface_area(kg, sd->object);
+	globals->time = sd->time;
 
 	/* booleans */
 	globals->raytype = path_flag; /* todo: add our own ray types */

File blender/intern/cycles/render/camera.cpp

View file
  • Ignore whitespace
 #ifdef __CAMERA_MOTION__
 	else if(need_motion == Scene::MOTION_BLUR) {
 		if(use_motion) {
-			transform_motion_decompose(&kcam->motion, &motion, &matrix);
+			transform_motion_decompose((DecompMotionTransform*)&kcam->motion, &motion, &matrix);
 			kcam->have_motion = 1;
 		}
 	}

File blender/intern/cycles/render/object.cpp

View file
  • Ignore whitespace
 	BoundBox mbounds = mesh->bounds;
 
 	if(motion_blur && use_motion) {
-		MotionTransform decomp;
+		DecompMotionTransform decomp;
 		transform_motion_decompose(&decomp, &motion, &tfm);
 
 		bounds = BoundBox::empty;
 				mtfm_post = mtfm_post * itfm;
 
 			memcpy(&objects[offset+8], &mtfm_pre, sizeof(float4)*4);
-			memcpy(&objects[offset+16], &mtfm_post, sizeof(float4)*4);
+			memcpy(&objects[offset+12], &mtfm_post, sizeof(float4)*4);
 		}
 #ifdef __OBJECT_MOTION__
 		else if(need_motion == Scene::MOTION_BLUR) {
 			if(ob->use_motion) {
 				/* decompose transformations for interpolation */
-				MotionTransform decomp;
+				DecompMotionTransform decomp;
 
 				transform_motion_decompose(&decomp, &ob->motion, &ob->tfm);
-				memcpy(&objects[offset+8], &decomp, sizeof(float4)*12);
+				memcpy(&objects[offset+8], &decomp, sizeof(float4)*8);
 				flag |= SD_OBJECT_MOTION;
 				have_motion = true;
 			}
 			else {
 				float4 no_motion = make_float4(FLT_MAX);
-				memcpy(&objects[offset+8], &no_motion, sizeof(float4)*12);
+				memcpy(&objects[offset+8], &no_motion, sizeof(float4)*8);
 			}
 		}
 #endif
 
 		/* dupli object coords */
-		objects[offset+20] = make_float4(ob->dupli_generated[0], ob->dupli_generated[1], ob->dupli_generated[2], 0.0f);
-		objects[offset+21] = make_float4(ob->dupli_uv[0], ob->dupli_uv[1], 0.0f, 0.0f);
+		objects[offset+16] = make_float4(ob->dupli_generated[0], ob->dupli_generated[1], ob->dupli_generated[2], 0.0f);
+		objects[offset+17] = make_float4(ob->dupli_uv[0], ob->dupli_uv[1], 0.0f, 0.0f);
 
 		/* object flag */
 		if(ob->use_holdout)

File blender/intern/cycles/render/session.cpp

View file
  • Ignore whitespace
 		reset_gpu(buffer_params, samples);
 	else
 		reset_cpu(buffer_params, samples);
+
+	if(params.progressive_refine) {
+		thread_scoped_lock buffers_lock(buffers_mutex);
+
+		foreach(RenderBuffers *buffers, tile_buffers)
+			delete buffers;
+
+		tile_buffers.clear();
+	}
 }
 
 void Session::set_samples(int samples)

File blender/intern/cycles/render/svm.cpp

View file
  • Ignore whitespace
 	}
 }
 
-void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done)
+void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done, set<ShaderNode*>& closure_done)
 {
 	/* todo: the weaks point here is that unlike the single closure sampling 
 	 * we will evaluate all nodes even if they are used as input for closures
 	 * nodes at runtime, especially if they are tangled up  */
 	
 	/* only generate once */
-	if(done.find(node) != done.end())
+	if(closure_done.find(node) != closure_done.end())
 		return;
 
-	done.insert(node);
+	closure_done.insert(node);
 
 	if(node->name == ustring("mix_closure") || node->name == ustring("add_closure")) {
 		/* weighting is already taken care of in ShaderGraph::transform_multi_closure */
 		ShaderInput *cl2in = node->input("Closure2");
 
 		if(cl1in->link)
-			generate_multi_closure(cl1in->link->parent, done);
+			generate_multi_closure(cl1in->link->parent, done, closure_done);
 		if(cl2in->link)
-			generate_multi_closure(cl2in->link->parent, done);
+			generate_multi_closure(cl2in->link->parent, done, closure_done);
 	}
 	else {
 		/* execute dependencies for closure */
 		if(node->name == ustring("transparent"))
 			current_shader->has_surface_transparent = true;
 	}
+
+	done.insert(node);
 }
 
 
 			if(generate) {
 				set<ShaderNode*> done;
 
-				if(use_multi_closure)
-					generate_multi_closure(clin->link->parent, done);
+				if(use_multi_closure) {
+					set<ShaderNode*> closure_done;
+					generate_multi_closure(clin->link->parent, done, closure_done);
+				}
 				else
 					generate_closure(clin->link->parent, done);
 			}

File blender/intern/cycles/render/svm.h

View file
  • Ignore whitespace
 	void generate_closure(ShaderNode *node, set<ShaderNode*>& done);
 
 	/* multi closure */
-	void generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done);
+	void generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done, set<ShaderNode*>& closure_done);
 
 	/* compile */
 	void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type);

File blender/intern/cycles/util/util_transform.cpp

View file
  • Ignore whitespace
 	decomp->w = make_float4(scale.y.z, scale.z.x, scale.z.y, scale.z.z);
 }
 
-void transform_motion_decompose(MotionTransform *decomp, const MotionTransform *motion, const Transform *mid)
+void transform_motion_decompose(DecompMotionTransform *decomp, const MotionTransform *motion, const Transform *mid)
 {
-	transform_decompose(&decomp->pre, &motion->pre);
+	Transform pre, post;
+
+	transform_decompose(&pre, &motion->pre);
 	transform_decompose(&decomp->mid, mid);
-	transform_decompose(&decomp->post, &motion->post);
+	transform_decompose(&post, &motion->post);
 
 	/* ensure rotation around shortest angle, negated quaternions are the same
 	 * but this means we don't have to do the check in quat_interpolate */
-	if(dot(decomp->mid.x, decomp->post.x) < 0.0f)
+	if(dot(decomp->mid.x, post.x) < 0.0f)
 		decomp->mid.x = -decomp->mid.x;
-	if(dot(decomp->pre.x, decomp->mid.x) < 0.0f)
-		decomp->pre.x = -decomp->pre.x;
+	if(dot(pre.x, decomp->mid.x) < 0.0f)
+		pre.x = -pre.x;
+	
+	/* drop scale of pre/post */
+	pre.y.w = decomp->mid.y.w;
+	post.y.w = decomp->mid.y.w;
+
+	/* store translation/rotation part of pre/post */
+	decomp->pre_x = pre.x;
+	decomp->pre_y = pre.y;
+	decomp->post_x = post.x;
+	decomp->post_y = post.y;
 }
 
 CCL_NAMESPACE_END

File blender/intern/cycles/util/util_transform.h

View file
  • Ignore whitespace
 
 /* transform decomposed in rotation/translation/scale. we use the same data
  * structure as Transform, and tightly pack decomposition into it. first the
- * rotation (4), then translation (3), then 3x3 scale matrix (9) */
+ * rotation (4), then translation (3), then 3x3 scale matrix (9).
+ *
+ * For the DecompMotionTransform we drop scale from pre/post. */
 
 typedef struct MotionTransform {
 	Transform pre;
 	Transform post;
 } MotionTransform;
 
+typedef struct DecompMotionTransform {
+	Transform mid;
+	float4 pre_x, pre_y;
+	float4 post_x, post_y;
+} DecompMotionTransform;
+
 /* Functions */
 
 __device_inline float3 transform_perspective(const Transform *t, const float3 a)
 
 __device_inline float4 quat_interpolate(float4 q1, float4 q2, float t)
 {
+	/* use simpe nlerp instead of slerp. it's faster and almost the same */
+	return normalize((1.0f - t)*q1 + t*q2);
+
+#if 0
 	/* note: this does not ensure rotation around shortest angle, q1 and q2
 	 * are assumed to be matched already in transform_motion_decompose */
 	float costheta = dot(q1, q2);
 		float thetap = theta * t;
 		return q1 * cosf(thetap) + qperp * sinf(thetap);
 	}
+#endif
 }
 
 __device_inline Transform transform_quick_inverse(Transform M)
 /* Disabled for now, need arc-length parametrization for constant speed motion.
  * #define CURVED_MOTION_INTERPOLATE */
 
-__device void transform_motion_interpolate(Transform *tfm, const MotionTransform *motion, float t)
+__device void transform_motion_interpolate(Transform *tfm, const DecompMotionTransform *motion, float t)
 {
 	/* possible optimization: is it worth it adding a check to skip scaling?
 	 * it's probably quite uncommon to have scaling objects. or can we skip
 
 #ifdef CURVED_MOTION_INTERPOLATE
 	/* 3 point bezier curve interpolation for position */
-	float3 Ppre = float4_to_float3(motion->pre.y);
+	float3 Ppre = float4_to_float3(motion->pre_y);
 	float3 Pmid = float4_to_float3(motion->mid.y);
-	float3 Ppost = float4_to_float3(motion->post.y);
+	float3 Ppost = float4_to_float3(motion->post_y);
 
 	float3 Pcontrol = 2.0f*Pmid - 0.5f*(Ppre + Ppost);
 	float3 P = Ppre*t*t + Pcontrol*2.0f*t*(1.0f - t) + Ppost*(1.0f - t)*(1.0f - t);
 	if(t < 0.5f) {
 		t *= 2.0f;
 
-		decomp.x = quat_interpolate(motion->pre.x, motion->mid.x, t);
+		decomp.x = quat_interpolate(motion->pre_x, motion->mid.x, t);
 #ifdef CURVED_MOTION_INTERPOLATE
-		decomp.y.w = (1.0f - t)*motion->pre.y.w + t*motion->mid.y.w;
+		decomp.y.w = (1.0f - t)*motion->pre_y.w + t*motion->mid.y.w;
 #else
-		decomp.y = (1.0f - t)*motion->pre.y + t*motion->mid.y;
+		decomp.y = (1.0f - t)*motion->pre_y + t*motion->mid.y;
 #endif
-		decomp.z = (1.0f - t)*motion->pre.z + t*motion->mid.z;
-		decomp.w = (1.0f - t)*motion->pre.w + t*motion->mid.w;
 	}
 	else {
 		t = (t - 0.5f)*2.0f;
 
-		decomp.x = quat_interpolate(motion->mid.x, motion->post.x, t);
+		decomp.x = quat_interpolate(motion->mid.x, motion->post_x, t);
 #ifdef CURVED_MOTION_INTERPOLATE
-		decomp.y.w = (1.0f - t)*motion->mid.y.w + t*motion->post.y.w;
+		decomp.y.w = (1.0f - t)*motion->mid.y.w + t*motion->post_y.w;
 #else
-		decomp.y = (1.0f - t)*motion->mid.y + t*motion->post.y;
+		decomp.y = (1.0f - t)*motion->mid.y + t*motion->post_y;
 #endif
-		decomp.z = (1.0f - t)*motion->mid.z + t*motion->post.z;
-		decomp.w = (1.0f - t)*motion->mid.w + t*motion->post.w;
 	}
 
+	decomp.z = motion->mid.z;
+	decomp.w = motion->mid.w;
+
 	/* compose rotation, translation, scale into matrix */
 	transform_compose(tfm, &decomp);
 }
 	return (A.pre == B.pre && A.post == B.post);
 }
 
-void transform_motion_decompose(MotionTransform *decomp, const MotionTransform *motion, const Transform *mid);
+void transform_motion_decompose(DecompMotionTransform *decomp, const MotionTransform *motion, const Transform *mid);
 
 #endif
 

File blender/intern/guardedalloc/intern/mallocn.c

View file
  • Ignore whitespace
  * store original buffer's name when doing MEM_dupallocN
  * helpful to profile issues with non-freed "dup_alloc" buffers,
  * but this introduces some overhead to memory header and makes
- * things slower a bit, so betterto keep disabled by default
+ * things slower a bit, so better to keep disabled by default
  */
 //#define DEBUG_MEMDUPLINAME
 

File blender/release/datafiles/startup.blend

  • Ignore whitespace
Binary file modified.

File blender/release/scripts/startup/bl_operators/uvcalc_follow_active.py

View file
  • Ignore whitespace
 
 
 def extend(obj, operator, EXTEND_MODE):
-    from bpy_extras import mesh_utils
-
+    import bmesh
     me = obj.data
-    me_verts = me.vertices
-
     # script will fail without UVs
     if not me.uv_textures:
         me.uv_textures.new()
+    
+    bm = bmesh.from_edit_mesh(me)
+    
+    f_act = bm.faces.active
+    uv_act = bm.loops.layers.uv.active
+    
+    if f_act is None:
+        operator.report({'ERROR'}, "No active face")
+        return
+    elif len(f_act.verts) != 4:
+        operator.report({'ERROR'}, "Active face must be a quad")
+        return
 
-    # Toggle Edit mode
-    is_editmode = (obj.mode == 'EDIT')
-    if is_editmode:
-        bpy.ops.object.mode_set(mode='OBJECT')
-
-    #t = sys.time()
-    edge_average_lengths = {}
-
-    OTHER_INDEX = 2, 3, 0, 1
-
-    def extend_uvs(face_source, face_target, edge_key):
-        """
-        Takes 2 faces,
-        Projects its extends its UV coords onto the face next to it.
-        Both faces must share an edge
-        """
-
-        def face_edge_vs(vi):
-            vlen = len(vi)
-            return [(vi[i], vi[(i + 1) % vlen]) for i in range(vlen)]
-
-        vidx_source = face_source.vertices
-        vidx_target = face_target.vertices
-
-        uv_layer = me.uv_layers.active.data
-        uvs_source = [uv_layer[i].uv for i in face_source.loop_indices]
-        uvs_target = [uv_layer[i].uv for i in face_target.loop_indices]
-
-        # vertex index is the key, uv is the value
-
-        uvs_vhash_source = {vindex: uvs_source[i] for i, vindex in enumerate(vidx_source)}
-
-        uvs_vhash_target = {vindex: uvs_target[i] for i, vindex in enumerate(vidx_target)}
-
-        edge_idxs_source = face_edge_vs(vidx_source)
-        edge_idxs_target = face_edge_vs(vidx_target)
-
-        source_matching_edge = -1
-        target_matching_edge = -1
-
-        edge_key_swap = edge_key[1], edge_key[0]
-
-        try:
-            source_matching_edge = edge_idxs_source.index(edge_key)
-        except:
-            source_matching_edge = edge_idxs_source.index(edge_key_swap)
-        try:
-            target_matching_edge = edge_idxs_target.index(edge_key)
-        except:
-            target_matching_edge = edge_idxs_target.index(edge_key_swap)
-
-        edgepair_inner_source = edge_idxs_source[source_matching_edge]
-        edgepair_inner_target = edge_idxs_target[target_matching_edge]
-        edgepair_outer_source = edge_idxs_source[OTHER_INDEX[source_matching_edge]]
-        edgepair_outer_target = edge_idxs_target[OTHER_INDEX[target_matching_edge]]
-
-        if edge_idxs_source[source_matching_edge] == edge_idxs_target[target_matching_edge]:
-            iA = 0  # Flipped, most common
-            iB = 1
-        else:  # The normals of these faces must be different
-            iA = 1
-            iB = 0
+    faces = [f for f in bm.faces if f.select and len(f.verts) == 4]
+
+    for f in faces:
+        f.tag = False
+    f_act.tag = True
+
+
+    # our own local walker
+    def walk_face(f):
+        # all faces in this list must be tagged
+        f.tag = True
+        faces_a = [f]
+        faces_b = []
+
+        while faces_a:
+            for f in faces_a:
+                for l in f.loops:
+                    l_edge = l.edge
+                    if (l_edge.is_manifold is True) and (l_edge.seam is False):
+                        l_other = l.link_loop_radial_next
+                        f_other = l_other.face
+                        if not f_other.tag:
+                            yield (f, l, f_other)
+                            f_other.tag = True
+                            faces_b.append(f_other)
+            # swap
+            faces_a, faces_b = faces_b, faces_a
+            faces_b.clear()
+
+    def extrapolate_uv(fac,
+                       l_a_outer, l_a_inner,
+                       l_b_outer, l_b_inner):
+        l_b_inner[:] = l_a_inner
+        l_b_outer[:] = l_a_inner + ((l_a_inner - l_a_outer) * fac)
+
+    def apply_uv(f_prev, l_prev, f_next):
+        l_a = [None, None, None, None]
+        l_b = [None, None, None, None]
+        
+        l_a[0] = l_prev
+        l_a[1] = l_a[0].link_loop_next
+        l_a[2] = l_a[1].link_loop_next
+        l_a[3] = l_a[2].link_loop_next
+
+        #  l_b
+        #  +-----------+
+        #  |(3)        |(2)
+        #  |           |
+        #  |l_next(0)  |(1)
+        #  +-----------+
+        #        ^
+        #  l_a   |
+        #  +-----------+
+        #  |l_prev(0)  |(1)
+        #  |    (f)    |
+        #  |(3)        |(2)
+        #  +-----------+
+        #  copy from this face to the one above.
+
+        # get the other loops 
+        l_next = l_prev.link_loop_radial_next
+        if l_next.vert != l_prev.vert:
+            l_b[1] = l_next
+            l_b[0] = l_b[1].link_loop_next
+            l_b[3] = l_b[0].link_loop_next
+            l_b[2] = l_b[3].link_loop_next
+        else:
+            l_b[0] = l_next
+            l_b[1] = l_b[0].link_loop_next
+            l_b[2] = l_b[1].link_loop_next
+            l_b[3] = l_b[2].link_loop_next
 
-        # Set the target UV's touching source face, no tricky calculations needed,
-        uvs_vhash_target[edgepair_inner_target[0]][:] = uvs_vhash_source[edgepair_inner_source[iA]]
-        uvs_vhash_target[edgepair_inner_target[1]][:] = uvs_vhash_source[edgepair_inner_source[iB]]
+        l_a_uv = [l[uv_act].uv for l in l_a]
+        l_b_uv = [l[uv_act].uv for l in l_b]
 
-        # Set the 2 UV's on the target face that are not touching
-        # for this we need to do basic expanding on the source faces UV's
         if EXTEND_MODE == 'LENGTH':
+            a0, b0, c0 = l_a[3].vert.co, l_a[0].vert.co, l_b[3].vert.co
+            a1, b1, c1 = l_a[2].vert.co, l_a[1].vert.co, l_b[2].vert.co
 
-            try:  # divide by zero is possible
-                '''
-                measure the length of each face from the middle of each edge to the opposite
-                along the axis we are copying, use this
-                '''
-                i1a = edgepair_outer_target[iB]
-                i2a = edgepair_inner_target[iA]
-                if i1a > i2a:
-                    i1a, i2a = i2a, i1a
-
-                i1b = edgepair_outer_source[iB]
-                i2b = edgepair_inner_source[iA]
-                if i1b > i2b:
-                    i1b, i2b = i2b, i1b
-                # print edge_average_lengths
-                factor = edge_average_lengths[i1a, i2a][0] / edge_average_lengths[i1b, i2b][0]
-            except:
-                # Div By Zero?
-                factor = 1.0
-
-            uvs_vhash_target[edgepair_outer_target[iB]][:] = uvs_vhash_source[edgepair_inner_source[0]] + factor * (uvs_vhash_source[edgepair_inner_source[0]] - uvs_vhash_source[edgepair_outer_source[1]])
-            uvs_vhash_target[edgepair_outer_target[iA]][:] = uvs_vhash_source[edgepair_inner_source[1]] + factor * (uvs_vhash_source[edgepair_inner_source[1]] - uvs_vhash_source[edgepair_outer_source[0]])
-
+            d1 = (a0 - b0).length + (a1 - b1).length
+            d2 = (b0 - c0).length + (b1 - c1).length
+            try:
+                fac = d2 / d1
+            except ZeroDivisionError:
+                fac = 1.0
         else:
-            # same as above but with no factors
-            uvs_vhash_target[edgepair_outer_target[iB]][:] = uvs_vhash_source[edgepair_inner_source[0]] + (uvs_vhash_source[edgepair_inner_source[0]] - uvs_vhash_source[edgepair_outer_source[1]])
-            uvs_vhash_target[edgepair_outer_target[iA]][:] = uvs_vhash_source[edgepair_inner_source[1]] + (uvs_vhash_source[edgepair_inner_source[1]] - uvs_vhash_source[edgepair_outer_source[0]])
+            fac = 1.0
 
-    face_act = me.polygons.active
-    if face_act == -1:
-        operator.report({'ERROR'}, "No active face")
-        return
+        extrapolate_uv(fac,
+                       l_a_uv[3], l_a_uv[0],
+                       l_b_uv[3], l_b_uv[0])
 
-    face_sel = [f for f in me.polygons if len(f.vertices) == 4 and f.select]
+        extrapolate_uv(fac,
+                       l_a_uv[2], l_a_uv[1],
+                       l_b_uv[2], l_b_uv[1])
 
-    face_act_local_index = -1
-    for i, f in enumerate(face_sel):
-        if f.index == face_act:
-            face_act_local_index = i
-            break
+    for f_triple in walk_face(f_act):
+        apply_uv(*f_triple)
 
-    if face_act_local_index == -1:
-        operator.report({'ERROR'}, "Active face not selected")
-        return
-
-    # Modes
-    # 0 not yet searched for.
-    # 1:mapped, use search from this face - removed!
-    # 2:all siblings have been searched. don't search again.
-    face_modes = [0] * len(face_sel)
-    face_modes[face_act_local_index] = 1  # extend UV's from this face.
-
-    # Edge connectivity
-    edge_faces = {}
-    for i, f in enumerate(face_sel):
-        for edkey in f.edge_keys:
-            try:
-                edge_faces[edkey].append(i)
-            except:
-                edge_faces[edkey] = [i]
-
-    if EXTEND_MODE == 'LENGTH':
-        edge_loops = mesh_utils.edge_loops_from_tessfaces(me, face_sel, [ed.key for ed in me.edges if ed.use_seam])
-        me_verts = me.vertices
-        for loop in edge_loops:
-            looplen = [0.0]
-            for ed in loop:
-                edge_average_lengths[ed] = looplen
-                looplen[0] += (me_verts[ed[0]].co - me_verts[ed[1]].co).length
-            looplen[0] = looplen[0] / len(loop)
-
-    # remove seams, so we don't map across seams.
-    for ed in me.edges:
-        if ed.use_seam:
-            # remove the edge pair if we can
-            try:
-                del edge_faces[ed.key]
-            except:
-                pass
-    # Done finding seams
-
-    # face connectivity - faces around each face
-    # only store a list of indices for each face.
-    face_faces = [[] for i in range(len(face_sel))]
-
-    for edge_key, faces in edge_faces.items():
-        if len(faces) == 2:  # Only do edges with 2 face users for now
-            face_faces[faces[0]].append((faces[1], edge_key))
-            face_faces[faces[1]].append((faces[0], edge_key))
-
-    # Now we know what face is connected to what other face, map them by connectivity
-    ok = True
-    while ok:
-        ok = False
-        for i in range(len(face_sel)):
-            if face_modes[i] == 1:  # searchable
-                for f_sibling, edge_key in face_faces[i]:
-                    if face_modes[f_sibling] == 0:
-                        face_modes[f_sibling] = 1  # mapped and search from.
-                        extend_uvs(face_sel[i], face_sel[f_sibling], edge_key)
-                        face_modes[i] = 1  # we can map from this one now.
-                        ok = True  # keep searching
-
-                face_modes[i] = 2  # don't search again
-
-    if is_editmode:
-        bpy.ops.object.mode_set(mode='EDIT')
-    else:
-        me.update_tag()
+    bmesh.update_edit_mesh(me, False)
 
 
 def main(context, operator):

File blender/release/scripts/templates/bmesh_simple_editmode.py

View file
  • Ignore whitespace
+# This example assumes we have a mesh object in edit-mode
+
+import bpy
+import bmesh
+
+# Get the active mesh
+obj = bpy.context.edit_object
+me = obj.data
+
+
+# Get a BMesh representation
+bm = bmesh.from_edit_mesh(me)
+
+bm.faces.active = None
+
+# Modify the BMesh, can do anything here...
+for v in bm.verts:
+    v.co.x += 1.0
+
+
+# Show the updates in the viewport
+# and recalculate n-gon tessellation.
+bmesh.update_edit_mesh(me, True)

File blender/release/scripts/templates/script_stub.py

View file
  • Ignore whitespace
 
 filepath = os.path.join(os.path.dirname(bpy.data.filepath), filename)
 global_namespace = {"__file__": filepath, "__name__": "__main__"}
-exec(compile(open(filepath).read(), filepath, 'exec'), global_namespace)
+file_handle = open(filepath, 'rb')
+exec(compile(file_handle.read(), filepath, 'exec'), global_namespace)
+file_handle.close()

File blender/source/blender/blenkernel/intern/modifiers_bmesh.c

View file
  • Ignore whitespace
 	/*do verts*/
 	mv = mvert = dm->dupVertArray(dm);
 	for (i = 0; i < totvert; i++, mv++) {
-		v = BM_vert_create(bm, mv->co, NULL);
+		v = BM_vert_create(bm, mv->co, NULL, BM_CREATE_SKIP_CD);
 		normal_short_to_float_v3(v->no, mv->no);
 		v->head.hflag = BM_vert_flag_from_mflag(mv->flag);
 		BM_elem_index_set(v, i); /* set_inline */
 	me = medge = dm->dupEdgeArray(dm);
 	for (i = 0; i < totedge; i++, me++) {
 		//BLI_assert(BM_edge_exists(vtable[me->v1], vtable[me->v2]) == NULL);
-		e = BM_edge_create(bm, vtable[me->v1], vtable[me->v2], NULL, FALSE);
+		e = BM_edge_create(bm, vtable[me->v1], vtable[me->v2], NULL, BM_CREATE_SKIP_CD);
 
 		e->head.hflag = BM_edge_flag_from_mflag(me->flag);
 		BM_elem_index_set(e, i); /* set_inline */
 			edges[j] = etable[ml->e];
 		}
 
-		f = BM_face_create_ngon(bm, verts[0], verts[1], edges, mp->totloop, FALSE);
+		f = BM_face_create_ngon(bm, verts[0], verts[1], edges, mp->totloop, BM_CREATE_SKIP_CD);
 
 		if (UNLIKELY(f == NULL)) {
 			continue;

File blender/source/blender/blenkernel/intern/sequencer.c

View file
  • Ignore whitespace
 		StripCrop c = {0};
 		StripTransform t = {0};
 		int sx, sy, dx, dy;
+		double xscale = 1.0;
+		double yscale = 1.0;
 
 		if (is_proxy_image) {
 			double f = seq_rendersize_to_scale_factor(context.preview_render_size);
 			t = *seq->strip->transform;
 		}
 
+		xscale = context.scene->r.xsch ? ((double)context.rectx / (double)context.scene->r.xsch) : 1.0;
+		yscale = context.scene->r.ysch ? ((double)context.recty / (double)context.scene->r.ysch) : 1.0;
+
+		xscale /= (double)context.rectx / (double)ibuf->x;
+		yscale /= (double)context.recty / (double)ibuf->y;
+
+		c.left *= xscale; c.right *= xscale;
+		c.top *= yscale; c.bottom *= yscale;
+
+		t.xofs *= xscale; t.yofs *= yscale;
+
 		sx = ibuf->x - c.left - c.right;
 		sy = ibuf->y - c.top - c.bottom;
 		dx = sx;
 	            0 /* (context.scene->r.seq_flag & R_SEQ_GL_REND) */ :
 	            (context.scene->r.seq_flag & R_SEQ_GL_PREV);
 	int do_seq;
-	int have_seq = FALSE;
+	// int have_seq = FALSE;  /* UNUSED */
 	int have_comp = FALSE;
 	Scene *scene;
 	int is_thread_main = BLI_thread_is_main();
 	scene = seq->scene;
 	frame = scene->r.sfra + nr + seq->anim_startofs;
 
-	have_seq = (scene->r.scemode & R_DOSEQ) && scene->ed && scene->ed->seqbase.first;
+	// have_seq = (scene->r.scemode & R_DOSEQ) && scene->ed && scene->ed->seqbase.first;  /* UNUSED */
 	have_comp = (scene->r.scemode & R_DOCOMP) && scene->use_nodes && scene->nodetree;
 
 	oldcfra = scene->r.cfra;

File blender/source/blender/bmesh/intern/bmesh_construct.c

View file
  • Ignore whitespace
 	/* make new face */
 	if ((f == NULL) && (!is_overlap)) {
 		BMEdge *edar[4] = {NULL};
-		edar[0] = BM_edge_create(bm, verts[0], verts[1], NULL, TRUE);
-		edar[1] = BM_edge_create(bm, verts[1], verts[2], NULL, TRUE);
+		edar[0] = BM_edge_create(bm, verts[0], verts[1], NULL, BM_CREATE_NO_DOUBLE);
+		edar[1] = BM_edge_create(bm, verts[1], verts[2], NULL, BM_CREATE_NO_DOUBLE);
 		if (len == 4) {
-			edar[2] = BM_edge_create(bm, verts[2], verts[3], NULL, TRUE);
-			edar[3] = BM_edge_create(bm, verts[3], verts[0], NULL, TRUE);
+			edar[2] = BM_edge_create(bm, verts[2], verts[3], NULL, BM_CREATE_NO_DOUBLE);
+			edar[3] = BM_edge_create(bm, verts[3], verts[0], NULL, BM_CREATE_NO_DOUBLE);
 		}
 		else {
-			edar[2] = BM_edge_create(bm, verts[2], verts[0], NULL, TRUE);
+			edar[2] = BM_edge_create(bm, verts[2], verts[0], NULL, BM_CREATE_NO_DOUBLE);
 		}
 
-		f = BM_face_create(bm, verts, edar, len, FALSE);
+		f = BM_face_create(bm, verts, edar, len, 0);
 
 		if (example && f) {
 			BM_elem_attrs_copy(bm, bm, example, f);
  * #BM_face_create should be considered over this function as it
  * avoids some unnecessary work.
  */
-BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, int nodouble)
+BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, const int create_flag)
 {
 	BMEdge **edges2 = NULL;
 	BLI_array_staticdeclare(edges2, BM_DEFAULT_NGON_STACK_SIZE);
 		BM_ELEM_API_FLAG_DISABLE(verts[i], _FLAG_MV);
 	}
 
-	f = BM_face_create(bm, verts, edges2, len, nodouble);
+	f = BM_face_create(bm, verts, edges2, len, create_flag);
 
 	/* clean up flags */
 	for (i = 0; i < len; i++) {
  *
  * \note Since this is a vcloud there is no direction.
  */
-BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int totv, int nodouble)
+BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int totv, const int create_flag)
 {
 	BMFace *f;
 
 
 	i_prev = totv - 1;
 	for (i = 0; i < totv; i++) {
-		edge_arr[i] = BM_edge_create(bm, vert_arr_map[i_prev], vert_arr_map[i], NULL, TRUE);
+		edge_arr[i] = BM_edge_create(bm, vert_arr_map[i_prev], vert_arr_map[i], NULL, BM_CREATE_NO_DOUBLE);
 
 		/* the edge may exist already and be attached to a face
 		 * in this case we can find the best winding to use for the new face */
 	/* --- */
 
 	/* create the face */
-	f = BM_face_create_ngon(bm, vert_arr_map[winding[0]], vert_arr_map[winding[1]], edge_arr, totv, nodouble);
+	f = BM_face_create_ngon(bm, vert_arr_map[winding[0]], vert_arr_map[winding[1]], edge_arr, totv, create_flag);
 
 	MEM_freeN(edge_arr);
 	MEM_freeN(vert_arr_map);
 
 	v = BM_iter_new(&iter, bm_old, BM_VERTS_OF_MESH, NULL);
 	for (i = 0; v; v = BM_iter_step(&iter), i++) {
-		v2 = BM_vert_create(bm_new, v->co, NULL); /* copy between meshes so cant use 'example' argument */
+		v2 = BM_vert_create(bm_new, v->co, NULL, BM_CREATE_SKIP_CD); /* copy between meshes so cant use 'example' argument */
 		BM_elem_attrs_copy(bm_old, bm_new, v, v2);
 		vtable[i] = v2;
 		BM_elem_index_set(v, i); /* set_inline */
 		e2 = BM_edge_create(bm_new,
 		                    vtable[BM_elem_index_get(e->v1)],
 		                    vtable[BM_elem_index_get(e->v2)],
-		                    e, FALSE);
+		                    e, BM_CREATE_SKIP_CD);
 
 		BM_elem_attrs_copy(bm_old, bm_new, e, e2);
 		etable[i] = e2;
 			v2 = vtable[BM_elem_index_get(loops[0]->v)];
 		}
 
-		f2 = BM_face_create_ngon(bm_new, v, v2, edges, f->len, FALSE);
+		f2 = BM_face_create_ngon(bm_new, v, v2, edges, f->len, BM_CREATE_SKIP_CD);
 		if (UNLIKELY(f2 == NULL)) {
 			continue;
 		}

File blender/source/blender/bmesh/intern/bmesh_construct.h

View file
  • Ignore whitespace
 
 void BM_face_copy_shared(BMesh *bm, BMFace *f);
 
-BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, int nodouble);
+BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, const int create_flag);
 
-BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, int nodouble);
+BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, const int create_flag);
 
 void BMO_remove_tagged_faces(BMesh *bm, const short oflag);
 void BMO_remove_tagged_edges(BMesh *bm, const short oflag);

File blender/source/blender/bmesh/intern/bmesh_core.c

View file
  • Ignore whitespace
 /**
  * \brief Main function for creating a new vertex.
  */
-BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example)
+BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example, const eBMCreateFlag create_flag)
 {
 	BMVert *v = BLI_mempool_calloc(bm->vpool);
 
 	BM_elem_index_set(v, -1); /* set_ok_invalid */
 #endif
 
+	/* disallow this flag for verts - its meaningless */
+	BLI_assert((create_flag & BM_CREATE_NO_DOUBLE) == 0);
+
 	bm->elem_index_dirty |= BM_VERT; /* may add to middle of the pool */
 
 	bm->totvert++;
 		v->oflags = BLI_mempool_calloc(bm->toolflagpool);
 	}
 
-	CustomData_bmesh_set_default(&bm->vdata, &v->head.data);
-	
-	if (example) {
-		int *keyi;
+	if (!(create_flag & BM_CREATE_SKIP_CD)) {
+		if (example) {
+			int *keyi;
 
-		BM_elem_attrs_copy(bm, bm, example, v);
+			BM_elem_attrs_copy(bm, bm, example, v);
 
-		/* exception: don't copy the original shapekey index */
-		keyi = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_SHAPE_KEYINDEX);
-		if (keyi) {
-			*keyi = ORIGINDEX_NONE;
+			/* exception: don't copy the original shapekey index */
+			keyi = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_SHAPE_KEYINDEX);
+			if (keyi) {
+				*keyi = ORIGINDEX_NONE;
+			}
+		}
+		else {
+			CustomData_bmesh_set_default(&bm->vdata, &v->head.data);
 		}
 	}
 
  * \note Duplicate edges are supported by the API however users should _never_ see them.
  * so unless you need a unique edge or know the edge won't exist, you should call with \a nodouble = TRUE
  */
-BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, int nodouble)
+BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, const eBMCreateFlag create_flag)
 {
 	BMEdge *e;
 	
-	if (nodouble && (e = BM_edge_exists(v1, v2)))
+	if ((create_flag & BM_CREATE_NO_DOUBLE) && (e = BM_edge_exists(v1, v2)))
 		return e;
 	
 	e = BLI_mempool_calloc(bm->epool);
 	
 	BM_elem_flag_enable(e, BM_ELEM_SMOOTH | BM_ELEM_DRAW);
 	
-	CustomData_bmesh_set_default(&bm->edata, &e->head.data);
-	
 	bmesh_disk_edge_append(e, e->v1);
 	bmesh_disk_edge_append(e, e->v2);
 	
-	if (example)
-		BM_elem_attrs_copy(bm, bm, example, e);
+	if (!(create_flag & BM_CREATE_SKIP_CD)) {
+		if (example) {
+			BM_elem_attrs_copy(bm, bm, example, e);
+		}
+		else {
+			CustomData_bmesh_set_default(&bm->edata, &e->head.data);
+		}
+	}
+
 	
 	BM_CHECK_ELEMENT(e);
 
 	return e;
 }
 
-static BMLoop *bm_loop_create(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f, const BMLoop *example)
+static BMLoop *bm_loop_create(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f,
+                              const BMLoop *example, const eBMCreateFlag create_flag)
 {
 	BMLoop *l = NULL;
 
 
 	bm->totloop++;
 
-	if (example) {
-		CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, example->head.data, &l->head.data);
-	}
-	else {
-		CustomData_bmesh_set_default(&bm->ldata, &l->head.data);
+	if (!(create_flag & BM_CREATE_SKIP_CD)) {
+		if (example) {
+			CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, example->head.data, &l->head.data);
+		}
+		else {
+			CustomData_bmesh_set_default(&bm->ldata, &l->head.data);
+		}
 	}
 
 	return l;
 }
 
-static BMLoop *bm_face_boundary_add(BMesh *bm, BMFace *f, BMVert *startv, BMEdge *starte)
+static BMLoop *bm_face_boundary_add(BMesh *bm, BMFace *f, BMVert *startv, BMEdge *starte, const int create_flag)
 {
 #ifdef USE_BMESH_HOLES
 	BMLoopList *lst = BLI_mempool_calloc(bm->looplistpool);
 #endif
-	BMLoop *l = bm_loop_create(bm, startv, starte, f, NULL);
+	BMLoop *l = bm_loop_create(bm, startv, starte, f, starte->l, create_flag);
 	
 	bmesh_radial_append(starte, l);
 
 	i = 0;
 	do {
 		if (copyverts) {
-			verts[i] = BM_vert_create(bm, l_iter->v->co, l_iter->v);
+			verts[i] = BM_vert_create(bm, l_iter->v->co, l_iter->v, 0);
 		}
 		else {
 			verts[i] = l_iter->v;
 				v1 = verts[(i + 1) % f->len];
 			}
 			
-			edges[i] = BM_edge_create(bm,  v1, v2, l_iter->e, FALSE);
+			edges[i] = BM_edge_create(bm,  v1, v2, l_iter->e, 0);
 		}
 		else {
 			edges[i] = l_iter->e;
 		i++;
 	} while ((l_iter = l_iter->next) != l_first);
 	
-	f_copy = BM_face_create(bm, verts, edges, f->len, FALSE);
+	f_copy = BM_face_create(bm, verts, edges, f->len, BM_CREATE_SKIP_CD);
 	
 	BM_elem_attrs_copy(bm, bm, f, f_copy);
 	
  * only create the face, since this calloc's the length is initialized to 0,
  * leave adding loops to the caller.
  */
-BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm)
+BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm, const eBMCreateFlag create_flag)
 {
 	BMFace *f;
 
 		f->oflags = BLI_mempool_calloc(bm->toolflagpool);
 	}
 
-	CustomData_bmesh_set_default(&bm->pdata, &f->head.data);
+	if (!(create_flag & BM_CREATE_SKIP_CD)) {
+		CustomData_bmesh_set_default(&bm->pdata, &f->head.data);
+	}
 
 #ifdef USE_BMESH_HOLES
 	f->totbounds = 0;
 /**
  * \brief Main face creation function
  */
-BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, int nodouble)
+BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, const eBMCreateFlag create_flag)
 {
 	BMFace *f = NULL;
 	BMLoop *l, *startl, *lastl;
 		return NULL;
 	}
 
-	if (nodouble) {
+	if (create_flag & BM_CREATE_NO_DOUBLE) {
 		/* Check if face already exists */
 		overlap = BM_face_exists(verts, len, &f);
 		if (overlap) {
 		}
 	}
 
-	f = bm_face_create__internal(bm);
+	f = bm_face_create__internal(bm, create_flag);
 
-	startl = lastl = bm_face_boundary_add(bm, f, verts[0], edges[0]);
+	startl = lastl = bm_face_boundary_add(bm, f, verts[0], edges[0], create_flag);
 	
 	startl->v = verts[0];
 	startl->e = edges[0];
 	for (i = 1; i < len; i++) {
-		l = bm_loop_create(bm, verts[i], edges[i], f, edges[i]->l);
+		l = bm_loop_create(bm, verts[i], edges[i], f, edges[i]->l, create_flag);
 		
 		l->f = f;
 		bmesh_radial_append(edges[i], l);
 	}
 
 	/* create region face */
-	newf = BM_face_create_ngon(bm, v1, v2, edges, tote, FALSE);
+	newf = BM_face_create_ngon(bm, v1, v2, edges, tote, 0);
 	if (UNLIKELY(!newf || BMO_error_occurred(bm))) {
 		if (!BMO_error_occurred(bm))
 			err = N_("Invalid boundary region to join faces");
 	BMLoopList *lst;
 #endif
 
-	f = bm_face_create__internal(bm);
+	f = bm_face_create__internal(bm, 0);
 
 #ifdef USE_BMESH_HOLES
 	lst = BLI_mempool_calloc(bm->looplistpool);
 	e = BM_edge_create(bm, v1, v2, example, nodouble);
 
 	f2 = bm_face_create__sfme(bm, f);
-	f1loop = bm_loop_create(bm, v2, e, f, v2loop);
-	f2loop = bm_loop_create(bm, v1, e, f2, v1loop);
+	f1loop = bm_loop_create(bm, v2, e, f, v2loop, 0);
+	f2loop = bm_loop_create(bm, v1, e, f2, v1loop, 0);
 
 	f1loop->prev = v2loop->prev;
 	f2loop->prev = v1loop->prev;
 
 	valence2 = bmesh_disk_count(tv);
 
-	nv = BM_vert_create(bm, tv->co, tv);
-	ne = BM_edge_create(bm, nv, tv, e, FALSE);
+	nv = BM_vert_create(bm, tv->co, tv, 0);
+	ne = BM_edge_create(bm, nv, tv, e, 0);
 
 	bmesh_disk_edge_remove(ne, tv);
 	bmesh_disk_edge_remove(ne, nv);
 			nextl = nextl != nextl->radial_next ? nextl->radial_next : NULL;
 			bmesh_radial_loop_remove(l, NULL);
 
-			nl = bm_loop_create(bm, NULL, NULL, l->f, l);
+			nl = bm_loop_create(bm, NULL, NULL, l->f, l, 0);
 			nl->prev = l;
 			nl->next = (l->next);
 			nl->prev->next = nl;
 	verts = MEM_callocN(sizeof(BMVert *) * maxindex, __func__);
 	verts[0] = v;
 	for (i = 1; i < maxindex; i++) {
-		verts[i] = BM_vert_create(bm, v->co, v);
+		verts[i] = BM_vert_create(bm, v->co, v, 0);
 	}
 
 	/* Replace v with the new verts in each group */
 		e->l = l_sep->radial_next;
 	}
 
-	ne = BM_edge_create(bm, e->v1, e->v2, e, FALSE);
+	ne = BM_edge_create(bm, e->v1, e->v2, e, 0);
 	bmesh_radial_loop_remove(l_sep, e);
 	bmesh_radial_append(ne, l_sep);
 	l_sep->e = ne;

File blender/source/blender/bmesh/intern/bmesh_core.h

View file
  • Ignore whitespace
 
 BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short copyedges);
 
-BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example);
-BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, int nodouble);
-BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, int nodouble);
+typedef enum eBMCreateFlag {
+	/* faces and edges only */
+	BM_CREATE_NO_DOUBLE = (1 << 1),
+	/* Skip CustomData - for all element types data,
+	 * use if we immediately write customdata into the element so this skips copying from 'example'
+	 * args or setting defaults, speeds up conversion when data is converted all at once. */
+	BM_CREATE_SKIP_CD   = (1 << 2),
+} eBMCreateFlag;
+
+BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example, const eBMCreateFlag create_flag);
+BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, const eBMCreateFlag create_flag);
+BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, const eBMCreateFlag create_flag);