def move(self, dx: float = 0.0, dy: float = 0.0, dz: float = 0.0, pitch: float = 0.0, yaw: float = 0.0, roll: float = 0.0): p, y, r = self.rotation self.rotation = p + pitch, y + yaw, r + roll x, y, z = self.location self.location = Vector(x + dx, y + dy, z + dz) for figure in self.figures: change = False if any([dx, dy, dz]): change = True x, y, z = figure.location figure.location = Vector(x + dx, y + dy, z + dz) dx = -dx figure.vertices = [(x + dx, y + dy, z + dz) for x, y, z in figure.vertices] if any([pitch, yaw, roll]): change = True p, y, r = figure.rotation figure.rotation = p + pitch, y + yaw, r + roll figure.vertices = rotate_3d(figure.vertices, self.location, pitch, yaw, roll) if change: figure.update()
def __init__(self, shape: _ElementTemplate, intial_velocity: Vector = None, mass: float = 1, do_standard_grav: bool = True, momentum: bool = True, friction_coefficient: float = 0.5, moveable: bool = True, do_collisions: bool = True): ''' :param shape: graphical representaiton :param intial_velocity: velocity @ time of creation :param mass: self explainatory :param do_standard_grav: whether assuming earth grav or calculating based on other objects :param momentum: whether object continues moving :param friction_coefficient: rate of slow down when colliding with other :param moveable: whether it can be moved by outside forces :param do_grav: whether it is affected by gravity :param do_collisions: whether to run collision checks with it ''' self.do_standard_gravity = do_standard_grav self.velocity = intial_velocity if intial_velocity is not None else Vector( [0 for i in range(shape.dimension)]) self.shape = shape self.do_momentum = momentum self.all_objects.append(self) self.friction_coefficient = friction_coefficient self.mass = mass self.moveable = moveable self.collideable = do_collisions self.fall = True
def move_forward(self, dis): if self.planar: dx, dy, dz = self.vision_vector() move = Vector(dx, 0, dz).unit_vector() * dis + self.velocity else: move = self.vision_vector() * dis + self.velocity self.velocity = move
def move_sideways(self, dis): side, up = self.rotation side += 90 dx = math.sin(math.radians(side)) * dis dz = math.cos(math.radians(side)) * dis dy = 0 # math.sin(math.radians(up)) * dis move = Vector(dx, dy, dz) + self.velocity self.velocity = move
def periodic(self, dt: float): self.check_user_input() self.move(dt) if self.hitbox is None: # else use the hitbox momentum variable self.velocity = Vector(0, 0, 0) if self.running_physics: for obj in Physical.all_objects: if obj is not self.hitbox: obj.update(dt)
def get_3D_version(self, pos): pos = convert_pos(pos) x, y, z = pos dx, dy = Vector.from_2_points(self.location, (x, y)) verts = deepcopy(self.vertices) self._convert_to3d([(x + dx, y + dy, 0) for x, y in self.vertices]) new = LowerDimensional(self) self.vertices = verts return new
def move(self, dt): if self.hitbox is not None: old_pos = self.hitbox.shape.location self.hitbox.velocity = self.velocity self.hitbox.update(dt) trans = Vector.from_2_points(old_pos, self.hitbox.shape.location) self.position = tuple(trans + self.position) self.velocity = self.hitbox.velocity else: self.velocity *= dt self.position = tuple(self.velocity + self.position)
def move(self, dx=0, dy=0, rotation=0): change = False if dx != 0 or dy != 0: change = True self.vertices = [(x+dx, y+dy) for x, y in self.vertices] x, y = self.location self.location = Vector(x + dx, y + dy) if self.rotation != 0: change = True self._rotate(rotation) if change: self.update()
def do_collision(self, other, dt: float): """ Check and apply collision between to objects :param other: other Physical object :param dt: time frame of movement :return: """ trans = self.velocity if trans.magnitude( ) == 0 or not self.collideable or not other.collideable: return new_pos = Vector(self.shape.location) + trans if self.shape.distance(other.shape) < 0: perp = Vector.from_2_points( self.shape.get_nearest_point(other.shape.location), other.shape.get_nearest_point( self.shape.location)) # this is vector up to wall dis_traveled = trans.magnitude( ) # full dis travelled in this increment theta = perp.angle_to(trans) perp2 = deepcopy( perp) # this is the perp compoent of the initial trans perp2.resize(cos(radians(theta)) * dis_traveled) # this resizes it to the prwoper length horizontal = Vector.from_2_points( perp2 + self.shape.location, new_pos ) # this find the component of initial trans parallel to wall # horizontal contains a dis, make into vector print(self.velocity) self.velocity = (perp + horizontal) / dt print("collide:", self, other, self.velocity) if self.do_momentum: acceleration = ( perp2 - perp) / dt # acceleration is change in velocity over time push_force = self.get_acceleration_force(acceleration) friction = push_force * self.friction_coefficient self.apply_force(friction, dt) other.apply_force(push_force, dt)
def __init__(self): super(Window, self).__init__(resizable=True) Window.active_window = self self.rotation = 0, 0 self.position = 0, 0, 0 self.mode = 2 self.bg_color = BLACK self._inner = LowLevel(self) self.turn_sensivity = 10 # 1-100 = pixels mouse moves per degree of rotation self.mouse_locked = False self.key_checker = KeyStateHandler() self.push_handlers(self.key_checker) self._is_fog = False self.speed = 10 self.velocity = Vector(0, 0, 0) self.colliables = [] self.hitbox = None self.third_person = False
def move(self, dx: float = 0.0, dy: float = 0.0, dz: float = 0.0, pitch: float = 0.0, yaw: float = 0.0, roll: float = 0.0): change = False if dx != 0 or dy != 0 or dz != 0: change = True x, y, z = self.location self.location = Vector(x + dx, y + dy, z + dz) dx = -dx self.vertices = [(x + dx, y + dy, z + dz) for x, y, z in self.vertices] if pitch != 0 or yaw != 0 or roll != 0: change = True self._rotate(pitch, yaw, roll) if change: self.update()
def move(self, dx: float = 0.0, dy: float = 0.0, dz: float = 0.0, pitch: float = 0.0, yaw: float = 0.0, roll: float = 0.0): change = False if any([dx, dy, dz]): change = True x, y, z = self.location self.location = Vector(x + dx, y + dy, z + dz) dx = -dx self.vertices = [(x + dx, y + dy, z + dz) for x, y, z in self.vertices] if any([pitch, yaw, roll]): change = True self._rotate(pitch, yaw, roll) if change: self.update()
def rotate_3d(list_of_points, center, pitch, yaw, roll): dx, dy, dz = center translation_vector = Vector([dx, dy, dz]) point_matrix = Matrix(list_of_points) for i, vector in enumerate(point_matrix): point_matrix[i] = vector - translation_vector x = radians(pitch) y = radians(yaw) z = radians(roll) rotation_matrix = Matrix([ cos(z) * cos(y), cos(y) * sin(x) * sin(z) - cos(x) * sin(y), cos(x) * cos(y) * sin(z) + sin(x) * sin(y) ], [ cos(z) * sin(y), cos(x) * cos(y) + sin(x) * sin(z) * sin(y), cos(x) * sin(z) * sin(y) - cos(y) * sin(x) ], [-sin(z), cos(z) * sin(x), cos(x) * cos(z)]) rotated_matrix = rotation_matrix * point_matrix for i, vector in enumerate(rotated_matrix): rotated_matrix[i] = vector + translation_vector new_points = [tuple(vector) for vector in rotated_matrix] return new_points
class Physical: """ General Object for applying physics to a rendering Units: STI (m, L, kg, etc) """ standard_grav = Vector(0, -10, 0) air_resistance = 1 gravitational_constant = 6.674e-11 # in standard units above all_objects = [] def __init__(self, shape: _ElementTemplate, intial_velocity: Vector = None, mass: float = 1, do_standard_grav: bool = True, momentum: bool = True, friction_coefficient: float = 0.5, moveable: bool = True, do_collisions: bool = True): ''' :param shape: graphical representaiton :param intial_velocity: velocity @ time of creation :param mass: self explainatory :param do_standard_grav: whether assuming earth grav or calculating based on other objects :param momentum: whether object continues moving :param friction_coefficient: rate of slow down when colliding with other :param moveable: whether it can be moved by outside forces :param do_grav: whether it is affected by gravity :param do_collisions: whether to run collision checks with it ''' self.do_standard_gravity = do_standard_grav self.velocity = intial_velocity if intial_velocity is not None else Vector( [0 for i in range(shape.dimension)]) self.shape = shape self.do_momentum = momentum self.all_objects.append(self) self.friction_coefficient = friction_coefficient self.mass = mass self.moveable = moveable self.collideable = do_collisions self.fall = True def do_collision(self, other, dt: float): """ Check and apply collision between to objects :param other: other Physical object :param dt: time frame of movement :return: """ trans = self.velocity if trans.magnitude( ) == 0 or not self.collideable or not other.collideable: return new_pos = Vector(self.shape.location) + trans if self.shape.distance(other.shape) < 0: perp = Vector.from_2_points( self.shape.get_nearest_point(other.shape.location), other.shape.get_nearest_point( self.shape.location)) # this is vector up to wall dis_traveled = trans.magnitude( ) # full dis travelled in this increment theta = perp.angle_to(trans) perp2 = deepcopy( perp) # this is the perp compoent of the initial trans perp2.resize(cos(radians(theta)) * dis_traveled) # this resizes it to the prwoper length horizontal = Vector.from_2_points( perp2 + self.shape.location, new_pos ) # this find the component of initial trans parallel to wall # horizontal contains a dis, make into vector print(self.velocity) self.velocity = (perp + horizontal) / dt print("collide:", self, other, self.velocity) if self.do_momentum: acceleration = ( perp2 - perp) / dt # acceleration is change in velocity over time push_force = self.get_acceleration_force(acceleration) friction = push_force * self.friction_coefficient self.apply_force(friction, dt) other.apply_force(push_force, dt) @property def momentum(self): return self.velocity * self.mass def update(self, dt): if not self.moveable: return if self.fall: self.apply_gravity(dt) for obj in self.all_objects: if obj is not self: self.do_collision(obj, dt) self.shape.move(*(self.velocity * dt)) if not self.do_momentum: self.velocity = self.velocity * 0 def apply_gravity(self, dt): if self.do_standard_gravity: # on planet self.velocity = self.velocity + self.standard_grav * dt else: # interplanetary for obj in self.all_objects: if obj is not self: f = self.get_gravitational_force(obj) self.apply_force(f, dt) def apply_force(self, force, dt): print(f"Force:" + str(force)) acceleration = force / self.inertial_mass self.velocity = self.velocity + acceleration * dt def get_gravitational_force(self, other): dis = distance(self.shape.location, other.shape.location) return self.gravitational_constant * self.gravitational_mass * other.gravatational_mass / ( dis * dis) def get_acceleration_force(self, acceleration: float): return acceleration * self.inertial_mass def __repr__(self): return str(self.shape) @property def mass(self): return self.inertial_mass, self.gravitational_mass @mass.setter def mass(self, value): self.inertial_mass = value self.gravitational_mass = value
def vision_vector(self): side, up = self.rotation dx = math.sin(math.radians(side)) * math.cos(math.radians(up)) dz = math.cos(math.radians(side)) * math.cos(math.radians(up)) dy = math.sin(math.radians(up)) return Vector(dx, dy, dz).unit_vector()
def convert_pos(pos): if len(pos) == 3: x, y, z = pos return Vector(-x, y, z) return Vector(*pos)
from Resources.Math import Vector x = (1, 1) y = 1 v = Vector(x, y, 10, None, True) if __name__ == '__main__': print(v) v.test()
class Sphere(Figure): mode = pyglet.gl.GL_TRIANGLES # pyglet.gl.GL_TRIANGLE_STRIP unit_sphere = None detail = 4 def __init__(self, pos: tuple, radius: float, overlay: _TemplateOverlay): if self.unit_sphere is None: self.unit_sphere = self.create_sphere() pos = LowLevel.convert_pos(pos) super(Sphere, self).__init__(overlay) self.location = pos self.radius = radius self.vertices = deepcopy(self.unit_sphere) for i, pt in enumerate(self.vertices): self.vertices[i] = pt * self.radius + pos # self.vertices = self._get_vertices() self._initialize() # not using this def _get_vertices(self, step): ox, oy, oz = self.location verts = [] previous_layer = [] for lat in range(-90, 90, step): is_first_layer = previous_layer == [] current_layer = [] stuff = [] for i, lon in enumerate(range(-180, 181, step)): x = -cos(radians(lat)) * cos(radians(lon)) * self.radius y = sin(radians(lat)) * self.radius z = cos(radians(lat)) * sin(radians(lon)) * self.radius pos = x + ox, y + oy, z + oz current_layer.append(pos) if is_first_layer and i > 0 and False: stuff.append(previous_layer[i]) stuff.append(previous_layer[i - 1]) x = -cos(radians( (lat + step))) * cos(radians(lon)) * self.radius + 0.1 y = sin(radians((lat + step))) * self.radius + 0.1 z = cos(radians( (lat + step))) * sin(radians(lon)) * self.radius + 0.1 pos = x + ox, y + oy, z + oz current_layer.append(pos) if is_first_layer and i > 0 and False: stuff.append(previous_layer[i]) stuff.append(previous_layer[i - 1]) previous_layer = current_layer if not is_first_layer: verts.extend(current_layer) verts.extend(stuff) return verts octahedron_vertices = [ Vector([1.0, 0.0, 0.0]), # 0 Vector([-1.0, 0.0, 0.0]), # 1 Vector([0.0, 1.0, 0.0]), # 2 Vector([0.0, -1.0, 0.0]), # 3 Vector([0.0, 0.0, 1.0]), # 4 Vector([0.0, 0.0, -1.0]) # 5 ] octahedron_triangles = [[ octahedron_vertices[0], octahedron_vertices[4], octahedron_vertices[2] ], [ octahedron_vertices[2], octahedron_vertices[4], octahedron_vertices[1] ], [ octahedron_vertices[1], octahedron_vertices[4], octahedron_vertices[3] ], [ octahedron_vertices[3], octahedron_vertices[4], octahedron_vertices[0] ], [ octahedron_vertices[0], octahedron_vertices[2], octahedron_vertices[5] ], [ octahedron_vertices[2], octahedron_vertices[1], octahedron_vertices[5] ], [ octahedron_vertices[1], octahedron_vertices[3], octahedron_vertices[5] ], [ octahedron_vertices[3], octahedron_vertices[0], octahedron_vertices[5] ]] def divide_triangle(self, triangle, depth): if depth <= 0: return [triangle] vert1, vert2, vert3 = triangle a = (vert1 + vert2) / 2 b = (vert2 + vert3) / 2 c = (vert1 + vert3) / 2 triangle1 = vert1, a, c triangle2 = vert2, a, b triangle3 = vert3, b, c triangle4 = a, b, c triangles = [] triangles.extend(self.divide_triangle(triangle1, depth - 1)) triangles.extend(self.divide_triangle(triangle2, depth - 1)) triangles.extend(self.divide_triangle(triangle3, depth - 1)) triangles.extend(self.divide_triangle(triangle4, depth - 1)) return triangles def inflate(self, triangles): points = [] for triangle in triangles: for vector in triangle: points.append(vector.unit_vector()) return points def create_sphere(self): recurision_level = self.detail triangles = [] for triangle in self.octahedron_triangles: triangles.extend(self.divide_triangle(triangle, recurision_level)) return self.inflate(triangles) def get_nearest_point(self, pt): v = Vector.from_2_points(self.location, pt) v.resize(self.radius) return v + self.location def distance(self, pt: tuple): return super(Sphere, self).distance(pt) - self.radius
def get_nearest_point(self, pt): v = Vector.from_2_points(self.location, pt) v.resize(self.radius) return v + self.location
def __init__(self, *args): self.figures = args self.location = Vector(sum([figure.location[0] for figure in args]) / len(args), \ sum([figure.location[1] for figure in args]) / len(args), \ sum([figure.location[2] for figure in args]) / len(args)) self.rotation = 0, 0, 0