Eyteneyer Posted June 26 Share Posted June 26 Hello dear Houdini Legion. I am trying to create this effect from the picture above. Try to copy on the extracted points geo, but it doesn't work properly. Please help me. I followed Matt Taylor tutorial on recursive subdivision. My goal is to use images from COPS to copy into every polygon center, and it should scale with polygon in time. Thanks for any advice. recursive_sub_v01.hip Quote Link to comment Share on other sites More sharing options...
Eyteneyer Posted June 26 Author Share Posted June 26 Quote Link to comment Share on other sites More sharing options...
Eyteneyer Posted June 26 Author Share Posted June 26 AA.mp4 Quote Link to comment Share on other sites More sharing options...
Librarian Posted June 27 Share Posted June 27 //detail float size_mult = chf("size_mult"); float min_size = chf("min_size"); float max_size = chf("max_size"); float normal_offset = chf("normal_offset"); int use_nonuniform = chi("use_nonuniform"); float thickness_scale = chf("thickness_scale"); int colorize = chi("colorize"); int random_color = chi("random_color"); int keep_only_polygons = chi("keep_only_polygons"); // ------------------------------------------------------------ // SAFE DEFAULTS // ------------------------------------------------------------ size_mult = max(size_mult, 0.00001); min_size = max(min_size, 0.0); max_size = max(max_size, min_size + 0.00001); thickness_scale = max(thickness_scale, 0.00001); // ------------------------------------------------------------ // STORAGE ARRAYS // ------------------------------------------------------------ vector centers[]; vector normals[]; vector ups[]; vector scales[]; vector colors[]; float pscales[]; int srcprims[]; float areas[]; // ------------------------------------------------------------ // READ ALL PRIMITIVES FIRST // ------------------------------------------------------------ int npr = nprimitives(0); for (int pr = 0; pr < npr; pr++) { string typename = primintrinsic(0, "typename", pr); if (keep_only_polygons == 1) { if (typename != "Poly" && typename != "Polygon" && typename != "Mesh") continue; } int nv = primvertexcount(0, pr); if (nv < 3) continue; // -------------------------------------------------------- // Polygon center // -------------------------------------------------------- vector C = set(0.0, 0.0, 0.0); for (int i = 0; i < nv; i++) { int vtx = vertexindex(0, pr, i); int pt = vertexpoint(0, vtx); vector P = point(0, "P", pt); C += P; } C /= float(nv); // -------------------------------------------------------- // Polygon normal using Newell method // More stable than relying only on prim_normal. // -------------------------------------------------------- vector N = set(0.0, 0.0, 0.0); for (int i = 0; i < nv; i++) { int vtx0 = vertexindex(0, pr, i); int vtx1 = vertexindex(0, pr, (i + 1) % nv); int pt0 = vertexpoint(0, vtx0); int pt1 = vertexpoint(0, vtx1); vector P0 = point(0, "P", pt0); vector P1 = point(0, "P", pt1); N.x += (P0.y - P1.y) * (P0.z + P1.z); N.y += (P0.z - P1.z) * (P0.x + P1.x); N.z += (P0.x - P1.x) * (P0.y + P1.y); } if (length(N) < 0.000001) N = prim_normal(0, pr, 0.5, 0.5); if (length(N) < 0.000001) N = set(0.0, 1.0, 0.0); N = normalize(N); // -------------------------------------------------------- // Find longest polygon edge as local X axis // This gives stable orientation for Copy to Points. // -------------------------------------------------------- vector X = set(1.0, 0.0, 0.0); float longest = -1.0; for (int i = 0; i < nv; i++) { int vtx0 = vertexindex(0, pr, i); int vtx1 = vertexindex(0, pr, (i + 1) % nv); int pt0 = vertexpoint(0, vtx0); int pt1 = vertexpoint(0, vtx1); vector P0 = point(0, "P", pt0); vector P1 = point(0, "P", pt1); vector E = P1 - P0; float L = length(E); if (L > longest) { longest = L; X = E; } } if (length(X) < 0.000001) X = set(1.0, 0.0, 0.0); // Remove any normal component from X. X = normalize(X - N * dot(X, N)); if (length(X) < 0.000001) { vector tmp = set(1.0, 0.0, 0.0); if (abs(dot(tmp, N)) > 0.95) tmp = set(0.0, 0.0, 1.0); X = normalize(cross(tmp, N)); } vector Y = normalize(cross(N, X)); if (length(Y) < 0.000001) Y = set(0.0, 1.0, 0.0); // -------------------------------------------------------- // Polygon area / perimeter scale // -------------------------------------------------------- float area = primintrinsic(0, "measuredarea", pr); if (area <= 0.000001) { // Fallback area approximation from triangulation to center. area = 0.0; for (int i = 0; i < nv; i++) { int vtx0 = vertexindex(0, pr, i); int vtx1 = vertexindex(0, pr, (i + 1) % nv); int pt0 = vertexpoint(0, vtx0); int pt1 = vertexpoint(0, vtx1); vector P0 = point(0, "P", pt0); vector P1 = point(0, "P", pt1); area += length(cross(P0 - C, P1 - C)) * 0.5; } } float uniform_size = sqrt(max(area, 0.0)) * size_mult; uniform_size = clamp(uniform_size, min_size, max_size); // -------------------------------------------------------- // Non-uniform scale from local polygon bounds // X/Y are measured in polygon local plane. // -------------------------------------------------------- float minx = 1e18; float maxx = -1e18; float miny = 1e18; float maxy = -1e18; for (int i = 0; i < nv; i++) { int vtx = vertexindex(0, pr, i); int pt = vertexpoint(0, vtx); vector P = point(0, "P", pt); vector D = P - C; float lx = dot(D, X); float ly = dot(D, Y); minx = min(minx, lx); maxx = max(maxx, lx); miny = min(miny, ly); maxy = max(maxy, ly); } float sx = max(maxx - minx, min_size) * size_mult; float sy = max(maxy - miny, min_size) * size_mult; float sz = uniform_size * thickness_scale; sx = clamp(sx, min_size, max_size); sy = clamp(sy, min_size, max_size); sz = clamp(sz, min_size, max_size); vector S = set(uniform_size, uniform_size, uniform_size); if (use_nonuniform == 1) S = set(sx, sy, sz); // -------------------------------------------------------- // Color // -------------------------------------------------------- vector Cd = set(1.0, 1.0, 1.0); if (random_color == 1) { float r = rand(float(pr) * 13.17 + 0.11); float g = rand(float(pr) * 41.73 + 0.37); float b = rand(float(pr) * 91.27 + 0.71); Cd = set(r, g, b); } else { float a_norm = fit(uniform_size, min_size, max_size, 0.0, 1.0); Cd = lerp(set(0.08, 0.25, 1.0), set(1.0, 0.55, 0.05), a_norm); } // -------------------------------------------------------- // Store arrays // -------------------------------------------------------- append(centers, C + N * normal_offset); append(normals, N); append(ups, Y); append(scales, S); append(pscales, uniform_size); append(srcprims, pr); append(areas, area); append(colors, Cd); } // ------------------------------------------------------------ // CLEAR INPUT GEOMETRY // ------------------------------------------------------------ for (int pr = nprimitives(0) - 1; pr >= 0; pr--) { removeprim(0, pr, 0); } for (int pt = npoints(0) - 1; pt >= 0; pt--) { removepoint(0, pt); } // ------------------------------------------------------------ // CREATE OUTPUT TEMPLATE POINTS // ------------------------------------------------------------ for (int i = 0; i < len(centers); i++) { int p = addpoint(0, centers[i]); vector N = normals[i]; vector UP = ups[i]; // Rebuild clean orientation. vector X = normalize(cross(UP, N)); if (length(X) < 0.000001) X = set(1.0, 0.0, 0.0); UP = normalize(cross(N, X)); matrix3 m = set(X, UP, N); vector4 q = quaternion(m); setpointattrib(0, "N", p, N, "set"); setpointattrib(0, "up", p, UP, "set"); setpointattrib(0, "orient", p, q, "set"); setpointattrib(0, "pscale", p, pscales[i], "set"); setpointattrib(0, "scale", p, scales[i], "set"); setpointattrib(0, "srcprim", p, srcprims[i], "set"); setpointattrib(0, "area", p, areas[i], "set"); setpointattrib(0, "id", p, srcprims[i], "set"); if (colorize == 1) setpointattrib(0, "Cd", p, colors[i], "set"); setpointgroup(0, "copy_centers", p, 1, "set"); } 2 Quote Link to comment Share on other sites More sharing options...
Eyteneyer Posted June 27 Author Share Posted June 27 Wow, thank you so much for the answer ! I'll try this method as soon as possible once I'm back home. Best regards, Ilya. 1 Quote Link to comment Share on other sites More sharing options...
Eyteneyer Posted June 27 Author Share Posted June 27 (edited) UPDATE Working as charm with usenonuniform! AA2.mp4 AA3.mp4 Edited June 27 by Eyteneyer Quote Link to comment Share on other sites More sharing options...
Eyteneyer Posted June 27 Author Share Posted June 27 Many thanks Tesan Srdjan! Quote Link to comment Share on other sites More sharing options...
Librarian Posted June 27 Share Posted June 27 1 Quote Link to comment Share on other sites More sharing options...
AntoineSfx Posted June 30 Share Posted June 30 On 6/27/2026 at 1:24 AM, Eyteneyer said: Hello dear Houdini Legion. I am trying to create this effect from the picture above. Try to copy on the extracted points geo, but it doesn't work properly. Please help me. I followed Matt Taylor tutorial on recursive subdivision. My goal is to use images from COPS to copy into every polygon center, and it should scale with polygon in time. Thanks for any advice. recursive_sub_v01.hip 220.02 kB · 4 downloads you're almost there: the way you tried to get the scale from the point is incorrect Do this instead, everything you need to change is visible in the wrangle This works because the extracted centers have the same element number as the primitives they're representing. And the bounding box can be used directly to scale a unit box to the size of that primitive. You can also remove measure SOP. scale.webm Quote Link to comment Share on other sites More sharing options...
Eyteneyer Posted June 30 Author Share Posted June 30 (edited) OMG thank you so much! Wow! Antonio, could you please help me with growing effect? Is there any way to grow this from, one big, lets say rerctangle and in 145 or more frames one by one divide gently this rectangles as i mention in reference picture)) mm2.mp4 Edited June 30 by Eyteneyer 1 Quote Link to comment Share on other sites More sharing options...
AntoineSfx Posted July 1 Share Posted July 1 (edited) 20 hours ago, Eyteneyer said: OMG thank you so much! Wow! Antonio, could you please help me with growing effect? Is there any way to grow this from, one big, lets say rerctangle and in 145 or more frames one by one divide gently this rectangles as i mention in reference picture)) mm2.mp4 You should start by fixing the original code so that the prims are all oriented the same way, and so that down the line, X always means world X, and Y always means world Y. This is left as exercise. This makes it simpler to debug or control if everything is nice and aligned to start with, all oriented the same. Other than that, it should be doable by linking the iteration count to the currents values of X and Y , with two separate ramps functions, with something like this (not tested): float iter = detail(1,"iteration",0)/ float(detail(1,"numiterations",0)); and use that iter value to read from a chramp With low iter values, you should return values close to something between 0 and 0.5 and the higher it gets, the closer to 0 or 1 it should go; this way, only one prim will dominate (visually) in the subdivision Getting it right is the tricky part though Edited July 1 by AntoineSfx 1 Quote Link to comment Share on other sites More sharing options...
Eyteneyer Posted July 2 Author Share Posted July 2 No it doesnt work smoothly i quess it is some houdini solver technicue? Quote Link to comment Share on other sites More sharing options...
AntoineSfx Posted July 3 Share Posted July 3 22 hours ago, Eyteneyer said: No it doesnt work smoothly i quess it is some houdini solver technicue? you have to be more specific Quote Link to comment Share on other sites More sharing options...
basketdani Posted July 9 Share Posted July 9 Hello @Ilya, here i have another example. If you like it, you are welcome. Test_Recursive_Subdivision.hipnc Dynamic-Grid_test.hipnc 1 Quote Link to comment Share on other sites More sharing options...
Eyteneyer Posted July 13 Author Share Posted July 13 Wow basketdani super thanks!!! Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.