Untitled
unknown
plain_text
a year ago
4.3 kB
11
Indexable
import bpy
import math
import csv
import os
from mathutils import Vector
from mathutils.bvhtree import BVHTree
def main():
# 1. Access the Active Mesh Object
obj = bpy.context.active_object
if obj is None:
print("Error: No active object selected.")
return
if obj.type != 'MESH':
print(f"Error: Active object '{obj.name}' is not a mesh.")
return
mesh = obj.data
# Ensure the mesh is up to date
mesh.calc_loop_triangles()
# 2. Define the Logical 250x250 Grid
GRID_SIZE = 250 # 250x250 grid
Z_SCALE = 250 # Z-axis scaling factor
# 3. Prepare for Ray Casting
# Build BVH Tree for efficient ray casting
try:
bvhtree = BVHTree.FromObject(obj, bpy.context.view_layer.depsgraph)
except Exception as e:
print(f"Error: Failed to create BVH Tree for object '{obj.name}'. Exception: {e}")
return
# 4. Determine Mesh Bounds in World Space
world_verts = [obj.matrix_world @ vertex.co for vertex in mesh.vertices]
min_x = min(vertex.x for vertex in world_verts)
max_x = max(vertex.x for vertex in world_verts)
min_y = min(vertex.y for vertex in world_verts)
max_y = max(vertex.y for vertex in world_verts)
min_z = min(vertex.z for vertex in world_verts)
max_z = max(vertex.z for vertex in world_verts)
range_x = max_x - min_x if max_x - min_x != 0 else 1
range_y = max_y - min_y if max_y - min_y != 0 else 1
range_z = max_z - min_z if max_z - min_z != 0 else 1
# 4.2 Define Grid Spacing
step_x = range_x / (GRID_SIZE - 1)
step_y = range_y / (GRID_SIZE - 1)
# 5. Initialize a 250x250 Two-Dimensional Array with default Z-value 0
terrain_array = [[0 for _ in range(GRID_SIZE)] for _ in range(GRID_SIZE)]
# 6. Perform Ray Casting for Each Grid Cell
print("Starting ray casting...")
for i in range(GRID_SIZE):
for j in range(GRID_SIZE):
# Calculate the (X, Y) position for this grid cell
x = min_x + j * step_x
y = min_y + i * step_y
origin = Vector((x, y, min_z - 10)) # Start well below the mesh
direction = Vector((0, 0, 1)) # Cast upwards along Z-axis
# Perform the ray cast
location, normal, index, distance = bvhtree.ray_cast(origin, direction)
if location:
# Calculate the Z-value from the intersection point
z = location.z
# Scale Z to fit within 0 to Z_SCALE
scaled_z = (z - min_z) / range_z * Z_SCALE
# Clamp to 0-Z_SCALE
scaled_z = max(0, min(Z_SCALE, scaled_z))
terrain_array[i][j] = scaled_z
else:
# If no intersection, assign default value (e.g., 0)
terrain_array[i][j] = 0
# Optional: Print progress every 25 rows
if (i+1) % 25 == 0:
print(f"Progress: {i+1}/{GRID_SIZE} rows processed.")
print("Ray casting completed.")
# 7. Output the 2D Array
# Option 1: Print to Console (Warning: Large Output)
# Uncomment the following lines if you want to print the array
# for row in terrain_array:
# print(row)
# Option 2: Export to CSV
# Define the output file path
output_dir = bpy.path.abspath("//") # Current Blender file directory
output_file = os.path.join(output_dir, "terrain_elevation.csv")
try:
with open(output_file, mode='w', newline='') as csv_file:
writer = csv.writer(csv_file)
for row in terrain_array:
writer.writerow(row)
print(f"Elevation data successfully exported to '{output_file}'.")
except Exception as e:
print(f"Error: Failed to write CSV file. {e}")
# Option 3: Return the Array for Further Processing
# Here, we'll store it in a custom scene property
bpy.context.scene["TerrainElevation"] = terrain_array
print("Elevation data stored in scene property 'TerrainElevation'.")
# Run the main function
if __name__ == "__main__":
main()
Editor is loading...
Leave a Comment