Зона заполнения между кривыми Безье с текстурой - PullRequest
0 голосов
/ 13 января 2020

Я хочу динамически рисовать 2D-сегменты дороги в Unity. Я знаю 4 краевые точки сегмента и необходимые контрольные точки для кривых Безье. Это позволяет мне довольно легко нарисовать внешнюю форму сегмента дороги, что приводит (в этом примере) к 2 конечным линиям и 2 кривым, которые формируют форму дороги.

Чтобы нарисовать кривые Безье, я использую это: https://github.com/dbrizov/NaughtyBezierCurves

Так выглядит внешняя форма

Цель - заполнить участок дороги некоторой текстурой. Как я могу создать какие-то самолеты или меня sh, которые имели бы такую ​​же форму дороги?

Моей первой идеей было go вдоль обеих кривых и создание плоскостей, возможно, каждой 1/100 длины кривой, и добавление к ним текстуры. Но при таком подходе я не знаю, как вращать плоскости или как предотвратить пробелы или перекрытия. Возможно, у кого-то есть более простое решение этой проблемы.

Это то, чего я хочу достичь

1 Ответ

0 голосов
/ 14 января 2020

Я взял 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 l oop пробует разные 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;
...