Project

General

Profile

Download (10 KB) Statistics
| Branch: | Revision:

library / src / main / java / org / distorted / library / DistortedTexture.java @ 432442f9

1 4e2382f3 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2016 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;
21
22
import android.graphics.Bitmap;
23
import android.graphics.Matrix;
24
import android.opengl.GLES20;
25
import android.opengl.GLUtils;
26
27 1942537e Leszek Koltunski
import java.util.Iterator;
28
import java.util.LinkedList;
29 4e2382f3 Leszek Koltunski
30
///////////////////////////////////////////////////////////////////////////////////////////////////
31 e0b6c593 Leszek Koltunski
/**
32
 * Class which represents a OpenGL Texture object.
33
 * <p>
34
 * Create a Texture of arbitrary size and feed some pixels to it via the setTexture() method.
35
 * <p>
36
 * Keep all objects created in a static LinkedList. The point: we need to be able to mark
37
 * Textures for deletion, and delete all marked objects later at a convenient time (that's
38
 * because we can only delete from a thread that holds the OpenGL context so here we provide a
39
 * framework where one is able to mark for deletion at any time and actual deletion takes place
40
 * on the next render).
41
 */
42 4e2382f3 Leszek Koltunski
public class DistortedTexture
43
  {
44 1942537e Leszek Koltunski
  private static boolean mListMarked = false;
45
  private static LinkedList<DistortedTexture> mList = new LinkedList<>();
46 4e2382f3 Leszek Koltunski
47 3ef3364d Leszek Koltunski
  private int mSizeX, mSizeY;  // in screen space
48
  float mHalfX, mHalfY;        // halves of the above
49 4e2382f3 Leszek Koltunski
  private long mID;
50 1942537e Leszek Koltunski
  private boolean mMarked;
51 4e2382f3 Leszek Koltunski
52
  private Bitmap[] mBmp= null; //
53
  int[] mTextureDataH;         // have to be shared among all the cloned Objects
54
  boolean[] mBitmapSet;        //
55
56
///////////////////////////////////////////////////////////////////////////////////////////////////
57
// We have to flip vertically every single Bitmap that we get fed with.
58
//
59
// Reason: textures read from files are the only objects in OpenGL which have their origins at the
60
// upper-left corner. Everywhere else the origin is in the lower-left corner. Thus we have to flip.
61
// The alternative solution, namely inverting the y-coordinate of the TexCoord does not really work-
62
// i.e. it works only in case of rendering directly to the screen, but if we render to an FBO and
63 421c2728 Leszek Koltunski
// then take the FBO and render to screen, (DistortedTree does so!) things get inverted as textures
64 4e2382f3 Leszek Koltunski
// created from FBO have their origins in the lower-left... Mindfuck!
65
66
  private static Bitmap flipBitmap(Bitmap src)
67
    {
68
    Matrix matrix = new Matrix();
69
    matrix.preScale(1.0f,-1.0f);
70
71
    return Bitmap.createBitmap(src,0,0,src.getWidth(),src.getHeight(), matrix,true);
72
    }
73
74
///////////////////////////////////////////////////////////////////////////////////////////////////
75 1942537e Leszek Koltunski
// must be called from a thread holding OpenGL Context
76 4e2382f3 Leszek Koltunski
77 1942537e Leszek Koltunski
  void createTexture()
78 4e2382f3 Leszek Koltunski
    {
79 1942537e Leszek Koltunski
    if( mBmp[0]!=null && mTextureDataH!=null )
80 4e2382f3 Leszek Koltunski
      {
81 1942537e Leszek Koltunski
      //android.util.Log.e("Texture", "creating "+mID);
82
83 4e2382f3 Leszek Koltunski
      if( mTextureDataH[0]==0 ) GLES20.glGenTextures(1, mTextureDataH, 0);
84
85
      GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataH[0]);
86
      GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR );
87
      GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR );
88
      GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE );
89
      GLES20.glTexParameteri ( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE );
90
91 1942537e Leszek Koltunski
      GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, flipBitmap(mBmp[0]), 0);
92
      mBmp[0] = null;
93 4e2382f3 Leszek Koltunski
      }
94
    }
95
96
///////////////////////////////////////////////////////////////////////////////////////////////////
97 1942537e Leszek Koltunski
// must be called from a thread holding OpenGL Context
98 4e2382f3 Leszek Koltunski
99 1942537e Leszek Koltunski
  private void deleteTexture()
100 4e2382f3 Leszek Koltunski
    {
101 1942537e Leszek Koltunski
    if( mTextureDataH!=null && mTextureDataH[0]>0 )
102
      {
103
      //android.util.Log.e("Texture", "deleting "+mID);
104 4e2382f3 Leszek Koltunski
105 1942537e Leszek Koltunski
      GLES20.glDeleteTextures(1, mTextureDataH, 0);
106 4e2382f3 Leszek Koltunski
107 1942537e Leszek Koltunski
      mTextureDataH[0] = 0;
108
      mBitmapSet[0] = false;
109
      }
110
111
    mMarked = false;
112 4e2382f3 Leszek Koltunski
    }
113
114 d558d9bd Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
115
116
  long getID()
117 1942537e Leszek Koltunski
    {
118
    return mID;
119
    }
120 d558d9bd Leszek Koltunski
121 4e2382f3 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
122
123 7b8086eb Leszek Koltunski
  static synchronized void onDestroy()
124 4e2382f3 Leszek Koltunski
    {
125 1942537e Leszek Koltunski
    mListMarked = false;
126
    mList.clear();
127 4e2382f3 Leszek Koltunski
    }
128
129
///////////////////////////////////////////////////////////////////////////////////////////////////
130 1942537e Leszek Koltunski
// must be called form a thread holding OpenGL Context
131 4e2382f3 Leszek Koltunski
132 1942537e Leszek Koltunski
  static synchronized void deleteAllMarked()
133 4e2382f3 Leszek Koltunski
    {
134 1942537e Leszek Koltunski
    if( mListMarked )
135 4e2382f3 Leszek Koltunski
      {
136 1942537e Leszek Koltunski
      DistortedTexture tmp;
137
      Iterator<DistortedTexture> iterator = mList.iterator();
138
139
      while(iterator.hasNext())
140
        {
141
        tmp = iterator.next();
142
143
        if( tmp.mMarked )
144
          {
145
          tmp.deleteTexture();
146
          iterator.remove();
147
          }
148
        }
149 4e2382f3 Leszek Koltunski
150 1942537e Leszek Koltunski
      mListMarked = false;
151
      }
152 4e2382f3 Leszek Koltunski
    }
153
154
///////////////////////////////////////////////////////////////////////////////////////////////////
155
// PUBLIC API
156
///////////////////////////////////////////////////////////////////////////////////////////////////
157
/**
158
 * Create empty texture of given dimensions.
159
 */
160 3ef3364d Leszek Koltunski
  public DistortedTexture(int width, int height)
161 4e2382f3 Leszek Koltunski
    {
162 3ef3364d Leszek Koltunski
    mSizeX= width ; mHalfX = mSizeX/2.0f;
163
    mSizeY= height; mHalfY = mSizeY/2.0f;
164
165 4e2382f3 Leszek Koltunski
    mTextureDataH   = new int[1];
166
    mTextureDataH[0]= 0;
167
    mBmp            = new Bitmap[1];
168
    mBmp[0]         = null;
169
    mBitmapSet      = new boolean[1];
170
    mBitmapSet[0]   = false;
171 1942537e Leszek Koltunski
    mID             = 0;
172
    mMarked         = false;
173 4e2382f3 Leszek Koltunski
174 1942537e Leszek Koltunski
    mList.add(this);
175 4e2382f3 Leszek Koltunski
    }
176
177
///////////////////////////////////////////////////////////////////////////////////////////////////
178
179
/**
180
 * Copy constructor.
181
 * <p>
182
 * Whatever we do not clone gets created just like in the default constructor.
183
 *
184
 * @param dt    Source object to create our object from
185
 * @param flags A bitmask of values specifying what to copy.
186 d558d9bd Leszek Koltunski
 *              Only possibilities: CLONE_BITMAP or CLONE_NOTHING.
187 4e2382f3 Leszek Koltunski
 */
188 d558d9bd Leszek Koltunski
189 4e2382f3 Leszek Koltunski
  public DistortedTexture(DistortedTexture dt, int flags)
190
    {
191 3ef3364d Leszek Koltunski
    mSizeX= dt.mSizeX ; mHalfX = mSizeX/2.0f;
192
    mSizeY= dt.mSizeY ; mHalfY = mSizeY/2.0f;
193 4e2382f3 Leszek Koltunski
194
    if( (flags & Distorted.CLONE_BITMAP) != 0 )
195
      {
196
      mTextureDataH = dt.mTextureDataH;
197
      mBmp          = dt.mBmp;
198
      mBitmapSet    = dt.mBitmapSet;
199 1942537e Leszek Koltunski
      mID           = dt.getID();
200 4e2382f3 Leszek Koltunski
      }
201
    else
202
      {
203
      mTextureDataH   = new int[1];
204
      mTextureDataH[0]= 0;
205
      mBitmapSet      = new boolean[1];
206
      mBitmapSet[0]   = false;
207
      mBmp            = new Bitmap[1];
208
      mBmp[0]         = null;
209 1942537e Leszek Koltunski
      mID             = 0;
210 4e2382f3 Leszek Koltunski
      }
211 1942537e Leszek Koltunski
212
    mMarked = false;
213
214
    mList.add(this);
215 4e2382f3 Leszek Koltunski
    }
216
217
///////////////////////////////////////////////////////////////////////////////////////////////////
218
/**
219 1942537e Leszek Koltunski
 * Mark the underlying OpenGL object for deletion. Actual deletion will take place on the next render.
220 4e2382f3 Leszek Koltunski
 */
221 1942537e Leszek Koltunski
  public void markForDeletion()
222 4e2382f3 Leszek Koltunski
    {
223 1942537e Leszek Koltunski
    //android.util.Log.e("Texture", "marking for deletion "+mID);
224
225
    mListMarked = true;
226
    mMarked     = true;
227 4e2382f3 Leszek Koltunski
    }
228
229
///////////////////////////////////////////////////////////////////////////////////////////////////
230
/**
231 1942537e Leszek Koltunski
 * Sets the underlying android.graphics.Bitmap object.
232 4e2382f3 Leszek Koltunski
 * <p>
233
 * You can only recycle() the passed Bitmap once the OpenGL context gets created (i.e. after call
234 432442f9 Leszek Koltunski
 * to GLSurfaceView.onSurfaceCreated) because only after this point can the Library upload it to the GPU!
235 4e2382f3 Leszek Koltunski
 *
236
 * @param bmp The android.graphics.Bitmap object to apply effects to and display.
237
 */
238
239
  public void setTexture(Bitmap bmp)
240
    {
241
    mBitmapSet[0] = true;
242 1942537e Leszek Koltunski
    mBmp[0]       = bmp;
243
    mID           = bmp.hashCode();
244 4e2382f3 Leszek Koltunski
245 1942537e Leszek Koltunski
    //android.util.Log.e("Texture", "setting new bitmap "+mID);
246 4e2382f3 Leszek Koltunski
    }
247
248
///////////////////////////////////////////////////////////////////////////////////////////////////
249
/**
250 46e25345 Leszek Koltunski
 * Returns the height of the Texture.
251 4e2382f3 Leszek Koltunski
 *
252
 * @return height of the object, in pixels.
253
 */
254
  public int getWidth()
255 1942537e Leszek Koltunski
    {
256
    return mSizeX;
257
    }
258 4e2382f3 Leszek Koltunski
259
///////////////////////////////////////////////////////////////////////////////////////////////////
260
/**
261 46e25345 Leszek Koltunski
 * Returns the width of the Texture.
262 4e2382f3 Leszek Koltunski
 *
263
 * @return width of the Object, in pixels.
264
 */
265
  public int getHeight()
266 1942537e Leszek Koltunski
    {
267
    return mSizeY;
268
    }
269 4e2382f3 Leszek Koltunski
270
///////////////////////////////////////////////////////////////////////////////////////////////////
271
/**
272 46e25345 Leszek Koltunski
 * Returns the depth of the Texture.
273 3ef3364d Leszek Koltunski
 * <p>
274
 * Admittedly quite a strange method. Why do we need to pass a Grid to it? Because one cannot determine
275
 * 'depth' of a texture when rendered based only on the texture itself, that depends on the Grid it is
276
 * rendered with.
277 4e2382f3 Leszek Koltunski
 *
278
 * @return depth of the Object, in pixels.
279
 */
280 3ef3364d Leszek Koltunski
  public int getDepth(GridObject grid)
281 1942537e Leszek Koltunski
    {
282
    return grid==null ? 0 : (int)(mSizeX*grid.zFactor);
283
    }
284 4e2382f3 Leszek Koltunski
  }