public void Render() { if (SharedLookAndFeel == null) { return; } if (IsActive && _grabSurfaceInfo.SurfaceType != GrabSurfaceType.Invalid) { Material material = MaterialPool.Get.SimpleColor; if (SharedLookAndFeel.DrawAnchorLines) { var linePoints = new List <Vector3>(_grabTargets.Count * 2); foreach (var grabTarget in _grabTargets) { linePoints.Add(grabTarget.Transform.position); linePoints.Add(_grabSurfaceInfo.AnchorPoint); } material.SetZTestAlways(); material.SetColor(_sharedLookAndFeel.AnchorLineColor); material.SetPass(0); GLRenderer.DrawLines3D(linePoints); } if (SharedLookAndFeel.DrawObjectBoxes) { material.SetZTestLess(); material.SetColor(SharedLookAndFeel.ObjectBoxWireColor); material.SetPass(0); var boundsQConfig = GetObjectBoundsQConfig(); foreach (var grabTarget in _grabTargets) { OBB obb = ObjectBounds.CalcHierarchyWorldOBB(grabTarget.GameObject, boundsQConfig); if (obb.IsValid) { GraphicsEx.DrawWireBox(obb); } } } if (SharedLookAndFeel.DrawObjectPosTicks) { material.SetColor(SharedLookAndFeel.ObjectPosTickColor); material.SetPass(0); foreach (var grabTarget in _grabTargets) { Vector2 screenPos = Camera.current.WorldToScreenPoint(grabTarget.Transform.position); GLRenderer.DrawRect2D(RectEx.FromCenterAndSize(screenPos, Vector2Ex.FromValue(SharedLookAndFeel.ObjectPosTickSize)), Camera.current); } } if (SharedLookAndFeel.DrawAnchorPosTick) { material.SetColor(SharedLookAndFeel.AnchorPosTickColor); material.SetPass(0); Vector2 anchorScreenPos = Camera.current.WorldToScreenPoint(_grabSurfaceInfo.AnchorPoint); GLRenderer.DrawRect2D(RectEx.FromCenterAndSize(anchorScreenPos, Vector2Ex.FromValue(SharedLookAndFeel.AnchorPosTickSize)), Camera.current); } } }
/// <summary> /// Renders a wire box with lines meeting at corners. /// </summary> /// <param name="wireCornerLinePercentage"> /// Can have values in the [0, 1] interval and it controls the length of the /// corner lines. A value of 0 draws lines of length 0 and a value of 1 /// draws lines of length equal to half the box length along a certain axis. /// </param> public static void DrawWireCornerBox(OBB box, float wireCornerLinePercentage) { // Store these for easy access Mesh wireCornerLineMesh = MeshPool.Get.UnitCoordSystem; List <Vector3> boxCorners = box.GetCornerPoints(); // Clamp percentage wireCornerLinePercentage = Mathf.Clamp(wireCornerLinePercentage, 0.0f, 1.0f); // Front bottom left point Vector3 originalScale = box.Extents * wireCornerLinePercentage; Vector3 scale = originalScale; Vector3 position = boxCorners[(int)BoxCorner.FrontBottomLeft]; Matrix4x4 transformMatrix = Matrix4x4.TRS(position, box.Rotation, scale); Graphics.DrawMeshNow(wireCornerLineMesh, transformMatrix); // Front bottom right point position = boxCorners[(int)BoxCorner.FrontBottomRight]; scale.x *= -1.0f; transformMatrix = Matrix4x4.TRS(position, box.Rotation, scale); Graphics.DrawMeshNow(wireCornerLineMesh, transformMatrix); // Front top right point position = boxCorners[(int)BoxCorner.FrontTopRight]; scale.y *= -1.0f; transformMatrix = Matrix4x4.TRS(position, box.Rotation, scale); Graphics.DrawMeshNow(wireCornerLineMesh, transformMatrix); // Front top left point position = boxCorners[(int)BoxCorner.FrontTopLeft]; scale = originalScale; scale.y *= -1.0f; transformMatrix = Matrix4x4.TRS(position, box.Rotation, scale); Graphics.DrawMeshNow(wireCornerLineMesh, transformMatrix); // Back bottom left point position = boxCorners[(int)BoxCorner.BackBottomLeft]; scale.y = originalScale.y; scale.x *= -1.0f; scale.z *= -1.0f; transformMatrix = Matrix4x4.TRS(position, box.Rotation, scale); Graphics.DrawMeshNow(wireCornerLineMesh, transformMatrix); // Back bottom right point position = boxCorners[(int)BoxCorner.BackBottomRight]; scale.x = originalScale.x; transformMatrix = Matrix4x4.TRS(position, box.Rotation, scale); Graphics.DrawMeshNow(wireCornerLineMesh, transformMatrix); // Back top right point position = boxCorners[(int)BoxCorner.BackTopRight]; scale.y *= -1.0f; transformMatrix = Matrix4x4.TRS(position, box.Rotation, scale); Graphics.DrawMeshNow(wireCornerLineMesh, transformMatrix); // Back top left point position = boxCorners[(int)BoxCorner.BackTopLeft]; scale.x *= -1.0f; transformMatrix = Matrix4x4.TRS(position, box.Rotation, scale); Graphics.DrawMeshNow(wireCornerLineMesh, transformMatrix); }
public bool IntersectsOBB(OBB otherOBB) { return(BoxMath.BoxIntersectsBox(_center, _size, _rotation, otherOBB.Center, otherOBB.Size, otherOBB.Rotation)); }
public static List <Vector3> CollectHierarchyVerts(GameObject root, BoxFace collectFace, float collectBoxScale, float collectEps) { List <GameObject> meshObjects = root.GetMeshObjectsInHierarchy(); List <GameObject> spriteObjects = root.GetSpriteObjectsInHierarchy(); if (meshObjects.Count == 0 && spriteObjects.Count == 0) { return(new List <Vector3>()); } ObjectBounds.QueryConfig boundsQConfig = new ObjectBounds.QueryConfig(); boundsQConfig.ObjectTypes = GameObjectType.Mesh | GameObjectType.Sprite; OBB hierarchyOBB = ObjectBounds.CalcHierarchyWorldOBB(root, boundsQConfig); if (!hierarchyOBB.IsValid) { return(new List <Vector3>()); } int faceAxisIndex = BoxMath.GetFaceAxisIndex(collectFace); Vector3 faceCenter = BoxMath.CalcBoxFaceCenter(hierarchyOBB.Center, hierarchyOBB.Size, hierarchyOBB.Rotation, collectFace); Vector3 faceNormal = BoxMath.CalcBoxFaceNormal(hierarchyOBB.Center, hierarchyOBB.Size, hierarchyOBB.Rotation, collectFace); float sizeEps = collectEps * 2.0f; Vector3 collectAABBSize = hierarchyOBB.Size; collectAABBSize[faceAxisIndex] = (hierarchyOBB.Size[faceAxisIndex] * collectBoxScale) + sizeEps; collectAABBSize[(faceAxisIndex + 1) % 3] += sizeEps; collectAABBSize[(faceAxisIndex + 2) % 3] += sizeEps; OBB collectOBB = new OBB(faceCenter + faceNormal * (-collectAABBSize[faceAxisIndex] * 0.5f + collectEps), collectAABBSize); collectOBB.Rotation = hierarchyOBB.Rotation; List <Vector3> collectedVerts = new List <Vector3>(80); foreach (GameObject meshObject in meshObjects) { Mesh mesh = meshObject.GetMesh(); RTMesh rtMesh = RTMeshDb.Get.GetRTMesh(mesh); if (rtMesh == null) { continue; } List <Vector3> verts = rtMesh.OverlapVerts(collectOBB, meshObject.transform); if (verts.Count != 0) { collectedVerts.AddRange(verts); } } foreach (GameObject spriteObject in spriteObjects) { List <Vector3> verts = CollectWorldSpriteVerts(spriteObject.GetSprite(), spriteObject.transform, collectOBB); if (verts.Count != 0) { collectedVerts.AddRange(verts); } } return(collectedVerts); }
public static void DrawWireBox(OBB box) { Graphics.DrawMeshNow(MeshPool.Get.UnitWireBox, box.GetUnitBoxTransform()); }
public static SnapResult CalculateSnapResult(GameObject root, Config snapConfig) { if (snapConfig.IgnoreDestObjects == null) { snapConfig.IgnoreDestObjects = new List <GameObject>(); } List <GameObject> sourceObjects = root.GetAllChildrenAndSelf(); if (sourceObjects.Count > MaxSourceObjects) { return(new SnapResult(SnapFailReson.MaxObjectsExceeded)); } List <GameObject> sourceMeshObjects = root.GetMeshObjectsInHierarchy(); List <GameObject> sourceSpriteObjects = root.GetSpriteObjectsInHierarchy(); if (sourceMeshObjects.Count == 0 && sourceSpriteObjects.Count == 0) { return(new SnapResult(SnapFailReson.InvalidSourceObjects)); } ObjectBounds.QueryConfig boundsQConfig = new ObjectBounds.QueryConfig(); boundsQConfig.ObjectTypes = GameObjectType.Mesh | GameObjectType.Sprite; Vector3 overlapSizeAdd = Vector3.one * snapConfig.SnapRadius * 2.0f; List <BoxFace> allSnapFaces = BoxMath.AllBoxFaces; bool tryMatchAreas = (snapConfig.Prefs & Prefs.TryMatchArea) != 0; bool foundMatchingAreas = false; List <SnapSortData> sortedSnapData = new List <SnapSortData>(10); SnapSortData sortData = new SnapSortData(); foreach (GameObject sourceObject in sourceObjects) { OBB overlapOBB = ObjectBounds.CalcWorldOBB(sourceObject, boundsQConfig); overlapOBB.Size = overlapOBB.Size + overlapSizeAdd; List <GameObject> nearbyObjects = RTScene.Get.OverlapBox(overlapOBB); nearbyObjects.RemoveAll(item => item.transform.IsChildOf(root.transform) || snapConfig.IgnoreDestObjects.Contains(item) || !LayerEx.IsLayerBitSet(snapConfig.DestinationLayers, item.layer)); if (nearbyObjects.Count == 0) { continue; } Object2ObjectSnapData sourceSnapData = Object2ObjectSnapDataDb.Get.GetObject2ObjectSnapData(sourceObject); if (sourceSnapData == null) { continue; } sortData.SrcObject = sourceObject; foreach (BoxFace srcSnapFace in allSnapFaces) { BoxFaceAreaDesc srcAreaDesc = sourceSnapData.GetWorldSnapAreaDesc(srcSnapFace); OBB srcAreaBounds = sourceSnapData.GetWorldSnapAreaBounds(srcSnapFace); List <Vector3> srcAreaPts = srcAreaBounds.GetCenterAndCornerPoints(); sortData.SrcSnapFace = srcSnapFace; foreach (GameObject destObject in nearbyObjects) { Object2ObjectSnapData destSnapData = Object2ObjectSnapDataDb.Get.GetObject2ObjectSnapData(destObject); if (destSnapData == null) { continue; } sortData.DestObject = destObject; foreach (BoxFace destSnapFace in allSnapFaces) { sortData.DestSnapFace = destSnapFace; BoxFaceAreaDesc destAreaDesc = destSnapData.GetWorldSnapAreaDesc(destSnapFace); sortData.FaceAreasMatch = false; if (tryMatchAreas && destAreaDesc.AreaType == srcAreaDesc.AreaType) { sortData.FaceAreaDiff = Mathf.Abs(destAreaDesc.Area - srcAreaDesc.Area); if (sortData.FaceAreaDiff <= 1000.0f) { sortData.FaceAreasMatch = true; } } OBB destAreaBounds = destSnapData.GetWorldSnapAreaBounds(destSnapFace); List <Vector3> destAreaPts = destAreaBounds.GetCenterAndCornerPoints(); foreach (Vector3 srcPt in srcAreaPts) { sortData.SnapPivot = srcPt; foreach (Vector3 destPt in destAreaPts) { sortData.SnapDistance = (destPt - srcPt).magnitude; if (sortData.SnapDistance < snapConfig.SnapRadius) { sortData.SnapDest = destPt; sortedSnapData.Add(sortData); if (sortData.FaceAreasMatch) { foundMatchingAreas = true; } } } } } } } } if (sortedSnapData.Count != 0) { if (!tryMatchAreas || !foundMatchingAreas) { sortedSnapData.Sort(delegate(SnapSortData s0, SnapSortData s1) { return(s0.SnapDistance.CompareTo(s1.SnapDistance)); }); } else { while (true) { if (!sortedSnapData[0].FaceAreasMatch) { sortedSnapData.RemoveAt(0); } else { break; } } sortedSnapData.Sort(delegate(SnapSortData s0, SnapSortData s1) { return(s0.FaceAreaDiff.CompareTo(s1.FaceAreaDiff)); }); } return(new SnapResult(sortedSnapData[0].SnapPivot, sortedSnapData[0].SnapDest, sortedSnapData[0].SnapDistance)); } return(new SnapResult(SnapFailReson.NoDestinationFound)); }
public static List <Vector3> CollectWorldSpriteVerts(Sprite sprite, Transform spriteTransform, OBB collectOBB) { List <Vector3> spriteWorldVerts = sprite.GetWorldVerts(spriteTransform); List <Vector3> collectedVerts = new List <Vector3>(7); foreach (Vector3 vertPos in spriteWorldVerts) { if (BoxMath.ContainsPoint(vertPos, collectOBB.Center, collectOBB.Size, collectOBB.Rotation)) { collectedVerts.Add(vertPos); } } return(collectedVerts); }
protected bool GetWorldPointClosestToInputDevice(Camera focusCamera, IEnumerable <GameObject> gameObjects, out Vector3 point) { point = Vector3.zero; if (gameObjects == null) { return(false); } if (!RTInputDevice.Get.Device.HasPointer()) { return(false); } Vector2 inputDeviceScreenPt = RTInputDevice.Get.Device.GetPositionYAxisUp(); float minDistSqr = float.MaxValue; bool foundPoint = false; foreach (var srcObject in gameObjects) { Mesh mesh = srcObject.GetMesh(); if (mesh != null) { MeshVertexChunkCollection meshVChunkCollection = MeshVertexChunkCollectionDb.Get[mesh]; if (meshVChunkCollection == null) { continue; } Matrix4x4 worldMtx = srcObject.transform.localToWorldMatrix; List <MeshVertexChunk> testChunks = meshVChunkCollection.GetWorldChunksHoveredByPoint(inputDeviceScreenPt, worldMtx, focusCamera); if (testChunks.Count == 0) { MeshVertexChunk closestChunk = meshVChunkCollection.GetWorldVertChunkClosestToScreenPt(inputDeviceScreenPt, worldMtx, focusCamera); if (closestChunk != null && closestChunk.VertexCount != 0) { testChunks.Add(closestChunk); } } foreach (var chunk in testChunks) { Vector3 worldVert = chunk.GetWorldVertClosestToScreenPt(inputDeviceScreenPt, worldMtx, focusCamera); Vector2 screenVert = focusCamera.WorldToScreenPoint(worldVert); float distSqr = (inputDeviceScreenPt - screenVert).sqrMagnitude; if (distSqr < minDistSqr) { minDistSqr = distSqr; point = worldVert; foundPoint = true; } } } else { OBB spriteWorldOBB = ObjectBounds.CalcSpriteWorldOBB(srcObject); if (spriteWorldOBB.IsValid) { List <Vector3> obbPoints = spriteWorldOBB.GetCenterAndCornerPoints(); List <Vector2> screenPoints = focusCamera.ConvertWorldToScreenPoints(obbPoints); int closestPtIndex = Vector2Ex.GetPointClosestToPoint(screenPoints, inputDeviceScreenPt); if (closestPtIndex >= 0) { Vector2 closestPt = screenPoints[closestPtIndex]; float distSqr = (inputDeviceScreenPt - closestPt).sqrMagnitude; if (distSqr < minDistSqr) { minDistSqr = distSqr; point = obbPoints[closestPtIndex]; foundPoint = true; } } } } } return(foundPoint); }
public static SnapResult SnapHierarchy(GameObject root, SnapConfig snapConfig) { const float collectEps = 1e-2f; const float collectBoxScale = 1e-3f; bool hierarchyHasMeshes = root.HierarchyHasMesh(); bool hierarchyHasSprites = root.HierarchyHasSprite(); if (!hierarchyHasMeshes && !hierarchyHasSprites) { Transform rootTransform = root.transform; rootTransform.position = snapConfig.SurfaceHitPlane.ProjectPoint(rootTransform.position) + snapConfig.OffsetFromSurface * snapConfig.SurfaceHitNormal; return(new SnapResult(snapConfig.SurfaceHitPlane, rootTransform.position)); } ObjectBounds.QueryConfig boundsQConfig = new ObjectBounds.QueryConfig(); boundsQConfig.ObjectTypes = GameObjectType.Sprite | GameObjectType.Mesh; bool isSurfaceSpherical = snapConfig.SurfaceType == Type.SphericalMesh; bool isSurfaceTerrain = snapConfig.SurfaceType == Type.UnityTerrain || snapConfig.SurfaceType == Type.TerrainMesh; bool isSurfaceUnityTerrain = snapConfig.SurfaceType == Type.UnityTerrain; SurfaceRaycaster raycaster = CreateSurfaceRaycaster(snapConfig.SurfaceType, snapConfig.SurfaceObject, true); if (snapConfig.SurfaceType != Type.SceneGrid) { Transform rootTransform = root.transform; if (snapConfig.AlignAxis) { if (isSurfaceTerrain) { rootTransform.Align(Vector3.up, snapConfig.AlignmentAxis); OBB hierarchyOBB = ObjectBounds.CalcHierarchyWorldOBB(root, boundsQConfig); if (!hierarchyOBB.IsValid) { return(new SnapResult()); } BoxFace pivotFace = BoxMath.GetMostAlignedFace(hierarchyOBB.Center, hierarchyOBB.Size, hierarchyOBB.Rotation, -Vector3.up); List <Vector3> collectedVerts = ObjectVertexCollect.CollectHierarchyVerts(root, pivotFace, collectBoxScale, collectEps); if (collectedVerts.Count != 0) { Vector3 vertsCenter = Vector3Ex.GetPointCloudCenter(collectedVerts); Ray ray = new Ray(vertsCenter + Vector3.up * 1e-3f, -Vector3.up); GameObjectRayHit surfaceHit = raycaster.Raycast(ray); if (surfaceHit != null) { Vector3 alignmentAxis = surfaceHit.HitNormal; if (isSurfaceUnityTerrain) { Terrain terrain = snapConfig.SurfaceObject.GetComponent <Terrain>(); alignmentAxis = terrain.GetInterpolatedNormal(surfaceHit.HitPoint); } Quaternion appliedRotation = rootTransform.Align(alignmentAxis, snapConfig.AlignmentAxis); hierarchyOBB = ObjectBounds.CalcHierarchyWorldOBB(root, boundsQConfig); appliedRotation.RotatePoints(collectedVerts, rootTransform.position); Vector3 sitOnPlaneOffset = ObjectSurfaceSnap.CalculateSitOnSurfaceOffset(hierarchyOBB, new Plane(Vector3.up, surfaceHit.HitPoint), 0.1f); rootTransform.position += sitOnPlaneOffset; hierarchyOBB.Center += sitOnPlaneOffset; Vector3Ex.OffsetPoints(collectedVerts, sitOnPlaneOffset); Vector3 embedVector = ObjectSurfaceSnap.CalculateEmbedVector(collectedVerts, snapConfig.SurfaceObject, -Vector3.up, snapConfig.SurfaceType); rootTransform.position += (embedVector + alignmentAxis * snapConfig.OffsetFromSurface); return(new SnapResult(new Plane(alignmentAxis, surfaceHit.HitPoint), surfaceHit.HitPoint)); } } } else { if (!isSurfaceSpherical) { rootTransform.Align(snapConfig.SurfaceHitNormal, snapConfig.AlignmentAxis); OBB hierarchyOBB = ObjectBounds.CalcHierarchyWorldOBB(root, boundsQConfig); if (!hierarchyOBB.IsValid) { return(new SnapResult()); } BoxFace pivotFace = BoxMath.GetMostAlignedFace(hierarchyOBB.Center, hierarchyOBB.Size, hierarchyOBB.Rotation, -snapConfig.SurfaceHitNormal); List <Vector3> collectedVerts = ObjectVertexCollect.CollectHierarchyVerts(root, pivotFace, collectBoxScale, collectEps); if (collectedVerts.Count != 0) { Vector3 vertsCenter = Vector3Ex.GetPointCloudCenter(collectedVerts); // Note: Cast the ray from far away enough so that we don't cast from the interior of the mesh. // This can happen when the object is embedded inside the mesh surface. AABB surfaceAABB = ObjectBounds.CalcMeshWorldAABB(snapConfig.SurfaceObject); float sphereRadius = surfaceAABB.Extents.magnitude; Vector3 rayOrigin = vertsCenter + snapConfig.SurfaceHitNormal * sphereRadius; Ray ray = new Ray(rayOrigin, -snapConfig.SurfaceHitNormal); GameObjectRayHit surfaceHit = raycaster.Raycast(ray); if (surfaceHit != null) { Vector3 alignmentAxis = surfaceHit.HitNormal; rootTransform.Align(alignmentAxis, snapConfig.AlignmentAxis); hierarchyOBB = ObjectBounds.CalcHierarchyWorldOBB(root, boundsQConfig); Vector3 sitOnPlaneOffset = ObjectSurfaceSnap.CalculateSitOnSurfaceOffset(hierarchyOBB, surfaceHit.HitPlane, 0.0f); rootTransform.position += sitOnPlaneOffset; rootTransform.position += alignmentAxis * snapConfig.OffsetFromSurface; return(new SnapResult(new Plane(alignmentAxis, surfaceHit.HitPoint), surfaceHit.HitPoint)); } else { Vector3 alignmentAxis = snapConfig.SurfaceHitNormal; rootTransform.Align(alignmentAxis, snapConfig.AlignmentAxis); hierarchyOBB = ObjectBounds.CalcHierarchyWorldOBB(root, boundsQConfig); Vector3 sitOnPlaneOffset = ObjectSurfaceSnap.CalculateSitOnSurfaceOffset(hierarchyOBB, snapConfig.SurfaceHitPlane, 0.0f); rootTransform.position += sitOnPlaneOffset; rootTransform.position += alignmentAxis * snapConfig.OffsetFromSurface; return(new SnapResult(snapConfig.SurfaceHitPlane, snapConfig.SurfaceHitPlane.ProjectPoint(vertsCenter))); } } } else { Transform surfaceObjectTransform = snapConfig.SurfaceObject.transform; Vector3 sphereCenter = surfaceObjectTransform.position; Vector3 radiusDir = (rootTransform.position - sphereCenter).normalized; float sphereRadius = surfaceObjectTransform.lossyScale.GetMaxAbsComp() * 0.5f; rootTransform.Align(radiusDir, snapConfig.AlignmentAxis); OBB hierarchyOBB = ObjectBounds.CalcHierarchyWorldOBB(root, boundsQConfig); if (!hierarchyOBB.IsValid) { return(new SnapResult()); } BoxFace pivotFace = BoxMath.GetMostAlignedFace(hierarchyOBB.Center, hierarchyOBB.Size, hierarchyOBB.Rotation, -radiusDir); List <Vector3> collectedVerts = ObjectVertexCollect.CollectHierarchyVerts(root, pivotFace, collectBoxScale, collectEps); Vector3 sitPoint = sphereCenter + radiusDir * sphereRadius; Plane sitPlane = new Plane(radiusDir, sitPoint); Vector3 sitOnPlaneOffset = ObjectSurfaceSnap.CalculateSitOnSurfaceOffset(hierarchyOBB, sitPlane, 0.0f); rootTransform.position += sitOnPlaneOffset; hierarchyOBB.Center += sitOnPlaneOffset; Vector3Ex.OffsetPoints(collectedVerts, sitOnPlaneOffset); rootTransform.position += radiusDir * snapConfig.OffsetFromSurface; return(new SnapResult(sitPlane, sitPoint)); } } } else { OBB hierarchyOBB = ObjectBounds.CalcHierarchyWorldOBB(root, boundsQConfig); if (!hierarchyOBB.IsValid) { return(new SnapResult()); } if (isSurfaceTerrain || (!isSurfaceSpherical && snapConfig.SurfaceType == Type.Mesh)) { Ray ray = new Ray(hierarchyOBB.Center, isSurfaceTerrain ? -Vector3.up : -snapConfig.SurfaceHitNormal); GameObjectRayHit surfaceHit = raycaster.Raycast(ray); if (surfaceHit != null) { Vector3 sitOnPlaneOffset = ObjectSurfaceSnap.CalculateSitOnSurfaceOffset(hierarchyOBB, surfaceHit.HitPlane, 0.0f); rootTransform.position += sitOnPlaneOffset; if (isSurfaceTerrain) { hierarchyOBB.Center += sitOnPlaneOffset; BoxFace pivotFace = BoxMath.GetMostAlignedFace(hierarchyOBB.Center, hierarchyOBB.Size, hierarchyOBB.Rotation, -surfaceHit.HitNormal); List <Vector3> collectedVerts = ObjectVertexCollect.CollectHierarchyVerts(root, pivotFace, collectBoxScale, collectEps); Vector3 embedVector = ObjectSurfaceSnap.CalculateEmbedVector(collectedVerts, snapConfig.SurfaceObject, -Vector3.up, snapConfig.SurfaceType); rootTransform.position += embedVector; } rootTransform.position += surfaceHit.HitNormal * snapConfig.OffsetFromSurface; return(new SnapResult(surfaceHit.HitPlane, surfaceHit.HitPoint)); } else if (!isSurfaceSpherical && snapConfig.SurfaceType == Type.Mesh) { Vector3 sitOnPlaneOffset = ObjectSurfaceSnap.CalculateSitOnSurfaceOffset(hierarchyOBB, snapConfig.SurfaceHitPlane, 0.0f); rootTransform.position += sitOnPlaneOffset; rootTransform.position += snapConfig.SurfaceHitNormal * snapConfig.OffsetFromSurface; return(new SnapResult(snapConfig.SurfaceHitPlane, snapConfig.SurfaceHitPlane.ProjectPoint(hierarchyOBB.Center))); } } else if (isSurfaceSpherical) { Transform surfaceObjectTransform = snapConfig.SurfaceObject.transform; Vector3 sphereCenter = surfaceObjectTransform.position; Vector3 radiusDir = (rootTransform.position - sphereCenter).normalized; float sphereRadius = surfaceObjectTransform.lossyScale.GetMaxAbsComp() * 0.5f; BoxFace pivotFace = BoxMath.GetMostAlignedFace(hierarchyOBB.Center, hierarchyOBB.Size, hierarchyOBB.Rotation, -radiusDir); List <Vector3> collectedVerts = ObjectVertexCollect.CollectHierarchyVerts(root, pivotFace, collectBoxScale, collectEps); Vector3 sitPoint = sphereCenter + radiusDir * sphereRadius; Plane sitPlane = new Plane(radiusDir, sitPoint); Vector3 sitOnPlaneOffset = ObjectSurfaceSnap.CalculateSitOnSurfaceOffset(hierarchyOBB, sitPlane, 0.0f); rootTransform.position += sitOnPlaneOffset; hierarchyOBB.Center += sitOnPlaneOffset; Vector3Ex.OffsetPoints(collectedVerts, sitOnPlaneOffset); rootTransform.position += radiusDir * snapConfig.OffsetFromSurface; return(new SnapResult(sitPlane, sitPoint)); } } } if (snapConfig.SurfaceType == Type.SceneGrid) { OBB hierarchyOBB = ObjectBounds.CalcHierarchyWorldOBB(root, boundsQConfig); if (!hierarchyOBB.IsValid) { return(new SnapResult()); } Transform rootTransform = root.transform; if (snapConfig.AlignAxis) { rootTransform.Align(snapConfig.SurfaceHitNormal, snapConfig.AlignmentAxis); hierarchyOBB = ObjectBounds.CalcHierarchyWorldOBB(root, boundsQConfig); } rootTransform.position += ObjectSurfaceSnap.CalculateSitOnSurfaceOffset(hierarchyOBB, snapConfig.SurfaceHitPlane, snapConfig.OffsetFromSurface); return(new SnapResult(snapConfig.SurfaceHitPlane, snapConfig.SurfaceHitPlane.ProjectPoint(hierarchyOBB.Center))); } return(new SnapResult()); }
public List <GameObjectRayHit> RaycastAll(Ray ray, SceneRaycastPrecision raycastPresicion) { List <SphereTreeNodeRayHit <GameObject> > nodeHits = _objectTree.RaycastAll(ray); if (nodeHits.Count == 0) { return(new List <GameObjectRayHit>()); } ObjectBounds.QueryConfig boundsQConfig = new ObjectBounds.QueryConfig(); boundsQConfig.ObjectTypes = GameObjectTypeHelper.AllCombined; boundsQConfig.NoVolumeSize = Vector3Ex.FromValue(RTScene.Get.Settings.NonMeshObjectSize); Vector3 camLook = RTFocusCamera.Get.Look; if (raycastPresicion == SceneRaycastPrecision.BestFit) { List <GameObjectRayHit> hitList = new List <GameObjectRayHit>(10); foreach (SphereTreeNodeRayHit <GameObject> nodeHit in nodeHits) { GameObject sceneObject = nodeHit.HitNode.Data; if (sceneObject == null || !sceneObject.activeInHierarchy) { continue; } Renderer renderer = sceneObject.GetComponent <Renderer>(); if (renderer != null && !renderer.isVisible) { continue; } GameObjectType objectType = sceneObject.GetGameObjectType(); if (objectType == GameObjectType.Mesh) { GameObjectRayHit objectHit = RaycastMeshObject(ray, sceneObject); if (objectHit != null) { hitList.Add(objectHit); } } else if (objectType == GameObjectType.Terrain) { TerrainCollider terrainCollider = sceneObject.GetComponent <TerrainCollider>(); if (terrainCollider != null) { RaycastHit hitInfo; if (terrainCollider.Raycast(ray, out hitInfo, float.MaxValue)) { hitList.Add(new GameObjectRayHit(ray, hitInfo)); } } } else if (objectType == GameObjectType.Sprite) { GameObjectRayHit objectHit = RaycastSpriteObject(ray, sceneObject); if (objectHit != null) { hitList.Add(objectHit); } } else { OBB worldOBB = ObjectBounds.CalcWorldOBB(sceneObject, boundsQConfig); if (worldOBB.IsValid) { float t; if (BoxMath.Raycast(ray, out t, worldOBB.Center, worldOBB.Size, worldOBB.Rotation)) { BoxFaceDesc faceDesc = BoxMath.GetFaceClosestToPoint(ray.GetPoint(t), worldOBB.Center, worldOBB.Size, worldOBB.Rotation, camLook); GameObjectRayHit hit = new GameObjectRayHit(ray, sceneObject, faceDesc.Plane.normal, t); hitList.Add(hit); } } } } return(hitList); } else if (raycastPresicion == SceneRaycastPrecision.Box) { List <GameObjectRayHit> hitList = new List <GameObjectRayHit>(10); foreach (SphereTreeNodeRayHit <GameObject> nodeHit in nodeHits) { GameObject sceneObject = nodeHit.HitNode.Data; if (sceneObject == null || !sceneObject.activeInHierarchy) { continue; } Renderer renderer = sceneObject.GetComponent <Renderer>(); if (renderer != null && !renderer.isVisible) { continue; } OBB worldOBB = ObjectBounds.CalcWorldOBB(sceneObject, boundsQConfig); if (worldOBB.IsValid) { float t; if (BoxMath.Raycast(ray, out t, worldOBB.Center, worldOBB.Size, worldOBB.Rotation)) { BoxFaceDesc faceDesc = BoxMath.GetFaceClosestToPoint(ray.GetPoint(t), worldOBB.Center, worldOBB.Size, worldOBB.Rotation, camLook); GameObjectRayHit hit = new GameObjectRayHit(ray, sceneObject, faceDesc.Plane.normal, t); hitList.Add(hit); } } } return(hitList); } return(new List <GameObjectRayHit>()); }
public void FromOBB(OBB obb) { Center = obb.Center; Size = obb.Size; Rotation = obb.Rotation; }
public void Render() { if (_sharedLookAndFeel == null) { return; } if (IsActive) { Material material = MaterialPool.Get.SimpleColor; if (_sharedLookAndFeel.DrawBoxes) { material.SetColor(_sharedLookAndFeel.BoxLineColor); material.SetZTestEnabled(true); material.SetPass(0); ObjectBounds.QueryConfig boundsQConfig = GetObjectBoundsQConfig(); foreach (GameObject targetObject in _targetObjects) { if (targetObject == null) { continue; } OBB worldOBB = ObjectBounds.CalcWorldOBB(targetObject, boundsQConfig); if (worldOBB.IsValid) { GraphicsEx.DrawWireBox(worldOBB); } } } Camera camera = Camera.current; Vector2 screenSnapPivot = camera.WorldToScreenPoint(_snapPivotPoint); if (_sharedLookAndFeel.PivotShapeType == PivotPointShapeType.Circle) { material.SetZTestEnabled(false); material.SetColor(_sharedLookAndFeel.PivotPointFillColor); material.SetPass(0); const int numCirclePoints = 100; List <Vector2> pivotCirclePoints = PrimitiveFactory.Generate2DCircleBorderPointsCW(screenSnapPivot, _sharedLookAndFeel.PivotCircleRadius, numCirclePoints); GLRenderer.DrawTriangleFan2D(screenSnapPivot, pivotCirclePoints, camera); if (_sharedLookAndFeel.DrawPivotBorder) { material.SetColor(_sharedLookAndFeel.PivotPointBorderColor); material.SetPass(0); GLRenderer.DrawLineLoop2D(pivotCirclePoints, camera); } } else if (_sharedLookAndFeel.PivotShapeType == PivotPointShapeType.Square) { material.SetZTestEnabled(false); material.SetColor(_sharedLookAndFeel.PivotPointFillColor); material.SetPass(0); Rect pivotRect = RectEx.FromCenterAndSize(screenSnapPivot, Vector2Ex.FromValue(_sharedLookAndFeel.PivotSquareSideLength)); GLRenderer.DrawRect2D(pivotRect, camera); if (_sharedLookAndFeel.DrawPivotBorder) { material.SetColor(_sharedLookAndFeel.PivotPointBorderColor); material.SetPass(0); GLRenderer.DrawRectBorder2D(pivotRect, camera); } } } }