benjamminf / warpjs

Warp, distort, bend, twist and smudge your SVG’s directly in the browser
https://benjamminf.github.io/warpjs
MIT License
480 stars 33 forks source link

Warping arbitrary coordinates? #11

Open fallenartist opened 6 years ago

fallenartist commented 6 years ago

Hi! Can individual points be controlled/warped with the script? I'm after a result as on the attached pic. Thanks. screen shot 2017-07-03 at 18 18 47

benjamminf commented 6 years ago

Achieving this effect is certainly possible with warp.js, but it'll require a bit of math and some knowledge of texture rendering in 2/3D graphics. What you'd want to do is use warp.js to warp the "WORD" SVG, and use texture mapping to project it onto the shape you have above.

This seems like a really interesting problem so I might give it a go and post my results here.

Can I ask how you produced this image? I'd like to inspect those tools to see how they do the math.

benjamminf commented 6 years ago

A bit of digging and I found this paper on generalised Barycentric coordinates, which I think would be a better method. It also looks like the method used in Illustrator's Envelope Distort feature. Just leaving this here for future reference.

fallenartist commented 6 years ago

Yes, the above image was created with AI's Envelope Distort (designer here). I've been scouting the Net for years to find a web based solution but I'm afraid your linked articles are way over my coding abilities to translate it into anything useful.

fallenartist commented 6 years ago

So far, I've found this, this and this (with source code). Maybe it will be of use for you.

benjamminf commented 6 years ago

That's all good, I don't expect anyone to be able to, I'm just leaving this here for reference for myself when I get around to tackling the problem. I think it's a useful and interesting feature that I'll probably write it into the library, but it might take a little bit of time – I'll keep this thread updated.

Thanks for the links. I had seen some of them before, but unfortunately they won't accomplish what you're after. What you need is to map a shape to some arbitrary polygon, one which can't be defined by some continuous mathematical function.

benjamminf commented 6 years ago

After much research, it seems like this is a feature that's disappointingly exclusive to Illustrator. Good news is I know roughly how they've implemented it, but it's quite mathematically complex so it's going to take some time to wrap my head around it. Just leaving these resources here for reference:

benjamminf commented 6 years ago

Success! I have created a proof of concept that works surprisingly well!

Things to note:

fallenartist commented 6 years ago

Wow, looks good! I'll play with it and report any issues.

As for Illustrator, it looks like envelope distortion, including built in presets, always creates a mesh grid around the object's bounding box, then applies a deformation. The grid is based on bezier curves – even straight lines are converted to curves (when using a custom drawn simple shape as a guide like in my first example above).

screen shot 2017-07-06 at 11 42 03

screen shot 2017-07-06 at 12 00 47

Interestingly, there's a Fidelity setting, where you can control the precision of distortion, so I guess it's a raster based effect.

screen shot 2017-07-06 at 11 58 16

In order to get a distorted vector, you need to Expand the effect. Fidelity=100:

screen shot 2017-07-06 at 12 08 40

And Fidelity=0:

screen shot 2017-07-06 at 12 09 18

benjamminf commented 6 years ago

Thanks for the detailed information and screenshots, it's really handy. From what I can see, the presets are like pre-made custom shapes, but some use a mesh for inner points (fig 1 and 3). The proof of concept doesn't (probably) support inner points, given the algorithm used. However it might with a little tweaking, since it still uses the same concept of barycentric coordinates.

You're right in that it always warps the target shape from it's bounding box. The proof of concept actually does this too – you'll notice the control points form the bounding box of the SVG when created. Illustrator seems to automatically figure this out for you when using custom shapes, so I'd like to implement the same. I have an algorithm in my head that I'm pretty sure will work, just need to sit down and try it out.

As for the fidelity, good to see my implementation does pretty much the same thing. I was worried they'd be a bit more clever with it! Fidelity for warp.js is essentially what the interpolate method is for. You'll see at the top of the proof of concept I'm interpolating the SVG – this is basically the "fidelity" option.

fallenartist commented 6 years ago

I've added custom font with bounding box detection and it works nicely.

One question – what does magnitude do?

benjamminf commented 6 years ago

That's cool! That magnitude variable wasn't necessary, I just had it there to make the code a bit cleaner.

razvanphp commented 6 years ago

Sorry to hijack this issue, but my question is rather similar: would it be possible to achieve this warping effect from photoshop (so 2d), for an image (logo)? Here's what I mean:

screen shot 2018-02-23 at 21 39 51

Thanks in advance!

natew commented 6 years ago

Wow, what a lucky stroke. Am looking for the exact effect @razvanphp posted, funny enough and couldn't believe how close this thread gets me. I'll post if I get anything going.

benjamminf commented 6 years ago

@razvanphp @natew I completely missed this back in Feb... GitHub no longer puts issue updates in my feed 👎so I miss them.

The fisheye or bulge effect you're after is a different effect altogether than the envelope distort. But thankfully it's actually much easier. I'm building this effect into the library, but I'm not sure how long it'll be until I complete it. In the meantime, here's a good reference if you're capable of the heavy math. It describes a fisheye effect on a pixel shader, but it's exactly the same thing for this library (though replace the word "pixel" with "path point").

jboarman commented 4 years ago

@benjamminf Do you accept bounties?! :moneybag: :grin: :moneybag:

I'm looking for a solution that works with a bounding SVG as the "fitting" shape that includes curves. Is that something you are still aiming to implement?

As a potential workaround, if one were to approximate a curved bounding shape with a series of small segments / control points, would you expect that to render a passable "curved" distortion? Or would you expect the warped distortion to have negative visual anomalies using this workaround method for curved fittings?

benjamminf commented 4 years ago

@jboarman unfortunately these days I have no time outside of my full time job :(

I'm looking for a solution that works with a bounding SVG as the "fitting" shape that includes curves. Is that something you are still aiming to implement?

Yes that's been the goal. There's still considerable work to be done to get this built into the library so I wouldn't hold my breath for it. Even though it's been well over a year since I've touched this project I still keep it in mind, but I have no plans or timelines.

As a potential workaround, if one were to approximate a curved bounding shape with a series of small segments / control points, would you expect that to render a passable "curved" distortion? Or would you expect the warped distortion to have negative visual anomalies using this workaround method for curved fittings?

This should work pretty well I'd say, depending on how small you make your line segments. I think the problem will be making the "squared" version of the fitting shape. With the example code in this thread it requires starting with a rectangular shape that the cartesian plane can be mapped to, then later distorting those points to the original shape it was. My intention was to write an algorithm to "square" your shapes for you, but I never got around to that. You may have to explore this yourself, as a shape with many points may be hard to manually "square".

PavelLaptev commented 3 years ago

@benjamminf made a concept with control points on your example above — https://pavellaptev.github.io/warp-svg/ Also, thank you for the great job you did

benjamminf commented 3 years ago

@PavelLaptev that's really awesome!! Such a nice interface, amazing work mate