git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@10406 75d07b2b-3a1a-0410-a2c5-0572b91ccdca3.0
parent
fe20cbb55f
commit
e100931c1f
@ -0,0 +1,483 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2012 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
package jme3test.games; |
||||||
|
|
||||||
|
import com.jme3.app.Application; |
||||||
|
import com.jme3.app.SimpleApplication; |
||||||
|
import com.jme3.app.state.AbstractAppState; |
||||||
|
import com.jme3.app.state.AppStateManager; |
||||||
|
import com.jme3.bullet.BulletAppState; |
||||||
|
import com.jme3.bullet.collision.shapes.CollisionShape; |
||||||
|
import com.jme3.bullet.collision.shapes.MeshCollisionShape; |
||||||
|
import com.jme3.bullet.collision.shapes.SphereCollisionShape; |
||||||
|
import com.jme3.bullet.control.RigidBodyControl; |
||||||
|
import com.jme3.bullet.debug.DebugTools; |
||||||
|
import com.jme3.input.KeyInput; |
||||||
|
import com.jme3.input.controls.AnalogListener; |
||||||
|
import com.jme3.input.controls.KeyTrigger; |
||||||
|
import com.jme3.material.Material; |
||||||
|
import com.jme3.math.ColorRGBA; |
||||||
|
import com.jme3.math.FastMath; |
||||||
|
import com.jme3.math.Ray; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.scene.Geometry; |
||||||
|
import com.jme3.scene.Mesh; |
||||||
|
import com.jme3.scene.Node; |
||||||
|
import com.jme3.scene.Spatial; |
||||||
|
import com.jme3.scene.shape.Sphere; |
||||||
|
import java.util.Random; |
||||||
|
import java.util.logging.Level; |
||||||
|
import java.util.logging.Logger; |
||||||
|
|
||||||
|
/** |
||||||
|
* WorldOfInception - Find the galaxy center ;) |
||||||
|
* |
||||||
|
* @author normenhansen |
||||||
|
*/ |
||||||
|
public class WorldOfInception extends SimpleApplication implements AnalogListener { |
||||||
|
|
||||||
|
//Assumptions: POI radius in world == 1, only one player, vector3f hash describes enough worlds
|
||||||
|
private static final Logger logger = Logger.getLogger(WorldOfInception.class.getName()); |
||||||
|
private static final Random random = new Random(System.currentTimeMillis()); |
||||||
|
private static final float scaleDist = 10; |
||||||
|
private static final float poiRadius = 100; |
||||||
|
private static final int poiCount = 30; |
||||||
|
private static Material poiMaterial; |
||||||
|
private static Mesh poiMesh; |
||||||
|
private static Material ballMaterial; |
||||||
|
private static Mesh ballMesh; |
||||||
|
private static CollisionShape poiHorizonCollisionShape; |
||||||
|
private static CollisionShape poiCollisionShape; |
||||||
|
private static CollisionShape ballCollisionShape; |
||||||
|
private InceptionLevel currentLevel; |
||||||
|
private final Vector3f walkDirection = new Vector3f(); |
||||||
|
private static DebugTools debugTools; |
||||||
|
|
||||||
|
public WorldOfInception() { |
||||||
|
//base level vector position hash == seed
|
||||||
|
super(new InceptionLevel(null, Vector3f.ZERO)); |
||||||
|
currentLevel = super.getStateManager().getState(InceptionLevel.class); |
||||||
|
currentLevel.takeOverParent(); |
||||||
|
currentLevel.getRootNode().setLocalScale(Vector3f.UNIT_XYZ); |
||||||
|
currentLevel.getRootNode().setLocalTranslation(Vector3f.ZERO); |
||||||
|
} |
||||||
|
|
||||||
|
public static void main(String[] args) { |
||||||
|
WorldOfInception app = new WorldOfInception(); |
||||||
|
app.start(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void simpleInitApp() { |
||||||
|
//set far frustum only so we see the outer world longer
|
||||||
|
cam.setFrustumFar(10000); |
||||||
|
cam.setLocation(Vector3f.ZERO); |
||||||
|
debugTools = new DebugTools(assetManager); |
||||||
|
rootNode.attachChild(debugTools.debugNode); |
||||||
|
poiMaterial = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); |
||||||
|
poiMaterial.setTexture("ColorMap", assetManager.loadTexture("Interface/Logo/Monkey.jpg")); |
||||||
|
poiMesh = new Sphere(16, 16, 1f); |
||||||
|
|
||||||
|
ballMaterial = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); |
||||||
|
ballMaterial.setTexture("ColorMap", assetManager.loadTexture("Interface/Logo/Monkey.jpg")); |
||||||
|
ballMaterial.setColor("Color", ColorRGBA.Red); |
||||||
|
ballMesh = new Sphere(16, 16, 1.0f); |
||||||
|
|
||||||
|
poiHorizonCollisionShape = new MeshCollisionShape(new Sphere(128, 128, poiRadius)); |
||||||
|
poiCollisionShape = new SphereCollisionShape(1f); |
||||||
|
ballCollisionShape = new SphereCollisionShape(1f); |
||||||
|
setupKeys(); |
||||||
|
} |
||||||
|
|
||||||
|
private void setupKeys() { |
||||||
|
inputManager.addMapping("StrafeLeft", new KeyTrigger(KeyInput.KEY_A)); |
||||||
|
inputManager.addMapping("StrafeRight", new KeyTrigger(KeyInput.KEY_D)); |
||||||
|
inputManager.addMapping("Forward", new KeyTrigger(KeyInput.KEY_W)); |
||||||
|
inputManager.addMapping("Back", new KeyTrigger(KeyInput.KEY_S)); |
||||||
|
inputManager.addMapping("StrafeUp", new KeyTrigger(KeyInput.KEY_Q)); |
||||||
|
inputManager.addMapping("StrafeDown", new KeyTrigger(KeyInput.KEY_Z), new KeyTrigger(KeyInput.KEY_Y)); |
||||||
|
inputManager.addMapping("Space", new KeyTrigger(KeyInput.KEY_SPACE)); |
||||||
|
inputManager.addMapping("Return", new KeyTrigger(KeyInput.KEY_RETURN)); |
||||||
|
inputManager.addMapping("Esc", new KeyTrigger(KeyInput.KEY_ESCAPE)); |
||||||
|
inputManager.addMapping("Up", new KeyTrigger(KeyInput.KEY_UP)); |
||||||
|
inputManager.addMapping("Down", new KeyTrigger(KeyInput.KEY_DOWN)); |
||||||
|
inputManager.addMapping("Left", new KeyTrigger(KeyInput.KEY_LEFT)); |
||||||
|
inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_RIGHT)); |
||||||
|
inputManager.addListener(this, "StrafeLeft", "StrafeRight", "Forward", "Back", "StrafeUp", "StrafeDown", "Space", "Reset", "Esc", "Up", "Down", "Left", "Right"); |
||||||
|
} |
||||||
|
|
||||||
|
public void onAnalog(String name, float value, float tpf) { |
||||||
|
Vector3f left = rootNode.getLocalRotation().mult(Vector3f.UNIT_X.negate()); |
||||||
|
Vector3f forward = rootNode.getLocalRotation().mult(Vector3f.UNIT_Z.negate()); |
||||||
|
Vector3f up = rootNode.getLocalRotation().mult(Vector3f.UNIT_Y); |
||||||
|
//TODO: properly scale input based on current scaling level
|
||||||
|
tpf = tpf * (10 - (9.0f * currentLevel.getCurrentScaleAmount())); |
||||||
|
if (name.equals("StrafeLeft") && value > 0) { |
||||||
|
walkDirection.addLocal(left.mult(tpf)); |
||||||
|
} else if (name.equals("StrafeRight") && value > 0) { |
||||||
|
walkDirection.addLocal(left.negate().multLocal(tpf)); |
||||||
|
} else if (name.equals("Forward") && value > 0) { |
||||||
|
walkDirection.addLocal(forward.mult(tpf)); |
||||||
|
} else if (name.equals("Back") && value > 0) { |
||||||
|
walkDirection.addLocal(forward.negate().multLocal(tpf)); |
||||||
|
} else if (name.equals("StrafeUp") && value > 0) { |
||||||
|
walkDirection.addLocal(up.mult(tpf)); |
||||||
|
} else if (name.equals("StrafeDown") && value > 0) { |
||||||
|
walkDirection.addLocal(up.negate().multLocal(tpf)); |
||||||
|
} else if (name.equals("Up") && value > 0) { |
||||||
|
//TODO: rotate rootNode, needs to be global
|
||||||
|
} else if (name.equals("Down") && value > 0) { |
||||||
|
} else if (name.equals("Left") && value > 0) { |
||||||
|
} else if (name.equals("Right") && value > 0) { |
||||||
|
} else if (name.equals("Esc")) { |
||||||
|
stop(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void simpleUpdate(float tpf) { |
||||||
|
currentLevel = currentLevel.getCurrentLevel(); |
||||||
|
currentLevel.move(walkDirection); |
||||||
|
walkDirection.set(Vector3f.ZERO); |
||||||
|
} |
||||||
|
|
||||||
|
public static class InceptionLevel extends AbstractAppState { |
||||||
|
|
||||||
|
private final InceptionLevel parent; |
||||||
|
private final Vector3f inParentPosition; |
||||||
|
private SimpleApplication application; |
||||||
|
private BulletAppState physicsState; |
||||||
|
private Node rootNode; |
||||||
|
private Vector3f playerPos; |
||||||
|
private InceptionLevel currentActiveChild; |
||||||
|
private InceptionLevel currentReturnLevel; |
||||||
|
private float curScaleAmount = 0; |
||||||
|
|
||||||
|
public InceptionLevel(InceptionLevel parent, Vector3f inParentPosition) { |
||||||
|
this.parent = parent; |
||||||
|
this.inParentPosition = inParentPosition; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void update(float tpf) { |
||||||
|
super.update(tpf); |
||||||
|
if (currentReturnLevel != this) { |
||||||
|
return; |
||||||
|
} |
||||||
|
debugTools.setYellowArrow(new Vector3f(0, 0, -2), playerPos.divide(poiRadius)); |
||||||
|
float curLocalDist = getPlayerPosition().length(); |
||||||
|
// If we are outside the range of one point of interest, move out to
|
||||||
|
// the next upper level
|
||||||
|
if (curLocalDist > poiRadius + FastMath.ZERO_TOLERANCE) { //DAFUQ normalize?
|
||||||
|
if (parent == null) { |
||||||
|
//TODO: could add new nodes coming in instead for literally endless space
|
||||||
|
logger.log(Level.INFO, "Hit event horizon"); |
||||||
|
currentReturnLevel = this; |
||||||
|
return; |
||||||
|
} |
||||||
|
//give to parent
|
||||||
|
logger.log(Level.INFO, "give to parent");; |
||||||
|
parent.takeOverChild(inParentPosition.add(playerPos.normalize())); |
||||||
|
application.getStateManager().attach(parent); |
||||||
|
currentReturnLevel = parent; |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
AppStateManager stateManager = application.getStateManager(); |
||||||
|
// We create child positions based on the parent position hash so we
|
||||||
|
// should in practice get the same galaxy w/o too many doubles
|
||||||
|
// with each run with the same root vector.
|
||||||
|
Vector3f[] vectors = getPositions(poiCount, inParentPosition.hashCode()); |
||||||
|
for (int i = 0; i < vectors.length; i++) { |
||||||
|
Vector3f vector3f = vectors[i]; |
||||||
|
//negative rootNode location is our actual player position
|
||||||
|
Vector3f distVect = vector3f.subtract(playerPos); |
||||||
|
float distance = distVect.length(); |
||||||
|
if (distance <= 1) { |
||||||
|
checkActiveChild(vector3f); |
||||||
|
float percent = 0; |
||||||
|
curScaleAmount = 0; |
||||||
|
this.scaleAsParent(percent, playerPos, distVect); |
||||||
|
currentActiveChild.scaleAsChild(percent, distVect); |
||||||
|
logger.log(Level.INFO, "Give over to child {0}", currentActiveChild); |
||||||
|
currentActiveChild.takeOverParent(); |
||||||
|
stateManager.detach(this); |
||||||
|
currentReturnLevel = currentActiveChild; |
||||||
|
return; |
||||||
|
} else if (distance <= 1 + scaleDist) { |
||||||
|
debugTools.setRedArrow(Vector3f.ZERO, distVect); |
||||||
|
checkActiveChild(vector3f); |
||||||
|
//TODO: scale percent nicer for less of an "explosion" effect
|
||||||
|
float percent = 1 - mapValue(distance - 1, 0, scaleDist, 0, 1); |
||||||
|
curScaleAmount = percent; |
||||||
|
rootNode.getChild(i).setCullHint(Spatial.CullHint.Always); |
||||||
|
this.scaleAsParent(percent, playerPos, distVect); |
||||||
|
currentActiveChild.scaleAsChild(percent, distVect); |
||||||
|
currentReturnLevel = this; |
||||||
|
return; |
||||||
|
} else if (currentActiveChild != null && currentActiveChild.getPositionInParent().equals(vector3f)) { |
||||||
|
//TODO: doing this here causes problems when close to multiple pois
|
||||||
|
logger.log(Level.INFO, "Detach child {0}", currentActiveChild); |
||||||
|
rootNode.getChild(i).setCullHint(Spatial.CullHint.Inherit); |
||||||
|
stateManager.detach(currentActiveChild); |
||||||
|
currentActiveChild = null; |
||||||
|
} |
||||||
|
} |
||||||
|
curScaleAmount = 0; |
||||||
|
rootNode.setLocalScale(1); |
||||||
|
rootNode.setLocalTranslation(playerPos.negate()); |
||||||
|
debugTools.setRedArrow(Vector3f.ZERO, Vector3f.ZERO); |
||||||
|
debugTools.setBlueArrow(Vector3f.ZERO, Vector3f.ZERO); |
||||||
|
debugTools.setGreenArrow(Vector3f.ZERO, Vector3f.ZERO); |
||||||
|
} |
||||||
|
|
||||||
|
private void checkActiveChild(Vector3f vector3f) { |
||||||
|
AppStateManager stateManager = application.getStateManager(); |
||||||
|
if (currentActiveChild == null) { |
||||||
|
currentActiveChild = new InceptionLevel(this, vector3f); |
||||||
|
stateManager.attach(currentActiveChild); |
||||||
|
logger.log(Level.INFO, "Attach child {0}", currentActiveChild); |
||||||
|
} else if (!currentActiveChild.getPositionInParent().equals(vector3f)) { |
||||||
|
logger.log(Level.INFO, "Switching from child {0}", currentActiveChild); |
||||||
|
stateManager.detach(currentActiveChild); |
||||||
|
currentActiveChild = new InceptionLevel(this, vector3f); |
||||||
|
stateManager.attach(currentActiveChild); |
||||||
|
logger.log(Level.INFO, "Attach child {0}", currentActiveChild); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static float linear2decibel(float x) { |
||||||
|
return (float) (20.0 * Math.log(x) / Math.log(10)); |
||||||
|
} |
||||||
|
|
||||||
|
public static float decibel2linear(float x) { |
||||||
|
return (float) Math.pow(10.0, x / 20.0); |
||||||
|
} |
||||||
|
|
||||||
|
private void scaleAsChild(float percent, Vector3f dist) { |
||||||
|
float childScale = mapValue(percent, 1.0f / poiRadius, 1); |
||||||
|
Vector3f distToHorizon = dist.normalize(); |
||||||
|
Vector3f scaledDistToHorizon = distToHorizon.mult(childScale * poiRadius); |
||||||
|
Vector3f rootOff = dist.add(scaledDistToHorizon); |
||||||
|
debugTools.setBlueArrow(Vector3f.ZERO, rootOff); |
||||||
|
getRootNode().setLocalScale(childScale); |
||||||
|
getRootNode().setLocalTranslation(rootOff); |
||||||
|
//prepare player position already
|
||||||
|
Vector3f playerPosition = dist.normalize().mult(-poiRadius); |
||||||
|
setPlayerPosition(playerPosition); |
||||||
|
} |
||||||
|
|
||||||
|
private void scaleAsParent(float percent, Vector3f playerPos, Vector3f dist) { |
||||||
|
float scale = mapValue(percent, 1.0f, poiRadius); |
||||||
|
Vector3f distToHorizon = dist.subtract(dist.normalize()); |
||||||
|
Vector3f offLocation = playerPos.add(distToHorizon); |
||||||
|
Vector3f rootOff = offLocation.mult(scale).negate(); |
||||||
|
rootOff.addLocal(dist); |
||||||
|
debugTools.setGreenArrow(Vector3f.ZERO, offLocation); |
||||||
|
getRootNode().setLocalScale(scale); |
||||||
|
getRootNode().setLocalTranslation(rootOff); |
||||||
|
} |
||||||
|
|
||||||
|
public void takeOverParent() { |
||||||
|
//got playerPos from scaleAsChild before
|
||||||
|
getPlayerPosition().normalizeLocal().multLocal(poiRadius); |
||||||
|
currentReturnLevel = this; |
||||||
|
} |
||||||
|
|
||||||
|
public void takeOverChild(Vector3f playerPos) { |
||||||
|
this.playerPos.set(playerPos); |
||||||
|
currentReturnLevel = this; |
||||||
|
} |
||||||
|
|
||||||
|
public InceptionLevel getLastLevel(Ray pickRay) { |
||||||
|
// TODO: get a level based on positions getting ever more accurate,
|
||||||
|
// from any given position
|
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
private void initData() { |
||||||
|
getRootNode(); |
||||||
|
physicsState = new BulletAppState(); |
||||||
|
physicsState.startPhysics(); |
||||||
|
physicsState.getPhysicsSpace().setGravity(Vector3f.ZERO); |
||||||
|
//horizon
|
||||||
|
physicsState.getPhysicsSpace().add(new RigidBodyControl(poiHorizonCollisionShape, 0)); |
||||||
|
int hashCode = inParentPosition.hashCode(); |
||||||
|
Vector3f[] positions = getPositions(poiCount, hashCode); |
||||||
|
for (int i = 0; i < positions.length; i++) { |
||||||
|
Vector3f vector3f = positions[i]; |
||||||
|
Geometry poiGeom = new Geometry("poi", poiMesh); |
||||||
|
poiGeom.setLocalTranslation(vector3f); |
||||||
|
poiGeom.setMaterial(poiMaterial); |
||||||
|
RigidBodyControl control = new RigidBodyControl(poiCollisionShape, 0); |
||||||
|
//!!! Important
|
||||||
|
control.setApplyPhysicsLocal(true); |
||||||
|
poiGeom.addControl(control); |
||||||
|
physicsState.getPhysicsSpace().add(poiGeom); |
||||||
|
rootNode.attachChild(poiGeom); |
||||||
|
|
||||||
|
} |
||||||
|
//add balls after so first 10 geoms == locations
|
||||||
|
for (int i = 0; i < positions.length; i++) { |
||||||
|
Vector3f vector3f = positions[i]; |
||||||
|
Geometry ball = getRandomBall(vector3f); |
||||||
|
physicsState.getPhysicsSpace().add(ball); |
||||||
|
rootNode.attachChild(ball); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private Geometry getRandomBall(Vector3f location) { |
||||||
|
Vector3f localLocation = new Vector3f(); |
||||||
|
localLocation.set(location); |
||||||
|
localLocation.addLocal(new Vector3f(random.nextFloat() - 0.5f, random.nextFloat() - 0.5f, random.nextFloat() - 0.5f).normalize().mult(3)); |
||||||
|
Geometry poiGeom = new Geometry("ball", ballMesh); |
||||||
|
poiGeom.setLocalTranslation(localLocation); |
||||||
|
poiGeom.setMaterial(ballMaterial); |
||||||
|
RigidBodyControl control = new RigidBodyControl(ballCollisionShape, 1); |
||||||
|
//!!! Important
|
||||||
|
control.setApplyPhysicsLocal(true); |
||||||
|
poiGeom.addControl(control); |
||||||
|
float x = (random.nextFloat() - 0.5f) * 100; |
||||||
|
float y = (random.nextFloat() - 0.5f) * 100; |
||||||
|
float z = (random.nextFloat() - 0.5f) * 100; |
||||||
|
control.setLinearVelocity(new Vector3f(x, y, z)); |
||||||
|
return poiGeom; |
||||||
|
} |
||||||
|
|
||||||
|
private void cleanupData() { |
||||||
|
physicsState.cleanup(); |
||||||
|
//TODO: remove all objects?
|
||||||
|
physicsState = null; |
||||||
|
rootNode = null; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void initialize(AppStateManager stateManager, Application app) { |
||||||
|
super.initialize(stateManager, app); |
||||||
|
//only generate data and attach node when we are actually attached (or picking)
|
||||||
|
initData(); |
||||||
|
application = (SimpleApplication) app; |
||||||
|
application.getRootNode().attachChild(getRootNode()); |
||||||
|
application.getStateManager().attach(physicsState); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void cleanup() { |
||||||
|
super.cleanup(); |
||||||
|
//detach everything when we are detached
|
||||||
|
application.getRootNode().detachChild(rootNode); |
||||||
|
application.getStateManager().detach(physicsState); |
||||||
|
cleanupData(); |
||||||
|
} |
||||||
|
|
||||||
|
public Node getRootNode() { |
||||||
|
if (rootNode == null) { |
||||||
|
rootNode = new Node("ZoomLevel"); |
||||||
|
if (parent != null) { |
||||||
|
rootNode.setLocalScale(1.0f / poiRadius); |
||||||
|
} |
||||||
|
} |
||||||
|
return rootNode; |
||||||
|
} |
||||||
|
|
||||||
|
public Vector3f getPositionInParent() { |
||||||
|
return inParentPosition; |
||||||
|
} |
||||||
|
|
||||||
|
public Vector3f getPlayerPosition() { |
||||||
|
if (playerPos == null) { |
||||||
|
playerPos = new Vector3f(); |
||||||
|
} |
||||||
|
return playerPos; |
||||||
|
} |
||||||
|
|
||||||
|
public void setPlayerPosition(Vector3f vec) { |
||||||
|
if (playerPos == null) { |
||||||
|
playerPos = new Vector3f(); |
||||||
|
} |
||||||
|
playerPos.set(vec); |
||||||
|
} |
||||||
|
|
||||||
|
public void move(Vector3f dir) { |
||||||
|
if (playerPos == null) { |
||||||
|
playerPos = new Vector3f(); |
||||||
|
} |
||||||
|
playerPos.addLocal(dir); |
||||||
|
} |
||||||
|
|
||||||
|
public float getCurrentScaleAmount() { |
||||||
|
return curScaleAmount; |
||||||
|
} |
||||||
|
|
||||||
|
public InceptionLevel getCurrentLevel() { |
||||||
|
return currentReturnLevel; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static Vector3f[] getPositions(int count, long seed) { |
||||||
|
Random rnd = new Random(seed); |
||||||
|
Vector3f[] vectors = new Vector3f[count]; |
||||||
|
for (int i = 0; i < count; i++) { |
||||||
|
vectors[i] = new Vector3f((rnd.nextFloat() - 0.5f) * poiRadius, |
||||||
|
(rnd.nextFloat() - 0.5f) * poiRadius, |
||||||
|
(rnd.nextFloat() - 0.5f) * poiRadius); |
||||||
|
} |
||||||
|
return vectors; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Maps a value from 0-1 to a range from min to max. |
||||||
|
* |
||||||
|
* @param x |
||||||
|
* @param min |
||||||
|
* @param max |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static float mapValue(float x, float min, float max) { |
||||||
|
return mapValue(x, 0, 1, min, max); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Maps a value from inputMin to inputMax to a range from min to max. |
||||||
|
* |
||||||
|
* @param x |
||||||
|
* @param inputMin |
||||||
|
* @param inputMax |
||||||
|
* @param min |
||||||
|
* @param max |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static float mapValue(float x, float inputMin, float inputMax, float min, float max) { |
||||||
|
return (x - inputMin) * (max - min) / (inputMax - inputMin) + min; |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue