From 7a90af7b5a50bac5bb9fa6bf8ec785dac145a90c Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 12 Jan 2013 10:59:13 +0000 Subject: Packed and generated images support for Cycles This commit adds support of packed and generated images for Cycles when using SVM backend. Movies are still not supported. This changes also doesn't touch OSL which is much less trivial to adopt for any images which are not saved to disk. Implementation details: - When adding images to Image Manager is now possible to mark image as builtin. Builtin images will bypass OIIO loader and will use special loading callbacks. - Callbacks are set by Blender Session and they're using C++ RNA interface to obtain needed data (pixels, dimensions, is_float flag). - Image Manager assumes file path is used as reference to a builtin images, but in fact currently image datablock name is used for reference. This makes it easy to find an image in BlendData database. - Added some extra properties to Image RNA: * channels, which denotes actual number of channels in ImBuf. This is needed to treat image's pixels correct (before it wasn't possible because API used internal number of channels for pixels which is in fact doesn't correlate with image depth) * is_float, which is truth if image is stored in float buffer of ImBuf. - Implemented string lookup for C++ RNA collections for cases there's no manual lookup function. OSL is not supported because it used own image loading and filtering routines and there's seems to be no API to feed pre-loaded pixels directly to the library. Think we'll either need to add some API to support such kind of feeding or consider OSL does not have support of packed images at all. Movies are not supported at this moment because of lack of RNA API to load specified frame. It's not difficult to solve, just need to consider what to best here: * Either write some general python interface for ImBuf and use it via C++ API, or * Write a PY API function which will return pixels for given frame, or * Use bad-level BKE_* call Anyway, small steps, further improvements later. Reviewed by Brecht, thanks! --- intern/cycles/blender/blender_session.cpp | 69 +++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) (limited to 'intern/cycles/blender/blender_session.cpp') diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index d0c7c06cbb3..60dfe37c9f8 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -109,6 +109,11 @@ void BlenderSession::create_session() session->reset(buffer_params, session_params.samples); b_engine.use_highlight_tiles(session_params.progressive_refine == false); + + /* setup callbacks for builtin image support */ + scene->image_manager->builtin_image_info_cb = function_bind(&BlenderSession::builtin_image_info, this, _1, _2, _3, _4, _5); + scene->image_manager->builtin_image_pixels_cb = function_bind(&BlenderSession::builtin_image_pixels, this, _1, _2); + scene->image_manager->builtin_image_float_pixels_cb = function_bind(&BlenderSession::builtin_image_float_pixels, this, _1, _2); } void BlenderSession::reset_session(BL::BlendData b_data_, BL::Scene b_scene_) @@ -607,5 +612,69 @@ void BlenderSession::test_cancel() session->progress.set_cancel("Cancelled"); } +void BlenderSession::builtin_image_info(const string &name, bool &is_float, int &width, int &height, int &channels) +{ + BL::Image b_image = b_data.images[name]; + + if(b_image) { + is_float = b_image.is_float(); + width = b_image.size()[0]; + height = b_image.size()[1]; + channels = b_image.channels(); + } + else { + is_float = false; + width = 0; + height = 0; + channels = 0; + } +} + +bool BlenderSession::builtin_image_pixels(const string &name, unsigned char *pixels) +{ + BL::Image b_image = b_data.images[name]; + + if(b_image) { + int width = b_image.size()[0]; + int height = b_image.size()[1]; + int channels = b_image.channels(); + + BL::DynamicArray pixels_array = b_image.pixels(); + float *float_pixels = pixels_array.data; + + /* 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; + } + + return true; + } + + return false; +} + +bool BlenderSession::builtin_image_float_pixels(const string &name, float *pixels) +{ + BL::Image b_image = b_data.images[name]; + + if(b_image) { + int width = b_image.size()[0]; + int height = b_image.size()[1]; + int channels = b_image.channels(); + + BL::DynamicArray pixels_array = b_image.pixels(); + + memcpy(pixels, pixels_array.data, width * height * channels * sizeof(float)); + + return true; + } + + return false; +} + CCL_NAMESPACE_END -- cgit v1.2.3