RGB colors were represented using a uint32_t with the red, green and blue
values stuffed into the lower three octets (i.e. 0x00BBGGRR), like
Microsoft's COLORREF. This approach did not lend itself to type safety,
however, so this change replaces it with an RgbColor class that provides
the same infomation plus a handful of useful methods to work with it. (Note
that sizeof(RgbColor) == sizeof(uint32_t), so this change should not lead
to memory bloat.)
Some of the new methods/fields replace what were previously macro calls;
e.g. RED(c) is now c.red, REDf(c) is now c.redF(). The .Equals() method is
now used instead of == to compare colors.
RGB colors still need to be represented as packed integers in file I/O and
preferences, so the methods .FromPackedInt() and .ToPackedInt() are
provided. Also implemented are Cnf{Freeze,Thaw}Color(), type-safe wrappers
around Cnf{Freeze,Thaw}Int() that facilitate I/O with preferences.
(Cnf{Freeze,Thaw}Color() are defined outside of the system-dependent code
to minimize the footprint of the latter; because the same can be done with
Cnf{Freeze,Thaw}Bool(), those are also moved out of the system code with
this commit.)
Color integers were being OR'ed with 0x80000000 in some places for two
distinct purposes: One, to indicate use of a default color in
glxFillMesh(); this has been replaced by use of the .UseDefault() method.
Two, to indicate to TextWindow::Printf() that the format argument of a
"%Bp"/"%Fp" specifier is an RGB color rather than a color "code" from
TextWindow::bgColors[] or TextWindow::fgColors[] (as the specifier can
accept either); instead, we define a new flag "z" (as in "%Bz" or "%Fz") to
indicate an RGBcolor pointer, leaving "%Bp"/"%Fp" to indicate a color code
exclusively.
(This also allows TextWindow::meta[][].bg to be a char instead of an int,
partly compensating for the new .bgRgb field added immediately after.)
In array declarations, RGB colors could previously be specified as 0 (often
in a terminating element). As that no longer works, we define NULL_COLOR,
which serves much the same purpose for RgbColor variables as NULL serves
for pointers.
surface's domain of u, v in [0, 1]. Cache the starting guess when
projecting a point into a ratpoly surface, to avoid brute force
searching for a good one every time. Split edges even if they
aren't quite inside the trim curve, since the trim boundaries are
pwl, not exact; unnecessary splits won't hurt, but failure to split
when necessary will. Make the triangulation code use a better (but
not perfect) epsilon, to avoid "can't find ear" failures on very
fine meshes.
And turn on compiler optimization! I had somehow forgotten about
that, and it's a ~2x improvement.
[git-p4: depot-paths = "//depot/solvespace/": change = 2026]
Otherwise, we might merge in ways that make things slower (because
the bboxes aren't as tight) or less robust (because the
intersection needs to be split in more places, and that might fail).
[git-p4: depot-paths = "//depot/solvespace/": change = 2003]
bad seems to happen when a trim curve's u or v coordinate goes even
slightly outside [0, 1]. And since I considered the bbox of the pwl
segments when merging coincident surfaces (and not the true
curves), that happened. So add a bit of slop, which seems to make
things happy.
[git-p4: depot-paths = "//depot/solvespace/": change = 1999]
empty (no trims) surfaces. It will generate a screwy bounding box,
which will make things break numerically later.
[git-p4: depot-paths = "//depot/solvespace/": change = 1979]
of revolution, and put them in the same form as if they had been
draw by an extrusion (so that we can use all the same special case
intersection curves).
And add code to merge coincident faces into one. That turns out to
be more than a cosmetic/efficiency thing, since edge splitting
fails at the join between two coincident faces.
[git-p4: depot-paths = "//depot/solvespace/": change = 1965]