Bounding Box Based Rotation
vector bbox_low, bbox_high;
getbbox(bbox_low, bbox_high);
float spin_limit = 4;
matrix3 base_mtx = ident();
float spin_factor = fit(@P.y, bbox_low.y, bbox_high.y, 0, 1);
rotate(base_mtx, spin_factor * spin_limit, {0, 1, 0});
@P *= base_mtx;
Custom Parameter UI Definition
#pragma label oper_mode "Operation"
#pragma label shift_amt "Offset Value"
#pragma group XFORM shift_amt oper_mode
#pragma choice oper_mode "0" "Bend"
#pragma choice oper_mode "1" "Twist"
#pragma choice oper_mode "2" "Taper"
Neighbor Velocity Averaging for Acceleration
float search_rad = 99999;
int max_hits = 10;
int src = pcopen(@OpInput1, "P", @P, search_rad, max_hits + 1);
int pt_idx;
int found_cnt = 0;
vector neighbor_vel;
vector vel_sum = {0, 0, 0};
while (pciterate(src)) {
pcimport(src, "point.number", pt_idx);
if (pt_idx == @ptnum)
continue;
pcimport(src, "v", neighbor_vel);
vel_sum += neighbor_vel;
found_cnt++;
}
if (found_cnt > 0) {
vel_sum /= float(found_cnt);
v@accel += (vel_sum - @v) * 0.4;
}
Orienting Copied Instances from Velocity
v@N = normalize(@v);
v@up_vec = {0, 1, 0};
v@side_vec = normalize(cross(v@N, v@up_vec));
v@up_vec = normalize(cross(v@N, v@side_vec));
Determining Planar Angle and Relatvie Direction
// Returns angle between vectors a and b in range [0, PI]
float vec_angle(vector a; vector b) {
return acos(dot(normalize(a), normalize(b)));
}
// For XY projection: returns -1 if b is left of a, 1 if right (view from -Z)
int side_flag(vector a; vector b) {
vector z_comp = normalize(cross(normalize(a), normalize(b)));
return (z_comp.z < 0) ? 1 : -1;
}
vector base_a = point(0, "P", 1) - point(0, "P", 0);
vector base_b = point(1, "P", 1) - point(1, "P", 0);
float angle_val = vec_angle(base_a, base_b);
int orientation = side_flag(base_a, base_b);
if (orientation == -1) {
printf("direction: left\n");
printf("degrees : %d\n", int(degrees(angle_val)));
} else {
printf("direction: right\n");
printf("degrees : %d\n", int(degrees(angle_val)));
}
Fractal Turbulence Noise Generator
float fractal_noise(vector pos; vector freq; vector offs;
float rough; float lac; int steps; float expo) {
float total = 0;
float amp = 1.0;
vector sample_pos = pos * freq + offs;
for (int o = 0; o <= steps; o++) {
total += pow(noise(sample_pos), expo) * amp * 4;
sample_pos *= lac;
amp *= rough;
}
return total;
}
vector freq_vec = chv("freq");
vector off_vec = chv("offset");
float rough_f = chf("rough");
float lac_f = chf("lacunarity");
int oct_num = chi("octaves");
float exp_f = chf("exp_scale");
float scl = chf("global_scale");
float nval = fractal_noise(@P, freq_vec, off_vec, rough_f, lac_f, oct_num, exp_f);
@P.y += nval;
Matching Points Against Multiple Groups
int match_res = 0;
string grp_list[] = split(chs("group_mask"));
foreach (string g; grp_list) {
match_res = inpointgroup(0, g, @ptnum);
}
Accessing Global Frame Count
float frame_num = atof(`$NFRAMES`);
printf("%g\n", frame_num);
Appending Points to Exisitng Geometry
int last_idx = npoints(geoself()) - 1;
vector new_pos = point(geoself(), "P", last_idx) + set(0, 0, 0.1);
int new_pt = addpoint(geoself(), new_pos);
addvertex(geoself(), 0, new_pt);
Steering Partciles Along a Curve
float close_r = ch("close_range");
float far_r = ch("far_range");
int curve_src = pcopen(1, "P", @P, 10000, 30);
int cur_idx = i@target_idx;
int prev_idx = i@target_idx;
float path_len = 0;
vector align_dir, guide_dir;
int hit_cnt = 0;
if (pcnumfound(curve_src) > 0) {
while (pciterate(curve_src)) {
int seg_idx, src_id;
pcimport(curve_src, "curve_id", seg_idx);
pcimport(curve_src, "source_curve", src_id);
pcimport(curve_src, "N", guide_dir);
pcimport(curve_src, "P", align_dir);
pcimport(curve_src, "sum", hit_cnt);
pcimport(curve_src, "perimeter", path_len);
if (seg_idx > cur_idx && src_id == i@src_curve) {
if (seg_idx - cur_idx <= 3) {
i@target_idx = seg_idx;
break;
}
}
}
}
if (i@target_idx <= prev_idx) {
i@target_idx += 1;
int pt_cnt = findattribvalcount(1, "point", "curve_id", i@target_idx);
for (int k = 0; k < pt_cnt; k++) {
int tmp_pt = findattribval(1, "point", "curve_id", i@target_idx, k);
int src = point(1, "source_curve", tmp_pt);
if (src == i@src_curve) {
guide_dir = point(1, "P", tmp_pt);
align_dir = point(1, "N", tmp_pt);
break;
}
}
}
v@guide_pos = guide_dir;
vector to_target = (guide_dir - @P) * (float(cur_idx) / hit_cnt);
float ratio = float(cur_idx) / hit_cnt;
vector force_a = normalize(to_target) * chf("power") * (frand(@id * 6.7) * 0.6 + 0.4);
vector force_b = normalize(align_dir) * chf("power") * (frand(@id * 6.7) * 0.6 + 0.4) * (ratio * 0.5 + 0.8);
v@steer_force = lerp(force_a * 14, force_b * 70, fit(distance(guide_dir, @P), 0.08, 0, 0, 1));
v@steer_force *= (frand(@id * 104.6) + 0.01);