2023-05-31 16:19:06 +02:00
|
|
|
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
2014-01-21 12:11:34 +01:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup bke
|
2014-01-21 12:11:34 +01:00
|
|
|
*/
|
|
|
|
|
|
2021-04-01 15:54:48 -05:00
|
|
|
#include <climits>
|
|
|
|
|
#include <cstddef>
|
|
|
|
|
#include <cstdlib>
|
2014-01-21 12:11:34 +01:00
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
|
|
#include "BLI_listbase.h"
|
Cleanup: reduce amount of math-related includes
Using ClangBuildAnalyzer on the whole Blender build, it was pointing
out that BLI_math.h is the heaviest "header hub" (i.e. non tiny file
that is included a lot).
However, there's very little (actually zero) source files in Blender
that need "all the math" (base, colors, vectors, matrices,
quaternions, intersection, interpolation, statistics, solvers and
time). A common use case is source files needing just vectors, or
just vectors & matrices, or just colors etc. Actually, 181 files
were including the whole math thing without needing it at all.
This change removes BLI_math.h completely, and instead in all the
places that need it, includes BLI_math_vector.h or BLI_math_color.h
and so on.
Change from that:
- BLI_math_color.h was included 1399 times -> now 408 (took 114.0sec
to parse -> now 36.3sec)
- BLI_simd.h 1403 -> 418 (109.7sec -> 34.9sec).
Full rebuild of Blender (Apple M1, Xcode, RelWithDebInfo) is not
affected much (342sec -> 334sec). Most of benefit would be when
someone's changing BLI_simd.h or BLI_math_color.h or similar files,
that now there's 3x fewer files result in a recompile.
Pull Request #110944
2023-08-09 11:39:20 +03:00
|
|
|
#include "BLI_math_vector.h"
|
2014-01-21 12:11:34 +01:00
|
|
|
#include "BLI_string_utf8.h"
|
|
|
|
|
|
2021-04-12 16:24:51 -05:00
|
|
|
#include "BLI_array.hh"
|
2024-02-19 15:54:48 +01:00
|
|
|
#include "BLI_math_color.hh"
|
Cleanup: reduce amount of math-related includes
Using ClangBuildAnalyzer on the whole Blender build, it was pointing
out that BLI_math.h is the heaviest "header hub" (i.e. non tiny file
that is included a lot).
However, there's very little (actually zero) source files in Blender
that need "all the math" (base, colors, vectors, matrices,
quaternions, intersection, interpolation, statistics, solvers and
time). A common use case is source files needing just vectors, or
just vectors & matrices, or just colors etc. Actually, 181 files
were including the whole math thing without needing it at all.
This change removes BLI_math.h completely, and instead in all the
places that need it, includes BLI_math_vector.h or BLI_math_color.h
and so on.
Change from that:
- BLI_math_color.h was included 1399 times -> now 408 (took 114.0sec
to parse -> now 36.3sec)
- BLI_simd.h 1403 -> 418 (109.7sec -> 34.9sec).
Full rebuild of Blender (Apple M1, Xcode, RelWithDebInfo) is not
affected much (342sec -> 334sec). Most of benefit would be when
someone's changing BLI_simd.h or BLI_math_color.h or similar files,
that now there's 3x fewer files result in a recompile.
Pull Request #110944
2023-08-09 11:39:20 +03:00
|
|
|
#include "BLI_math_geom.h"
|
|
|
|
|
#include "BLI_math_matrix.h"
|
2024-02-19 15:54:48 +01:00
|
|
|
#include "BLI_math_matrix.hh"
|
Cleanup: reduce amount of math-related includes
Using ClangBuildAnalyzer on the whole Blender build, it was pointing
out that BLI_math.h is the heaviest "header hub" (i.e. non tiny file
that is included a lot).
However, there's very little (actually zero) source files in Blender
that need "all the math" (base, colors, vectors, matrices,
quaternions, intersection, interpolation, statistics, solvers and
time). A common use case is source files needing just vectors, or
just vectors & matrices, or just colors etc. Actually, 181 files
were including the whole math thing without needing it at all.
This change removes BLI_math.h completely, and instead in all the
places that need it, includes BLI_math_vector.h or BLI_math_color.h
and so on.
Change from that:
- BLI_math_color.h was included 1399 times -> now 408 (took 114.0sec
to parse -> now 36.3sec)
- BLI_simd.h 1403 -> 418 (109.7sec -> 34.9sec).
Full rebuild of Blender (Apple M1, Xcode, RelWithDebInfo) is not
affected much (342sec -> 334sec). Most of benefit would be when
someone's changing BLI_simd.h or BLI_math_color.h or similar files,
that now there's 3x fewer files result in a recompile.
Pull Request #110944
2023-08-09 11:39:20 +03:00
|
|
|
#include "BLI_math_rotation.h"
|
2023-02-06 21:25:45 +01:00
|
|
|
#include "BLI_math_vector.hh"
|
2014-01-21 12:11:34 +01:00
|
|
|
#include "BLI_rand.h"
|
2021-04-01 16:23:16 -05:00
|
|
|
#include "BLI_span.hh"
|
2021-04-27 12:33:40 +02:00
|
|
|
#include "BLI_vector.hh"
|
2014-01-21 12:11:34 +01:00
|
|
|
|
2024-02-19 15:54:48 +01:00
|
|
|
#include "DNA_anim_types.h"
|
2018-08-29 15:32:50 +02:00
|
|
|
#include "DNA_collection_types.h"
|
Geometry Nodes: viewport preview
This adds support for showing geometry passed to the Viewer in the 3d
viewport (instead of just in the spreadsheet). The "viewer geometry"
bypasses the group output. So it is not necessary to change the final
output of the node group to be able to see the intermediate geometry.
**Activation and deactivation of a viewer node**
* A viewer node is activated by clicking on it.
* Ctrl+shift+click on any node/socket connects it to the viewer and
makes it active.
* Ctrl+shift+click in empty space deactivates the active viewer.
* When the active viewer is not visible anymore (e.g. another object
is selected, or the current node group is exit), it is deactivated.
* Clicking on the icon in the header of the Viewer node toggles whether
its active or not.
**Pinning**
* The spreadsheet still allows pinning the active viewer as before.
When pinned, the spreadsheet still references the viewer node even
when it becomes inactive.
* The viewport does not support pinning at the moment. It always shows
the active viewer.
**Attribute**
* When a field is linked to the second input of the viewer node it is
displayed as an overlay in the viewport.
* When possible the correct domain for the attribute is determined
automatically. This does not work in all cases. It falls back to the
face corner domain on meshes and the point domain on curves. When
necessary, the domain can be picked manually.
* The spreadsheet now only shows the "Viewer" column for the domain
that is selected in the Viewer node.
* Instance attributes are visualized as a constant color per instance.
**Viewport Options**
* The attribute overlay opacity can be controlled with the "Viewer Node"
setting in the overlays popover.
* A viewport can be configured not to show intermediate viewer-geometry
by disabling the "Viewer Node" option in the "View" menu.
**Implementation Details**
* The "spreadsheet context path" was generalized to a "viewer path" that
is used in more places now.
* The viewer node itself determines the attribute domain, evaluates the
field and stores the result in a `.viewer` attribute.
* A new "viewer attribute' overlay displays the data from the `.viewer`
attribute.
* The ground truth for the active viewer node is stored in the workspace
now. Node editors, spreadsheets and viewports retrieve the active
viewer from there unless they are pinned.
* The depsgraph object iterator has a new "viewer path" setting. When set,
the viewed geometry of the corresponding object is part of the iterator
instead of the final evaluated geometry.
* To support the instance attribute overlay `DupliObject` was extended
to contain the information necessary for drawing the overlay.
* The ctrl+shift+click operator has been refactored so that it can make
existing links to viewers active again.
* The auto-domain-detection in the Viewer node works by checking the
"preferred domain" for every field input. If there is not exactly one
preferred domain, the fallback is used.
Known limitations:
* Loose edges of meshes don't have the attribute overlay. This could be
added separately if necessary.
* Some attributes are hard to visualize as a color directly. For example,
the values might have to be normalized or some should be drawn as arrays.
For now, we encourage users to build node groups that generate appropriate
viewer-geometry. We might include some of that functionality in future versions.
Support for displaying attribute values as text in the viewport is planned as well.
* There seems to be an issue with the attribute overlay for pointclouds on
nvidia gpus, to be investigated.
Differential Revision: https://developer.blender.org/D15954
2022-09-28 17:54:59 +02:00
|
|
|
#include "DNA_curves_types.h"
|
2023-10-10 16:49:30 +02:00
|
|
|
#include "DNA_grease_pencil_types.h"
|
2014-01-21 12:11:34 +01:00
|
|
|
#include "DNA_mesh_types.h"
|
2024-02-19 15:54:48 +01:00
|
|
|
#include "DNA_meshdata_types.h"
|
Geometry Nodes: viewport preview
This adds support for showing geometry passed to the Viewer in the 3d
viewport (instead of just in the spreadsheet). The "viewer geometry"
bypasses the group output. So it is not necessary to change the final
output of the node group to be able to see the intermediate geometry.
**Activation and deactivation of a viewer node**
* A viewer node is activated by clicking on it.
* Ctrl+shift+click on any node/socket connects it to the viewer and
makes it active.
* Ctrl+shift+click in empty space deactivates the active viewer.
* When the active viewer is not visible anymore (e.g. another object
is selected, or the current node group is exit), it is deactivated.
* Clicking on the icon in the header of the Viewer node toggles whether
its active or not.
**Pinning**
* The spreadsheet still allows pinning the active viewer as before.
When pinned, the spreadsheet still references the viewer node even
when it becomes inactive.
* The viewport does not support pinning at the moment. It always shows
the active viewer.
**Attribute**
* When a field is linked to the second input of the viewer node it is
displayed as an overlay in the viewport.
* When possible the correct domain for the attribute is determined
automatically. This does not work in all cases. It falls back to the
face corner domain on meshes and the point domain on curves. When
necessary, the domain can be picked manually.
* The spreadsheet now only shows the "Viewer" column for the domain
that is selected in the Viewer node.
* Instance attributes are visualized as a constant color per instance.
**Viewport Options**
* The attribute overlay opacity can be controlled with the "Viewer Node"
setting in the overlays popover.
* A viewport can be configured not to show intermediate viewer-geometry
by disabling the "Viewer Node" option in the "View" menu.
**Implementation Details**
* The "spreadsheet context path" was generalized to a "viewer path" that
is used in more places now.
* The viewer node itself determines the attribute domain, evaluates the
field and stores the result in a `.viewer` attribute.
* A new "viewer attribute' overlay displays the data from the `.viewer`
attribute.
* The ground truth for the active viewer node is stored in the workspace
now. Node editors, spreadsheets and viewports retrieve the active
viewer from there unless they are pinned.
* The depsgraph object iterator has a new "viewer path" setting. When set,
the viewed geometry of the corresponding object is part of the iterator
instead of the final evaluated geometry.
* To support the instance attribute overlay `DupliObject` was extended
to contain the information necessary for drawing the overlay.
* The ctrl+shift+click operator has been refactored so that it can make
existing links to viewers active again.
* The auto-domain-detection in the Viewer node works by checking the
"preferred domain" for every field input. If there is not exactly one
preferred domain, the fallback is used.
Known limitations:
* Loose edges of meshes don't have the attribute overlay. This could be
added separately if necessary.
* Some attributes are hard to visualize as a color directly. For example,
the values might have to be normalized or some should be drawn as arrays.
For now, we encourage users to build node groups that generate appropriate
viewer-geometry. We might include some of that functionality in future versions.
Support for displaying attribute values as text in the viewport is planned as well.
* There seems to be an issue with the attribute overlay for pointclouds on
nvidia gpus, to be investigated.
Differential Revision: https://developer.blender.org/D15954
2022-09-28 17:54:59 +02:00
|
|
|
#include "DNA_modifier_types.h"
|
2020-08-04 11:35:44 +02:00
|
|
|
#include "DNA_pointcloud_types.h"
|
2014-01-21 12:11:34 +01:00
|
|
|
#include "DNA_scene_types.h"
|
2024-02-19 15:54:48 +01:00
|
|
|
#include "DNA_vfont_types.h"
|
2022-08-09 14:44:47 -05:00
|
|
|
#include "DNA_volume_types.h"
|
2014-01-21 12:11:34 +01:00
|
|
|
|
2024-02-19 15:54:48 +01:00
|
|
|
#include "BKE_collection.h"
|
|
|
|
|
#include "BKE_duplilist.h"
|
2023-11-16 11:41:55 +01:00
|
|
|
#include "BKE_editmesh.hh"
|
2023-07-07 08:19:52 -04:00
|
|
|
#include "BKE_editmesh_cache.hh"
|
2021-04-01 16:23:16 -05:00
|
|
|
#include "BKE_geometry_set.hh"
|
2023-06-15 22:18:28 +02:00
|
|
|
#include "BKE_geometry_set_instances.hh"
|
2024-02-19 15:54:48 +01:00
|
|
|
#include "BKE_global.h"
|
2017-12-01 11:24:21 -02:00
|
|
|
#include "BKE_idprop.h"
|
2022-10-17 11:39:40 +02:00
|
|
|
#include "BKE_instances.hh"
|
2024-02-19 15:54:48 +01:00
|
|
|
#include "BKE_lattice.hh"
|
2023-12-01 19:43:16 +01:00
|
|
|
#include "BKE_main.hh"
|
2023-03-12 22:29:15 +01:00
|
|
|
#include "BKE_mesh.hh"
|
2024-02-19 15:54:48 +01:00
|
|
|
#include "BKE_mesh_iterators.hh"
|
|
|
|
|
#include "BKE_mesh_runtime.hh"
|
|
|
|
|
#include "BKE_modifier.hh"
|
2023-10-09 23:41:53 +02:00
|
|
|
#include "BKE_object.hh"
|
2023-11-15 18:46:07 +01:00
|
|
|
#include "BKE_object_types.hh"
|
2016-12-28 17:30:58 +01:00
|
|
|
#include "BKE_particle.h"
|
2024-02-19 15:54:48 +01:00
|
|
|
#include "BKE_scene.h"
|
|
|
|
|
#include "BKE_type_conversions.hh"
|
2023-11-28 16:05:12 -05:00
|
|
|
#include "BKE_vfont.hh"
|
2014-01-21 12:11:34 +01:00
|
|
|
|
2023-09-22 03:18:17 +02:00
|
|
|
#include "DEG_depsgraph.hh"
|
|
|
|
|
#include "DEG_depsgraph_query.hh"
|
2014-01-21 12:11:34 +01:00
|
|
|
|
2017-04-14 18:13:44 +03:00
|
|
|
#include "BLI_hash.h"
|
Attribute Node: support accessing attributes of View Layer and Scene.
The attribute node already allows accessing attributes associated
with objects and meshes, which allows changing the behavior of the
same material between different objects or instances. The same idea
can be extended to an even more global level of layers and scenes.
Currently view layers provide an option to replace all materials
with a different one. However, since the same material will be applied
to all objects in the layer, varying the behavior between layers while
preserving distinct materials requires duplicating objects.
Providing access to properties of layers and scenes via the attribute
node enables making materials with built-in switches or settings that
can be controlled globally at the view layer level. This is probably
most useful for complex NPR shading and compositing. Like with objects,
the node can also access built-in scene properties, like render resolution
or FOV of the active camera. Lookup is also attempted in World, similar
to how the Object mode checks the Mesh datablock.
In Cycles this mode is implemented by replacing the attribute node with
the attribute value during sync, allowing constant folding to take the
values into account. This means however that materials that use this
feature have to be re-synced upon any changes to scene, world or camera.
The Eevee version uses a new uniform buffer containing a sorted array
mapping name hashes to values, with binary search lookup. The array
is limited to 512 entries, which is effectively limitless even
considering it is shared by all materials in the scene; it is also
just 16KB of memory so no point trying to optimize further.
The buffer has to be rebuilt when new attributes are detected in a
material, so the draw engine keeps a table of recently seen attribute
names to minimize the chance of extra rebuilds mid-draw.
Differential Revision: https://developer.blender.org/D15941
2022-09-12 00:30:58 +03:00
|
|
|
#include "DNA_world_types.h"
|
Geometry Nodes: viewport preview
This adds support for showing geometry passed to the Viewer in the 3d
viewport (instead of just in the spreadsheet). The "viewer geometry"
bypasses the group output. So it is not necessary to change the final
output of the node group to be able to see the intermediate geometry.
**Activation and deactivation of a viewer node**
* A viewer node is activated by clicking on it.
* Ctrl+shift+click on any node/socket connects it to the viewer and
makes it active.
* Ctrl+shift+click in empty space deactivates the active viewer.
* When the active viewer is not visible anymore (e.g. another object
is selected, or the current node group is exit), it is deactivated.
* Clicking on the icon in the header of the Viewer node toggles whether
its active or not.
**Pinning**
* The spreadsheet still allows pinning the active viewer as before.
When pinned, the spreadsheet still references the viewer node even
when it becomes inactive.
* The viewport does not support pinning at the moment. It always shows
the active viewer.
**Attribute**
* When a field is linked to the second input of the viewer node it is
displayed as an overlay in the viewport.
* When possible the correct domain for the attribute is determined
automatically. This does not work in all cases. It falls back to the
face corner domain on meshes and the point domain on curves. When
necessary, the domain can be picked manually.
* The spreadsheet now only shows the "Viewer" column for the domain
that is selected in the Viewer node.
* Instance attributes are visualized as a constant color per instance.
**Viewport Options**
* The attribute overlay opacity can be controlled with the "Viewer Node"
setting in the overlays popover.
* A viewport can be configured not to show intermediate viewer-geometry
by disabling the "Viewer Node" option in the "View" menu.
**Implementation Details**
* The "spreadsheet context path" was generalized to a "viewer path" that
is used in more places now.
* The viewer node itself determines the attribute domain, evaluates the
field and stores the result in a `.viewer` attribute.
* A new "viewer attribute' overlay displays the data from the `.viewer`
attribute.
* The ground truth for the active viewer node is stored in the workspace
now. Node editors, spreadsheets and viewports retrieve the active
viewer from there unless they are pinned.
* The depsgraph object iterator has a new "viewer path" setting. When set,
the viewed geometry of the corresponding object is part of the iterator
instead of the final evaluated geometry.
* To support the instance attribute overlay `DupliObject` was extended
to contain the information necessary for drawing the overlay.
* The ctrl+shift+click operator has been refactored so that it can make
existing links to viewers active again.
* The auto-domain-detection in the Viewer node works by checking the
"preferred domain" for every field input. If there is not exactly one
preferred domain, the fallback is used.
Known limitations:
* Loose edges of meshes don't have the attribute overlay. This could be
added separately if necessary.
* Some attributes are hard to visualize as a color directly. For example,
the values might have to be normalized or some should be drawn as arrays.
For now, we encourage users to build node groups that generate appropriate
viewer-geometry. We might include some of that functionality in future versions.
Support for displaying attribute values as text in the viewport is planned as well.
* There seems to be an issue with the attribute overlay for pointclouds on
nvidia gpus, to be investigated.
Differential Revision: https://developer.blender.org/D15954
2022-09-28 17:54:59 +02:00
|
|
|
|
|
|
|
|
#include "NOD_geometry_nodes_log.hh"
|
2023-08-10 22:40:27 +02:00
|
|
|
#include "RNA_access.hh"
|
|
|
|
|
#include "RNA_path.hh"
|
Attribute Node: support accessing attributes of View Layer and Scene.
The attribute node already allows accessing attributes associated
with objects and meshes, which allows changing the behavior of the
same material between different objects or instances. The same idea
can be extended to an even more global level of layers and scenes.
Currently view layers provide an option to replace all materials
with a different one. However, since the same material will be applied
to all objects in the layer, varying the behavior between layers while
preserving distinct materials requires duplicating objects.
Providing access to properties of layers and scenes via the attribute
node enables making materials with built-in switches or settings that
can be controlled globally at the view layer level. This is probably
most useful for complex NPR shading and compositing. Like with objects,
the node can also access built-in scene properties, like render resolution
or FOV of the active camera. Lookup is also attempted in World, similar
to how the Object mode checks the Mesh datablock.
In Cycles this mode is implemented by replacing the attribute node with
the attribute value during sync, allowing constant folding to take the
values into account. This means however that materials that use this
feature have to be re-synced upon any changes to scene, world or camera.
The Eevee version uses a new uniform buffer containing a sorted array
mapping name hashes to values, with binary search lookup. The array
is limited to 512 entries, which is effectively limitless even
considering it is shared by all materials in the scene; it is also
just 16KB of memory so no point trying to optimize further.
The buffer has to be rebuilt when new attributes are detected in a
material, so the draw engine keeps a table of recently seen attribute
names to minimize the chance of extra rebuilds mid-draw.
Differential Revision: https://developer.blender.org/D15941
2022-09-12 00:30:58 +03:00
|
|
|
#include "RNA_prototypes.h"
|
2024-02-19 15:54:48 +01:00
|
|
|
#include "RNA_types.hh"
|
2014-01-21 22:48:27 +11:00
|
|
|
|
2023-07-11 12:55:57 +02:00
|
|
|
#include "MOD_nodes.hh"
|
|
|
|
|
|
2021-04-12 16:24:51 -05:00
|
|
|
using blender::Array;
|
Mesh: Move UV layers to generic attributes
Currently the `MLoopUV` struct stores UV coordinates and flags related
to editing UV maps in the UV editor. This patch changes the coordinates
to use the generic 2D vector type, and moves the flags into three
separate boolean attributes. This follows the design in T95965, with
the ultimate intention of simplifying code and improving performance.
Importantly, the change allows exporters and renderers to use UVs
"touched" by geometry nodes, which only creates generic attributes.
It also allows geometry nodes to create "proper" UV maps from scratch,
though only with the Store Named Attribute node for now.
The new design considers any 2D vector attribute on the corner domain
to be a UV map. In the future, they might be distinguished from regular
2D vectors with attribute metadata, which may be helpful because they
are often interpolated differently.
Most of the code changes deal with passing around UV BMesh custom data
offsets and tracking the boolean "sublayers". The boolean layers are
use the following prefixes for attribute names: vert selection: `.vs.`,
edge selection: `.es.`, pinning: `.pn.`. Currently these are short to
avoid using up the maximum length of attribute names. To accommodate
for these 4 extra characters, the name length limit is enlarged to 68
bytes, while the maximum user settable name length is still 64 bytes.
Unfortunately Python/RNA API access to the UV flag data becomes slower.
Accessing the boolean layers directly is be better for performance in
general.
Like the other mesh SoA refactors, backward and forward compatibility
aren't affected, and won't be changed until 4.0. We pay for that by
making mesh reading and writing more expensive with conversions.
Resolves T85962
Differential Revision: https://developer.blender.org/D14365
2023-01-10 00:47:04 -05:00
|
|
|
using blender::float2;
|
2021-04-12 16:24:51 -05:00
|
|
|
using blender::float3;
|
2021-04-01 16:23:16 -05:00
|
|
|
using blender::float4x4;
|
|
|
|
|
using blender::Span;
|
2021-04-27 12:33:40 +02:00
|
|
|
using blender::Vector;
|
2023-06-15 22:18:28 +02:00
|
|
|
using blender::bke::GeometrySet;
|
2022-10-17 11:39:40 +02:00
|
|
|
using blender::bke::InstanceReference;
|
|
|
|
|
using blender::bke::Instances;
|
Geometry Nodes: viewport preview
This adds support for showing geometry passed to the Viewer in the 3d
viewport (instead of just in the spreadsheet). The "viewer geometry"
bypasses the group output. So it is not necessary to change the final
output of the node group to be able to see the intermediate geometry.
**Activation and deactivation of a viewer node**
* A viewer node is activated by clicking on it.
* Ctrl+shift+click on any node/socket connects it to the viewer and
makes it active.
* Ctrl+shift+click in empty space deactivates the active viewer.
* When the active viewer is not visible anymore (e.g. another object
is selected, or the current node group is exit), it is deactivated.
* Clicking on the icon in the header of the Viewer node toggles whether
its active or not.
**Pinning**
* The spreadsheet still allows pinning the active viewer as before.
When pinned, the spreadsheet still references the viewer node even
when it becomes inactive.
* The viewport does not support pinning at the moment. It always shows
the active viewer.
**Attribute**
* When a field is linked to the second input of the viewer node it is
displayed as an overlay in the viewport.
* When possible the correct domain for the attribute is determined
automatically. This does not work in all cases. It falls back to the
face corner domain on meshes and the point domain on curves. When
necessary, the domain can be picked manually.
* The spreadsheet now only shows the "Viewer" column for the domain
that is selected in the Viewer node.
* Instance attributes are visualized as a constant color per instance.
**Viewport Options**
* The attribute overlay opacity can be controlled with the "Viewer Node"
setting in the overlays popover.
* A viewport can be configured not to show intermediate viewer-geometry
by disabling the "Viewer Node" option in the "View" menu.
**Implementation Details**
* The "spreadsheet context path" was generalized to a "viewer path" that
is used in more places now.
* The viewer node itself determines the attribute domain, evaluates the
field and stores the result in a `.viewer` attribute.
* A new "viewer attribute' overlay displays the data from the `.viewer`
attribute.
* The ground truth for the active viewer node is stored in the workspace
now. Node editors, spreadsheets and viewports retrieve the active
viewer from there unless they are pinned.
* The depsgraph object iterator has a new "viewer path" setting. When set,
the viewed geometry of the corresponding object is part of the iterator
instead of the final evaluated geometry.
* To support the instance attribute overlay `DupliObject` was extended
to contain the information necessary for drawing the overlay.
* The ctrl+shift+click operator has been refactored so that it can make
existing links to viewers active again.
* The auto-domain-detection in the Viewer node works by checking the
"preferred domain" for every field input. If there is not exactly one
preferred domain, the fallback is used.
Known limitations:
* Loose edges of meshes don't have the attribute overlay. This could be
added separately if necessary.
* Some attributes are hard to visualize as a color directly. For example,
the values might have to be normalized or some should be drawn as arrays.
For now, we encourage users to build node groups that generate appropriate
viewer-geometry. We might include some of that functionality in future versions.
Support for displaying attribute values as text in the viewport is planned as well.
* There seems to be an issue with the attribute overlay for pointclouds on
nvidia gpus, to be investigated.
Differential Revision: https://developer.blender.org/D15954
2022-09-28 17:54:59 +02:00
|
|
|
namespace geo_log = blender::nodes::geo_eval_log;
|
2021-04-01 16:23:16 -05:00
|
|
|
|
2020-08-10 18:29:17 +10:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Internal Duplicate Context
|
|
|
|
|
* \{ */
|
2014-01-21 12:11:34 +01:00
|
|
|
|
2022-11-11 09:06:50 -06:00
|
|
|
static constexpr short GEOMETRY_SET_DUPLI_GENERATOR_TYPE = 1;
|
|
|
|
|
|
2021-04-01 15:54:48 -05:00
|
|
|
struct DupliContext {
|
2018-04-06 12:07:27 +02:00
|
|
|
Depsgraph *depsgraph;
|
2019-04-21 13:44:06 +10:00
|
|
|
/** XXX child objects are selected from this group if set, could be nicer. */
|
|
|
|
|
Collection *collection;
|
|
|
|
|
/** Only to check if the object is in edit-mode. */
|
|
|
|
|
Object *obedit;
|
2014-01-21 12:11:34 +01:00
|
|
|
|
|
|
|
|
Scene *scene;
|
2022-11-11 12:54:01 +01:00
|
|
|
/** Root parent object at the scene level. */
|
|
|
|
|
Object *root_object;
|
|
|
|
|
/** Immediate parent object in the context. */
|
2014-01-21 12:11:34 +01:00
|
|
|
Object *object;
|
|
|
|
|
float space_mat[4][4];
|
Geometry Nodes: viewport preview
This adds support for showing geometry passed to the Viewer in the 3d
viewport (instead of just in the spreadsheet). The "viewer geometry"
bypasses the group output. So it is not necessary to change the final
output of the node group to be able to see the intermediate geometry.
**Activation and deactivation of a viewer node**
* A viewer node is activated by clicking on it.
* Ctrl+shift+click on any node/socket connects it to the viewer and
makes it active.
* Ctrl+shift+click in empty space deactivates the active viewer.
* When the active viewer is not visible anymore (e.g. another object
is selected, or the current node group is exit), it is deactivated.
* Clicking on the icon in the header of the Viewer node toggles whether
its active or not.
**Pinning**
* The spreadsheet still allows pinning the active viewer as before.
When pinned, the spreadsheet still references the viewer node even
when it becomes inactive.
* The viewport does not support pinning at the moment. It always shows
the active viewer.
**Attribute**
* When a field is linked to the second input of the viewer node it is
displayed as an overlay in the viewport.
* When possible the correct domain for the attribute is determined
automatically. This does not work in all cases. It falls back to the
face corner domain on meshes and the point domain on curves. When
necessary, the domain can be picked manually.
* The spreadsheet now only shows the "Viewer" column for the domain
that is selected in the Viewer node.
* Instance attributes are visualized as a constant color per instance.
**Viewport Options**
* The attribute overlay opacity can be controlled with the "Viewer Node"
setting in the overlays popover.
* A viewport can be configured not to show intermediate viewer-geometry
by disabling the "Viewer Node" option in the "View" menu.
**Implementation Details**
* The "spreadsheet context path" was generalized to a "viewer path" that
is used in more places now.
* The viewer node itself determines the attribute domain, evaluates the
field and stores the result in a `.viewer` attribute.
* A new "viewer attribute' overlay displays the data from the `.viewer`
attribute.
* The ground truth for the active viewer node is stored in the workspace
now. Node editors, spreadsheets and viewports retrieve the active
viewer from there unless they are pinned.
* The depsgraph object iterator has a new "viewer path" setting. When set,
the viewed geometry of the corresponding object is part of the iterator
instead of the final evaluated geometry.
* To support the instance attribute overlay `DupliObject` was extended
to contain the information necessary for drawing the overlay.
* The ctrl+shift+click operator has been refactored so that it can make
existing links to viewers active again.
* The auto-domain-detection in the Viewer node works by checking the
"preferred domain" for every field input. If there is not exactly one
preferred domain, the fallback is used.
Known limitations:
* Loose edges of meshes don't have the attribute overlay. This could be
added separately if necessary.
* Some attributes are hard to visualize as a color directly. For example,
the values might have to be normalized or some should be drawn as arrays.
For now, we encourage users to build node groups that generate appropriate
viewer-geometry. We might include some of that functionality in future versions.
Support for displaying attribute values as text in the viewport is planned as well.
* There seems to be an issue with the attribute overlay for pointclouds on
nvidia gpus, to be investigated.
Differential Revision: https://developer.blender.org/D15954
2022-09-28 17:54:59 +02:00
|
|
|
/**
|
|
|
|
|
* Index of the top-level instance that contains this context or -1 when unused.
|
|
|
|
|
* This is an index into the instances component of #preview_base_geometry.
|
|
|
|
|
*/
|
|
|
|
|
int preview_instance_index;
|
|
|
|
|
/**
|
|
|
|
|
* Top level geometry set that is previewed.
|
|
|
|
|
*/
|
|
|
|
|
const GeometrySet *preview_base_geometry;
|
2014-01-21 12:11:34 +01:00
|
|
|
|
2021-04-27 12:33:40 +02:00
|
|
|
/**
|
|
|
|
|
* A stack that contains all the "parent" objects of a particular instance when recursive
|
|
|
|
|
* instancing is used. This is used to prevent objects from instancing themselves accidentally.
|
|
|
|
|
* Use a vector instead of a stack because we want to use the #contains method.
|
|
|
|
|
*/
|
|
|
|
|
Vector<Object *> *instance_stack;
|
|
|
|
|
|
2022-11-11 09:06:50 -06:00
|
|
|
/**
|
|
|
|
|
* Older code relies on the "dupli generator type" for various visibility or processing
|
|
|
|
|
* decisions. However, new code uses geometry instances in places that weren't using the dupli
|
|
|
|
|
* system previously. To fix this, keep track of the last dupli generator type that wasn't a
|
|
|
|
|
* geometry set instance.
|
2023-02-10 11:34:20 +11:00
|
|
|
*/
|
2022-11-11 09:06:50 -06:00
|
|
|
Vector<short> *dupli_gen_type_stack;
|
|
|
|
|
|
2014-01-21 12:11:34 +01:00
|
|
|
int persistent_id[MAX_DUPLI_RECUR];
|
2022-09-30 21:00:27 +03:00
|
|
|
int64_t instance_idx[MAX_DUPLI_RECUR];
|
|
|
|
|
const GeometrySet *instance_data[MAX_DUPLI_RECUR];
|
2014-01-21 12:11:34 +01:00
|
|
|
int level;
|
|
|
|
|
|
|
|
|
|
const struct DupliGenerator *gen;
|
|
|
|
|
|
2019-04-21 13:44:06 +10:00
|
|
|
/** Result containers. */
|
2020-08-13 09:49:49 +10:00
|
|
|
ListBase *duplilist; /* Legacy doubly-linked list. */
|
2021-04-01 15:54:48 -05:00
|
|
|
};
|
2014-01-21 12:11:34 +01:00
|
|
|
|
2021-04-01 15:54:48 -05:00
|
|
|
struct DupliGenerator {
|
2023-04-14 14:26:42 +10:00
|
|
|
/** Duplicator Type, see members of #OB_DUPLI. */
|
|
|
|
|
short type;
|
2014-01-21 12:11:34 +01:00
|
|
|
void (*make_duplis)(const DupliContext *ctx);
|
2021-04-01 15:54:48 -05:00
|
|
|
};
|
2014-01-21 12:11:34 +01:00
|
|
|
|
|
|
|
|
static const DupliGenerator *get_dupli_generator(const DupliContext *ctx);
|
|
|
|
|
|
2020-08-10 18:29:17 +10:00
|
|
|
/**
|
|
|
|
|
* Create initial context for root object.
|
|
|
|
|
*/
|
2019-09-14 08:10:50 +10:00
|
|
|
static void init_context(DupliContext *r_ctx,
|
|
|
|
|
Depsgraph *depsgraph,
|
|
|
|
|
Scene *scene,
|
|
|
|
|
Object *ob,
|
2021-04-27 12:33:40 +02:00
|
|
|
const float space_mat[4][4],
|
2022-11-11 09:06:50 -06:00
|
|
|
Vector<Object *> &instance_stack,
|
|
|
|
|
Vector<short> &dupli_gen_type_stack)
|
2014-01-21 12:11:34 +01:00
|
|
|
{
|
2018-04-06 12:07:27 +02:00
|
|
|
r_ctx->depsgraph = depsgraph;
|
2014-01-21 12:11:34 +01:00
|
|
|
r_ctx->scene = scene;
|
2021-04-01 15:54:48 -05:00
|
|
|
r_ctx->collection = nullptr;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-11-11 12:54:01 +01:00
|
|
|
r_ctx->root_object = ob;
|
2014-01-21 12:11:34 +01:00
|
|
|
r_ctx->object = ob;
|
2018-04-05 18:20:27 +02:00
|
|
|
r_ctx->obedit = OBEDIT_FROM_OBACT(ob);
|
2021-04-27 12:33:40 +02:00
|
|
|
r_ctx->instance_stack = &instance_stack;
|
2022-11-11 09:06:50 -06:00
|
|
|
r_ctx->dupli_gen_type_stack = &dupli_gen_type_stack;
|
2019-04-22 09:39:35 +10:00
|
|
|
if (space_mat) {
|
2014-01-21 12:11:34 +01:00
|
|
|
copy_m4_m4(r_ctx->space_mat, space_mat);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2014-01-21 12:11:34 +01:00
|
|
|
unit_m4(r_ctx->space_mat);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2014-01-21 12:11:34 +01:00
|
|
|
r_ctx->level = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-01-21 12:11:34 +01:00
|
|
|
r_ctx->gen = get_dupli_generator(r_ctx);
|
2022-11-11 09:06:50 -06:00
|
|
|
if (r_ctx->gen && r_ctx->gen->type != GEOMETRY_SET_DUPLI_GENERATOR_TYPE) {
|
|
|
|
|
r_ctx->dupli_gen_type_stack->append(r_ctx->gen->type);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-04-01 15:54:48 -05:00
|
|
|
r_ctx->duplilist = nullptr;
|
Geometry Nodes: viewport preview
This adds support for showing geometry passed to the Viewer in the 3d
viewport (instead of just in the spreadsheet). The "viewer geometry"
bypasses the group output. So it is not necessary to change the final
output of the node group to be able to see the intermediate geometry.
**Activation and deactivation of a viewer node**
* A viewer node is activated by clicking on it.
* Ctrl+shift+click on any node/socket connects it to the viewer and
makes it active.
* Ctrl+shift+click in empty space deactivates the active viewer.
* When the active viewer is not visible anymore (e.g. another object
is selected, or the current node group is exit), it is deactivated.
* Clicking on the icon in the header of the Viewer node toggles whether
its active or not.
**Pinning**
* The spreadsheet still allows pinning the active viewer as before.
When pinned, the spreadsheet still references the viewer node even
when it becomes inactive.
* The viewport does not support pinning at the moment. It always shows
the active viewer.
**Attribute**
* When a field is linked to the second input of the viewer node it is
displayed as an overlay in the viewport.
* When possible the correct domain for the attribute is determined
automatically. This does not work in all cases. It falls back to the
face corner domain on meshes and the point domain on curves. When
necessary, the domain can be picked manually.
* The spreadsheet now only shows the "Viewer" column for the domain
that is selected in the Viewer node.
* Instance attributes are visualized as a constant color per instance.
**Viewport Options**
* The attribute overlay opacity can be controlled with the "Viewer Node"
setting in the overlays popover.
* A viewport can be configured not to show intermediate viewer-geometry
by disabling the "Viewer Node" option in the "View" menu.
**Implementation Details**
* The "spreadsheet context path" was generalized to a "viewer path" that
is used in more places now.
* The viewer node itself determines the attribute domain, evaluates the
field and stores the result in a `.viewer` attribute.
* A new "viewer attribute' overlay displays the data from the `.viewer`
attribute.
* The ground truth for the active viewer node is stored in the workspace
now. Node editors, spreadsheets and viewports retrieve the active
viewer from there unless they are pinned.
* The depsgraph object iterator has a new "viewer path" setting. When set,
the viewed geometry of the corresponding object is part of the iterator
instead of the final evaluated geometry.
* To support the instance attribute overlay `DupliObject` was extended
to contain the information necessary for drawing the overlay.
* The ctrl+shift+click operator has been refactored so that it can make
existing links to viewers active again.
* The auto-domain-detection in the Viewer node works by checking the
"preferred domain" for every field input. If there is not exactly one
preferred domain, the fallback is used.
Known limitations:
* Loose edges of meshes don't have the attribute overlay. This could be
added separately if necessary.
* Some attributes are hard to visualize as a color directly. For example,
the values might have to be normalized or some should be drawn as arrays.
For now, we encourage users to build node groups that generate appropriate
viewer-geometry. We might include some of that functionality in future versions.
Support for displaying attribute values as text in the viewport is planned as well.
* There seems to be an issue with the attribute overlay for pointclouds on
nvidia gpus, to be investigated.
Differential Revision: https://developer.blender.org/D15954
2022-09-28 17:54:59 +02:00
|
|
|
r_ctx->preview_instance_index = -1;
|
|
|
|
|
r_ctx->preview_base_geometry = nullptr;
|
2014-01-21 12:11:34 +01:00
|
|
|
}
|
|
|
|
|
|
2020-08-10 18:29:17 +10:00
|
|
|
/**
|
|
|
|
|
* Create sub-context for recursive duplis.
|
|
|
|
|
*/
|
2022-09-30 21:00:27 +03:00
|
|
|
static bool copy_dupli_context(DupliContext *r_ctx,
|
|
|
|
|
const DupliContext *ctx,
|
|
|
|
|
Object *ob,
|
|
|
|
|
const float mat[4][4],
|
|
|
|
|
int index,
|
|
|
|
|
const GeometrySet *geometry = nullptr,
|
|
|
|
|
int64_t instance_index = 0)
|
2014-01-21 12:11:34 +01:00
|
|
|
{
|
|
|
|
|
*r_ctx = *ctx;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2019-04-27 12:07:07 +10:00
|
|
|
/* XXX annoying, previously was done by passing an ID* argument,
|
|
|
|
|
* this at least is more explicit. */
|
Geometry Nodes: viewport preview
This adds support for showing geometry passed to the Viewer in the 3d
viewport (instead of just in the spreadsheet). The "viewer geometry"
bypasses the group output. So it is not necessary to change the final
output of the node group to be able to see the intermediate geometry.
**Activation and deactivation of a viewer node**
* A viewer node is activated by clicking on it.
* Ctrl+shift+click on any node/socket connects it to the viewer and
makes it active.
* Ctrl+shift+click in empty space deactivates the active viewer.
* When the active viewer is not visible anymore (e.g. another object
is selected, or the current node group is exit), it is deactivated.
* Clicking on the icon in the header of the Viewer node toggles whether
its active or not.
**Pinning**
* The spreadsheet still allows pinning the active viewer as before.
When pinned, the spreadsheet still references the viewer node even
when it becomes inactive.
* The viewport does not support pinning at the moment. It always shows
the active viewer.
**Attribute**
* When a field is linked to the second input of the viewer node it is
displayed as an overlay in the viewport.
* When possible the correct domain for the attribute is determined
automatically. This does not work in all cases. It falls back to the
face corner domain on meshes and the point domain on curves. When
necessary, the domain can be picked manually.
* The spreadsheet now only shows the "Viewer" column for the domain
that is selected in the Viewer node.
* Instance attributes are visualized as a constant color per instance.
**Viewport Options**
* The attribute overlay opacity can be controlled with the "Viewer Node"
setting in the overlays popover.
* A viewport can be configured not to show intermediate viewer-geometry
by disabling the "Viewer Node" option in the "View" menu.
**Implementation Details**
* The "spreadsheet context path" was generalized to a "viewer path" that
is used in more places now.
* The viewer node itself determines the attribute domain, evaluates the
field and stores the result in a `.viewer` attribute.
* A new "viewer attribute' overlay displays the data from the `.viewer`
attribute.
* The ground truth for the active viewer node is stored in the workspace
now. Node editors, spreadsheets and viewports retrieve the active
viewer from there unless they are pinned.
* The depsgraph object iterator has a new "viewer path" setting. When set,
the viewed geometry of the corresponding object is part of the iterator
instead of the final evaluated geometry.
* To support the instance attribute overlay `DupliObject` was extended
to contain the information necessary for drawing the overlay.
* The ctrl+shift+click operator has been refactored so that it can make
existing links to viewers active again.
* The auto-domain-detection in the Viewer node works by checking the
"preferred domain" for every field input. If there is not exactly one
preferred domain, the fallback is used.
Known limitations:
* Loose edges of meshes don't have the attribute overlay. This could be
added separately if necessary.
* Some attributes are hard to visualize as a color directly. For example,
the values might have to be normalized or some should be drawn as arrays.
For now, we encourage users to build node groups that generate appropriate
viewer-geometry. We might include some of that functionality in future versions.
Support for displaying attribute values as text in the viewport is planned as well.
* There seems to be an issue with the attribute overlay for pointclouds on
nvidia gpus, to be investigated.
Differential Revision: https://developer.blender.org/D15954
2022-09-28 17:54:59 +02:00
|
|
|
if (ctx->gen && ctx->gen->type == OB_DUPLICOLLECTION) {
|
2019-02-17 19:00:54 +11:00
|
|
|
r_ctx->collection = ctx->object->instance_collection;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2014-01-21 12:11:34 +01:00
|
|
|
|
|
|
|
|
r_ctx->object = ob;
|
2021-04-27 12:33:40 +02:00
|
|
|
r_ctx->instance_stack = ctx->instance_stack;
|
2019-04-22 09:39:35 +10:00
|
|
|
if (mat) {
|
2014-01-21 12:11:34 +01:00
|
|
|
mul_m4_m4m4(r_ctx->space_mat, (float(*)[4])ctx->space_mat, mat);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2014-01-21 12:11:34 +01:00
|
|
|
r_ctx->persistent_id[r_ctx->level] = index;
|
2022-09-30 21:00:27 +03:00
|
|
|
r_ctx->instance_idx[r_ctx->level] = instance_index;
|
|
|
|
|
r_ctx->instance_data[r_ctx->level] = geometry;
|
2014-01-21 12:11:34 +01:00
|
|
|
++r_ctx->level;
|
|
|
|
|
|
2021-11-09 17:52:40 +01:00
|
|
|
if (r_ctx->level == MAX_DUPLI_RECUR - 1) {
|
|
|
|
|
std::cerr << "Warning: Maximum instance recursion level reached.\n";
|
2021-12-15 15:46:27 +01:00
|
|
|
return false;
|
2021-11-09 17:52:40 +01:00
|
|
|
}
|
|
|
|
|
|
2014-01-21 12:11:34 +01:00
|
|
|
r_ctx->gen = get_dupli_generator(r_ctx);
|
2022-11-11 09:06:50 -06:00
|
|
|
if (r_ctx->gen && r_ctx->gen->type != GEOMETRY_SET_DUPLI_GENERATOR_TYPE) {
|
|
|
|
|
r_ctx->dupli_gen_type_stack->append(r_ctx->gen->type);
|
|
|
|
|
}
|
2021-12-15 15:46:27 +01:00
|
|
|
return true;
|
2014-01-21 12:11:34 +01:00
|
|
|
}
|
|
|
|
|
|
2020-08-10 18:29:17 +10:00
|
|
|
/**
|
|
|
|
|
* Generate a dupli instance.
|
|
|
|
|
*
|
2022-10-24 14:16:37 +02:00
|
|
|
* \param mat: is transform of the object relative to current context (including
|
|
|
|
|
* #Object.object_to_world).
|
2014-01-21 12:11:34 +01:00
|
|
|
*/
|
2022-09-30 21:00:27 +03:00
|
|
|
static DupliObject *make_dupli(const DupliContext *ctx,
|
|
|
|
|
Object *ob,
|
|
|
|
|
const ID *object_data,
|
|
|
|
|
const float mat[4][4],
|
|
|
|
|
int index,
|
|
|
|
|
const GeometrySet *geometry = nullptr,
|
|
|
|
|
int64_t instance_index = 0)
|
2014-01-21 12:11:34 +01:00
|
|
|
{
|
|
|
|
|
DupliObject *dob;
|
|
|
|
|
int i;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Add a #DupliObject instance to the result container. */
|
2014-01-21 12:11:34 +01:00
|
|
|
if (ctx->duplilist) {
|
2021-12-24 22:17:49 -05:00
|
|
|
dob = MEM_cnew<DupliObject>("dupli object");
|
2014-01-21 12:11:34 +01:00
|
|
|
BLI_addtail(ctx->duplilist, dob);
|
|
|
|
|
}
|
|
|
|
|
else {
|
2021-04-01 15:54:48 -05:00
|
|
|
return nullptr;
|
2014-01-21 12:11:34 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-01-21 12:11:34 +01:00
|
|
|
dob->ob = ob;
|
2022-08-09 14:44:47 -05:00
|
|
|
dob->ob_data = const_cast<ID *>(object_data);
|
2014-01-21 12:11:34 +01:00
|
|
|
mul_m4_m4m4(dob->mat, (float(*)[4])ctx->space_mat, mat);
|
2022-11-11 09:06:50 -06:00
|
|
|
dob->type = ctx->gen == nullptr ? 0 : ctx->dupli_gen_type_stack->last();
|
Geometry Nodes: viewport preview
This adds support for showing geometry passed to the Viewer in the 3d
viewport (instead of just in the spreadsheet). The "viewer geometry"
bypasses the group output. So it is not necessary to change the final
output of the node group to be able to see the intermediate geometry.
**Activation and deactivation of a viewer node**
* A viewer node is activated by clicking on it.
* Ctrl+shift+click on any node/socket connects it to the viewer and
makes it active.
* Ctrl+shift+click in empty space deactivates the active viewer.
* When the active viewer is not visible anymore (e.g. another object
is selected, or the current node group is exit), it is deactivated.
* Clicking on the icon in the header of the Viewer node toggles whether
its active or not.
**Pinning**
* The spreadsheet still allows pinning the active viewer as before.
When pinned, the spreadsheet still references the viewer node even
when it becomes inactive.
* The viewport does not support pinning at the moment. It always shows
the active viewer.
**Attribute**
* When a field is linked to the second input of the viewer node it is
displayed as an overlay in the viewport.
* When possible the correct domain for the attribute is determined
automatically. This does not work in all cases. It falls back to the
face corner domain on meshes and the point domain on curves. When
necessary, the domain can be picked manually.
* The spreadsheet now only shows the "Viewer" column for the domain
that is selected in the Viewer node.
* Instance attributes are visualized as a constant color per instance.
**Viewport Options**
* The attribute overlay opacity can be controlled with the "Viewer Node"
setting in the overlays popover.
* A viewport can be configured not to show intermediate viewer-geometry
by disabling the "Viewer Node" option in the "View" menu.
**Implementation Details**
* The "spreadsheet context path" was generalized to a "viewer path" that
is used in more places now.
* The viewer node itself determines the attribute domain, evaluates the
field and stores the result in a `.viewer` attribute.
* A new "viewer attribute' overlay displays the data from the `.viewer`
attribute.
* The ground truth for the active viewer node is stored in the workspace
now. Node editors, spreadsheets and viewports retrieve the active
viewer from there unless they are pinned.
* The depsgraph object iterator has a new "viewer path" setting. When set,
the viewed geometry of the corresponding object is part of the iterator
instead of the final evaluated geometry.
* To support the instance attribute overlay `DupliObject` was extended
to contain the information necessary for drawing the overlay.
* The ctrl+shift+click operator has been refactored so that it can make
existing links to viewers active again.
* The auto-domain-detection in the Viewer node works by checking the
"preferred domain" for every field input. If there is not exactly one
preferred domain, the fallback is used.
Known limitations:
* Loose edges of meshes don't have the attribute overlay. This could be
added separately if necessary.
* Some attributes are hard to visualize as a color directly. For example,
the values might have to be normalized or some should be drawn as arrays.
For now, we encourage users to build node groups that generate appropriate
viewer-geometry. We might include some of that functionality in future versions.
Support for displaying attribute values as text in the viewport is planned as well.
* There seems to be an issue with the attribute overlay for pointclouds on
nvidia gpus, to be investigated.
Differential Revision: https://developer.blender.org/D15954
2022-09-28 17:54:59 +02:00
|
|
|
dob->preview_base_geometry = ctx->preview_base_geometry;
|
|
|
|
|
dob->preview_instance_index = ctx->preview_instance_index;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Set persistent id, which is an array with a persistent index for each level
|
2014-01-21 12:11:34 +01:00
|
|
|
* (particle number, vertex number, ..). by comparing this we can find the same
|
2020-08-13 09:49:49 +10:00
|
|
|
* dupli-object between frames, which is needed for motion blur.
|
|
|
|
|
* The last level is ordered first in the array. */
|
2014-01-21 12:11:34 +01:00
|
|
|
dob->persistent_id[0] = index;
|
2019-04-22 09:39:35 +10:00
|
|
|
for (i = 1; i < ctx->level + 1; i++) {
|
2014-01-21 21:01:12 +01:00
|
|
|
dob->persistent_id[i] = ctx->persistent_id[ctx->level - i];
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Fill rest of values with #INT_MAX which index will never have as value. */
|
2019-04-22 09:39:35 +10:00
|
|
|
for (; i < MAX_DUPLI_RECUR; i++) {
|
2014-01-21 21:01:12 +01:00
|
|
|
dob->persistent_id[i] = INT_MAX;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-09-30 21:00:27 +03:00
|
|
|
/* Store geometry set data for attribute lookup in innermost to outermost
|
|
|
|
|
* order, copying only non-null entries to save space. */
|
2023-02-14 11:50:00 +11:00
|
|
|
const int max_instance = ARRAY_SIZE(dob->instance_data);
|
2022-09-30 21:00:27 +03:00
|
|
|
int next_instance = 0;
|
|
|
|
|
if (geometry != nullptr) {
|
|
|
|
|
dob->instance_idx[next_instance] = int(instance_index);
|
|
|
|
|
dob->instance_data[next_instance] = geometry;
|
|
|
|
|
next_instance++;
|
|
|
|
|
}
|
|
|
|
|
for (i = ctx->level - 1; i >= 0 && next_instance < max_instance; i--) {
|
|
|
|
|
if (ctx->instance_data[i] != nullptr) {
|
|
|
|
|
dob->instance_idx[next_instance] = int(ctx->instance_idx[i]);
|
|
|
|
|
dob->instance_data[next_instance] = ctx->instance_data[i];
|
|
|
|
|
next_instance++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Meta-balls never draw in duplis, they are instead merged into one by the basis
|
|
|
|
|
* meta-ball outside of the group. this does mean that if that meta-ball is not in the
|
2014-01-21 12:11:34 +01:00
|
|
|
* scene, they will not show up at all, limitation that should be solved once. */
|
2022-08-17 10:20:25 -04:00
|
|
|
if (object_data && GS(object_data->name) == ID_MB) {
|
2014-01-21 12:11:34 +01:00
|
|
|
dob->no_draw = true;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-11-11 12:54:01 +01:00
|
|
|
/* Random number per instance.
|
|
|
|
|
* The root object in the scene, persistent ID up to the instance object, and the instance object
|
|
|
|
|
* name together result in a unique random number. */
|
2017-04-14 18:13:44 +03:00
|
|
|
dob->random_id = BLI_hash_string(dob->ob->id.name + 2);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-04-14 18:13:44 +03:00
|
|
|
if (dob->persistent_id[0] != INT_MAX) {
|
2020-07-06 16:52:28 +02:00
|
|
|
for (i = 0; i < MAX_DUPLI_RECUR; i++) {
|
2022-09-25 18:33:28 +10:00
|
|
|
dob->random_id = BLI_hash_int_2d(dob->random_id, uint(dob->persistent_id[i]));
|
2017-04-24 21:58:28 +10:00
|
|
|
}
|
2017-04-14 18:13:44 +03:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
dob->random_id = BLI_hash_int_2d(dob->random_id, 0);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-11-11 12:54:01 +01:00
|
|
|
if (ctx->root_object != ob) {
|
|
|
|
|
dob->random_id ^= BLI_hash_int(BLI_hash_string(ctx->root_object->id.name + 2));
|
2017-04-14 18:13:44 +03:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-01-21 12:11:34 +01:00
|
|
|
return dob;
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-09 14:44:47 -05:00
|
|
|
static DupliObject *make_dupli(const DupliContext *ctx,
|
|
|
|
|
Object *ob,
|
|
|
|
|
const float mat[4][4],
|
2022-09-30 21:00:27 +03:00
|
|
|
int index,
|
|
|
|
|
const GeometrySet *geometry = nullptr,
|
|
|
|
|
int64_t instance_index = 0)
|
2022-08-09 14:44:47 -05:00
|
|
|
{
|
2022-09-30 21:00:27 +03:00
|
|
|
return make_dupli(ctx, ob, static_cast<ID *>(ob->data), mat, index, geometry, instance_index);
|
2022-08-09 14:44:47 -05:00
|
|
|
}
|
|
|
|
|
|
2020-08-10 18:29:17 +10:00
|
|
|
/**
|
2020-08-13 09:49:49 +10:00
|
|
|
* Recursive dupli-objects.
|
2020-08-10 18:29:17 +10:00
|
|
|
*
|
2022-10-24 14:16:37 +02:00
|
|
|
* \param space_mat: is the local dupli-space (excluding dupli #Object.object_to_world).
|
2014-01-21 12:11:34 +01:00
|
|
|
*/
|
2018-06-06 14:39:05 +02:00
|
|
|
static void make_recursive_duplis(const DupliContext *ctx,
|
|
|
|
|
Object *ob,
|
2019-09-14 08:10:50 +10:00
|
|
|
const float space_mat[4][4],
|
2022-09-30 21:00:27 +03:00
|
|
|
int index,
|
|
|
|
|
const GeometrySet *geometry = nullptr,
|
|
|
|
|
int64_t instance_index = 0)
|
2014-01-21 12:11:34 +01:00
|
|
|
{
|
2021-04-27 12:33:40 +02:00
|
|
|
if (ctx->instance_stack->contains(ob)) {
|
|
|
|
|
/* Avoid recursive instances. */
|
|
|
|
|
printf("Warning: '%s' object is trying to instance itself.\n", ob->id.name + 2);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Simple preventing of too deep nested collections with #MAX_DUPLI_RECUR. */
|
2014-01-21 12:11:34 +01:00
|
|
|
if (ctx->level < MAX_DUPLI_RECUR) {
|
|
|
|
|
DupliContext rctx;
|
2022-09-30 21:00:27 +03:00
|
|
|
if (!copy_dupli_context(&rctx, ctx, ob, space_mat, index, geometry, instance_index)) {
|
2021-12-15 15:46:27 +01:00
|
|
|
return;
|
|
|
|
|
}
|
2014-01-21 12:11:34 +01:00
|
|
|
if (rctx.gen) {
|
2021-04-27 12:33:40 +02:00
|
|
|
ctx->instance_stack->append(ob);
|
2014-01-21 12:11:34 +01:00
|
|
|
rctx.gen->make_duplis(&rctx);
|
2021-04-27 12:33:40 +02:00
|
|
|
ctx->instance_stack->remove_last();
|
2022-11-22 15:38:19 -06:00
|
|
|
if (rctx.gen->type != GEOMETRY_SET_DUPLI_GENERATOR_TYPE) {
|
|
|
|
|
if (!ctx->dupli_gen_type_stack->is_empty()) {
|
|
|
|
|
ctx->dupli_gen_type_stack->remove_last();
|
|
|
|
|
}
|
2022-11-11 12:31:50 -06:00
|
|
|
}
|
2014-01-21 12:11:34 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-10 18:29:17 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Internal Child Duplicates (Used by Other Functions)
|
|
|
|
|
* \{ */
|
2014-01-21 12:11:34 +01:00
|
|
|
|
2021-04-01 15:54:48 -05:00
|
|
|
using MakeChildDuplisFunc = void (*)(const DupliContext *ctx, void *userdata, Object *child);
|
2014-01-21 12:11:34 +01:00
|
|
|
|
|
|
|
|
static bool is_child(const Object *ob, const Object *parent)
|
|
|
|
|
{
|
|
|
|
|
const Object *ob_parent = ob->parent;
|
|
|
|
|
while (ob_parent) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (ob_parent == parent) {
|
2014-01-21 12:11:34 +01:00
|
|
|
return true;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2014-01-21 12:11:34 +01:00
|
|
|
ob_parent = ob_parent->parent;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-10 18:29:17 +10:00
|
|
|
/**
|
|
|
|
|
* Create duplis from every child in scene or collection.
|
|
|
|
|
*/
|
2014-01-21 22:48:27 +11:00
|
|
|
static void make_child_duplis(const DupliContext *ctx,
|
|
|
|
|
void *userdata,
|
|
|
|
|
MakeChildDuplisFunc make_child_duplis_cb)
|
2014-01-21 12:11:34 +01:00
|
|
|
{
|
|
|
|
|
Object *parent = ctx->object;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Collections and groups unification
OVERVIEW
* In 2.7 terminology, all layers and groups are now collection datablocks.
* These collections are nestable, linkable, instanceable, overrideable, ..
which opens up new ways to set up scenes and link + override data.
* Viewport/render visibility and selectability are now a part of the collection
and shared across all view layers and linkable.
* View layers define which subset of the scene collection hierarchy is excluded
for each. For many workflows one view layer can be used, these are more of an
advanced feature now.
OUTLINER
* The outliner now has a "View Layer" display mode instead of "Collections",
which can display the collections and/or objects in the view layer.
* In this display mode, collections can be excluded with the right click menu.
These will then be greyed out and their objects will be excluded.
* To view collections not linked to any scene, the "Blender File" display mode
can be used, with the new filtering option to just see Colleciton datablocks.
* The outliner right click menus for collections and objects were reorganized.
* Drag and drop still needs to be improved. Like before, dragging the icon or
text gives different results, we'll unify this later.
LINKING AND OVERRIDES
* Collections can now be linked into the scene without creating an instance,
with the link/append operator or from the collections view in the outliner.
* Collections can get static overrides with the right click menu in the outliner,
but this is rather unreliable and not clearly communicated at the moment.
* We still need to improve the make override operator to turn collection instances
into collections with overrides directly in the scene.
PERFORMANCE
* We tried to make performance not worse than before and improve it in some
cases. The main thing that's still a bit slower is multiple scenes, we have to
change the layer syncing to only updated affected scenes.
* Collections keep a list of their parent collections for faster incremental
updates in syncing and caching.
* View layer bases are now in a object -> base hash to avoid quadratic time
lookups internally and in API functions like visible_get().
VERSIONING
* Compatibility with 2.7 files should be improved due to the new visibility
controls. Of course users may not want to set up their scenes differently
now to avoid having separate layers and groups.
* Compatibility with 2.8 is mostly there, and was tested on Eevee demo and Hero
files. There's a few things which are know to be not quite compatible, like
nested layer collections inside groups.
* The versioning code for 2.8 files is quite complicated, and isolated behind
#ifdef so it can be removed at the end of the release cycle.
KNOWN ISSUES
* The G-key group operators in the 3D viewport were left mostly as is, they
need to be modified still to fit better.
* Same for the groups panel in the object properties. This needs to be updated
still, or perhaps replaced by something better.
* Collections must all have a unique name. Less restrictive namespacing is to
be done later, we'll have to see how important this is as all objects within
the collections must also have a unique name anyway.
* Full scene copy and delete scene are exactly doing the right thing yet.
Differential Revision: https://developer.blender.org/D3383
https://code.blender.org/2018/05/collections-and-groups/
2018-04-30 15:57:22 +02:00
|
|
|
if (ctx->collection) {
|
2018-06-08 19:26:46 +02:00
|
|
|
eEvaluationMode mode = DEG_get_mode(ctx->depsgraph);
|
|
|
|
|
FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN (ctx->collection, ob, mode) {
|
|
|
|
|
if ((ob != ctx->obedit) && is_child(ob, parent)) {
|
2016-08-14 15:33:21 +02:00
|
|
|
DupliContext pctx;
|
2021-12-15 15:46:27 +01:00
|
|
|
if (copy_dupli_context(&pctx, ctx, ctx->object, nullptr, _base_id)) {
|
|
|
|
|
/* Meta-balls have a different dupli handling. */
|
|
|
|
|
if (ob->type != OB_MBALL) {
|
|
|
|
|
ob->flag |= OB_DONE; /* Doesn't render. */
|
|
|
|
|
}
|
|
|
|
|
make_child_duplis_cb(&pctx, userdata, ob);
|
2022-11-22 15:38:19 -06:00
|
|
|
if (pctx.gen->type != GEOMETRY_SET_DUPLI_GENERATOR_TYPE) {
|
|
|
|
|
if (!ctx->dupli_gen_type_stack->is_empty()) {
|
|
|
|
|
ctx->dupli_gen_type_stack->remove_last();
|
|
|
|
|
}
|
2022-11-11 12:31:50 -06:00
|
|
|
}
|
2017-12-01 11:24:21 -02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2014-01-21 12:11:34 +01:00
|
|
|
}
|
2018-06-08 19:26:46 +02:00
|
|
|
FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END;
|
2014-01-21 12:11:34 +01:00
|
|
|
}
|
|
|
|
|
else {
|
2021-10-11 18:18:51 +02:00
|
|
|
/* FIXME: using a mere counter to generate a 'persistent' dupli id is very weak. One possible
|
2024-01-22 13:47:13 +01:00
|
|
|
* better solution could be to use `session_uid` of ID's instead? */
|
2021-10-11 18:18:51 +02:00
|
|
|
int persistent_dupli_id = 0;
|
2022-09-23 12:39:56 +02:00
|
|
|
DEGObjectIterSettings deg_iter_settings{};
|
|
|
|
|
deg_iter_settings.depsgraph = ctx->depsgraph;
|
2021-10-11 18:18:51 +02:00
|
|
|
/* NOTE: this set of flags ensure we only iterate over objects that have a base in either the
|
|
|
|
|
* current scene, or the set (background) scene. */
|
2022-09-23 12:39:56 +02:00
|
|
|
deg_iter_settings.flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
|
|
|
|
|
DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET;
|
|
|
|
|
DEG_OBJECT_ITER_BEGIN (°_iter_settings, ob) {
|
2018-02-13 20:35:29 +11:00
|
|
|
if ((ob != ctx->obedit) && is_child(ob, parent)) {
|
2016-08-14 15:33:21 +02:00
|
|
|
DupliContext pctx;
|
2021-12-15 15:46:27 +01:00
|
|
|
if (copy_dupli_context(&pctx, ctx, ctx->object, nullptr, persistent_dupli_id)) {
|
|
|
|
|
/* Meta-balls have a different dupli-handling. */
|
|
|
|
|
if (ob->type != OB_MBALL) {
|
|
|
|
|
ob->flag |= OB_DONE; /* Doesn't render. */
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-12-15 15:46:27 +01:00
|
|
|
make_child_duplis_cb(&pctx, userdata, ob);
|
2022-11-22 15:38:19 -06:00
|
|
|
if (pctx.gen->type != GEOMETRY_SET_DUPLI_GENERATOR_TYPE) {
|
|
|
|
|
if (!ctx->dupli_gen_type_stack->is_empty()) {
|
|
|
|
|
ctx->dupli_gen_type_stack->remove_last();
|
|
|
|
|
}
|
2022-11-11 12:31:50 -06:00
|
|
|
}
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2014-01-21 12:11:34 +01:00
|
|
|
}
|
2021-10-11 18:18:51 +02:00
|
|
|
persistent_dupli_id++;
|
2014-01-21 12:11:34 +01:00
|
|
|
}
|
2021-10-11 18:18:51 +02:00
|
|
|
DEG_OBJECT_ITER_END;
|
2014-01-21 12:11:34 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-10 18:29:17 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
2020-08-13 13:30:25 +10:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Internal Data Access Utilities
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2021-07-01 23:03:09 -05:00
|
|
|
static const Mesh *mesh_data_from_duplicator_object(Object *ob,
|
|
|
|
|
BMEditMesh **r_em,
|
|
|
|
|
const float (**r_vert_coords)[3],
|
|
|
|
|
const float (**r_vert_normals)[3])
|
2020-08-13 13:30:25 +10:00
|
|
|
{
|
|
|
|
|
/* Gather mesh info. */
|
|
|
|
|
BMEditMesh *em = BKE_editmesh_from_object(ob);
|
2021-07-01 23:03:09 -05:00
|
|
|
const Mesh *me_eval;
|
2020-08-13 13:30:25 +10:00
|
|
|
|
2021-04-01 15:54:48 -05:00
|
|
|
*r_em = nullptr;
|
|
|
|
|
*r_vert_coords = nullptr;
|
|
|
|
|
if (r_vert_normals != nullptr) {
|
|
|
|
|
*r_vert_normals = nullptr;
|
2020-08-13 13:56:15 +10:00
|
|
|
}
|
2020-08-13 13:30:25 +10:00
|
|
|
|
|
|
|
|
/* We do not need any render-specific handling anymore, depsgraph takes care of that. */
|
|
|
|
|
/* NOTE: Do direct access to the evaluated mesh: this function is used
|
|
|
|
|
* during meta balls evaluation. But even without those all the objects
|
|
|
|
|
* which are needed for correct instancing are already evaluated. */
|
2021-04-01 15:54:48 -05:00
|
|
|
if (em != nullptr) {
|
2020-08-13 13:30:25 +10:00
|
|
|
/* Note that this will only show deformation if #eModifierMode_OnCage is enabled.
|
|
|
|
|
* We could change this but it matches 2.7x behavior. */
|
2022-01-11 15:42:07 +01:00
|
|
|
me_eval = BKE_object_get_editmesh_eval_cage(ob);
|
2022-10-12 20:55:26 -05:00
|
|
|
if ((me_eval == nullptr) || (me_eval->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH)) {
|
2023-12-04 15:22:00 -05:00
|
|
|
blender::bke::EditMeshData *emd = me_eval ? me_eval->runtime->edit_data.get() : nullptr;
|
2020-08-13 13:56:15 +10:00
|
|
|
|
|
|
|
|
/* Only assign edit-mesh in the case we can't use `me_eval`. */
|
|
|
|
|
*r_em = em;
|
2021-04-01 15:54:48 -05:00
|
|
|
me_eval = nullptr;
|
2020-08-13 13:56:15 +10:00
|
|
|
|
2023-07-10 19:49:54 +02:00
|
|
|
if ((emd != nullptr) && !emd->vertexCos.is_empty()) {
|
|
|
|
|
*r_vert_coords = reinterpret_cast<const float(*)[3]>(emd->vertexCos.data());
|
2021-04-01 15:54:48 -05:00
|
|
|
if (r_vert_normals != nullptr) {
|
2023-12-04 15:22:00 -05:00
|
|
|
BKE_editmesh_cache_ensure_vert_normals(*em, *emd);
|
2023-07-10 19:49:54 +02:00
|
|
|
*r_vert_normals = reinterpret_cast<const float(*)[3]>(emd->vertexNos.data());
|
2020-08-13 13:56:15 +10:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-08-13 13:30:25 +10:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
me_eval = BKE_object_get_evaluated_mesh(ob);
|
|
|
|
|
}
|
|
|
|
|
return me_eval;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
2020-08-10 18:29:17 +10:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Dupli-Collection Implementation (#OB_DUPLICOLLECTION)
|
|
|
|
|
* \{ */
|
2014-01-21 12:11:34 +01:00
|
|
|
|
Collections and groups unification
OVERVIEW
* In 2.7 terminology, all layers and groups are now collection datablocks.
* These collections are nestable, linkable, instanceable, overrideable, ..
which opens up new ways to set up scenes and link + override data.
* Viewport/render visibility and selectability are now a part of the collection
and shared across all view layers and linkable.
* View layers define which subset of the scene collection hierarchy is excluded
for each. For many workflows one view layer can be used, these are more of an
advanced feature now.
OUTLINER
* The outliner now has a "View Layer" display mode instead of "Collections",
which can display the collections and/or objects in the view layer.
* In this display mode, collections can be excluded with the right click menu.
These will then be greyed out and their objects will be excluded.
* To view collections not linked to any scene, the "Blender File" display mode
can be used, with the new filtering option to just see Colleciton datablocks.
* The outliner right click menus for collections and objects were reorganized.
* Drag and drop still needs to be improved. Like before, dragging the icon or
text gives different results, we'll unify this later.
LINKING AND OVERRIDES
* Collections can now be linked into the scene without creating an instance,
with the link/append operator or from the collections view in the outliner.
* Collections can get static overrides with the right click menu in the outliner,
but this is rather unreliable and not clearly communicated at the moment.
* We still need to improve the make override operator to turn collection instances
into collections with overrides directly in the scene.
PERFORMANCE
* We tried to make performance not worse than before and improve it in some
cases. The main thing that's still a bit slower is multiple scenes, we have to
change the layer syncing to only updated affected scenes.
* Collections keep a list of their parent collections for faster incremental
updates in syncing and caching.
* View layer bases are now in a object -> base hash to avoid quadratic time
lookups internally and in API functions like visible_get().
VERSIONING
* Compatibility with 2.7 files should be improved due to the new visibility
controls. Of course users may not want to set up their scenes differently
now to avoid having separate layers and groups.
* Compatibility with 2.8 is mostly there, and was tested on Eevee demo and Hero
files. There's a few things which are know to be not quite compatible, like
nested layer collections inside groups.
* The versioning code for 2.8 files is quite complicated, and isolated behind
#ifdef so it can be removed at the end of the release cycle.
KNOWN ISSUES
* The G-key group operators in the 3D viewport were left mostly as is, they
need to be modified still to fit better.
* Same for the groups panel in the object properties. This needs to be updated
still, or perhaps replaced by something better.
* Collections must all have a unique name. Less restrictive namespacing is to
be done later, we'll have to see how important this is as all objects within
the collections must also have a unique name anyway.
* Full scene copy and delete scene are exactly doing the right thing yet.
Differential Revision: https://developer.blender.org/D3383
https://code.blender.org/2018/05/collections-and-groups/
2018-04-30 15:57:22 +02:00
|
|
|
static void make_duplis_collection(const DupliContext *ctx)
|
2014-01-21 12:11:34 +01:00
|
|
|
{
|
|
|
|
|
Object *ob = ctx->object;
|
Collections and groups unification
OVERVIEW
* In 2.7 terminology, all layers and groups are now collection datablocks.
* These collections are nestable, linkable, instanceable, overrideable, ..
which opens up new ways to set up scenes and link + override data.
* Viewport/render visibility and selectability are now a part of the collection
and shared across all view layers and linkable.
* View layers define which subset of the scene collection hierarchy is excluded
for each. For many workflows one view layer can be used, these are more of an
advanced feature now.
OUTLINER
* The outliner now has a "View Layer" display mode instead of "Collections",
which can display the collections and/or objects in the view layer.
* In this display mode, collections can be excluded with the right click menu.
These will then be greyed out and their objects will be excluded.
* To view collections not linked to any scene, the "Blender File" display mode
can be used, with the new filtering option to just see Colleciton datablocks.
* The outliner right click menus for collections and objects were reorganized.
* Drag and drop still needs to be improved. Like before, dragging the icon or
text gives different results, we'll unify this later.
LINKING AND OVERRIDES
* Collections can now be linked into the scene without creating an instance,
with the link/append operator or from the collections view in the outliner.
* Collections can get static overrides with the right click menu in the outliner,
but this is rather unreliable and not clearly communicated at the moment.
* We still need to improve the make override operator to turn collection instances
into collections with overrides directly in the scene.
PERFORMANCE
* We tried to make performance not worse than before and improve it in some
cases. The main thing that's still a bit slower is multiple scenes, we have to
change the layer syncing to only updated affected scenes.
* Collections keep a list of their parent collections for faster incremental
updates in syncing and caching.
* View layer bases are now in a object -> base hash to avoid quadratic time
lookups internally and in API functions like visible_get().
VERSIONING
* Compatibility with 2.7 files should be improved due to the new visibility
controls. Of course users may not want to set up their scenes differently
now to avoid having separate layers and groups.
* Compatibility with 2.8 is mostly there, and was tested on Eevee demo and Hero
files. There's a few things which are know to be not quite compatible, like
nested layer collections inside groups.
* The versioning code for 2.8 files is quite complicated, and isolated behind
#ifdef so it can be removed at the end of the release cycle.
KNOWN ISSUES
* The G-key group operators in the 3D viewport were left mostly as is, they
need to be modified still to fit better.
* Same for the groups panel in the object properties. This needs to be updated
still, or perhaps replaced by something better.
* Collections must all have a unique name. Less restrictive namespacing is to
be done later, we'll have to see how important this is as all objects within
the collections must also have a unique name anyway.
* Full scene copy and delete scene are exactly doing the right thing yet.
Differential Revision: https://developer.blender.org/D3383
https://code.blender.org/2018/05/collections-and-groups/
2018-04-30 15:57:22 +02:00
|
|
|
Collection *collection;
|
|
|
|
|
float collection_mat[4][4];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-04-01 15:54:48 -05:00
|
|
|
if (ob->instance_collection == nullptr) {
|
2019-02-17 19:00:54 +11:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-02-17 19:00:54 +11:00
|
|
|
collection = ob->instance_collection;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Combine collection offset and `obmat`. */
|
Collections and groups unification
OVERVIEW
* In 2.7 terminology, all layers and groups are now collection datablocks.
* These collections are nestable, linkable, instanceable, overrideable, ..
which opens up new ways to set up scenes and link + override data.
* Viewport/render visibility and selectability are now a part of the collection
and shared across all view layers and linkable.
* View layers define which subset of the scene collection hierarchy is excluded
for each. For many workflows one view layer can be used, these are more of an
advanced feature now.
OUTLINER
* The outliner now has a "View Layer" display mode instead of "Collections",
which can display the collections and/or objects in the view layer.
* In this display mode, collections can be excluded with the right click menu.
These will then be greyed out and their objects will be excluded.
* To view collections not linked to any scene, the "Blender File" display mode
can be used, with the new filtering option to just see Colleciton datablocks.
* The outliner right click menus for collections and objects were reorganized.
* Drag and drop still needs to be improved. Like before, dragging the icon or
text gives different results, we'll unify this later.
LINKING AND OVERRIDES
* Collections can now be linked into the scene without creating an instance,
with the link/append operator or from the collections view in the outliner.
* Collections can get static overrides with the right click menu in the outliner,
but this is rather unreliable and not clearly communicated at the moment.
* We still need to improve the make override operator to turn collection instances
into collections with overrides directly in the scene.
PERFORMANCE
* We tried to make performance not worse than before and improve it in some
cases. The main thing that's still a bit slower is multiple scenes, we have to
change the layer syncing to only updated affected scenes.
* Collections keep a list of their parent collections for faster incremental
updates in syncing and caching.
* View layer bases are now in a object -> base hash to avoid quadratic time
lookups internally and in API functions like visible_get().
VERSIONING
* Compatibility with 2.7 files should be improved due to the new visibility
controls. Of course users may not want to set up their scenes differently
now to avoid having separate layers and groups.
* Compatibility with 2.8 is mostly there, and was tested on Eevee demo and Hero
files. There's a few things which are know to be not quite compatible, like
nested layer collections inside groups.
* The versioning code for 2.8 files is quite complicated, and isolated behind
#ifdef so it can be removed at the end of the release cycle.
KNOWN ISSUES
* The G-key group operators in the 3D viewport were left mostly as is, they
need to be modified still to fit better.
* Same for the groups panel in the object properties. This needs to be updated
still, or perhaps replaced by something better.
* Collections must all have a unique name. Less restrictive namespacing is to
be done later, we'll have to see how important this is as all objects within
the collections must also have a unique name anyway.
* Full scene copy and delete scene are exactly doing the right thing yet.
Differential Revision: https://developer.blender.org/D3383
https://code.blender.org/2018/05/collections-and-groups/
2018-04-30 15:57:22 +02:00
|
|
|
unit_m4(collection_mat);
|
2019-02-18 10:38:34 +11:00
|
|
|
sub_v3_v3(collection_mat[3], collection->instance_offset);
|
2024-02-19 15:54:48 +01:00
|
|
|
mul_m4_m4m4(collection_mat, ob->object_to_world, collection_mat);
|
|
|
|
|
/* Don't access 'ob->object_to_world' from now on. */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-06-08 19:26:46 +02:00
|
|
|
eEvaluationMode mode = DEG_get_mode(ctx->depsgraph);
|
|
|
|
|
FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN (collection, cob, mode) {
|
|
|
|
|
if (cob != ob) {
|
2014-01-21 12:11:34 +01:00
|
|
|
float mat[4][4];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Collection dupli-offset, should apply after everything else. */
|
2024-02-19 15:54:48 +01:00
|
|
|
mul_m4_m4m4(mat, collection_mat, cob->object_to_world);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-06-08 19:26:46 +02:00
|
|
|
make_dupli(ctx, cob, mat, _base_id);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Recursion. */
|
2018-06-08 19:26:46 +02:00
|
|
|
make_recursive_duplis(ctx, cob, collection_mat, _base_id);
|
2014-01-21 12:11:34 +01:00
|
|
|
}
|
|
|
|
|
}
|
2018-06-08 19:26:46 +02:00
|
|
|
FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END;
|
2014-01-21 12:11:34 +01:00
|
|
|
}
|
|
|
|
|
|
Collections and groups unification
OVERVIEW
* In 2.7 terminology, all layers and groups are now collection datablocks.
* These collections are nestable, linkable, instanceable, overrideable, ..
which opens up new ways to set up scenes and link + override data.
* Viewport/render visibility and selectability are now a part of the collection
and shared across all view layers and linkable.
* View layers define which subset of the scene collection hierarchy is excluded
for each. For many workflows one view layer can be used, these are more of an
advanced feature now.
OUTLINER
* The outliner now has a "View Layer" display mode instead of "Collections",
which can display the collections and/or objects in the view layer.
* In this display mode, collections can be excluded with the right click menu.
These will then be greyed out and their objects will be excluded.
* To view collections not linked to any scene, the "Blender File" display mode
can be used, with the new filtering option to just see Colleciton datablocks.
* The outliner right click menus for collections and objects were reorganized.
* Drag and drop still needs to be improved. Like before, dragging the icon or
text gives different results, we'll unify this later.
LINKING AND OVERRIDES
* Collections can now be linked into the scene without creating an instance,
with the link/append operator or from the collections view in the outliner.
* Collections can get static overrides with the right click menu in the outliner,
but this is rather unreliable and not clearly communicated at the moment.
* We still need to improve the make override operator to turn collection instances
into collections with overrides directly in the scene.
PERFORMANCE
* We tried to make performance not worse than before and improve it in some
cases. The main thing that's still a bit slower is multiple scenes, we have to
change the layer syncing to only updated affected scenes.
* Collections keep a list of their parent collections for faster incremental
updates in syncing and caching.
* View layer bases are now in a object -> base hash to avoid quadratic time
lookups internally and in API functions like visible_get().
VERSIONING
* Compatibility with 2.7 files should be improved due to the new visibility
controls. Of course users may not want to set up their scenes differently
now to avoid having separate layers and groups.
* Compatibility with 2.8 is mostly there, and was tested on Eevee demo and Hero
files. There's a few things which are know to be not quite compatible, like
nested layer collections inside groups.
* The versioning code for 2.8 files is quite complicated, and isolated behind
#ifdef so it can be removed at the end of the release cycle.
KNOWN ISSUES
* The G-key group operators in the 3D viewport were left mostly as is, they
need to be modified still to fit better.
* Same for the groups panel in the object properties. This needs to be updated
still, or perhaps replaced by something better.
* Collections must all have a unique name. Less restrictive namespacing is to
be done later, we'll have to see how important this is as all objects within
the collections must also have a unique name anyway.
* Full scene copy and delete scene are exactly doing the right thing yet.
Differential Revision: https://developer.blender.org/D3383
https://code.blender.org/2018/05/collections-and-groups/
2018-04-30 15:57:22 +02:00
|
|
|
static const DupliGenerator gen_dupli_collection = {
|
2023-01-16 12:41:11 +11:00
|
|
|
/*type*/ OB_DUPLICOLLECTION,
|
|
|
|
|
/*make_duplis*/ make_duplis_collection};
|
2014-01-21 12:11:34 +01:00
|
|
|
|
2020-08-10 18:29:17 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Dupli-Vertices Implementation (#OB_DUPLIVERTS for Geometry)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2020-08-13 13:56:15 +10:00
|
|
|
/** Values shared between different mesh types. */
|
2021-04-01 15:54:48 -05:00
|
|
|
struct VertexDupliData_Params {
|
2020-08-13 13:56:15 +10:00
|
|
|
/**
|
|
|
|
|
* It's important we use this context instead of the `ctx` passed into #make_child_duplis
|
|
|
|
|
* since these won't match in the case of recursion.
|
|
|
|
|
*/
|
|
|
|
|
const DupliContext *ctx;
|
|
|
|
|
|
|
|
|
|
bool use_rotation;
|
2021-04-01 15:54:48 -05:00
|
|
|
};
|
2020-08-13 13:56:15 +10:00
|
|
|
|
2021-04-01 15:54:48 -05:00
|
|
|
struct VertexDupliData_Mesh {
|
2020-08-13 13:56:15 +10:00
|
|
|
VertexDupliData_Params params;
|
|
|
|
|
|
2014-01-21 12:11:34 +01:00
|
|
|
int totvert;
|
Mesh: Move positions to a generic attribute
**Changes**
As described in T93602, this patch removes all use of the `MVert`
struct, replacing it with a generic named attribute with the name
`"position"`, consistent with other geometry types.
Variable names have been changed from `verts` to `positions`, to align
with the attribute name and the more generic design (positions are not
vertices, they are just an attribute stored on the point domain).
This change is made possible by previous commits that moved all other
data out of `MVert` to runtime data or other generic attributes. What
remains is mostly a simple type change. Though, the type still shows up
859 times, so the patch is quite large.
One compromise is that now `CD_MASK_BAREMESH` now contains
`CD_PROP_FLOAT3`. With the general move towards generic attributes
over custom data types, we are removing use of these type masks anyway.
**Benefits**
The most obvious benefit is reduced memory usage and the benefits
that brings in memory-bound situations. `float3` is only 3 bytes, in
comparison to `MVert` which was 4. When there are millions of vertices
this starts to matter more.
The other benefits come from using a more generic type. Instead of
writing algorithms specifically for `MVert`, code can just use arrays
of vectors. This will allow eliminating many temporary arrays or
wrappers used to extract positions.
Many possible improvements aren't implemented in this patch, though
I did switch simplify or remove the process of creating temporary
position arrays in a few places.
The design clarity that "positions are just another attribute" brings
allows removing explicit copying of vertices in some procedural
operations-- they are just processed like most other attributes.
**Performance**
This touches so many areas that it's hard to benchmark exhaustively,
but I observed some areas as examples.
* The mesh line node with 4 million count was 1.5x (8ms to 12ms) faster.
* The Spring splash screen went from ~4.3 to ~4.5 fps.
* The subdivision surface modifier/node was slightly faster
RNA access through Python may be slightly slower, since now we need
a name lookup instead of just a custom data type lookup for each index.
**Future Improvements**
* Remove uses of "vert_coords" functions:
* `BKE_mesh_vert_coords_alloc`
* `BKE_mesh_vert_coords_get`
* `BKE_mesh_vert_coords_apply{_with_mat4}`
* Remove more hidden copying of positions
* General simplification now possible in many areas
* Convert more code to C++ to use `float3` instead of `float[3]`
* Currently `reinterpret_cast` is used for those C-API functions
Differential Revision: https://developer.blender.org/D15982
2023-01-10 00:10:43 -05:00
|
|
|
Span<float3> vert_positions;
|
2023-03-15 14:00:40 -04:00
|
|
|
Span<float3> vert_normals;
|
2020-08-13 13:31:29 +10:00
|
|
|
|
2020-08-13 09:28:29 +10:00
|
|
|
const float (*orco)[3];
|
2021-04-01 15:54:48 -05:00
|
|
|
};
|
2020-08-11 15:26:14 +10:00
|
|
|
|
2021-04-01 15:54:48 -05:00
|
|
|
struct VertexDupliData_EditMesh {
|
2020-08-13 13:56:15 +10:00
|
|
|
VertexDupliData_Params params;
|
|
|
|
|
|
|
|
|
|
BMEditMesh *em;
|
|
|
|
|
|
2021-04-01 15:54:48 -05:00
|
|
|
/* Can be nullptr. */
|
2023-01-10 16:39:53 +11:00
|
|
|
const float (*vert_positions_deform)[3];
|
|
|
|
|
const float (*vert_normals_deform)[3];
|
2020-08-13 13:56:15 +10:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \note The edit-mesh may assign #DupliObject.orco in cases when a regular mesh wouldn't.
|
|
|
|
|
* For edit-meshes we only check for deformation, for regular meshes we check if #CD_ORCO exists.
|
|
|
|
|
*
|
|
|
|
|
* At the moment this isn't a meaningful difference since requesting #CD_ORCO causes the
|
|
|
|
|
* edit-mesh to be converted into a mesh.
|
|
|
|
|
*/
|
|
|
|
|
bool has_orco;
|
2021-04-01 15:54:48 -05:00
|
|
|
};
|
2014-01-21 12:11:34 +01:00
|
|
|
|
2020-08-13 10:09:39 +10:00
|
|
|
/**
|
|
|
|
|
* \param no: The direction,
|
|
|
|
|
* currently this is copied from a `short[3]` normal without division.
|
2020-08-13 13:56:15 +10:00
|
|
|
* Can be null when \a use_rotation is false.
|
2020-08-13 10:09:39 +10:00
|
|
|
*/
|
2019-03-28 14:44:12 +01:00
|
|
|
static void get_duplivert_transform(const float co[3],
|
2020-08-13 10:09:39 +10:00
|
|
|
const float no[3],
|
2020-08-13 09:28:29 +10:00
|
|
|
const bool use_rotation,
|
|
|
|
|
const short axis,
|
|
|
|
|
const short upflag,
|
|
|
|
|
float r_mat[4][4])
|
2014-01-21 12:11:34 +01:00
|
|
|
{
|
|
|
|
|
float quat[4];
|
|
|
|
|
const float size[3] = {1.0f, 1.0f, 1.0f};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-01-21 12:11:34 +01:00
|
|
|
if (use_rotation) {
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Construct rotation matrix from normals. */
|
2020-08-13 10:09:39 +10:00
|
|
|
float no_flip[3];
|
|
|
|
|
negate_v3_v3(no_flip, no);
|
|
|
|
|
vec_to_quat(quat, no_flip, axis, upflag);
|
2014-01-21 12:11:34 +01:00
|
|
|
}
|
2019-04-22 09:39:35 +10:00
|
|
|
else {
|
2014-01-21 12:11:34 +01:00
|
|
|
unit_qt(quat);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-13 09:28:29 +10:00
|
|
|
loc_quat_size_to_mat4(r_mat, co, quat, size);
|
2014-01-21 12:11:34 +01:00
|
|
|
}
|
|
|
|
|
|
2020-08-13 13:56:15 +10:00
|
|
|
static DupliObject *vertex_dupli(const DupliContext *ctx,
|
|
|
|
|
Object *inst_ob,
|
|
|
|
|
const float child_imat[4][4],
|
|
|
|
|
int index,
|
|
|
|
|
const float co[3],
|
|
|
|
|
const float no[3],
|
|
|
|
|
const bool use_rotation)
|
2014-01-21 12:11:34 +01:00
|
|
|
{
|
2020-08-13 09:49:49 +10:00
|
|
|
/* `obmat` is transform to vertex. */
|
2020-08-13 13:56:15 +10:00
|
|
|
float obmat[4][4];
|
|
|
|
|
get_duplivert_transform(co, no, use_rotation, inst_ob->trackflag, inst_ob->upflag, obmat);
|
|
|
|
|
|
|
|
|
|
float space_mat[4][4];
|
|
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Make offset relative to inst_ob using relative child transform. */
|
2020-08-13 13:56:15 +10:00
|
|
|
mul_mat3_m4_v3(child_imat, obmat[3]);
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Apply `obmat` _after_ the local vertex transform. */
|
2024-02-19 15:54:48 +01:00
|
|
|
mul_m4_m4m4(obmat, inst_ob->object_to_world, obmat);
|
2014-01-21 12:11:34 +01:00
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Space matrix is constructed by removing `obmat` transform,
|
|
|
|
|
* this yields the world-space transform for recursive duplis. */
|
2024-02-19 15:54:48 +01:00
|
|
|
mul_m4_m4m4(space_mat, obmat, inst_ob->world_to_object);
|
2014-01-21 12:11:34 +01:00
|
|
|
|
2020-08-13 13:56:15 +10:00
|
|
|
DupliObject *dob = make_dupli(ctx, inst_ob, obmat, index);
|
2014-01-21 12:11:34 +01:00
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Recursion. */
|
2020-08-13 13:56:15 +10:00
|
|
|
make_recursive_duplis(ctx, inst_ob, space_mat, index);
|
|
|
|
|
|
|
|
|
|
return dob;
|
2014-01-21 12:11:34 +01:00
|
|
|
}
|
|
|
|
|
|
2020-08-13 13:56:15 +10:00
|
|
|
static void make_child_duplis_verts_from_mesh(const DupliContext *ctx,
|
|
|
|
|
void *userdata,
|
|
|
|
|
Object *inst_ob)
|
2014-01-21 12:11:34 +01:00
|
|
|
{
|
2021-04-01 15:54:48 -05:00
|
|
|
VertexDupliData_Mesh *vdd = (VertexDupliData_Mesh *)userdata;
|
2020-08-13 13:56:15 +10:00
|
|
|
const bool use_rotation = vdd->params.use_rotation;
|
|
|
|
|
|
|
|
|
|
const int totvert = vdd->totvert;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-02-19 15:54:48 +01:00
|
|
|
invert_m4_m4(inst_ob->world_to_object, inst_ob->object_to_world);
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Relative transform from parent to child space. */
|
2020-08-13 13:56:15 +10:00
|
|
|
float child_imat[4][4];
|
2024-02-19 15:54:48 +01:00
|
|
|
mul_m4_m4m4(child_imat, inst_ob->world_to_object, ctx->object->object_to_world);
|
2020-08-11 16:12:44 +02:00
|
|
|
|
Refactor: Move normals out of MVert, lazy calculation
As described in T91186, this commit moves mesh vertex normals into a
contiguous array of float vectors in a custom data layer, how face
normals are currently stored.
The main interface is documented in `BKE_mesh.h`. Vertex and face
normals are now calculated on-demand and cached, retrieved with an
"ensure" function. Since the logical state of a mesh is now "has
normals when necessary", they can be retrieved from a `const` mesh.
The goal is to use on-demand calculation for all derived data, but
leave room for eager calculation for performance purposes (modifier
evaluation is threaded, but viewport data generation is not).
**Benefits**
This moves us closer to a SoA approach rather than the current AoS
paradigm. Accessing a contiguous `float3` is much more efficient than
retrieving data from a larger struct. The memory requirements for
accessing only normals or vertex locations are smaller, and at the
cost of more memory usage for just normals, they now don't have to
be converted between float and short, which also simplifies code
In the future, the remaining items can be removed from `MVert`,
leaving only `float3`, which has similar benefits (see T93602).
Removing the combination of derived and original data makes it
conceptually simpler to only calculate normals when necessary.
This is especially important now that we have more opportunities
for temporary meshes in geometry nodes.
**Performance**
In addition to the theoretical future performance improvements by
making `MVert == float3`, I've done some basic performance testing
on this patch directly. The data is fairly rough, but it gives an idea
about where things stand generally.
- Mesh line primitive 4m Verts: 1.16x faster (36 -> 31 ms),
showing that accessing just `MVert` is now more efficient.
- Spring Splash Screen: 1.03-1.06 -> 1.06-1.11 FPS, a very slight
change that at least shows there is no regression.
- Sprite Fright Snail Smoosh: 3.30-3.40 -> 3.42-3.50 FPS, a small
but observable speedup.
- Set Position Node with Scaled Normal: 1.36x faster (53 -> 39 ms),
shows that using normals in geometry nodes is faster.
- Normal Calculation 1.6m Vert Cube: 1.19x faster (25 -> 21 ms),
shows that calculating normals is slightly faster now.
- File Size of 1.6m Vert Cube: 1.03x smaller (214.7 -> 208.4 MB),
Normals are not saved in files, which can help with large meshes.
As for memory usage, it may be slightly more in some cases, but
I didn't observe any difference in the production files I tested.
**Tests**
Some modifiers and cycles test results need to be updated with this
commit, for two reasons:
- The subdivision surface modifier is not responsible for calculating
normals anymore. In master, the modifier creates different normals
than the result of the `Mesh` normal calculation, so this is a bug
fix.
- There are small differences in the results of some modifiers that
use normals because they are not converted to and from `short`
anymore.
**Future improvements**
- Remove `ModifierTypeInfo::dependsOnNormals`. Code in each modifier
already retrieves normals if they are needed anyway.
- Copy normals as part of a better CoW system for attributes.
- Make more areas use lazy instead of eager normal calculation.
- Remove `BKE_mesh_normals_tag_dirty` in more places since that is
now the default state of a new mesh.
- Possibly apply a similar change to derived face corner normals.
Differential Revision: https://developer.blender.org/D12770
2022-01-13 14:37:58 -06:00
|
|
|
for (int i = 0; i < totvert; i++) {
|
Mesh: Move positions to a generic attribute
**Changes**
As described in T93602, this patch removes all use of the `MVert`
struct, replacing it with a generic named attribute with the name
`"position"`, consistent with other geometry types.
Variable names have been changed from `verts` to `positions`, to align
with the attribute name and the more generic design (positions are not
vertices, they are just an attribute stored on the point domain).
This change is made possible by previous commits that moved all other
data out of `MVert` to runtime data or other generic attributes. What
remains is mostly a simple type change. Though, the type still shows up
859 times, so the patch is quite large.
One compromise is that now `CD_MASK_BAREMESH` now contains
`CD_PROP_FLOAT3`. With the general move towards generic attributes
over custom data types, we are removing use of these type masks anyway.
**Benefits**
The most obvious benefit is reduced memory usage and the benefits
that brings in memory-bound situations. `float3` is only 3 bytes, in
comparison to `MVert` which was 4. When there are millions of vertices
this starts to matter more.
The other benefits come from using a more generic type. Instead of
writing algorithms specifically for `MVert`, code can just use arrays
of vectors. This will allow eliminating many temporary arrays or
wrappers used to extract positions.
Many possible improvements aren't implemented in this patch, though
I did switch simplify or remove the process of creating temporary
position arrays in a few places.
The design clarity that "positions are just another attribute" brings
allows removing explicit copying of vertices in some procedural
operations-- they are just processed like most other attributes.
**Performance**
This touches so many areas that it's hard to benchmark exhaustively,
but I observed some areas as examples.
* The mesh line node with 4 million count was 1.5x (8ms to 12ms) faster.
* The Spring splash screen went from ~4.3 to ~4.5 fps.
* The subdivision surface modifier/node was slightly faster
RNA access through Python may be slightly slower, since now we need
a name lookup instead of just a custom data type lookup for each index.
**Future Improvements**
* Remove uses of "vert_coords" functions:
* `BKE_mesh_vert_coords_alloc`
* `BKE_mesh_vert_coords_get`
* `BKE_mesh_vert_coords_apply{_with_mat4}`
* Remove more hidden copying of positions
* General simplification now possible in many areas
* Convert more code to C++ to use `float3` instead of `float[3]`
* Currently `reinterpret_cast` is used for those C-API functions
Differential Revision: https://developer.blender.org/D15982
2023-01-10 00:10:43 -05:00
|
|
|
DupliObject *dob = vertex_dupli(vdd->params.ctx,
|
|
|
|
|
inst_ob,
|
|
|
|
|
child_imat,
|
|
|
|
|
i,
|
|
|
|
|
vdd->vert_positions[i],
|
|
|
|
|
vdd->vert_normals[i],
|
|
|
|
|
use_rotation);
|
2020-08-13 13:56:15 +10:00
|
|
|
if (vdd->orco) {
|
|
|
|
|
copy_v3_v3(dob->orco, vdd->orco[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-01-21 12:11:34 +01:00
|
|
|
}
|
|
|
|
|
|
2020-08-13 13:56:15 +10:00
|
|
|
static void make_child_duplis_verts_from_editmesh(const DupliContext *ctx,
|
|
|
|
|
void *userdata,
|
|
|
|
|
Object *inst_ob)
|
2014-01-21 12:11:34 +01:00
|
|
|
{
|
2021-04-01 15:54:48 -05:00
|
|
|
VertexDupliData_EditMesh *vdd = (VertexDupliData_EditMesh *)userdata;
|
2020-08-13 13:56:15 +10:00
|
|
|
BMEditMesh *em = vdd->em;
|
|
|
|
|
const bool use_rotation = vdd->params.use_rotation;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-02-19 15:54:48 +01:00
|
|
|
invert_m4_m4(inst_ob->world_to_object, inst_ob->object_to_world);
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Relative transform from parent to child space. */
|
2020-08-13 13:56:15 +10:00
|
|
|
float child_imat[4][4];
|
2024-02-19 15:54:48 +01:00
|
|
|
mul_m4_m4m4(child_imat, inst_ob->world_to_object, ctx->object->object_to_world);
|
2020-08-13 13:56:15 +10:00
|
|
|
|
|
|
|
|
BMVert *v;
|
|
|
|
|
BMIter iter;
|
|
|
|
|
int i;
|
|
|
|
|
|
2023-01-10 16:39:53 +11:00
|
|
|
const float(*vert_positions_deform)[3] = vdd->vert_positions_deform;
|
|
|
|
|
const float(*vert_normals_deform)[3] = vdd->vert_normals_deform;
|
2020-08-13 13:56:15 +10:00
|
|
|
|
|
|
|
|
BM_ITER_MESH_INDEX (v, &iter, em->bm, BM_VERTS_OF_MESH, i) {
|
|
|
|
|
const float *co, *no;
|
2023-01-10 16:39:53 +11:00
|
|
|
if (vert_positions_deform != nullptr) {
|
|
|
|
|
co = vert_positions_deform[i];
|
|
|
|
|
no = vert_normals_deform ? vert_normals_deform[i] : nullptr;
|
2020-08-13 13:56:15 +10:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
co = v->co;
|
|
|
|
|
no = v->no;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-13 13:56:15 +10:00
|
|
|
DupliObject *dob = vertex_dupli(vdd->params.ctx, inst_ob, child_imat, i, co, no, use_rotation);
|
|
|
|
|
if (vdd->has_orco) {
|
|
|
|
|
copy_v3_v3(dob->orco, v->co);
|
|
|
|
|
}
|
2019-03-28 14:44:12 +01:00
|
|
|
}
|
2014-01-21 12:11:34 +01:00
|
|
|
}
|
|
|
|
|
|
2020-08-11 16:12:44 +02:00
|
|
|
static void make_duplis_verts(const DupliContext *ctx)
|
2014-01-21 12:11:34 +01:00
|
|
|
{
|
2020-08-11 16:12:44 +02:00
|
|
|
Object *parent = ctx->object;
|
2020-08-13 13:56:15 +10:00
|
|
|
const bool use_rotation = parent->transflag & OB_DUPLIROT;
|
2020-08-11 15:26:14 +10:00
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Gather mesh info. */
|
2021-04-01 15:54:48 -05:00
|
|
|
BMEditMesh *em = nullptr;
|
2023-01-10 16:39:53 +11:00
|
|
|
const float(*vert_positions_deform)[3] = nullptr;
|
|
|
|
|
const float(*vert_normals_deform)[3] = nullptr;
|
2021-07-01 23:03:09 -05:00
|
|
|
const Mesh *me_eval = mesh_data_from_duplicator_object(
|
2023-01-10 16:39:53 +11:00
|
|
|
parent, &em, &vert_positions_deform, use_rotation ? &vert_normals_deform : nullptr);
|
2021-04-01 15:54:48 -05:00
|
|
|
if (em == nullptr && me_eval == nullptr) {
|
2020-08-13 13:30:25 +10:00
|
|
|
return;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-04-01 15:54:48 -05:00
|
|
|
VertexDupliData_Params vdd_params{ctx, use_rotation};
|
|
|
|
|
|
|
|
|
|
if (em != nullptr) {
|
|
|
|
|
VertexDupliData_EditMesh vdd{};
|
|
|
|
|
vdd.params = vdd_params;
|
|
|
|
|
vdd.em = em;
|
2023-01-10 16:39:53 +11:00
|
|
|
vdd.vert_positions_deform = vert_positions_deform;
|
|
|
|
|
vdd.vert_normals_deform = vert_normals_deform;
|
|
|
|
|
vdd.has_orco = (vert_positions_deform != nullptr);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-13 13:56:15 +10:00
|
|
|
make_child_duplis(ctx, &vdd, make_child_duplis_verts_from_editmesh);
|
|
|
|
|
}
|
|
|
|
|
else {
|
2021-04-01 15:54:48 -05:00
|
|
|
VertexDupliData_Mesh vdd{};
|
|
|
|
|
vdd.params = vdd_params;
|
2023-12-20 02:21:48 +01:00
|
|
|
vdd.totvert = me_eval->verts_num;
|
Mesh: Move positions to a generic attribute
**Changes**
As described in T93602, this patch removes all use of the `MVert`
struct, replacing it with a generic named attribute with the name
`"position"`, consistent with other geometry types.
Variable names have been changed from `verts` to `positions`, to align
with the attribute name and the more generic design (positions are not
vertices, they are just an attribute stored on the point domain).
This change is made possible by previous commits that moved all other
data out of `MVert` to runtime data or other generic attributes. What
remains is mostly a simple type change. Though, the type still shows up
859 times, so the patch is quite large.
One compromise is that now `CD_MASK_BAREMESH` now contains
`CD_PROP_FLOAT3`. With the general move towards generic attributes
over custom data types, we are removing use of these type masks anyway.
**Benefits**
The most obvious benefit is reduced memory usage and the benefits
that brings in memory-bound situations. `float3` is only 3 bytes, in
comparison to `MVert` which was 4. When there are millions of vertices
this starts to matter more.
The other benefits come from using a more generic type. Instead of
writing algorithms specifically for `MVert`, code can just use arrays
of vectors. This will allow eliminating many temporary arrays or
wrappers used to extract positions.
Many possible improvements aren't implemented in this patch, though
I did switch simplify or remove the process of creating temporary
position arrays in a few places.
The design clarity that "positions are just another attribute" brings
allows removing explicit copying of vertices in some procedural
operations-- they are just processed like most other attributes.
**Performance**
This touches so many areas that it's hard to benchmark exhaustively,
but I observed some areas as examples.
* The mesh line node with 4 million count was 1.5x (8ms to 12ms) faster.
* The Spring splash screen went from ~4.3 to ~4.5 fps.
* The subdivision surface modifier/node was slightly faster
RNA access through Python may be slightly slower, since now we need
a name lookup instead of just a custom data type lookup for each index.
**Future Improvements**
* Remove uses of "vert_coords" functions:
* `BKE_mesh_vert_coords_alloc`
* `BKE_mesh_vert_coords_get`
* `BKE_mesh_vert_coords_apply{_with_mat4}`
* Remove more hidden copying of positions
* General simplification now possible in many areas
* Convert more code to C++ to use `float3` instead of `float[3]`
* Currently `reinterpret_cast` is used for those C-API functions
Differential Revision: https://developer.blender.org/D15982
2023-01-10 00:10:43 -05:00
|
|
|
vdd.vert_positions = me_eval->vert_positions();
|
2023-03-15 14:00:40 -04:00
|
|
|
vdd.vert_normals = me_eval->vert_normals();
|
2023-07-25 21:15:52 +02:00
|
|
|
vdd.orco = (const float(*)[3])CustomData_get_layer(&me_eval->vert_data, CD_ORCO);
|
2021-04-01 15:54:48 -05:00
|
|
|
|
2020-08-13 13:56:15 +10:00
|
|
|
make_child_duplis(ctx, &vdd, make_child_duplis_verts_from_mesh);
|
|
|
|
|
}
|
2014-01-21 12:11:34 +01:00
|
|
|
}
|
|
|
|
|
|
2017-08-01 09:06:34 +10:00
|
|
|
static const DupliGenerator gen_dupli_verts = {
|
2023-01-16 12:41:11 +11:00
|
|
|
/*type*/ OB_DUPLIVERTS,
|
|
|
|
|
/*make_duplis*/ make_duplis_verts};
|
2014-01-21 12:11:34 +01:00
|
|
|
|
2020-08-10 18:29:17 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Dupli-Vertices Implementation (#OB_DUPLIVERTS for 3D Text)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2018-06-12 15:16:45 +02:00
|
|
|
static Object *find_family_object(
|
2022-09-25 17:04:52 +10:00
|
|
|
Main *bmain, const char *family, size_t family_len, uint ch, GHash *family_gh)
|
2014-01-21 12:11:34 +01:00
|
|
|
{
|
2018-09-19 12:05:58 +10:00
|
|
|
void *ch_key = POINTER_FROM_UINT(ch);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-04-01 15:54:48 -05:00
|
|
|
Object **ob_pt;
|
2014-01-21 12:11:34 +01:00
|
|
|
if ((ob_pt = (Object **)BLI_ghash_lookup_p(family_gh, ch_key))) {
|
2021-04-01 15:54:48 -05:00
|
|
|
return *ob_pt;
|
2014-01-21 12:11:34 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-08-28 22:44:55 +10:00
|
|
|
char ch_utf8[BLI_UTF8_MAX + 1];
|
2021-04-01 15:54:48 -05:00
|
|
|
size_t ch_utf8_len;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-08-28 22:44:55 +10:00
|
|
|
ch_utf8_len = BLI_str_utf8_from_unicode(ch, ch_utf8, sizeof(ch_utf8) - 1);
|
2021-04-01 15:54:48 -05:00
|
|
|
ch_utf8[ch_utf8_len] = '\0';
|
|
|
|
|
ch_utf8_len += 1; /* Compare with null terminator. */
|
|
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
|
|
|
|
|
if (STREQLEN(ob->id.name + 2 + family_len, ch_utf8, ch_utf8_len)) {
|
|
|
|
|
if (STREQLEN(ob->id.name + 2, family, family_len)) {
|
|
|
|
|
/* Inserted value can be nullptr, just to save searches in future. */
|
|
|
|
|
BLI_ghash_insert(family_gh, ch_key, ob);
|
|
|
|
|
return ob;
|
2014-01-21 12:11:34 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-04-01 15:54:48 -05:00
|
|
|
return nullptr;
|
2014-01-21 12:11:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void make_duplis_font(const DupliContext *ctx)
|
|
|
|
|
{
|
|
|
|
|
Object *par = ctx->object;
|
|
|
|
|
GHash *family_gh;
|
|
|
|
|
Object *ob;
|
|
|
|
|
Curve *cu;
|
2023-06-03 08:36:28 +10:00
|
|
|
CharTrans *ct, *chartransdata = nullptr;
|
2014-01-21 12:11:34 +01:00
|
|
|
float vec[3], obmat[4][4], pmat[4][4], fsize, xof, yof;
|
|
|
|
|
int text_len, a;
|
|
|
|
|
size_t family_len;
|
2021-04-01 15:54:48 -05:00
|
|
|
const char32_t *text = nullptr;
|
2014-01-21 12:11:34 +01:00
|
|
|
bool text_free = false;
|
|
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Font dupli-verts not supported inside collections. */
|
2019-04-22 09:39:35 +10:00
|
|
|
if (ctx->collection) {
|
2014-01-21 12:11:34 +01:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2014-01-21 12:11:34 +01:00
|
|
|
|
2024-02-19 15:54:48 +01:00
|
|
|
copy_m4_m4(pmat, par->object_to_world);
|
2014-01-21 12:11:34 +01:00
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* In `par` the family name is stored, use this to find the other objects. */
|
2014-01-21 12:11:34 +01:00
|
|
|
|
2018-06-12 15:03:51 +02:00
|
|
|
BKE_vfont_to_curve_ex(
|
2021-04-01 15:54:48 -05:00
|
|
|
par, (Curve *)par->data, FO_DUPLI, nullptr, &text, &text_len, &text_free, &chartransdata);
|
2014-01-21 12:11:34 +01:00
|
|
|
|
2021-04-01 15:54:48 -05:00
|
|
|
if (text == nullptr || chartransdata == nullptr) {
|
2014-01-21 12:11:34 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-01 15:54:48 -05:00
|
|
|
cu = (Curve *)par->data;
|
2014-01-21 12:11:34 +01:00
|
|
|
fsize = cu->fsize;
|
|
|
|
|
xof = cu->xof;
|
|
|
|
|
yof = cu->yof;
|
|
|
|
|
|
|
|
|
|
ct = chartransdata;
|
|
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Cache result. */
|
2014-01-21 12:11:34 +01:00
|
|
|
family_len = strlen(cu->family);
|
|
|
|
|
family_gh = BLI_ghash_int_new_ex(__func__, 256);
|
|
|
|
|
|
2020-02-03 18:37:12 +01:00
|
|
|
/* Safety check even if it might fail badly when called for original object. */
|
|
|
|
|
const bool is_eval_curve = DEG_is_evaluated_id(&cu->id);
|
|
|
|
|
|
2020-07-23 11:50:03 +10:00
|
|
|
/* Advance matching BLI_str_utf8_as_utf32. */
|
2014-01-21 12:11:34 +01:00
|
|
|
for (a = 0; a < text_len; a++, ct++) {
|
|
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* XXX That G.main is *really* ugly, but not sure what to do here.
|
|
|
|
|
* Definitively don't think it would be safe to put back `Main *bmain` pointer
|
|
|
|
|
* in #DupliContext as done in 2.7x? */
|
2022-09-25 18:33:28 +10:00
|
|
|
ob = find_family_object(G.main, cu->family, family_len, uint(text[a]), family_gh);
|
2020-02-03 18:37:12 +01:00
|
|
|
|
|
|
|
|
if (is_eval_curve) {
|
|
|
|
|
/* Workaround for the above hack. */
|
|
|
|
|
ob = DEG_get_evaluated_object(ctx->depsgraph, ob);
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-21 12:11:34 +01:00
|
|
|
if (ob) {
|
|
|
|
|
vec[0] = fsize * (ct->xof - xof);
|
|
|
|
|
vec[1] = fsize * (ct->yof - yof);
|
|
|
|
|
vec[2] = 0.0;
|
|
|
|
|
|
|
|
|
|
mul_m4_v3(pmat, vec);
|
|
|
|
|
|
2024-02-19 15:54:48 +01:00
|
|
|
copy_m4_m4(obmat, par->object_to_world);
|
2014-01-21 12:11:34 +01:00
|
|
|
|
|
|
|
|
if (UNLIKELY(ct->rot != 0.0f)) {
|
|
|
|
|
float rmat[4][4];
|
|
|
|
|
|
|
|
|
|
zero_v3(obmat[3]);
|
2016-11-25 16:20:30 +11:00
|
|
|
axis_angle_to_mat4_single(rmat, 'Z', -ct->rot);
|
2014-01-21 12:11:34 +01:00
|
|
|
mul_m4_m4m4(obmat, obmat, rmat);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
copy_v3_v3(obmat[3], vec);
|
|
|
|
|
|
2018-06-06 14:39:05 +02:00
|
|
|
make_dupli(ctx, ob, obmat, a);
|
2014-01-21 12:11:34 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (text_free) {
|
|
|
|
|
MEM_freeN((void *)text);
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-01 15:54:48 -05:00
|
|
|
BLI_ghash_free(family_gh, nullptr, nullptr);
|
2014-01-21 12:11:34 +01:00
|
|
|
|
|
|
|
|
MEM_freeN(chartransdata);
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-01 09:06:34 +10:00
|
|
|
static const DupliGenerator gen_dupli_verts_font = {
|
2023-01-16 12:41:11 +11:00
|
|
|
/*type*/ OB_DUPLIVERTS,
|
|
|
|
|
/*make_duplis*/ make_duplis_font};
|
2014-01-21 12:11:34 +01:00
|
|
|
|
2020-08-10 18:29:17 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
2020-12-02 13:25:25 +01:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Instances Geometry Component Implementation
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2021-09-06 18:22:24 +02:00
|
|
|
static void make_duplis_geometry_set_impl(const DupliContext *ctx,
|
|
|
|
|
const GeometrySet &geometry_set,
|
|
|
|
|
const float parent_transform[4][4],
|
Geometry Nodes: viewport preview
This adds support for showing geometry passed to the Viewer in the 3d
viewport (instead of just in the spreadsheet). The "viewer geometry"
bypasses the group output. So it is not necessary to change the final
output of the node group to be able to see the intermediate geometry.
**Activation and deactivation of a viewer node**
* A viewer node is activated by clicking on it.
* Ctrl+shift+click on any node/socket connects it to the viewer and
makes it active.
* Ctrl+shift+click in empty space deactivates the active viewer.
* When the active viewer is not visible anymore (e.g. another object
is selected, or the current node group is exit), it is deactivated.
* Clicking on the icon in the header of the Viewer node toggles whether
its active or not.
**Pinning**
* The spreadsheet still allows pinning the active viewer as before.
When pinned, the spreadsheet still references the viewer node even
when it becomes inactive.
* The viewport does not support pinning at the moment. It always shows
the active viewer.
**Attribute**
* When a field is linked to the second input of the viewer node it is
displayed as an overlay in the viewport.
* When possible the correct domain for the attribute is determined
automatically. This does not work in all cases. It falls back to the
face corner domain on meshes and the point domain on curves. When
necessary, the domain can be picked manually.
* The spreadsheet now only shows the "Viewer" column for the domain
that is selected in the Viewer node.
* Instance attributes are visualized as a constant color per instance.
**Viewport Options**
* The attribute overlay opacity can be controlled with the "Viewer Node"
setting in the overlays popover.
* A viewport can be configured not to show intermediate viewer-geometry
by disabling the "Viewer Node" option in the "View" menu.
**Implementation Details**
* The "spreadsheet context path" was generalized to a "viewer path" that
is used in more places now.
* The viewer node itself determines the attribute domain, evaluates the
field and stores the result in a `.viewer` attribute.
* A new "viewer attribute' overlay displays the data from the `.viewer`
attribute.
* The ground truth for the active viewer node is stored in the workspace
now. Node editors, spreadsheets and viewports retrieve the active
viewer from there unless they are pinned.
* The depsgraph object iterator has a new "viewer path" setting. When set,
the viewed geometry of the corresponding object is part of the iterator
instead of the final evaluated geometry.
* To support the instance attribute overlay `DupliObject` was extended
to contain the information necessary for drawing the overlay.
* The ctrl+shift+click operator has been refactored so that it can make
existing links to viewers active again.
* The auto-domain-detection in the Viewer node works by checking the
"preferred domain" for every field input. If there is not exactly one
preferred domain, the fallback is used.
Known limitations:
* Loose edges of meshes don't have the attribute overlay. This could be
added separately if necessary.
* Some attributes are hard to visualize as a color directly. For example,
the values might have to be normalized or some should be drawn as arrays.
For now, we encourage users to build node groups that generate appropriate
viewer-geometry. We might include some of that functionality in future versions.
Support for displaying attribute values as text in the viewport is planned as well.
* There seems to be an issue with the attribute overlay for pointclouds on
nvidia gpus, to be investigated.
Differential Revision: https://developer.blender.org/D15954
2022-09-28 17:54:59 +02:00
|
|
|
bool geometry_set_is_instance,
|
|
|
|
|
bool use_new_curves_type)
|
2020-12-02 13:25:25 +01:00
|
|
|
{
|
2021-09-06 18:22:24 +02:00
|
|
|
int component_index = 0;
|
|
|
|
|
if (ctx->object->type != OB_MESH || geometry_set_is_instance) {
|
2023-08-03 17:09:18 +02:00
|
|
|
if (const Mesh *mesh = geometry_set.get_mesh()) {
|
2022-08-09 14:44:47 -05:00
|
|
|
make_dupli(ctx, ctx->object, &mesh->id, parent_transform, component_index++);
|
2021-09-06 18:22:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (ctx->object->type != OB_VOLUME || geometry_set_is_instance) {
|
2023-08-03 17:09:18 +02:00
|
|
|
if (const Volume *volume = geometry_set.get_volume()) {
|
2022-08-09 14:44:47 -05:00
|
|
|
make_dupli(ctx, ctx->object, &volume->id, parent_transform, component_index++);
|
2021-09-06 18:22:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
2022-04-15 09:07:00 +02:00
|
|
|
if (!ELEM(ctx->object->type, OB_CURVES_LEGACY, OB_FONT, OB_CURVES) || geometry_set_is_instance) {
|
2023-06-15 22:18:28 +02:00
|
|
|
if (const blender::bke::CurveComponent *component =
|
2023-08-03 17:09:18 +02:00
|
|
|
geometry_set.get_component<blender::bke::CurveComponent>())
|
2023-06-15 22:18:28 +02:00
|
|
|
{
|
Geometry Nodes: viewport preview
This adds support for showing geometry passed to the Viewer in the 3d
viewport (instead of just in the spreadsheet). The "viewer geometry"
bypasses the group output. So it is not necessary to change the final
output of the node group to be able to see the intermediate geometry.
**Activation and deactivation of a viewer node**
* A viewer node is activated by clicking on it.
* Ctrl+shift+click on any node/socket connects it to the viewer and
makes it active.
* Ctrl+shift+click in empty space deactivates the active viewer.
* When the active viewer is not visible anymore (e.g. another object
is selected, or the current node group is exit), it is deactivated.
* Clicking on the icon in the header of the Viewer node toggles whether
its active or not.
**Pinning**
* The spreadsheet still allows pinning the active viewer as before.
When pinned, the spreadsheet still references the viewer node even
when it becomes inactive.
* The viewport does not support pinning at the moment. It always shows
the active viewer.
**Attribute**
* When a field is linked to the second input of the viewer node it is
displayed as an overlay in the viewport.
* When possible the correct domain for the attribute is determined
automatically. This does not work in all cases. It falls back to the
face corner domain on meshes and the point domain on curves. When
necessary, the domain can be picked manually.
* The spreadsheet now only shows the "Viewer" column for the domain
that is selected in the Viewer node.
* Instance attributes are visualized as a constant color per instance.
**Viewport Options**
* The attribute overlay opacity can be controlled with the "Viewer Node"
setting in the overlays popover.
* A viewport can be configured not to show intermediate viewer-geometry
by disabling the "Viewer Node" option in the "View" menu.
**Implementation Details**
* The "spreadsheet context path" was generalized to a "viewer path" that
is used in more places now.
* The viewer node itself determines the attribute domain, evaluates the
field and stores the result in a `.viewer` attribute.
* A new "viewer attribute' overlay displays the data from the `.viewer`
attribute.
* The ground truth for the active viewer node is stored in the workspace
now. Node editors, spreadsheets and viewports retrieve the active
viewer from there unless they are pinned.
* The depsgraph object iterator has a new "viewer path" setting. When set,
the viewed geometry of the corresponding object is part of the iterator
instead of the final evaluated geometry.
* To support the instance attribute overlay `DupliObject` was extended
to contain the information necessary for drawing the overlay.
* The ctrl+shift+click operator has been refactored so that it can make
existing links to viewers active again.
* The auto-domain-detection in the Viewer node works by checking the
"preferred domain" for every field input. If there is not exactly one
preferred domain, the fallback is used.
Known limitations:
* Loose edges of meshes don't have the attribute overlay. This could be
added separately if necessary.
* Some attributes are hard to visualize as a color directly. For example,
the values might have to be normalized or some should be drawn as arrays.
For now, we encourage users to build node groups that generate appropriate
viewer-geometry. We might include some of that functionality in future versions.
Support for displaying attribute values as text in the viewport is planned as well.
* There seems to be an issue with the attribute overlay for pointclouds on
nvidia gpus, to be investigated.
Differential Revision: https://developer.blender.org/D15954
2022-09-28 17:54:59 +02:00
|
|
|
if (use_new_curves_type) {
|
2023-08-03 17:09:18 +02:00
|
|
|
if (const Curves *curves = component->get()) {
|
Geometry Nodes: viewport preview
This adds support for showing geometry passed to the Viewer in the 3d
viewport (instead of just in the spreadsheet). The "viewer geometry"
bypasses the group output. So it is not necessary to change the final
output of the node group to be able to see the intermediate geometry.
**Activation and deactivation of a viewer node**
* A viewer node is activated by clicking on it.
* Ctrl+shift+click on any node/socket connects it to the viewer and
makes it active.
* Ctrl+shift+click in empty space deactivates the active viewer.
* When the active viewer is not visible anymore (e.g. another object
is selected, or the current node group is exit), it is deactivated.
* Clicking on the icon in the header of the Viewer node toggles whether
its active or not.
**Pinning**
* The spreadsheet still allows pinning the active viewer as before.
When pinned, the spreadsheet still references the viewer node even
when it becomes inactive.
* The viewport does not support pinning at the moment. It always shows
the active viewer.
**Attribute**
* When a field is linked to the second input of the viewer node it is
displayed as an overlay in the viewport.
* When possible the correct domain for the attribute is determined
automatically. This does not work in all cases. It falls back to the
face corner domain on meshes and the point domain on curves. When
necessary, the domain can be picked manually.
* The spreadsheet now only shows the "Viewer" column for the domain
that is selected in the Viewer node.
* Instance attributes are visualized as a constant color per instance.
**Viewport Options**
* The attribute overlay opacity can be controlled with the "Viewer Node"
setting in the overlays popover.
* A viewport can be configured not to show intermediate viewer-geometry
by disabling the "Viewer Node" option in the "View" menu.
**Implementation Details**
* The "spreadsheet context path" was generalized to a "viewer path" that
is used in more places now.
* The viewer node itself determines the attribute domain, evaluates the
field and stores the result in a `.viewer` attribute.
* A new "viewer attribute' overlay displays the data from the `.viewer`
attribute.
* The ground truth for the active viewer node is stored in the workspace
now. Node editors, spreadsheets and viewports retrieve the active
viewer from there unless they are pinned.
* The depsgraph object iterator has a new "viewer path" setting. When set,
the viewed geometry of the corresponding object is part of the iterator
instead of the final evaluated geometry.
* To support the instance attribute overlay `DupliObject` was extended
to contain the information necessary for drawing the overlay.
* The ctrl+shift+click operator has been refactored so that it can make
existing links to viewers active again.
* The auto-domain-detection in the Viewer node works by checking the
"preferred domain" for every field input. If there is not exactly one
preferred domain, the fallback is used.
Known limitations:
* Loose edges of meshes don't have the attribute overlay. This could be
added separately if necessary.
* Some attributes are hard to visualize as a color directly. For example,
the values might have to be normalized or some should be drawn as arrays.
For now, we encourage users to build node groups that generate appropriate
viewer-geometry. We might include some of that functionality in future versions.
Support for displaying attribute values as text in the viewport is planned as well.
* There seems to be an issue with the attribute overlay for pointclouds on
nvidia gpus, to be investigated.
Differential Revision: https://developer.blender.org/D15954
2022-09-28 17:54:59 +02:00
|
|
|
make_dupli(ctx, ctx->object, &curves->id, parent_transform, component_index++);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (const Curve *curve = component->get_curve_for_render()) {
|
|
|
|
|
make_dupli(ctx, ctx->object, &curve->id, parent_transform, component_index++);
|
|
|
|
|
}
|
2021-09-06 18:22:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (ctx->object->type != OB_POINTCLOUD || geometry_set_is_instance) {
|
2023-08-03 17:09:18 +02:00
|
|
|
if (const PointCloud *pointcloud = geometry_set.get_pointcloud()) {
|
2022-08-09 14:44:47 -05:00
|
|
|
make_dupli(ctx, ctx->object, &pointcloud->id, parent_transform, component_index++);
|
2021-09-06 18:22:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
2023-10-10 16:49:30 +02:00
|
|
|
if (ctx->object->type != OB_GREASE_PENCIL || geometry_set_is_instance) {
|
|
|
|
|
if (const GreasePencil *grease_pencil = geometry_set.get_grease_pencil()) {
|
|
|
|
|
make_dupli(ctx, ctx->object, &grease_pencil->id, parent_transform, component_index++);
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-09-06 18:22:24 +02:00
|
|
|
const bool creates_duplis_for_components = component_index >= 1;
|
|
|
|
|
|
2023-08-03 17:09:18 +02:00
|
|
|
const Instances *instances = geometry_set.get_instances();
|
2022-10-17 11:39:40 +02:00
|
|
|
if (instances == nullptr) {
|
2021-04-01 16:23:16 -05:00
|
|
|
return;
|
|
|
|
|
}
|
2020-12-02 13:25:25 +01:00
|
|
|
|
2021-09-06 18:22:24 +02:00
|
|
|
const DupliContext *instances_ctx = ctx;
|
|
|
|
|
/* Create a sub-context if some duplis were created above. This is to avoid dupli id collisions
|
|
|
|
|
* between the instances component below and the other components above. */
|
|
|
|
|
DupliContext new_instances_ctx;
|
|
|
|
|
if (creates_duplis_for_components) {
|
2021-12-15 15:46:27 +01:00
|
|
|
if (!copy_dupli_context(&new_instances_ctx, ctx, ctx->object, nullptr, component_index)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-09-06 18:22:24 +02:00
|
|
|
instances_ctx = &new_instances_ctx;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-17 11:39:40 +02:00
|
|
|
Span<float4x4> instance_offset_matrices = instances->transforms();
|
|
|
|
|
Span<int> reference_handles = instances->reference_handles();
|
|
|
|
|
Span<int> almost_unique_ids = instances->almost_unique_ids();
|
|
|
|
|
Span<InstanceReference> references = instances->references();
|
2020-12-11 18:00:37 +01:00
|
|
|
|
2021-05-04 10:16:24 +02:00
|
|
|
for (int64_t i : instance_offset_matrices.index_range()) {
|
2022-10-17 11:39:40 +02:00
|
|
|
const InstanceReference &reference = references[reference_handles[i]];
|
2021-02-12 17:41:28 +01:00
|
|
|
const int id = almost_unique_ids[i];
|
2021-01-07 09:27:42 -06:00
|
|
|
|
Geometry Nodes: viewport preview
This adds support for showing geometry passed to the Viewer in the 3d
viewport (instead of just in the spreadsheet). The "viewer geometry"
bypasses the group output. So it is not necessary to change the final
output of the node group to be able to see the intermediate geometry.
**Activation and deactivation of a viewer node**
* A viewer node is activated by clicking on it.
* Ctrl+shift+click on any node/socket connects it to the viewer and
makes it active.
* Ctrl+shift+click in empty space deactivates the active viewer.
* When the active viewer is not visible anymore (e.g. another object
is selected, or the current node group is exit), it is deactivated.
* Clicking on the icon in the header of the Viewer node toggles whether
its active or not.
**Pinning**
* The spreadsheet still allows pinning the active viewer as before.
When pinned, the spreadsheet still references the viewer node even
when it becomes inactive.
* The viewport does not support pinning at the moment. It always shows
the active viewer.
**Attribute**
* When a field is linked to the second input of the viewer node it is
displayed as an overlay in the viewport.
* When possible the correct domain for the attribute is determined
automatically. This does not work in all cases. It falls back to the
face corner domain on meshes and the point domain on curves. When
necessary, the domain can be picked manually.
* The spreadsheet now only shows the "Viewer" column for the domain
that is selected in the Viewer node.
* Instance attributes are visualized as a constant color per instance.
**Viewport Options**
* The attribute overlay opacity can be controlled with the "Viewer Node"
setting in the overlays popover.
* A viewport can be configured not to show intermediate viewer-geometry
by disabling the "Viewer Node" option in the "View" menu.
**Implementation Details**
* The "spreadsheet context path" was generalized to a "viewer path" that
is used in more places now.
* The viewer node itself determines the attribute domain, evaluates the
field and stores the result in a `.viewer` attribute.
* A new "viewer attribute' overlay displays the data from the `.viewer`
attribute.
* The ground truth for the active viewer node is stored in the workspace
now. Node editors, spreadsheets and viewports retrieve the active
viewer from there unless they are pinned.
* The depsgraph object iterator has a new "viewer path" setting. When set,
the viewed geometry of the corresponding object is part of the iterator
instead of the final evaluated geometry.
* To support the instance attribute overlay `DupliObject` was extended
to contain the information necessary for drawing the overlay.
* The ctrl+shift+click operator has been refactored so that it can make
existing links to viewers active again.
* The auto-domain-detection in the Viewer node works by checking the
"preferred domain" for every field input. If there is not exactly one
preferred domain, the fallback is used.
Known limitations:
* Loose edges of meshes don't have the attribute overlay. This could be
added separately if necessary.
* Some attributes are hard to visualize as a color directly. For example,
the values might have to be normalized or some should be drawn as arrays.
For now, we encourage users to build node groups that generate appropriate
viewer-geometry. We might include some of that functionality in future versions.
Support for displaying attribute values as text in the viewport is planned as well.
* There seems to be an issue with the attribute overlay for pointclouds on
nvidia gpus, to be investigated.
Differential Revision: https://developer.blender.org/D15954
2022-09-28 17:54:59 +02:00
|
|
|
const DupliContext *ctx_for_instance = instances_ctx;
|
|
|
|
|
/* Set the #preview_instance_index when necessary. */
|
|
|
|
|
DupliContext tmp_ctx_for_instance;
|
|
|
|
|
if (instances_ctx->preview_base_geometry == &geometry_set) {
|
|
|
|
|
tmp_ctx_for_instance = *instances_ctx;
|
|
|
|
|
tmp_ctx_for_instance.preview_instance_index = i;
|
|
|
|
|
ctx_for_instance = &tmp_ctx_for_instance;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-04 10:16:24 +02:00
|
|
|
switch (reference.type()) {
|
|
|
|
|
case InstanceReference::Type::Object: {
|
|
|
|
|
Object &object = reference.object();
|
2020-12-11 18:00:37 +01:00
|
|
|
float matrix[4][4];
|
2023-02-06 21:25:45 +01:00
|
|
|
mul_m4_m4m4(matrix, parent_transform, instance_offset_matrices[i].ptr());
|
2022-09-30 21:00:27 +03:00
|
|
|
make_dupli(ctx_for_instance, &object, matrix, id, &geometry_set, i);
|
2020-12-11 18:00:37 +01:00
|
|
|
|
|
|
|
|
float space_matrix[4][4];
|
2024-02-19 15:54:48 +01:00
|
|
|
mul_m4_m4m4(space_matrix, instance_offset_matrices[i].ptr(), object.world_to_object);
|
2021-09-06 18:22:24 +02:00
|
|
|
mul_m4_m4_pre(space_matrix, parent_transform);
|
2022-09-30 21:00:27 +03:00
|
|
|
make_recursive_duplis(ctx_for_instance, &object, space_matrix, id, &geometry_set, i);
|
2021-05-04 10:16:24 +02:00
|
|
|
break;
|
2020-12-11 18:00:37 +01:00
|
|
|
}
|
2021-05-04 10:16:24 +02:00
|
|
|
case InstanceReference::Type::Collection: {
|
|
|
|
|
Collection &collection = reference.collection();
|
2020-12-11 18:00:37 +01:00
|
|
|
float collection_matrix[4][4];
|
|
|
|
|
unit_m4(collection_matrix);
|
2021-05-04 10:16:24 +02:00
|
|
|
sub_v3_v3(collection_matrix[3], collection.instance_offset);
|
2023-02-06 21:25:45 +01:00
|
|
|
mul_m4_m4_pre(collection_matrix, instance_offset_matrices[i].ptr());
|
2021-09-06 18:22:24 +02:00
|
|
|
mul_m4_m4_pre(collection_matrix, parent_transform);
|
|
|
|
|
|
|
|
|
|
DupliContext sub_ctx;
|
2022-09-30 21:00:27 +03:00
|
|
|
if (!copy_dupli_context(&sub_ctx,
|
|
|
|
|
ctx_for_instance,
|
|
|
|
|
ctx_for_instance->object,
|
|
|
|
|
nullptr,
|
|
|
|
|
id,
|
|
|
|
|
&geometry_set,
|
|
|
|
|
i))
|
|
|
|
|
{
|
2021-12-15 15:46:27 +01:00
|
|
|
break;
|
|
|
|
|
}
|
2020-12-11 18:00:37 +01:00
|
|
|
|
Geometry Nodes: viewport preview
This adds support for showing geometry passed to the Viewer in the 3d
viewport (instead of just in the spreadsheet). The "viewer geometry"
bypasses the group output. So it is not necessary to change the final
output of the node group to be able to see the intermediate geometry.
**Activation and deactivation of a viewer node**
* A viewer node is activated by clicking on it.
* Ctrl+shift+click on any node/socket connects it to the viewer and
makes it active.
* Ctrl+shift+click in empty space deactivates the active viewer.
* When the active viewer is not visible anymore (e.g. another object
is selected, or the current node group is exit), it is deactivated.
* Clicking on the icon in the header of the Viewer node toggles whether
its active or not.
**Pinning**
* The spreadsheet still allows pinning the active viewer as before.
When pinned, the spreadsheet still references the viewer node even
when it becomes inactive.
* The viewport does not support pinning at the moment. It always shows
the active viewer.
**Attribute**
* When a field is linked to the second input of the viewer node it is
displayed as an overlay in the viewport.
* When possible the correct domain for the attribute is determined
automatically. This does not work in all cases. It falls back to the
face corner domain on meshes and the point domain on curves. When
necessary, the domain can be picked manually.
* The spreadsheet now only shows the "Viewer" column for the domain
that is selected in the Viewer node.
* Instance attributes are visualized as a constant color per instance.
**Viewport Options**
* The attribute overlay opacity can be controlled with the "Viewer Node"
setting in the overlays popover.
* A viewport can be configured not to show intermediate viewer-geometry
by disabling the "Viewer Node" option in the "View" menu.
**Implementation Details**
* The "spreadsheet context path" was generalized to a "viewer path" that
is used in more places now.
* The viewer node itself determines the attribute domain, evaluates the
field and stores the result in a `.viewer` attribute.
* A new "viewer attribute' overlay displays the data from the `.viewer`
attribute.
* The ground truth for the active viewer node is stored in the workspace
now. Node editors, spreadsheets and viewports retrieve the active
viewer from there unless they are pinned.
* The depsgraph object iterator has a new "viewer path" setting. When set,
the viewed geometry of the corresponding object is part of the iterator
instead of the final evaluated geometry.
* To support the instance attribute overlay `DupliObject` was extended
to contain the information necessary for drawing the overlay.
* The ctrl+shift+click operator has been refactored so that it can make
existing links to viewers active again.
* The auto-domain-detection in the Viewer node works by checking the
"preferred domain" for every field input. If there is not exactly one
preferred domain, the fallback is used.
Known limitations:
* Loose edges of meshes don't have the attribute overlay. This could be
added separately if necessary.
* Some attributes are hard to visualize as a color directly. For example,
the values might have to be normalized or some should be drawn as arrays.
For now, we encourage users to build node groups that generate appropriate
viewer-geometry. We might include some of that functionality in future versions.
Support for displaying attribute values as text in the viewport is planned as well.
* There seems to be an issue with the attribute overlay for pointclouds on
nvidia gpus, to be investigated.
Differential Revision: https://developer.blender.org/D15954
2022-09-28 17:54:59 +02:00
|
|
|
eEvaluationMode mode = DEG_get_mode(ctx_for_instance->depsgraph);
|
2021-09-06 18:22:24 +02:00
|
|
|
int object_id = 0;
|
2021-05-04 10:16:24 +02:00
|
|
|
FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN (&collection, object, mode) {
|
Geometry Nodes: viewport preview
This adds support for showing geometry passed to the Viewer in the 3d
viewport (instead of just in the spreadsheet). The "viewer geometry"
bypasses the group output. So it is not necessary to change the final
output of the node group to be able to see the intermediate geometry.
**Activation and deactivation of a viewer node**
* A viewer node is activated by clicking on it.
* Ctrl+shift+click on any node/socket connects it to the viewer and
makes it active.
* Ctrl+shift+click in empty space deactivates the active viewer.
* When the active viewer is not visible anymore (e.g. another object
is selected, or the current node group is exit), it is deactivated.
* Clicking on the icon in the header of the Viewer node toggles whether
its active or not.
**Pinning**
* The spreadsheet still allows pinning the active viewer as before.
When pinned, the spreadsheet still references the viewer node even
when it becomes inactive.
* The viewport does not support pinning at the moment. It always shows
the active viewer.
**Attribute**
* When a field is linked to the second input of the viewer node it is
displayed as an overlay in the viewport.
* When possible the correct domain for the attribute is determined
automatically. This does not work in all cases. It falls back to the
face corner domain on meshes and the point domain on curves. When
necessary, the domain can be picked manually.
* The spreadsheet now only shows the "Viewer" column for the domain
that is selected in the Viewer node.
* Instance attributes are visualized as a constant color per instance.
**Viewport Options**
* The attribute overlay opacity can be controlled with the "Viewer Node"
setting in the overlays popover.
* A viewport can be configured not to show intermediate viewer-geometry
by disabling the "Viewer Node" option in the "View" menu.
**Implementation Details**
* The "spreadsheet context path" was generalized to a "viewer path" that
is used in more places now.
* The viewer node itself determines the attribute domain, evaluates the
field and stores the result in a `.viewer` attribute.
* A new "viewer attribute' overlay displays the data from the `.viewer`
attribute.
* The ground truth for the active viewer node is stored in the workspace
now. Node editors, spreadsheets and viewports retrieve the active
viewer from there unless they are pinned.
* The depsgraph object iterator has a new "viewer path" setting. When set,
the viewed geometry of the corresponding object is part of the iterator
instead of the final evaluated geometry.
* To support the instance attribute overlay `DupliObject` was extended
to contain the information necessary for drawing the overlay.
* The ctrl+shift+click operator has been refactored so that it can make
existing links to viewers active again.
* The auto-domain-detection in the Viewer node works by checking the
"preferred domain" for every field input. If there is not exactly one
preferred domain, the fallback is used.
Known limitations:
* Loose edges of meshes don't have the attribute overlay. This could be
added separately if necessary.
* Some attributes are hard to visualize as a color directly. For example,
the values might have to be normalized or some should be drawn as arrays.
For now, we encourage users to build node groups that generate appropriate
viewer-geometry. We might include some of that functionality in future versions.
Support for displaying attribute values as text in the viewport is planned as well.
* There seems to be an issue with the attribute overlay for pointclouds on
nvidia gpus, to be investigated.
Differential Revision: https://developer.blender.org/D15954
2022-09-28 17:54:59 +02:00
|
|
|
if (object == ctx_for_instance->object) {
|
2020-12-11 18:00:37 +01:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float instance_matrix[4][4];
|
2024-02-19 15:54:48 +01:00
|
|
|
mul_m4_m4m4(instance_matrix, collection_matrix, object->object_to_world);
|
2020-12-11 18:00:37 +01:00
|
|
|
|
2021-09-06 18:22:24 +02:00
|
|
|
make_dupli(&sub_ctx, object, instance_matrix, object_id++);
|
|
|
|
|
make_recursive_duplis(&sub_ctx, object, collection_matrix, object_id++);
|
2020-12-11 18:00:37 +01:00
|
|
|
}
|
|
|
|
|
FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END;
|
2021-05-04 10:16:24 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2021-09-06 18:22:24 +02:00
|
|
|
case InstanceReference::Type::GeometrySet: {
|
|
|
|
|
float new_transform[4][4];
|
2023-02-06 21:25:45 +01:00
|
|
|
mul_m4_m4m4(new_transform, parent_transform, instance_offset_matrices[i].ptr());
|
2021-09-06 18:22:24 +02:00
|
|
|
|
|
|
|
|
DupliContext sub_ctx;
|
2022-09-30 21:00:27 +03:00
|
|
|
if (copy_dupli_context(&sub_ctx,
|
|
|
|
|
ctx_for_instance,
|
|
|
|
|
ctx_for_instance->object,
|
|
|
|
|
nullptr,
|
|
|
|
|
id,
|
|
|
|
|
&geometry_set,
|
|
|
|
|
i))
|
|
|
|
|
{
|
Geometry Nodes: viewport preview
This adds support for showing geometry passed to the Viewer in the 3d
viewport (instead of just in the spreadsheet). The "viewer geometry"
bypasses the group output. So it is not necessary to change the final
output of the node group to be able to see the intermediate geometry.
**Activation and deactivation of a viewer node**
* A viewer node is activated by clicking on it.
* Ctrl+shift+click on any node/socket connects it to the viewer and
makes it active.
* Ctrl+shift+click in empty space deactivates the active viewer.
* When the active viewer is not visible anymore (e.g. another object
is selected, or the current node group is exit), it is deactivated.
* Clicking on the icon in the header of the Viewer node toggles whether
its active or not.
**Pinning**
* The spreadsheet still allows pinning the active viewer as before.
When pinned, the spreadsheet still references the viewer node even
when it becomes inactive.
* The viewport does not support pinning at the moment. It always shows
the active viewer.
**Attribute**
* When a field is linked to the second input of the viewer node it is
displayed as an overlay in the viewport.
* When possible the correct domain for the attribute is determined
automatically. This does not work in all cases. It falls back to the
face corner domain on meshes and the point domain on curves. When
necessary, the domain can be picked manually.
* The spreadsheet now only shows the "Viewer" column for the domain
that is selected in the Viewer node.
* Instance attributes are visualized as a constant color per instance.
**Viewport Options**
* The attribute overlay opacity can be controlled with the "Viewer Node"
setting in the overlays popover.
* A viewport can be configured not to show intermediate viewer-geometry
by disabling the "Viewer Node" option in the "View" menu.
**Implementation Details**
* The "spreadsheet context path" was generalized to a "viewer path" that
is used in more places now.
* The viewer node itself determines the attribute domain, evaluates the
field and stores the result in a `.viewer` attribute.
* A new "viewer attribute' overlay displays the data from the `.viewer`
attribute.
* The ground truth for the active viewer node is stored in the workspace
now. Node editors, spreadsheets and viewports retrieve the active
viewer from there unless they are pinned.
* The depsgraph object iterator has a new "viewer path" setting. When set,
the viewed geometry of the corresponding object is part of the iterator
instead of the final evaluated geometry.
* To support the instance attribute overlay `DupliObject` was extended
to contain the information necessary for drawing the overlay.
* The ctrl+shift+click operator has been refactored so that it can make
existing links to viewers active again.
* The auto-domain-detection in the Viewer node works by checking the
"preferred domain" for every field input. If there is not exactly one
preferred domain, the fallback is used.
Known limitations:
* Loose edges of meshes don't have the attribute overlay. This could be
added separately if necessary.
* Some attributes are hard to visualize as a color directly. For example,
the values might have to be normalized or some should be drawn as arrays.
For now, we encourage users to build node groups that generate appropriate
viewer-geometry. We might include some of that functionality in future versions.
Support for displaying attribute values as text in the viewport is planned as well.
* There seems to be an issue with the attribute overlay for pointclouds on
nvidia gpus, to be investigated.
Differential Revision: https://developer.blender.org/D15954
2022-09-28 17:54:59 +02:00
|
|
|
make_duplis_geometry_set_impl(
|
|
|
|
|
&sub_ctx, reference.geometry_set(), new_transform, true, false);
|
2021-12-15 15:46:27 +01:00
|
|
|
}
|
2021-09-06 18:22:24 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2021-05-04 10:16:24 +02:00
|
|
|
case InstanceReference::Type::None: {
|
|
|
|
|
break;
|
2020-12-11 18:00:37 +01:00
|
|
|
}
|
|
|
|
|
}
|
2020-12-02 13:25:25 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-06 18:22:24 +02:00
|
|
|
static void make_duplis_geometry_set(const DupliContext *ctx)
|
|
|
|
|
{
|
2023-11-15 18:46:07 +01:00
|
|
|
const GeometrySet *geometry_set = ctx->object->runtime->geometry_set_eval;
|
2024-02-19 15:54:48 +01:00
|
|
|
make_duplis_geometry_set_impl(ctx, *geometry_set, ctx->object->object_to_world, false, false);
|
2021-09-06 18:22:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const DupliGenerator gen_dupli_geometry_set = {
|
2023-01-16 12:41:11 +11:00
|
|
|
/*type*/ GEOMETRY_SET_DUPLI_GENERATOR_TYPE,
|
|
|
|
|
/*make_duplis*/ make_duplis_geometry_set,
|
2020-12-02 13:25:25 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
2020-08-10 18:29:17 +10:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Dupli-Faces Implementation (#OB_DUPLIFACES)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2020-08-13 13:56:15 +10:00
|
|
|
/** Values shared between different mesh types. */
|
2021-04-01 15:54:48 -05:00
|
|
|
struct FaceDupliData_Params {
|
2020-08-13 13:56:15 +10:00
|
|
|
/**
|
|
|
|
|
* It's important we use this context instead of the `ctx` passed into #make_child_duplis
|
|
|
|
|
* since these won't match in the case of recursion.
|
|
|
|
|
*/
|
|
|
|
|
const DupliContext *ctx;
|
|
|
|
|
|
|
|
|
|
bool use_scale;
|
2021-04-01 15:54:48 -05:00
|
|
|
};
|
2020-08-13 13:56:15 +10:00
|
|
|
|
2021-04-01 15:54:48 -05:00
|
|
|
struct FaceDupliData_Mesh {
|
2020-08-13 13:56:15 +10:00
|
|
|
FaceDupliData_Params params;
|
|
|
|
|
|
2014-01-21 12:11:34 +01:00
|
|
|
int totface;
|
2023-07-24 22:06:55 +02:00
|
|
|
blender::OffsetIndices<int> faces;
|
Mesh: Replace MPoly struct with offset indices
Implements #95967.
Currently the `MPoly` struct is 12 bytes, and stores the index of a
face's first corner and the number of corners/verts/edges. Polygons
and corners are always created in order by Blender, meaning each
face's corners will be after the previous face's corners. We can take
advantage of this fact and eliminate the redundancy in mesh face
storage by only storing a single integer corner offset for each face.
The size of the face is then encoded by the offset of the next face.
The size of a single integer is 4 bytes, so this reduces memory
usage by 3 times.
The same method is used for `CurvesGeometry`, so Blender already has
an abstraction to simplify using these offsets called `OffsetIndices`.
This class is used to easily retrieve a range of corner indices for
each face. This also gives the opportunity for sharing some logic with
curves.
Another benefit of the change is that the offsets and sizes stored in
`MPoly` can no longer disagree with each other. Storing faces in the
order of their corners can simplify some code too.
Face/polygon variables now use the `IndexRange` type, which comes with
quite a few utilities that can simplify code.
Some:
- The offset integer array has to be one longer than the face count to
avoid a branch for every face, which means the data is no longer part
of the mesh's `CustomData`.
- We lose the ability to "reference" an original mesh's offset array
until more reusable CoW from #104478 is committed. That will be added
in a separate commit.
- Since they aren't part of `CustomData`, poly offsets often have to be
copied manually.
- To simplify using `OffsetIndices` in many places, some functions and
structs in headers were moved to only compile in C++.
- All meshes created by Blender use the same order for faces and face
corners, but just in case, meshes with mismatched order are fixed by
versioning code.
- `MeshPolygon.totloop` is no longer editable in RNA. This API break is
necessary here unfortunately. It should be worth it in 3.6, since
that's the best way to allow loading meshes from 4.0, which is
important for an LTS version.
Pull Request: https://projects.blender.org/blender/blender/pulls/105938
2023-04-04 20:39:28 +02:00
|
|
|
Span<int> corner_verts;
|
2023-01-10 16:34:39 +11:00
|
|
|
Span<float3> vert_positions;
|
2020-08-13 09:28:29 +10:00
|
|
|
const float (*orco)[3];
|
Mesh: Move UV layers to generic attributes
Currently the `MLoopUV` struct stores UV coordinates and flags related
to editing UV maps in the UV editor. This patch changes the coordinates
to use the generic 2D vector type, and moves the flags into three
separate boolean attributes. This follows the design in T95965, with
the ultimate intention of simplifying code and improving performance.
Importantly, the change allows exporters and renderers to use UVs
"touched" by geometry nodes, which only creates generic attributes.
It also allows geometry nodes to create "proper" UV maps from scratch,
though only with the Store Named Attribute node for now.
The new design considers any 2D vector attribute on the corner domain
to be a UV map. In the future, they might be distinguished from regular
2D vectors with attribute metadata, which may be helpful because they
are often interpolated differently.
Most of the code changes deal with passing around UV BMesh custom data
offsets and tracking the boolean "sublayers". The boolean layers are
use the following prefixes for attribute names: vert selection: `.vs.`,
edge selection: `.es.`, pinning: `.pn.`. Currently these are short to
avoid using up the maximum length of attribute names. To accommodate
for these 4 extra characters, the name length limit is enlarged to 68
bytes, while the maximum user settable name length is still 64 bytes.
Unfortunately Python/RNA API access to the UV flag data becomes slower.
Accessing the boolean layers directly is be better for performance in
general.
Like the other mesh SoA refactors, backward and forward compatibility
aren't affected, and won't be changed until 4.0. We pay for that by
making mesh reading and writing more expensive with conversions.
Resolves T85962
Differential Revision: https://developer.blender.org/D14365
2023-01-10 00:47:04 -05:00
|
|
|
const float2 *mloopuv;
|
2021-04-01 15:54:48 -05:00
|
|
|
};
|
2020-08-11 15:26:14 +10:00
|
|
|
|
2021-04-01 15:54:48 -05:00
|
|
|
struct FaceDupliData_EditMesh {
|
2020-08-13 13:56:15 +10:00
|
|
|
FaceDupliData_Params params;
|
|
|
|
|
|
|
|
|
|
BMEditMesh *em;
|
|
|
|
|
|
|
|
|
|
bool has_orco, has_uvs;
|
|
|
|
|
int cd_loop_uv_offset;
|
2021-04-01 15:54:48 -05:00
|
|
|
/* Can be nullptr. */
|
2023-01-10 16:39:53 +11:00
|
|
|
const float (*vert_positions_deform)[3];
|
2021-04-01 15:54:48 -05:00
|
|
|
};
|
2020-08-13 13:56:15 +10:00
|
|
|
|
2021-04-12 16:24:51 -05:00
|
|
|
static void get_dupliface_transform_from_coords(Span<float3> coords,
|
2020-08-13 13:56:15 +10:00
|
|
|
const bool use_scale,
|
|
|
|
|
const float scale_fac,
|
|
|
|
|
float r_mat[4][4])
|
2014-01-21 12:11:34 +01:00
|
|
|
{
|
BLI: Refactor vector types & functions to use templates
This patch implements the vector types (i.e:`float2`) by making heavy
usage of templating. All vector functions are now outside of the vector
classes (inside the `blender::math` namespace) and are not vector size
dependent for the most part.
In the ongoing effort to make shaders less GL centric, we are aiming
to share more code between GLSL and C++ to avoid code duplication.
####Motivations:
- We are aiming to share UBO and SSBO structures between GLSL and C++.
This means we will use many of the existing vector types and others
we currently don't have (uintX, intX). All these variations were
asking for many more code duplication.
- Deduplicate existing code which is duplicated for each vector size.
- We also want to share small functions. Which means that vector
functions should be static and not in the class namespace.
- Reduce friction to use these types in new projects due to their
incompleteness.
- The current state of the `BLI_(float|double|mpq)(2|3|4).hh` is a
bit of a let down. Most clases are incomplete, out of sync with each
others with different codestyles, and some functions that should be
static are not (i.e: `float3::reflect()`).
####Upsides:
- Still support `.x, .y, .z, .w` for readability.
- Compact, readable and easilly extendable.
- All of the vector functions are available for all the vectors types
and can be restricted to certain types. Also template specialization
let us define exception for special class (like mpq).
- With optimization ON, the compiler unroll the loops and performance
is the same.
####Downsides:
- Might impact debugability. Though I would arge that the bugs are
rarelly caused by the vector class itself (since the operations are
quite trivial) but by the type conversions.
- Might impact compile time. I did not saw a significant impact since
the usage is not really widespread.
- Functions needs to be rewritten to support arbitrary vector length.
For instance, one can't call `len_squared_v3v3` in
`math::length_squared()` and call it a day.
- Type cast does not work with the template version of the `math::`
vector functions. Meaning you need to manually cast `float *` and
`(float *)[3]` to `float3` for the function calls.
i.e: `math::distance_squared(float3(nearest.co), positions[i]);`
- Some parts might loose in readability:
`float3::dot(v1.normalized(), v2.normalized())`
becoming
`math::dot(math::normalize(v1), math::normalize(v2))`
But I propose, when appropriate, to use
`using namespace blender::math;` on function local or file scope to
increase readability.
`dot(normalize(v1), normalize(v2))`
####Consideration:
- Include back `.length()` method. It is quite handy and is more C++
oriented.
- I considered the GLM library as a candidate for replacement. It felt
like too much for what we need and would be difficult to extend / modify
to our needs.
- I used Macros to reduce code in operators declaration and potential
copy paste bugs. This could reduce debugability and could be reverted.
- This touches `delaunay_2d.cc` and the intersection code. I would like
to know @howardt opinion on the matter.
- The `noexcept` on the copy constructor of `mpq(2|3)` is being removed.
But according to @JacquesLucke it is not a real problem for now.
I would like to give a huge thanks to @JacquesLucke who helped during this
and pushed me to reduce the duplication further.
Reviewed By: brecht, sergey, JacquesLucke
Differential Revision: https://developer.blender.org/D13791
2022-01-12 12:57:07 +01:00
|
|
|
using namespace blender::math;
|
|
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Location. */
|
2021-04-12 16:24:51 -05:00
|
|
|
float3 location(0);
|
|
|
|
|
for (const float3 &coord : coords) {
|
|
|
|
|
location += coord;
|
2020-08-13 13:56:15 +10:00
|
|
|
}
|
2022-09-25 18:33:28 +10:00
|
|
|
location *= 1.0f / float(coords.size());
|
2021-04-12 16:24:51 -05:00
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Rotation. */
|
2021-04-12 16:24:51 -05:00
|
|
|
float quat[4];
|
|
|
|
|
|
BLI: Refactor vector types & functions to use templates
This patch implements the vector types (i.e:`float2`) by making heavy
usage of templating. All vector functions are now outside of the vector
classes (inside the `blender::math` namespace) and are not vector size
dependent for the most part.
In the ongoing effort to make shaders less GL centric, we are aiming
to share more code between GLSL and C++ to avoid code duplication.
####Motivations:
- We are aiming to share UBO and SSBO structures between GLSL and C++.
This means we will use many of the existing vector types and others
we currently don't have (uintX, intX). All these variations were
asking for many more code duplication.
- Deduplicate existing code which is duplicated for each vector size.
- We also want to share small functions. Which means that vector
functions should be static and not in the class namespace.
- Reduce friction to use these types in new projects due to their
incompleteness.
- The current state of the `BLI_(float|double|mpq)(2|3|4).hh` is a
bit of a let down. Most clases are incomplete, out of sync with each
others with different codestyles, and some functions that should be
static are not (i.e: `float3::reflect()`).
####Upsides:
- Still support `.x, .y, .z, .w` for readability.
- Compact, readable and easilly extendable.
- All of the vector functions are available for all the vectors types
and can be restricted to certain types. Also template specialization
let us define exception for special class (like mpq).
- With optimization ON, the compiler unroll the loops and performance
is the same.
####Downsides:
- Might impact debugability. Though I would arge that the bugs are
rarelly caused by the vector class itself (since the operations are
quite trivial) but by the type conversions.
- Might impact compile time. I did not saw a significant impact since
the usage is not really widespread.
- Functions needs to be rewritten to support arbitrary vector length.
For instance, one can't call `len_squared_v3v3` in
`math::length_squared()` and call it a day.
- Type cast does not work with the template version of the `math::`
vector functions. Meaning you need to manually cast `float *` and
`(float *)[3]` to `float3` for the function calls.
i.e: `math::distance_squared(float3(nearest.co), positions[i]);`
- Some parts might loose in readability:
`float3::dot(v1.normalized(), v2.normalized())`
becoming
`math::dot(math::normalize(v1), math::normalize(v2))`
But I propose, when appropriate, to use
`using namespace blender::math;` on function local or file scope to
increase readability.
`dot(normalize(v1), normalize(v2))`
####Consideration:
- Include back `.length()` method. It is quite handy and is more C++
oriented.
- I considered the GLM library as a candidate for replacement. It felt
like too much for what we need and would be difficult to extend / modify
to our needs.
- I used Macros to reduce code in operators declaration and potential
copy paste bugs. This could reduce debugability and could be reverted.
- This touches `delaunay_2d.cc` and the intersection code. I would like
to know @howardt opinion on the matter.
- The `noexcept` on the copy constructor of `mpq(2|3)` is being removed.
But according to @JacquesLucke it is not a real problem for now.
I would like to give a huge thanks to @JacquesLucke who helped during this
and pushed me to reduce the duplication further.
Reviewed By: brecht, sergey, JacquesLucke
Differential Revision: https://developer.blender.org/D13791
2022-01-12 12:57:07 +01:00
|
|
|
float3 f_no = normalize(cross_poly(coords));
|
2021-04-12 16:24:51 -05:00
|
|
|
tri_to_quat_ex(quat, coords[0], coords[1], coords[2], f_no);
|
|
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Scale. */
|
2021-04-12 16:24:51 -05:00
|
|
|
float scale;
|
2014-01-21 12:11:34 +01:00
|
|
|
if (use_scale) {
|
2022-09-25 18:33:28 +10:00
|
|
|
const float area = area_poly_v3((const float(*)[3])coords.data(), uint(coords.size()));
|
2014-01-21 12:11:34 +01:00
|
|
|
scale = sqrtf(area) * scale_fac;
|
|
|
|
|
}
|
2019-04-22 09:39:35 +10:00
|
|
|
else {
|
2014-01-21 12:11:34 +01:00
|
|
|
scale = 1.0f;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-04-12 16:24:51 -05:00
|
|
|
loc_quat_size_to_mat4(r_mat, location, quat, float3(scale));
|
2020-08-11 15:26:14 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-13 13:56:15 +10:00
|
|
|
static DupliObject *face_dupli(const DupliContext *ctx,
|
|
|
|
|
Object *inst_ob,
|
|
|
|
|
const float child_imat[4][4],
|
|
|
|
|
const int index,
|
|
|
|
|
const bool use_scale,
|
|
|
|
|
const float scale_fac,
|
2021-04-12 16:24:51 -05:00
|
|
|
Span<float3> coords)
|
2020-08-13 13:56:15 +10:00
|
|
|
{
|
|
|
|
|
float obmat[4][4];
|
|
|
|
|
float space_mat[4][4];
|
|
|
|
|
|
|
|
|
|
/* `obmat` is transform to face. */
|
2021-04-12 16:24:51 -05:00
|
|
|
get_dupliface_transform_from_coords(coords, use_scale, scale_fac, obmat);
|
2020-08-13 13:56:15 +10:00
|
|
|
|
|
|
|
|
/* Make offset relative to inst_ob using relative child transform. */
|
|
|
|
|
mul_mat3_m4_v3(child_imat, obmat[3]);
|
|
|
|
|
|
2020-08-13 16:36:20 +10:00
|
|
|
/* XXX ugly hack to ensure same behavior as in master.
|
|
|
|
|
* This should not be needed, #Object.parentinv is not consistent outside of parenting. */
|
2020-08-13 13:56:15 +10:00
|
|
|
{
|
|
|
|
|
float imat[3][3];
|
|
|
|
|
copy_m3_m4(imat, inst_ob->parentinv);
|
|
|
|
|
mul_m4_m3m4(obmat, imat, obmat);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Apply `obmat` _after_ the local face transform. */
|
2024-02-19 15:54:48 +01:00
|
|
|
mul_m4_m4m4(obmat, inst_ob->object_to_world, obmat);
|
2020-08-13 13:56:15 +10:00
|
|
|
|
|
|
|
|
/* Space matrix is constructed by removing `obmat` transform,
|
|
|
|
|
* this yields the world-space transform for recursive duplis. */
|
2024-02-19 15:54:48 +01:00
|
|
|
mul_m4_m4m4(space_mat, obmat, inst_ob->world_to_object);
|
2020-08-13 13:56:15 +10:00
|
|
|
|
|
|
|
|
DupliObject *dob = make_dupli(ctx, inst_ob, obmat, index);
|
|
|
|
|
|
|
|
|
|
/* Recursion. */
|
|
|
|
|
make_recursive_duplis(ctx, inst_ob, space_mat, index);
|
|
|
|
|
|
|
|
|
|
return dob;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static DupliObject *face_dupli_from_mesh(const DupliContext *ctx,
|
|
|
|
|
Object *inst_ob,
|
|
|
|
|
const float child_imat[4][4],
|
|
|
|
|
const int index,
|
|
|
|
|
const bool use_scale,
|
|
|
|
|
const float scale_fac,
|
|
|
|
|
|
|
|
|
|
/* Mesh variables. */
|
2023-07-24 22:06:55 +02:00
|
|
|
const Span<int> face_verts,
|
2023-01-10 16:34:39 +11:00
|
|
|
const Span<float3> vert_positions)
|
2020-08-11 15:26:14 +10:00
|
|
|
{
|
2023-07-24 22:06:55 +02:00
|
|
|
Array<float3, 64> coords(face_verts.size());
|
2020-08-13 13:56:15 +10:00
|
|
|
|
2023-07-24 22:06:55 +02:00
|
|
|
for (int i = 0; i < face_verts.size(); i++) {
|
|
|
|
|
coords[i] = vert_positions[face_verts[i]];
|
2020-08-13 13:56:15 +10:00
|
|
|
}
|
|
|
|
|
|
2021-04-12 16:24:51 -05:00
|
|
|
return face_dupli(ctx, inst_ob, child_imat, index, use_scale, scale_fac, coords);
|
2020-08-13 13:56:15 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static DupliObject *face_dupli_from_editmesh(const DupliContext *ctx,
|
|
|
|
|
Object *inst_ob,
|
|
|
|
|
const float child_imat[4][4],
|
|
|
|
|
const int index,
|
|
|
|
|
const bool use_scale,
|
|
|
|
|
const float scale_fac,
|
|
|
|
|
|
|
|
|
|
/* Mesh variables. */
|
|
|
|
|
BMFace *f,
|
2023-01-10 16:39:53 +11:00
|
|
|
const float (*vert_positions_deform)[3])
|
2020-08-11 15:26:14 +10:00
|
|
|
{
|
2020-08-13 13:56:15 +10:00
|
|
|
const int coords_len = f->len;
|
2021-04-12 16:24:51 -05:00
|
|
|
Array<float3, 64> coords(coords_len);
|
2020-08-13 13:56:15 +10:00
|
|
|
|
|
|
|
|
BMLoop *l_first, *l_iter;
|
|
|
|
|
int i = 0;
|
|
|
|
|
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
|
2023-01-10 16:39:53 +11:00
|
|
|
if (vert_positions_deform != nullptr) {
|
2020-08-13 13:56:15 +10:00
|
|
|
do {
|
2023-01-10 16:39:53 +11:00
|
|
|
copy_v3_v3(coords[i++], vert_positions_deform[BM_elem_index_get(l_iter->v)]);
|
2020-08-13 13:56:15 +10:00
|
|
|
} while ((l_iter = l_iter->next) != l_first);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
do {
|
|
|
|
|
copy_v3_v3(coords[i++], l_iter->v->co);
|
|
|
|
|
} while ((l_iter = l_iter->next) != l_first);
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-12 16:24:51 -05:00
|
|
|
return face_dupli(ctx, inst_ob, child_imat, index, use_scale, scale_fac, coords);
|
2020-08-13 13:56:15 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void make_child_duplis_faces_from_mesh(const DupliContext *ctx,
|
|
|
|
|
void *userdata,
|
|
|
|
|
Object *inst_ob)
|
|
|
|
|
{
|
2021-04-01 15:54:48 -05:00
|
|
|
FaceDupliData_Mesh *fdd = (FaceDupliData_Mesh *)userdata;
|
2020-08-13 09:28:29 +10:00
|
|
|
const float(*orco)[3] = fdd->orco;
|
Mesh: Move UV layers to generic attributes
Currently the `MLoopUV` struct stores UV coordinates and flags related
to editing UV maps in the UV editor. This patch changes the coordinates
to use the generic 2D vector type, and moves the flags into three
separate boolean attributes. This follows the design in T95965, with
the ultimate intention of simplifying code and improving performance.
Importantly, the change allows exporters and renderers to use UVs
"touched" by geometry nodes, which only creates generic attributes.
It also allows geometry nodes to create "proper" UV maps from scratch,
though only with the Store Named Attribute node for now.
The new design considers any 2D vector attribute on the corner domain
to be a UV map. In the future, they might be distinguished from regular
2D vectors with attribute metadata, which may be helpful because they
are often interpolated differently.
Most of the code changes deal with passing around UV BMesh custom data
offsets and tracking the boolean "sublayers". The boolean layers are
use the following prefixes for attribute names: vert selection: `.vs.`,
edge selection: `.es.`, pinning: `.pn.`. Currently these are short to
avoid using up the maximum length of attribute names. To accommodate
for these 4 extra characters, the name length limit is enlarged to 68
bytes, while the maximum user settable name length is still 64 bytes.
Unfortunately Python/RNA API access to the UV flag data becomes slower.
Accessing the boolean layers directly is be better for performance in
general.
Like the other mesh SoA refactors, backward and forward compatibility
aren't affected, and won't be changed until 4.0. We pay for that by
making mesh reading and writing more expensive with conversions.
Resolves T85962
Differential Revision: https://developer.blender.org/D14365
2023-01-10 00:47:04 -05:00
|
|
|
const float2 *mloopuv = fdd->mloopuv;
|
2020-08-13 13:56:15 +10:00
|
|
|
const int totface = fdd->totface;
|
|
|
|
|
const bool use_scale = fdd->params.use_scale;
|
|
|
|
|
|
2020-08-11 16:12:44 +02:00
|
|
|
float child_imat[4][4];
|
2020-08-11 15:26:14 +10:00
|
|
|
|
2024-02-19 15:54:48 +01:00
|
|
|
invert_m4_m4(inst_ob->world_to_object, inst_ob->object_to_world);
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Relative transform from parent to child space. */
|
2024-02-19 15:54:48 +01:00
|
|
|
mul_m4_m4m4(child_imat, inst_ob->world_to_object, ctx->object->object_to_world);
|
2020-08-13 13:56:15 +10:00
|
|
|
const float scale_fac = ctx->object->instance_faces_scale;
|
2020-08-11 15:26:14 +10:00
|
|
|
|
2023-03-03 10:50:54 -05:00
|
|
|
for (const int a : blender::IndexRange(totface)) {
|
2023-07-24 22:06:55 +02:00
|
|
|
const blender::IndexRange face = fdd->faces[a];
|
|
|
|
|
const Span<int> face_verts = fdd->corner_verts.slice(face);
|
Mesh: Move positions to a generic attribute
**Changes**
As described in T93602, this patch removes all use of the `MVert`
struct, replacing it with a generic named attribute with the name
`"position"`, consistent with other geometry types.
Variable names have been changed from `verts` to `positions`, to align
with the attribute name and the more generic design (positions are not
vertices, they are just an attribute stored on the point domain).
This change is made possible by previous commits that moved all other
data out of `MVert` to runtime data or other generic attributes. What
remains is mostly a simple type change. Though, the type still shows up
859 times, so the patch is quite large.
One compromise is that now `CD_MASK_BAREMESH` now contains
`CD_PROP_FLOAT3`. With the general move towards generic attributes
over custom data types, we are removing use of these type masks anyway.
**Benefits**
The most obvious benefit is reduced memory usage and the benefits
that brings in memory-bound situations. `float3` is only 3 bytes, in
comparison to `MVert` which was 4. When there are millions of vertices
this starts to matter more.
The other benefits come from using a more generic type. Instead of
writing algorithms specifically for `MVert`, code can just use arrays
of vectors. This will allow eliminating many temporary arrays or
wrappers used to extract positions.
Many possible improvements aren't implemented in this patch, though
I did switch simplify or remove the process of creating temporary
position arrays in a few places.
The design clarity that "positions are just another attribute" brings
allows removing explicit copying of vertices in some procedural
operations-- they are just processed like most other attributes.
**Performance**
This touches so many areas that it's hard to benchmark exhaustively,
but I observed some areas as examples.
* The mesh line node with 4 million count was 1.5x (8ms to 12ms) faster.
* The Spring splash screen went from ~4.3 to ~4.5 fps.
* The subdivision surface modifier/node was slightly faster
RNA access through Python may be slightly slower, since now we need
a name lookup instead of just a custom data type lookup for each index.
**Future Improvements**
* Remove uses of "vert_coords" functions:
* `BKE_mesh_vert_coords_alloc`
* `BKE_mesh_vert_coords_get`
* `BKE_mesh_vert_coords_apply{_with_mat4}`
* Remove more hidden copying of positions
* General simplification now possible in many areas
* Convert more code to C++ to use `float3` instead of `float[3]`
* Currently `reinterpret_cast` is used for those C-API functions
Differential Revision: https://developer.blender.org/D15982
2023-01-10 00:10:43 -05:00
|
|
|
DupliObject *dob = face_dupli_from_mesh(fdd->params.ctx,
|
|
|
|
|
inst_ob,
|
|
|
|
|
child_imat,
|
|
|
|
|
a,
|
|
|
|
|
use_scale,
|
|
|
|
|
scale_fac,
|
2023-07-24 22:06:55 +02:00
|
|
|
face_verts,
|
2023-01-10 16:34:39 +11:00
|
|
|
fdd->vert_positions);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-07-24 22:06:55 +02:00
|
|
|
const float w = 1.0f / float(face.size());
|
2019-02-21 17:25:34 +01:00
|
|
|
if (orco) {
|
2023-07-24 22:06:55 +02:00
|
|
|
for (int j = 0; j < face.size(); j++) {
|
|
|
|
|
madd_v3_v3fl(dob->orco, orco[face_verts[j]], w);
|
2014-01-21 12:11:34 +01:00
|
|
|
}
|
2019-02-21 17:25:34 +01:00
|
|
|
}
|
|
|
|
|
if (mloopuv) {
|
2023-07-24 22:06:55 +02:00
|
|
|
for (int j = 0; j < face.size(); j++) {
|
|
|
|
|
madd_v2_v2fl(dob->uv, mloopuv[face[j]], w);
|
2014-01-21 12:11:34 +01:00
|
|
|
}
|
|
|
|
|
}
|
2020-08-13 13:56:15 +10:00
|
|
|
}
|
|
|
|
|
}
|
2020-08-11 15:26:14 +10:00
|
|
|
|
2020-08-13 13:56:15 +10:00
|
|
|
static void make_child_duplis_faces_from_editmesh(const DupliContext *ctx,
|
|
|
|
|
void *userdata,
|
|
|
|
|
Object *inst_ob)
|
|
|
|
|
{
|
2021-04-01 15:54:48 -05:00
|
|
|
FaceDupliData_EditMesh *fdd = (FaceDupliData_EditMesh *)userdata;
|
2020-08-13 13:56:15 +10:00
|
|
|
BMEditMesh *em = fdd->em;
|
|
|
|
|
float child_imat[4][4];
|
|
|
|
|
int a;
|
|
|
|
|
BMFace *f;
|
|
|
|
|
BMIter iter;
|
|
|
|
|
const bool use_scale = fdd->params.use_scale;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-01-10 16:39:53 +11:00
|
|
|
const float(*vert_positions_deform)[3] = fdd->vert_positions_deform;
|
2020-08-13 13:56:15 +10:00
|
|
|
|
2023-01-10 16:39:53 +11:00
|
|
|
BLI_assert((vert_positions_deform == nullptr) || (em->bm->elem_index_dirty & BM_VERT) == 0);
|
2020-08-13 13:56:15 +10:00
|
|
|
|
2024-02-19 15:54:48 +01:00
|
|
|
invert_m4_m4(inst_ob->world_to_object, inst_ob->object_to_world);
|
2020-08-13 13:56:15 +10:00
|
|
|
/* Relative transform from parent to child space. */
|
2024-02-19 15:54:48 +01:00
|
|
|
mul_m4_m4m4(child_imat, inst_ob->world_to_object, ctx->object->object_to_world);
|
2020-08-13 13:56:15 +10:00
|
|
|
const float scale_fac = ctx->object->instance_faces_scale;
|
|
|
|
|
|
|
|
|
|
BM_ITER_MESH_INDEX (f, &iter, em->bm, BM_FACES_OF_MESH, a) {
|
|
|
|
|
DupliObject *dob = face_dupli_from_editmesh(
|
2023-01-10 16:39:53 +11:00
|
|
|
fdd->params.ctx, inst_ob, child_imat, a, use_scale, scale_fac, f, vert_positions_deform);
|
2020-08-13 13:56:15 +10:00
|
|
|
|
|
|
|
|
if (fdd->has_orco) {
|
2022-09-25 18:33:28 +10:00
|
|
|
const float w = 1.0f / float(f->len);
|
2020-08-13 13:56:15 +10:00
|
|
|
BMLoop *l_first, *l_iter;
|
|
|
|
|
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
|
|
|
|
|
do {
|
|
|
|
|
madd_v3_v3fl(dob->orco, l_iter->v->co, w);
|
|
|
|
|
} while ((l_iter = l_iter->next) != l_first);
|
|
|
|
|
}
|
|
|
|
|
if (fdd->has_uvs) {
|
|
|
|
|
BM_face_uv_calc_center_median(f, fdd->cd_loop_uv_offset, dob->uv);
|
|
|
|
|
}
|
2020-08-11 15:26:14 +10:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-11 15:26:14 +10:00
|
|
|
static void make_duplis_faces(const DupliContext *ctx)
|
|
|
|
|
{
|
|
|
|
|
Object *parent = ctx->object;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Gather mesh info. */
|
2021-04-01 15:54:48 -05:00
|
|
|
BMEditMesh *em = nullptr;
|
2023-01-10 16:39:53 +11:00
|
|
|
const float(*vert_positions_deform)[3] = nullptr;
|
|
|
|
|
const Mesh *me_eval = mesh_data_from_duplicator_object(
|
|
|
|
|
parent, &em, &vert_positions_deform, nullptr);
|
2021-04-01 15:54:48 -05:00
|
|
|
if (em == nullptr && me_eval == nullptr) {
|
2020-08-13 13:30:25 +10:00
|
|
|
return;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-04-01 15:54:48 -05:00
|
|
|
FaceDupliData_Params fdd_params = {ctx, (parent->transflag & OB_DUPLIFACES_SCALE) != 0};
|
2020-08-13 13:30:25 +10:00
|
|
|
|
2021-04-01 15:54:48 -05:00
|
|
|
if (em != nullptr) {
|
Mesh: Move UV layers to generic attributes
Currently the `MLoopUV` struct stores UV coordinates and flags related
to editing UV maps in the UV editor. This patch changes the coordinates
to use the generic 2D vector type, and moves the flags into three
separate boolean attributes. This follows the design in T95965, with
the ultimate intention of simplifying code and improving performance.
Importantly, the change allows exporters and renderers to use UVs
"touched" by geometry nodes, which only creates generic attributes.
It also allows geometry nodes to create "proper" UV maps from scratch,
though only with the Store Named Attribute node for now.
The new design considers any 2D vector attribute on the corner domain
to be a UV map. In the future, they might be distinguished from regular
2D vectors with attribute metadata, which may be helpful because they
are often interpolated differently.
Most of the code changes deal with passing around UV BMesh custom data
offsets and tracking the boolean "sublayers". The boolean layers are
use the following prefixes for attribute names: vert selection: `.vs.`,
edge selection: `.es.`, pinning: `.pn.`. Currently these are short to
avoid using up the maximum length of attribute names. To accommodate
for these 4 extra characters, the name length limit is enlarged to 68
bytes, while the maximum user settable name length is still 64 bytes.
Unfortunately Python/RNA API access to the UV flag data becomes slower.
Accessing the boolean layers directly is be better for performance in
general.
Like the other mesh SoA refactors, backward and forward compatibility
aren't affected, and won't be changed until 4.0. We pay for that by
making mesh reading and writing more expensive with conversions.
Resolves T85962
Differential Revision: https://developer.blender.org/D14365
2023-01-10 00:47:04 -05:00
|
|
|
const int uv_idx = CustomData_get_render_layer(&em->bm->ldata, CD_PROP_FLOAT2);
|
2021-04-01 15:54:48 -05:00
|
|
|
FaceDupliData_EditMesh fdd{};
|
|
|
|
|
fdd.params = fdd_params;
|
|
|
|
|
fdd.em = em;
|
2023-01-10 16:39:53 +11:00
|
|
|
fdd.vert_positions_deform = vert_positions_deform;
|
|
|
|
|
fdd.has_orco = (vert_positions_deform != nullptr);
|
2021-04-01 15:54:48 -05:00
|
|
|
fdd.has_uvs = (uv_idx != -1);
|
|
|
|
|
fdd.cd_loop_uv_offset = (uv_idx != -1) ?
|
Mesh: Move UV layers to generic attributes
Currently the `MLoopUV` struct stores UV coordinates and flags related
to editing UV maps in the UV editor. This patch changes the coordinates
to use the generic 2D vector type, and moves the flags into three
separate boolean attributes. This follows the design in T95965, with
the ultimate intention of simplifying code and improving performance.
Importantly, the change allows exporters and renderers to use UVs
"touched" by geometry nodes, which only creates generic attributes.
It also allows geometry nodes to create "proper" UV maps from scratch,
though only with the Store Named Attribute node for now.
The new design considers any 2D vector attribute on the corner domain
to be a UV map. In the future, they might be distinguished from regular
2D vectors with attribute metadata, which may be helpful because they
are often interpolated differently.
Most of the code changes deal with passing around UV BMesh custom data
offsets and tracking the boolean "sublayers". The boolean layers are
use the following prefixes for attribute names: vert selection: `.vs.`,
edge selection: `.es.`, pinning: `.pn.`. Currently these are short to
avoid using up the maximum length of attribute names. To accommodate
for these 4 extra characters, the name length limit is enlarged to 68
bytes, while the maximum user settable name length is still 64 bytes.
Unfortunately Python/RNA API access to the UV flag data becomes slower.
Accessing the boolean layers directly is be better for performance in
general.
Like the other mesh SoA refactors, backward and forward compatibility
aren't affected, and won't be changed until 4.0. We pay for that by
making mesh reading and writing more expensive with conversions.
Resolves T85962
Differential Revision: https://developer.blender.org/D14365
2023-01-10 00:47:04 -05:00
|
|
|
CustomData_get_n_offset(&em->bm->ldata, CD_PROP_FLOAT2, uv_idx) :
|
2021-04-01 15:54:48 -05:00
|
|
|
-1;
|
2020-08-13 13:56:15 +10:00
|
|
|
make_child_duplis(ctx, &fdd, make_child_duplis_faces_from_editmesh);
|
|
|
|
|
}
|
|
|
|
|
else {
|
2023-12-19 20:38:59 -05:00
|
|
|
const int uv_idx = CustomData_get_render_layer(&me_eval->corner_data, CD_PROP_FLOAT2);
|
2021-04-01 15:54:48 -05:00
|
|
|
FaceDupliData_Mesh fdd{};
|
|
|
|
|
fdd.params = fdd_params;
|
2023-07-24 22:06:55 +02:00
|
|
|
fdd.totface = me_eval->faces_num;
|
|
|
|
|
fdd.faces = me_eval->faces();
|
Mesh: Replace MPoly struct with offset indices
Implements #95967.
Currently the `MPoly` struct is 12 bytes, and stores the index of a
face's first corner and the number of corners/verts/edges. Polygons
and corners are always created in order by Blender, meaning each
face's corners will be after the previous face's corners. We can take
advantage of this fact and eliminate the redundancy in mesh face
storage by only storing a single integer corner offset for each face.
The size of the face is then encoded by the offset of the next face.
The size of a single integer is 4 bytes, so this reduces memory
usage by 3 times.
The same method is used for `CurvesGeometry`, so Blender already has
an abstraction to simplify using these offsets called `OffsetIndices`.
This class is used to easily retrieve a range of corner indices for
each face. This also gives the opportunity for sharing some logic with
curves.
Another benefit of the change is that the offsets and sizes stored in
`MPoly` can no longer disagree with each other. Storing faces in the
order of their corners can simplify some code too.
Face/polygon variables now use the `IndexRange` type, which comes with
quite a few utilities that can simplify code.
Some:
- The offset integer array has to be one longer than the face count to
avoid a branch for every face, which means the data is no longer part
of the mesh's `CustomData`.
- We lose the ability to "reference" an original mesh's offset array
until more reusable CoW from #104478 is committed. That will be added
in a separate commit.
- Since they aren't part of `CustomData`, poly offsets often have to be
copied manually.
- To simplify using `OffsetIndices` in many places, some functions and
structs in headers were moved to only compile in C++.
- All meshes created by Blender use the same order for faces and face
corners, but just in case, meshes with mismatched order are fixed by
versioning code.
- `MeshPolygon.totloop` is no longer editable in RNA. This API break is
necessary here unfortunately. It should be worth it in 3.6, since
that's the best way to allow loading meshes from 4.0, which is
important for an LTS version.
Pull Request: https://projects.blender.org/blender/blender/pulls/105938
2023-04-04 20:39:28 +02:00
|
|
|
fdd.corner_verts = me_eval->corner_verts();
|
2023-01-10 16:34:39 +11:00
|
|
|
fdd.vert_positions = me_eval->vert_positions();
|
Mesh: Move UV layers to generic attributes
Currently the `MLoopUV` struct stores UV coordinates and flags related
to editing UV maps in the UV editor. This patch changes the coordinates
to use the generic 2D vector type, and moves the flags into three
separate boolean attributes. This follows the design in T95965, with
the ultimate intention of simplifying code and improving performance.
Importantly, the change allows exporters and renderers to use UVs
"touched" by geometry nodes, which only creates generic attributes.
It also allows geometry nodes to create "proper" UV maps from scratch,
though only with the Store Named Attribute node for now.
The new design considers any 2D vector attribute on the corner domain
to be a UV map. In the future, they might be distinguished from regular
2D vectors with attribute metadata, which may be helpful because they
are often interpolated differently.
Most of the code changes deal with passing around UV BMesh custom data
offsets and tracking the boolean "sublayers". The boolean layers are
use the following prefixes for attribute names: vert selection: `.vs.`,
edge selection: `.es.`, pinning: `.pn.`. Currently these are short to
avoid using up the maximum length of attribute names. To accommodate
for these 4 extra characters, the name length limit is enlarged to 68
bytes, while the maximum user settable name length is still 64 bytes.
Unfortunately Python/RNA API access to the UV flag data becomes slower.
Accessing the boolean layers directly is be better for performance in
general.
Like the other mesh SoA refactors, backward and forward compatibility
aren't affected, and won't be changed until 4.0. We pay for that by
making mesh reading and writing more expensive with conversions.
Resolves T85962
Differential Revision: https://developer.blender.org/D14365
2023-01-10 00:47:04 -05:00
|
|
|
fdd.mloopuv = (uv_idx != -1) ? (const float2 *)CustomData_get_layer_n(
|
2023-12-19 20:38:59 -05:00
|
|
|
&me_eval->corner_data, CD_PROP_FLOAT2, uv_idx) :
|
2021-04-01 15:54:48 -05:00
|
|
|
nullptr;
|
2023-07-25 21:15:52 +02:00
|
|
|
fdd.orco = (const float(*)[3])CustomData_get_layer(&me_eval->vert_data, CD_ORCO);
|
2021-04-01 15:54:48 -05:00
|
|
|
|
2020-08-13 13:56:15 +10:00
|
|
|
make_child_duplis(ctx, &fdd, make_child_duplis_faces_from_mesh);
|
2014-01-21 12:11:34 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-14 14:26:42 +10:00
|
|
|
static const DupliGenerator gen_dupli_faces = {
|
|
|
|
|
/*type*/ OB_DUPLIFACES,
|
|
|
|
|
/*make_duplis*/ make_duplis_faces,
|
|
|
|
|
};
|
2014-01-21 12:11:34 +01:00
|
|
|
|
2020-08-10 18:29:17 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Dupli-Particles Implementation (#OB_DUPLIPARTS)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem *psys)
|
|
|
|
|
{
|
|
|
|
|
Scene *scene = ctx->scene;
|
|
|
|
|
Object *par = ctx->object;
|
2018-06-08 19:26:46 +02:00
|
|
|
eEvaluationMode mode = DEG_get_mode(ctx->depsgraph);
|
|
|
|
|
bool for_render = mode == DAG_EVAL_RENDER;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-04-01 15:54:48 -05:00
|
|
|
Object *ob = nullptr, **oblist = nullptr;
|
2016-12-28 17:30:58 +01:00
|
|
|
DupliObject *dob;
|
|
|
|
|
ParticleSettings *part;
|
|
|
|
|
ParticleData *pa;
|
2021-04-01 15:54:48 -05:00
|
|
|
ChildParticle *cpa = nullptr;
|
2016-12-28 17:30:58 +01:00
|
|
|
ParticleKey state;
|
|
|
|
|
ParticleCacheKey *cache;
|
2019-01-28 17:52:46 +01:00
|
|
|
float ctime, scale = 1.0f;
|
2019-02-01 13:56:13 +01:00
|
|
|
float tmat[4][4], mat[4][4], pamat[4][4], size = 0.0;
|
2016-12-28 17:30:58 +01:00
|
|
|
int a, b, hair = 0;
|
2018-06-28 14:29:54 +02:00
|
|
|
int totpart, totchild;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
int no_draw_flag = PARS_UNEXIST;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-04-01 15:54:48 -05:00
|
|
|
if (psys == nullptr) {
|
2016-12-28 17:30:58 +01:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
part = psys->part;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-04-01 15:54:48 -05:00
|
|
|
if (part == nullptr) {
|
2016-12-28 17:30:58 +01:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!psys_check_enabled(par, psys, for_render)) {
|
2016-12-28 17:30:58 +01:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!for_render) {
|
2016-12-28 17:30:58 +01:00
|
|
|
no_draw_flag |= PARS_NO_DISP;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* NOTE: in old animation system, used parent object's time-offset. */
|
2019-08-14 23:29:46 +10:00
|
|
|
ctime = DEG_get_ctime(ctx->depsgraph);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
totpart = psys->totpart;
|
|
|
|
|
totchild = psys->totchild;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-08 09:28:52 +02:00
|
|
|
if ((for_render || part->draw_as == PART_DRAW_REND) &&
|
|
|
|
|
ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR))
|
|
|
|
|
{
|
2021-04-01 15:54:48 -05:00
|
|
|
ParticleSimulationData sim = {nullptr};
|
2018-04-06 12:07:27 +02:00
|
|
|
sim.depsgraph = ctx->depsgraph;
|
2016-12-28 17:30:58 +01:00
|
|
|
sim.scene = scene;
|
|
|
|
|
sim.ob = par;
|
|
|
|
|
sim.psys = psys;
|
|
|
|
|
sim.psmd = psys_get_modifier(par, psys);
|
2022-11-02 14:41:49 +01:00
|
|
|
/* Make sure emitter `world_to_object` is in global coordinates instead of render view
|
|
|
|
|
* coordinates. */
|
2024-02-19 15:54:48 +01:00
|
|
|
invert_m4_m4(par->world_to_object, par->object_to_world);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* First check for loops (particle system object used as dupli-object). */
|
2016-12-28 17:30:58 +01:00
|
|
|
if (part->ren_as == PART_DRAW_OB) {
|
2021-04-01 15:54:48 -05:00
|
|
|
if (ELEM(part->instance_object, nullptr, par)) {
|
2016-12-28 17:30:58 +01:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
2020-08-13 09:49:49 +10:00
|
|
|
else { /* #PART_DRAW_GR. */
|
2021-04-01 15:54:48 -05:00
|
|
|
if (part->instance_collection == nullptr) {
|
2016-12-28 17:30:58 +01:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-17 19:00:54 +11:00
|
|
|
const ListBase dup_collection_objects = BKE_collection_object_cache_get(
|
|
|
|
|
part->instance_collection);
|
2019-04-22 09:39:35 +10:00
|
|
|
if (BLI_listbase_is_empty(&dup_collection_objects)) {
|
Collections and groups unification
OVERVIEW
* In 2.7 terminology, all layers and groups are now collection datablocks.
* These collections are nestable, linkable, instanceable, overrideable, ..
which opens up new ways to set up scenes and link + override data.
* Viewport/render visibility and selectability are now a part of the collection
and shared across all view layers and linkable.
* View layers define which subset of the scene collection hierarchy is excluded
for each. For many workflows one view layer can be used, these are more of an
advanced feature now.
OUTLINER
* The outliner now has a "View Layer" display mode instead of "Collections",
which can display the collections and/or objects in the view layer.
* In this display mode, collections can be excluded with the right click menu.
These will then be greyed out and their objects will be excluded.
* To view collections not linked to any scene, the "Blender File" display mode
can be used, with the new filtering option to just see Colleciton datablocks.
* The outliner right click menus for collections and objects were reorganized.
* Drag and drop still needs to be improved. Like before, dragging the icon or
text gives different results, we'll unify this later.
LINKING AND OVERRIDES
* Collections can now be linked into the scene without creating an instance,
with the link/append operator or from the collections view in the outliner.
* Collections can get static overrides with the right click menu in the outliner,
but this is rather unreliable and not clearly communicated at the moment.
* We still need to improve the make override operator to turn collection instances
into collections with overrides directly in the scene.
PERFORMANCE
* We tried to make performance not worse than before and improve it in some
cases. The main thing that's still a bit slower is multiple scenes, we have to
change the layer syncing to only updated affected scenes.
* Collections keep a list of their parent collections for faster incremental
updates in syncing and caching.
* View layer bases are now in a object -> base hash to avoid quadratic time
lookups internally and in API functions like visible_get().
VERSIONING
* Compatibility with 2.7 files should be improved due to the new visibility
controls. Of course users may not want to set up their scenes differently
now to avoid having separate layers and groups.
* Compatibility with 2.8 is mostly there, and was tested on Eevee demo and Hero
files. There's a few things which are know to be not quite compatible, like
nested layer collections inside groups.
* The versioning code for 2.8 files is quite complicated, and isolated behind
#ifdef so it can be removed at the end of the release cycle.
KNOWN ISSUES
* The G-key group operators in the 3D viewport were left mostly as is, they
need to be modified still to fit better.
* Same for the groups panel in the object properties. This needs to be updated
still, or perhaps replaced by something better.
* Collections must all have a unique name. Less restrictive namespacing is to
be done later, we'll have to see how important this is as all objects within
the collections must also have a unique name anyway.
* Full scene copy and delete scene are exactly doing the right thing yet.
Differential Revision: https://developer.blender.org/D3383
https://code.blender.org/2018/05/collections-and-groups/
2018-04-30 15:57:22 +02:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Collections and groups unification
OVERVIEW
* In 2.7 terminology, all layers and groups are now collection datablocks.
* These collections are nestable, linkable, instanceable, overrideable, ..
which opens up new ways to set up scenes and link + override data.
* Viewport/render visibility and selectability are now a part of the collection
and shared across all view layers and linkable.
* View layers define which subset of the scene collection hierarchy is excluded
for each. For many workflows one view layer can be used, these are more of an
advanced feature now.
OUTLINER
* The outliner now has a "View Layer" display mode instead of "Collections",
which can display the collections and/or objects in the view layer.
* In this display mode, collections can be excluded with the right click menu.
These will then be greyed out and their objects will be excluded.
* To view collections not linked to any scene, the "Blender File" display mode
can be used, with the new filtering option to just see Colleciton datablocks.
* The outliner right click menus for collections and objects were reorganized.
* Drag and drop still needs to be improved. Like before, dragging the icon or
text gives different results, we'll unify this later.
LINKING AND OVERRIDES
* Collections can now be linked into the scene without creating an instance,
with the link/append operator or from the collections view in the outliner.
* Collections can get static overrides with the right click menu in the outliner,
but this is rather unreliable and not clearly communicated at the moment.
* We still need to improve the make override operator to turn collection instances
into collections with overrides directly in the scene.
PERFORMANCE
* We tried to make performance not worse than before and improve it in some
cases. The main thing that's still a bit slower is multiple scenes, we have to
change the layer syncing to only updated affected scenes.
* Collections keep a list of their parent collections for faster incremental
updates in syncing and caching.
* View layer bases are now in a object -> base hash to avoid quadratic time
lookups internally and in API functions like visible_get().
VERSIONING
* Compatibility with 2.7 files should be improved due to the new visibility
controls. Of course users may not want to set up their scenes differently
now to avoid having separate layers and groups.
* Compatibility with 2.8 is mostly there, and was tested on Eevee demo and Hero
files. There's a few things which are know to be not quite compatible, like
nested layer collections inside groups.
* The versioning code for 2.8 files is quite complicated, and isolated behind
#ifdef so it can be removed at the end of the release cycle.
KNOWN ISSUES
* The G-key group operators in the 3D viewport were left mostly as is, they
need to be modified still to fit better.
* Same for the groups panel in the object properties. This needs to be updated
still, or perhaps replaced by something better.
* Collections must all have a unique name. Less restrictive namespacing is to
be done later, we'll have to see how important this is as all objects within
the collections must also have a unique name anyway.
* Full scene copy and delete scene are exactly doing the right thing yet.
Differential Revision: https://developer.blender.org/D3383
https://code.blender.org/2018/05/collections-and-groups/
2018-04-30 15:57:22 +02:00
|
|
|
if (BLI_findptr(&dup_collection_objects, par, offsetof(Base, object))) {
|
2016-12-28 17:30:58 +01:00
|
|
|
return;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* If we have a hair particle system, use the path cache. */
|
2016-12-28 17:30:58 +01:00
|
|
|
if (part->type == PART_HAIR) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (psys->flag & PSYS_HAIR_DONE) {
|
2016-12-28 17:30:58 +01:00
|
|
|
hair = (totchild == 0 || psys->childcache) && psys->pathcache;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
if (!hair) {
|
2016-12-28 17:30:58 +01:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* We use cache, update `totchild` according to cached data. */
|
2016-12-28 17:30:58 +01:00
|
|
|
totchild = psys->totchildcache;
|
|
|
|
|
totpart = psys->totcached;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-09-25 18:33:28 +10:00
|
|
|
RNG *rng = BLI_rng_new_srandom(31415926u + uint(psys->seed));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-11-09 20:30:41 +01:00
|
|
|
psys_sim_data_init(&sim);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Gather list of objects or single object. */
|
2018-06-28 14:29:54 +02:00
|
|
|
int totcollection = 0;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-09-10 14:14:52 +02:00
|
|
|
const bool use_whole_collection = part->draw & PART_DRAW_WHOLE_GR;
|
|
|
|
|
const bool use_collection_count = part->draw & PART_DRAW_COUNT_GR && !use_whole_collection;
|
2016-12-28 17:30:58 +01:00
|
|
|
if (part->ren_as == PART_DRAW_GR) {
|
2019-09-10 14:14:52 +02:00
|
|
|
if (use_collection_count) {
|
2018-06-28 14:29:54 +02:00
|
|
|
psys_find_group_weights(part);
|
2021-04-01 15:54:48 -05:00
|
|
|
LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) {
|
2019-02-17 19:00:54 +11:00
|
|
|
FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN (
|
2024-01-02 18:12:54 +01:00
|
|
|
part->instance_collection, object, mode)
|
|
|
|
|
{
|
2018-06-28 14:29:54 +02:00
|
|
|
if (dw->ob == object) {
|
|
|
|
|
totcollection += dw->count;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2018-06-28 14:29:54 +02:00
|
|
|
FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END;
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2016-12-28 17:30:58 +01:00
|
|
|
else {
|
2019-02-17 19:00:54 +11:00
|
|
|
FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN (part->instance_collection, object, mode)
|
|
|
|
|
{
|
2017-12-01 11:24:21 -02:00
|
|
|
(void)object;
|
Collections and groups unification
OVERVIEW
* In 2.7 terminology, all layers and groups are now collection datablocks.
* These collections are nestable, linkable, instanceable, overrideable, ..
which opens up new ways to set up scenes and link + override data.
* Viewport/render visibility and selectability are now a part of the collection
and shared across all view layers and linkable.
* View layers define which subset of the scene collection hierarchy is excluded
for each. For many workflows one view layer can be used, these are more of an
advanced feature now.
OUTLINER
* The outliner now has a "View Layer" display mode instead of "Collections",
which can display the collections and/or objects in the view layer.
* In this display mode, collections can be excluded with the right click menu.
These will then be greyed out and their objects will be excluded.
* To view collections not linked to any scene, the "Blender File" display mode
can be used, with the new filtering option to just see Colleciton datablocks.
* The outliner right click menus for collections and objects were reorganized.
* Drag and drop still needs to be improved. Like before, dragging the icon or
text gives different results, we'll unify this later.
LINKING AND OVERRIDES
* Collections can now be linked into the scene without creating an instance,
with the link/append operator or from the collections view in the outliner.
* Collections can get static overrides with the right click menu in the outliner,
but this is rather unreliable and not clearly communicated at the moment.
* We still need to improve the make override operator to turn collection instances
into collections with overrides directly in the scene.
PERFORMANCE
* We tried to make performance not worse than before and improve it in some
cases. The main thing that's still a bit slower is multiple scenes, we have to
change the layer syncing to only updated affected scenes.
* Collections keep a list of their parent collections for faster incremental
updates in syncing and caching.
* View layer bases are now in a object -> base hash to avoid quadratic time
lookups internally and in API functions like visible_get().
VERSIONING
* Compatibility with 2.7 files should be improved due to the new visibility
controls. Of course users may not want to set up their scenes differently
now to avoid having separate layers and groups.
* Compatibility with 2.8 is mostly there, and was tested on Eevee demo and Hero
files. There's a few things which are know to be not quite compatible, like
nested layer collections inside groups.
* The versioning code for 2.8 files is quite complicated, and isolated behind
#ifdef so it can be removed at the end of the release cycle.
KNOWN ISSUES
* The G-key group operators in the 3D viewport were left mostly as is, they
need to be modified still to fit better.
* Same for the groups panel in the object properties. This needs to be updated
still, or perhaps replaced by something better.
* Collections must all have a unique name. Less restrictive namespacing is to
be done later, we'll have to see how important this is as all objects within
the collections must also have a unique name anyway.
* Full scene copy and delete scene are exactly doing the right thing yet.
Differential Revision: https://developer.blender.org/D3383
https://code.blender.org/2018/05/collections-and-groups/
2018-04-30 15:57:22 +02:00
|
|
|
totcollection++;
|
2017-12-01 11:24:21 -02:00
|
|
|
}
|
2018-06-08 19:26:46 +02:00
|
|
|
FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END;
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-09-25 20:27:46 +10:00
|
|
|
oblist = (Object **)MEM_callocN(size_t(totcollection) * sizeof(Object *),
|
2021-04-01 15:54:48 -05:00
|
|
|
"dupcollection object list");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-09-10 14:14:52 +02:00
|
|
|
if (use_collection_count) {
|
2018-06-28 14:29:54 +02:00
|
|
|
a = 0;
|
2021-04-01 15:54:48 -05:00
|
|
|
LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) {
|
2019-02-17 19:00:54 +11:00
|
|
|
FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN (
|
2024-01-02 18:12:54 +01:00
|
|
|
part->instance_collection, object, mode)
|
|
|
|
|
{
|
2018-06-28 14:29:54 +02:00
|
|
|
if (dw->ob == object) {
|
|
|
|
|
for (b = 0; b < dw->count; b++, a++) {
|
|
|
|
|
oblist[a] = dw->ob;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2018-06-28 14:29:54 +02:00
|
|
|
FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END;
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2016-12-28 17:30:58 +01:00
|
|
|
else {
|
2017-12-01 11:24:21 -02:00
|
|
|
a = 0;
|
2019-02-17 19:00:54 +11:00
|
|
|
FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN (part->instance_collection, object, mode)
|
|
|
|
|
{
|
2017-12-01 11:24:21 -02:00
|
|
|
oblist[a] = object;
|
|
|
|
|
a++;
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
2018-06-08 19:26:46 +02:00
|
|
|
FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END;
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2016-12-28 17:30:58 +01:00
|
|
|
else {
|
2019-02-17 19:00:54 +11:00
|
|
|
ob = part->instance_object;
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (totchild == 0 || part->draw & PART_DRAW_PARENT) {
|
2016-12-28 17:30:58 +01:00
|
|
|
a = 0;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2016-12-28 17:30:58 +01:00
|
|
|
a = totpart;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
for (pa = psys->particles; a < totpart + totchild; a++, pa++) {
|
|
|
|
|
if (a < totpart) {
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Handle parent particle. */
|
2019-04-22 09:39:35 +10:00
|
|
|
if (pa->flag & no_draw_flag) {
|
2016-12-28 17:30:58 +01:00
|
|
|
continue;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
#if 0 /* UNUSED */
|
|
|
|
|
pa_num = pa->num;
|
|
|
|
|
#endif
|
2016-12-28 17:30:58 +01:00
|
|
|
size = pa->size;
|
|
|
|
|
}
|
|
|
|
|
else {
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Handle child particle. */
|
2016-12-28 17:30:58 +01:00
|
|
|
cpa = &psys->child[a - totpart];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
#if 0 /* UNUSED */
|
|
|
|
|
pa_num = a;
|
|
|
|
|
#endif
|
2021-04-01 15:54:48 -05:00
|
|
|
size = psys_get_child_size(psys, cpa, ctime, nullptr);
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Some hair paths might be non-existent so they can't be used for duplication. */
|
2016-12-28 17:30:58 +01:00
|
|
|
if (hair && psys->pathcache &&
|
|
|
|
|
((a < totpart && psys->pathcache[a]->segments < 0) ||
|
|
|
|
|
(a >= totpart && psys->childcache[a - totpart]->segments < 0)))
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
if (part->ren_as == PART_DRAW_GR) {
|
2023-02-12 14:37:16 +11:00
|
|
|
/* Prevent divide by zero below #28336. */
|
2019-04-22 09:39:35 +10:00
|
|
|
if (totcollection == 0) {
|
2016-12-28 17:30:58 +01:00
|
|
|
continue;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* For collections, pick the object based on settings. */
|
2019-09-10 14:14:52 +02:00
|
|
|
if (part->draw & PART_DRAW_RAND_GR && !use_whole_collection) {
|
2018-06-12 14:20:21 +02:00
|
|
|
b = BLI_rng_get_int(rng) % totcollection;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
else {
|
Collections and groups unification
OVERVIEW
* In 2.7 terminology, all layers and groups are now collection datablocks.
* These collections are nestable, linkable, instanceable, overrideable, ..
which opens up new ways to set up scenes and link + override data.
* Viewport/render visibility and selectability are now a part of the collection
and shared across all view layers and linkable.
* View layers define which subset of the scene collection hierarchy is excluded
for each. For many workflows one view layer can be used, these are more of an
advanced feature now.
OUTLINER
* The outliner now has a "View Layer" display mode instead of "Collections",
which can display the collections and/or objects in the view layer.
* In this display mode, collections can be excluded with the right click menu.
These will then be greyed out and their objects will be excluded.
* To view collections not linked to any scene, the "Blender File" display mode
can be used, with the new filtering option to just see Colleciton datablocks.
* The outliner right click menus for collections and objects were reorganized.
* Drag and drop still needs to be improved. Like before, dragging the icon or
text gives different results, we'll unify this later.
LINKING AND OVERRIDES
* Collections can now be linked into the scene without creating an instance,
with the link/append operator or from the collections view in the outliner.
* Collections can get static overrides with the right click menu in the outliner,
but this is rather unreliable and not clearly communicated at the moment.
* We still need to improve the make override operator to turn collection instances
into collections with overrides directly in the scene.
PERFORMANCE
* We tried to make performance not worse than before and improve it in some
cases. The main thing that's still a bit slower is multiple scenes, we have to
change the layer syncing to only updated affected scenes.
* Collections keep a list of their parent collections for faster incremental
updates in syncing and caching.
* View layer bases are now in a object -> base hash to avoid quadratic time
lookups internally and in API functions like visible_get().
VERSIONING
* Compatibility with 2.7 files should be improved due to the new visibility
controls. Of course users may not want to set up their scenes differently
now to avoid having separate layers and groups.
* Compatibility with 2.8 is mostly there, and was tested on Eevee demo and Hero
files. There's a few things which are know to be not quite compatible, like
nested layer collections inside groups.
* The versioning code for 2.8 files is quite complicated, and isolated behind
#ifdef so it can be removed at the end of the release cycle.
KNOWN ISSUES
* The G-key group operators in the 3D viewport were left mostly as is, they
need to be modified still to fit better.
* Same for the groups panel in the object properties. This needs to be updated
still, or perhaps replaced by something better.
* Collections must all have a unique name. Less restrictive namespacing is to
be done later, we'll have to see how important this is as all objects within
the collections must also have a unique name anyway.
* Full scene copy and delete scene are exactly doing the right thing yet.
Differential Revision: https://developer.blender.org/D3383
https://code.blender.org/2018/05/collections-and-groups/
2018-04-30 15:57:22 +02:00
|
|
|
b = a % totcollection;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
ob = oblist[b];
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
if (hair) {
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Hair we handle separate and compute transform based on hair keys. */
|
2016-12-28 17:30:58 +01:00
|
|
|
if (a < totpart) {
|
|
|
|
|
cache = psys->pathcache[a];
|
2021-04-01 15:54:48 -05:00
|
|
|
psys_get_dupli_path_transform(&sim, pa, nullptr, cache, pamat, &scale);
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
cache = psys->childcache[a - totpart];
|
2021-04-01 15:54:48 -05:00
|
|
|
psys_get_dupli_path_transform(&sim, nullptr, cpa, cache, pamat, &scale);
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
copy_v3_v3(pamat[3], cache->co);
|
|
|
|
|
pamat[3][3] = 1.0f;
|
|
|
|
|
}
|
|
|
|
|
else {
|
2020-08-13 09:49:49 +10:00
|
|
|
/* First key. */
|
2016-12-28 17:30:58 +01:00
|
|
|
state.time = ctime;
|
2021-12-08 09:52:38 +01:00
|
|
|
if (psys_get_particle_state(&sim, a, &state, false) == 0) {
|
2016-12-28 17:30:58 +01:00
|
|
|
continue;
|
|
|
|
|
}
|
2020-08-07 12:30:43 +02:00
|
|
|
|
|
|
|
|
float tquat[4];
|
|
|
|
|
normalize_qt_qt(tquat, state.rot);
|
|
|
|
|
quat_to_mat4(pamat, tquat);
|
|
|
|
|
copy_v3_v3(pamat[3], state.co);
|
|
|
|
|
pamat[3][3] = 1.0f;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
if (part->ren_as == PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) {
|
2017-12-01 11:24:21 -02:00
|
|
|
b = 0;
|
2019-02-17 19:00:54 +11:00
|
|
|
FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN (part->instance_collection, object, mode)
|
|
|
|
|
{
|
2024-02-19 15:54:48 +01:00
|
|
|
copy_m4_m4(tmat, oblist[b]->object_to_world);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-09-14 17:18:26 +02:00
|
|
|
/* Apply collection instance offset. */
|
|
|
|
|
sub_v3_v3(tmat[3], part->instance_collection->instance_offset);
|
|
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Apply particle scale. */
|
2016-12-28 17:30:58 +01:00
|
|
|
mul_mat3_m4_fl(tmat, size * scale);
|
|
|
|
|
mul_v3_fl(tmat[3], size * scale);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Individual particle transform. */
|
2016-12-28 17:30:58 +01:00
|
|
|
mul_m4_m4m4(mat, pamat, tmat);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-06-06 14:39:05 +02:00
|
|
|
dob = make_dupli(ctx, object, mat, a);
|
2016-12-28 17:30:58 +01:00
|
|
|
dob->particle_system = psys;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-21 17:25:34 +01:00
|
|
|
psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-12-01 11:24:21 -02:00
|
|
|
b++;
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
2018-06-08 19:26:46 +02:00
|
|
|
FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END;
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
|
|
|
|
else {
|
2019-02-01 13:56:13 +01:00
|
|
|
float obmat[4][4];
|
2024-02-19 15:54:48 +01:00
|
|
|
copy_m4_m4(obmat, ob->object_to_world);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-01 13:56:13 +01:00
|
|
|
float vec[3];
|
2016-12-28 17:30:58 +01:00
|
|
|
copy_v3_v3(vec, obmat[3]);
|
2019-02-01 13:56:13 +01:00
|
|
|
zero_v3(obmat[3]);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-27 12:07:07 +10:00
|
|
|
/* Particle rotation uses x-axis as the aligned axis,
|
|
|
|
|
* so pre-rotate the object accordingly. */
|
2016-12-28 17:30:58 +01:00
|
|
|
if ((part->draw & PART_DRAW_ROTATE_OB) == 0) {
|
|
|
|
|
float xvec[3], q[4], size_mat[4][4], original_size[3];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
mat4_to_size(original_size, obmat);
|
|
|
|
|
size_to_mat4(size_mat, original_size);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-06 11:25:27 +11:00
|
|
|
xvec[0] = -1.0f;
|
2016-12-28 17:30:58 +01:00
|
|
|
xvec[1] = xvec[2] = 0;
|
|
|
|
|
vec_to_quat(q, xvec, ob->trackflag, ob->upflag);
|
|
|
|
|
quat_to_mat4(obmat, q);
|
|
|
|
|
obmat[3][3] = 1.0f;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Add scaling if requested. */
|
2019-04-22 09:39:35 +10:00
|
|
|
if ((part->draw & PART_DRAW_NO_SCALE_OB) == 0) {
|
2016-12-28 17:30:58 +01:00
|
|
|
mul_m4_m4m4(obmat, obmat, size_mat);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
|
|
|
|
else if (part->draw & PART_DRAW_NO_SCALE_OB) {
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Remove scaling. */
|
2016-12-28 17:30:58 +01:00
|
|
|
float size_mat[4][4], original_size[3];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
mat4_to_size(original_size, obmat);
|
|
|
|
|
size_to_mat4(size_mat, original_size);
|
|
|
|
|
invert_m4(size_mat);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
mul_m4_m4m4(obmat, obmat, size_mat);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
mul_m4_m4m4(tmat, pamat, obmat);
|
|
|
|
|
mul_mat3_m4_fl(tmat, size * scale);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
copy_m4_m4(mat, tmat);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (part->draw & PART_DRAW_GLOBAL_OB) {
|
2016-12-28 17:30:58 +01:00
|
|
|
add_v3_v3v3(mat[3], mat[3], vec);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-06-06 14:39:05 +02:00
|
|
|
dob = make_dupli(ctx, ob, mat, a);
|
2016-12-28 17:30:58 +01:00
|
|
|
dob->particle_system = psys;
|
2019-02-21 17:25:34 +01:00
|
|
|
psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-06-26 11:31:28 +02:00
|
|
|
BLI_rng_free(rng);
|
2022-11-09 20:30:41 +01:00
|
|
|
psys_sim_data_free(&sim);
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Clean up. */
|
2019-04-22 09:39:35 +10:00
|
|
|
if (oblist) {
|
2016-12-28 17:30:58 +01:00
|
|
|
MEM_freeN(oblist);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void make_duplis_particles(const DupliContext *ctx)
|
|
|
|
|
{
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Particle system take up one level in id, the particles another. */
|
2021-04-01 15:54:48 -05:00
|
|
|
int psysid;
|
|
|
|
|
LISTBASE_FOREACH_INDEX (ParticleSystem *, psys, &ctx->object->particlesystem, psysid) {
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Particles create one more level for persistent `psys` index. */
|
2016-12-28 17:30:58 +01:00
|
|
|
DupliContext pctx;
|
2021-12-15 15:46:27 +01:00
|
|
|
if (copy_dupli_context(&pctx, ctx, ctx->object, nullptr, psysid)) {
|
|
|
|
|
make_duplis_particle_system(&pctx, psys);
|
|
|
|
|
}
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-14 14:26:42 +10:00
|
|
|
static const DupliGenerator gen_dupli_particles = {
|
|
|
|
|
/*type*/ OB_DUPLIPARTS,
|
|
|
|
|
/*make_duplis*/ make_duplis_particles,
|
|
|
|
|
};
|
2016-12-28 17:30:58 +01:00
|
|
|
|
2020-08-10 18:29:17 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Dupli-Generator Selector For The Given Context
|
|
|
|
|
* \{ */
|
2014-01-21 12:11:34 +01:00
|
|
|
|
|
|
|
|
static const DupliGenerator *get_dupli_generator(const DupliContext *ctx)
|
|
|
|
|
{
|
|
|
|
|
int transflag = ctx->object->transflag;
|
2021-08-04 17:46:55 +02:00
|
|
|
int visibility_flag = ctx->object->visibility_flag;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-11-15 18:46:07 +01:00
|
|
|
if ((transflag & OB_DUPLI) == 0 && ctx->object->runtime->geometry_set_eval == nullptr) {
|
2021-04-01 15:54:48 -05:00
|
|
|
return nullptr;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-09-05 10:49:20 +10:00
|
|
|
/* Meta-ball objects can't create instances, but the dupli system is used to "instance" their
|
2022-08-17 10:20:25 -04:00
|
|
|
* evaluated mesh to render engines. We need to exit early to avoid recursively instancing the
|
2023-09-05 10:49:20 +10:00
|
|
|
* evaluated meta-ball mesh on meta-ball instances that already contribute to the basis. */
|
2022-08-17 10:20:25 -04:00
|
|
|
if (ctx->object->type == OB_MBALL && ctx->level > 0) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-13 09:49:49 +10:00
|
|
|
/* Should the dupli's be generated for this object? - Respect restrict flags. */
|
2021-08-04 17:46:55 +02:00
|
|
|
if (DEG_get_mode(ctx->depsgraph) == DAG_EVAL_RENDER ? (visibility_flag & OB_HIDE_RENDER) :
|
|
|
|
|
(visibility_flag & OB_HIDE_VIEWPORT))
|
|
|
|
|
{
|
2021-04-01 15:54:48 -05:00
|
|
|
return nullptr;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-01-12 13:46:13 -06:00
|
|
|
/* Give "Object as Font" instances higher priority than geometry set instances, to retain
|
|
|
|
|
* the behavior from before curve object meshes were processed as instances internally. */
|
|
|
|
|
if (transflag & OB_DUPLIVERTS) {
|
|
|
|
|
if (ctx->object->type == OB_FONT) {
|
|
|
|
|
return &gen_dupli_verts_font;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-15 18:46:07 +01:00
|
|
|
if (ctx->object->runtime->geometry_set_eval != nullptr) {
|
2023-06-15 22:18:28 +02:00
|
|
|
if (blender::bke::object_has_geometry_set_instances(*ctx->object)) {
|
2021-09-06 18:22:24 +02:00
|
|
|
return &gen_dupli_geometry_set;
|
2020-12-02 13:25:25 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-28 17:30:58 +01:00
|
|
|
if (transflag & OB_DUPLIPARTS) {
|
|
|
|
|
return &gen_dupli_particles;
|
|
|
|
|
}
|
2020-08-07 12:30:43 +02:00
|
|
|
if (transflag & OB_DUPLIVERTS) {
|
2014-01-21 12:11:34 +01:00
|
|
|
if (ctx->object->type == OB_MESH) {
|
|
|
|
|
return &gen_dupli_verts;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (transflag & OB_DUPLIFACES) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (ctx->object->type == OB_MESH) {
|
2014-01-21 12:11:34 +01:00
|
|
|
return &gen_dupli_faces;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2014-01-21 12:11:34 +01:00
|
|
|
}
|
Collections and groups unification
OVERVIEW
* In 2.7 terminology, all layers and groups are now collection datablocks.
* These collections are nestable, linkable, instanceable, overrideable, ..
which opens up new ways to set up scenes and link + override data.
* Viewport/render visibility and selectability are now a part of the collection
and shared across all view layers and linkable.
* View layers define which subset of the scene collection hierarchy is excluded
for each. For many workflows one view layer can be used, these are more of an
advanced feature now.
OUTLINER
* The outliner now has a "View Layer" display mode instead of "Collections",
which can display the collections and/or objects in the view layer.
* In this display mode, collections can be excluded with the right click menu.
These will then be greyed out and their objects will be excluded.
* To view collections not linked to any scene, the "Blender File" display mode
can be used, with the new filtering option to just see Colleciton datablocks.
* The outliner right click menus for collections and objects were reorganized.
* Drag and drop still needs to be improved. Like before, dragging the icon or
text gives different results, we'll unify this later.
LINKING AND OVERRIDES
* Collections can now be linked into the scene without creating an instance,
with the link/append operator or from the collections view in the outliner.
* Collections can get static overrides with the right click menu in the outliner,
but this is rather unreliable and not clearly communicated at the moment.
* We still need to improve the make override operator to turn collection instances
into collections with overrides directly in the scene.
PERFORMANCE
* We tried to make performance not worse than before and improve it in some
cases. The main thing that's still a bit slower is multiple scenes, we have to
change the layer syncing to only updated affected scenes.
* Collections keep a list of their parent collections for faster incremental
updates in syncing and caching.
* View layer bases are now in a object -> base hash to avoid quadratic time
lookups internally and in API functions like visible_get().
VERSIONING
* Compatibility with 2.7 files should be improved due to the new visibility
controls. Of course users may not want to set up their scenes differently
now to avoid having separate layers and groups.
* Compatibility with 2.8 is mostly there, and was tested on Eevee demo and Hero
files. There's a few things which are know to be not quite compatible, like
nested layer collections inside groups.
* The versioning code for 2.8 files is quite complicated, and isolated behind
#ifdef so it can be removed at the end of the release cycle.
KNOWN ISSUES
* The G-key group operators in the 3D viewport were left mostly as is, they
need to be modified still to fit better.
* Same for the groups panel in the object properties. This needs to be updated
still, or perhaps replaced by something better.
* Collections must all have a unique name. Less restrictive namespacing is to
be done later, we'll have to see how important this is as all objects within
the collections must also have a unique name anyway.
* Full scene copy and delete scene are exactly doing the right thing yet.
Differential Revision: https://developer.blender.org/D3383
https://code.blender.org/2018/05/collections-and-groups/
2018-04-30 15:57:22 +02:00
|
|
|
else if (transflag & OB_DUPLICOLLECTION) {
|
|
|
|
|
return &gen_dupli_collection;
|
2014-01-21 12:11:34 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-04-01 15:54:48 -05:00
|
|
|
return nullptr;
|
2014-01-21 12:11:34 +01:00
|
|
|
}
|
|
|
|
|
|
2020-08-10 18:29:17 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Dupli-Container Implementation
|
|
|
|
|
* \{ */
|
2014-01-21 12:11:34 +01:00
|
|
|
|
2018-06-06 14:39:05 +02:00
|
|
|
ListBase *object_duplilist(Depsgraph *depsgraph, Scene *sce, Object *ob)
|
2014-01-21 12:11:34 +01:00
|
|
|
{
|
2021-12-24 22:17:49 -05:00
|
|
|
ListBase *duplilist = MEM_cnew<ListBase>("duplilist");
|
2014-01-21 12:11:34 +01:00
|
|
|
DupliContext ctx;
|
2021-04-27 12:33:40 +02:00
|
|
|
Vector<Object *> instance_stack;
|
2022-11-11 09:06:50 -06:00
|
|
|
Vector<short> dupli_gen_type_stack({0});
|
2021-04-27 12:33:40 +02:00
|
|
|
instance_stack.append(ob);
|
2022-11-11 09:06:50 -06:00
|
|
|
init_context(&ctx, depsgraph, sce, ob, nullptr, instance_stack, dupli_gen_type_stack);
|
2014-01-21 12:11:34 +01:00
|
|
|
if (ctx.gen) {
|
|
|
|
|
ctx.duplilist = duplilist;
|
|
|
|
|
ctx.gen->make_duplis(&ctx);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-01-21 12:11:34 +01:00
|
|
|
return duplilist;
|
|
|
|
|
}
|
|
|
|
|
|
Geometry Nodes: viewport preview
This adds support for showing geometry passed to the Viewer in the 3d
viewport (instead of just in the spreadsheet). The "viewer geometry"
bypasses the group output. So it is not necessary to change the final
output of the node group to be able to see the intermediate geometry.
**Activation and deactivation of a viewer node**
* A viewer node is activated by clicking on it.
* Ctrl+shift+click on any node/socket connects it to the viewer and
makes it active.
* Ctrl+shift+click in empty space deactivates the active viewer.
* When the active viewer is not visible anymore (e.g. another object
is selected, or the current node group is exit), it is deactivated.
* Clicking on the icon in the header of the Viewer node toggles whether
its active or not.
**Pinning**
* The spreadsheet still allows pinning the active viewer as before.
When pinned, the spreadsheet still references the viewer node even
when it becomes inactive.
* The viewport does not support pinning at the moment. It always shows
the active viewer.
**Attribute**
* When a field is linked to the second input of the viewer node it is
displayed as an overlay in the viewport.
* When possible the correct domain for the attribute is determined
automatically. This does not work in all cases. It falls back to the
face corner domain on meshes and the point domain on curves. When
necessary, the domain can be picked manually.
* The spreadsheet now only shows the "Viewer" column for the domain
that is selected in the Viewer node.
* Instance attributes are visualized as a constant color per instance.
**Viewport Options**
* The attribute overlay opacity can be controlled with the "Viewer Node"
setting in the overlays popover.
* A viewport can be configured not to show intermediate viewer-geometry
by disabling the "Viewer Node" option in the "View" menu.
**Implementation Details**
* The "spreadsheet context path" was generalized to a "viewer path" that
is used in more places now.
* The viewer node itself determines the attribute domain, evaluates the
field and stores the result in a `.viewer` attribute.
* A new "viewer attribute' overlay displays the data from the `.viewer`
attribute.
* The ground truth for the active viewer node is stored in the workspace
now. Node editors, spreadsheets and viewports retrieve the active
viewer from there unless they are pinned.
* The depsgraph object iterator has a new "viewer path" setting. When set,
the viewed geometry of the corresponding object is part of the iterator
instead of the final evaluated geometry.
* To support the instance attribute overlay `DupliObject` was extended
to contain the information necessary for drawing the overlay.
* The ctrl+shift+click operator has been refactored so that it can make
existing links to viewers active again.
* The auto-domain-detection in the Viewer node works by checking the
"preferred domain" for every field input. If there is not exactly one
preferred domain, the fallback is used.
Known limitations:
* Loose edges of meshes don't have the attribute overlay. This could be
added separately if necessary.
* Some attributes are hard to visualize as a color directly. For example,
the values might have to be normalized or some should be drawn as arrays.
For now, we encourage users to build node groups that generate appropriate
viewer-geometry. We might include some of that functionality in future versions.
Support for displaying attribute values as text in the viewport is planned as well.
* There seems to be an issue with the attribute overlay for pointclouds on
nvidia gpus, to be investigated.
Differential Revision: https://developer.blender.org/D15954
2022-09-28 17:54:59 +02:00
|
|
|
ListBase *object_duplilist_preview(Depsgraph *depsgraph,
|
|
|
|
|
Scene *sce,
|
|
|
|
|
Object *ob_eval,
|
|
|
|
|
const ViewerPath *viewer_path)
|
|
|
|
|
{
|
|
|
|
|
ListBase *duplilist = MEM_cnew<ListBase>("duplilist");
|
|
|
|
|
DupliContext ctx;
|
|
|
|
|
Vector<Object *> instance_stack;
|
2022-11-11 09:06:50 -06:00
|
|
|
Vector<short> dupli_gen_type_stack({0});
|
Geometry Nodes: viewport preview
This adds support for showing geometry passed to the Viewer in the 3d
viewport (instead of just in the spreadsheet). The "viewer geometry"
bypasses the group output. So it is not necessary to change the final
output of the node group to be able to see the intermediate geometry.
**Activation and deactivation of a viewer node**
* A viewer node is activated by clicking on it.
* Ctrl+shift+click on any node/socket connects it to the viewer and
makes it active.
* Ctrl+shift+click in empty space deactivates the active viewer.
* When the active viewer is not visible anymore (e.g. another object
is selected, or the current node group is exit), it is deactivated.
* Clicking on the icon in the header of the Viewer node toggles whether
its active or not.
**Pinning**
* The spreadsheet still allows pinning the active viewer as before.
When pinned, the spreadsheet still references the viewer node even
when it becomes inactive.
* The viewport does not support pinning at the moment. It always shows
the active viewer.
**Attribute**
* When a field is linked to the second input of the viewer node it is
displayed as an overlay in the viewport.
* When possible the correct domain for the attribute is determined
automatically. This does not work in all cases. It falls back to the
face corner domain on meshes and the point domain on curves. When
necessary, the domain can be picked manually.
* The spreadsheet now only shows the "Viewer" column for the domain
that is selected in the Viewer node.
* Instance attributes are visualized as a constant color per instance.
**Viewport Options**
* The attribute overlay opacity can be controlled with the "Viewer Node"
setting in the overlays popover.
* A viewport can be configured not to show intermediate viewer-geometry
by disabling the "Viewer Node" option in the "View" menu.
**Implementation Details**
* The "spreadsheet context path" was generalized to a "viewer path" that
is used in more places now.
* The viewer node itself determines the attribute domain, evaluates the
field and stores the result in a `.viewer` attribute.
* A new "viewer attribute' overlay displays the data from the `.viewer`
attribute.
* The ground truth for the active viewer node is stored in the workspace
now. Node editors, spreadsheets and viewports retrieve the active
viewer from there unless they are pinned.
* The depsgraph object iterator has a new "viewer path" setting. When set,
the viewed geometry of the corresponding object is part of the iterator
instead of the final evaluated geometry.
* To support the instance attribute overlay `DupliObject` was extended
to contain the information necessary for drawing the overlay.
* The ctrl+shift+click operator has been refactored so that it can make
existing links to viewers active again.
* The auto-domain-detection in the Viewer node works by checking the
"preferred domain" for every field input. If there is not exactly one
preferred domain, the fallback is used.
Known limitations:
* Loose edges of meshes don't have the attribute overlay. This could be
added separately if necessary.
* Some attributes are hard to visualize as a color directly. For example,
the values might have to be normalized or some should be drawn as arrays.
For now, we encourage users to build node groups that generate appropriate
viewer-geometry. We might include some of that functionality in future versions.
Support for displaying attribute values as text in the viewport is planned as well.
* There seems to be an issue with the attribute overlay for pointclouds on
nvidia gpus, to be investigated.
Differential Revision: https://developer.blender.org/D15954
2022-09-28 17:54:59 +02:00
|
|
|
instance_stack.append(ob_eval);
|
2022-11-11 09:06:50 -06:00
|
|
|
init_context(&ctx, depsgraph, sce, ob_eval, nullptr, instance_stack, dupli_gen_type_stack);
|
Geometry Nodes: viewport preview
This adds support for showing geometry passed to the Viewer in the 3d
viewport (instead of just in the spreadsheet). The "viewer geometry"
bypasses the group output. So it is not necessary to change the final
output of the node group to be able to see the intermediate geometry.
**Activation and deactivation of a viewer node**
* A viewer node is activated by clicking on it.
* Ctrl+shift+click on any node/socket connects it to the viewer and
makes it active.
* Ctrl+shift+click in empty space deactivates the active viewer.
* When the active viewer is not visible anymore (e.g. another object
is selected, or the current node group is exit), it is deactivated.
* Clicking on the icon in the header of the Viewer node toggles whether
its active or not.
**Pinning**
* The spreadsheet still allows pinning the active viewer as before.
When pinned, the spreadsheet still references the viewer node even
when it becomes inactive.
* The viewport does not support pinning at the moment. It always shows
the active viewer.
**Attribute**
* When a field is linked to the second input of the viewer node it is
displayed as an overlay in the viewport.
* When possible the correct domain for the attribute is determined
automatically. This does not work in all cases. It falls back to the
face corner domain on meshes and the point domain on curves. When
necessary, the domain can be picked manually.
* The spreadsheet now only shows the "Viewer" column for the domain
that is selected in the Viewer node.
* Instance attributes are visualized as a constant color per instance.
**Viewport Options**
* The attribute overlay opacity can be controlled with the "Viewer Node"
setting in the overlays popover.
* A viewport can be configured not to show intermediate viewer-geometry
by disabling the "Viewer Node" option in the "View" menu.
**Implementation Details**
* The "spreadsheet context path" was generalized to a "viewer path" that
is used in more places now.
* The viewer node itself determines the attribute domain, evaluates the
field and stores the result in a `.viewer` attribute.
* A new "viewer attribute' overlay displays the data from the `.viewer`
attribute.
* The ground truth for the active viewer node is stored in the workspace
now. Node editors, spreadsheets and viewports retrieve the active
viewer from there unless they are pinned.
* The depsgraph object iterator has a new "viewer path" setting. When set,
the viewed geometry of the corresponding object is part of the iterator
instead of the final evaluated geometry.
* To support the instance attribute overlay `DupliObject` was extended
to contain the information necessary for drawing the overlay.
* The ctrl+shift+click operator has been refactored so that it can make
existing links to viewers active again.
* The auto-domain-detection in the Viewer node works by checking the
"preferred domain" for every field input. If there is not exactly one
preferred domain, the fallback is used.
Known limitations:
* Loose edges of meshes don't have the attribute overlay. This could be
added separately if necessary.
* Some attributes are hard to visualize as a color directly. For example,
the values might have to be normalized or some should be drawn as arrays.
For now, we encourage users to build node groups that generate appropriate
viewer-geometry. We might include some of that functionality in future versions.
Support for displaying attribute values as text in the viewport is planned as well.
* There seems to be an issue with the attribute overlay for pointclouds on
nvidia gpus, to be investigated.
Differential Revision: https://developer.blender.org/D15954
2022-09-28 17:54:59 +02:00
|
|
|
ctx.duplilist = duplilist;
|
|
|
|
|
|
|
|
|
|
Object *ob_orig = DEG_get_original_object(ob_eval);
|
|
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (ModifierData *, md_orig, &ob_orig->modifiers) {
|
|
|
|
|
if (md_orig->type != eModifierType_Nodes) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
NodesModifierData *nmd_orig = reinterpret_cast<NodesModifierData *>(md_orig);
|
2023-07-11 12:55:57 +02:00
|
|
|
if (!nmd_orig->runtime->eval_log) {
|
Geometry Nodes: viewport preview
This adds support for showing geometry passed to the Viewer in the 3d
viewport (instead of just in the spreadsheet). The "viewer geometry"
bypasses the group output. So it is not necessary to change the final
output of the node group to be able to see the intermediate geometry.
**Activation and deactivation of a viewer node**
* A viewer node is activated by clicking on it.
* Ctrl+shift+click on any node/socket connects it to the viewer and
makes it active.
* Ctrl+shift+click in empty space deactivates the active viewer.
* When the active viewer is not visible anymore (e.g. another object
is selected, or the current node group is exit), it is deactivated.
* Clicking on the icon in the header of the Viewer node toggles whether
its active or not.
**Pinning**
* The spreadsheet still allows pinning the active viewer as before.
When pinned, the spreadsheet still references the viewer node even
when it becomes inactive.
* The viewport does not support pinning at the moment. It always shows
the active viewer.
**Attribute**
* When a field is linked to the second input of the viewer node it is
displayed as an overlay in the viewport.
* When possible the correct domain for the attribute is determined
automatically. This does not work in all cases. It falls back to the
face corner domain on meshes and the point domain on curves. When
necessary, the domain can be picked manually.
* The spreadsheet now only shows the "Viewer" column for the domain
that is selected in the Viewer node.
* Instance attributes are visualized as a constant color per instance.
**Viewport Options**
* The attribute overlay opacity can be controlled with the "Viewer Node"
setting in the overlays popover.
* A viewport can be configured not to show intermediate viewer-geometry
by disabling the "Viewer Node" option in the "View" menu.
**Implementation Details**
* The "spreadsheet context path" was generalized to a "viewer path" that
is used in more places now.
* The viewer node itself determines the attribute domain, evaluates the
field and stores the result in a `.viewer` attribute.
* A new "viewer attribute' overlay displays the data from the `.viewer`
attribute.
* The ground truth for the active viewer node is stored in the workspace
now. Node editors, spreadsheets and viewports retrieve the active
viewer from there unless they are pinned.
* The depsgraph object iterator has a new "viewer path" setting. When set,
the viewed geometry of the corresponding object is part of the iterator
instead of the final evaluated geometry.
* To support the instance attribute overlay `DupliObject` was extended
to contain the information necessary for drawing the overlay.
* The ctrl+shift+click operator has been refactored so that it can make
existing links to viewers active again.
* The auto-domain-detection in the Viewer node works by checking the
"preferred domain" for every field input. If there is not exactly one
preferred domain, the fallback is used.
Known limitations:
* Loose edges of meshes don't have the attribute overlay. This could be
added separately if necessary.
* Some attributes are hard to visualize as a color directly. For example,
the values might have to be normalized or some should be drawn as arrays.
For now, we encourage users to build node groups that generate appropriate
viewer-geometry. We might include some of that functionality in future versions.
Support for displaying attribute values as text in the viewport is planned as well.
* There seems to be an issue with the attribute overlay for pointclouds on
nvidia gpus, to be investigated.
Differential Revision: https://developer.blender.org/D15954
2022-09-28 17:54:59 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
2022-12-29 12:01:32 -05:00
|
|
|
if (const geo_log::ViewerNodeLog *viewer_log =
|
|
|
|
|
geo_log::GeoModifierLog::find_viewer_node_log_for_path(*viewer_path))
|
|
|
|
|
{
|
Geometry Nodes: viewport preview
This adds support for showing geometry passed to the Viewer in the 3d
viewport (instead of just in the spreadsheet). The "viewer geometry"
bypasses the group output. So it is not necessary to change the final
output of the node group to be able to see the intermediate geometry.
**Activation and deactivation of a viewer node**
* A viewer node is activated by clicking on it.
* Ctrl+shift+click on any node/socket connects it to the viewer and
makes it active.
* Ctrl+shift+click in empty space deactivates the active viewer.
* When the active viewer is not visible anymore (e.g. another object
is selected, or the current node group is exit), it is deactivated.
* Clicking on the icon in the header of the Viewer node toggles whether
its active or not.
**Pinning**
* The spreadsheet still allows pinning the active viewer as before.
When pinned, the spreadsheet still references the viewer node even
when it becomes inactive.
* The viewport does not support pinning at the moment. It always shows
the active viewer.
**Attribute**
* When a field is linked to the second input of the viewer node it is
displayed as an overlay in the viewport.
* When possible the correct domain for the attribute is determined
automatically. This does not work in all cases. It falls back to the
face corner domain on meshes and the point domain on curves. When
necessary, the domain can be picked manually.
* The spreadsheet now only shows the "Viewer" column for the domain
that is selected in the Viewer node.
* Instance attributes are visualized as a constant color per instance.
**Viewport Options**
* The attribute overlay opacity can be controlled with the "Viewer Node"
setting in the overlays popover.
* A viewport can be configured not to show intermediate viewer-geometry
by disabling the "Viewer Node" option in the "View" menu.
**Implementation Details**
* The "spreadsheet context path" was generalized to a "viewer path" that
is used in more places now.
* The viewer node itself determines the attribute domain, evaluates the
field and stores the result in a `.viewer` attribute.
* A new "viewer attribute' overlay displays the data from the `.viewer`
attribute.
* The ground truth for the active viewer node is stored in the workspace
now. Node editors, spreadsheets and viewports retrieve the active
viewer from there unless they are pinned.
* The depsgraph object iterator has a new "viewer path" setting. When set,
the viewed geometry of the corresponding object is part of the iterator
instead of the final evaluated geometry.
* To support the instance attribute overlay `DupliObject` was extended
to contain the information necessary for drawing the overlay.
* The ctrl+shift+click operator has been refactored so that it can make
existing links to viewers active again.
* The auto-domain-detection in the Viewer node works by checking the
"preferred domain" for every field input. If there is not exactly one
preferred domain, the fallback is used.
Known limitations:
* Loose edges of meshes don't have the attribute overlay. This could be
added separately if necessary.
* Some attributes are hard to visualize as a color directly. For example,
the values might have to be normalized or some should be drawn as arrays.
For now, we encourage users to build node groups that generate appropriate
viewer-geometry. We might include some of that functionality in future versions.
Support for displaying attribute values as text in the viewport is planned as well.
* There seems to be an issue with the attribute overlay for pointclouds on
nvidia gpus, to be investigated.
Differential Revision: https://developer.blender.org/D15954
2022-09-28 17:54:59 +02:00
|
|
|
ctx.preview_base_geometry = &viewer_log->geometry;
|
2024-02-19 15:54:48 +01:00
|
|
|
make_duplis_geometry_set_impl(
|
|
|
|
|
&ctx, viewer_log->geometry, ob_eval->object_to_world, true, ob_eval->type == OB_CURVES);
|
Geometry Nodes: viewport preview
This adds support for showing geometry passed to the Viewer in the 3d
viewport (instead of just in the spreadsheet). The "viewer geometry"
bypasses the group output. So it is not necessary to change the final
output of the node group to be able to see the intermediate geometry.
**Activation and deactivation of a viewer node**
* A viewer node is activated by clicking on it.
* Ctrl+shift+click on any node/socket connects it to the viewer and
makes it active.
* Ctrl+shift+click in empty space deactivates the active viewer.
* When the active viewer is not visible anymore (e.g. another object
is selected, or the current node group is exit), it is deactivated.
* Clicking on the icon in the header of the Viewer node toggles whether
its active or not.
**Pinning**
* The spreadsheet still allows pinning the active viewer as before.
When pinned, the spreadsheet still references the viewer node even
when it becomes inactive.
* The viewport does not support pinning at the moment. It always shows
the active viewer.
**Attribute**
* When a field is linked to the second input of the viewer node it is
displayed as an overlay in the viewport.
* When possible the correct domain for the attribute is determined
automatically. This does not work in all cases. It falls back to the
face corner domain on meshes and the point domain on curves. When
necessary, the domain can be picked manually.
* The spreadsheet now only shows the "Viewer" column for the domain
that is selected in the Viewer node.
* Instance attributes are visualized as a constant color per instance.
**Viewport Options**
* The attribute overlay opacity can be controlled with the "Viewer Node"
setting in the overlays popover.
* A viewport can be configured not to show intermediate viewer-geometry
by disabling the "Viewer Node" option in the "View" menu.
**Implementation Details**
* The "spreadsheet context path" was generalized to a "viewer path" that
is used in more places now.
* The viewer node itself determines the attribute domain, evaluates the
field and stores the result in a `.viewer` attribute.
* A new "viewer attribute' overlay displays the data from the `.viewer`
attribute.
* The ground truth for the active viewer node is stored in the workspace
now. Node editors, spreadsheets and viewports retrieve the active
viewer from there unless they are pinned.
* The depsgraph object iterator has a new "viewer path" setting. When set,
the viewed geometry of the corresponding object is part of the iterator
instead of the final evaluated geometry.
* To support the instance attribute overlay `DupliObject` was extended
to contain the information necessary for drawing the overlay.
* The ctrl+shift+click operator has been refactored so that it can make
existing links to viewers active again.
* The auto-domain-detection in the Viewer node works by checking the
"preferred domain" for every field input. If there is not exactly one
preferred domain, the fallback is used.
Known limitations:
* Loose edges of meshes don't have the attribute overlay. This could be
added separately if necessary.
* Some attributes are hard to visualize as a color directly. For example,
the values might have to be normalized or some should be drawn as arrays.
For now, we encourage users to build node groups that generate appropriate
viewer-geometry. We might include some of that functionality in future versions.
Support for displaying attribute values as text in the viewport is planned as well.
* There seems to be an issue with the attribute overlay for pointclouds on
nvidia gpus, to be investigated.
Differential Revision: https://developer.blender.org/D15954
2022-09-28 17:54:59 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return duplilist;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-21 12:11:34 +01:00
|
|
|
void free_object_duplilist(ListBase *lb)
|
|
|
|
|
{
|
|
|
|
|
BLI_freelistN(lb);
|
|
|
|
|
MEM_freeN(lb);
|
|
|
|
|
}
|
2020-08-10 18:29:17 +10:00
|
|
|
|
|
|
|
|
/** \} */
|
2022-09-30 18:54:26 +03:00
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Uniform attribute lookup
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2022-09-30 21:00:27 +03:00
|
|
|
/** Lookup instance attributes assigned via geometry nodes. */
|
|
|
|
|
static bool find_geonode_attribute_rgba(const DupliObject *dupli,
|
|
|
|
|
const char *name,
|
|
|
|
|
float r_value[4])
|
|
|
|
|
{
|
|
|
|
|
using namespace blender;
|
2023-06-15 22:18:28 +02:00
|
|
|
using namespace blender::bke;
|
2022-09-30 21:00:27 +03:00
|
|
|
|
|
|
|
|
/* Loop over layers from innermost to outermost. */
|
2023-02-14 11:50:00 +11:00
|
|
|
for (const int i : IndexRange(ARRAY_SIZE(dupli->instance_data))) {
|
2022-09-30 21:00:27 +03:00
|
|
|
/* Skip non-geonode layers. */
|
|
|
|
|
if (dupli->instance_data[i] == nullptr) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const InstancesComponent *component =
|
2023-08-03 17:09:18 +02:00
|
|
|
dupli->instance_data[i]->get_component<InstancesComponent>();
|
2022-09-30 21:00:27 +03:00
|
|
|
|
|
|
|
|
if (component == nullptr) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Attempt to look up the attribute. */
|
|
|
|
|
std::optional<bke::AttributeAccessor> attributes = component->attributes();
|
2023-04-19 11:21:06 +02:00
|
|
|
const VArray data = *attributes->lookup<ColorGeometry4f>(name);
|
2022-09-30 21:00:27 +03:00
|
|
|
|
|
|
|
|
/* If the attribute was found and converted to float RGBA successfully, output it. */
|
|
|
|
|
if (data) {
|
|
|
|
|
copy_v4_v4(r_value, data[dupli->instance_idx[i]]);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-30 18:54:26 +03:00
|
|
|
/** Lookup an arbitrary RNA property and convert it to RGBA if possible. */
|
|
|
|
|
static bool find_rna_property_rgba(PointerRNA *id_ptr, const char *name, float r_data[4])
|
|
|
|
|
{
|
|
|
|
|
if (id_ptr->data == nullptr) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* First, check custom properties. */
|
|
|
|
|
IDProperty *group = RNA_struct_idprops(id_ptr, false);
|
|
|
|
|
PropertyRNA *prop = nullptr;
|
|
|
|
|
|
|
|
|
|
if (group && group->type == IDP_GROUP) {
|
|
|
|
|
prop = (PropertyRNA *)IDP_GetPropertyFromGroup(group, name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If not found, do full path lookup. */
|
|
|
|
|
PointerRNA ptr;
|
|
|
|
|
|
|
|
|
|
if (prop != nullptr) {
|
|
|
|
|
ptr = *id_ptr;
|
|
|
|
|
}
|
|
|
|
|
else if (!RNA_path_resolve(id_ptr, name, &ptr, &prop)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (prop == nullptr) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Convert the value to RGBA if possible. */
|
|
|
|
|
PropertyType type = RNA_property_type(prop);
|
|
|
|
|
int array_len = RNA_property_array_length(&ptr, prop);
|
|
|
|
|
|
|
|
|
|
if (array_len == 0) {
|
|
|
|
|
float value;
|
|
|
|
|
|
|
|
|
|
if (type == PROP_FLOAT) {
|
|
|
|
|
value = RNA_property_float_get(&ptr, prop);
|
|
|
|
|
}
|
|
|
|
|
else if (type == PROP_INT) {
|
2022-10-07 22:52:52 +11:00
|
|
|
value = float(RNA_property_int_get(&ptr, prop));
|
2022-09-30 18:54:26 +03:00
|
|
|
}
|
|
|
|
|
else if (type == PROP_BOOLEAN) {
|
|
|
|
|
value = RNA_property_boolean_get(&ptr, prop) ? 1.0f : 0.0f;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
copy_v4_fl4(r_data, value, value, value, 1);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (type == PROP_FLOAT && array_len <= 4) {
|
|
|
|
|
copy_v4_fl4(r_data, 0, 0, 0, 1);
|
|
|
|
|
RNA_property_float_get_array(&ptr, prop, r_data);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (type == PROP_INT && array_len <= 4) {
|
|
|
|
|
int tmp[4] = {0, 0, 0, 1};
|
|
|
|
|
RNA_property_int_get_array(&ptr, prop, tmp);
|
|
|
|
|
for (int i = 0; i < 4; i++) {
|
2022-10-07 22:52:52 +11:00
|
|
|
r_data[i] = float(tmp[i]);
|
2022-09-30 18:54:26 +03:00
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-30 19:54:06 -05:00
|
|
|
static bool find_rna_property_rgba(const ID *id, const char *name, float r_data[4])
|
2022-09-30 18:54:26 +03:00
|
|
|
{
|
2023-11-30 19:54:06 -05:00
|
|
|
PointerRNA ptr = RNA_id_pointer_create(const_cast<ID *>(id));
|
2022-09-30 18:54:26 +03:00
|
|
|
return find_rna_property_rgba(&ptr, name, r_data);
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-30 19:54:06 -05:00
|
|
|
bool BKE_object_dupli_find_rgba_attribute(const Object *ob,
|
|
|
|
|
const DupliObject *dupli,
|
|
|
|
|
const Object *dupli_parent,
|
|
|
|
|
const char *name,
|
|
|
|
|
float r_value[4])
|
2022-09-30 18:54:26 +03:00
|
|
|
{
|
|
|
|
|
/* Check the dupli particle system. */
|
|
|
|
|
if (dupli && dupli->particle_system) {
|
2023-11-30 19:54:06 -05:00
|
|
|
const ParticleSettings *settings = dupli->particle_system->part;
|
2022-09-30 18:54:26 +03:00
|
|
|
|
|
|
|
|
if (find_rna_property_rgba(&settings->id, name, r_value)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-30 21:00:27 +03:00
|
|
|
/* Check geometry node dupli instance attributes. */
|
|
|
|
|
if (dupli && find_geonode_attribute_rgba(dupli, name, r_value)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-30 18:54:26 +03:00
|
|
|
/* Check the dupli parent object. */
|
|
|
|
|
if (dupli_parent && find_rna_property_rgba(&dupli_parent->id, name, r_value)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check the main object. */
|
|
|
|
|
if (ob) {
|
|
|
|
|
if (find_rna_property_rgba(&ob->id, name, r_value)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check the main object data (e.g. mesh). */
|
2023-11-30 19:54:06 -05:00
|
|
|
if (ob->data && find_rna_property_rgba((const ID *)ob->data, name, r_value)) {
|
2022-09-30 18:54:26 +03:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
copy_v4_fl(r_value, 0.0f);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-30 19:54:06 -05:00
|
|
|
bool BKE_view_layer_find_rgba_attribute(const Scene *scene,
|
|
|
|
|
const ViewLayer *layer,
|
Attribute Node: support accessing attributes of View Layer and Scene.
The attribute node already allows accessing attributes associated
with objects and meshes, which allows changing the behavior of the
same material between different objects or instances. The same idea
can be extended to an even more global level of layers and scenes.
Currently view layers provide an option to replace all materials
with a different one. However, since the same material will be applied
to all objects in the layer, varying the behavior between layers while
preserving distinct materials requires duplicating objects.
Providing access to properties of layers and scenes via the attribute
node enables making materials with built-in switches or settings that
can be controlled globally at the view layer level. This is probably
most useful for complex NPR shading and compositing. Like with objects,
the node can also access built-in scene properties, like render resolution
or FOV of the active camera. Lookup is also attempted in World, similar
to how the Object mode checks the Mesh datablock.
In Cycles this mode is implemented by replacing the attribute node with
the attribute value during sync, allowing constant folding to take the
values into account. This means however that materials that use this
feature have to be re-synced upon any changes to scene, world or camera.
The Eevee version uses a new uniform buffer containing a sorted array
mapping name hashes to values, with binary search lookup. The array
is limited to 512 entries, which is effectively limitless even
considering it is shared by all materials in the scene; it is also
just 16KB of memory so no point trying to optimize further.
The buffer has to be rebuilt when new attributes are detected in a
material, so the draw engine keeps a table of recently seen attribute
names to minimize the chance of extra rebuilds mid-draw.
Differential Revision: https://developer.blender.org/D15941
2022-09-12 00:30:58 +03:00
|
|
|
const char *name,
|
|
|
|
|
float r_value[4])
|
|
|
|
|
{
|
|
|
|
|
if (layer) {
|
2023-11-30 19:54:06 -05:00
|
|
|
PointerRNA layer_ptr = RNA_pointer_create(
|
|
|
|
|
&const_cast<ID &>(scene->id), &RNA_ViewLayer, const_cast<ViewLayer *>(layer));
|
Attribute Node: support accessing attributes of View Layer and Scene.
The attribute node already allows accessing attributes associated
with objects and meshes, which allows changing the behavior of the
same material between different objects or instances. The same idea
can be extended to an even more global level of layers and scenes.
Currently view layers provide an option to replace all materials
with a different one. However, since the same material will be applied
to all objects in the layer, varying the behavior between layers while
preserving distinct materials requires duplicating objects.
Providing access to properties of layers and scenes via the attribute
node enables making materials with built-in switches or settings that
can be controlled globally at the view layer level. This is probably
most useful for complex NPR shading and compositing. Like with objects,
the node can also access built-in scene properties, like render resolution
or FOV of the active camera. Lookup is also attempted in World, similar
to how the Object mode checks the Mesh datablock.
In Cycles this mode is implemented by replacing the attribute node with
the attribute value during sync, allowing constant folding to take the
values into account. This means however that materials that use this
feature have to be re-synced upon any changes to scene, world or camera.
The Eevee version uses a new uniform buffer containing a sorted array
mapping name hashes to values, with binary search lookup. The array
is limited to 512 entries, which is effectively limitless even
considering it is shared by all materials in the scene; it is also
just 16KB of memory so no point trying to optimize further.
The buffer has to be rebuilt when new attributes are detected in a
material, so the draw engine keeps a table of recently seen attribute
names to minimize the chance of extra rebuilds mid-draw.
Differential Revision: https://developer.blender.org/D15941
2022-09-12 00:30:58 +03:00
|
|
|
|
|
|
|
|
if (find_rna_property_rgba(&layer_ptr, name, r_value)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (find_rna_property_rgba(&scene->id, name, r_value)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (scene->world && find_rna_property_rgba(&scene->world->id, name, r_value)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
copy_v4_fl(r_value, 0.0f);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-30 18:54:26 +03:00
|
|
|
/** \} */
|