{"id":10006542,"date":"2022-09-19T23:27:46","date_gmt":"2022-09-19T15:27:46","guid":{"rendered":"https:\/\/ityet.com\/?p=10006542"},"modified":"2022-09-19T23:27:46","modified_gmt":"2022-09-19T15:27:46","slug":"%e4%ba%86%e8%a7%a33d%e4%b8%96%e7%95%8c%e7%9a%84%e9%bb%91%e9%ad%94%e6%b3%95-%e7%ba%afjava%e6%9e%84%e9%80%a0%e4%b8%80%e4%b8%aa%e7%ae%80%e5%8d%95%e7%9a%843d%e6%b8%b2%e6%9f%93%e5%bc%95%e6%93%8e","status":"publish","type":"post","link":"https:\/\/itmax.cn\/?p=10006542","title":{"rendered":"\u4e86\u89e33D\u4e16\u754c\u7684\u9ed1\u9b54\u6cd5-\u7eafJava\u6784\u9020\u4e00\u4e2a\u7b80\u5355\u76843D\u6e32\u67d3\u5f15\u64ce"},"content":{"rendered":"<p>\u7b80\u4ecb\uff1a\u00a0\u5bf9\u4e8e\u975e\u6e32\u67d3\u5f15\u64ce\u76f8\u5173\u5de5\u4f5c\u7684\u5f00\u53d1\u8005\u6765\u8bf4\uff0c\u53ef\u80fd\u8ba4\u4e3a\u5373\u4f7f\u6784\u5efa\u6700\u7b80\u5355\u76843D\u7a0b\u5e8f\u4e5f\u975e\u5e38\u56f0\u96be\uff0c\u4f46\u4e8b\u5b9e\u4e0a\u5e76\u975e\u5982\u6b64\uff0c\u672c\u7bc7\u6587\u7ae0\u5c06\u901a\u8fc7\u7b80\u5355\u7684200\u591a\u884c\u7684\u7eaf Java\u4ee3\u7801\uff0c\u53bb\u5b9e\u8df5\u6b63\u4ea4\u6295\u5f71\u3001\u7b80\u5355\u4e09\u89d2\u5f62\u5149\u6805\u5316\u3001z\u7f13\u51b2\uff08\u6df1\u5ea6\u7f13\u51b2\u533a\uff09\u548c\u5e73\u9762\u7740\u8272\u7b49\u57fa\u672c\u76843D\u6e32\u67d3\u6280\u672f\u3002<br \/><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042511564\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><br \/>\u4f5c\u8005 | \u674e\u5386\u6210(\u5f9c\u8446)\u6765\u6e90 | \u963f\u91cc\u5f00\u53d1\u8005\u516c\u4f17\u53f7\u524d\u8a00\u5f53\u4eca\u7528\u4e8e\u6e38\u620f\u548c\u591a\u5a92\u4f53\u76843D\u6e32\u67d3\u5f15\u64ce\u5728\u6570\u5b66\u548c\u7f16\u7a0b\u7684\u590d\u6742\u6027\u4e0a\u8db3\u4ee5\u4ee4\u5927\u591a\u6570\u4eba\u671b\u800c\u751f\u754f\uff0c\u4ece\u7f16\u7a0b\u63a5\u53e3\u7684OpenGL\u518d\u5230\u903c\u771f\u5230\u4ee4\u4eba\u53f9\u4e3a\u89c2\u6b62\u7684UE5\uff08\u865a\u5e7b\u4e94\uff09\u5f15\u64ce\uff0c\u540e\u8005\u5355\u5355\u5f15\u64ce\u672c\u8eab\uff08\u4e0d\u542b\u8c03\u8bd5\uff09\u7684\u5927\u5c0f\u5c31\u8fbe\u5230\u4e86\u5c06\u8fd140g\uff08\u5f53\u7136UE5\u4e0d\u5149\u53ea\u6709\u6e32\u67d3\u7684\u529f\u80fd\uff09\uff0c\u5176\u4e2d\u5e26\u6765\u7684\u5168\u65b0\u7684\u6838\u5fc3\u7684Nanite\u865a\u62df\u5fae\u591a\u8fb9\u5f62\u51e0\u4f55\u6280\u672f\u548cLumen\u52a8\u6001\u5168\u5c40\u5149\u7167\u6280\u672f\u66f4\u662f\u53ca\u5176\u590d\u6742\u3002\u5bf9\u4e8e\u975e\u6e32\u67d3\u5f15\u64ce\u76f8\u5173\u5de5\u4f5c\u7684\u5f00\u53d1\u8005\u6765\u8bf4\uff0c\u53ef\u80fd\u8ba4\u4e3a\u5373\u4f7f\u6784\u5efa\u6700\u7b80\u5355\u76843D\u7a0b\u5e8f\u4e5f\u975e\u5e38\u56f0\u96be\uff0c\u4f46\u4e8b\u5b9e\u4e0a\u5e76\u975e\u5982\u6b64\uff0c\u672c\u7bc7\u6587\u7ae0\u5c06\u901a\u8fc7\u7b80\u5355\u7684200\u591a\u884c\u7684\u7eaf Java\u4ee3\u7801\uff0c\u53bb\u5b9e\u8df5\u6b63\u4ea4\u6295\u5f71\u3001\u7b80\u5355\u4e09\u89d2\u5f62\u5149\u6805\u5316\u3001z\u7f13\u51b2\uff08\u6df1\u5ea6\u7f13\u51b2\u533a\uff09\u548c\u5e73\u9762\u7740\u8272\u7b49\u57fa\u672c\u76843D\u6e32\u67d3\u6280\u672f\uff0c\u7136\u540e\u5728\u4e0b\u4e00\u7247\u6587\u7ae0\u4e2d\uff0c\u5c06\u7740\u91cd\u4ecb\u7ecd\u5149\u7ebf\u8ffd\u8e2a\u7684\u77e5\u8bc6\u3002\u5f53\u7136\u672c\u7bc7\u6587\u7ae0\u6700\u7ec8\u5b9e\u73b0\u7684\u201c3D\u6e32\u67d3\u5f15\u64ce\u201d\u975e\u5e38\u7b80\u5355\uff0c\u6ca1\u6709\u505a\u4efb\u4f55\u7684\u7b97\u6cd5\u4f18\u5316\uff0c\u800c\u4e14\u4ec5\u4f7f\u7528\u5230\u4e86CPU\uff0c\u5b9e\u9645\u6027\u80fd\u8fdc\u4e0d\u5982OpenGl\u3002\u4e0d\u8fc7\u5176\u76ee\u7684\u662f\u7528\u4e8e\u53bb\u5e2e\u6211\u4eec\u4e86\u89e3\u771f\u6b63\u7684\u73b0\u4ee3\u5f15\u64ce\u662f\u5982\u4f55\u53d1\u6325\u5b83\u4eec\u7684\u9ed1\u9b54\u6cd5\uff0c\u4ee5\u4fbf\u66f4\u597d\u7684\u4e0a\u624b\u4f7f\u7528\u5b83\u4eec\u3002\u9700\u8981\u7684\u77e5\u8bc6\u50a8\u5907\u4e09\u89d2\u51fd\u6570\u3001\u77e9\u9635\u8fd0\u7b97\u3001\u5411\u91cf\u8fd0\u7b97\u3001\u6cd5\u5411\u91cf\u3002\u5982\u679c\u4f60\u5c1a\u672a\u5b66\u4e60\u6216\u8005\u5fd8\u8bb0\u4e86\u4ee5\u4e0a\u7684\u77e5\u8bc6\u4e5f\u4e0d\u7528\u62c5\u5fc3\uff0c\u672c\u7bc7\u6587\u7ae0\u4e2d\u4f1a\u7ed3\u5408\u4f8b\u5b50\u5bf9\u4e0a\u8ff0\u77e5\u8bc6\u8fdb\u884c\u7b80\u5355\u7684\u89e3\u91ca\uff0c\u540c\u65f6\u4e5f\u4e0d\u5fc5\u592a\u8fc7\u7ea0\u7ed3\u8fd9\u4e9b\u6570\u5b66\u77e5\u8bc6\uff0c\u4f1a\u7528\u5373\u53ef\uff0c\u6bd5\u7adf\u8fde\u5361\u795e\u4e5f\u4f1a\u201cwhat the fuck\uff1f\u201d\u3002\u5f53\u7136\u5982\u679c\u719f\u6089\u4e0a\u8ff0\u77e5\u8bc6\uff0c\u9605\u8bfb\u8d77\u6765\u4f1a\u66f4\u52a0\u8f7b\u677e\u3002\u76ee\u6807\u6211\u4eec\u5c06\u4f1a\u7ed8\u5236\u4e00\u4e2a\u56db\u9762\u4f53\uff0c\u56e0\u4e3a\u5b83\u662f\u6700\u7b80\u5355\u76843D\u56fe\u5f62\uff5e\u00a0<br \/><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042511565\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><br \/>\u00a0\u754c\u9762\u7528\u4e8e\u5c55\u793a\u56fe\u5f62\u7684\u754c\u9762public static void main(String[] args) {<\/p>\n<pre><code>    JFrame frame = new JFrame();\n    Container pane = frame.getContentPane();\n    pane.setLayout(new BorderLayout());\n   \n    \/\/ panel to display render results\n    JPanel renderPanel = new JPanel() {\n        public void paintComponent(Graphics g) {\n            Graphics2D g2 = (Graphics2D) g;\n            g2.setColor(Color.BLACK);\n            g2.fillRect(0, 0, getWidth(), getHeight());\n            \n            \/\/ rendering magic will happen here\n        }\n    };\n    pane.add(renderPanel, BorderLayout.CENTER);\n    \n    frame.setSize(600, 600);\n    frame.setVisible(true);\n}\u57fa\u7840\u5750\u6807\u7cfb\u00a0<\/code><\/pre>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042511566\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><br \/>\u00a0\u70b9\u4e0e\u5e73\u9762\u73b0\u5728\u8ba9\u6211\u4eec\u6dfb\u52a0\u4e00\u4e9b3D\u4e16\u754c\u7684\u57fa\u672c\u7684\u6a21\u578b\u7c7b\u2014\u2014\u9876\u70b9\u548c\u4e09\u89d2\u5f62\u3002Vertex \u53ea\u662f\u4e00\u4e2a\u7b80\u5355\u7684\u7ed3\u6784\u6765\u5b58\u50a8\u6211\u4eec\u7684\u4e09\u4e2a\u5750\u6807\uff08X\u3001Y \u548c Z\uff09\uff0c\u800c\u4e09\u89d2\u5f62\u5c06\u4e09\u4e2a\u9876\u70b9\u7ed1\u5b9a\u5728\u4e00\u8d77\u5e76\u5b58\u50a8\u5b83\u7684\u989c\u8272\u3002\/\/ X \u5750\u6807\u8868\u793a\u5de6\u53f3\u65b9\u5411\u7684\u79fb\u52a8<br \/>\/\/ Y \u8868\u793a\u5c4f\u5e55\u4e0a\u7684\u4e0a\u4e0b\u79fb\u52a8<br \/>\/\/ Z \u8868\u793a\u6df1\u5ea6\uff08\u56e0\u6b64 Z \u8f74\u5782\u76f4\u4e8e\u60a8\u7684\u5c4f\u5e55\uff09\u3002\u6b63 Z \u8868\u793a\u201c\u671d\u5411\u89c2\u5bdf\u8005\u201d\u3002<br \/>class Vertex {<\/p>\n<pre><code>double x;\ndouble y;\ndouble z;\nVertex(double x, double y, double z) {\n    this.x = x;\n    this.y = y;\n    this.z = z;\n}<\/code><\/pre>\n<p>}<\/p>\n<p>class Triangle {<\/p>\n<pre><code>Vertex v1;\nVertex v2;\nVertex v3;\nColor color;\nTriangle(Vertex v1, Vertex v2, Vertex v3, Color color) {\n    this.v1 = v1;\n    this.v2 = v2;\n    this.v3 = v3;\n    this.color = color;\n}<\/code><\/pre>\n<p>}\u90a3\u4e48\u4e3a\u4ec0\u4e48\u8981\u4f7f\u7528\u4e09\u89d2\u5f62\u6765\u63cf\u8ff03D\u4e16\u754c\u5462\uff1fa.\u4e09\u89d2\u5f62\u662f\u6700\u7b80\u5355\u7684\u591a\u8fb9\u5f62\uff0c\u5c11\u4e8e3\u4e2a\u9876\u70b9\u5c31\u4e0d\u80fd\u6210\u4e3a\u4e00\u4e2a\u8868\u9762b.\u4e09\u89d2\u5f62\u5fc5\u7136\u662f\u5e73\u5766\u7684c.\u4e09\u89d2\u5f62\u7ecf\u591a\u79cd\u8f6c\u6362\u4e4b\u540e\uff0c\u4ecd\u7136\u662f\u4e09\u89d2\u5f62\uff0c\u8fd9\u5bf9\u4e8e\u4eff\u5c04\u8f6c\u6362\u548c\u900f\u89c6\u8f6c\u6362\u4e5f\u6210\u7acb\u3002\u6700\u574f\u7684\u60c5\u51b5\u4e0b\uff0c\u4ece\u4e09\u89d2\u5f62\u7684\u8fb9\u53bb\u770b\uff0c\u4e09\u89d2\u5f62\u4f1a\u9000\u5316\u4e3a\u7ebf\u6bb5\u3002\u5728\u5176\u5b83\u89d2\u5ea6\u89c2\u5bdf\uff0c\u4ecd\u80fd\u7ef4\u6301\u662f\u4e09\u89d2\u5f62d.\u5b83\u53ef\u4ee5\u5f88\u597d\u5730\u7528\u53c9\u79ef\u5224\u65ad\u4e00\u4e2a\u70b9\u662f\u4e0d\u662f\u5728\u4e09\u89d2\u5f62\u5185\u90e8\uff08\u4e09\u89d2\u5f62\u7684\u5185\u5916\u5b9a\u4e49\u7279\u522b\u6e05\u6670\uff09e.\u51e0\u4e4e\u6240\u6709\u5546\u7528\u56fe\u5f62\u52a0\u901f\u786c\u4ef6\u90fd\u662f\u4e3a\u4e09\u89d2\u5f62\u5149\u6805\u5316\u800c\u8bbe\u8ba1\u7684\u6784\u9020\u76ee\u6807\u4e09\u7ef4\u56fe\u5f62\u975e\u5e38\u7b80\u5355\uff0c\u5c31\u662f\u56db\u4e2a\u4e09\u89d2\u5f62\u5408\u5e76\u800c\u6210\uff08\u5148\u5c06\u5b83\u4eec\u653e\u5165\u5217\u8868\uff09\u3002\u540c\u65f6\u4e3a\u4e86\u533a\u5206\u5b83\u4eec\uff0c\u8d4b\u4e88\u4e0d\u540c\u7684\u989c\u8272\u3002<br \/>List tris = new ArrayList&lt;&gt;();<br \/>tris.add(new Triangle(new Vertex(100, 100, 100),<\/p>\n<pre><code>                  new Vertex(-100, -100, 100),\n                  new Vertex(-100, 100, -100),\n                  Color.WHITE));<\/code><\/pre>\n<p>tris.add(new Triangle(new Vertex(100, 100, 100),<\/p>\n<pre><code>                  new Vertex(-100, -100, 100),\n                  new Vertex(100, -100, -100),\n                  Color.RED));<\/code><\/pre>\n<p>tris.add(new Triangle(new Vertex(-100, 100, -100),<\/p>\n<pre><code>                  new Vertex(100, -100, -100),\n                  new Vertex(100, 100, 100),\n                  Color.GREEN));<\/code><\/pre>\n<p>tris.add(new Triangle(new Vertex(-100, 100, -100),<\/p>\n<pre><code>                  new Vertex(100, -100, -100),\n                  new Vertex(-100, -100, 100),\n                  Color.BLUE));\u73b0\u5728\u5c06\u5b83\u4eec\u653e\u7f6e\u5230\u6211\u4eec\u4e4b\u524d\u7684\u754c\u9762\u4e2d\uff0c\u4e0d\u8fc7\u5148\u53ea\u5c55\u793a\u6846\u7ebf\u3002\u56e0\u4e3a\u662f\u6b63\u4ea4\u6295\u5f71\uff0c\u6240\u4ee5\u975e\u5e38\u7b80\u5355\uff0c\u5ffd\u7565z\u8f74\u7ed8\u5236\u8fde\u7ebf\u5373\u53ef\u3002\u6846\u7ebf\u4ec5\u662f\u7528\u4e8e\u76ee\u524d\u76f4\u89c2\u7684\u770b\u5230\u56db\u9762\u4f53\uff0c\u6700\u7ec8\u6e32\u67d3\u7684\u65f6\u5019\u4e0d\u4f1a\u7528\u5230\u6b642dAPI\/\/ \u751f\u6210\u7684\u5f62\u72b6\u4ee5\u539f\u70b9 (0, 0, 0) \u4e3a\u4e2d\u5fc3\uff0c\u7a0d\u540e\u6211\u4eec\u5c06\u56f4\u7ed5\u8be5\u70b9\u8fdb\u884c\u65cb\u8f6c\u3002<\/code><\/pre>\n<p>g2.translate(getWidth() \/ 2, getHeight() \/ 2);<br \/>g2.setColor(Color.WHITE);<br \/>for (Triangle t : tris) {<\/p>\n<pre><code>Path2D path = new Path2D.Double();\npath.moveTo(t.v1.x, t.v1.y);\npath.lineTo(t.v2.x, t.v2.y);\npath.lineTo(t.v3.x, t.v3.y);\npath.closePath();\ng2.draw(path);<\/code><\/pre>\n<p>}\u6211\u4eec\u5c06\u5f97\u5230\u5982\u4e0b\u7ed3\u679c\uff1a\u00a0<br \/><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042511567\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><br \/>\u00a0\u8fd9\u5c31\u662f\u6211\u4eec\u7684\u56db\u9762\u4f53\uff0c\u4e3a\u4e86\u8ba9\u4f60\u76f8\u4fe1\uff0c\u6211\u4eec\u6765\u4e3a\u5176\u6dfb\u52a0\u4e00\u4e9b\u65cb\u8f6c\u3002\u65cb\u8f6c\u5904\u7406 3d \u70b9\u7684\u65b9\u6cd5\u6709\u5f88\u591a\uff0c\u4f46\u6700\u7075\u6d3b\u7684\u662f\u4f7f\u7528\u77e9\u9635\u4e58\u6cd5\u3002\u5c06\u70b9\u8868\u793a\u4e3a 3&#215;1 \u5411\u91cf\uff0c\u7136\u540e\u8f6c\u6362\u5c31\u662f\u7b80\u5355\u5730\u4e58\u4ee5 3&#215;3 \u77e9\u9635\u3002\u00a0<br \/><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042511568\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><br \/>\u00a0\u4f8b\u5982\u4e24\u500d\u7f29\u653e\uff1a\u00a0<br \/><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042511569\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><br \/>\u00a0\u5f53\u7136\uff0c\u672c\u6b21\u91cd\u70b9\u8bb2\u89e3\u7684\u662f\u65cb\u8f6c\uff0c3D \u7a7a\u95f4\u4e2d\u7684\u4efb\u4f55\u65cb\u8f6c\u90fd\u53ef\u4ee5\u8868\u793a\u4e3a 3 \u79cd\u539f\u59cb\u65cb\u8f6c\u7684\u7ec4\u5408\uff1aXY \u5e73\u9762\u65cb\u8f6c\u3001YZ \u5e73\u9762\u65cb\u8f6c\u548c XZ \u5e73\u9762\u65cb\u8f6c\u3002\u6211\u4eec\u53ef\u4ee5\u4e3a\u6bcf\u4e2a\u65cb\u8f6c\u5199\u51fa\u53d8\u6362\u77e9\u9635\uff0c\u5982\u4e0b\u6240\u793a\uff1a\u00a0<br \/><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042511570\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><br \/>\u00a0\u540c\u65f6\u77e9\u9635\u53d8\u6362\u8fd8\u6709\u8fd9\u6837\u7684\u7279\u6027\uff1a\u00a0<br \/><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042511571\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><br \/>\u00a0\u5373\u591a\u6b21\u77e9\u9635\u53d8\u6362\u53ef\u4ee5\u9884\u5148\u5148\u5408\u5e76\u4e3a\u4e00\u4e2a\u3002\u770b\u770b\u901a\u8fc7\u4ee3\u7801\u5982\u4f55\u5b9e\u73b0\u77e9\u9635\u548c\u77e9\u9635\u7684\u4e58\u6cd5\uff1aclass Matrix3 {<\/p>\n<pre><code>double[] values;\nMatrix3(double[] values) {\n    this.values = values;\n}\nMatrix3 multiply(Matrix3 other) {\n    double[] result = new double[9];\n    for (int row = 0; row &lt; 3; row++) {\n        for (int col = 0; col &lt; 3; col++) {\n            for (int i = 0; i &lt; 3; i++) {\n                result[row * 3 + col] +=\n                    this.values[row * 3 + i] * other.values[i * 3 + col];\n            }\n        }\n    }\n    return new Matrix3(result);\n}\nVertex transform(Vertex in) {\n    return new Vertex(\n        in.x * values[0] + in.y * values[3] + in.z * values[6],\n        in.x * values[1] + in.y * values[4] + in.z * values[7],\n        in.x * values[2] + in.y * values[5] + in.z * values[8]\n    );\n}<\/code><\/pre>\n<p>}\u6784\u5efaXZ\u5e73\u9762\uff08\u4ee5Y\u4e3a\u8f74\u5de6\u53f3\uff09\u65cb\u8f6c\u548cYZ\u5e73\u9762\uff08\u4ee5X\u4e3a\u8f74\u4e0a\u4e0b\uff09\u65cb\u8f6c\u3002double heading = Math.toRadians(x[0]);<\/p>\n<pre><code>            Matrix3 headingTransform = new Matrix3(new double[]{\n                    Math.cos(heading), 0, -Math.sin(heading),\n                    0, 1, 0,\n                    Math.sin(heading), 0, Math.cos(heading)\n            });<\/code><\/pre>\n<p>double pitch = Math.toRadians(y[0]);<\/p>\n<pre><code>            Matrix3 pitchTransform = new Matrix3(new double[]{\n                    1, 0, 0,\n                    0, Math.cos(pitch), Math.sin(pitch),\n                    0, -Math.sin(pitch), Math.cos(pitch)\n            })<\/code><\/pre>\n<p>\/\/\u63d0\u524d\u8fdb\u884c\u77e9\u9635\u5408\u5e76<br \/>Matrix3 transform = headingTransform.multiply(pitchTransform);\u7136\u540e\u901a\u8fc7\u76d1\u542c\u9f20\u6807\u7684\u62d6\u62fd\uff0c\u6539\u53d8x\u548cy\u6240\u4ee3\u8868\u7684\u89d2\u5ea6\u3002renderPanel.addMouseMotionListener(new MouseMotionListener() {<\/p>\n<pre><code>        @Override\n        public void mouseDragged(MouseEvent e) {\n            double yi = 180.0 \/ renderPanel.getHeight();\n            double xi = 180.0 \/ renderPanel.getWidth();\n            x[0] = (int) (e.getX() * xi);\n            y[0] = -(int) (e.getY() * yi);\n            renderPanel.repaint();\n        }\n\n        @Override\n        public void mouseMoved(MouseEvent e) {\n\n        }\n    });\u73b0\u5728\u6211\u4eec\u53ef\u4ee5\u8bb2\u4e4b\u524d\u7684\u56db\u9762\u4f53\u65cb\u8f6c\u8d77\u6765\u4e86g2.translate(getWidth() \/ 2, getHeight() \/ 2);<\/code><\/pre>\n<p>g2.setColor(Color.WHITE);<br \/>for (Triangle t : tris) {<\/p>\n<pre><code>Vertex v1 = transform.transform(t.v1);\nVertex v2 = transform.transform(t.v2);\nVertex v3 = transform.transform(t.v3);\nPath2D path = new Path2D.Double();\npath.moveTo(v1.x, v1.y);\npath.lineTo(v2.x, v2.y);\npath.lineTo(v3.x, v3.y);\npath.closePath();\ng2.draw(path);<\/code><\/pre>\n<p>}\u6548\u679c\uff1a\u00a0<br \/><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042511572\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><br \/>\u00a0\u5149\u6805\u5316\u73b0\u5728\u6211\u4eec\u9700\u8981\u5f00\u59cb\u7528\u4e00\u4e9b\u7269\u8d28\u586b\u5145\u8fd9\u4e9b\u4e09\u89d2\u5f62\u3002\u4e3a\u6b64\uff0c\u6211\u4eec\u9996\u5148\u9700\u8981\u5bf9\u4e09\u89d2\u5f62\u8fdb\u884c\u201c\u5149\u6805\u5316\u201d\u2014\u2014\u5c06\u5176\u8f6c\u6362\u4e3a\u5c4f\u5e55\u4e0a\u5b83\u6240\u5360\u636e\u7684\u50cf\u7d20\u5217\u8868\u3002\u5149\u6805\u5316\uff08Rasterization\uff09\u8fd9\u4e00\u8bcd\u5728\u8ba1\u7b97\u673a\u56fe\u5f62\u5b66\u4e2d\u7ecf\u5e38\u51fa\u73b0\uff0c\u5f88\u591a\u76f8\u5173\u4e66\u7c4d\u90fd\u7ed9\u51fa\u4e86\u81ea\u5df1\u7684\u5b9a\u4e49\u3002\u4e0d\u8fc7\u6211\u770b\u76ee\u524d\u4e00\u4e2a\u6bd4\u8f83\u51c6\u786e\u7684\u5b9a\u4e49\u662f\uff1a\u5149\u6805\u5316\u5c31\u662f\u628a\u4e1c\u897f\u753b\u5728\u5c4f\u5e55\u4e0a\u7684\u4e00\u4e2a\u8fc7\u7a0b\uff08Rasterize == drawing onto the screen \uff09\u6587\u827a\u7248\u89e3\u91ca\uff1a\u51dd\u56fa\u751f\u547d\u7684\u5149\u6805\u5316\u5149\u6805\u5316\u4e2d\u6700\u91cd\u8981\u7684\u4e00\u4e2a\u6982\u5ff5\uff0c\u5224\u65ad\u4e00\u4e2a\u50cf\u7d20\u4e0e\u4e09\u89d2\u5f62\u4e4b\u95f4\u7684\u5173\u7cfb\uff0c\u66f4\u786e\u5374\u7684\u6765\u8bf4\u6211\u4eec\u8003\u8651\u50cf\u7d20\u7684\u4e2d\u5fc3\u70b9\u4e0e\u4e09\u89d2\u5f62\u7684\u4f4d\u7f6e\u5173\u7cfb\u3002\u00a0<br \/><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042511573\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><br \/>\u00a0\u5224\u65ad\u4e00\u4e2a\u70b9\u662f\u5426\u5728\u4e09\u89d2\u5f62\u5185\u5728\u6570\u5b66\u4e0a\u6709\u5f88\u591a\u65b9\u6cd5\uff0c\u672c\u7bc7\u6587\u7ae0\u9009\u62e9\u4e86\u53c9\u79ef\u7684\u65b9\u6cd5\uff08\u56e0\u4e3a\u662f\u6b63\u4ea4\u6295\u5f71\uff0c\u8fd9\u6837\u6bd4\u8f83\u7b80\u5355\uff09\u5bf9\u5176\u4ed6\u65b9\u6cd5\u611f\u5174\u8da3\u7684\uff0c\u53ef\u4ee5\u6839\u636e\u5176\u6570\u5b66\u539f\u7406\u81ea\u5df1\u53bb\u5b9e\u73b0\u4e00\u4e0b\uff1a3D\u6570\u5b66 | \u5224\u65ad\u70b9\u662f\u5426\u5728\u4e09\u89d2\u5f62\u5185\u53c9\u79ef\u53c9\u79ef\u7684\u65b9\u5411\u4e0e\u4e24\u4e2a\u521d\u59cb\u5411\u91cf\u6b63\u4ea4\uff0c\u8fd9\u4e2a\u65b9\u5411\u6211\u4eec\u53ef\u4ee5\u7531\u53f3\u624b\u87ba\u65cb\u5b9a\u5219\u786e\u5b9a\u3002\u6211\u4eec\u53ef\u4ee5\u4f38\u51fa\u53f3\u624b\u4f5ca\u5411\u91cf\u5230b\u5411\u91cf\u7684\u53c9\u79ef\u6211\u4eec\u53ef\u4ee5\u53d1\u73b0\u53c9\u51fa\u7684\u65b9\u5411\u662f\u6b63\u671d\u4e0a\u7684\uff08\u56fe\u4e00\uff09\uff0c\u800c\u7528\u53f3\u624b\u87ba\u65cb\u5b9a\u5219b\u5411\u91cf\u5230a\u5411\u91cf\u7684\u53c9\u79ef\u53c9\u51fa\u7684\u65b9\u5411\u662f\u6b63\u671d\u4e0b\u7684\uff0c\u8fd9\u5c31\u662f\u4e3a\u4ec0\u4e48a x b=-b x a\u3002\u5411\u91cf\u7684\u53c9\u4e58\u516c\u5f0f:(x1,y1,z1)X(x2,y2,z2)=(y1z2-y2z1, z1x2-z2y1, x1y2-x2y1)\u4e4b\u524d\u4e5f\u63d0\u5230\u4e86\uff0c\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u53c9\u79ef\u53bb\u5224\u65ad\u4e00\u4e2a\u70b9\u662f\u5426\u5728\u4e09\u89d2\u5f62\u5185\uff0c\u4e3e\u4e2a\u4f8b\u5b50\uff08\u56fe2\uff09\uff1a\u00a0<br \/><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042511574\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><br \/>\u56fe1\u00a0\u00a0<br \/><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042511575\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><br \/>\u56fe2\u00a0\u4e09\u89d2\u5f62\u7684\u65b9\u5411\u662f\u9006\u65f6\u9488\u7684\uff0c\u4ece\u5411\u91cfAB\u53c9\u5230\u5411\u91cfAP\u53c9\u51fa\u6765\u7684\u65b9\u5411\u662f-z,\u8bf4\u660eP\u70b9\u5728AB\u7684\u5de6\u4fa7\uff1b\u4ece\u5411\u91cfBC\u53c9\u5230\u5411\u91cfBP\u53c9\u51fa\u6765\u7684\u65b9\u5411\u662f- z,\u8bf4\u660eP\u70b9\u5728BC\u7684\u5de6\u4fa7;\u4ece\u5411\u91cfCA\u53c9\u5230\u5411\u91cfCP\u53c9\u51fa\u6765\u7684\u65b9\u5411\u662f-z,\u8bf4\u660eP\u70b9\u5728AC\u7684\u5de6\u4fa7,\u8fd9\u5c31\u8bf4\u660eP\u70b9\u5728\u4e09\u89d2\u5f62\u7684\u5185\u90e8\u3002\u56e0\u4e3a\u5982\u679c\u4e0d\u5728\u7684\u8bdd\u90a3\u4e48\u81f3\u5c11\u5b58\u5728\u4e00\u6761\u8fb9\u4f7f\u5f97P\u70b9\u5728\u53f3\u4fa7\uff08\u4e09\u89d2\u5f62\u662f\u987a\u65f6\u9488\u4e5f\u6ca1\u6709\u95ee\u9898\uff0cP\u70b9\u90fd\u5728\u4e09\u89d2\u5f62\u7684\u53f3\u8fb9\uff0c\u6211\u4eec\u53ea\u8981\u4fdd\u8bc1P\u70b9\u4e00\u76f4\u5728\u4e09\u6761\u8fb9\u7684\u5de6\u8fb9\u6216\u8005\u53f3\u8fb9\u5c31\u53ef\u4ee5\u8bf4\u5b83\u5728\u4e09\u89d2\u5f62\u7684\u5185\u90e8\uff09\u3002\u8fd9\u91cc\u6ce8\u610f\uff0c\u56e0\u4e3a\u662f\u6b63\u4ea4\u6295\u5f71\uff0c\u6240\u4ee5\u6211\u4eec\u53ea\u8003\u8651\u5728\u6295\u5f71\u5e73\u9762\uff08xy\u9762\uff09\u4e0a\u7684\u50cf\u7d20\u70b9\u662f\u5426\u5728\u7a7a\u95f4\u4e09\u89d2\u5f62\u5728\u8be5\u9762\u4e0a\u7684\u6295\u5f71\u4e09\u89d2\u5f62\u5185\u5373\u53ef\uff0c\u5373z\u53ef\u89c6\u4e3a0\u3002\u4ee3\u7801\uff1a    static boolean sameSide(Vertex A, Vertex B, Vertex C, Vertex p){<\/p>\n<pre><code>    Vertex V1V2 = new Vertex(B.x - A.x,B.y - A.y,B.z - A.z);\n    Vertex V1V3 = new Vertex(C.x - A.x,C.y - A.y,C.z - A.z);\n    Vertex V1P = new Vertex(p.x - A.x,p.y - A.y,p.z - A.z);\n\n    \/\/V1V2\u5411\u91cf\u4e0eV1V3\u7684\u53c9\u79ef\u5982\u679c\u548cV1V2\u5411\u91cf\u4e0eV1p\u7684\u53c9\u79ef\u76f8\u540c\u5219\u5728\u540c\u4e00\u4fa7\u3002\n    \/\/\u53ea\u7528\u5224\u65adz\u7684\u65b9\u5411\n    double V1V2CrossV1V3 = V1V2.x * V1V3.y - V1V3.x * V1V2.y;\n    double V1V2CrossP = V1V2.x * V1P.y - V1P.x * V1V2.y;\n\n    return V1V2CrossV1V3 * V1V2CrossP &gt;= 0;\n}\u5b9e\u73b0\u73b0\u5728\u6211\u4eec\u53ef\u4ee5\u77e5\u9053\u4e00\u4e2a\u70b9\u50cf\u7d20\u662f\u5426\u9700\u8981\u8fdb\u884c\u6e32\u67d3\u4e86\uff0c\u73b0\u5728\u8981\u505a\u7684\u5c31\u662f\u904d\u5386\u8303\u56f4\u5185\u6240\u6709\u7684\u50cf\u7d20\u70b9\uff0c\u5224\u65ad\u5b83\u4eec\u662f\u5426\u9700\u8981\u8fdb\u884c\u6e32\u67d3\u3002\u8865\u5168\u6211\u4eec\u7684\u4ee3\u7801\uff1a                for (Triangle t : tris) {\n                Vertex v1 = transform.transform(t.v1);\n                Vertex v2 = transform.transform(t.v2);\n                Vertex v3 = transform.transform(t.v3);\n                v1.x += getWidth() \/ 2.0;\n                v1.y += getHeight() \/ 2.0;\n                v2.x += getWidth() \/ 2.0;\n                v2.y += getHeight() \/ 2.0;\n                v3.x += getWidth() \/ 2.0;\n                v3.y += getHeight() \/ 2.0;\n                \/\/ \u8ba1\u7b97\u9700\u8981\u5904\u7406\u7684\u8303\u56f4\n                int minX = (int) Math.max(0, Math.ceil(Math.min(v1.x, Math.min(v2.x, v3.x))));\n                int maxX = (int) Math.min(img.getWidth() - 1,\n                        Math.floor(Math.max(v1.x, Math.max(v2.x, v3.x))));\n                int minY = (int) Math.max(0, Math.ceil(Math.min(v1.y, Math.min(v2.y, v3.y))));\n                int maxY = (int) Math.min(img.getHeight() - 1,\n                        Math.floor(Math.max(v1.y, Math.max(v2.y, v3.y))));\n\n                for (int y = minY; y &lt; = maxY; y++) {\n                    for (int x = minX; x &lt; = maxX; x++) {\n                        Vertex p = new Vertex(x,y,0);\n                        \/\/\u9488\u5bf9\u6bcf\u4e2a\u9876\u70b9\u5224\u65ad\u4e00\u6b21\n                        boolean V1 = sameSide(v1,v2,v3,p);\n                        boolean V2 = sameSide(v2,v3,v1,p);\n                        boolean V3 = sameSide(v3,v1,v2,p);\n                        if (V3 &amp;&amp; V2 &amp;&amp; V1) {\n                            img.setRGB(x, y, t.color.getRGB());\n                        }\n                    }\n                }\n            }\n\n            g2.drawImage(img, 0, 0, null);<\/code><\/pre>\n<p>\u6765\u770b\u770b\u5b9e\u9645\u7684\u6548\u679c\u5427\uff01\u00a0<br \/><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042511576\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><br \/>\u00a0\u76f8\u4fe1\u4f60\u5df2\u7ecf\u53d1\u73b0\u95ee\u9898\u4e86\uff1a\u84dd\u8272\u4e09\u89d2\u5f62\u603b\u662f\u5728\u5176\u4ed6\u4e09\u89d2\u5f62\u4e4b\u4e0a\u3002\u53d1\u751f\u8fd9\u79cd\u60c5\u51b5\u662f\u56e0\u4e3a\u6211\u4eec\u76ee\u524d\u6b63\u5728\u4e00\u4e2a\u63a5\u4e00\u4e2a\u5730\u7ed8\u5236\u4e09\u89d2\u5f62\uff0c\u800c\u84dd\u8272\u4e09\u89d2\u5f62\u662f\u6700\u540e\u4e00\u4e2a &#8211; \u56e0\u6b64\u5b83\u88ab\u7ed8\u5236\u5728\u6240\u6709\u5176\u4ed6\u4e09\u89d2\u5f62\u4e4b\u4e0a\u3002\u8fd9\u5c31\u5f15\u51fa\u4e86\u4e0b\u4e00\u4e2a\u6982\u5ff5\uff1az-buffer \uff08\u6216\u6df1\u5ea6\u7f13\u51b2\u533a\uff09\u7684\u6982\u5ff5z-buffer\u5b83\u7684\u4f5c\u7528\u662f\uff1a\u5728\u5149\u6805\u5316\u671f\u95f4\u6784\u5efa\u4e00\u4e2a\u4e2d\u95f4\u6570\u7ec4\uff0c\u8be5\u6570\u7ec4\u5c06\u5b58\u50a8\u4efb\u4f55\u7ed9\u5b9a\u50cf\u7d20\u5904\u6700\u540e\u770b\u5230\u7684\u5143\u7d20\u7684\u6df1\u5ea6\u3002\u5149\u6805\u5316\u4e09\u89d2\u5f62\u65f6\uff0c\u6211\u4eec\u5c06\u68c0\u67e5\u50cf\u7d20\u6df1\u5ea6\u662f\u5426\u5c0f\u4e8e(\u56e0\u4e3a\u6b63\u5411\u662f-z\u65b9\u5411)\u4e4b\u524d\u770b\u5230\u7684\uff0c\u5e76\u4e14\u4ec5\u5728\u50cf\u7d20\u9ad8\u4e8e\u5176\u4ed6\u50cf\u7d20\u65f6\u5bf9\u5176\u8fdb\u884c\u7740\u8272\u3002double[] zBuffer = new double[img.getWidth() * img.getHeight()];<br \/>\/\/ initialize array with extremely far away depths<br \/>for (int q = 0; q &lt; zBuffer.length; q++) {<\/p>\n<pre><code>zBuffer[q] = Double.NEGATIVE_INFINITY;<\/code><\/pre>\n<p>}<\/p>\n<p>for (Triangle t : tris) {<\/p>\n<pre><code>\/\/ \u4e4b\u524d\u7684\u4ee3\u7801\nif (V3 &amp;&amp; V2 &amp;&amp; V1) {\ndouble depth = v1.z + v2.z + v3.z;\nint zIndex = y * img.getWidth() + x;\nif (zBuffer[zIndex] &lt; depth) {\n  img.setRGB(x, y, t.color.getRGB());\n  zBuffer[zIndex] = depth;\n  }\n}<\/code><\/pre>\n<p>}\u6548\u679c\uff1a\u00a0<br \/><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042511577\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><br \/>\u00a0\u5230\u76ee\u524d\u4e3a\u6b62\u6e32\u67d3\u7ba1\u7ebf\u770b\u8d77\u6765\u4e00\u5207\u6b63\u5e38\u4e86\uff0c\u4f46\u662f\u8fd8\u7f3a\u5c11\u4e86\u4e00\u4e2a\u91cd\u8981\u7684\u6548\u679c\uff1a\u9634\u5f71\u9634\u5f71-\u5e73\u9762\u7740\u8272\u5728\u8ba1\u7b97\u673a\u56fe\u5f62\u5b66\u4e2d\u7684\u201c\u9634\u5f71\u201d\uff0c\u53ef\u4ee5\u7b80\u5355\u89e3\u91ca\u4e3a&#8211;\u6839\u636e\u8868\u9762\u7684\u89d2\u5ea6\u548c\u4e0e\u706f\u5149\u7684\u8ddd\u79bb\u6765\u6539\u53d8\u8868\u9762\u7684\u989c\u8272\u3002\u6700\u7b80\u5355\u7684\u7740\u8272\u5f62\u5f0f\u662f\u5e73\u9762\u7740\u8272\u3002\u5b83\u53ea\u8003\u8651\u8868\u9762\u6cd5\u7ebf\u548c\u5149\u6e90\u65b9\u5411\u4e4b\u95f4\u7684\u89d2\u5ea6\u3002\u60a8\u53ea\u9700\u8981\u627e\u5230\u8fd9\u4e24\u4e2a\u5411\u91cf\u4e4b\u95f4\u7684\u89d2\u5ea6\u4f59\u5f26\u5e76\u5c06\u989c\u8272\u4e58\u4ee5\u7ed3\u679c\u503c\u3002\u8fd9\u79cd\u65b9\u6cd5\u975e\u5e38\u7b80\u5355\u4e14\u5feb\u901f\uff0c\u56e0\u6b64\u5f53\u66f4\u9ad8\u7ea7\u7684\u7740\u8272\u6280\u672f\u8ba1\u7b97\u6210\u672c\u592a\u9ad8\u65f6\uff0c\u901a\u5e38\u7528\u5b83\u505a\u9ad8\u901f\u6e32\u67d3\u3002\u6cd5\u5411\u91cf\u6cd5\u5411\u91cf\uff0c\u662f\u7a7a\u95f4\u89e3\u6790\u51e0\u4f55\u7684\u4e00\u4e2a\u6982\u5ff5\uff0c\u5782\u76f4\u4e8e\u5e73\u9762\u7684\u76f4\u7ebf\u6240\u8868\u793a\u7684\u5411\u91cf\u4e3a\u8be5\u5e73\u9762\u7684\u6cd5\u5411\u91cf\u3002\u6cd5\u5411\u91cf\u9002\u7528\u4e8e\u89e3\u6790\u51e0\u4f55\u3002\u7531\u4e8e\u7a7a\u95f4\u5185\u6709\u65e0\u6570\u4e2a\u76f4\u7ebf\u5782\u76f4\u4e8e\u5df2\u77e5\u5e73\u9762\uff0c\u56e0\u6b64\u4e00\u4e2a\u5e73\u9762\u90fd\u5b58\u5728\u65e0\u6570\u4e2a\u6cd5\u5411\u91cf\uff08\u5305\u62ec\u4e24\u4e2a\u5355\u4f4d\u6cd5\u5411\u91cf\uff09\u3002\u8fd8\u8bb0\u5f97\u4e4b\u524d\u7684\u53c9\u79ef\u5417\uff0c\u6211\u4eec\u53ea\u9700\u8981\u9664\u6389\u81ea\u8eab\u7684\u6a21\u957f\u5373\u53ef\u5f97\u5230\u4e00\u4e2a\u6cd5\u5411\u91cf    Vertex ab = new Vertex(v2.x &#8211; v1.x, v2.y &#8211; v1.y, v2.z &#8211; v1.z);<\/p>\n<pre><code>Vertex ac = new Vertex(v3.x - v1.x, v3.y - v1.y, v3.z - v1.z);\n\/\/\u6cd5\u5411\u91cf\nVertex norm = new Vertex(\n     ab.y * ac.z - ab.z * ac.y,\n     ab.z * ac.x - ab.x * ac.z,\n     ab.x * ac.y - ab.y * ac.x\n);\ndouble normalLength =\n    Math.sqrt(norm.x * norm.x + norm.y * norm.y + norm.z * norm.z);\nnorm.x \/= normalLength;\nnorm.y \/= normalLength;\nnorm.z \/= normalLength;\u70b9\u79ef\u70b9\u79ef\u7684\u5b9a\u4e49\u8fd8\u662f\u6bd4\u8f83\u62bd\u8c61\u7684\uff0c\u6211\u4eec\u53ea\u9700\u8981\u4e86\u89e3\u5176\u5728\u4e09\u7ef4\u7a7a\u95f4\u4e2d\u7684\u51e0\u4f55\u610f\u4e49\uff0c\u4ee5\u53ca\u516c\u5f0f\u5373\u53ef\u3002\u516c\u5f0f\uff1a\u00a0<\/code><\/pre>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042511578\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><br \/>\u00a0\u51e0\u4f55\u610f\u4e49\uff1a\u7b2c\u4e00\u4e2a\u5411\u91cf\u6295\u5f71\u5230\u7b2c\u4e8c\u4e2a\u5411\u91cf\u4e0a\uff08\u8fd9\u91cc\uff0c\u5411\u91cf\u7684\u987a\u5e8f\u662f\u4e0d\u91cd\u8981\u7684\uff0c\u70b9\u79ef\u8fd0\u7b97\u662f\u53ef\u4ea4\u6362\u7684\uff09\uff0c\u7136\u540e\u901a\u8fc7\u9664\u4ee5\u5b83\u4eec\u7684\u6807\u91cf\u957f\u5ea6\u6765\u201c\u6807\u51c6\u5316\u201d\u3002\u8fd9\u6837\uff0c\u8fd9\u4e2a\u5206\u6570\u4e00\u5b9a\u662f\u5c0f\u4e8e\u7b49\u4e8e1\u7684\uff0c\u53ef\u4ee5\u7b80\u5355\u5730\u8f6c\u5316\u6210\u4e00\u4e2a\u89d2\u5ea6\u503c\u5373\uff1a\u00a0<br \/><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042511579\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><br \/>\u00a0\u5149\u6e90\u4e3a\u4e86\u7b80\u5355\u8d77\u89c1\uff0c\u6211\u4eec\u4f7f\u7528\u5b9a\u5411\u5149\u6e90\uff08\u5149\u76f4\u63a5\u4f4d\u4e8e\u76f8\u673a\u540e\u9762\u65e0\u9650\u8fdc\u7684\u8ddd\u79bb\uff09\uff0c\u5149\u6e90\u65b9\u5411\u5c06\u662f[0 0 1]\u3002\u73b0\u5728\u6211\u4eec\u9700\u8981\u8ba1\u7b97\u4e09\u89d2\u5f62\u6cd5\u5411\u91cf\u548c\u5149\u7ebf\u65b9\u5411\u4e4b\u95f4\u7684\u4f59\u5f26\uff0c\u4f5c\u4e3a\u9634\u5f71\u7684\u7cfb\u6570\u3002\u5728\u8be5\u573a\u666f\u4e0b\u6211\u4eec\u53ef\u4ee5\u5f97\u5230\uff1a\u00a0<br \/><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042511580\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><br \/>\u00a0\u5176\u4e2dA\u4e3a\u4e09\u89d2\u5f62\u7684\u6cd5\u5411\u91cf\uff0cB\u4e3a\u5149\u7ebf\u3002\u00a0<br \/><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042511581\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><br \/>\u00a0\u5316\u4e3a\u4ee3\u7801\u975e\u5e38\u7b80\u5355\uff1adouble angleCos = Math.abs(norm.z);\u4e3a\u4e86\u7b80\u5355\u5904\u7406\uff0c\u5728\u8fd9\u91cc\u6211\u4eec\u4e0d\u5173\u7cfb\u4e09\u89d2\u5f62\u662f\u5426\u9762\u5411\u76f8\u673a\uff0c\u4f46\u5b9e\u9645\u4e0a\u662f\u9700\u8981\u6839\u636e\u5149\u7ebf\u8ffd\u8e2a\u6765\u5224\u65ad\u7684\uff08\u4e0b\u4e00\u7bc7\u5149\u7ebf\u8ffd\u8e2a\u4e2d\u6211\u4eec\u518d\u6765\u5b8c\u5584\u5b83\uff09\u3002\u73b0\u5728\u6211\u4eec\u7684\u5f97\u5230\u4e86\u9634\u5f71\u7cfb\u6570\uff0c\u6240\u4ee5\u53ef\u4ee5\u7b80\u5355\u7684\u5904\u7406\u4e3a\uff1apublic static Color getShade(Color color, double shade) {<\/p>\n<pre><code>int red = (int) (color.getRed() * shade);\nint green = (int) (color.getGreen() * shade);\nint blue = (int) (color.getBlue() * shade);\nreturn new Color(red, green, blue);<\/code><\/pre>\n<p>}\u6548\u679c\uff1a\u00a0<br \/><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042511582\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><br \/>\u00a0\u53ef\u4ee5\u770b\u5230\uff0c\u867d\u7136\u6709\u4e86\u9634\u5f71\u4f46\u662f\u8870\u51cf\u7684\u592a\u5feb\uff0c\u8fd9\u662f\u56e0\u4e3aJava\u4f7f\u7528\u7684\u662fsRGB \u989c\u8272\u7a7a\u95f4\uff0c\u6240\u4ee5\u6211\u4eec\u9700\u8981\u5c06\u6bcf\u79cd\u989c\u8272\u4ece\u7f29\u653e\u683c\u5f0f\u8f6c\u6362\u4e3a\u7ebf\u6027\u683c\u5f0f\uff0c\u5e94\u7528\u9634\u5f71\uff0c\u7136\u540e\u518d\u8f6c\u6362sRGB\uff0c\u4f46\u662f\u5b9e\u9645\u7684\u8f6c\u6362\u8fc7\u7a0b\u975e\u5e38\u590d\u6742\uff0c\u6211\u4eec\u53ea\u505a\u7b80\u5355\u7684\u8fd1\u4f3c\uff1a\u5148\u505a2.2\u6b21\u5e42\u5230\u7ebf\u6027\u7a7a\u95f4\u8ba1\u7b97\u9634\u5f71\uff0c\u7136\u540e\u5728\u505a1\/2.2\u6b21\u5e42\u56de\u5230sRGB\u7a7a\u95f4\u53c2\u6570\u4f9d\u636e\u5728\u8fd9\u7bc7\u6587\u7ae0\uff1aGamma\u3001Linear\u3001sRGB \u548cUnity Color Space\uff0c\u4f60\u771f\u61c2\u4e86\u5417\uff1f\u73b0\u5728\u6211\u4eec\u6765\u6539\u8fdb\u4e0b\u4ee3\u7801\uff1a    public static Color getShade(Color color, double shade) {<\/p>\n<pre><code>    double redLinear = Math.pow(color.getRed(), 2.2) * shade;\n    double greenLinear = Math.pow(color.getGreen(), 2.2) * shade;\n    double blueLinear = Math.pow(color.getBlue(), 2.2) * shade;\n\n    int red = (int) Math.pow(redLinear, 1 \/ 2.2);\n    int green = (int) Math.pow(greenLinear, 1 \/ 2.2);\n    int blue = (int) Math.pow(blueLinear, 1 \/ 2.2);\n\n    return new Color(red, green, blue);\n}\u6548\u679c\u5bf9\u6bd4\uff1a\u00a0<\/code><\/pre>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042511583\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042511584\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><br \/>\u00a0\u66f2\u9762\u7269\u4f53\u7684\u5e73\u9762\u6211\u4eec\u53ef\u4ee5\u7528\u4e09\u89d2\u5f62\u7b80\u5355\u7684\u62fc\u63a5\u8fdb\u884c\u8868\u793a\uff0c\u90a3\u4e48\u66f2\u9762\u8be5\u5982\u4f55\u4f7f\u7528\u4e09\u89d2\u5f62\u8868\u793a\u5462\uff1f\u4e00\u79cd\u65b9\u5f0f\u662f\u901a\u8fc7\u5e73\u9762\u7684\u62c6\u5206-\u81a8\u80c0\u6765\u505a\u5230\u3002\u62c6\u5206\u4e00\u4e2a\u4e09\u89d2\u5f62\u53ef\u4ee5\u901a\u8fc7\u4e09\u4e2a\u8fb9\u7684\u4e2d\u70b9\uff0c\u6765\u62c6\u5206\u62104\u4e2a\u5c0f\u4e09\u89d2\u5f62\uff0c\u5982\u4e0b\u56fe\uff1a\u00a0<br \/><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042511585\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><br \/>\u00a0\u901a\u8fc7\u4ee3\u7801\u53ef\u4ee5\u8868\u793a\u4e3a\uff1a List&lt; Triangle&gt; result = new ArrayList&lt;&gt;();<\/p>\n<pre><code>    for (Triangle t : tris) {\n            Vertex m1 =\n                    new Vertex((t.v1.x + t.v2.x) \/ 2, (t.v1.y + t.v2.y) \/ 2, (t.v1.z + t.v2.z) \/ 2);\n            Vertex m2 =\n                    new Vertex((t.v2.x + t.v3.x) \/ 2, (t.v2.y + t.v3.y) \/ 2, (t.v2.z + t.v3.z) \/ 2);\n            Vertex m3 =\n                    new Vertex((t.v1.x + t.v3.x) \/ 2, (t.v1.y + t.v3.y) \/ 2, (t.v1.z + t.v3.z) \/ 2);\n            result.add(new Triangle(t.v1, m1, m3, t.color,true));\n            result.add(new Triangle(t.v2, m1, m2, t.color,true));\n            result.add(new Triangle(t.v3, m2, m3, t.color,true));\n            result.add(new Triangle(m1, m2, m3, t.color,true));\n        }\n    }\u81a8\u80c0\u73b0\u5728\u6211\u4eec\u83b7\u5f97\u4e86\u4e00\u4e9b\u66f4\u5c0f\u7684\u4e09\u89d2\u5f62\uff0c\u73b0\u5728\u8981\u505a\u7684\u5c31\u662f\u8ba9\u5b83\u4eec\u7684\u9876\u70b9\u81a8\u80c0\u5230\u5706\u5f27\u6240\u5728\u7684\u4f4d\u7f6e\u4e0a\u3002\u8ba9\u6211\u4eec\u5148\u7528\u4e8c\u7ef4\u7a7a\u95f4\u7684\u7b80\u5355\u573a\u666f\u6765\u63cf\u8ff0\u8fd9\u4e00\u8fc7\u7a0b\uff1a\u00a0<\/code><\/pre>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042511586\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><br \/>\u00a0\u901a\u8fc7\u4e0a\u56fe\u53ef\u77e5\uff1a\uff08\u539f\u4f4d\u7f6e\u4e0e\u539f\u70b9\u7684\u8ddd\u79bb\uff1aL\uff09\/\uff08\u4e09\u89d2\u5f62\u9876\u70b9\u5230\u539f\u70b9\u7684\u8ddd\u79bb\uff1ar\uff09\u83b7\u5f97\u4e00\u4e2a\u6bd4\u4f8b\u7cfb\u6570\uff1b\u7136\u540e\u7528\u5176\u5f53\u524d\u5750\u6807x0\uff0cy0\u5206\u522b\u9664\u4ee5\u8be5\u7cfb\u6570\u5373\u53ef\u3002\u8ddd\u79bb\u516c\u5f0f\uff1a\u00a0<br \/><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042511587\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><br \/>\u00a0\u5b9e\u9645\u4ee3\u7801\u5982\u4e0b\uff1a        for (Triangle t : result) {<\/p>\n<pre><code>            for (Vertex v : new Vertex[]{t.v1, t.v2, t.v3}) {\n                double l = Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z) \/ Math.sqrt(30000);\n                v.x \/= l;\n                v.y \/= l;\n                v.z \/= l;\n            }\n    }\u5176\u4e2d3000\u662f\u67d0\u4e00\u4e09\u89d2\u5f62\u9876\u70b9\u5230\u539f\u70b9\u7684\u8ddd\u79bb\u4f8b\u5982\u7528\uff08100\uff0c100\uff0c100\uff09\u8fd9\u4e2a\u9876\u70b9\u4e3a\u4f8b\uff1a\uff08100100+100100+100*100\uff09=30000\u6548\u679c\u8ba9\u6211\u4eec\u5148\u6765\u9488\u5bf9\u4e00\u4e2a\u9762\u62c6\u52065\u6b21\u7136\u540e\u81a8\u80c0\uff0c\u770b\u4e0b\u6548\u679c\uff1a\u00a0<\/code><\/pre>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042511588\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><br \/>\u00a0\u56db\u4e2a\u9762\u5168\u90e8\u81a8\u80c0\u5373\u53ef\u5f97\u5230\u4e00\u4e2a\u5706\u5f62\uff1a\u00a0<br \/><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042511589\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><br \/>\u00a0\u7136\u540e\u6211\u4eec\u51cf\u5c11\u62c6\u5206\u6b21\u6570\uff082\u6b21\uff09\u770b\u4e0b\u6548\u679c\uff1a\u00a0<br \/><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000042511590\" alt=\"\u56fe\u7247\" title=\"\u56fe\u7247\" loading=\"lazy\"><br \/>\u00a0\u7ed3\u675f\u6536\u5de5\uff01\u53c2\u8003\u9879\u76ee\uff1a<a href=\"https:\/\/gist.github.com\/Rogach\/f3dfd457d7ddb5fcfd99\/4f2aaf20a468867dc195cdc08a02e5705c2cc95c\">https:\/\/gist.github.com\/Rogac&#8230;<\/a>\u63a8\u8350\u9605\u8bfb\uff1a<a href=\"https:\/\/link.segmentfault.com\/?enc=2OkE229oZOfFfEQp3rPQXA%3D%3D.FASCj%2B44raGJEGnq2qN3m07lD%2FbgCGiRwS6KiPEMhC72yySUWSDZWo3UZRjHcmjcP7NeTi7WpDrWNkgBEyOk7w%3D%3D\" rel=\"nofollow\">https:\/\/www.cnblogs.com\/BigFe&#8230;<\/a>\u3001Linear\u3001sRGB \u548cUnity Color Space\uff0c\u4f60\u771f\u61c2\u4e86\u5417\uff1f<a href=\"https:\/\/link.segmentfault.com\/?enc=bYP7DydXhPjGhhPhDwKJsA%3D%3D.%2Ff5aZ3aGRRkT32Eur4pbP9aNYPGPpqjel0tjJ9egF9jiJG5PKu%2BTcoe7C5z9eYHl\" rel=\"nofollow\">https:\/\/zhuanlan.zhihu.com\/p\/&#8230;<\/a>\u63a8\u8350\u9605\u8bfb\uff1a1.\u4ee3\u7801\u5708\u590d\u6742\u5ea6\u6cbb\u7406\u5c0f\u7ed32.\u5982\u4f55\u5199\u51fa\u6709\u6548\u7684\u5355\u5143\u6d4b\u8bd53. java\u5e94\u7528\u63d0\u901f(\u901f\u5ea6\u4e0e\u6fc0\u60c5)\u00a0\u300a\u3008Java\u5f00\u53d1\u624b\u518c\uff08\u6cf0\u5c71\u7248\uff09\u3009\u7075\u9b4213\u95ee\u300b\u00a0\u4e00\u7ebf\u5927\u5382\u600e\u4e48\u7528Java\uff1f\u770b\u5343\u4e07\u9605\u8bfb\u91cf\u6280\u672f\u535a\u4e3b\u7ed9\u4f60\u5206\u6790\uff01\u76f8\u4fe1\u5927\u5bb6\u90fd\u8bfb\u8fc7\u300aJava\u5f00\u53d1\u624b\u518c\u300b\u6cf0\u5c71\u7248\uff0c\u6cf0\u5c71\u7248\u65b0\u589e5\u6761\u65e5\u671f\u65f6\u95f4\u89c4\u7ea6\uff1b\u65b0\u589e2\u6761\u8868\u522b\u540dsql\u89c4\u7ea6\uff1b\u65b0\u589e\u7edf\u4e00\u9519\u8bef\u7801\u89c4\u7ea6\u3002\u800c\u300a\u3008Java\u5f00\u53d1\u624b\u518c\uff08\u6cf0\u5c71\u7248\uff09\u3009\u7075\u9b4213\u95ee\u300b\u5219\u662f\u4e3a\u4e86\u5e2e\u52a9\u5927\u5bb6\u66f4\u597d\u7684\u7406\u89e3\u8fd9\u4e9b\u89c4\u7ea6\u80cc\u540e\u7684\u539f\u7406\uff0c\u4ece\u95ee\u9898\u91cd\u73b0\u5230\u539f\u7406\u5206\u6790\u518d\u5230\u89e3\u51b3\u95ee\u9898\uff0c\u5168\u7f51\u5343\u4e07\u9605\u8bfb\u91cf\u6280\u672f\u535a\u4e3bHollis\u5e26\u4f60\u5256\u6790\u963f\u91cc\u5df4\u5df4\u5f00\u53d1\u7ec6\u8282\u3002\u70b9\u51fb\u8fd9\u91cc\uff0c\u67e5\u770b\u8be6\u60c5\u3002\u539f\u6587\u94fe\u63a5\uff1a<a href=\"https:\/\/link.segmentfault.com\/?enc=avxSQoGEMkAfF8vjR4a2cw%3D%3D.6B3nSUTW%2B7HubsUZJFor5JSCn7ShOOtM56OBMO0pft%2BW8sITBcHI6M5k0jM4X5hC\" rel=\"nofollow\">https:\/\/click.aliyun.com\/m\/10&#8230;<\/a>\u672c\u6587\u4e3a\u963f\u91cc\u4e91\u539f\u521b\u5185\u5bb9\uff0c\u672a\u7ecf\u5141\u8bb8\u4e0d\u5f97\u8f6c\u8f7d\u3002<\/p>\n<p><a href=\"https:\/\/segmentfault.com\/a\/1190000042511562\">https:\/\/segmentfault.com\/a\/1190000042511562<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u7b80\u4ecb\uff1a\u00a0\u5bf9\u4e8e\u975e\u6e32\u67d3\u5f15\u64ce\u76f8\u5173\u5de5\u4f5c\u7684\u5f00\u53d1\u8005\u6765\u8bf4\uff0c\u53ef\u80fd\u8ba4\u4e3a\u5373\u4f7f\u6784\u5efa\u6700\u7b80\u5355\u76843D\u7a0b\u5e8f\u4e5f\u975e\u5e38\u56f0\u96be\uff0c\u4f46\u4e8b\u5b9e\u4e0a\u5e76\u975e\u5982\u6b64\uff0c\u672c\u7bc7 [&hellip;]<\/p>\n","protected":false},"author":0,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[],"tags":[],"class_list":["post-10006542","post","type-post","status-publish","format-standard","hentry"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10006542","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10006542"}],"version-history":[{"count":0,"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10006542\/revisions"}],"wp:attachment":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10006542"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=10006542"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=10006542"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}