From f433454ac2f4597136de02ed8da859fba4830b7f Mon Sep 17 00:00:00 2001 From: Mike Primm Date: Sat, 29 Jan 2022 03:57:04 -0600 Subject: [PATCH] Finish modellist implementation, use for campfire, comparator --- .../java/org/dynmap/hdmap/HDBlockModels.java | 30 ++- .../org/dynmap/hdmap/IsoHDPerspective.java | 4 + .../impl/ModModelDefinitionImpl.java | 4 +- .../modsupport/impl/ModelBlockModelImpl.java | 26 +- .../org/dynmap/utils/PatchDefinition.java | 224 +++++++++++------- .../dynmap/utils/PatchDefinitionFactory.java | 53 +++-- .../main/java/org/dynmap/utils/Vector3D.java | 21 +- DynmapCore/src/main/resources/models_1.txt | 31 +-- DynmapCore/src/main/resources/texture_1.txt | 2 +- .../dynmap/modsupport/ModelBlockModel.java | 10 +- .../dynmap/renderer/RenderPatchFactory.java | 2 +- 11 files changed, 267 insertions(+), 140 deletions(-) diff --git a/DynmapCore/src/main/java/org/dynmap/hdmap/HDBlockModels.java b/DynmapCore/src/main/java/org/dynmap/hdmap/HDBlockModels.java index 6318a797..47aac8bd 100644 --- a/DynmapCore/src/main/java/org/dynmap/hdmap/HDBlockModels.java +++ b/DynmapCore/src/main/java/org/dynmap/hdmap/HDBlockModels.java @@ -23,6 +23,7 @@ import org.dynmap.Log; import org.dynmap.MapManager; import org.dynmap.debug.Debug; import org.dynmap.modsupport.BlockSide; +import org.dynmap.modsupport.ModelBlockModel; import org.dynmap.renderer.CustomRenderer; import org.dynmap.renderer.DynmapBlockState; import org.dynmap.renderer.RenderPatch; @@ -326,6 +327,7 @@ public class HDBlockModels { BlockSide side; int textureid; double[] uv; + ModelBlockModel.SideRotation rot; }; private static class ModelBox { @@ -1054,13 +1056,32 @@ public class HDBlockModels { String v = prms[faceidx]; String[] flds = v.split("/"); ModelBoxSide side = new ModelBoxSide(); + side.rot = null; + if ((flds.length != 2) && (flds.length != 6)) { + Log.severe("Invalid modellist face '" + v + "' at line " + rdr.getLineNumber()); + continue; + } if (flds.length > 0) { String face = flds[0]; - side.side = toBlockSide.get(face); + side.side = toBlockSide.get(face.substring(0, 1)); if (side.side == null) { - Log.severe("Invalid modellist side value (" + face + ") at line " + rdr.getLineNumber()); + Log.severe("Invalid modellist side value (" + face + ") in '" + v + "' at line " + rdr.getLineNumber()); continue; } + if (flds[0].length() > 1) { + String r = flds[0].substring(1); + switch (r) { + case "90": + side.rot = ModelBlockModel.SideRotation.DEG90; + break; + case "180": + side.rot = ModelBlockModel.SideRotation.DEG180; + break; + case "270": + side.rot = ModelBlockModel.SideRotation.DEG270; + break; + } + } } if (flds.length > 1) { side.textureid = getIntValue(varvals, flds[1]); @@ -1085,7 +1106,7 @@ public class HDBlockModels { for (ModelBox bl : boxes) { // Loop through faces for (ModelBoxSide side : bl.sides) { - PatchDefinition patch = pdf.getModelFace(bl.from, bl.to, side.side, side.uv, side.textureid); + PatchDefinition patch = pdf.getModelFace(bl.from, bl.to, side.side, side.uv, side.rot, side.textureid); if (patch != null) { // If any rotations, apply them here if ((bl.xrot != 0) || (bl.yrot != 0) || (bl.zrot != 0)) { @@ -1093,6 +1114,9 @@ public class HDBlockModels { } pd.add(patch); } + else { + Log.severe(String.format("Invalid modellist patch for box %f/%f/%f:%f/%f/%f side %s at line %d", bl.from[0], bl.from[1], bl.from[2], bl.to[0], bl.to[1], bl.to[2], side.side, rdr.getLineNumber())); + } } } PatchDefinition[] patcharray = new PatchDefinition[pd.size()]; diff --git a/DynmapCore/src/main/java/org/dynmap/hdmap/IsoHDPerspective.java b/DynmapCore/src/main/java/org/dynmap/hdmap/IsoHDPerspective.java index 5b44a113..c2988215 100644 --- a/DynmapCore/src/main/java/org/dynmap/hdmap/IsoHDPerspective.java +++ b/DynmapCore/src/main/java/org/dynmap/hdmap/IsoHDPerspective.java @@ -408,6 +408,7 @@ public class IsoHDPerspective implements HDPerspective { /* If parallel to surface, no intercept */ switch(pd.sidevis) { case TOP: + case TOPFLIP: if (det < 0.000001) { return hitcnt; } @@ -454,6 +455,9 @@ public class IsoHDPerspective implements HDPerspective { patch_id[hitcnt] = pd.textureindex; if(det > 0) { patch_step[hitcnt] = pd.step.opposite(); + if (pd.sidevis == SideVisible.TOPFLIP) { + patch_u[hitcnt] = 1 - u; + } } else { if (pd.sidevis == SideVisible.FLIP) { diff --git a/DynmapCore/src/main/java/org/dynmap/modsupport/impl/ModModelDefinitionImpl.java b/DynmapCore/src/main/java/org/dynmap/modsupport/impl/ModModelDefinitionImpl.java index 6e8750a0..264575a9 100644 --- a/DynmapCore/src/main/java/org/dynmap/modsupport/impl/ModModelDefinitionImpl.java +++ b/DynmapCore/src/main/java/org/dynmap/modsupport/impl/ModModelDefinitionImpl.java @@ -223,8 +223,8 @@ public class ModModelDefinitionImpl implements ModModelDefinition { return id; } - public String getModelFacePatchID(double[] from, double[] to, BlockSide face, double[] uv, int textureid) { - PatchDefinition pd = pdf.getModelFace(from, to, face, uv, textureid); + public String getModelFacePatchID(double[] from, double[] to, BlockSide face, double[] uv, ModelBlockModel.SideRotation rot, int textureid) { + PatchDefinition pd = pdf.getModelFace(from, to, face, uv, rot, textureid); if (pd == null) return null; // Invalid patch for (int i = 0; i < blkPatch.size(); i++) { diff --git a/DynmapCore/src/main/java/org/dynmap/modsupport/impl/ModelBlockModelImpl.java b/DynmapCore/src/main/java/org/dynmap/modsupport/impl/ModelBlockModelImpl.java index e3772b76..a5da328b 100644 --- a/DynmapCore/src/main/java/org/dynmap/modsupport/impl/ModelBlockModelImpl.java +++ b/DynmapCore/src/main/java/org/dynmap/modsupport/impl/ModelBlockModelImpl.java @@ -6,11 +6,13 @@ import java.util.HashMap; import org.dynmap.modsupport.BlockSide; import org.dynmap.modsupport.ModelBlockModel; +import org.dynmap.modsupport.ModelBlockModel.SideRotation; public class ModelBlockModelImpl extends BlockModelImpl implements ModelBlockModel { private static class ModelSide { private double[] uv; + private SideRotation rot; int textureid; }; private static class ModelBlockImpl implements ModelBlock { @@ -19,12 +21,15 @@ public class ModelBlockModelImpl extends BlockModelImpl implements ModelBlockMod private double[] to = { 16, 16, 16 }; private double xrot = 0, yrot = 0, zrot = 0; @Override - public void addBlockSide(BlockSide side, double[] uv, int textureid) { + public void addBlockSide(BlockSide side, double[] uv, SideRotation rot, int textureid) { ModelSide ms = new ModelSide(); ms.textureid = textureid; if (uv != null) { ms.uv = Arrays.copyOf(uv, uv.length); } + if (rot != null) { + ms.rot = rot; + } if (side == BlockSide.FACE_0 || side == BlockSide.Y_MINUS) side = BlockSide.BOTTOM; if (side == BlockSide.FACE_1 || side == BlockSide.Y_PLUS) side = BlockSide.TOP; if (side == BlockSide.FACE_2 || side == BlockSide.Z_MINUS) side = BlockSide.NORTH; @@ -89,11 +94,26 @@ public class ModelBlockModelImpl extends BlockModelImpl implements ModelBlockMod String side = fromBlockSide.get(bs); ModelSide mside = mb.sides.get(bs); if (mside != null) { + String rval = side; + switch (mside.rot) { + case DEG0: + default: + break; + case DEG90: + rval += "90"; + break; + case DEG180: + rval += "180"; + break; + case DEG270: + rval += "270"; + break; + } if (mside.uv != null) { - line += String.format(":%s/%d/%f/%f/%f/%f", side, mside.textureid, mside.uv[0], mside.uv[1], mside.uv[2], mside.uv[3]); + line += String.format(":%s/%d/%f/%f/%f/%f", rval, mside.textureid, mside.uv[0], mside.uv[1], mside.uv[2], mside.uv[3]); } else { - line += String.format(":%s/%d", side, mside.textureid); + line += String.format(":%s/%d", rval, mside.textureid); } } } diff --git a/DynmapCore/src/main/java/org/dynmap/utils/PatchDefinition.java b/DynmapCore/src/main/java/org/dynmap/utils/PatchDefinition.java index 91b72b19..5203f969 100644 --- a/DynmapCore/src/main/java/org/dynmap/utils/PatchDefinition.java +++ b/DynmapCore/src/main/java/org/dynmap/utils/PatchDefinition.java @@ -2,6 +2,7 @@ package org.dynmap.utils; import org.dynmap.Log; import org.dynmap.modsupport.BlockSide; +import org.dynmap.modsupport.ModelBlockModel; import org.dynmap.renderer.RenderPatch; import org.dynmap.renderer.RenderPatchFactory.SideVisible; @@ -256,7 +257,9 @@ public class PatchDefinition implements RenderPatch { Log.severe("Invalid vmaxatumax=" + vmaxatumax); good = false; } - + if (!good) { + Log.warning("Patch not valid: " + toString()); + } return good; } @Override @@ -304,99 +307,140 @@ public class PatchDefinition implements RenderPatch { // @param to - vector of upper right corner of box (0-16 range for coordinates max x, y, z) // @param face - which face (determines use of xyz-min vs xyz-max // @param uv - bounds on UV (umin, vmin, umax, vmax): if undefined, default based on face range (minecraft UV is relative to top left corner of texture) + // @param rot - texture rotation (default 0 - DEG0, DEG90, DEG180, DEG270) // @param textureid - texture ID - public void updateModelFace(double[] from, double[] to, BlockSide face, double[] uv, int textureid) { - // Based on face, figure out coordinates of face corner (lower left for x0, y0, z0 - lower right for xu, yu, zy - top left for xv, yv, zv) - double x0 = 0, xu = 1, xv = 0, y0 = 0, yu = 0, yv = 1, z0 = 0, zu = 0, zv = 0; - double umin = 0, vmin = 0, umax = 1, vmax = 1; + public void updateModelFace(double[] from, double[] to, BlockSide face, double[] uv, ModelBlockModel.SideRotation rot, int textureid) { + if (rot == null) rot = ModelBlockModel.SideRotation.DEG0; + // Compute corners of the face + Vector3D lowleft; + Vector3D lowright; + Vector3D upleft; + Vector3D upright; + // Default UV, if not defined + double[] patchuv; + boolean flipU = false, flipV = false; + if (uv != null) { // MC V is top down, so flip + patchuv = new double[] { uv[0] / 16.0, 1 - uv[3] / 16.0, uv[2] / 16.0, 1 - uv[1] / 16.0 }; + if (patchuv[0] > patchuv[2]) { flipU = true; double save = patchuv[0]; patchuv[0] = patchuv[2]; patchuv[2] = save; } + if (patchuv[1] > patchuv[3]) { flipV = true; double save = patchuv[1]; patchuv[1] = patchuv[3]; patchuv[3] = save; } + } + else { + patchuv = new double[] { 0, 0, 1, 1 }; + } switch (face) { case BOTTOM: - case FACE_0: - case Y_MINUS: - // Bottom - Y-negative (top towards south (+Z), right towards east (+x)) - x0 = xv = from[0] / 16.0; xu = to[0] / 16.0; - y0 = yu = yv = from[1] / 16.0; // Bottom - z0 = zu = from[2] / 16.0; zv = to[2] / 16.0; - umin = x0; umax = xu; - vmin = z0; vmax = zv; - break; - case TOP: - case FACE_1: - case Y_PLUS: - // Top - Y-positive (top towards north (-Z), right towards east (+x)) - x0 = xv = from[0] / 16.0; xu = to[0] / 16.0; - y0 = yu = yv = to[1] / 16.0; // Top - z0 = zu = to[2] / 16.0; zv = from[2] / 16.0; - umin = x0; umax = xu; - vmin = 1 - z0; vmax = 1 - zv; - break; - case NORTH: - case FACE_2: - case Z_MINUS: - // North - Z-negative (top towards up (+Y), right towards west (-X)) - x0 = xv = to[0] / 16.0; xu = from[0] / 16.0; - y0 = yu = from[1] / 16.0; yv = to[1] / 16.0; - z0 = zu = zv = from[2] / 16.0; - umin = 1 - x0; umax = 1 - xu; - vmin = y0; vmax = yv; - break; - case SOUTH: - case FACE_3: - case Z_PLUS: - // South - Z-positive (top towards up (+Y), right towards east (+X)) - x0 = xv = from[0] / 16.0; xu = to[0] / 16.0; - y0 = yu = from[1] / 16.0; yv = to[1] / 16.0; - z0 = zu = zv = to[2] / 16.0; - umin = x0; umax = xu; - vmin = y0; vmax = yv; - break; - case WEST: - case FACE_4: - case X_MINUS: - // West - X-negative (top towards up (+Y), right towards south (+Z)) - x0 = xu = xv = from[0] / 16.0; - y0 = yu = from[1] / 16.0; yv = to[1] / 16.0; - z0 = zv = from[2] / 16.0; zu = to[2] / 16.0; - umin = z0; umax = zu; - vmin = y0; vmax = yv; - break; - case EAST: - case FACE_5: - case X_PLUS: - // East - X-positive (top towards up (+Y), right towards north (-Z)) - x0 = xu = xv = to[0] / 16.0; - y0 = yu = from[1] / 16.0; yv = to[1] / 16.0; - z0 = zv = to[2] / 16.0; zu = from[2] / 16.0; - umin = 1 - z0; umax = 1 - zu; - vmin = y0; vmax = yv; - break; - default: - Log.severe("Invalid side: " + face); - return; + case FACE_0: + case Y_MINUS: + // Bottom - Y-negative (top towards south (+Z), right towards east (+x)) + lowleft = new Vector3D(from[0] / 16.0, from[1] / 16.0, from[2] / 16.0); + lowright = new Vector3D(to[0] / 16.0, from[1] / 16.0, from[2] / 16.0); + upleft = new Vector3D(from[0] / 16.0, from[1] / 16.0, to[2] / 16.0); + upright = new Vector3D(to[0] / 16.0, from[1] / 16.0, to[2] / 16.0); + break; + case TOP: + case FACE_1: + case Y_PLUS: + // Top - Y-positive (top towards north (-Z), right towards east (+x)) + lowleft = new Vector3D(from[0] / 16.0, to[1] / 16.0, to[2] / 16.0); + lowright = new Vector3D(to[0] / 16.0, to[1] / 16.0, to[2] / 16.0); + upleft = new Vector3D(from[0] / 16.0, to[1] / 16.0, from[2] / 16.0); + upright = new Vector3D(to[0] / 16.0, to[1] / 16.0, from[2] / 16.0); + break; + case NORTH: + case FACE_2: + case Z_MINUS: + // North - Z-negative (top towards up (+Y), right towards west (-X)) + lowleft = new Vector3D(to[0] / 16.0, from[1] / 16.0, from[2] / 16.0); + lowright = new Vector3D(from[0] / 16.0, from[1] / 16.0, from[2] / 16.0); + upleft = new Vector3D(to[0] / 16.0, to[1] / 16.0, from[2] / 16.0); + upright = new Vector3D(from[0] / 16.0, to[1] / 16.0, from[2] / 16.0); + break; + case SOUTH: + case FACE_3: + case Z_PLUS: + // South - Z-positive (top towards up (+Y), right towards east (+X)) + lowleft = new Vector3D(from[0] / 16.0, from[1] / 16.0, to[2] / 16.0); + lowright = new Vector3D(to[0] / 16.0, from[1] / 16.0,to[2] / 16.0); + upleft = new Vector3D(from[0] / 16.0, to[1] / 16.0, to[2] / 16.0); + upright = new Vector3D(to[0] / 16.0, to[1] / 16.0, to[2] / 16.0); + break; + case WEST: + case FACE_4: + case X_MINUS: + // West - X-negative (top towards up (+Y), right towards south (+Z)) + lowleft = new Vector3D(from[0] / 16.0, from[1] / 16.0, from[2] / 16.0); + lowright = new Vector3D(from[0] / 16.0, from[1] / 16.0, to[2] / 16.0); + upleft = new Vector3D(from[0] / 16.0, to[1] / 16.0, from[2] / 16.0); + upright = new Vector3D(from[0] / 16.0, to[1] / 16.0, to[2] / 16.0); + break; + case EAST: + case FACE_5: + case X_PLUS: + // East - X-positive (top towards up (+Y), right towards north (-Z)) + lowleft = new Vector3D(to[0] / 16.0, from[1] / 16.0, to[2] / 16.0); + lowright = new Vector3D(to[0] / 16.0, from[1] / 16.0, from[2] / 16.0); + upleft = new Vector3D(to[0] / 16.0, to[1] / 16.0, to[2] / 16.0); + upright = new Vector3D(to[0] / 16.0, to[1] / 16.0, from[2] / 16.0); + break; + default: + Log.severe("Invalid side: " + face); + return; + } + // If rotation, rotate face corners + if (rot == ModelBlockModel.SideRotation.DEG90) { + // 90 degrees CW - origin is now upper left (V), V is now upper right (U+V-O), U is lower left (O) + Vector3D save = lowleft; + lowleft = lowright; + lowright = upright; + upright = upleft; + upleft = save; } - // If uv provided, use it to override - if ((uv != null) && (uv.length == 4)) { - umin = uv[0] / 16.0; - vmin = 1 - (uv[3] / 16.0); // MC V is inverted from our V - umax = uv[2] / 16.0; - vmax = 1 - (uv[1] / 16.0); // MC V is inverted from our V + else if (rot == ModelBlockModel.SideRotation.DEG180) { + // 180 degrees CW - origin is now upper right, U is now upper left (V), V is lower right (U) + Vector3D save = lowleft; + lowleft = upright; + upright = save; + save = lowright; + lowright = upleft; + upleft = save; } - // Compute texture origin for u,y = 0,0, based on coordinates - // x0,y0,z0 = u=umin,v=vmin; xu,yu,zu = u=umax,v=vmin; xv,yv,zv = u=umin,v=vmax - // Compute U vector (based on proportion of umax-umin versus U offset - double uvectx = (xu - x0) / (umax - umin); - double uvecty = (yu - y0) / (umax - umin); - double uvectz = (zu - z0) / (umax - umin); - // Compute V vector (based on proportion of vmax-vmin versus V offset - double vvectx = (xv - x0) / (vmax - vmin); - double vvecty = (yv - y0) / (vmax - vmin); - double vvectz = (zv - z0) / (vmax - vmin); - // Compute origin based on U vector and umin and V vector and vmin vs x0,y0,z0 - double ovectx = x0 - (uvectx * umin) - (vvectx * vmin); - double ovecty = y0 - (uvecty * umin) - (vvecty * vmin); - double ovectz = z0 - (uvectz * umin) - (vvectz * vmin); - - update(ovectx, ovecty, ovectz, uvectx + ovectx, uvecty + ovecty, uvectz + ovectz, vvectx + ovectx, vvecty + ovecty, vvectz + ovectz, - umin, umax, vmin, vmax, SideVisible.TOP, textureid, vmin, vmax); + else if (rot == ModelBlockModel.SideRotation.DEG270) { + // 270 degrees CW - origin is now lower right (V), U is now upper right (topright), V is lower right (O) + Vector3D save = lowright; + lowright = lowleft; + lowleft = upleft; + upleft = upright; + upright = save; + } + //System.out.println(String.format("ll=%s, lr=%s, ul=%s, ur=%s", lowleft, lowright, upleft, upright)); + // Compute texture origin, based on corners and patchuv + Vector3D txtorig = new Vector3D(); + Vector3D txtU = new Vector3D(); + Vector3D txtV = new Vector3D(); + Vector3D wrk = new Vector3D(); + // If nonzero texture size + if ((patchuv[0] != patchuv[2]) && (patchuv[1] != patchuv[3])) { + // Get scale along U axis + double du = patchuv[2] - patchuv[0]; + txtU.set(lowright).subtract(lowleft); // vector along U + double uScale = txtU.length() / du; + txtU.scale(uScale / du); // Compute full U vect + // Compute V axis + double dv = patchuv[3] - patchuv[1]; + txtV.set(upleft).subtract(lowleft); // vector along V + double vScale = txtV.length() / dv; + txtV.scale(vScale / dv); // Compute full V vect + // Compute texture origin + txtorig.set(txtU).scale(-patchuv[0]).add(lowleft); + wrk.set(txtV).scale(-patchuv[1]); + txtorig.add(wrk); + // Compute full U and V + txtU.add(txtorig); // And add it for full U + txtV.add(txtorig); // And add it to compute full V + } +// System.out.println(String.format("txtO=%s, txtU=%s, txtV=%s, uv=%f/%f/%f/%f", txtorig, txtU, txtV, patchuv[0], patchuv[1], patchuv[2], +// patchuv[3])); + update(txtorig.x, txtorig.y, txtorig.z, txtU.x, txtU.y, txtU.z, txtV.x, txtV.y, txtV.z, + patchuv[0], patchuv[2], patchuv[1], patchuv[3], flipU ? SideVisible.TOPFLIP : SideVisible.TOP, textureid, patchuv[1], patchuv[3]); } } diff --git a/DynmapCore/src/main/java/org/dynmap/utils/PatchDefinitionFactory.java b/DynmapCore/src/main/java/org/dynmap/utils/PatchDefinitionFactory.java index cb981c33..68e01c26 100644 --- a/DynmapCore/src/main/java/org/dynmap/utils/PatchDefinitionFactory.java +++ b/DynmapCore/src/main/java/org/dynmap/utils/PatchDefinitionFactory.java @@ -5,6 +5,7 @@ import java.util.Map; import org.dynmap.hdmap.TexturePack; import org.dynmap.modsupport.BlockSide; +import org.dynmap.modsupport.ModelBlockModel; import org.dynmap.renderer.RenderPatch; import org.dynmap.renderer.RenderPatchFactory; import org.dynmap.renderer.RenderPatchFactory.SideVisible; @@ -66,9 +67,9 @@ public class PatchDefinitionFactory implements RenderPatchFactory { } - public PatchDefinition getModelFace(double[] from, double[] to, BlockSide face, double[] uv, int textureid) { + public PatchDefinition getModelFace(double[] from, double[] to, BlockSide face, double[] uv, ModelBlockModel.SideRotation rot, int textureid) { synchronized(lock) { - lookup.updateModelFace(from, to, face, uv, textureid); + lookup.updateModelFace(from, to, face, uv, rot, textureid); if(lookup.validate() == false) return null; PatchDefinition pd2 = patches.get(lookup); /* See if in cache already */ @@ -189,28 +190,40 @@ public class PatchDefinitionFactory implements RenderPatchFactory { public static void main(String[] args) { PatchDefinitionFactory fact = new PatchDefinitionFactory(); - BlockSide[] faces = { BlockSide.BOTTOM, BlockSide.TOP, BlockSide.NORTH, BlockSide.SOUTH, BlockSide.WEST, BlockSide.EAST }; - double[] from = { 0,0,0 }; - double[] to = { 16,16,16 }; + PatchDefinition pd; + BlockSide[] faces = { BlockSide.NORTH, BlockSide.EAST, BlockSide.SOUTH, BlockSide.WEST, BlockSide.TOP, BlockSide.BOTTOM }; + // campfire log:box=1/0/0:5/4/16:n/0/0/4/4/8:e/0/0/1/16/5:s/0/0/4/4/8:w/0/16/0/0/4:u90/0/0/0/16/4:d90/0/0/0/16/4 + double[][] uvs = { { 0, 4, 4, 8 }, { 0, 1, 16, 5 }, { 0, 4, 4, 8 }, { 16, 0, 0, 4 }, { 0, 0, 16, 4 }, { 0, 0, 16, 4 } }; + ModelBlockModel.SideRotation[] rots = { ModelBlockModel.SideRotation.DEG0, ModelBlockModel.SideRotation.DEG0, ModelBlockModel.SideRotation.DEG0, + ModelBlockModel.SideRotation.DEG0, ModelBlockModel.SideRotation.DEG90, ModelBlockModel.SideRotation.DEG90 }; + double[] from = { 1, 0, 0 }; + double[] to = { 5, 4, 16 }; // Do normal faces, default limits - PatchDefinition pd = new PatchDefinition(); - for (BlockSide face : faces) { - pd.updateModelFace(from, to, face, null, 0); - System.out.println("Full cube " + face + ": " + pd); + pd = new PatchDefinition(); + for (int i = 0; i < faces.length; i++) { + pd.updateModelFace(from, to, faces[i], uvs[i], rots[i], 0); + System.out.println("Log " + faces[i] + ": " + pd); } - double[] toquarter = { 8,8,8 }; - for (BlockSide face : faces) { - pd.updateModelFace(from, toquarter, face, null, 0); - System.out.println("8x8x8 cube " + face + ": " + pd); - } - - - for (BlockSide face : faces) { - pd.updateModelFace(from, toquarter, face, new double[] { 4, 4, 12, 12 }, 0); - System.out.println("Full cube, middle half of texture " + face + ": " + pd); - } +// // Do normal faces, default limits +// pd = new PatchDefinition(); +// for (BlockSide face : faces) { +// pd.updateModelFace(from, to, face, null, 0); +// System.out.println("Full cube " + face + ": " + pd); +// } +// +// double[] toquarter = { 8,8,8 }; +// for (BlockSide face : faces) { +// pd.updateModelFace(from, toquarter, face, null, 0); +// System.out.println("8x8x8 cube " + face + ": " + pd); +// } +// +// +// for (BlockSide face : faces) { +// pd.updateModelFace(from, toquarter, face, new double[] { 4, 4, 12, 12 }, 0); +// System.out.println("Full cube, middle half of texture " + face + ": " + pd); +// } } } diff --git a/DynmapCore/src/main/java/org/dynmap/utils/Vector3D.java b/DynmapCore/src/main/java/org/dynmap/utils/Vector3D.java index 6f22864f..55618e15 100644 --- a/DynmapCore/src/main/java/org/dynmap/utils/Vector3D.java +++ b/DynmapCore/src/main/java/org/dynmap/utils/Vector3D.java @@ -17,28 +17,41 @@ public class Vector3D { public final void setFromLocation(DynmapLocation l) { x = l.x; y = l.y; z = l.z; } - public final void set(Vector3D v) { + public final Vector3D set(Vector3D v) { x = v.x; y = v.y; z = v.z; + return this; } - public final void subtract(Vector3D v) { + public final Vector3D subtract(Vector3D v) { x = x - v.x; y = y - v.y; z = z - v.z; + return this; } - public final void add(Vector3D v) { + public final Vector3D add(Vector3D v) { x = x + v.x; y = y + v.y; z = z + v.z; + return this; } public final double innerProduct(Vector3D v) { return (v.x * x) + (v.y * y) + (v.z * z); } + public final Vector3D scale(double m) { + x = x * m; y = y * m; z = z * m; + return this; + } + + public final double length() { + return Math.sqrt(x*x + y*y + z*z); + } + /* this = this X v */ - public final void crossProduct(Vector3D v) { + public final Vector3D crossProduct(Vector3D v) { double newx = (y*v.z) - (z*v.y); double newy = (z*v.x) - (x*v.z); double newz = (x*v.y) - (y*v.x); x = newx; y = newy; z = newz; + return this; } public String toString() { diff --git a/DynmapCore/src/main/resources/models_1.txt b/DynmapCore/src/main/resources/models_1.txt index c168a0af..24519249 100644 --- a/DynmapCore/src/main/resources/models_1.txt +++ b/DynmapCore/src/main/resources/models_1.txt @@ -955,7 +955,7 @@ patchrotate:id=comparator,data=5,rot=90 patchblock:id=comparator,data=13 patchrotate:id=comparator,data=5,rot=270 # Comparator (compare mode, on) - slab, comparator, unlit, lit, comparator_on -modellist:id=comparator,data=4,box=0/0/0:16/2/16:d/0/0/0/16/16:u/4/0/0/16/16:n/0/0/14/16/16:s/0/0/14/16/16:w/0/14/16/16:e/0/14/16/16,box=4/7/11:6/7/13:u/3/7/6/9/8,box=4/2/10:6/8/14:w/3/6/5/10/11:e/3/6/5/10/11,box=3/2/11:7/8/13:n/3/6/5/10/11:s/3/6/5/10/11,box=10/7/11:12/7/13:u/3/7/6/9/8,box=10/1/10:12/8/14:w/3/6/5/10/11:e/3/6/5/10/11,box=9/2/11:13/8/13:n/3/6/5/10/11:s/3/6/5/10/11,box=7/2/2:9/4/4:d/2/7/13/9/15:u/2/7/6/9/8:n/2/7/6/9/8:s/2/7/6/9/8:w/2/7/6/9/8:e/2/7/6/9/8 +modellist:id=comparator,data=4,box=0/0/0:16/2/16:d/0/0/0/16/16:u/4/0/0/16/16:n/0/0/14/16/16:s/0/0/14/16/16:w/0/0/14/16/16:e/0/0/14/16/16,box=4/7/11:6/7/13:u/3/7/6/9/8,box=4/2/10:6/8/14:w/3/6/5/10/11:e/3/6/5/10/11,box=3/2/11:7/8/13:n/3/6/5/10/11:s/3/6/5/10/11,box=10/7/11:12/7/13:u/3/7/6/9/8,box=10/1/10:12/8/14:w/3/6/5/10/11:e/3/6/5/10/11,box=9/2/11:13/8/13:n/3/6/5/10/11:s/3/6/5/10/11,box=7/2/2:9/4/4:d/2/7/13/9/15:u/2/7/6/9/8:n/2/7/6/9/8:s/2/7/6/9/8:w/2/7/6/9/8:e/2/7/6/9/8 patchblock:id=comparator,data=0 patchrotate:id=comparator,data=4,rot=180 patchblock:id=comparator,data=8 @@ -1411,21 +1411,24 @@ patchblock:id=bubble_column [1.14-]patchrotate:id=stonecutter,data=0,roty=270 [1.14-]patchblock:id=stonecutter,data=3 [1.14-]patchrotate:id=stonecutter,data=0,roty=90 -# Campfire -[1.14-]boxlist:id=campfire,data=0,data=1,data=2,data=3,box=0.0625:0.3125:0:0.25:0:1:0/0/1/0/0/0,box=0:1:0.1875:0.4375:0.6875:0.9375:0/1/1/1/0/0,box=0.6875:0.9375:0:0.25:0:1:0/0/0/0/1/0,box=0:1:0.1875:0.4375:0.0625:0.3125:0/1/1/1/0/0,box=0.3125:0.6875:0:0.0625:0:1:0/1/0/0/0/0,box=0.49:0.51:0:1:0:1:-1/-1/2/2/2/2,box=0:1:0:1:0.49:0.51:-1/-1/2/2/2/2 -[1.14-]boxlist:id=campfire,data=4,data=5,data=6,data=7,box=0.0625:0.3125:0:0.25:0:1:0/0/0/0/0/0,box=0:1:0.1875:0.4375:0.6875:0.9375:0/0/0/0/0/0,box=0.6875:0.9375:0:0.25:0:1:0/0/0/0/0/0,box=0:1:0.1875:0.4375:0.0625:0.3125:0/0/0/0/0/0,box=0.3125:0.6875:0:0.0625:0:1:0/0/0/0/0/0 -[1.14-]patchblock:id=campfire,data=8,data=9,data=10,data=11 -[1.14-]patchrotate:id=campfire,data=0,roty=180 -[1.14-]patchblock:id=campfire,data=12,data=13,data=14,data=15 -[1.14-]patchrotate:id=campfire,data=4,roty=180 +# Campfire (lit) (unlit log, lit log, fire) +[1.14-]modellist:id=campfire,data=8,data=9,data=10,data=11,box=1/0/0:5/4/16:n/0/0/4/4/8:e/1/0/1/16/5:s/0/0/4/4/8:w/0/16/0/0/4:u90/0/0/0/16/4:d90/0/0/0/16/4,box=0/3/11:16/7/15:n/1/16/0/0/4:e/0/0/4/4/8:s/1/0/0/16/4:w/0/0/4/4/8:u180/1/0/0/16/4:d/1/0/4/16/8,box=11/0/0:15/4/16:n/0/0/4/4/8:e/0/0/0/16/4:s/0/0/4/4/8:w/1/16/1/0/5:u90/0/0/0/16/4:d90/0/0/0/16/4,box=0/3/1:16/7/5:n/1/0/0/16/4:e/0/0/4/4/8:s/1/16/0/0/4:w/0/0/4/4/8:u180/0/0/0/16/4:d/1/0/4/16/8,box=5/0/0:11/1/16:n/0/0/15/6/16:s/0/10/15/16/16:u90/1/0/8/16/14:d90/0/0/8/16/14,box=0.8/1/8:15.2/17/8/0/45/0:n/2/0/0/16/16:s/2/0/0/16/16,box=8/1/0.8:8/17/15.2/0/45/0:w/2/0/0/16/16:e/2/0/0/16/16 +[1.14-]patchblock:id=campfire,data=0,data=1,data=2,data=3 +[1.14-]patchrotate:id=campfire,data=8,roty=180 [1.14-]patchblock:id=campfire,data=16,data=17,data=18,data=19 -[1.14-]patchrotate:id=campfire,data=0,roty=270 -[1.14-]patchblock:id=campfire,data=20,data=21,data=22,data=23 -[1.14-]patchrotate:id=campfire,data=4,roty=270 +[1.14-]patchrotate:id=campfire,data=8,roty=270 [1.14-]patchblock:id=campfire,data=24,data=25,data=26,data=27 -[1.14-]patchrotate:id=campfire,data=0,roty=90 +[1.14-]patchrotate:id=campfire,data=8,roty=90 +# Campfire (unlit) (unlit log, lit log, fire) +[1-14-]modellist:id=campfire,data=12,data=13,data=14,data=15,box=1/0/0:5/4/16:n/0/0/4/4/8:e/0/0/1/16/5:s/0/0/4/4/8:w/0/16/0/0/4:u90/0/0/0/16/4:d90/0/0/0/16/4,box=0/3/11:16/7/15:n/0/16/0/0/4:e/0/0/4/4/8:s/0/0/0/16/4:w/0/0/4/4/8:u180/0/0/0/16/4:d/0/0/0/16/4,box=11/0/0:15/4/16:n/0/0/4/4/8:e/0/0/0/16/4:s/0/0/4/4/8:w/0/16/1/0/5:u90/0/0/0/16/4:d90/0/0/0/16/4,box=0/3/1:16/7/5:n/0/0/0/16/4:e/0/0/4/4/8:s/0/16/0/0/4:w/0/0/4/4/8:u180/0/0/0/16/4:d/0/0/0/16/4,box=5/0/0:11/1/16:n/0/0/15/6/16:s/0/10/15/16/16:u90/0/0/8/16/14:d90/0/0/8/16/14 +[1.14-]patchblock:id=campfire,data=4,data=5,data=6,data=7 +[1.14-]patchrotate:id=campfire,data=12,roty=180 +[1.14-]patchblock:id=campfire,data=20,data=21,data=22,data=23 +[1.14-]patchrotate:id=campfire,data=12,roty=270 [1.14-]patchblock:id=campfire,data=28,data=29,data=30,data=31 -[1.14-]patchrotate:id=campfire,data=4,roty=90 +[1.14-]patchrotate:id=campfire,data=12,roty=90 + + # Bell (1.14.x) [1.14-1.14.4]boxlist:id=bell,data=2,box=0.125:0.875:0.8125:0.9375:0.4375:0.5625:0/0/0/0/0/0,box=0.875:1:0:1:0.375:0.625:1/1/1/1/1/1,box=0:0.125:0:1:0.375:0.625:1/1/1/1/1/1,box=0.3125:0.6875:0.375:0.8175:0.3125:0.6875:2/3/4/4/4/4,box=0.25:0.75:0.25:0.375:0.25:0.75:2/3/4/4/4/4 [1.14-1.14.4]patchblock:id=bell,data=3 @@ -1444,7 +1447,7 @@ patchblock:id=bubble_column [1.14-1.14.4]boxlist:id=bell,data=10,box=0.1875:1:0.8125:0.9375:0.4375:0.5625:0/0/0/0/0/0,box=0.3125:0.6875:0.375:0.8175:0.3125:0.6875:2/3/4/4/4/4,box=0.25:0.75:0.25:0.375:0.25:0.75:2/3/4/4/4/4 [1.14-1.14.4]patchblock:id=bell,data=11 [1.14-1.14.4]patchrotate:id=bell,data=10,roty=180 -[1.14-1.14.4]patchblock:id=bell,data=8 +[1.14-1.14.4]patchblock:id=bell,data=8d [1.14-1.14.4]patchrotate:id=bell,data=10,roty=270 [1.14-1.14.4]patchblock:id=bell,data=9 [1.14-1.14.4]patchrotate:id=bell,data=10,roty=90 diff --git a/DynmapCore/src/main/resources/texture_1.txt b/DynmapCore/src/main/resources/texture_1.txt index cb1ec3f3..f966355c 100644 --- a/DynmapCore/src/main/resources/texture_1.txt +++ b/DynmapCore/src/main/resources/texture_1.txt @@ -2359,7 +2359,7 @@ block:id=black_banner,id=black_wall_banner,data=*,patch0=0:oak_planks,patch1=0:b # Stonecutter [1.14-]block:id=stonecutter,patch0=0:stonecutter_bottom,patch1=0:stonecutter_top,patch2=0:stonecutter_side,patch3=0:stonecutter_saw,transparency=TRANSPARENT # Campfire -[1.14-]block:id=campfire,patch0=0:campfire_log,patch1=0:campfire_log_lit,patch2=0:campfire_fire,transparency=TRANSPARENT +[1.14-]block:id=campfire,data=*,patch0=0:campfire_log,patch1=0:campfire_log_lit,patch2=0:campfire_fire,transparency=TRANSPARENT # Bell [1.14-]block:id=bell,patch0=0:dark_oak_planks,patch1=0:stone,patch2=0:bell_bottom,patch3=0:bell_top,patch4=0:bell_side,transparency=TRANSPARENT diff --git a/DynmapCoreAPI/src/main/java/org/dynmap/modsupport/ModelBlockModel.java b/DynmapCoreAPI/src/main/java/org/dynmap/modsupport/ModelBlockModel.java index fac5ad1f..cfdf8dc0 100644 --- a/DynmapCoreAPI/src/main/java/org/dynmap/modsupport/ModelBlockModel.java +++ b/DynmapCoreAPI/src/main/java/org/dynmap/modsupport/ModelBlockModel.java @@ -6,16 +6,22 @@ import org.dynmap.modsupport.ModelBlockModel.ModelBlock; // All coordinates are 0-16 range per block, and 0-16 range for UV public interface ModelBlockModel extends BlockModel { - + public enum SideRotation { + DEG0, // zero degrees (default) + DEG90, // 90 degrees + DEG180, // 180 degrees + DEG270 // 270 degrees + }; public interface ModelBlock { /** * Factory method for adding a side to a model block started using addModelBlock. * * @param face - which face (determines use of xyz-min vs xyz-max * @param uv - bounds on UV (umin, vmin, umax, vmax): if null, default based on face range + * @param rot - rotation of the block side (default id DEG0) * @param textureid - texture ID */ - public void addBlockSide(BlockSide side, double[] uv, int textureid); + public void addBlockSide(BlockSide side, double[] uv, SideRotation rot, int textureid); } /** * Factory method to build a block of patches relative to a typical element in a MC model file. diff --git a/DynmapCoreAPI/src/main/java/org/dynmap/renderer/RenderPatchFactory.java b/DynmapCoreAPI/src/main/java/org/dynmap/renderer/RenderPatchFactory.java index e3301f6b..2d8af70f 100644 --- a/DynmapCoreAPI/src/main/java/org/dynmap/renderer/RenderPatchFactory.java +++ b/DynmapCoreAPI/src/main/java/org/dynmap/renderer/RenderPatchFactory.java @@ -1,7 +1,7 @@ package org.dynmap.renderer; public interface RenderPatchFactory { - public enum SideVisible { TOP, BOTTOM, BOTH, FLIP }; + public enum SideVisible { TOP, BOTTOM, BOTH, FLIP, TOPFLIP }; /** * Get/create patch with given attributes.