use of org.dynmap.utils.Vector3D in project dynmap by webbukkit.
the class AreaMarkerImpl method testTileForBoostMarkers.
final boolean testTileForBoostMarkers(DynmapWorld w, HDPerspective perspective, final double tile_x, final double tile_y, final double tile_dim) {
Map<String, BoundingBox> bbc = bb_cache;
if (bbc == null) {
bbc = new ConcurrentHashMap<String, BoundingBox>();
}
BoundingBox bb = bbc.get(perspective.getName());
if (bb == null) {
// No cached bounding box, so generate it
bb = new BoundingBox();
Vector3D v = new Vector3D();
Vector3D v2 = new Vector3D();
bb.xmin = Double.MAX_VALUE;
bb.xmax = -Double.MAX_VALUE;
bb.ymin = Double.MAX_VALUE;
bb.ymax = -Double.MAX_VALUE;
if (corners != null) {
ArrayList<Coord> crn = corners;
int cnt = crn.size();
if (cnt == 2) {
// Special case
cnt = 4;
crn = new ArrayList<Coord>();
Coord c0 = corners.get(0);
Coord c1 = corners.get(1);
crn.add(c0);
crn.add(new Coord(c0.x, c1.z));
crn.add(c1);
crn.add(new Coord(c1.x, c0.z));
}
double ymid = (this.ytop + this.ybottom) / 2.0;
bb.xp = new double[cnt];
bb.yp = new double[cnt];
for (int i = 0; i < cnt; i++) {
Coord c = crn.get(i);
// get coords of point, in world coord
v.x = c.x;
// get coords of point, in world coord
v.y = ymid;
// get coords of point, in world coord
v.z = c.z;
// Transform to map coord
perspective.transformWorldToMapCoord(v, v2);
if (v2.x < bb.xmin)
bb.xmin = v2.x;
if (v2.y < bb.ymin)
bb.ymin = v2.y;
if (v2.x > bb.xmax)
bb.xmax = v2.x;
if (v2.y > bb.ymax)
bb.ymax = v2.y;
bb.xp[i] = v2.x;
bb.yp[i] = v2.y;
}
}
// Log.info("x=" + bb.xmin + " - " + bb.xmax + ", y=" + bb.ymin + " - " + bb.ymax);
bbc.put(perspective.getName(), bb);
bb_cache = bbc;
}
final double tile_x2 = tile_x + tile_dim;
final double tile_y2 = tile_y + tile_dim;
if ((bb.xmin > tile_x2) || (bb.xmax < tile_x) || (bb.ymin > tile_y2) || (bb.ymax < tile_y)) {
// Log.info("tile: " + tile_x + " / " + tile_y + " - miss");
return false;
}
final int cnt = bb.xp.length;
final double[] px = bb.xp;
final double[] py = bb.yp;
/* Now see if tile square intersects polygon - start with seeing if any point inside */
if (MarkerImpl.testPointInPolygon(tile_x, tile_y, px, py)) {
// If tile corner inside, we intersect
return true;
}
if (MarkerImpl.testPointInPolygon(tile_x2, tile_y, px, py)) {
// If tile corner inside, we intersect
return true;
}
if (MarkerImpl.testPointInPolygon(tile_x, tile_y2, px, py)) {
// If tile corner inside, we intersect
return true;
}
if (MarkerImpl.testPointInPolygon(tile_x2, tile_y2, px, py)) {
// If tile corner inside, we intersect
return true;
}
/* Test if any polygon corners are inside square */
for (int i = 0; i < cnt; i++) {
if ((px[i] >= tile_x) && (px[i] <= tile_x2) && (py[i] >= tile_y) && (py[i] <= tile_y2)) {
// If poly corner inside tile, we intersect
return true;
}
}
// Log.info("tile: " + tile_x + " / " + tile_y + " - hit");
return false;
}
use of org.dynmap.utils.Vector3D in project dynmap by webbukkit.
the class CircleMarkerImpl method testTileForBoostMarkers.
final boolean testTileForBoostMarkers(DynmapWorld w, HDPerspective perspective, double tile_x, double tile_y, double tile_dim) {
Map<String, BoundingBox> bbc = bb_cache;
if (bbc == null) {
bbc = new ConcurrentHashMap<String, BoundingBox>();
}
BoundingBox bb = bbc.get(perspective.getName());
if (bb == null) {
// No cached bounding box, so generate it
bb = new BoundingBox();
Vector3D v = new Vector3D();
Vector3D v2 = new Vector3D();
bb.xmin = Double.MAX_VALUE;
bb.xmax = -Double.MAX_VALUE;
bb.ymin = Double.MAX_VALUE;
bb.ymax = -Double.MAX_VALUE;
// Just do 16 points for now
int cnt = 16;
bb.xp = new double[cnt];
bb.yp = new double[cnt];
for (int i = 0; i < cnt; i++) {
v.x = this.x + (this.xr * Math.cos(2.0 * Math.PI * i / cnt));
v.y = this.y;
v.z = this.z + (this.zr * Math.sin(2.0 * Math.PI * i / cnt));
// Transform to map coord
perspective.transformWorldToMapCoord(v, v2);
if (v2.x < bb.xmin)
bb.xmin = v2.x;
if (v2.y < bb.ymin)
bb.ymin = v2.y;
if (v2.x > bb.xmax)
bb.xmax = v2.x;
if (v2.y > bb.ymax)
bb.ymax = v2.y;
bb.xp[i] = v2.x;
bb.yp[i] = v2.y;
}
// Log.info("x=" + bb.xmin + " - " + bb.xmax + ", y=" + bb.ymin + " - " + bb.ymax);
bbc.put(perspective.getName(), bb);
bb_cache = bbc;
}
final double tile_x2 = tile_x + tile_dim;
final double tile_y2 = tile_y + tile_dim;
if ((bb.xmin > tile_x2) || (bb.xmax < tile_x) || (bb.ymin > tile_y2) || (bb.ymax < tile_y)) {
// Log.info("tile: " + tile_x + " / " + tile_y + " - miss");
return false;
}
final int cnt = bb.xp.length;
final double[] px = bb.xp;
final double[] py = bb.yp;
/* Now see if tile square intersects polygon - start with seeing if any point inside */
if (MarkerImpl.testPointInPolygon(tile_x, tile_y, px, py)) {
// If tile corner inside, we intersect
return true;
}
if (MarkerImpl.testPointInPolygon(tile_x2, tile_y, px, py)) {
// If tile corner inside, we intersect
return true;
}
if (MarkerImpl.testPointInPolygon(tile_x, tile_y2, px, py)) {
// If tile corner inside, we intersect
return true;
}
if (MarkerImpl.testPointInPolygon(tile_x2, tile_y2, px, py)) {
// If tile corner inside, we intersect
return true;
}
/* Test if any polygon corners are inside square */
for (int i = 0; i < cnt; i++) {
if ((px[i] >= tile_x) && (px[i] <= tile_x2) && (py[i] >= tile_y) && (py[i] <= tile_y2)) {
// If poly corner inside tile, we intersect
return true;
}
}
// Log.info("tile: " + tile_x + " / " + tile_y + " - hit");
return false;
}
use of org.dynmap.utils.Vector3D in project dynmap by webbukkit.
the class IsoHDPerspective method getTileCoords.
@Override
public List<TileFlags.TileCoord> getTileCoords(DynmapWorld world, int x, int y, int z, int tilescale) {
HashSet<TileFlags.TileCoord> tiles = new HashSet<TileFlags.TileCoord>();
Vector3D block = new Vector3D();
block.x = x;
block.y = y;
block.z = z;
Vector3D corner = new Vector3D();
int tileSize = 128 << tilescale;
/* Loop through corners of the cube */
for (int i = 0; i < 2; i++) {
double inity = block.y;
for (int j = 0; j < 2; j++) {
double initz = block.z;
for (int k = 0; k < 2; k++) {
world_to_map.transform(block, corner);
/* Get map coordinate of corner */
tiles.add(new TileFlags.TileCoord(fastFloor(corner.x / tileSize), fastFloor(corner.y / tileSize)));
block.z += 1;
}
block.z = initz;
block.y += 1;
}
block.y = inity;
block.x += 1;
}
return new ArrayList<TileFlags.TileCoord>(tiles);
}
use of org.dynmap.utils.Vector3D in project dynmap by webbukkit.
the class IsoHDPerspective method getRequiredChunks.
@Override
public List<DynmapChunk> getRequiredChunks(MapTile tile) {
if (!(tile instanceof HDMapTile))
return Collections.emptyList();
HDMapTile t = (HDMapTile) tile;
int min_chunk_x = Integer.MAX_VALUE;
int max_chunk_x = Integer.MIN_VALUE;
int min_chunk_z = Integer.MAX_VALUE;
int max_chunk_z = Integer.MIN_VALUE;
int tileSize = tile.getTileSize();
/* Make corners for volume:
* 0 = bottom-lower-left (xyz),
* 1 = top-lower-left (xyZ),
* 2 = bottom-upper-left (xYz),
* 3 = top-upper-left (xYZ),
* 4 = bottom-lower-right (Xyz),
* 5 = top-lower-right (XyZ),
* 6 = bottom-upper-right (XYz),
* 7 = top-upper-right (XYZ) */
Vector3D[] corners = new Vector3D[8];
double dx = -basemodscale, dy = -basemodscale;
/* Add 1 block on each axis */
for (int x = t.tx, idx = 0; x <= (t.tx + 1); x++) {
dy = -basemodscale;
for (int y = t.ty; y <= (t.ty + 1); y++) {
for (int z = 0; z <= 1; z++) {
corners[idx] = new Vector3D();
corners[idx].x = x * tileSize + dx;
corners[idx].y = y * tileSize + dy;
corners[idx].z = (z == 1) ? t.getDynmapWorld().worldheight : t.getDynmapWorld().minY;
map_to_world.transform(corners[idx]);
/* Compute chunk coordinates of corner */
int cx = fastFloor(corners[idx].x / 16);
int cz = fastFloor(corners[idx].z / 16);
/* Compute min/max of chunk coordinates */
if (min_chunk_x > cx)
min_chunk_x = cx;
if (max_chunk_x < cx)
max_chunk_x = cx;
if (min_chunk_z > cz)
min_chunk_z = cz;
if (max_chunk_z < cz)
max_chunk_z = cz;
idx++;
}
dy = basemodscale;
}
dx = basemodscale;
}
/* Make rectangles of X-Z projection of each side of the tile volume, 0 = top, 1 = bottom, 2 = left, 3 = right,
* 4 = upper, 5 = lower */
Polygon[] side = new Polygon[6];
for (int sidenum = 0; sidenum < side.length; sidenum++) {
side[sidenum] = new Polygon();
for (int corner = 0; corner < corners_by_side[sidenum].length; corner++) {
int cid = corners_by_side[sidenum][corner];
side[sidenum].addVertex(corners[cid].x, corners[cid].z);
}
}
/* Now, need to walk through the min/max range to see which chunks are actually needed */
ArrayList<DynmapChunk> chunks = new ArrayList<DynmapChunk>();
for (int x = min_chunk_x; x <= max_chunk_x; x++) {
for (int z = min_chunk_z; z <= max_chunk_z; z++) {
boolean hit = false;
for (int sidenum = 0; (!hit) && (sidenum < side.length); sidenum++) {
if (side[sidenum].clip(16.0 * x, 16.0 * z, 16.0 * (x + 1), 16.0 * (z + 1)) != null) {
hit = true;
}
}
// xs += c;
if (hit) {
DynmapChunk chunk = new DynmapChunk(x, z);
chunks.add(chunk);
}
}
}
return chunks;
}
use of org.dynmap.utils.Vector3D in project dynmap by webbukkit.
the class IsoHDPerspective method render.
@Override
public boolean render(MapChunkCache cache, HDMapTile tile, String mapname) {
final long startTimestamp = System.currentTimeMillis();
Color rslt = new Color();
MapIterator mapiter = cache.getIterator(0, 0, 0);
DynmapWorld world = tile.getDynmapWorld();
int tileSize = tile.getTileSize();
int scaled = 0;
if ((tile.boostzoom > 0) && MarkerAPIImpl.testTileForBoostMarkers(cache.getWorld(), this, tile.tx * tileSize, tile.ty * tileSize, tileSize)) {
scaled = tile.boostzoom;
}
int sizescale = 1 << scaled;
/* Build shader state object for each shader */
HDShaderState[] shaderstate = MapManager.mapman.hdmapman.getShaderStateForTile(tile, cache, mapiter, mapname, sizescale * this.basemodscale);
int numshaders = shaderstate.length;
if (numshaders == 0)
return false;
/* Check if nether world */
boolean isnether = world.isNether();
/* Create buffered image for each */
DynmapBufferedImage[] im = new DynmapBufferedImage[numshaders];
DynmapBufferedImage[] dayim = new DynmapBufferedImage[numshaders];
int[][] argb_buf = new int[numshaders][];
int[][] day_argb_buf = new int[numshaders][];
boolean[] isOpaque = new boolean[numshaders];
int[] bgday = new int[numshaders];
int[] bgnight = new int[numshaders];
for (int i = 0; i < numshaders; i++) {
HDLighting lighting = shaderstate[i].getLighting();
im[i] = DynmapBufferedImage.allocateBufferedImage(tileSize * sizescale, tileSize * sizescale);
argb_buf[i] = im[i].argb_buf;
if (lighting.isNightAndDayEnabled()) {
dayim[i] = DynmapBufferedImage.allocateBufferedImage(tileSize * sizescale, tileSize * sizescale);
day_argb_buf[i] = dayim[i].argb_buf;
}
isOpaque[i] = !shaderstate[i].getMap().getImageFormat().getEncoding().hasAlpha;
bgday[i] = shaderstate[i].getMap().getBackgroundARGBDay();
bgnight[i] = shaderstate[i].getMap().getBackgroundARGBNight();
}
// Mark the tiles we're going to render as validated
for (int i = 0; i < numshaders; i++) {
MapTypeState mts = world.getMapState(shaderstate[i].getMap());
if (mts != null) {
mts.validateTile(tile.tx, tile.ty);
}
}
/* Create perspective state object */
OurPerspectiveState ps = new OurPerspectiveState(mapiter, isnether, scaled);
ps.top = new Vector3D();
ps.bottom = new Vector3D();
ps.direction = new Vector3D();
double xbase = tile.tx * tileSize;
double ybase = tile.ty * tileSize;
boolean[] shaderdone = new boolean[numshaders];
boolean[] rendered = new boolean[numshaders];
double height = maxheight;
if (height == Integer.MIN_VALUE) {
/* Not set - assume world height - 1 */
if (isnether)
height = 127;
else
height = tile.getDynmapWorld().worldheight - 1;
}
double miny = minheight;
if (miny == Integer.MIN_VALUE) {
/* Not set - assume world height - 1 */
miny = tile.getDynmapWorld().minY;
}
for (int x = 0; x < tileSize * sizescale; x++) {
ps.px = x;
for (int y = 0; y < tileSize * sizescale; y++) {
ps.top.x = ps.bottom.x = xbase + (x + 0.5) / sizescale;
/* Start at center of pixel at Y=height+0.5, bottom at Y=-0.5 */
ps.top.y = ps.bottom.y = ybase + (y + 0.5) / sizescale;
ps.top.z = height + 0.5;
ps.bottom.z = miny - 0.5;
map_to_world.transform(ps.top);
/* Transform to world coordinates */
map_to_world.transform(ps.bottom);
ps.direction.set(ps.bottom);
ps.direction.subtract(ps.top);
ps.py = y / sizescale;
for (int i = 0; i < numshaders; i++) {
shaderstate[i].reset(ps);
}
try {
ps.raytrace(cache, shaderstate, shaderdone);
} catch (Exception ex) {
Log.severe("Error while raytracing tile: perspective=" + this.name + ", coord=" + mapiter.getX() + "," + mapiter.getY() + "," + mapiter.getZ() + ", blockid=" + mapiter.getBlockType() + ", lighting=" + mapiter.getBlockSkyLight() + ":" + mapiter.getBlockEmittedLight() + ", biome=" + mapiter.getBiome().toString(), ex);
ex.printStackTrace();
}
for (int i = 0; i < numshaders; i++) {
if (shaderdone[i] == false) {
shaderstate[i].rayFinished(ps);
} else {
shaderdone[i] = false;
rendered[i] = true;
}
shaderstate[i].getRayColor(rslt, 0);
int c_argb = rslt.getARGB();
if (c_argb != 0)
rendered[i] = true;
if (isOpaque[i] && (c_argb == 0)) {
argb_buf[i][(tileSize * sizescale - y - 1) * tileSize * sizescale + x] = bgnight[i];
} else {
argb_buf[i][(tileSize * sizescale - y - 1) * tileSize * sizescale + x] = c_argb;
}
if (day_argb_buf[i] != null) {
shaderstate[i].getRayColor(rslt, 1);
c_argb = rslt.getARGB();
if (isOpaque[i] && (c_argb == 0)) {
day_argb_buf[i][(tileSize * sizescale - y - 1) * tileSize * sizescale + x] = bgday[i];
} else {
day_argb_buf[i][(tileSize * sizescale - y - 1) * tileSize * sizescale + x] = c_argb;
}
}
}
}
}
boolean renderone = false;
/* Test to see if we're unchanged from older tile */
MapStorage storage = world.getMapStorage();
for (int i = 0; i < numshaders; i++) {
long crc = MapStorage.calculateImageHashCode(argb_buf[i], 0, argb_buf[i].length);
boolean tile_update = false;
String prefix = shaderstate[i].getMap().getPrefix();
MapStorageTile mtile = storage.getTile(world, shaderstate[i].getMap(), tile.tx, tile.ty, 0, MapType.ImageVariant.STANDARD);
mtile.getWriteLock();
try {
if (mtile.matchesHashCode(crc) == false) {
/* Wrap buffer as buffered image */
if (rendered[i]) {
mtile.write(crc, im[i].buf_img, startTimestamp);
} else {
mtile.delete();
}
MapManager.mapman.pushUpdate(tile.getDynmapWorld(), new Client.Tile(mtile.getURI()));
tile_update = true;
renderone = true;
} else {
if (!rendered[i]) {
mtile.delete();
}
}
} finally {
mtile.releaseWriteLock();
DynmapBufferedImage.freeBufferedImage(im[i]);
}
MapManager.mapman.updateStatistics(tile, prefix, true, tile_update, !rendered[i]);
/* Handle day image, if needed */
if (dayim[i] != null) {
crc = MapStorage.calculateImageHashCode(day_argb_buf[i], 0, day_argb_buf[i].length);
mtile = storage.getTile(world, shaderstate[i].getMap(), tile.tx, tile.ty, 0, MapType.ImageVariant.DAY);
mtile.getWriteLock();
tile_update = false;
try {
if (mtile.matchesHashCode(crc) == false) {
/* Wrap buffer as buffered image */
if (rendered[i]) {
mtile.write(crc, dayim[i].buf_img, startTimestamp);
} else {
mtile.delete();
}
MapManager.mapman.pushUpdate(tile.getDynmapWorld(), new Client.Tile(mtile.getURI()));
tile_update = true;
renderone = true;
} else {
if (!rendered[i]) {
mtile.delete();
}
}
} finally {
mtile.releaseWriteLock();
DynmapBufferedImage.freeBufferedImage(dayim[i]);
}
MapManager.mapman.updateStatistics(tile, prefix + "_day", true, tile_update, !rendered[i]);
}
}
return renderone;
}
Aggregations