Project

General

Profile

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

library / src / main / java / org / distorted / library / DistortedTree.java @ 421c2728

1 d333eb6b 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 6a06a912 Leszek Koltunski
package org.distorted.library;
21
22
import java.util.ArrayList;
23
import java.util.HashMap;
24
25
import android.opengl.GLES20;
26
27
///////////////////////////////////////////////////////////////////////////////////////////////////
28
/**
29 7b8086eb Leszek Koltunski
 * Class which represents a Node in a Tree of (Texture,EffectQueue,Grid) set.
30 6a06a912 Leszek Koltunski
 *  
31 7b8086eb Leszek Koltunski
 * Having organized such sets into a Tree, we can then render any Node to any Framebuffer.
32
 * That recursively renders the set held in the Node and all its children.
33 6a06a912 Leszek Koltunski
 */
34 421c2728 Leszek Koltunski
public class DistortedTree
35 6a06a912 Leszek Koltunski
  {
36 bd3da5b2 Leszek Koltunski
  private static HashMap<ArrayList<Long>,NodeData> mMapNodeID = new HashMap<>();
37
  private static long mNextNodeID =0;
38
39 b455eb48 Leszek Koltunski
  private GridObject mGrid;
40 421c2728 Leszek Koltunski
  private DistortedEffects mQueues;
41 4e2382f3 Leszek Koltunski
  private DistortedTexture mTexture;
42 6a06a912 Leszek Koltunski
  private NodeData mData;
43 bd3da5b2 Leszek Koltunski
44 421c2728 Leszek Koltunski
  private DistortedTree mParent;
45
  private ArrayList<DistortedTree> mChildren;
46 6a06a912 Leszek Koltunski
  private int[] mNumChildren;  // ==mChildren.length(), but we only create mChildren if the first one gets added
47
48
  private class NodeData
49
    {
50 bd3da5b2 Leszek Koltunski
    long ID;
51 6a06a912 Leszek Koltunski
    int numPointingNodes;
52 ed13a5de Leszek Koltunski
    DistortedFramebuffer mDF;
53 d620ff06 Leszek Koltunski
    int numRendered;
54 6a06a912 Leszek Koltunski
55 bd3da5b2 Leszek Koltunski
    NodeData(long id)
56 6a06a912 Leszek Koltunski
      {
57 bd3da5b2 Leszek Koltunski
      ID              = id;
58
      numPointingNodes= 1;
59 ed13a5de Leszek Koltunski
      mDF             = null;
60 d620ff06 Leszek Koltunski
      numRendered     = 0;
61 6a06a912 Leszek Koltunski
      }
62 bd3da5b2 Leszek Koltunski
    }
63 6a06a912 Leszek Koltunski
 
64 436899f2 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
65
66 7b8086eb Leszek Koltunski
  static synchronized void onDestroy()
67 436899f2 Leszek Koltunski
    {
68
    mNextNodeID = 0;
69
    mMapNodeID.clear();
70
    }
71
72 6a06a912 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
73
  
74 ed13a5de Leszek Koltunski
  private void drawRecursive(long currTime, DistortedFramebuffer df)
75 6a06a912 Leszek Koltunski
    {
76 1942537e Leszek Koltunski
    mTexture.createTexture();
77
78 6a06a912 Leszek Koltunski
    if( mNumChildren[0]<=0 )
79
      {
80 4e2382f3 Leszek Koltunski
      GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTexture.mTextureDataH[0]);
81 6a06a912 Leszek Koltunski
      }
82
    else
83
      {
84 7cf783cb Leszek Koltunski
      mData.mDF.createFBO();
85
86 d620ff06 Leszek Koltunski
      if( mData.numRendered==0 )
87 6a06a912 Leszek Koltunski
        {
88 7cf783cb Leszek Koltunski
        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mData.mDF.fboIds[0]);
89 bd3da5b2 Leszek Koltunski
90 6a06a912 Leszek Koltunski
        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
91
        GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
92
      
93 4e2382f3 Leszek Koltunski
        if( mTexture.mBitmapSet[0] )
94 6a06a912 Leszek Koltunski
          {
95 4e2382f3 Leszek Koltunski
          GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTexture.mTextureDataH[0]);
96
          mQueues.drawNoEffectsPriv(mTexture, mGrid, mData.mDF);
97 6a06a912 Leszek Koltunski
          }
98
      
99
        synchronized(this)
100
          {
101
          for(int i=0; i<mNumChildren[0]; i++)
102
            {
103 ed13a5de Leszek Koltunski
            mChildren.get(i).drawRecursive(currTime, mData.mDF);
104 6a06a912 Leszek Koltunski
            }
105
          }
106
        }
107 bd3da5b2 Leszek Koltunski
108 d620ff06 Leszek Koltunski
      mData.numRendered++;
109
      mData.numRendered %= mData.numPointingNodes;
110
111 7cf783cb Leszek Koltunski
      GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, df.fboIds[0]);
112
      GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mData.mDF.texIds[0]);
113 6a06a912 Leszek Koltunski
      }
114
    
115 4e2382f3 Leszek Koltunski
    mQueues.drawPriv(currTime, mTexture, mGrid, df);
116 6a06a912 Leszek Koltunski
    }
117
  
118
///////////////////////////////////////////////////////////////////////////////////////////////////
119
// tree isomorphism
120
  
121
  private void RecomputeNodeID(ArrayList<Long> prev)
122
    {
123
    ArrayList<Long> curr = generateIDList();
124
     
125
    if( mParent==null )
126
      {
127
      adjustNodeData(prev,curr);
128
      }
129
    else
130
      {
131
      ArrayList<Long> parentPrev = mParent.generateIDList();
132
      adjustNodeData(prev,curr);
133
      mParent.RecomputeNodeID(parentPrev);
134
      }
135
    }
136
137
///////////////////////////////////////////////////////////////////////////////////////////////////
138
139
  private ArrayList<Long> generateIDList()
140
    {
141 9361b337 Leszek Koltunski
    ArrayList<Long> ret = new ArrayList<>();
142 6a06a912 Leszek Koltunski
     
143 1942537e Leszek Koltunski
    ret.add( mTexture.getID() );
144 421c2728 Leszek Koltunski
    DistortedTree node;
145 6a06a912 Leszek Koltunski
   
146
    for(int i=0; i<mNumChildren[0]; i++)
147
      {
148
      node = mChildren.get(i);
149
      ret.add(node.mData.ID);
150
      }
151
   
152
    return ret;
153
    }
154
155
///////////////////////////////////////////////////////////////////////////////////////////////////
156
157
  private void adjustNodeData(ArrayList<Long> oldList, ArrayList<Long> newList)
158
    {
159 fee0865c Leszek Koltunski
    boolean otherNodesPoint = (mData.numPointingNodes>1);
160
161
    if( otherNodesPoint ) mData.numPointingNodes--;
162
    else                  mMapNodeID.remove(oldList);
163 1942537e Leszek Koltunski
164 6a06a912 Leszek Koltunski
    NodeData newData = mMapNodeID.get(newList);
165
    
166
    if( newData==null )
167
      {
168 fee0865c Leszek Koltunski
      if( otherNodesPoint )  mData = new NodeData(++mNextNodeID);
169
      else                   mData.ID = ++mNextNodeID;  // numPointingNodes must be 1 already
170
171 16d8b8f3 Leszek Koltunski
      if( newList.size()>1 )
172
        {
173
        if( mData.mDF==null )
174 4e2382f3 Leszek Koltunski
          mData.mDF = new DistortedFramebuffer(mTexture.getWidth(), mTexture.getHeight());
175 16d8b8f3 Leszek Koltunski
        }
176
      else
177
        {
178
        if( mData.mDF!=null )
179
          {
180
          mData.mDF.markForDeletion();
181
          mData.mDF = null;
182
          }
183
        else
184
          {
185 421c2728 Leszek Koltunski
          android.util.Log.e("DistortedTree", "adjustNodeData: impossible situation??");
186 16d8b8f3 Leszek Koltunski
          }
187
        }
188 bd3da5b2 Leszek Koltunski
189 6a06a912 Leszek Koltunski
      mMapNodeID.put(newList, mData);
190
      }
191
    else
192 fee0865c Leszek Koltunski
      {
193 6a06a912 Leszek Koltunski
      newData.numPointingNodes++;
194
      mData = newData;
195
      }
196
    }
197
198
///////////////////////////////////////////////////////////////////////////////////////////////////  
199
// this will be called on startup and every time OpenGL context has been lost
200 d620ff06 Leszek Koltunski
201 6a06a912 Leszek Koltunski
  static void reset()
202
    {
203
    NodeData tmp;   
204
     
205
    for(ArrayList<Long> key: mMapNodeID.keySet())
206
      {
207
      tmp = mMapNodeID.get(key);
208
          
209 ed13a5de Leszek Koltunski
      if( tmp.mDF != null )
210 6a06a912 Leszek Koltunski
        {
211 ed13a5de Leszek Koltunski
    	  tmp.mDF.reset();
212 d620ff06 Leszek Koltunski
        tmp.numRendered = 0;
213 6a06a912 Leszek Koltunski
        }
214
      }
215
    }
216 fee0865c Leszek Koltunski
217
///////////////////////////////////////////////////////////////////////////////////////////////////
218
// Debug - print all the Node IDs
219 1942537e Leszek Koltunski
220 fee0865c Leszek Koltunski
  void debug(int depth)
221
    {
222
    String tmp="";
223
    int i;
224
225
    for(i=0; i<depth; i++) tmp +="   ";
226 1942537e Leszek Koltunski
    tmp += (mData.ID+" (nodes: "+mData.numPointingNodes+")");
227 fee0865c Leszek Koltunski
228 1942537e Leszek Koltunski
    android.util.Log.e("NODE", tmp);
229 fee0865c Leszek Koltunski
230
    for(i=0; i<mNumChildren[0]; i++)
231
      mChildren.get(i).debug(depth+1);
232
    }
233
234
///////////////////////////////////////////////////////////////////////////////////////////////////
235
// Debug - print contents of the HashMap
236
237
  static void debugMap()
238
    {
239
    NodeData tmp;
240
241
    for(ArrayList<Long> key: mMapNodeID.keySet())
242
      {
243
      tmp = mMapNodeID.get(key);
244
245
      android.util.Log.e("NODE", "key="+key+" NodeID: "+tmp.ID);
246
      }
247
    }
248 1942537e Leszek Koltunski
249 6a06a912 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
250
// PUBLIC API
251
///////////////////////////////////////////////////////////////////////////////////////////////////
252
/**
253
 * Constructs new Node of the Tree.
254
 *     
255 4e2382f3 Leszek Koltunski
 * @param texture DistortedTexture to put into the new Node.
256 421c2728 Leszek Koltunski
 * @param queues  DistortedEffects to put into the new Node.
257 4e2382f3 Leszek Koltunski
 * @param grid GridObject to put into the new Node.
258 6a06a912 Leszek Koltunski
 */
259 421c2728 Leszek Koltunski
  public DistortedTree(DistortedTexture texture, DistortedEffects queues, GridObject grid)
260 6a06a912 Leszek Koltunski
    {
261 4e2382f3 Leszek Koltunski
    mTexture= texture;
262
    mQueues = queues;
263 a56bc359 Leszek Koltunski
    mGrid   = grid;
264 6a06a912 Leszek Koltunski
    mParent = null;
265
    mChildren = null;
266
    mNumChildren = new int[1];
267
    mNumChildren[0] = 0;
268
   
269 9361b337 Leszek Koltunski
    ArrayList<Long> list = new ArrayList<>();
270 1942537e Leszek Koltunski
    list.add(mTexture.getID());
271
272 6a06a912 Leszek Koltunski
    mData = mMapNodeID.get(list);
273
   
274
    if( mData!=null )
275
      {
276
      mData.numPointingNodes++;
277
      }
278
    else
279
      {
280
      mData = new NodeData(++mNextNodeID);   
281 1942537e Leszek Koltunski
      mMapNodeID.put(list, mData);
282 6a06a912 Leszek Koltunski
      }
283
    }
284
285
///////////////////////////////////////////////////////////////////////////////////////////////////  
286
/**
287
 * Copy-constructs new Node of the Tree from another Node.
288
 *     
289 421c2728 Leszek Koltunski
 * @param node The DistortedTree to copy data from.
290 6a06a912 Leszek Koltunski
 * @param flags bit field composed of a subset of the following:
291 015642fb Leszek Koltunski
 *        {@link Distorted#CLONE_BITMAP},  {@link Distorted#CLONE_MATRIX}, {@link Distorted#CLONE_VERTEX},
292 6a06a912 Leszek Koltunski
 *        {@link Distorted#CLONE_FRAGMENT} and {@link Distorted#CLONE_CHILDREN}.
293
 *        For example flags = CLONE_BITMAP | CLONE_CHILDREN.
294
 */
295 421c2728 Leszek Koltunski
  public DistortedTree(DistortedTree node, int flags)
296 6a06a912 Leszek Koltunski
    {
297 9361b337 Leszek Koltunski
    mParent = null;
298 4e2382f3 Leszek Koltunski
    mTexture= new DistortedTexture(node.mTexture,flags);
299 421c2728 Leszek Koltunski
    mQueues = new DistortedEffects(node.mQueues, flags);
300 a56bc359 Leszek Koltunski
    mGrid   = node.mGrid;
301 9361b337 Leszek Koltunski
302
    if( (flags & Distorted.CLONE_CHILDREN) != 0 )
303 6a06a912 Leszek Koltunski
      {
304
      mChildren = node.mChildren;
305
      mNumChildren = node.mNumChildren;
306
      }
307
    else
308
      {
309
      mChildren = null;
310
      mNumChildren = new int[1];
311
      mNumChildren[0] = 0;
312
      }
313
   
314
    ArrayList<Long> list = generateIDList();
315
   
316
    mData = mMapNodeID.get(list);
317
   
318
    if( mData!=null )
319
      {
320
      mData.numPointingNodes++;
321
      }
322
    else
323
      {
324
      mData = new NodeData(++mNextNodeID);   
325
      mMapNodeID.put(list, mData);
326
      }
327
    }
328
  
329
///////////////////////////////////////////////////////////////////////////////////////////////////
330
/**
331
 * Adds a new child to the last position in the list of our Node's children.
332
 * 
333
 * @param node The new Node to add.
334
 */
335 421c2728 Leszek Koltunski
  public synchronized void attach(DistortedTree node)
336 6a06a912 Leszek Koltunski
    {
337
    ArrayList<Long> prev = generateIDList(); 
338
   
339 9361b337 Leszek Koltunski
    if( mChildren==null ) mChildren = new ArrayList<>(2);
340 6a06a912 Leszek Koltunski
     
341
    node.mParent = this;
342
    mChildren.add(node);
343
    mNumChildren[0]++;
344
     
345
    RecomputeNodeID(prev);
346
    }
347
   
348
///////////////////////////////////////////////////////////////////////////////////////////////////
349
/**
350
 * Adds a new child to the last position in the list of our Node's children.
351
 * 
352 4e2382f3 Leszek Koltunski
 * @param texture DistortedTexture to initialize our child Node with.
353 421c2728 Leszek Koltunski
 * @param queues DistortedEffects to initialize our child Node with.
354 4e2382f3 Leszek Koltunski
 * @param grid GridObject to initialize our child Node with.
355 6a06a912 Leszek Koltunski
 * @return the newly constructed child Node, or null if we couldn't allocate resources.
356
 */
357 421c2728 Leszek Koltunski
  public synchronized DistortedTree attach(DistortedTexture texture, DistortedEffects queues, GridObject grid)
358 6a06a912 Leszek Koltunski
    {
359
    ArrayList<Long> prev = generateIDList(); 
360
      
361 9361b337 Leszek Koltunski
    if( mChildren==null ) mChildren = new ArrayList<>(2);
362 421c2728 Leszek Koltunski
    DistortedTree node = new DistortedTree(texture,queues,grid);
363 6a06a912 Leszek Koltunski
    node.mParent = this;
364
    mChildren.add(node);
365
    mNumChildren[0]++;
366
   
367
    RecomputeNodeID(prev);
368 fee0865c Leszek Koltunski
369 6a06a912 Leszek Koltunski
    return node;
370
    }
371
  
372
///////////////////////////////////////////////////////////////////////////////////////////////////
373
/**
374
 * Removes the first occurrence of a specified child from the list of children of our Node.
375
 * 
376
 * @param node The Node to remove.
377
 * @return <code>true</code> if the child was successfully removed.
378
 */
379 421c2728 Leszek Koltunski
  public synchronized boolean detach(DistortedTree node)
380 6a06a912 Leszek Koltunski
    {
381
    if( mNumChildren[0]>0 )
382
      {
383
      ArrayList<Long> prev = generateIDList();  
384
         
385
      if( mChildren.remove(node) )
386
        {
387
        node.mParent = null;  
388
        mNumChildren[0]--;
389
     
390
        RecomputeNodeID(prev);
391
     
392
        return true;
393
        }
394
      }
395
   
396
    return false;
397
    }
398
  
399
///////////////////////////////////////////////////////////////////////////////////////////////////
400
/**
401
 * Removes the first occurrence of a specified child from the list of children of our Node.
402
 * 
403 421c2728 Leszek Koltunski
 * @param queues DistortedEffects to remove.
404 6a06a912 Leszek Koltunski
 * @return <code>true</code> if the child was successfully removed.
405
 */
406 421c2728 Leszek Koltunski
  public synchronized boolean detach(DistortedEffects queues)
407 6a06a912 Leszek Koltunski
    {
408 4e2382f3 Leszek Koltunski
    long id = queues.getID();
409 421c2728 Leszek Koltunski
    DistortedTree node;
410 6a06a912 Leszek Koltunski
   
411
    for(int i=0; i<mNumChildren[0]; i++)
412
      {
413
      node = mChildren.get(i);
414
     
415 4e2382f3 Leszek Koltunski
      if( node.mQueues.getID()==id )
416 6a06a912 Leszek Koltunski
        {
417
        ArrayList<Long> prev = generateIDList();   
418
     
419
        node.mParent = null;  
420
        mChildren.remove(i);
421
        mNumChildren[0]--;
422
      
423
        RecomputeNodeID(prev);
424
      
425
        return true;
426
        }
427
      }
428
   
429
    return false;
430
    }
431
    
432
///////////////////////////////////////////////////////////////////////////////////////////////////
433
/**
434
 * Removes all children Nodes.
435
 */
436
  public synchronized void detachAll()
437
    {
438
    for(int i=0; i<mNumChildren[0]; i++)
439
      {
440
      mChildren.get(i).mParent = null;
441
      }
442
   
443
    if( mNumChildren[0]>0 )
444
      {
445
      ArrayList<Long> prev = generateIDList();  
446
      
447
      mNumChildren[0] = 0;
448
      mChildren.clear();
449
      RecomputeNodeID(prev);
450
      }
451
    }
452 d1e740c5 Leszek Koltunski
453
///////////////////////////////////////////////////////////////////////////////////////////////////
454
/**
455
 * Draws the Node, and all its children, to the Framebuffer passed.
456 6537ba91 Leszek Koltunski
 * <p>
457
 * Must be called from a thread holding OpenGL Context
458 d1e740c5 Leszek Koltunski
 *
459
 * @param currTime Current time, in milliseconds.
460
 * @param df       Framebuffer to render this to.
461
 */
462
  public void draw(long currTime, DistortedFramebuffer df)
463
    {
464 7cf783cb Leszek Koltunski
    df.createFBO();
465
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, df.fboIds[0]);
466 d1e740c5 Leszek Koltunski
    drawRecursive(currTime,df);
467 1942537e Leszek Koltunski
    DistortedFramebuffer.deleteAllMarked();
468
    DistortedTexture.deleteAllMarked();
469 d1e740c5 Leszek Koltunski
    }
470
471 6a06a912 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
472
/**
473 421c2728 Leszek Koltunski
 * Returns the DistortedEffects object that's in the Node.
474 6a06a912 Leszek Koltunski
 * 
475 421c2728 Leszek Koltunski
 * @return The DistortedEffects contained in the Node.
476 6a06a912 Leszek Koltunski
 */
477 421c2728 Leszek Koltunski
  public DistortedEffects getEffects()
478 6a06a912 Leszek Koltunski
    {
479 4e2382f3 Leszek Koltunski
    return mQueues;
480
    }
481
482
///////////////////////////////////////////////////////////////////////////////////////////////////
483
/**
484
 * Returns the DistortedTexture object that's in the Node.
485
 *
486
 * @return The DistortedTexture contained in the Node.
487
 */
488
  public DistortedTexture getTexture()
489
    {
490
    return mTexture;
491 6a06a912 Leszek Koltunski
    }
492
493
///////////////////////////////////////////////////////////////////////////////////////////////////
494
  }