Tutorial about writing a custom geometry node for Blender

Hello, I have drafted a quick tutorial about writing a custom geometry node for Blender, any feedback is more than welcome!

39 Likes

Thanks for writing that. Couldn’t spot an error yet.
Just wanted to mention that the callbacks you mention in the Other Callbacks section all probably shouldn’t be used with geometry nodes currently (don’t think there is any node that uses those currently).

4 Likes

Thanks a lot for proof reading it! I’ve removed the Other Callbacks section then.

I may add extensions while I go a bit deeper into the dynamic definition of nodes at runtime (for registering OpenMfx nodes from plugins at startup).

edit: Also, quick question, what are the padding rules for node DNA?

Thanks for the detailed post!
As a complete beginner at coding for blender (And in C), I tried to follow your guild as close as possible but got some errors nonetheless.
Can you point me to my mistakes?

/home/arye/blender-git/blender/source/blender/makesrna/intern/rna_nodetree.c:9860:3: error: ‘prop’ undeclared (first use in this function)
 9860 |   prop = RNA_def_property(srna, "olive_count", PROP_INT, PROP_NONE);
      |   ^~~~
/home/arye/blender-git/blender/source/blender/makesrna/intern/rna_nodetree.c:9860:3: note: each undeclared identifier is reported only once for each function it appears in
/home/arye/blender-git/blender/source/blender/makesrna/intern/rna_nodetree.c:9862:3: error: ‘RNA_def_property_’ undeclared (first use in this function); did you mean ‘RNA_def_property’?
 9862 |   RNA_def_property_[...](prop, [...]); // call various setters to fill in 'prop' attributes
      |   ^~~~~~~~~~~~~~~~~
      |   RNA_def_property
/home/arye/blender-git/blender/source/blender/makesrna/intern/rna_nodetree.c:9862:21: error: expected expression before ‘...’ token
 9862 |   RNA_def_property_[...](prop, [...]); // call various setters to fill in 'prop' attributes
      |                     ^~~
/home/arye/blender-git/blender/source/blender/makesrna/intern/rna_nodetree.c:9862:32: error: expected expression before ‘[’ token
 9862 |   RNA_def_property_[...](prop, [...]); // call various setters to fill in 'prop' attributes
      |                                ^
make[3]: *** [source/blender/makesrna/intern/CMakeFiles/makesrna.dir/build.make:596: source/blender/makesrna/intern/CMakeFiles/makesrna.dir/rna_nodetree.c.o] Error 1
make[2]: *** [CMakeFiles/Makefile2:5208: source/blender/makesrna/intern/CMakeFiles/makesrna.dir/all] Error 2
make[1]: *** [Makefile:163: all] Error 2
make: *** [GNUmakefile:349: all] Error 2

*Edit: I can upload the diff if needed.

3 Likes

Thanks a lot @aryeramaty!

I indeed forgot to define PropertyRNA *prop; at the beginning of def_geo_pizza. As for the line with [...] in it that meant “look at examples from around in the same file” but I admit it was not clear, I explicited it.

So, I’ve updated the code bloc defining def_geo_pizza let me know if it is now clear enough!

3 Likes

Thanks! It’s much clearer now, but I still couldn’t make it. Although this time I got a different error so I guess it is an improvement :sweat_smile:

../../lib/libbf_blenkernel.a(node.cc.o):node.cc:function BKE_node_system_init: error: undefined reference to 'register_node_type_geo_pizza'
collect2: error: ld returned 1 exit status
make[3]: *** [source/creator/CMakeFiles/blender.dir/build.make:288: bin/blender] Error 1
make[2]: *** [CMakeFiles/Makefile2:5471: source/creator/CMakeFiles/blender.dir/all] Error 2
make[1]: *** [Makefile:163: all] Error 2
make: *** [GNUmakefile:349: all] Error 2

Maybe you forgot to declare void register_node_type_geo_pizza(void); in source/blender/nodes/NOD_geometry.h?

Thank you very much :smiling_face_with_three_hearts:

Here is another one available online, the more resource we have on this subject the better!

7 Likes

Well, I’m pretty sure I did write this line. I’ll just upload the diff so you can find all of my stupid mistakes at once.

diff --cc release/scripts/startup/nodeitems_builtins.py
index a67941a3c37,a67941a3c37..f5282123ce8
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@@ -656,8 -656,8 +656,6 @@@ geometry_node_categories = 
          NodeItem("GeometryNodeMeshIcoSphere"),
          NodeItem("GeometryNodeMeshLine"),
          NodeItem("GeometryNodeMeshUVSphere"),
--        NodeItem("GeometryNodePizza"),
--
      ]),
      GeometryNodeCategory("GEO_OUTPUT", "Output", items=[
          NodeItem("GeometryNodeViewer"),
diff --cc source/blender/blenkernel/BKE_node.h
index c653ddc4e68,c653ddc4e68..1ff10d06b00
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@@ -1493,7 -1493,7 +1493,6 @@@ struct TexResult
  #define GEO_NODE_STORE_NAMED_ATTRIBUTE 1156
  #define GEO_NODE_INPUT_NAMED_ATTRIBUTE 1157
  #define GEO_NODE_REMOVE_ATTRIBUTE 1158
--#define GEO_NODE_PIZZA 1159
  
  /** \} */
  
diff --cc source/blender/blenkernel/intern/node.cc
index d253f5c2b37,d253f5c2b37..cf3b4f7bdf2
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@@ -4789,7 -4789,7 +4789,6 @@@ static void registerGeometryNodes(
    register_node_type_geo_mesh_to_curve();
    register_node_type_geo_mesh_to_points();
    register_node_type_geo_object_info();
--  register_node_type_geo_pizza();
    register_node_type_geo_points_to_vertices();
    register_node_type_geo_points_to_volume();
    register_node_type_geo_proximity();
diff --cc source/blender/makesdna/DNA_node_types.h
index 76caf02781b,76caf02781b..3be4f82ecb0
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@@ -1270,10 -1270,10 +1270,6 @@@ typedef struct NodeGeometryObjectInfo 
    uint8_t transform_space;
  } NodeGeometryObjectInfo;
  
--typedef struct NodeGeometryPizza {
--  int olive_count;
--} NodeGeometryPizza;
--
  typedef struct NodeGeometryPointsToVolume {
    /* GeometryNodePointsToVolumeResolutionMode */
    uint8_t resolution_mode;
diff --cc source/blender/makesrna/intern/rna_nodetree.c
index 54d0e81d668,54d0e81d668..a9dec810079
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@@ -9851,21 -9851,21 +9851,6 @@@ static void def_geo_object_info(StructR
        prop, "Transform Space", "The transformation of the vector and geometry outputs");
    RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update_relations");
  }
--static void def_geo_pizza(StructRNA *srna)
--{
--  PropertyRNA *prop;
--
--  RNA_def_struct_sdna_from(srna, "NodeGeometryPizza", "storage");
--
--  // For each property, i.e., each user-exposed parameter of the node
--  // that is not a pluggable input:
--  prop = RNA_def_property(srna, "olive_count", PROP_INT, PROP_NONE);
--  RNA_def_property_int_sdna(prop, NULL, "olive_count");
--  // Call various setters to fill in the property's settings:
--  RNA_def_property_range(prop, 0, 1000);
--  RNA_def_property_ui_text(prop, "Olive Count", "Number of olives topping the pizza");
--  RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
--}
  
  static void def_geo_points_to_volume(StructRNA *srna)
  {
diff --cc source/blender/nodes/NOD_geometry.h
index 455c5fea6c0,455c5fea6c0..064112b7efd
--- a/source/blender/nodes/NOD_geometry.h
+++ b/source/blender/nodes/NOD_geometry.h
@@@ -100,7 -100,7 +100,6 @@@ void register_node_type_geo_mesh_subdiv
  void register_node_type_geo_mesh_to_curve(void);
  void register_node_type_geo_mesh_to_points(void);
  void register_node_type_geo_object_info(void);
--void register_node_type_geo_pizza(void);
  void register_node_type_geo_points_to_vertices(void);
  void register_node_type_geo_points_to_volume(void);
  void register_node_type_geo_proximity(void);
diff --cc source/blender/nodes/NOD_static_types.h
index ff5ae7c3ef7,ff5ae7c3ef7..e0a4d241b3b
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@@ -375,7 -375,7 +375,6 @@@ DefNode(GeometryNode, GEO_NODE_SET_CURV
  DefNode(GeometryNode, GEO_NODE_SET_CURVE_TILT, 0, "SET_CURVE_TILT", SetCurveTilt, "Set Curve Tilt", "")
  DefNode(GeometryNode, GEO_NODE_SET_ID, 0, "SET_ID", SetID, "Set ID", "")
  DefNode(GeometryNode, GEO_NODE_SET_MATERIAL_INDEX, 0, "SET_MATERIAL_INDEX", SetMaterialIndex, "Set Material Index", "")
--DefNode(GeometryNode,  GEO_NODE_PIZZA,  def_geo_pizza,     "PIZZA",    Pizza,        "Pizza",  "")
  DefNode(GeometryNode, GEO_NODE_SET_MATERIAL, 0, "SET_MATERIAL", SetMaterial, "Set Material", "")
  DefNode(GeometryNode, GEO_NODE_SET_POINT_RADIUS, 0, "SET_POINT_RADIUS", SetPointRadius, "Set Point Radius", "")
  DefNode(GeometryNode, GEO_NODE_SET_POSITION, 0, "SET_POSITION", SetPosition, "Set Position", "")
@@@ -401,4 -401,4 +400,4 @@@ DefNode(GeometryNode, GEO_NODE_VOLUME_T
  /* undefine macros */
  #undef DefNode
  
--    /* clang-format on */
++    /* clang-format on */
diff --cc source/blender/nodes/geometry/nodes/node_geo_pizza.cc
index 00958020148,00958020148..00000000000
deleted file mode 100644,100644
--- a/source/blender/nodes/geometry/nodes/node_geo_pizza.cc
+++ /dev/null
@@@ -1,198 -1,198 +1,0 @@@
--
--#include "BLI_disjoint_set.hh"
--#include "BLI_task.hh"
--#include "BLI_vector_set.hh"
--
--#include "DNA_mesh_types.h"
--#include "DNA_meshdata_types.h"
--
--#include "BKE_attribute_math.hh"
--#include "BKE_mesh.h"
--#include "BKE_mesh_runtime.h"
--
--#include "UI_interface.h"
--#include "UI_resources.h"
--
--#include "node_geometry_util.hh"
--
--
--namespace blender::nodes::node_geo_pizza_cc{
--
--
--static void node_declare(NodeDeclarationBuilder &b)
--{
--    b.add_input<decl::Float>(N_("Radius"))
--        .default_value(1.0f)
--        .min(0.0f)
--        .subtype(PROP_DISTANCE)
--        .description(N_("Size of the pizza"));
--    b.add_output<decl::Geometry>("Mesh");
--    b.add_output<decl::Bool>(N_("Base")).field_source();
--    b.add_output<decl::Bool>(N_("Olives")).field_source();
--}
--
--static void node_init(bNodeTree *UNUSED(tree), bNode *node)
--{
--    NodeGeometryPizza *data = MEM_cnew<NodeGeometryPizza>(__func__);
--    data->olive_count = 5;
--    node->storage = data;
--}
--
--NODE_STORAGE_FUNCS(NodeGeometryPizza) // To define node_storage()
--
--static void node_update(bNodeTree *ntree, bNode *node)
--{
--    const NodeGeometryPizza &storage = node_storage(*node);
--
--    bNodeSocket *out_socket_geometry = (bNodeSocket *)node->outputs.first;
--    bNodeSocket *out_socket_base = out_socket_geometry->next;
--    bNodeSocket *out_socket_olives = out_socket_base->next;
--
--    // Stupid feature for the sake of the example: When there are too many
--    // olives, we no longer output the fields!
--    nodeSetSocketAvailability(ntree, out_socket_base, storage.olive_count < 25);
--    nodeSetSocketAvailability(ntree, out_socket_olives, storage.olive_count < 25);
--}
--
--static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
--{
--    uiLayoutSetPropSep(layout, true);
--    uiLayoutSetPropDecorate(layout, false);
--    uiItemR(layout, ptr, "olive_count", 0, "", ICON_NONE);
--}
--
--static void node_geo_exec(GeoNodeExecParams params)
--{
--    // We first retrieve the property (olive count) and the input socket (radius)
--    const NodeGeometryPizza &storage = node_storage(params.node());
--    const int olive_count = storage.olive_count;
--    const float radius = params.extract_input<float>("Radius");
--
--    // Then we create the mesh (let's put it in a separate function)
--    IndexRange base_polys, olives_polys;
--    Mesh *mesh = create_pizza_mesh(olive_count, radius, base_polys, olives_polys);
--
--    // We build a geometry set to wrap the mesh and set it as the output value
--    GeometrySet output_geo = GeometrySet::create_with_mesh(mesh);
--    params.set_output("Mesh", GeometrySet::create_with_mesh(mesh));
--
--    MeshComponent &component = output_geo.get_component_for_write<MeshComponent>();
--    if (params.output_is_required("Base")) {
--    // Create the field from a range and a mesh component:
--    StrongAnonymousAttributeID id("Base");
--    OutputAttribute_Typed<bool> attribute =
--      component.attribute_try_get_for_output_only<bool>(id.get(), ATTR_DOMAIN_FACE);
--    attribute.as_span().slice(base_polys).fill(true);
--    attribute.save();
--    
--    // Output this field in the Base output
--    params.set_output("Base",
--                      AnonymousAttributeFieldInput::Create<bool>(
--                          std::move(id), params.attribute_producer_name()));
--    }
--
--    if (params.output_is_required("Olives")) {
--         // [...] Idem for olives
--    }
--}
--
--static Mesh *create_pizza_mesh(const int olive_count,
--                               const float radius,
--                               IndexRange &base_polys,
--                               IndexRange &olives_polys)
--{
--  // (i) Compute element counts
--  int vert_count = 32 + olive_count * 4;
--  int edge_count = 32 + olive_count * 4;
--  int corner_count = 32 + olive_count * 4;
--  int face_count = 1 + olive_count;
--
--  // (ii) Allocate memory
--  Mesh *mesh = BKE_mesh_new_nomain(vert_count, edge_count, 0, corner_count, face_count);
--
--  // (iii) Fill in element buffers
--  MutableSpan<MVert> verts{mesh->mvert, mesh->totvert};
--  MutableSpan<MLoop> loops{mesh->mloop, mesh->totloop};
--  MutableSpan<MEdge> edges{mesh->medge, mesh->totedge};
--  MutableSpan<MPoly> polys{mesh->mpoly, mesh->totpoly};
--  base_polys = IndexRange{0, 1};
--  olives_polys = IndexRange{1, olive_count};
--
--  // (iii.a) Base
--  const float angle_delta = 2 * M_PI / 32;
--  for (const int i : IndexRange(32)) {
--    // Vertex coordinates
--    const float angle = i * angle_delta;
--    copy_v3_v3(verts[i].co, float3(std::cos(angle) * radius, std::sin(angle) * radius, 0.0f));
--
--    // Edge
--    MEdge &edge = edges[i];
--    edge.v1 = i;
--    edge.v2 = (i + 1) % 32;
--    edge.flag = ME_EDGEDRAW | ME_EDGERENDER;
--
--    // Corner
--    MLoop &loop = loops[i];
--    loop.e = i;
--    loop.v = i;
--  }
--  // Face
--  MPoly &poly = polys[0];
--  poly.loopstart = 0;
--  poly.totloop = 32;
--
--  // (iii.b) Olives
--  const float angle_delta_olive = 2.0f * (M_PI / static_cast<float>(olive_count - 1));
--  for (const int i : IndexRange(olive_count)) {
--    const int offset = 32 + 4 * i;
--
--    // Vertex coordinates
--    float cx = 0, cy = 0;
--    if (i > 0) { // (the olive #0 is at the center)
--      const float angle = (i - 1) * angle_delta_olive;
--      cx = std::cos(angle) * radius / 2;
--      cy = std::sin(angle) * radius / 2;
--    }
--    copy_v3_v3(verts[offset + 0].co, float3(cx + 0.05f, cy + 0.05f, 0.01f));
--    copy_v3_v3(verts[offset + 1].co, float3(cx - 0.05f, cy + 0.05f, 0.01f));
--    copy_v3_v3(verts[offset + 2].co, float3(cx - 0.05f, cy - 0.05f, 0.01f));
--    copy_v3_v3(verts[offset + 3].co, float3(cx + 0.05f, cy - 0.05f, 0.01f));
--
--    for (const int k : IndexRange(4)) {
--      // Edge
--      MEdge &edge = edges[offset + k];
--      edge.v1 = offset + k;
--      edge.v2 = offset + (k + 1) % 4;
--      edge.flag = ME_EDGEDRAW | ME_EDGERENDER;
--
--      // Corner
--      MLoop &loop = loops[offset + k];
--      loop.e = offset + k;
--      loop.v = offset + k;
--    }
--
--    // Face
--    MPoly &poly = polys[1 + i];
--    poly.loopstart = offset;
--    poly.totloop = 4;
--  }
--
--  BLI_assert(BKE_mesh_is_valid(mesh));
--  return mesh;
--}
--
--}
--void register_node_type_geo_pizza()
--{
--    namespace file_ns = blender::nodes::node_geo_pizza_cc;
--
--    static bNodeType ntype;
--    geo_node_type_base(&ntype, GEO_NODE_PIZZA, "Pizza", NODE_CLASS_GEOMETRY);
--    ntype.declare = file_ns::node_declare;
--    node_type_init(&ntype, file_ns::node_init);
--    node_type_update(&ntype, file_ns::node_update);
--    ntype.geometry_node_execute = file_ns::node_geo_exec;
--    node_type_storage(&ntype, "NodeGeometryPizza", node_free_standard_storage, node_copy_standard_storage);
--    ntype.draw_buttons = file_ns::node_layout;
--    nodeRegisterType(&ntype);
--}

Nice work. And here are more words so I can post this :slight_smile:

1 Like

Oh I know, it’s an undefined reference, meaning the linker does not find the implementation, which suggests you forgot to add node_geo_pizza.cc to source/blender/nodes/geometry/CmakeLists.txt, and the diff confirms so!

It’s actually even more embarrassing :sweat_smile: I have forgotten to save the CmakeLists.txt after changing it.
Anyway, now I got another problem, the build is working fine but the pizza node is crushing blender (when connecting it to the output). :expressionless:

This is the crush file:

# Blender 3.3.0, Unknown revision
bpy.ops.node.new_geometry_nodes_modifier()  # Operator
bpy.ops.node.add_search(use_transform=True, node_item='123')  # Operator
bpy.ops.node.translate_attach_remove_on_cancel(TRANSFORM_OT_translate={"value":(-125.926, 194.156, 0), "orient_axis_ortho":'X', "orient_type":'GLOBAL', "orient_matrix":((1, 0, 0), (0, 1, 0), (0, 0, 1)), "orient_matrix_type":'GLOBAL', "constraint_axis":(False, False, False), "mirror":False, "use_proportional_edit":False, "proportional_edit_falloff":'SMOOTH', "proportional_size":1, "use_proportional_connected":False, "use_proportional_projected":False, "snap":False, "snap_target":'CLOSEST', "snap_point":(0, 0, 0), "snap_align":False, "snap_normal":(0, 0, 0), "gpencil_strokes":False, "cursor_transform":False, "texture_space":False, "remove_on_cancel":True, "view2d_edge_pan":True, "release_confirm":False, "use_accurate":False, "use_automerge_and_split":False}, NODE_OT_attach={}, NODE_OT_insert_offset={})  # Operator
bpy.ops.node.translate_attach(TRANSFORM_OT_translate={"value":(-46.173, -41.1846, 0), "orient_axis_ortho":'X', "orient_type":'GLOBAL', "orient_matrix":((1, 0, 0), (0, 1, 0), (0, 0, 1)), "orient_matrix_type":'GLOBAL', "constraint_axis":(False, False, False), "mirror":False, "use_proportional_edit":False, "proportional_edit_falloff":'SMOOTH', "proportional_size":1, "use_proportional_connected":False, "use_proportional_projected":False, "snap":False, "snap_target":'CLOSEST', "snap_point":(0, 0, 0), "snap_align":False, "snap_normal":(0, 0, 0), "gpencil_strokes":False, "cursor_transform":False, "texture_space":False, "remove_on_cancel":False, "view2d_edge_pan":True, "release_confirm":False, "use_accurate":False, "use_automerge_and_split":False}, NODE_OT_attach={}, NODE_OT_insert_offset={})  # Operator
bpy.ops.node.select(extend=False, location=(963, 449))  # Operator
bpy.ops.node.nw_preview_node(run_in_geometry_nodes=True)  # Operator

# backtrace
/home/****/blender-git/build_linux_lite/bin/blender(BLI_system_backtrace+0x37) [0x205d957]
/home/****/blender-git/build_linux_lite/bin/blender() [0xaaef40]
/lib/x86_64-linux-gnu/libc.so.6(+0x43090) [0x7f5d9c816090]

# Python backtrace

Oh, could you run in it in a debugger to get more information about the location of the crash in the code and the value of variables when it occurs?

Hi, sorry for the delay, I’ve been trying to debug the build by myself, then I realize I still don’t have enough coding experience for this.
As I said, I have a little practical coding experience so it’s not that surprising.
I did find that the crash happened at the drawing stage, but not much about the variable.
I guess it would be better if I reuploaded the diff and let someone more knowledgeable solve this.

error_pizza1.txt (12.4 KB)

Hi, after going through the whole doc couple of times, I have some feedback.
But take it with a pinch of salt as I am talking from the perspective of an inexperienced coder.
Anyway, this is my list:

  1. Every bit of code should be inside a code block. Currently, most of the code is written inside code blocks, but some are only described without the actual lines of code(putting all the functions in a namespace, defining a number in BKE_node.h, adding node item in nodeitems_builtins.py, etc.). It’s much harder to locate mistakes/missed lines that way.
  2. It’s still unclear to me where the name “GeometryNodePizza” is coming from (when registering the node item).
  3. A list of all the modified files could also help when tackling mistakes.
  4. After mentioning “custom storage”, it would be nice to know in which circumstances you can’t use the regular storage.

That’s everything I can think of right now.
All in all, the tutorial is very straightforward, I even applied it successfully to another node.
And if I have done it, anyone can. I think I am the only person on this planet that uses blender to learn C++. :see_no_evil:
And again, thank you very much, I had a great time following it.

2 Likes

Thank you so much for writing this tut! I would have never found all the places where one needs to change so many things.
First, it wouldn’t compile, and I figured that while your olives_count may range from 0…1000, the struct NodeGeometryPizza defines a uint8_t, which Blender complained about with a BLI_STATIC_ASSERT, ‘invalid limits’. So I changed the uint8_t to an int32_t and the whole thing compiled! (I’m using Blender 3.2 on an Intel mac)

However, I then had the same problem as aryeramaty: Blender crashes as soon as the mesh socket is connected to the output. After inspection of the crash file, I think that the problem is in the mesh generation. On comparing your code with node_geo_mesh_primitive_ico_sphere.cc, I discovered that there are a lot of differences, maybe the code has changed a lot from 3.1 to 3.2?

Anyhow, you gave me a clue as to where to start if I want to make my own nodes, so thanks again for that!

PS: Here’s the output from the commandline when running Blender and adding a pizza:

me@mini-van-me blender % /Users/me/blender-git/build_darwin/bin/Blender.app/Contents/MacOS/Blender 
Malloc returns null: len=18446744073709551264 in MR_DATATYPE_LOOPTRI, total 18796368
Writing: /var/folders/gd/mtvz7mb9581c2rn1g3hwxfwr0000gn/T/blender.crash.txt
zsh: segmentation fault  /Users/hermen/blender-git/build_darwin/bin/Blender.app/Contents/MacOS/Blender

PPS: I can’t add the crash-report because I’m a newbie :unamused:

Diverging a bit, but does anyone know if there any plans for a python script node so to not go through the full process of compiling blender?

Lukas Tönne is working on a node that would allow you to write python(-like) code which would transpile into a MultiFunction. He has a short description of it here (not sure how up-to-date this is regarding his plans though): blender/geometry_nodes_script.md at geometry-nodes-script · lukas-toenne/blender · GitHub

5 Likes

Hi guys,

I tried Elie tutorial, and got this error that i cant fix :

D:/BLENDER/blender_git/blender/../lib/win64_vc15/usd/lib/usd_usd_m.lib : fatal error LNK1000: Internal error during IMAGE::Pass1 [D:\BLENDER\blender_git\build_windows_x64_vc16_Release\source\creator\blender.vcxproj]
    0 Warning(s)
    1 Error(s)

can any one help me to fix it?

Thank you

@aryeramaty Sorry I could not find the time to test you very diff to debug (I’m working on my own branch, it takes a lot of time to switch to a vanilla Blender to test this). Thanks a lot for your feedback. You’re not the first to report that a clear list of modified code would be easier to follow, so I’ll improve this (as well as the list of modified files). I just don’t want the tutorial to become a series of copy paste to execute blindly, because this would not be as helpful and would be less robust to changes in the code base. ANyways, I can do better and I will!

@aryeramaty @Hermenator Use the debugger to troubleshot the issue. When running your custom Blender with a debugger (gdb if you’re on linux, Visual Studio in Debug mode on Windows, or whatever other solution), than a segmentation fault should trigger the debugger and let you explore at the very moment of the crash the line of code that was being executed, the value of variables in the scope, the stack of function calls that lead to this line, etc. It’s close to impossible to debug this kind of runtime error without using a debugger. :wink:

@Kanzari-Haithem I actually bumped into this issues multiple times on other machines than mine, and I don’t know what causes this and it is really annoying, let me know if you find out. In my experience this happens in Release mode but not in Debug mode.