Last active
July 11, 2022 18:04
-
-
Save howiemnet/d9bae48fb1547edfe6b43d81308bccb4 to your computer and use it in GitHub Desktop.
Houdini Particle distance resizer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// NOTE: ignore the .cpp extension on the filename - this is VEX | |
// but I couldn't find a gist-friendly way to syntax-hilight it | |
// ¯\_(ツ)_/¯ | |
// | |
// h's magic adaptive point resizer for optimal | |
// rendering of tiny points/particles/wires | |
// | |
// 1/2/2018 [email protected] | |
// CC-0 - use and abuse | |
// ----------------------------------- | |
// | |
// Sanity checks | |
// | |
// ----------------------------------- | |
// Gotta have a camera! | |
if (chs("parm_cam_obj")=="") { | |
error("Need a camera object!"); | |
} | |
// Make sure there are pscale | |
// and Alpha attribs on the points | |
if (!haspointattrib(0, "pscale")) { | |
@pscale = 1.0; | |
} | |
if (!haspointattrib(0, "Alpha")) { | |
f@Alpha = 1.0; | |
} | |
// ----------------------------------- | |
// | |
// Pre-scaling | |
// | |
// ----------------------------------- | |
f@pscale *= chf("parm_pre_scale"); | |
// ----------------------------------- | |
// | |
// Get camera information | |
// | |
// ----------------------------------- | |
vector camPos = cracktransform(0,0,0,{0,0,0},optransform(chs("parm_cam_obj"))); | |
float resx = ch("`chs("parm_cam_obj")`/resx"); | |
float focal = ch("`chs("parm_cam_obj")`/focal"); | |
float filmwidth = ch("`chs("parm_cam_obj")`/aperture"); | |
// Per point, first transform it into world-space: | |
vector myP = ptransform("space:object","space:world",@P); | |
// get the distance between point and camera: | |
float dist_to_cam = abs(length(myP-camPos)); | |
// calculate resultant pixel size of the point: | |
float pixelSize; | |
if (chi("parm_use_dome_projection")) { | |
// dome projection | |
pixelSize = (atan(2*@pscale / dist_to_cam) * (resx/2.0)); | |
} else { | |
// perspective projection | |
pixelSize = ((2*@pscale / dist_to_cam) * ((resx * focal) / filmwidth)); | |
} | |
// now we know how big it'll be, we can calculate what | |
// factor it'd take to make it exactly the size (in pixels) specified | |
// by the user | |
if ((pixelSize == 0.0) || (@Alpha == 0.0)) { | |
// No point in dealing with things you | |
// can't see | |
@Alpha = 0.0; | |
} else { | |
// Calculate how much the particle needs | |
// to be embiggened to end up large enough | |
// to hit the minimum threshold: | |
float multFac = chf("parm_min_pixels")/pixelSize; | |
// If Visualise is enabled, don't change any sizes - | |
// just change the colour. | |
if (chi("parm_visualise")) { | |
@Cd = {0,1,0}; | |
if (pixelSize < chf("parm_min_pixels")) { | |
@Cd = {1,0,0}; | |
} | |
} else { | |
// Not in Visualise mode, so do the scaling and fading. | |
// | |
// If we're dealing with wires, Alpha needs to | |
// be reduced by the same factor as the width increase. | |
// For round points, the Alpha needs to be reduced by | |
// the square of the radius increase instead | |
if (pixelSize < chf("parm_min_pixels")) { | |
// Tiny points: | |
@pscale *= multFac; | |
if (chi("parm_col_not_alpha")) { | |
@Cd /= chi("parm_wires") ? multFac : pow(multFac,2); | |
} else { | |
@Alpha /= chi("parm_wires") ? multFac : pow(multFac,2); | |
} | |
} else { | |
// Big points: | |
if (chi("parm_brighten_near_ones")) { | |
// No point in providing an Alpha option | |
// here: only practical to brighten them | |
@pscale *= multFac; | |
@Cd /= chi("parm_wires") ? multFac : pow(multFac,2); | |
} | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment