How to attach hair to a surface #95776
Closed
opened 2022-02-14 14:32:35 +01:00 by Jacques Lucke
·
26 comments
No Branch/Tag Specified
main
universal-scene-description
temp-sculpt-dyntopo
blender-v3.3-release
blender-v3.6-release
asset-browser-frontend-split
brush-assets-project
asset-shelf
anim/armature-drawing-refactor-3
temp-sculpt-dyntopo-hive-alloc
tmp-usd-python-mtl
tmp-usd-3.6
blender-v3.5-release
blender-projects-basics
blender-v2.93-release
temp-sculpt-attr-api
realtime-clock
sculpt-dev
gpencil-next
bevelv2
microfacet_hair
xr-dev
principled-v2
v3.6.3
v3.3.11
v3.6.2
v3.3.10
v3.6.1
v3.3.9
v3.6.0
v3.3.8
v3.3.7
v2.93.18
v3.5.1
v3.3.6
v2.93.17
v3.5.0
v2.93.16
v3.3.5
v3.3.4
v2.93.15
v2.93.14
v3.3.3
v2.93.13
v2.93.12
v3.4.1
v3.3.2
v3.4.0
v3.3.1
v2.93.11
v3.3.0
v3.2.2
v2.93.10
v3.2.1
v3.2.0
v2.83.20
v2.93.9
v3.1.2
v3.1.1
v3.1.0
v2.83.19
v2.93.8
v3.0.1
v2.93.7
v3.0.0
v2.93.6
v2.93.5
v2.83.18
v2.93.4
v2.93.3
v2.83.17
v2.93.2
v2.93.1
v2.83.16
v2.93.0
v2.83.15
v2.83.14
v2.83.13
v2.92.0
v2.83.12
v2.91.2
v2.83.10
v2.91.0
v2.83.9
v2.83.8
v2.83.7
v2.90.1
v2.83.6.1
v2.83.6
v2.90.0
v2.83.5
v2.83.4
v2.83.3
v2.83.2
v2.83.1
v2.83
v2.82a
v2.82
v2.81a
v2.81
v2.80
v2.80-rc3
v2.80-rc2
v2.80-rc1
v2.79b
v2.79a
v2.79
v2.79-rc2
v2.79-rc1
v2.78c
v2.78b
v2.78a
v2.78
v2.78-rc2
v2.78-rc1
v2.77a
v2.77
v2.77-rc2
v2.77-rc1
v2.76b
v2.76a
v2.76
v2.76-rc3
v2.76-rc2
v2.76-rc1
v2.75a
v2.75
v2.75-rc2
v2.75-rc1
v2.74
v2.74-rc4
v2.74-rc3
v2.74-rc2
v2.74-rc1
v2.73a
v2.73
v2.73-rc1
v2.72b
2.72b
v2.72a
v2.72
v2.72-rc1
v2.71
v2.71-rc2
v2.71-rc1
v2.70a
v2.70
v2.70-rc2
v2.70-rc
v2.69
v2.68a
v2.68
v2.67b
v2.67a
v2.67
v2.66a
v2.66
v2.65a
v2.65
v2.64a
v2.64
v2.63a
v2.63
v2.61
v2.60a
v2.60
v2.59
v2.58a
v2.58
v2.57b
v2.57a
v2.57
v2.56a
v2.56
v2.55
v2.54
v2.53
v2.52
v2.51
v2.50
v2.49b
v2.49a
v2.49
v2.48a
v2.48
v2.47
v2.46
v2.45
v2.44
v2.43
v2.42a
v2.42
v2.41
v2.40
v2.37a
v2.37
v2.36
v2.35a
v2.35
v2.34
v2.33a
v2.33
v2.32
v2.31a
v2.31
v2.30
v2.28c
v2.28a
v2.28
v2.27
v2.26
v2.25
Labels
Clear labels
This issue affects/is about backward or forward compatibility
Issues relating to security: https://wiki.blender.org/wiki/Process/Vulnerability_Reports
Apply labels
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset Browser
Interest
Asset Browser Project Overview
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Collada
Interest
Compatibility
This issue affects/is about backward or forward compatibility
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
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
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
Interest
Vulkan
Interest: Wayland
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Issues relating to security: https://wiki.blender.org/wiki/Process/Vulnerability_Reports
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
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 Info 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 Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset Browser
Interest
Asset Browser Project Overview
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Collada
Interest
Compatibility
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
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
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
Interest
Vulkan
Interest: Wayland
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
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
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 Info 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
Milestone
Set milestone
Clear milestone
No items
No Milestone
Projects
Set Project
Clear projects
No project
Assignees
Assign users
Clear assignees
No Assignees
9 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.
No due date set.
Dependencies
No dependencies set.
Reference: blender/blender#95776
Reference in New Issue
There is no content yet.
Delete Branch "%!s(<nil>)"
Deleting a branch is permanent. Although the deleted branch may exist for a short time before cleaning up, in most cases it CANNOT be undone. Continue?
@brecht and I (@JacquesLucke) talked about this. We agreed to move forward with the following approach.
MLoopTri
index: Index of the triangle that the root hair point is attached to.position
attribute are in the local space of the object (instead of some relative coordinates based on the scalp).Curves
: Undeformed hair curves.Deformed Base Mesh
: The animated or simulated base mesh. The topology must match the topology of the scalp mesh.Rest Position
: A vector field input that determines the original position of each vertex of the defomed base mesh. Usually, this just references a named attribute likerest_position
/original_position
. This attribute has to be set on the scalp.Added subscriber: @JacquesLucke
Added subscriber: @Diogo_Valadares
Added subscriber: @brecht
Added subscriber: @lichtwerk
Changed status from 'Needs Triage' to: 'Confirmed'
Note sure if some of this is planned for another task, but will write down a few additional things from our discussion before I forget.
Rest position:
rest_position
attribute is set.Deform:
Sudivision Surfaces:
Added subscriber: @GeorgiaPacific
Added subscriber: @HooglyBoogly
One question-- Would the pointer to the mesh object have any effect during evaluation of geometry nodes, or would it just be used for interactive editing and to setup information at the start of evaluation. It seems like the consensus is the latter?
Deformation
I think it would be best to allow building the deform node with smaller nodes. Otherwise I think we're limiting the flexibility of future node-based tooling for deformation.For example, we should keep the "Set Position" node as the way to change position. I expect built-in / asset bundle node groups to be very important in this whole project, so curves deformation can be handled that way too.
Naming
Original Coordinates
This also sounds like a great improvement, I've wondered about that before. I created a task for that here: #95940
If there's more information that might be helpful for a refactor, it would be nice to add it there. I think we can refactor
to a more generic named "rest position" attribute with steps like this.
Attachment Data
I don't think my thoughts are that useful here, but one thing I'm seeing is that there seem to be many mapping methods,
each with pros and cons. So it's probably important to allow flexibility here.
This issue was referenced by
6e11cfc56a
Found an issue in our assumptions about
MLoopTri
. Brecht and I assumed thatMLoopTri
is when vertices are only moved around and not topology changes are done. This turned out to be wrong unfortunately.mesh_recalc_looptri__single_threaded
actually takes the normals as inputs.looptri_inconsistent_test.blend
We have to investigate new alternatives for how to store the attachment. Some initial ideas:
For animated meshes, a changing triangulation is problematic even without hair. In the attached the .blend, we can see how moving a vertex causes a flickering triangulation. That's going to look bad without hair, and with hair there would be sudden change in normal.
Triangulation could be based on undeformed coordinates for, I vaguely remember we added that in Blender Internal. Making meshes always do that can have a real performance cost though, for example in viewport playback of an armature deformed character with subdivision surfaces. In principle the triangulation of animated meshes can be cached from frame to frame, but the practical implementation of that doesn't seem simple. The ideal solution at that general mesh evaluation level is not obvious to me, but may be worth considering. If not feasible, hair attachment could potentially use its own triangulation based on undeformed coordinates, when there are any.
Maybe it's prohibitively complicated or expensive, but I think a solution that uses a poly index instead of a triangle index would have some real benefits.
Mainly we have no plan or design to expose a mesh's triangulation to geometry nodes. That severely limits our flexibility when dealing with this attachment information in a generic context.
I think that's an area where the current design is lacking. Maybe there's another way to solve that, but maybe one simpler approach is just to use polygon indices instead.
We could optimize the polygon attachment method for quads/triangles, and as long as N-gons don't fail terribly, I think it could be an improvement.
I build another simple test case that shows the issue with geometry nodes. Just change the Scale input in the modifier and see the flickering triangulation.
deformation_changes_triangulation.blend
A possible generic solution would be to store a
char *triangulation_position_attribute
onMesh
. It defaults toposition
which is the current behavior, but it could also be set to e.g.rest_position
which can be stored before deformation.BKE_mesh_recalc_looptri
would then use this attribute instead of always usingMVert.co
.A potential problem with this solution is that merging two meshes can break this information if both meshes use a different
triangulation_position_attribute
. A built-in attribute or a good attribute naming convention might help here.Solving this is not really in scope for the hair project right now, although I wouldn't mind looking into it later.
Regarding surface attachment, it seems like a good idea to base the attachment information on a uv map. This has more advantages than I first anticipated.
Specifically, I propose the following approach:
surface_uv_map
attribute name on theCurves
data block, next to thesurface
object pointer.surface_uv
:float2
attribute containing the uv coordinate of the position where the curve is attached to the surface.surface_rest_position
:float3
attribute that is usually equal to the position of the first control, but doesn't have to be.surface_rest_orientation
:Quaternion
attribute (doesn't exist yet) that combines the normal and tangent at the rest position on the surface.Compared to the old approach, this has some disadvantages:
sizeof(int) + sizeof(float2) = 4 + 8 = 12 bytes
of storage for the surface attachment per curve.sizeof(float2) + sizeof(float3) + sizeof(Quaternion) = 8 + 12 + 16 = 36 bytes
per curve.Quaternion
could potentially be stored in 3 floats, because it's normalized, but that memory optimization might not be worth the additional complexity and run-time overhead.There are also some advantages which seem more significant than the disadvantages to me:
MLoopTri
).I like the approach described in @JacquesLucke's comment. Particularly that it uses existing concepts that users are already familiar with and are useful more generally.
The rotation and position attributes on the curves seem conceptually a bit different than the UV, since they can always be computed when the UV and the surface mesh are available.
It's nice that the quality of the UV map doesn't matter, it means the downside of requiring a UV map doesn't carry much weight.
Using UVs to attatch hair is a pretty clever idea, and pretty simple to comprehend, and even if someone wants to make an UV that overlaps(for symmetric painting for example) or wants to change the UV after attathing hair, they can use an extra UV just for the hair if they want.
Also, it sounds much simpler to transfer hair from one surface to another if needed using this concept.
I can see the reasoning behind using UVs. It is requiring some manual work and understanding from users that would otherwise be automatic, but they gain hair preservation when editing meshes.
UVs can work with or without
surface_rest_position
andsurface_rest_orientation
attributes. I'm not sure if using those instead of arest_position
attribute on the surface is better.rest_position
every frame, and effectively caching it in per-curve attributes. But then such rest position and UV should not have to be re-interpolated, optimizations in subdivision could avoid that.I imagined it so that you couldn't use the
Curves > Empty Hair
operator if the surface object doesn't have a uv map already (with a proper disabled hint). Auto-generating them when entering a mode is possible, but not sure if that should be preferred.Right, there could be warnings for these cases.
Hmm, good point. I'd hope that keeping boundaries would be good enough, but that has to be tested. Worst case seems to be that we have to extend the subdivision surface node to interpolate different uv maps using different modes.
If no deformation is done, the
surface_*
attributes aren't strictly necessary and can also be removed. They could help when transferring data from the ground to e.g. grass though. We do want to support generating uv maps in geometry nodes. Simple non-optimized uv maps should be relative cheap to generate, I think. More complex layouts not so much of course..Yeah, that applies to all of geometry nodes really. If we notice that this becomes a real bottleneck in production, I'd fine with adding a local caching solution until there is more generic solution.
Hm right, could work either way.
That's right. That can either be an explicit operator call (exists already for the old attachment info), or it can be more automatic as tooling of the edit modes.
Yes, probably shouldn't be an implementation detail though. Not sure if we can reliably invalidate this cache in a generic geometry nodes setup.
I'm all for optimizations, but I think we have to be careful here with not making user-visible changes to what data is processed by a modifier/node based on how the data is used further down the line. That just doesn't scale well with more complex node setups. Providing a good and efficient default for what data is processed where makes sense though.
Started writing some notes about the different arguments for using
rest_position
on the surface vs. usingsurface_rest_position
andsurface_rest_orientation
on curves: https://hackmd.io/@II9-Bkl4TJifCqGL2jgbUw/BkZ-b7Bv9Based on the different arguments mentioned in https://hackmd.io/@II9-Bkl4TJifCqGL2jgbUw/BkZ-b7Bv9, I come to the conclusion that we should use a
rest_position
attribute on the surface.Working with
surface_rest_position
andsurface_rest_orientation
attributes on curves has some benefits in some use-cases and could be added later if there is need for it.The decisive argument for me was that consistent surface tangents for the deformation are much easier to achieve this way. Without consistent tangents, we can easily get hair that rotates around the surface normal, without clear ways on how to fix it.
Sounds reasonable to me. Another reason for
rest_position
that I did not see mentioned is that you need it to support a hair add brush on deformed characters in sculpt mode.Added subscriber: @Gareth-Jensen-1
This issue was referenced by
05b38ecc78
Added subscriber: @Cigitia
Changed status from 'Confirmed' to: 'Resolved'
Documented in the wiki now: https://wiki.blender.org/wiki/Source/Objects/Curves#Attachment_.26_Deformation