From 3a0fcd15179c3c68fa0c20cf8e4861f68e032ef7 Mon Sep 17 00:00:00 2001 From: Daniel Mills Date: Mon, 26 Oct 2020 16:53:20 -0400 Subject: [PATCH] What a mess of hunks --- .../iris/gen/v2/IrisTerrainGenerator.java | 5 +- .../v2/scaffold/hunk/ChunkBiomeHunkView.java | 46 ++ .../gen/v2/scaffold/hunk/ChunkHunkView.java | 47 +++ .../iris/gen/v2/scaffold/hunk/Hunk.java | 398 +++++++++++++----- .../v2/scaffold/hunk/InvertedHunkView.java | 47 +++ .../v2/scaffold/hunk/RotatedXHunkView.java | 61 +++ .../v2/scaffold/hunk/RotatedYHunkView.java | 62 +++ .../v2/scaffold/hunk/RotatedZHunkView.java | 57 +++ 8 files changed, 623 insertions(+), 100 deletions(-) create mode 100644 src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/ChunkBiomeHunkView.java create mode 100644 src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/ChunkHunkView.java create mode 100644 src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/InvertedHunkView.java create mode 100644 src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/RotatedXHunkView.java create mode 100644 src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/RotatedYHunkView.java create mode 100644 src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/RotatedZHunkView.java diff --git a/src/main/java/com/volmit/iris/gen/v2/IrisTerrainGenerator.java b/src/main/java/com/volmit/iris/gen/v2/IrisTerrainGenerator.java index 717242b3b..c305cf3b3 100644 --- a/src/main/java/com/volmit/iris/gen/v2/IrisTerrainGenerator.java +++ b/src/main/java/com/volmit/iris/gen/v2/IrisTerrainGenerator.java @@ -1,5 +1,6 @@ package com.volmit.iris.gen.v2; +import org.bukkit.Material; import org.bukkit.block.Biome; import org.bukkit.block.data.BlockData; @@ -43,7 +44,9 @@ public class IrisTerrainGenerator public void generateDecorations(int x, int z, Hunk blocks) { - + blocks.iterateSurfaces2D((b) -> !b.getMaterial().isAir() && !b.getMaterial().equals(Material.WATER) && !b.getMaterial().equals(Material.LAVA), (xx,zz,top,bottom) -> { + + }); } public void generateTerrain(int x, int z, Hunk blocks) diff --git a/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/ChunkBiomeHunkView.java b/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/ChunkBiomeHunkView.java new file mode 100644 index 000000000..4f9616bae --- /dev/null +++ b/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/ChunkBiomeHunkView.java @@ -0,0 +1,46 @@ +package com.volmit.iris.gen.v2.scaffold.hunk; + +import org.bukkit.Chunk; +import org.bukkit.block.Biome; + +import com.volmit.iris.Iris; + +public class ChunkBiomeHunkView implements Hunk +{ + private final Chunk chunk; + + public ChunkBiomeHunkView(Chunk chunk) + { + this.chunk = chunk; + } + + @Override + public int getWidth() + { + return 16; + } + + @Override + public int getDepth() + { + return 16; + } + + @Override + public int getHeight() + { + return chunk.getWorld().getMaxHeight(); + } + + @Override + public void setRaw(int x, int y, int z, Biome t) + { + Iris.edit.setBiome(chunk.getWorld(), x + (chunk.getX() * 16), y, z + (chunk.getZ() * 16), t); + } + + @Override + public Biome getRaw(int x, int y, int z) + { + return Iris.edit.getBiome(chunk.getWorld(), x + (chunk.getX() * 16), y, z + (chunk.getZ() * 16)); + } +} diff --git a/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/ChunkHunkView.java b/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/ChunkHunkView.java new file mode 100644 index 000000000..928b7de2b --- /dev/null +++ b/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/ChunkHunkView.java @@ -0,0 +1,47 @@ +package com.volmit.iris.gen.v2.scaffold.hunk; + +import org.bukkit.Chunk; +import org.bukkit.block.data.BlockData; + +import com.volmit.iris.Iris; +import com.volmit.iris.util.FastBlockData; + +public class ChunkHunkView implements Hunk +{ + private final Chunk chunk; + + public ChunkHunkView(Chunk chunk) + { + this.chunk = chunk; + } + + @Override + public int getWidth() + { + return 16; + } + + @Override + public int getDepth() + { + return 16; + } + + @Override + public int getHeight() + { + return chunk.getWorld().getMaxHeight(); + } + + @Override + public void setRaw(int x, int y, int z, BlockData t) + { + Iris.edit.set(chunk.getWorld(), x + (chunk.getX() * 16), y, z + (chunk.getZ() * 16), FastBlockData.of(t)); + } + + @Override + public BlockData getRaw(int x, int y, int z) + { + return Iris.edit.get(chunk.getWorld(), x + (chunk.getX() * 16), y, z + (chunk.getZ() * 16)).getBlockData(); + } +} diff --git a/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/Hunk.java b/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/Hunk.java index 6a0003f38..fdf6393f7 100644 --- a/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/Hunk.java +++ b/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/Hunk.java @@ -1,7 +1,8 @@ package com.volmit.iris.gen.v2.scaffold.hunk; -import java.util.function.Consumer; +import java.util.function.Predicate; +import org.bukkit.Chunk; import org.bukkit.block.Biome; import org.bukkit.block.data.BlockData; import org.bukkit.generator.ChunkGenerator.BiomeGrid; @@ -43,6 +44,16 @@ public interface Hunk return new ChunkDataHunkView(src); } + public static Hunk viewBlocks(Chunk src) + { + return new ChunkHunkView(src); + } + + public static Hunk viewBiomes(Chunk src) + { + return new ChunkBiomeHunkView(src); + } + public static Hunk newHunk(int w, int h, int d) { return newArrayHunk(w, h, d); @@ -166,57 +177,248 @@ public interface Hunk return b; } - default Hunk iterate(Consumer3 c) + default Hunk invertY() { - for(int i = 0; i < getWidth(); i++) + return new InvertedHunkView(this); + } + + default Hunk rotateX(double degrees) + { + return new RotatedXHunkView(this, degrees); + } + + default Hunk rotateY(double degrees) + { + return new RotatedYHunkView(this, degrees); + } + + default Hunk rotateZ(double degrees) + { + return new RotatedZHunkView(this, degrees); + } + + default int getMaximumDimension() + { + return Math.max(getWidth(), Math.max(getHeight(), getDepth())); + } + + default int getIdeal2DParallelism() + { + return getMax2DParallelism() / 2; + } + + default int getIdeal3DParallelism() + { + return getMax3DParallelism() / 2; + } + + default int getMinimumDimension() + { + return Math.min(getWidth(), Math.min(getHeight(), getDepth())); + } + + default int getMax2DParallelism() + { + return (int) Math.pow(getMinimumDimension() / 2, 2); + } + + default int getMax3DParallelism() + { + return (int) Math.pow(getMinimumDimension() / 2, 3); + } + + default int filterDimension(int dim) + { + if(dim <= 1) { - for(int j = 0; j < getWidth(); j++) + return 1; + } + + dim = dim % 2 != 0 ? dim + 1 : dim; + + if(dim > getMinimumDimension() / 2) + { + if(dim <= 2) { - for(int k = 0; k < getWidth(); k++) + return 1; + } + + dim -= 2; + } + + return dim; + } + + default int get2DDimension(int sections) + { + if(sections <= 1) + { + return 1; + } + + return filterDimension((int) Math.ceil(Math.sqrt(sections))); + } + + default int get3DDimension(int sections) + { + if(sections <= 1) + { + return 1; + } + + return filterDimension((int) Math.ceil(Math.cbrt(sections))); + } + + default Hunk iterateSurfaces2D(Predicate p, Consumer4 c) + { + return iterateSurfaces2D(getIdeal2DParallelism(), p, c); + } + + default Hunk iterateSurfaces2D(int parallelism, Predicate p, Consumer4 c) + { + iterate2DTop(parallelism, (x, z) -> + { + int in = getHeight() - 1; + boolean hitting = false; + for(int i = getHeight() - 1; i >= 0; i--) + { + boolean solid = p.test(get(x, i, z)); + + if(!hitting && solid) { - c.accept(i, j, k); + in = i; + hitting = true; + } + + else if(hitting && !solid) + { + hitting = false; + c.accept(x, z, in, i - 1); } } - } + }); + + return this; + } + + default Hunk iterate2DTop(Consumer2 c) + { + return iterate2DTop(getIdeal2DParallelism(), c); + } + + default Hunk iterate2DTop(int parallelism, Consumer2 c) + { + compute2D(parallelism, (x, y, z, h) -> + { + for(int i = 0; i < h.getWidth(); i++) + { + for(int k = 0; k < h.getDepth(); k++) + { + c.accept(i + x, k + z); + } + } + }); + + return this; + } + + default Hunk iterate(Predicate p, Consumer3 c) + { + return iterate(getIdeal3DParallelism(), p, c); + } + + default Hunk iterate(int parallelism, Predicate p, Consumer3 c) + { + iterate(parallelism, (x, y, z, t) -> + { + if(p.test(t)) + { + c.accept(x, y, z); + } + }); + + return this; + } + + default Hunk iterate(Predicate p, Consumer4 c) + { + return iterate(getIdeal3DParallelism(), p, c); + } + + default Hunk iterate(int parallelism, Predicate p, Consumer4 c) + { + iterate(parallelism, (x, y, z, t) -> + { + if(p.test(t)) + { + c.accept(x, y, z, t); + } + }); + + return this; + } + + default Hunk iterate(Consumer3 c) + { + return iterate(getIdeal3DParallelism(), c); + } + + default Hunk iterate(int parallelism, Consumer3 c) + { + compute3D(parallelism, (x, y, z, h) -> + { + for(int i = 0; i < h.getWidth(); i++) + { + for(int j = 0; j < h.getHeight(); j++) + { + for(int k = 0; k < h.getDepth(); k++) + { + c.accept(i + x, j + y, k + z); + } + } + } + }); return this; } default Hunk iterate(Consumer4 c) { - for(int i = 0; i < getWidth(); i++) + return iterate(getIdeal3DParallelism(), c); + } + + default Hunk iterate(int parallelism, Consumer4 c) + { + compute3D(parallelism, (x, y, z, h) -> { - for(int j = 0; j < getWidth(); j++) + for(int i = 0; i < h.getWidth(); i++) { - for(int k = 0; k < getWidth(); k++) + for(int j = 0; j < h.getHeight(); j++) { - c.accept(i, j, k, get(i, j, k)); + for(int k = 0; k < h.getDepth(); k++) + { + c.accept(i + x, j + y, k + z, h.get(i, j, k)); + } } } - } + }); return this; } - default Hunk compute3D(int parallelism, Consumer4> v) + default Hunk compute2D(Consumer4> v) { - BurstExecutor e = MultiBurst.burst.burst(parallelism); - KList rq = new KList(parallelism); - getSections3D(parallelism, (xx, yy, zz, h, r) -> e.queue(() -> - { - v.accept(xx, yy, zz, h); - synchronized(rq) - { - rq.add(r); - } - }), (xx, yy, zz, c) -> insert(xx, yy, zz, c)); - e.complete(); - rq.forEach(Runnable::run); - return this; + return compute2D(getIdeal2DParallelism(), v); } default Hunk compute2D(int parallelism, Consumer4> v) { + if(get2DDimension(parallelism) == 1) + { + v.accept(0, 0, 0, this); + return this; + } + BurstExecutor e = MultiBurst.burst.burst(parallelism); KList rq = new KList(parallelism); getSections2D(parallelism, (xx, yy, zz, h, r) -> e.queue(() -> @@ -232,21 +434,29 @@ public interface Hunk return this; } - default Hunk compute2DAtomically(int parallelism, Consumer4> v) + default Hunk compute3D(Consumer4> v) { - BurstExecutor e = MultiBurst.burst.burst(parallelism); - KList rq = new KList(parallelism); - getAtomicSections2D(parallelism, (xx, yy, zz, h) -> e.queue(() -> v.accept(xx, yy, zz, h))); - e.complete(); - rq.forEach(Runnable::run); - return this; + return compute3D(getIdeal3DParallelism(), v); } - default Hunk compute3DAtomically(int parallelism, Consumer4> v) + default Hunk compute3D(int parallelism, Consumer4> v) { + if(get3DDimension(parallelism) == 1) + { + v.accept(0, 0, 0, this); + return this; + } + BurstExecutor e = MultiBurst.burst.burst(parallelism); KList rq = new KList(parallelism); - getAtomicSections3D(parallelism, (xx, yy, zz, h) -> e.queue(() -> v.accept(xx, yy, zz, h))); + getSections3D(parallelism, (xx, yy, zz, h, r) -> e.queue(() -> + { + v.accept(xx, yy, zz, h); + synchronized(rq) + { + rq.add(r); + } + }), (xx, yy, zz, c) -> insert(xx, yy, zz, c)); e.complete(); rq.forEach(Runnable::run); return this; @@ -259,9 +469,14 @@ public interface Hunk default Hunk getSections2D(int sections, Consumer5, Runnable> v, Consumer4> inserter) { - int dim = (int) Math.ceil(Math.sqrt(sections)); - dim = dim < 2 ? 2 : dim; - dim = dim % 2 != 0 ? dim + 1 : dim; + int dim = (int) get2DDimension(sections); + + if(sections <= 1) + { + getSection(0, 0, 0, getWidth(), getHeight(), getDepth(), (hh, r) -> v.accept(0, 0, 0, hh, r), inserter); + return this; + } + int w = getWidth() / dim; int d = getDepth() / dim; int i, j; @@ -280,29 +495,6 @@ public interface Hunk return this; } - default Hunk getAtomicSections2D(int sections, Consumer4> v) - { - int dim = (int) Math.ceil(Math.sqrt(sections)); - dim = dim < 2 ? 2 : dim; - dim = dim % 2 != 0 ? dim + 1 : dim; - int w = getWidth() / dim; - int d = getDepth() / dim; - int i, j; - - for(i = 0; i < getWidth(); i += w) - { - int ii = i; - - for(j = 0; j < getDepth(); j += d) - { - int jj = j; - getAtomicSection(i, 0, j, i + w, getHeight(), j + d, (h) -> v.accept(ii, 0, jj, h)); - } - } - - return this; - } - default Hunk getSections3D(int sections, Consumer5, Runnable> v) { return getSections3D(sections, v, (xx, yy, zz, c) -> insert(xx, yy, zz, c)); @@ -310,9 +502,14 @@ public interface Hunk default Hunk getSections3D(int sections, Consumer5, Runnable> v, Consumer4> inserter) { - int dim = (int) Math.ceil(Math.cbrt(sections)); - dim = dim < 2 ? 2 : dim; - dim = dim % 2 != 0 ? dim + 1 : dim; + int dim = (int) get3DDimension(sections); + + if(sections <= 1) + { + getSection(0, 0, 0, getWidth(), getHeight(), getDepth(), (hh, r) -> v.accept(0, 0, 0, hh, r), inserter); + return this; + } + int w = getWidth() / dim; int h = getHeight() / dim; int d = getDepth() / dim; @@ -337,35 +534,6 @@ public interface Hunk return this; } - default Hunk getAtomicSections3D(int sections, Consumer4> v) - { - int dim = (int) Math.ceil(Math.cbrt(sections)); - dim = dim < 2 ? 2 : dim; - dim = dim % 2 != 0 ? dim + 1 : dim; - int w = getWidth() / dim; - int h = getHeight() / dim; - int d = getDepth() / dim; - int i, j, k; - - for(i = 0; i < getWidth(); i += w) - { - int ii = i; - - for(j = 0; j < getHeight(); j += d) - { - int jj = j; - - for(k = 0; k < getDepth(); k += d) - { - int kk = k; - getAtomicSection(i, j, k, i + w, j + h, k + d, (hh) -> v.accept(ii, jj, kk, hh)); - } - } - } - - return this; - } - default Hunk getSection(int x, int y, int z, int x1, int y1, int z1, Consumer2, Runnable> v) { return getSection(x, y, z, x1, y1, z1, v, (xx, yy, zz, c) -> insert(xx, yy, zz, c)); @@ -378,12 +546,6 @@ public interface Hunk return this; } - default Hunk getAtomicSection(int x, int y, int z, int x1, int y1, int z1, Consumer> v) - { - v.accept(croppedView(x, y, z, x1, y1, z1)); - return this; - } - default void enforceBounds(int x, int y, int z) { if(x < 0 || x >= getWidth() || y < 0 || y >= getHeight() || z < 0 || z >= getDepth()) @@ -608,6 +770,31 @@ public interface Hunk setRaw(x, y, z, t); } + default void setIfExists(int x, int y, int z, T t) + { + if(x < 0 || x >= getWidth() || y < 0 || y >= getHeight() || z < 0 || z >= getDepth()) + { + return; + } + + setRaw(x, y, z, t); + } + + default T getIfExists(int x, int y, int z, T t) + { + if(x < 0 || x >= getWidth() || y < 0 || y >= getHeight() || z < 0 || z >= getDepth()) + { + return t; + } + + return getOr(x, y, z, t); + } + + default T getIfExists(int x, int y, int z) + { + return getIfExists(x, y, z, null); + } + /** * Set a value at the given position without checking coordinate bounds * @@ -652,6 +839,19 @@ public interface Hunk return getRaw(x, y, z); } + default T getOr(int x, int y, int z, T t) + { + enforceBounds(x, y, z); + T v = getRaw(x, y, z); + + if(v == null) + { + return t; + } + + return v; + } + /** * Insert a hunk into this one with an offset the inserted hunk * diff --git a/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/InvertedHunkView.java b/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/InvertedHunkView.java new file mode 100644 index 000000000..c85352e72 --- /dev/null +++ b/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/InvertedHunkView.java @@ -0,0 +1,47 @@ +package com.volmit.iris.gen.v2.scaffold.hunk; + +public class InvertedHunkView implements Hunk +{ + private final Hunk src; + + public InvertedHunkView(Hunk src) + { + this.src = src; + } + + @Override + public void setRaw(int x, int y, int z, T t) + { + src.setRaw(x, getHeight() - y, z, t); + } + + @Override + public T getRaw(int x, int y, int z) + { + return src.getRaw(x, getHeight() - y, z); + } + + @Override + public int getWidth() + { + return src.getWidth(); + } + + @Override + public int getDepth() + { + return src.getDepth(); + } + + @Override + public int getHeight() + { + return src.getHeight(); + } + + @Override + public Hunk getSource() + { + return src; + } +} diff --git a/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/RotatedXHunkView.java b/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/RotatedXHunkView.java new file mode 100644 index 000000000..f4ec0bee1 --- /dev/null +++ b/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/RotatedXHunkView.java @@ -0,0 +1,61 @@ +package com.volmit.iris.gen.v2.scaffold.hunk; + +public class RotatedXHunkView implements Hunk +{ + private final Hunk src; + private final double sin; + private final double cos; + + public RotatedXHunkView(Hunk src, double deg) + { + this.src = src; + this.sin = Math.sin(Math.toRadians(deg)); + this.cos = Math.cos(Math.toRadians(deg)); + } + + @Override + public void setRaw(int x, int y, int z, T t) + { + int yc = (int) Math.round(cos * (getHeight() / 2) - sin * (getDepth() / 2)); + int zc = (int) Math.round(sin * (getHeight() / 2) + cos * (getDepth() / 2)); + src.setIfExists(x, + (int) Math.round(cos * (y-yc) - sin * (z-zc))-yc, + (int) Math.round(sin * y-yc + cos * (z-zc))-zc, + t); + } + + @Override + public T getRaw(int x, int y, int z) + { + int yc = (int) Math.round(cos * (getHeight() / 2) - sin * (getDepth() / 2)); + int zc = (int) Math.round(sin * (getHeight() / 2) + cos * (getDepth() / 2)); + return src.getIfExists(x, + (int) Math.round(cos * (y-yc) - sin * (z-zc))-yc, + (int) Math.round(sin * y-yc + cos * (z-zc))-zc + ); + } + + @Override + public int getWidth() + { + return src.getWidth(); + } + + @Override + public int getDepth() + { + return src.getDepth(); + } + + @Override + public int getHeight() + { + return src.getHeight(); + } + + @Override + public Hunk getSource() + { + return src; + } +} diff --git a/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/RotatedYHunkView.java b/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/RotatedYHunkView.java new file mode 100644 index 000000000..30791f677 --- /dev/null +++ b/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/RotatedYHunkView.java @@ -0,0 +1,62 @@ +package com.volmit.iris.gen.v2.scaffold.hunk; + +public class RotatedYHunkView implements Hunk +{ + private final Hunk src; + private final double sin; + private final double cos; + + public RotatedYHunkView(Hunk src, double deg) + { + this.src = src; + this.sin = Math.sin(Math.toRadians(deg)); + this.cos = Math.cos(Math.toRadians(deg)); + } + + @Override + public void setRaw(int x, int y, int z, T t) + { + int xc = (int) Math.round(cos * (getWidth() / 2) + sin * (getDepth() / 2)); + int zc = (int) Math.round(-sin * (getWidth() / 2) + cos * (getDepth() / 2)); + src.setIfExists((int) + Math.round(cos * (x - xc) + sin * (z - zc)) - xc, + y, + (int) Math.round(-sin * (x - xc) + cos * (z - zc)) - zc, t); + } + + @Override + public T getRaw(int x, int y, int z) + { + int xc = (int) Math.round(cos * (getWidth() / 2) + sin * (getDepth() / 2)); + int zc = (int) Math.round(-sin * (getWidth() / 2) + cos * (getDepth() / 2)); + return src.getIfExists( + (int) Math.round(cos * (x - xc) + sin * (z - zc)) - xc, + y, + (int) Math.round(-sin * (x - xc) + cos * (z - zc)) - zc + ); + } + + @Override + public int getWidth() + { + return src.getWidth(); + } + + @Override + public int getDepth() + { + return src.getDepth(); + } + + @Override + public int getHeight() + { + return src.getHeight(); + } + + @Override + public Hunk getSource() + { + return src; + } +} diff --git a/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/RotatedZHunkView.java b/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/RotatedZHunkView.java new file mode 100644 index 000000000..2ac02883b --- /dev/null +++ b/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/RotatedZHunkView.java @@ -0,0 +1,57 @@ +package com.volmit.iris.gen.v2.scaffold.hunk; + +public class RotatedZHunkView implements Hunk +{ + private final Hunk src; + private final double sin; + private final double cos; + + public RotatedZHunkView(Hunk src, double deg) + { + this.src = src; + this.sin = Math.sin(Math.toRadians(deg)); + this.cos = Math.cos(Math.toRadians(deg)); + } + + @Override + public void setRaw(int x, int y, int z, T t) + { + int xc = (int) Math.round(cos * (getWidth() / 2) - sin * (getHeight() / 2)); + int yc = (int) Math.round(sin * (getWidth() / 2) + cos * (getHeight() / 2)); + src.setIfExists((int) Math.round(cos * (x - xc) - sin * (y - yc)) - xc, (int) Math.round(sin * (x - xc) + cos * (y - yc)) - yc, z, t); + } + + @Override + public T getRaw(int x, int y, int z) + { + int xc = (int) Math.round(cos * (getWidth() / 2) - sin * (getHeight() / 2)); + int yc = (int) Math.round(sin * (getWidth() / 2) + cos * (getHeight() / 2)); + return src.getIfExists((int) Math.round(cos * (x - xc) - sin * (y - yc)) - xc, + (int) Math.round(sin * (x - xc) + cos * (y - yc)) - yc + , z); + } + + @Override + public int getWidth() + { + return src.getWidth(); + } + + @Override + public int getDepth() + { + return src.getDepth(); + } + + @Override + public int getHeight() + { + return src.getHeight(); + } + + @Override + public Hunk getSource() + { + return src; + } +}