Re: New version of mesh branch.

Hi guys,
I think the problem of discontinuity of color slopes at boundariescan be solved by applying a simple symmetric interpolant to the interpolation parameter prior to the bilinear interpolation.
Two such symmetric interpolants are sin^2 and the degenerate cubic Hermite (both end tangents set to zero).
The production becomes:
Either: bilinear( t=-2t^3+3t^2, colors... )or: bilinear( t=sin(t*pi/2)^2, colors... )
Where t is the interpolation parameter (u/v) over the unit square.
No matter what color is at which corner, this configuration ensures the derivative of the color change at all boundaries is zero.
Following demo implement the Hermite, results from sin^2 are very similar:http://owl3d.com/tests/Gradient_Mesh/bilinear_symmetric.html(Rest of the demos are in the same folder so referenced by file name only)
>From here on, the goal is to simulate the gradient mesh of the big guys (Illustrator/CorelDraw). I don't have access to CorelDraw, so the discussion is narrowed to the basic 2x2 Illustrator mesh - color1 center, rest color0!=color1.
>From symmetry reasons, it's enough if we simulate the top-left patch whichI will refer to as the basic (Illustrator) patch.
Couple years back, while trying to make strokes look like tubes, I bounced into the same discontinuity problem on the stroke skeleton as boundary. The above bilinear combo solution is an implementation of the solution described in the following article but symetrically:
http://owl3d.com/svg/tubefy/articles/article2.html
In the article, the interpolant is a quad because the goal is to produce a color profile to match a round-surface Lambertian diffused-light curve.
As it turn out, it seems like this is also the goal of the Illustrator mesh.If we examine the basic patch, we find that the color-profile of its right/bottom boundaries is also a quad. It means that to simulate the Illustrator mesh internal boundaries profiles *precisely*, all we need is to apply the above bilinear combo with a quad instead of the symmetric interpolant.
Does it mean the overall look of our mesh will be like the Illustrator mesh? Well, it might, but not guaranteed I'm afraid. Illustrator can produce internal quads as part of few different interpolation models,and I find it hard to believe any of them use bilinear blending on top of the quads.
Following demo applies pre-bilinear quad and sine interpolants to shoot at the basic Illustrator mesh. Unlike the symmetric interpolants above, differences between those two are noticeable so both of them are included. Note that because of their asymmetric nature, their direction is important so thattheir final zero slope lands on the internal boundaries.  The symmetric Hermite is also there for comparison: /bilinear_combos_compare.html
Observations: quad sample internal boundaries profile match as expected, but the diagonal profiles are slightly off. Our mesh is more "cushioned" while Illustrator mesh, though also cushioned, is more round. 
At this point, If we insist on keep following PDF type 6 advice to use bilinear interpolation, even with the combo trick, this is more or less the end of the road. 
In order to fine tune only the diagonal profile, we need to manipulate knots which are*only* on the diagonal, which the bilinear Bezier patch don't have. The "Bezier" is not a typo, bilinear interpolation over the unit square is a Bezier patch. Most primitive (degree 1), but still, a Bezier patch.
So in order to create internal control points, we turn to the next degree in line,the biquadratic Bezier patch. 
To start from the promising results we already got from the bilinear/quad combo, we can easily create precisely the same result - for the biquadratic Bezier patch to create quadratic profiles is really trivial:
PQ = [   [ [0, 0, 0], [1/2, 0, 0], [1, 0, 0] ],   [ [0, 1/2, 0], [1/2, 1/2, 1], [1, 1/2, 1] ],   [ [0, 1, 0], [1/2, 1, 1], [1, 1, 1] ] ];
Each row and each column are individual quadratic Bezier curves where the two colors are normalized to values 0 and 1 and are interpolated as the 3rd dimension. 
Note the projected 2D control polygon is still the unit square.Note the similarity between the color values on both two last rows and two lastcolumns, those same values is what guarantee the zero slopes at the right/bottom boundaries.
No point of showing the result of this patch as it is identical to the quad sample on the last demo, still, I think a 3D visualization of this patch will be helpful.
In the following image, view direction is perpendicular to the black-white diagonal (replaced by navy-aqua) so we can have an undistorted picture of its S shape profile.The red curve is what we are after - the diagonal profile of the basic patch.Note this wire-mesh was drawn without perspective correction so we can be surethat any curved wire is exclusively due to patch curvature: /wire_qBez.html
Yes, the basic patch profile is broken to linears around the top. Don't ask me, I just draw what I got from Illustrator: /basicMesh2x2.svg
Since we already simulate the internal boundaries, if we can make our diagonal profileto look like the Illustrator diagonal profile, then their overall shape should match.
Doing so must involve manipulating one or more control points along the diagonal.We cannot manipulate end points because they define the corner colors and we cannotmanipulate the nearest point to a boundary point because it will kill the boundary continuity, which means, practically, that with biquadratic Bezier patch there is nothing we can do.
Using the same remarkable degree-elevation quality of Bezier curves which we alreadyused to elevate the bilinear to biquadratic, we now elevate the biquadratic to bicubic.
Following bicubic Bezier patch is a one degree-elevation of PQ. It describes precisely the same shape:
PC = [ [ [ 0, 0, 0 ], [ 1/3, 0, 0 ], [ 2/3, 0, 0 ], [ 1, 0, 0 ] ],[ [ 0, 1/3, 0 ], [ 1/3, 1/3, 4/9 ], [ 2/3, 1/3, 2/3 ], [ 1, 1/3, 2/3 ] ],[ [ 0, 2/3, 0 ], [ 1/3, 2/3, 2/3 ], [ 2/3, 2/3, 1 ], [ 1, 2/3, 1 ] ],[ [ 0, 1, 0 ], [ 1/3, 1, 2/3 ], [ 2/3, 1, 1 ], [ 1, 1, 1 ] ] ];
With same reasoning as above, the only knot free for manipulation is PC[1][1]or more precisely PC[1][1][2] value because we manipulate only the 3rd dimension.
We can calculate the new value for this point:- find the result color at that point on the Illustrator patch (roughly 57-58)- find which PC[1][1][2] value will create the same color on the Bezier patch.Or,after contemplating on the last demo (/wire_qBez.html), we can come up with an educated guess:Observing the Illustrator profile goes through the center of the unit cube (the intersection of the gray cross), we can reasonably assume that its profileis symmetric around the center, and if so, then PC[1][1][2] = 1-PC[2][2][2] holds,which means the new value is... zero! 
Plugging this value to PC[1][1][2] creates result which finally looks the same as the basic mesh. Judge for yourself: /final_compare.html
In the last demo, the overlay is a maximum resolution topographical-map of the color values to show subtle differences in the texture. It was created with the hope it will shed some light on why the basic mesh diagonal profile is broken near the center.
Two other visualizations to allow profiles comparison: - Final result with profiles on top of Illustrator same profiles: /final_profiles.html- Wire-mesh of the final patch with overlay Illustrator profile: /wire_cBez.html
Please note this is still a simulation of the very basic configuration and use cases where more colors assigned to other corners are yet to be investigated.

Demos use Canvas to allow for sub-pixel manipulations without littering the SVGDOM with zillions of 1pixel objects (and with the spirit of the new Graphical Web :)).
Code written for fast production so might be inefficient in places and/or carry someghost variables/attributes.
Tested on Chrome16 only.
Regards,Israel

Received on Thursday, 2 February 2012 21:25:54 UTC