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:
authorHans Goudey <h.goudey@me.com>2022-01-22 02:22:11 +0300
committerHans Goudey <h.goudey@me.com>2022-01-22 02:22:11 +0300
commit32832197adc1550b63d9ff90d0eaa76f8c136e46 (patch)
tree40c26cc538167df3e01841933c4e76b149c110b0
parent02d167277d7cf1f5f558cfde51c05258b352b328 (diff)
parent45d038181ae25972011f9656ba4f7062aa1c534f (diff)
Merge branch 'master' into temp-geometry-nodes-extrude-mesh
-rw-r--r--build_files/cmake/platform/platform_apple.cmake4
-rw-r--r--source/blender/blenkernel/intern/curve.cc112
-rw-r--r--source/blender/blenkernel/intern/idprop_serialize.cc26
-rw-r--r--source/blender/blenkernel/intern/paint.c1
-rw-r--r--source/blender/blenkernel/intern/spline_nurbs.cc72
-rw-r--r--source/blender/editors/curve/editcurve.c11
-rw-r--r--source/blender/editors/curve/editcurve_add.c6
-rw-r--r--source/blender/editors/mesh/editmesh_undo.c8
-rw-r--r--source/blender/editors/object/object_transform.c4
-rw-r--r--source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc35
-rw-r--r--source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh9
-rw-r--r--source/blender/io/wavefront_obj/exporter/obj_exporter.cc26
-rw-r--r--source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc2
15 files changed, 132 insertions, 190 deletions
diff --git a/build_files/cmake/platform/platform_apple.cmake b/build_files/cmake/platform/platform_apple.cmake
index 447645b6806..8acea1be841 100644
--- a/build_files/cmake/platform/platform_apple.cmake
+++ b/build_files/cmake/platform/platform_apple.cmake
@@ -166,7 +166,11 @@ if(WITH_FFTW3)
find_package(Fftw3)
endif()
+# FreeType compiled with Brotli compression for woff2.
find_package(Freetype REQUIRED)
+list(APPEND FREETYPE_LIBRARIES
+ ${LIBDIR}/brotli/lib/libbrotlicommon-static.a
+ ${LIBDIR}/brotli/lib/libbrotlidec-static.a)
if(WITH_IMAGE_OPENEXR)
find_package(OpenEXR)
diff --git a/source/blender/blenkernel/intern/curve.cc b/source/blender/blenkernel/intern/curve.cc
index 755b05e2697..70edaccb244 100644
--- a/source/blender/blenkernel/intern/curve.cc
+++ b/source/blender/blenkernel/intern/curve.cc
@@ -30,6 +30,7 @@
#include "BLI_blenlib.h"
#include "BLI_endian_switch.h"
#include "BLI_ghash.h"
+#include "BLI_index_range.hh"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -67,10 +68,12 @@
#include "BLO_read_write.h"
+using blender::IndexRange;
+
/* globals */
/* local */
-static CLG_LogRef LOG = {"bke.curve"};
+// static CLG_LogRef LOG = {"bke.curve"};
static void curve_init_data(ID *id)
{
@@ -1160,81 +1163,34 @@ void BKE_nurb_bpoint_calc_plane(struct Nurb *nu, BPoint *bp, float r_plane[3])
static void calcknots(float *knots, const int pnts, const short order, const short flag)
{
- /* knots: number of pnts NOT corrected for cyclic */
- const int pnts_order = pnts + order;
- float k;
- int a;
+ const bool is_cyclic = flag & CU_NURB_CYCLIC;
+ const bool is_bezier = flag & CU_NURB_BEZIER && !(flag & CU_NURB_ENDPOINT);
+ const bool is_end_point = flag & CU_NURB_ENDPOINT && !(flag & CU_NURB_BEZIER);
+ /* Inner knots are always repeated once except on Bezier case. */
+ const int repeat_inner = is_bezier ? order - 1 : 1;
+ /* How many times to repeat 0.0 at the beginning of knot. */
+ const int head = is_end_point && !is_cyclic ? order : (is_bezier ? order / 2 : 1);
+ /* Number of knots replicating widths of the starting knots.
+ * Covers both Cyclic and EndPoint cases. */
+ const int tail = is_cyclic ? 2 * order - 1 : (is_end_point ? order : 0);
- switch (flag & (CU_NURB_ENDPOINT | CU_NURB_BEZIER)) {
- case CU_NURB_ENDPOINT:
- k = 0.0;
- for (a = 1; a <= pnts_order; a++) {
- knots[a - 1] = k;
- if (a >= order && a <= pnts) {
- k += 1.0f;
- }
- }
- break;
- case CU_NURB_BEZIER:
- /* Warning, the order MUST be 2 or 4,
- * if this is not enforced, the displist will be corrupt */
- if (order == 4) {
- k = 0.34;
- for (a = 0; a < pnts_order; a++) {
- knots[a] = floorf(k);
- k += (1.0f / 3.0f);
- }
- }
- else if (order == 3) {
- k = 0.6f;
- for (a = 0; a < pnts_order; a++) {
- if (a >= order && a <= pnts) {
- k += 0.5f;
- }
- knots[a] = floorf(k);
- }
- }
- else {
- CLOG_ERROR(&LOG, "bez nurb curve order is not 3 or 4, should never happen");
- }
- break;
- default:
- for (a = 0; a < pnts_order; a++) {
- knots[a] = (float)a;
- }
- break;
- }
-}
-
-static void makecyclicknots(float *knots, int pnts, short order)
-/* pnts, order: number of pnts NOT corrected for cyclic */
-{
- int a, b, order2, c;
-
- if (knots == nullptr) {
- return;
- }
+ const int knot_count = pnts + order + (is_cyclic ? order - 1 : 0);
- order2 = order - 1;
+ int r = head;
+ float current = 0.0f;
- /* do first long rows (order -1), remove identical knots at endpoints */
- if (order > 2) {
- b = pnts + order2;
- for (a = 1; a < order2; a++) {
- if (knots[b] != knots[b - a]) {
- break;
- }
- }
- if (a == order2) {
- knots[pnts + order - 2] += 1.0f;
+ for (const int i : IndexRange(knot_count - tail)) {
+ knots[i] = current;
+ r--;
+ if (r == 0) {
+ current += 1.0;
+ r = repeat_inner;
}
}
- b = order;
- c = pnts + order + order2;
- for (a = pnts + order2; a < c; a++) {
- knots[a] = knots[a - 1] + (knots[b] - knots[b - 1]);
- b--;
+ const int tail_index = knot_count - tail;
+ for (const int i : IndexRange(tail)) {
+ knots[tail_index + i] = current + (knots[i] - knots[0]);
}
}
@@ -1247,13 +1203,7 @@ static void makeknots(Nurb *nu, short uv)
}
if (BKE_nurb_check_valid_u(nu)) {
nu->knotsu = (float *)MEM_calloc_arrayN(KNOTSU(nu) + 1, sizeof(float), "makeknots");
- if (nu->flagu & CU_NURB_CYCLIC) {
- calcknots(nu->knotsu, nu->pntsu, nu->orderu, 0); /* cyclic should be uniform */
- makecyclicknots(nu->knotsu, nu->pntsu, nu->orderu);
- }
- else {
- calcknots(nu->knotsu, nu->pntsu, nu->orderu, nu->flagu);
- }
+ calcknots(nu->knotsu, nu->pntsu, nu->orderu, nu->flagu);
}
else {
nu->knotsu = nullptr;
@@ -1265,13 +1215,7 @@ static void makeknots(Nurb *nu, short uv)
}
if (BKE_nurb_check_valid_v(nu)) {
nu->knotsv = (float *)MEM_calloc_arrayN(KNOTSV(nu) + 1, sizeof(float), "makeknots");
- if (nu->flagv & CU_NURB_CYCLIC) {
- calcknots(nu->knotsv, nu->pntsv, nu->orderv, 0); /* cyclic should be uniform */
- makecyclicknots(nu->knotsv, nu->pntsv, nu->orderv);
- }
- else {
- calcknots(nu->knotsv, nu->pntsv, nu->orderv, nu->flagv);
- }
+ calcknots(nu->knotsv, nu->pntsv, nu->orderv, nu->flagv);
}
else {
nu->knotsv = nullptr;
diff --git a/source/blender/blenkernel/intern/idprop_serialize.cc b/source/blender/blenkernel/intern/idprop_serialize.cc
index 92dce49500c..08a7f13b806 100644
--- a/source/blender/blenkernel/intern/idprop_serialize.cc
+++ b/source/blender/blenkernel/intern/idprop_serialize.cc
@@ -304,7 +304,7 @@ class IDPStringSerializer : public IDPropertySerializer {
std::unique_ptr<IDProperty, IDPropertyDeleter> entry_to_idprop(
DictionaryEntryParser &entry_reader) const override
{
- BLI_assert(entry_reader.get_type().value() == IDP_STRING);
+ BLI_assert(*(entry_reader.get_type()) == IDP_STRING);
std::optional<std::string> name = entry_reader.get_name();
if (!name.has_value()) {
return nullptr;
@@ -344,7 +344,7 @@ class IDPIntSerializer : public IDPropertySerializer {
std::unique_ptr<IDProperty, IDPropertyDeleter> entry_to_idprop(
DictionaryEntryParser &entry_reader) const override
{
- BLI_assert(entry_reader.get_type().value() == IDP_INT);
+ BLI_assert(*(entry_reader.get_type()) == IDP_INT);
std::optional<std::string> name = entry_reader.get_name();
if (!name.has_value()) {
return nullptr;
@@ -384,7 +384,7 @@ class IDPFloatSerializer : public IDPropertySerializer {
std::unique_ptr<IDProperty, IDPropertyDeleter> entry_to_idprop(
DictionaryEntryParser &entry_reader) const override
{
- BLI_assert(entry_reader.get_type().value() == IDP_FLOAT);
+ BLI_assert(*(entry_reader.get_type()) == IDP_FLOAT);
std::optional<std::string> name = entry_reader.get_name();
if (!name.has_value()) {
return nullptr;
@@ -424,7 +424,7 @@ class IDPDoubleSerializer : public IDPropertySerializer {
std::unique_ptr<IDProperty, IDPropertyDeleter> entry_to_idprop(
DictionaryEntryParser &entry_reader) const override
{
- BLI_assert(entry_reader.get_type().value() == IDP_DOUBLE);
+ BLI_assert(*(entry_reader.get_type()) == IDP_DOUBLE);
std::optional<std::string> name = entry_reader.get_name();
if (!name.has_value()) {
return nullptr;
@@ -502,7 +502,7 @@ class IDPArraySerializer : public IDPropertySerializer {
std::unique_ptr<IDProperty, IDPropertyDeleter> entry_to_idprop(
DictionaryEntryParser &entry_reader) const override
{
- BLI_assert(entry_reader.get_type().value() == IDP_ARRAY);
+ BLI_assert(*(entry_reader.get_type()) == IDP_ARRAY);
std::optional<eIDPropertyType> property_subtype = entry_reader.get_subtype();
if (!property_subtype.has_value()) {
return nullptr;
@@ -556,8 +556,8 @@ class IDPArraySerializer : public IDPropertySerializer {
std::unique_ptr<IDProperty, IDPropertyDeleter> idprop_array_int_from_value(
DictionaryEntryParser &entry_reader) const
{
- BLI_assert(entry_reader.get_type().value() == IDP_ARRAY);
- BLI_assert(entry_reader.get_subtype().value() == IDP_INT);
+ BLI_assert(*(entry_reader.get_type()) == IDP_ARRAY);
+ BLI_assert(*(entry_reader.get_subtype()) == IDP_INT);
std::optional<std::string> name = entry_reader.get_name();
if (!name.has_value()) {
return nullptr;
@@ -572,8 +572,8 @@ class IDPArraySerializer : public IDPropertySerializer {
std::unique_ptr<IDProperty, IDPropertyDeleter> idprop_array_float_from_value(
DictionaryEntryParser &entry_reader) const
{
- BLI_assert(entry_reader.get_type().value() == IDP_ARRAY);
- BLI_assert(entry_reader.get_subtype().value() == IDP_FLOAT);
+ BLI_assert(*(entry_reader.get_type()) == IDP_ARRAY);
+ BLI_assert(*(entry_reader.get_subtype()) == IDP_FLOAT);
std::optional<std::string> name = entry_reader.get_name();
if (!name.has_value()) {
return nullptr;
@@ -588,8 +588,8 @@ class IDPArraySerializer : public IDPropertySerializer {
std::unique_ptr<IDProperty, IDPropertyDeleter> idprop_array_double_from_value(
DictionaryEntryParser &entry_reader) const
{
- BLI_assert(entry_reader.get_type().value() == IDP_ARRAY);
- BLI_assert(entry_reader.get_subtype().value() == IDP_DOUBLE);
+ BLI_assert(*(entry_reader.get_type()) == IDP_ARRAY);
+ BLI_assert(*(entry_reader.get_subtype()) == IDP_DOUBLE);
std::optional<std::string> name = entry_reader.get_name();
if (!name.has_value()) {
return nullptr;
@@ -639,7 +639,7 @@ class IDPGroupSerializer : public IDPropertySerializer {
std::unique_ptr<IDProperty, IDPropertyDeleter> entry_to_idprop(
DictionaryEntryParser &entry_reader) const override
{
- BLI_assert(entry_reader.get_type().value() == IDP_GROUP);
+ BLI_assert(*(entry_reader.get_type()) == IDP_GROUP);
std::optional<std::string> name = entry_reader.get_name();
if (!name.has_value()) {
return nullptr;
@@ -796,7 +796,7 @@ static IDProperty *idprop_from_value(const DictionaryValue &value)
return nullptr;
}
- const IDPropertySerializer &serializer = serializer_for(property_type.value());
+ const IDPropertySerializer &serializer = serializer_for(*property_type);
return serializer.entry_to_idprop(entry_reader).release();
}
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 72210eea71d..407375c4d22 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -1648,6 +1648,7 @@ static void sculpt_update_object(Depsgraph *depsgraph,
ss->totvert = me->totvert;
ss->totpoly = me->totpoly;
ss->totfaces = me->totpoly;
+ ss->vert_normals = BKE_mesh_vertex_normals_ensure(me);
ss->mvert = me->mvert;
ss->mpoly = me->mpoly;
ss->mloop = me->mloop;
diff --git a/source/blender/blenkernel/intern/spline_nurbs.cc b/source/blender/blenkernel/intern/spline_nurbs.cc
index 719ba4b7ecd..5993b9a9a27 100644
--- a/source/blender/blenkernel/intern/spline_nurbs.cc
+++ b/source/blender/blenkernel/intern/spline_nurbs.cc
@@ -179,65 +179,35 @@ int NURBSpline::knots_size() const
void NURBSpline::calculate_knots() const
{
const KnotsMode mode = this->knots_mode;
- const int length = this->size();
const int order = order_;
+ const bool is_bezier = mode == NURBSpline::KnotsMode::Bezier;
+ const bool is_end_point = mode == NURBSpline::KnotsMode::EndPoint;
+ /* Inner knots are always repeated once except on Bezier case. */
+ const int repeat_inner = is_bezier ? order - 1 : 1;
+ /* How many times to repeat 0.0 at the beginning of knot. */
+ const int head = is_end_point && !is_cyclic_ ? order : (is_bezier ? order / 2 : 1);
+ /* Number of knots replicating widths of the starting knots.
+ * Covers both Cyclic and EndPoint cases. */
+ const int tail = is_cyclic_ ? 2 * order - 1 : (is_end_point ? order : 0);
knots_.resize(this->knots_size());
-
MutableSpan<float> knots = knots_;
- if (mode == NURBSpline::KnotsMode::Normal || is_cyclic_) {
- for (const int i : knots.index_range()) {
- knots[i] = static_cast<float>(i);
- }
- }
- else if (mode == NURBSpline::KnotsMode::EndPoint) {
- float k = 0.0f;
- for (const int i : IndexRange(1, knots.size())) {
- knots[i - 1] = k;
- if (i >= order && i <= length) {
- k += 1.0f;
- }
- }
- }
- else if (mode == NURBSpline::KnotsMode::Bezier) {
- BLI_assert(ELEM(order, 3, 4));
- if (order == 3) {
- float k = 0.6f;
- for (const int i : knots.index_range()) {
- if (i >= order && i <= length) {
- k += 0.5f;
- }
- knots[i] = std::floor(k);
- }
- }
- else {
- float k = 0.34f;
- for (const int i : knots.index_range()) {
- knots[i] = std::floor(k);
- k += 1.0f / 3.0f;
- }
- }
- }
+ int r = head;
+ float current = 0.0f;
- if (is_cyclic_) {
- const int b = length + order - 1;
- if (order > 2) {
- for (const int i : IndexRange(1, order - 2)) {
- if (knots[b] != knots[b - i]) {
- if (i == order - 1) {
- knots[length + order - 2] += 1.0f;
- break;
- }
- }
- }
+ for (const int i : IndexRange(knots.size() - tail)) {
+ knots[i] = current;
+ r--;
+ if (r == 0) {
+ current += 1.0;
+ r = repeat_inner;
}
+ }
- int c = order;
- for (int i = b; i < this->knots_size(); i++) {
- knots[i] = knots[i - 1] + (knots[c] - knots[c - 1]);
- c--;
- }
+ const int tail_index = knots.size() - tail;
+ for (const int i : IndexRange(tail)) {
+ knots[tail_index + i] = current + (knots[i] - knots[0]);
}
}
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index a034e4bb10e..a70bc1c0350 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -4953,19 +4953,22 @@ bool ed_editnurb_spin(
if ((a & 1) == 0) {
rotateflagNurb(editnurb, SELECT, cent, scalemat1);
- weightflagNurb(editnurb, SELECT, 0.25 * M_SQRT2);
+ weightflagNurb(editnurb, SELECT, 0.5 * M_SQRT2);
}
else {
rotateflagNurb(editnurb, SELECT, cent, scalemat2);
- weightflagNurb(editnurb, SELECT, 4.0 / M_SQRT2);
+ weightflagNurb(editnurb, SELECT, 2.0 / M_SQRT2);
}
}
if (ok) {
LISTBASE_FOREACH (Nurb *, nu, editnurb) {
if (ED_curve_nurb_select_check(v3d, nu)) {
- nu->orderv = 4;
- nu->flagv |= CU_NURB_CYCLIC;
+ nu->orderv = 3;
+ /* It is challenging to create a good approximation of a circle with uniform knots vector
+ * (which is forced in Blender for cyclic NURBS curves). Here a NURBS circle is constructed
+ * by connecting four Bezier arcs. */
+ nu->flagv |= CU_NURB_CYCLIC | CU_NURB_BEZIER;
BKE_nurb_knot_calc_v(nu);
}
}
diff --git a/source/blender/editors/curve/editcurve_add.c b/source/blender/editors/curve/editcurve_add.c
index 614805a70f5..daef4a21692 100644
--- a/source/blender/editors/curve/editcurve_add.c
+++ b/source/blender/editors/curve/editcurve_add.c
@@ -306,9 +306,9 @@ Nurb *ED_curve_add_nurbs_primitive(
else if (cutype == CU_NURBS) { /* nurb */
nu->pntsu = 8;
nu->pntsv = 1;
- nu->orderu = 4;
+ nu->orderu = 3;
nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * nu->pntsu, "addNurbprim6");
- nu->flagu = CU_NURB_CYCLIC;
+ nu->flagu = CU_NURB_CYCLIC | CU_NURB_BEZIER;
bp = nu->bp;
for (a = 0; a < 8; a++) {
@@ -322,7 +322,7 @@ Nurb *ED_curve_add_nurbs_primitive(
bp->vec[2] += 0.25f * nurbcircle[a][1] * grid;
}
if (a & 1) {
- bp->vec[3] = 0.25 * M_SQRT2;
+ bp->vec[3] = 0.5 * M_SQRT2;
}
else {
bp->vec[3] = 1.0;
diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c
index 46a056f865b..5d573271ea3 100644
--- a/source/blender/editors/mesh/editmesh_undo.c
+++ b/source/blender/editors/mesh/editmesh_undo.c
@@ -687,11 +687,15 @@ static void undomesh_to_editmesh(UndoMesh *um, Object *ob, BMEditMesh *em, Key *
.active_shapekey = um->shapenr,
}));
+ /* Normals should not be stored in the undo mesh, so recalculate them. The edit
+ * mesh is expected to have valid normals and there is no tracked dirty state. */
+ BLI_assert(BKE_mesh_vertex_normals_are_dirty(&um->me));
+ BM_mesh_normals_update(bm);
+
em_tmp = BKE_editmesh_create(bm);
*em = *em_tmp;
- /* Calculate face normals and tessellation at once since it's multi-threaded.
- * The vertex normals are stored in the undo-mesh, so this doesn't need to be updated. */
+ /* Calculate face normals and tessellation at once since it's multi-threaded. */
BKE_editmesh_looptri_calc_ex(em,
&(const struct BMeshCalcTessellation_Params){
.face_normals = true,
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index c320313643d..6d04bd3f9d5 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -811,8 +811,8 @@ static int apply_objects_internal(bContext *C,
/* adjust data */
BKE_mesh_transform(me, mat, true);
- /* update normals */
- BKE_mesh_calc_normals(me);
+ /* If normal layers exist, they are now dirty. */
+ BKE_mesh_normals_tag_dirty(me);
}
else if (ob->type == OB_ARMATURE) {
bArmature *arm = ob->data;
diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc
index d6e1d8a7ea5..b77b5735784 100644
--- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc
+++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc
@@ -17,6 +17,8 @@
/** \file
* \ingroup obj
*/
+/* Silence warnings from copying deprecated fields. Needed for an Object copy constructor use. */
+#define DNA_DEPRECATED_ALLOW
#include "BKE_customdata.h"
#include "BKE_deform.h"
@@ -42,20 +44,21 @@
namespace blender::io::obj {
OBJMesh::OBJMesh(Depsgraph *depsgraph, const OBJExportParams &export_params, Object *mesh_object)
{
- export_object_eval_ = DEG_get_evaluated_object(depsgraph, mesh_object);
- export_mesh_eval_ = BKE_object_get_evaluated_mesh(export_object_eval_);
+ /* We need to copy the object because it may be in temporary space. */
+ Object *obj_eval = DEG_get_evaluated_object(depsgraph, mesh_object);
+ export_object_eval_ = *obj_eval;
+ export_mesh_eval_ = BKE_object_get_evaluated_mesh(&export_object_eval_);
mesh_eval_needs_free_ = false;
if (!export_mesh_eval_) {
/* Curves and NURBS surfaces need a new mesh when they're
* exported in the form of vertices and edges.
*/
- export_mesh_eval_ = BKE_mesh_new_from_object(depsgraph, export_object_eval_, true, true);
+ export_mesh_eval_ = BKE_mesh_new_from_object(depsgraph, &export_object_eval_, true, true);
/* Since a new mesh been allocated, it needs to be freed in the destructor. */
mesh_eval_needs_free_ = true;
}
- if (export_params.export_triangulated_mesh &&
- ELEM(export_object_eval_->type, OB_MESH, OB_SURF)) {
+ if (export_params.export_triangulated_mesh && ELEM(export_object_eval_.type, OB_MESH, OB_SURF)) {
std::tie(export_mesh_eval_, mesh_eval_needs_free_) = triangulate_mesh_eval();
}
set_world_axes_transform(export_params.forward_axis, export_params.up_axis);
@@ -116,10 +119,10 @@ void OBJMesh::set_world_axes_transform(const eTransformAxisForward forward,
mat3_from_axis_conversion(OBJ_AXIS_Y_FORWARD, OBJ_AXIS_Z_UP, forward, up, axes_transform);
/* mat3_from_axis_conversion returns a transposed matrix! */
transpose_m3(axes_transform);
- mul_m4_m3m4(world_and_axes_transform_, axes_transform, export_object_eval_->obmat);
+ mul_m4_m3m4(world_and_axes_transform_, axes_transform, export_object_eval_.obmat);
/* mul_m4_m3m4 does not transform last row of obmat, i.e. location data. */
- mul_v3_m3v3(world_and_axes_transform_[3], axes_transform, export_object_eval_->obmat[3]);
- world_and_axes_transform_[3][3] = export_object_eval_->obmat[3][3];
+ mul_v3_m3v3(world_and_axes_transform_[3], axes_transform, export_object_eval_.obmat[3]);
+ world_and_axes_transform_[3][3] = export_object_eval_.obmat[3][3];
}
int OBJMesh::tot_vertices() const
@@ -185,8 +188,14 @@ void OBJMesh::calc_smooth_groups(const bool use_bitflags)
const Material *OBJMesh::get_object_material(const int16_t mat_nr) const
{
- /* "+ 1" as material getter needs one-based indices. */
- const Material *r_mat = BKE_object_material_get(export_object_eval_, mat_nr + 1);
+ /**
+ * The const_cast is safe here because BKE_object_material_get won't change the object
+ * but it is a big can of worms to fix the declaration of that function right now.
+ *
+ * The call uses "+ 1" as material getter needs one-based indices.
+ */
+ Object *obj = const_cast<Object *>(&export_object_eval_);
+ const Material *r_mat = BKE_object_material_get(obj, mat_nr + 1);
#ifdef DEBUG
if (!r_mat) {
std::cerr << "Material not found for mat_nr = " << mat_nr << std::endl;
@@ -209,7 +218,7 @@ int16_t OBJMesh::ith_poly_matnr(const int poly_index) const
const char *OBJMesh::get_object_name() const
{
- return export_object_eval_->id.name + 2;
+ return export_object_eval_.id.name + 2;
}
const char *OBJMesh::get_object_mesh_name() const
@@ -403,7 +412,7 @@ int16_t OBJMesh::get_poly_deform_group_index(const int poly_index) const
BLI_assert(poly_index < export_mesh_eval_->totpoly);
const MPoly &mpoly = export_mesh_eval_->mpoly[poly_index];
const MLoop *mloop = &export_mesh_eval_->mloop[mpoly.loopstart];
- const Object *obj = export_object_eval_;
+ const Object *obj = &export_object_eval_;
const int tot_deform_groups = BKE_object_defgroup_count(obj);
/* Indices of the vector index into deform groups of an object; values are the]
* number of vertex members in one deform group. */
@@ -444,7 +453,7 @@ int16_t OBJMesh::get_poly_deform_group_index(const int poly_index) const
const char *OBJMesh::get_poly_deform_group_name(const int16_t def_group_index) const
{
const bDeformGroup &vertex_group = *(static_cast<bDeformGroup *>(
- BLI_findlink(BKE_object_defgroup_list(export_object_eval_), def_group_index)));
+ BLI_findlink(BKE_object_defgroup_list(&export_object_eval_), def_group_index)));
return vertex_group.name;
}
diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh
index 390d8034337..f3ace140006 100644
--- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh
+++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh
@@ -32,6 +32,7 @@
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
#include "IO_wavefront_obj.h"
@@ -57,7 +58,11 @@ using unique_bmesh_ptr = std::unique_ptr<BMesh, CustomBMeshDeleter>;
class OBJMesh : NonCopyable {
private:
- Object *export_object_eval_;
+ /**
+ * We need to copy the entire Object structure here because the dependency graph iterator
+ * sometimes builds an Object in a temporary space that doesn't persist.
+ */
+ Object export_object_eval_;
Mesh *export_mesh_eval_;
/**
* For curves which are converted to mesh, and triangulated meshes, a new mesh is allocated.
@@ -85,7 +90,7 @@ class OBJMesh : NonCopyable {
* Total number of normal indices (maximum entry, plus 1, in
* the loop_to_norm_index_ vector).
*/
- int tot_normal_indices_ = NEGATIVE_INIT;
+ int tot_normal_indices_ = 0;
/**
* Total smooth groups in an object.
*/
diff --git a/source/blender/io/wavefront_obj/exporter/obj_exporter.cc b/source/blender/io/wavefront_obj/exporter/obj_exporter.cc
index 595e6aaf4f2..0c753ccdcac 100644
--- a/source/blender/io/wavefront_obj/exporter/obj_exporter.cc
+++ b/source/blender/io/wavefront_obj/exporter/obj_exporter.cc
@@ -91,28 +91,29 @@ filter_supported_objects(Depsgraph *depsgraph, const OBJExportParams &export_par
{
Vector<std::unique_ptr<OBJMesh>> r_exportable_meshes;
Vector<std::unique_ptr<OBJCurve>> r_exportable_nurbs;
- const ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph);
- LISTBASE_FOREACH (const Base *, base, &view_layer->object_bases) {
- Object *object_in_layer = base->object;
- if (export_params.export_selected_objects && !(object_in_layer->base_flag & BASE_SELECTED)) {
+ const int deg_objects_visibility_flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
+ DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET |
+ DEG_ITER_OBJECT_FLAG_VISIBLE |
+ DEG_ITER_OBJECT_FLAG_DUPLI;
+ DEG_OBJECT_ITER_BEGIN (depsgraph, object, deg_objects_visibility_flags) {
+ if (export_params.export_selected_objects && !(object->base_flag & BASE_SELECTED)) {
continue;
}
- switch (object_in_layer->type) {
+ switch (object->type) {
case OB_SURF:
/* Export in mesh form: vertices and polygons. */
ATTR_FALLTHROUGH;
case OB_MESH:
- r_exportable_meshes.append(
- std::make_unique<OBJMesh>(depsgraph, export_params, object_in_layer));
+ r_exportable_meshes.append(std::make_unique<OBJMesh>(depsgraph, export_params, object));
break;
case OB_CURVE: {
- Curve *curve = static_cast<Curve *>(object_in_layer->data);
+ Curve *curve = static_cast<Curve *>(object->data);
Nurb *nurb{static_cast<Nurb *>(curve->nurb.first)};
if (!nurb) {
/* An empty curve. Not yet supported to export these as meshes. */
if (export_params.export_curves_as_nurbs) {
r_exportable_nurbs.append(
- std::make_unique<OBJCurve>(depsgraph, export_params, object_in_layer));
+ std::make_unique<OBJCurve>(depsgraph, export_params, object));
}
break;
}
@@ -121,18 +122,18 @@ filter_supported_objects(Depsgraph *depsgraph, const OBJExportParams &export_par
if (export_params.export_curves_as_nurbs) {
/* Export in parameter form: control points. */
r_exportable_nurbs.append(
- std::make_unique<OBJCurve>(depsgraph, export_params, object_in_layer));
+ std::make_unique<OBJCurve>(depsgraph, export_params, object));
}
else {
/* Export in mesh form: edges and vertices. */
r_exportable_meshes.append(
- std::make_unique<OBJMesh>(depsgraph, export_params, object_in_layer));
+ std::make_unique<OBJMesh>(depsgraph, export_params, object));
}
break;
case CU_BEZIER:
/* Always export in mesh form: edges and vertices. */
r_exportable_meshes.append(
- std::make_unique<OBJMesh>(depsgraph, export_params, object_in_layer));
+ std::make_unique<OBJMesh>(depsgraph, export_params, object));
break;
default:
/* Other curve types are not supported. */
@@ -145,6 +146,7 @@ filter_supported_objects(Depsgraph *depsgraph, const OBJExportParams &export_par
break;
}
}
+ DEG_OBJECT_ITER_END;
return {std::move(r_exportable_meshes), std::move(r_exportable_nurbs)};
}
diff --git a/source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc b/source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc
index 92d478c20a1..5dac913c902 100644
--- a/source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc
+++ b/source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc
@@ -60,7 +60,7 @@ TEST_F(obj_exporter_test, filter_objects_curves_as_mesh)
return;
}
auto [objmeshes, objcurves]{filter_supported_objects(depsgraph, _export.params)};
- EXPECT_EQ(objmeshes.size(), 17);
+ EXPECT_EQ(objmeshes.size(), 19);
EXPECT_EQ(objcurves.size(), 0);
}
@@ -73,7 +73,7 @@ TEST_F(obj_exporter_test, filter_objects_curves_as_nurbs)
}
_export.params.export_curves_as_nurbs = true;
auto [objmeshes, objcurves]{filter_supported_objects(depsgraph, _export.params)};
- EXPECT_EQ(objmeshes.size(), 16);
+ EXPECT_EQ(objmeshes.size(), 18);
EXPECT_EQ(objcurves.size(), 2);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc
index 9001cb2d1f2..840dfd2fbd3 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc
@@ -48,8 +48,8 @@ static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
- uiItemR(layout, ptr, "domain", 0, "", ICON_NONE);
uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "domain", 0, "", ICON_NONE);
}
static void node_init(bNodeTree *UNUSED(tree), bNode *node)
diff --git a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc
index a257af4391c..d17657bfa3a 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc
@@ -44,7 +44,7 @@ static void node_declare(NodeDeclarationBuilder &b)
b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field();
b.add_input<decl::Float>(N_("Distance Min")).min(0.0f).subtype(PROP_DISTANCE);
b.add_input<decl::Float>(N_("Density Max")).default_value(10.0f).min(0.0f);
- b.add_input<decl::Float>(N_("Density")).default_value(10.0f).supports_field();
+ b.add_input<decl::Float>(N_("Density")).default_value(10.0f).min(0.0f).supports_field();
b.add_input<decl::Float>(N_("Density Factor"))
.default_value(1.0f)
.min(0.0f)