Floor generator script (work in progress)


#1

see script below for explanation

"""
floor maker script *** work in progress ***
goal is to make something that looks like floor generator for 3dsmax
would require a multimaterial and ability to assign material IDs to objects
to work properly and ultimately randomization of the map color per object
which is currently not possible vray as far as I know.

Script will generate floor planks and add random text coordinates to each plank
but will do that within the maps size.
Right now a texture size of 2000 x 300 units is chosen. So the smaller the
planks are, the more it can be randomized

other possibilities to include:
- making the planks not straight, but this will require denser meshes
- rotation (180 degrees) of textures for more quasi uniqueness
- a check to avoid seams on short ends to not come to close together
***********************************
* script written by Gijs de Zwart *
* www.studiogijs.nl               *
* April, 2016                     *
***********************************
"""

import Rhino
import rhinoscriptsyntax as rs
import scriptcontext as sc
import random
import math

def createMesh(vertices,face_vertices):
    mesh = Rhino.Geometry.Mesh()
    for a, b, c in vertices: mesh.Vertices.Add(a, b, c)
    for face in face_vertices:
        if len(face)<4:
            mesh.Faces.AddFace(face[0], face[1], face[2])
        else:
            mesh.Faces.AddFace(face[0], face[1], face[2], face[3])
    return mesh


def addPlank(plane, width, length):
    
    #define texture size in world units here
    texWidth = 2000
    texHeight = 300
    
    rect=Rhino.Geometry.Rectangle3d(plane,width,length)
    pts=[rect.Corner(i) for i in range(0,4)]
    pts2=[]
    for i in range(0,4):
        pts2.append(Rhino.Geometry.Point3d(0,0,20))
    for i in range(0,len(pts2)):#modify points
        pts2[i].X=pts[i].X
        pts2[i].Y=pts[i].Y
    for pt in pts2:#add points to original points
        pts.append(pt)
        
    faceVertices = []
    faceVertices.append((0,3,2,1))
    faceVertices.append((0,1,5,4))
    faceVertices.append((1,2,6,5))
    faceVertices.append((2,3,7,6))
    faceVertices.append((3,0,4,7))
    faceVertices.append((4,5,6,7))
    
    
    mesh=createMesh(pts,faceVertices)
    mesh.Unweld(.3,True)
    dx=Rhino.Geometry.Interval(0,texWidth)
    dy=Rhino.Geometry.Interval(0,texHeight)
    dz=Rhino.Geometry.Interval(0,20)
    #add mesh to document to apply a texture map
    newmesh = sc.doc.Objects.AddMesh(mesh)
    randX=(texHeight-width)*random.uniform(0,1)
    randY=(texWidth-length)*random.uniform(0,1)
    texplane=Rhino.Geometry.Plane.WorldXY
    texplane.Origin = plane.Origin
    texplane.Rotate(math.pi/2,plane.ZAxis)
    texplane.OriginY+=length-texWidth+randY
    texplane.OriginX+=texHeight-randX
    texmap = Rhino.Render.TextureMapping.CreatePlaneMapping(texplane,dx,dy,dz)    
    table = Rhino.RhinoDoc.ActiveDoc.Objects
    Rhino.DocObjects.Tables.ObjectTable.ModifyTextureMapping(table,newmesh,1,texmap)

def randomFloor():
    floorwidth = rs.GetReal("enter floor width size",10000)
    floorlength = rs.GetReal("enter floor length size",10000)
    width=rs.GetReal("enter plank width",140)
    maxlength = rs.GetReal("enter plank max length",2000)
    minlength = rs.GetReal("enter plank min length",700)
    gapwidth = rs.GetReal("enter gap width", 2)
    plane = Rhino.Geometry.Plane.WorldXY
    i=0
    meshes=[]
    temp=0
    while i<floorwidth:
        j=0
        plane.OriginY=0
        while j<floorlength:
            
            randomlength = random.randint(minlength,maxlength)
            if j==0:
                startlength=random.randint(2,20)*maxlength/20
                while temp==startlength:
                    startlength=random.randint(3,20)*maxlength/20
                temp=startlength
                addPlank(plane, width, startlength)
                j+=startlength+gapwidth
                
            elif randomlength<floorlength-j:
                #if (floorlength-j)/2<randomlength:
                    #randomlength-=300
                addPlank(plane, width, randomlength)
                j+=randomlength+gapwidth
                
            else:
                addPlank(plane, width, floorlength-j)
                j=floorlength
                
            plane.OriginY=j
            
        plane.OriginX+=width+gapwidth
        i+=width
    floor=[sc.doc.Objects.AddMesh(mesh) for mesh in meshes]
    sc.doc.Views.Redraw()
            
    
randomFloor()


#2

Great! I was just deciding how to do this and saw your script. I wanted to have variable plank widths so I put in a random and IF stmts to select between 4.75 to 6 " with 1/4" increments. Also, I dont have a rectangular layout so I am turning the resulting meshes into NURB boxes and then triming them to size. Another thing I want to do is prevent edge joints being closer than 6" on adjacent rows and some other layout suggestions. Any comments?


#3

For now it’s probably easiest to turn on the control points of the generated mesh boxes and move some that are outside the boundary, and move some seams that are too close together. Because otherwise you will loose the texture mapping when turning them into nurbs boxes.


#4

Is this script working for anyone else? I edit a new script and copy/paste this into the script but I’m getting all kinds of error messages, such as “expected end of statement”. I’ve used Rhino for 12 years but a total amateur with the script editor. I’m using Rhino 5…


#5

Just tested it and it still works. Just to make sure: you choose EditPythonScript, not EditScript, because this is a python script.


#6

Thanks for clarifying, I wasn’t using Python and it’s working great now! Is there an easy way to apply texture mapping to the planks or is this a manual job?


(Andrea Montis) #7

Hey, new vray has multisubtext and random object id option, it is really simple to implement it… :wink:


#8

random mapping is included in the script. If your wood texture is large enough, it will look as if each plank is different.


#9

Anything new to know about this script and Rhino6 and Vray 3.6? Would really like to figure out how to have a more realistic plank floor with subtle randomness throught.

Thx


#10

the script is not bound to VRay, it’s just making the geometry and applying the texture coordinates. So it should work with any renderer/version


(Alexander Petrov) #11

Wow, this would be great man! I have found difficulties with the Floor generator for Max, especially when I had to export the texture. It seem that I couldn’t handle with the texture baking, which is needed to export texture and import it in Rhino.


#12

Is there a small tutorial of it somewhere? :slight_smile:


#13

I believe you are responding to Pitti’s question? Just select your objects and run VraySetObjectID, random then go to properties and select objects by ID and apply a material to it.
the multimaterial in Vray for Rhino is, as far as I know, only for proxy objects. Here at least, it doesn’t work to apply multimaterials to groups of objects that have their ID set.