From e4506bd9f0d824ece6f3cdd97b8d4263d5ab74fe Mon Sep 17 00:00:00 2001 From: Quinn Date: Tue, 27 Aug 2024 21:54:56 -0400 Subject: [PATCH] Got a single frame exporting correctly --- lib/Animator/Animation.h | 28 ++++++-- platformio.ini | 21 +++--- src/main.cpp | 3 +- tools/animation-tools/.gitignore | 3 +- tools/animation-tools/AnimationExporter.py | 74 ++++++++++++++++++++++ tools/animation-tools/README.md | 31 +++++++++ tools/animation-tools/Shapes.py | 6 ++ tools/animation-tools/animation-tool.py | 13 +++- 8 files changed, 161 insertions(+), 18 deletions(-) create mode 100644 tools/animation-tools/AnimationExporter.py create mode 100644 tools/animation-tools/README.md diff --git a/lib/Animator/Animation.h b/lib/Animator/Animation.h index 4adfa02..6f78b7a 100644 --- a/lib/Animator/Animation.h +++ b/lib/Animator/Animation.h @@ -13,7 +13,7 @@ namespace AnimationHelpers{ V3D cyan{0,255,255}; V3D magenta{255,0,255}; - Cell CreateCell(float x_percent, float y_percent, float z_percent, V3D &color){ + Cell CreateCell(float x_percent, float y_percent, float z_percent, const V3D &color){ float continuousMaxValue{static_cast(std::numeric_limits::max())}; Cell cell{ .position = V3D{ @@ -211,11 +211,27 @@ namespace RisingCubes{ .delay = std::chrono::milliseconds(1) }; + AnimationFrame frame0{ + .frame = { + CreateCell(0.0,0.0,0.0,V3D(255.0,255.0,255.0)), + CreateCell(0.0,0.5,0.0,V3D(0.0,255.0,0.0)), + CreateCell(0.0,1.0,0.0,V3D(0.0,255.0,0.0)), + CreateCell(0.0,0.0,0.5,V3D(0.0,0.0,255.0)), + CreateCell(0.0,0.0,1.0,V3D(0.0,0.0,255.0)), + CreateCell(0.5,0.0,0.0,V3D(255.0,0.0,0.0)), + CreateCell(1.0,0.0,0.0,V3D(255.0,0.0,0.0)) + }, + .fillInterpolation = FillInterpolation::NO_FILL, + .frameInterpolation = FrameInterpolation::FADE, + .delay = std::chrono::milliseconds(1000) + }; + std::vector rising{ - frame1, // 0 - frame2, // 1 - frame3, // 2 - frame4, // 3 - frame5 + frame0, frame0 + // frame1, // 0 + // frame2, // 1 + // frame3, // 2 + // frame4, // 3 + // frame5 }; } \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 2b70b1f..4e4922f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -7,34 +7,37 @@ ; ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html + [platformio] -default_envs = esp32s3_release ; this ensures that only this environment is built for anything but the debug build +default_envs = esp32s3_release extra_configs = platformio-local.ini [env] -; platform = espressif32 upload_protocol = esptool platform = https://github.com/platformio/platform-espressif32.git board = esp32-s3-devkitc-1 framework = arduino build_flags = -Iinclude - monitor_speed = 9600 monitor_filters = colorize, send_on_enter -upload_speed = 2000000 ;ESP32S3 USB-Serial Converter maximum 2000000bps -lib_deps = adafruit/Adafruit NeoPixel@^1.12.0 +upload_speed = 2000000 +lib_deps = + adafruit/Adafruit NeoPixel@^1.12.3 + fastled/FastLED@^3.7.3 [env:esp32s3_release] build_type = release +monitor_port = COM21 +upload_port = COM20 [env:esp32s3_debug] debug_init_break = tbreak setup debug_tool = esp-builtin build_type = debug debug_speed = 20000 -; debug_port = COM7 -; monitor_port = COM14 build_flags = - -D DEBUG = 1 - -I include \ No newline at end of file + -D DEBUG = 1 + -I include +monitor_port = COM21 +upload_port = COM20 diff --git a/src/main.cpp b/src/main.cpp index 737824f..3728c34 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -32,7 +32,7 @@ TaskHandle_t updateBoardTask; std::array*, 2> animations = { &RisingCubes::rising, - &RotatingCubes::rotating, + // &RotatingCubes::rotating, }; // BluetoothSerial SerialBT; @@ -112,6 +112,7 @@ void parseData(Message &message){ } case Commands::PING:{ GlobalPrint::Println("!" + String(Commands::PING) + ";"); + boardManager.PrintColorState(); break; } case Commands::SetStackColors:{ diff --git a/tools/animation-tools/.gitignore b/tools/animation-tools/.gitignore index 4ea05a1..77a7e05 100644 --- a/tools/animation-tools/.gitignore +++ b/tools/animation-tools/.gitignore @@ -1,2 +1,3 @@ venv/ -__pycache__/ \ No newline at end of file +__pycache__/ +output.txt \ No newline at end of file diff --git a/tools/animation-tools/AnimationExporter.py b/tools/animation-tools/AnimationExporter.py new file mode 100644 index 0000000..a267ad0 --- /dev/null +++ b/tools/animation-tools/AnimationExporter.py @@ -0,0 +1,74 @@ +from Scene import Scene +from enum import StrEnum +from pygame.math import Vector3 +from Shapes import Mesh + +class FillInterpolation(StrEnum): + NO_FILL = "NO_FILL" + CLOSEST_COLOR = "CLOSEST_COLOR" + LINEAR_WEIGHTED_DISTANCE = "LINEAR_WEIGHTED_DISTANCE" + SQUARE_WEIGHTED_DISTANCE = "SQUARE_WEIGHTED_DISTANCE" + +class FrameInterpolation(StrEnum): + SNAP = "SNAP" + FADE = "FADE" + +class Cell: + def __init__(self, position: Vector3, color: Vector3): + self.position: Vector3 = position + self.color: Vector3 = color + + def to_string(self): + message = f"CreateCell({self.position.x},{self.position.y},{self.position.z}" + message += f",V3D({self.color.x},{self.color.y},{self.color.z}))," + return message + +class AnimationFrame: + def __init__(self, cells: list[Cell], fill_interpolation: FillInterpolation, frame_interpolation: FrameInterpolation, delay: int): + self.cells = cells + self.fill = fill_interpolation + self.frame_interp = frame_interpolation + self.delay = delay + + def to_string(self, frame_number: int): + cell_str = "" + for cell in self.cells: + if cell.color.x != 0 or cell.color.y != 0 or cell.color.z != 0: + cell_str += cell.to_string() + "\n\t" + cell_str = cell_str[:-3] + message = f""" +AnimationFrame frame{frame_number}{{ + .frame = {{ + {cell_str} + }}, + .fillInterpolation = FillInterpolation::{self.fill}, + .frameInterpolation = FrameInterpolation::{self.frame_interp}, + .delay = std::chrono::milliseconds({self.delay}) +}}; + """ + return message + + +#TODO: Impliment this +def generate_animation_frame_struct(animation_types_path: str): + with open(animation_types_path, 'r') as AnimationTypes: + with open("AnimationTypes.py", 'w') as output: + pass + +def mesh_to_cell(mesh: Mesh) -> Cell: + if mesh.face_color[0] != 0 or mesh.face_color[1] != 0 or mesh.face_color[2] != 0: + pass + pos = (mesh.get_average_position() + Vector3(1,1,1)) / 2 + # need to swap z and y for the coordinate system + z = pos.y + pos.y = pos.z + pos.z = z + testVector = Vector3(0.1,0.5,0.9) + + cell = Cell(pos, Vector3(mesh.face_color)) + return cell + +def scene_to_frame(scene: Scene) -> str: + cells = [mesh_to_cell(cube) for cube in scene.meshes] + frame = AnimationFrame(cells, FillInterpolation.NO_FILL, FrameInterpolation.FADE, 1000) + return frame.to_string(0) \ No newline at end of file diff --git a/tools/animation-tools/README.md b/tools/animation-tools/README.md new file mode 100644 index 0000000..789b193 --- /dev/null +++ b/tools/animation-tools/README.md @@ -0,0 +1,31 @@ +# Setup +In order to run this tool follow these steps: + +1. ensure you're using python 3.12+. You can verify this by running +``` +python --version +``` +in a terminal. + +2. Inside of a terminal in the +``` +tools/animation-tools +``` +folder, run: +``` +python -m venv venv +``` + to create your virtual environment. + +3. Now activate the virtual environment. In powershell run +``` +venv\Scripts\activate +``` +You may need to fix permission issues if this is your first time using a virtual environment. For git bash just run: +``` +source venv/Scripts/activate +``` +4. Run +``` +pip install -r requirements.txt +``` \ No newline at end of file diff --git a/tools/animation-tools/Shapes.py b/tools/animation-tools/Shapes.py index 5280177..c72d6ca 100644 --- a/tools/animation-tools/Shapes.py +++ b/tools/animation-tools/Shapes.py @@ -18,6 +18,12 @@ class Mesh(): def calculate_average_z(self, vertices): return [(i, sum([vertices[j].z for j in f]) / len(f)) for i, f in enumerate(self.__faces)] + def get_average_position(self): + vertex_sum: Vector3 = Vector3() + for vertex in self.__vertices: + vertex_sum += vertex + return vertex_sum / len(self.__vertices) + def get_face(self, index): return self.__faces[index] def get_vertices(self): diff --git a/tools/animation-tools/animation-tool.py b/tools/animation-tools/animation-tool.py index 4aad042..5a5b58f 100644 --- a/tools/animation-tools/animation-tool.py +++ b/tools/animation-tools/animation-tool.py @@ -4,6 +4,8 @@ import pygame_widgets from Shapes import * from Scene import Scene from CustomWidgets import ColorPicker +from pygame_widgets.button import Button +from AnimationExporter import scene_to_frame # generate a list of cubes @@ -17,10 +19,19 @@ for origin in product([-1, 0, 1],[-1, 0, 1],[-1, 0, 1]): scene = Scene(meshes, 90, 5) +WINDOW_W = 500 +WINDOW_H = 500 + +def save_frame_to_file(frame_data=""): + frame_data += scene_to_frame(scene) + print(frame_data) + with open("tools/animation-tools/output.txt", 'w') as file: + file.write(frame_data) pygame.init() -window = pygame.display.set_mode((500, 500)) +window = pygame.display.set_mode((WINDOW_W, WINDOW_H)) colorPicker = ColorPicker(window, 20, 20, 100, 300) +save_button = Button(window, 20, WINDOW_H-40, 60, 30, text="Save",onClick=save_frame_to_file) clock = pygame.time.Clock() selected_meshes = [] run = True