/* * Returns the circle center position of the new path that starts at given intersection and uses given curve and radius. * */ private Vector3 calculateCircleCenterOfPath(VirtualIntersection startIntersection, Curve curve, float radius) { int newPathIndex = this.getPathIndex(startIntersection.getJoint(), curve); Vector3 directionToCurveCircleCenter = (curve.getCircleCenter() - startIntersection.getJoint().getWalkingStartPosition(newPathIndex)).normalized; Vector3 directionToPathCircleCenter = new Vector3(); // Check which paths are connected to the intersection and pick one (first) for calculation. // New path circle center can be calculated by using the direction to the curve circle center and rotating it. for (int i = 0; i < 4; i++) { if (startIntersection.getPath(i) != null) { Vector3 directionToStartWalkingPosOnPath = (startIntersection.getWalkingStartPosition(i) - startIntersection.getPosition()).normalized; Vector3 directionToStartWalkingPosOnCurve = (startIntersection.getJoint().getWalkingStartPosition(i) - startIntersection.getJoint().getPosition()).normalized; float angle = -angle360(directionToStartWalkingPosOnPath, directionToStartWalkingPosOnCurve); directionToPathCircleCenter = Quaternion.AngleAxis(angle, Vector3.up) * directionToCurveCircleCenter; break; } if (i == 3) { // If no case was chosen this is the start joint. Then, // we can use the curve circle center for calculating the path circle center without rotating. directionToPathCircleCenter = directionToCurveCircleCenter; } } Vector3 result = startIntersection.getWalkingStartPosition(newPathIndex) + directionToPathCircleCenter.normalized * radius; return(result); }
/* * Checks if user reached an intersection. * */ private bool isPathLeft(VirtualIntersection intersection) { int direction = getRedirectionDirection(intersection.getJoint(), currentPath.getCurve()); int pathIndex = data.getPathIndex(intersection.getJoint(), currentPath.getCurve()); Vector3 directionToPathCircleCenter = (currentPath.getCurve().getCircleCenter() - intersection.getJoint().getWalkingStartPosition(pathIndex)).normalized; Vector3 rotatedDirectionVector = Quaternion.AngleAxis(-direction * 90f, Vector3.up) * directionToPathCircleCenter; Plane plane = new Plane(rotatedDirectionVector.normalized, intersection.getJoint().getWalkingStartPosition(pathIndex)); if (plane.GetSide(Camera.main.transform.localPosition)) { return(false); } return(true); }
/* * Stops the redirection at the given intersection. * Sets current intersection and current joint to the next point. * If this intersection is not the same intersection the user started, the rotation angle is added (bool addAngle). * */ private void stopRedirection(VirtualIntersection intersection, bool addAngle) { currentIntersection = intersection; currentJoint = currentIntersection.getJoint(); if (addAngle) { oldRotation += Mathf.Rad2Deg * -redirectionDirection * (angleWalkedOnRealCircle - angleWalkedOnVirtualCircle); //(Mathf.Abs(currentCurve.getAngle()) - Mathf.Abs(currentPath.getAngle())) * -redirectionDirection; } redirectionStarted = false; Debug.Log("Redirection stopped at joint: " + currentJoint.getLabel() + ", intersection: " + currentIntersection.getLabel() + " (old rotation: " + oldRotation + ")"); }
void Start() { Debug.Log("Application started"); if (data == null) { this.loadPathLayout(pathLayoutAsset); } else { currentIntersection = data.intersections [0]; currentJoint = currentIntersection.getJoint(); } }
/* * Loads path layout asset with the specified name from a resources folder. * */ public void loadPathLayout(string layoutName) { pathLayoutAsset = layoutName; // Load data structure object (created by tool) from disk data = (RedirectionDataStructure)Resources.LoadAll(pathLayoutAsset)[0] as RedirectionDataStructure; if (data != null) { //Debug.Log("Label: " + data.jointPointA.getLabel()); currentIntersection = data.intersections[0]; currentJoint = currentIntersection.getJoint(); } else { Debug.Log("Data is null"); } }
/* * Returns the joint point that corresponds to the new end intersection that is connected to the given curve and * starts at the given intersection. * */ private JointPoint getCorrespondingEndJointPoint(VirtualIntersection intersection, Curve curve) { if (intersection.getJoint().Equals(jointPointA)) { if (curve.Equals(curveABsmallRadius)) { return(jointPointB); } if (curve.Equals(curveABlargeRadius)) { return(jointPointB); } if (curve.Equals(curveACsmallRadius)) { return(jointPointC); } if (curve.Equals(curveAClargeRadius)) { return(jointPointC); } } if (intersection.getJoint().Equals(jointPointB)) { if (curve.Equals(curveABsmallRadius)) { return(jointPointA); } if (curve.Equals(curveABlargeRadius)) { return(jointPointA); } if (curve.Equals(curveBCsmallRadius)) { return(jointPointC); } if (curve.Equals(curveBClargeRadius)) { return(jointPointC); } } if (intersection.getJoint().Equals(jointPointC)) { if (curve.Equals(curveBCsmallRadius)) { return(jointPointB); } if (curve.Equals(curveBClargeRadius)) { return(jointPointB); } if (curve.Equals(curveACsmallRadius)) { return(jointPointA); } if (curve.Equals(curveAClargeRadius)) { return(jointPointA); } } return(jointPointB); }
/* * Creates a new path and the corresponding intersection at the end. * */ public void createPathAndIntersection(VirtualIntersection startIntersection, Curve curve, float gain) { // Calculate radius of virtual path float radius = curve.getRadius() * gain; // Calculate length of curve float length = Mathf.Deg2Rad * curve.getAngle() * curve.getRadius(); // Calculate angle of virtual path float angle = Mathf.Rad2Deg * (length / radius); int newPathIndex = this.getPathIndex(startIntersection.getJoint(), curve); // Calculate end joint point JointPoint endJointPoint = getCorrespondingEndJointPoint(startIntersection, curve); // Calculate the circle center of the new path Vector3 circleCenter = calculateCircleCenterOfPath(startIntersection, curve, radius); // Calculate (nomralized) direction vector from circle center to start intersection Vector3 directionToStartPath = (startIntersection.getWalkingStartPosition(newPathIndex) - circleCenter).normalized; // Calculate direction vector from circle center to end intersection by: // 1. rotating the direction vector to start intersection (around angle of path and angle of walking zone) // 2. extending the vector by the virtual radius float angleOfWalkingZone = Mathf.Rad2Deg * startIntersection.getJoint().getWalkingZoneRadius() / radius; Vector3 directionToEndPath = Quaternion.AngleAxis(this.getSignOfCurve(startIntersection.getJoint(), endJointPoint) * angle, Vector3.up) * directionToStartPath; directionToEndPath = directionToEndPath * radius; Vector3 directionToEndIntersection = Quaternion.AngleAxis(this.getSignOfCurve(startIntersection.getJoint(), endJointPoint) * angleOfWalkingZone, Vector3.up) * directionToEndPath; // Calculate position of new end intersection Vector3 positionEndIntersection = circleCenter + directionToEndIntersection; VirtualIntersection endIntersection = CreateInstance <VirtualIntersection>(); endIntersection.init(positionEndIntersection, endJointPoint, "" + intersections.Count); List <VirtualIntersection> endPoints = new List <VirtualIntersection>(); endPoints.Add(startIntersection); endPoints.Add(endIntersection); VirtualPath path = CreateInstance <VirtualPath>(); path.init(circleCenter, gain, curve, endPoints, radius, angle); intersections.Add(endIntersection); paths.Add(path); startIntersection.addPath(path, this.getPathIndex(startIntersection.getJoint(), curve)); endIntersection.addPath(path, this.getPathIndex(endJointPoint, curve)); calculateWalkingStartPositions(this.getPathIndex(endJointPoint, curve), endJointPoint, endIntersection, circleCenter, directionToEndPath); #if UNITY_EDITOR SceneView.RepaintAll(); AssetDatabase.AddObjectToAsset(endIntersection, this); AssetDatabase.AddObjectToAsset(path, this); EditorUtility.SetDirty(this); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); #endif Debug.Log("Created new path and intersection"); }