From 64930ce5148706db67cd6d068cfe65b5db9bb252 Mon Sep 17 00:00:00 2001 From: Michael Becker Date: Sat, 30 Nov 2019 05:03:38 -0500 Subject: [PATCH] preliminary implementation of MM3D UI plugin with model editor - doesn't always work though --- .../Editors/Model/ModelEditor.cs | 297 ++++++++++++++++++ .../Properties/AssemblyInfo.cs | 46 +++ ....Plugins.Multimedia3D.UserInterface.csproj | 75 +++++ CSharp/UniversalEditor.sln | 14 + 4 files changed, 432 insertions(+) create mode 100644 CSharp/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia3D.UserInterface/Editors/Model/ModelEditor.cs create mode 100644 CSharp/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia3D.UserInterface/Properties/AssemblyInfo.cs create mode 100644 CSharp/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia3D.UserInterface/UniversalEditor.Plugins.Multimedia3D.UserInterface.csproj diff --git a/CSharp/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia3D.UserInterface/Editors/Model/ModelEditor.cs b/CSharp/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia3D.UserInterface/Editors/Model/ModelEditor.cs new file mode 100644 index 00000000..c7767914 --- /dev/null +++ b/CSharp/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia3D.UserInterface/Editors/Model/ModelEditor.cs @@ -0,0 +1,297 @@ +// +// ModelEditor.cs +// +// Author: +// Mike Becker +// +// Copyright (c) 2019 Mike Becker +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +using System.Collections.Generic; +using MBS.Framework.Drawing; +using MBS.Framework.Rendering; +using MBS.Framework.UserInterface; +using MBS.Framework.UserInterface.Controls; +using MBS.Framework.UserInterface.Layouts; +using UniversalEditor.ObjectModels.Multimedia3D.Model; +using UniversalEditor.UserInterface; + +namespace UniversalEditor.Plugins.Multimedia3D.UserInterface.Editors.Model +{ + public class ModelEditor : Editor + { + private static EditorReference _er = null; + public override EditorReference MakeReference() + { + if (_er == null) + { + _er = base.MakeReference(); + _er.SupportedObjectModels.Add(typeof(ModelObjectModel)); + } + return _er; + } + + public override void UpdateSelections() + { + throw new NotImplementedException(); + } + + protected override EditorSelection CreateSelectionInternal(object content) + { + throw new NotImplementedException(); + } + + private OpenGLCanvas gla = null; + + public ModelEditor() + { + this.Layout = new BoxLayout(Orientation.Vertical); + + gla = new OpenGLCanvas(); + gla.Realize += gla_Realize; + gla.Render += gla_Render; + this.Controls.Add(gla, new BoxLayout.Constraints(true, true)); + } + + private ShaderProgram p = null; + + [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)] + private struct VERTEX + { + public float PositionX; + public float PositionY; + public float PositionZ; + + public float NormalX; + public float NormalY; + public float NormalZ; + + public float ColorR; + public float ColorG; + public float ColorB; + + public float TextureU; + public float TextureV; + + public VERTEX(float x, float y, float z, float nx, float ny, float nz, float r, float g, float b, float u, float v) + { + PositionX = x; + PositionY = y; + PositionZ = z; + NormalX = nx; + NormalY = ny; + NormalZ = nz; + ColorR = r; + ColorG = g; + ColorB = b; + TextureU = u; + TextureV = v; + } + } + + private static VERTEX[] vertex_data = new VERTEX[] + { + // x , y , z nx, ny, nz , r, g , b , u, v + new VERTEX(0.0f, 0.500f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f), + new VERTEX(0.5f, -0.366f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f), + new VERTEX(-0.5f, -0.366f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f) + }; + + VertexArray[] vaos = null; + + /// + /// Computes the modelview projection + /// + /// the matrix to update. + /// Angle X axis (phi). + /// Angle Y axis (theta). + /// Angle Z axis (psi). + static void compute_mvp(ref float[] matrix, + float angleX, + float angleY, + float angleZ) + { + // holy balls + float x = (float)(angleX * (Math.PI / 180.0f)); + float y = (float)(angleY * (Math.PI / 180.0f)); + float z = (float)(angleZ * (Math.PI / 180.0f)); + float c1 = (float)Math.Cos(x), s1 = (float)Math.Sin(x); + float c2 = (float)Math.Cos(y), s2 = (float)Math.Sin(y); + float c3 = (float)Math.Cos(z), s3 = (float)Math.Sin(z); + float c3c2 = c3 * c2; + float s3c1 = s3 * c1; + float c3s2s1 = c3 * s2 * s1; + float s3s1 = s3 * s1; + float c3s2c1 = c3 * s2 * c1; + float s3c2 = s3 * c2; + float c3c1 = c3 * c1; + float s3s2s1 = s3 * s2 * s1; + float c3s1 = c3 * s1; + float s3s2c1 = s3 * s2 * c1; + float c2s1 = c2 * s1; + float c2c1 = c2 * c1; + + /* apply all three Euler angles rotations using the three matrices: + * + * ⎡ c3 s3 0 ⎤ ⎡ c2 0 -s2 ⎤ ⎡ 1 0 0 ⎤ + * ⎢ -s3 c3 0 ⎥ ⎢ 0 1 0 ⎥ ⎢ 0 c1 s1 ⎥ + * ⎣ 0 0 1 ⎦ ⎣ s2 0 c2 ⎦ ⎣ 0 -s1 c1 ⎦ + */ + matrix[0] = c3c2; matrix[4] = s3c1 + c3s2s1; matrix[8] = s3s1 - c3s2c1; matrix[12] = 0.0f; + matrix[1] = -s3c2; matrix[5] = c3c1 - s3s2s1; matrix[9] = c3s1 + s3s2c1; matrix[13] = 0.0f; + matrix[2] = s2; matrix[6] = -c2s1; matrix[10] = c2c1; matrix[14] = 0.0f; + matrix[3] = 0.0f; matrix[7] = 0.0f; matrix[11] = 0.0f; matrix[15] = 1.0f; + } + + void gla_Realize(object sender, EventArgs e) + { + mvp = new float[16]; + mvp[0] = 1.0f; mvp[4] = 0.0f; mvp[8] = 0.0f; mvp[12] = 0.0f; + mvp[1] = 0.0f; mvp[5] = 1.0f; mvp[9] = 0.0f; mvp[13] = 0.0f; + mvp[2] = 0.0f; mvp[6] = 0.0f; mvp[10] = 1.0f; mvp[14] = 0.0f; + mvp[3] = 0.0f; mvp[7] = 0.0f; mvp[11] = 0.0f; mvp[15] = 1.0f; + + compute_mvp(ref mvp, 0.0f, 0.0f, 0.0f); + } + + float[] mvp = null; + + void gla_Render(object sender, OpenGLCanvasRenderEventArgs e) + { + e.Canvas.Clear(Colors.Gray); + + if (p == null) + { + p = gla.Engine.CreateShaderProgram(); + Shader vtx = gla.Engine.CreateShaderFromString(ShaderType.Vertex, "#version 150\n\nin vec3 position;\nin vec3 normal;\nin vec3 color;\n\nuniform mat4 mvp;\n\nsmooth out vec4 vertexColor;\n\nvoid main() {\n gl_Position = mvp * vec4(position, 1.0);\n vertexColor = vec4(color, 1.0);\n}"); + vtx.Compile(); + + Shader frg = gla.Engine.CreateShaderFromString(ShaderType.Fragment, "#version 150\n\nsmooth in vec4 vertexColor;\n\nout vec4 outputColor;\n\nvoid main() {\n outputColor = vertexColor;\n}"); + frg.Compile(); + + p.Shaders.Add(vtx); + p.Shaders.Add(frg); + p.Link(); + } + e.Canvas.Program = p; + + /* update the "mvp" matrix we use in the shader */ + p.SetUniformMatrix("mvp", 1, false, mvp); + + /* use the buffers in the VAO */ + if (vaos != null) + { + vaos[0].Bind(); + + /* draw the three vertices as a triangle */ + e.Canvas.DrawArrays(RenderMode.Triangles, 0, vertex_data.Length); + } + + if (changed) + { + ModelObjectModel model = (ObjectModel as ModelObjectModel); + if (model == null) + return; + + if (model.Surfaces.Count > 0) + { + List list = new List(); + for (int i = 0; i < model.Materials.Count; i++) + { + for (int j = 0; j < model.Materials[i].Triangles.Count; j += 3) + { + VERTEX v1 = new VERTEX(), v2 = new VERTEX(), v3 = new VERTEX(); + v1.PositionX = (float)model.Materials[i].Triangles[j].Vertex1.Position.X; + v1.PositionY = (float)model.Materials[i].Triangles[j].Vertex1.Position.Y; + v1.PositionZ = (float)model.Materials[i].Triangles[j].Vertex1.Position.Z; + + v1.NormalX = (float)model.Materials[i].Triangles[j].Vertex1.Normal.X; + v1.NormalY = (float)model.Materials[i].Triangles[j].Vertex1.Normal.Y; + v1.NormalZ = (float)model.Materials[i].Triangles[j].Vertex1.Normal.Z; + + v1.TextureU = (float)model.Materials[i].Triangles[j].Vertex1.Texture.U; + v1.TextureV = (float)model.Materials[i].Triangles[j].Vertex1.Texture.V; + + v2.PositionX = (float)model.Materials[i].Triangles[j].Vertex2.Position.X; + v2.PositionY = (float)model.Materials[i].Triangles[j].Vertex2.Position.Y; + v2.PositionZ = (float)model.Materials[i].Triangles[j].Vertex2.Position.Z; + + v2.NormalX = (float)model.Materials[i].Triangles[j].Vertex2.Normal.X; + v2.NormalY = (float)model.Materials[i].Triangles[j].Vertex2.Normal.Y; + v2.NormalZ = (float)model.Materials[i].Triangles[j].Vertex2.Normal.Z; + + v2.TextureU = (float)model.Materials[i].Triangles[j].Vertex2.Texture.U; + v2.TextureV = (float)model.Materials[i].Triangles[j].Vertex2.Texture.V; + + v3.PositionX = (float)model.Materials[i].Triangles[j].Vertex3.Position.X; + v3.PositionY = (float)model.Materials[i].Triangles[j].Vertex3.Position.Y; + v3.PositionZ = (float)model.Materials[i].Triangles[j].Vertex3.Position.Z; + + v3.NormalX = (float)model.Materials[i].Triangles[j].Vertex3.Normal.X; + v3.NormalY = (float)model.Materials[i].Triangles[j].Vertex3.Normal.Y; + v3.NormalZ = (float)model.Materials[i].Triangles[j].Vertex3.Normal.Z; + + v3.TextureU = (float)model.Materials[i].Triangles[j].Vertex3.Texture.U; + v3.TextureV = (float)model.Materials[i].Triangles[j].Vertex3.Texture.V; + + list.AddRange(new VERTEX[] { v1, v2, v3 }); + } + } + vertex_data = list.ToArray(); + } + + // we need to create a VAO to store the other buffers + vaos = gla.Engine.CreateVertexArray(1); + + // this is the VBO that holds the vertex data + using (RenderBuffer buffer = gla.Engine.CreateBuffer()) + { + vaos[0].Bind(); + + buffer.Bind(BufferTarget.ArrayBuffer); + buffer.SetData(vertex_data, BufferDataUsage.StaticDraw); + + // enable and set the position attribute + buffer.SetVertexAttribute(p.GetAttributeLocation("position"), 3, ElementType.Float, false, 11 * 4, 0); + + // enable and set the normal attribute + // buffer.SetVertexAttribute(p.GetAttributeLocation("normal"), 3, ElementType.Float, false, 11 * 4, 3 * 4); + + // enable and set the color attribute + buffer.SetVertexAttribute(p.GetAttributeLocation("color"), 3, ElementType.Float, false, 11 * 4, 6 * 4); + + // reset the state; we will re-enable the VAO when needed + buffer.Unbind(); + + vaos[0].Unbind(); // must be called BEFORE the buffer gets disposed + } + changed = false; + } + + // we finished using the buffers and program + // e.Canvas.Engine.BindVertexArray(0); + // e.Canvas.Program = null; + } + + bool changed = false; + protected override void OnObjectModelChanged(EventArgs e) + { + base.OnObjectModelChanged(e); + + changed = true; + Refresh(); + } + } +} diff --git a/CSharp/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia3D.UserInterface/Properties/AssemblyInfo.cs b/CSharp/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia3D.UserInterface/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..330bc1b8 --- /dev/null +++ b/CSharp/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia3D.UserInterface/Properties/AssemblyInfo.cs @@ -0,0 +1,46 @@ +// +// AssemblyInfo.cs +// +// Author: +// Mike Becker +// +// Copyright (c) 2019 Mike Becker +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle("UniversalEditor.Plugins.Multimedia3D.UserInterface")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("Mike Becker")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly: AssemblyVersion("1.0.*")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] diff --git a/CSharp/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia3D.UserInterface/UniversalEditor.Plugins.Multimedia3D.UserInterface.csproj b/CSharp/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia3D.UserInterface/UniversalEditor.Plugins.Multimedia3D.UserInterface.csproj new file mode 100644 index 00000000..2dac74a7 --- /dev/null +++ b/CSharp/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia3D.UserInterface/UniversalEditor.Plugins.Multimedia3D.UserInterface.csproj @@ -0,0 +1,75 @@ + + + + Debug + AnyCPU + {D18D3E15-6913-4A91-A412-5B1E9BF92487} + Library + UniversalEditor.Plugins.Multimedia3D.UserInterface + UniversalEditor.Plugins.Multimedia3D.UserInterface + v4.7 + + + true + full + false + ..\..\Output\Debug\Plugins + DEBUG; + prompt + 4 + false + + + true + ..\..\Output\Release\Plugins + prompt + 4 + false + + + + + + + + + + + {00266B21-35C9-4A7F-A6BA-D54D7FDCC25C} + MBS.Framework + + + {2A0B4A53-8A3A-478D-80A7-B6FF20B38317} + MBS.Framework.Rendering + + + {29E1C1BB-3EA5-4062-B62F-85EEC703FE07} + MBS.Framework.UserInterface + + + {8622EBC4-8E20-476E-B284-33D472081F5C} + UniversalEditor.UserInterface + + + {4FD9DB1D-76AA-48D1-8446-95376C4A2BC2} + UniversalEditor.Plugins.Multimedia3D + + + {BE4D0BA3-0888-42A5-9C09-FC308A4509D2} + UniversalEditor.Plugins.Multimedia + + + {2D4737E6-6D95-408A-90DB-8DFF38147E85} + UniversalEditor.Core + + + {30467E5C-05BC-4856-AADC-13906EF4CADD} + UniversalEditor.Essential + + + + + + + + \ No newline at end of file diff --git a/CSharp/UniversalEditor.sln b/CSharp/UniversalEditor.sln index 367dbef5..58d440a3 100644 --- a/CSharp/UniversalEditor.sln +++ b/CSharp/UniversalEditor.sln @@ -151,6 +151,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UniversalEditor.Plugins.CRI EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UniversalEditor.Plugins.Sony", "Plugins\UniversalEditor.Plugins.Sony\UniversalEditor.Plugins.Sony.csproj", "{F9854149-5685-4F35-A698-C68F30AAF1B0}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MBS.Framework.Rendering", "..\..\MBS.Framework.Rendering\Libraries\MBS.Framework.Rendering\MBS.Framework.Rendering.csproj", "{2A0B4A53-8A3A-478D-80A7-B6FF20B38317}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UniversalEditor.Plugins.Multimedia3D.UserInterface", "Plugins.UserInterface\UniversalEditor.Plugins.Multimedia3D.UserInterface\UniversalEditor.Plugins.Multimedia3D.UserInterface.csproj", "{D18D3E15-6913-4A91-A412-5B1E9BF92487}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -435,6 +439,14 @@ Global {F9854149-5685-4F35-A698-C68F30AAF1B0}.Debug|Any CPU.Build.0 = Debug|Any CPU {F9854149-5685-4F35-A698-C68F30AAF1B0}.Release|Any CPU.ActiveCfg = Release|Any CPU {F9854149-5685-4F35-A698-C68F30AAF1B0}.Release|Any CPU.Build.0 = Release|Any CPU + {2A0B4A53-8A3A-478D-80A7-B6FF20B38317}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2A0B4A53-8A3A-478D-80A7-B6FF20B38317}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2A0B4A53-8A3A-478D-80A7-B6FF20B38317}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2A0B4A53-8A3A-478D-80A7-B6FF20B38317}.Release|Any CPU.Build.0 = Release|Any CPU + {D18D3E15-6913-4A91-A412-5B1E9BF92487}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D18D3E15-6913-4A91-A412-5B1E9BF92487}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D18D3E15-6913-4A91-A412-5B1E9BF92487}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D18D3E15-6913-4A91-A412-5B1E9BF92487}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {6F0AB1AF-E1A1-4D19-B19C-05BBB15C94B2} = {05D15661-E684-4EC9-8FBD-C014BA433CC5} @@ -505,6 +517,8 @@ Global {DBA93D1B-01BC-4218-8309-85FA0D5402FC} = {2ED32D16-6C06-4450-909A-40D32DA67FB4} {83709A63-8C43-4C67-80F6-00022986A086} = {7B535D74-5496-4802-B809-89ED88274A91} {F9854149-5685-4F35-A698-C68F30AAF1B0} = {2ED32D16-6C06-4450-909A-40D32DA67FB4} + {2A0B4A53-8A3A-478D-80A7-B6FF20B38317} = {20F315E0-52AE-479F-AF43-3402482C1FC8} + {D18D3E15-6913-4A91-A412-5B1E9BF92487} = {7B535D74-5496-4802-B809-89ED88274A91} EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution Policies = $0