Non-Destructive Geografts

Issue #869 resolved
Midnight Arrow created an issue

UPDATED PROCEDURE:

After exploring geometry nodes for a few months, I’ve returned to this issue and refined my workflow. The old caveats below still apply.

Consult #923 for a basic overview of how geometry nodes work and the terminology involved.

The geograft source is stored in its own collection. It is parented to the armature but has no armature modifier. The geograft data will be cloned and procedurally added to the figure’s mesh, so the source mesh doesn’t need to be visible and won’t be deformed by the armature. It'll be grafted to the figure in its A-pose, before the armature modifier is processed, so their origins need to match but that’s it. You’ll also need to do the usual steps of importing custom morphs and transferring shape keys, as if you were merging geografts, but since those are controlled by the figure’s drivers they don’t need a strict hierarchy.

Both the figure and the geograft need a vertex group containing the edge vertices that will be welded. Since geometry nodes use a name lookup they should have the same name for convenience. The figure needs another vertex group containing the area that will be deleted. Also create an attribute for a Vertex Table. If we want to perform operations on the mesh after the geografts are applied we’ll need a cached copy of the vertex indices.

I hoped to divorce the geograft from the figure completely, so geografts can be swapped without adjusting the underlying model. Unfortunately due to the current limitations of geometry nodes I wasn’t able to achieve this. If a geograft has its own bones, then you need to copy the vertex groups over to the figure so the armature deformation works. You don’t need to assign any vertices to them; all you need is an empty group with the same name and they’ll be automatically populated when the geometry nodes are evaluated.

This time I left the geograft’s custom bones attached to the Rigify armature.

Then create this node network. Geometry nodes change the structure of a mesh, so the Capture Attribute node allows you to cache its state and refer back to it later. The topmost capture node stores the original vertex indices (as indicated by the Index node plugged into it) and then sends them directly to the output, where they’re put inside the Vertex Table attribute we created. The bottom two cache the vertex groups from the figure and the geograft source mesh that contain the edges to be welded. Since we gave both the same name, we only need to expose one field on the modifier. They’re then or’d together with a Boolean math node and slotted into the Merge by Distance node so only the edges are welded together.

I haven’t had a chance to test this procedure extensively, but I haven’t noticed any unusual ripping or distortion so far.

ORIGINAL POST:

Following on from #862 I explored whether geometry nodes could be used to make non-destructive geografts and the preliminary results are looking good.

Here is RawArt’s Twi’lek for G8M with a non-destructive geograft for the tentacles.

First I created a vertex group to isolate the geograft area on the G8M mesh, then fed that into the geometry node modifier as an attribute. I hid the geograft source in the scene tree and used the following node setup to nondestructively remove the back of the G8M’s head and instance the Twi’lek tentacles in its place. This uses the 3.1 beta which has a new Merge by Distance node to solve the issues with the weld modifier I mentioned in #862.

I separated the tentacle armature from the base G8M skeleton. Since the tentacle bones were parented to the figure’s head bone I used a Child Of constraint to make the tentacle armature follow the Genesis skeleton.

I attempted to verify that shape keys will transfer over from the geograft source to the combined geometry but the exporter refused to load the tentacle morphs even when I started over from scratch. The system console had this to say:

Making morphs
 * Tip Point
Making missing morphs level 0
Building drivers
Building sum drivers
 + Left_13
 + Left_14
 + Right_13
 + Right_14
No rest drivers
Folder  loaded in 0.017 seconds
Did not find fingerprint 3430-6843-3414

However when I created a custom shape key on the geograft source it transferred over to the joined mesh without issue:

Using this workflow I completely isolated the geograft from the G8M armature and base mesh. Not only will this let morphs be loaded alongside geografts it’s also useful for sequential art (i.e. to show transformations or wounds) without needing to build separate figures. The geometry nodes can be applied non-destructively like any other modifier. And due to the node-based workflow you can (in theory) chain multiple geografts inside a single geometry node modifier and control them all by exposing parameters.

Caveats:

  • Viewport performance is dreadful. Right now it’s better to keep the geograft mesh visible in the viewport and hidden in the render, and vice versa for the geometry node setup. That way the geografting is only applied at render time.
  • As mentioned in #862 every material needs to use an Attribute node for the UV coordinates instead of the Texture Coordinate or UV Map node.
  • The Merge by Distance node caused some other dense areas of the body to also merge unless the threshold is extremely low. I believe this can be fixed by using a vertex group to create a selection that isolates the effect but I’m still puzzling out the whole attribute system.
  • The geometry node modifier must come before the armature modifier. The geometry needs to be merged in the A-pose or else the vertices can tear apart during posing as they cross the merge by distance threshold.

Comments (62)

  1. Midnight Arrow reporter

    After more experiments I’ve improved my workflow for geografts. The above node setup will theoretically allow you to create any geograft but it’s very confusing to get your head around at first.

    The geo-node modifier has three attribute fields: “Visibility”, a vertex group; “Geograft”, an object; and “Weld Group”, another vertex group. The Visibility VG is the area the geograft covers. It’s used to (non-destructively) delete the geometry from the base mesh. The Geograft object is the un-merged geograft mesh which must be located in the same position in world-space as the area it’s supposed to cover. The Weld VG is used to limit the effects of the weld modifier that comes right after the geo-node modifier in the stack. (When 3.1 is released the weld modifier can be replaced with a Merge By Distance node and the Weld Group fed directly into its Selection socket.)

    Besides the visibility group you also need to create a vertex group (“Geograft Edges” let’s call it) for the boundary of the geograft area, just like the “Set Graft Faces for Attachment” when creating a geograft in Daz Studio. You need to create that VG on both the source mesh and the geograft, and give them both the exact same name.

    The Capture Attribute node is used to fetch attributes from the geograft. If you go to the geo-nodes modifier and hit the spreadsheet icon it’ll show you a dropdown of every attribute in the object it’s attached to. However it (apparently) is just a simple string lookup, so even if something isn’t listed in the dropdown you can still type it in. Type in the name of the VG from the geograft and it’ll fetch its data even though it’s a completely separate object. Since we gave both VGs the same name we only need one Group Input socket for both. Use a simple math node to add them together and create a group containing only the overlapping vertices. Now assign the same “Geograft Edges” VG to the geo-nodes modifier’s output and use that to control the weld modifier so it only welds the overlapping vertices and nothing else. (Or in 3.1 just feed the product of the math node into the merge by distance node).

    Now you’re able to change the weld distance as high or low as you want and it won’t affect anything except the overlapping edges.

  2. Midnight Arrow reporter

    Previously I showed a way to add morphs with geometry nodes (#871). But one problem was this did not work with geonode geografts since Delete Geometry and Join Geometry rearranges the vertex indices.

    I’ve looked into it some more and found a way to reimplement the Vertex Table from the old, destructive merge geografts workflow.

    First you need to create a custom attribute. This can be done in the Object Data pane in the new Attributes header. Just create a new attribute named Vertex Table and you can pass its data between geometry node modifiers.

    In the geograft modifier add a Capture Attribute node before the Delete Geometry node. This will “freeze” the state of the geometry and allow us to use it later. The Index node plugged into Capture Attribute tells Blender what kind of data we’re interested in. Pass the frozen state data out of the geonode setup and in the modifier stack assign the Vertex Table attribute we created to that field.

    In the morph modifier create an input field for the Vertex Table and feed it into a Switch logic node. If the geograft isn’t active then using the Vertex Table will result in its own mesh distortion since the vertex order won’t match. So this Switch is hooked up to the driver I made to control the geograft visibility. When it’s active the meshes use Vertex Table. When it’s not active the meshes use their own indices. Plug the index output into the two Transfer Attribute nodes. We now have a vertex table allowing us to morph the base mesh vertices as if there was no geograft.

  3. Thomas Larsson repo owner

    I made a first implementation of this. There are a number of issue, e.g. that the geograft boundary is visible in the viewport and some issue with uvs of the base mesh, so it is very experimental. However, the basic structure for geometry nodes is in place which can be useful for other stuff too.

  4. Midnight Arrow reporter

    Is it in master yet? I tried the latest build but I didn’t see anything.

    If the geograft boundary is visible, it could be the geograft’s vertices are out of place. You may need to use snapping to put the vertices in the correct position or just turn up the welding threshold.

  5. Thomas Larsson repo owner

    Yes, it is an option in the Merge Geografts button. But it is only visible in Blender 3.1, of course.

  6. Midnight Arrow reporter

    I tested it out and here’s what I saw:

    • When you “merge” geografts, the geograft source mesh has its edge selected in edit mode but no actual vertex group is created. It should assign those selected vertices to a group called “Geograft Edge”. That’s why the seams are visible – though like I said in some cases it’s also because the geograft’s vertices don’t align properly.
    • The materials aren’t showing up because geometry nodes interferes with UVs (at least currently). All materials should have an Attribute node with the name of the UV map rather than a Texture Coordinate or UV Map node. It’d probably be more efficient to make an import option to create all materials that way rather than editing them when applying the geometry nodes. It’s basically the same thing as a UV Map node but it works with geonodes.
    • There should probably be an “experimental” warning in the tooltip.
    • The geograft modifier needs to come before the armature modifier since the geometry should be welded before deformation, or else it risks tearing.
    • The mesh needs a Vertex Table attribute to store the cached vertices, but none is created and hence the modifer’s output field is blank. You create an attribute with Python the same way you create a vertex group, except you go to the object’s attribute collection instead. After its created, assign the name to the modifier’s Vertex Table output field.
    • If the geograft has custom bones, the base mesh needs (empty) vertex groups with the same name to store them or else the armature-bone lookup doesn’t work.
    • The geograft source’s armature modifier should be disabled/removed or else it’ll “double-up” the bone rotation – the geograft source will be deformed by its armature, and then the fused mesh will be deformed again by its own armature – causing it to warp.
    • Although I did not do this in my most recent example, a better setup would be to expose the Object Info and the Merge by Distance value to the group input. That way they can be changed in the modifier stack.

  7. Aszrael

    Great to see that feature coming! However - I got problems with geometry welding.

    Either I have them still separated:

    or too many vertices merge - hope you can see the distortion.

    I played with the Distance option, but it seams like the the snapping-resolution is not enough. so more vertices than wanted merge. ‘Use Limit Surface’ for the Subdivision modifier makes it less obvious, but there’s still a notable separation in between.

    Btw - posing makes it even worth:

    Just wondering - that’s just the way GeoNodes works (i.e. no real merging) or have I done s.th. wrong?

    UPDATE: never mind - got my mistake - sorry.

  8. Thomas Larsson repo owner

    Will look into this later, but here is the reason why I put the armature modifier before the nodes modifier.

  9. Aszrael

    jepp - in the beginning I got the same - btw: what's the reason you put the Geograft geometry above the Figure Mesh at the 'Join Geometry'? Just wondering - I put it the other way around. Same for the OR? I put it with an Not And:

    If you change the GeoNode the way I show then you have to put the GeoNode-Modifier on top. If not the Armature will not move at all.

    And - you have to firstly remove all Modifiers from the Geograft.

    Btw: I would prefer to have the “Unlink Geografts” unchecked. That’s more in line with an non-destructive workflow.

    All left now is to include a script to copy the vertex groups of the Geograft over to the figure mesh - I wrote a dirty script for that.

    …And a fix for the UDIM creation. I still have to use 3.0 for it 😉

    PS.: is it only for me, that posing takes a hell of computation power now?

  10. Midnight Arrow reporter

    @Thomas

    You can examine changes to geometry with the spreadsheet editor. With that, we can see the order of the Join Geometry node affects the indices of the merged mesh. It looks like in your case the armature/shape keys are deforming the figure based on the vertex index, but the geograft’s vertices are before the figure’s. Just switch the order they’re fed into the Join node and it should fix the problem.

    @Aszrael

    One thing I forgot to mention: you still need to transfer shape keys to the geograft so it deforms along with the figure mesh. If you don’t, that can lead to tearing because the vertex edges won’t match. Luckily the big advantage of this workflow is that you can easily add, remove, and transfer morphs even if your figure has a geograft.

    Geonodes do do proper merging – the vertices of the two meshes are physically joined together and a new mesh is created out of them. You can verify this with the spreadsheet editor too. That’s why UVs don’t work properly, because it’s not really the original mesh. It’s an amalgam of two (or more).

    I agree the geograft source should stay linked, because you may need to adjust it.

    “Not And” is the incorrect type for the Boolean Math node. We don’t care if something is false, only that one of the inputs is true. Therefore it needs to be “Or”.

    As I said under the caveats in the original post, viewport performance is terrible. This is for rendering; it shouldn’t be used when posing. If you need to pose the geograft accurately there is a solution. Create a driver that, when it’s off, the geografting is disabled and the geograft source is visible and can be posed – unmerged – with an armature modifier. When the driver is on, the geograft source is hidden and its armature modifier disabled (to avoid doubling-up the bone deformation) but the geografting is activated.

  11. Thomas Larsson repo owner

    Most of the issues have been fixed. However, I don’t agree on the order of the modifiers. With the nodes modifier first, the mesh is still broken when posed, but when the inputs to the join node are reordered, it is the geograft meshes that are broken instead.

  12. Midnight Arrow reporter

    How many geografts are you applying at once? I’ve never tried it with more than one. If there’s an issue with the vertices being reshuffled, I’ll probably need to come up with some solution to cache them with a Capture Attribute node and reassociate them.

    I’ve looked at the latest build. Here’s what’s going on:

    In my experience it’s best to put the geograft modifier before the armature modifier. Welding vertices in an A-pose is more reliable than welding them after they’ve been deformed in world-space. In order for that to work, the geograft source mesh needs to have its armature modifier removed (or disabled with a driver while the geograft is active). In that case, the geograft will remain in its un-posed position while its geografted clone deforms along with the armature (provided the figure has those empty vertex groups I mentioned previously).

    The workflow in the latest branch instead leaves the armature modifier on the geograft and poses both the figure and the geograft in world-space, then attempts to weld the edges after posing. In that case, if you move the geograft modifier above the armature modifier in the stack, you get that doubling-up I mentioned, where the vertices are deformed by both armature modifiers.

    Your workflow isn’t wrong, and it does avoid the need to create empty vertex groups on the base mesh, but as I said I find welding vertices post-pose doesn’t work as well.

  13. Thomas Larsson repo owner

    The problem was that the original geografts still had armature modifiers with the same armature. When those modifiers are removed, and additional empty vertex groups are added to the base mesh, things work with the nodes modifier first. As you said.

    I think this can be very useful, especially for male genitals. If the geografts are merged with the body as a single mesh, we cannot use a shrinkwrap modifier to keep trousers outside the body. But now we can simple disable the nodes modifier when the trousers are visible.

  14. Aszrael

    Great to see active work here. I agree on Midnight - it makes more sense to firstly merge the Geograft together, than move them via the Figures Armature. Especially if you have more ‘extreme’ poses in the leg area… The issue is, that we have to find one distance merge parameter for all. I’m definitely not an expert here. But: Wouldn’t the best solution be to make a one-to-one assignment instead of merging by a constant distance? The workflow should be s.th. like:

    1. Get the vertices from Geograft Edge from both: Figure and the Geograft
    2. For each vertex of the figure “Geograft Edge” find the nearest vertex from the Geograft “Geograft Edge”
    3. Merge

    As you might notice, I’m not so firm with GeoNodes, but there should be some blender functions for that…

    @Midnight:

    Year, your right - OR makes definitely more sense… And when it comes to transfer morphs: the problem is, some (at least the one I use) transfer badly, especially if you combine them with some Geograft morphs. But that should be more related to the morphs itself, than the procedure.

    Btw: what’s the idea behind the Index here?

  15. Midnight Arrow reporter

    Geometry nodes are intended to replace modifiers so you may not even need a shrinkwrap modifier.

    ⚓ T86839 Converting Modifiers to Nodes (blender.org)

    You can in theory create a geonode setup for the clothing that raycasts to the figure and pushes the mesh outward. Geonodes are meant to be modular so the process is broken down into discrete chunks for more flexibility instead of hardcoded modifiers. The reason why I output a cached copy of the mesh vertices is to create a mapping with the original mesh, that can be used to manipulate the vertices as if they hadn’t been edited at all. For instance, using a delete geometry node instead of a mask modifier will change the vertex order, but that vertex table can be used to associate the changed mesh with the cached original.

  16. Midnight Arrow reporter

    @Aszrael There is probably a way to create a direct 1:1 assignment using vector math and booleans, but I don’t know enough about geonodes yet to even imagine what that node tree would look like.

    The Capture Attribute node caches the state of a mesh so we can refer to it later. In order for it to work we have to tell it what kind of data we want to cache. The Index node tells it to store the unmodified vertex indices. If we changed the dropdown to Vector and plugged in a Position node it would store the vertex coordinates of the mesh at that point in the tree.

    You can examine the attribute data with the spreadsheet editor and a viewer node.

  17. Aszrael

    @Thomas: I would suggest to only deactivate the modifiers of the Geografts. That’s again more consistent with the non-destructive workflow.

    Just wondering: At the very end, when you’re done with all the editing with GeoNodes. A button to apply, incl. clean up of all not-further required vertex groups makes sense. I learnt, that GeoNodes is quite computation consuming. But the impact it has was quite a surprise…

    And btw: Replacing the UV-map with Attribute node in all the Shaders:
    Would be great to have such a feature as a switch on-and-off as well. My gut feeling tells me, one day GeoNode will handle UV-Maps - so it simply can be removed.

  18. Aszrael

    @Thomas: I just checked you last commit. You forgot to either remove or deactivate the Subsurf Modifier of the Geograft. As told I’m not an expert in Geometry Nodes, but just my observations:

    That’s the geometry (= Geograft Edge) of the Geograft for merging with subsurf level 1 (vertex count 156):

    vs the Geograft after removing/deactivating the Geograft subdivision modifier (vertex count 36):

    As the GeoNode Modifier acts before the Subsurf Modifier of the Figure, the Figure is in non-subdivided state - hence merging will fail.

    Besides that: For the merged figure, the vertex count grows (e.g. vertex count: 18 484 vs 25 079). Further more, if subsurf of the merged geometry is enabled - the Geograft get subdivided on top.

  19. Aszrael

    @Midnight: actually an 1-to-1 assignment should be rather simple, as you have fixed vertex-IDs for all Daz-Objects. Of course you would have to create the assignment table for each geograft separately. However, GeoNodes’s Merge Node doesn’t provide such a feature (at least what I googled) - so I also see not benefit in follow this path further… Beside the fact, that doing it with mathematics would cost further performance…

  20. Midnight Arrow reporter

    @ Aszrael

    A UV map is just an attribute with a Face Corner → Vector2D mapping and geonodes already handle it to a limited extent, though it still has some failings right now.

    The merge node could handle a 1:1 assignment since you control everything passed into it. You just need a way to filter out vertices so that only the two vertices you’re interested in are selected for merging.

  21. Alessandro Padovani

    There’s “advanced setup > mesh > create graft groups” to get the graft borders and mask if this is what you’re looking for.

  22. Aszrael

    @Alesandro: No - we already have the GeoGraft and Figure Edges as vertex groups. What I need is a simple way to tell GeoNode to take Figure-VertexID[i] + GeoGraft-VertexID[i] and merge only those.

    As the VertexIDs are fixed for all DAZ-Models, you could directly tell GeoNode to only merge these vertices together doesn’t matter the distance they have. The Vertex count is rather small (only 36 vertices) so it should be doable.

    Alternatively, if one could force Geonode to only merge one vertex with only the next one - that would help as well. Currently, you can only give one float as a Distance value.

    That’s a problem, if you use a morphed figure, as the Geograft does not morph accordingly (even with the morph transfered). So, on one side some vertices will not merge (as distance value is too low) while on the other some vertices will merge with more than only their next neighbor. I know, that’s more related to a badly applied morph, but.. hey: at least a motivation to learn GeoNodes better 😉

    I already wrote a list for the Vector-IDs of the Figure:

    • 48, 4916, 3033, 1767, 1766 ,1768, 3979, 3347, 1607, 4397, 1409, 552, 873, 3113, 3105, 3112, 3111, 3103, 28, 9278, 3285, 9286, 9279, 9287, 7059, 6738, 7595, 10545, 7793, 9515, 10138, 7954, 7952, 7953, 9209, 1063

    and one for Dicktator:

    • 1, 18, 9, 7, 6, 8, 16, 15, 5, 17, 4, 2, 3, 14, 11, 13, 12, 10, 0, 27, 29, 30, 28, 31, 20, 19, 21, 34, 22, 32, 33, 25, 23, 24, 26, 35

    So only left is to force GeoNode going through the list Vertex per Vertex an merge only these.

    … Don’t liking the idea, to have put in 2x36 values and call merge by distance 36 times… In python it should be only a for-loop, but in GeoNodes…

    UPDATE: Just realizing, after Join Geometry the Vertex-ID should have changed… 😅

    UPDATE 2: Found a better way of doing it:

    Simply copy the vertex-positions of the morphed Figures Edge over to the morphed GeoGraft Edge does the job

  23. Thomas Larsson repo owner

    Merging shouldn’t be a problem provided that the merge distance is sufficiently small. The vertices on the geograft boundary are moved to the exact locations of the corresponding body vertices before the nodes modifier is created, so there shouldn’t be any risk of gaps.

    The Merge Distance has been extracted as an extra input. By default it is set to 0.1 mm, which should be small enough in most cases.

  24. Thomas Larsson repo owner

    @Aszrael: A separate button for applying the geograft modifier does not seem to be needed. You can either apply the modifier, or delete it and run the Merge Geografts tool again with Geometry Nodes disabled. The only left-overs are the Geograft Edge and Geograft Mask vertex groups.

  25. Aszrael

    @Thomas: Wow - your are quick. Actually to put the Merge distance into the Modifier panel was a suggestion I was thinking of, too.

    However, the problem is realated to applying morphs to the imported figure (and yes - I have already applied (transfer Shapekeys) to the Geograft.

    Fiddeling with the Distance parameter result in a merged geograft - but, on the backside - the merged Geograft have some vertices pushed to close together - smaller than the merge distance:

    (that’s actually is the crease of the butt 🙂 )

    Decreasing merge distance slightly will help:

    but results in a not completely merged geograft on the front. However, that’s more related to how the morph transfer on the geofraft. Reducing morph-value lifts the problem.
    Actually, as the morph induces other artefacts on the geograft as well, I will have to resculpt it anyway (it’s the MASSIV morph, btw). So it’s simpler to push the morphed geograft-edge vertices in the appropriate position as well. Hence, I see no reason to do it with a repositioning in GeoNodes as suggested before.

    Concerning the apply modifier. Yes - your right. You might consider a hint in the manual or even in the addon dialog as well. Something like Geometry Node (see: modfiers) or something like that.

  26. Aszrael

    @Thomas: Easy import crashes if Merge Geografts - Geometry Nodes (Experimental) is selected, if you also select Mannequin.

    and no Mannequin Mesh is created (only an empty Collection).
    Michael 8.1 with Dicktator v3.

    Make mannequin
    Python: Traceback (most recent call last):
      File "/home/stefan/.config/blender/3.1/scripts/addons/import_daz/error.py", line 208, in execute
        self.run(context)
      File "/home/stefan/.config/blender/3.1/scripts/addons/import_daz/proxy.py", line 1400, in run
        obs,nobs,rig = self.addMannequins(context)
      File "/home/stefan/.config/blender/3.1/scripts/addons/import_daz/proxy.py", line 1436, in addMannequins
        nobs[ob.name] = self.addMannequin(ob, context, rig, coll, mangrp)
      File "/home/stefan/.config/blender/3.1/scripts/addons/import_daz/proxy.py", line 1480, in addMannequin
        face_mats[rnd][tuple(round(x, rnd) for x in f.normal)] = ob.material_slots[f.material_index].material
    IndexError: bpy_prop_collection[index]: index 14 out of range, size 14
    
    location: /home/stefan/blender-git/3.1/bin/3.1/scripts/modules/bpy/ops.py:132
    Error: Python: Traceback (most recent call last):
      File "/home/stefan/.config/blender/3.1/scripts/addons/import_daz/error.py", line 208, in execute
        self.run(context)
      File "/home/stefan/.config/blender/3.1/scripts/addons/import_daz/proxy.py", line 1400, in run
        obs,nobs,rig = self.addMannequins(context)
      File "/home/stefan/.config/blender/3.1/scripts/addons/import_daz/proxy.py", line 1436, in addMannequins
        nobs[ob.name] = self.addMannequin(ob, context, rig, coll, mangrp)
      File "/home/stefan/.config/blender/3.1/scripts/addons/import_daz/proxy.py", line 1480, in addMannequin
        face_mats[rnd][tuple(round(x, rnd) for x in f.normal)] = ob.material_slots[f.material_index].material
    IndexError: bpy_prop_collection[index]: index 14 out of range, size 14
    
    location: /home/stefan/blender-git/3.1/bin/3.1/scripts/modules/bpy/ops.py:132
    
    Python: Traceback (most recent call last):
      File "/home/stefan/.config/blender/3.1/scripts/addons/import_daz/error.py", line 208, in execute
        self.run(context)
      File "/home/stefan/.config/blender/3.1/scripts/addons/import_daz/main.py", line 721, in run
        self.easyImport(context)
      File "/home/stefan/.config/blender/3.1/scripts/addons/import_daz/main.py", line 755, in easyImport
        self.treatRig(context, rigname)
      File "/home/stefan/.config/blender/3.1/scripts/addons/import_daz/main.py", line 975, in treatRig
        bpy.ops.daz.add_mannequin(useGroup=True, group="%s Mannequin" % mainRig.name)
      File "/home/stefan/blender-git/3.1/bin/3.1/scripts/modules/bpy/ops.py", line 132, in __call__
        ret = _op_call(self.idname_py(), None, kw)
    RuntimeError: Error: Python: Traceback (most recent call last):
      File "/home/stefan/.config/blender/3.1/scripts/addons/import_daz/error.py", line 208, in execute
        self.run(context)
      File "/home/stefan/.config/blender/3.1/scripts/addons/import_daz/proxy.py", line 1400, in run
        obs,nobs,rig = self.addMannequins(context)
      File "/home/stefan/.config/blender/3.1/scripts/addons/import_daz/proxy.py", line 1436, in addMannequins
        nobs[ob.name] = self.addMannequin(ob, context, rig, coll, mangrp)
      File "/home/stefan/.config/blender/3.1/scripts/addons/import_daz/proxy.py", line 1480, in addMannequin
        face_mats[rnd][tuple(round(x, rnd) for x in f.normal)] = ob.material_slots[f.material_index].material
    IndexError: bpy_prop_collection[index]: index 14 out of range, size 14
    
    location: /home/stefan/blender-git/3.1/bin/3.1/scripts/modules/bpy/ops.py:132
    

  27. Thomas Larsson repo owner

    Should work now. The nodes modifier is temporarily disabled when mannequins are made, and the problem disappears.

  28. Midnight Arrow reporter

    @ Azsrael

    It’s easy to isolate effects to only one vertex. Geonodes are context sensitive. If you use the Index node it’ll be evaluated for every element, so you run it through a Compare node to see if it matches whatever vertex you want to manipulate.

    The big problem is that geonodes has no capabilities for arrayed indices, so you need to create a nightmare of dozens of boolean math and compare nodes to do something relatively simple.

  29. Aszrael

    @Midnight: Year - GeoNodes really forces me to turn around thinking. Firstly, I created a Node group with 72 value inputs, even a loop I tried (avoid it, my rather beefy computer stopped reacting to me) only to learn that after a joint the internal vertex order is changed… 😅

    You know, I found a simpler solution already (see one of my last posts). But great to know someone here knows anything about GeoNodes. I’m sure it’ll have some further use for DAZ content.

    However, the root cause is: the Geograft is highly depended on how well the morph is transferred over to it. As I got oddly deformations elsewhere, I had to sculpt it for a fix, and - if you start sculpting - you can also fix the geograft’s edges to work with a simple merge with constant distance.

  30. Suttisak Denduangchai

    @Aszrael Can you explain how to copy the vertex-positions of the morphed Figures Edge over to the morphed GeoGraft Edge? I have the same problem as you describe. I try to use transfer attribute and set position node to transfer the vertex position from genesis 8.1 Geometry Edge vertex group to FulllMonty geograft Geometry Edge vertex group but the mesh become a mess I suspect the vertex Id is mismatch

  31. Midnight Arrow reporter

    @ Suttisak

    The vertex IDs won’t match because the geometry is different. Index matching only works if the meshes are identical.

    You shouldn’t be transferring vertex positions to the geograft. That can create a feedback loop where the mesh deforms the geograft which deforms the mesh etc. as they’re evaluated. It should have an only one-way relationship.

  32. Suttisak Denduangchai

    @Midnight Arrow I see, But I currently have the same problem as @Aszrael some morphs are not transferred 100% correct so when using some morph, the shape of geograft are not perfectly aligned causing a gap. Trying to change merge distance doesn’t help because it requires a different value for each vertex pair. This is not a problem for destructive geograft ( which I don’t really like much because it’s inflexible especially when I forget to import figure morph).

    If there is a way to copy the vertex position of edge of geograft to figure and vice versa. For example, If I use vag_open morph on FullMontyBBQ, the edge of geograft will not align with Futalicious and Figure edge causing the gap.

    or a way to applied to morph after merge geometry node it' would be good

  33. Midnight Arrow reporter

    I can offer an idea but I don’t have that product so I don’t know how well it’ll work.

    • Create two separate copies of the geograft mesh.
    • Use one as the geograft source.
    • Inside the figure’s geonodes, cache a copy of the geograft’s indices before joining it to the figure.
    • Import the shape keys to the other geograft mesh.
    • Create a geonode setup inside it.
    • Use vector math to subtract its vertex positions from the unaltered geograft.
    • Store the vertex positions as a Vertex → Vector attribute.
    • Back in the figure’s geonode setup, fetch the vertex deltas.
    • Use them with the cached indices to deform the joined mesh.

    It’s convoluted but I use something similar to create corrective shape keys for figues I link into a scene.

    The Blender Foundation are converting everything under the sun to nodes so I’m sure it won’t be long before there’s nodes to handle shape keying and animation.

  34. Suttisak Denduangchai

    Can you check my node setup?

    Geonode setup of shapekey mesh (FullMontyBBQ.001) This imports the unaltered geograft (FullMontyBBQ) and uses Vector Math to subtract the position (FullMontyBBQ.001 - FullMontyBBQ) and stores the result as “Vertex Delta” attribute of “FullMontyBBQ.001”

    Geonode setup of Fulalicious (I am testing by trying to join FullMontyBBQ over Futalicious)

    Right not you can see that I export Vertex Delta from FullMontyBBQ, but I don’t know how to import that in Futalicious node so I just replicate the Vector math again.

  35. Midnight Arrow reporter

    Unfortnately I just bungle my way through my own node setups until they work, so I can’t really say if that’ll be good enough.

    Come to think of it doing the vertex math inside the figure’s geonode setup probably makes more sense. But for the record if you want to import an attribute just use its name. Connect a socket to the group input, go to the modifier stack, and press the spreadsheet icon to open a field. Then just type the name there. It will only autocomplete attributes on the same node but whatever you type in there will work anyway. Take that input and feed it into a Transfer Attribute node, which is what associates the name with the data and brings it over.

  36. Алексей Беседин Account Deactivated

    In the new alpha version of Blender 3.4, rig does not work after join meshes node in geometry node editor, I'm not sure what the problem is, it seems to me it's something on the blender side...

  37. Thomas Larsson repo owner

    Alpha versions can be buggy. If the problem persists in the final release, I will look into it.

  38. Miki3d

    Hi there!
    I just jumped into the loop since I’m very interested in the non-destructive workflow using geonodes.
    Doing tests with the latest dev version 1.6.2.1207, works fine on blender 3.2.2, but on 3.3, after the merge, the rig doesn’t work anymore.
    I guess it’s the same problem mentioned by Алексей Беседин on b3.4.
    Thank you very much and keep the good work!

  39. Miki3d

    Aszrael I didn’t touch them, the order is the same as in blender 3.2, Geograft first, Armature later. If I switch them just the main body moves with the rig.

  40. Aszrael

    @Miki3d - My understanding is: that’s how it works now. I’m already on 3.3 and 3.4 alpha - cannot test 3.2 or 3.1 - sorry. But: in order to pose, you have to either disable the Geo-Modifier - or move the Armature-Modifier above the Geo-Modifier.

    Btw: if your problem is the detachment (not moving) of the Geograft: you have to enable the Armature Modifier for the original Geograft. The original Geograft is disabled after the Geo-merge (same for the Armature-Modifier of the Geograft). So: select the original Geograft in your “Scene Collection” and reenable the Armature Modifier of it.

    I might be wrong (I’m all else than an expert) - but that’s how Geometry Nodes works now (my guess). Scanning through the old text here: there was s.th. like armature doubling up (doubling the movement / pose of the geograft) - so: Thomas had to deactivate the armature of the original Geograft. However with 3.3 - blender evolved (again). Maybe s.o. with better knowledge can comment here - might even be, GeoNodes got new options I don’t know.
    However, as 3.3 is LTS now. Thomas might consider to take 3.3 blender as standard.
    And consider:

    • make an annotation somewhere on screen - or at least in the tutorial - saying s.th. like: in order to pose, geometry node Modifier has to be deactivated. Currently, there’s just a hint in the Tutorial to deactivate Geo-Node for performance reason.
    • enable the Armatrure for the original Geograft - so it moves / is posable by default.

    BTW: That’s all guesswork - so maybe s.o. with a lower blender version can check, if the modifier behavior was different.

    Also optional: it is simply a new blender bug 😅.

  41. Midnight Arrow reporter

    I’m not using Blender for rendering anymore, but when I was I found a much better workflow is to create a cube, delete the geometry input, and then add the figure and the geografts inside that with Object Info nodes. Don’t try and mix geometry nodes modifiers with armature modifiers. Just create a static duplicate of the whole mesh, totally separate from the original, and use that to stitch your geografts together and render it. Works much better and there’s no posing problems.

  42. Thomas Larsson repo owner

    I implemented Aszrael’s fix in the last commit. Now geografts are posed correctly in both Blender 3.2 and 3.3.

    Mignight, I’m not sure that I understand what you suggest, but it might be worth doing some experiments. We’ll see if anything comes out of it.

  43. Aszrael

    Thomas I like the approach midnight suggested: create a separate object and via static copys of the original meshes you tune the joined meshes within geonodes. Keeps the Scene organized and you even keep the original meshes!

    I’m on work now, can post some suggestions later if you want.

  44. Thomas Larsson repo owner

    The Merge Geograft tool now has an extra option, which controls whether the output is the original main mesh or a new, empty mesh. The latter almost works, but for some reason you have to select the nodes modifier and toggle one of the input attributes off and on again. Don’t know why this does not work automatically.

    The node tree has also been simplied, and the vertex table output has been removed. It didn’t make much sense with geonodes, IMO. With destructive merging you need a vertex table to add new morphs after the merge, but with geonodes the original meshes are still available and morphs can be loaded directly to these. Perhaps the nodes modifier must be temporarily disabled.

  45. Aszrael

    @Thomas: 2 things I want to mention:

    1. in order to have a good merge, you should deactivate or delete the subdivision modifiers from the original meshes. I would actually delete them.
    2. in Geo-Node: I have to switch the order of the 2 meshes in the “Join Geometry”-Node to make the Geograft get it’s textures/shading. So first the Geograft, 2nd the Base Mesh. (no clue why).

    BTW: on/off toggling: I do not understand what you mean - can you elaborate what’s not working for you? I do not have to toggle to get s.th. to work.

  46. Thomas Larsson repo owner

    Subdiv modifiers are disabled.

    I don’t notice any difference in shading depending on the order that the meshes are joined, but changing the order doesn’t seem to hurt either in Blender 3.3, so I did it. Not in Blender 3.2 though, because that would be a disaster.

    The other problem is solved. I had to set the modifier input attributes before changing them from value to attribute.

  47. Aszrael

    @Thomas: for some reason the base mesh subdiv modifier is not deactivated, while the geograft is. Far more important is to put an subdiv modifier for the merged meshes.

    Actually for me it makes no sense to keep the subdiv modifiers on the original mesh - so I delete them. Please, correct me if I got s.th. wrong here.

    Btw: That’s nothing directly related with the Geograft merge. The subdiv modifier after import directly throws the message: Autosmooth or custom normals detected, disabling GPU subdividions.

    Are you importing custom normals somehow or use autosmooth on the mesh?

    UPDATE: Ok - just found it in the discussions; you enabled autosmooth. I was just wondering - however: to be consistent: the merged meshes have no autosmooth enabled.

  48. Midnight Arrow reporter

    @ Thomas

    The reason I outputted a vertex table was because the Delete Geometry node is very useful to replace the Mask modifier. But Delete literally deletes the geometry and reorders the vertices. By caching the vertex order, they can be reassociated for operations after the mesh has been masked. If you’re using composition-based workflow (all operations are done on one separate object) then you can just use a Capture Attribute node to bypass the Delete Geometry so a vertex table isn’t necessary anymore.

    @ Aszrael

    Geometry nodes will destroy UVs unless you replace the Texture Coordinate/UVMap node with an Attribute node and use that to fetch the UVs. Integrating hardcoded data like UVs and bevel strength with generic attributes is still a WIP, but there’s some feature requests on the Blender repo to move towards this.

    Geometry nodes have their own subsurf node. Just remove all the subsurf modifiers and then add nodes to the unified node tree as needed.

  49. Alessandro Padovani

    As for autosmooth it is necessary to convert the iray shaders since iray uses it, especially for low poly meshes as primitives it makes the difference. But you can disable it in the global settings.

    As for geometry nodes I helped to fix the shells in #1020 so I hope you’re not breaking anything, because actually I have not much time for testing. But I’m definitely not an expert so I’m of little help here.

  50. Thomas Larsson repo owner

    Azrael, the subsurf modifier on the base mesh has now been moved to the new mesh. However, I don’t understand why the armature modifier cannot be moved too. I mean, it doesn’t work, but why doesn’t it when subsurf does? They should both work on the output of the nodes modifier above, shouldn’t they?

    Midnight, I just saw your comment on a subsurf node when I wrote this. Will look into that later.

    Merging replaces texture coordinate nodes with uvmap nodes. Do you really need attribute nodes? Uvmap nodes seems to work here.

  51. Rincewind

    There’s sadly one issue with the geo-nodes approach for geo-crafts with an own UV:
    It will break displacement.

    Well, this is a Blender issue and there’s nothing what we can do for now.

    In general, textures seems to be generally broken, as soon you are joining geometry with geocrafts.
    At least there’s a workaround. If you select manually the uv map for each texture, textures are working again:

    Sadly the same trick isn’t working for displacement.
    My displacement on a figure differes from a version without a geocraft and may also to have some visible erros in the displaced mesh.

    However, Blender is aware of the issues with UVs and geo-nodes mesh-joins.
    There’s already a ticket https://developer.blender.org/T85962
    And this comment is also pretty intresting:
    https://developer.blender.org/T85962#1387361

  52. Aszrael

    Thomas: Frankly, I have no clue why the Armatur-Modifier is not working on the geoMerged-mesh. I would have expected it to do so, too. But my GeoNode-Workflow is more trail end error and scanning through the manuals. I’m definitely not the guy you should ask for help - I’m sorry for that. However, I realized that after applying the GeoNode-modifier, the mesh has no Vertex Groups (i.e.: no weights).

    Btw: You might also consider to store the GeoNode-mesh in a separate Collection - just for readability.

    Subsurf within GeoNode: Yes, I know that. But, I would keep a separate modifier on the GeoMerged-Mesh, as:

    • It provides neither performance benefits, nor anything others. Please correct me if I’m wrong.
    • In case you will apply the GeoNode Modifier at the end, you will also apply the subdivisions. Of course, you can go into the node setup and switch the subdiv-level down, or present the division-level as an input value (for the GeoNode-Modifier) but that makes it even harder to read.

    Just my thoughts 😉

    PS: Thomas , please remember to update the easy import script as well - it’s so handy. 😃
    And: you also might explain somewhere, that in order the GeoNode-Merge to work, you must not change the original mesh. I frequently merge the Face-Meshes (Eyelashes, etc.), but that must be done after the GeoNode setup. BTW: why can’t Eyelashes beeing merged like Geografts - just wondering….

    For me the GeoNode-Merge workflow is only the first step for tuning a character - playing around with morphs, the shading, textures.
    But:

    • Sculpting is not possible (fixing some extreme morphs)
    • Posing might result in detached meshes
    • Animating is a pain - even on my relatively beefy machine
    • … and other stuff I did not come across, yet

    The great thing with this GeoNodes approach is: You keep the original files untouched, but create a copy. As soon I’m happy with the copy (all textures, shading, etc.): Apply, the GeoNode-Modifier - and you have a separate mesh for continuation (Posing, Animating, etc.). Jepp, that’s the reason I ask for a separate Collection. 😉

    PS: if anyone is interested in my approach: you have to transfer the weights from the original meshes over and - of course - add the Amature Modifier (and the subsurface).

  53. Midnight Arrow reporter

    @ Thomas @ Rincewind

    Last time I tried this (3.1), you needed to use an Attribute node in lieu of a UVMap/Texture Coordinate node or else the textures break. Maybe it’s been fixed since then? Thomas says it works, Rincewind says it doesn’t, so I don’t know.

    @ Aszrael

    The armature modifier correlates bone names with vertex groups. The merged mesh doesn’t have vertex groups, you need to transfer them manually. That’s why the armature modifier should stay on the original mesh. It’s pointless to put one on the merged mesh anyway because it lags as the depsgraph constantly reevaluates the geonode modifier. You keep the armature modifier on the original unmerged low-poly mesh(es) so it’s quick and efficient.

    It’s more useful to separate by scene than by collection. You create one scene with your low-poly posing meshes, then create another scene with your combined object for rendering. That way your outliner doesn’t have unnecessary objects in it.

    Geometry nodes are replacing modifiers. They’re meant to work in a nonlinear workflow, so putting them in the node tree is the new “correct” way. Plus it’s a bad idea to put them as modifiers because hair has a much higher vertex count than a body. You may want 3 subsurf levels for a figure but only 1 for hair. Just output them from the modifier and expose them in the modifier stack if you want to control the subsurf level.

    Sculpting is possible on a duplicate of the mesh. With some hack workarounds and vector math you can subtract vertex positions and send them to the merged mesh with a Set Position node.

  54. Rincewind

    @Midnight Arrow

    Can you give please an example/screenshot of what you meant with Attribute node instead of the UVMap like I did in my screenshot above?

  55. Aszrael

    Midnight wrote:

    “It’s more useful to separate by scene than by collection.”

    That’s definitely a quite creative way for organization… But, I really hope Thomas will not implement it, as most of the users here do not even know how to switch scenes (nor will have the motivation to do so…).

    “Geometry nodes are replacing modifiers.”

    That’s really new to me - do you have a source? I know that they try hard to finally bring all (and more) modifiers into GeoNodes, but hopefully they will NOT drop the object-centric way for modeling. I’m not even aware of any non-linear way for character creation (yes, I’m getting old).

    “Just output them from the modifier and expose them in the modifier stack if you want to control the subsurf level.”

    Please Thomas, do not put a subdiv-modifier into any GeoNode-Modifier. Remember: that most users here do not even know what a modifier is, nor does he/she wants to freak around with GeoNodes.

    @Midnight Arrow: Please, don’t get me wrong. I’m not saying you are doing/saying anything wrong. I’m quite sure you know the stuff mush better then I.
    But just by reading most of the posted Issues here: Most do not even know how to / or are willing to read a manual. So I think the best way of implementing things is to make it as simple and easy to follow for beginners as possible.

    That’s said: I would even suggest to remove the 2 attribute fields for the vertex groups from the GeoNode-Modifier of the merged mesh and only keep the Merge Distance exposed. The users should not fiddle around with them - and if they would/could they should know what they are doing.

    Thomas: You might even consider another Finalize Button, to create the Merged Mesh object (a Makro):

    • apply the GeoNode-modifier
    • Transfer the Vertex-weights from the original Mesh and the original Geograft to the new merged object (vertex-groups should be created by that)
    • Add an Armature-Modifier on top of the stack (The subdiv-Modifier below it)
    • deactivate the Armature-Modifiers for the original Meshes
    • shift the new Merged Object to another Collection (e.g. named: <Character name> Merged
    • optional: rename the original Collection with something that makes sense (e.g.: <Character name> original)

    My guess is: that’s what the most beginners would be best suited with

  56. Alessandro Padovani

    This is implemented now and there are no news. Please reopen if you get new ideas or enhancements.

    Bugs can be addressed apart for better handling.

  57. Log in to comment