/* Copyright (c) 2024-present miku-666 * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1.The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. **/ using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Linq; using OpenTK; using PckStudio.Core; using PckStudio.Core.Extensions; namespace PckStudio.Rendering { public class CubeMesh : GenericMesh { private Cube _cube; public Vector3 Center => _cube.Center; internal static int[] IndicesData { get; } = [ // Face 1 (Back) 0, 1, 2, 2, 3, 0, // Face 2 (Front) 4, 5, 6, 6, 7, 4, // Face 3 (Top) 8, 9, 10, 10, 11, 8, // Face 4 (Bottom) 12, 13, 14, 14, 15, 12, // Face 5 (Left) 16, 17, 18, 18, 19, 16, // Face 6 (Right) 20, 21, 22, 22, 23, 20 ]; internal static VertexBufferLayout VertexBufferLayout { get; } = new VertexBufferLayout().Add(ShaderDataType.Float3).Add(ShaderDataType.Float2); public CubeMesh(Cube cube) : this(nameof(CubeMesh), cube) { } public CubeMesh(string name, Cube cube) : this(name, cube, true) { } private CubeMesh(string name, Cube cube, bool visible) : base(name, visible, OpenTK.Graphics.OpenGL.PrimitiveType.Triangles, VertexBufferLayout) { _cube = cube; } public CubeMesh SetCube(Cube cube) { _ = cube ?? throw new ArgumentNullException(nameof(cube)); return new CubeMesh(Name, cube, Visible); } public override GenericMesh SetVisible(bool visible) => new CubeMesh(Name, _cube, visible); public Cube GetCube() => _cube; public override Matrix4 GetTransform() => _cube.GetBoundingBox().GetTransform(); public override BoundingBox GetBounds(Matrix4 transform) { return _cube.GetBoundingBox(transform); } public override IEnumerable GetVertices() { int mirror = Convert.ToInt32(_cube.MirrorTexture); Vector2 uv = _cube.Uv; Vector3 size = _cube.Size; // Back yield return new TextureVertex(new Vector3(0f, 1f, 1f), new Vector2(uv.X + size.Z * 2 + size.X + size.X * (1 - mirror), uv.Y + size.Z + size.Y)); yield return new TextureVertex(new Vector3(1f, 1f, 1f), new Vector2(uv.X + size.Z * 2 + size.X + size.X * mirror, uv.Y + size.Z + size.Y)); yield return new TextureVertex(new Vector3(1f, 0f, 1f), new Vector2(uv.X + size.Z * 2 + size.X + size.X * mirror, uv.Y + size.Z)); yield return new TextureVertex(new Vector3(0f, 0f, 1f), new Vector2(uv.X + size.Z * 2 + size.X + size.X * (1 - mirror), uv.Y + size.Z)); // Front yield return new TextureVertex(new Vector3(0f, 1f, 0f), new Vector2(uv.X + size.Z + size.X * mirror, uv.Y + size.Z + size.Y)); yield return new TextureVertex(new Vector3(1f, 1f, 0f), new Vector2(uv.X + size.Z + size.X * (1 - mirror), uv.Y + size.Z + size.Y)); yield return new TextureVertex(new Vector3(1f, 0f, 0f), new Vector2(uv.X + size.Z + size.X * (1 - mirror), uv.Y + size.Z)); yield return new TextureVertex(new Vector3(0f, 0f, 0f), new Vector2(uv.X + size.Z + size.X * mirror, uv.Y + size.Z)); // Top yield return new TextureVertex(new Vector3(0f, 0f, 0f), new Vector2(uv.X + size.Z + size.X * mirror, uv.Y + size.Z)); yield return new TextureVertex(new Vector3(0f, 0f, 1f), new Vector2(uv.X + size.Z + size.X * mirror, uv.Y)); yield return new TextureVertex(new Vector3(1f, 0f, 1f), new Vector2(uv.X + size.Z + size.X * (1 - mirror), uv.Y)); yield return new TextureVertex(new Vector3(1f, 0f, 0f), new Vector2(uv.X + size.Z + size.X * (1 - mirror), uv.Y + size.Z)); // Bottom yield return new TextureVertex(new Vector3(1f, 1f, 0f), new Vector2(uv.X + size.Z + size.X + size.X * (1 - mirror), uv.Y + (_cube.FlipZMapping ? size.Z : 0))); yield return new TextureVertex(new Vector3(1f, 1f, 1f), new Vector2(uv.X + size.Z + size.X + size.X * (1 - mirror), uv.Y + (!_cube.FlipZMapping ? size.Z : 0))); yield return new TextureVertex(new Vector3(0f, 1f, 1f), new Vector2(uv.X + size.Z + size.X + size.X * mirror, uv.Y + (!_cube.FlipZMapping ? size.Z : 0))); yield return new TextureVertex(new Vector3(0f, 1f, 0f), new Vector2(uv.X + size.Z + size.X + size.X * mirror, uv.Y + (_cube.FlipZMapping ? size.Z : 0))); // Left yield return new TextureVertex(new Vector3(_cube.MirrorTexture ? 0f : 1f, 0f, 0f), new Vector2(uv.X + size.X + size.Z, uv.Y + size.Z)); yield return new TextureVertex(new Vector3(_cube.MirrorTexture ? 0f : 1f, 1f, 0f), new Vector2(uv.X + size.X + size.Z, uv.Y + size.Z + size.Y)); yield return new TextureVertex(new Vector3(_cube.MirrorTexture ? 0f : 1f, 1f, 1f), new Vector2(uv.X + size.X + size.Z * 2, uv.Y + size.Z + size.Y)); yield return new TextureVertex(new Vector3(_cube.MirrorTexture ? 0f : 1f, 0f, 1f), new Vector2(uv.X + size.X + size.Z * 2, uv.Y + size.Z)); // Right yield return new TextureVertex(new Vector3(_cube.MirrorTexture ? 1f : 0f, 0f, 0f), new Vector2(uv.X + size.Z, uv.Y + size.Z)); yield return new TextureVertex(new Vector3(_cube.MirrorTexture ? 1f : 0f, 1f, 0f), new Vector2(uv.X + size.Z, uv.Y + size.Z + size.Y)); yield return new TextureVertex(new Vector3(_cube.MirrorTexture ? 1f : 0f, 1f, 1f), new Vector2(uv.X, uv.Y + size.Z + size.Y)); yield return new TextureVertex(new Vector3(_cube.MirrorTexture ? 1f : 0f, 0f, 1f), new Vector2(uv.X, uv.Y + size.Z)); yield break; } public override IEnumerable GetIndices() => IndicesData; } }