extract obj_props extract $ make_voxel_partial = ( colors: [@color], groups: [@group], group: @group, side: @number, offset, layer, d, vert, additional_groups, scaling, ) { left = groups[0] middle = groups[1] right = groups[2] left_color = colors[0] right_color = colors[1] add(obj { OBJ_ID: 211, X: offset[0], Y: offset[1], COLOR: right_color, Z_ORDER: -1 + layer, GROUPS: [right, group] + additional_groups, SCALING: scaling + 0.01, }) for y in [-1, 1] { let positions = [ [(30 / 4) * d, (30 / 4) * y], [- (30 / 4) * side * d, (30 / 4) * y] ] if vert { positions = positions[:, :-1:] } add(obj { OBJ_ID: 211, X: offset[0] + positions[0][0] * scaling, Y: offset[1] + positions[0][1] * scaling, COLOR: left_color, Z_ORDER: 1 + layer, GROUPS: [middle, group] + additional_groups, SCALING: 0.5 * scaling + 0.01, }) add(obj { OBJ_ID: 211, X: offset[0] + positions[1][0] * scaling, Y: offset[1] + positions[1][1] * scaling, COLOR: left_color, Z_ORDER: 1 + layer, GROUPS: [left, group] + additional_groups, SCALING: 0.5 * scaling + 0.01, }) } } normalize = (v: [@number]) { len = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]) return [v[0] / len, v[1] / len, v[2] / len] } dot = (a: [@number], b: [@number]) { return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] } lights = [ { dir: normalize([-1, 1, 0.8]), col: [255 * 1, 255 * 1, 200 * 1], }, { dir: normalize([0.5, -1, 1]), col: [30 * 0.3, 30 * 0.3, 255 * 0.3], }, ] ambient = [10, 10, 50] BG.set(0, 0, 0) get_lighting = (normal: [@number], variant) { metal = [200, 200, 200] shine = 4 normal = normalize([normal[0] + 0.01, normal[1] - 0.01, normal[2] - 0.01]) if variant == 0 else normalize([normal[0] - 0.01, normal[1] + 0.01, normal[2] + 0.01]) fac = 2 let lighting = [0, 0, 0] for light in lights { extract light diffuse = max(dot(dir, normal), 0) refl = [dir[0] - fac * diffuse * normal[0], dir[1] - fac * diffuse * normal[1], dir[2] - fac * diffuse * normal[2]] spec = max(dot(refl, [0, 0, -1]), 0) damped_spec = spec ^ shine lighting[0] += damped_spec * col[0] / 255 lighting[1] += damped_spec * col[1] / 255 lighting[2] += damped_spec * col[2] / 255 } return [ (metal[0] / 255 * ambient[0] / 255 + lighting[0] * (metal[0] / 255 + 1)) * 255, (metal[1] / 255 * ambient[1] / 255 + lighting[1] * (metal[1] / 255 + 1)) * 255, (metal[2] / 255 * ambient[2] / 255 + lighting[2] * (metal[2] / 255 + 1)) * 255, ] } type @voxel impl @voxel { new: (colors, groups: [@group], part_2: @group, direction, vert, scaling) { assert(groups.length == 3) part_2.toggle_off() new_face_normal = switch [direction, vert] { case [1, false]: [1, 0, 0], case [-1, false]: [-1, 0, 0], case [1, true]: [0, 1, 0], case [-1, true]: [0, -1, 0], } front_color_variant1 = get_lighting([0, 0, 1], 0) side_color_variant1 = get_lighting(new_face_normal, 0) front_color_variant2 = get_lighting([0, 0, 1], 1) side_color_variant2 = get_lighting(new_face_normal, 1) colors[0][0].set(front_color_variant1[0], front_color_variant1[1], front_color_variant1[2]) colors[0][1].set(side_color_variant1[0], side_color_variant1[1], side_color_variant1[2]) colors[1][0].set(front_color_variant2[0], front_color_variant2[1], front_color_variant2[2]) colors[1][1].set(side_color_variant2[0], side_color_variant2[1], side_color_variant2[2]) color1_anim_variant1 = [ front_color_variant1, get_lighting(normalize([-new_face_normal[0], -new_face_normal[1], -new_face_normal[2] + 1]), 0), get_lighting([-new_face_normal[0], -new_face_normal[1], -new_face_normal[2]], 0), ] color2_anim_variant1 = [ side_color_variant1, get_lighting(normalize([new_face_normal[0], new_face_normal[1], new_face_normal[2] + 1]), 0), front_color_variant1 ] color1_anim_variant2 = [ front_color_variant2, get_lighting(normalize([-new_face_normal[0], -new_face_normal[1], -new_face_normal[2] + 1]), 1), get_lighting([-new_face_normal[0], -new_face_normal[1], -new_face_normal[2]], 1), ] color2_anim_variant2 = [ side_color_variant2, get_lighting(normalize([new_face_normal[0], new_face_normal[1], new_face_normal[2] + 1]), 1), front_color_variant2 ] return @voxel::{ colors, groups, part_2, direction, vert, color1_anim_variant1, color2_anim_variant1, color1_anim_variant2, color2_anim_variant2, scaling } }, make: (self, offset, z_layer, additional_groups, first_variant, second_variant) { left = self.groups[0] middle = self.groups[1] right = self.groups[2] make_voxel_partial( [self.colors[first_variant][0], self.colors[second_variant][1]], [left, middle, right], 0g, 1, offset, 0 + z_layer * 4, self.direction, self.vert, additional_groups, self.scaling, ) make_voxel_partial( [self.colors[second_variant][1], self.colors[first_variant][0]], [right, middle, left], self.part_2, -1, offset, 2 + z_layer * 4, self.direction, self.vert, additional_groups, self.scaling, ) }, animate: (self, t) { left = self.groups[0] middle = self.groups[1] right = self.groups[2] left_color1 = self.colors[0][0] right_color1 = self.colors[0][1] left_color2 = self.colors[1][0] right_color2 = self.colors[1][1] // animation //while_loop(() => true, () { -> left_color1.set(self.color1_anim_variant1[1][0], self.color1_anim_variant1[1][1], self.color1_anim_variant1[1][2], t) -> right_color1.set(self.color2_anim_variant1[1][0], self.color2_anim_variant1[1][1], self.color2_anim_variant1[1][2], t) -> left_color2.set(self.color1_anim_variant2[1][0], self.color1_anim_variant2[1][1], self.color1_anim_variant2[1][2], t) -> right_color2.set(self.color2_anim_variant2[1][0], self.color2_anim_variant2[1][1], self.color2_anim_variant2[1][2], t) if self.vert { -> left.move(0, -3 * self.direction * self.scaling, t, easing = SINE_OUT) -> right.move(0, 3 * self.direction * self.scaling, t, easing = SINE_OUT) -> middle.move(0, -5 * self.direction * self.scaling, t) } else { -> left.move(-3 * self.direction * self.scaling, 0, t, easing = SINE_OUT) -> right.move(3 * self.direction * self.scaling, 0, t, easing = SINE_OUT) -> middle.move(-5 * self.direction * self.scaling, 0, t) } wait(t) self.part_2.toggle_on() -> left_color1.set(self.color1_anim_variant1[2][0], self.color1_anim_variant1[2][1], self.color1_anim_variant1[2][2], t) -> right_color1.set(self.color2_anim_variant1[2][0], self.color2_anim_variant1[2][1], self.color2_anim_variant1[2][2], t) -> left_color2.set(self.color1_anim_variant2[2][0], self.color1_anim_variant2[2][1], self.color1_anim_variant2[2][2], t) -> right_color2.set(self.color2_anim_variant2[2][0], self.color2_anim_variant2[2][1], self.color2_anim_variant2[2][2], t) if self.vert { -> left.move(0, 3 * self.direction * self.scaling, t, easing = SINE_IN) -> right.move(0, -3 * self.direction * self.scaling, t, easing = SINE_IN) -> middle.move(0, 5 * self.direction * self.scaling) -> middle.move(0, -5 * self.direction * self.scaling, t) } else { -> left.move(3 * self.direction * self.scaling, 0, t, easing = SINE_IN) -> right.move(-3 * self.direction * self.scaling, 0, t, easing = SINE_IN) -> middle.move(5 * self.direction * self.scaling, 0) -> middle.move(-5 * self.direction * self.scaling, 0, t) } wait(t) // reset // -> left_color1.set(self.color1_anim_variant1[0][0], self.color1_anim_variant1[0][1], self.color1_anim_variant1[0][2], t) // -> right_color1.set(self.color2_anim_variant1[0][0], self.color2_anim_variant1[0][1], self.color2_anim_variant1[0][2], t) // -> left_color2.set(self.color1_anim_variant2[0][0], self.color1_anim_variant2[0][1], self.color1_anim_variant2[0][2], t) // -> right_color2.set(self.color2_anim_variant2[0][0], self.color2_anim_variant2[0][1], self.color2_anim_variant2[0][2], t) // if self.vert { // -> middle.move(0, 5 * self.direction * self.scaling) // } else { // -> middle.move(5 * self.direction * self.scaling, 0) // } // -> ref_grid_main.rotate(ref_grid_center, (-90 if self.vert else 90), 0) // self.part_2.toggle_off() //}) } }