def set_up_vector(self, up_v): p = self.geocentric_coords u = negate(normalized(cross_product(p, up_v))) v = cross_product(u, p) v.scale(self.image_scale) u.scale(self.image_scale) self.ux = u.x self.uy = u.y self.uz = u.z self.vx = v.x self.vy = v.y self.vz = v.z
def draw_internal(self, gl): if self.render_state.night_vision_mode: return gl.glEnableClientState(gl.GL_VERTEX_ARRAY) gl.glEnableClientState(gl.GL_COLOR_ARRAY) gl.glDisableClientState(gl.GL_TEXTURE_COORD_ARRAY) gl.glEnable(gl.GL_CULL_FACE) gl.glFrontFace(gl.GL_CW) gl.glCullFace(gl.GL_BACK) gl.glShadeModel(gl.GL_SMOOTH) gl.glPushMatrix() # Rotate the sky box to the position of the sun. cp = cross_product(Vector3(0, 1, 0), self.sun_pos) cp = normalized(cp) angle = 180.0 / math.pi * math.acos(self.sun_pos.y) gl.glRotatef(angle, cp.x, cp.y, cp.z) self.vertex_buffer.set(gl) self.color_buffer.set(gl) self.index_buffer.draw(gl, gl.GL_TRIANGLES) gl.glPopMatrix()
def set_view_up_direction(self, viewer_up): if abs(viewer_up.y) < 0.999: cp = cross_product(viewer_up, Vector3(0, 0, 0)) cp = normalized(cp) self.geo_to_viewer_transform = create_rotation(math.acos(viewer_up.y), cp) else: self.geo_to_viewer_transform = create_identity() self.must_update_transformed_orientation = True
def update_view(self, gl): # Get a vector perpendicular to both, pointing to the right, by taking # lookDir cross up. look_dir = self.render_state.look_dir.copy() up_dir = self.render_state.up_dir.copy() right = cross_product(look_dir, up_dir) if self.DEBUG_MODE != None: from src.units.Vector3 import Vector3 look_dir = Vector3(Debug.LOOKDIRVECTORS[self.DEBUG_MODE][0], Debug.LOOKDIRVECTORS[self.DEBUG_MODE][1], Debug.LOOKDIRVECTORS[self.DEBUG_MODE][2]) up_dir = Vector3(Debug.UPDIRVECTORS[self.DEBUG_MODE][0], Debug.UPDIRVECTORS[self.DEBUG_MODE][1], Debug.UPDIRVECTORS[self.DEBUG_MODE][2]) right = Vector3(Debug.RIGHTVECTORS[self.DEBUG_MODE][0], Debug.RIGHTVECTORS[self.DEBUG_MODE][1], Debug.RIGHTVECTORS[self.DEBUG_MODE][2]) self.view_matrix = Matrix4x4.create_view(look_dir, up_dir, right) gl.glMatrixMode(gl.GL_MODELVIEW) adjust_matrix = Matrix4x4.Matrix4x4([0.0, 0.0, -1.0, 0.0, 0.0, 1.0, -0.0, 0.0, 1.0, 0.0, -0.0, 0.0, 0.0, 0.0, 0.0, 1.0]) matrix = Matrix4x4.multiply_MM(self.view_matrix, adjust_matrix) # Invert the left/right rotation of the matrix matrix.values[2] *= -1 matrix.values[8] *= -1 # Invert these so that we don't rotate in and out of the unit sphere matrix.values[1] *= -1 matrix.values[4] *= -1 matrix = np.array(matrix.values, dtype=np.float32) #matrix = np.array(self.view_matrix.values, dtype=np.float32) gl.glLoadMatrixf(matrix)
def update_objects(self, lines, update_type): # We only care about updates to positions, ignore any other updates. if not (self.update_type.Reset in update_type) and \ not (self.update_type.UpdatePositions in update_type): return num_line_segments = 0 for l_source in lines: num_line_segments += len(l_source.gc_vertices) - 1 # To render everything in one call, we render everything as a line list # rather than a series of line strips. num_vertices = 4 * num_line_segments num_indices = 6 * num_line_segments vb = self.vertex_buffer vb.reset(4 * num_line_segments) cb = self.color_buffer cb.reset(4 * num_line_segments) tb = self.text_coord_buffer tb.reset(num_vertices) ib = self.index_buffer ib.reset(num_indices) # See comment in PointObjectManager for justification of this calculation. fovy_in_radians = 60 * math.pi / 180.0 size_factor = math.tan(fovy_in_radians * 0.5) / 480.0 bool_opaque = True vertex_index = 0 for l_source in lines: coords_list = l_source.gc_vertices if len(coords_list) < 2: continue # If the color isn't fully opaque, set opaque to false. color = l_source.color bool_opaque &= int(color & 0xff000000) == 0xff000000 # Add the vertices. for i in range(0, len(coords_list) - 1): p1 = coords_list[i] p2 = coords_list[i + 1] u = difference(p2, p1) # The normal to the quad should face the origin at its midpoint. avg = sum_vectors(p1, p2) avg.scale(0.5) # I'm assum_vectorsing that the points will already be on a unit sphere. If this is not the case, # then we should normalize it here. v = normalized(cross_product(u, avg)) v.scale(size_factor * l_source.line_width) # Add the vertices # Lower left corner vb.add_point(difference(p1, v)) cb.add_color(color) tb.add_text_coord(0, 1) # Upper left corner vb.add_point(sum_vectors(p1, v)) cb.add_color(color) tb.add_text_coord(0, 0) # Lower left corner vb.add_point(difference(p2, v)) cb.add_color(color) tb.add_text_coord(1, 1) # Upper left corner vb.add_point(sum_vectors(p2, v)) cb.add_color(color) tb.add_text_coord(1, 0) # Add the indices bottom_left = vertex_index top_left = vertex_index + 1 bottom_right = vertex_index + 2 top_right = vertex_index + 3 vertex_index += 4 # First triangle ib.add_index(bottom_left) ib.add_index(top_left) ib.add_index(bottom_right) # Second triangle ib.add_index(bottom_right) ib.add_index(top_left) ib.add_index(top_right) self.opaque = bool_opaque
def update_objects(self, points, update_type): #only_update_points = True # We only care about updates to positions, ignore any other updates. if self.update_type.Reset in update_type: #only_update_points = False pass elif self.update_type.UpdatePositions in update_type: # Sanity check: make sure the number of points is unchanged. if len(points) != self.num_points: return else: return self.num_points = len(points) self.sky_regions.clear() if Debug.ALLREGIONS == "YES": self.COMPUTE_REGIONS = False region = SkyRegionMap.CATCHALL_REGION_ID if self.COMPUTE_REGIONS: # Find the region for each point, and put it in a separate list # for that region. for point in points: if len(points) < self.MINIMUM_NUM_POINTS_FOR_REGIONS: region = SkyRegionMap.CATCHALL_REGION_ID else: region = self.sky_regions.get_object_region(point.geocentric_coords) # self.sky_regions.get_region_data(region) is a RegionData instance data_for_region = self.sky_regions.get_region_data(region) data_for_region.sources.append(point) else: self.sky_regions.get_region_data(region).sources = points # Generate the resources for all of the regions. for data in self.sky_regions.region_data.values(): num_vertices = 4 * len(data.sources) num_indices = 6 * len(data.sources) data.vertex_buffer.reset(num_vertices) data.color_buffer.reset(num_vertices) data.text_coord_buffer.reset(num_vertices) data.index_buffer.reset(num_indices) up = Vector3(0, 1, 0) # By inspecting the perspective projection matrix, you can show that, # to have a quad at the center of the screen to be of size k by k # pixels, the width and height are both: # k * tan(fovy / 2) / screenHeight # This is not difficult to derive. Look at the transformation matrix # in SkyRenderer if you're interested in seeing why this is true. # I'm arbitrarily deciding that at a 60 degree field of view, and 480 # pixels high, a size of 1 means "1 pixel," so calculate size_factor # based on this. These numbers mostly come from the fact that that's # what I think looks reasonable. fovy_in_radians = 60 * math.pi / 180.0 size_factor = math.tan(fovy_in_radians * 0.5) / 480 bottom_left_pos = Vector3(0, 0, 0) top_left_pos = Vector3(0, 0, 0) bottom_right_pos = Vector3(0, 0, 0) top_right_pos = Vector3(0, 0, 0) su = Vector3(0, 0, 0) sv = Vector3(0, 0, 0) index = 0 star_width_in_texels = 1.0 / self.NUM_STARS_IN_TEXTURE for p_source in data.sources: color = 0xFF000000 | int(p_source.color) # Force alpha to 0xff if Debug.COLOR == "WHITE ONLY": color = 0xFFFFFFFF bottom_left = index top_left = index + 1 bottom_right = index + 2 top_right = index + 3 index += 4 # First triangle data.index_buffer.add_index(bottom_left) data.index_buffer.add_index(top_left) data.index_buffer.add_index(bottom_right) # Second triangle data.index_buffer.add_index(top_right); data.index_buffer.add_index(bottom_right); data.index_buffer.add_index(top_left); # PointSource.getPointShape().getImageIndex(); is always 0 star_index = 0 tex_offset_u = star_width_in_texels * star_index data.text_coord_buffer.add_text_coord(tex_offset_u, 1); data.text_coord_buffer.add_text_coord(tex_offset_u, 0); data.text_coord_buffer.add_text_coord(tex_offset_u + star_width_in_texels, 1); data.text_coord_buffer.add_text_coord(tex_offset_u + star_width_in_texels, 0); pos = p_source.geocentric_coords u = normalized(cross_product(pos, up)) v = cross_product(u, pos) s = p_source.size * size_factor su.assign(s*u.x, s*u.y, s*u.z) sv.assign(s*v.x, s*v.y, s*v.z) bottom_left_pos.assign(pos.x - su.x - sv.x, pos.y - su.y - sv.y, pos.z - su.z - sv.z) top_left_pos.assign(pos.x - su.x + sv.x, pos.y - su.y + sv.y, pos.z - su.z + sv.z) bottom_right_pos.assign(pos.x + su.x - sv.x, pos.y + su.y - sv.y, pos.z + su.z - sv.z) top_right_pos.assign(pos.x + su.x + sv.x, pos.y + su.y + sv.y, pos.z + su.z + sv.z) # Add the vertices data.vertex_buffer.add_point(bottom_left_pos) data.color_buffer.add_color(color) data.vertex_buffer.add_point(top_left_pos) data.color_buffer.add_color(color) data.vertex_buffer.add_point(bottom_right_pos) data.color_buffer.add_color(color) data.vertex_buffer.add_point(top_right_pos) data.color_buffer.add_color(color) data.sources = None
def update_objects(self, lines, update_type): # We only care about updates to positions, ignore any other updates. if not (self.update_type.Reset in update_type) and \ not (self.update_type.UpdatePositions in update_type): return num_line_segments = 0; for l_source in lines: num_line_segments += len(l_source.gc_vertices) - 1 # To render everything in one call, we render everything as a line list # rather than a series of line strips. num_vertices = 4 * num_line_segments num_indices = 6 * num_line_segments vb = self.vertex_buffer vb.reset(4 * num_line_segments) cb = self.color_buffer cb.reset(4 * num_line_segments) tb = self.text_coord_buffer tb.reset(num_vertices) ib = self.index_buffer ib.reset(num_indices) # See comment in PointObjectManager for justification of this calculation. fovy_in_radians = 60 * math.pi / 180.0 size_factor = math.tan(fovy_in_radians * 0.5) / 480.0 bool_opaque = True vertex_index = 0 for l_source in lines: coords_list = l_source.gc_vertices if len(coords_list) < 2: continue # If the color isn't fully opaque, set opaque to false. color = l_source.color bool_opaque &= int(color & 0xff000000) == 0xff000000 # Add the vertices. for i in range(0, len(coords_list) - 1): p1 = coords_list[i] p2 = coords_list[i+1] u = difference(p2, p1) # The normal to the quad should face the origin at its midpoint. avg = sum_vectors(p1, p2) avg.scale(0.5) # I'm assum_vectorsing that the points will already be on a unit sphere. If this is not the case, # then we should normalize it here. v = normalized(cross_product(u, avg)) v.scale(size_factor * l_source.line_width) # Add the vertices # Lower left corner vb.add_point(difference(p1, v)) cb.add_color(color) tb.add_text_coord(0, 1) # Upper left corner vb.add_point(sum_vectors(p1, v)) cb.add_color(color) tb.add_text_coord(0, 0) # Lower left corner vb.add_point(difference(p2, v)) cb.add_color(color) tb.add_text_coord(1, 1) # Upper left corner vb.add_point(sum_vectors(p2, v)) cb.add_color(color) tb.add_text_coord(1, 0) # Add the indices bottom_left = vertex_index top_left = vertex_index + 1 bottom_right = vertex_index +2 top_right = vertex_index + 3 vertex_index += 4 # First triangle ib.add_index(bottom_left) ib.add_index(top_left) ib.add_index(bottom_right) # Second triangle ib.add_index(bottom_right) ib.add_index(top_left) ib.add_index(top_right) self.opaque = bool_opaque