Project

General

Profile

« Previous | Next » 

Revision af4cc5db

Added by Leszek Koltunski about 7 years ago

Simplify yesterday's refactoring.

View differences:

src/main/java/org/distorted/library/Distorted.java
24 24
import android.opengl.GLES30;
25 25
import org.distorted.library.program.*;
26 26

  
27
import java.io.InputStream;
28

  
29 27
///////////////////////////////////////////////////////////////////////////////////////////////////
30 28
/**
31 29
 * A singleton class used to control various global settings.
......
136 134
 */
137 135
  public static void onDestroy()
138 136
    {
139
    DistortedRenderable.onDestroy();
137
    DistortedSurface.onDestroy();
140 138
    DistortedTree.onDestroy();
141 139
    EffectQueue.onDestroy();
142 140
    DistortedEffects.onDestroy();
src/main/java/org/distorted/library/DistortedEffects.java
194 194

  
195 195
    float x,y,z, X,Y,W, ndcX,ndcY;
196 196

  
197
    DistortedProjection projection = surface.getProjection();
198

  
199 197
    for(int i=0; i<len; i++)
200 198
      {
201 199
      x = 2*halfX*vertices[3*i  ];
......
209 207
      ndcX = X/W;
210 208
      ndcY = Y/W;
211 209

  
212
      wx = (int)(projection.mWidth *(ndcX+1)/2);
213
      wy = (int)(projection.mHeight*(ndcY+1)/2);
210
      wx = (int)(surface.mWidth *(ndcX+1)/2);
211
      wy = (int)(surface.mHeight*(ndcY+1)/2);
214 212

  
215 213
      if( wx<minx ) minx = wx;
216 214
      if( wx>maxx ) maxx = wx;
......
222 220
    surface.setAsOutput();
223 221

  
224 222
    Matrix.setIdentityM( mTmpMatrix, 0);
225
    Matrix.translateM  ( mTmpMatrix, 0, minx-projection.mWidth/2, maxy-projection.mHeight/2, -projection.mDistance);
223
    Matrix.translateM  ( mTmpMatrix, 0, minx-surface.mWidth/2, maxy-surface.mHeight/2, -surface.mDistance);
226 224
    Matrix.scaleM      ( mTmpMatrix, 0, (float)(maxx-minx)/(2*halfX), (float)(maxy-miny)/(2*halfY), 1.0f);
227 225
    Matrix.translateM  ( mTmpMatrix, 0, halfX,-halfY, 0);
228
    Matrix.multiplyMM  ( mMVPMatrix, 0, projection.mProjectionMatrix, 0, mTmpMatrix, 0);
226
    Matrix.multiplyMM  ( mMVPMatrix, 0, surface.mProjectionMatrix, 0, mTmpMatrix, 0);
229 227

  
230 228
    GLES30.glUniform2f( mObjDH , 2*halfX, 2*halfY);
231 229
    GLES30.glUniformMatrix4fv(mMVPMatrixH, 1, false, mMVPMatrix , 0);
......
244 242
    mP.compute(currTime);
245 243

  
246 244
    float halfZ = halfInputW*mesh.zFactor;
247
    DistortedProjection projection = surface.getProjection();
248
    GLES30.glViewport(0, 0, projection.mWidth, projection.mHeight);
245
    GLES30.glViewport(0, 0, surface.mWidth, surface.mHeight);
249 246

  
250 247
    if( mP.mNumEffects==0 )
251 248
      {
252 249
      mProgram.useProgram();
253 250
      surface.setAsOutput();
254
      mM.send(projection,halfInputW,halfInputH,halfZ);
251
      mM.send(surface,halfInputW,halfInputH,halfZ);
255 252
      mV.send(halfInputW,halfInputH,halfZ);
256 253
      mF.send(halfInputW,halfInputH);
257 254
      GLES30.glVertexAttribPointer(mProgram.mAttribute[0], POSITION_DATA_SIZE, GLES30.GL_FLOAT, false, 0, mesh.mMeshPositions);
......
263 260
      {
264 261
      if( mV.mNumEffects==0 && mF.mNumEffects==0 && (mesh instanceof MeshFlat) && mM.canUseShortcut() )
265 262
        {
266
        mM.constructMatrices(projection,halfInputW,halfInputH);
263
        mM.constructMatrices(surface,halfInputW,halfInputH);
267 264
        mP.render(2*halfInputW, 2*halfInputH, mM.getMVP(), surface);
268 265
        }
269 266
      else
270 267
        {
271 268
        mProgram.useProgram();
272
        mBufferFBO.resizeFast(projection.mWidth, projection.mHeight);
269
        mBufferFBO.resizeFast(surface.mWidth, surface.mHeight);
273 270
        mBufferFBO.setAsOutput();
274 271
        GLES30.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
275 272
        GLES30.glClear( GLES30.GL_DEPTH_BUFFER_BIT | GLES30.GL_COLOR_BUFFER_BIT);
276
        mM.send(mBufferFBO.getProjection(),halfInputW,halfInputH,halfZ);
273
        mM.send(mBufferFBO,halfInputW,halfInputH,halfZ);
277 274
        mV.send(halfInputW,halfInputH,halfZ);
278 275
        mF.send(halfInputW,halfInputH);
279 276
        GLES30.glVertexAttribPointer(mProgram.mAttribute[0], POSITION_DATA_SIZE, GLES30.GL_FLOAT, false, 0, mesh.mMeshPositions);
......
282 279
        GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP, 0, mesh.dataLength);
283 280

  
284 281
        Matrix.setIdentityM(mTmpMatrix, 0);
285
        Matrix.translateM(mTmpMatrix, 0, 0, 0, -projection.mDistance);
286
        Matrix.multiplyMM(mMVPMatrix, 0, projection.mProjectionMatrix, 0, mTmpMatrix, 0);
282
        Matrix.translateM(mTmpMatrix, 0, 0, 0, -surface.mDistance);
283
        Matrix.multiplyMM(mMVPMatrix, 0, surface.mProjectionMatrix, 0, mTmpMatrix, 0);
287 284

  
288 285
        mBufferFBO.setAsInput();
289
        mP.render(projection.mWidth, projection.mHeight, mMVPMatrix, surface);
286
        mP.render(surface.mWidth, surface.mHeight, mMVPMatrix, surface);
290 287
        }
291 288
      }
292 289

  
......
297 294

  
298 295
///////////////////////////////////////////////////////////////////////////////////////////////////
299 296
   
300
  static void drawNoEffectsPriv(float halfInputW, float halfInputH, MeshObject mesh, DistortedProjection projection)
297
  static void drawNoEffectsPriv(float halfInputW, float halfInputH, MeshObject mesh, DistortedOutputSurface projection)
301 298
    {
302 299
    GLES30.glViewport(0, 0, projection.mWidth, projection.mHeight);
303 300

  
src/main/java/org/distorted/library/DistortedFramebuffer.java
28 28
 * User is able to create offscreen FBOs and both a) render to them b) use their COLOR0 attachment as
29 29
 * an input texture.
30 30
 */
31
public class DistortedFramebuffer extends DistortedRenderable implements DistortedInputSurface, DistortedOutputSurface
31
public class DistortedFramebuffer extends DistortedOutputSurface implements DistortedInputSurface
32 32
  {
33 33
  private int[] mDepthH = new int[1];
34 34
  private int[] mFBOH   = new int[1];
35 35
  private boolean mDepthEnabled;
36
  private DistortedProjection mProjection;
37 36

  
38 37
///////////////////////////////////////////////////////////////////////////////////////////////////
39 38
// Must be called from a thread holding OpenGL Context
......
136 135
// if new size fits into the size of the underlying Texture, just change the projection without
137 136
// reallocating the Texture. Otherwise, we need to reallocate.
138 137
//
139
// Must be called form a thread holding the OpenGL context.
138
// Must be called from a thread holding the OpenGL context.
140 139

  
141 140
  void resizeFast(int width, int height)
142 141
    {
143
    if( mProjection.resize(width,height) )
142
    if( mWidth!=width || mHeight!=height )
144 143
      {
144
      mWidth = width;
145
      mHeight= height;
146
      createProjection();
147

  
145 148
      if( width> mSizeX || height> mSizeY)
146 149
        {
147 150
        mSizeX = width;
......
167 170
  public DistortedFramebuffer(int width, int height, boolean depthEnabled)
168 171
    {
169 172
    super(width,height,NOT_CREATED_YET);
170

  
171
    mProjection  = new DistortedProjection(width,height);
172 173
    mDepthEnabled= depthEnabled;
173 174
    mFBOH[0]     = NOT_CREATED_YET;
174 175
    mDepthH[0]   = NOT_CREATED_YET;
......
186 187
  public DistortedFramebuffer(int width, int height)
187 188
    {
188 189
    super(width,height,NOT_CREATED_YET);
189

  
190
    mProjection  = new DistortedProjection(width,height);
191 190
    mDepthEnabled= false;
192 191
    mFBOH[0]     = NOT_CREATED_YET;
193 192
    mDepthH[0]   = NOT_CREATED_YET;
......
196 195
///////////////////////////////////////////////////////////////////////////////////////////////////
197 196
/**
198 197
 * Bind the underlying rectangle of pixels as a OpenGL Texture.
198
 *
199
 * @returns <code>true</code> if successful.
199 200
 */
200 201
  public boolean setAsInput()
201 202
    {
......
240 241
    mDepthEnabled = enable;
241 242
    }
242 243

  
243
///////////////////////////////////////////////////////////////////////////////////////////////////
244

  
245
/**
246
 * Draw the (texture,mesh,effects) object to the Framebuffer.
247
 * <p>
248
 * Must be called from a thread holding OpenGL Context.
249
 *
250
 * @param surface InputSurface to skin our Mesh with.
251
 * @param mesh Class descendant from MeshObject
252
 * @param effects The DistortedEffects to use when rendering
253
 * @param time Current time, in milliseconds.
254
 */
255
  public void renderTo(DistortedInputSurface surface, MeshObject mesh, DistortedEffects effects, long time)
256
    {
257
    surface.create();  // Watch out  - this needs to be before
258
    create();          // the 'setAsInput' because this has side-effects!
259

  
260
    if( surface.setAsInput() )
261
      {
262
      DistortedRenderable.deleteAllMarked();
263
      effects.drawPriv(surface.getWidth()/2.0f, surface.getHeight()/2.0f, mesh, this, time);
264
      }
265
    }
266

  
267
///////////////////////////////////////////////////////////////////////////////////////////////////
268
/**
269
 * Draws the Tree, and all its children, to the Framebuffer.
270
 * <p>
271
 * Must be called from a thread holding OpenGL Context.
272
 *
273
 * @param dt DistortedTree to render.
274
 * @param time Current time, in milliseconds. This will be passed to all the Effects stored in the Tree.
275
 */
276
  public void renderTo(DistortedTree dt, long time)
277
    {
278
    DistortedRenderable.deleteAllMarked();
279
    create();
280
    dt.drawRecursive(time,this);
281
    }
282

  
283
///////////////////////////////////////////////////////////////////////////////////////////////////
284
/**
285
 * Create new Projection matrix.
286
 *
287
 * @param fov Vertical 'field of view' of the Projection frustrum (in degrees).
288
 * @param x X-coordinate of the point at which our camera looks at. 0 is the center.
289
 * @param y Y-coordinate of the point at which our camera looks at. 0 is the center.
290
 */
291
  public void setProjection(float fov, float x, float y)
292
    {
293
    mProjection.set(fov,x,y);
294
    mProjection.createProjection();
295
    }
296

  
297
///////////////////////////////////////////////////////////////////////////////////////////////////
298
/**
299
 * Resize the underlying Framebuffer.
300
 *
301
 * @param width The new width.
302
 * @param height The new height.
303
 */
304
  public void resize(int width, int height)
305
    {
306
    if( mProjection.resize(width,height) )
307
      {
308
      mSizeX = width;
309
      mSizeY = height;
310
      if( mColorH[0]>0 ) markForDeletion();
311
      }
312
    }
313

  
314 244
///////////////////////////////////////////////////////////////////////////////////////////////////
315 245
/**
316 246
 * Return the ID of the Texture (COLOR attachment 0) that's backing this FBO.
......
337 267
    {
338 268
    return mDepthEnabled;
339 269
    }
340

  
341
//////////////////////////////////////////////////////////////////////////////////////////////////
342
/**
343
 * Return Projection stored in this Framebuffer.
344
 *
345
 * @return DistortedProjection object.
346
 */
347
  public DistortedProjection getProjection()
348
    {
349
    return mProjection;
350
    }
351 270
  }
src/main/java/org/distorted/library/DistortedInputSurface.java
25 25
 * A Surface that we can set as Input, i.e. take its rectangle of pixels and skin our Mesh with it.
26 26
 */
27 27

  
28
public interface DistortedInputSurface extends DistortedSurface
28
interface DistortedInputSurface
29 29
{
30
/**
31
 * Create the underlying OpenGL part of the Surface.
32
 */
33
  void create();
34
/**
35
 * Return a unique ID of this Surface.
36
 */
37
  long getID();
38
/**
39
 * Return the width of this Surface.
40
 */
41
  int getWidth();
42
/**
43
 * Return the height of this Surface.
44
 */
45
  int getHeight();
30 46
/**
31 47
 * Take the underlying rectangle of pixels and bind this texture to OpenGL.
32 48
 */
src/main/java/org/distorted/library/DistortedOutputSurface.java
19 19

  
20 20
package org.distorted.library;
21 21

  
22
import android.opengl.Matrix;
23

  
24
///////////////////////////////////////////////////////////////////////////////////////////////////
25

  
26
abstract class DistortedOutputSurface extends DistortedSurface
27
{
28
  private float mX, mY, mFOV;
29
  int mWidth,mHeight,mDepth;
30
  float mDistance;
31
  float[] mProjectionMatrix;
32

  
33
///////////////////////////////////////////////////////////////////////////////////////////////////
34

  
35
  DistortedOutputSurface(int width, int height, int color)
36
    {
37
    super(width,height,color);
38

  
39
    mProjectionMatrix = new float[16];
40

  
41
    mWidth = width;
42
    mHeight= height;
43

  
44
    mFOV = 60.0f;
45
    mX   =  0.0f;
46
    mY   =  0.0f;
47

  
48
    createProjection();
49
    }
50

  
22 51
///////////////////////////////////////////////////////////////////////////////////////////////////
23 52

  
53
  void createProjection()
54
    {
55
    if( mWidth>0 && mHeight>1 )
56
      {
57
      if( mFOV>0.0f )  // perspective projection
58
        {
59
        float left   = (-mX-mWidth /2.0f)/mHeight;
60
        float right  = (-mX+mWidth /2.0f)/mHeight;
61
        float bottom = (-mY-mHeight/2.0f)/mHeight;
62
        float top    = (-mY+mHeight/2.0f)/mHeight;
63
        float near   = (top-bottom) / (2.0f*(float)Math.tan(mFOV*Math.PI/360));
64
        mDistance    = mHeight*near/(top-bottom);
65
        float far    = 2*mDistance-near;
66
        mDepth       = (int)((far-near)/2);
67

  
68
        Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
69
        }
70
      else             // parallel projection
71
        {
72
        float left   = -mX-mWidth /2.0f;
73
        float right  = -mX+mWidth /2.0f;
74
        float bottom = -mY-mHeight/2.0f;
75
        float top    = -mY+mHeight/2.0f;
76
        float near   = (mWidth+mHeight)/2;
77
        mDistance    = 2*near;
78
        float far    = 3*near;
79
        mDepth       = (int)near;
80

  
81
        Matrix.orthoM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
82
        }
83
      }
84
    }
85

  
86
///////////////////////////////////////////////////////////////////////////////////////////////////
87
// PUBLIC API
88
///////////////////////////////////////////////////////////////////////////////////////////////////
24 89
/**
25
 * A Surface that we can set as Output, i.e. render to it.
90
 * Draw the (texture,mesh,effects) object to the Framebuffer.
91
 * <p>
92
 * Must be called from a thread holding OpenGL Context.
93
 *
94
 * @param surface InputSurface to skin our Mesh with.
95
 * @param mesh Class descendant from MeshObject
96
 * @param effects The DistortedEffects to use when rendering
97
 * @param time Current time, in milliseconds.
26 98
 */
99
  public void renderTo(DistortedInputSurface surface, MeshObject mesh, DistortedEffects effects, long time)
100
    {
101
    surface.create();  // Watch out  - this needs to be before
102
    create();          // the 'setAsInput' because this has side-effects!
27 103

  
28
public interface DistortedOutputSurface extends DistortedSurface
29
{
104
    if( surface.setAsInput() )
105
      {
106
      DistortedSurface.deleteAllMarked();
107
      effects.drawPriv(surface.getWidth()/2.0f, surface.getHeight()/2.0f, mesh, this, time);
108
      }
109
    }
110

  
111
///////////////////////////////////////////////////////////////////////////////////////////////////
112
/**
113
 * Draws the Tree, and all its children, to the Framebuffer.
114
 * <p>
115
 * Must be called from a thread holding OpenGL Context.
116
 *
117
 * @param dt DistortedTree to render.
118
 * @param time Current time, in milliseconds. This will be passed to all the Effects stored in the Tree.
119
 */
120
  public void renderTo(DistortedTree dt, long time)
121
    {
122
    DistortedSurface.deleteAllMarked();
123
    create();
124
    dt.drawRecursive(time,this);
125
    }
126

  
127
///////////////////////////////////////////////////////////////////////////////////////////////////
30 128
/**
31 129
 * Bind this Surface as a Framebuffer we can render to.
32 130
 */
33
 void setAsOutput();
131
  public abstract void setAsOutput();
132

  
133
///////////////////////////////////////////////////////////////////////////////////////////////////
134
/**
135
 * Create new Projection matrix.
136
 *
137
 * @param fov Vertical 'field of view' of the Projection frustrum (in degrees).
138
 * @param x X-coordinate of the point at which our camera looks at. 0 is the center.
139
 * @param y Y-coordinate of the point at which our camera looks at. 0 is the center.
140
 */
141
  public void setProjection(float fov, float x, float y)
142
    {
143
    mFOV = fov;
144
    mX = x;
145
    mY = y;
146

  
147
    createProjection();
148
    }
149

  
150
///////////////////////////////////////////////////////////////////////////////////////////////////
34 151
/**
35
 * Return the Projection.
152
 * Resize the underlying Framebuffer.
153
 *
154
 * @param width The new width.
155
 * @param height The new height.
36 156
 */
37
 DistortedProjection getProjection();
38
}
157
  public void resize(int width, int height)
158
    {
159
    if( mWidth!=width || mHeight!=height )
160
      {
161
      mWidth = width;
162
      mHeight= height;
163
      createProjection();
164
      mSizeX = width;
165
      mSizeY = height;
166
      if( mColorH[0]>0 ) markForDeletion();
167
      }
168
    }
169
}
src/main/java/org/distorted/library/DistortedProjection.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
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.opengl.Matrix;
23

  
24
///////////////////////////////////////////////////////////////////////////////////////////////////
25

  
26
class DistortedProjection
27
{
28
  private float mX, mY, mFOV;
29
  int mWidth,mHeight,mDepth;
30
  float mDistance;
31
  float[] mProjectionMatrix;
32

  
33
///////////////////////////////////////////////////////////////////////////////////////////////////
34

  
35
  DistortedProjection()
36
    {
37
    mProjectionMatrix = new float[16];
38

  
39
    mWidth = 0;
40
    mHeight= 0;
41

  
42
    mFOV = 60.0f;
43
    mX   =  0.0f;
44
    mY   =  0.0f;
45
    }
46

  
47
///////////////////////////////////////////////////////////////////////////////////////////////////
48

  
49
  DistortedProjection(int width, int height)
50
    {
51
    mProjectionMatrix = new float[16];
52

  
53
    mWidth = width;
54
    mHeight= height;
55

  
56
    mFOV = 60.0f;
57
    mX   =  0.0f;
58
    mY   =  0.0f;
59

  
60
    createProjection();
61
    }
62

  
63
///////////////////////////////////////////////////////////////////////////////////////////////////
64

  
65
  boolean resize(int width, int height)
66
    {
67
    if( mWidth!=width || mHeight!=height )
68
      {
69
      mWidth = width;
70
      mHeight= height;
71
      createProjection();
72
      return true;
73
      }
74

  
75
    return false;
76
    }
77

  
78
///////////////////////////////////////////////////////////////////////////////////////////////////
79

  
80
  void set(float fov, float x, float y)
81
    {
82
    mFOV = fov;
83
    mX = x;
84
    mY = y;
85
    }
86

  
87
///////////////////////////////////////////////////////////////////////////////////////////////////
88

  
89
  void createProjection()
90
    {
91
    if( mWidth>0 && mHeight>1 )
92
      {
93
      if( mFOV>0.0f )  // perspective projection
94
        {
95
        float left   = (-mX-mWidth /2.0f)/mHeight;
96
        float right  = (-mX+mWidth /2.0f)/mHeight;
97
        float bottom = (-mY-mHeight/2.0f)/mHeight;
98
        float top    = (-mY+mHeight/2.0f)/mHeight;
99
        float near   = (top-bottom) / (2.0f*(float)Math.tan(mFOV*Math.PI/360));
100
        mDistance    = mHeight*near/(top-bottom);
101
        float far    = 2*mDistance-near;
102
        mDepth       = (int)((far-near)/2);
103

  
104
        Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
105
        }
106
      else             // parallel projection
107
        {
108
        float left   = -mX-mWidth /2.0f;
109
        float right  = -mX+mWidth /2.0f;
110
        float bottom = -mY-mHeight/2.0f;
111
        float top    = -mY+mHeight/2.0f;
112
        float near   = (mWidth+mHeight)/2;
113
        mDistance    = 2*near;
114
        float far    = 3*near;
115
        mDepth       = (int)near;
116

  
117
        Matrix.orthoM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
118
        }
119
      }
120
    }
121

  
122
///////////////////////////////////////////////////////////////////////////////////////////////////
123

  
124
}
src/main/java/org/distorted/library/DistortedRenderable.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
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 java.util.Iterator;
23
import java.util.LinkedList;
24

  
25
///////////////////////////////////////////////////////////////////////////////////////////////////
26
/**
27
 * Keep all objects created in a static LinkedList. The point: we need to be able to mark
28
 * Objects for deletion, and delete all marked Objects later at a convenient time (that's
29
 * because we can only delete from a thread that holds the OpenGL context so here we provide a
30
 * framework where one is able to mark for deletion at any time and actual deletion takes place
31
 * on the next render).
32
*/
33
abstract class DistortedRenderable implements DistortedSurface
34
  {
35
  static final int FAILED_TO_CREATE = -1;
36
  static final int NOT_CREATED_YET  = -2;
37
  static final int DONT_CREATE      = -3;
38

  
39
  private static boolean mListMarked = false;
40
  private static LinkedList<DistortedRenderable> mList = new LinkedList<>();
41

  
42
  private boolean mMarked;
43
  int[] mColorH = new int[1];
44
  int mSizeX, mSizeY;  // in screen space
45

  
46
///////////////////////////////////////////////////////////////////////////////////////////////////
47

  
48
  public abstract void create();
49
  abstract void delete();
50
  abstract void destroy();
51

  
52
///////////////////////////////////////////////////////////////////////////////////////////////////
53
// must be called form a thread holding OpenGL Context
54

  
55
  static synchronized void deleteAllMarked()
56
    {
57
    if( mListMarked )
58
      {
59
      DistortedRenderable tmp;
60
      Iterator<DistortedRenderable> iterator = mList.iterator();
61

  
62
      while(iterator.hasNext())
63
        {
64
        tmp = iterator.next();
65

  
66
        if( tmp.mMarked )
67
          {
68
          tmp.delete();
69
          tmp.mMarked = false;
70
          iterator.remove();
71
          }
72
        }
73

  
74
      mListMarked = false;
75
      }
76
    }
77

  
78
///////////////////////////////////////////////////////////////////////////////////////////////////
79

  
80
  static synchronized void onDestroy()
81
    {
82
    for( DistortedRenderable ren : mList)
83
      {
84
      ren.destroy();
85
      ren.mMarked = false;
86
      }
87

  
88
    mListMarked = false;
89
    }
90

  
91
///////////////////////////////////////////////////////////////////////////////////////////////////
92

  
93
  DistortedRenderable(int width, int height, int color)
94
    {
95
    mSizeX    = width ;
96
    mSizeY    = height;
97
    mColorH[0]= color;
98
    mMarked   = false;
99
    mList.add(this);
100
    }
101

  
102
///////////////////////////////////////////////////////////////////////////////////////////////////
103
// PUBLIC API
104
///////////////////////////////////////////////////////////////////////////////////////////////////
105
/**
106
 * Mark the underlying OpenGL object for deletion. Actual deletion will take place on the next render.
107
 */
108
  public void markForDeletion()
109
    {
110
    mListMarked = true;
111
    mMarked     = true;
112
    }
113

  
114
////////////////////////////////////////////////////////////////////////////////////////////////////
115
/**
116
 * Return unique ID of the Renderable.
117
 */
118
  public long getID()
119
    {
120
    return mColorH[0];
121
    }
122

  
123
///////////////////////////////////////////////////////////////////////////////////////////////////
124

  
125
/**
126
 * Returns the height of the Renderable.
127
 *
128
 * @return height of the object, in pixels.
129
 */
130
  public int getWidth()
131
    {
132
    return mSizeX;
133
    }
134

  
135
///////////////////////////////////////////////////////////////////////////////////////////////////
136
/**
137
 * Returns the width of the Renderable.
138
 *
139
 * @return width of the Object, in pixels.
140
 */
141
  public int getHeight()
142
    {
143
    return mSizeY;
144
    }
145

  
146
///////////////////////////////////////////////////////////////////////////////////////////////////
147
/**
148
 * Returns the depth of the Renderable.
149
 * <p>
150
 * Admittedly quite a strange method. Why do we need to pass a Mesh to it? Because one cannot determine
151
 * 'depth' of a Renderable (bitmap really!) when rendered based only on the texture itself, that depends
152
 * on the Mesh it is rendered with.
153
 *
154
 * @return depth of the Object, in pixels.
155
 */
156
  public int getDepth(MeshObject mesh)
157
    {
158
    return mesh==null ? 0 : (int)(mSizeX*mesh.zFactor);
159
    }
160
  }
src/main/java/org/distorted/library/DistortedScreen.java
27 27
 * <p>
28 28
 * User is able to render to it just like to a DistortedFramebuffer.
29 29
 */
30
public class DistortedScreen extends DistortedRenderable implements DistortedOutputSurface
30
public class DistortedScreen extends DistortedOutputSurface
31 31
  {
32
  private int[] mFBOH   = new int[1];
33
  private DistortedProjection mProjection;
34

  
35 32
///////////////////////////////////////////////////////////////////////////////////////////////////
33
// here we don't manage underlying OpenGL assets ourselves
36 34

  
37 35
  public void create() {}
38 36
  void delete() {}
......
49 47
  public DistortedScreen()
50 48
    {
51 49
    super(0,0,DONT_CREATE);
52

  
53
    mProjection  = new DistortedProjection();
54
    mFBOH[0]     = 0;
55 50
    }
56 51

  
57 52
///////////////////////////////////////////////////////////////////////////////////////////////////
......
60 55
 */
61 56
  public void setAsOutput()
62 57
    {
63
    GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, mFBOH[0]);
58
    GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0);
64 59
    GLES30.glEnable(GLES30.GL_DEPTH_TEST);
65 60
    GLES30.glDepthMask(true);
66 61
    }
67

  
68
///////////////////////////////////////////////////////////////////////////////////////////////////
69

  
70
/**
71
 * Draw the (texture,mesh,effects) object to the Framebuffer.
72
 * <p>
73
 * Must be called from a thread holding OpenGL Context.
74
 *
75
 * @param surface InputSurface to skin our Mesh with.
76
 * @param mesh Class descendant from MeshObject
77
 * @param effects The DistortedEffects to use when rendering
78
 * @param time Current time, in milliseconds.
79
 */
80
  public void renderTo(DistortedInputSurface surface, MeshObject mesh, DistortedEffects effects, long time)
81
    {
82
    surface.create();  // Watch out  - this needs to be before
83
    create();          // the 'setAsInput' because this has side-effects!
84

  
85
    if( surface.setAsInput() )
86
      {
87
      DistortedRenderable.deleteAllMarked();
88
      effects.drawPriv(surface.getWidth()/2.0f, surface.getHeight()/2.0f, mesh, this, time);
89
      }
90
    }
91

  
92
///////////////////////////////////////////////////////////////////////////////////////////////////
93
/**
94
 * Draws the Tree, and all its children, to the Framebuffer.
95
 * <p>
96
 * Must be called from a thread holding OpenGL Context.
97
 *
98
 * @param dt DistortedTree to render.
99
 * @param time Current time, in milliseconds. This will be passed to all the Effects stored in the Tree.
100
 */
101
  public void renderTo(DistortedTree dt, long time)
102
    {
103
    DistortedRenderable.deleteAllMarked();
104
    create();
105
    dt.drawRecursive(time,this);
106
    }
107

  
108
///////////////////////////////////////////////////////////////////////////////////////////////////
109
/**
110
 * Create new Projection matrix.
111
 *
112
 * @param fov Vertical 'field of view' of the Projection frustrum (in degrees).
113
 * @param x X-coordinate of the point at which our camera looks at. 0 is the center.
114
 * @param y Y-coordinate of the point at which our camera looks at. 0 is the center.
115
 */
116
  public void setProjection(float fov, float x, float y)
117
    {
118
    mProjection.set(fov,x,y);
119
    mProjection.createProjection();
120
    }
121

  
122
///////////////////////////////////////////////////////////////////////////////////////////////////
123
/**
124
 * Resize the underlying Projection.
125
 *
126
 * @param width The new width.
127
 * @param height The new height.
128
 */
129
  public void resize(int width, int height)
130
    {
131
    if( mProjection.resize(width,height) )
132
      {
133
      mSizeX = width;
134
      mSizeY = height;
135
      }
136
    }
137

  
138
//////////////////////////////////////////////////////////////////////////////////////////////////
139
/**
140
 * Return Projection stored in this Framebuffer.
141
 *
142
 * @return DistortedProjection object.
143
 */
144
  public DistortedProjection getProjection()
145
    {
146
    return mProjection;
147
    }
148 62
  }
src/main/java/org/distorted/library/DistortedSurface.java
19 19

  
20 20
package org.distorted.library;
21 21

  
22
import java.util.Iterator;
23
import java.util.LinkedList;
24

  
25
///////////////////////////////////////////////////////////////////////////////////////////////////
26
/**
27
 * Keep all objects created in a static LinkedList. The point: we need to be able to mark
28
 * Objects for deletion, and delete all marked Objects later at a convenient time (that's
29
 * because we can only delete from a thread that holds the OpenGL context so here we provide a
30
 * framework where one is able to mark for deletion at any time and actual deletion takes place
31
 * on the next render).
32
*/
33
abstract class DistortedSurface
34
  {
35
  static final int FAILED_TO_CREATE = -1;
36
  static final int NOT_CREATED_YET  = -2;
37
  static final int DONT_CREATE      = -3;
38

  
39
  private static boolean mListMarked = false;
40
  private static LinkedList<DistortedSurface> mList = new LinkedList<>();
41

  
42
  private boolean mMarked;
43
  int[] mColorH = new int[1];
44
  int mSizeX, mSizeY;  // in screen space
45

  
46
///////////////////////////////////////////////////////////////////////////////////////////////////
47

  
48
  public abstract void create();
49
  abstract void delete();
50
  abstract void destroy();
51

  
52
///////////////////////////////////////////////////////////////////////////////////////////////////
53
// must be called form a thread holding OpenGL Context
54

  
55
  static synchronized void deleteAllMarked()
56
    {
57
    if( mListMarked )
58
      {
59
      DistortedSurface tmp;
60
      Iterator<DistortedSurface> iterator = mList.iterator();
61

  
62
      while(iterator.hasNext())
63
        {
64
        tmp = iterator.next();
65

  
66
        if( tmp.mMarked )
67
          {
68
          tmp.delete();
69
          tmp.mMarked = false;
70
          iterator.remove();
71
          }
72
        }
73

  
74
      mListMarked = false;
75
      }
76
    }
77

  
22 78
///////////////////////////////////////////////////////////////////////////////////////////////////
23 79

  
80
  static synchronized void onDestroy()
81
    {
82
    for( DistortedSurface ren : mList)
83
      {
84
      ren.destroy();
85
      ren.mMarked = false;
86
      }
87

  
88
    mListMarked = false;
89
    }
90

  
91
///////////////////////////////////////////////////////////////////////////////////////////////////
92

  
93
  DistortedSurface(int width, int height, int color)
94
    {
95
    mSizeX    = width ;
96
    mSizeY    = height;
97
    mColorH[0]= color;
98
    mMarked   = false;
99
    mList.add(this);
100
    }
101

  
102
///////////////////////////////////////////////////////////////////////////////////////////////////
103
// PUBLIC API
104
///////////////////////////////////////////////////////////////////////////////////////////////////
24 105
/**
25
 * Abstract Surface.
106
 * Mark the underlying OpenGL object for deletion. Actual deletion will take place on the next render.
26 107
 */
108
  public void markForDeletion()
109
    {
110
    mListMarked = true;
111
    mMarked     = true;
112
    }
27 113

  
28
interface DistortedSurface
29
{
114
////////////////////////////////////////////////////////////////////////////////////////////////////
30 115
/**
31
 * Create the underlying OpenGL part of the Surface.
116
 * Return unique ID of the Surface.
32 117
 */
33
  void create();
118
  public long getID()
119
    {
120
    return mColorH[0];
121
    }
122

  
123
///////////////////////////////////////////////////////////////////////////////////////////////////
124

  
34 125
/**
35
 * Return a unique ID of this Surface.
126
 * Returns the height of the Surface.
127
 *
128
 * @return height of the object, in pixels.
36 129
 */
37
  long getID();
130
  public int getWidth()
131
    {
132
    return mSizeX;
133
    }
134

  
135
///////////////////////////////////////////////////////////////////////////////////////////////////
38 136
/**
39
 * Return the width of this Surface.
137
 * Returns the width of the Surface.
138
 *
139
 * @return width of the Object, in pixels.
40 140
 */
41
  int getWidth();
141
  public int getHeight()
142
    {
143
    return mSizeY;
144
    }
145

  
146
///////////////////////////////////////////////////////////////////////////////////////////////////
42 147
/**
43
 * Return the height of this Surface.
148
 * Returns the depth of the Surface.
149
 * <p>
150
 * Admittedly quite a strange method. Why do we need to pass a Mesh to it? Because one cannot determine
151
 * 'depth' of a Surface (bitmap really!) when rendered based only on the texture itself, that depends
152
 * on the Mesh it is rendered with.
153
 *
154
 * @return depth of the Object, in pixels.
44 155
 */
45
  int getHeight();
46
}
156
  public int getDepth(MeshObject mesh)
157
    {
158
    return mesh==null ? 0 : (int)(mSizeX*mesh.zFactor);
159
    }
160
  }
src/main/java/org/distorted/library/DistortedTexture.java
30 30
 * <p>
31 31
 * Create a Texture of arbitrary size and feed some pixels to it via the setTexture() method.
32 32
 */
33
public class DistortedTexture extends DistortedRenderable implements DistortedInputSurface
33
public class DistortedTexture extends DistortedSurface implements DistortedInputSurface
34 34
  {
35 35
  private Bitmap mBmp= null;
36 36

  
src/main/java/org/distorted/library/DistortedTree.java
220 220
        GLES30.glClear( GLES30.GL_DEPTH_BUFFER_BIT | GLES30.GL_COLOR_BUFFER_BIT);
221 221

  
222 222
        if( mSurface.setAsInput() )
223
          DistortedEffects.drawNoEffectsPriv(halfX, halfY, mMesh, mData.mFBO.getProjection() );
223
          DistortedEffects.drawNoEffectsPriv(halfX, halfY, mMesh, mData.mFBO );
224 224

  
225 225
        synchronized(this)
226 226
          {
src/main/java/org/distorted/library/EffectQueueMatrix.java
107 107
///////////////////////////////////////////////////////////////////////////////////////////////////
108 108
// here construct the ModelView and the ModelViewProjection Matrices
109 109

  
110
  void constructMatrices(DistortedProjection projection, float halfX, float halfY)
110
  void constructMatrices(DistortedOutputSurface projection, float halfX, float halfY)
111 111
    {
112 112
    Matrix.setIdentityM(mViewMatrix, 0);
113 113
    Matrix.translateM(mViewMatrix, 0, -projection.mWidth/2, projection.mHeight/2, -projection.mDistance);
......
284 284

  
285 285
///////////////////////////////////////////////////////////////////////////////////////////////////
286 286

  
287
  synchronized void send(DistortedProjection projection, float halfX, float halfY, float halfZ)
287
  synchronized void send(DistortedOutputSurface projection, float halfX, float halfY, float halfZ)
288 288
    {
289 289
    constructMatrices(projection,halfX,halfY);
290 290

  
......
297 297
///////////////////////////////////////////////////////////////////////////////////////////////////
298 298
// here construct the ModelView Matrix, but without any effects
299 299

  
300
  synchronized static void sendZero(DistortedProjection projection, float halfX, float halfY, float halfZ)
300
  synchronized static void sendZero(DistortedOutputSurface projection, float halfX, float halfY, float halfZ)
301 301
    {
302 302
    Matrix.setIdentityM(mTmpMatrix, 0);
303 303
    Matrix.translateM(mTmpMatrix, 0, halfX-projection.mWidth/2, projection.mHeight/2-halfY, -projection.mDistance);
src/main/java/org/distorted/library/EffectQueuePostprocess.java
233 233
    {
234 234
    mBlurProgram.useProgram();
235 235

  
236
    DistortedProjection inputP  = mBufferFBO.getProjection();
237
    DistortedProjection outputP = surface.getProjection();
238

  
239 236
    int radius = (int)mUniforms[0];
240 237
    if( radius>=MAX_BLUR ) radius = MAX_BLUR-1;
241 238
    computeGaussianKernel(radius);
......
255 252
    GLES30.glViewport(0, 0, (int)w, (int)h);
256 253

  
257 254
    Matrix.setIdentityM(mTmpMatrix, 0);
258
    Matrix.translateM(mTmpMatrix, 0, 0, 0, -inputP.mDistance);
259
    Matrix.multiplyMM(mMVPMatrix, 0, inputP.mProjectionMatrix, 0, mTmpMatrix, 0);
255
    Matrix.translateM(mTmpMatrix, 0, 0, 0, -mBufferFBO.mDistance);
256
    Matrix.multiplyMM(mMVPMatrix, 0, mBufferFBO.mProjectionMatrix, 0, mTmpMatrix, 0);
260 257

  
261 258
    // horizontal blur
262 259
    GLES30.glUniform1fv( mOffsetsH ,radius+1, mOffsets,0);
......
268 265
    mBufferFBO.setAsInput();
269 266
    surface.setAsOutput();
270 267

  
271
    GLES30.glViewport(0, 0, outputP.mWidth, outputP.mHeight);
268
    GLES30.glViewport(0, 0, surface.mWidth, surface.mHeight);
272 269

  
273 270
    for(int i=0; i<=radius; i++) mOffsets[i] = offsetsCache[offset+i]/w;
274 271

  

Also available in: Unified diff