top of page
Writer's pictureDavid Mans

Random Hair on Surface

💻 Rhino 5

🔼 Rhino Script

🛠️ Visual Basic

 

This rhino script allows the user to create highly varied, yet controllable, low polygon count “hairs”. This script operates based on the world coordinate system, growing upwards from a user-selected series of points.

Version 2 allows for the selection of a surface which will be randomly populated with grass blades perpendicular to the surface (about the surface normal) The user is given the option to specify the range of lengths (min-max), the range of bending per segment, and the base and tip radius. The user can control the number of segments the blade will have, the more segments, the smoother the bend, the greater the polygons. In addition as part of the interest in polygon optimization, the user can specify the number of sides on each blade, a 2 sided blade is flat, 3 sided become three dimensional (triangular), 4 rectangular, etc. the higher the number the rounder it is, the higher the polygon count.

 
Option Explicit
'Script written by <David Mans>
'Script copyrighted by <Neoarchaic Studio>
'Script version Sunday, July 05, 2009 9:42:52 PM
 
Call Main()
Sub Main()
    Dim strSurface, arrInputs
     
    strSurface = Rhino.GetObject("Select Surface", 8)
    If isNull(strSurface) Then Exit Sub
    Call reparameterize(strSurface)
     
    arrInputs = Rhino.PropertyListBox(array("Count", "Min Length", "Max Length", "Min Hair Bend", "Max Hair Bend", "Base Radius", "Tip Radius", "Segments", "Sides"), array(1000, 4, 12, 10, 45, 0.1, 0.01, 5, 2))
    If isNull(arrInputs) Then Exit Sub
     
    Dim i, stem(), blades(), sides
    If CInt(arrInputs(7)) < 2 Then
        sides = 2
    Else
        sides = CInt(arrInputs(7))
    End If
     
    Dim arrPlanes
     
    Call Rhino.EnableRedraw(False)
    arrPlanes = randomPtsSrf(strSurface, CInt(arrInputs(0)))
     
    ReDim stem(uBound(arrPlanes)), blades(uBound(arrPlanes))
    For i = 0 To uBound(arrPlanes) Step 1
        stem(i) = segmentedStem(arrPlanes(i), random(CDbl(arrInputs(1)), CDbl(arrInputs(2))), CInt(arrInputs(7)), random(CDbl(arrInputs(3)), CDbl(arrInputs(4))))
        blades(i) = bladesFlat(stem(i), CDbl(arrInputs(5)), CDbl(arrInputs(6)), sides)
    Next
    Call Rhino.EnableRedraw(True)
End Sub
Function randomPtsSrf(strSurface, intCount)
    randomPtsSrf = Null
    Dim i, uDom, vDom, arrOutput()
    ReDim arrOutput(intCount-1)
    uDom = Rhino.SurfaceDomain(strSurface, 0)
    vDom = Rhino.SurfaceDomain(strSurface, 1)
     
    For i = 0 To intCount - 1 Step 1
        arrOutput(i) = Rhino.SurfaceFrame(strSurface, array(random(uDom(0), uDom(1)), random(vDom(0), vDom(1))))
    Next
 
    randomPtsSrf = arrOutput
End Function
Function bladesFlat(arrPlanes, radB, radT, intSteps)
    bladesFlat = Null
    Dim i, j, k, r, arrOutput
    Dim radStep, rotStep
    Dim arrPoints(),arrFaces(), arrMesh()
    ReDim arrMesh(intSteps-1)
    If radB > radT Then
        radStep = -(radB - radT) / uBound(arrPlanes)
    Else
        radStep = (radT - radB) / uBound(arrPlanes)
    End If
     
    rotStep = 360 / intSteps
     
    For k = 0 To intSteps - 1 Step 1
        r = 0
        For i = 0 To uBound(arrPlanes) Step 1
            ReDim Preserve arrPoints(r)
            arrPoints(r) = Rhino.PointAdd(arrPlanes(i)(0), Rhino.VectorScale(Rhino.VectorUnitize(Rhino.RotatePlane(arrPlanes(i), k * rotStep, arrPlanes(i)(3))(1)), radB + i * radStep))
            r = r + 1
            ReDim Preserve arrPoints(r)
            arrPoints(r) = Rhino.PointAdd(arrPlanes(i)(0), Rhino.VectorScale(Rhino.VectorUnitize(Rhino.RotatePlane(arrPlanes(i), (k + 1) * rotStep, arrPlanes(i)(3))(1)), radB + i * radStep))
            r = r + 1
         
        Next
        r = 0
        ReDim arrFaces(uBound(arrPoints)-2)
        For i = 0 To uBound(arrPoints) - 2 Step 2
            arrFaces(r) = array(i, i + 1, i + 3, i + 3)
            r = r + 1
            arrFaces(r) = array(i, i + 3, i + 2, i + 2)
            r = r + 1
        Next
        If intSteps = 2 Then
            If k = 1 Then
                arrOutput = Rhino.addmesh(arrPoints, arrFaces)
            End If
        Else
            arrMesh(k) = Rhino.addmesh(arrPoints, arrFaces)
        End If
    Next
    If intSteps >< 2 Then
        arrOutput = Rhino.MeshBooleanUnion(arrMesh)
    End If
    bladesFlat = arrOutput
End Function
Function segmentedStem(arrPlane, dblHeight, dblSegments, maxRotation)
    segmentedStem = Null
    Dim i, count
    count = dblSegments - 1
    Dim dblStep, tempLen, dblLen()
    Dim mPlane(), tmpAngle(1), blnWavy
    ReDim dblLen(count), mPlane(count+1)
     
    mPlane(0) = Rhino.RotatePlane(arrPlane, random(0, 360), arrPlane(3))
    blnWavy = random(-1, 1)
     
    dblStep = dblHeight / dblSegments
    For i = 0 To count Step 1
        If i = 0 Then
            tempLen = random(0.5, 1) * dblStep
            dblLen(i) = dblStep - tempLen
        ElseIf i = count Then
            tempLen = dblStep + dblLen(i - 1)
        Else
            tempLen = random(0.5, 1) * (dblStep + dblLen(i - 1))
            dblLen(i) = dblStep + dblLen(i - 1) - tempLen
        End If
        If blnWavy >= 0 Then
            tmpAngle(0) = random(0, maxRotation)
            tmpAngle(1) = random(0, maxRotation)
        Else
            tmpAngle(0) = random(-maxRotation, 0)
            tmpAngle(1) = random(-maxRotation, 0)
        End If
        mPlane(i + 1) = Rhino.RotatePlane(Rhino.RotatePlane(Rhino.moveplane(mPlane(i), Rhino.PointAdd(mPlane(i)(0), Rhino.VectorScale(Rhino.VectorUnitize(mPlane(i)(3)), tempLen))), tmpAngle(0), mPlane(i)(1)), tmpAngle(1), mPlane(i)(2))
    Next
    segmentedStem = mPlane
End Function
Function reparameterize(strObjectID)
    If Rhino.IsCurve(strObjectID) = True Then
        Call rhino.SelectObject(strObjectID)
        Call rhino.Command("reparameterize 0 1", False)
        Call rhino.UnselectAllObjects()
    End If
    If Rhino.IsSurface(strObjectID) = True Then
        Call rhino.SelectObject(strObjectID)
        Call rhino.Command("reparameterize 0 1 0 1", False)
        Call rhino.UnselectAllObjects()
    End If
End Function
Function random(min, max)
    random = Null
    Dim dblValue: dblValue = min + (max - min) * rnd()
    random = dblValue
End Function
 


1 view

Recent Posts

See All

Comments


bottom of page