- Reads CSV files containing `x, y, z, label` - Converts coordinates from feet to the current Blender scene units - Offsets large world coordinates near the origin for precision - Corrects axis orientation (Y flip + proper Z alignment) - Creates labeled empties for each survey point - Optionally filters out unwanted point types (e.g. buildings or utilities) - Generates a Delaunay-triangulated 3D mesh surface from the remaining points The result is a clean, unit-accurate terrain mesh built directly from raw survey data inside Blender.
59 lines
No EOL
1.7 KiB
Python
59 lines
No EOL
1.7 KiB
Python
import bpy
|
|
import csv
|
|
|
|
# Path to your CSV file
|
|
csv_path = r"D:\Dropbox\Gitea_OD\Utility_Apps\Blender\simple scripts\CSV Terrain Import for Blender\example.csv" # change this
|
|
|
|
# Name for the collection
|
|
collection_name = "CSV_Points"
|
|
|
|
# CSV units: feet
|
|
CSV_UNIT_TO_METERS = 0.3048
|
|
|
|
# Get Blender unit scale
|
|
scene = bpy.context.scene
|
|
unit_scale = scene.unit_settings.scale_length # e.g., 1.0 for meters, 0.3048 for feet
|
|
|
|
# Combined scale to convert CSV feet to Blender units
|
|
scale = CSV_UNIT_TO_METERS / unit_scale
|
|
|
|
# Create collection (or get it if it exists)
|
|
if collection_name in bpy.data.collections:
|
|
col = bpy.data.collections[collection_name]
|
|
else:
|
|
col = bpy.data.collections.new(collection_name)
|
|
bpy.context.scene.collection.children.link(col)
|
|
|
|
# Read CSV and collect data
|
|
points_data = []
|
|
xs, ys, zs = [], [], []
|
|
|
|
with open(csv_path, newline='') as csvfile:
|
|
reader = csv.DictReader(csvfile)
|
|
for row in reader:
|
|
x = float(row['x'])
|
|
y = float(row['y'])
|
|
z = float(row['z'])
|
|
label = row['label']
|
|
points_data.append((x, y, z, label))
|
|
xs.append(x)
|
|
ys.append(y)
|
|
zs.append(z)
|
|
|
|
# Compute offsets to bring mesh near origin
|
|
x_offset = min(xs)
|
|
y_offset = min(ys)
|
|
z_min = min(zs)
|
|
|
|
# Create empties
|
|
for x, y, z, label in points_data:
|
|
x_adj = (x - x_offset) * scale
|
|
y_adj = -(y - y_offset) * scale # flip Y
|
|
z_adj = (z - z_min) * scale
|
|
empty = bpy.data.objects.new(label, None)
|
|
empty.location = (x_adj, y_adj, z_adj)
|
|
col.objects.link(empty)
|
|
|
|
print(f"Created {len(points_data)} empties in collection '{collection_name}'")
|
|
print(f"Offsets: X -= {x_offset}, Y flipped & offset -= {y_offset}, Z -= {z_min}")
|
|
print(f"Applied scale to convert CSV feet to Blender units: {scale}") |