//Caluclate tip path trajectory
 public void calculatePath()
 {
     if (arrowTipMode == ArrowTipMode.None) return;
     if (arrowTipPathType == ArrowTipPathType.FollowMainPath)
     {
         //path is caluclated by ArrowPath class, just calculate the length
         pathLength = 0;
         for (int i = 1; i < path.Count; i++)
         {
             pathLength += (path[i] - path[i - 1]).magnitude;
         }
         return;
     }
     //Default values for all functions if not set
     ArrowPath.validateAnimationFunction(pathAlongXFunction, 0, 0);
     ArrowPath.validateAnimationFunction(pathAlongYFunction, 0, 0);
     ArrowPath.validateAnimationFunction(pathAlongZFunction, 0, 0);
     float currentPercentage = 0;
     path = new List<Vector3>();
     //Set the first path point
     Vector3 tipDirection = end - start;
     Quaternion arrowTipRotation = Quaternion.FromToRotation(Vector3.up, tipDirection);
     path.Add(start + arrowTipRotation * new Vector3(pathAlongXFunction.Evaluate(0), pathAlongYFunction.Evaluate(0), pathAlongZFunction.Evaluate(0)));
     pathLength = 0;
     int[] currentKey = new int[3] { 0, 0, 0 };
     int currentKeyIndex = -1;
     float lastPathDifference = 0;
     //find the next Point
     increasePathPercentage(ref currentKeyIndex, ref currentPercentage, ref currentKey);
     while (true)
     {
         Vector3 pathItem;
         // add points until 100%
         if (currentPercentage >= 1.0f)
         {
             //Put the last point exacly at 100%
             pathItem = end + arrowTipRotation * new Vector3(pathAlongXFunction.Evaluate(pathAlongXFunctionLength), pathAlongYFunction.Evaluate(pathAlongYFunctionLength), pathAlongZFunction.Evaluate(pathAlongZFunctionLength));
             lastPathDifference = (path[path.Count - 1] - pathItem).magnitude;
             if (lastPathDifference > errorRate) path.Add(pathItem);
             pathLength += lastPathDifference;
             break;
         }
         pathItem = start + currentPercentage * tipDirection + arrowTipRotation * new Vector3(pathAlongXFunction.Evaluate(currentPercentage * pathAlongXFunctionLength), pathAlongYFunction.Evaluate(currentPercentage * pathAlongYFunctionLength), pathAlongZFunction.Evaluate(currentPercentage * pathAlongZFunctionLength));
         lastPathDifference = (path[path.Count - 1] - pathItem).magnitude;
         //never put the same path point twice
         if (lastPathDifference > errorRate) path.Add(pathItem);
         pathLength += lastPathDifference;
         increasePathPercentage(ref currentKeyIndex, ref currentPercentage, ref currentKey);
     }
 }
Exemple #2
0
        //Generate the extrude array
        public void generate()
        {
            if (arrowTipMode == ArrowTipMode.None)
            {
                return;
            }
            //set default functions if not set
            ArrowPath.validateAnimationFunction(widthFunction, 1, 0);
            ArrowPath.validateAnimationFunction(heightFunction, 1, 0);
            ArrowPath.validateAnimationFunction(rotateFunction, 0, 0);
            ArrowPath.validateAnimationFunction(shapeFunction, 0, 0);
            if (pathLength == 0)
            {
                return;
            }
            extrudePoints = new Matrix4x4[path.Count];
            primitives    = new Primitive[path.Count];
            openClosed    = new int[path.Count];
            float currentLength = 0;

            extrudePoints[0] = new Matrix4x4();
            //Calculate the first extrude
            Vector3 pathDiff = direction * (path[1] - path[0]);

            arrowPath.defaultRotateAngle = defaultRotateAngle;
            Quaternion nextDirectionX;
            Quaternion nextDirectionY;
            Quaternion extrudeDirectionX;
            Quaternion extrudeDirectionY;
            Quaternion lastDirectionX;
            Quaternion lastDirectionY;

            //First rotation depends on first path point direction and rotation from main path
            nextDirectionX = arrowPath.calculateUpDownQuaternion(pathDiff);
            nextDirectionY = arrowPath.calculateLeftRightQuaternion(pathDiff);
            lastDirectionX = nextDirectionX;
            lastDirectionY = nextDirectionY;
            float propagatingRotateAngle = 0;

            if (direction == -1)
            {
                propagatingRotateAngle = arrowPath.rotateFunction.Evaluate(0);
            }
            else
            {
                propagatingRotateAngle = arrowPath.rotateFunction.Evaluate(arrowPath.rotationFunctionLength);
            }
            extrudePoints[0].SetTRS(path[0], Quaternion.AngleAxis((rotateFunction.Evaluate(currentLength / pathLength * rotationFunctionLength) + propagatingRotateAngle) * 360, nextDirectionY * nextDirectionX * Vector2.up) * nextDirectionY * nextDirectionX, new Vector3(widthFunction.Evaluate(currentLength / pathLength * widthFunctionLength) * size.x, 1, heightFunction.Evaluate(currentLength / pathLength * heightFunctionLength) * size.z));
            //choose shape
            int primitiveIndex = (int)shapeFunction.Evaluate(0);

            if (primitiveIndex < 0)
            {
                primitiveIndex = 0;
            }
            if (primitiveIndex >= templatePrimitives.primitivesList.Count)
            {
                primitiveIndex = templatePrimitives.primitivesList.Count - 1;
            }
            primitives[0] = templatePrimitives.primitivesList[primitiveIndex];
            openClosed[0] = (getClosed()) ? 0 : 1;
            //Calculate the other extrude points
            for (int i = 1; i < path.Count; i++)
            {
                currentLength   += (path[i] - path[i - 1]).magnitude;
                extrudePoints[i] = new Matrix4x4();
                float scaleWidthByAngle  = 1f;
                float scaleHeightByAngle = 1f;
                if (i < path.Count - 1)
                {
                    pathDiff       = direction * (path[i + 1] - path[i]);
                    nextDirectionX = arrowPath.calculateUpDownQuaternion(pathDiff);
                    nextDirectionY = arrowPath.calculateLeftRightQuaternion(pathDiff);
                    //Points depend on previous and next point directions
                    if (Quaternion.Angle(lastDirectionX, nextDirectionX) < 0.1f)
                    {
                        extrudeDirectionX = nextDirectionX;
                    }
                    else
                    {
                        extrudeDirectionX = Quaternion.Lerp(lastDirectionX, nextDirectionX, 0.5f);
                    }
                    if (Quaternion.Angle(lastDirectionY, nextDirectionY) < 0.1f)
                    {
                        extrudeDirectionY = nextDirectionY;
                    }
                    else
                    {
                        extrudeDirectionY = Quaternion.Lerp(lastDirectionY, nextDirectionY, 0.5f);
                    }
                    //Scale depends on angle between points
                    scaleWidthByAngle  = Mathf.Abs(Mathf.Cos(Mathf.Deg2Rad * Vector3.Angle(lastDirectionY * Vector3.forward, nextDirectionY * Vector3.forward) / 2));
                    scaleWidthByAngle  = (scaleWidthByAngle < 0.5f) ? 1 : 1 / scaleWidthByAngle;
                    scaleHeightByAngle = Mathf.Abs(Mathf.Cos(Mathf.Deg2Rad * Vector3.Angle(lastDirectionX * Vector3.up, nextDirectionX * Vector3.up) / 2));
                    scaleHeightByAngle = (scaleHeightByAngle < 0.5f) ? 1 : 1 / scaleHeightByAngle;
                }
                else
                {
                    pathDiff          = direction * (path[i] - path[i - 1]);
                    nextDirectionX    = arrowPath.calculateUpDownQuaternion(pathDiff);
                    nextDirectionY    = arrowPath.calculateLeftRightQuaternion(pathDiff);
                    extrudeDirectionX = nextDirectionX;
                    extrudeDirectionY = nextDirectionY;
                }
                extrudePoints[i].SetTRS(path[i], Quaternion.AngleAxis((rotateFunction.Evaluate(currentLength / pathLength * rotationFunctionLength) + propagatingRotateAngle) * 360, extrudeDirectionY * extrudeDirectionX * Vector3.up) * extrudeDirectionY * extrudeDirectionX, new Vector3(scaleWidthByAngle * widthFunction.Evaluate(currentLength / pathLength * widthFunctionLength) * size.x, 1, scaleHeightByAngle * heightFunction.Evaluate(currentLength / pathLength * heightFunctionLength) * size.z));
                primitiveIndex = (int)(shapeFunction.Evaluate(currentLength / pathLength * shapeFunctionLength));
                if (primitiveIndex < 0)
                {
                    primitiveIndex = 0;
                }
                if (primitiveIndex >= templatePrimitives.primitivesList.Count)
                {
                    primitiveIndex = templatePrimitives.primitivesList.Count - 1;
                }
                primitives[i]  = templatePrimitives.primitivesList[primitiveIndex];
                openClosed[i]  = 1;
                lastDirectionX = nextDirectionX;
                lastDirectionY = nextDirectionY;
            }
            openClosed[path.Count - 1] = 2;
        }