Project

General

Profile

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

library / src / main / java / org / distorted / library / main / DistortedNode.java @ b4999b55

1 d333eb6b Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2016 Leszek Koltunski                                                               //
3
//                                                                                               //
4 46b572b5 Leszek Koltunski
// This file is part of Distorted.                                                               //
5 d333eb6b Leszek Koltunski
//                                                                                               //
6 46b572b5 Leszek Koltunski
// Distorted is free software: you can redistribute it and/or modify                             //
7 d333eb6b Leszek Koltunski
// 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 46b572b5 Leszek Koltunski
// Distorted is distributed in the hope that it will be useful,                                  //
12 d333eb6b Leszek Koltunski
// 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 46b572b5 Leszek Koltunski
// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                            //
18 d333eb6b Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
19
20 fe82a979 Leszek Koltunski
package org.distorted.library.main;
21 6a06a912 Leszek Koltunski
22 b7074bc6 Leszek Koltunski
import android.opengl.GLES30;
23 8dccc3c2 Leszek Koltunski
24 715e7726 Leszek Koltunski
import org.distorted.library.mesh.MeshBase;
25 6c00149d Leszek Koltunski
26 6a06a912 Leszek Koltunski
import java.util.ArrayList;
27 c9f953c2 Leszek Koltunski
import java.util.Collections;
28 6a06a912 Leszek Koltunski
29
///////////////////////////////////////////////////////////////////////////////////////////////////
30
/**
31 a09ada4c Leszek Koltunski
 * Class which represents a Node in a Tree of (InputSurface,Mesh,Effects) triplets.
32 c204c69d leszek
 * <p>
33 a09ada4c Leszek Koltunski
 * Having organized such sets into a Tree, we can then render any Node to any OutputSurface.
34 7b8086eb Leszek Koltunski
 * That recursively renders the set held in the Node and all its children.
35 c204c69d leszek
 * <p>
36
 * The class takes special care to only render identical sub-trees once. Each Node holds a reference
37
 * to sub-class 'NodeData'. Two identical sub-trees attached at different points of the main tree
38 3a70bd6d leszek
 * will point to the same NodeData; only the first of this is rendered (mData.numRender!).
39 6a06a912 Leszek Koltunski
 */
40 7602a827 Leszek Koltunski
public class DistortedNode implements InternalChildrenList.Parent
41 6a06a912 Leszek Koltunski
  {
42 209ea1c7 Leszek Koltunski
  private static final int DEFAULT_FBO_SIZE = 100;
43
44 3272cfb8 Leszek Koltunski
  private final MeshBase mMesh;
45
  private final DistortedEffects mEffects;
46
  private final InternalRenderState mState;
47
  private final InternalChildrenList mChildren;
48
  private InternalChildrenList.Parent mParent;
49 7602a827 Leszek Koltunski
  private InternalSurface mSurface;
50
  private InternalNodeData mData;
51 11845a9e Leszek Koltunski
52 23eecbd9 Leszek Koltunski
  private int mFboW, mFboH, mFboDepthStencil;
53 11845a9e Leszek Koltunski
  private boolean mRenderWayOIT;
54 209ea1c7 Leszek Koltunski
  private float mFOV, mNear;
55 835b197e Leszek Koltunski
  private long mLastTime;
56 bd3da5b2 Leszek Koltunski
57 c43abe6c Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
58
59
  public void markForDeletion()
60
    {
61 8bfefd68 Leszek Koltunski
    if( mData.removeData() )
62 c43abe6c Leszek Koltunski
      {
63 8bfefd68 Leszek Koltunski
      mData.mFBO.markForDeletion();
64
      mData.mFBO = null;
65 c43abe6c Leszek Koltunski
      }
66 d5b709df Leszek Koltunski
    }
67
68
///////////////////////////////////////////////////////////////////////////////////////////////////
69 46b572b5 Leszek Koltunski
// [3] --> the postprocessing queue. See EffectType.
70 c43abe6c Leszek Koltunski
71 d5b709df Leszek Koltunski
  long getBucket()
72
    {
73
    return mEffects.getQueues()[3].getID();
74 c43abe6c Leszek Koltunski
    }
75
76 6a06a912 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
77
78
  private ArrayList<Long> generateIDList()
79
    {
80 9361b337 Leszek Koltunski
    ArrayList<Long> ret = new ArrayList<>();
81 11845a9e Leszek Koltunski
    int numChildren = mChildren.getNumChildren();
82 7691a39f leszek
83 11845a9e Leszek Koltunski
    if( numChildren==0 )
84 7691a39f leszek
      {
85 c9f953c2 Leszek Koltunski
      // add a negative number so this leaf never gets confused with a internal node
86
      // with a single child that happens to have ID identical to some leaf's Effects ID.
87 7691a39f leszek
      ret.add(-mEffects.getID());
88
      }
89 c9f953c2 Leszek Koltunski
    else
90 6a06a912 Leszek Koltunski
      {
91 c9f953c2 Leszek Koltunski
      DistortedNode node;
92 6a06a912 Leszek Koltunski
   
93 11845a9e Leszek Koltunski
      for(int i=0; i<numChildren; i++)
94 c9f953c2 Leszek Koltunski
        {
95 11845a9e Leszek Koltunski
        node = mChildren.getChild(i);
96 c9f953c2 Leszek Koltunski
        ret.add(node.mData.ID);
97
        }
98
99
      // A bit questionable decision here - we are sorting the children IDs, which means
100
      // that order in which we draw the children is going to be undefined (well, this is not
101
      // strictly speaking true - when rendering, if no postprocessing and isomorphism are
102
      // involved, we *DO* render the children in order they were added; if however there
103
      // are two internal nodes with the same list of identical children, just added in a
104
      // different order each time, then we consider them isomorphic, i.e. identical and only
105
      // render the first one. If then two children of such 'pseudo-isomorphic' nodes are at
106
      // exactly the same Z-height this might result in some unexpected sights).
107
      //
108
      // Reason: with the children being sorted by postprocessing buckets, the order is
109
      // undefined anyway (although only when postprocessing is applied).
110
      //
111
      // See the consequences in the 'Olympic' app - remove a few leaves and add them back in
112 d5e053a5 Leszek Koltunski
      // different order. You will see the number of renders go back to the original 15.
113 c9f953c2 Leszek Koltunski
      Collections.sort(ret);
114
      }
115
116
    ret.add( 0, mSurface.getID() );
117
118 6a06a912 Leszek Koltunski
    return ret;
119
    }
120
121 9cae4322 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
122 11845a9e Leszek Koltunski
/**
123
 * This is not really part of the public API. Has to be public only because it is a part of the
124 7602a827 Leszek Koltunski
 * InternalChildrenList.Parent interface.
125 11845a9e Leszek Koltunski
 *
126
 * @y.exclude
127
 */
128
  public void adjustIsomorphism()
129 9cae4322 Leszek Koltunski
    {
130 7602a827 Leszek Koltunski
    InternalNodeData newData = InternalNodeData.returnData(generateIDList());
131 8bfefd68 Leszek Koltunski
    boolean deleteOldFBO = mData.removeData();
132 11845a9e Leszek Koltunski
    boolean createNewFBO = (mChildren.getNumChildren()>0 && newData.mFBO==null);
133 c204c69d leszek
134 f28fffc2 Leszek Koltunski
    if( deleteOldFBO && createNewFBO )
135
      {
136 8bfefd68 Leszek Koltunski
      newData.mFBO = mData.mFBO;
137 f28fffc2 Leszek Koltunski
      }
138
    else if( deleteOldFBO )
139
      {
140
      mData.mFBO.markForDeletion();
141
      mData.mFBO = null;
142
      }
143
    else if( createNewFBO )
144
      {
145 11845a9e Leszek Koltunski
      newData.mFBO = allocateNewFBO();
146 f28fffc2 Leszek Koltunski
      }
147 af27df87 leszek
148 f28fffc2 Leszek Koltunski
    mData = newData;
149 c204c69d leszek
150 f28fffc2 Leszek Koltunski
    if( mParent!=null ) mParent.adjustIsomorphism();
151 fee0865c Leszek Koltunski
    }
152 c204c69d leszek
153 8dccc3c2 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
154
// return the total number of render calls issued
155
156 7602a827 Leszek Koltunski
  int drawNoBlend(long currTime, InternalOutputSurface surface)
157 8dccc3c2 Leszek Koltunski
    {
158 eddf0cb7 Leszek Koltunski
    InternalSurface input = getSurface();
159 8dccc3c2 Leszek Koltunski
160
    if( input.setAsInput() )
161
      {
162
      mState.apply();
163 b7074bc6 Leszek Koltunski
      GLES30.glDisable(GLES30.GL_BLEND);
164 835b197e Leszek Koltunski
      if( mLastTime==0 ) mLastTime=currTime;
165
      DistortedLibrary.drawPriv(mEffects, mMesh, surface, currTime, (currTime-mLastTime));
166
      mLastTime = currTime;
167 b7074bc6 Leszek Koltunski
      GLES30.glEnable(GLES30.GL_BLEND);
168 8dccc3c2 Leszek Koltunski
      return 1;
169
      }
170 c1a38ba3 Leszek Koltunski
171
    return 0;
172
    }
173
174
///////////////////////////////////////////////////////////////////////////////////////////////////
175
// Use the Order Independent Transparency method to draw a non-postprocessed child.
176
177 7602a827 Leszek Koltunski
  int drawOIT(long currTime, InternalOutputSurface surface)
178 c1a38ba3 Leszek Koltunski
    {
179 eddf0cb7 Leszek Koltunski
    InternalSurface input = getSurface();
180 c1a38ba3 Leszek Koltunski
181
    if( input.setAsInput() )
182
      {
183
      mState.apply();
184 835b197e Leszek Koltunski
      if( mLastTime==0 ) mLastTime=currTime;
185
      DistortedLibrary.drawPrivOIT(mEffects, mMesh, surface, currTime, (currTime-mLastTime));
186
      mLastTime = currTime;
187 c1a38ba3 Leszek Koltunski
      return 1;
188
      }
189 8dccc3c2 Leszek Koltunski
190
    return 0;
191
    }
192
193 39086ebb leszek
///////////////////////////////////////////////////////////////////////////////////////////////////
194
// return the total number of render calls issued
195
196 7602a827 Leszek Koltunski
  int draw(long currTime, InternalOutputSurface surface)
197 39086ebb leszek
    {
198 eddf0cb7 Leszek Koltunski
    InternalSurface input = getSurface();
199 39086ebb leszek
200
    if( input.setAsInput() )
201
      {
202
      mState.apply();
203 835b197e Leszek Koltunski
      if( mLastTime==0 ) mLastTime=currTime;
204
      DistortedLibrary.drawPriv(mEffects, mMesh, surface, currTime, (currTime-mLastTime));
205
      mLastTime = currTime;
206 39086ebb leszek
      return 1;
207
      }
208
209
    return 0;
210
    }
211
212
///////////////////////////////////////////////////////////////////////////////////////////////////
213
// return the total number of render calls issued
214
215
  int renderRecursive(long currTime)
216
    {
217
    int numRenders = 0;
218 11845a9e Leszek Koltunski
    int numChildren = mChildren.getNumChildren();
219 39086ebb leszek
220 11845a9e Leszek Koltunski
    if( numChildren>0 && mData.notRenderedYetAtThisTime(currTime) )
221 39086ebb leszek
      {
222 d5b709df Leszek Koltunski
      DistortedNode node;
223
      long oldBucket=0, newBucket;
224
225 11845a9e Leszek Koltunski
      for (int i=0; i<numChildren; i++)
226 0c303a2c Leszek Koltunski
        {
227 d5b709df Leszek Koltunski
        node = mChildren.getChild(i);
228
        newBucket = node.getBucket();
229
        numRenders += node.renderRecursive(currTime);
230
        if( newBucket<oldBucket ) mChildren.rearrangeByBuckets(i,newBucket);
231
        else oldBucket=newBucket;
232 0c303a2c Leszek Koltunski
        }
233
234 11845a9e Leszek Koltunski
      if( mData.mFBO==null ) mData.mFBO = allocateNewFBO();
235 95c441a2 leszek
      mData.mFBO.setAsOutput(currTime);
236 39086ebb leszek
237
      if( mSurface.setAsInput() )
238
        {
239
        numRenders++;
240 7602a827 Leszek Koltunski
        DistortedLibrary.blitPriv(mData.mFBO);
241 39086ebb leszek
        }
242
243 11845a9e Leszek Koltunski
      numRenders += mData.mFBO.renderChildren(currTime,numChildren,mChildren,0, mRenderWayOIT);
244 39086ebb leszek
      }
245
246
    return numRenders;
247
    }
248
249 be60d4ff leszek
///////////////////////////////////////////////////////////////////////////////////////////////////
250
251 11845a9e Leszek Koltunski
  private DistortedFramebuffer allocateNewFBO()
252 be60d4ff leszek
    {
253 9ecac8cd Leszek Koltunski
    int width, height;
254
255
    if( mFboW>0 && mFboH>0 )
256
      {
257
      width = mFboW;
258
      height= mFboH;
259
      }
260
    else
261
      {
262
      if( mSurface instanceof DistortedFramebuffer )
263
        {
264
        DistortedFramebuffer fbo = (DistortedFramebuffer)mSurface;
265
        width = fbo.mWidth;
266
        height= fbo.mHeight;
267
        }
268
      else
269
        {
270 209ea1c7 Leszek Koltunski
        width = DEFAULT_FBO_SIZE;
271
        height= DEFAULT_FBO_SIZE;
272 9ecac8cd Leszek Koltunski
        }
273
      }
274
275 209ea1c7 Leszek Koltunski
    DistortedFramebuffer fbo = new DistortedFramebuffer(1,mFboDepthStencil, InternalSurface.TYPE_TREE, width, height);
276
277
    if( mFOV!=InternalOutputSurface.DEFAULT_FOV || mNear!=InternalOutputSurface.DEFAULT_NEAR )
278
      {
279
      fbo.setProjection(mFOV,mNear);
280
      }
281
282
    return fbo;
283 11845a9e Leszek Koltunski
    }
284
285 3272cfb8 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
286
287
  void resetLastTime()
288
    {
289
    mLastTime = 0;
290
    }
291
292 11845a9e Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
293
294 7602a827 Leszek Koltunski
  void setParent(InternalChildrenList.Parent parent)
295 11845a9e Leszek Koltunski
    {
296
    mParent = parent;
297 be60d4ff leszek
    }
298
299 6a06a912 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
300
// PUBLIC API
301
///////////////////////////////////////////////////////////////////////////////////////////////////
302
/**
303 a09ada4c Leszek Koltunski
 * Constructs new Node.
304 6a06a912 Leszek Koltunski
 *     
305 c5369f1b leszek
 * @param surface InputSurface to put into the new Node.
306 07d8ef09 Leszek Koltunski
 * @param effects DistortedEffects to put into the new Node.
307 715e7726 Leszek Koltunski
 * @param mesh MeshBase to put into the new Node.
308 6a06a912 Leszek Koltunski
 */
309 7602a827 Leszek Koltunski
  public DistortedNode(InternalSurface surface, DistortedEffects effects, MeshBase mesh)
310 6a06a912 Leszek Koltunski
    {
311 835b197e Leszek Koltunski
    mLastTime      = 0;
312 c5369f1b leszek
    mSurface       = surface;
313 8ca9f899 Leszek Koltunski
    mEffects       = effects;
314
    mMesh          = mesh;
315 7602a827 Leszek Koltunski
    mState         = new InternalRenderState();
316
    mChildren      = new InternalChildrenList(this);
317 f28fffc2 Leszek Koltunski
    mParent        = null;
318 406e2f6b Leszek Koltunski
    mRenderWayOIT  = false;
319 f28fffc2 Leszek Koltunski
320 209ea1c7 Leszek Koltunski
    mFOV = InternalOutputSurface.DEFAULT_FOV;
321
    mNear= InternalOutputSurface.DEFAULT_NEAR;
322
323 23eecbd9 Leszek Koltunski
    mFboW            = 0;  // i.e. take this from
324 c90aca24 Leszek Koltunski
    mFboH            = 0;  // mEffects's stretch{X,Y}
325 23eecbd9 Leszek Koltunski
    mFboDepthStencil = DistortedFramebuffer.DEPTH_NO_STENCIL;
326
327 7602a827 Leszek Koltunski
    mData = InternalNodeData.returnData(generateIDList());
328 6a06a912 Leszek Koltunski
    }
329
330
///////////////////////////////////////////////////////////////////////////////////////////////////  
331
/**
332 a09ada4c Leszek Koltunski
 * Copy-constructs new Node from another Node.
333 6a06a912 Leszek Koltunski
 *     
334 a09ada4c Leszek Koltunski
 * @param node The DistortedNode to copy data from.
335 6a06a912 Leszek Koltunski
 * @param flags bit field composed of a subset of the following:
336 7602a827 Leszek Koltunski
 *        {@link DistortedLibrary#CLONE_SURFACE},  {@link DistortedLibrary#CLONE_MATRIX}, {@link DistortedLibrary#CLONE_VERTEX},
337
 *        {@link DistortedLibrary#CLONE_FRAGMENT} and {@link DistortedLibrary#CLONE_CHILDREN}.
338 29a06526 Leszek Koltunski
 *        For example flags = CLONE_SURFACE | CLONE_CHILDREN.
339 6a06a912 Leszek Koltunski
 */
340 a09ada4c Leszek Koltunski
  public DistortedNode(DistortedNode node, int flags)
341 6a06a912 Leszek Koltunski
    {
342 835b197e Leszek Koltunski
    mLastTime     = 0;
343 be60d4ff leszek
    mEffects      = new DistortedEffects(node.mEffects,flags);
344
    mMesh         = node.mMesh;
345 7602a827 Leszek Koltunski
    mState        = new InternalRenderState();
346 be60d4ff leszek
    mParent       = null;
347 406e2f6b Leszek Koltunski
    mRenderWayOIT = false;
348 9361b337 Leszek Koltunski
349 209ea1c7 Leszek Koltunski
    mFOV = InternalOutputSurface.DEFAULT_FOV;
350
    mNear= InternalOutputSurface.DEFAULT_NEAR;
351
352 23eecbd9 Leszek Koltunski
    mFboW            = node.mFboW;
353
    mFboH            = node.mFboH;
354
    mFboDepthStencil = node.mFboDepthStencil;
355
356 7602a827 Leszek Koltunski
    if( (flags & DistortedLibrary.CLONE_SURFACE) != 0 )
357 e7a20702 Leszek Koltunski
      {
358 c5369f1b leszek
      mSurface = node.mSurface;
359 e7a20702 Leszek Koltunski
      }
360
    else
361
      {
362 c5369f1b leszek
      if( node.mSurface instanceof DistortedTexture )
363 8ca9f899 Leszek Koltunski
        {
364 c90aca24 Leszek Koltunski
        mSurface = new DistortedTexture(InternalSurface.TYPE_TREE);
365 8ca9f899 Leszek Koltunski
        }
366 c5369f1b leszek
      else if( node.mSurface instanceof DistortedFramebuffer )
367 8ca9f899 Leszek Koltunski
        {
368 d58b50e7 Leszek Koltunski
        DistortedFramebuffer fbo = (DistortedFramebuffer)node.mSurface;
369
370
        int w = fbo.getWidth();
371
        int h = fbo.getHeight();
372 23eecbd9 Leszek Koltunski
        int depthStencil = DistortedFramebuffer.NO_DEPTH_NO_STENCIL;
373 89de975c leszek
374 d58b50e7 Leszek Koltunski
        if( fbo.hasDepth() )
375 89de975c leszek
          {
376 d58b50e7 Leszek Koltunski
          boolean hasStencil = fbo.hasStencil();
377 89de975c leszek
          depthStencil = (hasStencil ? DistortedFramebuffer.BOTH_DEPTH_STENCIL:DistortedFramebuffer.DEPTH_NO_STENCIL);
378
          }
379
380 7602a827 Leszek Koltunski
        mSurface = new DistortedFramebuffer(1,depthStencil, InternalSurface.TYPE_TREE,w,h);
381 8ca9f899 Leszek Koltunski
        }
382 e7a20702 Leszek Koltunski
      }
383 11845a9e Leszek Koltunski
384 7602a827 Leszek Koltunski
    if( (flags & DistortedLibrary.CLONE_CHILDREN) != 0 )
385 6a06a912 Leszek Koltunski
      {
386
      mChildren = node.mChildren;
387
      }
388
    else
389
      {
390 7602a827 Leszek Koltunski
      mChildren = new InternalChildrenList(this);
391 6a06a912 Leszek Koltunski
      }
392 26a4e5f6 leszek
393 7602a827 Leszek Koltunski
    mData = InternalNodeData.returnData(generateIDList());
394 6a06a912 Leszek Koltunski
    }
395 c204c69d leszek
396 406e2f6b Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
397 b4999b55 Leszek Koltunski
  /**
398
   * Change the input surface while keeping everything else about the Node the same.
399
   *
400
   * @param surface The new input surface.
401
   */
402
  public void changeInputSurface(InternalSurface surface)
403
    {
404
    mSurface = surface;
405
    }
406
407
///////////////////////////////////////////////////////////////////////////////////////////////////
408
409 406e2f6b Leszek Koltunski
  /**
410
   * When rendering this Node, should we use the Order Independent Transparency render more?
411
   * <p>
412
   * There are two modes of rendering: the fast 'normal' way, which however renders transparent
413
   * fragments in different ways depending on which fragments get rendered first, or the slower
414
   * 'oit' way, which renders transparent fragments correctly regardless of their order.
415
   *
416
   * @param oit True if we want to render more slowly, but in a way which accounts for transparency.
417
   */
418
  public void setOrderIndependentTransparency(boolean oit)
419
    {
420
    mRenderWayOIT = oit;
421
    }
422
423 12f9e4bb Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
424
  /**
425
   * When rendering this Node, should we use the Order Independent Transparency render more?
426
   * <p>
427
   * There are two modes of rendering: the fast 'normal' way, which however renders transparent
428
   * fragments in different ways depending on which fragments get rendered first, or the slower
429
   * 'oit' way, which renders transparent fragments correctly regardless of their order.
430
   *
431
   * @param oit True if we want to render more slowly, but in a way which accounts for transparency.
432
   * @param initialSize Initial number of transparent fragments we expect, in screenfulls.
433 f953bee0 Leszek Koltunski
   *                    I.e '1.0' means 'the scene we are going to render contains dialog_about 1 screen
434 12f9e4bb Leszek Koltunski
   *                    worth of transparent fragments'. Valid values: 0.0 &lt; initialSize &lt; 10.0
435
   *                    Even if you get this wrong, the library will detect that there are more
436
   *                    transparent fragments than it has space for and readjust its internal buffers,
437
   *                    but only after a few frames during which one will probably see missing objects.
438
   */
439
  public void setOrderIndependentTransparency(boolean oit, float initialSize)
440
    {
441
    mRenderWayOIT = oit;
442
443
    if( initialSize>0.0f && initialSize<10.0f )
444 7602a827 Leszek Koltunski
      DistortedLibrary.setSSBOSize(initialSize);
445 12f9e4bb Leszek Koltunski
    }
446
447 6a06a912 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
448
/**
449
 * Adds a new child to the last position in the list of our Node's children.
450 c204c69d leszek
 * <p>
451
 * We cannot do this mid-render - actual attachment will be done just before the next render, by the
452 7602a827 Leszek Koltunski
 * InternalMaster (by calling doWork())
453 c204c69d leszek
 *
454 6a06a912 Leszek Koltunski
 * @param node The new Node to add.
455
 */
456 c204c69d leszek
  public void attach(DistortedNode node)
457 6a06a912 Leszek Koltunski
    {
458 11845a9e Leszek Koltunski
    mChildren.attach(node);
459 6a06a912 Leszek Koltunski
    }
460 c204c69d leszek
461 6a06a912 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
462
/**
463
 * Adds a new child to the last position in the list of our Node's children.
464 c204c69d leszek
 * <p>
465
 * We cannot do this mid-render - actual attachment will be done just before the next render, by the
466 7602a827 Leszek Koltunski
 * InternalMaster (by calling doWork())
467 c204c69d leszek
 *
468 c5369f1b leszek
 * @param surface InputSurface to initialize our child Node with.
469 07d8ef09 Leszek Koltunski
 * @param effects DistortedEffects to initialize our child Node with.
470 715e7726 Leszek Koltunski
 * @param mesh MeshBase to initialize our child Node with.
471 6a06a912 Leszek Koltunski
 * @return the newly constructed child Node, or null if we couldn't allocate resources.
472
 */
473 7602a827 Leszek Koltunski
  public DistortedNode attach(InternalSurface surface, DistortedEffects effects, MeshBase mesh)
474 6a06a912 Leszek Koltunski
    {
475 11845a9e Leszek Koltunski
    return mChildren.attach(surface,effects,mesh);
476 c204c69d leszek
    }
477 f8377ef8 leszek
478 6a06a912 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
479
/**
480
 * Removes the first occurrence of a specified child from the list of children of our Node.
481 c204c69d leszek
 * <p>
482
 * We cannot do this mid-render - actual detachment will be done just before the next render, by the
483 7602a827 Leszek Koltunski
 * InternalMaster (by calling doWork())
484 c204c69d leszek
 *
485 6a06a912 Leszek Koltunski
 * @param node The Node to remove.
486
 */
487 c204c69d leszek
  public void detach(DistortedNode node)
488 6a06a912 Leszek Koltunski
    {
489 11845a9e Leszek Koltunski
    mChildren.detach(node);
490 6a06a912 Leszek Koltunski
    }
491 a09ada4c Leszek Koltunski
492 6a06a912 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
493
/**
494
 * Removes the first occurrence of a specified child from the list of children of our Node.
495 a09ada4c Leszek Koltunski
 * <p>
496
 * A bit questionable method as there can be many different Nodes attached as children, some
497
 * of them having the same Effects but - for instance - different Mesh. Use with care.
498 c204c69d leszek
 * <p>
499
 * We cannot do this mid-render - actual detachment will be done just before the next render, by the
500 7602a827 Leszek Koltunski
 * InternalMaster (by calling doWork())
501 a09ada4c Leszek Koltunski
 *
502 07d8ef09 Leszek Koltunski
 * @param effects DistortedEffects to remove.
503 6a06a912 Leszek Koltunski
 */
504 c204c69d leszek
  public void detach(DistortedEffects effects)
505 6a06a912 Leszek Koltunski
    {
506 11845a9e Leszek Koltunski
    mChildren.detach(effects);
507 c204c69d leszek
    }
508
509
///////////////////////////////////////////////////////////////////////////////////////////////////
510
/**
511
 * Removes all children Nodes.
512
 * <p>
513
 * We cannot do this mid-render - actual detachment will be done just before the next render, by the
514 7602a827 Leszek Koltunski
 * InternalMaster (by calling doWork())
515 c204c69d leszek
 */
516
  public void detachAll()
517
    {
518 11845a9e Leszek Koltunski
    mChildren.detachAll();
519 6a06a912 Leszek Koltunski
    }
520 13687207 leszek
521 27f42cd6 leszek
///////////////////////////////////////////////////////////////////////////////////////////////////
522 6a06a912 Leszek Koltunski
/**
523 421c2728 Leszek Koltunski
 * Returns the DistortedEffects object that's in the Node.
524 6a06a912 Leszek Koltunski
 * 
525 421c2728 Leszek Koltunski
 * @return The DistortedEffects contained in the Node.
526 6a06a912 Leszek Koltunski
 */
527 421c2728 Leszek Koltunski
  public DistortedEffects getEffects()
528 6a06a912 Leszek Koltunski
    {
529 07d8ef09 Leszek Koltunski
    return mEffects;
530 4e2382f3 Leszek Koltunski
    }
531
532 a13dde77 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
533
  /**
534 eddf0cb7 Leszek Koltunski
   * Returns the surface this object gets rendered to.
535 a13dde77 Leszek Koltunski
   *
536 7602a827 Leszek Koltunski
   * @return The InternalSurface contained in the Node (if a leaf), or the FBO (if an internal Node)
537 a13dde77 Leszek Koltunski
   */
538 eddf0cb7 Leszek Koltunski
  public InternalSurface getSurface()
539 a13dde77 Leszek Koltunski
    {
540 11845a9e Leszek Koltunski
    return mChildren.getNumChildren()==0 ? mSurface : mData.mFBO;
541 a13dde77 Leszek Koltunski
    }
542
543 f1a82766 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
544
/**
545
 * Returns the Mesh object that's in the Node.
546
 *
547
 * @return Mesh contained in the Node.
548
 */
549 715e7726 Leszek Koltunski
  public MeshBase getMesh()
550 f1a82766 Leszek Koltunski
    {
551
    return mMesh;
552
    }
553
554 8c327653 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
555
/**
556 23eecbd9 Leszek Koltunski
 * Resizes the DistortedFramebuffer object that we render this Node to.
557 8c327653 Leszek Koltunski
 */
558 9ecac8cd Leszek Koltunski
  public void resizeFBO(int width, int height)
559 8c327653 Leszek Koltunski
    {
560 23eecbd9 Leszek Koltunski
    mFboW = width;
561
    mFboH = height;
562
563
    if ( mData.mFBO !=null )
564
      {
565
      // TODO: potentially allocate a new NodeData if we have to
566
      mData.mFBO.resize(width,height);
567
      }
568
    }
569
570 209ea1c7 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
571
/**
572
 * Set Projection Matrix for the Framebuffer contained in this Node.
573
 * <p>
574
 * If this Node is a Leaf and has no Framebuffer in it, this call does nothing.
575
 *
576
 * @param fov Vertical 'field of view' of the Projection frustrum (in degrees).
577
 *            Valid values: 0<=fov<180. FOV==0 means 'parallel projection'.
578
 * @param near The Near plane.
579
 */
580
  public void setProjection(float fov, float near)
581
    {
582
    if( fov < 180.0f && fov >=0.0f )
583
      {
584
      mFOV = fov;
585
      }
586
587
    if( near<   1.0f && near> 0.0f )
588
      {
589
      mNear= near;
590
      }
591
    else if( near<=0.0f )
592
      {
593
      mNear = 0.01f;
594
      }
595
    else if( near>=1.0f )
596
      {
597
      mNear=0.99f;
598
      }
599
600
    if( mData.mFBO!=null )
601
      {
602
      mData.mFBO.setProjection(mFOV,mNear);
603
      }
604
    }
605
606 23eecbd9 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
607
/**
608
 * Enables/disables DEPTH and STENCIL buffers in the Framebuffer object that we render this Node to.
609
 */
610
  public void enableDepthStencil(int depthStencil)
611
    {
612
    mFboDepthStencil = depthStencil;
613
614
    if ( mData.mFBO !=null )
615
      {
616
      // TODO: potentially allocate a new NodeData if we have to
617
      mData.mFBO.enableDepthStencil(depthStencil);
618
      }
619 8c327653 Leszek Koltunski
    }
620 6a06a912 Leszek Koltunski
621 ad16ed3b Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
622
// APIs that control how to set the OpenGL state just before rendering this Node.
623 c834348d leszek
///////////////////////////////////////////////////////////////////////////////////////////////////
624
/**
625
 * When rendering this Node, use ColorMask (r,g,b,a).
626
 *
627
 * @param r Write to the RED color channel when rendering this Node?
628
 * @param g Write to the GREEN color channel when rendering this Node?
629
 * @param b Write to the BLUE color channel when rendering this Node?
630
 * @param a Write to the ALPHA channel when rendering this Node?
631
 */
632 13687207 leszek
  @SuppressWarnings("unused")
633 c834348d leszek
  public void glColorMask(boolean r, boolean g, boolean b, boolean a)
634
    {
635
    mState.glColorMask(r,g,b,a);
636
    }
637
638
///////////////////////////////////////////////////////////////////////////////////////////////////
639
/**
640
 * When rendering this Node, switch on writing to Depth buffer?
641
 *
642
 * @param mask Write to the Depth buffer when rendering this Node?
643
 */
644 13687207 leszek
  @SuppressWarnings("unused")
645 c834348d leszek
  public void glDepthMask(boolean mask)
646
    {
647
    mState.glDepthMask(mask);
648
    }
649
650
///////////////////////////////////////////////////////////////////////////////////////////////////
651
/**
652
 * When rendering this Node, which bits of the Stencil buffer to write to?
653
 *
654
 * @param mask Marks the bits of the Stencil buffer we will write to when rendering this Node.
655
 */
656 13687207 leszek
  @SuppressWarnings("unused")
657 c834348d leszek
  public void glStencilMask(int mask)
658
    {
659
    mState.glStencilMask(mask);
660
    }
661
662
///////////////////////////////////////////////////////////////////////////////////////////////////
663
/**
664
 * When rendering this Node, which Tests to enable?
665
 *
666
 * @param test Valid values: GL_DEPTH_TEST, GL_STENCIL_TEST, GL_BLEND
667
 */
668 13687207 leszek
  @SuppressWarnings("unused")
669 c834348d leszek
  public void glEnable(int test)
670
    {
671
    mState.glEnable(test);
672
    }
673
674
///////////////////////////////////////////////////////////////////////////////////////////////////
675
/**
676
 * When rendering this Node, which Tests to enable?
677
 *
678
 * @param test Valid values: GL_DEPTH_TEST, GL_STENCIL_TEST, GL_BLEND
679
 */
680 13687207 leszek
  @SuppressWarnings("unused")
681 c834348d leszek
  public void glDisable(int test)
682
    {
683
    mState.glDisable(test);
684
    }
685
686
///////////////////////////////////////////////////////////////////////////////////////////////////
687
/**
688
 * When rendering this Node, use the following StencilFunc.
689
 *
690
 * @param func Valid values: GL_NEVER, GL_ALWAYS, GL_LESS, GL_LEQUAL, GL_EQUAL, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL
691
 * @param ref  Reference valut to compare our stencil with.
692
 * @param mask Mask used when comparing.
693
 */
694 13687207 leszek
  @SuppressWarnings("unused")
695 c834348d leszek
  public void glStencilFunc(int func, int ref, int mask)
696
    {
697
    mState.glStencilFunc(func,ref,mask);
698
    }
699
700
///////////////////////////////////////////////////////////////////////////////////////////////////
701
/**
702
 * When rendering this Node, use the following StencilOp.
703
 * <p>
704
 * Valid values of all 3 parameters: GL_KEEP, GL_ZERO, GL_REPLACE, GL_INCR, GL_DECR, GL_INVERT, GL_INCR_WRAP, GL_DECR_WRAP
705
 *
706
 * @param sfail  What to do when Stencil Test fails.
707
 * @param dpfail What to do when Depth Test fails.
708
 * @param dppass What to do when Depth Test passes.
709
 */
710 13687207 leszek
  @SuppressWarnings("unused")
711 c834348d leszek
  public void glStencilOp(int sfail, int dpfail, int dppass)
712
    {
713
    mState.glStencilOp(sfail,dpfail,dppass);
714
    }
715
716
///////////////////////////////////////////////////////////////////////////////////////////////////
717
/**
718
 * When rendering this Node, use the following DepthFunc.
719
 *
720
 * @param func Valid values: GL_NEVER, GL_ALWAYS, GL_LESS, GL_LEQUAL, GL_EQUAL, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL
721
 */
722 13687207 leszek
  @SuppressWarnings("unused")
723 c834348d leszek
  public void glDepthFunc(int func)
724
    {
725
    mState.glDepthFunc(func);
726
    }
727
728
///////////////////////////////////////////////////////////////////////////////////////////////////
729
/**
730
 * When rendering this Node, use the following Blending mode.
731
 * <p>
732
 * Valid values: GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
733
 *               GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR,
734
 *               GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA, GL_SRC_ALPHA_SATURATE
735
 *
736
 * @param src Source Blend function
737
 * @param dst Destination Blend function
738
 */
739 13687207 leszek
  @SuppressWarnings("unused")
740 c834348d leszek
  public void glBlendFunc(int src, int dst)
741
    {
742
    mState.glBlendFunc(src,dst);
743
    }
744 ad16ed3b Leszek Koltunski
745
///////////////////////////////////////////////////////////////////////////////////////////////////
746
/**
747
 * Before rendering this Node, clear the following buffers.
748
 * <p>
749
 * Valid values: 0, or bitwise OR of one or more values from the set GL_COLOR_BUFFER_BIT,
750
 *               GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT.
751
 * Default: 0
752
 *
753
 * @param mask bitwise OR of BUFFER_BITs to clear.
754
 */
755
  @SuppressWarnings("unused")
756
  public void glClear(int mask)
757
    {
758
    mState.glClear(mask);
759
    }
760 8c327653 Leszek Koltunski
  }