Transform any Mesh to complex Lego Geometry (Examples inkl.)

   6264   16   5
User Avatar
Member
9 posts
Joined: Dec. 2015
Offline
Hey Community,

nice to finally be part of the Houdini community. It is going to be great.

I'm very new to Houdini and will be using the software primarily for special FX like many in my line of work. But my first urgent project is already overwhelming without help.

I need help creating an asset that will allow me to turn any mesh into a complex Lego object. To make it easier to understand how exactly this should look like, I have linked some examples from other Houdini users.

Unfortunately, I don't even have a plan as to which tutorials and courses would be most suitable for targeting and implementation.
So please! If someone could make my way a little easier, has tips on which tutorials I should start with or can name some nodes for a more detailed assessment, I would be more than grateful.

Best Regards
Boris



Examples:
https://youtu.be/Ty-EKd9W0w8 [youtu.be]
https://vimeo.com/432816453 [vimeo.com]
https://www.behance.net/gallery/99293485/LEGO-Generator [www.behance.net]
User Avatar
Member
682 posts
Joined: Sept. 2013
Offline
Hi Boris,

have you seen this already?

https://www.youtube.com/watch?v=kljy7fuPc5k [www.youtube.com]
https://procegen.konstantinmagnus.de/ [procegen.konstantinmagnus.de]
User Avatar
Member
9 posts
Joined: Dec. 2015
Offline
Hey! Jo I watched all Houdini tutorials with Lego content. Unfortunately, I need the functions for generating procedural landscapes as mentioned in the examples.
User Avatar
Member
682 posts
Joined: Sept. 2013
Offline
You can fill meshes with the points from volume-node and take the volume's gradient as normal direction. Then copy the bricks onto the points. But the projects you've shown as examples are not exactly beginner level stuff.
https://procegen.konstantinmagnus.de/ [procegen.konstantinmagnus.de]
User Avatar
Member
9 posts
Joined: Dec. 2015
Offline
Konstantin Magnus
You can fill meshes with the points from volume-node and take the volume's gradient as normal direction. Then copy the bricks onto the points. But the projects you've shown as examples are not exactly beginner level stuff.

Yeah i know its not the easy way to start with. I Think its very Vex based. It would be cool when i have a look at a Node structure, maybe with two typed of Bricks with the right Directions to understand the Basics. Is there any Nice Houdini Expert to build me a Basic Node structure to learn it from a Example to know where i must be my eyes on to made my own? I Think the complicated part is to find the best Brick in the List insinde the Nore-Structure to Fill up a Mesh. And - Or Attach different Brick Sizes to each other without offsets.

In This Example from BCM Industries [www.behance.net], they has shown his Node Strukture, but i think there are more VEX Programming in it. (See Attachment)

Thanks Everyone
Edited by anon_user_97478895 - June 19, 2022 14:59:19

Attachments:
c695da99293485.5eefc7e3af536.jpg (581.7 KB)

User Avatar
Member
9 posts
Joined: Dec. 2015
Offline
EDIT:

Ok i´ve thought a while for a solution in Volumes and Points. So my theory:
Is it possible to Fill Points with an Geometry by the Numbers of Points in every axes?
For example a 1x1 Brick can only spawn in 8 contiguous Points. A 2x2 Brick in 18 Points, a 2x4 in 32 Points and so on...Until all points are used inset the covering Geometry. With a collision, that bricks are not overlapping each other, that could be work i think. But how can i realize this in an easy way? By Groups? By Geometry size as Bounding box? I dont know. In the meanwhile, i will google all informations about the volume gradient.

Thanks!
Edited by anon_user_97478895 - June 19, 2022 19:20:44
User Avatar
Member
682 posts
Joined: Sept. 2013
Offline
Hi Boris,

here is an example for one-unit Lego bricks oriented along perpendicular volume gradients:
https://procegen.konstantinmagnus.de/convert-meshes-to-lego-bricks [procegen.konstantinmagnus.de]

Attachments:
legofy.jpg (42.5 KB)

https://procegen.konstantinmagnus.de/ [procegen.konstantinmagnus.de]
User Avatar
Member
9 posts
Joined: Dec. 2015
Offline
Thank you for the quick and detailed help. Also for the files. I understand a lot more now! There is only one supplementary question, which I had not addressed before. My mistake. In my case, I would like to embed already created meshes from "Mecabricks" as objects in the calculation of the VDB. I have already managed to do this. The only question that arises here is how to explicitly assign different Lego bricks for the curves.

I had already mentioned whether it is possible to assign different Lego bricks to a certain number of points.
I made a little sketch for you. I'm pretty sure that this is also the approach of the examples in order to generate a certain randomness of different stones afterwards.

So far I've done collision queries and assignments of only single points myself. But the appropriate grouping of the individual points in connection with the individual stones is still a mystery.

Thanks!!

Ive also Attached some Bricks as .obj
Edited by anon_user_97478895 - June 20, 2022 09:34:57

Attachments:
skizze-lego-points.jpg (938.2 KB)
1x1.obj (14.4 KB)
1x1-Slope.obj (6.4 KB)
2x4.obj (149.3 KB)
2x4-slope.obj (78.6 KB)

User Avatar
Member
682 posts
Joined: Sept. 2013
Offline
The second example file on the procegen-page uses a "variant" attribute to assign suitable bricks. Maybe this is helpful?
https://procegen.konstantinmagnus.de/ [procegen.konstantinmagnus.de]
User Avatar
Member
9 posts
Joined: Dec. 2015
Offline
Unfortunately, I don't have enough VEX knowledge of my own to implement the whole thing the way I need it. I'm really starting to get frustrated. This feeling that the solution has already been implemented several times with Houdini, but no one has a plan exactly how 😅. I think without the absolute VEX professional that will unfortunately be nothing. I've now gone through all possible node combinations but you can forget that. Does anyone happen to know a platform where I could ask Houdini users with the right VEX knowledge? Unfortunately, since only Magnus has reported on this thread alone, despite the numerous views, I assume that the knowledge limit of many Houdini has already been reached here.
User Avatar
Member
8786 posts
Joined: July 2007
Offline
- this is not about VEX, but the algorithm

- if you feel more comfortable with Python you can use Python SOP, that allows you to process/update your point cloud sequantially unlike VEX

- or for each horizontal level process one block at a time in Feedback For Loop SOP until you fill it all, that way every iteration you will have updated pointcloud ready for next piece to be fitted
(the horizontal levels can be processed in parallel unless you have pieces that are more than 1 vertically)

EDIT: looking at the image that's exactly what's happening, big parallel loop over levels and inside chain of feedback loops that try to fit as much of each shape as possible before moving to next
Edited by tamte - June 25, 2022 22:11:07
Tomas Slancik
FX Supervisor
Method Studios, NY
User Avatar
Member
9 posts
Joined: Dec. 2015
Offline
First of all, thank you for your feedback on my Houdini project. I also notice every day that this type and implementation as well as general use of Houdini receives extremely little attention on the Internet. Iam also not proficient in python… sorry… but I must finished this project to finally build my Envionments for my Game Project. But I must tell you this dump questions…

Since I keep coming across the same or similar tutorials on houdini. I've read for the hundredth time how I spawn random colors in a copy to point node or balls of different sizes etc... but unfortunately it's already hard to come across tutorials that help my goal to be achieved, so I'm unfortunately forced to tell you to annoy you again with some questions :/

1.) When I spawn Bricks in my Geo like “CopyToPoint”. In Every Point it will spawn a Brick. For a 1x1 Brick it’s easy. But How I say Houdini to use 4 Points in a square to place ONE 2x4 Brick as an example. This is the first step I must know before I go to loops. As en Example, you have X Points. Take Brick Y and Fill as many Points you can do. But there are also a new Problem. Houdini must Know that every Point is a Nub of a Brick. And then come the next Problem, what ist with the height… and so on. I Google for weeks now to find a similar Workflow in any Projects but nothing…

2.) What is the best Tutorial Series (also premium for sale) to bring me a step further in practice??

3.) is it even possible as a beginner without Vex, Python or other programming languages and a bachelor in math to develop it yourself? I've seen hundreds of tutorials and learned a lot, no question, but unfortunately everything is thematically past this implementation.

4.) How much it cost when anybody build me a Example with different Bricks in Size and Height. Maybe with 1x1, 2x2 and 2x4 Brick? I need a example to Analyse all the functions I think….
User Avatar
Member
275 posts
Joined: Sept. 2012
Offline
tamte
- this is not about VEX, but the algorithm


Yes, i don't see how you will be implement that algorithm without at little a minimal knowledge of VEX or Python. I agree with master Tomas, i don't think that part is the most difficult.


-Maybe try in 2d first?
-You will try to place larges and angular pieces first
-Try to look at the "marching cubes" algorithm it will give you a good idea how you could possibly approach the problem...
Image Not Found
Edited by vinyvince - June 30, 2022 15:09:56

Attachments:
Lego_Houdini_3DWaveFunction.gif (2.1 MB)
legolize_3dWFC_5.PNG (1.3 MB)

Vincent Thomas   (VFX and Art since 1998)
Senior Env and Lighting  artist & Houdini generalist & Creative Concepts
http://fr.linkedin.com/in/vincentthomas [fr.linkedin.com]
User Avatar
Member
9 posts
Joined: Dec. 2015
Offline
vinyvince
tamte
- this is not about VEX, but the algorithm

Hey! It’s a very exiting Example how to use Houdini. I will definitely pursue this method.

An User on Artstation has Wrote me back today with some Tipps.

Here’s a piece of his message and it’s represents absolute what I want and how do i made this.

“So, for example, if I had a 1x4 piece, I would copy the geometry to a random point in the grid and check to wee whether it's a valid position for it to be. The way I did this was to group by bounding geometry. And counting how many points were inside. For a 1x4 piece, this would have been 12 points (3 height x 4 width). 3 height points due to having the thin pieces. 3 of those fit into 1 regular block.”

This Method is in my Brain for many weeks.

Can someone could help me out, how is the Vex Code to grouping Points like this by bounding geometry, but in loop to check all the Points in the Volume or Point cloud to find all possible places? As an example for a Grid of 2x4x3 (x,y,z) Points each.

Thank you!
User Avatar
Member
1 posts
Joined: April 2019
Offline
Were you able to successfully make a lego building algorythm? I would love to learn from your findings
User Avatar
Member
43 posts
Joined: April 2018
Offline
Here is a person who made a great implementation of what you want in Houdini.

If you search for the user name there's a page somewhere with a bit more detail on how they achieved it. However I don't think you will ever get a more in depth answer, as I think that person is now using it on an actual lego game project for a big studio.

https://www.youtube.com/watch?v=z_MBWceorJ8&ab_channel=PaQWaK [www.youtube.com]
User Avatar
Member
152 posts
Joined: Aug. 2017
Offline
Play with this .
Use first file of Konstantin, delete Wrangle normal's dont need to use transform with pscale also, use this Vex Code and make shapes that you like using merged-packed with names that you make before with nulls.
// Get gradient information
vector grad = normalize(v@grad);

// Gradient magnitude for overall control
float grad_magnitude = length(grad);

// User-defined ramps for controlling influence on X, Y, and Z
float x_influence = chramp("x_influence_ramp", abs(grad.x));
float y_influence = chramp("y_influence_ramp", abs(grad.y));
float z_influence = chramp("z_influence_ramp", abs(grad.z));

// Adjust thresholds for brick assignment
float grad_threshold_x = chf("grad_threshold_x");
float grad_threshold_y = chf("grad_threshold_y");
float grad_threshold_z = chf("grad_threshold_z");

// Introduce noise-based perturbation for variety
float noise_val = snoise(@P * chf("noise_frequency")) * chf("noise_amplitude");
grad += noise_val;  // Perturb the gradient to add variation

// Calculate blend factors with ramp-based influence
float blend_factor_x = (abs(grad.x) / grad_threshold_x) * x_influence;
float blend_factor_y = (abs(grad.y) / grad_threshold_y) * y_influence;
float blend_factor_z = (abs(grad.z) / grad_threshold_z) * z_influence;

// Clamp the blend factors to the range [0, 1]
blend_factor_x = clamp(blend_factor_x, 0.0, 1.0);
blend_factor_y = clamp(blend_factor_y, 0.0, 1.0);
blend_factor_z = clamp(blend_factor_z, 0.0, 1.0);

// Add more slope types based on gradient direction and strength
if (grad_magnitude > grad_threshold_y) {
    if (blend_factor_x > blend_factor_z) {
        // X-influenced slopes
        if (blend_factor_x > 0.9) {
            s@variant = "3x4-steep-slope";
        } else if (blend_factor_x > 0.7) {
            s@variant = "2x6-slope";
        } else if (blend_factor_x > 0.5) {
            s@variant = "2x4-slope";
        } else {
            s@variant = "2x4";
        }
        @N = normalize(set(grad.x, 0, 0));
    } else {
        // Z-influenced slopes
        if (blend_factor_z > 0.9) {
            s@variant = "3x3-steep-slope";
        } else if (blend_factor_z > 0.7) {
            s@variant = "1x3-slope";
        } else if (blend_factor_z > 0.5) {
            s@variant = "1x2-slope";
        } else {
            s@variant = "1x2";
        }
        @N = normalize(set(0, 0, grad.z));
    }
} else {
    // Y-influenced flat or gentle slopes
    if (blend_factor_y > 0.8) {
        s@variant = "1x2-flat";
    } else if (blend_factor_y > 0.6) {
        s@variant = "1x1-slope-gentle";
    } else if (blend_factor_y > 0.4) {
        s@variant = "1x1-slope";
    } else {
        s@variant = "1x1";
    }
}

// Apply orientation variation based on noise and ramps
float rotation_offset = chramp("rotation_offset_ramp", noise_val);
vector axis = normalize(v@up);  // Rotation axis remains up
@N = qrotate(quaternion(rotation_offset, axis), @N);

// Set up vector
v@up = {0, 1, 0};

// Brick placement refinement based on grid
float grid_size_x = chf("grid_size_x");
float grid_size_z = chf("grid_size_z");

// Snap the points to the grid to avoid overlap
@P.x = floor(@P.x / grid_size_x) * grid_size_x;
@P.z = floor(@P.z / grid_size_z) * grid_size_z;

// More complex pscale logic
float base_pscale = chf("base_pscale");

// Adjust pscale based on shape type (for larger bricks that cover more points)
int num_points_covered;
if (s@variant == "3x4-steep-slope" || s@variant == "2x6-slope") {
    num_points_covered = 12;
} else if (s@variant == "2x4-slope" || s@variant == "2x4") {
    num_points_covered = 8;
} else if (s@variant == "1x3-slope" || s@variant == "1x3") {
    num_points_covered = 3;
} else if (s@variant == "1x2-slope" || s@variant == "1x2") {
    num_points_covered = 2;
} else {
    num_points_covered = 1;  // Default for smaller bricks
}

// Adjust pscale based on the number of points the shape occupies
@pscale = base_pscale * float(num_points_covered) / 16.0;  // Normalize to 16-point base size

// Gradient-based scaling: stronger gradients in X, Y, or Z increase scale
float pscale_x = chramp("pscale_x_ramp", abs(grad.x)) * x_influence * base_pscale;
float pscale_y = chramp("pscale_y_ramp", abs(grad.y)) * y_influence * base_pscale;
float pscale_z = chramp("pscale_z_ramp", abs(grad.z)) * z_influence * base_pscale;

// Noise-based scaling variation: adds randomness to the scale
float noise_scale = snoise(@P * chf("pscale_noise_freq")) * chf("pscale_noise_amp");

// Combine noise with gradient scaling for final pscale
@pscale += noise_scale + (pscale_x + pscale_y + pscale_z) / 3.0;

// Ensure pscale stays within a valid range
@pscale = clamp(@pscale, chf("min_pscale"), chf("max_pscale"));
Conservation of Momentum
  • Quick Links