Метод JavaFX Canvas fillPolygon не создает гладкую поверхность (видны линии сетки)

#java #javafx #java-8 #3d #polygon

Вопрос:

Я хочу нарисовать сетчатую сетку 3d-поверхности. Поверхность может — в зависимости от выбранного разрешения — состоять из тысяч полигонов, расположенных рядом друг с другом.

При низком разрешении результат выглядит нормально. При более высоком разрешении линии сетки сетки либо хорошо видны, либо образуют этот странный эффект полос зебры (см. Изображение). Я хотел бы иметь гладкую поверхность — как мне этого добиться?

введите описание изображения здесь

Я использую java fx, java 1.8 на компьютере с Windows 10. Сглаживание активно.

минимальный пример:

 import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.DepthTest;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

import static javafx.scene.SceneAntialiasing.BALANCED;

public class MeshGridTest extends Application {


    @Override
    public void start(Stage primaryStage) throws Exception {
        try {

            primaryStage.setTitle("3D test");
            VBox root = new VBox();
            root.setDepthTest(DepthTest.ENABLE);
            root.setSpacing(10);
            HBox graphBox = new HBox();
            graphBox.setSpacing(10);
            graphBox.setPadding(new Insets(20, 20, 20, 20));
            root.getChildren().add(graphBox);
                        double canvasWidth = 500;
            double canvasHeight = 500;
            Canvas canvas = new Canvas(canvasWidth, canvasHeight);
            GraphicsContext context = canvas.getGraphicsContext2D();
            graphBox.getChildren().add(canvas);
            context.setFill(Color.web("0x4683b4ff"));
            context.fillPolygon(new double[]{79.38458612953876, 115.1333465737948, 124.35915222707138, 90.07817382229237}, new double[]{453.7674972431933, 453.62365127662974, 425.38481745205695, 425.3658453584012}, 4);
            context.setFill(Color.web("0x4685b5ff"));
            context.fillPolygon(new double[]{90.07817382229237, 124.35915222707138, 132.7123083001136, 99.6559534108369}, new double[]{425.3658453584012, 425.38481745205695, 399.1086555987629, 398.6272838484313}, 4);
            context.setFill(Color.web("0x458cb7ff"));
            context.fillPolygon(new double[]{99.6559534108369, 132.7123083001136, 139.89481376635175, 108.21467522318329}, new double[]{398.6272838484313, 399.1086555987629, 373.0866916804024, 373.0987504772544}, 4);
            context.setFill(Color.web("0x449bbbff"));
            context.fillPolygon(new double[]{108.21467522318329, 139.89481376635175, 145.98680660267343, 116.07375278278231}, new double[]{373.0987504772544, 373.0866916804024, 346.7109974406283, 349.12352586863017}, 4);
            context.setFill(Color.web("0x43afc2ff"));
            context.fillPolygon(new double[]{116.07375278278231, 145.98680660267343, 151.48043135860547, 123.13660694768703}, new double[]{349.12352586863017, 346.7109974406283, 321.0970002825233, 325.9076627857052}, 4);
            context.setFill(Color.web("0x41cccaff"));
            context.fillPolygon(new double[]{123.13660694768703, 151.48043135860547, 156.24933314601532, 129.30559799734607}, new double[]{325.9076627857052, 321.0970002825233, 295.24566224164175, 302.56790228993924}, 4);
            context.setFill(Color.web("0x65e6a8ff"));
            context.fillPolygon(new double[]{129.30559799734607, 156.24933314601532, 160.48424463177454, 134.57141212068763}, new double[]{302.56790228993924, 295.24566224164175, 269.4538308385731, 278.4751392714206}, 4);
            context.setFill(Color.web("0xbef547ff"));
            context.fillPolygon(new double[]{134.57141212068763, 160.48424463177454, 164.75351382381356, 139.19371903623178}, new double[]{278.4751392714206, 269.4538308385731, 246.0112935309454, 254.08862228739235}, 4);
            context.setFill(Color.web("0xfcec05ff"));
            context.fillPolygon(new double[]{139.19371903623178, 164.75351382381356, 169.36621372437594, 143.79263195686968}, new double[]{254.08862228739235, 246.0112935309454, 226.49445381500652, 231.64655982045508}, 4);
            context.setFill(Color.web("0xf2a916ff"));
            context.fillPolygon(new double[]{143.79263195686968, 169.36621372437594, 174.16498122336426, 148.7643186047649}, new double[]{231.64655982045508, 226.49445381500652, 210.33952100887984, 212.92380031415433}, 4);
            context.setFill(Color.web("0xed851fff"));
            context.fillPolygon(new double[]{148.7643186047649, 174.16498122336426, 178.94141300708233, 153.97544571540766}, new double[]{212.92380031415433, 210.33952100887984, 196.5379776965533, 197.53566928262848}, 4);
            context.setFill(Color.web("0xeb7922ff"));
            context.fillPolygon(new double[]{153.97544571540766, 178.94141300708233, 183.60324212961166, 159.19501673676973}, new double[]{197.53566928262848, 196.5379776965533, 184.53843497120874, 184.49494238828652}, 4);
            context.setFill(Color.web("0xec7d21ff"));
            context.fillPolygon(new double[]{159.19501673676973, 183.60324212961166, 188.1222449453474, 164.31197932847522}, new double[]{184.49494238828652, 184.53843497120874, 174.0815042668034, 173.23165438552195}, 4);
            context.setFill(Color.web("0x4685b5ff"));
            context.fillPolygon(new double[]{115.1333465737948, 150.71187770617652, 158.54986477004223, 124.35915222707138}, new double[]{453.62365127662974, 452.87242944863726, 425.09186653322604, 425.38481745205695}, 4);
            context.setFill(Color.web("0x4684b5ff"));
            context.fillPolygon(new double[]{124.35915222707138, 158.54986477004223, 165.60012074939144, 132.7123083001136}, new double[]{425.38481745205695, 425.09186653322604, 399.13379390423444, 399.1086555987629}, 4);
            context.setFill(Color.web("0x4689b6ff"));
            context.fillPolygon(new double[]{132.7123083001136, 165.60012074939144, 171.83179206641202, 139.89481376635175}, new double[]{399.1086555987629, 399.13379390423444, 374.1380223021333, 373.0866916804024}, 4);
            context.setFill(Color.web("0x449ebcff"));
            context.fillPolygon(new double[]{139.89481376635175, 171.83179206641202, 176.37561763303003, 145.98680660267343}, new double[]{373.0866916804024, 374.1380223021333, 345.4595014888617, 346.7109974406283}, 4);
            context.setFill(Color.web("0x42c6c8ff"));
            context.fillPolygon(new double[]{145.98680660267343, 176.37561763303003, 179.8481291080601, 151.48043135860547}, new double[]{346.7109974406283, 345.4595014888617, 314.4761503856426, 321.0970002825233}, 4);
            context.setFill(Color.web("0x69e7a3ff"));
            context.fillPolygon(new double[]{151.48043135860547, 179.8481291080601, 183.43079510430246, 156.24933314601532}, new double[]{321.0970002825233, 314.4761503856426, 286.2041149914594, 295.24566224164175}, 4);
            context.setFill(Color.web("0xc7f63dff"));
            context.fillPolygon(new double[]{156.24933314601532, 183.43079510430246, 187.26474778731273, 160.48424463177454}, new double[]{295.24566224164175, 286.2041149914594, 261.5075468958896, 269.4538308385731}, 4);
            context.setFill(Color.web("0xfbe307ff"));
            context.fillPolygon(new double[]{160.48424463177454, 187.26474778731273, 191.429026916089, 164.75351382381356}, new double[]{269.4538308385731, 261.5075468958896, 241.07103437098476, 246.0112935309454}, 4);
            context.setFill(Color.web("0xf1a218ff"));
            context.fillPolygon(new double[]{164.75351382381356, 191.429026916089, 195.73191191102035, 169.36621372437594}, new double[]{246.0112935309454, 241.07103437098476, 224.04785133565588, 226.49445381500652}, 4);
            context.setFill(Color.web("0xec8120ff"));
            context.fillPolygon(new double[]{169.36621372437594, 195.73191191102035, 199.9890645613384, 174.16498122336426}, new double[]{226.49445381500652, 224.04785133565588, 209.4004803784452, 210.33952100887984}, 4);
            context.setFill(Color.web("0xea7523ff"));
            context.fillPolygon(new double[]{174.16498122336426, 199.9890645613384, 204.12598154456248, 178.94141300708233}, new double[]{210.33952100887984, 209.4004803784452, 196.5919823216396, 196.5379776965533}, 4);
            context.setFill(Color.web("0xeb7922ff"));
            context.fillPolygon(new double[]{178.94141300708233, 204.12598154456248, 208.12453341832259, 183.60324212961166}, new double[]{196.5379776965533, 196.5919823216396, 185.38471553938376, 184.53843497120874}, 4);
            context.setFill(Color.web("0xed891eff"));
            context.fillPolygon(new double[]{183.60324212961166, 208.12453341832259, 211.95491329506487, 188.1222449453474}, new double[]{184.53843497120874, 185.38471553938376, 175.43384846181, 174.0815042668034}, 4);
            context.setFill(Color.web("0x458bb7ff"));
            context.fillPolygon(new double[]{150.71187770617652, 186.20520457333257, 192.43693191487066, 158.54986477004223}, new double[]{452.87242944863726, 451.40158648950126, 423.30893247464667, 425.09186653322604}, 4);
            context.setFill(Color.web("0x4689b6ff"));
            context.fillPolygon(new double[]{158.54986477004223, 192.43693191487066, 198.3196325771089, 165.60012074939144}, new double[]{425.09186653322604, 423.30893247464667, 398.36168724188406, 399.13379390423444}, 4);
            context.setFill(Color.web("0x4689b6ff"));
            context.fillPolygon(new double[]{165.60012074939144, 198.3196325771089, 203.4713843577531, 171.83179206641202}, new double[]{399.13379390423444, 398.36168724188406, 374.16895900242207, 374.1380223021333}, 4);
            context.setFill(Color.web("0x449bbbff"));
            context.fillPolygon(new double[]{171.83179206641202, 203.4713843577531, 207.50759808149047, 176.37561763303003}, new double[]{374.1380223021333, 374.16895900242207, 347.73356292823, 345.4595014888617}, 4);
            context.setFill(Color.web("0x41d4cdff"));
            context.fillPolygon(new double[]{176.37561763303003, 207.50759808149047, 209.14942590283852, 179.8481291080601}, new double[]{345.4595014888617, 347.73356292823, 310.12132358101934, 314.4761503856426}, 4);
            context.setFill(Color.web("0xb8f44dff"));
            context.fillPolygon(new double[]{179.8481291080601, 209.14942590283852, 211.61998483284617, 183.43079510430246}, new double[]{314.4761503856426, 310.12132358101934, 279.05112718572633, 286.2041149914594}, 4);
            context.setFill(Color.web("0xfade08ff"));
            context.fillPolygon(new double[]{183.43079510430246, 211.61998483284617, 215.12094526034042, 187.26474778731273}, new double[]{286.2041149914594, 279.05112718572633, 256.8461541054689, 261.5075468958896}, 4);
            context.setFill(Color.web("0xf09c19ff"));
            context.fillPolygon(new double[]{187.26474778731273, 215.12094526034042, 218.8194681929901, 191.429026916089}, new double[]{261.5075468958896, 256.8461541054689, 238.761242536079, 241.07103437098476}, 4);
            context.setFill(Color.web("0xec7c21ff"));
            context.fillPolygon(new double[]{191.429026916089, 218.8194681929901, 222.4678741782185, 195.73191191102035}, new double[]{241.07103437098476, 238.761242536079, 223.16290234376424, 224.04785133565588}, 4);
            context.setFill(Color.web("0xea7124ff"));
            context.fillPolygon(new double[]{195.73191191102035, 222.4678741782185, 225.9990616732908, 199.9890645613384}, new double[]{224.04785133565588, 223.16290234376424, 209.46224715829078, 209.4004803784452}, 4);
            context.setFill(Color.web("0xea7523ff"));
            context.fillPolygon(new double[]{199.9890645613384, 225.9990616732908, 229.40196475309995, 204.12598154456248}, new double[]{209.4004803784452, 209.46224715829078, 197.4313445122899, 196.5919823216396}, 4);
            context.setFill(Color.web("0xed851fff"));
            context.fillPolygon(new double[]{204.12598154456248, 229.40196475309995, 232.65760583289082, 208.12453341832259}, new double[]{196.5919823216396, 197.4313445122899, 186.7564306066988, 185.38471553938376}, 4);

            primaryStage.setScene(new Scene(root, 500, 500, true, BALANCED));
            primaryStage.show();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
 

Ответ №1:

Есть два пути. Для низких разрешений вы должны немного перекрывать плитки. Для высоких разрешений вы можете изменить свой алгоритм и вычислить явные цвета пикселей вместо использования полигонов. Другим вариантом было бы использовать для этого треугольную сетку вместо холста.