-
Notifications
You must be signed in to change notification settings - Fork 8
/
orbit_camera.py
137 lines (114 loc) · 3.77 KB
/
orbit_camera.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
132
133
134
135
136
137
import numpy as np
import math
import torch
""" orbit camera model """
class OrbitCamera:
def __init__(self, pivot=[0,0,0], azimuth=0, elevation=60, zoom=400):
"""
Args:
pivot: initial obit center (in voxel grid coordinate system)
azimuth: initial azimuth
elevation: initial elevation
zoom: initial zoom in factor (in voxel grid coordinate system)
"""
self.pivot = torch.tensor(pivot,dtype=torch.float32)
self.azimuth = np.deg2rad(azimuth)
self.elevation = np.deg2rad(elevation)
self.radius = zoom
self.zoom_speed = 10.
self.pan_speed = 0.5
self.rot_speed = 0.017453292519444
self.rotating = False
self.panning = False
self.R = torch.zeros(3,3) # rotation matrix
self.C = torch.zeros(3,) # camera center
self.updateR()
self.updateC()
def updateR(self,):
""" update rotation matrix given current azimuth, elevation"""
sp = math.sin(self.azimuth)
cp = math.cos(self.azimuth)
st = math.sin(self.elevation)
ct = math.cos(self.elevation)
self.R[0,0] = cp
self.R[0,1] = -sp*ct
self.R[0,2] = sp*st
self.R[1,0] = sp
self.R[1,1] = ct*cp
self.R[1,2] = -st*cp
self.R[2,1] = st
self.R[2,2] = ct
def updateC(self,):
""" update camera center given current orbit center, zooming, and rotation"""
self.C = self.pivot + self.R[:,-1]*self.radius
def rotate(self,dx,dy):
"""
Args:
dx: horizontal shift of mouse (azimuth)
dy: vertical shift of mouse (elevation)
Assume left click
"""
self.azimuth -= dx
self.elevation += dy
sp = math.sin(self.azimuth)
cp = math.cos(self.azimuth)
st = math.sin(self.elevation)
ct = math.cos(self.elevation)
self.R[0,0] = cp
self.R[0,1] = -sp*ct
self.R[0,2] = sp*st
self.R[1,0] = sp
self.R[1,1] = ct*cp
self.R[1,2] = -st*cp
self.R[2,1] = st
self.R[2,2] = ct
self.updateC()
def translate(self,dx,dy):
"""
Args:
dx: horizontal shift of mouse (move camera plane horitontally)
dy: vertical shift of mouse (move camera plane vertically)
Assume right clik
"""
right,up = self.R[:,0],self.R[:,1]
self.pivot -= up*dy-right*dx
self.updateC()
def read_zoom(self,fac):
""" scroll of middle mouse to zoom (in/out) """
self.radius += fac
self.updateC()
def get_position(self):
'''
Return 3x1 tensor
'''
return -self.extrinsic[:3, :3].T @ self.extrinsic[:3, 3:]
def set_position(self, pos):
'''
Args:
pos: 3x1 tensor
'''
self.extrinsic[:3, 3:] = -self.R @ pos
position = property(get_position, set_position)
def rotate_start(self, x, y):
self.rotating = True
def rotate_end(self, x, y):
self.rotating = False
def pan_start(self, x, y):
self.panning = True
def pan_end(self, x, y):
self.panning = False
def zoom_in(self, x, y):
""" scroll up to zoom in"""
self.radius += self.zoom_speed
self.updateC()
def zoom_out(self, x, y):
""" scroll down to zoom out"""
self.radius -= self.zoom_speed
self.updateC()
def update(self, x, y, dx, dy):
if(self.panning):
# handle camea pan
self.translate(dx * self.pan_speed, dy * self.pan_speed)
if(self.rotating):
# handle camera rot
self.rotate(dx * self.rot_speed, dy * self.rot_speed)