

You can assign your materials (up to 3 materials) directly to the Python Generator object. You should change their selection names to Color1, Color2, and Color3.

Mondrian Subdivide Script: A Python Generator for Cinema 4D
The Mondrian Subdivide Script is a Cinema 4D Python generator that enables artists to create abstract, grid-based designs inspired by the famous works of Piet Mondrian. With its intuitive parameters and randomization options, this script offers endless possibilities for motion designers and graphic artists to add unique, geometric compositions to their projects.
How the Script Works
The script subdivides a rectangular area into smaller, randomized sections using a recursive process. It then combines these sections into a single geometry object, while allowing you to assign different color selections to the resulting polygons. The final output is a Mondrian-style grid that can be easily customized and animated.
Key Features
- Recursive Subdivision: Subdivide a rectangular area into smaller sections with adjustable depth and randomness.
- Randomized Layouts: Use a seed value to generate unique layouts every time.
- Custom Polygon Selections: Automatically create polygon selection tags for applying different materials or colors.
- Adjustable Percentages: Distribute polygons into three customizable selection groups.
- Dynamic Grid Size: Control the overall size of the grid to fit your scene.
- Automatic Updates: Refresh the geometry with one click using the “Refresh” parameter.
Use Cases
- Motion Graphics: Animate the grid’s subdivisions or apply materials to create dynamic visuals.
- Graphic Design: Generate abstract geometric patterns for print or web designs.
- Architectural Mockups: Create facade designs with random or structured layouts.
- Abstract Art: Experiment with layouts and colors to produce digital art.
- Material Testing: Assign different materials to polygon groups for testing textures.
How to Use the Script
User Data Parameters
Before using the script, add the following user data fields to the Python Generator object:
- Subdivision Depth: Controls the recursive depth of the subdivision (default: 5).
- Grid Size: Defines the overall size of the grid in Cinema 4D units (default: 800).
- Seed: Randomization seed for generating unique layouts (default: 1).
- Color Group Percentages: Set the target percentages for three selection groups:
- Color1 Percentage (default: 33%)
- Color2 Percentage (default: 33%)
- Color3 Percentage (default: 34%)
- Refresh: Boolean toggle to refresh and regenerate the layout.
Step-by-Step Instructions
- Add the Script: Paste the script into a Python Generator in Cinema 4D.
- Set the Parameters: Adjust the user data fields to customize the layout.
- Generate the Layout: The script will create a Mondrian-style grid layout based on your parameters.
- Apply Materials: Use the generated selection tags (
Color1,Color2,Color3) to assign materials or colors to different groups of polygons.
Technical Overview
Recursive Subdivision
The subdivide_area function recursively divides a rectangular area into smaller sections. It uses a random factor to determine whether to split horizontally or vertically, ensuring a unique layout every time.
def subdivide_area(area, depth, rng, min_size=40):
# Recursive subdivision logic
Combining Geometry
The combine_objects function merges individual rectangular objects into a single polygon object.
def combine_objects(objs):
# Combines multiple objects into one
Polygon Selection
The script automatically creates selection tags for three color groups, allowing you to apply different materials or colors to distinct areas.
def make_selection(obj, ids, name):
# Creates selection tags for polygons
Percentage-Based Distribution
The distribute_counts function divides the total number of polygons into three groups based on the specified percentages.
def distribute_counts(total, weights):
# Distributes polygons into groups based on target percentages
Debugging Information
The script includes a debug printout to help you understand the generated layout:
--- MONDRIAN DEBUG ---
Polygons=50
Target %: 33.0, 33.0, 34.0
Counts: [16, 16, 18] Sum=50
Selections: [16, 16, 18]
----------------------
Tips for Motion Designers
- Animate the Parameters: Keyframe the subdivision depth or grid size for evolving layouts.
- Material Experimentation: Use the selection tags to test different materials or shaders on the grid.
- Play with Seeds: Change the seed value to generate entirely new compositions.
- Add Lighting: Enhance the 3D effect by adding dynamic lighting to the grid.
- Use in Compositions: Combine the Mondrian grid with other Cinema 4D objects for more complex designs.
Conclusion
The Mondrian Subdivide Script is a versatile tool for creating abstract, grid-based designs in Cinema 4D. Its customizable parameters and randomization features make it perfect for motion designers, graphic artists, and 3D enthusiasts. Download the script, experiment with its settings, and incorporate it into your next creative project!
import c4d, random, math
def get_ud(op_obj, idx, default=None):
try: return op_obj[c4d.ID_USERDATA, idx]
except: return default
def create_rect(x1, y1, x2, y2):
pts=[c4d.Vector(x1,y1,0),c4d.Vector(x2,y1,0),c4d.Vector(x2,y2,0),c4d.Vector(x1,y2,0)]
poly=c4d.CPolygon(0,1,2,3)
o=c4d.PolygonObject(4,1)
o.SetAllPoints(pts); o.SetPolygon(0,poly); o.Message(c4d.MSG_UPDATE)
return o
def subdivide_area(area, depth, rng, min_size=40):
x1,y1,x2,y2=area
w,h=x2-x1,y2-y1
if depth<=0 or w<min_size or h<min_size:
return [area]
if rng.random()>0.5:
split=x1+w*rng.uniform(0.3,0.7)
return subdivide_area((x1,y1,split,y2),depth-1,rng,min_size)+subdivide_area((split,y1,x2,y2),depth-1,rng,min_size)
else:
split=y1+h*rng.uniform(0.3,0.7)
return subdivide_area((x1,y1,x2,split),depth-1,rng,min_size)+subdivide_area((x1,split,x2,y2),depth-1,rng,min_size)
def combine_objects(objs):
if not objs: return None
base=objs[0].GetClone(); bp=base.GetPointCount(); bpolys=base.GetPolygonCount()
for o in objs[1:]:
t=o.GetClone(); tp=t.GetPointCount(); tpol=t.GetPolygonCount()
base.ResizeObject(bp+tp,bpolys+tpol)
for i in range(tp): base.SetPoint(bp+i,t.GetPoint(i))
for i in range(tpol):
p=t.GetPolygon(i)
base.SetPolygon(bpolys+i,c4d.CPolygon(p.a+bp,p.b+bp,p.c+bp,p.d+bp))
bp+=tp; bpolys+=tpol
base.Message(c4d.MSG_UPDATE); return base
def make_selection(obj,ids,name):
if not ids:return
tag=c4d.SelectionTag(c4d.Tpolygonselection)
sel=tag.GetBaseSelect()
[sel.Select(i) for i in ids]
tag.SetName(name)
obj.InsertTag(tag)
def distribute_counts(total,weights):
s=sum(weights)
if s==0:return [0,0,0]
q=[(w/s)*total for w in weights]
f=[math.floor(v) for v in q]
remain=total-sum(f)
frac=sorted([(q[i]-f[i],i) for i in range(3)],reverse=True)
for i in range(int(remain)): f[frac[i][1]]+=1
return f
def main():
depth=int(get_ud(op,1,5)); size=float(get_ud(op,2,800)); seed=int(get_ud(op,5,1))
c1p=float(get_ud(op,6,33)); c2p=float(get_ud(op,7,33)); c3p=float(get_ud(op,8,34))
refresh=bool(get_ud(op,9,False));
if refresh: op[c4d.ID_USERDATA,9]=False; c4d.EventAdd()
rng=random.Random(seed)
rects=subdivide_area((-size/2,-size/2,size/2,size/2),depth,rng)
# 🔁 Force more cuts if too few
while len(rects)<30 and depth<10:
rects+=subdivide_area(random.choice(rects),depth,rng)
depth+=1
objs=[create_rect(*r) for r in rects]
combined=combine_objects(objs)
total=len(rects)
counts=distribute_counts(total,[c1p,c2p,c3p])
assign=[];
for i,c in enumerate(counts,start=1): assign+=[i]*c
rng.shuffle(assign)
sel={1:[],2:[],3:[]}
for i,c in enumerate(assign): sel[c].append(i)
print("\n--- MONDRIAN DEBUG ---")
print(f"Polygons={total}")
print(f"Target %: {c1p},{c2p},{c3p}")
print(f"Counts: {counts} Sum={sum(counts)}")
print(f"Selections: {[len(sel[1]),len(sel[2]),len(sel[3])]}")
print("----------------------\n")
for i,n in enumerate(["Color1","Color2","Color3"],start=1): make_selection(combined,sel[i],n)
combined.SetName("Mondrian_Geometry")
return combinedYou can download the scene file by clicking the link below:
Download “Modrian_Geometry_Python_Generator” Modrian_Geometry_Python_Generator.zip – Downloaded 0 times – 94.85 KB