[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [53848] trunk/blender: Movies support for Cycles

Sergey Sharybin sergey.vfx at gmail.com
Wed Jan 16 18:07:25 CET 2013


Revision: 53848
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=53848
Author:   nazgul
Date:     2013-01-16 17:07:25 +0000 (Wed, 16 Jan 2013)
Log Message:
-----------
Movies support for Cycles

This adds support of movie textures for Cycles rendering.

Uses the same builtin images routines as packed/generated images,
but with some extra non-rna hookups from blender_session side.

Basically, it's not so clear how to give access to video frames
via C++ RNA -- it'll require exposing ImBuf to API, doing some
threading locks and so. Ended up adding two more functions which
are actually bad level call, but don't consider it's so much bad
-- we have few bad calls already, which are actually related.

Changed a bit how builtin images names are passing to image
manager. Now it's not just an ID datablock name, but also a frame
number concatenated via '@' character, which makes itpossible to
easily know frame number to be used for movie images, without
adding extra descriptors to image manager.

Decoding of builtin name is a bit slower now, but it should be
still nothing in comparison with rendering complexity.

Also exposed image user's frame_current to python API, which
is needed to get absolute frame number of movie from node's
image user.

P.S. Generated/packed images are also using bad level call but
only does it to make things more clear here.  Either all images
are using C++ RNA here or no images does. That's the most clear
for now.

Modified Paths:
--------------
    trunk/blender/intern/cycles/blender/blender_session.cpp
    trunk/blender/intern/cycles/blender/blender_session.h
    trunk/blender/intern/cycles/blender/blender_shader.cpp
    trunk/blender/intern/cycles/blender/blender_util.h
    trunk/blender/source/blender/blenkernel/BKE_image.h
    trunk/blender/source/blender/blenkernel/intern/image.c
    trunk/blender/source/blender/makesrna/intern/rna_image.c

Modified: trunk/blender/intern/cycles/blender/blender_session.cpp
===================================================================
--- trunk/blender/intern/cycles/blender/blender_session.cpp	2013-01-16 14:56:16 UTC (rev 53847)
+++ trunk/blender/intern/cycles/blender/blender_session.cpp	2013-01-16 17:07:25 UTC (rev 53848)
@@ -612,8 +612,25 @@
 			session->progress.set_cancel("Cancelled");
 }
 
-void BlenderSession::builtin_image_info(const string &name, bool &is_float, int &width, int &height, int &channels)
+/* builtin image file name is actually an image datablock name with
+ * absolute sequence frame number concatenated via '@' character
+ *
+ * this function splits image id name and frame number from a
+ * builtin image name
+ */
+void BlenderSession::builtin_name_split(const string &builtin_name, string &name, int &frame)
 {
+	int last = builtin_name.find_last_of('@');
+	name = builtin_name.substr(0, last);
+	frame = atoi(builtin_name.substr(last + 1, builtin_name.size() - last - 1).c_str());
+}
+
+void BlenderSession::builtin_image_info(const string &builtin_name, bool &is_float, int &width, int &height, int &channels)
+{
+	string name;
+	int frame;
+	builtin_name_split(builtin_name, name, frame);
+
 	BL::Image b_image = b_data.images[name];
 
 	if(b_image) {
@@ -630,8 +647,12 @@
 	}
 }
 
-bool BlenderSession::builtin_image_pixels(const string &name, unsigned char *pixels)
+bool BlenderSession::builtin_image_pixels(const string &builtin_name, unsigned char *pixels)
 {
+	string name;
+	int frame;
+	builtin_name_split(builtin_name, name, frame);
+
 	BL::Image b_image = b_data.images[name];
 
 	if(b_image) {
@@ -639,17 +660,28 @@
 		int height = b_image.size()[1];
 		int channels = b_image.channels();
 
-		BL::DynamicArray<float> pixels_array = b_image.pixels();
-		float *float_pixels = pixels_array.data;
+		unsigned char *image_pixels;
+		image_pixels = image_get_pixels_for_frame(b_image, frame);
 
-		/* a bit of shame, but Py API currently only returns float array,
-		 * which need to be converted back to char buffer
-		 */
-		unsigned char *cp = pixels;
-		float *fp = float_pixels;
-		for(int i = 0; i < channels * width * height; i++, cp++, fp++) {
-			*cp = *fp * 255;
+		if(image_pixels) {
+			memcpy(pixels, image_pixels, width * height * channels * sizeof(unsigned char));
+			MEM_freeN(image_pixels);
 		}
+		else {
+			if(channels == 1) {
+				memset(pixels, 0, width * height * sizeof(unsigned char));
+			}
+			else {
+				unsigned char *cp = pixels;
+				for(int i = 0; i < width * height; i++, cp += channels) {
+					cp[0] = 255;
+					cp[1] = 0;
+					cp[2] = 255;
+					if(channels == 4)
+						cp[3] = 255;
+				}
+			}
+		}
 
 		return true;
 	}
@@ -657,8 +689,12 @@
 	return false;
 }
 
-bool BlenderSession::builtin_image_float_pixels(const string &name, float *pixels)
+bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, float *pixels)
 {
+	string name;
+	int frame;
+	builtin_name_split(builtin_name, name, frame);
+
 	BL::Image b_image = b_data.images[name];
 
 	if(b_image) {
@@ -666,9 +702,28 @@
 		int height = b_image.size()[1];
 		int channels = b_image.channels();
 
-		BL::DynamicArray<float> pixels_array = b_image.pixels();
+		float *image_pixels;
+		image_pixels = image_get_float_pixels_for_frame(b_image, frame);
 
-		memcpy(pixels, pixels_array.data, width * height * channels * sizeof(float));
+		if(image_pixels) {
+			memcpy(pixels, image_pixels, width * height * channels * sizeof(float));
+			MEM_freeN(image_pixels);
+		}
+		else {
+			if(channels == 1) {
+				memset(pixels, 0, width * height * sizeof(float));
+			}
+			else {
+				float *fp = pixels;
+				for(int i = 0; i < width * height; i++, fp += channels) {
+					fp[0] = 1.0f;
+					fp[1] = 0.0f;
+					fp[2] = 1.0f;
+					if(channels == 4)
+						fp[3] = 1.0f;
+				}
+			}
+		}
 
 		return true;
 	}

Modified: trunk/blender/intern/cycles/blender/blender_session.h
===================================================================
--- trunk/blender/intern/cycles/blender/blender_session.h	2013-01-16 14:56:16 UTC (rev 53847)
+++ trunk/blender/intern/cycles/blender/blender_session.h	2013-01-16 17:07:25 UTC (rev 53848)
@@ -94,9 +94,10 @@
 	void do_write_update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile, bool do_update_only);
 	void do_write_update_render_tile(RenderTile& rtile, bool do_update_only);
 
-	void builtin_image_info(const string &name, bool &is_float, int &width, int &height, int &channels);
-	bool builtin_image_pixels(const string &name, unsigned char *pixels);
-	bool builtin_image_float_pixels(const string &name, float *pixels);
+	void builtin_name_split(const string &builtin_name, string &name, int &frame);
+	void builtin_image_info(const string &builtin_name, bool &is_float, int &width, int &height, int &channels);
+	bool builtin_image_pixels(const string &builtin_name, unsigned char *pixels);
+	bool builtin_image_float_pixels(const string &builtin_name, float *pixels);
 };
 
 CCL_NAMESPACE_END

Modified: trunk/blender/intern/cycles/blender/blender_shader.cpp
===================================================================
--- trunk/blender/intern/cycles/blender/blender_shader.cpp	2013-01-16 14:56:16 UTC (rev 53847)
+++ trunk/blender/intern/cycles/blender/blender_shader.cpp	2013-01-16 17:07:25 UTC (rev 53848)
@@ -511,17 +511,24 @@
 			BL::ShaderNodeTexImage b_image_node(b_node);
 			BL::Image b_image(b_image_node.image());
 			ImageTextureNode *image = new ImageTextureNode();
-			/* todo: handle movie images */
-			if(b_image && b_image.source() != BL::Image::source_MOVIE) {
+			if(b_image) {
 				/* builtin images will use callback-based reading because
 				 * they could only be loaded correct from blender side
 				 */
 				bool is_builtin = b_image.packed_file() ||
-				                  b_image.source() == BL::Image::source_GENERATED;
+				                  b_image.source() == BL::Image::source_GENERATED ||
+				                  b_image.source() == BL::Image::source_MOVIE;
 
 				if(is_builtin) {
-					/* for builtin images we're using image datablock name to find an image to read pixels from later */
-					image->filename = b_image.name();
+					/* for builtin images we're using image datablock name to find an image to
+					 * read pixels from later
+					 *
+					 * also store frame number as well, so there's no differences in handling
+					 * builtin names for packed images and movies
+					 */
+					int scene_frame = b_scene.frame_current();
+					int image_frame = image_user_frame_number(b_image_node.image_user(), scene_frame);
+					image->filename = b_image.name() + "@" + string_printf("%d", image_frame);
 					image->is_builtin = true;
 				}
 				else {
@@ -542,12 +549,15 @@
 			BL::ShaderNodeTexEnvironment b_env_node(b_node);
 			BL::Image b_image(b_env_node.image());
 			EnvironmentTextureNode *env = new EnvironmentTextureNode();
-			if(b_image && b_image.source() != BL::Image::source_MOVIE) {
+			if(b_image) {
 				bool is_builtin = b_image.packed_file() ||
-				                  b_image.source() == BL::Image::source_GENERATED;
+				                  b_image.source() == BL::Image::source_GENERATED ||
+				                  b_image.source() == BL::Image::source_MOVIE;
 
 				if(is_builtin) {
-					env->filename = b_image.name();
+					int scene_frame = b_scene.frame_current();
+					int image_frame = image_user_frame_number(b_env_node.image_user(), scene_frame);
+					env->filename = b_image.name() + "@" + string_printf("%d", image_frame);
 					env->is_builtin = true;
 				}
 				else {

Modified: trunk/blender/intern/cycles/blender/blender_util.h
===================================================================
--- trunk/blender/intern/cycles/blender/blender_util.h	2013-01-16 14:56:16 UTC (rev 53847)
+++ trunk/blender/intern/cycles/blender/blender_util.h	2013-01-16 17:07:25 UTC (rev 53848)
@@ -33,6 +33,8 @@
 void BLI_timestr(double _time, char *str);
 void BKE_image_user_frame_calc(void *iuser, int cfra, int fieldnr);
 void BKE_image_user_file_path(void *iuser, void *ima, char *path);
+unsigned char *BKE_image_get_pixels_for_frame(void *image, int frame);
+float *BKE_image_get_float_pixels_for_frame(void *image, int frame);
 }
 
 CCL_NAMESPACE_BEGIN
@@ -100,6 +102,22 @@
 	return string(filepath);
 }
 
+static inline int image_user_frame_number(BL::ImageUser iuser, int cfra)
+{
+	BKE_image_user_frame_calc(iuser.ptr.data, cfra, 0);
+	return iuser.frame_current();
+}
+
+static inline unsigned char *image_get_pixels_for_frame(BL::Image image, int frame)
+{
+	return BKE_image_get_pixels_for_frame(image.ptr.data, frame);
+}
+
+static inline float *image_get_float_pixels_for_frame(BL::Image image, int frame)
+{
+	return BKE_image_get_float_pixels_for_frame(image.ptr.data, frame);
+}
+
 /* Utilities */
 
 static inline Transform get_transform(BL::Array<float, 16> array)

Modified: trunk/blender/source/blender/blenkernel/BKE_image.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_image.h	2013-01-16 14:56:16 UTC (rev 53847)
+++ trunk/blender/source/blender/blenkernel/BKE_image.h	2013-01-16 17:07:25 UTC (rev 53848)
@@ -219,6 +219,10 @@
 void BKE_image_buf_fill_checker(unsigned char *rect, float *rect_float, int height, int width);
 void BKE_image_buf_fill_checker_color(unsigned char *rect, float *rect_float, int height, int width);
 
+/* Cycles hookup */
+unsigned char *BKE_image_get_pixels_for_frame(struct Image *image, int frame);
+float *BKE_image_get_float_pixels_for_frame(struct Image *image, int frame);
+
 #ifdef __cplusplus
 }
 #endif

Modified: trunk/blender/source/blender/blenkernel/intern/image.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/image.c	2013-01-16 14:56:16 UTC (rev 53847)
+++ trunk/blender/source/blender/blenkernel/intern/image.c	2013-01-16 17:07:25 UTC (rev 53848)
@@ -3199,3 +3199,57 @@
 	else
 		*aspy = 1.0f;
 }
+
+unsigned char *BKE_image_get_pixels_for_frame(struct Image *image, int frame)
+{
+	ImageUser iuser = {0};
+	void *lock;
+	ImBuf *ibuf;
+	unsigned char *pixels = NULL;
+
+	iuser.framenr = frame;
+	iuser.ok = TRUE;
+
+	ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
+
+	if (ibuf) {
+		pixels = (unsigned char *) ibuf->rect;
+
+		if (pixels)
+			pixels = MEM_dupallocN(pixels);
+
+		BKE_image_release_ibuf(image, ibuf, lock);
+	}
+
+	if (!pixels)
+		return NULL;
+
+	return pixels;
+}
+

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list