Project

General

Profile

« Previous | Next » 

Revision 18d15f2f

Added by Leszek Koltunski about 8 years ago

Polish up DEFORM.

View differences:

src/main/res/raw/main_vertex_shader.glsl
161 161
//////////////////////////////////////////////////////////////////////////////////////////////
162 162
// DEFORM EFFECT
163 163
//
164
// Deform the whole shape of the Object by force V
165
// 
166
// If the point of application (Sx,Sy) is on the upper edge of the Object, then:
167
// a) ignore Vz
168
// b) change shape of the whole Object in the following way:
169
//    Suppose the upper-left corner of the Object rectangle is point L, upper-right - R, force vector V
170
//    is applied to point M on the upper edge, width of the Object = w, height = h, |LM| = Wl, |MR| = Wr,
171
//    force vector V=(Vx,Vy). Also let H = h/(h+Vy)
172
//
173
//    Let now L' and R' be points such that vec(LL') = Wr/w * vec(V) and vec(RR') = Wl/w * vec(V)
174
//    now let Vl be a point on the line segment L --> M+vec(V) such that Vl(y) = L'(y)
175
//    and let Vr be a point on the line segment R --> M+vec(V) such that Vr(y) = R'(y)
176
//    
177
//    Now define points Fl and Fr, the points L and R will be moved to under force V, with Fl(y)=L'(y)
178
//    and Fr(y)=R'(y) and |VrFr|/|VrR'| = |VlFl|/|VlL'| = H
179
//    Now notice that |VrR'| = |VlL'| = Wl*Wr / w   ( a little geometric puzzle! )
180
//
181
//    Then points L,R under force V move by vectors vec(Fl), vec(Fr) where
182
//    vec(Fl) = (Wr/w) * [ (Vx+Wl)-Wl*H, Vy ] = (Wr/w) * [ Wl*Vy / (h+Vy) + Vx, Vy ]
183
//    vec(Fr) = (Wl/w) * [ (Vx-Wr)+Wr*H, Vy ] = (Wl/w) * [-Wr*Vy / (h+Vy) + Vx, Vy ]
184
//
185
//    Lets now denote M+vec(V) = M'. The line segment LMR gets distorted to the curve Fl-M'-Fr. Let's
186
//    now arbitrarilly decide that:
187
//    a) at point Fl the curve has to be parallel to line LM'
188
//    b) at point M' - to line LR
189
//    c) at point Fr - to line M'R
190
//
191
//    Now if Fl=(flx,fly) , M'=(mx,my) , Fr=(frx,fry); direction vector at Fl is (vx,vy) and at M'
192
//    is (+c,0) where +c is some positive constant, then  the parametric equations of the Fl--->M'
193
//    section of the curve (which has to satisfy (X(0),Y(0)) = Fl, (X(1),Y(1))=M',
194
//    (X'(0),Y'(0)) = (vx,vy), (X'(1),Y'(1)) = (+c,0) ) is
195
//
196
//    X(t) = ( (mx-flx)-vx )t^2 + vx*t + flx                                  (*)
197
//    Y(t) = ( vy - 2(my-fly) )t^3 + ( 3(my-fly) -2vy )t^2 + vy*t + fly
198
//
199
//    Here we have to have X'(1) = 2(mx-flx)-vx which is positive <==> vx<2(mx-flx). We also have to
200
//    have vy<2(my-fly) so that Y'(t)>0 (this is a must otherwise we have local loops!)
201
//    Similarly for the Fr--->M' part of the curve we have the same equation except for the fact that
202
//    this time we have to have X'(1)<0 so now we have to have vx>2(mx-frx).
203
//
204
//    If we are stretching the left or right edge of the bitmap then the only difference is that we
205
//    have to have (X'(1),Y'(1)) = (0,+-c) with + or - c depending on which part of the curve
206
//    we are tracing. Then the parametric equation is
207
//
208
//    X(t) = ( vx - 2(mx-flx) )t^3 + ( 3(mx-flx) -2vx )t^2 + vx*t + flx
209
//    Y(t) = ( (my-fly)-vy )t^2 + vy*t + fly
210
//
211
//    If we are dragging the top edge:    
212
//
213
//    Then point (x,h/2) on the top edge will move by vector (X(t),Y(t)) where those functions are
214
//    given by (*) and t =  x < dSx ? (w/2+x)/(w/2+dSx) : (w/2-x)/(w/2-dSx)    (-w/2 < x < +w/2 !)
215
//    (this is 'vec2 time' below in the code).
216
//    Any point (x,y) will move by vector (a*X(t),a*Y(t)) where a is (y+h/2)/h
217
  
164
// Deform the whole shape of the Object by force V. Algorithm is as follows:
165
//
166
// Suppose we apply force (Vx,Vy) at point (Cx,Cy) (i.e. the center of the effect). Then, first of all,
167
// divide the rectangle into 4 smaller rectangles along the 1 horizontal + 1 vertical lines that pass
168
// through (Cx,Cy). Now suppose we have already understood the following case:
169
//
170
// A vertical (0,Vy) force applied to a rectangle (WxH) in size, at center which is the top-left corner
171
// of the rectangle.  (*)
172
//
173
// If we understand (*), then we understand everything, because in order to compute the movement of the
174
// whole rectangle we can apply (*) 8 times: for each one of the 4 sub-rectangles, apply (*) twice,
175
// once for the vertical component of the force vector, the second time for the horizontal one.
176
//
177
// Let's then compute (*):
178
// 1) the top-left point will move by exactly (0,Vy)
179
// 2) we arbitrarily decide that the top-right point will move by (|Vy|/(|Vy|+A*W))*Vy, where A is some
180
//    arbitrary constant (const float A below). The F(V,W) = (|Vy|/(|Vy|+A*W)) comes from the following:
181
//    a) we want F(V,0) = 1
182
//    b) we want lim V->inf (F) = 1
183
//    c) we actually want F() to only depend on W/V, which we have here.
184
// 3) then the top edge of the rectangle will move along the line Vy*G(x), where G(x) = (1 - (A*W/(|Vy|+A*W))*(x/W)^2)
185
// 4) Now we decide that the left edge of the rectangle will move along Vy*H(y), where H(y) = (1 - |y|/(|Vy|+C*|y|))
186
//    where C is again an arbitrary constant. Again, H(y) comes from the requirement that no matter how
187
//    strong we push the left edge of the rectangle up or down, it can never 'go over itself', but its
188
//    length will approach 0 if squeezed very hard.
189
// 5) The last point we need to compute is the left-right motion of the top-right corner (i.e. if we push
190
//    the top-left corner up very hard, we want to have the top-right corner not only move up, but also to
191
//    the left at least a little bit).
192
//    We arbitrarily decide that, in addition to moving up-down by Vy*F(V,W), the corner will also move
193
//    left-right by I(V,W) = B*W*F(V,W), where B is again an arbitrary constant.
194
// 6) combining 3), 4) and 5) together, we arrive at a movement of an arbitrary point (x,y) away from the
195
//    top-left corner:
196
//    X(x,y) = -B*x * (|Vy|/(|Vy|+A*W)) * (1-(y/H)^2)                               (**)
197
//    Y(x,y) = Vy * (1 - |y|/(|Vy|+C*|y|)) * (1 - (A*W/(|Vy|+A*W))*(x/W)^2)         (**)
198
//
199
// We notice that formulas (**) have been construed so that it is possible to continously mirror them
200
// left-right and up-down (i.e. apply not only to the 'bottom-right' rectangle of the 4 subrectangles
201
// but to all 4 of them!).
202
//
203
// Constants:
204
// a) A : valid values: (0,infinity). 'Bendiness' if the surface - the higher A is, the more the surface
205
//        bends. A<=0 destroys the system,
206
// b) B : valid values: <-1,1>. The amount side edges get 'sucked' inwards when we pull the middle of the
207
//        top edge up. B=0 --> not at all, B=1: a looot. B=-0.5: the edges will actually be pushed outwards
208
//        quite a bit. One can also set it to <-1 or >1, but it will look a bit ridiculous.
209
// c) C : valid values: <1,infinity). The derivative of the H(y) function at 0, i.e. the rate of 'squeeze'
210
//        surface gets along the force line. C=1: our point gets pulled very closely to points above it
211
//        even when we apply only small vertical force to it. The higher C is, the more 'uniform' movement
212
//        along the force line is.
213
//        0<=C<1 looks completely ridiculous and C<0 destroys the system.
214

  
218 215
void deform(in int effect, inout vec4 v)
219 216
  {
217
  const vec2 one = vec2(1.0,1.0);
218

  
220 219
  const float A = 0.5;
221
  const float B = 0.3;
220
  const float B = 0.2;
221
  const float C = 5.0;
222 222

  
223 223
  vec2 center = vUniforms[effect+1].yz;
224 224
  vec2 force  = vUniforms[effect].xy;
......
229 229

  
230 230
  vec2 Aw = A*maxdist;
231 231
  vec2 quot = dist / maxdist;
232
  quot = quot*quot;                          // ( (x/W)^2 , (y/H)^2 ) where x,y are distances from V to center
233

  
234
  float denomV = 1.0 / (aForce.y + Aw.x);
235
  float denomH = 1.0 / (aForce.x + Aw.y);
232 236

  
233
  float mvXvert =-((B*dist.x*aForce.y)/(aForce.y + Aw.x))*(1.0-quot.y*quot.y);
234
  float mvYvert = force.y*( 1.0 - quot.x*quot.x*(Aw.x/(aForce.y+Aw.x)) ) * aForce.y/(aForce.y+aDist.y);
237
  vec2 vertCorr= one - aDist / ( aForce+C*aDist + (one-sign(aForce)) );
235 238

  
236
  float mvXhorz =-force.x*( 1.0 - quot.y*quot.y*(Aw.y/(aForce.x+Aw.y)) ) * aForce.x/(aForce.x+aDist.x);
237
  float mvYhorz =-((B*dist.y*aForce.x)/(aForce.x + Aw.y))*(1.0-quot.x*quot.x);
239
  float mvXvert = -B * dist.x * aForce.y * (1.0-quot.y) * denomV;    // impact the vertical   component of the force vector has on horizontal movement
240
  float mvYhorz = -B * dist.y * aForce.x * (1.0-quot.x) * denomH;    // impact the horizontal component of the force vector has on vertical   movement
241
  float mvYvert =  force.y * (1.0-quot.x*Aw.x*denomV) * vertCorr.y;  // impact the vertical   component of the force vector has on vertical   movement
242
  float mvXhorz = -force.x * (1.0-quot.y*Aw.y*denomH) * vertCorr.x;  // impact the horizontal component of the force vector has on horizontal movement
238 243

  
239 244
  v.x -= (mvXvert+mvXhorz);
240 245
  v.y -= (mvYvert+mvYhorz);

Also available in: Unified diff