2016

Week 21 (December 26)

Info

This week I added support for window resizing, which applies to sub-windows.

Added near/far clipping to 3D view drawing code, supporting edges partially behind the view or past the far clip plane. Sounds like detail but perspective drawing didn’t work properly without it.

Also added vertex selection operator which converts view context into a ray which is stored in operator properties. Seems simple too but needed to add vector property functions and macro for unpacking vectors.

Note, some hot days and Christmas took time away from regular dev :).

Next Week

There are a lot of basics to continue on with, probably continue with window management and basic operators, since there are still quite a few areas that aren’t well defined - such as floating windows (pop-ups, needed for menus), splitting & removing windows.

Also how to split runtime and on-disk data for window management.

BMesh-Rust

  • Edit-mesh pointer selection operator RB:f6843dc9
  • Add ‘unpack’ macro to avoid expanding in-line RB:ef0b7dc3
  • Add vector projection functions RB:c67be126
  • Use floating point coords for window sizes (avoids rounding errors with window resizing) RB:e7e48907
  • Window resizing support (Initial support for recursive window re-arrangement) RB:8934e07f
  • Blend colors correctly when clipping RB:989c0bb1
  • Line & vertex drawing now clips between near/far planes RB:fcb8fc6a RB:3e23b907
  • Add plane math functions RB:4c4b40e5
  • Move global event handlers into window-elements RB:ec2af244

Questions

  • 41391522 How to use a type (ty) within a macro to construct a struct instance in Rust?
  • 41410212 How to avoid repetition expanding indices with macros in Rust?

Up until RB:f6843dc9

Week 20 (December 19)

Info

This week I added initial Wayland support as planned, this took a bit longer then expected (2-3 days), and the method of updating the final image is quite slow however its served its purpose as a way to keep multiple back-ends available. (it will likely be easier to improve performance then write from scratch later on).

I also got basic windowing support started - so there is support for multiple regions for drawing and event handling, tested by adding view navigation modal operators.

Next Week

Continue, working on the windowing system, more basic operators.

General Tasks

  • Wrote a small utility for cargo out-of-source builds. A wrapper for cargo to automatically handle locating build outside the source tree.

    (avoids having to configure all my development tools to ignore build files).

BMesh-Rust

Questions

  • 41337856 How to keep an open file handle in a shell script on Linux?
  • 41322300 How to execute Rust code directly on Unix systems? (using the shebang)
  • 41274901 Out of source builds (external build directory) with Cargo?

Up until RB:6fe2ea8e

Week 19 (December 12)

Info

This week I got modal operators working, as well as basic window event handlers which was necessary.

Now interactive view zoom and orbit are working.

Also added color-blended line drawing so partially selected edges can draw, blending the selected vertex with the unselected.

Next Week

Investigate using an alternative driver to SDL. Mainly to avoid unintended coupling with the behavior of SDL.

I’ll look into using GLFW since its well supported in Rust, although there is no need for OpenGL, it looks like they are supporting Vulkan too.

Not sure how long this will take, after that I’ll start on a basic, hierarchical windowing system so I can properly test different contexts and per-region event handlers.

BMesh-Rust

Questions

  • 41195973 How to use Bresenham’s line drawing algorithm with sub pixel bias?
  • 41156227 Convenient Option<Box<Any>> access when success is assured?
  • 41101936 Which integer operations have higher performance alternate methods in Rust?
  • 41094315 How to declare a struct where only some members can use a value from another struct?
  • 41093527 How to blend two RGB unsigned byte colors stored as unsigned 32bit ints fast?

Up until RB:7b193041

Week 18 (December 5)

Info

This week I added an initial SDL application which imports the app_engine crate and passes events into it.

Also got very basic event system and keymap and operators working together together.

Added a sample select-invert tool.

Next Week

Work on operator API, add modal operators and test some basic view navigation (orbit for example).

Add other simple operators too.

Generally work towards working view-port and mesh editing so it can start to be used.

BMesh-Rust

Questions

  • 41035869 How to use a reference to an items struct member as its own ‘key’ when inserted to a map?
  • 41029772 How to create a handle for application context in Rust?
  • 40986141 How to group ‘Option’ assignments in Rust?

until RB:79553dab

Week 17 (November 28)

Info

This week I joined together the basic components to create a very basic application which adds a mesh, draws it in the viewport and writes out an image.

Also spent some time to get a good clipped line drawing function working, surprisingly I couldn’t find a good, existing implementation of this, ended up modifying code from upainter updating it with some minor improvements with tests in its own git repository. See: bresenham-line-plot-clip-py.

Next Week

Next week start on an interactive windowed application, basic event system and keymap.

BMesh-Rust

  • Add basic preferences struct RB:6c177c1e

  • Move macros into a reusable crate RB:72760da8

  • Added a line drawing method that can clip within a rectangle. RB:04ea8722

  • Initial application crate: draws a torus, writes to an image. RB:5a736881

  • Add enum_int_macros for C line enums, similar to bitflag_macros. RB:95383b11

  • Add mini png writing crate

    Single file uncompressed PNG writer, useful for visualizing test output. RB:fa3a8bda

  • Add stub application for tests RB:c4b839a3

Questions

  • 40925296 How to create new instances of a wrapped vector in Rust?
  • 40884680 How to use Bresenham’s line drawing algorithm with clipping?
  • 40857359 How to handle floating point exceptions (fpe) with Rust?
  • 40856862 How to swap values from a multidimensional array in Rust?

up until: RB:6c177c1e

Week 16 (November 21)

Info

This week I spent time to implement a real iterator for memory pool (as planned) and continued fleshing out the BMesh API.

But otherwise didn’t get as much done as I’d have liked.

Next Week

Make a start on software rendering, useful for viewport testing.

Possibly add a simple SDL test application.

BMesh-Rust

up until: RB:35a40731

Week 15 (November 14)

Info

This week I added more bmesh functions as well as triangulate, using polyfill_2d module.

Next Week

Continue adding bmesh functions, possibly loop into writing a proper memory pool iterator since currently its first converting to a vector.

BMesh-Rust

Questions

  • 40658487 How to pass Option<&mut ...> to multiple function calls without causing move errors?
  • 40657075 How to access a vector multiple times within an ‘Option’?
  • 40613725 Iterating over a slice’s values instead of references in Rust?
  • 40580250 Is it possible to declare a tuple struct whose members are private, except for initialization?
  • 40573055 Is it possible to access the type of a struct member for function signatures or declarations?
  • 40567538 How to avoid repetition re-declaring variables by calling their methods in Rust?
  • 40563116 How to assign multiple existing variables from a tuple in Rust?

up until: RB:a51d64d1

Week 14 (November 7)

Info

This week I continued to refine the API and add functionality.

Next Week

Continue adding more advanced bmesh functions.

BMesh-Rust

  • Support BM_faces_join_pair, BM_face_normal_flip, BM_face_normal_update RB:0e039ed0

  • Move macro loop execution logic into its own macro RB:7d7a1fe5

  • Support BM_faces_join and related functions

    • BM_edge_splice
    • BM_vert_collapse_faces
    • BM_face_vert_share_loop
    • bmesh_loop_validate
    • bmesh_jekv

    RB:5eeb19c8

  • Support bmesh_jekv WIP RB:6df649c0

  • Comments on why PtrConst.to_mut is needed. RB:b93f881e

  • Support BM_face_split RB:8d939dc3

  • Support BM_edge_split RB:586aba0a

  • Support bmesh_semv RB:c9a9705e

Questions

  • 40550665 How to include ASCII art/diagrams in Rust source-code comment documentation?
  • 40524165 How to write generic functions that take types which are themselves generic?
  • 40509400 How to pass named loop labels to a macro in Rust?
  • 40481199 How to define some macros as ‘private’ to a module, when using macro_use in Rust?

up until: RB:b7b5f06d

Week 13 (October 31)

Info

This week I got the basics of the bmesh API’s working.

Also spent time on figuring out how to structure macros, modules, tests... etc.

Next Week

Add more advanced bmesh editing functions.

BMesh-Rust

Questions

  • 40402317 Is it possible to nest a struct declaration in a macro to apply struct attributes?
  • 40401574 Possible to derive attributes after a struct declaration?
  • 40397672 Possible to combine assignment and comparison in an expression?
  • 40367127 How to wrap a do-while style loop in a macro, maintaining ‘continue’ flow control?
  • 40366586 How to break out of a do-while style loop in Rust?
  • 40354691 Is it possible to group sections of an API with rustdoc?
  • 40336735 How to generate a compilation error when pointer types differ in Rust?
  • 40332112 How to declare typed bitflags in Rust?
  • 40317860 How to declare a generic type that is a raw pointer?

up until: RB:b7b5f06d

Week 12 (October 24)

Info

This week I started porting BMesh from C to Rust, with the initial memory pool module.

Next Week

Setup basic BMesh API an tests.

BMesh-Rust

Questions

  • 40310483 How to get pointer offset in bytes?
  • 40309915 How to get the offset of a struct member in Rust? (offsetof)
  • 40302760 Convenient access to members of raw pointers?
  • 40301422 How to implement Default for a raw pointer?
  • 40276715 Should end user utilities/applications be registered on crates.io?
  • 40276179 How to bundle/nest crates when publishing?
  • 40212998 How to implement a trait in the same way for many types without repetition?

up until: RB:dc3ffecb

Week 11 (October 17)

Info

I’ve taken 3 weeks off, however I did explore some development I was curious about in this time, albeit in a more relaxed manner.

Next Week

Start on porting Blender’s BMesh mesh editing API to Rust.

General Tasks

Range Tree

I’d previously noticed that Blender’s range-tree structure wasn’t as optimal as it could be, using a libstdc++ set which added/removed items on every range adjustment.

Since a range-tree is a generally useful data structure, and may be useful for keeping track of used memory in a memory-pool for example.

I decided to look into writing a portable range-tree implementation which could be easily ported between languages.

  • Ported and extended a left-leaning rb-tree to Python with tests, see: btree-mini-py.

  • Wrote a Python Range-Tree tree with tests, see: rangetree-py.

  • Ported to Rust, using generic types - so a range-tree can be defined for any kind of number, see: rangetree-rs.

    Added memory pool for efficient element allocation, and submitted this as my first package to crates.io, see: crates.io.

Finally I ported this to C, and committed it to Blender, replacing it’s C++ implementation, giving a ~15% speedup to dynamic-topology sculpting with undo See commit.

Questions

  • 39813703 Algorithms for 2D polygon simplification by collapsing segments?
  • 39844260 How to use panic=abort with external dependencies?

Week 10 (October 10)

Some time off, see week 11.

Week 9 (October 3)

Some time off, see week 11.

Week 8 (September 26)

Info

This week I added PNG support, added majority turn policy, split the bitmat tracer into crates and other minor improvements.

Next Week

Finish up with bitmap tracing, nearly done already. Possibly start on some new project.

General Tasks

Bitmap Tracing

  • Add debug pass option (Useful for visualizing intermediate steps). RT:c622cfc3
  • Add turn-policy option: BLACK, WHITE, MAJORITY, MINORITY. RT:9eb79d32
  • Add initial PNG format support, with lodepng-rust. RT:91a71218
  • Split modules into crates RT:069c2c0a
  • Add grouping for argument parsing RT:090eee6b
  • Use curve smoothing for centerline tracing RT:f529ab79
  • Fix error where sign was incorrectly used for ‘offset’ method RT:16384a2f

Questions

  • 39734321 Is it possible to disable a single default feature in Cargo?
  • 39735660 How to make a local dependency depend on a feature in Cargo?

up until: RE:53279e7b RT:c622cfc3

Week 7 (September 19)

Info

This week I discarded the tessellating method of center-line extraction in favor of iterative pixel based thinning.

While extracting center-lines from tessellation worked reasonably well, it didn’t handle joins well and would have needed more work to correct end-points.

Instead I used: 3-D medial surface/axis thinning algorithms. Computer Vision, Graphics, and Image Processing, 56(6):462-478, 1994.

Which is intended for voxels but works for 2D shapes too. The resulting center-lines suffer a little from pixel-aligned stepping which is noticeable on thicker lines, while further work could be done here - I rather get an initial version of this tracing application working first.

Finally, center-line tracing was added as a command line option and integrated, adding support for non-cyclic curves.

Next Week

Generally keep on finishing things up, possibly split out some modules into crates, add support for other image formats besides PPM.

Bitmap Tracing

  • Use skeletonize center line extraction instead of extracting from tessellation. RT:5ab11eab
  • Add support for detecting loop-outlines RT:0450cd19
  • Exit when handling argument parsing instead of panicking. RT:86b2cc37
  • Add scale argument, also handle error in arguments. RT:f5a499b8
  • Add --mode argument (outline & center-line). RT:39979421

Questions

up until: RE:53279e7b RT:5ab11eab

Week 6 (September 12)

Info

This week I looked into getting better quality polygon extracted from the bitmap, before fitting the curve. This is needed since the tangents for curve fitting depend on having a relatively smooth curve.

When performing a close-fit, pixel stair-casing artifacts are visible.

I found an implementation of the “Depixelizing Pixel Art” algorithm, called depixel.

Spent an afternoon looking into this, (ported to Python3 and worked around a bug), but ultimately I found this method is too focused on extracting a shape from low resolution pixel art, which doesn’t work so well to fit higher resolution shapes.

I looked into center-line extraction, since from what I can see - existing open-source tracing programs don’t support this.

While I got it working on a basic level, the method Im using currently gives some annoying artifacts with varying width lines, so I’ll need to look into ways to better find the inner path.

Next Week

Further investigate center line extraction and (as noted last week), tie up loose ends.

Bitmap Tracing

  • Add triangle beautify, (initial center-line extraction) RT:96dd93d9

  • Add bitmap tessellation (triangulates from a bitmap outline). RT:26e0d380

  • Improved polygon smoothing (Avoid loosing volume, keep corners). RT:96c0c8ee

  • Change policy for diagonally touching pixels

    Consider them connected, this could be made configurable. RT:ac402aad

  • Avoid cloning for threaded calculation RT:1bb4d839

  • Optimize curve fitting, avoid excess checking RT:15c1b93d

  • Re-fitting improve split index selection

    Use the most distant point in the case of removing the knot. This tends to select the best place to split the curve.

    RT:26cc3f4b

  • Add a small argparse library to help with argument parsing and print a --help message. RT:5f87ab6b

Questions

  • 39560296 Best way to conditionally add to a HashMap, with as few hash lookups as possible?
  • 39555539 Can macros expand array/vector into multiple indexed arguments?
  • 39464237 Whats the idiomatic way reference BufReader/BufWriter when passing between functions?
  • 39463435 How to multi-thread function calls on read-only data without cloning it?

up until: RE:53279e7b RT:96dd93d9

Week 5 (September 5)

Info

This week mostly went as planned, with curve fitting entirely ported from curve-fit-nd to Rust and got image loading working using the simple PPM image format so arbitrary images can be traced.

Next Week

Generally tie up loose ends and prepare to make an initial release of the curve fitting tool.

Possibly re-visit polygon from bitmap conversion which works but is a bit rough.

General Tasks

Minor changes to rust-examples repo:

Bitmap Tracing

  • Image reader for the PPM image format. RT:99660fe3

  • Initial multi-threading support. (Currently duplicates input polygon, need to investigate how to avoid). RT:77031883

  • Cleanup: de-duplicate recalculation next/prev pairs RT:b57dce08

  • Cleanup: use a separate array for heap access (Simplifies logic for borrow checker). RT:b9e2e2ae

  • Support for corner detection RT:c5eb26b7

  • Simple improvements to polygon pre-processing

    • Perform a single subdivision after smoothing. This helps, giving an extra tangent to use when fitting knots.
    • Caller defined maximum length threshold, helps to give even density.

    RT:e170daae

  • Support N-dimensional curve fitting RT:f92556b0

  • Single-curve fitting support added RT:f69cf5f5

  • Refit ‘remove’ support RT:1cecaaa5

  • Refitting now works RT:94032828

Questions

  • 39404265 Does Rust provide a way to parse integer numbers directly from ASCII data in byte (u8) arrays?
  • 39369402 Possible to declare functions that will warn on unused results in Rust?
  • 39352014 How to reference a member of a module in its parent scope, from a module?
  • 39349286 Can macros match against constant arguments instead of literals?
  • 39346788 Is it possible to write a macro that expands an expression N times? (Where N is a constant)
  • 39334430 How to reference types from function signatures in private modules?
  • 39327859 How to swap variables pointing to data, without swapping their content?
  • 39324463 How to best return a fixed size array without creating one with dummy values or manual unrolling?

up until: RE:53279e7b RT:99660fe3

Week 4 (August 29)

Info

This week I didn’t manage to pull everything together but did manage to get polygon fitting working on a basic level.

It turns out Vladimir Agafonkin’s only works on polygons that have 2 endpoints (not cyclic polygon loops), so I’ll look into some different ways to simplify polygons later, for now I can continue without it.

This week I spent a lot of time to get different parts of the tracing program working together so I could test its working on a very basic level.

By the end of the week I had simple curve fitting working to trace a bitmap, however this is mainly to validate the basics, so I can then finish implementing details and see they work as expected.

This is taking longer then expected since I’m still learning a lot about Rust and how to structure things.

Next Week

Try to finish off both the curve fitting (which fits a single curve). And re-fitting, which adjusts spline placement over the polygon for an optimal result.

General Tasks

  • Made a min-heap implementation that allows nodes of duplicate weights to be in the tree and uses generic types for order & value. RE:44bf879f
  • Released cargo-watch shell script, I use for monitoring my source directory and rebuilding automatically. See repository.

Bitmap Tracing

  • Initial curve re-fitting (works on basic level) RT:34772c86

Questions

  • 39269408 How to quiet a warning for a single statement in Rust?
  • 39266001 How to introspect all available methods & members in Rust?
  • 39264143 Possible to prevent access to a variable declared in the scope or as a function argument?
  • 39263555 Whats the best way to join many vectors into a new vector?
  • 39240360 Idiomatic way to declare 2D, 3D vector types in Rust?
  • 39219961 How to get assembly output from building with Cargo?
  • 39219667 How to get the index of an element in a vector using pointer arithmetic?
  • 39204908 How to check release / debug builds using cfg in Rust?

up until: RE:4ce874d5 RT:34772c86

Week 3 (August 22)

Info

This week I made a start on my bitmap tracing utility, this is my attempt to create a stand-alone utility in Rust which is useful to other people (not just a toy project).

This is a rough equivalent to Potrace, for now I’m not reading its code, I’ll first put this together figuring out things myself, perhaps I come up with some better/different alternatives, or not, either way it helps with learning. And I rather not do a direct port of Potrace to Rust.

Once its working, I’ll see if its worth following some similar methods to Potrace if they’re an improvement.

This is currently quite messy, but I would like to get something working on a very basic level, I can focus on improving individual algorithms afterwards, once everything works.

I started a new repository for this, called raster-retrace.

Also got basic cubic curve fitting working, but didn’t commit this to a public repository yet, will include in raster-retrace.

Next Week

  • Make a version of Vladimir Agafonkin’s line simplification library which supports connected polygons.

    To have this working I’ll need a min-heap (binary-heap). Rust’s built-in BinaryHeap doesn’t support removal of any element within the heap (only the top), so I’ll need to write a small min-heap for this.

  • Attempt to pull everything together into the raster-retrace repository,

    • raster to polygon.
    • polygon smoothing.
    • polygon to cubic splines.

Eventually I’ll need to support image loading too, however I’m not so happy with the state of image loading libraries in Rust.

Existing image crate is written for games, includes filters and editing operations, image writing (which is fine but I don’t need it), and some formats aren’t fully working, I’d rather use FFI to access libpng & libjpeg directly since I only need to load data.

General Tasks

  • Poly filling (2D raster filling)

    This was a direct port of Darel Rex Finley’s Efficient Polygon Fill Algorithm.

    Improved on the overall performance by avoiding a search on all segments for every y-step. (using a sweep-line with in-out events).

    Also back-ported these changes to Blender’s C code, updating its polygon filling to use this method: See Patch.

    For 10,000 points I measured the method to be ~11x faster, however rounding the X value slows this down to ~7x.

    And for reference: See standalone C99 version.

  • Started raster-retrace project, (just initial bitmap to polygon code so far) RT:7f865f82.

Questions

  • 39187602 Idiomatic way to fill an arbitrary sized vector without array resizing?
  • 39178648 How to match against a flags/bitmasks in Rust?
  • 39178209 Possible to check a value is a compile time constant in Rust?
  • 39169790 Is it possible to de-duplicate if statements and their body in Rust, perhaps by using macros?
  • 39137063 Whats the best way to write an iterator supporting multiple logic branches?
  • 39107085 What’s the most straightforward way to chain comparisons, yielding the first non-equal?
  • 39075126 How to reuse generic function type boundaries?
  • 39074726 Generic functions in Rust with limited, known types?

Up until RE:c8afa3d7 RT:7898a7b3

Week 2 (August 15)

Info

This week I got polyfill 2d tessellation port, of the libGDX tessellation algorithm. (including kd-tree optimizations).

I also wrote a PNG image writer (from scratch), to be easily used in tests.

This took more time then expected since Rust doesn’t include a zlib encoder, I looked into linking to zlib, which can work but isn’t essential, In the end I include a zlib encoding logic which doesn’t do any compression, nevertheless I needed to include checksum methods (crc32 & adler32).

Next Week

Work towards, bezier curve fitting port, this will have to be broken up into a few steps.

  • Loading the image from a file (will likely use existing image crate).
  • Convert the image to a polygon. (possibly simplify it?).
  • Apply curve fitting algorithm.
  • Write it out to a known file format (SVG, EPS...)

General Tasks

Questions

  • 39029274 How to wrap a raw string literal in source code without inserting newlines?
  • 39017871 How to prefix/suffix macro identifiers in Rust?
  • 39016925 Is it possible to coerce int literals to floats in Rust without adding decimal point?
  • 39008880 Is it possible to declare local anonymous structs in Rust?
  • 38995892 How to move tests into a separate file for binaries in Rust’s Cargo?
  • 38948997 Is it possible to declare extern “C” functions without polluting the namespace?
  • 38948669 Whats the most direct way to convert a Path to a *c_char?
  • 38941025 How to define a function with a generic fixed-length array?

Up until RE:c8afa3d7

Week 1 (August 8)

Info

This week I started writing some very basic Rust examples, am very much a beginner, so am trying out having basic algorithms work in isolated test cases.

Even though drawing lines and polygons is very simple, looked into implementing them as both callback and iterators.

Next Week

Write more example tests.

  • Port my ear-clipping tessellator to Rust, (including tests).
  • Write a stand-alone PNG writing function (using only zlib).

Otherwise, there are some other small experiments to investigate, before tackling bigger projects.

General Tasks

Questions

Compared with more popular languages, theres a real lack of existing beginner questions for Rust, I’m also not sure what is/isn’t possible - so asked quite a lot of questions.

  • 38739088 Is it possible to declare arrays without an explicit length?
  • 38756951 How to add index support to a struct/tuples with homogeneous types?
  • 38778662 Possible to operate on all members of a homogeneous struct/tuple in Rust?
  • 38779591 Macro that declare variables in Rust?
  • 38810973 Assign a single value to multiple variables in one line in Rust?
  • 38811387 How to implement idiomatic operator overloading for values and references in Rust?
  • 38812562 Is it possible to use an argument multiple times in a Rust macros with a single instansiation?
  • 38828920 How to write a macro in Rust to match any element in a set?
  • 38863315 How to perform efficient vector initialization in Rust?
  • 38863781 How to create a tuple from a vector?
  • 38886081 How to save a PNG image in Rust?
  • 38888724 How to index vectors with integer types (besides usize), without explicit cast?
  • 38908103 Whats the best way to iterate over circular wrapped indices?
  • 38910078 How to a swap only some members of a struct in a vector?
  • 38911481 How to define a pass-through (identity or NOP) macro?
  • 38911652 What is a less verbose way to repeatedly pop() items from a vector?
  • 38918496 Is it possible to have a closure call itself in Rust?
  • 38928839 Is it possible to declare config tokens within a source file?
  • 38929233 Whats the best way to count indirect function calls conditionally using cfg attributes?
  • 38929524 How to measure a functions stack usage in Rust?
  • 38931479 Is it possible to prevent duplicate identical arguments to a macro in Rust?
  • 38941025 How to define a function with a generic fixed-length array?

Up until RE:fa20ff40