Add more vanilla model friendly modellist type for model file, use for

comparator
This commit is contained in:
Mike Primm 2022-01-23 21:44:26 -06:00
parent 9247b7ec2f
commit 4452777585
11 changed files with 540 additions and 110 deletions

View File

@ -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<ModelBoxSide> sides = new ArrayList<ModelBoxSide>();
};
private static HashMap<String, BlockSide> toBlockSide = new HashMap<String, BlockSide>();
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<String> blknames = new ArrayList<String>();
databits.clear();
line = line.substring(10);
String[] args = line.split(",");
ArrayList<ModelBox> boxes = new ArrayList<ModelBox>();
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:<side - upnsew>/<txtidx>/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 (<side - upnsew>/<txtidx>/umin/vmin/umax/vmax> or <<side - upnsew>/<txtidx>)
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<PatchDefinition> pd = new ArrayList<PatchDefinition>();
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<String> blknames = new ArrayList<String>();
HashMap<String,String> custargs = new HashMap<String,String>();

View File

@ -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);

View File

@ -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<BlockSide, ModelSide> sides = new HashMap<BlockSide, ModelSide>();
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<ModelBlockImpl> boxes = new ArrayList<ModelBlockImpl>();
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<BlockSide, String> fromBlockSide = new HashMap<BlockSide, String>();
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;
}
}

View File

@ -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) {

View File

@ -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);
}
}

View File

@ -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<PatchDefinition,PatchDefinition> patches = new HashMap<PatchDefinition,PatchDefinition>();
@ -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);
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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 &lt;x0,y0,z0&gt; within the block, and defined by two edge vectors -
* one with and end point of &lt;xu,yu,zu&gt;, and a second with an end point of &lt;xv,yv,zv&gt;. 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: &lt;=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.
*