MathJax example

Theory

MathJax example

Generating braid geometry using parametric curves. Based on a paper by Pixar. Learn more

A braid consists of $N$ individual curves where each curve, denoted by $S(t)$, is defined by:

$S(t) = \begin{cases}     x(t) = Asin(2\pi(F\alpha(t)+\delta))\\    y(t) = Bsin(2\pi(F\beta(t)-\delta))\\ z(t) += \omega \end{cases}$

$\text{where}$ $t \in [0,1]$.

$A = \text{ Braid thickness}$

$B = \text{Braid width}$

$F = \text{Frequency of knots}$

$\alpha(t)$ = is any function of $t$ and defines the distribution of the knots along the braid. For example you can let $\alpha(t) = t$ or $\alpha(t) = t^2$ etc.

$\beta(t) = \alpha(t)*0.5$

$\delta = \text{Strand Number} / \text{Total number of strands}$

$\omega$ = the amount by which to extend the curve along z direction at each time interval.

Implementation

The code block below is an example of how we could generate braid geometry using VEX scripting in Houdini. I have added some extra functionality like phase shift and variable scaling. If you would like to experiment with different values all you have to do is copy and paste this code into a "Detail Wrangle" node inside Houdini.

View VEX code
drop down toggle arrow
 


int numStrands = chi("strand_number");
int time_step = chi("divisions");
float length = chf("Length");
float F = chf("Frequency");
float A = chf("thickness");
float B = chf("width");
float phasex = chf("phase_X");
float phasey = chf("phase_Y");
float timeDomain = chf("time_domain");
int exponent = chi("alpha_order");
vector S_t;
float delta_time = 1.0/time_step;
float alpha; 
float beta;
int prev_pt;
int firstPoint = -1;
int newPt = -1;

for(int N_strand = 0; N_strand < numStrands; N_strand++)
{
  float strandRatio = (float)N_strand/numStrands;
  prev_pt = -1;
   
  for(float i=0;i<timeDomain; i+=delta_time)
  {
        float thicknessRamp = chramp("thickness_ramp", i);
        float widthRamp = chramp("width_ramp", i);
        alpha = pow(i,exponent);  // let alpha be any function of i like alpha = i*i; or alpha = sqrt(i) etc... 
        beta = 0.5*alpha;
       
        S_t.x = thicknessRamp*A*sin(2*PI*(F*alpha+strandRatio)+phasex*N_strand);
        S_t.y = widthRamp*B*sin(2*PI*(F*beta-strandRatio)+phasey*N_strand);
        S_t.z = i*length;
        
        newPt = addpoint(0, S_t);
        if(prev_pt == -1)
        {
            prev_pt = newPt;
            firstPoint = newPt;
        }
        else
        {
            int new_prim = addprim(0,"polyline");
            addvertex(0, new_prim, prev_pt);
            addvertex(0, new_prim, newPt);
            prev_pt = newPt;
        }
        
        //pscale for polywire
        float radius = i;
        if(ch("adaptiveRadius")==1){
            radius = i/timeDomain;
        }
        float pscale = chf("radius_scale")*chramp("wire_radius", radius);
        setpointattrib(0,"pscale",newPt, pscale);
        
    }
    

}


Once you run the script you will have to initialize some variables. You can use the image below as a reference.