Project

General

Profile

« Previous | Next » 

Revision 9420f2fe

Added by Leszek Koltunski almost 8 years ago

Fix for Bug 19: SWIRL effect: mess if Center out of Region.

View differences:

src/main/res/raw/main_vertex_shader.glsl
50 50
//////////////////////////////////////////////////////////////////////////////////////////////
51 51
// HELPER FUNCTIONS
52 52
//////////////////////////////////////////////////////////////////////////////////////////////
53
// Let (v.x,v.y) be point P (the current vertex).
54
// Let vPoint[effect].xy be point S (the center of effect)
55
// Let vPoint[effect].xy + vRegion[effect].xy be point O (the center of the Region circle)
56
// Let X be the point where the halfline SP meets a) if region is non-null, the region circle b) otherwise, the edge of the bitmap.
57
//
58
// If P is inside the Region, this function returns |PX|/||SX|, aka the 'degree' of point P. Otherwise, it returns 0.
59
//
60
// We compute the point where half-line from S to P intersects the edge of the bitmap. If that's inside the circle, end. If not, we solve the
61
// the triangle with vertices at O, P and the point of intersection with the circle we are looking for X.
62
// We know the lengths |PO|, |OX| and the angle OPX , because cos(OPX) = cos(180-OPS) = -cos(OPS) = -PS*PO/(|PS|*|PO|)
63
// then from the law of cosines PX^2 + PO^2 - 2*PX*PO*cos(OPX) = OX^2 so
64
// PX = -a + sqrt(a^2 + OX^2 - PO^2) where a = PS*PO/|PS| but we are really looking for d = |PX|/(|PX|+|PS|) = 1/(1+ (|PS|/|PX|) ) and
65
// |PX|/|PS| = -b + sqrt(b^2 + (OX^2-PO^2)/PS^2) where b=PS*PO/|PS|^2 which can be computed with only one sqrt.
66
//
67
// the trick below is the if-less version of the
53
// The trick below is the if-less version of the
68 54
//
69 55
// t = dx<0.0 ? (u_objD.x-v.x) / (u_objD.x-ux) : (u_objD.x+v.x) / (u_objD.x+ux);
70 56
// h = dy<0.0 ? (u_objD.y-v.y) / (u_objD.y-uy) : (u_objD.y+v.y) / (u_objD.y+uy);
......
90 76
  }
91 77

  
92 78
//////////////////////////////////////////////////////////////////////////////////////////////
93
// return degree of the point as defined by the Region
94
// Currently only supports circles; .xy = vector from center of effect to the center of the circle, .z = radius
79
// Return degree of the point as defined by the Region. Currently only supports circular regions.
80
//
81
// Let 'PS' be the vector from point P (the current vertex) to point S (the center of the effect).
82
// Should work regardless if S is inside or outside of the circle.
83
// Let region.xy be the vector from point S to point O (the center point of the region circle)
84
// Let region.z be the radius of the region circle.
85
//
86
// If P is outside the circle, return 0.
87
// Otherwise, let X be the point where the halfline SP meets the region circle - return |PX|/||SX|,
88
// aka the 'degree' of point P.
89
//
90
// We solve the the triangle OPX.
91
// We know the lengths |PO|, |OX| and the angle OPX, because cos(OPX) = cos(180-OPS) = -cos(OPS) = -PS*PO/(|PS|*|PO|)
92
// then from the law of cosines PX^2 + PO^2 - 2*PX*PO*cos(OPX) = OX^2 so PX = -a + sqrt(a^2 + OX^2 - PO^2)
93
// where a = PS*PO/|PS| but we are really looking for d = |PX|/(|PX|+|PS|) = 1/(1+ (|PS|/|PX|) ) and
94
// |PX|/|PS| = -b + sqrt(b^2 + (OX^2-PO^2)/PS^2) where b=PS*PO/|PS|^2 which can be computed with only one sqrt.
95 95

  
96 96
float degree_region(in vec3 region, in vec2 PS)
97 97
  {
98 98
  vec2 PO  = PS + region.xy;
99 99
  float D = region.z*region.z-dot(PO,PO);      // D = |OX|^2 - |PO|^2
100

  
101
  if( D<=0.0 ) return 0.0;
102

  
100 103
  float ps_sq = dot(PS,PS);
101 104
  float one_over_ps_sq = 1.0/(ps_sq+1.0-sign(ps_sq));  // return 1.0 if ps_sq = 0.0
102 105
  float DOT  = dot(PS,PO)*one_over_ps_sq;
103 106

  
104
  return max(sign(D),0.0) / (1.0 + 1.0/(sqrt(DOT*DOT+D*one_over_ps_sq)-DOT));  // if D<=0 (i.e p is outside the Region) return 0.
107
  return 1.0 / (1.0 + 1.0/(sqrt(DOT*DOT+D*one_over_ps_sq)-DOT));
105 108
  }
106 109

  
107 110
//////////////////////////////////////////////////////////////////////////////////////////////
......
111 114
  {
112 115
  vec2 PO  = PS + region.xy;
113 116
  float D = region.z*region.z-dot(PO,PO);      // D = |OX|^2 - |PO|^2
117

  
118
  if( D<=0.0 ) return 0.0;
119

  
114 120
  vec2 A = sign(PS)*u_objD.xy + S;
115 121
  vec2 signA = sign(A);
116 122
  vec2 signA_SQ = signA*signA;
......
121 127
  float one_over_ps_sq = 1.0/(ps_sq+1.0-sign(ps_sq));  // return 1.0 if ps_sq = 0.0
122 128
  float DOT  = dot(PS,PO)*one_over_ps_sq;
123 129

  
124
  return max(sign(D),0.0) * min(1.0/(1.0 + 1.0/(sqrt(DOT*DOT+D*one_over_ps_sq)-DOT)),E);  // if D<=0 (i.e p is outside the Region) return 0.
130
  return min(1.0/(1.0 + 1.0/(sqrt(DOT*DOT+D*one_over_ps_sq)-DOT)),E);
125 131
  }
126 132

  
127 133
//////////////////////////////////////////////////////////////////////////////////////////////

Also available in: Unified diff