Skip to content

Instantly share code, notes, and snippets.

@aidangannon
Last active May 10, 2022 01:29
Show Gist options
  • Save aidangannon/7904f998d9213cf2faf0b16b73d237e6 to your computer and use it in GitHub Desktop.
Save aidangannon/7904f998d9213cf2faf0b16b73d237e6 to your computer and use it in GitHub Desktop.
heuristic analysis of scene complexity
import string
from datetime import datetime
from typing import Callable
import bpy
from bpy.types import Object
from mathutils import Vector
VECTOR_LENGTH = 5
class CodeContract:
def __init__(self,
predicate: Callable[[], bool],
msg: string):
self.__predicate = predicate
self.__msg = msg
def evaluate(self):
if not self.__predicate():
raise AssertionError(self.__msg)
def cast_ray(direction):
cast_result = bpy.context.scene.ray_cast(view_layer=bpy.context.view_layer,
origin=Vector(seq=(0, 0, 0)),
direction=direction,
distance=100)
return cast_result[0]
def get_unit_normal_of_plane(p0: Vector,
p1: Vector,
p2: Vector):
"""
gets normal of plane such that p1 is a point that meets directly to p0 and p2
"""
p0_p1 = p0 - p1
p2_p1 = p2 - p1
normal = p0_p1.cross(p2_p1)
normal.normalize()
return normal
def get_vector_of_ray_intersection(vertex_on_plane: Vector,
normal_unit_vector_of_plane: Vector,
direction_unit_vector_of_ray: Vector):
distance = vertex_on_plane.dot(normal_unit_vector_of_plane)
return direction_unit_vector_of_ray * distance
def get_edge_normal_vector(normal_unit_vector_of_plane: Vector,
point_1: Vector,
point_2: Vector):
return normal_unit_vector_of_plane.cross(point_1 - point_2)
def is_position_not_over_edge(edge_normal_vector: Vector,
point: Vector,
ray_intersection: Vector):
return edge_normal_vector.dot(ray_intersection - point) >= 0
def do_three_dimensional(callback, length):
for i in range(0, length):
for j in range(0, length):
for k in range(0, length):
callback(i, j, k)
def vector_do_not_append_if_zero(i, j, k, vectors):
if not (i is 0 and j is 0 and k is 0):
vectors.append(Vector((i, j, k)))
def generate_vectors():
vectors = []
do_three_dimensional(callback=lambda i, j, k: vector_do_not_append_if_zero(i, j, k, vectors), length=VECTOR_LENGTH)
do_three_dimensional(callback=lambda i, j, k: vector_do_not_append_if_zero(-i, -j, -k, vectors),
length=VECTOR_LENGTH)
return vectors
def blender_ray_trace():
vectors = generate_vectors()
start_time = datetime.now()
ray_hits = 0
ray_did_hits = 0
for vector in vectors:
# print(f"vector {vector[0]} {vector[1]} {vector[2]}", end="")
did_ray_hit = cast_ray(direction=vector)
# print(f"did ray hit {did_ray_hit}")
ray_hits = ray_hits + 1
if did_ray_hit:
ray_did_hits = ray_did_hits + 1
print(datetime.now() - start_time)
print(ray_did_hits / ray_hits)
def get_all_vertex_coorinates(object):
coordinates = []
for polygon in object.data.polygons:
for vertex_index in polygon.vertices:
co = bpy.context.object.data.vertices[vertex_index].co
CodeContract(lambda: len(co) == 3, "all polygons must be triangulated").evaluate()
# print(f"{round(co[0], 2)} {round(co[1], 2)} {round(co[2], 2)}", end=" \t")
coordinates.append(co)
# print("=======")
return list(map(lambda x: Vector((x[0], x[1], x[2])), coordinates))
def get_vertex_coorinates_for_face(polygon, _object, matrix_world):
coordinates = []
for vertex_index in polygon.vertices:
co = matrix_world @ _object.vertices[vertex_index].co
CodeContract(lambda: len(co) == 3, "all polygons must be triangulated").evaluate()
print(f"{round(co[0], 2)} {round(co[1], 2)} {round(co[2], 2)}", end=" \t")
coordinates.append(co)
# print("=======")
return list(map(lambda x: Vector((x[0], x[1], x[2])), coordinates))
def get_current_scene_objects():
return list(filter(lambda x: x.type == "MESH", bpy.context.scene.objects))
def get_polygons(object):
return object.data.polygons
def normalize_vectors(vectors):
list(map(lambda x: x.normalize(), vectors))
return vectors
print("begin")
vector = Vector((2, 5, -10))
vector.normalize()
object_without_data = get_current_scene_objects()[0]
_object = object_without_data.data
coordinates = get_vertex_coorinates_for_face(polygon=_object.polygons[0],
_object=_object,
matrix_world=object_without_data.matrix_world)
unit_normal_of_plane = get_unit_normal_of_plane(p0=coordinates[0],
p1=coordinates[1],
p2=coordinates[2])
vector_of_ray_intersection = get_vector_of_ray_intersection(vertex_on_plane=coordinates[0],
normal_unit_vector_of_plane=unit_normal_of_plane,
direction_unit_vector_of_ray=vector)
vector_of_ray_intersection_2 = get_vector_of_ray_intersection(vertex_on_plane=coordinates[0],
normal_unit_vector_of_plane=unit_normal_of_plane,
direction_unit_vector_of_ray=vector)
vector_of_ray_intersection_3 = get_vector_of_ray_intersection(vertex_on_plane=coordinates[0],
normal_unit_vector_of_plane=unit_normal_of_plane,
direction_unit_vector_of_ray=vector)
CodeContract(
predicate=lambda: vector_of_ray_intersection_3 == vector_of_ray_intersection_2 == vector_of_ray_intersection,
msg="vector ray intersection miscalculation").evaluate()
edge_normal_1 = get_edge_normal_vector(point_1=coordinates[0],
point_2=coordinates[1],
normal_unit_vector_of_plane=unit_normal_of_plane)
edge_normal_2 = get_edge_normal_vector(point_1=coordinates[1],
point_2=coordinates[2],
normal_unit_vector_of_plane=unit_normal_of_plane)
edge_normal_3 = get_edge_normal_vector(point_1=coordinates[2],
point_2=coordinates[0],
normal_unit_vector_of_plane=unit_normal_of_plane)
is_over_1 = is_position_not_over_edge(edge_normal_vector=edge_normal_1,
point=coordinates[0],
ray_intersection=vector_of_ray_intersection)
is_over_2 = is_position_not_over_edge(edge_normal_vector=edge_normal_2,
point=coordinates[1],
ray_intersection=vector_of_ray_intersection)
is_over_3 = is_position_not_over_edge(edge_normal_vector=edge_normal_3,
point=coordinates[2],
ray_intersection=vector_of_ray_intersection)
print(is_over_1 and is_over_2 and is_over_3)
print()
# ray_trace()
# get_vertex_coorinates()
@aidangannon
Copy link
Author

vector maths... yeah mr white, yeah science

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment