001package com.fs.starfarer.api.util;
002
003import java.awt.Color;
004
005import org.lwjgl.opengl.GL11;
006
007import com.fs.starfarer.api.graphics.SpriteAPI;
008
009public class WarpingSpriteRendererUtil  {
010        
011        public static class MutatingValue {
012
013                public float value;
014                
015                public float min;
016                public float max;
017                
018                public float rate;
019                public float rateSign;
020                
021                public float sign = 0;
022
023                public MutatingValue() {
024                        
025                }
026                public MutatingValue(float min, float max, float rate) {
027                        this.min = min;
028                        this.max = max;
029                        this.rate = Math.abs(rate);
030                        
031                        value = min + (float) Math.random() * (max - min);
032                        rateSign = Math.signum(rate);
033                }
034                
035                public void set(float min, float max) {
036                        this.min = min;
037                        this.max = max;
038                        value = min + (float) Math.random() * (max - min);
039                }
040
041                public void advance(float amount) {
042                        if (rateSign != 0) {
043                                value += amount * rate * rateSign;
044                        } else {
045                                value += amount * rate;
046                        }
047                        if (value > max) {
048                                value = max;
049                                rateSign = -1f;
050                        } else if (value < min) {
051                                value = min;
052                                rateSign = 1f;
053                        }
054                }
055
056                public float getValue() {
057                        if (sign != 0) return value * sign;
058                        return value;
059                }
060
061                public void setValue(float value) {
062                        this.value = value;
063                }
064
065                public float getMin() {
066                        return min;
067                }
068
069                public void setMin(float min) {
070                        this.min = min;
071                }
072
073                public float getMax() {
074                        return max;
075                }
076
077                public void setMax(float max) {
078                        this.max = max;
079                }
080
081                public float getRate() {
082                        return rate;
083                }
084
085                public void setRate(float rate) {
086                        //System.out.println("RATE: " + rate);
087                        this.rate = Math.abs(rate);
088                        //rateSign = Math.signum(rate);
089                }
090
091                public float getSign() {
092                        return sign;
093                }
094
095                public void setSign(float sign) {
096                        this.sign = Math.signum(sign);
097                }
098                
099                public void setRandomSign() {
100                        sign = (float) Math.signum(Math.random() - 0.5f);
101                        if (sign == 0) sign = 1;
102                }
103                public void setRandomRateSign() {
104                        rateSign = (float) Math.signum(Math.random() - 0.5f);
105                        if (rateSign == 0) rateSign = 1;
106                }
107
108                public float getRateSign() {
109                        return rateSign;
110                }
111
112                public void setRateSign(float rateSign) {
113                        this.rateSign = rateSign;
114                }
115                
116        }
117        
118        
119        public static class WSVertex {
120                public MutatingValue theta;
121                public MutatingValue radius;
122                
123                public WSVertex() {
124                        //theta = new MutatingValue(-360f * ((float) Math.random() * 3f + 1f), 360f * ((float) Math.random() * 3f + 1f), 30f + 70f * (float) Math.random());
125                        theta = new MutatingValue(-360f * ((float) Math.random() * 30f + 1f), 360f * ((float) Math.random() * 30f + 1f), 30f + 70f * (float) Math.random());
126                        radius = new MutatingValue(0, 10f + 15f * (float) Math.random(), 3f + 7f * (float) Math.random());
127                }
128                
129                public void advance(float amount) {
130                        theta.advance(amount);
131                        radius.advance(amount);
132                }
133                
134                Object writeReplace() {
135                        theta.setMax((int)theta.getMax());
136                        theta.setMin((int)theta.getMin());
137                        theta.setRate((int)theta.getRate());
138                        theta.setValue((int)theta.getValue());
139                        
140                        radius.setMax((int)radius.getMax());
141                        radius.setMin((int)radius.getMin());
142                        radius.setRate((int)radius.getRate());
143                        radius.setValue((int)radius.getValue());
144                        return this;
145                }
146        }
147        
148        private int verticesWide, verticesTall;
149        private WSVertex [] [] vertices;
150        
151        public WarpingSpriteRendererUtil(int verticesWide, int verticesTall, float minWarpRadius, float maxWarpRadius, 
152                                                                float warpRateMult) {
153                this.verticesWide = verticesWide;
154                this.verticesTall = verticesTall;
155                
156                vertices = new WSVertex[verticesWide][verticesTall];
157                for (int i = 0; i < verticesWide; i++) {
158                        for (int j = 0; j < verticesTall; j++) {
159                                vertices[i][j] = new WSVertex();
160                                
161                                vertices[i][j].radius.set(minWarpRadius, maxWarpRadius);
162                                vertices[i][j].radius.rate *= warpRateMult;
163                                vertices[i][j].theta.rate *= warpRateMult;
164                                
165                        }
166                }
167                
168                readResolve();
169        }
170        
171        Object readResolve() {
172                return this;
173        }
174        
175        public void advance(float amount) {
176                for (int i = 0; i < verticesWide; i++) {
177                        for (int j = 0; j < verticesTall; j++) {
178                                vertices[i][j].advance(amount);
179                        }
180                }
181        }
182        
183        public void renderNoBlendOrRotate(SpriteAPI sprite, float x, float y) {
184                renderNoBlendOrRotate(sprite, x, y, true);      
185        }
186        
187        public void renderNoBlendOrRotate(SpriteAPI sprite, float xOff, float yOff, boolean disableBlend) { 
188                
189                sprite.bindTexture();
190                GL11.glPushMatrix();
191                
192                Color color = sprite.getColor();
193                GL11.glColor4ub((byte) color.getRed(), (byte) color.getGreen(),
194                                                (byte) color.getBlue(), (byte)(color.getAlpha() * sprite.getAlphaMult()));
195                
196                // translate to the right location and prepare to draw
197                GL11.glTranslatef(xOff, yOff, 0);
198
199                GL11.glEnable(GL11.GL_TEXTURE_2D);
200                if (disableBlend) {
201                        GL11.glDisable(GL11.GL_BLEND);
202                }
203
204                float w = sprite.getWidth();
205                float h = sprite.getHeight();
206                float tw = sprite.getTextureWidth() - 0.001f;
207                float th = sprite.getTextureHeight() - 0.001f;
208                
209                float cw = w / (float) (verticesWide - 1);
210                float ch = h / (float) (verticesTall- 1);
211                float ctw = tw / (float) (verticesWide - 1);
212                float cth = th / (float) (verticesTall- 1);
213        
214                for (float i = 0; i < verticesWide - 1; i++) {
215                //for (float i = 5; i < 7; i++) {
216                        GL11.glBegin(GL11.GL_QUAD_STRIP);
217                        {
218                                for (float j = 0; j < verticesTall; j++) {
219                                        float x1 = cw * i;
220                                        float y1 = ch * j;
221                                        float x2 = cw * (i + 1f);
222                                        float y2 = ch * j;
223                                        
224                                        float tx1 = ctw * i;
225                                        float ty1 = cth * j;
226                                        float tx2 = ctw * (i + 1f);
227                                        float ty2 = cth * j;
228                                        
229                                        if (i != 0 && i != verticesWide - 1 && j != 0 && j != verticesTall - 1) {
230                                                float theta = (float) Math.toRadians(vertices[(int)i][(int)j].theta.getValue());
231                                                float radius = vertices[(int)i][(int)j].radius.getValue();
232                                                float sin = (float) Math.sin(theta);
233                                                float cos = (float) Math.cos(theta);
234                                                
235                                                x1 += cos * radius; 
236                                                y1 += sin * radius;
237                                                //System.out.println("Radius: " + radius);
238                                        }
239                                        
240                                        if (i + 1 != 0 && i + 1 != verticesWide - 1 && j != 0 && j != verticesTall - 1) {
241                                                float theta = (float) Math.toRadians(vertices[(int)i + 1][(int)j].theta.getValue());
242                                                float radius = vertices[(int)i + 1][(int)j].radius.getValue();
243                                                float sin = (float) Math.sin(theta);
244                                                float cos = (float) Math.cos(theta);
245                                                
246                                                x2 += cos * radius; 
247                                                y2 += sin * radius;
248                                                //System.out.println("Radius: " + radius);
249                                        }
250
251                                        GL11.glTexCoord2f(tx1, ty1);
252                                        GL11.glVertex2f(x1, y1);
253                                        
254                                        GL11.glTexCoord2f(tx2, ty2);
255                                        GL11.glVertex2f(x2, y2);
256                                }
257                        }
258                        GL11.glEnd();
259                        
260                }
261//              GL11.glDisable(GL11.GL_TEXTURE_2D);
262//              GL11.glPointSize(32f);
263//              GLUtils.setColor(Color.white);
264//              GL11.glBegin(GL11.GL_POINTS);
265//              for (float i = 0; i < verticesWide - 1; i++) {
266//                      for (float j = 0; j < verticesTall; j++) {
267//                              float x1 = cw * i;
268//                              float y1 = ch * j;
269//                              float x2 = cw * (i + 1f);
270//                              float y2 = ch * j;
271//                              
272//                              if (i != 0 && i != verticesWide - 1 && j != 0 && j != verticesTall - 1) {
273//                                      float theta = (float) Math.toRadians(vertices[(int)i][(int)j].theta.getValue());
274//                                      float radius = vertices[(int)i][(int)j].radius.getValue();
275//                                      float sin = (float) Math.sin(theta);
276//                                      float cos = (float) Math.cos(theta);
277//                                      
278//                                      x1 += cos * radius; 
279//                                      y1 += sin * radius;
280//                                      //System.out.println("Radius: " + radius);
281//                              }
282//                              
283//                              
284//                              GL11.glVertex2f(x1, y1);
285//                      }
286//              }
287//              GL11.glEnd();
288                
289                GL11.glPopMatrix();
290        }
291        
292}
293
294
295
296
297
298
299
300
301
302
303
304
305
306