Sha,
What I did was to lay out a rectangular grid of points in my OpenGL coordinates. (I used a 50x50 grid). I then define one or more control points in that same coordinate space. I have a general pinch-stretch algorithm that I wrote. It takes a control point, a radius, and a signed integer for the amount to attract/repel grid points, and applies it to the coordinates of my grid. For a pinch, it pulls the grid points closer to the control point, and for a stretch, it pushes the control points away. The change is greatest at the control point and goes down as the distance from the control point increases up to the radius value.
Once I've changed the coordinates of my mesh, I then define a set of triangle strips that draws the entire (warped) rectangular area of my image. I can render my entire texture onto the warped mesh with one OpenGL drawing call. OpenGL takes care of stretching the image pixels to fit the distorted triangles in my mesh of control points. Here is a sample before/after image that uses several control points to create a fat-face look. It shows the mesh grid so you can see what it's doing. It's my ugly mug, so apologies in advance:
And the stretched image:
In my case I wanted the control points along the perimeter of the image to stay in place and only the interior of the image to be distorted, so I added extra code logic to lock the perimeter control points into place. That's why the frame of the image is not pushed in like in your image. That required extra code however.
The code ends up using the distance formula to figure out how far each grid-point is from a control point, and then trig to figure out the angle, multiplication to change the distance, and then more trig to calculate the new location for each grid-point. Since I'm only transforming a 50x50 grid of control points, though, its fast enough to keep up.
Our app, Face Dancer, is free on the app store. (Download it at this link: Face Dancer in the App store You might want to download it and try it out. (It includes a number of free morphs, and then offers additional morphs as in-app purchases) There is also a paid "Plus" version that has all the morphs included.
When you're running Face Dancer if you two finger double-tap on the image, it displays the grid of control points it's using to create the morph so you can see what it's doing.
There is an OpenGL sample app called GLCameraRipple that is included with Xcode and linked from the documentation. I would suggest taking a look at that as a starting point. It takes a video feed from the camera and draws it to the screen. If you touch the screen it distorts the image as if the screen were a pool of water and your finger was causing ripples in it. It uses a mesh warp technique like what I described.
Unfortunately I don't think the app uses GLKit, which is a much easier way to use OpenGL ES 2.0. GLKit offers a number of features that make it much easier to use, including GLKViews and GLKViewControllers.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…