void OnWillRenderObject() { if (Camera.current == Camera.main) { depth = 0; renderingPortalNode = null; } if (Camera.current != Camera.main && depth == 0) { // some camera not main and not rendered recursively, i.e. editor camera return; } PortalNode child = null; if (renderingPortalNode == null) { child = this.portalNode; } else { child = renderingPortalNode.children.FirstOrDefault(pn => pn.surface == this); } var camera = portal.GetCamera(depth); if (depth < maxDepth && child != null) { camera.transform.SetParent(Camera.current.transform); camera.transform.Reset(); camera.transform.SetParent(portal.front.transform, worldPositionStays: true); camera.transform.SetParent(portal.other.back, worldPositionStays: false); depth += 1; PortalNode parent = renderingPortalNode; renderingPortalNode = child; camera.Render(); DebugManager.cnt++; depth -= 1; renderingPortalNode = parent; camera.GetComponent<PortalCamera>().rendered = true; } else { camera.GetComponent<PortalCamera>().rendered = false; } }
public void AddPortal(int x, int y, int size, int start) { PortalNode node = new PortalNode(x, y, size, start, false); int index = nodes.Count; nodes.Add(node); if (x % 2 == 0) { associatedNodes[x / 2, y].Add(index); node.gridX = x / 2; node.gridY = y; node = new PortalNode(x, y + 1, size, start, true); node.gridX = x / 2; node.gridY = y + 1; index++; nodes.Add(node); associatedNodes[x / 2, y + 1].Add(index); } else { associatedNodes[(x - 1) / 2, y].Add(index); node.gridX = (x - 1) / 2; node.gridY = y; node = new PortalNode(x + 2, y, size, start, true); index++; nodes.Add(node); associatedNodes[(x + 1) / 2, y].Add(index); node.gridX = (x + 1) / 2; node.gridY = y; } Connect(index, index - 1); }
public void Connect(int i, int j) { PortalNode nodeA = nodes[i]; PortalNode nodeB = nodes[j]; nodeA.connectedNodes.Add(j); nodeB.connectedNodes.Add(i); }
public override void getNeighbors(AStarNode node, ref List <AStarNode> neighbors) { PortalNode pNode = (PortalNode)node; foreach (int i in pNode.connectedNodes) { neighbors.Add(nodes[i]); } }
public void BuildPortalViewTree() { if (rootNode == null) { rootNode = PortalNode.QueryNode(null, -1); } //currentLayer = 0; rootNode.Recycle(); BuildPortalViewTree(rootNode, 0); }
public PortalNode[] GetNodesAt(int x, int y) { List <int> nodeIndices = associatedNodes[x, y]; PortalNode[] output = new PortalNode[nodeIndices.Count]; int i = 0; foreach (int nodeIndex in nodeIndices) { output[i++] = nodes[nodeIndex]; } return(output); }
public static PortalNode QueryNode(Portal v, int layer) { Queue <PortalNode> pool; if (layer <= 0) { pool = highResPool; } else if (layer == 1) { pool = middleResPool; } else { pool = lowResPool; } if (pool.Count > 0) { var ret = pool.Dequeue(); ret.thisPortal = v; ret.rotation = Quaternion.identity; ret.position = Vector3.zero; ret.projMat = Matrix4x4.identity; ret.inQueue = false; return(ret); } Debug.Log("New Node Instance!"); layer = Mathf.Clamp(layer, 0, 2); var res = RES_LAYER[layer]; var temp = new PortalNode(v, pool); temp.rt = new RenderTexture((int)res.x, (int)res.y, 24); return(temp); }
public void setStartNodesAndGoal(Node from, Node to, PortalNode goal) { this._startFromNode = from; this._startToNode = to; this._goalPortalNode = goal; }
private void Update() { if (!this._initialized || this._isStoppedForCutscene) { return; } // Get some values baked out: var fromPos = this._fromNode.transform.position; var toPos = this._toNode.transform.position; var railAxis = (toPos - fromPos).normalized; var maxSpeedModifier = 1f; var inSlowOnApproachMode = (!this._hasLockedIntoCurrentSelection && this._toNode != this._goalPortalNode && this._currentlySelectedRail != null && (this.transform.position - toPos).sqrMagnitude <= this._easeIntoNodeDistance_c * this._easeIntoNodeDistance_c); // If I'm locked into my choice, move a little bit faster: if (this._hasLockedIntoCurrentSelection) { maxSpeedModifier = this._maxSpeedBoostMultiplier_c; } // Otherwise, as I'm reaching my destination node, clamp my max speed to slow down: else if (inSlowOnApproachMode) { maxSpeedModifier = Mathf.Clamp01((Vector3.Distance(this.transform.position, toPos) - 0.5f) / this._easeIntoNodeDistance_c); } if (inSlowOnApproachMode) { UIManager.singleton.ShowRailMessage(); } else { UIManager.singleton.HideRailMessage(); } // Apply acceleration: this._currentSpeed = Mathf.Clamp(this._currentSpeed + Time.deltaTime * this._acceleration_c, 0f, maxSpeedModifier * this._maxSpeed_c); // Move along rail: this.transform.position += railAxis * this._currentSpeed * Time.deltaTime; // Rotate: var twistInput = !this._hasLockedIntoCurrentSelection ? -Input.GetAxis("Horizontal") : 0f; if (Mathf.Abs(twistInput) > 0.001f) { this._angularVelocity = Mathf.Clamp(this._angularVelocity + twistInput * this._twistAcceleration_c * Time.deltaTime, -this._twistMaxVelocity_c, this._twistMaxVelocity_c); } else { this._angularVelocity = 0f; } this._twistAngle = (this._twistAngle + twistInput * this._twistAcceleration_c * Time.deltaTime) % 360f; // Update my rotation along the current rail: this.transform.rotation = Quaternion.AngleAxis(this._twistAngle, railAxis) * Quaternion.LookRotation(railAxis); // Calculate which rail is our next rail: Rail newSelectedRail; if (this._toNode == this._goalPortalNode) { // We're approaching a portal node, so there's no selected rail: newSelectedRail = null; } else { // We're approaching a regular node, so figure out which one it is: newSelectedRail = this.calculateWhichRailIsSelected(); } if (this._currentlySelectedRail != newSelectedRail) { this._currentlySelectedRail?.setSelectionState(this._currentlySelectedRail.selectionState != Rail.RailSelectionState.currentlyOn ? Rail.RailSelectionState.notSelected : Rail.RailSelectionState.currentlyOn); newSelectedRail?.setSelectionState(Rail.RailSelectionState.isSelected); this._currentlySelectedRail = newSelectedRail; } // Check for input to lock the player into their current rail: if (Input.GetKeyDown(KeyCode.Space) && this._currentlySelectedRail != null) { if (!this._hasLockedIntoCurrentSelection) { GameObject audioSourceObject = new GameObject("Audio Clip"); audioSourceObject.transform.position = transform.position; AudioSource newSource = audioSourceObject.AddComponent <AudioSource>(); newSource.clip = speedUpClip; newSource.volume = Random.Range(minSpeedUpClipVolume, maxSpeedUpClipVolume); newSource.pitch = Random.Range(.7f, 1.1f); newSource.Play(); Destroy(audioSourceObject, speedUpClip.length); } this._hasLockedIntoCurrentSelection = true; } // Check to see if I've passed the end of my current rail: if (Vector3.Dot(toPos - this.transform.position, toPos - fromPos) < 0f) { // Hit our portal node!! if (this._toNode == this._goalPortalNode) { // Stop and go play the cutscene for our mission finishing: this._isStoppedForCutscene = true; GameplayManager.singleton.finishCurrentMissionPart((newGoal) => { // After the cutscene finishes, un-stop and go in a direction this._isStoppedForCutscene = false; this.changeRail(this._toNode.GetFirstRail().endWhichIsNot(this._toNode)); this._goalPortalNode = newGoal; }); } // Just going to a new rail: else { // If I have a selected rail, go to it: if (this._currentlySelectedRail != null) { // If I have selected it officially: if (this._hasLockedIntoCurrentSelection) { // If so, move to the next rail: this.changeRail(this._currentlySelectedRail.endWhichIsNot(this._toNode)); } } // Otherwise, dead end! Just stop me in my tracks: else { this.transform.position = this._toNode.transform.position; this.changeRail(this._toNode.GetFirstRail().endWhichIsNot(this._toNode)); } } } this.updateWindParticles(); }
private void BuildPortalViewTree(PortalNode p, int lastDepth) { if (lastDepth >= maxLayer) { return; } lastDepth++; Camera currentCam = p.thisPortal == null ? rootCamera : p.thisPortal.portalCamera; if (p.thisPortal != null) { currentCam.transform.position = p.position; currentCam.transform.rotation = p.rotation; currentCam.projectionMatrix = p.projMat; currentCam.targetTexture = p.rt; } ScreenPoatalArea portalRect = p.thisPortal == null ? new ScreenPoatalArea() { scrrenRect = new Rect(0, 0, 1, 1), minDeep = 0, maxDeep = currentCam.nearClipPlane } : p.thisPortal.otherPortal.GetPortalRect(currentCam); foreach (var pair in PortalPair.portalPairs) { if (pair.portalA != null && pair.portalA.ShouldCameraRender(currentCam, portalRect)) { p.nextPairs.Add(PortalNode.QueryNode(pair.portalA, lastDepth - 1)); } if (pair.portalB != null && pair.portalB.ShouldCameraRender(currentCam, portalRect)) { p.nextPairs.Add(PortalNode.QueryNode(pair.portalB, lastDepth - 1)); } } foreach (var node in p.nextPairs) { if (p.thisPortal != null) { currentCam.transform.position = p.position; currentCam.transform.rotation = p.rotation; currentCam.projectionMatrix = p.projMat; currentCam.targetTexture = p.rt; } Transform Source = node.thisPortal.portalPlaneTransform; Transform Destination = node.thisPortal.otherPortal.portalPlaneTransform; Camera portalCamera = node.thisPortal.portalCamera; // Rotate Source 180 degrees so PortalCamera is mirror image of MainCamera Matrix4x4 destinationFlipRotation = Matrix4x4.TRS(ZeroV3, Quaternion.AngleAxis(180.0f, Vector3.up), OneV3); Matrix4x4 sourceInvMat = destinationFlipRotation * Source.worldToLocalMatrix; // Calculate translation and rotation of MainCamera in Source space Vector3 cameraPositionInSourceSpace = ToV3(sourceInvMat * PosToV4(currentCam.transform.position)); Quaternion cameraRotationInSourceSpace = Quaternion.AngleAxis(180, Vector3.up) * Quaternion.Inverse(Source.rotation) * currentCam.transform.rotation; // Transform Portal Camera to World Space relative to Destination transform, // matching the Main Camera position/orientation portalCamera.transform.position = Destination.TransformPoint(cameraPositionInSourceSpace); portalCamera.transform.rotation = Destination.rotation * cameraRotationInSourceSpace; node.position = Destination.TransformPoint(cameraPositionInSourceSpace); node.rotation = Destination.rotation * cameraRotationInSourceSpace; // Calculate clip plane for portal (for culling of objects inbetween destination camera and portal) Vector4 clipPlaneWorldSpace = new Vector4(node.thisPortal.otherPortal.portalForward.x, node.thisPortal.otherPortal.portalForward.y, node.thisPortal.otherPortal.portalForward.z, Vector3.Dot(Destination.position, -node.thisPortal.otherPortal.portalForward)); Vector4 clipPlaneCameraSpace = Matrix4x4.Transpose(Matrix4x4.Inverse(portalCamera.worldToCameraMatrix)) * clipPlaneWorldSpace; // Update projection based on new clip plane // Note: http://aras-p.info/texts/obliqueortho.html and http://www.terathon.com/lengyel/Lengyel-Oblique.pdf //portalCamera.projectionMatrix = rootCamera.CalculateObliqueMatrix(clipPlaneCameraSpace); node.projMat = rootCamera.CalculateObliqueMatrix(clipPlaneCameraSpace); BuildPortalViewTree(node, lastDepth); } }