def mandelboxSDF(pos, scale): orbitTrap = glm.vec4(10000) iterations = 17 #0 to 300 colorIterations = 3 #0 to 300 minRad2 = 0.25 #0.0 to 2.0 scale = glm.vec4(scale, scale, scale, abs(scale)) / minRad2 rotVector = glm.vec3(1, 1, 1) #(0, 0, 0) to (1, 1, 1) rotAngle = 0 #0 to 180(?) rot = rotationMatrix3(glm.normalize(rotVector), rotAngle) absScalem1 = abs(scale - 1) absScaleRaisedTo1mIters = pow(abs(scale), float(1 - iterations)) p = pos w = 1 p0 = p w0 = w for i in range(iterations): p *= rot p = glm.clamp(p, -1, 1) * 2 - p r2 = glm.dot(p, p) if i < colorIterations: orbitTrap = glm.min(orbitTrap, abs(glm.vec4(p, r2))) p *= glm.clamp(glm.max(minRad2 / r2, minRad2), 0, 1) w *= glm.clamp(glm.max(minRad2 / r2, minRad2), 0, 1) p = p * glm.vec3(scale[0], scale[1], scale[2]) + p0 w = w * scale[3] + w0 if r2 > 1000: break return (glm.length(p) - absScalem1[3]) / w - absScaleRaisedTo1mIters[3]
def cylinderSDF(p, h, r): inOutRadius = glm.length(p.xy) - r inOutHeight = glm.abs(p.z) - h / 2.0 insideDistance = glm.min(glm.max(inOutRadius, inOutHeight), 0.0) outsideDistance = glm.length( glm.max(glm.vec2(inOutRadius, inOutHeight), 0.0)) return insideDistance + outsideDistance
def union_update(self, other) -> 'self': ''' extend the volume of the current box to bound the given point or box ''' if isinstance(other, (dvec3, fvec3)): self.min = glm.min(self.min, other) self.max = glm.max(self.max, other) elif isinstance(other, Box): self.min = glm.min(self.min, other.min) self.max = glm.max(self.max, other.max) else: raise TypeError('unable to integrate {}'.format(type(other))) return self
def intersection_update(self, other) -> 'self': ''' reduce the volume of the current box to the intersection between the 2 boxes ''' if isinstance(other, Box): self.min = glm.max(self.min, other.min) self.max = glm.min(self.max, other.max) else: raise TypeError('expected a Box'.format(type(other))) return self
def intersection(self, other): ''' intersection area between the 2 boxes ''' if isinstance(other, Box): self.min = glm.max(self.min, other.min) self.max = glm.min(self.max, other.max) else: raise TypeError('expected a Box'.format(type(other))) return self
def compute_plane_minmax(position, far_screen, split): pm = glm.mat4(position, position, position, position) s0 = (far_screen - pm) * split + pm min0 = glm.min(s0[0], s0[1], s0[2], s0[3]) max0 = glm.max(s0[0], s0[1], s0[2], s0[3]) return min0, max0
def union(self, other) -> 'Box': ''' return a box containing the current and the given box (or point) Example: >>> Box(vec2(1,2), vec2(2,3)) .union(vec3(1,4)) Box(vec2(1,2), vec2(2,4)) >>> Box(vec2(1,2), vec2(2,3)) .union(Box(vec3(1,-4), vec3(2,8))) Box(vec2(1,-4), vec3(2,8)) ''' if isinstance(other, (dvec3, fvec3)): return Box(glm.min(self.min, other), glm.max(self.max, other)) elif isinstance(other, Box): return Box(glm.min(self.min, other.min), glm.max(self.max, other.max)) else: raise TypeError('unable to integrate {}'.format(type(other)))
def intersection(self, other) -> 'Box': ''' return a box for the volume common to the current and the given box Example: >>> Box(vec2(-1,2), vec2(2,3)) .intersection(Box(vec3(1,-4), vec3(2,8))) Box(vec2(1,2), vec3(2,3)) ''' if isinstance(other, Box): return Box(glm.max(self.min, other.min), glm.min(self.max, other.max)) else: raise TypeError('expected a Box'.format(type(other)))
def update(self): w = self.window LEFT = glfw.get_key(w, glfw.KEY_A) or glfw.get_key(w, glfw.KEY_LEFT) FORWARD = glfw.get_key(w, glfw.KEY_W) or glfw.get_key(w, glfw.KEY_UP) RIGHT = glfw.get_key(w, glfw.KEY_D) or glfw.get_key(w, glfw.KEY_RIGHT) BACK = glfw.get_key(w, glfw.KEY_S) or glfw.get_key(w, glfw.KEY_DOWN) UP = glfw.get_key(w, glfw.KEY_E) or glfw.get_key(w, glfw.KEY_PAGE_UP) DOWN = glfw.get_key(w, glfw.KEY_Q) or glfw.get_key( w, glfw.KEY_PAGE_DOWN) SPEED = 0.1 LEFT *= glm.vec3(-1.0, +0.0, +0.0) * SPEED FORWARD *= glm.vec3(+0.0, -1.0, +0.0) * SPEED RIGHT *= glm.vec3(+1.0, +0.0, +0.0) * SPEED BACK *= glm.vec3(+0.0, +1.0, +0.0) * SPEED UP *= glm.vec3(+0.0, +0.0, +1.0) * SPEED DOWN *= glm.vec3(+0.0, +0.0, -1.0) * SPEED self.movement += LEFT + FORWARD + RIGHT + BACK + UP + DOWN self.movement.y = glm.max(glm.min(self.movement.y, 100.0), -100.0) self.movement.z = glm.max(glm.min(self.movement.z, 30.0), -300.0) self.update_uniforms({ "u_movement": (self.movement.x, self.movement.y, self.movement.z) })
def boxSDF(p, size): d = glm.abs(p) - (size / 2.0) insideDistance = glm.min(glm.max(d.x, glm.max(d.y, d.z)), 0.0) outsideDistance = glm.length(glm.max(d, 0.0)) return insideDistance + outsideDistance
def differenceSDF(distA, distB): return glm.max(distA, -distB)
def intersectSDF(distA, distB): return glm.max(distA, distB)
def intersection(self, other): return AABB(glm.min(self.max, other.max), glm.max(self.min, other.min))
def merge(self, other): return AABB(glm.min(self.min, other.min), glm.max(self.max, other.max))
def prepare_render_shadowmap( self, shadowmap_index, shadowmap_layer, shader, camera_position, camera_screen ): si = shadowmap_index prefix = self.get_uniform_name('') view = glm.lookAt(self.position, self.position - self.front, self.up) if self.type == 'directional': position = view * camera_position screen = view * camera_screen min0, max0 = compute_plane_minmax( position, screen, self.shadowmaps_depths[si] ) min1, max1 = compute_plane_minmax( position, screen, self.shadowmaps_depths[si+1] ) min2 = glm.min(min0, min1) max2 = glm.max(max0, max1) projection = glm.ortho( round(min2.x), round(max2.x), round(min2.y), round(max2.y), self.snear, self.sfar ) scale = max(max2.x - min2.x, max2.y - min2.y) shader._members[prefix + 'scale'].value = scale elif self.type == 'point': projection = glm.perspective( math.pi / 2, 1., self.snear, self.sfar ) else: projection = glm.perspective( 2 * self.outer_cone, 1., self.snear, self.sfar ) self._view = view self._proj = projection pv = projection * view shader._members[prefix + 'shadowmap_textures[%s].layer' % si].value = shadowmap_layer shader._members[prefix + 'shadowmap_textures[%s].depth' % si].value = self.shadowmaps_depths[si] shader._members[prefix + 'shadowmap_textures[%s].projection' % si].write(pv) shader._members[prefix + 'shadowmap_projection'].write(pv)