java - 如何在 LWJGL 中将纹理正确映射到六边形?

标签 java opengl lwjgl

我有一个脚本,可以渲染六边形瓷砖的二维六边形网格。网格加载良好,但我的纹理缺少大量颜色。我的代码有什么问题吗?我是否错误地映射了坐标?

这是我正在加载的纹理图像: enter image description here

这就是纹理在我的游戏中的显示方式: enter image description here

这是我的代码:

public class LWJGLHelloWorld {

    public static int SCREEN_WIDTH;
    public static int SCREEN_HEIGHT;
    public static int WINDOW_WIDTH;
    public static int WINDOW_HEIGHT;
    public double WIDTH;
    public double HEIGHT;
    public ArrayList<Hexagon> hexagons = new ArrayList<Hexagon>();
    public ArrayList<String> resources = new ArrayList<String>();
    public Texture brick;
    public Texture stone;
    public Texture lumber;
    public Texture wool;
    public Texture wheat;
    public Texture wasteland;
    public int textureID;
    private float[][] textureCoords = { 
        {0.5f, 0.5f},
        {0.5f, 0.0f},
        {0.0f, 0.25f},
        {0.0f, 0.75f},
        {0.5f, 0.0f},
        {1.0f, 0.75f},
        {1.0f, 0.25f}
};
    private static enum State {
        INTRO, MAIN_MENU, GAME;
    }

    private State state = State.INTRO;

    public LWJGLHelloWorld(){

        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        double SCREEN_WIDTH = screenSize.getWidth();
        double SCREEN_HEIGHT = screenSize.getHeight();
        double WIDTH = SCREEN_WIDTH * .85;
        double HEIGHT = SCREEN_HEIGHT * .85;

        try {
            Display.setDisplayMode(new DisplayMode((int)WIDTH, (int)HEIGHT));
            Display.setTitle("Hello, LWJGL!");;
            Display.create();
        } catch (LWJGLException e){
            e.printStackTrace();
        }
        resetResources();


        brick = loadTexture("brick");
        stone = loadTexture("stone");
        lumber = loadTexture("lumber");
        //Texture wheat = loadTexture("wheat");
        wool = loadTexture("wool");
        wasteland = loadTexture("wasteland");

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0, WIDTH, HEIGHT, 0, 1, -1);
        glMatrixMode(GL_MODELVIEW);
        glEnable(GL_TEXTURE_2D);

        int originX = (int)(Display.getDisplayMode().getWidth() / 2);
        int originY = (int)(Display.getDisplayMode().getHeight() / 2);
        int radius = (int)(HEIGHT * .1);
        int padding = (int)(HEIGHT * .005);

        findHexCoords(originX, originY, 5, radius, padding);

        while(!Display.isCloseRequested()){
            checkInput();
            glClear(GL_COLOR_BUFFER_BIT);
            for(int h = 0; h < hexagons.size(); h++){
                String rsrc = resources.get(h);
                switch(rsrc){
                case "brick":
                    brick.bind();
                    break;
                case "stone":
                    stone.bind();
                    break;
                case "lumber":
                    lumber.bind();
                    break;
                case "wheat":
                    //wheat.bind();
                    break;
                case "wool":
                    wool.bind();
                    break;
                case "wasteland":
                    wasteland.bind();
                    break;  
                }
                glBegin(GL_POLYGON);
                Hexagon hex = hexagons.get(h);
                for(int p = 0; p < hex.points.length; p++){
                    Point point = hex.points[p];
                    glVertex2f(point.x, point.y);
                    glTexCoord2f(textureCoords[p][0], textureCoords[p][0]);
                    GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
                    GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
                }
                glEnd();
            }

            Display.update();
            Display.sync(60);
        }

        Display.destroy();
    }

    private void bindTexture(String rsrc){

    }

    private void findHexCoords(int x, int y, int size, int radius, int padding) {

        Point origin = new Point(x, y);
        double ang30 = Math.toRadians(30);
        double xOff = Math.cos(ang30) * (radius + padding);
        double yOff = Math.sin(ang30) * (radius + padding);
        int half = size / 2;

        int i = 0;
        for (int row = 0; row < size; row++) {

            int cols = size - Math.abs(row - half);

            for (int col = 0; col < cols; col++) {

                int xLbl = row < half ? col - row : col - half;
                int yLbl = row - half;
                int centerX = (int) (origin.x + xOff * (col * 2 + 1 - cols));
                int centerY = (int) (origin.y + yOff * (row - half) * 3);

                Hexagon hex = new Hexagon(centerX, centerY, radius);
                System.out.println(centerX+","+centerY);
                hexagons.add(hex);
                i++;
            }
        }
    }

    public void checkInput(){
        switch(state){
        case INTRO:
            if(Keyboard.isKeyDown(Keyboard.KEY_S)){
                state = State.MAIN_MENU;
            }
            if(Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)){
                Display.destroy();
                System.exit(0);;
            }
            break;
        case GAME:
            if(Keyboard.isKeyDown(Keyboard.KEY_BACK)){
                state = State.MAIN_MENU;
            }
            break;
        case MAIN_MENU:
            if(Keyboard.isKeyDown(Keyboard.KEY_RETURN)){
                state = State.GAME;
            }
            if(Keyboard.isKeyDown(Keyboard.KEY_SPACE)){
                state = State.INTRO;
            }
            break;
        }
    }

    private Texture loadTexture(String key){
        try {
            return TextureLoader.getTexture("PNG", new FileInputStream(new File("img/" + key + ".png")));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    public static void main(String[] args) {
        new LWJGLHelloWorld();

    }

    public void resetResources(){
        resources.clear();
        resources.add("Brick");
        resources.add("Brick");
        resources.add("Brick");
        resources.add("Wool");
        resources.add("Wool");
        resources.add("Wool");
        resources.add("Wool");
        resources.add("Lumber");
        resources.add("Lumber");
        resources.add("Lumber");
        resources.add("Lumber");
        resources.add("Stone");
        resources.add("Stone");
        resources.add("Stone");
        resources.add("Wheat");
        resources.add("Wheat");
        resources.add("Wheat");
        resources.add("Wheat");
        long seed = System.nanoTime();
        Collections.shuffle(resources, new Random(seed));
        int randomIndex = ThreadLocalRandom.current().nextInt(0, 19);
        resources.add(randomIndex, "Wasteland");
        for(int r = 0; r < resources.size(); r++){
            System.out.println(resources.get(r));
        }
    }

}

更新

我认为发生这种情况是因为我的纹理坐标不正确,因为每当我更改它们时,纹理中的黑色区域就会发生变化。

最佳答案

你的纹理坐标确实是错误的。由于您正在绘制一个整体多边形,因此没有任何纹理坐标为 [0.5, 0.5] 的顶点,该顶点是纹理的中心。

尝试使用下面的图像来正确确定纹理坐标。 :)

enter image description here

写下每个顶点的纹理坐标,并按照与绘制顶点相同的顺序放置它们。

编辑:

公平地说,您最好将这些图 block 绘制为矩形/四边形并使它们稍微重叠。假设您从左下角开始并顺时针绘制,那么您的纹理坐标将是 {[0, 0], [0, 1], [1, 1], [1, 0]} 。参见下图。

enter image description here

关于java - 如何在 LWJGL 中将纹理正确映射到六边形?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42413595/

相关文章:

java lwjgl 设置鼠标位置而不更改 dx 或 dy

java - OpenGL (LWJGL) - 获取纹理的像素颜色

java - 如何在不模糊图像的情况下制作小纹理比例?喜欢我的世界?

java - 为什么 java 编译器不显示明显除以零的警告?

java - 从结果集中提取时出错

java - Android 线程、锁、并发示例

c++ - 使用影响 TEXTURE_2D 的 TEXTURE_RECTANGLE_ARB

c++ - 什么时候绑定(bind)到 VAO?

opengl - OpenGL 二次色有什么用处?

java - 使用 1.7 需要使用 Android 4.4 (KitKat) 编译;当前使用 API 14