【问题标题】:Extruding multiple polygons with multiple holes and texturing the combined shape挤出具有多个孔的多个多边形并对组合形状进行纹理化
【发布时间】:2013-04-14 00:45:32
【问题描述】:

此问题与此question 有关。 answer 展示了一种非常好的方法来挤出有孔的多边形(参见the excellent live example)。答案的主要学习是three.js(r58)中的路径不能有多个moveTo命令并且它必须在路径的开头,这意味着路径必须被moveTos打破,以便moveTo开始总是一条新路。

在three.js 中拉伸意味着使用可能的斜角将2D 路径转换为3D 形状。它适用于挤压文本以制作 3D 字母和单词,但也可用于挤压自定义路径。

现在有两个问题:

  • 如何处理具有多个孔多边形和多个非孔多边形的多边形?
  • 如何将纹理添加到生成的整体形状中?

我在http://jsbin.com/oqomuj/1/edit 中做了一个 SVG 的例子:

使用此路径生成图像:

路径>

并将此路径转换为单个顶点数组:

var lower_house_material = [{x:57.11,y:271.77},{x:57.11,y:218.33},{x:41.99,y:218.63},{x:105.49,y:165.77},{x:138.42,y :193.18},{x:138.42,y:172.2},{x:152.53,y:172.2},{x:152.53,y:204.93},{x:168.99,y:218.63},{x:153.21,y :218.63},{x:153.21,y:271.77}]; var lower_house_hole_1 = [{x:74.14,y:264.13},{x:105.49,y:264.13},{x:105.49,y:232.8},{x:74.14,y:232.8}]; var lower_house_hole_2 = [{x:115.35,y:250.7},{x:135.96,y:250.7},{x:135.96,y:232.61},{x:115.35,y:232.61}]; var upper_house_material = [{x:56.11,y:145.77},{x:56.11,y:92.33},{x:40.99,y:92.63},{x:104.49,y:39.77},{x:137.42,y :67.18},{x:137.42,y:46.2},{x:151.53,y:46.2},{x:151.53,y:78.93},{x:152.53,y:79.76},{x:155.55,y :77.23},{x:159.5,y:74.52},{x:168.65,y:69.81},{x:176.46,y:66.93},{x:188.04,y:64.16},{x:200.63,y :62.7},{x:213.65,y:62.7},{x:226.05,y:64.1},{x:234.83,y:66.06},{x:245.65,y:69.73},{x:252.87,y :73.27},{x:259.12,y:77.35},{x:262.63,y:80.33},{x:265.6,y:83.47},{x:268.01,y:86.76},{x:269.84,y :90.17},{x:271.08,y:93.68},{x:271.76,y:99.08},{x:271.04,y:104.64},{x:269.75,y:108.2},{x:267.87,y :111.63},{x:265.42,y:114.91},{x:262.44,y:118.01},{x:258.96,y:120.92},{x:255.02,y:123.63},{x:245.86,y :128.34},{x:238.06,y:131.22},{x:226.48,y:133.99},{x:213.88,y:135.45},{x:200.63,y:135.45},{x:188.04,y :133.99},{x:176.46,y:131.22},{x:168.65,y:128.34},{x:159.5,y:123.63},{x:155.55,y:120.92},{x:152.21,y :118.12},{x:152.21,y:145.77}]; var upper_house_hole_1 = [{x:73.14,y:138.13},{x:104.49,y:138.13},{x:104.49,y:106.8},{x:73.14,y:106.8}]; var upper_house_hole_2 = [{x:114.35,y:124.7},{x:134.96,y:124.7},{x:134.96,y:106.61},{x:114.35,y:106.61}]; var upper_house_hole_3 = [{x:207.26,y:117.33},{x:210.57,y:117.26},{x:216.87,y:116.53},{x:222.66,y:115.15},{x:227.8,y :113.18},{x:233.11,y:110},{x:236.34,y:106.99},{x:238.51,y:103.64},{x:239.42,y:100.48},{x:239.42,y :97.67},{x:238.51,y:94.51},{x:236.34,y:91.16},{x:233.11,y:88.15},{x:227.8,y:84.97},{x:222.66,y :83},{x:216.87,y:81.62},{x:210.57,y:80.89},{x:203.94,y:80.89},{x:197.65,y:81.62},{x:191.86,y :83},{x:186.71,y:84.97},{x:181.41,y:88.15},{x:178.18,y:91.16},{x:176.01,y:94.51},{x:175.1,y :97.67},{x:175.1,y:100.48},{x:176.01,y:103.64},{x:178.18,y:106.99},{x:181.41,y:110},{x:186.71,y :113.18},{x:191.86,y:115.15},{x:197.65,y:116.53},{x:203.94,y:117.26}];

问题是,如何在 three.js 中将这种类似结构转换为 3D 对象,以便可以使用 THREE.ExtrudeGeometry( shape, extrusionSettings ) 将其挤出,然后将其作为一个整体纹理化?

我可以检查路径数据以了解哪个洞属于哪个多边形并将所有这些都作为单独的形状处理,但因为我想在所有形状中使用一个纹理图像,我认为首选方式是将所有材质多边形作为一种形状处理,将孔多边形作为另一种形状处理,并使用以下内容:

var shape = [lower_house_material,upper_house_material]; shape.holes = [lower_house_hole_1,lower_house_hole_2,upper_house_hole_1,upper_house_hole_2,upper_house_hole_3]; var 3d_geometry = THREE.ExtrudeGeometry(形状,挤压设置);

所以3d_geometry 应该在最后一个网格,我可以通过这种方式向其附加纹理:

var textureFront = new THREE.ImageUtils.loadTexture('textureFront.png'); var textureSide = new THREE.ImageUtils.loadTexture('textureSide.png'); var materialFront = new THREE.MeshBasicMaterial( { map: textureFront } ); var materialSide = new THREE.MeshBasicMaterial( { map: textureSide } ); var materialArray = [ materialFront, materialSide ]; var faceMaterial = new THREE.MeshFaceMaterial(materialArray); var final_mesh = new THREE.Mesh(3d_geometry, faceMaterial );

其中一个纹理可能是这样的(256x256px):

并应用纹理:

而且因为网格是挤压出来的,所以上面还有3D厚度,但是你得到了纹理的概念。

我知道 y 坐标必须翻转,但这是一项微不足道的任务,不是我的问题的重点,但如果 three.js 有现成的裁剪 y 的功能,那会很有帮助。

我花了好几个小时来检查three.js 源代码、示例和documentation,但是因为其中最常见的词是“todo”,所以没有多大帮助。而且我是three.js的新手,我认为这对于一些有经验的three.js用户来说可能是微不足道的任务。

更新:为了确保孔多边形始终表现良好,这意味着孔多边形始终完全位于材质多边形内,并且在材质多边形或孔洞中没有重复的顶点或自相交多边形和所有材质多边形都有 CW 缠绕顺序和孔 CCW。

更新:合并几何不是为由一个纹理设置的整个挤压多边形设置纹理的解决方案:http://jsfiddle.net/C5dga。纹理在所有单独的形状上重复,因此在这种情况下合并几何没有真正的意义。解决方案可能在它们被挤出之前合并形状中找到,但尚未找到解决方案。

【问题讨论】:

  • 这就是 SVG 过滤器的发明目的。我不熟悉它们的 three.js 语法,但基本上,您使用 feImage 拉入纹理,然后对源图形执行 feComposite operator="in"。
  • 感谢您的评论。确实,支持过滤器的浏览器可以在 SVG 中产生类似的效果,但在这个问题中,我对在 three.js 中对 3D 形状进行纹理化以在浏览器的 webGL 引擎中渲染输出感兴趣。

标签: svg three.js textures polygon


【解决方案1】:

您可以像下面的 sn-p 那样合并几何图形,从而只生成一个网格。从您之前的问题中,您已经知道如何对单个几何体进行纹理处理。

var geometry1 = new THREE.ExtrudeGeometry( shape1, extrusionSettings );
var geometry2 = new THREE.ExtrudeGeometry( shape2, extrusionSettings );

geometry1.merge( geometry2 );

. . .

var mesh = new THREE.Mesh( geometry1, material );

scene.add( mesh );

小提琴:http://jsfiddle.net/pHn2B/88/

小提琴:http://jsfiddle.net/C5dga/13/(带纹理)

编辑:作为创建单独几何图形和使用 merge 实用程序的替代方法,您可以使用以下模式创建单个几何图形,而不是:

var geometry1 = new THREE.ExtrudeGeometry( [ shape1, shape2 ], extrusionSettings );

编辑:更新到 three.js r.70

【讨论】:

  • 感谢您的回答!我尝试在整个网格上添加纹理,但纹理在每个形状上分别呈现:jsfiddle.net/C5dga 有什么想法吗?
  • 是的。我想你知道你必须做什么——提供你自己的紫外线发生器。
  • 我有一个边界框生成器 (jsfiddle.net/C5dga)。它将 UV:s 从几何的坐标空间缩放到范围 0-1。但问题是这些 UV:s 是在合并之前为每个单独的几何体在 THREE.ExtrudeGeometry 中生成的。我需要一些函数来将 UV 映射到合并的几何体。那么我应该在哪里提供我自己的紫外线发生器呢?
  • 关于我问题的另一部分:three.js 中是否有任何方法可以转换顶点数组,例如。 [{x:56.11,y:145.77},{x:56.11,y:92.33},...] 塑造(或路径)?或者在有成百上千个顶点的情况下是否也需要使用慢速 moveto 和 lineto 方法?
  • 您可以手动编辑 UV 以获得您想要的。 jsfiddle.net/C5dga/1 。我希望您可以自己解决任何剩余的问题,并且能够接受这个答案。
猜你喜欢
  • 2023-03-30
  • 2021-09-01
  • 2017-12-19
  • 1970-01-01
  • 2021-06-18
  • 2020-12-23
  • 2020-11-21
  • 1970-01-01
  • 2011-10-14
相关资源
最近更新 更多