3

我有孔(和未开孔)的轮廓,我尝试使用 Three.js 挤出,但控制台输出:

警告,无法对多边形进行三角剖分!

并且产生的形状是扭曲的:

在此处输入图像描述

这是原始的 2D 形状:

在此处输入图像描述

代码位于http://jsbin.com/odufih/1/edit。按“运行 Javascript”。

多边形按exPolygons数组排序,其中每个成员都是一个exPolygon对象,它具有成员outer(点数组​​)和holes(点数组数组),如下所示:

var expolygons = [
  {
    "outer": [point1,point2,point3], 
    "holes": [ [point1,point2,point3], [point1,point2,point3] ] 
  },
  { 
    "outer": [point1,point2,point3], 
    "holes": [ [point1,point2,point3], [point1,point2,point3] ] 
  },
  {
    "outer": [point1,point2,point3], 
    "holes": [ [point1,point2,point3], [point1,point2,point3] ] 
  } 
];

这是实际的 exPolygons 数组:

var polys = [{"outer":[{"X":103.181,"Y":220.799},{"X":104.364,"Y":190.337},{"X":99.849,"Y":182.369},{"X":104.803,"Y":183.405},{"X":105.069,"Y":164.693},{"X":101.856,"Y":144.889},{"X":96.602,"Y":131.47},{"X":94.137,"Y":128.41},{"X":87.938,"Y":126.121},{"X":68.853,"Y":124.712},{"X":55.191,"Y":137.809},{"X":54.012,"Y":135.274},{"X":57.142,"Y":133.283},{"X":55.261,"Y":131.519},{"X":49.807,"Y":133.03},{"X":48.27,"Y":137.16},{"X":48.762,"Y":142.672},{"X":47.331,"Y":146.85},{"X":44.672,"Y":148.789},{"X":45.573,"Y":135.814},{"X":43.345,"Y":140.126},{"X":42.719,"Y":137.016},{"X":36.671,"Y":141.24},{"X":33.291,"Y":130.355},{"X":37.363,"Y":127.208},{"X":36.772,"Y":122.604},{"X":39.952,"Y":125.467},{"X":42.663,"Y":124.482},{"X":44.19,"Y":120.736},{"X":43.192,"Y":117.816},{"X":36.355,"Y":119.368},{"X":34.878,"Y":115.119},{"X":38.146,"Y":113.954},{"X":35.52,"Y":109.941},{"X":36.896,"Y":107.535},{"X":40.517,"Y":109.3},{"X":48.975,"Y":99.851},{"X":54.198,"Y":97.87},{"X":55.123,"Y":96.323},{"X":53.293,"Y":92.238},{"X":47.891,"Y":91.602},{"X":44.017,"Y":97.261},{"X":43.072,"Y":95.066},{"X":44.522,"Y":90.935},{"X":44.008,"Y":88.647},{"X":40.073,"Y":88.1},{"X":43.185,"Y":74.685},{"X":45.661,"Y":77.401},{"X":52.455,"Y":76.115},{"X":52.093,"Y":71.941},{"X":48.26,"Y":65.59},{"X":52.041,"Y":62.795},{"X":54.785,"Y":62.356},{"X":60.725,"Y":53.764},{"X":64.398,"Y":54.837},{"X":61.601,"Y":44.213},{"X":62.183,"Y":42.429},{"X":68.685,"Y":38.57},{"X":70.857,"Y":43.864},{"X":75.301,"Y":36.658},{"X":79.74,"Y":34.903},{"X":81.903,"Y":30.601},{"X":86.186,"Y":30.127},{"X":96.983,"Y":24.682},{"X":99.042,"Y":24.701},{"X":102.3,"Y":28.63},{"X":103.329,"Y":25.855},{"X":118.837,"Y":26.405},{"X":120.026,"Y":29.068},{"X":121.061,"Y":27.36},{"X":125.084,"Y":25.838},{"X":126.883,"Y":26.514},{"X":127.849,"Y":38.57},{"X":128.615,"Y":33.388},{"X":130.273,"Y":31.36},{"X":131.323,"Y":33.438},{"X":132.884,"Y":29.553},{"X":134.28,"Y":32.955},{"X":133.89,"Y":37.482},{"X":135.186,"Y":37.093},{"X":138.311,"Y":30.826},{"X":140.772,"Y":37.436},{"X":141.693,"Y":35.85},{"X":144.879,"Y":37.805},{"X":142.882,"Y":42.808},{"X":148.072,"Y":39.964},{"X":157.87,"Y":48.073},{"X":158.349,"Y":54.987},{"X":159.992,"Y":53.247},{"X":165.235,"Y":59.029},{"X":168.358,"Y":68.004},{"X":166.742,"Y":72.543},{"X":165.338,"Y":71.529},{"X":160.255,"Y":72.686},{"X":158.431,"Y":75.073},{"X":161.396,"Y":76.487},{"X":168.524,"Y":74.919},{"X":169.529,"Y":78.059},{"X":168.336,"Y":85.228},{"X":173.242,"Y":81.367},{"X":174.67,"Y":82.369},{"X":173.259,"Y":76.874},{"X":174.359,"Y":75.745},{"X":178.357,"Y":80.253},{"X":179.604,"Y":88.167},{"X":182.692,"Y":88.307},{"X":183.609,"Y":92.202},{"X":182.202,"Y":94.947},{"X":180.434,"Y":95.677},{"X":181.412,"Y":98.679},{"X":183.225,"Y":97.639},{"X":185.774,"Y":116.788},{"X":184.176,"Y":122.163},{"X":185.003,"Y":125.744},{"X":178.737,"Y":137.703},{"X":176.195,"Y":132.677},{"X":178.874,"Y":144.616},{"X":176.53,"Y":145.613},{"X":171.927,"Y":132.208},{"X":159.229,"Y":117.148},{"X":154.959,"Y":115.578},{"X":154.223,"Y":118.482},{"X":151.973,"Y":119.361},{"X":153.848,"Y":123.672},{"X":152.992,"Y":125.585},{"X":151.361,"Y":125.072},{"X":151.736,"Y":135.538},{"X":152.862,"Y":136.284},{"X":153.905,"Y":134.54},{"X":153.711,"Y":137.53},{"X":151.96,"Y":137.511},{"X":146.422,"Y":122.475},{"X":143.737,"Y":118.367},{"X":132.696,"Y":126.829},{"X":117.466,"Y":150.083},{"X":112.725,"Y":162.23},{"X":112.52,"Y":196.304},{"X":115.346,"Y":220.799}],"holes":[[{"X":149.952,"Y":51.338},{"X":150.825,"Y":47.383},{"X":149.554,"Y":48.757}],[{"X":69.191,"Y":54.204},{"X":68.924,"Y":49.128},{"X":67.899,"Y":48.266}],[{"X":117.109,"Y":140.339},{"X":125.864,"Y":116.268},{"X":126.352,"Y":110.58},{"X":122.683,"Y":117.966}],[{"X":104.36,"Y":136.75},{"X":100.006,"Y":83.235},{"X":97.063,"Y":84.608},{"X":95.913,"Y":95.243},{"X":93.732,"Y":101.053},{"X":95.356,"Y":116.686}],[{"X":45.664,"Y":128.24},{"X":48.032,"Y":126.672},{"X":47.016,"Y":123.901},{"X":44.185,"Y":126.829}],[{"X":172.795,"Y":126.642},{"X":172.545,"Y":123.761},{"X":167.545,"Y":118.809}],[{"X":107.355,"Y":55.057},{"X":107.018,"Y":52.308},{"X":106.193,"Y":52.924}],[{"X":179.526,"Y":124.933},{"X":180.705,"Y":124.515},{"X":178.907,"Y":123.02}],[{"X":53.288,"Y":123.566},{"X":59.22,"Y":121.336},{"X":78.45,"Y":119.193},{"X":70.689,"Y":115.628},{"X":62.414,"Y":114.594},{"X":53.318,"Y":118.598},{"X":52.339,"Y":122.518}],[{"X":85.362,"Y":120.083},{"X":86.531,"Y":119.917},{"X":78.853,"Y":106.531},{"X":71.625,"Y":97.485},{"X":71.301,"Y":98.877},{"X":64.513,"Y":98.961},{"X":67.077,"Y":108.022}],[{"X":149.92,"Y":118.838},{"X":150.14,"Y":114.686},{"X":148.165,"Y":115.206},{"X":148.026,"Y":117.129}],[{"X":134.804,"Y":118.44},{"X":140.042,"Y":114.261},{"X":141.194,"Y":111.614},{"X":140.626,"Y":109.57},{"X":136.364,"Y":113.732}],[{"X":180.366,"Y":116.489},{"X":181.073,"Y":115.652},{"X":179.356,"Y":113.954},{"X":178.754,"Y":115.154}],[{"X":90.309,"Y":115.534},{"X":79.772,"Y":93.054},{"X":85.146,"Y":109.227}],[{"X":182.402,"Y":113.665},{"X":182.443,"Y":110.685},{"X":181.359,"Y":111.614}],[{"X":55.341,"Y":111.837},{"X":57.863,"Y":110.873},{"X":60.011,"Y":106.122},{"X":53.019,"Y":111.614}],[{"X":165.02,"Y":111.614},{"X":165.861,"Y":110.999},{"X":164.028,"Y":110.999}],[{"X":130.927,"Y":111.506},{"X":134.03,"Y":106.264},{"X":132.577,"Y":105.091}],[{"X":144.754,"Y":110.413},{"X":147.103,"Y":108.35},{"X":142.043,"Y":106.954}],[{"X":63.015,"Y":109.3},{"X":64.361,"Y":108.284},{"X":62.673,"Y":107.573},{"X":61.917,"Y":108.622}],[{"X":109.357,"Y":106.986},{"X":113.698,"Y":100.241},{"X":115.484,"Y":92.472},{"X":112.667,"Y":84.929},{"X":109.008,"Y":81.867},{"X":107.649,"Y":102.006}],[{"X":54.854,"Y":106.986},{"X":57.571,"Y":102.662},{"X":56.336,"Y":102.669},{"X":54.054,"Y":106.186}],[{"X":179.811,"Y":105.113},{"X":181.698,"Y":103.895},{"X":181.434,"Y":102.679},{"X":178.454,"Y":102.679}],[{"X":108.201,"Y":159.955},{"X":113.362,"Y":134.854},{"X":115.184,"Y":111.846},{"X":114.144,"Y":107.699},{"X":112.611,"Y":109.222},{"X":109.523,"Y":119.341}],[{"X":88.282,"Y":100.121},{"X":90.571,"Y":89.911},{"X":89.545,"Y":85.085},{"X":85.997,"Y":85.742},{"X":86.185,"Y":93.779}],[{"X":77.239,"Y":98.371},{"X":74.257,"Y":90.532},{"X":68.27,"Y":88.13}],[{"X":59.163,"Y":94.781},{"X":61.287,"Y":92.082},{"X":59.71,"Y":88.948},{"X":54.89,"Y":87.878},{"X":55.847,"Y":91.156}],[{"X":156.428,"Y":94.218},{"X":158.058,"Y":92.011},{"X":157.383,"Y":90.475},{"X":153.958,"Y":92.285}],[{"X":171.563,"Y":92.566},{"X":173.544,"Y":88.952},{"X":172.799,"Y":88.055},{"X":170.49,"Y":91.299}],[{"X":77.032,"Y":89.283},{"X":75.208,"Y":84.541},{"X":69.734,"Y":77.597},{"X":68.922,"Y":79.777}],[{"X":119.637,"Y":88.115},{"X":120.304,"Y":77.135},{"X":119.264,"Y":72.438},{"X":117.388,"Y":73.992},{"X":117.516,"Y":80.792}],[{"X":142.69,"Y":85.445},{"X":144.136,"Y":81.354},{"X":143.001,"Y":80.859}],[{"X":148.866,"Y":85.224},{"X":153.643,"Y":80.839},{"X":149.794,"Y":81.881}],[{"X":165.286,"Y":85.199},{"X":164.7,"Y":83.746},{"X":160.512,"Y":81.803},{"X":160.192,"Y":82.909}],[{"X":130.502,"Y":84.798},{"X":132.592,"Y":78.84},{"X":131.36,"Y":78.336}],[{"X":62.515,"Y":84.688},{"X":63.7,"Y":82.176},{"X":60.188,"Y":74.465},{"X":54.168,"Y":78.902},{"X":56.52,"Y":81.653}],[{"X":48.19,"Y":81.653},{"X":51.148,"Y":79.669},{"X":47.538,"Y":77.053},{"X":45.324,"Y":79.736}],[{"X":84.601,"Y":80.65},{"X":87.17,"Y":79.387},{"X":88.897,"Y":74.98},{"X":85.458,"Y":75.507}],[{"X":76.947,"Y":79.839},{"X":76.473,"Y":77.849},{"X":73.85,"Y":76.163}],[{"X":96.853,"Y":79.315},{"X":98.44,"Y":77.997},{"X":97.359,"Y":77},{"X":95.923,"Y":78.708}],[{"X":66.177,"Y":75.689},{"X":67.546,"Y":73.526},{"X":63.281,"Y":72.581}],[{"X":130.539,"Y":73.142},{"X":131.294,"Y":68.99},{"X":130.02,"Y":64.963}],[{"X":65.017,"Y":61.368},{"X":64.345,"Y":59.693},{"X":61.299,"Y":58.5},{"X":60.496,"Y":59.851}],[{"X":135.018,"Y":100.857},{"X":137.266,"Y":99.498},{"X":136.611,"Y":98.542},{"X":133.988,"Y":100.292}]]},{"outer":[{"X":38.514,"Y":145.195},{"X":37.752,"Y":142.742},{"X":39.6,"Y":142.152}],"holes":[]},{"outer":[{"X":157.87,"Y":124.933},{"X":156.944,"Y":122.296},{"X":160.246,"Y":121.59}],"holes":[]},{"outer":[{"X":47.011,"Y":72.151},{"X":46.675,"Y":68.557},{"X":47.796,"Y":70.737}],"holes":[]},{"outer":[{"X":54.646,"Y":61.208},{"X":53.213,"Y":60.121},{"X":54.348,"Y":57.995},{"X":55.63,"Y":58.915}],"holes":[]}]; 

然后我exPolygons使用以下方法将结构转换为 Three.js 形状:

if (typeof(polys) != "undefined")
{
    var exPolygons = polys;
    var a, i, j, jlen, ilen, exPolygon, holes, outer, polygon, outer_shape, hole_shape;
    var alen = exPolygons.length;
    var shapes = new Array(alen);
    for (a = 0; a < alen; a++)
    {
      exPolygon = exPolygons[a];
      holes = exPolygon.holes;
      outer = exPolygon.outer;
      jlen = outer.length;
      if (jlen)      
      {
        for (j = 0; j < jlen; j++)
        {
          point = outer[j];
          point = new THREE.Vector2(point.X, point.Y); // convert Clipper point to THREE.Vector2
          outer[j] = point;
        }
        outer = new THREE.Shape(outer);
        ilen = holes.length;
        if (ilen)
        {
          for (i = 0; i < ilen; i++)
          {
            polygon = holes[i];
            for (j = 0, jlen = polygon.length; j < jlen; j++)
            {
              point = polygon[j];
              point = new THREE.Vector2(point.X, point.Y); // convert Clipper point to THREE.Vector2
              polygon[j] = point;
            }
            holes[i] = new THREE.Shape(polygon);
          }
          outer.holes = holes;
        }
        shapes[a] = outer;
      }
    }
   shapes = shapes.filter(function(){return true});
}

然后我做一个基本的挤压:

var extrusionSettings = {
    amount: 20,
    bevelEnabled: true,
    bevelThickness: 0.7,
    bevelSize: 0.7,
    bevelSegments: 8,
    material: 0,
    extrudeMaterial: 1
};

var geometry1 = new THREE.ExtrudeGeometry(shapes, extrusionSettings);

知道是什么原因造成的,对于 Three.js 三角剖分中可挤压多边形的确切要求是什么?

它与孔有关,因为如果我完全删除它们,三角测量就不会出错。

4

4 回答 4

3

https://github.com/mrdoob/three.js/issues/3386

不过好在three.js中已经有tri2js三角器调用函数triangulateShape2(),被注释掉了(原因不明)。

我下载了https://code.google.com/r/remiturboult-poly2tri-js-2/source/browse/src/js/poly2tri.js并在 Three.js 中替换了行“triangulateShape:函数(轮廓,孔) ” 与“triangulateShape2:函数(轮廓,孔)”来禁用默认三角测量器。

然后通过将其更改为“triangulateShape:function(pts,holes)”来启用“triangulateShape2:function(pts,holes)”。

之后,多边形数据完全正确地进行了三角剖分!但当然,它也有关于半相邻副本的限制,需要以不破坏几何的方式处理。

错误部分不是我的数据或解析器,而是 Three.js r58 默认三角测量器中的一些奇怪错误。当我将其更改为使用 poly2tri.js 时,问题中的 Tree 图像进行了三角剖分并正确渲染:

在此处输入图像描述

于 2013-04-27T12:43:47.040 回答
2

如果您仍想在您的three.js 项目中使用poly2tri(或其他一些三角测量库),我想参考我制作的three.js 三角测量库(一个适配器)。该适配器允许将其他三个三角测量库无缝连接到您的 three.js 项目,其中之一是poly2tri

您需要做的就是包含该triangulation.js文件:

<script src="triangulation.js"></script>

setLibrary并使用以下方法设置您选择的库:

THREE.Triangulation.setLibrary('poly2tri');

显然,您将需要嵌入poly2tri库本身。

在这里,您可以看到对树的第一部分使用不同库的三角测量结果。

在 GitHub 上阅读有关该项目的更多信息。

于 2016-03-03T14:39:57.140 回答
0

我不熟悉 Three.js,但我敢打赌,重合表面和点的方向是顺时针/逆时针方向是一个问题。任何从零开始开发 3D 渲染代码的人都见过这种事情。即使您使用的 API 说它足够聪明来处理这些事情,也可能存在错误。

靠近顶部的那条长长的水平线困扰着我——试着在你的数组中找到确切的点,看看它们是如何相关的。语法错误?这些点来自阵列中的相邻孔吗?我认为有一个线索。

如果更改孔多边形的顺序会发生什么?我的意思是代替第 1 洞,第 2 洞,...,第 N 洞,尝试第 1 洞,第 1 洞,第 1 洞。然后尝试反转任何一个洞的点。

OTOH,曾几何时,我遇到了一个类似于 POV-Ray 的奇怪问题,结果证明是主板中的连接不良导致了罕见的位错误,十亿分之几。我使用的 C++ 编译器是在那台机器和 POV-Ray 上构建的。事情在 99.99% 的时间里都有效,但随之而来的是一些非常具体的奇怪问题。但是您的图像看起来像重合表面错误。

于 2013-04-26T17:29:59.767 回答
0

一些额外的发现:

将 THREE.Vector2 点数组转换为形状时遇到了同样的问题:

three.js:25339 THREE.ShapeUtils:无法对多边形进行三角剖分!在三角()

我通过将所有点坐标四舍五入为整数找到了解决此问题的方法。

于 2016-12-13T12:30:39.473 回答