首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何反求网格

如何反求网格
EN

Stack Overflow用户
提问于 2018-10-11 21:50:54
回答 1查看 390关注 0票数 1

我正在使用教程https://www.youtube.com/watch?v=73Dc5JTCmKI中的脚本,该脚本显示视图字段。但是我想逆它,所以你看不到白色网格的地方将是白色网格,而不是我现在的,

如何反求网格,这样在哪里是绿色的颜色(没有)将是网格,在哪里是网格,就不会有网格。

我的剧本:

代码语言:javascript
复制
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class FieldOfView : MonoBehaviour {

    public float viewRadius;
    [Range(0,360)]
    public float viewAngle;

    public LayerMask targetMask;
    public LayerMask obstacleMask;

    [HideInInspector]
    public List<Transform> visibleTargets = new List<Transform>();

    public float meshResolution;
    public int edgeResolveIterations;
    public float edgeDstThreshold;

    public float maskCutawayDst = .1f;

    public MeshFilter viewMeshFilter;
    Mesh viewMesh;

    void Start() {
        viewMesh = new Mesh ();
        viewMesh.name = "View Mesh";
        viewMeshFilter.mesh = viewMesh;

        StartCoroutine ("FindTargetsWithDelay", .2f);
    }


    IEnumerator FindTargetsWithDelay(float delay) {
        while (true) {
            yield return new WaitForSeconds (delay);
            FindVisibleTargets ();
        }
    }

    void LateUpdate() {
        DrawFieldOfView ();
    }

    void FindVisibleTargets() {
        visibleTargets.Clear ();
        Collider[] targetsInViewRadius = Physics.OverlapSphere (transform.position, viewRadius, targetMask);

        for (int i = 0; i < targetsInViewRadius.Length; i++) {
            Transform target = targetsInViewRadius [i].transform;
            Vector3 dirToTarget = (target.position - transform.position).normalized;
            if (Vector3.Angle (transform.forward, dirToTarget) < viewAngle / 2) {
                float dstToTarget = Vector3.Distance (transform.position, target.position);
                if (!Physics.Raycast (transform.position, dirToTarget, dstToTarget, obstacleMask)) {
                    visibleTargets.Add (target);
                }
            }
        }
    }

    void DrawFieldOfView() {
        int stepCount = Mathf.RoundToInt(viewAngle * meshResolution);
        float stepAngleSize = viewAngle / stepCount;
        List<Vector3> viewPoints = new List<Vector3> ();
        ViewCastInfo oldViewCast = new ViewCastInfo ();
        for (int i = 0; i <= stepCount; i++) {
            float angle = transform.eulerAngles.y - viewAngle / 2 + stepAngleSize * i;
            ViewCastInfo newViewCast = ViewCast (angle);

            if (i > 0) {
                bool edgeDstThresholdExceeded = Mathf.Abs (oldViewCast.dst - newViewCast.dst) > edgeDstThreshold;
                if (oldViewCast.hit != newViewCast.hit || (oldViewCast.hit && newViewCast.hit && edgeDstThresholdExceeded)) {
                    EdgeInfo edge = FindEdge (oldViewCast, newViewCast);
                    if (edge.pointA != Vector3.zero) {
                        viewPoints.Add (edge.pointA);
                    }
                    if (edge.pointB != Vector3.zero) {
                        viewPoints.Add (edge.pointB);
                    }
                }

            }


            viewPoints.Add (newViewCast.point);
            oldViewCast = newViewCast;
        }

        int vertexCount = viewPoints.Count + 1;
        Vector3[] vertices = new Vector3[vertexCount];
        int[] triangles = new int[(vertexCount-2) * 3];

        vertices [0] = Vector3.zero;
        for (int i = 0; i < vertexCount - 1; i++) {
            vertices [i + 1] = transform.InverseTransformPoint(viewPoints [i]) + Vector3.forward * maskCutawayDst;

            if (i < vertexCount - 2) {
                triangles [i * 3] = 0;
                triangles [i * 3 + 1] = i + 1;
                triangles [i * 3 + 2] = i + 2;
            }
        }

        viewMesh.Clear ();

        viewMesh.vertices = vertices;
        viewMesh.triangles = triangles;
        viewMesh.RecalculateNormals ();
    }


    EdgeInfo FindEdge(ViewCastInfo minViewCast, ViewCastInfo maxViewCast) {
        float minAngle = minViewCast.angle;
        float maxAngle = maxViewCast.angle;
        Vector3 minPoint = Vector3.zero;
        Vector3 maxPoint = Vector3.zero;

        for (int i = 0; i < edgeResolveIterations; i++) {
            float angle = (minAngle + maxAngle) / 2;
            ViewCastInfo newViewCast = ViewCast (angle);

            bool edgeDstThresholdExceeded = Mathf.Abs (minViewCast.dst - newViewCast.dst) > edgeDstThreshold;
            if (newViewCast.hit == minViewCast.hit && !edgeDstThresholdExceeded) {
                minAngle = angle;
                minPoint = newViewCast.point;
            } else {
                maxAngle = angle;
                maxPoint = newViewCast.point;
            }
        }

        return new EdgeInfo (minPoint, maxPoint);
    }


    ViewCastInfo ViewCast(float globalAngle) {
        Vector3 dir = DirFromAngle (globalAngle, true);
        RaycastHit hit;

        if (Physics.Raycast (transform.position, dir, out hit, viewRadius, obstacleMask)) {
            return new ViewCastInfo (true, hit.point, hit.distance, globalAngle);
        } else {
            return new ViewCastInfo (false, transform.position + dir * viewRadius, viewRadius, globalAngle);
        }
    }

    public Vector3 DirFromAngle(float angleInDegrees, bool angleIsGlobal) {
        if (!angleIsGlobal) {
            angleInDegrees += transform.eulerAngles.y;
        }
        return new Vector3(Mathf.Sin(angleInDegrees * Mathf.Deg2Rad),0,Mathf.Cos(angleInDegrees * Mathf.Deg2Rad));
    }

    public struct ViewCastInfo {
        public bool hit;
        public Vector3 point;
        public float dst;
        public float angle;

        public ViewCastInfo(bool _hit, Vector3 _point, float _dst, float _angle) {
            hit = _hit;
            point = _point;
            dst = _dst;
            angle = _angle;
        }
    }

    public struct EdgeInfo {
        public Vector3 pointA;
        public Vector3 pointB;

        public EdgeInfo(Vector3 _pointA, Vector3 _pointB) {
            pointA = _pointA;
            pointB = _pointB;
        }
    }

}

我知道我必须改变一些三角形,但我不知道如何设置它们。

代码语言:javascript
复制
    vertices [0] = Vector3.zero;
for (int i = 0; i < vertexCount - 1; i++) {
    vertices [i + 1] = transform.InverseTransformPoint(viewPoints [i]) + Vector3.forward * maskCutawayDst;

    if (i < vertexCount - 2) {
        triangles [i * 3] = 0;
        triangles [i * 3 + 1] = i + 1;
        triangles [i * 3 + 2] = i + 2;
    }
}

viewMesh.Clear ();

viewMesh.vertices = vertices;
viewMesh.triangles = triangles;
viewMesh.RecalculateNormals ();

对不起,我不知道如何更好地解释它。

编辑,所以我仍然有一些问题。你的解决方案对我没用。首先,没有"circleRadius",所以我使用viewRadius代替它。其次,它给我的论点始终超出范围。我的代码稍微变了一点,下面是它的外观:

代码语言:javascript
复制
        int vertexCount = viewPoints.Count + 1;
    var vertices = new Vector3[vertexCount];
    var triangles = new int[(vertexCount - 2) * 3];

    vertices[0] = Vector3.zero;
    for (int i = 0; i < vertexCount - 1; i++)
    {
        vertices[i + 1] = transform.InverseTransformPoint(viewPoints[i]);

        if (i < vertexCount - 2)
        {
            triangles[i * 3] = 0;
            triangles[i * 3 + 1] = i + 1;
            triangles[i * 3 + 2] = i + 2;
        }
    }

所以在这种情况下,我应该把它改为:

代码语言:javascript
复制
        int vertexCount = viewPoints.Count + 1;
    Vector3[] vertices = new Vector3[(vertexCount) * 2];
    int[] triangles = new int[(vertexCount) * 6];

    for (int i = 0; i < (vertexCount - 1) * 2; i += 2)
    {
        vertices[i] = transform.InverseTransformPoint(viewPoints[i]);
        vertices[i + 1] = Vector3.Normalize(viewPoints[i]) * viewRadius;
    }
    for (int i = 0; i < (vertexCount - 3) * 2; i += 1)
    {
        triangles[i * 6 + 0] = i * 4;
        triangles[i * 6 + 1] = i * 4 + 1;
        triangles[i * 6 + 2] = i * 4 + 2;
        triangles[i * 6 + 3] = i * 4 + 1;
        triangles[i * 6 + 4] = i * 4 + 2;
        triangles[i * 6 + 5] = i * 4 + 3;
    }

编辑2

所以我修改了我的代码,这很好,但是当我在播放模式下测试它时,它会给我错误:

代码语言:javascript
复制
ArgumentOutOfRangeException: Argument is out of range.
Parameter name: index
FieldOfViews.DrawFieldOfView () (at Assets/_Game/FieldOfView.cs:111)

它在网上:

代码语言:javascript
复制
vertices[i] = transform.InverseTransformPoint(viewPoints[i]) + Vector3.forward * maskCutawayDst;

当我为测试目的移除这条车道时,它还在以下方面出现了相同的错误:

代码语言:javascript
复制
vertices[i + 1] = Vector3.Normalize(viewPoints[i]) * circleRadius;

我不知道这是否会导致问题,但我的maskCutawayDst是0.1,circleRadius是15。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-10-11 22:22:26

密码如下:

代码语言:javascript
复制
  int vertexCount = viewPoints.Count + 1;
    Vector3[] vertices = new Vector3[vertexCount];
    int[] triangles = new int[(vertexCount-2) * 3];

    vertices [0] = Vector3.zero;
    for (int i = 0; i < vertexCount - 1; i++) {
        vertices [i + 1] = transform.InverseTransformPoint(viewPoints [i]) + Vector3.forward * maskCutawayDst;

        if (i < vertexCount - 2) {
            triangles [i * 3] = 0;
            triangles [i * 3 + 1] = i + 1;
            triangles [i * 3 + 2] = i + 2;
        }
    }

变到

代码语言:javascript
复制
        int vertexCount = viewPoints.Count + 1;
        Vector3[] vertices = new Vector3[(vertexCount) * 2];
        int[] triangles = new int[(vertexCount) * 6];

        for (int i = 0; i < vertexCount; i++)
        {
            Vector3 vertex = transform.InverseTransformPoint(viewPoints[(i == viewPoints.Count) ? 0 : i]);
            vertices[i * 2] = vertex;
            vertices[i * 2 + 1] = vertex.normalized * viewRadius;
        }
        for (int i = 0; i < (vertexCount); i++)
        {
            int j = (vertexCount - 1 == i) ? 0 : i;
            triangles[i * 6 + 0] = j * 2 + 0;
            triangles[i * 6 + 1] = j * 2 + 1;
            triangles[i * 6 + 2] = j * 2 + 2;
            triangles[i * 6 + 3] = j * 2 + 1;
            triangles[i * 6 + 4] = j * 2 + 3;
            triangles[i * 6 + 5] = j * 2 + 2;
        }

解释:

图1:正在发生的事情的一部分

第一个程序在红色区域创建了一个三角形。这是在中间和两条相交射线之间(相交的红线)。要“逆”这一点,我们必须将这两条线作为一个四角线连接到一个固定距离的外部点。将向量归一化为有一个单位长度,然后乘以具有所有点的固定距离。这是用代码完成的。

代码语言:javascript
复制
   for (int i = 0; i < vertexCount; i++)
        {
            Vector3 vertex = transform.InverseTransformPoint(viewPoints[(i == viewPoints.Count) ? 0 : i]);
            vertices[i * 2] = vertex;
            vertices[i * 2 + 1] = vertex.normalized * viewRadius;
        }

然后将这些顶点转换成两个三角形(以表示一个四角)。下面的代码。形成了绿色的区域。

代码语言:javascript
复制
for (int i = 0; i < (vertexCount); i++)
{
    int j = (vertexCount - 1 == i) ? 0 : i;
    triangles[i * 6 + 0] = j * 2 + 0;
    triangles[i * 6 + 1] = j * 2 + 1;
    triangles[i * 6 + 2] = j * 2 + 2;
    triangles[i * 6 + 3] = j * 2 + 1;
    triangles[i * 6 + 4] = j * 2 + 3;
    triangles[i * 6 + 5] = j * 2 + 2;
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52769405

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档