Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHimanshi Kalra <himanshikalra98@gmail.com>2020-12-17 18:07:01 +0300
committerHimanshi Kalra <himanshikalra98@gmail.com>2020-12-17 18:07:01 +0300
commit2d0c84cf765b62cf902fdc1852e68dd8ae5b0d52 (patch)
tree9ce2a9457f9e4b8aa5e40d83da8ffd6ac2c2ccd5
parent167eace0e73bef77cf362af04f1f0dd47c492a92 (diff)
parent3fc07d1e7482a6472bf6e34616ebe7b616189274 (diff)
Merge branch 'master' into soc-2020-testing-frameworkssoc-2020-testing-frameworks
-rw-r--r--intern/ghost/CMakeLists.txt14
-rw-r--r--source/blender/blenkernel/BKE_attribute_access.hh2
-rw-r--r--source/blender/blenkernel/BKE_geometry_set.hh5
-rw-r--r--source/blender/blenkernel/intern/attribute_access.cc22
-rw-r--r--source/blender/blenlib/BLI_hash.h58
-rw-r--r--source/blender/makesdna/DNA_modifier_defaults.h4
-rw-r--r--source/blender/nodes/NOD_geometry_exec.hh2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc84
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc42
9 files changed, 182 insertions, 51 deletions
diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt
index e8611839aea..1739659ab88 100644
--- a/intern/ghost/CMakeLists.txt
+++ b/intern/ghost/CMakeLists.txt
@@ -187,6 +187,11 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
${X11_X11_INCLUDE_PATH}
)
+ list(APPEND LIB
+ ${X11_X11_LIB}
+ ${X11_Xrender_LIB}
+ )
+
list(APPEND SRC
intern/GHOST_DisplayManagerX11.cpp
intern/GHOST_SystemX11.cpp
@@ -238,6 +243,9 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
list(APPEND INC_SYS
${X11_xf86vmode_INCLUDE_PATH}
)
+ list(APPEND LIB
+ ${X11_Xf86vmode_LIB}
+ )
endif()
if(WITH_X11_XFIXES)
@@ -245,6 +253,9 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
list(APPEND INC_SYS
${X11_Xfixes_INCLUDE_PATH}
)
+ list(APPEND LIB
+ ${X11_Xfixes_LIB}
+ )
endif()
if(WITH_X11_ALPHA)
@@ -256,6 +267,9 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
list(APPEND INC_SYS
${X11_Xinput_INCLUDE_PATH}
)
+ list(APPEND LIB
+ ${X11_Xinput_LIB}
+ )
endif()
add_definitions(-DWITH_GHOST_X11)
diff --git a/source/blender/blenkernel/BKE_attribute_access.hh b/source/blender/blenkernel/BKE_attribute_access.hh
index eafd86d176b..22e14e44bec 100644
--- a/source/blender/blenkernel/BKE_attribute_access.hh
+++ b/source/blender/blenkernel/BKE_attribute_access.hh
@@ -267,10 +267,12 @@ template<typename T> class TypedWriteAttribute {
using BooleanReadAttribute = TypedReadAttribute<bool>;
using FloatReadAttribute = TypedReadAttribute<float>;
using Float3ReadAttribute = TypedReadAttribute<float3>;
+using Int32ReadAttribute = TypedReadAttribute<int>;
using Color4fReadAttribute = TypedReadAttribute<Color4f>;
using BooleanWriteAttribute = TypedWriteAttribute<bool>;
using FloatWriteAttribute = TypedWriteAttribute<float>;
using Float3WriteAttribute = TypedWriteAttribute<float3>;
+using Int32WriteAttribute = TypedWriteAttribute<int>;
using Color4fWriteAttribute = TypedWriteAttribute<Color4f>;
} // namespace blender::bke
diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index 90d444aa270..e4232a84a00 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -136,6 +136,11 @@ class GeometryComponent {
const AttributeDomain domain,
const CustomDataType data_type) const;
+ /* Get a read-only attribute interpolated to the input domain, leaving the data type unchanged.
+ * Returns null when the attribute does not exist. */
+ blender::bke::ReadAttributePtr attribute_try_get_for_read(
+ const blender::StringRef attribute_name, const AttributeDomain domain) const;
+
/* Get a read-only attribute for the given domain and data type.
* Returns a constant attribute based on the default value if the attribute does not exist.
* Never returns null. */
diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc
index 623335f65a1..934beb8a848 100644
--- a/source/blender/blenkernel/intern/attribute_access.cc
+++ b/source/blender/blenkernel/intern/attribute_access.cc
@@ -660,6 +660,28 @@ ReadAttributePtr GeometryComponent::attribute_try_get_for_read(
return attribute;
}
+ReadAttributePtr GeometryComponent::attribute_try_get_for_read(const StringRef attribute_name,
+ const AttributeDomain domain) const
+{
+ if (!this->attribute_domain_supported(domain)) {
+ return {};
+ }
+
+ ReadAttributePtr attribute = this->attribute_try_get_for_read(attribute_name);
+ if (!attribute) {
+ return {};
+ }
+
+ if (attribute->domain() != domain) {
+ attribute = this->attribute_try_adapt_domain(std::move(attribute), domain);
+ if (!attribute) {
+ return {};
+ }
+ }
+
+ return attribute;
+}
+
ReadAttributePtr GeometryComponent::attribute_get_for_read(const StringRef attribute_name,
const AttributeDomain domain,
const CustomDataType data_type,
diff --git a/source/blender/blenlib/BLI_hash.h b/source/blender/blenlib/BLI_hash.h
index c2be416ef5f..d687e805323 100644
--- a/source/blender/blenlib/BLI_hash.h
+++ b/source/blender/blenlib/BLI_hash.h
@@ -26,35 +26,59 @@
extern "C" {
#endif
-BLI_INLINE unsigned int BLI_hash_int_2d(unsigned int kx, unsigned int ky)
-{
+/**
+ * Jenkins Lookup3 Hash Functions.
+ * Source: http://burtleburtle.net/bob/c/lookup3.c
+ */
+
#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
+#define final(a, b, c) \
+ { \
+ c ^= b; \
+ c -= rot(b, 14); \
+ a ^= c; \
+ a -= rot(c, 11); \
+ b ^= a; \
+ b -= rot(a, 25); \
+ c ^= b; \
+ c -= rot(b, 16); \
+ a ^= c; \
+ a -= rot(c, 4); \
+ b ^= a; \
+ b -= rot(a, 14); \
+ c ^= b; \
+ c -= rot(b, 24); \
+ } \
+ ((void)0)
+
+BLI_INLINE unsigned int BLI_hash_int_3d(unsigned int kx, unsigned int ky, unsigned int kz)
+{
+ unsigned int a, b, c;
+ a = b = c = 0xdeadbeef + (3 << 2) + 13;
+
+ c += kz;
+ b += ky;
+ a += kx;
+ final(a, b, c);
+
+ return c;
+}
+BLI_INLINE unsigned int BLI_hash_int_2d(unsigned int kx, unsigned int ky)
+{
unsigned int a, b, c;
a = b = c = 0xdeadbeef + (2 << 2) + 13;
a += kx;
b += ky;
- c ^= b;
- c -= rot(b, 14);
- a ^= c;
- a -= rot(c, 11);
- b ^= a;
- b -= rot(a, 25);
- c ^= b;
- c -= rot(b, 16);
- a ^= c;
- a -= rot(c, 4);
- b ^= a;
- b -= rot(a, 14);
- c ^= b;
- c -= rot(b, 24);
+ final(a, b, c);
return c;
+}
+#undef final
#undef rot
-}
BLI_INLINE unsigned int BLI_hash_string(const char *str)
{
diff --git a/source/blender/makesdna/DNA_modifier_defaults.h b/source/blender/makesdna/DNA_modifier_defaults.h
index e122d50cba8..fcb582ef837 100644
--- a/source/blender/makesdna/DNA_modifier_defaults.h
+++ b/source/blender/makesdna/DNA_modifier_defaults.h
@@ -503,8 +503,8 @@
.random_position = 0.0f, \
.rotation = 0.0f, \
.random_rotation = 0.0f, \
- .particle_offset = 1.0f, \
- .particle_amount = 0.0f, \
+ .particle_offset = 0.0f, \
+ .particle_amount = 1.0f, \
.index_layer_name = "", \
.value_layer_name = "", \
}
diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh
index 445e1ed6af2..cac04e18fc7 100644
--- a/source/blender/nodes/NOD_geometry_exec.hh
+++ b/source/blender/nodes/NOD_geometry_exec.hh
@@ -34,6 +34,8 @@ using bke::Float3ReadAttribute;
using bke::Float3WriteAttribute;
using bke::FloatReadAttribute;
using bke::FloatWriteAttribute;
+using bke::Int32ReadAttribute;
+using bke::Int32WriteAttribute;
using bke::PersistentDataHandleMap;
using bke::PersistentObjectHandle;
using bke::ReadAttribute;
diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc
index 53df2e8c087..2c3acfc9735 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc
@@ -16,6 +16,7 @@
#include "node_geometry_util.hh"
+#include "BLI_hash.h"
#include "BLI_rand.hh"
#include "DNA_mesh_types.h"
@@ -59,48 +60,85 @@ static void geo_node_attribute_randomize_update(bNodeTree *UNUSED(ntree), bNode
namespace blender::nodes {
-static void randomize_attribute(BooleanWriteAttribute &attribute, RandomNumberGenerator &rng)
+/** Rehash to combine the seed with the "id" hash and a mutator for each dimension. */
+static float noise_from_index_and_mutator(const int seed, const int hash, const int mutator)
+{
+ const int combined_hash = BLI_hash_int_3d(seed, hash, mutator);
+ return BLI_hash_int_01(combined_hash);
+}
+
+/** Rehash to combine the seed with the "id" hash. */
+static float noise_from_index(const int seed, const int hash)
+{
+ const int combined_hash = BLI_hash_int_2d(seed, hash);
+ return BLI_hash_int_01(combined_hash);
+}
+
+static void randomize_attribute(BooleanWriteAttribute &attribute, Span<int> hashes, const int seed)
{
MutableSpan<bool> attribute_span = attribute.get_span();
for (const int i : IndexRange(attribute.size())) {
- const bool value = rng.get_float() > 0.5f;
+ const bool value = noise_from_index(seed, hashes[i]) > 0.5f;
attribute_span[i] = value;
}
attribute.apply_span();
}
-static void randomize_attribute(FloatWriteAttribute &attribute,
- float min,
- float max,
- RandomNumberGenerator &rng)
+static void randomize_attribute(
+ FloatWriteAttribute &attribute, float min, float max, Span<int> hashes, const int seed)
{
MutableSpan<float> attribute_span = attribute.get_span();
for (const int i : IndexRange(attribute.size())) {
- const float value = rng.get_float() * (max - min) + min;
+ const float value = noise_from_index(seed, hashes[i]) * (max - min) + min;
attribute_span[i] = value;
}
attribute.apply_span();
}
-static void randomize_attribute(Float3WriteAttribute &attribute,
- float3 min,
- float3 max,
- RandomNumberGenerator &rng)
+static void randomize_attribute(
+ Float3WriteAttribute &attribute, float3 min, float3 max, Span<int> hashes, const int seed)
{
MutableSpan<float3> attribute_span = attribute.get_span();
for (const int i : IndexRange(attribute.size())) {
- const float x = rng.get_float();
- const float y = rng.get_float();
- const float z = rng.get_float();
+ const float x = noise_from_index_and_mutator(seed, hashes[i], 47);
+ const float y = noise_from_index_and_mutator(seed, hashes[i], 8);
+ const float z = noise_from_index_and_mutator(seed, hashes[i], 64);
const float3 value = float3(x, y, z) * (max - min) + min;
attribute_span[i] = value;
}
attribute.apply_span();
}
+static Array<int> get_element_hashes(GeometryComponent &component,
+ const AttributeDomain domain,
+ const int attribute_size)
+{
+ /* Hash the reserved name attribute "id" as a (hopefully) stable seed for each point. */
+ ReadAttributePtr hash_attribute = component.attribute_try_get_for_read("id", domain);
+ Array<int> hashes(attribute_size);
+ if (hash_attribute) {
+ BLI_assert(hashes.size() == hash_attribute->size());
+ const CPPType &cpp_type = hash_attribute->cpp_type();
+ fn::GSpan items = hash_attribute->get_span();
+ for (const int i : hashes.index_range()) {
+ hashes[i] = (int)cpp_type.hash(items[i]);
+ }
+ }
+ else {
+ /* If there is no "id" attribute for per-point variation, just create it here. */
+ RandomNumberGenerator rng;
+ rng.seed(0);
+ for (const int i : hashes.index_range()) {
+ hashes[i] = rng.get_int32();
+ }
+ }
+
+ return hashes;
+}
+
static void randomize_attribute(GeometryComponent &component,
const GeoNodeExecParams &params,
- RandomNumberGenerator &rng)
+ const int seed)
{
const bNode &node = params.node();
const CustomDataType data_type = static_cast<CustomDataType>(node.custom1);
@@ -116,24 +154,26 @@ static void randomize_attribute(GeometryComponent &component,
return;
}
+ Array<int> hashes = get_element_hashes(component, domain, attribute->size());
+
switch (data_type) {
case CD_PROP_FLOAT: {
FloatWriteAttribute float_attribute = std::move(attribute);
const float min_value = params.get_input<float>("Min_001");
const float max_value = params.get_input<float>("Max_001");
- randomize_attribute(float_attribute, min_value, max_value, rng);
+ randomize_attribute(float_attribute, min_value, max_value, hashes, seed);
break;
}
case CD_PROP_FLOAT3: {
Float3WriteAttribute float3_attribute = std::move(attribute);
const float3 min_value = params.get_input<float3>("Min");
const float3 max_value = params.get_input<float3>("Max");
- randomize_attribute(float3_attribute, min_value, max_value, rng);
+ randomize_attribute(float3_attribute, min_value, max_value, hashes, seed);
break;
}
case CD_PROP_BOOL: {
BooleanWriteAttribute boolean_attribute = std::move(attribute);
- randomize_attribute(boolean_attribute, rng);
+ randomize_attribute(boolean_attribute, hashes, seed);
break;
}
default:
@@ -147,14 +187,10 @@ static void geo_node_random_attribute_exec(GeoNodeExecParams params)
const int seed = params.get_input<int>("Seed");
if (geometry_set.has<MeshComponent>()) {
- RandomNumberGenerator rng;
- rng.seed_random(seed);
- randomize_attribute(geometry_set.get_component_for_write<MeshComponent>(), params, rng);
+ randomize_attribute(geometry_set.get_component_for_write<MeshComponent>(), params, seed);
}
if (geometry_set.has<PointCloudComponent>()) {
- RandomNumberGenerator rng;
- rng.seed_random(seed + 3245231);
- randomize_attribute(geometry_set.get_component_for_write<PointCloudComponent>(), params, rng);
+ randomize_attribute(geometry_set.get_component_for_write<PointCloudComponent>(), params, seed);
}
params.set_output("Geometry", geometry_set);
diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
index 8be9636e14d..1d3fbae5b2e 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
@@ -34,8 +34,8 @@
static bNodeSocketTemplate geo_node_point_distribute_in[] = {
{SOCK_GEOMETRY, N_("Geometry")},
- {SOCK_FLOAT, N_("Minimum Distance"), 0.1f, 0.0f, 0.0f, 0.0f, 0.0f, 100000.0f, PROP_NONE},
- {SOCK_FLOAT, N_("Maximum Density"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 100000.0f, PROP_NONE},
+ {SOCK_FLOAT, N_("Distance Min"), 0.1f, 0.0f, 0.0f, 0.0f, 0.0f, 100000.0f, PROP_NONE},
+ {SOCK_FLOAT, N_("Density Max"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 100000.0f, PROP_NONE},
{SOCK_STRING, N_("Density Attribute")},
{SOCK_INT, N_("Seed"), 0, 0, 0, 0, -10000, 10000},
{-1, ""},
@@ -58,6 +58,7 @@ namespace blender::nodes {
static Vector<float3> random_scatter_points_from_mesh(const Mesh *mesh,
const float density,
const FloatReadAttribute &density_factors,
+ Vector<int> &r_ids,
const int seed)
{
/* This only updates a cache and can be considered to be logically const. */
@@ -95,6 +96,9 @@ static Vector<float3> random_scatter_points_from_mesh(const Mesh *mesh,
float3 point_pos;
interp_v3_v3v3v3(point_pos, v0_pos, v1_pos, v2_pos, bary_coords);
points.append(point_pos);
+
+ /* Build a hash stable even when the mesh is deformed. */
+ r_ids.append(((int)(bary_coords.hash()) + looptri_index));
}
}
@@ -106,10 +110,14 @@ struct RayCastAll_Data {
BVHTree_RayCastCallback raycast_callback;
+ /** The original coordinate the result point was projected from. */
+ float2 raystart;
+
const Mesh *mesh;
float base_weight;
FloatReadAttribute *density_factors;
Vector<float3> *projected_points;
+ Vector<int> *stable_ids;
float cur_point_weight;
};
@@ -148,6 +156,9 @@ static void project_2d_bvh_callback(void *userdata,
if (point_weight >= FLT_EPSILON && data->cur_point_weight <= point_weight) {
data->projected_points->append(hit->co);
+
+ /* Build a hash stable even when the mesh is deformed. */
+ data->stable_ids->append((int)data->raystart.hash());
}
}
}
@@ -156,6 +167,7 @@ static Vector<float3> poisson_scatter_points_from_mesh(const Mesh *mesh,
const float density,
const float minimum_distance,
const FloatReadAttribute &density_factors,
+ Vector<int> &r_ids,
const int seed)
{
Vector<float3> points;
@@ -191,6 +203,7 @@ static Vector<float3> poisson_scatter_points_from_mesh(const Mesh *mesh,
const float3 bounds_max = float3(point_scale_multiplier, point_scale_multiplier, 0);
poisson_disk_point_elimination(&points, &output_points, 2.0f * minimum_distance, bounds_max);
Vector<float3> final_points;
+ r_ids.reserve(output_points_target);
final_points.reserve(output_points_target);
/* Check if we have any points we should remove from the final possion distribition. */
@@ -205,6 +218,7 @@ static Vector<float3> poisson_scatter_points_from_mesh(const Mesh *mesh,
data.raycast_callback = treedata.raycast_callback;
data.mesh = mesh;
data.projected_points = &final_points;
+ data.stable_ids = &r_ids;
data.density_factors = const_cast<FloatReadAttribute *>(&density_factors);
data.base_weight = std::min(
1.0f, density / (output_points.size() / (point_scale_multiplier * point_scale_multiplier)));
@@ -229,6 +243,7 @@ static Vector<float3> poisson_scatter_points_from_mesh(const Mesh *mesh,
raystart.y = output_points[idx].y + tile_curr_y_coord;
data.cur_point_weight = (float)idx / (float)output_points.size();
+ data.raystart = raystart;
BLI_bvhtree_ray_cast_all(
treedata.tree, raystart, dir, 0.0f, max_dist, project_2d_bvh_callback, &data);
@@ -252,7 +267,7 @@ static void geo_node_point_distribute_exec(GeoNodeExecParams params)
return;
}
- const float density = params.extract_input<float>("Maximum Density");
+ const float density = params.extract_input<float>("Density Max");
const std::string density_attribute = params.extract_input<std::string>("Density Attribute");
if (density <= 0.0f) {
@@ -267,15 +282,17 @@ static void geo_node_point_distribute_exec(GeoNodeExecParams params)
density_attribute, ATTR_DOMAIN_POINT, 1.0f);
const int seed = params.get_input<int>("Seed");
+ Vector<int> stable_ids;
Vector<float3> points;
-
switch (distribute_method) {
case GEO_NODE_POINT_DISTRIBUTE_RANDOM:
- points = random_scatter_points_from_mesh(mesh_in, density, density_factors, seed);
+ points = random_scatter_points_from_mesh(
+ mesh_in, density, density_factors, stable_ids, seed);
break;
case GEO_NODE_POINT_DISTRIBUTE_POISSON:
- const float min_dist = params.extract_input<float>("Minimum Distance");
- points = poisson_scatter_points_from_mesh(mesh_in, density, min_dist, density_factors, seed);
+ const float min_dist = params.extract_input<float>("Distance Min");
+ points = poisson_scatter_points_from_mesh(
+ mesh_in, density, min_dist, density_factors, stable_ids, seed);
break;
}
@@ -286,7 +303,16 @@ static void geo_node_point_distribute_exec(GeoNodeExecParams params)
pointcloud->radius[i] = 0.05f;
}
- geometry_set_out.replace_pointcloud(pointcloud);
+ PointCloudComponent &point_component =
+ geometry_set_out.get_component_for_write<PointCloudComponent>();
+ point_component.replace(pointcloud);
+
+ Int32WriteAttribute stable_id_attribute = point_component.attribute_try_ensure_for_write(
+ "id", ATTR_DOMAIN_POINT, CD_PROP_INT32);
+ MutableSpan<int> stable_ids_span = stable_id_attribute.get_span();
+ stable_ids_span.copy_from(stable_ids);
+ stable_id_attribute.apply_span();
+
params.set_output("Geometry", std::move(geometry_set_out));
}
} // namespace blender::nodes