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 com.jme3.terrain.geomipmap.lodcalc; 34 35 import com.jme3.export.JmeExporter; 36 import com.jme3.export.JmeImporter; 37 import com.jme3.math.FastMath; 38 import com.jme3.math.Vector3f; 39 import com.jme3.renderer.Camera; 40 import com.jme3.terrain.geomipmap.TerrainPatch; 41 import com.jme3.terrain.geomipmap.UpdatedTerrainPatch; 42 import java.io.IOException; 43 import java.util.HashMap; 44 import java.util.List; 45 46 public class PerspectiveLodCalculator implements LodCalculator { 47 48 private TerrainPatch patch; 49 private Camera cam; 50 private float[] entropyDistances; 51 private float pixelError; 52 PerspectiveLodCalculator()53 public PerspectiveLodCalculator() {} 54 PerspectiveLodCalculator(Camera cam, float pixelError)55 public PerspectiveLodCalculator(Camera cam, float pixelError){ 56 this.cam = cam; 57 this.pixelError = pixelError; 58 } 59 60 /** 61 * This computes the "C" value in the geomipmapping paper. 62 * See section "2.3.1.2 Pre-calculating d" 63 * 64 * @param cam 65 * @param pixelLimit 66 * @return 67 */ getCameraConstant(Camera cam, float pixelLimit)68 private float getCameraConstant(Camera cam, float pixelLimit){ 69 float n = cam.getFrustumNear(); 70 float t = FastMath.abs(cam.getFrustumTop()); 71 float A = n / t; 72 float v_res = cam.getHeight(); 73 float T = (2f * pixelLimit) / v_res; 74 return A / T; 75 } 76 calculateLod(List<Vector3f> locations, HashMap<String, UpdatedTerrainPatch> updates)77 public boolean calculateLod(List<Vector3f> locations, HashMap<String, UpdatedTerrainPatch> updates) { 78 return calculateLod(patch, locations, updates); 79 } 80 calculateLod(TerrainPatch terrainPatch, List<Vector3f> locations, HashMap<String, UpdatedTerrainPatch> updates)81 public boolean calculateLod(TerrainPatch terrainPatch, List<Vector3f> locations, HashMap<String, UpdatedTerrainPatch> updates) { 82 if (entropyDistances == null){ 83 // compute entropy distances 84 float[] lodEntropies = patch.getLodEntropies(); 85 entropyDistances = new float[lodEntropies.length]; 86 float cameraConstant = getCameraConstant(cam, pixelError); 87 for (int i = 0; i < lodEntropies.length; i++){ 88 entropyDistances[i] = lodEntropies[i] * cameraConstant; 89 } 90 } 91 92 Vector3f patchPos = getCenterLocation(patch); 93 94 // vector from camera to patch 95 //Vector3f toPatchDir = locations.get(0).subtract(patchPos).normalizeLocal(); 96 //float facing = cam.getDirection().dot(toPatchDir); 97 float distance = patchPos.distance(locations.get(0)); 98 99 // go through each lod level to find the one we are in 100 for (int i = 0; i <= patch.getMaxLod(); i++) { 101 if (distance < entropyDistances[i] || i == patch.getMaxLod()){ 102 boolean reIndexNeeded = false; 103 if (i != patch.getLod()) { 104 reIndexNeeded = true; 105 // System.out.println("lod change: "+lod+" > "+i+" dist: "+distance); 106 } 107 int prevLOD = patch.getLod(); 108 109 //previousLod = lod; 110 //lod = i; 111 UpdatedTerrainPatch utp = updates.get(patch.getName()); 112 if (utp == null) { 113 utp = new UpdatedTerrainPatch(patch, i);//save in here, do not update actual variables 114 updates.put(utp.getName(), utp); 115 } 116 utp.setPreviousLod(prevLOD); 117 utp.setReIndexNeeded(reIndexNeeded); 118 return reIndexNeeded; 119 } 120 } 121 122 return false; 123 } 124 getCenterLocation(TerrainPatch patch)125 public Vector3f getCenterLocation(TerrainPatch patch) { 126 Vector3f loc = patch.getWorldTranslation().clone(); 127 loc.x += patch.getSize() / 2; 128 loc.z += patch.getSize() / 2; 129 return loc; 130 } 131 132 @Override clone()133 public LodCalculator clone() { 134 try { 135 return (LodCalculator) super.clone(); 136 } catch (CloneNotSupportedException ex) { 137 throw new AssertionError(); 138 } 139 } 140 write(JmeExporter ex)141 public void write(JmeExporter ex) throws IOException { 142 } 143 read(JmeImporter im)144 public void read(JmeImporter im) throws IOException { 145 } 146 usesVariableLod()147 public boolean usesVariableLod() { 148 return true; 149 } 150 getPixelError()151 public float getPixelError() { 152 return pixelError; 153 } 154 setPixelError(float pixelError)155 public void setPixelError(float pixelError) { 156 this.pixelError = pixelError; 157 } 158 setCam(Camera cam)159 public void setCam(Camera cam) { 160 this.cam = cam; 161 } 162 turnOffLod()163 public void turnOffLod() { 164 //TODO 165 } 166 isLodOff()167 public boolean isLodOff() { 168 return false; //TODO 169 } 170 turnOnLod()171 public void turnOnLod() { 172 //TODO 173 } 174 175 } 176