A NURBS grass generated by script and scattered around the field using particles

The script:

import bpy
from random import random,randrange

def space():
    return randrange(-10000,10000)/100
def randhalf():
    return random()*2-1

curve = bpy.data.curves.new('ProceduralGrass', 'CURVE')
curve.dimensions = '3D'
curve.bevel_depth=.1
curve.bevel_resolution=4
curve.twist_mode='TANGENT'
curve.twist_smooth=.13

for i in range(256):
    place=(space(),space(),0,1)
    for j in range(randrange(3,13)):
        x,y,z,w=place
        spline = curve.splines.new(type='NURBS')
        spline.points.add(3)
        spline.points[1].co=(x,y,z,w)
        spline.points[1].radius=5
        spline.points[0].co=(x+randhalf()*2,y+randhalf()*2,-4,10)
        spline.points[0].radius=15
        x+=randhalf()*3
        y+=randhalf()*3
        z+=random()*36#or 25,16,9,4
        spline.points[2].co=(x,y,z,w)
        spline.points[2].radius=1.5
        x+=randhalf()*25#or 36,49,64,81
        y+=randhalf()*25#or 36,49,64,81
        z+=random()*16
        spline.points[3].co=(x,y,z,w)
        spline.points[3].radius=1

curve_object = bpy.data.objects.new('ProceduralGrass', curve)
scene = bpy.context.scene
scene.objects.link(curve_object)

And the result:


Thanks bckpkol,

I will see if I can create an addon with that…
Very nice result!
At soon…

I did even better. Changes:
wider grass;
Filmic Blender;
glossy shader intensity fix;
density;
textures.
Result:


curve.use_uv_as_generated=True

Not bad… what is main advantages of this method?

Maybe memory management?

I still didn’t figured out the advantages, but I never had such a complex grass. Blender was always freezing at more than 65536 particles, that’s only about 200. I’m currently thinking about lesser size fields for more uneven terrain. Now the rounded version of the field script:

import bpy
from math import pi,sin,cos
from random import random,randrange

def space():
    radian=pi*2*random()
    pos=randrange(10000)/100
    return (cos(radian)*pos,sin(radian)*pos)
def randhalf():
    return random()*2-1

curve = bpy.data.curves.new('ProceduralGrass', 'CURVE')
curve.dimensions = '3D'
curve.bevel_depth=.1
curve.bevel_resolution=4
curve.twist_mode='TANGENT'
curve.twist_smooth=.13
curve.use_uv_as_generated=True

for i in range(256):
    place=(*space(),0,1)
    for j in range(randrange(3,13)):
        x,y,z,w=place
        spline = curve.splines.new(type='NURBS')
        spline.points.add(3)
        spline.points[1].co=(x,y,z,w)
        spline.points[1].radius=5
        spline.points[0].co=(x+randhalf()*2,y+randhalf()*2,-4,10)
        spline.points[0].radius=15
        x+=randhalf()*3
        y+=randhalf()*3
        z+=random()*4
        spline.points[2].co=(x,y,z,w)
        spline.points[2].radius=1.5
        x+=randhalf()*81
        y+=randhalf()*81
        z+=random()*16
        spline.points[3].co=(x,y,z,w)
        spline.points[3].radius=1

curve_object = bpy.data.objects.new('ProceduralGrass', curve)
scene = bpy.context.scene
scene.objects.link(curve_object)


Try this:

import bpy
from math import pi,sin,cos
from random import random,randrange

def space():
    radian=pi*2*random()
    pos=randrange(1000)/100
    return (cos(radian)*pos,sin(radian)*pos)
def randhalf():
    return random()*2-1

group = bpy.data.groups.new('ProceduralGrass')

for root in range(2,5):
    height=root*root
    width=11-root
    width*=width
    for count in range(32):
        curve = bpy.data.curves.new('ProceduralGrass', 'CURVE')
        curve.dimensions = '3D'
        curve.bevel_depth=.1
        curve.bevel_resolution=4
        curve.twist_mode='TANGENT'
        curve.twist_smooth=.13
        curve.use_uv_as_generated=True
        for i in range(16):
            place=(*space(),0,1)
            for j in range(randrange(3,13)):
                x,y,z,w=place
                spline = curve.splines.new(type='NURBS')
                spline.points.add(3)
                spline.points[1].co=(x,y,z,w)
                spline.points[1].radius=5
                spline.points[0].co=(x+randhalf()*2,y+randhalf()*2,-4,10)
                spline.points[0].radius=15
                x+=randhalf()*3
                y+=randhalf()*3
                z+=random()*height
                spline.points[2].co=(x,y,z,w)
                spline.points[2].radius=1.5
                x+=randhalf()*width
                y+=randhalf()*width
                z+=random()*16
                spline.points[3].co=(x,y,z,w)
                spline.points[3].radius=1
        curve_object = bpy.data.objects.new('ProceduralGrass', curve)
        scene = bpy.context.scene
        scene.objects.link(curve_object)
        group.objects.link(curve_object)
        curve_object.rotation_euler[1]=pi/2

Test render, no DOF, no textures, no fog, no Fresnel:


That’s not perfect, sea volume should be denser, mist should start later.



Without mist:

Thanks bckpkol, for your warning.
I havn’t yet tested your code but your result is interesting. because reflectivity in #3 is very random and make your grass more real!
At soon…