mirror of https://github.com/webbukkit/dynmap.git
320 lines
12 KiB
Java
320 lines
12 KiB
Java
package org.dynmap.hdmap;
|
|
|
|
import static org.dynmap.JSONUtils.s;
|
|
|
|
import java.io.IOException;
|
|
|
|
import org.dynmap.Color;
|
|
import org.dynmap.ColorScheme;
|
|
import org.dynmap.ConfigurationNode;
|
|
import org.dynmap.DynmapCore;
|
|
import org.dynmap.MapManager;
|
|
import org.dynmap.common.BiomeMap;
|
|
import org.dynmap.common.DynmapCommandSender;
|
|
import org.dynmap.exporter.OBJExport;
|
|
import org.dynmap.renderer.DynmapBlockState;
|
|
import org.dynmap.utils.BlockStep;
|
|
import org.dynmap.utils.DynLongHashMap;
|
|
import org.dynmap.utils.MapChunkCache;
|
|
import org.dynmap.utils.MapIterator;
|
|
import org.json.simple.JSONObject;
|
|
|
|
public class DefaultHDShader implements HDShader {
|
|
private String name;
|
|
protected ColorScheme colorScheme;
|
|
|
|
protected boolean transparency; /* Is transparency support active? */
|
|
public enum BiomeColorOption {
|
|
NONE, BIOME, TEMPERATURE, RAINFALL
|
|
}
|
|
protected BiomeColorOption biomecolored = BiomeColorOption.NONE; /* Use biome for coloring */
|
|
|
|
public DefaultHDShader(DynmapCore core, ConfigurationNode configuration) {
|
|
name = (String) configuration.get("name");
|
|
colorScheme = ColorScheme.getScheme(core, configuration.getString("colorscheme", "default"));
|
|
transparency = configuration.getBoolean("transparency", true); /* Default on */
|
|
String biomeopt = configuration.getString("biomecolored", "none");
|
|
if(biomeopt.equals("biome")) {
|
|
biomecolored = BiomeColorOption.BIOME;
|
|
}
|
|
else if(biomeopt.equals("temperature")) {
|
|
biomecolored = BiomeColorOption.TEMPERATURE;
|
|
}
|
|
else if(biomeopt.equals("rainfall")) {
|
|
biomecolored = BiomeColorOption.RAINFALL;
|
|
}
|
|
else {
|
|
biomecolored = BiomeColorOption.NONE;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean isBiomeDataNeeded() {
|
|
return biomecolored == BiomeColorOption.BIOME;
|
|
}
|
|
|
|
@Override
|
|
public boolean isRawBiomeDataNeeded() {
|
|
return (biomecolored == BiomeColorOption.RAINFALL) || (biomecolored == BiomeColorOption.TEMPERATURE);
|
|
}
|
|
|
|
@Override
|
|
public boolean isHightestBlockYDataNeeded() {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean isBlockTypeDataNeeded() {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean isSkyLightLevelNeeded() {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean isEmittedLightLevelNeeded() {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public String getName() {
|
|
return name;
|
|
}
|
|
|
|
private class OurShaderState implements HDShaderState {
|
|
private Color color[];
|
|
protected MapIterator mapiter;
|
|
protected HDMap map;
|
|
private Color tmpcolor[];
|
|
private int pixelodd;
|
|
private HDLighting lighting;
|
|
final int[] lightingTable;
|
|
|
|
private OurShaderState(MapIterator mapiter, HDMap map, MapChunkCache cache) {
|
|
this.mapiter = mapiter;
|
|
this.map = map;
|
|
this.lighting = map.getLighting();
|
|
if(lighting.isNightAndDayEnabled()) {
|
|
color = new Color[] { new Color(), new Color() };
|
|
tmpcolor = new Color[] { new Color(), new Color() };
|
|
}
|
|
else {
|
|
color = new Color[] { new Color() };
|
|
tmpcolor = new Color[] { new Color() };
|
|
}
|
|
if (MapManager.mapman.useBrightnessTable()) {
|
|
lightingTable = cache.getWorld().getBrightnessTable();
|
|
}
|
|
else {
|
|
lightingTable = null;
|
|
}
|
|
}
|
|
/**
|
|
* Get our shader
|
|
*/
|
|
public HDShader getShader() {
|
|
return DefaultHDShader.this;
|
|
}
|
|
|
|
/**
|
|
* Get our map
|
|
*/
|
|
public HDMap getMap() {
|
|
return map;
|
|
}
|
|
/**
|
|
* Get our lighting
|
|
*/
|
|
public HDLighting getLighting() {
|
|
return lighting;
|
|
}
|
|
/**
|
|
* Reset renderer state for new ray
|
|
*/
|
|
public void reset(HDPerspectiveState ps) {
|
|
for(int i = 0; i < color.length; i++)
|
|
color[i].setTransparent();
|
|
pixelodd = (ps.getPixelX() & 0x3) + (ps.getPixelY()<<1);
|
|
}
|
|
|
|
protected Color[] getBlockColors(DynmapBlockState block) {
|
|
//TODO: this will not work right on 1.13+, but thwo whole colorscheme thing is broken anyway...
|
|
int blocktype = block.globalStateIndex / 16;
|
|
int blockdata = block.globalStateIndex & 0x0F;
|
|
if((blockdata != 0) && (colorScheme.datacolors[blocktype] != null))
|
|
return colorScheme.datacolors[blocktype][blockdata];
|
|
else
|
|
return colorScheme.colors[blocktype];
|
|
}
|
|
|
|
/**
|
|
* Process next ray step - called for each block on route
|
|
* @return true if ray is done, false if ray needs to continue
|
|
*/
|
|
public boolean processBlock(HDPerspectiveState ps) {
|
|
int i;
|
|
DynmapBlockState blocktype = ps.getBlockState();
|
|
if (blocktype.isAir())
|
|
return false;
|
|
Color[] colors = getBlockColors(blocktype);
|
|
|
|
if (colors != null) {
|
|
int seq;
|
|
int subalpha = ps.getSubmodelAlpha();
|
|
/* Figure out which color to use */
|
|
switch(ps.getLastBlockStep()) {
|
|
case X_PLUS:
|
|
case X_MINUS:
|
|
seq = 2;
|
|
break;
|
|
case Z_PLUS:
|
|
case Z_MINUS:
|
|
seq = 0;
|
|
break;
|
|
default:
|
|
//if(subalpha >= 0) /* We hit a block in a model */
|
|
// seq = 4; /* Use smooth top */
|
|
//else
|
|
if(((pixelodd + mapiter.getY()) & 0x03) == 0)
|
|
seq = 3;
|
|
else
|
|
seq = 1;
|
|
break;
|
|
}
|
|
Color c = colors[seq];
|
|
if (c.getAlpha() > 0) {
|
|
/* Handle light level, if needed */
|
|
lighting.applyLighting(ps, this, c, tmpcolor);
|
|
/* If we got alpha from subblock model, use it instead */
|
|
if(subalpha >= 0) {
|
|
for(int j = 0; j < tmpcolor.length; j++)
|
|
tmpcolor[j].setAlpha(Math.max(subalpha,tmpcolor[j].getAlpha()));
|
|
}
|
|
/* Blend color with accumulated color (weighted by alpha) */
|
|
if(!transparency) { /* No transparency support */
|
|
for(i = 0; i < color.length; i++)
|
|
color[i].setARGB(tmpcolor[i].getARGB() | 0xFF000000);
|
|
return true; /* We're done */
|
|
}
|
|
/* If no previous color contribution, use new color */
|
|
else if(color[0].isTransparent()) {
|
|
for(i = 0; i < color.length; i++)
|
|
color[i].setColor(tmpcolor[i]);
|
|
return (color[0].getAlpha() == 255);
|
|
}
|
|
/* Else, blend and generate new alpha */
|
|
else {
|
|
int alpha = color[0].getAlpha();
|
|
int alpha2 = tmpcolor[0].getAlpha() * (255-alpha) / 255;
|
|
int talpha = alpha + alpha2;
|
|
for(i = 0; i < color.length; i++)
|
|
color[i].setRGBA((tmpcolor[i].getRed()*alpha2 + color[i].getRed()*alpha) / talpha,
|
|
(tmpcolor[i].getGreen()*alpha2 + color[i].getGreen()*alpha) / talpha,
|
|
(tmpcolor[i].getBlue()*alpha2 + color[i].getBlue()*alpha) / talpha, talpha);
|
|
return (talpha >= 254); /* If only one short, no meaningful contribution left */
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
/**
|
|
* Ray ended - used to report that ray has exited map (called if renderer has not reported complete)
|
|
*/
|
|
public void rayFinished(HDPerspectiveState ps) {
|
|
}
|
|
/**
|
|
* Get result color - get resulting color for ray
|
|
* @param c - object to store color value in
|
|
* @param index - index of color to request (renderer specific - 0=default, 1=day for night/day renderer
|
|
*/
|
|
public void getRayColor(Color c, int index) {
|
|
c.setColor(color[index]);
|
|
}
|
|
/**
|
|
* Clean up state object - called after last ray completed
|
|
*/
|
|
public void cleanup() {
|
|
}
|
|
@Override
|
|
public DynLongHashMap getCTMTextureCache() {
|
|
return null;
|
|
}
|
|
@Override
|
|
public int[] getLightingTable() {
|
|
return lightingTable;
|
|
}
|
|
}
|
|
|
|
private class OurBiomeShaderState extends OurShaderState {
|
|
private OurBiomeShaderState(MapIterator mapiter, HDMap map, MapChunkCache cache) {
|
|
super(mapiter, map, cache);
|
|
}
|
|
@Override
|
|
protected Color[] getBlockColors(DynmapBlockState blk) {
|
|
BiomeMap bio = mapiter.getBiome();
|
|
if(bio != null)
|
|
return colorScheme.biomecolors[bio.ordinal()];
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private class OurBiomeRainfallShaderState extends OurShaderState {
|
|
private OurBiomeRainfallShaderState(MapIterator mapiter, HDMap map, MapChunkCache cache) {
|
|
super(mapiter, map, cache);
|
|
}
|
|
@Override
|
|
protected Color[] getBlockColors(DynmapBlockState blk) {
|
|
return colorScheme.getRainColor(mapiter.getBiome().getRainfall());
|
|
}
|
|
}
|
|
|
|
private class OurBiomeTempShaderState extends OurShaderState {
|
|
private OurBiomeTempShaderState(MapIterator mapiter, HDMap map, MapChunkCache cache) {
|
|
super(mapiter, map, cache);
|
|
}
|
|
@Override
|
|
protected Color[] getBlockColors(DynmapBlockState blk) {
|
|
return colorScheme.getTempColor(mapiter.getBiome().getTemperature());
|
|
}
|
|
}
|
|
/**
|
|
* Get renderer state object for use rendering a tile
|
|
* @param map - map being rendered
|
|
* @param cache - chunk cache containing data for tile to be rendered
|
|
* @param mapiter - iterator used when traversing rays in tile
|
|
* @param scale - scale of the perspecitve
|
|
* @return state object to use for all rays in tile
|
|
*/
|
|
@Override
|
|
public HDShaderState getStateInstance(HDMap map, MapChunkCache cache, MapIterator mapiter, int scale) {
|
|
switch(biomecolored) {
|
|
case NONE:
|
|
return new OurShaderState(mapiter, map, cache);
|
|
case BIOME:
|
|
return new OurBiomeShaderState(mapiter, map, cache);
|
|
case RAINFALL:
|
|
return new OurBiomeRainfallShaderState(mapiter, map, cache);
|
|
case TEMPERATURE:
|
|
return new OurBiomeTempShaderState(mapiter, map, cache);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/* Add shader's contributions to JSON for map object */
|
|
public void addClientConfiguration(JSONObject mapObject) {
|
|
s(mapObject, "shader", name);
|
|
}
|
|
@Override
|
|
public void exportAsMaterialLibrary(DynmapCommandSender sender, OBJExport out) throws IOException {
|
|
throw new IOException("Export unsupported");
|
|
}
|
|
private static final String[] nulllist = new String[0];
|
|
@Override
|
|
public String[] getCurrentBlockMaterials(DynmapBlockState blk, MapIterator mapiter, int[] txtidx,
|
|
BlockStep[] steps) {
|
|
return nulllist;
|
|
}
|
|
}
|