aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorolamedia <[email protected]>2012-12-23 11:30:36 +0600
committerolamedia <[email protected]>2012-12-23 11:30:36 +0600
commitf58bdfcb66353bb77213cab580bc49ef890417ad (patch)
tree2983a05d564891e92c115a679f9bfbf55465c755 /src
parent5320fd1dad5b77fa227e83fbbe0a958f2c5fc283 (diff)
0.1.7
Diffstat (limited to 'src')
-rw-r--r--src/jp/nyatla/nymmd/MmdException.java70
-rw-r--r--src/jp/nyatla/nymmd/MmdMotionPlayer.java434
-rw-r--r--src/jp/nyatla/nymmd/MmdMotionPlayerGL2.java434
-rw-r--r--src/jp/nyatla/nymmd/MmdPmdModel.java74
-rw-r--r--src/jp/nyatla/nymmd/MmdPmdModel_BasicClass.java317
-rw-r--r--src/jp/nyatla/nymmd/MmdVmdMotion.java55
-rw-r--r--src/jp/nyatla/nymmd/MmdVmdMotion_BasicClass.java290
-rw-r--r--src/jp/nyatla/nymmd/core/PmdBone.java224
-rw-r--r--src/jp/nyatla/nymmd/core/PmdFace.java108
-rw-r--r--src/jp/nyatla/nymmd/core/PmdIK.java194
-rw-r--r--src/jp/nyatla/nymmd/struct/DataReader.java120
-rw-r--r--src/jp/nyatla/nymmd/struct/StructReader.java82
-rw-r--r--src/jp/nyatla/nymmd/struct/StructType.java48
-rw-r--r--src/jp/nyatla/nymmd/struct/pmd/PMD_Bone.java66
-rw-r--r--src/jp/nyatla/nymmd/struct/pmd/PMD_FACE.java74
-rw-r--r--src/jp/nyatla/nymmd/struct/pmd/PMD_FACE_VTX.java75
-rw-r--r--src/jp/nyatla/nymmd/struct/pmd/PMD_Header.java69
-rw-r--r--src/jp/nyatla/nymmd/struct/pmd/PMD_IK.java83
-rw-r--r--src/jp/nyatla/nymmd/struct/pmd/PMD_Material.java82
-rw-r--r--src/jp/nyatla/nymmd/struct/pmd/PMD_Vertex.java78
-rw-r--r--src/jp/nyatla/nymmd/struct/vmd/VMD_Face.java60
-rw-r--r--src/jp/nyatla/nymmd/struct/vmd/VMD_Header.java63
-rw-r--r--src/jp/nyatla/nymmd/struct/vmd/VMD_Motion.java94
-rw-r--r--src/jp/nyatla/nymmd/types/BoneKeyFrame.java62
-rw-r--r--src/jp/nyatla/nymmd/types/FaceData.java45
-rw-r--r--src/jp/nyatla/nymmd/types/FaceKeyFrame.java53
-rw-r--r--src/jp/nyatla/nymmd/types/MmdColor3.java53
-rw-r--r--src/jp/nyatla/nymmd/types/MmdColor4.java59
-rw-r--r--src/jp/nyatla/nymmd/types/MmdMatrix.java377
-rw-r--r--src/jp/nyatla/nymmd/types/MmdTexUV.java59
-rw-r--r--src/jp/nyatla/nymmd/types/MmdVector3.java209
-rw-r--r--src/jp/nyatla/nymmd/types/MmdVector4.java137
-rw-r--r--src/jp/nyatla/nymmd/types/MotionData.java125
-rw-r--r--src/jp/nyatla/nymmd/types/PmdMaterial.java51
-rw-r--r--src/jp/nyatla/nymmd/types/PmdSkinInfo.java47
-rw-r--r--src/ru/olamedia/asset/Shader.java40
-rw-r--r--src/ru/olamedia/asset/Sprite.java115
-rw-r--r--src/ru/olamedia/asset/SpriteOffset.java10
-rw-r--r--src/ru/olamedia/asset/SpriteRectangle.java11
-rw-r--r--src/ru/olamedia/asset/shader/block.fp28
-rw-r--r--src/ru/olamedia/asset/shader/block.vp25
-rw-r--r--src/ru/olamedia/camera/Cameraman.java4
-rw-r--r--src/ru/olamedia/camera/MatrixCamera.java386
-rw-r--r--src/ru/olamedia/data/BitCube.java13
-rw-r--r--src/ru/olamedia/data/package-info.java8
-rw-r--r--src/ru/olamedia/game/GameFrame.java40
-rw-r--r--src/ru/olamedia/game/GameLogicThread.java76
-rw-r--r--src/ru/olamedia/game/GameManager.java143
-rw-r--r--src/ru/olamedia/game/GameTime.java71
-rw-r--r--src/ru/olamedia/game/Launcher.java4
-rw-r--r--src/ru/olamedia/geom/ChunkMesh.java83
-rw-r--r--src/ru/olamedia/geom/ChunkMeshNode.java97
-rw-r--r--src/ru/olamedia/geom/ChunkMeshOctree.java95
-rw-r--r--src/ru/olamedia/geom/DisplayList.java1
-rw-r--r--src/ru/olamedia/geom/Frustum.java34
-rw-r--r--src/ru/olamedia/geom/Frustum2.java282
-rw-r--r--src/ru/olamedia/geom/ImmModeMesh.java465
-rw-r--r--src/ru/olamedia/geom/IndexedMeshBulder.java207
-rw-r--r--src/ru/olamedia/geom/Mesh.java76
-rw-r--r--src/ru/olamedia/geom/MultiMesh.java34
-rw-r--r--src/ru/olamedia/geom/SimpleQuadMesh.java145
-rw-r--r--src/ru/olamedia/geom/VoxelRaypicker.java37
-rw-r--r--src/ru/olamedia/input/Keyboard.java77
-rw-r--r--src/ru/olamedia/input/MouseJail.java44
-rw-r--r--src/ru/olamedia/input/MouseListener.java4
-rw-r--r--src/ru/olamedia/liveEntity/LiveEntity.java202
-rw-r--r--src/ru/olamedia/math/Frustum.java108
-rw-r--r--src/ru/olamedia/math/Vector.java5
-rw-r--r--src/ru/olamedia/math/VectorUtil.java29
-rw-r--r--src/ru/olamedia/olacraft/OlaCraft.java2
-rw-r--r--src/ru/olamedia/olacraft/game/Game.java14
-rw-r--r--src/ru/olamedia/olacraft/inventory/Inventory.java416
-rw-r--r--src/ru/olamedia/olacraft/modelAnimator/Arm.java27
-rw-r--r--src/ru/olamedia/olacraft/modelAnimator/Bone.java215
-rw-r--r--src/ru/olamedia/olacraft/modelAnimator/BoneSet.java163
-rw-r--r--src/ru/olamedia/olacraft/modelAnimator/ISkeletonNode.java26
-rw-r--r--src/ru/olamedia/olacraft/modelAnimator/Leg.java27
-rw-r--r--src/ru/olamedia/olacraft/modelAnimator/ModelAnimator.java324
-rw-r--r--src/ru/olamedia/olacraft/modelAnimator/Randomizer.java92
-rw-r--r--src/ru/olamedia/olacraft/modelAnimator/Skeleton.java47
-rw-r--r--src/ru/olamedia/olacraft/modelAnimator/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/network/GameClient.java8
-rw-r--r--src/ru/olamedia/olacraft/network/GameServer.java14
-rw-r--r--src/ru/olamedia/olacraft/network/Network.java6
-rw-r--r--src/ru/olamedia/olacraft/network/packet/SectorDataPacket.java14
-rw-r--r--src/ru/olamedia/olacraft/network/provider/CacheProvider.java29
-rw-r--r--src/ru/olamedia/olacraft/network/provider/IProvider.java11
-rw-r--r--src/ru/olamedia/olacraft/network/provider/LocalProvider.java21
-rw-r--r--src/ru/olamedia/olacraft/network/provider/RemoteProvider.java19
-rw-r--r--src/ru/olamedia/olacraft/network/provider/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/render/jogl/ChunkRangeRenderer.java254
-rw-r--r--src/ru/olamedia/olacraft/render/jogl/DefaultRenderer.java29
-rw-r--r--src/ru/olamedia/olacraft/render/jogl/IRenderer.java1
-rw-r--r--src/ru/olamedia/olacraft/render/jogl/InventoryRenderer.java4
-rw-r--r--src/ru/olamedia/olacraft/render/jogl/joglViewport.java38
-rw-r--r--src/ru/olamedia/olacraft/scene/GameScene.java691
-rw-r--r--src/ru/olamedia/olacraft/world/biome/Biome.java10
-rw-r--r--src/ru/olamedia/olacraft/world/biome/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/world/block/Block.java372
-rw-r--r--src/ru/olamedia/olacraft/world/block/BlockRegistry.java31
-rw-r--r--src/ru/olamedia/olacraft/world/blockRenderer/AbstractBlockRenderer.java64
-rw-r--r--src/ru/olamedia/olacraft/world/blockRenderer/BoxRenderer.java282
-rw-r--r--src/ru/olamedia/olacraft/world/blockRenderer/ChunkMeshGarbageCollector.java82
-rw-r--r--src/ru/olamedia/olacraft/world/blockRenderer/ChunkRenderer.java356
-rw-r--r--src/ru/olamedia/olacraft/world/blockRenderer/CrossQuadsRenderer.java115
-rw-r--r--src/ru/olamedia/olacraft/world/blockRenderer/IBlockRenderer.java15
-rw-r--r--src/ru/olamedia/olacraft/world/blockRenderer/RenderLocation.java35
-rw-r--r--src/ru/olamedia/olacraft/world/blockRenderer/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/world/blockStack/BlockStack.java56
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/AbstractBlockType.java110
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/BlockType.java62
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/DirtBlockType.java6
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/EmptyBlockType.java6
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/GrassBlockType.java4
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/GravelBlockType.java4
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/IceBlockType.java32
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/SnowBlockType.java27
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/TallGrassBlockType.java58
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/WaterBlockType.java42
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/WheatBlockType.java58
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/stone/BrecciaStoneBlockType.java25
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/stone/ChertStoneBlockType.java25
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/stone/CoalStoneBlockType.java25
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/stone/ConglomerateStoneBlockType.java25
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/stone/LimestoneStoneBlockType.java25
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/stone/SandstoneStoneBlockType.java25
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/stone/ShaleStoneBlockType.java25
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/stone/SiltstoneStoneBlockType.java25
-rw-r--r--src/ru/olamedia/olacraft/world/blockTypes/stone/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/world/calc/LightCalculator.java118
-rw-r--r--src/ru/olamedia/olacraft/world/calc/LightData.java28
-rw-r--r--src/ru/olamedia/olacraft/world/calc/VisibilityCalculator.java99
-rw-r--r--src/ru/olamedia/olacraft/world/calc/VisibilityData.java30
-rw-r--r--src/ru/olamedia/olacraft/world/calc/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/world/chunk/BlockSlice.java22
-rw-r--r--src/ru/olamedia/olacraft/world/chunk/Chunk.java244
-rw-r--r--src/ru/olamedia/olacraft/world/chunk/ChunkMeshBulder.java11
-rw-r--r--src/ru/olamedia/olacraft/world/chunk/ChunkSlice.java19
-rw-r--r--src/ru/olamedia/olacraft/world/chunk/ChunkUnavailableException.java2
-rw-r--r--src/ru/olamedia/olacraft/world/data/ChunkData.java213
-rw-r--r--src/ru/olamedia/olacraft/world/data/ChunkDataManager.java22
-rw-r--r--src/ru/olamedia/olacraft/world/data/ChunkDataNeighbors.java162
-rw-r--r--src/ru/olamedia/olacraft/world/data/ChunkDataPointer.java82
-rw-r--r--src/ru/olamedia/olacraft/world/data/ChunkDataWrapper.java40
-rw-r--r--src/ru/olamedia/olacraft/world/data/RegionData.java24
-rw-r--r--src/ru/olamedia/olacraft/world/data/SectorData.java46
-rw-r--r--src/ru/olamedia/olacraft/world/dataProvider/AbstractChunkDataProvider.java12
-rw-r--r--src/ru/olamedia/olacraft/world/dataProvider/CachedChunkDataProvider.java93
-rw-r--r--src/ru/olamedia/olacraft/world/dataProvider/LocalChunkDataProvider.java76
-rw-r--r--src/ru/olamedia/olacraft/world/dataProvider/RemoteChunkDataProvider.java17
-rw-r--r--src/ru/olamedia/olacraft/world/drop/DroppedEntity.java17
-rw-r--r--src/ru/olamedia/olacraft/world/drop/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/world/fluid/FluidLevel.java9
-rw-r--r--src/ru/olamedia/olacraft/world/fluid/FluidLine.java56
-rw-r--r--src/ru/olamedia/olacraft/world/fluid/FluidSource.java99
-rw-r--r--src/ru/olamedia/olacraft/world/fluid/package-info.java8
-rw-r--r--src/ru/olamedia/olacraft/world/generator/HeightMapGenerator.java9
-rw-r--r--src/ru/olamedia/olacraft/world/generator/HumiditySelectLayer.java31
-rw-r--r--src/ru/olamedia/olacraft/world/generator/IslandSelectLayer.java31
-rw-r--r--src/ru/olamedia/olacraft/world/generator/MountainSelectLayer.java38
-rw-r--r--src/ru/olamedia/olacraft/world/generator/OceanSelectLayer.java31
-rw-r--r--src/ru/olamedia/olacraft/world/generator/RegionGenerator.java318
-rw-r--r--src/ru/olamedia/olacraft/world/generator/RiverSelectLayer.java56
-rw-r--r--src/ru/olamedia/olacraft/world/generator/TemperatureSelectLayer.java31
-rw-r--r--src/ru/olamedia/olacraft/world/location/BlockLocation.java88
-rw-r--r--src/ru/olamedia/olacraft/world/location/ChunkLocation.java21
-rw-r--r--src/ru/olamedia/olacraft/world/location/IntLocation.java200
-rw-r--r--src/ru/olamedia/olacraft/world/location/Location3f.java46
-rw-r--r--src/ru/olamedia/olacraft/world/location/Location3i.java71
-rw-r--r--src/ru/olamedia/olacraft/world/location/MetaLocation3i.java7
-rw-r--r--src/ru/olamedia/olacraft/world/location/RegionLocation.java36
-rw-r--r--src/ru/olamedia/olacraft/world/provider/IWorldProvider.java11
-rw-r--r--src/ru/olamedia/olacraft/world/provider/LocalWorld.java24
-rw-r--r--src/ru/olamedia/olacraft/world/provider/RemoteWorld.java32
-rw-r--r--src/ru/olamedia/olacraft/world/provider/WorldProvider.java144
-rw-r--r--src/ru/olamedia/player/Player.java436
-rw-r--r--src/ru/olamedia/player/RuntimeSettings.java5
-rw-r--r--src/ru/olamedia/texture/TextureManager.java64
178 files changed, 14045 insertions, 1279 deletions
diff --git a/src/jp/nyatla/nymmd/MmdException.java b/src/jp/nyatla/nymmd/MmdException.java
new file mode 100644
index 0000000..929d409
--- /dev/null
+++ b/src/jp/nyatla/nymmd/MmdException.java
@@ -0,0 +1,70 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd;
+
+
+
+public class MmdException extends Exception
+{
+ private static final long serialVersionUID = 1L;
+
+ public MmdException()
+ {
+ super();
+ }
+
+ public MmdException(Exception e)
+ {
+ super(e);
+ }
+
+ public MmdException(String m)
+ {
+ super(m);
+ }
+
+ public static void trap(String m) throws MmdException
+ {
+ throw new MmdException("トラップ:" + m);
+ }
+
+ public static void notImplement() throws MmdException
+ {
+ throw new MmdException("Not Implement!");
+ }
+}
diff --git a/src/jp/nyatla/nymmd/MmdMotionPlayer.java b/src/jp/nyatla/nymmd/MmdMotionPlayer.java
new file mode 100644
index 0000000..65b35ae
--- /dev/null
+++ b/src/jp/nyatla/nymmd/MmdMotionPlayer.java
@@ -0,0 +1,434 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd;
+
+import jp.nyatla.nymmd.core.PmdBone;
+import jp.nyatla.nymmd.core.PmdFace;
+import jp.nyatla.nymmd.core.PmdIK;
+import jp.nyatla.nymmd.types.*;
+
+public class MmdMotionPlayer {
+ protected MmdPmdModel_BasicClass _ref_pmd_model;
+ protected MmdVmdMotion_BasicClass _ref_vmd_motion;
+
+ private PmdBone[] m_ppBoneList;
+ private PmdFace[] m_ppFaceList;
+
+ public MmdMatrix[] _skinning_mat;
+
+ public PmdBone m_pNeckBone; // 首のボーン
+ public PmdBone m_centerBone; // センター
+ public PmdBone m_leftFootIK; // 左足IK先
+ public PmdBone m_rightFootIK; // 右足IK先
+ public PmdBone m_leftToe; // 左つま先
+ public PmdBone m_rightToe; // 右つま先
+ public PmdBone m_leftKnee; // 左ひざ
+ public PmdBone m_rightKnee; // 右ひざ
+ public PmdBone m_leftAnkle; // 左足首
+ public PmdBone m_rightAnkle; // 右足首
+ public PmdBone m_leftLeg; //
+ public PmdBone m_rightLeg; //
+ public PmdBone m_leftEyeDestination; // 左目先
+ public PmdBone m_rightEyeDestination; // 右目先
+ public PmdBone m_lowerBody; // 下半身
+ public PmdBone m_upperBody; // 上半身
+ public PmdBone m_leftArm; // 左腕
+ public PmdBone m_rightArm; // 右腕
+ public PmdBone m_leftElbow; // 左ひじ
+ public PmdBone m_rightElbow; // 右ひじ
+ public PmdBone m_leftWrist; // 左手首
+ public PmdBone m_rightWrist; // 右手首
+ public PmdBone m_skirtFrontLeft; //
+ public PmdBone m_skirtFrontRight; //
+
+ public MmdMotionPlayer() {
+ return;
+ }
+
+ public void setPmd(MmdPmdModel_BasicClass i_pmd_model) throws MmdException {
+ this._ref_pmd_model = i_pmd_model;
+ PmdBone[] bone_array = i_pmd_model.getBoneArray();
+ // スキニング用のmatrix
+ this._skinning_mat = MmdMatrix.createArray(bone_array.length);
+ // 首^H頭のボーンを探しておく
+ this.m_pNeckBone = null;
+ for (int i = 0; i < bone_array.length; i++) {
+ System.err.println("" + bone_array[i].getName() + "");
+ if (bone_array[i].getName().equals("頭")) {
+ this.m_pNeckBone = bone_array[i];
+ // break;
+ }
+ // センター先
+ if (bone_array[i].getName().equals("下半身")) {
+ this.m_lowerBody = bone_array[i];
+ }
+ if (bone_array[i].getName().equals("上半身")) {
+ this.m_upperBody = bone_array[i];
+ }
+
+ if (bone_array[i].getName().equals("左ス前2")) {
+ this.m_skirtFrontLeft = bone_array[i];
+ }
+ if (bone_array[i].getName().equals("左スカート前")) {
+ this.m_skirtFrontLeft = bone_array[i];
+ }
+ if (bone_array[i].getName().equals("右ス前2")) {
+ this.m_skirtFrontRight = bone_array[i];
+ }
+ if (bone_array[i].getName().equals("右スカート前")) {
+ this.m_skirtFrontRight = bone_array[i];
+ }
+ if (bone_array[i].getName().equals("左腕")) {
+ this.m_leftArm = bone_array[i];
+ }
+ if (bone_array[i].getName().equals("右腕")) {
+ this.m_rightArm = bone_array[i];
+ }
+
+ if (bone_array[i].getName().equals("左手首")) {
+ this.m_leftWrist = bone_array[i];
+ }
+ if (bone_array[i].getName().equals("右手首")) {
+ this.m_rightWrist = bone_array[i];
+ }
+ if (bone_array[i].getName().equals("左ひじ")) {
+ this.m_leftElbow = bone_array[i];
+ }
+ if (bone_array[i].getName().equals("右ひじ")) {
+ this.m_rightElbow = bone_array[i];
+ }
+ if (bone_array[i].getName().equals("左足")) {
+ this.m_leftLeg = bone_array[i];
+ }
+ if (bone_array[i].getName().equals("右足")) {
+ this.m_rightLeg = bone_array[i];
+ }
+ if (bone_array[i].getName().equals("左足首")) {
+ this.m_leftAnkle = bone_array[i];
+ }
+ if (bone_array[i].getName().equals("右足首")) {
+ this.m_rightAnkle = bone_array[i];
+ }
+ if (bone_array[i].getName().equals("左つま先")) {
+ this.m_leftToe = bone_array[i];
+ }
+ if (bone_array[i].getName().equals("右つま先")) {
+ this.m_rightToe = bone_array[i];
+ }
+ if (bone_array[i].getName().equals("左ひざ")) {
+ this.m_leftKnee = bone_array[i];
+ }
+ if (bone_array[i].getName().equals("右ひざ")) {
+ this.m_rightKnee = bone_array[i];
+ }
+ if (bone_array[i].getName().equals("左目")) {
+ this.m_leftEyeDestination = bone_array[i];
+ }
+ if (bone_array[i].getName().equals("右目先")) {
+ this.m_rightEyeDestination = bone_array[i];
+ }
+ if (bone_array[i].getName().equals("左足IK")) {
+ this.m_leftFootIK = bone_array[i];
+ }
+ if (bone_array[i].getName().equals("右足IK先")) {
+ this.m_rightFootIK = bone_array[i];
+ }
+ if (bone_array[i].getName().equals("センター先")) {
+ this.m_centerBone = bone_array[i];
+ }
+ }
+ // PMD/VMDが揃った?
+ if (this._ref_vmd_motion != null) {
+ makeBoneFaceList();
+ }
+ return;
+ }
+
+ public void setVmd(MmdVmdMotion_BasicClass i_vmd_model) throws MmdException {
+ this._ref_vmd_motion = i_vmd_model;
+ // 操作対象ボーンのポインタを設定する
+ MotionData[] pMotionDataList = i_vmd_model.refMotionDataArray();
+ this.m_ppBoneList = new PmdBone[pMotionDataList.length];
+ // 操作対象表情のポインタを設定する
+ FaceData[] pFaceDataList = i_vmd_model.refFaceDataArray();
+ this.m_ppFaceList = new PmdFace[pFaceDataList.length];
+ // PMD/VMDが揃った?
+ if (this._ref_pmd_model != null) {
+ makeBoneFaceList();
+ }
+ return;
+ }
+
+ private void makeBoneFaceList() {
+ MmdPmdModel_BasicClass pmd_model = this._ref_pmd_model;
+ MmdVmdMotion_BasicClass vmd_model = this._ref_vmd_motion;
+
+ // 操作対象ボーンのポインタを設定する
+ MotionData[] pMotionDataList = vmd_model.refMotionDataArray();
+ this.m_ppBoneList = new PmdBone[pMotionDataList.length];
+ for (int i = 0; i < pMotionDataList.length; i++) {
+ this.m_ppBoneList[i] = pmd_model.getBoneByName(pMotionDataList[i].szBoneName);
+ }
+ // 操作対象表情のポインタを設定する
+ FaceData[] pFaceDataList = vmd_model.refFaceDataArray();
+ this.m_ppFaceList = new PmdFace[pFaceDataList.length];
+ for (int i = 0; i < pFaceDataList.length; i++) {
+ this.m_ppFaceList[i] = pmd_model.getFaceByName(pFaceDataList[i].szFaceName);
+ }
+ return;
+ }
+
+ /**
+ * VMDの再生時間長を返します。
+ *
+ * @return
+ * ms単位の再生時間
+ */
+ public float getTimeLength() {
+ return (float) (this._ref_vmd_motion.getMaxFrame() * (100.0 / 3));
+ }
+
+ /**
+ * 指定した時刻のモーションに更新します。
+ *
+ * @param i_position_in_msec
+ * モーションの先頭からの時刻をms単位で指定します。
+ * @throws MmdException
+ */
+ public void updateMotion(float i_position_in_msec) throws MmdException {
+ final PmdIK[] ik_array = this._ref_pmd_model.getIKArray();
+ final PmdBone[] bone_array = this._ref_pmd_model.getBoneArray();
+ assert i_position_in_msec >= 0;
+ // 描画するフレームを計算する。
+ float frame = (float) (i_position_in_msec / (100.0 / 3));
+ // 範囲外を除外
+ if (frame > this._ref_vmd_motion.getMaxFrame()) {
+ frame = this._ref_vmd_motion.getMaxFrame();
+ }
+ this.updateFace(frame);
+
+ // モーション更新
+ // this.updateBone(frame);
+
+ // ボーン行列の更新
+ for (int i = 0; i < bone_array.length; i++) {
+ bone_array[i].updateMatrix();
+ }
+
+ // IKの更新
+ for (int i = 0; i < ik_array.length; i++) {
+ ik_array[i].update();
+ }
+ for (int i = 0; i < bone_array.length; i++) {
+ bone_array[i].updateMatrix();
+ }
+ // Lookme!
+ if (this._lookme_enabled) {
+ this.manualUpdateNeckBone();// updateNeckBone();
+ }
+ //
+ // スキニング用行列の更新
+ for (int i = 0; i < bone_array.length; i++) {
+ bone_array[i].updateSkinningMat(this._skinning_mat[i]);
+ }
+ this.onUpdateSkinningMatrix(this._skinning_mat);
+ return;
+ }
+
+ public void update() throws MmdException {
+ final PmdIK[] ik_array = this._ref_pmd_model.getIKArray();
+ final PmdBone[] bone_array = this._ref_pmd_model.getBoneArray();
+ for (int i = 0; i < ik_array.length; i++) {
+ // ik_array[i].update();
+ }
+ for (int i = 0; i < bone_array.length; i++) {
+ bone_array[i].updateMatrix();
+ }
+ for (int i = 0; i < bone_array.length; i++) {
+ bone_array[i].updateSkinningMat(this._skinning_mat[i]);
+ }
+ this.onUpdateSkinningMatrix(this._skinning_mat);
+ }
+
+ protected void onUpdateSkinningMatrix(MmdMatrix[] i_skinning_mat) throws MmdException {
+ throw new MmdException("Must be override onUpdateSkinningMatrix.");
+ }
+
+ public void setLookVector(float i_x, float i_y, float i_z) {
+ this._looktarget.x = i_x;
+ this._looktarget.y = i_y;
+ this._looktarget.z = i_z;
+ }
+
+ public void lookMeEnable(boolean i_enable) {
+ this._lookme_enabled = i_enable;
+ }
+
+ private MmdVector3 _looktarget = new MmdVector3();
+ private boolean _lookme_enabled = false;
+
+ /**
+ * look me
+ *
+ * @param pvec3LookTarget
+ */
+ private void updateNeckBone() {
+ if (this.m_pNeckBone == null) {
+ return;
+ }
+ this.m_pNeckBone.lookAt(this._looktarget);
+
+ PmdBone[] bone_array = this._ref_pmd_model.getBoneArray();
+ int i;
+ for (i = 0; i < bone_array.length; i++) {
+ if (this.m_pNeckBone == bone_array[i]) {
+ break;
+ }
+ }
+ for (; i < bone_array.length; i++) {
+ bone_array[i].updateMatrix();
+ }
+ return;
+ }
+
+ public void manualUpdateNeckBone() {
+ if (this.m_pNeckBone == null) {
+ return;
+ }
+
+ PmdBone[] bone_array = this._ref_pmd_model.getBoneArray();
+ int i;
+ for (i = 0; i < bone_array.length; i++) {
+ // if (this.m_pNeckBone == bone_array[i]) {
+ // break;
+ // }
+ // }
+ // for (; i < bone_array.length; i++) {
+ bone_array[i].updateMatrix();
+ }
+ return;
+ }
+
+ private void updateBone(float i_frame) throws MmdException {
+ // ---------------------------------------------------------
+ // 指定フレームのデータでボーンを動かす
+ final PmdBone[] ppBone = this.m_ppBoneList;
+
+ MotionData[] pMotionDataList = _ref_vmd_motion.refMotionDataArray();
+ for (int i = 0; i < pMotionDataList.length; i++) {
+ if (ppBone[i] == null) {
+ continue;
+ }
+ pMotionDataList[i].getMotionPosRot(i_frame, ppBone[i]);
+ // ppBone[i].m_vec3Position.setValue(vec3Position);
+ // 補間あり
+ // Vector3Lerp( &((*pBone)->m_vec3Position),
+ // &((*pBone)->m_vec3Position), &vec3Position, fLerpValue );
+ // QuaternionSlerp( &((*pBone)->m_vec4Rotate),
+ // &((*pBone)->m_vec4Rotate), &vec4Rotate, fLerpValue );
+ }
+ return;
+ }
+
+ /**
+ * 指定フレームのデータで表情を変形する
+ *
+ * @param i_frame
+ * @throws MmdException
+ */
+ private void updateFace(float i_frame) throws MmdException {
+ final MmdVector3[] position_array = this._ref_pmd_model.getPositionArray();
+ PmdFace[] ppFace = this.m_ppFaceList;
+ FaceData[] pFaceDataList = _ref_vmd_motion.refFaceDataArray();
+ for (int i = 0; i < pFaceDataList.length; i++) {
+ final float fFaceRate = getFaceRate(pFaceDataList[i], i_frame);
+ if (ppFace[i] == null) {
+ continue;
+ }
+ if (fFaceRate == 1.0f) {
+ ppFace[i].setFace(position_array);
+ } else if (0.001f < fFaceRate) {
+ ppFace[i].blendFace(position_array, fFaceRate);
+ }
+ }
+ return;
+ }
+
+ private float getFaceRate(FaceData pFaceData, float fFrame) {
+ int i;
+ int ulNumKeyFrame = pFaceData.ulNumKeyFrames;
+
+ // 最終フレームを過ぎていた場合
+ if (fFrame > pFaceData.pKeyFrames[ulNumKeyFrame - 1].fFrameNo) {
+ fFrame = pFaceData.pKeyFrames[ulNumKeyFrame - 1].fFrameNo;
+ }
+
+ // 現在の時間がどのキー近辺にあるか
+ for (i = 0; i < ulNumKeyFrame; i++) {
+ if (fFrame <= pFaceData.pKeyFrames[i].fFrameNo) {
+ break;
+ }
+ }
+
+ // 前後のキーを設定
+ int lKey0 = i - 1;
+ int lKey1 = i;
+
+ if (lKey0 <= 0) {
+ lKey0 = 0;
+ }
+ if (i == ulNumKeyFrame) {
+ lKey1 = ulNumKeyFrame - 1;
+ }
+
+ // 前後のキーの時間
+ float fTime0 = pFaceData.pKeyFrames[lKey0].fFrameNo;
+ float fTime1 = pFaceData.pKeyFrames[lKey1].fFrameNo;
+
+ // 前後のキーの間でどの位置にいるか
+ float fLerpValue;
+ if (lKey0 != lKey1) {
+ fLerpValue = (fFrame - fTime0) / (fTime1 - fTime0);
+ return (pFaceData.pKeyFrames[lKey0].fRate * (1.0f - fLerpValue))
+ + (pFaceData.pKeyFrames[lKey1].fRate * fLerpValue);
+ } else {
+ return pFaceData.pKeyFrames[lKey0].fRate;
+ }
+ }
+
+}
diff --git a/src/jp/nyatla/nymmd/MmdMotionPlayerGL2.java b/src/jp/nyatla/nymmd/MmdMotionPlayerGL2.java
new file mode 100644
index 0000000..c2f2882
--- /dev/null
+++ b/src/jp/nyatla/nymmd/MmdMotionPlayerGL2.java
@@ -0,0 +1,434 @@
+package jp.nyatla.nymmd;
+
+import java.awt.image.BufferedImage;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.nio.ShortBuffer;
+import java.util.ArrayList;
+import java.util.Vector;
+
+import javax.imageio.ImageIO;
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GLContext;
+
+import com.jogamp.opengl.util.texture.Texture;
+
+import ru.olamedia.olacraft.game.Game;
+import ru.olamedia.texture.TextureManager;
+
+import jp.nyatla.nymmd.core.PmdBone;
+import jp.nyatla.nymmd.types.*;
+
+public class MmdMotionPlayerGL2 extends MmdMotionPlayer {
+ private float minY = Float.MAX_VALUE;
+ private float maxY = Float.MAX_VALUE;
+ public float minX = Float.MAX_VALUE;
+ public float maxX = Float.MAX_VALUE;
+ public float minZ = Float.MAX_VALUE;
+ public float maxZ = Float.MAX_VALUE;
+ public float height = 0;
+ public float offsetX = 0;
+ public float offsetZ = 0;
+
+ private class TextureList extends ArrayList<TextureList.Item> {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ class Item {
+ public int gl_texture_id;
+ public String file_name;
+ }
+
+ public void clear() {
+ final GL2 gl = GLContext.getCurrentGL().getGL2();
+ for (TextureList.Item i : this) {
+ final int[] ids = { i.gl_texture_id };
+ gl.glDeleteTextures(1, ids, 0);
+ }
+ super.clear();
+ }
+
+ private TextureList.Item createTexture(String szFileName, InputStream i_st) throws MmdException {
+ final GL2 gl = GLContext.getCurrentGL().getGL2();
+ String ext = szFileName.substring(szFileName.length() - 3).toUpperCase();
+ String format = ext;
+ if (ext.equals("SPH")) {
+ format = "BMP";
+ }
+ if (ext.equals("SPA")) {
+ format = "BMP";
+ }
+ Texture tex = TextureManager.get(szFileName, i_st, format);
+ tex.setTexParameteri(gl, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_LINEAR);
+ tex.setTexParameteri(gl, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_LINEAR);
+ if (ext.equals("SPH") || ext.equals("SPA")) {
+ tex.setTexParameteri(gl, GL2.GL_TEXTURE_WRAP_S, GL2.GL_CLAMP_TO_EDGE);
+ tex.setTexParameteri(gl, GL2.GL_TEXTURE_WRAP_T, GL2.GL_CLAMP_TO_EDGE);
+ } else {
+ tex.setTexParameteri(gl, GL2.GL_TEXTURE_WRAP_S, GL2.GL_REPEAT);
+ tex.setTexParameteri(gl, GL2.GL_TEXTURE_WRAP_T, GL2.GL_REPEAT);
+ }
+ TextureList.Item ret = new TextureList.Item();
+ ret.file_name = szFileName;
+ ret.gl_texture_id = tex.getTextureObject(gl);
+ /*
+ * toonTexture.setWrap(Texture.WrapAxis.S,
+ * Texture.WrapMode.EdgeClamp);
+ * toonTexture.setWrap(Texture.WrapAxis.T,
+ * Texture.WrapMode.EdgeClamp);
+ * toonTexture.setMinFilter(Texture.MinFilter.BilinearNoMipMaps);
+ */
+ if (ext.equals("SPH")) {
+ }
+ if (ext.equals("SPA")) {
+ }
+ return ret;
+ /*
+ * IntBuffer texid = IntBuffer.allocate(1);
+ * BufferedImage img;
+ * try {
+ * img = ImageIO.read(i_st);
+ * } catch (Exception e) {
+ * throw new MmdException("Error while reading " + szFileName);
+ * }
+ * gl.glGenTextures(1, texid);
+ * gl.glBindTexture(GL.GL_TEXTURE_2D, texid.get(0));
+ * gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 4);
+ *
+ * gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER,
+ * GL.GL_LINEAR);
+ * gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER,
+ * GL.GL_LINEAR);
+ * 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);
+ * // 転写
+ *
+ * int[] rgb_array = img.getRGB(0, 0, img.getWidth(),
+ * img.getHeight(), null, 0, img.getWidth());
+ * gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, img.getWidth(),
+ * img.getHeight(), 0, GL.GL_RGBA,
+ * GL.GL_UNSIGNED_BYTE, IntBuffer.wrap(rgb_array));
+ * FloatBuffer prio = FloatBuffer.allocate(1);
+ * prio.put(0, 1.0f);
+ * gl.glPrioritizeTextures(1, texid, prio);
+ */
+ }
+
+ public int getTexture(String i_name, MmdPmdModel_BasicClass.IResourceProvider i_io) throws MmdException {
+ try {
+ for (TextureList.Item i : this) {
+ if (i.file_name.equalsIgnoreCase(i_name)) {
+ // 読み込み済みのテクスチャを発見
+ return i.gl_texture_id;
+ }
+ }
+ // なければファイルを読み込んでテクスチャ作成
+ TextureList.Item ret = this.createTexture(i_name, i_io.getTextureStream(i_name));
+ if (ret != null) {
+ this.add(ret);
+ return ret.gl_texture_id;
+ }
+ } catch (Exception e) {
+ throw new MmdException(e);
+ }
+ // テクスチャ読み込みか作成失敗
+ throw new MmdException();
+ }
+ }
+
+ private class Material {
+ public final float[] color = new float[12];// Diffuse,Specular,Ambientの順
+ public float fShininess;
+ public ShortBuffer indices;
+ public int ulNumIndices;
+ public int texture_id;
+ public int sph_texture_id;
+ public int unknown;
+ }
+
+ public MmdMotionPlayerGL2() {
+ super();
+ this._tex_list = new TextureList();
+ }
+
+ public void dispose() {
+ this._tex_list.clear();
+ }
+
+ private TextureList _tex_list;
+ private final MmdMatrix __tmp_matrix = new MmdMatrix();
+ private Material[] _materials;
+ private float[] _fbuf;
+ private FloatBuffer _pos_array;
+ private FloatBuffer _nom_array;
+ private FloatBuffer _tex_array;
+
+ public void setPmd(MmdPmdModel_BasicClass i_pmd_model) throws MmdException {
+ super.setPmd(i_pmd_model);
+
+ // 確保済みリソースのリセット
+ this._tex_list.clear();
+ // OpenGLResourceの生成
+ final int number_of_vertex = i_pmd_model.getNumberOfVertex();
+ this._pos_array = makeFloatBuffer(number_of_vertex * 3);
+ this._nom_array = makeFloatBuffer(number_of_vertex * 3);
+ this._tex_array = makeFloatBuffer(this._ref_pmd_model.getUvArray().length * 2);
+ this._fbuf = new float[number_of_vertex * 3 * 2];
+
+ MmdPmdModel_BasicClass.IResourceProvider tp = i_pmd_model.getResourceProvider();
+
+ // Material配列の作成
+ PmdMaterial[] m = i_pmd_model.getMaterials();// this._ref_materials;
+ Vector<Material> materials = new Vector<Material>();
+ for (int i = 0; i < m.length; i++) {
+ final Material new_material = new Material();
+ new_material.unknown = m[i].unknown;
+ // D,A,S[rgba]
+ m[i].col4Diffuse.getValue(new_material.color, 0);
+ m[i].col4Ambient.getValue(new_material.color, 4);
+ m[i].col4Specular.getValue(new_material.color, 8);
+ new_material.fShininess = m[i].fShininess;
+ if (m[i].texture_name != null) {
+ new_material.texture_id = this._tex_list.getTexture(m[i].texture_name, tp);
+ System.out.println("" + m[i].texture_name);
+ } else {
+ new_material.texture_id = 0;
+ }
+ if (m[i].sphere_name != null) {
+ new_material.sph_texture_id = this._tex_list.getTexture(m[i].sphere_name, tp);
+ System.out.println("" + m[i].sphere_name);
+ } else {
+ new_material.sph_texture_id = 0;
+ }
+ new_material.indices = ShortBuffer.wrap(m[i].indices);
+ new_material.ulNumIndices = m[i].indices.length;
+ materials.add(new_material);
+ }
+ this._materials = materials.toArray(new Material[materials.size()]);
+ // Integer.MAX_VALUE
+ FloatBuffer tex_array = this._tex_array;
+ tex_array.position(0);
+ final MmdTexUV[] texture_uv = this._ref_pmd_model.getUvArray();
+ for (int i = 0; i < number_of_vertex; i++) {
+ tex_array.put(texture_uv[i].u);
+ tex_array.put(texture_uv[i].v);
+ }
+ // find model height
+ MmdVector3[] org_pos_array = _ref_pmd_model.getPositionArray();
+
+ for (int i = 0; i < _ref_pmd_model.getNumberOfVertex(); i++) {
+ MmdVector3 vp = org_pos_array[i];
+ if (minY == Float.MAX_VALUE) {
+ minY = maxY = vp.y;
+ minX = maxX = vp.x;
+ minZ = maxZ = vp.z;
+ } else {
+ if (vp.y < minY) {
+ minY = vp.y;
+ }
+ if (vp.y > maxY) {
+ maxY = vp.y;
+ }
+ if (vp.x < minX) {
+ minX = vp.x;
+ }
+ if (vp.x > maxX) {
+ maxX = vp.x;
+ }
+ if (vp.z < minZ) {
+ minZ = vp.z;
+ }
+ if (vp.z > maxZ) {
+ maxZ = vp.z;
+ }
+ }
+ }
+ height = maxY - minY;
+ offsetX = minX + (maxX - minX) / 2;
+ offsetZ = minZ + (maxZ - minZ) / 2;
+ return;
+ }
+
+ public void setVmd(MmdVmdMotion_BasicClass i_vmd_model) throws MmdException {
+ super.setVmd(i_vmd_model);
+ }
+
+ /**
+ * この関数はupdateMotionがskinning_matを更新するを呼び出します。
+ */
+ protected void onUpdateSkinningMatrix(MmdMatrix[] i_skinning_mat) throws MmdException {
+ MmdVector3 vp;
+ MmdMatrix mat;
+ MmdVector3[] org_pos_array = this._ref_pmd_model.getPositionArray();
+ MmdVector3[] org_normal_array = this._ref_pmd_model.getNormatArray();
+ PmdSkinInfo[] org_skin_info = this._ref_pmd_model.getSkinInfoArray();
+
+ int number_of_vertex = this._ref_pmd_model.getNumberOfVertex();
+ float[] ft = this._fbuf;
+ int p1 = 0;
+ int p2 = number_of_vertex * 3;
+ for (int i = 0; i < this._ref_pmd_model.getNumberOfVertex(); i++) {
+ PmdSkinInfo info_ptr = org_skin_info[i];
+ if (info_ptr.fWeight == 0.0f) {
+ mat = i_skinning_mat[info_ptr.unBoneNo_1];
+ } else if (info_ptr.fWeight >= 0.9999f) {
+ mat = i_skinning_mat[info_ptr.unBoneNo_0];
+ } else {
+ final MmdMatrix mat0 = i_skinning_mat[info_ptr.unBoneNo_0];
+ final MmdMatrix mat1 = i_skinning_mat[info_ptr.unBoneNo_1];
+ mat = this.__tmp_matrix;
+ mat.MatrixLerp(mat0, mat1, info_ptr.fWeight);
+ }
+ vp = org_pos_array[i];
+ ft[p1++] = ((float) (vp.x * mat.m00 + vp.y * mat.m10 + vp.z * mat.m20 + mat.m30));
+ ft[p1++] = ((float) (vp.x * mat.m01 + vp.y * mat.m11 + vp.z * mat.m21 + mat.m31));
+ ft[p1++] = ((float) (vp.x * mat.m02 + vp.y * mat.m12 + vp.z * mat.m22 + mat.m32));
+
+ vp = org_normal_array[i];
+ ft[p2++] = ((float) (vp.x * mat.m00 + vp.y * mat.m10 + vp.z * mat.m20));
+ ft[p2++] = ((float) (vp.x * mat.m01 + vp.y * mat.m11 + vp.z * mat.m21));
+ ft[p2++] = ((float) (vp.x * mat.m02 + vp.y * mat.m12 + vp.z * mat.m22));
+ }
+ this._pos_array.position(0);
+ this._pos_array.put(ft, 0, number_of_vertex * 3);
+ this._nom_array.position(0);
+ this._nom_array.put(ft, number_of_vertex * 3, number_of_vertex * 3);
+ return;
+ }
+
+ public void render() throws MmdException {
+ final GL2 gl = GLContext.getCurrentGL().getGL2();
+ // gl.glEnable(GL.GL_CULL_FACE);
+ gl.glEnable(GL.GL_DEPTH_TEST);
+ gl.glShadeModel(GL2.GL_SMOOTH);
+ // gl.glCullFace(GL.GL_FRONT);
+ gl.glCullFace(GL.GL_BACK);
+ gl.glEnable(GL2.GL_NORMALIZE);
+ gl.glEnable(GL2.GL_BLEND);
+ // GLUtils.texImage2D generates premultiplied-alpha texture. so we use
+ // GL_ONE instead of GL_ALPHA
+ gl.glBlendFunc(GL2.GL_ONE, GL2.GL_ONE_MINUS_SRC_ALPHA);
+ // gl.glEnableClientState(GL2.GL_COLOR_ARRAY);
+ gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);
+ gl.glEnableClientState(GL2.GL_NORMAL_ARRAY);
+ gl.glEnableClientState(GL2.GL_TEXTURE_COORD_ARRAY);
+ gl.glEnable(GL2.GL_COLOR_MATERIAL);
+ gl.glTexEnvf(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_MODULATE);
+ gl.glEnable(GL2.GL_LIGHTING);
+ gl.glEnable(GL2.GL_LIGHT0);
+ final float[] diffuseColor = Game.client.getScene().dayTime.getClearColor();
+ gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_SPECULAR, new float[] { 1.0f, 1.0f, 1.0f }, 0);
+ gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_AMBIENT, diffuseColor, 0);//new float[] { 0f, 0f, 0f }
+ gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_DIFFUSE, diffuseColor, 0);// new
+ // float[]
+ // {
+ // 1.0f,
+ // 1.0f,
+ // 1.0f
+ // }
+ // とりあえずbufferに変換しよう
+ this._pos_array.position(0);
+ this._nom_array.position(0);
+ this._tex_array.position(0);
+ // とりあえず転写用
+
+ // 頂点座標、法線、テクスチャ座標の各配列をセット
+ gl.glVertexPointer(3, GL.GL_FLOAT, 0, this._pos_array);
+ gl.glNormalPointer(GL.GL_FLOAT, 0, this._nom_array);
+ gl.glTexCoordPointer(2, GL.GL_FLOAT, 0, this._tex_array);
+ if (null == this._materials) {
+ throw new MmdException("no materials");
+ }
+ for (int i = this._materials.length - 1; i >= 0; i--) {
+ final Material mt_ptr = this._materials[i];
+ // マテリアル設定
+// gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL2.GL_DIFFUSE, mt_ptr.color, 0);
+// gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL2.GL_AMBIENT, mt_ptr.color, 4);
+// gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL2.GL_SPECULAR, mt_ptr.color, 8);
+// gl.glMaterialf(GL.GL_FRONT_AND_BACK, GL2.GL_SHININESS, mt_ptr.fShininess);
+ final float wi = 0.6f;
+ final float[] color = mt_ptr.color;
+ gl.glColor4f((color[0] * wi + color[8 + 0]), (color[1] * wi + color[8 + 1]),
+ (color[2] * wi + color[8 + 2]), color[3]);// * wi
+ // +
+ // color[8
+ // +
+ // 3]
+ // don't cull face that has alpha value 0.99
+ if (color[3] < 1) {
+ gl.glDisable(GL2.GL_CULL_FACE);
+ } else {
+ gl.glEnable(GL2.GL_CULL_FACE);
+ }
+ // カリング判定:何となくうまくいったから
+ // if ((0x100 & mt_ptr.unknown) == 0x100) {
+ // gl.glDisable(GL.GL_CULL_FACE);
+ // } else {
+ // gl.glEnable(GL.GL_CULL_FACE);
+ // }
+
+ if (mt_ptr.texture_id != 0) {
+ // テクスチャありならBindする
+ gl.glEnable(GL.GL_TEXTURE_2D);
+ gl.glBindTexture(GL.GL_TEXTURE_2D, mt_ptr.texture_id);
+ } else {
+ // テクスチャなし
+ gl.glDisable(GL.GL_TEXTURE_2D);
+ }
+ if (mt_ptr.ulNumIndices > 0 && mt_ptr.indices.limit() > 0) {
+ // 頂点インデックスを指定してポリゴン描画
+ gl.glDrawElements(GL.GL_TRIANGLES, mt_ptr.ulNumIndices, GL.GL_UNSIGNED_SHORT, mt_ptr.indices);
+ }
+ if (mt_ptr.sph_texture_id != 0) {
+ gl.glEnable(GL.GL_TEXTURE_2D);
+ gl.glTexGeni(GL2.GL_S, GL2.GL_TEXTURE_GEN_MODE, GL2.GL_SPHERE_MAP);
+ gl.glTexGeni(GL2.GL_T, GL2.GL_TEXTURE_GEN_MODE, GL2.GL_SPHERE_MAP);
+ // gl.glTexGeni(GL2.GL_R, GL2.GL_TEXTURE_GEN_MODE,
+ // GL2.GL_REFLECTION_MAP);
+
+ gl.glEnable(GL2.GL_TEXTURE_GEN_S);
+ gl.glEnable(GL2.GL_TEXTURE_GEN_T);
+ // gl.glEnable(GL2.GL_TEXTURE_GEN_R);
+ gl.glBindTexture(GL.GL_TEXTURE_2D, mt_ptr.sph_texture_id);
+ }
+ if (mt_ptr.ulNumIndices > 0 && mt_ptr.indices.limit() > 0) {
+ // 頂点インデックスを指定してポリゴン描画
+ gl.glDrawElements(GL.GL_TRIANGLES, mt_ptr.ulNumIndices, GL.GL_UNSIGNED_SHORT, mt_ptr.indices);
+ }
+ if (mt_ptr.sph_texture_id != 0) {
+ gl.glDisable(GL2.GL_TEXTURE_GEN_S);
+ gl.glDisable(GL2.GL_TEXTURE_GEN_T);
+ // gl.glDisable(GL2.GL_TEXTURE_GEN_R);
+ }
+
+ }
+ // gl.glDisableClientState(GL2.GL_COLOR_ARRAY);
+ gl.glDisableClientState(GL2.GL_VERTEX_ARRAY);
+ gl.glDisableClientState(GL2.GL_NORMAL_ARRAY);
+ gl.glDisableClientState(GL2.GL_TEXTURE_COORD_ARRAY);
+ return;
+ }
+
+ private static FloatBuffer makeFloatBuffer(int i_size) {
+ ByteBuffer bb = ByteBuffer.allocateDirect(i_size * 4);
+ bb.order(ByteOrder.nativeOrder());
+ FloatBuffer fb = bb.asFloatBuffer();
+ return fb;
+ }
+
+ public void reset() {
+ final PmdBone[] bone_array = _ref_pmd_model.getBoneArray();
+ for (int i = 0; i < bone_array.length; i++) {
+ // bone_array[i].reset();
+ }
+ }
+
+}
diff --git a/src/jp/nyatla/nymmd/MmdPmdModel.java b/src/jp/nyatla/nymmd/MmdPmdModel.java
new file mode 100644
index 0000000..e4a4d10
--- /dev/null
+++ b/src/jp/nyatla/nymmd/MmdPmdModel.java
@@ -0,0 +1,74 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+
+/**
+ * ファイルシステムからPMDファイルを読み込むようにラップした{@link MmdPmdModel_BasicClass}
+ */
+public class MmdPmdModel extends MmdPmdModel_BasicClass {
+ public MmdPmdModel(String i_pmd_file_path) throws FileNotFoundException, MmdException {
+ super(new FileInputStream(i_pmd_file_path), new FileResourceProvider(i_pmd_file_path));
+ }
+
+ protected MmdPmdModel(InputStream i_stream, IResourceProvider i_res_provider) throws FileNotFoundException,
+ MmdException {
+ super(i_stream, i_res_provider);
+ }
+
+ protected static class FileResourceProvider implements IResourceProvider {
+ String _dir;
+
+ public FileResourceProvider(String i_pmd_file_path) {
+ File f = new File(i_pmd_file_path);// pmdのパス
+ this._dir = (f.getParentFile().getPath());
+ }
+
+ public InputStream getTextureStream(String i_name) throws MmdException {
+ try {
+ return new FileInputStream(this._dir + File.separator + i_name);
+ } catch (Exception e) {
+ throw new MmdException(e);
+ }
+ }
+ }
+}
diff --git a/src/jp/nyatla/nymmd/MmdPmdModel_BasicClass.java b/src/jp/nyatla/nymmd/MmdPmdModel_BasicClass.java
new file mode 100644
index 0000000..9c48c92
--- /dev/null
+++ b/src/jp/nyatla/nymmd/MmdPmdModel_BasicClass.java
@@ -0,0 +1,317 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd;
+
+import java.util.*;
+import java.io.*;
+
+import com.jogamp.opengl.util.texture.Texture;
+
+import jp.nyatla.nymmd.core.*;
+import jp.nyatla.nymmd.struct.*;
+import jp.nyatla.nymmd.struct.pmd.*;
+import jp.nyatla.nymmd.types.*;
+
+class DataComparator implements java.util.Comparator<PmdIK> {
+ public int compare(PmdIK o1, PmdIK o2) {
+ return (int) (o1.getSortVal() - o2.getSortVal());
+ }
+}
+
+/**
+ * PmdModelデータの格納クラス。PmdModelに関わるデータを提供します。
+ * 抽象関数 getResourceProviderを実装してください。
+ */
+public abstract class MmdPmdModel_BasicClass {
+ private String _name; // モデル名
+ private int _number_of_vertex; // 頂点数
+
+ private PmdFace[] m_pFaceArray; // 表情配列
+ private PmdBone[] m_pBoneArray; // ボーン配列
+ private PmdIK[] m_pIKArray; // IK配列
+
+ private MmdVector3[] _position_array; // 座標配列
+ private MmdVector3[] _normal_array; // 法線配列
+ private MmdTexUV[] _texture_uv; // テクスチャ座標配列
+ private PmdSkinInfo[] _skin_info_array;
+ private PmdMaterial[] _materials; // マテリアル配列
+ private IResourceProvider _res_provider;
+
+ public interface IResourceProvider {
+ public InputStream getTextureStream(String i_name) throws MmdException;
+ }
+
+ public MmdPmdModel_BasicClass(InputStream i_stream, IResourceProvider i_provider) throws MmdException {
+ initialize(i_stream);
+ this._res_provider = i_provider;
+ return;
+ }
+
+ public int getNumberOfVertex() {
+ return this._number_of_vertex;
+ }
+
+ public PmdMaterial[] getMaterials() {
+ return this._materials;
+ }
+
+ public MmdTexUV[] getUvArray() {
+ return this._texture_uv;
+ }
+
+ public MmdVector3[] getPositionArray() {
+ return this._position_array;
+ }
+
+ public MmdVector3[] getNormatArray() {
+ return this._normal_array;
+ }
+
+ public PmdSkinInfo[] getSkinInfoArray() {
+ return this._skin_info_array;
+ }
+
+ public PmdFace[] getFaceArray() {
+ return this.m_pFaceArray;
+ }
+
+ public PmdBone[] getBoneArray() {
+ return this.m_pBoneArray;
+ }
+
+ public PmdIK[] getIKArray() {
+ return this.m_pIKArray;
+ }
+
+ public PmdBone getBoneByName(String i_name) {
+ final PmdBone[] bone_array = this.m_pBoneArray;
+ for (int i = 0; i < bone_array.length; i++) {
+ final PmdBone bone = bone_array[i];
+ if (bone.getName().equals(i_name))
+ return bone;
+ }
+ return null;
+ }
+
+ public PmdFace getFaceByName(String i_name) {
+ final PmdFace[] face_array = this.m_pFaceArray;
+ for (int i = 0; i < face_array.length; i++) {
+ final PmdFace face = face_array[i];
+ if (face.getName().equals(i_name))
+ return face;
+ }
+ return null;
+ }
+
+ private void initialize(InputStream i_stream) throws MmdException {
+ DataReader reader = new DataReader(i_stream);
+ PMD_Header pPMDHeader = new PMD_Header();
+ pPMDHeader.read(reader);
+ if (!pPMDHeader.szMagic.equalsIgnoreCase("PMD")) {
+ throw new MmdException();
+ }
+
+ this._name = pPMDHeader.szName;
+
+ // -----------------------------------------------------
+ // 頂点数取得
+ this._number_of_vertex = reader.readInt();//
+ if (this._number_of_vertex < 0) {
+ throw new MmdException();
+ }
+
+ // 頂点配列をコピー
+ this._position_array = MmdVector3.createArray(this._number_of_vertex);
+ this._normal_array = MmdVector3.createArray(this._number_of_vertex);
+ this._texture_uv = MmdTexUV.createArray(this._number_of_vertex);
+ this._skin_info_array = new PmdSkinInfo[this._number_of_vertex];
+
+ PMD_Vertex tmp_pmd_vertex = new PMD_Vertex();
+ for (int i = 0; i < _number_of_vertex; i++) {
+ tmp_pmd_vertex.read(reader);
+ _position_array[i].setValue(tmp_pmd_vertex.vec3Pos);
+ _normal_array[i].setValue(tmp_pmd_vertex.vec3Normal);
+ _texture_uv[i].setValue(tmp_pmd_vertex.uvTex);
+
+ this._skin_info_array[i] = new PmdSkinInfo();
+ this._skin_info_array[i].fWeight = tmp_pmd_vertex.cbWeight / 100.0f;
+ this._skin_info_array[i].unBoneNo_0 = tmp_pmd_vertex.unBoneNo[0];
+ this._skin_info_array[i].unBoneNo_1 = tmp_pmd_vertex.unBoneNo[1];
+ }
+ // -----------------------------------------------------
+ // 頂点インデックス数取得
+ short[] indices_array = createIndicesArray(reader);
+
+ // -----------------------------------------------------
+ // マテリアル数取得
+ int number_of_materials = reader.readInt();
+
+ // マテリアル配列をコピー
+ this._materials = new PmdMaterial[number_of_materials];
+
+ PMD_Material tmp_pmd_material = new PMD_Material();
+
+ int indices_ptr = 0;
+ for (int i = 0; i < number_of_materials; i++) {
+ tmp_pmd_material.read(reader);
+ PmdMaterial pmdm = new PmdMaterial();
+ pmdm.unknown = tmp_pmd_material.unknown;
+ final int num_of_indices = tmp_pmd_material.ulNumIndices;
+
+ pmdm.indices = new short[num_of_indices];
+ System.arraycopy(indices_array, indices_ptr, pmdm.indices, 0, num_of_indices);
+ indices_ptr += num_of_indices;
+
+ pmdm.col4Diffuse.setValue(tmp_pmd_material.col4Diffuse);
+
+ pmdm.col4Specular.r = tmp_pmd_material.col3Specular.r;
+ pmdm.col4Specular.g = tmp_pmd_material.col3Specular.g;
+ pmdm.col4Specular.b = tmp_pmd_material.col3Specular.b;
+ pmdm.col4Specular.a = 1.0f;
+
+ pmdm.col4Ambient.r = tmp_pmd_material.col3Ambient.r;
+ pmdm.col4Ambient.g = tmp_pmd_material.col3Ambient.g;
+ pmdm.col4Ambient.b = tmp_pmd_material.col3Ambient.b;
+ pmdm.col4Ambient.a = 1.0f;
+
+ pmdm.fShininess = tmp_pmd_material.fShininess;
+
+ pmdm.texture_name = tmp_pmd_material.szTextureFileName;
+ if (pmdm.texture_name.length() < 1) {
+ pmdm.texture_name = null;
+ final int toon = tmp_pmd_material.toon + 1;
+ String t = "" + toon;
+ if (toon < 9 && toon > 0) {
+ t = "0" + t;
+ }
+ pmdm.texture_name = "toon" + t + ".bmp";
+ } else {
+ if (pmdm.texture_name.indexOf("*") >= 0) {
+ pmdm.sphere_name = pmdm.texture_name.substring(pmdm.texture_name.indexOf("*") + 1);
+ pmdm.texture_name = pmdm.texture_name.substring(0, pmdm.texture_name.indexOf("*"));
+ }
+ }
+
+ System.err.println(pmdm.texture_name);
+ this._materials[i] = pmdm;
+
+ }
+
+ // Boneの読み出し
+ this.m_pBoneArray = createBoneArray(reader);
+ // IK配列の読み出し
+ this.m_pIKArray = createIKArray(reader, this.m_pBoneArray);
+ // Face配列の読み出し
+ this.m_pFaceArray = createFaceArray(reader);
+
+ final PmdFace[] face_array = this.m_pFaceArray;
+ if (face_array != null) {
+ face_array[0].setFace(this._position_array);
+ }
+ return;
+ }
+
+ private static short[] createIndicesArray(DataReader i_reader) throws MmdException {
+ int num_of_indeces = i_reader.readInt();
+ short[] result = new short[num_of_indeces];
+ result = new short[num_of_indeces];
+
+ // 頂点インデックス配列をコピー
+ for (int i = 0; i < num_of_indeces; i++) {
+ result[i] = i_reader.readShort();
+ }
+ return result;
+ }
+
+ private static PmdBone[] createBoneArray(DataReader i_reader) throws MmdException {
+ final int number_of_bone = i_reader.readShort();
+ PMD_Bone tmp_pmd_bone = new PMD_Bone();
+
+ PmdBone[] result = new PmdBone[number_of_bone];
+ for (int i = 0; i < number_of_bone; i++) {
+ tmp_pmd_bone.read(i_reader);
+ // ボーンの親子関係を一緒に読みだすので。
+ result[i] = new PmdBone(tmp_pmd_bone, result);
+ }
+ for (int i = 0; i < number_of_bone; i++) {
+ result[i].recalcOffset();
+ }
+ return result;
+ }
+
+ private static PmdIK[] createIKArray(DataReader i_reader, PmdBone[] i_ref_bone_array) throws MmdException {
+ final int number_of_ik = i_reader.readShort();
+ PMD_IK tmp_pmd_ik = new PMD_IK();
+ PmdIK[] result = new PmdIK[number_of_ik];
+ // IK配列を作成
+ if (number_of_ik > 0) {
+
+ for (int i = 0; i < number_of_ik; i++) {
+ tmp_pmd_ik.read(i_reader);
+ result[i] = new PmdIK(tmp_pmd_ik, i_ref_bone_array);
+ }
+ Arrays.sort(result, new DataComparator());
+ }
+ return result;
+ }
+
+ private static PmdFace[] createFaceArray(DataReader i_reader) throws MmdException {
+ final int number_of_face = i_reader.readShort();
+ PMD_FACE tmp_pmd_face = new PMD_FACE();
+ PmdFace[] result = new PmdFace[number_of_face];
+
+ // 表情配列を作成
+ if (number_of_face > 0) {
+
+ for (int i = 0; i < number_of_face; i++) {
+ tmp_pmd_face.read(i_reader);
+ result[i] = new PmdFace(tmp_pmd_face, result[0]);
+ }
+ }
+ return result;
+ }
+
+ public String getModelName() {
+ return this._name;
+ }
+
+ public IResourceProvider getResourceProvider() {
+ return this._res_provider;
+ }
+
+}
diff --git a/src/jp/nyatla/nymmd/MmdVmdMotion.java b/src/jp/nyatla/nymmd/MmdVmdMotion.java
new file mode 100644
index 0000000..8f6fdce
--- /dev/null
+++ b/src/jp/nyatla/nymmd/MmdVmdMotion.java
@@ -0,0 +1,55 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+
+public class MmdVmdMotion extends MmdVmdMotion_BasicClass
+{
+ public MmdVmdMotion(String i_vmd_file_path) throws FileNotFoundException, MmdException
+ {
+ super(new FileInputStream(i_vmd_file_path));
+ }
+
+ protected MmdVmdMotion(InputStream i_stream) throws MmdException {
+ super(i_stream);
+ }
+
+}
diff --git a/src/jp/nyatla/nymmd/MmdVmdMotion_BasicClass.java b/src/jp/nyatla/nymmd/MmdVmdMotion_BasicClass.java
new file mode 100644
index 0000000..75d07b1
--- /dev/null
+++ b/src/jp/nyatla/nymmd/MmdVmdMotion_BasicClass.java
@@ -0,0 +1,290 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd;
+
+import java.util.*;
+
+import java.util.Arrays;
+import java.io.*;
+
+
+import jp.nyatla.nymmd.struct.DataReader;
+import jp.nyatla.nymmd.struct.vmd.VMD_Face;
+import jp.nyatla.nymmd.struct.vmd.VMD_Header;
+import jp.nyatla.nymmd.struct.vmd.VMD_Motion;
+import jp.nyatla.nymmd.types.*;
+
+//------------------------------
+//ボーンキーフレームソート用比較関数
+//------------------------------
+class BoneCompare implements java.util.Comparator<BoneKeyFrame>
+{
+ public int compare(BoneKeyFrame o1, BoneKeyFrame o2)
+ {
+ return (int)(o1.fFrameNo - o2.fFrameNo);
+ }
+}
+
+
+//------------------------------
+//表情キーフレームソート用比較関数
+//------------------------------
+class FaceCompare implements java.util.Comparator<FaceKeyFrame>
+{
+ public int compare(FaceKeyFrame o1, FaceKeyFrame o2)
+ {
+ return (int)(o1.fFrameNo - o2.fFrameNo);
+ }
+}
+
+public class MmdVmdMotion_BasicClass
+{
+ private MotionData[] _motion_data_array; // ボーンごとのキーフレームデータのリスト
+ private FaceData[] _face_data_array; // 表情ごとのキーフレームデータのリスト
+ private float _fMaxFrame; // 最後のフレーム番号
+
+ public MmdVmdMotion_BasicClass(InputStream i_stream) throws MmdException
+ {
+ initialize(i_stream);
+ return;
+ }
+
+ public MotionData[] refMotionDataArray()
+ {
+ return this._motion_data_array;
+ }
+ public FaceData[] refFaceDataArray()
+ {
+ return this._face_data_array;
+ }
+
+ public float getMaxFrame()
+ {
+ return this._fMaxFrame;
+ }
+
+
+ private boolean initialize(InputStream i_st) throws MmdException
+ {
+
+ DataReader reader=new DataReader(i_st);
+
+ // ヘッダのチェック
+ VMD_Header tmp_vmd_header=new VMD_Header();
+ tmp_vmd_header.read(reader);
+ if(!tmp_vmd_header.szHeader.equalsIgnoreCase("Vocaloid Motion Data 0002"))
+ {
+ throw new MmdException();
+ }
+ //ボーンと最大フレームを取得
+ float[] max_frame=new float[1];
+ this._motion_data_array=createMotionDataList(reader,max_frame);
+ this._fMaxFrame=max_frame[0];
+
+ //表情と最大フレームを再取得
+ this._face_data_array=createFaceDataList(reader,max_frame);
+ this._fMaxFrame=this._fMaxFrame>max_frame[0]?this._fMaxFrame:max_frame[0];
+
+ return true;
+ }
+
+ private static FaceData[] createFaceDataList(DataReader i_reader,float[] o_max_frame) throws MmdException
+ {
+ //-----------------------------------------------------
+ // 表情のキーフレーム数を取得
+ Vector<FaceData> result=new Vector<FaceData>();
+ int ulNumFaceKeyFrames=i_reader.readInt();
+
+ //規定フレーム数分表情を読み込み
+ VMD_Face[] tmp_vmd_face=new VMD_Face[ulNumFaceKeyFrames];
+ for(int i=0;i<ulNumFaceKeyFrames;i++){
+ tmp_vmd_face[i]= new VMD_Face();
+ tmp_vmd_face[i].read(i_reader);
+ }
+ float max_frame=0.0f;
+ for(int i = 0 ; i < ulNumFaceKeyFrames ; i++)
+ {
+ if(max_frame < (float)tmp_vmd_face[i].ulFrameNo ){
+ max_frame = (float)tmp_vmd_face[i].ulFrameNo; // 最大フレーム更新
+ }
+ boolean is_found=false;
+ for(int i2=0;i2<result.size();i2++)
+ {
+ final FaceData pFaceTemp = result.get(i2);
+ if(pFaceTemp.szFaceName.equals(tmp_vmd_face[i].szFaceName))
+ {
+ // リストに追加済み
+ pFaceTemp.ulNumKeyFrames++;
+ is_found=true;
+ break;
+ }
+ }
+
+ if(!is_found)
+ {
+ // リストにない場合は新規ノードを追加
+ FaceData pNew = new FaceData();
+ pNew.szFaceName=tmp_vmd_face[i].szFaceName;
+ pNew.ulNumKeyFrames = 1;
+ result.add(pNew);
+ }
+ }
+
+ // キーフレーム配列を確保
+ for(int i=0;i<result.size();i++)
+ {
+ FaceData pFaceTemp=result.get(i);
+ pFaceTemp.pKeyFrames = FaceKeyFrame.createArray(pFaceTemp.ulNumKeyFrames);
+ pFaceTemp.ulNumKeyFrames = 0; // 配列インデックス用にいったん0にする
+ }
+
+ // 表情ごとにキーフレームを格納
+ for(int i = 0 ; i < ulNumFaceKeyFrames ; i++)
+ {
+ for(int i2=0;i2<result.size();i2++)
+ {
+ FaceData pFaceTemp = result.get(i2);
+ if(pFaceTemp.szFaceName.equals(tmp_vmd_face[i].szFaceName))
+ {
+ FaceKeyFrame pKeyFrame = pFaceTemp.pKeyFrames[pFaceTemp.ulNumKeyFrames];
+
+ pKeyFrame.fFrameNo = (float)tmp_vmd_face[i].ulFrameNo;
+ pKeyFrame.fRate = tmp_vmd_face[i].fFactor;
+
+ pFaceTemp.ulNumKeyFrames++;
+ break;
+ }
+ }
+ }
+
+ // キーフレーム配列を昇順にソート
+ for(int i=0;i<result.size();i++)
+ {
+ FaceData pFaceTemp = result.get(i);
+ Arrays.sort(pFaceTemp.pKeyFrames, new FaceCompare());
+ }
+ o_max_frame[0]=max_frame;
+ return result.toArray(new FaceData[result.size()]);
+ }
+ private static MotionData[] createMotionDataList(DataReader i_reader,float[] o_max_frame) throws MmdException
+ {
+ Vector<MotionData> result=new Vector<MotionData>();
+ // まずはモーションデータ中のボーンごとのキーフレーム数をカウント
+ final int ulNumBoneKeyFrames=i_reader.readInt();
+
+
+ //ボーンを指定数読み込み
+ VMD_Motion[] tmp_vmd_motion=new VMD_Motion[ulNumBoneKeyFrames];
+ for(int i=0;i<ulNumBoneKeyFrames;i++){
+ tmp_vmd_motion[i]= new VMD_Motion();
+ tmp_vmd_motion[i].read(i_reader);
+ }
+
+ float max_frame=0.0f;
+
+ for(int i = 0 ; i < ulNumBoneKeyFrames ; i++)
+ {
+ if( max_frame < tmp_vmd_motion[i].ulFrameNo){
+ max_frame = tmp_vmd_motion[i].ulFrameNo; // 最大フレーム更新
+ }
+ boolean is_found=false;
+ for(int i2=0;i2<result.size();i2++)
+ {
+ final MotionData pMotTemp = result.get(i2);
+ if(pMotTemp.szBoneName.equals(tmp_vmd_motion[i].szBoneName))
+ {
+ // リストに追加済みのボーン
+ pMotTemp.ulNumKeyFrames++;
+ is_found=true;
+ break;
+ }
+ }
+
+ if(!is_found)
+ {
+ // リストにない場合は新規ノードを追加
+ MotionData pNew = new MotionData();
+ pNew.szBoneName=tmp_vmd_motion[i].szBoneName;
+ pNew.ulNumKeyFrames = 1;
+ result.add(pNew);
+ }
+ }
+
+
+ // キーフレーム配列を確保
+ for(int i=0;i<result.size();i++)
+ {
+ final MotionData pMotTemp = result.get(i);
+ pMotTemp.pKeyFrames = BoneKeyFrame.createArray(pMotTemp.ulNumKeyFrames);
+ pMotTemp.ulNumKeyFrames = 0; // 配列インデックス用にいったん0にする
+ }
+
+ // ボーンごとにキーフレームを格納
+ for(int i = 0 ; i < ulNumBoneKeyFrames ; i++)
+ {
+ for(int i2=0;i2<result.size();i2++)
+ {
+ final MotionData pMotTemp = result.get(i2);
+ if(pMotTemp.szBoneName.equals(tmp_vmd_motion[i].szBoneName))
+ {
+ final BoneKeyFrame pKeyFrame = pMotTemp.pKeyFrames[pMotTemp.ulNumKeyFrames];
+
+ pKeyFrame.fFrameNo = (float)tmp_vmd_motion[i].ulFrameNo;
+ pKeyFrame.vec3Position.setValue(tmp_vmd_motion[i].vec3Position);
+ pKeyFrame.vec4Rotate.QuaternionNormalize(tmp_vmd_motion[i].vec4Rotate);
+
+ pMotTemp.ulNumKeyFrames++;
+
+ break;
+ }
+ }
+ }
+
+ // キーフレーム配列を昇順にソート
+
+ for(int i=0;i<result.size();i++)
+ {
+ final MotionData pMotTemp = result.get(i);
+ Arrays.sort(pMotTemp.pKeyFrames, new BoneCompare());
+ }
+
+ o_max_frame[0]=max_frame;
+ return result.toArray(new MotionData[result.size()]);
+
+ }
+}
diff --git a/src/jp/nyatla/nymmd/core/PmdBone.java b/src/jp/nyatla/nymmd/core/PmdBone.java
new file mode 100644
index 0000000..6b01b85
--- /dev/null
+++ b/src/jp/nyatla/nymmd/core/PmdBone.java
@@ -0,0 +1,224 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd.core;
+
+
+import jp.nyatla.nymmd.struct.pmd.PMD_Bone;
+import jp.nyatla.nymmd.types.*;
+
+public class PmdBone
+{
+ private String _name;
+ private final MmdVector3 _pmd_bone_position=new MmdVector3();
+ private final MmdVector3 m_vec3Offset=new MmdVector3();
+ private final MmdMatrix m_matInvTransform=new MmdMatrix(); // 初期値のボーンを原点に移動させるような行列
+
+ private PmdBone _parent_bone;
+ private PmdBone m_pChildBone;
+
+ // 以下は現在の値
+ public final MmdMatrix m_matLocal=new MmdMatrix();
+
+
+ //強制public
+ public final MmdVector3 m_vec3Position=new MmdVector3();
+ public final MmdVector4 m_vec4Rotate=new MmdVector4();
+ public boolean m_bIKLimitAngle; // IK時に角度制限をするかどうか
+ //強制public/
+
+ public String getName()
+ {
+ return this._name;
+ }
+
+ public PmdBone(PMD_Bone pPMDBoneData,PmdBone[] pBoneArray)
+ {
+ // ボーン名のコピー
+ this._name=pPMDBoneData.szName;
+
+ // 位置のコピー
+ this._pmd_bone_position.setValue(pPMDBoneData.vec3Position);
+
+ // 親ボーンの設定
+ if( pPMDBoneData.nParentNo != -1 )
+ {
+ this._parent_bone = pBoneArray[pPMDBoneData.nParentNo];
+ if (this._parent_bone != null){
+ m_vec3Offset.Vector3Sub(this._pmd_bone_position,this._parent_bone._pmd_bone_position);
+ }else{
+ m_vec3Offset.Vector3Sub(this._pmd_bone_position,new MmdVector3(0,1,0));
+ }
+ }else{
+ // 親なし
+ this._parent_bone=null;
+ this.m_vec3Offset.setValue(this._pmd_bone_position);
+ }
+
+ // 子ボーンの設定
+ if( pPMDBoneData.nChildNo != -1 )
+ {
+ this.m_pChildBone =pBoneArray[pPMDBoneData.nChildNo];
+ }
+
+ this.m_matInvTransform.identity();
+ this.m_matInvTransform.m30 = -this._pmd_bone_position.x;
+ this.m_matInvTransform.m31 = -this._pmd_bone_position.y;
+ this.m_matInvTransform.m32 = -this._pmd_bone_position.z;
+
+ this.m_bIKLimitAngle = false;
+
+ // 各変数の初期値を設定
+ reset();
+ }
+ public void recalcOffset()
+ {
+ if(this._parent_bone!=null){
+ m_vec3Offset.Vector3Sub(this._pmd_bone_position,this._parent_bone._pmd_bone_position);
+ }
+ return;
+ }
+
+ public void reset()
+ {
+ m_vec3Position.x = m_vec3Position.y = m_vec3Position.z = 0.0f;
+ m_vec4Rotate.x = m_vec4Rotate.y = m_vec4Rotate.z = 0.0f; m_vec4Rotate.w = 1.0f;
+
+ this.m_matLocal.identity();
+ this.m_matLocal.m30 = _pmd_bone_position.x;
+ this.m_matLocal.m31 = _pmd_bone_position.y;
+ this.m_matLocal.m32 = _pmd_bone_position.z;
+ }
+ public void setIKLimitAngle(boolean i_value)
+ {
+ this.m_bIKLimitAngle=i_value;
+ return;
+ }
+
+
+ public void updateSkinningMat(MmdMatrix o_matrix)
+ {
+ o_matrix.mul(this.m_matInvTransform,this.m_matLocal);
+ return;
+ }
+
+ public void updateMatrix()
+ {
+ if(this._parent_bone!=null){
+ // クォータニオンと移動値からボーンのローカルマトリックスを作成
+ this._mat_tmp1.QuaternionToMatrix(this.m_vec4Rotate );
+ this._mat_tmp1.m30 = m_vec3Position.x + m_vec3Offset.x;
+ this._mat_tmp1.m31 = m_vec3Position.y + m_vec3Offset.y;
+ this._mat_tmp1.m32 = m_vec3Position.z + m_vec3Offset.z;
+ // 親があるなら親の回転を受け継ぐ
+ m_matLocal.mul(this._mat_tmp1,this._parent_bone.m_matLocal);
+ }else{
+ // クォータニオンと移動値からボーンのローカルマトリックスを作成
+ this.m_matLocal.QuaternionToMatrix(this.m_vec4Rotate );
+ this.m_matLocal.m30 = m_vec3Position.x + m_vec3Offset.x;
+ this.m_matLocal.m31 = m_vec3Position.y + m_vec3Offset.y;
+ this.m_matLocal.m32 = m_vec3Position.z + m_vec3Offset.z;
+ }
+ return;
+ }
+ private final MmdMatrix _mat_tmp1=new MmdMatrix();
+ private final MmdMatrix _mat_tmp2=new MmdMatrix();
+ private final MmdMatrix _mat_tmp3=new MmdMatrix();
+ private final MmdVector3 _lookAt_vec3LocalTgtPosZY=new MmdVector3();
+ private final MmdVector3 _lookAt_vec3LocalTgtPosXZ=new MmdVector3();
+ private final MmdVector3 _lookAt_vec3Angle=new MmdVector3();
+
+
+ public void lookAt(MmdVector3 pvecTargetPos )
+ {
+ // どうもおかしいので要調整
+ final MmdMatrix mat_tmp1=this._mat_tmp1;
+ final MmdMatrix mat_tmp3=this._mat_tmp3;
+ final MmdVector3 vec3LocalTgtPosZY=this._lookAt_vec3LocalTgtPosZY;
+ final MmdVector3 vec3LocalTgtPosXZ=this._lookAt_vec3LocalTgtPosXZ;
+
+ mat_tmp1.identity();
+ mat_tmp1.m30 = m_vec3Position.x + m_vec3Offset.x;
+ mat_tmp1.m31 = m_vec3Position.y + m_vec3Offset.y;
+ mat_tmp1.m32 = m_vec3Position.z + m_vec3Offset.z;
+
+ if(this._parent_bone!=null)
+ {
+ mat_tmp3.inverse(_parent_bone.m_matLocal );
+ this._mat_tmp2.mul(mat_tmp1, mat_tmp3 );
+ mat_tmp3.inverse(this._mat_tmp2);
+ vec3LocalTgtPosZY.Vector3Transform(pvecTargetPos, mat_tmp3 );
+ }else{
+ mat_tmp1.inverse(mat_tmp1);
+ vec3LocalTgtPosZY.Vector3Transform(pvecTargetPos, mat_tmp1 );
+ }
+
+ vec3LocalTgtPosXZ.setValue(vec3LocalTgtPosZY);
+ vec3LocalTgtPosXZ.y = 0.0f;
+ vec3LocalTgtPosXZ.Vector3Normalize(vec3LocalTgtPosXZ);
+
+ vec3LocalTgtPosZY.x = 0.0f;
+ vec3LocalTgtPosZY.Vector3Normalize(vec3LocalTgtPosZY);
+
+ MmdVector3 vec3Angle = this._lookAt_vec3Angle;
+ vec3Angle.x=vec3Angle.y=vec3Angle.z=0;
+
+ if( vec3LocalTgtPosZY.z > 0.0f ){
+ vec3Angle.x = (float)(Math.asin(vec3LocalTgtPosZY.y ) - (20.0*Math.PI/180.0));
+ }
+ if( vec3LocalTgtPosXZ.x < 0.0f ){
+ vec3Angle.y = (float)Math.acos(vec3LocalTgtPosXZ.z );
+ }else{
+ vec3Angle.y = (float)-Math.acos(vec3LocalTgtPosXZ.z );
+ }
+
+ if( vec3Angle.x < (-25.0*Math.PI/180.0) ){
+ vec3Angle.x = (float)(-25.0*Math.PI/180.0);
+ }
+ if( (45.0f*Math.PI/180.0) < vec3Angle.x ) {
+ vec3Angle.x = (float)( 45.0*Math.PI/180.0);
+ }
+ if( vec3Angle.y < (-80.0*Math.PI/180.0) ){
+ vec3Angle.y = (float)(-80.0*Math.PI/180.0);
+ }
+ if((80.0*Math.PI/180.0) < vec3Angle.y ){
+ vec3Angle.y =(float)( 80.0*Math.PI/180.0);
+ }
+
+ m_vec4Rotate.QuaternionCreateEuler(vec3Angle);
+ }
+}
diff --git a/src/jp/nyatla/nymmd/core/PmdFace.java b/src/jp/nyatla/nymmd/core/PmdFace.java
new file mode 100644
index 0000000..033e1a3
--- /dev/null
+++ b/src/jp/nyatla/nymmd/core/PmdFace.java
@@ -0,0 +1,108 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd.core;
+
+import jp.nyatla.nymmd.MmdException;
+import jp.nyatla.nymmd.struct.pmd.PMD_FACE;
+import jp.nyatla.nymmd.struct.pmd.PMD_FACE_VTX;
+import jp.nyatla.nymmd.types.MmdVector3;
+
+public class PmdFace
+{
+ private String _name;
+
+ private PMD_FACE_VTX[] _face_vertex; // 表情頂点データ
+
+ public PmdFace(PMD_FACE pPMDFaceData, PmdFace pPMDFaceBase)
+ {
+ // 表情名のコピー
+ this._name = pPMDFaceData.szName;
+
+ // 表情頂点データのコピー
+ final int number_of_vertex = pPMDFaceData.ulNumVertices;
+
+ this._face_vertex = PMD_FACE_VTX.createArray(number_of_vertex);
+ for (int i = 0; i < this._face_vertex.length; i++) {
+ this._face_vertex[i].setValue(pPMDFaceData.pVertices[i]);
+ }
+ // baseとの相対インデックスを絶対インデックスに変換
+ if (pPMDFaceBase != null) {
+ final PMD_FACE_VTX[] vertex_array = this._face_vertex;
+ for (int i =this._face_vertex.length-1; i>=0 ; i--) {
+ final PMD_FACE_VTX vertex = vertex_array[i];
+ vertex.vec3Pos.Vector3Add(pPMDFaceBase._face_vertex[vertex.ulIndex].vec3Pos, vertex.vec3Pos);
+ vertex.ulIndex = pPMDFaceBase._face_vertex[vertex.ulIndex].ulIndex;
+ }
+ }
+ return;
+ }
+
+ public void setFace(MmdVector3[] pvec3Vertices) throws MmdException
+ {
+ if (this._face_vertex == null) {
+ throw new MmdException();
+ }
+
+ final PMD_FACE_VTX[] vertex_array = this._face_vertex;
+ for (int i = vertex_array.length-1; i>=0 ; i--) {
+ final PMD_FACE_VTX vertex = vertex_array[i];
+ pvec3Vertices[vertex.ulIndex].setValue(vertex.vec3Pos);
+ }
+ return;
+ }
+
+ public void blendFace(MmdVector3[] pvec3Vertices, float fRate) throws MmdException
+ {
+ if (this._face_vertex == null) {
+ throw new MmdException();
+ }
+
+ PMD_FACE_VTX[] vertex_array = this._face_vertex;
+ for (int i = vertex_array.length-1; i >=0 ; i--) {
+ final PMD_FACE_VTX vertex = vertex_array[i];
+ MmdVector3 vec=pvec3Vertices[vertex.ulIndex];
+ vec.Vector3Lerp(vec, vertex.vec3Pos, fRate);
+ }
+ return;
+ }
+
+ public String getName()
+ {
+ return this._name;
+ }
+}
diff --git a/src/jp/nyatla/nymmd/core/PmdIK.java b/src/jp/nyatla/nymmd/core/PmdIK.java
new file mode 100644
index 0000000..5135858
--- /dev/null
+++ b/src/jp/nyatla/nymmd/core/PmdIK.java
@@ -0,0 +1,194 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd.core;
+
+import jp.nyatla.nymmd.struct.pmd.PMD_IK;
+import jp.nyatla.nymmd.types.*;
+
+public class PmdIK
+{
+ private PmdBone m_pTargetBone; // IKターゲットボーン
+ private PmdBone m_pEffBone; // IK先端ボーン
+
+ private int m_unCount;
+ private double _fact;
+ private int m_nSortVal;
+
+ private PmdBone[] m_ppBoneList; // IKを構成するボーンの配列
+
+ private final MmdVector3[] _work_vector3=MmdVector3.createArray(4);
+ private final MmdVector4 _work_vector4=new MmdVector4();
+ public PmdIK(PMD_IK pPMDIKData, PmdBone[] i_ref_bone_array)
+ {
+ // IKターゲットボーン
+ this.m_pTargetBone = i_ref_bone_array[pPMDIKData.nTargetNo];
+
+ // IK先端ボーン
+ this.m_pEffBone =i_ref_bone_array[pPMDIKData.nEffNo];
+
+ this.m_unCount = pPMDIKData.unCount;
+ this._fact =pPMDIKData.fFact * Math.PI;
+ this.m_nSortVal = pPMDIKData.punLinkNo[0];
+
+ // IKリンク配列の作成
+ final int number_of_ik_link=pPMDIKData.cbNumLink;
+
+ this.m_ppBoneList = new PmdBone[number_of_ik_link];//参照
+ for(int i = 0 ; i < number_of_ik_link ; i++ )
+ {
+ this.m_ppBoneList[i] =i_ref_bone_array[ pPMDIKData.punLinkNo[i] ]; // ボーン番号は降順で格納されている
+ if(this.m_ppBoneList[i].getName().equals("左ひざ") || this.m_ppBoneList[i].getName().equals("右ひざ"))
+ {
+ this.m_ppBoneList[i].setIKLimitAngle(true);
+ }
+ }
+ }
+ private void limitAngle( MmdVector4 pvec4Out,MmdVector4 pvec4Src )
+ {
+ final MmdVector3 vec3Angle=this._work_vector3[0];
+
+ // XYZ軸回転の取得
+ vec3Angle.QuaternionToEuler(pvec4Src);
+
+ // 角度制限
+ if( vec3Angle.x <-Math.PI ){
+ vec3Angle.x = (float)-Math.PI;
+ }
+ if( -0.002f < vec3Angle.x ){
+ vec3Angle.x = -0.002f;
+ }
+ vec3Angle.y = 0.0f;
+ vec3Angle.z = 0.0f;
+
+ // XYZ軸回転からクォータニオンへ
+ pvec4Out.QuaternionCreateEuler(vec3Angle);
+ return;
+ }
+
+ public int getSortVal()
+ {
+ return this.m_nSortVal;
+ }
+ private final MmdMatrix __update_matInvBone=new MmdMatrix();
+ public void update()
+ {
+ final MmdMatrix matInvBone=this.__update_matInvBone;
+
+
+ final MmdVector3 vec3EffPos=this._work_vector3[0];
+ final MmdVector3 vec3TargetPos=this._work_vector3[1];
+ final MmdVector3 vec3Diff=this._work_vector3[2];
+ final MmdVector3 vec3RotAxis=this._work_vector3[3];
+ final MmdVector4 vec4RotQuat=this._work_vector4;
+
+ //事前に全Boneをupdateしてるなら、このコードは要らない?
+ for(int i =this.m_ppBoneList.length - 1 ; i >= 0 ; i-- ){
+ this.m_ppBoneList[i].updateMatrix();
+ }
+ m_pEffBone.updateMatrix();
+
+ for(int it = this.m_unCount-1 ; it >=0 ; it--)
+ {
+ for(int j = 0 ; j < this.m_ppBoneList.length ; j++ )
+ {
+ // エフェクタの位置の取得
+
+ // ワールド座標系から注目ノードの局所(ローカル)座標系への変換
+ matInvBone.inverse(m_ppBoneList[j].m_matLocal );
+
+ // エフェクタ,到達目標のローカル位置
+ vec3EffPos.Vector3Transform(m_pEffBone.m_matLocal, matInvBone );
+ vec3TargetPos.Vector3Transform(m_pTargetBone.m_matLocal, matInvBone);
+
+ // 十分近ければ終了
+
+ vec3Diff.Vector3Sub(vec3EffPos,vec3TargetPos);
+ if(vec3Diff.Vector3DotProduct(vec3Diff) < 0.0000001f ){
+ return;
+ }
+
+ // (1) 基準関節→エフェクタ位置への方向ベクトル
+ vec3EffPos.Vector3Normalize(vec3EffPos);
+
+ // (2) 基準関節→目標位置への方向ベクトル
+ vec3TargetPos.Vector3Normalize(vec3TargetPos);
+
+ // ベクトル (1) を (2) に一致させるための最短回転量(Axis-Angle)
+ //
+ // 回転角
+ double fRotAngle = Math.acos(vec3EffPos.Vector3DotProduct(vec3TargetPos ) );
+
+ if( 0.00000001 < Math.abs( fRotAngle))
+ {
+ if( fRotAngle < -this._fact ){
+ fRotAngle = -this._fact;
+ }else if( this._fact < fRotAngle ){
+ fRotAngle = this._fact;
+ }
+
+ // 回転軸
+
+ vec3RotAxis.Vector3CrossProduct(vec3EffPos,vec3TargetPos);
+ if( vec3RotAxis.Vector3DotProduct(vec3RotAxis) < 0.0000001 ){
+ continue;
+ }
+
+ vec3RotAxis.Vector3Normalize(vec3RotAxis);
+
+ // 関節回転量の補正
+ vec4RotQuat.QuaternionCreateAxis(vec3RotAxis,fRotAngle);
+
+ if( m_ppBoneList[j].m_bIKLimitAngle){
+ limitAngle(vec4RotQuat,vec4RotQuat );
+ }
+
+ vec4RotQuat.QuaternionNormalize(vec4RotQuat);
+
+ m_ppBoneList[j].m_vec4Rotate.QuaternionMultiply(m_ppBoneList[j].m_vec4Rotate,vec4RotQuat);
+ m_ppBoneList[j].m_vec4Rotate.QuaternionNormalize(m_ppBoneList[j].m_vec4Rotate);
+
+ for(int i = j ; i >= 0 ; i-- ){
+ m_ppBoneList[i].updateMatrix();
+ }
+ m_pEffBone.updateMatrix();
+ }
+ }
+ }
+ return;
+ }
+}
diff --git a/src/jp/nyatla/nymmd/struct/DataReader.java b/src/jp/nyatla/nymmd/struct/DataReader.java
new file mode 100644
index 0000000..fd0f86e
--- /dev/null
+++ b/src/jp/nyatla/nymmd/struct/DataReader.java
@@ -0,0 +1,120 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd.struct;
+
+import java.io.*;
+import java.nio.*;
+
+import jp.nyatla.nymmd.*;
+
+public class DataReader
+{
+ private ByteBuffer _buf;
+ public DataReader(InputStream i_stream) throws MmdException
+ {
+ try{
+ //コレなんとかしよう。C#のBinaryReaderみたいに振舞うように。
+ int file_len=i_stream.available();
+ if(file_len<1){
+ file_len=2*1024*1024;
+ }
+ byte[] buf=new byte[file_len];
+ int buf_len=i_stream.read(buf,0,file_len);
+ this._buf=ByteBuffer.wrap(buf,0,buf_len);
+ this._buf.order(ByteOrder.LITTLE_ENDIAN);
+ return;
+ }catch(Exception e){
+ throw new MmdException();
+ }
+ }
+ public int readByte()
+ {
+ return this._buf.get();
+ }
+ public int read()
+ {
+ int v=this._buf.get();
+ return (v>=0)?v:0xff+v;//unsignedに戻す
+ }
+ public short readShort()
+ {
+ return this._buf.getShort();
+ }
+ public int readUnsignedShort()
+ {
+ int v=this._buf.getShort();
+ return (v>=0)?v:0xffff+v;//unsignedに戻す
+ }
+ public int readInt()
+ {
+ return this._buf.getInt();
+ }
+ public float readFloat()
+ {
+ return this._buf.getFloat();
+ }
+ public double readDouble()
+ {
+ return this._buf.getDouble();
+ }
+ public String readAscii(int i_length) throws MmdException
+ {
+ try{
+ String ret="";
+ int len=0;
+ byte[] tmp=new byte[i_length];
+ int i;
+ for(i=0;i<i_length;i++){
+ byte b=this._buf.get();
+ if(b==0x00){
+ i++;
+ break;
+ }
+ tmp[i]=b;
+ len++;
+ }
+ ret=new String(tmp,0,len,"Shift_JIS");
+ for(;i<i_length;i++){
+ this._buf.get();
+ }
+ return ret;
+ }catch(Exception e){
+ throw new MmdException();
+ }
+ }
+}
diff --git a/src/jp/nyatla/nymmd/struct/StructReader.java b/src/jp/nyatla/nymmd/struct/StructReader.java
new file mode 100644
index 0000000..4a5a658
--- /dev/null
+++ b/src/jp/nyatla/nymmd/struct/StructReader.java
@@ -0,0 +1,82 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd.struct;
+
+
+import jp.nyatla.nymmd.MmdException;
+import jp.nyatla.nymmd.types.*;
+
+public class StructReader
+{
+ public static void read(MmdColor4 i_dest,DataReader i_reader) throws MmdException
+ {
+ i_dest.r=i_reader.readFloat();
+ i_dest.g=i_reader.readFloat();
+ i_dest.b=i_reader.readFloat();
+ i_dest.a=i_reader.readFloat();
+ return;
+ }
+ public static void read(MmdColor3 i_dest,DataReader i_reader) throws MmdException
+ {
+ i_dest.r=i_reader.readFloat();
+ i_dest.g=i_reader.readFloat();
+ i_dest.b=i_reader.readFloat();
+ return;
+ }
+ public static void read(MmdTexUV i_dest,DataReader i_reader) throws MmdException
+ {
+ i_dest.u=i_reader.readFloat();
+ i_dest.v=i_reader.readFloat();
+ return;
+ }
+ public static void read(MmdVector3 i_dest,DataReader i_reader) throws MmdException
+ {
+ i_dest.x=i_reader.readFloat();
+ i_dest.y=i_reader.readFloat();
+ i_dest.z=i_reader.readFloat();
+ return;
+ }
+ public static void read(MmdVector4 i_dest,DataReader i_reader) throws MmdException
+ {
+ i_dest.x=i_reader.readFloat();
+ i_dest.y=i_reader.readFloat();
+ i_dest.z=i_reader.readFloat();
+ i_dest.w=i_reader.readFloat();
+ return;
+ }
+}
diff --git a/src/jp/nyatla/nymmd/struct/StructType.java b/src/jp/nyatla/nymmd/struct/StructType.java
new file mode 100644
index 0000000..27f19fa
--- /dev/null
+++ b/src/jp/nyatla/nymmd/struct/StructType.java
@@ -0,0 +1,48 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd.struct;
+
+
+
+import jp.nyatla.nymmd.MmdException;
+
+public interface StructType
+{
+ public void read(DataReader i_reader) throws MmdException;
+
+}
diff --git a/src/jp/nyatla/nymmd/struct/pmd/PMD_Bone.java b/src/jp/nyatla/nymmd/struct/pmd/PMD_Bone.java
new file mode 100644
index 0000000..cb949d5
--- /dev/null
+++ b/src/jp/nyatla/nymmd/struct/pmd/PMD_Bone.java
@@ -0,0 +1,66 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd.struct.pmd;
+
+
+
+import jp.nyatla.nymmd.MmdException;
+import jp.nyatla.nymmd.struct.*;
+import jp.nyatla.nymmd.types.MmdVector3;
+
+public class PMD_Bone implements StructType
+{
+ public String szName; // ボーン名 (0x00 終端,余白は 0xFD)
+ public int nParentNo; // 親ボーン番号 (なければ -1)
+ public int nChildNo; // 子ボーン番号
+ public int cbKind; // ボーンの種類
+ public int unIKTarget; // IK時のターゲットボーン
+ public final MmdVector3 vec3Position=new MmdVector3(); // モデル原点からの位置
+
+ public void read(DataReader i_reader) throws MmdException
+ {
+ //szName
+ this.szName=i_reader.readAscii(20);
+ this.nParentNo=i_reader.readShort();
+ this.nChildNo=i_reader.readShort();
+ this.cbKind=i_reader.readByte();
+ this.unIKTarget=i_reader.readShort();
+ StructReader.read(this.vec3Position, i_reader);
+ return;
+ }
+}
diff --git a/src/jp/nyatla/nymmd/struct/pmd/PMD_FACE.java b/src/jp/nyatla/nymmd/struct/pmd/PMD_FACE.java
new file mode 100644
index 0000000..e2c4f5c
--- /dev/null
+++ b/src/jp/nyatla/nymmd/struct/pmd/PMD_FACE.java
@@ -0,0 +1,74 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd.struct.pmd;
+
+
+import jp.nyatla.nymmd.MmdException;
+import jp.nyatla.nymmd.struct.*;
+
+public class PMD_FACE implements StructType
+{
+ public String szName; // 表情名 (0x00 終端,余白は 0xFD)
+ public int ulNumVertices; // 表情頂点数
+ public int cbType; // 分類
+ public PMD_FACE_VTX [] pVertices=PMD_FACE_VTX.createArray(64);// 表情頂点データ
+ public void read(DataReader i_reader) throws MmdException
+ {
+ int i;
+ //szName
+ this.szName=i_reader.readAscii(20);
+ this.ulNumVertices=i_reader.readInt();
+ this.cbType=i_reader.read();
+ //必要な数だけ配列を確保しなおす。
+ if(this.ulNumVertices>this.pVertices.length){
+ this.pVertices=PMD_FACE_VTX.createArray(this.ulNumVertices);
+ }
+ for(i=0;i<this.ulNumVertices;i++){
+ this.pVertices[i].read(i_reader);
+ }
+ return;
+ }
+/*
+ char szName[20]; // 表情名 (0x00 終端,余白は 0xFD)
+
+ unsigned long ulNumVertices; // 表情頂点数
+ unsigned char cbType; // 分類
+
+ PMD_FACE_VTX pVertices[1]; // 表情頂点データ
+*/
+}
diff --git a/src/jp/nyatla/nymmd/struct/pmd/PMD_FACE_VTX.java b/src/jp/nyatla/nymmd/struct/pmd/PMD_FACE_VTX.java
new file mode 100644
index 0000000..6581be1
--- /dev/null
+++ b/src/jp/nyatla/nymmd/struct/pmd/PMD_FACE_VTX.java
@@ -0,0 +1,75 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd.struct.pmd;
+
+
+import jp.nyatla.nymmd.*;
+import jp.nyatla.nymmd.struct.*;
+import jp.nyatla.nymmd.types.MmdVector3;
+public class PMD_FACE_VTX implements StructType
+{
+ public int ulIndex;
+ public MmdVector3 vec3Pos=new MmdVector3();
+ public void read(DataReader i_reader) throws MmdException
+ {
+ this.ulIndex=i_reader.readInt();
+ StructReader.read(this.vec3Pos, i_reader);
+ return;
+ }
+ public static PMD_FACE_VTX[] createArray(int i_length)
+ {
+ PMD_FACE_VTX[] ret=new PMD_FACE_VTX[i_length];
+ for(int i=0;i<i_length;i++)
+ {
+ ret[i]=new PMD_FACE_VTX();
+ }
+ return ret;
+ }
+ public void setValue(PMD_FACE_VTX i_value)
+ {
+ this.ulIndex=i_value.ulIndex;
+ this.vec3Pos.setValue(i_value.vec3Pos);
+ return;
+ }
+
+
+/*
+ unsigned long ulIndex;
+ Vector3 vec3Pos;
+*/
+}
diff --git a/src/jp/nyatla/nymmd/struct/pmd/PMD_Header.java b/src/jp/nyatla/nymmd/struct/pmd/PMD_Header.java
new file mode 100644
index 0000000..a5b5863
--- /dev/null
+++ b/src/jp/nyatla/nymmd/struct/pmd/PMD_Header.java
@@ -0,0 +1,69 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd.struct.pmd;
+
+import jp.nyatla.nymmd.*;
+import jp.nyatla.nymmd.struct.*;
+
+public class PMD_Header implements StructType
+{
+ public final static int SIZE_OF_STRUCT=3+4+20+256;
+ public String szMagic;
+ public float fVersion;
+ public String szName;
+ public String szComment;
+
+ public void read(DataReader i_reader) throws MmdException
+ {
+ this.szMagic=i_reader.readAscii(3);
+ //
+ this.fVersion=i_reader.readFloat();
+ //szName
+ this.szName=i_reader.readAscii(20);
+
+ //szComment
+ this.szComment=i_reader.readAscii(256);
+ return;
+ }
+/*
+ char szMagic[3]; // "Pmd"
+ float fVersion; // PMDバージョン番号
+ char szName[20]; // モデル名
+ char szComment[256]; // コメント(著作権表示など)
+*/
+}
diff --git a/src/jp/nyatla/nymmd/struct/pmd/PMD_IK.java b/src/jp/nyatla/nymmd/struct/pmd/PMD_IK.java
new file mode 100644
index 0000000..d5fceea
--- /dev/null
+++ b/src/jp/nyatla/nymmd/struct/pmd/PMD_IK.java
@@ -0,0 +1,83 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd.struct.pmd;
+
+
+
+import jp.nyatla.nymmd.MmdException;
+import jp.nyatla.nymmd.struct.DataReader;
+import jp.nyatla.nymmd.struct.StructType;
+
+public class PMD_IK implements StructType
+{
+ public int nTargetNo; // IKターゲットボーン番号
+ public int nEffNo; // IK先端ボーン番号
+ public int cbNumLink; // IKを構成するボーンの数
+ public int unCount;
+ public float fFact;
+ public int[] punLinkNo;// IKを構成するボーンの配列(可変長配列)
+
+ public void read(DataReader i_reader) throws MmdException
+ {
+ this.nTargetNo=i_reader.readShort();
+ this.nEffNo=i_reader.readShort();
+ this.cbNumLink=i_reader.read();
+ this.unCount=i_reader.readUnsignedShort();
+ this.fFact=i_reader.readFloat();
+ //必要な数だけ配列を確保しなおす。
+ this.punLinkNo=new int[this.cbNumLink];
+ for(int i=0;i<this.cbNumLink;i++){
+ this.punLinkNo[i]=i_reader.readUnsignedShort();
+ }
+ return;
+ }
+
+
+
+/*
+ short nTargetNo; // IKターゲットボーン番号
+ short nEffNo; // IK先端ボーン番号
+
+ unsigned char cbNumLink; // IKを構成するボーンの数
+
+ unsigned short unCount;
+ float fFact;
+
+ unsigned short punLinkNo[1];// IKを構成するボーンの配列
+*/
+}
diff --git a/src/jp/nyatla/nymmd/struct/pmd/PMD_Material.java b/src/jp/nyatla/nymmd/struct/pmd/PMD_Material.java
new file mode 100644
index 0000000..6d5e97c
--- /dev/null
+++ b/src/jp/nyatla/nymmd/struct/pmd/PMD_Material.java
@@ -0,0 +1,82 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd.struct.pmd;
+
+import jp.nyatla.nymmd.MmdException;
+import jp.nyatla.nymmd.struct.DataReader;
+import jp.nyatla.nymmd.struct.StructReader;
+import jp.nyatla.nymmd.struct.StructType;
+import jp.nyatla.nymmd.types.MmdColor3;
+import jp.nyatla.nymmd.types.MmdColor4;
+
+public class PMD_Material implements StructType {
+ public final MmdColor4 col4Diffuse = new MmdColor4();
+ public float fShininess;
+ public final MmdColor3 col3Specular = new MmdColor3();
+ public final MmdColor3 col3Ambient = new MmdColor3();
+ public int unknown;
+ public int toon;
+ public int edgeFlag;
+ public int ulNumIndices; // この材質に対応する頂点数
+ public String szTextureFileName; // テクスチャファイル名
+ public String szSphFileName; // テクスチャファイル名
+
+ public void read(DataReader i_reader) throws MmdException {
+ StructReader.read(this.col4Diffuse, i_reader);
+ this.fShininess = i_reader.readFloat();
+ StructReader.read(this.col3Specular, i_reader);
+ StructReader.read(this.col3Ambient, i_reader);
+ toon = i_reader.readByte();
+ edgeFlag = i_reader.readByte();
+ // this.unknown = i_reader.readUnsignedShort();
+ this.ulNumIndices = i_reader.readInt();
+ this.szTextureFileName = i_reader.readAscii(20);
+ return;
+ }
+ /*
+ * Color4 col4Diffuse;
+ * float fShininess;
+ * Color3 col3Specular,
+ * col3Ambient;
+ *
+ * unsigned short unknown;
+ * unsigned long ulNumIndices; // この材質に対応する頂点数
+ * char szTextureFileName[20]; // テクスチャファイル名
+ */
+
+}
diff --git a/src/jp/nyatla/nymmd/struct/pmd/PMD_Vertex.java b/src/jp/nyatla/nymmd/struct/pmd/PMD_Vertex.java
new file mode 100644
index 0000000..efc425d
--- /dev/null
+++ b/src/jp/nyatla/nymmd/struct/pmd/PMD_Vertex.java
@@ -0,0 +1,78 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd.struct.pmd;
+
+
+import jp.nyatla.nymmd.MmdException;
+import jp.nyatla.nymmd.struct.DataReader;
+import jp.nyatla.nymmd.struct.StructReader;
+import jp.nyatla.nymmd.struct.StructType;
+import jp.nyatla.nymmd.types.MmdTexUV;
+import jp.nyatla.nymmd.types.MmdVector3;
+
+public class PMD_Vertex implements StructType
+{
+ public MmdVector3 vec3Pos=new MmdVector3(); // 座標
+ public MmdVector3 vec3Normal=new MmdVector3(); // 法線ベクトル
+ public MmdTexUV uvTex=new MmdTexUV(); // テクスチャ座標
+
+ public int[] unBoneNo=new int[2]; // ボーン番号
+ public int cbWeight; // ブレンドの重み (0~100%)
+ public int cbEdge; // エッジフラグ
+/*
+ Vector3 vec3Pos; // 座標
+ Vector3 vec3Normal; // 法線ベクトル
+ TexUV uvTex; // テクスチャ座標
+
+ unsigned short unBoneNo[2]; // ボーン番号
+ unsigned char cbWeight; // ブレンドの重み (0~100%)
+ unsigned char cbEdge; // エッジフラグ
+*/
+ public void read(DataReader i_reader) throws MmdException
+ {
+ StructReader.read(this.vec3Pos, i_reader);
+ StructReader.read(this.vec3Normal, i_reader);
+ StructReader.read(this.uvTex, i_reader);
+ this.unBoneNo[0]=i_reader.readUnsignedShort();
+ this.unBoneNo[1]=i_reader.readUnsignedShort();
+ this.cbWeight=i_reader.read();
+ this.cbEdge=i_reader.read();
+ return;
+ }
+
+}
diff --git a/src/jp/nyatla/nymmd/struct/vmd/VMD_Face.java b/src/jp/nyatla/nymmd/struct/vmd/VMD_Face.java
new file mode 100644
index 0000000..d78ddbe
--- /dev/null
+++ b/src/jp/nyatla/nymmd/struct/vmd/VMD_Face.java
@@ -0,0 +1,60 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd.struct.vmd;
+
+
+
+import jp.nyatla.nymmd.MmdException;
+import jp.nyatla.nymmd.struct.DataReader;
+import jp.nyatla.nymmd.struct.StructType;
+
+public class VMD_Face implements StructType
+{
+ public String szFaceName;
+ public long ulFrameNo;
+ public float fFactor;
+ public void read(DataReader i_reader) throws MmdException
+ {
+ //szFaceName
+ this.szFaceName=i_reader.readAscii(15);
+ this.ulFrameNo=i_reader.readInt();
+ this.fFactor=i_reader.readFloat();
+ return;
+ }
+
+}
diff --git a/src/jp/nyatla/nymmd/struct/vmd/VMD_Header.java b/src/jp/nyatla/nymmd/struct/vmd/VMD_Header.java
new file mode 100644
index 0000000..5a61aa7
--- /dev/null
+++ b/src/jp/nyatla/nymmd/struct/vmd/VMD_Header.java
@@ -0,0 +1,63 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd.struct.vmd;
+
+
+import jp.nyatla.nymmd.MmdException;
+import jp.nyatla.nymmd.struct.DataReader;
+import jp.nyatla.nymmd.struct.StructType;
+
+public class VMD_Header implements StructType
+{
+ public String szHeader;
+ public String szModelName;
+ public void read(DataReader i_reader) throws MmdException
+ {
+ //szHeader
+ this.szHeader=i_reader.readAscii(30);
+ //szModelName
+ this.szModelName=i_reader.readAscii(20);
+ return;
+ }
+
+
+/*
+ char szHeader[30]; // "Vocaloid Motion Data 0002"
+ char szModelName[20]; // 対象モデル名
+*/
+}
diff --git a/src/jp/nyatla/nymmd/struct/vmd/VMD_Motion.java b/src/jp/nyatla/nymmd/struct/vmd/VMD_Motion.java
new file mode 100644
index 0000000..10512cf
--- /dev/null
+++ b/src/jp/nyatla/nymmd/struct/vmd/VMD_Motion.java
@@ -0,0 +1,94 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd.struct.vmd;
+
+
+import jp.nyatla.nymmd.MmdException;
+import jp.nyatla.nymmd.struct.*;
+import jp.nyatla.nymmd.types.MmdVector3;
+import jp.nyatla.nymmd.types.MmdVector4;
+public class VMD_Motion implements StructType
+{
+ public String szBoneName; // ボーン名
+ public long ulFrameNo; // フレーム番号
+
+ public final MmdVector3 vec3Position=new MmdVector3();// 位置
+ public final MmdVector4 vec4Rotate=new MmdVector4(); // 回転(クォータニオン)
+
+ public final int[] cInterpolation1=new int[16]; // 補間情報
+ public final int[] cInterpolation2=new int[16];
+ public final int[] cInterpolation3=new int[16];
+ public final int[] cInterpolation4=new int[16];
+
+ public void read(DataReader i_reader) throws MmdException
+ {
+ int i;
+ //szName
+ this.szBoneName=i_reader.readAscii(15);
+ this.ulFrameNo=i_reader.readInt();
+ StructReader.read(this.vec3Position, i_reader);
+ StructReader.read(this.vec4Rotate,i_reader);
+ for(i=0;i<16;i++){
+ this.cInterpolation1[i]=i_reader.readByte();
+ }
+ for(i=0;i<16;i++){
+ this.cInterpolation2[i]=i_reader.readByte();
+ }
+ for(i=0;i<16;i++){
+ this.cInterpolation3[i]=i_reader.readByte();
+ }
+ for(i=0;i<16;i++){
+ this.cInterpolation4[i]=i_reader.readByte();
+ }
+ return;
+ }
+
+/*
+ char szBoneName[15]; // ボーン名
+
+ unsigned long ulFrameNo; // フレーム番号
+
+ Vector3 vec3Position; // 位置
+ Vector4 vec4Rotate; // 回転(クォータニオン)
+
+ char cInterpolation1[16]; // 補間情報
+ char cInterpolation2[16];
+ char cInterpolation3[16];
+ char cInterpolation4[16];
+*/
+}
diff --git a/src/jp/nyatla/nymmd/types/BoneKeyFrame.java b/src/jp/nyatla/nymmd/types/BoneKeyFrame.java
new file mode 100644
index 0000000..190c9c2
--- /dev/null
+++ b/src/jp/nyatla/nymmd/types/BoneKeyFrame.java
@@ -0,0 +1,62 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd.types;
+
+
+
+public class BoneKeyFrame
+{
+ public float fFrameNo; // フレーム番号
+ public final MmdVector3 vec3Position=new MmdVector3(); // 位置
+ public final MmdVector4 vec4Rotate=new MmdVector4(); // 回転(クォータニオン)
+ public static BoneKeyFrame[] createArray(int i_length)
+ {
+ BoneKeyFrame[] ret=new BoneKeyFrame[i_length];
+ for(int i=0;i<i_length;i++)
+ {
+ ret[i]=new BoneKeyFrame();
+ }
+ return ret;
+ }
+/*
+ float fFrameNo; // フレーム番号
+
+ Vector3 vec3Position; // 位置
+ Vector4 vec4Rotate; // 回転(クォータニオン)
+*/
+}
diff --git a/src/jp/nyatla/nymmd/types/FaceData.java b/src/jp/nyatla/nymmd/types/FaceData.java
new file mode 100644
index 0000000..fb4e803
--- /dev/null
+++ b/src/jp/nyatla/nymmd/types/FaceData.java
@@ -0,0 +1,45 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd.types;
+
+public class FaceData
+{
+ public String szFaceName; // 表情名
+ public int ulNumKeyFrames; // キーフレーム数
+ public FaceKeyFrame[] pKeyFrames; // キーフレームデータ配列
+}
diff --git a/src/jp/nyatla/nymmd/types/FaceKeyFrame.java b/src/jp/nyatla/nymmd/types/FaceKeyFrame.java
new file mode 100644
index 0000000..0fec1f1
--- /dev/null
+++ b/src/jp/nyatla/nymmd/types/FaceKeyFrame.java
@@ -0,0 +1,53 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd.types;
+
+public class FaceKeyFrame
+{
+ public float fFrameNo; // フレーム番号
+ public float fRate; // ブレンド率
+ public static FaceKeyFrame[] createArray(int i_length)
+ {
+ FaceKeyFrame[] ret=new FaceKeyFrame[i_length];
+ for(int i=0;i<i_length;i++)
+ {
+ ret[i]=new FaceKeyFrame();
+ }
+ return ret;
+ }
+}
diff --git a/src/jp/nyatla/nymmd/types/MmdColor3.java b/src/jp/nyatla/nymmd/types/MmdColor3.java
new file mode 100644
index 0000000..7c179b7
--- /dev/null
+++ b/src/jp/nyatla/nymmd/types/MmdColor3.java
@@ -0,0 +1,53 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd.types;
+
+
+
+public class MmdColor3
+{
+ public float r, g, b;
+
+ public void setValue(MmdColor4 v)
+ {
+ this.r=v.r;
+ this.g=v.g;
+ this.b=v.b;
+ return;
+ }
+}
diff --git a/src/jp/nyatla/nymmd/types/MmdColor4.java b/src/jp/nyatla/nymmd/types/MmdColor4.java
new file mode 100644
index 0000000..3f7ebd0
--- /dev/null
+++ b/src/jp/nyatla/nymmd/types/MmdColor4.java
@@ -0,0 +1,59 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd.types;
+
+public class MmdColor4
+{
+ public float r, g, b, a;
+ public void setValue(MmdColor4 v)
+ {
+ this.r=v.r;
+ this.g=v.g;
+ this.b=v.b;
+ this.a=v.a;
+ return;
+ }
+ public void getValue(float[] v,int i_st)
+ {
+ v[i_st+0]=this.r;
+ v[i_st+1]=this.g;
+ v[i_st+2]=this.b;
+ v[i_st+3]=this.a;
+ return;
+ }
+}
diff --git a/src/jp/nyatla/nymmd/types/MmdMatrix.java b/src/jp/nyatla/nymmd/types/MmdMatrix.java
new file mode 100644
index 0000000..3a9a7d2
--- /dev/null
+++ b/src/jp/nyatla/nymmd/types/MmdMatrix.java
@@ -0,0 +1,377 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd.types;
+
+public class MmdMatrix
+{
+ //////
+ // <NyARToolkitからのポート>
+ //////
+
+ /** 行列の要素値です。*/
+ public double m00;
+ /** 行列の要素値です。*/
+ public double m01;
+ /** 行列の要素値です。*/
+ public double m02;
+ /** 行列の要素値です。*/
+ public double m03;
+ /** 行列の要素値です。*/
+ public double m10;
+ /** 行列の要素値です。*/
+ public double m11;
+ /** 行列の要素値です。*/
+ public double m12;
+ /** 行列の要素値です。*/
+ public double m13;
+ /** 行列の要素値です。*/
+ public double m20;
+ /** 行列の要素値です。*/
+ public double m21;
+ /** 行列の要素値です。*/
+ public double m22;
+ /** 行列の要素値です。*/
+ public double m23;
+ /** 行列の要素値です。*/
+ public double m30;
+ /** 行列の要素値です。*/
+ public double m31;
+ /** 行列の要素値です。*/
+ public double m32;
+ /** 行列の要素値です。*/
+ public double m33;
+ /**
+ * この関数は、オブジェクトの配列を生成して返します。
+ * @param i_number
+ * 配列の長さ
+ * @return
+ * 新しいオブジェクト配列
+ */
+ public static MmdMatrix[] createArray(int i_number)
+ {
+ MmdMatrix[] ret=new MmdMatrix[i_number];
+ for(int i=0;i<i_number;i++)
+ {
+ ret[i]=new MmdMatrix();
+ }
+ return ret;
+ }
+ /**
+ * この関数は、要素数16の配列を、行列にセットします。
+ * 00,01,02,03,10...の順です。
+ */
+ public void setValue(double[] i_value)
+ {
+ this.m00=i_value[ 0];
+ this.m01=i_value[ 1];
+ this.m02=i_value[ 2];
+ this.m03=i_value[ 3];
+ this.m10=i_value[ 4];
+ this.m11=i_value[ 5];
+ this.m12=i_value[ 6];
+ this.m13=i_value[ 7];
+ this.m20=i_value[ 8];
+ this.m21=i_value[ 9];
+ this.m22=i_value[10];
+ this.m23=i_value[11];
+ this.m30=i_value[12];
+ this.m31=i_value[13];
+ this.m32=i_value[14];
+ this.m33=i_value[15];
+ return;
+ }
+ /**
+ * この関数は、オブジェクトの内容をインスタンスにコピーします。
+ * @param i_value
+ * コピー元のオブジェクト
+ */
+ public void setValue(MmdMatrix i_value)
+ {
+ this.m00=i_value.m00;
+ this.m01=i_value.m01;
+ this.m02=i_value.m02;
+ this.m03=i_value.m03;
+ this.m10=i_value.m10;
+ this.m11=i_value.m11;
+ this.m12=i_value.m12;
+ this.m13=i_value.m13;
+ this.m20=i_value.m20;
+ this.m21=i_value.m21;
+ this.m22=i_value.m22;
+ this.m23=i_value.m23;
+ this.m30=i_value.m30;
+ this.m31=i_value.m31;
+ this.m32=i_value.m32;
+ this.m33=i_value.m33;
+ return;
+ }
+ /**
+ * この関数は、要素数16の配列に、行列の内容をコピーします。
+ * 順番は、00,01,02,03,10...の順です。
+ */
+ public void getValue(double[] o_value)
+ {
+ o_value[ 0]=this.m00;
+ o_value[ 1]=this.m01;
+ o_value[ 2]=this.m02;
+ o_value[ 3]=this.m03;
+ o_value[ 4]=this.m10;
+ o_value[ 5]=this.m11;
+ o_value[ 6]=this.m12;
+ o_value[ 7]=this.m13;
+ o_value[ 8]=this.m20;
+ o_value[ 9]=this.m21;
+ o_value[10]=this.m22;
+ o_value[11]=this.m23;
+ o_value[12]=this.m30;
+ o_value[13]=this.m31;
+ o_value[14]=this.m32;
+ o_value[15]=this.m33;
+ return;
+ }
+ /**
+ * この関数は、要素数16の配列に、行列の内容を転置してからコピーします。
+ * 順番は、00,10,20,30,01...の順です。
+ * @param o_value
+ * 値を受け取る配列
+ */
+ public void getValueT(double[] o_value)
+ {
+ o_value[ 0]=this.m00;
+ o_value[ 1]=this.m10;
+ o_value[ 2]=this.m20;
+ o_value[ 3]=this.m30;
+ o_value[ 4]=this.m01;
+ o_value[ 5]=this.m11;
+ o_value[ 6]=this.m21;
+ o_value[ 7]=this.m31;
+ o_value[ 8]=this.m02;
+ o_value[ 9]=this.m12;
+ o_value[10]=this.m22;
+ o_value[11]=this.m32;
+ o_value[12]=this.m03;
+ o_value[13]=this.m13;
+ o_value[14]=this.m23;
+ o_value[15]=this.m33;
+ return;
+ }
+ /**
+ * この関数は、逆行列を計算して、インスタンスにセットします。
+ * @param i_src
+ * 逆行列を計算するオブジェクト。thisを指定できます。
+ * @return
+ * 逆行列を得られると、trueを返します。
+ */
+ public boolean inverse(MmdMatrix i_src)
+ {
+ final double a11,a12,a13,a14,a21,a22,a23,a24,a31,a32,a33,a34,a41,a42,a43,a44;
+ final double b11,b12,b13,b14,b21,b22,b23,b24,b31,b32,b33,b34,b41,b42,b43,b44;
+ double t1,t2,t3,t4,t5,t6;
+ a11=i_src.m00;a12=i_src.m01;a13=i_src.m02;a14=i_src.m03;
+ a21=i_src.m10;a22=i_src.m11;a23=i_src.m12;a24=i_src.m13;
+ a31=i_src.m20;a32=i_src.m21;a33=i_src.m22;a34=i_src.m23;
+ a41=i_src.m30;a42=i_src.m31;a43=i_src.m32;a44=i_src.m33;
+
+ t1=a33*a44-a34*a43;
+ t2=a34*a42-a32*a44;
+ t3=a32*a43-a33*a42;
+ t4=a34*a41-a31*a44;
+ t5=a31*a43-a33*a41;
+ t6=a31*a42-a32*a41;
+
+ b11=a22*t1+a23*t2+a24*t3;
+ b21=-(a23*t4+a24*t5+a21*t1);
+ b31=a24*t6-a21*t2+a22*t4;
+ b41=-(a21*t3-a22*t5+a23*t6);
+
+ t1=a43*a14-a44*a13;
+ t2=a44*a12-a42*a14;
+ t3=a42*a13-a43*a12;
+ t4=a44*a11-a41*a14;
+ t5=a41*a13-a43*a11;
+ t6=a41*a12-a42*a11;
+
+ b12=-(a32*t1+a33*t2+a34*t3);
+ b22=a33*t4+a34*t5+a31*t1;
+ b32=-(a34*t6-a31*t2+a32*t4);
+ b42=a31*t3-a32*t5+a33*t6;
+
+ t1=a13*a24-a14*a23;
+ t2=a14*a22-a12*a24;
+ t3=a12*a23-a13*a22;
+ t4=a14*a21-a11*a24;
+ t5=a11*a23-a13*a21;
+ t6=a11*a22-a12*a21;
+
+ b13=a42*t1+a43*t2+a44*t3;
+ b23=-(a43*t4+a44*t5+a41*t1);
+ b33=a44*t6-a41*t2+a42*t4;
+ b43=-(a41*t3-a42*t5+a43*t6);
+
+ t1=a23*a34-a24*a33;
+ t2=a24*a32-a22*a34;
+ t3=a22*a33-a23*a32;
+ t4=a24*a31-a21*a34;
+ t5=a21*a33-a23*a31;
+ t6=a21*a32-a22*a31;
+
+ b14=-(a12*t1+a13*t2+a14*t3);
+ b24=a13*t4+a14*t5+a11*t1;
+ b34=-(a14*t6-a11*t2+a12*t4);
+ b44=a11*t3-a12*t5+a13*t6;
+
+ double det_1=(a11*b11+a21*b12+a31*b13+a41*b14);
+ if(det_1==0){
+ return false;
+ }
+ det_1=1/det_1;
+
+ this.m00=b11*det_1;
+ this.m01=b12*det_1;
+ this.m02=b13*det_1;
+ this.m03=b14*det_1;
+
+ this.m10=b21*det_1;
+ this.m11=b22*det_1;
+ this.m12=b23*det_1;
+ this.m13=b24*det_1;
+
+ this.m20=b31*det_1;
+ this.m21=b32*det_1;
+ this.m22=b33*det_1;
+ this.m23=b34*det_1;
+
+ this.m30=b41*det_1;
+ this.m31=b42*det_1;
+ this.m32=b43*det_1;
+ this.m33=b44*det_1;
+
+ return true;
+ }
+ /**
+ * この関数は、行列同士の掛け算をして、インスタンスに格納します。
+ * i_mat_lとi_mat_rには、thisを指定しないでください。
+ * @param i_mat_l
+ * 左成分の行列
+ * @param i_mat_r
+ * 右成分の行列
+ */
+ public final void mul(MmdMatrix i_mat_l,MmdMatrix i_mat_r)
+ {
+ assert(this!=i_mat_l);
+ assert(this!=i_mat_r);
+ this.m00=i_mat_l.m00*i_mat_r.m00 + i_mat_l.m01*i_mat_r.m10 + i_mat_l.m02*i_mat_r.m20 + i_mat_l.m03*i_mat_r.m30;
+ this.m01=i_mat_l.m00*i_mat_r.m01 + i_mat_l.m01*i_mat_r.m11 + i_mat_l.m02*i_mat_r.m21 + i_mat_l.m03*i_mat_r.m31;
+ this.m02=i_mat_l.m00*i_mat_r.m02 + i_mat_l.m01*i_mat_r.m12 + i_mat_l.m02*i_mat_r.m22 + i_mat_l.m03*i_mat_r.m32;
+ this.m03=i_mat_l.m00*i_mat_r.m03 + i_mat_l.m01*i_mat_r.m13 + i_mat_l.m02*i_mat_r.m23 + i_mat_l.m03*i_mat_r.m33;
+
+ this.m10=i_mat_l.m10*i_mat_r.m00 + i_mat_l.m11*i_mat_r.m10 + i_mat_l.m12*i_mat_r.m20 + i_mat_l.m13*i_mat_r.m30;
+ this.m11=i_mat_l.m10*i_mat_r.m01 + i_mat_l.m11*i_mat_r.m11 + i_mat_l.m12*i_mat_r.m21 + i_mat_l.m13*i_mat_r.m31;
+ this.m12=i_mat_l.m10*i_mat_r.m02 + i_mat_l.m11*i_mat_r.m12 + i_mat_l.m12*i_mat_r.m22 + i_mat_l.m13*i_mat_r.m32;
+ this.m13=i_mat_l.m10*i_mat_r.m03 + i_mat_l.m11*i_mat_r.m13 + i_mat_l.m12*i_mat_r.m23 + i_mat_l.m13*i_mat_r.m33;
+
+ this.m20=i_mat_l.m20*i_mat_r.m00 + i_mat_l.m21*i_mat_r.m10 + i_mat_l.m22*i_mat_r.m20 + i_mat_l.m23*i_mat_r.m30;
+ this.m21=i_mat_l.m20*i_mat_r.m01 + i_mat_l.m21*i_mat_r.m11 + i_mat_l.m22*i_mat_r.m21 + i_mat_l.m23*i_mat_r.m31;
+ this.m22=i_mat_l.m20*i_mat_r.m02 + i_mat_l.m21*i_mat_r.m12 + i_mat_l.m22*i_mat_r.m22 + i_mat_l.m23*i_mat_r.m32;
+ this.m23=i_mat_l.m20*i_mat_r.m03 + i_mat_l.m21*i_mat_r.m13 + i_mat_l.m22*i_mat_r.m23 + i_mat_l.m23*i_mat_r.m33;
+
+ this.m30=i_mat_l.m30*i_mat_r.m00 + i_mat_l.m31*i_mat_r.m10 + i_mat_l.m32*i_mat_r.m20 + i_mat_l.m33*i_mat_r.m30;
+ this.m31=i_mat_l.m30*i_mat_r.m01 + i_mat_l.m31*i_mat_r.m11 + i_mat_l.m32*i_mat_r.m21 + i_mat_l.m33*i_mat_r.m31;
+ this.m32=i_mat_l.m30*i_mat_r.m02 + i_mat_l.m31*i_mat_r.m12 + i_mat_l.m32*i_mat_r.m22 + i_mat_l.m33*i_mat_r.m32;
+ this.m33=i_mat_l.m30*i_mat_r.m03 + i_mat_l.m31*i_mat_r.m13 + i_mat_l.m32*i_mat_r.m23 + i_mat_l.m33*i_mat_r.m33;
+ return;
+ }
+ /**
+ * この関数は、行列を単位行列にします。
+ */
+ public final void identity()
+ {
+ this.m00=this.m11=this.m22=this.m33=1;
+ this.m01=this.m02=this.m03=this.m10=this.m12=this.m13=this.m20=this.m21=this.m23=this.m30=this.m31=this.m32=0;
+ return;
+ }
+
+ public void MatrixLerp(MmdMatrix sm1, MmdMatrix sm2, float fLerpValue )
+ {
+ double fT = 1.0 - fLerpValue;
+ this.m00 = sm1.m00 * fLerpValue + sm2.m00 * fT;
+ this.m01 = sm1.m01 * fLerpValue + sm2.m01 * fT;
+ this.m02 = sm1.m02 * fLerpValue + sm2.m02 * fT;
+ this.m03 = sm1.m03 * fLerpValue + sm2.m03 * fT;
+ this.m10 = sm1.m10 * fLerpValue + sm2.m10 * fT;
+ this.m11 = sm1.m11 * fLerpValue + sm2.m11 * fT;
+ this.m12 = sm1.m12 * fLerpValue + sm2.m12 * fT;
+ this.m13 = sm1.m13 * fLerpValue + sm2.m13 * fT;
+ this.m20 = sm1.m20 * fLerpValue + sm2.m20 * fT;
+ this.m21 = sm1.m21 * fLerpValue + sm2.m21 * fT;
+ this.m22 = sm1.m22 * fLerpValue + sm2.m22 * fT;
+ this.m23 = sm1.m23 * fLerpValue + sm2.m23 * fT;
+ this.m30 = sm1.m30 * fLerpValue + sm2.m30 * fT;
+ this.m31 = sm1.m31 * fLerpValue + sm2.m31 * fT;
+ this.m32 = sm1.m32 * fLerpValue + sm2.m32 * fT;
+ this.m33 = sm1.m33 * fLerpValue + sm2.m33 * fT;
+ return;
+ }
+ public void QuaternionToMatrix(MmdVector4 pvec4Quat)
+ {
+ double x2 = pvec4Quat.x * pvec4Quat.x * 2.0f;
+ double y2 = pvec4Quat.y * pvec4Quat.y * 2.0f;
+ double z2 = pvec4Quat.z * pvec4Quat.z * 2.0f;
+ double xy = pvec4Quat.x * pvec4Quat.y * 2.0f;
+ double yz = pvec4Quat.y * pvec4Quat.z * 2.0f;
+ double zx = pvec4Quat.z * pvec4Quat.x * 2.0f;
+ double xw = pvec4Quat.x * pvec4Quat.w * 2.0f;
+ double yw = pvec4Quat.y * pvec4Quat.w * 2.0f;
+ double zw = pvec4Quat.z * pvec4Quat.w * 2.0f;
+
+ this.m00 = 1.0f - y2 - z2;
+ this.m01 = xy + zw;
+ this.m02 = zx - yw;
+ this.m10 = xy - zw;
+ this.m11 = 1.0f - z2 - x2;
+ this.m12 = yz + xw;
+ this.m20 = zx + yw;
+ this.m21 = yz - xw;
+ this.m22 = 1.0f - x2 - y2;
+
+ this.m03 = this.m13 = this.m23 = this.m30 = this.m31 = this.m32 = 0.0f;
+ this.m33 = 1.0f;
+ return;
+ }
+
+}
diff --git a/src/jp/nyatla/nymmd/types/MmdTexUV.java b/src/jp/nyatla/nymmd/types/MmdTexUV.java
new file mode 100644
index 0000000..248e23f
--- /dev/null
+++ b/src/jp/nyatla/nymmd/types/MmdTexUV.java
@@ -0,0 +1,59 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd.types;
+
+
+public class MmdTexUV
+{
+ public float u, v;
+ public static MmdTexUV[] createArray(int i_length)
+ {
+ MmdTexUV[] ret=new MmdTexUV[i_length];
+ for(int i=0;i<i_length;i++)
+ {
+ ret[i]=new MmdTexUV();
+ }
+ return ret;
+ }
+ public void setValue(MmdTexUV v)
+ {
+ this.u=v.u;
+ this.v=v.v;
+ return;
+ }
+}
diff --git a/src/jp/nyatla/nymmd/types/MmdVector3.java b/src/jp/nyatla/nymmd/types/MmdVector3.java
new file mode 100644
index 0000000..8ff2231
--- /dev/null
+++ b/src/jp/nyatla/nymmd/types/MmdVector3.java
@@ -0,0 +1,209 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd.types;
+
+
+
+public class MmdVector3
+{
+ public float x, y, z;
+ public MmdVector3()
+ {
+ }
+ public MmdVector3(float ix,float iy,float iz)
+ {
+ this.x=ix;this.y=iy;this.z=iz;
+ }
+ public static MmdVector3[] createArray(int i_length)
+ {
+ MmdVector3[] ret=new MmdVector3[i_length];
+ for(int i=0;i<i_length;i++)
+ {
+ ret[i]=new MmdVector3();
+ }
+ return ret;
+ }
+ public void setValue(MmdVector3 v)
+ {
+ this.x=v.x;
+ this.y=v.y;
+ this.z=v.z;
+ return;
+ }
+ public void Vector3Add(MmdVector3 pvec3Add1,MmdVector3 pvec3Add2)
+ {
+ this.x = pvec3Add1.x + pvec3Add2.x;
+ this.y = pvec3Add1.y + pvec3Add2.y;
+ this.z = pvec3Add1.z + pvec3Add2.z;
+ return;
+ }
+ public void Vector3Sub(MmdVector3 pvec3Sub1,MmdVector3 pvec3Sub2)
+ {
+ this.x = pvec3Sub1.x - pvec3Sub2.x;
+ this.y = pvec3Sub1.y - pvec3Sub2.y;
+ this.z = pvec3Sub1.z - pvec3Sub2.z;
+ return;
+ }
+ public void Vector3MulAdd(MmdVector3 pvec3Add1,MmdVector3 pvec3Add2, float fRate )
+ {
+ this.x = pvec3Add1.x + pvec3Add2.x * fRate;
+ this.y = pvec3Add1.y + pvec3Add2.y * fRate;
+ this.z = pvec3Add1.z + pvec3Add2.z * fRate;
+ }
+ public void Vector3Normalize(MmdVector3 pvec3Src)
+ {
+ double fSqr =(1.0f / Math.sqrt( pvec3Src.x * pvec3Src.x + pvec3Src.y * pvec3Src.y + pvec3Src.z * pvec3Src.z ));
+ this.x =(float)(pvec3Src.x * fSqr);
+ this.y =(float)(pvec3Src.y * fSqr);
+ this.z =(float)(pvec3Src.z * fSqr);
+ return;
+ }
+
+
+ public double Vector3DotProduct(MmdVector3 pvec3Src2)
+ {
+ return (this.x * pvec3Src2.x + this.y * pvec3Src2.y + this.z * pvec3Src2.z);
+ }
+
+ public void Vector3CrossProduct(MmdVector3 pvec3Src1, MmdVector3 pvec3Src2 )
+ {
+ final float vx1=pvec3Src1.x;
+ final float vy1=pvec3Src1.y;
+ final float vz1=pvec3Src1.z;
+ final float vx2=pvec3Src2.x;
+ final float vy2=pvec3Src2.y;
+ final float vz2=pvec3Src2.z;
+ this.x = vy1 * vz2 - vz1 * vy2;
+ this.y = vz1 * vx2 - vx1 * vz2;
+ this.z = vx1 * vy2 - vy1 * vx2;
+ }
+ public void Vector3Lerp(MmdVector3 pvec3Src1,MmdVector3 pvec3Src2, float fLerpValue )
+ {
+ float t0 = 1.0f - fLerpValue;
+
+ this.x = pvec3Src1.x * t0 + pvec3Src2.x * fLerpValue;
+ this.y = pvec3Src1.y * t0 + pvec3Src2.y * fLerpValue;
+ this.z = pvec3Src1.z * t0 + pvec3Src2.z * fLerpValue;
+ return;
+ }
+
+ public void Vector3Transform(MmdVector3 pVec3In,MmdMatrix matTransform)
+ {
+ final double vx=pVec3In.x;
+ final double vy=pVec3In.y;
+ final double vz=pVec3In.z;
+ this.x =(float)(vx * matTransform.m00 + vy * matTransform.m10 + vz * matTransform.m20 + matTransform.m30);
+ this.y =(float)(vx * matTransform.m01 + vy * matTransform.m11 + vz * matTransform.m21 + matTransform.m31);
+ this.z =(float)(vx * matTransform.m02 + vy * matTransform.m12 + vz * matTransform.m22 + matTransform.m32);
+ return;
+ }
+ public void Vector3Transform(MmdMatrix i_posmat,MmdMatrix matTransform)
+ {
+ final double vx=i_posmat.m30;
+ final double vy=i_posmat.m31;
+ final double vz=i_posmat.m32;
+ this.x =(float)(vx * matTransform.m00 + vy * matTransform.m10 + vz * matTransform.m20 + matTransform.m30);
+ this.y =(float)(vx * matTransform.m01 + vy * matTransform.m11 + vz * matTransform.m21 + matTransform.m31);
+ this.z =(float)(vx * matTransform.m02 + vy * matTransform.m12 + vz * matTransform.m22 + matTransform.m32);
+ return;
+ }
+
+ public void Vector3Rotate(MmdVector3 pVec3In,MmdMatrix matRotate)
+ {
+ final double vx=pVec3In.x;
+ final double vy=pVec3In.y;
+ final double vz=pVec3In.z;
+ this.x =(float)(vx * matRotate.m00 + vy * matRotate.m10 + vz * matRotate.m20);
+ this.y =(float)(vx * matRotate.m01 + vy * matRotate.m11 + vz * matRotate.m21);
+ this.z =(float)(vx * matRotate.m02 + vy * matRotate.m12 + vz * matRotate.m22);
+ return;
+ }
+ public void QuaternionToEuler(MmdVector4 pvec4Quat )
+ {
+ // XYZ軸回転の取得
+ // Y回転を求める
+ final double x2 = pvec4Quat.x + pvec4Quat.x;
+ final double y2 = pvec4Quat.y + pvec4Quat.y;
+ final double z2 = pvec4Quat.z + pvec4Quat.z;
+ final double xz2 = pvec4Quat.x * z2;
+ final double wy2 = pvec4Quat.w * y2;
+ double temp = -(xz2 - wy2);
+
+ // 誤差対策
+ if( temp >= 1.0 ){
+ temp = 1.0;
+ }else if( temp <= -1.0 ){
+ temp = -1.0;
+ }
+
+ double yRadian = Math.sin(temp);
+
+ // 他の回転を求める
+ double xx2 = pvec4Quat.x * x2;
+ double xy2 = pvec4Quat.x * y2;
+ double zz2 = pvec4Quat.z * z2;
+ double wz2 = pvec4Quat.w * z2;
+
+ if( yRadian < 3.1415926f * 0.5f )
+ {
+ if( yRadian > -3.1415926f * 0.5f )
+ {
+ double yz2 = pvec4Quat.y * z2;
+ double wx2 = pvec4Quat.w * x2;
+ double yy2 = pvec4Quat.y * y2;
+ this.x = (float)Math.atan2(yz2 + wx2, (1.0f - (xx2 + yy2)) );
+ this.y = (float)yRadian;
+ this.z = (float)Math.atan2( (xy2 + wz2), (1.0f - (yy2 + zz2)) );
+ }
+ else
+ {
+ this.x = (float)-Math.atan2( (xy2 - wz2), (1.0f - (xx2 + zz2)) );
+ this.y = (float)yRadian;
+ this.z = 0.f;
+ }
+ }
+ else
+ {
+ this.x = (float)Math.atan2( (xy2 - wz2), (1.0f - (xx2 + zz2)) );
+ this.y = (float)yRadian;
+ this.z = 0.0f;
+ }
+ }
+
+
+}
diff --git a/src/jp/nyatla/nymmd/types/MmdVector4.java b/src/jp/nyatla/nymmd/types/MmdVector4.java
new file mode 100644
index 0000000..f92e6f6
--- /dev/null
+++ b/src/jp/nyatla/nymmd/types/MmdVector4.java
@@ -0,0 +1,137 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd.types;
+
+
+public class MmdVector4
+{
+ public double x, y, z, w;
+ public void setValue(MmdVector4 v)
+ {
+ this.x=v.x;
+ this.y=v.y;
+ this.z=v.z;
+ this.w=v.w;
+ return;
+ }
+ public void QuaternionSlerp(MmdVector4 pvec4Src1,MmdVector4 pvec4Src2, double fLerpValue )
+ {
+
+ // Qlerp
+ double qr = pvec4Src1.x * pvec4Src2.x + pvec4Src1.y * pvec4Src2.y + pvec4Src1.z * pvec4Src2.z + pvec4Src1.w * pvec4Src2.w;
+ double t0 = 1.0f - fLerpValue;
+
+ if( qr < 0 )
+ {
+ this.x = pvec4Src1.x * t0 - pvec4Src2.x * fLerpValue;
+ this.y = pvec4Src1.y * t0 - pvec4Src2.y * fLerpValue;
+ this.z = pvec4Src1.z * t0 - pvec4Src2.z * fLerpValue;
+ this.w = pvec4Src1.w * t0 - pvec4Src2.w * fLerpValue;
+ }
+ else
+ {
+ this.x = pvec4Src1.x * t0 + pvec4Src2.x * fLerpValue;
+ this.y = pvec4Src1.y * t0 + pvec4Src2.y * fLerpValue;
+ this.z = pvec4Src1.z * t0 + pvec4Src2.z * fLerpValue;
+ this.w = pvec4Src1.w * t0 + pvec4Src2.w * fLerpValue;
+ }
+ QuaternionNormalize(this);
+ return;
+ }
+ public void QuaternionNormalize(MmdVector4 pvec4Src)
+ {
+ final double fSqr =1.0 / Math.sqrt(( pvec4Src.x * pvec4Src.x + pvec4Src.y * pvec4Src.y + pvec4Src.z * pvec4Src.z + pvec4Src.w * pvec4Src.w));
+
+ this.x =(pvec4Src.x * fSqr);
+ this.y =(pvec4Src.y * fSqr);
+ this.z =(pvec4Src.z * fSqr);
+ this.w =(pvec4Src.w * fSqr);
+ }
+ public void QuaternionCreateAxis(MmdVector3 pvec3Axis, double fRotAngle )
+ {
+ if( Math.abs( fRotAngle ) < 0.0001f )
+ {
+ this.x = this.y = this.z = 0.0f;
+ this.w = 1.0f;
+ }
+ else
+ {
+ fRotAngle *= 0.5f;
+ double fTemp = Math.sin(fRotAngle);
+
+ this.x = pvec3Axis.x * fTemp;
+ this.y = pvec3Axis.y * fTemp;
+ this.z = pvec3Axis.z * fTemp;
+ this.w = Math.cos( fRotAngle );
+ }
+ return;
+ }
+ public void QuaternionMultiply(MmdVector4 pvec4Src1,MmdVector4 pvec4Src2)
+ {
+ double px, py, pz, pw;
+ double qx, qy, qz, qw;
+
+ px = pvec4Src1.x; py = pvec4Src1.y; pz = pvec4Src1.z; pw = pvec4Src1.w;
+ qx = pvec4Src2.x; qy = pvec4Src2.y; qz = pvec4Src2.z; qw = pvec4Src2.w;
+
+ this.x = pw * qx + px * qw + py * qz - pz * qy;
+ this.y = pw * qy - px * qz + py * qw + pz * qx;
+ this.z = pw * qz + px * qy - py * qx + pz * qw;
+ this.w = pw * qw - px * qx - py * qy - pz * qz;
+ }
+
+ public void QuaternionCreateEuler(MmdVector3 pvec3EulerAngle )
+ {
+ final double xRadian = pvec3EulerAngle.x * 0.5;
+ final double yRadian = pvec3EulerAngle.y * 0.5;
+ final double zRadian = pvec3EulerAngle.z * 0.5;
+ final double sinX = Math.sin( xRadian );
+ final double cosX = Math.cos( xRadian );
+ final double sinY = Math.sin( yRadian );
+ final double cosY = Math.cos( yRadian );
+ final double sinZ = Math.sin( zRadian );
+ final double cosZ = Math.cos( zRadian );
+
+ // XYZ
+ this.x = sinX * cosY * cosZ - cosX * sinY * sinZ;
+ this.y = cosX * sinY * cosZ + sinX * cosY * sinZ;
+ this.z = cosX * cosY * sinZ - sinX * sinY * cosZ;
+ this.w = cosX * cosY * cosZ + sinX * sinY * sinZ;
+ }
+
+}
diff --git a/src/jp/nyatla/nymmd/types/MotionData.java b/src/jp/nyatla/nymmd/types/MotionData.java
new file mode 100644
index 0000000..c8352eb
--- /dev/null
+++ b/src/jp/nyatla/nymmd/types/MotionData.java
@@ -0,0 +1,125 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd.types;
+
+import jp.nyatla.nymmd.core.PmdBone;
+
+
+public class MotionData
+{
+ public String szBoneName; // ボーン名
+ public int ulNumKeyFrames; // キーフレーム数
+ public BoneKeyFrame[] pKeyFrames; // キーフレームデータ配列
+ /**
+ *
+ * @param fFrame
+ * @param i_pmd_bone
+ * 出力先オブジェクト
+ */
+ public void getMotionPosRot(float fFrame,PmdBone i_pmd_bone)
+ {
+ int ulNumKeyFrame = this.ulNumKeyFrames;
+ BoneKeyFrame[] bone_key_frame=this.pKeyFrames;
+
+
+ // 最終フレームを過ぎていた場合
+ if( fFrame > bone_key_frame[ulNumKeyFrame - 1].fFrameNo )
+ {
+ fFrame = bone_key_frame[ulNumKeyFrame - 1].fFrameNo;
+ }
+
+ // 現在の時間がどのキー近辺にあるか
+ int lKey0=findByBinarySearch(bone_key_frame,fFrame,0,ulNumKeyFrame-1)-1;
+ int lKey1=lKey0+1;
+ if( lKey1 == ulNumKeyFrame )
+ {
+ lKey1 = ulNumKeyFrame - 1;
+ }
+ if(lKey0<0){
+ lKey0=0;
+ }
+ // 前後のキーの時間
+ float fTime0 = bone_key_frame[lKey0].fFrameNo;
+ float fTime1 = bone_key_frame[lKey1].fFrameNo;
+
+ MmdVector3 pvec3Pos= i_pmd_bone.m_vec3Position;
+ MmdVector4 pvec4Rot= i_pmd_bone.m_vec4Rotate;
+
+ // 前後のキーの間でどの位置にいるか
+ if( lKey0 != lKey1 )
+ {
+ float fLerpValue = (fFrame - fTime0) / (fTime1 - fTime0);
+ pvec3Pos.Vector3Lerp(bone_key_frame[lKey0].vec3Position,bone_key_frame[lKey1].vec3Position, fLerpValue);
+ pvec4Rot.QuaternionSlerp(bone_key_frame[lKey0].vec4Rotate,bone_key_frame[lKey1].vec4Rotate, fLerpValue);
+ pvec4Rot.QuaternionNormalize(pvec4Rot);//これほんとにいるの?
+ }else{
+ pvec3Pos.setValue(bone_key_frame[lKey0].vec3Position);
+ pvec4Rot.setValue(bone_key_frame[lKey0].vec4Rotate);
+ }
+ }
+ /**
+ * @author やねうらお さん
+ * @param pKeyFrames
+ * @param fFrame
+ * @param start
+ * @param end
+ * @return
+ */
+ private static int findByBinarySearch(BoneKeyFrame[] pKeyFrames,float fFrame, int start, int end)
+ {
+ int diff = end - start;
+ if (diff < 8) {
+ // ある程度小さくなったら逐次サーチ。このな かに見つかるはずなんだ。
+ for (int i = start; i < end; i++) {
+ if (fFrame < pKeyFrames[i].fFrameNo) {
+ return i;
+ }
+ }
+ return end;
+ }
+
+ // 再帰的に調べる
+ int mid = (start + end) / 2;
+ if (fFrame < pKeyFrames[mid].fFrameNo){
+ return findByBinarySearch(pKeyFrames, fFrame, start, mid);
+ }
+ else{
+ return findByBinarySearch(pKeyFrames, fFrame, mid, end);
+ }
+ }
+}
diff --git a/src/jp/nyatla/nymmd/types/PmdMaterial.java b/src/jp/nyatla/nymmd/types/PmdMaterial.java
new file mode 100644
index 0000000..16a8890
--- /dev/null
+++ b/src/jp/nyatla/nymmd/types/PmdMaterial.java
@@ -0,0 +1,51 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd.types;
+
+
+public class PmdMaterial
+{
+ public final MmdColor4 col4Diffuse=new MmdColor4();
+ public final MmdColor4 col4Specular=new MmdColor4();
+ public final MmdColor4 col4Ambient=new MmdColor4();
+ public float fShininess;
+ public String texture_name;
+ public String sphere_name;
+ public short[] indices;
+ public int unknown;
+};
diff --git a/src/jp/nyatla/nymmd/types/PmdSkinInfo.java b/src/jp/nyatla/nymmd/types/PmdSkinInfo.java
new file mode 100644
index 0000000..1249ba5
--- /dev/null
+++ b/src/jp/nyatla/nymmd/types/PmdSkinInfo.java
@@ -0,0 +1,47 @@
+/*
+ * PROJECT: NyMmd
+ * --------------------------------------------------------------------------------
+ * The MMD for Java is Java version MMD Motion player class library.
+ * NyMmd is modules which removed the ARToolKit origin codes from ARTK_MMD,
+ * and was ported to Java.
+ *
+ * This is based on the ARTK_MMD v0.1 by PY.
+ * http://ppyy.if.land.to/artk_mmd.html
+ * py1024<at>gmail.com
+ * http://www.nicovideo.jp/watch/sm7398691
+ *
+ *
+ * The MIT License
+ * Copyright (C)2008-2012 nyatla
+ * nyatla39<at>gmail.com
+ * http://nyatla.jp
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+package jp.nyatla.nymmd.types;
+
+
+
+public class PmdSkinInfo
+{
+ public float fWeight;// ウェイト
+ public int unBoneNo_0;
+ public int unBoneNo_1;
+} \ No newline at end of file
diff --git a/src/ru/olamedia/asset/Shader.java b/src/ru/olamedia/asset/Shader.java
new file mode 100644
index 0000000..8fd9ada
--- /dev/null
+++ b/src/ru/olamedia/asset/Shader.java
@@ -0,0 +1,40 @@
+package ru.olamedia.asset;
+
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLContext;
+
+import com.jogamp.opengl.util.glsl.ShaderCode;
+import com.jogamp.opengl.util.glsl.ShaderProgram;
+import com.jogamp.opengl.util.glsl.ShaderState;
+
+public class Shader {
+ private ShaderState state;
+
+ public ShaderState getState() {
+ return state;
+ }
+
+ public void compile() {
+ GL2ES2 gl = GLContext.getCurrentGL().getGL2ES2();
+ state = new ShaderState();
+ state.setVerbose(true);
+ final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), "shader", "shader/bin",
+ "block", true);
+ final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), "shader",
+ "shader/bin", "block", true);
+ final ShaderProgram sp0 = new ShaderProgram();
+ sp0.add(gl, vp0, System.err);
+ sp0.add(gl, fp0, System.err);
+ state.attachShaderProgram(gl, sp0, true);
+ }
+
+ public void enable() {
+ GL2ES2 gl = GLContext.getCurrentGL().getGL2ES2();
+ state.useProgram(gl, true);
+ }
+
+ public void disable() {
+ GL2ES2 gl = GLContext.getCurrentGL().getGL2ES2();
+ state.useProgram(gl, false);
+ }
+}
diff --git a/src/ru/olamedia/asset/Sprite.java b/src/ru/olamedia/asset/Sprite.java
new file mode 100644
index 0000000..84839d2
--- /dev/null
+++ b/src/ru/olamedia/asset/Sprite.java
@@ -0,0 +1,115 @@
+package ru.olamedia.asset;
+
+import java.awt.Graphics;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+
+public class Sprite {
+ private BufferedImage combinedImage;
+ Graphics g;
+ int width;
+ int height;
+ int w;
+ int h;
+ int sizeX;
+ int sizeY;
+ int size;
+ int length = 0;
+ SpriteOffset current;
+ public void dispose(){
+ if (null != combinedImage){
+ combinedImage = null;
+ }
+ if (null != g){
+ g.dispose();
+ }
+ }
+
+ int waiting = 0;
+
+ public BufferedImage getImage() {
+ return combinedImage;
+ }
+
+ public Sprite(int width, int height, int w, int h) {
+ this.width = width;
+ this.height = height;
+ this.w = w;
+ this.h = h;
+ sizeX = width / w;
+ sizeY = height / h;
+ size = sizeY * sizeX;
+ current = new SpriteOffset(0, 0);
+ combinedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+ g = combinedImage.getGraphics();
+ /*g.setColor(Color.darkGray);
+ g.setPaintMode();
+ g.fillRect(0, 0, width, height);*/
+ }
+
+ public void next() {
+ current.x += w;
+ if (current.x + w > width) {
+ current.x = 0;
+ current.y += h;
+ }
+ }
+
+ public SpriteRectangle addImage(String path) throws AssetNotFoundException {
+ final Asset asset = AssetManager.getAsset(path);
+ BufferedImage image;
+ try {
+ image = ImageIO.read(asset.getInputStream());
+ return addImage(image);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public SpriteRectangle addImage(BufferedImage img) {
+ if (current.y + h > height) {
+ throw new RuntimeException("Out of bounds while creating Sprite");
+ }
+ final int x = (int) current.x;
+ final int y = (int) current.y;
+ waiting++;
+ // img.getWidth(new ImageObserver() {
+ // @Override
+ // public boolean imageUpdate(Image img1, int arg1, int arg2, int arg3,
+ // int arg4, int arg5) {
+ //System.out.println("Sprite: draw " + img.getWidth(null));
+ /*g.setColor(Color.magenta);
+ g.fillRect(x, y, w, h);*/
+ g.drawImage(img, x, y, w, h, null, null);
+ waiting--;
+ // return false;
+ // }
+ // });
+ SpriteRectangle area = new SpriteRectangle((1 / (float) width) * current.x, (1 / (float) height) * current.y,
+ (1 / (float) width) * (current.x + 16), (1 / (float) height) * (current.y + 16));
+ next();
+ return area;
+ }
+
+ public void write(String path) {
+ /*
+ * while (waiting > 0) {
+ * try {
+ * Thread.sleep(100);
+ * } catch (InterruptedException e) {
+ * e.printStackTrace();
+ * }
+ * }
+ */
+ g.dispose();
+ try {
+ ImageIO.write(combinedImage, "PNG", new File(path));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/ru/olamedia/asset/SpriteOffset.java b/src/ru/olamedia/asset/SpriteOffset.java
new file mode 100644
index 0000000..6720daa
--- /dev/null
+++ b/src/ru/olamedia/asset/SpriteOffset.java
@@ -0,0 +1,10 @@
+package ru.olamedia.asset;
+
+public class SpriteOffset {
+ public float x;
+ public float y;
+ public SpriteOffset(float x, float y) {
+ this.x = x;
+ this.y = y;
+ }
+}
diff --git a/src/ru/olamedia/asset/SpriteRectangle.java b/src/ru/olamedia/asset/SpriteRectangle.java
new file mode 100644
index 0000000..401d6aa
--- /dev/null
+++ b/src/ru/olamedia/asset/SpriteRectangle.java
@@ -0,0 +1,11 @@
+package ru.olamedia.asset;
+
+public class SpriteRectangle {
+ public SpriteOffset topLeft;
+ public SpriteOffset bottomRight;
+
+ public SpriteRectangle(float left, float top, float right, float bottom) {
+ topLeft = new SpriteOffset(left, top);
+ bottomRight = new SpriteOffset(right, bottom);
+ }
+}
diff --git a/src/ru/olamedia/asset/shader/block.fp b/src/ru/olamedia/asset/shader/block.fp
new file mode 100644
index 0000000..291e975
--- /dev/null
+++ b/src/ru/olamedia/asset/shader/block.fp
@@ -0,0 +1,28 @@
+
+
+smooth in vec2 texCoord;
+//vec4 frontColor;
+
+uniform sampler2D mesh_ActiveTexture;
+
+vec4 frontColor = vec4(1.0);
+const vec4 texEnvColor = vec4(0.0);
+
+const vec4 zerov4 = vec4(0.0);
+const vec4 onev4 = vec4(1.0);
+
+vec4 calcTexColor(in vec4 color, in vec4 texColor) {
+ color.rgb = mix(color.rgb, texEnvColor.rgb, texColor.rgb);
+ color.a *= texColor.a;
+ color = clamp(color, zerov4, onev4);
+ return color;
+}
+
+void main (void)
+{
+ vec4 texColor;
+ texColor = texture2D(mesh_ActiveTexture, texCoord.st);
+ if (texColor.a < 0.1f) discard;
+ vec4 color = calcTexColor(frontColor, texColor);
+ gl_FragColor = vec4(gl_FragColor.a) * gl_FragColor + vec4(1.0 - gl_FragColor.a) * texColor;
+} \ No newline at end of file
diff --git a/src/ru/olamedia/asset/shader/block.vp b/src/ru/olamedia/asset/shader/block.vp
new file mode 100644
index 0000000..989d182
--- /dev/null
+++ b/src/ru/olamedia/asset/shader/block.vp
@@ -0,0 +1,25 @@
+//precision lowp float;
+//precision lowp int;
+uniform mat4 pmvMatrix[4]; // P, Mv, Mvi and Mvit
+uniform vec4 sunColor;
+uniform sampler2D mesh_ActiveTexture;
+
+attribute vec4 mesh_vertices;
+attribute vec4 mesh_colors;
+
+attribute vec2 mesh_texCoord;
+
+invariant out vec4 position;
+vec4 color;
+smooth out vec2 texCoord;
+
+void main(void)
+{
+ // Transforming The Vertex Position To ModelView-Space
+ position = pmvMatrix[1] * mesh_vertices; // vertex eye position
+ texCoord = mesh_texCoord;
+
+ gl_Position = pmvMatrix[0] * position;
+
+ color = mesh_colors * sunColor;
+}
diff --git a/src/ru/olamedia/camera/Cameraman.java b/src/ru/olamedia/camera/Cameraman.java
index 7dbbcc0..1ea1e92 100644
--- a/src/ru/olamedia/camera/Cameraman.java
+++ b/src/ru/olamedia/camera/Cameraman.java
@@ -9,6 +9,10 @@ package ru.olamedia.camera;
*
*/
public interface Cameraman {
+ public MatrixCamera getCamera();
+
+ public void setCamera(MatrixCamera camera);
+
public float getCameraX();
public float getCameraY();
diff --git a/src/ru/olamedia/camera/MatrixCamera.java b/src/ru/olamedia/camera/MatrixCamera.java
index b9290b7..de07c6f 100644
--- a/src/ru/olamedia/camera/MatrixCamera.java
+++ b/src/ru/olamedia/camera/MatrixCamera.java
@@ -10,29 +10,39 @@ import javax.media.opengl.fixedfunc.GLMatrixFunc;
import javax.media.opengl.glu.GLU;
import javax.vecmath.Vector3f;
+import jogamp.opengl.ProjectFloat;
+
+import org.openmali.vecmath2.Matrix4f;
+
import ru.olamedia.olacraft.game.Game;
+import ru.olamedia.olacraft.world.location.Location3f;
+import ru.olamedia.geom.Frustum2;
import ru.olamedia.input.Keyboard;
-import ru.olamedia.math.Frustum;
import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.math.geom.Frustum;
import com.jogamp.opengl.util.PMVMatrix;
-public class MatrixCamera {
-
+public class MatrixCamera implements Cameraman {
+ protected MatrixCamera attachedCamera = null;
public PMVMatrix pmvMatrix = new PMVMatrix(true);
private boolean isDirty = true;
- public GLUniformData pmvMatrixUniform;
+ public GLUniformData pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf());
public boolean isOrientationChanged = true;
protected float fov = 90f;
protected float aspect = 1f;
protected float zNear = 0.1f;
- protected float zFar = 1000f;
+ protected float zFar = 500f;
private boolean isPitchLocked = true;
private float minPitch = -80f;
private float maxPitch = 80f;
public Frustum frustum = new Frustum();
+ public Frustum frustump = new Frustum();
+ public ru.olamedia.math.Frustum frustum1 = new ru.olamedia.math.Frustum();
+ public Frustum2 frustum2 = new Frustum2();
private Vector3f position = new Vector3f();
private float yaw = 0; // around y
@@ -40,17 +50,42 @@ public class MatrixCamera {
private float roll = 0;
private Vector3f look = new Vector3f();
+ private Vector3f nlook = new Vector3f();
+
+ /**
+ * @return the nlook
+ */
+ public Vector3f getNlook() {
+ return nlook;
+ }
+
private Vector3f right = new Vector3f();
private Vector3f up = new Vector3f();
public boolean isFrustumVisible = false;
int counter = 0;
+ private FloatBuffer mv = pmvMatrix.glGetMvMatrixf();
+ final private int mvOffset = mv.position();
+ private float[] mulMVP = new float[16]; // as calculated by pmvMatrix
+ StringBuilder s = new StringBuilder();
+
+ public Location3f offset = new Location3f();
public void pack() {
if (isAttachedToCameraman) {
- position.x = cameraman.getCameraX();
- position.y = cameraman.getCameraY();
- position.z = cameraman.getCameraZ();
+ position.x = cameraman.getCameraX() + offset.x;
+ position.y = cameraman.getCameraY() + offset.y;
+ position.z = cameraman.getCameraZ() + offset.z;
+ if (cameraman instanceof MatrixCamera) {
+ final MatrixCamera cam = (MatrixCamera) cameraman;
+ yaw = cam.getYaw();
+ pitch = cam.getPitch();
+ roll = cam.getRoll();
+ zNear = cam.getzNear();
+ zFar = cam.getzFar();
+ fov = cam.getFov();
+ aspect = cam.getAspect();
+ }
}
pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
pmvMatrix.glLoadIdentity();
@@ -58,78 +93,224 @@ public class MatrixCamera {
pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
pmvMatrix.glLoadIdentity();
- pmvMatrix.glRotatef(360 - pitch, 1, 0, 0);
- pmvMatrix.glRotatef(360 - yaw, 0, 1, 0);
- pmvMatrix.glRotatef(360 - roll, 0, 0, 1);
+ pmvMatrix.glRotatef(-pitch, 1, 0, 0);
+ pmvMatrix.glRotatef(-yaw, 0, 1, 0);
+ pmvMatrix.glRotatef(-roll, 0, 0, 1);
+ pmvMatrix.glGetFrustum();
pmvMatrix.glTranslatef(-position.x, -position.y, -position.z);
// pmvMatrix.setDirty();
pmvMatrix.update();
- FloatBuffer mv = FloatBuffer.allocate(16);
- pmvMatrix.glGetFloatv(GLMatrixFunc.GL_MODELVIEW_MATRIX, mv);
+ // mv = pmvMatrix.glGetMatrixf(GLMatrixFunc.GL_MODELVIEW);
+ // pmvMatrix.glGetFloatv(GLMatrixFunc.GL_MODELVIEW_MATRIX, mv);
- right.set(mv.get(0), mv.get(4), mv.get(8));
- look.set(mv.get(2), mv.get(6), mv.get(10));
+ right.set(mv.get(mvOffset + 0), mv.get(mvOffset + 4), mv.get(mvOffset + 8));
+ look.set(mv.get(mvOffset + 2), mv.get(mvOffset + 6), mv.get(mvOffset + 10));
+ // look.negate();
up.cross(look, right);
+ nlook.set(look);
+ nlook.negate();
+ // System.out.println(frustum2.toString());
+ // packFrustum();
+ isDirty = false;
+ isOrientationChanged = false;
+ }
+
+ protected FloatBuffer Mvi = FloatBuffer.allocate(16);
+ protected FloatBuffer Pi = FloatBuffer.allocate(16);
+ protected ProjectFloat projectFloat = new ProjectFloat(true);
+
+ public void renderFrustum() {
+ final GL2 gl = GLContext.getCurrentGL().getGL2();
+ gl.glDisable(GL2.GL_CULL_FACE);
+ gl.glDisable(GL2.GL_DEPTH_TEST);
+ gl.glDisable(GL2.GL_TEXTURE_2D);
+ gl.glDisable(GL2.GL_ALPHA_TEST);
+ gl.glEnable(GL2.GL_BLEND);
+ gl.glBlendFunc(GL2.GL_SRC_ALPHA, GL2.GL_ONE);
+ gl.glColor4f(0.2f, 0.2f, 0.7f, 0.3f);
+ gl.glBegin(GL2.GL_QUADS);
+ flb.v();
+ flt.v();
+ frt.v();
+ frb.v();
+ gl.glEnd();
+ gl.glBegin(GL2.GL_QUADS);
+ nlb.v();
+ nlt.v();
+ nrt.v();
+ nrb.v();
+ gl.glEnd();
+ gl.glBegin(GL2.GL_LINES);
+ gl.glColor4f(1f, 1f, 1f, 0.4f);
+ nearc.v();
+ farc.v();
+ gl.glColor3f(1.0f, 0.0f, 1.0f);
+ nlb.v();
+ flb.v();
+ nlt.v();
+ flt.v();
+ nrt.v();
+ frt.v();
+ nrb.v();
+ frb.v();
+ gl.glEnd();
+ }
+
+ private float renderFrustumTang = (float) Math.tan((Math.PI * fov / 180) / 2.0f);
+ private float renderFrustumNear = 1f;
+ private float renderFrustumFar = 100f;
+ private float renderFrustumNh = renderFrustumNear * renderFrustumTang;
+ private float renderFrustumNw = renderFrustumNh * aspect;
+ private float renderFrustumFh = renderFrustumFar * renderFrustumTang;
+ private float renderFrustumFw = renderFrustumFh * aspect;
+
+ public void updateFrustum() {
+ frustum.updateByPlanes(pmvMatrix.glGetFrustum().getPlanes());
+ projectFloat.gluInvertMatrixf(pmvMatrix.glGetMvMatrixf(), Mvi);
+ projectFloat.gluInvertMatrixf(pmvMatrix.glGetPMatrixf(), Pi);
+ renderFrustumTang = (float) Math.tan((Math.PI * fov / 180) / 2.0f);
+ renderFrustumNear = 1f;
+ renderFrustumFar = 100f;
+ renderFrustumNh = renderFrustumNear * renderFrustumTang;
+ renderFrustumNw = renderFrustumNh * aspect;
+ renderFrustumFh = renderFrustumFar * renderFrustumTang;
+ renderFrustumFw = renderFrustumFh * aspect;
+
+ eye.set(position.x, position.y, position.z);
+ nearc.set(eye);
+ nearc.translate(look, -renderFrustumNear);
+ farc.set(eye);
+ farc.translate(look, -renderFrustumFar);
+ flb.set(farc);
+ flb.translate(right, -renderFrustumFw / 2);
+ flb.translate(up, -renderFrustumFh / 2);
+ flt.set(farc);
+ flt.translate(right, -renderFrustumFw / 2);
+ flt.translate(up, renderFrustumFh / 2);
+ frb.set(farc);
+ frb.translate(right, renderFrustumFw / 2);
+ frb.translate(up, -renderFrustumFh / 2);
+ frt.set(farc);
+ frt.translate(right, renderFrustumFw / 2);
+ frt.translate(up, renderFrustumFh / 2);
+
+ nlb.set(nearc);
+ nlb.translate(right, -renderFrustumNw / 2);
+ nlb.translate(up, -renderFrustumNh / 2);
+ nlt.set(nearc);
+ nlt.translate(right, -renderFrustumNw / 2);
+ nlt.translate(up, renderFrustumNh / 2);
+ nrb.set(nearc);
+ nrb.translate(right, renderFrustumNw / 2);
+ nrb.translate(up, -renderFrustumNh / 2);
+ nrt.set(nearc);
+ nrt.translate(right, renderFrustumNw / 2);
+ nrt.translate(up, renderFrustumNh / 2);
+
+ }
+
+ private vec eye = new vec();
+ private vec nearc = new vec();
+ private vec flb = new vec();
+ private vec flt = new vec();
+ private vec frb = new vec();
+ private vec frt = new vec();
+ private vec nlb = new vec();
+ private vec nlt = new vec();
+ private vec nrb = new vec();
+ private vec nrt = new vec();
+ private vec farc = new vec();
+ private GL2 gl2;
+
+ private class vec {
+ public float x;
+ public float y;
+ public float z;
+
+ public void v() {
+ gl2.glVertex3f(x, y, z);
+ }
- pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf());
-
- packFrustum();
- }
-
- 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 = (float) Math.tan((Math.PI * fov / 180) / 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);
+ public void set(vec v) {
+ set(v.x, v.y, v.z);
+ }
+
+ public void set(float x, float y, float z) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public void translate(Vector3f dir, float d) {
+ translate(dir.x * d, dir.y * d, dir.z * d);
+ }
+
+ public void translate(float x, float y, float z) {
+ this.x += x;
+ this.y += y;
+ this.z += z;
+ }
}
+ // private void packFrustum() {
+ // 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, zNear);
+ // ru.olamedia.math.Vector3f farc = eyef.translate(look, zFar);
+ // final float tang = (float) Math.tan((Math.PI * fov / 180) / 2.0f);
+ // final float nh = zNear * tang * (isFrustumVisible ? 0.3f : 1);// zNear *
+ // // tang;
+ // final float nw = nh * aspect * aspect;
+ // final float fh = zFar * tang * (isFrustumVisible ? 0.5f : 1);// zNear *
+ // // tang;
+ // final float fw = fh * aspect * aspect;
+ // final ru.olamedia.math.Vector3f nrb = nearc.translate(right, -nw /
+ // 2).translate(up, -nh / 2);
+ // final ru.olamedia.math.Vector3f nlb = nearc.translate(right, nw /
+ // 2).translate(up, -nh / 2);
+ // @SuppressWarnings("unused")
+ // final ru.olamedia.math.Vector3f nrt = nearc.translate(right, -nw /
+ // 2).translate(up, nh / 2);
+ // final ru.olamedia.math.Vector3f nlt = nearc.translate(right, nw /
+ // 2).translate(up, nh / 2);
+ // final ru.olamedia.math.Vector3f frb = farc.translate(right, -fw /
+ // 2).translate(up, -fh / 2);
+ // final ru.olamedia.math.Vector3f flb = farc.translate(right, fw /
+ // 2).translate(up, -fh / 2);
+ // final ru.olamedia.math.Vector3f frt = farc.translate(right, -fw /
+ // 2).translate(up, fh / 2);
+ // final ru.olamedia.math.Vector3f flt = farc.translate(right, fw /
+ // 2).translate(up, fh / 2);
+ //
+ // frustum1.leftPlane.set3Points(nlb, flb, flt);
+ // frustum1.leftPlane.n.negate();
+ // frustum1.rightPlane.set3Points(nrb, frt, frb);
+ // // frustum.rightPlane.n.negate();
+ // frustum1.topPlane.set3Points(nlb, frb, flb);// nlt, frt, flt);
+ // // frustum.topPlane.n.negate();
+ // frustum1.bottomPlane.set3Points(frt, nlt, flt);
+ // // frustum.bottomPlane.n.negate();
+ // frustum1.nearPlane.set3Points(nlb, nlt, nrb);
+ // frustum1.farPlane.set3Points(flt, flb, frb);
+ // }
+
private GLU glu;
- public void setUp(GLAutoDrawable drawable) {
+ public void updateControls() {
updateKeyboard();
updateMouse();
- if (glu == null) {
- glu = new GLU();
- }
- if (isDirty) {
- pack();
- }
- GL2 gl = GLContext.getCurrentGL().getGL2();
+ }
+
+ public void setUp() {
+ final GL2 gl = GLContext.getCurrentGL().getGL2();
gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
gl.glLoadMatrixf(pmvMatrix.glGetPMatrixf());
gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
- FloatBuffer pmv = FloatBuffer.allocate(16);
- pmvMatrix.glGetFloatv(GLMatrixFunc.GL_MODELVIEW_MATRIX, pmv);
- gl.glLoadMatrixf(pmv);
+ // FloatBuffer pmv = FloatBuffer.allocate(16);
+ // pmvMatrix.glGetFloatv(GLMatrixFunc.GL_MODELVIEW_MATRIX, pmv);
+ gl.glLoadMatrixf(pmvMatrix.glGetMvMatrixf());
}
public float intersectsRectangle(Vector3f vertex1, Vector3f vertex2, Vector3f vertex3, Vector3f vertex4) {
@@ -234,6 +415,7 @@ public class MatrixCamera {
pitch = pitch % 360;
setDirty();
isOrientationChanged = true;
+ updateMouse();
}
public void updateMouse() {
@@ -258,17 +440,18 @@ public class MatrixCamera {
public void updateKeyboard() {
if (isAttachedToCameraman) {
- this.cameraman.update(Game.instance.getDelta());
+ this.cameraman.update(Game.instance.getFrameDelta());
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
+ final int left = Keyboard.isKeyDown("strafeLeft") ? 1 : 0;
+ final int right = Keyboard.isKeyDown("strafeRight") ? 1 : 0;
+ final int up = Keyboard.isKeyDown("flyForward") ? 1 : 0;
+ final int down = Keyboard.isKeyDown("flyBack") ? 1 : 0;
+ final int flyUp = Keyboard.isKeyDown("flyUp") ? 1 : 0;
+ final int flyDown = Keyboard.isKeyDown("flyDown") ? 1 : 0;
+ final float distance = 4f * 4.5f * Game.instance.getFrameDelta(); // runspeed,
+ // m/s
if (up + down + right + left + flyDown + flyUp > 0) {
translate(//
right * distance - left * distance,//
@@ -312,8 +495,10 @@ public class MatrixCamera {
* the aspect to set
*/
public void setAspect(float aspect) {
- this.aspect = aspect;
- setDirty();
+ if (aspect != this.aspect) {
+ this.aspect = aspect;
+ setDirty();
+ }
}
/**
@@ -378,6 +563,7 @@ public class MatrixCamera {
public void setPitch(float pitch) {
this.pitch = pitch;
setDirty();
+ updateMouse();
}
/**
@@ -455,7 +641,7 @@ public class MatrixCamera {
setDirty();
}
- private void setDirty() {
+ public void setDirty() {
isDirty = true;
}
@@ -475,15 +661,21 @@ public class MatrixCamera {
return roll;
}
- public void attachTo(Cameraman player) {
+ public void attachTo(Cameraman player, boolean captureControls) {
this.cameraman = player;
this.isAttachedToCameraman = true;
- this.cameraman.captureControls();
+ if (captureControls) {
+ this.cameraman.captureControls();
+ }
+ this.cameraman.setCamera(this);
}
- public void detach() {
+ public void detach(boolean captureControls) {
this.isAttachedToCameraman = false;
- this.captureControls();
+ if (captureControls) {
+ this.captureControls();
+ }
+ this.cameraman.setCamera(null);
}
/**
@@ -507,4 +699,38 @@ public class MatrixCamera {
return up;
}
+ @Override
+ public MatrixCamera getCamera() {
+ return attachedCamera;
+ }
+
+ @Override
+ public void setCamera(MatrixCamera camera) {
+ attachedCamera = camera;
+ }
+
+ @Override
+ public float getCameraX() {
+ return position.x;
+ }
+
+ @Override
+ public float getCameraY() {
+ return position.y - 2;// + look.y * 2;
+ }
+
+ @Override
+ public float getCameraZ() {
+ return position.z;// + look.z * 2;
+ }
+
+ @Override
+ public void update(float delta) {
+
+ }
+
+ public boolean isDirty() {
+ return isDirty;
+ }
+
}
diff --git a/src/ru/olamedia/data/BitCube.java b/src/ru/olamedia/data/BitCube.java
new file mode 100644
index 0000000..58252d3
--- /dev/null
+++ b/src/ru/olamedia/data/BitCube.java
@@ -0,0 +1,13 @@
+package ru.olamedia.data;
+
+import ru.olamedia.math.OpenBitSet;
+
+public class BitCube {
+ private int width = 16;
+ private int height = 16;
+ private int depth = 16;
+ private OpenBitSet data;
+ private int size = 1; // bit
+ // bit=0/1 count=0-15=4 bit
+ // 4096/8=512
+}
diff --git a/src/ru/olamedia/data/package-info.java b/src/ru/olamedia/data/package-info.java
new file mode 100644
index 0000000..e11738e
--- /dev/null
+++ b/src/ru/olamedia/data/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.data; \ No newline at end of file
diff --git a/src/ru/olamedia/game/GameFrame.java b/src/ru/olamedia/game/GameFrame.java
index 973fcb8..6227a15 100644
--- a/src/ru/olamedia/game/GameFrame.java
+++ b/src/ru/olamedia/game/GameFrame.java
@@ -4,8 +4,11 @@ import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Image;
import java.awt.Toolkit;
+import java.awt.event.KeyListener;
+import java.awt.im.InputContext;
import java.util.ArrayList;
import java.util.List;
+import java.util.Locale;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLProfile;
@@ -16,6 +19,7 @@ import ru.olamedia.asset.AssetNotFoundException;
import ru.olamedia.input.Keyboard;
import ru.olamedia.input.MouseJail;
import ru.olamedia.olacraft.OlaCraft;
+import ru.olamedia.olacraft.game.Game;
import jogamp.newt.awt.NewtFactoryAWT;
@@ -26,7 +30,6 @@ import com.jogamp.newt.event.KeyAdapter;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.util.Animator;
-import com.jogamp.opengl.util.FPSAnimator;
public class GameFrame {
// java.awt.SystemTray
@@ -54,8 +57,9 @@ public class GameFrame {
// ES2
caps = new GLCapabilities(glProfile);
caps.setHardwareAccelerated(true);
- caps.setDoubleBuffered(true);
- caps.setBackgroundOpaque(false);
+ caps.setDoubleBuffered(true); // hardware swap
+ caps.setBackgroundOpaque(true);
+ caps.setSampleBuffers(false);
display = NewtFactoryAWT.createDisplay(null);
screen = NewtFactoryAWT.createScreen(display, screenId);
@@ -63,15 +67,17 @@ public class GameFrame {
// caps);
newtCanvasAWT = new NewtCanvasAWT(glWindow);
glWindow.setUndecorated(false);
+ glWindow.setAutoSwapBufferMode(false);
glWindow.setPointerVisible(true);
glWindow.confinePointer(false);
glWindow.addWindowListener(new QuitAdapter());
animator = new Animator(glWindow);
- //animator = new FPSAnimator(glWindow, 60);
- //animator.setRunAsFastAsPossible(true); // By default there is a
- // brief
- // pause in the animation
- // loop
+ // animator.setUpdateFPSFrames(200, System.out);
+ // animator = new FPSAnimator(glWindow, 60);
+ animator.setRunAsFastAsPossible(true); // By default there is a
+ // brief
+ // pause in the animation
+ // loop
animator.start();
glWindow.addMouseListener(MouseJail.instance);
glWindow.addKeyListener(Keyboard.instance);
@@ -84,8 +90,14 @@ public class GameFrame {
glWindow.setPointerVisible(true);
}
}
+
+ @Override
+ public void keyPressed(KeyEvent e) {
+ super.keyPressed(e);
+ System.out.println(e.toString());
+ }
});
- // animator.setUpdateFPSFrames(100, System.err);
+ //animator.setUpdateFPSFrames(1000, System.err);
jFrame.add(newtCanvasAWT);
glWindow.addGLEventListener(GameManager.instance);
}
@@ -121,6 +133,14 @@ public class GameFrame {
return glWindow.getWidth();
}
+ public static int getGLWidth() {
+ return Game.Display.getWidth();
+ }
+
+ public static int getGLHeight() {
+ return Game.Display.getHeight();
+ }
+
public static int getHeight() {
if (null == glWindow) {
return jFrame.getHeight();
@@ -130,6 +150,7 @@ public class GameFrame {
public GameFrame() {
instance = this;
+ // en.selectInputMethod(Locale.ENGLISH);
jFrame = new JFrame();
jFrame.setMinimumSize(new Dimension(200, 200));
jFrame.setSize(width, height);
@@ -139,6 +160,7 @@ public class GameFrame {
// glWindow.setLocation(100, 100);
jFrame.addWindowListener(new QuitAdapter());
jFrame.setVisible(true);
+
}
private void setIcons() {
diff --git a/src/ru/olamedia/game/GameLogicThread.java b/src/ru/olamedia/game/GameLogicThread.java
new file mode 100644
index 0000000..ec95aee
--- /dev/null
+++ b/src/ru/olamedia/game/GameLogicThread.java
@@ -0,0 +1,76 @@
+package ru.olamedia.game;
+
+import java.util.Random;
+
+import ru.olamedia.olacraft.game.Game;
+import ru.olamedia.olacraft.game.Timer;
+import ru.olamedia.olacraft.scene.GameScene;
+import ru.olamedia.olacraft.world.chunk.ChunkUnavailableException;
+
+public class GameLogicThread extends Thread {
+ public static GameLogicThread instance = new GameLogicThread("Game logic");
+ private Timer fpsTimer = new Timer();
+
+ public GameLogicThread(String name) {
+ super(name);
+
+ }
+
+ private Random rand = new Random();
+
+ @Override
+ public synchronized void start() {
+ super.start();
+ fpsTimer.initialize();
+ fpsTimer.update();
+ }
+
+ private float delta;
+
+ private void tick() {
+ fpsTimer.update();
+ delta = (float) fpsTimer.getElapsedTime() / 1000f;
+ if (rand.nextFloat() > 0.95f) {
+ Game.client.getScene().dayTime.tick();
+ }
+ // bullets.update(Game.instance.getDelta());
+ // physics.getWorld().step(Game.instance.getDelta());
+ if (Game.client.getScene().isInitialized && null != Game.client.getScene().player) {
+ Game.client.getScene().player.camera.setAspect(Game.Display.getAspect());
+ try {
+ Game.client.getScene().player.updateKeyboard(delta);
+ } catch (ChunkUnavailableException e) {
+ e.printStackTrace();
+ }
+ if (Game.client.getScene().player.isOrientationChanged || Game.instance.camera.isOrientationChanged) {
+ Game.client.getScene().player.isOrientationChanged = false;
+ Game.instance.camera.isOrientationChanged = false;
+ updateNearestBlock();
+ }
+ }
+ }
+
+ private void updateNearestBlock() {
+ final GameScene scene = Game.client.getScene();
+ if (null != scene.player && null != scene.pickSlice) {
+ scene.pickSlice.setCenter(scene.player.getCameraX(), scene.player.getCameraY(), scene.player.getCameraZ());
+ scene.nearestBlock = scene.pickSlice.getNearest(Game.instance.camera);
+ scene.nearestPutBlock = scene.pickSlice.getNearestPutBlock();
+ }
+ }
+
+ @Override
+ public void run() {
+ while (true) {
+ try {
+ tick();
+ Thread.sleep(50);
+ // 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/game/GameManager.java b/src/ru/olamedia/game/GameManager.java
index 7118c85..7e1ed71 100644
--- a/src/ru/olamedia/game/GameManager.java
+++ b/src/ru/olamedia/game/GameManager.java
@@ -1,27 +1,25 @@
package ru.olamedia.game;
-import java.nio.FloatBuffer;
+import java.awt.event.KeyListener;
import java.util.Set;
import javax.media.opengl.GL;
-import javax.media.opengl.GL2;
import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL3;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
-import javax.media.opengl.GLUniformData;
-import javax.media.opengl.fixedfunc.GLMatrixFunc;
-import javax.media.opengl.glu.GLU;
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.olacraft.world.blockRenderer.ChunkMeshGarbageCollector;
+import ru.olamedia.olacraft.world.chunk.Chunk;
import ru.olamedia.olacraft.world.chunk.ChunkMeshBulder;
import ru.olamedia.olacraft.world.location.BlockLocation;
import ru.olamedia.tasks.TaskManager;
import com.jogamp.opengl.JoglVersion;
-import com.jogamp.opengl.util.PMVMatrix;
public class GameManager implements GLEventListener {
public static GameManager instance;
@@ -36,34 +34,79 @@ public class GameManager implements GLEventListener {
tests();
}
+ private void assertBoolean(boolean val) {
+ if (!val) {
+ throw new RuntimeException("Assert failed");
+ }
+ }
+
private void tests() {
+ System.out.println("====TESTS====");
+ // Game.client.getWorldProvider().loadChunk(new ChunkLocation());
+ // Game.client.getWorldProvider().loadChunk(new ChunkLocation(-1,0,0));
+ // Game.client.getWorldProvider().loadChunk(new ChunkLocation(0,0,-1));
+ // Game.client.getWorldProvider().loadChunk(new ChunkLocation(-1,0,-1));
BlockLocation b;
b = new BlockLocation(0, 0, 0);
- assert b.getChunkLocation().x == 0;
- assert b.getChunkLocation().getBlockLocation().x == 0;
+ assertBoolean(b.getChunkLocation().x == 0);
+ assertBoolean(b.getChunkLocation().getBlockLocation().x == 0);
b = new BlockLocation(14, 0, 0);
- assert b.getChunkLocation().x == 0;
- assert b.getChunkLocation().getBlockLocation().x == 0;
+ assertBoolean(b.getChunkLocation().x == 0);
+ assertBoolean(b.getChunkLocation().getBlockLocation().x == 0);
b = new BlockLocation(15, 0, 0);
- assert b.getChunkLocation().x == 0;
- assert b.getChunkLocation().getBlockLocation().x == 0;
+ assertBoolean(b.getChunkLocation().x == 0);
+ assertBoolean(b.getChunkLocation().getBlockLocation().x == 0);
b = new BlockLocation(16, 0, 0);
- assert b.getChunkLocation().x == 1;
- assert b.getChunkLocation().getBlockLocation().x == 0;
+ assertBoolean(b.getChunkLocation().x == 1);
+ assertBoolean(b.getChunkX() == Chunk.v(b.x));
+ assertBoolean(b.getChunkY() == Chunk.v(b.y + 128));
+ assertBoolean(b.getChunkZ() == Chunk.v(b.z));
+ // failed assertBoolean(b.getChunkLocation().getBlockLocation().x == 0);
b = new BlockLocation(-1, 0, 0);
- assert b.getChunkLocation().x == -1;
- assert b.getChunkLocation().getBlockLocation().x == -1;
+ assertBoolean(b.getChunkLocation().x == -1);
+ assertBoolean(b.getChunkX() == Chunk.v(b.x));
+ assertBoolean(b.getChunkY() == Chunk.v(b.y + 128));
+ assertBoolean(b.getChunkZ() == Chunk.v(b.z));
+ // failed assertBoolean(b.getChunkLocation().getBlockLocation().x ==
+ // -1);
b = new BlockLocation(-14, 0, 0);
- assert b.getChunkLocation().x == -1;
+ assertBoolean(b.getChunkLocation().x == -1);
+ assertBoolean(b.getChunkX() == Chunk.v(b.x));
+ assertBoolean(b.getChunkY() == Chunk.v(b.y + 128));
+ assertBoolean(b.getChunkZ() == Chunk.v(b.z));
b = new BlockLocation(-15, 0, 0);
- assert b.getChunkLocation().x == -1;
- assert b.getChunkLocation().getBlockLocation().x == -1;
+ assertBoolean(b.getChunkLocation().x == -1);
+ assertBoolean(b.getChunkX() == Chunk.v(b.x));
+ assertBoolean(b.getChunkY() == Chunk.v(b.y + 128));
+ assertBoolean(b.getChunkZ() == Chunk.v(b.z));
+ // failed assertBoolean(b.getChunkLocation().getBlockLocation().x ==
+ // -1);
b = new BlockLocation(-16, 0, 0);
- assert b.getChunkLocation().x == -1;
- assert b.getChunkLocation().getBlockLocation().x == -1;
+ assertBoolean(b.getChunkLocation().x == -1);
+ // failed assertBoolean(b.getChunkLocation().getBlockLocation().x ==
+ // -1);
+
+ assertBoolean(b.getByteX() == 0);
+ assertBoolean(b.getByteY() == 0);
+ assertBoolean(b.getByteZ() == 0);
+ assertBoolean(b.getChunkX() == Chunk.v(b.x));
+ assertBoolean(b.getChunkY() == Chunk.v(b.y + 128));
+ assertBoolean(b.getChunkZ() == Chunk.v(b.z));
b = new BlockLocation(-17, 0, 0);
- assert b.getChunkLocation().x == -2;
- assert b.getChunkLocation().getBlockLocation().x == -17;
+ assertBoolean(b.getChunkLocation().x == -2);
+ // assertBoolean(b.getChunkLocation().getBlockLocation().x == -17);
+ assertBoolean(b.getByteX() == 15);
+ assertBoolean(b.getByteY() == 0);
+ assertBoolean(b.getByteZ() == 0);
+ int id = Chunk.in(b.x) * 16 * 16 + Chunk.in(b.y) * 16 + Chunk.in(b.z);
+ System.out.print(b.getChunkX() + "/" + Chunk.v(b.x));
+ assertBoolean(b.getId() == id);
+ assertBoolean(b.getChunkX() == Chunk.v(b.x));
+ assertBoolean(b.getChunkY() == Chunk.v(b.y + 128));
+ assertBoolean(b.getChunkZ() == Chunk.v(b.z));
+ // ChunkData data = new ChunkData();
+ // data.setVoidLight(18, (byte) 6);
+ // assert data.getVoidLight(18) == 6;
}
private void createServerGame() {
@@ -114,11 +157,31 @@ public class GameManager implements GLEventListener {
menu = new MainMenu();
this.renderer = new DefaultRenderer();
GameFrame.getFrame().getContentPane().add(menu);
- menu.setVisible(true);
- GameFrame.getFrame().validate();
+ GameFrame.getFrame().getContentPane().repaint();
+ GameFrame.getFrame().addKeyListener(new KeyListener() {
+ @Override
+ public void keyTyped(java.awt.event.KeyEvent e) {
+ System.out.println(e.toString());
+ }
+ @Override
+ public void keyReleased(java.awt.event.KeyEvent e) {
+ System.out.println(e.toString());
+ }
+
+ @Override
+ public void keyPressed(java.awt.event.KeyEvent e) {
+ System.out.println(e.toString());
+ }
+ });
+ // GameFrame.getFrame().getContentPane().validate();
+ // GameFrame.getFrame().validate();
+ // GameFrame.getFrame().getContentPane().paintComponents(GameFrame.getFrame().getContentPane().getGraphics());
+ // GameFrame.getFrame().validate();
+ // menu.setVisible(true);
+ // GameFrame.getFrame().setVisible(true);
}
- private PMVMatrix m;
+
private void glTest(GLAutoDrawable drawable) {
// m = new PMVMatrix(true);
// m.glGetMviMatrixf();
@@ -157,7 +220,7 @@ public class GameManager implements GLEventListener {
// for (int i = 0; i < 16; i++) {
// System.out.println(pmv.get(i) + " == " + glmv.get(i));
// }
- // System.exit(0);
+ // System.exit(0);
}
public void start() {
@@ -188,6 +251,12 @@ public class GameManager implements GLEventListener {
if (ChunkMeshBulder.instance.isAlive()) {
ChunkMeshBulder.instance.interrupt();
}
+ if (GameLogicThread.instance.isAlive()) {
+ GameLogicThread.instance.interrupt();
+ }
+ if (ChunkMeshGarbageCollector.instance.isAlive()) {
+ ChunkMeshGarbageCollector.instance.interrupt();
+ }
// Get all threads
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
for (Thread t : threadSet) {
@@ -204,6 +273,8 @@ public class GameManager implements GLEventListener {
public void init(GLAutoDrawable drawable) {
// GLContext.getContext().getGL()
GL2ES2 gl = drawable.getGL().getGL2ES2();
+ drawable.setAutoSwapBufferMode(false);
+ gl.setSwapInterval(0);
// drawable.setGL(new DebugGL2ES2(gl));
System.err.println(JoglVersion.getGLInfo(drawable.getGL(), null));
System.err.println(Thread.currentThread() + " Chosen GLCapabilities: " + drawable.getChosenGLCapabilities());
@@ -226,16 +297,28 @@ public class GameManager implements GLEventListener {
@Override
public void display(GLAutoDrawable drawable) {
- GL2ES2 gl = drawable.getGL().getGL2ES2();
- gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ final GL3 gl = drawable.getGL().getGL3();
+ // gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
// gl.glClearColor(0.2f, 0.2f, 0.2f, 1);
renderer.render(drawable);
+ // Different GL implementations buffer commands in several different
+ // locations, including network buffers and the graphics accelerator
+ // itself. glFlush empties all of these buffers, causing all issued
+ // commands to be executed as quickly as they are accepted by the actual
+ // rendering engine. Though this execution may not be completed in any
+ // particular time period, it does complete in finite time.
+ //gl.glF
+ //gl.glFlush();
+ //gl.glFinish();
+ //gl.glFlush();
+ drawable.swapBuffers();
}
@Override
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
- GL gl = drawable.getGL().getGL2ES2();
+ final GL gl = drawable.getGL().getGL2ES2();
gl.glViewport(0, 0, width, height);
+ renderer.reshape(drawable);
}
public void showMainMenu() {
diff --git a/src/ru/olamedia/game/GameTime.java b/src/ru/olamedia/game/GameTime.java
index bd687d9..1d243ad 100644
--- a/src/ru/olamedia/game/GameTime.java
+++ b/src/ru/olamedia/game/GameTime.java
@@ -1,5 +1,6 @@
package ru.olamedia.game;
+import java.nio.FloatBuffer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
@@ -8,6 +9,8 @@ import java.util.TimeZone;
import ru.olamedia.astronomy.SunCalendar;
public class GameTime {
+ public FloatBuffer sunColor = FloatBuffer.allocate(4);
+
public static class SunCalc {
private GameTime time;
private int r = 450;
@@ -94,63 +97,46 @@ public class GameTime {
return new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(new Date((long) (gameTime * 1000)));
}
- private static float addComponent(float a, float b) {
- return a + b;
- }
+ private final float[] spaceColors = new float[] { 0.03f, 0.03f, 0.05f };
+ private final float[] sunSkyColors = new float[] { (float) 203 / 255, (float) 233 / 255, (float) 244 / 255 };
+ private final float[] sunRedColorsAdd = new float[] { 0.3f, 0.1f, 0.0f };
+ private final float sunAngularDiameter = 32;
+ private final float sunRenderDistance = 700;
+ private final float sunRenderDiameter = (float) ((float) 2 * sunRenderDistance * Math.tan(sunAngularDiameter / 2)) / 15f;
- private static float mulComponent(float a, float b) {
- return a * b;
+ public float[] getClearColor() {
+ return clearColors;
}
- public float[] getClearColor() {
- float sunAngularDiameter = 32;
- float sunRenderDistance = 700;
- @SuppressWarnings("unused")
- float sunRenderDiameter = (float) ((float) 2 * sunRenderDistance * Math.tan(sunAngularDiameter / 2));
+ public float[] updateClearColor() {
- sunRenderDiameter /= 15;
+ // a little
+ // blue
- float[] spaceColors = new float[] { 0.03f, 0.03f, 0.05f }; // a little
- // blue
+ clearColors[0] = 0;
+ clearColors[1] = 0;
+ clearColors[2] = 0;
- clearColors = new float[] { 0.0f, 0.0f, 0.0f };
+ final double crossAngle = sunCalendar.getHourAngle();
- double crossAngle = sunCalendar.getHourAngle();
- @SuppressWarnings("unused")
- int elevationAngle = (int) sunCalendar.radToDeg(sunCalendar.getElevationAngle());
+ final float minSunlightFactor = 0.2097152f;
+ final float maxSunlightFactor = (1f - minSunlightFactor);
+ sunlightFactor = minSunlightFactor;
- sunlightFactor = 0f;
if ((crossAngle > -120 && crossAngle < -70) || (crossAngle > 70 && crossAngle < 120)) {
- sunlightFactor = (float) 1f - (Math.abs(crossAngle) - 70) / 50;
+ sunlightFactor = minSunlightFactor + maxSunlightFactor * ((float) 1f - (Math.abs(crossAngle) - 70) / 50);
}
if (crossAngle >= -70 && crossAngle <= 70) {
sunlightFactor = (float) 1f;
}
- int sunlight = (int) Math.round(15 * sunlightFactor);
- if (sunlight != lastSunLight) {
- spaceLightIsInvalid = true;
- receivedLightIsInvalid = true;
- }
- //float[] sunSkyColors = new float[] { (float) 179 / 255, (float) 195 / 255, (float) 184 / 255 };
- //float[] sunSkyColors = new float[] { (float) 209 / 255, (float) 227 / 255, (float) 251 / 255 };
- float[] sunSkyColors = new float[] { (float) 203 / 255, (float) 233 / 255, (float) 244 / 255 };
- for (int i = 0; i < 3; i++) {
- clearColors[i] = addComponent(sunSkyColors[i] * (float) sunlightFactor, spaceColors[i]);
- }
- float lightness = clearColors[0] + clearColors[1] + clearColors[2];
- float[] sunRedColorsAdd = new float[] { 0.3f, 0.1f, 0.0f };
- for (int i = 0; i < 3; i++) {
- if (sunlightFactor < 0.5f && sunlightFactor > 0.0f) {
- float redFactor = (float) (1 - Math.abs(1 - sunlightFactor * 4));
- clearColors[i] = addComponent(clearColors[i], (float) sunRedColorsAdd[i] * redFactor);
- }
- clearColors[i] = mulComponent(clearColors[i], (float) sunlightFactor);
- }
- // fix lightness
- float newLightness = clearColors[0] + clearColors[1] + clearColors[2];
+
for (int i = 0; i < 3; i++) {
- clearColors[i] = clearColors[i] * lightness / newLightness;
+ clearColors[i] = (float) (sunSkyColors[i] * sunlightFactor + spaceColors[i] * (1 - sunlightFactor));
}
+ sunColor.position(0);
+ sunColor.put(clearColors);
+ sunColor.put(3, 1f);
+ sunColor.position(0);
return clearColors;
}
@@ -166,6 +152,7 @@ public class GameTime {
// noon
sunEA = Math.floor(sunCalendar.getElevationAngle() * 1000) / 1000;
sunTC = Math.floor(sunCalendar.getTimeCorrectionFactor() * 1000) / 1000;
+ updateClearColor();
}
}
diff --git a/src/ru/olamedia/game/Launcher.java b/src/ru/olamedia/game/Launcher.java
index 7849468..c7ceca0 100644
--- a/src/ru/olamedia/game/Launcher.java
+++ b/src/ru/olamedia/game/Launcher.java
@@ -5,11 +5,13 @@ public class Launcher {
public Launcher() {
}
+ private static GameManager manager;
+
/**
* @param args
*/
public static void main(String[] args) {
- GameManager manager = new GameManager();
+ manager = new GameManager();
manager.start();
manager.dispose();
}
diff --git a/src/ru/olamedia/geom/ChunkMesh.java b/src/ru/olamedia/geom/ChunkMesh.java
new file mode 100644
index 0000000..3ff36df
--- /dev/null
+++ b/src/ru/olamedia/geom/ChunkMesh.java
@@ -0,0 +1,83 @@
+package ru.olamedia.geom;
+
+import ru.olamedia.olacraft.render.jogl.ChunkRangeRenderer;
+
+public class ChunkMesh {
+ private ImmModeMesh opaqueMesh;
+ private ImmModeMesh mesh;
+ private boolean isCompiled = false;
+ private boolean isValid = false;
+ private int vertexCount = 0;
+
+ private void updateVertexCount() {
+ vertexCount = 0;
+ if (null != mesh) {
+ vertexCount += mesh.getVertexCount();
+ }
+ if (null != opaqueMesh) {
+ vertexCount += opaqueMesh.getVertexCount();
+ }
+ }
+
+ public int getVertexCount() {
+ return vertexCount;
+ }
+
+ public void setMesh(ImmModeMesh m) {
+ mesh = m;
+ updateVertexCount();
+ }
+
+ public void setOpaqueMesh(ImmModeMesh m) {
+ opaqueMesh = m;
+ updateVertexCount();
+ }
+
+ public void render(int pass) {
+ if (pass == ChunkRangeRenderer.OPAQUE_PASS) {
+ if (null != opaqueMesh) {
+ opaqueMesh.draw();
+ }
+ } else {
+ if (null != mesh) {
+ mesh.draw();
+ }
+ }
+ }
+
+ public boolean isCompiled() {
+ return isCompiled;
+ }
+
+ public void setCompiled(boolean isCompiled) {
+ this.isCompiled = isCompiled;
+ }
+
+ public boolean isValid() {
+ return isValid;
+ }
+
+ public void setValid(boolean isValid) {
+ this.isValid = isValid;
+ }
+
+ public boolean isEmpty() {
+ return isValid() && (null == mesh) && (null == opaqueMesh);
+ }
+
+ public ImmModeMesh getTransparentMesh() {
+ return mesh;
+ }
+
+ public ImmModeMesh getOpaqueMesh() {
+ return opaqueMesh;
+ }
+
+ public int getOpaqueVertexCount() {
+ return null == opaqueMesh ? 0 : opaqueMesh.getVertexCount();
+ }
+
+ public int getTransparentVertexCount() {
+ return null == mesh ? 0 : mesh.getVertexCount();
+ }
+}
diff --git a/src/ru/olamedia/geom/ChunkMeshNode.java b/src/ru/olamedia/geom/ChunkMeshNode.java
new file mode 100644
index 0000000..f0593f3
--- /dev/null
+++ b/src/ru/olamedia/geom/ChunkMeshNode.java
@@ -0,0 +1,97 @@
+package ru.olamedia.geom;
+
+public class ChunkMeshNode {
+ private ChunkMesh mesh = new ChunkMesh();
+ private ChunkMesh[] leafs = new ChunkMesh[8];
+ private int vertexCount = 0;
+ private int opaqueVertexCount = 0;
+ private int transparentVertexCount = 0;
+ private int level = 1;
+ private int axisChunks = 2;
+ private int axisShift = 1;
+ private int volumeChunks = 8;
+
+ public ChunkMeshNode(int level) {
+ this.level = level;
+ this.axisChunks = (int) Math.pow(2, level);
+ this.axisShift = level;
+ this.volumeChunks = (int) Math.pow(8, level);
+ }
+
+ public void putChunkMesh(int chunkX, int chunkY, int chunkZ, ChunkMesh mesh) {
+ // id = 0..7
+ // final int id = (chunkX & )*4 + ()*2+(chunkZ & );
+ }
+
+ private void updateVertexCount() {
+ if (!mesh.isValid()) {
+ vertexCount = 0;
+ opaqueVertexCount = 0;
+ transparentVertexCount = 0;
+ for (ChunkMesh m : leafs) {
+ if (null != m) {
+ vertexCount += m.getVertexCount();
+ opaqueVertexCount += m.getOpaqueVertexCount();
+ transparentVertexCount += m.getTransparentVertexCount();
+ }
+ }
+ }
+ }
+
+ public int getVertexCount() {
+ return vertexCount;
+ }
+
+ public void render(int pass) {
+ if (mesh.isValid()) {
+ mesh.render(pass);
+ } else {
+ for (ChunkMesh m : leafs) {
+ if (null != m) {
+ m.render(pass);
+ }
+ }
+ }
+ }
+
+ public void combine() {
+ updateVertexCount();
+ if (!mesh.isValid()) {
+ if (transparentVertexCount > 0) {
+ final ImmModeMesh tMesh = ImmModeMesh.allocate(transparentVertexCount);
+ tMesh.setGLSL(true);
+ tMesh.enableColor4();
+ tMesh.enableTexCoord2();
+ tMesh.enableVertex3();
+ tMesh.beginQuads();
+ for (ChunkMesh m : leafs) {
+ if (null != m) {
+ tMesh.put(m.getTransparentMesh());
+ }
+ }
+ tMesh.end();
+ mesh.setMesh(tMesh);
+ } else {
+ mesh.setMesh(null);
+ }
+ if (opaqueVertexCount > 0) {
+ final ImmModeMesh oMesh = ImmModeMesh.allocate(opaqueVertexCount);
+ oMesh.setGLSL(true);
+ oMesh.enableColor4();
+ oMesh.enableTexCoord2();
+ oMesh.enableVertex3();
+ oMesh.beginQuads();
+ for (ChunkMesh m : leafs) {
+ if (null != m) {
+ oMesh.put(m.getOpaqueMesh());
+ }
+ }
+ oMesh.end();
+ mesh.setOpaqueMesh(oMesh);
+ } else {
+ mesh.setOpaqueMesh(null);
+ }
+ mesh.setValid(true);
+ }
+ }
+}
diff --git a/src/ru/olamedia/geom/ChunkMeshOctree.java b/src/ru/olamedia/geom/ChunkMeshOctree.java
new file mode 100644
index 0000000..1c5202c
--- /dev/null
+++ b/src/ru/olamedia/geom/ChunkMeshOctree.java
@@ -0,0 +1,95 @@
+package ru.olamedia.geom;
+
+import java.util.HashMap;
+
+import ru.olamedia.olacraft.game.Game;
+
+public class ChunkMeshOctree {
+ private HashMap<Integer, HashMap<Integer, HashMap<Integer, ChunkMeshNode>>> nodes = new HashMap<Integer, HashMap<Integer, HashMap<Integer, ChunkMeshNode>>>();
+ private static int level = 2;
+ private static int nodeAxisChunks = 4;
+ private static int nodeChunks = 64;
+ private static int levelp = 4;
+
+ private int getRenderDistance() {
+ return Game.instance.player.settings.renderDistance;
+ }
+
+ private int getCameraX() {
+ return (int) Game.instance.player.camera.getCameraX();
+ }
+
+ private int getCameraY() {
+ return (int) Game.instance.player.camera.getCameraY();
+ }
+
+ private int getCameraZ() {
+ return (int) Game.instance.player.camera.getCameraZ();
+ }
+
+ public void render(int pass) {
+ final int startX = getCameraX() - getRenderDistance() / 2;
+ final int startY = getCameraY() - getRenderDistance() / 2;
+ final int startZ = getCameraZ() - getRenderDistance() / 2;
+ final int deltaChunks = getRenderDistance() / 16;
+ // renderDistance = 256, deltaChunks = 16
+ // renderDistance = 128, deltaChunks = 8
+ // renderDistance = 64, deltaChunks = 4
+ // renderDistance = 32, deltaChunks = 2
+ // level = 1: 1 parent quadtree node (32x32x32), each root node = 8
+ // chunks
+ // level = 2: 2 parent quadtree nodes (64x64x64), each root node = 64
+ // chunks
+ final int chunkStartX = (startX / 16) / nodeAxisChunks;
+ final int chunkStartY = (startY / 16) / nodeAxisChunks;
+ final int chunkStartZ = (startZ / 16) / nodeAxisChunks;
+ for (int ix = chunkStartX; ix < nodeAxisChunks; ix++) {
+ for (int iy = chunkStartY; iy < nodeAxisChunks; iy++) {
+ for (int iz = chunkStartZ; iz < nodeAxisChunks; iz++) {
+ renderNode(ix, iy, iz, pass);
+ }
+ }
+ }
+ }
+
+ private void renderNode(int ix, int iy, int iz, int pass) {
+ if (!nodes.containsKey(ix)) {
+ return;
+ }
+ if (!nodes.get(ix).containsKey(iy)) {
+ return;
+ }
+ if (!nodes.get(ix).get(iy).containsKey(iz)) {
+ return;
+ }
+ nodes.get(ix).get(iy).get(iz).render(pass);
+ }
+
+ public void render(int x, int y, int z, int pass) {
+ final int ix = x >> 2;
+ final int iy = y >> 2;
+ final int iz = z >> 2;
+ if (!nodes.containsKey(ix)) {
+ nodes.put(ix, new HashMap<Integer, HashMap<Integer, ChunkMeshNode>>());
+ nodes.get(ix).put(iy, new HashMap<Integer, ChunkMeshNode>());
+ // nodes.get(ix).get(iy).put(iz, new ChunkMeshNode());
+ }
+ }
+
+ public void put(int chunkX, int chunkY, int chunkZ, ChunkMesh mesh) {
+ final int ix = chunkX / nodeAxisChunks;
+ final int iy = chunkY / nodeAxisChunks;
+ final int iz = chunkZ / nodeAxisChunks;
+ final int id = (chunkX & 64) * +(chunkY & 64) * +(chunkZ & 64);
+ if (!nodes.containsKey(ix)) {
+ nodes.put(ix, new HashMap<Integer, HashMap<Integer, ChunkMeshNode>>());
+ }
+ if (!nodes.get(ix).containsKey(iy)) {
+ nodes.get(ix).put(iy, new HashMap<Integer, ChunkMeshNode>());
+ }
+ if (!nodes.get(ix).get(iy).containsKey(iz)) {
+ nodes.get(ix).get(iy).put(iz, new ChunkMeshNode(level));
+ }
+ nodes.get(ix).get(iy).get(iz).combine();
+ }
+}
diff --git a/src/ru/olamedia/geom/DisplayList.java b/src/ru/olamedia/geom/DisplayList.java
index aeaffc7..eb6cf04 100644
--- a/src/ru/olamedia/geom/DisplayList.java
+++ b/src/ru/olamedia/geom/DisplayList.java
@@ -2,7 +2,6 @@ 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;
diff --git a/src/ru/olamedia/geom/Frustum.java b/src/ru/olamedia/geom/Frustum.java
index 2065157..1a9d58d 100644
--- a/src/ru/olamedia/geom/Frustum.java
+++ b/src/ru/olamedia/geom/Frustum.java
@@ -1,9 +1,43 @@
package ru.olamedia.geom;
+import java.nio.FloatBuffer;
+
+import org.openmali.vecmath2.Matrix4f;
+
+import com.jogamp.opengl.util.PMVMatrix;
+
//import org.openmali.spatial.bodies.Frustum;
public class Frustum extends org.openmali.spatial.bodies.Frustum {
+ protected PMVMatrix pmvMatrix;
+ protected int mvOffset;
+
public Frustum() {
super();
}
+
+ public Frustum(PMVMatrix matrix) {
+ super();
+ this.pmvMatrix = matrix;
+ }
+
+ public float[] getMatrixFloat(FloatBuffer b) {
+ if (pmvMatrix.usesBackingArray()) {
+ return b.array();
+ } else {
+ int p = b.position();
+ float[] pm = new float[16];
+ b.get(pm, p, 16);
+ b.position(p);
+ return pm;
+ }
+ }
+
+ public void compute() {
+ Matrix4f proj = new Matrix4f(getMatrixFloat(pmvMatrix.glGetPMatrixf()));
+ // proj.transpose();
+ Matrix4f modl = new Matrix4f(getMatrixFloat(pmvMatrix.glGetMviMatrixf()));
+ // modl.transpose();
+ compute(proj, modl);
+ }
}
diff --git a/src/ru/olamedia/geom/Frustum2.java b/src/ru/olamedia/geom/Frustum2.java
new file mode 100644
index 0000000..9c382b0
--- /dev/null
+++ b/src/ru/olamedia/geom/Frustum2.java
@@ -0,0 +1,282 @@
+package ru.olamedia.geom;
+
+import java.nio.FloatBuffer;
+
+import org.ode4j.ode.internal.gimpact.GimGeometry.aabb3f;
+import org.openmali.spatial.bodies.Box;
+import org.openmali.spatial.bodies.Classifier;
+import org.openmali.vecmath2.Matrix4f;
+
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.math.geom.AABBox;
+import com.jogamp.opengl.util.PMVMatrix;
+
+public class Frustum2 {
+ protected Plane[] planes = new Plane[6];
+ protected PMVMatrix pmvMatrix;
+ protected FloatBuffer pmv = FloatBuffer.allocate(16);
+ protected float[] mvp = new float[16];
+ protected int pmvOffset;
+
+ public Frustum2() {
+ for (int i = 0; i < 6; ++i) {
+ planes[i] = new Plane();
+ }
+ }
+
+ public Frustum2(PMVMatrix matrix) {
+ setMatrix(matrix);
+ for (int i = 0; i < 6; ++i) {
+ planes[i] = new Plane();
+ }
+ }
+
+ public void setMatrix(PMVMatrix matrix) {
+ this.pmvMatrix = matrix;
+ // pmv = pmvMatrix.glGetPMvMatrixf();
+ // pmvOffset = pmv.position();
+ makePmvMatrix();
+ }
+
+ protected Matrix4f proj;
+ protected Matrix4f modl;
+
+ private static FloatBuffer b;
+ private static int bOffset;
+
+ private static float f(int offset) {
+ return b.get(bOffset + offset);
+ }
+
+ public static Matrix4f getMatrix4f(FloatBuffer buf) {
+ b = buf;
+ bOffset = b.position();
+ return new Matrix4f(f(0), f(1), f(2), f(3), f(4), f(5), f(6)/* 12 */, f(7), f(8), f(9), f(10), f(11), f(12),
+ f(13), f(14), f(15));
+ }
+
+ public void makePmvMatrix() {
+ FloatUtil.multMatrixf(pmvMatrix.glGetPMatrixf(), pmvMatrix.glGetMvMatrixf(), mvp, 0);
+ getMatrix4f(pmvMatrix.glGetPMatrixf()).mul(getMatrix4f(pmvMatrix.glGetMvMatrixf())).writeToBuffer(pmv, true,
+ false);
+ }
+
+ protected class Vector3f {
+ public float x;
+ public float y;
+ public float z;
+
+ @Override
+ public String toString() {
+ return "{" + x + "," + y + "," + z + "}";
+ }
+ }
+
+ protected class Plane {
+ public Vector3f n = new Vector3f();
+ public float d;
+
+ public final float distanceTo(float x, float y, float z) {
+ return (n.x * x) + (n.y * y) + (n.z * z) + d;
+ }
+
+ @Override
+ public String toString() {
+ return "Plane[" + n + ", " + d + "]";
+ }
+ }
+
+ protected float[] getMatrixFloat(FloatBuffer b) {
+ if (pmvMatrix.usesBackingArray()) {
+ return b.array();
+ } else {
+ int p = b.position();
+ float[] pm = new float[16];
+ b.get(pm, p, 16);
+ b.position(p);
+ return pm;
+ }
+ }
+
+ protected float m(int a) {
+ return mvp[a];
+ // return pmv.get(a);
+ }
+
+ private static final boolean isInside(Plane p, AABBox box) {
+ final float[] low = box.getLow();
+ final float[] high = box.getHigh();
+ if (p.distanceTo(low[0], low[1], low[2]) > 0.0f)
+ return (true);
+ if (p.distanceTo(high[0], low[1], low[2]) > 0.0f)
+ return (true);
+ if (p.distanceTo(low[0], high[1], low[2]) > 0.0f)
+ return (true);
+ if (p.distanceTo(high[0], high[1], low[2]) > 0.0f)
+ return (true);
+ if (p.distanceTo(low[0], low[1], high[2]) > 0.0f)
+ return (true);
+ if (p.distanceTo(high[0], low[1], high[2]) > 0.0f)
+ return (true);
+ if (p.distanceTo(low[0], high[1], high[2]) > 0.0f)
+ return (true);
+ if (p.distanceTo(high[0], high[1], high[2]) > 0.0f)
+ return (true);
+
+ return (false);
+ }
+
+ /**
+ * Quick check to see if an orthogonal bounding box is inside the frustum
+ */
+ public final boolean isOutside(AABBox box) {
+
+ // if all points are behind 1 specific plane, we are out
+ // if we are in with all points, then we are fully in
+ for (int p = 0; p < 6; ++p) {
+ if (!isInside(planes[p], box)) {
+ return true;
+ }
+ }
+
+ // so if iTotalIn is 6, then all are inside the view
+ // if(iTotalIn == 6)
+ // return(IN);
+
+ // we must be partly in then otherwise
+ return false;
+ // for (int i = 0; i < 3; ++i) {
+ // if (!quickClassify(planes[i], box))
+ // return true;
+ // }
+ //
+ // // We make no attempt to determine whether it's fully inside or not.
+ // return false;
+ }
+
+ protected float[] mat = new float[16];
+
+ public void extractFrustumPlanes(boolean normalize) {
+ // Left: [30+00, 31+01, 32+02, 33+03]
+ // comboMatrix.m[12] + comboMatrix.m[0];
+
+ planes[0].n.x = m(12) + m(0);
+ planes[0].n.y = m(13) + m(1);
+ planes[0].n.z = m(14) + m(2);
+ planes[0].d = m(15) + m(3);
+
+ // Right: [30-00, 31-01, 32-02, 33-03]
+
+ planes[1].n.x = m(12) - m(0);
+ planes[1].n.y = m(13) - m(1);
+ planes[1].n.z = m(14) - m(2);
+ planes[1].d = m(15) - m(3);
+
+ // Bottom: [30+10, 31+11, 32+12, 33+13]
+
+ planes[2].n.x = m(12) + m(4);
+ planes[2].n.y = m(13) + m(5);
+ planes[2].n.z = m(14) + m(6);
+ planes[2].d = m(15) + m(7);
+
+ // Top: [30-10, 31-11, 32-12, 33-13]
+
+ planes[3].n.x = m(12) - m(4);
+ planes[3].n.y = m(13) - m(5);
+ planes[3].n.z = m(14) - m(6);
+ planes[3].d = m(15) - m(7);
+
+ // Far: [30-20, 31-21, 32-22, 33-23]
+
+ planes[5].n.x = m(12) - m(8);
+ planes[5].n.y = m(13) - m(9);
+ planes[5].n.z = m(14) - m(10);
+ planes[5].d = m(15) - m(11);
+
+ // Near: [30+20, 31+21, 32+22, 33+23]
+
+ planes[4].n.x = m(12) + m(8);
+ planes[4].n.y = m(13) + m(9);
+ planes[4].n.z = m(14) + m(10);
+ planes[4].d = m(15) + m(11);
+
+ // Normalize
+ if (normalize) {
+ for (int i = 0; i < 6; ++i) {
+ double mag = Math.sqrt(planes[i].n.x * planes[i].n.x + planes[i].n.y * planes[i].n.y + planes[i].n.z
+ * planes[i].n.z);
+
+ planes[i].n.x /= mag;
+ planes[i].n.y /= mag;
+ planes[i].n.z /= mag;
+ planes[i].d /= mag;
+ }
+ }
+ }
+
+ public void extractFrustumPlanes2(boolean normalize) {
+ // Left: [30+00, 31+01, 32+02, 33+03]
+ // comboMatrix.m[12] + comboMatrix.m[0];
+
+ planes[0].n.x = m(3) + m(0);
+ planes[0].n.y = m(7) + m(4);
+ planes[0].n.z = m(11) + m(8);
+ planes[0].d = m(15) + m(12);
+
+ // Right: [30-00, 31-01, 32-02, 33-03]
+
+ planes[1].n.x = m(3) - m(0);
+ planes[1].n.y = m(7) - m(4);
+ planes[1].n.z = m(11) - m(8);
+ planes[1].d = m(15) - m(12);
+
+ // Bottom: [30+10, 31+11, 32+12, 33+13]
+
+ planes[2].n.x = m(3) + m(1);
+ planes[2].n.y = m(7) + m(5);
+ planes[2].n.z = m(11) + m(9);
+ planes[2].d = m(15) + m(13);
+
+ // Top: [30-10, 31-11, 32-12, 33-13]
+
+ planes[3].n.x = m(3) - m(1);
+ planes[3].n.y = m(7) - m(5);
+ planes[3].n.z = m(11) - m(9);
+ planes[3].d = m(15) - m(13);
+
+ // Far: [30-20, 31-21, 32-22, 33-23]
+
+ planes[5].n.x = m(3) - m(2);
+ planes[5].n.y = m(7) - m(6);
+ planes[5].n.z = m(11) - m(10);
+ planes[5].d = m(15) - m(14);
+
+ // Near: [30+20, 31+21, 32+22, 33+23]
+
+ planes[4].n.x = m(3) + m(2);
+ planes[4].n.y = m(7) + m(6);
+ planes[4].n.z = m(11) + m(10);
+ planes[4].d = m(15) + m(14);
+
+ // Normalize
+ if (normalize) {
+ for (int i = 0; i < 6; ++i) {
+ double mag = Math.sqrt(planes[i].n.x * planes[i].n.x + planes[i].n.y * planes[i].n.y + planes[i].n.z
+ * planes[i].n.z);
+
+ planes[i].n.x /= mag;
+ planes[i].n.y /= mag;
+ planes[i].n.z /= mag;
+ planes[i].d /= mag;
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "f2\n" + m(0) + " " + m(1) + " " + m(2) + " " + m(3) + "\n" + m(4) + " " + m(5) + " " + m(6) + " "
+ + m(7) + "\n" + m(8) + " " + m(9) + " " + m(10) + " " + m(11) + "\n" + m(12) + " " + m(13) + " "
+ + m(14) + " " + m(15) + " " + "Frustum2[" + planes[0] + ", " + planes[1] + ", " + planes[2] + ", "
+ + planes[3] + ", " + planes[4] + ", " + planes[5] + "]";
+ }
+}
diff --git a/src/ru/olamedia/geom/ImmModeMesh.java b/src/ru/olamedia/geom/ImmModeMesh.java
new file mode 100644
index 0000000..4ce419b
--- /dev/null
+++ b/src/ru/olamedia/geom/ImmModeMesh.java
@@ -0,0 +1,465 @@
+package ru.olamedia.geom;
+
+import java.nio.Buffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.fixedfunc.GLPointerFunc;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.util.GLArrayDataServer;
+
+public class ImmModeMesh {
+ private IndexedMeshBulder indexed = IndexedMeshBulder.instance;
+ private boolean useIndexed = false;
+ protected GLArrayDataServer interleaved;
+ protected FloatBuffer buf;
+ private int vertexCount = 0;
+ protected int mode = GL2.GL_QUADS;
+ protected boolean isGLSL = false;
+ protected byte vertexComponent = 0;
+ protected byte normalComponent = 0;
+ protected byte colorComponent = 0;
+ protected byte texCoordComponent = 0;
+ protected float red = 1;
+ protected float green = 1;
+ protected float blue = 1;
+ protected float alpha = 1;
+ protected float offsetX = 0;
+ protected float offsetY = 0;
+ protected float offsetZ = 0;
+ protected float x = 0;
+ protected float y = 0;
+ protected float z = 0;
+ protected float nx = 0;
+ protected float ny = 0;
+ protected float nz = 0;
+ protected float u = 0;
+ protected float v = 0;
+ protected boolean isFinished = false;
+ protected boolean isServer = false;
+
+ public void setGLSL(boolean glsl) {
+ this.isGLSL = glsl;
+ }
+
+ public void makeServer() {
+ if (null == interleaved) {
+ if (isGLSL) {
+ allocateGLSLBuffer();
+ } else {
+ allocateFixedBuffer();
+ }
+ if (null != buf) {
+ buf.flip();
+ interleaved.put(buf);
+ buf.clear();
+ buf = null;
+ }
+ interleaved.seal(true);
+ isServer = true;
+ }
+ }
+
+ public Buffer getBuffer() {
+ if (!isServer) {
+ return buf;
+ }
+ return interleaved.getBuffer();
+ }
+
+ public void put(ImmModeMesh mesh) {
+ if (isServer) {
+ final FloatBuffer b = (FloatBuffer) mesh.getBuffer();
+ b.rewind();
+ interleaved.put(b);
+ } else {
+ final FloatBuffer b = (FloatBuffer) mesh.getBuffer();
+ b.rewind();
+ if (null == buf) {
+ allocateBuffer();
+ }
+ growBufferIfNecessary(b.remaining());
+ buf.put(b);
+ }
+ vertexCount += mesh.getVertexCount();
+ }
+
+ public void destroy() {
+ if (isServer) {
+ interleaved.destroy(GLContext.getCurrentGL().getGL2ES2());
+ interleaved = null;
+ } else {
+ if (null != buf) {
+ buf.clear();
+ buf = null;
+ }
+ }
+ }
+
+ public int getComponents() {
+ return vertexComponent + normalComponent + colorComponent + texCoordComponent;
+ }
+
+ protected void allocateBuffer() {
+ if (!isServer) {
+ buf = Buffers.newDirectFloatBuffer(getComponents() * getVertexCount());
+ } else {
+ if (isGLSL) {
+ allocateGLSLBuffer();
+ } else {
+ allocateFixedBuffer();
+ }
+ }
+ }
+
+ protected final void growBuffer(int additionalElements) {
+ final int osize = (buf != null) ? buf.capacity() : 0;
+ final int nsize = osize + (additionalElements * getComponents());
+ FloatBuffer newFBuffer = Buffers.newDirectFloatBuffer(nsize);
+ if (buf != null) {
+ buf.flip();
+ newFBuffer.put((FloatBuffer) buf);
+ }
+ buf = newFBuffer;
+ }
+
+ protected void allocateFixedBuffer() {
+ final GLArrayDataServer buf = GLArrayDataServer.createFixedInterleaved(getComponents(), GL.GL_FLOAT, false,
+ getVertexCount(), GL.GL_STATIC_DRAW);
+ if (vertexComponent != 0) {
+ buf.addFixedSubArray(GLPointerFunc.GL_VERTEX_ARRAY, vertexComponent, GL.GL_ARRAY_BUFFER);
+ }
+ if (colorComponent != 0) {
+ buf.addFixedSubArray(GLPointerFunc.GL_COLOR_ARRAY, colorComponent, GL.GL_ARRAY_BUFFER);
+ }
+ if (normalComponent != 0) {
+ buf.addFixedSubArray(GLPointerFunc.GL_NORMAL_ARRAY, normalComponent, GL.GL_ARRAY_BUFFER);
+ }
+ if (texCoordComponent != 0) {
+ buf.addFixedSubArray(GLPointerFunc.GL_TEXTURE_COORD_ARRAY, texCoordComponent, GL.GL_ARRAY_BUFFER);
+ }
+ interleaved = buf;
+ }
+
+ protected void allocateGLSLBuffer() {
+ final GLArrayDataServer buf = GLArrayDataServer.createGLSLInterleaved(getComponents(), GL.GL_FLOAT, false,
+ getVertexCount(), GL.GL_STATIC_DRAW);
+ if (vertexComponent != 0) {
+ buf.addGLSLSubArray("mesh_vertices", vertexComponent, GL.GL_ARRAY_BUFFER);
+ }
+ if (colorComponent != 0) {
+ buf.addGLSLSubArray("mesh_colors", colorComponent, GL.GL_ARRAY_BUFFER);
+ }
+ if (normalComponent != 0) {
+ buf.addGLSLSubArray("mesh_normal", normalComponent, GL.GL_ARRAY_BUFFER);
+ }
+ if (texCoordComponent != 0) {
+ buf.addGLSLSubArray("mesh_texCoord", texCoordComponent, GL.GL_ARRAY_BUFFER);
+ }
+ buf.rewind();
+ interleaved = buf;
+ }
+
+ protected final boolean growBufferIfNecessary(int spare) {
+ if (buf == null || buf.remaining() < spare) {
+ growBuffer(spare);
+ return true;
+ }
+ return false;
+ }
+
+ private void putf(float f) {
+ if (isServer) {
+ if (null == interleaved) {
+ allocateBuffer();
+ }
+ interleaved.putf(f);
+ } else {
+ // buf.put(f);
+ growBufferIfNecessary(256);
+ Buffers.putf(buf, f);
+ }
+ }
+
+ protected void putVertex() {
+ if (vertexComponent > 0) {
+ putf(x);
+ putf(y);
+ if (vertexComponent > 2) {
+ putf(z);
+ }
+ }
+ if (colorComponent > 0) {
+ putf(red);
+ putf(green);
+ putf(blue);
+ if (colorComponent > 3) {
+ putf(alpha);
+ }
+ }
+ if (normalComponent != 0) {
+ putf(nx);
+ putf(ny);
+ if (normalComponent > 2) {
+ putf(nz);
+ }
+ }
+ if (texCoordComponent > 0) {
+ putf(u);
+ putf(v);
+ }
+ }
+
+ public void getIndexed() {
+
+ }
+
+ public void enableColor3() {
+ colorComponent = 3;
+ if (useIndexed) {
+ indexed.setColorComponent(colorComponent);
+ }
+ }
+
+ public void enableColor4() {
+ colorComponent = 4;
+ if (useIndexed) {
+ indexed.setColorComponent(colorComponent);
+ }
+ }
+
+ public void enableVertex2() {
+ vertexComponent = 2;
+ if (useIndexed) {
+ indexed.setVertexComponent(vertexComponent);
+ }
+ }
+
+ public void enableVertex3() {
+ vertexComponent = 3;
+ if (useIndexed) {
+ indexed.setVertexComponent(vertexComponent);
+ }
+ }
+
+ public void enableNormal3() {
+ normalComponent = 3;
+ if (useIndexed) {
+ indexed.setNormalComponent(normalComponent);
+ }
+ }
+
+ public void enableTexCoord2() {
+ texCoordComponent = 2;
+ if (useIndexed) {
+ indexed.setUVComponent(texCoordComponent);
+ }
+ }
+
+ public void enableTexCoord4() {
+ texCoordComponent = 4;
+ if (useIndexed) {
+ indexed.setUVComponent(texCoordComponent);
+ }
+ }
+
+ public void glBegin(int mode) {
+ this.mode = mode;
+ allocateBuffer();
+ if (useIndexed) {
+ indexed.reset();
+ }
+ }
+
+ public void beginQuads() {
+ glBegin(GL2.GL_QUADS);
+ }
+
+ public void beginTriangles() {
+ glBegin(GL2.GL_TRIANGLES);
+ }
+
+ public void glEnd() {
+ if (useIndexed) {
+ indexed.end();
+ final IntBuffer ind = indexed.getIndices();
+ System.out.println("glEnd: " + vertexCount + " / " + ind.limit());
+ }
+ if (isServer) {
+ if (null == interleaved) {
+ allocateBuffer();
+ }
+ interleaved.seal(true);
+ }
+ isFinished = true;
+ }
+
+ public void end() {
+ glEnd();
+ }
+
+ public void setServer(boolean isServer) {
+ this.isServer = isServer;
+ }
+
+ public int getVBOName() {
+ return interleaved.getVBOName();
+ }
+
+ public int getMode() {
+ return mode;
+ }
+
+ public boolean draw() {
+ if (!isFinished) {
+ return false;
+ }
+ makeServer();
+ final GL2ES2 gl = GLContext.getCurrentGL().getGL2ES2();
+ interleaved.enableBuffer(gl, true);
+ // Вывод геометрии VBO выполняется такими же функциями, как и при
+ // использовании буфера в оперативной памяти.
+ gl.glDrawArrays(mode, 0, interleaved.getElementCount());
+ interleaved.enableBuffer(gl, false);
+ //gl.glFlush();
+ return true;
+ }
+
+ public void setColor(float red, float green, float blue) {
+ this.red = red;
+ this.green = green;
+ this.blue = blue;
+ if (useIndexed) {
+ indexed.glColor3f(red, green, blue);
+ }
+ }
+
+ public void setColor(float red, float green, float blue, float alpha) {
+ this.red = red;
+ this.green = green;
+ this.blue = blue;
+ this.alpha = alpha;
+ if (useIndexed) {
+ indexed.glColor4f(red, green, blue, alpha);
+ }
+ }
+
+ public void glColor3f(float red, float green, float blue) {
+ this.red = red;
+ this.green = green;
+ this.blue = blue;
+ if (useIndexed) {
+ indexed.glColor3f(red, green, blue);
+ }
+ }
+
+ public void glColor4f(float red, float green, float blue, float alpha) {
+ this.red = red;
+ this.green = green;
+ this.blue = blue;
+ this.alpha = alpha;
+ if (useIndexed) {
+ indexed.glColor4f(red, green, blue, alpha);
+ }
+ }
+
+ public void glVertex3f(float x, float y, float z) {
+ this.x = offsetX + x;
+ this.y = offsetY + y;
+ this.z = offsetZ + z;
+ putVertex();
+ if (useIndexed) {
+ indexed.glVertex3f(x, y, z);
+ }
+ }
+
+ public void glVertex2f(float x, float y) {
+ this.x = offsetX + x;
+ this.y = offsetY + y;
+ putVertex();
+ if (useIndexed) {
+ indexed.glVertex2f(x, y);
+ }
+ }
+
+ public void setUV(float u, float v) {
+ this.u = u;
+ this.v = v;
+ if (useIndexed) {
+ indexed.setUV(u, v);
+ }
+ }
+
+ public void glTexCoord2f(float u, float v) {
+ this.u = u;
+ this.v = v;
+ if (useIndexed) {
+ indexed.setUV(u, v);
+ }
+ }
+
+ public void glRectf(float x1, float y1, float x2, float y2) {
+ glVertex2f(x1, y1);
+ glVertex2f(x1, y2);
+ glVertex2f(x2, y2);
+ glVertex2f(x2, y1);
+ }
+
+ protected ImmModeMesh(int vertexCount) {
+ this.setVertexCount(vertexCount);
+ }
+
+ public static ImmModeMesh allocate(int elementCount) {
+ return new ImmModeMesh(elementCount);
+ }
+
+ public int getVertexCount() {
+ return vertexCount;
+ }
+
+ public void setVertexCount(int vertexCount) {
+ this.vertexCount = vertexCount;
+ }
+
+ public void glTranslate(float x, float y, float z) {
+ offsetX = x;
+ offsetY = y;
+ offsetZ = z;
+ if (useIndexed) {
+ indexed.glTranslate(x, y, z);
+ }
+ }
+
+ public void dispose() {
+ if (null != interleaved) {
+ interleaved.destroy(GLContext.getCurrentGL().getGL2ES2());
+ }
+ if (null != buf) {
+ buf.clear();
+ buf = null;
+ }
+ }
+
+ public void compact() {
+ if (null != interleaved) {
+ if (null != interleaved.getBuffer()) {
+ interleaved.getBuffer().flip();
+ ((FloatBuffer) interleaved.getBuffer()).compact();
+ }
+ }
+ }
+
+ public void glNormal3f(float nx, float ny, float nz) {
+ this.nx = nx;
+ this.ny = ny;
+ this.nz = nz;
+ if (useIndexed) {
+ indexed.glNormal3f(nx, ny, nz);
+ }
+ }
+}
diff --git a/src/ru/olamedia/geom/IndexedMeshBulder.java b/src/ru/olamedia/geom/IndexedMeshBulder.java
new file mode 100644
index 0000000..ec66305
--- /dev/null
+++ b/src/ru/olamedia/geom/IndexedMeshBulder.java
@@ -0,0 +1,207 @@
+package ru.olamedia.geom;
+
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+
+public class IndexedMeshBulder {
+ protected static IndexedMeshBulder instance = new IndexedMeshBulder();
+ protected IntBuffer indices = IntBuffer.allocate(4096);
+ protected FloatBuffer vertex = FloatBuffer.allocate(4096 * 3);
+ protected FloatBuffer color = FloatBuffer.allocate(4096 * 4);
+ protected FloatBuffer normal = FloatBuffer.allocate(4096 * 3);
+ protected FloatBuffer uv = FloatBuffer.allocate(4096 * 2);
+ protected int indexCount = 0;
+ protected int vertexCount = 0;
+ protected int colorCount = 0;
+ protected int normalCount = 0;
+ protected int uvCount = 0;
+
+ protected byte vertexComponent = 0;
+ protected byte normalComponent = 0;
+ protected byte colorComponent = 0;
+ protected byte uvComponent = 0;
+
+ protected float red = 1;
+ protected float green = 1;
+ protected float blue = 1;
+ protected float alpha = 1;
+ protected float offsetX = 0;
+ protected float offsetY = 0;
+ protected float offsetZ = 0;
+ protected float x = 0;
+ protected float y = 0;
+ protected float z = 0;
+ protected float nx = 0;
+ protected float ny = 0;
+ protected float nz = 0;
+ protected float u = 0;
+ protected float v = 0;
+
+ public void reset() {
+ vertex.clear();
+ color.clear();
+ normal.clear();
+ uv.clear();
+ indices.clear();
+ vertexCount = indexCount = vertexComponent = colorComponent = normalComponent = uvComponent = 0;
+ }
+
+ public void end(){
+ indices.flip();
+ vertex.flip();
+ color.flip();
+ normal.flip();
+ uv.flip();
+ }
+
+ public IntBuffer getIndices() {
+ IntBuffer ind = IntBuffer.allocate(indices.limit());
+ ind.put(indices);
+ return ind;
+ }
+
+ private boolean _sameVertex(int i) {
+ if (vertexComponent != 0) {
+ if (vertex.get(i * vertexComponent) == z) {
+ if (vertex.get(i * vertexComponent + 1) == y) {
+ if ((vertexComponent == 2) || (vertex.get(i * vertexComponent) == z)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean _sameColor(int i) {
+ if (colorComponent != 0) {
+ if (color.get(i * colorComponent) == red) {
+ if (color.get(i * colorComponent + 1) == green) {
+ if (color.get(i * colorComponent + 2) == blue) {
+ if ((colorComponent == 2) || (color.get(i * colorComponent) == alpha)) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean _sameUV(int i) {
+ if (uvComponent != 0) {
+ if (uv.get(i * uvComponent) == u) {
+ if (uv.get(i * uvComponent + 1) == v) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private void _addVertex() {
+ if (vertexComponent != 0) {
+ vertex.put(x);
+ vertex.put(y);
+ if (vertexComponent > 2) {
+ vertex.put(z);
+ }
+ }
+ if (colorComponent != 0) {
+ color.put(red);
+ color.put(green);
+ color.put(blue);
+ if (colorComponent > 3) {
+ color.put(alpha);
+ }
+ }
+ if (normalComponent != 0) {
+ normal.put(nx);
+ normal.put(ny);
+ if (normalComponent > 2) {
+ normal.put(nz);
+ }
+ }
+ if (uvComponent != 0) {
+ uv.put(u);
+ uv.put(v);
+ }
+ indices.put(indexCount);
+ indexCount++;
+ }
+
+ private void putVertex() {
+ vertexCount++;
+ for (int i = 0; i < vertexCount; i++) {
+ if (_sameVertex(i) && _sameColor(i) && _sameUV(i)) {
+ indices.put(i);
+ return;
+ }
+ }
+ _addVertex();
+ }
+
+ public void setVertexComponent(byte vertexComponent) {
+ this.vertexComponent = vertexComponent;
+ }
+
+ public void setNormalComponent(byte normalComponent) {
+ this.normalComponent = normalComponent;
+ }
+
+ public void setColorComponent(byte colorComponent) {
+ this.colorComponent = colorComponent;
+ }
+
+ public void setUVComponent(byte uvComponent) {
+ this.uvComponent = uvComponent;
+ }
+
+ private int comps() {
+ return vertexComponent + normalComponent + colorComponent + uvComponent;
+ }
+
+ public void glTranslate(float x, float y, float z) {
+ offsetX = x;
+ offsetY = y;
+ offsetZ = z;
+ }
+
+ public void glColor3f(float red, float green, float blue) {
+ this.red = red;
+ this.green = green;
+ this.blue = blue;
+ }
+
+ public void glColor4f(float red, float green, float blue, float alpha) {
+ this.red = red;
+ this.green = green;
+ this.blue = blue;
+ this.alpha = alpha;
+ }
+
+ public void glVertex3f(float x, float y, float z) {
+ this.x = offsetX + x;
+ this.y = offsetY + y;
+ this.z = offsetZ + z;
+ putVertex();
+ }
+
+ public void glVertex2f(float x, float y) {
+ this.x = offsetX + x;
+ this.y = offsetY + y;
+ putVertex();
+ }
+
+ public void glNormal3f(float nx, float ny, float nz) {
+ this.nx = nx;
+ this.ny = ny;
+ this.nz = nz;
+ }
+
+ public void setUV(float u, float v) {
+ this.u = u;
+ this.v = v;
+ }
+
+}
diff --git a/src/ru/olamedia/geom/Mesh.java b/src/ru/olamedia/geom/Mesh.java
index bda53b9..7e25666 100644
--- a/src/ru/olamedia/geom/Mesh.java
+++ b/src/ru/olamedia/geom/Mesh.java
@@ -10,12 +10,52 @@ import javax.media.opengl.GL2;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLContext;
-import javax.media.opengl.fixedfunc.GLPointerFunc;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLUniformData;
+import javax.vecmath.Point3f;
+
+import ru.olamedia.asset.Shader;
+import ru.olamedia.olacraft.game.Game;
import com.jogamp.opengl.util.GLArrayDataServer;
+import com.jogamp.opengl.util.PMVMatrix;
+import com.jogamp.opengl.util.glsl.ShaderState;
import com.jogamp.opengl.util.texture.Texture;
public class Mesh {
+ private static Shader shader = null;
+ private static GLUniformData pmvMatrixUniform;
+ private static GLUniformData sunColor;
+
+ private static Shader getShader() {
+ if (null == shader) {
+ shader = new Shader();
+ shader.compile();
+ GL2ES2 gl = GLContext.getCurrentGL().getGL2ES2();
+ ShaderState state = shader.getState();
+ PMVMatrix pmvMatrix = Game.client.getScene().getPmvMatrix();
+ state.attachObject("pmvMatrix", pmvMatrix);
+ pmvMatrixUniform = new GLUniformData("pmvMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf());
+ state.ownUniform(pmvMatrixUniform);
+ state.uniform(gl, pmvMatrixUniform);
+
+ state.attachObject("sunColor", sunColor);
+ sunColor = new GLUniformData("sunColor", 4, Game.client.getScene().dayTime.sunColor);
+ state.ownUniform(sunColor);
+ state.uniform(gl, sunColor);
+
+ // if (!state.uniform(gl, new GLUniformData("sunColor", 4,
+ // Game.client.getScene().time.sunColor))) {
+ // throw new GLException("Error setting sunColor in shader: " +
+ // state);
+ // }
+ if (!state.uniform(gl, new GLUniformData("mesh_ActiveTexture", 0))) {
+ throw new GLException("Error setting mesh_ActiveTexture in shader: " + state);
+ }
+ }
+ return shader;
+ }
+
public void invalidate() {
buffer = null;
data = null;
@@ -103,11 +143,11 @@ public class Mesh {
}
for (Integer m : materials.keySet()) {
int matVertCount = materials.get(m);
- final GLArrayDataServer interleaved = GLArrayDataServer.createFixedInterleaved(9, GL2.GL_FLOAT, false,
+ final GLArrayDataServer interleaved = GLArrayDataServer.createGLSLInterleaved(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);
+ interleaved.addGLSLSubArray("mesh_vertices", 3, GL.GL_ARRAY_BUFFER);
+ interleaved.addGLSLSubArray("mesh_colors", 4, GL.GL_ARRAY_BUFFER);
+ interleaved.addGLSLSubArray("mesh_texCoord", 2, GL.GL_ARRAY_BUFFER);
arrays.put(m, interleaved);
}
for (int n = 0; n < vertexCount; n++) {
@@ -143,6 +183,10 @@ public class Mesh {
zOffset = z;
}
+ public void setPoint3f(Point3f point) {
+ setPoint3f(point.x, point.y, point.z);
+ }
+
public void setPoint3f(float x, float y, float z) {
ptr = vertexPtr * vertexSize;
data[ptr + 0] = x + xOffset;
@@ -225,19 +269,24 @@ public class Mesh {
return;
}
GL glx = GLContext.getCurrentGL();
- if (true){
- GL2 gl = glx.getGL2();
- gl.glShadeModel(GL2.GL_FLAT);
- }
if (useVbo) {
GL2ES2 gl = glx.getGL2ES2();
// GL2 gl = glx.getGL2();
+ getShader().enable();
+ Game.client.getScene().dayTime.getClearColor();
+ getShader().getState().uniform(gl, pmvMatrixUniform);
+ getShader().getState().uniform(gl, sunColor);
for (Integer m : materials.keySet()) {
-
- gl.glEnable(GL.GL_TEXTURE_2D);
+ gl.glActiveTexture(GL.GL_TEXTURE0);
gl.glBindTexture(GL.GL_TEXTURE_2D, (int) m);
- 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_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_MAG_FILTER, GL.GL_LINEAR);
+ // gl.glTexParameteri(GL.GL_TEXTURE_2D,
+ // GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR_MIPMAP_LINEAR);
arrays.get(m).enableBuffer(gl, true);
gl.glEnable(GL.GL_CULL_FACE);
gl.glEnable(GL.GL_DEPTH_TEST);
@@ -246,6 +295,7 @@ public class Mesh {
arrays.get(m).enableBuffer(gl, false);
// System.exit(0);
}
+ getShader().disable();
} else {
GL2 gl = glx.getGL2();
if (useDisplayList) {
diff --git a/src/ru/olamedia/geom/MultiMesh.java b/src/ru/olamedia/geom/MultiMesh.java
new file mode 100644
index 0000000..98becd1
--- /dev/null
+++ b/src/ru/olamedia/geom/MultiMesh.java
@@ -0,0 +1,34 @@
+package ru.olamedia.geom;
+
+import java.nio.IntBuffer;
+
+import javax.media.opengl.GL2;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL3;
+import javax.media.opengl.GLContext;
+
+public class MultiMesh {
+ private IntBuffer vboIndices;
+ private IntBuffer counts;
+ private int mode = GL2.GL_TRIANGLES;
+
+ public void clear() {
+ vboIndices.clear();
+ }
+
+ public void add(ImmModeMesh mesh) {
+ vboIndices.put(mesh.getVBOName());
+ }
+
+ public void draw() {
+ final GL3 gl = GLContext.getCurrentGL().getGL3();
+ }
+
+ public MultiMesh(int meshCount) {
+ vboIndices = IntBuffer.allocate(meshCount);
+ }
+
+ public static MultiMesh allocate(int meshCount) {
+ return new MultiMesh(meshCount);
+ }
+}
diff --git a/src/ru/olamedia/geom/SimpleQuadMesh.java b/src/ru/olamedia/geom/SimpleQuadMesh.java
index ad3c27c..c28c799 100644
--- a/src/ru/olamedia/geom/SimpleQuadMesh.java
+++ b/src/ru/olamedia/geom/SimpleQuadMesh.java
@@ -1,9 +1,28 @@
package ru.olamedia.geom;
+import javax.vecmath.Point3f;
+
+import ru.olamedia.asset.SpriteRectangle;
+
public class SimpleQuadMesh extends Mesh {
public boolean restart = true;
+ public Point3f bottomLeftBack = new Point3f();
+ public Point3f bottomLeftFront = new Point3f();
+ public Point3f bottomRightBack = new Point3f();
+ public Point3f bottomRightFront = new Point3f();
+
+ public Point3f topLeftBack = new Point3f();
+ public Point3f topLeftFront = new Point3f();
+ public Point3f topRightBack = new Point3f();
+ public Point3f topRightFront = new Point3f();
+
+ public float textureTop = 1;
+ public float textureBottom = 0;
+ public float textureLeft = 0;
+ public float textureRight = 1;
+
public void restart() {
restart = true;
}
@@ -16,108 +35,154 @@ public class SimpleQuadMesh extends Mesh {
super(size * 4);
}
- private void addBottomLeftBackVertex() {
- setPoint3f(-0.5f, -0.5f, -0.5f);
+ public void addBottomLeftBackVertex() {
+ setPoint3f(bottomLeftBack);
}
- private void addBottomLeftFrontVertex() {
- setPoint3f(-0.5f, -0.5f, 0.5f);
+ public void addBottomLeftFrontVertex() {
+ setPoint3f(bottomLeftFront);
}
- private void addBottomRightBackVertex() {
- setPoint3f(0.5f, -0.5f, -0.5f);
+ public void addBottomRightBackVertex() {
+ setPoint3f(bottomRightBack);
}
- private void addBottomRightFrontVertex() {
- setPoint3f(0.5f, -0.5f, 0.5f);
+ public void addBottomRightFrontVertex() {
+ setPoint3f(bottomRightFront);
}
- private void addTopLeftBackVertex() {
- setPoint3f(-0.5f, 0.5f, -0.5f);
+ public void addTopLeftBackVertex() {
+ setPoint3f(topLeftBack);
}
- private void addTopLeftFrontVertex() {
- setPoint3f(-0.5f, 0.5f, 0.5f);
+ public void addTopLeftFrontVertex() {
+ setPoint3f(topLeftFront);
}
- private void addTopRightBackVertex() {
- setPoint3f(0.5f, 0.5f, -0.5f);
+ public void addTopRightBackVertex() {
+ setPoint3f(topRightBack);
}
- private void addTopRightFrontVertex() {
- setPoint3f(0.5f, 0.5f, 0.5f);
+ public void addTopRightFrontVertex() {
+ setPoint3f(topRightFront);
}
public void addFrontQuad() {
// triangle strip: И
- setUV(0, 1);
+ setUV(textureLeft, textureTop);
addTopLeftFrontVertex(); // top left
- setUV(0, 0);
+ setUV(textureLeft, textureBottom);
addBottomLeftFrontVertex(); // bottom left
- setUV(1, 0);
+ setUV(textureRight, textureBottom);
addBottomRightFrontVertex(); // bottom right
- setUV(1, 1);
+ setUV(textureRight, textureTop);
addTopRightFrontVertex(); // top right
}
public void addBackQuad() {
// triangle strip: И
- setUV(0, 1);
+ setUV(textureLeft, textureTop);
addTopRightBackVertex();
- setUV(0, 0);
+ setUV(textureLeft, textureBottom);
addBottomRightBackVertex();
- setUV(1, 0);
+ setUV(textureRight, textureBottom);
addBottomLeftBackVertex();
- setUV(1, 1);
+ setUV(textureRight, textureTop);
addTopLeftBackVertex();
}
public void addLeftQuad() {
// triangle strip: И
- setUV(0, 1);
+ setUV(textureLeft, textureTop);
addTopLeftBackVertex();
- setUV(0, 0);
+ setUV(textureLeft, textureBottom);
addBottomLeftBackVertex();
- setUV(1, 0);
+ setUV(textureRight, textureBottom);
addBottomLeftFrontVertex();
- setUV(1, 1);
+ setUV(textureRight, textureTop);
addTopLeftFrontVertex();
}
public void addRightQuad() {
// triangle strip: И
- setUV(0, 1);
+ setUV(textureLeft, textureTop);
addTopRightFrontVertex();
- setUV(0, 0);
+ setUV(textureLeft, textureBottom);
addBottomRightFrontVertex();
- setUV(1, 0);
+ setUV(textureRight, textureBottom);
addBottomRightBackVertex();
- setUV(1, 1);
+ setUV(textureRight, textureTop);
addTopRightBackVertex();
}
public void addTopQuad() {
// triangle strip: И
- setUV(0, 0);
+ setUV(textureLeft, textureBottom);
addTopLeftBackVertex();
- setUV(0, 1);
+ setUV(textureLeft, textureTop);
addTopLeftFrontVertex();
- setUV(1, 1);
+ setUV(textureRight, textureTop);
addTopRightFrontVertex();
- setUV(1, 0);
+ setUV(textureRight, textureBottom);
addTopRightBackVertex();
}
public void addBottomQuad() {
// triangle strip: И
- setUV(0, 0);
+ setUV(textureLeft, textureBottom);
addBottomLeftFrontVertex();
- setUV(0, 1);
+ setUV(textureLeft, textureTop);
addBottomLeftBackVertex();
- setUV(1, 1);
+ setUV(textureRight, textureTop);
addBottomRightBackVertex();
- setUV(1, 0);
+ setUV(textureRight, textureBottom);
addBottomRightFrontVertex();
}
+ public void setPointOffset(float offset) {
+ bottomLeftBack.x = -offset;
+ bottomLeftBack.y = -offset;
+ bottomLeftBack.z = -offset;
+ //
+ bottomLeftFront.x = -offset;
+ bottomLeftFront.y = -offset;
+ bottomLeftFront.z = offset;
+ //
+ bottomRightBack.x = offset;
+ bottomRightBack.y = -offset;
+ bottomRightBack.z = -offset;
+ //
+ bottomRightFront.x = offset;
+ bottomRightFront.y = -offset;
+ bottomRightFront.z = offset;
+ //
+ topLeftBack.x = -offset;
+ topLeftBack.y = offset;
+ topLeftBack.z = -offset;
+ //
+ topLeftFront.x = -offset;
+ topLeftFront.y = offset;
+ topLeftFront.z = offset;
+ //
+ topRightBack.x = offset;
+ topRightBack.y = offset;
+ topRightBack.z = -offset;
+ //
+ topRightFront.x = offset;
+ topRightFront.y = offset;
+ topRightFront.z = offset;
+
+ }
+
+ public void setTextureOffset(SpriteRectangle offset) {
+ if (null != offset) {
+ // System.out.print("Offset " + "[" + offset.topLeft.x + "," +
+ // offset.topLeft.y + "]");
+ textureTop = offset.topLeft.y;
+ textureLeft = offset.topLeft.x;
+ textureRight = offset.bottomRight.x;
+ textureBottom = offset.bottomRight.y;
+ }
+ }
+
}
diff --git a/src/ru/olamedia/geom/VoxelRaypicker.java b/src/ru/olamedia/geom/VoxelRaypicker.java
new file mode 100644
index 0000000..9e8c533
--- /dev/null
+++ b/src/ru/olamedia/geom/VoxelRaypicker.java
@@ -0,0 +1,37 @@
+package ru.olamedia.geom;
+
+public class VoxelRaypicker {
+ public float[] center = new float[3];
+ public float[] dir = new float[3];
+ public float radius;
+ public float[] picker = new float[3];
+ public float[] minDelta = new float[3];
+ public float[] delta = new float[3];
+ public float[] absDelta = new float[3];
+
+ private void calcDelta(byte i) {
+ if (dir[i] > 0) {
+ delta[i] = ((float) ((int) (center[i] + 1)) - center[i]) / dir[i];
+ absDelta[i] = delta[i];
+ } else if (dir[0] < 0) {
+ delta[i] = -((float) ((int) (center[i] - 1)) - center[i]) / dir[i];
+ absDelta[i] = delta[i];
+ } else {
+ delta[i] = 0;
+ absDelta[i] = 0;
+ }
+ minDelta[i] = delta[i];
+ }
+
+ public void reset() {
+ picker[0] = center[0];
+ picker[1] = center[1];
+ picker[2] = center[2];
+ calcDelta((byte) 0);
+ calcDelta((byte) 1);
+ calcDelta((byte) 2);
+ }
+
+ public void next() {
+ }
+}
diff --git a/src/ru/olamedia/input/Keyboard.java b/src/ru/olamedia/input/Keyboard.java
index 6a9ecbd..77e0b7a 100644
--- a/src/ru/olamedia/input/Keyboard.java
+++ b/src/ru/olamedia/input/Keyboard.java
@@ -36,22 +36,79 @@ public class Keyboard implements com.jogamp.newt.event.KeyListener {
@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);
+ /*
+ * Key pressed: 87
+ * Key pressed: 65
+ * Key pressed: 83
+ * Key pressed: 68
+ * Key pressed: 65034
+ * Key pressed: 1731
+ * Key pressed: 1734
+ * Key pressed: 1753
+ * Key pressed: 1751
+ *
+ * keycode 24 = q Q Cyrillic_shorti Cyrillic_SHORTI
+ * keycode 25 = w W Cyrillic_tse Cyrillic_TSE
+ * keycode 26 = e E Cyrillic_u Cyrillic_U
+ * keycode 27 = r R Cyrillic_ka Cyrillic_KA
+ * keycode 28 = t T Cyrillic_ie Cyrillic_IE
+ * keycode 29 = y Y Cyrillic_en Cyrillic_EN
+ * keycode 30 = u U Cyrillic_ghe Cyrillic_GHE
+ * keycode 31 = i I Cyrillic_sha Cyrillic_SHA
+ * keycode 32 = o O Cyrillic_shcha Cyrillic_SHCHA
+ * keycode 33 = p P Cyrillic_ze Cyrillic_ZE
+ *
+ * KeyPress event, serial 36, synthetic NO, window 0x4600001,
+ * root 0xb7, subw 0x0, time 326572351, (602,679), root:(669,730),
+ * state 0x10, keycode 25 (keysym 0x77, w), same_screen YES,
+ * XLookupString gives 1 bytes: (77) "w"
+ * XmbLookupString gives 1 bytes: (77) "w"
+ * XFilterEvent returns: False
+ *
+ * KeyRelease event, serial 36, synthetic NO, window 0x4600001,
+ * root 0xb7, subw 0x0, time 326572447, (602,679), root:(669,730),
+ * state 0x10, keycode 25 (keysym 0x77, w), same_screen YES,
+ * XLookupString gives 1 bytes: (77) "w"
+ * XFilterEvent returns: False
+ *
+ * KeyPress event, serial 36, synthetic NO, window 0x4600001,
+ * root 0xb7, subw 0x0, time 326588119, (118,-7), root:(185,44),
+ * state 0x2010, keycode 25 (keysym 0x6c3, Cyrillic_tse), same_screen
+ * YES,
+ * XLookupString gives 2 bytes: (d1 86) "ц"
+ * XmbLookupString gives 2 bytes: (d1 86) "ц"
+ * XFilterEvent returns: False
+ *
+ * KeyRelease event, serial 36, synthetic NO, window 0x4600001,
+ * root 0xb7, subw 0x0, time 326588200, (118,-7), root:(185,44),
+ * state 0x2010, keycode 25 (keysym 0x6c3, Cyrillic_tse), same_screen
+ * YES,
+ * XLookupString gives 2 bytes: (d1 86) "ц"
+ * XFilterEvent returns: False
+ */
+ if (e.getKeyCode() < 256) {
+ 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);
+ }
}
+ System.out.println("Key pressed: " + e.getKeyCode());
+ } else {
+ System.err.println("Key pressed: " + e.getKeyCode());
}
}
@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);
+ if (e.getKeyCode() < 256) {
+ 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);
+ }
}
}
}
diff --git a/src/ru/olamedia/input/MouseJail.java b/src/ru/olamedia/input/MouseJail.java
index bd12b0a..9168cc8 100644
--- a/src/ru/olamedia/input/MouseJail.java
+++ b/src/ru/olamedia/input/MouseJail.java
@@ -1,9 +1,5 @@
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;
@@ -15,10 +11,22 @@ import ru.olamedia.game.GameFrame;
public class MouseJail extends MouseAdapter {
public static MouseJail instance = new MouseJail();
+ public int x;
+ public int y;
+
public MouseJail() {
}
private static boolean isActive = false;
+ private static boolean isEnabled = true; // disabled if GUI is opened
+
+ public static void disable() {
+ isEnabled = false;
+ }
+
+ public static void enable() {
+ isEnabled = true;
+ }
/**
* @return the isActive
@@ -32,22 +40,26 @@ public class MouseJail extends MouseAdapter {
* 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);
+ if (isEnabled) {
+ 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 (isEnabled) {
if (e.isAltDown()) {
setActive(false);
} else {
setActive(true);
}
for (ru.olamedia.input.MouseListener l : listeners) {
- l.onMouseClick();
+ l.onMouseClick(e);
}
+ // }
}
@Override
@@ -61,7 +73,7 @@ public class MouseJail extends MouseAdapter {
System.out.println("Exited");
isActive = false;
if (isActive) {
- //moveToCenter();
+ // moveToCenter();
}
}
@@ -83,19 +95,17 @@ public class MouseJail extends MouseAdapter {
private float sensitivity = 2f;
private void onMove(MouseEvent e) {
+ x = e.getX();
+ y = e.getY();
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;
+ final float dx = (e.getX() - GameFrame.getGLWidth() / 2) * sensitivity / 10;
+ final float dy = (e.getY() - GameFrame.getGLHeight() / 2) * 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);
+ GameFrame.getWindow().warpPointer(GameFrame.getGLWidth() / 2, GameFrame.getGLHeight() / 2);
}
}
diff --git a/src/ru/olamedia/input/MouseListener.java b/src/ru/olamedia/input/MouseListener.java
index 3d93d1d..c9f7088 100644
--- a/src/ru/olamedia/input/MouseListener.java
+++ b/src/ru/olamedia/input/MouseListener.java
@@ -1,6 +1,8 @@
package ru.olamedia.input;
+import com.jogamp.newt.event.MouseEvent;
+
public interface MouseListener {
public void onMouseMove(float dx, float dy);
- public void onMouseClick();
+ public void onMouseClick(MouseEvent e);
}
diff --git a/src/ru/olamedia/liveEntity/LiveEntity.java b/src/ru/olamedia/liveEntity/LiveEntity.java
index 1befec6..2489a57 100644
--- a/src/ru/olamedia/liveEntity/LiveEntity.java
+++ b/src/ru/olamedia/liveEntity/LiveEntity.java
@@ -4,21 +4,24 @@ import javax.vecmath.Vector3f;
import com.jogamp.newt.event.KeyEvent;
-import ru.olamedia.Options;
import ru.olamedia.camera.Cameraman;
+import ru.olamedia.camera.MatrixCamera;
import ru.olamedia.olacraft.game.Game;
import ru.olamedia.olacraft.inventory.Inventory;
-import ru.olamedia.olacraft.network.GameClient;
-import ru.olamedia.olacraft.scene.GameScene;
import ru.olamedia.olacraft.world.block.Block;
import ru.olamedia.olacraft.world.blockStack.BlockStack;
import ru.olamedia.olacraft.world.blockTypes.GravelBlockType;
import ru.olamedia.olacraft.world.chunk.ChunkUnavailableException;
import ru.olamedia.olacraft.world.location.BlockLocation;
+import ru.olamedia.player.RuntimeSettings;
+import ru.olamedia.input.KeyListener;
import ru.olamedia.input.Keyboard;
-public class LiveEntity implements Cameraman {
- private Inventory inventory; // every living entity can have inventory
+public class LiveEntity implements Cameraman, KeyListener {
+ public MatrixCamera camera;
+ public MatrixCamera thirdPerson = new MatrixCamera();
+ public RuntimeSettings settings = new RuntimeSettings();
+ protected Inventory inventory; // every living entity can have inventory
private float x;
private float y;
private float z;
@@ -40,7 +43,7 @@ public class LiveEntity implements Cameraman {
private float walkSpeed = 1.3f;// 1.3-1.5 m/s
private float runSpeed = 4.5f;// m/s
- private boolean isWalking = false;
+ protected boolean isWalking = false;
private boolean isRunning = false;
private boolean isSneaking = false;
private boolean isCrouching = false;
@@ -67,8 +70,6 @@ public class LiveEntity implements Cameraman {
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());
}
}
@@ -108,7 +109,7 @@ public class LiveEntity implements Cameraman {
}
public boolean isEmptyUnderFoot() throws ChunkUnavailableException {
- return isEmptyBlock(0, -1, 0);
+ return canMoveThrough(0, -1, 0);
}
/**
@@ -128,11 +129,38 @@ public class LiveEntity implements Cameraman {
boolean keySneak = Keyboard.isKeyDown("playerSneak");
boolean keyCrouch = Keyboard.isKeyDown("playerCrouch");
boolean keyRenderDistance = Keyboard.isKeyDown("playerRenderDistance");
+ if (Keyboard.isKeyDown("playerInventory1")) {
+ inventory.select(0);
+ }
+ if (Keyboard.isKeyDown("playerInventory2")) {
+ inventory.select(1);
+ }
+ if (Keyboard.isKeyDown("playerInventory3")) {
+ inventory.select(2);
+ }
+ if (Keyboard.isKeyDown("playerInventory4")) {
+ inventory.select(3);
+ }
+ if (Keyboard.isKeyDown("playerInventory5")) {
+ inventory.select(4);
+ }
+ if (Keyboard.isKeyDown("playerInventory6")) {
+ inventory.select(5);
+ }
+ if (Keyboard.isKeyDown("playerInventory7")) {
+ inventory.select(6);
+ }
+ if (Keyboard.isKeyDown("playerInventory8")) {
+ inventory.select(7);
+ }
+ if (Keyboard.isKeyDown("playerInventory9")) {
+ inventory.select(8);
+ }
+ if (Keyboard.isKeyDown("playerInventory0")) {
+ inventory.select(9);
+ }
if (keyRenderDistance) {
- Options.renderDistance *= 2;
- if (Options.renderDistance > 256) {
- Options.renderDistance = 32;
- }
+
}
if (keySneak) {
if (!isSneaking) {
@@ -393,15 +421,17 @@ public class LiveEntity implements Cameraman {
}
- public boolean isEmptyBlock(int dx, int dy, int dz) {
- BlockLocation loc = new BlockLocation((int) x + dx, (int) Math.ceil(y) + dy, (int) z + dz);
- if (!Game.client.getWorldProvider().isChunkAvailable(loc.getChunkLocation())) {
- Game.client.getWorldProvider().loadChunk(loc.getChunkLocation());
+ BlockLocation testLoc = new BlockLocation();
+
+ public boolean canMoveThrough(int dx, int dy, int dz) {
+ testLoc.set((int) x + dx, (int) Math.ceil(y) + dy, (int) z + dz);
+ if (!Game.client.getWorldProvider().isChunkAvailable(testLoc.getChunkLocation())) {
+ Game.client.getWorldProvider().loadChunk(testLoc.getChunkLocation());
return false;
}
try {
- return Game.client.getWorldProvider().isEmptyBlock((int) x + dx, (int) Math.ceil(y) + dy, (int) z + dz);
+ return Game.client.getWorldProvider().canMoveThrough((int) x + dx, (int) Math.ceil(y) + dy, (int) z + dz);
} catch (ChunkUnavailableException e) {
e.printStackTrace();
return false;
@@ -409,11 +439,11 @@ public class LiveEntity implements Cameraman {
}
public boolean haveBlockUnder(int dy) throws ChunkUnavailableException {
- return !isEmptyBlock(0, -dy, 0);
+ return !canMoveThrough(0, -dy, 0);
}
public boolean inAir() throws ChunkUnavailableException {
- if (!isEmptyBlock(0, -1, 0)) {
+ if (!canMoveThrough(0, -1, 0)) {
if (y > getBlock(0, -1, 0).getY() + 0.5f) {
return true;
}
@@ -455,24 +485,28 @@ public class LiveEntity implements Cameraman {
public boolean hasValidPosition(Block head, boolean checkTop, boolean checkBottom) throws ChunkUnavailableException {
// Check if we're too near to the wall
- Block[] LRNeighbors = { head.getNeighbor(-1, 0, 0), head.getNeighbor(1, 0, 0) };
- for (Block n : LRNeighbors) {
- if (n.isEmpty()) {
- continue;
- }
- if (Math.abs(n.getX() - x) < 0.5) {
- return false;
- }
- }
- Block[] FBNeighbors = { head.getNeighbor(0, 0, -1), head.getNeighbor(0, 0, 1) };
- for (Block n : FBNeighbors) {
- if (n.isEmpty()) {
- continue;
- }
- if (Math.abs(n.getZ() - z) < 0.5) {
- return false;
- }
- }
+ /*
+ * Block[] LRNeighbors = { head.getNeighbor(-1, 0, 0),
+ * head.getNeighbor(1, 0, 0) };
+ * for (Block n : LRNeighbors) {
+ * if (!n.canMoveThrough()) {
+ * return false;
+ * }
+ * if (Math.abs(n.getX() - x) < 0.5) {
+ * return false;
+ * }
+ * }
+ * Block[] FBNeighbors = { head.getNeighbor(0, 0, -1),
+ * head.getNeighbor(0, 0, 1) };
+ * for (Block n : FBNeighbors) {
+ * if (!n.canMoveThrough()) {
+ * return false;
+ * }
+ * if (Math.abs(n.getZ() - z) < 0.5) {
+ * return false;
+ * }
+ * }
+ */
// if (checkBottom) {
// Block n = head.getNeighbor(0, -1, 0);
// if (Math.abs(n.getY() - y) < 0.5) {
@@ -485,7 +519,7 @@ public class LiveEntity implements Cameraman {
// return false;
// }
// }
- return head.isEmpty();
+ return head.canMoveThrough();
}
public boolean hasValidPosition() throws ChunkUnavailableException {
@@ -493,7 +527,7 @@ public class LiveEntity implements Cameraman {
Block underFoot = getBlock(0, -1, 0);
Block head = getBlock(0, (int) getHeight(), 0);
if (!inJump) {
- if (underFoot.isEmpty()) {
+ if (underFoot.canMoveThrough()) {
// In AIR while normal walking
if (isSneaking) {
// TODO Jumping while Sneaking fixes x,z while jumping
@@ -510,6 +544,9 @@ public class LiveEntity implements Cameraman {
if (hasValidPosition()) {
backupPosition();
isPositionChanged = true;
+ if (null != camera) {
+ camera.setDirty();
+ }
return true;
}
restorePosition();
@@ -557,8 +594,8 @@ public class LiveEntity implements Cameraman {
if (y < -20) {
// spawnAt((int) x, (int) z);
}
- pitch = Game.instance.camera.getPitch();
- yaw = Game.instance.camera.getYaw();
+ setPitch(Game.instance.camera.getPitch());
+ setYaw(Game.instance.camera.getYaw());
// Game.camera.setRoll(roll);
// saveTrace();
// if (isWalking && onGround) {
@@ -573,6 +610,9 @@ public class LiveEntity implements Cameraman {
if (isPositionChanged) {
isOrientationChanged = true;
notifyLocationUpdate();
+ if (null != camera) {
+ camera.setDirty();
+ }
}
}
@@ -634,8 +674,11 @@ public class LiveEntity implements Cameraman {
return y + getCameraLevel();
}
+ private BlockLocation cameraBlockLocation = new BlockLocation();
+
public BlockLocation getCameraBlockLocation() {
- return new BlockLocation(x, y, z);
+ cameraBlockLocation.set(x, y, z);
+ return cameraBlockLocation;
}
@Override
@@ -654,8 +697,25 @@ public class LiveEntity implements Cameraman {
Keyboard.setName("playerSneak", KeyEvent.VK_SHIFT);
Keyboard.setName("playerCrouch", KeyEvent.VK_CONTROL);
Keyboard.setName("playerRenderDistance", KeyEvent.VK_F4);
+ Keyboard.setName("playerInventory1", KeyEvent.VK_1);
+ Keyboard.setName("playerInventory2", KeyEvent.VK_2);
+ Keyboard.setName("playerInventory3", KeyEvent.VK_3);
+ Keyboard.setName("playerInventory4", KeyEvent.VK_4);
+ Keyboard.setName("playerInventory5", KeyEvent.VK_5);
+ Keyboard.setName("playerInventory6", KeyEvent.VK_6);
+ Keyboard.setName("playerInventory7", KeyEvent.VK_7);
+ Keyboard.setName("playerInventory8", KeyEvent.VK_8);
+ Keyboard.setName("playerInventory9", KeyEvent.VK_9);
+ Keyboard.setName("playerInventory0", KeyEvent.VK_0);
+ Keyboard.setName("playerInventoryToggle", KeyEvent.VK_E);
+ if (!isListeningControls) {
+ isListeningControls = true;
+ Keyboard.attach(this);
+ }
}
+ private boolean isListeningControls = false;
+
public void setId(int id) {
this.id = id;
}
@@ -671,4 +731,60 @@ public class LiveEntity implements Cameraman {
public void setConnectionId(int connectionId) {
this.connectionId = connectionId;
}
+
+ @Override
+ public void onKeyPressed(String name, KeyEvent e) {
+ if (name.equals("playerInventoryToggle")) {
+ inventory.toggleGUI();
+ }
+ if (name.equals("playerRenderDistance")) {
+ settings.renderDistance *= 2;
+ if (settings.renderDistance > 256) {
+ settings.renderDistance = 32;
+ }
+ }
+
+ }
+
+ @Override
+ public void onKeyReleased(String name, KeyEvent e) {
+
+ }
+
+ @Override
+ public MatrixCamera getCamera() {
+ return camera;
+ }
+
+ @Override
+ public void setCamera(MatrixCamera camera) {
+ this.camera = camera;
+ if (null != camera) {
+ // thirdPerson.attachTo(this.camera, false);
+ }
+ }
+
+ public float getPitch() {
+ return pitch;
+ }
+
+ public void setPitch(float pitch) {
+ this.pitch = pitch;
+ }
+
+ public float getYaw() {
+ return yaw;
+ }
+
+ public void setYaw(float yaw) {
+ this.yaw = yaw;
+ }
+
+ public float getRoll() {
+ return roll;
+ }
+
+ public void setRoll(float roll) {
+ this.roll = roll;
+ }
}
diff --git a/src/ru/olamedia/math/Frustum.java b/src/ru/olamedia/math/Frustum.java
index e127cc0..7fb1827 100644
--- a/src/ru/olamedia/math/Frustum.java
+++ b/src/ru/olamedia/math/Frustum.java
@@ -1,5 +1,7 @@
package ru.olamedia.math;
+import com.jogamp.opengl.math.geom.AABBox;
+
public class Frustum {
public Plane topPlane = new Plane();
public Plane bottomPlane = new Plane();
@@ -31,45 +33,48 @@ public class Frustum {
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 quickClassify(Plane p, AABBox box) {
+ final float[] low = box.getLow();
+ final float[] high = box.getHigh();
+ if (p.distance(low[0], low[1], low[2]) > 0.0f)
+ return (true);
+ if (p.distance(high[0], low[1], low[2]) > 0.0f)
+ return (true);
+ if (p.distance(low[0], high[1], low[2]) > 0.0f)
+ return (true);
+ if (p.distance(high[0], high[1], low[2]) > 0.0f)
+ return (true);
+ if (p.distance(low[0], low[1], high[2]) > 0.0f)
+ return (true);
+ if (p.distance(high[0], low[1], high[2]) > 0.0f)
+ return (true);
+ if (p.distance(low[0], high[1], high[2]) > 0.0f)
+ return (true);
+ if (p.distance(high[0], high[1], high[2]) > 0.0f)
+ return (true);
+
+ return (false);
+ }
+
+ /**
+ * Quick check to see if an orthogonal bounding box is inside the frustum
+ */
+ public final boolean isOutside(AABBox box) {
+ if (!quickClassify(leftPlane, box))
+ return true;
+// if (!quickClassify(rightPlane, box))
+// return true;
+// if (!quickClassify(topPlane, box))
+// return true;
+// if (!quickClassify(bottomPlane, box))
+// return true;
+// if (!quickClassify(nearPlane, box))
+// return true;
+// if (!quickClassify(farPlane, box))
+// return true;
+
+ // We make no attempt to determine whether it's fully inside or not.
+ return false;
}
private static final boolean isPointInside(Plane plane, Vector3f p) {
@@ -82,31 +87,6 @@ public class Frustum {
&& 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)
*
diff --git a/src/ru/olamedia/math/Vector.java b/src/ru/olamedia/math/Vector.java
new file mode 100644
index 0000000..08a31f7
--- /dev/null
+++ b/src/ru/olamedia/math/Vector.java
@@ -0,0 +1,5 @@
+package ru.olamedia.math;
+
+public class Vector {
+
+}
diff --git a/src/ru/olamedia/math/VectorUtil.java b/src/ru/olamedia/math/VectorUtil.java
new file mode 100644
index 0000000..304bc5e
--- /dev/null
+++ b/src/ru/olamedia/math/VectorUtil.java
@@ -0,0 +1,29 @@
+package ru.olamedia.math;
+
+public class VectorUtil {
+ private static float[] tmpVec = new float[3];
+
+ public static float dot(float[] vec1, float[] vec2) {
+ return (vec1[0] * vec2[0] + vec1[1] * vec2[1] + vec1[2] * vec2[2]);
+ }
+
+ public static void translate(float[] result, float[] vec, float distance) {
+ for (int i = 0; i < 3; i++) {
+ result[i] += vec[i] * distance;
+ }
+ }
+
+ public static void set(float[] result, float[] vec) {
+ for (int i = 0; i < 3; i++) {
+ result[i] = vec[i];
+ }
+ }
+
+ public static void cross(float[] vec1, float[] vec2) {
+ set(tmpVec, vec1);
+
+ vec1[0] = vec2[2] * tmpVec[1] - vec2[1] * tmpVec[2];
+ vec1[1] = vec2[0] * tmpVec[2] - vec2[2] * tmpVec[0];
+ vec1[2] = vec2[1] * tmpVec[0] - vec2[0] * tmpVec[1];
+ }
+}
diff --git a/src/ru/olamedia/olacraft/OlaCraft.java b/src/ru/olamedia/olacraft/OlaCraft.java
index b5b3234..2dd39f0 100644
--- a/src/ru/olamedia/olacraft/OlaCraft.java
+++ b/src/ru/olamedia/olacraft/OlaCraft.java
@@ -1,6 +1,6 @@
package ru.olamedia.olacraft;
public class OlaCraft {
- public static String version = "0.1.6";
+ public static String version = "0.1.7";
}
diff --git a/src/ru/olamedia/olacraft/game/Game.java b/src/ru/olamedia/olacraft/game/Game.java
index 0980505..a2bc05e 100644
--- a/src/ru/olamedia/olacraft/game/Game.java
+++ b/src/ru/olamedia/olacraft/game/Game.java
@@ -1,14 +1,10 @@
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 {
@@ -17,7 +13,7 @@ public class Game {
public static boolean isServerRunning = false;
public static GameServer server = new GameServer();
public static GameClient client = new GameClient();
- public static Timer timer = new Timer();
+ public static Timer fpsTimer = new Timer();
public MatrixCamera camera;
@@ -27,7 +23,6 @@ public class Game {
@SuppressWarnings("unused")
private int mode = 1;
private boolean isRunning = false;
- @SuppressWarnings("unused")
// player
public Player player;
@@ -50,7 +45,7 @@ public class Game {
}
player = new Player();
camera = new MatrixCamera();
- camera.attachTo(player);
+ camera.attachTo(player, true);
camera.setFov(90);
camera.pack();
// scene.registerLiveEntity(player);
@@ -81,7 +76,6 @@ public class Game {
}
public void tick() {
- timer.update();
}
@@ -99,8 +93,8 @@ public class Game {
}
}
- public float getDelta() {
- return (float) timer.getElapsedTime() / 1000;
+ public float getFrameDelta() {
+ return (float) fpsTimer.getElapsedTime() / 1000f;
}
}
diff --git a/src/ru/olamedia/olacraft/inventory/Inventory.java b/src/ru/olamedia/olacraft/inventory/Inventory.java
index 2ce843b..3076dfe 100644
--- a/src/ru/olamedia/olacraft/inventory/Inventory.java
+++ b/src/ru/olamedia/olacraft/inventory/Inventory.java
@@ -1,76 +1,402 @@
package ru.olamedia.olacraft.inventory;
-import ru.olamedia.olacraft.world.block.Block;
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GLContext;
+
+import com.jogamp.opengl.util.texture.Texture;
+
+import ru.olamedia.asset.SpriteRectangle;
+import ru.olamedia.game.GameFrame;
+import ru.olamedia.geom.ImmModeMesh;
+import ru.olamedia.input.MouseJail;
+import ru.olamedia.olacraft.game.Game;
import ru.olamedia.olacraft.world.blockStack.BlockStack;
+import ru.olamedia.olacraft.world.blockTypes.EmptyBlockType;
+import ru.olamedia.olacraft.world.blockTypes.GravelBlockType;
+import ru.olamedia.olacraft.world.blockTypes.WheatBlockType;
+import ru.olamedia.olacraft.world.blockTypes.stone.BrecciaStoneBlockType;
+import ru.olamedia.texture.TextureManager;
public class Inventory {
public static int BIND_NUM = 10;
- public BlockStack[] binded = new BlockStack[BIND_NUM];
+ public static int BACKPACK_NUM = 10 * 5;
+ public static int TOTAL_NUM = BIND_NUM + BACKPACK_NUM;
+ public BlockStack[] binded = new BlockStack[TOTAL_NUM];
public BlockStack selected;
- public int selectedId;
- private boolean isInventoryGUIOpen = false;
+ public int selectedId = 0;
+ private boolean isGUIOpened = false;
- public Inventory() {
+ private int[] bindedX = new int[TOTAL_NUM];
+ private int[] bindedY = new int[TOTAL_NUM];
+
+ public BlockStack picked = null;
+ public int pickedId = 0;
+
+ private ImmModeMesh bindedGUI;
+
+ public void pickHover(boolean half) {
+ System.out.println("pick hover " + MouseJail.instance.y);
+ int x = MouseJail.instance.x;
+ int y = MouseJail.instance.y;
+ for (int i = 0; i < TOTAL_NUM; i++) {
+ if (x >= bindedX[i] && x <= bindedX[i] + 32 && y >= bindedY[i] && y <= bindedY[i] + 32) {
+ if (binded[i].count > 0) {
+ int pickCount = binded[i].count;
+ if (pickCount > 1 && half) {
+ pickCount = pickCount / 2;
+ }
+ System.out.println("pick binded");
+ pickedId = i;
+ picked = binded[pickedId].get(pickCount);
+ }
+ }
+ }
}
- 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);
+ public void placePicked() {
+ if (null == picked) {
+ return;
+ }
+ int x = MouseJail.instance.x;
+ int y = MouseJail.instance.y;
+ for (int i = 0; i < TOTAL_NUM; i++) {
+ if (x >= bindedX[i] && x <= bindedX[i] + 32 && y >= bindedY[i] && y <= bindedY[i] + 32) {
+ if (picked.type.getClass().getName().equals(binded[i].type.getClass().getName())
+ || binded[i].count == 0) {
+ // same type or empty slot
+ binded[i].putStack(picked);
+ if (picked.count == 0) {
+ picked = null;
+ } else {
+ binded[pickedId] = picked; // place picked to hovered
+ picked = null;
+ }
+ } else {
+ // different types
+ // swap
+ binded[pickedId].putStack(picked);
+ picked = binded[pickedId];
+ binded[pickedId] = binded[i];
+ binded[i] = picked;
+ picked = null;
+ }
+ }
}
- 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);
+ public void putPickedBack() {
+ if (null != picked) {
+ binded[pickedId].putStack(picked); // put back
+ picked = null;
}
- if (key == Keyboard.KEY_2) {
- select(1);
+ }
+
+ public Inventory() {
+ for (int i = 0; i < TOTAL_NUM; i++) {
+ binded[i] = new BlockStack(new EmptyBlockType(), 0);
}
- if (key == Keyboard.KEY_3) {
- select(2);
+ binded[0].type = new WheatBlockType();
+ binded[0].count = 60;
+ binded[1].type = new BrecciaStoneBlockType();
+ binded[1].count = 60;
+ }
+
+ public void openGUI() {
+ isGUIOpened = true;
+ MouseJail.enable();
+ MouseJail.setActive(false);
+ MouseJail.disable();
+ }
+
+ public void buildMeshes() {
+ bindedGUI = ImmModeMesh.allocate(2 * 4 + BIND_NUM * 4);
+ bindedGUI.enableColor3();
+ bindedGUI.enableVertex2();
+ int x = 0 + GameFrame.getGLWidth() / 2 - width / 2;
+ int y = GameFrame.getGLHeight() - height - padding;
+ bindedGUI.glBegin(GL2.GL_QUADS);
+ {
+ bindedGUI.glColor3f(0.2f, 0.2f, 0.2f);
+ bindedGUI.glRectf(x, y, x + width, y + height);
+ for (int i = 0; i < BIND_NUM; i++) {
+ bindedX[i] = x + padding + spacing * i + 34 * i + 1;
+ bindedY[i] = y + padding + 1;
+ int fx = x + padding + spacing * i + 34 * i;
+ int fy = y + padding;
+ // left
+ bindedGUI.glColor3f(0.0f, 0.0f, 0.0f);
+ bindedGUI.glRectf(fx, fy, fx + spacing / 2, fy + 34);
+ // right
+ bindedGUI.glColor3f(0.5f, 0.5f, 0.5f);
+ bindedGUI.glRectf(fx + 33, fy, fx + 33 + spacing / 2, fy + 34);
+ // top
+ bindedGUI.glColor3f(0.2f, 0.2f, 0.2f);
+ bindedGUI.glRectf(fx, fy, fx + 34, fy + spacing / 2);
+ // bottom
+ bindedGUI.glColor3f(0.3f, 0.3f, 0.3f);
+ bindedGUI.glRectf(fx, fy + 33, fx + 34, fy + 33 + spacing / 2);
+ bindedGUI.glColor3f(0.6f, 0.6f, 0.6f);
+ bindedGUI.glRectf(fx + 1, fy + 1, fx + 1 + 32, fy + 1 + 32);
+ }
+ // frame
+ bindedGUI.glColor3f(0.2f, 0.2f, 0.2f);
+ int fx = x + padding + spacing * selectedId + 34 * selectedId;
+ int fy = y + padding;
+ bindedGUI.glColor3f(15f / 15f, 6f / 15f, 0f);
+ bindedGUI.glRectf(fx, fy, fx + 32 + 2, fy + 32 + 2);
+ bindedGUI.glColor3f(0.8f, 0.8f, 0.8f);
+ bindedGUI.glRectf(fx + 1, fy + 1, fx + 1 + 32, fy + 1 + 32);
}
- if (key == Keyboard.KEY_4) {
- select(3);
+ bindedGUI.glEnd();
+ }
+
+ public BlockStack getSelectedBlockStack() {
+ return binded[selectedId];
+ }
+
+ /**
+ *
+ */
+ public void putBlockStack(BlockStack external) {
+ System.out.println("put stack " + external.type.getClass().getName());
+ // looking for same type
+ int i = 0;
+ while (i < TOTAL_NUM && external.count > 0) {
+ if (binded[i].type.getClass().getName() == external.type.getClass().getName()) {
+ System.out.println("append stack");
+ binded[i].putStack(external);
+ }
+ i++;
}
- if (key == Keyboard.KEY_5) {
- select(4);
+ i = 0;
+ // looking for empty slot
+ while (i < TOTAL_NUM && external.count > 0) {
+ if (binded[i].count == 0) { // empty
+ System.out.println("replace stack");
+ binded[i].putStack(external);
+ }
+ i++;
}
- if (key == Keyboard.KEY_6) {
- select(5);
+ }
+
+ public void closeGUI() {
+ isGUIOpened = false;
+ MouseJail.enable();
+ MouseJail.setActive(true);
+ if (null != picked) {
+ putPickedBack();
}
- if (key == Keyboard.KEY_7) {
- select(6);
+ }
+
+ private int spacing = 2;
+ private int padding = spacing / 2 + 1;
+ private int width = 34 * BIND_NUM + padding * 2 + spacing * (BIND_NUM - 1);
+ private int height = 34 + padding * 2;
+
+ public void renderGUIClosed() {
+ // render bottom line
+ GL2 gl = GLContext.getCurrentGL().getGL2();
+
+ int x = 0 + GameFrame.getGLWidth() / 2 - width / 2;
+ int y = GameFrame.getGLHeight() - height - padding;
+ /*
+ * gl.glColor3f(0.8f, 0.8f, 0.8f);
+ * gl.glRecti(x, y, x + width, y + height);
+ * for (int i = 0; i < BIND_NUM; i++) {
+ * bindedX[i] = x + padding + spacing * i + 32 * i + 1;
+ * bindedY[i] = y + padding + 1;
+ * int fx = x + padding + spacing * i + 32 * i;
+ * int fy = y + padding;
+ * // left
+ * gl.glColor3f(0.6f, 0.6f, 0.6f);
+ * gl.glRecti(fx, fy, fx + spacing / 2, fy + 32);
+ * // right
+ * gl.glColor3f(0.5f, 0.5f, 0.5f);
+ * gl.glRecti(fx, fy, fx + spacing / 2, fy + 32);
+ * // top
+ * gl.glColor3f(0.4f, 0.4f, 0.4f);
+ * gl.glRecti(fx, fy, fx + 32, fy + spacing / 2);
+ * // bottom
+ * gl.glColor3f(0.3f, 0.3f, 0.3f);
+ * gl.glRecti(fx, fy, fx + 32, fy + spacing / 2);
+ * }
+ */
+ if (null != bindedGUI) {
+ bindedGUI.draw();
}
- if (key == Keyboard.KEY_8) {
- select(7);
+
+ gl.glEnable(GL2.GL_TEXTURE_2D);
+ for (int i = 0; i < BIND_NUM; i++) {
+ BlockStack stack = binded[i];
+ if (null != stack && !(stack.type instanceof EmptyBlockType) && stack.count > 0 && !stack.hidden) {
+ Texture tex = TextureManager.getSprite(stack.type.getStackTextureFile());
+ SpriteRectangle uv = TextureManager.getSpriteOffset(stack.type.getStackTextureFile());
+ 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 sx = x + padding + spacing * i + 34 * i + 1;
+ int sy = y + padding + 1;
+ gl.glTexCoord4f(uv.topLeft.x, uv.topLeft.y, uv.bottomRight.x, uv.bottomRight.y);
+ gl.glBegin(GL2.GL_QUADS);
+ {
+ gl.glTexCoord2f(uv.topLeft.x, uv.topLeft.y);
+ gl.glVertex2f(sx, sy);
+ gl.glTexCoord2f(uv.topLeft.x, uv.bottomRight.y);
+ gl.glVertex2f(sx, sy + 32);
+ gl.glTexCoord2f(uv.bottomRight.x, uv.bottomRight.y);
+ gl.glVertex2f(sx + 32, sy + 32);
+ gl.glTexCoord2f(uv.bottomRight.x, uv.topLeft.y);
+ gl.glVertex2f(sx + 32, sy);
+ }
+ gl.glEnd();
+ // if (stack.count > 0) {
+ gl.glColor4f(1, 1, 1, 1);
+ Game.client.getScene().viewport.drawText("" + stack.count, sx, GameFrame.getGLHeight() - sy - 10);
+ // }
+ }
}
- if (key == Keyboard.KEY_9) {
- select(8);
+ if (null != picked) {
+ // draw picked
+ BlockStack stack = picked;
+ if (null != stack && !(stack.type instanceof EmptyBlockType) && stack.count > 0) {
+ Texture tex = TextureManager.getSprite(stack.type.getStackTextureFile());
+ SpriteRectangle uv = TextureManager.getSpriteOffset(stack.type.getStackTextureFile());
+ 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 sx = MouseJail.instance.x - 16;
+ int sy = MouseJail.instance.y - 16;
+ gl.glTexCoord4f(uv.topLeft.x, uv.topLeft.y, uv.bottomRight.x, uv.bottomRight.y);
+ gl.glBegin(GL2.GL_QUADS);
+ {
+ gl.glTexCoord2f(uv.topLeft.x, uv.topLeft.y);
+ gl.glVertex2f(sx, sy);
+ gl.glTexCoord2f(uv.topLeft.x, uv.bottomRight.y);
+ gl.glVertex2f(sx, sy + 32);
+ gl.glTexCoord2f(uv.bottomRight.x, uv.bottomRight.y);
+ gl.glVertex2f(sx + 32, sy + 32);
+ gl.glTexCoord2f(uv.bottomRight.x, uv.topLeft.y);
+ gl.glVertex2f(sx + 32, sy);
+ }
+ gl.glEnd();
+ // if (stack.count > 0) {
+ gl.glColor4f(1, 1, 1, 1);
+ Game.client.getScene().viewport.drawText("" + stack.count, sx, GameFrame.getGLHeight() - sy - 10);
+ // }
+ }
}
- if (key == Keyboard.KEY_0) {
- select(9);
+ gl.glDisable(GL2.GL_TEXTURE_2D);
+ }
+
+ public void renderGUIOpened() {
+ GL2 gl = GLContext.getCurrentGL().getGL2();
+
+ int oHeight = 300;
+ int x = 0 + GameFrame.getGLWidth() / 2 - width / 2;
+ int y = GameFrame.getGLHeight() - oHeight - height - padding - 32;
+ gl.glColor3f(0.8f, 0.8f, 0.8f);
+ gl.glRecti(x, y, x + width, y + oHeight);
+ for (int ni = BIND_NUM; ni < BIND_NUM + BACKPACK_NUM; ni++) {
+ int dy = ni / 10;
+ int dx = ni - dy * 10;
+ bindedX[ni] = x + padding + spacing * dx + 32 * dx + 1;
+ bindedY[ni] = y + padding + spacing * dy + 32 * dy + 1;
+ int fx = x + padding + spacing * dx + 32 * dx;
+ int fy = y + padding + spacing * dy + 32 * dy;
+ // left
+ gl.glColor3f(0.6f, 0.6f, 0.6f);
+ gl.glRecti(fx, fy, fx + spacing / 2, fy + 32);
+ // right
+ gl.glColor3f(0.5f, 0.5f, 0.5f);
+ gl.glRecti(fx, fy, fx + spacing / 2, fy + 32);
+ // top
+ gl.glColor3f(0.4f, 0.4f, 0.4f);
+ gl.glRecti(fx, fy, fx + 32, fy + spacing / 2);
+ // bottom
+ gl.glColor3f(0.3f, 0.3f, 0.3f);
+ gl.glRecti(fx, fy, fx + 32, fy + spacing / 2);
}
- if (key == Keyboard.KEY_E) {
- isInventoryGUIOpen = !isInventoryGUIOpen;
+ gl.glColor3f(0.2f, 0.2f, 0.2f);
+ int fx = x + padding + spacing * selectedId + 32 * selectedId;
+ int fy = y + padding;
+ gl.glRecti(fx, fy, fx + 32 + 2, fy + 32 + 2);
+ gl.glEnable(GL2.GL_TEXTURE_2D);
+ for (int ni = BIND_NUM; ni < BIND_NUM + BACKPACK_NUM; ni++) {
+ int dy = ni / 10;
+ int dx = ni - dy * 10;
+ bindedX[ni] = x + padding + spacing * dx + 32 * dx + 1;
+ bindedY[ni] = y + padding + spacing * dy + 32 * dy + 1;
+ int sx = x + padding + spacing * dx + 32 * dx + 1;
+ int sy = y + padding + spacing * dy + 32 * dy + 1;
+ BlockStack stack = binded[ni];
+ if (null != stack && !(stack.type instanceof EmptyBlockType) && stack.count > 0 && !stack.hidden) {
+ Texture tex = TextureManager.getSprite(stack.type.getStackTextureFile());
+ SpriteRectangle uv = TextureManager.getSpriteOffset(stack.type.getStackTextureFile());
+ 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);
+ gl.glTexCoord4f(uv.topLeft.x, uv.topLeft.y, uv.bottomRight.x, uv.bottomRight.y);
+ gl.glBegin(GL2.GL_QUADS);
+ {
+ gl.glTexCoord2f(uv.topLeft.x, uv.topLeft.y);
+ gl.glVertex2f(sx, sy);
+ gl.glTexCoord2f(uv.topLeft.x, uv.bottomRight.y);
+ gl.glVertex2f(sx, sy + 32);
+ gl.glTexCoord2f(uv.bottomRight.x, uv.bottomRight.y);
+ gl.glVertex2f(sx + 32, sy + 32);
+ gl.glTexCoord2f(uv.bottomRight.x, uv.topLeft.y);
+ gl.glVertex2f(sx + 32, sy);
+ }
+ gl.glEnd();
+ // if (stack.count > 0) {
+ gl.glColor4f(1, 1, 1, 1);
+ Game.client.getScene().viewport.drawText("" + stack.count, sx, GameFrame.getGLHeight() - sy - 10);
+ // }
+ }
}
+ gl.glDisable(GL2.GL_TEXTURE_2D);
+ }
+ public void renderGUI() {
+ if (isGUIOpened) {
+ renderGUIOpened();
+ } else {
+ if (null != picked) {
+ putPickedBack();
+ }
+ }
+ renderGUIClosed();
}
public void select(int i) {
+ selectedId = i;
selected = binded[i];
+ buildMeshes();
+ }
+
+ public void toggleGUI() {
+ if (isGUIOpened) {
+ closeGUI();
+ } else {
+ openGUI();
+ }
+ buildMeshes();
+ }
+
+ public boolean isGUIOpened() {
+ return isGUIOpened;
+ }
+
+ public void click(boolean half) {
+ if (null == picked) {
+ pickHover(half);
+ } else {
+ placePicked();
+ }
+ buildMeshes();
}
}
diff --git a/src/ru/olamedia/olacraft/modelAnimator/Arm.java b/src/ru/olamedia/olacraft/modelAnimator/Arm.java
new file mode 100644
index 0000000..eeeea77
--- /dev/null
+++ b/src/ru/olamedia/olacraft/modelAnimator/Arm.java
@@ -0,0 +1,27 @@
+package ru.olamedia.olacraft.modelAnimator;
+
+public class Arm extends BoneSet {
+ // 左腕 - левая рука
+ // 左ひじ - левый локоть
+ // 左手首 - левое запястье
+ // 左袖 - левый рукав
+ public Bone top;
+ public Bone elbow;
+ public Bone wrist;
+
+ public Arm() {
+ super(3);
+ top = new Bone();
+ elbow = new Bone();
+ wrist = new Bone();
+ setChild(0, top);
+ setChild(1, elbow);
+ setChild(2, wrist);
+ }
+
+ public void setNamePrefix(String prefix) {
+ top.setName(prefix + top.getName());
+ elbow.setName(prefix + elbow.getName());
+ wrist.setName(prefix + wrist.getName());
+ }
+}
diff --git a/src/ru/olamedia/olacraft/modelAnimator/Bone.java b/src/ru/olamedia/olacraft/modelAnimator/Bone.java
new file mode 100644
index 0000000..0bda33d
--- /dev/null
+++ b/src/ru/olamedia/olacraft/modelAnimator/Bone.java
@@ -0,0 +1,215 @@
+package ru.olamedia.olacraft.modelAnimator;
+
+import java.util.Random;
+
+public class Bone implements ISkeletonNode {
+ private String name;
+ /**
+ * @return the name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @param name the name to set
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ private float speed = 1f;
+ private float yaw;
+ private float pitch;
+ private float roll;
+ private float yawCorrection = 0;
+ private float pitchCorrection = 0;
+ private float rollCorrection = 0;
+ @SuppressWarnings("unused")
+ private boolean isAnglesModified = false;
+ private boolean isMatrixModified = false;
+
+ @Override
+ public int getChildrenCount() {
+ return 0;
+ }
+
+ @Override
+ public Bone getChild(int i) {
+ return null;
+ }
+
+ private void updateAngles() {
+ if (isMatrixModified) {
+
+ }
+ }
+
+ /*
+ * private void updateMatrix() {
+ * if (isAnglesModified) {
+ *
+ * }
+ * }
+ */
+
+ public float getSpeed() {
+ return speed;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see ru.olamedia.olacraft.modelAnimator.ISkeletonNode#setSpeed(float)
+ */
+ @Override
+ public void setSpeed(float speed) {
+ this.speed = speed;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * ru.olamedia.olacraft.modelAnimator.ISkeletonNode#copyOrientation(ru.olamedia
+ * .olacraft.modelAnimator.Bone)
+ */
+ @Override
+ public void copyOrientation(ISkeletonNode node) {
+ final Bone b = (Bone) node;
+ setPitch(b.getPitch());
+ setPitchCorrection(b.getPitchCorrection());
+ setYaw(b.getYaw());
+ setYawCorrection(b.getYawCorrection());
+ setRoll(b.getRoll());
+ setRollCorrection(b.getRollCorrection());
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * ru.olamedia.olacraft.modelAnimator.ISkeletonNode#setDelta(ru.olamedia
+ * .olacraft.modelAnimator.Bone, ru.olamedia.olacraft.modelAnimator.Bone,
+ * float)
+ */
+ @Override
+ public void setDelta(ISkeletonNode firstNode, ISkeletonNode secondNode, float delta) {
+ final Bone first = (Bone) firstNode;
+ final Bone second = (Bone) secondNode;
+ final float dPitch = second.getPitch() - first.getPitch();
+ setPitch(first.getPitch() + dPitch * getSpeed() * delta);
+ final float dYaw = second.getYaw() - first.getYaw();
+ setYaw(first.getYaw() + dYaw * getSpeed() * delta);
+ final float dRoll = second.getRoll() - first.getRoll();
+ setRoll(first.getRoll() + dRoll * getSpeed() * delta);
+ }
+
+ public float getYaw() {
+ updateAngles();
+ return yaw;
+ }
+
+ public float getCorrectedYaw() {
+ return getYawCorrection() + getYaw();
+ }
+
+ public void setYaw(float yaw) {
+ this.yaw = yaw;
+ isAnglesModified = true;
+ }
+
+ public float getPitch() {
+ updateAngles();
+ return pitch;
+ }
+
+ public float getCorrectedPitch() {
+ return getPitchCorrection() + getPitch();
+ }
+
+ public void setPitch(float pitch) {
+ this.pitch = pitch;
+ isAnglesModified = true;
+ }
+
+ public float getRoll() {
+ updateAngles();
+ return roll;
+ }
+
+ public float getCorrectedRoll() {
+ return getRollCorrection() + getRoll();
+ }
+
+ public void setRoll(float roll) {
+ this.roll = roll;
+ isAnglesModified = true;
+ }
+
+ private final float yawRand = 5f;
+ private final float pitchRand = 1f;
+ private final float rollRand = 5f;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see ru.olamedia.olacraft.modelAnimator.ISkeletonNode#reset()
+ */
+ @Override
+ public void reset() {
+ yaw = 0;
+ pitch = 0;
+ roll = 0;
+ }
+
+ private float nextFloatDelta(Random rand, Random prev, float delta) {
+ final float first = prev.nextFloat();
+ final float second = rand.nextFloat();
+ return first + (second - first) * delta;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * ru.olamedia.olacraft.modelAnimator.ISkeletonNode#randomize(java.util.
+ * Random, java.util.Random, float)
+ */
+ @Override
+ public void randomize(Random rand, Random prev, float delta) {
+ // delta = 1;
+ setYaw(yaw + (nextFloatDelta(rand, prev, delta) - 0.5f) * yawRand);
+ setPitch(pitch + (nextFloatDelta(rand, prev, delta) - 0.5f) * pitchRand);
+ setRoll(roll + (nextFloatDelta(rand, prev, delta) - 0.5f) * rollRand);
+ }
+
+ public float getYawCorrection() {
+ return yawCorrection;
+ }
+
+ public void setYawCorrection(float yawCorrection) {
+ this.yawCorrection = yawCorrection;
+ }
+
+ public float getPitchCorrection() {
+ return pitchCorrection;
+ }
+
+ public void setPitchCorrection(float pitchCorrection) {
+ this.pitchCorrection = pitchCorrection;
+ }
+
+ public float getRollCorrection() {
+ return rollCorrection;
+ }
+
+ public void setRollCorrection(float rollCorrection) {
+ this.rollCorrection = rollCorrection;
+ }
+
+ @Override
+ public void setChild(int i, ISkeletonNode b) {
+
+ }
+}
diff --git a/src/ru/olamedia/olacraft/modelAnimator/BoneSet.java b/src/ru/olamedia/olacraft/modelAnimator/BoneSet.java
new file mode 100644
index 0000000..0e3ce2c
--- /dev/null
+++ b/src/ru/olamedia/olacraft/modelAnimator/BoneSet.java
@@ -0,0 +1,163 @@
+package ru.olamedia.olacraft.modelAnimator;
+
+import java.util.Iterator;
+import java.util.Random;
+
+public class BoneSet implements ISkeletonNode, Iterable<Bone> {
+
+ private class BonesIterator implements Iterator<Bone> {
+ private BoneSet set;
+ private Iterator<Bone> childIterator = null;
+ private int current = 0;
+
+ public BonesIterator(BoneSet boneSet) {
+ set = boneSet;
+ }
+
+ @Override
+ public boolean hasNext() {
+ if (null == childIterator) {
+ return current < set.getChildrenCount();
+ } else {
+ return childIterator.hasNext() || current < set.getChildrenCount();
+ }
+ }
+
+ private boolean nextIsChild;
+
+ @Override
+ public Bone next() {
+ if (null == childIterator) {
+ ISkeletonNode node = set.getChild(current);
+ if (node instanceof Bone) {
+ Bone b = (Bone) node;
+ current++;
+ return b;
+ } else if (node instanceof BoneSet) {
+ childIterator = ((BoneSet) node).iterator();
+ current++;
+ }
+ }
+ if (null != childIterator) {
+ nextIsChild = childIterator.hasNext();
+ if (nextIsChild) {
+ Bone b = childIterator.next();
+ return b;
+ }
+ if (!nextIsChild) {
+ childIterator = null;
+ }
+ }
+ if (current < set.getChildrenCount()) {
+ return next();
+ }
+ return null;
+ }
+
+ @Override
+ public void remove() {
+
+ }
+
+ }
+
+ public BoneSet(int bonesCount) {
+ nodes = new ISkeletonNode[bonesCount];
+ for (int i = 0; i < bonesCount; i++) {
+ // bones[i] = new Bone();
+ }
+ }
+
+ private ISkeletonNode[] nodes;
+ private String name;
+
+ /**
+ * @return the name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @param name
+ * the name to set
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public int getChildrenCount() {
+ return nodes.length;
+ }
+
+ public ISkeletonNode getChild(int i) {
+ return nodes[i];
+ }
+
+ @Override
+ public void setSpeed(float speed) {
+ for (ISkeletonNode b : nodes) {
+ b.setSpeed(speed);
+ }
+ }
+
+ @Override
+ public void copyOrientation(ISkeletonNode bs) {
+ for (int i = 0; i < nodes.length; i++) {
+ nodes[i].copyOrientation(bs.getChild(i));
+ }
+ }
+
+ @Override
+ public void setDelta(ISkeletonNode first, ISkeletonNode second, float delta) {
+ for (int i = 0; i < nodes.length; i++) {
+ nodes[i].setDelta(first.getChild(i), second.getChild(i), delta);
+ }
+ }
+
+ @Override
+ public void reset() {
+ for (int i = 0; i < nodes.length; i++) {
+ nodes[i].reset();
+ }
+ }
+
+ @Override
+ public void randomize(Random rand, Random prev, float delta) {
+ for (int i = 0; i < nodes.length; i++) {
+ nodes[i].randomize(rand, prev, delta);
+ }
+ }
+
+ @Override
+ public void setChild(int i, ISkeletonNode node) {
+ nodes[i] = node;
+ }
+
+ @Override
+ public Iterator<Bone> iterator() {
+ return new BonesIterator(this);
+ }
+
+ public int getBoneCount() {
+ int n = 0;
+ Iterator<Bone> it = iterator();
+ while (it.hasNext()) {
+ it.next();
+ n++;
+ }
+ return n;
+ }
+
+ public Bone getBone(int i) {
+ int j = 0;
+ Iterator<Bone> it = iterator();
+ Bone b = null;
+ while (it.hasNext() && j <= i) {
+ b = it.next();
+ j++;
+ }
+ return b;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/modelAnimator/ISkeletonNode.java b/src/ru/olamedia/olacraft/modelAnimator/ISkeletonNode.java
new file mode 100644
index 0000000..2b1b28a
--- /dev/null
+++ b/src/ru/olamedia/olacraft/modelAnimator/ISkeletonNode.java
@@ -0,0 +1,26 @@
+package ru.olamedia.olacraft.modelAnimator;
+
+import java.util.Random;
+
+public interface ISkeletonNode {
+ public void setName(String name);
+
+ public String getName();
+
+ public ISkeletonNode getChild(int i);
+
+ public void setChild(int i, ISkeletonNode b);
+
+ public int getChildrenCount();
+
+ public abstract void setSpeed(float speed);
+
+ public abstract void copyOrientation(ISkeletonNode b);
+
+ public abstract void setDelta(ISkeletonNode first, ISkeletonNode second, float delta);
+
+ public abstract void reset();
+
+ public abstract void randomize(Random rand, Random prev, float delta);
+
+} \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/modelAnimator/Leg.java b/src/ru/olamedia/olacraft/modelAnimator/Leg.java
new file mode 100644
index 0000000..0f9000d
--- /dev/null
+++ b/src/ru/olamedia/olacraft/modelAnimator/Leg.java
@@ -0,0 +1,27 @@
+package ru.olamedia.olacraft.modelAnimator;
+
+public class Leg extends BoneSet {
+
+ public Bone top;
+ public Bone knee;
+ public Bone foot;
+
+ public Leg() {
+ super(3);
+ top = new Bone();
+ knee = new Bone();
+ foot = new Bone();
+ setChild(0, top);
+ setChild(1, knee);
+ setChild(2, foot);
+ top.setName("Top");
+ knee.setName("Knee");
+ foot.setName("Foot");
+ }
+
+ public void setNamePrefix(String prefix) {
+ top.setName(prefix + top.getName());
+ knee.setName(prefix + knee.getName());
+ foot.setName(prefix + foot.getName());
+ }
+}
diff --git a/src/ru/olamedia/olacraft/modelAnimator/ModelAnimator.java b/src/ru/olamedia/olacraft/modelAnimator/ModelAnimator.java
new file mode 100644
index 0000000..712cbd1
--- /dev/null
+++ b/src/ru/olamedia/olacraft/modelAnimator/ModelAnimator.java
@@ -0,0 +1,324 @@
+package ru.olamedia.olacraft.modelAnimator;
+
+public class ModelAnimator {
+ private boolean isWalking = false;
+ private boolean isCrawling = false;
+ private boolean isCrouching = false;
+ private boolean isJumping = false;
+ private boolean isFalling = false;
+ private boolean isStrafingLeft = false;
+ private boolean isStrafingRight = false;
+ private boolean isMovingForward = false;
+ private boolean isMovingBackward = false;
+ private float delta;
+
+ private Skeleton currentOrientation = new Skeleton();
+ public Skeleton finalOrientation = new Skeleton();
+ public Skeleton deltaOrientation = new Skeleton();
+
+ public ModelAnimator() {
+ generateFrames();
+ }
+
+ public boolean isWalking() {
+ return isWalking;
+ }
+
+ public void setWalking(boolean isWalking) {
+ this.isWalking = isWalking;
+ }
+
+ public boolean isCrawling() {
+ return isCrawling;
+ }
+
+ public void setCrawling(boolean isCrawling) {
+ this.isCrawling = isCrawling;
+ }
+
+ public boolean isCrouching() {
+ return isCrouching;
+ }
+
+ public void setCrouching(boolean isCrouching) {
+ this.isCrouching = isCrouching;
+ }
+
+ public boolean isJumping() {
+ return isJumping;
+ }
+
+ public void setJumping(boolean isJumping) {
+ this.isJumping = isJumping;
+ }
+
+ public boolean isFalling() {
+ return isFalling;
+ }
+
+ public void setFalling(boolean isFalling) {
+ this.isFalling = isFalling;
+ }
+
+ public boolean isStrafingLeft() {
+ return isStrafingLeft;
+ }
+
+ public void setStrafingLeft(boolean isStrafingLeft) {
+ this.isStrafingLeft = isStrafingLeft;
+ }
+
+ public boolean isStrafingRight() {
+ return isStrafingRight;
+ }
+
+ public void setStrafingRight(boolean isStrafingRight) {
+ this.isStrafingRight = isStrafingRight;
+ }
+
+ public boolean isMovingForward() {
+ return isMovingForward;
+ }
+
+ public void setMovingForward(boolean isMovingForward) {
+ this.isMovingForward = isMovingForward;
+ }
+
+ public boolean isMovingBackward() {
+ return isMovingBackward;
+ }
+
+ public void setMovingBackward(boolean isMovingBackward) {
+ this.isMovingBackward = isMovingBackward;
+ }
+
+ public float getDelta() {
+ return delta;
+ }
+
+ public void setDelta(float delta) {
+ this.delta = delta;
+ }
+
+ // Frames
+ private Skeleton walkLeftLegForward = new Skeleton();
+ private Skeleton walkRightLegForward = new Skeleton();
+ private Skeleton standLeftLegApart = new Skeleton();
+ private Skeleton standRightLegApart = new Skeleton();
+
+ private void generateFrames() {
+ // walkLeftLegForward.leftLeg.top.setYaw(-5);
+ walkLeftLegForward.skirtFrontLeft.setPitch(30);
+ walkLeftLegForward.skirtFrontLeft.setYaw(30);
+ walkLeftLegForward.skirtFrontRight.setPitch(-5);
+ walkRightLegForward.skirtFrontRight.setPitch(30);
+ walkRightLegForward.skirtFrontRight.setYaw(-30);
+ walkRightLegForward.skirtFrontLeft.setPitch(-5);
+ // walkLeftLegForward.skirtFrontLeft.setYaw(40);
+ // walkLeftLegForward.skirtFrontLeft.setRoll(40);
+ // walkLeftLegForward.rightLeg.top.setYaw(5);
+ walkLeftLegForward.leftLeg.top.setPitch(35);
+ walkLeftLegForward.leftLeg.knee.setPitch(-30);
+ walkLeftLegForward.leftLeg.foot.setPitch(25);
+ walkLeftLegForward.leftLeg.top.setYaw(-10);
+ walkLeftLegForward.leftLeg.knee.setYaw(-10);
+ walkLeftLegForward.rightLeg.top.setYaw(-10);
+ walkLeftLegForward.rightLeg.knee.setYaw(-10);
+ walkLeftLegForward.rightLeg.top.setPitch(-10);
+ walkLeftLegForward.rightLeg.knee.setPitch(-15);
+ walkLeftLegForward.rightLeg.foot.setPitch(8);
+ /*walkLeftLegForward.leftLeg.top.setPitch(59);
+ walkLeftLegForward.leftLeg.top.setYaw(-9);
+ walkLeftLegForward.leftLeg.top.setRoll(10);
+ walkLeftLegForward.leftLeg.knee.setPitch(-100);
+ walkLeftLegForward.leftLeg.knee.setYaw(-9);*/
+ walkRightLegForward.leftLeg.copyOrientation(walkLeftLegForward.rightLeg);
+ walkRightLegForward.rightLeg.copyOrientation(walkLeftLegForward.leftLeg);
+ walkRightLegForward.rightLeg.top.setYaw(10);
+ walkRightLegForward.rightLeg.knee.setYaw(10);
+ walkRightLegForward.leftLeg.top.setYaw(10);
+ walkRightLegForward.leftLeg.knee.setYaw(10);
+
+ walkLeftLegForward.waist.setYaw(18);
+ walkRightLegForward.waist.setYaw(-18);
+ walkLeftLegForward.shoulders.setYaw(-10);
+ walkLeftLegForward.shoulders.setRoll(-4);
+ walkRightLegForward.shoulders.setYaw(10);
+ walkRightLegForward.shoulders.setRoll(4);
+ // ARMS
+ walkLeftLegForward.rightArm.top.setPitch(15);
+ walkLeftLegForward.rightArm.top.setRoll(-7);
+ walkLeftLegForward.rightArm.elbow.setYaw(-90);
+ walkLeftLegForward.rightArm.wrist.setYaw(0);
+ walkLeftLegForward.rightArm.wrist.setPitch(0);
+ walkLeftLegForward.rightArm.wrist.setRoll(50);
+ walkLeftLegForward.leftArm.wrist.setRoll(30);
+ walkLeftLegForward.leftArm.top.setPitch(-14);
+ walkLeftLegForward.leftArm.top.setYaw(-2);
+ walkLeftLegForward.leftArm.top.setRoll(17);
+ // walkRightLegForward.leftArm.elbow.setRoll(90);
+ walkRightLegForward.leftArm.top.setPitch(15);
+ walkRightLegForward.leftArm.top.setRoll(7);
+ walkRightLegForward.leftArm.elbow.setYaw(90);
+ walkRightLegForward.leftArm.wrist.setYaw(0);
+ walkRightLegForward.leftArm.wrist.setPitch(0);
+ walkRightLegForward.leftArm.wrist.setRoll(-50);
+ walkRightLegForward.rightArm.wrist.setRoll(-30);
+ walkRightLegForward.rightArm.top.setPitch(-14);
+ walkRightLegForward.rightArm.top.setYaw(2);
+ walkRightLegForward.rightArm.top.setRoll(-17);
+
+ standLeftLegApart.leftLeg.top.setRoll(-10);
+ standLeftLegApart.leftLeg.foot.setYaw(-10);
+ standRightLegApart.rightLeg.top.setRoll(10);
+ standRightLegApart.rightLeg.foot.setYaw(10);
+ }
+
+ private boolean areLegsApart = false;
+ private boolean areLegsTogether = true;
+ private boolean isLeftLegAhead = false;
+ private boolean isLegReturning = false;
+ private float walkStepTimer = 0;
+ private float walkStepTime = 0.25f;
+ private float standTimer = 0;
+ private float standTime = 3f;
+ private boolean isStandLeftLegApart = true;
+
+ private void standTick() {
+ standTimer += getDelta();
+ if (standTimer >= standTime) {
+ // Switch legs
+ standTimer -= standTime;
+ isStandLeftLegApart = !isStandLeftLegApart;
+ }
+ }
+
+ private void setLegsStanding() {
+ if (isStandLeftLegApart) {
+ finalOrientation.leftLeg.copyOrientation(standLeftLegApart.leftLeg);
+ finalOrientation.rightLeg.copyOrientation(standLeftLegApart.rightLeg);
+ } else {
+ finalOrientation.leftLeg.copyOrientation(standRightLegApart.leftLeg);
+ finalOrientation.rightLeg.copyOrientation(standRightLegApart.rightLeg);
+ }
+ }
+
+ private void walkTick() {
+ walkStepTimer += getDelta();
+ if (walkStepTimer >= walkStepTime) {
+ // Switch step, legs
+ walkStepTimer -= walkStepTime;
+ if (areLegsTogether) {
+ areLegsTogether = false;
+ areLegsApart = true;
+ isLeftLegAhead = !isLeftLegAhead;
+ isLegReturning = false;
+ } else {
+ areLegsTogether = true;
+ areLegsApart = false;
+ isLegReturning = true;
+ }
+ }
+ }
+
+ private void setLegsWalking() {
+ if (isLeftLegAhead) {
+ finalOrientation.leftLeg.copyOrientation(walkLeftLegForward.leftLeg);
+ finalOrientation.rightLeg.copyOrientation(walkLeftLegForward.rightLeg);
+ finalOrientation.waist.copyOrientation(walkLeftLegForward.waist);
+ finalOrientation.shoulders.copyOrientation(walkLeftLegForward.shoulders);
+ finalOrientation.leftArm.copyOrientation(walkLeftLegForward.leftArm);
+ finalOrientation.rightArm.copyOrientation(walkLeftLegForward.rightArm);
+ finalOrientation.skirtFrontLeft.copyOrientation(walkLeftLegForward.skirtFrontLeft);
+ finalOrientation.skirtFrontRight.copyOrientation(walkLeftLegForward.skirtFrontRight);
+ } else {
+ finalOrientation.leftLeg.copyOrientation(walkRightLegForward.leftLeg);
+ finalOrientation.rightLeg.copyOrientation(walkRightLegForward.rightLeg);
+ finalOrientation.waist.copyOrientation(walkRightLegForward.waist);
+ finalOrientation.shoulders.copyOrientation(walkRightLegForward.shoulders);
+ finalOrientation.leftArm.copyOrientation(walkRightLegForward.leftArm);
+ finalOrientation.rightArm.copyOrientation(walkRightLegForward.rightArm);
+ finalOrientation.skirtFrontLeft.copyOrientation(walkRightLegForward.skirtFrontLeft);
+ finalOrientation.skirtFrontRight.copyOrientation(walkRightLegForward.skirtFrontRight);
+ }
+ }
+
+ private Randomizer leftLegRandomizer = new Randomizer(0.5f, 7f);
+ private Randomizer rightLegRandomizer = new Randomizer(0.5f, 7f);
+
+ private void randomize() {
+ rightLegRandomizer.setPaused(!leftLegRandomizer.isPaused());
+ rightLegRandomizer.tick(delta);
+ leftLegRandomizer.tick(delta);
+ leftLegRandomizer.randomize(finalOrientation.leftLeg);
+ rightLegRandomizer.randomize(finalOrientation.rightLeg);
+ }
+
+ private void fixClothOrientation() {
+
+ }
+
+ public void tick() {
+ if (!demoMode) {
+ finalOrientation.reset();
+ }
+ if (!demoMode) {
+ // deltaOrientation.reset();
+ if (isJumping()) {
+ // air motion
+ while (!areLegsApart) {
+ walkTick();
+ setLegsWalking();
+ }
+ } else {
+ // on-ground motion
+ if (isWalking()) {
+ walkTick();
+ if (isCrawling()) {
+
+ } else if (isCrouching()) {
+
+ } else {
+ // standing
+ setLegsWalking();
+ }
+ } else {
+ // make legs together, switch forward leg
+ while (!areLegsTogether) {
+ walkTick();
+ standTick();
+ setLegsWalking();
+ setLegsStanding();
+ }
+ }
+ }
+ randomize();
+ // System.err.println("[leg] " +
+ // finalOrientation.leftLeg.top.getPitch());
+ fixClothOrientation();
+ deltaOrientation.leftArm.top.setRollCorrection(-50f);
+ deltaOrientation.rightArm.top.setRollCorrection(-deltaOrientation.leftArm.top.getRollCorrection());
+ deltaOrientation.setSpeed(4f);
+ deltaOrientation.skirtFrontLeft.setSpeed(1f);
+ deltaOrientation.skirtFrontRight.setSpeed(1f);
+ if (isLeftLegAhead && !isLegReturning) {
+ deltaOrientation.skirtFrontLeft.setSpeed(4f);
+ }
+ if (!isLeftLegAhead && !isLegReturning) {
+ deltaOrientation.skirtFrontRight.setSpeed(4f);
+ }
+ }else{
+ deltaOrientation.setSpeed(4f);
+ }
+ deltaOrientation.setDelta(currentOrientation, finalOrientation, getDelta());
+ // deltaOrientation.copyOrientation(finalOrientation);
+ currentOrientation.copyOrientation(deltaOrientation);
+ }
+
+ private boolean demoMode = false;
+
+ public void setPause(boolean boneMode) {
+ demoMode = boneMode;
+ }
+
+}
diff --git a/src/ru/olamedia/olacraft/modelAnimator/Randomizer.java b/src/ru/olamedia/olacraft/modelAnimator/Randomizer.java
new file mode 100644
index 0000000..1e66c87
--- /dev/null
+++ b/src/ru/olamedia/olacraft/modelAnimator/Randomizer.java
@@ -0,0 +1,92 @@
+package ru.olamedia.olacraft.modelAnimator;
+
+import java.util.Random;
+
+public class Randomizer {
+
+ public Randomizer(float minTimeout, float maxTimeout) {
+ super();
+ this.minTimeout = minTimeout;
+ this.maxTimeout = maxTimeout;
+ }
+
+ private float minTimeout = 1f;
+ private float maxTimeout = 1f;
+ private long seed;
+ private long prevSeed = 0;
+ private float seedTimeout = 0;
+ private float seedTime = 0;
+ private float delta;
+ private boolean isPaused = false;
+ private boolean isForcePaused = false;
+
+ /**
+ * @return the isPaused
+ */
+ public boolean isPaused() {
+ return isPaused;
+ }
+
+ /**
+ * @param isPaused
+ * the isPaused to set
+ */
+ public void setPaused(boolean isPaused) {
+ this.isForcePaused = isPaused;
+ }
+
+ private Random rand = new Random();
+ private Random prev = new Random();
+
+ public void tick(float delta) {
+ if (!isForcePaused) {
+ seedTimeout -= delta;
+ }
+ if (seedTimeout <= 0) {
+ if (!isPaused) {
+ prevSeed = seed;
+ }
+ Random srand = new Random();
+ seed = srand.nextLong();
+ seedTime = seedTimeout = minTimeout + srand.nextFloat() * (maxTimeout - minTimeout);
+ }
+ prev.setSeed(prevSeed);
+ rand.setSeed(seed);
+ prev.nextBoolean();
+ isPaused = rand.nextBoolean();
+ if (isPaused) {
+ this.delta = 0;
+ } else {
+ this.delta = (seedTime - seedTimeout) / seedTime;
+ }
+ }
+
+ public float getMinTimeout() {
+ return minTimeout;
+ }
+
+ public void setMinTimeout(float minTimeout) {
+ this.minTimeout = minTimeout;
+ }
+
+ public float getMaxTimeout() {
+ return maxTimeout;
+ }
+
+ public void setMaxTimeout(float maxTimeout) {
+ this.maxTimeout = maxTimeout;
+ }
+
+ public void randomize(Skeleton skel) {
+ skel.randomize(rand, prev, delta);
+ }
+
+ public void randomize(Leg leg) {
+ leg.randomize(rand, prev, delta);
+ }
+
+ public void randomize(ISkeletonNode b) {
+ b.randomize(rand, prev, delta);
+ }
+
+}
diff --git a/src/ru/olamedia/olacraft/modelAnimator/Skeleton.java b/src/ru/olamedia/olacraft/modelAnimator/Skeleton.java
new file mode 100644
index 0000000..5cae422
--- /dev/null
+++ b/src/ru/olamedia/olacraft/modelAnimator/Skeleton.java
@@ -0,0 +1,47 @@
+package ru.olamedia.olacraft.modelAnimator;
+
+public class Skeleton extends BoneSet {
+
+ public Bone neck; // 首 - шея
+ public Bone shoulders; // 上半身 - верхняя часть тела
+ public Bone waist; // 下半身 - нижняя часть корпуса
+ public Bone skirtFrontLeft;
+ public Bone skirtFrontRight;
+
+ public Arm leftArm;
+ public Arm rightArm;
+
+ public Leg leftLeg;
+ public Leg rightLeg;
+
+ public Skeleton() {
+ super(9);
+ neck = new Bone();
+ neck.setName("Neck");
+ waist = new Bone();
+ waist.setName("Waist");
+ shoulders = new Bone();
+ shoulders.setName("Shoulders");
+ skirtFrontLeft = new Bone();
+ skirtFrontLeft.setName("Skirt Front Left");
+ skirtFrontRight = new Bone();
+ skirtFrontRight.setName("Skirt Front Right");
+ leftArm = new Arm();
+ rightArm = new Arm();
+ leftLeg = new Leg();
+ rightLeg = new Leg();
+ leftArm.setNamePrefix("Left arm ");
+ rightArm.setNamePrefix("Right arm ");
+ leftLeg.setNamePrefix("Left leg ");
+ rightLeg.setNamePrefix("Right leg ");
+ setChild(0, neck);
+ setChild(1, waist);
+ setChild(2, shoulders);
+ setChild(3, skirtFrontLeft);
+ setChild(4, skirtFrontRight);
+ setChild(5, leftArm);
+ setChild(6, rightArm);
+ setChild(7, leftLeg);
+ setChild(8, rightLeg);
+ }
+}
diff --git a/src/ru/olamedia/olacraft/modelAnimator/package-info.java b/src/ru/olamedia/olacraft/modelAnimator/package-info.java
new file mode 100644
index 0000000..7bc19b6
--- /dev/null
+++ b/src/ru/olamedia/olacraft/modelAnimator/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.modelAnimator; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/network/GameClient.java b/src/ru/olamedia/olacraft/network/GameClient.java
index f74340a..ee9ce32 100644
--- a/src/ru/olamedia/olacraft/network/GameClient.java
+++ b/src/ru/olamedia/olacraft/network/GameClient.java
@@ -25,6 +25,7 @@ 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.LocalChunkDataProvider;
import ru.olamedia.olacraft.world.dataProvider.RemoteChunkDataProvider;
import ru.olamedia.olacraft.world.provider.WorldProvider;
@@ -63,9 +64,12 @@ public class GameClient extends ConnectionStateListener implements IPacketListen
public GameClient() {
// INIT WORLD
worldProvider = new WorldProvider();
- worldProvider.setChunkDataProvider(new CachedChunkDataProvider(new RemoteChunkDataProvider(this)));
// worldProvider.setChunkDataProvider(new CachedChunkDataProvider(new
- // LocalChunkDataProvider(worldProvider.getInfo().name)));
+ // RemoteChunkDataProvider(this)));
+ // worldProvider.setChunkDataProvider(new
+ // LocalChunkDataProvider(worldProvider.getInfo().name));
+ worldProvider.setChunkDataProvider(new CachedChunkDataProvider(new LocalChunkDataProvider(worldProvider
+ .getInfo().name)));
// CREATE SCENE
scene = new GameScene(worldProvider);
Kryo kryo = client.getKryo();
diff --git a/src/ru/olamedia/olacraft/network/GameServer.java b/src/ru/olamedia/olacraft/network/GameServer.java
index 717b40b..13b70c4 100644
--- a/src/ru/olamedia/olacraft/network/GameServer.java
+++ b/src/ru/olamedia/olacraft/network/GameServer.java
@@ -32,6 +32,20 @@ import com.esotericsoftware.kryonet.Server;
public class GameServer {
private WorldProvider worldProvider;
+ /**
+ * @return the worldProvider
+ */
+ public WorldProvider getWorldProvider() {
+ return worldProvider;
+ }
+
+ /**
+ * @param worldProvider the worldProvider to set
+ */
+ public void setWorldProvider(WorldProvider worldProvider) {
+ this.worldProvider = worldProvider;
+ }
+
private ExecutorService threadPool = Executors.newFixedThreadPool(1);
public static Server server = new Server(30 * 1024 * 1024, 1024 * 1024) {
@Override
diff --git a/src/ru/olamedia/olacraft/network/Network.java b/src/ru/olamedia/olacraft/network/Network.java
index 22434f1..2c44850 100644
--- a/src/ru/olamedia/olacraft/network/Network.java
+++ b/src/ru/olamedia/olacraft/network/Network.java
@@ -21,8 +21,11 @@ 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.drop.DroppedEntity;
import ru.olamedia.olacraft.world.location.BlockLocation;
import ru.olamedia.olacraft.world.location.ChunkLocation;
+import ru.olamedia.olacraft.world.location.Location3f;
+import ru.olamedia.olacraft.world.location.Location3i;
import ru.olamedia.olacraft.world.location.RegionLocation;
import ru.olamedia.olacraft.world.location.SectorLocation;
@@ -53,10 +56,13 @@ public class Network {
kryo.register(HeightMap.class);
kryo.register(WorldInfo.class);
kryo.register(WorldInfoPacket.class);
+ kryo.register(Location3f.class);
+ kryo.register(Location3i.class);
kryo.register(BlockLocation.class);
kryo.register(ChunkLocation.class);
kryo.register(SectorLocation.class);
kryo.register(RegionLocation.class);
+ kryo.register(DroppedEntity.class);
kryo.register(ChunkData.class);
kryo.register(ChunkData[].class);
kryo.register(SectorData.class);
diff --git a/src/ru/olamedia/olacraft/network/packet/SectorDataPacket.java b/src/ru/olamedia/olacraft/network/packet/SectorDataPacket.java
new file mode 100644
index 0000000..d592a10
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/packet/SectorDataPacket.java
@@ -0,0 +1,14 @@
+package ru.olamedia.olacraft.network.packet;
+
+import ru.olamedia.olacraft.world.data.SectorData;
+
+public class SectorDataPacket implements IPacket {
+ public SectorDataPacket() {
+ }
+
+ public SectorDataPacket(SectorData data) {
+ this.data = data;
+ }
+
+ public SectorData data;
+}
diff --git a/src/ru/olamedia/olacraft/network/provider/CacheProvider.java b/src/ru/olamedia/olacraft/network/provider/CacheProvider.java
new file mode 100644
index 0000000..267edb0
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/provider/CacheProvider.java
@@ -0,0 +1,29 @@
+package ru.olamedia.olacraft.network.provider;
+
+public class CacheProvider<T> implements IProvider<T> {
+ public CacheProvider(IProvider<T> parent) {
+ this.parent = parent;
+ }
+
+ private T obj;
+ private IProvider<T> parent;
+
+ public boolean has() {
+ return null != obj || parent.has();
+ }
+
+ public void request() {
+ parent.request();
+ }
+
+ public T get() {
+ if (null == obj) {
+ obj = parent.get();
+ }
+ return obj;
+ }
+
+ public void put(T obj) {
+ this.obj = obj;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/network/provider/IProvider.java b/src/ru/olamedia/olacraft/network/provider/IProvider.java
new file mode 100644
index 0000000..d73b55e
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/provider/IProvider.java
@@ -0,0 +1,11 @@
+package ru.olamedia.olacraft.network.provider;
+
+public interface IProvider<T> {
+ public boolean has();
+
+ public void request();
+
+ public T get();
+
+ public void put(T obj);
+}
diff --git a/src/ru/olamedia/olacraft/network/provider/LocalProvider.java b/src/ru/olamedia/olacraft/network/provider/LocalProvider.java
new file mode 100644
index 0000000..da9b82c
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/provider/LocalProvider.java
@@ -0,0 +1,21 @@
+package ru.olamedia.olacraft.network.provider;
+
+public class LocalProvider<T> implements IProvider<T> {
+ private T obj;
+
+ public boolean has() {
+ return true;
+ }
+
+ public void request() {
+
+ }
+
+ public T get() {
+ return obj;
+ }
+
+ public void put(T obj) {
+ this.obj = obj;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/network/provider/RemoteProvider.java b/src/ru/olamedia/olacraft/network/provider/RemoteProvider.java
new file mode 100644
index 0000000..854293c
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/provider/RemoteProvider.java
@@ -0,0 +1,19 @@
+package ru.olamedia.olacraft.network.provider;
+
+abstract public class RemoteProvider<T> implements IProvider<T> {
+ private T obj;
+
+ public boolean has() {
+ return null != obj;
+ }
+
+ abstract public void request();
+
+ public T get() {
+ return obj;
+ }
+
+ public void put(T obj) {
+ this.obj = obj;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/network/provider/package-info.java b/src/ru/olamedia/olacraft/network/provider/package-info.java
new file mode 100644
index 0000000..f444cac
--- /dev/null
+++ b/src/ru/olamedia/olacraft/network/provider/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.network.provider; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/render/jogl/ChunkRangeRenderer.java b/src/ru/olamedia/olacraft/render/jogl/ChunkRangeRenderer.java
new file mode 100644
index 0000000..cd84c99
--- /dev/null
+++ b/src/ru/olamedia/olacraft/render/jogl/ChunkRangeRenderer.java
@@ -0,0 +1,254 @@
+package ru.olamedia.olacraft.render.jogl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import javax.media.opengl.GL2;
+import javax.media.opengl.GLContext;
+
+import com.jogamp.opengl.math.geom.AABBox;
+
+import ru.olamedia.geom.ImmModeMesh;
+import ru.olamedia.olacraft.game.Game;
+import ru.olamedia.olacraft.world.blockRenderer.ChunkRenderer;
+import ru.olamedia.olacraft.world.blockTypes.BlockType;
+import ru.olamedia.olacraft.world.blockTypes.GrassBlockType;
+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;
+import ru.olamedia.olacraft.world.location.BlockLocation;
+import ru.olamedia.olacraft.world.location.ChunkLocation;
+import ru.olamedia.player.Player;
+
+public class ChunkRangeRenderer {
+
+ private class Point {
+ public int x;
+ public int y;
+ public int z;
+ }
+
+ private ArrayList<ArrayList<Point>> ranges = new ArrayList<ArrayList<Point>>();
+ private ArrayList<ArrayList<Point>> visibleRanges = new ArrayList<ArrayList<Point>>();
+
+ public ImmModeMesh big;
+ private boolean makeBig = false;
+ private boolean isBigInvalid = true;
+
+ private void precalcRange() {
+ for (int d = 0; d < 32; d++) {
+ ranges.add(new ArrayList<ChunkRangeRenderer.Point>());
+ }
+ for (int d = 0; d < 32; d++) {
+ visibleRanges.add(new ArrayList<ChunkRangeRenderer.Point>());
+ }
+ for (int dx = -15; dx <= 15; dx++) {
+ for (int dy = -15; dy <= 15; dy++) {
+ for (int dz = -15; dz <= 15; dz++) {
+ final Point p = new Point();
+ p.x = dx;
+ p.y = dy;
+ p.z = dz;
+ final int d = (int) Math.floor(Math.sqrt(dx * dx + dy * dy + dz * dz));
+ ranges.get(d).add(p);
+ }
+ }
+ }
+ }
+
+ private int vertexTmpCount;
+ private int components = 0;
+
+ public void updateFrustumCulling() {
+ if (null == chunkSlice) {
+ return;
+ }
+ final Player player = Game.client.getScene().getPlayer();
+ cameraBlock = player.getCameraBlockLocation();
+ cameraChunk = cameraBlock.getChunkLocation();
+ final float x = player.camera.getX();
+ final float y = player.camera.getY();
+ final float z = player.camera.getZ();
+ renderDistance = player.settings.renderDistance;
+ vertexTmpCount = 0;
+ for (int d = 0; d < renderDistance / 16; d++) {
+ visibleRanges.get(d).clear();
+ for (Point delta : ranges.get(d)) {
+ renderLoc.x = cameraChunk.x + delta.x;
+ renderLoc.y = cameraChunk.y + delta.y;
+ renderLoc.z = cameraChunk.z + delta.z;
+ final Chunk chunk = chunkSlice.getChunk(renderLoc);
+ center[0] = (float) (chunk.getOffset().x + 8);
+ center[1] = (float) (chunk.getOffset().y + 8);
+ center[2] = (float) (chunk.getOffset().z + 8);
+ if (!Game.instance.camera.frustum.isSphereOutside(center, radius)) {
+ if (chunk.mesh.isValid() && chunk.mesh.isEmpty()) {
+
+ } else {
+ visibleRanges.get(d).add(delta);
+ vertexTmpCount += chunk.mesh.getVertexCount();
+ if ((0 == components) && (null != chunk.mesh.getOpaqueMesh())) {
+ components = chunk.mesh.getOpaqueMesh().getComponents();
+ }
+ }
+ }
+ }
+ }
+ if (null != big) {
+ big.destroy();
+ big = null;
+ }
+ if (makeBig) {
+ big = ImmModeMesh.allocate(vertexTmpCount * components);
+ big.setGLSL(true);
+ big.enableVertex3();
+ big.enableColor4();
+ big.enableTexCoord2();
+ big.setServer(true);
+ big.beginQuads();
+ for (distance = 0; distance <= renderDistance / 16; distance++) {
+ for (Point offset : visibleRanges.get(distance)) {
+ renderLoc.x = cameraChunk.x + offset.x;
+ renderLoc.y = cameraChunk.y + offset.y;
+ renderLoc.z = cameraChunk.z + offset.z;
+ final Chunk chunk = chunkSlice.getChunk(renderLoc);
+ if (chunk.inWorldRange()) {
+ if (chunk.mesh.isValid() && chunk.mesh.isEmpty()) {
+
+ } else {
+ if (null != chunk.mesh.getOpaqueMesh()) {
+ big.put(chunk.mesh.getOpaqueMesh());
+ }
+ if (!chunk.mesh.isValid()) {
+ if (!ChunkMeshBulder.instance.isFull()) {
+ ChunkMeshBulder.instance.add(chunk);
+ }
+ }
+ }
+ }
+ }
+ }
+ big.end();
+ }
+ }
+
+ private boolean useShaders = true;
+
+ public ChunkRangeRenderer(BlockSlice slice) {
+ precalcRange();
+ }
+
+ private BlockType blockType = new GrassBlockType();
+
+ public int testedChunks = 0;
+ public int testedChunksVertices = 0;
+
+ 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 int visibleBlocks = 0;
+ public int vertexCount = 0;
+
+ public static int lightTick = 0;
+
+ public static int OPAQUE_PASS = 0;
+ public static int ALPHA_PASS = 1;
+ private AABBox box = new AABBox();
+ private float d;
+ final float radius = (float) Math.sqrt(8 * 8 + 8 * 8 + 8 * 8);
+ final float radius2 = (float) Math.sqrt(0.5 * 0.5 + 0.5 * 0.5 + 0.5 * 0.5);
+ private float[] center = new float[3];
+
+ public boolean renderChunk(Chunk chunk, boolean skipnew, int pass) {
+ testedChunks++;
+ if (!chunk.inWorldRange()) {
+ return skipnew;
+ }
+ // center[0] = (float) (chunk.getOffset().x + 8);
+ // center[1] = (float) (chunk.getOffset().y + 8);
+ // center[2] = (float) (chunk.getOffset().z + 8);
+ chunk.render(pass);
+
+ vertexCount += chunk.mesh.getVertexCount();
+ if (!chunk.mesh.isValid()) {
+ if (!skipnew) {
+ ChunkMeshBulder.instance.add(chunk);
+ if (ChunkMeshBulder.instance.isFull()) {
+ skipnew = true;
+ }
+ }
+ }
+ return skipnew;
+ }
+
+ Chunk lastInvalidChunk = null;
+ BlockLocation cameraBlock;
+ ChunkLocation cameraChunk;
+ int distance;
+ private int renderDistance;
+ public ChunkSlice chunkSlice;
+
+ private boolean allChunksRendered = false;
+ private boolean allChunksValid = false;
+ private ChunkLocation renderLoc = new ChunkLocation();
+
+ public void render(int pass) {
+ final GL2 gl = GLContext.getCurrentGL().getGL2();
+ visibleBlocks = 0;
+ vertexCount = 0;
+ allChunksRendered = true;
+ allChunksValid = true;
+ renderDistance = Game.client.getScene().getPlayer().settings.renderDistance;
+ if (!ChunkMeshBulder.instance.isAlive() && !ChunkMeshBulder.instance.isInterrupted()) {
+ ChunkMeshBulder.instance.start();
+ }
+ if (null == chunkSlice) {
+ ChunkSlice.rendererInstance = chunkSlice = new ChunkSlice(Game.client.getWorldProvider(), 1, 1, 1);// slice.getChunkSlice();
+ }
+ /*
+ * if (!ChunkMeshGarbageCollector.instance.isAlive() &&
+ * !ChunkMeshGarbageCollector.instance.isInterrupted()) {
+ * ChunkMeshGarbageCollector.instance.start();
+ * }
+ */
+ // chunkSlice = new ChunkSlice(Game.client.getWorldProvider(), 1, 1, 1);
+ testedChunks = 0;
+ visibleTop = 0;
+ visibleBottom = 0;
+ visibleLeft = 0;
+ visibleRight = 0;
+ visibleFront = 0;
+ visibleBack = 0;
+ frustumCulledChunks = 0;
+
+ cameraBlock = Game.client.getScene().getPlayer().getCameraBlockLocation();
+ cameraChunk = cameraBlock.getChunkLocation();
+
+ boolean skipnew = false;
+ if (null != big) {
+ big.draw();
+ } else {
+ for (distance = 0; distance <= renderDistance / 16; distance++) {
+ if (distance > 0) {
+ for (Point offset : visibleRanges.get(distance)) {
+ renderLoc.x = cameraChunk.x + offset.x;
+ renderLoc.y = cameraChunk.y + offset.y;
+ renderLoc.z = cameraChunk.z + offset.z;
+ skipnew = renderChunk(chunkSlice.getChunk(renderLoc), skipnew, pass);
+ }
+ } else {
+ renderLoc.set(cameraChunk);
+ skipnew = renderChunk(chunkSlice.getChunk(renderLoc), skipnew, pass);
+ }
+ }
+ }
+ }
+}
diff --git a/src/ru/olamedia/olacraft/render/jogl/DefaultRenderer.java b/src/ru/olamedia/olacraft/render/jogl/DefaultRenderer.java
index 12c12e0..60475cf 100644
--- a/src/ru/olamedia/olacraft/render/jogl/DefaultRenderer.java
+++ b/src/ru/olamedia/olacraft/render/jogl/DefaultRenderer.java
@@ -1,6 +1,9 @@
package ru.olamedia.olacraft.render.jogl;
+import java.util.Random;
+
import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.event.MouseEvent;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.glu.GLU;
@@ -22,9 +25,14 @@ public class DefaultRenderer implements IRenderer, KeyListener, MouseListener {
MouseJail.attach(this);
}
+ private Random rand = new Random();
+
@Override
public void render(GLAutoDrawable drawable) {
+ Game.instance.fpsTimer.update();
+ // if (rand.nextFloat() > 0.8f) {
Game.client.getScene().tick();
+ // }
Game.client.getScene().render(drawable);
}
@@ -48,14 +56,6 @@ public class DefaultRenderer implements IRenderer, KeyListener, MouseListener {
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
@@ -64,12 +64,19 @@ public class DefaultRenderer implements IRenderer, KeyListener, MouseListener {
}
@Override
- public void onMouseClick() {
- Game.instance.player.onMouseClick();
+ public void onMouseClick(MouseEvent e) {
+ if (null != Game.instance.player) {
+ Game.instance.player.onMouseClick(e);
+ }
}
@Override
public void init(GLAutoDrawable drawable) {
-
+
+ }
+
+ @Override
+ public void reshape(GLAutoDrawable drawable) {
+ Game.client.getScene().reshape(drawable);
}
}
diff --git a/src/ru/olamedia/olacraft/render/jogl/IRenderer.java b/src/ru/olamedia/olacraft/render/jogl/IRenderer.java
index 1ba581a..492e046 100644
--- a/src/ru/olamedia/olacraft/render/jogl/IRenderer.java
+++ b/src/ru/olamedia/olacraft/render/jogl/IRenderer.java
@@ -5,4 +5,5 @@ import javax.media.opengl.GLAutoDrawable;
public interface IRenderer {
public void render(GLAutoDrawable drawable);
public void init(GLAutoDrawable drawable);
+ public void reshape(GLAutoDrawable drawable);
}
diff --git a/src/ru/olamedia/olacraft/render/jogl/InventoryRenderer.java b/src/ru/olamedia/olacraft/render/jogl/InventoryRenderer.java
index 46daa4a..d2d103b 100644
--- a/src/ru/olamedia/olacraft/render/jogl/InventoryRenderer.java
+++ b/src/ru/olamedia/olacraft/render/jogl/InventoryRenderer.java
@@ -51,8 +51,8 @@ public class InventoryRenderer {
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 != stack && !(stack.type instanceof EmptyBlockType)) {
+ Texture tex = TextureManager.get(stack.type.getStackTextureFile());
if (null != tex) {
tex.bind(gl);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
diff --git a/src/ru/olamedia/olacraft/render/jogl/joglViewport.java b/src/ru/olamedia/olacraft/render/jogl/joglViewport.java
index ef59352..3a62835 100644
--- a/src/ru/olamedia/olacraft/render/jogl/joglViewport.java
+++ b/src/ru/olamedia/olacraft/render/jogl/joglViewport.java
@@ -8,19 +8,41 @@ import com.jogamp.opengl.util.awt.TextRenderer;
public class joglViewport {
private GLAutoDrawable drawable;
- private TextRenderer sans11;
+ private TextRenderer sans11Black;
+ private TextRenderer sans11White;
+
+ // private TextRenderer sans12;
public joglViewport(GLAutoDrawable drawable) {
this.drawable = drawable;
- sans11 = new TextRenderer(new Font("SansSerif", Font.PLAIN, 11));
+ //sans11Black = new TextRenderer(new Font("SansSerif", Font.PLAIN, 11));
+ //sans11Black.setColor(0, 0, 0, 1f);
+ sans11White = new TextRenderer(new Font("SansSerif", Font.PLAIN, 11));
+ sans11White.setColor(0, 0, 0, 0.9f);
+ // sans12 = new TextRenderer(new Font("SansSerif", Font.PLAIN, 11));
+ }
+
+ public void beginRendering() {
+ sans11White.beginRendering(drawable.getWidth(), drawable.getHeight());
+ //sans11Black.beginRendering(drawable.getWidth(), drawable.getHeight());
+ }
+
+ public void endRendering() {
+ sans11White.flush();
+ sans11White.endRendering();
+ //sans11Black.endRendering();
}
public void drawText(String text, int x, int y) {
- sans11.setColor(0, 0, 0, 0.7f);
- sans11.beginRendering(drawable.getWidth(), drawable.getHeight());
- sans11.draw(text, x - 1, y - 1);
- // sans11.setColor(1, 1, 1, 0.7f);
- // sans11.draw(text, x, y);
- sans11.endRendering();
+ // sans12.beginRendering(drawable.getWidth(), drawable.getHeight());
+ // sans12.setColor(1, 1, 1, 0.9f);
+ // sans12.draw(text, x, y);
+ // sans12.endRendering();
+ //sans11White.draw(text, x - 1, y);
+ //sans11White.draw(text, x + 1, y);
+ //sans11White.draw(text, x, y - 1);
+ //sans11White.draw(text, x, y + 1);
+ sans11White.draw(text, x, y);
+
}
}
diff --git a/src/ru/olamedia/olacraft/scene/GameScene.java b/src/ru/olamedia/olacraft/scene/GameScene.java
index e5655c9..c0a3f86 100644
--- a/src/ru/olamedia/olacraft/scene/GameScene.java
+++ b/src/ru/olamedia/olacraft/scene/GameScene.java
@@ -3,53 +3,83 @@ package ru.olamedia.olacraft.scene;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryUsage;
import java.util.HashMap;
+import java.util.Random;
import javax.media.opengl.GL2;
+import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLContext;
import javax.media.opengl.glu.GLU;
import javax.media.opengl.glu.GLUquadric;
import org.ode4j.ode.DBody;
-import ru.olamedia.Options;
+import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.opengl.util.PMVMatrix;
+
+import ru.olamedia.game.GameFrame;
+import ru.olamedia.game.GameLogicThread;
import ru.olamedia.game.GameTime;
+import ru.olamedia.geom.ImmModeMesh;
+import ru.olamedia.input.KeyListener;
+import ru.olamedia.input.Keyboard;
import ru.olamedia.liveEntity.LiveEntity;
import ru.olamedia.olacraft.game.Game;
+import ru.olamedia.olacraft.modelAnimator.Bone;
import ru.olamedia.olacraft.physics.GamePhysicsWorld;
-import ru.olamedia.olacraft.render.jogl.ChunkRenderer;
+import ru.olamedia.olacraft.render.jogl.ChunkRangeRenderer;
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.block.Block;
-import ru.olamedia.olacraft.world.blockTypes.AbstractBlockType;
-import ru.olamedia.olacraft.world.blockTypes.DirtBlockType;
+import ru.olamedia.olacraft.world.blockRenderer.ChunkRenderer;
+import ru.olamedia.olacraft.world.blockTypes.BlockType;
import ru.olamedia.olacraft.world.blockTypes.GrassBlockType;
-import ru.olamedia.olacraft.world.blockTypes.GravelBlockType;
-import ru.olamedia.olacraft.world.blockTypes.StoneBlockType;
import ru.olamedia.olacraft.world.chunk.BlockSlice;
-import ru.olamedia.olacraft.world.chunk.Chunk;
-import ru.olamedia.olacraft.world.chunk.ChunkSlice;
-import ru.olamedia.olacraft.world.location.BlockLocation;
+import ru.olamedia.olacraft.world.chunk.ChunkUnavailableException;
import ru.olamedia.olacraft.world.provider.WorldProvider;
import ru.olamedia.player.Player;
+import ru.olamedia.texture.TextureManager;
-public class GameScene {
-
+public class GameScene implements KeyListener {
+ private boolean isHUDEnabled = false;
+ private boolean thirdPersonMode = true;
+ public boolean boneMode = false;
+ private boolean renderFrustum = false;
private HashMap<Integer, LiveEntity> liveEntities = new HashMap<Integer, LiveEntity>();
WorldProvider provider;
- private int renderDistance = Options.renderDistance;
- private joglViewport viewport;
+ public joglViewport viewport;
private BulletScene bullets = new BulletScene();
private GamePhysicsWorld physics = new GamePhysicsWorld();
- private boolean isInitialized = false;
+ public boolean isInitialized = false;
BlockSlice viewSlice;
- public GameTime time = new GameTime();
+ public GameTime dayTime = new GameTime();
+
+ private ImmModeMesh crosshair;
+
+ public Bone selectedBone = null;
+ public int bonesCount = 0;
+
+ private BlockType blockType = new GrassBlockType();
public GameScene(WorldProvider provider) {
this.provider = provider;
- setRenderDistance(renderDistance);
+ pickSlice = new BlockSlice(provider, 10, 10, 10);
+ Keyboard.attach(this);
+ Keyboard.setName("3_left", KeyEvent.VK_NUMPAD4);
+ Keyboard.setName("3_right", KeyEvent.VK_NUMPAD6);
+ Keyboard.setName("3_up", KeyEvent.VK_NUMPAD8);
+ Keyboard.setName("3_down", KeyEvent.VK_NUMPAD2);
+ Keyboard.setName("3_in", KeyEvent.VK_NUMPAD7);
+ Keyboard.setName("3_out", KeyEvent.VK_NUMPAD1);
+ Keyboard.setName("3_mode", KeyEvent.VK_F6);
+ Keyboard.setName("hud", KeyEvent.VK_F9);
+ Keyboard.setName("bone_mode", KeyEvent.VK_B);
+ Keyboard.setName("next", KeyEvent.VK_N);
+ Keyboard.setName("rotate_cw", KeyEvent.VK_RIGHT);
+ Keyboard.setName("rotate_ccw", KeyEvent.VK_LEFT);
}
public void addBullet(Bullet b) {
@@ -70,46 +100,51 @@ public class GameScene {
return bullets.getCount();
}
+ public void buildCrosshair() {
+ final int width = GameFrame.getGLWidth();
+ final int height = GameFrame.getGLHeight();
+ final int w = 1;
+ final int l = 5;
+ crosshair = ImmModeMesh.allocate(8);// 2 rectangles
+ // crosshair.setServer(true);
+ // crosshair.setGLSL(true);
+ crosshair.enableColor4();
+ crosshair.enableVertex2();
+ crosshair.setColor(0f, 1f, 1f, 0.7f);
+ crosshair.beginQuads();
+ {
+ crosshair.glRectf(width / 2 - w, height / 2 - l * 2, width / 2 + w, height / 2 + l * 2); // vertical
+ crosshair.glRectf(width / 2 - l * 2, height / 2 - w, width / 2 - 1, height / 2 + w); // horizontal
+ crosshair.glRectf(width / 2 + 1, height / 2 - w, width / 2 + l * 2, height / 2 + w); // horizontal
+ }
+ crosshair.end();
+ }
+
public void init(GLAutoDrawable drawable) {
if (isInitialized) {
return;
}
- isInitialized = true;
- time.init();
+ final GL2ES2 gl = GLContext.getCurrentGL().getGL2ES2();
+ gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_NEAREST);
+ gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_NEAREST);// _MIPMAP_NEAREST
registerTextures();
+ gl.glActiveTexture(GL2.GL_TEXTURE1);
+ gl.glBindTexture(blockType.getTopTexture().getTarget(), blockType.getTopTexture().getTextureObject(gl));
+ gl.glActiveTexture(GL2.GL_TEXTURE0);
+ isInitialized = true;
+ dayTime.init();
viewport = new joglViewport(drawable);
+ buildCrosshair();
+ GameLogicThread.instance.start();
}
private void registerTextures() {
- AbstractBlockType t;
- t = new GrassBlockType();
- t.register(provider);
- t = new StoneBlockType();
- t.register(provider);
- t = new DirtBlockType();
- t.register(provider);
- t = new GravelBlockType();
- t.register(provider);
- }
-
- /**
- * @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, renderDistance);
- blockRenderer = new ChunkRenderer(viewSlice);
+ provider.registerTextures();
+ TextureManager.writeSprite("sprite.png");
+ TextureManager.finishSprite();
}
- public ChunkRenderer blockRenderer = new ChunkRenderer(viewSlice);
+ public ChunkRangeRenderer blockRenderer = new ChunkRangeRenderer(viewSlice);
GLU glu = new GLU();
public void registerLiveEntity(LiveEntity entity) {
@@ -120,11 +155,12 @@ public class GameScene {
private InventoryRenderer inventoryRenderer;
- private Player player;
+ public Player player;
public void registerPlayer(LiveEntity player) {
inventoryRenderer = new InventoryRenderer(player.getInventory());
this.player = (Player) player;
+ // this.player.getInventory().buildMeshes();
}
public LiveEntity getLiveEntity(int connectionId) {
@@ -139,221 +175,434 @@ public class GameScene {
}
public Block nearestBlock = null;
+ public Block nearestPutBlock = null;
+ public BlockSlice pickSlice;
+ private Random rand = new Random();
public void tick() {
- time.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());
- BlockSlice pickSlice = new BlockSlice(provider, 10, 10, 10);
- if (null != player) {
- if (player.isOrientationChanged || Game.instance.camera.isOrientationChanged) {
- player.isOrientationChanged = false;
- Game.instance.camera.isOrientationChanged = false;
- pickSlice.setCenter(player.getCameraX(), player.getCameraY(), player.getCameraZ());
- nearestBlock = pickSlice.getNearest(Game.instance.camera);
- }
+ if (rand.nextFloat() > 0.95f) {
+ final GL2ES2 gl = GLContext.getCurrentGL().getGL2ES2();
+ // ChunkRenderer.getShader().enable();
+ dayTime.sunColor.put(0, 1);
+ dayTime.sunColor.put(1, 1);
+ dayTime.sunColor.put(2, 1);
+ // ChunkRenderer.getShader().getState().uniform(gl,
+ // ChunkRenderer.sunColor);
+ // ChunkRenderer.getShader().disable();
+ final float[] clearColor = dayTime.getClearColor();
+ // gl.glClearColor(clearColor[0], clearColor[1], clearColor[2], 1);
+ gl.glClearColor(0.8f, 0.8f, 0.8f, 1);
}
}
+ float dLook = 2;
+ float dUp = 0;
+ float dRight = 0;
+
public void render(GLAutoDrawable drawable) {
if (null == player || !Game.instance.isRunning()) {
// not running, just clear screen
- GL2 gl = drawable.getGL().getGL2();
+ final 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);
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
return;
}
init(drawable);
- float[] clearColor = time.getClearColor();
- GL2 gl = drawable.getGL().getGL2();
+ // final float[] clearColor = time.getClearColor();
+ final GL2 gl = drawable.getGL().getGL2();
gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
- gl.glClearColor(clearColor[0], clearColor[1], clearColor[2], 1);
+ // gl.glClear(GL2.GL_DEPTH_BUFFER_BIT);
+ // gl.glClearColor(clearColor[0], clearColor[1], clearColor[2], 1);
// gl.glClearColor(49f / 255f, 119f / 255f, 243f / 255f, 1);
- // GOING 3D
- gl.glPushMatrix();
gl.glPushAttrib(GL2.GL_ALL_ATTRIB_BITS);
- Game.instance.camera.setUp(drawable);
- // RENDER SUN
- // gl.glPushAttrib(GL2.GL_ALL_ATTRIB_BITS);
- // gl.glEnable(GL2.GL_BLEND); // Enable Blending
- // gl.glBlendFunc(GL2.GL_SRC_ALPHA, GL2.GL_ONE); // Set Blending Mode To
- // // Mix Based On SRC
- // // Alpha
- // GLUquadric sun = glu.gluNewQuadric();
- // glu.gluQuadricDrawStyle(sun, GLU.GLU_FILL);
- // glu.gluQuadricNormals(sun, GLU.GLU_SMOOTH);
+ // GOING 3D
+ if (player.camera.isDirty()) {
+ player.camera.offset.x = 0;
+ player.camera.offset.y = 0;
+ player.camera.offset.z = 0;
+ player.camera.pack();
+ if (thirdPersonMode) {
+ player.camera.offset.x = player.camera.getLook().x * dLook + player.camera.getUp().x * dUp
+ + player.camera.getRight().x * dRight;
+ player.camera.offset.y = player.camera.getLook().y * dLook + player.camera.getUp().y * dUp
+ + player.camera.getRight().y * dRight;
+ player.camera.offset.z = player.camera.getLook().z * dLook + player.camera.getUp().z * dUp
+ + player.camera.getRight().z * dRight;
+ player.camera.pack();
+ player.camera.updateFrustum();
+ blockRenderer.updateFrustumCulling();
+ }
+ ChunkRenderer.getShader().enable();
+ ChunkRenderer.getShader().getState().uniform(gl, ChunkRenderer.pmvMatrixUniform);
+ ChunkRenderer.getShader().disable();
+ }
+ player.camera.setUp();
// gl.glPushMatrix();
- // gl.glTranslatef(time.sun.getX() + player.getCameraX(),
- // time.sun.getY(), time.sun.getZ() + player.getCameraZ());
- // gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_FILL);
- // gl.glColor4f(1, 1, 1, 0.02f);
- // gl.glColor4f((float) 251 / 255, (float) 255 / 255, (float) 228 / 255,
- // 0.02f);
- // glu.gluSphere(sun, 100f, 10, 10);
- // glu.gluSphere(sun, 90f, 10, 10);
- // glu.gluSphere(sun, 80f, 10, 10);
- // glu.gluSphere(sun, 70f, 10, 10);
- // glu.gluSphere(sun, 60f, 10, 10);
- // glu.gluSphere(sun, 50f, 10, 10);
- // glu.gluSphere(sun, 40f, 10, 10);
- // glu.gluSphere(sun, 35f, 10, 10);
- // gl.glColor4f(1, 1, 1, 1f);
- // glu.gluSphere(sun, 30f, 10, 10);
- // gl.glPopMatrix();
- // gl.glPopAttrib();
+ // gl.glPushAttrib(GL2.GL_ALL_ATTRIB_BITS);
+
+ // RENDER SUN
+ /*
+ * gl.glPushAttrib(GL2.GL_ALL_ATTRIB_BITS);
+ * gl.glEnable(GL2.GL_BLEND); // Enable Blending
+ * gl.glBlendFunc(GL2.GL_SRC_ALPHA, GL2.GL_ONE); // Set Blending Mode To
+ * // Mix Based On SRC
+ * // Alpha
+ * GLUquadric sun = glu.gluNewQuadric();
+ * glu.gluQuadricDrawStyle(sun, GLU.GLU_FILL);
+ * glu.gluQuadricNormals(sun, GLU.GLU_SMOOTH);
+ * gl.glPushMatrix();
+ * gl.glTranslatef(time.sun.getX() + player.getCameraX(),
+ * time.sun.getY(), time.sun.getZ() + player.getCameraZ());
+ * gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_FILL);
+ * gl.glColor4f(1, 1, 1, 0.02f);
+ * gl.glColor4f((float) 251 / 255, (float) 255 / 255, (float) 228 / 255,
+ * 0.02f);
+ * glu.gluSphere(sun, 100f, 10, 10);
+ * glu.gluSphere(sun, 90f, 10, 10);
+ * glu.gluSphere(sun, 80f, 10, 10);
+ * glu.gluSphere(sun, 70f, 10, 10);
+ * glu.gluSphere(sun, 60f, 10, 10);
+ * glu.gluSphere(sun, 50f, 10, 10);
+ * glu.gluSphere(sun, 40f, 10, 10);
+ * glu.gluSphere(sun, 35f, 10, 10);
+ * gl.glColor4f(1, 1, 1, 1f);
+ * glu.gluSphere(sun, 30f, 10, 10);
+ * gl.glPopMatrix();
+ * gl.glPopAttrib();
+ */
- viewSlice.setCenter((int) Game.instance.camera.getX(), (int) Game.instance.camera.getY(),
- (int) Game.instance.camera.getZ());
// RENDER BLOCKS
- gl.glPopAttrib();
- gl.glPushAttrib(GL2.GL_ALL_ATTRIB_BITS);
- gl.glColor4f(0f, 1f, 0, 1);
- gl.glEnable(GL2.GL_DEPTH_TEST);
+ // gl.glColor4f(0f, 1f, 0, 1);
gl.glShadeModel(GL2.GL_FLAT);
- gl.glCullFace(GL2.GL_BACK);
+ gl.glEnable(GL2.GL_DEPTH_TEST);
+ gl.glEnable(GL2.GL_CULL_FACE);
+ // gl.glColorMask(false, false, false, false);
+ // gl.glEnable(GL2.GL_TEXTURE_2D);
+ gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_NEAREST);
+ gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_NEAREST);// _MIPMAP_NEAREST
+ ChunkRenderer.enableShader();
+ // ChunkRenderer.getShader().getState().uniform(gl,
+ // ChunkRenderer.sunColor);
+ gl.glActiveTexture(GL2.GL_TEXTURE1);
+ // gl.glBindTexture(blockType.getTopTexture().getTarget(),
+ // blockType.getTopTexture().getTextureObject(gl));
+ gl.glDisable(GL2.GL_BLEND);
+ blockRenderer.render(ChunkRangeRenderer.OPAQUE_PASS);
+ gl.glDisable(GL2.GL_BLEND);
+ // gl.glEnable(GL2.GL_BLEND);
+ // gl.glBlendFunc(GL2.GL_SRC_ALPHA, GL2.GL_ONE_MINUS_SRC_ALPHA);
+ // gl.glBlendEquationSeparate(GL2.GL_FUNC_ADD, GL2.GL_FUNC_ADD); // copy
+ // blockRenderer.render(ChunkRangeRenderer.ALPHA_PASS);
+ // gl.glDisable(GL2.GL_TEXTURE_2D);
+ gl.glDisable(GL2.GL_CULL_FACE);
+ gl.glDisable(GL2.GL_DEPTH_TEST);
+ gl.glDisable(GL2.GL_BLEND);
+ // gl.glDisable(GL2.GL_ALPHA_TEST);
+ ChunkRenderer.disableShader();
+ gl.glActiveTexture(GL2.GL_TEXTURE0);
+ // gl.glPushAttrib(GL2.GL_ALL_ATTRIB_BITS);
+ // 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_START, player.settings.renderDistance / 2 -
+ // player.settings.renderDistance / 10);
+ // gl.glFogf(GL2.GL_FOG_END, player.settings.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();
- gl.glPopAttrib();
+ // 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());
- gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_LINE);
- glu.gluSphere(qobj0, 0.1f, 10, 10);
- gl.glPopMatrix();
- }
- gl.glPopAttrib();
+ /*
+ * 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());
+ * gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_LINE);
+ * glu.gluSphere(qobj0, 0.03f, 10, 10);
+ * gl.glPopMatrix();
+ * }
+ * gl.glPopAttrib();
+ */
if (nearestBlock != null) {
gl.glPushAttrib(GL2.GL_ALL_ATTRIB_BITS);
- nearestBlock.renderFrame();
+ if (nearestBlock != null) {
+ nearestBlock.renderFrame();
+ }
gl.glPopAttrib();
}
+ if (thirdPersonMode && renderFrustum) {
+ player.camera.renderFrustum();
+ }
// bullets.render(drawable);
- gl.glPopMatrix();
+ // gl.glPushAttrib(GL2.GL_ALL_ATTRIB_BITS);
+ // player.render();
+ // gl.glPopAttrib();
+ // gl.glPopMatrix();
// testObject.render();
-
+ gl.glPopAttrib();
// 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);
- }
+ if (isHUDEnabled) {
+ gl.glMatrixMode(GL2.GL_PROJECTION);
+ gl.glLoadIdentity();
+ final int width = GameFrame.getGLWidth();
+ final int height = GameFrame.getGLHeight();
+ glu.gluOrtho2D(0, width, height, 0);
+ gl.glMatrixMode(GL2.GL_MODELVIEW);
+ gl.glPushAttrib(GL2.GL_ALL_ATTRIB_BITS);
+ // 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);
+
+ // MAP--
+ // crosshair
+ if (null != crosshair) {
+ gl.glDisable(GL2.GL_TEXTURE_2D);
+ gl.glDisable(GL2.GL_CULL_FACE);
+ gl.glDisable(GL2.GL_DEPTH_TEST);
+ gl.glDisable(GL2.GL_BLEND);
+ gl.glBindTexture(GL2.GL_TEXTURE_2D, 0);
+ gl.glEnable(GL2.GL_BLEND);
+ gl.glBlendFunc(GL2.GL_ONE, GL2.GL_ONE);
+ gl.glBlendEquation(GL2.GL_FUNC_SUBTRACT);
+ // ChunkRenderer.enableShader();
+ crosshair.draw();
+ // ChunkRenderer.disableShader();
+ gl.glBlendEquation(GL2.GL_FUNC_ADD);
+ gl.glDisable(GL2.GL_BLEND);
+ } else {
+ System.err.println("no 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
+ // TODO ENABLE
+ // inventory
+ // player.getInventory().renderGUI();
+ // inventoryprivate PMVMatrix matrix;
+ // if (null != inventoryRenderer) {
+ // // inventoryRenderer.render(drawable);
+ // }
+ gl.glPushAttrib(GL2.GL_ALL_ATTRIB_BITS);
+ viewport.beginRendering();
+ gl.glEnable(GL2.GL_BLEND);
+ // gl.glBlendColor(0, 0, 0, 1);
+ gl.glBlendFunc(GL2.GL_ZERO, GL2.GL_ONE_MINUS_SRC_ALPHA);
+ //gl.glBlendFuncSeparate(GL2.GL_DST_COLOR, GL2.GL_ONE_MINUS_SRC_ALPHA, GL2.GL_SRC_ALPHA,
+ // GL2.GL_ONE_MINUS_DST_COLOR);
+ gl.glBlendEquation(GL2.GL_FUNC_ADD);
+ viewport.drawText("⌀ " + player.settings.renderDistance, 10, height - 20);
+ viewport.drawText("avg fps: " + (int) Game.fpsTimer.getAvgFps(), 10, height - 35);
+ viewport.drawText("fps: " + (int) Game.fpsTimer.getFps(), 10, height - 50);
+ final MemoryUsage heap = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
+ final MemoryUsage nonheap = ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage();
+ viewport.drawText("heap: " + (heap.getUsed() / (1024 * 1024)) + "/" + (heap.getMax() / (1024 * 1024)), 10,
+ height - 65);
+ viewport.drawText("non heap: " + (nonheap.getUsed() / (1024 * 1024)) + "/"
+ + (nonheap.getMax() / (1024 * 1024)), 10, height - 80);
+ // viewport.drawText("b: " + blockRenderer.visibleBlocks, 10, height
+ // -
+ // 80);
+ if (null != blockRenderer.big) {
+ viewport.drawText("v: " + blockRenderer.big.getVertexCount(), 10, height - 95);
+ }
+ viewport.drawText("c: " + blockRenderer.testedChunks, 10, height - 105);
+ //
+ viewport.drawText("y: " + Game.instance.player.getY(), width - 100 - 10, height - 100 - 20);
+ viewport.drawText("y: " + Game.instance.player.getCameraY() + " (cam)", width - 100 - 10, height - 100 - 30);
+ viewport.drawText("x: " + Game.instance.player.getX(), width - 100 - 10, height - 100 - 40);
+ viewport.drawText("z: " + Game.instance.player.getZ(), width - 100 - 10, height - 100 - 50);
+ if (boneMode) {
+ viewport.drawText("bones count: " + bonesCount, width - 100 - 10, height - 100 - 80);
+ }
+ if (boneMode && null != selectedBone) {
+ viewport.drawText("bone: " + selectedBone.getName(), width - 100 - 10, height - 100 - 90);
+ viewport.drawText("pitch: " + selectedBone.getPitch(), width - 100 - 10, height - 100 - 100);
+ viewport.drawText("__yaw: " + selectedBone.getYaw(), width - 100 - 10, height - 100 - 110);
+ viewport.drawText("_roll: " + selectedBone.getRoll(), width - 100 - 10, height - 100 - 120);
+ }
+ viewport.endRendering();
+ gl.glDisable(GL2.GL_BLEND);
+ gl.glBlendEquation(GL2.GL_FUNC_ADD);
+ gl.glBlendColor(0, 0, 0, 0);
+ gl.glPopAttrib();
- viewport.drawText("rad: " + Options.renderDistance, 10, height - 20);
- viewport.drawText("avg fps: " + (int) Game.timer.getAvgFps(), 10, height - 35);
- viewport.drawText("fps: " + (int) Game.timer.getFps(), 10, height - 50);
- MemoryUsage heap = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
- viewport.drawText("mem: " + (heap.getUsed() / (1024 * 1024)) + "/" + (heap.getMax() / (1024 * 1024)), 10,
- height - 65);
- //
- // viewport.drawText("y: " + Game.instance.player.getY(), width - msz -
- // 10, height - msz - 20);
- // viewport.drawText("y: " + Game.instance.player.getCameraY() +
- // " (cam)", width - msz - 10, height - msz - 30);
- // 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 - 50);
- // viewport.drawText("players: " + liveEntities.size(), width - msz -
- // 10, height - msz - 70);
- // viewport.drawText("bullets: " + getBulletsCount(), width - msz - 10,
- // height - msz - 95);
- // viewport.drawText("y velocity: " + player.velocity.y + " y accel: " +
- // player.acceleration.y + " inJump: "
- // + player.inJump + " onGround: " + player.onGround, width - msz - 350
- // - 10, height - msz - 110);
- // viewport.drawText("rdistance: " + Options.renderDistance, width - msz
- // - 10, height - msz - 155);
-
- // ChunkSlice cs = viewSlice.getChunkSlice();
- // viewport.drawText("slice x: " + cs.getX() + ".." + (cs.getX() +
- // cs.getWidth() - 1) + " y: " + cs.getY() + ".."
- // + (cs.getY() + cs.getHeight() - 1) + " z: " + cs.getZ() + ".." +
- // (cs.getZ() + cs.getDepth() - 1), width
- // - msz * 2 - 10, height - msz - 170);
- // viewport.drawText("time: " + time.getDateTimeString(), width - msz *
- // 2 - 10, height - msz - 185);
- // if (nearestBlock != null) {
- // viewport.drawText("pick: " + nearestBlock.getX() + "," +
- // nearestBlock.getY() + "," + nearestBlock.getZ()
- // + " d " + nearestBlock.getDistance(Game.instance.camera), width - msz
- // * 2 - 10, height - msz - 200);
- // viewport.drawText(
- // "edge: " + nearestBlock.location.isChunkEdge() + " left " +
- // nearestBlock.location.isChunkLeftEdge(),
- // width - msz * 2 - 10, height - msz - 210);
- // }
-
- // BlockLocation camloc = player.getCameraBlockLocation();
- // viewport.drawText("cam chunk: " + camloc.getChunkLocation(), width -
- // 200 - msz * 2 - 10, height - msz - 225);
- // Chunk camc =
- // viewSlice.getChunkSlice().getChunk(camloc.getChunkLocation());
- // viewport.drawText("cam chunk: " + camc.isMeshCostructed + " mesh: " +
- // camc.mesh, width - 200 - msz * 2 - 10,
- // height - msz - 235);
- // viewport.drawText(
- // "chunk available: " + camc.isAvailable() + " chunk empty: "
- // + (camc.isAvailable() ? camc.isEmpty() : "unknown"), width - 200 -
- // msz * 2 - 10, height - msz
- // - 245);
+ // viewport.drawText("players: " + liveEntities.size(), width - msz
+ // -
+ // 10, height - msz - 70);
+ // viewport.drawText("bullets: " + getBulletsCount(), width - msz -
+ // 10,
+ // height - msz - 95);
+ // viewport.drawText("y velocity: " + player.velocity.y +
+ // " y accel: " +
+ // player.acceleration.y + " inJump: "
+ // + player.inJump + " onGround: " + player.onGround, width - msz -
+ // 350
+ // - 10, height - msz - 110);
+ // viewport.drawText("rdistance: " + Options.renderDistance, width -
+ // msz
+ // - 10, height - msz - 155);
+
+ // ChunkSlice cs = viewSlice.getChunkSlice();
+ // viewport.drawText("slice x: " + cs.getX() + ".." + (cs.getX() +
+ // cs.getWidth() - 1) + " y: " + cs.getY() + ".."
+ // + (cs.getY() + cs.getHeight() - 1) + " z: " + cs.getZ() + ".." +
+ // (cs.getZ() + cs.getDepth() - 1), width
+ // - msz * 2 - 10, height - msz - 170);
+ // viewport.drawText("time: " + time.getDateTimeString(), width -
+ // msz *
+ // 2 - 10, height - msz - 185);
+ // if (nearestBlock != null) {
+ // viewport.drawText("pick: " + nearestBlock.getX() + "," +
+ // nearestBlock.getY() + "," + nearestBlock.getZ()
+ // + " d " + nearestBlock.getDistance(Game.instance.camera), width -
+ // msz
+ // * 2 - 10, height - msz - 200);
+ // viewport.drawText(
+ // "edge: " + nearestBlock.location.isChunkEdge() + " left " +
+ // nearestBlock.location.isChunkLeftEdge(),
+ // width - msz * 2 - 10, height - msz - 210);
+ // }
+
+ // BlockLocation camloc = player.getCameraBlockLocation();
+ // viewport.drawText("cam chunk: " + camloc.getChunkLocation(),
+ // width -
+ // 200 - msz * 2 - 10, height - msz - 225);
+ // Chunk camc =
+ // viewSlice.getChunkSlice().getChunk(camloc.getChunkLocation());
+ // viewport.drawText("cam chunk: " + camc.isMeshCostructed +
+ // " mesh: " +
+ // camc.mesh, width - 200 - msz * 2 - 10,
+ // height - msz - 235);
+ // viewport.drawText(
+ // "chunk available: " + camc.isAvailable() + " chunk empty: "
+ // + (camc.isAvailable() ? camc.isEmpty() : "unknown"), width - 200
+ // -
+ // msz * 2 - 10, height - msz
+ // - 245);
+
+ // gl.glPopAttrib();
+ // gl.glPopMatrix();
+ // gl.glFlush();
+ disposeMeshes();
+ gl.glPopAttrib();
+ }
+ }
- gl.glPopAttrib();
- gl.glPopMatrix();
- // gl.glFlush();
+ public void disposeMeshes() {
+ // blockRenderer.chunkSlice.disposeMeshes();
}
public Player getPlayer() {
return player;
}
+
+ public PMVMatrix getPmvMatrix() {
+ return Game.instance.camera.pmvMatrix;
+ }
+
+ public void reshape(GLAutoDrawable drawable) {
+ buildCrosshair();
+ if (null != player) {
+ // player.getInventory().buildMeshes();
+ }
+ }
+
+ @Override
+ public void onKeyPressed(String name, KeyEvent e) {
+ if (e.getKeyCode() == KeyEvent.VK_F6) {
+ thirdPersonMode = !thirdPersonMode;
+ }
+ if (e.getKeyCode() == KeyEvent.VK_B) {
+ boneMode = !boneMode;
+ }
+ final boolean thirdPersonControlsEnabled = thirdPersonMode && !boneMode;
+ if (thirdPersonControlsEnabled) {
+ final int shiftSpeed = 10;
+ if (e.getKeyCode() == KeyEvent.VK_NUMPAD4) {
+ dRight += -0.1 * shiftSpeed;
+ }
+ if (e.getKeyCode() == KeyEvent.VK_NUMPAD6) {
+ dRight += 0.1 * shiftSpeed;
+ }
+ if (e.getKeyCode() == KeyEvent.VK_NUMPAD8) {
+ dUp += 0.1 * shiftSpeed;
+ }
+ if (e.getKeyCode() == KeyEvent.VK_NUMPAD2) {
+ dUp += -0.1 * shiftSpeed;
+ }
+ if (e.getKeyCode() == KeyEvent.VK_NUMPAD1) {
+ dLook += 0.1 * shiftSpeed;
+ }
+ if (e.getKeyCode() == KeyEvent.VK_NUMPAD7) {
+ dLook += -0.1 * shiftSpeed;
+ }
+ }
+ if (boneMode && null != selectedBone) {
+ if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
+ player.rotateCW();
+ }
+ if (e.getKeyCode() == KeyEvent.VK_LEFT) {
+ player.rotateCCW();
+ }
+ if (e.getKeyCode() == KeyEvent.VK_NUMPAD4) {
+ selectedBone.setRoll(selectedBone.getRoll() + 1);
+ }
+ if (e.getKeyCode() == KeyEvent.VK_NUMPAD6) {
+ selectedBone.setRoll(selectedBone.getRoll() - 1);
+ }
+ if (e.getKeyCode() == KeyEvent.VK_NUMPAD8) {
+ selectedBone.setPitch(selectedBone.getPitch() + 1);
+ }
+ if (e.getKeyCode() == KeyEvent.VK_NUMPAD2) {
+ selectedBone.setPitch(selectedBone.getPitch() - 1);
+ }
+ if (e.getKeyCode() == KeyEvent.VK_NUMPAD1) {
+ selectedBone.setYaw(selectedBone.getYaw() + 1);
+ }
+ if (e.getKeyCode() == KeyEvent.VK_NUMPAD7) {
+ selectedBone.setYaw(selectedBone.getYaw() - 1);
+ }
+ if (e.getKeyCode() == KeyEvent.VK_N) {
+ player.selectNextBone();
+ }
+ }
+ if (e.getKeyCode() == KeyEvent.VK_F7) {
+ renderFrustum = !renderFrustum;
+ }
+ if (e.getKeyCode() == KeyEvent.VK_F9) {
+ isHUDEnabled = !isHUDEnabled;
+ }
+ if (null != player) {
+ player.camera.setDirty();
+ }
+ }
+
+ @Override
+ public void onKeyReleased(String name, KeyEvent e) {
+
+ }
}
diff --git a/src/ru/olamedia/olacraft/world/biome/Biome.java b/src/ru/olamedia/olacraft/world/biome/Biome.java
new file mode 100644
index 0000000..178e799
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/biome/Biome.java
@@ -0,0 +1,10 @@
+package ru.olamedia.olacraft.world.biome;
+
+public class Biome {
+ public static int ocean = 1;
+ public static int land = 2;
+ public static int island = 3;
+ public static int beach = 4;
+ public static int desert = 5;
+ public static int snow = 5;
+}
diff --git a/src/ru/olamedia/olacraft/world/biome/package-info.java b/src/ru/olamedia/olacraft/world/biome/package-info.java
new file mode 100644
index 0000000..b39342c
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/biome/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.world.biome; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/world/block/Block.java b/src/ru/olamedia/olacraft/world/block/Block.java
index 50752f0..1e7175f 100644
--- a/src/ru/olamedia/olacraft/world/block/Block.java
+++ b/src/ru/olamedia/olacraft/world/block/Block.java
@@ -1,7 +1,6 @@
package ru.olamedia.olacraft.world.block;
import javax.media.opengl.GL2;
-import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLContext;
import javax.vecmath.Vector3f;
@@ -22,35 +21,16 @@ public class Block {
public void removeFromWorld() {
ChunkData cdata = provider.getChunk(location.getChunkLocation());
cdata.setEmpty(location, true);
- Chunk chunk = Game.client.getScene().blockRenderer.chunkSlice.getChunk(location.getChunkLocation());
- chunk.invalidate();
- if (location.isChunkEdge()) {
- if (location.isChunkBackEdge()) {
- Chunk neighbor = Game.client.getScene().blockRenderer.chunkSlice.getChunk(location.getChunkLocation()
- .getBack());
- neighbor.invalidate();
- } else if (location.isChunkFrontEdge()) {
- Chunk neighbor = Game.client.getScene().blockRenderer.chunkSlice.getChunk(location.getChunkLocation()
- .getFront());
- neighbor.invalidate();
- } else if (location.isChunkLeftEdge()) {
- Chunk neighbor = Game.client.getScene().blockRenderer.chunkSlice.getChunk(location.getChunkLocation()
- .getLeft());
- neighbor.invalidate();
- } else if (location.isChunkRightEdge()) {
- Chunk neighbor = Game.client.getScene().blockRenderer.chunkSlice.getChunk(location.getChunkLocation()
- .getRight());
- neighbor.invalidate();
- } else if (location.isChunkTopEdge()) {
- Chunk neighbor = Game.client.getScene().blockRenderer.chunkSlice.getChunk(location.getChunkLocation()
- .getTop());
- neighbor.invalidate();
- } else if (location.isChunkBottomEdge()) {
- Chunk neighbor = Game.client.getScene().blockRenderer.chunkSlice.getChunk(location.getChunkLocation()
- .getBottom());
- neighbor.invalidate();
- }
- }
+ cdata.voidLightPrecomputed = false;
+ invalidateChunks();
+ }
+
+ public void insertToWorld() {
+ ChunkData cdata = provider.getChunk(location.getChunkLocation());
+ cdata.setEmpty(location, false);
+ cdata.types[ChunkData.ClampID(location.x, location.y, location.z)] = (byte) type.getId(provider);
+ cdata.voidLightPrecomputed = false;
+ invalidateChunks();
}
/**
@@ -63,7 +43,7 @@ public class Block {
location.z = 0;
}
- public void putIntoWorld(WorldProvider worldProvider, int x, int y, int z) {
+ public void setLocation(WorldProvider worldProvider, int x, int y, int z) {
this.provider = worldProvider;
location.x = x;
location.y = y;
@@ -71,7 +51,11 @@ public class Block {
}
public Block(WorldProvider worldProvider, int x, int y, int z) {
- putIntoWorld(worldProvider, x, y, z);
+ setLocation(worldProvider, x, y, z);
+ }
+
+ public Block(WorldProvider worldProvider, BlockLocation location) {
+ setLocation(worldProvider, location.x, location.y, location.z);
}
/**
@@ -152,8 +136,14 @@ public class Block {
return type;
}
+ public int nearestX = 0;
+ public int nearestY = 0;
+ public int nearestZ = 0;
+
public float getDistance(MatrixCamera cam) {
- String nearest = "";
+ nearestX = 0;
+ nearestY = 0;
+ nearestZ = 0;
float topDistance = cam.intersectsRectangle(getTopLeftBack(), getTopLeftFront(), getTopRightFront(),
getTopRightBack());
float bottomDistance = cam.intersectsRectangle(getBottomLeftBack(), getBottomLeftFront(),
@@ -171,22 +161,17 @@ public class Block {
float frontBack = Math.min(frontDistance, backDistance);
float distance = Math.min(Math.min(topBottom, leftRight), frontBack);
if (distance == bottomDistance) {
- nearest = "BOTTOM";
- }
- if (distance == topDistance) {
- nearest = "TOP";
- }
- if (distance == leftDistance) {
- nearest = "LEFT";
- }
- if (distance == rightDistance) {
- nearest = "RIGHT";
- }
- if (distance == frontDistance) {
- nearest = "FRONT";
- }
- if (distance == backDistance) {
- nearest = "BACK";
+ nearestY = -1;
+ } else if (distance == topDistance) {
+ nearestY = 1;
+ } else if (distance == leftDistance) {
+ nearestX = -1;
+ } else if (distance == rightDistance) {
+ nearestX = 1;
+ } else if (distance == frontDistance) {
+ nearestZ = 1;
+ } else if (distance == backDistance) {
+ nearestZ = -1;
}
return distance;
}
@@ -243,127 +228,176 @@ public class Block {
gl.glBegin(GL2.GL_QUADS);
{
gl.glColor4f(0, 0, 0, 0.8f);
- // top: right
- gl.glVertex3f(location.x + min, location.y + min, location.z + min);
- gl.glVertex3f(location.x + min, location.y + min, location.z - min);
- gl.glVertex3f(location.x + max, location.y + min, location.z - min);
- gl.glVertex3f(location.x + max, location.y + min, location.z + min);
- // top: left
- gl.glVertex3f(location.x - min, location.y + min, location.z + min);
- gl.glVertex3f(location.x - min, location.y + min, location.z - min);
- gl.glVertex3f(location.x - max, location.y + min, location.z - min);
- gl.glVertex3f(location.x - max, location.y + min, location.z + min);
- // top: back
- gl.glVertex3f(location.x + min, location.y + min, location.z - min);
- gl.glVertex3f(location.x - min, location.y + min, location.z - min);
- gl.glVertex3f(location.x - min, location.y + min, location.z - max);
- gl.glVertex3f(location.x + min, location.y + min, location.z - max);
- // top: front
- gl.glVertex3f(location.x + min, location.y + min, location.z + min);
- gl.glVertex3f(location.x - min, location.y + min, location.z + min);
- gl.glVertex3f(location.x - min, location.y + min, location.z + max);
- gl.glVertex3f(location.x + min, location.y + min, location.z + max);
- // bottom: right
- gl.glVertex3f(location.x + min, location.y - min, location.z + min);
- gl.glVertex3f(location.x + min, location.y - min, location.z - min);
- gl.glVertex3f(location.x + max, location.y - min, location.z - min);
- gl.glVertex3f(location.x + max, location.y - min, location.z + min);
- // bottom: left
- gl.glVertex3f(location.x - min, location.y - min, location.z + min);
- gl.glVertex3f(location.x - min, location.y - min, location.z - min);
- gl.glVertex3f(location.x - max, location.y - min, location.z - min);
- gl.glVertex3f(location.x - max, location.y - min, location.z + min);
- // bottom: back
- gl.glVertex3f(location.x + min, location.y - min, location.z - min);
- gl.glVertex3f(location.x - min, location.y - min, location.z - min);
- gl.glVertex3f(location.x - min, location.y - min, location.z - max);
- gl.glVertex3f(location.x + min, location.y - min, location.z - max);
- // bottom: front
- gl.glVertex3f(location.x + min, location.y - min, location.z + min);
- gl.glVertex3f(location.x - min, location.y - min, location.z + min);
- gl.glVertex3f(location.x - min, location.y - min, location.z + max);
- gl.glVertex3f(location.x + min, location.y - min, location.z + max);
- // front: right
- gl.glVertex3f(location.x + min, location.y + min, location.z + min);
- gl.glVertex3f(location.x + min, location.y - min, location.z + min);
- gl.glVertex3f(location.x + max, location.y - min, location.z + min);
- gl.glVertex3f(location.x + max, location.y + min, location.z + min);
- // front: left
- gl.glVertex3f(location.x - min, location.y + min, location.z + min);
- gl.glVertex3f(location.x - min, location.y - min, location.z + min);
- gl.glVertex3f(location.x - max, location.y - min, location.z + min);
- gl.glVertex3f(location.x - max, location.y + min, location.z + min);
- // front: bottom
- gl.glVertex3f(location.x + min, location.y - min, location.z + min);
- gl.glVertex3f(location.x - min, location.y - min, location.z + min);
- gl.glVertex3f(location.x - min, location.y - max, location.z + min);
- gl.glVertex3f(location.x + min, location.y - max, location.z + min);
- // front: top
- gl.glVertex3f(location.x + min, location.y + min, location.z + min);
- gl.glVertex3f(location.x - min, location.y + min, location.z + min);
- gl.glVertex3f(location.x - min, location.y + max, location.z + min);
- gl.glVertex3f(location.x + min, location.y + max, location.z + min);
- // back: right
- gl.glVertex3f(location.x + min, location.y + min, location.z - min);
- gl.glVertex3f(location.x + min, location.y - min, location.z - min);
- gl.glVertex3f(location.x + max, location.y - min, location.z - min);
- gl.glVertex3f(location.x + max, location.y + min, location.z - min);
- // back: left
- gl.glVertex3f(location.x - min, location.y + min, location.z - min);
- gl.glVertex3f(location.x - min, location.y - min, location.z - min);
- gl.glVertex3f(location.x - max, location.y - min, location.z - min);
- gl.glVertex3f(location.x - max, location.y + min, location.z - min);
- // back: bottom
- gl.glVertex3f(location.x + min, location.y - min, location.z + min);
- gl.glVertex3f(location.x - min, location.y - min, location.z + min);
- gl.glVertex3f(location.x - min, location.y - max, location.z + min);
- gl.glVertex3f(location.x + min, location.y - max, location.z + min);
- // back: top
- gl.glVertex3f(location.x + min, location.y + min, location.z + min);
- gl.glVertex3f(location.x - min, location.y + min, location.z + min);
- gl.glVertex3f(location.x - min, location.y + max, location.z + min);
- gl.glVertex3f(location.x + min, location.y + max, location.z + min);
- // left: back
- gl.glVertex3f(location.x - min, location.y + min, location.z - min);
- gl.glVertex3f(location.x - min, location.y - min, location.z - min);
- gl.glVertex3f(location.x - min, location.y - min, location.z - max);
- gl.glVertex3f(location.x - min, location.y + min, location.z - max);
- // left: front
- gl.glVertex3f(location.x - min, location.y + min, location.z + min);
- gl.glVertex3f(location.x - min, location.y - min, location.z + min);
- gl.glVertex3f(location.x - min, location.y - min, location.z + max);
- gl.glVertex3f(location.x - min, location.y + min, location.z + max);
- // left: top
- gl.glVertex3f(location.x - min, location.y + min, location.z + min);
- gl.glVertex3f(location.x - min, location.y + min, location.z - min);
- gl.glVertex3f(location.x - min, location.y + max, location.z - min);
- gl.glVertex3f(location.x - min, location.y + max, location.z + min);
- // left: bottom
- gl.glVertex3f(location.x - min, location.y - min, location.z + min);
- gl.glVertex3f(location.x - min, location.y - min, location.z - min);
- gl.glVertex3f(location.x - min, location.y - max, location.z - min);
- gl.glVertex3f(location.x - min, location.y - max, location.z + min);
- // right: back
- gl.glVertex3f(location.x + min, location.y + min, location.z - min);
- gl.glVertex3f(location.x + min, location.y - min, location.z - min);
- gl.glVertex3f(location.x + min, location.y - min, location.z - max);
- gl.glVertex3f(location.x + min, location.y + min, location.z - max);
- // right: front
- gl.glVertex3f(location.x + min, location.y + min, location.z + min);
- gl.glVertex3f(location.x + min, location.y - min, location.z + min);
- gl.glVertex3f(location.x + min, location.y - min, location.z + max);
- gl.glVertex3f(location.x + min, location.y + min, location.z + max);
- // right: top
- gl.glVertex3f(location.x + min, location.y + min, location.z + min);
- gl.glVertex3f(location.x + min, location.y + min, location.z - min);
- gl.glVertex3f(location.x + min, location.y + max, location.z - min);
- gl.glVertex3f(location.x + min, location.y + max, location.z + min);
- // right: bottom
- gl.glVertex3f(location.x + min, location.y - min, location.z + min);
- gl.glVertex3f(location.x + min, location.y - min, location.z - min);
- gl.glVertex3f(location.x + min, location.y - max, location.z - min);
- gl.glVertex3f(location.x + min, location.y - max, location.z + min);
+ if (nearestY == 1) {
+ // top: right
+ gl.glVertex3f(location.x + min, location.y + min, location.z + min);
+ gl.glVertex3f(location.x + min, location.y + min, location.z - min);
+ gl.glVertex3f(location.x + max, location.y + min, location.z - min);
+ gl.glVertex3f(location.x + max, location.y + min, location.z + min);
+ // top: left
+ gl.glVertex3f(location.x - min, location.y + min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y + min, location.z - min);
+ gl.glVertex3f(location.x - max, location.y + min, location.z - min);
+ gl.glVertex3f(location.x - max, location.y + min, location.z + min);
+ // top: back
+ gl.glVertex3f(location.x + min, location.y + min, location.z - min);
+ gl.glVertex3f(location.x - min, location.y + min, location.z - min);
+ gl.glVertex3f(location.x - min, location.y + min, location.z - max);
+ gl.glVertex3f(location.x + min, location.y + min, location.z - max);
+ // top: front
+ gl.glVertex3f(location.x + min, location.y + min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y + min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y + min, location.z + max);
+ gl.glVertex3f(location.x + min, location.y + min, location.z + max);
+ }
+ if (nearestY == -1) {
+ // bottom: right
+ gl.glVertex3f(location.x + min, location.y - min, location.z + min);
+ gl.glVertex3f(location.x + min, location.y - min, location.z - min);
+ gl.glVertex3f(location.x + max, location.y - min, location.z - min);
+ gl.glVertex3f(location.x + max, location.y - min, location.z + min);
+ // bottom: left
+ gl.glVertex3f(location.x - min, location.y - min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y - min, location.z - min);
+ gl.glVertex3f(location.x - max, location.y - min, location.z - min);
+ gl.glVertex3f(location.x - max, location.y - min, location.z + min);
+ // bottom: back
+ gl.glVertex3f(location.x + min, location.y - min, location.z - min);
+ gl.glVertex3f(location.x - min, location.y - min, location.z - min);
+ gl.glVertex3f(location.x - min, location.y - min, location.z - max);
+ gl.glVertex3f(location.x + min, location.y - min, location.z - max);
+ // bottom: front
+ gl.glVertex3f(location.x + min, location.y - min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y - min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y - min, location.z + max);
+ gl.glVertex3f(location.x + min, location.y - min, location.z + max);
+ }
+ if (nearestZ == 1) {
+ // front: right
+ gl.glVertex3f(location.x + min, location.y + min, location.z + min);
+ gl.glVertex3f(location.x + min, location.y - min, location.z + min);
+ gl.glVertex3f(location.x + max, location.y - min, location.z + min);
+ gl.glVertex3f(location.x + max, location.y + min, location.z + min);
+ // front: left
+ gl.glVertex3f(location.x - min, location.y + min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y - min, location.z + min);
+ gl.glVertex3f(location.x - max, location.y - min, location.z + min);
+ gl.glVertex3f(location.x - max, location.y + min, location.z + min);
+ // front: bottom
+ gl.glVertex3f(location.x + min, location.y - min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y - min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y - max, location.z + min);
+ gl.glVertex3f(location.x + min, location.y - max, location.z + min);
+ // front: top
+ gl.glVertex3f(location.x + min, location.y + min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y + min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y + max, location.z + min);
+ gl.glVertex3f(location.x + min, location.y + max, location.z + min);
+ }
+ if (nearestZ == -1) {
+ // back: right
+ gl.glVertex3f(location.x + min, location.y + min, location.z - min);
+ gl.glVertex3f(location.x + min, location.y - min, location.z - min);
+ gl.glVertex3f(location.x + max, location.y - min, location.z - min);
+ gl.glVertex3f(location.x + max, location.y + min, location.z - min);
+ // back: left
+ gl.glVertex3f(location.x - min, location.y + min, location.z - min);
+ gl.glVertex3f(location.x - min, location.y - min, location.z - min);
+ gl.glVertex3f(location.x - max, location.y - min, location.z - min);
+ gl.glVertex3f(location.x - max, location.y + min, location.z - min);
+ // back: bottom
+ gl.glVertex3f(location.x + min, location.y - min, location.z - min);
+ gl.glVertex3f(location.x - min, location.y - min, location.z - min);
+ gl.glVertex3f(location.x - min, location.y - max, location.z - min);
+ gl.glVertex3f(location.x + min, location.y - max, location.z - min);
+ // back: top
+ gl.glVertex3f(location.x + min, location.y + min, location.z - min);
+ gl.glVertex3f(location.x - min, location.y + min, location.z - min);
+ gl.glVertex3f(location.x - min, location.y + max, location.z - min);
+ gl.glVertex3f(location.x + min, location.y + max, location.z - min);
+ }
+ if (nearestX == -1) {
+ // left: back
+ gl.glVertex3f(location.x - min, location.y + min, location.z - min);
+ gl.glVertex3f(location.x - min, location.y - min, location.z - min);
+ gl.glVertex3f(location.x - min, location.y - min, location.z - max);
+ gl.glVertex3f(location.x - min, location.y + min, location.z - max);
+ // left: front
+ gl.glVertex3f(location.x - min, location.y + min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y - min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y - min, location.z + max);
+ gl.glVertex3f(location.x - min, location.y + min, location.z + max);
+ // left: top
+ gl.glVertex3f(location.x - min, location.y + min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y + min, location.z - min);
+ gl.glVertex3f(location.x - min, location.y + max, location.z - min);
+ gl.glVertex3f(location.x - min, location.y + max, location.z + min);
+ // left: bottom
+ gl.glVertex3f(location.x - min, location.y - min, location.z + min);
+ gl.glVertex3f(location.x - min, location.y - min, location.z - min);
+ gl.glVertex3f(location.x - min, location.y - max, location.z - min);
+ gl.glVertex3f(location.x - min, location.y - max, location.z + min);
+ }
+ if (nearestX == 1) {
+ // right: back
+ gl.glVertex3f(location.x + min, location.y + min, location.z - min);
+ gl.glVertex3f(location.x + min, location.y - min, location.z - min);
+ gl.glVertex3f(location.x + min, location.y - min, location.z - max);
+ gl.glVertex3f(location.x + min, location.y + min, location.z - max);
+ // right: front
+ gl.glVertex3f(location.x + min, location.y + min, location.z + min);
+ gl.glVertex3f(location.x + min, location.y - min, location.z + min);
+ gl.glVertex3f(location.x + min, location.y - min, location.z + max);
+ gl.glVertex3f(location.x + min, location.y + min, location.z + max);
+ // right: top
+ gl.glVertex3f(location.x + min, location.y + min, location.z + min);
+ gl.glVertex3f(location.x + min, location.y + min, location.z - min);
+ gl.glVertex3f(location.x + min, location.y + max, location.z - min);
+ gl.glVertex3f(location.x + min, location.y + max, location.z + min);
+ // right: bottom
+ gl.glVertex3f(location.x + min, location.y - min, location.z + min);
+ gl.glVertex3f(location.x + min, location.y - min, location.z - min);
+ gl.glVertex3f(location.x + min, location.y - max, location.z - min);
+ gl.glVertex3f(location.x + min, location.y - max, location.z + min);
+ }
}
gl.glEnd();
}
+
+ public void invalidateChunks() {
+ // TODO Auto-generated method stub
+ Chunk chunk = Game.client.getScene().blockRenderer.chunkSlice.getChunk(location.getChunkLocation());
+ chunk.invalidate();
+ if (location.isChunkEdge()) {
+ if (location.isChunkBackEdge()) {
+ Chunk neighbor = Game.client.getScene().blockRenderer.chunkSlice.getChunk(location.getChunkLocation()
+ .getBack());
+ neighbor.invalidate();
+ } else if (location.isChunkFrontEdge()) {
+ Chunk neighbor = Game.client.getScene().blockRenderer.chunkSlice.getChunk(location.getChunkLocation()
+ .getFront());
+ neighbor.invalidate();
+ } else if (location.isChunkLeftEdge()) {
+ Chunk neighbor = Game.client.getScene().blockRenderer.chunkSlice.getChunk(location.getChunkLocation()
+ .getLeft());
+ neighbor.invalidate();
+ } else if (location.isChunkRightEdge()) {
+ Chunk neighbor = Game.client.getScene().blockRenderer.chunkSlice.getChunk(location.getChunkLocation()
+ .getRight());
+ neighbor.invalidate();
+ } else if (location.isChunkTopEdge()) {
+ Chunk neighbor = Game.client.getScene().blockRenderer.chunkSlice.getChunk(location.getChunkLocation()
+ .getTop());
+ neighbor.invalidate();
+ } else if (location.isChunkBottomEdge()) {
+ Chunk neighbor = Game.client.getScene().blockRenderer.chunkSlice.getChunk(location.getChunkLocation()
+ .getBottom());
+ neighbor.invalidate();
+ }
+ }
+ }
+
+ public boolean canMoveThrough() throws ChunkUnavailableException {
+ return provider.canMoveThrough(location.x, location.y, location.z);
+ }
}
diff --git a/src/ru/olamedia/olacraft/world/block/BlockRegistry.java b/src/ru/olamedia/olacraft/world/block/BlockRegistry.java
index ec9f9c1..a6e8d38 100644
--- a/src/ru/olamedia/olacraft/world/block/BlockRegistry.java
+++ b/src/ru/olamedia/olacraft/world/block/BlockRegistry.java
@@ -2,20 +2,24 @@ package ru.olamedia.olacraft.world.block;
import java.util.HashMap;
-import ru.olamedia.olacraft.world.blockTypes.BlockType;
+import ru.olamedia.olacraft.world.blockTypes.AbstractBlockType;
public class BlockRegistry {
private HashMap<Integer, String> names = new HashMap<Integer, String>();
- private HashMap<Integer, BlockType> types = new HashMap<Integer, BlockType>();
+ private HashMap<Integer, Boolean> opaque = new HashMap<Integer, Boolean>();
+ private HashMap<Integer, Boolean> canMoveThrough = new HashMap<Integer, Boolean>();
+ private HashMap<Integer, AbstractBlockType> types = new HashMap<Integer, AbstractBlockType>();
+ private HashMap<String, Integer> ids = new HashMap<String, Integer>();
private int autoincrement = 0;
private BlockRegistry worldRegistry;
public BlockRegistry() {
+
}
- public BlockType getBlockType(int id) {
+ public AbstractBlockType getBlockType(int id) {
return types.get(id);
}
@@ -23,12 +27,19 @@ public class BlockRegistry {
return names.get(id);
}
- public int registerBlockType(BlockType type) {
+ public boolean isOpaque(int id) {
+ return opaque.get(id);
+ }
+
+ public int registerBlockType(AbstractBlockType type) {
autoincrement++;
int id = autoincrement;
- String classId = type.getClass().getName();
- names.put(id, classId);
+ String className = type.getClass().getName();
+ names.put(id, className);
types.put(id, type);
+ opaque.put(id, type.isOpaque());
+ canMoveThrough.put(id, type.canMoveThrough());
+ ids.put(className, id);
return autoincrement;
}
@@ -40,4 +51,12 @@ public class BlockRegistry {
this.worldRegistry = worldRegistry;
}
+ public int getBlockIdByClassName(String className) {
+ return ids.get(className);
+ }
+
+ public boolean canMoveThrough(int id) {
+ return canMoveThrough.get(id);
+ }
+
}
diff --git a/src/ru/olamedia/olacraft/world/blockRenderer/AbstractBlockRenderer.java b/src/ru/olamedia/olacraft/world/blockRenderer/AbstractBlockRenderer.java
new file mode 100644
index 0000000..dfb8e1c
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockRenderer/AbstractBlockRenderer.java
@@ -0,0 +1,64 @@
+package ru.olamedia.olacraft.world.blockRenderer;
+
+import java.nio.FloatBuffer;
+
+import ru.olamedia.geom.ImmModeMesh;
+import ru.olamedia.olacraft.world.blockTypes.BlockType;
+import ru.olamedia.olacraft.world.data.ChunkDataNeighbors;
+import ru.olamedia.olacraft.world.location.Location3f;
+import ru.olamedia.olacraft.world.location.Location3i;
+
+public abstract class AbstractBlockRenderer implements IBlockRenderer {
+
+ public boolean renderBottom = true;
+ public boolean renderTop = true;
+ public boolean renderLeft = true;
+ public boolean renderRight = true;
+ public boolean renderFront = true;
+ public boolean renderBack = true;
+ public float scale = 1f;
+ private ChunkDataNeighbors neighbors;
+
+ protected ImmModeMesh mesh = null;
+
+ public void renderAllSides() {
+ renderBottom = true;
+ renderTop = true;
+ renderLeft = true;
+ renderRight = true;
+ renderFront = true;
+ renderBack = true;
+ }
+
+ abstract public void putMesh(ImmModeMesh mesh, BlockType type, FloatBuffer renderLocation, boolean useShader);
+
+ public ImmModeMesh getMesh(BlockType type, FloatBuffer renderLocation, boolean useShader) {
+ return mesh;
+ }
+
+ public ImmModeMesh getMesh(BlockType type, Location3f location, boolean glsl) {
+ return mesh;
+ }
+
+ @Override
+ public void render(BlockType type, Location3f location, boolean glsl) {
+ getMesh(type, location, glsl).draw();
+ }
+
+ @Override
+ public void render(BlockType type, Location3i location, boolean glsl) {
+ getMesh(type, new Location3f(location), glsl).draw();
+ }
+
+ public void setScale(float f) {
+ scale = f;
+ }
+
+ abstract public int getMeshVertexCount(BlockType currentType, FloatBuffer renderLocation,
+ boolean useShader);
+
+ public void setNeighbors(ChunkDataNeighbors neighbors) {
+ this.neighbors = neighbors;
+ }
+
+}
diff --git a/src/ru/olamedia/olacraft/world/blockRenderer/BoxRenderer.java b/src/ru/olamedia/olacraft/world/blockRenderer/BoxRenderer.java
new file mode 100644
index 0000000..8482595
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockRenderer/BoxRenderer.java
@@ -0,0 +1,282 @@
+package ru.olamedia.olacraft.world.blockRenderer;
+
+import java.nio.FloatBuffer;
+
+import javax.vecmath.Point3f;
+
+import ru.olamedia.asset.SpriteRectangle;
+import ru.olamedia.geom.ImmModeMesh;
+import ru.olamedia.olacraft.world.blockTypes.BlockType;
+
+public class BoxRenderer extends AbstractBlockRenderer {
+
+ public static boolean useTriangles = false;
+
+ public Point3f bottomLeftBack = new Point3f();
+ public Point3f bottomLeftFront = new Point3f();
+ public Point3f bottomRightBack = new Point3f();
+ public Point3f bottomRightFront = new Point3f();
+
+ public Point3f topLeftBack = new Point3f();
+ public Point3f topLeftFront = new Point3f();
+ public Point3f topRightBack = new Point3f();
+ public Point3f topRightFront = new Point3f();
+ public float textureTop = 1;
+ public float textureBottom = 0;
+ public float textureLeft = 0;
+ public float textureRight = 1;
+
+ public void setPoint3f(Point3f p) {
+ mesh.glVertex3f(p.x, p.y, p.z);
+ }
+
+ public void addBottomLeftBackVertex() {
+ setPoint3f(bottomLeftBack);
+ }
+
+ public void addBottomLeftFrontVertex() {
+ setPoint3f(bottomLeftFront);
+ }
+
+ public void addBottomRightBackVertex() {
+ setPoint3f(bottomRightBack);
+ }
+
+ public void addBottomRightFrontVertex() {
+ setPoint3f(bottomRightFront);
+ }
+
+ public void addTopLeftBackVertex() {
+ setPoint3f(topLeftBack);
+ }
+
+ public void addTopLeftFrontVertex() {
+ setPoint3f(topLeftFront);
+ }
+
+ public void addTopRightBackVertex() {
+ setPoint3f(topRightBack);
+ }
+
+ public void addTopRightFrontVertex() {
+ setPoint3f(topRightFront);
+ }
+
+ public void addFrontQuad() {
+ // triangle strip: И
+ mesh.setUV(textureLeft, textureTop);
+ addTopLeftFrontVertex(); // top left
+ mesh.setUV(textureLeft, textureBottom);
+ addBottomLeftFrontVertex(); // bottom left
+ if (useTriangles) {
+ mesh.setUV(textureRight, textureBottom);
+ addBottomRightFrontVertex(); // bottom right
+
+ mesh.setUV(textureLeft, textureTop);
+ addTopLeftFrontVertex(); // top left
+ }
+ mesh.setUV(textureRight, textureBottom);
+ addBottomRightFrontVertex(); // bottom right
+ mesh.setUV(textureRight, textureTop);
+ addTopRightFrontVertex(); // top right
+ }
+
+ public void addBackQuad() {
+ // triangle strip: И
+ mesh.setUV(textureLeft, textureTop);
+ addTopRightBackVertex();
+ mesh.setUV(textureLeft, textureBottom);
+ addBottomRightBackVertex();
+ if (useTriangles) {
+ mesh.setUV(textureRight, textureBottom);
+ addBottomLeftBackVertex();
+
+ mesh.setUV(textureLeft, textureTop);
+ addTopRightBackVertex();
+ }
+ mesh.setUV(textureRight, textureBottom);
+ addBottomLeftBackVertex();
+ mesh.setUV(textureRight, textureTop);
+ addTopLeftBackVertex();
+ }
+
+ public void addLeftQuad() {
+ // triangle strip: И
+ mesh.setUV(textureLeft, textureTop);
+ addTopLeftBackVertex();
+ mesh.setUV(textureLeft, textureBottom);
+ addBottomLeftBackVertex();
+ if (useTriangles) {
+ mesh.setUV(textureRight, textureBottom);
+ addBottomLeftFrontVertex();
+
+ mesh.setUV(textureLeft, textureTop);
+ addTopLeftBackVertex();
+ }
+ mesh.setUV(textureRight, textureBottom);
+ addBottomLeftFrontVertex();
+ mesh.setUV(textureRight, textureTop);
+ addTopLeftFrontVertex();
+ }
+
+ public void addRightQuad() {
+ // triangle strip: И
+ mesh.setUV(textureLeft, textureTop);
+ addTopRightFrontVertex();
+ mesh.setUV(textureLeft, textureBottom);
+ addBottomRightFrontVertex();
+ if (useTriangles) {
+ mesh.setUV(textureRight, textureBottom);
+ addBottomRightBackVertex();
+
+ mesh.setUV(textureLeft, textureTop);
+ addTopRightFrontVertex();
+ }
+ mesh.setUV(textureRight, textureBottom);
+ addBottomRightBackVertex();
+ mesh.setUV(textureRight, textureTop);
+ addTopRightBackVertex();
+ }
+
+ public void addTopQuad() {
+ // triangle strip: И
+ mesh.setUV(textureLeft, textureBottom);
+ addTopLeftBackVertex();
+ mesh.setUV(textureLeft, textureTop);
+ addTopLeftFrontVertex();
+ if (useTriangles) {
+ mesh.setUV(textureRight, textureTop);
+ addTopRightFrontVertex();
+
+ mesh.setUV(textureLeft, textureBottom);
+ addTopLeftBackVertex();
+ }
+ mesh.setUV(textureRight, textureTop);
+ addTopRightFrontVertex();
+ mesh.setUV(textureRight, textureBottom);
+ addTopRightBackVertex();
+ }
+
+ public void addBottomQuad() {
+ // triangle strip: И
+ mesh.setUV(textureLeft, textureBottom);
+ addBottomLeftFrontVertex();
+ mesh.setUV(textureLeft, textureTop);
+ addBottomLeftBackVertex();
+ if (useTriangles) {
+ mesh.setUV(textureRight, textureTop);
+ addBottomRightBackVertex();
+
+ mesh.setUV(textureLeft, textureBottom);
+ addBottomLeftFrontVertex();
+ }
+ mesh.setUV(textureRight, textureTop);
+ addBottomRightBackVertex();
+ mesh.setUV(textureRight, textureBottom);
+ addBottomRightFrontVertex();
+ }
+
+ public void setPointOffset(float offset) {
+ bottomLeftBack.x = -offset;
+ bottomLeftBack.y = -offset;
+ bottomLeftBack.z = -offset;
+ //
+ bottomLeftFront.x = -offset;
+ bottomLeftFront.y = -offset;
+ bottomLeftFront.z = offset;
+ //
+ bottomRightBack.x = offset;
+ bottomRightBack.y = -offset;
+ bottomRightBack.z = -offset;
+ //
+ bottomRightFront.x = offset;
+ bottomRightFront.y = -offset;
+ bottomRightFront.z = offset;
+ //
+ topLeftBack.x = -offset;
+ topLeftBack.y = offset;
+ topLeftBack.z = -offset;
+ //
+ topLeftFront.x = -offset;
+ topLeftFront.y = offset;
+ topLeftFront.z = offset;
+ //
+ topRightBack.x = offset;
+ topRightBack.y = offset;
+ topRightBack.z = -offset;
+ //
+ topRightFront.x = offset;
+ topRightFront.y = offset;
+ topRightFront.z = offset;
+
+ }
+
+ static float tcfix = 0.00001f;
+
+ public void setTextureOffset(SpriteRectangle texRect) {
+ tcfix = (texRect.bottomRight.x - texRect.topLeft.x) / 512;
+ textureLeft = texRect.topLeft.x + tcfix;
+ textureRight = texRect.bottomRight.x - tcfix;
+ textureTop = texRect.topLeft.y + tcfix;
+ textureBottom = texRect.bottomRight.y - tcfix;
+ }
+
+ @Override
+ public int getMeshVertexCount(BlockType currentType, FloatBuffer renderLocation, boolean useShader) {
+ return 4 * ((renderBack ? 1 : 0) + (renderFront ? 1 : 0) + (renderLeft ? 1 : 0) + (renderRight ? 1 : 0)
+ + (renderBottom ? 1 : 0) + (renderTop ? 1 : 0));
+ }
+
+ @Override
+ public void putMesh(ImmModeMesh mesh, BlockType type, FloatBuffer location, boolean useShader) {
+ this.mesh = mesh;
+ mesh.enableColor4();
+ mesh.enableVertex3();
+ mesh.enableTexCoord2();
+ // mesh.enableNormal3();
+ mesh.glTranslate(location.get(0), location.get(1), location.get(2));
+ mesh.glColor4f(1, 1, 1, 1);
+ setPointOffset(0.5f * scale);
+ {
+ if (renderBack) {
+ setTextureOffset(type.getBackTextureOffset());
+ mesh.glNormal3f(0, 0, 1);
+ addBackQuad();
+ }
+ if (renderFront) {
+ setTextureOffset(type.getFrontTextureOffset());
+ mesh.glNormal3f(0, 0, -1);
+ addFrontQuad();
+ }
+ if (renderLeft) {
+ setTextureOffset(type.getLeftTextureOffset());
+ mesh.glNormal3f(1, 0, 0);
+ addLeftQuad();
+ }
+ if (renderRight) {
+ setTextureOffset(type.getRightTextureOffset());
+ mesh.glNormal3f(-1, 0, 1);
+ addRightQuad();
+ }
+ if (renderBottom) {
+ setTextureOffset(type.getBottomTextureOffset());
+ mesh.glNormal3f(0, -1, 0);
+ addBottomQuad();
+ }
+ if (renderTop) {
+ setTextureOffset(type.getTopTextureOffset());
+ mesh.glNormal3f(0, 1, 0);
+ addTopQuad();
+ }
+ }
+ }
+
+ @Override
+ public ImmModeMesh getMesh(BlockType type, FloatBuffer location, boolean glsl) {
+ mesh = ImmModeMesh.allocate(4 * 6); // 6 rectangles
+ mesh.setGLSL(glsl);
+ putMesh(mesh, type, location, glsl);
+ mesh.end();
+ return mesh;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/blockRenderer/ChunkMeshGarbageCollector.java b/src/ru/olamedia/olacraft/world/blockRenderer/ChunkMeshGarbageCollector.java
new file mode 100644
index 0000000..ad8bb81
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockRenderer/ChunkMeshGarbageCollector.java
@@ -0,0 +1,82 @@
+package ru.olamedia.olacraft.world.blockRenderer;
+
+import java.util.concurrent.ArrayBlockingQueue;
+
+import ru.olamedia.olacraft.game.Game;
+import ru.olamedia.olacraft.world.chunk.Chunk;
+import ru.olamedia.olacraft.world.chunk.ChunkSlice;
+import ru.olamedia.olacraft.world.location.BlockLocation;
+
+public class ChunkMeshGarbageCollector extends Thread {
+ public static ChunkMeshGarbageCollector instance = new ChunkMeshGarbageCollector("Mesh GC");
+ private ArrayBlockingQueue<Chunk> chunks = new ArrayBlockingQueue<Chunk>(32);
+
+ public ChunkMeshGarbageCollector(String name) {
+ super(name);
+ }
+
+ BlockLocation cameraBlock;
+ private int renderDistance;
+
+ public void lookup() {
+ renderDistance = Game.client.getScene().getPlayer().settings.renderDistance;
+ cameraBlock = Game.client.getScene().getPlayer().getCameraBlockLocation();
+ // FIXME: cuncurrent modification
+ for (Integer x : ChunkSlice.rendererInstance.iChunks.keySet()) {
+ for (Integer y : ChunkSlice.rendererInstance.iChunks.get(x).keySet()) {
+ for (Integer z : ChunkSlice.rendererInstance.iChunks.get(x).get(y).keySet()) {
+ if (isFull()) {
+ return;
+ }
+ Chunk chunk = ChunkSlice.rendererInstance.iChunks.get(x).get(y).get(z);
+ float d = (float) Math.sqrt(Math.pow(chunk.getOffset().x + 8 - cameraBlock.x, 2)
+ + Math.pow(chunk.getOffset().y + 8 - cameraBlock.y, 2)
+ + Math.pow(chunk.getOffset().z + 8 - cameraBlock.z, 2));
+ if (d > renderDistance + renderDistance / 4) {
+ add(chunk);
+ }
+ }
+ }
+ }
+ }
+
+ 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();
+ ChunkSlice.rendererInstance.removeChunk(chunk.location);
+ } else {
+ lookup();
+ }
+ }
+
+ @Override
+ public void run() {
+ // glc.makeCurrent();
+ while (true) {
+ // main loop
+ try {
+ tick();
+ if (chunks.isEmpty()) {
+ Thread.sleep(50);
+ }
+ // 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/blockRenderer/ChunkRenderer.java b/src/ru/olamedia/olacraft/world/blockRenderer/ChunkRenderer.java
new file mode 100644
index 0000000..f27eb76
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockRenderer/ChunkRenderer.java
@@ -0,0 +1,356 @@
+package ru.olamedia.olacraft.world.blockRenderer;
+
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.util.ArrayList;
+import java.util.concurrent.ArrayBlockingQueue;
+
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLUniformData;
+
+import com.jogamp.opengl.util.PMVMatrix;
+import com.jogamp.opengl.util.glsl.ShaderState;
+
+import ru.olamedia.asset.Shader;
+import ru.olamedia.geom.ChunkMesh;
+import ru.olamedia.geom.ImmModeMesh;
+import ru.olamedia.olacraft.game.Game;
+import ru.olamedia.olacraft.render.jogl.ChunkRangeRenderer;
+import ru.olamedia.olacraft.world.blockTypes.BlockType;
+import ru.olamedia.olacraft.world.calc.LightCalculator;
+import ru.olamedia.olacraft.world.calc.LightData;
+import ru.olamedia.olacraft.world.chunk.Chunk;
+import ru.olamedia.olacraft.world.chunk.ChunkUnavailableException;
+import ru.olamedia.olacraft.world.data.ChunkData;
+import ru.olamedia.olacraft.world.data.ChunkDataNeighbors;
+import ru.olamedia.olacraft.world.drop.DroppedEntity;
+import ru.olamedia.olacraft.world.location.BlockLocation;
+import ru.olamedia.olacraft.world.location.IntLocation;
+import ru.olamedia.olacraft.world.provider.WorldProvider;
+
+public class ChunkRenderer {
+ protected static WorldProvider provider;
+ protected static Chunk chunk;
+ protected static ChunkData data;
+ protected ChunkData top;
+ protected ChunkData bottom;
+ protected ChunkData left;
+ protected ChunkData right;
+ protected ChunkData front;
+ protected ChunkData back;
+
+ protected int[] visible;
+
+ public static int visibleCount = 0;
+ public static int visibleOpaqueCount = 0;
+ public static int vertexCount = 0;
+ public static int vertexOpaqueCount = 0;
+
+ public boolean isAvailable = false;
+ public boolean isCompiling = false;
+ public boolean isCompiled = false;
+ public boolean needRecompilation = true;
+
+ protected static ImmModeMesh mesh;
+ protected ImmModeMesh prevMesh;
+ protected ImmModeMesh[] meshes;
+
+ protected static ImmModeMesh opaqueMesh;
+ protected ImmModeMesh prevOpaqueMesh;
+ protected ImmModeMesh[] opaqueMeshes;
+
+ protected ImmModeMesh[] droppedMeshes;
+
+ protected ArrayBlockingQueue<ImmModeMesh> disposable = new ArrayBlockingQueue<ImmModeMesh>(4096);
+ int droppedEntityVertexCount = 0;
+
+ private static Shader shader = null;
+ public static GLUniformData pmvMatrixUniform;
+ public static GLUniformData sunColor;
+
+ private static boolean useShader = true;
+
+ public static Shader getShader() {
+ if (null == shader) {
+ shader = new Shader();
+ shader.compile();
+ final GL2ES2 gl = GLContext.getCurrentGL().getGL2ES2();
+ final ShaderState state = shader.getState();
+ final PMVMatrix pmvMatrix = Game.client.getScene().getPmvMatrix();
+ state.attachObject("pmvMatrix", pmvMatrix);
+ pmvMatrixUniform = new GLUniformData("pmvMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf());
+ state.ownUniform(pmvMatrixUniform);
+ state.uniform(gl, pmvMatrixUniform);
+
+ state.attachObject("sunColor", ChunkRenderer.sunColor);
+ sunColor = new GLUniformData("sunColor", 4, Game.client.getScene().dayTime.sunColor);
+ state.ownUniform(ChunkRenderer.sunColor);
+ state.uniform(gl, ChunkRenderer.sunColor);
+
+ // if (!state.uniform(gl, new GLUniformData("sunColor", 4,
+ // Game.client.getScene().time.sunColor))) {
+ // throw new GLException("Error setting sunColor in shader: " +
+ // state);
+ // }
+ if (!state.uniform(gl, new GLUniformData("mesh_ActiveTexture", 0))) {
+ throw new GLException("Error setting mesh_ActiveTexture in shader: " + state);
+ }
+ }
+ return shader;
+ }
+
+ public ChunkRenderer(Chunk chunk) {
+ this.chunk = chunk;
+ this.provider = chunk.getProvider();
+ }
+
+ public void invalidate() {
+ needRecompilation = true;
+ }
+
+ protected void disposeMesh(ImmModeMesh mesh) {
+ if (null != mesh) {
+ disposable.offer(mesh);
+ }
+ }
+
+ public void disposeMeshes() {
+ // while (!disposable.isEmpty()){
+ // final ImmModeMesh mesh = disposable.poll();
+ // mesh.dispose();
+ // }
+ }
+
+ private static IntBuffer blockLocation = IntBuffer.allocate(3);
+ private static FloatBuffer renderLocation = FloatBuffer.allocate(3);
+
+ private static short currentId;
+ private static BlockType currentType;
+ private static AbstractBlockRenderer currentRenderer;
+
+ private static void prepareRenderer(WorldProvider provider, Chunk chunk, ChunkData data) {
+ currentType = provider.getTypeRegistry().getBlockType(data.types[currentId]);
+ if (null == currentType) {
+ throw new RuntimeException("invalid type: " + currentType + " " + currentId);
+ }
+ final int x = currentId / 256;
+ final int y = (currentId - x * 256) / 16;
+ final int z = currentId - x * 256 - y * 16;
+ IntLocation.set(blockLocation, chunk.offset.x + x, chunk.offset.y + y, chunk.offset.z + z);
+ renderLocation.put(0, blockLocation.get(0));
+ renderLocation.put(1, blockLocation.get(1));
+ renderLocation.put(2, blockLocation.get(2));
+ // final RenderLocation location = new
+ // RenderLocation(blockLocation);
+ // System.out.println(chunk.location);
+ currentRenderer = currentType.getRenderer();
+ if (null == currentRenderer) {
+ throw new RuntimeException("invalid renderer: " + currentType.getClass().getName());
+ }
+ currentRenderer.setScale(1);
+ currentRenderer.setNeighbors(neighbors);
+ if (currentType.hideTouchedSides() || currentType.isOpaque()) {
+ // check each side
+ try {
+ currentRenderer.renderBottom = !provider.hideTouchedSides(blockLocation.get(0),
+ blockLocation.get(1) - 1, blockLocation.get(2), data.types[currentId]);
+ currentRenderer.renderTop = !provider.hideTouchedSides(blockLocation.get(0), blockLocation.get(1) + 1,
+ blockLocation.get(2), data.types[currentId]);
+ currentRenderer.renderLeft = !provider.hideTouchedSides(blockLocation.get(0) - 1, blockLocation.get(1),
+ blockLocation.get(2), data.types[currentId]);
+ currentRenderer.renderRight = !provider.hideTouchedSides(blockLocation.get(0) + 1,
+ blockLocation.get(1), blockLocation.get(2), data.types[currentId]);
+ currentRenderer.renderFront = !provider.hideTouchedSides(blockLocation.get(0), blockLocation.get(1),
+ blockLocation.get(2) + 1, data.types[currentId]);
+ currentRenderer.renderBack = !provider.hideTouchedSides(blockLocation.get(0), blockLocation.get(1),
+ blockLocation.get(2) - 1, data.types[currentId]);
+ } catch (ChunkUnavailableException e) {
+ e.printStackTrace();
+ }
+ } else {
+ currentRenderer.renderAllSides();
+ }
+ }
+
+ private static ChunkDataNeighbors neighbors = new ChunkDataNeighbors();
+
+ public static void compile(Chunk chunk) {
+ final ChunkMesh chunkMesh = chunk.mesh;
+ chunkMesh.setValid(true);
+ final WorldProvider provider = chunk.getProvider();
+ if (chunk.offset.y >= provider.getInfo().maxHeight) {
+ chunkMesh.setCompiled(true);
+ return;
+ }
+ if (chunk.offset.y < provider.getInfo().minHeight) {
+ chunkMesh.setCompiled(true);
+ return;
+ }
+
+ if (!chunk.isAvailable()) {
+ chunk.request();
+ return;
+ }
+ if (!chunk.isNeighborsAvailable()) {
+ chunk.requestNeighbors();
+ return;
+ }
+ final ChunkData data = chunk.getData();
+ neighbors.setProvider(provider);
+ neighbors.setData(data);
+ neighbors.loadNeighbors();
+ neighbors.calcLight();
+ neighbors.calcVisibility();
+ // data.computeVisibility(provider);
+ // updateVisibility();
+
+ // droppedEntityVertexCount = 0;
+ // if (!data.droppedEntities.isEmpty()) {
+ // droppedMeshes = new ImmModeMesh[data.droppedEntities.size()];
+ // int i = 0;
+ // for (DroppedEntity entity : data.droppedEntities) {
+ // droppedMeshes[i] = compileDroppedEntity(entity);
+ // droppedEntityVertexCount += droppedMeshes[i].getVertexCount();
+ // i++;
+ // }
+ // }
+ //
+ // vertexCount = droppedEntityVertexCount;
+ vertexCount = 0;
+ vertexOpaqueCount = 0;
+ for (currentId = 0; currentId < 4096; currentId++) {
+ if (neighbors.isVisible(currentId)) {
+ prepareRenderer(provider, chunk, data);
+ if (null != currentRenderer) {
+ if (currentType.isOpaque()) {
+ vertexOpaqueCount += currentRenderer.getMeshVertexCount(currentType, renderLocation, useShader);
+ } else {
+ vertexOpaqueCount += currentRenderer.getMeshVertexCount(currentType, renderLocation, useShader);
+ //vertexCount += currentRenderer.getMeshVertexCount(currentType, renderLocation, useShader);
+ }
+ }
+ }
+ }
+ if (vertexCount > 0) {
+ mesh = ImmModeMesh.allocate(vertexCount);
+ // mesh.setServer(true);
+ mesh.setGLSL(true);
+ mesh.enableColor4();
+ mesh.enableTexCoord2();
+ mesh.enableVertex3();
+ // mesh.enableNormal3();
+ mesh.beginQuads();
+ } else {
+ mesh = null;
+ }
+ if (vertexOpaqueCount > 0) {
+ opaqueMesh = ImmModeMesh.allocate(vertexOpaqueCount);
+ // opaqueMesh.setServer(true);
+ opaqueMesh.setGLSL(true);
+ opaqueMesh.enableColor4();
+ opaqueMesh.enableTexCoord2();
+ opaqueMesh.enableVertex3();
+ // opaqueMesh.enableNormal3();
+ opaqueMesh.beginQuads();
+ } else {
+ opaqueMesh = null;
+ }
+ for (currentId = 0; currentId < 4096; currentId++) {
+ if (neighbors.isVisible(currentId)) {
+ prepareRenderer(provider, chunk, data);
+ //if (currentType.isOpaque()) {
+ visibleOpaqueCount++;
+ if (vertexOpaqueCount > 0) {
+ currentRenderer.putMesh(opaqueMesh, currentType, renderLocation, useShader);
+ }
+ //} else {
+ // if (vertexCount > 0) {
+ // currentRenderer.putMesh(mesh, currentType, renderLocation, useShader);
+ // }
+ //}
+ }
+ }
+ if (vertexCount > 0) {
+ mesh.end();
+ mesh.compact();
+ }
+ if (vertexOpaqueCount > 0) {
+ opaqueMesh.end();
+ opaqueMesh.compact();
+ }
+ chunkMesh.setMesh(mesh);
+ chunkMesh.setOpaqueMesh(opaqueMesh);
+ }
+
+ public ImmModeMesh getOpaqueMesh() {
+ return opaqueMesh;
+ }
+
+ public ImmModeMesh getMesh() {
+ return mesh;
+ }
+
+ public ImmModeMesh compileDroppedEntity(DroppedEntity entity) {
+ final BlockType type = entity.stack.type;
+ final RenderLocation location = new RenderLocation(entity.location);
+ // int id = location.clampId();
+ // System.out.println(chunk.location);
+ final AbstractBlockRenderer renderer = type.getRenderer();
+ renderer.setScale(0.3f);
+ renderer.renderAllSides();
+ return renderer.getMesh(type, location, useShader);
+ }
+
+ public void render(int pass) {
+
+ if (!isCompiled || isCompiling || !isAvailable) {
+ // compile();
+ return;
+ }
+ if (pass == ChunkRangeRenderer.OPAQUE_PASS) {
+ if (null != opaqueMesh) {
+ opaqueMesh.draw();
+ } else if (null != prevOpaqueMesh) {
+ prevOpaqueMesh.draw();
+ }
+ } else {
+ if (null != mesh) {
+ mesh.draw();
+ } else if (null != prevMesh) {
+ prevMesh.draw();
+ }
+ }
+ /*
+ * if (!disposable.isEmpty()) {
+ * for (ImmModeMesh mesh : disposable) {
+ * mesh.dispose();
+ * }
+ * disposable.clear();
+ * }
+ */
+ }
+
+ public static void disableShader() {
+ getShader().disable();
+ }
+
+ public static void enableShader() {
+ // GL2ES2 gl = GLContext.getCurrentGL().getGL2ES2();
+ getShader().enable();
+ // Game.client.getScene().time.getClearColor();
+ // getShader().getState().uniform(gl, pmvMatrixUniform);
+ // getShader().getState().uniform(gl, sunColor);
+ }
+
+ public void destroy() {
+ isCompiling = true;
+ mesh = null;
+ prevMesh = null;
+ meshes = null;
+ needRecompilation = true;
+ isCompiled = false;
+ isCompiling = false;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/blockRenderer/CrossQuadsRenderer.java b/src/ru/olamedia/olacraft/world/blockRenderer/CrossQuadsRenderer.java
new file mode 100644
index 0000000..4dc14a6
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockRenderer/CrossQuadsRenderer.java
@@ -0,0 +1,115 @@
+package ru.olamedia.olacraft.world.blockRenderer;
+
+import java.nio.FloatBuffer;
+import java.util.HashMap;
+
+import ru.olamedia.geom.ImmModeMesh;
+import ru.olamedia.olacraft.world.blockTypes.BlockType;
+
+public class CrossQuadsRenderer extends BoxRenderer {
+ public static boolean useTriangles = false;
+ private HashMap<Integer, ImmModeMesh> precompiled = new HashMap<Integer, ImmModeMesh>();
+
+ public void addLeftQuad() {
+ // triangle strip: И
+ mesh.setUV(textureLeft, textureTop);
+ addTopLeftBackVertex();
+ mesh.setUV(textureLeft, textureBottom);
+ addBottomLeftBackVertex();
+ if (useTriangles) {
+ mesh.setUV(textureRight, textureBottom);
+ addBottomRightFrontVertex();
+
+ mesh.setUV(textureLeft, textureTop);
+ addTopLeftBackVertex();
+ }
+ mesh.setUV(textureRight, textureBottom);
+ addBottomRightFrontVertex();
+ mesh.setUV(textureRight, textureTop);
+ addTopRightFrontVertex();
+ // mirror
+ mesh.setUV(textureLeft, textureTop);
+ addTopRightFrontVertex();
+ mesh.setUV(textureLeft, textureBottom);
+ addBottomRightFrontVertex();
+ if (useTriangles) {
+ mesh.setUV(textureRight, textureBottom);
+ addBottomLeftBackVertex();
+
+ mesh.setUV(textureLeft, textureTop);
+ addTopRightFrontVertex();
+ }
+ mesh.setUV(textureRight, textureBottom);
+ addBottomLeftBackVertex();
+ mesh.setUV(textureRight, textureTop);
+ addTopLeftBackVertex();
+ }
+
+ public void addRightQuad() {
+ // triangle strip: И
+ mesh.setUV(textureLeft, textureTop);
+ addTopRightBackVertex();
+ mesh.setUV(textureLeft, textureBottom);
+ addBottomRightBackVertex();
+ if (useTriangles) {
+ mesh.setUV(textureLeft, textureTop);
+ addTopRightBackVertex();
+
+ mesh.setUV(textureRight, textureBottom);
+ addBottomLeftFrontVertex();
+ }
+ mesh.setUV(textureRight, textureBottom);
+ addBottomLeftFrontVertex();
+ mesh.setUV(textureRight, textureTop);
+ addTopLeftFrontVertex();
+ // mirror
+ mesh.setUV(textureLeft, textureTop);
+ addTopLeftFrontVertex();
+ mesh.setUV(textureLeft, textureBottom);
+ addBottomLeftFrontVertex();
+ if (useTriangles) {
+ mesh.setUV(textureRight, textureBottom);
+ addBottomRightBackVertex();
+
+ mesh.setUV(textureLeft, textureTop);
+ addTopLeftFrontVertex();
+ }
+ mesh.setUV(textureRight, textureBottom);
+ addBottomRightBackVertex();
+ mesh.setUV(textureRight, textureTop);
+ addTopRightBackVertex();
+ }
+
+ @Override
+ public int getMeshVertexCount(BlockType currentType, FloatBuffer renderLocation, boolean useShader) {
+ return 4 * 4;
+ }
+
+ @Override
+ public void putMesh(ImmModeMesh mesh, BlockType type, FloatBuffer location, boolean useShader) {
+ this.mesh = mesh;
+ // mesh.enableNormal3();
+ mesh.glNormal3f(1, 0, 0);
+ mesh.glTranslate(location.get(0), location.get(1), location.get(2));
+ mesh.glColor4f(1, 1, 1, 1f);
+ setPointOffset(0.5f * scale);
+ {
+ setTextureOffset(type.getLeftTextureOffset());
+ addLeftQuad();
+ addRightQuad();
+ }
+ }
+
+ @Override
+ public ImmModeMesh getMesh(BlockType type, FloatBuffer location, boolean glsl) {
+ mesh = ImmModeMesh.allocate(4 * 4); // 6 rectangles
+ mesh.enableColor4();
+ mesh.enableVertex3();
+ mesh.enableTexCoord2();
+ mesh.setGLSL(glsl);
+ putMesh(mesh, type, location, glsl);
+ mesh.end();
+ return mesh;
+ }
+
+}
diff --git a/src/ru/olamedia/olacraft/world/blockRenderer/IBlockRenderer.java b/src/ru/olamedia/olacraft/world/blockRenderer/IBlockRenderer.java
new file mode 100644
index 0000000..4d2a239
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockRenderer/IBlockRenderer.java
@@ -0,0 +1,15 @@
+package ru.olamedia.olacraft.world.blockRenderer;
+
+import ru.olamedia.geom.ImmModeMesh;
+import ru.olamedia.olacraft.world.blockTypes.BlockType;
+import ru.olamedia.olacraft.world.location.Location3f;
+import ru.olamedia.olacraft.world.location.Location3i;
+
+public interface IBlockRenderer {
+
+ public void render(BlockType type, Location3i location, boolean glsl);
+
+ public void render(BlockType type, Location3f location, boolean glsl);
+
+ public ImmModeMesh getMesh(BlockType type, Location3f location, boolean glsl);
+}
diff --git a/src/ru/olamedia/olacraft/world/blockRenderer/RenderLocation.java b/src/ru/olamedia/olacraft/world/blockRenderer/RenderLocation.java
new file mode 100644
index 0000000..b396010
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockRenderer/RenderLocation.java
@@ -0,0 +1,35 @@
+package ru.olamedia.olacraft.world.blockRenderer;
+
+import java.nio.IntBuffer;
+
+import ru.olamedia.olacraft.world.data.ChunkData;
+import ru.olamedia.olacraft.world.location.Location3f;
+import ru.olamedia.olacraft.world.location.Location3i;
+
+public class RenderLocation extends Location3f {
+ public RenderLocation(float x, float y, float z) {
+ super(x, y, z);
+ }
+
+ public RenderLocation(Location3i location) {
+ super(location);
+ }
+
+ public RenderLocation(Location3f location) {
+ super(location);
+ }
+
+ public RenderLocation(IntBuffer location) {
+ super(location.get(0), location.get(1), location.get(2));
+ }
+
+ public void set(float x, float y, float z) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public int clampId() {
+ return ChunkData.ClampID((int) x, (int) y, (int) z);
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/blockRenderer/package-info.java b/src/ru/olamedia/olacraft/world/blockRenderer/package-info.java
new file mode 100644
index 0000000..65ce990
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockRenderer/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.world.blockRenderer; \ 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
index 57258ef..0d6dd7f 100644
--- a/src/ru/olamedia/olacraft/world/blockStack/BlockStack.java
+++ b/src/ru/olamedia/olacraft/world/blockStack/BlockStack.java
@@ -1,13 +1,15 @@
package ru.olamedia.olacraft.world.blockStack;
-import ru.olamedia.olacraft.world.block.Block;
+import ru.olamedia.olacraft.world.blockTypes.AbstractBlockType;
+import ru.olamedia.olacraft.world.blockTypes.EmptyBlockType;
public class BlockStack {
- public Block block;
- public int count;
+ public AbstractBlockType type;
+ public int count = 0;
+ public boolean hidden = false; // do not render
- public BlockStack(Block block, int count) {
- this.block = block;
+ public BlockStack(AbstractBlockType type, int count) {
+ this.type = type;
this.count = count;
}
@@ -23,40 +25,40 @@ public class BlockStack {
} else {
c = count;
count = 0;
+ type = new EmptyBlockType();
}
- return new BlockStack(block, c);
+ return new BlockStack(type, c);
}
public BlockStack getAll() {
int c = count;
count = 0;
- return new BlockStack(block, c);
+ return new BlockStack(type, 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;
- }
+ public void putStack(BlockStack stack) {
+ if (!type.getClass().getName().equals(stack.type.getClass().getName())) {
+ try {
+ type = stack.type.getClass().newInstance();
+ } catch (InstantiationException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ } // replace
+ }
+ int max = type.getMaxStack();
+ // Stack
+ int total = count + stack.count;
+ if (total < max) {
+ count = total;
+ stack.count = 0;
+ stack.type = new EmptyBlockType();
} else {
- // Replace
- BlockStack remains = new BlockStack(block, count);
- block = stack.block;
- count = stack.count;
- return remains;
+ count = max;
+ stack.count = total - max;
}
}
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/AbstractBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/AbstractBlockType.java
index 717c01f..43e1332 100644
--- a/src/ru/olamedia/olacraft/world/blockTypes/AbstractBlockType.java
+++ b/src/ru/olamedia/olacraft/world/blockTypes/AbstractBlockType.java
@@ -2,12 +2,26 @@ package ru.olamedia.olacraft.world.blockTypes;
import com.jogamp.opengl.util.texture.Texture;
-import ru.olamedia.olacraft.world.block.BlockRegistry;
+import ru.olamedia.asset.SpriteRectangle;
+import ru.olamedia.olacraft.world.blockRenderer.AbstractBlockRenderer;
+import ru.olamedia.olacraft.world.blockRenderer.BoxRenderer;
+import ru.olamedia.olacraft.world.blockRenderer.RenderLocation;
+import ru.olamedia.olacraft.world.location.BlockLocation;
import ru.olamedia.olacraft.world.provider.WorldProvider;
import ru.olamedia.texture.TextureManager;
public abstract class AbstractBlockType implements BlockType {
+ protected AbstractBlockRenderer renderer = new BoxRenderer();
+
+ public void dropBlock(WorldProvider provider, BlockLocation location){
+ provider.dropBlock(location, this);
+ }
+
+ public AbstractBlockRenderer getRenderer() {
+ return this.renderer;
+ }
+
@Override
abstract public String getName();
@@ -16,6 +30,23 @@ public abstract class AbstractBlockType implements BlockType {
return 64;
}
+ public boolean isOpaque() { // solid, non-transparent block
+ return true;
+ }
+
+ public boolean isLoose() {
+ return false;
+ }
+
+ @Override
+ public boolean hideTouchedSides() {
+ return isOpaque();
+ }
+
+ public boolean canMoveThrough() {
+ return false;
+ }
+
@Override
abstract public String getStackTextureFile();
@@ -49,41 +80,88 @@ public abstract class AbstractBlockType implements BlockType {
@Override
public Texture getTopTexture() {
- return TextureManager.get(this.getTopTextureFile());
+ return TextureManager.getSprite(this.getTopTextureFile());
+ }
+
+ @Override
+ public SpriteRectangle getTopTextureOffset() {
+ return TextureManager.getSpriteOffset(this.getTopTextureFile());
}
@Override
public Texture getBottomTexture() {
- return TextureManager.get(this.getBottomTextureFile());
+ return TextureManager.getSprite(this.getBottomTextureFile());
+ }
+
+ @Override
+ public SpriteRectangle getBottomTextureOffset() {
+ return TextureManager.getSpriteOffset(this.getBottomTextureFile());
}
@Override
public Texture getLeftTexture() {
- return TextureManager.get(this.getLeftTextureFile());
+ return TextureManager.getSprite(this.getLeftTextureFile());
+ }
+
+ @Override
+ public SpriteRectangle getLeftTextureOffset() {
+ return TextureManager.getSpriteOffset(this.getLeftTextureFile());
}
@Override
public Texture getRightTexture() {
- return TextureManager.get(this.getRightTextureFile());
+ return TextureManager.getSprite(this.getRightTextureFile());
+ }
+
+ @Override
+ public SpriteRectangle getRightTextureOffset() {
+ return TextureManager.getSpriteOffset(this.getRightTextureFile());
}
@Override
public Texture getFrontTexture() {
- return TextureManager.get(this.getFrontTextureFile());
+ return TextureManager.getSprite(this.getFrontTextureFile());
+ }
+
+ @Override
+ public SpriteRectangle getFrontTextureOffset() {
+ return TextureManager.getSpriteOffset(this.getFrontTextureFile());
}
@Override
public Texture getBackTexture() {
- return TextureManager.get(this.getBackTextureFile());
+ return TextureManager.getSprite(this.getBackTextureFile());
}
-
- public void register(WorldProvider provider){
- getBackTexture();
- getBottomTexture();
- getFrontTexture();
- getLeftTexture();
- getRightTexture();
- getTopTexture();
- provider.getTypeRegistry().registerBlockType(this);
+
+ @Override
+ public SpriteRectangle getBackTextureOffset() {
+ return TextureManager.getSpriteOffset(this.getBackTextureFile());
+ }
+
+ public void register(WorldProvider provider, boolean registerTextures) {
+ if (registerTextures) {
+ getBackTexture();
+ getBottomTexture();
+ getFrontTexture();
+ getLeftTexture();
+ getRightTexture();
+ getTopTexture();
+ } else {
+ provider.getTypeRegistry().registerBlockType(this);
+ }
+ }
+
+ public int getId(WorldProvider provider) {
+ return provider.getTypeRegistry().getBlockIdByClassName(this.getClass().getName());
+ }
+
+ @Override
+ public void render(RenderLocation location) {
+ this.renderer.render(this, location, true);
+ }
+
+ @Override
+ public boolean isTimeManaged() {
+ return false;
}
}
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/BlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/BlockType.java
index 0bda2eb..d74dd6b 100644
--- a/src/ru/olamedia/olacraft/world/blockTypes/BlockType.java
+++ b/src/ru/olamedia/olacraft/world/blockTypes/BlockType.java
@@ -1,21 +1,83 @@
package ru.olamedia.olacraft.world.blockTypes;
+import ru.olamedia.asset.SpriteOffset;
+import ru.olamedia.asset.SpriteRectangle;
+import ru.olamedia.olacraft.world.blockRenderer.AbstractBlockRenderer;
+import ru.olamedia.olacraft.world.blockRenderer.IBlockRenderer;
+import ru.olamedia.olacraft.world.blockRenderer.RenderLocation;
+import ru.olamedia.olacraft.world.location.BlockLocation;
+import ru.olamedia.olacraft.world.provider.WorldProvider;
+
import com.jogamp.opengl.util.texture.Texture;
public interface BlockType {
public String getName();
+
public int getMaxStack();
+
+ public int getId(WorldProvider provider);
+
public String getStackTextureFile();
+
public String getTopTextureFile();
+
+ public SpriteRectangle getTopTextureOffset();
+
public String getBottomTextureFile();
+
+ public SpriteRectangle getBottomTextureOffset();
+
public String getLeftTextureFile();
+
+ public SpriteRectangle getLeftTextureOffset();
+
public String getRightTextureFile();
+
+ public SpriteRectangle getRightTextureOffset();
+
public String getFrontTextureFile();
+
+ public SpriteRectangle getFrontTextureOffset();
+
public String getBackTextureFile();
+
+ public SpriteRectangle getBackTextureOffset();
+
public Texture getTopTexture();
+
public Texture getBottomTexture();
+
public Texture getLeftTexture();
+
public Texture getRightTexture();
+
public Texture getFrontTexture();
+
public Texture getBackTexture();
+
+ /**
+ * Is block solid and completely non-transparent
+ */
+ public boolean isOpaque();
+
+ /**
+ * Is block solid and we can remove sides if touched by another solid block
+ */
+ public boolean hideTouchedSides();
+
+ /**
+ * Is block loose
+ */
+ public boolean isLoose();
+
+ /**
+ * Can live entities move through this block
+ */
+ public boolean canMoveThrough();
+
+ public AbstractBlockRenderer getRenderer();
+
+ public void render(RenderLocation location);
+
+ public boolean isTimeManaged();
}
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/DirtBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/DirtBlockType.java
index a4e5dd7..b359b08 100644
--- a/src/ru/olamedia/olacraft/world/blockTypes/DirtBlockType.java
+++ b/src/ru/olamedia/olacraft/world/blockTypes/DirtBlockType.java
@@ -3,7 +3,11 @@ package ru.olamedia.olacraft.world.blockTypes;
public class DirtBlockType extends AbstractBlockType {
@Override
public String getName() {
- return "Gravel";
+ return "Dirt";
+ }
+
+ public boolean isLoose() {
+ return true;
}
@Override
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/EmptyBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/EmptyBlockType.java
index 4073356..595c977 100644
--- a/src/ru/olamedia/olacraft/world/blockTypes/EmptyBlockType.java
+++ b/src/ru/olamedia/olacraft/world/blockTypes/EmptyBlockType.java
@@ -3,7 +3,7 @@ package ru.olamedia.olacraft.world.blockTypes;
public class EmptyBlockType extends AbstractBlockType {
@Override
public String getName() {
- return "";
+ return "Empty";
}
@Override
@@ -20,4 +20,8 @@ public class EmptyBlockType extends AbstractBlockType {
public String getTopTextureFile() {
return "texture/empty.png";
}
+ @Override
+ public boolean isOpaque() {
+ return false;
+ }
}
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/GrassBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/GrassBlockType.java
index d863139..6104d13 100644
--- a/src/ru/olamedia/olacraft/world/blockTypes/GrassBlockType.java
+++ b/src/ru/olamedia/olacraft/world/blockTypes/GrassBlockType.java
@@ -6,6 +6,10 @@ public class GrassBlockType extends AbstractBlockType {
return "Grass";
}
+ public boolean isLoose() {
+ return true;
+ }
+
@Override
public int getMaxStack() {
return 64;
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/GravelBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/GravelBlockType.java
index 354d383..e013148 100644
--- a/src/ru/olamedia/olacraft/world/blockTypes/GravelBlockType.java
+++ b/src/ru/olamedia/olacraft/world/blockTypes/GravelBlockType.java
@@ -6,6 +6,10 @@ public class GravelBlockType extends AbstractBlockType {
return "Gravel";
}
+ public boolean isLoose() {
+ return true;
+ }
+
@Override
public int getMaxStack() {
return 64;
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/IceBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/IceBlockType.java
new file mode 100644
index 0000000..a5c6767
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockTypes/IceBlockType.java
@@ -0,0 +1,32 @@
+package ru.olamedia.olacraft.world.blockTypes;
+
+public class IceBlockType extends AbstractBlockType {
+ @Override
+ public String getName() {
+ return "Ice";
+ }
+
+ public boolean isLoose() {
+ return true;
+ }
+
+ @Override
+ public boolean isOpaque() {
+ return true;
+ }
+
+ @Override
+ public int getMaxStack() {
+ return 1;
+ }
+
+ @Override
+ public String getStackTextureFile() {
+ return "texture/ice.png";
+ }
+
+ @Override
+ public String getTopTextureFile() {
+ return "texture/ice.png";
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/SnowBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/SnowBlockType.java
new file mode 100644
index 0000000..18697e4
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockTypes/SnowBlockType.java
@@ -0,0 +1,27 @@
+package ru.olamedia.olacraft.world.blockTypes;
+
+public class SnowBlockType extends AbstractBlockType {
+ @Override
+ public String getName() {
+ return "Snow";
+ }
+
+ public boolean isLoose() {
+ return true;
+ }
+
+ @Override
+ public int getMaxStack() {
+ return 1;
+ }
+
+ @Override
+ public String getStackTextureFile() {
+ return "texture/snow.png";
+ }
+
+ @Override
+ public String getTopTextureFile() {
+ return "texture/snow.png";
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/TallGrassBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/TallGrassBlockType.java
new file mode 100644
index 0000000..c277d72
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockTypes/TallGrassBlockType.java
@@ -0,0 +1,58 @@
+package ru.olamedia.olacraft.world.blockTypes;
+
+import ru.olamedia.olacraft.world.blockRenderer.AbstractBlockRenderer;
+import ru.olamedia.olacraft.world.blockRenderer.CrossQuadsRenderer;
+
+public class TallGrassBlockType extends AbstractBlockType {
+
+ protected AbstractBlockRenderer renderer = new CrossQuadsRenderer();
+
+ @Override
+ public AbstractBlockRenderer getRenderer() {
+ return this.renderer;
+ }
+
+ @Override
+ public String getName() {
+ return "Tall Grass";
+ }
+
+ @Override
+ public boolean canMoveThrough() {
+ return true;
+ }
+
+ public boolean isLoose() {
+ return false;
+ }
+
+ @Override
+ public boolean isOpaque() {
+ return false;
+ }
+
+ @Override
+ public int getMaxStack() {
+ return 64;
+ }
+
+ @Override
+ public String getStackTextureFile() {
+ return "texture/terrain-wheatgrass-lightgreen-med.png";
+ }
+
+ @Override
+ public String getTopTextureFile() {
+ return "texture/terrain-wheatgrass-lightgreen-med.png";
+ }
+
+ @Override
+ public String getFrontTextureFile() {
+ return "texture/terrain-wheatgrass-lightgreen-med.png";
+ }
+
+ @Override
+ public boolean isTimeManaged() {
+ return true;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/WaterBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/WaterBlockType.java
new file mode 100644
index 0000000..0ff984f
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockTypes/WaterBlockType.java
@@ -0,0 +1,42 @@
+package ru.olamedia.olacraft.world.blockTypes;
+
+public class WaterBlockType extends AbstractBlockType {
+ @Override
+ public String getName() {
+ return "Water";
+ }
+
+ public boolean isLoose() {
+ return true;
+ }
+
+ @Override
+ public int getMaxStack() {
+ return 1;
+ }
+
+ @Override
+ public boolean isOpaque() {
+ return false;
+ }
+
+ @Override
+ public boolean hideTouchedSides() {
+ return true;
+ }
+
+ @Override
+ public boolean canMoveThrough() {
+ return true;
+ }
+
+ @Override
+ public String getStackTextureFile() {
+ return "texture/water.png";
+ }
+
+ @Override
+ public String getTopTextureFile() {
+ return "texture/water.png";
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/WheatBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/WheatBlockType.java
new file mode 100644
index 0000000..583e91a
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockTypes/WheatBlockType.java
@@ -0,0 +1,58 @@
+package ru.olamedia.olacraft.world.blockTypes;
+
+import ru.olamedia.olacraft.world.blockRenderer.AbstractBlockRenderer;
+import ru.olamedia.olacraft.world.blockRenderer.CrossQuadsRenderer;
+
+public class WheatBlockType extends AbstractBlockType {
+
+ protected AbstractBlockRenderer renderer = new CrossQuadsRenderer();
+
+ @Override
+ public AbstractBlockRenderer getRenderer() {
+ return this.renderer;
+ }
+
+ @Override
+ public String getName() {
+ return "Wheat";
+ }
+
+ @Override
+ public boolean canMoveThrough() {
+ return true;
+ }
+
+ public boolean isLoose() {
+ return false;
+ }
+
+ @Override
+ public boolean isOpaque() {
+ return false;
+ }
+
+ @Override
+ public int getMaxStack() {
+ return 64;
+ }
+
+ @Override
+ public String getStackTextureFile() {
+ return "texture/wheat.png";
+ }
+
+ @Override
+ public String getTopTextureFile() {
+ return "texture/wheat.png";
+ }
+
+ @Override
+ public String getFrontTextureFile() {
+ return "texture/wheat.png";
+ }
+
+ @Override
+ public boolean isTimeManaged() {
+ return true;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/stone/BrecciaStoneBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/stone/BrecciaStoneBlockType.java
new file mode 100644
index 0000000..187938b
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockTypes/stone/BrecciaStoneBlockType.java
@@ -0,0 +1,25 @@
+package ru.olamedia.olacraft.world.blockTypes.stone;
+
+import ru.olamedia.olacraft.world.blockTypes.AbstractBlockType;
+
+public class BrecciaStoneBlockType extends AbstractBlockType {
+ @Override
+ public String getName() {
+ return "Breccia";
+ }
+
+ @Override
+ public int getMaxStack() {
+ return 64;
+ }
+
+ @Override
+ public String getStackTextureFile() {
+ return "texture/stone/sedimentary/breccia.png";
+ }
+
+ @Override
+ public String getTopTextureFile() {
+ return "texture/stone/sedimentary/breccia.png";
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/stone/ChertStoneBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/stone/ChertStoneBlockType.java
new file mode 100644
index 0000000..706abfc
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockTypes/stone/ChertStoneBlockType.java
@@ -0,0 +1,25 @@
+package ru.olamedia.olacraft.world.blockTypes.stone;
+
+import ru.olamedia.olacraft.world.blockTypes.AbstractBlockType;
+
+public class ChertStoneBlockType extends AbstractBlockType {
+ @Override
+ public String getName() {
+ return "Chert";
+ }
+
+ @Override
+ public int getMaxStack() {
+ return 64;
+ }
+
+ @Override
+ public String getStackTextureFile() {
+ return "texture/stone/sedimentary/chert.png";
+ }
+
+ @Override
+ public String getTopTextureFile() {
+ return "texture/stone/sedimentary/chert.png";
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/stone/CoalStoneBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/stone/CoalStoneBlockType.java
new file mode 100644
index 0000000..fe06c3d
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockTypes/stone/CoalStoneBlockType.java
@@ -0,0 +1,25 @@
+package ru.olamedia.olacraft.world.blockTypes.stone;
+
+import ru.olamedia.olacraft.world.blockTypes.AbstractBlockType;
+
+public class CoalStoneBlockType extends AbstractBlockType {
+ @Override
+ public String getName() {
+ return "Coal";
+ }
+
+ @Override
+ public int getMaxStack() {
+ return 64;
+ }
+
+ @Override
+ public String getStackTextureFile() {
+ return "texture/stone/sedimentary/coal.png";
+ }
+
+ @Override
+ public String getTopTextureFile() {
+ return "texture/stone/sedimentary/coal.png";
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/stone/ConglomerateStoneBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/stone/ConglomerateStoneBlockType.java
new file mode 100644
index 0000000..e3829b2
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockTypes/stone/ConglomerateStoneBlockType.java
@@ -0,0 +1,25 @@
+package ru.olamedia.olacraft.world.blockTypes.stone;
+
+import ru.olamedia.olacraft.world.blockTypes.AbstractBlockType;
+
+public class ConglomerateStoneBlockType extends AbstractBlockType {
+ @Override
+ public String getName() {
+ return "Conglomerate";
+ }
+
+ @Override
+ public int getMaxStack() {
+ return 64;
+ }
+
+ @Override
+ public String getStackTextureFile() {
+ return "texture/stone/sedimentary/conglomerate.png";
+ }
+
+ @Override
+ public String getTopTextureFile() {
+ return "texture/stone/sedimentary/conglomerate.png";
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/stone/LimestoneStoneBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/stone/LimestoneStoneBlockType.java
new file mode 100644
index 0000000..bb49e9c
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockTypes/stone/LimestoneStoneBlockType.java
@@ -0,0 +1,25 @@
+package ru.olamedia.olacraft.world.blockTypes.stone;
+
+import ru.olamedia.olacraft.world.blockTypes.AbstractBlockType;
+
+public class LimestoneStoneBlockType extends AbstractBlockType {
+ @Override
+ public String getName() {
+ return "Limestone";
+ }
+
+ @Override
+ public int getMaxStack() {
+ return 64;
+ }
+
+ @Override
+ public String getStackTextureFile() {
+ return "texture/stone/sedimentary/limestone.png";
+ }
+
+ @Override
+ public String getTopTextureFile() {
+ return "texture/stone/sedimentary/limestone.png";
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/stone/SandstoneStoneBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/stone/SandstoneStoneBlockType.java
new file mode 100644
index 0000000..c91bdce
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockTypes/stone/SandstoneStoneBlockType.java
@@ -0,0 +1,25 @@
+package ru.olamedia.olacraft.world.blockTypes.stone;
+
+import ru.olamedia.olacraft.world.blockTypes.AbstractBlockType;
+
+public class SandstoneStoneBlockType extends AbstractBlockType {
+ @Override
+ public String getName() {
+ return "Sandstone";
+ }
+
+ @Override
+ public int getMaxStack() {
+ return 64;
+ }
+
+ @Override
+ public String getStackTextureFile() {
+ return "texture/stone/sedimentary/sandstone.png";
+ }
+
+ @Override
+ public String getTopTextureFile() {
+ return "texture/stone/sedimentary/sandstone.png";
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/stone/ShaleStoneBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/stone/ShaleStoneBlockType.java
new file mode 100644
index 0000000..e099227
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockTypes/stone/ShaleStoneBlockType.java
@@ -0,0 +1,25 @@
+package ru.olamedia.olacraft.world.blockTypes.stone;
+
+import ru.olamedia.olacraft.world.blockTypes.AbstractBlockType;
+
+public class ShaleStoneBlockType extends AbstractBlockType {
+ @Override
+ public String getName() {
+ return "Stone";
+ }
+
+ @Override
+ public int getMaxStack() {
+ return 64;
+ }
+
+ @Override
+ public String getStackTextureFile() {
+ return "texture/stone/sedimentary/shale.png";
+ }
+
+ @Override
+ public String getTopTextureFile() {
+ return "texture/stone/sedimentary/shale.png";
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/stone/SiltstoneStoneBlockType.java b/src/ru/olamedia/olacraft/world/blockTypes/stone/SiltstoneStoneBlockType.java
new file mode 100644
index 0000000..db1a0f3
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockTypes/stone/SiltstoneStoneBlockType.java
@@ -0,0 +1,25 @@
+package ru.olamedia.olacraft.world.blockTypes.stone;
+
+import ru.olamedia.olacraft.world.blockTypes.AbstractBlockType;
+
+public class SiltstoneStoneBlockType extends AbstractBlockType {
+ @Override
+ public String getName() {
+ return "Stone";
+ }
+
+ @Override
+ public int getMaxStack() {
+ return 64;
+ }
+
+ @Override
+ public String getStackTextureFile() {
+ return "texture/stone/sedimentary/siltstone.png";
+ }
+
+ @Override
+ public String getTopTextureFile() {
+ return "texture/stone/sedimentary/siltstone.png";
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/blockTypes/stone/package-info.java b/src/ru/olamedia/olacraft/world/blockTypes/stone/package-info.java
new file mode 100644
index 0000000..dd284af
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/blockTypes/stone/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.world.blockTypes.stone; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/world/calc/LightCalculator.java b/src/ru/olamedia/olacraft/world/calc/LightCalculator.java
new file mode 100644
index 0000000..7f55f71
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/calc/LightCalculator.java
@@ -0,0 +1,118 @@
+package ru.olamedia.olacraft.world.calc;
+
+import ru.olamedia.olacraft.world.data.ChunkData;
+import ru.olamedia.olacraft.world.data.ChunkDataNeighbors;
+import ru.olamedia.olacraft.world.data.ChunkDataWrapper;
+import ru.olamedia.olacraft.world.location.IntLocation;
+
+public class LightCalculator {
+
+ private static final byte fallingLight = 15;
+ private static boolean exposed = true;
+
+ public static void calculateVoidLightIgnoreNeighbors(ChunkDataWrapper dataWrapper) {
+ precalculateVoidLight(dataWrapper);
+ spreadVoidLightIgnoreNeighbors(dataWrapper);
+ }
+
+ public static void precalculateVoidLight(ChunkDataWrapper dataWrapper) {
+ final ChunkData data = dataWrapper.getData();
+ final LightData light = dataWrapper.getLight();
+ for (int x = 0; x <= 15; x++) {
+ for (int z = 0; z <= 15; z++) {
+ // FIXME (heightmap)
+ // falling from top
+ exposed = true;
+ for (byte y = 15; y >= 0; y--) {
+ final short id = IntLocation.id(x, y, z);
+ if (data.isEmpty(id)) {
+ if (exposed) {
+ light.setVoidLight(id, fallingLight);
+ } else {
+ light.setVoidLight(id, (byte) 0);
+ }
+ } else {
+ exposed = false;
+ light.setVoidLight(id, (byte) 0);
+ }
+ }
+ }
+ }
+ }
+
+ public static byte max(byte a, byte b, byte c, byte d) {
+ return max(max(a, b), max(c, d));
+ }
+
+ public static byte max(byte a, byte b) {
+ return a > b ? a : b;
+ }
+
+ public static void spreadVoidLightIgnoreNeighbors(ChunkDataWrapper dataWrapper) {
+ final ChunkData data = dataWrapper.getData();
+ final LightData light = dataWrapper.getLight();
+ for (byte i = 0; i < 15; i++) {
+ for (byte x = 0; x <= 15; x++) {
+ for (byte z = 0; z <= 15; z++) {
+ for (byte y = 0; y <= 15; y++) {
+ final short id = IntLocation.id(x, y, z);
+ if (data.isEmpty(id)) {
+ final byte current = light.getVoidLight(id);
+ if (current < 15) {
+ final byte top = (y == 15) ? 0 : (byte) (light
+ .getVoidLight(IntLocation.id(x, y + 1, z)) - 1);
+ final byte bottom = (y == 0) ? 0 : (byte) (light.getVoidLight(IntLocation.id(x, y - 1,
+ z)) - 1);
+ final byte left = (x == 0) ? 0 : (byte) (light
+ .getVoidLight(IntLocation.id(x - 1, y, z)) - 1);
+ final byte right = (x == 15) ? 0 : (byte) (light.getVoidLight(IntLocation.id(x + 1, y,
+ z)) - 1);
+ final byte front = (z == 15) ? 0 : (byte) (light.getVoidLight(IntLocation.id(x, y,
+ z + 1)) - 1);
+ final byte back = (z == 0) ? 0 : (byte) (light
+ .getVoidLight(IntLocation.id(x, y, z - 1)) - 1);
+ light.setVoidLight(id,
+ max(max(top, bottom, left, right), max(max(front, back), current)));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public static void spreadVoidLight(ChunkDataNeighbors neighbors) {
+ final LightData light = neighbors.getCenter().getLight();
+ for (byte x = 0; x <= 15; x++) {
+ for (byte z = 0; z <= 15; z++) {
+ for (byte y = 0; y <= 15; y++) {
+ final LightData topData = y == 15 ? neighbors.getTop().getLight() : light;
+ final LightData bottomData = y == 0 ? neighbors.getBottom().getLight() : light;
+ final LightData leftData = x == 0 ? neighbors.getLeft().getLight() : light;
+ final LightData rightData = x == 15 ? neighbors.getRight().getLight() : light;
+ final LightData frontData = z == 15 ? neighbors.getFront().getLight() : light;
+ final LightData backData = z == 0 ? neighbors.getBack().getLight() : light;
+ final short id = IntLocation.id(x, y, z);
+ if (neighbors.getCenterData().isEmpty(id)) {
+ final byte current = light.getVoidLight(id);
+ if (current < 15) {
+ final byte top = (byte) (topData.getVoidLight(IntLocation.id(x, y + 1, z)) - 1);
+ final byte bottom = (byte) (bottomData.getVoidLight(IntLocation.id(x, y - 1, z)) - 1);
+ final byte left = (byte) (leftData.getVoidLight(IntLocation.id(x - 1, y, z)) - 1);
+ final byte right = (byte) (rightData.getVoidLight(IntLocation.id(x + 1, y, z)) - 1);
+ final byte front = (byte) (frontData.getVoidLight(IntLocation.id(x, y, z + 1)) - 1);
+ final byte back = (byte) (backData.getVoidLight(IntLocation.id(x, y, z - 1)) - 1);
+ final byte tb = (top > bottom ? top : bottom);
+ final byte lr = (left > right ? left : right);
+ final byte fb = (front > back ? front : back);
+ final byte tblr = (tb > lr ? tb : lr);
+ final byte fbc = (fb > current ? fb : current);
+ light.setVoidLight(id, (tblr > fbc ? tblr : fbc));
+ }
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/src/ru/olamedia/olacraft/world/calc/LightData.java b/src/ru/olamedia/olacraft/world/calc/LightData.java
new file mode 100644
index 0000000..62a91fd
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/calc/LightData.java
@@ -0,0 +1,28 @@
+package ru.olamedia.olacraft.world.calc;
+
+public class LightData {
+ private byte[] light = new byte[4096];
+
+ public byte getVoidLight(short id) {
+ return (byte) (light[id] & 15);
+ }
+
+ public void setVoidLight(short id, byte value) {
+ if (value != getVoidLight(id)) {
+ // voidLightChanged = true;
+ }
+ light[id] = (byte) ((getEmitLight(id) << 4) | value);
+ }
+
+ public byte getEmitLight(short id) {
+ return (byte) ((light[id] >> 4) & 15);
+ }
+
+ public void setEmitLight(short id, byte value) {
+ light[id] = (byte) ((light[id] & 15) | (value << 4));
+ }
+
+ public void reset() {
+ light = null;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/calc/VisibilityCalculator.java b/src/ru/olamedia/olacraft/world/calc/VisibilityCalculator.java
new file mode 100644
index 0000000..3009697
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/calc/VisibilityCalculator.java
@@ -0,0 +1,99 @@
+package ru.olamedia.olacraft.world.calc;
+
+import ru.olamedia.olacraft.world.data.ChunkData;
+import ru.olamedia.olacraft.world.data.ChunkDataNeighbors;
+import ru.olamedia.olacraft.world.location.IntLocation;
+import ru.olamedia.olacraft.world.provider.WorldProvider;
+
+public class VisibilityCalculator {
+ /**
+ * Compute visibility ("visible" if any side have non-opaque neighbor)
+ * Leaving side blocks invisible. Use computeVisibility(WorldProvider) to
+ * compute visibility of side blocks
+ */
+ public static void precomputeVisibility(ChunkDataNeighbors neighbors) {
+ final VisibilityData v = neighbors.getCenter().getVisibility();
+ // first pass, make all blocks invisible, except side blocks
+ v.setAllInvisible();
+ // second pass, make some blocks visible
+ short id = 0;
+ for (byte x = 0; x <= 15; x++) {
+ for (byte y = 0; y <= 15; y++) {
+ for (byte z = 0; z <= 15; z++) {
+ if (!neighbors.isOpaque(id)) {
+ setVisible(v, (byte) (x - 1), y, z);
+ setVisible(v, (byte) (x + 1), y, z);
+ setVisible(v, x, (byte) (y - 1), z);
+ setVisible(v, x, (byte) (y + 1), z);
+ setVisible(v, x, y, (byte) (z - 1));
+ setVisible(v, x, y, (byte) (z + 1));
+ }
+ id++;
+ }
+ }
+ }
+ }
+
+ public static void computeVisibility(VisibilityData v, WorldProvider provider, ChunkData left, ChunkData right,
+ ChunkData top, ChunkData bottom, ChunkData front, ChunkData back) {
+ // compute left/right
+ byte x, y, z;
+ short id;
+ for (y = 0; y <= 15; y++) {
+ for (z = 0; z <= 15; z++) {
+ x = 15;
+ id = IntLocation.id(x, y, z);
+ if (!left.isOpaque(provider, id)) {
+ x = 0;
+ setVisible(v, x, y, z);
+ }
+ x = 0;
+ id = IntLocation.id(x, y, z);
+ if (!right.isOpaque(provider, id)) {
+ x = 15;
+ setVisible(v, x, y, z);
+ }
+ }
+ }
+ // top/bottom
+ for (x = 0; x <= 15; x++) {
+ for (z = 0; z <= 15; z++) {
+ y = 15;
+ id = IntLocation.id(x, y, z);
+ if (!bottom.isOpaque(provider, id)) {
+ y = 0;
+ setVisible(v, x, y, z);
+ }
+ y = 0;
+ id = IntLocation.id(x, y, z);
+ if (!top.isOpaque(provider, id)) {
+ y = 15;
+ setVisible(v, x, y, z);
+ }
+ }
+ }
+ // front/back
+ for (x = 0; x <= 15; x++) {
+ for (y = 0; y <= 15; y++) {
+ z = 15;
+ id = IntLocation.id(x, y, z);
+ if (!back.isOpaque(provider, id)) {
+ z = 0;
+ setVisible(v, x, y, z);
+ }
+ z = 0;
+ id = IntLocation.id(x, y, z);
+ if (!front.isOpaque(provider, id)) {
+ z = 15;
+ setVisible(v, x, y, z);
+ }
+ }
+ }
+ }
+
+ private static void setVisible(VisibilityData v, byte x, byte y, byte z) {
+ if (IntLocation.inRange(x, y, z)) {
+ v.setVisible(IntLocation.id(x, y, z));
+ }
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/calc/VisibilityData.java b/src/ru/olamedia/olacraft/world/calc/VisibilityData.java
new file mode 100644
index 0000000..3e61cb3
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/calc/VisibilityData.java
@@ -0,0 +1,30 @@
+package ru.olamedia.olacraft.world.calc;
+
+import ru.olamedia.math.OpenBitSet;
+
+public class VisibilityData {
+ private OpenBitSet visibility = new OpenBitSet(4096);
+
+ public void setVisible(short id) {
+ visibility.set(id);
+ }
+
+ public void setAllInvisible() {
+ for (short id = 0; id < 4096; id++) {
+ visibility.clear(id);
+ }
+ }
+
+ public void setInvisible(short id) {
+ visibility.clear(id);
+ }
+
+ public boolean isVisible(short id) {
+ return visibility.get(id);
+ }
+
+ public void reset() {
+ visibility = null;
+ }
+
+}
diff --git a/src/ru/olamedia/olacraft/world/calc/package-info.java b/src/ru/olamedia/olacraft/world/calc/package-info.java
new file mode 100644
index 0000000..ce047c7
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/calc/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.world.calc; \ 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
index d02999d..3da74f2 100644
--- a/src/ru/olamedia/olacraft/world/chunk/BlockSlice.java
+++ b/src/ru/olamedia/olacraft/world/chunk/BlockSlice.java
@@ -10,7 +10,7 @@ import ru.olamedia.olacraft.world.provider.WorldProvider;
public class BlockSlice implements Iterator<Block> {
protected WorldProvider provider;
- protected BlockLocation offset;
+ public BlockLocation offset;
protected int width;
protected int height;
protected int depth;
@@ -19,25 +19,31 @@ public class BlockSlice implements Iterator<Block> {
private int itY = 0;
private int itZ = 0;
+ private Block nearestPlaceholder = null;
+ Block nearestBlock = null;
+
public Block getNearest(MatrixCamera cam) {
+ nearestPlaceholder = null;
+ nearestBlock = null;
float notEmptyBlockDistance = Float.MAX_VALUE;
- Block nearestBlock = null;
while (hasNext()) {
Block b = next();
try {
if (!b.isEmpty()) {
- float d = b.getDistance(cam);
- //System.out.print("d: " + d + " ");
- if (d <= notEmptyBlockDistance) {
+ final float d = b.getDistance(cam);
+ if (d < notEmptyBlockDistance) {
notEmptyBlockDistance = d;
nearestBlock = b;
}
}
} catch (ChunkUnavailableException e) {
- //e.printStackTrace();
b.request();
}
}
+ if (null != nearestBlock) {
+ nearestPlaceholder = new Block(provider, nearestBlock.location.x + nearestBlock.nearestX,
+ nearestBlock.location.y + +nearestBlock.nearestY, nearestBlock.location.z + +nearestBlock.nearestZ);
+ }
return nearestBlock;
}
@@ -202,4 +208,8 @@ public class BlockSlice implements Iterator<Block> {
public void setCenter(float x, float y, float z) {
setCenter((int) x, (int) y, (int) z);
}
+
+ public Block getNearestPutBlock() {
+ return nearestPlaceholder;
+ }
}
diff --git a/src/ru/olamedia/olacraft/world/chunk/Chunk.java b/src/ru/olamedia/olacraft/world/chunk/Chunk.java
index f390ebc..51b78c5 100644
--- a/src/ru/olamedia/olacraft/world/chunk/Chunk.java
+++ b/src/ru/olamedia/olacraft/world/chunk/Chunk.java
@@ -1,7 +1,8 @@
package ru.olamedia.olacraft.world.chunk;
+import ru.olamedia.geom.ChunkMesh;
import ru.olamedia.geom.SimpleQuadMesh;
-import ru.olamedia.olacraft.world.blockTypes.BlockType;
+import ru.olamedia.olacraft.world.blockRenderer.ChunkRenderer;
import ru.olamedia.olacraft.world.data.ChunkData;
import ru.olamedia.olacraft.world.location.BlockLocation;
import ru.olamedia.olacraft.world.location.ChunkLocation;
@@ -9,9 +10,7 @@ import ru.olamedia.olacraft.world.provider.WorldProvider;
public class Chunk extends BlockSlice {
public boolean isMeshCostructed = false;
- public SimpleQuadMesh mesh;
public boolean usePrevMesh = false;
- public SimpleQuadMesh prevMesh;
public int visibleTop = 0;
public int visibleBottom = 0;
@@ -19,28 +18,21 @@ public class Chunk extends BlockSlice {
public int visibleRight = 0;
public int visibleFront = 0;
public int visibleBack = 0;
+ public ChunkLocation location;
- public void render() {
- if (isMeshCostructed) {
- mesh.joglRender();
- } else if (usePrevMesh) {
- prevMesh.joglRender();
- }
+ public ChunkMesh mesh = new ChunkMesh();
+
+ public void render(int pass) {
+ mesh.render(pass);
}
public void invalidate() {
- if (null != mesh) {
- prevMesh = mesh;
- usePrevMesh = true;
- if (null != mesh) {
- mesh.restart();
- }
- }
- isMeshCostructed = false;
+ mesh.setValid(false);
}
- public Chunk(WorldProvider provider) {
+ public Chunk(WorldProvider provider, ChunkLocation location) {
super(provider, 16, 16, 16);
+ setLocation(location);
}
/**
@@ -98,159 +90,78 @@ public class Chunk extends BlockSlice {
// }
}
+ public void setMeshBrightness(ChunkData origin, ChunkData data, short id, boolean side) {
+ // data.calculateVoidLight(provider);
+ // float[] sunlight = Game.client.getScene().time.getClearColor();
+ // byte lv = data.getVoidLight(id);
+ // light = lightValues[lv];
+ // if (side && lv > 0) {
+ // light = lightValues[lv - 1];
+ // }
+ // lightR = light;// * sunlight[0];
+ // lightG = light;// * sunlight[1];
+ // lightB = light;// * sunlight[2];
+ }
+
+ public void setMeshBrightness(SimpleQuadMesh mesh, int x, int y, int z, ChunkData data, boolean side) {
+ if (x < 0) {
+ setMeshBrightness(data, provider.getChunk(data.location.getLeft()), ChunkData.ClampID(x, y, z), side);
+ } else if (x > 15) {
+ setMeshBrightness(data, provider.getChunk(data.location.getRight()), ChunkData.ClampID(x, y, z), side);
+ } else if (y < 0) {
+ setMeshBrightness(data, provider.getChunk(data.location.getBottom()), ChunkData.ClampID(x, y, z), side);
+ } else if (y > 15) {
+ setMeshBrightness(data, provider.getChunk(data.location.getTop()), ChunkData.ClampID(x, y, z), side);
+ } else if (z < 0) {
+ setMeshBrightness(data, provider.getChunk(data.location.getBack()), ChunkData.ClampID(x, y, z), side);
+ } else if (z > 15) {
+ setMeshBrightness(data, provider.getChunk(data.location.getFront()), ChunkData.ClampID(x, y, z), side);
+ } else {
+ setMeshBrightness(data, data, ChunkData.ID(x, y, z), side);
+ }
+ }
+
+ private float light = 0f;
+ private float lightR = 0f;
+ private float lightG = 0f;
+ private float lightB = 0f;
+ private static float[] lightValues = new float[] {//
+ 0.035f, // 0.035184372f, 0
+ 0.043980465f, // 1
+ 0.054975581f, // 2
+ 0.068719477f, // 3
+ 0.085899346f, // 4
+ 0.107374182f, // 5
+ 0.134217728f, // 6
+ 0.16777216f, // 7
+ 0.2097152f, // 8
+ 0.262144f, // 9
+ 0.32768f, // 10
+ 0.4096f, // 11
+ 0.512f, // 12
+ 0.64f, // 13
+ 0.8f, // 14
+ 1f // 15
+ };
+
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);
+ mesh.setColor4f(lightR, lightG, lightB, 1);
if (y < 0) {
- mesh.setColor4f(0, 0, 1, 1);
+ // mesh.setColor4f(0, 0, 1, 1);
} else if (y > 30) {
- mesh.setColor4f(1, 1, 1, 1);
+ // mesh.setColor4f(1, 1, 1, 1);
} else {
- mesh.setColor4f(1, 1, 0, 1);
+ // mesh.setColor4f(1, 1, 0, 1);
}
}
/**
* @return the mesh
*/
- public SimpleQuadMesh getMesh() {
- if (!isAvailable()) {
- return null;
- }
- if (isMeshCostructed) {
- return mesh;
- }
- if (offset.y >= provider.getInfo().maxHeight) {
- isMeshCostructed = true;
- return null;
+ public void getMesh() {
+ if (!mesh.isCompiled()) {
+ ChunkRenderer.compile(this);
}
- if (offset.y < provider.getInfo().minHeight) {
- isMeshCostructed = true;
- return null;
- }
-
- if (null == mesh || mesh.restart) {
- ChunkData data = provider.getChunk(offset.getChunkLocation());
- data.computeVisibility(provider);
- // max 14739
- System.out.println(data.visibleCount + " vis");
- mesh = new SimpleQuadMesh(14739);
- //mesh = new SimpleQuadMesh(Math.min(data.visibleCount * 6, 14739));
- mesh.start();
- // 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);
- BlockType grass;
- for (int dx = 0; dx < 16; dx++) {
- for (int dy = 0; dy < 16; dy++) {
- for (int dz = 0; dz < 16; dz++) {
- int x = offset.x + dx;
- int y = offset.y + dy;
- int z = offset.z + dz;
- if (mesh.restart) {
- return null;
- }
- //
- try {
- int id = dx * 16 * 16 + dy * 16 + dz;
- if (data.visible.get(id) && !data.emptyBlocks.get(id)) {
- grass = provider.getTypeRegistry().getBlockType(
- provider.getChunk((new BlockLocation(x, y, z)).getChunkLocation()).types[id]);
- 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++;
- }
- // System.out.println("mesh not empty");
- } else {
- // System.out.println("mesh empty");
- }
- } catch (ChunkUnavailableException e) {
- e.printStackTrace();
- }
- }
- }
- }
- mesh.endMesh();
- data.visible = null;
- isMeshCostructed = true;
- return null;
- }
- return mesh;
- }
-
- /**
- * @param mesh
- * the mesh to set
- */
- public void setMesh(SimpleQuadMesh mesh) {
- this.mesh = mesh;
}
public boolean isEmpty() {
@@ -352,9 +263,22 @@ public class Chunk extends BlockSlice {
public void setLocation(ChunkLocation location) {
setLocation(location.getBlockLocation().x, location.getBlockLocation().y, location.getBlockLocation().z);
+ this.location = new ChunkLocation(location);
}
public boolean inWorldRange() {
return (offset.y + 16 < provider.getInfo().maxHeight) && (offset.y > provider.getInfo().minHeight);
}
+
+ public boolean meshInvalid = false;
+
+ public void markMeshInvalid() {
+ if (isMeshCostructed) {
+ meshInvalid = true;
+ }
+ }
+
+ public ChunkData getData() {
+ return provider.getChunk(location);
+ }
}
diff --git a/src/ru/olamedia/olacraft/world/chunk/ChunkMeshBulder.java b/src/ru/olamedia/olacraft/world/chunk/ChunkMeshBulder.java
index e823b2f..3ad2da2 100644
--- a/src/ru/olamedia/olacraft/world/chunk/ChunkMeshBulder.java
+++ b/src/ru/olamedia/olacraft/world/chunk/ChunkMeshBulder.java
@@ -2,9 +2,11 @@ package ru.olamedia.olacraft.world.chunk;
import java.util.concurrent.ArrayBlockingQueue;
+import ru.olamedia.olacraft.world.blockRenderer.ChunkRenderer;
+
public class ChunkMeshBulder extends Thread {
public static ChunkMeshBulder instance = new ChunkMeshBulder("Mesh builder");
- private ArrayBlockingQueue<Chunk> chunks = new ArrayBlockingQueue<Chunk>(256);
+ private ArrayBlockingQueue<Chunk> chunks = new ArrayBlockingQueue<Chunk>(16);
public ChunkMeshBulder(String name) {
super(name);
@@ -24,20 +26,19 @@ public class ChunkMeshBulder extends Thread {
public void tick() throws InterruptedException {
if (!chunks.isEmpty()) {
- Chunk chunk = chunks.take();
- chunk.getMesh();
+ ChunkRenderer.compile(chunks.take());
}
}
@Override
public void run() {
- // glc.makeCurrent();
while (true) {
// main loop
try {
tick();
- if (chunks.isEmpty()){
+ if (chunks.isEmpty()) {
Thread.sleep(50);
+ } else {
}
// Thread.sleep(10); // or wait/join etc
} catch (InterruptedException ex) {
diff --git a/src/ru/olamedia/olacraft/world/chunk/ChunkSlice.java b/src/ru/olamedia/olacraft/world/chunk/ChunkSlice.java
index 14e2c1f..909f0fe 100644
--- a/src/ru/olamedia/olacraft/world/chunk/ChunkSlice.java
+++ b/src/ru/olamedia/olacraft/world/chunk/ChunkSlice.java
@@ -12,6 +12,8 @@ public class ChunkSlice {
private int height;
private int depth;
+ public static ChunkSlice rendererInstance;
+
public ChunkSlice(WorldProvider provider, int width, int height, int depth) {
this.provider = provider;
this.width = width;
@@ -20,8 +22,7 @@ public class ChunkSlice {
offset = new ChunkLocation();
}
- protected HashMap<String, Chunk> chunks = new HashMap<String, Chunk>();
- protected HashMap<Integer, HashMap<Integer, HashMap<Integer, Chunk>>> iChunks = new HashMap<Integer, HashMap<Integer, HashMap<Integer, Chunk>>>();
+ public HashMap<Integer, HashMap<Integer, HashMap<Integer, Chunk>>> iChunks = new HashMap<Integer, HashMap<Integer, HashMap<Integer, Chunk>>>();
public Chunk getChunk(ChunkLocation location) {
// int x = location.x;
@@ -43,8 +44,7 @@ public class ChunkSlice {
iChunks.get(location.x).put(location.y, new HashMap<Integer, Chunk>());
}
- Chunk chunk = new Chunk(provider);
- chunk.setLocation(location);
+ Chunk chunk = new Chunk(provider, location);
// chunks.put(key, chunk);
iChunks.get(location.x).get(location.y).put(location.z, chunk);
return chunk;
@@ -58,6 +58,16 @@ public class ChunkSlice {
// }
}
+ public void removeChunk(ChunkLocation location) {
+ if (iChunks.containsKey(location.x)) {
+ if (iChunks.get(location.x).containsKey(location.y)) {
+ if (iChunks.get(location.x).get(location.y).containsKey(location.z)) {
+ iChunks.get(location.x).get(location.y).remove(location.z);
+ }
+ }
+ }
+ }
+
/**
* @return the width
*/
@@ -133,4 +143,5 @@ public class ChunkSlice {
public void setLocation(ChunkLocation chunkOffset) {
offset = chunkOffset;
}
+
}
diff --git a/src/ru/olamedia/olacraft/world/chunk/ChunkUnavailableException.java b/src/ru/olamedia/olacraft/world/chunk/ChunkUnavailableException.java
index 9fef715..5fe81f6 100644
--- a/src/ru/olamedia/olacraft/world/chunk/ChunkUnavailableException.java
+++ b/src/ru/olamedia/olacraft/world/chunk/ChunkUnavailableException.java
@@ -1,6 +1,6 @@
package ru.olamedia.olacraft.world.chunk;
-public class ChunkUnavailableException extends Exception {
+public class ChunkUnavailableException extends RuntimeException {
private static final long serialVersionUID = -5382060550128159125L;
diff --git a/src/ru/olamedia/olacraft/world/data/ChunkData.java b/src/ru/olamedia/olacraft/world/data/ChunkData.java
index 42f7811..af703c0 100644
--- a/src/ru/olamedia/olacraft/world/data/ChunkData.java
+++ b/src/ru/olamedia/olacraft/world/data/ChunkData.java
@@ -1,28 +1,155 @@
package ru.olamedia.olacraft.world.data;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
import ru.olamedia.math.OpenBitSet;
-import ru.olamedia.olacraft.world.blockTypes.BlockType;
+import ru.olamedia.olacraft.world.blockTypes.AbstractBlockType;
import ru.olamedia.olacraft.world.chunk.Chunk;
+import ru.olamedia.olacraft.world.drop.DroppedEntity;
import ru.olamedia.olacraft.world.location.BlockLocation;
import ru.olamedia.olacraft.world.location.ChunkLocation;
+import ru.olamedia.olacraft.world.location.IntLocation;
import ru.olamedia.olacraft.world.provider.WorldProvider;
+/**
+ * 1 bit for opaque
+ * if non-opaque, some left bits will be used for light, else can be used for
+ * meta
+ *
+ * Opaque blocks:
+ * stone/cobblestone/gravel/sand(dust) is a state, 2 bits
+ * dirt/peat
+ *
+ * Non-opaque:
+ * fluids: water, acid, lava
+ * glass
+ *
+ * trees etc is an entities, not the blocks
+ *
+ *
+ *
+ * @author olamedia
+ *
+ */
public class ChunkData implements Serializable {
private static final long serialVersionUID = -5704237444737895501L;
public ChunkLocation location;
- public static transient int SIZE = 4096;
+ private static transient int SIZE = 4096;
// private boolean[] notEmpty = new boolean[SIZE];
- public OpenBitSet emptyBlocks = new OpenBitSet(4096);
+ private OpenBitSet emptyBlocks = new OpenBitSet(4096);
public int visibleCount = 0;
public OpenBitSet visible = null; // fast precomputed
- // visibility (true if
- // any side is open)
- //public OpenBitSet sunlight = new OpenBitSet(65536);
+ // visibility (true if
+ // any side is open)
+ // public OpenBitSet sunlight = new OpenBitSet(65536);
public byte[] types = new byte[4096];
public int notEmptyCount = 0;
public boolean visibilityPrecomputed = false;
+ public boolean voidLightPrecomputed = false;
+ public boolean voidLightChanged = false;
+ private boolean compressionStarted = false;
+ private boolean isCompressed = false;
+ private byte[] compressed;
+ private ChunkDataPointer pointer = new ChunkDataPointer();
+ public HashMap<Integer, AbstractBlockType> timeManagedBlocks = new HashMap<Integer, AbstractBlockType>();
+ public ArrayList<DroppedEntity> droppedEntities = new ArrayList<DroppedEntity>();
+
+ public void invalidateComputations() {
+ visibilityPrecomputed = false;
+ voidLightPrecomputed = false;
+ }
+
+ public void detachBlock(short id) {
+ emptyBlocks.set(id);
+ types[id] = 0;
+ }
+
+ public void tick(WorldProvider provider) {
+
+ }
+
+ /**
+ * After populating with blocks, create entities
+ *
+ * @param provider
+ */
+ public void initBlockEntities(WorldProvider provider) {
+ pointer.reset();
+ while (pointer.hasNext()) {
+ if (!isEmpty(pointer.getId()) && types[pointer.getId()] != 0) {
+ AbstractBlockType type = provider.getTypeRegistry().getBlockType(types[pointer.getId()]);
+ // check if entity-managed block
+ // check if time-managed block
+ if (type.isTimeManaged()) {
+ timeManagedBlocks.put(pointer.getId(), type);
+ }
+ }
+ //
+ pointer.next();
+ }
+ }
+
+ public static short ID(int x, int y, int z) {
+ return (short) (x * 256 + y * 16 + z);
+ }
+
+ public static short ClampID(BlockLocation location) {
+ return location.getId();
+ }
+
+ public static short ClampID(int x, int y, int z) {
+ return ID(x & 15, y & 15, z & 15);
+ }
+
+ public void compress() {
+ if (!isCompressed && !compressionStarted) {
+ compressionStarted = true;
+ try {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ // GZIPOutputStream gzout = new GZIPOutputStream(bout);
+ ObjectOutputStream out = new ObjectOutputStream(bout);
+ out.writeObject(this);
+ compressed = bout.toByteArray();
+ types = null;
+ emptyBlocks = null;
+ out.close();
+ // gzout.close();
+ bout.close();
+ isCompressed = true;
+ } catch (IOException e) {
+ compressionStarted = false;
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public ChunkData decompress() {
+ if (isCompressed) {
+ try {
+ ByteArrayInputStream bin = new ByteArrayInputStream(compressed);
+ // GZIPInputStream gzin = new GZIPInputStream(new
+ // BufferedInputStream(bin));
+ ObjectInputStream in = new ObjectInputStream(bin);
+ ChunkData data = (ChunkData) in.readObject();
+ in.close();
+ // gzin.close();
+ bin.close();
+ return data;
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ }
+ }
+ return null;
+ }
// public transient int[] type = new int[SIZE];
@@ -30,22 +157,16 @@ public class ChunkData implements Serializable {
}
private void setVisible(int x, int y, int z) {
- if (x < 0 || x > 15 || y < 0 || y > 15 || z < 0 || z > 15) {
- return;
- }
- int id = x * 16 * 16 + y * 16 + z;
- if (!visible.get(id)){
+ final short id = IntLocation.id(x, y, z);
+ if (!visible.get(id)) {
visibleCount++;
}
visible.set(id);
}
private void setInvisible(int x, int y, int z) {
- if (x < 0 || x > 15 || y < 0 || y > 15 || z < 0 || z > 15) {
- return;
- }
- int id = x * 16 * 16 + y * 16 + z;
- if (visible.get(id)){
+ final short id = IntLocation.id(x, y, z);
+ if (visible.get(id)) {
visibleCount--;
}
visible.clear(id);
@@ -54,27 +175,28 @@ public class ChunkData implements Serializable {
public void computeVisibility(WorldProvider provider) {
visible = new OpenBitSet(4096);
visibleCount = 0;
- precomputeVisibility();
- computeVisibility(provider.getChunk(location.getLeft()), provider.getChunk(location.getRight()),
+ precomputeVisibility(provider);
+ computeVisibility(provider, provider.getChunk(location.getLeft()), provider.getChunk(location.getRight()),
provider.getChunk(location.getTop()), provider.getChunk(location.getBottom()),
provider.getChunk(location.getFront()), provider.getChunk(location.getBack()));
}
- public void computeVisibility(ChunkData left, ChunkData right, ChunkData top, ChunkData bottom, ChunkData front,
- ChunkData back) {
+ public void computeVisibility(WorldProvider provider, ChunkData left, ChunkData right, ChunkData top,
+ ChunkData bottom, ChunkData front, ChunkData back) {
// compute left/right
- int x, y, z, id;
+ int x, y, z;
+ short id;
for (y = 0; y <= 15; y++) {
for (z = 0; z <= 15; z++) {
x = 15;
- id = x * 16 * 16 + y * 16 + z;
- if (left.emptyBlocks.get(id)) {
+ id = IntLocation.id(x, y, z);
+ if (!left.isOpaque(provider, id)) {
x = 0;
setVisible(x, y, z);
}
x = 0;
- id = x * 16 * 16 + y * 16 + z;
- if (right.emptyBlocks.get(id)) {
+ id = IntLocation.id(x, y, z);
+ if (!right.isOpaque(provider, id)) {
x = 15;
setVisible(x, y, z);
}
@@ -84,14 +206,14 @@ public class ChunkData implements Serializable {
for (x = 0; x <= 15; x++) {
for (z = 0; z <= 15; z++) {
y = 15;
- id = x * 16 * 16 + y * 16 + z;
- if (bottom.emptyBlocks.get(id)) {
+ id = IntLocation.id(x, y, z);
+ if (!bottom.isOpaque(provider, id)) {
y = 0;
setVisible(x, y, z);
}
y = 0;
- id = x * 16 * 16 + y * 16 + z;
- if (top.emptyBlocks.get(id)) {
+ id = IntLocation.id(x, y, z);
+ if (!top.isOpaque(provider, id)) {
y = 15;
setVisible(x, y, z);
}
@@ -101,14 +223,14 @@ public class ChunkData implements Serializable {
for (x = 0; x <= 15; x++) {
for (y = 0; y <= 15; y++) {
z = 15;
- id = x * 16 * 16 + y * 16 + z;
- if (back.emptyBlocks.get(id)) {
+ id = IntLocation.id(x, y, z);
+ if (!back.isOpaque(provider, id)) {
z = 0;
setVisible(x, y, z);
}
z = 0;
- id = x * 16 * 16 + y * 16 + z;
- if (front.emptyBlocks.get(id)) {
+ id = IntLocation.id(x, y, z);
+ if (!front.isOpaque(provider, id)) {
z = 15;
setVisible(x, y, z);
}
@@ -118,9 +240,10 @@ public class ChunkData implements Serializable {
/**
* Compute visibility ("visible" if any side have non-opaque neighbor)
- * Leaving side blocks invisible. Use computeVisibility(WorldProvider) to compute visibility of side blocks
+ * Leaving side blocks invisible. Use computeVisibility(WorldProvider) to
+ * compute visibility of side blocks
*/
- public void precomputeVisibility() {
+ public void precomputeVisibility(WorldProvider provider) {
// first pass, make all blocks invisible, except side blocks
for (int x = 0; x <= 15; x++) {
for (int y = 0; y <= 15; y++) {
@@ -140,7 +263,7 @@ public class ChunkData implements Serializable {
for (int y = 0; y <= 15; y++) {
for (int z = 0; z <= 15; z++) {
int id = x * 16 * 16 + y * 16 + z;
- if (emptyBlocks.get(id)) {
+ if (!isOpaque(provider, id)) {
setVisible(x - 1, y, z);
setVisible(x + 1, y, z);
setVisible(x, y - 1, z);
@@ -154,13 +277,17 @@ public class ChunkData implements Serializable {
visibilityPrecomputed = true;
}
+ public boolean isOpaque(WorldProvider provider, int id) {
+ return !isEmpty(id) && provider.getTypeRegistry().isOpaque(types[id]);
+ }
+
public void compact() {
- if (emptyBlocks.cardinality() == 0) {
+ if (notEmptyCount == 0) {
// emptyBlocks = null;
}
}
- public BlockType getType(BlockLocation blockLocation, WorldProvider provider) {
+ public AbstractBlockType getType(BlockLocation blockLocation, WorldProvider provider) {
if (emptyBlocks == null) {
return null;
}
@@ -215,4 +342,14 @@ public class ChunkData implements Serializable {
setEmpty(id, isEmpty);
}
+ public void freeRenderData() {
+ visible = null;
+ // light = null;
+ // voidLightPrecomputed = false;
+ }
+
+ public void addDroppedEntity(DroppedEntity droppedEntity) {
+ droppedEntities.add(droppedEntity);
+ }
+
}
diff --git a/src/ru/olamedia/olacraft/world/data/ChunkDataManager.java b/src/ru/olamedia/olacraft/world/data/ChunkDataManager.java
new file mode 100644
index 0000000..ba5b50a
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/data/ChunkDataManager.java
@@ -0,0 +1,22 @@
+package ru.olamedia.olacraft.world.data;
+
+import ru.olamedia.olacraft.world.provider.WorldProvider;
+
+public class ChunkDataManager {
+ private ChunkData data;
+ private ChunkDataPointer pointer = new ChunkDataPointer();
+ private WorldProvider provider;
+
+ public void setProvider(WorldProvider provider){
+ this.provider = provider;
+ }
+
+ public void setData(ChunkData data) {
+ this.data = data;
+ pointer.reset();
+ }
+
+ private void loadNeighbors(){
+
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/data/ChunkDataNeighbors.java b/src/ru/olamedia/olacraft/world/data/ChunkDataNeighbors.java
new file mode 100644
index 0000000..de82b5b
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/data/ChunkDataNeighbors.java
@@ -0,0 +1,162 @@
+package ru.olamedia.olacraft.world.data;
+
+import ru.olamedia.olacraft.world.calc.LightCalculator;
+import ru.olamedia.olacraft.world.calc.VisibilityCalculator;
+import ru.olamedia.olacraft.world.location.ChunkLocation;
+import ru.olamedia.olacraft.world.provider.WorldProvider;
+
+public class ChunkDataNeighbors {
+ private static byte CENTER = 0;
+ private static byte LEFT = 1;
+ private static byte RIGHT = 2;
+ private static byte TOP = 3;
+ private static byte BOTTOM = 4;
+ private static byte FRONT = 5;
+ private static byte BACK = 6;
+ private WorldProvider provider;
+ private ChunkLocation center;
+ private ChunkDataWrapper data;
+ private ChunkDataWrapper left;
+ private ChunkDataWrapper right;
+ private ChunkDataWrapper top;
+ private ChunkDataWrapper bottom;
+ private ChunkDataWrapper front;
+ private ChunkDataWrapper back;
+ private ChunkDataWrapper[] chunks;
+
+ public ChunkDataNeighbors() {
+ chunks = new ChunkDataWrapper[7];
+ for (byte i = 0; i < 7; i++) {
+ chunks[i] = new ChunkDataWrapper();
+ }
+ left = new ChunkDataWrapper();
+ right = new ChunkDataWrapper();
+ top = new ChunkDataWrapper();
+ bottom = new ChunkDataWrapper();
+ front = new ChunkDataWrapper();
+ back = new ChunkDataWrapper();
+ data = new ChunkDataWrapper();
+ center = new ChunkLocation();
+ }
+
+ public void setProvider(WorldProvider provider) {
+ this.provider = provider;
+ }
+
+ public void setData(ChunkData data) {
+ this.data.setData(data);
+ center.set(data.location);
+ chunks[CENTER].setData(data);
+ }
+
+ public void loadNeighbors() {
+ top.setData(provider.getChunk(center.getTop()));
+ bottom.setData(provider.getChunk(center.getBottom()));
+ left.setData(provider.getChunk(center.getLeft()));
+ right.setData(provider.getChunk(center.getRight()));
+ front.setData(provider.getChunk(center.getFront()));
+ back.setData(provider.getChunk(center.getBack()));
+ chunks[TOP].setData(top.getData());
+ chunks[BOTTOM].setData(bottom.getData());
+ chunks[LEFT].setData(left.getData());
+ chunks[RIGHT].setData(right.getData());
+ chunks[FRONT].setData(front.getData());
+ chunks[BACK].setData(back.getData());
+ }
+
+ public ChunkDataWrapper getCenter() {
+ return data;
+ }
+
+ public ChunkData getCenterData() {
+ return data.getData();
+ }
+
+ public ChunkDataWrapper getTop() {
+ return top;
+ }
+
+ public ChunkDataWrapper getBottom() {
+ return bottom;
+ }
+
+ public ChunkDataWrapper getLeft() {
+ return left;
+ }
+
+ public ChunkDataWrapper getRight() {
+ return right;
+ }
+
+ public ChunkDataWrapper getFront() {
+ return front;
+ }
+
+ public ChunkDataWrapper getBack() {
+ return back;
+ }
+
+ public ChunkData getTopData() {
+ return top.getData();
+ }
+
+ public ChunkData getBottomData() {
+ return bottom.getData();
+ }
+
+ public ChunkData getLeftData() {
+ return left.getData();
+ }
+
+ public ChunkData getRightData() {
+ return right.getData();
+ }
+
+ public ChunkData getFrontData() {
+ return front.getData();
+ }
+
+ public ChunkData getBackData() {
+ return back.getData();
+ }
+
+ public void calcLight() {
+ LightCalculator.calculateVoidLightIgnoreNeighbors(top);
+ LightCalculator.calculateVoidLightIgnoreNeighbors(bottom);
+ LightCalculator.calculateVoidLightIgnoreNeighbors(left);
+ LightCalculator.calculateVoidLightIgnoreNeighbors(right);
+ LightCalculator.calculateVoidLightIgnoreNeighbors(front);
+ LightCalculator.calculateVoidLightIgnoreNeighbors(back);
+ LightCalculator.precalculateVoidLight(data);
+ LightCalculator.spreadVoidLight(this);
+ }
+
+ public void reset() {
+ provider = null;
+ data.reset();
+ top.reset();
+ bottom.reset();
+ left.reset();
+ right.reset();
+ front.reset();
+ back.reset();
+ }
+
+ public ChunkLocation getLocation() {
+ return center;
+ }
+
+ public boolean isOpaque(short id) {
+ return !data.getData().isEmpty(id) && provider.getTypeRegistry().isOpaque(data.getData().types[id]);
+ }
+
+ public boolean isVisible(short id) {
+ return data.getVisibility().isVisible(id) && !data.getData().isEmpty(id) && (0 != data.getData().types[id]);
+ }
+
+ public void calcVisibility() {
+ VisibilityCalculator.precomputeVisibility(this);
+ VisibilityCalculator.computeVisibility(data.getVisibility(), provider, getLeftData(), getRightData(),
+ getTopData(), getBottomData(), getFrontData(), getBackData());
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/data/ChunkDataPointer.java b/src/ru/olamedia/olacraft/world/data/ChunkDataPointer.java
new file mode 100644
index 0000000..2c0f059
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/data/ChunkDataPointer.java
@@ -0,0 +1,82 @@
+package ru.olamedia.olacraft.world.data;
+
+import ru.olamedia.olacraft.world.chunk.Chunk;
+
+/**
+ * pointer.reset()
+ * while (pointer.hasNext()){
+ * int id = pointer.getId()
+ * ...
+ * pointer.next()
+ * }
+ * @author olamedia
+ *
+ */
+public class ChunkDataPointer {
+ private int x = 0;
+ private int y = 0;
+ private int z = 0;
+ private int id = 0;
+
+ public ChunkDataPointer() {
+ reset();
+ }
+
+ public ChunkDataPointer(int x, int y, int z) {
+ if (x >= 0 && x < 16) {
+ if (y >= 0 && y < 16) {
+ if (z >= 0 && z < 16) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ id = this.x * 16 * 16 + this.y * 16 + this.z;
+ return;
+ }
+ }
+ }
+ this.x = Chunk.in(x);
+ this.y = Chunk.in(y);
+ this.z = Chunk.in(z);
+ id = this.x * 16 * 16 + this.y * 16 + this.z;
+ }
+
+ public int getX() {
+ return x;
+ }
+
+ public int getY() {
+ return y;
+ }
+
+ public int getZ() {
+ return z;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void reset() {
+ x = 0;
+ y = 0;
+ z = 0;
+ id = 0;
+ }
+
+ public boolean hasNext() {
+ return id < 4096;
+ }
+
+ public void next() {
+ id++;
+ x++;
+ if (x > 15) {
+ x = 0;
+ y++;
+ if (y > 15) {
+ y = 0;
+ z++;
+ }
+ }
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/data/ChunkDataWrapper.java b/src/ru/olamedia/olacraft/world/data/ChunkDataWrapper.java
new file mode 100644
index 0000000..ae0f582
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/data/ChunkDataWrapper.java
@@ -0,0 +1,40 @@
+package ru.olamedia.olacraft.world.data;
+
+import ru.olamedia.math.OpenBitSet;
+import ru.olamedia.olacraft.world.calc.LightData;
+import ru.olamedia.olacraft.world.calc.VisibilityData;
+
+public class ChunkDataWrapper {
+ private ChunkData data;
+ private LightData light;
+ private VisibilityData visibility;
+
+ public ChunkDataWrapper() {
+ light = new LightData();
+ visibility = new VisibilityData();
+ }
+
+ public void setData(ChunkData data) {
+ this.data = data;
+ }
+
+ public ChunkData getData() {
+ return data;
+ }
+
+ public LightData getLight() {
+ return light;
+ }
+
+ public VisibilityData getVisibility() {
+ return visibility;
+ }
+
+ public void reset() {
+ data = null;
+ light.reset();
+ light = null;
+ visibility.reset();
+ visibility = null;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/data/RegionData.java b/src/ru/olamedia/olacraft/world/data/RegionData.java
index f58a424..cdc4497 100644
--- a/src/ru/olamedia/olacraft/world/data/RegionData.java
+++ b/src/ru/olamedia/olacraft/world/data/RegionData.java
@@ -24,10 +24,18 @@ public class RegionData implements Serializable {
public HeightMap heightMap = new HeightMap(256, 256);
public SectorData[][] sectorData = new SectorData[16][16];
- public RegionData(){
-
+ public RegionData() {
+
+ }
+
+ public void compress() {
+ for (int x = 0; x < 16; x++) {
+ for (int z = 0; z < 16; z++) {
+ sectorData[x][z].compress();
+ }
+ }
}
-
+
public void writeTo(OutputStream stream) throws IOException {
ObjectOutputStream out = new ObjectOutputStream(stream);
out.writeObject(this);
@@ -50,7 +58,7 @@ public class RegionData implements Serializable {
public ChunkData getChunkData(ChunkLocation chunkLocation) {
SectorData sector = getSectorData(chunkLocation.getSectorLocation());
int y = Chunk.in(chunkLocation.y + 128); // minHeight = -128
- return sector.chunkData[y];
+ return sector.get(y);
}
public SectorData getSectorData(SectorLocation sectorLocation) {
@@ -58,4 +66,12 @@ public class RegionData implements Serializable {
int z = Chunk.in(sectorLocation.z);
return sectorData[x][z];
}
+
+ public void decompress() {
+ for (int x = 0; x < 16; x++) {
+ for (int z = 0; z < 16; z++) {
+ sectorData[x][z].decompress();
+ }
+ }
+ }
}
diff --git a/src/ru/olamedia/olacraft/world/data/SectorData.java b/src/ru/olamedia/olacraft/world/data/SectorData.java
index 31526a7..76414d4 100644
--- a/src/ru/olamedia/olacraft/world/data/SectorData.java
+++ b/src/ru/olamedia/olacraft/world/data/SectorData.java
@@ -10,26 +10,56 @@ import ru.olamedia.olacraft.world.location.SectorLocation;
* @author olamedia
*
*/
-public class SectorData implements Serializable{
+public class SectorData implements Serializable {
private static final long serialVersionUID = 5304471397211814748L;
- public HeightMap heightMap = new HeightMap(16, 16); // locations of highest nonempty blocks
- public ChunkData[] chunkData = new ChunkData[16]; // 256/16 = 16
+ public HeightMap heightMap = new HeightMap(16, 16); // locations of highest
+ // nonempty blocks
+ protected ChunkData[] chunkData = new ChunkData[16]; // 256/16 = 16
public SectorLocation location;
- public SectorData(){
-
+ public SectorData() {
+
}
-
+
public static int yIndex(int y) {
return (y + 128) / 16;
- // 1: (-128 + 128) / 16 = 0
+ // 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(){
+
+ public static SectorData generate() {
SectorData data = new SectorData();
return data;
}
+
+ public void compress() {
+ /*
+ * for (int y = 0; y < 16; y++) {
+ * chunkData[y].compress();
+ * }
+ */
+ }
+
+ public void set(int y, ChunkData data) {
+ // data.compress();
+ chunkData[y] = data;
+ }
+
+ public ChunkData get(int y) {
+ /*
+ * if (chunkData[y].isCompressed){
+ * return chunkData[y].decompress();
+ * }
+ */
+ return chunkData[y];
+ }
+
+ public void decompress() {
+ for (int y = 0; y < 16; y++) {
+ // chunkData[y] = chunkData[y].decompress();
+ }
+ }
}
diff --git a/src/ru/olamedia/olacraft/world/dataProvider/AbstractChunkDataProvider.java b/src/ru/olamedia/olacraft/world/dataProvider/AbstractChunkDataProvider.java
index 1670ef3..495fae4 100644
--- a/src/ru/olamedia/olacraft/world/dataProvider/AbstractChunkDataProvider.java
+++ b/src/ru/olamedia/olacraft/world/dataProvider/AbstractChunkDataProvider.java
@@ -1,5 +1,6 @@
package ru.olamedia.olacraft.world.dataProvider;
+import ru.olamedia.olacraft.world.block.BlockRegistry;
import ru.olamedia.olacraft.world.data.ChunkData;
import ru.olamedia.olacraft.world.data.RegionData;
import ru.olamedia.olacraft.world.data.SectorData;
@@ -8,6 +9,13 @@ import ru.olamedia.olacraft.world.location.RegionLocation;
import ru.olamedia.olacraft.world.location.SectorLocation;
abstract public class AbstractChunkDataProvider {
+
+ protected BlockRegistry types;
+
+ public void setTypeRegistry(BlockRegistry types) {
+ this.types = types;
+ }
+
/**
* is data already available or we should wait
*
@@ -30,9 +38,9 @@ abstract public class AbstractChunkDataProvider {
* @param RegionLocation
*/
public void loadChunk(ChunkLocation chunkLocation) {
- //System.out.println("loadChunk(" + chunkLocation + ")");
+ // System.out.println("loadChunk(" + chunkLocation + ")");
this.loadRegion(chunkLocation.getRegionLocation());
- //System.out.println("loadChunk(" + chunkLocation + ")--");
+ // System.out.println("loadChunk(" + chunkLocation + ")--");
}
public void loadSector(SectorLocation sectorLocation) {
diff --git a/src/ru/olamedia/olacraft/world/dataProvider/CachedChunkDataProvider.java b/src/ru/olamedia/olacraft/world/dataProvider/CachedChunkDataProvider.java
index 1e6c0c1..d779a40 100644
--- a/src/ru/olamedia/olacraft/world/dataProvider/CachedChunkDataProvider.java
+++ b/src/ru/olamedia/olacraft/world/dataProvider/CachedChunkDataProvider.java
@@ -1,62 +1,69 @@
package ru.olamedia.olacraft.world.dataProvider;
+import java.util.ArrayList;
import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
+import ru.olamedia.olacraft.game.Game;
+import ru.olamedia.olacraft.world.block.BlockRegistry;
import ru.olamedia.olacraft.world.data.RegionData;
+import ru.olamedia.olacraft.world.location.BlockLocation;
+import ru.olamedia.olacraft.world.location.ChunkLocation;
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 ConcurrentHashMap<String, Integer> ticks = new ConcurrentHashMap<String, Integer>();
+ private HashMap<RegionLocation, RegionData> regionMap = new HashMap<RegionLocation, RegionData>();
+
+ private RegionData current;
public CachedChunkDataProvider(AbstractChunkDataProvider provider) {
this.provider = provider;
+ this.provider.setTypeRegistry(types);
+ }
+
+ @Override
+ public void setTypeRegistry(BlockRegistry types) {
+ super.setTypeRegistry(types);
+ this.provider.setTypeRegistry(types);
}
private static boolean DEBUG = true;
private void debug(String s) {
if (DEBUG) {
- System.out.println("[CachedChunkDataProvider] " + s);
+ System.err.println("[CachedChunkDataProvider] " + s);
}
}
- @SuppressWarnings("unused")
- private void tick(String key) {
- ticks.put(key, 0);
- gc();
+ private boolean containsKey(RegionLocation l) {
+ return regionMap.containsKey(l);
}
- private void gc() {
- Iterator<String> keys = ticks.keySet().iterator();
- while (keys.hasNext()) {
- String key = keys.next();
- ticks.put(key, ticks.get(key) + 1);
- if (ticks.get(key) > 30) {
- ticks.remove(key);
- regionMap.remove(key);
- }
- }
+ // private boolean containsKey(int x, int y, int z) {
+ // return regionMap.containsKey(x) && regionMap.get(x).containsKey(y) &&
+ // regionMap.get(x).get(y).containsKey(z);
+ // }
+
+ private void put(RegionLocation l, RegionData data) {
+ regionMap.put(l, data);
+ }
+
+ private RegionData get(RegionLocation l) {
+ return regionMap.get(l);
}
@Override
public boolean isRegionAvailable(RegionLocation regionLocation) {
- String key = regionLocation.toString();// regionLocation.x + "-" +
- if (regionMap.containsKey(key)) {
+ if (regionMap.containsKey(regionLocation)) {
return true;
}
+ debug("regions: " + regionMap.size() + "");
return provider.isRegionAvailable(regionLocation);
}
@Override
public void loadRegion(RegionLocation regionLocation) {
- String key = regionLocation.toString();
- // debug("loadRegion(" + regionLocation + ")");
- if (!regionMap.containsKey(key)) {
+ if (!containsKey(regionLocation)) {
provider.loadRegion(regionLocation);
} else {
debug("error: loadRegion(" + regionLocation + ") already in regionMap");
@@ -65,15 +72,37 @@ public class CachedChunkDataProvider extends AbstractChunkDataProvider {
@Override
public RegionData getRegion(RegionLocation regionLocation) {
- String key = regionLocation.toString();
- // tick(key);
- if (regionMap.containsKey(key)) {
- return regionMap.get(key);
+ if (containsKey(regionLocation)) {
+ return get(regionLocation);
} else {
- RegionData data = provider.getRegion(regionLocation);
- regionMap.put(key, data);
- return data;
+ put(regionLocation, provider.getRegion(regionLocation));
+ gc();
+ return get(regionLocation);
}
}
+ public void unloadRegion(RegionLocation regionLocation) {
+ regionMap.remove(regionLocation);
+ }
+
+ private ArrayList<RegionLocation> gcKeys = new ArrayList<RegionLocation>();
+
+ public void gc() {
+ if (Game.instance.player != null && regionMap.size() > 4) {
+ final BlockLocation b = Game.instance.player.getCameraBlockLocation();
+ final RegionLocation r = b.getRegionLocation();
+ for (RegionLocation l : regionMap.keySet()) {
+ if ((l.x > r.x + 1) || (l.x < r.x - 1)) {
+ if ((l.z > r.z + 1) || (l.z < r.z - 1)) {
+ gcKeys.add(l);
+ }
+ }
+ }
+ for (RegionLocation l : gcKeys) {
+ unloadRegion(l);
+ }
+ gcKeys.clear();
+ regionMap.clear();
+ }
+ }
}
diff --git a/src/ru/olamedia/olacraft/world/dataProvider/LocalChunkDataProvider.java b/src/ru/olamedia/olacraft/world/dataProvider/LocalChunkDataProvider.java
index 887421f..4464b96 100644
--- a/src/ru/olamedia/olacraft/world/dataProvider/LocalChunkDataProvider.java
+++ b/src/ru/olamedia/olacraft/world/dataProvider/LocalChunkDataProvider.java
@@ -83,48 +83,50 @@ public class LocalChunkDataProvider extends AbstractChunkDataProvider {
@SuppressWarnings("unused")
@Override
public RegionData getRegion(RegionLocation regionLocation) {
- String filename = path + File.separator + regionLocation.getFilename();
- RegionData data = null;
- if (true) {
- return generateRegion(regionLocation);
- }
- File chunkFile = new File(filename);
- if (false && chunkFile.exists()) {
- InputStream in;
- try {
- FileInputStream fIn = new FileInputStream(chunkFile);
- in = new GZIPInputStream(fIn);
- data = RegionData.loadFrom(in);
- in.close();
- fIn.close();
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- } else {
- data = generateRegion(regionLocation);
- OutputStream out;
- try {
- chunkFile.createNewFile();
- FileOutputStream fOut = new FileOutputStream(chunkFile);
- out = new GZIPOutputStream(fOut);
- data.writeTo(out);
- out.close();
- fOut.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- return data;
+ // String filename = path + File.separator +
+ // regionLocation.getFilename();
+ // RegionData data = null;
+ return generateRegion(regionLocation);
+ // File chunkFile = new File(filename);
+ // if (false && chunkFile.exists()) {
+ // InputStream in;
+ // try {
+ // FileInputStream fIn = new FileInputStream(chunkFile);
+ // in = new GZIPInputStream(fIn);
+ // data = RegionData.loadFrom(in);
+ // in.close();
+ // fIn.close();
+ // } catch (FileNotFoundException e) {
+ // e.printStackTrace();
+ // } catch (IOException e) {
+ // e.printStackTrace();
+ // } catch (ClassNotFoundException e) {
+ // e.printStackTrace();
+ // }
+ // } else {
+ // data = generateRegion(regionLocation);
+ // OutputStream out;
+ // try {
+ // chunkFile.createNewFile();
+ // FileOutputStream fOut = new FileOutputStream(chunkFile);
+ // out = new GZIPOutputStream(fOut);
+ // data.writeTo(out);
+ // out.close();
+ // fOut.close();
+ // } catch (IOException e) {
+ // e.printStackTrace();
+ // }
+ // }
+ // return data;
}
+ RegionGenerator generator;
+
public RegionData generateRegion(RegionLocation regionLocation) {
- RegionData data = new RegionData();
+ final RegionData data = new RegionData();
data.location = regionLocation;
RegionGenerator generator = new RegionGenerator();
+ generator.setTypes(types);
try {
generator.setSeed(getSeed());
} catch (IOException e) {
diff --git a/src/ru/olamedia/olacraft/world/dataProvider/RemoteChunkDataProvider.java b/src/ru/olamedia/olacraft/world/dataProvider/RemoteChunkDataProvider.java
index 0c52ced..1f860d6 100644
--- a/src/ru/olamedia/olacraft/world/dataProvider/RemoteChunkDataProvider.java
+++ b/src/ru/olamedia/olacraft/world/dataProvider/RemoteChunkDataProvider.java
@@ -17,7 +17,7 @@ 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 HashMap<RegionLocation, RegionData> map = new HashMap<RegionLocation, RegionData>();
private List<String> loading = new ArrayList<String>();
private List<RegionLocation> queue = new ArrayList<RegionLocation>();
@@ -51,14 +51,13 @@ public class RemoteChunkDataProvider extends AbstractChunkDataProvider implement
if (loading.contains(key)) {
return false;
}
- return map.containsKey(key);
+ return map.containsKey(regionLocation);
}
@Override
public RegionData getRegion(RegionLocation regionLocation) {
- String key = regionLocation.toString();
- RegionData data = map.get(key);
- map.remove(key);
+ RegionData data = map.get(regionLocation);
+ map.remove(regionLocation);
return data;
}
@@ -67,10 +66,10 @@ public class RemoteChunkDataProvider extends AbstractChunkDataProvider implement
if (p instanceof RegionDataPacket) {
debug("received packet [conn " + connection.getID() + "]: RegionDataPacket");
RegionData data = ((RegionDataPacket) p).data;
- System.out.println(data.sectorData[0][0].chunkData[15].isEmpty(0) + "");
- String key = data.location.toString();
- map.put(key, data);
- loading.remove(key);
+ data.decompress();
+ //System.out.println(data.sectorData[0][0].get(15).isEmpty(0) + "");
+ map.put(data.location, data);
+ loading.remove(data.location);
}
}
diff --git a/src/ru/olamedia/olacraft/world/drop/DroppedEntity.java b/src/ru/olamedia/olacraft/world/drop/DroppedEntity.java
new file mode 100644
index 0000000..0d2fede
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/drop/DroppedEntity.java
@@ -0,0 +1,17 @@
+package ru.olamedia.olacraft.world.drop;
+
+import ru.olamedia.olacraft.world.blockStack.BlockStack;
+import ru.olamedia.olacraft.world.blockTypes.AbstractBlockType;
+import ru.olamedia.olacraft.world.location.BlockLocation;
+import ru.olamedia.olacraft.world.location.Location3f;
+
+public class DroppedEntity {
+ public DroppedEntity(BlockLocation location, AbstractBlockType type, int count) {
+ this.location = new Location3f(location);
+ this.location.addRandomOffset(0.4f);
+ stack = new BlockStack(type, count);
+ }
+
+ public Location3f location;
+ public BlockStack stack;
+}
diff --git a/src/ru/olamedia/olacraft/world/drop/package-info.java b/src/ru/olamedia/olacraft/world/drop/package-info.java
new file mode 100644
index 0000000..d349368
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/drop/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.world.drop; \ No newline at end of file
diff --git a/src/ru/olamedia/olacraft/world/fluid/FluidLevel.java b/src/ru/olamedia/olacraft/world/fluid/FluidLevel.java
new file mode 100644
index 0000000..8e90e3c
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/fluid/FluidLevel.java
@@ -0,0 +1,9 @@
+package ru.olamedia.olacraft.world.fluid;
+
+import java.util.HashMap;
+
+public class FluidLevel {
+ public HashMap<Integer, FluidLine> lines = new HashMap<Integer, FluidLine>();
+ public float fluidLevel = 1f;
+ public int size = 0;
+}
diff --git a/src/ru/olamedia/olacraft/world/fluid/FluidLine.java b/src/ru/olamedia/olacraft/world/fluid/FluidLine.java
new file mode 100644
index 0000000..9dc8d44
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/fluid/FluidLine.java
@@ -0,0 +1,56 @@
+package ru.olamedia.olacraft.world.fluid;
+
+import java.util.ArrayList;
+
+import ru.olamedia.olacraft.world.data.ChunkData;
+import ru.olamedia.olacraft.world.location.BlockLocation;
+import ru.olamedia.olacraft.world.provider.WorldProvider;
+
+public class FluidLine {
+ public int y;
+ public int z;
+ public int start;
+ public int finish;
+ public int size;
+
+ public FluidLine(int x, int y, int z) {
+ this.start = this.finish = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public FluidLine(BlockLocation location) {
+ this.start = this.finish = location.x;
+ this.y = location.y;
+ this.z = location.z;
+ }
+
+ public ArrayList<FluidLine> getSideLines(WorldProvider provider) {
+ ArrayList<FluidLine> sideLines;
+ sideLines = getSideLines(provider, z + 1);
+ sideLines.addAll(getSideLines(provider, z - 1));
+ return sideLines;
+ }
+
+ public ArrayList<FluidLine> getSideLines(WorldProvider provider, int z) {
+ ArrayList<FluidLine> sideLines = new ArrayList<FluidLine>();
+ BlockLocation test = new BlockLocation(start, y, z);
+ boolean found = false;
+ FluidLine side = null;
+ while (test.x < finish) {
+ ChunkData data = provider.getChunk(test.getChunkLocation());
+ if (data.isEmpty(test)) {
+ found = true;
+ side = new FluidLine(test);
+ } else {
+ if (found) {
+ side.finish = test.x;
+ sideLines.add(side);
+ found = false;
+ }
+ }
+ test.x++;
+ }
+ return sideLines;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/fluid/FluidSource.java b/src/ru/olamedia/olacraft/world/fluid/FluidSource.java
new file mode 100644
index 0000000..17bffe8
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/fluid/FluidSource.java
@@ -0,0 +1,99 @@
+package ru.olamedia.olacraft.world.fluid;
+
+import java.util.HashMap;
+import java.util.List;
+
+import ru.olamedia.olacraft.world.data.ChunkData;
+import ru.olamedia.olacraft.world.location.BlockLocation;
+import ru.olamedia.olacraft.world.provider.WorldProvider;
+
+public class FluidSource {
+ public HashMap<Integer, FluidLevel> levels = new HashMap<Integer, FluidLevel>();
+ int minY = 0;
+ int maxY = 0;
+
+ public FluidSource(int y) {
+ minY = y;
+ maxY = y;
+ }
+
+ public void flow(WorldProvider provider, BlockLocation location, float amount) {
+ ChunkData data = provider.getChunk(location.getChunkLocation());
+ if (!data.isEmpty(location)) {
+ return;
+ }
+ FluidLevel level = null;
+ int y = location.y;
+ while (null == level || amount > 0) {
+ level = getFluidLevel(provider, location);
+ if (null == level) {
+ return;
+ }
+ if (level.size < amount) {
+ level.fluidLevel = 1f;
+ amount--;
+ } else {
+ level.fluidLevel = ((float) level.size) / amount;
+ }
+ levels.put(y, level);
+ y++;
+ }
+ }
+
+ private FluidLevel getFluidLevel(WorldProvider provider, BlockLocation location) {
+ ChunkData data = provider.getChunk(location.getChunkLocation());
+ if (!data.isEmpty(location)) {
+ return null;
+ }
+ FluidLevel level = new FluidLevel();
+ FluidLine startLine = getFluidLine(provider, location);
+
+ if (location.z > 0) {
+ BlockLocation test = new BlockLocation(location);
+ for (test.z = location.z - 1; test.z >= 0; test.z--) {
+ test.x = startLine.start;
+ FluidLine nextLine = getFluidLine(provider, test);
+ if (null != nextLine) {
+ test.x = nextLine.finish + 2;
+ if (test.x <= 15) {
+ // continue
+ }else{
+ //
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ private FluidLine getFluidLine(WorldProvider provider, BlockLocation location) {
+ ChunkData data = provider.getChunk(location.getChunkLocation());
+ if (!data.isEmpty(location)) {
+ return null;
+ }
+ FluidLine line = new FluidLine(location);
+ line.start = line.finish = location.x;
+ BlockLocation test = new BlockLocation(location);
+ if (location.x > 0) {
+ for (test.x = location.x - 1; test.x >= 0; test.x--) {
+ if (!data.isEmpty(test)) {
+ break;
+ }
+ line.start = test.x;
+ }
+ } else {
+ line.start = 0;
+ }
+ if (location.x < 15) {
+ for (test.x = location.x + 1; test.x <= 15; test.x++) {
+ if (!data.isEmpty(test)) {
+ break;
+ }
+ line.finish = test.x;
+ }
+ } else {
+ line.finish = 15;
+ }
+ return line;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/fluid/package-info.java b/src/ru/olamedia/olacraft/world/fluid/package-info.java
new file mode 100644
index 0000000..d2764d9
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/fluid/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author olamedia
+ *
+ */
+package ru.olamedia.olacraft.world.fluid; \ 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
index 649961f..5d6d0d5 100644
--- a/src/ru/olamedia/olacraft/world/generator/HeightMapGenerator.java
+++ b/src/ru/olamedia/olacraft/world/generator/HeightMapGenerator.java
@@ -1,6 +1,5 @@
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;
@@ -58,7 +57,7 @@ public class HeightMapGenerator {
// MOUNTAINS
mountainsNoise = new RidgedMulti();
mountainsNoise.setFrequency(0.04);
- mountainsNoise.setOctaveCount(6);
+ mountainsNoise.setOctaveCount(4);
turbulence = new Turbulence(mountainsNoise);
turbulence.setFrequency(0.2);
turbulence.setPower(1);
@@ -105,7 +104,7 @@ public class HeightMapGenerator {
// finalTerrain.setEdgeFalloff(1.25);
NoiseMap heightMap = new NoiseMap(16, 16);
- builder.setSourceModule(maxTerrain);
+ builder.setSourceModule(blendedTerrain);
builder.setDestNoiseMap(heightMap);
double bx = chunkX;
double bz = chunkZ;
@@ -118,7 +117,7 @@ public class HeightMapGenerator {
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) (50 + minValue + (maxValue - minValue) * (heights[x][z] + 1) / 2);
+ ints[x][z] = (int) (minValue + (maxValue - minValue) * (heights[x][z] + 1) / 2);
}
}
// System.out.println("");
@@ -138,8 +137,6 @@ public class HeightMapGenerator {
builder.setSourceModule(finalTerrain);
builder.setDestNoiseMap(heightMap);
builder.setDestSize(256, 256);
- float bx = location.getBlockLocation().x;
- float bz = location.getBlockLocation().z;
float cx = location.getChunkLocation().x;
float cz = location.getChunkLocation().z;
builder.setBounds(cx, cx + 16, cz, cz + 16);
diff --git a/src/ru/olamedia/olacraft/world/generator/HumiditySelectLayer.java b/src/ru/olamedia/olacraft/world/generator/HumiditySelectLayer.java
new file mode 100644
index 0000000..63d25c6
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/generator/HumiditySelectLayer.java
@@ -0,0 +1,31 @@
+package ru.olamedia.olacraft.world.generator;
+
+import libnoiseforjava.NoiseGen.NoiseQuality;
+import libnoiseforjava.exception.ExceptionInvalidParam;
+import libnoiseforjava.module.Perlin;
+import libnoiseforjava.module.RidgedMulti;
+
+public class HumiditySelectLayer {
+ protected long seed;
+
+ protected Perlin noise = new Perlin();
+ //protected RidgedMulti noise = new RidgedMulti();
+
+ public HumiditySelectLayer() {
+ noise.setNoiseQuality(NoiseQuality.QUALITY_BEST);
+ try {
+ noise.setOctaveCount(5);
+ noise.setFrequency(0.004);
+ } catch (ExceptionInvalidParam e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void setSeed(int seed) {
+ noise.setSeed(seed);
+ }
+
+ public double getHumidity(double x, double z) {
+ return noise.getValue(x, 0, z);
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/generator/IslandSelectLayer.java b/src/ru/olamedia/olacraft/world/generator/IslandSelectLayer.java
new file mode 100644
index 0000000..facfc3b
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/generator/IslandSelectLayer.java
@@ -0,0 +1,31 @@
+package ru.olamedia.olacraft.world.generator;
+
+import libnoiseforjava.NoiseGen.NoiseQuality;
+import libnoiseforjava.exception.ExceptionInvalidParam;
+import libnoiseforjava.module.Perlin;
+import libnoiseforjava.module.RidgedMulti;
+
+public class IslandSelectLayer {
+ protected long seed;
+
+ protected Perlin noise = new Perlin();
+ //protected RidgedMulti noise = new RidgedMulti();
+
+ public IslandSelectLayer() {
+ noise.setNoiseQuality(NoiseQuality.QUALITY_BEST);
+ try {
+ noise.setOctaveCount(5);
+ noise.setFrequency(0.004);
+ } catch (ExceptionInvalidParam e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void setSeed(int seed) {
+ noise.setSeed(seed);
+ }
+
+ public double getHeight(double x, double z) {
+ return noise.getValue(x, 0, z);
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/generator/MountainSelectLayer.java b/src/ru/olamedia/olacraft/world/generator/MountainSelectLayer.java
new file mode 100644
index 0000000..5c0390f
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/generator/MountainSelectLayer.java
@@ -0,0 +1,38 @@
+package ru.olamedia.olacraft.world.generator;
+
+import libnoiseforjava.NoiseGen.NoiseQuality;
+import libnoiseforjava.exception.ExceptionInvalidParam;
+import libnoiseforjava.module.Perlin;
+import libnoiseforjava.module.RidgedMulti;
+
+public class MountainSelectLayer {
+ protected long seed;
+
+ protected Perlin mountainNoise = new Perlin();
+ protected Perlin hillNoise = new Perlin();
+
+ public MountainSelectLayer() {
+ hillNoise.setNoiseQuality(NoiseQuality.QUALITY_BEST);
+ mountainNoise.setNoiseQuality(NoiseQuality.QUALITY_BEST);
+ try {
+ hillNoise.setOctaveCount(5);
+ hillNoise.setFrequency(0.004);
+ mountainNoise.setOctaveCount(7);
+ mountainNoise.setFrequency(0.004);
+ } catch (ExceptionInvalidParam e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void setSeed(int seed) {
+ hillNoise.setSeed(seed);
+ mountainNoise.setSeed(seed);
+ }
+
+ private double val;
+
+ public double getHeight(double x, double z) {
+ val = mountainNoise.getValue(x, 0, z);
+ return (val > 0) ? 1 - val : 1 + val;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/generator/OceanSelectLayer.java b/src/ru/olamedia/olacraft/world/generator/OceanSelectLayer.java
new file mode 100644
index 0000000..f0ca567
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/generator/OceanSelectLayer.java
@@ -0,0 +1,31 @@
+package ru.olamedia.olacraft.world.generator;
+
+import libnoiseforjava.NoiseGen.NoiseQuality;
+import libnoiseforjava.exception.ExceptionInvalidParam;
+import libnoiseforjava.module.Perlin;
+import libnoiseforjava.module.RidgedMulti;
+
+public class OceanSelectLayer {
+ protected long seed;
+
+ protected Perlin noise = new Perlin();
+ //protected RidgedMulti noise = new RidgedMulti();
+
+ public OceanSelectLayer() {
+ noise.setNoiseQuality(NoiseQuality.QUALITY_BEST);
+ try {
+ noise.setOctaveCount(5);
+ noise.setFrequency(0.0004);
+ } catch (ExceptionInvalidParam e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void setSeed(int seed) {
+ noise.setSeed(seed);
+ }
+
+ public double getHeight(double x, double z) {
+ return noise.getValue(x, 0, z);
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/generator/RegionGenerator.java b/src/ru/olamedia/olacraft/world/generator/RegionGenerator.java
index 79ac898..8156b65 100644
--- a/src/ru/olamedia/olacraft/world/generator/RegionGenerator.java
+++ b/src/ru/olamedia/olacraft/world/generator/RegionGenerator.java
@@ -1,5 +1,18 @@
package ru.olamedia.olacraft.world.generator;
+import java.nio.IntBuffer;
+import java.util.Random;
+
+import libnoiseforjava.exception.ExceptionInvalidParam;
+import libnoiseforjava.module.Perlin;
+import ru.olamedia.olacraft.world.biome.Biome;
+import ru.olamedia.olacraft.world.block.BlockRegistry;
+import ru.olamedia.olacraft.world.blockTypes.GrassBlockType;
+import ru.olamedia.olacraft.world.blockTypes.IceBlockType;
+import ru.olamedia.olacraft.world.blockTypes.SnowBlockType;
+import ru.olamedia.olacraft.world.blockTypes.TallGrassBlockType;
+import ru.olamedia.olacraft.world.blockTypes.WaterBlockType;
+import ru.olamedia.olacraft.world.blockTypes.stone.SandstoneStoneBlockType;
import ru.olamedia.olacraft.world.chunk.Chunk;
import ru.olamedia.olacraft.world.data.ChunkData;
import ru.olamedia.olacraft.world.data.HeightMap;
@@ -7,10 +20,23 @@ 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.IntLocation;
import ru.olamedia.olacraft.world.location.SectorLocation;
public class RegionGenerator {
private int[] seed;
+ private Random rand;
+
+ private OceanSelectLayer oceanSelect = new OceanSelectLayer();
+ private IslandSelectLayer islandSelect = new IslandSelectLayer();
+ private TemperatureSelectLayer tempSelect = new TemperatureSelectLayer();
+ private HumiditySelectLayer humSelect = new HumiditySelectLayer();
+ private RiverSelectLayer riverSelect = new RiverSelectLayer();
+ private MountainSelectLayer mountainSelect = new MountainSelectLayer();
+ private BlockRegistry types;
+
+ private byte waterId;
+ private byte iceId;
public void setSeed(int[] seed) {
this.seed = seed;
@@ -20,13 +46,229 @@ public class RegionGenerator {
System.out.println("[RegionGenerator] " + s);
}
+ private int[] heightCache;
+ private double[] temps;
+ private double[] hums;
+ private int[] biome;
+ private boolean[] initialized;
+ private boolean[] water;
+
+ protected Perlin erosionNoise = new Perlin();
+
+ public double avg(double a, double b) {
+ return (a + b) / 2;
+ }
+
+ public double blend(double... args) {
+ double x = 0;
+ for (int i = 0; i < args.length; i++) {
+ x += args[i];
+ }
+ return x / args.length;
+ }
+
+ public int getHeight(int vid, int x, int z) { // vid - vertical id
+ if (!initialized[vid]) {
+ double height = 0;
+ double oceanHeight = Math.min(0, oceanSelect.getHeight(x, z) * 100);
+ double isleHeight = islandSelect.getHeight(x, z) * 4;
+ double riverHeight = riverSelect.getHeight(x, z) * 15;
+ double temp = 10;// tempSelect.getTemperature(x, z) * 40; // -40..40
+ double humidity = humSelect.getHumidity(x, z) * 50 + 50; // 0..100
+ double mountain = mountainSelect.getHeight(x, z) * 20;
+ temps[vid] = temp;
+ hums[vid] = humidity;
+ height = mountain;// blend(oceanHeight, isleHeight);
+ if (oceanHeight < 0) {
+ water[vid] = true;
+ height = (int) Math.max(-120, oceanHeight);
+ } else {
+ water[vid] = false;
+ // height = (int) Math.max(0, avg(oceanHeight, avg(isleHeight,
+ // avg(oceanHeight, mountain))));
+ }
+
+ biome[vid] = Biome.land;
+ //
+ // if (oceanHeight > 0) {
+ // // materic
+ // biome[vid] = Biome.land;
+ // height = isleHeight;
+ // if (mountain > 1) {
+ // height = isleHeight;
+ // }
+ // if (riverHeight < 0) {
+ // // RIVERS
+ // water[vid] = true;
+ // height = riverHeight;
+ // } else {
+ // if (temp > 30) {
+ // biome[vid] = Biome.desert;
+ // }
+ // }
+ // } else {
+ // if (isleHeight > 0) {
+ // // island core
+ // height = 2;
+ // biome[vid] = Biome.island;
+ // } else if (oceanHeight > -3 && isleHeight > -10) {
+ // // half-island merged
+ // height = 1;
+ // biome[vid] = Biome.island;
+ // } else {
+ // water[vid] = true;
+ // height = -2;
+ // }
+ // }
+
+ // return (int) height;
+ heightCache[vid] = (int) height;
+ initialized[vid] = true;
+ }
+ return heightCache[vid];
+ }
+
+ public static int clampFloat(float x, float min, float max) { // x in -1..1
+ return (int) (min + (max - min) * ((1 + x) / 2));
+ }
+
+ // BlockLocation blockOffset = new BlockLocation();
+
+ private IntBuffer blockLocation = IntLocation.allocate();
+ private IntBuffer blockOffset = IntLocation.allocate();
+ private IntBuffer chunkLocation = IntLocation.allocate();
+ private IntBuffer chunkOffset = IntLocation.allocate();
+
+ public void generateSector(SectorData sector) {
+ heightCache = new int[256];
+ temps = new double[256];
+ hums = new double[256];
+ biome = new int[256];
+ initialized = new boolean[256];
+ water = new boolean[256];
+ for (int i = 0; i < 256; i++) {
+ initialized[i] = false;
+ water[i] = false;
+ }
+ sector.heightMap = new HeightMap(16, 16);
+ for (int y = 0; y < 16; y++) {
+ // CREATE CHUNK
+ final ChunkData chunk = new ChunkData();
+ chunk.location = new ChunkLocation(sector.location.x, y, sector.location.z);
+ IntLocation.set(chunkLocation, sector.location.x, y, sector.location.z);
+ IntLocation.chunk2block(chunkLocation, chunkOffset);
+ // final BlockLocation chunkOffset =
+ // chunk.location.getBlockLocation();
+ for (int inChunkX = 0; inChunkX < 16; inChunkX++) {
+ for (int inChunkZ = 0; inChunkZ < 16; inChunkZ++) {
+ final int vid = inChunkX * 16 + inChunkZ;
+ final int height = getHeight(vid, sector.location.x * 16 + inChunkX, sector.location.z * 16
+ + inChunkZ);
+ // int height = 60;
+ // System.out.println("height: " + height);
+ sector.heightMap.setHeight(inChunkX, inChunkZ, height);
+ IntLocation.setXZ(blockOffset, inChunkX, inChunkZ);
+ for (int inChunkY = 0; inChunkY < 16; inChunkY++) {
+ IntLocation.setY(blockOffset, inChunkY);
+ IntLocation.setSum(blockLocation, chunkOffset, blockOffset);
+ blockID = IntLocation.id(blockLocation);
+ // height = sector.heightMap.getHeight(inChunkX,
+ // inChunkZ);
+ makeBlock(chunk, vid);
+
+ }
+ }
+ }
+ // debug(sector.heightMap.toString());
+ chunk.compact();
+ sector.set(y, chunk);
+ }
+ }
+
+ private int blockHeight;
+ private int blockY;
+ private int blockID;
+
+ private void makeBlock(ChunkData chunk, int vid) {
+ if (null == types) {
+ throw new RuntimeException("types is null");
+ }
+ blockHeight = getHeight(vid, 0, 0); // coordinates makes no difference
+ // as
+ // cached already
+ blockY = IntLocation.getY(blockLocation);
+ blockID = IntLocation.id(blockLocation);
+ /*
+ * double erosion = erosionNoise.getValue(blockOffset.x, blockOffset.y,
+ * blockOffset.z);
+ * if (erosion > 0.99) {
+ * chunk.setEmpty(blockOffset, true);
+ * return;
+ * }
+ */
+ // WATER:
+ if (blockY <= 0) {
+ if (water[vid]) {
+ if (blockY > blockHeight) {
+ chunk.setEmpty(blockID, false);
+ chunk.types[blockID] = waterId;
+ if (temps[vid] < -10) {
+ chunk.types[blockID] = iceId;
+ }
+ return;
+ }
+ }
+ }
+ if (blockY > blockHeight) {
+ // AIR
+ chunk.setEmpty(blockID, true);
+ if (blockY - 1 == blockHeight) {
+ // floor level
+ if (temps[vid] > 15 && temps[vid] < 25 && hums[vid] > 30 && hums[vid] < 70) {
+ if (rand.nextInt(15) > 2) {
+ chunk.setEmpty(blockID, false);
+ chunk.types[blockID] = (byte) (types.getBlockIdByClassName(TallGrassBlockType.class.getName())); // FIXME,
+ }
+ }
+ }
+ } else {
+ // LAND
+ chunk.setEmpty(blockID, false);
+ if (temps[vid] > 30) {
+ chunk.types[blockID] = (byte) types.getBlockIdByClassName(SandstoneStoneBlockType.class.getName());
+ } else if (temps[vid] < -10 && hums[vid] > 30) {
+ chunk.types[blockID] = (byte) (types.getBlockIdByClassName(SnowBlockType.class.getName())); // FIXME,
+ // SNOW
+ } else {
+ chunk.types[blockID] = (byte) (types.getBlockIdByClassName(GrassBlockType.class.getName()));// (1
+ // +
+ // Math.random()
+ // *
+ // 11);
+ }
+ }
+ }
+
public void generate(RegionData data) {
+ final SectorLocation sectorOffset = data.location.getSectorLocation();
HeightMapGenerator.minValue = -5;
HeightMapGenerator.maxValue = 60;
HeightMapGenerator.init();
HeightMapGenerator.seed = seed[0];
+ oceanSelect.setSeed(seed[0]);
+ islandSelect.setSeed(seed[1]);
+ tempSelect.setSeed(seed[2]);
+ humSelect.setSeed(seed[3]);
+ riverSelect.setSeed(seed[4]);
+ rand = new Random(seed[6]);
+ erosionNoise.setFrequency(0.01);
+ try {
+ erosionNoise.setOctaveCount(5);
+ } catch (ExceptionInvalidParam e) {
+ e.printStackTrace();
+ }
+ erosionNoise.setSeed(seed[5]);
// BlockLocation blockOffset = data.location.getBlockLocation();
- SectorLocation sectorOffset = data.location.getSectorLocation();
// int[][] heightMap =
// HeightMapGenerator.getHeightMap(data.location.getBlockLocation().x,
// data.location.getBlockLocation().z, 256, 256);
@@ -37,51 +279,41 @@ public class RegionGenerator {
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
// CREATE SECTOR
- SectorData sector = new SectorData();
+ final SectorData sector = new SectorData();
sector.location = new SectorLocation(sectorOffset.x + x, sectorOffset.z + z);
- 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);
- BlockLocation chunkOffset = chunk.location.getBlockLocation();
- 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);
- BlockLocation blockOffset = new BlockLocation();
- blockOffset.x = chunkOffset.x + inChunkX;
- blockOffset.z = chunkOffset.z + inChunkZ;
- for (int inChunkY = 0; inChunkY < 16; inChunkY++) {
- blockOffset.y = chunkOffset.y + inChunkY;
- // height = sector.heightMap.getHeight(inChunkX,
- // inChunkZ);
- if (blockOffset.y > height) {
- // System.out.println("--- height: " +
- // height + " block:" + blockOffset);
- chunk.setEmpty(blockOffset, true);
- } else {
- if (blockOffset.y > 0) {
- // System.out.println("+++ height: " +
- // height + " block:" + blockOffset);
- // System.out.println("not empty, height: "
- // + height);
- }
- int id = Chunk.in(blockOffset.x) * 16 * 16 + Chunk.in(blockOffset.y) * 16
- + Chunk.in(blockOffset.z);
- chunk.setEmpty(blockOffset, false);
- chunk.types[id] = (byte) (1 + Math.random() * 4);
- }
- }
- }
- }
- chunk.compact();
- sector.chunkData[y] = chunk;
- }
+ generateSector(sector);
data.sectorData[x][z] = sector;
}
}
}
+
+ public void setTypes(BlockRegistry types) {
+ this.types = types;
+ waterId = (byte) types.getBlockIdByClassName(WaterBlockType.class.getName());
+ iceId = (byte) types.getBlockIdByClassName(IceBlockType.class.getName());
+ }
+
+ 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/RiverSelectLayer.java b/src/ru/olamedia/olacraft/world/generator/RiverSelectLayer.java
new file mode 100644
index 0000000..a7b7c3e
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/generator/RiverSelectLayer.java
@@ -0,0 +1,56 @@
+package ru.olamedia.olacraft.world.generator;
+
+import libnoiseforjava.NoiseGen.NoiseQuality;
+import libnoiseforjava.exception.ExceptionInvalidParam;
+import libnoiseforjava.module.Perlin;
+import libnoiseforjava.module.RidgedMulti;
+
+public class RiverSelectLayer {
+
+ protected Perlin noise = new Perlin();
+ protected Perlin widthNoise = new Perlin();
+ protected Perlin deepNoise = new Perlin();
+
+ // protected RidgedMulti noise = new RidgedMulti();
+
+ public RiverSelectLayer() {
+ noise.setNoiseQuality(NoiseQuality.QUALITY_BEST);
+ widthNoise.setNoiseQuality(NoiseQuality.QUALITY_BEST);
+ deepNoise.setNoiseQuality(NoiseQuality.QUALITY_BEST);
+ try {
+ noise.setOctaveCount(5);
+ noise.setFrequency(0.000004);
+ widthNoise.setOctaveCount(6);
+ widthNoise.setFrequency(0.004);
+ deepNoise.setOctaveCount(3);
+ deepNoise.setFrequency(0.004);
+ } catch (ExceptionInvalidParam e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void setSeed(int seed) {
+ noise.setSeed(seed);
+ widthNoise.setSeed(seed);
+ deepNoise.setSeed(seed);
+ }
+
+ static double min = -0.0005;
+ static double max = 0;
+ private static double deepFactor = 0;
+
+ public static double scale(double value) {
+ final double factor = 1 / (max - min);
+ final double r01 = (value - min) * factor; // 0..1
+ final double r3 = r01 > 0.5 ? -r01 : -r01;
+ return -(1 - Math.abs(1 - r01 * 2)) * deepFactor;
+ }
+
+ public double getHeight(double x, double z) {
+ final double widthFactor = widthNoise.getValue(x, 0, z);
+ deepFactor = (deepNoise.getValue(x, 0, z) + 1.2) / 2.2;
+ min = -0.000005 * (1 + (1 + widthFactor) * 40);
+ final double value = noise.getValue(x, 0, z);
+ return value >= min && value <= max ? scale(value) : 0;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/generator/TemperatureSelectLayer.java b/src/ru/olamedia/olacraft/world/generator/TemperatureSelectLayer.java
new file mode 100644
index 0000000..ca3902f
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/generator/TemperatureSelectLayer.java
@@ -0,0 +1,31 @@
+package ru.olamedia.olacraft.world.generator;
+
+import libnoiseforjava.NoiseGen.NoiseQuality;
+import libnoiseforjava.exception.ExceptionInvalidParam;
+import libnoiseforjava.module.Perlin;
+import libnoiseforjava.module.RidgedMulti;
+
+public class TemperatureSelectLayer {
+ protected long seed;
+
+ protected Perlin noise = new Perlin();
+ //protected RidgedMulti noise = new RidgedMulti();
+
+ public TemperatureSelectLayer() {
+ noise.setNoiseQuality(NoiseQuality.QUALITY_BEST);
+ try {
+ noise.setOctaveCount(5);
+ noise.setFrequency(0.004);
+ } catch (ExceptionInvalidParam e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void setSeed(int seed) {
+ noise.setSeed(seed);
+ }
+
+ public double getTemperature(double x, double z) {
+ return noise.getValue(x, 0, z);
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/location/BlockLocation.java b/src/ru/olamedia/olacraft/world/location/BlockLocation.java
index 9639ac1..371c084 100644
--- a/src/ru/olamedia/olacraft/world/location/BlockLocation.java
+++ b/src/ru/olamedia/olacraft/world/location/BlockLocation.java
@@ -2,70 +2,110 @@ package ru.olamedia.olacraft.world.location;
import java.io.Serializable;
-import ru.olamedia.olacraft.world.chunk.Chunk;
-
-public class BlockLocation implements Serializable {
+public class BlockLocation extends Location3i implements Serializable {
private static final long serialVersionUID = -4987461467575474762L;
- public int x;
- public int y;
- public int z;
+ private static int yChunkShift = 128;
public BlockLocation() {
}
+ public byte getByteX() {
+ return (byte) (x & 15);
+ }
+
+ public int getChunkX() {
+ return (int) (x >> 4);
+ }
+
+ public int getRegionX() {
+ return (int) (x >> 8);
+ }
+
+ public byte getByteY() {
+ return (byte) (y & 15);
+ }
+
+ public int getChunkY() {
+ return (int) ((y + yChunkShift) >> 4);
+ }
+
+ public int getRegionY() {
+ return (int) ((y + yChunkShift) >> 8);
+ }
+
+ public byte getByteZ() {
+ return (byte) (z & 15);
+ }
+
+ public int getChunkZ() {
+ return (int) (z >> 4);
+ }
+
+ public int getRegionZ() {
+ return (int) (z >> 8);
+ }
+
+ public short getId() {
+ return IntLocation.id(x, y, z);
+ }
+
public boolean isChunkEdge() {
- int cx = Chunk.in(x);
- int cy = Chunk.in(y);
- int cz = Chunk.in(z);
+ int cx = getByteX();
+ int cy = getByteY();
+ int cz = getByteZ();
return (cx == 0 || cy == 0 || cz == 0 || cx == 15 || cy == 15 || cz == 15);
}
public boolean isChunkLeftEdge() {
- return Chunk.in(x) == 0;
+ return getByteX() == 0;
}
public boolean isChunkRightEdge() {
- return Chunk.in(x) == 15;
+ return getByteX() == 15;
}
public boolean isChunkTopEdge() {
- return Chunk.in(y) == 15;
+ return getByteY() == 15;
}
public boolean isChunkBottomEdge() {
- return Chunk.in(y) == 0;
+ return getByteY() == 0;
}
public boolean isChunkFrontEdge() {
- return Chunk.in(z) == 15;
+ return getByteZ() == 15;
}
public boolean isChunkBackEdge() {
- return Chunk.in(z) == 0;
+ return getByteZ() == 0;
}
public BlockLocation(int x, int y, int z) {
- this.x = x;
- this.y = y;
- this.z = z;
+ super(x, y, z);
}
public BlockLocation(float x, float y, float z) {
- this.x = (int) x;
- this.y = (int) y;
- this.z = (int) z;
+ super(x, y, z);
+ }
+
+ public BlockLocation(Location3i location) {
+ super(location);
+ }
+
+ public BlockLocation(Location3f location) {
+ super(location);
}
public ChunkLocation getChunkLocation() {
- return new ChunkLocation(Chunk.v(x), Chunk.v(y + 128), Chunk.v(z));
+ return new ChunkLocation(getChunkX(), getChunkY(), getChunkZ());
}
public RegionLocation getRegionLocation() {
- return new RegionLocation(Chunk.v(Chunk.v(x)), Chunk.v(Chunk.v(z)));
+ return new RegionLocation(getRegionX(), getRegionZ());
}
public SectorLocation getSectorLocation() {
- return new SectorLocation(Chunk.v(x), Chunk.v(z));
+ return new SectorLocation(getChunkX(), getChunkZ());
}
public String toString() {
diff --git a/src/ru/olamedia/olacraft/world/location/ChunkLocation.java b/src/ru/olamedia/olacraft/world/location/ChunkLocation.java
index 439b9be..73a9c16 100644
--- a/src/ru/olamedia/olacraft/world/location/ChunkLocation.java
+++ b/src/ru/olamedia/olacraft/world/location/ChunkLocation.java
@@ -4,28 +4,19 @@ import java.io.Serializable;
import ru.olamedia.olacraft.world.chunk.Chunk;
-public class ChunkLocation implements Serializable {
+public class ChunkLocation extends Location3i 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;
+ super(x, y, z);
}
- public ChunkLocation(ChunkLocation loc) {
- this.x = loc.x;
- this.y = loc.y;
- this.z = loc.z;
+ public ChunkLocation(Location3i cameraChunk) {
+ super(cameraChunk);
}
- public int x;
- public int y;
- public int z;
+ public ChunkLocation() {
+ }
public SectorLocation getSectorLocation() {
return new SectorLocation(x, z);
diff --git a/src/ru/olamedia/olacraft/world/location/IntLocation.java b/src/ru/olamedia/olacraft/world/location/IntLocation.java
new file mode 100644
index 0000000..3ee7110
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/location/IntLocation.java
@@ -0,0 +1,200 @@
+package ru.olamedia.olacraft.world.location;
+
+import java.nio.IntBuffer;
+
+public class IntLocation {
+ private static int yShift = 128;
+
+ public static IntBuffer allocate() {
+ return IntBuffer.allocate(3);
+ }
+
+ public static boolean inRange(int x, int y, int z) {
+ return inRange(x) && inRange(y) && inRange(z);
+ }
+
+ public static boolean inRange(int val) {
+ return (val >= 0) && (val <= 15);
+ }
+
+ public static byte in(int val) {
+ return (byte) (val & 15);
+ }
+
+ public static int chunk(int val) {
+ return val >> 4;
+ }
+
+ public static int region(int val) {
+ return val >> 8;
+ }
+
+ public static int rev(int val) {
+ return val * 16;
+ }
+
+ public static int rev2(int val) {
+ return val * 256;
+ }
+
+ public static short id(int x, int y, int z) {
+ return (short) ((x & 15) * 256 + (y & 15) * 16 + (z & 15));
+ }
+
+ public static short leftId(int x, int y, int z) {
+ return id(x - 1, y, z);
+ }
+
+ public static short rightId(int x, int y, int z) {
+ return id(x + 1, y, z);
+ }
+
+ public static short topId(int x, int y, int z) {
+ return id(x, y + 1, z);
+ }
+
+ public static short bottomId(int x, int y, int z) {
+ return id(x, y - 1, z);
+ }
+
+ public static short backId(int x, int y, int z) {
+ return id(x, y, z + 1);
+ }
+
+ public static short frontId(int x, int y, int z) {
+ return id(x, y, z - 1);
+ }
+
+ public static int[] block2chunk(int[] b) {
+ return new int[] { chunk(b[0]), chunk(b[1] + yShift), chunk(b[2]) };
+ }
+
+ public static void block2chunk(int[] b, int[] c) {
+ c[0] = chunk(b[0]);
+ c[1] = chunk(b[1] + yShift);
+ c[2] = chunk(b[2]);
+ }
+
+ public static void block2chunk(IntBuffer b, IntBuffer c) {
+ c.put(0, chunk(b.get(0)));
+ c.put(1, chunk(b.get(1) + yShift));
+ c.put(2, chunk(b.get(2)));
+ }
+
+ public static int[] chunk2block(int[] c) {
+ return new int[] { rev(c[0]), rev(c[1]) - yShift, rev(c[2]) };
+ }
+
+ public static void chunk2block(int[] c, int[] b) {
+ b[0] = rev(c[0]);
+ b[1] = rev(c[1]) - yShift;
+ b[2] = rev(c[2]);
+ }
+
+ public static void chunk2block(IntBuffer c, IntBuffer b) {
+ b.put(0, rev(c.get(0)));
+ b.put(1, rev(c.get(1)) - yShift);
+ b.put(2, rev(c.get(2)));
+ }
+
+ public static int[] region2chunk(int[] r) {
+ return new int[] { rev(r[0]), rev(r[1]), rev(r[2]) };
+ }
+
+ public static void region2chunk(int[] r, int[] c) {
+ c[0] = rev(r[0]);
+ c[1] = rev(r[1]);
+ c[2] = rev(r[2]);
+ }
+
+ public static void region2chunk(IntBuffer r, IntBuffer c) {
+ c.put(0, rev(r.get(0)));
+ c.put(1, rev(r.get(1)));
+ c.put(2, rev(r.get(2)));
+ }
+
+ public static int[] region2block(int[] r) {
+ return new int[] { rev2(r[0]), rev2(r[1]) - yShift, rev2(r[2]) };
+ }
+
+ public static void region2block(int[] r, int[] b) {
+ b[0] = rev2(r[0]);
+ b[1] = rev2(r[1]) - yShift;
+ b[2] = rev2(r[2]);
+ }
+
+ public static void region2block(IntBuffer r, IntBuffer b) {
+ b.put(0, rev2(r.get(0)));
+ b.put(1, rev2(r.get(1)) - yShift);
+ b.put(2, rev2(r.get(2)));
+ }
+
+ public static int[] block2region(int[] b) {
+ return new int[] { chunk(chunk(b[0])), chunk(chunk(b[1] + yShift)), chunk(chunk(b[2])) };
+ }
+
+ public static void block2region(int[] b, int[] r) {
+ r[0] = region(b[0]);
+ r[1] = region(b[1] + yShift);
+ r[2] = region(b[2]);
+ }
+
+ public static void block2region(IntBuffer b, IntBuffer r) {
+ r.put(0, region(b.get(0)));
+ r.put(1, region(b.get(1) + yShift));
+ r.put(2, region(b.get(2)));
+ }
+
+ public static int[] chunk2region(int[] c) {
+ return new int[] { chunk(c[0]), chunk(c[1]), chunk(c[2]) };
+ }
+
+ public static void chunk2region(int[] c, int[] r) {
+ r[0] = chunk(c[0]);
+ r[1] = chunk(c[1]);
+ r[2] = chunk(c[2]);
+ }
+
+ public static void chunk2region(IntBuffer c, IntBuffer r) {
+ r.put(0, chunk(c.get(0)));
+ r.put(1, chunk(c.get(1)));
+ r.put(2, chunk(c.get(2)));
+ }
+
+ public static void set(IntBuffer b, int x, int y, int z) {
+ b.put(0, x);
+ b.put(1, y);
+ b.put(2, z);
+ }
+
+ public static void setXZ(IntBuffer b, int x, int z) {
+ b.put(0, x);
+ b.put(2, z);
+ }
+
+ public static void setY(IntBuffer b, int y) {
+ b.put(1, y);
+ }
+
+ public static int getX(IntBuffer b) {
+ return b.get(0);
+ }
+
+ public static int getY(IntBuffer b) {
+ return b.get(1);
+ }
+
+ public static int getZ(IntBuffer b) {
+ return b.get(2);
+ }
+
+ public static int id(IntBuffer b) {
+ return id(b.get(0), b.get(1), b.get(2));
+ }
+
+ public static void setSum(IntBuffer target, IntBuffer b1, IntBuffer b2) {
+ target.put(0, b1.get(0) + b2.get(0));
+ target.put(1, b1.get(1) + b2.get(1));
+ target.put(2, b1.get(2) + b2.get(2));
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/location/Location3f.java b/src/ru/olamedia/olacraft/world/location/Location3f.java
new file mode 100644
index 0000000..a30c6d7
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/location/Location3f.java
@@ -0,0 +1,46 @@
+package ru.olamedia.olacraft.world.location;
+
+public class Location3f {
+ public float x;
+ public float y;
+ public float z;
+
+ public Location3f() {
+ x = 0;
+ y = 0;
+ z = 0;
+ }
+
+ public Location3f(float x, float y, float z) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public Location3f(int x, int y, int z) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public Location3f(Location3f location) {
+ x = location.x;
+ y = location.y;
+ z = location.z;
+ }
+
+ public Location3f(Location3i location) {
+ x = location.x;
+ y = location.y;
+ z = location.z;
+ }
+
+ public String toString() {
+ return "Location3f[" + x + "," + y + "," + z + "]";
+ }
+
+ public void addRandomOffset(float d) {
+ x += Math.random() * d * 2 - d;
+ z += Math.random() * d * 2 - d;
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/location/Location3i.java b/src/ru/olamedia/olacraft/world/location/Location3i.java
new file mode 100644
index 0000000..347e4bc
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/location/Location3i.java
@@ -0,0 +1,71 @@
+package ru.olamedia.olacraft.world.location;
+
+public class Location3i {
+ public int x;
+ public int y;
+ public int z;
+
+ public byte getByteX() {
+ return (byte) (x & 15);
+ }
+
+ public byte getByteY() {
+ return (byte) (y & 15);
+ }
+
+ public byte getByteZ() {
+ return (byte) (z & 15);
+ }
+
+ public Location3i() {
+ x = 0;
+ y = 0;
+ z = 0;
+ }
+
+ public Location3i(float x, float y, float z) {
+ this.x = (int) x;
+ this.y = (int) y;
+ this.z = (int) z;
+ }
+
+ public Location3i(int x, int y, int z) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public Location3i(Location3i location) {
+ x = location.x;
+ y = location.y;
+ z = location.z;
+ }
+
+ public Location3i(Location3f location) {
+ x = (int) location.x;
+ y = (int) location.y;
+ z = (int) location.z;
+ }
+
+ public void set(Location3i location) {
+ this.x = location.x;
+ this.y = location.y;
+ this.z = location.z;
+ }
+
+ public void set(int x, int y, int z) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public void set(float x, float y, float z) {
+ this.x = (int) x;
+ this.y = (int) y;
+ this.z = (int) z;
+ }
+
+ public String toString() {
+ return "Location3i[" + x + "," + y + "," + z + "]";
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/location/MetaLocation3i.java b/src/ru/olamedia/olacraft/world/location/MetaLocation3i.java
new file mode 100644
index 0000000..e440572
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/location/MetaLocation3i.java
@@ -0,0 +1,7 @@
+package ru.olamedia.olacraft.world.location;
+
+import java.nio.IntBuffer;
+
+public class MetaLocation3i {
+ private IntBuffer b = IntBuffer.allocate(3);
+}
diff --git a/src/ru/olamedia/olacraft/world/location/RegionLocation.java b/src/ru/olamedia/olacraft/world/location/RegionLocation.java
index a1100c0..c11d3c8 100644
--- a/src/ru/olamedia/olacraft/world/location/RegionLocation.java
+++ b/src/ru/olamedia/olacraft/world/location/RegionLocation.java
@@ -36,4 +36,40 @@ public class RegionLocation implements Serializable {
public BlockLocation getBlockLocation() {
return new BlockLocation(Chunk.rev(Chunk.rev(x)), 0, Chunk.rev(Chunk.rev(z)));
}
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + x;
+ result = prime * result + z;
+ return result;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ RegionLocation other = (RegionLocation) obj;
+ if (x != other.x)
+ return false;
+ if (z != other.z)
+ return false;
+ return true;
+ }
+
}
diff --git a/src/ru/olamedia/olacraft/world/provider/IWorldProvider.java b/src/ru/olamedia/olacraft/world/provider/IWorldProvider.java
new file mode 100644
index 0000000..5605728
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/provider/IWorldProvider.java
@@ -0,0 +1,11 @@
+package ru.olamedia.olacraft.world.provider;
+
+import ru.olamedia.olacraft.world.WorldInfo;
+
+public interface IWorldProvider {
+ public boolean hasInfo();
+
+ public void requestInfo();
+
+ public WorldInfo getInfo();
+}
diff --git a/src/ru/olamedia/olacraft/world/provider/LocalWorld.java b/src/ru/olamedia/olacraft/world/provider/LocalWorld.java
new file mode 100644
index 0000000..1756118
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/provider/LocalWorld.java
@@ -0,0 +1,24 @@
+package ru.olamedia.olacraft.world.provider;
+
+import ru.olamedia.olacraft.network.provider.LocalProvider;
+import ru.olamedia.olacraft.world.WorldInfo;
+
+public class LocalWorld implements IWorldProvider {
+ private LocalProvider<WorldInfo> info;
+
+ public LocalWorld() {
+ info.put(new WorldInfo());
+ }
+
+ public boolean hasInfo() {
+ return true;
+ }
+
+ public void requestInfo() {
+ // do nothing
+ }
+
+ public WorldInfo getInfo() {
+ return info.get();
+ }
+}
diff --git a/src/ru/olamedia/olacraft/world/provider/RemoteWorld.java b/src/ru/olamedia/olacraft/world/provider/RemoteWorld.java
new file mode 100644
index 0000000..d086bf1
--- /dev/null
+++ b/src/ru/olamedia/olacraft/world/provider/RemoteWorld.java
@@ -0,0 +1,32 @@
+package ru.olamedia.olacraft.world.provider;
+
+import ru.olamedia.olacraft.network.provider.CacheProvider;
+import ru.olamedia.olacraft.network.provider.RemoteProvider;
+import ru.olamedia.olacraft.world.WorldInfo;
+
+public class RemoteWorld implements IWorldProvider {
+ private CacheProvider<WorldInfo> info;
+
+ public RemoteWorld() {
+ info = new CacheProvider<WorldInfo>(new RemoteProvider<WorldInfo>() {
+ @Override
+ public void request() {
+
+ }
+ });
+ }
+
+ public boolean hasInfo() {
+ return info.has();
+ }
+
+ public void requestInfo() {
+ info.request();
+ }
+
+ @Override
+ public WorldInfo getInfo() {
+ return info.get();
+ }
+
+}
diff --git a/src/ru/olamedia/olacraft/world/provider/WorldProvider.java b/src/ru/olamedia/olacraft/world/provider/WorldProvider.java
index 7471b52..decf24d 100644
--- a/src/ru/olamedia/olacraft/world/provider/WorldProvider.java
+++ b/src/ru/olamedia/olacraft/world/provider/WorldProvider.java
@@ -6,25 +6,86 @@ import ru.olamedia.olacraft.world.block.Block;
import ru.olamedia.olacraft.world.block.BlockRegistry;
import ru.olamedia.olacraft.world.blockTypes.AbstractBlockType;
import ru.olamedia.olacraft.world.blockTypes.BlockType;
+import ru.olamedia.olacraft.world.blockTypes.DirtBlockType;
+import ru.olamedia.olacraft.world.blockTypes.GrassBlockType;
+import ru.olamedia.olacraft.world.blockTypes.GravelBlockType;
+import ru.olamedia.olacraft.world.blockTypes.IceBlockType;
+import ru.olamedia.olacraft.world.blockTypes.SnowBlockType;
+import ru.olamedia.olacraft.world.blockTypes.TallGrassBlockType;
+import ru.olamedia.olacraft.world.blockTypes.WaterBlockType;
+import ru.olamedia.olacraft.world.blockTypes.WheatBlockType;
+import ru.olamedia.olacraft.world.blockTypes.stone.BrecciaStoneBlockType;
+import ru.olamedia.olacraft.world.blockTypes.stone.ChertStoneBlockType;
+import ru.olamedia.olacraft.world.blockTypes.stone.CoalStoneBlockType;
+import ru.olamedia.olacraft.world.blockTypes.stone.ConglomerateStoneBlockType;
+import ru.olamedia.olacraft.world.blockTypes.stone.LimestoneStoneBlockType;
+import ru.olamedia.olacraft.world.blockTypes.stone.SandstoneStoneBlockType;
+import ru.olamedia.olacraft.world.blockTypes.stone.ShaleStoneBlockType;
+import ru.olamedia.olacraft.world.blockTypes.stone.SiltstoneStoneBlockType;
import ru.olamedia.olacraft.world.chunk.ChunkUnavailableException;
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.drop.DroppedEntity;
import ru.olamedia.olacraft.world.location.BlockLocation;
import ru.olamedia.olacraft.world.location.ChunkLocation;
import ru.olamedia.olacraft.world.location.RegionLocation;
+/**
+ * Provides ALL information about world (world height, block types, chunks, mobs, spawn locations etc)
+ *
+ */
public class WorldProvider {
private WorldInfo info = new WorldInfo();
- private BlockRegistry typeRegistry = new BlockRegistry();
+ private BlockRegistry types = new BlockRegistry();
private AbstractChunkDataProvider dataProvider;
+
+ public WorldProvider() {
+ registerBlockTypes(false);
+ }
+
+ public void registerTextures(){
+ registerBlockTypes(true);
+ }
+
+ protected void registerBlockType(AbstractBlockType t, boolean registerTextures){
+ if (registerTextures) {
+ t.getBackTexture();
+ t.getBottomTexture();
+ t.getFrontTexture();
+ t.getLeftTexture();
+ t.getRightTexture();
+ t.getTopTexture();
+ } else {
+ types.registerBlockType(t);
+ }
+ }
+
+ protected void registerBlockTypes(boolean registerTextures) {
+ registerBlockType(new GrassBlockType(), registerTextures);
+ registerBlockType(new ConglomerateStoneBlockType(), registerTextures);
+ registerBlockType(new LimestoneStoneBlockType(), registerTextures);
+ registerBlockType(new ChertStoneBlockType(), registerTextures);
+ registerBlockType(new SiltstoneStoneBlockType(), registerTextures);
+ registerBlockType(new SandstoneStoneBlockType(), registerTextures);
+ registerBlockType(new ShaleStoneBlockType(), registerTextures);
+ registerBlockType(new CoalStoneBlockType(), registerTextures);
+ registerBlockType(new BrecciaStoneBlockType(), registerTextures);
+ registerBlockType(new DirtBlockType(), registerTextures);
+ registerBlockType(new GravelBlockType(), registerTextures);
+ registerBlockType(new WheatBlockType(), registerTextures);
+ registerBlockType(new WaterBlockType(), registerTextures);
+ registerBlockType(new IceBlockType(), registerTextures);
+ registerBlockType(new SnowBlockType(), registerTextures);
+ registerBlockType(new TallGrassBlockType(), registerTextures);
+ }
public WorldInfo getInfo() {
return info;
}
-
- public BlockRegistry getTypeRegistry(){
- return typeRegistry;
+
+ public BlockRegistry getTypeRegistry() {
+ return types;
}
public void setInfo(WorldInfo worldInfo) {
@@ -39,9 +100,11 @@ public class WorldProvider {
public void setChunkDataProvider(AbstractChunkDataProvider provider) {
dataProvider = provider;
+ dataProvider.setTypeRegistry(this.types);
}
public SpawnLocation getSpawnLocation(int connectionId) {
+ dataProvider.setTypeRegistry(this.types);
SpawnLocation l = new SpawnLocation();
int maxShift = 10;
l.x = (int) (maxShift - Math.random() * 2 * maxShift);
@@ -140,7 +203,76 @@ public class WorldProvider {
return dataProvider.getChunk(chunkLocation);
}
- public BlockType getBlockTypeById(int id) {
- return typeRegistry.getBlockType(id);
+ public AbstractBlockType getBlockTypeById(int id) {
+ return types.getBlockType(id);
}
+
+ public boolean isOpaque(int x, int y, int z) throws ChunkUnavailableException {
+ BlockLocation blockLocation = new BlockLocation(x, y, z);
+ if (isChunkAvailable(blockLocation.getChunkLocation())) {
+ ChunkData data = dataProvider.getChunk(blockLocation.getChunkLocation());
+ if (null != data) {
+ int id = ChunkData.ClampID(x, y, z);
+ if (data.isEmpty(id)) {
+ return false;
+ }
+ return types.isOpaque(data.types[id]);
+ } else {
+ System.out.println("chunk null " + x + " " + y + " " + z);
+ }
+ } else {
+ throw new ChunkUnavailableException();
+ }
+ return false;
+ }
+
+ public boolean hideTouchedSides(int x, int y, int z, int typeid) throws ChunkUnavailableException {
+ BlockLocation blockLocation = new BlockLocation(x, y, z);
+ if (isChunkAvailable(blockLocation.getChunkLocation())) {
+ ChunkData data = dataProvider.getChunk(blockLocation.getChunkLocation());
+ if (null != data) {
+ int id = ChunkData.ClampID(x, y, z);
+ if (data.isEmpty(id)) {
+ return false;
+ }
+ if (data.types[id] == typeid) {
+ return types.getBlockType(data.types[id]).hideTouchedSides();
+ }
+ return types.isOpaque(data.types[id]);
+ } else {
+ System.out.println("chunk null " + x + " " + y + " " + z);
+ }
+ } else {
+ throw new ChunkUnavailableException();
+ }
+ return false;
+ }
+
+ public boolean canMoveThrough(int x, int y, int z) throws ChunkUnavailableException {
+ BlockLocation blockLocation = new BlockLocation(x, y, z);
+ if (isChunkAvailable(blockLocation.getChunkLocation())) {
+ ChunkData data = dataProvider.getChunk(blockLocation.getChunkLocation());
+ if (null != data) {
+ int id = ChunkData.ClampID(x, y, z);
+ if (data.isEmpty(id)) {
+ return true;
+ }
+ return types.canMoveThrough(data.types[id]);
+ } else {
+ System.out.println("chunk null " + x + " " + y + " " + z);
+ }
+ } else {
+ throw new ChunkUnavailableException();
+ }
+ return false;
+ }
+
+ public void dropBlock(BlockLocation location, AbstractBlockType type) throws ChunkUnavailableException {
+ if (!isChunkAvailable(location.getChunkLocation())) {
+ throw new ChunkUnavailableException();
+ }
+ ChunkData data = dataProvider.getChunk(location.getChunkLocation());
+ data.addDroppedEntity(new DroppedEntity(location, type, 1));
+ }
+
}
diff --git a/src/ru/olamedia/player/Player.java b/src/ru/olamedia/player/Player.java
index bb62201..342175a 100644
--- a/src/ru/olamedia/player/Player.java
+++ b/src/ru/olamedia/player/Player.java
@@ -1,14 +1,385 @@
package ru.olamedia.player;
+import java.io.FileNotFoundException;
+
+import javax.media.opengl.GL2;
+import javax.media.opengl.GLContext;
+
+import jp.nyatla.nymmd.MmdException;
+import jp.nyatla.nymmd.MmdMotionPlayerGL2;
+import jp.nyatla.nymmd.MmdPmdModel;
+import jp.nyatla.nymmd.MmdVmdMotion;
+import jp.nyatla.nymmd.types.MmdVector3;
+import jp.nyatla.nymmd.types.MmdVector4;
+
+import com.jogamp.newt.event.MouseEvent;
+
+import ru.olamedia.asset.Asset;
+import ru.olamedia.asset.AssetManager;
+import ru.olamedia.asset.AssetNotFoundException;
+import ru.olamedia.game.GameTime;
+import ru.olamedia.input.MouseJail;
import ru.olamedia.liveEntity.LiveEntity;
import ru.olamedia.olacraft.game.Game;
+import ru.olamedia.olacraft.modelAnimator.Arm;
+import ru.olamedia.olacraft.modelAnimator.Bone;
+import ru.olamedia.olacraft.modelAnimator.Leg;
+import ru.olamedia.olacraft.modelAnimator.ModelAnimator;
+import ru.olamedia.olacraft.modelAnimator.Skeleton;
import ru.olamedia.olacraft.network.packet.LiveEntityLocationUpdatePacket;
-import ru.olamedia.olacraft.weapon.Bullet;
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.blockStack.BlockStack;
+import ru.olamedia.olacraft.world.blockTypes.EmptyBlockType;
+import ru.olamedia.olacraft.world.chunk.ChunkUnavailableException;
public class Player extends LiveEntity {
+ private MmdMotionPlayerGL2 gl2player;
+ private MmdPmdModel model;
+ private MmdVmdMotion motion;
+ private boolean reverseModelLook = true;
+
+ private float motionTimer = 0;
+ private float motionTimerSpeed = 1f;
+ private float motionTimerFinish = 1;
+
+ private MmdVmdMotion getMotion() {
+ if (null == motion) {
+ try {
+ final Asset motionAsset = AssetManager.getAsset("models/test.vmd");
+ motion = new MmdVmdMotion(motionAsset.getFile());
+ } catch (AssetNotFoundException e) {
+ e.printStackTrace();
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (MmdException e) {
+ e.printStackTrace();
+ }
+ }
+ return motion;
+ }
+
+ private MmdPmdModel getModel() {
+ if (null == model) {
+ try {
+ // final Asset modelAsset =
+ // AssetManager.getAsset("models/neru/Rin_Kagamine.pmd");
+ final Asset modelAsset = AssetManager.getAsset("models/raisen/raisen.pmd");
+ // final Asset modelAsset =
+ // AssetManager.getAsset("models/marisa/marisa.pmd");
+ // final Asset modelAsset =
+ // AssetManager.getAsset("models/alice/alice.pmd");
+ // final Asset modelAsset =
+ // AssetManager.getAsset("models/lat_miku/Normal.pmd");
+ // final Asset modelAsset =
+ // AssetManager.getAsset("models/rin/rin.pmd");
+ model = new MmdPmdModel(modelAsset.getFile());
+ } catch (AssetNotFoundException e) {
+ e.printStackTrace();
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (MmdException e) {
+ e.printStackTrace();
+ }
+ }
+ return model;
+ }
+
+ private float motionFrame = 0;
+ private float bodyYaw = 0;
+ private float cameraYaw = 0;
+ private float cameraDeltaYaw = 0;
+ private float leftWalkFrame;
+ private float walkFrameHalf1;
+ private float walkFrameHalf2;
+ private float rightWalkFrame;
+ private float rightWalkFrameHalf1;
+ private float rightWalkFrameHalf2;
+
+ private float clamp360(float value) {
+ if (value < 0) {
+ return value + (-(int) value / 360) * 360;
+ }
+ if (value > 0) {
+ return value - ((int) value / 360) * 360;
+ }
+ return value;
+ }
+
+ private MmdMotionPlayerGL2 getPlayerModel() throws MmdException {
+ if (null == gl2player) {
+ gl2player = new MmdMotionPlayerGL2();
+ gl2player.setPmd(getModel());
+ gl2player.setVmd(getMotion());
+ bodyYaw = cameraYaw = camera.getYaw();
+ }
+ cameraYaw = camera.getYaw() + (reverseModelLook ? -180 : 0);
+ final float yawDelta = clamp360(cameraYaw - bodyYaw);
+ if (yawDelta > 45) {
+ bodyYaw = cameraYaw - 45;
+ } else if (yawDelta < -45) {
+ bodyYaw = cameraYaw + 45;
+ } else {
+ bodyYaw += yawDelta * Game.instance.getFrameDelta();
+ bodyYaw = clamp360(bodyYaw);
+ }
+ cameraDeltaYaw = clamp360(cameraYaw - bodyYaw);
+ gl2player.lookMeEnable(true);
+ // gl2player.setLookVector(camera.getLook().x, camera.getLook().y,
+ // camera.getLook().z);
+ motionFrame += Game.instance.getFrameDelta();
+ if (motionFrame >= getMotion().getMaxFrame() * (100 / 3)) {
+ motionFrame = 0;
+ }
+
+ if (null != gl2player.m_centerBone) {
+ gl2player.m_centerBone.m_vec3Position.x = 0;
+ gl2player.m_centerBone.m_vec3Position.y = 0;
+ gl2player.m_centerBone.m_vec3Position.z = 0;
+ }
+
+ if (null != gl2player.m_pNeckBone) {
+ final MmdVector3 euler = new MmdVector3((float) Math.toRadians(-camera.getPitch()),
+ (float) Math.toRadians(cameraDeltaYaw), (float) Math.toRadians(camera.getRoll()));
+ gl2player.m_pNeckBone.m_vec4Rotate.QuaternionCreateEuler(euler);
+ // final MmdVector3 yAxis = new MmdVector3(0, 0, 1);
+ // gl2player.m_pNeckBone.m_vec4Rotate.QuaternionCreateAxis(yAxis,
+ // (float) Math.toRadians(camera.getYaw()));// .x
+ // =
+ // camera.getLook().x;
+ // gl2player.m_pNeckBone.m_vec4Rotate.y = camera.getLook().y;
+ // gl2player.m_pNeckBone.m_vec4Rotate.z = camera.getLook().z;
+ // gl2player.m_pNeckBone.m_vec4Rotate.w = 1;
+ // .QuaternionCreateEuler(euler);
+ // gl2player.manualUpdateNeckBone();
+ }
+ gl2player.m_leftEyeDestination.lookAt(new MmdVector3(camera.getNlook().x, 0, camera.getNlook().z));
+ final float maxFootOffset = 1f;
+ final MmdVector3 xAxis = new MmdVector3(1, 0, 0);
+ final MmdVector3 yAxis = new MmdVector3(0, 1, 0);
+
+ // gl2player.m_leftFootDestinationIK.m_vec3Position.y = maxFootOffset *
+ // walkFrame;
+ // gl2player.m_leftKnee.m_vec3Position.y = maxFootOffset * walkFrame;
+ gl2player.reset();
+ /*
+ * final float hipAngle = 15;
+ * final float hipLegYaw = 5;
+ * final float legPitch = 40;
+ * final float hipLegRoll = -5;
+ * final float lowerBodyYaw = -(float) Math.toRadians(-hipAngle *
+ * walkFrameHalf1 + hipAngle * walkFrameHalf2);
+ * final float leftLegYaw = -(float) Math.toRadians(hipLegYaw *
+ * walkFrameHalf1);
+ * final float rightLegYaw = -(float) Math.toRadians(-hipLegYaw *
+ * walkFrameHalf2);
+ * final float leftLegRoll = -(float) Math.toRadians(-hipLegRoll *
+ * walkFrameHalf1 + hipLegRoll * walkFrameHalf2);
+ * final float rightLegRoll = (float) Math.toRadians(hipLegRoll *
+ * walkFrameHalf1 - hipLegRoll * walkFrameHalf2);
+ * final float leftLegPitch = -(float) Math.toRadians(-legPitch *
+ * walkFrameHalf1 + legPitch * walkFrameHalf2);
+ * final float rightLegPitch = -(float) Math.toRadians(-legPitch *
+ * walkFrameHalf2 + legPitch * walkFrameHalf1);
+ * gl2player.m_lowerBody.m_vec4Rotate.QuaternionCreateAxis(yAxis,
+ * lowerBodyYaw);
+ * final MmdVector3 leftLegEuler = new MmdVector3(leftLegPitch,
+ * leftLegYaw, leftLegRoll);
+ * final MmdVector3 rightLegEuler = new MmdVector3(rightLegPitch,
+ * rightLegYaw, rightLegRoll);
+ * gl2player.m_leftLeg.m_vec4Rotate.QuaternionCreateEuler(leftLegEuler);
+ * gl2player.m_rightLeg.m_vec4Rotate.QuaternionCreateEuler(rightLegEuler)
+ * ;
+ * gl2player.m_leftKnee.m_vec4Rotate.QuaternionCreateAxis(xAxis,
+ * -(float) Math.toRadians(20 * walkFrameHalf2 + 30 * walkFrameHalf1));
+ * gl2player.m_rightKnee.m_vec4Rotate.QuaternionCreateAxis(xAxis,
+ * -(float) Math.toRadians(30 * walkFrameHalf2 + 20 * walkFrameHalf1));
+ * gl2player.m_leftAnkle.m_vec4Rotate.QuaternionCreateAxis(xAxis,
+ * -(float) Math.toRadians(15 * walkFrameHalf2 - 30 * walkFrameHalf1));
+ * gl2player.m_rightAnkle.m_vec4Rotate.QuaternionCreateAxis(xAxis,
+ * -(float) Math.toRadians(-30 * walkFrameHalf2 + 15 * walkFrameHalf1));
+ * gl2player.update();
+ * // gl2player.m_leftFootIK.m_vec3Position.z = 0;
+ * // gl2player.m_leftFootIK.m_vec4Rotate.x = 0;
+ * // gl2player.m_leftFootIK.m_vec4Rotate.y = 0;
+ * // gl2player.m_leftFootIK.m_vec4Rotate.z = 0;
+ * // gl2player.m_leftToe.m_vec3Position.x = 0;
+ * // gl2player.m_leftToe.m_vec3Position.y = 0;
+ * // gl2player.m_leftToe.m_vec3Position.z = 0;
+ * // gl2player.m_leftToe.m_vec4Rotate.x = 0;
+ * // gl2player.m_leftToe.m_vec4Rotate.y = 0;
+ * // gl2player.m_leftToe.m_vec4Rotate.z = 0;
+ * // if (motionTimer > 1) {
+ * // gl2player.m_leftKnee.m_vec3Position.z = maxFootOffset +
+ * maxFootOffset
+ * // * ((1 - (motionTimer - 1) * 2));
+ * // if (gl2player.m_leftKnee.m_vec3Position.z < 0) {
+ * // gl2player.m_leftKnee.m_vec3Position.z = 0;
+ * // }
+ * // }
+ * gl2player.m_rightFootIK.m_vec3Position.x = -maxFootOffset * (1 -
+ * motionTimer);
+ * // gl2player.updateMotion(motionFrame * 1000);
+ */
+ return gl2player;
+ }
+
+ private MmdVector3 createEuler(float pitch, float yaw, float roll) {
+ return new MmdVector3(pitch, yaw, roll);
+ }
+
+ private MmdVector3 createEuler(Bone b) {
+ return new MmdVector3((float) Math.toRadians(b.getCorrectedPitch()),
+ (float) Math.toRadians(b.getCorrectedYaw()), (float) Math.toRadians(b.getCorrectedRoll()));
+ }
+
+ private void calcWalkFrames() {
+ leftWalkFrame = (float) (motionTimer > 0.5 ? (motionTimer - 0.5) * 2 : 1 - motionTimer * 2);
+ if (motionTimer > 0.5f) {
+ // Half2
+ walkFrameHalf1 = 0;
+ walkFrameHalf2 = (motionTimer - 0.5f) * 2f;
+ walkFrameHalf2 = 1f - (float) Math.abs(walkFrameHalf2 * 2f - 1f);
+ } else {
+ // Half1
+ walkFrameHalf1 = motionTimer * 2f;
+ walkFrameHalf2 = 0;
+ walkFrameHalf1 = 1f - (float) Math.abs(walkFrameHalf1 * 2f - 1f);
+ }
+ rightWalkFrame = 1 - leftWalkFrame;
+ }
+
+ private void updateMotionTimer() {
+ motionTimer += Game.instance.getFrameDelta() * motionTimerSpeed;
+ if (motionTimer >= motionTimerFinish) {
+ motionTimer = 0;
+ }
+ }
+
+ private ModelAnimator animator = new ModelAnimator();
+
+ private MmdMotionPlayerGL2 getOrientedModel() {
+ try {
+ final MmdMotionPlayerGL2 player = getPlayerModel();
+ player.reset();
+ final Skeleton skel = animator.deltaOrientation;
+ final Leg leftLeg = skel.leftLeg;
+ final Leg rightLeg = skel.rightLeg;
+ // LEGS
+ player.m_leftLeg.m_vec4Rotate.QuaternionCreateEuler(createEuler(leftLeg.top));
+ player.m_rightLeg.m_vec4Rotate.QuaternionCreateEuler(createEuler(rightLeg.top));
+ player.m_leftKnee.m_vec4Rotate.QuaternionCreateEuler(createEuler(leftLeg.knee));
+ player.m_rightKnee.m_vec4Rotate.QuaternionCreateEuler(createEuler(rightLeg.knee));
+ player.m_leftAnkle.m_vec4Rotate.QuaternionCreateEuler(createEuler(leftLeg.foot));
+ player.m_rightAnkle.m_vec4Rotate.QuaternionCreateEuler(createEuler(rightLeg.foot));
+ player.m_rightFootIK.m_vec3Position.y = 0;
+ player.m_leftFootIK.m_vec3Position.y = 0;
+ // ARMS
+ final Arm leftArm = skel.leftArm;
+ final Arm rightArm = skel.rightArm;
+ player.m_leftArm.m_vec4Rotate.QuaternionCreateEuler(createEuler(leftArm.top));
+ player.m_rightArm.m_vec4Rotate.QuaternionCreateEuler(createEuler(rightArm.top));
+ player.m_leftElbow.m_vec4Rotate.QuaternionCreateEuler(createEuler(leftArm.elbow));
+ player.m_rightElbow.m_vec4Rotate.QuaternionCreateEuler(createEuler(rightArm.elbow));
+ player.m_leftWrist.m_vec4Rotate.QuaternionCreateEuler(createEuler(leftArm.wrist));
+ player.m_rightWrist.m_vec4Rotate.QuaternionCreateEuler(createEuler(rightArm.wrist));
+
+ player.m_lowerBody.m_vec4Rotate.QuaternionCreateEuler(createEuler(skel.waist));
+ player.m_upperBody.m_vec4Rotate.QuaternionCreateEuler(createEuler(skel.shoulders));
+ if (null != player.m_skirtFrontLeft) {
+ player.m_skirtFrontLeft.m_vec4Rotate.QuaternionCreateEuler(createEuler(skel.skirtFrontLeft));
+ player.m_skirtFrontRight.m_vec4Rotate.QuaternionCreateEuler(createEuler(skel.skirtFrontRight));
+ }
+ // player.m_upperBody.m_vec3Position.z = 1;
+ player.update();
+ return player;
+ } catch (MmdException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ private int bonesCount = 0;
+ private int selectedBone = 0;
+
+ private int bodyYawCorrection = 0;
+
+ public void rotateCW() {
+ bodyYawCorrection++;
+ if (bodyYawCorrection > 360) {
+ bodyYawCorrection -= 360;
+ }
+ }
+
+ public void rotateCCW() {
+ bodyYawCorrection--;
+ if (bodyYawCorrection < 0) {
+ bodyYawCorrection += 360;
+ }
+ }
+
+ public void selectNextBone() {
+ selectedBone++;
+ if (selectedBone > bonesCount) {
+ selectedBone = 0;
+ }
+ Game.client.getScene().selectedBone = animator.finalOrientation.getBone(selectedBone);
+ }
+
+ public void render() {
+ if (null == Game.client.getScene().selectedBone) {
+ bonesCount = Game.client.getScene().bonesCount = animator.deltaOrientation.getBoneCount();
+ int i = 0;
+ Game.client.getScene().selectedBone = animator.finalOrientation.getBone(selectedBone);
+ }
+ animator.setPause(Game.client.getScene().boneMode);
+ animator.setJumping(inJump ? true : false);
+ animator.setWalking(isWalking ? true : false);
+ animator.setDelta(Game.instance.getFrameDelta());
+ animator.tick();
+
+ /*
+ * if (inJump) {
+ * if (walkFrameHalf1 < 0.9f && walkFrameHalf2 < 0.9f) {
+ * updateMotionTimer();
+ * calcWalkFrames();
+ * }
+ * } else if (isWalking) {
+ * updateMotionTimer();
+ * calcWalkFrames();
+ * } else {
+ * motionTimer -= Game.instance.getDelta() * motionTimerSpeed;
+ * if (motionTimer <= 0) {
+ * motionTimer = 0;
+ * }
+ * leftWalkFrame += Game.instance.getDelta() * (0 - leftWalkFrame) * 5;
+ * rightWalkFrame += Game.instance.getDelta() * (0 - rightWalkFrame) *
+ * 5;
+ * walkFrameHalf1 += Game.instance.getDelta() * (0 - walkFrameHalf1) *
+ * 5;
+ * walkFrameHalf2 += Game.instance.getDelta() * (0 - walkFrameHalf2) *
+ * 5;
+ * }
+ */
+
+ try {
+ final MmdMotionPlayerGL2 player = getOrientedModel();
+ final GL2 gl = GLContext.getCurrentGL().getGL2();
+ gl.glPushMatrix();
+ gl.glPushAttrib(GL2.GL_ALL_ATTRIB_BITS);
+ final float scale = getHeight() / player.height;
+ gl.glTranslatef(getX(), getY(), getZ());// - 2.5f
+ gl.glScalef(scale, scale, scale);
+ // gl.glRotatef(getPitch(), 1, 0, 0);
+
+ gl.glRotatef(bodyYaw + bodyYawCorrection, 0, 1, 0);
+ // gl.glRotatef(getRoll(), 0, 0, 1);
+ player.render();
+ gl.glPopAttrib();
+ gl.glPopMatrix();
+ } catch (MmdException e) {
+ e.printStackTrace();
+ }
+ }
@Override
public void notifyLocationUpdate() {
@@ -21,14 +392,63 @@ public class Player extends LiveEntity {
public Player() {
}
-
- public void pickBlock(Block b){
+
+ public void pickBlock(Block b) {
+ BlockStack stack = new BlockStack(b.provider.getChunk(b.location.getChunkLocation()).getType(b.location,
+ b.provider), 1);
+ if (null != stack.type) {
+ // inventory.putBlockStack(stack);
+ stack.type.dropBlock(b.provider, b.location);
+ }
b.removeFromWorld();
+ try {
+ if (inAir()) {
+ System.out.println("in air while picking");
+ inJump = true;
+ onGround = false;
+ isOrientationChanged = true;
+ }
+ } catch (ChunkUnavailableException e) {
+ e.printStackTrace();
+ }
+ // Game.client.getScene().updateNearestBlock();
}
- public void onMouseClick() {
- if (null != Game.client.getScene().nearestBlock){
- pickBlock(Game.client.getScene().nearestBlock);
+ public void putBlock(Block b) {
+ BlockStack stack = inventory.getSelectedBlockStack();
+ if (stack.count > 0) {
+ b.setType(stack.type);
+ stack.count--;
+ if (stack.count == 0) {
+ stack.type = new EmptyBlockType();
+ }
+ b.setLocation(b.provider, b.location.x, b.location.y, b.location.z);
+ System.out.println("put block " + b.getType().getClass().getName());
+ b.insertToWorld();
+ // Game.client.getScene().updateNearestBlock();
+ }
+ }
+
+ public void onMouseClick(MouseEvent e) {
+ if (null != inventory) {
+ if (e.getButton() == 1) {
+ inventory.click(false);
+ }
+ if (e.getButton() == 3) {
+ inventory.click(true);
+ }
+ }
+ if (e.isConfined() && MouseJail.isActive()) {
+ if (e.getButton() == 1) {
+ if (null != Game.client.getScene().nearestBlock) {
+ pickBlock(Game.client.getScene().nearestBlock);
+ }
+ }
+ if (e.getButton() == 3) {
+ if (null != Game.client.getScene().nearestPutBlock) {
+ putBlock(Game.client.getScene().nearestPutBlock);
+ }
+ }
}
// Bullet b = new Bullet();
// b.velocity.set(Game.instance.camera.getLook());
diff --git a/src/ru/olamedia/player/RuntimeSettings.java b/src/ru/olamedia/player/RuntimeSettings.java
new file mode 100644
index 0000000..d5ce012
--- /dev/null
+++ b/src/ru/olamedia/player/RuntimeSettings.java
@@ -0,0 +1,5 @@
+package ru.olamedia.player;
+
+public class RuntimeSettings {
+ public int renderDistance = 128;
+}
diff --git a/src/ru/olamedia/texture/TextureManager.java b/src/ru/olamedia/texture/TextureManager.java
index c790cee..afe5da3 100644
--- a/src/ru/olamedia/texture/TextureManager.java
+++ b/src/ru/olamedia/texture/TextureManager.java
@@ -1,17 +1,31 @@
package ru.olamedia.texture;
+import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
+import javax.media.opengl.GLProfile;
+
import ru.olamedia.asset.AssetManager;
import ru.olamedia.asset.AssetNotFoundException;
+import ru.olamedia.asset.Sprite;
+import ru.olamedia.asset.SpriteRectangle;
import com.jogamp.opengl.util.texture.Texture;
import com.jogamp.opengl.util.texture.TextureIO;
+import com.jogamp.opengl.util.texture.awt.AWTTextureIO;
public class TextureManager {
private static HashMap<String, Texture> list = new HashMap<String, Texture>();
+ private static HashMap<String, Sprite> currentSpriteList = new HashMap<String, Sprite>();
+ private static HashMap<String, SpriteRectangle> offsets = new HashMap<String, SpriteRectangle>();
+ private static Sprite currentSprite = new Sprite(256, 256, 32, 32); // 64
+ // tiles
+
+ public static void writeSprite(String filename) {
+ currentSprite.write(filename);
+ }
public static Texture get(String filename) {
if (!list.containsKey(filename)) {
@@ -39,4 +53,54 @@ public class TextureManager {
}
return list.get(key);
}
+
+ public static Texture get(String key, InputStream stream, String format) {
+ if (!list.containsKey(key)) {
+ try {
+ list.put(key, TextureIO.newTexture(stream, true, format));
+ } catch (IOException e) {
+ list.put(key, null);
+ e.printStackTrace();
+ }
+ }
+ return list.get(key);
+ }
+
+ public static Texture makeTextureFromBufferedImage(BufferedImage b) {
+ return null;
+ }
+
+ public static Texture getSprite(String filename) {
+ if (!list.containsKey(filename)) {
+ try {
+ SpriteRectangle offset = currentSprite.addImage(filename);
+ offsets.put(filename, offset);
+ currentSpriteList.put(filename, currentSprite);
+ } catch (AssetNotFoundException e) {
+ e.printStackTrace();
+ }
+ return get(filename);
+ }
+ return list.get(filename);
+ }
+
+ public static SpriteRectangle getSpriteOffset(String filename) {
+ if (!offsets.containsKey(filename)) {
+ getSprite(filename);
+ if (!offsets.containsKey(filename)) {
+ return null;
+ }
+ }
+ return offsets.get(filename);
+ }
+
+ public static void finishSprite() {
+ GLProfile gp = GLProfile.getGL2ES2();
+ Texture texture = AWTTextureIO.newTexture(gp, currentSprite.getImage(), true);
+ currentSprite.dispose();
+ for (String key : currentSpriteList.keySet()) {
+ list.put(key, texture);
+ }
+ currentSpriteList.clear();
+ }
}