1 /* 2 * Copyright (c) 2009-2010 jMonkeyEngine 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 package jme3tools.optimize; 34 35 import com.jme3.bounding.BoundingBox; 36 import com.jme3.renderer.Camera; 37 import com.jme3.scene.Geometry; 38 import java.util.Set; 39 40 public class FastOctnode { 41 42 int offset; 43 int length; 44 FastOctnode child; 45 FastOctnode next; 46 47 private static final BoundingBox tempBox = new BoundingBox(); 48 49 public int getSide(){ 50 return ((offset & 0xE0000000) >> 29) & 0x7; 51 } 52 53 public void setSide(int side){ 54 offset &= 0x1FFFFFFF; 55 offset |= (side << 29); 56 } 57 58 public void setOffset(int offset){ 59 if (offset < 0 || offset > 20000000){ 60 throw new IllegalArgumentException(); 61 } 62 63 this.offset &= 0xE0000000; 64 this.offset |= offset; 65 } 66 67 public int getOffset(){ 68 return this.offset & 0x1FFFFFFF; 69 } 70 71 private void generateRenderSetNoCheck(Geometry[] globalGeomList, Set<Geometry> renderSet, Camera cam){ 72 if (length != 0){ 73 int start = getOffset(); 74 int end = start + length; 75 for (int i = start; i < end; i++){ 76 renderSet.add(globalGeomList[i]); 77 } 78 } 79 80 if (child == null) 81 return; 82 83 FastOctnode node = child; 84 while (node != null){ 85 node.generateRenderSetNoCheck(globalGeomList, renderSet, cam); 86 node = node.next; 87 } 88 } 89 90 private static void findChildBound(BoundingBox bbox, int side){ 91 float extent = bbox.getXExtent() * 0.5f; 92 bbox.getCenter().set(bbox.getCenter().x + extent * Octnode.extentMult[side].x, 93 bbox.getCenter().y + extent * Octnode.extentMult[side].y, 94 bbox.getCenter().z + extent * Octnode.extentMult[side].z); 95 bbox.setXExtent(extent); 96 bbox.setYExtent(extent); 97 bbox.setZExtent(extent); 98 } 99 100 public void generateRenderSet(Geometry[] globalGeomList, Set<Geometry> renderSet, Camera cam, BoundingBox parentBox, boolean isRoot){ 101 tempBox.setCenter(parentBox.getCenter()); 102 tempBox.setXExtent(parentBox.getXExtent()); 103 tempBox.setYExtent(parentBox.getYExtent()); 104 tempBox.setZExtent(parentBox.getZExtent()); 105 106 if (!isRoot){ 107 findChildBound(tempBox, getSide()); 108 } 109 110 tempBox.setCheckPlane(0); 111 cam.setPlaneState(0); 112 Camera.FrustumIntersect result = cam.contains(tempBox); 113 if (result != Camera.FrustumIntersect.Outside){ 114 if (length != 0){ 115 int start = getOffset(); 116 int end = start + length; 117 for (int i = start; i < end; i++){ 118 renderSet.add(globalGeomList[i]); 119 } 120 } 121 122 if (child == null) 123 return; 124 125 FastOctnode node = child; 126 127 float x = tempBox.getCenter().x; 128 float y = tempBox.getCenter().y; 129 float z = tempBox.getCenter().z; 130 float ext = tempBox.getXExtent(); 131 132 while (node != null){ 133 if (result == Camera.FrustumIntersect.Inside){ 134 node.generateRenderSetNoCheck(globalGeomList, renderSet, cam); 135 }else{ 136 node.generateRenderSet(globalGeomList, renderSet, cam, tempBox, false); 137 } 138 139 tempBox.getCenter().set(x,y,z); 140 tempBox.setXExtent(ext); 141 tempBox.setYExtent(ext); 142 tempBox.setZExtent(ext); 143 144 node = node.next; 145 } 146 } 147 } 148 149 @Override 150 public String toString(){ 151 return "OCTNode[O=" + getOffset() + ", L=" + length + 152 ", S=" + getSide() + "]"; 153 } 154 155 public String toStringVerbose(int indent){ 156 String str = "------------------".substring(0,indent) + toString() + "\n"; 157 if (child == null) 158 return str; 159 160 FastOctnode children = child; 161 while (children != null){ 162 str += children.toStringVerbose(indent+1); 163 children = children.next; 164 } 165 166 return str; 167 } 168 169 } 170