* added terrain tool undo/redo support git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7718 75d07b2b-3a1a-0410-a2c5-0572b91ccdca3.0
parent
5024fa6c32
commit
e08dc6f6cf
@ -0,0 +1,105 @@ |
||||
/* |
||||
* Copyright (c) 2009-2011 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 com.jme3.gde.core.sceneexplorer.nodes.actions; |
||||
|
||||
import com.jme3.gde.core.scene.SceneApplication; |
||||
import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; |
||||
import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit; |
||||
import com.jme3.gde.core.undoredo.SceneUndoRedoManager; |
||||
import java.util.concurrent.Callable; |
||||
import javax.swing.undo.CannotRedoException; |
||||
import javax.swing.undo.CannotUndoException; |
||||
import org.openide.loaders.DataObject; |
||||
import org.openide.util.Lookup; |
||||
|
||||
/** |
||||
* Similar as AbstractToolAction but this one is executed from the GL thread. |
||||
* This is also allowed to be stateful. |
||||
* |
||||
* @author Brent Owens |
||||
*/ |
||||
public abstract class AbstractStatefulGLToolAction { |
||||
|
||||
protected String name = "*"; |
||||
|
||||
public void actionPerformed(final AbstractSceneExplorerNode rootNode, final DataObject dataObject) { |
||||
SceneApplication.getApplication().enqueue(new Callable<Void>() { |
||||
|
||||
public Void call() throws Exception { |
||||
doActionPerformed(rootNode, dataObject); |
||||
return null; |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public void doActionPerformed(final AbstractSceneExplorerNode rootNode, final DataObject dataObject) { |
||||
|
||||
final Object object = doApplyTool(rootNode); |
||||
if (object!=null) { |
||||
Lookup lookup = Lookup.getDefault() ; |
||||
SceneUndoRedoManager manager = lookup.lookup(SceneUndoRedoManager.class); |
||||
|
||||
AbstractUndoableSceneEdit undoer = new AbstractUndoableSceneEdit() { |
||||
|
||||
@Override |
||||
public void sceneUndo() throws CannotUndoException { |
||||
doUndoTool(rootNode,object); |
||||
setModified(rootNode, dataObject); |
||||
} |
||||
|
||||
@Override |
||||
public void sceneRedo() throws CannotRedoException { |
||||
doApplyTool(rootNode); |
||||
setModified(rootNode, dataObject); |
||||
} |
||||
|
||||
}; |
||||
manager.addEdit(this, undoer); |
||||
setModified(rootNode, dataObject); |
||||
} |
||||
|
||||
} |
||||
|
||||
protected void setModified(final AbstractSceneExplorerNode rootNode, final DataObject dataObject) { |
||||
java.awt.EventQueue.invokeLater(new Runnable() { |
||||
|
||||
public void run() { |
||||
dataObject.setModified(true); |
||||
rootNode.refresh(true); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
protected abstract Object doApplyTool(AbstractSceneExplorerNode rootNode); |
||||
|
||||
protected abstract void doUndoTool(AbstractSceneExplorerNode rootNode, Object undoObject); |
||||
} |
@ -0,0 +1,66 @@ |
||||
/* |
||||
* Copyright (c) 2009-2011 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 com.jme3.gde.terraineditor.tools; |
||||
|
||||
import com.jme3.gde.core.sceneexplorer.nodes.actions.AbstractStatefulGLToolAction; |
||||
import com.jme3.scene.Node; |
||||
import com.jme3.scene.Spatial; |
||||
import com.jme3.terrain.Terrain; |
||||
|
||||
/** |
||||
* Helps find the terrain in the scene |
||||
* @author Brent Owens |
||||
*/ |
||||
public abstract class AbstractTerrainToolAction extends AbstractStatefulGLToolAction { |
||||
|
||||
protected Terrain getTerrain(Spatial root) { |
||||
|
||||
// is this the terrain?
|
||||
if (root instanceof Terrain && root instanceof Node) { |
||||
return (Terrain)root; |
||||
} |
||||
|
||||
if (root instanceof Node) { |
||||
Node n = (Node) root; |
||||
for (Spatial c : n.getChildren()) { |
||||
if (c instanceof Node){ |
||||
Terrain res = getTerrain(c); |
||||
if (res != null) |
||||
return res; |
||||
} |
||||
} |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
} |
@ -0,0 +1,65 @@ |
||||
/* |
||||
* Copyright (c) 2009-2011 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 com.jme3.gde.terraineditor.tools; |
||||
|
||||
import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; |
||||
import com.jme3.math.ColorRGBA; |
||||
import com.jme3.math.Vector3f; |
||||
import com.jme3.scene.Node; |
||||
import org.openide.loaders.DataObject; |
||||
|
||||
/** |
||||
* Erase the texture on the terrain |
||||
* |
||||
* @author Brent Owens |
||||
*/ |
||||
public class EraseTerrainTool extends TerrainTool { |
||||
|
||||
@Override |
||||
public void actionPrimary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject) { |
||||
if (radius == 0 || weight == 0) |
||||
return; |
||||
PaintTerrainToolAction action = new PaintTerrainToolAction(point, radius, -weight, textureIndex); // negate the weight
|
||||
action.doActionPerformed(rootNode, dataObject); |
||||
} |
||||
|
||||
@Override |
||||
public void actionSecondary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject) { |
||||
// do nothing
|
||||
} |
||||
|
||||
@Override |
||||
public void addMarkerPrimary(Node parent) { |
||||
super.addMarkerPrimary(parent); |
||||
markerPrimary.getMaterial().setColor("Color", ColorRGBA.Cyan); |
||||
} |
||||
} |
@ -0,0 +1,84 @@ |
||||
/* |
||||
* Copyright (c) 2009-2011 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 com.jme3.gde.terraineditor.tools; |
||||
|
||||
import com.jme3.asset.AssetManager; |
||||
import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; |
||||
import com.jme3.math.ColorRGBA; |
||||
import com.jme3.math.Vector3f; |
||||
import com.jme3.scene.Node; |
||||
import org.openide.loaders.DataObject; |
||||
|
||||
/** |
||||
* Level the terrain. Uses a desired height point set by the secondary |
||||
* action (right mouse button) and raises/lowers the terrain to that |
||||
* desired height. |
||||
* |
||||
* @author Brent Owens |
||||
*/ |
||||
public class LevelTerrainTool extends TerrainTool { |
||||
|
||||
private Vector3f desiredHeight; |
||||
|
||||
|
||||
public LevelTerrainTool() { |
||||
toolHintTextKey = "TerrainEditorTopComponent.toolHint.level"; |
||||
} |
||||
|
||||
@Override |
||||
public void activate(AssetManager manager, Node parent) { |
||||
super.activate(manager, parent); |
||||
addMarkerSecondary(parent); |
||||
} |
||||
|
||||
@Override |
||||
public void actionPrimary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject) { |
||||
if (radius == 0 || weight == 0) |
||||
return; |
||||
if (desiredHeight == null) |
||||
desiredHeight = point.clone(); |
||||
LevelTerrainToolAction action = new LevelTerrainToolAction(point, radius, weight, desiredHeight); |
||||
action.doActionPerformed(rootNode, dataObject); |
||||
} |
||||
|
||||
@Override |
||||
public void actionSecondary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject) { |
||||
desiredHeight = point; |
||||
markerSecondary.setLocalTranslation(desiredHeight); |
||||
} |
||||
|
||||
@Override |
||||
public void addMarkerPrimary(Node parent) { |
||||
super.addMarkerPrimary(parent); |
||||
markerPrimary.getMaterial().setColor("Color", ColorRGBA.Red); |
||||
} |
||||
} |
@ -0,0 +1,159 @@ |
||||
/* |
||||
* Copyright (c) 2009-2011 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 com.jme3.gde.terraineditor.tools; |
||||
|
||||
import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; |
||||
import com.jme3.math.Vector2f; |
||||
import com.jme3.math.Vector3f; |
||||
import com.jme3.scene.Node; |
||||
import com.jme3.terrain.Terrain; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Level the terrain to a desired height, executed from the OpenGL thread. |
||||
* It will pull down or raise terrain towards the desired height, still |
||||
* using the radius of the tool and the weight. There are some slight rounding |
||||
* errors that are corrected with float epsilon testing. |
||||
* |
||||
* @author Brent Owens |
||||
*/ |
||||
public class LevelTerrainToolAction extends AbstractTerrainToolAction { |
||||
|
||||
private Vector3f worldLoc; |
||||
private float radius; |
||||
private float height; |
||||
private Vector3f levelTerrainLocation; |
||||
|
||||
List<Vector2f> undoLocs; |
||||
List<Float> undoHeights; |
||||
|
||||
public LevelTerrainToolAction(Vector3f markerLocation, float radius, float height, Vector3f levelTerrainLocation) { |
||||
this.worldLoc = markerLocation.clone(); |
||||
this.radius = radius; |
||||
this.height = height; |
||||
this.levelTerrainLocation = levelTerrainLocation; |
||||
name = "Level terrain"; |
||||
} |
||||
|
||||
@Override |
||||
protected Object doApplyTool(AbstractSceneExplorerNode rootNode) { |
||||
Terrain terrain = getTerrain(rootNode.getLookup().lookup(Node.class)); |
||||
if (terrain == null) |
||||
return null; |
||||
modifyHeight(terrain, radius, height); |
||||
return terrain; |
||||
} |
||||
|
||||
@Override |
||||
protected void doUndoTool(AbstractSceneExplorerNode rootNode, Object undoObject) { |
||||
if (undoObject == null) |
||||
return; |
||||
if (undoLocs == null || undoHeights == null) |
||||
return; |
||||
resetHeight((Terrain)undoObject, undoLocs, undoHeights); |
||||
} |
||||
|
||||
private void modifyHeight(Terrain terrain, float radius, float height) { |
||||
if (levelTerrainLocation == null) |
||||
return; |
||||
|
||||
float desiredHeight = levelTerrainLocation.y; |
||||
|
||||
int radiusStepsX = (int)(radius / ((Node)terrain).getLocalScale().x); |
||||
int radiusStepsZ = (int)(radius / ((Node)terrain).getLocalScale().z); |
||||
|
||||
float xStepAmount = ((Node)terrain).getLocalScale().x; |
||||
float zStepAmount = ((Node)terrain).getLocalScale().z; |
||||
|
||||
List<Vector2f> locs = new ArrayList<Vector2f>(); |
||||
List<Float> heights = new ArrayList<Float>(); |
||||
|
||||
for (int z=-radiusStepsZ; z<radiusStepsZ; z++) { |
||||
for (int x=-radiusStepsZ; x<radiusStepsX; x++) { |
||||
|
||||
float locX = worldLoc.x + (x*xStepAmount); |
||||
float locZ = worldLoc.z + (z*zStepAmount); |
||||
|
||||
// see if it is in the radius of the tool
|
||||
if (ToolUtils.isInRadius(locX-worldLoc.x,locZ-worldLoc.z,radius)) { |
||||
|
||||
Vector2f terrainLoc = new Vector2f(locX, locZ); |
||||
// adjust height based on radius of the tool
|
||||
float terrainHeightAtLoc = terrain.getHeightmapHeight(terrainLoc)*terrain.getSpatial().getWorldScale().y; |
||||
float radiusWeight = ToolUtils.calculateRadiusPercent(radius, locX-worldLoc.x, locZ-worldLoc.z); |
||||
|
||||
float epsilon = 0.1f*height; // rounding error for snapping
|
||||
|
||||
float adj = 0; |
||||
if (terrainHeightAtLoc < desiredHeight) |
||||
adj = 1; |
||||
else if (terrainHeightAtLoc > desiredHeight) |
||||
adj = -1; |
||||
|
||||
adj *= radiusWeight * height; |
||||
|
||||
// test if adjusting too far and then cap it
|
||||
if (adj > 0 && ToolUtils.floatGreaterThan((terrainHeightAtLoc + adj), desiredHeight, epsilon)) |
||||
adj = desiredHeight - terrainHeightAtLoc; |
||||
else if (adj < 0 && ToolUtils.floatLessThan((terrainHeightAtLoc + adj), desiredHeight, epsilon)) |
||||
adj = terrainHeightAtLoc - desiredHeight; |
||||
|
||||
if (!ToolUtils.floatEquals(adj, 0, 0.001f)) { |
||||
locs.add(terrainLoc); |
||||
heights.add(adj); |
||||
} |
||||
|
||||
} |
||||
} |
||||
} |
||||
undoLocs = locs; |
||||
undoHeights = heights; |
||||
|
||||
// do the actual height adjustment
|
||||
terrain.adjustHeight(locs, heights); |
||||
|
||||
((Node)terrain).updateModelBound(); // or else we won't collide with it where we just edited
|
||||
|
||||
} |
||||
|
||||
|
||||
private void resetHeight(Terrain terrain, List<Vector2f> undoLocs, List<Float> undoHeights) { |
||||
List<Float> neg = new ArrayList<Float>(); |
||||
for (Float f : undoHeights) |
||||
neg.add( f * -1f ); |
||||
|
||||
terrain.adjustHeight(undoLocs, neg); |
||||
((Node)terrain).updateModelBound(); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,65 @@ |
||||
/* |
||||
* Copyright (c) 2009-2011 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 com.jme3.gde.terraineditor.tools; |
||||
|
||||
import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; |
||||
import com.jme3.math.ColorRGBA; |
||||
import com.jme3.math.Vector3f; |
||||
import com.jme3.scene.Node; |
||||
import org.openide.loaders.DataObject; |
||||
|
||||
/** |
||||
* Lowers the terrain |
||||
* |
||||
* @author Brent Owens |
||||
*/ |
||||
public class LowerTerrainTool extends TerrainTool { |
||||
|
||||
@Override |
||||
public void actionPrimary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject) { |
||||
if (radius == 0 || weight == 0) |
||||
return; |
||||
RaiseTerrainToolAction action = new RaiseTerrainToolAction(point, radius, -weight); // negative weight
|
||||
action.doActionPerformed(rootNode, dataObject); |
||||
} |
||||
|
||||
@Override |
||||
public void actionSecondary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject) { |
||||
// no secondary option
|
||||
} |
||||
|
||||
@Override |
||||
public void addMarkerPrimary(Node parent) { |
||||
super.addMarkerPrimary(parent); |
||||
markerPrimary.getMaterial().setColor("Color", ColorRGBA.Green); |
||||
} |
||||
} |
@ -0,0 +1,64 @@ |
||||
/* |
||||
* Copyright (c) 2009-2011 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 com.jme3.gde.terraineditor.tools; |
||||
|
||||
import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; |
||||
import com.jme3.math.ColorRGBA; |
||||
import com.jme3.math.Vector3f; |
||||
import com.jme3.scene.Node; |
||||
import org.openide.loaders.DataObject; |
||||
|
||||
/** |
||||
* |
||||
* @author Brent Owens |
||||
*/ |
||||
public class PaintTerrainTool extends TerrainTool { |
||||
|
||||
@Override |
||||
public void actionPrimary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject) { |
||||
if (radius == 0 || weight == 0) |
||||
return; |
||||
PaintTerrainToolAction action = new PaintTerrainToolAction(point, radius, weight, textureIndex); |
||||
action.doActionPerformed(rootNode, dataObject); |
||||
} |
||||
|
||||
@Override |
||||
public void actionSecondary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject) { |
||||
// do nothing
|
||||
} |
||||
|
||||
@Override |
||||
public void addMarkerPrimary(Node parent) { |
||||
super.addMarkerPrimary(parent); |
||||
markerPrimary.getMaterial().setColor("Color", ColorRGBA.Cyan); |
||||
} |
||||
} |
@ -0,0 +1,260 @@ |
||||
/* |
||||
* Copyright (c) 2009-2011 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 com.jme3.gde.terraineditor.tools; |
||||
|
||||
import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; |
||||
import com.jme3.material.MatParam; |
||||
import com.jme3.math.ColorRGBA; |
||||
import com.jme3.math.Vector2f; |
||||
import com.jme3.math.Vector3f; |
||||
import com.jme3.scene.Node; |
||||
import com.jme3.terrain.Terrain; |
||||
import com.jme3.terrain.geomipmap.TerrainQuad; |
||||
import com.jme3.texture.Image; |
||||
import com.jme3.texture.Texture; |
||||
import java.nio.ByteBuffer; |
||||
|
||||
/** |
||||
* Paint the texture at the specified location. |
||||
* |
||||
* @author Brent Owens |
||||
*/ |
||||
public class PaintTerrainToolAction extends AbstractTerrainToolAction { |
||||
|
||||
private Vector3f worldLoc; |
||||
private float radius; |
||||
private float weight; |
||||
private int selectedTextureIndex; |
||||
|
||||
public PaintTerrainToolAction(Vector3f markerLocation, float radius, float weight, int selectedTextureIndex) { |
||||
this.worldLoc = markerLocation.clone(); |
||||
this.radius = radius; |
||||
this.weight = weight; |
||||
this.selectedTextureIndex = selectedTextureIndex; |
||||
name = "Paint terrain"; |
||||
} |
||||
|
||||
@Override |
||||
protected Object doApplyTool(AbstractSceneExplorerNode rootNode) { |
||||
Terrain terrain = getTerrain(rootNode.getLookup().lookup(Node.class)); |
||||
if (terrain == null) |
||||
return null; |
||||
paintTexture(terrain, worldLoc, radius, weight, selectedTextureIndex); |
||||
return terrain; |
||||
} |
||||
|
||||
@Override |
||||
protected void doUndoTool(AbstractSceneExplorerNode rootNode, Object undoObject) { |
||||
if (undoObject == null) |
||||
return; |
||||
paintTexture((Terrain)undoObject, worldLoc, radius, -weight, selectedTextureIndex); |
||||
} |
||||
|
||||
public void paintTexture(Terrain terrain, Vector3f markerLocation, float toolRadius, float toolWeight, int selectedTextureIndex) { |
||||
if (selectedTextureIndex < 0 || markerLocation == null) |
||||
return; |
||||
|
||||
int alphaIdx = selectedTextureIndex/4; // 4 = rgba = 4 textures
|
||||
Texture tex = getAlphaTexture(terrain, alphaIdx); |
||||
Image image = tex.getImage(); |
||||
|
||||
Vector2f UV = terrain.getPointPercentagePosition(markerLocation.x, markerLocation.z); |
||||
|
||||
// get the radius of the brush in pixel-percent
|
||||
float brushSize = toolRadius/((TerrainQuad)terrain).getTotalSize(); |
||||
int texIndex = selectedTextureIndex - ((selectedTextureIndex/4)*4); // selectedTextureIndex/4 is an int floor, do not simplify the equation
|
||||
boolean erase = toolWeight<0; |
||||
if (erase) |
||||
toolWeight *= -1; |
||||
|
||||
doPaintAction(texIndex, image, UV, true, brushSize, erase, toolWeight); |
||||
|
||||
tex.getImage().setUpdateNeeded(); |
||||
} |
||||
|
||||
private Texture getAlphaTexture(Terrain terrain, int alphaLayer) { |
||||
if (terrain == null) |
||||
return null; |
||||
MatParam matParam = null; |
||||
if (alphaLayer == 0) |
||||
matParam = terrain.getMaterial().getParam("AlphaMap"); |
||||
else if(alphaLayer == 1) |
||||
matParam = terrain.getMaterial().getParam("AlphaMap_1"); |
||||
else if(alphaLayer == 2) |
||||
matParam = terrain.getMaterial().getParam("AlphaMap_2"); |
||||
|
||||
if (matParam == null || matParam.getValue() == null) { |
||||
return null; |
||||
} |
||||
Texture tex = (Texture) matParam.getValue(); |
||||
return tex; |
||||
} |
||||
|
||||
/** |
||||
* Goes through each pixel in the image. At each pixel it looks to see if the UV mouse coordinate is within the |
||||
* of the brush. If it is in the brush radius, it gets the existing color from that pixel so it can add/subtract to/from it. |
||||
* Essentially it does a radius check and adds in a fade value. It does this to the color value returned by the |
||||
* first pixel color query. |
||||
* Next it sets the color of that pixel. If it was within the radius, the color will change. If it was outside |
||||
* the radius, then nothing will change, the color will be the same; but it will set it nonetheless. Not efficient. |
||||
* |
||||
* If the mouse is being dragged with the button down, then the dragged value should be set to true. This will reduce |
||||
* the intensity of the brush to 10% of what it should be per spray. Otherwise it goes to 100% opacity within a few pixels. |
||||
* This makes it work a little more realistically. |
||||
* |
||||
* @param image to manipulate |
||||
* @param uv the world x,z coordinate |
||||
* @param dragged true if the mouse button is down and it is being dragged, use to reduce brush intensity |
||||
* @param radius in percentage so it can be translated to the image dimensions |
||||
* @param erase true if the tool should remove the paint instead of add it |
||||
* @param fadeFalloff the percentage of the radius when the paint begins to start fading |
||||
*/ |
||||
protected void doPaintAction(int texIndex, Image image, Vector2f uv, boolean dragged, float radius, boolean erase, float fadeFalloff){ |
||||
Vector2f texuv = new Vector2f(); |
||||
ColorRGBA color = ColorRGBA.Black; |
||||
|
||||
float width = image.getWidth(); |
||||
float height = image.getHeight(); |
||||
|
||||
int minx = (int) (uv.x*width - radius*width); // convert percents to pixels to limit how much we iterate
|
||||
int maxx = (int) (uv.x*width + radius*width); |
||||
int miny = (int) (uv.y*height - radius*height); |
||||
int maxy = (int) (uv.y*height + radius*height); |
||||
|
||||
float radiusSquared = radius*radius; |
||||
float radiusFalloff = radius*fadeFalloff; |
||||
// go through each pixel, in the radius of the tool, in the image
|
||||
for (int y = miny; y < maxy; y++){ |
||||
for (int x = minx; x < maxx; x++){ |
||||
|
||||
texuv.set((float)x / width, (float)y / height);// gets the position in percentage so it can compare with the mouse UV coordinate
|
||||
|
||||
float dist = texuv.distanceSquared(uv); |
||||
if (dist < radiusSquared ) { // if the pixel is within the distance of the radius, set a color (distance times intensity)
|
||||
manipulatePixel(image, x, y, color, false); // gets the color at that location (false means don't write to the buffer)
|
||||
|
||||
// calculate the fade falloff intensity
|
||||
float intensity = 0.1f; |
||||
if (dist > radiusFalloff) { |
||||
float dr = radius - radiusFalloff; // falloff to radius length
|
||||
float d2 = dist - radiusFalloff; // dist minus falloff
|
||||
d2 = d2/dr; // dist percentage of falloff length
|
||||
intensity = 1-d2; // fade out more the farther away it is
|
||||
} |
||||
|
||||
//if (dragged)
|
||||
// intensity = intensity*0.1f; // magical divide it by 10 to reduce its intensity when mouse is dragged
|
||||
|
||||
if (erase) { |
||||
switch (texIndex) { |
||||
case 0: |
||||
color.r -= intensity; break; |
||||
case 1: |
||||
color.g -= intensity; break; |
||||
case 2: |
||||
color.b -= intensity; break; |
||||
case 3: |
||||
color.a -= intensity; break; |
||||
} |
||||
} else { |
||||
switch (texIndex) { |
||||
case 0: |
||||
color.r += intensity; break; |
||||
case 1: |
||||
color.g += intensity; break; |
||||
case 2: |
||||
color.b += intensity; break; |
||||
case 3: |
||||
color.a += intensity; break; |
||||
} |
||||
} |
||||
color.clamp(); |
||||
|
||||
manipulatePixel(image, x, y, color, true); // set the new color
|
||||
} |
||||
|
||||
} |
||||
} |
||||
|
||||
image.getData(0).rewind(); |
||||
} |
||||
|
||||
/** |
||||
* We are only using RGBA8 images for alpha textures right now. |
||||
* @param image to get/set the color on |
||||
* @param x location |
||||
* @param y location |
||||
* @param color color to get/set |
||||
* @param write to write the color or not |
||||
*/ |
||||
protected void manipulatePixel(Image image, int x, int y, ColorRGBA color, boolean write){ |
||||
ByteBuffer buf = image.getData(0); |
||||
int width = image.getWidth(); |
||||
|
||||
int position = (y * width + x) * 4; |
||||
|
||||
if ( position> buf.capacity()-1 || position<0 ) |
||||
return; |
||||
|
||||
if (write) { |
||||
switch (image.getFormat()){ |
||||
case RGBA8: |
||||
buf.position( position ); |
||||
buf.put(float2byte(color.r)) |
||||
.put(float2byte(color.g)) |
||||
.put(float2byte(color.b)) |
||||
.put(float2byte(color.a)); |
||||
return; |
||||
default: |
||||
throw new UnsupportedOperationException("Image format: "+image.getFormat()); |
||||
} |
||||
} else { |
||||
switch (image.getFormat()){ |
||||
case RGBA8: |
||||
buf.position( position ); |
||||
color.set(byte2float(buf.get()), byte2float(buf.get()), byte2float(buf.get()), byte2float(buf.get())); |
||||
return; |
||||
default: |
||||
throw new UnsupportedOperationException("Image format: "+image.getFormat()); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
private float byte2float(byte b){ |
||||
return ((float)(b & 0xFF)) / 255f; |
||||
} |
||||
|
||||
private byte float2byte(float f){ |
||||
return (byte) (f * 255f); |
||||
} |
||||
} |
@ -0,0 +1,69 @@ |
||||
/* |
||||
* Copyright (c) 2009-2011 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 com.jme3.gde.terraineditor.tools; |
||||
|
||||
import com.jme3.asset.AssetManager; |
||||
import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; |
||||
import com.jme3.math.ColorRGBA; |
||||
import com.jme3.math.Vector3f; |
||||
import com.jme3.scene.Node; |
||||
import org.openide.loaders.DataObject; |
||||
|
||||
/** |
||||
* Raise the terrain |
||||
* |
||||
* @author Brent Owens |
||||
*/ |
||||
public class RaiseTerrainTool extends TerrainTool { |
||||
|
||||
|
||||
@Override |
||||
public void actionPrimary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject) { |
||||
if (radius == 0 || weight == 0) |
||||
return; |
||||
RaiseTerrainToolAction action = new RaiseTerrainToolAction(point, radius, weight); |
||||
action.doActionPerformed(rootNode, dataObject); |
||||
} |
||||
|
||||
@Override |
||||
public void actionSecondary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject) { |
||||
// no secondary option
|
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void addMarkerPrimary(Node parent) { |
||||
super.addMarkerPrimary(parent); |
||||
markerPrimary.getMaterial().setColor("Color", ColorRGBA.Green); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,113 @@ |
||||
/* |
||||
* Copyright (c) 2009-2011 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 com.jme3.gde.terraineditor.tools; |
||||
|
||||
import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; |
||||
import com.jme3.math.Vector2f; |
||||
import com.jme3.math.Vector3f; |
||||
import com.jme3.scene.Node; |
||||
import com.jme3.terrain.Terrain; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Raise/lower the terrain, executed from the OpenGL thread. |
||||
* |
||||
* @author Brent Owens |
||||
*/ |
||||
public class RaiseTerrainToolAction extends AbstractTerrainToolAction { |
||||
|
||||
private Vector3f worldLoc; |
||||
private float radius; |
||||
private float height; |
||||
|
||||
public RaiseTerrainToolAction(Vector3f markerLocation, float radius, float height) { |
||||
this.worldLoc = markerLocation.clone(); |
||||
this.radius = radius; |
||||
this.height = height; |
||||
name = "Raise terrain"; |
||||
} |
||||
|
||||
@Override |
||||
protected Object doApplyTool(AbstractSceneExplorerNode rootNode) { |
||||
Terrain terrain = getTerrain(rootNode.getLookup().lookup(Node.class)); |
||||
if (terrain == null) |
||||
return null; |
||||
modifyHeight(terrain, radius, height); |
||||
return terrain; |
||||
} |
||||
|
||||
@Override |
||||
protected void doUndoTool(AbstractSceneExplorerNode rootNode, Object undoObject) { |
||||
if (undoObject == null) |
||||
return; |
||||
modifyHeight((Terrain)undoObject, radius, -height); |
||||
} |
||||
|
||||
private void modifyHeight(Terrain terrain, float radius, float heightDir) { |
||||
|
||||
int radiusStepsX = (int) (radius / ((Node)terrain).getLocalScale().x); |
||||
int radiusStepsZ = (int) (radius / ((Node)terrain).getLocalScale().z); |
||||
|
||||
float xStepAmount = ((Node)terrain).getLocalScale().x; |
||||
float zStepAmount = ((Node)terrain).getLocalScale().z; |
||||
|
||||
List<Vector2f> locs = new ArrayList<Vector2f>(); |
||||
List<Float> heights = new ArrayList<Float>(); |
||||
|
||||
for (int z=-radiusStepsZ; z<radiusStepsZ; z++) { |
||||
for (int x=-radiusStepsZ; x<radiusStepsX; x++) { |
||||
|
||||
float locX = worldLoc.x + (x*xStepAmount); |
||||
float locZ = worldLoc.z + (z*zStepAmount); |
||||
|
||||
// see if it is in the radius of the tool
|
||||
if (ToolUtils.isInRadius(locX-worldLoc.x,locZ-worldLoc.z,radius)) { |
||||
// adjust height based on radius of the tool
|
||||
float h = ToolUtils.calculateHeight(radius, heightDir, locX-worldLoc.x, locZ-worldLoc.z); |
||||
// increase the height
|
||||
locs.add(new Vector2f(locX, locZ)); |
||||
heights.add(h); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// do the actual height adjustment
|
||||
terrain.adjustHeight(locs, heights); |
||||
|
||||
((Node)terrain).updateModelBound(); // or else we won't collide with it where we just edited
|
||||
} |
||||
|
||||
|
||||
|
||||
} |
@ -0,0 +1,65 @@ |
||||
/* |
||||
* Copyright (c) 2009-2011 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 com.jme3.gde.terraineditor.tools; |
||||
|
||||
import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; |
||||
import com.jme3.math.ColorRGBA; |
||||
import com.jme3.math.Vector3f; |
||||
import com.jme3.scene.Node; |
||||
import org.openide.loaders.DataObject; |
||||
|
||||
/** |
||||
* Smooth the terrain by averaging the heights of the surrounding areas. |
||||
* |
||||
* @author Brent Owens |
||||
*/ |
||||
public class SmoothTerrainTool extends TerrainTool { |
||||
|
||||
@Override |
||||
public void actionPrimary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject) { |
||||
if (radius == 0 || weight == 0) |
||||
return; |
||||
SmoothTerrainToolAction action = new SmoothTerrainToolAction(point, radius, weight); |
||||
action.doActionPerformed(rootNode, dataObject); |
||||
} |
||||
|
||||
@Override |
||||
public void actionSecondary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject) { |
||||
// do nothing
|
||||
} |
||||
|
||||
@Override |
||||
public void addMarkerPrimary(Node parent) { |
||||
super.addMarkerPrimary(parent); |
||||
markerPrimary.getMaterial().setColor("Color", ColorRGBA.Yellow); |
||||
} |
||||
} |
@ -0,0 +1,159 @@ |
||||
/* |
||||
* Copyright (c) 2009-2011 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 com.jme3.gde.terraineditor.tools; |
||||
|
||||
import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; |
||||
import com.jme3.math.Vector2f; |
||||
import com.jme3.math.Vector3f; |
||||
import com.jme3.scene.Node; |
||||
import com.jme3.terrain.Terrain; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Smooth bumps in the terrain by averaging the height in the tool radius. |
||||
* The smoothAmount affects how many neighbour points are averaged, The smaller |
||||
* the value, then only the smaller bumps will disappear. A large value will |
||||
* smooth larger hills. |
||||
* |
||||
* @author sploreg |
||||
*/ |
||||
public class SmoothTerrainToolAction extends AbstractTerrainToolAction { |
||||
|
||||
private Vector3f worldLoc; |
||||
private float radius; |
||||
private float height; |
||||
|
||||
List<Vector2f> undoLocs; |
||||
List<Float> undoHeights; |
||||
|
||||
public SmoothTerrainToolAction(Vector3f markerLocation, float radius, float height) { |
||||
this.worldLoc = markerLocation.clone(); |
||||
this.radius = radius; |
||||
this.height = height; |
||||
name = "Smooth terrain"; |
||||
} |
||||
|
||||
@Override |
||||
protected Object doApplyTool(AbstractSceneExplorerNode rootNode) { |
||||
Terrain terrain = getTerrain(rootNode.getLookup().lookup(Node.class)); |
||||
if (terrain == null) |
||||
return null; |
||||
modifyHeight(terrain, radius, height); |
||||
return terrain; |
||||
} |
||||
|
||||
@Override |
||||
protected void doUndoTool(AbstractSceneExplorerNode rootNode, Object undoObject) { |
||||
if (undoObject == null) |
||||
return; |
||||
if (undoLocs == null || undoHeights == null) |
||||
return; |
||||
resetHeight((Terrain)undoObject, undoLocs, undoHeights); |
||||
} |
||||
|
||||
private void modifyHeight(Terrain terrain, float radius, float height) { |
||||
|
||||
int radiusStepsX = (int)(radius / ((Node)terrain).getLocalScale().x); |
||||
int radiusStepsZ = (int)(radius / ((Node)terrain).getLocalScale().z); |
||||
|
||||
float xStepAmount = ((Node)terrain).getLocalScale().x; |
||||
float zStepAmount = ((Node)terrain).getLocalScale().z; |
||||
|
||||
List<Vector2f> locs = new ArrayList<Vector2f>(); |
||||
List<Float> heights = new ArrayList<Float>(); |
||||
|
||||
for (int z=-radiusStepsZ; z<radiusStepsZ; z++) { |
||||
for (int x=-radiusStepsZ; x<radiusStepsX; x++) { |
||||
|
||||
float locX = worldLoc.x + (x*xStepAmount); |
||||
float locZ = worldLoc.z + (z*zStepAmount); |
||||
|
||||
// see if it is in the radius of the tool
|
||||
if (ToolUtils.isInRadius(locX-worldLoc.x,locZ-worldLoc.z,radius)) { |
||||
|
||||
Vector2f terrainLoc = new Vector2f(locX, locZ); |
||||
// adjust height based on radius of the tool
|
||||
float center = terrain.getHeightmapHeight(terrainLoc); |
||||
float left = terrain.getHeightmapHeight(new Vector2f(terrainLoc.x-1, terrainLoc.y)); |
||||
float right = terrain.getHeightmapHeight(new Vector2f(terrainLoc.x+1, terrainLoc.y)); |
||||
float up = terrain.getHeightmapHeight(new Vector2f(terrainLoc.x, terrainLoc.y+1)); |
||||
float down = terrain.getHeightmapHeight(new Vector2f(terrainLoc.x, terrainLoc.y-1)); |
||||
int count = 1; |
||||
float amount = center; |
||||
if (left != Float.NaN) { |
||||
amount += left; |
||||
count++; |
||||
} |
||||
if (right != Float.NaN) { |
||||
amount += right; |
||||
count++; |
||||
} |
||||
if (up != Float.NaN) { |
||||
amount += up; |
||||
count++; |
||||
} |
||||
if (down != Float.NaN) { |
||||
amount += down; |
||||
count++; |
||||
} |
||||
|
||||
amount /= count; // take average
|
||||
|
||||
// weigh it
|
||||
float diff = amount-center; |
||||
diff *= height; |
||||
|
||||
locs.add(terrainLoc); |
||||
heights.add(diff); |
||||
} |
||||
} |
||||
} |
||||
|
||||
undoLocs = locs; |
||||
undoHeights = heights; |
||||
|
||||
// do the actual height adjustment
|
||||
terrain.adjustHeight(locs, heights); |
||||
|
||||
((Node)terrain).updateModelBound(); // or else we won't collide with it where we just edited
|
||||
} |
||||
|
||||
private void resetHeight(Terrain terrain, List<Vector2f> undoLocs, List<Float> undoHeights) { |
||||
List<Float> neg = new ArrayList<Float>(); |
||||
for (Float f : undoHeights) |
||||
neg.add( f * -1f ); |
||||
|
||||
terrain.adjustHeight(undoLocs, neg); |
||||
((Node)terrain).updateModelBound(); |
||||
} |
||||
} |
@ -0,0 +1,184 @@ |
||||
/* |
||||
* Copyright (c) 2009-2011 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 com.jme3.gde.terraineditor.tools; |
||||
|
||||
import com.jme3.asset.AssetManager; |
||||
import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; |
||||
import com.jme3.material.Material; |
||||
import com.jme3.math.ColorRGBA; |
||||
import com.jme3.math.Vector3f; |
||||
import com.jme3.scene.Geometry; |
||||
import com.jme3.scene.Mesh; |
||||
import com.jme3.scene.Node; |
||||
import com.jme3.scene.VertexBuffer; |
||||
import com.jme3.scene.shape.Sphere; |
||||
import com.jme3.util.IntMap.Entry; |
||||
import org.openide.loaders.DataObject; |
||||
|
||||
/** |
||||
* Modifies the terrain in some way. |
||||
* It has a primary and secondary action, activated from left and right mouse button respectively. |
||||
* It will also attach tool geometries to the scene so the user can see where they are editing. |
||||
* |
||||
* @author Brent Owens |
||||
*/ |
||||
public abstract class TerrainTool { |
||||
|
||||
protected AssetManager manager; |
||||
protected Geometry markerPrimary; |
||||
protected Geometry markerSecondary; |
||||
protected float radius; |
||||
protected float weight; |
||||
protected float maxToolSize = 20; // override in sub classes
|
||||
|
||||
// the key to load the tool hint text from the resource bundle
|
||||
protected String toolHintTextKey = "TerrainEditorTopComponent.toolHint.default"; |
||||
|
||||
/** |
||||
* The tool was selected, start showing the marker. |
||||
* @param manager |
||||
* @param parent node that the marker will attach to |
||||
*/ |
||||
public void activate(AssetManager manager, Node parent) { |
||||
this.manager = manager; |
||||
addMarkerPrimary(parent); |
||||
} |
||||
|
||||
/** |
||||
* The primary action for the tool gets activated |
||||
*/ |
||||
public abstract void actionPrimary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject); |
||||
|
||||
/** |
||||
* The secondary action for the tool gets activated |
||||
*/ |
||||
public abstract void actionSecondary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject); |
||||
|
||||
/** |
||||
* Location of the primary editor marker |
||||
*/ |
||||
public Vector3f getMarkerPrimaryLocation() { |
||||
if (markerPrimary != null) |
||||
return markerPrimary.getLocalTranslation(); |
||||
else |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Move the marker to a new location, usually follows the mouse |
||||
* @param newLoc |
||||
*/ |
||||
public void markerMoved(Vector3f newLoc) { |
||||
if (markerPrimary != null) |
||||
markerPrimary.setLocalTranslation(newLoc); |
||||
} |
||||
|
||||
/** |
||||
* The radius of the tool has changed, so update the marker |
||||
* @param radius percentage of the max radius |
||||
*/ |
||||
public void radiusChanged(float radius) { |
||||
this.radius = maxToolSize*radius; |
||||
|
||||
if (markerPrimary != null) { |
||||
for (Entry e: markerPrimary.getMesh().getBuffers()) |
||||
((VertexBuffer)e.getValue()).resetObject(); |
||||
((Sphere)markerPrimary.getMesh()).updateGeometry(8, 8, this.radius); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* The weight of the tool has changed. Optionally change |
||||
* the marker look. |
||||
* @param weight percent |
||||
*/ |
||||
public void weightChanged(float weight) { |
||||
this.weight = weight; |
||||
} |
||||
|
||||
/** |
||||
* Create the primary marker mesh, follows the mouse. |
||||
* @param parent it will attach to |
||||
*/ |
||||
public void addMarkerPrimary(Node parent) { |
||||
if (markerPrimary == null) { |
||||
markerPrimary = new Geometry("edit marker primary"); |
||||
Mesh m = new Sphere(8, 8, radius); |
||||
markerPrimary.setMesh(m); |
||||
Material mat = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md"); |
||||
mat.getAdditionalRenderState().setWireframe(true); |
||||
markerPrimary.setMaterial(mat); |
||||
markerPrimary.setLocalTranslation(0,0,0); |
||||
mat.setColor("Color", ColorRGBA.LightGray); |
||||
} |
||||
parent.attachChild(markerPrimary); |
||||
} |
||||
|
||||
/** |
||||
* Create the secondary marker mesh, placed |
||||
* with the right mouse button. |
||||
* @param parent it will attach to |
||||
*/ |
||||
public void addMarkerSecondary(Node parent) { |
||||
if (markerSecondary == null) { |
||||
markerSecondary = new Geometry("edit marker secondary"); |
||||
Mesh m2 = new Sphere(8, 8, 0.5f); |
||||
markerSecondary.setMesh(m2); |
||||
Material mat2 = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md"); |
||||
mat2.getAdditionalRenderState().setWireframe(false); |
||||
markerSecondary.setMaterial(mat2); |
||||
markerSecondary.setLocalTranslation(0,0,0); |
||||
mat2.setColor("Color", ColorRGBA.Red); |
||||
} |
||||
parent.attachChild(markerSecondary); |
||||
} |
||||
|
||||
/** |
||||
* Remove the markers from the scene. |
||||
*/ |
||||
public void hideMarkers() { |
||||
if (markerPrimary != null) |
||||
markerPrimary.removeFromParent(); |
||||
if (markerSecondary != null) |
||||
markerSecondary.removeFromParent(); |
||||
} |
||||
|
||||
public String getToolHintTextKey() { |
||||
return toolHintTextKey; |
||||
} |
||||
|
||||
public void setToolHintTextKey(String toolHintTextKey) { |
||||
this.toolHintTextKey = toolHintTextKey; |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,101 @@ |
||||
/* |
||||
* Copyright (c) 2009-2011 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 com.jme3.gde.terraineditor.tools; |
||||
|
||||
import com.jme3.math.Vector2f; |
||||
|
||||
/** |
||||
* Handy utilities for the editor tools |
||||
* @author Brent Owens |
||||
*/ |
||||
public class ToolUtils { |
||||
|
||||
/** |
||||
* See if the X,Y coordinate is in the radius of the circle. It is assumed |
||||
* that the "grid" being tested is located at 0,0 and its dimensions are 2*radius. |
||||
* @param x |
||||
* @param z |
||||
* @param radius |
||||
* @return |
||||
*/ |
||||
public static boolean isInRadius(float x, float y, float radius) { |
||||
Vector2f point = new Vector2f(x,y); |
||||
// return true if the distance is less than equal to the radius
|
||||
return Math.abs(point.length()) <= radius; |
||||
} |
||||
|
||||
/** |
||||
* Interpolate the height value based on its distance from the center (how far along |
||||
* the radius it is). |
||||
* The farther from the center, the less the height will be. |
||||
* This produces a linear height falloff. |
||||
* @param radius of the tool |
||||
* @param heightFactor potential height value to be adjusted |
||||
* @param x location |
||||
* @param z location |
||||
* @return the adjusted height value |
||||
*/ |
||||
public static float calculateHeight(float radius, float heightFactor, float x, float z) { |
||||
float val = calculateRadiusPercent(radius, x, z); |
||||
return heightFactor * val; |
||||
} |
||||
|
||||
public static float calculateRadiusPercent(float radius, float x, float z) { |
||||
// find percentage for each 'unit' in radius
|
||||
Vector2f point = new Vector2f(x,z); |
||||
float val = Math.abs(point.length()) / radius; |
||||
val = 1f - val; |
||||
return val; |
||||
} |
||||
|
||||
public static int compareFloat(float a, float b, float epsilon) { |
||||
if (floatEquals(a, b, epsilon)) |
||||
return 0; |
||||
else if (floatLessThan(a, b, epsilon)) |
||||
return -1; |
||||
else |
||||
return 1; |
||||
} |
||||
|
||||
public static boolean floatEquals(float a, float b, float epsilon) { |
||||
return a == b ? true : Math.abs(a - b) < epsilon; |
||||
} |
||||
|
||||
public static boolean floatLessThan(float a, float b, float epsilon) { |
||||
return b - a > epsilon; |
||||
} |
||||
|
||||
public static boolean floatGreaterThan(float a, float b, float epsilon) { |
||||
return a - b > epsilon; |
||||
} |
||||
} |
Loading…
Reference in new issue