/* * 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); }
/* * Executes the redirection according to the chosen curve and path by * calculating a position and orientation for the virtual camera. * */ private void doRedirection() { // Set offset transforms (virtual position/orientation is set to zero) orientationOffset.localRotation = Quaternion.Inverse(UnityEngine.VR.InputTracking.GetLocalRotation(UnityEngine.VR.VRNode.Head)); positionOffset.localPosition = -UnityEngine.VR.InputTracking.GetLocalPosition(UnityEngine.VR.VRNode.Head); // Get current position and rotation (data from tracking system) Vector2 realWorldCurrentPosition = switchDimensions(Camera.main.transform.localPosition); Quaternion realWorldCurrentRotation = Camera.main.transform.localRotation; //Debug.Log("Current: " + realWorldCurrentPosition); int pathIndex = data.getPathIndex(currentJoint, currentCurve); // Calculate distance between real world current position and real world circle center point float distance = Vector2.Distance(realWorldCurrentPosition, switchDimensions(currentCurve.getCircleCenter())); //Debug.Log("Distance: " + distance); // Calculate angle between start and current position //float angleWalkedOnRealCircle = Vector2.Angle(switchDimensions(switchDimensions(currentJoint.getPosition() + redirectionDirection*data.calculateOffset(currentJoint.getPosition(), currentCurve.getCircleCenter()) - currentCurve.getCircleCenter())), realWorldCurrentPosition - switchDimensions(currentCurve.getCircleCenter())); Vector3 realWalkingStartPosition = currentJoint.getWalkingStartPosition(pathIndex); angleWalkedOnRealCircle = Mathf.Acos((Vector2.Dot((switchDimensions(currentCurve.getCircleCenter()) - switchDimensions(realWalkingStartPosition)), (switchDimensions(currentCurve.getCircleCenter()) - realWorldCurrentPosition))) / ((switchDimensions(currentCurve.getCircleCenter()) - switchDimensions(realWalkingStartPosition)).magnitude * (switchDimensions(currentCurve.getCircleCenter()) - realWorldCurrentPosition).magnitude)); //Debug.Log("angleWalkedOnRealCircle: " + angleWalkedOnRealCircle); // Multiply angle and radius = walked distance float walkedDistance = angleWalkedOnRealCircle * currentCurve.getRadius(); //Debug.Log("Walked: " + walkedDistance); // Calculate side drift: d-r float sideDrift = distance - currentCurve.getRadius(); //Debug.Log("Side: " + sideDrift); // Calculate angle on virtual circle angleWalkedOnVirtualCircle = walkedDistance / currentPath.getRadius(); //Debug.Log("angleWalkedOnVirtualCircle: " + angleWalkedOnVirtualCircle); // Calculate direction from virtual circle center to intersection // - redirectionDirection*data.calculateOffset(currentIntersection.getPosition(), currentPath.getCircleCenter()) Vector3 virtualWalkingStartPosition = currentIntersection.getWalkingStartPosition(pathIndex); Vector2 directionToIntersection = switchDimensions(virtualWalkingStartPosition - currentPath.getCircleCenter()).normalized; //Debug.Log("directionToIntersection: " + directionToIntersection); // Calculate direction to virtual position by rotating direction by angle walked Vector3 directionToVirtualPosition = Quaternion.AngleAxis(redirectionDirection * angleWalkedOnVirtualCircle * Mathf.Rad2Deg, Vector3.up) * new Vector3(directionToIntersection.x, 0, directionToIntersection.y); // Multiply direction by radius + side drift directionToVirtualPosition = directionToVirtualPosition * (currentPath.getRadius() + sideDrift); //Debug.Log("virtualPosition: " + virtualPosition); // Calculate and set virtual position this.transform.position = new Vector3(currentPath.getCircleCenter().x + directionToVirtualPosition.x, Camera.main.transform.localPosition.y, currentPath.getCircleCenter().z + directionToVirtualPosition.z); //Debug.Log(this.transform.position); // Calculate and set virtual rotation: redirection + current camera rotation + old rotation float redirection = Mathf.Rad2Deg * -redirectionDirection * (angleWalkedOnRealCircle - angleWalkedOnVirtualCircle); float y = redirection + realWorldCurrentRotation.eulerAngles.y + oldRotation; Quaternion virtualRotation = Quaternion.Euler(realWorldCurrentRotation.eulerAngles.x, y, realWorldCurrentRotation.eulerAngles.z); this.transform.rotation = virtualRotation; }
/* * 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"); }