5

这个问题与这个问题有关答案显示了挤出有孔的多边形的非常好的方法(请参阅出色的实时示例)。答案的主要学习是three.js(r58)中的路径不能有多个moveTo命令并且它必须在路径的开头,这意味着路径必须被moveTos打破,以便moveTo开始总是一条新的道路。

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

现在出现了两个问题:

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

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

在此处输入图像描述

使用此路径生成图像:

<路径 d="
 M57.11,271.77 L57.11,218.33 L41.99,218.63 L105.49,165.77 L138.41,193.18 L138.41,172.2 L152.53,172.2 L152.53,204.93 L168.99,218.63 L153.21,218.63 L153.21,271.77Z
 M74.14,264.13 L105.49,264.13 L105.49,232.8 L74.14,232.8Z
 M115.35,250.7 L135.96,250.7 L135.96,232.61 L115.35,232.61Z
 M56.11,145.77 L56.11,92.33 L40.99,92.63 L104.49,39.77 L137.41,67.18 L137.41,46.2 L151.53,46.2 L151.53,78.93 L152.53,79.76 L1559.55,77.2 5,74.52 L168.65,69.81 L176.46,66.93 L188.04,64.16 L200.63,62.7 L213.65,62.7 L226.05,64.09 L234.83,66.06 L245.65,69.73 L252.87,73.27 L29 12,77.34 L262.63,80.33 L265.6,83.47 L268.01,86.76 L269.83,90.17 L271.08,93.68 L271.76,76,99.08 95,120.92 L255.02,123.63 L245.86,128.34 L238.06,131.22 L226.48,133.99 L213.88,135.44 L200.63,135.44 L188.04,133.99 L176.46,131.22 L168.65,128.34 L159.5,123.63 L155.55,120.92 L152.21,118.12 L152.21,145.77Z
 M73.14,138.13 L104.49,138.13 L104.49,106.8 L73.14,106.8Z
 M114.35,124.7 L134.96,124.7 L134.96,106.61 L114.35,106.61Z
 M207.26,117.33 L210.57,117.26 L216.87,116.53 L222.66,115.15 L227.8,113.18 L233.11,110 L236.34,106.99 L238.51,103.64 L239.42,100.48 L239.42,97.67 L238.51,94.51 L236.34,91.16 L233.11,88.15 L227.8 ,84.97 L222.66,83 L216.87,81.62 L210.57,80.89 L203.94,80.89 L197.65,81.62 L191.86,83 L186.71,84.97 L181.41,88.15 L178.18,91.16 L176.01 ,94.51 L175.1,97.67 L175.1,100.48 L176.01,103.64 L178.18,106.99 L181.41,110 L186.71,113.18 L191.86,115.15 L197.65,116.53 L203.94,117.2
"></路径>

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

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 的源代码、示例和文档,但是因为其中最常见的词是“todo”,所以它并没有多大帮助。而且我是three.js 的新手,我认为这对于一些有经验的three.js 用户来说可能是微不足道的任务。

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

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

4

1 回答 1

6

您可以像下面的代码片段那样合并几何,生成一个网格。从您之前的问题中,您已经知道如何对单个几何体进行纹理处理。

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

于 2013-04-20T21:08:18.593 回答