Last active
May 10, 2022 01:29
-
-
Save aidangannon/7904f998d9213cf2faf0b16b73d237e6 to your computer and use it in GitHub Desktop.
heuristic analysis of scene complexity
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
vector maths... yeah mr white, yeah science