Advertisement
Guest User

Untitled

a guest
Aug 3rd, 2022
154
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 40.17 KB | None | 0 0
  1. import javafx.application.Application;
  2. import javafx.scene.*;
  3. import javafx.scene.image.WritableImage;
  4. import javafx.scene.layout.AnchorPane;
  5. import javafx.scene.paint.Color;
  6. import javafx.scene.paint.PhongMaterial;
  7. import javafx.scene.shape.*;
  8. import javafx.scene.transform.Rotate;
  9. import javafx.scene.transform.Scale;
  10. import javafx.scene.transform.Translate;
  11. import javafx.stage.Stage;
  12.  
  13. import java.util.*;
  14. import java.util.stream.IntStream;
  15.  
  16. /**
  17.  * To run this, create a new class (e.g. RunTriangleMeshTransparency), create a main method and add this line:
  18.  * Application.launch(TriangleMeshTransparency.class);
  19.  * then run that class
  20.  */
  21. public class TriangleMeshTransparency extends Application {
  22.  
  23.     private static final int WIDTH = 800;
  24.     private static final int HEIGHT = 600;
  25.  
  26.     private AnchorPane modelPane;
  27.  
  28.     private Group scene;
  29.     private SubScene subScene;
  30.     private final float MODEL_SCALE = 0.03f;
  31.     private RSTriangleMeshView meshView;
  32.  
  33.     @Override
  34.     public void start(Stage primaryStage) throws Exception {
  35.  
  36.         modelPane = new AnchorPane();
  37.         modelPane.setPrefWidth(WIDTH);
  38.         modelPane.setPrefHeight(HEIGHT);
  39.         initScene();
  40.  
  41.         // data for the same mesh i used as an example in my question
  42. // write palette
  43.         /*try {
  44.             ImageIO.write(SwingFXUtils.fromFXImage(atlas, null), "png", new File("./palette.png"));
  45.         } catch (IOException e) {
  46.             e.printStackTrace();
  47.         }*/
  48.  
  49.         int idx = 0;
  50.         for (int i = 0; i < model.triangleCount; i++) {
  51.  
  52.             int faceA = model.faceIndicesA[i];
  53.             int faceB = model.faceIndicesB[i];
  54.             int faceC = model.faceIndicesC[i];
  55.             int vertexIndex1 = mesh.addVertex(faceA, model.verticesXCoordinate[faceA], model.verticesYCoordinate[faceA], model.verticesZCoordinate[faceA]);
  56.             int vertexIndex2 = mesh.addVertex(faceB, model.verticesXCoordinate[faceB], model.verticesYCoordinate[faceB], model.verticesZCoordinate[faceB]);
  57.             int vertexIndex3 = mesh.addVertex(faceC, model.verticesXCoordinate[faceC], model.verticesYCoordinate[faceC], model.verticesZCoordinate[faceC]);
  58.  
  59.             float u = (idx % width + 0.5f) / width;
  60.             float v = (idx / width + 0.5f) / (float) atlas.getHeight();
  61.  
  62.             int texIndex1 = mesh.addUV(u, v);
  63.             int texIndex2 = mesh.addUV(u, v);
  64.             int texIndex3 = mesh.addUV(u, v);
  65.  
  66.             mesh.getFaces().addAll(
  67.                     vertexIndex1, texIndex1,
  68.                     vertexIndex2, texIndex2,
  69.                     vertexIndex3, texIndex3
  70.             );
  71.             idx++;
  72.         }
  73.  
  74.         RSTriangleMeshView view = new RSTriangleMeshView(mesh);
  75.         PhongMaterial mat = new PhongMaterial();
  76.         mat.setDiffuseMap(atlas);
  77.  
  78.         view.setMaterial(mat);
  79.         view.getTransforms().add(new Scale(MODEL_SCALE, MODEL_SCALE, MODEL_SCALE));
  80.         view.setDepthTest(DepthTest.ENABLE);
  81.         view.setCullFace(CullFace.BACK);
  82.         meshView = view;
  83.     }
  84.  
  85.     private void initScene() {
  86.         scene = new Group();
  87.         //Group grid = new Grid3D().create(48f, 1.25f);
  88.         //scene.getChildren().add(grid);
  89.         subScene = createScene3D();
  90.         scene.getChildren().add(new AmbientLight(Color.WHITE));
  91.         modelPane.getChildren().addAll(subScene);
  92.     }
  93.  
  94.     private SubScene createScene3D() {
  95.         SubScene scene3d = new SubScene(scene, modelPane.getPrefWidth(), modelPane.getPrefHeight(), true, SceneAntialiasing.BALANCED);
  96.         scene3d.setFill(Color.rgb(25, 25, 25));
  97.         new OrbitCamera(scene3d, scene);
  98.         return scene3d;
  99.     }
  100.  
  101.     /*
  102.      * Orbit camera
  103.      */
  104.  
  105.     private static class OrbitCamera {
  106.  
  107.         private final SubScene subScene;
  108.         private final Group root3D;
  109.  
  110.         private final double MAX_ZOOM = 300.0;
  111.  
  112.         public OrbitCamera(SubScene subScene, Group root) {
  113.             this.subScene = subScene;
  114.             this.root3D = root;
  115.             init();
  116.         }
  117.  
  118.         private void init() {
  119.             camera.setNearClip(0.1D);
  120.             camera.setFarClip(MAX_ZOOM * 1.15D);
  121.             camera.getTransforms().addAll(
  122.                     yUpRotate,
  123.                     cameraPosition,
  124.                     cameraLookXRotate,
  125.                     cameraLookZRotate
  126.             );
  127.  
  128.             Group rotateGroup = new Group();
  129.             try {
  130.                 rotateGroup.getChildren().addAll(cameraXform);
  131.             } catch (Exception e) {
  132.                 e.printStackTrace();
  133.             }
  134.             cameraXform.ry.setAngle(0);
  135.             cameraXform.rx.setAngle(-18);
  136.             cameraXform.getChildren().add(cameraXform2);
  137.             cameraXform2.getChildren().add(cameraXform3);
  138.             cameraXform3.getChildren().add(camera);
  139.             cameraPosition.setZ(-cameraDistance);
  140.  
  141.             root3D.getChildren().addAll(rotateGroup);
  142.  
  143.             subScene.setCamera(camera);
  144.             subScene.setOnScroll(event -> {
  145.  
  146.                 double zoomFactor = 1.05;
  147.                 double deltaY = event.getDeltaY();
  148.  
  149.                 if (deltaY < 0) {
  150.                     zoomFactor = 2.0 - zoomFactor;
  151.                 }
  152.                 double z = cameraPosition.getZ() / zoomFactor;
  153.                 z = Math.max(z, -MAX_ZOOM);
  154.                 z = Math.min(z, 10.0);
  155.                 cameraPosition.setZ(z);
  156.             });
  157.  
  158.             subScene.setOnMousePressed(event -> {
  159.                 if (!event.isAltDown()) {
  160.                     dragStartX = event.getSceneX();
  161.                     dragStartY = event.getSceneY();
  162.                     dragStartRotateX = cameraXRotate.getAngle();
  163.                     dragStartRotateY = cameraYRotate.getAngle();
  164.                     mousePosX = event.getSceneX();
  165.                     mousePosY = event.getSceneY();
  166.                     mouseOldX = event.getSceneX();
  167.                     mouseOldY = event.getSceneY();
  168.                 }
  169.             });
  170.  
  171.             subScene.setOnMouseDragged(event -> {
  172.                 if (!event.isAltDown()) {
  173.                     double modifier = 1.0;
  174.                     double modifierFactor = 0.3;
  175.  
  176.                     if (event.isControlDown()) modifier = 0.1;
  177.                     if (event.isSecondaryButtonDown()) modifier = 0.035;
  178.  
  179.                     mouseOldX = mousePosX;
  180.                     mouseOldY = mousePosY;
  181.                     mousePosX = event.getSceneX();
  182.                     mousePosY = event.getSceneY();
  183.                     mouseDeltaX = mousePosX - mouseOldX;
  184.                     mouseDeltaY = mousePosY - mouseOldY;
  185.  
  186.                     double flip = -1.0;
  187.  
  188.                     if (event.isSecondaryButtonDown()) {
  189.                         double newX = cameraXform2.t.getX() + flip * mouseDeltaX * modifierFactor * modifier * 2.0;
  190.                         double newY = cameraXform2.t.getY() + 1.0 * -mouseDeltaY * modifierFactor * modifier * 2.0;
  191.                         cameraXform2.t.setX(newX);
  192.                         cameraXform2.t.setY(newY);
  193.                     } else if (event.isPrimaryButtonDown()) {
  194.                         double yAngle = cameraXform.ry.getAngle() - 1.0 * -mouseDeltaX * modifierFactor * modifier * 2.0;
  195.                         double xAngle = cameraXform.rx.getAngle() + flip * mouseDeltaY * modifierFactor * modifier * 2.0;
  196.                         cameraXform.ry.setAngle(yAngle);
  197.                         cameraXform.rx.setAngle(xAngle);
  198.                     }
  199.                 }
  200.             });
  201.         }
  202.  
  203.  
  204.         private final PerspectiveCamera camera = new PerspectiveCamera(true);
  205.         private final Rotate cameraXRotate = new Rotate(-20.0, 0.0, 0.0, 0.0, Rotate.X_AXIS);
  206.         private final Rotate cameraYRotate = new Rotate(-20.0, 0.0, 0.0, 0.0, Rotate.Y_AXIS);
  207.         private final Rotate cameraLookXRotate = new Rotate(0.0, 0.0, 0.0, 0.0, Rotate.X_AXIS);
  208.         private final Rotate cameraLookZRotate = new Rotate(0.0, 0.0, 0.0, 0.0, Rotate.Z_AXIS);
  209.         private final Translate cameraPosition = new Translate(0.0, 0.0, 0.0);
  210.         private Xform cameraXform = new Xform();
  211.         private Xform cameraXform2 = new Xform();
  212.         private Xform cameraXform3 = new Xform();
  213.         private double cameraDistance = 25.0;
  214.         private double dragStartX = 0;
  215.         private double dragStartY = 0;
  216.         private double dragStartRotateX = 0;
  217.         private double dragStartRotateY = 0;
  218.         private double mousePosX = 0;
  219.         private double mousePosY = 0;
  220.         private double mouseOldX = 0;
  221.         private double mouseOldY = 0;
  222.         private double mouseDeltaX = 0;
  223.         private double mouseDeltaY = 0;
  224.         private Rotate yUpRotate = new Rotate(0.0, 0.0, 0.0, 0.0, Rotate.X_AXIS);
  225.  
  226.         public Camera getCamera() {
  227.             return camera;
  228.         }
  229.  
  230.         public Xform getCameraXform() {
  231.             return cameraXform;
  232.         }
  233.     }
  234.  
  235.     private static class Xform extends Group {
  236.  
  237.         Translate t = new Translate();
  238.         Translate p = new Translate();
  239.         public Rotate rx = new Rotate();
  240.         public Rotate ry = new Rotate();
  241.         Rotate rz = new Rotate();
  242.         Scale s = new Scale();
  243.  
  244.         public Xform() {
  245.             rx.setAxis(Rotate.X_AXIS);
  246.             ry.setAxis(Rotate.Y_AXIS);
  247.             rz.setAxis(Rotate.Z_AXIS);
  248.             getTransforms().addAll(t, rz, ry, rx, s);
  249.         }
  250.     }
  251.  
  252.     // contains data + decoder for the mesh format i use
  253.     private static class Model {
  254.  
  255.         public static Model decode(byte[] data) {
  256.             Model model = new Model();
  257.             model.decodeOld(data);
  258.             return model;
  259.         }
  260.  
  261.         public void decodeOld(byte[] data) {
  262.             TriangleMeshTransparency.Buffer first = new TriangleMeshTransparency.Buffer(data);
  263.             TriangleMeshTransparency.Buffer second = new TriangleMeshTransparency.Buffer(data);
  264.             TriangleMeshTransparency.Buffer third = new TriangleMeshTransparency.Buffer(data);
  265.             TriangleMeshTransparency.Buffer fourth = new TriangleMeshTransparency.Buffer(data);
  266.             TriangleMeshTransparency.Buffer fifth = new TriangleMeshTransparency.Buffer(data);
  267.             first.pos = data.length - 18;
  268.             vertexCount = first.getUnsignedShort();
  269.             triangleCount = first.getUnsignedShort();
  270.             texturedTriangleCount = first.getUnsignedByte();
  271.  
  272.  
  273.             int renderTypeOpcode = first.getUnsignedByte();
  274.             int renderPriorityOpcode = first.getUnsignedByte();
  275.             int triangleAlphaOpcode = first.getUnsignedByte();
  276.             int triangleSkinOpcode = first.getUnsignedByte();
  277.             int vertexLabelOpcode = first.getUnsignedByte();
  278.             int verticesXCoordinateOffset = first.getUnsignedShort();
  279.  
  280.             int verticesYCoordinateOffset = first.getUnsignedShort();
  281.             int verticesZCoordinateOffset = first.getUnsignedShort();
  282.             int triangleIndicesOffset = first.getUnsignedShort();
  283.  
  284.             int pos = 0;
  285.  
  286.             int vertexFlagOffset = pos;
  287.             pos += vertexCount;
  288.  
  289.             int triangleCompressTypeOffset = pos;
  290.             pos += triangleCount;
  291.  
  292.             int facePriorityOffset = pos;
  293.             if (renderPriorityOpcode == 255) {
  294.                 pos += triangleCount;
  295.             }
  296.  
  297.             int triangleSkinOffset = pos;
  298.             if (triangleSkinOpcode == 1) {
  299.                 pos += triangleCount;
  300.             }
  301.  
  302.             int renderTypeOffset = pos;
  303.             if (renderTypeOpcode == 1) {
  304.                 pos += triangleCount;
  305.             }
  306.  
  307.             int vertexLabelsOffset = pos;
  308.             if (vertexLabelOpcode == 1) {
  309.                 pos += vertexCount;
  310.             }
  311.  
  312.             int triangleAlphaOffset = pos;
  313.             if (triangleAlphaOpcode == 1) {
  314.                 pos += triangleCount;
  315.             }
  316.  
  317.             int indicesOffset = pos;
  318.             pos += triangleIndicesOffset;
  319.  
  320.             int triangleColorOffset = pos;
  321.             pos += triangleCount * 2;
  322.  
  323.             int textureOffset = pos;
  324.             pos += texturedTriangleCount * 6;
  325.  
  326.             int xOffset = pos;
  327.             pos += verticesXCoordinateOffset;
  328.  
  329.             int yOffset = pos;
  330.             pos += verticesYCoordinateOffset;
  331.  
  332.             int zOffset = pos;
  333.  
  334.             verticesXCoordinate = new int[vertexCount];
  335.             verticesYCoordinate = new int[vertexCount];
  336.             verticesZCoordinate = new int[vertexCount];
  337.             faceIndicesA = new int[triangleCount];
  338.             faceIndicesB = new int[triangleCount];
  339.             faceIndicesC = new int[triangleCount];
  340.             if (texturedTriangleCount > 0) {
  341.                 textureMap = new short[texturedTriangleCount];
  342.                 textureVertexA = new short[texturedTriangleCount];
  343.                 textureVertexB = new short[texturedTriangleCount];
  344.                 textureVertexC = new short[texturedTriangleCount];
  345.             }
  346.  
  347.             if (vertexLabelOpcode == 1)
  348.                 vertexLabels = new int[vertexCount];
  349.  
  350.  
  351.             if (renderTypeOpcode == 1) {
  352.                 triangleInfo = new int[triangleCount];
  353.                 faceTexture = new short[triangleCount];
  354.                 triangleMaterial = new int[triangleCount];
  355.                 faceTextureMasks = new byte[triangleCount];
  356.             }
  357.  
  358.             if (renderPriorityOpcode == 255)
  359.                 trianglePriorities = new byte[triangleCount];
  360.             else
  361.                 modelPriority = (byte) renderPriorityOpcode;
  362.  
  363.             if (triangleAlphaOpcode == 1)
  364.                 triangleAlpha = new int[triangleCount];
  365.  
  366.             if (triangleSkinOpcode == 1)
  367.                 triangleLabels = new int[triangleCount];
  368.  
  369.             triangleColors = new int[triangleCount];
  370.             first.pos = vertexFlagOffset;
  371.             second.pos = xOffset;
  372.             third.pos = yOffset;
  373.             fourth.pos = zOffset;
  374.             fifth.pos = vertexLabelsOffset; // 18 +
  375.             int baseX = 0;
  376.             int baseY = 0;
  377.             int baseZ = 0;
  378.  
  379.             for (int point = 0; point < vertexCount; point++) {
  380.                 int flag = first.getUnsignedByte();
  381.  
  382.                 int x = 0;
  383.                 if ((flag & 0x1) != 0) {
  384.                     x = second.getSignedSmart();
  385.                 }
  386.  
  387.                 int y = 0;
  388.                 if ((flag & 0x2) != 0) {
  389.                     y = third.getSignedSmart();
  390.                 }
  391.                 int z = 0;
  392.                 if ((flag & 0x4) != 0) {
  393.                     z = fourth.getSignedSmart();
  394.                 }
  395.  
  396.                 verticesXCoordinate[point] = baseX + x;
  397.                 verticesYCoordinate[point] = baseY + y;
  398.                 verticesZCoordinate[point] = baseZ + z;
  399.  
  400.                 baseX = verticesXCoordinate[point];
  401.                 baseY = verticesYCoordinate[point];
  402.                 baseZ = verticesZCoordinate[point];
  403.                 if (vertexLabelOpcode == 1) {
  404.                     vertexLabels[point] = fifth.getUnsignedByte();
  405.                 }
  406.             }
  407.  
  408.  
  409.             first.pos = triangleColorOffset;
  410.             second.pos = renderTypeOffset;
  411.             third.pos = facePriorityOffset;
  412.             fourth.pos = triangleAlphaOffset;
  413.             fifth.pos = triangleSkinOffset;
  414.  
  415.             for (int face = 0; face < triangleCount; face++) {
  416.                 int color = first.getUnsignedShort();
  417.                 triangleColors[face] = color;
  418.  
  419.                 if (renderTypeOpcode == 1) {
  420.                     triangleInfo[face] = second.getUnsignedByte();
  421.                 }
  422.                 if (renderPriorityOpcode == 255) {
  423.                     trianglePriorities[face] = third.getSignedByte();
  424.                 }
  425.  
  426.                 if (triangleAlphaOpcode == 1) {
  427.                     triangleAlpha[face] = fourth.getUnsignedByte();
  428.  
  429.                 }
  430.                 if (triangleSkinOpcode == 1) {
  431.                     triangleLabels[face] = fifth.getUnsignedByte();
  432.                 }
  433.  
  434.             }
  435.             first.pos = indicesOffset;
  436.             second.pos = triangleCompressTypeOffset;
  437.             int a = 0;
  438.             int b = 0;
  439.             int c = 0;
  440.             int offset = 0;
  441.             int coordinate;
  442.  
  443.             for (int face = 0; face < triangleCount; face++) {
  444.                 int opcode = second.getUnsignedByte();
  445.  
  446.  
  447.                 if (opcode == 1) {
  448.                     a = (first.getSignedSmart() + offset);
  449.                     offset = a;
  450.                     b = (first.getSignedSmart() + offset);
  451.                     offset = b;
  452.                     c = (first.getSignedSmart() + offset);
  453.                     offset = c;
  454.                     faceIndicesA[face] = a;
  455.                     faceIndicesB[face] = b;
  456.                     faceIndicesC[face] = c;
  457.  
  458.                 }
  459.                 if (opcode == 2) {
  460.                     b = c;
  461.                     c = (first.getSignedSmart() + offset);
  462.                     offset = c;
  463.                     faceIndicesA[face] = a;
  464.                     faceIndicesB[face] = b;
  465.                     faceIndicesC[face] = c;
  466.                 }
  467.                 if (opcode == 3) {
  468.                     a = c;
  469.                     c = (first.getSignedSmart() + offset);
  470.                     offset = c;
  471.                     faceIndicesA[face] = a;
  472.                     faceIndicesB[face] = b;
  473.                     faceIndicesC[face] = c;
  474.                 }
  475.                 if (opcode == 4) {
  476.                     coordinate = a;
  477.                     a = b;
  478.                     b = coordinate;
  479.                     c = (first.getSignedSmart() + offset);
  480.                     offset = c;
  481.                     faceIndicesA[face] = a;
  482.                     faceIndicesB[face] = b;
  483.                     faceIndicesC[face] = c;
  484.                 }
  485.  
  486.             }
  487.             first.pos = textureOffset;
  488.  
  489.             for (int face = 0; face < texturedTriangleCount; face++) {
  490.                 textureMap[face] = 0;
  491.                 textureVertexA[face] = (short) first.getUnsignedShort();
  492.                 textureVertexB[face] = (short) first.getUnsignedShort();
  493.                 textureVertexC[face] = (short) first.getUnsignedShort();
  494.             }
  495.  
  496.             if (triangleInfo == null) {
  497.                 triangleInfo = new int[triangleCount];
  498.             }
  499.         }
  500.  
  501.         public int vertexCount;
  502.         public int triangleCount;
  503.         public int[] verticesXCoordinate;
  504.         public int[] verticesYCoordinate;
  505.         public int[] verticesZCoordinate;
  506.         public int[] faceIndicesA;
  507.         public int[] faceIndicesB;
  508.         public int[] faceIndicesC;
  509.         public int[] triangleInfo;
  510.         public byte[] trianglePriorities;
  511.  
  512.         public int[] triangleAlpha;
  513.         public int[] triangleColors;
  514.         public byte modelPriority = 0;
  515.         public int texturedTriangleCount;
  516.         public short[] textureVertexA;
  517.         public short[] textureVertexB;
  518.         public short[] textureVertexC;
  519.         public int[] vertexLabels;
  520.         public int[] triangleLabels;
  521.  
  522.         public int[] triangleMaterial;
  523.         public short[] faceTexture;
  524.         public short[] textureMap;
  525.         public byte[] faceTextureMasks;
  526.  
  527.  
  528.     }
  529.  
  530.     private static class Buffer {
  531.         public Buffer(byte[] payload) {
  532.             this.payload = payload;
  533.             this.pos = 0;
  534.         }
  535.  
  536.         public int getUnsignedByte() {
  537.             return this.payload[this.pos++] & 0xff;
  538.         }
  539.  
  540.  
  541.         public byte getSignedByte() {
  542.             return this.payload[this.pos++];
  543.         }
  544.  
  545.  
  546.         public int getUnsignedShort() {
  547.             this.pos += 2;
  548.             return ((this.payload[this.pos - 2] & 0xff) << 8) + (this.payload[this.pos - 1] & 0xff);
  549.         }
  550.  
  551.         public int getSignedSmart() {
  552.             int value = this.payload[this.pos] & 0xff;
  553.             if (value < 128) {
  554.                 return this.getUnsignedByte() - 64;
  555.             } else {
  556.                 return this.getUnsignedShort() - 49152;
  557.             }
  558.         }
  559.  
  560.         public byte[] payload;
  561.         public int pos;
  562.     }
  563.  
  564.  
  565.     private static class ColorUtils {
  566.         public static int getBlue(int rgb) {
  567.             return rgb & 0xFF;
  568.         }
  569.  
  570.         public static int getGreen(int rgb) {
  571.             return (rgb >> 8) & 0xFF;
  572.         }
  573.  
  574.         public static int getRed(int rgb) {
  575.             return (rgb >> 16) & 0xFF;
  576.         }
  577.  
  578.         public static Color getJFXColor(int rgb, double opacity) {
  579.             return Color.color(getRed(rgb) / 255.0, getGreen(rgb) / 255.0, getBlue(rgb) / 255.0, opacity);
  580.         }
  581.     }
  582.  
  583.     // just a wrapper for TriangleMesh, includes helper methods like addVertex, addUV
  584.     private static class RSTriangleMesh extends TriangleMesh {
  585.  
  586.         private final Map<Integer, Integer> vertexMap = new HashMap<>();
  587.  
  588.         public int addVertex(int vertex, int x, int y, int z) {
  589.             int cur = getPoints().size() / 3;
  590.             getPoints().addAll(x, y, z);
  591.             vertexMap.putIfAbsent(vertex, cur);
  592.             return vertexMap.getOrDefault(vertex, 0);
  593.         }
  594.  
  595.         public int addUV(float u, float v) {
  596.             int cur = getTexCoords().size() / 2;
  597.             getTexCoords().addAll(u, v);
  598.             return cur;
  599.         }
  600.     }
  601.  
  602.     private static class RSTriangleMeshView extends MeshView {
  603.  
  604.         public RSTriangleMeshView(TriangleMeshTransparency.RSTriangleMesh mesh) {
  605.             super(mesh);
  606.         }
  607.  
  608.         public TriangleMeshTransparency.RSTriangleMesh toRSTriangleMesh() {
  609.             return (TriangleMeshTransparency.RSTriangleMesh) getMesh();
  610.         }
  611.     }
  612.  
  613.     private static class HSLPalette {
  614.         public static int[] table = new int[128 * 512];
  615.  
  616.         static {
  617.             generatePalette(0.80000000000000004D); // default is 0.8 in the engine
  618.         }
  619.  
  620.         public static void generatePalette(double brightness) {
  621.             int index = 0;
  622.             for (int y = 0; y < 512; y++) {
  623.                 double hue = ((double) (y / 8) / 64.0) + 0.0078125;
  624.                 double saturation = ((double) (y & 0x7) / 8.0) + 0.0625;
  625.                 for (int x = 0; x < 128; x++) {
  626.                     double lightness = (double) x / 128.0;
  627.                     double red = lightness;
  628.                     double green = lightness;
  629.                     double blue = lightness;
  630.  
  631.                     if (saturation != 0.0) {
  632.                         double a;
  633.  
  634.                         if (lightness < 0.5) {
  635.                             a = lightness * (1.0 + saturation);
  636.                         } else {
  637.                             a = (lightness + saturation) - (lightness * saturation);
  638.                         }
  639.  
  640.                         double b = (2.0 * lightness) - a;
  641.  
  642.                         double fRed = hue + (1.0 / 3.0);
  643.                         double fBlue = hue - (1.0 / 3.0);
  644.  
  645.                         if (fRed > 1.0) fRed--;
  646.                         if (fBlue < 0.0) fBlue++;
  647.  
  648.                         red = hueToRgb(fRed, a, b);
  649.                         green = hueToRgb(hue, a, b);
  650.                         blue = hueToRgb(fBlue, a, b);
  651.                     }
  652.  
  653.                     table[index++] = applyBrightness(((int) (red * 256.0) << 16) | ((int) (green * 256.0) << 8) | (int) (blue * 256.0), brightness);
  654.                 }
  655.             }
  656.         }
  657.  
  658.         private static double hueToRgb(double value, double a, double b) {
  659.             if ((6.0 * value) < 1.0)
  660.                 return b + ((a - b) * 6.0 * value);
  661.             if (2.0 * value < 1.0)
  662.                 return a;
  663.             if (3.0 * value < 2.0)
  664.                 return b + ((a - b) * ((2.0 / 3.0) - value) * 6.0);
  665.             return b;
  666.         }
  667.  
  668.         public static int applyBrightness(int rgb, double brightness) {
  669.             double r = (double) (rgb >> 16) / 256.0;
  670.             double g = (double) (rgb >> 8 & 0xff) / 256.0;
  671.             double b = (double) (rgb & 0xff) / 256.0;
  672.             r = Math.pow(r, brightness);
  673.             g = Math.pow(g, brightness);
  674.             b = Math.pow(b, brightness);
  675.             return ((int) (r * 256.0) << 16) + ((int) (g * 256.0) << 8) + (int) (b * 256.0);
  676.         }
  677.  
  678.         public static int getRgbForHsl(int hsl) {
  679.             if (hsl >= table.length) {
  680.                 return 0;
  681.             }
  682.  
  683.             return table[hsl & 0xFFFF];
  684.         }
  685.     }
  686.  
  687. }
  688.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement