68. 创建参数化形状物体的旧方法

本教程翻译自官方教程Create Parametric Shapes - Legacy,各位也可以进入本站镜像站点查看

本文目录

  1. 如何使用旧方法创建参数化形状物体
  2. 带状物体
  3. 管状物体
  4. 不规则多边形
  5. 不规则多边形的挤压
  6. 线
  7. 虚线
  8. 挤压形状
  9. 延伸阅读
    1. 基础 - L1

如何使用旧方法创建参数化形状物体

带状物体 Ribbon

更多关于带状物体是如何创建的请移步Ribbon Tutorial

var ribbon = BABYLON.Mesh.CreateRibbon("ribbon", [path1, path2, ..., pathn], false, false, 0, scene, false, BABYLON.Mesh.DEFAULTSIDE);

参数依次为:name, pathArray, closeArray, closePath, offset , scene,updatable,side orientation

  • name: string 形状的名称
  • pathArray: Vector3[][] 由路径组成的一个数组,路径是连续的三维向量构成的一个三维向量数组。每一个路径至少包含4个三维向量点,pathArray至少包含一个路径
  • closeArray: boolean 如果设置为true,则最后一个路径和第一个路径会构成一个额外的三角面
  • closePath: boolean 如果设置为true,则pathArray中的每一个路径的最后一个三维向量连接当前路径的第一个三维向量,形成一个闭合路径
  • offset: integer(默认值为path大小的一半) 仅当路径数组只包含一个路径时才强制执行,如果有多个路径则不会生效。将第 i 个点和 i+offset 个点连接在一起。
  • scene: 当前的scene对象
  • updatable: boolean 是否允许更新
  • sideOrientation: 想让用户看到的面(BABYLON.Mesh.FRONTSIDE / BACKSIDE / DOUBLESIDE / DEFAULT).

最后两个参数如果我们只需要默认值,就可以省略掉。

var ribbon = BABYLON.Mesh.CreateRibbon("ribbon", [path1, path2, ..., pathn], false, false, 0, scene);

管状物体 Tube

var tube = BABYLON.Mesh.CreateTube("tube", [V1, V2, ..., Vn], radius, tesselation, radiusFunction, cap, scene, false, BABYLON.Mesh.DEFAULTSIDE);

参数依次为:name, path, radius, tesselation, radiusFunction(可选), cap, scene, updatable, sideOrientation

  • name: string 形状的名称
  • path: Vector3[] 路径是连续的三维向量构成的一个三维向量数组。每一个路径至少包含2个三维向量点
  • radius: number 管的半径,如果使用radiusFunction参数,将该参数设置null
  • cap: BABYLON.Mesh.NO_CAP, BABYLON.Mesh.CAP_START,BABYLON.Mesh.CAP_END, BABYLON.Mesh.CAP_ALL,
  • updatable: boolean 是否允许更新
  • sideOrientation: 想让用户看到的面(BABYLON.Mesh.FRONTSIDE / BACKSIDE / DOUBLESIDE / DEFAULT).

最后两个参数如果我们只需要默认值,就可以省略掉。

var tube = BABYLON.Mesh.CreateTube("tube", [V1, V2, ..., Vn], radius, tesselation, radiusFunction, cap, scene);

管状物体不仅能创建圆柱体,还能创建更多类型的管状物体

radiusFunction必须返回一个 radius
示例:

var myFunction = function(i, distance) {
  var radius = 3 * Math.cos(distance / 5);
  return radius;
};
var tube = BABYLON.Mesh.CreateTube("lumps", path, null, 20, myFunction, scene);

这里还有一个半径正弦变化和正弦递增路径的示例

这是另一个圆形路径和变化半径的例子

不规则多边形 Non Regular Polygon

    需要注意的是: CreatePolygon 使用了第三方库Earcut,所以当我们在非playground项目中使用时,我们需要引入它的cdn或者直接下载 npm包

var polygon = BABYLON.Mesh.CreatePolygon("polygon", [V1, V2, ..., Vn], scene, [[V1, V2, ..., Vn], [V1, V2, ..., Vn], ....[V1, V2, ..., Vn]], false, BABYLON.Mesh.DEFAULTSIDE);

参数依次为:name, 多边形顶点坐标三维向量构成的数组, 掏空形状的坐标三维向量, updatable, sideOrientation.最后两个参数如果我们只需要默认值,就可以省略掉。

  • 注意:所有的三维向量都应该属于XOZ平面,顺序是逆时针排列,如这样的BABYLON.Vector3(x, 0, z)
var polygon = BABYLON.Mesh.CreatePolygon("polygon", [V1, V2, ..., Vn], 2, scene);

更多关于PolygonMeshBuilder

线条 Lines

var lines = BABYLON.Mesh.CreateLines("lines", [
    new BABYLON.Vector3(-10, 0, 0),
    new BABYLON.Vector3(10, 0, 0),
    new BABYLON.Vector3(0, 0, -10),
    new BABYLON.Vector3(0, 0, 10)
], scene);

参数依次为:name, 逗号分隔的向量点组成的数组,scene.

简单介绍一下Lines Mesh 构造函数的工作原理:其实我们通过上面的示例代码就可以看出来它的工作原理。注意 [] 这是Javascript的数组表示方法。数组的第一个三维向量是创建线条的开始位置。然后,一个逗号,接下来是下一个三维向量的位置...指示线条下一步往那个位置画。然后,在一个逗号,另一个向量指向下一个位置。我们可以任意添加三维向量,但是要注意最后一个三维向量后面没有逗号。请遵循数组的格式规范。

虚线 Dashed Lines

var dashedlines = BABYLON.Mesh.CreateDashedLines("dashedLines", [v1, v2, ... vn], dashSize, gapSize, dashNb, scene);

参数依次为:name, 逗号分隔的向量点组成的数组,dashSize, gapSize, dashNumber, scene
和线段一样,虚线也是由沿着三维向量点构成的。通过dashNumber来决定两个相邻的三维向量之间的分段数。

dashSizegapSize 是相对的。

挤压形状 Extruded Shape

什么是挤压?
挤压就是将2D形状转换3D立体的形状(volumic shape体积大的形状)
我们想象一下,我们通过连续的三维向点构成一个2D的星星状的物体,我们这能在XOY平面上设置这些三维坐标点,因此每一个向量点的Z轴的值为0
例如:https://playground.cnbabylon.com/#873V35#1

通过世界坐标系我们可以看的更清楚https://playground.cnbabylon.com/#C9V84I
我们现在想象,沿着Z轴拉伸2D形状,给这个形状一些体积(有了高度或者深度)...这就是挤压https://playground.cnbabylon.com/#G4VJBS

现在想象一下,不只是沿着Z轴方向拉伸,而是沿着像正弦曲线那样的3D路径拉伸。https://playground.cnbabylon.com/#L6GDG0

有基础的和高级的(自定义的)两种不同的挤压方法。

参数依次为:name, 逗号分隔的向量点组成的数组,dashSize, gapSize, dashNumber, scene
和线段一样,虚线也是由沿着三维向量点构成的。通过dashNumber来决定两个相邻的三维向量之间的分段数。

基础方法

BABYLON.Mesh.ExtrudeShape(name, shape, path, scale, rotation, cap, scene, updatable?, sideOrientation)
  • name: string 挤压形状的名称
  • shape: Vector3[] 被挤压物体的形状,连续的三维向量组成的数组
  • path: Vector3[] 挤压(拉伸)的路径,连续的三维向量组成的数组
  • scale: number 默认为 1 缩放比例
  • rotation: number 默认为 0,每一段挤压过程种的旋转角度
  • cap: BABYLON.Mesh.NO_CAP, BABYLON.Mesh.CAP_START,BABYLON.Mesh.CAP_END, BABYLON.Mesh.CAP_ALL,
  • scene: 当前的scene
  • updatable: boolean 是否允许更新
  • sideOrientation: 想让用户看到的面

如果我们将scale的值改为3,则原来的形状会沿着曲线放大三倍。https://playground.cnbabylon.com/#2TRVSE

如果我们将rotation的值改为 PI/24,则在曲线的每一点都会扭曲相应的角度。https://playground.cnbabylon.com/#6K0TKF

当然,尽管我们只能在XOY平面上定义我们的形状,但是我们仍然沿任何路径挤压我们的形状https://playground.cnbabylon.com/#6K0TKF#1

此外,我们的形状也不一定是闭合的,我们可以创建简单的或者复杂的不闭合的形状。https://playground.cnbabylon.com/#6K0TKF#2
挤压形状:https://playground.cnbabylon.com/#6K0TKF#3
挤压并旋转:https://playground.cnbabylon.com/#6K0TKF#4

我们的形状也可以不以坐标系为中心。
这是一个简单的偏移形状https://playground.cnbabylon.com/#6K0TKF#5
挤压形状(洋红色的线是挤压路径,偏移是为了方便查看):https://playground.cnbabylon.com/#6K0TKF#5
围绕轴线旋转https://playground.cnbabylon.com/#6K0TKF#6
如你所见,这是一种无需处理数学运算的更简单的方法来构建复杂的螺旋形网格的方法https://playground.cnbabylon.com/#6K0TKF#7
由于要挤压的形状是不可预测的,因此如果要在挤压物体中添加一个或两个盖子,其中心设置为形状重心。

高级方法

BABYLON.Mesh.ExtrudeShapeCustom(name, shape, path, scaleFunction, rotateFunction, ribbonCloseArray, ribbonClosePath, cap, scene)
  • name: string 挤压形状的名称
  • shape: Vector3[] 被挤压物体的形状,连续的三维向量组成的数组
  • path: Vector3[] 挤压(拉伸)的路径,连续的三维向量组成的数组
  • scaleFunction: function 自定义js函数,这个函数在每一个路径点被调用,参数为 i(当前路径点的在路径数组中的索引) distance(当前点到开始点的距离),函数必须返回一个 number 作为 scale的值,这个值将会被应用到第 i 个点的形状绘制中。
  • rotationFunction: function 自定义js函数,这个函数在每一个路径点被调用,参数为 i(当前路径点的在路径数组中的索引) distance(当前点到开始点的距离),函数必须返回一个 number 作为 rotation的值,这个值将会被应用到第 i 个点的形状绘制中。
  • ribbonCloseArray: boolean 默认为 false.底层的ribbon closeArray参数,This can be used to automatically close a path with right normals computation.
  • ribbonClosePath: boolean 默认为 false. This can be used to automatically close a shape with right normals computation.
  • cap: BABYLON.Mesh.NO_CAP, BABYLON.Mesh.CAP_START,BABYLON.Mesh.CAP_END, BABYLON.Mesh.CAP_ALL,
  • scene: 当前的scene
  • updatable: boolean 是否允许更新
  • sideOrientation: 想让用户看到的面

在这个高级的方法中,使用自定义函数来代替scalerotation

scaleFunction
在物体在挤压的时候,在路径上的每一个点都会调用这个方法来生成scale的值。有两个参数 idistance.

  • i 代表这个点在路径数组中的索引,第一个点是0
  • distance 是当前点距离第一个点的距离

这个自定义函数必须返回一个number类型的值用来当作当前点挤压的 scale 值。

示例:

var myScale = function(i, distance) {
  var scale = 2 * Math.sin(i / 5);
  return scale;
};

这是一个不闭合,不是以坐标原点为中心,scale 沿着路径线性增加的一个简单形状物体:https://playground.cnbabylon.com/#6K0TKF#8

现在我们使用一个线性缩放函数,可以得到一个有趣的结果:https://playground.cnbabylon.com/#6K0TKF#9

我们甚至可以通过交替缩放正负来模拟旋转:https://playground.cnbabylon.com/#6K0TKF#10

rotateFunction
在物体在挤压过程中,在路径上的每一个点都会调用这个方法来生成rotate的值。有两个参数 idistance.

  • i 代表这个点在路径数组中的索引,第一个点是0
  • distance 是当前点距离第一个点的距离

这个自定义函数必须返回一个number类型的值用来当作当前点挤压的 rotate 值。

示例:

var myRotation = function(i, distance) {
  var rotation = distance / 20;
  return rotation;
};

这是一个scale 不变,rotation根据distance计算的例子:https://playground.cnbabylon.com/#6K0TKF#11

你也可以创建一个非线性的旋转函数,例如正弦函数https://playground.cnbabylon.com/#6K0TKF#12

固定值

这个高级方法需要提供两个自定义函数。但是有时候我们可能只需要一个自定义缩放函数,而rotation只需要一个固定值。这时,我们只需传递一个自定义旋转函数返回一个固定的值:

示例:

var noRotation = function(i, distance) {
  return 0;
};

如果你认真的看了刚才例子的代码,你就会发现其实这个例子scaleFunction就是返回了一个固定值 1.https://playground.cnbabylon.com/#6K0TKF#11

ribbonCloseXXX

这个挤压物体其实是基于带状物体。当我们挤压一个形状时,实际上是创建了一个特别的带状物体。
这就意味着当我们想要闭合挤压形状时可以使用带状物体的参数 closeArrayclosePath

注意: closeXXX 中的PathArray实际指的是带状物体的。而不是挤压形状的。
这可能是你对下面两点描述疑惑的原因 :

  • ribbonCloseArray 设置为 true 时会闭合挤压形状的 path
  • ribbonClosePath 设置为 true 时会闭合我们创建的形状(如果没有闭合的话)

我们现在来看一下这个不闭合,不以坐标原点为中心的形状:https://playground.cnbabylon.com/#6K0TKF#13
这时个几乎是圆形的路径https://playground.cnbabylon.com/#6K0TKF#15
设置固定的scale和不旋转进行挤压https://playground.cnbabylon.com/#6K0TKF#16
现在我们将ribbonCloseArray设置为 true https://playground.cnbabylon.com/#6K0TKF#17
正如你所看到的,实际上是闭合了挤压物体的path。现在我们将ribbonCloseArray设置为 false,并将ribbonClosePath设置为 truehttps://playground.cnbabylon.com/#6K0TKF#18
现在是形状闭合了。

将两个都设为true https://playground.cnbabylon.com/#6K0TKF#14

总结

最后,一个完整的自定义挤压形状的创建应该是这样的:

BABYLON.Mesh.ExtrudeShapeCustom("extruded", shape, path, myScale, myRotation, false, true, scene)

被挤压的形状是由连续的三维向量构造的数组,这就意味这无论是2D还是3D的形状都可以被挤压。
被挤压的形状将在局部坐标系中设计,以z轴为挤出路径轴。
最后,形状不一定要以本地坐标系(局部坐标系)坐标原点为中心。
居中的形状将沿路径轴对称的挤压,未居中的形状可能会偏离挤压路径轴。

所以我们可以很容易的生成一些奇怪的形状https://playground.cnbabylon.com/#6K0TKF#19

延伸阅读

基础 - L1

Mesh Overview
Set Shapes 101
Parametric Shapes 101
Set Shapes
Parametric Shapes
Polyhedra Shapes
Tiled Planes and Boxes

贡献者

翻译: 阿恒 cnblogs
校对: Catherine catherine__long@126.com
技术支持: 吉吉国王 jijiking@office2.cn / Dushusir github

参与贡献? 联系sevice@office2.cn