Untitled
unknown
plain_text
8 days ago
4.3 kB
2
Indexable
Never
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()
Leave a Comment