2011-04-27 11:58:34 +00:00
|
|
|
/*
|
2013-08-18 14:16:15 +00:00
|
|
|
* Copyright 2011-2013 Blender Foundation
|
2011-04-27 11:58:34 +00:00
|
|
|
*
|
2013-08-18 14:16:15 +00:00
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
|
* You may obtain a copy of the License at
|
2011-04-27 11:58:34 +00:00
|
|
|
*
|
2013-08-18 14:16:15 +00:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2011-04-27 11:58:34 +00:00
|
|
|
*
|
2013-08-18 14:16:15 +00:00
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
* See the License for the specific language governing permissions and
|
2014-12-25 02:50:24 +01:00
|
|
|
* limitations under the License.
|
2011-04-27 11:58:34 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef __BLENDER_UTIL_H__
|
|
|
|
|
#define __BLENDER_UTIL_H__
|
|
|
|
|
|
Cycles: Make all #include statements relative to cycles source directory
The idea is to make include statements more explicit and obvious where the
file is coming from, additionally reducing chance of wrong header being
picked up.
For example, it was not obvious whether bvh.h was refferring to builder
or traversal, whenter node.h is a generic graph node or a shader node
and cases like that.
Surely this might look obvious for the active developers, but after some
time of not touching the code it becomes less obvious where file is coming
from.
This was briefly mentioned in T50824 and seems @brecht is fine with such
explicitness, but need to agree with all active developers before committing
this.
Please note that this patch is lacking changes related on GPU/OpenCL
support. This will be solved if/when we all agree this is a good idea to move
forward.
Reviewers: brecht, lukasstockner97, maiself, nirved, dingto, juicyfruit, swerner
Reviewed By: lukasstockner97, maiself, nirved, dingto
Subscribers: brecht
Differential Revision: https://developer.blender.org/D2586
2017-03-28 20:39:14 +02:00
|
|
|
#include "render/mesh.h"
|
2016-09-18 12:04:12 -04:00
|
|
|
|
Cycles: Make all #include statements relative to cycles source directory
The idea is to make include statements more explicit and obvious where the
file is coming from, additionally reducing chance of wrong header being
picked up.
For example, it was not obvious whether bvh.h was refferring to builder
or traversal, whenter node.h is a generic graph node or a shader node
and cases like that.
Surely this might look obvious for the active developers, but after some
time of not touching the code it becomes less obvious where file is coming
from.
This was briefly mentioned in T50824 and seems @brecht is fine with such
explicitness, but need to agree with all active developers before committing
this.
Please note that this patch is lacking changes related on GPU/OpenCL
support. This will be solved if/when we all agree this is a good idea to move
forward.
Reviewers: brecht, lukasstockner97, maiself, nirved, dingto, juicyfruit, swerner
Reviewed By: lukasstockner97, maiself, nirved, dingto
Subscribers: brecht
Differential Revision: https://developer.blender.org/D2586
2017-03-28 20:39:14 +02:00
|
|
|
#include "util/util_algorithm.h"
|
|
|
|
|
#include "util/util_map.h"
|
|
|
|
|
#include "util/util_path.h"
|
|
|
|
|
#include "util/util_set.h"
|
|
|
|
|
#include "util/util_transform.h"
|
|
|
|
|
#include "util/util_types.h"
|
|
|
|
|
#include "util/util_vector.h"
|
2011-04-27 11:58:34 +00:00
|
|
|
|
2011-11-08 14:10:33 +00:00
|
|
|
/* Hacks to hook into Blender API
|
2012-06-09 17:22:52 +00:00
|
|
|
* todo: clean this up ... */
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
|
extern "C" {
|
2015-06-30 14:47:31 +10:00
|
|
|
size_t BLI_timecode_string_from_time_simple(char *str, size_t maxlen, double time_seconds);
|
2012-06-10 07:35:45 +00:00
|
|
|
void BKE_image_user_frame_calc(void *iuser, int cfra, int fieldnr);
|
|
|
|
|
void BKE_image_user_file_path(void *iuser, void *ima, char *path);
|
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.
2013-01-16 17:07:25 +00:00
|
|
|
unsigned char *BKE_image_get_pixels_for_frame(void *image, int frame);
|
|
|
|
|
float *BKE_image_get_float_pixels_for_frame(void *image, int frame);
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CCL_NAMESPACE_BEGIN
|
|
|
|
|
|
2014-02-12 23:13:45 +01:00
|
|
|
void python_thread_state_save(void **python_thread_state);
|
|
|
|
|
void python_thread_state_restore(void **python_thread_state);
|
2014-02-12 21:49:34 +01:00
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static inline BL::Mesh object_to_mesh(BL::BlendData& data,
|
|
|
|
|
BL::Object& object,
|
|
|
|
|
BL::Scene& scene,
|
2017-11-22 10:52:39 -02:00
|
|
|
BL::ViewLayer view_layer,
|
2016-01-30 14:18:29 +01:00
|
|
|
bool apply_modifiers,
|
|
|
|
|
bool render,
|
2016-07-16 19:42:28 -04:00
|
|
|
bool calc_undeformed,
|
2017-01-11 16:23:54 +01:00
|
|
|
Mesh::SubdivisionType subdivision_type)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
2017-07-20 23:51:15 +02:00
|
|
|
bool subsurf_mod_show_render = false;
|
|
|
|
|
bool subsurf_mod_show_viewport = false;
|
2016-07-16 19:56:45 -04:00
|
|
|
|
2017-01-11 16:23:54 +01:00
|
|
|
if(subdivision_type != Mesh::SUBDIVISION_NONE) {
|
2016-07-16 19:56:45 -04:00
|
|
|
BL::Modifier subsurf_mod = object.modifiers[object.modifiers.length()-1];
|
|
|
|
|
|
|
|
|
|
subsurf_mod_show_render = subsurf_mod.show_render();
|
2016-09-18 22:11:07 -04:00
|
|
|
subsurf_mod_show_viewport = subsurf_mod.show_viewport();
|
2016-07-16 19:56:45 -04:00
|
|
|
|
|
|
|
|
subsurf_mod.show_render(false);
|
|
|
|
|
subsurf_mod.show_viewport(false);
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-22 10:52:39 -02:00
|
|
|
BL::Mesh me = data.meshes.new_from_object(scene, view_layer, object, apply_modifiers, (render)? 2: 1, false, calc_undeformed);
|
2016-07-16 19:56:45 -04:00
|
|
|
|
2017-01-11 16:23:54 +01:00
|
|
|
if(subdivision_type != Mesh::SUBDIVISION_NONE) {
|
2016-07-16 19:56:45 -04:00
|
|
|
BL::Modifier subsurf_mod = object.modifiers[object.modifiers.length()-1];
|
|
|
|
|
|
|
|
|
|
subsurf_mod.show_render(subsurf_mod_show_render);
|
|
|
|
|
subsurf_mod.show_viewport(subsurf_mod_show_viewport);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-28 00:15:15 +05:00
|
|
|
if((bool)me) {
|
|
|
|
|
if(me.use_auto_smooth()) {
|
2017-01-11 16:32:57 +01:00
|
|
|
if(subdivision_type == Mesh::SUBDIVISION_CATMULL_CLARK) {
|
|
|
|
|
me.calc_normals_split();
|
|
|
|
|
}
|
|
|
|
|
else {
|
2017-02-22 10:53:28 +01:00
|
|
|
me.split_faces(false);
|
2017-01-11 16:32:57 +01:00
|
|
|
}
|
2014-04-21 23:41:39 +02:00
|
|
|
}
|
2017-01-11 16:23:54 +01:00
|
|
|
if(subdivision_type == Mesh::SUBDIVISION_NONE) {
|
2016-07-16 19:42:28 -04:00
|
|
|
me.calc_tessface(true);
|
|
|
|
|
}
|
2014-04-13 12:51:06 +02:00
|
|
|
}
|
|
|
|
|
return me;
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static inline void colorramp_to_array(BL::ColorRamp& ramp,
|
2016-05-08 01:54:35 +02:00
|
|
|
array<float3>& ramp_color,
|
|
|
|
|
array<float>& ramp_alpha,
|
2016-01-30 14:18:29 +01:00
|
|
|
int size)
|
2012-03-26 12:45:14 +00:00
|
|
|
{
|
2016-05-08 01:54:35 +02:00
|
|
|
ramp_color.resize(size);
|
|
|
|
|
ramp_alpha.resize(size);
|
|
|
|
|
|
2012-03-26 12:45:14 +00:00
|
|
|
for(int i = 0; i < size; i++) {
|
|
|
|
|
float color[4];
|
|
|
|
|
|
2014-05-03 07:22:14 +10:00
|
|
|
ramp.evaluate((float)i/(float)(size-1), color);
|
2016-05-08 01:54:35 +02:00
|
|
|
ramp_color[i] = make_float3(color[0], color[1], color[2]);
|
|
|
|
|
ramp_alpha[i] = color[3];
|
2012-03-26 12:45:14 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-04 20:17:25 +05:00
|
|
|
static inline void curvemap_minmax_curve(/*const*/ BL::CurveMap& curve,
|
|
|
|
|
float *min_x,
|
|
|
|
|
float *max_x)
|
|
|
|
|
{
|
|
|
|
|
*min_x = min(*min_x, curve.points[0].location()[0]);
|
|
|
|
|
*max_x = max(*max_x, curve.points[curve.points.length() - 1].location()[0]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void curvemapping_minmax(/*const*/ BL::CurveMapping& cumap,
|
|
|
|
|
bool rgb_curve,
|
|
|
|
|
float *min_x,
|
|
|
|
|
float *max_x)
|
|
|
|
|
{
|
|
|
|
|
/* const int num_curves = cumap.curves.length(); */ /* Gives linking error so far. */
|
|
|
|
|
const int num_curves = rgb_curve? 4: 3;
|
|
|
|
|
*min_x = FLT_MAX;
|
|
|
|
|
*max_x = -FLT_MAX;
|
|
|
|
|
for(int i = 0; i < num_curves; ++i) {
|
|
|
|
|
BL::CurveMap map(cumap.curves[i]);
|
|
|
|
|
curvemap_minmax_curve(map, min_x, max_x);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static inline void curvemapping_to_array(BL::CurveMapping& cumap,
|
2016-05-08 00:28:21 +02:00
|
|
|
array<float>& data,
|
2016-01-30 14:18:29 +01:00
|
|
|
int size)
|
2015-10-27 19:00:51 +05:00
|
|
|
{
|
|
|
|
|
cumap.update();
|
|
|
|
|
BL::CurveMap curve = cumap.curves[0];
|
2016-05-08 00:28:21 +02:00
|
|
|
data.resize(size);
|
2015-10-27 19:00:51 +05:00
|
|
|
for(int i = 0; i < size; i++) {
|
|
|
|
|
float t = (float)i/(float)(size-1);
|
|
|
|
|
data[i] = curve.evaluate(t);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static inline void curvemapping_color_to_array(BL::CurveMapping& cumap,
|
2016-05-08 01:54:35 +02:00
|
|
|
array<float3>& data,
|
2015-12-04 20:17:25 +05:00
|
|
|
int size,
|
|
|
|
|
bool rgb_curve)
|
2012-12-11 14:39:37 +00:00
|
|
|
{
|
2015-12-04 20:17:25 +05:00
|
|
|
float min_x = 0.0f, max_x = 1.0f;
|
2015-12-15 16:23:33 +05:00
|
|
|
|
|
|
|
|
/* TODO(sergey): There is no easy way to automatically guess what is
|
|
|
|
|
* the range to be used here for the case when mapping is applied on
|
|
|
|
|
* top of another mapping (i.e. R curve applied on top of common
|
|
|
|
|
* one).
|
|
|
|
|
*
|
|
|
|
|
* Using largest possible range form all curves works correct for the
|
|
|
|
|
* cases like vector curves and should be good enough heuristic for
|
|
|
|
|
* the color curves as well.
|
|
|
|
|
*
|
|
|
|
|
* There might be some better estimations here tho.
|
|
|
|
|
*/
|
|
|
|
|
curvemapping_minmax(cumap, rgb_curve, &min_x, &max_x);
|
|
|
|
|
|
2015-12-04 20:17:25 +05:00
|
|
|
const float range_x = max_x - min_x;
|
|
|
|
|
|
2012-12-11 14:39:37 +00:00
|
|
|
cumap.update();
|
|
|
|
|
|
|
|
|
|
BL::CurveMap mapR = cumap.curves[0];
|
|
|
|
|
BL::CurveMap mapG = cumap.curves[1];
|
|
|
|
|
BL::CurveMap mapB = cumap.curves[2];
|
|
|
|
|
|
2016-05-08 01:54:35 +02:00
|
|
|
data.resize(size);
|
|
|
|
|
|
2012-12-11 14:39:37 +00:00
|
|
|
if(rgb_curve) {
|
|
|
|
|
BL::CurveMap mapI = cumap.curves[3];
|
|
|
|
|
for(int i = 0; i < size; i++) {
|
2017-04-04 13:47:18 +02:00
|
|
|
const float t = min_x + (float)i/(float)(size-1) * range_x;
|
|
|
|
|
data[i] = make_float3(mapR.evaluate(mapI.evaluate(t)),
|
|
|
|
|
mapG.evaluate(mapI.evaluate(t)),
|
|
|
|
|
mapB.evaluate(mapI.evaluate(t)));
|
2012-12-11 14:39:37 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
for(int i = 0; i < size; i++) {
|
2015-12-04 20:17:25 +05:00
|
|
|
float t = min_x + (float)i/(float)(size-1) * range_x;
|
2017-04-04 13:47:18 +02:00
|
|
|
data[i] = make_float3(mapR.evaluate(t),
|
|
|
|
|
mapG.evaluate(t),
|
|
|
|
|
mapB.evaluate(t));
|
2012-12-11 14:39:37 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static inline bool BKE_object_is_modified(BL::Object& self,
|
|
|
|
|
BL::Scene& scene,
|
|
|
|
|
bool preview)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
2012-10-22 17:34:16 +00:00
|
|
|
return self.is_modified(scene, (preview)? (1<<0): (1<<1))? true: false;
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static inline bool BKE_object_is_deform_modified(BL::Object& self,
|
|
|
|
|
BL::Scene& scene,
|
|
|
|
|
bool preview)
|
2012-04-30 12:49:26 +00:00
|
|
|
{
|
2012-10-22 17:34:16 +00:00
|
|
|
return self.is_deform_modified(scene, (preview)? (1<<0): (1<<1))? true: false;
|
2012-04-30 12:49:26 +00:00
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static inline int render_resolution_x(BL::RenderSettings& b_render)
|
2013-05-16 21:53:21 +00:00
|
|
|
{
|
|
|
|
|
return b_render.resolution_x()*b_render.resolution_percentage()/100;
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static inline int render_resolution_y(BL::RenderSettings& b_render)
|
2013-05-16 21:53:21 +00:00
|
|
|
{
|
|
|
|
|
return b_render.resolution_y()*b_render.resolution_percentage()/100;
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static inline string image_user_file_path(BL::ImageUser& iuser,
|
|
|
|
|
BL::Image& ima,
|
|
|
|
|
int cfra)
|
2012-06-04 19:38:33 +00:00
|
|
|
{
|
|
|
|
|
char filepath[1024];
|
2012-06-10 07:35:45 +00:00
|
|
|
BKE_image_user_frame_calc(iuser.ptr.data, cfra, 0);
|
|
|
|
|
BKE_image_user_file_path(iuser.ptr.data, ima.ptr.data, filepath);
|
2012-06-04 19:38:33 +00:00
|
|
|
return string(filepath);
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static inline int image_user_frame_number(BL::ImageUser& iuser, int cfra)
|
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.
2013-01-16 17:07:25 +00:00
|
|
|
{
|
|
|
|
|
BKE_image_user_frame_calc(iuser.ptr.data, cfra, 0);
|
|
|
|
|
return iuser.frame_current();
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static inline unsigned char *image_get_pixels_for_frame(BL::Image& image,
|
|
|
|
|
int frame)
|
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.
2013-01-16 17:07:25 +00:00
|
|
|
{
|
|
|
|
|
return BKE_image_get_pixels_for_frame(image.ptr.data, frame);
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static inline float *image_get_float_pixels_for_frame(BL::Image& image,
|
|
|
|
|
int frame)
|
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.
2013-01-16 17:07:25 +00:00
|
|
|
{
|
|
|
|
|
return BKE_image_get_float_pixels_for_frame(image.ptr.data, frame);
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
/* Utilities */
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static inline Transform get_transform(const BL::Array<float, 16>& array)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
2018-03-08 06:48:14 +01:00
|
|
|
ProjectionTransform projection;
|
2011-04-27 11:58:34 +00:00
|
|
|
|
2018-03-08 06:48:14 +01:00
|
|
|
/* We assume both types to be just 16 floats, and transpose because blender
|
|
|
|
|
* use column major matrix order while we use row major. */
|
|
|
|
|
memcpy(&projection, &array, sizeof(float)*16);
|
|
|
|
|
projection = projection_transpose(projection);
|
2011-04-27 11:58:34 +00:00
|
|
|
|
2018-03-08 06:48:14 +01:00
|
|
|
/* Drop last row, matrix is assumed to be affine transform. */
|
|
|
|
|
return projection_to_transform(projection);
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static inline float2 get_float2(const BL::Array<float, 2>& array)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
|
|
|
|
return make_float2(array[0], array[1]);
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static inline float3 get_float3(const BL::Array<float, 2>& array)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
|
|
|
|
return make_float3(array[0], array[1], 0.0f);
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static inline float3 get_float3(const BL::Array<float, 3>& array)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
|
|
|
|
return make_float3(array[0], array[1], array[2]);
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static inline float3 get_float3(const BL::Array<float, 4>& array)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
|
|
|
|
return make_float3(array[0], array[1], array[2]);
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static inline float4 get_float4(const BL::Array<float, 4>& array)
|
2012-08-31 19:38:59 +00:00
|
|
|
{
|
|
|
|
|
return make_float4(array[0], array[1], array[2], array[3]);
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static inline int3 get_int3(const BL::Array<int, 3>& array)
|
2014-03-29 13:03:48 +01:00
|
|
|
{
|
|
|
|
|
return make_int3(array[0], array[1], array[2]);
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static inline int4 get_int4(const BL::Array<int, 4>& array)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
|
|
|
|
return make_int4(array[0], array[1], array[2], array[3]);
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static inline uint get_layer(const BL::Array<int, 20>& array)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
|
|
|
|
uint layer = 0;
|
|
|
|
|
|
|
|
|
|
for(uint i = 0; i < 20; i++)
|
|
|
|
|
if(array[i])
|
|
|
|
|
layer |= (1 << i);
|
2017-05-30 09:43:43 +02:00
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
return layer;
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static inline uint get_layer(const BL::Array<int, 20>& array,
|
|
|
|
|
const BL::Array<int, 8>& local_array,
|
2015-10-11 19:59:51 +05:00
|
|
|
bool is_light = false,
|
2017-11-22 10:52:39 -02:00
|
|
|
uint view_layers = (1 << 20) - 1)
|
2012-06-25 11:43:22 +00:00
|
|
|
{
|
|
|
|
|
uint layer = 0;
|
|
|
|
|
|
|
|
|
|
for(uint i = 0; i < 20; i++)
|
|
|
|
|
if(array[i])
|
|
|
|
|
layer |= (1 << i);
|
|
|
|
|
|
|
|
|
|
if(is_light) {
|
2015-10-11 19:59:51 +05:00
|
|
|
/* Consider light is visible if it was visible without layer
|
|
|
|
|
* override, which matches behavior of Blender Internal.
|
|
|
|
|
*/
|
2017-11-22 10:52:39 -02:00
|
|
|
if(layer & view_layers) {
|
2015-10-11 19:59:51 +05:00
|
|
|
for(uint i = 0; i < 8; i++)
|
|
|
|
|
layer |= (1 << (20+i));
|
|
|
|
|
}
|
2012-06-25 11:43:22 +00:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
for(uint i = 0; i < 8; i++)
|
|
|
|
|
if(local_array[i])
|
|
|
|
|
layer |= (1 << (20+i));
|
|
|
|
|
}
|
2012-09-04 13:29:07 +00:00
|
|
|
|
2012-06-25 11:43:22 +00:00
|
|
|
return layer;
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-09 17:22:52 +00:00
|
|
|
static inline float3 get_float3(PointerRNA& ptr, const char *name)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
|
|
|
|
float3 f;
|
|
|
|
|
RNA_float_get_array(&ptr, name, &f.x);
|
|
|
|
|
return f;
|
2012-06-09 17:22:52 +00:00
|
|
|
}
|
2013-03-18 16:34:57 +00:00
|
|
|
|
|
|
|
|
static inline void set_float3(PointerRNA& ptr, const char *name, float3 value)
|
|
|
|
|
{
|
|
|
|
|
RNA_float_set_array(&ptr, name, &value.x);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline float4 get_float4(PointerRNA& ptr, const char *name)
|
|
|
|
|
{
|
|
|
|
|
float4 f;
|
|
|
|
|
RNA_float_get_array(&ptr, name, &f.x);
|
|
|
|
|
return f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void set_float4(PointerRNA& ptr, const char *name, float4 value)
|
|
|
|
|
{
|
|
|
|
|
RNA_float_set_array(&ptr, name, &value.x);
|
|
|
|
|
}
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
|
static inline bool get_boolean(PointerRNA& ptr, const char *name)
|
|
|
|
|
{
|
2011-05-03 18:29:11 +00:00
|
|
|
return RNA_boolean_get(&ptr, name)? true: false;
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
static inline void set_boolean(PointerRNA& ptr, const char *name, bool value)
|
|
|
|
|
{
|
|
|
|
|
RNA_boolean_set(&ptr, name, (int)value);
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
static inline float get_float(PointerRNA& ptr, const char *name)
|
|
|
|
|
{
|
|
|
|
|
return RNA_float_get(&ptr, name);
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
static inline void set_float(PointerRNA& ptr, const char *name, float value)
|
|
|
|
|
{
|
|
|
|
|
RNA_float_set(&ptr, name, value);
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
static inline int get_int(PointerRNA& ptr, const char *name)
|
|
|
|
|
{
|
|
|
|
|
return RNA_int_get(&ptr, name);
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
static inline void set_int(PointerRNA& ptr, const char *name, int value)
|
|
|
|
|
{
|
|
|
|
|
RNA_int_set(&ptr, name, value);
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-10 15:09:45 +01:00
|
|
|
/* Get a RNA enum value with sanity check: if the RNA value is above num_values
|
|
|
|
|
* the function will return a fallback default value.
|
|
|
|
|
*
|
|
|
|
|
* NOTE: This function assumes that RNA enum values are a continuous sequence
|
|
|
|
|
* from 0 to num_values-1. Be careful to use it with enums where some values are
|
|
|
|
|
* deprecated!
|
|
|
|
|
*/
|
|
|
|
|
static inline int get_enum(PointerRNA& ptr,
|
|
|
|
|
const char *name,
|
|
|
|
|
int num_values = -1,
|
|
|
|
|
int default_value = -1)
|
|
|
|
|
{
|
|
|
|
|
int value = RNA_enum_get(&ptr, name);
|
|
|
|
|
if(num_values != -1 && value >= num_values) {
|
|
|
|
|
assert(default_value != -1);
|
|
|
|
|
value = default_value;
|
|
|
|
|
}
|
|
|
|
|
return value;
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline string get_enum_identifier(PointerRNA& ptr, const char *name)
|
|
|
|
|
{
|
|
|
|
|
PropertyRNA *prop = RNA_struct_find_property(&ptr, name);
|
|
|
|
|
const char *identifier = "";
|
|
|
|
|
int value = RNA_property_enum_get(&ptr, prop);
|
|
|
|
|
|
|
|
|
|
RNA_property_enum_identifier(NULL, &ptr, prop, value, &identifier);
|
|
|
|
|
|
|
|
|
|
return string(identifier);
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
static inline void set_enum(PointerRNA& ptr, const char *name, int value)
|
|
|
|
|
{
|
|
|
|
|
RNA_enum_set(&ptr, name, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void set_enum(PointerRNA& ptr, const char *name, const string &identifier)
|
|
|
|
|
{
|
2016-01-07 21:52:54 +01:00
|
|
|
RNA_enum_set_identifier(NULL, &ptr, name, identifier.c_str());
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline string get_string(PointerRNA& ptr, const char *name)
|
|
|
|
|
{
|
|
|
|
|
char cstrbuf[1024];
|
|
|
|
|
char *cstr = RNA_string_get_alloc(&ptr, name, cstrbuf, sizeof(cstrbuf));
|
|
|
|
|
string str(cstr);
|
2015-03-28 00:15:15 +05:00
|
|
|
if(cstr != cstrbuf)
|
2013-03-18 16:34:57 +00:00
|
|
|
MEM_freeN(cstr);
|
2017-05-30 09:43:43 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
return str;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void set_string(PointerRNA& ptr, const char *name, const string &value)
|
|
|
|
|
{
|
|
|
|
|
RNA_string_set(&ptr, name, value.c_str());
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
/* Relative Paths */
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static inline string blender_absolute_path(BL::BlendData& b_data,
|
|
|
|
|
BL::ID& b_id,
|
|
|
|
|
const string& path)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
|
|
|
|
if(path.size() >= 2 && path[0] == '/' && path[1] == '/') {
|
2011-11-16 16:10:11 +00:00
|
|
|
string dirname;
|
2017-05-30 09:43:43 +02:00
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
if(b_id.library()) {
|
|
|
|
|
BL::ID b_library_id(b_id.library());
|
|
|
|
|
dirname = blender_absolute_path(b_data,
|
|
|
|
|
b_library_id,
|
|
|
|
|
b_id.library().filepath());
|
|
|
|
|
}
|
2011-11-16 16:10:11 +00:00
|
|
|
else
|
|
|
|
|
dirname = b_data.filepath();
|
|
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
return path_join(path_dirname(dirname), path.substr(2));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return path;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-03 12:31:05 +00:00
|
|
|
/* Texture Space */
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static inline void mesh_texture_space(BL::Mesh& b_mesh,
|
|
|
|
|
float3& loc,
|
|
|
|
|
float3& size)
|
2013-01-03 12:31:05 +00:00
|
|
|
{
|
|
|
|
|
loc = get_float3(b_mesh.texspace_location());
|
|
|
|
|
size = get_float3(b_mesh.texspace_size());
|
|
|
|
|
|
|
|
|
|
if(size.x != 0.0f) size.x = 0.5f/size.x;
|
|
|
|
|
if(size.y != 0.0f) size.y = 0.5f/size.y;
|
|
|
|
|
if(size.z != 0.0f) size.z = 0.5f/size.z;
|
|
|
|
|
|
|
|
|
|
loc = loc*size - make_float3(0.5f, 0.5f, 0.5f);
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-08 04:04:52 +01:00
|
|
|
/* Object motion steps, returns 0 if no motion blur needed. */
|
|
|
|
|
static inline uint object_motion_steps(BL::Object& b_parent, BL::Object& b_ob)
|
2014-03-29 13:03:47 +01:00
|
|
|
{
|
2018-03-08 04:04:52 +01:00
|
|
|
/* Get motion enabled and steps from object itself. */
|
2014-03-29 13:03:47 +01:00
|
|
|
PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
|
|
|
|
|
bool use_motion = get_boolean(cobject, "use_motion_blur");
|
2018-03-08 04:04:52 +01:00
|
|
|
if(!use_motion) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint steps = max(1, get_int(cobject, "motion_steps"));
|
|
|
|
|
|
|
|
|
|
/* Also check parent object, so motion blur and steps can be
|
|
|
|
|
* controlled by dupligroup duplicator for linked groups. */
|
|
|
|
|
if(b_parent.ptr.data != b_ob.ptr.data) {
|
2015-06-12 13:54:17 +02:00
|
|
|
PointerRNA parent_cobject = RNA_pointer_get(&b_parent.ptr, "cycles");
|
|
|
|
|
use_motion &= get_boolean(parent_cobject, "use_motion_blur");
|
2014-03-29 13:03:47 +01:00
|
|
|
|
2018-03-08 04:04:52 +01:00
|
|
|
if(!use_motion) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
steps = max(steps, get_int(parent_cobject, "motion_steps"));
|
|
|
|
|
}
|
2014-03-29 13:03:47 +01:00
|
|
|
|
2018-03-08 04:04:52 +01:00
|
|
|
/* Use uneven number of steps so we get one keyframe at the current frame,
|
|
|
|
|
* and use 2^(steps - 1) so objects with more/fewer steps still have samples
|
|
|
|
|
* at the same times, to avoid sampling at many different times. */
|
2014-03-29 13:03:47 +01:00
|
|
|
return (2 << (steps - 1)) + 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* object uses deformation motion blur */
|
2016-01-30 14:18:29 +01:00
|
|
|
static inline bool object_use_deform_motion(BL::Object& b_parent,
|
|
|
|
|
BL::Object& b_ob)
|
2014-03-29 13:03:47 +01:00
|
|
|
{
|
|
|
|
|
PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
|
|
|
|
|
bool use_deform_motion = get_boolean(cobject, "use_deform_motion");
|
2015-06-12 13:54:17 +02:00
|
|
|
/* If motion blur is enabled for the object we also check
|
|
|
|
|
* whether it's enabled for the parent object as well.
|
|
|
|
|
*
|
|
|
|
|
* This way we can control motion blur from the dupligroup
|
|
|
|
|
* duplicator much easier.
|
|
|
|
|
*/
|
|
|
|
|
if(use_deform_motion && b_parent.ptr.data != b_ob.ptr.data) {
|
|
|
|
|
PointerRNA parent_cobject = RNA_pointer_get(&b_parent.ptr, "cycles");
|
|
|
|
|
use_deform_motion &= get_boolean(parent_cobject, "use_deform_motion");
|
|
|
|
|
}
|
2014-03-29 13:03:47 +01:00
|
|
|
return use_deform_motion;
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
static inline BL::SmokeDomainSettings object_smoke_domain_find(BL::Object& b_ob)
|
2014-03-29 13:03:48 +01:00
|
|
|
{
|
|
|
|
|
BL::Object::modifiers_iterator b_mod;
|
|
|
|
|
|
|
|
|
|
for(b_ob.modifiers.begin(b_mod); b_mod != b_ob.modifiers.end(); ++b_mod) {
|
2015-03-28 00:15:15 +05:00
|
|
|
if(b_mod->is_a(&RNA_SmokeModifier)) {
|
2014-03-29 13:03:48 +01:00
|
|
|
BL::SmokeModifier b_smd(*b_mod);
|
|
|
|
|
|
|
|
|
|
if(b_smd.smoke_type() == BL::SmokeModifier::smoke_type_DOMAIN)
|
|
|
|
|
return b_smd.domain_settings();
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-05-30 09:43:43 +02:00
|
|
|
|
2014-03-29 13:03:48 +01:00
|
|
|
return BL::SmokeDomainSettings(PointerRNA_NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-16 18:56:59 +02:00
|
|
|
static inline BL::DomainFluidSettings object_fluid_domain_find(BL::Object b_ob)
|
|
|
|
|
{
|
|
|
|
|
BL::Object::modifiers_iterator b_mod;
|
|
|
|
|
|
|
|
|
|
for(b_ob.modifiers.begin(b_mod); b_mod != b_ob.modifiers.end(); ++b_mod) {
|
|
|
|
|
if(b_mod->is_a(&RNA_FluidSimulationModifier)) {
|
|
|
|
|
BL::FluidSimulationModifier b_fmd(*b_mod);
|
|
|
|
|
BL::FluidSettings fss = b_fmd.settings();
|
|
|
|
|
|
|
|
|
|
if(fss.type() == BL::FluidSettings::type_DOMAIN)
|
|
|
|
|
return (BL::DomainFluidSettings)b_fmd.settings();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return BL::DomainFluidSettings(PointerRNA_NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-18 12:04:12 -04:00
|
|
|
static inline Mesh::SubdivisionType object_subdivision_type(BL::Object& b_ob, bool preview, bool experimental)
|
|
|
|
|
{
|
|
|
|
|
PointerRNA cobj = RNA_pointer_get(&b_ob.ptr, "cycles");
|
|
|
|
|
|
|
|
|
|
if(cobj.data && b_ob.modifiers.length() > 0 && experimental) {
|
|
|
|
|
BL::Modifier mod = b_ob.modifiers[b_ob.modifiers.length()-1];
|
|
|
|
|
bool enabled = preview ? mod.show_viewport() : mod.show_render();
|
|
|
|
|
|
|
|
|
|
if(enabled && mod.type() == BL::Modifier::type_SUBSURF && RNA_boolean_get(&cobj, "use_adaptive_subdivision")) {
|
|
|
|
|
BL::SubsurfModifier subsurf(mod);
|
|
|
|
|
|
|
|
|
|
if(subsurf.subdivision_type() == BL::SubsurfModifier::subdivision_type_CATMULL_CLARK) {
|
|
|
|
|
return Mesh::SUBDIVISION_CATMULL_CLARK;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
return Mesh::SUBDIVISION_LINEAR;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Mesh::SUBDIVISION_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
/* ID Map
|
|
|
|
|
*
|
|
|
|
|
* Utility class to keep in sync with blender data.
|
|
|
|
|
* Used for objects, meshes, lights and shaders. */
|
|
|
|
|
|
|
|
|
|
template<typename K, typename T>
|
|
|
|
|
class id_map {
|
|
|
|
|
public:
|
|
|
|
|
id_map(vector<T*> *scene_data_)
|
|
|
|
|
{
|
|
|
|
|
scene_data = scene_data_;
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
T *find(const BL::ID& id)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
|
|
|
|
return find(id.ptr.id.data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
T *find(const K& key)
|
|
|
|
|
{
|
|
|
|
|
if(b_map.find(key) != b_map.end()) {
|
|
|
|
|
T *data = b_map[key];
|
|
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
void set_recalc(const BL::ID& id)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
|
|
|
|
b_recalc.insert(id.ptr.data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool has_recalc()
|
|
|
|
|
{
|
|
|
|
|
return !(b_recalc.empty());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void pre_sync()
|
|
|
|
|
{
|
|
|
|
|
used_set.clear();
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
bool sync(T **r_data, const BL::ID& id)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
2011-05-31 10:41:01 +00:00
|
|
|
return sync(r_data, id, id, id.ptr.id.data);
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
2016-01-30 14:18:29 +01:00
|
|
|
bool sync(T **r_data, const BL::ID& id, const BL::ID& parent, const K& key)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
|
|
|
|
T *data = find(key);
|
|
|
|
|
bool recalc;
|
|
|
|
|
|
|
|
|
|
if(!data) {
|
|
|
|
|
/* add data if it didn't exist yet */
|
|
|
|
|
data = new T();
|
|
|
|
|
scene_data->push_back(data);
|
|
|
|
|
b_map[key] = data;
|
|
|
|
|
recalc = true;
|
|
|
|
|
}
|
2011-05-31 10:41:01 +00:00
|
|
|
else {
|
2011-04-27 11:58:34 +00:00
|
|
|
recalc = (b_recalc.find(id.ptr.data) != b_recalc.end());
|
2011-05-31 10:41:01 +00:00
|
|
|
if(parent.ptr.data)
|
|
|
|
|
recalc = recalc || (b_recalc.find(parent.ptr.data) != b_recalc.end());
|
|
|
|
|
}
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
|
used(data);
|
|
|
|
|
|
|
|
|
|
*r_data = data;
|
|
|
|
|
return recalc;
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-08 16:35:28 +00:00
|
|
|
bool is_used(const K& key)
|
|
|
|
|
{
|
|
|
|
|
T *data = find(key);
|
2012-11-09 03:08:02 +00:00
|
|
|
return (data) ? used_set.find(data) != used_set.end() : false;
|
2012-11-08 16:35:28 +00:00
|
|
|
}
|
|
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
void used(T *data)
|
|
|
|
|
{
|
|
|
|
|
/* tag data as still in use */
|
|
|
|
|
used_set.insert(data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void set_default(T *data)
|
|
|
|
|
{
|
|
|
|
|
b_map[NULL] = data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool post_sync(bool do_delete = true)
|
|
|
|
|
{
|
|
|
|
|
/* remove unused data */
|
|
|
|
|
vector<T*> new_scene_data;
|
|
|
|
|
typename vector<T*>::iterator it;
|
|
|
|
|
bool deleted = false;
|
|
|
|
|
|
|
|
|
|
for(it = scene_data->begin(); it != scene_data->end(); it++) {
|
|
|
|
|
T *data = *it;
|
|
|
|
|
|
|
|
|
|
if(do_delete && used_set.find(data) == used_set.end()) {
|
|
|
|
|
delete data;
|
|
|
|
|
deleted = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
new_scene_data.push_back(data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*scene_data = new_scene_data;
|
|
|
|
|
|
|
|
|
|
/* update mapping */
|
|
|
|
|
map<K, T*> new_map;
|
|
|
|
|
typedef pair<const K, T*> TMapPair;
|
|
|
|
|
typename map<K, T*>::iterator jt;
|
|
|
|
|
|
|
|
|
|
for(jt = b_map.begin(); jt != b_map.end(); jt++) {
|
|
|
|
|
TMapPair& pair = *jt;
|
|
|
|
|
|
|
|
|
|
if(used_set.find(pair.second) != used_set.end())
|
|
|
|
|
new_map[pair.first] = pair.second;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
used_set.clear();
|
|
|
|
|
b_recalc.clear();
|
|
|
|
|
b_map = new_map;
|
|
|
|
|
|
|
|
|
|
return deleted;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
vector<T*> *scene_data;
|
|
|
|
|
map<K, T*> b_map;
|
|
|
|
|
set<T*> used_set;
|
|
|
|
|
set<void*> b_recalc;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Object Key */
|
|
|
|
|
|
2016-08-14 15:33:21 +02:00
|
|
|
enum { OBJECT_PERSISTENT_ID_SIZE = 16 };
|
2012-11-08 16:35:28 +00:00
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
struct ObjectKey {
|
|
|
|
|
void *parent;
|
2012-11-08 16:35:28 +00:00
|
|
|
int id[OBJECT_PERSISTENT_ID_SIZE];
|
2011-04-27 11:58:34 +00:00
|
|
|
void *ob;
|
|
|
|
|
|
2012-11-08 16:35:28 +00:00
|
|
|
ObjectKey(void *parent_, int id_[OBJECT_PERSISTENT_ID_SIZE], void *ob_)
|
|
|
|
|
: parent(parent_), ob(ob_)
|
|
|
|
|
{
|
|
|
|
|
if(id_)
|
|
|
|
|
memcpy(id, id_, sizeof(id));
|
|
|
|
|
else
|
|
|
|
|
memset(id, 0, sizeof(id));
|
|
|
|
|
}
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
|
bool operator<(const ObjectKey& k) const
|
2012-11-08 16:35:28 +00:00
|
|
|
{
|
2012-12-04 07:48:09 +00:00
|
|
|
if(ob < k.ob) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if(ob == k.ob) {
|
|
|
|
|
if(parent < k.parent)
|
|
|
|
|
return true;
|
|
|
|
|
else if(parent == k.parent)
|
|
|
|
|
return memcmp(id, k.id, sizeof(id)) < 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
2012-11-08 16:35:28 +00:00
|
|
|
}
|
2011-04-27 11:58:34 +00:00
|
|
|
};
|
|
|
|
|
|
2012-12-04 07:48:09 +00:00
|
|
|
/* Particle System Key */
|
|
|
|
|
|
2012-08-31 17:27:08 +00:00
|
|
|
struct ParticleSystemKey {
|
|
|
|
|
void *ob;
|
2012-11-08 16:35:28 +00:00
|
|
|
int id[OBJECT_PERSISTENT_ID_SIZE];
|
2012-08-31 17:27:08 +00:00
|
|
|
|
2012-11-08 16:35:28 +00:00
|
|
|
ParticleSystemKey(void *ob_, int id_[OBJECT_PERSISTENT_ID_SIZE])
|
|
|
|
|
: ob(ob_)
|
|
|
|
|
{
|
|
|
|
|
if(id_)
|
|
|
|
|
memcpy(id, id_, sizeof(id));
|
|
|
|
|
else
|
|
|
|
|
memset(id, 0, sizeof(id));
|
|
|
|
|
}
|
2012-08-31 17:27:08 +00:00
|
|
|
|
|
|
|
|
bool operator<(const ParticleSystemKey& k) const
|
2012-11-08 16:35:28 +00:00
|
|
|
{
|
|
|
|
|
/* first id is particle index, we don't compare that */
|
2012-12-04 07:48:09 +00:00
|
|
|
if(ob < k.ob)
|
|
|
|
|
return true;
|
|
|
|
|
else if(ob == k.ob)
|
|
|
|
|
return memcmp(id+1, k.id+1, sizeof(int)*(OBJECT_PERSISTENT_ID_SIZE-1)) < 0;
|
|
|
|
|
|
|
|
|
|
return false;
|
2012-11-08 16:35:28 +00:00
|
|
|
}
|
2012-08-31 17:27:08 +00:00
|
|
|
};
|
|
|
|
|
|
2017-02-10 13:33:02 +01:00
|
|
|
class EdgeMap {
|
|
|
|
|
public:
|
|
|
|
|
EdgeMap() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void clear() {
|
|
|
|
|
edges_.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void insert(int v0, int v1) {
|
|
|
|
|
get_sorted_verts(v0, v1);
|
|
|
|
|
edges_.insert(std::pair<int, int>(v0, v1));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool exists(int v0, int v1) {
|
|
|
|
|
get_sorted_verts(v0, v1);
|
|
|
|
|
return edges_.find(std::pair<int, int>(v0, v1)) != edges_.end();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
void get_sorted_verts(int& v0, int& v1) {
|
|
|
|
|
if(v0 > v1) {
|
|
|
|
|
swap(v0, v1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set< std::pair<int, int> > edges_;
|
|
|
|
|
};
|
|
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
CCL_NAMESPACE_END
|
|
|
|
|
|
|
|
|
|
#endif /* __BLENDER_UTIL_H__ */
|