/// Copyright (c) 2021 Iiro Iivanainen, Harri Linna, Jere Pakkanen, Riikka Vilavaara /// /// Permission is hereby granted, free of charge, to any person obtaining /// a copy of this software and associated documentation files (the /// "Software"), to deal in the Software without restriction, including /// without limitation the rights to use, copy, modify, merge, publish, /// distribute, sublicense, and/or sell copies of the Software, and to /// permit persons to whom the Software is furnished to do so, subject to /// the following conditions: /// /// The above copyright notice and this permission notice shall be included /// in all copies or substantial portions of the Software. /// /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, /// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF /// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. /// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY /// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, /// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE /// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using System; using System.Numerics; using SharpGL; using SharpGL.WPF; using SharpGL.SceneGraph; using SharpGL.SceneGraph.Assets; namespace WPFOpenGL { public class UserShape : Shape { public MainWindow.Planes plane; private Vector2 bottomleft = new Vector2(); private Vector2 topright = new Vector2(); private float depth; private Vector3 v0; private Vector3 v1; private Vector3 v2; private Vector3 v3; private Vector4 color = new Vector4(1f, 1f, 0f, 1f); /// v2 v3 /// +--------+ /// | | /// | | /// | | /// +--------+ /// v0 v1 public UserShape(Vector2 start, Vector2 end, float depth, MainWindow.Planes plane) { this.plane = plane; this.depth = depth; bottomleft.X = MathF.Min(start.X, end.X); bottomleft.Y = MathF.Min(start.Y, end.Y); topright.X = MathF.Max(start.X, end.X); topright.Y = MathF.Max(start.Y, end.Y); calculateVertices(); } public UserShape(Vector3 start, Vector3 end, MainWindow.Planes plane) { this.plane = plane; if (plane == MainWindow.Planes.XY) { SetStartEnd(new Vector2(start.X, start.Y), new Vector2(end.X, end.Y), start.Z); } if (plane == MainWindow.Planes.XZ) { SetStartEnd(new Vector2(start.X, start.Z), new Vector2(end.X, end.Z), start.Y); } if (plane == MainWindow.Planes.YZ) { SetStartEnd(new Vector2(start.Y, start.Z), new Vector2(end.Y, end.Z), start.X); } } public void SetColor(Vector4 color) { this.color = color; } public void SetStartEnd(Vector2 start, Vector2 end, float depth) { this.depth = depth; bottomleft.X = MathF.Min(start.X, end.X); bottomleft.Y = MathF.Min(start.Y, end.Y); topright.X = MathF.Max(start.X, end.X); topright.Y = MathF.Max(start.Y, end.Y); calculateVertices(); } public void SetStartEnd(Vector3 start, Vector3 end) { if (plane == MainWindow.Planes.XY) { SetStartEnd(new Vector2(start.X, start.Y), new Vector2(end.X, end.Y), start.Z); } if (plane == MainWindow.Planes.XZ) { SetStartEnd(new Vector2(start.X, start.Z), new Vector2(end.X, end.Z), start.Y); } if (plane == MainWindow.Planes.YZ) { SetStartEnd(new Vector2(start.Y, start.Z), new Vector2(end.Y, end.Z), start.X); } calculateVertices(); } private void calculateVertices() { if (plane == MainWindow.Planes.XY) { v0 = new Vector3(bottomleft.X, bottomleft.Y, depth); v1 = new Vector3(topright.X, bottomleft.Y, depth); v2 = new Vector3(bottomleft.X, topright.Y, depth); v3 = new Vector3(topright.X, topright.Y, depth); } if (plane == MainWindow.Planes.XZ) { v0 = new Vector3(bottomleft.X, depth, bottomleft.Y); v1 = new Vector3(topright.X, depth, bottomleft.Y); v2 = new Vector3(bottomleft.X, depth, topright.Y); v3 = new Vector3(topright.X, depth, topright.Y); } if (plane == MainWindow.Planes.YZ) { v0 = new Vector3(depth, bottomleft.X, bottomleft.Y); v1 = new Vector3(depth, topright.X, bottomleft.Y); v2 = new Vector3(depth, bottomleft.X, topright.Y); v3 = new Vector3(depth, topright.X, topright.Y); } } public override bool IntersectRay(Vector3 rayOrigin, Vector3 rayDirection, out Vector3 hit, out float distance) { hit = new Vector3(0f, 0f, 0f); distance = -1f; if (!isVisible || !isRaycastable) return false; return RayCast.IntersectQuad(rayOrigin, rayDirection, v0, v1, v2, v3, out hit, out distance); } public override void Render(OpenGL openGL) { openGL.Begin(OpenGL.GL_LINE_LOOP); openGL.Color(color.X, color.Y, color.Z, color.W); openGL.Vertex(v0.X, v0.Y, v0.Z); openGL.Vertex(v1.X, v1.Y, v1.Z); openGL.Vertex(v3.X, v3.Y, v3.Z); openGL.Vertex(v2.X, v2.Y, v2.Z); openGL.Vertex(v0.X, v0.Y, v0.Z); openGL.End(); } } }