def create_objects(self): if not self.isValid(): self.invalid_count += 1 print 'Radarwidget: Context not valid in create_objects, count=%d' % self.invalid_count QTimer.singleShot(100, self.create_objects) return # Make the radarwidget context current, necessary when create_objects is not called from initializeGL self.makeCurrent() # Initialize font for radar view with specified settings self.font = Font() self.font.create_font_array(char_height=text_texture_size, font_family=font_family, font_weight=font_weight) self.font.init_shader(self.text_shader) # Load and bind world texture max_texture_size = gl.glGetIntegerv(gl.GL_MAX_TEXTURE_SIZE) print 'Maximum supported texture size: %d' % max_texture_size for i in [16384, 8192, 4096]: if max_texture_size >= i: fname = 'data/graphics/world.%dx%d.dds' % (i, i / 2) print 'Loading texture ' + fname self.map_texture = self.bindTexture(fname) break # Create initial empty buffers for aircraft position, orientation, label, and color self.achdgbuf = create_empty_buffer(MAX_NAIRCRAFT * 4, usage=gl.GL_STREAM_DRAW) self.aclatbuf = create_empty_buffer(MAX_NAIRCRAFT * 4, usage=gl.GL_STREAM_DRAW) self.aclonbuf = create_empty_buffer(MAX_NAIRCRAFT * 4, usage=gl.GL_STREAM_DRAW) self.acaltbuf = create_empty_buffer(MAX_NAIRCRAFT * 4, usage=gl.GL_STREAM_DRAW) self.actasbuf = create_empty_buffer(MAX_NAIRCRAFT * 4, usage=gl.GL_STREAM_DRAW) self.accolorbuf = create_empty_buffer(MAX_NAIRCRAFT * 3, usage=gl.GL_STREAM_DRAW) self.aclblbuf = create_empty_buffer(MAX_NAIRCRAFT * 24, usage=gl.GL_STREAM_DRAW) self.confcpabuf = create_empty_buffer(MAX_NCONFLICTS * 16, usage=gl.GL_STREAM_DRAW) self.polyprevbuf = create_empty_buffer(MAX_POLYPREV_SEGMENTS * 8, usage=gl.GL_DYNAMIC_DRAW) self.allpolysbuf = create_empty_buffer(MAX_ALLPOLYS_SEGMENTS * 16, usage=gl.GL_DYNAMIC_DRAW) self.routebuf = create_empty_buffer(MAX_ROUTE_LENGTH * 8, usage=gl.GL_DYNAMIC_DRAW) self.routewplatbuf = create_empty_buffer(MAX_ROUTE_LENGTH * 4, usage=gl.GL_DYNAMIC_DRAW) self.routewplonbuf = create_empty_buffer(MAX_ROUTE_LENGTH * 4, usage=gl.GL_DYNAMIC_DRAW) self.routelblbuf = create_empty_buffer(MAX_ROUTE_LENGTH * 12, usage=gl.GL_DYNAMIC_DRAW) # ------- Map ------------------------------------ self.map = RenderObject(gl.GL_TRIANGLE_FAN, vertex_count=4) mapvertices = np.array([(-90.0, 540.0), (-90.0, -540.0), (90.0, -540.0), (90.0, 540.0)], dtype=np.float32) texcoords = np.array([(1, 3), (1, 0), (0, 0), (0, 3)], dtype=np.float32) self.map.bind_attrib(ATTRIB_VERTEX, 2, mapvertices) self.map.bind_attrib(ATTRIB_TEXCOORDS, 2, texcoords) # ------- Coastlines ----------------------------- self.coastlines = RenderObject(gl.GL_LINES) coastvertices, coastindices = load_coastlines() self.coastlines.bind_attrib(ATTRIB_VERTEX, 2, coastvertices) self.coastlines.bind_attrib(ATTRIB_COLOR, 3, np.array(lightblue2, dtype=np.uint8), datatype=gl.GL_UNSIGNED_BYTE, normalize=True, instance_divisor=1) self.vcount_coast = len(coastvertices) self.coastindices = coastindices del coastvertices # ------- Runways -------------------------------- self.runways = RenderObject(gl.GL_TRIANGLES) self.runways.bind_attrib(ATTRIB_VERTEX, 2, self.vbuf_runways) self.runways.bind_attrib(ATTRIB_COLOR, 3, np.array(grey, dtype=np.uint8), datatype=gl.GL_UNSIGNED_BYTE, normalize=True, instance_divisor=1) self.runways.set_vertex_count(len(self.vbuf_runways) / 2) #---------Runway Thresholds----------------------- self.thresholds = RenderObject(gl.GL_TRIANGLES) self.thresholds.bind_attrib(ATTRIB_VERTEX, 2, self.vbuf_rwythr) self.thresholds.bind_attrib(ATTRIB_COLOR, 3, np.array(white, dtype=np.uint8), datatype=gl.GL_UNSIGNED_BYTE, normalize=True, instance_divisor=1) self.thresholds.set_vertex_count(len(self.vbuf_rwythr) / 2) # ------- Taxiways ------------------------------- self.taxiways = RenderObject(gl.GL_TRIANGLES) self.taxiways.bind_attrib(ATTRIB_VERTEX, 2, self.vbuf_asphalt) self.taxiways.bind_attrib(ATTRIB_COLOR, 3, np.array(grey, dtype=np.uint8), datatype=gl.GL_UNSIGNED_BYTE, normalize=True, instance_divisor=1) self.taxiways.set_vertex_count(len(self.vbuf_asphalt) / 2) # ------- Pavement ------------------------------- self.pavement = RenderObject(gl.GL_TRIANGLES) self.pavement.bind_attrib(ATTRIB_VERTEX, 2, self.vbuf_concrete) self.pavement.bind_attrib(ATTRIB_COLOR, 3, np.array(lightgrey, dtype=np.uint8), datatype=gl.GL_UNSIGNED_BYTE, normalize=True, instance_divisor=1) self.pavement.set_vertex_count(len(self.vbuf_concrete) / 2) # Polygon preview object self.polyprev = RenderObject(gl.GL_LINE_LOOP) self.polyprev.bind_attrib(ATTRIB_VERTEX, 2, self.polyprevbuf) self.polyprev.bind_attrib(ATTRIB_COLOR, 3, np.array(lightblue, dtype=np.uint8), datatype=gl.GL_UNSIGNED_BYTE, normalize=True, instance_divisor=1) # Fixed polygons self.allpolys = RenderObject(gl.GL_LINES) self.allpolys.bind_attrib(ATTRIB_VERTEX, 2, self.allpolysbuf) self.allpolys.bind_attrib(ATTRIB_COLOR, 3, np.array(blue, dtype=np.uint8), datatype=gl.GL_UNSIGNED_BYTE, normalize=True, instance_divisor=1) # ------- SSD object ----------------------------- self.ssd = RenderObject(gl.GL_POINTS) self.ssd.bind_attrib(ATTRIB_LAT0, 1, self.aclatbuf, instance_divisor=1) self.ssd.bind_attrib(ATTRIB_LON0, 1, self.aclonbuf, instance_divisor=1) self.ssd.bind_attrib(ATTRIB_ALT0, 1, self.acaltbuf, instance_divisor=1) self.ssd.bind_attrib(ATTRIB_TAS0, 1, self.actasbuf, instance_divisor=1) self.ssd.bind_attrib(ATTRIB_TRK0, 1, self.achdgbuf, instance_divisor=1) self.ssd.bind_attrib(ATTRIB_LAT1, 1, self.aclatbuf) self.ssd.bind_attrib(ATTRIB_LON1, 1, self.aclonbuf) self.ssd.bind_attrib(ATTRIB_ALT1, 1, self.acaltbuf) self.ssd.bind_attrib(ATTRIB_TAS1, 1, self.actasbuf) self.ssd.bind_attrib(ATTRIB_TRK1, 1, self.achdgbuf) # ------- Circle --------------------------------- # Create a new VAO (Vertex Array Object) and bind it self.protectedzone = RenderObject(gl.GL_LINE_LOOP, vertex_count=self.vcount_circle) circlevertices = np.transpose( np.array( (2.5 * nm * np.cos(np.linspace(0.0, 2.0 * np.pi, self.vcount_circle)), 2.5 * nm * np.sin(np.linspace(0.0, 2.0 * np.pi, self.vcount_circle))), dtype=np.float32)) self.protectedzone.bind_attrib(ATTRIB_VERTEX, 2, circlevertices) self.protectedzone.bind_attrib(ATTRIB_LAT, 1, self.aclatbuf, instance_divisor=1) self.protectedzone.bind_attrib(ATTRIB_LON, 1, self.aclonbuf, instance_divisor=1) self.protectedzone.bind_attrib(ATTRIB_COLOR, 3, self.accolorbuf, datatype=gl.GL_UNSIGNED_BYTE, normalize=True, instance_divisor=1) # ------- A/C symbol ----------------------------- self.ac_symbol = RenderObject(gl.GL_TRIANGLE_FAN, vertex_count=4) acvertices = np.array([(0.0, 0.5 * ac_size), (-0.5 * ac_size, -0.5 * ac_size), (0.0, -0.25 * ac_size), (0.5 * ac_size, -0.5 * ac_size)], dtype=np.float32) self.ac_symbol.bind_attrib(ATTRIB_VERTEX, 2, acvertices) self.ac_symbol.bind_attrib(ATTRIB_LAT, 1, self.aclatbuf, instance_divisor=1) self.ac_symbol.bind_attrib(ATTRIB_LON, 1, self.aclonbuf, instance_divisor=1) self.ac_symbol.bind_attrib(ATTRIB_ORIENTATION, 1, self.achdgbuf, instance_divisor=1) self.ac_symbol.bind_attrib(ATTRIB_COLOR, 3, self.accolorbuf, datatype=gl.GL_UNSIGNED_BYTE, normalize=True, instance_divisor=1) self.aclabels = self.font.prepare_text_instanced( self.aclblbuf, (8, 3), self.aclatbuf, self.aclonbuf, self.accolorbuf, char_size=text_size, vertex_offset=(ac_size, -0.5 * ac_size)) # ------- Conflict CPA lines --------------------- self.cpalines = RenderObject(gl.GL_LINES) self.cpalines.bind_attrib(ATTRIB_VERTEX, 2, self.confcpabuf) self.cpalines.bind_attrib(ATTRIB_COLOR, 3, np.array(amber, dtype=np.uint8), datatype=gl.GL_UNSIGNED_BYTE, normalize=True, instance_divisor=1) # ------- Aircraft Route ------------------------- self.route = RenderObject(gl.GL_LINES) self.route.bind_attrib(ATTRIB_VERTEX, 2, self.routebuf) self.route.bind_attrib(ATTRIB_COLOR, 3, np.array(magenta, dtype=np.uint8), datatype=gl.GL_UNSIGNED_BYTE, normalize=True, instance_divisor=1) self.routelbl = self.font.prepare_text_instanced( self.routelblbuf, (12, 1), self.routewplatbuf, self.routewplonbuf, char_size=text_size, vertex_offset=(wpt_size, 0.5 * wpt_size)) # ------- Waypoints ------------------------------ self.nwaypoints = len(self.navdb.wplat) self.waypoints = RenderObject(gl.GL_LINE_LOOP, vertex_count=3, n_instances=self.nwaypoints) wptvertices = np.array([(0.0, 0.5 * wpt_size), (-0.5 * wpt_size, -0.5 * wpt_size), (0.5 * wpt_size, -0.5 * wpt_size)], dtype=np.float32) # a triangle self.waypoints.bind_attrib(ATTRIB_VERTEX, 2, wptvertices) # Sort based on id string length llid = sorted(zip(self.navdb.wpid, self.navdb.wplat, self.navdb.wplon), key=lambda i: len(i[0]) > 3) wplat = [lat for (wpid, lat, lon) in llid] wplon = [lon for (wpid, lon, lon) in llid] self.wptlatbuf = self.waypoints.bind_attrib(ATTRIB_LAT, 1, np.array(wplat, dtype=np.float32), instance_divisor=1) self.wptlonbuf = self.waypoints.bind_attrib(ATTRIB_LON, 1, np.array(wplon, dtype=np.float32), instance_divisor=1) wptids = '' self.nnavaids = 0 for wptid in llid: if len(wptid[0]) <= 3: self.nnavaids += 1 wptids += wptid[0].ljust(5) self.wptlabels = self.font.prepare_text_instanced( np.array(wptids, dtype=np.string_), (5, 1), self.wptlatbuf, self.wptlonbuf, char_size=text_size, vertex_offset=(wpt_size, 0.5 * wpt_size)) del wptids # ------- Airports ------------------------------- self.nairports = len(self.navdb.aptlat) self.airports = RenderObject(gl.GL_LINE_LOOP, vertex_count=4, n_instances=self.nairports) aptvertices = np.array([(-0.5 * apt_size, -0.5 * apt_size), (0.5 * apt_size, -0.5 * apt_size), (0.5 * apt_size, 0.5 * apt_size), (-0.5 * apt_size, 0.5 * apt_size)], dtype=np.float32) # a square self.airports.bind_attrib(ATTRIB_VERTEX, 2, aptvertices) indices = self.navdb.aptype.argsort() aplat = np.array(self.navdb.aptlat[indices], dtype=np.float32) aplon = np.array(self.navdb.aptlon[indices], dtype=np.float32) aptypes = self.navdb.aptype[indices] apnames = np.array(self.navdb.aptid) apnames = apnames[indices] # The number of large, large+med, and large+med+small airports self.nairports = [ aptypes.searchsorted(2), aptypes.searchsorted(3), self.nairports ] self.aptlatbuf = self.airports.bind_attrib(ATTRIB_LAT, 1, aplat, instance_divisor=1) self.aptlonbuf = self.airports.bind_attrib(ATTRIB_LON, 1, aplon, instance_divisor=1) aptids = '' for aptid in apnames: aptids += aptid.ljust(4) self.aptlabels = self.font.prepare_text_instanced( np.array(aptids, dtype=np.string_), (4, 1), self.aptlatbuf, self.aptlonbuf, char_size=text_size, vertex_offset=(apt_size, 0.5 * apt_size)) del aptids # Unbind VAO, VBO RenderObject.unbind_all() # Set initial values for the global uniforms self.globaldata.set_wrap(self.wraplon, self.wrapdir) self.globaldata.set_pan_and_zoom(self.panlat, self.panlon, self.zoom) # Clean up memory del self.vbuf_asphalt, self.vbuf_concrete, self.vbuf_runways, self.vbuf_rwythr self.initialized = True
def create_objects(self): self.mcp = RenderObject(gl.GL_TRIANGLES, vertex=np.array(rect(-1, -1, 2, 2), dtype=np.float32)) self.mcp_texture = load_texture('mcp737.png') self.btn_tex = load_texture('btn_led.png') self.lcd_tex = load_lcd_font() v_mcp_text = [] for pos in [ 0.0, 0.03, 0.06, 0.31, 0.34, 0.37, 0.4, 0.43, 0.644, 0.674, 0.704, 0.955, 0.985, 1.015, 1.045, 1.075, 1.22, 1.25, 1.28, 1.31, 1.34, 1.69, 1.72, 1.75 ]: v, t = Font.char(-0.886 + pos, 0.45, 0.03, 0.25) v_mcp_text += v self.mcp_text = RenderObject(gl.GL_TRIANGLES, vertex=np.array(v_mcp_text, dtype=np.float32)) self.lcd_charcoords = np.zeros(24 * 6, dtype=np.float32) self.lcdbuf = self.mcp_text.bind_attrib(1, 1, self.lcd_charcoords, datatype=gl.GL_FLOAT) btn_leds = [] for pos in [(-0.74, -0.75), (-0.645, -0.75), (-0.37, -0.75), (-0.232, -0.75), (-0.09, -0.75), (0.105, -0.75), (0.2, -0.75), (-0.37, 0.5), (-0.09, 0.5), (-0.09, -0.125), (0.575, 0.34), (0.575, -0.34), (0.684, 0.34), (0.684, -0.34)]: btn_leds += rect(pos[0], pos[1], 0.055, 0.075) btn_color = np.zeros(14 * 6 * 4, dtype=np.uint8) self.btn_leds = RenderObject(gl.GL_TRIANGLES, vertex=np.array(btn_leds, dtype=np.float32), color=btn_color) # Button up/down indicator w, h, offset = 0.04, 0.16, 0.04 triangles = np.array([ -w, offset, 0.0, offset + h, w, offset, -w, -offset, 0.0, -offset - h, w, -offset ], dtype=np.float32) col_triangles = np.array(6 * [255, 255, 255, 180], dtype=np.uint8) self.updown = RenderObject(gl.GL_TRIANGLES, vertex=triangles, color=col_triangles) # Use the same font as the radarwidget self.font = Font() self.font.create_font_array('../../data/graphics/font/') self.font.init_shader(self.text_shader) edge = np.zeros(120, dtype=np.float32) edge[0:120:2] = 1.4 * np.sin(np.radians(np.arange(-60, 60, 2))) edge[1:120:2] = 1.4 * np.cos(np.radians(np.arange(-60, 60, 2))) self.edge = RenderObject(gl.GL_LINE_STRIP, vertex=edge, color=white) arcs = [] for i in range(1, 4): for angle in range(-60, 60, max(2, 6 - 2 * i)): arcs.append(float(i) * 0.35 * sin(radians(angle))) arcs.append(float(i) * 0.35 * cos(radians(angle))) if i == 4: arcs.append(float(i) * 0.35 * sin(radians(angle + 2))) arcs.append(float(i) * 0.35 * cos(radians(angle + 2))) arcs = np.array(arcs, dtype=np.float32) self.arcs = RenderObject(gl.GL_LINES, vertex=arcs, color=white) mask = [] for angle in range(-60, 60, 2): mask.append(1.4 * sin(radians(angle))) mask.append(10.0) mask.append(1.4 * sin(radians(angle))) mask.append(1.4 * cos(radians(angle))) mask = np.array(mask, dtype=np.float32) self.mask = RenderObject(gl.GL_TRIANGLE_STRIP, vertex=mask, color=black) ticks = np.zeros(288, dtype=np.float32) for i in range(72): ticktop = 1.46 if i % 6 == 0 else (1.44 if i % 2 == 0 else 1.42) ticks[4 * i:4 * i + 2] = (1.4 * sin(radians(i * 5)), 1.4 * cos(radians(i * 5))) ticks[4 * i + 2:4 * i + 4] = (ticktop * sin(radians(i * 5)), ticktop * cos(radians(i * 5))) self.ticks = RenderObject(gl.GL_LINES, vertex=ticks, color=white) ticklbls = np.zeros(24 * 36, dtype=np.float32) texcoords = np.zeros(36 * 36, dtype=np.float32) for i in range(36): if i % 3 == 0: w, h, y = 0.045, 0.09, 1.48 else: w, h, y = 0.035, 0.07, 1.46 tmp = [(-w, h + y), (-w, y), (0.0, h + y), (0.0, h + y), (-w, y), (0.0, y), (0.0, h + y), (0.0, y), (w, h + y), (w, h + y), (0.0, y), (w, y)] # numerics start at ASCII 48 c1 = i / 10 + 48 c2 = i % 10 + 48 texcoords[36 * i:36 * i + 18] = [ 0, 0, c1, 0, 1, c1, 1, 0, c1, 1, 0, c1, 0, 1, c1, 1, 1, c1 ] texcoords[36 * i + 18:36 * i + 36] = [ 0, 0, c2, 0, 1, c2, 1, 0, c2, 1, 0, c2, 0, 1, c2, 1, 1, c2 ] angle = radians(10 * (36 - i)) rot = np.array([[cos(angle), -sin(angle)], [sin(angle), cos(angle)]]) for j in range(12): ticklbls[24 * i + 2 * j:24 * i + 2 * j + 2] = rot.dot(tmp[j]) self.ticklbls = RenderObject(gl.GL_TRIANGLES, vertex=ticklbls, color=white, texcoords=texcoords) vown = np.array([ 0.0, 0.0, 0.0, -0.12, 0.065, -0.03, -0.065, -0.03, 0.022, -0.1, -0.022, -0.1 ], dtype=np.float32) self.ownship = RenderObject(gl.GL_LINES, vertex=vown, color=yellow) self.spdlabel_text = self.font.prepare_text_string( 'GS TAS', 0.05, white, (-0.98, 1.6)) self.spdlabel_val = self.font.prepare_text_string( ' 000 000', 0.05, green, (-0.97, 1.6)) self.initialized = True # Unbind everything RenderObject.unbind_all()