summaryrefslogtreecommitdiff
path: root/geometry.py
blob: d36514178439e9d7666874d063b0d69b96547b33 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import numpy as np
from bvh import *

class Geometry(object):
    """
    Geometry object.
    """

    def __init__(self):
        self.materials = []
        self.mesh = np.empty(0)
        self.inside = np.empty(0)
        self.outside = np.empty(0)

    def add_mesh(self, mesh, inside, outside):
        """
        Add a triangle mesh.

        Args:
            - mesh: array of shape (n,3,3)
                Array of vertices for a closed mesh with n triangles.

            - inside: Material
                Material inside the mesh.

            - outside: Material
                Material outside the mesh.
         """

        if len(mesh.shape) != 3 or mesh.shape[1] != 3 or mesh.shape[2] != 3:
            raise Exception('shape mismatch')

        if inside not in self.materials:
            self.materials.append(inside)
        if outside not in self.materials:
            self.materials.append(outside)

        self.inside.resize(self.inside.size+mesh.shape[0])
        self.inside[-mesh.shape[0]:] = np.tile(self.materials.index(inside), mesh.shape[0])

        self.outside.resize(self.outside.size+mesh.shape[0])
        self.outside[-mesh.shape[0]:] = np.tile(self.materials.index(outside), mesh.shape[0])

        self.mesh.resize((self.mesh.shape[0]+mesh.shape[0],3,3))
        self.mesh[-mesh.shape[0]:] = mesh

    def build(self, bits=16):
        order, zvalues = morton_order(self.mesh, bits)


        zvalues = zvalues[order]
        self.mesh = self.mesh[order]
        self.inside = self.inside[order]
        self.outside = self.outside[order]

        leafs = []

        for z in sorted(set(zvalues)):
            mask = (zvalues == z)
            leafs.append(Leaf(self.mesh[mask], 3*np.where(mask)[0][0], z))

        layers = []
        layers.append(leafs)

        while True:
            zvalues = np.array([node.zvalue for node in layers[-1]])

            bit_shifted_zvalues = zvalues >> 1

            nodes = []
            for z in sorted(set(bit_shifted_zvalues)):
                mask = (bit_shifted_zvalues == z)
                nodes.append(Node(list(compress(layers[-1], mask)), z))

            layers.append(nodes)

            if len(nodes) == 1:
                break

        layers.reverse()

        nodes = []
        for layer in layers:
            for node in layer:
                nodes.append(node)


        self.lower_bound = np.empty((len(nodes),3))
        self.upper_bound = np.empty((len(nodes),3))
        self.child_map = np.empty(len(nodes))
        self.child_len = np.empty(len(nodes))
        self.first_leaf = -1

        for i, node in enumerate(nodes):
            self.lower_bound[i] = node.lower_bound
            self.upper_bound[i] = node.upper_bound
            
            self.child_len[i] = node.size

            if isinstance(node, Node):
                for j, child in enumerate(nodes):
                    if child is node.children[0]:
                        self.child_map[i] = j
                        break

            if isinstance(node, Leaf):
                self.child_map[i] = node.mesh_idx

                if self.first_leaf == -1:
                    self.first_leaf = i