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.MapManager;
import org.dynmap.debug.Debug; import org.dynmap.debug.Debug;
import org.dynmap.modsupport.BlockSide; import org.dynmap.modsupport.BlockSide;
import org.dynmap.modsupport.ModelBlockModel;
import org.dynmap.renderer.CustomRenderer; import org.dynmap.renderer.CustomRenderer;
import org.dynmap.renderer.DynmapBlockState; import org.dynmap.renderer.DynmapBlockState;
import org.dynmap.renderer.RenderPatch; import org.dynmap.renderer.RenderPatch;
@ -326,6 +327,7 @@ public class HDBlockModels {
BlockSide side; BlockSide side;
int textureid; int textureid;
double[] uv; double[] uv;
ModelBlockModel.SideRotation rot;
}; };
private static class ModelBox { private static class ModelBox {
@ -1054,13 +1056,32 @@ public class HDBlockModels {
String v = prms[faceidx]; String v = prms[faceidx];
String[] flds = v.split("/"); String[] flds = v.split("/");
ModelBoxSide side = new ModelBoxSide(); 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) { if (flds.length > 0) {
String face = flds[0]; String face = flds[0];
side.side = toBlockSide.get(face); side.side = toBlockSide.get(face.substring(0, 1));
if (side.side == null) { 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; 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) { if (flds.length > 1) {
side.textureid = getIntValue(varvals, flds[1]); side.textureid = getIntValue(varvals, flds[1]);
@ -1085,7 +1106,7 @@ public class HDBlockModels {
for (ModelBox bl : boxes) { for (ModelBox bl : boxes) {
// Loop through faces // Loop through faces
for (ModelBoxSide side : bl.sides) { 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 (patch != null) {
// If any rotations, apply them here // If any rotations, apply them here
if ((bl.xrot != 0) || (bl.yrot != 0) || (bl.zrot != 0)) { if ((bl.xrot != 0) || (bl.yrot != 0) || (bl.zrot != 0)) {
@ -1093,6 +1114,9 @@ public class HDBlockModels {
} }
pd.add(patch); 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()]; PatchDefinition[] patcharray = new PatchDefinition[pd.size()];

View File

@ -408,6 +408,7 @@ public class IsoHDPerspective implements HDPerspective {
/* If parallel to surface, no intercept */ /* If parallel to surface, no intercept */
switch(pd.sidevis) { switch(pd.sidevis) {
case TOP: case TOP:
case TOPFLIP:
if (det < 0.000001) { if (det < 0.000001) {
return hitcnt; return hitcnt;
} }
@ -454,6 +455,9 @@ public class IsoHDPerspective implements HDPerspective {
patch_id[hitcnt] = pd.textureindex; patch_id[hitcnt] = pd.textureindex;
if(det > 0) { if(det > 0) {
patch_step[hitcnt] = pd.step.opposite(); patch_step[hitcnt] = pd.step.opposite();
if (pd.sidevis == SideVisible.TOPFLIP) {
patch_u[hitcnt] = 1 - u;
}
} }
else { else {
if (pd.sidevis == SideVisible.FLIP) { if (pd.sidevis == SideVisible.FLIP) {

View File

@ -223,8 +223,8 @@ public class ModModelDefinitionImpl implements ModModelDefinition {
return id; return id;
} }
public String getModelFacePatchID(double[] from, double[] to, BlockSide face, double[] uv, int 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, textureid); PatchDefinition pd = pdf.getModelFace(from, to, face, uv, rot, textureid);
if (pd == null) if (pd == null)
return null; // Invalid patch return null; // Invalid patch
for (int i = 0; i < blkPatch.size(); i++) { 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.BlockSide;
import org.dynmap.modsupport.ModelBlockModel; import org.dynmap.modsupport.ModelBlockModel;
import org.dynmap.modsupport.ModelBlockModel.SideRotation;
public class ModelBlockModelImpl extends BlockModelImpl implements ModelBlockModel { public class ModelBlockModelImpl extends BlockModelImpl implements ModelBlockModel {
private static class ModelSide { private static class ModelSide {
private double[] uv; private double[] uv;
private SideRotation rot;
int textureid; int textureid;
}; };
private static class ModelBlockImpl implements ModelBlock { 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[] to = { 16, 16, 16 };
private double xrot = 0, yrot = 0, zrot = 0; private double xrot = 0, yrot = 0, zrot = 0;
@Override @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(); ModelSide ms = new ModelSide();
ms.textureid = textureid; ms.textureid = textureid;
if (uv != null) { if (uv != null) {
ms.uv = Arrays.copyOf(uv, uv.length); 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_0 || side == BlockSide.Y_MINUS) side = BlockSide.BOTTOM;
if (side == BlockSide.FACE_1 || side == BlockSide.Y_PLUS) side = BlockSide.TOP; 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_2 || side == BlockSide.Z_MINUS) side = BlockSide.NORTH;
@ -89,11 +94,26 @@ public class ModelBlockModelImpl extends BlockModelImpl implements ModelBlockMod
String side = fromBlockSide.get(bs); String side = fromBlockSide.get(bs);
ModelSide mside = mb.sides.get(bs); ModelSide mside = mb.sides.get(bs);
if (mside != null) { 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) { 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 { 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.Log;
import org.dynmap.modsupport.BlockSide; import org.dynmap.modsupport.BlockSide;
import org.dynmap.modsupport.ModelBlockModel;
import org.dynmap.renderer.RenderPatch; import org.dynmap.renderer.RenderPatch;
import org.dynmap.renderer.RenderPatchFactory.SideVisible; import org.dynmap.renderer.RenderPatchFactory.SideVisible;
@ -256,7 +257,9 @@ public class PatchDefinition implements RenderPatch {
Log.severe("Invalid vmaxatumax=" + vmaxatumax); Log.severe("Invalid vmaxatumax=" + vmaxatumax);
good = false; good = false;
} }
if (!good) {
Log.warning("Patch not valid: " + toString());
}
return good; return good;
} }
@Override @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 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 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 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 // @param textureid - texture ID
public void updateModelFace(double[] from, double[] to, BlockSide face, double[] uv, int textureid) { public void updateModelFace(double[] from, double[] to, BlockSide face, double[] uv, ModelBlockModel.SideRotation rot, 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) if (rot == null) rot = ModelBlockModel.SideRotation.DEG0;
double x0 = 0, xu = 1, xv = 0, y0 = 0, yu = 0, yv = 1, z0 = 0, zu = 0, zv = 0; // Compute corners of the face
double umin = 0, vmin = 0, umax = 1, vmax = 1; 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) { switch (face) {
case BOTTOM: case BOTTOM:
case FACE_0: case FACE_0:
case Y_MINUS: case Y_MINUS:
// Bottom - Y-negative (top towards south (+Z), right towards east (+x)) // Bottom - Y-negative (top towards south (+Z), right towards east (+x))
x0 = xv = from[0] / 16.0; xu = to[0] / 16.0; lowleft = new Vector3D(from[0] / 16.0, from[1] / 16.0, from[2] / 16.0);
y0 = yu = yv = from[1] / 16.0; // Bottom lowright = new Vector3D(to[0] / 16.0, from[1] / 16.0, from[2] / 16.0);
z0 = zu = from[2] / 16.0; zv = to[2] / 16.0; upleft = new Vector3D(from[0] / 16.0, from[1] / 16.0, to[2] / 16.0);
umin = x0; umax = xu; upright = new Vector3D(to[0] / 16.0, from[1] / 16.0, to[2] / 16.0);
vmin = z0; vmax = zv; break;
break; case TOP:
case TOP: case FACE_1:
case FACE_1: case Y_PLUS:
case Y_PLUS: // Top - Y-positive (top towards north (-Z), right towards east (+x))
// 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);
x0 = xv = from[0] / 16.0; xu = to[0] / 16.0; lowright = new Vector3D(to[0] / 16.0, to[1] / 16.0, to[2] / 16.0);
y0 = yu = yv = to[1] / 16.0; // Top upleft = new Vector3D(from[0] / 16.0, to[1] / 16.0, from[2] / 16.0);
z0 = zu = to[2] / 16.0; zv = from[2] / 16.0; upright = new Vector3D(to[0] / 16.0, to[1] / 16.0, from[2] / 16.0);
umin = x0; umax = xu; break;
vmin = 1 - z0; vmax = 1 - zv; case NORTH:
break; case FACE_2:
case NORTH: case Z_MINUS:
case FACE_2: // North - Z-negative (top towards up (+Y), right towards west (-X))
case Z_MINUS: lowleft = new Vector3D(to[0] / 16.0, from[1] / 16.0, from[2] / 16.0);
// North - Z-negative (top towards up (+Y), right towards west (-X)) lowright = new Vector3D(from[0] / 16.0, from[1] / 16.0, from[2] / 16.0);
x0 = xv = to[0] / 16.0; xu = from[0] / 16.0; upleft = new Vector3D(to[0] / 16.0, to[1] / 16.0, from[2] / 16.0);
y0 = yu = from[1] / 16.0; yv = to[1] / 16.0; upright = new Vector3D(from[0] / 16.0, to[1] / 16.0, from[2] / 16.0);
z0 = zu = zv = from[2] / 16.0; break;
umin = 1 - x0; umax = 1 - xu; case SOUTH:
vmin = y0; vmax = yv; case FACE_3:
break; case Z_PLUS:
case SOUTH: // South - Z-positive (top towards up (+Y), right towards east (+X))
case FACE_3: lowleft = new Vector3D(from[0] / 16.0, from[1] / 16.0, to[2] / 16.0);
case Z_PLUS: lowright = new Vector3D(to[0] / 16.0, from[1] / 16.0,to[2] / 16.0);
// South - Z-positive (top towards up (+Y), right towards east (+X)) upleft = new Vector3D(from[0] / 16.0, to[1] / 16.0, to[2] / 16.0);
x0 = xv = from[0] / 16.0; xu = to[0] / 16.0; upright = new Vector3D(to[0] / 16.0, to[1] / 16.0, to[2] / 16.0);
y0 = yu = from[1] / 16.0; yv = to[1] / 16.0; break;
z0 = zu = zv = to[2] / 16.0; case WEST:
umin = x0; umax = xu; case FACE_4:
vmin = y0; vmax = yv; case X_MINUS:
break; // West - X-negative (top towards up (+Y), right towards south (+Z))
case WEST: lowleft = new Vector3D(from[0] / 16.0, from[1] / 16.0, from[2] / 16.0);
case FACE_4: lowright = new Vector3D(from[0] / 16.0, from[1] / 16.0, to[2] / 16.0);
case X_MINUS: upleft = new Vector3D(from[0] / 16.0, to[1] / 16.0, from[2] / 16.0);
// West - X-negative (top towards up (+Y), right towards south (+Z)) upright = new Vector3D(from[0] / 16.0, to[1] / 16.0, to[2] / 16.0);
x0 = xu = xv = from[0] / 16.0; break;
y0 = yu = from[1] / 16.0; yv = to[1] / 16.0; case EAST:
z0 = zv = from[2] / 16.0; zu = to[2] / 16.0; case FACE_5:
umin = z0; umax = zu; case X_PLUS:
vmin = y0; vmax = yv; // East - X-positive (top towards up (+Y), right towards north (-Z))
break; lowleft = new Vector3D(to[0] / 16.0, from[1] / 16.0, to[2] / 16.0);
case EAST: lowright = new Vector3D(to[0] / 16.0, from[1] / 16.0, from[2] / 16.0);
case FACE_5: upleft = new Vector3D(to[0] / 16.0, to[1] / 16.0, to[2] / 16.0);
case X_PLUS: upright = new Vector3D(to[0] / 16.0, to[1] / 16.0, from[2] / 16.0);
// East - X-positive (top towards up (+Y), right towards north (-Z)) break;
x0 = xu = xv = to[0] / 16.0; default:
y0 = yu = from[1] / 16.0; yv = to[1] / 16.0; Log.severe("Invalid side: " + face);
z0 = zv = to[2] / 16.0; zu = from[2] / 16.0; return;
umin = 1 - z0; umax = 1 - zu; }
vmin = y0; vmax = yv; // If rotation, rotate face corners
break; if (rot == ModelBlockModel.SideRotation.DEG90) {
default: // 90 degrees CW - origin is now upper left (V), V is now upper right (U+V-O), U is lower left (O)
Log.severe("Invalid side: " + face); Vector3D save = lowleft;
return; lowleft = lowright;
lowright = upright;
upright = upleft;
upleft = save;
} }
// If uv provided, use it to override else if (rot == ModelBlockModel.SideRotation.DEG180) {
if ((uv != null) && (uv.length == 4)) { // 180 degrees CW - origin is now upper right, U is now upper left (V), V is lower right (U)
umin = uv[0] / 16.0; Vector3D save = lowleft;
vmin = 1 - (uv[3] / 16.0); // MC V is inverted from our V lowleft = upright;
umax = uv[2] / 16.0; upright = save;
vmax = 1 - (uv[1] / 16.0); // MC V is inverted from our V save = lowright;
lowright = upleft;
upleft = save;
} }
// Compute texture origin for u,y = 0,0, based on coordinates else if (rot == ModelBlockModel.SideRotation.DEG270) {
// x0,y0,z0 = u=umin,v=vmin; xu,yu,zu = u=umax,v=vmin; xv,yv,zv = u=umin,v=vmax // 270 degrees CW - origin is now lower right (V), U is now upper right (topright), V is lower right (O)
// Compute U vector (based on proportion of umax-umin versus U offset Vector3D save = lowright;
double uvectx = (xu - x0) / (umax - umin); lowright = lowleft;
double uvecty = (yu - y0) / (umax - umin); lowleft = upleft;
double uvectz = (zu - z0) / (umax - umin); upleft = upright;
// Compute V vector (based on proportion of vmax-vmin versus V offset upright = save;
double vvectx = (xv - x0) / (vmax - vmin); }
double vvecty = (yv - y0) / (vmax - vmin); //System.out.println(String.format("ll=%s, lr=%s, ul=%s, ur=%s", lowleft, lowright, upleft, upright));
double vvectz = (zv - z0) / (vmax - vmin); // Compute texture origin, based on corners and patchuv
// Compute origin based on U vector and umin and V vector and vmin vs x0,y0,z0 Vector3D txtorig = new Vector3D();
double ovectx = x0 - (uvectx * umin) - (vvectx * vmin); Vector3D txtU = new Vector3D();
double ovecty = y0 - (uvecty * umin) - (vvecty * vmin); Vector3D txtV = new Vector3D();
double ovectz = z0 - (uvectz * umin) - (vvectz * vmin); Vector3D wrk = new Vector3D();
// If nonzero texture size
update(ovectx, ovecty, ovectz, uvectx + ovectx, uvecty + ovecty, uvectz + ovectz, vvectx + ovectx, vvecty + ovecty, vvectz + ovectz, if ((patchuv[0] != patchuv[2]) && (patchuv[1] != patchuv[3])) {
umin, umax, vmin, vmax, SideVisible.TOP, textureid, vmin, vmax); // 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.hdmap.TexturePack;
import org.dynmap.modsupport.BlockSide; import org.dynmap.modsupport.BlockSide;
import org.dynmap.modsupport.ModelBlockModel;
import org.dynmap.renderer.RenderPatch; import org.dynmap.renderer.RenderPatch;
import org.dynmap.renderer.RenderPatchFactory; import org.dynmap.renderer.RenderPatchFactory;
import org.dynmap.renderer.RenderPatchFactory.SideVisible; 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) { synchronized(lock) {
lookup.updateModelFace(from, to, face, uv, textureid); lookup.updateModelFace(from, to, face, uv, rot, textureid);
if(lookup.validate() == false) if(lookup.validate() == false)
return null; return null;
PatchDefinition pd2 = patches.get(lookup); /* See if in cache already */ 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) { public static void main(String[] args) {
PatchDefinitionFactory fact = new PatchDefinitionFactory(); PatchDefinitionFactory fact = new PatchDefinitionFactory();
BlockSide[] faces = { BlockSide.BOTTOM, BlockSide.TOP, BlockSide.NORTH, BlockSide.SOUTH, BlockSide.WEST, BlockSide.EAST }; PatchDefinition pd;
double[] from = { 0,0,0 }; BlockSide[] faces = { BlockSide.NORTH, BlockSide.EAST, BlockSide.SOUTH, BlockSide.WEST, BlockSide.TOP, BlockSide.BOTTOM };
double[] to = { 16,16,16 }; // 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 // Do normal faces, default limits
PatchDefinition pd = new PatchDefinition(); pd = new PatchDefinition();
for (BlockSide face : faces) { for (int i = 0; i < faces.length; i++) {
pd.updateModelFace(from, to, face, null, 0); pd.updateModelFace(from, to, faces[i], uvs[i], rots[i], 0);
System.out.println("Full cube " + face + ": " + pd); System.out.println("Log " + faces[i] + ": " + pd);
} }
double[] toquarter = { 8,8,8 }; // // Do normal faces, default limits
for (BlockSide face : faces) { // pd = new PatchDefinition();
pd.updateModelFace(from, toquarter, face, null, 0); // for (BlockSide face : faces) {
System.out.println("8x8x8 cube " + face + ": " + pd); // pd.updateModelFace(from, to, face, null, 0);
} // System.out.println("Full cube " + face + ": " + pd);
// }
//
for (BlockSide face : faces) { // double[] toquarter = { 8,8,8 };
pd.updateModelFace(from, toquarter, face, new double[] { 4, 4, 12, 12 }, 0); // for (BlockSide face : faces) {
System.out.println("Full cube, middle half of texture " + face + ": " + pd); // 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 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; 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; 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; x = x + v.x; y = y + v.y; z = z + v.z;
return this;
} }
public final double innerProduct(Vector3D v) { public final double innerProduct(Vector3D v) {
return (v.x * x) + (v.y * y) + (v.z * z); 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 */ /* 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 newx = (y*v.z) - (z*v.y);
double newy = (z*v.x) - (x*v.z); double newy = (z*v.x) - (x*v.z);
double newz = (x*v.y) - (y*v.x); double newz = (x*v.y) - (y*v.x);
x = newx; y = newy; z = newz; x = newx; y = newy; z = newz;
return this;
} }
public String toString() { public String toString() {

View File

@ -955,7 +955,7 @@ patchrotate:id=comparator,data=5,rot=90
patchblock:id=comparator,data=13 patchblock:id=comparator,data=13
patchrotate:id=comparator,data=5,rot=270 patchrotate:id=comparator,data=5,rot=270
# Comparator (compare mode, on) - slab, comparator, unlit, lit, comparator_on # 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 patchblock:id=comparator,data=0
patchrotate:id=comparator,data=4,rot=180 patchrotate:id=comparator,data=4,rot=180
patchblock:id=comparator,data=8 patchblock:id=comparator,data=8
@ -1411,21 +1411,24 @@ patchblock:id=bubble_column
[1.14-]patchrotate:id=stonecutter,data=0,roty=270 [1.14-]patchrotate:id=stonecutter,data=0,roty=270
[1.14-]patchblock:id=stonecutter,data=3 [1.14-]patchblock:id=stonecutter,data=3
[1.14-]patchrotate:id=stonecutter,data=0,roty=90 [1.14-]patchrotate:id=stonecutter,data=0,roty=90
# Campfire # Campfire (lit) (unlit log, lit log, fire)
[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-]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-]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=0,data=1,data=2,data=3
[1.14-]patchblock:id=campfire,data=8,data=9,data=10,data=11 [1.14-]patchrotate:id=campfire,data=8,roty=180
[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
[1.14-]patchblock:id=campfire,data=16,data=17,data=18,data=19 [1.14-]patchblock:id=campfire,data=16,data=17,data=18,data=19
[1.14-]patchrotate:id=campfire,data=0,roty=270 [1.14-]patchrotate:id=campfire,data=8,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-]patchblock:id=campfire,data=24,data=25,data=26,data=27 [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-]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) # 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]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 [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]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]patchblock:id=bell,data=11
[1.14-1.14.4]patchrotate:id=bell,data=10,roty=180 [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]patchrotate:id=bell,data=10,roty=270
[1.14-1.14.4]patchblock:id=bell,data=9 [1.14-1.14.4]patchblock:id=bell,data=9
[1.14-1.14.4]patchrotate:id=bell,data=10,roty=90 [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 # Stonecutter
[1.14-]block:id=stonecutter,patch0=0:stonecutter_bottom,patch1=0:stonecutter_top,patch2=0:stonecutter_side,patch3=0:stonecutter_saw,transparency=TRANSPARENT [1.14-]block:id=stonecutter,patch0=0:stonecutter_bottom,patch1=0:stonecutter_top,patch2=0:stonecutter_side,patch3=0:stonecutter_saw,transparency=TRANSPARENT
# Campfire # 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 # 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 [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 // All coordinates are 0-16 range per block, and 0-16 range for UV
public interface ModelBlockModel extends BlockModel { public interface ModelBlockModel extends BlockModel {
public enum SideRotation {
DEG0, // zero degrees (default)
DEG90, // 90 degrees
DEG180, // 180 degrees
DEG270 // 270 degrees
};
public interface ModelBlock { public interface ModelBlock {
/** /**
* Factory method for adding a side to a model block started using addModelBlock. * 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 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 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 * @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. * 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; package org.dynmap.renderer;
public interface RenderPatchFactory { public interface RenderPatchFactory {
public enum SideVisible { TOP, BOTTOM, BOTH, FLIP }; public enum SideVisible { TOP, BOTTOM, BOTH, FLIP, TOPFLIP };
/** /**
* Get/create patch with given attributes. * Get/create patch with given attributes.