from nodebpy import geometry as g
with g.tree("Hello World") as tree:
height = tree.inputs.float("Height", 3.0)
omega = tree.inputs.float("Omega", 2.0)
with g.Frame("Computing the wave"):
pos = g.Position().o.position
distance = g.Math.square_root(pos.x**2 + pos.y**2)
z = height * g.Math.sine(distance * omega) / distance
with g.Frame("Point offset & smooth"):
mesh = (
g.Grid(20, 20, 200, 200)
>> g.SetPosition(offset=g.CombineXYZ(z=z))
>> g.SetShadeSmooth.face()
)
mesh >> tree.outputs.geometry("Mesh")Comapring the API
How does the API compare to other existing solutions?
geonodes
‘Hello World’
The hello world example from geonodes readme: https://github.com/al1brn/geonodes
from geonodes import *
with GeoNodes("Hello World"):
height = 3
omega = 2
grid = Mesh.Grid(vertices_x=200, vertices_y=200, size_x=20, size_y=20)
with Layout("Computing the wave"):
pos = nd.position
distance = gnmath.sqrt(pos.x**2 + pos.y**2)
z = height*gnmath.sin(distance*omega)/distance
with Layout("Point offset and smoothness"):
grid.offset = (0, 0, z)
grid.faces.smooth = True
grid.out()geometry-script
README Demo
from nodebpy import geometry as g
with g.tree("Repeat Grid") as tree:
geometry = tree.inputs.geometry("Geometry")
width = tree.inputs.integer("Width")
height = tree.inputs.integer("Height")
(
g.Grid(width, height, vertices_x=width, vertices_y=height)
>> g.MeshToPoints()
>> g.InstanceOnPoints(instance=geometry)
>> tree.outputs.geometry("Instances")
)from geometry_script import *
@tree("Repeat Grid")
def repeat_grid(geometry: Geometry, width: Int, height: Int):
g = grid(
size_x=width, size_y=height,
vertices_x=width, vertices_y=height
).mesh.mesh_to_points()
return g.instance_on_points(instance=geometry)Primitive Shapes
from nodebpy import geometry as g
with g.tree("Primitive Shapes") as tree:
join = g.JoinGeometry([g.Cube(), g.UVSphere(), g.Cylinder()])
join >> tree.outputs.geometry("Result")@tree("Primitive Shapes")
def primitive_shapes():
yield cube()
yield uv_sphere()
yield cylinder().meshVoxelise
Example script found here.
from nodebpy import geometry as g
with g.tree("Voxelise") as tree:
geo = tree.inputs.geometry("Geometry")
resolution = tree.inputs.float("Resolution", 0.2)
(
geo
>> g.MeshToVolume(interior_band_width=resolution)
>> g.DistributePointsInVolume(mode="Grid", spacing=resolution)
>> g.InstanceOnPoints(instance=g.Cube(size=resolution))
>> tree.outputs.geometry("Result")
)from geometry_script import *
@tree("Voxelize")
def voxelize(geometry: Geometry, resolution: Float = 0.2):
return geometry.mesh_to_volume(
interior_band_width=resolution,
fill_volume=False
).distribute_points_in_volume(
mode=DistributePointsInVolume.Mode.DENSITY_GRID,
spacing=resolution
).instance_on_points(
instance=cube(size=resolution)
)City Builder
Example script found here.
from nodebpy import geometry as g
with g.tree("Voxelise") as tree:
geo = tree.inputs.geometry("Geometry")
seed = tree.inputs.integer("Seed")
road_width = tree.inputs.float("Road Width", 0.25)
size_x = tree.inputs.float("Size X", 5.0)
size_y = tree.inputs.float("Size Y", 5.0)
density = tree.inputs.float("Density", 10.0)
building_size_min = tree.inputs.vector("Building Size Min", (0.1, 0.1, 0.2))
building_size_max = tree.inputs.vector("Building Size Max", (0.3, 0.3, 1.0))
curve_mesh = geo >> g.CurveToMesh(
profile_curve=g.CurveLine(
start=g.CombineXYZ(x=road_width * -0.5),
end=g.CombineXYZ(x=road_width * 0.5),
),
)
building_points = g.Grid(size_x, size_y) >> g.DistributePointsOnFaces(
density=density, seed=seed
)
road_points = geo >> g.CurveToPoints(mode="EVALUATED")
building_points = g.DeleteGeometry.point(
building_points,
selection=g.GeometryProximity(
target_element="POINTS",
target=road_points,
source_position=g.Position().o.position,
).o.distance
< road_width,
)
buildings = building_points >> g.InstanceOnPoints(
instance=g.Cube() >> g.TransformGeometry(translation=(0, 0, 0.5)),
scale=g.RandomValue.vector(
min=building_size_min, max=building_size_max, seed=seed
),
)
g.JoinGeometry((curve_mesh, buildings)) >> tree.outputs.geometry("Result")from geometry_script import *
@tree("City Builder")
def city_builder(
geometry: Geometry,
seed: Int,
road_width: Float = 0.25,
size_x: Float = 5,
size_y: Float = 5,
density: Float = 10,
building_size_min: Vector = (0.1, 0.1, 0.2),
building_size_max: Vector = (0.3, 0.3, 1),
):
# Road mesh
yield geometry.curve_to_mesh(
profile_curve=curve_line(
start=combine_xyz(x=road_width * -0.5), end=combine_xyz(x=road_width * 0.5)
)
)
# Building points
building_points = (
grid(size_x=size_x, size_y=size_y)
.distribute_points_on_faces(density=density, seed=seed)
.points
)
road_points = geometry.curve_to_points(mode=CurveToPoints.Mode.EVALUATED).points
# Delete points within the curve
building_points = building_points.delete_geometry(
domain=DeleteGeometry.Domain.POINT,
selection=geometry_proximity(
target_element=GeometryProximity.TargetElement.POINTS,
target=road_points,
source_position=position(),
).distance
< road_width,
)
# Building instances
yield building_points.instance_on_points(
instance=cube().transform(translation=(0, 0, 0.5)),
scale=random_value(
data_type=RandomValue.DataType.FLOAT_VECTOR,
min=building_size_min,
max=building_size_max,
seed=seed,
),
)