mirror of https://github.com/webbukkit/dynmap.git
Make state sensitive custom models cache more efficient (save memory)
This commit is contained in:
parent
0166895a7f
commit
c48ed688b2
|
@ -366,8 +366,8 @@ public class OBJExport {
|
|||
/* If no patches, see if custom model */
|
||||
if(patches == null) {
|
||||
CustomBlockModel cbm = models.getCustomBlockModel(blk);
|
||||
if(cbm != null) { /* If so, get our meshes */
|
||||
patches = cbm.getMeshForBlock(map);
|
||||
if (cbm != null) { /* If so, get our meshes */
|
||||
patches = cbm.getMeshForBlock(map);
|
||||
}
|
||||
}
|
||||
if (patches != null) {
|
||||
|
|
|
@ -43,6 +43,9 @@ public class CustomBlockModel extends HDBlockModel {
|
|||
return render.getMaximumTextureCount(HDBlockModels.pdf);
|
||||
}
|
||||
|
||||
public boolean isOnlyBlockStateSensitive() {
|
||||
return render.isOnlyBlockStateSensitive();
|
||||
}
|
||||
private static final RenderPatch[] empty_list = new RenderPatch[0];
|
||||
|
||||
public RenderPatch[] getMeshForBlock(MapDataContext ctx) {
|
||||
|
|
|
@ -5,14 +5,22 @@ import org.dynmap.utils.PatchDefinition;
|
|||
|
||||
public class HDScaledBlockModels {
|
||||
private short[][] modelvectors;
|
||||
private PatchDefinition[][] patches;
|
||||
private CustomBlockModel[] custom;
|
||||
// These are scale invariant - only need once
|
||||
private static PatchDefinition[][] patches;
|
||||
private static CustomBlockModel[] custom;
|
||||
|
||||
public HDScaledBlockModels(int scale) {
|
||||
short[][] blockmodels = new short[DynmapBlockState.getGlobalIndexMax()][];
|
||||
PatchDefinition[][] patches = new PatchDefinition[DynmapBlockState.getGlobalIndexMax()][];
|
||||
CustomBlockModel[] custom = new CustomBlockModel[DynmapBlockState.getGlobalIndexMax()];
|
||||
|
||||
PatchDefinition[][] newpatches = null;
|
||||
if (patches == null) {
|
||||
newpatches = new PatchDefinition[DynmapBlockState.getGlobalIndexMax()][];
|
||||
patches = newpatches;
|
||||
}
|
||||
CustomBlockModel[] newcustom = null;
|
||||
if (custom == null) {
|
||||
newcustom = new CustomBlockModel[DynmapBlockState.getGlobalIndexMax()];
|
||||
custom = newcustom;
|
||||
}
|
||||
for(Integer gidx : HDBlockModels.models_by_id_data.keySet()) {
|
||||
HDBlockModel m = HDBlockModels.models_by_id_data.get(gidx);
|
||||
|
||||
|
@ -34,18 +42,19 @@ public class HDScaledBlockModels {
|
|||
}
|
||||
}
|
||||
else if(m instanceof HDBlockPatchModel) {
|
||||
HDBlockPatchModel pm = (HDBlockPatchModel)m;
|
||||
patches[gidx] = pm.getPatches();
|
||||
if (newpatches != null) {
|
||||
HDBlockPatchModel pm = (HDBlockPatchModel)m;
|
||||
newpatches[gidx] = pm.getPatches();
|
||||
}
|
||||
}
|
||||
else if(m instanceof CustomBlockModel) {
|
||||
CustomBlockModel cbm = (CustomBlockModel)m;
|
||||
custom[gidx] = cbm;
|
||||
if (newcustom != null) {
|
||||
CustomBlockModel cbm = (CustomBlockModel)m;
|
||||
newcustom[gidx] = cbm;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.modelvectors = blockmodels;
|
||||
this.patches = patches;
|
||||
this.custom = custom;
|
||||
}
|
||||
|
||||
public final short[] getScaledModel(DynmapBlockState blk) {
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.dynmap.Client;
|
||||
import org.dynmap.Color;
|
||||
|
@ -27,6 +28,7 @@ import org.dynmap.renderer.RenderPatchFactory.SideVisible;
|
|||
import org.dynmap.storage.MapStorage;
|
||||
import org.dynmap.storage.MapStorageTile;
|
||||
import org.dynmap.utils.BlockStep;
|
||||
import org.dynmap.utils.DynIntHashMap;
|
||||
import org.dynmap.hdmap.TexturePack.BlockTransparency;
|
||||
import org.dynmap.utils.DynmapBufferedImage;
|
||||
import org.dynmap.utils.LightLevels;
|
||||
|
@ -79,6 +81,9 @@ public class IsoHDPerspective implements HDPerspective {
|
|||
|
||||
private static final BlockStep [] semi_steps = { BlockStep.Y_PLUS, BlockStep.X_MINUS, BlockStep.X_PLUS, BlockStep.Z_MINUS, BlockStep.Z_PLUS };
|
||||
|
||||
// Cache for custom meshes by state (shared, reusable)
|
||||
private static RenderPatch[][] custom_meshes_by_globalstateindex = null;
|
||||
|
||||
private class OurPerspectiveState implements HDPerspectiveState {
|
||||
DynmapBlockState blocktype = DynmapBlockState.AIR;
|
||||
DynmapBlockState lastblocktype = DynmapBlockState.AIR;
|
||||
|
@ -554,7 +559,15 @@ public class IsoHDPerspective implements HDPerspective {
|
|||
this.setCustomFluidMesh(patches);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Else, if block state specific model
|
||||
else if (cbm.isOnlyBlockStateSensitive()) {
|
||||
patches = this.getCustomMeshForState(bt); // Look up mesh by state
|
||||
if (patches == null) { // Miss, generate it
|
||||
patches = cbm.getMeshForBlock(mapiter);
|
||||
this.setCustomMeshForState(bt, patches);
|
||||
}
|
||||
}
|
||||
else { // Else, block specific
|
||||
patches = this.getCustomMesh();
|
||||
if (patches == null) {
|
||||
patches = cbm.getMeshForBlock(mapiter);
|
||||
|
@ -919,6 +932,12 @@ public class IsoHDPerspective implements HDPerspective {
|
|||
long key = this.mapiter.getBlockKey(); /* Get key for current block */
|
||||
return (RenderPatch[])custom_meshes.get(key);
|
||||
}
|
||||
/**
|
||||
* Get custom mesh for block, if defined (null if not)
|
||||
*/
|
||||
public final RenderPatch[] getCustomMeshForState(DynmapBlockState bs) {
|
||||
return (RenderPatch[]) custom_meshes_by_globalstateindex[bs.globalStateIndex];
|
||||
}
|
||||
/**
|
||||
* Save custom mesh for block
|
||||
*/
|
||||
|
@ -926,6 +945,12 @@ public class IsoHDPerspective implements HDPerspective {
|
|||
long key = this.mapiter.getBlockKey(); /* Get key for current block */
|
||||
custom_meshes.put(key, mesh);
|
||||
}
|
||||
/**
|
||||
* Set custom mesh for block, if defined (null if not)
|
||||
*/
|
||||
public final void setCustomMeshForState(DynmapBlockState bs, RenderPatch[] mesh) {
|
||||
custom_meshes_by_globalstateindex[bs.globalStateIndex] = mesh;
|
||||
}
|
||||
/**
|
||||
* Get custom fluid mesh for block, if defined (null if not)
|
||||
*/
|
||||
|
@ -943,6 +968,9 @@ public class IsoHDPerspective implements HDPerspective {
|
|||
}
|
||||
|
||||
public IsoHDPerspective(DynmapCore core, ConfigurationNode configuration) {
|
||||
if (custom_meshes_by_globalstateindex == null) {
|
||||
custom_meshes_by_globalstateindex = new RenderPatch[DynmapBlockState.getGlobalIndexMax()][];
|
||||
}
|
||||
name = configuration.getString("name", null);
|
||||
if(name == null) {
|
||||
Log.severe("Perspective definition missing name - must be defined and unique");
|
||||
|
|
|
@ -73,4 +73,8 @@ public class BoxRenderer extends CustomRenderer {
|
|||
public RenderPatch[] getRenderPatchList(MapDataContext ctx) {
|
||||
return model;
|
||||
}
|
||||
@Override
|
||||
public boolean isOnlyBlockStateSensitive() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,4 +89,8 @@ public class BoxStateRenderer extends CustomRenderer {
|
|||
public RenderPatch[] getRenderPatchList(MapDataContext ctx) {
|
||||
return models[ctx.getBlockType().stateIndex];
|
||||
}
|
||||
@Override
|
||||
public boolean isOnlyBlockStateSensitive() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,4 +31,8 @@ public class ChestStateRenderer extends ChestRenderer {
|
|||
}
|
||||
return models[byIndex[idx].ordinal()];
|
||||
}
|
||||
@Override
|
||||
public boolean isOnlyBlockStateSensitive() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -123,4 +123,8 @@ public class CuboidRenderer extends CustomRenderer {
|
|||
int idx = ctx.getBlockType().stateIndex;
|
||||
return models[idx % models.length];
|
||||
}
|
||||
@Override
|
||||
public boolean isOnlyBlockStateSensitive() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,4 +108,8 @@ public class FenceGateBlockRenderer extends CustomRenderer {
|
|||
|
||||
return meshes[meta & 0x7];
|
||||
}
|
||||
@Override
|
||||
public boolean isOnlyBlockStateSensitive() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,5 +120,9 @@ public class FenceGateBlockStateRenderer extends CustomRenderer {
|
|||
// 32 states: meta%2=powered|unpowered, (meta/2)%2=open/closed, (meta/4)%2=in-wall/not-in-wall, (meta/8)%4=n/s/w/e
|
||||
return meshes[(meta >> 1) & 0xF]; // Don't care about powered: models are 0-15
|
||||
}
|
||||
@Override
|
||||
public boolean isOnlyBlockStateSensitive() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -216,4 +216,8 @@ public class FenceWallBlockStateRenderer extends CustomRenderer {
|
|||
}
|
||||
return meshes[off];
|
||||
}
|
||||
@Override
|
||||
public boolean isOnlyBlockStateSensitive() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,4 +55,8 @@ public class GlowLichenStateRenderer extends CustomRenderer {
|
|||
int idx = ((ctx.getBlockType().stateIndex & 0x7C) >> 1) + (ctx.getBlockType().stateIndex & 0x1); // Shift out waterlogged bit
|
||||
return meshes[idx];
|
||||
}
|
||||
@Override
|
||||
public boolean isOnlyBlockStateSensitive() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,4 +61,8 @@ public class HeadRenderer extends CustomRenderer {
|
|||
else
|
||||
return meshes[0];
|
||||
}
|
||||
@Override
|
||||
public boolean isOnlyBlockStateSensitive() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,4 +14,8 @@ public class PaneStateRenderer extends PaneRenderer {
|
|||
int meshidx = (((idx & 0x10) == 0) ? SIDE_XP : 0) | (((idx & 0x08) == 0) ? SIDE_ZN : 0) | (((idx & 0x04) == 0) ? SIDE_ZP : 0) | (((idx & 0x01) == 0) ? SIDE_XN : 0);
|
||||
return meshes[meshidx];
|
||||
}
|
||||
@Override
|
||||
public boolean isOnlyBlockStateSensitive() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,4 +45,8 @@ public class RedstoneWireStateRenderer extends RedstoneWireRenderer {
|
|||
}
|
||||
return getMesh(pidx);
|
||||
}
|
||||
@Override
|
||||
public boolean isOnlyBlockStateSensitive() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -131,4 +131,8 @@ public class RotatedBoxRenderer extends CustomRenderer {
|
|||
Log.info("Unmatched rotation index: " + textureIdx + " for " + ctx.getBlockType());
|
||||
return models[0];
|
||||
}
|
||||
@Override
|
||||
public boolean isOnlyBlockStateSensitive() {
|
||||
return idx_attrib == null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -154,4 +154,8 @@ public class RotatedPatchRenderer extends CustomRenderer {
|
|||
return basemodel;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public boolean isOnlyBlockStateSensitive() {
|
||||
return idx_attrib == null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -159,4 +159,8 @@ public class StairStateRenderer extends CustomRenderer {
|
|||
}
|
||||
return rp;
|
||||
}
|
||||
@Override
|
||||
public boolean isOnlyBlockStateSensitive() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,4 +52,8 @@ public class VineStateRenderer extends CustomRenderer {
|
|||
public RenderPatch[] getRenderPatchList(MapDataContext ctx) {
|
||||
return meshes[ctx.getBlockType().stateIndex];
|
||||
}
|
||||
@Override
|
||||
public boolean isOnlyBlockStateSensitive() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,4 +61,8 @@ public class WallHeadRenderer extends CustomRenderer {
|
|||
else
|
||||
return meshes[0];
|
||||
}
|
||||
@Override
|
||||
public boolean isOnlyBlockStateSensitive() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -184,4 +184,12 @@ public abstract class CustomRenderer {
|
|||
public RenderPatch getSidePatch(RenderPatchFactory rpf, int side, int rot, int textureidx) {
|
||||
return getSidePatch(rpf, side, 0.0, 0.0, 1.0, 0.0, 1.0, rot, textureidx);
|
||||
}
|
||||
/**
|
||||
* Test if the given renderer is purely a function of the block state of the given block (that is, not
|
||||
* directly tied to neighbor blocks, location, or other factors). If true, the returned model for a getRenderPatchList() is
|
||||
* cached by block state, versus by specific block location/instance.
|
||||
*/
|
||||
public boolean isOnlyBlockStateSensitive() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -549,4 +549,18 @@ public class DynmapBlockState {
|
|||
public String toString() {
|
||||
return fullName;
|
||||
}
|
||||
// Equals check
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) return true;
|
||||
if (obj instanceof DynmapBlockState) {
|
||||
return ((DynmapBlockState)obj).globalStateIndex == this.globalStateIndex;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// Hashcode
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.globalStateIndex;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue