Processing to rhino/Grasshopper

Hi @Shruhman,

Yes, it is possible to connect Processing with Rhino/Grasshopper and the way people usually do it is by sending UDP sockets via OSC protocol. For that you will need to install:

  • OscP5 for Processing (client side)
  • gHowl for Grasshopper (server side)

However there are 3 main limitations to this kind of set-up:

  • because of the difference of format between the two environments (PVector vs Vector, PShape vs Surface, Mesh or Polyline, etc), each geometry must be broken down to a set of coordinates.

  • these coordinates can be sent via 1D arrays only. 2D arrays will automatically be flatten.

  • UDP packet length is reached very quickly and cannot allow for the transfer of large amount of coordinates (<1000 points per message).

In other words, not only the geometry you chose to send must be limited in size (coordinates data) but it also needs to be reconstructed upon reception.

First example: The vertices of a polygon (list of PVectors) are converted one by one as tuples (x and y coordinates as floats) and sent in a single message from Processing to Grasshopper. Upon reception the 1D array is transformed to a “data tree” with branches of size 2 using the Partition List component. Points are then reconstructed and used as input vertices to form a closed “polyline”.

Processing sketch (Python mode)
add_library('oscP5')

verts = [PVector(228, 131),PVector(233, 142),PVector(188, 141),PVector(280, 168),PVector(266, 149),PVector(297, 142),
         PVector(291, 163),PVector(322, 180),PVector(288, 173),PVector(325, 196),PVector(339, 225),PVector(387, 214),
         PVector(443, 169),PVector(491, 160),PVector(560, 208),PVector(608, 268),PVector(636, 270),PVector(664, 308),
         PVector(650, 446),PVector(667, 472),PVector(661, 459),PVector(676, 467),PVector(680, 450),PVector(666, 423),
         PVector(707, 447),PVector(686, 495),PVector(671, 495),PVector(731, 580),PVector(748, 584),PVector(734, 557),
         PVector(766, 560),PVector(755, 569),PVector(764, 617),PVector(789, 594),PVector(773, 624),PVector(791, 628),
         PVector(813, 700),PVector(862, 708),PVector(891, 759),PVector(922, 780),PVector(911, 788),PVector(891, 773),
         PVector(907, 799),PVector(967, 774),PVector(984, 782),PVector(998, 689),PVector(1005, 678),PVector(1010, 695),
         PVector(1004, 555),PVector(888, 338),PVector(874, 294),PVector(889, 316),PVector(907, 314),PVector(912, 366),
         PVector(915, 322),PVector(825, 196),PVector(767, 61),PVector(779, 59),PVector(773, 43),PVector(711, 33),
         PVector(703, 98),PVector(681, 72),PVector(375, 83),PVector(353, 46),PVector(55, 70),PVector(90, 144),
         PVector(70, 165),PVector(97, 154),PVector(107, 125),PVector(119, 139),PVector(126, 118),PVector(142, 139),
         PVector(109, 152),PVector(189, 124)]


def setup():

    osc = OscP5(this, 12002) 
    net = NetAddress("127.0.0.1", 12002) #remote location 
    message = OscMessage("/gHowlTest")
    for v in verts:
        message.add((v.x, v.y))
    osc.send(message, net)

Second example: At each iteration of a simple Line Growth algorithm the connectivity information of all the vertices (whole list of indices as integers, no coordinates) is sent from Processing to Grasshopper. Upon reception indices are grouped back to couples and used to construct lines. All the physics (springs + repulsive force) is then handled by the Kangaroo plugin.

Processing sketch (Python mode)
add_library('oscP5')

a = [(0, 1), (0, 2), (1, 2)] 
z = 3 

def setup():
    global osc
    osc = OscP5(this, 12001) 
    
def draw():
    global z
    
    if z <100:
        id = int(random(z)) 
        x, y = a[id] 
        del a[id] 
        a.extend([(y, z), (z, x)])
        z += 1 
        
        net = NetAddress("127.0.0.1", 12001) #remote location 
        message = OscMessage("/gHowlTest")
        message.add(sum(a,()))
        osc.send(message, net)

For the transfer and the reconstruction of meshes, see this past post of mine on a similar topic.

Grasshopper file

4 Likes