首页 > 解决方案 > 用纹理填充贝塞尔曲线之间的区域

问题描述

我想在 Unity 中动态绘制 2D 路段。我知道段的 4 个边缘点和贝塞尔曲线所需的控制点。这使我可以很容易地绘制路段的外部形状,这导致(在此示例中)形成道路形状的 2 条端点线和 2 条曲线。

为了绘制贝塞尔曲线,我使用这个:https ://github.com/dbrizov/NaughtyBezierCurves

这是外部形状的样子:
外形是这样的

目标是用一些纹理填充路段。如何创建某种具有相同道路形状的平面或网格?

我的第一个想法是沿着两条曲线走并创建平面,可能是曲线的每 1/100 长度,然后向它们添加纹理。但是使用这种方法,我不知道如何旋转平面或如何防止空间或重叠。也许有人对这个问题有更简单的解决方案。

这就是我想要实现的目标:
这就是我想要实现的

标签: unity3dgeometrymeshbezierspline

解决方案


从一个相关问题中获取了 Dshook 的答案并更改了几行以使其采用两个任意样条曲线:

using UnityEngine;

[ExecuteInEditMode]
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer), typeof(BezierSpline))]
public class SplineMesh : MonoBehaviour {

  [Range(1, 20)]
  public int sampleFrequency = 5;

  BezierSpline[] splines;

  Mesh mesh;

  private void Awake () {
    splines = GetComponents<BezierSpline>();
    mesh = GetComponent<Mesh>();
  }

  private Vector3[] vertices;

  public void GenerateMesh(){
    vertices = new Vector3[(sampleFrequency + 1) * 2];

    //iterate over our samples adding two vertices for each one
    for(int s = 0, i = 0; s <= sampleFrequency; s++, i += 2){
      float interval = s / (float)sampleFrequency;

      //get point along spline, and translate to local coords from world
      var point1 = transform.InverseTransformPoint(splines[0].GetPoint(interval));
      var point2 = transform.InverseTransformPoint(splines[1].GetPoint(interval));

      vertices[i] = point1;
      vertices[i + 1] = point2;
    }

    GetComponent<MeshFilter>().mesh = mesh = new Mesh();
    mesh.name = "Spline Mesh";

    mesh.vertices = vertices;

    //now figure out our triangles
    int [] triangles = new int[sampleFrequency * 6];
    for(int s = 0, ti = 0, vi = 0; s < sampleFrequency; s++, ti += 6, vi += 2){
      //first tri
      triangles[ti] = vi;
      triangles[ti + 1] = vi + 3;
      triangles[ti + 2] = vi + 1;
      //second matching tri
      triangles[ti + 3] = vi;
      triangles[ti + 4] = vi + 2;
      triangles[ti + 5] = vi + 3;
    }

    mesh.triangles = triangles;
    mesh.RecalculateNormals();

    Debug.Log("Generated Spline Mesh");
  }


}

你需要确保你渲染它的着色器没有背面剔除,即有Cull Off.

此代码在许多情况下都可以使用,但理论上可能会导致边缘自重叠。在没有关于样条线的相对定位的任何保证的情况下,我能想到的唯一方法是在sampleFrequency循环的每个步骤中尝试intervals对大于或等于前一对的每个样条线尝试不同,intervals直到找到一对删除(或最小化)该对将添加的重叠。

至于设置 uvs,你可以像这样设置 uvs:

    private Vector3[] vertices;
    private Vector2[] uvs;

    // ...

      vertices[i] = point1;
      vertices[i + 1] = point2;

      uvs[i] = new Vector2(0f, sample);
      uvs[i+1] = new Vector2(1f, sample);

    // ...

    mesh.triangles = triangles;
    mesh.RecalculateNormals();
    mesh.uv = uvs;

推荐阅读