//Loops: private void Update() { //wait for hand input to come online: if (!HandInput.Ready) { return; } //shoulder: float shoulderDistance = shoulderWidth * .5f; //swap for the left shoulder: if (handedness == MLHandTracking.HandType.Left) { shoulderDistance *= -1; } //source locations: Vector3 flatForward = Vector3.ProjectOnPlane(_mainCamera.forward, Vector3.up); Vector3 shoulder = TransformUtilities.WorldPosition(_mainCamera.position, Quaternion.LookRotation(flatForward), new Vector2(shoulderDistance, Mathf.Abs(shoulderDistanceBelowHead) * -1)); Vector3 pointerOrigin = Vector3.Lerp(Hand.Skeleton.Thumb.Knuckle.positionFiltered, Hand.Skeleton.Position, .5f); //direction: Quaternion orientation = Quaternion.LookRotation(Vector3.Normalize(pointerOrigin - shoulder), Hand.Skeleton.Rotation * Vector3.up); //application: transform.position = pointerOrigin; transform.rotation = orientation; }
private void PreviewArea() { //visualize: Vector3[] playspacePerimeterOnFloor = new Vector3[_playspaceCorners.Count]; Vector3[] playspacePerimeterOnCeiling = new Vector3[_playspaceCorners.Count]; //populate floor and ceiling corner loops: for (int i = 0; i < _playspaceCorners.Count; i++) { //cache floor and ceiling locations: Vector3 floor = TransformUtilities.WorldPosition(pcfAnchor.Position, pcfAnchor.Rotation, _playspaceCorners[i]); Vector3 ceiling = floor + new Vector3(0, Height); playspacePerimeterOnFloor[i] = floor; playspacePerimeterOnCeiling[i] = ceiling; //draw corner supports: LineRenderer cornerSupportsOutline = Lines.DrawLine($"PlayspaceCornerSupport{i}", Color.green, Color.green, .005f, floor, ceiling); cornerSupportsOutline.material = perimeterOutlineMaterial; } //draw ceiling and floor perimeter: LineRenderer ceilingOutline = Lines.DrawLine($"PlayspaceCeilingOutline", Color.green, Color.green, .005f, playspacePerimeterOnCeiling); LineRenderer floorOutline = Lines.DrawLine($"PlayspaceFloorOutline", Color.green, Color.green, .005f, playspacePerimeterOnFloor); ceilingOutline.material = perimeterOutlineMaterial; floorOutline.material = perimeterOutlineMaterial; }
private void FindWalls_GenerateGeometry() { //transform matrix: Vector3 correctedForward = Vector3.ProjectOnPlane(pcfAnchor.Rotation * Vector3.forward, Vector3.up).normalized; Quaternion correctedRotation = Quaternion.LookRotation(correctedForward); Matrix4x4 transformMatrix = Matrix4x4.TRS(pcfAnchor.Position, correctedRotation, Vector3.one); //build wall geometry: Vector3 verticalOffset = Vector3.up * Height; List <Vector3> wallVerticies = new List <Vector3>(); List <int> wallTriangles = new List <int>(); for (int i = 0; i < _playspaceCorners.Count - 1; i++) { Vector3 pointA = TransformUtilities.WorldPosition(pcfAnchor.Position, pcfAnchor.Rotation, _playspaceCorners[i]); Vector3 pointB = TransformUtilities.WorldPosition(pcfAnchor.Position, pcfAnchor.Rotation, _playspaceCorners[i + 1]); //locate verticies (local space): Vector3 a = transformMatrix.inverse.MultiplyPoint3x4(pointA); Vector3 b = transformMatrix.inverse.MultiplyPoint3x4(pointB); Vector3 c = b + verticalOffset; Vector3 d = a + verticalOffset; //store verticies (reverse order so normals face inwards): wallVerticies.Add(d); wallVerticies.Add(c); wallVerticies.Add(b); wallVerticies.Add(a); //store triangles wallTriangles.Add(wallVerticies.Count - 4); wallTriangles.Add(wallVerticies.Count - 3); wallTriangles.Add(wallVerticies.Count - 2); wallTriangles.Add(wallVerticies.Count - 2); wallTriangles.Add(wallVerticies.Count - 1); wallTriangles.Add(wallVerticies.Count - 4); } //get points for polygon construction: Vector2[] polygonPoints = new Vector2[_playspaceCorners.Count - 1]; Vector3[] floorVerticies = new Vector3[_playspaceCorners.Count - 1]; Vector3[] ceilingVerticies = new Vector3[_playspaceCorners.Count - 1]; for (int i = 0; i < _playspaceCorners.Count - 1; i++) { Vector3 point = TransformUtilities.WorldPosition(pcfAnchor.Position, pcfAnchor.Rotation, _playspaceCorners[i]); Vector3 local = transformMatrix.inverse.MultiplyPoint3x4(point); polygonPoints[i] = new Vector2(local.x, local.z); floorVerticies[i] = local; ceilingVerticies[i] = local + verticalOffset; } //triangles: int[] floorTriangles = new Triangulator(polygonPoints).Triangulate(); BuildGeometry(wallVerticies.ToArray(), wallTriangles.ToArray(), floorVerticies, floorTriangles, ceilingVerticies); //FindWalls_Analyze(); ChangeState(State.ConfirmArea); }
private void HandleTransformSync(TransformSyncMessage transformSyncMessage) { //is this a pose message for us? if (transformSyncMessage.ig != guid) { return; } //unpack: Vector3 receivedLocalPosition = new Vector3((float)transformSyncMessage.px, (float)transformSyncMessage.py, (float)transformSyncMessage.pz); Quaternion receivedRotationOffset = new Quaternion((float)transformSyncMessage.rx, (float)transformSyncMessage.ry, (float)transformSyncMessage.rz, (float)transformSyncMessage.rw); _targetPosition = TransformUtilities.WorldPosition(Transmission.Instance.sharedOrigin.position, Transmission.Instance.sharedOrigin.rotation, receivedLocalPosition); _targetRotation = TransformUtilities.ApplyRotationOffset(Transmission.Instance.sharedOrigin.rotation, receivedRotationOffset); targetScale = new Vector3((float)transformSyncMessage.sx, (float)transformSyncMessage.sy, (float)transformSyncMessage.sz); }
private void FindWalls_LocateBoundry() { //remove initial guides: RemovePlottedBounds(); //sort by angles from a base vector to find clockwise order: Vector3 baseVector = Vector3.Normalize(_virtualWalls[0].plane.Center - _plottedBounds.center); SortedDictionary <float, int> sortedDirection = new SortedDictionary <float, int>(); for (int i = 0; i < _virtualWalls.Count; i++) { Vector3 toNext = Vector3.Normalize(_virtualWalls[i].plane.Center - _plottedBounds.center); float angle = Vector3.SignedAngle(baseVector, toNext, Vector3.up) + 180; if (sortedDirection.ContainsKey(angle)) { //we have a bad set of locations so it is best to just everything: Create(); break; } else { sortedDirection.Add(angle, i); } } int[] clockwiseOrder = sortedDirection.Values.ToArray <int>(); //find and connect 'betweens' which end up being final walls of playspace List <bool> physicalStatus = new List <bool>(); _playspaceCorners = new List <Vector3>(); for (int i = 0; i < clockwiseOrder.Length; i++) { //parts: int next = (i + 1) % clockwiseOrder.Length; float angle = Vector3.Angle(_virtualWalls[clockwiseOrder[i]].plane.Rotation * Vector3.right, _virtualWalls[clockwiseOrder[next]].plane.Rotation * Vector3.right); //save physical status: physicalStatus.Add(_virtualWalls[clockwiseOrder[next]].physical); //add solved between: if (angle < 45 || angle > 135) { //wall - use mid point: Vector3 mid = Vector3.Lerp(_virtualWalls[clockwiseOrder[i]].plane.Center, _virtualWalls[clockwiseOrder[next]].plane.Center, .5f); mid.y = _roomFloorHeight; _playspaceCorners.Add(TransformUtilities.LocalPosition(pcfAnchor.Position, pcfAnchor.Rotation, mid)); } else { //corner - use intersection by creating inverted lines from each plane: Vector3 point = Vector2.zero; if (MathUtilities.RayIntersection( new Ray(_virtualWalls[clockwiseOrder[i]].plane.Center, _virtualWalls[clockwiseOrder[i]].plane.Rotation * Vector3.right), new Ray(_virtualWalls[clockwiseOrder[next]].plane.Center, _virtualWalls[clockwiseOrder[next]].plane.Rotation * Vector3.left), ref point)) { point.y = _roomFloorHeight; _playspaceCorners.Add(TransformUtilities.LocalPosition(pcfAnchor.Position, pcfAnchor.Rotation, point)); } } } //close loop: _playspaceCorners.Add(_playspaceCorners[0]); //store walls: List <PlayspaceWall> playspaceWalls = new List <PlayspaceWall>(); for (int i = 0; i < _playspaceCorners.Count - 1; i++) { Vector3 pointA = TransformUtilities.WorldPosition(pcfAnchor.Position, pcfAnchor.Rotation, _playspaceCorners[i]); Vector3 pointB = TransformUtilities.WorldPosition(pcfAnchor.Position, pcfAnchor.Rotation, _playspaceCorners[i + 1]); Vector3 vector = pointB - pointA; Vector3 normal = Quaternion.AngleAxis(90, Vector3.up) * vector.normalized; Vector3 center = Vector3.Lerp(pointA, pointB, .5f); center.y = _roomVerticalCenter; float width = vector.magnitude; PlayspaceWall wall = new PlayspaceWall(center, Quaternion.LookRotation(normal), width, Height, physicalStatus[i]); playspaceWalls.Add(wall); } Walls = playspaceWalls.ToArray(); FindWalls_GenerateGeometry(); }