From f58bdfcb66353bb77213cab580bc49ef890417ad Mon Sep 17 00:00:00 2001 From: olamedia Date: Sun, 23 Dec 2012 11:30:36 +0600 Subject: 0.1.7 --- res/models/alice/2.spa | Bin 0 -> 307256 bytes res/models/alice/3.spa | Bin 0 -> 196664 bytes res/models/alice/4.sph | Bin 0 -> 12344 bytes res/models/alice/5.sph | Bin 0 -> 12344 bytes res/models/alice/6.spa | Bin 0 -> 307256 bytes res/models/alice/alice.pmd | Bin 0 -> 4618546 bytes ...\277\320\237C\320\240\342\224\202Ver111025.pmd" | Bin 0 -> 4630567 bytes res/models/alice/k_toon03.bmp | Bin 0 -> 12344 bytes res/models/alice/readme.txt | 40 ++ res/models/alice/tex_asi.tga | Bin 0 -> 3145772 bytes res/models/alice/tex_body.tga | Bin 0 -> 1048620 bytes res/models/alice/tex_buki.tga | Bin 0 -> 3145772 bytes res/models/alice/tex_eyes2.tga | Bin 0 -> 1048620 bytes res/models/alice/tex_eyesb.tga | Bin 0 -> 196652 bytes res/models/alice/tex_fuku.tga | Bin 0 -> 786476 bytes res/models/alice/tex_gun2a.tga | Bin 0 -> 786476 bytes res/models/alice/tex_gun2b.tga | Bin 0 -> 786476 bytes res/models/alice/tex_guna.tga | Bin 0 -> 786476 bytes res/models/alice/tex_gunb.tga | Bin 0 -> 786476 bytes res/models/alice/tex_kami1.tga | Bin 0 -> 786476 bytes res/models/alice/tex_kao.tga | Bin 0 -> 1048620 bytes res/models/alice/tex_kutu.tga | Bin 0 -> 786476 bytes res/models/alice/toon0.bmp | Bin 0 -> 3126 bytes res/models/alice/toon01.bmp | Bin 0 -> 3128 bytes res/models/alice/toon02.bmp | Bin 0 -> 3128 bytes res/models/alice/toon03.bmp | Bin 0 -> 3128 bytes res/models/alice/toon04.bmp | Bin 0 -> 3128 bytes res/models/alice/toon05.bmp | Bin 0 -> 3126 bytes res/models/alice/toon06.bmp | Bin 0 -> 3126 bytes res/models/alice/toon07.bmp | Bin 0 -> 3126 bytes res/models/alice/toon08.bmp | Bin 0 -> 3126 bytes res/models/alice/toon09.bmp | Bin 0 -> 3126 bytes res/models/alice/toon10.bmp | Bin 0 -> 3126 bytes ...0\236\321\210\320\222\342\225\224\320\237e.vpd" | 175 ++++++ res/models/lat_miku/BLAZER.bmp | Bin 0 -> 3145784 bytes res/models/lat_miku/BLAZER.psd | Bin 0 -> 3083868 bytes res/models/lat_miku/HP-1.bmp | Bin 0 -> 1080056 bytes res/models/lat_miku/LatMikuWhite.pmd | Bin 0 -> 1251966 bytes res/models/lat_miku/LatSailore2.pmd | Bin 0 -> 1985930 bytes res/models/lat_miku/Normal.pmd | Bin 0 -> 987408 bytes res/models/lat_miku/Normal2.pmd | Bin 0 -> 955488 bytes res/models/lat_miku/Sailore.pmd | Bin 0 -> 1987990 bytes res/models/lat_miku/Sailoro.pmd | Bin 0 -> 2059259 bytes res/models/lat_miku/Sailoroo.pmd | Bin 0 -> 2057199 bytes res/models/lat_miku/White.pmd | Bin 0 -> 1283886 bytes res/models/lat_miku/heltudofon.bmp | Bin 0 -> 786488 bytes res/models/lat_miku/hoho.png | Bin 0 -> 41139 bytes res/models/lat_miku/huk3sb.bmp | Bin 0 -> 3145784 bytes res/models/lat_miku/huku1.bmp | Bin 0 -> 3145784 bytes res/models/lat_miku/huku1w.bmp | Bin 0 -> 3145784 bytes res/models/lat_miku/huku3.bmp | Bin 0 -> 3145784 bytes res/models/lat_miku/huku3s.bmp | Bin 0 -> 3145784 bytes res/models/lat_miku/huku3w.bmp | Bin 0 -> 3145784 bytes res/models/lat_miku/huku_s.bmp | Bin 0 -> 3145784 bytes res/models/lat_miku/hukus2.bmp | Bin 0 -> 3145784 bytes res/models/lat_miku/kami.bmp | Bin 0 -> 3145784 bytes res/models/lat_miku/kami_ol.bmp | Bin 0 -> 3145784 bytes res/models/lat_miku/loafer.bmp | Bin 0 -> 786488 bytes res/models/lat_miku/m.sph | Bin 0 -> 196664 bytes res/models/lat_miku/mahura-.bmp | Bin 0 -> 786488 bytes res/models/lat_miku/me.bmp | Bin 0 -> 786488 bytes res/models/lat_miku/p.spa | Bin 0 -> 196664 bytes res/models/lat_miku/portapro1.png | Bin 0 -> 17313 bytes res/models/lat_miku/portapro2.bmp | Bin 0 -> 196664 bytes res/models/lat_miku/sp_g.spa | Bin 0 -> 196664 bytes res/models/lat_miku/sp_g.sph | Bin 0 -> 196664 bytes res/models/lat_miku/sp_h.spa | Bin 0 -> 196664 bytes res/models/lat_miku/sp_k.spa | Bin 0 -> 196664 bytes res/models/lat_miku/sp_s.spa | Bin 0 -> 196664 bytes res/models/lat_miku/toon-1.bmp | Bin 0 -> 3128 bytes res/models/lat_miku/toon0.bmp | Bin 0 -> 3126 bytes res/models/lat_miku/toon01.bmp | Bin 0 -> 3128 bytes res/models/lat_miku/toon02.bmp | Bin 0 -> 3128 bytes res/models/lat_miku/toon03.bmp | Bin 0 -> 3128 bytes res/models/lat_miku/toon04.bmp | Bin 0 -> 3128 bytes res/models/lat_miku/toon05.bmp | Bin 0 -> 3126 bytes res/models/lat_miku/toon06.bmp | Bin 0 -> 3126 bytes res/models/lat_miku/toon07.bmp | Bin 0 -> 3126 bytes res/models/lat_miku/toon08.bmp | Bin 0 -> 3126 bytes res/models/lat_miku/toon09.bmp | Bin 0 -> 3126 bytes res/models/lat_miku/toon10.bmp | Bin 0 -> 3126 bytes res/models/lat_miku/toon_g.bmp | Bin 0 -> 3128 bytes res/models/lat_miku/toon_hada.bmp | Bin 0 -> 3128 bytes res/models/lat_miku/toon_huku.bmp | Bin 0 -> 3128 bytes res/models/lat_miku/toon_kami.bmp | Bin 0 -> 3128 bytes res/models/lat_miku/toon_mahu.bmp | Bin 0 -> 3128 bytes res/models/lat_miku/toon_s.bmp | Bin 0 -> 3128 bytes res/models/lat_miku/uwabaki.bmp | Bin 0 -> 786488 bytes ...20\260\320\222\342\225\237\320\222\321\216.txt" | 102 +++ ...37\321\203\320\247\320\252\320\222\320\273.psd" | Bin 0 -> 3616844 bytes ...\321\216\320\244\320\277\320\221Qtoon_kami.bmp" | Bin 0 -> 3128 bytes res/models/marisa/marisa.pmd | Bin 0 -> 2247483 bytes res/models/marisa/t000.bmp | Bin 0 -> 4194360 bytes res/models/marisa/t001.bmp | Bin 0 -> 16054 bytes res/models/marisa/t001.sph | Bin 0 -> 58 bytes res/models/marisa/t002.bmp | Bin 0 -> 262198 bytes res/models/marisa/t003.bmp | Bin 0 -> 16054 bytes res/models/marisa/t003.sph | Bin 0 -> 58 bytes res/models/marisa/t004.bmp | Bin 0 -> 262198 bytes res/models/marisa/t005.bmp | Bin 0 -> 4150 bytes res/models/marisa/t006.bmp | Bin 0 -> 4150 bytes res/models/marisa/t007.bmp | Bin 0 -> 262198 bytes res/models/marisa/t008.bmp | Bin 0 -> 16438 bytes res/models/marisa/t009.bmp | Bin 0 -> 16054 bytes res/models/marisa/t009.sph | Bin 0 -> 58 bytes res/models/marisa/t010.bmp | Bin 0 -> 262198 bytes res/models/marisa/t011.bmp | Bin 0 -> 262198 bytes res/models/marisa/t012.bmp | Bin 0 -> 262198 bytes res/models/marisa/t013.bmp | Bin 0 -> 16438 bytes res/models/marisa/t014.bmp | Bin 0 -> 16054 bytes res/models/marisa/t014.sph | Bin 0 -> 58 bytes res/models/marisa/t015.bmp | Bin 0 -> 16438 bytes res/models/marisa/t016.bmp | Bin 0 -> 16438 bytes res/models/marisa/t017.bmp | Bin 0 -> 262198 bytes res/models/marisa/t018.bmp | Bin 0 -> 65590 bytes res/models/marisa/t019.bmp | Bin 0 -> 262198 bytes res/models/marisa/t020.bmp | Bin 0 -> 262198 bytes res/models/marisa/t021.bmp | Bin 0 -> 262198 bytes res/models/marisa/t022.bmp | Bin 0 -> 262198 bytes res/models/motion.vmd | Bin 0 -> 1080077 bytes res/models/neru/Dammy_Bone.pmd | Bin 0 -> 3496 bytes res/models/neru/Haku_Yowane.pmd | Bin 0 -> 454079 bytes res/models/neru/KAITO.pmd | Bin 0 -> 425126 bytes res/models/neru/Len_Kagamine.pmd | Bin 0 -> 394951 bytes res/models/neru/Meiko_Sakine.pmd | Bin 0 -> 926118 bytes res/models/neru/Miku_Hatsune.pmd | Bin 0 -> 474665 bytes res/models/neru/Miku_Hatsune_Ver2.pmd | Bin 0 -> 712126 bytes res/models/neru/Miku_Hatsune_metal.pmd | Bin 0 -> 712126 bytes res/models/neru/Neru_Akita.pmd | Bin 0 -> 503376 bytes res/models/neru/Rin_Kagamine.pmd | Bin 0 -> 471938 bytes res/models/neru/Rin_Kagamine_act2.pmd | Bin 0 -> 927621 bytes res/models/neru/eye2.bmp | Bin 0 -> 3128 bytes res/models/neru/eye3.bmp | Bin 0 -> 3128 bytes res/models/neru/eye3Ne.bmp | Bin 0 -> 3126 bytes res/models/neru/eye4.bmp | Bin 0 -> 3128 bytes res/models/neru/eyeKT.bmp | Bin 0 -> 3128 bytes res/models/neru/eyeM2.bmp | Bin 0 -> 33976 bytes res/models/neru/eyeR2.bmp | Bin 0 -> 33976 bytes res/models/neru/metal.sph | Bin 0 -> 196664 bytes res/models/neru/mikuhair.sph | Bin 0 -> 196664 bytes res/models/neru/sakine1.bmp | Bin 0 -> 196664 bytes res/models/neru/toon0.bmp | Bin 0 -> 3126 bytes res/models/neru/toon01.bmp | Bin 0 -> 3128 bytes res/models/neru/toon02.bmp | Bin 0 -> 3128 bytes res/models/neru/toon03.bmp | Bin 0 -> 3128 bytes res/models/neru/toon04.bmp | Bin 0 -> 3128 bytes res/models/neru/toon05.bmp | Bin 0 -> 3126 bytes res/models/neru/toon06.bmp | Bin 0 -> 3126 bytes res/models/neru/toon07.bmp | Bin 0 -> 3126 bytes res/models/neru/toon08.bmp | Bin 0 -> 3126 bytes res/models/neru/toon09.bmp | Bin 0 -> 3126 bytes res/models/neru/toon10.bmp | Bin 0 -> 3126 bytes res/models/raisen/motion.vmd | Bin 0 -> 1080077 bytes res/models/raisen/raisen.pmd | Bin 0 -> 2106793 bytes res/models/raisen/t000.bmp | Bin 0 -> 262198 bytes res/models/raisen/t001.bmp | Bin 0 -> 16054 bytes res/models/raisen/t001.sph | Bin 0 -> 58 bytes res/models/raisen/t002.bmp | Bin 0 -> 262198 bytes res/models/raisen/t003.bmp | Bin 0 -> 262198 bytes res/models/raisen/t004.bmp | Bin 0 -> 4150 bytes res/models/raisen/t005.bmp | Bin 0 -> 1048630 bytes res/models/raisen/t006.bmp | Bin 0 -> 16438 bytes res/models/raisen/t007.bmp | Bin 0 -> 1048630 bytes res/models/raisen/t008.bmp | Bin 0 -> 16054 bytes res/models/raisen/t008.sph | Bin 0 -> 58 bytes res/models/raisen/t009.bmp | Bin 0 -> 262198 bytes res/models/raisen/t010.bmp | Bin 0 -> 262198 bytes res/models/raisen/t011.bmp | Bin 0 -> 16054 bytes res/models/raisen/t011.sph | Bin 0 -> 58 bytes res/models/raisen/t012.bmp | Bin 0 -> 65590 bytes res/models/raisen/t013.bmp | Bin 0 -> 4150 bytes res/models/raisen/t014.bmp | Bin 0 -> 65590 bytes res/models/raisen/t015.bmp | Bin 0 -> 65590 bytes res/models/raisen/t016.bmp | Bin 0 -> 65590 bytes res/models/raisen/t017.bmp | Bin 0 -> 262198 bytes res/models/raisen/t018.bmp | Bin 0 -> 262198 bytes res/models/raisen/t019.bmp | Bin 0 -> 16438 bytes res/models/raisen/t020.bmp | Bin 0 -> 262198 bytes res/models/raisen/t021.bmp | Bin 0 -> 65590 bytes res/models/raisen/t022.bmp | Bin 0 -> 16438 bytes res/models/raisen/t023.bmp | Bin 0 -> 262198 bytes res/models/rin/motion.vmd | Bin 0 -> 1080077 bytes res/models/rin/rin.pmd | Bin 0 -> 987560 bytes res/models/rin/tex_body2.tga | Bin 0 -> 614444 bytes res/models/rin/tex_eyes2.tga | Bin 0 -> 1638444 bytes res/models/rin/tex_eyes2base.tga | Bin 0 -> 307244 bytes res/models/rin/tex_fuku0.tga | Bin 0 -> 307244 bytes res/models/rin/tex_kami0.tga | Bin 0 -> 307244 bytes res/models/rin/tex_kami1.tga | Bin 0 -> 307244 bytes res/models/rin/tex_kami2.tga | Bin 0 -> 307244 bytes res/models/rin/tex_kao.tga | Bin 0 -> 1228844 bytes res/models/rin/tex_nafuda.tga | Bin 0 -> 307244 bytes res/models/rin/tex_pants.tga | Bin 0 -> 307244 bytes res/models/rin/tex_skirt.tga | Bin 0 -> 614444 bytes res/models/rin/tex_taitu.tga | Bin 0 -> 307244 bytes res/models/rin/tex_uwabaki2.tga | Bin 0 -> 307244 bytes res/models/rin/toon0.bmp | Bin 0 -> 3126 bytes res/models/rin/toon01.bmp | Bin 0 -> 3128 bytes res/models/rin/toon02.bmp | Bin 0 -> 3128 bytes res/models/rin/toon03.bmp | Bin 0 -> 3128 bytes res/models/rin/toon04.bmp | Bin 0 -> 3128 bytes res/models/rin/toon05.bmp | Bin 0 -> 3126 bytes res/models/rin/toon06.bmp | Bin 0 -> 3126 bytes res/models/rin/toon07.bmp | Bin 0 -> 3126 bytes res/models/rin/toon08.bmp | Bin 0 -> 3126 bytes res/models/rin/toon09.bmp | Bin 0 -> 3126 bytes res/models/rin/toon10.bmp | Bin 0 -> 3126 bytes res/models/test.vmd | Bin 0 -> 407782 bytes res/models/yuki/tex_yukibody.bmp | Bin 0 -> 786488 bytes res/models/yuki/tex_yukihead.bmp | Bin 0 -> 786488 bytes res/models/yuki/tex_yukireg.bmp | Bin 0 -> 786488 bytes res/models/yuki/yuki.pmd | Bin 0 -> 191355 bytes res/texture/gravel2.png | Bin 0 -> 351379 bytes res/texture/ice.png | Bin 0 -> 3467 bytes res/texture/snow.png | Bin 0 -> 3015 bytes res/texture/stone/gabbro.png | Bin 0 -> 854 bytes res/texture/stone/granite.png | Bin 0 -> 702 bytes res/texture/stone/sedimentary/breccia.png | Bin 0 -> 681 bytes res/texture/stone/sedimentary/breccia32.png | Bin 0 -> 1338 bytes res/texture/stone/sedimentary/chert.png | Bin 0 -> 356 bytes res/texture/stone/sedimentary/chert32.png | Bin 0 -> 667 bytes res/texture/stone/sedimentary/coal.png | Bin 0 -> 546 bytes res/texture/stone/sedimentary/coal32.png | Bin 0 -> 1191 bytes res/texture/stone/sedimentary/conglomerate.png | Bin 0 -> 773 bytes res/texture/stone/sedimentary/conglomerate32.png | Bin 0 -> 1858 bytes res/texture/stone/sedimentary/limestone.png | Bin 0 -> 555 bytes res/texture/stone/sedimentary/limestone32.png | Bin 0 -> 1191 bytes res/texture/stone/sedimentary/sandstone.png | Bin 0 -> 650 bytes res/texture/stone/sedimentary/sandstone32.png | Bin 0 -> 1554 bytes res/texture/stone/sedimentary/shale.png | Bin 0 -> 440 bytes res/texture/stone/sedimentary/shale32.png | Bin 0 -> 771 bytes res/texture/stone/sedimentary/siltstone.png | Bin 0 -> 469 bytes res/texture/stone/sedimentary/siltstone32.png | Bin 0 -> 830 bytes res/texture/terrain-wheatgrass-lightgreen-med.png | Bin 0 -> 3024 bytes res/texture/water.png | Bin 0 -> 3376 bytes res/texture/wheat.png | Bin 0 -> 3383 bytes src/jp/nyatla/nymmd/MmdException.java | 70 +++ src/jp/nyatla/nymmd/MmdMotionPlayer.java | 434 +++++++++++++ src/jp/nyatla/nymmd/MmdMotionPlayerGL2.java | 434 +++++++++++++ src/jp/nyatla/nymmd/MmdPmdModel.java | 74 +++ src/jp/nyatla/nymmd/MmdPmdModel_BasicClass.java | 317 ++++++++++ src/jp/nyatla/nymmd/MmdVmdMotion.java | 55 ++ src/jp/nyatla/nymmd/MmdVmdMotion_BasicClass.java | 290 +++++++++ src/jp/nyatla/nymmd/core/PmdBone.java | 224 +++++++ src/jp/nyatla/nymmd/core/PmdFace.java | 108 ++++ src/jp/nyatla/nymmd/core/PmdIK.java | 194 ++++++ src/jp/nyatla/nymmd/struct/DataReader.java | 120 ++++ src/jp/nyatla/nymmd/struct/StructReader.java | 82 +++ src/jp/nyatla/nymmd/struct/StructType.java | 48 ++ src/jp/nyatla/nymmd/struct/pmd/PMD_Bone.java | 66 ++ src/jp/nyatla/nymmd/struct/pmd/PMD_FACE.java | 74 +++ src/jp/nyatla/nymmd/struct/pmd/PMD_FACE_VTX.java | 75 +++ src/jp/nyatla/nymmd/struct/pmd/PMD_Header.java | 69 ++ src/jp/nyatla/nymmd/struct/pmd/PMD_IK.java | 83 +++ src/jp/nyatla/nymmd/struct/pmd/PMD_Material.java | 82 +++ src/jp/nyatla/nymmd/struct/pmd/PMD_Vertex.java | 78 +++ src/jp/nyatla/nymmd/struct/vmd/VMD_Face.java | 60 ++ src/jp/nyatla/nymmd/struct/vmd/VMD_Header.java | 63 ++ src/jp/nyatla/nymmd/struct/vmd/VMD_Motion.java | 94 +++ src/jp/nyatla/nymmd/types/BoneKeyFrame.java | 62 ++ src/jp/nyatla/nymmd/types/FaceData.java | 45 ++ src/jp/nyatla/nymmd/types/FaceKeyFrame.java | 53 ++ src/jp/nyatla/nymmd/types/MmdColor3.java | 53 ++ src/jp/nyatla/nymmd/types/MmdColor4.java | 59 ++ src/jp/nyatla/nymmd/types/MmdMatrix.java | 377 +++++++++++ src/jp/nyatla/nymmd/types/MmdTexUV.java | 59 ++ src/jp/nyatla/nymmd/types/MmdVector3.java | 209 +++++++ src/jp/nyatla/nymmd/types/MmdVector4.java | 137 ++++ src/jp/nyatla/nymmd/types/MotionData.java | 125 ++++ src/jp/nyatla/nymmd/types/PmdMaterial.java | 51 ++ src/jp/nyatla/nymmd/types/PmdSkinInfo.java | 47 ++ src/ru/olamedia/asset/Shader.java | 40 ++ src/ru/olamedia/asset/Sprite.java | 115 ++++ src/ru/olamedia/asset/SpriteOffset.java | 10 + src/ru/olamedia/asset/SpriteRectangle.java | 11 + src/ru/olamedia/asset/shader/block.fp | 28 + src/ru/olamedia/asset/shader/block.vp | 25 + src/ru/olamedia/camera/Cameraman.java | 4 + src/ru/olamedia/camera/MatrixCamera.java | 386 +++++++++--- src/ru/olamedia/data/BitCube.java | 13 + src/ru/olamedia/data/package-info.java | 8 + src/ru/olamedia/game/GameFrame.java | 40 +- src/ru/olamedia/game/GameLogicThread.java | 76 +++ src/ru/olamedia/game/GameManager.java | 143 ++++- src/ru/olamedia/game/GameTime.java | 71 +-- src/ru/olamedia/game/Launcher.java | 4 +- src/ru/olamedia/geom/ChunkMesh.java | 83 +++ src/ru/olamedia/geom/ChunkMeshNode.java | 97 +++ src/ru/olamedia/geom/ChunkMeshOctree.java | 95 +++ src/ru/olamedia/geom/DisplayList.java | 1 - src/ru/olamedia/geom/Frustum.java | 34 + src/ru/olamedia/geom/Frustum2.java | 282 +++++++++ src/ru/olamedia/geom/ImmModeMesh.java | 465 ++++++++++++++ src/ru/olamedia/geom/IndexedMeshBulder.java | 207 ++++++ src/ru/olamedia/geom/Mesh.java | 76 ++- src/ru/olamedia/geom/MultiMesh.java | 34 + src/ru/olamedia/geom/SimpleQuadMesh.java | 145 +++-- src/ru/olamedia/geom/VoxelRaypicker.java | 37 ++ src/ru/olamedia/input/Keyboard.java | 77 ++- src/ru/olamedia/input/MouseJail.java | 44 +- src/ru/olamedia/input/MouseListener.java | 4 +- src/ru/olamedia/liveEntity/LiveEntity.java | 202 ++++-- src/ru/olamedia/math/Frustum.java | 108 ++-- src/ru/olamedia/math/Vector.java | 5 + src/ru/olamedia/math/VectorUtil.java | 29 + src/ru/olamedia/olacraft/OlaCraft.java | 2 +- src/ru/olamedia/olacraft/game/Game.java | 14 +- src/ru/olamedia/olacraft/inventory/Inventory.java | 416 +++++++++++-- src/ru/olamedia/olacraft/modelAnimator/Arm.java | 27 + src/ru/olamedia/olacraft/modelAnimator/Bone.java | 215 +++++++ .../olamedia/olacraft/modelAnimator/BoneSet.java | 163 +++++ .../olacraft/modelAnimator/ISkeletonNode.java | 26 + src/ru/olamedia/olacraft/modelAnimator/Leg.java | 27 + .../olacraft/modelAnimator/ModelAnimator.java | 324 ++++++++++ .../olacraft/modelAnimator/Randomizer.java | 92 +++ .../olamedia/olacraft/modelAnimator/Skeleton.java | 47 ++ .../olacraft/modelAnimator/package-info.java | 8 + src/ru/olamedia/olacraft/network/GameClient.java | 8 +- src/ru/olamedia/olacraft/network/GameServer.java | 14 + src/ru/olamedia/olacraft/network/Network.java | 6 + .../olacraft/network/packet/SectorDataPacket.java | 14 + .../olacraft/network/provider/CacheProvider.java | 29 + .../olacraft/network/provider/IProvider.java | 11 + .../olacraft/network/provider/LocalProvider.java | 21 + .../olacraft/network/provider/RemoteProvider.java | 19 + .../olacraft/network/provider/package-info.java | 8 + .../olacraft/render/jogl/ChunkRangeRenderer.java | 254 ++++++++ .../olacraft/render/jogl/DefaultRenderer.java | 29 +- .../olamedia/olacraft/render/jogl/IRenderer.java | 1 + .../olacraft/render/jogl/InventoryRenderer.java | 4 +- .../olacraft/render/jogl/joglViewport.java | 38 +- src/ru/olamedia/olacraft/scene/GameScene.java | 691 ++++++++++++++------- src/ru/olamedia/olacraft/world/biome/Biome.java | 10 + .../olacraft/world/biome/package-info.java | 8 + src/ru/olamedia/olacraft/world/block/Block.java | 372 ++++++----- .../olacraft/world/block/BlockRegistry.java | 31 +- .../world/blockRenderer/AbstractBlockRenderer.java | 64 ++ .../olacraft/world/blockRenderer/BoxRenderer.java | 282 +++++++++ .../blockRenderer/ChunkMeshGarbageCollector.java | 82 +++ .../world/blockRenderer/ChunkRenderer.java | 356 +++++++++++ .../world/blockRenderer/CrossQuadsRenderer.java | 115 ++++ .../world/blockRenderer/IBlockRenderer.java | 15 + .../world/blockRenderer/RenderLocation.java | 35 ++ .../olacraft/world/blockRenderer/package-info.java | 8 + .../olacraft/world/blockStack/BlockStack.java | 56 +- .../world/blockTypes/AbstractBlockType.java | 110 +++- .../olacraft/world/blockTypes/BlockType.java | 62 ++ .../olacraft/world/blockTypes/DirtBlockType.java | 6 +- .../olacraft/world/blockTypes/EmptyBlockType.java | 6 +- .../olacraft/world/blockTypes/GrassBlockType.java | 4 + .../olacraft/world/blockTypes/GravelBlockType.java | 4 + .../olacraft/world/blockTypes/IceBlockType.java | 32 + .../olacraft/world/blockTypes/SnowBlockType.java | 27 + .../world/blockTypes/TallGrassBlockType.java | 58 ++ .../olacraft/world/blockTypes/WaterBlockType.java | 42 ++ .../olacraft/world/blockTypes/WheatBlockType.java | 58 ++ .../blockTypes/stone/BrecciaStoneBlockType.java | 25 + .../blockTypes/stone/ChertStoneBlockType.java | 25 + .../world/blockTypes/stone/CoalStoneBlockType.java | 25 + .../stone/ConglomerateStoneBlockType.java | 25 + .../blockTypes/stone/LimestoneStoneBlockType.java | 25 + .../blockTypes/stone/SandstoneStoneBlockType.java | 25 + .../blockTypes/stone/ShaleStoneBlockType.java | 25 + .../blockTypes/stone/SiltstoneStoneBlockType.java | 25 + .../world/blockTypes/stone/package-info.java | 8 + .../olacraft/world/calc/LightCalculator.java | 118 ++++ src/ru/olamedia/olacraft/world/calc/LightData.java | 28 + .../olacraft/world/calc/VisibilityCalculator.java | 99 +++ .../olacraft/world/calc/VisibilityData.java | 30 + .../olamedia/olacraft/world/calc/package-info.java | 8 + .../olamedia/olacraft/world/chunk/BlockSlice.java | 22 +- src/ru/olamedia/olacraft/world/chunk/Chunk.java | 244 +++----- .../olacraft/world/chunk/ChunkMeshBulder.java | 11 +- .../olamedia/olacraft/world/chunk/ChunkSlice.java | 19 +- .../world/chunk/ChunkUnavailableException.java | 2 +- src/ru/olamedia/olacraft/world/data/ChunkData.java | 213 +++++-- .../olacraft/world/data/ChunkDataManager.java | 22 + .../olacraft/world/data/ChunkDataNeighbors.java | 162 +++++ .../olacraft/world/data/ChunkDataPointer.java | 82 +++ .../olacraft/world/data/ChunkDataWrapper.java | 40 ++ .../olamedia/olacraft/world/data/RegionData.java | 24 +- .../olamedia/olacraft/world/data/SectorData.java | 46 +- .../dataProvider/AbstractChunkDataProvider.java | 12 +- .../dataProvider/CachedChunkDataProvider.java | 93 ++- .../world/dataProvider/LocalChunkDataProvider.java | 76 +-- .../dataProvider/RemoteChunkDataProvider.java | 17 +- .../olacraft/world/drop/DroppedEntity.java | 17 + .../olamedia/olacraft/world/drop/package-info.java | 8 + .../olamedia/olacraft/world/fluid/FluidLevel.java | 9 + .../olamedia/olacraft/world/fluid/FluidLine.java | 56 ++ .../olamedia/olacraft/world/fluid/FluidSource.java | 99 +++ .../olacraft/world/fluid/package-info.java | 8 + .../world/generator/HeightMapGenerator.java | 9 +- .../world/generator/HumiditySelectLayer.java | 31 + .../world/generator/IslandSelectLayer.java | 31 + .../world/generator/MountainSelectLayer.java | 38 ++ .../olacraft/world/generator/OceanSelectLayer.java | 31 + .../olacraft/world/generator/RegionGenerator.java | 318 ++++++++-- .../olacraft/world/generator/RiverSelectLayer.java | 56 ++ .../world/generator/TemperatureSelectLayer.java | 31 + .../olacraft/world/location/BlockLocation.java | 88 ++- .../olacraft/world/location/ChunkLocation.java | 21 +- .../olacraft/world/location/IntLocation.java | 200 ++++++ .../olacraft/world/location/Location3f.java | 46 ++ .../olacraft/world/location/Location3i.java | 71 +++ .../olacraft/world/location/MetaLocation3i.java | 7 + .../olacraft/world/location/RegionLocation.java | 36 ++ .../olacraft/world/provider/IWorldProvider.java | 11 + .../olacraft/world/provider/LocalWorld.java | 24 + .../olacraft/world/provider/RemoteWorld.java | 32 + .../olacraft/world/provider/WorldProvider.java | 144 ++++- src/ru/olamedia/player/Player.java | 436 ++++++++++++- src/ru/olamedia/player/RuntimeSettings.java | 5 + src/ru/olamedia/texture/TextureManager.java | 64 ++ 414 files changed, 14362 insertions(+), 1279 deletions(-) create mode 100644 res/models/alice/2.spa create mode 100644 res/models/alice/3.spa create mode 100644 res/models/alice/4.sph create mode 100644 res/models/alice/5.sph create mode 100644 res/models/alice/6.spa create mode 100644 res/models/alice/alice.pmd create mode 100644 "res/models/alice/alice_\320\244\320\277\320\237C\320\240\342\224\202Ver111025.pmd" create mode 100644 res/models/alice/k_toon03.bmp create mode 100644 res/models/alice/readme.txt create mode 100644 res/models/alice/tex_asi.tga create mode 100644 res/models/alice/tex_body.tga create mode 100644 res/models/alice/tex_buki.tga create mode 100644 res/models/alice/tex_eyes2.tga create mode 100644 res/models/alice/tex_eyesb.tga create mode 100644 res/models/alice/tex_fuku.tga create mode 100644 res/models/alice/tex_gun2a.tga create mode 100644 res/models/alice/tex_gun2b.tga create mode 100644 res/models/alice/tex_guna.tga create mode 100644 res/models/alice/tex_gunb.tga create mode 100644 res/models/alice/tex_kami1.tga create mode 100644 res/models/alice/tex_kao.tga create mode 100644 res/models/alice/tex_kutu.tga create mode 100644 res/models/alice/toon0.bmp create mode 100644 res/models/alice/toon01.bmp create mode 100644 res/models/alice/toon02.bmp create mode 100644 res/models/alice/toon03.bmp create mode 100644 res/models/alice/toon04.bmp create mode 100644 res/models/alice/toon05.bmp create mode 100644 res/models/alice/toon06.bmp create mode 100644 res/models/alice/toon07.bmp create mode 100644 res/models/alice/toon08.bmp create mode 100644 res/models/alice/toon09.bmp create mode 100644 res/models/alice/toon10.bmp create mode 100644 "res/models/alice/\320\247\342\225\235\320\236\321\210\320\222\342\225\224\320\237e.vpd" create mode 100644 res/models/lat_miku/BLAZER.bmp create mode 100644 res/models/lat_miku/BLAZER.psd create mode 100644 res/models/lat_miku/HP-1.bmp create mode 100644 res/models/lat_miku/LatMikuWhite.pmd create mode 100644 res/models/lat_miku/LatSailore2.pmd create mode 100644 res/models/lat_miku/Normal.pmd create mode 100644 res/models/lat_miku/Normal2.pmd create mode 100644 res/models/lat_miku/Sailore.pmd create mode 100644 res/models/lat_miku/Sailoro.pmd create mode 100644 res/models/lat_miku/Sailoroo.pmd create mode 100644 res/models/lat_miku/White.pmd create mode 100644 res/models/lat_miku/heltudofon.bmp create mode 100644 res/models/lat_miku/hoho.png create mode 100644 res/models/lat_miku/huk3sb.bmp create mode 100644 res/models/lat_miku/huku1.bmp create mode 100644 res/models/lat_miku/huku1w.bmp create mode 100644 res/models/lat_miku/huku3.bmp create mode 100644 res/models/lat_miku/huku3s.bmp create mode 100644 res/models/lat_miku/huku3w.bmp create mode 100644 res/models/lat_miku/huku_s.bmp create mode 100644 res/models/lat_miku/hukus2.bmp create mode 100644 res/models/lat_miku/kami.bmp create mode 100644 res/models/lat_miku/kami_ol.bmp create mode 100644 res/models/lat_miku/loafer.bmp create mode 100644 res/models/lat_miku/m.sph create mode 100644 res/models/lat_miku/mahura-.bmp create mode 100644 res/models/lat_miku/me.bmp create mode 100644 res/models/lat_miku/p.spa create mode 100644 res/models/lat_miku/portapro1.png create mode 100644 res/models/lat_miku/portapro2.bmp create mode 100644 res/models/lat_miku/sp_g.spa create mode 100644 res/models/lat_miku/sp_g.sph create mode 100644 res/models/lat_miku/sp_h.spa create mode 100644 res/models/lat_miku/sp_k.spa create mode 100644 res/models/lat_miku/sp_s.spa create mode 100644 res/models/lat_miku/toon-1.bmp create mode 100644 res/models/lat_miku/toon0.bmp create mode 100644 res/models/lat_miku/toon01.bmp create mode 100644 res/models/lat_miku/toon02.bmp create mode 100644 res/models/lat_miku/toon03.bmp create mode 100644 res/models/lat_miku/toon04.bmp create mode 100644 res/models/lat_miku/toon05.bmp create mode 100644 res/models/lat_miku/toon06.bmp create mode 100644 res/models/lat_miku/toon07.bmp create mode 100644 res/models/lat_miku/toon08.bmp create mode 100644 res/models/lat_miku/toon09.bmp create mode 100644 res/models/lat_miku/toon10.bmp create mode 100644 res/models/lat_miku/toon_g.bmp create mode 100644 res/models/lat_miku/toon_hada.bmp create mode 100644 res/models/lat_miku/toon_huku.bmp create mode 100644 res/models/lat_miku/toon_kami.bmp create mode 100644 res/models/lat_miku/toon_mahu.bmp create mode 100644 res/models/lat_miku/toon_s.bmp create mode 100644 res/models/lat_miku/uwabaki.bmp create mode 100644 "res/models/lat_miku/\320\222\321\212\320\222\320\260\320\222\342\225\237\320\222\321\216.txt" create mode 100644 "res/models/lat_miku/\320\237\321\203\320\247\320\252\320\222\320\273.psd" create mode 100644 "res/models/lat_miku/\320\240-\320\222\342\226\214\320\244\320\246\320\222\321\216\320\244\320\277\320\221Qtoon_kami.bmp" create mode 100644 res/models/marisa/marisa.pmd create mode 100644 res/models/marisa/t000.bmp create mode 100644 res/models/marisa/t001.bmp create mode 100644 res/models/marisa/t001.sph create mode 100644 res/models/marisa/t002.bmp create mode 100644 res/models/marisa/t003.bmp create mode 100644 res/models/marisa/t003.sph create mode 100644 res/models/marisa/t004.bmp create mode 100644 res/models/marisa/t005.bmp create mode 100644 res/models/marisa/t006.bmp create mode 100644 res/models/marisa/t007.bmp create mode 100644 res/models/marisa/t008.bmp create mode 100644 res/models/marisa/t009.bmp create mode 100644 res/models/marisa/t009.sph create mode 100644 res/models/marisa/t010.bmp create mode 100644 res/models/marisa/t011.bmp create mode 100644 res/models/marisa/t012.bmp create mode 100644 res/models/marisa/t013.bmp create mode 100644 res/models/marisa/t014.bmp create mode 100644 res/models/marisa/t014.sph create mode 100644 res/models/marisa/t015.bmp create mode 100644 res/models/marisa/t016.bmp create mode 100644 res/models/marisa/t017.bmp create mode 100644 res/models/marisa/t018.bmp create mode 100644 res/models/marisa/t019.bmp create mode 100644 res/models/marisa/t020.bmp create mode 100644 res/models/marisa/t021.bmp create mode 100644 res/models/marisa/t022.bmp create mode 100644 res/models/motion.vmd create mode 100644 res/models/neru/Dammy_Bone.pmd create mode 100644 res/models/neru/Haku_Yowane.pmd create mode 100644 res/models/neru/KAITO.pmd create mode 100644 res/models/neru/Len_Kagamine.pmd create mode 100644 res/models/neru/Meiko_Sakine.pmd create mode 100644 res/models/neru/Miku_Hatsune.pmd create mode 100644 res/models/neru/Miku_Hatsune_Ver2.pmd create mode 100644 res/models/neru/Miku_Hatsune_metal.pmd create mode 100644 res/models/neru/Neru_Akita.pmd create mode 100644 res/models/neru/Rin_Kagamine.pmd create mode 100644 res/models/neru/Rin_Kagamine_act2.pmd create mode 100644 res/models/neru/eye2.bmp create mode 100644 res/models/neru/eye3.bmp create mode 100644 res/models/neru/eye3Ne.bmp create mode 100644 res/models/neru/eye4.bmp create mode 100644 res/models/neru/eyeKT.bmp create mode 100644 res/models/neru/eyeM2.bmp create mode 100644 res/models/neru/eyeR2.bmp create mode 100644 res/models/neru/metal.sph create mode 100644 res/models/neru/mikuhair.sph create mode 100644 res/models/neru/sakine1.bmp create mode 100644 res/models/neru/toon0.bmp create mode 100644 res/models/neru/toon01.bmp create mode 100644 res/models/neru/toon02.bmp create mode 100644 res/models/neru/toon03.bmp create mode 100644 res/models/neru/toon04.bmp create mode 100644 res/models/neru/toon05.bmp create mode 100644 res/models/neru/toon06.bmp create mode 100644 res/models/neru/toon07.bmp create mode 100644 res/models/neru/toon08.bmp create mode 100644 res/models/neru/toon09.bmp create mode 100644 res/models/neru/toon10.bmp create mode 100644 res/models/raisen/motion.vmd create mode 100644 res/models/raisen/raisen.pmd create mode 100644 res/models/raisen/t000.bmp create mode 100644 res/models/raisen/t001.bmp create mode 100644 res/models/raisen/t001.sph create mode 100644 res/models/raisen/t002.bmp create mode 100644 res/models/raisen/t003.bmp create mode 100644 res/models/raisen/t004.bmp create mode 100644 res/models/raisen/t005.bmp create mode 100644 res/models/raisen/t006.bmp create mode 100644 res/models/raisen/t007.bmp create mode 100644 res/models/raisen/t008.bmp create mode 100644 res/models/raisen/t008.sph create mode 100644 res/models/raisen/t009.bmp create mode 100644 res/models/raisen/t010.bmp create mode 100644 res/models/raisen/t011.bmp create mode 100644 res/models/raisen/t011.sph create mode 100644 res/models/raisen/t012.bmp create mode 100644 res/models/raisen/t013.bmp create mode 100644 res/models/raisen/t014.bmp create mode 100644 res/models/raisen/t015.bmp create mode 100644 res/models/raisen/t016.bmp create mode 100644 res/models/raisen/t017.bmp create mode 100644 res/models/raisen/t018.bmp create mode 100644 res/models/raisen/t019.bmp create mode 100644 res/models/raisen/t020.bmp create mode 100644 res/models/raisen/t021.bmp create mode 100644 res/models/raisen/t022.bmp create mode 100644 res/models/raisen/t023.bmp create mode 100644 res/models/rin/motion.vmd create mode 100644 res/models/rin/rin.pmd create mode 100644 res/models/rin/tex_body2.tga create mode 100644 res/models/rin/tex_eyes2.tga create mode 100644 res/models/rin/tex_eyes2base.tga create mode 100644 res/models/rin/tex_fuku0.tga create mode 100644 res/models/rin/tex_kami0.tga create mode 100644 res/models/rin/tex_kami1.tga create mode 100644 res/models/rin/tex_kami2.tga create mode 100644 res/models/rin/tex_kao.tga create mode 100644 res/models/rin/tex_nafuda.tga create mode 100644 res/models/rin/tex_pants.tga create mode 100644 res/models/rin/tex_skirt.tga create mode 100644 res/models/rin/tex_taitu.tga create mode 100644 res/models/rin/tex_uwabaki2.tga create mode 100644 res/models/rin/toon0.bmp create mode 100644 res/models/rin/toon01.bmp create mode 100644 res/models/rin/toon02.bmp create mode 100644 res/models/rin/toon03.bmp create mode 100644 res/models/rin/toon04.bmp create mode 100644 res/models/rin/toon05.bmp create mode 100644 res/models/rin/toon06.bmp create mode 100644 res/models/rin/toon07.bmp create mode 100644 res/models/rin/toon08.bmp create mode 100644 res/models/rin/toon09.bmp create mode 100644 res/models/rin/toon10.bmp create mode 100644 res/models/test.vmd create mode 100644 res/models/yuki/tex_yukibody.bmp create mode 100644 res/models/yuki/tex_yukihead.bmp create mode 100644 res/models/yuki/tex_yukireg.bmp create mode 100644 res/models/yuki/yuki.pmd create mode 100644 res/texture/gravel2.png create mode 100644 res/texture/ice.png create mode 100644 res/texture/snow.png create mode 100644 res/texture/stone/gabbro.png create mode 100644 res/texture/stone/granite.png create mode 100644 res/texture/stone/sedimentary/breccia.png create mode 100644 res/texture/stone/sedimentary/breccia32.png create mode 100644 res/texture/stone/sedimentary/chert.png create mode 100644 res/texture/stone/sedimentary/chert32.png create mode 100644 res/texture/stone/sedimentary/coal.png create mode 100644 res/texture/stone/sedimentary/coal32.png create mode 100644 res/texture/stone/sedimentary/conglomerate.png create mode 100644 res/texture/stone/sedimentary/conglomerate32.png create mode 100644 res/texture/stone/sedimentary/limestone.png create mode 100644 res/texture/stone/sedimentary/limestone32.png create mode 100644 res/texture/stone/sedimentary/sandstone.png create mode 100644 res/texture/stone/sedimentary/sandstone32.png create mode 100644 res/texture/stone/sedimentary/shale.png create mode 100644 res/texture/stone/sedimentary/shale32.png create mode 100644 res/texture/stone/sedimentary/siltstone.png create mode 100644 res/texture/stone/sedimentary/siltstone32.png create mode 100644 res/texture/terrain-wheatgrass-lightgreen-med.png create mode 100644 res/texture/water.png create mode 100644 res/texture/wheat.png create mode 100644 src/jp/nyatla/nymmd/MmdException.java create mode 100644 src/jp/nyatla/nymmd/MmdMotionPlayer.java create mode 100644 src/jp/nyatla/nymmd/MmdMotionPlayerGL2.java create mode 100644 src/jp/nyatla/nymmd/MmdPmdModel.java create mode 100644 src/jp/nyatla/nymmd/MmdPmdModel_BasicClass.java create mode 100644 src/jp/nyatla/nymmd/MmdVmdMotion.java create mode 100644 src/jp/nyatla/nymmd/MmdVmdMotion_BasicClass.java create mode 100644 src/jp/nyatla/nymmd/core/PmdBone.java create mode 100644 src/jp/nyatla/nymmd/core/PmdFace.java create mode 100644 src/jp/nyatla/nymmd/core/PmdIK.java create mode 100644 src/jp/nyatla/nymmd/struct/DataReader.java create mode 100644 src/jp/nyatla/nymmd/struct/StructReader.java create mode 100644 src/jp/nyatla/nymmd/struct/StructType.java create mode 100644 src/jp/nyatla/nymmd/struct/pmd/PMD_Bone.java create mode 100644 src/jp/nyatla/nymmd/struct/pmd/PMD_FACE.java create mode 100644 src/jp/nyatla/nymmd/struct/pmd/PMD_FACE_VTX.java create mode 100644 src/jp/nyatla/nymmd/struct/pmd/PMD_Header.java create mode 100644 src/jp/nyatla/nymmd/struct/pmd/PMD_IK.java create mode 100644 src/jp/nyatla/nymmd/struct/pmd/PMD_Material.java create mode 100644 src/jp/nyatla/nymmd/struct/pmd/PMD_Vertex.java create mode 100644 src/jp/nyatla/nymmd/struct/vmd/VMD_Face.java create mode 100644 src/jp/nyatla/nymmd/struct/vmd/VMD_Header.java create mode 100644 src/jp/nyatla/nymmd/struct/vmd/VMD_Motion.java create mode 100644 src/jp/nyatla/nymmd/types/BoneKeyFrame.java create mode 100644 src/jp/nyatla/nymmd/types/FaceData.java create mode 100644 src/jp/nyatla/nymmd/types/FaceKeyFrame.java create mode 100644 src/jp/nyatla/nymmd/types/MmdColor3.java create mode 100644 src/jp/nyatla/nymmd/types/MmdColor4.java create mode 100644 src/jp/nyatla/nymmd/types/MmdMatrix.java create mode 100644 src/jp/nyatla/nymmd/types/MmdTexUV.java create mode 100644 src/jp/nyatla/nymmd/types/MmdVector3.java create mode 100644 src/jp/nyatla/nymmd/types/MmdVector4.java create mode 100644 src/jp/nyatla/nymmd/types/MotionData.java create mode 100644 src/jp/nyatla/nymmd/types/PmdMaterial.java create mode 100644 src/jp/nyatla/nymmd/types/PmdSkinInfo.java create mode 100644 src/ru/olamedia/asset/Shader.java create mode 100644 src/ru/olamedia/asset/Sprite.java create mode 100644 src/ru/olamedia/asset/SpriteOffset.java create mode 100644 src/ru/olamedia/asset/SpriteRectangle.java create mode 100644 src/ru/olamedia/asset/shader/block.fp create mode 100644 src/ru/olamedia/asset/shader/block.vp create mode 100644 src/ru/olamedia/data/BitCube.java create mode 100644 src/ru/olamedia/data/package-info.java create mode 100644 src/ru/olamedia/game/GameLogicThread.java create mode 100644 src/ru/olamedia/geom/ChunkMesh.java create mode 100644 src/ru/olamedia/geom/ChunkMeshNode.java create mode 100644 src/ru/olamedia/geom/ChunkMeshOctree.java create mode 100644 src/ru/olamedia/geom/Frustum2.java create mode 100644 src/ru/olamedia/geom/ImmModeMesh.java create mode 100644 src/ru/olamedia/geom/IndexedMeshBulder.java create mode 100644 src/ru/olamedia/geom/MultiMesh.java create mode 100644 src/ru/olamedia/geom/VoxelRaypicker.java create mode 100644 src/ru/olamedia/math/Vector.java create mode 100644 src/ru/olamedia/math/VectorUtil.java create mode 100644 src/ru/olamedia/olacraft/modelAnimator/Arm.java create mode 100644 src/ru/olamedia/olacraft/modelAnimator/Bone.java create mode 100644 src/ru/olamedia/olacraft/modelAnimator/BoneSet.java create mode 100644 src/ru/olamedia/olacraft/modelAnimator/ISkeletonNode.java create mode 100644 src/ru/olamedia/olacraft/modelAnimator/Leg.java create mode 100644 src/ru/olamedia/olacraft/modelAnimator/ModelAnimator.java create mode 100644 src/ru/olamedia/olacraft/modelAnimator/Randomizer.java create mode 100644 src/ru/olamedia/olacraft/modelAnimator/Skeleton.java create mode 100644 src/ru/olamedia/olacraft/modelAnimator/package-info.java create mode 100644 src/ru/olamedia/olacraft/network/packet/SectorDataPacket.java create mode 100644 src/ru/olamedia/olacraft/network/provider/CacheProvider.java create mode 100644 src/ru/olamedia/olacraft/network/provider/IProvider.java create mode 100644 src/ru/olamedia/olacraft/network/provider/LocalProvider.java create mode 100644 src/ru/olamedia/olacraft/network/provider/RemoteProvider.java create mode 100644 src/ru/olamedia/olacraft/network/provider/package-info.java create mode 100644 src/ru/olamedia/olacraft/render/jogl/ChunkRangeRenderer.java create mode 100644 src/ru/olamedia/olacraft/world/biome/Biome.java create mode 100644 src/ru/olamedia/olacraft/world/biome/package-info.java create mode 100644 src/ru/olamedia/olacraft/world/blockRenderer/AbstractBlockRenderer.java create mode 100644 src/ru/olamedia/olacraft/world/blockRenderer/BoxRenderer.java create mode 100644 src/ru/olamedia/olacraft/world/blockRenderer/ChunkMeshGarbageCollector.java create mode 100644 src/ru/olamedia/olacraft/world/blockRenderer/ChunkRenderer.java create mode 100644 src/ru/olamedia/olacraft/world/blockRenderer/CrossQuadsRenderer.java create mode 100644 src/ru/olamedia/olacraft/world/blockRenderer/IBlockRenderer.java create mode 100644 src/ru/olamedia/olacraft/world/blockRenderer/RenderLocation.java create mode 100644 src/ru/olamedia/olacraft/world/blockRenderer/package-info.java create mode 100644 src/ru/olamedia/olacraft/world/blockTypes/IceBlockType.java create mode 100644 src/ru/olamedia/olacraft/world/blockTypes/SnowBlockType.java create mode 100644 src/ru/olamedia/olacraft/world/blockTypes/TallGrassBlockType.java create mode 100644 src/ru/olamedia/olacraft/world/blockTypes/WaterBlockType.java create mode 100644 src/ru/olamedia/olacraft/world/blockTypes/WheatBlockType.java create mode 100644 src/ru/olamedia/olacraft/world/blockTypes/stone/BrecciaStoneBlockType.java create mode 100644 src/ru/olamedia/olacraft/world/blockTypes/stone/ChertStoneBlockType.java create mode 100644 src/ru/olamedia/olacraft/world/blockTypes/stone/CoalStoneBlockType.java create mode 100644 src/ru/olamedia/olacraft/world/blockTypes/stone/ConglomerateStoneBlockType.java create mode 100644 src/ru/olamedia/olacraft/world/blockTypes/stone/LimestoneStoneBlockType.java create mode 100644 src/ru/olamedia/olacraft/world/blockTypes/stone/SandstoneStoneBlockType.java create mode 100644 src/ru/olamedia/olacraft/world/blockTypes/stone/ShaleStoneBlockType.java create mode 100644 src/ru/olamedia/olacraft/world/blockTypes/stone/SiltstoneStoneBlockType.java create mode 100644 src/ru/olamedia/olacraft/world/blockTypes/stone/package-info.java create mode 100644 src/ru/olamedia/olacraft/world/calc/LightCalculator.java create mode 100644 src/ru/olamedia/olacraft/world/calc/LightData.java create mode 100644 src/ru/olamedia/olacraft/world/calc/VisibilityCalculator.java create mode 100644 src/ru/olamedia/olacraft/world/calc/VisibilityData.java create mode 100644 src/ru/olamedia/olacraft/world/calc/package-info.java create mode 100644 src/ru/olamedia/olacraft/world/data/ChunkDataManager.java create mode 100644 src/ru/olamedia/olacraft/world/data/ChunkDataNeighbors.java create mode 100644 src/ru/olamedia/olacraft/world/data/ChunkDataPointer.java create mode 100644 src/ru/olamedia/olacraft/world/data/ChunkDataWrapper.java create mode 100644 src/ru/olamedia/olacraft/world/drop/DroppedEntity.java create mode 100644 src/ru/olamedia/olacraft/world/drop/package-info.java create mode 100644 src/ru/olamedia/olacraft/world/fluid/FluidLevel.java create mode 100644 src/ru/olamedia/olacraft/world/fluid/FluidLine.java create mode 100644 src/ru/olamedia/olacraft/world/fluid/FluidSource.java create mode 100644 src/ru/olamedia/olacraft/world/fluid/package-info.java create mode 100644 src/ru/olamedia/olacraft/world/generator/HumiditySelectLayer.java create mode 100644 src/ru/olamedia/olacraft/world/generator/IslandSelectLayer.java create mode 100644 src/ru/olamedia/olacraft/world/generator/MountainSelectLayer.java create mode 100644 src/ru/olamedia/olacraft/world/generator/OceanSelectLayer.java create mode 100644 src/ru/olamedia/olacraft/world/generator/RiverSelectLayer.java create mode 100644 src/ru/olamedia/olacraft/world/generator/TemperatureSelectLayer.java create mode 100644 src/ru/olamedia/olacraft/world/location/IntLocation.java create mode 100644 src/ru/olamedia/olacraft/world/location/Location3f.java create mode 100644 src/ru/olamedia/olacraft/world/location/Location3i.java create mode 100644 src/ru/olamedia/olacraft/world/location/MetaLocation3i.java create mode 100644 src/ru/olamedia/olacraft/world/provider/IWorldProvider.java create mode 100644 src/ru/olamedia/olacraft/world/provider/LocalWorld.java create mode 100644 src/ru/olamedia/olacraft/world/provider/RemoteWorld.java create mode 100644 src/ru/olamedia/player/RuntimeSettings.java diff --git a/res/models/alice/2.spa b/res/models/alice/2.spa new file mode 100644 index 0000000..aeaef91 Binary files /dev/null and b/res/models/alice/2.spa differ diff --git a/res/models/alice/3.spa b/res/models/alice/3.spa new file mode 100644 index 0000000..a230378 Binary files /dev/null and b/res/models/alice/3.spa differ diff --git a/res/models/alice/4.sph b/res/models/alice/4.sph new file mode 100644 index 0000000..2bac167 Binary files /dev/null and b/res/models/alice/4.sph differ diff --git a/res/models/alice/5.sph b/res/models/alice/5.sph new file mode 100644 index 0000000..fc37d8c Binary files /dev/null and b/res/models/alice/5.sph differ diff --git a/res/models/alice/6.spa b/res/models/alice/6.spa new file mode 100644 index 0000000..b59f6db Binary files /dev/null and b/res/models/alice/6.spa differ diff --git a/res/models/alice/alice.pmd b/res/models/alice/alice.pmd new file mode 100644 index 0000000..4301cf7 Binary files /dev/null and b/res/models/alice/alice.pmd differ diff --git "a/res/models/alice/alice_\320\244\320\277\320\237C\320\240\342\224\202Ver111025.pmd" "b/res/models/alice/alice_\320\244\320\277\320\237C\320\240\342\224\202Ver111025.pmd" new file mode 100644 index 0000000..6b6ff7e Binary files /dev/null and "b/res/models/alice/alice_\320\244\320\277\320\237C\320\240\342\224\202Ver111025.pmd" differ diff --git a/res/models/alice/k_toon03.bmp b/res/models/alice/k_toon03.bmp new file mode 100644 index 0000000..24cacf0 Binary files /dev/null and b/res/models/alice/k_toon03.bmp differ diff --git a/res/models/alice/readme.txt b/res/models/alice/readme.txt new file mode 100644 index 0000000..1969140 --- /dev/null +++ b/res/models/alice/readme.txt @@ -0,0 +1,40 @@ +「クイーンズゲイト 門を開く者 アリス」PMD (ver.100910_5) + +* +このデータは「クイーンズゲイト 門を開く者 アリス」 +の「MikuMikuDance」用のモデルデータ(.pmd)です。 +MikuMikuDancev7.07で動作確認してあります。 +(それ以前のMMDだと正しく物理演算が機能しません。) + +* +データの転載、商用利用は厳禁です。 +このデータの一部をそのまま流用、または改造したものを含むデータの配布もご遠慮ください。 +(データを改造して遊んでいただくのはOK。) + +* +またこのデータは18歳未満の方のご使用は固く禁じさせていただきます。 +MMD界隈に迷惑のかからない遊び方をしてください。 + + +* +銃を持たせるのは大変だと思いますのです +銃を両手に持つポーズデータ(.vqd)を同梱してあります。(「両手に銃.vqd」) +しょぼいですがぜひ使ってやってください。 + + +「クイーンズゲイト」公式サイト +http://queensblade.net/qg/ + +HobbyJAPANさま公式サイト +http://www.hobbyjapan.co.jp/ + +ニトロプラスさま公式サイト +http://www.nitroplus.co.jp/ + + +勝手にモデリングした人:かこみき +http://www003.upp.so-net.ne.jp/kakomiki/ + + + + diff --git a/res/models/alice/tex_asi.tga b/res/models/alice/tex_asi.tga new file mode 100644 index 0000000..2d4907e Binary files /dev/null and b/res/models/alice/tex_asi.tga differ diff --git a/res/models/alice/tex_body.tga b/res/models/alice/tex_body.tga new file mode 100644 index 0000000..c463328 Binary files /dev/null and b/res/models/alice/tex_body.tga differ diff --git a/res/models/alice/tex_buki.tga b/res/models/alice/tex_buki.tga new file mode 100644 index 0000000..de4a3d6 Binary files /dev/null and b/res/models/alice/tex_buki.tga differ diff --git a/res/models/alice/tex_eyes2.tga b/res/models/alice/tex_eyes2.tga new file mode 100644 index 0000000..fea59f3 Binary files /dev/null and b/res/models/alice/tex_eyes2.tga differ diff --git a/res/models/alice/tex_eyesb.tga b/res/models/alice/tex_eyesb.tga new file mode 100644 index 0000000..c8dfdb4 Binary files /dev/null and b/res/models/alice/tex_eyesb.tga differ diff --git a/res/models/alice/tex_fuku.tga b/res/models/alice/tex_fuku.tga new file mode 100644 index 0000000..5a04110 Binary files /dev/null and b/res/models/alice/tex_fuku.tga differ diff --git a/res/models/alice/tex_gun2a.tga b/res/models/alice/tex_gun2a.tga new file mode 100644 index 0000000..28d0436 Binary files /dev/null and b/res/models/alice/tex_gun2a.tga differ diff --git a/res/models/alice/tex_gun2b.tga b/res/models/alice/tex_gun2b.tga new file mode 100644 index 0000000..95d4d71 Binary files /dev/null and b/res/models/alice/tex_gun2b.tga differ diff --git a/res/models/alice/tex_guna.tga b/res/models/alice/tex_guna.tga new file mode 100644 index 0000000..4fbeec4 Binary files /dev/null and b/res/models/alice/tex_guna.tga differ diff --git a/res/models/alice/tex_gunb.tga b/res/models/alice/tex_gunb.tga new file mode 100644 index 0000000..9a4dae6 Binary files /dev/null and b/res/models/alice/tex_gunb.tga differ diff --git a/res/models/alice/tex_kami1.tga b/res/models/alice/tex_kami1.tga new file mode 100644 index 0000000..a0faf6f Binary files /dev/null and b/res/models/alice/tex_kami1.tga differ diff --git a/res/models/alice/tex_kao.tga b/res/models/alice/tex_kao.tga new file mode 100644 index 0000000..4786d63 Binary files /dev/null and b/res/models/alice/tex_kao.tga differ diff --git a/res/models/alice/tex_kutu.tga b/res/models/alice/tex_kutu.tga new file mode 100644 index 0000000..0d99484 Binary files /dev/null and b/res/models/alice/tex_kutu.tga differ diff --git a/res/models/alice/toon0.bmp b/res/models/alice/toon0.bmp new file mode 100644 index 0000000..1b982fe Binary files /dev/null and b/res/models/alice/toon0.bmp differ diff --git a/res/models/alice/toon01.bmp b/res/models/alice/toon01.bmp new file mode 100644 index 0000000..08950ab Binary files /dev/null and b/res/models/alice/toon01.bmp differ diff --git a/res/models/alice/toon02.bmp b/res/models/alice/toon02.bmp new file mode 100644 index 0000000..9c39cd5 Binary files /dev/null and b/res/models/alice/toon02.bmp differ diff --git a/res/models/alice/toon03.bmp b/res/models/alice/toon03.bmp new file mode 100644 index 0000000..093094e Binary files /dev/null and b/res/models/alice/toon03.bmp differ diff --git a/res/models/alice/toon04.bmp b/res/models/alice/toon04.bmp new file mode 100644 index 0000000..2fbb80d Binary files /dev/null and b/res/models/alice/toon04.bmp differ diff --git a/res/models/alice/toon05.bmp b/res/models/alice/toon05.bmp new file mode 100644 index 0000000..136a709 Binary files /dev/null and b/res/models/alice/toon05.bmp differ diff --git a/res/models/alice/toon06.bmp b/res/models/alice/toon06.bmp new file mode 100644 index 0000000..9c500c0 Binary files /dev/null and b/res/models/alice/toon06.bmp differ diff --git a/res/models/alice/toon07.bmp b/res/models/alice/toon07.bmp new file mode 100644 index 0000000..1b982fe Binary files /dev/null and b/res/models/alice/toon07.bmp differ diff --git a/res/models/alice/toon08.bmp b/res/models/alice/toon08.bmp new file mode 100644 index 0000000..1b982fe Binary files /dev/null and b/res/models/alice/toon08.bmp differ diff --git a/res/models/alice/toon09.bmp b/res/models/alice/toon09.bmp new file mode 100644 index 0000000..1b982fe Binary files /dev/null and b/res/models/alice/toon09.bmp differ diff --git a/res/models/alice/toon10.bmp b/res/models/alice/toon10.bmp new file mode 100644 index 0000000..1b982fe Binary files /dev/null and b/res/models/alice/toon10.bmp differ diff --git "a/res/models/alice/\320\247\342\225\235\320\236\321\210\320\222\342\225\224\320\237e.vpd" "b/res/models/alice/\320\247\342\225\235\320\236\321\210\320\222\342\225\224\320\237e.vpd" new file mode 100644 index 0000000..85eb827 --- /dev/null +++ "b/res/models/alice/\320\247\342\225\235\320\236\321\210\320\222\342\225\224\320\237e.vpd" @@ -0,0 +1,175 @@ +Vocaloid Pose Data file + +門を開く者 アリス.osm; // 親ファイル名 +34; // 総ポーズボーン数 + +Bone0{右手首 + 0.000000,0.000000,0.000000; // trans x,y,z + 0.000000,0.000000,0.000000,1.000000; // Quaternion x,y,z,w +} + +Bone1{右ガン + 1.612447,-0.266657,-0.355809; // trans x,y,z + -0.575623,0.412605,-0.220967,0.670514; // Quaternion x,y,z,w +} + +Bone2{右親指0 + 0.000000,0.000000,0.000000; // trans x,y,z + -0.102034,-0.027499,0.144979,0.983775; // Quaternion x,y,z,w +} + +Bone3{右親指1 + 0.000000,0.000000,0.000000; // trans x,y,z + -0.256927,-0.095515,-0.235400,0.932444; // Quaternion x,y,z,w +} + +Bone4{右親指2 + -0.000000,0.000000,0.000000; // trans x,y,z + -0.154560,0.230438,0.113734,0.953978; // Quaternion x,y,z,w +} + +Bone5{右小指1 + -0.000000,0.000000,0.000000; // trans x,y,z + 0.296617,-0.083466,0.371816,0.875673; // Quaternion x,y,z,w +} + +Bone6{右小指2 + -0.000000,0.000000,0.000000; // trans x,y,z + 0.152086,0.058655,0.311912,0.936024; // Quaternion x,y,z,w +} + +Bone7{右小指3 + -0.000000,0.000000,0.000000; // trans x,y,z + 0.014369,-0.046583,0.340936,0.938822; // Quaternion x,y,z,w +} + +Bone8{右薬指1 + -0.000000,0.000000,0.000000; // trans x,y,z + 0.217944,-0.085974,0.521585,0.820401; // Quaternion x,y,z,w +} + +Bone9{右薬指2 + -0.000000,0.000000,0.000000; // trans x,y,z + 0.067904,-0.039948,0.234951,0.968809; // Quaternion x,y,z,w +} + +Bone10{右薬指3 + 0.000000,0.000000,0.000000; // trans x,y,z + 0.098877,0.048031,0.247578,0.962612; // Quaternion x,y,z,w +} + +Bone11{右中指1 + -0.000000,0.000000,0.000000; // trans x,y,z + 0.087757,-0.010046,0.338843,0.936687; // Quaternion x,y,z,w +} + +Bone12{右中指2 + -0.000000,0.000000,0.000000; // trans x,y,z + 0.059888,-0.038414,0.554317,0.829258; // Quaternion x,y,z,w +} + +Bone13{右中指3 + 0.000000,0.000000,0.000000; // trans x,y,z + -0.022173,-0.067596,0.176121,0.981795; // Quaternion x,y,z,w +} + +Bone14{右人指1 + -0.000000,0.000000,0.000000; // trans x,y,z + 0.110380,0.059755,-0.017646,0.991934; // Quaternion x,y,z,w +} + +Bone15{右人指2 + -0.000000,0.000000,0.000000; // trans x,y,z + 0.000000,0.000000,0.280488,0.959857; // Quaternion x,y,z,w +} + +Bone16{右人指3 + -0.000000,0.000000,0.000000; // trans x,y,z + -0.069746,-0.000340,0.312723,0.947280; // Quaternion x,y,z,w +} + +Bone17{左手首 + -0.000000,0.000000,0.000000; // trans x,y,z + 0.000000,-0.000000,-0.000000,1.000000; // Quaternion x,y,z,w +} + +Bone18{左ガン + -1.612447,-0.266657,-0.355809; // trans x,y,z + -0.575623,-0.412605,0.220967,0.670514; // Quaternion x,y,z,w +} + +Bone19{左親指0 + -0.000000,0.000000,0.000000; // trans x,y,z + -0.102034,0.027499,-0.144979,0.983775; // Quaternion x,y,z,w +} + +Bone20{左親指1 + -0.000000,0.000000,0.000000; // trans x,y,z + -0.256927,0.095515,0.235400,0.932444; // Quaternion x,y,z,w +} + +Bone21{左親指2 + 0.000000,0.000000,0.000000; // trans x,y,z + -0.154560,-0.230438,-0.113734,0.953978; // Quaternion x,y,z,w +} + +Bone22{左小指1 + 0.000000,0.000000,0.000000; // trans x,y,z + 0.296617,0.083466,-0.371816,0.875673; // Quaternion x,y,z,w +} + +Bone23{左小指2 + 0.000000,0.000000,0.000000; // trans x,y,z + 0.152086,-0.058655,-0.311912,0.936024; // Quaternion x,y,z,w +} + +Bone24{左小指3 + 0.000000,0.000000,0.000000; // trans x,y,z + 0.014369,0.046583,-0.340936,0.938822; // Quaternion x,y,z,w +} + +Bone25{左薬指1 + 0.000000,0.000000,0.000000; // trans x,y,z + 0.217944,0.085974,-0.521585,0.820401; // Quaternion x,y,z,w +} + +Bone26{左薬指2 + 0.000000,0.000000,0.000000; // trans x,y,z + 0.067904,0.039948,-0.234951,0.968809; // Quaternion x,y,z,w +} + +Bone27{左薬指3 + -0.000000,0.000000,0.000000; // trans x,y,z + 0.098877,-0.048031,-0.247578,0.962612; // Quaternion x,y,z,w +} + +Bone28{左中指1 + 0.000000,0.000000,0.000000; // trans x,y,z + 0.087757,0.010046,-0.338843,0.936687; // Quaternion x,y,z,w +} + +Bone29{左中指2 + 0.000000,0.000000,0.000000; // trans x,y,z + 0.059888,0.038414,-0.554317,0.829258; // Quaternion x,y,z,w +} + +Bone30{左中指3 + -0.000000,0.000000,0.000000; // trans x,y,z + -0.022173,0.067596,-0.176121,0.981795; // Quaternion x,y,z,w +} + +Bone31{左人指1 + 0.000000,0.000000,0.000000; // trans x,y,z + 0.110380,-0.059755,0.017646,0.991934; // Quaternion x,y,z,w +} + +Bone32{左人指2 + 0.000000,0.000000,0.000000; // trans x,y,z + 0.000000,-0.000000,-0.280488,0.959857; // Quaternion x,y,z,w +} + +Bone33{左人指3 + 0.000000,0.000000,0.000000; // trans x,y,z + -0.069746,0.000340,-0.312723,0.947280; // Quaternion x,y,z,w +} + diff --git a/res/models/lat_miku/BLAZER.bmp b/res/models/lat_miku/BLAZER.bmp new file mode 100644 index 0000000..4269fc5 Binary files /dev/null and b/res/models/lat_miku/BLAZER.bmp differ diff --git a/res/models/lat_miku/BLAZER.psd b/res/models/lat_miku/BLAZER.psd new file mode 100644 index 0000000..66e9522 Binary files /dev/null and b/res/models/lat_miku/BLAZER.psd differ diff --git a/res/models/lat_miku/HP-1.bmp b/res/models/lat_miku/HP-1.bmp new file mode 100644 index 0000000..779f10f Binary files /dev/null and b/res/models/lat_miku/HP-1.bmp differ diff --git a/res/models/lat_miku/LatMikuWhite.pmd b/res/models/lat_miku/LatMikuWhite.pmd new file mode 100644 index 0000000..8bdd601 Binary files /dev/null and b/res/models/lat_miku/LatMikuWhite.pmd differ diff --git a/res/models/lat_miku/LatSailore2.pmd b/res/models/lat_miku/LatSailore2.pmd new file mode 100644 index 0000000..3aaa02a Binary files /dev/null and b/res/models/lat_miku/LatSailore2.pmd differ diff --git a/res/models/lat_miku/Normal.pmd b/res/models/lat_miku/Normal.pmd new file mode 100644 index 0000000..1173535 Binary files /dev/null and b/res/models/lat_miku/Normal.pmd differ diff --git a/res/models/lat_miku/Normal2.pmd b/res/models/lat_miku/Normal2.pmd new file mode 100644 index 0000000..37bb031 Binary files /dev/null and b/res/models/lat_miku/Normal2.pmd differ diff --git a/res/models/lat_miku/Sailore.pmd b/res/models/lat_miku/Sailore.pmd new file mode 100644 index 0000000..b864be6 Binary files /dev/null and b/res/models/lat_miku/Sailore.pmd differ diff --git a/res/models/lat_miku/Sailoro.pmd b/res/models/lat_miku/Sailoro.pmd new file mode 100644 index 0000000..67190a9 Binary files /dev/null and b/res/models/lat_miku/Sailoro.pmd differ diff --git a/res/models/lat_miku/Sailoroo.pmd b/res/models/lat_miku/Sailoroo.pmd new file mode 100644 index 0000000..7fa916c Binary files /dev/null and b/res/models/lat_miku/Sailoroo.pmd differ diff --git a/res/models/lat_miku/White.pmd b/res/models/lat_miku/White.pmd new file mode 100644 index 0000000..de82dcc Binary files /dev/null and b/res/models/lat_miku/White.pmd differ diff --git a/res/models/lat_miku/heltudofon.bmp b/res/models/lat_miku/heltudofon.bmp new file mode 100644 index 0000000..342f23e Binary files /dev/null and b/res/models/lat_miku/heltudofon.bmp differ diff --git a/res/models/lat_miku/hoho.png b/res/models/lat_miku/hoho.png new file mode 100644 index 0000000..1f57c99 Binary files /dev/null and b/res/models/lat_miku/hoho.png differ diff --git a/res/models/lat_miku/huk3sb.bmp b/res/models/lat_miku/huk3sb.bmp new file mode 100644 index 0000000..503cb54 Binary files /dev/null and b/res/models/lat_miku/huk3sb.bmp differ diff --git a/res/models/lat_miku/huku1.bmp b/res/models/lat_miku/huku1.bmp new file mode 100644 index 0000000..35fc404 Binary files /dev/null and b/res/models/lat_miku/huku1.bmp differ diff --git a/res/models/lat_miku/huku1w.bmp b/res/models/lat_miku/huku1w.bmp new file mode 100644 index 0000000..bc149df Binary files /dev/null and b/res/models/lat_miku/huku1w.bmp differ diff --git a/res/models/lat_miku/huku3.bmp b/res/models/lat_miku/huku3.bmp new file mode 100644 index 0000000..980fc18 Binary files /dev/null and b/res/models/lat_miku/huku3.bmp differ diff --git a/res/models/lat_miku/huku3s.bmp b/res/models/lat_miku/huku3s.bmp new file mode 100644 index 0000000..9e2815b Binary files /dev/null and b/res/models/lat_miku/huku3s.bmp differ diff --git a/res/models/lat_miku/huku3w.bmp b/res/models/lat_miku/huku3w.bmp new file mode 100644 index 0000000..1661593 Binary files /dev/null and b/res/models/lat_miku/huku3w.bmp differ diff --git a/res/models/lat_miku/huku_s.bmp b/res/models/lat_miku/huku_s.bmp new file mode 100644 index 0000000..38228ad Binary files /dev/null and b/res/models/lat_miku/huku_s.bmp differ diff --git a/res/models/lat_miku/hukus2.bmp b/res/models/lat_miku/hukus2.bmp new file mode 100644 index 0000000..f04fa64 Binary files /dev/null and b/res/models/lat_miku/hukus2.bmp differ diff --git a/res/models/lat_miku/kami.bmp b/res/models/lat_miku/kami.bmp new file mode 100644 index 0000000..7c29c98 Binary files /dev/null and b/res/models/lat_miku/kami.bmp differ diff --git a/res/models/lat_miku/kami_ol.bmp b/res/models/lat_miku/kami_ol.bmp new file mode 100644 index 0000000..8465c27 Binary files /dev/null and b/res/models/lat_miku/kami_ol.bmp differ diff --git a/res/models/lat_miku/loafer.bmp b/res/models/lat_miku/loafer.bmp new file mode 100644 index 0000000..b8d302a Binary files /dev/null and b/res/models/lat_miku/loafer.bmp differ diff --git a/res/models/lat_miku/m.sph b/res/models/lat_miku/m.sph new file mode 100644 index 0000000..c9aec64 Binary files /dev/null and b/res/models/lat_miku/m.sph differ diff --git a/res/models/lat_miku/mahura-.bmp b/res/models/lat_miku/mahura-.bmp new file mode 100644 index 0000000..be8d209 Binary files /dev/null and b/res/models/lat_miku/mahura-.bmp differ diff --git a/res/models/lat_miku/me.bmp b/res/models/lat_miku/me.bmp new file mode 100644 index 0000000..f16d4b7 Binary files /dev/null and b/res/models/lat_miku/me.bmp differ diff --git a/res/models/lat_miku/p.spa b/res/models/lat_miku/p.spa new file mode 100644 index 0000000..8daedc2 Binary files /dev/null and b/res/models/lat_miku/p.spa differ diff --git a/res/models/lat_miku/portapro1.png b/res/models/lat_miku/portapro1.png new file mode 100644 index 0000000..c217c81 Binary files /dev/null and b/res/models/lat_miku/portapro1.png differ diff --git a/res/models/lat_miku/portapro2.bmp b/res/models/lat_miku/portapro2.bmp new file mode 100644 index 0000000..afd141a Binary files /dev/null and b/res/models/lat_miku/portapro2.bmp differ diff --git a/res/models/lat_miku/sp_g.spa b/res/models/lat_miku/sp_g.spa new file mode 100644 index 0000000..c5bfc25 Binary files /dev/null and b/res/models/lat_miku/sp_g.spa differ diff --git a/res/models/lat_miku/sp_g.sph b/res/models/lat_miku/sp_g.sph new file mode 100644 index 0000000..89441c6 Binary files /dev/null and b/res/models/lat_miku/sp_g.sph differ diff --git a/res/models/lat_miku/sp_h.spa b/res/models/lat_miku/sp_h.spa new file mode 100644 index 0000000..4fb2e48 Binary files /dev/null and b/res/models/lat_miku/sp_h.spa differ diff --git a/res/models/lat_miku/sp_k.spa b/res/models/lat_miku/sp_k.spa new file mode 100644 index 0000000..05671ef Binary files /dev/null and b/res/models/lat_miku/sp_k.spa differ diff --git a/res/models/lat_miku/sp_s.spa b/res/models/lat_miku/sp_s.spa new file mode 100644 index 0000000..bdc3af9 Binary files /dev/null and b/res/models/lat_miku/sp_s.spa differ diff --git a/res/models/lat_miku/toon-1.bmp b/res/models/lat_miku/toon-1.bmp new file mode 100644 index 0000000..08950ab Binary files /dev/null and b/res/models/lat_miku/toon-1.bmp differ diff --git a/res/models/lat_miku/toon0.bmp b/res/models/lat_miku/toon0.bmp new file mode 100644 index 0000000..1b982fe Binary files /dev/null and b/res/models/lat_miku/toon0.bmp differ diff --git a/res/models/lat_miku/toon01.bmp b/res/models/lat_miku/toon01.bmp new file mode 100644 index 0000000..08950ab Binary files /dev/null and b/res/models/lat_miku/toon01.bmp differ diff --git a/res/models/lat_miku/toon02.bmp b/res/models/lat_miku/toon02.bmp new file mode 100644 index 0000000..9c39cd5 Binary files /dev/null and b/res/models/lat_miku/toon02.bmp differ diff --git a/res/models/lat_miku/toon03.bmp b/res/models/lat_miku/toon03.bmp new file mode 100644 index 0000000..093094e Binary files /dev/null and b/res/models/lat_miku/toon03.bmp differ diff --git a/res/models/lat_miku/toon04.bmp b/res/models/lat_miku/toon04.bmp new file mode 100644 index 0000000..2fbb80d Binary files /dev/null and b/res/models/lat_miku/toon04.bmp differ diff --git a/res/models/lat_miku/toon05.bmp b/res/models/lat_miku/toon05.bmp new file mode 100644 index 0000000..136a709 Binary files /dev/null and b/res/models/lat_miku/toon05.bmp differ diff --git a/res/models/lat_miku/toon06.bmp b/res/models/lat_miku/toon06.bmp new file mode 100644 index 0000000..9c500c0 Binary files /dev/null and b/res/models/lat_miku/toon06.bmp differ diff --git a/res/models/lat_miku/toon07.bmp b/res/models/lat_miku/toon07.bmp new file mode 100644 index 0000000..1b982fe Binary files /dev/null and b/res/models/lat_miku/toon07.bmp differ diff --git a/res/models/lat_miku/toon08.bmp b/res/models/lat_miku/toon08.bmp new file mode 100644 index 0000000..1b982fe Binary files /dev/null and b/res/models/lat_miku/toon08.bmp differ diff --git a/res/models/lat_miku/toon09.bmp b/res/models/lat_miku/toon09.bmp new file mode 100644 index 0000000..1b982fe Binary files /dev/null and b/res/models/lat_miku/toon09.bmp differ diff --git a/res/models/lat_miku/toon10.bmp b/res/models/lat_miku/toon10.bmp new file mode 100644 index 0000000..1b982fe Binary files /dev/null and b/res/models/lat_miku/toon10.bmp differ diff --git a/res/models/lat_miku/toon_g.bmp b/res/models/lat_miku/toon_g.bmp new file mode 100644 index 0000000..c776edf Binary files /dev/null and b/res/models/lat_miku/toon_g.bmp differ diff --git a/res/models/lat_miku/toon_hada.bmp b/res/models/lat_miku/toon_hada.bmp new file mode 100644 index 0000000..3765035 Binary files /dev/null and b/res/models/lat_miku/toon_hada.bmp differ diff --git a/res/models/lat_miku/toon_huku.bmp b/res/models/lat_miku/toon_huku.bmp new file mode 100644 index 0000000..76e194c Binary files /dev/null and b/res/models/lat_miku/toon_huku.bmp differ diff --git a/res/models/lat_miku/toon_kami.bmp b/res/models/lat_miku/toon_kami.bmp new file mode 100644 index 0000000..3b8b962 Binary files /dev/null and b/res/models/lat_miku/toon_kami.bmp differ diff --git a/res/models/lat_miku/toon_mahu.bmp b/res/models/lat_miku/toon_mahu.bmp new file mode 100644 index 0000000..c58a67e Binary files /dev/null and b/res/models/lat_miku/toon_mahu.bmp differ diff --git a/res/models/lat_miku/toon_s.bmp b/res/models/lat_miku/toon_s.bmp new file mode 100644 index 0000000..8424755 Binary files /dev/null and b/res/models/lat_miku/toon_s.bmp differ diff --git a/res/models/lat_miku/uwabaki.bmp b/res/models/lat_miku/uwabaki.bmp new file mode 100644 index 0000000..9dcca50 Binary files /dev/null and b/res/models/lat_miku/uwabaki.bmp differ diff --git "a/res/models/lat_miku/\320\222\321\212\320\222\320\260\320\222\342\225\237\320\222\321\216.txt" "b/res/models/lat_miku/\320\222\321\212\320\222\320\260\320\222\342\225\237\320\222\321\216.txt" new file mode 100644 index 0000000..ce6c102 --- /dev/null +++ "b/res/models/lat_miku/\320\222\321\212\320\222\320\260\320\222\342\225\237\320\222\321\216.txt" @@ -0,0 +1,102 @@ +::::Lat式ミクVer2.3:::: + +このデータは「初音ミク」のMikuMikuDance用PMDモデルデータ、「Lat式ミクVer2.3」です。 + + + +袖のテクスチャーは三次元CG@七葉に上がってるものを使わせてもらってます。 +スカートにもコピペして使わせてもらいましたー。 +物理演算はhttp://www.nicovideo.jp/watch/sm8362123こちらを元データとして使わせていただきました。 +セーラー版のデザインは好きな絵(作者さん不明)を勝手にマネさせて頂いてます。 +皆様にサンクスサンクスです! + + + +::使い方:: +以下のソフトで作成しています。 + 極北PさんのPMDエディタ ver0.0.6.3 + 樋口MさんのMikuMikuDance (Multi-Model Edition) ver7.04 + + + +普通なNormal版と、アレンジ気味のWhite版、冬服セーラーなSailor冬服版に加えて、 +今回から夏服セーラーなSailor夏服版を追加しました。 +またそれぞれのエッジ無し専用モデルの、計8体のデータが入ってます。 +表情「照れ」「portaPro」で透過pngテクスチャーを使用しているのでMMDVer6以降使用推奨です。 +全モデルが腕捩り・手捩りボーン&物理演算&スフィアマップ&セルフシャドウに対応しています。 + + + +エッジ無し専用モデルは通常版だと消すことの出来ない部分的なエッジを取り除いたモデルです。 +MMDで読み込み後に「エッジ太さ」を0にして使用してください。 + +基本的にMMD純正初音ミク互換で作ってますので、ある程度はモーションの流用が可能です。 +ある程度はですけども。 + +表情に入っているこっちみんな目をデフォルトとして作成していたモデルなので、 +目の表情「コッチミンナ」パラメータMAXでの使用をおすすめです。 + +目の表情「平行下」は、ボーン制御では傾いてしまう下目線を自然にする為の表情です。 + +眼鏡ボーンは、表情の「眼鏡」パラメータMAXにして使用してください。 + +髪のtoon画像が2つ入っています。 +特にセルフシャドウ時に青みがきつ過ぎる場合、 +「青み薄め髪_toon_kami.bmp」をリネームして使用すると色味を薄めに出来ます。 + +セーラー冬服版の表情「マフラーoff」は一応ある程度は見えなくなりますが、実は完全に消しきれていません。 +邪魔になる場合はお手数ですがPMDエディタで素材の一番下を削除してください。 + +おまけでセーラー版の上履きテクスチャー用と、セーラー夏服版のスニーカーテクスチャー用psdデータ付き。 +既にしてある落書きを消したい時や色を変えたい時にお使いください。 + + + + +::使用条件:: +モデルデータは、版権元のキャラクター利用のガイドラインと同様になります。 +その範囲内であればデータの改変・流用を含む利用・再配布等オールOKです。 + + + +::更新履歴:: + +10.07.06 +Ver表記そのままですがセーラー夏服エッジ無し専用モデルの不正法線のみ修正しました + +10.06.27 +Ver2.3公開 +セーラー夏服版追加 +Ver2.2公開動画用モーション削除 +他、モデルデータ一部調整 + +10.04.20 +Ver2.2公開 +捩りボーン実装・セーラー版追加・ツインテ差し替え・一部表情追加&変更 +Ver2.2公開動画用モーション追加 +他、モデルデータ一部調整 + +10.01.19 +Ver2.01公開 +セルフシャドウ用にtoon.bmpのみ調整 + +09.12.27 +Ver2正式版公開 +エッジ無し専用モデル・Ver2公開動画用ステージ&モーション追加 +モデルデータ一部調整 + +09.11.13 +Ver2β版公開 +物理演算&スフィアマップ対応・モデルデータ全体的に調整 + +09.06.13 +正式版公開 +WhiteVersion・眼鏡ボーン・アクセサリーFloorRing追加 +モデルデータ一部調整 + +09.06.07 +beta版公開 + +::::::::::::::::::::::: +Presented by Lat +http://innoce.nobody.jp/ \ No newline at end of file diff --git "a/res/models/lat_miku/\320\237\321\203\320\247\320\252\320\222\320\273.psd" "b/res/models/lat_miku/\320\237\321\203\320\247\320\252\320\222\320\273.psd" new file mode 100644 index 0000000..8a3f908 Binary files /dev/null and "b/res/models/lat_miku/\320\237\321\203\320\247\320\252\320\222\320\273.psd" differ diff --git "a/res/models/lat_miku/\320\240-\320\222\342\226\214\320\244\320\246\320\222\321\216\320\244\320\277\320\221Qtoon_kami.bmp" "b/res/models/lat_miku/\320\240-\320\222\342\226\214\320\244\320\246\320\222\321\216\320\244\320\277\320\221Qtoon_kami.bmp" new file mode 100644 index 0000000..cd4fcae Binary files /dev/null and "b/res/models/lat_miku/\320\240-\320\222\342\226\214\320\244\320\246\320\222\321\216\320\244\320\277\320\221Qtoon_kami.bmp" differ diff --git a/res/models/marisa/marisa.pmd b/res/models/marisa/marisa.pmd new file mode 100644 index 0000000..ceace71 Binary files /dev/null and b/res/models/marisa/marisa.pmd differ diff --git a/res/models/marisa/t000.bmp b/res/models/marisa/t000.bmp new file mode 100644 index 0000000..7ebb34a Binary files /dev/null and b/res/models/marisa/t000.bmp differ diff --git a/res/models/marisa/t001.bmp b/res/models/marisa/t001.bmp new file mode 100644 index 0000000..5cd4a68 Binary files /dev/null and b/res/models/marisa/t001.bmp differ diff --git a/res/models/marisa/t001.sph b/res/models/marisa/t001.sph new file mode 100644 index 0000000..07ba6b9 Binary files /dev/null and b/res/models/marisa/t001.sph differ diff --git a/res/models/marisa/t002.bmp b/res/models/marisa/t002.bmp new file mode 100644 index 0000000..58ddace Binary files /dev/null and b/res/models/marisa/t002.bmp differ diff --git a/res/models/marisa/t003.bmp b/res/models/marisa/t003.bmp new file mode 100644 index 0000000..3791dbb Binary files /dev/null and b/res/models/marisa/t003.bmp differ diff --git a/res/models/marisa/t003.sph b/res/models/marisa/t003.sph new file mode 100644 index 0000000..88f954b Binary files /dev/null and b/res/models/marisa/t003.sph differ diff --git a/res/models/marisa/t004.bmp b/res/models/marisa/t004.bmp new file mode 100644 index 0000000..806e0ce Binary files /dev/null and b/res/models/marisa/t004.bmp differ diff --git a/res/models/marisa/t005.bmp b/res/models/marisa/t005.bmp new file mode 100644 index 0000000..3356cb1 Binary files /dev/null and b/res/models/marisa/t005.bmp differ diff --git a/res/models/marisa/t006.bmp b/res/models/marisa/t006.bmp new file mode 100644 index 0000000..0e744d5 Binary files /dev/null and b/res/models/marisa/t006.bmp differ diff --git a/res/models/marisa/t007.bmp b/res/models/marisa/t007.bmp new file mode 100644 index 0000000..3464286 Binary files /dev/null and b/res/models/marisa/t007.bmp differ diff --git a/res/models/marisa/t008.bmp b/res/models/marisa/t008.bmp new file mode 100644 index 0000000..6964b66 Binary files /dev/null and b/res/models/marisa/t008.bmp differ diff --git a/res/models/marisa/t009.bmp b/res/models/marisa/t009.bmp new file mode 100644 index 0000000..3b2f82b Binary files /dev/null and b/res/models/marisa/t009.bmp differ diff --git a/res/models/marisa/t009.sph b/res/models/marisa/t009.sph new file mode 100644 index 0000000..c28a21d Binary files /dev/null and b/res/models/marisa/t009.sph differ diff --git a/res/models/marisa/t010.bmp b/res/models/marisa/t010.bmp new file mode 100644 index 0000000..adf6ca3 Binary files /dev/null and b/res/models/marisa/t010.bmp differ diff --git a/res/models/marisa/t011.bmp b/res/models/marisa/t011.bmp new file mode 100644 index 0000000..f9c4499 Binary files /dev/null and b/res/models/marisa/t011.bmp differ diff --git a/res/models/marisa/t012.bmp b/res/models/marisa/t012.bmp new file mode 100644 index 0000000..ad118eb Binary files /dev/null and b/res/models/marisa/t012.bmp differ diff --git a/res/models/marisa/t013.bmp b/res/models/marisa/t013.bmp new file mode 100644 index 0000000..213d5c2 Binary files /dev/null and b/res/models/marisa/t013.bmp differ diff --git a/res/models/marisa/t014.bmp b/res/models/marisa/t014.bmp new file mode 100644 index 0000000..5532dac Binary files /dev/null and b/res/models/marisa/t014.bmp differ diff --git a/res/models/marisa/t014.sph b/res/models/marisa/t014.sph new file mode 100644 index 0000000..c28a21d Binary files /dev/null and b/res/models/marisa/t014.sph differ diff --git a/res/models/marisa/t015.bmp b/res/models/marisa/t015.bmp new file mode 100644 index 0000000..267f9bf Binary files /dev/null and b/res/models/marisa/t015.bmp differ diff --git a/res/models/marisa/t016.bmp b/res/models/marisa/t016.bmp new file mode 100644 index 0000000..dab5afa Binary files /dev/null and b/res/models/marisa/t016.bmp differ diff --git a/res/models/marisa/t017.bmp b/res/models/marisa/t017.bmp new file mode 100644 index 0000000..5e7104c Binary files /dev/null and b/res/models/marisa/t017.bmp differ diff --git a/res/models/marisa/t018.bmp b/res/models/marisa/t018.bmp new file mode 100644 index 0000000..c14d803 Binary files /dev/null and b/res/models/marisa/t018.bmp differ diff --git a/res/models/marisa/t019.bmp b/res/models/marisa/t019.bmp new file mode 100644 index 0000000..0607367 Binary files /dev/null and b/res/models/marisa/t019.bmp differ diff --git a/res/models/marisa/t020.bmp b/res/models/marisa/t020.bmp new file mode 100644 index 0000000..ea22a0f Binary files /dev/null and b/res/models/marisa/t020.bmp differ diff --git a/res/models/marisa/t021.bmp b/res/models/marisa/t021.bmp new file mode 100644 index 0000000..145af10 Binary files /dev/null and b/res/models/marisa/t021.bmp differ diff --git a/res/models/marisa/t022.bmp b/res/models/marisa/t022.bmp new file mode 100644 index 0000000..995f2ea Binary files /dev/null and b/res/models/marisa/t022.bmp differ diff --git a/res/models/motion.vmd b/res/models/motion.vmd new file mode 100644 index 0000000..a99b58d Binary files /dev/null and b/res/models/motion.vmd differ diff --git a/res/models/neru/Dammy_Bone.pmd b/res/models/neru/Dammy_Bone.pmd new file mode 100644 index 0000000..cb857ad Binary files /dev/null and b/res/models/neru/Dammy_Bone.pmd differ diff --git a/res/models/neru/Haku_Yowane.pmd b/res/models/neru/Haku_Yowane.pmd new file mode 100644 index 0000000..e6d66f6 Binary files /dev/null and b/res/models/neru/Haku_Yowane.pmd differ diff --git a/res/models/neru/KAITO.pmd b/res/models/neru/KAITO.pmd new file mode 100644 index 0000000..ed8e2ce Binary files /dev/null and b/res/models/neru/KAITO.pmd differ diff --git a/res/models/neru/Len_Kagamine.pmd b/res/models/neru/Len_Kagamine.pmd new file mode 100644 index 0000000..e9aa914 Binary files /dev/null and b/res/models/neru/Len_Kagamine.pmd differ diff --git a/res/models/neru/Meiko_Sakine.pmd b/res/models/neru/Meiko_Sakine.pmd new file mode 100644 index 0000000..1278f96 Binary files /dev/null and b/res/models/neru/Meiko_Sakine.pmd differ diff --git a/res/models/neru/Miku_Hatsune.pmd b/res/models/neru/Miku_Hatsune.pmd new file mode 100644 index 0000000..68e6495 Binary files /dev/null and b/res/models/neru/Miku_Hatsune.pmd differ diff --git a/res/models/neru/Miku_Hatsune_Ver2.pmd b/res/models/neru/Miku_Hatsune_Ver2.pmd new file mode 100644 index 0000000..3fcbbb8 Binary files /dev/null and b/res/models/neru/Miku_Hatsune_Ver2.pmd differ diff --git a/res/models/neru/Miku_Hatsune_metal.pmd b/res/models/neru/Miku_Hatsune_metal.pmd new file mode 100644 index 0000000..2252074 Binary files /dev/null and b/res/models/neru/Miku_Hatsune_metal.pmd differ diff --git a/res/models/neru/Neru_Akita.pmd b/res/models/neru/Neru_Akita.pmd new file mode 100644 index 0000000..ba6641a Binary files /dev/null and b/res/models/neru/Neru_Akita.pmd differ diff --git a/res/models/neru/Rin_Kagamine.pmd b/res/models/neru/Rin_Kagamine.pmd new file mode 100644 index 0000000..14a866b Binary files /dev/null and b/res/models/neru/Rin_Kagamine.pmd differ diff --git a/res/models/neru/Rin_Kagamine_act2.pmd b/res/models/neru/Rin_Kagamine_act2.pmd new file mode 100644 index 0000000..29c9f42 Binary files /dev/null and b/res/models/neru/Rin_Kagamine_act2.pmd differ diff --git a/res/models/neru/eye2.bmp b/res/models/neru/eye2.bmp new file mode 100644 index 0000000..c4fefa9 Binary files /dev/null and b/res/models/neru/eye2.bmp differ diff --git a/res/models/neru/eye3.bmp b/res/models/neru/eye3.bmp new file mode 100644 index 0000000..feccb70 Binary files /dev/null and b/res/models/neru/eye3.bmp differ diff --git a/res/models/neru/eye3Ne.bmp b/res/models/neru/eye3Ne.bmp new file mode 100644 index 0000000..f0b81db Binary files /dev/null and b/res/models/neru/eye3Ne.bmp differ diff --git a/res/models/neru/eye4.bmp b/res/models/neru/eye4.bmp new file mode 100644 index 0000000..19a5ec1 Binary files /dev/null and b/res/models/neru/eye4.bmp differ diff --git a/res/models/neru/eyeKT.bmp b/res/models/neru/eyeKT.bmp new file mode 100644 index 0000000..4b4b68d Binary files /dev/null and b/res/models/neru/eyeKT.bmp differ diff --git a/res/models/neru/eyeM2.bmp b/res/models/neru/eyeM2.bmp new file mode 100644 index 0000000..32ff763 Binary files /dev/null and b/res/models/neru/eyeM2.bmp differ diff --git a/res/models/neru/eyeR2.bmp b/res/models/neru/eyeR2.bmp new file mode 100644 index 0000000..645d71d Binary files /dev/null and b/res/models/neru/eyeR2.bmp differ diff --git a/res/models/neru/metal.sph b/res/models/neru/metal.sph new file mode 100644 index 0000000..394c5b2 Binary files /dev/null and b/res/models/neru/metal.sph differ diff --git a/res/models/neru/mikuhair.sph b/res/models/neru/mikuhair.sph new file mode 100644 index 0000000..f546004 Binary files /dev/null and b/res/models/neru/mikuhair.sph differ diff --git a/res/models/neru/sakine1.bmp b/res/models/neru/sakine1.bmp new file mode 100644 index 0000000..0bcaad8 Binary files /dev/null and b/res/models/neru/sakine1.bmp differ diff --git a/res/models/neru/toon0.bmp b/res/models/neru/toon0.bmp new file mode 100644 index 0000000..1b982fe Binary files /dev/null and b/res/models/neru/toon0.bmp differ diff --git a/res/models/neru/toon01.bmp b/res/models/neru/toon01.bmp new file mode 100644 index 0000000..08950ab Binary files /dev/null and b/res/models/neru/toon01.bmp differ diff --git a/res/models/neru/toon02.bmp b/res/models/neru/toon02.bmp new file mode 100644 index 0000000..9c39cd5 Binary files /dev/null and b/res/models/neru/toon02.bmp differ diff --git a/res/models/neru/toon03.bmp b/res/models/neru/toon03.bmp new file mode 100644 index 0000000..093094e Binary files /dev/null and b/res/models/neru/toon03.bmp differ diff --git a/res/models/neru/toon04.bmp b/res/models/neru/toon04.bmp new file mode 100644 index 0000000..2fbb80d Binary files /dev/null and b/res/models/neru/toon04.bmp differ diff --git a/res/models/neru/toon05.bmp b/res/models/neru/toon05.bmp new file mode 100644 index 0000000..136a709 Binary files /dev/null and b/res/models/neru/toon05.bmp differ diff --git a/res/models/neru/toon06.bmp b/res/models/neru/toon06.bmp new file mode 100644 index 0000000..9c500c0 Binary files /dev/null and b/res/models/neru/toon06.bmp differ diff --git a/res/models/neru/toon07.bmp b/res/models/neru/toon07.bmp new file mode 100644 index 0000000..1b982fe Binary files /dev/null and b/res/models/neru/toon07.bmp differ diff --git a/res/models/neru/toon08.bmp b/res/models/neru/toon08.bmp new file mode 100644 index 0000000..1b982fe Binary files /dev/null and b/res/models/neru/toon08.bmp differ diff --git a/res/models/neru/toon09.bmp b/res/models/neru/toon09.bmp new file mode 100644 index 0000000..1b982fe Binary files /dev/null and b/res/models/neru/toon09.bmp differ diff --git a/res/models/neru/toon10.bmp b/res/models/neru/toon10.bmp new file mode 100644 index 0000000..1b982fe Binary files /dev/null and b/res/models/neru/toon10.bmp differ diff --git a/res/models/raisen/motion.vmd b/res/models/raisen/motion.vmd new file mode 100644 index 0000000..a99b58d Binary files /dev/null and b/res/models/raisen/motion.vmd differ diff --git a/res/models/raisen/raisen.pmd b/res/models/raisen/raisen.pmd new file mode 100644 index 0000000..61901a7 Binary files /dev/null and b/res/models/raisen/raisen.pmd differ diff --git a/res/models/raisen/t000.bmp b/res/models/raisen/t000.bmp new file mode 100644 index 0000000..e4d3422 Binary files /dev/null and b/res/models/raisen/t000.bmp differ diff --git a/res/models/raisen/t001.bmp b/res/models/raisen/t001.bmp new file mode 100644 index 0000000..f54fc26 Binary files /dev/null and b/res/models/raisen/t001.bmp differ diff --git a/res/models/raisen/t001.sph b/res/models/raisen/t001.sph new file mode 100644 index 0000000..8f2539b Binary files /dev/null and b/res/models/raisen/t001.sph differ diff --git a/res/models/raisen/t002.bmp b/res/models/raisen/t002.bmp new file mode 100644 index 0000000..5c97c4d Binary files /dev/null and b/res/models/raisen/t002.bmp differ diff --git a/res/models/raisen/t003.bmp b/res/models/raisen/t003.bmp new file mode 100644 index 0000000..806e0ce Binary files /dev/null and b/res/models/raisen/t003.bmp differ diff --git a/res/models/raisen/t004.bmp b/res/models/raisen/t004.bmp new file mode 100644 index 0000000..3356cb1 Binary files /dev/null and b/res/models/raisen/t004.bmp differ diff --git a/res/models/raisen/t005.bmp b/res/models/raisen/t005.bmp new file mode 100644 index 0000000..b8423f1 Binary files /dev/null and b/res/models/raisen/t005.bmp differ diff --git a/res/models/raisen/t006.bmp b/res/models/raisen/t006.bmp new file mode 100644 index 0000000..200ef36 Binary files /dev/null and b/res/models/raisen/t006.bmp differ diff --git a/res/models/raisen/t007.bmp b/res/models/raisen/t007.bmp new file mode 100644 index 0000000..8deb2aa Binary files /dev/null and b/res/models/raisen/t007.bmp differ diff --git a/res/models/raisen/t008.bmp b/res/models/raisen/t008.bmp new file mode 100644 index 0000000..3b2f82b Binary files /dev/null and b/res/models/raisen/t008.bmp differ diff --git a/res/models/raisen/t008.sph b/res/models/raisen/t008.sph new file mode 100644 index 0000000..c28a21d Binary files /dev/null and b/res/models/raisen/t008.sph differ diff --git a/res/models/raisen/t009.bmp b/res/models/raisen/t009.bmp new file mode 100644 index 0000000..e8d30a0 Binary files /dev/null and b/res/models/raisen/t009.bmp differ diff --git a/res/models/raisen/t010.bmp b/res/models/raisen/t010.bmp new file mode 100644 index 0000000..8f9465c Binary files /dev/null and b/res/models/raisen/t010.bmp differ diff --git a/res/models/raisen/t011.bmp b/res/models/raisen/t011.bmp new file mode 100644 index 0000000..855199e Binary files /dev/null and b/res/models/raisen/t011.bmp differ diff --git a/res/models/raisen/t011.sph b/res/models/raisen/t011.sph new file mode 100644 index 0000000..bce8ef8 Binary files /dev/null and b/res/models/raisen/t011.sph differ diff --git a/res/models/raisen/t012.bmp b/res/models/raisen/t012.bmp new file mode 100644 index 0000000..f911d3d Binary files /dev/null and b/res/models/raisen/t012.bmp differ diff --git a/res/models/raisen/t013.bmp b/res/models/raisen/t013.bmp new file mode 100644 index 0000000..b252c00 Binary files /dev/null and b/res/models/raisen/t013.bmp differ diff --git a/res/models/raisen/t014.bmp b/res/models/raisen/t014.bmp new file mode 100644 index 0000000..10f74df Binary files /dev/null and b/res/models/raisen/t014.bmp differ diff --git a/res/models/raisen/t015.bmp b/res/models/raisen/t015.bmp new file mode 100644 index 0000000..ff10a37 Binary files /dev/null and b/res/models/raisen/t015.bmp differ diff --git a/res/models/raisen/t016.bmp b/res/models/raisen/t016.bmp new file mode 100644 index 0000000..65927a5 Binary files /dev/null and b/res/models/raisen/t016.bmp differ diff --git a/res/models/raisen/t017.bmp b/res/models/raisen/t017.bmp new file mode 100644 index 0000000..225b109 Binary files /dev/null and b/res/models/raisen/t017.bmp differ diff --git a/res/models/raisen/t018.bmp b/res/models/raisen/t018.bmp new file mode 100644 index 0000000..2526ac1 Binary files /dev/null and b/res/models/raisen/t018.bmp differ diff --git a/res/models/raisen/t019.bmp b/res/models/raisen/t019.bmp new file mode 100644 index 0000000..267f9bf Binary files /dev/null and b/res/models/raisen/t019.bmp differ diff --git a/res/models/raisen/t020.bmp b/res/models/raisen/t020.bmp new file mode 100644 index 0000000..5e7104c Binary files /dev/null and b/res/models/raisen/t020.bmp differ diff --git a/res/models/raisen/t021.bmp b/res/models/raisen/t021.bmp new file mode 100644 index 0000000..ed7a0c1 Binary files /dev/null and b/res/models/raisen/t021.bmp differ diff --git a/res/models/raisen/t022.bmp b/res/models/raisen/t022.bmp new file mode 100644 index 0000000..61f95b1 Binary files /dev/null and b/res/models/raisen/t022.bmp differ diff --git a/res/models/raisen/t023.bmp b/res/models/raisen/t023.bmp new file mode 100644 index 0000000..995f2ea Binary files /dev/null and b/res/models/raisen/t023.bmp differ diff --git a/res/models/rin/motion.vmd b/res/models/rin/motion.vmd new file mode 100644 index 0000000..a99b58d Binary files /dev/null and b/res/models/rin/motion.vmd differ diff --git a/res/models/rin/rin.pmd b/res/models/rin/rin.pmd new file mode 100644 index 0000000..59b86ec Binary files /dev/null and b/res/models/rin/rin.pmd differ diff --git a/res/models/rin/tex_body2.tga b/res/models/rin/tex_body2.tga new file mode 100644 index 0000000..92c632d Binary files /dev/null and b/res/models/rin/tex_body2.tga differ diff --git a/res/models/rin/tex_eyes2.tga b/res/models/rin/tex_eyes2.tga new file mode 100644 index 0000000..966306e Binary files /dev/null and b/res/models/rin/tex_eyes2.tga differ diff --git a/res/models/rin/tex_eyes2base.tga b/res/models/rin/tex_eyes2base.tga new file mode 100644 index 0000000..8304aa7 Binary files /dev/null and b/res/models/rin/tex_eyes2base.tga differ diff --git a/res/models/rin/tex_fuku0.tga b/res/models/rin/tex_fuku0.tga new file mode 100644 index 0000000..63c6d9f Binary files /dev/null and b/res/models/rin/tex_fuku0.tga differ diff --git a/res/models/rin/tex_kami0.tga b/res/models/rin/tex_kami0.tga new file mode 100644 index 0000000..2d6bdc3 Binary files /dev/null and b/res/models/rin/tex_kami0.tga differ diff --git a/res/models/rin/tex_kami1.tga b/res/models/rin/tex_kami1.tga new file mode 100644 index 0000000..cfd6b17 Binary files /dev/null and b/res/models/rin/tex_kami1.tga differ diff --git a/res/models/rin/tex_kami2.tga b/res/models/rin/tex_kami2.tga new file mode 100644 index 0000000..409d0b7 Binary files /dev/null and b/res/models/rin/tex_kami2.tga differ diff --git a/res/models/rin/tex_kao.tga b/res/models/rin/tex_kao.tga new file mode 100644 index 0000000..f3d873b Binary files /dev/null and b/res/models/rin/tex_kao.tga differ diff --git a/res/models/rin/tex_nafuda.tga b/res/models/rin/tex_nafuda.tga new file mode 100644 index 0000000..ad00f78 Binary files /dev/null and b/res/models/rin/tex_nafuda.tga differ diff --git a/res/models/rin/tex_pants.tga b/res/models/rin/tex_pants.tga new file mode 100644 index 0000000..91840ed Binary files /dev/null and b/res/models/rin/tex_pants.tga differ diff --git a/res/models/rin/tex_skirt.tga b/res/models/rin/tex_skirt.tga new file mode 100644 index 0000000..1b1fc8d Binary files /dev/null and b/res/models/rin/tex_skirt.tga differ diff --git a/res/models/rin/tex_taitu.tga b/res/models/rin/tex_taitu.tga new file mode 100644 index 0000000..ffd7d48 Binary files /dev/null and b/res/models/rin/tex_taitu.tga differ diff --git a/res/models/rin/tex_uwabaki2.tga b/res/models/rin/tex_uwabaki2.tga new file mode 100644 index 0000000..2c749d4 Binary files /dev/null and b/res/models/rin/tex_uwabaki2.tga differ diff --git a/res/models/rin/toon0.bmp b/res/models/rin/toon0.bmp new file mode 100644 index 0000000..1b982fe Binary files /dev/null and b/res/models/rin/toon0.bmp differ diff --git a/res/models/rin/toon01.bmp b/res/models/rin/toon01.bmp new file mode 100644 index 0000000..08950ab Binary files /dev/null and b/res/models/rin/toon01.bmp differ diff --git a/res/models/rin/toon02.bmp b/res/models/rin/toon02.bmp new file mode 100644 index 0000000..9c39cd5 Binary files /dev/null and b/res/models/rin/toon02.bmp differ diff --git a/res/models/rin/toon03.bmp b/res/models/rin/toon03.bmp new file mode 100644 index 0000000..093094e Binary files /dev/null and b/res/models/rin/toon03.bmp differ diff --git a/res/models/rin/toon04.bmp b/res/models/rin/toon04.bmp new file mode 100644 index 0000000..2fbb80d Binary files /dev/null and b/res/models/rin/toon04.bmp differ diff --git a/res/models/rin/toon05.bmp b/res/models/rin/toon05.bmp new file mode 100644 index 0000000..136a709 Binary files /dev/null and b/res/models/rin/toon05.bmp differ diff --git a/res/models/rin/toon06.bmp b/res/models/rin/toon06.bmp new file mode 100644 index 0000000..9c500c0 Binary files /dev/null and b/res/models/rin/toon06.bmp differ diff --git a/res/models/rin/toon07.bmp b/res/models/rin/toon07.bmp new file mode 100644 index 0000000..1b982fe Binary files /dev/null and b/res/models/rin/toon07.bmp differ diff --git a/res/models/rin/toon08.bmp b/res/models/rin/toon08.bmp new file mode 100644 index 0000000..1b982fe Binary files /dev/null and b/res/models/rin/toon08.bmp differ diff --git a/res/models/rin/toon09.bmp b/res/models/rin/toon09.bmp new file mode 100644 index 0000000..1b982fe Binary files /dev/null and b/res/models/rin/toon09.bmp differ diff --git a/res/models/rin/toon10.bmp b/res/models/rin/toon10.bmp new file mode 100644 index 0000000..1b982fe Binary files /dev/null and b/res/models/rin/toon10.bmp differ diff --git a/res/models/test.vmd b/res/models/test.vmd new file mode 100644 index 0000000..d308aa7 Binary files /dev/null and b/res/models/test.vmd differ diff --git a/res/models/yuki/tex_yukibody.bmp b/res/models/yuki/tex_yukibody.bmp new file mode 100644 index 0000000..12e43f7 Binary files /dev/null and b/res/models/yuki/tex_yukibody.bmp differ diff --git a/res/models/yuki/tex_yukihead.bmp b/res/models/yuki/tex_yukihead.bmp new file mode 100644 index 0000000..10d09de Binary files /dev/null and b/res/models/yuki/tex_yukihead.bmp differ diff --git a/res/models/yuki/tex_yukireg.bmp b/res/models/yuki/tex_yukireg.bmp new file mode 100644 index 0000000..d0c2742 Binary files /dev/null and b/res/models/yuki/tex_yukireg.bmp differ diff --git a/res/models/yuki/yuki.pmd b/res/models/yuki/yuki.pmd new file mode 100644 index 0000000..fc7a783 Binary files /dev/null and b/res/models/yuki/yuki.pmd differ diff --git a/res/texture/gravel2.png b/res/texture/gravel2.png new file mode 100644 index 0000000..712e7d1 Binary files /dev/null and b/res/texture/gravel2.png differ diff --git a/res/texture/ice.png b/res/texture/ice.png new file mode 100644 index 0000000..c6f8efb Binary files /dev/null and b/res/texture/ice.png differ diff --git a/res/texture/snow.png b/res/texture/snow.png new file mode 100644 index 0000000..4ede9e7 Binary files /dev/null and b/res/texture/snow.png differ diff --git a/res/texture/stone/gabbro.png b/res/texture/stone/gabbro.png new file mode 100644 index 0000000..6d689ee Binary files /dev/null and b/res/texture/stone/gabbro.png differ diff --git a/res/texture/stone/granite.png b/res/texture/stone/granite.png new file mode 100644 index 0000000..6ba1791 Binary files /dev/null and b/res/texture/stone/granite.png differ diff --git a/res/texture/stone/sedimentary/breccia.png b/res/texture/stone/sedimentary/breccia.png new file mode 100644 index 0000000..67d70a6 Binary files /dev/null and b/res/texture/stone/sedimentary/breccia.png differ diff --git a/res/texture/stone/sedimentary/breccia32.png b/res/texture/stone/sedimentary/breccia32.png new file mode 100644 index 0000000..024ab06 Binary files /dev/null and b/res/texture/stone/sedimentary/breccia32.png differ diff --git a/res/texture/stone/sedimentary/chert.png b/res/texture/stone/sedimentary/chert.png new file mode 100644 index 0000000..30fb59e Binary files /dev/null and b/res/texture/stone/sedimentary/chert.png differ diff --git a/res/texture/stone/sedimentary/chert32.png b/res/texture/stone/sedimentary/chert32.png new file mode 100644 index 0000000..2165862 Binary files /dev/null and b/res/texture/stone/sedimentary/chert32.png differ diff --git a/res/texture/stone/sedimentary/coal.png b/res/texture/stone/sedimentary/coal.png new file mode 100644 index 0000000..c2d9d23 Binary files /dev/null and b/res/texture/stone/sedimentary/coal.png differ diff --git a/res/texture/stone/sedimentary/coal32.png b/res/texture/stone/sedimentary/coal32.png new file mode 100644 index 0000000..d34f962 Binary files /dev/null and b/res/texture/stone/sedimentary/coal32.png differ diff --git a/res/texture/stone/sedimentary/conglomerate.png b/res/texture/stone/sedimentary/conglomerate.png new file mode 100644 index 0000000..891dcda Binary files /dev/null and b/res/texture/stone/sedimentary/conglomerate.png differ diff --git a/res/texture/stone/sedimentary/conglomerate32.png b/res/texture/stone/sedimentary/conglomerate32.png new file mode 100644 index 0000000..f203c4d Binary files /dev/null and b/res/texture/stone/sedimentary/conglomerate32.png differ diff --git a/res/texture/stone/sedimentary/limestone.png b/res/texture/stone/sedimentary/limestone.png new file mode 100644 index 0000000..821bc73 Binary files /dev/null and b/res/texture/stone/sedimentary/limestone.png differ diff --git a/res/texture/stone/sedimentary/limestone32.png b/res/texture/stone/sedimentary/limestone32.png new file mode 100644 index 0000000..de7477f Binary files /dev/null and b/res/texture/stone/sedimentary/limestone32.png differ diff --git a/res/texture/stone/sedimentary/sandstone.png b/res/texture/stone/sedimentary/sandstone.png new file mode 100644 index 0000000..d30960c Binary files /dev/null and b/res/texture/stone/sedimentary/sandstone.png differ diff --git a/res/texture/stone/sedimentary/sandstone32.png b/res/texture/stone/sedimentary/sandstone32.png new file mode 100644 index 0000000..420faf8 Binary files /dev/null and b/res/texture/stone/sedimentary/sandstone32.png differ diff --git a/res/texture/stone/sedimentary/shale.png b/res/texture/stone/sedimentary/shale.png new file mode 100644 index 0000000..2eef904 Binary files /dev/null and b/res/texture/stone/sedimentary/shale.png differ diff --git a/res/texture/stone/sedimentary/shale32.png b/res/texture/stone/sedimentary/shale32.png new file mode 100644 index 0000000..a52b83c Binary files /dev/null and b/res/texture/stone/sedimentary/shale32.png differ diff --git a/res/texture/stone/sedimentary/siltstone.png b/res/texture/stone/sedimentary/siltstone.png new file mode 100644 index 0000000..f4ee02d Binary files /dev/null and b/res/texture/stone/sedimentary/siltstone.png differ diff --git a/res/texture/stone/sedimentary/siltstone32.png b/res/texture/stone/sedimentary/siltstone32.png new file mode 100644 index 0000000..9481b40 Binary files /dev/null and b/res/texture/stone/sedimentary/siltstone32.png differ diff --git a/res/texture/terrain-wheatgrass-lightgreen-med.png b/res/texture/terrain-wheatgrass-lightgreen-med.png new file mode 100644 index 0000000..ec4f1f2 Binary files /dev/null and b/res/texture/terrain-wheatgrass-lightgreen-med.png differ diff --git a/res/texture/water.png b/res/texture/water.png new file mode 100644 index 0000000..48ef370 Binary files /dev/null and b/res/texture/water.png differ diff --git a/res/texture/wheat.png b/res/texture/wheat.png new file mode 100644 index 0000000..504cdee Binary files /dev/null and b/res/texture/wheat.png differ 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 + * py1024gmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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 + * py1024gmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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; // 蟾ヲ雜ウシゥシォ蜈 + public PmdBone m_rightFootIK; // 蜿ウ雜ウシゥシォ蜈 + 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("蟾ヲ繧ケ蜑搾シ")) { + this.m_skirtFrontLeft = bone_array[i]; + } + if (bone_array[i].getName().equals("蟾ヲスススカスーセ蜑")) { + this.m_skirtFrontLeft = bone_array[i]; + } + if (bone_array[i].getName().equals("蜿ウ繧ケ蜑搾シ")) { + 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("蟾ヲ雜ウシゥシォ")) { + this.m_leftFootIK = bone_array[i]; + } + if (bone_array[i].getName().equals("蜿ウ雜ウシゥシォ蜈")) { + 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 + * 繝「繝シ繧キ繝ァ繝ウ縺ョ蜈磯ュ縺九i縺ョ譎ょ綾繧知s蜊倅ス阪〒謖螳壹@縺セ縺吶 + * @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; + // 謠冗判縺吶k繝輔Ξ繝シ繝繧定ィ育ョ励☆繧九 + float frame = (float) (i_position_in_msec / (100.0 / 3)); + // 遽蝗イ螟悶r髯、螟 + 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); + // 陬憺俣縺ゅj + // Vector3Lerp( &((*pBone)->m_vec3Position), + // &((*pBone)->m_vec3Position), &vec3Position, fLerpValue ); + // QuaternionSlerp( &((*pBone)->m_vec4Rotate), + // &((*pBone)->m_vec4Rotate), &vec4Rotate, fLerpValue ); + } + return; + } + + /** + * 謖螳壹ヵ繝ャ繝シ繝縺ョ繝繝シ繧ソ縺ァ陦ィ諠繧貞、牙ス「縺吶k + * + * @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; + } + + // 迴セ蝨ィ縺ョ譎る俣縺後←縺ョ繧ュ繝シ霑題セコ縺ォ縺ゅk縺 + 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 { + /** + * + */ + 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; + } + } + // 縺ェ縺代l縺ー繝輔ぃ繧、繝ォ繧定ェュ縺ソ霎シ繧薙〒繝繧ッ繧ケ繝√Ε菴懈 + 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 materials = new Vector(); + 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縺茎kinning_mat繧呈峩譁ー縺吶k繧貞他縺ウ蜃コ縺励∪縺吶 + */ + 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縺ォ螟画鋤縺励h縺 + this._pos_array.position(0); + this._nom_array.position(0); + this._tex_array.position(0); + // 縺ィ繧翫≠縺医★霆「蜀咏畑 + + // 鬆らせ蠎ァ讓吶∵ウ慕キ壹√ユ繧ッ繧ケ繝√Ε蠎ァ讓吶ョ蜷驟榊励r繧サ繝繝 + 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) { + // 繝繧ッ繧ケ繝√Ε縺ゅj縺ェ繧隠ind縺吶k + 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 + * py1024gmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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; + +/** + * 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝縺九iPMD繝輔ぃ繧、繝ォ繧定ェュ縺ソ霎シ繧繧医≧縺ォ繝ゥ繝繝励@縺毬@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 + * py1024gmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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 { + public int compare(PmdIK o1, PmdIK o2) { + return (int) (o1.getSortVal() - o2.getSortVal()); + } +} + +/** + * PmdModel繝繝シ繧ソ縺ョ譬シ邏阪け繝ゥ繧ケ縲1mdModel縺ォ髢「繧上k繝繝シ繧ソ繧呈署萓帙@縺セ縺吶 + * 謚ス雎。髢「謨ー 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(); + } + + // 鬆らせ驟榊励r繧ウ繝斐シ + 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(); + + // 繝槭ユ繝ェ繧「繝ォ驟榊励r繧ウ繝斐シ + 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]; + + // 鬆らせ繧、繝ウ繝繝繧ッ繧ケ驟榊励r繧ウ繝斐シ + 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); + // 繝懊シ繝ウ縺ョ隕ェ蟄宣未菫ゅr荳邱偵↓隱ュ縺ソ縺縺吶ョ縺ァ縲 + 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驟榊励r菴懈 + 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]; + + // 陦ィ諠驟榊励r菴懈 + 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 + * py1024gmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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 + * py1024gmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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 +{ + public int compare(BoneKeyFrame o1, BoneKeyFrame o2) + { + return (int)(o1.fFrameNo - o2.fFrameNo); + } +} + + +//------------------------------ +//陦ィ諠繧ュ繝シ繝輔Ξ繝シ繝繧ス繝シ繝育畑豈碑シ髢「謨ー +//------------------------------ +class FaceCompare implements java.util.Comparator +{ + 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 result=new Vector(); + int ulNumFaceKeyFrames=i_reader.readInt(); + + //隕丞ョ壹ヵ繝ャ繝シ繝謨ー蛻陦ィ諠繧定ェュ縺ソ霎シ縺ソ + VMD_Face[] tmp_vmd_face=new VMD_Face[ulNumFaceKeyFrames]; + for(int i=0;i result=new Vector(); + // 縺セ縺壹ッ繝「繝シ繧キ繝ァ繝ウ繝繝シ繧ソ荳ュ縺ョ繝懊シ繝ウ縺斐→縺ョ繧ュ繝シ繝輔Ξ繝シ繝謨ー繧偵き繧ヲ繝ウ繝 + final int ulNumBoneKeyFrames=i_reader.readInt(); + + + //繝懊シ繝ウ繧呈欠螳壽焚隱ュ縺ソ霎シ縺ソ + VMD_Motion[] tmp_vmd_motion=new VMD_Motion[ulNumBoneKeyFrames]; + for(int i=0;igmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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(); // 蛻晄悄蛟、縺ョ繝懊シ繝ウ繧貞次轤ケ縺ォ遘サ蜍輔&縺帙k繧医≧縺ェ陦悟 + + 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譎ゅ↓隗貞コヲ蛻カ髯舌r縺吶k縺九←縺縺 + //蠑キ蛻カ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){ + // 繧ッ繧ゥ繝シ繧ソ繝九が繝ウ縺ィ遘サ蜍募、縺九i繝懊シ繝ウ縺ョ繝ュ繝シ繧ォ繝ォ繝槭ヨ繝ェ繝繧ッ繧ケ繧剃ス懈 + 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{ + // 繧ッ繧ゥ繝シ繧ソ繝九が繝ウ縺ィ遘サ蜍募、縺九i繝懊シ繝ウ縺ョ繝ュ繝シ繧ォ繝ォ繝槭ヨ繝ェ繝繧ッ繧ケ繧剃ス懈 + 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 + * py1024gmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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 + * py1024gmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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霆ク蝗櫁サ「縺九i繧ッ繧ゥ繝シ繧ソ繝九が繝ウ縺ク + 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繧置pdate縺励※繧九↑繧峨√%縺ョ繧ウ繝シ繝峨ッ隕√i縺ェ縺? + 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++ ) + { + // 繧ィ繝輔ぉ繧ッ繧ソ縺ョ菴咲スョ縺ョ蜿門セ + + // 繝ッ繝シ繝ォ繝牙コァ讓咏ウサ縺九i豕ィ逶ョ繝弱シ繝峨ョ螻謇(繝ュ繝シ繧ォ繝ォ)蠎ァ讓咏ウサ縺ク縺ョ螟画鋤 + 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 + * py1024gmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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;igmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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 + * py1024gmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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 + * py1024gmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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; // 隕ェ繝懊シ繝ウ逡ェ蜿キ (縺ェ縺代l縺ー -1) + public int nChildNo; // 蟄舌懊シ繝ウ逡ェ蜿キ + public int cbKind; // 繝懊シ繝ウ縺ョ遞ョ鬘 + public int unIKTarget; // IK譎ゅョ繧ソ繝シ繧イ繝繝医懊シ繝ウ + public final MmdVector3 vec3Position=new MmdVector3(); // 繝「繝繝ォ蜴溽せ縺九i縺ョ菴咲スョ + + 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 + * py1024gmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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(); + //蠢隕√↑謨ー縺縺鷹榊励r遒コ菫昴@縺ェ縺翫☆縲 + if(this.ulNumVertices>this.pVertices.length){ + this.pVertices=PMD_FACE_VTX.createArray(this.ulNumVertices); + } + for(i=0;igmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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;igmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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 + * py1024gmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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(); + //蠢隕√↑謨ー縺縺鷹榊励r遒コ菫昴@縺ェ縺翫☆縲 + this.punLinkNo=new int[this.cbNumLink]; + for(int i=0;igmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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 + * py1024gmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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 + * py1024gmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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 + * py1024gmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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 + * py1024gmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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 + * py1024gmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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;igmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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 + * py1024gmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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;igmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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 + * py1024gmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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 + * py1024gmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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 +{ + ////// + // + ////// + + /** 陦悟励ョ隕∫エ蛟、縺ァ縺吶*/ + 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; + /** + * 縺薙ョ髢「謨ー縺ッ縲√が繝悶ず繧ァ繧ッ繝医ョ驟榊励r逕滓舌@縺ヲ霑斐@縺セ縺吶 + * @param i_number + * 驟榊励ョ髟キ縺 + * @return + * 譁ー縺励>繧ェ繝悶ず繧ァ繧ッ繝磯榊 + */ + public static MmdMatrix[] createArray(int i_number) + { + MmdMatrix[] ret=new MmdMatrix[i_number]; + for(int i=0;igmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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;igmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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= 1.0 ){ + temp = 1.0; + }else if( temp <= -1.0 ){ + temp = -1.0; + } + + double yRadian = Math.sin(temp); + + // 莉悶ョ蝗櫁サ「繧呈アゅa繧 + 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 + * py1024gmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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 + * py1024gmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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; + } + + // 迴セ蝨ィ縺ョ譎る俣縺後←縺ョ繧ュ繝シ霑題セコ縺ォ縺ゅk縺 + 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);//縺薙l縺サ繧薙→縺ォ縺繧九ョシ + }else{ + pvec3Pos.setValue(bone_key_frame[lKey0].vec3Position); + pvec4Rot.setValue(bone_key_frame[lKey0].vec4Rotate); + } + } + /** + * @author 繧縺ュ縺繧峨♀ 縺輔s + * @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) { + // 縺ゅk遞句コヲ蟆上&縺上↑縺」縺溘i騾先ャ。繧オ繝シ繝√ゅ%縺ョ縺ェ 縺九↓隕九▽縺九k縺ッ縺壹↑繧薙□縲 + 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 + * py1024gmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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 + * py1024gmail.com + * http://www.nicovideo.jp/watch/sm7398691 + * + * + * The MIT License + * Copyright (C)2008-2012 nyatla + * nyatla39gmail.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 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>> nodes = new HashMap>>(); + 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>()); + nodes.get(ix).put(iy, new HashMap()); + // 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>()); + } + if (!nodes.get(ix).containsKey(iy)) { + nodes.get(ix).put(iy, new HashMap()); + } + 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 { + + private class BonesIterator implements Iterator { + private BoneSet set; + private Iterator 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 iterator() { + return new BonesIterator(this); + } + + public int getBoneCount() { + int n = 0; + Iterator it = iterator(); + while (it.hasNext()) { + it.next(); + n++; + } + return n; + } + + public Bone getBone(int i) { + int j = 0; + Iterator 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 implements IProvider { + public CacheProvider(IProvider parent) { + this.parent = parent; + } + + private T obj; + private IProvider 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 { + 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 implements IProvider { + 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 implements IProvider { + 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> ranges = new ArrayList>(); + private ArrayList> visibleRanges = new ArrayList>(); + + 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()); + } + for (int d = 0; d < 32; d++) { + visibleRanges.add(new ArrayList()); + } + 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 liveEntities = new HashMap(); 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 names = new HashMap(); - private HashMap types = new HashMap(); + private HashMap opaque = new HashMap(); + private HashMap canMoveThrough = new HashMap(); + private HashMap types = new HashMap(); + private HashMap ids = new HashMap(); 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 chunks = new ArrayBlockingQueue(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 disposable = new ArrayBlockingQueue(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 precompiled = new HashMap(); + + 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 { 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 { 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 { 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 chunks = new ArrayBlockingQueue(256); + private ArrayBlockingQueue chunks = new ArrayBlockingQueue(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 chunks = new HashMap(); - protected HashMap>> iChunks = new HashMap>>(); + public HashMap>> iChunks = new HashMap>>(); 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()); } - 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 timeManagedBlocks = new HashMap(); + public ArrayList droppedEntities = new ArrayList(); + + 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 regionMap = new HashMap(); - private ConcurrentHashMap ticks = new ConcurrentHashMap(); + private HashMap regionMap = new HashMap(); + + 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 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 gcKeys = new ArrayList(); + + 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 map = new HashMap(); + private HashMap map = new HashMap(); private List loading = new ArrayList(); private List queue = new ArrayList(); @@ -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 lines = new HashMap(); + 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 getSideLines(WorldProvider provider) { + ArrayList sideLines; + sideLines = getSideLines(provider, z + 1); + sideLines.addAll(getSideLines(provider, z - 1)); + return sideLines; + } + + public ArrayList getSideLines(WorldProvider provider, int z) { + ArrayList sideLines = new ArrayList(); + 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 levels = new HashMap(); + 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 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 info; + + public RemoteWorld() { + info = new CacheProvider(new RemoteProvider() { + @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 list = new HashMap(); + private static HashMap currentSpriteList = new HashMap(); + private static HashMap offsets = new HashMap(); + 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(); + } } -- cgit v1.2.3