aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorolamedia <[email protected]>2012-09-28 18:46:42 +0600
committerolamedia <[email protected]>2012-09-28 18:46:42 +0600
commitb4192c7a88bad111bebbd42d391d6e729c8617d6 (patch)
treeb05a586dbc60c5427fcc7f3fe01cf2fdcb970272 /src
initial
Diffstat (limited to 'src')
-rw-r--r--src/libnoiseforjava/Interp.java107
-rw-r--r--src/libnoiseforjava/Misc.java51
-rw-r--r--src/libnoiseforjava/NoiseGen.java261
-rw-r--r--src/libnoiseforjava/VectorTable.java309
-rw-r--r--src/libnoiseforjava/exception/ExceptionInvalidParam.java42
-rw-r--r--src/libnoiseforjava/exception/ExceptionNoModule.java41
-rw-r--r--src/libnoiseforjava/model/Cylinder.java115
-rw-r--r--src/libnoiseforjava/model/Line.java264
-rw-r--r--src/libnoiseforjava/model/Plane.java105
-rw-r--r--src/libnoiseforjava/model/Sphere.java118
-rw-r--r--src/libnoiseforjava/module/Abs.java52
-rw-r--r--src/libnoiseforjava/module/Add.java53
-rw-r--r--src/libnoiseforjava/module/Billow.java184
-rw-r--r--src/libnoiseforjava/module/Blend.java79
-rw-r--r--src/libnoiseforjava/module/Cached.java97
-rw-r--r--src/libnoiseforjava/module/Checkerboard.java62
-rw-r--r--src/libnoiseforjava/module/Clamp.java90
-rw-r--r--src/libnoiseforjava/module/Const.java70
-rw-r--r--src/libnoiseforjava/module/Curve.java203
-rw-r--r--src/libnoiseforjava/module/Cylinders.java103
-rw-r--r--src/libnoiseforjava/module/Displace.java238
-rw-r--r--src/libnoiseforjava/module/Exponent.java79
-rw-r--r--src/libnoiseforjava/module/Gradient.java119
-rw-r--r--src/libnoiseforjava/module/Identity.java70
-rw-r--r--src/libnoiseforjava/module/Intersection.java63
-rw-r--r--src/libnoiseforjava/module/Invert.java48
-rw-r--r--src/libnoiseforjava/module/Max.java54
-rw-r--r--src/libnoiseforjava/module/Min.java56
-rw-r--r--src/libnoiseforjava/module/ModuleBase.java171
-rw-r--r--src/libnoiseforjava/module/Multiply.java55
-rw-r--r--src/libnoiseforjava/module/Perlin.java357
-rw-r--r--src/libnoiseforjava/module/Power.java56
-rw-r--r--src/libnoiseforjava/module/RidgedMulti.java357
-rw-r--r--src/libnoiseforjava/module/RotatePoint.java216
-rw-r--r--src/libnoiseforjava/module/ScaleBias.java124
-rw-r--r--src/libnoiseforjava/module/ScalePoint.java182
-rw-r--r--src/libnoiseforjava/module/Select.java300
-rw-r--r--src/libnoiseforjava/module/Simplex.java395
-rw-r--r--src/libnoiseforjava/module/Spheres.java102
-rw-r--r--src/libnoiseforjava/module/Terrace.java326
-rw-r--r--src/libnoiseforjava/module/TranslatePoint.java192
-rw-r--r--src/libnoiseforjava/module/Turbulence.java282
-rw-r--r--src/libnoiseforjava/module/Voronoi.java283
-rw-r--r--src/libnoiseforjava/util/ColorCafe.java105
-rw-r--r--src/libnoiseforjava/util/GradientColor.java251
-rw-r--r--src/libnoiseforjava/util/GradientPoint.java74
-rw-r--r--src/libnoiseforjava/util/ImageCafe.java173
-rw-r--r--src/libnoiseforjava/util/MiscUtilities.java52
-rw-r--r--src/libnoiseforjava/util/NoiseMap.java158
-rw-r--r--src/libnoiseforjava/util/NoiseMapBuilder.java195
-rw-r--r--src/libnoiseforjava/util/NoiseMapBuilderCylinder.java213
-rw-r--r--src/libnoiseforjava/util/NoiseMapBuilderPlane.java245
-rw-r--r--src/libnoiseforjava/util/NoiseMapBuilderSphere.java195
-rw-r--r--src/libnoiseforjava/util/RendererImage.java755
-rw-r--r--src/libnoiseforjava/util/RendererNormalMap.java316
-rw-r--r--src/ru/olamedia/Options.java5
-rw-r--r--src/ru/olamedia/asset/Asset.java29
-rw-r--r--src/ru/olamedia/asset/AssetManager.java28
-rw-r--r--src/ru/olamedia/asset/AssetNotFoundException.java22
-rw-r--r--src/ru/olamedia/asset/package-info.java8
-rw-r--r--src/ru/olamedia/camera/CameraProjectionMatrix.java77
-rw-r--r--src/ru/olamedia/camera/Cameraman.java21
-rw-r--r--src/ru/olamedia/camera/MatrixCamera.java545
-rw-r--r--src/ru/olamedia/camera/package-info.java8
-rw-r--r--src/ru/olamedia/controls/package-info.java8
-rw-r--r--src/ru/olamedia/debug/SystemInfo.java24
-rw-r--r--src/ru/olamedia/debug/package-info.java8
-rw-r--r--src/ru/olamedia/game/ClientGame.java13
-rw-r--r--src/ru/olamedia/game/DynamicJList.java16
-rw-r--r--src/ru/olamedia/game/Game.java25
-rw-r--r--src/ru/olamedia/game/GameFrame.java194
-rw-r--r--src/ru/olamedia/game/GameManager.java165
-rw-r--r--src/ru/olamedia/game/Launcher.java17
-rw-r--r--src/ru/olamedia/game/MainMenu.java168
-rw-r--r--src/ru/olamedia/game/QuitAdapter.java71
-rw-r--r--src/ru/olamedia/game/ServerGame.java10
-rw-r--r--src/ru/olamedia/game/icon128x128.pngbin0 -> 2158 bytes
-rw-r--r--src/ru/olamedia/game/icon16x16.pngbin0 -> 635 bytes
-rw-r--r--src/ru/olamedia/game/icon256x256.pngbin0 -> 2820 bytes
-rw-r--r--src/ru/olamedia/game/icon32x32.pngbin0 -> 1426 bytes
-rw-r--r--src/ru/olamedia/game/icon64x64.pngbin0 -> 1715 bytes
-rw-r--r--src/ru/olamedia/game/package-info.java8
-rw-r--r--src/ru/olamedia/geom/DisplayList.java39
-rw-r--r--src/ru/olamedia/geom/Frustum.java11
-rw-r--r--src/ru/olamedia/geom/Mesh.java346
-rw-r--r--src/ru/olamedia/geom/Quad.java12
-rw-r--r--src/ru/olamedia/geom/SimpleQuadMesh.java113
-rw-r--r--src/ru/olamedia/geom/package-info.java8
-rw-r--r--src/ru/olamedia/input/AWTRobotUtil.java97
-rw-r--r--src/ru/olamedia/input/KeyListener.java10
-rw-r--r--src/ru/olamedia/input/Keyboard.java64
-rw-r--r--src/ru/olamedia/input/MouseJail.java113
-rw-r--r--src/ru/olamedia/input/MouseListener.java6
-rw-r--r--src/ru/olamedia/input/package-info.java8
-rw-r--r--src/ru/olamedia/liveEntity/LiveEntity.java683
-rw-r--r--src/ru/olamedia/liveEntity/LiveEntityEvent.java31
-rw-r--r--src/ru/olamedia/liveEntity/LiveEntityEventDispatcher.java7
-rw-r--r--src/ru/olamedia/liveEntity/package-info.java8
-rw-r--r--src/ru/olamedia/math/Box.java74
-rw-r--r--src/ru/olamedia/math/Classifier.java8
-rw-r--r--src/ru/olamedia/math/Frustum.java127
-rw-r--r--src/ru/olamedia/math/FrustumUtil.java72
-rw-r--r--src/ru/olamedia/math/Halfspace.java7
-rw-r--r--src/ru/olamedia/math/Matrix4f.java191
-rw-r--r--src/ru/olamedia/math/Matrix4fUtil.java36
-rw-r--r--src/ru/olamedia/math/Plane.java71
-rw-r--r--src/ru/olamedia/math/Quaternion.java25
-rw-r--r--src/ru/olamedia/math/QuaternionUtil.java54
-rw-r--r--src/ru/olamedia/math/TransformMatrix.java15
-rw-r--r--src/ru/olamedia/math/Vector3f.java70
-rw-r--r--src/ru/olamedia/math/ViewMatrix.java111
-rw-r--r--src/ru/olamedia/math/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/OlaCraft.java6
-rw-r--r--src/ru/olamedia/olacraft/OlaCraftFrame.java10
-rw-r--r--src/ru/olamedia/olacraft/events/GameEvent.java32
-rw-r--r--src/ru/olamedia/olacraft/events/GameEventDispatcher.java22
-rw-r--r--src/ru/olamedia/olacraft/events/GameEventListener.java5
-rw-r--r--src/ru/olamedia/olacraft/events/GameEventRegistry.java17
-rw-r--r--src/ru/olamedia/olacraft/events/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/game/Game.java106
-rw-r--r--src/ru/olamedia/olacraft/game/GameInterface.java7
-rw-r--r--src/ru/olamedia/olacraft/game/IGameWrapper.java7
-rw-r--r--src/ru/olamedia/olacraft/game/LocalGameWrapper.java17
-rw-r--r--src/ru/olamedia/olacraft/game/SpawnLocation.java7
-rw-r--r--src/ru/olamedia/olacraft/game/Timer.java99
-rw-r--r--src/ru/olamedia/olacraft/game/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/inventory/Frame.java44
-rw-r--r--src/ru/olamedia/olacraft/inventory/Inventory.java76
-rw-r--r--src/ru/olamedia/olacraft/inventory/package-info.java9
-rw-r--r--src/ru/olamedia/olacraft/network/ConnectionState.java17
-rw-r--r--src/ru/olamedia/olacraft/network/ConnectionStateListener.java7
-rw-r--r--src/ru/olamedia/olacraft/network/GameClient.java209
-rw-r--r--src/ru/olamedia/olacraft/network/GameServer.java169
-rw-r--r--src/ru/olamedia/olacraft/network/Network.java71
-rw-r--r--src/ru/olamedia/olacraft/network/PlayerConnection.java9
-rw-r--r--src/ru/olamedia/olacraft/network/discovery/DiscoveryClient.java143
-rw-r--r--src/ru/olamedia/olacraft/network/discovery/DiscoveryListener.java9
-rw-r--r--src/ru/olamedia/olacraft/network/discovery/DiscoveryThread.java91
-rw-r--r--src/ru/olamedia/olacraft/network/discovery/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/network/package-info.java9
-rw-r--r--src/ru/olamedia/olacraft/network/packet/ChatMessagePacket.java5
-rw-r--r--src/ru/olamedia/olacraft/network/packet/ChunkDataPacket.java10
-rw-r--r--src/ru/olamedia/olacraft/network/packet/ConnectionPacket.java11
-rw-r--r--src/ru/olamedia/olacraft/network/packet/ConnectionRequestPacket.java5
-rw-r--r--src/ru/olamedia/olacraft/network/packet/GetChunkDataPacket.java7
-rw-r--r--src/ru/olamedia/olacraft/network/packet/GetRegionPacket.java15
-rw-r--r--src/ru/olamedia/olacraft/network/packet/IPacket.java5
-rw-r--r--src/ru/olamedia/olacraft/network/packet/IPacketListener.java7
-rw-r--r--src/ru/olamedia/olacraft/network/packet/LiveEntityLocationUpdatePacket.java15
-rw-r--r--src/ru/olamedia/olacraft/network/packet/RegionDataPacket.java7
-rw-r--r--src/ru/olamedia/olacraft/network/packet/SpawnPacket.java15
-rw-r--r--src/ru/olamedia/olacraft/network/packet/SpawnRequestPacket.java4
-rw-r--r--src/ru/olamedia/olacraft/network/packet/WorldInfoPacket.java15
-rw-r--r--src/ru/olamedia/olacraft/network/packet/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/physics/GamePhysicsWorld.java27
-rw-r--r--src/ru/olamedia/olacraft/physics/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/picker/joglBlockPicker.java27
-rw-r--r--src/ru/olamedia/olacraft/picker/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/render/jogl/BlockRenderer.java87
-rw-r--r--src/ru/olamedia/olacraft/render/jogl/BlockStackRenderer.java9
-rw-r--r--src/ru/olamedia/olacraft/render/jogl/ChunkRenderer.java146
-rw-r--r--src/ru/olamedia/olacraft/render/jogl/DefaultRenderer.java75
-rw-r--r--src/ru/olamedia/olacraft/render/jogl/IRenderer.java8
-rw-r--r--src/ru/olamedia/olacraft/render/jogl/InventoryRenderer.java87
-rw-r--r--src/ru/olamedia/olacraft/render/jogl/PlaneRenderer.java102
-rw-r--r--src/ru/olamedia/olacraft/render/jogl/VectorRenderer.java20
-rw-r--r--src/ru/olamedia/olacraft/render/jogl/joglViewport.java24
-rw-r--r--src/ru/olamedia/olacraft/render/jogl/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/scene/GameScene.java252
-rw-r--r--src/ru/olamedia/olacraft/scene/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/weapon/Bullet.java51
-rw-r--r--src/ru/olamedia/olacraft/weapon/BulletScene.java35
-rw-r--r--src/ru/olamedia/olacraft/weapon/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/world/World.java12
-rw-r--r--src/ru/olamedia/olacraft/world/WorldInfo.java11
-rw-r--r--src/ru/olamedia/olacraft/world/block/Block.java111
-rw-r--r--src/ru/olamedia/olacraft/world/block/BlockRegistry.java46
-rw-r--r--src/ru/olamedia/olacraft/world/block/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/world/blockStack/BlockStack.java63
-rw-r--r--src/ru/olamedia/olacraft/world/blockStack/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/AbstractBlockType.java86
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/BlockType.java21
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/EmptyBlockType.java23
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/GrassBlockType.java28
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/GravelBlockType.java23
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/world/chunk/BlockSlice.java164
-rw-r--r--src/ru/olamedia/olacraft/world/chunk/Chunk.java290
-rw-r--r--src/ru/olamedia/olacraft/world/chunk/ChunkMeshBulder.java47
-rw-r--r--src/ru/olamedia/olacraft/world/chunk/ChunkSlice.java114
-rw-r--r--src/ru/olamedia/olacraft/world/chunk/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/world/data/ChunkData.java86
-rw-r--r--src/ru/olamedia/olacraft/world/data/ChunkLightData.java102
-rw-r--r--src/ru/olamedia/olacraft/world/data/HeightMap.java42
-rw-r--r--src/ru/olamedia/olacraft/world/data/RegionData.java57
-rw-r--r--src/ru/olamedia/olacraft/world/data/SectorData.java33
-rw-r--r--src/ru/olamedia/olacraft/world/data/UnavailableDataException.java23
-rw-r--r--src/ru/olamedia/olacraft/world/data/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/world/dataProvider/AbstractChunkDataProvider.java60
-rw-r--r--src/ru/olamedia/olacraft/world/dataProvider/CachedChunkDataProvider.java70
-rw-r--r--src/ru/olamedia/olacraft/world/dataProvider/LocalChunkDataProvider.java218
-rw-r--r--src/ru/olamedia/olacraft/world/dataProvider/LocalRegionDataProvider.java57
-rw-r--r--src/ru/olamedia/olacraft/world/dataProvider/RemoteChunkDataProvider.java75
-rw-r--r--src/ru/olamedia/olacraft/world/dataProvider/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/world/generator/HeightMapGenerator.java157
-rw-r--r--src/ru/olamedia/olacraft/world/generator/ImprovedNoise.java61
-rw-r--r--src/ru/olamedia/olacraft/world/generator/Lerp.java27
-rw-r--r--src/ru/olamedia/olacraft/world/generator/RegionGenerator.java71
-rw-r--r--src/ru/olamedia/olacraft/world/generator/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/world/location/BlockLocation.java37
-rw-r--r--src/ru/olamedia/olacraft/world/location/ChunkLocation.java40
-rw-r--r--src/ru/olamedia/olacraft/world/location/RegionLocation.java29
-rw-r--r--src/ru/olamedia/olacraft/world/location/SectorLocation.java29
-rw-r--r--src/ru/olamedia/olacraft/world/location/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/world/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/world/provider/IChunkProvider.java8
-rw-r--r--src/ru/olamedia/olacraft/world/provider/WorldProvider.java130
-rw-r--r--src/ru/olamedia/olacraft/world/provider/blockData/BlockData.java5
-rw-r--r--src/ru/olamedia/olacraft/world/provider/blockData/EmptyBlockData.java5
-rw-r--r--src/ru/olamedia/olacraft/world/provider/blockData/IBlockData.java5
-rw-r--r--src/ru/olamedia/olacraft/world/provider/blockData/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/world/provider/package-info.java8
-rw-r--r--src/ru/olamedia/player/Player.java31
-rw-r--r--src/ru/olamedia/tasks/Task.java24
-rw-r--r--src/ru/olamedia/tasks/TaskManager.java18
-rw-r--r--src/ru/olamedia/tasks/package-info.java8
-rw-r--r--src/ru/olamedia/texture/ResourceUtil.java126
-rw-r--r--src/ru/olamedia/texture/TextureManager.java42
-rw-r--r--src/ru/olamedia/texture/package-info.java8
-rw-r--r--src/ru/olamedia/util/BufferUtils.java16
-rw-r--r--src/ru/olamedia/vbo/VBO.java29
-rw-r--r--src/ru/olamedia/vbo/package-info.java8
233 files changed, 18371 insertions, 0 deletions
diff --git a/src/libnoiseforjava/Interp.java b/src/libnoiseforjava/Interp.java
new file mode 100644
index 0000000..53ed56d
--- /dev/null
+++ b/src/libnoiseforjava/Interp.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava;
+
+public class Interp
+{
+
+ /// Performs cubic interpolation between two values bound between two other
+ /// values.
+ ///
+ /// @param n0 The value before the first value.
+ /// @param n1 The first value.
+ /// @param n2 The second value.
+ /// @param n3 The value after the second value.
+ /// @param a The alpha value.
+ ///
+ /// @returns The interpolated value.
+ ///
+ /// The alpha value should range from 0.0 to 1.0. If the alpha value is
+ /// 0.0, this function returns @a n1. If the alpha value is 1.0, this
+ /// function returns @a n2.
+ public static double cubicInterp (double n0, double n1, double n2, double n3,
+ double a)
+ {
+ double p = (n3 - n2) - (n0 - n1);
+ double q = (n0 - n1) - p;
+ double r = n2 - n0;
+ double s = n1;
+ return p * a * a * a + q * a * a + r * a + s;
+ }
+
+ /// Performs linear interpolation between two values.
+ ///
+ /// @param n0 The first value.
+ /// @param n1 The second value.
+ /// @param a The alpha value.
+ ///
+ /// @returns The interpolated value.
+ ///
+ /// The alpha value should range from 0.0 to 1.0. If the alpha value is
+ /// 0.0, this function returns @a n0. If the alpha value is 1.0, this
+ /// function returns @a n1.
+ public static double linearInterp (double n0, double n1, double a)
+ {
+ return ((1.0 - a) * n0) + (a * n1);
+ }
+
+ /// Maps a value onto a cubic S-curve.
+ ///
+ /// @param a The value to map onto a cubic S-curve.
+ ///
+ /// @returns The mapped value.
+ ///
+ /// @a a should range from 0.0 to 1.0.
+ ///
+ /// The derivative of a cubic S-curve is zero at @a a = 0.0 and @a a =
+ /// 1.0
+ public static double SCurve3 (double a)
+ {
+ return (a * a * (3.0 - 2.0 * a));
+ }
+
+ /// Maps a value onto a quintic S-curve.
+ ///
+ /// @param a The value to map onto a quintic S-curve.
+ ///
+ /// @returns The mapped value.
+ ///
+ /// @a a should range from 0.0 to 1.0.
+ ///
+ /// The first derivative of a quintic S-curve is zero at @a a = 0.0 and
+ /// @a a = 1.0
+ ///
+ /// The second derivative of a quintic S-curve is zero at @a a = 0.0 and
+ /// @a a = 1.0
+ static double SCurve5 (double a)
+ {
+ double a3 = a * a * a;
+ double a4 = a3 * a;
+ double a5 = a4 * a;
+ return (6.0 * a5) - (15.0 * a4) + (10.0 * a3);
+ }
+
+}
diff --git a/src/libnoiseforjava/Misc.java b/src/libnoiseforjava/Misc.java
new file mode 100644
index 0000000..11d2a7f
--- /dev/null
+++ b/src/libnoiseforjava/Misc.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava;
+
+public class Misc
+{
+ /// Clamps a value onto a clamping range.
+ ///
+ /// @param value The value to clamp.
+ /// @param lowerBound The lower bound of the clamping range.
+ /// @param upperBound The upper bound of the clamping range.
+ ///
+ /// @returns
+ /// - @a value if @a value lies between @a lowerBound and @a upperBound.
+ /// - @a lowerBound if @a value is less than @a lowerBound.
+ /// - @a upperBound if @a value is greater than @a upperBound.
+ ///
+ /// This function does not modify any parameters.
+ public static int ClampValue (int value, int lowerBound, int upperBound)
+ {
+ if (value < lowerBound)
+ return lowerBound;
+ else if (value > upperBound)
+ return upperBound;
+ else
+ return value;
+ }
+}
diff --git a/src/libnoiseforjava/NoiseGen.java b/src/libnoiseforjava/NoiseGen.java
new file mode 100644
index 0000000..fd98be3
--- /dev/null
+++ b/src/libnoiseforjava/NoiseGen.java
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava;
+
+public class NoiseGen
+{
+
+ /// Enumerates the noise quality.
+ public enum NoiseQuality
+ {
+
+ /// Generates coherent noise quickly. When a coherent-noise function with
+ /// this quality setting is used to generate a bump-map image, there are
+ /// noticeable "creasing" artifacts in the resulting image. This is
+ /// because the derivative of that function is discontinuous at integer
+ /// boundaries.
+ QUALITY_FAST,
+
+ /// Generates standard-quality coherent noise. When a coherent-noise
+ /// function with this quality setting is used to generate a bump-map
+ /// image, there are some minor "creasing" artifacts in the resulting
+ /// image. This is because the second derivative of that function is
+ /// discontinuous at integer boundaries.
+ QUALITY_STD,
+
+ /// Generates the best-quality coherent noise. When a coherent-noise
+ /// function with this quality setting is used to generate a bump-map
+ /// image, there are no "creasing" artifacts in the resulting image. This
+ /// is because the first and second derivatives of that function are
+ /// continuous at integer boundaries.
+ QUALITY_BEST
+ }
+
+ static final int X_NOISE_GEN = 1619;
+ static final int Y_NOISE_GEN = 31337;
+ static final int Z_NOISE_GEN = 6971;
+ static final int SEED_NOISE_GEN = 1013;
+ static final int SHIFT_NOISE_GEN = 8;
+
+ public static double GradientCoherentNoise3D (double x, double y, double z, int seed,
+ NoiseQuality noiseQuality)
+ {
+
+ // Create a unit-length cube aligned along an integer boundary. This cube
+ // surrounds the input point.
+ int x0 = (x > 0.0? (int)x: (int)x - 1);
+ int x1 = x0 + 1;
+ int y0 = (y > 0.0? (int)y: (int)y - 1);
+ int y1 = y0 + 1;
+ int z0 = (z > 0.0? (int)z: (int)z - 1);
+ int z1 = z0 + 1;
+
+ // Map the difference between the coordinates of the input value and the
+ // coordinates of the cube's outer-lower-left vertex onto an S-curve.
+ double xs = 0, ys = 0, zs = 0;
+ switch (noiseQuality)
+ {
+ case QUALITY_FAST:
+ xs = (x - (double)x0);
+ ys = (y - (double)y0);
+ zs = (z - (double)z0);
+ break;
+ case QUALITY_STD:
+ xs = Interp.SCurve3 (x - (double)x0);
+ ys = Interp.SCurve3 (y - (double)y0);
+ zs = Interp.SCurve3 (z - (double)z0);
+ break;
+ case QUALITY_BEST:
+ xs = Interp.SCurve5 (x - (double)x0);
+ ys = Interp.SCurve5 (y - (double)y0);
+ zs = Interp.SCurve5 (z - (double)z0);
+ break;
+ }
+
+ // Now calculate the noise values at each vertex of the cube. To generate
+ // the coherent-noise value at the input point, interpolate these eight
+ // noise values using the S-curve value as the interpolant (trilinear
+ // interpolation.)
+ double n0, n1, ix0, ix1, iy0, iy1;
+ n0 = GradientNoise3D (x, y, z, x0, y0, z0, seed);
+ n1 = GradientNoise3D (x, y, z, x1, y0, z0, seed);
+ ix0 = Interp.linearInterp (n0, n1, xs);
+ n0 = GradientNoise3D (x, y, z, x0, y1, z0, seed);
+ n1 = GradientNoise3D (x, y, z, x1, y1, z0, seed);
+ ix1 = Interp.linearInterp (n0, n1, xs);
+ iy0 = Interp.linearInterp (ix0, ix1, ys);
+ n0 = GradientNoise3D (x, y, z, x0, y0, z1, seed);
+ n1 = GradientNoise3D (x, y, z, x1, y0, z1, seed);
+ ix0 = Interp.linearInterp (n0, n1, xs);
+ n0 = GradientNoise3D (x, y, z, x0, y1, z1, seed);
+ n1 = GradientNoise3D (x, y, z, x1, y1, z1, seed);
+ ix1 = Interp.linearInterp (n0, n1, xs);
+ iy1 = Interp.linearInterp (ix0, ix1, ys);
+
+ return Interp.linearInterp (iy0, iy1, zs);
+ }
+
+ public static double GradientNoise3D (double fx, double fy, double fz, int ix,
+ int iy, int iz, int seed)
+ {
+
+ //VectorTable vectorTable = new VectorTable();
+ // Randomly generate a gradient vector given the integer coordinates of the
+ // input value. This implementation generates a random number and uses it
+ // as an index into a normalized-vector lookup table.
+ int vectorIndex = (X_NOISE_GEN * ix
+ + Y_NOISE_GEN * iy
+ + Z_NOISE_GEN * iz
+ + SEED_NOISE_GEN * seed)
+ & 0xffffffff;
+
+ vectorIndex ^= (vectorIndex >> SHIFT_NOISE_GEN);
+ vectorIndex &= 0xff;
+
+ double xvGradient = VectorTable.getRandomVectors(vectorIndex, 0);
+ double yvGradient = VectorTable.getRandomVectors(vectorIndex, 1);
+ double zvGradient = VectorTable.getRandomVectors(vectorIndex, 2);
+ // array size too large when using this original, changed to above for all 3
+ // double zvGradient = vectorTable.getRandomVectors(vectorIndex << 2, 2);
+
+ // Set up us another vector equal to the distance between the two vectors
+ // passed to this function.
+ double xvPoint = (fx - (double)ix);
+ double yvPoint = (fy - (double)iy);
+ double zvPoint = (fz - (double)iz);
+
+ // Now compute the dot product of the gradient vector with the distance
+ // vector. The resulting value is gradient noise. Apply a scaling value
+ // so that this noise value ranges from -1.0 to 1.0.
+ return ((xvGradient * xvPoint)
+ + (yvGradient * yvPoint)
+ + (zvGradient * zvPoint)) * 2.12;
+ }
+
+ public static int IntValueNoise3D (int x, int y, int z, int seed)
+ {
+ // All constants are primes and must remain prime in order for this noise
+ // function to work correctly.
+ int n = (X_NOISE_GEN * x
+ + Y_NOISE_GEN * y
+ + Z_NOISE_GEN * z
+ + SEED_NOISE_GEN * seed)
+ & 0x7fffffff;
+
+ n = (n >> 13) ^ n;
+
+ return (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
+ }
+
+ public static double ValueCoherentNoise3D (double x, double y, double z, int seed,
+ NoiseQuality noiseQuality)
+ {
+ // Create a unit-length cube aligned along an integer boundary. This cube
+ // surrounds the input point.
+ int x0 = (x > 0.0? (int)x: (int)x - 1);
+ int x1 = x0 + 1;
+ int y0 = (y > 0.0? (int)y: (int)y - 1);
+ int y1 = y0 + 1;
+ int z0 = (z > 0.0? (int)z: (int)z - 1);
+ int z1 = z0 + 1;
+
+ // Map the difference between the coordinates of the input value and the
+ // coordinates of the cube's outer-lower-left vertex onto an S-curve.
+ double xs = 0, ys = 0, zs = 0;
+ switch (noiseQuality)
+ {
+ case QUALITY_FAST:
+ xs = (x - (double)x0);
+ ys = (y - (double)y0);
+ zs = (z - (double)z0);
+ break;
+ case QUALITY_STD:
+ xs = Interp.SCurve3 (x - (double)x0);
+ ys = Interp.SCurve3 (y - (double)y0);
+ zs = Interp.SCurve3 (z - (double)z0);
+ break;
+ case QUALITY_BEST:
+ xs = Interp.SCurve5 (x - (double)x0);
+ ys = Interp.SCurve5 (y - (double)y0);
+ zs = Interp.SCurve5 (z - (double)z0);
+ break;
+ }
+
+ // Now calculate the noise values at each vertex of the cube. To generate
+ // the coherent-noise value at the input point, interpolate these eight
+ // noise values using the S-curve value as the interpolant (trilinear
+ // interpolation.)
+ double n0, n1, ix0, ix1, iy0, iy1;
+ n0 = ValueNoise3D (x0, y0, z0, seed);
+ n1 = ValueNoise3D (x1, y0, z0, seed);
+ ix0 = Interp.linearInterp (n0, n1, xs);
+ n0 = ValueNoise3D (x0, y1, z0, seed);
+ n1 = ValueNoise3D (x1, y1, z0, seed);
+ ix1 = Interp.linearInterp (n0, n1, xs);
+ iy0 = Interp.linearInterp (ix0, ix1, ys);
+ n0 = ValueNoise3D (x0, y0, z1, seed);
+ n1 = ValueNoise3D (x1, y0, z1, seed);
+ ix0 = Interp.linearInterp (n0, n1, xs);
+ n0 = ValueNoise3D (x0, y1, z1, seed);
+ n1 = ValueNoise3D (x1, y1, z1, seed);
+ ix1 = Interp.linearInterp (n0, n1, xs);
+ iy1 = Interp.linearInterp (ix0, ix1, ys);
+
+ return Interp.linearInterp (iy0, iy1, zs);
+ }
+
+ public static double ValueNoise3D (int x, int y, int z, int seed)
+ {
+ return 1.0 - ((double)IntValueNoise3D (x, y, z, seed) / 1073741824.0);
+ }
+
+ /// Modifies a floating-point value so that it can be stored in a
+ /// int32 variable.
+ ///
+ /// @param n A floating-point number.
+ ///
+ /// @returns The modified floating-point number.
+ ///
+ /// This function does not modify @a n.
+ ///
+ /// In libnoise, the noise-generating algorithms are all integer-based;
+ /// they use variables of type int32. Before calling a noise
+ /// function, pass the @a x, @a y, and @a z coordinates to this function to
+ /// ensure that these coordinates can be cast to a int32 value.
+ ///
+ /// Although you could do a straight cast from double to int32, the
+ /// resulting value may differ between platforms. By using this function,
+ /// you ensure that the resulting value is identical between platforms.
+ public static double MakeInt32Range (double n) {
+ if (n >= 1073741824.0)
+ return (2.0 * (n % 1073741824.0)) - 1073741824.0;
+ else if (n <= -1073741824.0)
+ return (2.0 * (n % 1073741824.0)) + 1073741824.0;
+ else
+ return n;
+ }
+
+}
diff --git a/src/libnoiseforjava/VectorTable.java b/src/libnoiseforjava/VectorTable.java
new file mode 100644
index 0000000..7b904a2
--- /dev/null
+++ b/src/libnoiseforjava/VectorTable.java
@@ -0,0 +1,309 @@
+/*
+ * This file is in the public domain
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava;
+
+public class VectorTable
+{
+ // A table of 256 random normalized vectors. Each row is an (x, y, z, 0)
+ // coordinate. The 0 is used as padding so we can use bit shifts to index
+ // any row in the table. These vectors have an even statistical
+ // distribution, which improves the quality of the coherent noise
+ // generated by these vectors. For more information, see "GPU Gems",
+ // Chapter 5 - Implementing Improved Perlin Noise by Ken Perlin,
+ // specifically page 76.
+
+ private static double[][] randomVectors = {
+ {-0.763874, -0.596439, -0.246489, 0.0},
+ {0.396055, 0.904518, -0.158073, 0.0},
+ {-0.499004, -0.8665, -0.0131631, 0.0},
+ {0.468724, -0.824756, 0.316346, 0.0},
+ {0.829598, 0.43195, 0.353816, 0.0},
+ {-0.454473, 0.629497, -0.630228, 0.0},
+ {-0.162349, -0.869962, -0.465628, 0.0},
+ {0.932805, 0.253451, 0.256198, 0.0},
+ {-0.345419, 0.927299, -0.144227, 0.0},
+ {-0.715026, -0.293698, -0.634413, 0.0},
+ {-0.245997, 0.717467, -0.651711, 0.0},
+ {-0.967409, -0.250435, -0.037451, 0.0},
+ {0.901729, 0.397108, -0.170852, 0.0},
+ {0.892657, -0.0720622, -0.444938, 0.0},
+ {0.0260084, -0.0361701, 0.999007, 0.0},
+ {0.949107, -0.19486, 0.247439, 0.0},
+ {0.471803, -0.807064, -0.355036, 0.0},
+ {0.879737, 0.141845, 0.453809, 0.0},
+ {0.570747, 0.696415, 0.435033, 0.0},
+ {-0.141751, -0.988233, -0.0574584, 0.0},
+ {-0.58219, -0.0303005, 0.812488, 0.0},
+ {-0.60922, 0.239482, -0.755975, 0.0},
+ {0.299394, -0.197066, -0.933557, 0.0},
+ {-0.851615, -0.220702, -0.47544, 0.0},
+ {0.848886, 0.341829, -0.403169, 0.0},
+ {-0.156129, -0.687241, 0.709453, 0.0},
+ {-0.665651, 0.626724, 0.405124, 0.0},
+ {0.595914, -0.674582, 0.43569, 0.0},
+ {0.171025, -0.509292, 0.843428, 0.0},
+ {0.78605, 0.536414, -0.307222, 0.0},
+ {0.18905, -0.791613, 0.581042, 0.0},
+ {-0.294916, 0.844994, 0.446105, 0.0},
+ {0.342031, -0.58736, -0.7335, 0.0},
+ {0.57155, 0.7869, 0.232635, 0.0},
+ {0.885026, -0.408223, 0.223791, 0.0},
+ {-0.789518, 0.571645, 0.223347, 0.0},
+ {0.774571, 0.31566, 0.548087, 0.0},
+ {-0.79695, -0.0433603, -0.602487, 0.0},
+ {-0.142425, -0.473249, -0.869339, 0.0},
+ {-0.0698838, 0.170442, 0.982886, 0.0},
+ {0.687815, -0.484748, 0.540306, 0.0},
+ {0.543703, -0.534446, -0.647112, 0.0},
+ {0.97186, 0.184391, -0.146588, 0.0},
+ {0.707084, 0.485713, -0.513921, 0.0},
+ {0.942302, 0.331945, 0.043348, 0.0},
+ {0.499084, 0.599922, 0.625307, 0.0},
+ {-0.289203, 0.211107, 0.9337, 0.0},
+ {0.412433, -0.71667, -0.56239, 0.0},
+ {0.87721, -0.082816, 0.47291, 0.0},
+ {-0.420685, -0.214278, 0.881538, 0.0},
+ {0.752558, -0.0391579, 0.657361, 0.0},
+ {0.0765725, -0.996789, 0.0234082, 0.0},
+ {-0.544312, -0.309435, -0.779727, 0.0},
+ {-0.455358, -0.415572, 0.787368, 0.0},
+ {-0.874586, 0.483746, 0.0330131, 0.0},
+ {0.245172, -0.0838623, 0.965846, 0.0},
+ {0.382293, -0.432813, 0.81641, 0.0},
+ {-0.287735, -0.905514, 0.311853, 0.0},
+ {-0.667704, 0.704955, -0.239186, 0.0},
+ {0.717885, -0.464002, -0.518983, 0.0},
+ {0.976342, -0.214895, 0.0240053, 0.0},
+ {-0.0733096, -0.921136, 0.382276, 0.0},
+ {-0.986284, 0.151224, -0.0661379, 0.0},
+ {-0.899319, -0.429671, 0.0812908, 0.0},
+ {0.652102, -0.724625, 0.222893, 0.0},
+ {0.203761, 0.458023, -0.865272, 0.0},
+ {-0.030396, 0.698724, -0.714745, 0.0},
+ {-0.460232, 0.839138, 0.289887, 0.0},
+ {-0.0898602, 0.837894, 0.538386, 0.0},
+ {-0.731595, 0.0793784, 0.677102, 0.0},
+ {-0.447236, -0.788397, 0.422386, 0.0},
+ {0.186481, 0.645855, -0.740335, 0.0},
+ {-0.259006, 0.935463, 0.240467, 0.0},
+ {0.445839, 0.819655, -0.359712, 0.0},
+ {0.349962, 0.755022, -0.554499, 0.0},
+ {-0.997078, -0.0359577, 0.0673977, 0.0},
+ {-0.431163, -0.147516, -0.890133, 0.0},
+ {0.299648, -0.63914, 0.708316, 0.0},
+ {0.397043, 0.566526, -0.722084, 0.0},
+ {-0.502489, 0.438308, -0.745246, 0.0},
+ {0.0687235, 0.354097, 0.93268, 0.0},
+ {-0.0476651, -0.462597, 0.885286, 0.0},
+ {-0.221934, 0.900739, -0.373383, 0.0},
+ {-0.956107, -0.225676, 0.186893, 0.0},
+ {-0.187627, 0.391487, -0.900852, 0.0},
+ {-0.224209, -0.315405, 0.92209, 0.0},
+ {-0.730807, -0.537068, 0.421283, 0.0},
+ {-0.0353135, -0.816748, 0.575913, 0.0},
+ {-0.941391, 0.176991, -0.287153, 0.0},
+ {-0.154174, 0.390458, 0.90762, 0.0},
+ {-0.283847, 0.533842, 0.796519, 0.0},
+ {-0.482737, -0.850448, 0.209052, 0.0},
+ {-0.649175, 0.477748, 0.591886, 0.0},
+ {0.885373, -0.405387, -0.227543, 0.0},
+ {-0.147261, 0.181623, -0.972279, 0.0},
+ {0.0959236, -0.115847, -0.988624, 0.0},
+ {-0.89724, -0.191348, 0.397928, 0.0},
+ {0.903553, -0.428461, -0.00350461, 0.0},
+ {0.849072, -0.295807, -0.437693, 0.0},
+ {0.65551, 0.741754, -0.141804, 0.0},
+ {0.61598, -0.178669, 0.767232, 0.0},
+ {0.0112967, 0.932256, -0.361623, 0.0},
+ {-0.793031, 0.258012, 0.551845, 0.0},
+ {0.421933, 0.454311, 0.784585, 0.0},
+ {-0.319993, 0.0401618, -0.946568, 0.0},
+ {-0.81571, 0.551307, -0.175151, 0.0},
+ {-0.377644, 0.00322313, 0.925945, 0.0},
+ {0.129759, -0.666581, -0.734052, 0.0},
+ {0.601901, -0.654237, -0.457919, 0.0},
+ {-0.927463, -0.0343576, -0.372334, 0.0},
+ {-0.438663, -0.868301, -0.231578, 0.0},
+ {-0.648845, -0.749138, -0.133387, 0.0},
+ {0.507393, -0.588294, 0.629653, 0.0},
+ {0.726958, 0.623665, 0.287358, 0.0},
+ {0.411159, 0.367614, -0.834151, 0.0},
+ {0.806333, 0.585117, -0.0864016, 0.0},
+ {0.263935, -0.880876, 0.392932, 0.0},
+ {0.421546, -0.201336, 0.884174, 0.0},
+ {-0.683198, -0.569557, -0.456996, 0.0},
+ {-0.117116, -0.0406654, -0.992285, 0.0},
+ {-0.643679, -0.109196, -0.757465, 0.0},
+ {-0.561559, -0.62989, 0.536554, 0.0},
+ {0.0628422, 0.104677, -0.992519, 0.0},
+ {0.480759, -0.2867, -0.828658, 0.0},
+ {-0.228559, -0.228965, -0.946222, 0.0},
+ {-0.10194, -0.65706, -0.746914, 0.0},
+ {0.0689193, -0.678236, 0.731605, 0.0},
+ {0.401019, -0.754026, 0.52022, 0.0},
+ {-0.742141, 0.547083, -0.387203, 0.0},
+ {-0.00210603, -0.796417, -0.604745, 0.0},
+ {0.296725, -0.409909, -0.862513, 0.0},
+ {-0.260932, -0.798201, 0.542945, 0.0},
+ {-0.641628, 0.742379, 0.192838, 0.0},
+ {-0.186009, -0.101514, 0.97729, 0.0},
+ {0.106711, -0.962067, 0.251079, 0.0},
+ {-0.743499, 0.30988, -0.592607, 0.0},
+ {-0.795853, -0.605066, -0.0226607, 0.0},
+ {-0.828661, -0.419471, -0.370628, 0.0},
+ {0.0847218, -0.489815, -0.8677, 0.0},
+ {-0.381405, 0.788019, -0.483276, 0.0},
+ {0.282042, -0.953394, 0.107205, 0.0},
+ {0.530774, 0.847413, 0.0130696, 0.0},
+ {0.0515397, 0.922524, 0.382484, 0.0},
+ {-0.631467, -0.709046, 0.313852, 0.0},
+ {0.688248, 0.517273, 0.508668, 0.0},
+ {0.646689, -0.333782, -0.685845, 0.0},
+ {-0.932528, -0.247532, -0.262906, 0.0},
+ {0.630609, 0.68757, -0.359973, 0.0},
+ {0.577805, -0.394189, 0.714673, 0.0},
+ {-0.887833, -0.437301, -0.14325, 0.0},
+ {0.690982, 0.174003, 0.701617, 0.0},
+ {-0.866701, 0.0118182, 0.498689, 0.0},
+ {-0.482876, 0.727143, 0.487949, 0.0},
+ {-0.577567, 0.682593, -0.447752, 0.0},
+ {0.373768, 0.0982991, 0.922299, 0.0},
+ {0.170744, 0.964243, -0.202687, 0.0},
+ {0.993654, -0.035791, -0.106632, 0.0},
+ {0.587065, 0.4143, -0.695493, 0.0},
+ {-0.396509, 0.26509, -0.878924, 0.0},
+ {-0.0866853, 0.83553, -0.542563, 0.0},
+ {0.923193, 0.133398, -0.360443, 0.0},
+ {0.00379108, -0.258618, 0.965972, 0.0},
+ {0.239144, 0.245154, -0.939526, 0.0},
+ {0.758731, -0.555871, 0.33961, 0.0},
+ {0.295355, 0.309513, 0.903862, 0.0},
+ {0.0531222, -0.91003, -0.411124, 0.0},
+ {0.270452, 0.0229439, -0.96246, 0.0},
+ {0.563634, 0.0324352, 0.825387, 0.0},
+ {0.156326, 0.147392, 0.976646, 0.0},
+ {-0.0410141, 0.981824, 0.185309, 0.0},
+ {-0.385562, -0.576343, -0.720535, 0.0},
+ {0.388281, 0.904441, 0.176702, 0.0},
+ {0.945561, -0.192859, -0.262146, 0.0},
+ {0.844504, 0.520193, 0.127325, 0.0},
+ {0.0330893, 0.999121, -0.0257505, 0.0},
+ {-0.592616, -0.482475, -0.644999, 0.0},
+ {0.539471, 0.631024, -0.557476, 0.0},
+ {0.655851, -0.027319, -0.754396, 0.0},
+ {0.274465, 0.887659, 0.369772, 0.0},
+ {-0.123419, 0.975177, -0.183842, 0.0},
+ {-0.223429, 0.708045, 0.66989, 0.0},
+ {-0.908654, 0.196302, 0.368528, 0.0},
+ {-0.95759, -0.00863708, 0.288005, 0.0},
+ {0.960535, 0.030592, 0.276472, 0.0},
+ {-0.413146, 0.907537, 0.0754161, 0.0},
+ {-0.847992, 0.350849, -0.397259, 0.0},
+ {0.614736, 0.395841, 0.68221, 0.0},
+ {-0.503504, -0.666128, -0.550234, 0.0},
+ {-0.268833, -0.738524, -0.618314, 0.0},
+ {0.792737, -0.60001, -0.107502, 0.0},
+ {-0.637582, 0.508144, -0.579032, 0.0},
+ {0.750105, 0.282165, -0.598101, 0.0},
+ {-0.351199, -0.392294, -0.850155, 0.0},
+ {0.250126, -0.960993, -0.118025, 0.0},
+ {-0.732341, 0.680909, -0.0063274, 0.0},
+ {-0.760674, -0.141009, 0.633634, 0.0},
+ {0.222823, -0.304012, 0.926243, 0.0},
+ {0.209178, 0.505671, 0.836984, 0.0},
+ {0.757914, -0.56629, -0.323857, 0.0},
+ {-0.782926, -0.339196, 0.52151, 0.0},
+ {-0.462952, 0.585565, 0.665424, 0.0},
+ {0.61879, 0.194119, -0.761194, 0.0},
+ {0.741388, -0.276743, 0.611357, 0.0},
+ {0.707571, 0.702621, 0.0752872, 0.0},
+ {0.156562, 0.819977, 0.550569, 0.0},
+ {-0.793606, 0.440216, 0.42, 0.0},
+ {0.234547, 0.885309, -0.401517, 0.0},
+ {0.132598, 0.80115, -0.58359, 0.0},
+ {-0.377899, -0.639179, 0.669808, 0.0},
+ {-0.865993, -0.396465, 0.304748, 0.0},
+ {-0.624815, -0.44283, 0.643046, 0.0},
+ {-0.485705, 0.825614, -0.287146, 0.0},
+ {-0.971788, 0.175535, 0.157529, 0.0},
+ {-0.456027, 0.392629, 0.798675, 0.0},
+ {-0.0104443, 0.521623, -0.853112, 0.0},
+ {-0.660575, -0.74519, 0.091282, 0.0},
+ {-0.0157698, -0.307475, -0.951425, 0.0},
+ {-0.603467, -0.250192, 0.757121, 0.0},
+ {0.506876, 0.25006, 0.824952, 0.0},
+ {0.255404, 0.966794, 0.00884498, 0.0},
+ {0.466764, -0.874228, -0.133625, 0.0},
+ {0.475077, -0.0682351, -0.877295, 0.0},
+ {-0.224967, -0.938972, -0.260233, 0.0},
+ {-0.377929, -0.814757, -0.439705, 0.0},
+ {-0.305847, 0.542333, -0.782517, 0.0},
+ {0.26658, -0.902905, -0.337191, 0.0},
+ {0.0275773, 0.322158, -0.946284, 0.0},
+ {0.0185422, 0.716349, 0.697496, 0.0},
+ {-0.20483, 0.978416, 0.0273371, 0.0},
+ {-0.898276, 0.373969, 0.230752, 0.0},
+ {-0.00909378, 0.546594, 0.837349, 0.0},
+ {0.6602, -0.751089, 0.000959236, 0.0},
+ {0.855301, -0.303056, 0.420259, 0.0},
+ {0.797138, 0.0623013, -0.600574, 0.0},
+ {0.48947, -0.866813, 0.0951509, 0.0},
+ {0.251142, 0.674531, 0.694216, 0.0},
+ {-0.578422, -0.737373, -0.348867, 0.0},
+ {-0.254689, -0.514807, 0.818601, 0.0},
+ {0.374972, 0.761612, 0.528529, 0.0},
+ {0.640303, -0.734271, -0.225517, 0.0},
+ {-0.638076, 0.285527, 0.715075, 0.0},
+ {0.772956, -0.15984, -0.613995, 0.0},
+ {0.798217, -0.590628, 0.118356, 0.0},
+ {-0.986276, -0.0578337, -0.154644, 0.0},
+ {-0.312988, -0.94549, 0.0899272, 0.0},
+ {-0.497338, 0.178325, 0.849032, 0.0},
+ {-0.101136, -0.981014, 0.165477, 0.0},
+ {-0.521688, 0.0553434, -0.851339, 0.0},
+ {-0.786182, -0.583814, 0.202678, 0.0},
+ {-0.565191, 0.821858, -0.0714658, 0.0},
+ {0.437895, 0.152598, -0.885981, 0.0},
+ {-0.92394, 0.353436, -0.14635, 0.0},
+ {0.212189, -0.815162, -0.538969, 0.0},
+ {-0.859262, 0.143405, -0.491024, 0.0},
+ {0.991353, 0.112814, 0.0670273, 0.0},
+ {0.0337884, -0.979891, -0.196654, 0.0}
+ };
+
+ private VectorTable()
+ {
+
+ }
+
+ public static double getRandomVectors(int a, int b)
+ {
+ return randomVectors[a][b];
+ }
+
+
+
+}
+
diff --git a/src/libnoiseforjava/exception/ExceptionInvalidParam.java b/src/libnoiseforjava/exception/ExceptionInvalidParam.java
new file mode 100644
index 0000000..f79bf91
--- /dev/null
+++ b/src/libnoiseforjava/exception/ExceptionInvalidParam.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.exception;
+
+public class ExceptionInvalidParam extends Exception
+{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 5603051793321603318L;
+
+ public ExceptionInvalidParam(String message)
+ {
+ super(message);
+ }
+
+}
+
diff --git a/src/libnoiseforjava/exception/ExceptionNoModule.java b/src/libnoiseforjava/exception/ExceptionNoModule.java
new file mode 100644
index 0000000..c6dccd6
--- /dev/null
+++ b/src/libnoiseforjava/exception/ExceptionNoModule.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.exception;
+
+public class ExceptionNoModule extends Exception
+{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -4820882012470782847L;
+
+ public ExceptionNoModule(String message)
+ {
+ super(message);
+ }
+
+}
diff --git a/src/libnoiseforjava/model/Cylinder.java b/src/libnoiseforjava/model/Cylinder.java
new file mode 100644
index 0000000..04647b7
--- /dev/null
+++ b/src/libnoiseforjava/model/Cylinder.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.model;
+
+import libnoiseforjava.module.ModuleBase;
+
+public class Cylinder
+{
+ /// Model that defines the surface of a cylinder.
+ ///
+ /// @image html modelcylinder.png
+ ///
+ /// This model returns an output value from a noise module given the
+ /// coordinates of an input value located on the surface of a cylinder.
+ ///
+ /// To generate an output value, pass the (angle, height) coordinates of
+ /// an input value to the GetValue() method.
+ ///
+ /// This model is useful for creating:
+ /// - seamless textures that can be mapped onto a cylinder
+ ///
+ /// This cylinder has a radius of 1.0 unit and has infinite height. It is
+ /// oriented along the @a y axis. Its center is located at the origin.
+
+
+
+ /// A pointer to the noise module used to generate the output values.
+ ModuleBase module;
+
+ public Cylinder ()
+ {
+ module = new ModuleBase(1);
+ }
+
+ Cylinder (ModuleBase module)
+ {
+ this.module = module;
+ }
+
+ /// Returns the output value from the noise module given the
+ /// (angle, height) coordinates of the specified input value located
+ /// on the surface of the cylinder.
+ ///
+ /// @param angle The angle around the cylinder's center, in degrees.
+ /// @param height The height along the @a y axis.
+ ///
+ /// @returns The output value from the noise module.
+ ///
+ /// @pre A noise module was passed to the setModule() method.
+ ///
+ /// This output value is generated by the noise module passed to the
+ /// SetModule() method.
+ ///
+ /// This cylinder has a radius of 1.0 unit and has infinite height.
+ /// It is oriented along the @a y axis. Its center is located at the
+ /// origin.
+ public double getValue (double angle, double height)
+ {
+ assert (module != null);
+
+ double x, y, z;
+ x = Math.cos(Math.toRadians(angle));
+ y = height;
+ z = Math.sin(Math.toRadians(angle));
+ return module.getValue (x, y, z);
+ }
+
+ /// Returns the noise module that is used to generate the output
+ /// values.
+ ///
+ /// @returns A reference to the noise module.
+ ///
+ /// @pre A noise module was passed to the setModule() method.
+ public ModuleBase getModule ()
+ {
+ assert (module != null);
+ return module;
+ }
+
+ /// Sets the noise module that is used to generate the output values.
+ ///
+ /// @param module The noise module that is used to generate the output
+ /// values.
+ ///
+ /// This noise module must exist for the lifetime of this object,
+ /// until you pass a new noise module to this method.
+ public void setModule (ModuleBase module)
+ {
+ this.module = module;
+ }
+
+}
diff --git a/src/libnoiseforjava/model/Line.java b/src/libnoiseforjava/model/Line.java
new file mode 100644
index 0000000..7509f90
--- /dev/null
+++ b/src/libnoiseforjava/model/Line.java
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.model;
+
+import libnoiseforjava.module.ModuleBase;
+
+public class Line
+{
+
+ /// Model that defines the displacement of a line segment.
+ ///
+ /// This model returns an output value from a noise module given the
+ /// one-dimensional coordinate of an input value located on a line
+ /// segment, which can be used as displacements.
+ ///
+ /// This class is useful for creating:
+ /// - roads and rivers
+ /// - disaffected college students
+ ///
+ /// To generate an output value, pass an input value between 0.0 and 1.0
+ /// to the getValue() method. 0.0 represents the start position of the
+ /// line segment and 1.0 represents the end position of the line segment.
+
+
+ /// A flag that specifies whether the value is to be attenuated
+ /// (moved toward 0.0) as the ends of the line segment are approached.
+ boolean attenuate;
+
+ /// A pointer to the noise module used to generate the output values.
+ ModuleBase module;
+
+ /// @a x coordinate of the start of the line segment.
+ double x0;
+
+ /// @a x coordinate of the end of the line segment.
+ double x1;
+
+ /// @a y coordinate of the start of the line segment.
+ double y0;
+
+ /// @a y coordinate of the end of the line segment.
+ double y1;
+
+ /// @a z coordinate of the start of the line segment.
+ double z0;
+
+ /// @a z coordinate of the end of the line segment.
+ double z1;
+
+ Line ()
+ {
+ attenuate = true;
+ module = new ModuleBase(1);
+ x0 = 0.0;
+ x1 = 1.0;
+ y0 = 0.0;
+ y1 = 1.0;
+ z0 = 0.0;
+ z1 = 1.0;
+ }
+
+ Line (ModuleBase module)
+ {
+ attenuate = true;
+ this.module = module;
+ x0 = 0.0;
+ x1 = 1.0;
+ y0 = 0.0;
+ y1 = 1.0;
+ z0 = 0.0;
+ z1 = 1.0;
+ }
+
+ /// Returns the output value from the noise module given the
+ /// one-dimensional coordinate of the specified input value located
+ /// on the line segment.
+ ///
+ /// @param p The distance along the line segment (ranges from 0.0
+ /// to 1.0)
+ ///
+ /// @returns The output value from the noise module.
+ ///
+ /// @pre A noise module was passed to the setModule() method.
+ /// @pre The start and end points of the line segment were specified.
+ ///
+ /// The output value is generated by the noise module passed to the
+ /// setModule() method. This value may be attenuated (moved toward
+ /// 0.0) as @a p approaches either end of the line segment; this is
+ /// the default behavior.
+ ///
+ /// If the value is not to be attenuated, @a p can safely range
+ /// outside the 0.0 to 1.0 range; the output value will be
+ /// extrapolated along the line that this segment is part of.
+ public double getValue (double p)
+ {
+ assert (module != null);
+
+ double x = (x1 - x0) * p + x0;
+ double y = (y1 - y0) * p + y0;
+ double z = (z1 - z0) * p + z0;
+ double value = module.getValue (x, y, z);
+
+ if (attenuate)
+ return p * (1.0 - p) * 4 * value;
+ else
+ return value;
+ }
+
+ /// Returns a flag indicating whether the output value is to be
+ /// attenuated (moved toward 0.0) as the ends of the line segment are
+ /// approached by the input value.
+ ///
+ /// @returns
+ /// - @a true if the value is to be attenuated
+ /// - @a false if not.
+ public boolean getAttenuate ()
+ {
+ return attenuate;
+ }
+
+ /// Returns the noise module that is used to generate the output
+ /// values.
+ ///
+ /// @returns A reference to the noise module.
+ ///
+ /// @pre A noise module was passed to the setModule() method.
+ public ModuleBase getModule ()
+ {
+ assert (module != null);
+ return module;
+ }
+
+ /// Sets a flag indicating that the output value is to be attenuated
+ /// (moved toward 0.0) as the ends of the line segment are approached.
+ ///
+ /// @param att A flag that specifies whether the output value is to be
+ /// attenuated.
+ public void setAttenuate (boolean att)
+ {
+ attenuate = att;
+ }
+
+ /// Sets the position ( @a x, @a y, @a z ) of the end of the line
+ /// segment to choose values along.
+ ///
+ /// @param x x coordinate of the end position.
+ /// @param y y coordinate of the end position.
+ /// @param z z coordinate of the end position.
+ public void setEndPoint (double x, double y, double z)
+ {
+ x1 = x;
+ y1 = y;
+ z1 = z;
+ }
+
+ /// Sets the noise module that is used to generate the output values.
+ ///
+ /// @param module The noise module that is used to generate the output
+ /// values.
+ ///
+ /// This noise module must exist for the lifetime of this object,
+ /// until you pass a new noise module to this method.
+ public void setModule (ModuleBase module)
+ {
+ this.module = module;
+ }
+
+ /// Sets the position ( @a x, @a y, @a z ) of the start of the line
+ /// segment to choose values along.
+ ///
+ /// @param x x coordinate of the start position.
+ /// @param y y coordinate of the start position.
+ /// @param z z coordinate of the start position.
+ public void setStartPoint (double x, double y, double z)
+ {
+ x0 = x;
+ y0 = y;
+ z0 = z;
+ }
+
+ public double getX0()
+ {
+ return x0;
+ }
+
+ public double getX1()
+ {
+ return x1;
+ }
+
+ public double getY0()
+ {
+ return y0;
+ }
+
+ public double getY1()
+ {
+ return y1;
+ }
+
+ public double getZ0()
+ {
+ return z0;
+ }
+
+ public double getZ1()
+ {
+ return z1;
+ }
+
+ public void setX0(double x0)
+ {
+ this.x0 = x0;
+ }
+
+ public void setX1(double x1)
+ {
+ this.x1 = x1;
+ }
+
+ public void setY0(double y0)
+ {
+ this.y0 = y0;
+ }
+
+ public void setY1(double y1)
+ {
+ this.y1 = y1;
+ }
+
+ public void setZ0(double z0)
+ {
+ this.z0 = z0;
+ }
+
+ public void setZ1(double z1)
+ {
+ this.z1 = z1;
+ }
+
+}
diff --git a/src/libnoiseforjava/model/Plane.java b/src/libnoiseforjava/model/Plane.java
new file mode 100644
index 0000000..4d498f4
--- /dev/null
+++ b/src/libnoiseforjava/model/Plane.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.model;
+
+import libnoiseforjava.module.ModuleBase;
+
+public class Plane
+{
+ /// Model that defines the surface of a plane.
+ ///
+ /// This model returns an output value from a noise module given the
+ /// coordinates of an input value located on the surface of an ( @a x,
+ /// @a z ) plane.
+ ///
+ /// To generate an output value, pass the ( @a x, @a z ) coordinates of
+ /// an input value to the GetValue() method.
+ ///
+ /// This model is useful for creating:
+ /// - two-dimensional textures
+ /// - terrain height maps for local areas
+ ///
+ /// This plane extends infinitely in both directions.
+
+
+ /// A pointer to the noise module used to generate the output values.
+ ModuleBase module;
+
+ public Plane ()
+ {
+ module = new ModuleBase(1);
+ }
+
+ public Plane (ModuleBase module)
+ {
+ this.module = module;
+ }
+
+ /// Returns the output value from the noise module given the
+ /// ( @a x, @a z ) coordinates of the specified input value located
+ /// on the surface of the plane.
+ ///
+ /// @param x The @a x coordinate of the input value.
+ /// @param z The @a z coordinate of the input value.
+ ///
+ /// @returns The output value from the noise module.
+ ///
+ /// @pre A noise module was passed to the setModule() method.
+ ///
+ /// This output value is generated by the noise module passed to the
+ /// setModule() method.
+ public double getValue (double x, double z)
+ {
+ assert (module != null);
+
+ return module.getValue (x, 0, z);
+ }
+
+ /// Returns the noise module that is used to generate the output
+ /// values.
+ ///
+ /// @returns A reference to the noise module.
+ ///
+ /// @pre A noise module was passed to the setModule() method.
+ public ModuleBase getModule ()
+ {
+ assert (module != null);
+ return module;
+ }
+
+ /// Sets the noise module that is used to generate the output values.
+ ///
+ /// @param module The noise module that is used to generate the output
+ /// values.
+ ///
+ /// This noise module must exist for the lifetime of this object,
+ /// until you pass a new noise module to this method.
+ public void setModule (ModuleBase module)
+ {
+ this.module = module;
+ }
+
+}
diff --git a/src/libnoiseforjava/model/Sphere.java b/src/libnoiseforjava/model/Sphere.java
new file mode 100644
index 0000000..43d2bb9
--- /dev/null
+++ b/src/libnoiseforjava/model/Sphere.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.model;
+
+import libnoiseforjava.module.ModuleBase;
+
+public class Sphere
+{
+ /// Model that defines the surface of a sphere.
+ ///
+ /// @image html modelsphere.png
+ ///
+ /// This model returns an output value from a noise module given the
+ /// coordinates of an input value located on the surface of a sphere.
+ ///
+ /// To generate an output value, pass the (latitude, longitude)
+ /// coordinates of an input value to the getValue() method.
+ ///
+ /// This model is useful for creating:
+ /// - seamless textures that can be mapped onto a sphere
+ /// - terrain height maps for entire planets
+ ///
+ /// This sphere has a radius of 1.0 unit and its center is located at
+ /// the origin.
+
+ /// A pointer to the noise module used to generate the output values.
+ ModuleBase module;
+
+
+ public Sphere()
+ {
+ module = new ModuleBase(1);
+ }
+
+ Sphere(ModuleBase module)
+ {
+ this.module = module;
+ }
+
+ /// Returns the output value from the noise module given the
+ /// (latitude, longitude) coordinates of the specified input value
+ /// located on the surface of the sphere.
+ ///
+ /// @param lat The latitude of the input value, in degrees.
+ /// @param lon The longitude of the input value, in degrees.
+ ///
+ /// @returns The output value from the noise module.
+ ///
+ /// @pre A noise module was passed to the setModule() method.
+ ///
+ /// This output value is generated by the noise module passed to the
+ /// setModule() method.
+ ///
+ /// Use a negative latitude if the input value is located on the
+ /// southern hemisphere.
+ ///
+ /// Use a negative longitude if the input value is located on the
+ /// western hemisphere.
+ public double getValue (double lat, double lon)
+ {
+ assert (module != null);
+
+ double x, y, z;
+ double r = Math.cos(Math.toRadians(lat));
+ x = r * Math.cos (Math.toRadians(lon));
+ y = Math.sin (Math.toRadians(lat));
+ z = r * Math.sin (Math.toRadians(lon));
+ return module.getValue (x, y, z);
+ }
+
+ /// Returns the noise module that is used to generate the output
+ /// values.
+ ///
+ /// @returns A reference to the noise module.
+ ///
+ /// @pre A noise module was passed to the setModule() method.
+ public ModuleBase getModule ()
+ {
+ assert (module != null);
+ return module;
+ }
+
+ /// Sets the noise module that is used to generate the output values.
+ ///
+ /// @param module The noise module that is used to generate the output
+ /// values.
+ ///
+ /// This noise module must exist for the lifetime of this object,
+ /// until you pass a new noise module to this method.
+ public void setModule (ModuleBase module)
+ {
+ this.module = module;
+ }
+
+}
diff --git a/src/libnoiseforjava/module/Abs.java b/src/libnoiseforjava/module/Abs.java
new file mode 100644
index 0000000..89e5c22
--- /dev/null
+++ b/src/libnoiseforjava/module/Abs.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+import libnoiseforjava.exception.ExceptionInvalidParam;
+
+public class Abs extends ModuleBase
+{
+ /// Noise module that outputs the absolute value of the output value from
+ /// a source module.
+ ///
+ /// @image html moduleabs.png
+ ///
+ /// This noise module requires one source module.
+
+ Abs (ModuleBase sourceModule) throws ExceptionInvalidParam
+ {
+ super(1);
+ setSourceModule(0, sourceModule);
+ }
+
+ public double getValue (double x, double y, double z)
+ {
+ assert (this.sourceModules[0] != null);
+
+ return Math.abs(this.sourceModules[0].getValue (x, y, z));
+ }
+
+}
diff --git a/src/libnoiseforjava/module/Add.java b/src/libnoiseforjava/module/Add.java
new file mode 100644
index 0000000..f06c895
--- /dev/null
+++ b/src/libnoiseforjava/module/Add.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+import libnoiseforjava.exception.ExceptionInvalidParam;
+
+public class Add extends ModuleBase
+{
+ /// Noise module that outputs the additive value of the output value from
+ /// two source modules.
+ ///
+ /// This noise module requires two source modules.
+
+ public Add (ModuleBase sourceModuleOne, ModuleBase sourceModuleTwo) throws ExceptionInvalidParam
+ {
+ super(2);
+ setSourceModule(0, sourceModuleOne);
+ setSourceModule(1, sourceModuleTwo);
+ }
+
+ public double getValue (double x, double y, double z)
+ {
+ assert (sourceModules[0] != null);
+ assert (sourceModules[1] != null);
+
+ return sourceModules[0].getValue (x, y, z)
+ + sourceModules[1].getValue (x, y, z);
+ }
+
+}
diff --git a/src/libnoiseforjava/module/Billow.java b/src/libnoiseforjava/module/Billow.java
new file mode 100644
index 0000000..047c8df
--- /dev/null
+++ b/src/libnoiseforjava/module/Billow.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+import libnoiseforjava.NoiseGen;
+import libnoiseforjava.NoiseGen.NoiseQuality;
+
+public class Billow extends ModuleBase
+{
+ /// Noise module that outputs three-dimensional "billowy" noise.
+ ///
+ /// @image html modulebillow.png
+ ///
+ /// This noise module generates "billowy" noise suitable for clouds and
+ /// rocks.
+ ///
+ /// This noise module is nearly identical to noise::module::Perlin except
+ /// this noise module modifies each octave with an absolute-value
+ /// function. See the documentation of noise::module::Perlin for more
+ /// information.
+
+
+ /// Default frequency for the Billow noise module.
+ static final double DEFAULT_BILLOW_FREQUENCY = 1.0;
+
+ /// Default lacunarity for the Billow noise module.
+ static final double DEFAULT_BILLOW_LACUNARITY = 2.0;
+
+ /// Default number of octaves for the the noise::module::Billow noise
+ /// module.
+ static final int DEFAULT_BILLOW_OCTAVE_COUNT = 6;
+
+ /// Default persistence value for the the noise::module::Billow noise
+ /// module.
+ static final double DEFAULT_BILLOW_PERSISTENCE = 0.5;
+
+ /// Default noise quality for the the noise::module::Billow noise module.
+ static final NoiseQuality DEFAULT_BILLOW_QUALITY = NoiseQuality.QUALITY_STD;
+
+ /// Default noise seed for the the noise::module::Billow noise module.
+ static final int DEFAULT_BILLOW_SEED = 0;
+
+ /// Maximum number of octaves for the the noise::module::Billow noise
+ /// module.
+ static final int BILLOW_MAX_OCTAVE = 30;
+
+ double frequency, lacunarity, persistence;
+ int octaveCount, seed;
+ NoiseQuality noiseQuality;
+
+ public Billow ()
+ {
+ super(0);
+ frequency = DEFAULT_BILLOW_FREQUENCY;
+ lacunarity = DEFAULT_BILLOW_LACUNARITY;
+ noiseQuality = DEFAULT_BILLOW_QUALITY;
+ octaveCount = DEFAULT_BILLOW_OCTAVE_COUNT;
+ persistence = DEFAULT_BILLOW_PERSISTENCE;
+ seed = DEFAULT_BILLOW_SEED;
+ }
+
+ public double getValue (double x, double y, double z)
+ {
+ double value = 0.0;
+ double signal = 0.0;
+ double curPersistence = 1.0;
+ double nx, ny, nz;
+ int calcSeed;
+
+ x *= frequency;
+ y *= frequency;
+ z *= frequency;
+
+ for (int curOctave = 0; curOctave < octaveCount; curOctave++)
+ {
+ // Make sure that these floating-point values have the same range as a 32-
+ // bit integer so that we can pass them to the coherent-noise functions.
+ nx = NoiseGen.MakeInt32Range (x);
+ ny = NoiseGen.MakeInt32Range (y);
+ nz = NoiseGen.MakeInt32Range (z);
+
+ // Get the coherent-noise value from the input value and add it to the
+ // final result.
+ calcSeed = (seed + curOctave) & 0xffffffff;
+ signal = NoiseGen.GradientCoherentNoise3D (nx, ny, nz, calcSeed, noiseQuality);
+ signal = 2.0 * Math.abs(signal) - 1.0;
+ value += signal * curPersistence;
+
+ // Prepare the next octave.
+ x *= lacunarity;
+ y *= lacunarity;
+ z *= lacunarity;
+ curPersistence *= persistence;
+ }
+
+ value += 0.5;
+
+ return value;
+ }
+
+ public double getFrequency()
+ {
+ return frequency;
+ }
+
+ public double getLacunarity()
+ {
+ return lacunarity;
+ }
+
+ public double getPersistence()
+ {
+ return persistence;
+ }
+
+ public int getOctaveCount()
+ {
+ return octaveCount;
+ }
+
+ public int getSeed()
+ {
+ return seed;
+ }
+
+ public NoiseQuality getNoiseQuality()
+ {
+ return noiseQuality;
+ }
+
+ public void setFrequency(double frequency)
+ {
+ this.frequency = frequency;
+ }
+
+ public void setLacunarity(double lacunarity)
+ {
+ this.lacunarity = lacunarity;
+ }
+
+ public void setPersistence(double persistence)
+ {
+ this.persistence = persistence;
+ }
+
+ public void setOctaveCount(int octaveCount)
+ {
+ this.octaveCount = octaveCount;
+ }
+
+ public void setSeed(int seed)
+ {
+ this.seed = seed;
+ }
+
+ public void setNoiseQuality(NoiseQuality noiseQuality)
+ {
+ this.noiseQuality = noiseQuality;
+ }
+
+}
diff --git a/src/libnoiseforjava/module/Blend.java b/src/libnoiseforjava/module/Blend.java
new file mode 100644
index 0000000..5e442b7
--- /dev/null
+++ b/src/libnoiseforjava/module/Blend.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+import libnoiseforjava.Interp;
+import libnoiseforjava.exception.ExceptionInvalidParam;
+
+public class Blend extends ModuleBase
+{
+ /// Noise module that outputs a weighted blend of the output values from
+ /// two source modules given the output value supplied by a control module.
+ ///
+ /// Unlike most other noise modules, the index value assigned to a source
+ /// module determines its role in the blending operation:
+ /// - Source module 0 outputs one of the
+ /// values to blend.
+ /// - Source module 1 outputs one of the
+ /// values to blend.
+ /// - Source module 2 is known as the <i>control
+ /// module</i>. The control module determines the weight of the
+ /// blending operation. Negative values weigh the blend towards the
+ /// output value from the source module with an index value of 0.
+ /// Positive values weigh the blend towards the output value from the
+ /// source module with an index value of 1.
+ ///
+ /// An application can pass the control module to the setControlModule()
+ /// method instead of the setSourceModule() method. This may make the
+ /// application code easier to read.
+ ///
+ /// This noise module uses linear interpolation to perform the blending
+ /// operation.
+ ///
+ /// This noise module requires three source modules.
+
+ public Blend (ModuleBase sourceModuleOne, ModuleBase sourceModuleTwo,
+ ModuleBase sourceModuleThree) throws ExceptionInvalidParam
+ {
+ super(3);
+ setSourceModule(0, sourceModuleOne);
+ setSourceModule(1, sourceModuleTwo);
+ setSourceModule(2, sourceModuleThree);
+ }
+
+ public double getValue (double x, double y, double z)
+ {
+ assert (sourceModules[0] != null);
+ assert (sourceModules[1] != null);
+ assert (sourceModules[2] != null);
+
+ double v0 = sourceModules[0].getValue (x, y, z);
+ double v1 = sourceModules[1].getValue (x, y, z);
+ double alpha = (sourceModules[2].getValue (x, y, z) + 1.0) / 2.0;
+
+ return Interp.linearInterp (v0, v1, alpha);
+ }
+}
diff --git a/src/libnoiseforjava/module/Cached.java b/src/libnoiseforjava/module/Cached.java
new file mode 100644
index 0000000..3afab4c
--- /dev/null
+++ b/src/libnoiseforjava/module/Cached.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+import libnoiseforjava.exception.ExceptionInvalidParam;
+
+public class Cached extends ModuleBase
+{
+ /// Noise module that caches the last output value generated by a source
+ /// module.
+ ///
+ /// If an application passes an input value to the getValue() method that
+ /// differs from the previously passed-in input value, this noise module
+ /// instructs the source module to calculate the output value. This
+ /// value, as well as the ( @a x, @a y, @a z ) coordinates of the input
+ /// value, are stored (cached) in this noise module.
+ ///
+ /// If the application passes an input value to the getValue() method
+ /// that is equal to the previously passed-in input value, this noise
+ /// module returns the cached output value without having the source
+ /// module recalculate the output value.
+ ///
+ /// If an application passes a new source module to the setSourceModule()
+ /// method, the cache is invalidated.
+ ///
+ /// Caching a noise module is useful if it is used as a source module for
+ /// multiple noise modules. If a source module is not cached, the source
+ /// module will redundantly calculate the same output value once for each
+ /// noise module in which it is included.
+ ///
+ /// This noise module requires one source module.
+
+ /// The cached output value at the cached input value.
+ double cachedValue;
+
+ /// Determines if a cached output value is stored in this noise module.
+ boolean isCached;
+
+ /// @a x coordinate of the cached input value.
+ double xCache;
+
+ /// @a y coordinate of the cached input value.
+ double yCache;
+
+ /// @a z coordinate of the cached input value.
+ double zCache;
+
+ public Cached(ModuleBase sourceModule) throws ExceptionInvalidParam
+ {
+ super(1);
+ setSourceModule(0, sourceModule);
+ isCached = false;
+ }
+
+ public double getValue (double x, double y, double z)
+ {
+ assert (sourceModules[0] != null);
+
+ if (!(isCached && x == xCache && y == yCache && z == zCache))
+ {
+ cachedValue = sourceModules[0].getValue (x, y, z);
+ xCache = x;
+ yCache = y;
+ zCache = z;
+ }
+
+ isCached = true;
+
+ return cachedValue;
+ }
+
+
+
+}
diff --git a/src/libnoiseforjava/module/Checkerboard.java b/src/libnoiseforjava/module/Checkerboard.java
new file mode 100644
index 0000000..d9f4e1f
--- /dev/null
+++ b/src/libnoiseforjava/module/Checkerboard.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+import libnoiseforjava.NoiseGen;
+
+public class Checkerboard extends ModuleBase
+{
+ /// Noise module that outputs a checkerboard pattern.
+ ///
+ /// This noise module outputs unit-sized blocks of alternating values.
+ /// The values of these blocks alternate between -1.0 and +1.0.
+ ///
+ /// This noise module is not really useful by itself, but it is often used
+ /// for debugging purposes.
+ ///
+ /// This noise module does not require any source modules.
+
+ public Checkerboard()
+ {
+ super(0);
+ }
+
+ public double getValue (double x, double y, double z)
+ {
+ int ix = (int)(Math.floor(NoiseGen.MakeInt32Range (x)));
+ int iy = (int)(Math.floor(NoiseGen.MakeInt32Range (y)));
+ int iz = (int)(Math.floor(NoiseGen.MakeInt32Range (z)));
+
+ // original was
+ //(ix & 1 ^ iy & 1 ^ iz & 1)
+ // not certain if this duplicates it or not
+ if ((ix%2 == 1) ^ (iy%2 == 1) ^ (iz%2 == 1))
+ return -1.0;
+ else
+ return 1.0;
+ }
+}
+
diff --git a/src/libnoiseforjava/module/Clamp.java b/src/libnoiseforjava/module/Clamp.java
new file mode 100644
index 0000000..3ad6d39
--- /dev/null
+++ b/src/libnoiseforjava/module/Clamp.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+import libnoiseforjava.exception.ExceptionInvalidParam;
+
+public class Clamp extends ModuleBase
+{
+
+ /// Noise module that clamps the output value from a source module to a
+ /// range of values.
+ ///
+ /// @image html moduleclamp.png
+ ///
+ /// The range of values in which to clamp the output value is called the
+ /// <i>clamping range</i>.
+ ///
+ /// If the output value from the source module is less than the lower
+ /// bound of the clamping range, this noise module clamps that value to
+ /// the lower bound. If the output value from the source module is
+ /// greater than the upper bound of the clamping range, this noise module
+ /// clamps that value to the upper bound.
+ ///
+ /// To specify the upper and lower bounds of the clamping range, call the
+ /// setBounds() method.
+ ///
+ /// This noise module requires one source module.
+
+ /// Default lower bound of the clamping range for the Clamp noise module.
+ static final double DEFAULT_CLAMP_LOWER_BOUND = -1.0;
+
+ /// Default upper bound of the clamping range for the Clamp noise module.
+ static final double DEFAULT_CLAMP_UPPER_BOUND = 1.0;
+
+ double lowerBound, upperBound;
+
+ public Clamp (ModuleBase sourceModule) throws ExceptionInvalidParam
+ {
+ super(1);
+ setSourceModule(0, sourceModule);
+
+ lowerBound = DEFAULT_CLAMP_LOWER_BOUND;
+ upperBound = DEFAULT_CLAMP_UPPER_BOUND;
+ }
+
+ public double getValue (double x, double y, double z)
+ {
+ assert (sourceModules[0] != null);
+
+ double value = sourceModules[0].getValue (x, y, z);
+ if (value < lowerBound)
+ return lowerBound;
+ else if (value > upperBound)
+ return upperBound;
+ else
+ return value;
+ }
+
+ public void setBounds (double lowerBound, double upperBound)
+ {
+ assert (lowerBound < upperBound);
+
+ this.lowerBound = lowerBound;
+ this.upperBound = upperBound;
+ }
+
+}
diff --git a/src/libnoiseforjava/module/Const.java b/src/libnoiseforjava/module/Const.java
new file mode 100644
index 0000000..4454f7d
--- /dev/null
+++ b/src/libnoiseforjava/module/Const.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+public class Const extends ModuleBase
+{
+ /// Noise module that outputs a constant value.
+ ///
+ /// @image html moduleconst.png
+ ///
+ /// To specify the constant value, call the setConstValue() method.
+ ///
+ /// This noise module is not useful by itself, but it is often used as a
+ /// source module for other noise modules.
+ ///
+ /// This noise module does not require any source modules.
+
+ /// Default constant value for the Const noise module.
+ static final double DEFAULT_CONST_VALUE = 0.0;
+
+ double constValue;
+
+ public Const ()
+ {
+ super(0);
+ this.constValue = DEFAULT_CONST_VALUE;
+ }
+
+ public Const(double c) {
+ super(0);
+ this.constValue = c;
+ }
+
+ public double getValue (double x, double y, double z)
+ {
+ return constValue;
+ }
+
+ /// Sets the constant output value for this noise module.
+ ///
+ /// @param constValue The constant output value for this noise module.
+ public void setConstValue (double constValue)
+ {
+ this.constValue = constValue;
+ }
+
+}
diff --git a/src/libnoiseforjava/module/Curve.java b/src/libnoiseforjava/module/Curve.java
new file mode 100644
index 0000000..2d78818
--- /dev/null
+++ b/src/libnoiseforjava/module/Curve.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+import libnoiseforjava.Interp;
+import libnoiseforjava.Misc;
+import libnoiseforjava.exception.ExceptionInvalidParam;
+
+public class Curve extends ModuleBase
+{
+ /// Noise module that maps the output value from a source module onto an
+ /// arbitrary function curve.
+ ///
+ /// This noise module maps the output value from the source module onto an
+ /// application-defined curve. This curve is defined by a number of
+ /// <i>control points</i>; each control point has an <i>input value</i>
+ /// that maps to an <i>output value</i>.
+ ///
+ /// To add the control points to this curve, call the addControlPoint()
+ /// method. Note that the class ControlPoint follows the class Curve in
+ /// this file.
+ ///
+ /// Since this curve is a cubic spline, an application must add a minimum
+ /// of four control points to the curve. If this is not done, the
+ /// getValue() method fails. Each control point can have any input and
+ /// output value, although no two control points can have the same input
+ /// value. There is no limit to the number of control points that can be
+ /// added to the curve.
+ ///
+ /// This noise module requires one source module
+
+ int controlPointCount;
+ ControlPoint[] controlPoints;
+
+ public Curve (ModuleBase sourceModule) throws ExceptionInvalidParam
+ {
+ super(1);
+ setSourceModule(0, sourceModule);
+ controlPointCount = 0;
+ controlPoints= new ControlPoint[1];
+ controlPoints[0] = new ControlPoint(0.0, 0.0);
+ }
+
+ public void addControlPoint (double inputValue, double outputValue)
+ throws ExceptionInvalidParam
+ {
+ // Find the insertion point for the new control point and insert the new
+ // point at that position. The control point array will remain sorted by
+ // input value.
+ int insertionPos = findInsertionPos(inputValue);
+ insertAtPos (insertionPos, inputValue, outputValue);
+ }
+
+ public void clearAllControlPoints ()
+ {
+ controlPoints = null;
+ controlPointCount = 0;
+ }
+
+ public int findInsertionPos (double inputValue) throws ExceptionInvalidParam
+ {
+ int insertionPos;
+ for (insertionPos = 0; insertionPos < controlPointCount; insertionPos++)
+ {
+ if (inputValue < controlPoints[insertionPos].inputValue)
+ // We found the array index in which to insert the new control point.
+ // Exit now.
+ break;
+ else if (inputValue == controlPoints[insertionPos].inputValue)
+ // Each control point is required to contain a unique input value, so
+ // throw an exception.
+ throw new ExceptionInvalidParam("Invalid Parameter in Curve");
+ }
+ return insertionPos;
+ }
+
+ public double getValue (double x, double y, double z)
+ {
+ assert (sourceModules[0] != null);
+ assert (controlPointCount >= 4);
+
+ // Get the output value from the source module.
+ double sourceModuleValue = sourceModules[0].getValue (x, y, z);
+
+ // Find the first element in the control point array that has an input value
+ // larger than the output value from the source module.
+ int indexPos;
+ for (indexPos = 0; indexPos < controlPointCount; indexPos++)
+ {
+ if (sourceModuleValue < controlPoints[indexPos].inputValue)
+ break;
+
+ }
+
+ // Find the four nearest control points so that we can perform cubic
+ // interpolation.
+ int index0 = Misc.ClampValue (indexPos - 2, 0, controlPointCount - 1);
+ int index1 = Misc.ClampValue (indexPos - 1, 0, controlPointCount - 1);
+ int index2 = Misc.ClampValue (indexPos , 0, controlPointCount - 1);
+ int index3 = Misc.ClampValue (indexPos + 1, 0, controlPointCount - 1);
+
+ // If some control points are missing (which occurs if the value from the
+ // source module is greater than the largest input value or less than the
+ // smallest input value of the control point array), get the corresponding
+ // output value of the nearest control point and exit now.
+ if (index1 == index2) {
+ return controlPoints[index1].outputValue;
+ }
+
+ // Compute the alpha value used for cubic interpolation.
+ double input0 = controlPoints[index1].inputValue;
+ double input1 = controlPoints[index2].inputValue;
+ double alpha = (sourceModuleValue - input0) / (input1 - input0);
+
+ // Now perform the cubic interpolation given the alpha value.
+ return Interp.cubicInterp(
+ controlPoints[index0].outputValue,
+ controlPoints[index1].outputValue,
+ controlPoints[index2].outputValue,
+ controlPoints[index3].outputValue,
+ alpha);
+ }
+
+ public void insertAtPos (int insertionPos, double inputValue,
+ double outputValue)
+ {
+ // Make room for the new control point at the specified position within the
+ // control point array. The position is determined by the input value of
+ // the control point; the control points must be sorted by input value
+ // within that array.
+ ControlPoint[] newControlPoints = new ControlPoint[controlPointCount + 1];
+
+ for (int t = 0; t < (controlPointCount + 1); t++)
+ newControlPoints[t] = new ControlPoint();
+
+ for (int i = 0; i < controlPointCount; i++) {
+ if (i < insertionPos) {
+ newControlPoints[i] = controlPoints[i];
+ } else {
+ newControlPoints[i + 1] = controlPoints[i];
+ }
+ }
+
+ controlPoints = newControlPoints;
+ ++controlPointCount;
+
+ // Now that we've made room for the new control point within the array, add
+ // the new control point.
+ controlPoints[insertionPos].inputValue = inputValue;
+ controlPoints[insertionPos].outputValue = outputValue;
+ }
+}
+
+
+/// This class defines a control point.
+///
+/// Control points are used for defining splines.
+class ControlPoint
+{
+ /// The input value.
+ double inputValue;
+
+ /// The output value that is mapped from the input value.
+ double outputValue;
+
+ ControlPoint()
+ {
+ inputValue = 0.0;
+ outputValue = 0.0;
+ }
+
+ ControlPoint(double inputValue, double outputValue)
+ {
+ this.inputValue = inputValue;
+ this.outputValue = outputValue;
+ }
+
+
+
+} \ No newline at end of file
diff --git a/src/libnoiseforjava/module/Cylinders.java b/src/libnoiseforjava/module/Cylinders.java
new file mode 100644
index 0000000..c67d019
--- /dev/null
+++ b/src/libnoiseforjava/module/Cylinders.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+public class Cylinders extends ModuleBase
+{
+ /// Noise module that outputs concentric cylinders.
+ ///
+ /// This noise module outputs concentric cylinders centered on the origin.
+ /// These cylinders are oriented along the @a y axis similar to the
+ /// concentric rings of a tree. Each cylinder extends infinitely along
+ /// the @a y axis.
+ ///
+ /// The first cylinder has a radius of 1.0. Each subsequent cylinder has
+ /// a radius that is 1.0 unit larger than the previous cylinder.
+ ///
+ /// The output value from this noise module is determined by the distance
+ /// between the input value and the the nearest cylinder surface. The
+ /// input values that are located on a cylinder surface are given the
+ /// output value 1.0 and the input values that are equidistant from two
+ /// cylinder surfaces are given the output value -1.0.
+ ///
+ /// An application can change the frequency of the concentric cylinders.
+ /// Increasing the frequency reduces the distances between cylinders. To
+ /// specify the frequency, call the setFrequency() method.
+ ///
+ /// This noise module, modified with some low-frequency, low-power
+ /// turbulence, is useful for generating wood-like textures.
+ ///
+ /// This noise module does not require any source modules.
+
+ /// Default frequency value for the Cylinders noise module.
+ static final double DEFAULT_CYLINDERS_FREQUENCY = 1.0;
+
+ /// Frequency of the concentric cylinders.
+ double frequency;
+
+ public Cylinders ()
+ {
+ super(0);
+ frequency = DEFAULT_CYLINDERS_FREQUENCY;
+ }
+
+ public double getValue (double x, double y, double z)
+ {
+ x *= frequency;
+ z *= frequency;
+
+ double distFromCenter = Math.sqrt(x * x + z * z);
+ double distFromSmallerSphere = distFromCenter - Math.floor(distFromCenter);
+ double distFromLargerSphere = 1.0 - distFromSmallerSphere;
+ double nearestDist = Math.min(distFromSmallerSphere, distFromLargerSphere);
+
+ // Puts it in the -1.0 to +1.0 range.
+ return 1.0 - (nearestDist * 4.0);
+ }
+
+ /// Returns the frequency of the concentric cylinders.
+ ///
+ /// @returns The frequency of the concentric cylinders.
+ ///
+ /// Increasing the frequency increases the density of the concentric
+ /// cylinders, reducing the distances between them.
+ public double getFrequency()
+ {
+ return frequency;
+ }
+
+ /// Sets the frequency of the concentric cylinders.
+ ///
+ /// @param frequency The frequency of the concentric cylinders.
+ ///
+ /// Increasing the frequency increases the density of the concentric
+ /// cylinders, reducing the distances between them.
+ public void setFrequency (double frequency)
+ {
+ this.frequency = frequency;
+ }
+
+}
diff --git a/src/libnoiseforjava/module/Displace.java b/src/libnoiseforjava/module/Displace.java
new file mode 100644
index 0000000..7725ce6
--- /dev/null
+++ b/src/libnoiseforjava/module/Displace.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+import libnoiseforjava.exception.ExceptionInvalidParam;
+import libnoiseforjava.exception.ExceptionNoModule;
+
+public class Displace extends ModuleBase
+{
+ /// Noise module that uses three source modules to displace each
+ /// coordinate of the input value before returning the output value from
+ /// a source module.
+ ///
+ /// Unlike most other noise modules, the index value assigned to a source
+ /// module determines its role in the displacement operation:
+ /// - Source module 0 (left in the diagram) outputs a value.
+ /// - Source module 1 (lower left in the diagram) specifies the offset to
+ /// apply to the @a x coordinate of the input value.
+ /// - Source module 2 (lower center in the diagram) specifies the
+ /// offset to apply to the @a y coordinate of the input value.
+ /// - Source module 3 (lower right in the diagram) specifies the offset
+ /// to apply to the @a z coordinate of the input value.
+ ///
+ /// The getValue() method modifies the ( @a x, @a y, @a z ) coordinates of
+ /// the input value using the output values from the three displacement
+ /// modules before retrieving the output value from the source module.
+ ///
+ /// The Turbulence noise module is a special case of the
+ /// Displace module; internally, there are three Perlin-noise modules
+ /// that perform the displacement operation.
+ ///
+ /// This noise module requires four source modules.
+
+ public Displace (ModuleBase sourceModuleOne, ModuleBase sourceModuleTwo,
+ ModuleBase sourceModuleThree, ModuleBase sourceModuleFour) throws ExceptionInvalidParam
+ {
+ super(4);
+ setSourceModule(0, sourceModuleOne);
+ setSourceModule(1, sourceModuleTwo);
+ setSourceModule(2, sourceModuleThree);
+ setSourceModule(3, sourceModuleFour);
+ }
+
+ public double getValue (double x, double y, double z)
+ {
+ assert (sourceModules[0] != null);
+ assert (sourceModules[1] != null);
+ assert (sourceModules[2] != null);
+ assert (sourceModules[3] != null);
+
+ // Get the output values from the three displacement modules. Add each
+ // value to the corresponding coordinate in the input value.
+ double xDisplace = x + (sourceModules[1].getValue (x, y, z));
+ double yDisplace = y + (sourceModules[2].getValue (x, y, z));
+ double zDisplace = z + (sourceModules[3].getValue (x, y, z));
+
+ // Retrieve the output value using the offset input value instead of
+ // the original input value.
+ return sourceModules[0].getValue (xDisplace, yDisplace, zDisplace);
+ }
+
+ public ModuleBase getXDisplaceModule() throws ExceptionNoModule
+ {
+ if (sourceModules == null || sourceModules[1] == null)
+ throw new ExceptionNoModule ("Could not retrieve a source module " +
+ "from a noise module.");
+
+ return sourceModules[1];
+ }
+
+ /// Returns the @a y displacement module.
+ ///
+ /// @returns A reference to the @a y displacement module.
+ ///
+ /// @pre This displacement module has been added to this noise module
+ /// via a call to setSourceModule() or setYDisplaceModule().
+ ///
+ /// @throw ExceptionNoModule See the preconditions for more
+ /// information.
+ ///
+ /// The getValue() method displaces the input value by adding the output
+ /// value from this displacement module to the @a y coordinate of the
+ /// input value before returning the output value from the source
+ /// module.
+ public ModuleBase getYDisplaceModule () throws ExceptionNoModule
+ {
+ if (sourceModules == null || sourceModules[2] == null)
+ throw new ExceptionNoModule ("Could not retrieve a source module " +
+ "from Displace noise module.");
+
+ return sourceModules[2];
+ }
+
+ /// Returns the @a z displacement module.
+ ///
+ /// @returns A reference to the @a z displacement module.
+ ///
+ /// @pre This displacement module has been added to this noise module
+ /// via a call to setSourceModule() or setZDisplaceModule().
+ ///
+ /// @throw ExceptionNoModule See the preconditions for more
+ /// information.
+ ///
+ /// The getValue() method displaces the input value by adding the output
+ /// value from this displacement module to the @a z coordinate of the
+ /// input value before returning the output value from the source
+ /// module.
+ public ModuleBase getZDisplaceModule () throws ExceptionNoModule
+ {
+ if (sourceModules == null || sourceModules[3] == null)
+ throw new ExceptionNoModule ("Could not retrieve a source module " +
+ "from Displace noise module.");
+
+ return sourceModules[3];
+ }
+
+
+ /// Sets the @a x, @a y, and @a z displacement modules.
+ ///
+ /// @param xDisplaceModule Displacement module that displaces the @a x
+ /// coordinate of the input value.
+ /// @param yDisplaceModule Displacement module that displaces the @a y
+ /// coordinate of the input value.
+ /// @param zDisplaceModule Displacement module that displaces the @a z
+ /// coordinate of the input value.
+ ///
+ /// The getValue() method displaces the input value by adding the output
+ /// value from each of the displacement modules to the corresponding
+ /// coordinates of the input value before returning the output value
+ /// from the source module.
+ ///
+ /// This method assigns an index value of 1 to the @a x displacement
+ /// module, an index value of 2 to the @a y displacement module, and an
+ /// index value of 3 to the @a z displacement module.
+ ///
+ /// These displacement modules must exist throughout the lifetime of
+ /// this noise module unless another displacement module replaces it.
+ public void setDisplaceModules (ModuleBase xDisplaceModule,
+ ModuleBase yDisplaceModule, ModuleBase zDisplaceModule)
+ {
+ setXDisplaceModule (xDisplaceModule);
+ setYDisplaceModule (yDisplaceModule);
+ setZDisplaceModule (zDisplaceModule);
+ }
+
+ /// Sets the @a x displacement module.
+ ///
+ /// @param xDisplaceModule Displacement module that displaces the @a x
+ /// coordinate.
+ ///
+ /// The getValue() method displaces the input value by adding the output
+ /// value from this displacement module to the @a x coordinate of the
+ /// input value before returning the output value from the source
+ /// module.
+ ///
+ /// This method assigns an index value of 1 to the @a x displacement
+ /// module. Passing this displacement module to this method produces
+ /// the same results as passing this displacement module to the
+ /// setSourceModule() method while assigning it an index value of 1.
+ ///
+ /// This displacement module must exist throughout the lifetime of this
+ /// noise module unless another displacement module replaces it.
+ public void setXDisplaceModule (ModuleBase xDisplaceModule)
+ {
+ assert (sourceModules != null);
+ sourceModules[1] = xDisplaceModule;
+ }
+
+ /// Sets the @a y displacement module.
+ ///
+ /// @param yDisplaceModule Displacement module that displaces the @a y
+ /// coordinate.
+ ///
+ /// The getValue() method displaces the input value by adding the output
+ /// value from this displacement module to the @a y coordinate of the
+ /// input value before returning the output value from the source
+ /// module.
+ ///
+ /// This method assigns an index value of 2 to the @a y displacement
+ /// module. Passing this displacement module to this method produces
+ /// the same results as passing this displacement module to the
+ /// setSourceModule() method while assigning it an index value of 2.
+ ///
+ /// This displacement module must exist throughout the lifetime of this
+ /// noise module unless another displacement module replaces it.
+ public void setYDisplaceModule (ModuleBase yDisplaceModule)
+ {
+ assert (sourceModules != null);
+ sourceModules[2] = yDisplaceModule;
+ }
+
+ /// Sets the @a z displacement module.
+ ///
+ /// @param zDisplaceModule Displacement module that displaces the @a z
+ /// coordinate.
+ ///
+ /// The getValue() method displaces the input value by adding the output
+ /// value from this displacement module to the @a z coordinate of the
+ /// input value before returning the output value from the source
+ /// module.
+ ///
+ /// This method assigns an index value of 3 to the @a z displacement
+ /// module. Passing this displacement module to this method produces
+ /// the same results as passing this displacement module to the
+ /// setSourceModule() method while assigning it an index value of 3.
+ ///
+ /// This displacement module must exist throughout the lifetime of this
+ /// noise module unless another displacement module replaces it.
+ public void setZDisplaceModule (ModuleBase zDisplaceModule)
+ {
+ assert (sourceModules != null);
+ sourceModules[3] = zDisplaceModule;
+ }
+
+}
diff --git a/src/libnoiseforjava/module/Exponent.java b/src/libnoiseforjava/module/Exponent.java
new file mode 100644
index 0000000..64f9cdc
--- /dev/null
+++ b/src/libnoiseforjava/module/Exponent.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+import libnoiseforjava.exception.ExceptionInvalidParam;
+
+public class Exponent extends ModuleBase
+{
+ /// Noise module that maps the output value from a source module onto an
+ /// exponential curve.
+ ///
+ /// Because most noise modules will output values that range from -1.0 to
+ /// +1.0, this noise module first normalizes this output value (the range
+ /// becomes 0.0 to 1.0), maps that value onto an exponential curve, then
+ /// rescales that value back to the original range.
+ ///
+ /// This noise module requires one source module.
+
+ /// Default exponent for the Exponent noise module.
+ static final double DEFAULT_EXPONENT = 1.0;
+
+
+ /// Exponent to apply to the output value from the source module.
+ double exponent;
+
+ public Exponent (ModuleBase sourceModule) throws ExceptionInvalidParam
+ {
+ super(1);
+ setSourceModule(0, sourceModule);
+ exponent = DEFAULT_EXPONENT;
+
+ }
+
+ public double getValue (double x, double y, double z)
+ {
+ assert (sourceModules[0] != null);
+
+ double value = sourceModules[0].getValue (x, y, z);
+ return (Math.pow (Math.abs ((value + 1.0) / 2.0), exponent) * 2.0 - 1.0);
+ }
+
+ /// Returns the exponent value to apply to the output value from the
+ /// source module.
+ ///
+ /// @returns The exponent value.
+ public double getExponent ()
+ {
+ return exponent;
+ }
+
+ public void setExponent(double exponent)
+ {
+ this.exponent = exponent;
+ }
+
+}
diff --git a/src/libnoiseforjava/module/Gradient.java b/src/libnoiseforjava/module/Gradient.java
new file mode 100644
index 0000000..91b4132
--- /dev/null
+++ b/src/libnoiseforjava/module/Gradient.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ * Copyright 2012 Michael Nugent (This module)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+/**
+ * User: mike nugent
+ * Date: 2/5/12
+ * Time: 4:40 PM
+ * URL: https://github.com/michaelnugent/libnoiseforjava
+ * Package: libnoiseforjava.module
+ */
+public class Gradient extends ModuleBase {
+
+ AXIS axis = AXIS.Y;
+
+ double inputMin = 0;
+ double inputMax = 255;
+
+ double scaledMin = -1;
+ double scaledMax = 1;
+
+ public enum AXIS {
+ X,
+ Y,
+ Z
+ };
+
+ public Gradient() {
+ super();
+ }
+
+ public Gradient(AXIS axis) {
+ super();
+ this.axis = axis;
+ }
+
+ public double getValue(double x, double y, double z) {
+ if (axis == AXIS.Y) {
+ double outy = scale(y, this.inputMin, this.inputMax, this.scaledMin, this.scaledMax);
+ return outy;
+ } else if (axis == AXIS.X) {
+ double outx = scale(x, this.inputMin, this.inputMax, this.scaledMin, this.scaledMax);
+ return outx;
+ } else {
+ double outz = scale(z, this.inputMin, this.inputMax, this.scaledMin, this.scaledMax);
+ return outz;
+ }
+ }
+
+ private double scale( double inVal, double inMin, double inMax, double min, double max ) {
+ double m = (max-min)/(inMax-inMin);
+ double c = min-inMin*m;
+ return m*inVal+c;
+ }
+
+ public AXIS getAxis() {
+ return axis;
+ }
+
+ public void setAxis(AXIS axis) {
+ this.axis = axis;
+ }
+
+ public double getInputMin() {
+ return inputMin;
+ }
+
+ public void setInputMin(double inputMin) {
+ this.inputMin = inputMin;
+ }
+
+ public double getInputMax() {
+ return inputMax;
+ }
+
+ public void setInputMax(double inputMax) {
+ this.inputMax = inputMax;
+ }
+
+ public double getScaledMin() {
+ return scaledMin;
+ }
+
+ public void setScaledMin(double scaledMin) {
+ this.scaledMin = scaledMin;
+ }
+
+ public double getScaledMax() {
+ return scaledMax;
+ }
+
+ public void setScaledMax(double scaledMax) {
+ this.scaledMax = scaledMax;
+ }
+}
diff --git a/src/libnoiseforjava/module/Identity.java b/src/libnoiseforjava/module/Identity.java
new file mode 100644
index 0000000..6fe0f3a
--- /dev/null
+++ b/src/libnoiseforjava/module/Identity.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ * Copyright 2012 Michael Nugent (This module)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+/**
+ * User: mike nugent
+ * Date: 2/5/12
+ * Time: 4:19 PM
+ * URL: https://github.com/michaelnugent/libnoiseforjava
+ * Package: libnoiseforjava.module
+ */
+public class Identity extends ModuleBase {
+
+ AXIS axis = AXIS.Y;
+
+ public enum AXIS {
+ X,
+ Y,
+ Z
+ };
+
+ public Identity() {
+ super();
+ }
+
+ public Identity( AXIS axis ) {
+ super();
+ this.axis = axis;
+ }
+
+ public void setAxis( AXIS axis ) {
+ this.axis = axis;
+ }
+
+ public double getValue(double x, double y, double z) {
+ if ( axis == AXIS.Y ) {
+ return y;
+ }
+ else if ( axis == AXIS.X ) {
+ return x;
+ }
+ else {
+ return z;
+ }
+ }
+}
diff --git a/src/libnoiseforjava/module/Intersection.java b/src/libnoiseforjava/module/Intersection.java
new file mode 100644
index 0000000..4a0f20e
--- /dev/null
+++ b/src/libnoiseforjava/module/Intersection.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ * Copyright 2012 Michael Nugent (This module)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+import libnoiseforjava.exception.ExceptionInvalidParam;
+
+/**
+ * User: mike nugent
+ * Date: 2/18/12
+ * Time: 11:57 PM
+ * URL: https://github.com/michaelnugent/libnoiseforjava
+ * Package: libnoiseforjava.module
+ */
+public class Intersection extends ModuleBase {
+ double cutoff;
+ public Intersection(ModuleBase sourceModuleOne, ModuleBase sourceModuleTwo, double cutoff) throws ExceptionInvalidParam
+ {
+ super(2);
+ setSourceModule(0, sourceModuleOne);
+ setSourceModule(1, sourceModuleTwo);
+ this.cutoff = cutoff;
+ }
+
+ public double getValue (double x, double y, double z)
+ {
+ assert (sourceModules[0] != null);
+ assert (sourceModules[1] != null);
+
+ double s1 = sourceModules[0].getValue(x,y,z);
+ double s2 = sourceModules[1].getValue(x,y,z);
+
+ if ( s1 + cutoff > s2 && s1 - cutoff < s2 ) {
+ return s1;
+ }
+ else {
+ return -1;
+ }
+ }
+}
diff --git a/src/libnoiseforjava/module/Invert.java b/src/libnoiseforjava/module/Invert.java
new file mode 100644
index 0000000..106b79f
--- /dev/null
+++ b/src/libnoiseforjava/module/Invert.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+import libnoiseforjava.exception.ExceptionInvalidParam;
+
+public class Invert extends ModuleBase
+{
+ /// Noise module that inverts the output value from a source module.
+ ///
+ /// This noise module requires one source module.
+ public Invert (ModuleBase sourceModule) throws ExceptionInvalidParam
+ {
+ super(1);
+ setSourceModule(0, sourceModule);
+ }
+
+ public double getValue (double x, double y, double z)
+ {
+ assert (sourceModules[0] != null);
+
+ return -(sourceModules[0].getValue (x, y, z));
+ }
+
+}
diff --git a/src/libnoiseforjava/module/Max.java b/src/libnoiseforjava/module/Max.java
new file mode 100644
index 0000000..34757f6
--- /dev/null
+++ b/src/libnoiseforjava/module/Max.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+import libnoiseforjava.exception.ExceptionInvalidParam;
+
+public class Max extends ModuleBase
+{
+ /// Noise module that outputs the larger of the two output values from two
+ /// source modules.
+ ///
+ /// This noise module requires two source modules.
+
+ public Max (ModuleBase sourceModuleOne, ModuleBase sourceModuleTwo) throws ExceptionInvalidParam
+ {
+ super(2);
+ setSourceModule(0, sourceModuleOne);
+ setSourceModule(1, sourceModuleTwo);
+ }
+
+ public double getValue (double x, double y, double z)
+ {
+ assert (sourceModules[0] != null);
+ assert (sourceModules[1] != null);
+
+ double v0 = sourceModules[0].getValue (x, y, z);
+ double v1 = sourceModules[1].getValue (x, y, z);
+ return Math.max(v0, v1);
+ }
+
+}
diff --git a/src/libnoiseforjava/module/Min.java b/src/libnoiseforjava/module/Min.java
new file mode 100644
index 0000000..cd6bea0
--- /dev/null
+++ b/src/libnoiseforjava/module/Min.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+import libnoiseforjava.exception.ExceptionInvalidParam;
+
+public class Min extends ModuleBase
+{
+ /// Noise module that outputs the smaller of the two output values from
+ /// two source modules.
+ ///
+ /// @image html modulemin.png
+ ///
+ /// This noise module requires two source modules.
+
+ public Min (ModuleBase sourceModuleOne, ModuleBase sourceModuleTwo) throws ExceptionInvalidParam
+ {
+ super(2);
+ setSourceModule(0, sourceModuleOne);
+ setSourceModule(1, sourceModuleTwo);
+ }
+
+ public double getValue (double x, double y, double z)
+ {
+ assert (sourceModules[0] != null);
+ assert (sourceModules[1] != null);
+
+ double v0 = sourceModules[0].getValue (x, y, z);
+ double v1 = sourceModules[1].getValue (x, y, z);
+ return Math.min(v0, v1);
+ }
+
+}
diff --git a/src/libnoiseforjava/module/ModuleBase.java b/src/libnoiseforjava/module/ModuleBase.java
new file mode 100644
index 0000000..895e67b
--- /dev/null
+++ b/src/libnoiseforjava/module/ModuleBase.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+import libnoiseforjava.exception.ExceptionInvalidParam;
+import libnoiseforjava.exception.ExceptionNoModule;
+
+public class ModuleBase
+{
+
+ // base class for noise modules.
+ public ModuleBase[] sourceModules;
+ public int modulesRequired;
+
+ public ModuleBase()
+ {
+ modulesRequired = 0;
+ }
+
+ public ModuleBase (int modulesRequired)
+ {
+ // Create an array of pointers to all source modules required by this
+ // noise module. Set these pointers to null.
+ if(modulesRequired>0)
+ {
+ sourceModules = new ModuleBase[modulesRequired];
+ for (int i = 0; i < modulesRequired; i++)
+ {
+ sourceModules[i] = new ModuleBase();
+ }
+ }
+ else
+ sourceModules = null;
+
+ this.modulesRequired = modulesRequired;
+ }
+
+ /// Returns a reference to a source module connected to this noise
+ /// module.
+ ///
+ /// @param index The index value assigned to the source module.
+ ///
+ /// @returns A reference to the source module.
+ ///
+ /// @pre The index value ranges from 0 to one less than the number of
+ /// source modules required by this noise module.
+ /// @pre A source module with the specified index value has been added
+ /// to this noise module via a call to setSourceModule().
+ ///
+ /// @throw ExceptionNoModule See the preconditions for more
+ /// information.
+ ///
+ /// Each noise module requires the attachment of a certain number of
+ /// source modules before an application can call the getValue()
+ /// method.
+ public ModuleBase getSourceModule (int index) throws ExceptionNoModule
+ {
+ if (sourceModules != null)
+ {
+ if (index >= getSourceModuleCount () || index < 0
+ || sourceModules[index] == null)
+ {
+ throw new ExceptionNoModule ("Could not retrieve a source module " +
+ "from a noise module.");
+ }
+
+ return (sourceModules[index]);
+ }
+ throw new ExceptionNoModule ("Could not retrieve a source module " +
+ "from a noise module.");
+ }
+
+ /// Returns the number of source modules required by this noise
+ /// module.
+ ///
+ /// @returns The number of source modules required by this noise
+ /// module.
+ public int getSourceModuleCount()
+ {
+ return modulesRequired;
+ }
+
+ /// Generates an output value given the coordinates of the specified
+ /// input value.
+ ///
+ /// @param x The @a x coordinate of the input value.
+ /// @param y The @a y coordinate of the input value.
+ /// @param z The @a z coordinate of the input value.
+ ///
+ /// @returns The output value.
+ ///
+ /// @pre All source modules required by this noise module have been
+ /// passed to the setSourceModule() method.
+ ///
+ /// Before an application can call this method, it must first connect
+ /// all required source modules via the setSourceModule() method. If
+ /// these source modules are not connected to this noise module, this
+ /// method raises a debug assertion.
+ ///
+ /// To determine the number of source modules required by this noise
+ /// module, call the getSourceModuleCount() method.
+ public double getValue (double x, double y, double z)
+ {
+ return x;
+ }
+
+ /// Connects a source module to this noise module.
+ ///
+ /// @param index An index value to assign to this source module.
+ /// @param sourceModule The source module to attach.
+ ///
+ /// @pre The index value ranges from 0 to one less than the number of
+ /// source modules required by this noise module.
+ ///
+ /// @throw ExceptionInvalidParam An invalid parameter was
+ /// specified; see the preconditions for more information.
+ ///
+ /// A noise module mathematically combines the output values from the
+ /// source modules to generate the value returned by getValue().
+ ///
+ /// The index value to assign a source module is a unique identifier
+ /// for that source module. If an index value has already been
+ /// assigned to a source module, this noise module replaces the old
+ /// source module with the new source module.
+ ///
+ /// Before an application can call the getValue() method, it must
+ /// first connect all required source modules. To determine the
+ /// number of source modules required by this noise module, call the
+ /// getSourceModuleCount() method.
+ ///
+ /// This source module must exist throughout the lifetime of this
+ /// noise module unless another source module replaces that source
+ /// module.
+ ///
+ /// A noise module does not modify a source module; it only modifies
+ /// its output values.
+ public void setSourceModule (int index, ModuleBase sourceModule)
+ throws ExceptionInvalidParam
+ {
+ if (sourceModules != null)
+ {
+ if (index >= getSourceModuleCount () || index < 0)
+ throw new ExceptionInvalidParam ("Invalid Parameter in ModuleBase");
+ }
+ this.sourceModules[index] = sourceModule;
+ }
+
+}
diff --git a/src/libnoiseforjava/module/Multiply.java b/src/libnoiseforjava/module/Multiply.java
new file mode 100644
index 0000000..944994e
--- /dev/null
+++ b/src/libnoiseforjava/module/Multiply.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+import libnoiseforjava.exception.ExceptionInvalidParam;
+
+public class Multiply extends ModuleBase
+{
+ /// Noise module that outputs the product of the two output values from
+ /// two source modules.
+ ///
+ /// @image html modulemultiply.png
+ ///
+ /// This noise module requires two source modules.
+
+ public Multiply (ModuleBase sourceModuleOne, ModuleBase sourceModuleTwo) throws ExceptionInvalidParam
+ {
+ super(2);
+ setSourceModule(0, sourceModuleOne);
+ setSourceModule(1, sourceModuleTwo);
+ }
+
+ public double getValue (double x, double y, double z)
+ {
+ assert (sourceModules[0] != null);
+ assert (sourceModules[1] != null);
+
+ return sourceModules[0].getValue (x, y, z)
+ * sourceModules[1].getValue (x, y, z);
+ }
+
+}
diff --git a/src/libnoiseforjava/module/Perlin.java b/src/libnoiseforjava/module/Perlin.java
new file mode 100644
index 0000000..70fb22e
--- /dev/null
+++ b/src/libnoiseforjava/module/Perlin.java
@@ -0,0 +1,357 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+import libnoiseforjava.NoiseGen;
+import libnoiseforjava.NoiseGen.NoiseQuality;
+import libnoiseforjava.exception.ExceptionInvalidParam;
+
+public class Perlin extends ModuleBase
+{
+ /// Noise module that outputs 3-dimensional Perlin noise.
+ ///
+ /// Perlin noise is the sum of several coherent-noise functions of
+ /// ever-increasing frequencies and ever-decreasing amplitudes.
+ ///
+ /// An important property of Perlin noise is that a small change in the
+ /// input value will produce a small change in the output value, while a
+ /// large change in the input value will produce a random change in the
+ /// output value.
+ ///
+ /// This noise module outputs Perlin-noise values that usually range from
+ /// -1.0 to +1.0, but there are no guarantees that all output values will
+ /// exist within that range.
+ ///
+ /// For a better description of Perlin noise, see the links in the
+ /// <i>References and Acknowledgments</i> section.
+ ///
+ /// This noise module does not require any source modules.
+ ///
+ /// <b>Octaves</b>
+ ///
+ /// The number of octaves control the <i>amount of detail</i> of the
+ /// Perlin noise. Adding more octaves increases the detail of the Perlin
+ /// noise, but with the drawback of increasing the calculation time.
+ ///
+ /// An octave is one of the coherent-noise functions in a series of
+ /// coherent-noise functions that are added together to form Perlin
+ /// noise.
+ ///
+ /// An application may specify the frequency of the first octave by
+ /// calling the setFrequency() method.
+ ///
+ /// An application may specify the number of octaves that generate Perlin
+ /// noise by calling the setOctaveCount() method.
+ ///
+ /// These coherent-noise functions are called octaves because each octave
+ /// has, by default, double the frequency of the previous octave. Musical
+ /// tones have this property as well; a musical C tone that is one octave
+ /// higher than the previous C tone has double its frequency.
+ ///
+ /// <b>Frequency</b>
+ ///
+ /// An application may specify the frequency of the first octave by
+ /// calling the setFrequency() method.
+ ///
+ /// <b>Persistence</b>
+ ///
+ /// The persistence value controls the <i>roughness</i> of the Perlin
+ /// noise. Larger values produce rougher noise.
+ ///
+ /// The persistence value determines how quickly the amplitudes diminish
+ /// for successive octaves. The amplitude of the first octave is 1.0.
+ /// The amplitude of each subsequent octave is equal to the product of the
+ /// previous octave's amplitude and the persistence value. So a
+ /// persistence value of 0.5 sets the amplitude of the first octave to
+ /// 1.0; the second, 0.5; the third, 0.25; etc.
+ ///
+ /// An application may specify the persistence value by calling the
+ /// setPersistence() method.
+ ///
+ /// <b>Lacunarity</b>
+ ///
+ /// The lacunarity specifies the frequency multipler between successive
+ /// octaves.
+ ///
+ /// The effect of modifying the lacunarity is subtle; you may need to play
+ /// with the lacunarity value to determine the effects. For best results,
+ /// set the lacunarity to a number between 1.5 and 3.5.
+ ///
+ /// <b>References &amp; acknowledgments</b>
+ ///
+ /// <a href=http://www.noisemachine.com/talk1/>The Noise Machine</a> -
+ /// From the master, Ken Perlin himself. This page contains a
+ /// presentation that describes Perlin noise and some of its variants.
+ /// He won an Oscar for creating the Perlin noise algorithm!
+ ///
+ /// <a
+ /// href=http://freespace.virgin.net/hugo.elias/models/m_perlin.htm>
+ /// Perlin Noise</a> - Hugo Elias's webpage contains a very good
+ /// description of Perlin noise and describes its many applications. This
+ /// page gave me the inspiration to create libnoise in the first place.
+ /// Now that I know how to generate Perlin noise, I will never again use
+ /// cheesy subdivision algorithms to create terrain (unless I absolutely
+ /// need the speed.)
+ ///
+ /// <a
+ /// href=http://www.robo-murito.net/code/perlin-noise-math-faq.html>The
+ /// Perlin noise math FAQ</a> - A good page that describes Perlin noise in
+ /// plain English with only a minor amount of math. During development of
+ /// libnoise, I noticed that my coherent-noise function generated terrain
+ /// with some "regularity" to the terrain features. This page describes a
+ /// better coherent-noise function called <i>gradient noise</i>. This
+ /// version of the Perlin module uses gradient coherent noise to
+ /// generate Perlin noise.
+
+
+ /// Default frequency for the noise::module::Perlin noise module.
+ static final double DEFAULT_PERLIN_FREQUENCY = 1.0;
+
+ /// Default lacunarity for the noise::module::Perlin noise module.
+ static final double DEFAULT_PERLIN_LACUNARITY = 2.0;
+
+ /// Default number of octaves for the noise::module::Perlin noise module.
+ static final int DEFAULT_PERLIN_OCTAVE_COUNT = 6;
+
+ /// Default persistence value for the noise::module::Perlin noise module.
+ static final double DEFAULT_PERLIN_PERSISTENCE = 0.5;
+
+ /// Default noise quality for the noise::module::Perlin noise module.
+ static final NoiseQuality DEFAULT_PERLIN_QUALITY = NoiseQuality.QUALITY_STD;
+
+ /// Default noise seed for the noise::module::Perlin noise module.
+ static final int DEFAULT_PERLIN_SEED = 0;
+
+ /// Maximum number of octaves for the noise::module::Perlin noise module.
+ static final int PERLIN_MAX_OCTAVE = 30;
+
+
+ /// Frequency of the first octave.
+ double frequency;
+
+ /// Frequency multiplier between successive octaves.
+ double lacunarity;
+
+ /// Quality of the Perlin noise.
+ NoiseQuality noiseQuality;
+
+ /// Total number of octaves that generate the Perlin noise.
+ int octaveCount;
+
+ /// Persistence of the Perlin noise.
+ double persistence;
+
+ /// Seed value used by the Perlin-noise function.
+ int seed;
+
+
+ public Perlin ()
+ {
+ super(0);
+ frequency = DEFAULT_PERLIN_FREQUENCY;
+ lacunarity = DEFAULT_PERLIN_LACUNARITY;
+ noiseQuality = DEFAULT_PERLIN_QUALITY;
+ octaveCount = DEFAULT_PERLIN_OCTAVE_COUNT;
+ persistence = DEFAULT_PERLIN_PERSISTENCE;
+ seed = DEFAULT_PERLIN_SEED;
+ }
+
+ public double getValue (double x, double y, double z)
+ {
+ double value = 0.0;
+ double signal = 0.0;
+ double curPersistence = 1.0;
+ double nx, ny, nz;
+ int curSeed;
+
+ x *= frequency;
+ y *= frequency;
+ z *= frequency;
+
+ for (int curOctave = 0; curOctave < octaveCount; curOctave++)
+ {
+
+ // Make sure that these floating-point values have the same range as a 32-
+ // bit integer so that we can pass them to the coherent-noise functions.
+ nx = NoiseGen.MakeInt32Range (x);
+ ny = NoiseGen.MakeInt32Range (y);
+ nz = NoiseGen.MakeInt32Range (z);
+
+ // Get the coherent-noise value from the input value and add it to the
+ // final result.
+ curSeed = (seed + curOctave) & 0xffffffff;
+ signal = NoiseGen.GradientCoherentNoise3D (nx, ny, nz, curSeed, noiseQuality);
+ value += signal * curPersistence;
+
+ // Prepare the next octave.
+ x *= lacunarity;
+ y *= lacunarity;
+ z *= lacunarity;
+ curPersistence *= persistence;
+ }
+
+ return value;
+ }
+
+ /// Returns the frequency of the first octave.
+ ///
+ /// @returns The frequency of the first octave.
+ public double getFrequency ()
+ {
+ return frequency;
+ }
+
+ /// Returns the lacunarity of the Perlin noise.
+ ///
+ /// @returns The lacunarity of the Perlin noise.
+ ///
+ /// The lacunarity is the frequency multiplier between successive
+ /// octaves.
+ public double getLacunarity ()
+ {
+ return lacunarity;
+ }
+
+ /// Returns the quality of the Perlin noise.
+ ///
+ /// @returns The quality of the Perlin noise.
+ ///
+ /// See NoiseQuality for definitions of the various
+ /// coherent-noise qualities.
+ public NoiseQuality getNoiseQuality ()
+ {
+ return noiseQuality;
+ }
+
+ /// Returns the number of octaves that generate the Perlin noise.
+ ///
+ /// @returns The number of octaves that generate the Perlin noise.
+ ///
+ /// The number of octaves controls the amount of detail in the Perlin
+ /// noise.
+ public int getOctaveCount ()
+ {
+ return octaveCount;
+ }
+
+ /// Returns the persistence value of the Perlin noise.
+ ///
+ /// @returns The persistence value of the Perlin noise.
+ ///
+ /// The persistence value controls the roughness of the Perlin noise.
+ public double getPersistence ()
+ {
+ return persistence;
+ }
+
+ /// Returns the seed value used by the Perlin-noise function.
+ ///
+ /// @returns The seed value.
+ public int getSeed ()
+ {
+ return seed;
+ }
+
+ /// Sets the frequency of the first octave.
+ ///
+ /// @param frequency The frequency of the first octave.
+ public void setFrequency (double frequency)
+ {
+ this.frequency = frequency;
+ }
+
+ /// Sets the lacunarity of the Perlin noise.
+ ///
+ /// @param lacunarity The lacunarity of the Perlin noise.
+ ///
+ /// The lacunarity is the frequency multiplier between successive
+ /// octaves.
+ ///
+ /// For best results, set the lacunarity to a number between 1.5 and
+ /// 3.5.
+ public void setLacunarity (double lacunarity)
+ {
+ this.lacunarity = lacunarity;
+ }
+
+ /// Sets the quality of the Perlin noise.
+ ///
+ /// @param noiseQuality The quality of the Perlin noise.
+ ///
+ /// See NoiseQuality for definitions of the various
+ /// coherent-noise qualities.
+ public void setNoiseQuality (NoiseQuality noiseQuality)
+ {
+ this.noiseQuality = noiseQuality;
+ }
+
+ /// Sets the number of octaves that generate the Perlin noise.
+ ///
+ /// @param octaveCount The number of octaves that generate the Perlin
+ /// noise.
+ ///
+ /// @pre The number of octaves ranges from 1 to PERLIN_MAX_OCTAVE.
+ ///
+ /// @throw noise::ExceptionInvalidParam An invalid parameter was
+ /// specified; see the preconditions for more information.
+ ///
+ /// The number of octaves controls the amount of detail in the Perlin
+ /// noise.
+ ///
+ /// The larger the number of octaves, the more time required to
+ /// calculate the Perlin-noise value.
+ public void setOctaveCount (int octaveCount) throws ExceptionInvalidParam
+ {
+ if (octaveCount < 1 || octaveCount > PERLIN_MAX_OCTAVE)
+ {
+ throw new ExceptionInvalidParam ("Invalid parameter In Perlin Noise Module");
+ }
+
+ this.octaveCount = octaveCount;
+ }
+
+ /// Sets the persistence value of the Perlin noise.
+ ///
+ /// @param persistence The persistence value of the Perlin noise.
+ ///
+ /// The persistence value controls the roughness of the Perlin noise.
+ ///
+ /// For best results, set the persistence to a number between 0.0 and
+ /// 1.0.
+ public void setPersistence (double persistence)
+ {
+ this.persistence = persistence;
+ }
+
+ /// Sets the seed value used by the Perlin-noise function.
+ ///
+ /// @param seed The seed value.
+ public void setSeed (int seed)
+ {
+ this.seed = seed;
+ }
+
+}
diff --git a/src/libnoiseforjava/module/Power.java b/src/libnoiseforjava/module/Power.java
new file mode 100644
index 0000000..53484a9
--- /dev/null
+++ b/src/libnoiseforjava/module/Power.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+import libnoiseforjava.exception.ExceptionInvalidParam;
+
+public class Power extends ModuleBase
+{
+ /// Noise module that raises the output value from a first source module
+ /// to the power of the output value from a second source module.
+ ///
+ /// The first source module must have an index value of 0.
+ ///
+ /// The second source module must have an index value of 1.
+ ///
+ /// This noise module requires two source modules.
+
+ public Power (ModuleBase sourceModuleOne, ModuleBase sourceModuleTwo) throws ExceptionInvalidParam
+ {
+ super(2);
+ setSourceModule(0, sourceModuleOne);
+ setSourceModule(1, sourceModuleTwo);
+ }
+
+ public double getValue (double x, double y, double z)
+ {
+ assert (sourceModules[0] != null);
+ assert (sourceModules[1] != null);
+
+ return Math.pow (sourceModules[0].getValue (x, y, z),
+ sourceModules[1].getValue (x, y, z));
+ }
+}
diff --git a/src/libnoiseforjava/module/RidgedMulti.java b/src/libnoiseforjava/module/RidgedMulti.java
new file mode 100644
index 0000000..c1a2d4c
--- /dev/null
+++ b/src/libnoiseforjava/module/RidgedMulti.java
@@ -0,0 +1,357 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+import libnoiseforjava.NoiseGen;
+import libnoiseforjava.NoiseGen.NoiseQuality;
+import libnoiseforjava.exception.ExceptionInvalidParam;
+
+public class RidgedMulti extends ModuleBase
+{
+ /// Noise module that outputs 3-dimensional ridged-multifractal noise.
+ ///
+ /// This noise module, heavily based on the Perlin-noise module, generates
+ /// ridged-multifractal noise. Ridged-multifractal noise is generated in
+ /// much of the same way as Perlin noise, except the output of each octave
+ /// is modified by an absolute-value function. Modifying the octave
+ /// values in this way produces ridge-like formations.
+ ///
+ /// Ridged-multifractal noise does not use a persistence value. This is
+ /// because the persistence values of the octaves are based on the values
+ /// generated from from previous octaves, creating a feedback loop (or
+ /// that's what it looks like after reading the code.)
+ ///
+ /// This noise module outputs ridged-multifractal-noise values that
+ /// usually range from -1.0 to +1.0, but there are no guarantees that all
+ /// output values will exist within that range.
+ ///
+ /// @note For ridged-multifractal noise generated with only one octave,
+ /// the output value ranges from -1.0 to 0.0.
+ ///
+ /// Ridged-multifractal noise is often used to generate craggy mountainous
+ /// terrain or marble-like textures.
+ ///
+ /// This noise module does not require any source modules.
+ ///
+ /// <b>Octaves</b>
+ ///
+ /// The number of octaves control the <i>amount of detail</i> of the
+ /// ridged-multifractal noise. Adding more octaves increases the detail
+ /// of the ridged-multifractal noise, but with the drawback of increasing
+ /// the calculation time.
+ ///
+ /// An application may specify the number of octaves that generate
+ /// ridged-multifractal noise by calling the setOctaveCount() method.
+ ///
+ /// <b>Frequency</b>
+ ///
+ /// An application may specify the frequency of the first octave by
+ /// calling the setFrequency() method.
+ ///
+ /// <b>Lacunarity</b>
+ ///
+ /// The lacunarity specifies the frequency multipler between successive
+ /// octaves.
+ ///
+ /// The effect of modifying the lacunarity is subtle; you may need to play
+ /// with the lacunarity value to determine the effects. For best results,
+ /// set the lacunarity to a number between 1.5 and 3.5.
+ ///
+ /// <b>References &amp; Acknowledgments</b>
+ ///
+ /// <a href=http://www.texturingandmodeling.com/Musgrave.html>F.
+ /// Kenton "Doc Mojo" Musgrave's texturing page</a> - This page contains
+ /// links to source code that generates ridged-multfractal noise, among
+ /// other types of noise. The source file <a
+ /// href=http://www.texturingandmodeling.com/CODE/MUSGRAVE/CLOUD/fractal.c>
+ /// fractal.c</a> contains the code I used in my ridged-multifractal class
+ /// (see the @a RidgedMultifractal() function.) This code was written by F.
+ /// Kenton Musgrave, the person who created
+ /// <a href=http://www.pandromeda.com/>MojoWorld</a>. He is also one of
+ /// the authors in <i>Texturing and Modeling: A Procedural Approach</i>
+ /// (Morgan Kaufmann, 2002. ISBN 1-55860-848-6.)
+
+ /// Default frequency for the noise::module::RidgedMulti noise module.
+ static final double DEFAULT_RIDGED_FREQUENCY = 1.0;
+
+ /// Default lacunarity for the noise::module::RidgedMulti noise module.
+ static final double DEFAULT_RIDGED_LACUNARITY = 2.0;
+
+ /// Default number of octaves for the noise::module::RidgedMulti noise
+ /// module.
+ static final int DEFAULT_RIDGED_OCTAVE_COUNT = 6;
+
+ /// Default noise quality for the noise::module::RidgedMulti noise
+ /// module.
+ static final NoiseQuality DEFAULT_RIDGED_QUALITY = NoiseQuality.QUALITY_STD;
+
+ /// Default noise seed for the noise::module::RidgedMulti noise module.
+ static final int DEFAULT_RIDGED_SEED = 0;
+
+ /// Maximum number of octaves for the noise::module::RidgedMulti noise
+ /// module.
+ static final int RIDGED_MAX_OCTAVE = 30;
+
+ /// Frequency of the first octave.
+ double frequency;
+
+ /// Frequency multiplier between successive octaves.
+ double lacunarity;
+
+ /// Quality of the ridged-multifractal noise.
+ NoiseQuality noiseQuality;
+
+ /// Total number of octaves that generate the ridged-multifractal
+ /// noise.
+ int octaveCount;
+
+ /// Contains the spectral weights for each octave.
+ double [] spectralWeights = new double[RIDGED_MAX_OCTAVE];
+
+ /// Seed value used by the ridged-multfractal-noise function.
+ int seed;
+
+
+ public RidgedMulti ()
+ {
+ super(0);
+ frequency = DEFAULT_RIDGED_FREQUENCY;
+ lacunarity = DEFAULT_RIDGED_LACUNARITY;
+ noiseQuality = DEFAULT_RIDGED_QUALITY;
+ octaveCount = DEFAULT_RIDGED_OCTAVE_COUNT;
+ seed = DEFAULT_RIDGED_SEED;
+
+ calcSpectralWeights();
+ }
+
+ // Calculates the spectral weights for each octave.
+ public void calcSpectralWeights ()
+ {
+ // This exponent parameter should be user-defined; it may be exposed in a
+ // future version of libnoise.
+ double h = 1.0;
+
+ double frequency = 1.0;
+ for (int i = 0; i < RIDGED_MAX_OCTAVE; i++) {
+ // Compute weight for each frequency.
+ this.spectralWeights[i] = Math.pow (frequency, -h);
+ frequency *= lacunarity;
+ }
+ }
+
+ // Multifractal code originally written by F. Kenton "Doc Mojo" Musgrave,
+ // 1998. Modified by jas for use with libnoise.
+ public double getValue (double x, double y, double z)
+ {
+ x *= frequency;
+ y *= frequency;
+ z *= frequency;
+
+ double signal = 0.0;
+ double value = 0.0;
+ double weight = 1.0;
+
+ // These parameters should be user-defined; they may be exposed in a
+ // future version of libnoiseforjava.
+ double offset = 1.0;
+ double gain = 2.0;
+
+ for (int curOctave = 0; curOctave < octaveCount; curOctave++)
+ {
+ // Make sure that these floating-point values have the same range as a 32-
+ // bit integer so that we can pass them to the coherent-noise functions.
+ double nx, ny, nz;
+ nx = NoiseGen.MakeInt32Range (x);
+ ny = NoiseGen.MakeInt32Range (y);
+ nz = NoiseGen.MakeInt32Range (z);
+
+ // Get the coherent-noise value.
+ int curSeed = (seed + curOctave) & 0x7fffffff;
+ signal = NoiseGen.GradientCoherentNoise3D (nx, ny, nz, curSeed, noiseQuality);
+
+ // Make the ridges.
+ signal = Math.abs (signal);
+ signal = offset - signal;
+
+ // Square the signal to increase the sharpness of the ridges.
+ signal *= signal;
+
+ // The weighting from the previous octave is applied to the signal.
+ // Larger values have higher weights, producing sharp points along the
+ // ridges.
+ signal *= weight;
+
+ // Weight successive contributions by the previous signal.
+ weight = signal * gain;
+ if (weight > 1.0)
+ weight = 1.0;
+ if (weight < 0.0)
+ weight = 0.0;
+
+
+ // Add the signal to the output value.
+ value += (signal * spectralWeights[curOctave]);
+
+ // Go to the next octave.
+ x *= lacunarity;
+ y *= lacunarity;
+ z *= lacunarity;
+ }
+
+ return (value * 1.25) - 1.0;
+ }
+
+ public double getFrequency ()
+ {
+ return frequency;
+ }
+
+ /// Returns the lacunarity of the ridged-multifractal noise.
+ ///
+ /// @returns The lacunarity of the ridged-multifractal noise.
+ ///
+ /// The lacunarity is the frequency multiplier between successive
+ /// octaves.
+ public double getLacunarity ()
+ {
+ return lacunarity;
+ }
+
+ /// Returns the quality of the ridged-multifractal noise.
+ ///
+ /// @returns The quality of the ridged-multifractal noise.
+ ///
+ /// See noise::NoiseQuality for definitions of the various
+ /// coherent-noise qualities.
+ public NoiseQuality getNoiseQuality ()
+ {
+ return noiseQuality;
+ }
+
+ /// Returns the number of octaves that generate the
+ /// ridged-multifractal noise.
+ ///
+ /// @returns The number of octaves that generate the
+ /// ridged-multifractal noise.
+ ///
+ /// The number of octaves controls the amount of detail in the
+ /// ridged-multifractal noise.
+ public int getOctaveCount ()
+ {
+ return octaveCount;
+ }
+
+ /// Returns the seed value used by the ridged-multifractal-noise
+ /// function.
+ ///
+ /// @returns The seed value.
+ public int getSeed ()
+ {
+ return seed;
+ }
+
+
+ /// Sets the frequency of the first octave.
+ ///
+ /// @param frequency The frequency of the first octave.
+ public void setFrequency (double frequency)
+ {
+ this.frequency = frequency;
+ }
+
+ /// Sets the lacunarity of the ridged-multifractal noise.
+ ///
+ /// @param lacunarity The lacunarity of the ridged-multifractal noise.
+ ///
+ /// The lacunarity is the frequency multiplier between successive
+ /// octaves.
+ ///
+ /// For best results, set the lacunarity to a number between 1.5 and
+ /// 3.5.
+ public void setLacunarity (double lacunarity)
+ {
+ this.lacunarity = lacunarity;
+ calcSpectralWeights ();
+ }
+
+ /// Sets the quality of the ridged-multifractal noise.
+ ///
+ /// @param noiseQuality The quality of the ridged-multifractal noise.
+ ///
+ /// See NoiseQuality for definitions of the various
+ /// coherent-noise qualities.
+ public void setNoiseQuality (NoiseQuality noiseQuality)
+ {
+ this.noiseQuality = noiseQuality;
+ }
+
+ /// Sets the number of octaves that generate the ridged-multifractal
+ /// noise.
+ ///
+ /// @param octaveCount The number of octaves that generate the
+ /// ridged-multifractal noise.
+ ///
+ /// @pre The number of octaves ranges from 1 to RIDGED_MAX_OCTAVE.
+ ///
+ /// @throw ExceptionInvalidParam An invalid parameter was
+ /// specified; see the preconditions for more information.
+ ///
+ /// The number of octaves controls the amount of detail in the
+ /// ridged-multifractal noise.
+ ///
+ /// The larger the number of octaves, the more time required to
+ /// calculate the ridged-multifractal-noise value.
+ public void setOctaveCount (int octaveCount) throws ExceptionInvalidParam
+ {
+ if (octaveCount > RIDGED_MAX_OCTAVE)
+ {
+ throw new ExceptionInvalidParam ("An invalid parameter was passed" +
+ " to a libnoise function or method.");
+ }
+
+ this.octaveCount = octaveCount;
+ }
+
+ /// Sets the seed value used by the ridged-multifractal-noise
+ /// function.
+ ///
+ /// @param seed The seed value.
+ public void setSeed (int seed)
+ {
+ this.seed = seed;
+ }
+
+ public double[] getSpectralWeights()
+ {
+ return spectralWeights;
+ }
+
+ public void setSpectralWeights(double[] spectralWeights)
+ {
+ this.spectralWeights = spectralWeights;
+ }
+
+}
diff --git a/src/libnoiseforjava/module/RotatePoint.java b/src/libnoiseforjava/module/RotatePoint.java
new file mode 100644
index 0000000..a1a57b5
--- /dev/null
+++ b/src/libnoiseforjava/module/RotatePoint.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+import libnoiseforjava.exception.ExceptionInvalidParam;
+
+public class RotatePoint extends ModuleBase
+{
+ /// Noise module that rotates the input value around the origin before
+ /// returning the output value from a source module.
+ ///
+ /// The getValue() method rotates the coordinates of the input value
+ /// around the origin before returning the output value from the source
+ /// module. To set the rotation angles, call the setAngles() method. To
+ /// set the rotation angle around the individual @a x, @a y, or @a z axes,
+ /// call the setXAngle(), setYAngle() or setZAngle() methods,
+ /// respectively.
+ ///
+ /// The coordinate system of the input value is assumed to be
+ /// "left-handed" (@a x increases to the right, @a y increases upward,
+ /// and @a z increases inward.)
+ ///
+ /// This noise module requires one source module.
+
+ /// Default @a x rotation angle for the RotatePoint noise
+ /// module.
+ static final double DEFAULT_ROTATE_X = 0.0;
+
+ /// Default @a y rotation angle for the RotatePoint noise
+ /// module.
+ static final double DEFAULT_ROTATE_Y = 0.0;
+
+ /// Default @a z rotation angle for the RotatePoint noise
+ /// module.
+ static final double DEFAULT_ROTATE_Z = 0.0;
+
+
+ /// An entry within the 3x3 rotation matrix used for rotating the
+ /// input value.
+ double x1Matrix;
+
+ /// An entry within the 3x3 rotation matrix used for rotating the
+ /// input value.
+ double x2Matrix;
+
+ /// An entry within the 3x3 rotation matrix used for rotating the
+ /// input value.
+ double x3Matrix;
+
+ /// @a x rotation angle applied to the input value, in degrees.
+ double xAngle;
+
+ /// An entry within the 3x3 rotation matrix used for rotating the
+ /// input value.
+ double y1Matrix;
+
+ /// An entry within the 3x3 rotation matrix used for rotating the
+ /// input value.
+ double y2Matrix;
+
+ /// An entry within the 3x3 rotation matrix used for rotating the
+ /// input value.
+ double y3Matrix;
+
+ /// @a y rotation angle applied to the input value, in degrees.
+ double yAngle;
+
+ /// An entry within the 3x3 rotation matrix used for rotating the
+ /// input value.
+ double z1Matrix;
+
+ /// An entry within the 3x3 rotation matrix used for rotating the
+ /// input value.
+ double z2Matrix;
+
+ /// An entry within the 3x3 rotation matrix used for rotating the
+ /// input value.
+ double z3Matrix;
+
+ /// @a z rotation angle applied to the input value, in degrees.
+ double zAngle;
+
+
+ public RotatePoint (ModuleBase sourceModule) throws ExceptionInvalidParam
+ {
+ super(1);
+ setSourceModule(0, sourceModule);
+ setAngles (DEFAULT_ROTATE_X, DEFAULT_ROTATE_Y, DEFAULT_ROTATE_Z);
+ }
+
+ public double getValue (double x, double y, double z)
+ {
+ assert (sourceModules[0] != null);
+
+ double nx = (x1Matrix * x) + (y1Matrix * y) + (z1Matrix * z);
+ double ny = (x2Matrix * x) + (y2Matrix * y) + (z2Matrix * z);
+ double nz = (x3Matrix * x) + (y3Matrix * y) + (z3Matrix * z);
+ return sourceModules[0].getValue (nx, ny, nz);
+ }
+
+ public void setAngles (double xAngle, double yAngle,
+ double zAngle)
+ {
+ double xCos, yCos, zCos, xSin, ySin, zSin;
+ xCos = Math.cos (Math.toRadians(xAngle));
+ yCos = Math.cos (Math.toRadians(yAngle));
+ zCos = Math.cos (Math.toRadians(zAngle));
+ xSin = Math.sin (Math.toRadians(xAngle));
+ ySin = Math.sin (Math.toRadians(yAngle));
+ zSin = Math.sin (Math.toRadians(zAngle));
+
+ x1Matrix = ySin * xSin * zSin + yCos * zCos;
+ y1Matrix = xCos * zSin;
+ z1Matrix = ySin * zCos - yCos * xSin * zSin;
+ x2Matrix = ySin * xSin * zCos - yCos * zSin;
+ y2Matrix = xCos * zCos;
+ z2Matrix = -yCos * xSin * zCos - ySin * zSin;
+ x3Matrix = -ySin * xCos;
+ y3Matrix = xSin;
+ z3Matrix = yCos * xCos;
+
+ this.xAngle = xAngle;
+ this.yAngle = yAngle;
+ this.zAngle = zAngle;
+ }
+
+ /// Returns the rotation angle around the @a x axis to apply to the
+ /// input value.
+ ///
+ /// @returns The rotation angle around the @a x axis, in degrees.
+ public double getXAngle ()
+ {
+ return xAngle;
+ }
+
+ /// Returns the rotation angle around the @a y axis to apply to the
+ /// input value.
+ ///
+ /// @returns The rotation angle around the @a y axis, in degrees.
+ public double getYAngle ()
+ {
+ return yAngle;
+ }
+
+ /// Returns the rotation angle around the @a z axis to apply to the
+ /// input value.
+ ///
+ /// @returns The rotation angle around the @a z axis, in degrees.
+ public double getZAngle ()
+ {
+ return zAngle;
+ }
+
+ /// Sets the rotation angle around the @a x axis to apply to the input
+ /// value.
+ ///
+ /// @param xAngle The rotation angle around the @a x axis, in degrees.
+ ///
+ /// The getValue() method rotates the coordinates of the input value
+ /// around the origin before returning the output value from the
+ /// source module.
+ public void setXAngle (double xAngle)
+ {
+ setAngles (xAngle, this.yAngle, this.zAngle);
+ }
+
+ /// Sets the rotation angle around the @a y axis to apply to the input
+ /// value.
+ ///
+ /// @param yAngle The rotation angle around the @a y axis, in degrees.
+ ///
+ /// The getValue() method rotates the coordinates of the input value
+ /// around the origin before returning the output value from the
+ /// source module.
+ public void SetYAngle (double yAngle)
+ {
+ setAngles (this.xAngle, yAngle, this.zAngle);
+ }
+
+ /// Sets the rotation angle around the @a z axis to apply to the input
+ /// value.
+ ///
+ /// @param zAngle The rotation angle around the @a z axis, in degrees.
+ ///
+ /// The getValue() method rotates the coordinates of the input value
+ /// around the origin before returning the output value from the
+ /// source module.
+ public void SetZAngle (double zAngle)
+ {
+ setAngles (this.xAngle, this.yAngle, zAngle);
+ }
+
+}
diff --git a/src/libnoiseforjava/module/ScaleBias.java b/src/libnoiseforjava/module/ScaleBias.java
new file mode 100644
index 0000000..66daea4
--- /dev/null
+++ b/src/libnoiseforjava/module/ScaleBias.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+import libnoiseforjava.exception.ExceptionInvalidParam;
+
+public class ScaleBias extends ModuleBase
+{
+
+ /// Noise module that applies a scaling factor and a bias to the output
+ /// value from a source module.
+ ///
+ /// The getValue() method retrieves the output value from the source
+ /// module, multiplies it with a scaling factor, adds a bias to it, then
+ /// outputs the value.
+ ///
+ /// This noise module requires one source module.
+
+ /// Default bias for the ScaleBias noise module.
+ static final double DEFAULT_BIAS = 0.0;
+
+ /// Default scale for the ScaleBias noise module.
+ static final double DEFAULT_SCALE = 1.0;
+
+ /// Bias to apply to the scaled output value from the source module.
+ double bias;
+
+ /// Scaling factor to apply to the output value from the source
+ /// module.
+ double scale;
+
+
+ public ScaleBias (ModuleBase sourceModule) throws ExceptionInvalidParam
+ {
+ super(1);
+ setSourceModule(0, sourceModule);
+ bias = DEFAULT_BIAS;
+ scale = DEFAULT_SCALE;
+ }
+
+ public double getValue (double x, double y, double z)
+ {
+ assert (sourceModules[0] != null);
+
+ return sourceModules[0].getValue (x, y, z) * scale + bias;
+ }
+
+ /// Returns the bias to apply to the scaled output value from the
+ /// source module.
+ ///
+ /// @returns The bias to apply.
+ ///
+ /// The getValue() method retrieves the output value from the source
+ /// module, multiplies it with the scaling factor, adds the bias to
+ /// it, then outputs the value.
+ public double getBias ()
+ {
+ return bias;
+ }
+
+ /// Returns the scaling factor to apply to the output value from the
+ /// source module.
+ ///
+ /// @returns The scaling factor to apply.
+ ///
+ /// The getValue() method retrieves the output value from the source
+ /// module, multiplies it with the scaling factor, adds the bias to
+ /// it, then outputs the value.
+ public double getScale ()
+ {
+ return scale;
+ }
+
+
+ /// Sets the bias to apply to the scaled output value from the source
+ /// module.
+ ///
+ /// @param bias The bias to apply.
+ ///
+ /// The getValue() method retrieves the output value from the source
+ /// module, multiplies it with the scaling factor, adds the bias to
+ /// it, then outputs the value.
+ public void setBias (double bias)
+ {
+ this.bias = bias;
+ }
+
+ /// Sets the scaling factor to apply to the output value from the
+ /// source module.
+ ///
+ /// @param scale The scaling factor to apply.
+ ///
+ /// The getValue() method retrieves the output value from the source
+ /// module, multiplies it with the scaling factor, adds the bias to
+ /// it, then outputs the value.
+ public void setScale (double scale)
+ {
+ this.scale = scale;
+ }
+
+}
diff --git a/src/libnoiseforjava/module/ScalePoint.java b/src/libnoiseforjava/module/ScalePoint.java
new file mode 100644
index 0000000..f0c10ce
--- /dev/null
+++ b/src/libnoiseforjava/module/ScalePoint.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+import libnoiseforjava.exception.ExceptionInvalidParam;
+
+public class ScalePoint extends ModuleBase
+{
+
+ /// Noise module that scales the coordinates of the input value before
+ /// returning the output value from a source module.
+ ///
+ /// The getValue() method multiplies the ( @a x, @a y, @a z ) coordinates
+ /// of the input value with a scaling factor before returning the output
+ /// value from the source module. To set the scaling factor, call the
+ /// setScale() method. To set the scaling factor to apply to the
+ /// individual @a x, @a y, or @a z coordinates, call the setXScale(),
+ /// setYScale() or setZScale() methods, respectively.
+ ///
+ /// This noise module requires one source module.
+
+ // Default scaling factor applied to the @a x coordinate for the
+ /// ScalePoint noise module.
+ static final double DEFAULT_SCALE_POINT_X = 1.0;
+
+ /// Default scaling factor applied to the @a y coordinate for the
+ /// ScalePoint noise module.
+ static final double DEFAULT_SCALE_POINT_Y = 1.0;
+
+ /// Default scaling factor applied to the @a z coordinate for the
+ /// ScalePoint noise module.
+ static final double DEFAULT_SCALE_POINT_Z = 1.0;
+
+ /// Scaling factor applied to the @a x coordinate of the input value.
+ double xScale;
+
+ /// Scaling factor applied to the @a y coordinate of the input value.
+ double yScale;
+
+ /// Scaling factor applied to the @a z coordinate of the input value.
+ double zScale;
+
+
+ public ScalePoint (ModuleBase sourceModule) throws ExceptionInvalidParam
+ {
+ super(1);
+ setSourceModule(0, sourceModule);
+
+ xScale = DEFAULT_SCALE_POINT_X;
+ yScale = DEFAULT_SCALE_POINT_Y;
+ zScale = DEFAULT_SCALE_POINT_Z;
+ }
+
+ public double getValue (double x, double y, double z)
+ {
+ assert (sourceModules[0] != null);
+
+ return sourceModules[0].getValue (x * xScale, y * yScale,
+ z * zScale);
+ }
+
+ /// Returns the scaling factor applied to the @a x coordinate of the
+ /// input value.
+ ///
+ /// @returns The scaling factor applied to the @a x coordinate.
+ public double getXScale ()
+ {
+ return xScale;
+ }
+
+ /// Returns the scaling factor applied to the @a y coordinate of the
+ /// input value.
+ ///
+ /// @returns The scaling factor applied to the @a y coordinate.
+ public double getYScale ()
+ {
+ return yScale;
+ }
+
+ /// Returns the scaling factor applied to the @a z coordinate of the
+ /// input value.
+ ///
+ /// @returns The scaling factor applied to the @a z coordinate.
+ public double getZScale ()
+ {
+ return zScale;
+ }
+
+ /// Sets the scaling factor to apply to the input value.
+ ///
+ /// @param scale The scaling factor to apply.
+ ///
+ /// The getValue() method multiplies the ( @a x, @a y, @a z )
+ /// coordinates of the input value with a scaling factor before
+ /// returning the output value from the source module.
+ public void setScale (double scale)
+ {
+ this.xScale = scale;
+ this.yScale = scale;
+ this.zScale = scale;
+ }
+
+ /// Sets the scaling factor to apply to the ( @a x, @a y, @a z )
+ /// coordinates of the input value.
+ ///
+ /// @param xScale The scaling factor to apply to the @a x coordinate.
+ /// @param yScale The scaling factor to apply to the @a y coordinate.
+ /// @param zScale The scaling factor to apply to the @a z coordinate.
+ ///
+ /// The getValue() method multiplies the ( @a x, @a y, @a z )
+ /// coordinates of the input value with a scaling factor before
+ /// returning the output value from the source module.
+ public void setScale (double xScale, double yScale, double zScale)
+ {
+ this.xScale = xScale;
+ this.yScale = yScale;
+ this.zScale = zScale;
+ }
+
+ /// Sets the scaling factor to apply to the @a x coordinate of the
+ /// input value.
+ ///
+ /// @param xScale The scaling factor to apply to the @a x coordinate.
+ ///
+ /// The getValue() method multiplies the ( @a x, @a y, @a z )
+ /// coordinates of the input value with a scaling factor before
+ /// returning the output value from the source module.
+ public void setXScale (double xScale)
+ {
+ this.xScale = xScale;
+ }
+
+ /// Sets the scaling factor to apply to the @a y coordinate of the
+ /// input value.
+ ///
+ /// @param yScale The scaling factor to apply to the @a y coordinate.
+ ///
+ /// The getValue() method multiplies the ( @a x, @a y, @a z )
+ /// coordinates of the input value with a scaling factor before
+ /// returning the output value from the source module.
+ public void setYScale (double yScale)
+ {
+ this.yScale = yScale;
+ }
+
+ /// Sets the scaling factor to apply to the @a z coordinate of the
+ /// input value.
+ ///
+ /// @param zScale The scaling factor to apply to the @a z coordinate.
+ ///
+ /// The getValue() method multiplies the ( @a x, @a y, @a z )
+ /// coordinates of the input value with a scaling factor before
+ /// returning the output value from the source module.
+ public void setZScale (double zScale)
+ {
+ this.zScale = zScale;
+ }
+
+}
diff --git a/src/libnoiseforjava/module/Select.java b/src/libnoiseforjava/module/Select.java
new file mode 100644
index 0000000..d394aa3
--- /dev/null
+++ b/src/libnoiseforjava/module/Select.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+import libnoiseforjava.Interp;
+import libnoiseforjava.exception.ExceptionInvalidParam;
+import libnoiseforjava.exception.ExceptionNoModule;
+
+public class Select extends ModuleBase
+{
+ /// Noise module that outputs the value selected from one of two source
+ /// modules chosen by the output value from a control module.
+ ///
+ /// Unlike most other noise modules, the index value assigned to a source
+ /// module determines its role in the selection operation:
+ /// - Source module 0 (upper left in the diagram) outputs a value.
+ /// - Source module 1 (lower left in the diagram) outputs a value.
+ /// - Source module 2 (bottom of the diagram) is known as the <i>control
+ /// module</i>. The control module determines the value to select. If
+ /// the output value from the control module is within a range of values
+ /// known as the <i>selection range</i>, this noise module outputs the
+ /// value from the source module with an index value of 1. Otherwise,
+ /// this noise module outputs the value from the source module with an
+ /// index value of 0.
+ ///
+ /// To specify the bounds of the selection range, call the setBounds()
+ /// method.
+ ///
+ /// An application can pass the control module to the setControlModule()
+ /// method instead of the setSourceModule() method. This may make the
+ /// application code easier to read.
+ ///
+ /// By default, there is an abrupt transition between the output values
+ /// from the two source modules at the selection-range boundary. To
+ /// smooth the transition, pass a non-zero value to the setEdgeFalloff()
+ /// method. Higher values result in a smoother transition.
+ ///
+ /// This noise module requires three source modules.
+
+ /// Default edge-falloff value for the Select noise module.
+ static final double DEFAULT_SELECT_EDGE_FALLOFF = 0.0;
+
+ /// Default lower bound of the selection range for the
+ /// Select noise module.
+ static final double DEFAULT_SELECT_LOWER_BOUND = -1.0;
+
+ /// Default upper bound of the selection range for the
+ /// Select noise module.
+ static final double DEFAULT_SELECT_UPPER_BOUND = 1.0;
+
+ /// Edge-falloff value.
+ double edgeFalloff;
+
+ /// Lower bound of the selection range.
+ double lowerBound;
+
+ /// Upper bound of the selection range.
+ double upperBound;
+
+
+ public Select (ModuleBase sourceModuleOne, ModuleBase sourceModuleTwo,
+ ModuleBase sourceModuleThree) throws ExceptionInvalidParam
+ {
+ super(3);
+ setSourceModule(0, sourceModuleOne);
+ setSourceModule(1, sourceModuleTwo);
+ setSourceModule(2, sourceModuleThree);
+
+ edgeFalloff = DEFAULT_SELECT_EDGE_FALLOFF;
+ lowerBound = DEFAULT_SELECT_LOWER_BOUND;
+ upperBound = DEFAULT_SELECT_UPPER_BOUND;
+ }
+
+ public double getValue (double x, double y, double z)
+ {
+ assert (sourceModules[0] != null);
+ assert (sourceModules[1] != null);
+ assert (sourceModules[2] != null);
+
+ double controlValue = sourceModules[2].getValue (x, y, z);
+ double alpha;
+
+ if (edgeFalloff > 0.0)
+ {
+ if (controlValue < (lowerBound - edgeFalloff))
+ // The output value from the control module is below the selector
+ // threshold; return the output value from the first source module.
+ return sourceModules[0].getValue (x, y, z);
+ else if (controlValue < (lowerBound + edgeFalloff))
+ {
+ // The output value from the control module is near the lower end of the
+ // selector threshold and within the smooth curve. Interpolate between
+ // the output values from the first and second source modules.
+ double lowerCurve = (lowerBound - edgeFalloff);
+ double upperCurve = (lowerBound + edgeFalloff);
+ alpha = Interp.SCurve3 (
+ (controlValue - lowerCurve) / (upperCurve - lowerCurve));
+ return Interp.linearInterp (sourceModules[0].getValue (x, y, z),
+ sourceModules[2].getValue (x, y, z),
+ alpha);
+ }
+ else if (controlValue < (upperBound - edgeFalloff))
+ // The output value from the control module is within the selector
+ // threshold; return the output value from the second source module.
+ return sourceModules[1].getValue (x, y, z);
+ else if (controlValue < (upperBound + edgeFalloff))
+ {
+ // The output value from the control module is near the upper end of the
+ // selector threshold and within the smooth curve. Interpolate between
+ // the output values from the first and second source modules.
+ double lowerCurve = (upperBound - edgeFalloff);
+ double upperCurve = (upperBound + edgeFalloff);
+ alpha = Interp.SCurve3 (
+ (controlValue - lowerCurve) / (upperCurve - lowerCurve));
+ return Interp.linearInterp (sourceModules[1].getValue (x, y, z),
+ sourceModules[0].getValue (x, y, z),
+ alpha);
+ }
+ else
+ // Output value from the control module is above the selector threshold;
+ // return the output value from the first source module.
+ return sourceModules[0].getValue (x, y, z);
+ }
+ else
+ {
+ if (controlValue < lowerBound || controlValue > upperBound)
+ return sourceModules[0].getValue (x, y, z);
+ else
+ return sourceModules[1].getValue (x, y, z);
+ }
+ }
+
+ /// Sets the lower and upper bounds of the selection range.
+ ///
+ /// @param lowerBound The lower bound.
+ /// @param upperBound The upper bound.
+ ///
+ /// @pre The lower bound must be less than or equal to the upper
+ /// bound.
+ public void setBounds (double lowerBound, double upperBound)
+ {
+ assert (lowerBound < upperBound);
+
+ this.lowerBound = lowerBound;
+ this.upperBound = upperBound;
+
+ // Make sure that the edge falloff curves do not overlap.
+ setEdgeFalloff (edgeFalloff);
+ }
+
+ /// Sets the falloff value at the edge transition.
+ ///
+ /// @param edgeFalloff The falloff value at the edge transition.
+ ///
+ /// The falloff value is the width of the edge transition at either
+ /// edge of the selection range.
+ ///
+ /// By default, there is an abrupt transition between the values from
+ /// the two source modules at the boundaries of the selection range.
+ ///
+ /// For example, if the selection range is 0.5 to 0.8, and the edge
+ /// falloff value is 0.1, then the getValue() method outputs:
+ /// - the output value from the source module with an index value of 0
+ /// if the output value from the control module is less than 0.4
+ /// ( = 0.5 - 0.1).
+ /// - a linear blend between the two output values from the two source
+ /// modules if the output value from the control module is between
+ /// 0.4 ( = 0.5 - 0.1) and 0.6 ( = 0.5 + 0.1).
+ /// - the output value from the source module with an index value of 1
+ /// if the output value from the control module is between 0.6
+ /// ( = 0.5 + 0.1) and 0.7 ( = 0.8 - 0.1).
+ /// - a linear blend between the output values from the two source
+ /// modules if the output value from the control module is between
+ /// 0.7 ( = 0.8 - 0.1 ) and 0.9 ( = 0.8 + 0.1).
+ /// - the output value from the source module with an index value of 0
+ /// if the output value from the control module is greater than 0.9
+ /// ( = 0.8 + 0.1).
+ public void setEdgeFalloff (double edgeFalloff)
+ {
+ // Make sure that the edge falloff curves do not overlap.
+ double boundSize = upperBound - lowerBound;
+ edgeFalloff = (edgeFalloff > boundSize / 2)? boundSize / 2: edgeFalloff;
+ }
+
+ /// Returns the control module.
+ ///
+ /// @returns A reference to the control module.
+ ///
+ /// @pre A control module has been added to this noise module via a
+ /// call to setSourceModule() or setControlModule().
+ ///
+ /// @throw ExceptionNoModule See the preconditions for more
+ /// information.
+ ///
+ /// The control module determines the output value to select. If the
+ /// output value from the control module is within a range of values
+ /// known as the <i>selection range</i>, the getValue() method outputs
+ /// the value from the source module with an index value of 1.
+ /// Otherwise, this method outputs the value from the source module
+ /// with an index value of 0.
+
+ // not sure this does what it says it does. Recheck original source
+ public ModuleBase getControlModule () throws ExceptionNoModule
+ {
+ if (sourceModules == null || sourceModules[2] == null) {
+ throw new ExceptionNoModule ("Could not retrieve a source module from a noise module.");
+ }
+ return (sourceModules[2]);
+ }
+
+ /// Returns the falloff value at the edge transition.
+ ///
+ /// @returns The falloff value at the edge transition.
+ ///
+ /// The falloff value is the width of the edge transition at either
+ /// edge of the selection range.
+ ///
+ /// By default, there is an abrupt transition between the output
+ /// values from the two source modules at the selection-range
+ /// boundary.
+ public double getEdgeFalloff ()
+ {
+ return edgeFalloff;
+ }
+
+ /// Returns the lower bound of the selection range.
+ ///
+ /// @returns The lower bound of the selection range.
+ ///
+ /// If the output value from the control module is within the
+ /// selection range, the getValue() method outputs the value from the
+ /// source module with an index value of 1. Otherwise, this method
+ /// outputs the value from the source module with an index value of 0.
+ public double getLowerBound ()
+ {
+ return lowerBound;
+ }
+
+ /// Returns the upper bound of the selection range.
+ ///
+ /// @returns The upper bound of the selection range.
+ ///
+ /// If the output value from the control module is within the
+ /// selection range, the getValue() method outputs the value from the
+ /// source module with an index value of 1. Otherwise, this method
+ /// outputs the value from the source module with an index value of 0.
+ public double getUpperBound ()
+ {
+ return upperBound;
+ }
+
+ /// Sets the control module.
+ ///
+ /// @param controlModule The control module.
+ ///
+ /// The control module determines the output value to select. If the
+ /// output value from the control module is within a range of values
+ /// known as the <i>selection range</i>, the getValue() method outputs
+ /// the value from the source module with an index value of 1.
+ /// Otherwise, this method outputs the value from the source module
+ /// with an index value of 0.
+ ///
+ /// This method assigns the control module an index value of 2.
+ /// Passing the control module to this method produces the same
+ /// results as passing the control module to the setSourceModule()
+ /// method while assigning that noise module an index value of 2.
+ ///
+ /// This control module must exist throughout the lifetime of this
+ /// noise module unless another control module replaces that control
+ /// module.
+ public void setControlModule (ModuleBase controlModule)
+ {
+ assert (sourceModules != null);
+ sourceModules[2] = controlModule;
+ }
+
+}
diff --git a/src/libnoiseforjava/module/Simplex.java b/src/libnoiseforjava/module/Simplex.java
new file mode 100644
index 0000000..82d58c6
--- /dev/null
+++ b/src/libnoiseforjava/module/Simplex.java
@@ -0,0 +1,395 @@
+package libnoiseforjava.module;
+
+/**
+ * Michael Nugent
+ * Date: 3/9/12
+ * Time: 6:12 PM
+ * URL: https://github.com/michaelnugent/libnoiseforjava
+ * Package: libnoiseforjava.module
+ */
+
+
+/*
+* A speed-improved simplex noise algorithm for 2D, 3D and 4D in Java.
+*
+* Based on example code by Stefan Gustavson ([email protected]).
+* Optimisations by Peter Eastman ([email protected]).
+* Better rank ordering method by Stefan Gustavson in 2012.
+*
+* This could be speeded up even further, but it's useful as it is.
+*
+* Version 2012-03-09
+*
+* This code was placed in the public domain by its original author,
+* Stefan Gustavson. You may use it as you see fit, but
+* attribution is appreciated.
+*
+* Modified by Michael Nugent ([email protected]) for the
+* libnoise framework 20120309
+* All libnoise expects 3d, but I've left the 2d and 4d functions in for
+* reference.
+*
+*/
+
+public class Simplex extends ModuleBase { // Simplex noise in 2D, 3D and 4D
+ private static Grad grad3[] = {new Grad(1,1,0),new Grad(-1,1,0),new Grad(1,-1,0),new Grad(-1,-1,0),
+ new Grad(1,0,1),new Grad(-1,0,1),new Grad(1,0,-1),new Grad(-1,0,-1),
+ new Grad(0,1,1),new Grad(0,-1,1),new Grad(0,1,-1),new Grad(0,-1,-1)};
+
+ private static Grad grad4[]= {new Grad(0,1,1,1),new Grad(0,1,1,-1),new Grad(0,1,-1,1),new Grad(0,1,-1,-1),
+ new Grad(0,-1,1,1),new Grad(0,-1,1,-1),new Grad(0,-1,-1,1),new Grad(0,-1,-1,-1),
+ new Grad(1,0,1,1),new Grad(1,0,1,-1),new Grad(1,0,-1,1),new Grad(1,0,-1,-1),
+ new Grad(-1,0,1,1),new Grad(-1,0,1,-1),new Grad(-1,0,-1,1),new Grad(-1,0,-1,-1),
+ new Grad(1,1,0,1),new Grad(1,1,0,-1),new Grad(1,-1,0,1),new Grad(1,-1,0,-1),
+ new Grad(-1,1,0,1),new Grad(-1,1,0,-1),new Grad(-1,-1,0,1),new Grad(-1,-1,0,-1),
+ new Grad(1,1,1,0),new Grad(1,1,-1,0),new Grad(1,-1,1,0),new Grad(1,-1,-1,0),
+ new Grad(-1,1,1,0),new Grad(-1,1,-1,0),new Grad(-1,-1,1,0),new Grad(-1,-1,-1,0)};
+
+ private static short p[] = {151,160,137,91,90,15,
+ 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
+ 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
+ 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
+ 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
+ 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
+ 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
+ 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
+ 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
+ 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
+ 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
+ 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
+ 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180};
+ // To remove the need for index wrapping, double the permutation table length
+ private short perm[] = new short[512];
+ private short permMod12[] = new short[512];
+
+ private double seed = 0;
+
+ public Simplex() {
+ super(0);
+ for(int i=0; i<512; i++) {
+ perm[i]=p[i & 255];
+ permMod12[i] = (short)(perm[i] % 12);
+ }
+ }
+
+ public double getSeed() {
+ return seed;
+ }
+
+ public void setSeed(double seed) {
+ this.seed = seed;
+ }
+
+ public void setSeed(int seed) {
+ this.seed = (double)seed;
+ }
+
+ // Skewing and unskewing factors for 2, 3, and 4 dimensions
+ private static final double F2 = 0.5*(Math.sqrt(3.0)-1.0);
+ private static final double G2 = (3.0-Math.sqrt(3.0))/6.0;
+ private static final double F3 = 1.0/3.0;
+ private static final double G3 = 1.0/6.0;
+ private static final double F4 = (Math.sqrt(5.0)-1.0)/4.0;
+ private static final double G4 = (5.0-Math.sqrt(5.0))/20.0;
+
+ // This method is a *lot* faster than using (int)Math.floor(x)
+ private static int fastfloor(double x) {
+ int xi = (int)x;
+ return x<xi ? xi-1 : xi;
+ }
+
+ private static double dot(Grad g, double x, double y) {
+ return g.x*x + g.y*y;
+ }
+
+ private static double dot(Grad g, double x, double y, double z) {
+ return g.x*x + g.y*y + g.z*z;
+ }
+
+ private static double dot(Grad g, double x, double y, double z, double w) {
+ return g.x*x + g.y*y + g.z*z + g.w*w;
+ }
+
+
+ // 2D simplex noise
+ public double getValue2d(double xin, double yin) {
+ double n0, n1, n2; // Noise contributions from the three corners
+ // Skew the input space to determine which simplex cell we're in
+ double s = (xin+yin)*F2; // Hairy factor for 2D
+ int i = fastfloor(xin+s);
+ int j = fastfloor(yin+s);
+ double t = (i+j)*G2;
+ double X0 = i-t; // Unskew the cell origin back to (x,y) space
+ double Y0 = j-t;
+ double x0 = xin-X0; // The x,y distances from the cell origin
+ double y0 = yin-Y0;
+ // For the 2D case, the simplex shape is an equilateral triangle.
+ // Determine which simplex we are in.
+ int i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords
+ if(x0>y0) {i1=1; j1=0;} // lower triangle, XY order: (0,0)->(1,0)->(1,1)
+ else {i1=0; j1=1;} // upper triangle, YX order: (0,0)->(0,1)->(1,1)
+ // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
+ // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
+ // c = (3-sqrt(3))/6
+ double x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords
+ double y1 = y0 - j1 + G2;
+ double x2 = x0 - 1.0 + 2.0 * G2; // Offsets for last corner in (x,y) unskewed coords
+ double y2 = y0 - 1.0 + 2.0 * G2;
+ // Work out the hashed gradient indices of the three simplex corners
+ int ii = i & 255;
+ int jj = j & 255;
+
+ int gi0 = permMod12[ii+perm[jj]];
+ int gi1 = permMod12[ii+i1+perm[jj+j1]];
+ int gi2 = permMod12[ii+1+perm[jj+1]];
+ // Calculate the contribution from the three corners
+ double t0 = 0.5 - x0*x0-y0*y0;
+ if(t0<0) n0 = 0.0;
+ else {
+ t0 *= t0;
+ n0 = t0 * t0 * dot(grad3[gi0], x0, y0); // (x,y) of grad3 used for 2D gradient
+ }
+ double t1 = 0.5 - x1*x1-y1*y1;
+ if(t1<0) n1 = 0.0;
+ else {
+ t1 *= t1;
+ n1 = t1 * t1 * dot(grad3[gi1], x1, y1);
+ }
+ double t2 = 0.5 - x2*x2-y2*y2;
+ if(t2<0) n2 = 0.0;
+ else {
+ t2 *= t2;
+ n2 = t2 * t2 * dot(grad3[gi2], x2, y2);
+ }
+ // Add contributions from each corner to get the final noise value.
+ // The result is scaled to return values in the interval [-1,1].
+ return 70.0 * (n0 + n1 + n2);
+ }
+
+
+ // 3D simplex noise
+ public double getValue(double xin, double yin, double zin) {
+ double n0, n1, n2, n3; // Noise contributions from the four corners
+ // Skew the input space to determine which simplex cell we're in
+ xin+=(seed + (seed * 7)) % Double.MAX_VALUE;
+ xin+=(seed + (seed * 13)) % Double.MAX_VALUE;
+ xin+=(seed + (seed * 17)) % Double.MAX_VALUE;
+ double s = (xin+yin+zin)*F3; // Very nice and simple skew factor for 3D
+ int i = fastfloor(xin+s);
+ int j = fastfloor(yin+s);
+ int k = fastfloor(zin+s);
+ double t = (i+j+k)*G3;
+ double X0 = i-t; // Unskew the cell origin back to (x,y,z) space
+ double Y0 = j-t;
+ double Z0 = k-t;
+ double x0 = xin-X0; // The x,y,z distances from the cell origin
+ double y0 = yin-Y0;
+ double z0 = zin-Z0;
+ // For the 3D case, the simplex shape is a slightly irregular tetrahedron.
+ // Determine which simplex we are in.
+ int i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords
+ int i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords
+ if(x0>=y0) {
+ if(y0>=z0)
+ { i1=1; j1=0; k1=0; i2=1; j2=1; k2=0; } // X Y Z order
+ else if(x0>=z0) { i1=1; j1=0; k1=0; i2=1; j2=0; k2=1; } // X Z Y order
+ else { i1=0; j1=0; k1=1; i2=1; j2=0; k2=1; } // Z X Y order
+ }
+ else { // x0<y0
+ if(y0<z0) { i1=0; j1=0; k1=1; i2=0; j2=1; k2=1; } // Z Y X order
+ else if(x0<z0) { i1=0; j1=1; k1=0; i2=0; j2=1; k2=1; } // Y Z X order
+ else { i1=0; j1=1; k1=0; i2=1; j2=1; k2=0; } // Y X Z order
+ }
+ // A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z),
+ // a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and
+ // a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where
+ // c = 1/6.
+ double x1 = x0 - i1 + G3; // Offsets for second corner in (x,y,z) coords
+ double y1 = y0 - j1 + G3;
+ double z1 = z0 - k1 + G3;
+ double x2 = x0 - i2 + 2.0*G3; // Offsets for third corner in (x,y,z) coords
+ double y2 = y0 - j2 + 2.0*G3;
+ double z2 = z0 - k2 + 2.0*G3;
+ double x3 = x0 - 1.0 + 3.0*G3; // Offsets for last corner in (x,y,z) coords
+ double y3 = y0 - 1.0 + 3.0*G3;
+ double z3 = z0 - 1.0 + 3.0*G3;
+ // Work out the hashed gradient indices of the four simplex corners
+ int ii = i & 255;
+ int jj = j & 255;
+ int kk = k & 255;
+
+ int gi0 = permMod12[ii+perm[jj+perm[kk]]];
+ int gi1 = permMod12[ii+i1+perm[jj+j1+perm[kk+k1]]];
+ int gi2 = permMod12[ii+i2+perm[jj+j2+perm[kk+k2]]];
+ int gi3 = permMod12[ii+1+perm[jj+1+perm[kk+1]]];
+ // Calculate the contribution from the four corners
+ double t0 = 0.6 - x0*x0 - y0*y0 - z0*z0;
+ if(t0<0) n0 = 0.0;
+ else {
+ t0 *= t0;
+ n0 = t0 * t0 * dot(grad3[gi0], x0, y0, z0);
+ }
+ double t1 = 0.6 - x1*x1 - y1*y1 - z1*z1;
+ if(t1<0) n1 = 0.0;
+ else {
+ t1 *= t1;
+ n1 = t1 * t1 * dot(grad3[gi1], x1, y1, z1);
+ }
+ double t2 = 0.6 - x2*x2 - y2*y2 - z2*z2;
+ if(t2<0) n2 = 0.0;
+ else {
+ t2 *= t2;
+ n2 = t2 * t2 * dot(grad3[gi2], x2, y2, z2);
+ }
+ double t3 = 0.6 - x3*x3 - y3*y3 - z3*z3;
+ if(t3<0) n3 = 0.0;
+ else {
+ t3 *= t3;
+ n3 = t3 * t3 * dot(grad3[gi3], x3, y3, z3);
+ }
+ // Add contributions from each corner to get the final noise value.
+ // The result is scaled to stay just inside [-1,1]
+ return 32.0*(n0 + n1 + n2 + n3);
+ }
+
+
+ // 4D simplex noise, better simplex rank ordering method 2012-03-09
+ public double getValue4d(double x, double y, double z, double w) {
+
+ double n0, n1, n2, n3, n4; // Noise contributions from the five corners
+ // Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in
+ double s = (x + y + z + w) * F4; // Factor for 4D skewing
+ int i = fastfloor(x + s);
+ int j = fastfloor(y + s);
+ int k = fastfloor(z + s);
+ int l = fastfloor(w + s);
+ double t = (i + j + k + l) * G4; // Factor for 4D unskewing
+ double X0 = i - t; // Unskew the cell origin back to (x,y,z,w) space
+ double Y0 = j - t;
+ double Z0 = k - t;
+ double W0 = l - t;
+ double x0 = x - X0; // The x,y,z,w distances from the cell origin
+ double y0 = y - Y0;
+ double z0 = z - Z0;
+ double w0 = w - W0;
+ // For the 4D case, the simplex is a 4D shape I won't even try to describe.
+ // To find out which of the 24 possible simplices we're in, we need to
+ // determine the magnitude ordering of x0, y0, z0 and w0.
+ // Six pair-wise comparisons are performed between each possible pair
+ // of the four coordinates, and the results are used to rank the numbers.
+ int rankx = 0;
+ int ranky = 0;
+ int rankz = 0;
+ int rankw = 0;
+ if(x0 > y0) rankx++; else ranky++;
+ if(x0 > z0) rankx++; else rankz++;
+ if(x0 > w0) rankx++; else rankw++;
+ if(y0 > z0) ranky++; else rankz++;
+ if(y0 > w0) ranky++; else rankw++;
+ if(z0 > w0) rankz++; else rankw++;
+ int i1, j1, k1, l1; // The integer offsets for the second simplex corner
+ int i2, j2, k2, l2; // The integer offsets for the third simplex corner
+ int i3, j3, k3, l3; // The integer offsets for the fourth simplex corner
+ // simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order.
+ // Many values of c will never occur, since e.g. x>y>z>w makes x<z, y<w and x<w
+ // impossible. Only the 24 indices which have non-zero entries make any sense.
+ // We use a thresholding to set the coordinates in turn from the largest magnitude.
+ // Rank 3 denotes the largest coordinate.
+ i1 = rankx >= 3 ? 1 : 0;
+ j1 = ranky >= 3 ? 1 : 0;
+ k1 = rankz >= 3 ? 1 : 0;
+ l1 = rankw >= 3 ? 1 : 0;
+ // Rank 2 denotes the second largest coordinate.
+ i2 = rankx >= 2 ? 1 : 0;
+ j2 = ranky >= 2 ? 1 : 0;
+ k2 = rankz >= 2 ? 1 : 0;
+ l2 = rankw >= 2 ? 1 : 0;
+ // Rank 1 denotes the second smallest coordinate.
+ i3 = rankx >= 1 ? 1 : 0;
+ j3 = ranky >= 1 ? 1 : 0;
+ k3 = rankz >= 1 ? 1 : 0;
+ l3 = rankw >= 1 ? 1 : 0;
+ // The fifth corner has all coordinate offsets = 1, so no need to compute that.
+ double x1 = x0 - i1 + G4; // Offsets for second corner in (x,y,z,w) coords
+ double y1 = y0 - j1 + G4;
+ double z1 = z0 - k1 + G4;
+ double w1 = w0 - l1 + G4;
+ double x2 = x0 - i2 + 2.0*G4; // Offsets for third corner in (x,y,z,w) coords
+ double y2 = y0 - j2 + 2.0*G4;
+ double z2 = z0 - k2 + 2.0*G4;
+ double w2 = w0 - l2 + 2.0*G4;
+ double x3 = x0 - i3 + 3.0*G4; // Offsets for fourth corner in (x,y,z,w) coords
+ double y3 = y0 - j3 + 3.0*G4;
+ double z3 = z0 - k3 + 3.0*G4;
+ double w3 = w0 - l3 + 3.0*G4;
+ double x4 = x0 - 1.0 + 4.0*G4; // Offsets for last corner in (x,y,z,w) coords
+ double y4 = y0 - 1.0 + 4.0*G4;
+ double z4 = z0 - 1.0 + 4.0*G4;
+ double w4 = w0 - 1.0 + 4.0*G4;
+ // Work out the hashed gradient indices of the five simplex corners
+ int ii = i & 255;
+ int jj = j & 255;
+ int kk = k & 255;
+ int ll = l & 255;
+ int gi0 = perm[ii+perm[jj+perm[kk+perm[ll]]]] % 32;
+ int gi1 = perm[ii+i1+perm[jj+j1+perm[kk+k1+perm[ll+l1]]]] % 32;
+ int gi2 = perm[ii+i2+perm[jj+j2+perm[kk+k2+perm[ll+l2]]]] % 32;
+ int gi3 = perm[ii+i3+perm[jj+j3+perm[kk+k3+perm[ll+l3]]]] % 32;
+ int gi4 = perm[ii+1+perm[jj+1+perm[kk+1+perm[ll+1]]]] % 32;
+ // Calculate the contribution from the five corners
+ double t0 = 0.6 - x0*x0 - y0*y0 - z0*z0 - w0*w0;
+ if(t0<0) n0 = 0.0;
+ else {
+ t0 *= t0;
+ n0 = t0 * t0 * dot(grad4[gi0], x0, y0, z0, w0);
+ }
+ double t1 = 0.6 - x1*x1 - y1*y1 - z1*z1 - w1*w1;
+ if(t1<0) n1 = 0.0;
+ else {
+ t1 *= t1;
+ n1 = t1 * t1 * dot(grad4[gi1], x1, y1, z1, w1);
+ }
+ double t2 = 0.6 - x2*x2 - y2*y2 - z2*z2 - w2*w2;
+ if(t2<0) n2 = 0.0;
+ else {
+ t2 *= t2;
+ n2 = t2 * t2 * dot(grad4[gi2], x2, y2, z2, w2);
+ }
+ double t3 = 0.6 - x3*x3 - y3*y3 - z3*z3 - w3*w3;
+ if(t3<0) n3 = 0.0;
+ else {
+ t3 *= t3;
+ n3 = t3 * t3 * dot(grad4[gi3], x3, y3, z3, w3);
+ }
+ double t4 = 0.6 - x4*x4 - y4*y4 - z4*z4 - w4*w4;
+ if(t4<0) n4 = 0.0;
+ else {
+ t4 *= t4;
+ n4 = t4 * t4 * dot(grad4[gi4], x4, y4, z4, w4);
+ }
+ // Sum up and scale the result to cover the range [-1,1]
+ return 27.0 * (n0 + n1 + n2 + n3 + n4);
+ }
+
+ // Inner class to speed upp gradient computations
+ // (array access is a lot slower than member access)
+ private static class Grad
+ {
+ double x, y, z, w;
+
+ Grad(double x, double y, double z)
+ {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ Grad(double x, double y, double z, double w)
+ {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.w = w;
+ }
+ }
+}
diff --git a/src/libnoiseforjava/module/Spheres.java b/src/libnoiseforjava/module/Spheres.java
new file mode 100644
index 0000000..03b580f
--- /dev/null
+++ b/src/libnoiseforjava/module/Spheres.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+public class Spheres extends ModuleBase
+{
+
+ /// Noise module that outputs concentric spheres.
+ ///
+ /// This noise module outputs concentric spheres centered on the origin
+ /// like the concentric rings of an onion.
+ ///
+ /// The first sphere has a radius of 1.0. Each subsequent sphere has a
+ /// radius that is 1.0 unit larger than the previous sphere.
+ ///
+ /// The output value from this noise module is determined by the distance
+ /// between the input value and the the nearest spherical surface. The
+ /// input values that are located on a spherical surface are given the
+ /// output value 1.0 and the input values that are equidistant from two
+ /// spherical surfaces are given the output value -1.0.
+ ///
+ /// An application can change the frequency of the concentric spheres.
+ /// Increasing the frequency reduces the distances between spheres. To
+ /// specify the frequency, call the setFrequency() method.
+ ///
+ /// This noise module, modified with some low-frequency, low-power
+ /// turbulence, is useful for generating agate-like textures.
+ ///
+ /// This noise module does not require any source modules.
+
+ /// Default frequency value for the Spheres noise module.
+ static final double DEFAULT_SPHERES_FREQUENCY = 1.0;
+
+ /// Frequency of the concentric spheres.
+ double frequency;
+
+
+ public Spheres ()
+ {
+ super(0);
+ frequency = DEFAULT_SPHERES_FREQUENCY;
+ }
+
+ public double getValue (double x, double y, double z)
+ {
+ x *= frequency;
+ y *= frequency;
+ z *= frequency;
+
+ double distFromCenter = Math.sqrt (x * x + y * y + z * z);
+ double distFromSmallerSphere = distFromCenter - Math.floor (distFromCenter);
+ double distFromLargerSphere = 1.0 - distFromSmallerSphere;
+ double nearestDist = Math.min(distFromSmallerSphere, distFromLargerSphere);
+ return 1.0 - (nearestDist * 4.0); // Puts it in the -1.0 to +1.0 range.
+ }
+
+ /// Returns the frequency of the concentric spheres.
+ ///
+ /// @returns The frequency of the concentric spheres.
+ ///
+ /// Increasing the frequency increases the density of the concentric
+ /// spheres, reducing the distances between them.
+ public double getFrequency ()
+ {
+ return frequency;
+ }
+
+ /// Sets the frequency of the concentric spheres.
+ ///
+ /// @param frequency The frequency of the concentric spheres.
+ ///
+ /// Increasing the frequency increases the density of the concentric
+ /// spheres, reducing the distances between them.
+ public void setFrequency (double frequency)
+ {
+ this.frequency = frequency;
+ }
+
+}
diff --git a/src/libnoiseforjava/module/Terrace.java b/src/libnoiseforjava/module/Terrace.java
new file mode 100644
index 0000000..2c22733
--- /dev/null
+++ b/src/libnoiseforjava/module/Terrace.java
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+import libnoiseforjava.Interp;
+import libnoiseforjava.Misc;
+import libnoiseforjava.exception.ExceptionInvalidParam;
+
+public class Terrace extends ModuleBase
+{
+
+ /// Noise module that maps the output value from a source module onto a
+ /// terrace-forming curve.
+ ///
+ /// This noise module maps the output value from the source module onto a
+ /// terrace-forming curve. The start of this curve has a slope of zero;
+ /// its slope then smoothly increases. This curve also contains
+ /// <i>control points</i> which resets the slope to zero at that point,
+ /// producing a "terracing" effect. Refer to the following illustration:
+ ///
+ /// @image html terrace.png
+ ///
+ /// To add a control point to this noise module, call the
+ /// addControlPoint() method.
+ ///
+ /// An application must add a minimum of two control points to the curve.
+ /// If this is not done, the getValue() method fails. The control points
+ /// can have any value, although no two control points can have the same
+ /// value. There is no limit to the number of control points that can be
+ /// added to the curve.
+ ///
+ /// This noise module clamps the output value from the source module if
+ /// that value is less than the value of the lowest control point or
+ /// greater than the value of the highest control point.
+ ///
+ /// This noise module is often used to generate terrain features such as
+ /// your stereotypical desert canyon.
+ ///
+ /// This noise module requires one source module.
+
+
+ /// Number of control points stored in this noise module.
+ int controlPointCount;
+
+ /// Determines if the terrace-forming curve between all control points
+ /// is inverted.
+ boolean invertTerraces;
+
+ /// Array that stores the control points.
+ double [] controlPoints;
+
+
+ public Terrace (ModuleBase sourceModule) throws ExceptionInvalidParam
+ {
+ super(1);
+ setSourceModule(0, sourceModule);
+ controlPointCount = 0;
+ invertTerraces = false;
+ controlPoints = new double [0];
+
+ }
+
+ /// Adds a control point to the terrace-forming curve.
+ ///
+ /// @param value The value of the control point to add.
+ ///
+ /// @pre No two control points have the same value.
+ ///
+ /// @throw ExceptionInvalidParam An invalid parameter was
+ /// specified; see the preconditions for more information.
+ ///
+ /// Two or more control points define the terrace-forming curve. The
+ /// start of this curve has a slope of zero; its slope then smoothly
+ /// increases. At the control points, its slope resets to zero.
+ ///
+ /// It does not matter which order these points are added.
+ public void addControlPoint (double value) throws ExceptionInvalidParam
+ {
+ // Find the insertion point for the new control point and insert the new
+ // point at that position. The control point array will remain sorted by
+ // value.
+ int insertionPos = findInsertionPos (value);
+ insertAtPos (insertionPos, value);
+ }
+
+
+ /// Deletes all the control points on the terrace-forming curve.
+ ///
+ /// @post All control points on the terrace-forming curve are deleted.
+ public void clearAllControlPoints ()
+ {
+ controlPoints = null;
+ controlPointCount = 0;
+ }
+
+ /// Determines the array index in which to insert the control point
+ /// into the internal control point array.
+ ///
+ /// @param value The value of the control point.
+ ///
+ /// @returns The array index in which to insert the control point.
+ ///
+ /// @pre No two control points have the same value.
+ ///
+ /// @throw ExceptionInvalidParam An invalid parameter was
+ /// specified; see the preconditions for more information.
+ ///
+ /// By inserting the control point at the returned array index, this
+ /// class ensures that the control point array is sorted by value.
+ /// The code that maps a value onto the curve requires a sorted
+ /// control point array.
+ public int findInsertionPos (double value) throws ExceptionInvalidParam
+ {
+ int insertionPos;
+ for (insertionPos = 0; insertionPos < controlPointCount; insertionPos++)
+ {
+ if (value < controlPoints[insertionPos])
+ // We found the array index in which to insert the new control point.
+ // Exit now.
+ break;
+ else if (value == controlPoints[insertionPos])
+ // Each control point is required to contain a unique value, so throw
+ // an exception.
+ throw new ExceptionInvalidParam ("Invalid Parameter in Terrace Noise Moduled");
+ }
+ return insertionPos;
+ }
+
+ public double getValue (double x, double y, double z)
+ {
+ assert (sourceModules[0] != null);
+ assert (controlPointCount >= 2);
+
+ // Get the output value from the source module.
+ double sourceModuleValue = sourceModules[0].getValue (x, y, z);
+
+ // Find the first element in the control point array that has a value
+ // larger than the output value from the source module.
+ int indexPos;
+ for (indexPos = 0; indexPos < controlPointCount; indexPos++)
+ {
+ if (sourceModuleValue < controlPoints[indexPos])
+ break;
+
+ }
+
+ // Find the two nearest control points so that we can map their values
+ // onto a quadratic curve.
+ int index0 = Misc.ClampValue (indexPos - 1, 0, controlPointCount - 1);
+ int index1 = Misc.ClampValue (indexPos, 0, controlPointCount - 1);
+
+ // If some control points are missing (which occurs if the output value from
+ // the source module is greater than the largest value or less than the
+ // smallest value of the control point array), get the value of the nearest
+ // control point and exit now.
+ if (index0 == index1)
+ return controlPoints[index1];
+
+ // Compute the alpha value used for linear interpolation.
+ double value0 = controlPoints[index0];
+ double value1 = controlPoints[index1];
+ double alpha = (sourceModuleValue - value0) / (value1 - value0);
+ if (invertTerraces)
+ {
+ alpha = 1.0 - alpha;
+ double tempValue = value0;
+ value0 = value1;
+ value1 = tempValue;
+ }
+
+ // Squaring the alpha produces the terrace effect.
+ alpha *= alpha;
+
+ // Now perform the linear interpolation given the alpha value.
+ return Interp.linearInterp (value0, value1, alpha);
+ }
+
+ /// Inserts the control point at the specified position in the
+ /// internal control point array.
+ ///
+ /// @param insertionPos The zero-based array position in which to
+ /// insert the control point.
+ /// @param value The value of the control point.
+ ///
+ /// To make room for this new control point, this method reallocates
+ /// the control point array and shifts all control points occurring
+ /// after the insertion position up by one.
+ ///
+ /// Because the curve mapping algorithm in this noise module requires
+ /// that all control points in the array be sorted by value, the new
+ /// control point should be inserted at the position in which the
+ /// order is still preserved.
+ public void insertAtPos (int insertionPos, double value)
+ {
+ // Make room for the new control point at the specified position within
+ // the control point array. The position is determined by the value of
+ // the control point; the control points must be sorted by value within
+ // that array.
+ double[] newControlPoints = new double[controlPointCount + 1];
+
+ for (int i = 0; i < controlPointCount; i++)
+ {
+ if (i < insertionPos)
+ newControlPoints[i] = controlPoints[i];
+ else
+ newControlPoints[i + 1] = controlPoints[i];
+ }
+
+ controlPoints = newControlPoints;
+ ++controlPointCount;
+
+ // Now that we've made room for the new control point within the array,
+ // add the new control point.
+ controlPoints[insertionPos] = value;
+ }
+
+ /// Creates a number of equally-spaced control points that range from
+ /// -1 to +1.
+ ///
+ /// @param controlPointCount The number of control points to generate.
+ ///
+ /// @pre The number of control points must be greater than or equal to
+ /// 2.
+ ///
+ /// @post The previous control points on the terrace-forming curve are
+ /// deleted.
+ ///
+ /// @throw ExceptionInvalidParam An invalid parameter was
+ /// specified; see the preconditions for more information.
+ ///
+ /// Two or more control points define the terrace-forming curve. The
+ /// start of this curve has a slope of zero; its slope then smoothly
+ /// increases. At the control points, its slope resets to zero.
+ void makeControlPoints (int controlPointCount) throws ExceptionInvalidParam
+ {
+ if (controlPointCount < 2)
+ throw new ExceptionInvalidParam ("Invalid Parameter in Terrace Noise Module");
+
+ clearAllControlPoints ();
+
+ double terraceStep = 2.0 / ((double)controlPointCount - 1.0);
+ double curValue = -1.0;
+ for (int i = 0; i < (int)controlPointCount; i++)
+ {
+ addControlPoint (curValue);
+ curValue += terraceStep;
+ }
+ }
+
+ /// Returns a pointer to the array of control points on the
+ /// terrace-forming curve.
+ ///
+ /// @returns A pointer to the array of control points in this noise
+ /// module.
+ ///
+ /// Two or more control points define the terrace-forming curve. The
+ /// start of this curve has a slope of zero; its slope then smoothly
+ /// increases. At the control points, its slope resets to zero.
+ ///
+ /// Before calling this method, call getControlPointCount() to
+ /// determine the number of control points in this array.
+ ///
+ /// It is recommended that an application does not store this pointer
+ /// for later use since the pointer to the array may change if the
+ /// application calls another method of this object.
+ public double[] getControlPointArray ()
+ {
+ return controlPoints;
+ }
+
+ /// Returns the number of control points on the terrace-forming curve.
+ ///
+ /// @returns The number of control points on the terrace-forming
+ /// curve.
+ public int getControlPointCount ()
+ {
+ return controlPointCount;
+ }
+
+ /// Enables or disables the inversion of the terrace-forming curve
+ /// between the control points.
+ ///
+ /// @param invert Specifies whether to invert the curve between the
+ /// control points.
+ public void invertTerraces (boolean invert)
+ {
+ if (invert)
+ invertTerraces = invert;
+ }
+
+ /// Determines if the terrace-forming curve between the control
+ /// points is inverted.
+ ///
+ /// @returns
+ /// - @a true if the curve between the control points is inverted.
+ /// - @a false if the curve between the control points is not
+ /// inverted.
+ public boolean isTerracesInverted ()
+ {
+ return invertTerraces;
+ }
+
+}
diff --git a/src/libnoiseforjava/module/TranslatePoint.java b/src/libnoiseforjava/module/TranslatePoint.java
new file mode 100644
index 0000000..23ed712
--- /dev/null
+++ b/src/libnoiseforjava/module/TranslatePoint.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+import libnoiseforjava.exception.ExceptionInvalidParam;
+
+public class TranslatePoint extends ModuleBase
+{
+ /// Noise module that moves the coordinates of the input value before
+ /// returning the output value from a source module.
+ ///
+ /// The getValue() method moves the ( @a x, @a y, @a z ) coordinates of
+ /// the input value by a translation amount before returning the output
+ /// value from the source module. To set the translation amount, call
+ /// the setTranslation() method. To set the translation amount to
+ /// apply to the individual @a x, @a y, or @a z coordinates, call the
+ /// setXTranslation(), setYTranslation() or setZTranslation() methods,
+ /// respectively.
+ ///
+ /// This noise module requires one source module.
+
+
+ /// Default translation factor applied to the @a x coordinate for the
+ /// TranslatePoint noise module.
+ static final double DEFAULT_TRANSLATE_POINT_X = 0.0;
+
+ /// Default translation factor applied to the @a y coordinate for the
+ /// TranslatePoint noise module.
+ static final double DEFAULT_TRANSLATE_POINT_Y = 0.0;
+
+ /// Default translation factor applied to the @a z coordinate for the
+ /// TranslatePoint noise module.
+ static final double DEFAULT_TRANSLATE_POINT_Z = 0.0;
+
+ /// Translation amount applied to the @a x coordinate of the input
+ /// value.
+ double xTranslation;
+
+ /// Translation amount applied to the @a y coordinate of the input
+ /// value.
+ double yTranslation;
+
+ /// Translation amount applied to the @a z coordinate of the input
+ /// value.
+ double zTranslation;
+
+ public TranslatePoint (ModuleBase sourceModule) throws ExceptionInvalidParam
+ {
+ super(1);
+ setSourceModule(0, sourceModule);
+ xTranslation = DEFAULT_TRANSLATE_POINT_X;
+ yTranslation = DEFAULT_TRANSLATE_POINT_Y;
+ zTranslation = DEFAULT_TRANSLATE_POINT_Z;
+
+ }
+
+ public double getValue (double x, double y, double z)
+ {
+ assert (sourceModules[0] != null);
+
+ return sourceModules[0].getValue (x + xTranslation, y + yTranslation,
+ z + zTranslation);
+ }
+
+ /// Returns the translation amount to apply to the @a x coordinate of
+ /// the input value.
+ ///
+ /// @returns The translation amount to apply to the @a x coordinate.
+ public double getXTranslation ()
+ {
+ return xTranslation;
+ }
+
+ /// Returns the translation amount to apply to the @a y coordinate of
+ /// the input value.
+ ///
+ /// @returns The translation amount to apply to the @a y coordinate.
+ public double getYTranslation ()
+ {
+ return yTranslation;
+ }
+
+ /// Returns the translation amount to apply to the @a z coordinate of
+ /// the input value.
+ ///
+ /// @returns The translation amount to apply to the @a z coordinate.
+ public double getZTranslation ()
+ {
+ return zTranslation;
+ }
+
+ /// Sets the translation amount to apply to the input value.
+ ///
+ /// @param translation The translation amount to apply.
+ ///
+ /// The getValue() method moves the ( @a x, @a y, @a z ) coordinates
+ /// of the input value by a translation amount before returning the
+ /// output value from the source module
+ public void setTranslation (double translation)
+ {
+ this.xTranslation = translation;
+ this.yTranslation = translation;
+ this.zTranslation = translation;
+ }
+
+ /// Sets the translation amounts to apply to the ( @a x, @a y, @a z )
+ /// coordinates of the input value.
+ ///
+ /// @param xTranslation The translation amount to apply to the @a x
+ /// coordinate.
+ /// @param yTranslation The translation amount to apply to the @a y
+ /// coordinate.
+ /// @param zTranslation The translation amount to apply to the @a z
+ /// coordinate.
+ ///
+ /// The getValue() method moves the ( @a x, @a y, @a z ) coordinates
+ /// of the input value by a translation amount before returning the
+ /// output value from the source module
+ public void setTranslation (double xTranslation, double yTranslation,
+ double zTranslation)
+ {
+ this.xTranslation = xTranslation;
+ this.yTranslation = yTranslation;
+ this.zTranslation = zTranslation;
+ }
+
+ /// Sets the translation amount to apply to the @a x coordinate of the
+ /// input value.
+ ///
+ /// @param xTranslation The translation amount to apply to the @a x
+ /// coordinate.
+ ///
+ /// The getValue() method moves the ( @a x, @a y, @a z ) coordinates
+ /// of the input value by a translation amount before returning the
+ /// output value from the source module
+ public void setXTranslation (double xTranslation)
+ {
+ this.xTranslation = xTranslation;
+ }
+
+ /// Sets the translation amount to apply to the @a y coordinate of the
+ /// input value.
+ ///
+ /// @param yTranslation The translation amount to apply to the @a y
+ /// coordinate.
+ ///
+ /// The getValue() method moves the ( @a x, @a y, @a z ) coordinates
+ /// of the input value by a translation amount before returning the
+ /// output value from the source module
+ public void setYTranslation (double yTranslation)
+ {
+ this.yTranslation = yTranslation;
+ }
+
+ /// Sets the translation amount to apply to the @a z coordinate of the
+ /// input value.
+ ///
+ /// @param zTranslation The translation amount to apply to the @a z
+ /// coordinate.
+ ///
+ /// The getValue() method moves the ( @a x, @a y, @a z ) coordinates
+ /// of the input value by a translation amount before returning the
+ /// output value from the source module
+ public void setZTranslation (double zTranslation)
+ {
+ this.zTranslation = zTranslation;
+ }
+
+}
diff --git a/src/libnoiseforjava/module/Turbulence.java b/src/libnoiseforjava/module/Turbulence.java
new file mode 100644
index 0000000..021cff0
--- /dev/null
+++ b/src/libnoiseforjava/module/Turbulence.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+import libnoiseforjava.exception.ExceptionInvalidParam;
+
+public class Turbulence extends ModuleBase
+{
+ /// Noise module that randomly displaces the input value before
+ /// returning the output value from a source module.
+ ///
+ /// @a Turbulence is the pseudo-random displacement of the input value.
+ /// The getValue() method randomly displaces the ( @a x, @a y, @a z )
+ /// coordinates of the input value before retrieving the output value from
+ /// the source module. To control the turbulence, an application can
+ /// modify its frequency, its power, and its roughness.
+ ///
+ /// The frequency of the turbulence determines how rapidly the
+ /// displacement amount changes. To specify the frequency, call the
+ /// setFrequency() method.
+ ///
+ /// The power of the turbulence determines the scaling factor that is
+ /// applied to the displacement amount. To specify the power, call the
+ /// setPower() method.
+ ///
+ /// The roughness of the turbulence determines the roughness of the
+ /// changes to the displacement amount. Low values smoothly change the
+ /// displacement amount. High values roughly change the displacement
+ /// amount, which produces more "kinky" changes. To specify the
+ /// roughness, call the setRoughness() method.
+ ///
+ /// Use of this noise module may require some trial and error. Assuming
+ /// that you are using a generator module as the source module, you
+ /// should first:
+ /// - Set the frequency to the same frequency as the source module.
+ /// - Set the power to the reciprocal of the frequency.
+ ///
+ /// From these initial frequency and power values, modify these values
+ /// until this noise module produce the desired changes in your terrain or
+ /// texture. For example:
+ /// - Low frequency (1/8 initial frequency) and low power (1/8 initial
+ /// power) produces very minor, almost unnoticeable changes.
+ /// - Low frequency (1/8 initial frequency) and high power (8 times
+ /// initial power) produces "ropey" lava-like terrain or marble-like
+ /// textures.
+ /// - High frequency (8 times initial frequency) and low power (1/8
+ /// initial power) produces a noisy version of the initial terrain or
+ /// texture.
+ /// - High frequency (8 times initial frequency) and high power (8 times
+ /// initial power) produces nearly pure noise, which isn't entirely
+ /// useful.
+ ///
+ /// Displacing the input values result in more realistic terrain and
+ /// textures. If you are generating elevations for terrain height maps,
+ /// you can use this noise module to produce more realistic mountain
+ /// ranges or terrain features that look like flowing lava rock. If you
+ /// are generating values for textures, you can use this noise module to
+ /// produce realistic marble-like or "oily" textures.
+ ///
+ /// Internally, there are three noise::module::Perlin noise modules
+ /// that displace the input value; one for the @a x, one for the @a y,
+ /// and one for the @a z coordinate.
+ ///
+ /// This noise module requires one source module.
+
+ /// Default frequency for the Turbulence noise module.
+ static final double DEFAULT_TURBULENCE_FREQUENCY = Perlin.DEFAULT_PERLIN_FREQUENCY;
+
+ /// Default power for the Turbulence noise module.
+ static final double DEFAULT_TURBULENCE_POWER = 1.0;
+
+ /// Default roughness for the Turbulence noise module.
+ static final int DEFAULT_TURBULENCE_ROUGHNESS = 3;
+
+ /// Default noise seed for the Turbulence noise module.
+ static final int DEFAULT_TURBULENCE_SEED = Perlin.DEFAULT_PERLIN_SEED;
+
+
+ /// The power (scale) of the displacement.
+ double power;
+
+ /// Noise module that displaces the @a x coordinate.
+ Perlin xDistortModule;
+
+ /// Noise module that displaces the @a y coordinate.
+ Perlin yDistortModule;
+
+ /// Noise module that displaces the @a z coordinate.
+ Perlin zDistortModule;
+
+ public Turbulence (ModuleBase sourceModule) throws ExceptionInvalidParam
+ {
+ super(1);
+ setSourceModule(0, sourceModule);
+
+ power = DEFAULT_TURBULENCE_POWER;
+
+ xDistortModule = new Perlin();
+ yDistortModule = new Perlin();
+ zDistortModule = new Perlin();
+
+ setSeed(DEFAULT_TURBULENCE_SEED);
+ setFrequency(DEFAULT_TURBULENCE_FREQUENCY);
+ setRoughness (DEFAULT_TURBULENCE_ROUGHNESS);
+ }
+
+ /// Returns the frequency of the turbulence.
+ ///
+ /// @returns The frequency of the turbulence.
+ ///
+ /// The frequency of the turbulence determines how rapidly the
+ /// displacement amount changes.
+ public double getFrequency ()
+ {
+ // Since each noise::module::Perlin noise module has the same frequency, it
+ // does not matter which module we use to retrieve the frequency.
+ return xDistortModule.getFrequency ();
+ }
+
+ /// Returns the seed value of the internal Perlin-noise modules that
+ /// are used to displace the input values.
+ ///
+ /// @returns The seed value.
+ ///
+ /// Internally, there are three Perlin noise modules
+ /// that displace the input value; one for the @a x, one for the @a y,
+ /// and one for the @a z coordinate.
+ public int getSeed ()
+ {
+ return xDistortModule.getSeed ();
+ }
+
+ public double getValue (double x, double y, double z)
+ {
+ assert (sourceModules[0] != null);
+
+ // Get the values from the three Perlin noise modules and
+ // add each value to each coordinate of the input value. There are also
+ // some offsets added to the coordinates of the input values. This prevents
+ // the distortion modules from returning zero if the (x, y, z) coordinates,
+ // when multiplied by the frequency, are near an integer boundary. This is
+ // due to a property of gradient coherent noise, which returns zero at
+ // integer boundaries.
+ double x0, y0, z0;
+ double x1, y1, z1;
+ double x2, y2, z2;
+
+ x0 = x + (12414.0 / 65536.0);
+ y0 = y + (65124.0 / 65536.0);
+ z0 = z + (31337.0 / 65536.0);
+ x1 = x + (26519.0 / 65536.0);
+ y1 = y + (18128.0 / 65536.0);
+ z1 = z + (60493.0 / 65536.0);
+ x2 = x + (53820.0 / 65536.0);
+ y2 = y + (11213.0 / 65536.0);
+ z2 = z + (44845.0 / 65536.0);
+
+ double xDistort = x + (xDistortModule.getValue (x0, y0, z0)
+ * power);
+ double yDistort = y + (yDistortModule.getValue (x1, y1, z1)
+ * power);
+ double zDistort = z + (zDistortModule.getValue (x2, y2, z2)
+ * power);
+
+ // Retrieve the output value at the offsetted input value instead of the
+ // original input value.
+ return sourceModules[0].getValue (xDistort, yDistort, zDistort);
+ }
+
+ /// Sets the seed value of the internal noise modules that are used to
+ /// displace the input values.
+ ///
+ /// @param seed The seed value.
+ ///
+ /// Internally, there are three Perlin noise modules
+ /// that displace the input value; one for the @a x, one for the @a y,
+ /// and one for the @a z coordinate. This noise module assigns the
+ /// following seed values to the Perlin noise modules:
+ /// - It assigns the seed value (@a seed + 0) to the @a x noise module.
+ /// - It assigns the seed value (@a seed + 1) to the @a y noise module.
+ /// - It assigns the seed value (@a seed + 2) to the @a z noise module.
+ /// This is done to prevent any sort of weird artifacting.
+ public void setSeed (int seed)
+ {
+ xDistortModule.setSeed (seed);
+ yDistortModule.setSeed (seed + 1);
+ zDistortModule.setSeed (seed + 2);
+ }
+
+ /// Returns the power of the turbulence.
+ ///
+ /// @returns The power of the turbulence.
+ ///
+ /// The power of the turbulence determines the scaling factor that is
+ /// applied to the displacement amount.
+ public double getPower ()
+ {
+ return power;
+ }
+
+ /// Returns the roughness of the turbulence.
+ ///
+ /// @returns The roughness of the turbulence.
+ ///
+ /// The roughness of the turbulence determines the roughness of the
+ /// changes to the displacement amount. Low values smoothly change
+ /// the displacement amount. High values roughly change the
+ /// displacement amount, which produces more "kinky" changes.
+ public int getRoughnessCount ()
+ {
+ return xDistortModule.getOctaveCount ();
+ }
+
+ /// Sets the frequency of the turbulence.
+ ///
+ /// @param frequency The frequency of the turbulence.
+ ///
+ /// The frequency of the turbulence determines how rapidly the
+ /// displacement amount changes.
+ public void setFrequency (double frequency)
+ {
+ xDistortModule.setFrequency (frequency);
+ yDistortModule.setFrequency (frequency);
+ zDistortModule.setFrequency (frequency);
+ }
+
+ /// Sets the power of the turbulence.
+ ///
+ /// @param power The power of the turbulence.
+ ///
+ /// The power of the turbulence determines the scaling factor that is
+ /// applied to the displacement amount.
+ public void setPower (double power)
+ {
+ this.power = power;
+ }
+
+ /// Sets the roughness of the turbulence.
+ ///
+ /// @param roughness The roughness of the turbulence.
+ ///
+ /// The roughness of the turbulence determines the roughness of the
+ /// changes to the displacement amount. Low values smoothly change
+ /// the displacement amount. High values roughly change the
+ /// displacement amount, which produces more "kinky" changes.
+ ///
+ /// Internally, there are three Perlin noise modules
+ /// that displace the input value; one for the @a x, one for the @a y,
+ /// and one for the @a z coordinate. The roughness value is equal to
+ /// the number of octaves used by the noise::module::Perlin noise
+ /// modules.
+ public void setRoughness (int roughness) throws ExceptionInvalidParam
+ {
+ xDistortModule.setOctaveCount (roughness);
+ yDistortModule.setOctaveCount (roughness);
+ zDistortModule.setOctaveCount (roughness);
+ }
+
+}
diff --git a/src/libnoiseforjava/module/Voronoi.java b/src/libnoiseforjava/module/Voronoi.java
new file mode 100644
index 0000000..79776c1
--- /dev/null
+++ b/src/libnoiseforjava/module/Voronoi.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.module;
+
+import libnoiseforjava.NoiseGen;
+
+public class Voronoi extends ModuleBase
+{
+
+ /// Noise module that outputs Voronoi cells.
+ ///
+ /// In mathematics, a <i>Voronoi cell</i> is a region containing all the
+ /// points that are closer to a specific <i>seed point</i> than to any
+ /// other seed point. These cells mesh with one another, producing
+ /// polygon-like formations.
+ ///
+ /// By default, this noise module randomly places a seed point within
+ /// each unit cube. By modifying the <i>frequency</i> of the seed points,
+ /// an application can change the distance between seed points. The
+ /// higher the frequency, the closer together this noise module places
+ /// the seed points, which reduces the size of the cells. To specify the
+ /// frequency of the cells, call the setFrequency() method.
+ ///
+ /// This noise module assigns each Voronoi cell with a random constant
+ /// value from a coherent-noise function. The <i>displacement value</i>
+ /// controls the range of random values to assign to each cell. The
+ /// range of random values is +/- the displacement value. Call the
+ /// setDisplacement() method to specify the displacement value.
+ ///
+ /// To modify the random positions of the seed points, call the SetSeed()
+ /// method.
+ ///
+ /// This noise module can optionally add the distance from the nearest
+ /// seed to the output value. To enable this feature, call the
+ /// enableDistance() method. This causes the points in the Voronoi cells
+ /// to increase in value the further away that point is from the nearest
+ /// seed point.
+ ///
+ /// Voronoi cells are often used to generate cracked-mud terrain
+ /// formations or crystal-like textures
+ ///
+ /// This noise module requires no source modules.
+
+
+ /// Default displacement to apply to each cell for the
+ /// Voronoi noise module.
+ final static double DEFAULT_VORONOI_DISPLACEMENT = 1.0;
+
+ /// Default frequency of the seed points for the Voronoi
+ /// noise module.
+ final static double DEFAULT_VORONOI_FREQUENCY = 1.0;
+
+ /// Default seed of the noise function for the Voronoi
+ /// noise module.
+ final static int DEFAULT_VORONOI_SEED = 0;
+
+ private static final double SQRT_3 = 1.7320508075688772935;
+
+
+ /// Scale of the random displacement to apply to each Voronoi cell.
+ double displacement;
+
+ /// Determines if the distance from the nearest seed point is applied to
+ /// the output value.
+ boolean enableDistance;
+
+ /// Frequency of the seed points.
+ double frequency;
+
+ /// Seed value used by the coherent-noise function to determine the
+ /// positions of the seed points.
+ int seed;
+
+
+ public Voronoi ()
+ {
+ super(0);
+ displacement = DEFAULT_VORONOI_DISPLACEMENT;
+ enableDistance = false;
+ frequency = DEFAULT_VORONOI_FREQUENCY;
+ seed = DEFAULT_VORONOI_SEED;
+ }
+
+ public double getValue (double x, double y, double z)
+ {
+ // This method could be more efficient by caching the seed values. Fix
+ // later.
+
+ x *= frequency;
+ y *= frequency;
+ z *= frequency;
+
+ int xInt = (x > 0.0? (int)x: (int)x - 1);
+ int yInt = (y > 0.0? (int)y: (int)y - 1);
+ int zInt = (z > 0.0? (int)z: (int)z - 1);
+
+ double minDist = 2147483647.0;
+ double xCandidate = 0;
+ double yCandidate = 0;
+ double zCandidate = 0;
+
+ // Inside each unit cube, there is a seed point at a random position. Go
+ // through each of the nearby cubes until we find a cube with a seed point
+ // that is closest to the specified position.
+ for (int zCur = zInt - 2; zCur <= zInt + 2; zCur++)
+ {
+ for (int yCur = yInt - 2; yCur <= yInt + 2; yCur++)
+ {
+ for (int xCur = xInt - 2; xCur <= xInt + 2; xCur++)
+ {
+ // Calculate the position and distance to the seed point inside of
+ // this unit cube.
+ double xPos = xCur + NoiseGen.ValueNoise3D (xCur, yCur, zCur, seed);
+ double yPos = yCur + NoiseGen.ValueNoise3D (xCur, yCur, zCur, seed + 1);
+ double zPos = zCur + NoiseGen.ValueNoise3D (xCur, yCur, zCur, seed + 2);
+ double xDist = xPos - x;
+ double yDist = yPos - y;
+ double zDist = zPos - z;
+ double dist = xDist * xDist + yDist * yDist + zDist * zDist;
+
+ if (dist < minDist)
+ {
+ // This seed point is closer to any others found so far, so record
+ // this seed point.
+ minDist = dist;
+ xCandidate = xPos;
+ yCandidate = yPos;
+ zCandidate = zPos;
+ }
+ }
+ }
+ }
+
+ double value;
+ if (enableDistance)
+ {
+ // Determine the distance to the nearest seed point.
+ double xDist = xCandidate - x;
+ double yDist = yCandidate - y;
+ double zDist = zCandidate - z;
+ value = (Math.sqrt(xDist * xDist + yDist * yDist + zDist * zDist)
+ ) * SQRT_3 - 1.0;
+ } else {
+ value = 0.0;
+ }
+
+ // Return the calculated distance with the displacement value applied.
+ return value + (displacement * (double)NoiseGen.ValueNoise3D (
+ (int)(Math.floor (xCandidate)),
+ (int)(Math.floor (yCandidate)),
+ (int)(Math.floor (zCandidate)), seed));// added seed here, not in original
+ // but there isn't a working method
+ // without seed
+ }
+
+ /// Enables or disables applying the distance from the nearest seed
+ /// point to the output value.
+ ///
+ /// @param enable Specifies whether to apply the distance to the
+ /// output value or not.
+ ///
+ /// Applying the distance from the nearest seed point to the output
+ /// value causes the points in the Voronoi cells to increase in value
+ /// the further away that point is from the nearest seed point.
+ /// Setting this value to @a true (and setting the displacement to a
+ /// near-zero value) causes this noise module to generate cracked mud
+ /// formations.
+ public void enableDistance (boolean enable)
+ {
+ enableDistance = enable;
+ }
+
+ /// Returns the displacement value of the Voronoi cells.
+ ///
+ /// @returns The displacement value of the Voronoi cells.
+ ///
+ /// This noise module assigns each Voronoi cell with a random constant
+ /// value from a coherent-noise function. The <i>displacement
+ /// value</i> controls the range of random values to assign to each
+ /// cell. The range of random values is +/- the displacement value.
+ public double getDisplacement ()
+ {
+ return displacement;
+ }
+
+ /// Returns the frequency of the seed points.
+ ///
+ /// @returns The frequency of the seed points.
+ ///
+ /// The frequency determines the size of the Voronoi cells and the
+ /// distance between these cells.
+ public double GetFrequency ()
+ {
+ return frequency;
+ }
+
+ /// Returns the seed value used by the Voronoi cells
+ ///
+ /// @returns The seed value.
+ ///
+ /// The positions of the seed values are calculated by a
+ /// coherent-noise function. By modifying the seed value, the output
+ /// of that function changes.
+ public int getSeed ()
+ {
+ return seed;
+ }
+
+ /// Determines if the distance from the nearest seed point is applied
+ /// to the output value.
+ ///
+ /// @returns
+ /// - @a true if the distance is applied to the output value.
+ /// - @a false if not.
+ ///
+ /// Applying the distance from the nearest seed point to the output
+ /// value causes the points in the Voronoi cells to increase in value
+ /// the further away that point is from the nearest seed point.
+ public boolean IsDistanceEnabled ()
+ {
+ return enableDistance;
+ }
+
+ /// Sets the displacement value of the Voronoi cells.
+ ///
+ /// @param displacement The displacement value of the Voronoi cells.
+ ///
+ /// This noise module assigns each Voronoi cell with a random constant
+ /// value from a coherent-noise function. The <i>displacement
+ /// value</i> controls the range of random values to assign to each
+ /// cell. The range of random values is +/- the displacement value.
+ public void setDisplacement (double displacement)
+ {
+ this.displacement = displacement;
+ }
+
+ /// Sets the frequency of the seed points.
+ ///
+ /// @param frequency The frequency of the seed points.
+ ///
+ /// The frequency determines the size of the Voronoi cells and the
+ /// distance between these cells.
+ public void setFrequency (double frequency)
+ {
+ this.frequency = frequency;
+ }
+
+ /// Sets the seed value used by the Voronoi cells
+ ///
+ /// @param seed The seed value.
+ ///
+ /// The positions of the seed values are calculated by a
+ /// coherent-noise function. By modifying the seed value, the output
+ /// of that function changes.
+ public void setSeed (int seed)
+ {
+ this.seed = seed;
+ }
+
+}
diff --git a/src/libnoiseforjava/util/ColorCafe.java b/src/libnoiseforjava/util/ColorCafe.java
new file mode 100644
index 0000000..0b98471
--- /dev/null
+++ b/src/libnoiseforjava/util/ColorCafe.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.util;
+
+public class ColorCafe
+{
+ /// Defines a color.
+ ///
+ /// A color object contains four 8-bit channels: red, green, blue, and an
+ /// alpha (transparency) channel. Channel values range from 0 to 255.
+ ///
+ /// The alpha channel defines the transparency of the color. If the alpha
+ /// channel has a value of 0, the color is completely transparent. If the
+ /// alpha channel has a value of 255, the color is completely opaque.
+
+ /// Value of the alpha (transparency) channel.
+ int alpha;
+
+ /// Value of the blue channel.
+ int blue;
+
+ /// Value of the green channel.
+ int green;
+
+ /// Value of the red channel.
+ int red;
+
+ /// Constructor.
+ ///
+ /// @param r Value of the red channel.
+ /// @param g Value of the green channel.
+ /// @param b Value of the blue channel.
+ /// @param a Value of the alpha (transparency) channel.
+ public ColorCafe (int red, int green, int blue, int alpha)
+ {
+ this.red = red;
+ this.blue = blue;
+ this.green = green;
+ this.alpha = alpha;
+ }
+
+ public int getAlpha()
+ {
+ return alpha;
+ }
+
+ public int getBlue()
+ {
+ return blue;
+ }
+
+ public int getGreen()
+ {
+ return green;
+ }
+
+ public int getRed()
+ {
+ return red;
+ }
+
+ public void setAlpha(int alpha)
+ {
+ this.alpha = alpha;
+ }
+
+ public void setBlue(int blue)
+ {
+ this.blue = blue;
+ }
+
+ public void setGreen(int green)
+ {
+ this.green = green;
+ }
+
+ public void setRed(int red)
+ {
+ this.red = red;
+ }
+
+}
diff --git a/src/libnoiseforjava/util/GradientColor.java b/src/libnoiseforjava/util/GradientColor.java
new file mode 100644
index 0000000..ee241f4
--- /dev/null
+++ b/src/libnoiseforjava/util/GradientColor.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.util;
+
+import libnoiseforjava.Misc;
+import libnoiseforjava.exception.ExceptionInvalidParam;
+
+public class GradientColor
+{
+ /// Defines a color gradient.
+ ///
+ /// A color gradient is a list of gradually-changing colors. A color
+ /// gradient is defined by a list of <i>gradient points</i>. Each
+ /// gradient point has a position and a color. In a color gradient, the
+ /// colors between two adjacent gradient points are linearly interpolated.
+ ///
+ /// To add a gradient point to the color gradient, pass its position and
+ /// color to the addGradientPoint() method.
+ ///
+ /// To retrieve a color from a specific position in the color gradient,
+ /// pass that position to the getColor() method.
+ ///
+ /// This class is a useful tool for coloring height maps based on
+ /// elevation.
+ ///
+ /// <b>Gradient example</b>
+ ///
+ /// Suppose a gradient object contains the following gradient points:
+ /// - -1.0 maps to black.
+ /// - 0.0 maps to white.
+ /// - 1.0 maps to red.
+ ///
+ /// If an application passes -0.5 to the getColor() method, this method
+ /// will return a gray color that is halfway between black and white.
+ ///
+ /// If an application passes 0.25 to the getColor() method, this method
+ /// will return a very light pink color that is one quarter of the way
+ /// between white and red.
+
+
+ GradientPoint [] gradientPoints;
+ int gradientPointCount;
+ ColorCafe workingColor;
+
+ public GradientColor()
+ {
+ gradientPoints = new GradientPoint[1];
+ gradientPoints[0] = new GradientPoint(0.0, new ColorCafe(0, 0, 0, 0));
+ }
+
+ /// Adds a gradient point to this gradient object.
+ ///
+ /// @param gradientPos The position of this gradient point.
+ /// @param gradientColor The color of this gradient point.
+ ///
+ /// @pre No two gradient points have the same position.
+ ///
+ /// @throw noise::ExceptionInvalidParam See the precondition.
+ ///
+ /// It does not matter which order these gradient points are added.
+ public void addGradientPoint (double gradientPos, ColorCafe gradientColor) throws ExceptionInvalidParam
+ {
+ // Find the insertion point for the new gradient point and insert the new
+ // gradient point at that insertion point. The gradient point array will
+ // remain sorted by gradient position.
+ int insertionPos = findInsertionPos (gradientPos);
+ insertAtPos (insertionPos, gradientPos, gradientColor);
+ }
+
+ /// Deletes all the gradient points from this gradient object.
+ ///
+ /// @post All gradient points from this gradient object are deleted.
+ public void clear ()
+ {
+ gradientPoints = null;
+ gradientPointCount = 0;
+ }
+
+ /// Determines the array index in which to insert the gradient point
+ /// into the internal gradient-point array.
+ ///
+ /// @param gradientPos The position of this gradient point.
+ ///
+ /// @returns The array index in which to insert the gradient point.
+ ///
+ /// @pre No two gradient points have the same input value.
+ ///
+ /// @throw noise::ExceptionInvalidParam See the precondition.
+ ///
+ /// By inserting the gradient point at the returned array index, this
+ /// object ensures that the gradient-point array is sorted by input
+ /// value. The code that maps a value to a color requires a sorted
+ /// gradient-point array.
+ public int findInsertionPos (double gradientPos) throws ExceptionInvalidParam
+ {
+ int insertionPos;
+ for (insertionPos = 0; insertionPos < gradientPointCount;
+ insertionPos++) {
+ if (gradientPos < gradientPoints[insertionPos].position) {
+ // We found the array index in which to insert the new gradient point.
+ // Exit now.
+ break;
+ } else if (gradientPos == gradientPoints[insertionPos].position) {
+ // Each gradient point is required to contain a unique gradient
+ // position, so throw an exception.
+ throw new ExceptionInvalidParam ("Invalid Parameter in Gradient Color");
+ }
+ }
+ return insertionPos;
+ }
+
+ /// Returns the color at the specified position in the color gradient.
+ ///
+ /// @param gradientPos The specified position.
+ ///
+ /// @returns The color at that position.
+ public ColorCafe getColor (double gradientPos)
+ {
+ assert (gradientPointCount >= 2);
+
+ // Find the first element in the gradient point array that has a gradient
+ // position larger than the gradient position passed to this method.
+ int indexPos;
+ for (indexPos = 0; indexPos < gradientPointCount; indexPos++)
+ {
+ if (gradientPos < gradientPoints[indexPos].position)
+ break;
+ }
+
+ // Find the two nearest gradient points so that we can perform linear
+ // interpolation on the color.
+ int index0 = Misc.ClampValue (indexPos - 1, 0, gradientPointCount - 1);
+ int index1 = Misc.ClampValue (indexPos, 0, gradientPointCount - 1);
+
+ // If some gradient points are missing (which occurs if the gradient
+ // position passed to this method is greater than the largest gradient
+ // position or less than the smallest gradient position in the array), get
+ // the corresponding gradient color of the nearest gradient point and exit
+ // now.
+ if (index0 == index1)
+ {
+ workingColor = gradientPoints[index1].color;
+ return workingColor;
+ }
+
+ // Compute the alpha value used for linear interpolation.
+ double input0 = gradientPoints[index0].position;
+ double input1 = gradientPoints[index1].position;
+ double alpha = (gradientPos - input0) / (input1 - input0);
+
+ // Now perform the linear interpolation given the alpha value.
+ ColorCafe color0 = gradientPoints[index0].color;
+ ColorCafe color1 = gradientPoints[index1].color;
+ workingColor = MiscUtilities.linearInterpColor (color0, color1, (float)alpha);
+ return workingColor;
+ }
+
+ /// Inserts the gradient point at the specified position in the
+ /// internal gradient-point array.
+ ///
+ /// @param insertionPos The zero-based array position in which to
+ /// insert the gradient point.
+ /// @param gradientPos The position of this gradient point.
+ /// @param gradientColor The color of this gradient point.
+ ///
+ /// To make room for this new gradient point, this method reallocates
+ /// the gradient-point array and shifts all gradient points occurring
+ /// after the insertion position up by one.
+ ///
+ /// Because this object requires that all gradient points in the array
+ /// must be sorted by the position, the new gradient point should be
+ /// inserted at the position in which the order is still preserved.
+ public void insertAtPos (int insertionPos, double gradientPos,
+ ColorCafe gradientColor)
+ {
+ // Make room for the new gradient point at the specified insertion position
+ // within the gradient point array. The insertion position is determined by
+ // the gradient point's position; the gradient points must be sorted by
+ // gradient position within that array.
+ GradientPoint [] newGradientPoints;
+ newGradientPoints = new GradientPoint[gradientPointCount + 1];
+
+ for (int t = 0; t < (gradientPointCount + 1); t++)
+ newGradientPoints[t] = new GradientPoint();
+
+
+
+ for (int i = 0; i < gradientPointCount; i++)
+ {
+ if (i < insertionPos)
+ newGradientPoints[i] = gradientPoints[i];
+ else
+ newGradientPoints[i + 1] = gradientPoints[i];
+ }
+
+ gradientPoints = newGradientPoints;
+ ++gradientPointCount;
+
+ // Now that we've made room for the new gradient point within the array, add
+ // the new gradient point.
+ gradientPoints[insertionPos].position = gradientPos;
+ gradientPoints[insertionPos].color = gradientColor;
+ }
+
+ /// Returns a pointer to the array of gradient points in this object.
+ ///
+ /// @returns A pointer to the array of gradient points.
+ ///
+ /// Before calling this method, call getGradientPointCount() to
+ /// determine the number of gradient points in this array.
+ ///
+ /// It is recommended that an application does not store this pointer
+ /// for later use since the pointer to the array may change if the
+ /// application calls another method of this object.
+ public GradientPoint[] getGradientPointArray ()
+ {
+ return gradientPoints;
+ }
+
+ /// Returns the number of gradient points stored in this object.
+ ///
+ /// @returns The number of gradient points stored in this object.
+ public int getGradientPointCount ()
+ {
+ return gradientPointCount;
+ }
+
+}
diff --git a/src/libnoiseforjava/util/GradientPoint.java b/src/libnoiseforjava/util/GradientPoint.java
new file mode 100644
index 0000000..b48dab6
--- /dev/null
+++ b/src/libnoiseforjava/util/GradientPoint.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.util;
+
+public class GradientPoint
+{
+ /// Defines a point used to build a color gradient.
+ ///
+ /// A color gradient is a list of gradually-changing colors. A color
+ /// gradient is defined by a list of <i>gradient points</i>. Each
+ /// gradient point has a position and a color. In a color gradient, the
+ /// colors between two adjacent gradient points are linearly interpolated.
+ ///
+ /// The ColorGradient class defines a color gradient by a list of these
+ /// objects.
+
+ double position;
+ ColorCafe color;
+
+ public GradientPoint()
+ {
+ position = 0.0;
+ color = new ColorCafe(0,0,0,0);
+ }
+
+ public GradientPoint(double position, ColorCafe color)
+ {
+ this.position = position;
+ this.color = color;
+ }
+
+ public double getPosition()
+ {
+ return position;
+ }
+
+ public ColorCafe getColor()
+ {
+ return color;
+ }
+
+ public void setPosition(double position)
+ {
+ this.position = position;
+ }
+
+ public void setColor(ColorCafe color)
+ {
+ this.color = color;
+ }
+}
diff --git a/src/libnoiseforjava/util/ImageCafe.java b/src/libnoiseforjava/util/ImageCafe.java
new file mode 100644
index 0000000..746e700
--- /dev/null
+++ b/src/libnoiseforjava/util/ImageCafe.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.util;
+
+import libnoiseforjava.exception.ExceptionInvalidParam;
+
+public class ImageCafe
+{
+
+ /// Implements an image, a 2-dimensional array of color values.
+ ///
+ /// An image can be used to store a color texture.
+ ///
+ /// These color values are of type ColorCafe.
+ ///
+ /// The size (width and height) of the image can be specified during
+ /// object construction.
+ ///
+ /// The getValue() and setValue() methods can be used to access individual
+ /// color values stored in the image.
+ ///
+ ///
+ /// <b>Border Values</b>
+ ///
+ /// All of the color values outside of the image are assumed to have a
+ /// common color value known as the <i>border value</i>.
+ ///
+ /// To set the border value, call the setBorderValue() method.
+ ///
+ /// The getValue() method returns the border value if the specified
+ /// position lies outside of the image.
+ ///
+
+ /// The Color value used for all positions outside of the image.
+ ColorCafe borderValue;
+
+ /// The current height of the image.
+ int height;
+
+ /// The current width of the image.
+ int width;
+
+ /// Array of ColorCafes holding the color values
+ ColorCafe [][] imageCafeColors;
+
+ public ImageCafe (int width, int height) throws ExceptionInvalidParam
+ {
+ setSize (width, height);
+ borderValue = new ColorCafe (0, 0, 0, 0);
+ imageCafeColors = new ColorCafe[width][height];
+ }
+
+ /// Returns a color value from the specified position in the image.
+ ///
+ /// @param x The x coordinate of the position.
+ /// @param y The y coordinate of the position.
+ ///
+ /// @returns The color value at that position.
+ ///
+ /// This method returns the border value if the coordinates exist
+ /// outside of the image.
+ public ColorCafe getValue (int x, int y)
+ {
+ if (x >= 0 && x < width && y >= 0 && y < height)
+ return imageCafeColors[x][y];
+ else
+ // The coordinates specified are outside the image. Return the border
+ // value.
+ return borderValue;
+ }
+
+ /// Sets the new size for the image.
+ ///
+ /// @param width The new width for the image.
+ /// @param height The new height for the image.
+ ///
+ /// @pre The width and height values are positive.
+ /// @pre The width and height values do not exceed the maximum
+ /// possible width and height for the image.
+ ///
+ /// @throw ExceptionInvalidParam See the preconditions.
+ public void setSize (int width, int height) throws ExceptionInvalidParam
+ {
+ if (width < 0 || height < 0)
+ // Invalid width or height.
+ throw new ExceptionInvalidParam ("Invalid Parameter in ImageCafe");
+ else
+ {
+ this.width = width;
+ this.height = height;
+ }
+ }
+
+ /// Sets a color value at a specified position in the image.
+ ///
+ /// @param x The x coordinate of the position.
+ /// @param y The y coordinate of the position.
+ /// @param value The color value to set at the given position.
+ ///
+ /// This method does nothing if the image is empty or the position is
+ /// outside the bounds of the image.
+ public void setValue (int x, int y, ColorCafe value)
+ {
+ if (x >= 0 && x < width && y >= 0 && y < height)
+ this.imageCafeColors[x][y] = value;
+ }
+
+
+ /// Returns the color value used for all positions outside of the
+ /// image.
+ ///
+ /// @returns The color value used for all positions outside of the
+ /// image.
+ ///
+ /// All positions outside of the image are assumed to have a common
+ /// color value known as the <i>border value</i>.
+ public ColorCafe getBorderValue ()
+ {
+ return borderValue;
+ }
+
+ /// Returns the height of the image.
+ ///
+ /// @returns The height of the image.
+ public int getHeight ()
+ {
+ return height;
+ }
+
+ /// Returns the width of the image.
+ ///
+ /// @returns The width of the image.
+ public int getWidth ()
+ {
+ return width;
+ }
+
+ /// Sets the color value to use for all positions outside of the
+ /// image.
+ ///
+ /// @param borderValue The color value to use for all positions
+ /// outside of the image.
+ ///
+ /// All positions outside of the image are assumed to have a common
+ /// color value known as the <i>border value</i>.
+ public void setBorderValue (ColorCafe borderValue)
+ {
+ this.borderValue = borderValue;
+ }
+}
diff --git a/src/libnoiseforjava/util/MiscUtilities.java b/src/libnoiseforjava/util/MiscUtilities.java
new file mode 100644
index 0000000..a18aa6b
--- /dev/null
+++ b/src/libnoiseforjava/util/MiscUtilities.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.util;
+
+public class MiscUtilities
+{
+
+ // Performs linear interpolation between two 8-bit channel values.
+ public static short blendChannel (int red, int red2, float alpha)
+ {
+ double c0 = (float)red / 255.0;
+ double c1 = (float)red2 / 255.0;
+ return (short)(((c1 * alpha) + (c0 * (1.0f - alpha))) * 255.0f);
+ }
+
+ // Performs linear interpolation between two colors
+ public static ColorCafe linearInterpColor (ColorCafe color0, ColorCafe color1,
+ float alpha)
+ {
+ ColorCafe color = new ColorCafe(
+ blendChannel (color0.red, color1.red, alpha),
+ blendChannel (color0.green, color1.green, alpha),
+ blendChannel (color0.blue, color1.blue, alpha),
+ blendChannel (color0.alpha, color1.alpha, alpha)
+ );
+ return color;
+ }
+
+}
diff --git a/src/libnoiseforjava/util/NoiseMap.java b/src/libnoiseforjava/util/NoiseMap.java
new file mode 100644
index 0000000..b0636f2
--- /dev/null
+++ b/src/libnoiseforjava/util/NoiseMap.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.util;
+
+import libnoiseforjava.exception.ExceptionInvalidParam;
+
+public class NoiseMap
+{
+ /// Implements a noise map, a 2-dimensional array of floating-point
+ /// values.
+ ///
+ /// A noise map is designed to store coherent-noise values generated by a
+ /// noise module, although it can store values from any source. A noise
+ /// map is often used as a terrain height map or a grayscale texture.
+ ///
+ /// The size (width and height) of the noise map can be specified during
+ /// object construction.
+ ///
+ /// The getValue() method can be used to access individual
+ /// values stored in the noise map.
+ ///
+
+
+ /// The height of the noise map.
+ int height;
+
+ /// The width of the noise map.
+ int width;
+
+ /// The array of doubles holding the noise map values
+ double[][] noiseMap;
+
+ double borderValue;
+
+ public NoiseMap (int width, int height) throws ExceptionInvalidParam
+ {
+ setSize (width, height);
+ noiseMap = new double [width][height];
+ borderValue = 0.0;
+ }
+
+ /// Returns a value from the specified position in the noise map.
+ ///
+ /// @param x The x coordinate of the position.
+ /// @param y The y coordinate of the position.
+ ///
+ /// @returns The value at that position.
+ ///
+ /// This method returns the border value if the coordinates exist
+ /// outside of the noise map.
+ public double getValue (int x, int y)
+ {
+ if (x >= 0 && x < width && y >= 0 && y < height)
+ return noiseMap[x] [y];
+ // The coordinates specified are outside the noise map. Return the border
+ // value.
+ else
+ return borderValue;
+ }
+
+ public void setSize (int width, int height) throws ExceptionInvalidParam
+ {
+ if (width < 1 || height < 1)
+ // Invalid width or height.
+ throw new ExceptionInvalidParam ("Invalid parameter in NoiseMap");
+ else
+ {
+ this.width = width;
+ this.height = height;
+ }
+ }
+
+ /// Sets a value at a specified position in the noise map.
+ ///
+ /// @param x The x coordinate of the position.
+ /// @param y The y coordinate of the position.
+ /// @param value The value to set at the given position.
+ ///
+ /// This method does nothing if the noise map object is empty or the
+ /// position is outside the bounds of the noise map.
+ public void setValue (int x, int y, double value)
+ {
+ if (x >= 0 && x < width && y >= 0 && y < height)
+ this.noiseMap[x][y]= value;
+ }
+
+ /// Returns the value used for all positions outside of the noise map.
+ ///
+ /// @returns The value used for all positions outside of the noise
+ /// map.
+ ///
+ /// All positions outside of the noise map are assumed to have a
+ /// common value known as the <i>border value</i>.
+ public double getBorderValue ()
+ {
+ return borderValue;
+ }
+
+ /// Returns the height of the noise map.
+ ///
+ /// @returns The height of the noise map.
+ public int getHeight ()
+ {
+ return height;
+ }
+
+ /// Returns the width of the noise map.
+ ///
+ /// @returns The width of the noise map.
+ public int getWidth ()
+ {
+ return width;
+ }
+
+ /// Sets the value to use for all positions outside of the noise map.
+ ///
+ /// @param borderValue The value to use for all positions outside of
+ /// the noise map.
+ ///
+ /// All positions outside of the noise map are assumed to have a
+ /// common value known as the <i>border value</i>.
+ public void setBorderValue (double borderValue)
+ {
+ this.borderValue = borderValue;
+ }
+
+ public double[][] getNoiseMap() {
+ return noiseMap;
+ }
+
+ public void setNoiseMap(double[][] noiseMap) {
+ this.noiseMap = noiseMap;
+ }
+
+}
diff --git a/src/libnoiseforjava/util/NoiseMapBuilder.java b/src/libnoiseforjava/util/NoiseMapBuilder.java
new file mode 100644
index 0000000..a091226
--- /dev/null
+++ b/src/libnoiseforjava/util/NoiseMapBuilder.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.util;
+
+import libnoiseforjava.exception.ExceptionInvalidParam;
+import libnoiseforjava.module.ModuleBase;
+
+public class NoiseMapBuilder
+{
+
+ /// Base class for a noise-map builder
+ ///
+ /// A builder class builds a noise map by filling it with coherent-noise
+ /// values generated from the surface of a three-dimensional mathematical
+ /// object. Each builder class defines a specific three-dimensional
+ /// surface, such as a cylinder, sphere, or plane.
+ ///
+ /// A builder class describes these input values using a coordinate system
+ /// applicable for the mathematical object (e.g., a latitude/longitude
+ /// coordinate system for the spherical noise-map builder.) It then
+ /// "flattens" these coordinates onto a plane so that it can write the
+ /// coherent-noise values into a two-dimensional noise map.
+ ///
+ /// <b>Building the Noise Map</b>
+ ///
+ /// To build the noise map, perform the following steps:
+ /// - Pass the bounding coordinates to the setBounds() method.
+ /// - Pass the noise map size, in points, to the setDestSize() method.
+ /// - Pass a NoiseMap object to the setDestNoiseMap() method.
+ /// - Pass a noise module (derived from ModuleBase) to the
+ /// setSourceModule() method.
+ /// - Call the build() method.
+ ///
+ /// Note that setBounds() is not defined in the base class; it is
+ /// only defined in the derived classes. This is because each model uses
+ /// a different coordinate system.
+
+
+ /// Count of rows completed
+ int callback;
+
+ /// Height of the destination noise map, in points.
+ int destHeight;
+
+ /// Width of the destination noise map, in points.
+ int destWidth;
+
+ /// Destination noise map that will contain the coherent-noise values.
+ NoiseMap destNoiseMap;
+
+ /// Source noise module that will generate the coherent-noise values.
+ ModuleBase sourceModule;
+
+
+ public NoiseMapBuilder () throws ExceptionInvalidParam
+ {
+ callback = 0;
+ destHeight = 0;
+ destWidth = 0;
+ destNoiseMap = new NoiseMap(1,1);
+ sourceModule = new ModuleBase(0);
+ }
+
+ public NoiseMapBuilder (int height, int width) throws ExceptionInvalidParam
+ {
+ callback = 0;
+ destHeight = 0;
+ destWidth = 0;
+ destNoiseMap = new NoiseMap(height,width);
+ sourceModule = new ModuleBase(0);
+ }
+
+ /// Builds the noise map.
+ ///
+ /// @pre setBounds() was previously called.
+ /// @pre setDestNoiseMap() was previously called.
+ /// @pre setSourceModule() was previously called.
+ /// @pre The width and height values specified by setDestSize() are
+ /// positive.
+ /// @pre The width and height values specified by setDestSize() do not
+ /// exceed the maximum possible width and height for the noise map.
+ ///
+ /// @post The original contents of the destination noise map is
+ /// destroyed.
+ ///
+ /// @throw ExceptionInvalidParam See the preconditions.
+ /// @throw ExceptionOutOfMemory Out of memory.
+ ///
+ /// If this method is successful, the destination noise map contains
+ /// the coherent-noise values from the noise module specified by
+ /// setSourceModule().
+ public void build () throws ExceptionInvalidParam
+ {
+ //override in child classes
+ }
+
+ /// Returns the height of the destination noise map.
+ ///
+ /// @returns The height of the destination noise map, in points.
+ ///
+ /// This object does not change the height in the destination noise
+ /// map object until the build() method is called.
+ public double getDestHeight ()
+ {
+ return destHeight;
+ }
+
+ /// Returns the width of the destination noise map.
+ ///
+ /// @returns The width of the destination noise map, in points.
+ ///
+ /// This object does not change the height in the destination noise
+ /// map object until the build() method is called.
+ public double getDestWidth ()
+ {
+ return destWidth;
+ }
+
+ /// Sets the destination noise map.
+ ///
+ /// @param destNoiseMap The destination noise map.
+ ///
+ /// The destination noise map will contain the coherent-noise values
+ /// from this noise map after a successful call to the build() method.
+ ///
+ /// The destination noise map must exist throughout the lifetime of
+ /// this object unless another noise map replaces that noise map.
+ public void setDestNoiseMap (NoiseMap destNoiseMap)
+ {
+ this.destNoiseMap = destNoiseMap;
+ }
+
+ /// Sets the source module.
+ ///
+ /// @param sourceModule The source module.
+ ///
+ /// This object fills in a noise map with the coherent-noise values
+ /// from this source module.
+ ///
+ /// The source module must exist throughout the lifetime of this
+ /// object unless another noise module replaces that noise module.
+ public void setSourceModule (ModuleBase sourceModule)
+ {
+ this.sourceModule = sourceModule;
+ }
+
+ /// Sets the size of the destination noise map.
+ ///
+ /// @param destWidth The width of the destination noise map, in
+ /// points.
+ /// @param destHeight The height of the destination noise map, in
+ /// points.
+ ///
+ /// This method does not change the size of the destination noise map
+ /// until the build() method is called.
+ public void setDestSize (int destWidth, int destHeight)
+ {
+ this.destWidth = destWidth ;
+ this.destHeight = destHeight;
+ }
+
+ public NoiseMap getDestNoiseMap()
+ {
+ return destNoiseMap;
+ }
+
+ void setCallback (int callback)
+ {
+ this.callback = callback;
+ }
+
+} \ No newline at end of file
diff --git a/src/libnoiseforjava/util/NoiseMapBuilderCylinder.java b/src/libnoiseforjava/util/NoiseMapBuilderCylinder.java
new file mode 100644
index 0000000..4d33219
--- /dev/null
+++ b/src/libnoiseforjava/util/NoiseMapBuilderCylinder.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.util;
+
+import libnoiseforjava.exception.ExceptionInvalidParam;
+import libnoiseforjava.model.Cylinder;
+
+public class NoiseMapBuilderCylinder extends NoiseMapBuilder
+{
+
+ /// Builds a cylindrical noise map.
+ ///
+ /// This class builds a noise map by filling it with coherent-noise values
+ /// generated from the surface of a cylinder.
+ ///
+ /// This class describes these input values using an (angle, height)
+ /// coordinate system. After generating the coherent-noise value from the
+ /// input value, it then "flattens" these coordinates onto a plane so that
+ /// it can write the values into a two-dimensional noise map.
+ ///
+ /// The cylinder model has a radius of 1.0 unit and has infinite height.
+ /// The cylinder is oriented along the @a y axis. Its center is at the
+ /// origin.
+ ///
+ /// The x coordinate in the noise map represents the angle around the
+ /// cylinder's y axis. The y coordinate in the noise map represents the
+ /// height above the x-z plane.
+ ///
+ /// The application must provide the lower and upper angle bounds of the
+ /// noise map, in degrees, and the lower and upper height bounds of the
+ /// noise map, in units.
+
+ /// Lower angle boundary of the cylindrical noise map, in degrees.
+ double lowerAngleBound;
+
+ /// Lower height boundary of the cylindrical noise map, in units.
+ double lowerHeightBound;
+
+ /// Upper angle boundary of the cylindrical noise map, in degrees.
+ double upperAngleBound;
+
+ /// Upper height boundary of the cylindrical noise map, in units.
+ double upperHeightBound;
+
+
+
+ public NoiseMapBuilderCylinder () throws ExceptionInvalidParam
+ {
+ super();
+ lowerAngleBound = 0.0;
+ lowerHeightBound = 0.0;
+ upperAngleBound = 0.0;
+ upperHeightBound = 0.0;
+ }
+
+ public void build () throws ExceptionInvalidParam
+ {
+ if (upperAngleBound <= lowerAngleBound
+ || upperHeightBound <= lowerHeightBound
+ || destWidth <= 0
+ || destHeight <= 0
+ || sourceModule == null
+ || destNoiseMap == null)
+ throw new ExceptionInvalidParam ("Invalid Parameter in NoiseMapBuilderCylinder");
+
+
+ // Resize the destination noise map so that it can store the new output
+ // values from the source model.
+ destNoiseMap.setSize (destWidth, destHeight);
+
+ // Create the cylinder model.
+ Cylinder cylinderModel = new Cylinder();
+ cylinderModel.setModule (sourceModule);
+
+ double angleExtent = upperAngleBound - lowerAngleBound ;
+ double heightExtent = upperHeightBound - lowerHeightBound;
+ double xDelta = angleExtent / (double)destWidth ;
+ double yDelta = heightExtent / (double)destHeight;
+ double curAngle = lowerAngleBound ;
+ double curHeight = lowerHeightBound;
+
+ // Fill every point in the noise map with the output values from the model.
+ for (int y = 0; y < destHeight; y++)
+ {
+ curAngle = lowerAngleBound;
+ for (int x = 0; x < destWidth; x++)
+ {
+ float curValue = (float)cylinderModel.getValue (curAngle, curHeight);
+ destNoiseMap.setValue(x, y, curValue);
+ curAngle += xDelta;
+ }
+ curHeight += yDelta;
+ setCallback (y);
+ }
+ }
+
+ /// Returns the lower angle boundary of the cylindrical noise map.
+ ///
+ /// @returns The lower angle boundary of the noise map, in degrees.
+ public double getLowerAngleBound ()
+ {
+ return lowerAngleBound;
+ }
+
+ /// Returns the lower height boundary of the cylindrical noise map.
+ ///
+ /// @returns The lower height boundary of the noise map, in units.
+ ///
+ /// One unit is equal to the radius of the cylinder.
+ public double getLowerHeightBound ()
+ {
+ return lowerHeightBound;
+ }
+
+ /// Returns the upper angle boundary of the cylindrical noise map.
+ ///
+ /// @returns The upper angle boundary of the noise map, in degrees.
+ public double GetUpperAngleBound ()
+ {
+ return upperAngleBound;
+ }
+
+ /// Returns the upper height boundary of the cylindrical noise map.
+ ///
+ /// @returns The upper height boundary of the noise map, in units.
+ ///
+ /// One unit is equal to the radius of the cylinder.
+ public double getUpperHeightBound ()
+ {
+ return upperHeightBound;
+ }
+
+ /// Sets the coordinate boundaries of the noise map.
+ ///
+ /// @param lowerAngleBound The lower angle boundary of the noise map,
+ /// in degrees.
+ /// @param upperAngleBound The upper angle boundary of the noise map,
+ /// in degrees.
+ /// @param lowerHeightBound The lower height boundary of the noise
+ /// map, in units.
+ /// @param upperHeightBound The upper height boundary of the noise
+ /// map, in units.
+ ///
+ /// @pre The lower angle boundary is less than the upper angle
+ /// boundary.
+ /// @pre The lower height boundary is less than the upper height
+ /// boundary.
+ ///
+ /// @throw noise::ExceptionInvalidParam See the preconditions.
+ ///
+ /// One unit is equal to the radius of the cylinder.
+ public void setBounds (double lowerAngleBound, double upperAngleBound,
+ double lowerHeightBound, double upperHeightBound) throws ExceptionInvalidParam
+ {
+ if (lowerAngleBound >= upperAngleBound
+ || lowerHeightBound >= upperHeightBound)
+ throw new ExceptionInvalidParam ("Invalid Parameter in NoiseMapBuilder Cylinder");
+
+ this.lowerAngleBound = lowerAngleBound ;
+ this.upperAngleBound = upperAngleBound ;
+ this.lowerHeightBound = lowerHeightBound;
+ this.upperHeightBound = upperHeightBound;
+ }
+
+ public double getUpperAngleBound()
+ {
+ return upperAngleBound;
+ }
+
+ public void setLowerAngleBound(double lowerAngleBound)
+ {
+ this.lowerAngleBound = lowerAngleBound;
+ }
+
+ public void setLowerHeightBound(double lowerHeightBound)
+ {
+ this.lowerHeightBound = lowerHeightBound;
+ }
+
+ public void setUpperAngleBound(double upperAngleBound)
+ {
+ this.upperAngleBound = upperAngleBound;
+ }
+
+ public void setUpperHeightBound(double upperHeightBound)
+ {
+ this.upperHeightBound = upperHeightBound;
+ }
+
+}
diff --git a/src/libnoiseforjava/util/NoiseMapBuilderPlane.java b/src/libnoiseforjava/util/NoiseMapBuilderPlane.java
new file mode 100644
index 0000000..20e5fcb
--- /dev/null
+++ b/src/libnoiseforjava/util/NoiseMapBuilderPlane.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.util;
+
+import libnoiseforjava.Interp;
+import libnoiseforjava.exception.ExceptionInvalidParam;
+import libnoiseforjava.model.Plane;
+
+public class NoiseMapBuilderPlane extends NoiseMapBuilder
+{
+ /// Builds a planar noise map.
+ ///
+ /// This class builds a noise map by filling it with coherent-noise values
+ /// generated from the surface of a plane.
+ ///
+ /// This class describes these input values using (x, z) coordinates.
+ /// Their y coordinates are always 0.0.
+ ///
+ /// The application must provide the lower and upper x coordinate bounds
+ /// of the noise map, in units, and the lower and upper z coordinate
+ /// bounds of the noise map, in units.
+ ///
+ /// To make a tileable noise map with no seams at the edges, call the
+ /// enableSeamless() method.
+
+ /// A flag specifying whether seamless tiling is enabled.
+ boolean isSeamlessEnabled;
+
+ /// Lower x boundary of the planar noise map, in units.
+ double lowerXBound;
+
+ /// Lower z boundary of the planar noise map, in units.
+ double lowerZBound;
+
+ /// Upper x boundary of the planar noise map, in units.
+ double upperXBound;
+
+ /// Upper z boundary of the planar noise map, in units.
+ double upperZBound;
+
+
+ public NoiseMapBuilderPlane () throws ExceptionInvalidParam
+ {
+ super();
+ isSeamlessEnabled = false;
+ lowerXBound = 0.0;
+ lowerZBound = 0.0;
+ upperXBound = 0.0;
+ upperZBound = 0.0;
+ }
+
+ public NoiseMapBuilderPlane (int height, int width) throws ExceptionInvalidParam
+ {
+ super(height, width);
+ isSeamlessEnabled = false;
+ lowerXBound = 0.0;
+ lowerZBound = 0.0;
+ upperXBound = 0.0;
+ upperZBound = 0.0;
+ }
+
+ public void build () throws ExceptionInvalidParam
+ {
+ if ( upperXBound <= lowerXBound
+ || upperZBound <= lowerZBound
+ || destWidth <= 0
+ || destHeight <= 0
+ || sourceModule == null
+ || destNoiseMap == null)
+ throw new ExceptionInvalidParam ("Invalid parameter in NoiseMapBuilderPlane");
+
+ // Resize the destination noise map so that it can store the new output
+ // values from the source model.
+ destNoiseMap.setSize (destWidth, destHeight);
+
+ // Create the plane model.
+ Plane planeModel = new Plane();
+ planeModel.setModule (sourceModule);
+
+ double xExtent = upperXBound - lowerXBound;
+ double zExtent = upperZBound - lowerZBound;
+ double xDelta = xExtent / (double)destWidth ;
+ double zDelta = zExtent / (double)destHeight;
+ double xCur = lowerXBound;
+ double zCur = lowerZBound;
+
+ // Fill every point in the noise map with the output values from the model.
+ for (int z = 0; z < destHeight; z++)
+ {
+ xCur = lowerXBound;
+ for (int x = 0; x < destWidth; x++)
+ {
+ double finalValue;
+
+ if (!isSeamlessEnabled)
+ finalValue = planeModel.getValue (xCur, zCur);
+ else
+ {
+ double swValue, seValue, nwValue, neValue;
+ swValue = planeModel.getValue (xCur, zCur);
+ seValue = planeModel.getValue (xCur + xExtent, zCur);
+ nwValue = planeModel.getValue (xCur, zCur + zExtent);
+ neValue = planeModel.getValue (xCur + xExtent, zCur + zExtent);
+ double xBlend = 1.0 - ((xCur - lowerXBound) / xExtent);
+ double zBlend = 1.0 - ((zCur - lowerZBound) / zExtent);
+ double z0 = Interp.linearInterp (swValue, seValue, xBlend);
+ double z1 = Interp.linearInterp (nwValue, neValue, xBlend);
+ finalValue = Interp.linearInterp (z0, z1, zBlend);
+ }
+
+ destNoiseMap.setValue(x, z, finalValue);
+ xCur += xDelta;
+ }
+ zCur += zDelta;
+ setCallback (z);
+ }
+ }
+
+ /// Enables or disables seamless tiling.
+ ///
+ /// @param enable A flag that enables or disables seamless tiling.
+ ///
+ /// Enabling seamless tiling builds a noise map with no seams at the
+ /// edges. This allows the noise map to be tileable.
+ public void enableSeamless (boolean enable)
+ {
+ isSeamlessEnabled = enable;
+ }
+
+ /// Returns the lower x boundary of the planar noise map.
+ ///
+ /// @returns The lower x boundary of the planar noise map, in units.
+ public double getLowerXBound ()
+ {
+ return lowerXBound;
+ }
+
+ /// Returns the lower z boundary of the planar noise map.
+ ///
+ /// @returns The lower z boundary of the noise map, in units.
+ public double getLowerZBound ()
+ {
+ return lowerZBound;
+ }
+
+ /// Returns the upper x boundary of the planar noise map.
+ ///
+ /// @returns The upper x boundary of the noise map, in units.
+ public double getUpperXBound ()
+ {
+ return upperXBound;
+ }
+
+ /// Returns the upper z boundary of the planar noise map.
+ ///
+ /// @returns The upper z boundary of the noise map, in units.
+ public double getUpperZBound ()
+ {
+ return upperZBound;
+ }
+
+ /// Determines if seamless tiling is enabled.
+ ///
+ /// @returns
+ /// - @a true if seamless tiling is enabled.
+ /// - @a false if seamless tiling is disabled.
+ ///
+ /// Enabling seamless tiling builds a noise map with no seams at the
+ /// edges. This allows the noise map to be tileable.
+ public boolean isSeamlessEnabled ()
+ {
+ return isSeamlessEnabled;
+ }
+
+ /// Sets the boundaries of the planar noise map.
+ ///
+ /// @param lowerXBound The lower x boundary of the noise map, in
+ /// units.
+ /// @param upperXBound The upper x boundary of the noise map, in
+ /// units.
+ /// @param lowerZBound The lower z boundary of the noise map, in
+ /// units.
+ /// @param upperZBound The upper z boundary of the noise map, in
+ /// units.
+ ///
+ /// @pre The lower x boundary is less than the upper x boundary.
+ /// @pre The lower z boundary is less than the upper z boundary.
+ ///
+ /// @throw ExceptionInvalidParam See the preconditions.
+ public void setBounds (double lowerXBound, double upperXBound,
+ double lowerZBound, double upperZBound) throws ExceptionInvalidParam
+ {
+ if (lowerXBound >= upperXBound || lowerZBound >= upperZBound)
+ throw new ExceptionInvalidParam ("Invalid parameter in NoiseMapBuilderPlane");
+
+ this.lowerXBound = lowerXBound;
+ this.upperXBound = upperXBound;
+ this.lowerZBound = lowerZBound;
+ this.upperZBound = upperZBound;
+ }
+
+ public void setLowerXBound(double lowerXBound)
+ {
+ this.lowerXBound = lowerXBound;
+ }
+
+ public void setLowerZBound(double lowerZBound)
+ {
+ this.lowerZBound = lowerZBound;
+ }
+
+ public void setUpperXBound(double upperXBound)
+ {
+ this.upperXBound = upperXBound;
+ }
+
+ public void setUpperZBound(double upperZBound)
+ {
+ this.upperZBound = upperZBound;
+ }
+
+}
diff --git a/src/libnoiseforjava/util/NoiseMapBuilderSphere.java b/src/libnoiseforjava/util/NoiseMapBuilderSphere.java
new file mode 100644
index 0000000..0aa560a
--- /dev/null
+++ b/src/libnoiseforjava/util/NoiseMapBuilderSphere.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.util;
+
+import libnoiseforjava.exception.ExceptionInvalidParam;
+import libnoiseforjava.model.Sphere;
+
+public class NoiseMapBuilderSphere extends NoiseMapBuilder
+{
+ /// Builds a spherical noise map.
+ ///
+ /// This class builds a noise map by filling it with coherent-noise values
+ /// generated from the surface of a sphere.
+ ///
+ /// This class describes these input values using a (latitude, longitude)
+ /// coordinate system. After generating the coherent-noise value from the
+ /// input value, it then "flattens" these coordinates onto a plane so that
+ /// it can write the values into a two-dimensional noise map.
+ ///
+ /// The sphere model has a radius of 1.0 unit. Its center is at the
+ /// origin.
+ ///
+ /// The x coordinate in the noise map represents the longitude. The y
+ /// coordinate in the noise map represents the latitude.
+ ///
+ /// The application must provide the southern, northern, western, and
+ /// eastern bounds of the noise map, in degrees.
+
+ /// Eastern boundary of the spherical noise map, in degrees.
+ double eastLonBound;
+
+ /// Northern boundary of the spherical noise map, in degrees.
+ double northLatBound;
+
+ /// Southern boundary of the spherical noise map, in degrees.
+ double southLatBound;
+
+ /// Western boundary of the spherical noise map, in degrees.
+ double westLonBound;
+
+ public NoiseMapBuilderSphere () throws ExceptionInvalidParam
+ {
+ super();
+ eastLonBound = 0.0;
+ northLatBound = 0.0;
+ southLatBound = 0.0;
+ westLonBound = 0.0;
+ }
+
+ public void build () throws ExceptionInvalidParam
+ {
+ if ( eastLonBound <= westLonBound
+ || northLatBound <= southLatBound
+ || destWidth <= 0
+ || destHeight <= 0
+ || sourceModule == null
+ || destNoiseMap == null)
+ throw new ExceptionInvalidParam ("Invalid Parameter in NoiseMapBuilderSphere");
+
+
+ // Resize the destination noise map so that it can store the new output
+ // values from the source model.
+ destNoiseMap.setSize (destWidth, destHeight);
+
+ // Create the plane model.
+ Sphere sphereModel = new Sphere();
+ sphereModel.setModule (sourceModule);
+
+ double lonExtent = eastLonBound - westLonBound ;
+ double latExtent = northLatBound - southLatBound;
+ double xDelta = lonExtent / (double)destWidth ;
+ double yDelta = latExtent / (double)destHeight;
+ double curLon = westLonBound ;
+ double curLat = southLatBound;
+
+ // Fill every point in the noise map with the output values from the model.
+ for (int y = 0; y < destHeight; y++)
+ {
+ curLon = westLonBound;
+ for (int x = 0; x < destWidth; x++)
+ {
+ float curValue = (float)sphereModel.getValue (curLat, curLon);
+ destNoiseMap.setValue(x, y, curValue);
+ curLon += xDelta;
+ }
+ curLat += yDelta;
+ setCallback(y);
+
+ }
+ }
+
+ /// Returns the eastern boundary of the spherical noise map.
+ ///
+ /// @returns The eastern boundary of the noise map, in degrees.
+ public double getEastLonBound ()
+ {
+ return eastLonBound;
+ }
+
+ /// Returns the northern boundary of the spherical noise map
+ ///
+ /// @returns The northern boundary of the noise map, in degrees.
+ public double getNorthLatBound ()
+ {
+ return northLatBound;
+ }
+
+ /// Returns the southern boundary of the spherical noise map
+ ///
+ /// @returns The southern boundary of the noise map, in degrees.
+ public double getSouthLatBound ()
+ {
+ return southLatBound;
+ }
+
+ /// Returns the western boundary of the spherical noise map
+ ///
+ /// @returns The western boundary of the noise map, in degrees.
+ public double getWestLonBound ()
+ {
+ return westLonBound;
+ }
+
+ /// Sets the coordinate boundaries of the noise map.
+ ///
+ /// @param southLatBound The southern boundary of the noise map, in
+ /// degrees.
+ /// @param northLatBound The northern boundary of the noise map, in
+ /// degrees.
+ /// @param westLonBound The western boundary of the noise map, in
+ /// degrees.
+ /// @param eastLonBound The eastern boundary of the noise map, in
+ /// degrees.
+ ///
+ /// @pre The southern boundary is less than the northern boundary.
+ /// @pre The western boundary is less than the eastern boundary.
+ ///
+ /// @throw noise::ExceptionInvalidParam See the preconditions.
+ public void setBounds (double southLatBound, double northLatBound,
+ double westLonBound, double eastLonBound) throws ExceptionInvalidParam
+ {
+ if (southLatBound >= northLatBound
+ || westLonBound >= eastLonBound)
+ throw new ExceptionInvalidParam ("Invalid Parameter in NoiseMapBuilderSphere");
+
+ this.southLatBound = southLatBound;
+ this.northLatBound = northLatBound;
+ this.westLonBound = westLonBound ;
+ this.eastLonBound = eastLonBound ;
+ }
+
+ public void setEastLonBound(double eastLonBound)
+ {
+ this.eastLonBound = eastLonBound;
+ }
+
+ public void setNorthLatBound(double northLatBound)
+ {
+ this.northLatBound = northLatBound;
+ }
+
+ public void setSouthLatBound(double southLatBound)
+ {
+ this.southLatBound = southLatBound;
+ }
+
+ public void setWestLonBound(double westLonBound)
+ {
+ this.westLonBound = westLonBound;
+ }
+
+}
diff --git a/src/libnoiseforjava/util/RendererImage.java b/src/libnoiseforjava/util/RendererImage.java
new file mode 100644
index 0000000..e437f89
--- /dev/null
+++ b/src/libnoiseforjava/util/RendererImage.java
@@ -0,0 +1,755 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.util;
+
+import libnoiseforjava.Interp;
+import libnoiseforjava.exception.ExceptionInvalidParam;
+
+public class RendererImage {
+
+ // / Renders an image from a noise map.
+ // /
+ // / This class renders an image given the contents of a noise-map object.
+ // /
+ // / An application can configure the output of the image in three ways:
+ // / - Specify the color gradient.
+ // / - Specify the light source parameters.
+ // / - Specify the background image.
+ // /
+ // / <b>Specify the color gradient</b>
+ // /
+ // / This class uses a color gradient to calculate the color for each pixel
+ // / in the destination image according to the value from the corresponding
+ // / position in the noise map.
+ // /
+ // / A color gradient is a list of gradually-changing colors. A color
+ // / gradient is defined by a list of <i>gradient points</i>. Each
+ // / gradient point has a position and a color. In a color gradient, the
+ // / colors between two adjacent gradient points are linearly interpolated.
+ // /
+ // / For example, suppose this class contains the following color gradient:
+ // /
+ // / - -1.0 maps to dark blue.
+ // / - -0.2 maps to light blue.
+ // / - -0.1 maps to tan.
+ // / - 0.0 maps to green.
+ // / - 1.0 maps to white.
+ // /
+ // / The value 0.5 maps to a greenish-white color because 0.5 is halfway
+ // / between 0.0 (mapped to green) and 1.0 (mapped to white).
+ // /
+ // / The value -0.6 maps to a medium blue color because -0.6 is halfway
+ // / between -1.0 (mapped to dark blue) and -0.2 (mapped to light blue).
+ // /
+ // / The color gradient requires a minimum of two gradient points.
+ // /
+ // / This class contains two pre-made gradients: a grayscale gradient and a
+ // / color gradient suitable for terrain. To use these pre-made gradients,
+ // / call the buildGrayscaleGradient() or buildTerrainGradient() methods,
+ // / respectively.
+ // /
+ // / @note The color value passed to addGradientPoint() has an alpha
+ // / channel. This alpha channel specifies how a pixel in the background
+ // / image (if specified) is blended with the calculated color. If the
+ // / alpha value is high, this class weighs the blend towards the
+ // / calculated color, and if the alpha value is low, this class weighs the
+ // / blend towards the color from the corresponding pixel in the background
+ // / image.
+ // /
+ // / <b>Specify the light source parameters</b>
+ // /
+ // / This class contains a parallel light source that lights the image. It
+ // / interprets the noise map as a bump map.
+ // /
+ // / To enable or disable lighting, pass a Boolean value to the
+ // / enableLight() method.
+ // /
+ // / To set the position of the light source in the "sky", call the
+ // / setLightAzimuth() and setLightElev() methods.
+ // /
+ // / To set the color of the light source, call the setLightColor() method.
+ // /
+ // / To set the intensity of the light source, call the setLightIntensity()
+ // / method. A good intensity value is 2.0, although that value tends to
+ // / "wash out" very light colors from the image.
+ // /
+ // / To set the contrast amount between areas in light and areas in shadow,
+ // / call the setLightContrast() method. Determining the correct contrast
+ // / amount requires some trial and error, but if your application
+ // / interprets the noise map as a height map that has its elevation values
+ // / measured in meters and has a horizontal resolution of @a h meters, a
+ // / good contrast amount to use is ( 1.0 / @a h ).
+ // /
+ // / <b>Specify the background image</b>
+ // /
+ // / To specify a background image, pass an Image object to the
+ // / setBackgroundImage() method.
+ // /
+ // / This class determines the color of a pixel in the destination image by
+ // / blending the calculated color with the color of the corresponding
+ // / pixel from the background image.
+ // /
+ // / The blend amount is determined by the alpha of the calculated color.
+ // / If the alpha value is high, this class weighs the blend towards the
+ // / calculated color, and if the alpha value is low, this class weighs the
+ // / blend towards the color from the corresponding pixel in the background
+ // / image.
+ // /
+ // / <b>Rendering the image</b>
+ // /
+ // / To render the image, perform the following steps:
+ // / - Pass a NoiseMap object to the setSourceNoiseMap() method.
+ // / - Pass an ImageCafe object to the setDestImage() method.
+ // / - Pass an ImageCafe object to the setBackgroundImage() method
+ // (optional)
+ // / - Call the render() method.
+
+ static final double SQRT_2 = 1.4142135623730950488;
+
+ // / The cosine of the azimuth of the light source.
+ double cosAzimuth;
+
+ // / The cosine of the elevation of the light source.
+ double cosElev;
+
+ // / The color gradient used to specify the image colors.
+ GradientColor gradient;
+
+ // / A flag specifying whether lighting is enabled.
+ boolean isLightEnabled;
+
+ // / A flag specifying whether wrapping is enabled.
+ boolean isWrapEnabled;
+
+ // / The azimuth of the light source, in degrees.
+ double lightAzimuth;
+
+ // / The brightness of the light source.
+ double lightBrightness;
+
+ // / The color of the light source.
+ ColorCafe lightColor;
+
+ // / The contrast between areas in light and areas in shadow.
+ double lightContrast;
+
+ // / The elevation of the light source, in degrees.
+ double lightElev;
+
+ // / The intensity of the light source.
+ double lightIntensity;
+
+ // / A pointer to the background image.
+ ImageCafe backgroundImage;
+
+ // / A pointer to the destination image.
+ ImageCafe destImageCafe;
+
+ // / A pointer to the source noise map.
+ NoiseMap sourceNoiseMap;
+
+ // / Used by the calcLightIntensity() method to recalculate the light
+ // / values only if the light parameters change.
+ // /
+ // / When the light parameters change, this value is set to True. When
+ // / the calcLightIntensity() method is called, this value is set to
+ // / false.
+ boolean recalcLightValues;
+
+ // / The sine of the azimuth of the light source.
+ double sinAzimuth;
+
+ // / The sine of the elevation of the light source.
+ double sinElev;
+
+ public RendererImage() throws ExceptionInvalidParam {
+ isLightEnabled = false;
+ isWrapEnabled = false;
+ lightAzimuth = 45.0;
+ lightBrightness = 1.0;
+ lightColor = new ColorCafe(255, 255, 255, 255);
+ lightContrast = 1.0;
+ lightElev = 45.0;
+ lightIntensity = 1.0;
+ backgroundImage = null;
+ destImageCafe = null;
+ sourceNoiseMap = null;
+ recalcLightValues = true;
+
+ buildGrayscaleGradient();
+ }
+
+ // / Adds a gradient point to this gradient object.
+ // /
+ // / @param gradientPos The position of this gradient point.
+ // / @param gradientColor The color of this gradient point.
+ // /
+ // / @pre No two gradient points have the same position.
+ // /
+ // / @throw noise::ExceptionInvalidParam See the preconditions.
+ // /
+ // / This object uses a color gradient to calculate the color for each
+ // / pixel in the destination image according to the value from the
+ // / corresponding position in the noise map.
+ // /
+ // / The gradient requires a minimum of two gradient points.
+ // /
+ // / The specified color value passed to this method has an alpha
+ // / channel. This alpha channel specifies how a pixel in the
+ // / background image (if specified) is blended with the calculated
+ // / color. If the alpha value is high, this object weighs the blend
+ // / towards the calculated color, and if the alpha value is low, this
+ // / object weighs the blend towards the color from the corresponding
+ // / pixel in the background image.
+ public void addGradientPoint(double gradientPos, ColorCafe gradientColor) throws ExceptionInvalidParam {
+ gradient.addGradientPoint(gradientPos, gradientColor);
+ }
+
+ // / Builds a grayscale gradient.
+ // /
+ // / @post The original gradient is cleared and a grayscale gradient is
+ // / created.
+ // /
+ // / This color gradient contains the following gradient points:
+ // / - -1.0 maps to black
+ // / - 1.0 maps to white
+ public void buildGrayscaleGradient() throws ExceptionInvalidParam {
+ clearGradient();
+ gradient.addGradientPoint(-1.0, new ColorCafe(0, 0, 0, 255));
+ gradient.addGradientPoint(1.0, new ColorCafe(255, 255, 255, 255));
+ }
+
+ // / Builds a color gradient suitable for terrain.
+ // /
+ // / @post The original gradient is cleared and a terrain gradient is
+ // / created.
+ // /
+ // / This gradient color at position 0.0 is the "sea level". Above
+ // / that value, the gradient contains greens, browns, and whites.
+ // / Below that value, the gradient contains various shades of blue.
+ public void buildTerrainGradient() throws ExceptionInvalidParam {
+ clearGradient();
+ gradient.addGradientPoint(-1.00, new ColorCafe(0, 0, 128, 255));
+ gradient.addGradientPoint(-0.20, new ColorCafe(32, 64, 128, 255));
+ gradient.addGradientPoint(-0.04, new ColorCafe(64, 96, 192, 255));
+ gradient.addGradientPoint(-0.02, new ColorCafe(192, 192, 128, 255));
+ gradient.addGradientPoint(0.00, new ColorCafe(0, 192, 0, 255));
+ gradient.addGradientPoint(0.25, new ColorCafe(192, 192, 0, 255));
+ gradient.addGradientPoint(0.50, new ColorCafe(160, 96, 64, 255));
+ gradient.addGradientPoint(0.75, new ColorCafe(128, 255, 255, 255));
+ gradient.addGradientPoint(1.00, new ColorCafe(255, 255, 255, 255));
+ }
+
+ // / Calculates the destination color.
+ // /
+ // / @param sourceColor The source color generated from the color
+ // / gradient.
+ // / @param backgroundColor The color from the background image at the
+ // / corresponding position.
+ // / @param lightValue The intensity of the light at that position.
+ // /
+ // / @returns The destination color.
+ public ColorCafe calcDestColor(ColorCafe sourceColor, ColorCafe backgroundColor, double lightValue) {
+ double sourceRed = (double) sourceColor.red / 255.0;
+ double sourceGreen = (double) sourceColor.green / 255.0;
+ double sourceBlue = (double) sourceColor.blue / 255.0;
+ double sourceAlpha = (double) sourceColor.alpha / 255.0;
+ double backgroundRed = (double) backgroundColor.red / 255.0;
+ double backgroundGreen = (double) backgroundColor.green / 255.0;
+ double backgroundBlue = (double) backgroundColor.blue / 255.0;
+
+ // First, blend the source color to the background color using the alpha
+ // of the source color.
+ double red = Interp.linearInterp(backgroundRed, sourceRed, sourceAlpha);
+ double green = Interp.linearInterp(backgroundGreen, sourceGreen, sourceAlpha);
+ double blue = Interp.linearInterp(backgroundBlue, sourceBlue, sourceAlpha);
+
+ if (isLightEnabled) {
+ // Now calculate the light color.
+ double lightRed = lightValue * (double) lightColor.red / 255.0;
+ double lightGreen = lightValue * (double) lightColor.green / 255.0;
+ double lightBlue = lightValue * (double) lightColor.blue / 255.0;
+
+ // Apply the light color to the new color.
+ red *= lightRed;
+ green *= lightGreen;
+ blue *= lightBlue;
+ }
+
+ // Clamp the color channels to the (0..1) range.
+ red = (red < 0.0) ? 0.0 : red;
+ red = (red > 1.0) ? 1.0 : red;
+ green = (green < 0.0) ? 0.0 : green;
+ green = (green > 1.0) ? 1.0 : green;
+ blue = (blue < 0.0) ? 0.0 : blue;
+ blue = (blue > 1.0) ? 1.0 : blue;
+
+ // Rescale the color channels to the noise::uint8 (0..255) range and
+ // return
+ // the new color.
+ ColorCafe newColor = new ColorCafe((int) (red * 255.0) & 0xff, (int) (green * 255.0) & 0xff,
+ (int) (blue * 255.0) & 0xff, Math.max(sourceColor.alpha, backgroundColor.alpha));
+ return newColor;
+ }
+
+ // / Calculates the intensity of the light given some elevation values.
+ // /
+ // / @param center Elevation of the center point.
+ // / @param left Elevation of the point directly left of the center
+ // / point.
+ // / @param right Elevation of the point directly right of the center
+ // / point.
+ // / @param down Elevation of the point directly below the center
+ // / point.
+ // / @param up Elevation of the point directly above the center point.
+ // /
+ // / These values come directly from the noise map.
+ public double calcLightIntensity(double center, double left, double right, double down, double up) {
+ // Recalculate the sine and cosine of the various light values if
+ // necessary so it does not have to be calculated each time this method
+ // is
+ // called.
+ if (recalcLightValues) {
+ cosAzimuth = Math.cos(Math.toRadians(lightAzimuth));
+ sinAzimuth = Math.sin(Math.toRadians(lightAzimuth));
+ cosElev = Math.cos(Math.toRadians(lightElev));
+ sinElev = Math.sin(Math.toRadians(lightElev));
+ recalcLightValues = false;
+ }
+
+ // Now do the lighting calculations.
+ double I_MAX = 1.0;
+ double io = I_MAX * SQRT_2 * sinElev / 2.0;
+ double ix = (I_MAX - io) * lightContrast * SQRT_2 * cosElev * cosAzimuth;
+ double iy = (I_MAX - io) * lightContrast * SQRT_2 * cosElev * sinAzimuth;
+ double intensity = (ix * (left - right) + iy * (down - up) + io);
+
+ if (intensity < 0.0)
+ intensity = 0.0;
+
+ return intensity;
+ }
+
+ // / Clears the color gradient.
+ // /
+ // / Before calling the render() method, the application must specify a
+ // / new color gradient with at least two gradient points.
+ public void clearGradient() {
+ gradient = new GradientColor();
+ gradient.clear();
+ }
+
+ // / Renders the destination image using the contents of the source
+ // / noise map and an optional background image.
+ // /
+ // / @pre setSourceNoiseMap() has been previously called.
+ // / @pre setDestImage() has been previously called.
+ // / @pre There are at least two gradient points in the color gradient.
+ // / @pre No two gradient points have the same position.
+ // / @pre If a background image was specified, it has the exact same
+ // / size as the source height map.
+ // /
+ // / @post The original contents of the destination image is destroyed.
+ // /
+ // / @throw ExceptionInvalidParam See the preconditions.
+ // /
+ // / The background image and the destination image can safely refer to
+ // / the same image, although in this case, the destination image is
+ // / irretrievably blended into the background image.
+ public void render() throws ExceptionInvalidParam {
+ if (sourceNoiseMap == null || destImageCafe == null || sourceNoiseMap.getWidth() <= 0
+ || sourceNoiseMap.getHeight() <= 0 || gradient.getGradientPointCount() < 2)
+ throw new ExceptionInvalidParam("Invalid Parameter in RendererImage");
+
+ int width = sourceNoiseMap.getWidth();
+ int height = sourceNoiseMap.getHeight();
+
+ // If a background image was provided, make sure it is the same size the
+ // source noise map.
+ if (backgroundImage != null)
+ if (backgroundImage.getWidth() != width || backgroundImage.getHeight() != height)
+ throw new ExceptionInvalidParam("Invalid Parameter in RendererImage");
+
+ // Create the destination image. It is safe to reuse it if this is also
+ // the
+ // background image.
+ if (destImageCafe != backgroundImage)
+ destImageCafe.setSize(width, height);
+
+ for (int y = 0; y < height; y++) {
+ @SuppressWarnings("unused")
+ ColorCafe background = new ColorCafe(255, 255, 255, 255);
+
+ for (int x = 0; x < width; x++) {
+ // Get the color based on the value at the current point in the
+ // noise
+ // map.
+ ColorCafe destColor = gradient.getColor(sourceNoiseMap.getValue(x, y));
+
+ // If lighting is enabled, calculate the light intensity based
+ // on the
+ // rate of change at the current point in the noise map.
+ double lightIntensity;
+ if (isLightEnabled) {
+ // Calculate the positions of the current point's
+ // four-neighbors.
+ int xLeftOffset, xRightOffset;
+ int yUpOffset, yDownOffset;
+ if (isWrapEnabled) {
+ if (x == 0) {
+ xLeftOffset = (int) width - 1;
+ xRightOffset = 1;
+ } else if (x == (int) width - 1) {
+ xLeftOffset = -1;
+ xRightOffset = -((int) width - 1);
+ } else {
+ xLeftOffset = -1;
+ xRightOffset = 1;
+ }
+
+ if (y == 0) {
+ yDownOffset = (int) height - 1;
+ yUpOffset = 1;
+ } else if (y == (int) height - 1) {
+ yDownOffset = -1;
+ yUpOffset = -((int) height - 1);
+ } else {
+ yDownOffset = -1;
+ yUpOffset = 1;
+ }
+ } else {
+ if (x == 0) {
+ xLeftOffset = 0;
+ xRightOffset = 1;
+ } else if (x == (int) width - 1) {
+ xLeftOffset = -1;
+ xRightOffset = 0;
+ } else {
+ xLeftOffset = -1;
+ xRightOffset = 1;
+ }
+
+ if (y == 0) {
+ yDownOffset = 0;
+ yUpOffset = 1;
+ } else if (y == (int) height - 1) {
+ yDownOffset = -1;
+ yUpOffset = 0;
+ } else {
+ yDownOffset = -1;
+ yUpOffset = 1;
+ }
+ }
+
+ // Get the noise value of the current point in the source
+ // noise map
+ // and the noise values of its four-neighbors.
+ double nc = (double) (sourceNoiseMap.getValue(x, y));
+ double nl = (double) (sourceNoiseMap.getValue(x + xLeftOffset, y));
+ double nr = (double) (sourceNoiseMap.getValue(x + xRightOffset, y));
+ double nd = (double) (sourceNoiseMap.getValue(x, y + yDownOffset));
+ double nu = (double) (sourceNoiseMap.getValue(x, y + yUpOffset));
+
+ // Now we can calculate the lighting intensity.
+ lightIntensity = calcLightIntensity(nc, nl, nr, nd, nu);
+ lightIntensity *= lightBrightness;
+
+ } else {
+ // These values will apply no lighting to the destination
+ // image.
+ lightIntensity = 1.0;
+ }
+
+ // Get the current background color from the background image.
+ ColorCafe backgroundColor = new ColorCafe(255, 255, 255, 255);
+ if (backgroundImage != null)
+ backgroundColor = backgroundImage.getValue(x, y);
+
+ // Blend the destination color, background color, and the light
+ // intensity together, then update the destination image with
+ // that
+ // color.
+ destImageCafe.setValue(x, y, calcDestColor(destColor, backgroundColor, lightIntensity));
+ }
+ }
+ }
+
+ // / Enables or disables the light source.
+ // /
+ // / @param enable A flag that enables or disables the light source.
+ // /
+ // / If the light source is enabled, this object will interpret the
+ // / noise map as a bump map.
+ public void enableLight(boolean enable) {
+ isLightEnabled = enable;
+ }
+
+ // / Enables or disables noise-map wrapping.
+ // /
+ // / @param enable A flag that enables or disables noise-map wrapping.
+ // /
+ // / This object requires five points (the initial point and its four
+ // / neighbors) to calculate light shading. If wrapping is enabled,
+ // / and the initial point is on the edge of the noise map, the
+ // / appropriate neighbors that lie outside of the noise map will
+ // / "wrap" to the opposite side(s) of the noise map. Otherwise, the
+ // / appropriate neighbors are cropped to the edge of the noise map.
+ // /
+ // / Enabling wrapping is useful when creating spherical renderings and
+ // / tileable textures.
+ public void enableWrap(boolean enable) {
+ isWrapEnabled = enable;
+ }
+
+ // / Returns the azimuth of the light source, in degrees.
+ // /
+ // / @returns The azimuth of the light source.
+ // /
+ // / The azimuth is the location of the light source around the
+ // / horizon:
+ // / - 0.0 degrees is east.
+ // / - 90.0 degrees is north.
+ // / - 180.0 degrees is west.
+ // / - 270.0 degrees is south.
+ public double getLightAzimuth() {
+ return lightAzimuth;
+ }
+
+ // / Returns the brightness of the light source.
+ // /
+ // / @returns The brightness of the light source.
+ public double getLightBrightness() {
+ return lightBrightness;
+ }
+
+ // / Returns the color of the light source.
+ // /
+ // / @returns The color of the light source.
+ public ColorCafe getLightColor() {
+ return lightColor;
+ }
+
+ // / Returns the contrast of the light source.
+ // /
+ // / @returns The contrast of the light source.
+ // /
+ // / The contrast specifies how sharp the boundary is between the
+ // / light-facing areas and the shadowed areas.
+ // /
+ // / The contrast determines the difference between areas in light and
+ // / areas in shadow. Determining the correct contrast amount requires
+ // / some trial and error, but if your application interprets the noise
+ // / map as a height map that has a spatial resolution of @a h meters
+ // / and an elevation resolution of 1 meter, a good contrast amount to
+ // / use is ( 1.0 / @a h ).
+ public double getLightContrast() {
+ return lightContrast;
+ }
+
+ // / Returns the elevation of the light source, in degrees.
+ // /
+ // / @returns The elevation of the light source.
+ // /
+ // / The elevation is the angle above the horizon:
+ // / - 0 degrees is on the horizon.
+ // / - 90 degrees is straight up.
+ public double getLightElev() {
+ return lightElev;
+ }
+
+ // / Returns the intensity of the light source.
+ // /
+ // / @returns The intensity of the light source.
+ public double getLightIntensity() {
+ return lightIntensity;
+ }
+
+ // / Determines if the light source is enabled.
+ // /
+ // / @returns
+ // / - @a true if the light source is enabled.
+ // / - @a false if the light source is disabled.
+ public boolean isLightEnabled() {
+ return isLightEnabled;
+ }
+
+ // / Determines if noise-map wrapping is enabled.
+ // /
+ // / @returns
+ // / - @a true if noise-map wrapping is enabled.
+ // / - @a false if noise-map wrapping is disabled.
+ // /
+ // / This object requires five points (the initial point and its four
+ // / neighbors) to calculate light shading. If wrapping is enabled,
+ // / and the initial point is on the edge of the noise map, the
+ // / appropriate neighbors that lie outside of the noise map will
+ // / "wrap" to the opposite side(s) of the noise map. Otherwise, the
+ // / appropriate neighbors are cropped to the edge of the noise map.
+ // /
+ // / Enabling wrapping is useful when creating spherical renderings and
+ // / tileable textures
+ public boolean isWrapEnabled() {
+ return isWrapEnabled;
+ }
+
+ // / Sets the background image.
+ // /
+ // / @param backgroundImage The background image.
+ // /
+ // / If a background image has been specified, the Render() method
+ // / blends the pixels from the background image onto the corresponding
+ // / pixels in the destination image. The blending weights are
+ // / determined by the alpha channel in the pixels in the destination
+ // / image.
+ // /
+ // / The destination image must exist throughout the lifetime of this
+ // / object unless another image replaces that image.
+ public void setBackgroundImage(ImageCafe backgroundImage) {
+ this.backgroundImage = backgroundImage;
+ }
+
+ // / Sets the destination image.
+ // /
+ // / @param destImage The destination image.
+ // /
+ // / The destination image will contain the rendered image after a
+ // / successful call to the Render() method.
+ // /
+ // / The destination image must exist throughout the lifetime of this
+ // / object unless another image replaces that image.
+ public void setDestImage(ImageCafe destImage) {
+ this.destImageCafe = destImage;
+ }
+
+ // / Sets the azimuth of the light source, in degrees.
+ // /
+ // / @param lightAzimuth The azimuth of the light source.
+ // /
+ // / The azimuth is the location of the light source around the
+ // / horizon:
+ // / - 0.0 degrees is east.
+ // / - 90.0 degrees is north.
+ // / - 180.0 degrees is west.
+ // / - 270.0 degrees is south.
+ // /
+ // / Make sure the light source is enabled via a call to the
+ // / EnableLight() method before calling the Render() method.
+ public void setLightAzimuth(double lightAzimuth) {
+ this.lightAzimuth = lightAzimuth;
+ this.recalcLightValues = true;
+ }
+
+ // / Sets the brightness of the light source.
+ // /
+ // / @param lightBrightness The brightness of the light source.
+ // /
+ // / Make sure the light source is enabled via a call to the
+ // / EnableLight() method before calling the Render() method.
+ public void setLightBrightness(double lightBrightness) {
+ this.lightBrightness = lightBrightness;
+ this.recalcLightValues = true;
+ }
+
+ // / Sets the color of the light source.
+ // /
+ // / @param lightColor The light color.
+ // /
+ // / Make sure the light source is enabled via a call to the
+ // / EnableLight() method before calling the Render() method.
+ public void setLightColor(ColorCafe lightColor) {
+ this.lightColor = lightColor;
+ }
+
+ // / Sets the contrast of the light source.
+ // /
+ // / @param lightContrast The contrast of the light source.
+ // /
+ // / @pre The specified light contrast is positive.
+ // /
+ // / @throw noise::ExceptionInvalidParam See the preconditions.
+ // /
+ // / The contrast specifies how sharp the boundary is between the
+ // / light-facing areas and the shadowed areas.
+ // /
+ // / The contrast determines the difference between areas in light and
+ // / areas in shadow. Determining the correct contrast amount requires
+ // / some trial and error, but if your application interprets the noise
+ // / map as a height map that has a spatial resolution of @a h meters
+ // / and an elevation resolution of 1 meter, a good contrast amount to
+ // / use is ( 1.0 / @a h ).
+ // /
+ // / Make sure the light source is enabled via a call to the
+ // / EnableLight() method before calling the Render() method.
+ public void setLightContrast(double lightContrast) throws ExceptionInvalidParam {
+ if (lightContrast <= 0.0)
+ throw new ExceptionInvalidParam("Invalid Parameter in RendererImage");
+
+ this.lightContrast = lightContrast;
+ this.recalcLightValues = true;
+ }
+
+ // / Sets the elevation of the light source, in degrees.
+ // /
+ // / @param lightElev The elevation of the light source.
+ // /
+ // / The elevation is the angle above the horizon:
+ // / - 0 degrees is on the horizon.
+ // / - 90 degrees is straight up.
+ // /
+ // / Make sure the light source is enabled via a call to the
+ // / EnableLight() method before calling the Render() method.
+ public void setLightElev(double lightElev) {
+ this.lightElev = lightElev;
+ this.recalcLightValues = true;
+ }
+
+ // / Sets the intensity of the light source.
+ // /
+ // / @returns The intensity of the light source.
+ // /
+ // / A good value for intensity is 2.0.
+ // /
+ // / Make sure the light source is enabled via a call to the
+ // / enableLight() method before calling the render() method.
+ public void setLightIntensity(double lightIntensity) throws ExceptionInvalidParam {
+ if (lightIntensity < 0.0)
+ throw new ExceptionInvalidParam("Invalid Parameter in RendererImage");
+
+ this.lightIntensity = lightIntensity;
+ this.recalcLightValues = true;
+ }
+
+ // / Sets the source noise map.
+ // /
+ // / @param sourceNoiseMap The source noise map.
+ // /
+ // / The destination image must exist throughout the lifetime of this
+ // / object unless another image replaces that image.
+ public void setSourceNoiseMap(NoiseMap sourceNoiseMap) {
+ this.sourceNoiseMap = sourceNoiseMap;
+ }
+
+}
diff --git a/src/libnoiseforjava/util/RendererNormalMap.java b/src/libnoiseforjava/util/RendererNormalMap.java
new file mode 100644
index 0000000..c3b648b
--- /dev/null
+++ b/src/libnoiseforjava/util/RendererNormalMap.java
@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code)
+ * Copyright 2010 Thomas J. Hodge (java port of libnoise)
+ *
+ * This file is part of libnoiseforjava.
+ *
+ * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at
+ * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be
+ * contacted at [email protected] (for great email, take off every 'zig').
+ * Porting to Java was done by Thomas Hodge, who may be contacted at
+ * [email protected] (remove every 'zag').
+ *
+ * libnoiseforjava is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * libnoiseforjava is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * libnoiseforjava. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package libnoiseforjava.util;
+
+import libnoiseforjava.exception.ExceptionInvalidParam;
+
+public class RendererNormalMap
+{
+ /// Renders a normal map from a noise map.
+ ///
+ /// This class renders an image containing the normal vectors from a noise
+ /// map object. This image can then be used as a bump map for a 3D
+ /// application or game.
+ ///
+ /// This class encodes the (x, y, z) components of the normal vector into
+ /// the (red, green, blue) channels of the image. Like any 24-bit
+ /// true-color image, the channel values range from 0 to 255. 0
+ /// represents a normal coordinate of -1.0 and 255 represents a normal
+ /// coordinate of +1.0.
+ ///
+ /// You should also specify the <i>bump height</i> before rendering the
+ /// normal map. The bump height specifies the ratio of spatial resolution
+ /// to elevation resolution. For example, if your noise map has a spatial
+ /// resolution of 30 meters and an elevation resolution of one meter, set
+ /// the bump height to 1.0 / 30.0.
+ ///
+ /// <b>Rendering the normal map</b>
+ ///
+ /// To render the image containing the normal map, perform the following
+ /// steps:
+ /// - Pass a NoiseMap object to the setSourceNoiseMap() method.
+ /// - Pass an ImageCafe object to the setDestImage() method.
+ /// - Call the render() method.
+
+ /// The bump height for the normal map.
+ double bumpHeight;
+
+ /// A flag specifying whether wrapping is enabled.
+ boolean isWrapEnabled;
+
+ /// A pointer to the destination image.
+ ImageCafe destImageCafe;
+
+ /// A pointer to the source noise map.
+ NoiseMap sourceNoiseMap;
+
+
+ public RendererNormalMap () throws ExceptionInvalidParam
+ {
+ bumpHeight = 1.0;
+ isWrapEnabled = false;
+ destImageCafe = new ImageCafe(0,0);
+ sourceNoiseMap = new NoiseMap(0,0);
+ }
+
+ public RendererNormalMap (int height, int width) throws ExceptionInvalidParam
+ {
+ bumpHeight = 1.0;
+ isWrapEnabled = false;
+ destImageCafe = new ImageCafe(height, width);
+ sourceNoiseMap = new NoiseMap(height, width);
+ }
+
+ /// Calculates the normal vector at a given point on the noise map.
+ ///
+ /// @param nc The height of the given point in the noise map.
+ /// @param nr The height of the left neighbor.
+ /// @param nu The height of the up neighbor.
+ /// @param bumpHeight The bump height.
+ ///
+ /// @returns The normal vector represented as a color.
+ ///
+ /// This method encodes the (x, y, z) components of the normal vector
+ /// into the (red, green, blue) channels of the returned color. In
+ /// order to represent the vector as a color, each coordinate of the
+ /// normal is mapped from the -1.0 to 1.0 range to the 0 to 255 range.
+ ///
+ /// The bump height specifies the ratio of spatial resolution to
+ /// elevation resolution. For example, if your noise map has a
+ /// spatial resolution of 30 meters and an elevation resolution of one
+ /// meter, set the bump height to 1.0 / 30.0.
+ ///
+ /// The spatial resolution and elevation resolution are determined by
+ /// the application.
+ public ColorCafe calcNormalColor (double nc, double nr, double nu,
+ double bumpHeight)
+ {
+ // Calculate the surface normal.
+ nc *= bumpHeight;
+ nr *= bumpHeight;
+ nu *= bumpHeight;
+ double ncr = (nc - nr);
+ double ncu = (nc - nu);
+ double d = Math.sqrt ((ncu * ncu) + (ncr * ncr) + 1);
+ double vxc = (nc - nr) / d;
+ double vyc = (nc - nu) / d;
+ double vzc = 1.0 / d;
+
+ // Map the normal range from the (-1.0 .. +1.0) range to the (0 .. 255)
+ // range.
+ int xc, yc, zc;
+ xc = (int) (Math.floor((vxc + 1.0) * 127.5)) & 0xff;
+ yc = (int) (Math.floor((vyc + 1.0) * 127.5)) & 0xff;
+ zc = (int) (Math.floor((vzc + 1.0) * 127.5)) & 0xff;
+
+ // left as example of what was here in case above conversion doesn't work.
+ //zc = (noise::uint8)((noise::uint)((floor)((vzc + 1.0) * 127.5)) & 0xff);
+
+ return new ColorCafe (xc, yc, zc, 255);
+ }
+
+ /// Renders the noise map to the destination image.
+ ///
+ /// @pre setSourceNoiseMap() has been previously called.
+ /// @pre setDestImage() has been previously called.
+ ///
+ /// @post The original contents of the destination image is destroyed.
+ ///
+ /// @throw ExceptionInvalidParam See the preconditions.
+ public void render () throws ExceptionInvalidParam
+ {
+ if ( sourceNoiseMap == null
+ || destImageCafe == null
+ || sourceNoiseMap.getWidth () <= 0
+ || sourceNoiseMap.getHeight () <= 0)
+ throw new ExceptionInvalidParam ("Invalid Parameter in RendererNormalMap");
+
+
+ int width = sourceNoiseMap.getWidth ();
+ int height = sourceNoiseMap.getHeight ();
+
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ // Calculate the positions of the current point's right and up
+ // neighbors.
+ int xRightOffset, yUpOffset;
+ if (isWrapEnabled)
+ {
+ if (x == (int)width - 1)
+ xRightOffset = -((int)width - 1);
+ else
+ xRightOffset = 1;
+
+ if (y == (int)height - 1)
+ yUpOffset = -((int)height - 1);
+ else
+ yUpOffset = 1;
+ }
+ else
+ {
+ if (x == (int)width - 1)
+ xRightOffset = 0;
+ else
+ xRightOffset = 1;
+
+ if (y == (int)height - 1)
+ yUpOffset = 0;
+ else
+ yUpOffset = 1;
+
+ }
+
+ // Get the noise value of the current point in the source noise map
+ // and the noise values of its right and up neighbors.
+ double nc = (double)(sourceNoiseMap.getValue(x, y));
+ double nr = (double)(sourceNoiseMap.getValue((x + xRightOffset),y));
+ double nu = (double)(sourceNoiseMap.getValue(x, (y + yUpOffset)));
+
+ // Calculate the normal product.
+ destImageCafe.setValue(x,y, (calcNormalColor (nc, nr, nu, bumpHeight)));
+
+ // Go to the next point.
+ //++pSource;
+ //++pDest;
+ }
+ }
+ }
+
+ /// Enables or disables noise-map wrapping.
+ ///
+ /// @param enable A flag that enables or disables noise-map wrapping.
+ ///
+ /// This object requires three points (the initial point and the right
+ /// and up neighbors) to calculate the normal vector at that point.
+ /// If wrapping is/ enabled, and the initial point is on the edge of
+ /// the noise map, the appropriate neighbors that lie outside of the
+ /// noise map will "wrap" to the opposite side(s) of the noise map.
+ /// Otherwise, the appropriate neighbors are cropped to the edge of
+ /// the noise map.
+ ///
+ /// Enabling wrapping is useful when creating spherical and tileable
+ /// normal maps.
+ public void enableWrap (boolean enable)
+ {
+ isWrapEnabled = enable;
+ }
+
+ /// Returns the bump height.
+ ///
+ /// @returns The bump height.
+ ///
+ /// The bump height specifies the ratio of spatial resolution to
+ /// elevation resolution. For example, if your noise map has a
+ /// spatial resolution of 30 meters and an elevation resolution of one
+ /// meter, set the bump height to 1.0 / 30.0.
+ ///
+ /// The spatial resolution and elevation resolution are determined by
+ /// the application.
+ public double getBumpHeight ()
+ {
+ return bumpHeight;
+ }
+
+ /// Determines if noise-map wrapping is enabled.
+ ///
+ /// @returns
+ /// - @a true if noise-map wrapping is enabled.
+ /// - @a false if noise-map wrapping is disabled.
+ ///
+ /// This object requires three points (the initial point and the right
+ /// and up neighbors) to calculate the normal vector at that point.
+ /// If wrapping is/ enabled, and the initial point is on the edge of
+ /// the noise map, the appropriate neighbors that lie outside of the
+ /// noise map will "wrap" to the opposite side(s) of the noise map.
+ /// Otherwise, the appropriate neighbors are cropped to the edge of
+ /// the noise map.
+ ///
+ /// Enabling wrapping is useful when creating spherical and tileable
+ /// normal maps.
+ public boolean isWrapEnabled ()
+ {
+ return isWrapEnabled;
+ }
+
+ /// Sets the bump height.
+ ///
+ /// @param bumpHeight The bump height.
+ ///
+ /// The bump height specifies the ratio of spatial resolution to
+ /// elevation resolution. For example, if your noise map has a
+ /// spatial resolution of 30 meters and an elevation resolution of one
+ /// meter, set the bump height to 1.0 / 30.0.
+ ///
+ /// The spatial resolution and elevation resolution are determined by
+ /// the application.
+ public void setBumpHeight (double bumpHeight)
+ {
+ this.bumpHeight = bumpHeight;
+ }
+
+ /// Sets the destination image.
+ ///
+ /// @param destImage The destination image.
+ ///
+ /// The destination image will contain the normal map after a
+ /// successful call to the render() method.
+ ///
+ /// The destination image must exist throughout the lifetime of this
+ /// object unless another image replaces that image.
+ public void setDestImage (ImageCafe destImage)
+ {
+ this.destImageCafe = destImage;
+ }
+
+ /// Sets the source noise map.
+ ///
+ /// @param sourceNoiseMap The source noise map.
+ ///
+ /// The destination image must exist throughout the lifetime of this
+ /// object unless another image replaces that image.
+ public void setSourceNoiseMap (NoiseMap sourceNoiseMap)
+ {
+ this.sourceNoiseMap = sourceNoiseMap;
+ }
+
+ public ImageCafe getDestImageCafe()
+ {
+ return destImageCafe;
+ }
+
+ public NoiseMap getSourceNoiseMap()
+ {
+ return sourceNoiseMap;
+ }
+
+ public void setDestImageCafe(ImageCafe destImageCafe)
+ {
+ this.destImageCafe = destImageCafe;
+ }
+
+}
diff --git a/src/ru/olamedia/Options.java b/src/ru/olamedia/Options.java
new file mode 100644
index 0000000..e1c4d41
--- /dev/null
+++ b/src/ru/olamedia/Options.java
@@ -0,0 +1,5 @@
+package ru.olamedia;
+
+public class Options {
+ public static int renderDistance = 256;
+}
diff --git a/src/ru/olamedia/asset/Asset.java b/src/ru/olamedia/asset/Asset.java
new file mode 100644
index 0000000..a420c10
--- /dev/null
+++ b/src/ru/olamedia/asset/Asset.java
@@ -0,0 +1,29 @@
+package ru.olamedia.asset;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+public class Asset {
+ protected URL url;
+
+ public boolean inJar() {
+ return url.toString().startsWith("file:jar:");
+ }
+
+ public Asset(URL url) {
+ this.url = url;
+ }
+
+ public URL getURL() {
+ return url;
+ }
+
+ public InputStream getInputStream() throws IOException {
+ return url.openStream();
+ }
+
+ public String getFile() {
+ return url.getFile();
+ }
+}
diff --git a/src/ru/olamedia/asset/AssetManager.java b/src/ru/olamedia/asset/AssetManager.java
new file mode 100644
index 0000000..d1de11b
--- /dev/null
+++ b/src/ru/olamedia/asset/AssetManager.java
@@ -0,0 +1,28 @@
+package ru.olamedia.asset;
+
+import java.net.URL;
+
+public class AssetManager {
+
+ public static URL getBaseURL() {
+ return AssetManager.class.getResource(AssetManager.class.getSimpleName() + ".class");
+ }
+
+ public boolean inJar() {
+ // file:jar:c:/path/to/jar/somejar.jar!
+ return getBaseURL().toString().startsWith("file:jar:");
+ // return getBaseURL().toString().indexOf(".jar!") > 0;
+ }
+
+ public static URL getURL(String path) throws AssetNotFoundException {
+ URL url = AssetManager.class.getClassLoader().getResource(path);
+ if (null == url) {
+ throw new AssetNotFoundException(path);
+ }
+ return url;
+ }
+
+ public static Asset getAsset(String path) throws AssetNotFoundException {
+ return new Asset(getURL(path));
+ }
+}
diff --git a/src/ru/olamedia/asset/AssetNotFoundException.java b/src/ru/olamedia/asset/AssetNotFoundException.java
new file mode 100644
index 0000000..29afdf0
--- /dev/null
+++ b/src/ru/olamedia/asset/AssetNotFoundException.java
@@ -0,0 +1,22 @@
+package ru.olamedia.asset;
+
+public class AssetNotFoundException extends Exception {
+
+ public AssetNotFoundException() {
+ super();
+ }
+
+ public AssetNotFoundException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public AssetNotFoundException(String message) {
+ super(message);
+ }
+
+ public AssetNotFoundException(Throwable cause) {
+ super(cause);
+ }
+
+ private static final long serialVersionUID = 2197816222986044998L;
+}
diff --git a/src/ru/olamedia/asset/package-info.java b/src/ru/olamedia/asset/package-info.java
new file mode 100644
index 0000000..d2ed4df
--- /dev/null
+++ b/src/ru/olamedia/asset/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.asset; \ No newline at end of file
diff --git a/src/ru/olamedia/camera/CameraProjectionMatrix.java b/src/ru/olamedia/camera/CameraProjectionMatrix.java
new file mode 100644
index 0000000..ec1c390
--- /dev/null
+++ b/src/ru/olamedia/camera/CameraProjectionMatrix.java
@@ -0,0 +1,77 @@
+package ru.olamedia.camera;
+
+import org.openmali.FastMath;
+import org.openmali.vecmath2.Matrix4f;
+
+public class CameraProjectionMatrix extends Matrix4f {
+
+ /**
+ * Creates a mesa-style perspective projection transform, that mimics a
+ * standard, camera-based, view-model.
+ *
+ * @param fovy
+ * specifies the field of view in the y direction, in radians
+ * @param aspect
+ * specifies the aspect ratio and thus the field of view in the x
+ * direction. The aspect ratio is the ratio of x to y, or width
+ * to height.
+ * @param zNear
+ * the distance to the frustum's near clipping plane. This value
+ * must be positive, (the value -zNear is the location of the
+ * near clip plane).
+ * @param zFar
+ * the distance to the frustum's far clipping plane.
+ */
+ public final void perspectiveMesa(float fovy, float aspect, float zNear,
+ float zFar) {
+ final float ymax = zNear * FastMath.tan(fovy);
+ final float ymin = -ymax;
+ final float xmin = ymin * aspect;
+ final float xmax = ymax * aspect;
+
+ // don't call glFrustum() because of error semantics (covglu)
+ frustumMesa(xmin, xmax, ymin, ymax, zNear, zFar);
+ }
+
+ /**
+ * Creates a masa-style perspective projection transform, that mimics a
+ * standard, camera-based, view-model. The frustum function-call establishes
+ * a view-model with the eye at the apex of a symmetric view frustum. The
+ * arguments define the frustum and its associated perspective projection:
+ * (left, bottom, -near) and (right, top, -near) specify the point on the
+ * near clipping plane that maps onto the lower-left and upper-right corners
+ * of the window respectively, assuming the eye is located at (0, 0, 0).
+ *
+ * @param left
+ * the vertical line on the left edge of the near clipping plane
+ * mapped to the left edge of the graphics window
+ * @param right
+ * the vertical line on the right edge of the near clipping plane
+ * mapped to the right edge of the graphics window
+ * @param bottom
+ * the horizontal line on the bottom edge of the near clipping
+ * plane mapped to the bottom edge of the graphics window
+ * @param top
+ * the horizontal line on the top edge of the near
+ * @param zNear
+ * the distance to the frustum's near clipping plane. This value
+ * must be positive, (the value -near is the location of the near
+ * clip plane).
+ * @param zFar
+ * the distance to the frustum's far clipping plane. This value
+ * must be positive, and must be greater than near.
+ */
+ public final void frustumMesa(float left, float right, float bottom,
+ float top, float zNear, float zFar) {
+ final float x = (2.0f * zNear) / (right - left);
+ final float y = (2.0f * zNear) / (top - bottom);
+ final float a = (right + left) / (right - left);
+ final float b = (top + bottom) / (top - bottom);
+ final float c = -(zFar + zNear) / (zFar - zNear);
+ final float d = -(2.0f * zFar * zNear) / (zFar - zNear);
+
+ this.set(x, 0f, 0f, 0f, 0f, y, 0f, 0f, a, b, c, -1f, 0f, 0f, d, 0f);
+
+ }
+
+}
diff --git a/src/ru/olamedia/camera/Cameraman.java b/src/ru/olamedia/camera/Cameraman.java
new file mode 100644
index 0000000..7dbbcc0
--- /dev/null
+++ b/src/ru/olamedia/camera/Cameraman.java
@@ -0,0 +1,21 @@
+package ru.olamedia.camera;
+
+/**
+ * Cameraman.
+ *
+ * @desc Primary purpose is providing eyes level: getCameraY()
+ *
+ * @author olamedia
+ *
+ */
+public interface Cameraman {
+ public float getCameraX();
+
+ public float getCameraY();
+
+ public float getCameraZ();
+
+ public void update(float delta);
+
+ public void captureControls();
+}
diff --git a/src/ru/olamedia/camera/MatrixCamera.java b/src/ru/olamedia/camera/MatrixCamera.java
new file mode 100644
index 0000000..de37fc8
--- /dev/null
+++ b/src/ru/olamedia/camera/MatrixCamera.java
@@ -0,0 +1,545 @@
+package ru.olamedia.camera;
+
+import javax.media.opengl.GL2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.glu.GLU;
+import javax.vecmath.Vector3f;
+import javax.vecmath.Matrix4f;
+
+import org.openmali.FastMath;
+
+import static org.openmali.FastMath.*;
+
+import ru.olamedia.olacraft.game.Game;
+import ru.olamedia.input.Keyboard;
+import ru.olamedia.math.Frustum;
+import ru.olamedia.olacraft.render.jogl.PlaneRenderer;
+import ru.olamedia.olacraft.render.jogl.VectorRenderer;
+
+import com.jogamp.newt.event.KeyEvent;
+
+public class MatrixCamera {
+ protected float fov = 90f;
+ protected float aspect = 1f;
+ protected float zNear = 0.1f;
+ protected float zFar = 1000f;
+ private boolean isPitchLocked = true;
+ private float minPitch = -80f;
+ private float maxPitch = 80f;
+ public Frustum frustum = new Frustum();
+
+ private Vector3f position = new Vector3f();
+ private float yaw = 0; // around y
+ private float pitch = 0;
+ private float roll = 0;
+ public Matrix4f projectionMatrix = new Matrix4f();
+ private Matrix4f translationMatrix = new Matrix4f();
+ private Matrix4f xRotationMatrix = new Matrix4f();
+ private Matrix4f yRotationMatrix = new Matrix4f();
+ private Matrix4f zRotationMatrix = new Matrix4f();
+ private Matrix4f rotationMatrix = new Matrix4f();
+ public Matrix4f viewMatrix = new Matrix4f();
+ public Matrix4f worldMatrix = new Matrix4f();
+
+ private Vector3f look = new Vector3f();
+ private Vector3f right = new Vector3f();
+ private Vector3f up = new Vector3f();
+ public boolean isFrustumVisible = false;
+
+ @SuppressWarnings("unused")
+ private org.openmali.vecmath2.Matrix4f matrixToOpenMali(Matrix4f m) {
+ return new org.openmali.vecmath2.Matrix4f(matrixToTransposeArray(m));
+ }
+
+ public void pack() {
+ if (isAttachedToCameraman) {
+ position.x = cameraman.getCameraX();
+ position.y = cameraman.getCameraY();
+ position.z = cameraman.getCameraZ();
+ }
+
+ worldMatrix.setIdentity();
+ packProjectionMatrix();
+ // projectionMatrix.transpose();
+ // worldMatrix.mul(projectionMatrix);
+ translationMatrix.setIdentity();
+ translationMatrix.m03 = position.x;
+ translationMatrix.m13 = position.y - 0.5f; // FIXME y is looking greater
+ // than it should
+ translationMatrix.m23 = position.z;
+ packRotation();
+ packView();
+ // after view matrix created, retrieve vectors:
+ viewMatrix.invert();
+ viewMatrix.transpose();
+ packLookVector();
+ packRightVector();
+ packUpVector();
+ packFrustum();
+ // worldMatrix.mul(projectionMatrix, viewMatrix);
+ // worldMatrix.transpose();
+ // // oglViewMatrix.set(viewMatrix);
+ // // oglViewMatrix.transpose();
+ // frustum = FrustumUtil.extractFrustum(worldMatrix);
+ // Matrix4f vm = new Matrix4f(viewMatrix);
+ // vm.invert();
+ // frustum.compute(matrixToOpenMali(projectionMatrix),
+ // matrixToOpenMali(vm));
+ // ......
+ // finally
+ // ......
+ }
+
+ private ru.olamedia.math.Vector3f nearc;
+
+ private void packFrustum() {
+ float nearD = zNear + (isFrustumVisible ? 0.2f : 0);// zNear;
+ float farD = zFar - (isFrustumVisible ? 1f : 0);// zFar;
+ ru.olamedia.math.Vector3f eye = new ru.olamedia.math.Vector3f(position.getX(), position.getY(), position.getZ());
+ ru.olamedia.math.Vector3f eyef = eye;// .translate(look, 1f);
+ nearc = eyef.translate(look, nearD);
+ ru.olamedia.math.Vector3f farc = eyef.translate(look, farD);
+ final float tang = FastMath.tan(FastMath.toRad(fov) / 2.0f);
+ float nh = nearD * tang * (isFrustumVisible ? 0.3f : 1);// zNear * tang;
+ float nw = nh * aspect * aspect;
+ float fh = farD * tang * (isFrustumVisible ? 0.5f : 1);// zNear * tang;
+ float fw = fh * aspect * aspect;
+ ru.olamedia.math.Vector3f nrb = nearc.translate(right, -nw / 2).translate(up, -nh / 2);
+ ru.olamedia.math.Vector3f nlb = nearc.translate(right, nw / 2).translate(up, -nh / 2);
+ @SuppressWarnings("unused")
+ ru.olamedia.math.Vector3f nrt = nearc.translate(right, -nw / 2).translate(up, nh / 2);
+ ru.olamedia.math.Vector3f nlt = nearc.translate(right, nw / 2).translate(up, nh / 2);
+ ru.olamedia.math.Vector3f frb = farc.translate(right, -fw / 2).translate(up, -fh / 2);
+ ru.olamedia.math.Vector3f flb = farc.translate(right, fw / 2).translate(up, -fh / 2);
+ ru.olamedia.math.Vector3f frt = farc.translate(right, -fw / 2).translate(up, fh / 2);
+ ru.olamedia.math.Vector3f flt = farc.translate(right, fw / 2).translate(up, fh / 2);
+
+ frustum.leftPlane.set3Points(nlb, flb, flt);
+ frustum.leftPlane.n.negate();
+ frustum.rightPlane.set3Points(nrb, frt, frb);
+ // frustum.rightPlane.n.negate();
+ frustum.topPlane.set3Points(nlb, frb, flb);// nlt, frt, flt);
+ // frustum.topPlane.n.negate();
+ frustum.bottomPlane.set3Points(frt, nlt, flt);
+ // frustum.bottomPlane.n.negate();
+ frustum.nearPlane.set3Points(nlb, nlt, nrb);
+ frustum.farPlane.set3Points(flt, flb, frb);
+ }
+
+ private float[] matrixToTransposeArray(Matrix4f m) {
+ return new float[] {
+ //
+ m.m00, m.m01, m.m02, m.m03,//
+ m.m10, m.m11, m.m12, m.m13,//
+ m.m20, m.m21, m.m22, m.m23,//
+ m.m30, m.m31, m.m32, m.m33,//
+ };
+ }
+
+ private float[] matrixToArray(Matrix4f m) {
+ return new float[] {
+ //
+ m.m00, m.m10, m.m20, m.m30,//
+ m.m01, m.m11, m.m21, m.m31,//
+ m.m02, m.m12, m.m22, m.m32,//
+ m.m03, m.m13, m.m23, m.m33,//
+ };
+ }
+
+ private GLU glu;
+
+ public void setUp(GLAutoDrawable drawable) {
+ GL2 gl = drawable.getGL().getGL2();
+ updateKeyboard();
+ updateMouse();
+ if (glu == null) {
+ glu = new GLU();
+ }
+ // gl.glMatrixMode(GL2.GL_PROJECTION);
+ // gl.glLoadIdentity();
+ // glu.gluPerspective(100f, aspect, 0.2, 1000);
+ loadProjectionMatrix(drawable);
+ loadViewMatrix(drawable);
+
+ gl.glColor3f(1, 0, 0);
+ PlaneRenderer.render(frustum.leftPlane, drawable);
+ gl.glColor3f(1, 1, 0);
+ PlaneRenderer.render(frustum.rightPlane, drawable);
+ gl.glColor3f(1, 0, 1);
+ PlaneRenderer.render(frustum.topPlane, drawable);
+ gl.glColor3f(1, 1, 1);
+ PlaneRenderer.render(frustum.bottomPlane, drawable);
+
+ VectorRenderer.render(nearc, frustum.leftPlane.n, drawable);
+ }
+
+ private void loadViewMatrix(GLAutoDrawable drawable) {
+ GL2 gl = drawable.getGL().getGL2();
+ gl.glMatrixMode(GL2.GL_MODELVIEW);
+ gl.glLoadTransposeMatrixf(matrixToArray(viewMatrix), 0);
+ }
+
+ private void loadProjectionMatrix(GLAutoDrawable drawable) {
+ GL2 gl = drawable.getGL().getGL2();
+ gl.glMatrixMode(GL2.GL_PROJECTION);
+ gl.glLoadTransposeMatrixf(matrixToArray(projectionMatrix), 0);
+ }
+
+ private void packProjectionMatrix() {
+ projectionMatrix.setZero();
+ final float tang = FastMath.tan(FastMath.toRad(fov) / 2.0f);
+ final float size = zNear * tang;
+ float left = -size, right = size, bottom = -size / aspect, top = size / aspect;
+ // First Column
+ projectionMatrix.m00 = 2 * zNear / (right - left);
+ // Second Column
+ projectionMatrix.m11 = 2 * zNear / (top - bottom);
+ // Third Column
+ projectionMatrix.m20 = (right + left) / (right - left);
+ projectionMatrix.m21 = (top + bottom) / (top - bottom);
+ projectionMatrix.m22 = -(zFar + zNear) / (zFar - zNear);
+ projectionMatrix.m23 = -1;
+ // Fourth Column
+ projectionMatrix.m32 = -(2 * zFar * zNear) / (zFar - zNear);
+ }
+
+ private void packRotation() {
+ xRotationMatrix.rotX(toRad(pitch));
+ yRotationMatrix.rotY(toRad(yaw));
+ zRotationMatrix.rotZ(toRad(roll));
+
+ rotationMatrix.setIdentity();
+ rotationMatrix.mul(zRotationMatrix);
+ rotationMatrix.mul(yRotationMatrix);
+ rotationMatrix.mul(xRotationMatrix);
+ }
+
+ private void translatePoint(Vector3f point, Vector3f direction, float delta) {
+ point.x += direction.x * delta;
+ point.y += direction.y * delta;
+ point.z += direction.z * delta;
+ }
+
+ private void translate(Vector3f direction, float delta) {
+ translatePoint(position, direction, delta);
+ }
+
+ private void translate(float dx, float dy, float dz) {
+ translate(right, dx);
+ translate(up, dy);
+ translate(look, -dz);
+ }
+
+ private void packView() {
+ viewMatrix.setIdentity();
+ viewMatrix.mul(translationMatrix);
+ viewMatrix.mul(rotationMatrix);
+
+ }
+
+ private void packUpVector() {
+ up.set(viewMatrix.m01, viewMatrix.m11, viewMatrix.m21);
+ }
+
+ private void packRightVector() {
+ right.set(viewMatrix.m00, viewMatrix.m10, viewMatrix.m20);
+ }
+
+ private void packLookVector() {
+ look.set(viewMatrix.m02, viewMatrix.m12, viewMatrix.m22);
+ }
+
+ public MatrixCamera() {
+ right = new Vector3f(1, 0, 0);
+ up = new Vector3f(0, 1, 0);
+ look = new Vector3f(0, 0, 1);
+ isPitchLocked = true;
+ pack();
+ }
+
+ public void captureControls() {
+ Keyboard.setName("flyForward", KeyEvent.VK_W);
+ Keyboard.setName("flyBack", KeyEvent.VK_S);
+ Keyboard.setName("strafeLeft", KeyEvent.VK_A);
+ Keyboard.setName("strafeRight", KeyEvent.VK_D);
+ Keyboard.setName("flyUp", KeyEvent.VK_SPACE);
+ Keyboard.setName("flyDown", KeyEvent.VK_SHIFT);
+ }
+
+ public void mouseMoved(float dx, float dy) {
+ yaw += -dx;
+ pitch += -dy;
+ yaw = yaw % 360;
+ pitch = pitch % 360;
+ }
+
+ public void updateMouse() {
+ if (isPitchLocked) {
+ if (pitch < minPitch) {
+ pitch = minPitch;
+ } else if (pitch > maxPitch) {
+ pitch = maxPitch;
+ }
+ }
+ pack();
+ }
+
+ public void lockPitch(float min, float max) {
+ this.minPitch = min;
+ this.maxPitch = max;
+ isPitchLocked = true;
+ }
+
+ public void unlockPitch() {
+ isPitchLocked = false;
+ }
+
+ public void updateKeyboard() {
+ if (isAttachedToCameraman) {
+ this.cameraman.update(Game.instance.getDelta());
+ return;
+ }
+ // --- Keyboard
+ int left = Keyboard.isKeyDown("strafeLeft") ? 1 : 0;
+ int right = Keyboard.isKeyDown("strafeRight") ? 1 : 0;
+ int up = Keyboard.isKeyDown("flyForward") ? 1 : 0;
+ int down = Keyboard.isKeyDown("flyBack") ? 1 : 0;
+ int flyUp = Keyboard.isKeyDown("flyUp") ? 1 : 0;
+ int flyDown = Keyboard.isKeyDown("flyDown") ? 1 : 0;
+ float distance = 4f * 4.5f * Game.instance.getDelta(); // runspeed, m/s
+ if (up + down + right + left + flyDown + flyUp > 0) {
+ translate(//
+ right * distance - left * distance,//
+ (isAttachedToCameraman ? 0 : flyUp * distance - flyDown * distance),//
+ up * distance - down * distance//
+ );
+ pack();
+ // System.out.println("Moving... " + position.getX() + " "
+ // + position.getY() + " " + position.getZ());
+ }
+ }
+
+ protected Cameraman cameraman = null;
+ protected boolean isAttachedToCameraman = false;
+ protected float distanceFromCameraman = 0; // third-person view / 0 for
+ protected boolean lookToCameraman = false; // back/front third-person view
+
+ /**
+ * @return the fov
+ */
+ public float getFov() {
+ return fov;
+ }
+
+ /**
+ * @param fov
+ * the fov to set
+ */
+ public void setFov(float fov) {
+ this.fov = fov;
+ }
+
+ /**
+ * @return the aspect
+ */
+ public float getAspect() {
+ return aspect;
+ }
+
+ /**
+ * @param aspect
+ * the aspect to set
+ */
+ public void setAspect(float aspect) {
+ this.aspect = aspect;
+ }
+
+ /**
+ * @return the zNear
+ */
+ public float getzNear() {
+ return zNear;
+ }
+
+ /**
+ * @param zNear
+ * the zNear to set
+ */
+ public void setzNear(float zNear) {
+ this.zNear = zNear;
+ }
+
+ /**
+ * @return the zFar
+ */
+ public float getzFar() {
+ return zFar;
+ }
+
+ /**
+ * @param zFar
+ * the zFar to set
+ */
+ public void setzFar(float zFar) {
+ this.zFar = zFar;
+ }
+
+ /**
+ * @return the yaw
+ */
+ public float getYaw() {
+ return yaw;
+ }
+
+ /**
+ * @param yaw
+ * the yaw to set
+ */
+ public void setYaw(float yaw) {
+ this.yaw = yaw;
+ }
+
+ /**
+ * @return the pitch
+ */
+ public float getPitch() {
+ return pitch;
+ }
+
+ /**
+ * @param pitch
+ * the pitch to set
+ */
+ public void setPitch(float pitch) {
+ this.pitch = pitch;
+ }
+
+ /**
+ * @return the cameraman
+ */
+ public Cameraman getCameraman() {
+ return cameraman;
+ }
+
+ /**
+ * @param cameraman
+ * the cameraman to set
+ */
+ public void setCameraman(Cameraman cameraman) {
+ this.cameraman = cameraman;
+ }
+
+ /**
+ * @return the isAttachedToCameraman
+ */
+ public boolean isAttachedToCameraman() {
+ return isAttachedToCameraman;
+ }
+
+ /**
+ * @param isAttachedToCameraman
+ * the isAttachedToCameraman to set
+ */
+ public void setAttachedToCameraman(boolean isAttachedToCameraman) {
+ this.isAttachedToCameraman = isAttachedToCameraman;
+ }
+
+ /**
+ * @return the distanceFromCameraman
+ */
+ public float getDistanceFromCameraman() {
+ return distanceFromCameraman;
+ }
+
+ /**
+ * @param distanceFromCameraman
+ * the distanceFromCameraman to set
+ */
+ public void setDistanceFromCameraman(float distanceFromCameraman) {
+ this.distanceFromCameraman = distanceFromCameraman;
+ }
+
+ /**
+ * @return the lookToCameraman
+ */
+ public boolean isLookToCameraman() {
+ return lookToCameraman;
+ }
+
+ /**
+ * @param lookToCameraman
+ * the lookToCameraman to set
+ */
+ public void setLookToCameraman(boolean lookToCameraman) {
+ this.lookToCameraman = lookToCameraman;
+ }
+
+ public void setX(float x) {
+ position.x = x;
+ }
+
+ public void setY(float y) {
+ position.y = y;
+ }
+
+ public void setZ(float z) {
+ position.z = z;
+ }
+
+ public float getX() {
+ return position.x;
+ }
+
+ public float getY() {
+ return position.y;
+ }
+
+ public float getZ() {
+ return position.z;
+ }
+
+ public float[] getViewMatrixArray() {
+ return matrixToArray(viewMatrix);
+ }
+
+ public float[] getProjectionMatrixArray() {
+ return matrixToArray(viewMatrix);
+ }
+
+ public float getRoll() {
+ return roll;
+ }
+
+ public void attachTo(Cameraman player) {
+ this.cameraman = player;
+ this.isAttachedToCameraman = true;
+ this.cameraman.captureControls();
+ }
+
+ public void detach() {
+ this.isAttachedToCameraman = false;
+ this.captureControls();
+ }
+
+ /**
+ * @return the look
+ */
+ public Vector3f getLook() {
+ return look;
+ }
+
+ /**
+ * @return the right
+ */
+ public Vector3f getRight() {
+ return right;
+ }
+
+ /**
+ * @return the up
+ */
+ public Vector3f getUp() {
+ return up;
+ }
+
+}
diff --git a/src/ru/olamedia/camera/package-info.java b/src/ru/olamedia/camera/package-info.java
new file mode 100644
index 0000000..7a19b7f
--- /dev/null
+++ b/src/ru/olamedia/camera/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.camera; \ No newline at end of file
diff --git a/src/ru/olamedia/controls/package-info.java b/src/ru/olamedia/controls/package-info.java
new file mode 100644
index 0000000..09ce499
--- /dev/null
+++ b/src/ru/olamedia/controls/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.controls; \ No newline at end of file
diff --git a/src/ru/olamedia/debug/SystemInfo.java b/src/ru/olamedia/debug/SystemInfo.java
new file mode 100644
index 0000000..30060a5
--- /dev/null
+++ b/src/ru/olamedia/debug/SystemInfo.java
@@ -0,0 +1,24 @@
+package ru.olamedia.debug;
+
+public class SystemInfo {
+ public static void dump() {
+ int cpu = Runtime.getRuntime().availableProcessors();
+ long maxMemory = Runtime.getRuntime().maxMemory();
+ long totalMemory = Runtime.getRuntime().totalMemory();
+ long freeMemory = Runtime.getRuntime().freeMemory();
+ // String country = System.getProperty("user.country");
+ String username = System.getProperty("user.name");
+ String os = System.getProperty("os.name");
+ String osver = System.getProperty("os.version");
+ String arch = System.getProperty("os.arch");
+ System.out.println("Hello, " + username + " :)");
+ System.out.println("" + os + " " + arch + " " + osver);
+ System.out
+ .println("Total CPU: " + cpu + " Memory free/total/max: "
+ + ((int) Math.floor(freeMemory / (1024 * 1024))) + "/"
+ + ((int) Math.floor(totalMemory / (1024 * 1024))) + "/"
+ + ((int) Math.floor(maxMemory / (1024 * 1024))));
+ System.out.println(System.getProperty("java.vendor") + " " + System.getProperty("java.version"));
+ System.out.println(System.getProperty("java.runtime.name") + " " + System.getProperty("java.runtime.version"));
+ }
+}
diff --git a/src/ru/olamedia/debug/package-info.java b/src/ru/olamedia/debug/package-info.java
new file mode 100644
index 0000000..fbf0e84
--- /dev/null
+++ b/src/ru/olamedia/debug/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.debug; \ No newline at end of file
diff --git a/src/ru/olamedia/game/ClientGame.java b/src/ru/olamedia/game/ClientGame.java
new file mode 100644
index 0000000..1f0eeae
--- /dev/null
+++ b/src/ru/olamedia/game/ClientGame.java
@@ -0,0 +1,13 @@
+package ru.olamedia.game;
+
+public class ClientGame extends Game {
+ GameManager manager;
+ public ClientGame(GameManager manager) {
+ this.manager = manager;
+ }
+ public void pause(){
+ // open in-game menu
+ super.pause();
+ manager.start();
+ }
+}
diff --git a/src/ru/olamedia/game/DynamicJList.java b/src/ru/olamedia/game/DynamicJList.java
new file mode 100644
index 0000000..f944ba3
--- /dev/null
+++ b/src/ru/olamedia/game/DynamicJList.java
@@ -0,0 +1,16 @@
+package ru.olamedia.game;
+
+import javax.swing.DefaultListModel;
+import javax.swing.JList;
+
+public class DynamicJList extends JList {
+ private static final long serialVersionUID = 8188447632893130182L;
+
+ public DynamicJList() {
+ super(new DefaultListModel());
+ }
+
+ public DefaultListModel getContents() {
+ return (DefaultListModel) getModel();
+ }
+}
diff --git a/src/ru/olamedia/game/Game.java b/src/ru/olamedia/game/Game.java
new file mode 100644
index 0000000..8e04259
--- /dev/null
+++ b/src/ru/olamedia/game/Game.java
@@ -0,0 +1,25 @@
+package ru.olamedia.game;
+
+public class Game {
+ public boolean isRunning = false;
+ public boolean isPaused = false;
+ public void dispose(){
+
+ }
+ public void start(){
+ isRunning = true;
+ init();
+ }
+ public void pause(){
+ isPaused = true;
+ }
+ public void resume(){
+ isPaused = false;
+ }
+ public void finish(){
+ isRunning = false;
+ }
+ public void init(){
+
+ }
+}
diff --git a/src/ru/olamedia/game/GameFrame.java b/src/ru/olamedia/game/GameFrame.java
new file mode 100644
index 0000000..e768b63
--- /dev/null
+++ b/src/ru/olamedia/game/GameFrame.java
@@ -0,0 +1,194 @@
+package ru.olamedia.game;
+
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.Image;
+import java.awt.Toolkit;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+import javax.swing.JFrame;
+
+import ru.olamedia.asset.AssetManager;
+import ru.olamedia.asset.AssetNotFoundException;
+import ru.olamedia.input.Keyboard;
+import ru.olamedia.input.MouseJail;
+import ru.olamedia.olacraft.OlaCraft;
+
+import jogamp.newt.awt.NewtFactoryAWT;
+
+import com.jogamp.newt.Display;
+import com.jogamp.newt.Screen;
+import com.jogamp.newt.awt.NewtCanvasAWT;
+import com.jogamp.newt.event.KeyAdapter;
+import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.util.Animator;
+
+public class GameFrame {
+ // java.awt.SystemTray
+ // http://www.oracle.com/technetwork/articles/javase/systemtray-139788.html
+
+ public static GameFrame instance;
+
+ Display display;
+ Screen screen;
+ int screenId;
+ GLProfile glProfile;
+ GLCapabilities caps;
+ protected Frame awtFrame;
+ protected static GLWindow glWindow;
+ protected static JFrame jFrame;
+ int width = 854;
+ int height = 480;
+ public static Animator animator;
+ NewtCanvasAWT newtCanvasAWT;
+ private boolean glMode = false;
+
+ public void initGL() {
+ if (null == newtCanvasAWT) {
+ glProfile = GLProfile.get(GLProfile.GL2);// Default();
+ // ES2
+ caps = new GLCapabilities(glProfile);
+ caps.setHardwareAccelerated(true);
+ caps.setDoubleBuffered(true);
+ caps.setBackgroundOpaque(false);
+
+ display = NewtFactoryAWT.createDisplay(null);
+ screen = NewtFactoryAWT.createScreen(display, screenId);
+ glWindow = GLWindow.create(screen, caps);// GLWindow.create(screen,
+ // caps);
+ newtCanvasAWT = new NewtCanvasAWT(glWindow);
+ glWindow.setUndecorated(false);
+ glWindow.setPointerVisible(true);
+ glWindow.confinePointer(false);
+ glWindow.addWindowListener(new QuitAdapter());
+ animator = new Animator(glWindow);
+ animator.setRunAsFastAsPossible(true); // By default there is a
+ // brief
+ // pause in the animation
+ // loop
+ animator.start();
+ glWindow.addMouseListener(MouseJail.instance);
+ glWindow.addKeyListener(Keyboard.instance);
+ glWindow.addKeyListener(new KeyAdapter() {
+ @Override
+ public void keyReleased(KeyEvent e) {
+ super.keyReleased(e);
+ if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
+ glWindow.confinePointer(false);
+ glWindow.setPointerVisible(true);
+ }
+ }
+ });
+ // animator.setUpdateFPSFrames(100, System.err);
+ jFrame.add(newtCanvasAWT);
+ glWindow.addGLEventListener(GameManager.instance);
+ }
+ }
+
+ public void setGLMode() {
+ if (!glMode) {
+ initGL();
+ glMode = true;
+ newtCanvasAWT.setVisible(true);
+ }
+ }
+
+ public void setUIMode() {
+ if (glMode) {
+ glMode = false;
+ newtCanvasAWT.setVisible(false);
+ }
+ }
+
+ public static int getX() {
+ return jFrame.getX();
+ }
+
+ public static int getY() {
+ return jFrame.getY();
+ }
+
+ public static int getWidth() {
+ if (null == glWindow) {
+ return jFrame.getWidth();
+ }
+ return glWindow.getWidth();
+ }
+
+ public static int getHeight() {
+ if (null == glWindow) {
+ return jFrame.getHeight();
+ }
+ return glWindow.getHeight();
+ }
+
+ public GameFrame() {
+ instance = this;
+ jFrame = new JFrame();
+ jFrame.setMinimumSize(new Dimension(200, 200));
+ jFrame.setSize(width, height);
+ jFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
+ jFrame.setTitle("OlaCraft " + OlaCraft.version);
+ setIcons();
+ // glWindow.setLocation(100, 100);
+ jFrame.addWindowListener(new QuitAdapter());
+ jFrame.setVisible(true);
+ }
+
+ private void setIcons() {
+ List<Image> icons = new ArrayList<Image>();
+ try {
+ icons.add(getImage("icon16x16.png"));
+ icons.add(getImage("icon32x32.png"));
+ icons.add(getImage("icon64x64.png"));
+ icons.add(getImage("icon128x128.png"));
+ icons.add(getImage("icon256x256.png"));
+ } catch (AssetNotFoundException e1) {
+ e1.printStackTrace();
+ }
+ // if (!icons.isEmpty()) {
+ // awtFrame.setIconImage(getImage("icon32x32.png"));
+ jFrame.setIconImages(icons);
+ // }
+ }
+
+ private Image getImage(String filename) throws AssetNotFoundException {
+ String iconFile = AssetManager.getAsset("ru/olamedia/game/" + filename).getFile();
+ return Toolkit.getDefaultToolkit().createImage(iconFile);
+ }
+
+ public Animator getAnimator() {
+ return animator;
+ }
+
+ public static void confinePointer(boolean confine) {
+ if (glWindow != null) {
+ glWindow.confinePointer(confine);
+ }
+ }
+
+ public static void setPointerVisible(boolean visible) {
+ if (glWindow != null) {
+ glWindow.setPointerVisible(visible);
+ }
+ }
+
+ public static GLWindow getWindow() {
+ return glWindow;
+ }
+
+ public static JFrame getFrame() {
+ return jFrame;
+ }
+
+ public void dispose() {
+ // glWindow.destroy();
+ // newtCanvasAWT.destroy();
+ jFrame.dispose();
+ // System.err.close();
+ }
+}
diff --git a/src/ru/olamedia/game/GameManager.java b/src/ru/olamedia/game/GameManager.java
new file mode 100644
index 0000000..f8c05d9
--- /dev/null
+++ b/src/ru/olamedia/game/GameManager.java
@@ -0,0 +1,165 @@
+package ru.olamedia.game;
+
+import java.util.Set;
+
+import javax.media.nativewindow.WindowClosingProtocol.WindowClosingMode;
+import javax.media.opengl.DebugGL2ES2;
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+
+import ru.olamedia.olacraft.game.Game;
+import ru.olamedia.olacraft.network.discovery.DiscoveryThread;
+import ru.olamedia.olacraft.render.jogl.DefaultRenderer;
+import ru.olamedia.olacraft.render.jogl.IRenderer;
+import ru.olamedia.tasks.TaskManager;
+
+
+import com.jogamp.opengl.JoglVersion;
+
+public class GameManager implements GLEventListener {
+ public static GameManager instance;
+ private GameFrame frame;
+ private ClientGame clientGame;
+ private ServerGame serverGame;
+ private IRenderer renderer;
+ private MainMenu menu;
+
+ public GameManager() {
+ instance = this;
+ }
+
+ private void createServerGame() {
+ if (null == serverGame) {
+ serverGame = new ServerGame(this);
+ }
+ }
+
+ private void createClientGame() {
+ if (null == clientGame) {
+ clientGame = new ClientGame(this);
+ }
+ }
+
+ public void startServerGame() {
+ createServerGame();
+ serverGame.start();
+ }
+
+ public void startClientGame() {
+ createClientGame();
+ clientGame.start();
+ }
+
+ public void resumeClientGame() {
+ createClientGame();
+ clientGame.resume();
+ }
+
+ public void finishClientGame() {
+ createClientGame();
+ clientGame.finish();
+ }
+
+ public void resumeServerGame() {
+ createServerGame();
+ serverGame.resume();
+ }
+
+ public void finishServerGame() {
+ createServerGame();
+ clientGame.finish();
+ serverGame.dispose();
+ }
+
+ private void init() {
+ this.frame = new GameFrame();
+ menu = new MainMenu();
+ this.renderer = new DefaultRenderer();
+ GameFrame.getFrame().getContentPane().add(menu);
+ menu.setVisible(true);
+ GameFrame.getFrame().validate();
+ }
+
+ public void start() {
+ init();
+ while (!QuitAdapter.shouldQuit) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void dispose() {
+ TaskManager.stopAll();
+ if (null != Game.server) {
+ Game.server.dispose();
+ }
+ if (null != Game.client) {
+ Game.client.dispose();
+ }
+ if (null != GameFrame.animator) {
+ if (GameFrame.animator.isStarted()) {
+ GameFrame.animator.stop();
+ }
+ }
+ frame.dispose();
+ // Get all threads
+ Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
+ for (Thread t : threadSet) {
+ if (t instanceof DiscoveryThread) {
+ t.interrupt();
+ }
+ }
+ }
+
+ @Override
+ public void init(GLAutoDrawable drawable) {
+ // GLContext.getContext().getGL()
+ GL2ES2 gl = drawable.getGL().getGL2ES2();
+ //drawable.setGL(new DebugGL2ES2(gl));
+ System.err.println(JoglVersion.getGLInfo(drawable.getGL(), null));
+ System.err.println(Thread.currentThread() + " Chosen GLCapabilities: "
+ + drawable.getChosenGLCapabilities());
+ System.err.println(Thread.currentThread() + " INIT GL IS: " + gl.getClass().getName());
+ System.err.println(Thread.currentThread() + " GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR));
+ System.err.println(Thread.currentThread() + " GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER));
+ System.err.println(Thread.currentThread() + " GL_VERSION: " + gl.glGetString(GL.GL_VERSION));
+ System.err.println(Thread.currentThread() + " GL Profile: " + gl.getGLProfile());
+ System.err.println(Thread.currentThread() + " GL:" + gl);
+ System.err.println(Thread.currentThread() + " GL_VERSION=" + gl.glGetString(GL.GL_VERSION));
+ renderer.init(drawable);
+ }
+
+ @Override
+ public void dispose(GLAutoDrawable drawable) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void display(GLAutoDrawable drawable) {
+ GL2ES2 gl = drawable.getGL().getGL2ES2();
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ //gl.glClearColor(0.2f, 0.2f, 0.2f, 1);
+ renderer.render(drawable);
+ }
+
+ @Override
+ public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+ GL gl = drawable.getGL().getGL2ES2();
+ gl.glViewport(0, 0, width, height);
+ }
+
+ public void showMainMenu() {
+ menu.setVisible(true);
+ }
+
+ public void hideMainMenu() {
+ menu.setVisible(false);
+ }
+
+}
diff --git a/src/ru/olamedia/game/Launcher.java b/src/ru/olamedia/game/Launcher.java
new file mode 100644
index 0000000..7849468
--- /dev/null
+++ b/src/ru/olamedia/game/Launcher.java
@@ -0,0 +1,17 @@
+package ru.olamedia.game;
+
+public class Launcher {
+
+ public Launcher() {
+ }
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+ GameManager manager = new GameManager();
+ manager.start();
+ manager.dispose();
+ }
+
+}
diff --git a/src/ru/olamedia/game/MainMenu.java b/src/ru/olamedia/game/MainMenu.java
new file mode 100644
index 0000000..1b3db13
--- /dev/null
+++ b/src/ru/olamedia/game/MainMenu.java
@@ -0,0 +1,168 @@
+package ru.olamedia.game;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.net.InetAddress;
+
+import javax.swing.JButton;
+import javax.swing.JPanel;
+import javax.swing.border.Border;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.LineBorder;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+
+import ru.olamedia.olacraft.game.Game;
+import ru.olamedia.olacraft.network.ConnectionState;
+import ru.olamedia.olacraft.network.ConnectionStateListener;
+import ru.olamedia.olacraft.network.discovery.DiscoveryClient;
+import ru.olamedia.olacraft.network.discovery.DiscoveryListener;
+
+public class MainMenu extends JPanel implements ActionListener {
+ private JButton startButton;
+ private JButton startServerButton;
+ private JButton discoveryButton;
+ private DynamicJList hosts;
+ private DiscoveryClient discoveryClient = DiscoveryClient.getInstance();
+ private Thread discoveryClientThread;
+ private static final long serialVersionUID = -271797500986576805L;
+
+ private void stylizeButton(JButton b) {
+ Border line = new LineBorder(Color.BLACK);
+ Border margin = new EmptyBorder(5, 15, 5, 15);
+ Border compound = new CompoundBorder(line, margin);
+ b.setBackground(new Color(1f, 1f, 1f, 0.8f));
+ b.setBorder(compound);
+ }
+
+ private static boolean DEBUG = true;
+
+ @SuppressWarnings("unused")
+ private void debug(String s) {
+ if (DEBUG) {
+ System.out.println("[MainMenu] " + s);
+ }
+ }
+
+ public MainMenu() {
+ setSize(GameFrame.getWidth(), GameFrame.getHeight());
+ setOpaque(false);
+ // setBackground(new Color(0f, 0f, 0f, 0.8f));
+ startButton = new JButton();
+ startButton.setSize(500, 40);
+ startButton.setLocation((GameFrame.getWidth() - 500) / 2, 200);
+ startButton.setText("JOIN GAME");
+ startButton.setEnabled(false);
+ startButton.setActionCommand("connect");
+ startButton.addActionListener(this);
+ stylizeButton(startButton);
+ startServerButton = new JButton();
+ startServerButton.setSize(500, 40);
+ startServerButton.setLocation((GameFrame.getWidth() - 500) / 2, 260);
+ startServerButton.setText("START SERVER");
+ startServerButton.setActionCommand("start server");
+ startServerButton.addActionListener(this);
+ stylizeButton(startServerButton);
+ discoveryButton = new JButton();
+ discoveryButton.setSize(500, 40);
+ discoveryButton.setLocation((GameFrame.getWidth() - 500) / 2, 320);
+ discoveryButton.setText("REFRESH");
+ discoveryButton.setActionCommand("discovery lan");
+ discoveryButton.addActionListener(this);
+ stylizeButton(discoveryButton);
+ hosts = new DynamicJList();
+ hosts.setSize(500, 150);
+ hosts.setLocation((GameFrame.getWidth() - 500) / 2, 10);
+ hosts.addListSelectionListener(new ListSelectionListener() {
+ @Override
+ public void valueChanged(ListSelectionEvent e) {
+ if (hosts.getContents().isEmpty()) {
+ Game.client.setHostname("127.0.0.1");
+ System.out.println("Selected: none");
+ startButton.setEnabled(false);
+ } else {
+ String host = (String) hosts.getContents().get(e.getFirstIndex());
+ Game.client.setHostname(host);
+ System.out.println("Selected: " + host);
+ startButton.setEnabled(true);
+ }
+ }
+ });
+ add(hosts);
+ add(startButton);
+ add(startServerButton);
+ add(discoveryButton);
+ // LAN discover
+ // InetAddress address = Game.client.discoverHost(54777, 5000);
+ // System.out.println(address);
+ setLayout(new BorderLayout());
+ validate();
+ Game.client.addStateListener(new ConnectionStateListener() {
+ @Override
+ public void onChangeState(ConnectionState state) {
+ // debug("Client ConnectionState changed");
+ if (state.isConnected()) {
+ GameFrame.instance.setGLMode();
+ Game.instance.player.captureControls();
+ startButton.setText("LEAVE GAME");
+ } else {
+ GameFrame.instance.setUIMode();
+ startButton.setText("JOIN GAME");
+ }
+ }
+ });
+ discoveryClient.addHostListener(new DiscoveryListener() {
+ @Override
+ public void onHost(InetAddress address) {
+ if (null == address) {
+ discoveryButton.setEnabled(true);
+ } else {
+ hosts.getContents().addElement(address.getHostAddress());
+ }
+ }
+ });
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ String cmd = e.getActionCommand();
+ if (cmd.equals("connect")) {
+ if (null != Game.instance) {
+ Game.instance = null;
+ }
+ Game.instance = new Game(Game.MODE_MULTIPLAYER);
+ if (Game.client.isConnected()) {
+ // LEAVE GAME
+ Game.client.close();
+ } else {
+ Game.client.connect();
+ }
+ Game.instance.start();
+ }
+ if (cmd.equals("start server")) {
+ startServerButton.setEnabled(false);
+ if (Game.server.isRunning()) {
+ Game.server.stop();
+ startServerButton.setText("START SERVER");
+ startServerButton.setEnabled(true);
+ } else {
+ Game.server.start();
+ if (Game.server.isRunning()) {
+ startServerButton.setText("STOP SERVER");
+ startServerButton.setEnabled(true);
+ } else {
+ startServerButton.setEnabled(true);
+ }
+ }
+ }
+ if (cmd.equals("discovery lan")) {
+ discoveryButton.setEnabled(false);
+ discoveryClientThread = new Thread(DiscoveryClient.getInstance(), "DISCOVERY CLIENT");
+ discoveryClientThread.start();
+ hosts.getContents().clear();
+ }
+ }
+}
diff --git a/src/ru/olamedia/game/QuitAdapter.java b/src/ru/olamedia/game/QuitAdapter.java
new file mode 100644
index 0000000..8de1e8a
--- /dev/null
+++ b/src/ru/olamedia/game/QuitAdapter.java
@@ -0,0 +1,71 @@
+package ru.olamedia.game;
+
+import com.jogamp.newt.event.*;
+
+public class QuitAdapter extends WindowAdapter implements WindowListener, KeyListener, java.awt.event.WindowListener {
+ public static boolean shouldQuit = false;
+
+ public boolean shouldQuit() {
+ return shouldQuit;
+ }
+
+ public void windowDestroyNotify(WindowEvent e) {
+ System.err.println("QUIT Window " + Thread.currentThread());
+ shouldQuit = true;
+ }
+
+ public void keyTyped(KeyEvent e) {
+ if (e.getKeyChar() == 'q') {
+ System.err.println("QUIT Key " + Thread.currentThread());
+ shouldQuit = true;
+ }
+ }
+
+ public void keyPressed(KeyEvent e) {
+ }
+
+ public void keyReleased(KeyEvent e) {
+ }
+
+ @Override
+ public void windowActivated(java.awt.event.WindowEvent arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void windowClosed(java.awt.event.WindowEvent arg0) {
+ // TODO Auto-generated method stub
+ shouldQuit = true;
+ }
+
+ @Override
+ public void windowClosing(java.awt.event.WindowEvent arg0) {
+ System.err.println("QUIT Window " + Thread.currentThread());
+ shouldQuit = true;
+ }
+
+ @Override
+ public void windowDeactivated(java.awt.event.WindowEvent arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void windowDeiconified(java.awt.event.WindowEvent arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void windowIconified(java.awt.event.WindowEvent arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void windowOpened(java.awt.event.WindowEvent arg0) {
+ // TODO Auto-generated method stub
+
+ }
+}
diff --git a/src/ru/olamedia/game/ServerGame.java b/src/ru/olamedia/game/ServerGame.java
new file mode 100644
index 0000000..900a93f
--- /dev/null
+++ b/src/ru/olamedia/game/ServerGame.java
@@ -0,0 +1,10 @@
+package ru.olamedia.game;
+
+public class ServerGame extends Game {
+ GameManager manager;
+
+ public ServerGame(GameManager manager) {
+ this.manager = manager;
+ }
+
+}
diff --git a/src/ru/olamedia/game/icon128x128.png b/src/ru/olamedia/game/icon128x128.png
new file mode 100644
index 0000000..3572950
--- /dev/null
+++ b/src/ru/olamedia/game/icon128x128.png
Binary files differ
diff --git a/src/ru/olamedia/game/icon16x16.png b/src/ru/olamedia/game/icon16x16.png
new file mode 100644
index 0000000..1e2d694
--- /dev/null
+++ b/src/ru/olamedia/game/icon16x16.png
Binary files differ
diff --git a/src/ru/olamedia/game/icon256x256.png b/src/ru/olamedia/game/icon256x256.png
new file mode 100644
index 0000000..441eae8
--- /dev/null
+++ b/src/ru/olamedia/game/icon256x256.png
Binary files differ
diff --git a/src/ru/olamedia/game/icon32x32.png b/src/ru/olamedia/game/icon32x32.png
new file mode 100644
index 0000000..78a1277
--- /dev/null
+++ b/src/ru/olamedia/game/icon32x32.png
Binary files differ
diff --git a/src/ru/olamedia/game/icon64x64.png b/src/ru/olamedia/game/icon64x64.png
new file mode 100644
index 0000000..34a184b
--- /dev/null
+++ b/src/ru/olamedia/game/icon64x64.png
Binary files differ
diff --git a/src/ru/olamedia/game/package-info.java b/src/ru/olamedia/game/package-info.java
new file mode 100644
index 0000000..86a2d0d
--- /dev/null
+++ b/src/ru/olamedia/game/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.game; \ No newline at end of file
diff --git a/src/ru/olamedia/geom/DisplayList.java b/src/ru/olamedia/geom/DisplayList.java
new file mode 100644
index 0000000..aeaffc7
--- /dev/null
+++ b/src/ru/olamedia/geom/DisplayList.java
@@ -0,0 +1,39 @@
+package ru.olamedia.geom;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GLAutoDrawable;
+
+public class DisplayList {
+ private GL2 gl;
+ private int glDL;
+
+ public DisplayList(GL glx) {
+ gl = glx.getGL2();
+ glDL = gl.glGenLists(1);
+ }
+
+ public void start() {
+ gl.glNewList(glDL, GL2.GL_COMPILE);
+ }
+
+ public void stop() {
+ gl.glEndList();
+ }
+
+ public void render() {
+ gl.glCallList(glDL);
+ }
+
+ public void destroy() {
+ gl.glDeleteLists(glDL, 1);
+ }
+
+ public void begin() {
+ start();
+ }
+
+ public void end() {
+ stop();
+ }
+}
diff --git a/src/ru/olamedia/geom/Frustum.java b/src/ru/olamedia/geom/Frustum.java
new file mode 100644
index 0000000..5428302
--- /dev/null
+++ b/src/ru/olamedia/geom/Frustum.java
@@ -0,0 +1,11 @@
+package ru.olamedia.geom;
+
+//import org.openmali.spatial.bodies.Frustum;
+
+public class Frustum extends org.openmali.spatial.bodies.Frustum {
+
+ public Frustum() {
+ super();
+ }
+
+}
diff --git a/src/ru/olamedia/geom/Mesh.java b/src/ru/olamedia/geom/Mesh.java
new file mode 100644
index 0000000..140cc4d
--- /dev/null
+++ b/src/ru/olamedia/geom/Mesh.java
@@ -0,0 +1,346 @@
+package ru.olamedia.geom;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.util.HashMap;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.fixedfunc.GLPointerFunc;
+
+import com.jogamp.opengl.util.GLArrayDataServer;
+import com.jogamp.opengl.util.texture.Texture;
+
+public class Mesh {
+ private FloatBuffer buffer;
+ private float[] data;
+ private int ptr;
+ private int vertexCount;
+ private int vertexPtr;
+ private float xOffset;
+ private float yOffset;
+ private float zOffset;
+
+ private boolean useColor;
+ private float red = 1f;
+ private float green = 1f;
+ private float blue = 1f;
+ private float alpha = 1f;
+
+ private boolean useTexture;
+ private float GLTexture;
+ private float u = 0f;
+ private float v = 0f;
+ @SuppressWarnings("unused")
+ private float uFactor = 1f;
+ @SuppressWarnings("unused")
+ private float vFactor = 1f;
+
+ private boolean wireframe = false;
+
+ private static int vertexSize = 10;
+
+ private GLArrayDataServer interleaved;
+ private HashMap<Integer, Integer> materials = new HashMap<Integer, Integer>();
+ private HashMap<Integer, GLArrayDataServer> arrays = new HashMap<Integer, GLArrayDataServer>();
+
+ public void setTexture(Texture tex) {
+ if (null != tex) {
+ setTextureSize(tex.getWidth(), tex.getHeight());
+ setGLTexture(tex.getTextureObject(null));
+ }
+ }
+
+ public void setGLTexture(int tex) {
+ this.GLTexture = tex;
+ }
+
+ @SuppressWarnings("unused")
+ private static boolean useVbo = true;
+
+ private static boolean useQuad = true;
+ private static boolean useDisplayList = false;
+ private DisplayList DL;
+
+ public Mesh(int size) {
+ vertexCount = 0;
+ data = new float[size * vertexSize];
+ // data = new float[size * vertexSize];
+ vertexPtr = 0;
+ useTexture = false;
+ useColor = false;
+ }
+
+ private static FloatBuffer generateFloatBuffer(int size) {
+ return ByteBuffer.allocateDirect(size * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
+ }
+
+ /**
+ * Reallocates an array with a new size, and copies the contents of the old
+ * array to the new array.
+ *
+ * @param oldArray
+ * the old array, to be reallocated.
+ * @param newSize
+ * the new array size.
+ * @return A new array with the same contents.
+ */
+ private static float[] resizeArray(float[] oldArray, int newSize) {
+ int oldSize = oldArray.length;
+ float[] newArray = new float[newSize];
+ int preserveLength = Math.min(oldSize, newSize);
+ if (preserveLength > 0)
+ System.arraycopy(oldArray, 0, newArray, 0, preserveLength);
+ return newArray;
+ }
+
+ public void compact() {
+ // data = resizeArray(data, vertexCount * vertexSize);
+ int size = vertexCount * vertexSize;
+ buffer = generateFloatBuffer(size);
+ buffer.position(0);
+ buffer.put(data, 0, size);
+ data = null;
+ // calc vertex count for each material
+ for (int n = 0; n < vertexCount; n++) {
+ int tex = (int) buffer.get(vertexSize * n + 9);
+ if (!materials.containsKey(tex)) {
+ materials.put(tex, 1);
+ } else {
+ materials.put(tex, materials.get(tex) + 1);
+ }
+ }
+ for (Integer m : materials.keySet()) {
+ int matVertCount = materials.get(m);
+ final GLArrayDataServer interleaved = GLArrayDataServer.createFixedInterleaved(9, GL2.GL_FLOAT, false,
+ matVertCount, GL.GL_STATIC_DRAW);
+ interleaved.addFixedSubArray(GLPointerFunc.GL_VERTEX_ARRAY, 3, GL.GL_ARRAY_BUFFER);
+ interleaved.addFixedSubArray(GLPointerFunc.GL_COLOR_ARRAY, 4, GL.GL_ARRAY_BUFFER);
+ interleaved.addFixedSubArray(GLPointerFunc.GL_TEXTURE_COORD_ARRAY, 2, GL.GL_ARRAY_BUFFER);
+ arrays.put(m, interleaved);
+ }
+ for (int n = 0; n < vertexCount; n++) {
+ int m = (int) buffer.get(vertexSize * n + 9);
+ final GLArrayDataServer interleaved = arrays.get(m);
+ interleaved.putf(buffer.get(vertexSize * n + 0));
+ interleaved.putf(buffer.get(vertexSize * n + 1));
+ interleaved.putf(buffer.get(vertexSize * n + 2));
+ interleaved.putf(buffer.get(vertexSize * n + 3));
+ interleaved.putf(buffer.get(vertexSize * n + 4));
+ interleaved.putf(buffer.get(vertexSize * n + 5));
+ interleaved.putf(buffer.get(vertexSize * n + 6));
+ interleaved.putf(buffer.get(vertexSize * n + 7));
+ interleaved.putf(buffer.get(vertexSize * n + 8));
+ }
+ for (Integer m : materials.keySet()) {
+ final GLArrayDataServer interleaved = arrays.get(m);
+ interleaved.seal(true);
+ }
+ // interleaved.put(buffer);
+ if (vertexCount > 0) {
+ // System.out.println(interleaved);
+ }
+ /*
+ * buffer.position(0);
+ * buffer.limit(size * vertexSize);
+ * buffer.position(0);
+ * buffer.limit(vertexCount * vertexSize);
+ * buffer.compact();
+ * buffer.position(0);
+ */
+ }
+
+ public void endMesh() {
+ compact();
+ }
+
+ public void setTranslation(float x, float y, float z) {
+ xOffset = x;
+ yOffset = y;
+ zOffset = z;
+ }
+
+ public void setPoint3f(float x, float y, float z) {
+ ptr = vertexPtr * vertexSize;
+ data[ptr + 0] = x + xOffset;
+ // buffer.put(x + xOffset);
+ data[ptr + 1] = y + yOffset;
+ // buffer.put(y + yOffset);
+ data[ptr + 2] = z + zOffset;
+ // buffer.put(z + zOffset);
+ if (useColor) {
+ data[ptr + 3] = red;
+ // buffer.put(red);
+ data[ptr + 4] = green;
+ // buffer.put(green);
+ data[ptr + 5] = blue;
+ // buffer.put(blue);
+ data[ptr + 6] = alpha;
+ // buffer.put(alpha);
+ } else {
+ // buffer.put(1f);
+ // buffer.put(1f);
+ // buffer.put(1f);
+ // buffer.put(1f);
+ }
+ if (useTexture) {
+ // buffer.put(GLTexture);
+ data[ptr + 7] = u;// * uFactor;
+ // buffer.put(u);
+ data[ptr + 8] = v;// * vFactor;
+ data[ptr + 9] = GLTexture;
+ // buffer.put(v);
+ } else {
+ // buffer.put(0f);
+ // buffer.put(0f);
+ // buffer.put(0f);
+ }
+ vertexPtr++;
+ vertexCount++;
+ }
+
+ public void setColor4f(float red, float green, float blue, float alpha) {
+ this.red = red;
+ this.green = green;
+ this.blue = blue;
+ this.alpha = alpha;
+ }
+
+ public void useColor() {
+ useColor = true;
+ }
+
+ public void useTexture() {
+ useTexture = true;
+ }
+
+ public void setUV(float u, float v) {
+ this.u = u;
+ this.v = v;
+ }
+
+ public void setTextureSize(float uSize, float vSize) {
+ this.uFactor = uSize;
+ this.vFactor = vSize;
+ }
+
+ public boolean joglIsVBOAvailable(GLAutoDrawable drawable) {
+ GL2 gl = drawable.getGL().getGL2();
+ return gl.isFunctionAvailable("glGenBuffers") && gl.isFunctionAvailable("glBindBuffer")
+ && gl.isFunctionAvailable("glBufferData") && gl.isFunctionAvailable("glDeleteBuffers");
+ }
+
+ public void joglCreateVBO(GLAutoDrawable drawable) {
+ @SuppressWarnings("unused")
+ GL2 gl = drawable.getGL().getGL2();
+ // gl.glInterleavedArrays(GL2.GL_T2F_C4F_N3F_V3F, stride, pointer)
+
+ }
+
+ public void joglRender(GL glx) {
+ if (vertexCount < 1) {
+ return;
+ }
+ GL2 gl;
+ GL2ES2 es2;
+ gl = glx.getGL2();
+ if (useDisplayList) {
+ gl.glEnable(GL2.GL_CULL_FACE);
+ gl.glEnable(GL2.GL_DEPTH_TEST);
+ }
+ if (wireframe) {
+ // Set wireframe mode
+ gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL2.GL_LINE);
+ } else {
+ gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL2.GL_FILL);
+ }
+
+ if (useVbo) {
+ // es2 = glx.getGL2ES2();
+ // gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, data);
+
+ // gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0);
+ // gl.glBindBuffer(GL2.GL_ELEMENT_ARRAY_BUFFER, 0);
+ for (Integer m : materials.keySet()) {
+ //final GLArrayDataServer interleaved = arrays.get(m);
+ arrays.get(m).enableBuffer(gl, true);
+ gl.glEnable(GL.GL_TEXTURE_2D);
+ gl.glEnable(GL2.GL_CULL_FACE);
+ gl.glEnable(GL2.GL_DEPTH_TEST);
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST_MIPMAP_NEAREST);
+ gl.glBindTexture(GL.GL_TEXTURE_2D, (int) m);
+ gl.glDrawArrays(GL2.GL_QUADS, 0, arrays.get(m).getElementCount());
+ arrays.get(m).enableBuffer(gl, false);
+ }
+ /*
+ * gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);
+ * gl.glVertexPointer(3, GL2.GL_FLOAT, 10, buffer);
+ * gl.glDrawArrays(GL2.GL_QUADS, 0, vertexCount);
+ * gl.glDisableClientState(GL2.GL_VERTEX_ARRAY);
+ */
+
+ } else {
+ if (useDisplayList) {
+ if (DL == null) {
+ DL = new DisplayList(glx);
+ } else {
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST_MIPMAP_NEAREST);
+ DL.render();
+ return;
+ }
+ DL.begin();
+ }
+ gl.glPushAttrib(GL2.GL_ENABLE_BIT | GL2.GL_POLYGON_BIT | GL2.GL_TEXTURE_BIT);
+ if (useTexture) {
+ gl.glEnable(GL.GL_TEXTURE_2D);
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST_MIPMAP_NEAREST);
+ }
+ for (int quadI = 0; quadI < vertexCount / 4; quadI++) {
+ ptr = (quadI * 4 + 0) * vertexSize;
+ if (useTexture) {
+ gl.glBindTexture(GL.GL_TEXTURE_2D, (int) buffer.get(ptr + 9));
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST_MIPMAP_NEAREST);
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT);
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT);
+ // gl.glDisable(GL.GL_BLEND);
+ // gl.glTexParameterf(GL.GL_TEXTURE_2D,
+ // GL.GL_TEXTURE_MAX_ANISOTROPY_EXT, 0);
+ }
+ if (useQuad) {
+ gl.glBegin(GL2.GL_QUADS);
+ } else {
+ gl.glBegin(GL2.GL_TRIANGLE_STRIP);
+ }
+ {
+ for (int i = 0; i < 4; i++) {
+ int k = (useQuad) ? i : ((i == 2) ? 3 : (i == 3 ? 2 : i));
+ ptr = (quadI * 4 + k) * vertexSize;
+ if (useColor) {
+ gl.glColor4f(buffer.get(ptr + 3), buffer.get(ptr + 4), buffer.get(ptr + 5),
+ buffer.get(ptr + 6));
+ }
+ if (useTexture) {
+ float u = buffer.get(ptr + 7);
+ float v = buffer.get(ptr + 8);
+ gl.glTexCoord2f(u, v);
+ }
+ gl.glVertex3f(buffer.get(ptr), buffer.get(ptr + 1), buffer.get(ptr + 2));
+ }
+ }
+ gl.glEnd();
+ }
+ gl.glPopAttrib();
+ if (useDisplayList) {
+ DL.end();
+ DL.render();
+ }
+ }
+ }
+}
diff --git a/src/ru/olamedia/geom/Quad.java b/src/ru/olamedia/geom/Quad.java
new file mode 100644
index 0000000..e3d34dd
--- /dev/null
+++ b/src/ru/olamedia/geom/Quad.java
@@ -0,0 +1,12 @@
+package ru.olamedia.geom;
+
+public class Quad {
+ private float[] vertices;
+ private int vertexCount;
+
+ public void addVertex(float x, float y, float z) {
+ vertices[vertexCount] = x;
+ vertices[vertexCount + 1] = y;
+ vertices[vertexCount + 2] = z;
+ }
+}
diff --git a/src/ru/olamedia/geom/SimpleQuadMesh.java b/src/ru/olamedia/geom/SimpleQuadMesh.java
new file mode 100644
index 0000000..42cf439
--- /dev/null
+++ b/src/ru/olamedia/geom/SimpleQuadMesh.java
@@ -0,0 +1,113 @@
+package ru.olamedia.geom;
+
+public class SimpleQuadMesh extends Mesh {
+
+ public SimpleQuadMesh(int size) {
+ super(size * 4);
+ }
+
+ private void addBottomLeftBackVertex() {
+ setPoint3f(-0.5f, -0.5f, -0.5f);
+ }
+
+ private void addBottomLeftFrontVertex() {
+ setPoint3f(-0.5f, -0.5f, 0.5f);
+ }
+
+ private void addBottomRightBackVertex() {
+ setPoint3f(0.5f, -0.5f, -0.5f);
+ }
+
+ private void addBottomRightFrontVertex() {
+ setPoint3f(0.5f, -0.5f, 0.5f);
+ }
+
+ private void addTopLeftBackVertex() {
+ setPoint3f(-0.5f, 0.5f, -0.5f);
+ }
+
+ private void addTopLeftFrontVertex() {
+ setPoint3f(-0.5f, 0.5f, 0.5f);
+ }
+
+ private void addTopRightBackVertex() {
+ setPoint3f(0.5f, 0.5f, -0.5f);
+ }
+
+ private void addTopRightFrontVertex() {
+ setPoint3f(0.5f, 0.5f, 0.5f);
+ }
+
+ public void addFrontQuad() {
+ // triangle strip: И
+ setUV(0, 1);
+ addTopLeftFrontVertex(); // top left
+ setUV(0, 0);
+ addBottomLeftFrontVertex(); // bottom left
+ setUV(1, 0);
+ addBottomRightFrontVertex(); // bottom right
+ setUV(1, 1);
+ addTopRightFrontVertex(); // top right
+ }
+
+ public void addBackQuad() {
+ // triangle strip: И
+ setUV(0, 1);
+ addTopRightBackVertex();
+ setUV(0, 0);
+ addBottomRightBackVertex();
+ setUV(1, 0);
+ addBottomLeftBackVertex();
+ setUV(1, 1);
+ addTopLeftBackVertex();
+ }
+
+ public void addLeftQuad() {
+ // triangle strip: И
+ setUV(0, 1);
+ addTopLeftBackVertex();
+ setUV(0, 0);
+ addBottomLeftBackVertex();
+ setUV(1, 0);
+ addBottomLeftFrontVertex();
+ setUV(1, 1);
+ addTopLeftFrontVertex();
+ }
+
+ public void addRightQuad() {
+ // triangle strip: И
+ setUV(0, 1);
+ addTopRightFrontVertex();
+ setUV(0, 0);
+ addBottomRightFrontVertex();
+ setUV(1, 0);
+ addBottomRightBackVertex();
+ setUV(1, 1);
+ addTopRightBackVertex();
+ }
+
+ public void addTopQuad() {
+ // triangle strip: И
+ setUV(0, 0);
+ addTopLeftBackVertex();
+ setUV(0, 1);
+ addTopLeftFrontVertex();
+ setUV(1, 1);
+ addTopRightFrontVertex();
+ setUV(1, 0);
+ addTopRightBackVertex();
+ }
+
+ public void addBottomQuad() {
+ // triangle strip: И
+ setUV(0, 0);
+ addBottomLeftFrontVertex();
+ setUV(0, 1);
+ addBottomLeftBackVertex();
+ setUV(1, 1);
+ addBottomRightBackVertex();
+ setUV(1, 0);
+ addBottomRightFrontVertex();
+ }
+
+}
diff --git a/src/ru/olamedia/geom/package-info.java b/src/ru/olamedia/geom/package-info.java
new file mode 100644
index 0000000..97fe3c5
--- /dev/null
+++ b/src/ru/olamedia/geom/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.geom; \ No newline at end of file
diff --git a/src/ru/olamedia/input/AWTRobotUtil.java b/src/ru/olamedia/input/AWTRobotUtil.java
new file mode 100644
index 0000000..9c6778c
--- /dev/null
+++ b/src/ru/olamedia/input/AWTRobotUtil.java
@@ -0,0 +1,97 @@
+package ru.olamedia.input;
+
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``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 JogAmp Community 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.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+import java.lang.reflect.InvocationTargetException;
+import java.awt.AWTException;
+import java.awt.Component;
+import java.awt.Point;
+import java.awt.Robot;
+
+public class AWTRobotUtil {
+
+ private static final int ROBOT_DELAY = 100; // ms
+
+ public static Point getCenterLocation(Object obj, boolean onTitleBarIfWindow) throws InterruptedException,
+ InvocationTargetException {
+ Component comp = null;
+ com.jogamp.newt.Window win = null;
+
+ if (obj instanceof com.jogamp.newt.Window) {
+ win = (com.jogamp.newt.Window) obj;
+ } else if (obj instanceof Component) {
+ comp = (Component) obj;
+ } else {
+ throw new RuntimeException("Neither AWT nor NEWT: " + obj);
+ }
+
+ int x0, y0;
+ if (null != comp) {
+ java.awt.Point p0 = comp.getLocationOnScreen();
+ java.awt.Rectangle r0 = comp.getBounds();
+ if (onTitleBarIfWindow && comp instanceof java.awt.Window) {
+ java.awt.Window window = (java.awt.Window) comp;
+ java.awt.Insets insets = window.getInsets();
+ y0 = (int) (p0.getY() + insets.top / 2.0 + .5);
+ } else {
+ y0 = (int) (p0.getY() + r0.getHeight() / 2.0 + .5);
+ }
+ x0 = (int) (p0.getX() + r0.getWidth() / 2.0 + .5);
+ } else {
+ javax.media.nativewindow.util.Point p0 = win.getLocationOnScreen(null);
+ if (onTitleBarIfWindow) {
+ javax.media.nativewindow.util.InsetsImmutable insets = win.getInsets();
+ p0.translate(win.getWidth() / 2, insets.getTopHeight() / 2);
+ } else {
+ javax.media.nativewindow.util.InsetsImmutable insets = win.getInsets();
+ p0.translate(win.getWidth() / 2, (win.getHeight() - insets.getTopHeight()) / 2);
+ }
+ x0 = p0.getX();
+ y0 = p0.getY();
+ }
+
+ return new Point(x0, y0);
+ }
+
+ /**
+ * centerMouse
+ */
+ public static Point centerMouse(Robot robot, Object obj, boolean onTitleBarIfWindow) throws AWTException,
+ InterruptedException, InvocationTargetException {
+
+ Point p0 = getCenterLocation(obj, onTitleBarIfWindow);
+ // System.err.println("centerMouse: robot pos: " + p0 +
+ // ", onTitleBarIfWindow: " + onTitleBarIfWindow);
+
+ robot.mouseMove((int) p0.getX(), (int) p0.getY());
+ // robot.delay(ROBOT_DELAY);
+ return p0;
+ }
+
+}
diff --git a/src/ru/olamedia/input/KeyListener.java b/src/ru/olamedia/input/KeyListener.java
new file mode 100644
index 0000000..8fb5d49
--- /dev/null
+++ b/src/ru/olamedia/input/KeyListener.java
@@ -0,0 +1,10 @@
+package ru.olamedia.input;
+
+import com.jogamp.newt.event.KeyEvent;
+
+public interface KeyListener {
+ public void onKeyPressed(String name, KeyEvent e);
+
+ public void onKeyReleased(String name, KeyEvent e);
+
+}
diff --git a/src/ru/olamedia/input/Keyboard.java b/src/ru/olamedia/input/Keyboard.java
new file mode 100644
index 0000000..6a9ecbd
--- /dev/null
+++ b/src/ru/olamedia/input/Keyboard.java
@@ -0,0 +1,64 @@
+package ru.olamedia.input;
+
+import java.awt.event.KeyEvent;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.collections.BidiMap;
+import org.apache.commons.collections.bidimap.DualHashBidiMap;
+
+public class Keyboard implements com.jogamp.newt.event.KeyListener {
+ public static Keyboard instance = new Keyboard();
+ private static boolean[] downState = new boolean[256];
+ private static BidiMap names = new DualHashBidiMap();
+
+ public static void setName(String name, int keyCode) {
+ names.put(name, keyCode);
+ }
+
+ public static boolean isKeyDown(int keyCode) {
+ return downState[keyCode];
+ }
+
+ public static boolean isKeyDown(String name) {
+ if (names.containsKey(name)) {
+ return downState[((Integer) names.get(name)).intValue()];
+ }
+ return false;
+ }
+
+ private static List<ru.olamedia.input.KeyListener> listeners = new ArrayList<ru.olamedia.input.KeyListener>();
+
+ public static void attach(ru.olamedia.input.KeyListener l) {
+ listeners.add(l);
+ }
+
+ @Override
+ public void keyPressed(com.jogamp.newt.event.KeyEvent e) {
+ downState[e.getKeyCode()] = true;
+ if (names.containsValue(e.getKeyCode())) {
+ String name = (String) names.getKey(e.getKeyCode());
+ for (ru.olamedia.input.KeyListener l : listeners) {
+ l.onKeyPressed(name, e);
+ }
+ }
+ }
+
+ @Override
+ public void keyReleased(com.jogamp.newt.event.KeyEvent e) {
+ downState[e.getKeyCode()] = false;
+ if (names.containsValue(e.getKeyCode())) {
+ String name = (String) names.getKey(e.getKeyCode());
+ for (ru.olamedia.input.KeyListener l : listeners) {
+ l.onKeyReleased(name, e);
+ }
+ }
+ }
+
+ @Override
+ public void keyTyped(com.jogamp.newt.event.KeyEvent arg0) {
+ // TODO Auto-generated method stub
+
+ }
+}
diff --git a/src/ru/olamedia/input/MouseJail.java b/src/ru/olamedia/input/MouseJail.java
new file mode 100644
index 0000000..bd12b0a
--- /dev/null
+++ b/src/ru/olamedia/input/MouseJail.java
@@ -0,0 +1,113 @@
+package ru.olamedia.input;
+
+import java.awt.AWTException;
+import java.awt.Point;
+import java.awt.Robot;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.jogamp.newt.event.MouseAdapter;
+import com.jogamp.newt.event.MouseEvent;
+
+import ru.olamedia.game.GameFrame;
+
+public class MouseJail extends MouseAdapter {
+ public static MouseJail instance = new MouseJail();
+
+ public MouseJail() {
+ }
+
+ private static boolean isActive = false;
+
+ /**
+ * @return the isActive
+ */
+ public static boolean isActive() {
+ return isActive;
+ }
+
+ /**
+ * @param isActive
+ * the isActive to set
+ */
+ public static void setActive(boolean isActive) {
+ System.out.println("Mouse jail " + (isActive ? "active" : "not active"));
+ MouseJail.isActive = isActive;
+ GameFrame.confinePointer(isActive);
+ GameFrame.setPointerVisible(!isActive);
+ }
+
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ if (e.isAltDown()) {
+ setActive(false);
+ } else {
+ setActive(true);
+ }
+ for (ru.olamedia.input.MouseListener l : listeners) {
+ l.onMouseClick();
+ }
+ }
+
+ @Override
+ public void mouseEntered(MouseEvent e) {
+ System.out.println("Entered");
+
+ }
+
+ @Override
+ public void mouseExited(MouseEvent e) {
+ System.out.println("Exited");
+ isActive = false;
+ if (isActive) {
+ //moveToCenter();
+ }
+ }
+
+ @Override
+ public void mousePressed(MouseEvent e) {
+
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent e) {
+
+ }
+
+ @Override
+ public void mouseDragged(MouseEvent e) {
+ onMove(e);
+ }
+
+ private float sensitivity = 2f;
+
+ private void onMove(MouseEvent e) {
+ if (isActive) {
+ int cx = GameFrame.getWidth() / 2;
+ int cy = GameFrame.getHeight() / 2;
+ float dx = e.getX() - cx;
+ float dy = e.getY() - cy;
+ dx *= sensitivity / 10;
+ dy *= sensitivity / 10;
+ // System.out.println("Mouse moved " + " dx:" + dx + " dy:" + dy
+ // + " x:" + e.getX() + " y:" + e.getY());
+ for (ru.olamedia.input.MouseListener l : listeners) {
+ l.onMouseMove(dx, dy);
+ }
+ GameFrame.getWindow().warpPointer(cx, cy);
+ }
+ }
+
+ @Override
+ public void mouseMoved(MouseEvent e) {
+ onMove(e);
+ }
+
+ private static List<ru.olamedia.input.MouseListener> listeners = new ArrayList<ru.olamedia.input.MouseListener>();
+
+ public static void attach(ru.olamedia.input.MouseListener l) {
+ listeners.add(l);
+ }
+
+}
diff --git a/src/ru/olamedia/input/MouseListener.java b/src/ru/olamedia/input/MouseListener.java
new file mode 100644
index 0000000..3d93d1d
--- /dev/null
+++ b/src/ru/olamedia/input/MouseListener.java
@@ -0,0 +1,6 @@
+package ru.olamedia.input;
+
+public interface MouseListener {
+ public void onMouseMove(float dx, float dy);
+ public void onMouseClick();
+}
diff --git a/src/ru/olamedia/input/package-info.java b/src/ru/olamedia/input/package-info.java
new file mode 100644
index 0000000..ad3f418
--- /dev/null
+++ b/src/ru/olamedia/input/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.input; \ No newline at end of file
diff --git a/src/ru/olamedia/liveEntity/LiveEntity.java b/src/ru/olamedia/liveEntity/LiveEntity.java
new file mode 100644
index 0000000..ce31108
--- /dev/null
+++ b/src/ru/olamedia/liveEntity/LiveEntity.java
@@ -0,0 +1,683 @@
+package ru.olamedia.liveEntity;
+
+import javax.vecmath.Vector3f;
+
+import com.jogamp.newt.event.KeyEvent;
+
+import ru.olamedia.camera.Cameraman;
+import ru.olamedia.olacraft.game.Game;
+import ru.olamedia.olacraft.inventory.Inventory;
+import ru.olamedia.olacraft.world.block.Block;
+import ru.olamedia.olacraft.world.blockStack.BlockStack;
+import ru.olamedia.olacraft.world.blockTypes.GravelBlockType;
+import ru.olamedia.input.Keyboard;
+
+public class LiveEntity implements Cameraman {
+ private Inventory inventory; // every living entity can have inventory
+ private float x;
+ private float y;
+ private float z;
+ public Vector3f velocity = new Vector3f(0, 0, 0);
+ public Vector3f acceleration = new Vector3f(0, 0, 0);
+
+ private float fov = 90f;
+ private float mouseSpeed = 1.0f;
+ private float maxLookUp = 80.0f;
+ private float maxLookDown = -80.0f;
+ private float maxHeight = 1.9f;
+ private float cameraLevel = 1.8f;
+
+ private float pitch = 0f;
+ private float yaw = 0f;
+ private float roll = 0f;
+
+ private float walkSpeed = 1.3f;// 1.3-1.5 m/s
+ private float runSpeed = 4.5f;// m/s
+
+ private boolean isWalking = false;
+ private boolean isRunning = false;
+ private boolean isSneaking = false;
+ private boolean isCrouching = false;
+ private boolean isViewBobbing = true;
+ private float bob = 0f;
+ private float hSpeed = runSpeed; // horizontal speed
+ private float vVelocity = 0f;
+
+ @SuppressWarnings("unused")
+ private float maxHealthPoints;
+ private float healthPoints;
+ public float qD = 0;
+ public float qInvD = 0;
+ public boolean inJump = false;
+ public boolean inFall = false;
+ public boolean onGround = false;
+ private float savedX;
+ private float savedY;
+ private float savedZ;
+ private int id;
+ private int connectionId;
+ private boolean isPositionChanged = false;
+
+ protected void generateInventory() {
+ // can be overriden for mobs
+ for (int i = 0; i <= 9; i++) {
+ inventory.binded[i] = new BlockStack(new Block(), (int) Math.random() * 64);
+ inventory.binded[i].block.setType(new GravelBlockType());
+ }
+ }
+
+ public Inventory getInventory() {
+ if (null == inventory) {
+ inventory = new Inventory();
+ generateInventory();
+ }
+ return inventory;
+ }
+
+ public float getHSpeed() {
+ return (hSpeed) * (isCrouching ? 0.4f : 1) * (isSneaking ? 0.5f : 1);
+ }
+
+ public float getHeight() {
+ return maxHeight * (isCrouching ? 0.5f : 1) * (isSneaking ? 0.8f : 1);
+ }
+
+ public float getMaxJumpHeight() {
+ // ~1.5 for 1.8
+ return (float) ((float) (maxHeight * 0.83)) * (isCrouching ? 0.8f : 1f);
+ }
+
+ /**
+ * Returns the vertical velocity needed to jump the specified height (based
+ * on current gravity). Uses the Math.sqrt() function.
+ */
+ public float getJumpVelocity(float jumpHeight) {
+ // use velocity/acceleration formal: v*v = -2 * a(y-y0)
+ // (v is jump velocity, a is accel, y-y0 is max height)
+ return (float) Math.sqrt(2 * Game.client.getWorldInfo().gravity * jumpHeight);
+ }
+
+ public float getCameraLevel() {
+ return getHeight() * 0.9f;
+ }
+
+ public boolean isEmptyUnderFoot() {
+ return isEmptyBlock(0, -1, 0);
+ }
+
+ /**
+ * @param delta
+ * the elapsed time since the last frame update in seconds
+ */
+ public void updateKeyboard(float delta) {
+ acceleration.x = 0;
+ acceleration.y = 0;
+ acceleration.z = 0;
+ boolean keyLeft = Keyboard.isKeyDown("playerStrafeLeft");
+ boolean keyRight = Keyboard.isKeyDown("playerStrafeRight");
+ boolean keyForward = Keyboard.isKeyDown("playerForward");
+ boolean keyBack = Keyboard.isKeyDown("playerBack");
+ boolean keyJump = Keyboard.isKeyDown("playerJump");
+ boolean keySneak = Keyboard.isKeyDown("playerSneak");
+ boolean keyCrouch = Keyboard.isKeyDown("playerCrouch");
+
+ if (keySneak) {
+ if (!isSneaking) {
+ isSneaking = true;
+ if (!applyPosition()) {
+ isSneaking = false;
+ }
+ }
+ } else {
+ if (isSneaking) {
+ isSneaking = false;
+ if (!applyPosition()) {
+ isSneaking = true;
+ }
+ }
+ }
+ if (keyCrouch) {
+ if (!isCrouching) {
+ isCrouching = true;
+ if (!applyPosition()) {
+ isCrouching = false;
+ }
+ }
+ } else {
+ if (isCrouching) {
+ isCrouching = false;
+ if (!applyPosition()) { // Test if we don't have a block over
+ // head
+ isCrouching = true;
+ }
+ }
+ }
+ isWalking = false;
+ if ((keyForward && !keyBack) || (keyBack && !keyForward)) {
+ Vector3f look = Game.instance.camera.getLook();
+ acceleration.x += look.x * (keyBack ? 1 : -1) * 1f;
+ acceleration.y += 0;
+ acceleration.z += look.z * (keyBack ? 1 : -1) * 1f;
+ }
+ if ((keyLeft && !keyRight) || (keyRight && !keyLeft)) {
+ Vector3f right = Game.instance.camera.getRight();
+ acceleration.x += right.x * (keyRight ? 1 : -1) * 1f;
+ acceleration.y += 0;
+ acceleration.z += right.z * (keyRight ? 1 : -1) * 1f;
+ }
+ // acceleration.normalize();
+ float normalSpeed = 4.5f;
+ acceleration.x *= normalSpeed;// running
+ acceleration.y *= normalSpeed;
+ acceleration.z *= normalSpeed;
+
+ // if (inJump) {
+ // float FPS = (float) (delta / 1);
+ // float accelY = Game.world.gravity;
+ // float dt = (float) (delta / 1); // in seconds
+ // vVelocity -= accelY * dt;
+ // y += vVelocity * dt;
+ // if (vVelocity < 0) {
+ // inFall = true;
+ // }
+ // if (vVelocity > 0) {
+ // if (!keyJump) {
+ // vVelocity = 0;
+ // }
+ // }
+ // if (!applyPosition()) {
+ // if (vVelocity > 0) {
+ // // roof
+ // vVelocity = 0;
+ // } else {
+ // y = underFoot().getY() + 1;
+ // vVelocity = 0;
+ // inJump = false;
+ // inFall = false;
+ // }
+ // }
+ //
+ // } else {
+ // if (!inFall) {
+ // if (inAir()) {
+ //
+ // inJump = true;
+ // inFall = true;
+ // }
+ // }
+ // }
+ if (!onGround && !inAir()) {
+ // LANDING
+ onGround = true;
+ inJump = false;
+ velocity.y = 0;
+ acceleration.y = 0;
+ y = getJumperBlock().getY() + 1;
+ }
+ if (onGround && velocity.length() > 0 && acceleration.length() > 0) {
+ // BEFORE NEW JUMP
+ // Check direction changed
+ float vy = velocity.y;
+ float ay = acceleration.y;
+ velocity.y = 0;
+ acceleration.y = 0;
+ float dAngle = velocity.angle(acceleration);
+ float speedLimit = 10;
+ if (dAngle > 0) {
+ // changing angle
+ Vector3f newDirection = new Vector3f(velocity);
+ newDirection.add(acceleration);
+ if (newDirection.length() > 0) {
+ newDirection.normalize();
+ newDirection.scale(velocity.length());
+ }
+ velocity.set(newDirection);
+ // check velocity
+ if (velocity.length() * Math.cos(dAngle) > speedLimit) {
+ float deltaSpeed = (float) (velocity.length() * Math.cos(dAngle) - speedLimit);
+ velocity.scale((1 / velocity.length()) * (velocity.length() - deltaSpeed * 0.7f));
+ // velocity.scale((float) (10 / velocity.length() *
+ // Math.cos(dAngle)));
+ // velocity.scale((float) (velocity.length()
+ // - (velocity.length() - (10 / velocity.length() *
+ // Math.cos(dAngle))) * 0.5f * delta));
+ }
+ } else {
+ if (velocity.length() > speedLimit) {
+ float deltaSpeed = (float) (velocity.length() - speedLimit);
+ velocity.scale((1 / velocity.length()) * (velocity.length() - deltaSpeed * 0.7f));
+ }
+ }
+ velocity.y = vy;
+ acceleration.y = ay;
+ }
+ if (onGround && keyJump) {
+ // JUMPING
+ inJump = true;
+ onGround = false;
+ velocity.y = getJumpVelocity(getMaxJumpHeight());
+ acceleration.y = velocity.y;
+ // vVelocity = getJumpVelocity(getMaxJumpHeight());
+ System.out.println("Max jump height " + getMaxJumpHeight());
+ System.out.println("Starting velocity " + velocity.y);
+ }
+
+ if (onGround && !inJump) {
+ if (velocity.length() > normalSpeed) {
+ velocity.scale(normalSpeed / velocity.length());
+ }
+ // APPLY FRICTION
+ // Vector3f friction = new Vector3f(velocity);
+ // friction.negate();
+ // friction.scale(friction.length());
+ // friction.scale(delta);
+ // velocity.scale((float) Math.exp(-0.2 * delta));
+ // acceleration.scale(friction.length());
+ }
+
+ if (velocity.length() > 0 && acceleration.length() > 0) {
+ qD = Math.abs(velocity.dot(acceleration)) / (velocity.length() * acceleration.length());
+ }
+
+ // Vector3f a = new Vector3f(acceleration);
+ // if (a.length() > 0) {
+ // a.normalize();
+ // }
+ //
+ // if (qD > 0) {
+ // qInvD = (float) Math.acos(qD);
+ // acceleration.scale(qInvD * 10f);
+ // }
+ // if (qD > 10) {
+ // if (velocity.length() > 0) {
+ // velocity.normalize();
+ // }
+ // velocity.scale(qD);
+ // }
+ // if (qd > 10) {
+ // qd = 10;
+ // }
+ // velocity.set(acceleration);
+ // if (velocity.length() > 1){
+ // velocity.scale(1 / velocity.length());
+ // }
+ // velocity.scale(qd);
+
+ if (!onGround || inAir()) { // 0_o
+ acceleration.y = -Game.client.getWorldInfo().gravity;
+ }
+
+ // float qangle = (float) Math.abs(Math.acos(qd));
+ // if (qangle > 180){
+ // acceleration.scale(10f);
+ // }else if (qangle > 90){
+ // acceleration.scale(5f);
+ // }else if (qangle > 45){
+ // acceleration.scale(2f);
+ // }
+
+ // Quake-like tricks here...
+ // Vector3f qa = new Vector3f(acceleration);
+ // if (qa.length() != 0) {
+ // qa.scale(1 / qa.length());
+ // float qd = acceleration.dot(velocity);
+ // float qangle = (float) Math.abs(Math.acos(qd));
+ // if (qangle > 180) {
+ // // fast stop
+ // velocity.x *= 0.5f;
+ // velocity.z *= 0.5f;
+ // }else{
+ //
+ // }
+ // if (qd > 14) {
+ // velocity.x *= 1 / qd;
+ // velocity.z *= 1 / qd;
+ // }
+ // }
+ if (onGround && (acceleration.length() == 0)) {
+ velocity.set(0f, 0f, 0f);
+ } else {
+ // acceleration.normalize();
+ // Vector3f a = new Vector3f(acceleration);
+ // a.scale(delta);
+
+ if (velocity.length() == 0) {
+ velocity.x = acceleration.x;
+ // velocity.y = acceleration.y;
+ velocity.z = acceleration.z;
+ } else {
+ velocity.x += acceleration.x * delta;
+ velocity.z += acceleration.z * delta;
+ velocity.y += acceleration.y * delta;
+ }
+
+ Vector3f move = new Vector3f(velocity);
+ move.scale(delta);
+ float dx = 0;
+ while (move.x != 0) {
+ if (move.x > 1) {
+ dx = 1;
+ move.x -= 1;
+ } else if (move.x < -1) {
+ dx = -1;
+ move.x += 1;
+ } else {
+ dx = move.x;
+ move.x = 0;
+ }
+ x += dx;
+ if (applyPosition()) {
+ isWalking = true;
+ } else {
+ // full stop
+ velocity.x = 0;
+ }
+ }
+ float dz = 0;
+ while (move.z != 0) {
+ if (move.z > 1) {
+ dz = 1;
+ move.z -= 1;
+ } else if (move.z < -1) {
+ dz = -1;
+ move.z += 1;
+ } else {
+ dz = move.z;
+ move.z = 0;
+ }
+ z += dz;
+ if (applyPosition()) {
+ isWalking = true;
+ } else {
+ // full stop
+ velocity.z = 0;
+ }
+ }
+ float dy = 0;
+ if (move.y != 0) {
+ while (move.y != 0) {
+ if (move.y > 1) {
+ dy = 1;
+ move.y -= 1;
+ } else if (move.y < -1) {
+ dy = -1;
+ move.y += 1;
+ } else {
+ dy = move.y;
+ move.y = 0;
+ }
+ y += dy;
+ if (applyPosition()) {
+ isWalking = true;
+ } else {
+ // full stop
+ velocity.y = 0;
+ }
+ }
+
+ }
+ }
+ }
+
+ private Block underFoot() {
+ return getBlock(0, -1, 0);
+ }
+
+ public boolean isEmptyBlock(int dx, int dy, int dz) {
+ return Game.client.getWorldProvider().isEmptyBlock((int) x + dx, (int) Math.ceil(y) + dy, (int) z + dz);
+ }
+
+ public boolean haveBlockUnder(int dy) {
+ return !isEmptyBlock(0, -dy, 0);
+ }
+
+ public boolean inAir() {
+ return !haveBlockUnder(1);
+ }
+
+ public boolean underJumpHeight() {
+ return haveBlockUnder(1) || haveBlockUnder(2);
+ }
+
+ public Block getJumperBlock() {
+ if (haveBlockUnder(1)) {
+ return getBlock(0, -1, 0);
+ }
+ if (haveBlockUnder(2)) {
+ return getBlock(0, -2, 0);
+ }
+ return null;
+ }
+
+ private Block getBlock(int dx, int dy, int dz) {
+ return Game.client.getWorldProvider().getBlock((int) x + dx, (int) Math.ceil(y) + dy, (int) z + dz);
+ }
+
+ public void backupPosition() {
+ savedX = x;
+ savedY = y;
+ savedZ = z;
+ }
+
+ public void restorePosition() {
+ x = savedX;
+ y = savedY;
+ z = savedZ;
+ }
+
+ public boolean hasValidPosition() {
+ Block foot = getBlock(0, 0, 0);
+ Block underFoot = getBlock(0, -1, 0);
+ Block head = getBlock(0, (int) getHeight(), 0);
+ if (!inJump) {
+ if (underFoot.isEmpty()) {
+ // In AIR while normal walking
+ if (isSneaking) {
+ // TODO Jumping while Sneaking fixes x,z while jumping
+ return false;
+ }
+ }
+ }
+ // Check if we're too near to the wall
+ float screenPlane = 0.2f;
+ float screenPlaneVertical = 0.4f;
+ Block[] headNeighbors = head.getNeighbors();
+ for (Block b : headNeighbors) {
+ if (b.isEmpty()) {
+ continue;
+ }
+ if (b.getX() != head.getX()) {
+ // LEFT or RIGHT
+ float testX = b.getX();
+ if (testX < head.getX()) {
+ // LEFT, fixing
+ testX = head.getX();
+ }
+ float minDistance = Math.abs(testX - getX());
+ if (minDistance < screenPlane) {
+ return false;
+ }
+ }
+ if (b.getY() > head.getY()) { // Upper block
+ float minDistance = Math.abs(b.getY() - getY() + this.getHeight());// player
+ // height
+ if (minDistance < screenPlaneVertical) {
+ return false;
+ }
+ }
+
+ if (b.getZ() != head.getZ()) {
+ // FRONT OR BACK
+ float testZ = b.getZ();
+ if (testZ < head.getZ()) {
+ // BACK, fixing
+ testZ = head.getZ();
+ }
+ float minDistance = Math.abs(testZ - getZ());
+ if (minDistance < screenPlane) {
+ return false;
+ }
+ }
+ }
+ return foot.isEmpty() && head.isEmpty();
+ }
+
+ public boolean applyPosition() {
+ isPositionChanged = false;
+ if (hasValidPosition()) {
+ backupPosition();
+ isPositionChanged = true;
+ return true;
+ }
+ restorePosition();
+ return false;
+ }
+
+ public void notifyLocationUpdate() {
+ // overriden at player class
+ }
+
+ public void fixPosition() {
+ float dx = x - savedX;
+ float dy = y - savedY;
+ float dz = z - savedZ;
+ restorePosition();
+ if (Math.abs(dx) < 1) { // in a block range
+ x += dx;
+ applyPosition();
+ }
+ if (Math.abs(dy) < 1) { // in a block range
+ y += dy;
+ applyPosition();
+ }
+ if (Math.abs(dz) < 1) { // in a block range
+ y += dz;
+ applyPosition();
+ }
+ }
+
+ @Override
+ public void update(float delta) {
+ isPositionChanged = false;
+ backupPosition();
+ onGround = false;
+ Block below = getBlock(0, -1, 0);
+ if (y == below.getY() + 1) {
+ onGround = true;
+ }
+ updateKeyboard(delta);
+ // Check if position is valid
+ // fixPosition();
+
+ if (y < -20) {
+ // spawnAt((int) x, (int) z);
+ }
+ pitch = Game.instance.camera.getPitch();
+ yaw = Game.instance.camera.getYaw();
+ // Game.camera.setRoll(roll);
+ // saveTrace();
+ // if (isWalking && onGround) {
+ // if (!stepsound.isPlaying()) {
+ // stepsound.playAsSoundEffect(1f, 0.4f, true);
+ // }
+ // } else {
+ // if (stepsound.isPlaying()) {
+ // stepsound.stop();
+ // }
+ // }
+ if (isPositionChanged) {
+ notifyLocationUpdate();
+ }
+ }
+
+ public void setLocation(float x, float y, float z) {
+ this.setX(x);
+ this.setY(y);
+ this.setZ(z);
+ }
+
+ public void say(String message) {
+
+ }
+
+ public void die() {
+ healthPoints = 0;
+ LiveEntityEvent e = new LiveEntityEvent(this);
+ e.setType(LiveEntityEvent.ON_DIE);
+ e.dispatch();
+ }
+
+ public void acceptDamage(float amount) {
+ healthPoints -= amount;
+ if (healthPoints < 0) {
+ die();
+ }
+ }
+
+ public float getX() {
+ return x;
+ }
+
+ public void setX(float x) {
+ this.x = x;
+ }
+
+ public float getY() {
+ return y;
+ }
+
+ public void setY(float y) {
+ this.y = y;
+ }
+
+ public float getZ() {
+ return z;
+ }
+
+ public void setZ(float z) {
+ this.z = z;
+ }
+
+ @Override
+ public float getCameraX() {
+ return x;
+ }
+
+ @Override
+ public float getCameraY() {
+ return y + getCameraLevel();
+ }
+
+ @Override
+ public float getCameraZ() {
+ return z;
+ }
+
+ @Override
+ public void captureControls() {
+ System.out.println("Player took controls");
+ Keyboard.setName("playerForward", KeyEvent.VK_W);
+ Keyboard.setName("playerBack", KeyEvent.VK_S);
+ Keyboard.setName("playerStrafeLeft", KeyEvent.VK_A);
+ Keyboard.setName("playerStrafeRight", KeyEvent.VK_D);
+ Keyboard.setName("playerJump", KeyEvent.VK_SPACE);
+ Keyboard.setName("playerSneak", KeyEvent.VK_SHIFT);
+ Keyboard.setName("playerCrouch", KeyEvent.VK_CONTROL);
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public int getConnectionId() {
+ return connectionId;
+ }
+
+ public void setConnectionId(int connectionId) {
+ this.connectionId = connectionId;
+ }
+}
diff --git a/src/ru/olamedia/liveEntity/LiveEntityEvent.java b/src/ru/olamedia/liveEntity/LiveEntityEvent.java
new file mode 100644
index 0000000..5c0ded5
--- /dev/null
+++ b/src/ru/olamedia/liveEntity/LiveEntityEvent.java
@@ -0,0 +1,31 @@
+package ru.olamedia.liveEntity;
+
+public class LiveEntityEvent {
+ public static int ON_DIE;
+ private Object source;
+ private int type;
+
+ public LiveEntityEvent(Object source) {
+ this.setSource(source);
+ }
+
+ public int getType() {
+ return type;
+ }
+
+ public void setType(int type) {
+ this.type = type;
+ }
+
+ public Object getSource() {
+ return source;
+ }
+
+ public void setSource(Object source) {
+ this.source = source;
+ }
+
+ public void dispatch() {
+ LiveEntityEventDispatcher.dispatch(this);
+ }
+}
diff --git a/src/ru/olamedia/liveEntity/LiveEntityEventDispatcher.java b/src/ru/olamedia/liveEntity/LiveEntityEventDispatcher.java
new file mode 100644
index 0000000..5d29ae1
--- /dev/null
+++ b/src/ru/olamedia/liveEntity/LiveEntityEventDispatcher.java
@@ -0,0 +1,7 @@
+package ru.olamedia.liveEntity;
+
+public class LiveEntityEventDispatcher {
+ public static void dispatch(LiveEntityEvent e){
+
+ }
+}
diff --git a/src/ru/olamedia/liveEntity/package-info.java b/src/ru/olamedia/liveEntity/package-info.java
new file mode 100644
index 0000000..9c27733
--- /dev/null
+++ b/src/ru/olamedia/liveEntity/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.liveEntity; \ No newline at end of file
diff --git a/src/ru/olamedia/math/Box.java b/src/ru/olamedia/math/Box.java
new file mode 100644
index 0000000..7b9d968
--- /dev/null
+++ b/src/ru/olamedia/math/Box.java
@@ -0,0 +1,74 @@
+package ru.olamedia.math;
+
+public class Box {
+ private Vector3f low = new Vector3f();
+ private Vector3f high = new Vector3f();
+
+ /**
+ * @param x
+ * left
+ * @param y
+ * lower
+ * @param z
+ * back
+ * @param x2
+ * right
+ * @param y2
+ * higher
+ * @param z2
+ * front
+ */
+ public Box(float x, float y, float z, float x2, float y2, float z2) {
+ low.x = x;
+ low.y = y;
+ low.z = z;
+ high.x = x2;
+ high.y = y2;
+ high.z = z2;
+ }
+
+ public Vector3f getVertex(int i) {
+ Vector3f vertex = new Vector3f(low);
+ if (i > 3) {
+ // 4, 5, 6, 7
+ vertex.z = high.z;
+ }
+ if (i % 4 > 1) {
+ // 0 1 2 3 4 5 6 7
+ // 0 1 2 3 0 1 2 3
+ // - - + + - - + +
+ vertex.y = high.y;
+ }
+ if (i % 2 > 0) {
+ // 0 1 2 3 4 5 6 7
+ // 0 1 0 1 0 1 0 1
+ // - + - + - + - +
+ vertex.x = high.x;
+ }
+ return vertex;
+ }
+
+ public float getLowerX() {
+ return low.x;
+ }
+
+ public float getLowerY() {
+ return low.y;
+ }
+
+ public float getLowerZ() {
+ return low.z;
+ }
+
+ public float getUpperX() {
+ return high.x;
+ }
+
+ public float getUpperY() {
+ return high.y;
+ }
+
+ public float getUpperZ() {
+ return high.z;
+ }
+}
diff --git a/src/ru/olamedia/math/Classifier.java b/src/ru/olamedia/math/Classifier.java
new file mode 100644
index 0000000..551bcf6
--- /dev/null
+++ b/src/ru/olamedia/math/Classifier.java
@@ -0,0 +1,8 @@
+package ru.olamedia.math;
+
+public class Classifier {
+ // INSIDE > INTERSECT > OUTSIDE
+ public static int OUTSIDE = 0;
+ public static int INTERSECT = 1;
+ public static int INSIDE = 2;
+}
diff --git a/src/ru/olamedia/math/Frustum.java b/src/ru/olamedia/math/Frustum.java
new file mode 100644
index 0000000..e127cc0
--- /dev/null
+++ b/src/ru/olamedia/math/Frustum.java
@@ -0,0 +1,127 @@
+package ru.olamedia.math;
+
+public class Frustum {
+ public Plane topPlane = new Plane();
+ public Plane bottomPlane = new Plane();
+ public Plane leftPlane = new Plane();
+ public Plane rightPlane = new Plane();
+ public Plane nearPlane = new Plane();
+ public Plane farPlane = new Plane();
+ private Plane[] planes = getPlanes();
+
+ private Plane[] getPlanes() {
+ return new Plane[] { leftPlane, rightPlane, topPlane, bottomPlane };// ,
+ // topPlane,,
+ // topPlane
+ // bottomPlane,
+ // leftPlane,
+ // rightPlane, farPlane };
+ }
+
+ public Vector3f[] getVertices() {
+ Vector3f[] v = new Vector3f[8];
+ v[0] = topPlane.cross(leftPlane, nearPlane);
+ v[1] = topPlane.cross(leftPlane, farPlane);
+ v[2] = topPlane.cross(rightPlane, nearPlane);
+ v[3] = topPlane.cross(rightPlane, farPlane);
+ v[4] = bottomPlane.cross(leftPlane, nearPlane);
+ v[5] = bottomPlane.cross(leftPlane, farPlane);
+ v[6] = bottomPlane.cross(rightPlane, nearPlane);
+ v[7] = bottomPlane.cross(rightPlane, farPlane);
+ return v;
+ }
+
+ public int test(Box b) {
+ return quickClassify(b);
+ // int out, in = 0, result;
+ // result = Classifier.INSIDE;
+ // int pc = 5;
+ // for (int i = 0; i < 5; i++) {
+ // Plane plane = planes[i];
+ // out = 0;
+ // in = 0;
+ // for (int k = 0; k < 8 && (in == 0 || out == 0); k++) {
+ // if (plane.distance(b.getVertex(k)) > 0) {
+ // out++;
+ // } else {
+ // in++;
+ // }
+ // }
+ // if (out == 8) {
+ // System.out.println(i);
+ // return Classifier.OUTSIDE;
+ // }
+ // }
+ // if (in < pc) {
+ // result = Classifier.INTERSECT;
+ // }
+ // // for (int i = 0; i < 6; i++) {
+ // // for (int k = 0; k < 8 && (in == 0 || out == 0); k++) {
+ // // if (planes[i].distance(b.getVertex(k)) < 0) {
+ // // out++;
+ // // } else {
+ // // in++;
+ // // }
+ // // }
+ // // }
+ // // if (in < 1) {
+ // // return Classifier.OUTSIDE;
+ // // } else if (out > 0) {
+ // // result = Classifier.INTERSECT;
+ // // }
+ // return result;
+ }
+
+ private static final boolean isPointInside(Plane plane, Vector3f p) {
+ return (plane.distance(p) <= 0.0f);
+ }
+
+ @SuppressWarnings("unused")
+ private final boolean isPointInside(Vector3f p) {
+ return isPointInside(topPlane, p) && isPointInside(bottomPlane, p) && isPointInside(leftPlane, p)
+ && isPointInside(rightPlane, p) && isPointInside(nearPlane, p);
+ }
+
+ /**
+ * Quick check to see if an orthogonal bounding box is inside the frustum
+ */
+ public final int quickClassify(Box box) {
+ // If all vertices is outside of at least one of planes
+ for (Plane p : planes) {
+ int in = 0;
+ @SuppressWarnings("unused")
+ int out = 0;
+ for (int i = 0; i < 8; i++) {
+ Vector3f v = box.getVertex(i);
+ if (p.distance(v) > 0.0f) {
+ out++;
+ } else {
+ in++;
+ }
+ }
+ if (in < 1) {
+ return (Classifier.OUTSIDE);
+ }
+ }
+
+ return (Classifier.INTERSECT);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return "Frustum[\r\n" + //
+ "Top " + topPlane + "\r\n" + //
+ "Bottom " + bottomPlane + "\r\n" + //
+ "Left " + leftPlane + "\r\n" + //
+ "Right " + rightPlane + "\r\n" + //
+ "Near " + nearPlane + "\r\n" + //
+ "Far " + farPlane + "\r\n" + //
+ "]";
+ }
+
+}
diff --git a/src/ru/olamedia/math/FrustumUtil.java b/src/ru/olamedia/math/FrustumUtil.java
new file mode 100644
index 0000000..80b01fb
--- /dev/null
+++ b/src/ru/olamedia/math/FrustumUtil.java
@@ -0,0 +1,72 @@
+package ru.olamedia.math;
+
+public class FrustumUtil {
+ public static Plane[] extractPlanes(javax.vecmath.Matrix4f m, boolean normalize) {
+
+ Plane[] planes = new Plane[6];
+ for (int j = 0; j < 6; j++) {
+ planes[j] = new Plane();
+ }
+ // Left: [30+00, 31+01, 32+02, 33+03]
+
+ planes[0].n.x = m.m30 + m.m00;
+ planes[0].n.y = m.m31 + m.m01;
+ planes[0].n.z = m.m32 + m.m02;
+ planes[0].d = m.m33 + m.m03;
+
+ // Right: [30-00, 31-01, 32-02, 33-03]
+
+ planes[1].n.x = m.m30 - m.m00;
+ planes[1].n.y = m.m31 - m.m01;
+ planes[1].n.z = m.m32 - m.m02;
+ planes[1].d = m.m33 - m.m03;
+
+ // Bottom: [30+10, 31+11, 32+12, 33+13]
+
+ planes[2].n.x = m.m30 + m.m10;
+ planes[2].n.y = m.m31 + m.m11;
+ planes[2].n.z = m.m32 + m.m12;
+ planes[2].d = m.m33 + m.m13;
+
+ // Top: [30-10, 31-11, 32-12, 33-13]
+
+ planes[3].n.x = m.m30 - m.m10;
+ planes[3].n.y = m.m31 - m.m11;
+ planes[3].n.z = m.m32 - m.m12;
+ planes[3].d = m.m33 - m.m13;
+
+ // Near: [30+20, 31+21, 32+22, 33+23]
+
+ planes[4].n.x = m.m30 + m.m20;
+ planes[4].n.y = m.m31 + m.m21;
+ planes[4].n.z = m.m32 + m.m22;
+ planes[4].d = m.m33 + m.m23;
+
+ // Far: [30-20, 31-21, 32-22, 33-23]
+
+ planes[5].n.x = m.m30 - m.m20;
+ planes[5].n.y = m.m31 - m.m21;
+ planes[5].n.z = m.m32 - m.m22;
+ planes[5].d = m.m33 - m.m23;
+
+ // Normalize
+ if (normalize) {
+ for (int i = 0; i < 6; ++i) {
+ planes[i].normalize();
+ }
+ }
+ return planes;
+ }
+
+ public static Frustum extractFrustum(javax.vecmath.Matrix4f m) {
+ Frustum f = new Frustum();
+ Plane[] planes = extractPlanes(m, true);
+ f.leftPlane.set(planes[0]);
+ f.rightPlane.set(planes[1]);
+ f.bottomPlane.set(planes[2]);
+ f.topPlane.set(planes[3]);
+ f.nearPlane.set(planes[4]);
+ f.farPlane.set(planes[5]);
+ return f;
+ }
+}
diff --git a/src/ru/olamedia/math/Halfspace.java b/src/ru/olamedia/math/Halfspace.java
new file mode 100644
index 0000000..64834df
--- /dev/null
+++ b/src/ru/olamedia/math/Halfspace.java
@@ -0,0 +1,7 @@
+package ru.olamedia.math;
+
+public class Halfspace {
+ public static int NEGATIVE = -1;
+ public static int ON_PLANE = 0;
+ public static int POSITIVE = 1;
+}
diff --git a/src/ru/olamedia/math/Matrix4f.java b/src/ru/olamedia/math/Matrix4f.java
new file mode 100644
index 0000000..1ce2eb6
--- /dev/null
+++ b/src/ru/olamedia/math/Matrix4f.java
@@ -0,0 +1,191 @@
+package ru.olamedia.math;
+
+import static org.openmali.FastMath.*;
+
+// 4x4 float matrix, column-major notation
+public class Matrix4f {
+ protected float[] m;
+
+ public Matrix4f() {
+ m = new float[16];
+ }
+
+ public Matrix4f(float[] m) {
+ this.m = m;
+ }
+
+ public Matrix4f(javax.vecmath.Matrix4f m2) {
+ m = new float[16];
+ m[0] = m2.m00;
+ m[1] = m2.m10;
+ m[2] = m2.m20;
+ m[3] = m2.m30;
+ m[4] = m2.m01;
+ m[5] = m2.m11;
+ m[6] = m2.m21;
+ m[7] = m2.m31;
+ m[8] = m2.m02;
+ m[9] = m2.m12;
+ m[10] = m2.m22;
+ m[11] = m2.m32;
+ m[12] = m2.m03;
+ m[13] = m2.m13;
+ m[14] = m2.m23;
+ m[15] = m2.m33;
+ }
+
+ public float[] toFloatArray() {
+ return m;
+ }
+
+ public void set(int i, float v) {
+ m[i] = v;
+ }
+
+ public float get(int i) {
+ return m[i];
+ }
+
+ public void loadIdentity() {
+ setIdentity();
+ }
+
+ public void setIdentity() {
+ m[0] = m[5] = m[10] = m[15] = 1.0f;
+ m[1] = m[2] = m[3] = m[4] = 0.0f;
+ m[6] = m[7] = m[8] = m[9] = 0.0f;
+ m[11] = m[12] = m[13] = m[14] = 0.0f;
+ }
+
+ public static Matrix4f translateMatrix(float x, float y, float z) {
+ Matrix4f m = new Matrix4f();
+ m.setIdentity();
+ // Translate slots.
+ m.set(12, x);
+ m.set(13, y);
+ m.set(14, z);
+ return m;
+ }
+
+ public static Matrix4f scaleMatrix(float sx, float sy, float sz) {
+ Matrix4f m = new Matrix4f();
+ m.setIdentity();
+ // Scale slots.
+ m.set(0, sx);
+ m.set(5, sy);
+ m.set(10, sz);
+ return m;
+ }
+
+ public static Matrix4f rotateXMatrix(float degrees) {
+ float radians = toRad(degrees);
+ float c = cos(radians);
+ float s = sin(radians);
+ Matrix4f m = new Matrix4f();
+ m.setIdentity();
+ // Rotate X formula.
+ m.set(5, c);
+ m.set(6, -s);
+ m.set(9, s);
+ m.set(10, c);
+ return m;
+ }
+
+ public static Matrix4f rotateYMatrix(float degrees) {
+ float radians = toRad(degrees);
+ float c = cos(radians);
+ float s = sin(radians);
+ Matrix4f m = new Matrix4f();
+ m.setIdentity();
+ // Rotate Y formula.
+ m.set(0, c);
+ m.set(2, s);
+ m.set(8, -s);
+ m.set(10, c);
+ return m;
+ }
+
+ public static Matrix4f rotateZMatrix(float degrees) {
+ float radians = toRad(degrees);
+ float c = cos(radians);
+ float s = sin(radians);
+ Matrix4f m = new Matrix4f();
+ m.setIdentity();
+ // Rotate Z formula.
+ m.set(0, c);
+ m.set(1, s);
+ m.set(4, -s);
+ m.set(5, c);
+ return m;
+ }
+
+ public Vector3f getUpVector() {
+ return new Vector3f(m[1], m[5], m[9]);
+ }
+
+ public Vector3f getLookVector() { // POSITIVE_Z
+ return new Vector3f(m[2], m[6], m[10]);
+ }
+
+ public Vector3f getRightVector() {
+ return new Vector3f(m[0], m[4], m[8]);
+ }
+
+ public Matrix4f multiply(Matrix4f m) {
+ return Matrix4fUtil.multiply(this, m);
+ }
+
+ public void apply(Matrix4f m) {
+ this.m = multiply(m).toFloatArray();
+ }
+
+ public float[] getAngles() {
+ // TODO check majority
+ float ax, ay, az;
+ float cy;
+ ay = -asin(m[2]); /* Calculate Y-axis angle */
+ cy = cos(ay);
+ ay = toDeg(ay);
+ float trX, trY;
+
+ if (Math.abs(cy) > 0.005) /* Gimball lock? */
+ {
+ trX = m[10] / cy; /* No, so get X-axis angle */
+ trY = -m[6] / cy;
+
+ ax = toDeg(atan2(trY, trX));
+
+ trX = m[0] / cy; /* Get Z-axis angle */
+ trY = -m[1] / cy;
+
+ az = toDeg(atan2(trY, trX));
+ } else /* Gimball lock has occurred */
+ {
+ ax = 0; /* Set X-axis angle to zero */
+
+ trX = m[5]; /* And calculate Z-axis angle */
+ trY = m[4];
+
+ az = toDeg(atan2(trY, trX));
+ }
+
+ ax = clamp(ax, 0, 360); /* Clamp all angles to range */
+ ay = clamp(ay, 0, 360);
+ az = clamp(az, 0, 360);
+ return new float[] { ax, ay, ax };
+ }
+
+ private float clamp(float a, float min, float max) {
+ a = a % max;
+ return a;
+ }
+
+ public float c(int column, int row) {
+ // COLUMN-BASED
+ return m[column * 4 + row];
+ }
+
+ public void set(float[] m) {
+ this.m = m;
+ }
+}
diff --git a/src/ru/olamedia/math/Matrix4fUtil.java b/src/ru/olamedia/math/Matrix4fUtil.java
new file mode 100644
index 0000000..46d153e
--- /dev/null
+++ b/src/ru/olamedia/math/Matrix4fUtil.java
@@ -0,0 +1,36 @@
+package ru.olamedia.math;
+
+public class Matrix4fUtil {
+ public static Matrix4f multiply(Matrix4f m1, Matrix4f m2) {
+ return new Matrix4f(multiply(m1.toFloatArray(), m2.toFloatArray()));
+ }
+
+ // MATRIX MULTIPLICATION
+ public static float[] multiply(float[] m1, float[] m2) {
+ float[] result = new float[16];
+ // First Column
+ result[0] = m1[0] * m2[0] + m1[4] * m2[1] + m1[8] * m2[2] + m1[12] * m2[3];
+ result[1] = m1[1] * m2[0] + m1[5] * m2[1] + m1[9] * m2[2] + m1[13] * m2[3];
+ result[2] = m1[2] * m2[0] + m1[6] * m2[1] + m1[10] * m2[2] + m1[14] * m2[3];
+ result[3] = m1[3] * m2[0] + m1[7] * m2[1] + m1[11] * m2[2] + m1[15] * m2[3];
+
+ // Second Column
+ result[4] = m1[0] * m2[4] + m1[4] * m2[5] + m1[8] * m2[6] + m1[12] * m2[7];
+ result[5] = m1[1] * m2[4] + m1[5] * m2[5] + m1[9] * m2[6] + m1[13] * m2[7];
+ result[6] = m1[2] * m2[4] + m1[6] * m2[5] + m1[10] * m2[6] + m1[14] * m2[7];
+ result[7] = m1[3] * m2[4] + m1[7] * m2[5] + m1[11] * m2[6] + m1[15] * m2[7];
+
+ // Third Column
+ result[8] = m1[0] * m2[8] + m1[4] * m2[9] + m1[8] * m2[10] + m1[12] * m2[11];
+ result[9] = m1[1] * m2[8] + m1[5] * m2[9] + m1[9] * m2[10] + m1[13] * m2[11];
+ result[10] = m1[2] * m2[8] + m1[6] * m2[9] + m1[10] * m2[10] + m1[14] * m2[11];
+ result[11] = m1[3] * m2[8] + m1[7] * m2[9] + m1[11] * m2[10] + m1[15] * m2[11];
+
+ // Fourth Column
+ result[12] = m1[0] * m2[12] + m1[4] * m2[13] + m1[8] * m2[14] + m1[12] * m2[15];
+ result[13] = m1[1] * m2[12] + m1[5] * m2[13] + m1[9] * m2[14] + m1[13] * m2[15];
+ result[14] = m1[2] * m2[12] + m1[6] * m2[13] + m1[10] * m2[14] + m1[14] * m2[15];
+ result[15] = m1[3] * m2[12] + m1[7] * m2[13] + m1[11] * m2[14] + m1[15] * m2[15];
+ return result;
+ }
+}
diff --git a/src/ru/olamedia/math/Plane.java b/src/ru/olamedia/math/Plane.java
new file mode 100644
index 0000000..d5cd9d0
--- /dev/null
+++ b/src/ru/olamedia/math/Plane.java
@@ -0,0 +1,71 @@
+package ru.olamedia.math;
+
+import static java.lang.Math.sqrt;
+
+public class Plane {
+ // normal
+ public Vector3f n = new Vector3f();
+ // distance
+ public float d;
+
+ public void set(Plane p) {
+ n.x = p.n.x;
+ n.y = p.n.y;
+ n.z = p.n.z;
+ d = p.d;
+ }
+
+ public float magnitude() {
+ return (float) sqrt(n.x * n.x + n.y * n.y + n.z * n.z);
+ }
+
+ public void normalize() {
+ float mag = magnitude();
+ n.x /= mag;
+ n.y /= mag;
+ n.z /= mag;
+ d /= mag;
+ }
+
+ public float distance(float x, float y, float z) {
+ return n.x * x + n.y * y + n.z * z + d;
+ }
+
+ public float distance(Vector3f point) {
+ return n.x * point.x + n.y * point.y + n.z * point.z + d;
+ }
+
+ private float dec(float a) {
+ return (float) Math.floor(a * 100) / 100;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return "Plane[nx=" + dec(n.x) + ";ny=" + dec(n.y) + ";nz=" + dec(n.z) + ";d=" + dec(d) + "]";
+ }
+
+ public Vector3f cross(Plane a, Plane b) {
+ return n.cross(a.n.cross(b.n));
+ }
+
+ public void set3Points(Vector3f va, Vector3f vb, Vector3f vc) {
+ // A = y1 (z2 - z3) + y2 (z3 - z1) + y3 (z1 - z2)
+ // B = z1 (x2 - x3) + z2 (x3 - x1) + z3 (x1 - x2)
+ // C = x1 (y2 - y3) + x2 (y3 - y1) + x3 (y1 - y2)
+ // - D = x1 (y2 z3 - y3 z2) + x2 (y3 z1 - y1 z3) + x3 (y1 z2 - y2 z1)
+ Vector3f ab = vb.sub(va);
+ Vector3f ac = vc.sub(va);
+ Vector3f vn = ab.cross(ac);
+ n.set(vn);
+ n.x = va.y * (vb.z - vc.z) + vb.y * (vc.z - va.z) + vc.y * (va.z - vb.z);
+ n.y = va.z * (vb.x - vc.x) + vb.z * (vc.x - va.x) + vc.z * (va.x - vb.x);
+ n.z = va.x * (vb.y - vc.y) + vb.x * (vc.y - va.y) + vc.x * (va.y - vb.y);
+ d = -(vn.x * va.x + vn.y * va.y + vn.z * va.z);
+ normalize();
+ }
+}
diff --git a/src/ru/olamedia/math/Quaternion.java b/src/ru/olamedia/math/Quaternion.java
new file mode 100644
index 0000000..a263f39
--- /dev/null
+++ b/src/ru/olamedia/math/Quaternion.java
@@ -0,0 +1,25 @@
+package ru.olamedia.math;
+
+public class Quaternion {
+ // identity:
+ public float x = 0;
+ public float y = 0;
+ public float z = 0;
+ public float w = 1;
+
+ public static Quaternion identity() {
+ return new Quaternion();
+ }
+
+ public Quaternion inverse() {
+ return QuaternionUtil.inverse(this);
+ }
+
+ public Quaternion mul(Quaternion q) {
+ return QuaternionUtil.multiply(this, q);
+ }
+
+ public float[] toMatrixArray(){
+ return QuaternionUtil.toMatrixArray(this);
+ }
+}
diff --git a/src/ru/olamedia/math/QuaternionUtil.java b/src/ru/olamedia/math/QuaternionUtil.java
new file mode 100644
index 0000000..83ee005
--- /dev/null
+++ b/src/ru/olamedia/math/QuaternionUtil.java
@@ -0,0 +1,54 @@
+package ru.olamedia.math;
+
+public class QuaternionUtil {
+ // QUATERNION INVERSE
+ public static Quaternion inverse(Quaternion q) {
+ Quaternion newQ = new Quaternion();
+ newQ.w = q.w;
+ newQ.x = -q.x;
+ newQ.y = -q.y;
+ newQ.z = -q.z;
+ // normalize here
+ return newQ;
+ }
+
+ // QUATERNION MULTIPLICATION
+ public static Quaternion multiply(Quaternion q1, Quaternion q2) {
+ Quaternion newQ = new Quaternion();
+ newQ.w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z;
+ newQ.x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y;
+ newQ.y = q1.w * q2.y - q1.x * q2.z + q1.y * q2.w + q1.z * q2.x;
+ newQ.z = q1.w * q2.z + q1.x * q2.y - q1.y * q2.x + q1.z * q2.w;
+ return newQ;
+ }
+
+ // QUATERNION-TO-MATRIX, COLUMN-MAJOR NOTATION
+ public static float[] toMatrixArray(Quaternion q) {
+ float[] matrix = new float[16];
+ // First Column
+ matrix[0] = 1 - 2 * (q.y * q.y + q.z * q.z);
+ matrix[1] = 2 * (q.x * q.y + q.z * q.w);
+ matrix[2] = 2 * (q.x * q.z - q.y * q.w);
+ matrix[3] = 0;
+ // Second Column
+ matrix[4] = 2 * (q.x * q.y - q.z * q.w);
+ matrix[5] = 1 - 2 * (q.x * q.x + q.z * q.z);
+ matrix[6] = 2 * (q.z * q.y + q.x * q.w);
+ matrix[7] = 0;
+ // Third Column
+ matrix[8] = 2 * (q.x * q.z + q.y * q.w);
+ matrix[9] = 2 * (q.y * q.z - q.x * q.w);
+ matrix[10] = 1 - 2 * (q.x * q.x + q.y * q.y);
+ matrix[11] = 0;
+ // Fourth Column
+ matrix[12] = 0;
+ matrix[13] = 0;
+ matrix[14] = 0;
+ matrix[15] = 1;
+ return matrix;
+ }
+
+ public static float magnitude(Quaternion qa) {
+ return (float) (Math.sqrt((double) (qa.w * qa.w + qa.x * qa.x + qa.y * qa.y + qa.z * qa.z)));
+ }
+}
diff --git a/src/ru/olamedia/math/TransformMatrix.java b/src/ru/olamedia/math/TransformMatrix.java
new file mode 100644
index 0000000..6f2ea9d
--- /dev/null
+++ b/src/ru/olamedia/math/TransformMatrix.java
@@ -0,0 +1,15 @@
+package ru.olamedia.math;
+
+public class TransformMatrix extends Matrix4f {
+ public void applyTranslation(Matrix4f m) {
+ apply(m);
+ }
+
+ public void applyRotation(Matrix4f m) {
+ apply(m);
+ }
+
+ public void applyScale(Matrix4f m) {
+ apply(m);
+ }
+}
diff --git a/src/ru/olamedia/math/Vector3f.java b/src/ru/olamedia/math/Vector3f.java
new file mode 100644
index 0000000..b16a356
--- /dev/null
+++ b/src/ru/olamedia/math/Vector3f.java
@@ -0,0 +1,70 @@
+package ru.olamedia.math;
+
+public class Vector3f {
+ public float x;
+ public float y;
+ public float z;
+
+ public Vector3f() {
+ this(0, 0, 0);
+ }
+
+ public Vector3f(float x, float y, float z) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public Vector3f(Vector3f vector) {
+ this(vector.x, vector.y, vector.z);
+ }
+
+ public float dot(Vector3f v) {
+ return (x * v.x + y * v.y + z * v.z);
+ }
+
+ public Vector3f cross(Vector3f n) {
+ Vector3f r = new Vector3f(y * n.z - z * n.y, z * n.x - x * n.z, x * n.y - y * n.x);
+ return r;
+ }
+
+ public Vector3f add(Vector3f n) {
+ Vector3f r = new Vector3f(x + n.x, y + n.y, z + n.z);
+ return r;
+ }
+
+ public Vector3f sub(Vector3f n) {
+ return add(n.negate());
+ }
+
+ public Vector3f negate() {
+ Vector3f n = new Vector3f(this);
+ n.x = -n.x;
+ n.y = -n.y;
+ n.z = -n.z;
+ return n;
+ }
+
+ public Vector3f translate(Vector3f look, float f) {
+ Vector3f v = new Vector3f(this);
+ v.x += look.x * f;
+ v.y += look.y * f;
+ v.z += look.z * f;
+ return v;
+ }
+
+ public Vector3f translate(javax.vecmath.Vector3f look, float f) {
+ Vector3f v = new Vector3f(this);
+ v.x += look.x * f;
+ v.y += look.y * f;
+ v.z += look.z * f;
+ return v;
+ }
+
+ public void set(Vector3f vn) {
+ x = vn.x;
+ y = vn.y;
+ z = vn.z;
+ }
+
+}
diff --git a/src/ru/olamedia/math/ViewMatrix.java b/src/ru/olamedia/math/ViewMatrix.java
new file mode 100644
index 0000000..dad4778
--- /dev/null
+++ b/src/ru/olamedia/math/ViewMatrix.java
@@ -0,0 +1,111 @@
+package ru.olamedia.math;
+
+public class ViewMatrix extends Matrix4f {
+ private Matrix4f translation = new Matrix4f();
+ private Matrix4f scale = new Matrix4f();
+ private Matrix4f rotation = new Matrix4f();
+ private TransformMatrix transform = new TransformMatrix();
+
+ public ViewMatrix() {
+ translation.setIdentity();
+ scale.setIdentity();
+ rotation.setIdentity();
+ transform.setIdentity();
+ pack();
+ }
+
+ public void pack() {
+ loadIdentity();
+ transform.loadIdentity();
+ transform.applyScale(scale);
+ transform.applyRotation(rotation);
+ transform.applyTranslation(translation);
+ apply(transform);
+ @SuppressWarnings("unused")
+ float[] t = transform.toFloatArray();
+
+ // this.m[12] = 0;
+ // this.m[13] = 0;
+ // this.m[14] = 0;
+ // Fill translation:
+ // this.m[3] = -(t[0] * t[12] + t[1] * t[13] + t[2] * t[14]);
+ // this.m[7] = -(t[4] * t[12] + t[5] * t[13] + t[6] * t[14]);
+ // this.m[11] = (t[8] * t[12] + t[9] * t[13] + t[10] * t[14]);
+ // m[12] = -(t[0] * t[12] + t[1] * t[13] + t[2] * t[14]);
+ // m[13] = -(t[4] * t[12] + t[5] * t[13] + t[6] * t[14]);
+ // m[14] = (t[8] * t[12] + t[9] * t[13] + t[10] * t[14]);
+ }
+
+ public float getX() {
+ return -translation.get(12);
+ }
+
+ public float getY() {
+ return -translation.get(13);
+ }
+
+ public float getZ() {
+ return -translation.get(14);
+ }
+
+ /**
+ * @return the translation
+ */
+ public Matrix4f getTranslation() {
+ return translation;
+ }
+
+ /**
+ * @param translation
+ * the translation to set
+ */
+ public void setTranslation(Matrix4f translation) {
+ this.translation = translation;
+ }
+
+ /**
+ * @return the scale
+ */
+ public Matrix4f getScale() {
+ return scale;
+ }
+
+ /**
+ * @param scale
+ * the scale to set
+ */
+ public void setScale(Matrix4f scale) {
+ this.scale = scale;
+ }
+
+ /**
+ * @return the rotation
+ */
+ public Matrix4f getRotation() {
+ return rotation;
+ }
+
+ /**
+ * @param rotation
+ * the rotation to set
+ */
+ public void setRotation(Matrix4f rotation) {
+ this.rotation = rotation;
+ }
+
+ public void rotateX(float degrees) {
+ setRotation(getRotation().multiply(Matrix4f.rotateXMatrix(degrees)));
+ }
+
+ public void rotateY(float degrees) {
+ setRotation(getRotation().multiply(Matrix4f.rotateYMatrix(degrees)));
+ }
+
+ public void rotateZ(float degrees) {
+ setRotation(getRotation().multiply(Matrix4f.rotateZMatrix(degrees)));
+ }
+
+ public Matrix4f getTransform() {
+ return transform;
+ }
+}
diff --git a/src/ru/olamedia/math/package-info.java b/src/ru/olamedia/math/package-info.java
new file mode 100644
index 0000000..82b4066
--- /dev/null
+++ b/src/ru/olamedia/math/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.math; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/OlaCraft.java b/src/ru/olamedia/olacraft/OlaCraft.java
new file mode 100644
index 0000000..b5b3234
--- /dev/null
+++ b/src/ru/olamedia/olacraft/OlaCraft.java
@@ -0,0 +1,6 @@
+package ru.olamedia.olacraft;
+
+public class OlaCraft {
+ public static String version = "0.1.6";
+
+}
diff --git a/src/ru/olamedia/olacraft/OlaCraftFrame.java b/src/ru/olamedia/olacraft/OlaCraftFrame.java
new file mode 100644
index 0000000..95f1835
--- /dev/null
+++ b/src/ru/olamedia/olacraft/OlaCraftFrame.java
@@ -0,0 +1,10 @@
+package ru.olamedia.olacraft;
+
+import ru.olamedia.game.GameFrame;
+
+public class OlaCraftFrame extends GameFrame {
+ public OlaCraftFrame() {
+ super();
+ jFrame.setTitle("OlaCraft " + OlaCraft.version);
+ }
+}
diff --git a/src/ru/olamedia/olacraft/events/GameEvent.java b/src/ru/olamedia/olacraft/events/GameEvent.java
new file mode 100644
index 0000000..94b291c
--- /dev/null
+++ b/src/ru/olamedia/olacraft/events/GameEvent.java
@@ -0,0 +1,32 @@
+package ru.olamedia.olacraft.events;
+
+public class GameEvent {
+ public static int GAME_START = GameEventRegistry.get("game.start");
+ public static int PLAYER_SPAWN = GameEventRegistry.get("player.spawn");
+ private Object source;
+ private int type;
+
+ public GameEvent(Object source) {
+ this.setSource(source);
+ }
+
+ public int getType() {
+ return type;
+ }
+
+ public void setType(int type) {
+ this.type = type;
+ }
+
+ public Object getSource() {
+ return source;
+ }
+
+ public void setSource(Object source) {
+ this.source = source;
+ }
+
+ public void dispatch() {
+ GameEventDispatcher.dispatch(this);
+ }
+}
diff --git a/src/ru/olamedia/olacraft/events/GameEventDispatcher.java b/src/ru/olamedia/olacraft/events/GameEventDispatcher.java
new file mode 100644
index 0000000..7cae41a
--- /dev/null
+++ b/src/ru/olamedia/olacraft/events/GameEventDispatcher.java
@@ -0,0 +1,22 @@
+package ru.olamedia.olacraft.events;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class GameEventDispatcher {
+ private static List<GameEventListener> listeners = new ArrayList<GameEventListener>();
+
+ public static void attach(GameEventListener listener) {
+ listeners.add(listener);
+ }
+
+ public static void detach(GameEventListener listener) {
+ listeners.remove(listener);
+ }
+
+ public static void dispatch(GameEvent e) {
+ for (GameEventListener l : listeners) {
+ l.on(e);
+ }
+ }
+}
diff --git a/src/ru/olamedia/olacraft/events/GameEventListener.java b/src/ru/olamedia/olacraft/events/GameEventListener.java
new file mode 100644
index 0000000..1ff8185
--- /dev/null
+++ b/src/ru/olamedia/olacraft/events/GameEventListener.java
@@ -0,0 +1,5 @@
+package ru.olamedia.olacraft.events;
+
+public interface GameEventListener {
+ public void on(GameEvent e);
+}
diff --git a/src/ru/olamedia/olacraft/events/GameEventRegistry.java b/src/ru/olamedia/olacraft/events/GameEventRegistry.java
new file mode 100644
index 0000000..a9e1885
--- /dev/null
+++ b/src/ru/olamedia/olacraft/events/GameEventRegistry.java
@@ -0,0 +1,17 @@
+package ru.olamedia.olacraft.events;
+
+import java.util.HashMap;
+
+public class GameEventRegistry {
+ private static HashMap<String, Integer> map = new HashMap<String, Integer>();
+ private static int i = 0;
+
+ public static int get(String name) {
+ if (map.containsKey(name)) {
+ return map.get(name);
+ }
+ i++;
+ map.put(name, i);
+ return i;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/events/package-info.java b/src/ru/olamedia/olacraft/events/package-info.java
new file mode 100644
index 0000000..2a5a677
--- /dev/null
+++ b/src/ru/olamedia/olacraft/events/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.events; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/game/Game.java b/src/ru/olamedia/olacraft/game/Game.java
new file mode 100644
index 0000000..0980505
--- /dev/null
+++ b/src/ru/olamedia/olacraft/game/Game.java
@@ -0,0 +1,106 @@
+package ru.olamedia.olacraft.game;
+
+import com.jogamp.newt.opengl.GLWindow;
+
+import ru.olamedia.camera.MatrixCamera;
+import ru.olamedia.game.GameFrame;
+import ru.olamedia.olacraft.events.GameEvent;
+import ru.olamedia.olacraft.network.GameClient;
+import ru.olamedia.olacraft.network.GameServer;
+import ru.olamedia.olacraft.scene.GameScene;
+import ru.olamedia.olacraft.world.dataProvider.AbstractChunkDataProvider;
+import ru.olamedia.player.Player;
+
+public class Game {
+ public static Game instance = null;
+ public static int port = 26002;
+ public static boolean isServerRunning = false;
+ public static GameServer server = new GameServer();
+ public static GameClient client = new GameClient();
+ public static Timer timer = new Timer();
+
+ public MatrixCamera camera;
+
+ public static int MODE_SINGLEPLAYER = 1;
+ public static int MODE_MULTIPLAYER = 2;
+ public static int MODE_SERVER = 4;
+ @SuppressWarnings("unused")
+ private int mode = 1;
+ private boolean isRunning = false;
+ @SuppressWarnings("unused")
+ // player
+ public Player player;
+
+ // block world
+ // private blockWorld;
+ // live entities (including player and npcs)
+ // private liveEntities;
+ public Game() {
+ this(MODE_SINGLEPLAYER);
+ }
+
+ public Game(int mode) {
+ this.mode = mode;
+ if ((MODE_MULTIPLAYER & mode) > 0) {
+ if ((MODE_SERVER & mode) > 0) {
+ // init server
+ } else {
+ // init client
+ }
+ }
+ player = new Player();
+ camera = new MatrixCamera();
+ camera.attachTo(player);
+ camera.setFov(90);
+ camera.pack();
+ // scene.registerLiveEntity(player);
+ }
+
+ public void start() {
+ isRunning = true;
+ GameEvent e = new GameEvent(null);
+ e.setType(GameEvent.GAME_START);
+ e.dispatch();
+ }
+
+ // Pause game in single mode
+ public void pause() {
+
+ }
+
+ public void stop() {
+
+ }
+
+ public boolean isRunning() {
+ return isRunning;
+ }
+
+ public void spawnMe(int x, int y, int z) {
+ player.setLocation(x, y, z);
+ }
+
+ public void tick() {
+ timer.update();
+
+ }
+
+ public static class Display {
+ public static int getWidth() {
+ return (int) GameFrame.getWidth();
+ }
+
+ public static int getHeight() {
+ return (int) GameFrame.getHeight();
+ }
+
+ public static float getAspect() {
+ return ((float) getWidth()) / ((float) getHeight());
+ }
+ }
+
+ public float getDelta() {
+ return (float) timer.getElapsedTime() / 1000;
+ }
+
+}
diff --git a/src/ru/olamedia/olacraft/game/GameInterface.java b/src/ru/olamedia/olacraft/game/GameInterface.java
new file mode 100644
index 0000000..1f02071
--- /dev/null
+++ b/src/ru/olamedia/olacraft/game/GameInterface.java
@@ -0,0 +1,7 @@
+package ru.olamedia.olacraft.game;
+
+public class GameInterface {
+ public void requestSpawn(){
+
+ }
+}
diff --git a/src/ru/olamedia/olacraft/game/IGameWrapper.java b/src/ru/olamedia/olacraft/game/IGameWrapper.java
new file mode 100644
index 0000000..a4a7ed1
--- /dev/null
+++ b/src/ru/olamedia/olacraft/game/IGameWrapper.java
@@ -0,0 +1,7 @@
+package ru.olamedia.olacraft.game;
+
+public interface IGameWrapper {
+ public void setMyId(int connectionId);
+
+ public void spawn(int connectionId, int x, int y, int z);
+}
diff --git a/src/ru/olamedia/olacraft/game/LocalGameWrapper.java b/src/ru/olamedia/olacraft/game/LocalGameWrapper.java
new file mode 100644
index 0000000..8c19ce6
--- /dev/null
+++ b/src/ru/olamedia/olacraft/game/LocalGameWrapper.java
@@ -0,0 +1,17 @@
+package ru.olamedia.olacraft.game;
+
+public class LocalGameWrapper implements IGameWrapper {
+
+ @Override
+ public void setMyId(int connectionId) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void spawn(int connectionId, int x, int y, int z) {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/src/ru/olamedia/olacraft/game/SpawnLocation.java b/src/ru/olamedia/olacraft/game/SpawnLocation.java
new file mode 100644
index 0000000..2ff0c39
--- /dev/null
+++ b/src/ru/olamedia/olacraft/game/SpawnLocation.java
@@ -0,0 +1,7 @@
+package ru.olamedia.olacraft.game;
+
+public class SpawnLocation {
+ public int x;
+ public int y;
+ public int z;
+}
diff --git a/src/ru/olamedia/olacraft/game/Timer.java b/src/ru/olamedia/olacraft/game/Timer.java
new file mode 100644
index 0000000..1c0aaee
--- /dev/null
+++ b/src/ru/olamedia/olacraft/game/Timer.java
@@ -0,0 +1,99 @@
+package ru.olamedia.olacraft.game;
+
+/**
+ * For frame-rate independent movement
+ *
+ * @author Oskar Veerhoek
+ */
+public class Timer {
+ private long lastTime; // nanoseconds
+ private double elapsedTime;
+ private float fps;
+ private int fpsCounter = 0;
+ private long lastFPS;
+ private float avgSeconds = 3;
+
+ /**
+ * @return the fps
+ */
+ public float getFps() {
+ return fps;
+ }
+
+ /**
+ * @return the avgFps
+ */
+ public float getAvgFps() {
+ return avgFps;
+ }
+
+ private float avgFps;
+
+ /**
+ * Creates a timer.
+ */
+ public Timer() {
+ fps = 0;
+ }
+
+ /**
+ * Initializes the timer. Call this just before entering the game loop.
+ */
+ public void initialize() {
+ lastTime = System.nanoTime();
+ }
+
+ /**
+ * @return the elapsed time since the the next to last update call
+ */
+ public double getElapsedTime() {
+ return elapsedTime;
+ }
+
+ /**
+ * Updates the timer. Call this once every iteration of the game loop.
+ *
+ * @return the elapsed time in milliseconds
+ */
+ public double update() {
+ if (lastTime == 0) {
+ lastTime = System.nanoTime();
+ return 0;
+ } else {
+ long elapsedTime = System.nanoTime() - lastTime;
+ updateFps(elapsedTime);
+ lastTime = System.nanoTime();
+ this.elapsedTime = elapsedTime / (double) 1000000;
+ return this.elapsedTime;
+ }
+ }
+
+ public void updateFps(long elapsedTime) {
+ if (elapsedTime > 0) {
+ float ms = (float) (elapsedTime / 1000000);
+ if (ms > 0) {
+ fps = (float) (1000 / ms);
+ }
+ }
+ fpsCounter++;
+ if (lastFPS == 0) {
+ lastFPS = System.nanoTime();
+ } else {
+ double elapsedFPS = (System.nanoTime() - lastFPS) / (double) 1000000;
+ if (elapsedFPS > 1000 * avgSeconds) {
+ avgFps = fpsCounter / avgSeconds;
+ fpsCounter = 0;
+ lastFPS = System.nanoTime();
+ }
+ }
+
+ // if (elapsedTime > 0) {
+ // fps = (float) (1000 / (elapsedTime / 1000000));
+ // if (avgFps == 0) {
+ // avgFps = fps;
+ // } else {
+ // avgFps = avgFps + (fps - avgFps) / 1000;
+ // }
+ // }
+ }
+} \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/game/package-info.java b/src/ru/olamedia/olacraft/game/package-info.java
new file mode 100644
index 0000000..85b0f16
--- /dev/null
+++ b/src/ru/olamedia/olacraft/game/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.game; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/inventory/Frame.java b/src/ru/olamedia/olacraft/inventory/Frame.java
new file mode 100644
index 0000000..a5cd979
--- /dev/null
+++ b/src/ru/olamedia/olacraft/inventory/Frame.java
@@ -0,0 +1,44 @@
+package ru.olamedia.olacraft.inventory;
+
+import org.olamedia.olacraft.draw.DrawInterface;
+import org.olamedia.olacraft.entity.AbstractEntity;
+
+import static org.olamedia.olacraft.blocks.Block.BLOCK_SIZE;
+import org.olamedia.olacraft.util.CommonApi;
+
+public class Frame extends AbstractEntity implements DrawInterface {
+ public Frame(double x, double y, double z, double width, double height,
+ double depth) {
+ super(x, y, z, width, height, depth);
+ }
+
+ public CommonApi api = CommonApi.instance;
+
+ @Override
+ public void update(double delta) {
+
+ }
+
+ @Override
+ public void draw() {
+ api.draw.texRecti("inventory_frame", x, y, BLOCK_SIZE, BLOCK_SIZE);
+ return;
+ // Texture t = api.texture.get("inventory_frame");
+ // t.bind();
+ // glColor3f(1, 1, 1);
+ // glLoadIdentity();
+ // glTranslated(x, y, 0);
+ // glBegin(GL_QUADS);
+ // glTexCoord2f(0, 0);
+ // glVertex2f(0, 0); // Upper-left
+ // glTexCoord2f(1, 0);
+ // glVertex2f(BLOCK_SIZE, 0); // Upper-right
+ // glTexCoord2f(1, 1);
+ // glVertex2f(BLOCK_SIZE, BLOCK_SIZE); // Bottom-right
+ // glTexCoord2f(0, 1);
+ // glVertex2f(0, BLOCK_SIZE); // Bottom-left
+ // glEnd();
+ // glLoadIdentity();
+ }
+
+}
diff --git a/src/ru/olamedia/olacraft/inventory/Inventory.java b/src/ru/olamedia/olacraft/inventory/Inventory.java
new file mode 100644
index 0000000..2ce843b
--- /dev/null
+++ b/src/ru/olamedia/olacraft/inventory/Inventory.java
@@ -0,0 +1,76 @@
+package ru.olamedia.olacraft.inventory;
+
+import ru.olamedia.olacraft.world.block.Block;
+import ru.olamedia.olacraft.world.blockStack.BlockStack;
+
+public class Inventory {
+ public static int BIND_NUM = 10;
+ public BlockStack[] binded = new BlockStack[BIND_NUM];
+ public BlockStack selected;
+ public int selectedId;
+ private boolean isInventoryGUIOpen = false;
+
+ public Inventory() {
+ }
+
+ public void init() {
+ for (int i = 0; i < BIND_NUM; i++) {
+ Block block = new Block(x + bindedWrapperPadding + i * BLOCK_SIZE + bindedSpacing * i, y
+ + bindedWrapperPadding + 0, 0, "gravel");
+ binded[i] = new BlockStack(block, 64);
+ }
+ binded[0].block.setName("dirt");
+ binded[1].block.setName("grass");
+ binded[2].block.setName("water");
+ binded[3].block.setName("wood");
+ binded[4].block.setName("asphalt");
+ binded[5].block.setName("torch");
+ binded[8].block.setName("grass");
+ binded[9].block.setName("dirt");
+ frame = new Frame(0, 0, 0, BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
+ select(0);
+ }
+
+ public void onKeyDown() {
+ // System.out.println("keyName: " + api.keyboard.keyName);
+ int key = Keyboard.getEventKey();
+ if (key == Keyboard.KEY_1) {
+ select(0);
+ }
+ if (key == Keyboard.KEY_2) {
+ select(1);
+ }
+ if (key == Keyboard.KEY_3) {
+ select(2);
+ }
+ if (key == Keyboard.KEY_4) {
+ select(3);
+ }
+ if (key == Keyboard.KEY_5) {
+ select(4);
+ }
+ if (key == Keyboard.KEY_6) {
+ select(5);
+ }
+ if (key == Keyboard.KEY_7) {
+ select(6);
+ }
+ if (key == Keyboard.KEY_8) {
+ select(7);
+ }
+ if (key == Keyboard.KEY_9) {
+ select(8);
+ }
+ if (key == Keyboard.KEY_0) {
+ select(9);
+ }
+ if (key == Keyboard.KEY_E) {
+ isInventoryGUIOpen = !isInventoryGUIOpen;
+ }
+
+ }
+
+ public void select(int i) {
+ selected = binded[i];
+ }
+}
diff --git a/src/ru/olamedia/olacraft/inventory/package-info.java b/src/ru/olamedia/olacraft/inventory/package-info.java
new file mode 100644
index 0000000..fe2b1fc
--- /dev/null
+++ b/src/ru/olamedia/olacraft/inventory/package-info.java
@@ -0,0 +1,9 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.inventory;
+
diff --git a/src/ru/olamedia/olacraft/network/ConnectionState.java b/src/ru/olamedia/olacraft/network/ConnectionState.java
new file mode 100644
index 0000000..2d6c5c5
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/ConnectionState.java
@@ -0,0 +1,17 @@
+package ru.olamedia.olacraft.network;
+
+public class ConnectionState {
+ private int state;
+
+ public ConnectionState(int state) {
+ this.state = state;
+ }
+
+ public static ConnectionState STATE_DISCONNECTED = new ConnectionState(0);
+ public static ConnectionState STATE_CONNECTED = new ConnectionState(1);
+ public static ConnectionState STATE_CONNECTING = new ConnectionState(2);
+
+ public boolean isConnected() {
+ return state == 1;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/network/ConnectionStateListener.java b/src/ru/olamedia/olacraft/network/ConnectionStateListener.java
new file mode 100644
index 0000000..6220029
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/ConnectionStateListener.java
@@ -0,0 +1,7 @@
+package ru.olamedia.olacraft.network;
+
+public class ConnectionStateListener {
+ public void onChangeState(ConnectionState state){
+ // override
+ }
+}
diff --git a/src/ru/olamedia/olacraft/network/GameClient.java b/src/ru/olamedia/olacraft/network/GameClient.java
new file mode 100644
index 0000000..669d954
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/GameClient.java
@@ -0,0 +1,209 @@
+package ru.olamedia.olacraft.network;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryonet.Client;
+import com.esotericsoftware.kryonet.Connection;
+import com.esotericsoftware.kryonet.Listener;
+
+import ru.olamedia.game.GameManager;
+import ru.olamedia.liveEntity.LiveEntity;
+import ru.olamedia.olacraft.game.Game;
+import ru.olamedia.olacraft.network.packet.ConnectionPacket;
+import ru.olamedia.olacraft.network.packet.ConnectionRequestPacket;
+import ru.olamedia.olacraft.network.packet.IPacket;
+import ru.olamedia.olacraft.network.packet.IPacketListener;
+import ru.olamedia.olacraft.network.packet.LiveEntityLocationUpdatePacket;
+import ru.olamedia.olacraft.network.packet.SpawnPacket;
+import ru.olamedia.olacraft.network.packet.SpawnRequestPacket;
+import ru.olamedia.olacraft.network.packet.WorldInfoPacket;
+import ru.olamedia.olacraft.scene.GameScene;
+import ru.olamedia.olacraft.world.WorldInfo;
+import ru.olamedia.olacraft.world.dataProvider.CachedChunkDataProvider;
+import ru.olamedia.olacraft.world.dataProvider.RemoteChunkDataProvider;
+import ru.olamedia.olacraft.world.provider.WorldProvider;
+
+public class GameClient extends ConnectionStateListener implements IPacketListener {
+ private WorldProvider worldProvider;
+ private GameScene scene;
+
+ private Client client = new Client(70 * 1024 * 1024, 70 * 1024 * 1024);
+ private String hostname = "127.0.0.1";
+
+ @Override
+ public void onChangeState(ConnectionState state) {
+ if (state.isConnected()) {
+ GameManager.instance.hideMainMenu();
+ client.sendTCP(new ConnectionRequestPacket());
+ //
+ // provider.load(0, 0, 0);
+ // provider.load(1, 2, 3);
+ }
+ }
+
+ /*
+ * public AbstractChunkDataProvider getChunkDataProvider() {
+ * return worldProvider.getChunkDataProvider();
+ * }
+ */
+
+ public WorldProvider getWorldProvider() {
+ return worldProvider;
+ }
+
+ private List<ConnectionStateListener> stateListeners = new ArrayList<ConnectionStateListener>();
+ private List<IPacketListener> packetListeners = new ArrayList<IPacketListener>();
+ private ExecutorService threadPool = Executors.newFixedThreadPool(1);
+
+ public GameClient() {
+ // INIT WORLD
+ worldProvider = new WorldProvider();
+ worldProvider.setChunkDataProvider(new CachedChunkDataProvider(new RemoteChunkDataProvider(this)));
+ // CREATE SCENE
+ scene = new GameScene(worldProvider);
+ Kryo kryo = client.getKryo();
+ Network.registerPackets(kryo);
+ addStateListener(this);
+ addPacketListener(this);
+ client.addListener(new Listener.ThreadedListener(new Listener() {
+
+ @Override
+ public void received(Connection connection, Object object) {
+ if (object instanceof IPacket) {
+ dispatchPacket(connection, (IPacket) object);
+ }
+ }
+
+ @Override
+ public void disconnected(Connection connection) {
+ super.disconnected(connection);
+ dispatchState(ConnectionState.STATE_DISCONNECTED);
+ }
+ }, threadPool));
+ client.start();
+ }
+
+ public void addStateListener(ConnectionStateListener listener) {
+ stateListeners.add(listener);
+ }
+
+ private void dispatchState(ConnectionState state) {
+ for (ConnectionStateListener l : stateListeners) {
+ l.onChangeState(state);
+ }
+ }
+
+ private void dispatchPacket(Connection connection, IPacket p) {
+ for (IPacketListener l : packetListeners) {
+ l.onPacket(connection, p);
+ }
+ }
+
+ public void connect() {
+ new Thread("Connect") {
+ public void run() {
+ try {
+ dispatchState(ConnectionState.STATE_CONNECTING);
+ client.connect(5000, hostname, Game.port);
+ dispatchState(ConnectionState.STATE_CONNECTED);
+ } catch (IOException ex) {
+ dispatchState(ConnectionState.STATE_DISCONNECTED);
+ }
+ }
+ }.start();
+ }
+
+ public void close() {
+ client.close();
+ }
+
+ public void send(IPacket p) {
+ client.sendTCP(p);
+ }
+
+ public void addPacketListener(IPacketListener listener) {
+ packetListeners.add(listener);
+ }
+
+ public boolean isConnected() {
+ return client.isConnected();
+ }
+
+ private static boolean DEBUG = true;
+
+ private void debug(String s) {
+ if (DEBUG) {
+ System.out.println("[GameClient] " + s);
+ }
+ }
+
+ @Override
+ public void onPacket(Connection connection, IPacket p) {
+ debug("received " + p.getClass().getName());
+ // 1. receive ConnectionPacket, send SpawnRequestPacket
+ if (p instanceof ConnectionPacket) {
+ Game.instance.player.setConnectionId(((ConnectionPacket) p).connectionId);
+ send(new SpawnRequestPacket());
+ }
+ if (p instanceof WorldInfoPacket) {
+ worldProvider.setInfo(((WorldInfoPacket) p).info);
+ }
+ // 2. Receive SpawnPacket
+ if (p instanceof SpawnPacket) {
+ LiveEntity entity;
+ if (((SpawnPacket) p).connectionId == client.getID()) {
+ // me
+ entity = Game.instance.player;
+ } else {
+ // another player
+ entity = new LiveEntity();
+ }
+ entity.setX(((SpawnPacket) p).x);
+ entity.setY(((SpawnPacket) p).y);
+ entity.setZ(((SpawnPacket) p).z);
+ entity.setConnectionId(((SpawnPacket) p).connectionId);
+ scene.registerLiveEntity(entity);
+ if (((SpawnPacket) p).connectionId == client.getID()) {
+ // me
+ scene.registerPlayer(entity);
+ }
+ }
+ if (p instanceof LiveEntityLocationUpdatePacket) {
+ LiveEntity entity = scene.getLiveEntity(((LiveEntityLocationUpdatePacket) p).connectionId);
+ if (null != entity) {
+ entity.setX(((LiveEntityLocationUpdatePacket) p).x);
+ entity.setY(((LiveEntityLocationUpdatePacket) p).y);
+ entity.setZ(((LiveEntityLocationUpdatePacket) p).z);
+ }
+ }
+ }
+
+ public String getHostname() {
+ return hostname;
+ }
+
+ public void setHostname(String hostname) {
+ this.hostname = hostname;
+ }
+
+ public void dispose() {
+ client.close();
+ client.stop();
+ // threadPool.awaitTermination(1000, TimeUnit.MILLISECONDS);
+ threadPool.shutdownNow();
+ }
+
+ public GameScene getScene() {
+ return scene;
+ }
+
+ public WorldInfo getWorldInfo() {
+ return worldProvider.getInfo();
+ }
+
+}
diff --git a/src/ru/olamedia/olacraft/network/GameServer.java b/src/ru/olamedia/olacraft/network/GameServer.java
new file mode 100644
index 0000000..67dffc5
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/GameServer.java
@@ -0,0 +1,169 @@
+package ru.olamedia.olacraft.network;
+
+import java.io.IOException;
+import java.net.BindException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import ru.olamedia.liveEntity.LiveEntity;
+import ru.olamedia.olacraft.game.Game;
+import ru.olamedia.olacraft.game.SpawnLocation;
+import ru.olamedia.olacraft.network.discovery.DiscoveryThread;
+import ru.olamedia.olacraft.network.packet.ConnectionPacket;
+import ru.olamedia.olacraft.network.packet.ConnectionRequestPacket;
+import ru.olamedia.olacraft.network.packet.GetRegionPacket;
+import ru.olamedia.olacraft.network.packet.IPacket;
+import ru.olamedia.olacraft.network.packet.LiveEntityLocationUpdatePacket;
+import ru.olamedia.olacraft.network.packet.RegionDataPacket;
+import ru.olamedia.olacraft.network.packet.SpawnPacket;
+import ru.olamedia.olacraft.network.packet.SpawnRequestPacket;
+import ru.olamedia.olacraft.network.packet.WorldInfoPacket;
+import ru.olamedia.olacraft.scene.GameScene;
+import ru.olamedia.olacraft.world.data.RegionData;
+import ru.olamedia.olacraft.world.dataProvider.CachedChunkDataProvider;
+import ru.olamedia.olacraft.world.dataProvider.LocalChunkDataProvider;
+import ru.olamedia.olacraft.world.provider.WorldProvider;
+
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryonet.Connection;
+import com.esotericsoftware.kryonet.Listener;
+import com.esotericsoftware.kryonet.Server;
+
+public class GameServer {
+ private WorldProvider worldProvider;
+
+ private ExecutorService threadPool = Executors.newFixedThreadPool(1);
+ public static Server server = new Server(70 * 1024 * 1024, 1024 * 1024) {
+ @Override
+ protected PlayerConnection newConnection() {
+ // By providing our own connection implementation, we can store per
+ // connection state without a connection ID to state look up.
+ return new PlayerConnection();
+ }
+ };
+ private boolean isServerRunning = false;
+
+ private GameScene scene;
+
+ private static boolean DEBUG = true;
+
+ private void debug(String s) {
+ if (DEBUG) {
+ System.out.println("[GameServer] " + s);
+ }
+ }
+
+ public GameServer() {
+ // INIT WORLD
+ worldProvider = new WorldProvider();
+ worldProvider.setChunkDataProvider(new CachedChunkDataProvider(new LocalChunkDataProvider(worldProvider.getInfo().name)));
+ // CREATE SCENE
+ scene = new GameScene(worldProvider);
+ // worldProvider.getInfo().name = "world";
+ Kryo kryo = server.getKryo();
+ Network.registerPackets(kryo);
+ server.addListener(new Listener.ThreadedListener(new Listener() {
+ @Override
+ public void disconnected(Connection connection) {
+ }
+
+ @Override
+ public void received(Connection connection, Object object) {
+ debug("received " + object.getClass());
+ if (object instanceof ConnectionRequestPacket) {
+ ConnectionPacket p = new ConnectionPacket();
+ p.connectionId = connection.getID();
+ server.sendToTCP(connection.getID(), p);
+ }
+ if (object instanceof GetRegionPacket) {
+ GetRegionPacket p = (GetRegionPacket) object;
+ RegionData data = worldProvider.getRegion(p.location);
+ RegionDataPacket response = new RegionDataPacket();
+ response.data = data;
+ server.sendToTCP(connection.getID(), response);
+ }
+ if (object instanceof SpawnRequestPacket) {
+ SpawnLocation loc = worldProvider.getSpawnLocation(connection.getID());
+ if (null != loc) {
+ server.sendToTCP(connection.getID(), new WorldInfoPacket(worldProvider));
+ LiveEntity entity = new LiveEntity();
+ entity.setX(loc.x);
+ entity.setY(loc.y);
+ entity.setZ(loc.z);
+ entity.setConnectionId(connection.getID());
+ scene.registerLiveEntity(entity);
+ // send all entity locations
+ for (LiveEntity nextEntity : scene.getLiveEntities().values()) {
+ SpawnPacket p = new SpawnPacket();
+ p.x = nextEntity.getX();
+ p.y = nextEntity.getY();
+ p.z = nextEntity.getZ();
+ p.connectionId = nextEntity.getConnectionId();
+ if (p.connectionId == connection.getID()) {
+ server.sendToAllTCP(p);
+ } else {
+ server.sendToTCP(connection.getID(), p);
+ }
+ }
+ }
+ }
+ if (object instanceof LiveEntityLocationUpdatePacket) {
+ LiveEntityLocationUpdatePacket p = ((LiveEntityLocationUpdatePacket) object);
+ p.connectionId = connection.getID();
+ LiveEntity entity = scene.getLiveEntity(connection.getID());
+ if (null != entity) {
+ entity.setLocation(p.x, p.y, p.z);
+ server.sendToAllTCP(object);
+ }
+ }
+
+ // super.received(connection, object);
+ }
+ }, threadPool));
+ }
+
+ private DiscoveryThread discovery;
+
+ public void start() {
+ try {
+ server.start();
+ server.bind(Game.port);
+ discovery = new DiscoveryThread("SERVER DISCOVERY");
+ discovery.start();
+ isServerRunning = true;
+ // server.addListener(new Listener());
+ } catch (BindException ex) {
+ server.stop();
+ if (null != discovery && discovery.isAlive()) {
+ discovery.interrupt();
+ }
+ isServerRunning = false;
+ } catch (IOException e1) {
+ server.stop();
+ if (null != discovery && discovery.isAlive()) {
+ discovery.interrupt();
+ }
+ e1.printStackTrace();
+ isServerRunning = false;
+ }
+ }
+
+ public void stop() {
+ server.close();
+ server.stop();
+ isServerRunning = false;
+ }
+
+ public boolean isRunning() {
+ return isServerRunning;
+ }
+
+ public void send(IPacket p) {
+ }
+
+ public void dispose() {
+ stop();
+ // threadPool.awaitTermination(1000, TimeUnit.MILLISECONDS);
+ threadPool.shutdownNow();
+ }
+}
diff --git a/src/ru/olamedia/olacraft/network/Network.java b/src/ru/olamedia/olacraft/network/Network.java
new file mode 100644
index 0000000..2ba8eab
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/Network.java
@@ -0,0 +1,71 @@
+package ru.olamedia.olacraft.network;
+
+import java.util.BitSet;
+
+import ru.olamedia.olacraft.network.packet.ChunkDataPacket;
+import ru.olamedia.olacraft.network.packet.ConnectionPacket;
+import ru.olamedia.olacraft.network.packet.ConnectionRequestPacket;
+import ru.olamedia.olacraft.network.packet.GetChunkDataPacket;
+import ru.olamedia.olacraft.network.packet.GetRegionPacket;
+import ru.olamedia.olacraft.network.packet.LiveEntityLocationUpdatePacket;
+import ru.olamedia.olacraft.network.packet.RegionDataPacket;
+import ru.olamedia.olacraft.network.packet.SpawnPacket;
+import ru.olamedia.olacraft.network.packet.SpawnRequestPacket;
+import ru.olamedia.olacraft.network.packet.WorldInfoPacket;
+import ru.olamedia.olacraft.world.WorldInfo;
+import ru.olamedia.olacraft.world.data.ChunkData;
+import ru.olamedia.olacraft.world.data.ChunkLightData;
+import ru.olamedia.olacraft.world.data.HeightMap;
+import ru.olamedia.olacraft.world.data.RegionData;
+import ru.olamedia.olacraft.world.data.SectorData;
+import ru.olamedia.olacraft.world.location.BlockLocation;
+import ru.olamedia.olacraft.world.location.ChunkLocation;
+import ru.olamedia.olacraft.world.location.RegionLocation;
+import ru.olamedia.olacraft.world.location.SectorLocation;
+
+import com.esotericsoftware.kryo.Kryo;
+
+public class Network {
+ public static void registerPackets(Kryo kryo) {
+ // types
+ kryo.register(boolean.class);
+ kryo.register(boolean[].class);
+ kryo.register(byte.class);
+ kryo.register(byte[].class);
+ kryo.register(byte[][].class);
+ kryo.register(int.class);
+ kryo.register(int[].class);
+ kryo.register(float.class);
+ kryo.register(float[].class);
+ kryo.register(long.class);
+ kryo.register(long[].class);
+ kryo.register(BitSet.class);
+ kryo.register(HeightMap.class);
+ kryo.register(WorldInfo.class);
+ kryo.register(WorldInfoPacket.class);
+ kryo.register(BlockLocation.class);
+ kryo.register(ChunkLocation.class);
+ kryo.register(SectorLocation.class);
+ kryo.register(RegionLocation.class);
+ kryo.register(ChunkData.class);
+ kryo.register(ChunkData[].class);
+ kryo.register(SectorData.class);
+ kryo.register(SectorData[].class);
+ kryo.register(SectorData[][].class);
+ kryo.register(RegionData.class);
+ kryo.register(GetRegionPacket.class);
+ kryo.register(RegionDataPacket.class);
+
+
+ kryo.register(ChunkLightData.class);
+ kryo.register(ChunkData.class);
+ // packets
+ kryo.register(ConnectionRequestPacket.class);
+ kryo.register(ConnectionPacket.class);
+ kryo.register(SpawnRequestPacket.class);
+ kryo.register(SpawnPacket.class);
+ kryo.register(GetChunkDataPacket.class);
+ kryo.register(ChunkDataPacket.class);
+ kryo.register(LiveEntityLocationUpdatePacket.class);
+ }
+}
diff --git a/src/ru/olamedia/olacraft/network/PlayerConnection.java b/src/ru/olamedia/olacraft/network/PlayerConnection.java
new file mode 100644
index 0000000..3120b4d
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/PlayerConnection.java
@@ -0,0 +1,9 @@
+package ru.olamedia.olacraft.network;
+
+import ru.olamedia.liveEntity.LiveEntity;
+
+import com.esotericsoftware.kryonet.Connection;
+
+public class PlayerConnection extends Connection{
+ public LiveEntity entity;
+}
diff --git a/src/ru/olamedia/olacraft/network/discovery/DiscoveryClient.java b/src/ru/olamedia/olacraft/network/discovery/DiscoveryClient.java
new file mode 100644
index 0000000..629e6e3
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/discovery/DiscoveryClient.java
@@ -0,0 +1,143 @@
+package ru.olamedia.olacraft.network.discovery;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.InterfaceAddress;
+import java.net.NetworkInterface;
+import java.net.SocketTimeoutException;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+
+import ru.olamedia.tasks.Task;
+
+public class DiscoveryClient extends Task {
+ private static DatagramSocket c;
+ public static List<InetAddress> list = new ArrayList<InetAddress>();
+ private static List<DiscoveryListener> listeners = new ArrayList<DiscoveryListener>();
+
+ public void addHostListener(DiscoveryListener listener) {
+ listeners.add(listener);
+ }
+
+ public static void discovery() {
+ list.clear();
+ try {
+ list.add(InetAddress.getByName("127.0.0.1"));
+ } catch (UnknownHostException e1) {
+ e1.printStackTrace();
+ }
+ // Find the server using UDP broadcast
+ try {
+ // Open a random port to send the package
+ c = new DatagramSocket();
+ c.setBroadcast(true);
+ c.setSoTimeout(3000);
+
+ byte[] sendData = "DISCOVER_OLACRAFTSERVER_REQUEST".getBytes();
+
+ // Try the 255.255.255.255 first
+ try {
+ DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length,
+ InetAddress.getByName("255.255.255.255"), DiscoveryThread.port);
+ c.send(sendPacket);
+ System.out.println(DiscoveryClient.class.getName()
+ + ">>> Request packet sent to: 255.255.255.255 (DEFAULT)");
+ } catch (Exception e) {
+ }
+
+ // Broadcast the message over all the network interfaces
+ @SuppressWarnings("rawtypes")
+ Enumeration interfaces = NetworkInterface.getNetworkInterfaces();
+ while (interfaces.hasMoreElements()) {
+ NetworkInterface networkInterface = (NetworkInterface) interfaces.nextElement();
+
+ if (networkInterface.isLoopback() || !networkInterface.isUp()) {
+ continue; // Don't want to broadcast to the loopback
+ // interface
+ }
+
+ for (InterfaceAddress interfaceAddress : networkInterface.getInterfaceAddresses()) {
+ InetAddress broadcast = interfaceAddress.getBroadcast();
+ if (broadcast == null) {
+ continue;
+ }
+
+ // Send the broadcast package!
+ try {
+ DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, broadcast, 8888);
+ c.send(sendPacket);
+ } catch (Exception e) {
+ }
+
+ System.out.println(DiscoveryClient.class.getName() + ">>> Request packet sent to: "
+ + broadcast.getHostAddress() + "; Interface: " + networkInterface.getDisplayName());
+ }
+ }
+
+ System.out.println(DiscoveryClient.class.getName()
+ + ">>> Done looping over all network interfaces. Now waiting for a reply!");
+ while (true) {
+ // Wait for a response
+ byte[] recvBuf = new byte[15000];
+ DatagramPacket receivePacket = new DatagramPacket(recvBuf, recvBuf.length);
+ c.receive(receivePacket);
+
+ // We have a response
+ System.out.println(DiscoveryClient.class.getName() + ">>> Broadcast response from server: "
+ + receivePacket.getAddress().getHostAddress());
+
+ // Check if the message is correct
+ String message = new String(receivePacket.getData()).trim();
+ if (message.equals("DISCOVER_OLACRAFTSERVER_RESPONSE")) {
+ list.add(receivePacket.getAddress());
+ for (DiscoveryListener l : listeners) {
+ l.onHost(receivePacket.getAddress());
+ }
+ // DO SOMETHING WITH THE SERVER'S IP (for example, store it
+ // in
+ // your controller)
+ // Controller_Base.setServerIp(receivePacket.getAddress());
+ }
+ }
+ } catch (SocketTimeoutException ex) {
+ // no hosts were discovered
+ } catch (IOException ex) {
+ // no hosts were discovered
+ } finally {
+ // Close the port!
+ if (null != c) {
+ c.close();
+ }
+ for (DiscoveryListener l : listeners) {
+ l.onHost(null); // end of list marker
+ }
+ }
+ }
+
+ @Override
+ public void run() {
+// while (!shouldStop()) {
+ discovery();
+ // try {
+ // wait(3000);
+ // } catch (InterruptedException e) {
+ // e.printStackTrace();
+ // }
+ // }
+ }
+
+ public void refresh() {
+ }
+
+ public static DiscoveryClient getInstance() {
+ return DiscoveryThreadHolder.INSTANCE;
+ }
+
+ private static class DiscoveryThreadHolder {
+ private static final DiscoveryClient INSTANCE = new DiscoveryClient();
+ }
+}
diff --git a/src/ru/olamedia/olacraft/network/discovery/DiscoveryListener.java b/src/ru/olamedia/olacraft/network/discovery/DiscoveryListener.java
new file mode 100644
index 0000000..81c1019
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/discovery/DiscoveryListener.java
@@ -0,0 +1,9 @@
+package ru.olamedia.olacraft.network.discovery;
+
+import java.net.InetAddress;
+
+public class DiscoveryListener {
+ public void onHost(InetAddress address){
+
+ }
+}
diff --git a/src/ru/olamedia/olacraft/network/discovery/DiscoveryThread.java b/src/ru/olamedia/olacraft/network/discovery/DiscoveryThread.java
new file mode 100644
index 0000000..a6302fa
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/discovery/DiscoveryThread.java
@@ -0,0 +1,91 @@
+package ru.olamedia.olacraft.network.discovery;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.SocketException;
+import java.net.SocketTimeoutException;
+import java.net.UnknownHostException;
+
+public class DiscoveryThread extends Thread {
+ public DiscoveryThread() {
+ super();
+ try {
+ socket = new DatagramSocket(port, InetAddress.getByName("0.0.0.0"));
+ socket.setBroadcast(true);
+ socket.setSoTimeout(1000);
+ } catch (SocketException e) {
+ e.printStackTrace();
+ } catch (UnknownHostException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public DiscoveryThread(String name) {
+ this();
+ setName(name);
+ }
+
+ private DatagramSocket socket;
+ public static int port = 26003;
+
+ @Override
+ public void run() {
+ try {
+ System.out.println(getClass().getName() + ">>>Ready to receive broadcast packets!");
+ while (true) {
+
+ // Receive a packet
+ byte[] recvBuf = new byte[15000];
+ DatagramPacket packet = new DatagramPacket(recvBuf, recvBuf.length);
+ try {
+ socket.receive(packet);
+
+ // Packet received
+ System.out.println(getClass().getName() + ">>>Discovery packet received from: "
+ + packet.getAddress().getHostAddress());
+ System.out.println(getClass().getName() + ">>>Packet received; data: "
+ + new String(packet.getData()));
+
+ // See if the packet holds the right command (message)
+ String message = new String(packet.getData()).trim();
+ if (message.equals("DISCOVER_OLACRAFTSERVER_REQUEST")) {
+ byte[] sendData = "DISCOVER_OLACRAFTSERVER_RESPONSE".getBytes();
+
+ // Send a response
+ DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, packet.getAddress(),
+ packet.getPort());
+ socket.send(sendPacket);
+
+ System.out.println(getClass().getName() + ">>>Sent packet to: "
+ + sendPacket.getAddress().getHostAddress());
+ }
+ } catch (SocketTimeoutException ex) {
+
+ }
+ try {
+ Thread.sleep(100);
+ } catch (IllegalMonitorStateException ex) {
+ ex.printStackTrace();
+ } catch (InterruptedException ex) {
+ socket.close();
+ Thread.currentThread().interrupt(); // very important
+ break;
+ }
+ }
+ } catch (IOException ex) {
+ socket.close();
+ }
+ }
+
+ public static DiscoveryThread getInstance() {
+ return DiscoveryThreadHolder.INSTANCE;
+ }
+
+ private static class DiscoveryThreadHolder {
+
+ private static final DiscoveryThread INSTANCE = new DiscoveryThread();
+ }
+
+}
diff --git a/src/ru/olamedia/olacraft/network/discovery/package-info.java b/src/ru/olamedia/olacraft/network/discovery/package-info.java
new file mode 100644
index 0000000..cb376c8
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/discovery/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.network.discovery; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/network/package-info.java b/src/ru/olamedia/olacraft/network/package-info.java
new file mode 100644
index 0000000..dfbaec9
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/package-info.java
@@ -0,0 +1,9 @@
+/**
+ *
+ */
+/**
+ * Used KryoNet library (Which is under BSD License)
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.network; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/network/packet/ChatMessagePacket.java b/src/ru/olamedia/olacraft/network/packet/ChatMessagePacket.java
new file mode 100644
index 0000000..332c9dd
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/packet/ChatMessagePacket.java
@@ -0,0 +1,5 @@
+package ru.olamedia.olacraft.network.packet;
+
+public class ChatMessagePacket implements IPacket {
+ public String message;
+}
diff --git a/src/ru/olamedia/olacraft/network/packet/ChunkDataPacket.java b/src/ru/olamedia/olacraft/network/packet/ChunkDataPacket.java
new file mode 100644
index 0000000..1bf92c4
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/packet/ChunkDataPacket.java
@@ -0,0 +1,10 @@
+package ru.olamedia.olacraft.network.packet;
+
+import ru.olamedia.olacraft.world.data.ChunkData;
+
+public class ChunkDataPacket implements IPacket {
+ public int chunkX;
+ public int chunkY;
+ public int chunkZ;
+ public ChunkData data;
+}
diff --git a/src/ru/olamedia/olacraft/network/packet/ConnectionPacket.java b/src/ru/olamedia/olacraft/network/packet/ConnectionPacket.java
new file mode 100644
index 0000000..ced43d5
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/packet/ConnectionPacket.java
@@ -0,0 +1,11 @@
+package ru.olamedia.olacraft.network.packet;
+
+/**
+ * Server sends connection packet with assigned connection ID on client connect
+ *
+ * @author olamedia
+ *
+ */
+public class ConnectionPacket implements IPacket{
+ public int connectionId;
+}
diff --git a/src/ru/olamedia/olacraft/network/packet/ConnectionRequestPacket.java b/src/ru/olamedia/olacraft/network/packet/ConnectionRequestPacket.java
new file mode 100644
index 0000000..419f339
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/packet/ConnectionRequestPacket.java
@@ -0,0 +1,5 @@
+package ru.olamedia.olacraft.network.packet;
+
+public class ConnectionRequestPacket implements IPacket{
+
+}
diff --git a/src/ru/olamedia/olacraft/network/packet/GetChunkDataPacket.java b/src/ru/olamedia/olacraft/network/packet/GetChunkDataPacket.java
new file mode 100644
index 0000000..492ce15
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/packet/GetChunkDataPacket.java
@@ -0,0 +1,7 @@
+package ru.olamedia.olacraft.network.packet;
+
+public class GetChunkDataPacket implements IPacket{
+ public int chunkX;
+ public int chunkY;
+ public int chunkZ;
+}
diff --git a/src/ru/olamedia/olacraft/network/packet/GetRegionPacket.java b/src/ru/olamedia/olacraft/network/packet/GetRegionPacket.java
new file mode 100644
index 0000000..2c57057
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/packet/GetRegionPacket.java
@@ -0,0 +1,15 @@
+package ru.olamedia.olacraft.network.packet;
+
+import ru.olamedia.olacraft.world.location.RegionLocation;
+
+public class GetRegionPacket implements IPacket {
+ public RegionLocation location;
+
+ public GetRegionPacket() {
+
+ }
+
+ public GetRegionPacket(RegionLocation location) {
+ this.location = location;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/network/packet/IPacket.java b/src/ru/olamedia/olacraft/network/packet/IPacket.java
new file mode 100644
index 0000000..adfa3c7
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/packet/IPacket.java
@@ -0,0 +1,5 @@
+package ru.olamedia.olacraft.network.packet;
+
+public interface IPacket {
+
+}
diff --git a/src/ru/olamedia/olacraft/network/packet/IPacketListener.java b/src/ru/olamedia/olacraft/network/packet/IPacketListener.java
new file mode 100644
index 0000000..2a17cd4
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/packet/IPacketListener.java
@@ -0,0 +1,7 @@
+package ru.olamedia.olacraft.network.packet;
+
+import com.esotericsoftware.kryonet.Connection;
+
+public interface IPacketListener {
+ public void onPacket(Connection connection, IPacket p);
+}
diff --git a/src/ru/olamedia/olacraft/network/packet/LiveEntityLocationUpdatePacket.java b/src/ru/olamedia/olacraft/network/packet/LiveEntityLocationUpdatePacket.java
new file mode 100644
index 0000000..15edfd9
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/packet/LiveEntityLocationUpdatePacket.java
@@ -0,0 +1,15 @@
+package ru.olamedia.olacraft.network.packet;
+
+/**
+ * Client sends this packet every time location changed
+ * Server fills connectionId and sends back to every connection
+ *
+ * @author olamedia
+ *
+ */
+public class LiveEntityLocationUpdatePacket implements IPacket {
+ public float x;
+ public float y;
+ public float z;
+ public int connectionId; // filled by server only
+}
diff --git a/src/ru/olamedia/olacraft/network/packet/RegionDataPacket.java b/src/ru/olamedia/olacraft/network/packet/RegionDataPacket.java
new file mode 100644
index 0000000..3a60230
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/packet/RegionDataPacket.java
@@ -0,0 +1,7 @@
+package ru.olamedia.olacraft.network.packet;
+
+import ru.olamedia.olacraft.world.data.RegionData;
+
+public class RegionDataPacket implements IPacket {
+ public RegionData data;
+}
diff --git a/src/ru/olamedia/olacraft/network/packet/SpawnPacket.java b/src/ru/olamedia/olacraft/network/packet/SpawnPacket.java
new file mode 100644
index 0000000..d25a692
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/packet/SpawnPacket.java
@@ -0,0 +1,15 @@
+package ru.olamedia.olacraft.network.packet;
+
+/**
+ * Client sends SpawnRequestPacket on connect
+ * Server fills location, connectionId and sends SpawnPacket to every connection
+ *
+ * @author olamedia
+ *
+ */
+public class SpawnPacket implements IPacket {
+ public float x;
+ public float y;
+ public float z;
+ public int connectionId; // filled by server only
+}
diff --git a/src/ru/olamedia/olacraft/network/packet/SpawnRequestPacket.java b/src/ru/olamedia/olacraft/network/packet/SpawnRequestPacket.java
new file mode 100644
index 0000000..0628272
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/packet/SpawnRequestPacket.java
@@ -0,0 +1,4 @@
+package ru.olamedia.olacraft.network.packet;
+
+public class SpawnRequestPacket implements IPacket {
+}
diff --git a/src/ru/olamedia/olacraft/network/packet/WorldInfoPacket.java b/src/ru/olamedia/olacraft/network/packet/WorldInfoPacket.java
new file mode 100644
index 0000000..9c8e1c7
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/packet/WorldInfoPacket.java
@@ -0,0 +1,15 @@
+package ru.olamedia.olacraft.network.packet;
+
+import ru.olamedia.olacraft.world.WorldInfo;
+import ru.olamedia.olacraft.world.provider.WorldProvider;
+
+public class WorldInfoPacket implements IPacket {
+ public WorldInfoPacket(){
+
+ }
+ public WorldInfoPacket(WorldProvider worldProvider) {
+ info = worldProvider.getInfo();
+ }
+
+ public WorldInfo info;
+}
diff --git a/src/ru/olamedia/olacraft/network/packet/package-info.java b/src/ru/olamedia/olacraft/network/packet/package-info.java
new file mode 100644
index 0000000..a1da5fd
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/packet/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.network.packet; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/package-info.java b/src/ru/olamedia/olacraft/package-info.java
new file mode 100644
index 0000000..0049efb
--- /dev/null
+++ b/src/ru/olamedia/olacraft/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft;
diff --git a/src/ru/olamedia/olacraft/physics/GamePhysicsWorld.java b/src/ru/olamedia/olacraft/physics/GamePhysicsWorld.java
new file mode 100644
index 0000000..dd66ef0
--- /dev/null
+++ b/src/ru/olamedia/olacraft/physics/GamePhysicsWorld.java
@@ -0,0 +1,27 @@
+package ru.olamedia.olacraft.physics;
+
+import org.ode4j.ode.DBody;
+import org.ode4j.ode.DRay;
+import org.ode4j.ode.DWorld;
+import org.ode4j.ode.OdeHelper;
+
+public class GamePhysicsWorld {
+ private DWorld world;
+
+ public GamePhysicsWorld() {
+ world = OdeHelper.createWorld();
+ world.setGravity(0, -0.98, 0);
+ }
+
+ public DWorld getWorld() {
+ return world;
+ }
+
+ public DBody createBody(){
+ return OdeHelper.createBody(world);
+ }
+
+ public DRay createRay(int length){
+ return OdeHelper.createRay(length);
+ }
+}
diff --git a/src/ru/olamedia/olacraft/physics/package-info.java b/src/ru/olamedia/olacraft/physics/package-info.java
new file mode 100644
index 0000000..6eaba10
--- /dev/null
+++ b/src/ru/olamedia/olacraft/physics/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.physics; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/picker/joglBlockPicker.java b/src/ru/olamedia/olacraft/picker/joglBlockPicker.java
new file mode 100644
index 0000000..6eb279c
--- /dev/null
+++ b/src/ru/olamedia/olacraft/picker/joglBlockPicker.java
@@ -0,0 +1,27 @@
+package ru.olamedia.olacraft.picker;
+
+import java.nio.FloatBuffer;
+
+import javax.media.opengl.GL2;
+import javax.media.opengl.GLAutoDrawable;
+
+import ru.olamedia.olacraft.world.block.Block;
+import ru.olamedia.olacraft.world.provider.ChunkProvider;
+
+public class joglBlockPicker {
+ ChunkProvider provider;
+
+ public void setChunkProvider(ChunkProvider provider) {
+ this.provider = provider;
+ }
+
+ public Block pickBlock(GLAutoDrawable drawable) {
+ GL2 gl = drawable.getGL().getGL2();
+ FloatBuffer projMatrix = FloatBuffer.allocate(16);
+ FloatBuffer modelMatrix = FloatBuffer.allocate(16);
+ gl.glGetFloatv(GL2.GL_PROJECTION, projMatrix);
+ gl.glGetFloatv(GL2.GL_MODELVIEW, modelMatrix);
+
+ return null;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/picker/package-info.java b/src/ru/olamedia/olacraft/picker/package-info.java
new file mode 100644
index 0000000..b254232
--- /dev/null
+++ b/src/ru/olamedia/olacraft/picker/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.picker; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/render/jogl/BlockRenderer.java b/src/ru/olamedia/olacraft/render/jogl/BlockRenderer.java
new file mode 100644
index 0000000..6d96403
--- /dev/null
+++ b/src/ru/olamedia/olacraft/render/jogl/BlockRenderer.java
@@ -0,0 +1,87 @@
+package ru.olamedia.olacraft.render.jogl;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GLAutoDrawable;
+
+import com.jogamp.opengl.util.texture.Texture;
+import com.jogamp.opengl.util.texture.TextureCoords;
+
+import ru.olamedia.geom.SimpleQuadMesh;
+import ru.olamedia.olacraft.world.chunk.BlockSlice;
+import ru.olamedia.texture.TextureManager;
+
+public class BlockRenderer {
+ private BlockSlice slice;
+ private SimpleQuadMesh mesh;
+
+ public BlockRenderer(BlockSlice slice) {
+ this.slice = slice;
+ }
+
+ public SimpleQuadMesh getMesh(GL glx) {
+ GL2 gl = glx.getGL2();
+ // 14739
+ SimpleQuadMesh mesh = new SimpleQuadMesh(999999);
+ mesh.useColor();
+ mesh.useTexture();
+
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER,
+ GL.GL_NEAREST_MIPMAP_NEAREST);
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER,
+ GL.GL_NEAREST_MIPMAP_NEAREST);
+ gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL2.GL_FASTEST);
+ gl.glHint(GL2.GL_LINE_SMOOTH_HINT, GL2.GL_NICEST);
+ Texture grass = TextureManager.get("texture/grass.png");
+ int tex = grass.getTextureObject(gl);
+
+ TextureCoords tc = grass.getImageTexCoords();
+ // mesh.setTextureSize(tc.right(), tc.top());
+ System.out.println(grass.getWidth() + " " + grass.getHeight() + " | "
+ + tc.left() + " " + tc.right() + " " + tc.top() + " "
+ + tc.bottom());
+ mesh.setTextureSize(grass.getWidth(), grass.getHeight());
+ for (int x = 0; x < slice.getWidth(); x++) {
+ for (int y = 0; y < slice.getHeight(); y++) {
+ for (int z = 0; z < slice.getDepth(); z++) {
+ mesh.setTranslation(x, y, z);
+ // mesh.setColor4f(0, 1, 0, 1);
+ mesh.setColor4f((float) Math.random(),
+ (float) Math.random(), (float) Math.random(), 1);
+ mesh.setGLTexture(tex);
+ if (y == 0) {
+ mesh.addBottomQuad();
+ }
+ if (y == 3) {
+ // Math.random();
+ mesh.addTopQuad();
+ }
+ if (y < 4) {
+ if (x == 0) {
+ mesh.addLeftQuad();
+ }
+ if (x == slice.getWidth() - 1) {
+ mesh.addRightQuad();
+ }
+ if (z == 0) {
+ mesh.addBackQuad();
+ }
+ if (z == slice.getDepth() - 1) {
+ mesh.addFrontQuad();
+ }
+ }
+ }
+ }
+ }
+ mesh.endMesh();
+ return mesh;
+ }
+
+ public void render(GL glx) {
+ if (null == mesh) {
+ mesh = getMesh(glx);
+ }
+ mesh.joglRender(glx);
+ }
+
+}
diff --git a/src/ru/olamedia/olacraft/render/jogl/BlockStackRenderer.java b/src/ru/olamedia/olacraft/render/jogl/BlockStackRenderer.java
new file mode 100644
index 0000000..28f07fd
--- /dev/null
+++ b/src/ru/olamedia/olacraft/render/jogl/BlockStackRenderer.java
@@ -0,0 +1,9 @@
+package ru.olamedia.olacraft.render.jogl;
+
+import javax.media.opengl.GLAutoDrawable;
+
+public class BlockStackRenderer {
+ public void render(GLAutoDrawable drawable) {
+
+ }
+}
diff --git a/src/ru/olamedia/olacraft/render/jogl/ChunkRenderer.java b/src/ru/olamedia/olacraft/render/jogl/ChunkRenderer.java
new file mode 100644
index 0000000..e24e8e9
--- /dev/null
+++ b/src/ru/olamedia/olacraft/render/jogl/ChunkRenderer.java
@@ -0,0 +1,146 @@
+package ru.olamedia.olacraft.render.jogl;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLContext;
+
+import ru.olamedia.math.Box;
+import ru.olamedia.math.Classifier;
+import ru.olamedia.olacraft.game.Game;
+import ru.olamedia.olacraft.world.chunk.BlockSlice;
+import ru.olamedia.olacraft.world.chunk.Chunk;
+import ru.olamedia.olacraft.world.chunk.ChunkMeshBulder;
+import ru.olamedia.olacraft.world.chunk.ChunkSlice;
+
+public class ChunkRenderer {
+ private BlockSlice slice;
+
+ public ChunkRenderer(BlockSlice slice) {
+ this.slice = slice;
+ }
+
+ public int visibleTop = 0;
+ public int visibleBottom = 0;
+ public int visibleLeft = 0;
+ public int visibleRight = 0;
+ public int visibleFront = 0;
+ public int visibleBack = 0;
+
+ public int frustumCulledChunks = 0;
+ public int frustumIntersectChunks = 0;
+
+ public boolean renderChunk(Chunk chunk, boolean skipnew) {
+ GL gl = GLContext.getCurrentGL();
+ if (!chunk.isAvailable()) {
+ // System.out.println("not available");
+ chunk.request();
+ return skipnew;
+ }
+ /*
+ * if (!chunk.isNeighborsAvailable()) {
+ * System.out.println("no neighbors");
+ * chunk.requestNeighbors();
+ * return;
+ * }
+ */
+ // System.out.println("available");
+ Box box = new Box(chunk.getX(), chunk.getY(), chunk.getZ(), chunk.getX() + chunk.getWidth(), chunk.getY()
+ + chunk.getHeight(), chunk.getZ() + chunk.getDepth());
+ if (Game.instance.camera.frustum.quickClassify(box) == Classifier.OUTSIDE) {
+ frustumCulledChunks++;
+ return skipnew;
+ }
+
+ // // boolean inside = true;
+ // if (Game.camera.frustum != null) {
+ // if (Game.camera.frustum.quickClassify(box) ==
+ // Classifier.Classification.OUTSIDE) {
+ // frustumCulledChunks++;
+ // return;
+ // }
+ // }
+ // } else if (Game.camera.frustum.test(box) == Classifier.INTERSECT) {
+ // inside = false;
+ // frustumIntersectChunks++;
+ // } else {
+ // frustumCulledChunks++;
+ // return;
+ // }
+ if (!chunk.isMeshCostructed) {
+ if (skipnew) {
+ return skipnew;
+ }
+ }
+ if (!chunk.isMeshCostructed) {
+ ChunkMeshBulder.instance.add(chunk);
+ if (ChunkMeshBulder.instance.isFull()) {
+ skipnew = true;
+ }
+ return skipnew;
+ }
+ if (null == chunk.getMesh()) {
+ } else {
+ chunk.getMesh().joglRender(gl);
+ }
+ return skipnew;
+ }
+
+ public void render(GLAutoDrawable drawable) {
+
+ if (!ChunkMeshBulder.instance.isAlive()) {
+ ChunkMeshBulder.instance.start();
+ }
+
+ visibleTop = 0;
+ visibleBottom = 0;
+ visibleLeft = 0;
+ visibleRight = 0;
+ visibleFront = 0;
+ visibleBack = 0;
+ frustumCulledChunks = 0;
+ boolean skipnew = false;
+ ChunkSlice cs = slice.getChunkSlice();
+ // rendering from center
+ int x, y, z;
+ int dw = cs.getWidth() / 2;
+ int dd = cs.getDepth() / 2;
+ int dh = cs.getHeight() / 2;
+ for (int dx = 0; dx < dw; dx++) {
+ x = cs.getX() + dw + dx;
+ for (int dz = 0; dz < dd; dz++) {
+ z = cs.getZ() + dd + dz;
+ for (int dy = 0; dy < dh; dy++) {
+ y = cs.getY() + dh + dy;
+ skipnew = renderChunk(cs.getChunk(x, y, z), skipnew);
+ y = cs.getY() + dh - dy - 1;
+ skipnew = renderChunk(cs.getChunk(x, y, z), skipnew);
+ }
+ z = cs.getZ() + dd - dz - 1;
+ for (int dy = 0; dy < dh; dy++) {
+ y = cs.getY() + dh + dy;
+ skipnew = renderChunk(cs.getChunk(x, y, z), skipnew);
+ y = cs.getY() + dh - dy - 1;
+ skipnew = renderChunk(cs.getChunk(x, y, z), skipnew);
+ }
+ }
+ x = cs.getX() + dw - dx - 1;
+ for (int dz = 0; dz < dd; dz++) {
+ z = cs.getZ() + dd + dz;
+ for (int dy = 0; dy < dh; dy++) {
+ y = cs.getY() + dh + dy;
+ skipnew = renderChunk(cs.getChunk(x, y, z), skipnew);
+ y = cs.getY() + dh - dy - 1;
+ skipnew = renderChunk(cs.getChunk(x, y, z), skipnew);
+ }
+ z = cs.getZ() + dd - dz - 1;
+ for (int dy = 0; dy < dh; dy++) {
+ y = cs.getY() + dh + dy;
+ skipnew = renderChunk(cs.getChunk(x, y, z), skipnew);
+ y = cs.getY() + dh - dy - 1;
+ skipnew = renderChunk(cs.getChunk(x, y, z), skipnew);
+ }
+ }
+ }
+ // System.out.println("visible top " + visibleTop);
+ }
+}
diff --git a/src/ru/olamedia/olacraft/render/jogl/DefaultRenderer.java b/src/ru/olamedia/olacraft/render/jogl/DefaultRenderer.java
new file mode 100644
index 0000000..12c12e0
--- /dev/null
+++ b/src/ru/olamedia/olacraft/render/jogl/DefaultRenderer.java
@@ -0,0 +1,75 @@
+package ru.olamedia.olacraft.render.jogl;
+
+import com.jogamp.newt.event.KeyEvent;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.glu.GLU;
+
+import ru.olamedia.input.KeyListener;
+import ru.olamedia.input.Keyboard;
+import ru.olamedia.input.MouseJail;
+import ru.olamedia.input.MouseListener;
+import ru.olamedia.olacraft.game.Game;
+
+public class DefaultRenderer implements IRenderer, KeyListener, MouseListener {
+ private boolean isHUDEnabled = true;
+ GLU glu = new GLU();
+ // private static Color BLACK_TRANSPARENT = new Color(0, 0, 0, 0);
+ long lastHUD = System.nanoTime();
+
+ public DefaultRenderer() {
+ Keyboard.attach(this);
+ MouseJail.attach(this);
+ }
+
+ @Override
+ public void render(GLAutoDrawable drawable) {
+ Game.client.getScene().tick();
+ Game.client.getScene().render(drawable);
+ }
+
+ @Override
+ public void onKeyPressed(String name, KeyEvent e) {
+
+ }
+
+ @Override
+ public void onKeyReleased(String name, KeyEvent e) {
+ // System.out.println(name);
+ if (name == "toggleHUD") {
+ isHUDEnabled = !isHUDEnabled;
+ }
+ if (name == "captureMouse") {
+ MouseJail.setActive(true);
+ }
+ if (name == "releaseMouse") {
+ MouseJail.setActive(false);
+ }
+ if (name == "toggleFrustum") {
+ Game.instance.camera.isFrustumVisible = !Game.instance.camera.isFrustumVisible;
+ }
+ if (name == "toggleRenderDistance") {
+ int renderDistance = Game.client.getScene().getRenderDistance();
+ renderDistance *= 2;
+ if (renderDistance > 256) {
+ renderDistance = 32;
+ }
+ Game.client.getScene().setRenderDistance(renderDistance);
+ }
+ }
+
+ @Override
+ public void onMouseMove(float dx, float dy) {
+ Game.instance.camera.mouseMoved(dx, dy);
+ }
+
+ @Override
+ public void onMouseClick() {
+ Game.instance.player.onMouseClick();
+ }
+
+ @Override
+ public void init(GLAutoDrawable drawable) {
+
+ }
+}
diff --git a/src/ru/olamedia/olacraft/render/jogl/IRenderer.java b/src/ru/olamedia/olacraft/render/jogl/IRenderer.java
new file mode 100644
index 0000000..1ba581a
--- /dev/null
+++ b/src/ru/olamedia/olacraft/render/jogl/IRenderer.java
@@ -0,0 +1,8 @@
+package ru.olamedia.olacraft.render.jogl;
+
+import javax.media.opengl.GLAutoDrawable;
+
+public interface IRenderer {
+ public void render(GLAutoDrawable drawable);
+ public void init(GLAutoDrawable drawable);
+}
diff --git a/src/ru/olamedia/olacraft/render/jogl/InventoryRenderer.java b/src/ru/olamedia/olacraft/render/jogl/InventoryRenderer.java
new file mode 100644
index 0000000..46daa4a
--- /dev/null
+++ b/src/ru/olamedia/olacraft/render/jogl/InventoryRenderer.java
@@ -0,0 +1,87 @@
+package ru.olamedia.olacraft.render.jogl;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GLAutoDrawable;
+
+import com.jogamp.opengl.util.texture.Texture;
+
+import ru.olamedia.olacraft.inventory.Inventory;
+import ru.olamedia.olacraft.world.blockStack.BlockStack;
+import ru.olamedia.olacraft.world.blockTypes.EmptyBlockType;
+import ru.olamedia.texture.TextureManager;
+
+public class InventoryRenderer {
+ private Inventory inventory;
+ private BlockStackRenderer stackRenderer;
+
+ int stackSize = 32;
+ int spacing = 2;
+ int padding = 2;
+ int x;
+ int y;
+
+ public InventoryRenderer(Inventory inventory) {
+ this.inventory = inventory;
+ stackRenderer = new BlockStackRenderer();
+ }
+
+ public void render(GLAutoDrawable drawable) {
+ GL2 gl = drawable.getGL().getGL2();
+ gl.glPushAttrib(GL2.GL_ALL_ATTRIB_BITS);
+ int vWidth = drawable.getWidth();
+ int vHeight = drawable.getHeight();
+ // Draw GUI
+
+ int width = stackSize * Inventory.BIND_NUM + spacing * (Inventory.BIND_NUM - 1) + padding * 2;
+ int height = stackSize + padding * 2;
+ x = (vWidth - width) / 2;
+ y = (vHeight - height) - 10;
+ gl.glRecti(x, y, x + width, y + height);
+ // Draw stacks
+ gl.glEnable(GL2.GL_TEXTURE_2D);
+ for (int i = 0; i < Inventory.BIND_NUM; i++) {
+ renderStack(i, drawable);
+ }
+ gl.glPopAttrib();
+ }
+
+ public void renderStack(int i, GLAutoDrawable drawable) {
+ GL2 gl = drawable.getGL().getGL2();
+ BlockStack stack = inventory.binded[i];
+ int sx = x + padding + stackSize * i + spacing * i;
+ int sy = y + padding;
+ if (null != stack && !(stack.block.getType() instanceof EmptyBlockType)) {
+ Texture tex = TextureManager.get(stack.block.getType().getStackTextureFile());
+ if (null != tex) {
+ tex.bind(gl);
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST_MIPMAP_NEAREST);
+ gl.glColor3f(1, 1, 1);
+ int x1 = sx;
+ int x2 = sx + stackSize;
+ int y1 = sy;
+ int y2 = sy + stackSize;
+ gl.glBegin(GL2.GL_QUADS);
+ {
+ gl.glTexCoord2f(0, 0);
+ gl.glVertex2f(x1, y1);
+ gl.glTexCoord2f(0, 1);
+ gl.glVertex2f(x1, y2);
+ gl.glTexCoord2f(1, 1);
+ gl.glVertex2f(x2, y2);
+ gl.glTexCoord2f(1, 0);
+ gl.glVertex2f(x2, y1);
+ }
+ gl.glEnd();
+ // gl.glRecti(sx, sy, sx + stackSize, sy + stackSize);
+ }
+ } else {
+ gl.glDisable(GL2.GL_TEXTURE_2D);
+ float gray = 0.5f;
+ gl.glColor3f(gray, gray, gray);
+ gl.glRecti(sx, sy, sx + stackSize, sy + stackSize);
+ gl.glEnable(GL2.GL_TEXTURE_2D);
+ }
+ }
+}
diff --git a/src/ru/olamedia/olacraft/render/jogl/PlaneRenderer.java b/src/ru/olamedia/olacraft/render/jogl/PlaneRenderer.java
new file mode 100644
index 0000000..754a093
--- /dev/null
+++ b/src/ru/olamedia/olacraft/render/jogl/PlaneRenderer.java
@@ -0,0 +1,102 @@
+package ru.olamedia.olacraft.render.jogl;
+
+import javax.media.opengl.GL2;
+import javax.media.opengl.GLAutoDrawable;
+
+import ru.olamedia.math.Plane;
+
+public class PlaneRenderer {
+ private static float getZ(Plane p, float x, float y) {
+ return -(p.n.x * x + p.n.y * y + p.d) / p.n.z;
+ }
+
+ private static float getY(Plane p, float x, float z) {
+ return -(p.n.x * x + p.n.z * z + p.d) / p.n.y;
+ }
+
+ private static float getX(Plane p, float y, float z) {
+ return -(p.n.y * y + p.n.z * z + p.d) / p.n.x;
+ }
+
+ public static void render(Plane p, GLAutoDrawable drawable) {
+ GL2 gl = drawable.getGL().getGL2();
+ float size = 100;
+ float step = size / 5;
+ for (float x = -size; x <= size; x += step) {
+ for (float y = -size; y <= size; y += step) {
+ // nx * x + ny * y + nz * z + d = 0
+ // (z = nx * x + ny * y + d) / nz
+ float z = getZ(p, x, y);
+ float x2 = x + step;
+ float y2 = y;
+ float z2 = getZ(p, x2, y2);
+ float x3 = x + step;
+ float y3 = y + step;
+ float z3 = getZ(p, x3, y3);
+ float x4 = x;
+ float y4 = y + step;
+ float z4 = getZ(p, x4, y4);
+ gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_LINE);
+ gl.glBegin(GL2.GL_QUADS);
+ {
+ gl.glVertex3f(x, y, z);
+ gl.glVertex3f(x2, y2, z2);
+ gl.glVertex3f(x3, y3, z3);
+ gl.glVertex3f(x4, y4, z4);
+ }
+ gl.glEnd();
+ }
+ }
+ for (float x = -size; x <= size; x += step) {
+ for (float z = -size; z <= size; z += step) {
+ // nx * x + ny * y + nz * z + d = 0
+ // (z = nx * x + ny * y + d) / nz
+ float y = getY(p, x, z);
+ float x2 = x + step;
+ float z2 = z;
+ float y2 = getY(p, x2, z2);
+ float x3 = x + step;
+ float z3 = z + step;
+ float y3 = getY(p, x3, z3);
+ float x4 = x;
+ float z4 = z + step;
+ float y4 = getY(p, x4, z4);
+ gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_LINE);
+ gl.glBegin(GL2.GL_QUADS);
+ {
+ gl.glVertex3f(x, y, z);
+ gl.glVertex3f(x2, y2, z2);
+ gl.glVertex3f(x3, y3, z3);
+ gl.glVertex3f(x4, y4, z4);
+ }
+ gl.glEnd();
+ }
+ }
+
+ for (float y = -size; y <= size; y += step) {
+ for (float z = -size; z <= size; z += step) {
+ // nx * x + ny * y + nz * z + d = 0
+ // (z = nx * x + ny * y + d) / nz
+ float x = getX(p, y, z);
+ float y2 = y + step;
+ float z2 = z;
+ float x2 = getX(p, y2, z2);
+ float y3 = y + step;
+ float z3 = z + step;
+ float x3 = getX(p, y3, z3);
+ float y4 = y;
+ float z4 = z + step;
+ float x4 = getX(p, y4, z4);
+ gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_LINE);
+ gl.glBegin(GL2.GL_QUADS);
+ {
+ gl.glVertex3f(x, y, z);
+ gl.glVertex3f(x2, y2, z2);
+ gl.glVertex3f(x3, y3, z3);
+ gl.glVertex3f(x4, y4, z4);
+ }
+ gl.glEnd();
+ }
+ }
+ }
+}
diff --git a/src/ru/olamedia/olacraft/render/jogl/VectorRenderer.java b/src/ru/olamedia/olacraft/render/jogl/VectorRenderer.java
new file mode 100644
index 0000000..180ec2a
--- /dev/null
+++ b/src/ru/olamedia/olacraft/render/jogl/VectorRenderer.java
@@ -0,0 +1,20 @@
+package ru.olamedia.olacraft.render.jogl;
+
+import javax.media.opengl.GL2;
+import javax.media.opengl.GLAutoDrawable;
+
+import ru.olamedia.math.Vector3f;
+
+public class VectorRenderer {
+ public static void render(Vector3f point, Vector3f v, GLAutoDrawable drawable) {
+ GL2 gl = drawable.getGL().getGL2();
+ gl.glDisable(GL2.GL_TEXTURE_2D);
+ gl.glColor3f(1, 0, 0);
+ gl.glBegin(GL2.GL_LINES);
+ {
+ gl.glVertex3f(point.x, point.y, point.z);
+ gl.glVertex3f(point.x + v.x, point.y + v.y, point.z + v.z);
+ }
+ gl.glEnd();
+ }
+}
diff --git a/src/ru/olamedia/olacraft/render/jogl/joglViewport.java b/src/ru/olamedia/olacraft/render/jogl/joglViewport.java
new file mode 100644
index 0000000..b3da2ce
--- /dev/null
+++ b/src/ru/olamedia/olacraft/render/jogl/joglViewport.java
@@ -0,0 +1,24 @@
+package ru.olamedia.olacraft.render.jogl;
+
+import java.awt.Font;
+
+import javax.media.opengl.GLAutoDrawable;
+
+import com.jogamp.opengl.util.awt.TextRenderer;
+
+public class joglViewport {
+ private GLAutoDrawable drawable;
+ private TextRenderer sans11;
+
+ public joglViewport(GLAutoDrawable drawable) {
+ this.drawable = drawable;
+ sans11 = new TextRenderer(new Font("SansSerif", Font.PLAIN, 11));
+ }
+
+ public void drawText(String text, int x, int y) {
+ sans11.setColor(1, 1, 1, 0.7f);
+ sans11.beginRendering(drawable.getWidth(), drawable.getHeight());
+ sans11.draw(text, x, y);
+ sans11.endRendering();
+ }
+}
diff --git a/src/ru/olamedia/olacraft/render/jogl/package-info.java b/src/ru/olamedia/olacraft/render/jogl/package-info.java
new file mode 100644
index 0000000..73b0ace
--- /dev/null
+++ b/src/ru/olamedia/olacraft/render/jogl/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.render.jogl; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/scene/GameScene.java b/src/ru/olamedia/olacraft/scene/GameScene.java
new file mode 100644
index 0000000..618e270
--- /dev/null
+++ b/src/ru/olamedia/olacraft/scene/GameScene.java
@@ -0,0 +1,252 @@
+package ru.olamedia.olacraft.scene;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryUsage;
+import java.util.HashMap;
+
+import javax.media.opengl.GL2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.glu.GLU;
+import javax.media.opengl.glu.GLUquadric;
+
+import org.ode4j.ode.DBody;
+
+import com.jogamp.opengl.util.PMVMatrix;
+
+import ru.olamedia.Options;
+import ru.olamedia.liveEntity.LiveEntity;
+import ru.olamedia.olacraft.game.Game;
+import ru.olamedia.olacraft.physics.GamePhysicsWorld;
+import ru.olamedia.olacraft.render.jogl.ChunkRenderer;
+import ru.olamedia.olacraft.render.jogl.InventoryRenderer;
+import ru.olamedia.olacraft.render.jogl.joglViewport;
+import ru.olamedia.olacraft.weapon.Bullet;
+import ru.olamedia.olacraft.weapon.BulletScene;
+import ru.olamedia.olacraft.world.blockTypes.AbstractBlockType;
+import ru.olamedia.olacraft.world.blockTypes.GrassBlockType;
+import ru.olamedia.olacraft.world.chunk.BlockSlice;
+import ru.olamedia.olacraft.world.provider.WorldProvider;
+import ru.olamedia.player.Player;
+import ru.olamedia.vbo.VBO;
+
+public class GameScene {
+
+ private PMVMatrix matrix;
+
+ private HashMap<Integer, LiveEntity> liveEntities = new HashMap<Integer, LiveEntity>();
+ WorldProvider provider;
+ private int renderDistance = Options.renderDistance;
+ private joglViewport viewport;
+ private BulletScene bullets = new BulletScene();
+ private GamePhysicsWorld physics = new GamePhysicsWorld();
+
+ private VBO testObject;
+
+ private boolean isInitialized = false;
+ BlockSlice viewSlice;
+
+ public GameScene(WorldProvider provider) {
+ this.provider = provider;
+ setRenderDistance(renderDistance);
+ }
+
+ public void addBullet(Bullet b) {
+ bullets.add(b);
+ DBody body = physics.createBody();
+ body.setPosition(b.location.x, b.location.y, b.location.z);
+ body.setLinearVel(b.velocity.x, b.velocity.y, b.velocity.z);
+ /*
+ * DMass mass = OdeHelper.createMass();
+ * mass.setMass(10);
+ * mass.setI(OdeHelper.c);
+ * body.setMass(mass);
+ */
+ b.body = body;
+ }
+
+ public int getBulletsCount() {
+ return bullets.getCount();
+ }
+
+ public void init(GLAutoDrawable drawable) {
+ if (isInitialized) {
+ return;
+ }
+ isInitialized = true;
+ registerTextures();
+ viewport = new joglViewport(drawable);
+ testObject = new VBO(drawable);
+ }
+
+ private void registerTextures() {
+ AbstractBlockType t;
+ t = new GrassBlockType();
+ t.register();
+ }
+
+ /**
+ * @return the renderDistance
+ */
+ public int getRenderDistance() {
+ return renderDistance;
+ }
+
+ /**
+ * @param renderDistance
+ * the renderDistance to set
+ */
+ public void setRenderDistance(int renderDistance) {
+ this.renderDistance = renderDistance;
+ viewSlice = new BlockSlice(provider, renderDistance, renderDistance * 2, renderDistance);
+ blockRenderer = new ChunkRenderer(viewSlice);
+ }
+
+ ChunkRenderer blockRenderer = new ChunkRenderer(viewSlice);
+ GLU glu = new GLU();
+
+ public void registerLiveEntity(LiveEntity entity) {
+ // liveEntityIncrement++;
+ // entity.setId(liveEntityIncrement);
+ liveEntities.put(entity.getConnectionId(), entity);
+ }
+
+ private InventoryRenderer inventoryRenderer;
+
+ private Player player;
+
+ public void registerPlayer(LiveEntity player) {
+ inventoryRenderer = new InventoryRenderer(player.getInventory());
+ this.player = (Player) player;
+ }
+
+ public LiveEntity getLiveEntity(int connectionId) {
+ if (liveEntities.containsKey(connectionId)) {
+ return liveEntities.get(connectionId);
+ }
+ return null;
+ }
+
+ public HashMap<Integer, LiveEntity> getLiveEntities() {
+ return liveEntities;
+ }
+
+ public void tick() {
+ Game.instance.tick();
+ float aspect = Game.Display.getAspect();
+ Game.instance.camera.setAspect(aspect);
+ // bullets.update(Game.instance.getDelta());
+ physics.getWorld().step(Game.instance.getDelta());
+ }
+
+ public void render(GLAutoDrawable drawable) {
+ if (!Game.instance.isRunning()) {
+ // not running, just clear screen
+ GL2 gl = drawable.getGL().getGL2();
+ gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
+ gl.glClearColor(49f / 255f, 49f / 255f, 49f / 255f, 1);
+ return;
+ }
+ init(drawable);
+ GL2 gl = drawable.getGL().getGL2();
+ gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
+ gl.glClearColor(49f / 255f, 119f / 255f, 243f / 255f, 1);
+ // GOING 3D
+ gl.glPushMatrix();
+ Game.instance.camera.setUp(drawable);
+ viewSlice.setCenter((int) Game.instance.camera.getX(), (int) Game.instance.camera.getY(),
+ (int) Game.instance.camera.getZ());
+ // RENDER BLOCKS
+ gl.glPushAttrib(GL2.GL_ALL_ATTRIB_BITS);
+ gl.glColor4f(0f, 1f, 0, 1);
+ gl.glEnable(GL2.GL_DEPTH_TEST);
+ gl.glShadeModel(GL2.GL_FLAT);
+ gl.glCullFace(GL2.GL_BACK);
+ // gl.glEnable(GL2.GL_FOG);
+ // gl.glFogf(GL2.GL_FOG_MODE, GL2.GL_LINEAR);
+ // gl.glFogf(GL2.GL_FOG_MODE, GL2.GL_EXP);
+ // gl.glFogf(GL2.GL_FOG_START, renderDistance / 2 - renderDistance /
+ // 10);
+ // gl.glFogf(GL2.GL_FOG_END, renderDistance / 2);
+ // gl.glFogf(GL2.GL_FOG_DENSITY, 0.002f);
+ // new float[] { 49f / 255f, 119f / 255f, 243f / 255f }
+ // gl.glFogfv(GL2.GL_FOG_COLOR, new float[] { 1, 1, 1, 0.2f }, 0);
+ blockRenderer.render(drawable);
+ gl.glPopAttrib();
+ // RENDER ANYTHING ELSE
+ gl.glPushAttrib(GL2.GL_ALL_ATTRIB_BITS);
+ GLUquadric qobj0 = glu.gluNewQuadric();
+ glu.gluQuadricDrawStyle(qobj0, GLU.GLU_FILL);
+ glu.gluQuadricNormals(qobj0, GLU.GLU_SMOOTH);
+ for (LiveEntity entity : liveEntities.values()) {
+ gl.glPushMatrix();
+ gl.glTranslatef(entity.getX(), entity.getCameraY(), entity.getZ());
+ glu.gluSphere(qobj0, 0.5f, 10, 10);
+ gl.glPopMatrix();
+ }
+ gl.glPopAttrib();
+ // bullets.render(drawable);
+ gl.glPopMatrix();
+
+ testObject.render();
+
+ // GOIND 2D
+ gl.glMatrixMode(GL2.GL_PROJECTION);
+ gl.glLoadIdentity();
+ int width = Game.Display.getWidth();
+ int height = Game.Display.getHeight();
+ glu.gluOrtho2D(0, width, height, 0);
+ gl.glMatrixMode(GL2.GL_MODELVIEW);
+ gl.glPushMatrix();
+ // renderHUD();
+ // MAP++
+ gl.glPushAttrib(GL2.GL_ALL_ATTRIB_BITS);
+ gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_FILL);
+ int msz = 100;
+ gl.glColor4f(0.3f, 0.3f, 0.3f, 0.7f);
+ gl.glRectf(width - msz - 12, 8, width - 8, msz + 12);
+ gl.glColor4f(0.9f, 0.9f, 0.9f, 1);
+ gl.glRectf(width - msz - 10, 10, width - 10, msz + 10);
+ gl.glColor4f(0.0f, 0.0f, 0.0f, 0.9f);
+ /*
+ * for (int mx = 0; mx < msz; mx++) {
+ * for (int mz = 0; mz < msz; mz++) {
+ * float h = (float) viewSlice
+ * .getHighest((int) (mx - msz / 2 + player.getX()), (int) (mz - msz / 2
+ * + player.getZ()));
+ * gl.glColor4f(h / 128, h / 128, h / 128, 1f);
+ * gl.glRectf(width - msz - 10 + mx, 10 + mz, width - msz - 10 + mx + 1,
+ * 10 + mz + 1);
+ * }
+ * }
+ */
+ // MAP--
+ // crosshair
+ gl.glColor4f(1f, 1f, 1f, 0.7f);
+ gl.glRectf(width / 2 - 1, height / 2 - 10, width / 2 + 1, height / 2 + 10); // vertical
+ gl.glRectf(width / 2 - 10, height / 2 - 1, width / 2 + 10, height / 2 + 1); // horizontal
+
+ // inventoryprivate PMVMatrix matrix;
+ if (null != inventoryRenderer) {
+ inventoryRenderer.render(drawable);
+ }
+
+ viewport.drawText("avg fps: " + (int) Game.timer.getAvgFps(), 10, height - 20);
+ viewport.drawText("fps: " + (int) Game.timer.getFps(), 10, height - 35);
+ MemoryUsage heap = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
+ viewport.drawText("mem: " + (heap.getUsed() / (1024 * 1024)) + "/" + (heap.getMax() / (1024 * 1024)), 10,
+ height - 50);
+
+ viewport.drawText("y: " + Game.instance.player.getY(), width - msz - 10, height - msz - 25);
+ viewport.drawText("x: " + Game.instance.player.getX(), width - msz - 10, height - msz - 40);
+ viewport.drawText("z: " + Game.instance.player.getZ(), width - msz - 10, height - msz - 55);
+ viewport.drawText("players: " + liveEntities.size(), width - msz - 10, height - msz - 70);
+ viewport.drawText("bullets: " + getBulletsCount(), width - msz - 10, height - msz - 95);
+ viewport.drawText("inAir: " + Game.instance.player.inAir(), width - msz - 10, height - msz - 110);
+ viewport.drawText("rdistance: " + renderDistance, width - msz - 10, height - msz - 155);
+
+ viewport.drawText("cam x: " + Game.instance.camera.getX(), width - msz - 10, height - msz - 170);
+ gl.glPopAttrib();
+ gl.glPopMatrix();
+ gl.glFlush();
+ }
+}
diff --git a/src/ru/olamedia/olacraft/scene/package-info.java b/src/ru/olamedia/olacraft/scene/package-info.java
new file mode 100644
index 0000000..660e324
--- /dev/null
+++ b/src/ru/olamedia/olacraft/scene/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.scene; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/weapon/Bullet.java b/src/ru/olamedia/olacraft/weapon/Bullet.java
new file mode 100644
index 0000000..6292bf2
--- /dev/null
+++ b/src/ru/olamedia/olacraft/weapon/Bullet.java
@@ -0,0 +1,51 @@
+package ru.olamedia.olacraft.weapon;
+
+import javax.media.opengl.GL2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.glu.GLU;
+import javax.media.opengl.glu.GLUquadric;
+import javax.vecmath.Point3f;
+import javax.vecmath.Vector3f;
+
+import org.ode4j.ode.DBody;
+
+public class Bullet {
+ public Point3f location = new Point3f();
+ public Vector3f velocity = new Vector3f();
+ public Vector3f acceleration = new Vector3f(0, -0.98f, 0);
+ public DBody body;
+ public float width = 0.05f;
+ public float height = 0.05f;
+ public float depth = 0.25f;
+ public boolean toRemove = false;
+ private static GLU glu = new GLU();
+
+ public void update(float deltams) {
+ // acceleration.set(velocity);
+ // acceleration.negate();
+ // acceleration.scale(0.1f);
+ // acceleration.y += -0.98f;
+ // velocity.x += acceleration.x * deltams;
+ // velocity.y += acceleration.y * deltams;
+ // velocity.z += acceleration.z * deltams;
+ // float step = deltams;
+ // location.x += velocity.x * deltams;
+ // location.y += velocity.y * deltams;
+ // location.z += velocity.z * deltams;
+ if (body.getPosition().get1() < 0 || body.getPosition().get1() > 100) {
+ // FIXME
+ toRemove = true;
+ }
+ }
+
+ public void render(GLAutoDrawable drawable) {
+ GL2 gl = drawable.getGL().getGL2();
+ gl.glPushMatrix();
+ gl.glTranslated(body.getPosition().get0(), body.getPosition().get1(), body.getPosition().get2());
+ GLUquadric bulletGeom = glu.gluNewQuadric();
+ glu.gluQuadricDrawStyle(bulletGeom, GLU.GLU_FILL);
+ glu.gluQuadricNormals(bulletGeom, GLU.GLU_SMOOTH);
+ glu.gluDisk(bulletGeom, 0.3, 0.4, 5, 5);
+ gl.glPopMatrix();
+ }
+}
diff --git a/src/ru/olamedia/olacraft/weapon/BulletScene.java b/src/ru/olamedia/olacraft/weapon/BulletScene.java
new file mode 100644
index 0000000..1e5ea05
--- /dev/null
+++ b/src/ru/olamedia/olacraft/weapon/BulletScene.java
@@ -0,0 +1,35 @@
+package ru.olamedia.olacraft.weapon;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.media.opengl.GLAutoDrawable;
+
+public class BulletScene {
+ private List<Bullet> bullets = new ArrayList<Bullet>();
+
+ public void add(Bullet b) {
+ bullets.add(b);
+ }
+
+ public int getCount(){
+ return bullets.size();
+ }
+
+ public void update(float deltas) {
+ for (int i = 0; i < bullets.size(); i++) {
+ Bullet b = bullets.get(i);
+ b.update(deltas);
+ if (b.toRemove) {
+ bullets.remove(b);
+ i--;
+ }
+ }
+ }
+
+ public void render(GLAutoDrawable drawable) {
+ for (Bullet b : bullets) {
+ b.render(drawable);
+ }
+ }
+}
diff --git a/src/ru/olamedia/olacraft/weapon/package-info.java b/src/ru/olamedia/olacraft/weapon/package-info.java
new file mode 100644
index 0000000..89ca87c
--- /dev/null
+++ b/src/ru/olamedia/olacraft/weapon/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.weapon; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/world/World.java b/src/ru/olamedia/olacraft/world/World.java
new file mode 100644
index 0000000..e3d25f2
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/World.java
@@ -0,0 +1,12 @@
+package ru.olamedia.olacraft.world;
+
+import ru.olamedia.olacraft.world.block.BlockRegistry;
+import ru.olamedia.olacraft.world.blockTypes.GrassBlockType;
+
+public class World {
+ private BlockRegistry blockRegistry;
+ public void setup() {
+ blockRegistry = new BlockRegistry();
+ blockRegistry.registerBlockType(GrassBlockType.class);
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/WorldInfo.java b/src/ru/olamedia/olacraft/world/WorldInfo.java
new file mode 100644
index 0000000..797339f
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/WorldInfo.java
@@ -0,0 +1,11 @@
+package ru.olamedia.olacraft.world;
+
+import java.io.Serializable;
+
+public class WorldInfo implements Serializable {
+ private static final long serialVersionUID = -3669317489158639456L;
+ public String name = "world";
+ public int minHeight = -128;
+ public int maxHeight = 127;
+ public float gravity = 9.81f;
+}
diff --git a/src/ru/olamedia/olacraft/world/block/Block.java b/src/ru/olamedia/olacraft/world/block/Block.java
new file mode 100644
index 0000000..a48c9df
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/block/Block.java
@@ -0,0 +1,111 @@
+package ru.olamedia.olacraft.world.block;
+
+import ru.olamedia.olacraft.world.blockTypes.BlockType;
+import ru.olamedia.olacraft.world.blockTypes.EmptyBlockType;
+import ru.olamedia.olacraft.world.provider.WorldProvider;
+
+public class Block {
+ private WorldProvider provider;
+ private int x;
+ private int y;
+ private int z;
+
+ /**
+ * Inventory block
+ */
+ public Block() {
+ this.provider = null;
+ this.x = 0;
+ this.y = 0;
+ this.z = 0;
+ }
+
+ public void putIntoWorld(WorldProvider worldProvider, int x, int y, int z) {
+ this.provider = worldProvider;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public Block(WorldProvider worldProvider, int x, int y, int z) {
+ putIntoWorld(worldProvider, x, y, z);
+ }
+
+ /**
+ * @return the x
+ */
+ public int getX() {
+ return x;
+ }
+
+ /**
+ * @param x
+ * the x to set
+ */
+ public void setX(int x) {
+ this.x = x;
+ }
+
+ /**
+ * @return the y
+ */
+ public int getY() {
+ return y;
+ }
+
+ /**
+ * @param y
+ * the y to set
+ */
+ public void setY(int y) {
+ this.y = y;
+ }
+
+ /**
+ * @return the z
+ */
+ public int getZ() {
+ return z;
+ }
+
+ /**
+ * @param z
+ * the z to set
+ */
+ public void setZ(int z) {
+ this.z = z;
+ }
+
+ public boolean isEmpty() {
+ return provider.isEmptyBlock(x, y, z);
+ }
+
+ public Block getNeighbor(int dx, int dy, int dz) {
+ return new Block(provider, x + dx, y + dy, z + dz);
+ }
+
+ public Block[] getNeighbors() {
+ return new Block[] {
+ //
+ getNeighbor(1, 0, 0),//
+ getNeighbor(0, 1, 0),//
+ getNeighbor(0, 0, 1),//
+ getNeighbor(-1, 0, 0),//
+ getNeighbor(0, -1, 0),//
+ getNeighbor(0, 0, -1),//
+ };
+ }
+
+ private BlockType type;
+
+ public void setType(BlockType type) {
+ this.type = type;
+ }
+
+ public BlockType getType() {
+ if (null == type) {
+ type = new EmptyBlockType();
+ }
+ return type;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/block/BlockRegistry.java b/src/ru/olamedia/olacraft/world/block/BlockRegistry.java
new file mode 100644
index 0000000..19ccc94
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/block/BlockRegistry.java
@@ -0,0 +1,46 @@
+package ru.olamedia.olacraft.world.block;
+
+import java.util.HashMap;
+
+import ru.olamedia.olacraft.world.blockTypes.BlockType;
+
+public class BlockRegistry {
+
+ private HashMap<Integer, String> names = new HashMap<Integer, String>();
+ private HashMap<Integer, BlockType> types = new HashMap<Integer, BlockType>();
+ private int autoincrement = 0;
+
+ private BlockRegistry worldRegistry;
+
+ public BlockRegistry() {
+ }
+
+ public BlockType getBlockType(int id) {
+ return types.get(id);
+ }
+
+ public String getBlockHumanId(int id) {
+ return names.get(id);
+ }
+
+ public int registerBlockType(@SuppressWarnings("rawtypes") Class type) {
+ if (type.isInstance(BlockType.class)) {
+ autoincrement++;
+ int id = autoincrement;
+ String classId = type.getName();
+ names.put(id, classId);
+ // types.put(id, type);
+ return autoincrement;
+ }
+ return 0;
+ }
+
+ public BlockRegistry getWorldRegistry() {
+ return worldRegistry;
+ }
+
+ public void setWorldRegistry(BlockRegistry worldRegistry) {
+ this.worldRegistry = worldRegistry;
+ }
+
+}
diff --git a/src/ru/olamedia/olacraft/world/block/package-info.java b/src/ru/olamedia/olacraft/world/block/package-info.java
new file mode 100644
index 0000000..0924926
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/block/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.world.block; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/world/blockStack/BlockStack.java b/src/ru/olamedia/olacraft/world/blockStack/BlockStack.java
new file mode 100644
index 0000000..57258ef
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockStack/BlockStack.java
@@ -0,0 +1,63 @@
+package ru.olamedia.olacraft.world.blockStack;
+
+import ru.olamedia.olacraft.world.block.Block;
+
+public class BlockStack {
+ public Block block;
+ public int count;
+
+ public BlockStack(Block block, int count) {
+ this.block = block;
+ this.count = count;
+ }
+
+ public BlockStack get() {
+ return get(1);
+ }
+
+ public BlockStack get(int getcount) {
+ int c = 0;
+ if (count >= getcount) {
+ c = getcount;
+ count -= getcount;
+ } else {
+ c = count;
+ count = 0;
+ }
+ return new BlockStack(block, c);
+ }
+
+ public BlockStack getAll() {
+ int c = count;
+ count = 0;
+ return new BlockStack(block, c);
+ }
+
+ /**
+ *
+ * @return Remaining BlockStack
+ */
+ public BlockStack putStack(BlockStack stack) {
+
+ if (block.getType() == stack.block.getType()) {
+ int max = block.getType().getMaxStack();
+ // Stack
+ int total = count + stack.count;
+ if (total < max) {
+ count = total;
+ return new BlockStack(block, 0);
+ } else {
+ BlockStack remains = new BlockStack(block, total - max);
+ count = max;
+ return remains;
+ }
+ } else {
+ // Replace
+ BlockStack remains = new BlockStack(block, count);
+ block = stack.block;
+ count = stack.count;
+ return remains;
+ }
+ }
+
+}
diff --git a/src/ru/olamedia/olacraft/world/blockStack/package-info.java b/src/ru/olamedia/olacraft/world/blockStack/package-info.java
new file mode 100644
index 0000000..933dc87
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockStack/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.world.blockStack; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/AbstractBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/AbstractBlockType.java
new file mode 100644
index 0000000..6e2a86f
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockTypes/AbstractBlockType.java
@@ -0,0 +1,86 @@
+package ru.olamedia.olacraft.world.blockTypes;
+
+import com.jogamp.opengl.util.texture.Texture;
+
+import ru.olamedia.texture.TextureManager;
+
+public abstract class AbstractBlockType implements BlockType {
+
+ @Override
+ abstract public String getName();
+
+ @Override
+ public int getMaxStack() {
+ return 64;
+ }
+
+ @Override
+ abstract public String getStackTextureFile();
+
+ @Override
+ abstract public String getTopTextureFile();
+
+ @Override
+ public String getBottomTextureFile() {
+ return this.getTopTextureFile();
+ }
+
+ @Override
+ public String getLeftTextureFile() {
+ return this.getFrontTextureFile();
+ }
+
+ @Override
+ public String getRightTextureFile() {
+ return this.getFrontTextureFile();
+ }
+
+ @Override
+ public String getFrontTextureFile() {
+ return this.getTopTextureFile();
+ }
+
+ @Override
+ public String getBackTextureFile() {
+ return this.getFrontTextureFile();
+ }
+
+ @Override
+ public Texture getTopTexture() {
+ return TextureManager.get(this.getTopTextureFile());
+ }
+
+ @Override
+ public Texture getBottomTexture() {
+ return TextureManager.get(this.getBottomTextureFile());
+ }
+
+ @Override
+ public Texture getLeftTexture() {
+ return TextureManager.get(this.getLeftTextureFile());
+ }
+
+ @Override
+ public Texture getRightTexture() {
+ return TextureManager.get(this.getRightTextureFile());
+ }
+
+ @Override
+ public Texture getFrontTexture() {
+ return TextureManager.get(this.getFrontTextureFile());
+ }
+
+ @Override
+ public Texture getBackTexture() {
+ return TextureManager.get(this.getBackTextureFile());
+ }
+
+ public void register(){
+ getBackTexture();
+ getBottomTexture();
+ getFrontTexture();
+ getLeftTexture();
+ getRightTexture();
+ getTopTexture();
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/BlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/BlockType.java
new file mode 100644
index 0000000..0bda2eb
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockTypes/BlockType.java
@@ -0,0 +1,21 @@
+package ru.olamedia.olacraft.world.blockTypes;
+
+import com.jogamp.opengl.util.texture.Texture;
+
+public interface BlockType {
+ public String getName();
+ public int getMaxStack();
+ public String getStackTextureFile();
+ public String getTopTextureFile();
+ public String getBottomTextureFile();
+ public String getLeftTextureFile();
+ public String getRightTextureFile();
+ public String getFrontTextureFile();
+ public String getBackTextureFile();
+ public Texture getTopTexture();
+ public Texture getBottomTexture();
+ public Texture getLeftTexture();
+ public Texture getRightTexture();
+ public Texture getFrontTexture();
+ public Texture getBackTexture();
+}
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/EmptyBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/EmptyBlockType.java
new file mode 100644
index 0000000..4073356
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockTypes/EmptyBlockType.java
@@ -0,0 +1,23 @@
+package ru.olamedia.olacraft.world.blockTypes;
+
+public class EmptyBlockType extends AbstractBlockType {
+ @Override
+ public String getName() {
+ return "";
+ }
+
+ @Override
+ public int getMaxStack() {
+ return 64;
+ }
+
+ @Override
+ public String getStackTextureFile() {
+ return "texture/empty.png";
+ }
+
+ @Override
+ public String getTopTextureFile() {
+ return "texture/empty.png";
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/GrassBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/GrassBlockType.java
new file mode 100644
index 0000000..816b283
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockTypes/GrassBlockType.java
@@ -0,0 +1,28 @@
+package ru.olamedia.olacraft.world.blockTypes;
+
+public class GrassBlockType extends AbstractBlockType {
+ @Override
+ public String getName() {
+ return "Grass";
+ }
+
+ @Override
+ public int getMaxStack() {
+ return 64;
+ }
+
+ @Override
+ public String getStackTextureFile() {
+ return "texture/terrain-grassdarkgreen.png";
+ }
+
+ @Override
+ public String getTopTextureFile() {
+ return "texture/terrain-grassdarkgreen.png";
+ }
+
+ @Override
+ public String getFrontTextureFile() {
+ return "texture/terrain-glong-darkgreen-dirt.png";
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/GravelBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/GravelBlockType.java
new file mode 100644
index 0000000..354d383
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockTypes/GravelBlockType.java
@@ -0,0 +1,23 @@
+package ru.olamedia.olacraft.world.blockTypes;
+
+public class GravelBlockType extends AbstractBlockType {
+ @Override
+ public String getName() {
+ return "Gravel";
+ }
+
+ @Override
+ public int getMaxStack() {
+ return 64;
+ }
+
+ @Override
+ public String getStackTextureFile() {
+ return "texture/gravel.png";
+ }
+
+ @Override
+ public String getTopTextureFile() {
+ return "texture/gravel.png";
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/package-info.java b/src/ru/olamedia/olacraft/world/blockTypes/package-info.java
new file mode 100644
index 0000000..a49dda8
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockTypes/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.world.blockTypes; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/world/chunk/BlockSlice.java b/src/ru/olamedia/olacraft/world/chunk/BlockSlice.java
new file mode 100644
index 0000000..ca4c92a
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/chunk/BlockSlice.java
@@ -0,0 +1,164 @@
+package ru.olamedia.olacraft.world.chunk;
+
+import ru.olamedia.olacraft.world.provider.WorldProvider;
+
+public class BlockSlice {
+ protected WorldProvider provider;
+ protected int leftX;
+ protected int bottomY;
+ protected int backZ;
+ protected int width;
+ protected int height;
+ protected int depth;
+
+ protected ChunkSlice chunkSlice;
+
+ // Memory leak:
+ //protected int[][] highest = new int[256][256];
+
+ public void invalidateCache(){
+ //highest = new int[256][256];
+ }
+
+/* public int getHighest(int blockX, int blockZ) {
+ if (highest[blockX - leftX][blockZ - backZ] > 0){
+ return highest[blockX - leftX][blockZ - backZ];
+ }
+ for (int y = 0; y < 128; y++) {
+ if (provider.isEmptyBlock(blockX, y, blockZ)){
+ highest[blockX - leftX][blockZ - backZ] = y;
+ return y;
+ }
+ }
+ return 0;
+ }*/
+
+ /**
+ *
+ * @param provider
+ * @param width
+ * (blocks)
+ * @param height
+ * (blocks)
+ * @param depth
+ * (blocks)
+ */
+ public BlockSlice(WorldProvider provider, int width, int height, int depth) {
+ this.provider = provider;
+ this.width = width;
+ this.height = height;
+ this.depth = depth;
+ }
+
+ public ChunkSlice getChunkSlice() {
+ if (null == chunkSlice) {
+ chunkSlice = new ChunkSlice(provider, width / 16, height / 16, depth / 16);
+ }
+ int x = Chunk.v(leftX);
+ int y = Chunk.v(bottomY);
+ int z = Chunk.v(backZ);
+ chunkSlice.setLocation(x, y, z);
+ return chunkSlice;
+ }
+
+ public int getTotalBlocks() {
+ return getWidth() * getHeight() * getDepth();
+ }
+
+ /**
+ * @return the width (blocks)
+ */
+ public int getWidth() {
+ return width;
+ }
+
+ /**
+ * @param width
+ * (blocks)
+ */
+ public void setWidth(int width) {
+ this.width = width;
+ }
+
+ /**
+ * @return the height (blocks)
+ */
+ public int getHeight() {
+ return height;
+ }
+
+ /**
+ * @param height
+ * (blocks)
+ */
+ public void setHeight(int height) {
+ this.height = height;
+ }
+
+ /**
+ * @return the depth (blocks)
+ */
+ public int getDepth() {
+ return depth;
+ }
+
+ /**
+ * @param depth
+ * (blocks)
+ */
+ public void setDepth(int depth) {
+ this.depth = depth;
+ }
+
+ /**
+ *
+ * @param x
+ * (blocks)
+ * @param y
+ * (blocks)
+ * @param z
+ * (blocks)
+ */
+ public void setLocation(int x, int y, int z) {
+ if (x != leftX || y != bottomY || z != backZ){
+ invalidateCache();
+ }
+ leftX = x;
+ bottomY = y;
+ backZ = z;
+ }
+
+ /**
+ *
+ * @param x
+ * (blocks)
+ * @param y
+ * (blocks)
+ * @param z
+ * (blocks)
+ */
+ public void setCenter(int x, int y, int z) {
+ setLocation(x - width / 2, y - height / 2, z - depth / 2);
+ }
+
+ /**
+ * @return the left x (blocks)
+ */
+ public int getX() {
+ return leftX;
+ }
+
+ /**
+ * @return the bottom y (blocks)
+ */
+ public int getY() {
+ return bottomY;
+ }
+
+ /**
+ * @return the back z (blocks)
+ */
+ public int getZ() {
+ return backZ;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/chunk/Chunk.java b/src/ru/olamedia/olacraft/world/chunk/Chunk.java
new file mode 100644
index 0000000..ca2d4bf
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/chunk/Chunk.java
@@ -0,0 +1,290 @@
+package ru.olamedia.olacraft.world.chunk;
+
+import ru.olamedia.geom.SimpleQuadMesh;
+import ru.olamedia.olacraft.world.blockTypes.GrassBlockType;
+import ru.olamedia.olacraft.world.location.BlockLocation;
+import ru.olamedia.olacraft.world.location.ChunkLocation;
+import ru.olamedia.olacraft.world.provider.WorldProvider;
+
+public class Chunk extends BlockSlice {
+ public boolean isMeshCostructed = false;
+ public SimpleQuadMesh mesh;
+
+ public int visibleTop = 0;
+ public int visibleBottom = 0;
+ public int visibleLeft = 0;
+ public int visibleRight = 0;
+ public int visibleFront = 0;
+ public int visibleBack = 0;
+
+ public Chunk(WorldProvider provider) {
+ super(provider, 16, 16, 16);
+ }
+
+ /**
+ * Convert block coordinate into chunk coordinate
+ *
+ * @param v
+ * block coordinate along one axis
+ * @return
+ */
+ public static int v(int v) {
+ if (v >= 0) {
+ return v / 16;
+ } else {
+ return (v + 1) / 16 - 1;
+ }
+ }
+
+ /**
+ * Convert block coordinate into block position inside of chunk
+ *
+ * @param v
+ * block coordinate along one axis
+ * @return
+ */
+ public static int in(int v) {
+ int tmp = v - v(v) * 16;
+ return tmp >= 0 ? tmp : 16 + tmp; // block location minus chunk base
+ // location
+ // (lower-left-back corner)
+ // if (v >= 0) {
+ // return v % 16;
+ // } else {
+ // int in = v + 1; // shift up so -1 will be 0
+ // in %= 16; // get remaining -15..0
+ // in += 15; // revert 0..15
+ // return in;
+ // }
+ }
+
+ public void setMeshColor(SimpleQuadMesh mesh, int x, int y, int z, boolean isSide) {
+ float level = 1f;// ((float) getProvider().getBlockLightLevel(x, y, z) -
+ // (isSide ? 2 : 0)) / 15.0f;
+ mesh.setColor4f(level, level, level, 1);
+ if (y < 0) {
+ mesh.setColor4f(0, 0, 1, 1);
+ } else if (y > 30) {
+ mesh.setColor4f(1, 1, 1, 1);
+ } else {
+ mesh.setColor4f(1, 1, 0, 1);
+ }
+ }
+
+ /**
+ * @return the mesh
+ */
+ public SimpleQuadMesh getMesh() {
+ if (isMeshCostructed) {
+ return mesh;
+ }
+ if (getY() > provider.getInfo().maxHeight) {
+ isMeshCostructed = true;
+ return null;
+ }
+ if (getY() < provider.getInfo().minHeight) {
+ isMeshCostructed = true;
+ return null;
+ }
+ if (null == mesh) {
+ mesh = new SimpleQuadMesh(14739); // unindexed
+ // 17x17x17
+ // vertices
+ mesh.useColor();
+ mesh.useTexture();
+ // gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL2.GL_FASTEST);
+ // gl.glHint(GL2.GL_LINE_SMOOTH_HINT, GL2.GL_NICEST);
+ GrassBlockType grass = new GrassBlockType();
+ for (int x = getX(); x < getX() + getWidth(); x++) {
+ for (int y = getY(); y < getY() + getHeight(); y++) {
+ for (int z = getZ(); z < getZ() + getDepth(); z++) {
+ //
+
+ if (!isEmptyBlock(x, y, z)) {
+ mesh.setTranslation(x, y, z);
+ // mesh.setColor4f(0, 1, 0, 1);
+ float cbase = (float) (y / 200.0) * (float) (7.0 / 10.0);
+ if (cbase > 9 / 10) {
+ cbase = (float) (9.0 / 10.0);
+ }
+ // cbase = (float) (9.0 / 10.0);
+ float cred, cgreen, cblue;
+ // cbase;
+ cred = cgreen = cblue = getLightLevel256(x, y, z);
+ if (x == 1) {
+ mesh.setColor4f(1, 0, 0, 1);
+ // red to the right
+ }
+ if (x == 0 || z == 0) {
+ if (y == 6) {
+ mesh.setColor4f(1, 0, 0, 1);
+ } else if (y % 2 == 0) {
+ mesh.setColor4f(1, 0, 1, 1);
+ } else {
+ mesh.setColor4f(1, 1, 0, 1);
+ }
+ }
+ if (z == 1) {
+ mesh.setColor4f(0, 0, 1, 1);
+ // blue to the bottom
+ }
+ if (renderBottom(x, y, z)) {
+ setMeshColor(mesh, x, y - 1, z, false);
+ mesh.setTexture(grass.getBottomTexture());
+ mesh.addBottomQuad();
+ visibleBottom++;
+ }
+ if (renderTop(x, y, z)) {
+ if (x == 15 || z == 15) {
+ // debug: show through..
+ } else {
+ setMeshColor(mesh, x, y + 1, z, false);
+ mesh.setTexture(grass.getTopTexture());
+ mesh.addTopQuad();
+ }
+ visibleTop++;
+ }
+ if (renderLeft(x, y, z)) {
+ setMeshColor(mesh, x - 1, y, z, true);
+ mesh.setTexture(grass.getLeftTexture());
+ mesh.addLeftQuad();
+ visibleLeft++;
+ }
+ if (renderRight(x, y, z)) {
+ setMeshColor(mesh, x + 1, y, z, true);
+ mesh.setTexture(grass.getRightTexture());
+ mesh.addRightQuad();
+ visibleRight++;
+ }
+ if (renderBack(x, y, z)) {
+ setMeshColor(mesh, x, y, z - 1, true);
+ mesh.setTexture(grass.getBackTexture());
+ mesh.addBackQuad();
+ visibleBack++;
+ }
+ if (renderFront(x, y, z)) {
+ setMeshColor(mesh, x, y, z + 1, true);
+ mesh.setTexture(grass.getFrontTexture());
+ mesh.addFrontQuad();
+ visibleFront++;
+ }
+ }
+ }
+ }
+ }
+ mesh.endMesh();
+ isMeshCostructed = true;
+ return null;
+ }
+ return mesh;
+ }
+
+ /**
+ * @param mesh
+ * the mesh to set
+ */
+ public void setMesh(SimpleQuadMesh mesh) {
+ this.mesh = mesh;
+ }
+
+ public boolean isEmpty() {
+ // MUST BE LOADED
+ return provider.getChunk(getBlockLocation().getChunkLocation()).isEmpty();
+ }
+
+ private BlockLocation getBlockLocation() {
+ return new BlockLocation(getX(), getY(), getZ());
+ }
+
+ public boolean isAvailable() {
+ return provider.isChunkAvailable(getBlockLocation().getChunkLocation());
+ }
+
+ public boolean isNeighborsAvailable() {
+ int x = Chunk.v(getX());
+ int y = Chunk.v(getY());
+ int z = Chunk.v(getZ());
+ return provider.isChunkAvailable(new ChunkLocation(x - 1, y, z))
+ && provider.isChunkAvailable(new ChunkLocation(x + 1, y, z))
+ && provider.isChunkAvailable(new ChunkLocation(x, y - 1, z))
+ && provider.isChunkAvailable(new ChunkLocation(x, y + 1, z))
+ && provider.isChunkAvailable(new ChunkLocation(x, y, z - 1))
+ && provider.isChunkAvailable(new ChunkLocation(x, y, z + 1));
+ }
+
+ public void requestNeighbors() {
+ int x = Chunk.v(getX());
+ int y = Chunk.v(getY());
+ int z = Chunk.v(getZ());
+ if (!provider.isChunkAvailable(new ChunkLocation(x - 1, y, z))) {
+ provider.loadChunk(new ChunkLocation(x - 1, y, z));
+ }
+ if (!provider.isChunkAvailable(new ChunkLocation(x + 1, y, z))) {
+ provider.loadChunk(new ChunkLocation(x + 1, y, z));
+ }
+ if (!provider.isChunkAvailable(new ChunkLocation(x, y - 1, z))) {
+ provider.loadChunk(new ChunkLocation(x, y - 1, z));
+ }
+ if (!provider.isChunkAvailable(new ChunkLocation(x, y + 1, z))) {
+ provider.loadChunk(new ChunkLocation(x, y + 1, z));
+ }
+ if (!provider.isChunkAvailable(new ChunkLocation(x, y, z - 1))) {
+ provider.loadChunk(new ChunkLocation(x, y, z - 1));
+ }
+ if (!provider.isChunkAvailable(new ChunkLocation(x, y, z + 1))) {
+ provider.loadChunk(new ChunkLocation(x, y, z + 1));
+ }
+ }
+
+ public void request() {
+ BlockLocation blockLocation = new BlockLocation(getX(), getY(), getZ());
+ // System.out.println("provider.requestChunk(" +
+ // blockLocation.getRegionLocation() + blockLocation.getChunkLocation()
+ // + ")");
+ provider.loadChunk(blockLocation.getChunkLocation());
+ }
+
+ // public BlockType getBlockType(int x, int y, int z) {
+ // return provider.getBlockType(int x, int y, int z);
+ // }
+
+ public boolean isEmptyBlock(int x, int y, int z) {
+ return provider.isEmptyBlock(x, y, z);
+ }
+
+ public float getLightLevel256(int x, int y, int z) {
+ return ((float) getLightLevel(x, y, z)) / 15.0f;// * 255.0f
+ }
+
+ public int getLightLevel(int x, int y, int z) {
+ return 15;
+ }
+
+ public boolean renderBottom(int x, int y, int z) {
+ return provider.renderBottom(x, y, z);
+ }
+
+ public boolean renderTop(int x, int y, int z) {
+ return provider.renderTop(x, y, z);
+ }
+
+ public boolean renderLeft(int x, int y, int z) {
+ return provider.renderLeft(x, y, z);
+ }
+
+ public boolean renderRight(int x, int y, int z) {
+ return provider.renderRight(x, y, z);
+ }
+
+ public boolean renderFront(int x, int y, int z) {
+ return provider.renderFront(x, y, z);
+ }
+
+ public boolean renderBack(int x, int y, int z) {
+ return provider.renderBack(x, y, z);
+ }
+
+ public WorldProvider getProvider() {
+ return provider;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/chunk/ChunkMeshBulder.java b/src/ru/olamedia/olacraft/world/chunk/ChunkMeshBulder.java
new file mode 100644
index 0000000..d362199
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/chunk/ChunkMeshBulder.java
@@ -0,0 +1,47 @@
+package ru.olamedia.olacraft.world.chunk;
+
+import java.util.concurrent.ArrayBlockingQueue;
+
+public class ChunkMeshBulder extends Thread {
+ public static ChunkMeshBulder instance = new ChunkMeshBulder("Mesh builder");
+ private ArrayBlockingQueue<Chunk> chunks = new ArrayBlockingQueue<Chunk>(16);
+
+ public ChunkMeshBulder(String name) {
+ super(name);
+ }
+
+ public boolean isFull() {
+ return chunks.remainingCapacity() == 0;
+ }
+
+ public void add(Chunk chunk) {
+ chunks.offer(chunk);
+ }
+
+ public void clear() {
+ chunks.clear();
+ }
+
+ public void tick() throws InterruptedException {
+ if (!chunks.isEmpty()) {
+ Chunk chunk = chunks.take();
+ chunk.getMesh();
+ }
+ }
+
+ @Override
+ public void run() {
+ // glc.makeCurrent();
+ while (true) {
+ // main loop
+ try {
+ tick();
+ // Thread.sleep(10); // or wait/join etc
+ } catch (InterruptedException ex) {
+ // cleanup here
+ Thread.currentThread().interrupt(); // for nested loops
+ break;
+ }
+ }
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/chunk/ChunkSlice.java b/src/ru/olamedia/olacraft/world/chunk/ChunkSlice.java
new file mode 100644
index 0000000..e440740
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/chunk/ChunkSlice.java
@@ -0,0 +1,114 @@
+package ru.olamedia.olacraft.world.chunk;
+
+import java.util.HashMap;
+
+import ru.olamedia.olacraft.world.provider.WorldProvider;
+
+public class ChunkSlice {
+ private WorldProvider provider;
+ private int leftX;
+ private int bottomY;
+ private int backZ;
+ private int width;
+ private int height;
+ private int depth;
+
+ public ChunkSlice(WorldProvider provider, int width, int height, int depth) {
+ this.provider = provider;
+ this.width = width;
+ this.height = height;
+ this.depth = depth;
+ }
+
+ protected HashMap<String, Chunk> chunks = new HashMap<String, Chunk>();
+
+ public Chunk getChunk(int x, int y, int z) {
+ String key = x + ";" + y + ";" + z;
+ if (chunks.containsKey(key)) {
+ return chunks.get(key);
+ } else {
+ Chunk chunk = new Chunk(provider);
+ chunk.setLocation(x * 16, y * 16, z * 16);
+ chunks.put(key, chunk);
+ return chunk;
+ }
+ }
+
+ /**
+ * @return the width
+ */
+ public int getWidth() {
+ return width;
+ }
+
+ /**
+ * @param width
+ * the width to set
+ */
+ public void setWidth(int width) {
+ this.width = width;
+ }
+
+ /**
+ * @return the height
+ */
+ public int getHeight() {
+ return height;
+ }
+
+ /**
+ * @param height
+ * the height to set
+ */
+ public void setHeight(int height) {
+ this.height = height;
+ }
+
+ /**
+ * @return the depth
+ */
+ public int getDepth() {
+ return depth;
+ }
+
+ /**
+ * @param depth
+ * the depth to set
+ */
+ public void setDepth(int depth) {
+ this.depth = depth;
+ }
+
+ public void setLocation(int x, int y, int z) {
+ leftX = x;
+ bottomY = y;
+ backZ = z;
+ }
+
+ public void setCenter(int x, int y, int z) {
+ leftX = x - width / 2;
+ bottomY = y - height / 2;
+ backZ = z - depth / 2;
+ }
+
+ /**
+ * @return the leftX
+ */
+ public int getX() {
+ return leftX;
+ }
+
+ /**
+ * @return the bottomY
+ */
+ public int getY() {
+ return bottomY;
+ }
+
+ /**
+ * @return the backZ
+ */
+ public int getZ() {
+ return backZ;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/chunk/package-info.java b/src/ru/olamedia/olacraft/world/chunk/package-info.java
new file mode 100644
index 0000000..314ea35
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/chunk/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.world.chunk; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/world/data/ChunkData.java b/src/ru/olamedia/olacraft/world/data/ChunkData.java
new file mode 100644
index 0000000..a1abc9e
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/data/ChunkData.java
@@ -0,0 +1,86 @@
+package ru.olamedia.olacraft.world.data;
+
+import java.io.Serializable;
+import java.util.BitSet;
+
+import ru.olamedia.olacraft.world.chunk.Chunk;
+import ru.olamedia.olacraft.world.location.BlockLocation;
+import ru.olamedia.olacraft.world.location.ChunkLocation;
+
+public class ChunkData implements Serializable {
+ private static final long serialVersionUID = -5704237444737895501L;
+ public ChunkLocation location;
+ public static transient int SIZE = 4096;
+ // private boolean[] notEmpty = new boolean[SIZE];
+ private BitSet emptyBlocks = new BitSet(4096);
+ public int notEmptyCount = 0;
+
+ // public transient int[] type = new int[SIZE];
+ // /public transient ChunkLightData light;
+
+ public ChunkData() {
+ // light = new ChunkLightData();
+ }
+
+ public void compact() {
+ if (notEmptyCount == 0) {
+ emptyBlocks = null;
+ }
+ }
+
+ public static int normalize(int v) {
+ int n = v;
+ if (n > 15) {
+ n = n % 16;
+ }
+ if (n < 0) {
+ n = 16 + n % 16 - 1;
+ // v = 15 - v;
+ }
+ // System.out.println("normalize(" + v + ") = " + n);
+ return n;
+ }
+
+ public static int getId(int xInsideChunk, int yInsideChunk, int zInsideChunk) {
+ xInsideChunk = normalize(xInsideChunk);
+ yInsideChunk = normalize(yInsideChunk);
+ zInsideChunk = normalize(zInsideChunk);
+ int id = xInsideChunk * 16 * 16 + yInsideChunk * 16 + zInsideChunk;
+ if (id > SIZE) {
+ System.err.println("Exception while getID(" + xInsideChunk + "," + yInsideChunk + "," + zInsideChunk + ")");
+ throw new ArrayIndexOutOfBoundsException(id);
+ }
+ return id;
+ }
+
+ public boolean isEmpty(BlockLocation blockLocation) {
+ if (notEmptyCount == 0) {
+ return true;
+ }
+ int id = getId(Chunk.in(blockLocation.x), Chunk.in(blockLocation.y), Chunk.in(blockLocation.z));
+ return isEmpty(id);
+ // return !notEmpty[id];
+ }
+
+ public boolean isEmpty(int id) {
+ if (notEmptyCount == 0) {
+ return true;
+ }
+ return emptyBlocks.get(id);
+ }
+
+ public void setEmpty(int id, boolean isEmpty) {
+ if (isEmpty(id) != isEmpty) {
+ if (!isEmpty) {
+ notEmptyCount++;
+ } else {
+ notEmptyCount--;
+ }
+ }
+ emptyBlocks.set(id, isEmpty);
+ }
+
+ public boolean isEmpty() {
+ return notEmptyCount == 0;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/data/ChunkLightData.java b/src/ru/olamedia/olacraft/world/data/ChunkLightData.java
new file mode 100644
index 0000000..f574420
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/data/ChunkLightData.java
@@ -0,0 +1,102 @@
+package ru.olamedia.olacraft.world.data;
+
+import ru.olamedia.olacraft.world.dataProvider.AbstractChunkDataProvider;
+
+/**
+ * The daylight calculated as sum of sunlight + emitted light
+ * The nightlight calculated as sum of emitted light
+ *
+ * The light at some time of a day calculated as part of daylight + part of
+ * nightlight (ex 30% of night + 70% of daylight) - sum of two array's elements
+ */
+public class ChunkLightData {
+ public static int SIZE = 4096;
+ /**
+ * Constant sunlight level
+ */
+ public byte[] sunLevel = new byte[SIZE];
+ /**
+ * Constant sunlight level
+ */
+ public byte[] emittedLevel = new byte[SIZE];
+ /**
+ * Constant light level during middle of a day
+ */
+ public byte[] daytimeLevel = new byte[SIZE];
+ /**
+ * Constant light level during midnight
+ */
+ public byte[] nighttimeLevel = new byte[SIZE];
+ public boolean isCalculated = false;
+ public boolean isSunlevelCalculated = false;
+ public byte[] level = new byte[SIZE];
+
+ public static int normalize(int v) {
+ int n = v;
+ if (n > 15) {
+ n = n % 16;
+ }
+ if (n < 0) {
+ n = 16 + n % 16 - 1;
+ // v = 15 - v;
+ }
+ // System.out.println("normalize(" + v + ") = " + n);
+ return n;
+ }
+
+ public static int getId(int xInsideChunk, int yInsideChunk, int zInsideChunk) {
+ xInsideChunk = normalize(xInsideChunk);
+ yInsideChunk = normalize(yInsideChunk);
+ zInsideChunk = normalize(zInsideChunk);
+ int id = xInsideChunk * 16 * 16 + yInsideChunk * 16 + zInsideChunk;
+ if (id > SIZE) {
+ System.err.println("Exception while getID(" + xInsideChunk + "," + yInsideChunk + "," + zInsideChunk + ")");
+ throw new ArrayIndexOutOfBoundsException(id);
+ }
+ return id;
+ }
+
+ private static byte sunlight = 15;
+
+ public void fillSunlight() {
+ // simplify: straight from top to bottom, utility to fill top layer
+ for (int x = 0; x < 16; x++) {
+ for (int z = 0; z < 16; z++) {
+ sunLevel[getId(x, 15, z)] = sunlight;
+ }
+ }
+ }
+
+ public void copySunlightFromAbove(ChunkLightData above) {
+ for (int x = 0; x < 16; x++) {
+ for (int z = 0; z < 16; z++) {
+ sunLevel[getId(x, 15, z)] = above.sunLevel[getId(x, 0, z)];
+ }
+ }
+ System.out.print("Copy sunlight");
+ }
+
+ /**
+ * Sunlight falling down until meets nonempty block from data
+ *
+ * @param data
+ */
+ public void falldownSunlight(ChunkData data) {
+ for (int x = 0; x < 16; x++) {
+ for (int z = 0; z < 16; z++) {
+ for (int y = 14; y >= 0; y--) {
+ if (!data.isEmpty(getId(x, y, z))) {
+ break;
+ } else {
+ sunLevel[getId(x, y, z)] = sunLevel[getId(x, y + 1, z)];
+ }
+ }
+ }
+ }
+ }
+
+ public void receiveNeighborLight(AbstractChunkDataProvider abstractChunkDataProvider) {
+
+ }
+
+}
diff --git a/src/ru/olamedia/olacraft/world/data/HeightMap.java b/src/ru/olamedia/olacraft/world/data/HeightMap.java
new file mode 100644
index 0000000..b2c0a63
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/data/HeightMap.java
@@ -0,0 +1,42 @@
+package ru.olamedia.olacraft.world.data;
+
+import java.io.Serializable;
+
+/**
+ * Heightmap
+ * Useful when looking for spawn location, calculating light
+ *
+ * @author olamedia
+ *
+ */
+public class HeightMap implements Serializable {
+ private static final long serialVersionUID = -6777972159522169977L;
+ public byte[][] map; // -128..127
+ public HeightMap(){
+
+ }
+ public HeightMap(int width, int height) {
+ map = new byte[width][height];
+ }
+
+ public void setHeight(int x, int y, int height) {
+ map[x][y] = (byte) height;
+ }
+
+ public int getHeight(int x, int y) {
+ return map[x][y];
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder b = new StringBuilder();
+ for (int x = 0; x < map.length; x++){
+ for (int z = 0; z < map[x].length; z++){
+ b.append(map[x][z]);
+ b.append(",");
+ }
+ b.append("\n");
+ }
+ return b.toString();
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/data/RegionData.java b/src/ru/olamedia/olacraft/world/data/RegionData.java
new file mode 100644
index 0000000..fa292d2
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/data/RegionData.java
@@ -0,0 +1,57 @@
+package ru.olamedia.olacraft.world.data;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+
+import ru.olamedia.olacraft.world.chunk.Chunk;
+import ru.olamedia.olacraft.world.location.ChunkLocation;
+import ru.olamedia.olacraft.world.location.RegionLocation;
+import ru.olamedia.olacraft.world.location.SectorLocation;
+
+/**
+ * Region is a 16x16 range of sectors. (256x256x256 blocks)
+ *
+ * @author olamedia
+ *
+ */
+public class RegionData implements Serializable {
+ private static final long serialVersionUID = 7449677895073874520L;
+ public RegionLocation location;
+ public HeightMap heightMap = new HeightMap(256, 256);
+ public SectorData[][] sectorData = new SectorData[16][16];
+
+ public void writeTo(OutputStream stream) throws IOException {
+ ObjectOutputStream out = new ObjectOutputStream(stream);
+ out.writeObject(this);
+ out.close();
+ }
+
+ public static RegionData loadFrom(InputStream stream) throws IOException, ClassNotFoundException {
+ ObjectInputStream in = new ObjectInputStream(stream);
+ RegionData data = (RegionData) in.readObject();
+ in.close();
+ return data;
+ }
+
+ public static RegionData createEmpty(RegionLocation location) {
+ RegionData data = new RegionData();
+ data.location = location;
+ return data;
+ }
+
+ public ChunkData getChunkData(ChunkLocation chunkLocation) {
+ SectorData sector = getSectorData(chunkLocation.getSectorLocation());
+ int y = Chunk.in(chunkLocation.y + 128); // minHeight = -128
+ return sector.chunkData[y];
+ }
+
+ public SectorData getSectorData(SectorLocation sectorLocation) {
+ int x = Chunk.in(sectorLocation.x);
+ int z = Chunk.in(sectorLocation.z);
+ return sectorData[x][z];
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/data/SectorData.java b/src/ru/olamedia/olacraft/world/data/SectorData.java
new file mode 100644
index 0000000..12a97cd
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/data/SectorData.java
@@ -0,0 +1,33 @@
+package ru.olamedia.olacraft.world.data;
+
+import java.io.Serializable;
+
+import ru.olamedia.olacraft.world.location.SectorLocation;
+
+/**
+ * Sector: set of all chunks by one x,z vertical
+ *
+ * @author olamedia
+ *
+ */
+public class SectorData implements Serializable{
+ private static final long serialVersionUID = 5304471397211814748L;
+ public HeightMap heightMap; // locations of highest nonempty blocks
+ public ChunkData[] chunkData; // 256/16 = 16
+ public SectorLocation location;
+
+ public static int yIndex(int y) {
+ return (y + 128) / 16;
+ // 1: (-128 + 128) / 16 = 0
+ // ......
+ // 15: (-114 + 128) / 16 = 14/16 = 0
+ // 16: (-113 + 128) / 16 = 15/16 = 0
+ // 17: (-112 + 128) / 16 = 16/16 = 1
+ }
+ public static SectorData generate(){
+ SectorData data = new SectorData();
+ data.heightMap = new HeightMap(16, 16);
+ data.chunkData = new ChunkData[16];
+ return data;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/data/UnavailableDataException.java b/src/ru/olamedia/olacraft/world/data/UnavailableDataException.java
new file mode 100644
index 0000000..a75a42e
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/data/UnavailableDataException.java
@@ -0,0 +1,23 @@
+package ru.olamedia.olacraft.world.data;
+
+public class UnavailableDataException extends Exception {
+
+ public UnavailableDataException() {
+ super();
+ }
+
+ public UnavailableDataException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public UnavailableDataException(String message) {
+ super(message);
+ }
+
+ public UnavailableDataException(Throwable cause) {
+ super(cause);
+ }
+
+ private static final long serialVersionUID = -8955947061088863309L;
+
+}
diff --git a/src/ru/olamedia/olacraft/world/data/package-info.java b/src/ru/olamedia/olacraft/world/data/package-info.java
new file mode 100644
index 0000000..2a171a6
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/data/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.world.data; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/world/dataProvider/AbstractChunkDataProvider.java b/src/ru/olamedia/olacraft/world/dataProvider/AbstractChunkDataProvider.java
new file mode 100644
index 0000000..1670ef3
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/dataProvider/AbstractChunkDataProvider.java
@@ -0,0 +1,60 @@
+package ru.olamedia.olacraft.world.dataProvider;
+
+import ru.olamedia.olacraft.world.data.ChunkData;
+import ru.olamedia.olacraft.world.data.RegionData;
+import ru.olamedia.olacraft.world.data.SectorData;
+import ru.olamedia.olacraft.world.location.ChunkLocation;
+import ru.olamedia.olacraft.world.location.RegionLocation;
+import ru.olamedia.olacraft.world.location.SectorLocation;
+
+abstract public class AbstractChunkDataProvider {
+ /**
+ * is data already available or we should wait
+ *
+ * @param RegionLocation
+ * @return
+ */
+ public boolean isChunkAvailable(ChunkLocation chunkLocation) {
+ return this.isRegionAvailable(chunkLocation.getRegionLocation());
+ }
+
+ public boolean isSectorAvailable(SectorLocation sectorLocation) {
+ return this.isRegionAvailable(sectorLocation.getRegionLocation());
+ }
+
+ abstract public boolean isRegionAvailable(RegionLocation regionLocation);
+
+ /**
+ * we need this chunk now, send request to server or preload
+ *
+ * @param RegionLocation
+ */
+ public void loadChunk(ChunkLocation chunkLocation) {
+ //System.out.println("loadChunk(" + chunkLocation + ")");
+ this.loadRegion(chunkLocation.getRegionLocation());
+ //System.out.println("loadChunk(" + chunkLocation + ")--");
+ }
+
+ public void loadSector(SectorLocation sectorLocation) {
+ this.loadRegion(sectorLocation.getRegionLocation());
+ }
+
+ abstract public void loadRegion(RegionLocation regionLocation);
+
+ /**
+ * Get data if already available
+ *
+ * @param RegionLocation
+ * @return
+ */
+ public ChunkData getChunk(ChunkLocation chunkLocation) {
+ return this.getRegion(chunkLocation.getRegionLocation()).getChunkData(chunkLocation);
+ }
+
+ public SectorData getSector(SectorLocation sectorLocation) {
+ return this.getRegion(sectorLocation.getRegionLocation()).getSectorData(sectorLocation);
+ }
+
+ abstract public RegionData getRegion(RegionLocation regionLocation);
+
+}
diff --git a/src/ru/olamedia/olacraft/world/dataProvider/CachedChunkDataProvider.java b/src/ru/olamedia/olacraft/world/dataProvider/CachedChunkDataProvider.java
new file mode 100644
index 0000000..23270a7
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/dataProvider/CachedChunkDataProvider.java
@@ -0,0 +1,70 @@
+package ru.olamedia.olacraft.world.dataProvider;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import ru.olamedia.olacraft.world.data.RegionData;
+import ru.olamedia.olacraft.world.location.RegionLocation;
+
+public class CachedChunkDataProvider extends AbstractChunkDataProvider {
+ private AbstractChunkDataProvider provider;
+ private HashMap<String, RegionData> regionMap = new HashMap<String, RegionData>();
+ private List<String> loading = new ArrayList<String>();
+
+ public CachedChunkDataProvider(AbstractChunkDataProvider provider) {
+ this.provider = provider;
+ }
+
+ private static boolean DEBUG = true;
+
+ private void debug(String s) {
+ if (DEBUG) {
+ System.out.println("[CachedChunkDataProvider] " + s);
+ }
+ }
+
+ @Override
+ public boolean isRegionAvailable(RegionLocation regionLocation) {
+ String key = regionLocation.toString();// regionLocation.x + "-" +
+ // regionLocation.z;
+ if (regionMap.containsKey(key)) {
+ return true;
+ }
+ if (loading.contains(key)) {
+ // return false;
+ }
+ return provider.isRegionAvailable(regionLocation);
+ }
+
+ @Override
+ public void loadRegion(RegionLocation regionLocation) {
+ String key = regionLocation.toString();
+ //debug("loadRegion(" + regionLocation + ")");
+ if (!regionMap.containsKey(key)) {
+ if (!loading.contains(key)) {
+ debug("load()");
+ loading.add(key);
+ provider.loadRegion(regionLocation);
+ }else{
+ //debug("loadRegion(" + regionLocation + ") already in loading");
+ }
+ }else{
+ debug("error: loadRegion(" + regionLocation + ") already in regionMap");
+ }
+ }
+
+ @Override
+ public RegionData getRegion(RegionLocation regionLocation) {
+ String key = regionLocation.toString();
+ if (regionMap.containsKey(key)) {
+ return regionMap.get(key);
+ } else {
+ RegionData data = provider.getRegion(regionLocation);
+ regionMap.put(key, data);
+ loading.remove(key);
+ return data;
+ }
+ }
+
+}
diff --git a/src/ru/olamedia/olacraft/world/dataProvider/LocalChunkDataProvider.java b/src/ru/olamedia/olacraft/world/dataProvider/LocalChunkDataProvider.java
new file mode 100644
index 0000000..514081f
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/dataProvider/LocalChunkDataProvider.java
@@ -0,0 +1,218 @@
+package ru.olamedia.olacraft.world.dataProvider;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import ru.olamedia.olacraft.world.data.ChunkData;
+import ru.olamedia.olacraft.world.data.RegionData;
+import ru.olamedia.olacraft.world.generator.HeightMapGenerator;
+import ru.olamedia.olacraft.world.generator.RegionGenerator;
+import ru.olamedia.olacraft.world.location.RegionLocation;
+
+public class LocalChunkDataProvider extends AbstractChunkDataProvider {
+ private String worldName;
+ private String path;
+
+ private static boolean DEBUG = true;
+
+ private void debug(String s) {
+ if (DEBUG) {
+ System.out.println("[LocalChunkDataProvider] " + s);
+ }
+ }
+
+ public LocalChunkDataProvider(String worldName) {
+ this.worldName = worldName;
+ path = "data" + File.separator + this.worldName;
+ File worldDir = new File(path);
+ if (!worldDir.isDirectory()) {
+ worldDir.mkdirs();
+ }
+ }
+
+ private int[] seed;
+
+ private int[] getSeed() throws IOException {
+ if (null == seed) {
+ String filename = path + File.separator + "world.seed";
+ File seedFile = new File(filename);
+ // md5 - 32x0-f = 16 bytes or 8 short int
+ seed = new int[8];
+ if (seedFile.exists()) {
+ InputStream in = null;
+ DataInputStream din = null;
+ in = new FileInputStream(seedFile);
+ din = new DataInputStream(in);
+ for (int i = 0; i < 8; i++) {
+ seed[i] = din.readShort();
+ }
+ din.close();
+ in.close();
+ } else {
+ OutputStream out = new FileOutputStream(seedFile);
+ DataOutputStream dout = new DataOutputStream(out);
+ for (int i = 0; i < 8; i++) {
+ seed[i] = (int) (Integer.MAX_VALUE * Math.random());
+ dout.writeShort(seed[i]);
+ }
+ dout.close();
+ out.close();
+ }
+ }
+ return seed;
+ }
+
+ @Override
+ public boolean isRegionAvailable(RegionLocation regionLocation) {
+ return true;
+ }
+
+ @Override
+ public void loadRegion(RegionLocation regionLocation) {
+ // do nothing...
+ debug("loadRegion(" + regionLocation + ")");
+ }
+
+ private ChunkData createChunk(int chunkX, int chunkY, int chunkZ) {
+ debug("createChunk " + chunkX + " " + chunkY + " " + chunkZ);
+ ChunkData data = new ChunkData();
+ try {
+ getSeed();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ HeightMapGenerator.minValue = 1;
+ HeightMapGenerator.maxValue = 64;
+ HeightMapGenerator.init();
+ HeightMapGenerator.seed = seed[0];
+ int[][] heightMap = HeightMapGenerator.getChunkHeightMap(chunkX, chunkZ);
+ for (int y = 0; y < 16; y++) {
+ for (int x = 0; x < 16; x++) {
+ for (int z = 0; z < 16; z++) {
+ data.setEmpty(ChunkData.getId(x, y, z), (heightMap[x][z] < chunkY * 16 + y));
+ }
+ }
+ }
+ return data;
+ }
+
+ @Override
+ public RegionData getRegion(RegionLocation regionLocation) {
+ String filename = path + File.separator + regionLocation.getFilename();
+ RegionData data = null;
+ // TODO READ/WRITE FILE
+ File chunkFile = new File(filename);
+ if (chunkFile.exists()) {
+ InputStream in;
+ try {
+ in = new FileInputStream(chunkFile);
+ data = RegionData.loadFrom(in);
+ in.close();
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ }
+ } else {
+ data = generateRegion(regionLocation);
+ try {
+ chunkFile.createNewFile();
+ FileOutputStream out = new FileOutputStream(chunkFile);
+ data.writeTo(out);
+ out.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ return data;
+ }
+
+ public RegionData generateRegion(RegionLocation regionLocation) {
+ RegionData data = new RegionData();
+ data.location = regionLocation;
+ // TODO FILL HERE
+ RegionGenerator generator = new RegionGenerator();
+ try {
+ generator.setSeed(getSeed());
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ generator.generate(data);
+ return data;
+ }
+
+ public ChunkData get(int chunkX, int chunkY, int chunkZ) {
+ debug("get " + chunkX + " " + chunkY + " " + chunkZ);
+ ChunkData data = null;
+ String filename = path + File.separator + chunkX + "_" + chunkY + "_" + chunkZ + ".chunk";
+ /*
+ * File chunkFile = new File(filename);
+ * if (chunkFile.exists()) {
+ * try {
+ * InputStream in = new FileInputStream(chunkFile);
+ * DataInputStream din = new DataInputStream(in);
+ * data = new ChunkData();
+ * data.readFrom(din);
+ * din.close();
+ * in.close();
+ * } catch (FileNotFoundException e) {
+ * e.printStackTrace();
+ * } catch (IOException e) {
+ * e.printStackTrace();
+ * }
+ * } else {
+ */
+ data = createChunk(chunkX, chunkY, chunkZ);
+ /*
+ * OutputStream out = null;
+ * ByteArrayOutputStream bout = null;
+ * DataOutputStream dout = null;
+ * try {
+ * chunkFile.createNewFile();
+ * out = new FileOutputStream(chunkFile);
+ * // bout = new ByteArrayOutputStream(4096);
+ * dout = new DataOutputStream(out);
+ * data.writeTo(dout);
+ * // dout.flush();
+ * // out.write(bout.toByteArray());
+ * out.flush();
+ * } catch (IOException e) {
+ * e.printStackTrace();
+ * } finally {
+ * if (null != dout) {
+ * try {
+ * dout.close();
+ * } catch (IOException e) {
+ * e.printStackTrace();
+ * }
+ * }
+ * if (null != bout) {
+ * try {
+ * bout.close();
+ * } catch (IOException e) {
+ * e.printStackTrace();
+ * }
+ * }
+ * if (null != out) {
+ * try {
+ * out.close();
+ * } catch (IOException e) {
+ * e.printStackTrace();
+ * }
+ * }
+ * }
+ * }
+ */
+ return data;
+ }
+
+}
diff --git a/src/ru/olamedia/olacraft/world/dataProvider/LocalRegionDataProvider.java b/src/ru/olamedia/olacraft/world/dataProvider/LocalRegionDataProvider.java
new file mode 100644
index 0000000..447bcc3
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/dataProvider/LocalRegionDataProvider.java
@@ -0,0 +1,57 @@
+package ru.olamedia.olacraft.world.dataProvider;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class LocalRegionDataProvider {
+ private String worldName;
+ private String path;
+
+ public LocalRegionDataProvider(String worldName) {
+ this.worldName = worldName;
+ path = "data" + File.separator + this.worldName;
+ File worldDir = new File(path);
+ if (!worldDir.isDirectory()) {
+ worldDir.mkdirs();
+ }
+ }
+
+ private int[] seed;
+
+ private int[] getSeed() throws IOException {
+ if (null == seed) {
+ String filename = path + File.separator + "world.seed";
+ File seedFile = new File(filename);
+ // md5 - 32x0-f = 16 bytes or 8 short int
+ seed = new int[8];
+ if (seedFile.exists()) {
+ InputStream in = null;
+ DataInputStream din = null;
+ in = new FileInputStream(seedFile);
+ din = new DataInputStream(in);
+ for (int i = 0; i < 8; i++) {
+ seed[i] = din.readShort();
+ }
+ din.close();
+ in.close();
+ } else {
+ OutputStream out = new FileOutputStream(seedFile);
+ DataOutputStream dout = new DataOutputStream(out);
+ for (int i = 0; i < 8; i++) {
+ seed[i] = (int) (Integer.MAX_VALUE * Math.random());
+ dout.writeShort(seed[i]);
+ }
+ dout.close();
+ out.close();
+ }
+ }
+ return seed;
+ }
+
+}
diff --git a/src/ru/olamedia/olacraft/world/dataProvider/RemoteChunkDataProvider.java b/src/ru/olamedia/olacraft/world/dataProvider/RemoteChunkDataProvider.java
new file mode 100644
index 0000000..8284ff9
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/dataProvider/RemoteChunkDataProvider.java
@@ -0,0 +1,75 @@
+package ru.olamedia.olacraft.world.dataProvider;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import com.esotericsoftware.kryonet.Connection;
+
+import ru.olamedia.olacraft.network.GameClient;
+import ru.olamedia.olacraft.network.packet.GetRegionPacket;
+import ru.olamedia.olacraft.network.packet.IPacket;
+import ru.olamedia.olacraft.network.packet.IPacketListener;
+import ru.olamedia.olacraft.network.packet.RegionDataPacket;
+import ru.olamedia.olacraft.world.data.RegionData;
+import ru.olamedia.olacraft.world.location.RegionLocation;
+
+public class RemoteChunkDataProvider extends AbstractChunkDataProvider implements IPacketListener {
+
+ private GameClient client;
+ private HashMap<String, RegionData> map = new HashMap<String, RegionData>();
+ private List<String> loading = new ArrayList<String>();
+
+ public RemoteChunkDataProvider(GameClient client) {
+ this.client = client;
+ this.client.addPacketListener(this);
+ }
+
+ private static boolean DEBUG = true;
+
+ private void debug(String s) {
+ if (DEBUG) {
+ System.out.println("[RemoteChunkDataProvider] " + s);
+ }
+ }
+
+ @Override
+ public void loadRegion(RegionLocation regionLocation) {
+ String key = regionLocation.toString();
+ debug("loadRegion(" + key + ")");
+ if (!loading.contains(key)) {
+ loading.add(key);
+ client.send(new GetRegionPacket(regionLocation));
+ debug("sent packet: GetRegionPacket");
+ }
+ }
+
+ @Override
+ public boolean isRegionAvailable(RegionLocation regionLocation) {
+ String key = regionLocation.toString();
+ if (loading.contains(key)) {
+ return false;
+ }
+ return map.containsKey(key);
+ }
+
+ @Override
+ public RegionData getRegion(RegionLocation regionLocation) {
+ String key = regionLocation.toString();
+ RegionData data = map.get(key);
+ map.remove(key);
+ return data;
+ }
+
+ @Override
+ public void onPacket(Connection connection, IPacket p) {
+ if (p instanceof RegionDataPacket) {
+ debug("received packet [conn " + connection.getID() + "]: ChunkDataPacket");
+ RegionData data = ((RegionDataPacket) p).data;
+ String key = data.location.toString();
+ map.put(key, data);
+ loading.remove(key);
+ }
+ }
+
+}
diff --git a/src/ru/olamedia/olacraft/world/dataProvider/package-info.java b/src/ru/olamedia/olacraft/world/dataProvider/package-info.java
new file mode 100644
index 0000000..6a411e6
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/dataProvider/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.world.dataProvider; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/world/generator/HeightMapGenerator.java b/src/ru/olamedia/olacraft/world/generator/HeightMapGenerator.java
new file mode 100644
index 0000000..c3e32b5
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/generator/HeightMapGenerator.java
@@ -0,0 +1,157 @@
+package ru.olamedia.olacraft.world.generator;
+
+import ru.olamedia.olacraft.world.chunk.Chunk;
+import ru.olamedia.olacraft.world.data.HeightMap;
+import ru.olamedia.olacraft.world.location.RegionLocation;
+import libnoiseforjava.NoiseGen.NoiseQuality;
+import libnoiseforjava.exception.ExceptionInvalidParam;
+import libnoiseforjava.module.Billow;
+import libnoiseforjava.module.Blend;
+import libnoiseforjava.module.Max;
+import libnoiseforjava.module.Perlin;
+import libnoiseforjava.module.RidgedMulti;
+import libnoiseforjava.module.ScaleBias;
+import libnoiseforjava.module.Select;
+import libnoiseforjava.module.Turbulence;
+import libnoiseforjava.util.NoiseMap;
+import libnoiseforjava.util.NoiseMapBuilderPlane;
+
+public class HeightMapGenerator {
+ public static int minValue;
+ public static int maxValue;
+
+ public static int seed = (int) (Integer.MAX_VALUE * Math.random());
+
+ private static Billow plainsNoise;
+ private static ScaleBias plains;
+ private static RidgedMulti hillsNoise;
+ private static ScaleBias hills;
+ private static RidgedMulti mountainsNoise;
+ private static ScaleBias mountains;
+ private static Perlin terrainType;
+ private static Blend blendedTerrain;
+ private static Select selectedTerrain;
+ private static Max maxTerrain;
+ private static Turbulence turbulence;
+ private static ScaleBias finalTerrain;
+
+ private static boolean isInitialized = false;
+
+ public static void init() {
+ if (isInitialized) {
+ return;
+ }
+ isInitialized = true;
+ try {
+ // PLAINS
+ plainsNoise = new Billow();
+ plainsNoise.setFrequency(0.01);
+ plains = new ScaleBias(plainsNoise);
+ plains.setScale(0.05);
+ plains.setBias(-0.75);
+ // HILLS
+ hillsNoise = new RidgedMulti();
+ hillsNoise.setFrequency(0.01);
+ hills = new ScaleBias(hillsNoise);
+ hills.setScale(0.5);
+ hills.setBias(-0.75);
+ // MOUNTAINS
+ mountainsNoise = new RidgedMulti();
+ mountainsNoise.setFrequency(0.04);
+ mountainsNoise.setOctaveCount(6);
+ turbulence = new Turbulence(mountainsNoise);
+ turbulence.setFrequency(0.2);
+ turbulence.setPower(1);
+ mountains = new ScaleBias(turbulence);
+ mountains.setScale(1.0);
+ mountains.setBias(-1.25);
+ terrainType = new Perlin();
+ terrainType.setOctaveCount(6);
+ terrainType.setFrequency(0.06);
+ terrainType.setPersistence(0.25);
+ terrainType.setNoiseQuality(NoiseQuality.QUALITY_BEST);
+ selectedTerrain = new Select(plains, mountains, terrainType);
+ selectedTerrain.setBounds(0, 1);
+ selectedTerrain.setEdgeFalloff(0.125);
+ blendedTerrain = new Blend(plains, mountains, terrainType);
+ maxTerrain = new Max(plains, turbulence);
+ finalTerrain = new ScaleBias(maxTerrain);
+ finalTerrain.setBias(2);
+ setSeed(seed);
+ } catch (ExceptionInvalidParam e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static void setSeed(int newseed) {
+ seed = newseed;
+ plainsNoise.setSeed(seed);
+ hillsNoise.setSeed(seed);
+ mountainsNoise.setSeed(seed);
+ terrainType.setSeed(seed);
+ }
+
+ public static int[][] getChunkHeightMap(int chunkX, int chunkZ) {
+ init();
+ try {
+ NoiseMapBuilderPlane builder = new NoiseMapBuilderPlane(16, 16);
+ // builder.enableSeamless(true);
+ // Perlin plains = new Perlin();
+
+ // Select finalTerrain = new Select(plains, mountains, null);
+ // finalTerrain.setControlModule(terrainType);
+ // finalTerrain.setBounds(0.0, 1000);
+ // finalTerrain.setEdgeFalloff(1.25);
+
+ NoiseMap heightMap = new NoiseMap(16, 16);
+ builder.setSourceModule(maxTerrain);
+ builder.setDestNoiseMap(heightMap);
+ double bx = chunkX;
+ double bz = chunkZ;
+ builder.setDestSize(16, 16);
+ builder.setBounds(bx, bx + 1, bz, bz + 1);
+ builder.build();
+ double[][] heights = heightMap.getNoiseMap();
+ int[][] ints = new int[16][16];
+ // System.out.print("heightmap:");
+ for (int x = 0; x < 16; x++) {
+ for (int z = 0; z < 16; z++) {
+ // System.out.print(((float) heights[x][z]) + ";");
+ ints[x][z] = (int) (minValue + (maxValue - minValue) * (heights[x][z] + 1) / 2);
+ }
+ }
+ // System.out.println("");
+ return ints;
+ } catch (ExceptionInvalidParam e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public static HeightMap getHeightMap(RegionLocation location) {
+ init();
+ HeightMap map = new HeightMap(256, 256);
+ try {
+ NoiseMapBuilderPlane builder = new NoiseMapBuilderPlane(256, 256);
+ NoiseMap heightMap = new NoiseMap(256, 256);
+ builder.setSourceModule(finalTerrain);
+ builder.setDestNoiseMap(heightMap);
+ builder.setDestSize(256, 256);
+ float bx = location.x;
+ float bz = location.z;
+ builder.setBounds(bx, bx + 1, bz, bz + 1);
+ builder.build();
+ double[][] heights = heightMap.getNoiseMap();
+ for (int x = 0; x < 256; x++) {
+ for (int z = 0; z < 256; z++) {
+ map.setHeight(x, z, 0);
+ //(int) (minValue + (maxValue - minValue) * (heights[x][z] + 1) / 2)
+ }
+ }
+ return map;
+ } catch (ExceptionInvalidParam e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/generator/ImprovedNoise.java b/src/ru/olamedia/olacraft/world/generator/ImprovedNoise.java
new file mode 100644
index 0000000..365aa12
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/generator/ImprovedNoise.java
@@ -0,0 +1,61 @@
+package ru.olamedia.olacraft.world.generator;
+
+//JAVA REFERENCE IMPLEMENTATION OF IMPROVED NOISE - COPYRIGHT 2002 KEN PERLIN.
+
+public final class ImprovedNoise {
+ static public double noise(double x, double y, double z) {
+ int X = (int) Math.floor(x) & 255, // FIND UNIT CUBE THAT
+ Y = (int) Math.floor(y) & 255, // CONTAINS POINT.
+ Z = (int) Math.floor(z) & 255;
+ x -= Math.floor(x); // FIND RELATIVE X,Y,Z
+ y -= Math.floor(y); // OF POINT IN CUBE.
+ z -= Math.floor(z);
+ double u = fade(x), // COMPUTE FADE CURVES
+ v = fade(y), // FOR EACH OF X,Y,Z.
+ w = fade(z);
+ int A = p[X] + Y, AA = p[A] + Z, AB = p[A + 1] + Z, // HASH COORDINATES
+ // OF
+ B = p[X + 1] + Y, BA = p[B] + Z, BB = p[B + 1] + Z; // THE 8 CUBE
+ // CORNERS,
+
+ return lerp(w, lerp(v, lerp(u, grad(p[AA], x, y, z), // AND ADD
+ grad(p[BA], x - 1, y, z)), // BLENDED
+ lerp(u, grad(p[AB], x, y - 1, z), // RESULTS
+ grad(p[BB], x - 1, y - 1, z))),// FROM 8
+ lerp(v, lerp(u, grad(p[AA + 1], x, y, z - 1), // CORNERS
+ grad(p[BA + 1], x - 1, y, z - 1)), // OF CUBE
+ lerp(u, grad(p[AB + 1], x, y - 1, z - 1), grad(p[BB + 1], x - 1, y - 1, z - 1))));
+ }
+
+ static double fade(double t) {
+ return t * t * t * (t * (t * 6 - 15) + 10);
+ }
+
+ static double lerp(double t, double a, double b) {
+ return a + t * (b - a);
+ }
+
+ static double grad(int hash, double x, double y, double z) {
+ int h = hash & 15; // CONVERT LO 4 BITS OF HASH CODE
+ double u = h < 8 ? x : y, // INTO 12 GRADIENT DIRECTIONS.
+ v = h < 4 ? y : h == 12 || h == 14 ? x : z;
+ return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
+ }
+
+ static final int p[] = new int[512], permutation[] = { 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194,
+ 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26,
+ 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171,
+ 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230,
+ 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187,
+ 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226,
+ 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189,
+ 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9, 129,
+ 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193,
+ 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199,
+ 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24,
+ 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180 };
+ static {
+ for (int i = 0; i < 256; i++)
+ p[256 + i] = p[i] = permutation[i];
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/generator/Lerp.java b/src/ru/olamedia/olacraft/world/generator/Lerp.java
new file mode 100644
index 0000000..cc009fe
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/generator/Lerp.java
@@ -0,0 +1,27 @@
+package ru.olamedia.olacraft.world.generator;
+
+public class Lerp {
+ public static float lerp(float x, float x1, float x2, float q00, float q01) {
+ return ((x2 - x) / (x2 - x1)) * q00 + ((x - x1) / (x2 - x1)) * q01;
+ }
+
+ public static float biLerp(float x, float y, float q11, float q12, float q21, float q22, float x1, float x2,
+ float y1, float y2) {
+ float r1 = lerp(x, x1, x2, q11, q21);
+ float r2 = lerp(x, x1, x2, q12, q22);
+
+ return lerp(y, y1, y2, r1, r2);
+ }
+
+ public static float triLerp(float x, float y, float z, float q000, float q001, float q010, float q011, float q100,
+ float q101, float q110, float q111, float x1, float x2, float y1, float y2, float z1, float z2) {
+ float x00 = lerp(x, x1, x2, q000, q100);
+ float x10 = lerp(x, x1, x2, q010, q110);
+ float x01 = lerp(x, x1, x2, q001, q101);
+ float x11 = lerp(x, x1, x2, q011, q111);
+ float r0 = lerp(y, y1, y2, x00, x01);
+ float r1 = lerp(y, y1, y2, x10, x11);
+
+ return lerp(z, z1, z2, r0, r1);
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/generator/RegionGenerator.java b/src/ru/olamedia/olacraft/world/generator/RegionGenerator.java
new file mode 100644
index 0000000..9657e32
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/generator/RegionGenerator.java
@@ -0,0 +1,71 @@
+package ru.olamedia.olacraft.world.generator;
+
+import ru.olamedia.olacraft.world.data.ChunkData;
+import ru.olamedia.olacraft.world.data.HeightMap;
+import ru.olamedia.olacraft.world.data.RegionData;
+import ru.olamedia.olacraft.world.data.SectorData;
+import ru.olamedia.olacraft.world.location.BlockLocation;
+import ru.olamedia.olacraft.world.location.ChunkLocation;
+import ru.olamedia.olacraft.world.location.SectorLocation;
+
+public class RegionGenerator {
+ private int[] seed;
+
+ public void setSeed(int[] seed) {
+ this.seed = seed;
+ }
+
+ public void debug(String s) {
+ System.out.println("[RegionGenerator] " + s);
+ }
+
+ public void generate(RegionData data) {
+ HeightMapGenerator.minValue = -5;
+ HeightMapGenerator.maxValue = 100;
+ HeightMapGenerator.init();
+ HeightMapGenerator.seed = seed[0];
+ BlockLocation offset = data.location.getBlockLocation();
+ // int[][] heightMap =
+ // HeightMapGenerator.getHeightMap(data.location.getBlockLocation().x,
+ // data.location.getBlockLocation().z, 256, 256);
+ debug(data.location.toString());
+ data.heightMap = HeightMapGenerator.getHeightMap(data.location);
+ //debug(data.heightMap.toString());
+ data.sectorData = new SectorData[16][16];
+ for (int x = 0; x < 16; x++) {
+ for (int z = 0; z < 16; z++) {
+ // CREATE SECTOR
+ SectorData sector = new SectorData();
+ sector.location = new SectorLocation(offset.x + x * 16, offset.z + z * 16);
+ sector.heightMap = new HeightMap(16, 16);
+ sector.chunkData = new ChunkData[16];
+ for (int y = 0; y < 16; y++) {
+ // CREATE CHUNK
+ ChunkData chunk = new ChunkData();
+ chunk.location = new ChunkLocation(sector.location.x, y, sector.location.z);
+ int chunkOffsetY = y * 16 - 128;
+ for (int inChunkX = 0; inChunkX < 16; inChunkX++) {
+ for (int inChunkZ = 0; inChunkZ < 16; inChunkZ++) {
+ int height = data.heightMap.getHeight(x * 16 + inChunkX, z * 16 + inChunkZ);
+ //System.out.println("height: " + height);
+ sector.heightMap.setHeight(inChunkX, inChunkZ, height);
+ for (int inChunkY = 0; inChunkY < 16; inChunkY++) {
+ //height = sector.heightMap.getHeight(inChunkX, inChunkZ);
+ int id = ChunkData.getId(inChunkX, inChunkY, inChunkZ);
+ if (chunkOffsetY + inChunkY > height) {
+ chunk.setEmpty(id, true);
+ } else {
+ //System.out.println("not empty, height: " + height);
+ chunk.setEmpty(id, false);
+ }
+ }
+ }
+ }
+ chunk.compact();
+ sector.chunkData[y] = chunk;
+ }
+ data.sectorData[x][z] = sector;
+ }
+ }
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/generator/package-info.java b/src/ru/olamedia/olacraft/world/generator/package-info.java
new file mode 100644
index 0000000..2f62117
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/generator/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.world.generator; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/world/location/BlockLocation.java b/src/ru/olamedia/olacraft/world/location/BlockLocation.java
new file mode 100644
index 0000000..b104bad
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/location/BlockLocation.java
@@ -0,0 +1,37 @@
+package ru.olamedia.olacraft.world.location;
+
+import java.io.Serializable;
+
+import ru.olamedia.olacraft.world.chunk.Chunk;
+
+public class BlockLocation implements Serializable {
+ private static final long serialVersionUID = -4987461467575474762L;
+ public int x;
+ public int y;
+ public int z;
+
+ public BlockLocation() {
+ }
+
+ public BlockLocation(int x, int y, int z) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public ChunkLocation getChunkLocation() {
+ return new ChunkLocation(Chunk.v(x), Chunk.v(y + 128), Chunk.v(z));
+ }
+
+ public RegionLocation getRegionLocation() {
+ return new RegionLocation(Chunk.v(Chunk.v(x)), Chunk.v(Chunk.v(z)));
+ }
+
+ public SectorLocation getSectorLocation() {
+ return new SectorLocation(Chunk.v(x), Chunk.v(z));
+ }
+
+ public String toString() {
+ return "blockLocation[" + x + "," + y + "," + z + "]";
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/location/ChunkLocation.java b/src/ru/olamedia/olacraft/world/location/ChunkLocation.java
new file mode 100644
index 0000000..57acc52
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/location/ChunkLocation.java
@@ -0,0 +1,40 @@
+package ru.olamedia.olacraft.world.location;
+
+import java.io.Serializable;
+
+import ru.olamedia.olacraft.world.chunk.Chunk;
+
+public class ChunkLocation implements Serializable {
+ private static final long serialVersionUID = -3620722885522274470L;
+
+ public ChunkLocation() {
+
+ }
+
+ public ChunkLocation(int x, int y, int z) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public int x;
+ public int y;
+ public int z;
+
+ public SectorLocation getSectorLocation() {
+ return new SectorLocation(x, z);
+ }
+
+ public RegionLocation getRegionLocation() {
+ return new RegionLocation(Chunk.v(x), Chunk.v(z));
+ }
+
+ public String toString() {
+ return "chunkLocation[" + x + "," + y + "," + z + "]";
+ }
+ /*
+ * public BlockSlice getSlice(){
+ *
+ * }
+ */
+}
diff --git a/src/ru/olamedia/olacraft/world/location/RegionLocation.java b/src/ru/olamedia/olacraft/world/location/RegionLocation.java
new file mode 100644
index 0000000..59a57ec
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/location/RegionLocation.java
@@ -0,0 +1,29 @@
+package ru.olamedia.olacraft.world.location;
+
+import java.io.Serializable;
+
+public class RegionLocation implements Serializable {
+ private static final long serialVersionUID = -141619138379029773L;
+ public int x;
+ public int z;
+
+ public RegionLocation() {
+ }
+
+ public RegionLocation(int x, int z) {
+ this.x = x;
+ this.z = z;
+ }
+
+ public String toString() {
+ return "regionLocation[" + x + "," + z + "]";
+ }
+
+ public String getFilename() {
+ return "" + x + "_" + z + ".region";
+ }
+
+ public BlockLocation getBlockLocation() {
+ return new BlockLocation(x * 256, 0, z * 256);
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/location/SectorLocation.java b/src/ru/olamedia/olacraft/world/location/SectorLocation.java
new file mode 100644
index 0000000..59390b8
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/location/SectorLocation.java
@@ -0,0 +1,29 @@
+package ru.olamedia.olacraft.world.location;
+
+import java.io.Serializable;
+
+import ru.olamedia.olacraft.world.chunk.Chunk;
+
+public class SectorLocation implements Serializable {
+ private static final long serialVersionUID = 4500216114186249375L;
+
+ public SectorLocation() {
+
+ }
+
+ public SectorLocation(int x, int z) {
+ this.x = x;
+ this.z = z;
+ }
+
+ public int x;
+ public int z;
+
+ public RegionLocation getRegionLocation() {
+ return new RegionLocation(Chunk.v(x), Chunk.v(z));
+ }
+
+ public String toString() {
+ return "sectorLocation[" + x + "," + z + "]";
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/location/package-info.java b/src/ru/olamedia/olacraft/world/location/package-info.java
new file mode 100644
index 0000000..37f205d
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/location/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.world.location; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/world/package-info.java b/src/ru/olamedia/olacraft/world/package-info.java
new file mode 100644
index 0000000..914d8d2
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.world; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/world/provider/IChunkProvider.java b/src/ru/olamedia/olacraft/world/provider/IChunkProvider.java
new file mode 100644
index 0000000..5076c75
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/provider/IChunkProvider.java
@@ -0,0 +1,8 @@
+package ru.olamedia.olacraft.world.provider;
+
+import ru.olamedia.olacraft.world.block.Block;
+
+public interface IChunkProvider {
+ public boolean isEmptyBlock(int x, int y, int z);
+ public Block getBlock(int x, int y, int z);
+}
diff --git a/src/ru/olamedia/olacraft/world/provider/WorldProvider.java b/src/ru/olamedia/olacraft/world/provider/WorldProvider.java
new file mode 100644
index 0000000..8dacce9
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/provider/WorldProvider.java
@@ -0,0 +1,130 @@
+package ru.olamedia.olacraft.world.provider;
+
+import ru.olamedia.olacraft.game.SpawnLocation;
+import ru.olamedia.olacraft.world.WorldInfo;
+import ru.olamedia.olacraft.world.block.Block;
+import ru.olamedia.olacraft.world.chunk.Chunk;
+import ru.olamedia.olacraft.world.data.ChunkData;
+import ru.olamedia.olacraft.world.data.RegionData;
+import ru.olamedia.olacraft.world.dataProvider.AbstractChunkDataProvider;
+import ru.olamedia.olacraft.world.location.BlockLocation;
+import ru.olamedia.olacraft.world.location.ChunkLocation;
+import ru.olamedia.olacraft.world.location.RegionLocation;
+
+public class WorldProvider {
+ private WorldInfo info = new WorldInfo();
+ private AbstractChunkDataProvider dataProvider;
+
+ public WorldInfo getInfo() {
+ return info;
+ }
+
+ public void setInfo(WorldInfo worldInfo) {
+ info = worldInfo;
+ }
+
+ /*
+ * public AbstractChunkDataProvider getChunkDataProvider() {
+ * return dataProvider;
+ * }
+ */
+
+ public void setChunkDataProvider(AbstractChunkDataProvider provider) {
+ dataProvider = provider;
+ }
+
+ public SpawnLocation getSpawnLocation(int connectionId) {
+ SpawnLocation l = new SpawnLocation();
+ int maxShift = 10;
+ l.x = (int) (maxShift - Math.random() * 2 * maxShift);
+ l.z = (int) (maxShift - Math.random() * 2 * maxShift);
+ System.out.print("Searching spawn Y");
+ BlockLocation spawnLocation = new BlockLocation(l.x, 0, l.z);
+ for (int y = info.maxHeight; y > info.minHeight; y--) {
+ // search for floor block
+ spawnLocation.y = y;
+ System.out.print(y + ". ");
+ ChunkData chunk = dataProvider.getChunk(spawnLocation.getChunkLocation());
+ boolean notEmpty = !chunk.isEmpty(ChunkData.getId(Chunk.in(spawnLocation.x), Chunk.in(spawnLocation.y),
+ Chunk.in(spawnLocation.z)));
+ if (notEmpty) {
+ // found
+ l.y = y + 1;
+ System.out.println("found: " + y);
+ return l;
+ }
+ }
+ System.out.println("not found ");
+ // not found
+ l.y = info.maxHeight;
+ return l;
+ }
+
+ public boolean renderBottom(int x, int y, int z) {
+ return (!isEmptyBlock(x, y, z)) && (isEmptyBlock(x, y - 1, z));
+ }
+
+ public boolean renderTop(int x, int y, int z) {
+ return (!isEmptyBlock(x, y, z)) && (isEmptyBlock(x, y + 1, z));
+ }
+
+ public boolean renderLeft(int x, int y, int z) {
+ return (!isEmptyBlock(x, y, z)) && (isEmptyBlock(x - 1, y, z));
+ }
+
+ public boolean renderRight(int x, int y, int z) {
+ return (!isEmptyBlock(x, y, z)) && (isEmptyBlock(x + 1, y, z));
+ }
+
+ public boolean renderBack(int x, int y, int z) {
+ return (!isEmptyBlock(x, y, z)) && (isEmptyBlock(x, y, z - 1));
+ }
+
+ public boolean renderFront(int x, int y, int z) {
+ return (!isEmptyBlock(x, y, z)) && (isEmptyBlock(x, y, z + 1));
+ }
+
+ public boolean isEmptyBlock(int x, int y, int z) {
+ BlockLocation blockLocation = new BlockLocation(x, y, z);
+
+ if (isChunkAvailable(blockLocation.getChunkLocation())) {
+ ChunkData data = dataProvider.getChunk(blockLocation.getChunkLocation());
+ if (null != data) {
+ return data.isEmpty(blockLocation);
+ }
+ }
+ return false;
+ }
+
+ public void requestChunk(int chunkX, int chunkY, int chunkZ) {
+ ChunkLocation chunkLocation = new ChunkLocation(chunkX, chunkY, chunkZ);
+ // getChunkDataProvider().loadRegion(chunkLocation.getRegionLocation());
+ loadChunk(chunkLocation);
+ }
+
+ public boolean isChunkAvailable(ChunkLocation chunkLocation) {
+ return dataProvider.isChunkAvailable(chunkLocation);
+ }
+
+ public boolean isAvailableBlock(int x, int y, int z) {
+ BlockLocation blockLocation = new BlockLocation(x, y, z);
+ return dataProvider.isChunkAvailable(blockLocation.getChunkLocation());
+ }
+
+ public void loadChunk(ChunkLocation chunkLocation) {
+ dataProvider.loadChunk(chunkLocation);
+ }
+
+ public RegionData getRegion(RegionLocation regionLocation) {
+ return dataProvider.getRegion(regionLocation);
+ }
+
+ public Block getBlock(int x, int y, int z) {
+ BlockLocation blockLocation = new BlockLocation(x, y, z);
+ return new Block(this, x, y, z);
+ }
+
+ public ChunkData getChunk(ChunkLocation chunkLocation) {
+ return dataProvider.getChunk(chunkLocation);
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/provider/blockData/BlockData.java b/src/ru/olamedia/olacraft/world/provider/blockData/BlockData.java
new file mode 100644
index 0000000..94be4d7
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/provider/blockData/BlockData.java
@@ -0,0 +1,5 @@
+package ru.olamedia.olacraft.world.provider.blockData;
+
+public class BlockData {
+
+}
diff --git a/src/ru/olamedia/olacraft/world/provider/blockData/EmptyBlockData.java b/src/ru/olamedia/olacraft/world/provider/blockData/EmptyBlockData.java
new file mode 100644
index 0000000..ab17107
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/provider/blockData/EmptyBlockData.java
@@ -0,0 +1,5 @@
+package ru.olamedia.olacraft.world.provider.blockData;
+
+public class EmptyBlockData implements IBlockData{
+ public boolean notEmpty = false;
+}
diff --git a/src/ru/olamedia/olacraft/world/provider/blockData/IBlockData.java b/src/ru/olamedia/olacraft/world/provider/blockData/IBlockData.java
new file mode 100644
index 0000000..95dfb35
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/provider/blockData/IBlockData.java
@@ -0,0 +1,5 @@
+package ru.olamedia.olacraft.world.provider.blockData;
+
+public interface IBlockData {
+ public boolean notEmpty = false;
+}
diff --git a/src/ru/olamedia/olacraft/world/provider/blockData/package-info.java b/src/ru/olamedia/olacraft/world/provider/blockData/package-info.java
new file mode 100644
index 0000000..0fa952a
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/provider/blockData/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.world.provider.blockData; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/world/provider/package-info.java b/src/ru/olamedia/olacraft/world/provider/package-info.java
new file mode 100644
index 0000000..c43643a
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/provider/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.world.provider; \ No newline at end of file
diff --git a/src/ru/olamedia/player/Player.java b/src/ru/olamedia/player/Player.java
new file mode 100644
index 0000000..08811b5
--- /dev/null
+++ b/src/ru/olamedia/player/Player.java
@@ -0,0 +1,31 @@
+package ru.olamedia.player;
+
+import ru.olamedia.liveEntity.LiveEntity;
+import ru.olamedia.olacraft.game.Game;
+import ru.olamedia.olacraft.network.packet.LiveEntityLocationUpdatePacket;
+import ru.olamedia.olacraft.weapon.Bullet;
+
+public class Player extends LiveEntity {
+
+ @Override
+ public void notifyLocationUpdate() {
+ LiveEntityLocationUpdatePacket p = new LiveEntityLocationUpdatePacket();
+ p.x = getX();
+ p.y = getY();
+ p.z = getZ();
+ Game.client.send(p);
+ }
+
+ public Player() {
+
+ }
+
+ public void onMouseClick() {
+ Bullet b = new Bullet();
+ b.velocity.set(Game.instance.camera.getLook());
+ b.velocity.negate();
+ b.velocity.scale(100);
+ b.location.set(getX(), getCameraY(), getZ());
+ Game.client.getScene().addBullet(b);
+ }
+}
diff --git a/src/ru/olamedia/tasks/Task.java b/src/ru/olamedia/tasks/Task.java
new file mode 100644
index 0000000..1886265
--- /dev/null
+++ b/src/ru/olamedia/tasks/Task.java
@@ -0,0 +1,24 @@
+package ru.olamedia.tasks;
+
+public abstract class Task implements Runnable {
+
+ public Task(){
+ TaskManager.add(this);
+ }
+
+ protected volatile boolean stopped = false;
+
+ public void setStopped(boolean s){
+ this.stopped = s;
+ }
+
+ public void stop() {
+ this.stopped = true;
+ }
+
+ protected boolean shouldStop() {
+ return this.stopped;
+ }
+
+ public abstract void run();
+}
diff --git a/src/ru/olamedia/tasks/TaskManager.java b/src/ru/olamedia/tasks/TaskManager.java
new file mode 100644
index 0000000..e1a637e
--- /dev/null
+++ b/src/ru/olamedia/tasks/TaskManager.java
@@ -0,0 +1,18 @@
+package ru.olamedia.tasks;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class TaskManager {
+ private static List<Task> tasks = new ArrayList<Task>();
+
+ public static void add(Task task) {
+ tasks.add(task);
+ }
+
+ public static void stopAll() {
+ for (Task task : tasks) {
+ task.stop();
+ }
+ }
+}
diff --git a/src/ru/olamedia/tasks/package-info.java b/src/ru/olamedia/tasks/package-info.java
new file mode 100644
index 0000000..88dffa7
--- /dev/null
+++ b/src/ru/olamedia/tasks/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.tasks; \ No newline at end of file
diff --git a/src/ru/olamedia/texture/ResourceUtil.java b/src/ru/olamedia/texture/ResourceUtil.java
new file mode 100644
index 0000000..656e3a8
--- /dev/null
+++ b/src/ru/olamedia/texture/ResourceUtil.java
@@ -0,0 +1,126 @@
+package ru.olamedia.texture;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+public class ResourceUtil {
+
+ private static URL baseURL;
+
+ private static ResourceUtil instance;
+
+ public static ResourceUtil getInstance() {
+ if (null == instance) {
+ instance = new ResourceUtil();
+ }
+ return instance;
+ }
+
+ public static URL getInternalBaseURL() {
+ if (null == baseURL) {
+ URL url = getInstance().getClass().getResource("ResourceUtil.class");
+ // URL back = null;
+ // try {
+ // back = new URL(url, "..");
+ // } catch (MalformedURLException e1) {
+ // e1.printStackTrace();
+ // }
+ // System.out.println("Back:" + back);
+ // System.out.println("Class:" + url);
+ int p = url.toString().indexOf("jar!");
+ if (p > 0) {
+ // in local jar:
+ // jar:file:/E:/com/mindprod/thepackage/thepackage.jar!/com/mindprod/thepackage/images/blueball.gif
+ // in remote jar:
+ // jar:http://mindprod.com/thepackage.jar!/com/mindprod/thepackage/images/blueball.gif
+ try {
+ baseURL = new URL(url.toString().substring(0, p + 4));
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ }
+ } else {
+ // in local file:
+ // file:/E:/com/mindprod/thepackage/images/blueball.gif
+ // in remote file:
+ // http://mindprod.com/com/mindprod/the...s/blueball.gif
+ int l = url.toString().length() - (ResourceUtil.class.toString()).length();
+ try {
+ baseURL = new URL(url.toString().substring(0, l));
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return baseURL;
+ }
+
+ public static String getInternalFilename(String fn) {
+ return getInternalBaseURL() + fn;
+ }
+
+ public static URL getInternalResource(String internalPath) throws MalformedURLException {
+ URL url = ResourceUtil.class.getClassLoader().getResource(internalPath);
+ if (url == null) {
+ System.out.println(internalPath + " not found");
+ } else {
+ System.out.println(url.toString());
+ }
+ return url;
+ // return new URL(getInternalBaseURL(), internalPath);
+ }
+
+ public static URL getURL(String internalPath) {
+ try {
+ return new URL(getInternalBaseURL(), internalPath);
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public static String getFilename(String internalPath) {
+ try {
+ URL url = new URL(getInternalBaseURL(), internalPath);
+ return url.getFile();
+ } catch (MalformedURLException e) {
+ System.err.println("Problems with " + internalPath);
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public static InputStream getInternalInputStream(String internalPath) {
+ try {
+ return getInternalResource(internalPath).openStream();
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public static File getFile(String fn) {
+ URL url = null;
+ try {
+ url = new URL(getInternalFilename(fn));
+ } catch (MalformedURLException e1) {
+ e1.printStackTrace();
+ }
+ System.out.println("Fn:" + fn);
+ System.out.println("Base:" + getInternalBaseURL());
+ System.out.println("Internal:" + getInternalFilename(fn));
+ System.out.println("Url:" + url);
+ File f;
+ try {
+ f = new File(url.toURI());
+ } catch (URISyntaxException e) {
+ f = new File(url.getPath());
+ }
+ return f;
+ }
+}
diff --git a/src/ru/olamedia/texture/TextureManager.java b/src/ru/olamedia/texture/TextureManager.java
new file mode 100644
index 0000000..c790cee
--- /dev/null
+++ b/src/ru/olamedia/texture/TextureManager.java
@@ -0,0 +1,42 @@
+package ru.olamedia.texture;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+
+import ru.olamedia.asset.AssetManager;
+import ru.olamedia.asset.AssetNotFoundException;
+
+import com.jogamp.opengl.util.texture.Texture;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+public class TextureManager {
+ private static HashMap<String, Texture> list = new HashMap<String, Texture>();
+
+ public static Texture get(String filename) {
+ if (!list.containsKey(filename)) {
+ try {
+ return get(filename, AssetManager.getAsset(filename).getInputStream());
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ } catch (AssetNotFoundException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+ return list.get(filename);
+ }
+
+ public static Texture get(String key, InputStream stream) {
+ if (!list.containsKey(key)) {
+ try {
+ list.put(key, TextureIO.newTexture(stream, true, "PNG"));
+ } catch (IOException e) {
+ list.put(key, null);
+ e.printStackTrace();
+ }
+ }
+ return list.get(key);
+ }
+}
diff --git a/src/ru/olamedia/texture/package-info.java b/src/ru/olamedia/texture/package-info.java
new file mode 100644
index 0000000..fb1a5d4
--- /dev/null
+++ b/src/ru/olamedia/texture/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.texture; \ No newline at end of file
diff --git a/src/ru/olamedia/util/BufferUtils.java b/src/ru/olamedia/util/BufferUtils.java
new file mode 100644
index 0000000..10d9f36
--- /dev/null
+++ b/src/ru/olamedia/util/BufferUtils.java
@@ -0,0 +1,16 @@
+package ru.olamedia.util;
+
+import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
+
+public class BufferUtils {
+
+ public static ShortBuffer createShortBuffer(int capacity) {
+ return ShortBuffer.allocate(capacity);
+ }
+
+ public static FloatBuffer createFloatBuffer(int capacity) {
+ return FloatBuffer.allocate(capacity);
+ }
+
+}
diff --git a/src/ru/olamedia/vbo/VBO.java b/src/ru/olamedia/vbo/VBO.java
new file mode 100644
index 0000000..6f6c508
--- /dev/null
+++ b/src/ru/olamedia/vbo/VBO.java
@@ -0,0 +1,29 @@
+package ru.olamedia.vbo;
+
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLUniformData;
+
+import com.jogamp.opengl.util.PMVMatrix;
+
+public class VBO {
+ private GLAutoDrawable drawable;
+ private PMVMatrix pmvMatrix;
+ private GLUniformData pmvMatrixUniform;
+ private GLUniformData colorUniform;
+ private int[] vboIda = new int[10];
+
+ public VBO(GLAutoDrawable drawable) {
+ this.drawable = drawable;
+ GL2ES2 gl = drawable.getGL().getGL2ES2();
+ // gl.glGenBuffersARB(1, vboIda, 0);
+ }
+
+ public void setDrawable(GLAutoDrawable drawable) {
+ this.drawable = drawable;
+ }
+
+ public void render() {
+
+ }
+}
diff --git a/src/ru/olamedia/vbo/package-info.java b/src/ru/olamedia/vbo/package-info.java
new file mode 100644
index 0000000..325d96f
--- /dev/null
+++ b/src/ru/olamedia/vbo/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.vbo; \ No newline at end of file