Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/doxygen/Doxyfile2
-rw-r--r--intern/cycles/blender/blender_geometry.cpp85
-rw-r--r--intern/cycles/blender/blender_object.cpp39
-rw-r--r--intern/cycles/blender/blender_sync.h11
-rw-r--r--release/datafiles/splash.pngbin760281 -> 737984 bytes
-rw-r--r--release/scripts/startup/bl_operators/gpencil_mesh_bake.py6
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h6
-rw-r--r--source/blender/editors/gpencil/gpencil_mesh.c80
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c5
9 files changed, 179 insertions, 55 deletions
diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile
index 6e4a087fa36..ca545eec4ca 100644
--- a/doc/doxygen/Doxyfile
+++ b/doc/doxygen/Doxyfile
@@ -38,7 +38,7 @@ PROJECT_NAME = Blender
# could be handy for archiving the generated documentation or if some version
# control system is used.
-PROJECT_NUMBER = "V2.91"
+PROJECT_NUMBER = "V2.92"
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
diff --git a/intern/cycles/blender/blender_geometry.cpp b/intern/cycles/blender/blender_geometry.cpp
index 002f5e0fdb7..14da8075903 100644
--- a/intern/cycles/blender/blender_geometry.cpp
+++ b/intern/cycles/blender/blender_geometry.cpp
@@ -25,6 +25,7 @@
#include "blender/blender_util.h"
#include "util/util_foreach.h"
+#include "util/util_task.h"
CCL_NAMESPACE_BEGIN
@@ -45,7 +46,8 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
BL::Object &b_ob,
BL::Object &b_ob_instance,
bool object_updated,
- bool use_particle_hair)
+ bool use_particle_hair,
+ TaskPool *task_pool)
{
/* Test if we can instance or if the object is modified. */
BL::ID b_ob_data = b_ob.data();
@@ -77,8 +79,15 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
used_shaders.push_back(default_shader);
}
- /* Test if we need to sync. */
+ /* Ensure we only sync instanced geometry once. */
Geometry *geom = geometry_map.find(key);
+ if (geom) {
+ if (geometry_synced.find(geom) != geometry_synced.end()) {
+ return geom;
+ }
+ }
+
+ /* Test if we need to sync. */
bool sync = true;
if (geom == NULL) {
/* Add new geometry if it did not exist yet. */
@@ -125,28 +134,36 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
}
}
- /* Ensure we only sync instanced geometry once. */
- if (geometry_synced.find(geom) != geometry_synced.end()) {
- return geom;
- }
-
- progress.set_sync_status("Synchronizing object", b_ob.name());
-
geometry_synced.insert(geom);
geom->name = ustring(b_ob_data.name().c_str());
- if (geom_type == Geometry::HAIR) {
- Hair *hair = static_cast<Hair *>(geom);
- sync_hair(b_depsgraph, b_ob, hair, used_shaders);
- }
- else if (geom_type == Geometry::VOLUME) {
- Volume *volume = static_cast<Volume *>(geom);
- sync_volume(b_ob, volume, used_shaders);
+ auto sync_func = [=]() mutable {
+ if (progress.get_cancel())
+ return;
+
+ progress.set_sync_status("Synchronizing object", b_ob.name());
+
+ if (geom_type == Geometry::HAIR) {
+ Hair *hair = static_cast<Hair *>(geom);
+ sync_hair(b_depsgraph, b_ob, hair, used_shaders);
+ }
+ else if (geom_type == Geometry::VOLUME) {
+ Volume *volume = static_cast<Volume *>(geom);
+ sync_volume(b_ob, volume, used_shaders);
+ }
+ else {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ sync_mesh(b_depsgraph, b_ob, mesh, used_shaders);
+ }
+ };
+
+ /* Defer the actual geometry sync to the task_pool for multithreading */
+ if (task_pool) {
+ task_pool->push(sync_func);
}
else {
- Mesh *mesh = static_cast<Mesh *>(geom);
- sync_mesh(b_depsgraph, b_ob, mesh, used_shaders);
+ sync_func();
}
return geom;
@@ -156,7 +173,8 @@ void BlenderSync::sync_geometry_motion(BL::Depsgraph &b_depsgraph,
BL::Object &b_ob,
Object *object,
float motion_time,
- bool use_particle_hair)
+ bool use_particle_hair,
+ TaskPool *task_pool)
{
/* Ensure we only sync instanced geometry once. */
Geometry *geom = object->geometry;
@@ -177,16 +195,29 @@ void BlenderSync::sync_geometry_motion(BL::Depsgraph &b_depsgraph,
return;
}
- if (b_ob.type() == BL::Object::type_HAIR || use_particle_hair) {
- Hair *hair = static_cast<Hair *>(geom);
- sync_hair_motion(b_depsgraph, b_ob, hair, motion_step);
- }
- else if (b_ob.type() == BL::Object::type_VOLUME || object_fluid_gas_domain_find(b_ob)) {
- /* No volume motion blur support yet. */
+ auto sync_func = [=]() mutable {
+ if (progress.get_cancel())
+ return;
+
+ if (b_ob.type() == BL::Object::type_HAIR || use_particle_hair) {
+ Hair *hair = static_cast<Hair *>(geom);
+ sync_hair_motion(b_depsgraph, b_ob, hair, motion_step);
+ }
+ else if (b_ob.type() == BL::Object::type_VOLUME || object_fluid_gas_domain_find(b_ob)) {
+ /* No volume motion blur support yet. */
+ }
+ else {
+ Mesh *mesh = static_cast<Mesh *>(geom);
+ sync_mesh_motion(b_depsgraph, b_ob, mesh, motion_step);
+ }
+ };
+
+ /* Defer the actual geometry sync to the task_pool for multithreading */
+ if (task_pool) {
+ task_pool->push(sync_func);
}
else {
- Mesh *mesh = static_cast<Mesh *>(geom);
- sync_mesh_motion(b_depsgraph, b_ob, mesh, motion_step);
+ sync_func();
}
}
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index 212b9cbe103..c3420c24469 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -32,6 +32,7 @@
#include "util/util_foreach.h"
#include "util/util_hash.h"
#include "util/util_logging.h"
+#include "util/util_task.h"
CCL_NAMESPACE_BEGIN
@@ -103,7 +104,8 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
bool use_particle_hair,
bool show_lights,
BlenderObjectCulling &culling,
- bool *use_portal)
+ bool *use_portal,
+ TaskPool *geom_task_pool)
{
const bool is_instance = b_instance.is_instance();
BL::Object b_ob = b_instance.object();
@@ -181,6 +183,10 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
return NULL;
}
+ /* Use task pool only for non-instances, since sync_dupli_particle accesses
+ * geometry. This restriction should be removed for better performance. */
+ TaskPool *object_geom_task_pool = (is_instance) ? NULL : geom_task_pool;
+
/* key to lookup object */
ObjectKey key(b_parent, persistent_id, b_ob_instance, use_particle_hair);
Object *object;
@@ -198,7 +204,12 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
/* mesh deformation */
if (object->geometry)
- sync_geometry_motion(b_depsgraph, b_ob, object, motion_time, use_particle_hair);
+ sync_geometry_motion(b_depsgraph,
+ b_ob_instance,
+ object,
+ motion_time,
+ use_particle_hair,
+ object_geom_task_pool);
}
return object;
@@ -211,8 +222,15 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
object_updated = true;
/* mesh sync */
- object->geometry = sync_geometry(
- b_depsgraph, b_ob, b_ob_instance, object_updated, use_particle_hair);
+ /* b_ob is owned by the iterator and will go out of scope at the end of the block.
+ * b_ob_instance is the original object and will remain valid for deferred geometry
+ * sync. */
+ object->geometry = sync_geometry(b_depsgraph,
+ b_ob_instance,
+ b_ob_instance,
+ object_updated,
+ use_particle_hair,
+ object_geom_task_pool);
/* special case not tracked by object update flags */
@@ -331,6 +349,9 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
BL::SpaceView3D &b_v3d,
float motion_time)
{
+ /* Task pool for multithreaded geometry sync. */
+ TaskPool geom_task_pool;
+
/* layer data */
bool motion = motion_time != 0.0f;
@@ -355,8 +376,8 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
const bool show_lights = BlenderViewportParameters(b_v3d).use_scene_lights;
BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval();
-
BL::Depsgraph::object_instances_iterator b_instance_iter;
+
for (b_depsgraph.object_instances.begin(b_instance_iter);
b_instance_iter != b_depsgraph.object_instances.end() && !cancel;
++b_instance_iter) {
@@ -381,7 +402,8 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
false,
show_lights,
culling,
- &use_portal);
+ &use_portal,
+ &geom_task_pool);
}
/* Particle hair as separate object. */
@@ -393,12 +415,15 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
true,
show_lights,
culling,
- &use_portal);
+ &use_portal,
+ &geom_task_pool);
}
cancel = progress.get_cancel();
}
+ geom_task_pool.wait_work();
+
progress.set_sync_status("");
if (!cancel && !motion) {
diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h
index 62fd1ac2351..a17db128957 100644
--- a/intern/cycles/blender/blender_sync.h
+++ b/intern/cycles/blender/blender_sync.h
@@ -50,6 +50,7 @@ class ViewLayer;
class Shader;
class ShaderGraph;
class ShaderNode;
+class TaskPool;
class BlenderSync {
public:
@@ -145,7 +146,8 @@ class BlenderSync {
bool use_particle_hair,
bool show_lights,
BlenderObjectCulling &culling,
- bool *use_portal);
+ bool *use_portal,
+ TaskPool *geom_task_pool);
/* Volume */
void sync_volume(BL::Object &b_ob, Volume *volume, const vector<Shader *> &used_shaders);
@@ -177,12 +179,15 @@ class BlenderSync {
BL::Object &b_ob,
BL::Object &b_ob_instance,
bool object_updated,
- bool use_particle_hair);
+ bool use_particle_hair,
+ TaskPool *task_pool);
+
void sync_geometry_motion(BL::Depsgraph &b_depsgraph,
BL::Object &b_ob,
Object *object,
float motion_time,
- bool use_particle_hair);
+ bool use_particle_hair,
+ TaskPool *task_pool);
/* Light */
void sync_light(BL::Object &b_parent,
diff --git a/release/datafiles/splash.png b/release/datafiles/splash.png
index 9f6078722ee..babb3e30c6d 100644
--- a/release/datafiles/splash.png
+++ b/release/datafiles/splash.png
Binary files differ
diff --git a/release/scripts/startup/bl_operators/gpencil_mesh_bake.py b/release/scripts/startup/bl_operators/gpencil_mesh_bake.py
index d4b1b11ed69..251e0af5854 100644
--- a/release/scripts/startup/bl_operators/gpencil_mesh_bake.py
+++ b/release/scripts/startup/bl_operators/gpencil_mesh_bake.py
@@ -99,6 +99,11 @@ class GPENCIL_OT_mesh_bake(Operator):
description="Export faces as filled strokes",
default=True,
)
+ only_selected: BoolProperty(
+ name="Only Selected Keyframes",
+ description="Convert only selected keyframes",
+ default=False,
+ )
target: EnumProperty(
name="Target Object",
description="Grease Pencil Object",
@@ -139,6 +144,7 @@ class GPENCIL_OT_mesh_bake(Operator):
thickness=self.thickness,
seams=self.seams,
faces=self.faces,
+ only_selected=self.only_selected,
offset=self.offset,
target=self.target,
frame_target=self.frame_target,
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index 741abb50453..987b64c217e 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -31,15 +31,15 @@ extern "C" {
*/
/* Blender major and minor version. */
-#define BLENDER_VERSION 291
+#define BLENDER_VERSION 292
/* Blender patch version for bugfix releases. */
#define BLENDER_VERSION_PATCH 0
/** Blender release cycle stage: alpha/beta/rc/release. */
-#define BLENDER_VERSION_CYCLE beta
+#define BLENDER_VERSION_CYCLE alpha
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
-#define BLENDER_FILE_SUBVERSION 9
+#define BLENDER_FILE_SUBVERSION 0
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file
diff --git a/source/blender/editors/gpencil/gpencil_mesh.c b/source/blender/editors/gpencil/gpencil_mesh.c
index e4862617d12..7cf4325d03b 100644
--- a/source/blender/editors/gpencil/gpencil_mesh.c
+++ b/source/blender/editors/gpencil/gpencil_mesh.c
@@ -25,12 +25,15 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
#include "BLI_math.h"
+#include "DNA_anim_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
+#include "BKE_anim_data.h"
#include "BKE_context.h"
#include "BKE_duplilist.h"
#include "BKE_global.h"
@@ -86,6 +89,35 @@ typedef struct GpBakeOb {
Object *ob;
} GpBakeOb;
+/* Get list of keyframes used by selected objects. */
+static void animdata_keyframe_list_get(ListBase *ob_list,
+ const bool only_selected,
+ GHash *r_keyframes)
+{
+ /* Loop all objects to get the list of keyframes used. */
+ LISTBASE_FOREACH (GpBakeOb *, elem, ob_list) {
+ Object *ob = elem->ob;
+ AnimData *adt = BKE_animdata_from_id(&ob->id);
+ if ((adt == NULL) || (adt->action == NULL)) {
+ continue;
+ }
+ LISTBASE_FOREACH (FCurve *, fcurve, &adt->action->curves) {
+ int i;
+ BezTriple *bezt;
+ for (i = 0, bezt = fcurve->bezt; i < fcurve->totvert; i++, bezt++) {
+ /* Keyframe number is x value of point. */
+ if ((bezt->f2 & SELECT) || (!only_selected)) {
+ /* Insert only one key for each keyframe number. */
+ int key = (int)bezt->vec[1][0];
+ if (!BLI_ghash_haskey(r_keyframes, POINTER_FROM_INT(key))) {
+ BLI_ghash_insert(r_keyframes, POINTER_FROM_INT(key), POINTER_FROM_INT(key));
+ }
+ }
+ }
+ }
+ }
+}
+
static void gpencil_bake_duplilist(Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *list)
{
GpBakeOb *elem = NULL;
@@ -161,13 +193,13 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op)
View3D *v3d = CTX_wm_view3d(C);
Object *ob_gpencil = NULL;
- ListBase list = {NULL, NULL};
- gpencil_bake_ob_list(C, depsgraph, scene, &list);
+ ListBase ob_selected_list = {NULL, NULL};
+ gpencil_bake_ob_list(C, depsgraph, scene, &ob_selected_list);
/* Cannot check this in poll because the active object changes. */
- if (list.first == NULL) {
+ if (ob_selected_list.first == NULL) {
BKE_report(op->reports, RPT_INFO, "No valid object selected");
- gpencil_bake_free_ob_list(&list);
+ gpencil_bake_free_ob_list(&ob_selected_list);
return OPERATOR_CANCELLED;
}
@@ -186,6 +218,7 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op)
const int thickness = RNA_int_get(op->ptr, "thickness");
const bool use_seams = RNA_boolean_get(op->ptr, "seams");
const bool use_faces = RNA_boolean_get(op->ptr, "faces");
+ const bool only_selected = RNA_boolean_get(op->ptr, "only_selected");
const float offset = RNA_float_get(op->ptr, "offset");
const int frame_offset = RNA_int_get(op->ptr, "frame_target") - frame_start;
char target[64];
@@ -206,7 +239,7 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op)
if ((ob_gpencil == NULL) || (ob_gpencil->type != OB_GPENCIL)) {
BKE_report(op->reports, RPT_ERROR, "Target grease pencil object not valid");
- gpencil_bake_free_ob_list(&list);
+ gpencil_bake_free_ob_list(&ob_selected_list);
return OPERATOR_CANCELLED;
}
@@ -237,6 +270,13 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op)
/* Loop all frame range. */
int oldframe = (int)DEG_get_ctime(depsgraph);
int key = -1;
+
+ /* Get list of keyframes. */
+ GHash *keyframe_list = BLI_ghash_int_new(__func__);
+ if (only_selected) {
+ animdata_keyframe_list_get(&ob_selected_list, only_selected, keyframe_list);
+ }
+
for (int i = frame_start; i < frame_end + 1; i++) {
key++;
/* Jump if not step limit but include last frame always. */
@@ -244,12 +284,17 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op)
continue;
}
+ /* Check if frame is in the list of frames to be exported. */
+ if ((only_selected) && (!BLI_ghash_haskey(keyframe_list, POINTER_FROM_INT(i)))) {
+ continue;
+ }
+
/* Move scene to new frame. */
CFRA = i;
BKE_scene_graph_update_for_newframe(depsgraph);
/* Loop all objects in the list. */
- LISTBASE_FOREACH (GpBakeOb *, elem, &list) {
+ LISTBASE_FOREACH (GpBakeOb *, elem, &ob_selected_list) {
Object *ob_eval = (Object *)DEG_get_evaluated_object(depsgraph, elem->ob);
/* Generate strokes. */
@@ -270,13 +315,14 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op)
if (project_type != GP_REPROJECT_KEEP) {
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
bGPDframe *gpf = gpl->actframe;
- if (gpf != NULL) {
- LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
- if ((gps->flag & GP_STROKE_TAG) == 0) {
- ED_gpencil_stroke_reproject(
- depsgraph, &gsc, sctx, gpl, gpf, gps, project_type, false);
- gps->flag |= GP_STROKE_TAG;
- }
+ if (gpf == NULL) {
+ continue;
+ }
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ if ((gps->flag & GP_STROKE_TAG) == 0) {
+ ED_gpencil_stroke_reproject(
+ depsgraph, &gsc, sctx, gpl, gpf, gps, project_type, false);
+ gps->flag |= GP_STROKE_TAG;
}
}
}
@@ -314,10 +360,14 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op)
}
/* Free memory. */
- gpencil_bake_free_ob_list(&list);
+ gpencil_bake_free_ob_list(&ob_selected_list);
if (sctx != NULL) {
ED_transform_snap_object_context_destroy(sctx);
}
+ /* Free temp hash table. */
+ if (keyframe_list != NULL) {
+ BLI_ghash_free(keyframe_list, NULL, NULL);
+ }
/* notifiers */
if (newob) {
@@ -394,6 +444,8 @@ void GPENCIL_OT_bake_mesh_animation(wmOperatorType *ot)
RNA_def_int(ot->srna, "thickness", 1, 1, 100, "Thickness", "", 1, 100);
RNA_def_boolean(ot->srna, "seams", 0, "Only Seam Edges", "Convert only seam edges");
RNA_def_boolean(ot->srna, "faces", 1, "Export Faces", "Export faces as filled strokes");
+ RNA_def_boolean(
+ ot->srna, "only_selected", 0, "Only Selected Keyframes", "Convert only selected keyframes");
RNA_def_float_distance(
ot->srna, "offset", 0.001f, 0.0, 100.0, "Offset", "Offset strokes from fill", 0.0, 100.00);
RNA_def_int(ot->srna, "frame_target", 1, 1, 100000, "Frame Target", "", 1, 100000);
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c
index 6eb12974408..8f17be97710 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c
@@ -101,6 +101,11 @@ static void deformStroke(GpencilModifierData *md,
}
BKE_gpencil_stroke_subdivide(gps, mmd->level, mmd->type);
+
+ /* If the stroke is cyclic, must generate the closing geometry. */
+ if (gps->flag & GP_STROKE_CYCLIC) {
+ BKE_gpencil_stroke_close(gps);
+ }
}
static void bakeModifier(struct Main *UNUSED(bmain),