{"id":16521940,"url":"https://github.com/meshula/wrinkles","last_synced_at":"2025-07-14T11:07:06.853Z","repository":{"id":147568090,"uuid":"537273596","full_name":"meshula/wrinkles","owner":"meshula","description":"wrinkles zig demonstrator","archived":false,"fork":false,"pushed_at":"2025-06-07T21:07:39.000Z","size":257530,"stargazers_count":10,"open_issues_count":0,"forks_count":1,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-06-30T17:49:58.121Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Zig","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/meshula.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-09-16T02:11:25.000Z","updated_at":"2025-06-07T21:07:44.000Z","dependencies_parsed_at":"2023-09-27T11:09:30.930Z","dependency_job_id":"86ad77ac-f18f-419a-97ea-db04a82fc1cc","html_url":"https://github.com/meshula/wrinkles","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/meshula/wrinkles","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meshula%2Fwrinkles","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meshula%2Fwrinkles/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meshula%2Fwrinkles/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meshula%2Fwrinkles/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/meshula","download_url":"https://codeload.github.com/meshula/wrinkles/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meshula%2Fwrinkles/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265281150,"owners_count":23739863,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-11T16:58:42.185Z","updated_at":"2025-07-14T11:07:06.823Z","avatar_url":"https://github.com/meshula.png","language":"Zig","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Wrinkles app - Robust Temporal Math V3 Prototype Project\n\n@TODO: next step is to use the work on Ordinates to define how ranges, and\n        times are used to define where a clip sits in the timeline.  IE does a\n        media reference describe its media range in integer sample indices?\n        Does the clip cut in continuous time?  How does a track describe its\n        metric or is that per clip?\n        Is the \"does the clip cut in continuous time\" question analogous to the\n        LoD over continuous time in the sampling framework that AAA mentioned?\n\n## Contents\n\n* `opentime`: low level points, intervals and affine transforms, and\n  `Dual` for doing dual arithmetic/implicit differentiation.  Also includes the\n  likely-to-be-deleted `PhaseOrdinate` [^1].\n* `curve`: structures and functions for making and manipulating linear and\n  bezier splines\n* `sampling`: tools for dealing with discrete spaces, particularly sets of either\n  samples or sample indices.  Includes tools for transforming and resampling\n  such arrays.\n* `Mapping`: linear, monontonic, composable transformation functions for\n  continuous transformation\n* `Topology`: monotonic over their input spaces, use sets of Mappings to\n  continuously project from an input space to an output space.\n* `OpenTimelineIO`: structures to represent an editorial timeline document\n* `ProjectionOperator`: pairs a topology with source and destination references\n  which can define discrete spaces so that you can project from a discrete\n  space to another discrete space with a continuous transformation in the\n  middle.\n* `TopologicalMap`: tools to transform an editorial document described by\n  OpenTimelineIO structures into a temporal hierarchy.  ProjectionOperators can\n  be built from endpoints in this hierarchy.\n* `ProjectionOperatorMap`: decomposes/flattens a TopologicalMap from a source\n  space such that each segment maps a set of ProjectionOperators to region of\n  the source space, mapping media under each section of the output timeline\n\nAdditionally there are tools for visualizing curves, transformations, and the\ntemporal hierarchies of editorial documents.\n\n![Screenshot of visualizer app](app.png)\n\n## Lessons/Differences to OTIO V1\n\n* clarify that OTIO is modelling a temporally-oriented hierarchy, not a data\n  model that necessarily resembles an NLE\n* Time is the domain that is handled, so model the structure around time\n* transform the data, don't provide a ton of flexibility in the algorithms\n  * makes the algorithms simpler and easier to use as templates for\n    business-logic specific use cases\n* use hierarchy rather than \"has-a\" to clarify temporal relationships\n* having hierarchy object schemas be runtime definable: juice seems not to have\n  been worth the squeeze\n* explicitly modelling discrete/continuous means no need for rational time\n* implementing in a low level language (zig-\u003eC) to allow flatter higher level\n  language bindings\n* explicitly model references into the hierarchy\n\n## Ideal Demonstrator Gui App 8/23\n\n* timeline view\n* topological graph node view\n* curve projection demonstration app\n  * pick curves to project from presets\n  * edit / drag points\n  * see derivatives\n  * see projection result\n\n* app that can open an existing .otio file\n* visualize the presentation time-space of the top level track\n* tlrender++ scrub around the track and see a render of what the composition\n  looks like at that frame decorated with coordinates in the media timespaces\n  and media sources for each section/clip\n* raven/raven++\n* topological view -- for a selection of the document, show the topological\n  graph of the temporal structural, decorated with the Transformation curves\n  * select two nodes to see the projection operator from one to the other\n\n## Current Todo List (11/6/24)\n\n* [x] add build variable for debug messages\n* [x] prune existing debug messages out\n* [x] clean up how graphviz is found\n* [x] decompose opentimelineio.zig into a library w/ multiple modules\n* [x] boil time out of opentime (hm might need to rename this library) —\n    * [x] particularly ContinuousTimeInterval-\u003eContinuousInterval\n    * [x] opentime\n* [x] and the rest of the library (notably sampling.zig)\n    * [x] sampling\n    * [x] ripple out into the c library too\n* [x] fold DiscreteDatasourceIndexGenerator into Sampling\n    * [x] -\u003e SignalIndexGenerator\n    * [x] add more functionality to the DiscreteDatasourceIndexGenerator so that\n    * [x] build out into the otio layer too\n* [x] rename “time_topology” build unit to “topology”\n* [x] `PhaseOrdinate` (or some other means of accurately handling integers over\n  rates changing)\n    * [x] confirm that this is really better than an `f64` or `f128`\n    * ... it isn't, see: [https://github.com/ssteinbach/ordinate_precision_research](https://github.com/ssteinbach/ordinate_precision_research)\n* [ ] 0.5 offset todo in sampling\n* [ ] thread the \"domain\" idea out to the discrete spaces, so you can\n      define on the timeline a discrete info per domain (ie 24 for picture\n      48000 for sound)\n* [ ] handle non-integer rates (ie 1000/1001 rates) in the sample rate\n* [ ] review the high level tests and make sure they’re covering all the stuff\n  in the slides\n    * [ ] factor out the code that builds the timelines into a couple\n          prototypical timelines, then the tests can operate on those structures\n          and make the tests a bit more readable/direct\n* [ ] write the slide examples in C\n* [ ] handle/test cases where projection results in multiple solutions (maybe\n  because inversion creates multiple concurrent topologies?)\n* [ ] add a catmull-rom basis function\n* [ ] zbez library specific for bezier?\n     * [ ] remove the two point/three point approximations and simplify the\n           curve library\n     * [ ] export bezier code into a zbez library that can be freestanding\n* [ ] finish parameterizing the sampling library on type, like the curve\n  library\n     * ie index_at_time -\u003e output_index_at_input_ordinate\n     * [ ] handle acyclical sampling as well (variable bitrate data, held\n           frames, etc).?\n* [ ] do a scan to make sure that `opentime.Ordinate` is used in place of f32\n  directly\n* [ ] integrate inside of raven\n\n## Todo List (8/23/24)\n\n* build new gui app\n  * visual demonstration application for helping demo concepts\n* additional tests/functionality to show the library is capable of handling\n  * [ ] cleaning up existing high level tests\n  * [ ] arbitrarily held frames\n  * [ ] transitions\n    * what about NTSC times?\n* [x] demonstration c-api\n  * [ ] add metadata support\n  * [ ] what would a C++ layer look like on top of this?\n    * [ ] ...and then what would a Pybind layer on top of the C++/C?\n* refactoring core library pieces to clarify/simplify/improve the\n  implementation\n  * [ ] consistent names\n    * replacing `f32` with `opentime.Ordinate`\n\n        ```zig\n        pub const Ordinate = struct {\n          value : f32,\n\n          pub fn add(self: @This(), rhs: Ordinate) Ordinate{}\n          pub fn sub(self: @This(), rhs: Ordinate) Ordinate{}\n          pub fn mul(self: @This(), rhs: Ordinate) Ordinate{}\n          pub fn div(self: @This(), rhs: Ordinate) Ordinate{}\n        };\n        ```\n    * struct/union with add/mul/div/sub\n     * [ ] test_topology_projections.zig\n * [ ]  let brains cool off \u003c- beers\n\n### Bigger, Later Questions/Todos\n\n * [ ]  what if not beziers internally but instead b-splines with bezier\n        interfaces\n * [ ]  rebuild in c?\n * [ ]  PR to OTIO?\n\n## Todo\n\n* domains (how do you handle that you want to evaluate the timeline at 30fps?)\n* transitions\n\n### later\n\n* schema design\n* `graphviz` viewer for otio files\n    * plain format (dot -Tplain) produces a parsable output\n    * visualize graph transformations over a topology with different targets\n* redesign the `opentimelineio` layer\n    * clean up mess of `Item` and `ItemPtr`\n    * Allocators should be exposed as parameters, not through `allocator.ALLOCATOR`\n    * project_curve and so on should be !TimeCurve, not use catch unreachable\n      everywhere\n* move to zig v0.11 and bump deps\n* topology-\u003e[]topology projection (for handling inversions)\n* time-varying parameters\n* time-varying metadata\n\n## ZIG REFERENCES\n\n* [Zig Lang](https://github.com/ziglang/zig): The language homepage\n* [Zig Learn](https://ziglearn.org/chapter-0/): Good starting place for a language overview\n* [Language Reference](https://ziglang.org/documentation/master/): Full Language Reference\n* [Stdlib Reference](https://ziglang.org/documentation/master/std/#A;std)\n* [Stdlib Source](https://github.com/ziglang/zig/tree/master/lib/std): I hate to admit it but often times its faster to just look at the source of the standard lib rather than going through the docs\n\n### DONE\n\n* sampling\n## Path System\n\n* support arbitrary path lengths\n    * use an array list of u128 to encode arbitrarily long paths\n* arbitrary `TopologicalPathHash` lengths\n* fix the simple_cut\n* JSON OTIO parsing\n    * can parse small OTIO files (but because of path length constraints, can't\n      build maps for large files)\n\n* Right now the topology has bounds, transform and curves.  This is\n  inconsistent because the curves _inside_ the topology also represent a\n  transformation, and implicitly define bounds (in that they're finite lists of\n  segments, which are bounded).  The math reflects this - the way that\n  transform and boundary are applied is pretty inconsistent.\n\n* Part of the reason why this is the case is that there are several special\n  cases of topology in play:\n    * infinite identity (could have a transform but no bounds)\n    * finite segments (do they have bounds?)\n    * empty\n\nTwo options:\n\n* do what we did for the graph and define a set of operators that bundle up a\n  topology and work through the cases, providing clean constructors for those\n  useful special types\n* break these features up into things that the topology can contain and\n  localize the math, push the matrix into handling combinations of those child\n  types\n\n* Stacks\n* Timeline\n* Gap (fully)\n\n* how hard would parsing OTIO JSON be?  Would be cool to read in real\n  timeilines and do transformations there\n\n### Inversion\n\n* need to add inversion functions to the topologies\n* add error when a function isn't trivially invertible\n* if we do something with the mappings, when things aren't trivially\n  invertible, we still know how to invert them and how the mapping functions.\n  Can we exploit this? Or is the juice not worth the squeeze for this project\n\n### Optimization and Caching\n\n* MxN track related time stuff - the map should cache those kinds of intermediates\n* Can the map also cache optimizations like linearizing curves?\n\n### Ordinate Notes\n\n```zig\nconst Ordinate = union(enum) {\n    f32: f32,\n    rational: rational,\n\n    // math\n    pub fn add() Ordinate {}\n    pub fn addWithOverflow() Ordinate {}\n    pub fn sub() Ordinate {}\n    pub fn subWithOverflow() Ordinate {}\n    pub fn mul() Ordinate {}\n    pub fn mulWithOverflow() Ordinate {}\n    pub fn divExact() Ordinate {}\n    pub fn divFloor() Ordinate {}\n    pub fn divTrunc() Ordinate {}\n\n    pub fn to_float() f32 {}\n};\n```\n\n# Memory Management Notes\n\n* The zig pattern has either:\n    * `init` and `deinit`: initialize and return a pointer to new memory\n    * `create` and `destroy` - create single values in memory and return an \n      `undefined` pointer to the memory.  Equivalent to \n      `var thing : Something = undefined;`, but on the heap.\n* we have value types that contain references to memory because they are of\n  unknown size - IE \"name\".  We could fix the size of the name slice, then \n  they would also be fixed value types\n* ... but the array types (track, stack, etc) would still need allocations\n* if you want the lifetime to extend past the scope, you need to init/deinit\n* the `ItemPtr` is definitely a reference type\n* I think the questions are:\n    * should the containers contain value types?  or reference types?\n    * what should users expect from ownership?\n\n## Places for demoing animated parameters on warped scopes\n\n* properties: one time configuration of information (IE, name, temporal\n  bounds, media_reference, discrete_info)\n* parameters: varying data over some domain (a mapping and an embedding\n  domain)\n\n* lens parameters on a clip (ie an animated rack focus or aperture or something)\n  * animated focus distance or aperture\n* parameter that drives a wipe in a transition\n* animating a 2d image space transform \n* a color correct parameter\n* state of a gyroscope during capture\n* mocap data\n    * floats over time\n\n## Why Is This So Complicated\n\n* Editorial Time is Complicated\n    * Sometimes Continuous, sometimes discrete\n    * Even when its discrete its Complicated\n        * different rates/metrics (at the very least, audio vs video)\n        * audio rates can be huge, meaning even with not that much wall clock\n          time numbers get enormous (ie 192khz - 1 minute of audio is already\n          at index 11,520,000, 3.1 hours = max in32)\n        * NTSC rates (with a 1001 denominator) mean that mixing rates can be\n          difficult to represent with integer rationals\n    * Even when its continuous its Complicated\n        * Because typically pictures are not resampled, precision is important\n        * Audio rates mean that increments can be tiny but still go for large\n          ranges\n        * when dealing with the media a frame index integer is generally what\n          is desired\n    * Deformations can be non-linear\n        * Bezier curve-based transformations for speed ramps\n        * F,M,L type presentations in dailies\n        * pulldowns/pullups for going between NTSC and non-NTSC rates\n    * Animated parameters are often driven off of time, meaning that time warps\n      need to also warp \n* What does OTIO do\n    * Uses \"RationalTime\" - a double value over a double rate.\n        * some smarts but used in a handwavvy \"both continuous and discrete\"\n          sort of way\n    * Doesn't deal with non-linear transformations\n    * Cannot project ranges or points under warp\n* What do we propose\n    * Join discrete and continuous math via sampling theory\n\n## References\n\n[^1]: [Ordinate Precision Research](https://github.com/ssteinbach/ordinate_precision_research)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmeshula%2Fwrinkles","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmeshula%2Fwrinkles","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmeshula%2Fwrinkles/lists"}