import math import struct try: from .vec_math import Vector3, Quaternion, Aabb, Triangle from .util import Data except: from vec_math import Vector3, Quaternion, Aabb, Triangle from util import Data #PolyGrid is an octree where the leaf nodes contain a list of all triangles that intersect that leaf node. #Each node on a PolyGrid is a PolyCell. #POLYGRID_EPSILON exapnds the cube of a PolyCell for purposes of finding a triangle collision. POLYGRID_EPSILON_MAX = 0.1 #Amount to expand the max corner of the AABB. POLYGRID_EPSILON_MIN = 0.0 #Amount to expand the min corner of the AABB. POLYGRID_MINIMUM_SIZE = 1 class PolyCell: def __init__(self): self.children = None self.tri_idxs = [] self.tri_count = 0 self.position = [0, 0, 0] self.width = 0 def decode(self, data, offset): (children_offset, tri_idxs_offset, self.tri_count) = struct.unpack("> 1) & 0x1] z = (0, halfwidth)[(i >> 2) & 0x1] p = pos + Vector3(x, y, z) cell = PolyCell() if cell.rebuild(min_width, tris, p, halfwidth): #Child cell has triangles store in its branch, store it. self.children[i] = cell return True def encode(self, data): data.seekEnd() offset = data.tell() o = offset + 12 if len(self.tri_idxs) > 0: to = o o += len(self.tri_idxs) * struct.calcsize(" 0: data.encode("<" + "H" * len(self.tri_idxs), *self.tri_idxs) if self.children is not None: data.encode(" 2000: min_width = 1024 elif radius > 1000: min_width = 256 elif radius > 500: min_width = 128 else: min_width = 64 self.width = max(sz[0], sz[1], sz[2]) self.width = 2.0 ** math.ceil(math.log(self.width, 2.0)) self.width = max(1.0, self.width) self.bits = int(math.floor(math.log(self.width, 2) + 0.5)) self.cell = PolyCell() self.cell.rebuild(min_width, tris, self.position, self.width) if not self.check(): print(self.model.name) print(repr(tris)) self.dump() def encode(self): #Reconstruct the cell tree. self.rebuild() assert(self.check()) #Encode data self.data = Data() o = self.cell.encode(self.data) self.grid_header = (0, self.position[0], self.position[1], self.position[2], self.width, 1.0 / self.width, 0, self.bits) return self.data.data def check(self): """Checks that all triangles in the model are in at least of the nodes of the tree.""" used_tris = [0] * len(self.model.tris) self.cell.collectTris(used_tris) for v in used_tris: if v <= 0: print(repr(used_tris)) return False return True def dump(self, indent = " "): print(indent + "position: %s width: %s" % (self.position, self.width)) if self.cell is not None: self.cell.dump(indent + " ")