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>2021-09-11 21:54:40 +0300
committerHans Goudey <h.goudey@me.com>2021-09-11 21:54:40 +0300
commitb9febb54a492ac6c93802fb0aa189d4c3fd99b0b (patch)
treea2f3b1d773d3a2424d7db0c8d9a0a0899da17747
parentc946fdb2e5fc1eab139f70f01ea4e673435455bd (diff)
Geometry Nodes: Support modifier on curve objects
With this commit, curve objects support the geometry nodes modifier. Curves objects now evaluate to `CurveEval` unless there was a previous implicit conversion (tessellating modifiers, mesh modifiers, or the settings in the curve "Geometry" panel). In the new code, curves are only considered to be the wire edges-- any generated surface is a mesh instead, stored in the evaluated geometry set. The consolidation of concepts mentioned above allows remove a lot of code that had to do with maintaining the `DispList` type temporarily for modifiers and rendering. Instead, render engines see a separate object for the mesh from the mesh geometry component, and when the curve object evaluates to a curve, the `CurveEval` is always used for drawing wire edges. However, currently the `DispList` type is still maintained and used as an intermediate step in implicit mesh conversion. In the future, more uses of it could be changed to use `CurveEval` and `Mesh` instead. This is mostly not changed behavior, it is just a formalization of existing logic after recent fixes for 2.8 versions last year and two years ago. Also, in the future more functionality can be converted to nodes, removing cases of implicit conversions. For more discussion on that topic, see T89676. The `use_fill_deform` option is removed. It has not worked properly since 2.62, and the choice for filling a curve before or after deformation will work much better and be clearer with a node system. Applying the geometry nodes modifier to generate a curve is not implemented with this commit, so applying the modifier won't work at all. This is a separate technical challenge, and should be solved in a separate step. Differential Revision: https://developer.blender.org/D11597
-rw-r--r--release/scripts/startup/bl_operators/geometry_nodes.py4
-rw-r--r--release/scripts/startup/bl_ui/properties_data_curve.py1
-rw-r--r--source/blender/blenkernel/BKE_displist.h2
-rw-r--r--source/blender/blenkernel/intern/displist.cc328
-rw-r--r--source/blender/blenkernel/intern/geometry_component_curve.cc2
-rw-r--r--source/blender/blenkernel/intern/geometry_set.cc2
-rw-r--r--source/blender/blenkernel/intern/geometry_set_instances.cc13
-rw-r--r--source/blender/blenkernel/intern/mesh_convert.c36
-rw-r--r--source/blender/blenkernel/intern/object.c5
-rw-r--r--source/blender/blenkernel/intern/object_dupli.cc2
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc10
-rw-r--r--source/blender/draw/engines/overlay/overlay_edit_text.c13
-rw-r--r--source/blender/draw/engines/overlay/overlay_wireframe.c10
-rw-r--r--source/blender/draw/intern/draw_cache.c199
-rw-r--r--source/blender/draw/intern/draw_cache.h14
-rw-r--r--source/blender/draw/intern/draw_cache_impl_curve.cc153
-rw-r--r--source/blender/editors/curve/editcurve_add.c1
-rw-r--r--source/blender/editors/space_spreadsheet/space_spreadsheet.cc2
-rw-r--r--source/blender/io/alembic/intern/abc_reader_curves.cc2
-rw-r--r--source/blender/io/usd/intern/usd_reader_curve.cc2
-rw-r--r--source/blender/io/usd/intern/usd_reader_nurbs.cc2
-rw-r--r--source/blender/makesdna/DNA_curve_types.h10
-rw-r--r--source/blender/makesdna/DNA_object_types.h3
-rw-r--r--source/blender/makesrna/intern/rna_curve.c6
-rw-r--r--source/blender/modifiers/intern/MOD_nodes.cc7
25 files changed, 237 insertions, 592 deletions
diff --git a/release/scripts/startup/bl_operators/geometry_nodes.py b/release/scripts/startup/bl_operators/geometry_nodes.py
index ec2887a1a74..258a73bd70b 100644
--- a/release/scripts/startup/bl_operators/geometry_nodes.py
+++ b/release/scripts/startup/bl_operators/geometry_nodes.py
@@ -42,8 +42,8 @@ def geometry_node_group_empty_new():
def geometry_modifier_poll(context):
ob = context.object
- # Test object support for geometry node modifier (No curve, or hair object support yet)
- if not ob or ob.type not in {'MESH', 'POINTCLOUD', 'VOLUME'}:
+ # Test object support for geometry node modifier (No hair object support yet)
+ if not ob or ob.type not in {'MESH', 'POINTCLOUD', 'VOLUME', 'CURVE', 'FONT'}:
return False
return True
diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py
index 85f672cd50f..e5b675db2c5 100644
--- a/release/scripts/startup/bl_ui/properties_data_curve.py
+++ b/release/scripts/startup/bl_ui/properties_data_curve.py
@@ -120,7 +120,6 @@ class DATA_PT_shape_curve(CurveButtonsPanel, Panel):
sub = col.column()
sub.active = (curve.dimensions == '2D' or (curve.bevel_mode != 'OBJECT' and curve.dimensions == '3D'))
sub.prop(curve, "fill_mode")
- col.prop(curve, "use_fill_deform")
if is_curve:
col = layout.column()
diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h
index 0f37ba6c4ce..37e144ebbd3 100644
--- a/source/blender/blenkernel/BKE_displist.h
+++ b/source/blender/blenkernel/BKE_displist.h
@@ -99,7 +99,7 @@ void BKE_displist_make_mball_forRender(struct Depsgraph *depsgraph,
struct Object *ob,
struct ListBase *dispbase);
-bool BKE_curve_calc_modifiers_pre(struct Depsgraph *depsgraph,
+void BKE_curve_calc_modifiers_pre(struct Depsgraph *depsgraph,
const struct Scene *scene,
struct Object *ob,
struct ListBase *source_nurb,
diff --git a/source/blender/blenkernel/intern/displist.cc b/source/blender/blenkernel/intern/displist.cc
index 58509e95de6..bdab508eb1f 100644
--- a/source/blender/blenkernel/intern/displist.cc
+++ b/source/blender/blenkernel/intern/displist.cc
@@ -40,6 +40,7 @@
#include "BLI_math.h"
#include "BLI_memarena.h"
#include "BLI_scanfill.h"
+#include "BLI_span.hh"
#include "BLI_string.h"
#include "BLI_utildefines.h"
@@ -47,6 +48,7 @@
#include "BKE_curve.h"
#include "BKE_displist.h"
#include "BKE_font.h"
+#include "BKE_geometry_set.hh"
#include "BKE_key.h"
#include "BKE_lattice.h"
#include "BKE_lib_id.h"
@@ -55,6 +57,7 @@
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
+#include "BKE_spline.hh"
#include "BLI_sys_types.h" /* For #intptr_t support. */
@@ -745,10 +748,7 @@ static ModifierData *curve_get_tessellate_point(const Scene *scene,
return pretessellatePoint;
}
-/**
- * \return True if any modifier was applied.
- */
-bool BKE_curve_calc_modifiers_pre(Depsgraph *depsgraph,
+void BKE_curve_calc_modifiers_pre(Depsgraph *depsgraph,
const Scene *scene,
Object *ob,
ListBase *source_nurb,
@@ -793,7 +793,6 @@ bool BKE_curve_calc_modifiers_pre(Depsgraph *depsgraph,
const ModifierEvalContext mectx = {depsgraph, ob, apply_flag};
ModifierData *pretessellatePoint = curve_get_tessellate_point(scene, ob, for_render, editmode);
- bool modified = false;
if (pretessellatePoint) {
VirtualModifierData virtualModifierData;
@@ -813,7 +812,6 @@ bool BKE_curve_calc_modifiers_pre(Depsgraph *depsgraph,
}
mti->deformVerts(md, &mectx, nullptr, deformedVerts, numVerts);
- modified = true;
if (md == pretessellatePoint) {
break;
@@ -832,48 +830,59 @@ bool BKE_curve_calc_modifiers_pre(Depsgraph *depsgraph,
if (keyVerts) {
MEM_freeN(keyVerts);
}
- return modified;
}
-static float (*displist_vert_coords_alloc(ListBase *dispbase, int *r_vert_len))[3]
+/**
+ * \return True if the deformed curve control point data should be implicitly
+ * converted directly to a mesh, or false if it can be left as curve data via #CurveEval.
+ */
+static bool do_curve_implicit_mesh_conversion(const Curve *curve,
+ ModifierData *first_modifier,
+ const Scene *scene,
+ const ModifierMode required_mode)
{
- *r_vert_len = 0;
+ /* Skip implicit filling and conversion to mesh when using "fast text editing". */
+ if (curve->flag & CU_FAST) {
+ return false;
+ }
- LISTBASE_FOREACH (DispList *, dl, dispbase) {
- *r_vert_len += (dl->type == DL_INDEX3) ? dl->nr : dl->parts * dl->nr;
+ /* Do implicit conversion to mesh with the object bevel mode. */
+ if (curve->bevel_mode == CU_BEV_MODE_OBJECT && curve->bevobj != nullptr) {
+ return true;
}
- float(*allverts)[3] = (float(*)[3])MEM_mallocN(sizeof(float[3]) * (*r_vert_len), __func__);
- float *fp = (float *)allverts;
- LISTBASE_FOREACH (DispList *, dl, dispbase) {
- const int ofs = 3 * ((dl->type == DL_INDEX3) ? dl->nr : dl->parts * dl->nr);
- memcpy(fp, dl->verts, sizeof(float) * ofs);
- fp += ofs;
+ /* 2D curves are sometimes implicitly filled and converted to a mesh. */
+ if (CU_DO_2DFILL(curve)) {
+ return true;
}
- return allverts;
-}
+ /* Curve objects with implicit "tube" meshes should convert implicitly to a mesh. */
+ if (curve->ext1 != 0.0f || curve->ext2 != 0.0f) {
+ return true;
+ }
-static void displist_vert_coords_apply(ListBase *dispbase, const float (*allverts)[3])
-{
- const float *fp = (float *)allverts;
- LISTBASE_FOREACH (DispList *, dl, dispbase) {
- int ofs = 3 * ((dl->type == DL_INDEX3) ? dl->nr : dl->parts * dl->nr);
- memcpy(dl->verts, fp, sizeof(float) * ofs);
- fp += ofs;
+ /* If a non-geometry-nodes modifier is enabled before a nodes modifier,
+ * force conversion to mesh, since only the nodes modifier supports curve data. */
+ ModifierData *md = first_modifier;
+ for (; md; md = md->next) {
+ if (BKE_modifier_is_enabled(scene, md, required_mode)) {
+ if (md->type == eModifierType_Nodes) {
+ break;
+ }
+ return true;
+ }
}
+
+ return false;
}
-static void curve_calc_modifiers_post(Depsgraph *depsgraph,
- const Scene *scene,
- Object *ob,
- ListBase *dispbase,
- const bool for_render,
- const bool force_mesh_conversion,
- Mesh **r_final)
+static GeometrySet curve_calc_modifiers_post(Depsgraph *depsgraph,
+ const Scene *scene,
+ Object *ob,
+ const ListBase *dispbase,
+ const bool for_render)
{
const Curve *cu = (const Curve *)ob->data;
-
const bool editmode = (!for_render && (cu->editnurb || cu->editfont));
const bool use_cache = !for_render;
@@ -897,166 +906,64 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph,
BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData) :
pretessellatePoint->next;
- if (r_final && *r_final) {
- BKE_id_free(nullptr, *r_final);
+ GeometrySet geometry_set;
+ if (ob->type == OB_SURF || do_curve_implicit_mesh_conversion(cu, md, scene, required_mode)) {
+ Mesh *mesh = BKE_mesh_new_nomain_from_curve_displist(ob, dispbase);
+ geometry_set.replace_mesh(mesh);
+ }
+ else {
+ std::unique_ptr<CurveEval> curve_eval = curve_eval_from_dna_curve(
+ *cu, ob->runtime.curve_cache->deformed_nurbs);
+ geometry_set.replace_curve(curve_eval.release());
}
- Mesh *modified = nullptr;
- float(*vertCos)[3] = nullptr;
- int totvert = 0;
for (; md; md = md->next) {
const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type);
-
if (!BKE_modifier_is_enabled(scene, md, required_mode)) {
continue;
}
- /* If we need normals, no choice, have to convert to mesh now. */
- const bool need_normal = mti->dependsOnNormals != nullptr && mti->dependsOnNormals(md);
- /* XXX 2.8 : now that batch cache is stored inside the ob->data
- * we need to create a Mesh for each curve that uses modifiers. */
- if (modified == nullptr /* && need_normal */) {
- if (vertCos != nullptr) {
- displist_vert_coords_apply(dispbase, vertCos);
- }
-
- if (ELEM(ob->type, OB_CURVE, OB_FONT) && (cu->flag & CU_DEFORM_FILL)) {
- curve_to_filledpoly(cu, dispbase);
- }
+ if (md->type == eModifierType_Nodes) {
+ mti->modifyGeometrySet(md, &mectx_apply, &geometry_set);
+ continue;
+ }
- modified = BKE_mesh_new_nomain_from_curve_displist(ob, dispbase);
+ if (!geometry_set.has_mesh()) {
+ geometry_set.replace_mesh(BKE_mesh_new_nomain(0, 0, 0, 0, 0));
}
+ Mesh *mesh = geometry_set.get_mesh_for_write();
- if (mti->type == eModifierTypeType_OnlyDeform ||
- (mti->type == eModifierTypeType_DeformOrConstruct && !modified)) {
- if (modified) {
- if (!vertCos) {
- vertCos = BKE_mesh_vert_coords_alloc(modified, &totvert);
- }
- if (need_normal) {
- BKE_mesh_ensure_normals(modified);
- }
- mti->deformVerts(md, &mectx_deform, modified, vertCos, totvert);
- }
- else {
- if (!vertCos) {
- vertCos = displist_vert_coords_alloc(dispbase, &totvert);
- }
- mti->deformVerts(md, &mectx_deform, nullptr, vertCos, totvert);
+ if (mti->type == eModifierTypeType_OnlyDeform) {
+ int totvert;
+ float(*vertex_coords)[3] = BKE_mesh_vert_coords_alloc(mesh, &totvert);
+ if (mti->dependsOnNormals != nullptr && mti->dependsOnNormals(md)) {
+ BKE_mesh_ensure_normals(mesh);
}
+ mti->deformVerts(md, &mectx_deform, mesh, vertex_coords, totvert);
+ BKE_mesh_vert_coords_apply(mesh, vertex_coords);
+ MEM_freeN(vertex_coords);
}
else {
- if (!r_final) {
- /* makeDisplistCurveTypes could be used for beveling, where mesh
- * is totally unnecessary, so we could stop modifiers applying
- * when we found constructive modifier but mesh is unwanted. */
- break;
- }
-
- if (modified) {
- if (vertCos) {
- Mesh *temp_mesh = (Mesh *)BKE_id_copy_ex(
- nullptr, &modified->id, nullptr, LIB_ID_COPY_LOCALIZE);
- BKE_id_free(nullptr, modified);
- modified = temp_mesh;
-
- BKE_mesh_vert_coords_apply(modified, vertCos);
- }
- }
- else {
- if (vertCos) {
- displist_vert_coords_apply(dispbase, vertCos);
- }
-
- if (ELEM(ob->type, OB_CURVE, OB_FONT) && (cu->flag & CU_DEFORM_FILL)) {
- curve_to_filledpoly(cu, dispbase);
- }
-
- modified = BKE_mesh_new_nomain_from_curve_displist(ob, dispbase);
- }
-
- if (vertCos) {
- /* Vertex coordinates were applied to necessary data, could free it */
- MEM_freeN(vertCos);
- vertCos = nullptr;
- }
-
- if (need_normal) {
- BKE_mesh_ensure_normals(modified);
+ if (mti->dependsOnNormals != nullptr && mti->dependsOnNormals(md)) {
+ BKE_mesh_ensure_normals(mesh);
}
- Mesh *mesh_applied = mti->modifyMesh(md, &mectx_apply, modified);
-
- if (mesh_applied) {
- if (modified && modified != mesh_applied) {
- BKE_id_free(nullptr, modified);
- }
- modified = mesh_applied;
+ Mesh *output_mesh = mti->modifyMesh(md, &mectx_apply, mesh);
+ if (mesh != output_mesh) {
+ geometry_set.replace_mesh(output_mesh);
}
}
}
- if (vertCos) {
- if (modified) {
- Mesh *temp_mesh = (Mesh *)BKE_id_copy_ex(
- nullptr, &modified->id, nullptr, LIB_ID_COPY_LOCALIZE);
- BKE_id_free(nullptr, modified);
- modified = temp_mesh;
+ if (geometry_set.has_mesh()) {
+ Mesh *final_mesh = geometry_set.get_mesh_for_write();
- BKE_mesh_vert_coords_apply(modified, vertCos);
- BKE_mesh_calc_normals(modified);
+ BKE_mesh_calc_normals(final_mesh);
- MEM_freeN(vertCos);
- }
- else {
- displist_vert_coords_apply(dispbase, vertCos);
- MEM_freeN(vertCos);
- vertCos = nullptr;
- }
+ BLI_strncpy(final_mesh->id.name, cu->id.name, sizeof(final_mesh->id.name));
+ *((short *)final_mesh->id.name) = ID_ME;
}
- if (r_final) {
- if (force_mesh_conversion && !modified) {
- /* XXX 2.8 : This is a workaround for by some deeper technical debts:
- * - DRW Batch cache is stored inside the ob->data.
- * - Curve data is not COWed for instances that use different modifiers.
- * This can causes the modifiers to be applied on all user of the same data-block
- * (see T71055)
- *
- * The easy workaround is to force to generate a Mesh that will be used for display data
- * since a Mesh output is already used for generative modifiers.
- * However it does not fix problems with actual edit data still being shared.
- *
- * The right solution would be to COW the Curve data block at the input of the modifier
- * stack just like what the mesh modifier does.
- */
- modified = BKE_mesh_new_nomain_from_curve_displist(ob, dispbase);
- }
-
- if (modified) {
-
- /* XXX2.8(Sybren): make sure the face normals are recalculated as well */
- BKE_mesh_ensure_normals(modified);
-
- /* Special tweaks, needed since neither BKE_mesh_new_nomain_from_template() nor
- * BKE_mesh_new_nomain_from_curve_displist() properly duplicate mat info... */
- BLI_strncpy(modified->id.name, cu->id.name, sizeof(modified->id.name));
- *((short *)modified->id.name) = ID_ME;
- MEM_SAFE_FREE(modified->mat);
- /* Set flag which makes it easier to see what's going on in a debugger. */
- modified->id.tag |= LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT;
- modified->mat = (Material **)MEM_dupallocN(cu->mat);
- modified->totcol = cu->totcol;
-
- (*r_final) = modified;
- }
- else {
- (*r_final) = nullptr;
- }
- }
- else if (modified != nullptr) {
- /* Pretty stupid to generate that whole mesh if it's unused, yet we have to free it. */
- BKE_id_free(nullptr, modified);
- }
+ return geometry_set;
}
static void displist_surf_indices(DispList *dl)
@@ -1109,8 +1016,7 @@ static void evaluate_surface_object(Depsgraph *depsgraph,
BKE_nurbList_duplicate(deformed_nurbs, &cu->nurb);
}
- bool force_mesh_conversion = BKE_curve_calc_modifiers_pre(
- depsgraph, scene, ob, deformed_nurbs, deformed_nurbs, for_render);
+ BKE_curve_calc_modifiers_pre(depsgraph, scene, ob, deformed_nurbs, deformed_nurbs, for_render);
LISTBASE_FOREACH (const Nurb *, nu, deformed_nurbs) {
if (!(for_render || nu->hide == 0) || !BKE_nurb_check_valid_uv(nu)) {
@@ -1173,8 +1079,14 @@ static void evaluate_surface_object(Depsgraph *depsgraph,
}
}
- curve_calc_modifiers_post(
- depsgraph, scene, ob, r_dispbase, for_render, force_mesh_conversion, r_final);
+ curve_to_filledpoly(cu, r_dispbase);
+ GeometrySet geometry_set = curve_calc_modifiers_post(
+ depsgraph, scene, ob, r_dispbase, for_render);
+ if (!geometry_set.has_mesh()) {
+ geometry_set.replace_mesh(BKE_mesh_new_nomain(0, 0, 0, 0, 0));
+ }
+ MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
+ *r_final = mesh_component.release();
}
static void rotateBevelPiece(const Curve *cu,
@@ -1394,12 +1306,11 @@ static void calc_bevfac_mapping(const Curve *cu,
}
}
-static void evaluate_curve_type_object(Depsgraph *depsgraph,
- const Scene *scene,
- Object *ob,
- const bool for_render,
- ListBase *r_dispbase,
- Mesh **r_final)
+static GeometrySet evaluate_curve_type_object(Depsgraph *depsgraph,
+ const Scene *scene,
+ Object *ob,
+ const bool for_render,
+ ListBase *r_dispbase)
{
BLI_assert(ELEM(ob->type, OB_CURVE, OB_FONT));
const Curve *cu = (const Curve *)ob->data;
@@ -1413,8 +1324,7 @@ static void evaluate_curve_type_object(Depsgraph *depsgraph,
BKE_nurbList_duplicate(deformed_nurbs, BKE_curve_nurbs_get_for_read(cu));
}
- bool force_mesh_conversion = BKE_curve_calc_modifiers_pre(
- depsgraph, scene, ob, deformed_nurbs, deformed_nurbs, for_render);
+ BKE_curve_calc_modifiers_pre(depsgraph, scene, ob, deformed_nurbs, deformed_nurbs, for_render);
BKE_curve_bevelList_make(ob, deformed_nurbs, for_render);
@@ -1603,16 +1513,8 @@ static void evaluate_curve_type_object(Depsgraph *depsgraph,
BKE_displist_free(&dlbev);
- if (!(cu->flag & CU_DEFORM_FILL)) {
- curve_to_filledpoly(cu, r_dispbase);
- }
-
- curve_calc_modifiers_post(
- depsgraph, scene, ob, r_dispbase, for_render, force_mesh_conversion, r_final);
-
- if (cu->flag & CU_DEFORM_FILL && !ob->runtime.data_eval) {
- curve_to_filledpoly(cu, r_dispbase);
- }
+ curve_to_filledpoly(cu, r_dispbase);
+ return curve_calc_modifiers_post(depsgraph, scene, ob, r_dispbase, for_render);
}
void BKE_displist_make_curveTypes(Depsgraph *depsgraph,
@@ -1621,25 +1523,43 @@ void BKE_displist_make_curveTypes(Depsgraph *depsgraph,
const bool for_render)
{
BLI_assert(ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT));
+ Curve &cow_curve = *(Curve *)ob->data;
BKE_object_free_derived_caches(ob);
+ cow_curve.curve_eval = nullptr;
- if (!ob->runtime.curve_cache) {
- ob->runtime.curve_cache = (CurveCache *)MEM_callocN(sizeof(CurveCache), __func__);
- }
-
+ ob->runtime.curve_cache = (CurveCache *)MEM_callocN(sizeof(CurveCache), __func__);
ListBase *dispbase = &(ob->runtime.curve_cache->disp);
- Mesh *mesh_eval = nullptr;
if (ob->type == OB_SURF) {
+ Mesh *mesh_eval;
evaluate_surface_object(depsgraph, scene, ob, for_render, dispbase, &mesh_eval);
+ BKE_object_eval_assign_data(ob, &mesh_eval->id, true);
}
else {
- evaluate_curve_type_object(depsgraph, scene, ob, for_render, dispbase, &mesh_eval);
- }
+ GeometrySet geometry = evaluate_curve_type_object(depsgraph, scene, ob, for_render, dispbase);
+
+ if (geometry.has_curve()) {
+ /* Assign the evaluated curve to the object's "data_eval". In addition to the curve_eval
+ * added to the curve here, it will also contain a copy of the original curve's data. This is
+ * essential, because it maintains the expected behavior for evaluated curve data from before
+ * the CurveEval data type was introduced, when an evaluated object's curve data was just a
+ * copy of the original curve and everything else ended up in #CurveCache. */
+ CurveComponent &curve_component = geometry.get_component_for_write<CurveComponent>();
+ cow_curve.curve_eval = curve_component.get_for_write();
+ BKE_object_eval_assign_data(ob, &cow_curve.id, false);
+ }
+ else if (geometry.has_mesh()) {
+ /* Most areas of Blender don't yet know how to look in #geometry_set_eval for evaluated mesh
+ * data, and look in #data_eval instead. When the object evaluates to a curve, that field
+ * must be used for the evaluated curve data, but otherwise we can use the field to store a
+ * pointer to the mesh, so more areas can retrieve the mesh. */
+ MeshComponent &mesh_component = geometry.get_component_for_write<MeshComponent>();
+ Mesh *mesh_eval = mesh_component.get_for_write();
+ BKE_object_eval_assign_data(ob, &mesh_eval->id, false);
+ }
- if (mesh_eval != nullptr) {
- BKE_object_eval_assign_data(ob, &mesh_eval->id, true);
+ ob->runtime.geometry_set_eval = new GeometrySet(std::move(geometry));
}
boundbox_displist_object(ob);
@@ -1656,7 +1576,9 @@ void BKE_displist_make_curveTypes_forRender(
evaluate_surface_object(depsgraph, scene, ob, true, r_dispbase, r_final);
}
else {
- evaluate_curve_type_object(depsgraph, scene, ob, true, r_dispbase, r_final);
+ GeometrySet geometry_set = evaluate_curve_type_object(depsgraph, scene, ob, true, r_dispbase);
+ MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
+ *r_final = mesh_component.release();
}
}
diff --git a/source/blender/blenkernel/intern/geometry_component_curve.cc b/source/blender/blenkernel/intern/geometry_component_curve.cc
index a24b60ee288..afafd766760 100644
--- a/source/blender/blenkernel/intern/geometry_component_curve.cc
+++ b/source/blender/blenkernel/intern/geometry_component_curve.cc
@@ -64,6 +64,8 @@ void CurveComponent::clear()
delete curve_;
}
if (curve_for_render_ != nullptr) {
+ /* The curve created by this component should not have any edit mode data. */
+ BLI_assert(curve_for_render_->editfont == nullptr && curve_for_render_->editnurb == nullptr);
BKE_id_free(nullptr, curve_for_render_);
curve_for_render_ = nullptr;
}
diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc
index dafebef1812..e717d289894 100644
--- a/source/blender/blenkernel/intern/geometry_set.cc
+++ b/source/blender/blenkernel/intern/geometry_set.cc
@@ -408,7 +408,7 @@ bool BKE_object_has_geometry_set_instances(const Object *ob)
if (ob->type == OB_VOLUME) {
return has_mesh || has_pointcloud || has_curve;
}
- if (ob->type == OB_CURVE) {
+ if (ELEM(ob->type, OB_CURVE, OB_FONT)) {
return has_mesh || has_pointcloud || has_volume;
}
return false;
diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc
index 0e19324a3c1..9dca2c2907e 100644
--- a/source/blender/blenkernel/intern/geometry_set_instances.cc
+++ b/source/blender/blenkernel/intern/geometry_set_instances.cc
@@ -51,16 +51,6 @@ static void add_final_mesh_as_geometry_component(const Object &object, GeometryS
}
}
-static void add_curve_data_as_geometry_component(const Object &object, GeometrySet &geometry_set)
-{
- BLI_assert(object.type == OB_CURVE);
- if (object.data != nullptr) {
- std::unique_ptr<CurveEval> curve = curve_eval_from_dna_curve(*(const Curve *)object.data);
- CurveComponent &curve_component = geometry_set.get_component_for_write<CurveComponent>();
- curve_component.replace(curve.release(), GeometryOwnershipType::Owned);
- }
-}
-
/**
* \note This doesn't extract instances from the "dupli" system for non-geometry-nodes instances.
*/
@@ -84,9 +74,6 @@ static GeometrySet object_get_geometry_set_for_read(const Object &object)
if (object.type == OB_MESH) {
add_final_mesh_as_geometry_component(object, geometry_set);
}
- else if (object.type == OB_CURVE) {
- add_curve_data_as_geometry_component(object, geometry_set);
- }
/* TODO: Cover the case of point-clouds without modifiers-- they may not be covered by the
* #geometry_set_eval case above. */
diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c
index d5524312612..9fd75be0d35 100644
--- a/source/blender/blenkernel/intern/mesh_convert.c
+++ b/source/blender/blenkernel/intern/mesh_convert.c
@@ -483,8 +483,24 @@ static int mesh_nurbs_displist_to_mdata(const Curve *cu,
return 0;
}
+/**
+ * Copy evaluated texture space from curve to mesh.
+ *
+ * \note We disable auto texture space feature since that will cause texture space to evaluate
+ * differently for curve and mesh, since curves use control points and handles to calculate the
+ * bounding box, and mesh uses the tessellated curve.
+ */
+static void mesh_copy_texture_space_from_curve_type(const Curve *cu, Mesh *me)
+{
+ me->texflag = cu->texflag & ~CU_AUTOSPACE;
+ copy_v3_v3(me->loc, cu->loc);
+ copy_v3_v3(me->size, cu->size);
+ BKE_mesh_texspace_calc(me);
+}
+
Mesh *BKE_mesh_new_nomain_from_curve_displist(const Object *ob, const ListBase *dispbase)
{
+ const Curve *cu = ob->data;
Mesh *mesh;
MVert *allvert;
MEdge *alledge;
@@ -493,7 +509,7 @@ Mesh *BKE_mesh_new_nomain_from_curve_displist(const Object *ob, const ListBase *
MLoopUV *alluv = NULL;
int totvert, totedge, totloop, totpoly;
- if (mesh_nurbs_displist_to_mdata(ob->data,
+ if (mesh_nurbs_displist_to_mdata(cu,
dispbase,
&allvert,
&totvert,
@@ -529,6 +545,12 @@ Mesh *BKE_mesh_new_nomain_from_curve_displist(const Object *ob, const ListBase *
CustomData_add_layer_named(&mesh->ldata, CD_MLOOPUV, CD_ASSIGN, alluv, totloop, uvname);
}
+ mesh_copy_texture_space_from_curve_type(cu, mesh);
+
+ /* Copy curve materials. */
+ mesh->mat = (Material **)MEM_dupallocN(cu->mat);
+ mesh->totcol = cu->totcol;
+
MEM_freeN(allvert);
MEM_freeN(alledge);
MEM_freeN(allloop);
@@ -612,17 +634,7 @@ static void mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const char
me->totcol = cu->totcol;
me->mat = cu->mat;
- /* Copy evaluated texture space from curve to mesh.
- *
- * Note that we disable auto texture space feature since that will cause
- * texture space to evaluate differently for curve and mesh, since curve
- * uses CV to calculate bounding box, and mesh uses what is coming from
- * tessellated curve.
- */
- me->texflag = cu->texflag & ~CU_AUTOSPACE;
- copy_v3_v3(me->loc, cu->loc);
- copy_v3_v3(me->size, cu->size);
- BKE_mesh_texspace_calc(me);
+ mesh_copy_texture_space_from_curve_type(cu, me);
cu->mat = NULL;
cu->totcol = 0;
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index b4343578eab..465ec9dc665 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -1341,6 +1341,11 @@ bool BKE_object_support_modifier_type_check(const Object *ob, int modifier_type)
{
const ModifierTypeInfo *mti = BKE_modifier_get_info(modifier_type);
+ /* Surface and lattice objects don't output geometry sets. */
+ if (mti->modifyGeometrySet != NULL && ELEM(ob->type, OB_SURF, OB_LATTICE)) {
+ return false;
+ }
+
/* Only geometry objects should be able to get modifiers T25291. */
if (ob->type == OB_HAIR) {
return (mti->modifyHair != NULL) || (mti->flags & eModifierTypeFlag_AcceptsVertexCosOnly);
diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc
index 47d4d03d1e1..04739ec19d3 100644
--- a/source/blender/blenkernel/intern/object_dupli.cc
+++ b/source/blender/blenkernel/intern/object_dupli.cc
@@ -855,7 +855,7 @@ static void make_duplis_geometry_set_impl(const DupliContext *ctx,
dupli->ob_data = (ID *)volume;
}
}
- if (ctx->object->type != OB_CURVE || geometry_set_is_instance) {
+ if (!ELEM(ctx->object->type, OB_CURVE, OB_FONT) || geometry_set_is_instance) {
const CurveComponent *curve_component = geometry_set.get_component_for_read<CurveComponent>();
if (curve_component != nullptr) {
const Curve *curve = curve_component->get_curve_for_render();
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc
index 30ec9e948fd..1081528ece1 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc
@@ -98,7 +98,7 @@ void ObjectRuntimeBackup::restore_to_object(Object *object)
object->runtime = runtime;
object->runtime.data_orig = data_orig;
object->runtime.bb = bb;
- if (ELEM(object->type, OB_MESH, OB_LATTICE) && data_eval != nullptr) {
+ if (ELEM(object->type, OB_MESH, OB_LATTICE, OB_CURVE, OB_FONT) && data_eval != nullptr) {
if (object->id.recalc & ID_RECALC_GEOMETRY) {
/* If geometry is tagged for update it means, that part of
* evaluated mesh are not valid anymore. In this case we can not
@@ -112,9 +112,11 @@ void ObjectRuntimeBackup::restore_to_object(Object *object)
BKE_object_free_derived_caches(object);
}
else {
- /* Do same thing as object update: override actual object data
- * pointer with evaluated datablock. */
- object->data = data_eval;
+ /* Do same thing as object update: override actual object data pointer with evaluated
+ * datablock, but only if the evaluated data has the same type as the original data. */
+ if (GS(((ID *)object->data)->name) == GS(data_eval->name)) {
+ object->data = data_eval;
+ }
/* Evaluated mesh simply copied edit_mesh pointer from
* original mesh during update, need to make sure no dead
diff --git a/source/blender/draw/engines/overlay/overlay_edit_text.c b/source/blender/draw/engines/overlay/overlay_edit_text.c
index fd68b319f02..5356700f156 100644
--- a/source/blender/draw/engines/overlay/overlay_edit_text.c
+++ b/source/blender/draw/engines/overlay/overlay_edit_text.c
@@ -180,19 +180,12 @@ static void edit_text_cache_populate_boxes(OVERLAY_Data *vedata, Object *ob)
void OVERLAY_edit_text_cache_populate(OVERLAY_Data *vedata, Object *ob)
{
OVERLAY_PrivateData *pd = vedata->stl->pd;
- Curve *cu = ob->data;
struct GPUBatch *geom;
bool do_in_front = (ob->dtx & OB_DRAW_IN_FRONT) != 0;
- bool has_surface = (cu->flag & (CU_FRONT | CU_BACK)) || cu->ext1 != 0.0f || cu->ext2 != 0.0f;
- if ((cu->flag & CU_FAST) || !has_surface) {
- geom = DRW_cache_text_edge_wire_get(ob);
- if (geom) {
- DRW_shgroup_call(pd->edit_text_wire_grp[do_in_front], geom, ob);
- }
- }
- else {
- /* object mode draws */
+ geom = DRW_cache_text_edge_wire_get(ob);
+ if (geom) {
+ DRW_shgroup_call(pd->edit_text_wire_grp[do_in_front], geom, ob);
}
edit_text_cache_populate_select(vedata, ob);
diff --git a/source/blender/draw/engines/overlay/overlay_wireframe.c b/source/blender/draw/engines/overlay/overlay_wireframe.c
index b8a61ecc403..fde376beeb2 100644
--- a/source/blender/draw/engines/overlay/overlay_wireframe.c
+++ b/source/blender/draw/engines/overlay/overlay_wireframe.c
@@ -218,18 +218,10 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata,
struct GPUBatch *geom = NULL;
switch (ob->type) {
case OB_CURVE:
- if (!pd->wireframe_mode && !use_wire && ob->runtime.curve_cache &&
- BKE_displist_has_faces(&ob->runtime.curve_cache->disp)) {
- break;
- }
geom = DRW_cache_curve_edge_wire_get(ob);
break;
case OB_FONT:
- if (!pd->wireframe_mode && !use_wire && ob->runtime.curve_cache &&
- BKE_displist_has_faces(&ob->runtime.curve_cache->disp)) {
- break;
- }
- geom = DRW_cache_text_loose_edges_get(ob);
+ geom = DRW_cache_text_edge_wire_get(ob);
break;
case OB_SURF:
geom = DRW_cache_surf_edge_wire_get(ob);
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index 000ab540813..a3a5d6b065a 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -794,6 +794,10 @@ GPUBatch *DRW_gpencil_dummy_buffer_get(void)
/* -------------------------------------------------------------------- */
/** \name Common Object API
+ *
+ * \note Curve and text objects evaluate to the evaluated geometry set's mesh component if
+ * they have a surface, so curve objects themselves do not have a surface (the mesh component
+ * is presented to render engines as a separate object).
* \{ */
GPUBatch *DRW_cache_object_all_edges_get(Object *ob)
@@ -814,11 +818,11 @@ GPUBatch *DRW_cache_object_edge_detection_get(Object *ob, bool *r_is_manifold)
case OB_MESH:
return DRW_cache_mesh_edge_detection_get(ob, r_is_manifold);
case OB_CURVE:
- return DRW_cache_curve_edge_detection_get(ob, r_is_manifold);
+ return NULL;
case OB_SURF:
return DRW_cache_surf_edge_detection_get(ob, r_is_manifold);
case OB_FONT:
- return DRW_cache_text_edge_detection_get(ob, r_is_manifold);
+ return NULL;
case OB_MBALL:
return DRW_cache_mball_edge_detection_get(ob, r_is_manifold);
case OB_HAIR:
@@ -838,11 +842,11 @@ GPUBatch *DRW_cache_object_face_wireframe_get(Object *ob)
case OB_MESH:
return DRW_cache_mesh_face_wireframe_get(ob);
case OB_CURVE:
- return DRW_cache_curve_face_wireframe_get(ob);
+ return NULL;
case OB_SURF:
return DRW_cache_surf_face_wireframe_get(ob);
case OB_FONT:
- return DRW_cache_text_face_wireframe_get(ob);
+ return NULL;
case OB_MBALL:
return DRW_cache_mball_face_wireframe_get(ob);
case OB_HAIR:
@@ -865,11 +869,11 @@ GPUBatch *DRW_cache_object_loose_edges_get(struct Object *ob)
case OB_MESH:
return DRW_cache_mesh_loose_edges_get(ob);
case OB_CURVE:
- return DRW_cache_curve_loose_edges_get(ob);
+ return NULL;
case OB_SURF:
return DRW_cache_surf_loose_edges_get(ob);
case OB_FONT:
- return DRW_cache_text_loose_edges_get(ob);
+ return NULL;
case OB_MBALL:
return NULL;
case OB_HAIR:
@@ -889,11 +893,11 @@ GPUBatch *DRW_cache_object_surface_get(Object *ob)
case OB_MESH:
return DRW_cache_mesh_surface_get(ob);
case OB_CURVE:
- return DRW_cache_curve_surface_get(ob);
+ return NULL;
case OB_SURF:
return DRW_cache_surf_surface_get(ob);
case OB_FONT:
- return DRW_cache_text_surface_get(ob);
+ return NULL;
case OB_MBALL:
return DRW_cache_mball_surface_get(ob);
case OB_HAIR:
@@ -939,9 +943,9 @@ int DRW_cache_object_material_count_get(struct Object *ob)
Mesh *me = BKE_object_get_evaluated_mesh(ob);
if (me != NULL && type != OB_POINTCLOUD) {
- /* Some object types (e.g. curves) can have a Curve in ob->data, but will be rendered as mesh.
- * For point clouds this never happens. Ideally this check would happen at another level and we
- * would just have to care about ob->data here. */
+ /* Some object types can have one data type in ob->data, but will be rendered as mesh.
+ * For point clouds this never happens. Ideally this check would happen at another level
+ * and we would just have to care about ob->data here. */
type = OB_MESH;
}
@@ -974,11 +978,11 @@ GPUBatch **DRW_cache_object_surface_material_get(struct Object *ob,
case OB_MESH:
return DRW_cache_mesh_surface_shaded_get(ob, gpumat_array, gpumat_array_len);
case OB_CURVE:
- return DRW_cache_curve_surface_shaded_get(ob, gpumat_array, gpumat_array_len);
+ return NULL;
case OB_SURF:
return DRW_cache_surf_surface_shaded_get(ob, gpumat_array, gpumat_array_len);
case OB_FONT:
- return DRW_cache_text_surface_shaded_get(ob, gpumat_array, gpumat_array_len);
+ return NULL;
case OB_MBALL:
return DRW_cache_mball_surface_shaded_get(ob, gpumat_array, gpumat_array_len);
case OB_HAIR:
@@ -2929,20 +2933,13 @@ GPUBatch *DRW_cache_mesh_surface_mesh_analysis_get(Object *ob)
GPUBatch *DRW_cache_curve_edge_wire_get(Object *ob)
{
BLI_assert(ob->type == OB_CURVE);
-
struct Curve *cu = ob->data;
- struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
- if (mesh_eval != NULL) {
- return DRW_mesh_batch_cache_get_loose_edges(mesh_eval);
- }
-
return DRW_curve_batch_cache_get_wire_edge(cu);
}
GPUBatch *DRW_cache_curve_edge_normal_get(Object *ob)
{
BLI_assert(ob->type == OB_CURVE);
-
struct Curve *cu = ob->data;
return DRW_curve_batch_cache_get_normal_edge(cu);
}
@@ -2963,75 +2960,6 @@ GPUBatch *DRW_cache_curve_vert_overlay_get(Object *ob)
return DRW_curve_batch_cache_get_edit_verts(cu);
}
-GPUBatch *DRW_cache_curve_surface_get(Object *ob)
-{
- BLI_assert(ob->type == OB_CURVE);
-
- struct Curve *cu = ob->data;
- struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
- if (mesh_eval != NULL) {
- return DRW_mesh_batch_cache_get_surface(mesh_eval);
- }
-
- return DRW_curve_batch_cache_get_triangles_with_normals(cu);
-}
-
-GPUBatch *DRW_cache_curve_loose_edges_get(Object *ob)
-{
- BLI_assert(ob->type == OB_CURVE);
-
- struct Curve *cu = ob->data;
- struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
- if (mesh_eval != NULL) {
- return DRW_mesh_batch_cache_get_loose_edges(mesh_eval);
- }
-
- /* TODO */
- UNUSED_VARS(cu);
- return NULL;
-}
-
-GPUBatch *DRW_cache_curve_face_wireframe_get(Object *ob)
-{
- BLI_assert(ob->type == OB_CURVE);
-
- struct Curve *cu = ob->data;
- struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
- if (mesh_eval != NULL) {
- return DRW_mesh_batch_cache_get_wireframes_face(mesh_eval);
- }
-
- return DRW_curve_batch_cache_get_wireframes_face(cu);
-}
-
-GPUBatch *DRW_cache_curve_edge_detection_get(Object *ob, bool *r_is_manifold)
-{
- BLI_assert(ob->type == OB_CURVE);
- struct Curve *cu = ob->data;
- struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
- if (mesh_eval != NULL) {
- return DRW_mesh_batch_cache_get_edge_detection(mesh_eval, r_is_manifold);
- }
-
- return DRW_curve_batch_cache_get_edge_detection(cu, r_is_manifold);
-}
-
-/* Return list of batches */
-GPUBatch **DRW_cache_curve_surface_shaded_get(Object *ob,
- struct GPUMaterial **gpumat_array,
- uint gpumat_array_len)
-{
- BLI_assert(ob->type == OB_CURVE);
-
- struct Curve *cu = ob->data;
- struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
- if (mesh_eval != NULL) {
- return DRW_mesh_batch_cache_get_surface_shaded(mesh_eval, gpumat_array, gpumat_array_len);
- }
-
- return DRW_curve_batch_cache_get_surface_shaded(cu, gpumat_array, gpumat_array_len);
-}
-
/** \} */
/* -------------------------------------------------------------------- */
@@ -3075,96 +3003,9 @@ GPUBatch *DRW_cache_text_edge_wire_get(Object *ob)
{
BLI_assert(ob->type == OB_FONT);
struct Curve *cu = ob->data;
- struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
- const bool has_surface = (cu->flag & (CU_FRONT | CU_BACK)) || cu->ext1 != 0.0f ||
- cu->ext2 != 0.0f;
- if (!has_surface) {
- return NULL;
- }
- if (mesh_eval != NULL) {
- return DRW_mesh_batch_cache_get_loose_edges(mesh_eval);
- }
-
- return DRW_curve_batch_cache_get_wire_edge(cu);
-}
-
-GPUBatch *DRW_cache_text_surface_get(Object *ob)
-{
- BLI_assert(ob->type == OB_FONT);
- struct Curve *cu = ob->data;
- struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
- if (cu->editfont && (cu->flag & CU_FAST)) {
- return NULL;
- }
- if (mesh_eval != NULL) {
- return DRW_mesh_batch_cache_get_surface(mesh_eval);
- }
-
- return DRW_curve_batch_cache_get_triangles_with_normals(cu);
-}
-
-GPUBatch *DRW_cache_text_edge_detection_get(Object *ob, bool *r_is_manifold)
-{
- BLI_assert(ob->type == OB_FONT);
- struct Curve *cu = ob->data;
- struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
- if (cu->editfont && (cu->flag & CU_FAST)) {
- return NULL;
- }
- if (mesh_eval != NULL) {
- return DRW_mesh_batch_cache_get_edge_detection(mesh_eval, r_is_manifold);
- }
-
- return DRW_curve_batch_cache_get_edge_detection(cu, r_is_manifold);
-}
-
-GPUBatch *DRW_cache_text_loose_edges_get(Object *ob)
-{
- BLI_assert(ob->type == OB_FONT);
- struct Curve *cu = ob->data;
- struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
- if (cu->editfont && (cu->flag & CU_FAST)) {
- return NULL;
- }
- if (mesh_eval != NULL) {
- return DRW_mesh_batch_cache_get_loose_edges(mesh_eval);
- }
-
return DRW_curve_batch_cache_get_wire_edge(cu);
}
-GPUBatch *DRW_cache_text_face_wireframe_get(Object *ob)
-{
- BLI_assert(ob->type == OB_FONT);
- struct Curve *cu = ob->data;
- struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
- if (cu->editfont && (cu->flag & CU_FAST)) {
- return NULL;
- }
- if (mesh_eval != NULL) {
- return DRW_mesh_batch_cache_get_wireframes_face(mesh_eval);
- }
-
- return DRW_curve_batch_cache_get_wireframes_face(cu);
-}
-
-GPUBatch **DRW_cache_text_surface_shaded_get(Object *ob,
- struct GPUMaterial **gpumat_array,
- uint gpumat_array_len)
-{
- BLI_assert(ob->type == OB_FONT);
- struct Curve *cu = ob->data;
- struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
- if (cu->editfont && (cu->flag & CU_FAST)) {
- return NULL;
- }
- if (mesh_eval != NULL) {
- return DRW_mesh_batch_cache_get_surface_shaded(mesh_eval, gpumat_array, gpumat_array_len);
- }
-
- return DRW_curve_batch_cache_get_surface_shaded(cu, gpumat_array, gpumat_array_len);
-}
-
/** \} */
/* -------------------------------------------------------------------- */
@@ -3544,6 +3385,8 @@ void drw_batch_cache_validate(Object *ob)
break;
case OB_CURVE:
case OB_FONT:
+ DRW_curve_batch_cache_validate((Curve *)ob->data);
+ break;
case OB_SURF:
if (mesh_eval != NULL) {
DRW_mesh_batch_cache_validate(mesh_eval);
@@ -3592,6 +3435,8 @@ void drw_batch_cache_generate_requested(Object *ob)
break;
case OB_CURVE:
case OB_FONT:
+ DRW_curve_batch_cache_create_requested(ob, scene);
+ break;
case OB_SURF:
if (mesh_eval) {
DRW_mesh_batch_cache_create_requested(
@@ -3618,8 +3463,6 @@ void DRW_batch_cache_free_old(Object *ob, int ctime)
case OB_MESH:
DRW_mesh_batch_cache_free_old((Mesh *)ob->data, ctime);
break;
- case OB_CURVE:
- case OB_FONT:
case OB_SURF:
if (mesh_eval) {
DRW_mesh_batch_cache_free_old(mesh_eval, ctime);
diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h
index 6b2b0a173fe..5863ada2ccf 100644
--- a/source/blender/draw/intern/draw_cache.h
+++ b/source/blender/draw/intern/draw_cache.h
@@ -154,28 +154,14 @@ struct GPUBatch *DRW_cache_mesh_surface_mesh_analysis_get(struct Object *ob);
struct GPUBatch *DRW_cache_mesh_face_wireframe_get(struct Object *ob);
/* Curve */
-struct GPUBatch *DRW_cache_curve_surface_get(struct Object *ob);
-struct GPUBatch **DRW_cache_curve_surface_shaded_get(struct Object *ob,
- struct GPUMaterial **gpumat_array,
- uint gpumat_array_len);
-struct GPUBatch *DRW_cache_curve_loose_edges_get(struct Object *ob);
struct GPUBatch *DRW_cache_curve_edge_wire_get(struct Object *ob);
-struct GPUBatch *DRW_cache_curve_face_wireframe_get(struct Object *ob);
-struct GPUBatch *DRW_cache_curve_edge_detection_get(struct Object *ob, bool *r_is_manifold);
/* edit-mode */
struct GPUBatch *DRW_cache_curve_edge_normal_get(struct Object *ob);
struct GPUBatch *DRW_cache_curve_edge_overlay_get(struct Object *ob);
struct GPUBatch *DRW_cache_curve_vert_overlay_get(struct Object *ob);
/* Font */
-struct GPUBatch *DRW_cache_text_surface_get(struct Object *ob);
-struct GPUBatch *DRW_cache_text_edge_detection_get(struct Object *ob, bool *r_is_manifold);
-struct GPUBatch *DRW_cache_text_loose_edges_get(struct Object *ob);
struct GPUBatch *DRW_cache_text_edge_wire_get(struct Object *ob);
-struct GPUBatch **DRW_cache_text_surface_shaded_get(struct Object *ob,
- struct GPUMaterial **gpumat_array,
- uint gpumat_array_len);
-struct GPUBatch *DRW_cache_text_face_wireframe_get(struct Object *ob);
/* Surface */
struct GPUBatch *DRW_cache_surf_surface_get(struct Object *ob);
diff --git a/source/blender/draw/intern/draw_cache_impl_curve.cc b/source/blender/draw/intern/draw_cache_impl_curve.cc
index 1efe0c080be..0804745fab5 100644
--- a/source/blender/draw/intern/draw_cache_impl_curve.cc
+++ b/source/blender/draw/intern/draw_cache_impl_curve.cc
@@ -112,43 +112,6 @@ static void curve_render_overlay_verts_edges_len_get(ListBase *lb,
}
}
-static void curve_render_wire_verts_edges_len_get(const CurveCache *ob_curve_cache,
- int *r_curve_len,
- int *r_vert_len,
- int *r_edge_len)
-{
- BLI_assert(r_vert_len || r_edge_len);
- int vert_len = 0;
- int edge_len = 0;
- int curve_len = 0;
- LISTBASE_FOREACH (const BevList *, bl, &ob_curve_cache->bev) {
- if (bl->nr > 0) {
- const bool is_cyclic = bl->poly != -1;
- edge_len += (is_cyclic) ? bl->nr : bl->nr - 1;
- vert_len += bl->nr;
- curve_len += 1;
- }
- }
- LISTBASE_FOREACH (const DispList *, dl, &ob_curve_cache->disp) {
- if (ELEM(dl->type, DL_SEGM, DL_POLY)) {
- BLI_assert(dl->parts == 1);
- const bool is_cyclic = dl->type == DL_POLY;
- edge_len += (is_cyclic) ? dl->nr : dl->nr - 1;
- vert_len += dl->nr;
- curve_len += 1;
- }
- }
- if (r_vert_len) {
- *r_vert_len = vert_len;
- }
- if (r_edge_len) {
- *r_edge_len = edge_len;
- }
- if (r_curve_len) {
- *r_curve_len = curve_len;
- }
-}
-
static void curve_eval_render_wire_verts_edges_len_get(const CurveEval &curve_eval,
int *r_curve_len,
int *r_vert_len,
@@ -243,7 +206,7 @@ enum {
};
/*
- * ob_curve_cache can be NULL, only needed for CU_DATATYPE_WIRE
+ * ob_curve_cache can be NULL
*/
static CurveRenderData *curve_render_data_create(Curve *cu,
CurveCache *ob_curve_cache,
@@ -267,12 +230,6 @@ static CurveRenderData *curve_render_data_create(Curve *cu,
&rdata->wire.vert_len,
&rdata->wire.edge_len);
}
- else {
- curve_render_wire_verts_edges_len_get(rdata->ob_curve_cache,
- &rdata->wire.curve_len,
- &rdata->wire.vert_len,
- &rdata->wire.edge_len);
- }
}
if (cu->editnurb) {
@@ -594,6 +551,10 @@ void DRW_curve_batch_cache_free(Curve *cu)
/* GPUBatch cache usage. */
static void curve_create_curves_pos(CurveRenderData *rdata, GPUVertBuf *vbo_curves_pos)
{
+ if (rdata->curve_eval == nullptr) {
+ return;
+ }
+
static GPUVertFormat format = {0};
static struct {
uint pos;
@@ -606,46 +567,26 @@ static void curve_create_curves_pos(CurveRenderData *rdata, GPUVertBuf *vbo_curv
GPU_vertbuf_init_with_format(vbo_curves_pos, &format);
GPU_vertbuf_data_alloc(vbo_curves_pos, vert_len);
- if (rdata->curve_eval != nullptr) {
- const CurveEval &curve_eval = *rdata->curve_eval;
- Span<SplinePtr> splines = curve_eval.splines();
- Array<int> offsets = curve_eval.evaluated_point_offsets();
- BLI_assert(offsets.last() == vert_len);
-
- for (const int i_spline : splines.index_range()) {
- Span<float3> positions = splines[i_spline]->evaluated_positions();
- for (const int i_point : positions.index_range()) {
- GPU_vertbuf_attr_set(
- vbo_curves_pos, attr_id.pos, offsets[i_spline] + i_point, positions[i_point]);
- }
- }
- }
- else {
- BLI_assert(rdata->ob_curve_cache != nullptr);
-
- int v_idx = 0;
- LISTBASE_FOREACH (const BevList *, bl, &rdata->ob_curve_cache->bev) {
- if (bl->nr <= 0) {
- continue;
- }
- const int i_end = v_idx + bl->nr;
- for (const BevPoint *bevp = bl->bevpoints; v_idx < i_end; v_idx++, bevp++) {
- GPU_vertbuf_attr_set(vbo_curves_pos, attr_id.pos, v_idx, bevp->vec);
- }
- }
- LISTBASE_FOREACH (const DispList *, dl, &rdata->ob_curve_cache->disp) {
- if (ELEM(dl->type, DL_SEGM, DL_POLY)) {
- for (int i = 0; i < dl->nr; v_idx++, i++) {
- GPU_vertbuf_attr_set(vbo_curves_pos, attr_id.pos, v_idx, &((float(*)[3])dl->verts)[i]);
- }
- }
+ const CurveEval &curve_eval = *rdata->curve_eval;
+ Span<SplinePtr> splines = curve_eval.splines();
+ Array<int> offsets = curve_eval.evaluated_point_offsets();
+ BLI_assert(offsets.last() == vert_len);
+
+ for (const int i_spline : splines.index_range()) {
+ Span<float3> positions = splines[i_spline]->evaluated_positions();
+ for (const int i_point : positions.index_range()) {
+ GPU_vertbuf_attr_set(
+ vbo_curves_pos, attr_id.pos, offsets[i_spline] + i_point, positions[i_point]);
}
- BLI_assert(v_idx == vert_len);
}
}
static void curve_create_curves_lines(CurveRenderData *rdata, GPUIndexBuf *ibo_curve_lines)
{
+ if (rdata->curve_eval == nullptr) {
+ return;
+ }
+
const int vert_len = curve_render_data_wire_verts_len_get(rdata);
const int edge_len = curve_render_data_wire_edges_len_get(rdata);
const int curve_len = curve_render_data_wire_curve_len_get(rdata);
@@ -655,54 +596,20 @@ static void curve_create_curves_lines(CurveRenderData *rdata, GPUIndexBuf *ibo_c
GPUIndexBufBuilder elb;
GPU_indexbuf_init_ex(&elb, GPU_PRIM_LINE_STRIP, index_len, vert_len);
- if (rdata->curve_eval != nullptr) {
- const CurveEval &curve_eval = *rdata->curve_eval;
- Span<SplinePtr> splines = curve_eval.splines();
- Array<int> offsets = curve_eval.evaluated_point_offsets();
- BLI_assert(offsets.last() == vert_len);
-
- for (const int i_spline : splines.index_range()) {
- const int eval_size = splines[i_spline]->evaluated_points_size();
- if (splines[i_spline]->is_cyclic() && splines[i_spline]->evaluated_edges_size() > 1) {
- GPU_indexbuf_add_generic_vert(&elb, offsets[i_spline] + eval_size - 1);
- }
- for (const int i_point : IndexRange(eval_size)) {
- GPU_indexbuf_add_generic_vert(&elb, offsets[i_spline] + i_point);
- }
- GPU_indexbuf_add_primitive_restart(&elb);
- }
- }
- else {
- BLI_assert(rdata->ob_curve_cache != nullptr);
+ const CurveEval &curve_eval = *rdata->curve_eval;
+ Span<SplinePtr> splines = curve_eval.splines();
+ Array<int> offsets = curve_eval.evaluated_point_offsets();
+ BLI_assert(offsets.last() == vert_len);
- int v_idx = 0;
- LISTBASE_FOREACH (const BevList *, bl, &rdata->ob_curve_cache->bev) {
- if (bl->nr <= 0) {
- continue;
- }
- const bool is_cyclic = bl->poly != -1;
- if (is_cyclic) {
- GPU_indexbuf_add_generic_vert(&elb, v_idx + (bl->nr - 1));
- }
- for (int i = 0; i < bl->nr; i++) {
- GPU_indexbuf_add_generic_vert(&elb, v_idx + i);
- }
- GPU_indexbuf_add_primitive_restart(&elb);
- v_idx += bl->nr;
+ for (const int i_spline : splines.index_range()) {
+ const int eval_size = splines[i_spline]->evaluated_points_size();
+ if (splines[i_spline]->is_cyclic() && splines[i_spline]->evaluated_edges_size() > 1) {
+ GPU_indexbuf_add_generic_vert(&elb, offsets[i_spline] + eval_size - 1);
}
- LISTBASE_FOREACH (const DispList *, dl, &rdata->ob_curve_cache->disp) {
- if (ELEM(dl->type, DL_SEGM, DL_POLY)) {
- const bool is_cyclic = dl->type == DL_POLY;
- if (is_cyclic) {
- GPU_indexbuf_add_generic_vert(&elb, v_idx + (dl->nr - 1));
- }
- for (int i = 0; i < dl->nr; i++) {
- GPU_indexbuf_add_generic_vert(&elb, v_idx + i);
- }
- GPU_indexbuf_add_primitive_restart(&elb);
- v_idx += dl->nr;
- }
+ for (const int i_point : IndexRange(eval_size)) {
+ GPU_indexbuf_add_generic_vert(&elb, offsets[i_spline] + i_point);
}
+ GPU_indexbuf_add_primitive_restart(&elb);
}
GPU_indexbuf_build_in_place(&elb, ibo_curve_lines);
diff --git a/source/blender/editors/curve/editcurve_add.c b/source/blender/editors/curve/editcurve_add.c
index d1fe162fc4a..19aad20cbc1 100644
--- a/source/blender/editors/curve/editcurve_add.c
+++ b/source/blender/editors/curve/editcurve_add.c
@@ -535,7 +535,6 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf)
newob = true;
cu = (Curve *)obedit->data;
- cu->flag |= CU_DEFORM_FILL;
if (type & CU_PRIM_PATH) {
cu->flag |= CU_PATH | CU_3D;
diff --git a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc
index fcc92345bea..d503297f540 100644
--- a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc
+++ b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc
@@ -270,7 +270,7 @@ Object *spreadsheet_get_object_eval(const SpaceSpreadsheet *sspreadsheet,
return nullptr;
}
Object *object_orig = (Object *)used_id;
- if (!ELEM(object_orig->type, OB_MESH, OB_POINTCLOUD, OB_VOLUME)) {
+ if (!ELEM(object_orig->type, OB_MESH, OB_POINTCLOUD, OB_VOLUME, OB_CURVE, OB_FONT)) {
return nullptr;
}
diff --git a/source/blender/io/alembic/intern/abc_reader_curves.cc b/source/blender/io/alembic/intern/abc_reader_curves.cc
index 688ba23333a..d2ec7fb84db 100644
--- a/source/blender/io/alembic/intern/abc_reader_curves.cc
+++ b/source/blender/io/alembic/intern/abc_reader_curves.cc
@@ -94,7 +94,7 @@ void AbcCurveReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSele
{
Curve *cu = BKE_curve_add(bmain, m_data_name.c_str(), OB_CURVE);
- cu->flag |= CU_DEFORM_FILL | CU_3D;
+ cu->flag |= CU_3D;
cu->actvert = CU_ACT_NONE;
cu->resolu = 1;
diff --git a/source/blender/io/usd/intern/usd_reader_curve.cc b/source/blender/io/usd/intern/usd_reader_curve.cc
index 31ecf27cf7e..7410757a9d9 100644
--- a/source/blender/io/usd/intern/usd_reader_curve.cc
+++ b/source/blender/io/usd/intern/usd_reader_curve.cc
@@ -46,7 +46,7 @@ void USDCurvesReader::create_object(Main *bmain, const double /* motionSampleTim
{
curve_ = BKE_curve_add(bmain, name_.c_str(), OB_CURVE);
- curve_->flag |= CU_DEFORM_FILL | CU_3D;
+ curve_->flag |= CU_3D;
curve_->actvert = CU_ACT_NONE;
curve_->resolu = 2;
diff --git a/source/blender/io/usd/intern/usd_reader_nurbs.cc b/source/blender/io/usd/intern/usd_reader_nurbs.cc
index 9b30b524729..d6977d9c91a 100644
--- a/source/blender/io/usd/intern/usd_reader_nurbs.cc
+++ b/source/blender/io/usd/intern/usd_reader_nurbs.cc
@@ -62,7 +62,7 @@ void USDNurbsReader::create_object(Main *bmain, const double /* motionSampleTime
{
curve_ = BKE_curve_add(bmain, name_.c_str(), OB_CURVE);
- curve_->flag |= CU_DEFORM_FILL | CU_3D;
+ curve_->flag |= CU_3D;
curve_->actvert = CU_ACT_NONE;
curve_->resolu = 2;
diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h
index 520fc6c1b00..77ab2b67f3d 100644
--- a/source/blender/makesdna/DNA_curve_types.h
+++ b/source/blender/makesdna/DNA_curve_types.h
@@ -302,8 +302,11 @@ typedef struct Curve {
float fsize_realtime;
/**
- * A pointer to curve data from geometry nodes, currently only set for evaluated
- * objects by the dependency graph iterator, and owned by #geometry_set_eval.
+ * A pointer to curve data from evaluation. Owned by the object's #geometry_set_eval, either as a
+ * geometry instance or the data of the evalauted #CurveComponent. The curve may also contain
+ * data in the #nurb list, but for evaluated curves this is the proper place to retrieve data,
+ * since it also contains the result of geometry nodes evaluation, and isn't just a copy of the
+ * original object data.
*/
struct CurveEval *curve_eval;
@@ -344,8 +347,7 @@ enum {
CU_DS_EXPAND = 1 << 11,
/** make use of the path radius if this is enabled (default for new curves) */
CU_PATH_RADIUS = 1 << 12,
- /** fill 2d curve after deformation */
- CU_DEFORM_FILL = 1 << 13,
+ /* CU_DEFORM_FILL = 1 << 13, */ /* DEPRECATED */
/** fill bevel caps */
CU_FILL_CAPS = 1 << 14,
/** map taper object to beveled area */
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index 0250d853898..5a88ce7c9f5 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -158,8 +158,7 @@ typedef struct Object_Runtime {
struct ID *data_orig;
/**
* Object data structure created during object evaluation. It has all modifiers applied.
- * The type is determined by the type of the original object. For example, for mesh and curve
- * objects, this is a mesh. For a volume object, this is a volume.
+ * The type is determined by the type of the original object.
*/
struct ID *data_eval;
diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c
index 9c6659a7130..0bfb1200f49 100644
--- a/source/blender/makesrna/intern/rna_curve.c
+++ b/source/blender/makesrna/intern/rna_curve.c
@@ -1809,12 +1809,6 @@ static void rna_def_curve(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Twist Smooth", "Smoothing iteration for tangents");
RNA_def_property_update(prop, 0, "rna_Curve_update_data");
- prop = RNA_def_property(srna, "use_fill_deform", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", CU_DEFORM_FILL);
- RNA_def_property_ui_text(
- prop, "Fill Deformed", "Fill curve after applying shape keys and all modifiers");
- RNA_def_property_update(prop, 0, "rna_Curve_update_data");
-
prop = RNA_def_property(srna, "use_fill_caps", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", CU_FILL_CAPS);
RNA_def_property_ui_text(prop, "Fill Caps", "Fill caps for beveled curves");
diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc
index f6d145bfdd7..3b952e1e649 100644
--- a/source/blender/modifiers/intern/MOD_nodes.cc
+++ b/source/blender/modifiers/intern/MOD_nodes.cc
@@ -1075,9 +1075,10 @@ ModifierTypeInfo modifierType_Nodes = {
/* srna */ &RNA_NodesModifier,
/* type */ eModifierTypeType_Constructive,
/* flags */
- static_cast<ModifierTypeFlag>(
- eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode |
- eModifierTypeFlag_EnableInEditmode | eModifierTypeFlag_SupportsMapping),
+ static_cast<ModifierTypeFlag>(eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs |
+ eModifierTypeFlag_SupportsEditmode |
+ eModifierTypeFlag_EnableInEditmode |
+ eModifierTypeFlag_SupportsMapping),
/* icon */ ICON_NODETREE,
/* copyData */ copyData,