def project_ray(self, px, py): # cam_view = (self.center - self.location).normalize() # self.cam_h = cam_view.cross(self.up).normalize() # self.cam_v = -1 * cam_view.cross(self.cam_h).normalize() view = -Vector3(*self.matrix[8:11]) h = Vector3(*self.matrix[0:3]) v = Vector3(*self.matrix[4:7]) half_v = math.tan(self.fov) * 0.5 * self.clipnear win = self.window.get_size() aspect = win[0] / float(win[1]) half_h = half_v * aspect # mouse to ndc nx = (px - win[0] * 0.5) / (win[0] * 0.5) ny = (py - win[1] * 0.5) / (win[1] * 0.5) h *= half_h v *= half_v click = self.location + (view * self.clipnear) + (nx * h) + (ny * v) dir = (click - self.location).normalize() return Ray3(click, dir)
def func(x,y,z): r = Vector3(x,y,z) s = sphere(r, j) g = gyroid(r) t = torus(r - Vector3(0,0,2)) c = cube(r, Vector3(1,1,1)) return smin(s, t)
def get_targets(self, lookahead=10, range=30): """Get a dictionary of potential targets on either side. We look for targets that are within a distance of range units and up to lookahead units ahead or astern of us. """ if not self.world: return [] targets = { 'port': [], 'starboard': [] } m = self.get_matrix() forward = m * Vector3(0, 0, -1) port = m * Vector3(1, 0, 0) range2 = range * range for o in self.world.objects: if isinstance(o, Ship) and o is not self: rel = o.pos - self.pos if abs(rel.dot(forward)) < lookahead and rel.magnitude_squared() < range2: side = 'port' if rel.dot(port) > 0 else 'starboard' targets[side].append(o) return targets
def __init__(self, position=None, forward=None, velocity=None): super(Movement, self).__init__(position, forward) if velocity: self.velocity = velocity else: self.velocity = Vector3() self.acceleration = Vector3()
def inverse_spherical_projection(r, n, t=Vector3(0, 0, 0), blend=1.0): "lines parrallel to n are mapped to radial lines through the origin" d = r.dot(n) mag = r.magnitude() mu = 0 if d == 0 else abs(d) / mag new_r = r / mu if mu != 0 else Vector3(float("inf") * 3) new_r -= t return (new_r * blend) + r * (1.0 - blend)
def draw_coords(mtx, size, width=1): x = Vector3(size, 0, 0) y = Vector3(0, size, 0) z = Vector3(0, 0, size) orig = mtx[12:15] draw_line(orig, orig + mtx * x, (1, 0, 0), width) draw_line(orig, orig + mtx * y, (0, 1, 0), width) draw_line(orig, orig + mtx * z, (0, 0, 1), width)
def __init__(self, center=Point3(0, 0, 0), normal=Vector3(0, 1, 0), size=1000.0, divisions=1, material=None): material = material or Material(name='plane_material') normal = normal.normalized() up = Vector3(0, 1, 0) x = up.cross(normal) if x.magnitude_squared() < 1e-3: up = Vector3(0, 0, 1) x = up.cross(normal) x = x.normalized() y = x.cross(normal) sx = x * float(size) / divisions sy = y * float(size) / divisions ns = [] uvs = [] vs = [] y = -sy * divisions * 0.5 for j in xrange(divisions + 1): x = -sx * divisions * 0.5 v = j / float(divisions) for i in xrange(divisions + 1): vs.extend(center + x + y) ns.extend(normal) u = i / float(divisions) uvs.extend((u, v)) x += sx y += sy indices = [] def idx(i, j): indices.append(j * (divisions + 1) + i) # TODO: Use quad strips and save some index memory for j in xrange(divisions): for i in xrange(divisions): idx(i, j + 1) idx(i + 1, j + 1) idx(i + 1, j) idx(i, j) super(Plane, self).__init__(GL_QUADS, vertices=vs, normals=ns, texcoords=uvs, indices=indices, material=material, name=repr(self))
def normal(a, b, c): n = vector_product(b - a, c - a) m = mag(n) return n from euclid import Vector3 a = Vector3(1, 2, 3) b = Vector3(2, 3, 4) print vector_product(a, b)
def update(self, dt): self.t += dt if self.alive: self.helm.update(dt) self.sail.update(dt) self.update_masts(self.sail.current) # damp roll self.roll *= pow(0.6, dt) # Compute some bobbing motion rollmoment = 0.05 * sin(self.t) pitch = 0.02 * sin(0.31 * self.t) # Compute the forward vector from the curent heading q = self.get_quaternion() forward = q * Vector3(0, 0, 1) angular_velocity = self.helm.current * min(forward.dot(self.vel), 2) * 0.03 angle_to_wind = map_angle(self.world.wind_angle - self.angle) sail_power = get_sail_power(angle_to_wind) heeling_moment = get_heeling_moment(angle_to_wind) rollmoment += angular_velocity * 0.5 # lean over from centrifugal force of turn rollmoment -= heeling_moment * 0.05 * self.sail.current # heel from wind force # Update ship angle and position self.angle = map_angle(self.angle + angular_velocity * dt) accel = forward * self.sail.current * sail_power * 0.5 * dt self.vel += accel self.vel *= pow(0.7, dt) # Drag self.pos += self.vel * dt # Float if self.alive: self.pos += Vector3(0, -0.5, 0) * self.pos.y * dt else: self.pos += Vector3(0, -1, 0) * dt self.roll += rollmoment * dt # Apply ship angle and position to model self.rot = ( q * Quaternion.new_rotate_axis(pitch, Vector3(1, 0, 0)) * Quaternion.new_rotate_axis(self.roll, Vector3(0, 0, 1)) ) rotangle, (rotx, roty, rotz) = self.rot.get_angle_axis() self.model.rotation = (degrees(rotangle), rotx, roty, rotz) self.model.pos = self.pos # Adjust sail angle to wind direction if self.alive: sail_angle = get_sail_setting(angle_to_wind) for sail in self.model.nodes[1:]: sail.rotation = degrees(sail_angle), 0, 1, 0
def reproject(self, rot): self.prj = Matrix4() self.prj.scale(self.tile_size, self.tile_size, 1.0) self.prj.rotate_axis(math.radians(60), Vector3(1, 0, 0)) self.prj.rotate_axis(rot, Vector3(0, 0, 1)) self.inv_prj = Matrix4() self.inv_prj.scale(self.tile_size, self.tile_size / 2, 1.0) self.inv_prj.rotate_axis(rot, Vector3(0, 0, 1)) self.inv_prj = self.inv_prj.inverse()
def __init__(self, scene): self.batch = pyglet.graphics.Batch() self.translate = Parameter(default=Vector3(0,0,0)) self.rotate= Parameter(default=Vector3(0,0,0)) self.scale= Parameter(default=Vector3(1,1,1)) self.shader = Shader(self.vertex_shader, self.fragment_shader) scene.objects.append( self )
def render(self): shape = shapes.Block.get(self.side, self.side, self.side, 1, 1, 1) if self.health > 1: tmp_color = Vector3(0, 0, 0) tmp_color.x = self.color.x * (self.health / 100.0) tmp_color.y = self.color.y * (self.health / 100.0) tmp_color.z = self.color.z * (self.health / 100.0) shape.draw(self.position, self.forward, color=tmp_color) else: shape.draw(self.position, self.forward, color=Vector3(1, 1, 1)) if settings.DISPLAY_BBOXES: bbox = shapes.BBox.get(self.aabb) bbox.draw(self.position)
def _calculateSunVector(self): """Calculate sun vector for this sun.""" zAxis = Vector3(0., 0., -1.) xAxis = Vector3(1., 0., 0.) northVector = Vector3(0., 1., 0.) # rotate north vector based on azimuth, altitude, and north _sunvector = northVector \ .rotate_around(xAxis, self.altitudeInRadians) \ .rotate_around(zAxis, self.azimuthInRadians) \ .rotate_around(zAxis, math.radians(-1 * self.northAngle)) _sunvector.normalize().flip() self._sunVector = _sunvector
class WakeEmitter(object): group = wake_particles # position, velocity, rate for each emitter emitter_positions = [ (Point3(1.3, 0.2, 3), Vector3(0.5, 0, 0), 5), # port bow (Point3(-1.3, 0.2, 3), Vector3(-0.5, 0, 0), 5), # starboard bow (Point3(0, 0.2, -3), Vector3(0, 0, 0), 20), # stern ] def __init__(self, ship): self.ship = ship self.emitters = [ StaticEmitter(template=Particle( position=tuple(p), velocity=tuple(v), size=(0.2, 0.2, 0.0), color=(1, 1, 1, 0.2), ), deviation=Particle( position=(0.02, 0.0, 0.02) if i < 2 else (0.2, 0.0, 0.2), size=(0.0, 0.07, 0.0), velocity=(0.04, 0.0, 0.04), ), rate=5 if i < 2 else 20) for i, (p, v, rate) in enumerate(self.emitter_positions) ] def start(self): """Bind all emitters to their groups so that they will emit""" wake_particles.bind_controller(*self.emitters) def stop(self): """Unbind all emitters from their groups""" for e in self.emitters: wake_particles.unbind_controller(e) def update(self): """Update the emitters.""" m = self.ship.get_matrix() for e, (p, v, r) in zip(self.emitters, self.emitter_positions): px, _, pz = m * p e.template.position = px, 0.1, pz vx, _, vz = m * v e.template.velocity = vx, 0.0, vz e.rate = self.ship.vel.magnitude() * r
def create_scene(self): """Initialise the scene with static objects.""" self.scene = Scene(ambient=(0.2, 0.2, 0.2, 1.0), ) for m in Ship.MODELS: self.scene.prepare_model(m) # Add the particle system self.scene.add(particles) # Sun self.scene.add( Sunlight( direction=Vector3(0.82, 0.31, 0.48), colour=(1.0, 0.85, 0.6, 1.0), intensity=1, )) # Sky dome self.skydome = ModelNode(skydome, rotation=(59, 0, 1, 0)) self.scene.add(self.skydome) # Sea self.sea = SeaNode(sea_model) self.sea.shader = sea_shader self.scene.add(self.sea)
def test_line_sphere_intersection5(): """Point of intersection if we hit the sphere at an oblique angle.""" s = Sphere() l = LineSegment(Point3(0.5, 0, -5), Vector3(0, 0, 5)) i = l.first_intersection(s) assert i is not None eq_(i[0], 5 - math.sqrt(0.75))
def render(self): shape = shapes.Torus.get(self.radius, self.inner_radius, self.slices, self.inner_slices) if self.down_gates < 4: shape.draw(self.position, self.forward, color=self.color) else: shape.draw(self.position, self.forward, color=Vector3(0, 0, 0))
def __init__(self, position, forward, up, length): self.length = length self.forward = forward self.position = position self.up = up self.gfx = shapes.GrapplingHook(length, 12) self.connection = Vector3(0.0, 0.0, 0.0)
def add_items(self, world, blocks, room_color, wall_color): for y, block in enumerate(blocks): for z, line in enumerate(block): for x, char in enumerate(line): position = Vector3(x, y, z) if char in ' ~': pass elif char == '#': world.add( Wall( size=(1, 1, 1), position=position, color=wall_color, )) elif char == 's': self.gameloop.player.position = position elif char == 'e': world.add(Exit(position)) elif char == 'c': world.add( self.gameloop.camera, position=position, ) else: logging.error('unknown char %c loading level %d' % (char, self.number))
def add(self, item, position=None): if position is not None: if not isinstance(position, Vector3): position = Vector3(*position) item.position = position self.items[item.id] = item self.item_added.fire(item)
def test_line_sphere_intersection4(): """Point of intersection if we start inside the sphere.""" s = Sphere() l = LineSegment(Point3(), Vector3(0, 0, 2)) i = l.first_intersection(s) assert i is not None eq_(i, (0, Point3()))
def __init__(self, direction=Vector3(0, 0, 0), colour=(1, 1, 1, 1), intensity=5): self.direction = direction self._colour = colour self.intensity = intensity
def __init__(self, vertices, faces, colors): # sanity checks len_verts = len(vertices) for face in faces: assert len(face) >= 3 for index in face: assert 0 <= index < len_verts # convert vertices from tuple to Vector3 if required if len(vertices) > 0 and not isinstance(vertices[0], Vector3): vertices = [Vector3(*v) for v in vertices] # if given one color instead of a sequence of them, # then construct a sequence if identical colors out of it if (isinstance(colors, tuple) and len(colors) == 4 and isinstance(colors[0], int)): colors = Color(*colors) if isinstance(colors, Color): colors = repeat(colors) self.vertices = vertices self.faces = [ Face(face, color, vertices) for face, color in zip(faces, colors) ]
def __init__(self, position=None, forward=None, up=None): super(Position, self).__init__() if position: self.position = position if forward: self.forward = forward upcross = up and up or Vector3(0, 1, 0) self.right = self.forward.cross(upcross).normalized() self.up = -self.forward.cross(self.right).normalized()
def _bound_volume(self): """Compute an untransformed bounding volume for the body's shapes.""" centroid = (sum((s.centre for s in self._shapes), Vector3(0, 0, 0)) * (1.0 / len(self._shapes))) r = 0.0 for s in self._shapes: r = max(r, (s.centre - centroid).magnitude() + s.radius) return Sphere(centroid, r)
def render(self): sphere = shapes.Sphere.get(1, 12) cube = shapes.Cube.get(5, 12) color = (0, 0, 0) if self.dead else self.team.rgb # TODO: this shouldn't be necessary glDisable(GL_CULL_FACE) cube.draw_rotated(self.position, self.forward, self.up, color=color) tmp_color = Vector3(*color) tmp_color = tmp_color * Vector3(0.5, 0.5, 0.5) + Vector3(0.5, 0.5, 0.5) sphere.draw(self.position + self.forward * 3, self.forward, color=tmp_color) glEnable(GL_CULL_FACE) if DISPLAY_BBOXES: # bbox = shapes.BBox.get(self.oobb) # bbox.draw(self.position) bbox = shapes.BBox.get(self.aabb) bbox.draw(self.position)
def test_body_collision(): """We can get a separation vector if two bodies collide.""" shapes = [Sphere(Point3(0, 0, 0), 2)] b1 = Body(Positionable(pos=Point3(1, 0, 0)), shapes) b2 = Body(Positionable(pos=Point3(4.75, 0, 0)), shapes) col = b1.collide(b2) assert col is not None eq_(col, Vector3(0.25, 0, 0))
def spherical_projection(r, n, t=Vector3(0, 0, 0), blend=1.0): "lines parrallel to n are mapped to radial lines through the origin" r -= t d = r.dot(n) mag = r.magnitude() mu = 0.0 if d == 0 else abs(d) / mag new_r = r * mu return (new_r * blend) + r * (1.0 - blend)
def spawn(self, dt=None, set_health=True): point = self._determine_spawn(self.team) if point is not None: #will return None if all the gates have been destroyed self.position, self.forward, self.up = point.position + point.forward * 5, point.forward, point.up self.velocity = Vector3(0,0,0) if set_health: self.health, self.dead = 100, False else: clock.schedule_once(self.spawn, 5)
def isClose(self, obj): if (self.getPos()-obj.getPos()).magnitude_squared()>=0.22: return False perm_att=self.getAttitude() temp_att=obj.getAttitude().conjugated() diff=(perm_att*temp_att) #print 'isClose: '+str(Vector3(diff.x, diff.y, diff.z).magnitude_squared()) return Vector3(diff.x, diff.y, diff.z).magnitude_squared()<0.0001