-
Notifications
You must be signed in to change notification settings - Fork 3
/
scene.py
131 lines (103 loc) · 4 KB
/
scene.py
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import numpy
import cache
import open3dhub
def sirikata_bounds(boundsInfo):
minpt, maxpt = boundsInfo['bounds']
minpt, maxpt = numpy.copy(minpt), numpy.copy(maxpt)
center = boundsInfo['center']
center_distance = boundsInfo['center_farthest_distance']
# center the bounding box
minpt -= center
maxpt -= center
# bounding box is scaled by 1 / (distance from center to farthest point)
minpt /= center_distance
maxpt /= center_distance
return (minpt, maxpt)
def height_offset(boundsInfo):
minpt, maxpt = sirikata_bounds(boundsInfo)
height_range = (maxpt[2] - minpt[2])
return height_range / 2.0
def mapgen_coords_to_sirikata(loc, terrain):
# mapgen starts at 0,0,0 as the corner, but terrain gets centered at 0,0,0
loc = loc - terrain.center
# scale the coordinates to the scaled coordinates of the terrain mesh
loc /= terrain.boundsInfo['center_farthest_distance']
# then scale back by the terrain's scale
loc *= terrain.scale
# adjust the height by how much the terrain is offset
loc[2] += height_offset(terrain.boundsInfo) * terrain.scale
return loc
class SceneModel(object):
def __init__(self, path, x, y, z, scale, model_type,
orient_x=0, orient_y=0, orient_z=0, orient_w=1):
self.path = path
self.x = x
self.y = y
self.z = z
self.scale = scale
self.model_type = model_type
self.orient_x = orient_x
self.orient_y = orient_y
self.orient_z = orient_z
self.orient_w = orient_w
self._metadata = None
self._mesh = None
self._boundsInfo = None
def _load_mesh(self):
if self._mesh is None:
self._metadata, self._mesh = open3dhub.path_to_mesh(self.path, cache=True)
def _get_mesh(self):
self._load_mesh()
return self._mesh
mesh = property(_get_mesh)
def _get_metadata(self):
if self._metadata is None:
self._metadata = cache.get_metadata(self.path)
return self._metadata
metadata = property(_get_metadata)
def _get_bounds_info(self):
if self._boundsInfo is None:
self._boundsInfo = cache.get_bounds(self.path)
return self._boundsInfo
boundsInfo = property(_get_bounds_info)
center = property(lambda s: s.boundsInfo['center'])
v3 = property(lambda s: numpy.array([s.x, s.y, s.z], dtype=numpy.float32))
sirikata_uri = property(lambda s: 'meerkat:///' +
s.metadata['basepath'] + '/' +
'optimized' + '/' +
s.metadata['version'] + '/' +
s.metadata['basename'])
def to_json(self):
z = self.z + height_offset(self.boundsInfo) * self.scale
# below swaps from z-up to y-up
return {
'path': self.path,
'sirikata_uri': self.sirikata_uri,
'x': self.x,
'y': z,
'z': -1.0 * self.y,
'orient_x': self.orient_x,
'orient_y': self.orient_z,
'orient_z': -1.0 * self.orient_y,
'orient_w': self.orient_w,
'scale': self.scale,
'type': self.model_type,
}
def __str__(self):
return '<SceneModel %s <%.7g,%.7g,%.7g> %.7g>' % \
(self.path, self.x, self.y, self.z, self.scale)
def __repr__(self):
return str(self)
@staticmethod
def from_json(j):
m = SceneModel(j['path'],
j['x'],
-1.0 * j['z'],
j['y'],
j['scale'],
j['type'],
orient_x=j['orient_x'],
orient_y=-1.0 * j['orient_z'],
orient_z=j['orient_y'],
orient_w=j['orient_w'])
return m