Tinker with performance on some base data classes
This commit is contained in:
parent
5a30ab0d3f
commit
c6fb0be7e7
8 changed files with 172 additions and 119 deletions
|
|
@ -38,12 +38,13 @@ public class Color {
|
|||
val = TRANSPARENT;
|
||||
}
|
||||
public final void setGrayscale() {
|
||||
int alpha = (val >> 24) & 0xFF;
|
||||
int red = (val >> 16) & 0xFF;
|
||||
int green = (val >> 8) & 0xFF;
|
||||
int blue = val & 0xFF;
|
||||
int gray = ((red * 76) + (green * 151) + (blue * 28)) / 255;
|
||||
setRGBA(gray, gray, gray, alpha);
|
||||
int alpha = val & 0xFF000000;
|
||||
int num = (((val >> 16) & 0xFF) * 76)
|
||||
+ (((val >> 8) & 0xFF) * 151)
|
||||
+ (( val & 0xFF) * 28);
|
||||
// weights sum to 255, so num ∈ [0, 65025]; fast /255 via shift
|
||||
int gray = (num + (num >> 8) + 1) >> 8;
|
||||
val = alpha | (gray << 16) | (gray << 8) | gray;
|
||||
}
|
||||
public final void setColor(Color c) {
|
||||
val = c.val;
|
||||
|
|
@ -85,11 +86,10 @@ public class Color {
|
|||
* @param argb - ARGB to blend
|
||||
*/
|
||||
public final void blendColor(int argb) {
|
||||
int nval = (((((val >> 24) & 0xFF) * ((argb >> 24) & 0xFF)) / 255) << 24);
|
||||
nval = nval | (((((val >> 16) & 0xFF) * ((argb >> 16) & 0xFF)) / 255) << 16);
|
||||
nval = nval | (((((val >> 8) & 0xFF) * ((argb >> 8) & 0xFF)) / 255) << 8);
|
||||
nval = nval | (((val & 0xFF) * (argb & 0xFF)) / 255);
|
||||
val = nval;
|
||||
val = (mulDiv255(val >>> 24, argb >>> 24 ) << 24)
|
||||
| (mulDiv255((val >> 16) & 0xFF, (argb >> 16) & 0xFF) << 16)
|
||||
| (mulDiv255((val >> 8) & 0xFF, (argb >> 8) & 0xFF) << 8)
|
||||
| mulDiv255( val & 0xFF, argb & 0xFF);
|
||||
}
|
||||
/**
|
||||
* Scale each color component, based on the corresponding component
|
||||
|
|
@ -98,10 +98,30 @@ public class Color {
|
|||
* @return blended color
|
||||
*/
|
||||
public static final int blendColor(int argb0, int argb1) {
|
||||
int nval = (((((argb0 >> 24) & 0xFF) * ((argb1 >> 24) & 0xFF)) / 255) << 24);
|
||||
nval = nval | (((((argb0 >> 16) & 0xFF) * ((argb1 >> 16) & 0xFF)) / 255) << 16);
|
||||
nval = nval | (((((argb0 >> 8) & 0xFF) * ((argb1 >> 8) & 0xFF)) / 255) << 8);
|
||||
nval = nval | (((argb0 & 0xFF) * (argb1 & 0xFF)) / 255);
|
||||
return nval;
|
||||
return (mulDiv255(argb0 >>> 24, argb1 >>> 24 ) << 24)
|
||||
| (mulDiv255((argb0 >> 16) & 0xFF, (argb1 >> 16) & 0xFF) << 16)
|
||||
| (mulDiv255((argb0 >> 8) & 0xFF, (argb1 >> 8) & 0xFF) << 8)
|
||||
| mulDiv255( argb0 & 0xFF, argb1 & 0xFF);
|
||||
}
|
||||
/**
|
||||
* Scale the RGB channels by scale/256, leaving alpha unchanged.
|
||||
* Equivalent to setRGBA(getRed()*scale>>8, getGreen()*scale>>8, getBlue()*scale>>8, getAlpha())
|
||||
* but avoids redundant unpack/repack of the alpha channel.
|
||||
* @param scale - scale factor 0..256 (256 = full brightness)
|
||||
*/
|
||||
public final void scaleRGB(int scale) {
|
||||
val = (val & 0xFF000000)
|
||||
| ((((val >> 16) & 0xFF) * scale >> 8) << 16)
|
||||
| ((((val >> 8) & 0xFF) * scale >> 8) << 8)
|
||||
| ((val & 0xFF) * scale >> 8);
|
||||
}
|
||||
/**
|
||||
* Fast multiply-then-divide-by-255 for two values a, b each in [0, 255].
|
||||
* Returns floor(a*b/255), equivalent to the standard integer division but
|
||||
* computed with shifts only: (x + (x >> 8) + 1) >> 8 where x = a * b.
|
||||
*/
|
||||
private static int mulDiv255(int a, int b) {
|
||||
int x = a * b;
|
||||
return (x + (x >> 8) + 1) >> 8;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package org.dynmap.common;
|
|||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
|
|
@ -11,7 +12,9 @@ import org.dynmap.hdmap.HDBlockModels;
|
|||
public class BiomeMap {
|
||||
public static final int NO_INDEX = -2;
|
||||
private static BiomeMap[] biome_by_index = new BiomeMap[256];
|
||||
private static Map<String, BiomeMap> biome_by_rl = new HashMap<String, BiomeMap>();
|
||||
private static Map<String, BiomeMap> biome_by_rl = new HashMap<String, BiomeMap>(256);
|
||||
// Tracks registered IDs for O(1) uniqueness checks during initialization
|
||||
private static final HashSet<String> biome_ids = new HashSet<String>(256);
|
||||
public static final BiomeMap NULL = new BiomeMap(-1, "NULL", 0.5, 0.5, 0xFFFFFF, 0, 0, null);
|
||||
|
||||
public static final BiomeMap OCEAN = new BiomeMap(0, "OCEAN", "minecraft:ocean");
|
||||
|
|
@ -145,12 +148,17 @@ public class BiomeMap {
|
|||
}
|
||||
|
||||
private static boolean isUniqueID(String id) {
|
||||
for(int i = 0; i < biome_by_index.length; i++) {
|
||||
if(biome_by_index[i] == null) continue;
|
||||
if(biome_by_index[i].id.equals(id))
|
||||
return false;
|
||||
return !biome_ids.contains(id);
|
||||
}
|
||||
return true;
|
||||
|
||||
/**
|
||||
* Encodes a grass/foliage color multiplier for efficient hot-path dispatch:
|
||||
* == 0 → 0 (passthrough: return raw value unchanged)
|
||||
* 0 < val ≤ 0xFFFFFF → positive (blend: average with raw)
|
||||
* val > 0xFFFFFF → -(val & 0xFFFFFF) (negative sentinel: fixed override color)
|
||||
*/
|
||||
private static int encodeColorMult(int val) {
|
||||
return (val > 0xFFFFFF) ? -(val & 0xFFFFFF) : val;
|
||||
}
|
||||
|
||||
private static void resizeIfNeeded(int idx) {
|
||||
|
|
@ -171,8 +179,8 @@ public class BiomeMap {
|
|||
setTemperature(tmp);
|
||||
setRainfall(rain);
|
||||
this.watercolormult = waterColorMultiplier;
|
||||
this.grassmult = grassmult;
|
||||
this.foliagemult = foliagemult;
|
||||
this.grassmult = encodeColorMult(grassmult);
|
||||
this.foliagemult = encodeColorMult(foliagemult);
|
||||
// Handle null biome
|
||||
if (id == null) { id = "biome_" + idx; }
|
||||
id = id.toUpperCase().replace(' ', '_');
|
||||
|
|
@ -180,6 +188,7 @@ public class BiomeMap {
|
|||
id = id + "_" + idx;
|
||||
}
|
||||
this.id = id;
|
||||
biome_ids.add(this.id);
|
||||
// If index is NO_INDEX, find one after the well known ones
|
||||
if (idx == NO_INDEX) {
|
||||
idx = LAST_WELL_KNOWN;
|
||||
|
|
@ -235,21 +244,15 @@ public class BiomeMap {
|
|||
}
|
||||
|
||||
public final int getModifiedGrassMultiplier(int rawgrassmult) {
|
||||
if(grassmult == 0)
|
||||
return rawgrassmult;
|
||||
else if(grassmult > 0xFFFFFF)
|
||||
return grassmult & 0xFFFFFF;
|
||||
else
|
||||
return ((rawgrassmult & 0xfefefe) + grassmult) / 2;
|
||||
if (grassmult == 0) return rawgrassmult; // common case: no override
|
||||
if (grassmult < 0) return -grassmult; // fixed color (pre-masked at set-time)
|
||||
return ((rawgrassmult & 0xfefefe) + grassmult) >> 1; // blend
|
||||
}
|
||||
|
||||
public final int getModifiedFoliageMultiplier(int rawfoliagemult) {
|
||||
if(foliagemult == 0)
|
||||
return rawfoliagemult;
|
||||
else if(foliagemult > 0xFFFFFF)
|
||||
return foliagemult & 0xFFFFFF;
|
||||
else
|
||||
return ((rawfoliagemult & 0xfefefe) + foliagemult) / 2;
|
||||
if (foliagemult == 0) return rawfoliagemult; // common case: no override
|
||||
if (foliagemult < 0) return -foliagemult; // fixed color (pre-masked at set-time)
|
||||
return ((rawfoliagemult & 0xfefefe) + foliagemult) >> 1; // blend
|
||||
}
|
||||
public final int getWaterColorMult() {
|
||||
return watercolormult;
|
||||
|
|
@ -278,10 +281,10 @@ public class BiomeMap {
|
|||
this.watercolormult = watercolormult;
|
||||
}
|
||||
public void setGrassColorMultiplier(int grassmult) {
|
||||
this.grassmult = grassmult;
|
||||
this.grassmult = encodeColorMult(grassmult);
|
||||
}
|
||||
public void setFoliageColorMultiplier(int foliagemult) {
|
||||
this.foliagemult = foliagemult;
|
||||
this.foliagemult = encodeColorMult(foliagemult);
|
||||
}
|
||||
public void setTemperature(double tmp) {
|
||||
if(tmp < 0.0) tmp = 0.0;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ public class GenericChunk {
|
|||
// Get section for given block Y coord
|
||||
public final GenericChunkSection getSection(int y) {
|
||||
int idx = (y >> 4) - this.cy_min;
|
||||
if ((idx < 0) || (idx >= sectionCnt)) {
|
||||
if ((idx < 0) || (idx >= sections.length)) {
|
||||
return GenericChunkSection.EMPTY;
|
||||
}
|
||||
return this.sections[idx];
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import java.lang.ref.Reference;
|
|||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.HashMap;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
|
@ -23,22 +24,26 @@ public class GenericChunkCache {
|
|||
private long cache_attempts;
|
||||
private long cache_success;
|
||||
private boolean softref;
|
||||
// World name -> small integer ID, used to build long cache keys without String concatenation.
|
||||
// Accessed only while holding snapcachelock.
|
||||
private final HashMap<String, Integer> worldIds = new HashMap<String, Integer>();
|
||||
private int nextWorldId = 0;
|
||||
|
||||
private static class CacheRec {
|
||||
Reference<ChunkCacheRec> ref;
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class CacheHashMap extends LinkedHashMap<String, CacheRec> {
|
||||
public class CacheHashMap extends LinkedHashMap<Long, CacheRec> {
|
||||
private int limit;
|
||||
private IdentityHashMap<Reference<ChunkCacheRec>, String> reverselookup;
|
||||
private IdentityHashMap<Reference<ChunkCacheRec>, Long> reverselookup;
|
||||
|
||||
public CacheHashMap(int lim) {
|
||||
super(16, (float)0.75, true);
|
||||
limit = lim;
|
||||
reverselookup = new IdentityHashMap<Reference<ChunkCacheRec>, String>();
|
||||
reverselookup = new IdentityHashMap<Reference<ChunkCacheRec>, Long>();
|
||||
}
|
||||
protected boolean removeEldestEntry(Map.Entry<String, CacheRec> last) {
|
||||
protected boolean removeEldestEntry(Map.Entry<Long, CacheRec> last) {
|
||||
boolean remove = (size() >= limit);
|
||||
if(remove && (last != null) && (last.getValue() != null)) {
|
||||
reverselookup.remove(last.getValue().ref);
|
||||
|
|
@ -56,15 +61,26 @@ public class GenericChunkCache {
|
|||
refqueue = new ReferenceQueue<ChunkCacheRec>();
|
||||
this.softref = softref;
|
||||
}
|
||||
private String getKey(String w, int cx, int cz) {
|
||||
return w + ":" + cx + ":" + cz;
|
||||
/**
|
||||
* Encode world name + chunk coords as a single long key.
|
||||
* Worlds are assigned small integer IDs (10 bits) on first use.
|
||||
* cx and cz are each encoded in 27 bits (signed, supports ±8M chunks / ±128M blocks).
|
||||
* Must be called while holding snapcachelock.
|
||||
*/
|
||||
private long getKey(String w, int cx, int cz) {
|
||||
Integer wid = worldIds.get(w);
|
||||
if (wid == null) {
|
||||
wid = nextWorldId++;
|
||||
worldIds.put(w, wid);
|
||||
}
|
||||
return ((long)(wid & 0x3FF) << 54) | ((long)(cx & 0x7FFFFFF) << 27) | (long)(cz & 0x7FFFFFF);
|
||||
}
|
||||
/**
|
||||
* Invalidate cached snapshot, if in cache
|
||||
*/
|
||||
public void invalidateSnapshot(String w, int x, int y, int z) {
|
||||
String key = getKey(w, x>>4, z>>4);
|
||||
synchronized(snapcachelock) {
|
||||
long key = getKey(w, x>>4, z>>4);
|
||||
CacheRec rec = (snapcache != null) ? snapcache.remove(key) : null;
|
||||
if(rec != null) {
|
||||
snapcache.reverselookup.remove(rec.ref);
|
||||
|
|
@ -77,10 +93,10 @@ public class GenericChunkCache {
|
|||
* Invalidate cached snapshot, if in cache
|
||||
*/
|
||||
public void invalidateSnapshot(String w, int x0, int y0, int z0, int x1, int y1, int z1) {
|
||||
synchronized(snapcachelock) {
|
||||
for(int xx = (x0>>4); xx <= (x1>>4); xx++) {
|
||||
for(int zz = (z0>>4); zz <= (z1>>4); zz++) {
|
||||
String key = getKey(w, xx, zz);
|
||||
synchronized(snapcachelock) {
|
||||
long key = getKey(w, xx, zz);
|
||||
CacheRec rec = (snapcache != null) ? snapcache.remove(key) : null;
|
||||
if(rec != null) {
|
||||
snapcache.reverselookup.remove(rec.ref);
|
||||
|
|
@ -95,11 +111,11 @@ public class GenericChunkCache {
|
|||
* Look for chunk snapshot in cache
|
||||
*/
|
||||
public ChunkCacheRec getSnapshot(String w, int chunkx, int chunkz) {
|
||||
String key = getKey(w, chunkx, chunkz);
|
||||
processRefQueue();
|
||||
ChunkCacheRec ss = null;
|
||||
CacheRec rec;
|
||||
synchronized(snapcachelock) {
|
||||
long key = getKey(w, chunkx, chunkz);
|
||||
rec = (snapcache != null) ? snapcache.get(key) : null;
|
||||
if(rec != null) {
|
||||
ss = rec.ref.get();
|
||||
|
|
@ -118,7 +134,6 @@ public class GenericChunkCache {
|
|||
* Add chunk snapshot to cache
|
||||
*/
|
||||
public void putSnapshot(String w, int chunkx, int chunkz, ChunkCacheRec ss) {
|
||||
String key = getKey(w, chunkx, chunkz);
|
||||
processRefQueue();
|
||||
CacheRec rec = new CacheRec();
|
||||
if (softref)
|
||||
|
|
@ -126,6 +141,7 @@ public class GenericChunkCache {
|
|||
else
|
||||
rec.ref = new WeakReference<ChunkCacheRec>(ss, refqueue);
|
||||
synchronized(snapcachelock) {
|
||||
long key = getKey(w, chunkx, chunkz);
|
||||
CacheRec prevrec = (snapcache != null) ? snapcache.put(key, rec) : null;
|
||||
if(prevrec != null) {
|
||||
snapcache.reverselookup.remove(prevrec.ref);
|
||||
|
|
@ -140,7 +156,7 @@ public class GenericChunkCache {
|
|||
Reference<? extends ChunkCacheRec> ref;
|
||||
while((ref = refqueue.poll()) != null) {
|
||||
synchronized(snapcachelock) {
|
||||
String k = (snapcache != null) ? snapcache.reverselookup.remove(ref) : null;
|
||||
Long k = (snapcache != null) ? snapcache.reverselookup.remove(ref) : null;
|
||||
if(k != null) {
|
||||
snapcache.remove(k);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ public class GenericChunkSection {
|
|||
blocks = bs;
|
||||
}
|
||||
public final DynmapBlockState getBlock(int x, int y, int z) {
|
||||
return blocks[(256 * (y & 0xF)) + (16 * (z & 0xF)) + (x & 0xF)];
|
||||
return blocks[((y & 0xF) << 8) | ((z & 0xF) << 4) | (x & 0xF)];
|
||||
}
|
||||
public final DynmapBlockState getBlock(GenericChunkPos pos) {
|
||||
return blocks[pos.soffset];
|
||||
|
|
@ -40,7 +40,7 @@ public class GenericChunkSection {
|
|||
palette = pal;
|
||||
}
|
||||
public final DynmapBlockState getBlock(int x, int y, int z) {
|
||||
return palette[blocks[(256 * (y & 0xF)) + (16 * (z & 0xF)) + (x & 0xF)]];
|
||||
return palette[blocks[((y & 0xF) << 8) | ((z & 0xF) << 4) | (x & 0xF)]];
|
||||
}
|
||||
public final DynmapBlockState getBlock(GenericChunkPos pos) {
|
||||
return palette[blocks[pos.soffset]];
|
||||
|
|
@ -126,12 +126,12 @@ public class GenericChunkSection {
|
|||
light = new long[256];
|
||||
if (lig != null) {
|
||||
for (int off = 0; (off < lig.length) && (off < 2048); off++) {
|
||||
light[off >> 3] |= (0xFFL & (long)lig[off]) << (8 * (off & 0x7));
|
||||
light[off >> 3] |= (0xFFL & (long)lig[off]) << ((off & 0x7) << 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
public final int getLight(int x, int y, int z) {
|
||||
return 0xF & (int)(light[(16 * (y & 0xF)) + (z & 0xF)] >> (4 * (x & 0xF)));
|
||||
return 0xF & (int)(light[((y & 0xF) << 4) | (z & 0xF)] >> ((x & 0xF) << 2));
|
||||
}
|
||||
public final int getLight(GenericChunkPos pos) {
|
||||
return 0xF & (int)(light[pos.soffset >> 4] >> (4 * pos.sx));
|
||||
|
|
|
|||
|
|
@ -154,9 +154,7 @@ public class ShadowHDLighting extends DefaultHDLighting {
|
|||
}
|
||||
}
|
||||
if(cscale < 256) {
|
||||
Color c = outcolor[0];
|
||||
c.setRGBA((c.getRed() * cscale) >> 8, (c.getGreen() * cscale) >> 8,
|
||||
(c.getBlue() * cscale) >> 8, c.getAlpha());
|
||||
outcolor[0].scaleRGB(cscale);
|
||||
}
|
||||
if(outcolor.length > 1) {
|
||||
ll0 = getLightLevel(skyemit0, false);
|
||||
|
|
@ -194,9 +192,7 @@ public class ShadowHDLighting extends DefaultHDLighting {
|
|||
}
|
||||
}
|
||||
if(cscale < 256) {
|
||||
Color c = outcolor[1];
|
||||
c.setRGBA((c.getRed() * cscale) >> 8, (c.getGreen() * cscale) >> 8,
|
||||
(c.getBlue() * cscale) >> 8, c.getAlpha());
|
||||
outcolor[1].scaleRGB(cscale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -269,8 +265,7 @@ public class ShadowHDLighting extends DefaultHDLighting {
|
|||
private final void shadowColor(Color c, int lightlevel, int[] shadowscale) {
|
||||
int scale = shadowscale[lightlevel];
|
||||
if(scale < 256)
|
||||
c.setRGBA((c.getRed() * scale) >> 8, (c.getGreen() * scale) >> 8,
|
||||
(c.getBlue() * scale) >> 8, c.getAlpha());
|
||||
c.scaleRGB(scale);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -97,16 +97,21 @@ public class PatchDefinition implements RenderPatch {
|
|||
*/
|
||||
PatchDefinition(PatchDefinition orig, double rotatex, double rotatey, double rotatez, Vector3D rotorigin, int textureindex) {
|
||||
if (rotorigin == null) rotorigin = offsetCenter;
|
||||
/* Precompute trig once - reused for all three vector rotations */
|
||||
double sinX = 0, cosX = 1, sinY = 0, cosY = 1, sinZ = 0, cosZ = 1;
|
||||
if (rotatex != 0) { double r = Math.toRadians(rotatex); sinX = Math.sin(r); cosX = Math.cos(r); }
|
||||
if (rotatey != 0) { double r = Math.toRadians(rotatey); sinY = Math.sin(r); cosY = Math.cos(r); }
|
||||
if (rotatez != 0) { double r = Math.toRadians(rotatez); sinZ = Math.sin(r); cosZ = Math.cos(r); }
|
||||
Vector3D vec = new Vector3D(orig.x0, orig.y0, orig.z0);
|
||||
rotate(vec, rotatex, rotatey, rotatez, rotorigin); /* Rotate origin */
|
||||
rotatePrecomputed(vec, sinX, cosX, sinY, cosY, sinZ, cosZ, rotorigin); /* Rotate origin */
|
||||
x0 = vec.x; y0 = vec.y; z0 = vec.z;
|
||||
/* Rotate U */
|
||||
vec.x = orig.xu; vec.y = orig.yu; vec.z = orig.zu;
|
||||
rotate(vec, rotatex, rotatey, rotatez, rotorigin); /* Rotate origin */
|
||||
rotatePrecomputed(vec, sinX, cosX, sinY, cosY, sinZ, cosZ, rotorigin);
|
||||
xu = vec.x; yu = vec.y; zu = vec.z;
|
||||
/* Rotate V */
|
||||
vec.x = orig.xv; vec.y = orig.yv; vec.z = orig.zv;
|
||||
rotate(vec, rotatex, rotatey, rotatez, rotorigin); /* Rotate origin */
|
||||
rotatePrecomputed(vec, sinX, cosX, sinY, cosY, sinZ, cosZ, rotorigin);
|
||||
xv = vec.x; yv = vec.y; zv = vec.z;
|
||||
umin = orig.umin; vmin = orig.vmin;
|
||||
umax = orig.umax; vmax = orig.vmax;
|
||||
|
|
@ -120,26 +125,30 @@ public class PatchDefinition implements RenderPatch {
|
|||
update();
|
||||
}
|
||||
|
||||
private void rotate(Vector3D vec, double xcnt, double ycnt, double zcnt, Vector3D origin) {
|
||||
// If no rotation, skip
|
||||
if ((xcnt == 0) && (ycnt == 0) && (zcnt == 0)) return;
|
||||
vec.subtract(origin); /* Shoft to center of block */
|
||||
private static void rotatePrecomputed(Vector3D vec,
|
||||
double sinX, double cosX, double sinY, double cosY, double sinZ, double cosZ,
|
||||
Vector3D origin) {
|
||||
if (sinX == 0 && sinY == 0 && sinZ == 0) return;
|
||||
vec.subtract(origin);
|
||||
/* Do X rotation */
|
||||
double rot = Math.toRadians(xcnt);
|
||||
double nval = vec.z * Math.sin(rot) + vec.y * Math.cos(rot);
|
||||
vec.z = vec.z * Math.cos(rot) - vec.y * Math.sin(rot);
|
||||
if (sinX != 0) {
|
||||
double nval = vec.z * sinX + vec.y * cosX;
|
||||
vec.z = vec.z * cosX - vec.y * sinX;
|
||||
vec.y = nval;
|
||||
}
|
||||
/* Do Y rotation */
|
||||
rot = Math.toRadians(ycnt);
|
||||
nval = vec.x * Math.cos(rot) - vec.z * Math.sin(rot);
|
||||
vec.z = vec.x * Math.sin(rot) + vec.z * Math.cos(rot);
|
||||
if (sinY != 0) {
|
||||
double nval = vec.x * cosY - vec.z * sinY;
|
||||
vec.z = vec.x * sinY + vec.z * cosY;
|
||||
vec.x = nval;
|
||||
}
|
||||
/* Do Z rotation */
|
||||
rot = Math.toRadians(zcnt);
|
||||
nval = vec.y * Math.sin(rot) + vec.x * Math.cos(rot);
|
||||
vec.y = vec.y * Math.cos(rot) - vec.x * Math.sin(rot);
|
||||
if (sinZ != 0) {
|
||||
double nval = vec.y * sinZ + vec.x * cosZ;
|
||||
vec.y = vec.y * cosZ - vec.x * sinZ;
|
||||
vec.x = nval;
|
||||
vec.add(origin); /* Shoft back to corner */
|
||||
}
|
||||
vec.add(origin);
|
||||
}
|
||||
public void update(double x0, double y0, double z0, double xu,
|
||||
double yu, double zu, double xv, double yv, double zv, double umin,
|
||||
|
|
@ -171,7 +180,7 @@ public class PatchDefinition implements RenderPatch {
|
|||
/* Compute hash code */
|
||||
hc = (int)((Double.doubleToLongBits(x0 + xu + xv) >> 32) ^
|
||||
(Double.doubleToLongBits(y0 + yu + yv) >> 34) ^
|
||||
(Double.doubleToLongBits(z0 + yu + yv) >> 36) ^
|
||||
(Double.doubleToLongBits(z0 + zu + zv) >> 36) ^
|
||||
(Double.doubleToLongBits(umin + umax + vmin + vmax + vmaxatumax) >> 38)) ^
|
||||
(sidevis.ordinal() << 8) ^ textureindex;
|
||||
/* Now compute normal of surface - U cross V */
|
||||
|
|
@ -221,27 +230,27 @@ public class PatchDefinition implements RenderPatch {
|
|||
}
|
||||
public boolean validate() {
|
||||
boolean good = true;
|
||||
// Compute visible corners to see if we're inside cube
|
||||
double xx0 = x0 + (xu - x0) * umin + (xv - x0) * vmin;
|
||||
double xx1 = x0 + (xu - x0) * vmin + (xv - x0) * vmax;
|
||||
double xx2 = x0 + (xu - x0) * umax + (xv - x0) * vmin;
|
||||
double xx3 = x0 + (xu - x0) * vmax + (xv - x0) * vmax;;
|
||||
// Compute visible corners to see if we're inside cube (u.x = xu-x0, v.x = xv-x0)
|
||||
double xx0 = x0 + u.x * umin + v.x * vmin;
|
||||
double xx1 = x0 + u.x * vmin + v.x * vmax;
|
||||
double xx2 = x0 + u.x * umax + v.x * vmin;
|
||||
double xx3 = x0 + u.x * vmax + v.x * vmax;
|
||||
if (outOfRange(xx0) || outOfRange(xx1) || outOfRange(xx2) || outOfRange(xx3)) {
|
||||
Log.verboseinfo(String.format("Invalid visible range xu=[%f:%f], xv=[%f:%f]", xx0, xx2, xx1, xx3));
|
||||
good = false;
|
||||
}
|
||||
double yy0 = y0 + (yu - y0) * umin + (yv - y0) * vmin;
|
||||
double yy1 = y0 + (yu - y0) * vmin + (yv - y0) * vmax;
|
||||
double yy2 = y0 + (yu - y0) * umax + (yv - y0) * vmin;
|
||||
double yy3 = y0 + (yu - y0) * vmax + (yv - y0) * vmax;;
|
||||
double yy0 = y0 + u.y * umin + v.y * vmin;
|
||||
double yy1 = y0 + u.y * vmin + v.y * vmax;
|
||||
double yy2 = y0 + u.y * umax + v.y * vmin;
|
||||
double yy3 = y0 + u.y * vmax + v.y * vmax;
|
||||
if (outOfRange(yy0) || outOfRange(yy1) || outOfRange(yy2) || outOfRange(yy3)) {
|
||||
Log.verboseinfo(String.format("Invalid visible range yu=[%f:%f], yv=[%f:%f]", yy0, yy2, yy1, yy3));
|
||||
good = false;
|
||||
}
|
||||
double zz0 = z0 + (zu - z0) * umin + (zv - z0) * vmin;
|
||||
double zz1 = z0 + (zu - z0) * vmin + (zv - z0) * vmax;
|
||||
double zz2 = z0 + (zu - z0) * umax + (zv - z0) * vmin;
|
||||
double zz3 = z0 + (zu - z0) * vmax + (zv - z0) * vmax;
|
||||
double zz0 = z0 + u.z * umin + v.z * vmin;
|
||||
double zz1 = z0 + u.z * vmin + v.z * vmax;
|
||||
double zz2 = z0 + u.z * umax + v.z * vmin;
|
||||
double zz3 = z0 + u.z * vmax + v.z * vmax;
|
||||
if (outOfRange(zz0) || outOfRange(zz1) || outOfRange(zz2) || outOfRange(zz3)) {
|
||||
Log.verboseinfo(String.format("Invalid visible range zu=[%f:%f], zv=[%f:%f]", zz0, zz2, zz1, zz3));
|
||||
good = false;
|
||||
|
|
|
|||
|
|
@ -306,11 +306,10 @@ public class DynmapBlockState {
|
|||
*/
|
||||
public static final DynmapBlockState getStateByGlobalIndex(int gidx) {
|
||||
if (blockArrayByIndex != null) {
|
||||
try {
|
||||
if (gidx >= 0 && gidx < blockArrayByIndex.length) {
|
||||
return blockArrayByIndex[gidx];
|
||||
} catch (ArrayIndexOutOfBoundsException aioob) {
|
||||
return AIR;
|
||||
}
|
||||
return AIR;
|
||||
}
|
||||
DynmapBlockState bs = blocksByIndex.get(gidx);
|
||||
return (bs != null) ? bs : AIR;
|
||||
|
|
@ -322,11 +321,10 @@ public class DynmapBlockState {
|
|||
*/
|
||||
public static final DynmapBlockState getStateByLegacyBlockID(int legacyid) {
|
||||
if (blockArrayByLegacyID != null) {
|
||||
try {
|
||||
if (legacyid >= 0 && legacyid < blockArrayByLegacyID.length) {
|
||||
return blockArrayByLegacyID[legacyid];
|
||||
} catch (ArrayIndexOutOfBoundsException aioob) {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return blocksByLegacyID.get(legacyid);
|
||||
}
|
||||
|
|
@ -348,7 +346,9 @@ public class DynmapBlockState {
|
|||
|
||||
rslt = AIR; // Assume miss
|
||||
String[] statelist = statename.toLowerCase().split(",");
|
||||
for (DynmapBlockState bb : blk.states) {
|
||||
for (int sidx = 0; sidx <= blk.stateLastIdx; sidx++) {
|
||||
DynmapBlockState bb = blk.states[sidx];
|
||||
if (bb == AIR) continue; // Skip AIR fill slots
|
||||
boolean match = true;
|
||||
for (int i = 0; i < statelist.length; i++) {
|
||||
boolean valmatch = false;
|
||||
|
|
@ -546,10 +546,20 @@ public class DynmapBlockState {
|
|||
* Test if matches attrib=value pair
|
||||
*/
|
||||
public final boolean isStateMatch(String attrib, String value) {
|
||||
String v = attrib + "=" + value;
|
||||
v = v.toLowerCase();
|
||||
int alen = attrib.length();
|
||||
int vlen = value.length();
|
||||
int total = alen + 1 + vlen;
|
||||
outer:
|
||||
for (String state : stateList) {
|
||||
if (state.equals(v)) return true;
|
||||
if (state.length() != total) continue;
|
||||
for (int i = 0; i < alen; i++) {
|
||||
if (Character.toLowerCase(attrib.charAt(i)) != state.charAt(i)) continue outer;
|
||||
}
|
||||
if (state.charAt(alen) != '=') continue;
|
||||
for (int i = 0; i < vlen; i++) {
|
||||
if (Character.toLowerCase(value.charAt(i)) != state.charAt(alen + 1 + i)) continue outer;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue