Leaderboard
Popular Content
Showing content with the highest reputation since 01/15/2026 in all areas
-
You can also use the clip node (clip attribute). The attribute can be generated by some random function (combined sin, cos, ...). You can clip your curve into two complement sets. One of these parts can be resampled for the dots and the other for the lines (ribbons). Here is a file with some ideas. clip_carve_lines_dots.hipnc3 points
-
New video on how USD Render Prims work and how to use the new Render Pass prim.2 points
-
2 points
-
Yep, kinda like this but devil's always in the details and you have to account for oversampling (timestep) of the sim, especially with age accumulation. You only need the Gas Field VOP to use increment age by the timestep using density as a mask btw. Everything else can be done with Gas Calculate (tends to be faster than Gas Field VOP for simple stuff). - initialize age field at sim start channel matching fields from Smoke Object DOP - increment age by timestep using density as a mask (unless you want to add time to all voxels, up to you). - Keep source field around (need to remove "source" from clear fields in Source Volume DOP) - create temporary agetemp field and add source field reset to be constant timestep (you can't count on source always being set to 1) - Add agetemp to age - advect age I haven't really thought about the best order of things: - when to add agetemp to age. Before or after advection. Open to suggestions/advice. See the attached hip file for an attempt at this. age_field.hip This temp field is pretty hard to read in the viewport when it is visualized as it is kind of like density but counters velocity (to be expected as faster areas should be darker when visualization set to greyscale for age). it looks to be kinda correct. I hope...2 points
-
// DETAIL WRANGLE (run once) // Input 0: a single curve/polyline primitive (uses "prim" parm) // -------------------- Parameters -------------------- int prim = chi("prim"); int seed = chi("seed"); string msg = chs("message"); float unit_len = chf("unit_len"); // unit length in curve-u (0..1) float spacing_units = chf("spacing_units"); // base dot spacing in "units" float dot_mult = chf("dot_mult"); // density multiplier for dot float dash_mult = chf("dash_mult"); // density multiplier for dash (dense dots) float jitter_radius = chf("jitter_radius"); // world-space jitter radius around curve float jitter_along = chf("jitter_along"); // along-interval jitter (0..1) int max_pts = chi("max_pts"); // Morse timing (in units) float dot_units = chf("dot_units"); // usually 1 float dash_units = chf("dash_units"); // usually 3 float gap_symbol_units = chf("gap_symbol_units"); // usually 1 (between . and - in same letter) float gap_letter_units = chf("gap_letter_units"); // usually 3 (between letters) float gap_word_units = chf("gap_word_units"); // usually 7 (between words) // -------------------- Helpers -------------------- function void frame_on_curve(int geoh; int pr; float u; vector up; export vector P; export vector T; export vector N; export vector B) { P = primuv(geoh, "P", pr, set(u, 0, 0)); float du = 1e-4; vector P2 = primuv(geoh, "P", pr, set(clamp(u + du, 0.0, 1.0), 0, 0)); T = normalize(P2 - P); vector a = normalize(cross(up, T)); if (length(a) < 1e-6) a = normalize(cross({1,0,0}, T)); B = normalize(a); N = normalize(cross(T, B)); } function int emit_interval(int geoh; int pr; float u0; float u1; float density_mult; int seedbase; float unit_len; float spacing_units; float jitter_radius; float jitter_along; int max_pts) { float du = max(0.0, u1 - u0); float interval_units = du / max(1e-8, unit_len); float base_count = interval_units / max(1e-8, spacing_units); int npts = int(ceil(base_count * max(0.0, density_mult))); if (npts <= 0) return 0; vector up = {0,1,0}; int created = 0; for (int i = 0; i < npts; i++) { if (created >= max_pts) break; float t = (npts <= 1) ? 0.5 : (float(i) / float(npts - 1)); float r = rand(set(seedbase, i, 19.123)); float u = lerp(u0, u1, t); // jitter a bit along the interval u += (r - 0.5) * jitter_along * (spacing_units * unit_len); u = clamp(u, u0, u1); vector P, T, N, B; frame_on_curve(geoh, pr, u, up, P, T, N, B); // jitter in disk around curve float ang = rand(set(seedbase, i, 3.7)) * 2.0 * M_PI; float rr = sqrt(rand(set(seedbase, i, 8.1))) * jitter_radius; vector jitter = cos(ang) * N * rr + sin(ang) * B * rr; int pt = addpoint(0, P + jitter); setpointattrib(0, "curveu", pt, u, "set"); setpointattrib(0, "pscale", pt, fit01(rand(set(seedbase, i, 77.7)), 0.6, 1.2), "set"); created++; } return created; } // Morse lookup: chars and their morse strings function string morse_of(string ch) { string chars[] = { "A","B","C","D","E","F","G","H","I","J", "K","L","M","N","O","P","Q","R","S","T", "U","V","W","X","Y","Z", "0","1","2","3","4","5","6","7","8","9" }; string codes[] = { ".-","-...","-.-.","-..",".","..-.","--.","....","..",".---", "-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-", "..-","...-",".--","-..-","-.--","--..", "-----",".----","..---","...--","....-",".....","-....","--...","---..","----." }; // already uppercase before calling, but safe: string up = toupper(ch); int idx = -1; for (int i = 0; i < len(chars); i++) { if (up == chars[i]) { idx = i; break; } } if (idx < 0) return ""; // unsupported char -> treat as gap return codes[idx]; } // -------------------- Main: walk along curve-u -------------------- float u = 0.0; int total = 0; msg = toupper(msg); // iterate message characters for (int c = 0; c < len(msg); c++) { if (u >= 1.0 || total >= max_pts) break; string ch = msg[c]; // Word gap if (ch == " ") { u = min(1.0, u + gap_word_units * unit_len); continue; } string code = morse_of(ch); // Unsupported char: treat like a word-ish gap if (code == "") { u = min(1.0, u + gap_letter_units * unit_len); continue; } // For each symbol in morse code for (int s = 0; s < len(code); s++) { if (u >= 1.0 || total >= max_pts) break; string sym = code[s]; float dur_units = (sym == ".") ? dot_units : dash_units; float dens = (sym == ".") ? dot_mult : dash_mult; float u1 = min(1.0, u + dur_units * unit_len); total += emit_interval(0, prim, u, u1, dens, seed + total * 31, unit_len, spacing_units, jitter_radius, jitter_along, max_pts); u = u1; // symbol gap (but not after last symbol) if (s < len(code) - 1) u = min(1.0, u + gap_symbol_units * unit_len); } // letter gap after each character (but not if next is space) if (c < len(msg) - 1 && msg[c+1] != " ") u = min(1.0, u + gap_letter_units * unit_len); } multiple Lines // DETAIL WRANGLE (run once) // Input 0: multiple polyline primitives int seed = chi("seed"); string msg = chs("message"); float unit_len = chf("unit_len"); float spacing_units = chf("spacing_units"); float dot_mult = chf("dot_mult"); float dash_mult = chf("dash_mult"); float jitter_radius = chf("jitter_radius"); float jitter_along = chf("jitter_along"); int max_pts_total = chi("max_pts_total"); // Morse timing (units) float dot_units = chf("dot_units"); float dash_units = chf("dash_units"); float gap_symbol_units = chf("gap_symbol_units"); float gap_letter_units = chf("gap_letter_units"); float gap_word_units = chf("gap_word_units"); // ---------- Helpers ---------- function void frame_on_curve(int geoh; int pr; float u; vector up; export vector P; export vector T; export vector N; export vector B) { P = primuv(geoh, "P", pr, set(u, 0, 0)); float du = 1e-4; vector P2 = primuv(geoh, "P", pr, set(clamp(u + du, 0.0, 1.0), 0, 0)); T = normalize(P2 - P); vector a = normalize(cross(up, T)); if (length(a) < 1e-6) a = normalize(cross({1,0,0}, T)); B = normalize(a); N = normalize(cross(T, B)); } function int emit_interval(int geoh; int pr; float u0; float u1; float density_mult; int seedbase; float unit_len; float spacing_units; float jitter_radius; float jitter_along; int max_pts_cap; int prim_id; int symbol_id) { float du = max(0.0, u1 - u0); float interval_units = du / max(1e-8, unit_len); float base_count = interval_units / max(1e-8, spacing_units); int npts = int(ceil(base_count * max(0.0, density_mult))); if (npts <= 0) return 0; vector up = {0,1,0}; int created = 0; for (int i = 0; i < npts; i++) { if (created >= max_pts_cap) break; float t = (npts <= 1) ? 0.5 : (float(i) / float(npts - 1)); float r = rand(set(seedbase, i, 19.123)); float u = lerp(u0, u1, t); u += (r - 0.5) * jitter_along * (spacing_units * unit_len); u = clamp(u, u0, u1); vector P, T, N, B; frame_on_curve(geoh, pr, u, up, P, T, N, B); float ang = rand(set(seedbase, i, 3.7)) * 2.0 * M_PI; float rr = sqrt(rand(set(seedbase, i, 8.1))) * jitter_radius; vector jitter = cos(ang) * N * rr + sin(ang) * B * rr; int pt = addpoint(0, P + jitter); setpointattrib(0, "curveu", pt, u, "set"); setpointattrib(0, "pscale", pt, fit01(rand(set(seedbase, i, 77.7)), 0.6, 1.2), "set"); // super useful for shading / grouping setpointattrib(0, "sourceprim", pt, prim_id, "set"); // which input curve setpointattrib(0, "symbol", pt, symbol_id, "set"); // 0=dot, 1=dash created++; } return created; } function string morse_of(string ch) { string chars[] = { "A","B","C","D","E","F","G","H","I","J", "K","L","M","N","O","P","Q","R","S","T", "U","V","W","X","Y","Z", "0","1","2","3","4","5","6","7","8","9" }; string codes[] = { ".-","-...","-.-.","-..",".","..-.","--.","....","..",".---", "-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-", "..-","...-",".--","-..-","-.--","--..", "-----",".----","..---","...--","....-",".....","-....","--...","---..","----." }; string upc = toupper(ch); for (int i = 0; i < len(chars); i++) if (upc == chars[i]) return codes[i]; return ""; } // ---------- Main ---------- msg = toupper(msg); int npr = nprimitives(0); int total_pts = 0; // You can choose: same message for every curve, or offset/seed per curve. for (int pr = 0; pr < npr; pr++) { if (total_pts >= max_pts_total) break; float u = 0.0; // per-primitive seed so each curve has a unique pattern jitter int sseed = seed + pr * 10007; for (int c = 0; c < len(msg); c++) { if (u >= 1.0 || total_pts >= max_pts_total) break; string ch = msg[c]; if (ch == " ") { u = min(1.0, u + gap_word_units * unit_len); continue; } string code = morse_of(ch); if (code == "") { u = min(1.0, u + gap_letter_units * unit_len); continue; } for (int k = 0; k < len(code); k++) { if (u >= 1.0 || total_pts >= max_pts_total) break; string sym = code[k]; float dur = (sym == ".") ? dot_units : dash_units; float den = (sym == ".") ? dot_mult : dash_mult; int sid = (sym == ".") ? 0 : 1; float u1 = min(1.0, u + dur * unit_len); // cap per-interval emission so one curve can't explode points int cap_here = max(1, (max_pts_total - total_pts)); int made = emit_interval(0, pr, u, u1, den, sseed + total_pts * 31, unit_len, spacing_units, jitter_radius, jitter_along, cap_here, pr, sid); total_pts += made; u = u1; if (k < len(code) - 1) u = min(1.0, u + gap_symbol_units * unit_len); } if (c < len(msg) - 1 && msg[c+1] != " ") u = min(1.0, u + gap_letter_units * unit_len); } }1 point
-
I'm back, After checking the code, here's what I found: - UI_EVENT_REDRAW comes from Houdini's env variables. Its limit needs to be up. - "wmic" bug fixed Concerning aspect ratio: - They are made for horizontal framing, can be customized with dedicated button for vertical. Pixel size are shown for custom ratio to help get exact resolution wanted. Note that I'll add vertical toggle since it seems rather useful. - Added helpcards for buttons that don't seem straightforward. Can you send me your email so I can send you a beta version @Dmitry Futoryan?1 point
-
Hi @Dmitry Futoryan Thank you for reaching out and for taking the time to explain the issues in detail. Really appreciate it. I’m sorry for the frustration you’ve run into. I wasn’t aware of these specific errors occurring in H21.0.596, I’ll follow up once I’ve identified the cause of the errors and can provide either a fix or clear setup instructions. Thanks again for your patience and for bringing this to my attention. Note that for support, you just have to reply to your Gumroad's receipt email.1 point
-
Heya! We're Those Awesome Guys, a small indie gamedev team looking for someone to help us turn our concept art into a robust procedural Houdini city generator, hooked up to Unreal Engine. What you’ll be doing: Turning concept art into a cohesive, procedural CityGen HDA Building systems that play nicely with Unreal (splines, assets importing, the whole deal) Making tools that artists actually enjoy working with You should be comfy with: Designing and building procedural city systems in Houdini Creating and maintaining complex, well-structured HDAs Houdini ↔ Unreal integrations Geometry, attributes, and VEX (you know your way around them) Keeping networks and parameters clean, readable, and organized Bonus points if you like problem-solving, experimenting, and shipping cool stuff with a small team. Please send an email with your portfolio and any other relevant links or info to: welackahrdepartment@thoseawesomeguys.com (yes, it's a real email)1 point
-
The interesting thing in the video is indeed the fact that adding ramp points adds geometry. I found a quick way of doing this, maybe a bit dirty but it looks like it's working ! chrampedgeloop.hipnc1 point
-
I wanted to share a quick visual comparison between the SideFX recording of my Houdini HIVE Tokyo 2025 session "Adaptive Fracture Synthesis and Propagation in VEX using OpenSubdiv Limit Surface Derivatives" and my own local QHD capture. The SideFX version is completely fine for watching the presentation, but my recording was captured directly from my display source with no compression loss, so it preserves a lot more clarity across the entire presentation. This includes all geometry details, colors, UI elements, and text. This is one of the main reasons I am preparing my own edited cuts. The attached images show the difference between the two versions. The full END-JPN cut will be posted next, followed later by the English-only version. These edited cuts will be available exclusively to paid members on Patreon.1 point
-
I spent a fair bit of time trying to figure this out today so I figured I'd post a quick tutorial for posterity. The only other guides and info I could find were specific to getting pscale and Cd into C4d for Redshift. Nothing on orientation or other attributes generally. Long story short: - Unless your attribute is explicitly typed (i.e. Vector, Quaternion, Matrix instead of 3flt, 4flt, 9flt) C4d will read it as a float (or "Real") - Orientation is handled by the "Alignment" TP channel, so you need to convert your @orient to a matrix3 before export Hope this saves someone else some time.1 point
-
Hi, yeah I tried that originally, but only did set "nextid", forgot about the "id" so I was getting -1 as id on the first frame haha, thanks!1 point
-
Hi, You can do it like this: function int [ ] getPointNeighbours ( int geo; int ptindex; int depth; int accumulate ) { int pts [ ] = array ( ptindex ); int lastpts [ ] = pts; for ( int i = 0; i < depth; ++i ) { int newpts [ ] = { }; foreach ( int pt; lastpts ) { int connected [ ] = neighbours ( geo, pt ); foreach ( int c; connected ) { if ( find ( pts, c ) < 0 ) { append ( pts, c ); append ( newpts, c ); } } } lastpts = newpts; } if ( accumulate ) return pts; else return lastpts; } int pts [ ] = getPointNeighbours ( 0, 42, chi("depth"), chi("accumulate") ); foreach ( int pt; pts ) setpointgroup ( 0, "pts", pt, 1 );1 point
-
1 point
-
I'm pretty new with houdini, so I am sure there is a better way. randomselection.hiplc1 point
-
1 point