def __init__(self, parent, data): self.parent = parent self.size = 12 * 4 r11, r21, r31, r21, r22, r23, r31, r32, r33, x, y, z = unpack( 'f' * 12, data) self.rot = [r11, r21, r31, r21, r22, r23, r31, r32, r33] self.center = Vec3(x, z, -y)
def avg_tangent(self, faces): tangent = Vec3() for face in faces: tangent = tangent + face.tangent #tangent = tangent / float(len(faces)) #return tangent.normalize() return tangent
def position_at(self, true_anomaly: float) -> Vec3: if self.is_nearly_radial: raise ValueError("True anomaly is nonsensical for radial orbits") radius = self.semilatus_rectum / ( 1 + self.eccentricity * math.cos(true_anomaly)) position = Vec3(radius * math.cos(true_anomaly), radius * math.sin(true_anomaly), 0 * METERS) return self.rot.act_on(position)
def from_cartesian(body: Body, pos: Vec3, vel: Vec3) -> Orbit: mu = body.mu r = pos.length() v = vel.length() energy = v * v / 2 - mu / r angmom = pos.cross(vel) # eccentricity vector = v x h / mu - r/|r| # = [(v.v)r - (r.v)v] - r/|r| # = [(v^2/mu - 1/r)] r - [(r.v)/mu] v ecc = vel.cross(angmom) / mu - pos / r # P = a (1 - e) = mu a (1-e)^2 / mu / (1+e) = h^2 / mu / (1+e) periapsis = angmom.dot(angmom) / mu / (1 + ecc.length()) rot = Quaternion.from_xz_frame(ecc.norm(), angmom.norm()) return Orbit(body, periapsis, energy, rot)
def __init__(self, parent, data): self.parent = parent count = unpack('H', data[:2])[0] data = data[2:] self.vertices = [] for i in range(count): x, y, z = unpack('fff', data[:3 * 4]) data = data[3 * 4:] self.vertices.append(Vec3(x, z, -y)) self.size = 2 + count * 3 * 4 for i, v1 in enumerate(self.vertices): for j, v2 in list(enumerate(self.vertices))[i + 1:]: if v1.x == v2.x and v1.y == v2.y and v1.z == v2.z: self.vertices[j] = v1
def __init__(self, group, v1, v2, v3): self.group = group self.v1 = v1 self.v2 = v2 self.v3 = v3 edge1 = self.v2.pos - self.v1.pos edge2 = self.v3.pos - self.v1.pos edgeuv1 = self.v2.uv - self.v1.uv edgeuv2 = self.v3.uv - self.v2.uv self.normal = edge1.cross(edge2).normalize() cp = edgeuv1.y*edgeuv2.x - edgeuv1.x*edgeuv2.y if cp != 0: self.tangent = ((edge1 * -edgeuv2.y + edge2 * edgeuv1.y) / cp).normalize(); self.bitangent = ((edge1 * -edgeuv2.x + edge2 * edgeuv1.x) / cp).normalize(); else: self.tangent = self.normal.cross(Vec3(0.00001, 0.00001, 1.0)).normalize() self.bitangent = self.normal.cross(self.tangent).normalize()
def open(filename, bones=None): infile = File3Ds.open(filename) objects = [] objs = infile.main.children.editor.children.object if not isinstance(objs, list): #FIXME objs = [objs] for index, obj in enumerate(objs): name = obj.data.name mesh = obj.children.mesh faces = mesh.children.faces vertices = mesh.children.vertices texcoords = mesh.children.texcoords center = mesh.children.matrix.data.center groups = faces.children.smoothgroup.data.groups facelist = [] for i, (i1, i2, i3, flags) in enumerate(faces.data.faces): group = groups[i] pos1 = vertices.data.vertices[i1] pos2 = vertices.data.vertices[i2] pos3 = vertices.data.vertices[i3] uv1 = texcoords.data.texcoords[i1] uv2 = texcoords.data.texcoords[i2] uv3 = texcoords.data.texcoords[i3] v1 = Vertex(i1, pos1, uv1) v2 = Vertex(i2, pos2, uv2) v3 = Vertex(i3, pos3, uv3) facelist.append(Face(group, v1, v2, v3)) objects.append(Object(index, name, center, facelist)) if bones: root = Model.walk(bones, objects) else: root = Object(0, 'root', Vec3(), []) for obj in objects: root.add_child(obj) return Model(root)
def main(): img_width = 256 img_height = 256 max_val = 255 ppm_h = f'P6 {img_width} {img_height} {max_val}\n' j = 0 i = 0 k = 0 image = array.array('B', [0, 0, 63] * img_width * img_height) for j in range(img_height - 1, 0, -1): sys.stderr.write(f'\rScanlines remaining: {j}\n') sys.stderr.flush() if j < 255: k = k + 1 for i in range(0, img_width, 1): index = 3 * (k * img_width + i) col = Vec3([i / (img_width - 1), j / (img_height - 1), 0.25]) ncol = col.multiply_s(255) image[index] = int(ncol.r()) image[index + 1] = int(ncol.g()) image[index + 2] = int(ncol.b()) print(f'{int(ncol.x())} {int(ncol.y())} {int(ncol.z())}\n') sys.stderr.write(f'\nDone.\n') with open("img.ppm", 'wb') as f: f.write(bytearray(ppm_h, 'ascii')) image.tofile(f)
def get_triangle(self, index): triangle = self.triangles[index] v1 = self.vertices[triangle.v1] v1 = v1.x, v1.y, v1.z n1 = triangle.n1 n1 = n1.x, n1.y, n1.z uv1 = triangle.s1, triangle.t1 v2 = self.vertices[triangle.v2] v2 = v2.x, v2.y, v2.z n2 = triangle.n2 n2 = n2.x, n2.y, n2.z uv2 = triangle.s2, triangle.t2 v3 = self.vertices[triangle.v3] v3 = v3.x, v3.y, v3.z n3 = triangle.n3 n3 = n3.x, n3.y, n3.z uv3 = triangle.s3, triangle.t3 t1 = self.get_tangent(Vec3(*n1), Vec3(*v2) - Vec3(*v1), Vec3(*v3) - Vec3(*v1), Vec2(*uv2) - Vec2(*uv1), Vec2(*uv3) - Vec2(*uv1)) t2 = self.get_tangent(Vec3(*n2), Vec3(*v3) - Vec3(*v2), Vec3(*v1) - Vec3(*v2), Vec2(*uv3) - Vec2(*uv2), Vec2(*uv1) - Vec2(*uv2)) t3 = self.get_tangent(Vec3(*n3), Vec3(*v1) - Vec3(*v3), Vec3(*v2) - Vec3(*v3), Vec2(*uv1) - Vec2(*uv3), Vec2(*uv2) - Vec2(*uv3)) return [ (v1, n1, uv1, t1), (v2, n2, uv2, t2), (v3, n3, uv3, t3), ]
def avg_normal(self, faces): normal = Vec3() for face in faces: normal = normal + face.normal normal = normal / float(len(faces)) return normal.normalize()
def get_local_offset(self): if self.parent: return (self.center - self.parent.center)*scale else: return Vec3(0.0, 0.0, 0.0)
def main(): aspect_ratio = 16 / 9 img_width = 400 img_height = int(img_width / aspect_ratio) max_val = 255 ppm_h = f'P6 {img_width} {img_height} {max_val}\n' image = array.array('B', [217, 232, 255] * img_width * img_height) vp_height = 2.0 vp_width = round(aspect_ratio * vp_height) focal = 1.0 origin = Vec3([0, 0, 0]) horizontal = Vec3([vp_width, 0, 0]) vertical = Vec3([0, vp_height, 0]) hlc = horizontal.multiply_s(0.5) vlc = vertical.multiply_s(0.5) fl = Vec3([0, 0, focal]) llc = origin.sub( hlc) #origin - horizontal/2 - vertical/2 - vec3(0, 0, focal_length); llc = llc.sub(vlc) llc = llc.sub(fl) sphere = [255, 0, 0] print(f'P6 {img_width} {img_height} {max_val}\n') print(vp_width) k = 0 for j in range(img_height - 1, 0, -1): sys.stderr.write(f'\rScanlines remaining: {j}\n') sys.stderr.flush() if j < 255: k = k + 1 for i in range(0, img_width, 1): index = 3 * (k * img_width + i) col1 = [1.0, 1.0, 1.0] col2 = [0.5, 0.7, 1.0] u = i / (img_width - 1) v = j / (img_height - 1) r = llc.add(horizontal.multiply_s(u)).add( vertical.multiply_s(v)).sub(origin) center = Vec3([0, 0, -1]) oc = origin.sub(center) da = r.dot_p(r) db = oc.dot_p(r) db = 2.0 * db dc = oc.dot_p(oc) dc = dc - 0.5 * 0.5 discrim = (db**2) - 4 * da * dc if discrim < 0: t = -1.0 else: t = (-db - math.sqrt(discrim)) / (2.0 * da) # Red Circle if t > 0: N = r.multiply_s(t) N = N.sub(center) N = N.unitvec() p = Vec3([1, 1, 1]) rayN = N.add(p) rayN = rayN.multiply_s(0.5) image[index] = round(255.0 * rayN.x()) image[index + 1] = round(255.0 * rayN.y()) image[index + 2] = round(255.0 * rayN.z()) else: unit_direction = r.unitvec() t = 0.5 * (unit_direction.y() + 1.0) l = 0 for x in col1: col1[l] = (1.0 - t) * x l = l + 1 m = 0 for y in col2: col2[m] = t * y m = m + 1 ray_color = [x + y for x, y in zip(col1, col2)] retray = Vec3(ray_color) rayr = round(255 * retray.x()) rayg = round(255 * retray.y()) rayb = round(255 * retray.z()) image[index] = rayr image[index + 1] = rayg image[index + 2] = rayb print(image[index], image[index + 1], image[index + 2]) sys.stderr.write(f'\nDone.\n') with open("rayimg.ppm", 'wb') as f: f.write(bytearray(ppm_h, 'ascii')) image.tofile(f)