def init_origin(scene: Scene): """Origin object, construction cone, so user knows ARB is running.""" # TODO: migrate to shared-scene setting size = [0.2, 0.4, 0.2] scene.add_object(Cone( # 370mm x 370mm # 750mm object_id="arb-origin", material=Material( color=Color(255, 114, 33), transparent=True, opacity=0.5, shader="flat"), position=Position(0, size[1] / 2, 0), scale=Scale(size[0] / 2, size[1], size[2] / 2))) scene.add_object(Cone( object_id="arb-origin-hole", **{"material-extras": {"transparentOccluder": True}}, position=Position(0, size[1] - (size[1] / 2 / 15), 0), scale=Scale(size[0] / 15, size[1] / 10, size[2] / 15))) scene.add_object(Box( object_id="arb-origin-base", material=Material( color=Color(0, 0, 0), transparent=True, opacity=0.5, shader="flat"), position=Position(0, size[1] / 20, 0), scale=Scale(size[0], size[1] / 10, size[2])))
def temp_rot_marker(position, rotation): return Box(ttl=120, rotation=rotation, material=Material(color=Color(255, 255, 255)), position=position, scale=Scale(0.02, 0.01, 0.15), clickable=True)
def boxline(object_id, axis, direction, delim, suffix, start, end, line_width, move, color, parent): line_width = line_width / SCL_CLICK end = Position(x=(end.x - start.x) / SCL_CLICK, y=(end.y - start.y) / SCL_CLICK, z=(end.z - start.z) / SCL_CLICK) if start.y == end.y and start.z == end.z: scale = Scale(x=abs(start.x - end.x), y=line_width, z=line_width) elif start.x == end.x and start.z == end.z: scale = Scale(x=line_width, y=abs(start.y - end.y), z=line_width) elif start.x == end.x and start.y == end.y: scale = Scale(x=line_width, y=line_width, z=abs(start.z - end.z)) name = f"{object_id}{delim}{axis}{direction}_{suffix}" position = Position(statistics.median([start.x, end.x]), statistics.median([start.y, end.y]), statistics.median([start.z, end.z])) if name not in CONTROLS[object_id]: CONTROLS[object_id][name] = Box( object_id=name, # TODO: restore ttl=arblib.TTL_TEMP, parent=parent, scale=scale, position=position, material=Material(color=color, transparent=True, opacity=0.4, shader="flat"), ) scene.add_object(CONTROLS[object_id][name]) elif move: scene.update_object(CONTROLS[object_id][name], position=position, scale=scale)
def make_clickroot(objid, position, delim, rotation=None, move=False): if objid not in CONTROLS.keys(): CONTROLS[objid] = {} name = f"{objid}{delim}clickroot" if rotation: name += "_rotated" else: rotation = Rotation(0, 0, 0, 1) if name not in CONTROLS[objid]: CONTROLS[objid][name] = Box( object_id=name, material=Material(transparent=True, opacity=0), position=position, scale=Scale(SCL_CLICK, SCL_CLICK, SCL_CLICK), rotation=rotation, ) scene.add_object(CONTROLS[objid][name]) elif move: scene.update_object(CONTROLS[objid][name], position=position, rotation=rotation) return name
def __init__(self, scene: Scene, camname, panel_callback): self.scene = scene self.camname = camname self.mode = Mode.NONE self.clipboard = self.cliptarget = None self.target_id = self.target_control_id = None self.position = self.rotation = None self.position_last = self.rotation_last = None self.gesturing = False self.target_style = self.typetext = "" self.locky = LOCK_YOFF self.lockx = LOCK_XOFF self.wloc_start = self.wloc_end = None self.wrot_start = self.wrot_end = None self.lamp = None init_origin(self.scene) # set HUD to each user self.hud = Box( object_id=f"hud_{camname}", parent=camname, material=Material(transparent=True, opacity=0), position=Position(0, 0, 0), scale=Scale(SCL_HUD, SCL_HUD, SCL_HUD), rotation=Rotation(0, 0, 0, 1), ) self.scene.add_object(self.hud) self.hudtext_left = self.make_hudtext( "hudTextLeft", Position(-0.15, 0.15, -0.5), str(self.mode)) self.hudtext_right = self.make_hudtext( "hudTextRight", Position(0.1, 0.15, -0.5), "") self.hudtext_status = self.make_hudtext( "hudTextStatus", Position(0.02, -0.15, -0.5), "") # workaround x=0 bad? # AR Control Panel self.follow_lock = False self.follow = Box( object_id=f"follow_{camname}", parent=camname, material=Material(transparent=True, opacity=0), position=Position(0, 0, -PANEL_RADIUS * 0.1), scale=Scale(0.1, 0.01, 0.1), rotation=Rotation(0.7, 0, 0, 0.7), ) self.scene.add_object(self.follow) self.redpill = False self.slider = False self.panel = {} # button dictionary self.dbuttons = {} buttons = [ # top row [Mode.ROTATE, -2, 1, True, ButtonType.ACTION], [Mode.NUDGE, -1, 1, True, ButtonType.ACTION], [Mode.SCALE, 0, 1, True, ButtonType.ACTION], [Mode.STRETCH, 1, 1, True, ButtonType.ACTION], [Mode.MODEL, 2, 1, True, ButtonType.ACTION], [Mode.CREATE, 3, 1, True, ButtonType.ACTION], # center row [Mode.REDPILL, -2, 0, True, ButtonType.TOGGLE], [Mode.MOVE, -1, 0, True, ButtonType.ACTION], [Mode.LOCK, 0, 0, True, ButtonType.TOGGLE], [Mode.DELETE, 1, 0, True, ButtonType.ACTION], [Mode.PARENT, 2, 0, True, ButtonType.ACTION], # bottom row [Mode.WALL, -2, -1, True, ButtonType.ACTION], [Mode.OCCLUDE, -1, -1, True, ButtonType.ACTION], [Mode.RENAME, 0, -1, True, ButtonType.ACTION], [Mode.COLOR, 1, -1, True, ButtonType.ACTION], [Mode.LAMP, 2, -1, True, ButtonType.TOGGLE], [Mode.SLIDER, 3, -1, False, ButtonType.TOGGLE], # TODO: adjust scale ] for but in buttons: pbutton = Button( scene, camname, but[0], but[1], but[2], enable=but[3], btype=but[4], parent=self.follow.object_id, callback=panel_callback) self.panel[pbutton.button.object_id] = pbutton
def make_wall(camname): # Wall theory: capture two poses and use them to place a wall object. # Also assumes first corner easier to capture accurate rotation than last. # Click 1: Capture the position and rotation. # Click 2: Capture the position only. sloc = USERS[camname].wloc_start eloc = USERS[camname].wloc_end srot = USERS[camname].wrot_start erot = USERS[camname].wrot_end print(f"S POS {str(sloc)}") print(f"E POS {str(eloc)}") # center point (blue) locx = statistics.median([sloc.x, eloc.x]) locy = statistics.median([sloc.y, eloc.y]) locz = statistics.median([sloc.z, eloc.z]) pos = Position(locx, locy, locz) scene.add_object(arblib.temp_loc_marker(pos, Color(0, 0, 255))) print(f"wall position {str(pos)}") # rotation print(f"S ROT {str(srot)}") print(f"E ROT {str(erot)}") rotx = arblib.probable_quat(srot.x) roty = arblib.probable_quat(srot.y) rotz = arblib.probable_quat(srot.z) rotw = arblib.probable_quat(srot.w) rot = Rotation(rotx, roty, rotz, rotw) gaze = (rotx, roty, rotz, rotw) scene.add_object(arblib.temp_rot_marker(pos, rot)) print(f"wall rotation {str(rot)}") # which axis to use for wall? use camera gaze # TODO: rotation still off if gaze in arblib.GAZES[0]: height = abs(sloc.y - eloc.y) width = abs(sloc.x - eloc.x) elif gaze in arblib.GAZES[1]: height = abs(sloc.y - eloc.y) width = abs(sloc.z - eloc.z) elif gaze in arblib.GAZES[2]: height = abs(sloc.z - eloc.z) width = abs(sloc.x - eloc.x) else: # TODO: (placeholder) add direction and hypotenuse height = abs(sloc.y - eloc.y) width = abs(sloc.x - eloc.x) print(f"Non-axis parallel rotation: {str(rot)}") # scale scax = width scay = height scaz = arblib.WALL_WIDTH sca = Scale(scax, scay, scaz) print(f"wall scale {str(sca)}") # make wall randstr = str(random.randrange(0, 1000000)) new_wall = Box( persist=True, clickable=True, object_id=f"wall_{randstr}", position=pos, rotation=rot, scale=sca, material=Material(color=Color(200, 200, 200), transparent=True, opacity=0.5), ) scene.add_object(new_wall) USERS[camname].target_id = new_wall.object_id print(f"Created {new_wall.object_id} r{str(rot)} s{str(sca)}")