1 |
125cee3d
|
Leszek Koltunski
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
2 |
|
|
// Copyright 2017 Leszek Koltunski //
|
3 |
|
|
// //
|
4 |
|
|
// This file is part of Distorted. //
|
5 |
|
|
// //
|
6 |
|
|
// Distorted is free software: you can redistribute it and/or modify //
|
7 |
|
|
// it under the terms of the GNU General Public License as published by //
|
8 |
|
|
// the Free Software Foundation, either version 2 of the License, or //
|
9 |
|
|
// (at your option) any later version. //
|
10 |
|
|
// //
|
11 |
|
|
// Distorted is distributed in the hope that it will be useful, //
|
12 |
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
13 |
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
14 |
|
|
// GNU General Public License for more details. //
|
15 |
|
|
// //
|
16 |
|
|
// You should have received a copy of the GNU General Public License //
|
17 |
|
|
// along with Distorted. If not, see <http://www.gnu.org/licenses/>. //
|
18 |
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
19 |
|
|
|
20 |
|
|
package org.distorted.library.effect;
|
21 |
|
|
|
22 |
|
|
import org.distorted.library.type.Data3D;
|
23 |
|
|
import org.distorted.library.type.Data4D;
|
24 |
15aa7d94
|
Leszek Koltunski
|
import org.distorted.library.type.Static4D;
|
25 |
125cee3d
|
Leszek Koltunski
|
|
26 |
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
27 |
faa3ff56
|
Leszek Koltunski
|
/**
|
28 |
|
|
* Distort the Mesh by applying a 3D vector of force.
|
29 |
|
|
*/
|
30 |
125cee3d
|
Leszek Koltunski
|
public class VertexEffectDistort extends VertexEffect
|
31 |
|
|
{
|
32 |
0dd98279
|
Leszek Koltunski
|
private Data3D mVector, mCenter;
|
33 |
|
|
private Data4D mRegion;
|
34 |
|
|
|
35 |
125cee3d
|
Leszek Koltunski
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
36 |
6bb59aad
|
Leszek Koltunski
|
/**
|
37 |
faa3ff56
|
Leszek Koltunski
|
* Only for use by the library itself.
|
38 |
6bb59aad
|
Leszek Koltunski
|
*
|
39 |
faa3ff56
|
Leszek Koltunski
|
* @y.exclude
|
40 |
6bb59aad
|
Leszek Koltunski
|
*/
|
41 |
15aa7d94
|
Leszek Koltunski
|
public boolean compute(float[] uniforms, int index, long currentDuration, long step )
|
42 |
|
|
{
|
43 |
0dd98279
|
Leszek Koltunski
|
mCenter.get(uniforms,index+5,currentDuration,step);
|
44 |
|
|
mRegion.get(uniforms,index+8,currentDuration,step);
|
45 |
|
|
boolean ret = mVector.get(uniforms,index,currentDuration,step);
|
46 |
15aa7d94
|
Leszek Koltunski
|
|
47 |
|
|
uniforms[index+1] =-uniforms[index+1];
|
48 |
82d6f93a
|
Leszek Koltunski
|
uniforms[index+9] =-uniforms[index+9];
|
49 |
15aa7d94
|
Leszek Koltunski
|
|
50 |
|
|
return ret;
|
51 |
125cee3d
|
Leszek Koltunski
|
}
|
52 |
7cd24173
|
leszek
|
|
53 |
faa3ff56
|
Leszek Koltunski
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
54 |
|
|
// PUBLIC API
|
55 |
7cd24173
|
leszek
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
56 |
|
|
// Point (Px,Py) gets moved by vector (Wx,Wy,Wz) where Wx/Wy = Vx/Vy i.e. Wx=aVx and Wy=aVy where
|
57 |
|
|
// a=Py/Sy (N --> when (Px,Py) is above (Sx,Sy)) or a=Px/Sx (W) or a=(w-Px)/(w-Sx) (E) or a=(h-Py)/(h-Sy) (S)
|
58 |
|
|
// It remains to be computed which of the N,W,E or S case we have: answer: a = min[ Px/Sx , Py/Sy , (w-Px)/(w-Sx) , (h-Py)/(h-Sy) ]
|
59 |
|
|
// Computations above are valid for screen (0,0)x(w,h) but here we have (-w/2,-h/2)x(w/2,h/2)
|
60 |
|
|
//
|
61 |
|
|
// the vertical part
|
62 |
|
|
// Let |(v.x,v.y),(ux,uy)| = |PS|, ux-v.x=dx,uy-v.y=dy, f(x) (0<=x<=|SX|) be the shape of the side of the bubble.
|
63 |
|
|
// H(v.x,v.y) = |PS|>|SX| ? 0 : f(|PX|)
|
64 |
|
|
// N(v.x,v.y) = |PS|>|SX| ? (0,0,1) : ( -(dx/|PS|)sin(beta), -(dy/|PS|)sin(beta), cos(beta) ) where tan(beta) is f'(|PX|)
|
65 |
|
|
// ( i.e. normalize( dx, dy, -|PS|/f'(|PX|))
|
66 |
|
|
//
|
67 |
|
|
// Now we also have to take into account the effect horizontal move by V=(u_dVx[i],u_dVy[i]) will have on the normal vector.
|
68 |
|
|
// Solution:
|
69 |
|
|
// 1. Decompose the V into two subcomponents, one parallel to SX and another perpendicular.
|
70 |
|
|
// 2. Convince yourself (draw!) that the perpendicular component has no effect on normals.
|
71 |
|
|
// 3. The parallel component changes the length of |SX| by the factor of a=(|SX|-|Vpar|)/|SX| (where the length
|
72 |
|
|
// can be negative depending on the direction)
|
73 |
|
|
// 4. that in turn leaves the x and y parts of the normal unchanged and multiplies the z component by a!
|
74 |
|
|
//
|
75 |
|
|
// |Vpar| = (u_dVx[i]*dx - u_dVy[i]*dy) / sqrt(ps_sq) = (Vx*dx-Vy*dy)/ sqrt(ps_sq) (-Vy because y is inverted)
|
76 |
|
|
// a = (|SX| - |Vpar|)/|SX| = 1 - |Vpar|/((sqrt(ps_sq)/(1-d)) = 1 - (1-d)*|Vpar|/sqrt(ps_sq) = 1-(1-d)*(Vx*dx-Vy*dy)/ps_sq
|
77 |
|
|
//
|
78 |
|
|
// Side of the bubble
|
79 |
|
|
//
|
80 |
|
|
// choose from one of the three bubble shapes: the cone, the thin bubble and the thick bubble
|
81 |
|
|
// Case 1:
|
82 |
|
|
// f(t) = t, i.e. f(x) = uz * x/|SX| (a cone)
|
83 |
|
|
// -|PS|/f'(|PX|) = -|PS|*|SX|/uz but since ps_sq=|PS|^2 and d=|PX|/|SX| then |PS|*|SX| = ps_sq/(1-d)
|
84 |
|
|
// so finally -|PS|/f'(|PX|) = -ps_sq/(uz*(1-d))
|
85 |
|
|
//
|
86 |
|
|
// Case 2:
|
87 |
|
|
// f(t) = 3t^2 - 2t^3 --> f(0)=0, f'(0)=0, f'(1)=0, f(1)=1 (the bell curve)
|
88 |
|
|
// here we have t = x/|SX| which makes f'(|PX|) = 6*uz*|PS|*|PX|/|SX|^3.
|
89 |
|
|
// so -|PS|/f'(|PX|) = (-|SX|^3)/(6uz|PX|) = (-|SX|^2) / (6*uz*d) but
|
90 |
|
|
// d = |PX|/|SX| and ps_sq = |PS|^2 so |SX|^2 = ps_sq/(1-d)^2
|
91 |
|
|
// so finally -|PS|/f'(|PX|) = -ps_sq/ (6uz*d*(1-d)^2)
|
92 |
|
|
//
|
93 |
|
|
// Case 3:
|
94 |
|
|
// f(t) = 3t^4-8t^3+6t^2 would be better as this satisfies f(0)=0, f'(0)=0, f'(1)=0, f(1)=1,
|
95 |
|
|
// f(0.5)=0.7 and f'(t)= t(t-1)^2 >=0 for t>=0 so this produces a fuller, thicker bubble!
|
96 |
|
|
// then -|PS|/f'(|PX|) = (-|PS|*|SX)) / (12uz*d*(d-1)^2) but |PS|*|SX| = ps_sq/(1-d) (see above!)
|
97 |
|
|
// so finally -|PS|/f'(|PX|) = -ps_sq/ (12uz*d*(1-d)^3)
|
98 |
|
|
//
|
99 |
|
|
// Now, new requirement: we have to be able to add up normal vectors, i.e. distort already distorted surfaces.
|
100 |
|
|
// If a surface is given by z = f(x,y), then the normal vector at (x0,y0) is given by (-df/dx (x0,y0), -df/dy (x0,y0), 1 ).
|
101 |
|
|
// so if we have two surfaces defined by f1(x,y) and f2(x,y) with their normals expressed as (f1x,f1y,1) and (f2x,f2y,1)
|
102 |
|
|
// then the normal to g = f1+f2 is simply given by (f1x+f2x,f1y+f2y,1), i.e. if the third components are equal, then we
|
103 |
|
|
// can simply add up the first and second components.
|
104 |
|
|
//
|
105 |
|
|
// Thus we actually want to compute N(v.x,v.y) = a*(-(dx/|PS|)*f'(|PX|), -(dy/|PS|)*f'(|PX|), 1) and keep adding
|
106 |
|
|
// the first two components. (a is the horizontal part)
|
107 |
faa3ff56
|
Leszek Koltunski
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
108 |
|
|
/**
|
109 |
|
|
* Have to call this before the shaders get compiled (i.e before Distorted.onCreate()) for the Effect to work.
|
110 |
|
|
*/
|
111 |
7cd24173
|
leszek
|
public static void enable()
|
112 |
|
|
{
|
113 |
|
|
addEffect(EffectName.DISTORT,
|
114 |
|
|
|
115 |
|
|
"vec2 center = vUniforms[effect+1].yz; \n"
|
116 |
|
|
+ "vec2 ps = center-v.xy; \n"
|
117 |
|
|
+ "vec3 force = vUniforms[effect].xyz; \n"
|
118 |
|
|
+ "float d = degree(vUniforms[effect+2],center,ps); \n"
|
119 |
|
|
+ "float denom = dot(ps+(1.0-d)*force.xy,ps); \n"
|
120 |
|
|
+ "float one_over_denom = 1.0/(denom-0.001*(sign(denom)-1.0)); \n" // = denom==0 ? 1000:1/denom;
|
121 |
|
|
|
122 |
|
|
//v.z += force.z*d; // cone
|
123 |
|
|
//b = -(force.z*(1.0-d))*one_over_denom; //
|
124 |
|
|
|
125 |
|
|
//v.z += force.z*d*d*(3.0-2.0*d); // thin bubble
|
126 |
|
|
//b = -(6.0*force.z*d*(1.0-d)*(1.0-d))*one_over_denom; //
|
127 |
|
|
|
128 |
|
|
+ "v.z += force.z*d*d*(3.0*d*d -8.0*d +6.0); \n" // thick bubble
|
129 |
|
|
+ "float b = -(12.0*force.z*d*(1.0-d)*(1.0-d)*(1.0-d))*one_over_denom; \n" //
|
130 |
|
|
|
131 |
|
|
+ "v.xy += d*force.xy; \n"
|
132 |
|
|
+ "n.xy += n.z*b*ps;"
|
133 |
|
|
);
|
134 |
|
|
}
|
135 |
faa3ff56
|
Leszek Koltunski
|
|
136 |
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
137 |
|
|
/**
|
138 |
6b816678
|
Leszek Koltunski
|
* Distort a (possibly changing in time) part of the Mesh by a (possibly changing in time) vector of force.
|
139 |
faa3ff56
|
Leszek Koltunski
|
*
|
140 |
|
|
* @param vector vector of force the Center of the Effect is currently being dragged with.
|
141 |
|
|
* @param center 3-dimensional Data that, at any given time, returns the Center of the Effect.
|
142 |
|
|
* @param region Region that masks the Effect.
|
143 |
|
|
*/
|
144 |
|
|
public VertexEffectDistort(Data3D vector, Data3D center, Data4D region)
|
145 |
|
|
{
|
146 |
|
|
super(EffectName.DISTORT);
|
147 |
|
|
mVector = vector;
|
148 |
|
|
mCenter = center;
|
149 |
|
|
mRegion = (region==null ? new Static4D(0,0,Float.MAX_VALUE, Float.MAX_VALUE) : region);
|
150 |
|
|
}
|
151 |
|
|
|
152 |
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
153 |
|
|
/**
|
154 |
6b816678
|
Leszek Koltunski
|
* Distort the whole Mesh by a (possibly changing in time) vector of force.
|
155 |
faa3ff56
|
Leszek Koltunski
|
*
|
156 |
|
|
* @param vector vector of force the Center of the Effect is currently being dragged with.
|
157 |
|
|
* @param center 3-dimensional Data that, at any given time, returns the Center of the Effect.
|
158 |
|
|
*/
|
159 |
|
|
public VertexEffectDistort(Data3D vector, Data3D center)
|
160 |
|
|
{
|
161 |
|
|
super(EffectName.DISTORT);
|
162 |
|
|
mVector = vector;
|
163 |
|
|
mCenter = center;
|
164 |
|
|
mRegion = new Static4D(0,0,Float.MAX_VALUE, Float.MAX_VALUE);
|
165 |
|
|
}
|
166 |
125cee3d
|
Leszek Koltunski
|
}
|
167 |
15aa7d94
|
Leszek Koltunski
|
|