From 44527775850217fbe7e7345af4f9846e0fe859b9 Mon Sep 17 00:00:00 2001 From: Mike Primm Date: Sun, 23 Jan 2022 21:44:26 -0600 Subject: [PATCH] Add more vanilla model friendly modellist type for model file, use for comparator --- .../java/org/dynmap/hdmap/HDBlockModels.java | 143 ++++++++++++++++++ .../impl/ModModelDefinitionImpl.java | 30 ++++ .../modsupport/impl/ModelBlockModelImpl.java | 120 +++++++++++++++ .../modsupport/impl/PatchBlockModelImpl.java | 9 -- .../org/dynmap/utils/PatchDefinition.java | 119 +++++++++++++++ .../dynmap/utils/PatchDefinitionFactory.java | 45 ++++++ DynmapCore/src/main/resources/models_1.txt | 92 ++++------- DynmapCore/src/main/resources/texture_1.txt | 14 +- .../dynmap/modsupport/ModModelDefinition.java | 16 ++ .../dynmap/modsupport/ModelBlockModel.java | 32 ++++ .../dynmap/modsupport/PatchBlockModel.java | 30 ---- 11 files changed, 540 insertions(+), 110 deletions(-) create mode 100644 DynmapCore/src/main/java/org/dynmap/modsupport/impl/ModelBlockModelImpl.java create mode 100644 DynmapCoreAPI/src/main/java/org/dynmap/modsupport/ModelBlockModel.java diff --git a/DynmapCore/src/main/java/org/dynmap/hdmap/HDBlockModels.java b/DynmapCore/src/main/java/org/dynmap/hdmap/HDBlockModels.java index a462b82e..856aad35 100644 --- a/DynmapCore/src/main/java/org/dynmap/hdmap/HDBlockModels.java +++ b/DynmapCore/src/main/java/org/dynmap/hdmap/HDBlockModels.java @@ -22,6 +22,7 @@ import org.dynmap.DynmapCore; import org.dynmap.Log; import org.dynmap.MapManager; import org.dynmap.debug.Debug; +import org.dynmap.modsupport.BlockSide; import org.dynmap.renderer.CustomRenderer; import org.dynmap.renderer.DynmapBlockState; import org.dynmap.renderer.RenderPatch; @@ -320,6 +321,29 @@ public class HDBlockModels { int yrot = 0; int[] patches = new int[6]; // Default all to patch0 } + + private static class ModelBoxSide { + BlockSide side; + int textureid; + double[] uv; + }; + + private static class ModelBox { + double[] from = new double[3]; + double[] to = new double[3]; + ArrayList sides = new ArrayList(); + }; + + private static HashMap toBlockSide = new HashMap(); + static { + toBlockSide.put("u", BlockSide.TOP); + toBlockSide.put("d", BlockSide.BOTTOM); + toBlockSide.put("n", BlockSide.NORTH); + toBlockSide.put("s", BlockSide.SOUTH); + toBlockSide.put("w", BlockSide.WEST); + toBlockSide.put("e", BlockSide.EAST); + }; + /** * Load models from file * @param core @@ -964,6 +988,125 @@ public class HDBlockModels { Log.severe("Box list block model missing required parameters = line " + rdr.getLineNumber() + " of " + fname); } } + // Shortcur for building JSON model style + else if(line.startsWith("modellist:")) { + ArrayList blknames = new ArrayList(); + databits.clear(); + line = line.substring(10); + String[] args = line.split(","); + ArrayList boxes = new ArrayList(); + for(String a : args) { + String[] av = a.split("="); + if(av.length < 2) continue; + if(av[0].equals("id")) { + blknames.add(getBlockName(modname,av[1])); + } + else if(av[0].equals("data")) { + if(av[1].equals("*")) { + databits.clear(); + } + else if (av[1].indexOf('-') > 0) { + String[] sp = av[1].split("-"); + int m0 = getIntValue(varvals, sp[0]); + int m1 = getIntValue(varvals, sp[1]); + for (int m = m0; m <= m1; m++) { + databits.set(m); + } + } + else + databits.set(getIntValue(varvals,av[1])); + } + else if(av[0].equals("box")) { + // box=fromx/y/z:tox/y/z://umin/vmin/umax/vmax>:... + String[] prms = av[1].split(":"); + + ModelBox box = new ModelBox(); + if (prms.length > 0) { // Handle from + String[] xyz = prms[0].split("/"); + if (xyz.length == 3) { + box.from[0] = Double.parseDouble(xyz[0]); + box.from[1] = Double.parseDouble(xyz[1]); + box.from[2] = Double.parseDouble(xyz[2]); + } + else { + Log.severe("Invalid modellist FROM value (" + prms[0] + " at line " + rdr.getLineNumber()); + } + } + if (prms.length > 1) { // Handle to + String[] xyz = prms[1].split("/"); + if (xyz.length == 3) { + box.to[0] = Double.parseDouble(xyz[0]); + box.to[1] = Double.parseDouble(xyz[1]); + box.to[2] = Double.parseDouble(xyz[2]); + } + else { + Log.severe("Invalid modellist TO value (" + prms[1] + " at line " + rdr.getLineNumber()); + } + } + // Rest are faces (//umin/vmin/umax/vmax> or </) + for (int faceidx = 2; faceidx < prms.length; faceidx++) { + String v = prms[faceidx]; + String[] flds = v.split("/"); + ModelBoxSide side = new ModelBoxSide(); + if (flds.length > 0) { + String face = flds[0]; + side.side = toBlockSide.get(face); + if (side.side == null) { + Log.severe("Invalid modellist side value (" + face + " at line " + rdr.getLineNumber()); + continue; + } + } + if (flds.length > 1) { + side.textureid = getIntValue(varvals, flds[1]); + } + if (flds.length >= 6) { + side.uv = new double[4]; + side.uv[0] = Double.parseDouble(flds[2]); + side.uv[1] = Double.parseDouble(flds[3]); + side.uv[2] = Double.parseDouble(flds[4]); + side.uv[3] = Double.parseDouble(flds[5]); + } + box.sides.add(side); + } + boxes.add(box); + } + } + /* If we have everything, build block */ + pmodlist.clear(); + if (blknames.size() > 0) { + ArrayList pd = new ArrayList(); + + 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); + if (patch != null) { + pd.add(patch); + Log.info("patch=" + patch); + } + } + } + PatchDefinition[] patcharray = new PatchDefinition[pd.size()]; + for (int i = 0; i < patcharray.length; i++) { + patcharray[i] = pd.get(i); + } + if (patcharray.length > max_patches) + max_patches = patcharray.length; + for(String nm : blknames) { + DynmapBlockState bs = DynmapBlockState.getBaseStateByName(nm); + if (bs.isNotAir()) { + pmodlist.add(new HDBlockPatchModel(bs, databits, patcharray, blockset)); + cnt++; + } + else { + Log.severe("Invalid modellist block name " + nm + " at line " + rdr.getLineNumber()); + } + } + } + else { + Log.severe("Model list block model missing required parameters = line " + rdr.getLineNumber() + " of " + fname); + } + } else if(line.startsWith("customblock:")) { ArrayList blknames = new ArrayList(); HashMap custargs = new HashMap(); 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 98cb19e6..6e8750a0 100644 --- a/DynmapCore/src/main/java/org/dynmap/modsupport/impl/ModModelDefinitionImpl.java +++ b/DynmapCore/src/main/java/org/dynmap/modsupport/impl/ModModelDefinitionImpl.java @@ -8,11 +8,13 @@ import java.util.LinkedHashMap; import java.util.Locale; import org.dynmap.hdmap.HDBlockModels; +import org.dynmap.modsupport.BlockSide; import org.dynmap.modsupport.BoxBlockModel; import org.dynmap.modsupport.CuboidBlockModel; import org.dynmap.modsupport.DoorBlockModel; import org.dynmap.modsupport.ModModelDefinition; import org.dynmap.modsupport.ModTextureDefinition; +import org.dynmap.modsupport.ModelBlockModel; import org.dynmap.modsupport.PaneBlockModel; import org.dynmap.modsupport.PatchBlockModel; import org.dynmap.modsupport.PlantBlockModel; @@ -190,6 +192,19 @@ public class ModModelDefinitionImpl implements ModModelDefinition { blkModel.add(mod); return mod; } + + @Override + public ModelBlockModel addModelBlockModel(String blockname) { + ModelBlockModelImpl mod = new ModelBlockModelImpl(blockname, this); + blkModel.add(mod); + return mod; + } + @Override + public ModelBlockModel addRotatedModelBlockModel(String blockname, ModelBlockModel model, int xrot, int yrot, int zrot) { + ModelBlockModelImpl mod = new ModelBlockModelImpl(blockname, this, model, xrot, yrot, zrot); + blkModel.add(mod); + return mod; + } public String getPatchID(double x0, double y0, double z0, double xu, double yu, double zu, double xv, double yv, double zv, double umin, @@ -207,6 +222,21 @@ public class ModModelDefinitionImpl implements ModModelDefinition { blkPatchMap.put(id, pd); return id; } + + public String getModelFacePatchID(double[] from, double[] to, BlockSide face, double[] uv, int textureid) { + PatchDefinition pd = pdf.getModelFace(from, to, face, uv, textureid); + if (pd == null) + return null; // Invalid patch + for (int i = 0; i < blkPatch.size(); i++) { + if (blkPatch.get(i) == pd) { + return "patch" + i; + } + } + blkPatch.add(pd); + String id = "patch" + (blkPatch.size() - 1); + blkPatchMap.put(id, pd); + return id; + } public String getRotatedPatchID(String patchid, int xrot, int yrot, int zrot) { PatchDefinition pd = blkPatchMap.get(patchid); diff --git a/DynmapCore/src/main/java/org/dynmap/modsupport/impl/ModelBlockModelImpl.java b/DynmapCore/src/main/java/org/dynmap/modsupport/impl/ModelBlockModelImpl.java new file mode 100644 index 00000000..b26aac70 --- /dev/null +++ b/DynmapCore/src/main/java/org/dynmap/modsupport/impl/ModelBlockModelImpl.java @@ -0,0 +1,120 @@ +package org.dynmap.modsupport.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; + +import org.dynmap.modsupport.BlockSide; +import org.dynmap.modsupport.ModelBlockModel; + +public class ModelBlockModelImpl extends BlockModelImpl implements ModelBlockModel { + + private static class ModelSide { + private double[] uv; + int textureid; + }; + private static class ModelBlockImpl implements ModelBlock { + private HashMap sides = new HashMap(); + private double[] from = { 0, 0, 0 }; + private double[] to = { 16, 16, 16 }; + @Override + public void addBlockSide(BlockSide side, double[] uv, int textureid) { + ModelSide ms = new ModelSide(); + ms.textureid = textureid; + if (uv != null) { + ms.uv = Arrays.copyOf(uv, uv.length); + } + 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; + if (side == BlockSide.FACE_3 || side == BlockSide.Z_PLUS) side = BlockSide.SOUTH; + if (side == BlockSide.FACE_4 || side == BlockSide.X_MINUS) side = BlockSide.WEST; + if (side == BlockSide.FACE_5 || side == BlockSide.X_PLUS) side = BlockSide.EAST; + + sides.put(side, ms); + } + } + private ArrayList boxes = new ArrayList(); + private String rotsourceblockname; + private int rotsourcemetaindex; + private int xrot, yrot, zrot; + + public ModelBlockModelImpl(String blkname, ModModelDefinitionImpl mdf) { + super(blkname, mdf); + } + + public ModelBlockModelImpl(String blkname, ModModelDefinitionImpl mdf, ModelBlockModel mod, int xrot, int yrot, int zrot) { + super(blkname, mdf); + this.rotsourceblockname = mod.getBlockNames()[0]; + this.rotsourcemetaindex = Integer.numberOfTrailingZeros(mod.getMetaValueMask()); + this.xrot = xrot; this.yrot = yrot; this.zrot = zrot; + } + + private static HashMap fromBlockSide = new HashMap(); + static { + fromBlockSide.put(BlockSide.TOP, "u"); + fromBlockSide.put(BlockSide.BOTTOM, "d"); + fromBlockSide.put(BlockSide.NORTH, "n"); + fromBlockSide.put(BlockSide.SOUTH, "s"); + fromBlockSide.put(BlockSide.WEST, "e"); + fromBlockSide.put(BlockSide.EAST, "w"); + }; + + @Override + public String getLine() { + String ids = this.getIDsAndMeta(); + if (ids == null) return null; + String line = String.format("patchblock:%s", ids); + // If rotating another model + if (rotsourceblockname != null) { + line += "\npatchrotate:id=" + rotsourceblockname + ",data=" + rotsourcemetaindex; + if (xrot != 0) { + line += ",rotx=" + xrot; + } + if (yrot != 0) { + line += ",roty=" + yrot; + } + if (zrot != 0) { + line += ",rotz=" + yrot; + } + } + else { + for (ModelBlockImpl mb: boxes) { + line += String.format(",box=%f/%f/%f:%f/%f/%f", mb.from[0], mb.from[1], mb.from[2], mb.to[0], mb.to[1], mb.to[2]); + for (BlockSide bs : fromBlockSide.keySet()) { + String side = fromBlockSide.get(bs); + ModelSide mside = mb.sides.get(bs); + if (mside != null) { + 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]); + } + else { + line += String.format(":%s/%d", side, mside.textureid); + } + } + } + } + } + return line; + } + /** + * Factory method to build a block of patches relative to a typical element in a MC model file. + * Specifically, all coordinates are relative to 0-16 range for + * side of a cube, and relative to 0-16 range for U,V within a texture: + * + * from, to in model drive 'from', 'to' inputs + * + * face, uv of face, and texture in model drives face, uv, textureid (added using addBlockSide) + * + * @param from - vector of lower left corner of box (0-16 range for coordinates - min x, y, z) + * @param to - vector of upper right corner of box (0-16 range for coordinates max x, y, z) + * @return model block to add faces to + */ + public ModelBlock addModelBlock(double[] from, double[] to) { + ModelBlockImpl mbi = new ModelBlockImpl(); + if (from != null) { mbi.from[0] = from[0]; mbi.from[1] = from[1]; mbi.from[2] = from[2]; } + if (to != null) { mbi.to[0] = to[0]; mbi.to[1] = to[1]; mbi.to[2] = to[2]; } + boxes.add(mbi); + return mbi; + } +} diff --git a/DynmapCore/src/main/java/org/dynmap/modsupport/impl/PatchBlockModelImpl.java b/DynmapCore/src/main/java/org/dynmap/modsupport/impl/PatchBlockModelImpl.java index cf7b5f42..80f26e16 100644 --- a/DynmapCore/src/main/java/org/dynmap/modsupport/impl/PatchBlockModelImpl.java +++ b/DynmapCore/src/main/java/org/dynmap/modsupport/impl/PatchBlockModelImpl.java @@ -46,15 +46,6 @@ public class PatchBlockModelImpl extends BlockModelImpl implements PatchBlockMod return pi; } - @Override - @Deprecated - public String addPatch(double x0, double y0, double z0, double xu, double yu, - double zu, double xv, double yv, double zv, double umin, - double umax, double vmin, double vmax, double uplusvmax, - SideVisible sidevis) { - return addPatch(x0, y0, z0, xu, yu, zu, xv, yv, zv, umin, umax, vmin, vmin, vmax, ((uplusvmax - umax) < vmax) ? uplusvmax - umax : vmax, sidevis); - } - @Override public String addPatch(double x0, double y0, double z0, double xu, double yu, double zu, double xv, double yv, double zv, SideVisible sidevis) { diff --git a/DynmapCore/src/main/java/org/dynmap/utils/PatchDefinition.java b/DynmapCore/src/main/java/org/dynmap/utils/PatchDefinition.java index 839f543a..f975fa87 100644 --- a/DynmapCore/src/main/java/org/dynmap/utils/PatchDefinition.java +++ b/DynmapCore/src/main/java/org/dynmap/utils/PatchDefinition.java @@ -1,9 +1,20 @@ package org.dynmap.utils; import org.dynmap.Log; +import org.dynmap.modsupport.BlockSide; import org.dynmap.renderer.RenderPatch; import org.dynmap.renderer.RenderPatchFactory.SideVisible; +// +// (v = 1) umin umax +// x0+xv,y0+yv,z0+zv *-----|-------|--------* (u=1, v=1) x0,y0,z0 = lower left corner relative to cube origin (0,0,0 to 1,1,1) +// | | | | length of xu,yu,zu = width of whole texture (u=0 to u=1) +// |-----+=======+--------| vmax length of xv,yv,zv = height of whole texture (v=0 to v=1) +// | [visible] | umin to umax = clipping (visible portion of texture) horizontally +// |-----+=======+--------| vmin vmin to vmax = clipping (visible portion of texture) vertically +// (u=0,v=0)| | | | +// x0,y0,z0 *----|-------|--------* x0+xu, y0+yu, z0+zu (u = 1) +// /* Define patch in surface-based models - origin (xyz), u-vector (xyz) v-vector (xyz), u limits and v limits */ public class PatchDefinition implements RenderPatch { public double x0, y0, z0; /* Origin of patch (lower left corner of texture) */ @@ -280,4 +291,112 @@ public class PatchDefinition implements RenderPatch { return String.format("xyz0=%f/%f/%f,xyzU=%f/%f/%f,xyzV=%f/%f/%f,minU=%f,maxU=%f,vMin=%f/%f,vmax=%f/%f,side=%s,txtidx=%d", x0, y0, z0, xu, yu, zu, xv, yv, zv, umin, umax, vmin, vminatumax, vmax, vmaxatumax, sidevis, textureindex); } + + // + // Update patch relative to typical parameters found in + // minecraft model files. Specifically, all coordinates are relative to 0-16 range for + // side of a cube, and relative to 0-16 range for U,V within a texture: + // + // from, to in model drive 'from', 'to' inputs + // face, uv of face, and texture in model drives face, uv, textureid + // + // @param from - vector of lower left corner of box (0-16 range for coordinates - min x, y, z) + // @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 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; + 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; + } + // 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 + } + // 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); + } } diff --git a/DynmapCore/src/main/java/org/dynmap/utils/PatchDefinitionFactory.java b/DynmapCore/src/main/java/org/dynmap/utils/PatchDefinitionFactory.java index aeadc367..a1e69fa8 100644 --- a/DynmapCore/src/main/java/org/dynmap/utils/PatchDefinitionFactory.java +++ b/DynmapCore/src/main/java/org/dynmap/utils/PatchDefinitionFactory.java @@ -4,8 +4,11 @@ import java.util.HashMap; import java.util.Map; import org.dynmap.hdmap.TexturePack; +import org.dynmap.modsupport.BlockSide; import org.dynmap.renderer.RenderPatch; import org.dynmap.renderer.RenderPatchFactory; +import org.dynmap.renderer.RenderPatchFactory.SideVisible; +import org.dynmap.Log; public class PatchDefinitionFactory implements RenderPatchFactory { private HashMap patches = new HashMap(); @@ -62,6 +65,22 @@ public class PatchDefinitionFactory implements RenderPatchFactory { } } + + public PatchDefinition getModelFace(double[] from, double[] to, BlockSide face, double[] uv, int textureid) { + synchronized(lock) { + lookup.updateModelFace(from, to, face, uv, textureid); + if(lookup.validate() == false) + return null; + PatchDefinition pd2 = patches.get(lookup); /* See if in cache already */ + if(pd2 == null) { + PatchDefinition pd = new PatchDefinition(lookup); + patches.put(pd, pd); + pd2 = pd; + } + return pd2; + } + } + @Override public RenderPatch getRotatedPatch(RenderPatch patch, int xrot, int yrot, int zrot, int textureindex) { @@ -163,4 +182,30 @@ public class PatchDefinitionFactory implements RenderPatchFactory { return TexturePack.getTextureMapLength(id); } + 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 }; + + // 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); + } + + 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/resources/models_1.txt b/DynmapCore/src/main/resources/models_1.txt index d26dbae5..c168a0af 100644 --- a/DynmapCore/src/main/resources/models_1.txt +++ b/DynmapCore/src/main/resources/models_1.txt @@ -946,66 +946,38 @@ patchrotate:id=anvil,data=1,rot=180 # Daylight Sensor boxblock:id=daylight_detector,ymax=0.375 -# (149) Redstone Comparator (inactive) -# (150) Redstone Comparator (active) -block:id=comparator,data=0,data=1,data=2,data=3,scale=16 -layer:0,1 -**************** -**************** -**************** -**************** -**************** -**************** -**************** -**************** -**************** -**************** -**************** -**************** -**************** -**************** -**************** -**************** -layer:2,3 ----------------- ----------------- ----------------- ----------------- ----**----------- ----**----------- ----------------- -------------**-- -------------**-- ----------------- ----**----------- ----**----------- ----------------- ----------------- ----------------- ----------------- -layer:4,5,6 ----------------- ----------------- ----------------- ----------------- ----**----------- ----**----------- ----------------- ----------------- ----------------- ----------------- ----**----------- ----**----------- ----------------- ----------------- ----------------- ----------------- -block:id=comparator,data=4,data=5,data=6,data=7,scale=16 -rotate:id=comparator,data=0,rot=90 -block:id=comparator,,data=8,data=9,data=10,data=11,scale=16 -rotate:id=comparator,data=0,rot=180 -block:id=comparator,data=12,data=13,data=14,data=15,scale=16 -rotate:id=comparator,data=0,rot=270 +# Comparator (compare mode, off) - slab, comparator, unlit, lit, comparator_on +modellist:id=comparator,data=5,box=0/0/0:16/2/16:d/0/0/0/16/16:u/1/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/2/11:6/7/13:d/2/7/13/9/15:u/2/7/6/9/8:n/2/7/6/9/11:s/2/7/6/9/11:w/2/7/6/9/11:e/2/7/6/9/11,box=10/2/11:12/7/13:d/2/7/13/9/15:u/2/7/6/9/8:n/2/7/6/9/11:s/2/7/6/9/11:w/2/7/6/9/11:e/2/7/6/9/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=1 +patchrotate:id=comparator,data=5,rot=180 +patchblock:id=comparator,data=9 +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 +patchblock:id=comparator,data=0 +patchrotate:id=comparator,data=4,rot=180 +patchblock:id=comparator,data=8 +patchrotate:id=comparator,data=4,rot=90 +patchblock:id=comparator,data=12 +patchrotate:id=comparator,data=4,rot=270 +# Comparator (subtract mode, off) - slab, comparator, unlit, lit, comparator_on +modellist:id=comparator,data=7,box=0/0/0:16/2/16:d/0/0/0/16/16:u/1/0/0/16/16:n/0/0/14/16/16:s/0/0/14/16/16:e/0/0/14/16/16:w/0/0/14/16/16,box=4/2/11:6/7/13:d/2/7/13/9/15:u/2/7/6/9/8:n/2/7/6/9/11:s/2/7/6/9/11:w/2/7/6/9/11:e/2/7/6/9/11,box=10/2/11:12/7/13:d/2/7/13/9/15:u/2/7/6/9/8:n/2/7/6/9/11:s/2/7/6/9/11:w/2/7/6/9/11:e/2/7/6/9/11,box=7/5/2:9/5/4:u/3/7/6/9/8,box=7/2/1:9/6/5:w/3/6/5/10/9:e/3/6/5/10/9,box=6/2/2:10/6/4:n/3/6/5/10/9:s/3/6/5/10/9 +patchblock:id=comparator,data=3 +patchrotate:id=comparator,data=7,rot=180 +patchblock:id=comparator,data=11 +patchrotate:id=comparator,data=7,rot=90 +patchblock:id=comparator,data=15 +patchrotate:id=comparator,data=7,rot=270 +# Comparator (subtract mode, on) - slab, comparator, unlit, lit, comparator_on +modellist:id=comparator,data=6,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/2/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/5/2:9/5/4:u/3/7/6/9/8,box=7/2/1:9/6/5:w/3/6/5/10/9:e/3/6/5/10/9,box=6/2/2:10/6/4:n/3/6/5/10/9:s/3/6/5/10/9 +patchblock:id=comparator,data=2 +patchrotate:id=comparator,data=6,rot=180 +patchblock:id=comparator,data=10 +patchrotate:id=comparator,data=6,rot=90 +patchblock:id=comparator,data=14 +patchrotate:id=comparator,data=6,rot=270 # (154) Hopper block:id=hopper,scale=16 diff --git a/DynmapCore/src/main/resources/texture_1.txt b/DynmapCore/src/main/resources/texture_1.txt index f69b1dba..cb1ec3f3 100644 --- a/DynmapCore/src/main/resources/texture_1.txt +++ b/DynmapCore/src/main/resources/texture_1.txt @@ -88,6 +88,7 @@ texture:id=dropper_front texture:id=dropper_front_vertical texture:id=hopper_inside texture:id=hopper_outside +texture:id=smooth_stone texture:id=black_terracotta texture:id=blue_terracotta texture:id=brown_terracotta @@ -1358,16 +1359,8 @@ block:id=light_weighted_pressure_plate,allfaces=0:gold_block,stdrot=true,transpa # Heavy weighted pressure plate block:id=heavy_weighted_pressure_plate,allfaces=0:iron_block,stdrot=true,transparency=TRANSPARENT -# Redstone Comparator (active) -block:id=comparator,data=0,data=2,top=6000:comparator_on,allsides=0:stone,bottom=0:stone,transparency=TRANSPARENT -block:id=comparator,data=4,data=6,top=5000:comparator_on,allsides=0:stone,bottom=0:stone,transparency=TRANSPARENT -block:id=comparator,data=8,data=10,top=4000:comparator_on,allsides=0:stone,bottom=0:stone,transparency=TRANSPARENT -block:id=comparator,data=12,data=14,top=0:comparator_on,allsides=0:stone,bottom=0:stone,transparency=TRANSPARENT -# Redstone Comparator (inactive) -block:id=comparator,data=1,data=3,top=6000:comparator,allsides=0:stone,bottom=0:stone,transparency=TRANSPARENT -block:id=comparator,data=5,data=7,top=5000:comparator,allsides=0:stone,bottom=0:stone,transparency=TRANSPARENT -block:id=comparator,data=9,data=11,top=4000:comparator,allsides=0:stone,bottom=0:stone,transparency=TRANSPARENT -block:id=comparator,data=13,data=15,top=0:comparator,allsides=0:stone,bottom=0:stone,transparency=TRANSPARENT +# Comparator (on) +block:id=comparator,data=*,patch0=0:smooth_stone,patch1=0:comparator,patch2=0:redstone_torch_off,patch3=0:redstone_torch,patch4=0:comparator_on,transparency=TRANSPARENT # Daylight Sensor # Inverted Daylight Sensor @@ -2132,7 +2125,6 @@ block:id=black_banner,id=black_wall_banner,data=*,patch0=0:oak_planks,patch1=0:b [1.14-]texture:id=wither_rose [1.14-]texture:id=lily_of_the_valley [1.14-]texture:id=smooth_stone_slab_side -[1.14-]texture:id=smooth_stone [1.14-]texture:id=bamboo_stage0 [1.14-]texture:id=bamboo_stalk [1.14-]texture:id=scaffolding_top diff --git a/DynmapCoreAPI/src/main/java/org/dynmap/modsupport/ModModelDefinition.java b/DynmapCoreAPI/src/main/java/org/dynmap/modsupport/ModModelDefinition.java index 47336bfd..bd871a6a 100644 --- a/DynmapCoreAPI/src/main/java/org/dynmap/modsupport/ModModelDefinition.java +++ b/DynmapCoreAPI/src/main/java/org/dynmap/modsupport/ModModelDefinition.java @@ -151,6 +151,22 @@ public interface ModModelDefinition { * @return block model record */ public PatchBlockModel addRotatedPatchModel(String blockname, PatchBlockModel model, int xrot, int yrot, int zrot); + /** + * Add model block model: default assumes all metadata values are matching + * @param blockname - block name + * @return block model record + */ + public ModelBlockModel addModelBlockModel(String blockname); + /** + * Add rotated model block model, based on existing model : default assumes all metadata values are matching + * @param blockname - block name + * @param model - existing model to be rotated + * @param xrot - x rotation in degrees (0, 90, 180, 270) + * @param yrot - y rotation in degrees (0, 90, 180, 270) + * @param zrot - z rotation in degrees (0, 90, 180, 270) + * @return block model record + */ + public ModelBlockModel addRotatedModelBlockModel(String blockname, ModelBlockModel model, int xrot, int yrot, int zrot); /** * Final call for model definition: publishes definiiton to Dynmap to be used for the mod * @return true if successful, false if error diff --git a/DynmapCoreAPI/src/main/java/org/dynmap/modsupport/ModelBlockModel.java b/DynmapCoreAPI/src/main/java/org/dynmap/modsupport/ModelBlockModel.java new file mode 100644 index 00000000..41722ddb --- /dev/null +++ b/DynmapCoreAPI/src/main/java/org/dynmap/modsupport/ModelBlockModel.java @@ -0,0 +1,32 @@ +package org.dynmap.modsupport; + +// Model for more direct translation of MC models +// All coordinates are 0-16 range per block, and 0-16 range for UV + +public interface ModelBlockModel extends BlockModel { + + 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 textureid - texture ID + */ + public void addBlockSide(BlockSide side, double[] uv, int textureid); + } + /** + * Factory method to build a block of patches relative to a typical element in a MC model file. + * Specifically, all coordinates are relative to 0-16 range for + * side of a cube, and relative to 0-16 range for U,V within a texture: + * + * from, to in model drive 'from', 'to' inputs + * + * face, uv of face, and texture in model drives face, uv, textureid (added using addBlockSide) + * + * @param from - vector of lower left corner of box (0-16 range for coordinates - min x, y, z) + * @param to - vector of upper right corner of box (0-16 range for coordinates max x, y, z) + * @return model block to add faces to + */ + public ModelBlock addModelBlock(double[] from, double[] to); +} diff --git a/DynmapCoreAPI/src/main/java/org/dynmap/modsupport/PatchBlockModel.java b/DynmapCoreAPI/src/main/java/org/dynmap/modsupport/PatchBlockModel.java index af967a7c..38aa6946 100644 --- a/DynmapCoreAPI/src/main/java/org/dynmap/modsupport/PatchBlockModel.java +++ b/DynmapCoreAPI/src/main/java/org/dynmap/modsupport/PatchBlockModel.java @@ -6,36 +6,6 @@ import org.dynmap.renderer.RenderPatchFactory.SideVisible; * Patch block model */ public interface PatchBlockModel extends BlockModel { - /** - * Add patch with given attributes. - * - * Definition is a 2D parallelogram surface, with origin <x0,y0,z0> within the block, and defined by two edge vectors - - * one with and end point of <xu,yu,zu>, and a second with an end point of <xv,yv,zv>. The patch is - * defined within the unit vector range umin to umax (parallel to the U vecotr) and vmin to vmax - * (parallel to the V vector). - * The surface can be visible via one side (SideVisible.TOP, SideVisible.BOTTOM) or both sides (SideVisible.BOTH). - * - * @param x0 - X coordinate of origin of patch - * @param y0 - Y coordinate of origin of patch - * @param z0 - Z coordinate of origin of patch - * @param xu - X coordinate of end of U vector - * @param yu - Y coordinate of end of U vector - * @param zu - Z coordinate of end of U vector - * @param xv - X coordinate of end of V vector - * @param yv - Y coordinate of end of V vector - * @param zv - Z coordinate of end of V vector - * @param umin - lower bound for visibility along U vector (use 0.0 by default) - * @param umax - upper bound for visibility along U vector (use 1.0 by default) - * @param vmin - lower bound for visibility along V vector (use 0.0 by default) - * @param vmax - upper bound for visibility along V vector (use 1.0 by default) - * @param uplusvmax - upper bound for visibility for U+V (use 100.0 by default: <=1.0 for triangle) - * @param sidevis - Controls which sides of the surface are visible (U cross V defines normal - TOP is from that side, BOTTOM is opposite side) - * @return patch ID - */ - @Deprecated - public String addPatch(double x0, double y0, double z0, double xu, - double yu, double zu, double xv, double yv, double zv, double umin, - double umax, double vmin, double vmax, double uplusvmax, SideVisible sidevis); /** * Add patch with given attributes. *