diff --git a/POT/assets.zip b/POT/assets.zip index 47895ef..7f92322 100755 Binary files a/POT/assets.zip and b/POT/assets.zip differ diff --git a/POT/src/com/pot/client/renderer/model/POTModels.java b/POT/src/com/pot/client/renderer/model/POTModels.java index cb98a5b..e9ede75 100755 --- a/POT/src/com/pot/client/renderer/model/POTModels.java +++ b/POT/src/com/pot/client/renderer/model/POTModels.java @@ -18,7 +18,7 @@ public class POTModels implements IModResource { @Override public void load(Mod mod, ResourceManager manager) { - registerJSONModel(manager, R.getResPath(ModPOT.MOD_ID, "models/physicTest/"), EntityBipedTest.class); + registerJSONModel(manager, R.getResPath(ModPOT.MOD_ID, "models/physicTest2/"), EntityBipedTest.class); registerJSONModel(manager, R.getResPath(ModPOT.MOD_ID, "models/animTest/"), EntityTest.class); } diff --git a/VoxelEngine/assets.zip b/VoxelEngine/assets.zip index 1f5940f..7438523 100755 Binary files a/VoxelEngine/assets.zip and b/VoxelEngine/assets.zip differ diff --git a/VoxelEngine/src/com/grillecube/client/opengl/object/ImageUtils.java b/VoxelEngine/src/com/grillecube/client/opengl/object/ImageUtils.java index e7cb4e1..c777712 100755 --- a/VoxelEngine/src/com/grillecube/client/opengl/object/ImageUtils.java +++ b/VoxelEngine/src/com/grillecube/client/opengl/object/ImageUtils.java @@ -62,8 +62,11 @@ public static byte[] getImagePixels(BufferedImage img) { * @param atlas */ public static void exportPNGImage(String filepath, BufferedImage image) { + exportPNGImage(new File(filepath), image); + } + + public static void exportPNGImage(File file, BufferedImage image) { try { - File file = new File(filepath); if (!file.exists()) { file.mkdirs(); file.createNewFile(); diff --git a/VoxelEngine/src/com/grillecube/client/renderer/gui/components/GuiViewWorld.java b/VoxelEngine/src/com/grillecube/client/renderer/gui/components/GuiViewWorld.java index 8551039..33d6195 100755 --- a/VoxelEngine/src/com/grillecube/client/renderer/gui/components/GuiViewWorld.java +++ b/VoxelEngine/src/com/grillecube/client/renderer/gui/components/GuiViewWorld.java @@ -9,14 +9,12 @@ import com.grillecube.client.renderer.gui.GuiRenderer; import com.grillecube.client.renderer.gui.event.GuiEventAspectRatio; import com.grillecube.client.renderer.gui.event.GuiListener; -import com.grillecube.client.renderer.world.WorldRenderer; import com.grillecube.client.renderer.world.flat.WorldFlatRenderer; -import com.grillecube.common.world.WorldFlat; public class GuiViewWorld extends GuiView { private GuiTexture txWorld; - private WorldRenderer worldRenderer; + private WorldFlatRenderer worldRenderer; private CameraProjective camera; private int worldID; @@ -84,7 +82,7 @@ protected void onUpdate() { this.worldRenderer.getCamera().setAspect(aspect); } - public final WorldRenderer getWorldRenderer() { + public final WorldFlatRenderer getWorldRenderer() { return (this.worldRenderer); } } diff --git a/VoxelEngine/src/com/grillecube/client/renderer/model/ModelSkeleton.java b/VoxelEngine/src/com/grillecube/client/renderer/model/ModelSkeleton.java index 2a1cdc3..69165ba 100755 --- a/VoxelEngine/src/com/grillecube/client/renderer/model/ModelSkeleton.java +++ b/VoxelEngine/src/com/grillecube/client/renderer/model/ModelSkeleton.java @@ -60,6 +60,17 @@ public final Bone getBone(String boneName) { return (this.bonesMap.get(boneName)); } + /** get a bone by it id */ + public final Bone getBone(int boneID) { + return (boneID < 0 || boneID >= this.bonesList.size() ? null : this.bonesList.get(boneID)); + } + + /** get a bone by it id */ + public final String getBoneName(int boneID) { + Bone bone = this.getBone(boneID); + return (bone == null ? null : bone.getName()); + } + /** remove a bone */ public final void removeBone(Bone bone) { this.bonesMap.remove(bone.getName()); diff --git a/VoxelEngine/src/com/grillecube/client/renderer/model/animation/Bone.java b/VoxelEngine/src/com/grillecube/client/renderer/model/animation/Bone.java index 35e2f51..2877b9a 100755 --- a/VoxelEngine/src/com/grillecube/client/renderer/model/animation/Bone.java +++ b/VoxelEngine/src/com/grillecube/client/renderer/model/animation/Bone.java @@ -28,7 +28,7 @@ public class Bone { private final Matrix4f localBindTransform; private final Matrix4f inverseBindTransform; private final Vector3f translate; - private final Vector3f rotate; + private final Quaternion rotate; /** * @param ModelSkeleton @@ -43,7 +43,7 @@ public Bone(ModelSkeleton modelSkeleton, String name) { this.localBindTransform = new Matrix4f(); this.inverseBindTransform = new Matrix4f(); this.translate = new Vector3f(); - this.rotate = new Vector3f(0.0f, 0.0f, 0.0f); + this.rotate = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); } /** get the joint name */ @@ -69,10 +69,15 @@ public String addChild(String child) { } /** return true if this joint has a children */ - public boolean hasChildren() { + public final boolean hasChildren() { return (this.childrenNames != null && this.childrenNames.size() > 0); } + /** return true if this joint has a parent */ + public final boolean hasParent() { + return (this.parentName != null); + } + /** remove a child of this joint */ public void removeChild(String childName) { this.childrenNames.remove(childName); @@ -112,15 +117,16 @@ public final void setLocalBindTransform(Matrix4f setLocalBindTransform) { public final void setLocalBindTransform(float x, float y, float z, float rx, float ry, float rz, float rw) { this.translate.set(x, y, z); - Quaternion.toEulerAngle(this.rotate, rx, ry, rz, rw); + this.rotate.set(rx, ry, rz, rw); + Vector3f rot = Quaternion.toEulerAngle(rx, ry, rz, rw); this.localBindTransform.setIdentity(); this.localBindTransform.translate(x, y, z); - this.localBindTransform.rotateXYZ(this.rotate); + this.localBindTransform.rotateXYZ(rot); this.localBindTransform.translate(this.translate); } - public final Vector3f getLocalRotation() { + public final Quaternion getLocalRotation() { return (this.rotate); } diff --git a/VoxelEngine/src/com/grillecube/client/renderer/model/editor/ModelEditor.java b/VoxelEngine/src/com/grillecube/client/renderer/model/editor/ModelEditor.java index 69abd03..91a548d 100755 --- a/VoxelEngine/src/com/grillecube/client/renderer/model/editor/ModelEditor.java +++ b/VoxelEngine/src/com/grillecube/client/renderer/model/editor/ModelEditor.java @@ -4,6 +4,9 @@ import com.grillecube.client.renderer.model.editor.gui.GuiModelEditor; import com.grillecube.client.renderer.model.editor.gui.GuiModelView; import com.grillecube.client.renderer.model.editor.gui.toolbox.GuiToolbox; +import com.grillecube.client.renderer.model.json.JSONModelExporter; +import com.grillecube.common.Logger; +import com.grillecube.common.resources.R; public class ModelEditor { @@ -40,7 +43,15 @@ private void run() { try { engine.loop(); } catch (InterruptedException e) { - e.printStackTrace(); + Logger.get().log(Logger.Level.ERROR, "That's unfortunate... VoxelEngine crashed.", e.getLocalizedMessage()); + String path = R.getResPath("models/tmp/" + System.currentTimeMillis()); + try { + Logger.get().log(Logger.Level.ERROR, "Trying to save model...", path); + JSONModelExporter.export(guiModelEditor.getSelectedModel(), path); + } catch (Exception exception) { + Logger.get().log(Logger.Level.ERROR, "Couldn't save model... sorry bro", + exception.getLocalizedMessage()); + } } engine.deinitialize(); } diff --git a/VoxelEngine/src/com/grillecube/client/renderer/model/editor/camera/CameraToolExtrude.java b/VoxelEngine/src/com/grillecube/client/renderer/model/editor/camera/CameraToolExtrude.java index 97f5a6c..d01e31d 100755 --- a/VoxelEngine/src/com/grillecube/client/renderer/model/editor/camera/CameraToolExtrude.java +++ b/VoxelEngine/src/com/grillecube/client/renderer/model/editor/camera/CameraToolExtrude.java @@ -233,14 +233,14 @@ private final void updateSelection() { Vector3i o1 = BlockRenderer.VERTICES[BlockRenderer.FACES_VERTICES[face.getID()][1]]; Vector3i o2 = BlockRenderer.VERTICES[BlockRenderer.FACES_VERTICES[face.getID()][2]]; Vector3i o3 = BlockRenderer.VERTICES[BlockRenderer.FACES_VERTICES[face.getID()][3]]; - this.quad[0].set(this.getX() + this.getWidth() * o0.x, this.getY() + this.getHeight() * o0.y, - this.getZ() + this.getDepth() * o0.z); - this.quad[1].set(this.getX() + this.getWidth() * o1.x, this.getY() + this.getHeight() * o1.y, - this.getZ() + this.getDepth() * o1.z); - this.quad[2].set(this.getX() + this.getWidth() * o2.x, this.getY() + this.getHeight() * o2.y, - this.getZ() + this.getDepth() * o2.z); - this.quad[3].set(this.getX() + this.getWidth() * o3.x, this.getY() + this.getHeight() * o3.y, - this.getZ() + this.getDepth() * o3.z); + this.quad[0].set(this.getPositionX() + this.getSizeX() * o0.x, this.getPositionY() + this.getSizeY() * o0.y, + this.getPositionZ() + this.getSizeZ() * o0.z); + this.quad[1].set(this.getPositionX() + this.getSizeX() * o1.x, this.getPositionY() + this.getSizeY() * o1.y, + this.getPositionZ() + this.getSizeZ() * o1.z); + this.quad[2].set(this.getPositionX() + this.getSizeX() * o2.x, this.getPositionY() + this.getSizeY() * o2.y, + this.getPositionZ() + this.getSizeZ() * o2.z); + this.quad[3].set(this.getPositionX() + this.getSizeX() * o3.x, this.getPositionY() + this.getSizeY() * o3.y, + this.getPositionZ() + this.getSizeZ() * o3.z); LineRendererFactory factory = super.guiModelView.getWorldRenderer().getLineRendererFactory(); for (Line line : this.lines) { diff --git a/VoxelEngine/src/com/grillecube/client/renderer/model/editor/camera/CameraToolPaint.java b/VoxelEngine/src/com/grillecube/client/renderer/model/editor/camera/CameraToolPaint.java index 3716e3d..9d8204b 100755 --- a/VoxelEngine/src/com/grillecube/client/renderer/model/editor/camera/CameraToolPaint.java +++ b/VoxelEngine/src/com/grillecube/client/renderer/model/editor/camera/CameraToolPaint.java @@ -171,14 +171,14 @@ private final void updateSelection() { Vector3i o1 = BlockRenderer.VERTICES[BlockRenderer.FACES_VERTICES[face.getID()][1]]; Vector3i o2 = BlockRenderer.VERTICES[BlockRenderer.FACES_VERTICES[face.getID()][2]]; Vector3i o3 = BlockRenderer.VERTICES[BlockRenderer.FACES_VERTICES[face.getID()][3]]; - this.quad[0].set(this.getX() + this.getWidth() * o0.x, this.getY() + this.getHeight() * o0.y, - this.getZ() + this.getDepth() * o0.z); - this.quad[1].set(this.getX() + this.getWidth() * o1.x, this.getY() + this.getHeight() * o1.y, - this.getZ() + this.getDepth() * o1.z); - this.quad[2].set(this.getX() + this.getWidth() * o2.x, this.getY() + this.getHeight() * o2.y, - this.getZ() + this.getDepth() * o2.z); - this.quad[3].set(this.getX() + this.getWidth() * o3.x, this.getY() + this.getHeight() * o3.y, - this.getZ() + this.getDepth() * o3.z); + this.quad[0].set(this.getPositionX() + this.getSizeX() * o0.x, this.getPositionY() + this.getSizeY() * o0.y, + this.getPositionZ() + this.getSizeZ() * o0.z); + this.quad[1].set(this.getPositionX() + this.getSizeX() * o1.x, this.getPositionY() + this.getSizeY() * o1.y, + this.getPositionZ() + this.getSizeZ() * o1.z); + this.quad[2].set(this.getPositionX() + this.getSizeX() * o2.x, this.getPositionY() + this.getSizeY() * o2.y, + this.getPositionZ() + this.getSizeZ() * o2.z); + this.quad[3].set(this.getPositionX() + this.getSizeX() * o3.x, this.getPositionY() + this.getSizeY() * o3.y, + this.getPositionZ() + this.getSizeZ() * o3.z); LineRendererFactory factory = super.guiModelView.getWorldRenderer().getLineRendererFactory(); for (Line line : this.lines) { diff --git a/VoxelEngine/src/com/grillecube/client/renderer/model/editor/gui/toolbox/GuiToolbox.java b/VoxelEngine/src/com/grillecube/client/renderer/model/editor/gui/toolbox/GuiToolbox.java index 0330499..c33bd5b 100755 --- a/VoxelEngine/src/com/grillecube/client/renderer/model/editor/gui/toolbox/GuiToolbox.java +++ b/VoxelEngine/src/com/grillecube/client/renderer/model/editor/gui/toolbox/GuiToolbox.java @@ -1,5 +1,7 @@ package com.grillecube.client.renderer.model.editor.gui.toolbox; +import java.io.IOException; + import com.grillecube.client.renderer.gui.components.Gui; import com.grillecube.client.renderer.gui.components.GuiButton; import com.grillecube.client.renderer.gui.components.GuiColoredQuad; @@ -17,6 +19,7 @@ import com.grillecube.client.renderer.model.editor.mesher.EditableModel; import com.grillecube.client.renderer.model.instance.ModelInstance; import com.grillecube.client.renderer.model.json.JSONEditableModelInitializer; +import com.grillecube.client.renderer.model.json.JSONModelExporter; import com.grillecube.common.Logger; import com.grillecube.common.resources.R; import com.grillecube.common.utils.Color; @@ -115,7 +118,13 @@ public void invoke(GuiSpinnerEventPick event) { } private final void saveCurrentModel() { - // TODO + try { + String path = R.getResPath("models/" + System.currentTimeMillis()); + JSONModelExporter.export(this.getSelectedModel(), path); + Logger.get().log(Logger.Level.FINE, "model saved properly at", path); + } catch (Exception e) { + Logger.get().log(Logger.Level.ERROR, "error when exporting model", e.getMessage()); + } } private final void createNewModel() { diff --git a/VoxelEngine/src/com/grillecube/client/renderer/model/editor/gui/toolbox/GuiToolboxModel.java b/VoxelEngine/src/com/grillecube/client/renderer/model/editor/gui/toolbox/GuiToolboxModel.java index 18ec9f2..c88b50c 100755 --- a/VoxelEngine/src/com/grillecube/client/renderer/model/editor/gui/toolbox/GuiToolboxModel.java +++ b/VoxelEngine/src/com/grillecube/client/renderer/model/editor/gui/toolbox/GuiToolboxModel.java @@ -38,6 +38,8 @@ public class GuiToolboxModel extends GuiView { public GuiToolboxModel(ModelInstance modelInstance) { super(); + this.setHoverable(false); + this.modelInstance = modelInstance; GuiParameter center = new GuiTextParameterTextCenterBox(); diff --git a/VoxelEngine/src/com/grillecube/client/renderer/model/editor/gui/toolbox/GuiToolboxModelPanelSkeleton.java b/VoxelEngine/src/com/grillecube/client/renderer/model/editor/gui/toolbox/GuiToolboxModelPanelSkeleton.java index 0331fbc..5683f24 100755 --- a/VoxelEngine/src/com/grillecube/client/renderer/model/editor/gui/toolbox/GuiToolboxModelPanelSkeleton.java +++ b/VoxelEngine/src/com/grillecube/client/renderer/model/editor/gui/toolbox/GuiToolboxModelPanelSkeleton.java @@ -16,6 +16,7 @@ import com.grillecube.client.renderer.model.editor.gui.GuiPromptEditor; import com.grillecube.client.renderer.model.editor.gui.GuiSpinnerEditor; import com.grillecube.common.maths.Matrix4f; +import com.grillecube.common.maths.Quaternion; import com.grillecube.common.maths.Vector3f; public class GuiToolboxModelPanelSkeleton extends GuiToolboxModelPanel { @@ -131,7 +132,7 @@ public void invoke(GuiEventClick event) { this.posY.getPrompt().setHeldText(String.valueOf(bone.getLocalTranslation().y)); this.posZ.getPrompt().setHeldText(String.valueOf(bone.getLocalTranslation().z)); - Vector3f rot = bone.getLocalRotation(); + Vector3f rot = Quaternion.toEulerAngle(bone.getLocalRotation()); this.rotX.getPrompt().setHeldText(String.valueOf(rot.x)); this.rotY.getPrompt().setHeldText(String.valueOf(rot.y)); this.rotZ.getPrompt().setHeldText(String.valueOf(rot.z)); @@ -145,11 +146,14 @@ public void invoke(GuiPromptEventHeldTextChanged event) { float ry = rotY.getPrompt().asFloat(0.0f); float rz = rotZ.getPrompt().asFloat(0.0f); localBindTransform.rotateXYZ(rx, ry, rz); + Quaternion q = Quaternion.toQuaternion(rx, ry, rz); + getSelectedBone().getLocalRotation().set(q); + float x = posX.getPrompt().asFloat(0.0f); float y = posY.getPrompt().asFloat(0.0f); float z = posZ.getPrompt().asFloat(0.0f); - System.out.println(x + " : " + y + " : " + z); localBindTransform.translate(-x, -y, -z); + getSelectedBone().getLocalTranslation().set(x, y, z); getSelectedBone().setLocalBindTransform(localBindTransform); getSelectedBone().calcInverseBindTransform(); } diff --git a/VoxelEngine/src/com/grillecube/client/renderer/model/editor/mesher/ModelMesherCull.java b/VoxelEngine/src/com/grillecube/client/renderer/model/editor/mesher/ModelMesherCull.java index 8bdba44..81d3bba 100755 --- a/VoxelEngine/src/com/grillecube/client/renderer/model/editor/mesher/ModelMesherCull.java +++ b/VoxelEngine/src/com/grillecube/client/renderer/model/editor/mesher/ModelMesherCull.java @@ -49,7 +49,6 @@ public final void doGenerate(EditableModel editableModel, Stack /** generate the model mesh */ private final void generateMeshAndSkin(EditableModel editableModel, ArrayList planes, Stack vertices, Stack indices, HashMap skinsData) { - boolean[] ba = new boolean[] { false, false, false, false, false, false }; ModelSkinPacker.fit(planes); int txWidth = 0, txHeight = 0; diff --git a/VoxelEngine/src/com/grillecube/client/renderer/model/json/JSONModelExporter.java b/VoxelEngine/src/com/grillecube/client/renderer/model/json/JSONModelExporter.java index ea9149b..a7ead11 100755 --- a/VoxelEngine/src/com/grillecube/client/renderer/model/json/JSONModelExporter.java +++ b/VoxelEngine/src/com/grillecube/client/renderer/model/json/JSONModelExporter.java @@ -4,46 +4,163 @@ import java.io.File; import java.io.FileWriter; import java.io.IOException; +import java.nio.ByteBuffer; import java.nio.file.Path; import java.nio.file.Paths; import org.json.JSONArray; import org.json.JSONObject; +import com.grillecube.client.opengl.object.ImageUtils; +import com.grillecube.client.renderer.model.ModelMesh; import com.grillecube.client.renderer.model.ModelSkin; +import com.grillecube.client.renderer.model.animation.Bone; import com.grillecube.client.renderer.model.animation.BoneTransform; import com.grillecube.client.renderer.model.animation.KeyFrame; import com.grillecube.client.renderer.model.animation.ModelSkeletonAnimation; import com.grillecube.client.renderer.model.editor.mesher.EditableModel; +import com.grillecube.client.renderer.model.editor.mesher.ModelBlockData; +import com.grillecube.common.maths.Maths; public class JSONModelExporter { /** - * initializer override + * export the given model to the given dirpath * - * @throws IOException + * @throws Exception */ - public final void export(EditableModel model, String dirpath) throws IOException { + public static final void export(EditableModel editableModel, String dirPath) throws Exception { + + if (editableModel == null) { + throw new Exception("null Model in export()"); + } + JSONObject jsonInfo = new JSONObject(); // name - jsonInfo.put("name", model.getName()); + jsonInfo.put("name", editableModel.getName()); // mesh - jsonInfo.put("mesh", "mesh/mesh.json"); + String meshPath = "mesh/mesh.json"; + ModelMesh mesh = editableModel.getMesh(); + JSONObject jsonMesh = new JSONObject(); + + ByteBuffer vertices = mesh.getVertices(); + JSONArray jsonVertices = new JSONArray(); + float precision = 1000.0f; + while (vertices.hasRemaining()) { + float x = Maths.approximatate(vertices.getFloat(), precision); + float y = Maths.approximatate(vertices.getFloat(), precision); + float z = Maths.approximatate(vertices.getFloat(), precision); + float u = Maths.approximatate(vertices.getFloat(), precision); + float v = Maths.approximatate(vertices.getFloat(), precision); + float nx = Maths.approximatate(vertices.getFloat(), precision); + float ny = Maths.approximatate(vertices.getFloat(), precision); + float nz = Maths.approximatate(vertices.getFloat(), precision); + String b1 = editableModel.getSkeleton().getBoneName(vertices.getInt()); + String b2 = editableModel.getSkeleton().getBoneName(vertices.getInt()); + String b3 = editableModel.getSkeleton().getBoneName(vertices.getInt()); + float w1 = Maths.approximatate(vertices.getFloat(), precision); + float w2 = Maths.approximatate(vertices.getFloat(), precision); + float w3 = Maths.approximatate(vertices.getFloat(), precision); + float ao = Maths.approximatate(vertices.getFloat(), precision); + + jsonVertices.put(x); + jsonVertices.put(y); + jsonVertices.put(z); + jsonVertices.put(u); + jsonVertices.put(v); + jsonVertices.put(nx); + jsonVertices.put(ny); + jsonVertices.put(nz); + jsonVertices.put(b1); + jsonVertices.put(b2); + jsonVertices.put(b3); + jsonVertices.put(w1); + jsonVertices.put(w2); + jsonVertices.put(w3); + jsonVertices.put(ao); + } + jsonMesh.put("vertices", jsonVertices); + + ByteBuffer indices = mesh.getIndices(); + JSONArray jsonIndices = new JSONArray(); + while (indices.hasRemaining()) { + short i = indices.getShort(); + jsonIndices.put(i); + } + jsonMesh.put("indices", jsonIndices); + writeJSON(jsonMesh, dirPath, meshPath); + jsonInfo.put("mesh", meshPath); // skeleton - jsonInfo.put("skeleton", "skeleton/skeleton.json"); + String skeletonPath = "skeleton/skeleton.json"; + jsonInfo.put("skeleton", skeletonPath); + JSONObject jsonSkeleton = new JSONObject(); + JSONArray jsonBones = new JSONArray(); + jsonSkeleton.put("bones", jsonBones); + for (Bone bone : editableModel.getSkeleton().getBones()) { + JSONObject jsonBone = new JSONObject(); + + jsonBone.put("name", bone.getName()); + + if (bone.hasParent()) { + jsonBone.put("parentName", bone.getParentName()); + } + + if (bone.hasChildren()) { + JSONArray jsonChildren = new JSONArray(); + for (String childName : bone.getChildrens()) { + jsonChildren.put(childName); + } + jsonBone.put("childrenNames", jsonChildren); + } + + JSONObject jsonLocalBindTransform = new JSONObject(); + + JSONObject jsonTranslation = new JSONObject(); + jsonTranslation.put("x", bone.getLocalTranslation().x); + jsonTranslation.put("y", bone.getLocalTranslation().y); + jsonTranslation.put("z", bone.getLocalTranslation().z); + jsonLocalBindTransform.put("translation", jsonTranslation); + + JSONObject jsonRotation = new JSONObject(); + jsonRotation.put("x", bone.getLocalRotation().getX()); + jsonRotation.put("y", bone.getLocalRotation().getY()); + jsonRotation.put("z", bone.getLocalRotation().getZ()); + jsonRotation.put("w", bone.getLocalRotation().getW()); + jsonLocalBindTransform.put("rotation", jsonRotation); + + jsonBone.put("localBindTransform", jsonLocalBindTransform); + + jsonBones.put(jsonBone); + } + writeJSON(jsonSkeleton, dirPath, skeletonPath); // blocks String blocksPath = "blocks/blocks.json"; jsonInfo.put("blocks", blocksPath); - //TODO - + JSONObject jsonBlocks = new JSONObject(); + jsonBlocks.put("sizeUnit", editableModel.getBlockSizeUnit()); + JSONArray jsonBlocksData = new JSONArray(); + for (ModelBlockData blockData : editableModel.getRawBlockDatas().values()) { + jsonBlocksData.put(blockData.getX()); + jsonBlocksData.put(blockData.getY()); + jsonBlocksData.put(blockData.getZ()); + jsonBlocksData.put(blockData.getBone(0)); + jsonBlocksData.put(blockData.getBone(1)); + jsonBlocksData.put(blockData.getBone(2)); + jsonBlocksData.put(blockData.getBoneWeight(0)); + jsonBlocksData.put(blockData.getBoneWeight(1)); + jsonBlocksData.put(blockData.getBoneWeight(2)); + } + jsonBlocks.put("blocks", jsonBlocksData); + writeJSON(jsonBlocks, dirPath, blocksPath); + jsonInfo.put("blocks", blocksPath); // animations JSONArray jsonAnimations = new JSONArray(); - for (ModelSkeletonAnimation animation : model.getAnimations()) { + for (ModelSkeletonAnimation animation : editableModel.getAnimations()) { String animationPath = "animations/" + animation.getName().toLowerCase() + ".json"; jsonAnimations.put(animationPath); @@ -56,8 +173,12 @@ public final void export(EditableModel model, String dirpath) throws IOException JSONObject jsonKeyFrame = new JSONObject(); jsonKeyFrame.put("time", keyFrame.getTime()); - JSONObject jsonPose = new JSONObject(); + JSONArray jsonPoses = new JSONArray(); for (String boneName : keyFrame.getBoneKeyFrames().keySet()) { + JSONObject jsonPose = new JSONObject(); + + jsonPose.put("bone", boneName); + BoneTransform boneTransform = keyFrame.getBoneKeyFrames().get(boneName); JSONObject jsonTransform = new JSONObject(); JSONObject jsonPosition = new JSONObject(); @@ -73,33 +194,43 @@ public final void export(EditableModel model, String dirpath) throws IOException jsonRotation.put("w", boneTransform.getRotation().getW()); jsonTransform.put("rotation", jsonRotation); - jsonKeyFrame.put("transform", jsonTransform); + jsonPose.put("transform", jsonTransform); + + jsonPoses.put(jsonPose); } - jsonKeyFrames.put(jsonPose); + jsonKeyFrame.put("pose", jsonPoses); + jsonKeyFrames.put(jsonKeyFrame); } - writeJSON(jsonAnimation, dirpath, animationPath); + jsonAnimation.put("keyFrames", jsonKeyFrames); + writeJSON(jsonAnimation, dirPath, animationPath); } jsonInfo.put("animations", jsonAnimations); // skins JSONArray jsonSkins = new JSONArray(); - for (ModelSkin skin : model.getSkins()) { - String skinPath = "skins/" + skin.getName().toLowerCase() + ".json"; + for (ModelSkin skin : editableModel.getSkins()) { + String rawPath = "skins/" + skin.getName().toLowerCase(); + String skinPath = rawPath + ".json"; jsonSkins.put(skinPath); - - //TODO + JSONObject jsonSkin = new JSONObject(); + jsonSkin.put("name", skin.getName()); + String texturePath = rawPath + ".png"; + ImageUtils.exportPNGImage(Paths.get(dirPath, texturePath).toFile(), skin.getGLTexture().getData()); + jsonSkin.put("texture", texturePath); + writeJSON(jsonSkin, dirPath, skinPath); } jsonInfo.put("skins", jsonSkins); // finally, write file - writeJSON(jsonInfo, dirpath, "info.json"); + writeJSON(jsonInfo, dirPath, "info.json"); } private static final void writeJSON(JSONObject obj, String dirpath, String... more) throws IOException { Path info = Paths.get(dirpath, more); File file = info.toFile(); + file.getParentFile().mkdirs(); BufferedWriter output = new BufferedWriter(new FileWriter(file)); - output.write(obj.toString()); + output.write(obj.toString(4)); output.close(); } } diff --git a/VoxelEngine/src/com/grillecube/client/renderer/world/WorldRenderer.java b/VoxelEngine/src/com/grillecube/client/renderer/world/WorldRenderer.java index bb78c8a..23f6d56 100755 --- a/VoxelEngine/src/com/grillecube/client/renderer/world/WorldRenderer.java +++ b/VoxelEngine/src/com/grillecube/client/renderer/world/WorldRenderer.java @@ -64,12 +64,8 @@ public abstract class WorldRenderer extends RendererFactorized private int height; private final LineRendererFactory lineFactory; - private final ModelRendererFactory modelFactory; private final ParticleRendererFactory particleFactory; - private EventListener modelInstanceAddCallback; - private EventListener modelInstanceRemoveCallback; - private final EventPreWorldRender preRenderEvent; private final EventPostWorldRender postRenderEvent; @@ -78,11 +74,9 @@ public WorldRenderer(MainRenderer mainRenderer) { super(mainRenderer); this.lineFactory = new LineRendererFactory(mainRenderer); - this.modelFactory = new ModelRendererFactory(mainRenderer); this.particleFactory = new ParticleRendererFactory(mainRenderer); super.addFactory(this.lineFactory); - super.addFactory(this.modelFactory); super.addFactory(this.particleFactory); this.preRenderEvent = new EventPreWorldRender(this); @@ -115,29 +109,6 @@ protected void onInitialized() { GLH.glhCheckError("post worldrenderer fbo creation"); this.setPostProcessingProgram(null); - - // callback to add every model instances to the renderer, if they are in - // the correct world - EventManager eventManager = this.getMainRenderer().getResourceManager().getEventManager(); - this.modelInstanceAddCallback = new EventListener() { - @Override - public void invoke(EventModelInstanceAdded event) { - if (event.getModelInstance().getEntity().getWorld() == world) { - modelFactory.addModelInstance(event.getModelInstance()); - } - } - }; - this.modelInstanceRemoveCallback = new EventListener() { - @Override - public void invoke(EventModelInstanceRemoved event) { - if (event.getModelInstance().getEntity().getWorld() == world) { - modelFactory.removeModelInstance(event.getModelInstance()); - } - } - }; - - eventManager.addListener(this.modelInstanceAddCallback); - eventManager.addListener(this.modelInstanceRemoveCallback); } @Override @@ -152,10 +123,6 @@ protected void onDeinitialized() { this.fbo = null; this.fboTexture = null; this.fboDepthBuffer = null; - - EventManager eventManager = this.getMainRenderer().getResourceManager().getEventManager(); - eventManager.removeListener(this.modelInstanceAddCallback); - eventManager.removeListener(this.modelInstanceRemoveCallback); } // TODO : take size as parameter @@ -248,8 +215,6 @@ public final GLTexture getFBOTexture() { public final void setWorld(T world) { this.world = world; - this.modelFactory.clear(); - this.modelFactory.loadWorldModelInstance(world); this.onWorldSet(); } @@ -264,7 +229,6 @@ public final void setWorld(int worldID) { public final void setCamera(CameraProjective camera) { this.camera = camera; - this.modelFactory.setCamera(camera); this.lineFactory.setCamera(camera); this.particleFactory.setCamera(camera); this.onCameraSet(); @@ -287,10 +251,6 @@ public final LineRendererFactory getLineRendererFactory() { return (this.lineFactory); } - public final ModelRendererFactory getModelRendererFactory() { - return (this.modelFactory); - } - public final ParticleRendererFactory getParticleRendererFactory() { return (this.particleFactory); } diff --git a/VoxelEngine/src/com/grillecube/client/renderer/world/flat/WorldFlatRenderer.java b/VoxelEngine/src/com/grillecube/client/renderer/world/flat/WorldFlatRenderer.java index 2f90820..784ba82 100755 --- a/VoxelEngine/src/com/grillecube/client/renderer/world/flat/WorldFlatRenderer.java +++ b/VoxelEngine/src/com/grillecube/client/renderer/world/flat/WorldFlatRenderer.java @@ -1,21 +1,59 @@ package com.grillecube.client.renderer.world.flat; +import com.grillecube.client.event.renderer.model.EventModelInstanceAdded; +import com.grillecube.client.event.renderer.model.EventModelInstanceRemoved; import com.grillecube.client.renderer.MainRenderer; +import com.grillecube.client.renderer.model.ModelRendererFactory; import com.grillecube.client.renderer.sky.SkyRendererFactory; import com.grillecube.client.renderer.world.WorldRenderer; +import com.grillecube.common.event.EventListener; +import com.grillecube.common.resources.EventManager; import com.grillecube.common.world.WorldFlat; public class WorldFlatRenderer extends WorldRenderer { private SkyRendererFactory skyFactory; private FlatTerrainRendererFactory terrainFactory; + private final ModelRendererFactory modelFactory; + + private EventListener modelInstanceAddCallback; + private EventListener modelInstanceRemoveCallback; public WorldFlatRenderer(MainRenderer mainRenderer) { super(mainRenderer); this.skyFactory = new SkyRendererFactory(mainRenderer); this.terrainFactory = new FlatTerrainRendererFactory(mainRenderer); + this.modelFactory = new ModelRendererFactory(mainRenderer); + super.addFactory(this.skyFactory, 0); - super.addFactory(this.terrainFactory, 1); + super.addFactory(this.modelFactory, 1); + // line renderer here + super.addFactory(this.terrainFactory, 3); + // particle renderer here + + this.modelInstanceAddCallback = new EventListener() { + @Override + public void invoke(EventModelInstanceAdded event) { + if (event.getModelInstance().getEntity().getWorld() == getWorld()) { + modelFactory.addModelInstance(event.getModelInstance()); + } + } + }; + this.modelInstanceRemoveCallback = new EventListener() { + @Override + public void invoke(EventModelInstanceRemoved event) { + if (event.getModelInstance().getEntity().getWorld() == getWorld()) { + modelFactory.removeModelInstance(event.getModelInstance()); + } + } + }; + + // callback to add every model instances to the renderer, if they are in + // the correct world + EventManager eventManager = this.getMainRenderer().getResourceManager().getEventManager(); + + eventManager.addListener(this.modelInstanceAddCallback); + eventManager.addListener(this.modelInstanceRemoveCallback); } @Override @@ -23,16 +61,28 @@ protected void onInitialized() { super.onInitialized(); } + @Override + protected void onDeinitialized() { + super.onDeinitialized(); + + EventManager eventManager = this.getMainRenderer().getResourceManager().getEventManager(); + eventManager.removeListener(this.modelInstanceAddCallback); + eventManager.removeListener(this.modelInstanceRemoveCallback); + } + @Override protected final void onWorldSet() { this.terrainFactory.setWorld(super.getWorld()); this.skyFactory.setSky(super.getWorld().getSky()); + this.modelFactory.clear(); + this.modelFactory.loadWorldModelInstance(super.getWorld()); } @Override protected final void onCameraSet() { this.terrainFactory.setCamera(super.getCamera()); this.skyFactory.setCamera(super.getCamera()); + this.modelFactory.setCamera(super.getCamera()); } public final SkyRendererFactory getSkyRendererFactory() { @@ -42,4 +92,8 @@ public final SkyRendererFactory getSkyRendererFactory() { public final FlatTerrainRendererFactory getTerrainRendererFactory() { return (this.terrainFactory); } + + public final ModelRendererFactory getModelRendererFactory() { + return (this.modelFactory); + } } diff --git a/VoxelEngine/src/com/grillecube/common/maths/Maths.java b/VoxelEngine/src/com/grillecube/common/maths/Maths.java index 7dc3509..071f12f 100755 --- a/VoxelEngine/src/com/grillecube/common/maths/Maths.java +++ b/VoxelEngine/src/com/grillecube/common/maths/Maths.java @@ -1,5 +1,8 @@ package com.grillecube.common.maths; +import org.junit.Assert; +import org.junit.Test; + /** * * @author Romain @@ -188,4 +191,23 @@ public static int signum(float x) { public static float mod(float s, int modulus) { return (s % modulus + modulus) % modulus; } + + public Maths() { + + } + + @Test + public final void processTests() { + float e = 0.000000000000001f; + Assert.assertEquals(0.0f, Maths.approximatate(0.123456789f, 1.0f), e); + Assert.assertEquals(0.1f, Maths.approximatate(0.123456789f, 10.0f), e); + Assert.assertEquals(0.12f, Maths.approximatate(0.123456789f, 100.0f), e); + Assert.assertEquals(0.123f, Maths.approximatate(0.123456789f, 1000.0f), e); + + Assert.assertEquals(4.25f, Maths.floor(4.26f, 0.25f), e); + Assert.assertEquals(4.25f, Maths.floor(4.49f, 0.25f), e); + Assert.assertEquals(4.50f, Maths.floor(4.50f, 0.25f), e); + + } + }