Пример #1
0
        public void SetupTrajectory(PrincipalSpace3D principalSpace3D,
                                    PrincipalTrajectory principalTrajectory,
                                    Vector3 principalTargetPosition,
                                    float marginDistance)
        {
            _principalSpace3D        = principalSpace3D;
            _principalTrajectory     = principalTrajectory;
            _principalTargetPosition = principalTargetPosition;
            _marginDistance          = marginDistance;

            _triangleOverTriangleSoupHelper.SetupTrajectory(principalTrajectory, principalTargetPosition);
        }
Пример #2
0
            public void SetupTrajectory(PrincipalTrajectory principalTrajectory, Vector2 principalTargetPosition)
            {
                float k         = principalTrajectory.k;
                float vInfinity = principalTrajectory.vInfinity;
                float v0x       = principalTrajectory.v0.x;
                float v0y       = principalTrajectory.v0.y;

                _twoAPerDY           = (k + k) * v0x;
                _twoAPerDX           = -(k + k) * (v0y + vInfinity);
                _bPerDYAndCPerBiasDX = -v0x * v0x;
                _bPerBiasDX          = v0x * k;
                _bPerDX              = v0x * v0y;
                _targetPosition      = principalTargetPosition;
                _principalTrajectory = principalTrajectory;
            }
Пример #3
0
            // Find a trajectory for which the trajectory's y is at least as high as any
            // of the vertices remaining in _edgesOnPrincipalPlane.
            private float GetTimeToTargetOnIntersection(
                PrincipalSpace3D principalSpace3D,
                PrincipalTrajectory principalTrajectory,
                Vector2 principalTargetPosition)
            {
                for (int index = 0; index < _edgesOnPrincipalPlane.vertexCount; index += 2)
                {
                    if (_edgeClassifier.CrossesXBound(
                            _edgesOnPrincipalPlane.vertices[index],
                            _edgesOnPrincipalPlane.vertices[index + 1]))
                    {
                        return(0);
                    }
                }


                float timeToTarget = 0.0f;

                for (int index = 0; index < _edgesOnPrincipalPlane.vertexCount; index += 2)
                {
                    Vector2 vertex = _edgesOnPrincipalPlane.vertices[index];
                    if (principalTrajectory.PositionYAtX(vertex.x) < vertex.y)
                    {
                        /*
                         * Debug.DrawLine(principalSpace3D.p0,
                         *             principalSpace3D.p0 + principalSpace3D.xAxis * vertex.x + principalSpace3D.yAxis * vertex.y,
                         *             Color.grey);
                         */
                        timeToTarget = PrincipalTimePlanners.GetTimeToTargetRGivenIntermediatePositionQ(
                            principalTrajectory,
                            principalTargetPosition,
                            vertex);

                        principalTrajectory.v0 =
                            principalTrajectory.GetInitialVelocityGivenRelativeTargetAndTime(
                                principalTargetPosition, timeToTarget);
                    }
                }
                return(timeToTarget);
            }
Пример #4
0
            public float GetTimeToTargetOverTriangleSoup(
                PrincipalSpace3D principalSpace3D,
                PrincipalTrajectory principalTrajectory,
                Vector2 principalTargetPosition,
                Vector3[] principalVertices,
                int[] indexTriplets)
            {
                int numTriangles = indexTriplets.Length / 3;

                bool foundIntersection = false;

                _edgesOnPrincipalPlane.Initialize(numTriangles);

                for (int index = 0; index < indexTriplets.Length; index += 3)
                {
                    // Get the vertices of the current triangle
                    Vector3 v0 = principalVertices[indexTriplets[index]];
                    Vector3 v1 = principalVertices[indexTriplets[index + 1]];
                    Vector3 v2 = principalVertices[indexTriplets[index + 2]];

                    // Test if triangle intersects the principal plane
                    if (_edgesOnPrincipalPlane.TryAddTriangle(v0, v1, v2))
                    {
                        bool withinXRange;


                        Debug.DrawLine(principalSpace3D.p0 +
                                       principalSpace3D.xAxis * _edgesOnPrincipalPlane.vertices[_edgesOnPrincipalPlane.vertexCount - 2].x +
                                       principalSpace3D.yAxis * _edgesOnPrincipalPlane.vertices[_edgesOnPrincipalPlane.vertexCount - 2].y,
                                       principalSpace3D.p0 +
                                       principalSpace3D.xAxis * _edgesOnPrincipalPlane.vertices[_edgesOnPrincipalPlane.vertexCount - 1].x +
                                       principalSpace3D.yAxis * _edgesOnPrincipalPlane.vertices[_edgesOnPrincipalPlane.vertexCount - 1].y,
                                       _edgeClassifier.IntersectsTrajectory(
                                           _edgesOnPrincipalPlane.vertices[_edgesOnPrincipalPlane.vertexCount - 2],
                                           _edgesOnPrincipalPlane.vertices[_edgesOnPrincipalPlane.vertexCount - 1],
                                           out withinXRange) ? Color.red : ((v1.z - v0.z) * (v2.x - v0.x) - (v1.x - v0.x) * (v2.z - v0.z) > 0 ? Color.blue : Color.green));


                        // Test if the triangle intersects the trajectory
                        if (_edgeClassifier.IntersectsTrajectory(
                                _edgesOnPrincipalPlane.vertices[_edgesOnPrincipalPlane.vertexCount - 2],
                                _edgesOnPrincipalPlane.vertices[_edgesOnPrincipalPlane.vertexCount - 1],
                                out withinXRange))
                        {
                            foundIntersection = true;
                        }

                        // Discard all segments for down-facing triangles and those
                        // segments that are outside the trajectory's valid x range.
                        // What remains is kept around for the case a trajectory over
                        // the obstacles needs to be calculated later on.
                        bool facesDown = (v1.z - v0.z) * (v2.x - v0.x) - (v1.x - v0.x) * (v2.z - v0.z) < 0;
                        if (!withinXRange || facesDown)
                        {
                            _edgesOnPrincipalPlane.RemoveLastAddedEdge();
                        }
                    }
                }

                if (foundIntersection)
                {
                    return(GetTimeToTargetOnIntersection(principalSpace3D, principalTrajectory, principalTargetPosition));
                }

                return(-1);
            }
Пример #5
0
 public void SetupTrajectory(PrincipalTrajectory principalTrajectory, Vector2 principalTargetPosition)
 {
     _edgeClassifier.SetupTrajectory(principalTrajectory, principalTargetPosition);
 }
Пример #6
0
    public override bool PlanTimeToTarget(Projectile3D projectile3D,
                                          Vector3 initialPosition,
                                          Vector3 targetPosition,
                                          ref float timeToTarget)
    {
        // Allow this planner to only modify an already existing plan, not create a new one.
        if (timeToTarget <= 0)
        {
            return(false);
        }

        // Convert the problem to principal space
        PrincipalProjectile principalProjectile;
        PrincipalSpace3D    principalSpace3D = PrincipalSpace3D.Create(projectile3D,
                                                                       initialPosition, targetPosition, out principalProjectile);

        Vector2 principalTargetPosition = principalSpace3D.ToPrincipalPosition(targetPosition);

        PrincipalTrajectory principalTrajectory = new PrincipalTrajectory(principalProjectile);

        principalTrajectory.v0 = principalTrajectory.GetInitialVelocityGivenRelativeTargetAndTime(
            principalTargetPosition, timeToTarget);

        // notify helper classes/structs of the trajectory to test
        _trajectoryOverGameObjectHelper.SetupTrajectory(principalSpace3D, principalTrajectory, principalTargetPosition, marginDistance);

        // (Re-)check all the gameobjects until no further intersections are detected, or until
        // an intersecting gameobject is found that can't have a trajectory passing over it.
        int lastIntersectingGameObjectIndex = -1;

        //bool foundAnotherIntersection;
        //do
        {
            //foundAnotherIntersection = false;

            for (int index = 0; index < obstacles.Length; ++index)
            {
                if (index != lastIntersectingGameObjectIndex)
                {
                    float foundTimeToTarget = _trajectoryOverGameObjectHelper.GetTimeToTargetOverGameObject(obstacles[index]);
                    if (foundTimeToTarget >= 0) // found intersection
                    {
                        //foundAnotherIntersection = true;
                        lastIntersectingGameObjectIndex = index;
                        timeToTarget = foundTimeToTarget;
                        if (timeToTarget == 0)
                        {
                            return(true); // trajectory over the object is impossible, so give up
                        }

                        // use the new initial velocity in the tested trajecory
                        principalTrajectory.v0 = principalTrajectory.GetInitialVelocityGivenRelativeTargetAndTime(
                            principalTargetPosition, timeToTarget);
                        // notify helper classes/structs of the new trajectory to test
                        _trajectoryOverGameObjectHelper.SetupTrajectory(principalSpace3D,
                                                                        principalTrajectory, principalTargetPosition, marginDistance);
                    }
                }
            }
        }
        //while (foundAnotherIntersection);

        return(lastIntersectingGameObjectIndex >= 0); // true iff the plan changed
    }
Пример #7
0
            public bool IntersectsPrincipalRectangle(
                PrincipalSpace3D principalSpace3D,
                PrincipalTrajectory principalTrajectory,
                Vector2 principalTargetPosition,
                Matrix4x4 localToWorldMatrix,
                Vector3 boundsCenter,
                Vector3 boundsExtents,
                float marginDistance,
                ref Matrix4x4 localToPrincipalMatrix)
            {
                _localToWorldMatrix = localToWorldMatrix;

                Vector3 axisZ = Vector3.Cross(principalSpace3D.xAxis, principalSpace3D.yAxis);

                // Get the non-uniform scale of the matrix based on the bounding box size
                // and marginDistance
                Vector3 scale = GetMarginMatrixScale(boundsExtents, marginDistance);

                // Get the data necessary to get the z component in principal space
                // of any local vertex (not considering translation yet).
                localToPrincipalMatrix.m20 = DotMatrixColumn0(axisZ) * scale.x;
                localToPrincipalMatrix.m21 = DotMatrixColumn1(axisZ) * scale.y;
                localToPrincipalMatrix.m22 = DotMatrixColumn2(axisZ) * scale.z;

                Vector3 relBoundsCenter        = _localToWorldMatrix.MultiplyPoint(boundsCenter) - principalSpace3D.p0;
                float   principalBoundsCenterZ = Vector3.Dot(relBoundsCenter, axisZ);

                // Get the bounding box size projected onto the principal z axis
                float extentsZ = Mathf.Abs(localToPrincipalMatrix.m20) * boundsExtents.x +
                                 Mathf.Abs(localToPrincipalMatrix.m21) * boundsExtents.y +
                                 Mathf.Abs(localToPrincipalMatrix.m22) * boundsExtents.z;

                if (Mathf.Abs(principalBoundsCenterZ) > extentsZ)
                {
                    return(false); // bounding box doens't intersect the principal plane
                }

                // Get the data necessary to get the x component in principal space
                // of any local vertex (not considering translation yet).
                localToPrincipalMatrix.m00 = DotMatrixColumn0(principalSpace3D.xAxis) * scale.x;
                localToPrincipalMatrix.m01 = DotMatrixColumn1(principalSpace3D.xAxis) * scale.y;
                localToPrincipalMatrix.m02 = DotMatrixColumn2(principalSpace3D.xAxis) * scale.z;

                // Test the bounding box projected on the x axis of the principal space
                // against the initial (i.e. min) and target (i.e. max) x interval.
                float principalBoundsCenterX = Vector3.Dot(relBoundsCenter, principalSpace3D.xAxis);
                float extentsX = Mathf.Abs(localToPrincipalMatrix.m00) * boundsExtents.x +
                                 Mathf.Abs(localToPrincipalMatrix.m01) * boundsExtents.y +
                                 Mathf.Abs(localToPrincipalMatrix.m02) * boundsExtents.z;

                if (principalBoundsCenterX + extentsX < 0 ||
                    principalBoundsCenterX - extentsX > principalTargetPosition.x)
                {
                    return(false);
                }

                // Get the data necessary to get the y component in principal space
                // of any local vertex (not considering translation yet).
                localToPrincipalMatrix.m10 = DotMatrixColumn0(principalSpace3D.yAxis) * scale.x;
                localToPrincipalMatrix.m11 = DotMatrixColumn1(principalSpace3D.yAxis) * scale.y;
                localToPrincipalMatrix.m12 = DotMatrixColumn2(principalSpace3D.yAxis) * scale.z;

                // Test the bounding box projected on the y axis of the principal space
                // against the min and max y interval.
                float principalBoundsCenterY = Vector3.Dot(relBoundsCenter, principalSpace3D.yAxis);
                float extentsY = Mathf.Abs(localToPrincipalMatrix.m10) * boundsExtents.x +
                                 Mathf.Abs(localToPrincipalMatrix.m11) * boundsExtents.y +
                                 Mathf.Abs(localToPrincipalMatrix.m12) * boundsExtents.z;

                if (principalBoundsCenterY + extentsY < Mathf.Min(0.0f, principalTargetPosition.y) ||
                    principalBoundsCenterY - extentsY > principalTrajectory.PositionAtTime(
                        principalTrajectory.GetTimeAtMaximumHeight()).y)
                {
                    return(false);
                }

                // Get the data necessary to do the translation part from local to
                // principal space
                Vector3 delta = new Vector3(_localToWorldMatrix.m03 - principalSpace3D.p0.x,
                                            _localToWorldMatrix.m13 - principalSpace3D.p0.y,
                                            _localToWorldMatrix.m23 - principalSpace3D.p0.z);

                localToPrincipalMatrix.m03 = Vector3.Dot(delta, principalSpace3D.xAxis);
                localToPrincipalMatrix.m13 = Vector3.Dot(delta, principalSpace3D.yAxis);
                localToPrincipalMatrix.m23 = Vector3.Dot(delta, axisZ);

                // No projection components
                localToPrincipalMatrix.m30 = 0;
                localToPrincipalMatrix.m31 = 0;
                localToPrincipalMatrix.m32 = 0;
                localToPrincipalMatrix.m33 = 1;

                return(true);
            }