Project

General

Profile

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

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

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