Finish modellist implementation, use for campfire, comparator

This commit is contained in:
Mike Primm 2022-01-29 03:57:04 -06:00
parent c6c46bdd41
commit f433454ac2
11 changed files with 267 additions and 140 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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