# PageTurningUIEffect

A page turning UI effect made with unity, the paper deformation is determined by the pins’ position on it.

## Algorithm

This algorithm is about wrapping a paper around a cylinder and calculate the vertexes’ positions on the paper. First, let’s imagine dragging the mouse from a paper’s right up corner, and a cylinder whose central axis always pass through the mouse position and perpendicular to the mouse drag direction dynamically, just like Fig.1.

Fig.1

#### Cylinder central axis

The mouse drag direction will be determined by the current mouse position and a corner of the parper, that means as you clicked and dragging the mouse on the paper, the start point of the vector will always be one of the four corners of the paper and end point is the mouse’s position. You may ask why not calculated the vector by the mouse’s position in last frame as the start point and the mouse’s position in this frame as the end point. Try it and look the paper’s behaviour 😃

Assume we drag the paper at right up corner on 3D coordinate system, the paper is on the xz coordinate plane and its corner position is `(x0, y0, z0)`

. Currently the mouse’s position is `(x1, y1, z1)`

. The straight line equation can be derived as `z=(z1-z0)/(x1-x0)*x+z1+(z0-z1)/(x1-x0)*x1`

. Then the central axis of the cylinder which is perpendicular to the mouse dragging direction can be derived as `z=(x1-x0)/(z0-z1)*x+z1+(x0-x1)/(z0-z1)*x1`

.

#### Paper deformation

The right up part of the paper will be wrapped on the cylinder as Fig.2.

Fig.2

Let’s choose a vertex on the paper, its position is `(xv, yv, zv)`

, the distance of the vertex to the cylinder’s central axis on xz coordinate plane is `dist=abs(A*xv+B*zv+C)/sqrt(A*A+B*B)`

, `A=(x1-x0)/(y0-y1)`

, `B=-1`

, `C=z1+(x0-x1)/(z0-z1)*x1`

.

In Fig.2, we can get `θ=dist/R`

(clyinder’s radius is `R`

). The y position of the vertex on the paper after wrapping on the cylinder is `yv=R-R*cosθ`

.

The move direction on xz coordinate plane of this vertex is `dir=(x1, z1)-(x0, z0)`

. The xz position of the vertex on the paper after wrapping on the cylinder is `(xv, zv)+normalized(dir)*(dist-R*sinθ)`

.

When the paper wrapped on the cylinder exceed 180 degree, we flatten the exceed part and the position of vertexes on this part can be derived as `(xv, zv)+normalized(dir)*(dist+dist-pi*R)`

and `yv=2*R`

, if you can not figure out the equation, just try to draw the image as Fig.2 and wrap large part of the paper on the cylinder.

We need to determine which part of the paper should be wrapped on the cylinder, we can use cross product to check if the vertex on the paper is in clockwise direction of the vector which is acquired by rotating the mouse dragging direction 90 degree in clockwise direction. The start point of the vector is `(x1, z1)`

, the end point of the vector is `(x2, z2)`

, the check point is `(x3, z3)`

. The cross product is `(x1-x3)*(z2-z3)-(x2-x3)*(z1-z3)`

, if it’s negative the check point is in clockwise direction.

When the mouse button up, the paper need to be flattened smoothly. This can be implemented by scrolling the cylinder back along the mouse drag direction to the paper’s corner.

#### Paper deformation with considering Pins on it

Let’s imagine turning a paper which has a pin on it. The paper curling as you dragging it from right to left until it touches a pin. Unless you tear the paper, it can not move along current drag direction anymore. We can only drag the paper around the pin, but not curling it. This effect is really easy to implement 😃

Assume we put lots of pins on a paper, then we drag the paper from right up corner to left as some direction. How could we determine which pin is first touched by the cylinder’s central axis? We have derived the direction which is acquired by rotating the mouse drag direction 90 degree in clockwise direction `newDir=(z1-z0, x0-x1)`

. We only need to set the start point of the vector as a pin’s position, and check if there is a pin in clockwise direction of it (just like what we did in above to check which part of the paper should be wrapped on the cylinder). We find a pin which has no pins in clockwise direction of it, and it must be the first pin the cylinder’s central axis touches.

Now, we have the pin’s position and just replace the mouse position in above calculation as the pin’s position. The steps are:

```
1. Drag the mouse and acquire the cylinder's central axis;
2. Find the pin which will be first touched by the cylinder's central axis;
3. Scroll back the cylinder from mouse's position to pin's position with keeping its direction unchanged.
```

That’s the main part of this page turning algorithm, if you have any question, please don’t hesitate to contact me 😃