hair disconnect/reconnect not working with modifiers #54488

Closed
opened 5 years ago by omgold · 15 comments
omgold commented 5 years ago

System Information
Linux (Arch), GTX 1080

Blender Version
2.79b f4dc9f9d68

Short description of error

When using a hair particle system on an object with a mirror modifier, and trying to disconnect and then reconnect the hair the particle positions are messed up.

Exact steps for others to reproduce the error

  • create a cube object
  • add a mirror modifier with merge and clipping options enabled (it seems to happen in the same way with separated mirrored cubes also, though)
  • add a hair particle system to the object
  • comb hair in particle edit mode
  • disconnect and reconnect particle system

hair-mirror-2.blend

More Info

  • After the steps done for the first and second blend files everything looks good. Adding a particle system and particle edit on a mirror object seems to work.
  • But disconnecting and reconnecting has the (immediately to be seen) effect of moving all the hair from the 'mirrored' (right) part of the object to the rightmost end of the left part, as shown in the third blend file
  • Enabling and disabling children shows that in addition to that problem the particle system data seems to have been messed up further by the disconnect/reconnect, as after that last step the hair positions are completely messed up.
  • If you enable 'Simple' children in particle system settings and disable them again, will see a different mess:
    hair-mirror-4.blend
**System Information** Linux (Arch), GTX 1080 **Blender Version** 2.79b f4dc9f9d68b **Short description of error** When using a hair particle system on an object with a mirror modifier, and trying to disconnect and then reconnect the hair the particle positions are messed up. **Exact steps for others to reproduce the error** - create a cube object - add a mirror modifier with merge and clipping options enabled (it seems to happen in the same way with separated mirrored cubes also, though) - add a hair particle system to the object - comb hair in particle edit mode - disconnect and reconnect particle system [hair-mirror-2.blend](https://archive.blender.org/developer/F2567847/hair-mirror-2.blend) **More Info** - After the steps done for the first and second blend files everything looks good. Adding a particle system and particle edit on a mirror object seems to work. - But disconnecting and reconnecting has the (immediately to be seen) effect of moving all the hair from the 'mirrored' (right) part of the object to the rightmost end of the left part, as shown in the third blend file - Enabling and disabling children shows that in addition to that problem the particle system data seems to have been messed up further by the disconnect/reconnect, as after that last step the hair positions are completely messed up. - If you enable 'Simple' children in particle system settings and disable them again, will see a different mess: [hair-mirror-4.blend](https://archive.blender.org/developer/F2567848/hair-mirror-4.blend)
omgold commented 5 years ago
Poster

Added subscriber: @omgold

Added subscriber: @omgold
Collaborator

#67069 was marked as duplicate of this issue

#67069 was marked as duplicate of this issue
brecht commented 5 years ago
Owner

Added subscriber: @brecht

Added subscriber: @brecht
brecht commented 5 years ago
Owner

The problem here is that the "Use Modifier Stack" setting is not properly taken into account for these disconnect/reconnect operators.

The problem here is that the "Use Modifier Stack" setting is not properly taken into account for these disconnect/reconnect operators.
Collaborator

Added subscriber: @lichtwerk

Added subscriber: @lichtwerk
Collaborator

Hi @brecht, @omgold, I've seen you discuss this on the mailinglist (and I understand reaching out here as for some reason this report seemed to slip under the radar)
But: why not continue here? This way others (including me) can follow and participate much better.
Sorry for the wall of text, but pasting from the mailinglist, so it doesnt get lost...

Hi,

thanks you very much for taking the time to explain.

After more checking of the behavior with or without using dm_deformed, I understand things somewhat better.

  • I believe what you mean with 'use modifier stack' in combination with subsurf not working well is, that generative modifiers garble the face indices, so changes like switching the modifiers on/off or changing subdivision level will result in the hair >being a complete mess. Correct?

  • What surprised me a little, though, was that disconnect/reconnect will result in garbage also in the presence of generative modifiers, without 'use modifier stack' enabled. E.g. for subsurf the hair will be attached at the location of the original >mesh, leaving a gap.

  • I found, when using dm_final instead of dm_deformed, both with and without 'use modifier stack', the hairs are placed nicely after a reconnect, but in both cases, they seem not to be attached correctly. This will only become visible after deforming >or moving geometry around.

  • Only got a rough understanding about the latter problem. The culprit seems to be this:

    tpa->num_dmcache = psys_particle_dm_face_lookup(target_dm, dm, tpa->num, tpa->fuv, NULL);

As far as I get it, psys_particle_dm_face_lookup() doesn't do the right thing then. The other place, where this is used, psys_calc_dmcache() in source/blender/blenkernel/intern/particle_system.c, seem to have a special treatment for the case of >'use modifier stack' enabled.

Best regards,

O.

Hi,

By default for hair, it is attached to the original mesh before modifier
stack evaluation, referencing one of the faces in the original mesh. The
advice is generally to apply the mirror modifier before starting hair
editing.

In your file the "Use Modifier Stack" option is enabled, which attaches the
hair to the mesh after modifier evaluation. This makes it work for the
mirror modifier (but will not work so well in other cases like subsurf
which is why the option is off by default).

The bug seems to be that the disconnect/reconnect hair operator does not
take into account this "Use Modifier Stack" setting, in that case it should
use the final mesh instead of the deformed (original) mesh.

Regards,
Brecht.

On Sun, May 27, 2018 at 7:35 PM, Oliver Mangold <o.mangold at gmail.com> wrote:

Hi,

I would like to fix a bug, concerning disconnect/reconnect of hairs on an
object with a mirror modifier. I already reported it (
https://developer.blender.org/T54488), but now I also dug a little into
the relevant code. My findings are, that in the function
remap_hair_emitter(), which does the main work of reconnecting hair to the
mesh, there is a weird case decision

   if (target_psmd->dm_final->deformedOnly) {
          /* we don't want to mess up target_psmd->dm when

converting to global coordinates below */
dm = target_psmd->dm_final;
}
else {
dm = target_psmd->dm_deformed;
}

where in my tests the second branch is taken, thus dm_deformed is used for
the further steps, in particular to build the BVH which is used to search
for the nearest face to connect the a hair to.

          bvhtree_from_mesh_get(&bvhtree, dm, BVHTREE_FROM_FACES, 2);

It seems that in dm_final the mirrored faces are present, while in
dm_deformed they are not. Thus was happens is, that the hair on the
mirrored side get connected to the nearest point of the nearest unmirrored
face. The problem goes away when removing the case decision and always
using dm_final. Checking the history, once it worked that way, and was
changed to the current situation in this commit:

commit 0666de06f3
Date: Thu Jan 15 18:15:52 2015 +0100

Fix for particle system copy: This has to make sure the ORIGSPACE data
layer is available.

Otherwise particle mapping to the new mesh cannot work with subdivided
and constructively-modified meshes.

I have to admit, that I got lost at that point. I'm not familiar enough
with the code yet, to understand what really is the idea behind selecting
dm_final or dm_deformed, and what problem exactly was fixed by that. Would
be great if someone could explain. How can this bug be fixed without
breaking the fix of the commit above?

Best regards,

O.

Hi @brecht, @omgold, I've seen you discuss this on the mailinglist (and I understand reaching out here as for some reason this report seemed to slip under the radar) But: why not continue here? This way others (including me) can follow and participate much better. Sorry for the wall of text, but pasting from the mailinglist, so it doesnt get lost... > Hi, > >thanks you very much for taking the time to explain. > >After more checking of the behavior with or without using dm_deformed, I understand things somewhat better. > >- I believe what you mean with 'use modifier stack' in combination with subsurf not working well is, that generative modifiers garble the face indices, so changes like switching the modifiers on/off or changing subdivision level will result in the hair >being a complete mess. Correct? > >- What surprised me a little, though, was that disconnect/reconnect will result in garbage also in the presence of generative modifiers, *without* 'use modifier stack' enabled. E.g. for subsurf the hair will be attached at the location of the original >mesh, leaving a gap. > >- I found, when using dm_final instead of dm_deformed, both with and without 'use modifier stack', the hairs are placed nicely after a reconnect, but in both cases, they seem not to be attached correctly. This will only become visible after deforming >or moving geometry around. > >- Only got a rough understanding about the latter problem. The culprit seems to be this: > > tpa->num_dmcache = psys_particle_dm_face_lookup(target_dm, dm, tpa->num, tpa->fuv, NULL); > > As far as I get it, psys_particle_dm_face_lookup() doesn't do the right thing then. The other place, where this is used, psys_calc_dmcache() in source/blender/blenkernel/intern/particle_system.c, seem to have a special treatment for the case of >'use modifier stack' enabled. > >Best regards, > >O. > >Hi, > > > >By default for hair, it is attached to the original mesh before modifier > >stack evaluation, referencing one of the faces in the original mesh. The > >advice is generally to apply the mirror modifier before starting hair > >editing. > > > >In your file the "Use Modifier Stack" option is enabled, which attaches the > >hair to the mesh after modifier evaluation. This makes it work for the > >mirror modifier (but will not work so well in other cases like subsurf > >which is why the option is off by default). > > > >The bug seems to be that the disconnect/reconnect hair operator does not > >take into account this "Use Modifier Stack" setting, in that case it should > >use the final mesh instead of the deformed (original) mesh. > > > >Regards, > >Brecht. > > > > > > > > > > >On Sun, May 27, 2018 at 7:35 PM, Oliver Mangold <o.mangold at gmail.com> wrote: > > > > > >Hi, > > > > > >I would like to fix a bug, concerning disconnect/reconnect of hairs on an > > >object with a mirror modifier. I already reported it ( > > >https://developer.blender.org/T54488), but now I also dug a little into > > >the relevant code. My findings are, that in the function > > >remap_hair_emitter(), which does the main work of reconnecting hair to the > > >mesh, there is a weird case decision > > > > > > if (target_psmd->dm_final->deformedOnly) { > > > /* we don't want to mess up target_psmd->dm when > > >converting to global coordinates below */ > > > dm = target_psmd->dm_final; > > > } > > > else { > > > dm = target_psmd->dm_deformed; > > > } > > > > > >where in my tests the second branch is taken, thus dm_deformed is used for > > >the further steps, in particular to build the BVH which is used to search > > >for the nearest face to connect the a hair to. > > > > > > bvhtree_from_mesh_get(&bvhtree, dm, BVHTREE_FROM_FACES, 2); > > > > > >It seems that in dm_final the mirrored faces are present, while in > > >dm_deformed they are not. Thus was happens is, that the hair on the > > >mirrored side get connected to the nearest point of the nearest unmirrored > > >face. The problem goes away when removing the case decision and always > > >using dm_final. Checking the history, once it worked that way, and was > > >changed to the current situation in this commit: > > > > > >commit 0666de06f3119ff1640f1eb66833cd4feb669209 > > >Date: Thu Jan 15 18:15:52 2015 +0100 > > > > > > Fix for particle system copy: This has to make sure the ORIGSPACE data > > > layer is available. > > > > > > Otherwise particle mapping to the new mesh cannot work with subdivided > > > and constructively-modified meshes. > > > > > >I have to admit, that I got lost at that point. I'm not familiar enough > > >with the code yet, to understand what really is the idea behind selecting > > >dm_final or dm_deformed, and what problem exactly was fixed by that. Would > > >be great if someone could explain. How can this bug be fixed without > > >breaking the fix of the commit above? > > > > > >Best regards, > > > > > >O.
omgold commented 5 years ago
Poster

@lichtwerk Yes, of course. Sorry in case I failed to follow the preferred procedures. No secret that I'm rather new around here.

In any case, I looked further into the matter, and as psys_calc_dmcache() is just setting num_dmcache = DMCACHE_ISCHILD in the case of 'use modifier stack', I did this also, and voila stuff seems to work. Apparently the marker DMCACHE_ISCHILD is abused to handle the case of modifier stacks also. In case this reasoning is right, and you want to try, here is the fix:

0d6a3aaf87

I'm still trying to understand the wrong placement of hair after disconnect with subsurf and 'use modifier stack' disabled. I will let you know, if I can figure out more.

@lichtwerk Yes, of course. Sorry in case I failed to follow the preferred procedures. No secret that I'm rather new around here. In any case, I looked further into the matter, and as psys_calc_dmcache() is just setting num_dmcache = DMCACHE_ISCHILD in the case of 'use modifier stack', I did this also, and voila stuff seems to work. Apparently the marker DMCACHE_ISCHILD is abused to handle the case of modifier stacks also. In case this reasoning is right, and you want to try, here is the fix: https://github.com/omgold/blender/commit/0d6a3aaf877c58d2eac385bee1af618fbef65fed I'm still trying to understand the wrong placement of hair after disconnect with subsurf and 'use modifier stack' disabled. I will let you know, if I can figure out more.
omgold commented 5 years ago
Poster

About the situation with subsurf and no 'use modfiier stack', not it is clearer to me. The reconnect in this case seems to work like this:

  • Find face and point on mesh closest to location of hair root. For this the location of the hair root is taken after modifiers, while the mesh is taken before modifiers.
  • Offset between this closest point and old location of hair root is computed.
  • This offset is added to locations of all hair keys.

I guess the best way to solve this, would be to use the final mesh (after modifiers) in the first step. The problem that appears there, though, is that the index of the face the hair is attached to has to be giving on the original mesh. I couldn't find a method available to do that, so I didn't come up with a patch (yet). Basically what would be needed is the inverse of psys_particle_dm_face_lookup().

About the situation with subsurf and no 'use modfiier stack', not it is clearer to me. The reconnect in this case seems to work like this: - Find face and point on mesh closest to location of hair root. For this the location of the hair root is taken after modifiers, while the mesh is taken before modifiers. - Offset between this closest point and old location of hair root is computed. - This offset is added to locations of all hair keys. I guess the best way to solve this, would be to use the final mesh (after modifiers) in the first step. The problem that appears there, though, is that the index of the face the hair is attached to has to be giving on the original mesh. I couldn't find a method available to do that, so I didn't come up with a patch (yet). Basically what would be needed is the inverse of psys_particle_dm_face_lookup().
Collaborator

Added subscribers: @MarekHolly, @grosgood

Added subscribers: @MarekHolly, @grosgood
mano-wii changed title from Mirror modifier and hair disconnect/reconnect not working together to hair disconnect/reconnect not working with modifiers 3 years ago
Collaborator

Added subscriber: @JacquesLucke

Added subscriber: @JacquesLucke
Collaborator

It seems unlikely that someone will work on this before the new hair type is usable. Therefore, I'll reclassify this as known issue.

It seems unlikely that someone will work on this before the new hair type is usable. Therefore, I'll reclassify this as known issue.
Collaborator

This issue was referenced by a4171f4866

This issue was referenced by a4171f48661b87b4a2e4ca66f1156c863261d759
Collaborator

This issue was referenced by db9ddb8a45

This issue was referenced by db9ddb8a453f88321d0b43609f532bc2c729fbcc
Collaborator

This issue was referenced by 5dedb39d44

This issue was referenced by 5dedb39d447bcb51ad0d797aae765667edf5321c
brecht commented 1 year ago
Owner

Changed status from 'Confirmed' to: 'Resolved'

Changed status from 'Confirmed' to: 'Resolved'
brecht closed this issue 1 year ago
brecht self-assigned this 1 year ago
Sign in to join this conversation.
No Label
Interest/Alembic
Interest/Animation & Rigging
Interest/Asset Browser
Interest/Asset Browser Project Overview
Interest/Audio
Interest/Automated Testing
Interest/Blender Asset Bundle
Interest/Collada
Interest/Compositing
Interest/Core
Interest/Cycles
Interest/Dependency Graph
Interest/Development Management
Interest/Eevee & Viewport
Interest/Freestyle
Interest/Geometry Nodes
Interest/Grease Pencil
Interest/ID Management
Interest/Images & Movies
Interest/Import/Export
Interest/Line Art
Interest/Masking
Interest/Modeling
Interest/Modifiers
Interest/Motion Tracking
Interest/Nodes & Physics
Interest/Overrides
Interest/Performance
Interest/Performance
Interest/Physics
Interest/Pipeline, Assets & I/O
Interest/Platforms, Builds, Tests & Devices
Interest/Python API
Interest/Render & Cycles
Interest/Render Pipeline
Interest/Sculpt, Paint & Texture
Interest/Text Editor
Interest/Translations
Interest/Triaging
Interest/Undo
Interest/USD
Interest/User Interface
Interest/UV Editing
Interest/VFX & Video
Interest/Video Sequencer
Interest/Virtual Reality
legacy module/Animation & Rigging
legacy module/Core
legacy module/Development Management
legacy module/Eevee & Viewport
legacy module/Grease Pencil
legacy module/Modeling
legacy module/Nodes & Physics
legacy module/Pipeline, Assets & IO
legacy module/Platforms, Builds, Tests & Devices
legacy module/Python API
legacy module/Rendering & Cycles
legacy module/Sculpt, Paint & Texture
legacy module/Triaging
legacy module/User Interface
legacy module/VFX & Video
legacy project/1.0.0-beta.2
legacy project/Asset Browser (Archived)
legacy project/BF Blender: 2.8
legacy project/BF Blender: After Release
legacy project/BF Blender: Next
legacy project/BF Blender: Regressions
legacy project/BF Blender: Unconfirmed
legacy project/Blender 2.70
legacy project/Code Quest
legacy project/Datablocks and Libraries
legacy project/Eevee
legacy project/Game Animation
legacy project/Game Audio
legacy project/Game Data Conversion
legacy project/Game Engine
legacy project/Game Logic
legacy project/Game Physics
legacy project/Game Python
legacy project/Game Rendering
legacy project/Game UI
legacy project/GPU / Viewport
legacy project/GSoC
legacy project/Infrastructure: Websites
legacy project/LibOverrides - Usability and UX
legacy project/Milestone 1: Basic, Local Asset Browser
legacy project/Nodes
legacy project/OpenGL Error
legacy project/Papercut
legacy project/Pose Library Basics
legacy project/Retrospective
legacy project/Tracker Curfew
legacy project/Wintab High Frequency
Meta/Good First Issue
Meta/Papercut
migration/requires-manual-verification
Module › Animation & Rigging
Module › Core
Module › Development Management
Module › Eevee & Viewport
Module › Grease Pencil
Module › Modeling
Module › Nodes & Physics
Module › Pipeline, Assets & IO
Module › Platforms, Builds, Tests & Devices
Module › Python API
Module › Render & Cycles
Module › Sculpt, Paint & Texture
Module › Triaging
Module › User Interface
Module › VFX & Video
Platform/FreeBSD
Platform/Linux
Platform/macOS
Platform/Windows
Priority › High
Priority › Low
Priority › Normal
Priority › Unbreak Now!
Status › Archived
Status › Confirmed
Status › Duplicate
Status › Needs Information from Developers
Status › Needs Information from User
Status › Needs Triage
Status › Resolved
Type › Bug
Type › Design
Type › Known Issue
Type › Patch
Type › Report
Type › To Do
No Milestone
No project
No Assignees
6 Participants
Notifications
Due Date

No due date set.

Dependencies

No dependencies set.

Reference: blender/blender#54488
Loading…
There is no content yet.