如何为每一面创建一个使用不同图像的立方体?
我想使用用户的输入选择要动态使用的图像。
显而易见的解决方案是创建六个单独的矩形(这不是性能更差吗?),但是有一种方法可以利用现有的Box
功能(例如类似于{{3}的东西)在Java3D中)?
到目前为止,我发现只有使用一个图像作为整个立方体的纹理的解决方案(例如:TextureCubeMap
。)
答案 0 :(得分:2)
我最终编写了一个原始纹理图集类,使用WritableImage
组合图像。使用bin打包算法可能更有效,我目前正在阅读,但在我的特殊情况下,所有图像都是相同的宽度,这对我来说很好。它只是垂直放置图像。但是,它目前的结构应该可以轻松扩展到不同布局的地图集实施。
阿特拉斯:
public class TextureAtlas {
private final Image image;
private final Map<String, TextureRegion> regions;
public TextureAtlas(Image image) {
this.image = image;
regions = new HashMap<>();
}
/**
* Creates an extremely primitive texture atlas.
* Could use bin packing eventually.
*/
public TextureAtlas(Map<String, Image> images) {
this.regions = new HashMap<>();
int height = (int) Math.ceil(images.values().stream().mapToDouble(Image::getHeight).sum());
OptionalDouble w = images.values().stream().mapToDouble(Image::getWidth).max();
WritableImage i = new WritableImage(w.isPresent() ? (int) w.getAsDouble() : 0, height);
int h = 0;
PixelWriter writer = i.getPixelWriter();
for(Map.Entry<String, Image> entry : images.entrySet()) {
Image img = entry.getValue();
PixelReader reader = img.getPixelReader();
for(int x = 0; x < img.getWidth(); x++)
for(int y = 0; y < img.getHeight(); y++)
writer.setColor(x, y + h, reader.getColor(x, y));
createRegion(entry.getKey(), img, 0, h, (int) img.getWidth(), (int) img.getHeight());
h += img.getHeight();
} this.image = i;
}
public TextureRegion createRegion(String name, int x, int y, int width, int height) {
TextureRegion reg;
regions.put(name, reg = new TextureRegion(this, x, y, width, height));
return reg;
}
private TextureRegion createRegion(String name, Image image, int x, int y, int width, int height) {
TextureRegion reg;
regions.put(name, reg = new TextureRegion(this, x, y, width, height));
return reg;
}
public TextureRegion getRegion(String name) {
return regions.get(name);
}
public Map<String, TextureRegion> getRegions() {
return Collections.unmodifiableMap(regions);
}
public int getWidth() {
return (int) image.getWidth();
}
public int getHeight() {
return (int) image.getHeight();
}
public int getColorAt(int x, int y) {
if(x >= image.getWidth() || y >= image.getHeight()) return -1;
return image.getPixelReader().getArgb(x, y);
}
public Image getImage() {
return image;
}
}
纹理区域:
public class TextureRegion {
public final TextureAtlas atlas;
public final int x, y, width, height;
private Image image;
public TextureRegion(TextureAtlas atlas, int x, int y, int width, int height) {
this.atlas = atlas;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public TextureRegion(TextureAtlas atlas, Image image, int x, int y, int width, int height) {
this.atlas = atlas;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.image = image;
}
public int getColorAt(int x, int y) {
return atlas.getColorAt(this.x + x, this.y + y);
}
public double[] getTextureCoordinates(double x, double y) {
return new double[] {getU(x), getV(y)};
}
public double[] scaleTextureCoordinates(double u, double v, double max) {
return new double[] {scaleU(u, max), scaleV(v, max)};
}
public double getU(double x) {
return (this.x + x) / atlas.getWidth();
}
public double getV(double y) {
return (this.y + y) / atlas.getHeight();
}
public double scaleU(double u, double max) { //For conversion from UV systems using a different max value than 1.0
return getU(u / max * this.width);
}
public double scaleV(double v, double max) {
return getV(v / max * this.height);
}
public Image getImage() {
if(image != null) return image; //Lazily initialize
else {
WritableImage img = new WritableImage(width, height);
PixelWriter writer = img.getPixelWriter();
PixelReader reader = atlas.getImage().getPixelReader();
for(int x = 0; x < width; x++)
for(int y = 0; y < height; y++)
writer.setArgb(x, y, reader.getArgb(x + this.x, y + this.y));
return this.image = img;
}
}
}
TextureRegion
代表地图集的某个区域,getImage
返回一个代表整个地区的延迟初始化Image
。
答案 1 :(得分:1)
为什么不将单独的图像复制到一个图像中?您甚至可以通过画布和快照在程序中执行此操作。