public override void OnMouseDown(Mouse3DEventArgs mouseEvent3D) { var selectedItem = RootSelection; ActiveSelectedItem = selectedItem; if (mouseEvent3D.MouseEvent2D.Button == MouseButtons.Left && mouseEvent3D.info != null && selectedItem != null) { hadClickOnControl = true; diameterValueDisplayInfo.Visible = true; var(edge, otherSide) = GetHitPosition(selectedItem); var upNormal = (edge - otherSide).GetNormal(); var sideNormal = upNormal.Cross(mouseEvent3D.MouseRay.directionNormal).GetNormal(); var planeNormal = upNormal.Cross(sideNormal).GetNormal(); hitPlane = new PlaneShape(new Plane(planeNormal, mouseEvent3D.info.HitPosition), null); initialHitPosition = mouseEvent3D.info.HitPosition; scaleController = new ScaleController(Object3DControlContext, null, null, null, null, getHeight, setHeight, getDiameters, setDiameters); Object3DControlContext.Scene.ShowSelectionShadow = false; } base.OnMouseDown(mouseEvent3D); }
public IEnumerator UpdateUVsCorrectly() { float[] uvs = new float[] { 0, 0.75f, 0.25f, 0.75f, 0.25f, 1, 0, 1, 0, 0.75f, 0.25f, 0.75f, 0.25f, 1, 0, 1 }; DecentralandEntity entity; PlaneShape plane = TestHelpers.InstantiateEntityWithShape <PlaneShape, PlaneShape.Model>( scene, DCL.Models.CLASS_ID.PLANE_SHAPE, Vector3.zero, out entity, new PlaneShape.Model() { height = 1, width = 1, uvs = uvs }); yield return(plane.routine); Assert.IsTrue(entity != null); Assert.IsTrue(plane != null); Assert.IsTrue(plane.currentMesh != null); CollectionAssert.AreEqual(Utils.FloatArrayToV2List(uvs), plane.currentMesh.uv); }
public override void OnMouseDown(Mouse3DEventArgs mouseEvent3D) { var selectedItem = RootSelection; ActiveSelectedItem = selectedItem; if (mouseEvent3D.MouseEvent2D.Button == MouseButtons.Left && mouseEvent3D.info != null && selectedItem != null) { hadClickOnControl = true; xValueDisplayInfo.Visible = true; yValueDisplayInfo.Visible = true; hitPlane = new PlaneShape(Vector3.UnitZ, mouseEvent3D.info.HitPosition.Z, null); originalPointToMove = GetEdgePosition(selectedItem, edgeIndex); initialHitPosition = mouseEvent3D.info.HitPosition; transformOnMouseDown = transformAppliedByThis = selectedItem.Matrix; mouseDownSelectedBounds = selectedItem.GetAxisAlignedBoundingBox(); } base.OnMouseDown(mouseEvent3D); }
public override void OnMouseDown(Mouse3DEventArgs mouseEvent3D) { if (mouseEvent3D.info != null && mouseEvent3D.MouseEvent2D.Button == MouseButtons.Left && Object3DControlContext.Scene.SelectedItem != null) { hadClickOnControl = true; activeSelectedItem = RootSelection; heightValueDisplayInfo.Visible = true; var selectedItem = activeSelectedItem; var bottomPosition = GetBottomPosition(selectedItem); var topPosition = GetTopPosition(selectedItem); originalPointToMove = topPosition; var upNormal = (topPosition - bottomPosition).GetNormal(); var sideNormal = upNormal.Cross(mouseEvent3D.MouseRay.directionNormal).GetNormal(); var planeNormal = upNormal.Cross(sideNormal).GetNormal(); hitPlane = new PlaneShape(new Plane(planeNormal, mouseEvent3D.info.HitPosition), null); initialHitPosition = mouseEvent3D.info.HitPosition; scaleController = new ScaleController(Object3DControlContext, getWidth, setWidth, getDepth, setDepth, getHeight, setHeight, getDiameters, setDiameters); Object3DControlContext.Scene.ShowSelectionShadow = false; } base.OnMouseDown(mouseEvent3D); }
public override void OnMouseDown(Mouse3DEventArgs mouseEvent3D) { if (mouseEvent3D.info != null && Object3DControlContext.Scene.SelectedItem != null) { hadClickOnControl = true; activeSelectedItem = RootSelection; zValueDisplayInfo.Visible = true; var selectedItem = activeSelectedItem; double distanceToHit = Vector3Ex.Dot(mouseEvent3D.info.HitPosition, mouseEvent3D.MouseRay.directionNormal); hitPlane = new PlaneShape(mouseEvent3D.MouseRay.directionNormal, distanceToHit, null); originalPointToMove = GetTopPosition(selectedItem); initialHitPosition = mouseEvent3D.info.HitPosition; if (selectedItem is IObjectWithHeight heightObject) { heightOnMouseDown = heightObject.Height; } mouseDownSelectedBounds = selectedItem.GetAxisAlignedBoundingBox(); } base.OnMouseDown(mouseEvent3D); }
public override void OnMouseDown(Mouse3DEventArgs mouseEvent3D) { if (mouseEvent3D.info != null && mouseEvent3D.MouseEvent2D.Button == MouseButtons.Left && Object3DControlContext.Scene.SelectedItem != null) { hadClickOnControl = true; activeSelectedItem = RootSelection; heightValueDisplayInfo.Visible = true; var selectedItem = activeSelectedItem; var bottomPosition = GetBottomPosition(selectedItem); var topPosition = GetTopPosition(selectedItem); var upNormal = (topPosition - bottomPosition).GetNormal(); var sideNormal = upNormal.Cross(mouseEvent3D.MouseRay.directionNormal).GetNormal(); var planeNormal = upNormal.Cross(sideNormal).GetNormal(); hitPlane = new PlaneShape(new Plane(planeNormal, mouseEvent3D.info.HitPosition), null); originalPointToMove = GetTopPosition(selectedItem); initialHitPosition = mouseEvent3D.info.HitPosition; if (selectedItem is IObjectWithHeight heightObject) { heightOnMouseDown = heightObject.Height; } } base.OnMouseDown(mouseEvent3D); }
private void CalculateMouseDownPostionAndPlane(Vector2 mousePosition) { var rayAtMousePosition = world.GetRayForLocalBounds(mousePosition); var intersectionInfo = Object3DControlLayer.Scene.GetBVHData().GetClosestIntersection(rayAtMousePosition); var rayAtScreenCenter = world.GetRayForLocalBounds(new Vector2(Width / 2, Height / 2)); if (intersectionInfo != null) { // we hit an object in the scene set the position to that mouseDownWorldPosition = intersectionInfo.HitPosition; hitPlane = new PlaneShape(new Plane(rayAtScreenCenter.directionNormal, mouseDownWorldPosition), null); } else { // we did not hit anything // find a new 3d mouse position by hitting the screen plane at the distance of the last 3d mouse down position hitPlane = new PlaneShape(new Plane(rayAtScreenCenter.directionNormal, mouseDownWorldPosition), null); intersectionInfo = hitPlane.GetClosestIntersection(rayAtMousePosition); if (intersectionInfo != null) { mouseDownWorldPosition = intersectionInfo.HitPosition; } else { int a = 0; } } }
public override void OnMouseDown(Mouse3DEventArgs mouseEvent3D) { var selectedItem = RootSelection; ActiveSelectedItem = selectedItem; if (mouseEvent3D.MouseEvent2D.Button == MouseButtons.Left && mouseEvent3D.info != null && selectedItem != null) { hadClickOnControl = true; xValueDisplayInfo.Visible = true; yValueDisplayInfo.Visible = true; var edge0 = ObjectSpace.GetEdgePosition(selectedItem, quadrantIndex); var edge1 = ObjectSpace.GetEdgePosition(selectedItem, quadrantIndex + 1); var edge3 = ObjectSpace.GetEdgePosition(selectedItem, quadrantIndex + 2); var normal01 = (edge1 - edge0).GetNormal(); var normal03 = (edge3 - edge0).GetNormal(); var planeNormal = normal01.Cross(normal03).GetNormal(); hitPlane = new PlaneShape(new Plane(planeNormal, edge0), null); initialHitPosition = mouseEvent3D.info.HitPosition; scaleController = new ScaleController(Object3DControlContext, getWidth, setWidth, getDepth, setDepth, getHeight, setHeight); Object3DControlContext.Scene.ShowSelectionShadow = false; } base.OnMouseDown(mouseEvent3D); }
public IEnumerator AlbedoTexture_AlbedoAlpha(float alpha) { yield return(InitVisualTestsScene($"PBRMaterialVisualTests_AlbedoTexture_AlbedoAlpha_{alpha.ToString(CultureInfo.InvariantCulture)}")); VisualTestHelpers.SetSSAOActive(true); Vector3 camTarget = new Vector3(5, 1, 5); VisualTestHelpers.RepositionVisualTestsCamera(VisualTestController.i.camera, new Vector3(4.6f, 1.8f, 0.6f), camTarget); DCLTexture texture = TestHelpers.CreateDCLTexture(scene, TestAssetsUtils.GetPath() + "/Images/avatar.png"); yield return(texture.routine); PlaneShape plane = TestHelpers.CreateEntityWithPlaneShape(scene, new Vector3(5, 1, 5), true); IDCLEntity planeEntity = plane.attachedEntities.FirstOrDefault(); TestHelpers.SetEntityTransform(scene, planeEntity, new Vector3(5, 1, 5), Quaternion.Euler(0, 0, 180), Vector3.one * 3); PBRMaterial planeMaterial = TestHelpers.AttachPBRMaterialToEntity(scene, planeEntity, new PBRMaterial.Model { transparencyMode = 2, albedoTexture = texture.id, albedoColor = new Color(1, 1, 1, alpha) }); yield return(plane.routine); yield return(planeMaterial.routine); yield return(null); yield return(VisualTestHelpers.TakeSnapshot()); }
public void Clone() { PlaneShape plane = new PlaneShape(new Vector3F(1, 2, 3).Normalized, new Vector3F(2, 3, 4)); PlaneShape clone = plane.Clone() as PlaneShape; Assert.IsNotNull(clone); Assert.AreEqual(plane.Normal, clone.Normal); Assert.AreEqual(plane.DistanceFromOrigin, clone.DistanceFromOrigin); Assert.AreEqual(plane.GetAabb(Pose.Identity).Minimum, clone.GetAabb(Pose.Identity).Minimum); Assert.AreEqual(plane.GetAabb(Pose.Identity).Maximum, clone.GetAabb(Pose.Identity).Maximum); }
public void Clone() { PlaneShape plane = new PlaneShape(new Vector3(1, 2, 3).Normalized, new Vector3(2, 3, 4)); PlaneShape clone = plane.Clone() as PlaneShape; Assert.IsNotNull(clone); Assert.AreEqual(plane.Normal, clone.Normal); Assert.AreEqual(plane.DistanceFromOrigin, clone.DistanceFromOrigin); Assert.AreEqual(plane.GetAabb(Pose.Identity).Minimum, clone.GetAabb(Pose.Identity).Minimum); Assert.AreEqual(plane.GetAabb(Pose.Identity).Maximum, clone.GetAabb(Pose.Identity).Maximum); }
public override void OnMouseDown(MouseEvent3DArgs mouseEvent3D) { zHitHeight = mouseEvent3D.info.hitPosition.z; lastMoveDelta = new Vector3(); double distanceToHit = Vector3.Dot(mouseEvent3D.info.hitPosition, mouseEvent3D.MouseRay.directionNormal); hitPlane = new PlaneShape(mouseEvent3D.MouseRay.directionNormal, distanceToHit, null); IntersectInfo info = hitPlane.GetClosestIntersection(mouseEvent3D.MouseRay); zHitHeight = info.hitPosition.z; base.OnMouseDown(mouseEvent3D); }
public void Properties() { PlaneShape p = new PlaneShape(); Assert.AreEqual(new Vector3(0, 1, 0), p.Normal); Assert.AreEqual(0, p.DistanceFromOrigin); p.DistanceFromOrigin = -10; Assert.AreEqual(new Vector3(0, 1, 0), p.Normal); Assert.AreEqual(-10, p.DistanceFromOrigin); var normal = new Vector3(1, 2, 3).Normalized; p.Normal = normal; Assert.AreEqual(normal, p.Normal); Assert.AreEqual(-10, p.DistanceFromOrigin); }
public void SerializationBinary() { var a = new PlaneShape(new Vector3(1, 2, 3).Normalized, 44); // Serialize object. var stream = new MemoryStream(); var formatter = new BinaryFormatter(); formatter.Serialize(stream, a); // Deserialize object. stream.Position = 0; var deserializer = new BinaryFormatter(); var b = (PlaneShape)deserializer.Deserialize(stream); Assert.AreEqual(a.Normal, b.Normal); Assert.AreEqual(a.DistanceFromOrigin, b.DistanceFromOrigin); }
public void GetMesh() { PlaneShape p = new PlaneShape(new Vector3(1, 2, 3).Normalized, 10); var m = p.GetMesh(0, 1); Assert.Greater(m.NumberOfTriangles, 0); // Check if all vertices lie in the plane. for (int i = 0; i < m.NumberOfTriangles; i++) { Triangle t = m.GetTriangle(i); Assert.IsTrue(GeometryHelper.GetDistance(new Plane(p), t.Vertex0) < 0.0001f); Assert.IsTrue(GeometryHelper.GetDistance(new Plane(p), t.Vertex1) < 0.0001f); Assert.IsTrue(GeometryHelper.GetDistance(new Plane(p), t.Vertex2) < 0.0001f); } }
[Explicit, Category("Explicit")] //Enable the test once we properly render opaque objects with SSAO behind transparents public IEnumerator TransparentObjectsAndSSAO() { yield return(InitVisualTestsScene("PBRMaterialVisualTests_TransparentObjectsAndSSAO")); VisualTestHelpers.SetSSAOActive(true); Vector3 camTarget = new Vector3(5, 1, 5); VisualTestHelpers.RepositionVisualTestsCamera(VisualTestController.i.camera, new Vector3(4.6f, 1.8f, 0.6f), camTarget); PlaneShape plane = TestHelpers.CreateEntityWithPlaneShape(scene, new Vector3(5, 1, 5), true); IDCLEntity planeEntity = plane.attachedEntities.FirstOrDefault(); TestHelpers.SetEntityTransform(scene, planeEntity, new Vector3(5, 1, 5), Quaternion.identity, Vector3.one * 3); PBRMaterial planeMaterial = TestHelpers.AttachPBRMaterialToEntity(scene, planeEntity, new PBRMaterial.Model { alphaTest = 1, transparencyMode = 1, albedoColor = Vector4.one }); yield return(plane.routine); yield return(planeMaterial.routine); BoxShape box1 = TestHelpers.CreateEntityWithBoxShape(scene, new Vector3(4, 1, 6), true); PBRMaterial box1Material = TestHelpers.AttachPBRMaterialToEntity(scene, box1.attachedEntities.FirstOrDefault(), new PBRMaterial.Model { transparencyMode = 0, albedoColor = Color.blue }); yield return(box1.routine); yield return(box1Material.routine); BoxShape box2 = TestHelpers.CreateEntityWithBoxShape(scene, new Vector3(5, 1, 6.5f), true); PBRMaterial box2Material = TestHelpers.AttachPBRMaterialToEntity(scene, box2.attachedEntities.FirstOrDefault(), new PBRMaterial.Model { transparencyMode = 0, albedoColor = Color.red }); yield return(box2.routine); yield return(box2Material.routine); yield return(null); yield return(VisualTestHelpers.TakeSnapshot()); }
private void UpdatePosition(Vector2 screenPosition) { var ray = context.World.GetRayForLocalBounds(screenPosition); var scene = context.Scene; var intersectionInfo = scene.GetBVHData().GetClosestIntersection(ray); var oldPosition = getPosition(); var newPosition = oldPosition; var world = Object3DControlContext.World; var rayNormal = (oldPosition - world.EyePosition).GetNormal(); if (intersectionInfo == null) { if (HitPlane == null) { HitPlane = new PlaneShape(new Plane(rayNormal, oldPosition), null); } intersectionInfo = HitPlane.GetClosestIntersection(ray); if (intersectionInfo != null) { newPosition = intersectionInfo.HitPosition; } } else { HitPlane = new PlaneShape(new Plane(rayNormal, oldPosition), null); foreach (var object3D in scene.Children) { if (object3D.GetBVHData().Contains(intersectionInfo.HitPosition)) { newPosition = intersectionInfo.HitPosition; break; } } } if (newPosition != oldPosition) { setPosition(newPosition); context.GuiSurface.Invalidate(); } }
private StaticBody CreateCollisionPlane(Vector3 position, Vector3 normal, float d) { StaticBody body = new StaticBody(); CollisionShape colShape = new CollisionShape(); PlaneShape plaShape = new PlaneShape(); plaShape.Plane = new Plane(normal, d); colShape.Shape = plaShape; Transform tform = Transform.Identity; tform.origin = position; body.CollisionLayer = (int)CollisionLayers.Floor; body.Transform = tform; body.AddChild(colShape); return(body); }
public override void OnMouseDown(MouseEvent3DArgs mouseEvent3D) { if (mouseEvent3D.info != null && InteractionContext.Scene.SelectedItem != null) { HadClickOnControl = true; ActiveSelectedItem = RootSelection; zValueDisplayInfo.Visible = true; var selectedItem = ActiveSelectedItem; double distanceToHit = Vector3Ex.Dot(mouseEvent3D.info.HitPosition, mouseEvent3D.MouseRay.directionNormal); hitPlane = new PlaneShape(mouseEvent3D.MouseRay.directionNormal, distanceToHit, null); originalPointToMove = GetTopPosition(selectedItem); initialHitPosition = mouseEvent3D.info.HitPosition; transformOnMouseDown = selectedItem.Matrix; mouseDownSelectedBounds = selectedItem.GetAxisAlignedBoundingBox(Matrix4X4.Identity); } base.OnMouseDown(mouseEvent3D); }
public override void OnMouseDown(MouseEvent3DArgs mouseEvent3D) { var selectedItem = RootSelection; if (mouseEvent3D.info != null && selectedItem != null) { HadClickOnControl = true; ActiveSelectedItem = selectedItem; zHeightDisplayInfo.Visible = true; double distanceToHit = Vector3Ex.Dot(mouseEvent3D.info.HitPosition, mouseEvent3D.MouseRay.directionNormal); hitPlane = new PlaneShape(mouseEvent3D.MouseRay.directionNormal, distanceToHit, null); initialHitPosition = mouseEvent3D.info.HitPosition; transformOnMouseDown = selectedItem.Matrix; mouseDownSelectedBounds = selectedItem.GetAxisAlignedBoundingBox(); } base.OnMouseDown(mouseEvent3D); }
public void SerializationXml() { var a = new PlaneShape(new Vector3(1, 2, 3).Normalized, 44); // Serialize object. var stream = new MemoryStream(); var serializer = new XmlSerializer(typeof(Shape)); serializer.Serialize(stream, a); // Output generated xml. Can be manually checked in output window. stream.Position = 0; var xml = new StreamReader(stream).ReadToEnd(); Trace.WriteLine("Serialized Object:\n" + xml); // Deserialize object. stream.Position = 0; var deserializer = new XmlSerializer(typeof(Shape)); var b = (PlaneShape)deserializer.Deserialize(stream); Assert.AreEqual(a.Normal, b.Normal); Assert.AreEqual(a.DistanceFromOrigin, b.DistanceFromOrigin); }
public BaseDisposable SharedComponentCreate(string id, int classId) { BaseDisposable disposableComponent; if (disposableComponents.TryGetValue(id, out disposableComponent)) { return(disposableComponent); } BaseDisposable newComponent = null; switch ((CLASS_ID)classId) { case CLASS_ID.BOX_SHAPE: { newComponent = new BoxShape(this); break; } case CLASS_ID.SPHERE_SHAPE: { newComponent = new SphereShape(this); break; } case CLASS_ID.CONE_SHAPE: { newComponent = new ConeShape(this); break; } case CLASS_ID.CYLINDER_SHAPE: { newComponent = new CylinderShape(this); break; } case CLASS_ID.PLANE_SHAPE: { newComponent = new PlaneShape(this); break; } case CLASS_ID.GLTF_SHAPE: { newComponent = new GLTFShape(this); break; } case CLASS_ID.NFT_SHAPE: { newComponent = new NFTShape(this); break; } case CLASS_ID.OBJ_SHAPE: { newComponent = new OBJShape(this); break; } case CLASS_ID.BASIC_MATERIAL: { newComponent = new BasicMaterial(this); break; } case CLASS_ID.PBR_MATERIAL: { newComponent = new PBRMaterial(this); break; } case CLASS_ID.AUDIO_CLIP: { newComponent = new DCLAudioClip(this); break; } case CLASS_ID.TEXTURE: { newComponent = new DCLTexture(this); break; } case CLASS_ID.UI_INPUT_TEXT_SHAPE: { newComponent = new UIInputText(this); break; } case CLASS_ID.UI_FULLSCREEN_SHAPE: case CLASS_ID.UI_SCREEN_SPACE_SHAPE: { if (GetSharedComponent <UIScreenSpace>() == null) { newComponent = new UIScreenSpace(this); } break; } case CLASS_ID.UI_CONTAINER_RECT: { newComponent = new UIContainerRect(this); break; } case CLASS_ID.UI_SLIDER_SHAPE: { newComponent = new UIScrollRect(this); break; } case CLASS_ID.UI_CONTAINER_STACK: { newComponent = new UIContainerStack(this); break; } case CLASS_ID.UI_IMAGE_SHAPE: { newComponent = new UIImage(this); break; } case CLASS_ID.UI_TEXT_SHAPE: { newComponent = new UIText(this); break; } case CLASS_ID.VIDEO_CLIP: { newComponent = new DCLVideoClip(this); break; } case CLASS_ID.VIDEO_TEXTURE: { newComponent = new DCLVideoTexture(this); break; } case CLASS_ID.FONT: { newComponent = new DCLFont(this); break; } case CLASS_ID.NAME: { newComponent = new DCLName(this); break; } case CLASS_ID.LOCKED_ON_EDIT: { newComponent = new DCLLockedOnEdit(this); break; } case CLASS_ID.VISIBLE_ON_EDIT: { newComponent = new DCLVisibleOnEdit(this); break; } default: Debug.LogError($"Unknown classId"); break; } if (newComponent != null) { newComponent.id = id; disposableComponents.Add(id, newComponent); OnAddSharedComponent?.Invoke(id, newComponent); } return(newComponent); }
public override void OnMouseMove(MouseEvent3DArgs mouseEvent3D) { IObject3D selectedItem = RootSelection; if (selectedItem != null) { var controlCenter = GetControlCenter(selectedItem); if (mouseDownInfo != null) { controlCenter = mouseDownInfo.ControlCenter; } var hitPlane = new PlaneShape(RotationPlanNormal, Vector3Ex.Dot(RotationPlanNormal, controlCenter), null); IntersectInfo hitOnRotationPlane = hitPlane.GetClosestIntersection(mouseEvent3D.MouseRay); if (hitOnRotationPlane != null) { AxisAlignedBoundingBox currentSelectedBounds = selectedItem.GetAxisAlignedBoundingBox(Matrix4X4.Identity); var selectedObjectRotationCenter = currentSelectedBounds.Center; if (mouseDownInfo != null) { selectedObjectRotationCenter = mouseDownInfo.SelectedObjectRotationCenter; } Vector3 cornerForAxis = GetCornerPosition(selectedItem); // move the rotation center to the correct side of the bounding box selectedObjectRotationCenter[RotationAxis] = cornerForAxis[RotationAxis]; mouseMoveInfo = new Mouse3DInfo( hitOnRotationPlane.HitPosition, selectedItem.Matrix, selectedObjectRotationCenter, controlCenter, RotationAxis ); if (MouseDownOnControl && mouseDownInfo != null) { double rawDeltaRotationAngle = mouseMoveInfo.AngleOfHit - mouseDownInfo.AngleOfHit; double snapRadians = MathHelper.DegreesToRadians(1); // snap this position to the grid if (rawDeltaRotationAngle > 0) { SnappedRotationAngle = ((int)((rawDeltaRotationAngle / snapRadians) + .5)) * snapRadians; } else { SnappedRotationAngle = ((int)((rawDeltaRotationAngle / snapRadians) - .5)) * snapRadians; } int snappingIndex = GetSnapIndex(selectedItem, numSnapPoints); if (snappingIndex != -1) { SnappedRotationAngle = snappingIndex * MathHelper.Tau / numSnapPoints; } else if (InteractionContext.GuiSurface.ModifierKeys == Keys.Shift) { snapRadians = MathHelper.DegreesToRadians(45); if (rawDeltaRotationAngle > 0) { SnappedRotationAngle = ((int)((rawDeltaRotationAngle / snapRadians) + .5)) * snapRadians; } else { SnappedRotationAngle = ((int)((rawDeltaRotationAngle / snapRadians) - .5)) * snapRadians; } } if (SnappedRotationAngle < 0) { SnappedRotationAngle += MathHelper.Tau; } // check if this move crosses zero degrees if (lastSnappedRotation == 0 && SnappedRotationAngle != 0) { rotatingCW = DeltaAngle(0, SnappedRotationAngle) < 0; } else if ((DeltaAngle(0, SnappedRotationAngle) < 0 && DeltaAngle(0, lastSnappedRotation) > 0 && Math.Abs(DeltaAngle(0, lastSnappedRotation)) < 1) || (DeltaAngle(0, SnappedRotationAngle) > 0 && DeltaAngle(0, lastSnappedRotation) < 0 && Math.Abs(DeltaAngle(0, lastSnappedRotation)) < 1)) { // let's figure out which way we are going rotatingCW = (DeltaAngle(0, SnappedRotationAngle) < 0 && DeltaAngle(0, lastSnappedRotation) > 0); } // undo the last rotation RotateAroundAxis(selectedItem, -lastSnappedRotation); // rotate it RotateAroundAxis(selectedItem, SnappedRotationAngle); lastSnappedRotation = SnappedRotationAngle; Invalidate(); } } } base.OnMouseMove(mouseEvent3D); }
public void SerializationBinary() { var a = new PlaneShape(new Vector3F(1, 2, 3).Normalized, 44); // Serialize object. var stream = new MemoryStream(); var formatter = new BinaryFormatter(); formatter.Serialize(stream, a); // Deserialize object. stream.Position = 0; var deserializer = new BinaryFormatter(); var b = (PlaneShape)deserializer.Deserialize(stream); Assert.AreEqual(a.Normal, b.Normal); Assert.AreEqual(a.DistanceFromOrigin, b.DistanceFromOrigin); }
public void SerializationXml() { var a = new PlaneShape(new Vector3F(1, 2, 3).Normalized, 44); // Serialize object. var stream = new MemoryStream(); var serializer = new XmlSerializer(typeof(Shape)); serializer.Serialize(stream, a); // Output generated xml. Can be manually checked in output window. stream.Position = 0; var xml = new StreamReader(stream).ReadToEnd(); Trace.WriteLine("Serialized Object:\n" + xml); // Deserialize object. stream.Position = 0; var deserializer = new XmlSerializer(typeof(Shape)); var b = (PlaneShape)deserializer.Deserialize(stream); Assert.AreEqual(a.Normal, b.Normal); Assert.AreEqual(a.DistanceFromOrigin, b.DistanceFromOrigin); }
public override void ComputeCollision(ContactSet contactSet, CollisionQueryType type) { // Object A should be the plane. // Object B should be the other object. IGeometricObject planeObject = contactSet.ObjectA.GeometricObject; IGeometricObject convexObject = contactSet.ObjectB.GeometricObject; // Swap objects if necessary. bool swapped = (convexObject.Shape is PlaneShape); if (swapped) { MathHelper.Swap(ref planeObject, ref convexObject); } PlaneShape planeShape = planeObject.Shape as PlaneShape; ConvexShape convexShape = convexObject.Shape as ConvexShape; // Check if shapes are correct. if (planeShape == null || convexShape == null) { throw new ArgumentException("The contact set must contain a plane and a convex shape.", "contactSet"); } // Get transformations. Vector3F scalePlane = planeObject.Scale; Vector3F scaleB = convexObject.Scale; Pose planePose = planeObject.Pose; Pose poseB = convexObject.Pose; // Apply scale to plane and transform plane into world space. Plane planeWorld = new Plane(planeShape); planeWorld.Scale(ref scalePlane); // Scale plane. planeWorld.ToWorld(ref planePose); // Transform plane to world space. // Transform plane normal to local space of convex. Vector3F planeNormalLocalB = poseB.ToLocalDirection(planeWorld.Normal); // Get support vertex nearest to the plane. Vector3F supportVertexBLocal = convexShape.GetSupportPoint(-planeNormalLocalB, scaleB); // Transform support vertex into world space. Vector3F supportVertexBWorld = poseB.ToWorldPosition(supportVertexBLocal); // Project vertex onto separating axis (given by plane normal). float distance = Vector3F.Dot(supportVertexBWorld, planeWorld.Normal); // Check for collision. float penetrationDepth = planeWorld.DistanceFromOrigin - distance; contactSet.HaveContact = (penetrationDepth >= 0); if (type == CollisionQueryType.Boolean || (type == CollisionQueryType.Contacts && !contactSet.HaveContact)) { // HaveContact queries can exit here. // GetContacts queries can exit here if we don't have a contact. return; } // Position is between support vertex and plane. Vector3F position = supportVertexBWorld + planeWorld.Normal * (penetrationDepth / 2); Vector3F normal = (swapped) ? -planeWorld.Normal : planeWorld.Normal; // Update contact set. Contact contact = ContactHelper.CreateContact(contactSet, position, normal, penetrationDepth, false); ContactHelper.Merge(contactSet, contact, type, CollisionDetection.ContactPositionTolerance); if (CollisionDetection.FullContactSetPerFrame && type == CollisionQueryType.Contacts && contactSet.Count > 0 && contactSet.Count < 4) { // Special treatment for tetrahedra: Test all vertices against plane. IList <Vector3F> vertices = null; if (convexShape is ConvexHullOfPoints) { var convexHullOfPoints = (ConvexHullOfPoints)convexShape; vertices = convexHullOfPoints.Points; } else if (convexShape is ConvexPolyhedron) { var convexPolyhedron = (ConvexPolyhedron)convexShape; vertices = convexPolyhedron.Vertices; } if (vertices != null && vertices.Count <= 8) { // Convex has 8 or less vertices. Explicitly test all vertices against the plane. int numberOfVertices = vertices.Count; for (int i = 0; i < numberOfVertices; i++) { // Test is the same as above. var vertex = vertices[i]; Vector3F scaledVertex = vertex * scaleB; if (scaledVertex != supportVertexBLocal) // supportVertexBLocal has already been added. { Vector3F vertexWorld = poseB.ToWorldPosition(scaledVertex); distance = Vector3F.Dot(vertexWorld, planeWorld.Normal); penetrationDepth = planeWorld.DistanceFromOrigin - distance; if (penetrationDepth >= 0) { position = vertexWorld + planeWorld.Normal * (penetrationDepth / 2); normal = (swapped) ? -planeWorld.Normal : planeWorld.Normal; contact = ContactHelper.CreateContact(contactSet, position, normal, penetrationDepth, false); ContactHelper.Merge(contactSet, contact, type, CollisionDetection.ContactPositionTolerance); } } } } else { // Convex is a complex shape with more than 4 vertices. ContactHelper.TestWithPerturbations( CollisionDetection, contactSet, !swapped, // Perturb the convex object, not the plane. _computeContactsMethod); } } }
public void Properties() { PlaneShape p = new PlaneShape(); Assert.AreEqual(new Vector3F(0, 1, 0), p.Normal); Assert.AreEqual(0, p.DistanceFromOrigin); p.DistanceFromOrigin = -10; Assert.AreEqual(new Vector3F(0, 1, 0), p.Normal); Assert.AreEqual(-10, p.DistanceFromOrigin); var normal = new Vector3F(1, 2, 3).Normalized; p.Normal = normal; Assert.AreEqual(normal, p.Normal); Assert.AreEqual(-10, p.DistanceFromOrigin); }
public override void ComputeCollision(ContactSet contactSet, CollisionQueryType type) { // Object A should be the plane. // Object B should be the sphere. IGeometricObject planeObject = contactSet.ObjectA.GeometricObject; IGeometricObject sphereObject = contactSet.ObjectB.GeometricObject; // A should be the plane, swap objects if necessary. bool swapped = (sphereObject.Shape is PlaneShape); if (swapped) { MathHelper.Swap(ref planeObject, ref sphereObject); } PlaneShape planeShape = planeObject.Shape as PlaneShape; SphereShape sphereShape = sphereObject.Shape as SphereShape; // Check if collision object shapes are correct. if (planeShape == null || sphereShape == null) { throw new ArgumentException("The contact set must contain a plane and a sphere.", "contactSet"); } // Get scalings. Vector3F planeScale = planeObject.Scale; Vector3F sphereScale = Vector3F.Absolute(sphereObject.Scale); // Call other algorithm for non-uniformly scaled spheres. if (sphereScale.X != sphereScale.Y || sphereScale.Y != sphereScale.Z) { if (_fallbackAlgorithm == null) { _fallbackAlgorithm = CollisionDetection.AlgorithmMatrix[typeof(PlaneShape), typeof(ConvexShape)]; } _fallbackAlgorithm.ComputeCollision(contactSet, type); return; } // Get poses. Pose planePose = planeObject.Pose; Pose spherePose = sphereObject.Pose; // Apply scaling to plane and transform plane to world space. Plane plane = new Plane(planeShape); plane.Scale(ref planeScale); // Scale plane. plane.ToWorld(ref planePose); // Transform plane to world space. // Calculate distance from plane to sphere surface. float sphereRadius = sphereShape.Radius * sphereScale.X; Vector3F sphereCenter = spherePose.Position; float planeToSphereDistance = Vector3F.Dot(sphereCenter, plane.Normal) - sphereRadius - plane.DistanceFromOrigin; float penetrationDepth = -planeToSphereDistance; contactSet.HaveContact = (penetrationDepth >= 0); if (type == CollisionQueryType.Boolean || (type == CollisionQueryType.Contacts && !contactSet.HaveContact)) { // HaveContact queries can exit here. // GetContacts queries can exit here if we don't have a contact. return; } // Compute contact details. Vector3F position = sphereCenter - plane.Normal * (sphereRadius - penetrationDepth / 2); Vector3F normal = (swapped) ? -plane.Normal : plane.Normal; // Update contact set. Contact contact = ContactHelper.CreateContact(contactSet, position, normal, penetrationDepth, false); ContactHelper.Merge(contactSet, contact, type, CollisionDetection.ContactPositionTolerance); }
public BaseDisposable SharedComponentCreate(string id, string name, int classId) { SceneController.i.OnMessageDecodeStart?.Invoke("ComponentCreated"); sharedComponentCreatedMessage.id = id; sharedComponentCreatedMessage.name = name; sharedComponentCreatedMessage.classId = classId; SceneController.i.OnMessageDecodeEnds?.Invoke("ComponentCreated"); BaseDisposable disposableComponent; if (disposableComponents.TryGetValue(sharedComponentCreatedMessage.id, out disposableComponent)) { return(disposableComponent); } BaseDisposable newComponent = null; switch ((CLASS_ID)sharedComponentCreatedMessage.classId) { case CLASS_ID.BOX_SHAPE: { newComponent = new BoxShape(this); break; } case CLASS_ID.SPHERE_SHAPE: { newComponent = new SphereShape(this); break; } case CLASS_ID.CONE_SHAPE: { newComponent = new ConeShape(this); break; } case CLASS_ID.CYLINDER_SHAPE: { newComponent = new CylinderShape(this); break; } case CLASS_ID.PLANE_SHAPE: { newComponent = new PlaneShape(this); break; } case CLASS_ID.GLTF_SHAPE: { newComponent = new GLTFShape(this); break; } case CLASS_ID.NFT_SHAPE: { newComponent = new NFTShape(this); break; } case CLASS_ID.OBJ_SHAPE: { newComponent = new OBJShape(this); break; } case CLASS_ID.BASIC_MATERIAL: { newComponent = new BasicMaterial(this); break; } case CLASS_ID.PBR_MATERIAL: { newComponent = new PBRMaterial(this); break; } case CLASS_ID.AUDIO_CLIP: { newComponent = new DCLAudioClip(this); break; } case CLASS_ID.TEXTURE: { newComponent = new DCLTexture(this); break; } case CLASS_ID.UI_INPUT_TEXT_SHAPE: { newComponent = new UIInputText(this); break; } case CLASS_ID.UI_FULLSCREEN_SHAPE: case CLASS_ID.UI_SCREEN_SPACE_SHAPE: { if (uiScreenSpace == null) { newComponent = new UIScreenSpace(this); } break; } case CLASS_ID.UI_CONTAINER_RECT: { newComponent = new UIContainerRect(this); break; } case CLASS_ID.UI_SLIDER_SHAPE: { newComponent = new UIScrollRect(this); break; } case CLASS_ID.UI_CONTAINER_STACK: { newComponent = new UIContainerStack(this); break; } case CLASS_ID.UI_IMAGE_SHAPE: { newComponent = new UIImage(this); break; } case CLASS_ID.UI_TEXT_SHAPE: { newComponent = new UIText(this); break; } case CLASS_ID.VIDEO_CLIP: { newComponent = new DCLVideoClip(this); break; } case CLASS_ID.VIDEO_TEXTURE: { newComponent = new DCLVideoTexture(this); break; } case CLASS_ID.FONT: { newComponent = new DCLFont(this); break; } default: Debug.LogError($"Unknown classId"); break; } if (newComponent != null) { newComponent.id = sharedComponentCreatedMessage.id; disposableComponents.Add(sharedComponentCreatedMessage.id, newComponent); if (state != State.READY) { disposableNotReady.Add(id); } } return(newComponent); }
public void DirectionException() { PlaneShape p = new PlaneShape(); p.Normal = new Vector3(); }
public void DirectionException() { PlaneShape p = new PlaneShape(); p.Normal = new Vector3F(); }
public override void ComputeCollision(ContactSet contactSet, CollisionQueryType type) { Debug.Assert(contactSet.Count <= 1, "Ray vs. plane should have at max 1 contact."); // Object A should be the plane. // Object B should be the ray. IGeometricObject planeObject = contactSet.ObjectA.GeometricObject; IGeometricObject rayObject = contactSet.ObjectB.GeometricObject; // Swap objects if necessary. bool swapped = (rayObject.Shape is PlaneShape); if (swapped) { MathHelper.Swap(ref planeObject, ref rayObject); } PlaneShape planeShape = planeObject.Shape as PlaneShape; RayShape rayShape = rayObject.Shape as RayShape; // Check if A is really a plane and B is a ray. if (planeShape == null || rayShape == null) { throw new ArgumentException("The contact set must contain a plane and a ray.", "contactSet"); } // Get transformations. Vector3F planeScale = planeObject.Scale; Vector3F rayScale = rayObject.Scale; Pose rayPose = rayObject.Pose; Pose planePose = planeObject.Pose; // Apply scale to plane. Plane plane = new Plane(planeShape); plane.Scale(ref planeScale); // Apply scale to ray and transform ray into local space of plane. Ray ray = new Ray(rayShape); ray.Scale(ref rayScale); // Scale ray. ray.ToWorld(ref rayPose); // Transform ray to world space. ray.ToLocal(ref planePose); // Transform ray to local space of plane. // Convert ray into a line segment. LineSegment segment = new LineSegment { Start = ray.Origin, End = ray.Origin + ray.Direction * ray.Length }; // Check if ray origin is inside the plane. Otherwise call plane vs. ray query. Vector3F linePoint; Vector3F planePoint = Vector3F.Zero; if (Vector3F.Dot(segment.Start, plane.Normal) <= plane.DistanceFromOrigin) { // The origin of the ray is below the plane. linePoint = segment.Start; contactSet.HaveContact = true; } else { // The origin of the ray is above the plane. contactSet.HaveContact = GeometryHelper.GetClosestPoints(plane, segment, out linePoint, out planePoint); } if (type == CollisionQueryType.Boolean || (type == CollisionQueryType.Contacts && !contactSet.HaveContact)) { // HaveContact queries can exit here. // GetContacts queries can exit here if we don't have a contact. return; } // ----- Create contact info. Vector3F position; float penetrationDepth; if (contactSet.HaveContact) { // We have a contact. position = planePose.ToWorldPosition(linePoint); penetrationDepth = (linePoint - segment.Start).Length; } else { // Closest points, but separated. position = planePose.ToWorldPosition((planePoint + linePoint) / 2); penetrationDepth = -(linePoint - planePoint).Length; } Vector3F normal = planePose.ToWorldDirection(plane.Normal); if (swapped) { normal = -normal; } Contact contact = ContactHelper.CreateContact(contactSet, position, normal, penetrationDepth, contactSet.HaveContact); ContactHelper.Merge(contactSet, contact, type, CollisionDetection.ContactPositionTolerance); }
public override void ComputeCollision(ContactSet contactSet, CollisionQueryType type) { // Object A should be the plane. // Object B should be the other object. IGeometricObject planeObject = contactSet.ObjectA.GeometricObject; IGeometricObject boxObject = contactSet.ObjectB.GeometricObject; // Swap objects if necessary. bool swapped = (boxObject.Shape is PlaneShape); if (swapped) { MathHelper.Swap(ref planeObject, ref boxObject); } PlaneShape planeShape = planeObject.Shape as PlaneShape; BoxShape boxShape = boxObject.Shape as BoxShape; // Check if shapes are correct. if (planeShape == null || boxShape == null) { throw new ArgumentException("The contact set must contain a plane and a box shape.", "contactSet"); } // Get transformations. Vector3 scalePlane = planeObject.Scale; Vector3 scaleBox = boxObject.Scale; Pose posePlane = planeObject.Pose; Pose poseBox = boxObject.Pose; // Apply scale to plane and transform plane into world space. Plane planeWorld = new Plane(planeShape); planeWorld.Scale(ref scalePlane); // Scale plane. planeWorld.ToWorld(ref posePlane); // Transform plane to world space. // Transform plane normal to local space of box. Vector3 planeNormalLocalB = poseBox.ToLocalDirection(planeWorld.Normal); // Get support vertex nearest to the plane. Vector3 supportVertexBLocal = boxShape.GetSupportPoint(-planeNormalLocalB, scaleBox); // Transform support vertex into world space. Vector3 supportVertexBWorld = poseBox.ToWorldPosition(supportVertexBLocal); // Project vertex onto separating axis (given by plane normal). float distance = Vector3.Dot(supportVertexBWorld, planeWorld.Normal); // Check for collision. float penetrationDepth = planeWorld.DistanceFromOrigin - distance; contactSet.HaveContact = (penetrationDepth >= 0); if (type == CollisionQueryType.Boolean || (type == CollisionQueryType.Contacts && !contactSet.HaveContact)) { // HaveContact queries can exit here. // GetContacts queries can exit here if we don't have a contact. return; } // We have contact. if (!CollisionDetection.FullContactSetPerFrame || type == CollisionQueryType.ClosestPoints) { // Use only the already known contact. AddContact(ref supportVertexBWorld, ref planeWorld, penetrationDepth, swapped, contactSet, type); } else { // Apply scale to box extent. Vector3 boxHalfExtent = boxShape.Extent * scaleBox * 0.5f; // Check all box vertices against plane. CheckContact(ref planeWorld, new Vector3(-boxHalfExtent.X, -boxHalfExtent.Y, -boxHalfExtent.Z), ref poseBox, swapped, contactSet); CheckContact(ref planeWorld, new Vector3(-boxHalfExtent.X, -boxHalfExtent.Y, boxHalfExtent.Z), ref poseBox, swapped, contactSet); CheckContact(ref planeWorld, new Vector3(-boxHalfExtent.X, boxHalfExtent.Y, -boxHalfExtent.Z), ref poseBox, swapped, contactSet); CheckContact(ref planeWorld, new Vector3(-boxHalfExtent.X, boxHalfExtent.Y, boxHalfExtent.Z), ref poseBox, swapped, contactSet); CheckContact(ref planeWorld, new Vector3(boxHalfExtent.X, -boxHalfExtent.Y, -boxHalfExtent.Z), ref poseBox, swapped, contactSet); CheckContact(ref planeWorld, new Vector3(boxHalfExtent.X, -boxHalfExtent.Y, boxHalfExtent.Z), ref poseBox, swapped, contactSet); CheckContact(ref planeWorld, new Vector3(boxHalfExtent.X, boxHalfExtent.Y, -boxHalfExtent.Z), ref poseBox, swapped, contactSet); CheckContact(ref planeWorld, new Vector3(boxHalfExtent.X, boxHalfExtent.Y, boxHalfExtent.Z), ref poseBox, swapped, contactSet); } }
private void Update(bool invalidateRenderData) { if (invalidateRenderData) { RenderData.SafeDispose(); } // Update shape. if (Volume == null) { // Use a PlaneShape for an infinite ocean. var planeShape = Shape as PlaneShape; if (planeShape != null) { planeShape.Normal = new Vector3F(0, 1, 0); planeShape.DistanceFromOrigin = ExtraHeight; } else { Shape = new PlaneShape(new Vector3F(0, 1, 0), ExtraHeight); } return; } // Check if we have a valid AABB. var aabb = Volume.GetAabb(); if (!Numeric.IsZeroOrPositiveFinite(aabb.Extent.LengthSquared)) { throw new GraphicsException("Invalid water volume. The water volume must be a finite shape or null."); } // Apply ExtraHeight. We also apply it horizontally because choppy waves // move vertices horizontally too. aabb.Minimum.X -= ExtraHeight; // Minimum y should be at least max y - ExtraHeight. aabb.Minimum.Y = Math.Min(aabb.Minimum.Y, aabb.Maximum.Y - ExtraHeight); aabb.Minimum.Z -= ExtraHeight; aabb.Maximum.X += ExtraHeight; aabb.Maximum.Y += ExtraHeight; aabb.Maximum.Z += ExtraHeight; // Create shape from volume AABB. if (aabb.Center.IsNumericallyZero) { // Use BoxShape. var boxShape = Shape as BoxShape; if (boxShape != null) { boxShape.Extent = aabb.Extent; } else { Shape = new BoxShape(aabb.Extent); } } else { BoxShape boxShape = null; var transformedShape = Shape as TransformedShape; if (transformedShape != null) { boxShape = transformedShape.Child.Shape as BoxShape; } if (boxShape != null) { boxShape.Extent = aabb.Extent; ((GeometricObject)transformedShape.Child).Pose = new Pose(aabb.Center); } else { Shape = new TransformedShape( new GeometricObject(new BoxShape(aabb.Extent), new Pose(aabb.Center))); } } }
public void GetMesh() { PlaneShape p = new PlaneShape(new Vector3F(1, 2, 3).Normalized, 10); var m = p.GetMesh(0, 1); Assert.Greater(m.NumberOfTriangles, 0); // Check if all vertices lie in the plane. for (int i = 0; i < m.NumberOfTriangles; i++) { Triangle t = m.GetTriangle(i); Assert.IsTrue(GeometryHelper.GetDistance(new Plane(p), t.Vertex0) < 0.0001f); Assert.IsTrue(GeometryHelper.GetDistance(new Plane(p), t.Vertex1) < 0.0001f); Assert.IsTrue(GeometryHelper.GetDistance(new Plane(p), t.Vertex2) < 0.0001f); } }