Unity3d 网格曲面上的线渲染器

Unity3d 网格曲面上的线渲染器,unity3d,3d,mesh,Unity3d,3d,Mesh,目标:渲染基于网格的基本体(即球体、立方体等)曲面上两点之间的距离线 当前解决方案:迭代遍历两个端点之间的距离线,并通过该点反向光线投射。由于距离线通过网格直接连接两个顶点,因此需要网格曲面上的相应点 然后,使用Unity的LineRenderer绘制线,只要识别到上一个光线投射的法线发生更改,就会使用顶点位置填充LineRenderer 问题: 当端点移动时,100条射线被投射,表现非常糟糕 解决方案并不总是有效,并产生意外的锯齿线/点 问题: 有没有更好的方法来实现这一点?如果要优化解决方

目标:渲染基于网格的基本体(即球体、立方体等)曲面上两点之间的距离线

当前解决方案:迭代遍历两个端点之间的距离线,并通过该点反向光线投射。由于距离线通过网格直接连接两个顶点,因此需要网格曲面上的相应点

然后,使用Unity的LineRenderer绘制线,只要识别到上一个光线投射的法线发生更改,就会使用顶点位置填充LineRenderer

问题:

当端点移动时,100条射线被投射,表现非常糟糕

解决方案并不总是有效,并产生意外的锯齿线/点

问题:
有没有更好的方法来实现这一点?

如果要优化解决方案,可能需要为每个原语编写一个脚本,并利用原语特定的数学

例如,您可以简单地获取网格的半径并将线顶点放置在半径*方向FromCenter处,而不是投射光线

下面是一个示例脚本:

[RequireComponent(typeof(LineRenderer))]
public class SurfaceLine : MonoBehaviour, IPointerClickHandler
{
    [SerializeField] private float pointsPerUnit;
    [SerializeField] private MeshFilter mesh;

    private Vector3 start;
    private Vector3 end;
    private LineRenderer lineRenderer;

    void Awake()
    {
        this.lineRenderer = this.GetComponent<LineRenderer>();
    }

    public void OnPointerClick(PointerEventData eventData)
    {
        if(eventData.button == PointerEventData.InputButton.Left)
        {
            this.start = this.transform.InverseTransformPoint(eventData.pointerCurrentRaycast.worldPosition);
            this.Render();
            return;
        }

        if(eventData.button == PointerEventData.InputButton.Right)
        {
            this.end = this.transform.InverseTransformPoint(eventData.pointerCurrentRaycast.worldPosition);
            this.Render();
        }
    }

    private void Render()
    {
        var distance = Vector3.Distance(this.end, this.start);

        var direction = (this.end - this.start).normalized;

        var numPoints = Mathf.FloorToInt(distance * this.pointsPerUnit);

        numPoints = Mathf.Max(numPoints, 2);

        this.lineRenderer.positionCount = numPoints;

        var positions = new Vector3[numPoints];

        var stepInDir = direction * (distance / (float)numPoints);

        for(int i = 0; i < numPoints; i++)
        {
            positions[i] = this.start + i * stepInDir;

            var dirFromCenter = positions[i] - this.mesh.mesh.bounds.center;

            positions[i] = this.mesh.mesh.bounds.center + dirFromCenter.normalized * (this.mesh.mesh.bounds.size.x / 2.0f);
        }

        positions[positions.Length - 1] = this.end;

        this.lineRenderer.SetPositions(positions);
    }
}

这在更新循环中似乎也可以执行。缺点当然是解决方案不是通用的。您将需要每个基本体的策略

或者,您至少可以利用脚本中的pointsPerUnit概念来控制行的分辨率,并坚持光线投射。我认为你看到的奇怪的人工制品是由于太高的点密度造成的。使每单位距离的点数保持一致也可能有更好的性能

以下是上述脚本的结果:

感谢您的洞察力!正如您自己所指出的,不幸的是,这只适用于单个原语,但是如上所述,我至少会尝试利用pointsPerUnit变量。
[RequireComponent(typeof(LineRenderer))]
public class SurfaceLine : MonoBehaviour, IPointerClickHandler
{
    [SerializeField] private float pointsPerUnit;
    [SerializeField] private MeshFilter mesh;

    private Vector3 start;
    private Vector3 end;
    private LineRenderer lineRenderer;

    void Awake()
    {
        this.lineRenderer = this.GetComponent<LineRenderer>();
    }

    public void OnPointerClick(PointerEventData eventData)
    {
        if(eventData.button == PointerEventData.InputButton.Left)
        {
            this.start = this.transform.InverseTransformPoint(eventData.pointerCurrentRaycast.worldPosition);
            this.Render();
            return;
        }

        if(eventData.button == PointerEventData.InputButton.Right)
        {
            this.end = this.transform.InverseTransformPoint(eventData.pointerCurrentRaycast.worldPosition);
            this.Render();
        }
    }

    private void Render()
    {
        var distance = Vector3.Distance(this.end, this.start);

        var direction = (this.end - this.start).normalized;

        var numPoints = Mathf.FloorToInt(distance * this.pointsPerUnit);

        numPoints = Mathf.Max(numPoints, 2);

        this.lineRenderer.positionCount = numPoints;

        var positions = new Vector3[numPoints];

        var stepInDir = direction * (distance / (float)numPoints);

        for(int i = 0; i < numPoints; i++)
        {
            positions[i] = this.start + i * stepInDir;

            var dirFromCenter = positions[i] - this.mesh.mesh.bounds.center;

            positions[i] = this.mesh.mesh.bounds.center + dirFromCenter.normalized * (this.mesh.mesh.bounds.size.x / 2.0f);
        }

        positions[positions.Length - 1] = this.end;

        this.lineRenderer.SetPositions(positions);
    }
}