private void PickChange(Vector2 mousePosition) { GeneralUtility.DisableAndThrowOnUnassignedReference(this, partitioning, "The FaceSpatialPartitioningPicker component requires a reference to a UniversalFaceSpatialPartitioning scriptable object. Either create a saved asset using generators available in the Assets/Create/Topology menu, or create and assign one at runtime before the picker's Start() event runs."); var ray = Geometry.InverseTransformRay(transform, camera.ScreenPointToRay(mousePosition)); var face = partitioning.FindFace(ray); if (face && _currentFace != face) { var previousFace = _currentFace; _currentFace = face; OnPickChange.Invoke(previousFace, face); } }
/// <summary> /// Finds the shortest or path from the specified source vertex to the specified target vertex, /// using the A* algorithm and the supplied vertex positions to measure spherical arc distance /// between vertices and over vertex edges. /// </summary> /// <param name="source">The source vertex from which the path should start.</param> /// <param name="target">The target vertex that the path should attempt to reach.</param> /// <param name="surface">The surface describing the overall shape of the spherical manifold.</param> /// <param name="vertexPositions">The three dimensional positions of each face in the world.</param> /// <param name="path">An optional existing path created by an earlier call to one of the <seealso cref="O:MakeIt.Tile.PathFinder.FindPath"/> functions, which will be overwritten with the new path data.</param> /// <returns>A vertex edge path instance describing the path found from source to target, or an incomplete object if no path was found.</returns> /// <remarks><para>The optional <paramref name="path"/> parameter is useful for reducing allocation activity /// and pressure on the garbage collector. Reusing an existing path object will not require an additional /// allocation to store the path as long as the new path fits inside the capacity already available in the /// existing path.</para></remarks> public IVertexEdgePath FindSphericalEuclideanPath(Topology.Vertex source, Topology.Vertex target, SphericalSurface surface, IVertexAttribute <Vector3> vertexPositions, IVertexEdgePath path = null) { return(FindPath(source, target, (Topology.Vertex s, Topology.Vertex t, int pathLength) => { var sourcePosition = vertexPositions[s]; var targetPosition = vertexPositions[t]; return Geometry.SphericalArcLength(sourcePosition, targetPosition, surface.radius); }, (Topology.VertexEdge edge, int pathLength) => { var sourcePosition = vertexPositions[edge.nearVertex]; var targetPosition = vertexPositions[edge.farVertex]; return Geometry.SphericalArcLength(sourcePosition, targetPosition, surface.radius); }, path)); }
private void PickStart(Vector2 mousePosition, int button) { GeneralUtility.DisableAndThrowOnUnassignedReference(this, partitioning, "The FaceSpatialPartitioningPicker component requires a reference to a UniversalFaceSpatialPartitioning scriptable object. Either create a saved asset using generators available in the Assets/Create/Topology menu, or create and assign one at runtime before the picker's Start() event runs."); var ray = Geometry.InverseTransformRay(transform, camera.ScreenPointToRay(mousePosition)); var startFace = partitioning.FindFace(ray); if (startFace) { _currentFace = startFace; _picking[button] = true; OnPickStart.Invoke(startFace, button); } else { _picking[button] = false; _currentFace = Topology.Face.none; } }
/// <summary> /// Finds the shortest or path from the specified source face to the specified target face, /// using the A* algorithm and the supplied face positions to measure spherical arc distance /// between faces and over face edges. /// </summary> /// <param name="source">The source face from which the path should start.</param> /// <param name="target">The target face that the path should attempt to reach.</param> /// <param name="surface">The surface describing the overall shape of the spherical manifold.</param> /// <param name="facePositions">The three dimensional positions of each face in the world.</param> /// <param name="path">An optional existing path created by an earlier call to one of the <seealso cref="O:MakeIt.Tile.PathFinder.FindPath"/> functions, which will be overwritten with the new path data.</param> /// <returns>A face edge path instance describing the path found from source to target, or an incomplete object if no path was found.</returns> /// <remarks><para>The optional <paramref name="path"/> parameter is useful for reducing allocation activity /// and pressure on the garbage collector. Reusing an existing path object will not require an additional /// allocation to store the path as long as the new path fits inside the capacity already available in the /// existing path.</para></remarks> public IFaceEdgePath FindSphericalEuclideanPath(Topology.Face source, Topology.Face target, SphericalSurface surface, IFaceAttribute <Vector3> facePositions, IFaceEdgePath path = null) { return(FindPath(source, target, (Topology.Face s, Topology.Face t, int pathLength) => { var sourcePosition = facePositions[s]; var targetPosition = facePositions[t]; return Geometry.SphericalArcLength(sourcePosition, targetPosition, surface.radius); }, (Topology.FaceEdge edge, int pathLength) => { if (edge.isOuterBoundary) { return float.PositiveInfinity; } var sourcePosition = facePositions[edge.nearFace]; var targetPosition = facePositions[edge.farFace]; return Geometry.SphericalArcLength(sourcePosition, targetPosition, surface.radius); }, path)); }
protected new void Start() { if (screenCamera == null) { screenCamera = GetComponent <Camera>(); } this.DisableAndThrowOnUnassignedReference(screenCamera, "The CameraWorld component requires a reference to a Camera component."); if (nearPlaneDistance == 0f && farPlaneDistance == 0f) { nearPlaneDistance = screenCamera.nearClipPlane; farPlaneDistance = screenCamera.farClipPlane; } if (wrappingPlaneDistance == 0f) { wrappingPlaneDistance = (nearPlaneDistance + farPlaneDistance) * 0.5f; } var frustumPlanes = GeometryUtility.CalculateFrustumPlanes(screenCamera); var leftPlaneIndex = Geometry.FindMatchingPlane(screenCamera.transform.right, frustumPlanes); var rightPlaneIndex = Geometry.FindMatchingPlane(-screenCamera.transform.right, frustumPlanes); var lowerPlaneIndex = Geometry.FindMatchingPlane(screenCamera.transform.up, frustumPlanes); var upperPlaneIndex = Geometry.FindMatchingPlane(-screenCamera.transform.up, frustumPlanes); var wrappingPlane = new Plane(screenCamera.transform.forward, screenCamera.transform.position + screenCamera.transform.forward * nearPlaneDistance); var origin = Geometry.Intersect(frustumPlanes[leftPlaneIndex], frustumPlanes[lowerPlaneIndex], wrappingPlane); var rightPosition = Geometry.Intersect(frustumPlanes[rightPlaneIndex], frustumPlanes[lowerPlaneIndex], wrappingPlane); var upperPosition = Geometry.Intersect(frustumPlanes[leftPlaneIndex], frustumPlanes[upperPlaneIndex], wrappingPlane); _untransformedOrigin = transform.InverseTransformPoint(origin); _untransformedAxis0Vector = transform.InverseTransformVector(rightPosition - origin); _untransformedAxis1Vector = transform.InverseTransformVector(upperPosition - origin); _untransformedAxis2Vector = transform.InverseTransformVector(screenCamera.transform.forward * (farPlaneDistance - nearPlaneDistance)); base.Start(); }