Fix #116809: Geometry nodes UV map of UV Sphere #116856

Open
Balázs Füvesi wants to merge 15 commits from fuvesib/blender:gn-uvsphere-uvsegmentfix into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
3 changed files with 105 additions and 6 deletions

View File

@ -29,7 +29,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 9
#define BLENDER_FILE_SUBVERSION 10
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and cancel loading the file, showing a warning to

View File

@ -1802,6 +1802,96 @@ static void versioning_grease_pencil_stroke_radii_scaling(GreasePencil *grease_p
}
}
static void geometry_nodes_uv_sphere_uvmap(bNodeTree &ntree)
{
blender::Map<bNode *, bNodeLink *> primitive_nodes_inputs;
blender::MultiValueMap<bNode *, bNodeLink *> primitive_nodes_outputs;
LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) {
bNode *to_node = link->tonode;
if ((to_node->type == GEO_NODE_MESH_PRIMITIVE_UV_SPHERE) &&
fuvesib marked this conversation as resolved Outdated

You can simply check name of socket (STREQ(link->tosock->name, "Segments")). Same below.

You can simply check name of socket (`STREQ(link->tosock->name, "Segments")`). Same below.
(STREQ(link->tosock->name, "Segments")))
{
primitive_nodes_inputs.add(to_node, link);
}
fuvesib marked this conversation as resolved

Can you run in your root folder of blender fork:

git diff main --name-only
make format FILES-CHANGED-IN-BRANCH

To format this and other lines. See https://wiki.blender.org/wiki/Tools/ClangFormat

Can you run in your root folder of blender fork: ``` git diff main --name-only make format FILES-CHANGED-IN-BRANCH ``` To format this and other lines. See https://wiki.blender.org/wiki/Tools/ClangFormat
bNode *from_node = link->fromnode;
if ((from_node->type == GEO_NODE_MESH_PRIMITIVE_UV_SPHERE) &&
(STREQ(link->fromsock->name, "Mesh")))
{
primitive_nodes_outputs.add(from_node, link);
}
}
for (bNode *primitive_node : primitive_nodes_outputs.keys()) {
bNodeSocket *segments_input = nodeFindSocket(primitive_node, SOCK_IN, "Segments");
bNodeSocket *mesh_output = nodeFindSocket(primitive_node, SOCK_OUT, "Mesh");
bNode *transform_node = nodeAddStaticNode(nullptr, &ntree, GEO_NODE_TRANSFORM_GEOMETRY);
transform_node->locx = primitive_node->locx + primitive_node->width * 1.25f;
transform_node->locy = primitive_node->locy;
bNodeSocket *geometry_input = nodeFindSocket(transform_node, SOCK_IN, "Geometry");
bNodeSocket *rotation_input = nodeFindSocket(transform_node, SOCK_IN, "Rotation");
bNodeSocket *geometry_output = nodeFindSocket(transform_node, SOCK_OUT, "Geometry");
for (bNodeLink *link : primitive_nodes_outputs.lookup(primitive_node)) {
link->fromnode = transform_node;
link->fromsock = geometry_output;
}
nodeAddLink(&ntree, primitive_node, mesh_output, transform_node, geometry_input);
bNode *euler_node = nodeAddStaticNode(nullptr, &ntree, FN_NODE_EULER_TO_ROTATION);
euler_node->locx = primitive_node->locx;
euler_node->locy = primitive_node->locy - primitive_node->height * 1.25f;
bNodeSocket *euler_input = nodeFindSocket(euler_node, SOCK_IN, "Euler");
bNodeSocket *rotation_output = nodeFindSocket(euler_node, SOCK_OUT, "Rotation");
nodeAddLink(&ntree, euler_node, rotation_output, transform_node, rotation_input);
bNode *combine_node = nodeAddStaticNode(nullptr, &ntree, SH_NODE_COMBXYZ);
combine_node->locx = euler_node->locx - euler_node->width * 1.25f;
combine_node->locy = euler_node->locy;
bNodeSocket *z_input = nodeFindSocket(combine_node, SOCK_IN, "Z");
bNodeSocket *vector_output = nodeFindSocket(combine_node, SOCK_OUT, "Vector");
nodeAddLink(&ntree, combine_node, vector_output, euler_node, euler_input);
bNode *divide_node = nodeAddStaticNode(nullptr, &ntree, SH_NODE_MATH);
divide_node->locx = combine_node->locx - combine_node->width * 1.25f;
divide_node->locy = combine_node->locy;
divide_node->custom1 = NODE_MATH_DIVIDE;
divide_node->typeinfo->updatefunc(&ntree, divide_node);
bNodeSocket *dividend_input = static_cast<bNodeSocket *>(
fuvesib marked this conversation as resolved Outdated
`2` -> `2.0f` See https://wiki.blender.org/wiki/Style_Guide/C_Cpp#Value_Literals
BLI_findlink(&divide_node->inputs, 0));
bNodeSocket *divisor_input = static_cast<bNodeSocket *>(BLI_findlink(&divide_node->inputs, 1));
bNodeSocket *value_output = nodeFindSocket(divide_node, SOCK_OUT, "Value");
*version_cycles_node_socket_float_value(dividend_input) = M_PI * 2.0f;
fuvesib marked this conversation as resolved Outdated

Add continue; in end of this branch, and delete else after. This is early return pattern (to reduce nesting).

Add `continue;` in end of this branch, and delete `else` after. This is early return pattern (to reduce nesting).
nodeAddLink(&ntree, divide_node, value_output, combine_node, z_input);
if (primitive_nodes_inputs.contains(primitive_node)) {
bNodeLink *link = primitive_nodes_inputs.lookup(primitive_node);
nodeAddLink(&ntree, link->fromnode, link->fromsock, divide_node, divisor_input);
continue;
}
bNode *segments_node = nodeAddStaticNode(nullptr, &ntree, FN_NODE_INPUT_INT);
segments_node->locx = divide_node->locx - divide_node->width * 1.25f;
segments_node->locy = primitive_node->locy;
fuvesib marked this conversation as resolved Outdated

version_cycles_node_socket_int_value->default_value_typed<bNodeSocketValueInt>()->value

`version_cycles_node_socket_int_value->default_value_typed<bNodeSocketValueInt>()->value`
NodeInputInt *node_storage = static_cast<NodeInputInt *>(segments_node->storage);
node_storage->integer = segments_input->default_value_typed<bNodeSocketValueInt>()->value;
bNodeSocket *integer_output = nodeFindSocket(segments_node, SOCK_OUT, "Integer");
nodeAddLink(&ntree, segments_node, integer_output, primitive_node, segments_input);
nodeAddLink(&ntree, segments_node, integer_output, divide_node, divisor_input);
}
}
void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
{
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 1)) {
@ -2559,6 +2649,15 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
}
}
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 10)) {
LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
if (ntree->type != NTREE_GEOMETRY) {
continue;
}
geometry_nodes_uv_sphere_uvmap(*ntree);
}
}
/**
* Versioning code until next subversion bump goes here.
*

View File

@ -67,13 +67,13 @@ BLI_NOINLINE static void calculate_sphere_vertex_data(MutableSpan<float3> positi
const float delta_theta = M_PI / rings;
const float delta_phi = (2.0f * M_PI) / segments;
Array<float, 64> segment_cosines(segments + 1);
for (const int segment : IndexRange(1, segments)) {
Array<float, 64> segment_cosines(segments);
for (const int segment : IndexRange(segments)) {
const float phi = segment * delta_phi;
segment_cosines[segment] = std::cos(phi);
}
Array<float, 64> segment_sines(segments + 1);
for (const int segment : IndexRange(1, segments)) {
Array<float, 64> segment_sines(segments);
for (const int segment : IndexRange(segments)) {
const float phi = segment * delta_phi;
segment_sines[segment] = std::sin(phi);
}
@ -86,7 +86,7 @@ BLI_NOINLINE static void calculate_sphere_vertex_data(MutableSpan<float3> positi
const float theta = ring * delta_theta;
const float sin_theta = std::sin(theta);
const float z = std::cos(theta);
for (const int segment : IndexRange(1, segments)) {
for (const int segment : IndexRange(segments)) {
const float x = sin_theta * segment_cosines[segment];
const float y = sin_theta * segment_sines[segment];
positions[vert_index] = float3(x, y, z) * radius;