Refactoring: Geometry Nodes: Rewrite Ico Sphere mesh primitive #116729
No reviewers
Labels
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
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
Overlay
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
Interest
Workbench
Interest: X11
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
No Milestone
No project
No Assignees
5 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: blender/blender#116729
Loading…
Reference in New Issue
No description provided.
Delete Branch "mod_moder/blender:ico_sphere"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Abstract
This refactoring is part of implicit project of removing BMesh from Geometry Nodes.
Other such commits:
e83f46ea76
,b44406f963
, #112264.Main goal is to avoid overhead for all listed case:
This Pull Request change
Ico Sphere
mesh primitive node to make result mesh from scratch in simple way.This refactoring totaly delete old BMesh version from this file. New version is achieved impressive speed and
memory usage impact by generation mesh as single-time allocation final buffers of topology data and applying index math.
Everything works with linear complexity which is depends on amount of final mesh components (vertices, edges, faces, corners).
Now generation of Ico Sphere can be done much faster for final user in largers resolution, 100x~.
Benchmark
Bellow listed timings to compare old and new implementations (ms):
UV is optional function and its impact is measured separately.
Previously Ico Sphere resolution was limited by 10 internally. New mesh version is limited by 12 (due to not enough memory to hold result). BMesh results for 11 resolution is not checked due to not enough memory.
Not so many threads is used there, main limitation there is memory bandwidth.
New algorithm produce result Mesh in single pass, and resolution is not limited by power of 2. Right now resolution is still
treated as power of 2, but now this not real limitation and this can be changed in future.
New algorithm produce mesh looks the same as older. The same positions of vertices, topology and uv map. Internal indices
is different though, so this might cause changed result for node tree setups which is depend on indices of mesh primitive.
Writing of all data is sequential (not randomly distributed segments).
Multithreading might introduce some randomization, but that is not matter on such level.
Possible improvements for future:
mix2
and improve CPU cach (here is one func just to interpolate 6 floats in one array by chunks...).3.1. Implicit sharing for all data of result ico sphere with one weak user?
memory_bandwidth_bound_task
for each face.Hello if I may, you use #include while the new c++ standard uses import std;
So I think you should use import std;
Next few years blender going to keep on Cpp17 standart (due to vfx platform).
ok sorry I thought it was interesting to stick to the latest standard it's for this.
I know this is just WIP, but I was interested to see how you constructed the icosphere.
I think the comments shouldn't be too difficult to implement
@ -118,0 +256,4 @@
positions.last() = float3(0.0f, 0.0f, -1.0f);
for (float3 &position : positions) {
position *= radius;
I would suggest only scaling by the radius after all the points (also the subdivided) have been calculated. This way you avoid having to do expensive normalisations later.
You could then also do it in a parallel_for loop.
@ -118,0 +369,4 @@
const float3 normalized_b = math::normalize(point_b);
const float3 normal = math::normalize(
math::cross_tri(float3(0.0f), normalized_a, normalized_b));
If
a
andb
are normalized, then the cross product is automatically normalized.As I mentioned in the other comment, we don't need even need to normalize
a
andb
if we don't scale by the radius at the start!@ -118,0 +376,4 @@
for (float3 &vert : verts) {
steps += rotation * lerp_factor;
const math::AxisAngle axis(normal, steps);
vert = math::transform_point(math::to_quaternion(axis), point_a);
I think it is possible to speed this up a little bit:
edge_verts_num
points betweena
andb
. (let's call them $v_1, v_2, \dots$)v_k
, we can calculatev_{k+1}
using a reflection:v_{k+1} = \text{Refl}_{v_k}(v_{k-1}) = 2 \;\text{dot}(v_k, v_{k-1}) v_{k} - v_{k+1}
. This is faster than calculating a rotation. Also, since the points are evenly spaced, the dot product is always the same (so you only need to calculate it once).v_1
(since $v_0 = a$). This can be done as you did, or using theslerp
formula:v_1 = a \frac{\sin((1- t) \alpha)}{\sin (\alpha )} + b \frac{\sin(t \alpha)}{\sin(\alpha)}
where\alpha
is the angle betweena
andb
. I think this formula might be faster than calculating the normal and using the axis angle rotations.See: https://en.wikipedia.org/wiki/Slerp for more information.
Didn't think about reflection as way to rotate points! Right now this function take half of time of whole node (except normals calculation). So i am very intereasting to check this approath. Initially i thought that scaling might be much more expensive (and i was believe there is way to faster rotate along normal), but i can see that this would be much better to add separate transformation step later.
Thanks for check this!
Here is my idea for calculating normals:
I mean, order of points/edges in face corner. Right now this order is random, and i have to calculate real normal (based on this order) for each face, and flip this face in case normal does not directed into required side. Probably possible to change algorithms instead (to keep correct corner order for each faces), but this is not important right now. So i just treet timings of normal fixing as separate part of node measurement.
Originl: Timer 'interpolate_face_points': (Average: 57.03 ms, Min: 55.49 ms, Last: 55.49 ms)
SphericalIterator
only for face points: Timer 'interpolate_face_points': (Average: 18.46 ms, Min: 16.43 ms, Last: 17.15 ms)SphericalIterator
for virtual points on edges, and actually face points: Timer 'interpolate_face_points': (Average: 17.44 ms, Min: 15.55 ms, Last: 17.53 ms)Timer 'Scaling': (Average: 5.04 ms, Min: 4.72 ms, Last: 5.03 ms)
Edit: for 10 level of subdivision.
In the end i found the fact that spherical interpolation is was not the way how icosphere was made. For now i use just
normalize(lerp())
to keep old result. I'll also have to check if this will be fast enough in context of low precision of such method. So some modifications also required. Thanks again for this investigation, i'll back to this later.@ -11,0 +25,4 @@
#include "BLI_ordered_edge.hh"
#include "BLI_span.hh"
#include "BLI_timeit.hh"
This, some commented
SCOPED_TIMER_AVERAGED
, some other commented things and also BMesh code will be keep here while viewe to simplify checking. But can be deleted on ping.WIP: Refactoring: Geometry Nodes: Rewrite Ico Sphere mesh primitiveto Refactoring: Geometry Nodes: Rewrite Ico Sphere mesh primitiveIs this 100% compatible with the previous implementation or e.g. index ordering changed, UV positioning changed?
Only indices is changed.
Checkout
From your project repository, check out a new branch and test the changes.