3
$\begingroup$

This post was originally asking to solve a different issue with this node setup (gaps in between stacked GN objects), but as that issue has been solved by myself, the question has been edited, with permission by a Moderator (see comments below) to focus on stacking objects within a collection.


TL:DR - How can I find the scale of a random object in a geometry nodes collection node to stack those objects?

I'm attempting to create a lightweight skyscraper generator to use for a scene. Which I intend to use different collections of various meshes to make up the bottom, middle, and top sections to make modular buildings. With each piece sitting neatly on top of each other without any gaps.

The idea being, for each building, it'll pick a single base from the collection, a single middle (arrayed to a random height), and put a top on it.

It's important to note that the middle section isn't made up of random elements from the collection stacked upon each other, rather that one object is randomly chosen from the "middle" collection and arrayed to make the main body of the building. See the image below for what I mean

Example

Essentially, I'm making the array modifier using the start and end caps option, but the objects used in the array are random.

I've arrived at some kind of solution, though it's not exactly what I need just yet. I can get objects in an array, with a start and end cap, and even offset the middle and top sections depending on the size of the base. However, it's currently only working with single objects, and not collections.

["Middle" section of the image below] I take a mesh line, and use the Z-height of the middle object's bounding box to offset the points using an "Accumulate Field" node. Then I instance the middle object. By subtracting "1" from the bounding box's Z output, this stacks the sections without gaps, no matter how tall the object is.

["Base" section of the image below] Using another mesh line, I instance the base of the building.

[Top section of the image below] I use a "points" node to instance the top cap. By finding the z-height of a single section of the middle (using a similar method as before, without the subtract), then multiplying by the amount of segments the middle's "mesh line" has (currently they're driven by random values), I can offset the top cap to place it above the middle section, no matter how high it is.

["Base offset" section of the image below] Finally, I offset the middle and top sections by the height of the base.

Example of Node setup

All in all, it works great when I plug single objects into the setup for the base/middle/top sections. However, as I'd like the buildings to be random, I need to use collections, which is where my issue lies.

Unlike the "Object Info" node, Collections lack a "scale" output, which means I can't plug it into my Bounding Box group to find out how tall a given element is. If I can't find that out, I can't offset any of the pieces, and it won't make a building.

To put it into simple terms, I need to find out how tall a given element in a collection is so I can offset them.

In a perfect world, I'd want this to work without using the "realize instances" node, since as far as I understand, it turns the mesh into "real" geometry, and can (and probably will) tank performance using this generator on the scale of an entire city. At least more so than keeping everything in "instance land".

Here's a Blend file with the current node setup.

Please know that my knowledge of geo nodes is pretty limited, and I'm stretching my ability to do even this.

Thanks in advance!

$\endgroup$
9
  • $\begingroup$ Maybe Accumulate Field would point the way to a general method, here? $\endgroup$
    – Robin Betts
    Commented Mar 2 at 8:58
  • 1
    $\begingroup$ From my searching, it seems like what I need, but I've got no clue how to use it in this context. As mentioned in the post, I'm pretty much a beginner with GN, and while I'm picking things up slowly it's all still pretty arcane to me. $\endgroup$
    – AxiDes
    Commented Mar 2 at 10:04
  • 1
    $\begingroup$ Alright so I've gotten single parts to stack no matter the size using Accumulate Fields, by checking the Z value of the bounding box, and subtracting 1 (why that works I don't know). However, the question then arises of how to do it with a collection, as a collection input doesn't have a "scale" output to plug into the bounding box... $\endgroup$
    – AxiDes
    Commented Mar 3 at 5:41
  • $\begingroup$ Yeah, so I've more or less solved my original issue, and have buildings that generate without gaps (using single elements). I've got new issues, trying to make it work with collections instead of single objects, but I think that no longer fits within the scope of this question. I'll post my solution to the original issue in a bit. $\endgroup$
    – AxiDes
    Commented Mar 3 at 7:28
  • $\begingroup$ You may be able to edit this post, if you can do it concisely.. I don't think it's 'under threat'.. it's well-constructed and not an obvious duplicate.. sorry I haven't had time to address this one myself, yet. $\endgroup$
    – Robin Betts
    Commented Mar 3 at 8:39

2 Answers 2

1
+50
$\begingroup$

You want to get 1 element from base, N elements from middle and 1 from top.

This is a possible setting using two node groups ("pick N" and "bounding box"):

enter image description here

All picked elements are joined in the good order (base then middles then top), so that we have N + 2 instances.

Then instanciated again on a set of points placed by accumulation of the instances dimension in Z.


Pick N node group:

enter image description here

Its picks 1 instance randomly, then duplicate it by instanciating on a set of points.


Bounding box:

enter image description here

We have a set of N + 2 instances,

Converted into bounding boxes and realized, we have 8 x (N + 2) points.

Each bounding box has its min as first point and max as last point.

So sampling from instance index for every i * 8 points gives the min.

And sampling from instance index for every (i * 8) + 7 points gives the max.


enter image description here

(Blender 4.0)

$\endgroup$
1
  • $\begingroup$ Knocked it out of the park. Much cleaner than my amateur solution, with room to expand. Great work, and thanks a ton. Thanks for the writeup as well I'll be picking this one apart to see how it works in depth. $\endgroup$
    – AxiDes
    Commented Mar 7 at 21:56
1
$\begingroup$

Get random object from collection

After reading everything, I think I have the solution. Lemme know if I misunderstood something.

You can retrieve a single random object from a collection by accessing the number of objects in the collection. The setup would look like that :

enter image description here

  • Here my objects in the collection are : cube, cone, sphere.
  • You need to specify a global value for the ID input of the Random Value. Otherwise, each one of the objects inside the collection will have its own random value. We want only one value for all objects, thus explicitly giving one value as ID.
  • If you have multiple objects using this group of nodes, you may want to change the Seed of Random Value.
  • Domain Size will return the number of objects (here 3). We need to subtract 1 to match the index (which start at 0).
$\endgroup$
2
  • $\begingroup$ I think you might have gotten caught up on my emphasis of "picking one", when that wasn't exactly what I was looking to solve. That being said, your method would still prove useful I think for trying to find the bounding box size of a given object in a collection, which was ultimately what I was trying to do. I think my overly elaborate writeup might have been too much information in this case. That's my bad! $\endgroup$
    – AxiDes
    Commented Mar 7 at 21:59
  • 1
    $\begingroup$ As long as it can be somewhat useful, I'm glad. :) $\endgroup$
    – Lutzi
    Commented Mar 7 at 22:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .