2017-01-26 45 views
0

如何创建使用不同图像的立方体?在JavaFX中使用不同纹理创建立方体

我想选择使用用户输入动态使用的图像。

明显的解决办法是创建六个独立的矩形(这是不是可以表现更差明智?),但有利用现有Box功能(例如,类似于TextureCubeMap东西Java3D的)的方式?

到目前为止,所有我发现是解决使用一个图像作为纹理整个立方体(例如:this

回答

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 s为图谱和getImage返回一个延迟初始化Image表示整个区域的区域。

+0

干得好。这正是我回答你的问题时想到的。我应该明确地提到关键词“纹理地图集”:-)。 – mipa

1

你为什么不只是单独的图像复制到一个单一的一个?您甚至可以通过画布和快照在程序中执行此操作。

相关问题