EvergineTeam / Feedback

Feedback, feature requests, and bug reports for Evergine.
https://evergine.com
14 stars 1 forks source link

Cargar modelos grandes en tiempo de ejecucion #67

Closed zaidorx closed 2 years ago

zaidorx commented 3 years ago

Hola, estoy tratando de crear una aplicacion que carga varios modelos en tiempo de ejecucion. Logre cargar varios modelos pequeños, pero cuando trato de cargar modelos mas grandes, me da una excepcion de tipo ArgumentOutOfRangeException. Despues de un poco de investigacion, me encontre que hay un limite en el codigo de 65535 indices. El modelo es un stl que ya esta cargado en memoria usando la libreria geometry3sharp y esta es la parte del codigo que uso para mapearlo a waveengine: ......... var v1 = new Vector3d(); var v2 = new Vector3d(); var v3 = new Vector3d(); var geometric = new LargeModel(); var triangleIndexCount = 0; foreach (var i in mesh.TriangleIndices()) { triangleIndexCount++; if (triangleIndexCount > 10500) { geometrics.Add(geometric); geometric = new LargeModel(); triangleIndexCount = 0; }
mesh.GetTriVertices(i, ref v1, ref v2, ref v3); geometric.AddNewIndex(geometric.VertexCount); geometric.AddNewIndex(geometric.VertexCount + 1); geometric.AddNewIndex(geometric.VertexCount + 2); var vertex = new Vector3((float)v1.x, (float)v1.y, (float)v1.z); var n = mesh.GetTriNormal(i); var normal = new Vector3((float)n.x, (float)n.y, (float)n.z); normal.Normalize(); geometric.AddNewVertex(vertex, normal); vertex = new Vector3((float)v2.x, (float)v2.y, (float)v2.z); geometric.AddNewVertex(vertex, normal); vertex = new Vector3((float)v3.x, (float)v3.y, (float)v3.z); geometric.AddNewVertex(vertex, normal); } Model = new Model(modelMeshName, geometrics[0].CreateMesh()); if (geometrics.Count > 1) { for (int i = 1; i < geometrics.Count; i++) { Model.MeshContainers[0].Meshes.Add(geometrics[i].CreateMesh()); } Model.RefreshBoundingBox(); } ............ El modelo se logra cargar pero no se muestra correctamente.

Es esta forma de hacerlo la correcta? De ser asi, que me esta faltando? Podrian proveer algun ejemplo de la forma correcta de hacerlo? Muchas gracias de antemano.

emepetres commented 2 years ago

@zaidorx thank you for your report and sorry for the late response, we'll check whenever possible. If you need a quick resolution, please contact our priority support.

Jorgemagic commented 2 years ago

Hola Zaidorx,

Cuando creas un Mesh a través de un vertexbuffer y un indexbuffer tu puedes elegir si el index buffer es de 16 bits o 32 bits. Por defecto es de 16 bits lo cual usa un ushort para almacenar los indices. ushort.MaxValue es igual 65535. Creo que ese es el límite que te está saliendo en tu ejemplo. Por lo tanto te diría que para poder crear meshes más grandes deberías usar 32 bits para el index buffer algo que se especifica en la propia creación del index buffer:

public IndexBuffer(Buffer buffer, IndexFormat indexFormat = IndexFormat.UInt16, int offset = 0, int size = -1, bool flipWinding = false, IntPtr data = default(IntPtr))

Te dejo un componente que crea multiples meshes para que puedas tenerlo de referencia.

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using WaveEngine.Common.Attributes;
using WaveEngine.Common.Graphics;
using WaveEngine.Common.Graphics.VertexFormats;
using WaveEngine.Components.Graphics3D;
using WaveEngine.Framework;
using WaveEngine.Framework.Graphics;
using WaveEngine.Mathematics;
using Buffer = WaveEngine.Common.Graphics.Buffer;

namespace CreateMesh.Components
{
    public class MultipleMeshes : MeshComponent
    {
        [BindService]
        private GraphicsContext graphicsContext = null;

        VertexPositionColor[] vertexData1 = new VertexPositionColor[]
        {
            new VertexPositionColor(new Vector3(-1.5f, 0.5f, 0.0f), Color.Blue),
            new VertexPositionColor(new Vector3(-0.5f, 0.5f, 0.0f), Color.Blue),
            new VertexPositionColor(new Vector3(-0.5f, -0.5f, 0.0f), Color.Blue),
            new VertexPositionColor(new Vector3(-1.5f, -0.5f, 0.0f), Color.Blue),
        };

        VertexPositionColor[] vertexData2 = new VertexPositionColor[]
        {
            new VertexPositionColor(new Vector3(0.5f, 0.5f, 0.0f), Color.Red),
            new VertexPositionColor(new Vector3(1.5f, 0.5f, 0.0f), Color.Red),
            new VertexPositionColor(new Vector3(1.5f, -0.5f, 0.0f), Color.Red),
            new VertexPositionColor(new Vector3(0.5f, -0.5f, 0.0f), Color.Red),
        };

        ushort[] indexData = new ushort[] { 0, 1, 2, 0, 2, 3 };

        /// <summary>
        /// Gets the model data.
        /// </summary>
        [DontRenderProperty]
        public new Model Model
        {
            get => this.modelLink.Value;

            private set
            {
                this.modelLink.Value = value;

                this.ThrowRefreshEvent();
            }
        }

        /// <summary>
        /// Gets the mesh name to render.
        /// </summary>
        [DontRenderProperty]
        public new string ModelMeshName => this.modelMeshName;

        public MultipleMeshes()
        {
        }

        protected override bool OnAttached()
        {
            var ok = base.OnAttached();

            // Create two meshes
            var mesh1 = this.CreateMesh(this.graphicsContext, this.vertexData1, this.indexData);
            var mesh2 = this.CreateMesh(this.graphicsContext, this.vertexData2, this.indexData);

            // Create MeshContainer
            var meshContainer = new MeshContainer()
            {
                Name = "MultiplesMeshes",
                Meshes = new List<Mesh>() { mesh1, mesh2 }
            };

            // Create RootNode
            var rootNode = new NodeContent()
            {
                Name = "MultiplesMeshes",
                Mesh = meshContainer,
                Children = new NodeContent[0],
                ChildIndices = new int[0],
            };

            // Create material List
            var materialCollection = new List<(string, System.Guid)>()
            {
                ("Default", Guid.Empty),
            };

            this.Model = new Model()
            {
                MeshContainers = new[] { meshContainer },
                Materials = materialCollection,
                AllNodes = new[] { rootNode },
                RootNodes = new[] { 0 },
            };            

            this.Model.RefreshBoundingBox();

            return ok;
        }

        private Mesh CreateMesh(GraphicsContext graphicsContext, VertexPositionColor[] vertexData, ushort[] indexData)
        {
            // Vertex Buffer
            var vBufferDescription = new BufferDescription((uint)Unsafe.SizeOf<VertexPositionColor>() * (uint)vertexData.Length,
                                                                BufferFlags.ShaderResource | BufferFlags.VertexBuffer,
                                                                ResourceUsage.Default);
            Buffer vBuffer = graphicsContext.Factory.CreateBuffer(vertexData, ref vBufferDescription);
            VertexBuffer vertexBuffer = new VertexBuffer(vBuffer, VertexPositionColor.VertexFormat);

            // Index Buffer
            var iBufferDescription = new BufferDescription((uint)(sizeof(ushort) * indexData.Length), BufferFlags.IndexBuffer, ResourceUsage.Default);
            Buffer iBuffer = graphicsContext.Factory.CreateBuffer(this.indexData, ref iBufferDescription);
            var indexBuffer = new IndexBuffer(iBuffer, IndexFormat.UInt32);

            // Create Mesh
            return new Mesh(new VertexBuffer[] { vertexBuffer }, indexBuffer, PrimitiveTopology.TriangleList)
            {
                BoundingBox = this.ComputeBoundingBox(vertexData),
            };
        }

        private BoundingBox ComputeBoundingBox(VertexPositionColor[] vertexData)
        {
            var min = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
            var max = new Vector3(float.MinValue, float.MinValue, float.MinValue);

            Vector3 currentVertex;
            for (int i = 0; i < vertexData.Length; i++)
            {
                currentVertex = vertexData[i].Position;
                Vector3.Max(ref currentVertex, ref max, out max);
                Vector3.Min(ref currentVertex, ref min, out min);
            }

            return new BoundingBox(min, max);
        }
    }
}

Espero que ayude. Saludos Jorge