# Copyright (C) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # # This work is made available under the Nvidia Source Code License-NC. # To view a copy of this license, check out LICENSE.md import numpy as np import torch class EvalCameraController: def __init__(self, voxel, maxstep=128, pattern=0, cam_ang=73, smooth_decay_multiplier=1.0): self.voxel = voxel self.maxstep = maxstep self.camera_poses = [] # ori, dir, up, f circle = torch.linspace(0, 2*np.pi, steps=maxstep) size = min(voxel.voxel_t.size(1), voxel.voxel_t.size(2)) / 2 # Shrink the circle a bit. shift = size * 0.2 size = size * 0.8 if pattern == 0: height_history = [] # Calculate smooth height. for i in range(maxstep): farpoint = torch.tensor([ 70, torch.sin(circle[i])*size + voxel.voxel_t.size(1)/2 + shift, torch.cos(circle[i])*size + voxel.voxel_t.size(2)/2 + shift]) height_history.append(self._get_height(farpoint[1], farpoint[2], farpoint[0])) # Filtfilt height_history = self.filtfilt(height_history, decay=0.2*smooth_decay_multiplier) for i in range(maxstep): farpoint = torch.tensor([ 70, torch.sin(circle[i])*size + voxel.voxel_t.size(1)/2 + shift, torch.cos(circle[i])*size + voxel.voxel_t.size(2)/2 + shift]) farpoint[0] = height_history[i] nearpoint = torch.tensor([ 60, torch.sin(circle[i]+0.5*np.pi)*size*0.5 + voxel.voxel_t.size(1)/2 + shift, torch.cos(circle[i]+0.5*np.pi)*size*0.5 + voxel.voxel_t.size(2)/2 + shift]) cam_ori = self.voxel.world2local(farpoint) cam_dir = self.voxel.world2local(nearpoint - farpoint, is_vec=True) cam_up = self.voxel.world2local(torch.tensor([1, 0, 0], dtype=torch.float32), is_vec=True) cam_f = 0.5/np.tan(np.deg2rad(cam_ang/2)) # about 24mm fov self.camera_poses.append((cam_ori, cam_dir, cam_up, cam_f)) elif pattern == 1: zoom = torch.linspace(1.0, 0.25, steps=maxstep) height_history = [] for i in range(maxstep): farpoint = torch.tensor([ 90, torch.sin(circle[i])*size + voxel.voxel_t.size(1)/2 + shift, torch.cos(circle[i])*size + voxel.voxel_t.size(2)/2 + shift]) height_history.append(self._get_height(farpoint[1], farpoint[2], farpoint[0])) height_history = self.filtfilt(height_history, decay=0.2*smooth_decay_multiplier) for i in range(maxstep): farpoint = torch.tensor([ 90, torch.sin(circle[i])*size + voxel.voxel_t.size(1)/2 + shift, torch.cos(circle[i])*size + voxel.voxel_t.size(2)/2 + shift]) farpoint[0] = height_history[i] nearpoint = torch.tensor([ 60, torch.sin(circle[i]-0.3*np.pi)*size*0.3 + voxel.voxel_t.size(1)/2 + shift, torch.cos(circle[i]-0.3*np.pi)*size*0.3 + voxel.voxel_t.size(2)/2 + shift]) cam_ori = self.voxel.world2local(farpoint) cam_dir = self.voxel.world2local(nearpoint - farpoint, is_vec=True) cam_up = self.voxel.world2local(torch.tensor([1, 0, 0], dtype=torch.float32), is_vec=True) cam_f = 0.5/np.tan(np.deg2rad(cam_ang/2)*zoom[i]) # about 24mm fov self.camera_poses.append((cam_ori, cam_dir, cam_up, cam_f)) elif pattern == 2: move = torch.linspace(1.0, 0.2, steps=maxstep) height_history = [] for i in range(maxstep): farpoint = torch.tensor([ 90, torch.sin(circle[i])*size*move[i] + voxel.voxel_t.size(1)/2 + shift, torch.cos(circle[i])*size*move[i] + voxel.voxel_t.size(2)/2 + shift]) height_history.append(self._get_height(farpoint[1], farpoint[2], farpoint[0])) height_history = self.filtfilt(height_history, decay=0.2*smooth_decay_multiplier) for i in range(maxstep): farpoint = torch.tensor([ 90, torch.sin(circle[i])*size*move[i] + voxel.voxel_t.size(1)/2 + shift, torch.cos(circle[i])*size*move[i] + voxel.voxel_t.size(2)/2 + shift]) farpoint[0] = height_history[i] nearpoint = torch.tensor([ 60, torch.sin(circle[i]+0.5*np.pi)*size*0.3*move[i] + voxel.voxel_t.size(1)/2 + shift, torch.cos(circle[i]+0.5*np.pi)*size*0.3*move[i] + voxel.voxel_t.size(2)/2 + shift]) cam_ori = self.voxel.world2local(farpoint) cam_dir = self.voxel.world2local(nearpoint - farpoint, is_vec=True) cam_up = self.voxel.world2local(torch.tensor([1, 0, 0], dtype=torch.float32), is_vec=True) cam_f = 0.5/np.tan(np.deg2rad(cam_ang/2)) # about 24mm fov self.camera_poses.append((cam_ori, cam_dir, cam_up, cam_f)) elif pattern == 3: move = torch.linspace(0.75, 0.2, steps=maxstep) height_history = [] for i in range(maxstep): farpoint = torch.tensor([ 70, torch.sin(-circle[i])*size*move[i] + voxel.voxel_t.size(1)/2 + shift, torch.cos(-circle[i])*size*move[i] + voxel.voxel_t.size(2)/2 + shift]) height_history.append(self._get_height(farpoint[1], farpoint[2], farpoint[0])) height_history = self.filtfilt(height_history, decay=0.2*smooth_decay_multiplier) for i in range(maxstep): farpoint = torch.tensor([ 70, torch.sin(-circle[i])*size*move[i] + voxel.voxel_t.size(1)/2 + shift, torch.cos(-circle[i])*size*move[i] + voxel.voxel_t.size(2)/2 + shift]) farpoint[0] = height_history[i] nearpoint = torch.tensor([ 60, torch.sin(-circle[i]-0.4*np.pi)*size*0.9*move[i] + voxel.voxel_t.size(1)/2 + shift, torch.cos(-circle[i]-0.4*np.pi)*size*0.9*move[i] + voxel.voxel_t.size(2)/2 + shift]) cam_ori = self.voxel.world2local(farpoint) cam_dir = self.voxel.world2local(nearpoint - farpoint, is_vec=True) cam_up = self.voxel.world2local(torch.tensor([1, 0, 0], dtype=torch.float32), is_vec=True) cam_f = 0.5/np.tan(np.deg2rad(cam_ang/2)) # about 24mm fov self.camera_poses.append((cam_ori, cam_dir, cam_up, cam_f)) elif pattern == 4: move = torch.linspace(1.0, 0.5, steps=maxstep) height_history = [] for i in range(maxstep): farpoint = torch.tensor([ 90, torch.sin(circle[i])*size*move[i] + voxel.voxel_t.size(1)/2 + shift, torch.cos(circle[i])*size*move[i] + voxel.voxel_t.size(2)/2 + shift]) height_history.append(self._get_height(farpoint[1], farpoint[2], farpoint[0])) height_history = self.filtfilt(height_history, decay=0.2*smooth_decay_multiplier) for i in range(maxstep): farpoint = torch.tensor([ 90, torch.sin(circle[i])*size*move[i] + voxel.voxel_t.size(1)/2 + shift, torch.cos(circle[i])*size*move[i] + voxel.voxel_t.size(2)/2 + shift]) farpoint[0] = height_history[i] nearpoint = torch.tensor([ 60, torch.sin(circle[i]+0.5*np.pi)*size*0.3*move[i] + voxel.voxel_t.size(1)/2 + shift, torch.cos(circle[i]+0.5*np.pi)*size*0.3*move[i] + voxel.voxel_t.size(2)/2 + shift]) cam_ori = self.voxel.world2local(farpoint) cam_dir = self.voxel.world2local(nearpoint - farpoint, is_vec=True) cam_up = self.voxel.world2local(torch.tensor([1, 0, 0], dtype=torch.float32), is_vec=True) cam_f = 0.5/np.tan(np.deg2rad(cam_ang/2)) # about 24mm fov self.camera_poses.append((cam_ori, cam_dir, cam_up, cam_f)) # look outward elif pattern == 5: move = torch.linspace(1.0, 0.5, steps=maxstep) height_history = [] for i in range(maxstep): nearpoint = torch.tensor([ 60, torch.sin(circle[i]+0.5*np.pi)*size*0.3*move[i] + voxel.voxel_t.size(1)/2 + shift, torch.cos(circle[i]+0.5*np.pi)*size*0.3*move[i] + voxel.voxel_t.size(2)/2 + shift]) height_history.append(self._get_height(nearpoint[1], nearpoint[2], nearpoint[0])) height_history = self.filtfilt(height_history, decay=0.2*smooth_decay_multiplier) for i in range(maxstep): nearpoint = torch.tensor([ 60, torch.sin(circle[i]+0.5*np.pi)*size*0.3*move[i] + voxel.voxel_t.size(1)/2 + shift, torch.cos(circle[i]+0.5*np.pi)*size*0.3*move[i] + voxel.voxel_t.size(2)/2 + shift]) nearpoint[0] = height_history[i] farpoint = torch.tensor([ 60, torch.sin(circle[i])*size*move[i] + voxel.voxel_t.size(1)/2 + shift, torch.cos(circle[i])*size*move[i] + voxel.voxel_t.size(2)/2 + shift]) cam_ori = self.voxel.world2local(nearpoint) cam_dir = self.voxel.world2local(farpoint - nearpoint, is_vec=True) cam_up = self.voxel.world2local(torch.tensor([1, 0, 0], dtype=torch.float32), is_vec=True) cam_f = 0.5/np.tan(np.deg2rad(cam_ang/2)) # about 24mm fov self.camera_poses.append((cam_ori, cam_dir, cam_up, cam_f)) # Rise elif pattern == 6: shift = 0 lift = torch.linspace(0.0, 200.0, steps=maxstep) zoom = torch.linspace(0.8, 1.6, steps=maxstep) for i in range(maxstep): farpoint = torch.tensor([ 80+lift[i], torch.sin(circle[i]/4)*size*0.2 + voxel.voxel_t.size(1)/2 + shift, torch.cos(circle[i]/4)*size*0.2 + voxel.voxel_t.size(2)/2 + shift]) farpoint[0] = self._get_height(farpoint[1], farpoint[2], farpoint[0]) nearpoint = torch.tensor([ 65, torch.sin(circle[i]/4+0.5*np.pi)*size*0.1 + voxel.voxel_t.size(1)/2 + shift, torch.cos(circle[i]/4+0.5*np.pi)*size*0.1 + voxel.voxel_t.size(2)/2 + shift]) cam_ori = self.voxel.world2local(farpoint) cam_dir = self.voxel.world2local(nearpoint - farpoint, is_vec=True) cam_up = self.voxel.world2local(torch.tensor([1, 0, 0], dtype=torch.float32), is_vec=True) cam_f = 0.5/np.tan(np.deg2rad(73/2)*zoom[i]) # about 24mm fov self.camera_poses.append((cam_ori, cam_dir, cam_up, cam_f)) # 45deg elif pattern == 7: rad = torch.tensor([np.deg2rad(45).astype(np.float32)]) size = 1536 for i in range(maxstep): farpoint = torch.tensor([ 61+size, torch.sin(rad)*size + voxel.voxel_t.size(1)/2, torch.cos(rad)*size + voxel.voxel_t.size(2)/2]) nearpoint = torch.tensor([ 61, voxel.voxel_t.size(1)/2, voxel.voxel_t.size(2)/2]) cam_ori = self.voxel.world2local(farpoint) cam_dir = self.voxel.world2local(nearpoint - farpoint, is_vec=True) cam_up = self.voxel.world2local(torch.tensor([1, 0, 0], dtype=torch.float32), is_vec=True) cam_f = 0.5/np.tan(np.deg2rad(19.5/2)) # about 50mm fov self.camera_poses.append((cam_ori, cam_dir, cam_up, cam_f)) def _get_height(self, loc0, loc1, minheight): loc0 = int(loc0) loc1 = int(loc1) height = minheight for dx in range(-3, 4): for dy in range(-3, 4): if (loc0+dx) < 0 or (loc0+dx) >= self.voxel.heightmap.shape[0] or (loc1+dy) < 0 or \ (loc1+dy) >= self.voxel.heightmap.shape[1]: height = max(height, minheight) else: height = max(height, self.voxel.heightmap[loc0+dx, loc1+dy] + 2) return height def filtfilt(self, height_history, decay=0.2): # Filtfilt height_history2 = [] maxstep = len(height_history) prev_height = height_history[0] for i in range(maxstep): prev_height = prev_height - decay if prev_height < height_history[i]: prev_height = height_history[i] height_history2.append(prev_height) prev_height = height_history[-1] for i in range(maxstep-1, -1, -1): prev_height = prev_height - decay if prev_height < height_history[i]: prev_height = height_history[i] height_history2[i] = max(prev_height, height_history2[i]) return height_history2 def __len__(self): return len(self.camera_poses) def __getitem__(self, idx): return self.camera_poses[idx] class TourCameraController: def __init__(self, voxel, maxstep=128): self.voxel = voxel self.maxstep = maxstep self.camera_poses = [] # ori, dir, up, f circle = torch.linspace(0, 2*np.pi, steps=maxstep//4) size = min(voxel.voxel_t.size(1), voxel.voxel_t.size(2)) / 2 # Shrink the circle a bit shift = size * 0.2 size = size * 0.8 for i in range(maxstep//4): farpoint = torch.tensor([ 70, torch.sin(circle[i])*size + voxel.voxel_t.size(1)/2 + shift, torch.cos(circle[i])*size + voxel.voxel_t.size(2)/2 + shift]) farpoint[0] = self._get_height(farpoint[1], farpoint[2], farpoint[0]) nearpoint = torch.tensor([ 60, torch.sin(circle[i]+0.5*np.pi)*size*0.5 + voxel.voxel_t.size(1)/2 + shift, torch.cos(circle[i]+0.5*np.pi)*size*0.5 + voxel.voxel_t.size(2)/2 + shift]) cam_ori = self.voxel.world2local(farpoint) cam_dir = self.voxel.world2local(nearpoint - farpoint, is_vec=True) cam_up = self.voxel.world2local(torch.tensor([1, 0, 0], dtype=torch.float32), is_vec=True) cam_f = 0.5/np.tan(np.deg2rad(73/2)) # about 24mm fov self.camera_poses.append((cam_ori, cam_dir, cam_up, cam_f)) zoom = torch.linspace(1.0, 0.25, steps=maxstep//4) for i in range(maxstep//4): farpoint = torch.tensor([ 90, torch.sin(circle[i])*size + voxel.voxel_t.size(1)/2 + shift, torch.cos(circle[i])*size + voxel.voxel_t.size(2)/2 + shift]) farpoint[0] = self._get_height(farpoint[1], farpoint[2], farpoint[0]) nearpoint = torch.tensor([ 60, torch.sin(circle[i]-0.3*np.pi)*size*0.3 + voxel.voxel_t.size(1)/2 + shift, torch.cos(circle[i]-0.3*np.pi)*size*0.3 + voxel.voxel_t.size(2)/2 + shift]) cam_ori = self.voxel.world2local(farpoint) cam_dir = self.voxel.world2local(nearpoint - farpoint, is_vec=True) cam_up = self.voxel.world2local(torch.tensor([1, 0, 0], dtype=torch.float32), is_vec=True) cam_f = 0.5/np.tan(np.deg2rad(73/2)*zoom[i]) # about 24mm fov self.camera_poses.append((cam_ori, cam_dir, cam_up, cam_f)) move = torch.linspace(1.0, 0.2, steps=maxstep//4) for i in range(maxstep//4): farpoint = torch.tensor([ 90, torch.sin(circle[i])*size*move[i] + voxel.voxel_t.size(1)/2 + shift, torch.cos(circle[i])*size*move[i] + voxel.voxel_t.size(2)/2 + shift]) farpoint[0] = self._get_height(farpoint[1], farpoint[2], farpoint[0]) nearpoint = torch.tensor([ 60, torch.sin(circle[i]+0.5*np.pi)*size*0.3*move[i] + voxel.voxel_t.size(1)/2 + shift, torch.cos(circle[i]+0.5*np.pi)*size*0.3*move[i] + voxel.voxel_t.size(2)/2 + shift]) cam_ori = self.voxel.world2local(farpoint) cam_dir = self.voxel.world2local(nearpoint - farpoint, is_vec=True) cam_up = self.voxel.world2local(torch.tensor([1, 0, 0], dtype=torch.float32), is_vec=True) cam_f = 0.5/np.tan(np.deg2rad(73/2)) # about 24mm fov self.camera_poses.append((cam_ori, cam_dir, cam_up, cam_f)) lift = torch.linspace(0.0, 200.0, steps=maxstep//4) zoom = torch.linspace(0.6, 1.2, steps=maxstep//4) for i in range(maxstep//4): farpoint = torch.tensor([ 80+lift[i], torch.sin(circle[i])*size*0.2 + voxel.voxel_t.size(1)/2 + shift, torch.cos(circle[i])*size*0.2 + voxel.voxel_t.size(2)/2 + shift]) farpoint[0] = self._get_height(farpoint[1], farpoint[2], farpoint[0]) nearpoint = torch.tensor([ 60, torch.sin(circle[i]+0.5*np.pi)*size*0.1 + voxel.voxel_t.size(1)/2 + shift, torch.cos(circle[i]+0.5*np.pi)*size*0.1 + voxel.voxel_t.size(2)/2 + shift]) cam_ori = self.voxel.world2local(farpoint) cam_dir = self.voxel.world2local(nearpoint - farpoint, is_vec=True) cam_up = self.voxel.world2local(torch.tensor([1, 0, 0], dtype=torch.float32), is_vec=True) cam_f = 0.5/np.tan(np.deg2rad(73/2)*zoom[i]) # about 24mm fov self.camera_poses.append((cam_ori, cam_dir, cam_up, cam_f)) def _get_height(self, loc0, loc1, minheight): loc0 = int(loc0) loc1 = int(loc1) height = minheight for dx in range(-3, 4): for dy in range(-3, 4): if (loc0+dx) < 0 or (loc0+dx) >= self.voxel.heightmap.shape[0] or (loc1+dy) < 0 or \ (loc1+dy) >= self.voxel.heightmap.shape[1]: height = max(height, minheight) else: height = max(height, self.voxel.heightmap[loc0+dx, loc1+dy] + 2) return height def __len__(self): return len(self.camera_poses) def __getitem__(self, idx): return self.camera_poses[idx] def rand_camera_pose_birdseye(voxel, border=128): r"""Generating random camera pose in the upper hemisphere, in the format of origin-direction-up Assuming [Y X Z] coordinate. Y is negative gravity direction. The camera pose is converted into the voxel coordinate system so that it can be used directly for rendering 1. Uniformly sample a point on the upper hemisphere of a unit sphere, as cam_ori. 2. Set cam_dir to be from cam_ori to the origin 3. cam_up is always pointing towards sky 4. move cam_ori to random place according to voxel size """ cam_dir = torch.randn(3, dtype=torch.float32) cam_dir = cam_dir / torch.sqrt(torch.sum(cam_dir*cam_dir)) cam_dir[0] = -torch.abs(cam_dir[0]) cam_up = torch.tensor([1, 0, 0], dtype=torch.float32) # generate camera lookat target r = np.random.rand(2) r[0] *= voxel.voxel_t.size(1)-border-border r[1] *= voxel.voxel_t.size(2)-border-border r = r + border y = voxel.heightmap[int(r[0]+0.5), int(r[1]+0.5)] + (np.random.rand(1)-0.5) * 5 cam_target = torch.tensor([y, r[0], r[1]], dtype=torch.float32) cam_ori = cam_target - cam_dir * (np.random.rand(1).item() * 100) cam_ori[0] = max(voxel.heightmap[int(cam_ori[1]+0.5), int(cam_ori[2]+0.5)]+2, cam_ori[0]) # Translate to voxel coordinate cam_ori = voxel.world2local(cam_ori) cam_dir = voxel.world2local(cam_dir, is_vec=True) cam_up = voxel.world2local(cam_up, is_vec=True) return cam_ori, cam_dir, cam_up def get_neighbor_height(heightmap, loc0, loc1, minheight, neighbor_size=7): loc0 = int(loc0) loc1 = int(loc1) height = 0 for dx in range(-neighbor_size//2, neighbor_size//2+1): for dy in range(-neighbor_size//2, neighbor_size//2+1): if (loc0+dx) < 0 or (loc0+dx) >= heightmap.shape[0] or (loc1+dy) < 0 or (loc1+dy) >= heightmap.shape[1]: height = max(height, minheight) else: height = max(minheight, heightmap[loc0+dx, loc1+dy] + 2) return height def rand_camera_pose_firstperson(voxel, border=128): r"""Generating random camera pose in the upper hemisphere, in the format of origin-direction-up """ r = np.random.rand(5) r[0] *= voxel.voxel_t.size(1)-border-border r[1] *= voxel.voxel_t.size(2)-border-border r[0] = r[0] + border r[1] = r[1] + border y = get_neighbor_height(voxel.heightmap, r[0], r[1], 0) + np.random.rand(1) * 15 cam_ori = torch.tensor([y, r[0], r[1]], dtype=torch.float32) rand_ang_h = r[2] * 2 * np.pi cam_target = torch.tensor([0, cam_ori[1]+np.sin(rand_ang_h)*border*r[4], cam_ori[2] + np.cos(rand_ang_h)*border*r[4]], dtype=torch.float32) cam_target[0] = get_neighbor_height(voxel.heightmap, cam_target[1], cam_target[2], 0, neighbor_size=1) - 2 + r[3] * 10 cam_dir = cam_target - cam_ori cam_up = torch.tensor([1, 0, 0], dtype=torch.float32) cam_ori = voxel.world2local(cam_ori) cam_dir = voxel.world2local(cam_dir, is_vec=True) cam_up = voxel.world2local(cam_up, is_vec=True) return cam_ori, cam_dir, cam_up def rand_camera_pose_thridperson(voxel, border=96): r = torch.rand(2) r[0] *= voxel.voxel_t.size(1) r[1] *= voxel.voxel_t.size(2) rand_height = 60 + torch.rand(1) * 40 rand_height = get_neighbor_height(voxel.heightmap, r[0], r[1], rand_height, neighbor_size=5) farpoint = torch.tensor([rand_height, r[0], r[1]], dtype=torch.float32) r = torch.rand(2) r[0] *= voxel.voxel_t.size(1) - border - border r[1] *= voxel.voxel_t.size(2) - border - border r[0] = r[0] + border r[1] = r[1] + border rand_height = get_neighbor_height(voxel.heightmap, r[0], r[1], 65, neighbor_size=1) - 5 nearpoint = torch.tensor([rand_height, r[0], r[1]], dtype=torch.float32) cam_ori = voxel.world2local(farpoint) cam_dir = voxel.world2local(nearpoint - farpoint, is_vec=True) cam_up = voxel.world2local(torch.tensor([1, 0, 0], dtype=torch.float32), is_vec=True) return cam_ori, cam_dir, cam_up def rand_camera_pose_thridperson2(voxel, border=48): r = torch.rand(2) r[0] *= voxel.voxel_t.size(1) - border - border r[1] *= voxel.voxel_t.size(2) - border - border r[0] = r[0] + border r[1] = r[1] + border rand_height = 60 + torch.rand(1) * 40 rand_height = get_neighbor_height(voxel.heightmap, r[0], r[1], rand_height, neighbor_size=5) farpoint = torch.tensor([rand_height, r[0], r[1]], dtype=torch.float32) r = torch.rand(2) r[0] *= voxel.voxel_t.size(1) - border - border r[1] *= voxel.voxel_t.size(2) - border - border r[0] = r[0] + border r[1] = r[1] + border rand_height = get_neighbor_height(voxel.heightmap, r[0], r[1], 65, neighbor_size=1) - 5 nearpoint = torch.tensor([rand_height, r[0], r[1]], dtype=torch.float32) # Random Up vector (tilt a little bit) # up = torch.randn(3) * 0.05 # cutoff +-0.1, Tan(10deg) = 0.176 up = torch.randn(3) * 0.02 up[0] = 1.0 up = up / up.norm(p=2) cam_ori = voxel.world2local(farpoint) cam_dir = voxel.world2local(nearpoint - farpoint, is_vec=True) cam_up = voxel.world2local(up, is_vec=True) return cam_ori, cam_dir, cam_up def rand_camera_pose_thridperson3(voxel, border=64): r"""Attempting to solve the camera too close to wall problem and the lack of aerial poses.""" r = torch.rand(2) r[0] *= voxel.voxel_t.size(1) - border - border r[1] *= voxel.voxel_t.size(2) - border - border r[0] = r[0] + border r[1] = r[1] + border rand_height = 60 + torch.rand(1) * 40 if torch.rand(1) > 0.8: rand_height = 60 + torch.rand(1) * 60 rand_height = get_neighbor_height(voxel.heightmap, r[0], r[1], rand_height, neighbor_size=7) farpoint = torch.tensor([rand_height, r[0], r[1]], dtype=torch.float32) r = torch.rand(2) r[0] *= voxel.voxel_t.size(1) - border - border r[1] *= voxel.voxel_t.size(2) - border - border r[0] = r[0] + border r[1] = r[1] + border rand_height = get_neighbor_height(voxel.heightmap, r[0], r[1], 65, neighbor_size=3) - 5 nearpoint = torch.tensor([rand_height, r[0], r[1]], dtype=torch.float32) # Random Up vector (tilt a little bit) # up = torch.randn(3) * 0.05 # cutoff +-0.1, Tan(10deg) = 0.176 up = torch.randn(3) * 0.02 up[0] = 1.0 up = up / up.norm(p=2) # print(up) cam_ori = voxel.world2local(farpoint) cam_dir = voxel.world2local(nearpoint - farpoint, is_vec=True) cam_up = voxel.world2local(up, is_vec=True) return cam_ori, cam_dir, cam_up def rand_camera_pose_tour(voxel): size = min(voxel.voxel_t.size(1), voxel.voxel_t.size(2)) / 2 center = [voxel.voxel_t.size(1)/2, voxel.voxel_t.size(2)/2] rnd = torch.rand(8) rnd_deg = torch.rand(1) * 2 * np.pi far_radius = rnd[0]*0.8+0.2 far_height = rnd[1]*30 + 60 farpoint = torch.tensor([ far_height, torch.sin(rnd_deg)*size*far_radius + center[0], torch.cos(rnd_deg)*size*far_radius + center[1]]) farpoint[0] = get_neighbor_height(voxel.heightmap, farpoint[1], farpoint[2], farpoint[0], neighbor_size=7) near_radius = far_radius * rnd[2] near_shift_rad = np.pi*(rnd[3]-0.5) near_height = 60 + rnd[4] * 10 nearpoint = torch.tensor([ near_height, torch.sin(rnd_deg+near_shift_rad)*size*near_radius + center[0], torch.cos(rnd_deg+near_shift_rad)*size*near_radius + center[1]]) # Random Up vector (tilt a little bit) # up = torch.randn(3) * 0.05 # cutoff +-0.1, Tan(10deg) = 0.176 up = torch.randn(3) * 0.02 up[0] = 1.0 up = up / up.norm(p=2) cam_ori = voxel.world2local(farpoint) cam_dir = voxel.world2local(nearpoint - farpoint, is_vec=True) cam_up = voxel.world2local(up, is_vec=True) cam_f = 0.5/np.tan(np.deg2rad(73/2)*(rnd[5]*0.75+0.25)) # about 24mm fov return cam_ori, cam_dir, cam_up, cam_f # Look from center to outward def rand_camera_pose_insideout(voxel): size = min(voxel.voxel_t.size(1), voxel.voxel_t.size(2)) / 2 center = [voxel.voxel_t.size(1)/2, voxel.voxel_t.size(2)/2] rnd = torch.rand(8) rnd_deg = torch.rand(1) * 2 * np.pi far_radius = rnd[0]*0.8+0.2 far_height = rnd[1]*10 + 60 farpoint = torch.tensor([ far_height, torch.sin(rnd_deg)*size*far_radius + center[0], torch.cos(rnd_deg)*size*far_radius + center[1]]) near_radius = far_radius * rnd[2] near_shift_rad = np.pi*(rnd[3]-0.5) near_height = 60 + rnd[4] * 30 nearpoint = torch.tensor([ near_height, torch.sin(rnd_deg+near_shift_rad)*size*near_radius + center[0], torch.cos(rnd_deg+near_shift_rad)*size*near_radius + center[1]]) nearpoint[0] = get_neighbor_height(voxel.heightmap, nearpoint[1], nearpoint[2], nearpoint[0], neighbor_size=7) # Random Up vector (tilt a little bit) # up = torch.randn(3) * 0.05 # cutoff +-0.1, Tan(10deg) = 0.176 up = torch.randn(3) * 0.02 up[0] = 1.0 up = up / up.norm(p=2) cam_ori = voxel.world2local(nearpoint) cam_dir = voxel.world2local(farpoint-nearpoint, is_vec=True) cam_up = voxel.world2local(up, is_vec=True) cam_f = 0.5/np.tan(np.deg2rad(73/2)*(rnd[5]*0.75+0.25)) # about 24mm fov return cam_ori, cam_dir, cam_up, cam_f