Linecast with Tags


#1

Well basically I had to do it manually. Do linecast only on nodes with appropriate tags.
I filter nodes returned by Linecast as “trace” list.
I take last proper node in chain of proper nodes and do my own intersection against mesh to get intersection point. And I think such a functionality should be implemented in a library.

BTW. Here is a part of my code:

public StraightPathCheckResult CheckStraightPathValidity(Vector3 start, Vector3 end, PathGraph pathGraph, uint pathfindingTags) {
    IRaycastableGraph reycastableGraph = this.GetRecastableGraph(pathGraph);
    if (reycastableGraph == null) {
        throw new GameException("Graph (" + pathGraph.ToString() + ") is not IRaycastableGraph");
    }
    StraightPathCheckResult straightPathCheckResult = new StraightPathCheckResult();
    List<GraphNode> traversedNodes = new List<GraphNode>();
    GraphHitInfo graphHitInfo;
    straightPathCheckResult.isStraight = !reycastableGraph.Linecast(start, end, null, out graphHitInfo, traversedNodes);
    straightPathCheckResult.hitPoint = straightPathCheckResult.isStraight ? end : graphHitInfo.point;
    straightPathCheckResult.isHitPointOnValidNode = true;
    if (pathfindingTags == ~(uint)0) {
        return straightPathCheckResult;
    }
    if (traversedNodes.Count == 0) {
        straightPathCheckResult.isHitPointOnValidNode = false;
        return straightPathCheckResult;
    }
    if (traversedNodes[0] is MeshNode) {
        for(int i=0;i <  traversedNodes.Count; i++) {
            MeshNode node = traversedNodes[i] as MeshNode;
            if ( ((1 << (int)node.Tag) & pathfindingTags) == 0) { // first invalid tag node
                if(i == 0) { //first node is invalid
                    straightPathCheckResult.isHitPointOnValidNode = false;
                    return straightPathCheckResult;
                }
                
                MeshNode lastValidNode = traversedNodes[i - 1] as MeshNode;
                int vertexCount = lastValidNode.GetVertexCount();
                Vector2[] vertices = new Vector2[vertexCount + 1];
                for(int vInd = 0; vInd < vertexCount; vInd++) {
                    Vector3 v3 = (Vector3)lastValidNode.GetVertex(vInd);
                    vertices[vInd] = new Vector2(v3.x, v3.z);
                }
                vertices[vertexCount - 1] = vertices[0];
                Vector2 startV2 = new Vector2(start.x, start.z);
                Vector2 endV2 = new Vector2(end.x, end.z);
                float minSqrDistance = float.MaxValue;
                Vector3 closestIntersection = Vector3.zero;
                for (int segmentInd = 1; segmentInd < vertexCount; segmentInd++) {
                    Vector2 intersection;
                    if(MathUtils.LineSegmentsIntersection(vertices[segmentInd - 1], vertices[segmentInd], startV2, endV2, out intersection)) {
                        float curSqrDist = (intersection - endV2).sqrMagnitude;
                        if(curSqrDist <= minSqrDistance) {
                            minSqrDistance = curSqrDist;
                            closestIntersection = new Vector3(intersection.x,0,intersection.y);
                        }
                    }
                }
                straightPathCheckResult.hitPoint = closestIntersection;
                straightPathCheckResult.isHitPointOnValidNode = true;
                straightPathCheckResult.isStraight = false;
            }
        }
    } 
    return straightPathCheckResult;
}

#2

Hi

Good suggestion!
I will add that to my todo list.