Exemple #1
0
        internal bool Approx(InteropVector2 v)
        {
            var epsilon = 1e-6f;

            return(Math.Abs(x - v.x) < epsilon &&
                   Math.Abs(y - v.y) < epsilon);
        }
Exemple #2
0
        /// <summary>
        /// Copy all mesh data - aligned to loops (thus no combination of like-vertices)
        /// </summary>
        internal void CopyMeshDataAlignedtoLoops(
            MVert[] verts,
            MLoop[] loops,
            MLoopTri[] loopTris,
            MLoopCol[] loopCols,
            List <MLoopUV[]> loopUVs
            )
        {
            #if LEGACY
            Reallocate(loops.Length, loopTris.Length, loopUVs.Count, loopCols != null);

            // Normals need to be cast from short -> float from Blender
            var normalScale = 1f / 32767f;

            for (int i = 0; i < loops.Length; i++)
            {
                var co = verts[loops[i].v].co;
                var no = verts[loops[i].v].no;

                _vertices[i] = new InteropVector3(co[0], co[1], co[2]);
                _normals[i]  = new InteropVector3(
                    no[0] * normalScale,
                    no[1] * normalScale,
                    no[2] * normalScale
                    );

                // Copy UV layers - same length as loops
                for (int layer = 0; layer < loopUVs.Count; layer++)
                {
                    _uvs[layer][i] = new InteropVector2(
                        loopUVs[layer][i].uv
                        );
                }

                // Copy vertex colors - same length as loops
                if (loopCols != null)
                {
                    var col = loopCols[i];
                    _colors[i] = new InteropColor32(
                        col.r,
                        col.g,
                        col.b,
                        col.a
                        );
                }
            }

            // Copy triangles
            for (uint t = 0; t < loopTris.Length; t++)
            {
                for (uint i = 0; i < 3; i++)
                {
                    _triangles[(t * 3) + i] = loopTris[t].tri[i];
                }
            }
            #endif
        }
Exemple #3
0
        /// <summary>
        /// Copy all mesh data from Blender in one go and optimize down as much as possible.
        /// </summary>
        /// <remarks>
        ///     Reference: LuxCoreRender/LuxCore::Scene_DefineBlenderMesh
        ///     for the logic dealing with split normals / UVs / etc.
        /// </remarks>
        /// <param name="verts"></param>
        /// <param name="loops"></param>
        /// <param name="loopTris"></param>
        /// <param name="loopUVs"></param>
        /// <param name="loopCols"></param>
        internal void CopyMeshData_V1(
            MVert[] verts,
            MLoop[] loops,
            MLoopTri[] loopTris,
            MLoopCol[] loopCols,
            List <MLoopUV[]> loopUVs
            )
        {
            #if LEGACY
            // In the case of split vertices - this'll resize DOWN
            // and then resize UP again for split vertices.

            Reallocate(verts.Length, loopTris.Length, loopUVs.Count, loopCols != null);

            var normalScale = 1f / 32767f;

            // Copy in vertex coordinates and normals
            for (int i = 0; i < verts.Length; i++)
            {
                var co = verts[i].co;
                var no = verts[i].no;

                _vertices[i] = new InteropVector3(co[0], co[1], co[2]);

                // Normals need to be cast from short -> float from Blender
                _normals[i] = new InteropVector3(
                    no[0] * normalScale,
                    no[1] * normalScale,
                    no[2] * normalScale
                    );
            }

            // Copy UV layers
            for (int layer = 0; layer < loopUVs.Count; layer++)
            {
                var uvLayer = _uvs[layer];
                for (uint i = 0; i < loopUVs[layer].Length; i++)
                {
                    var vertIndex = loops[i].v;

                    // This will overwrite itself for shared vertices - that's fine.
                    // We'll be handling split UVs when reading in triangle data.
                    uvLayer[vertIndex] = new InteropVector2(
                        loopUVs[layer][i].uv
                        );
                }
            }

            // Copy vertex colors if we got 'em
            if (loopCols != null)
            {
                for (uint i = 0; i < loopCols.Length; i++)
                {
                    var vertIndex = loops[i].v;
                    var col       = loopCols[i];
                    _colors[vertIndex] = new InteropColor32(
                        col.r,
                        col.g,
                        col.b,
                        col.a
                        );
                }
            }

            // Track what triangle vertices need to be split.
            // This maps an index in `triangles` to an index in `loops`
            var splitTris = new Dictionary <uint, uint>();

            // Generate triangle list while identifying any vertices that will need
            // to be split - due to having split UVs, normals, etc in the loop data.
            for (uint t = 0; t < loopTris.Length; t++)
            {
                for (uint i = 0; i < 3; i++)
                {
                    var loopIndex = loopTris[t].tri[i];
                    var vertIndex = loops[loopIndex].v;

                    var split = false; // Assumes .v is already < verts.Length

                    // TODO: Test differing normals - not applicable
                    // here as normals are only read in from MVert

                    // Determine if we should make a new vertex for split UVs
                    for (int layer = 0; layer < loopUVs.Count && !split; layer++)
                    {
                        var loopUV = loopUVs[layer][loopIndex].uv;
                        var vertUV = _uvs[layer][vertIndex];
                        // TODO: Handle floating point errors?
                        if (loopUV[0] != vertUV.x || loopUV[1] != vertUV.y)
                        {
                            split = true;
                        }
                    }

                    // If we have vertex colors, check for split colors
                    if (loopCols != null)
                    {
                        var col     = loopCols[loopIndex];
                        var vertCol = _colors[vertIndex];

                        if (col.r != vertCol.r ||
                            col.g != vertCol.g ||
                            col.b != vertCol.b ||
                            col.a != vertCol.a
                            )
                        {
                            split = true;
                        }
                    }

                    _triangles[(t * 3) + i] = vertIndex;

                    // Track if we need to split the vertex in the triangle
                    // to a new one once we've iterated through everything
                    if (split)
                    {
                        splitTris.Add((t * 3) + i, loopIndex);
                    }
                }
            }

            // 7958 + 32245 = 40203
            // LOOPS are 31488

            // 7958 * 3 = 23874
            // 15744 loop triangles
            // 31488 vertex color indices

            // If we have triangle verts to split - apply all at once so there's
            // only a single re-allocation to our arrays.
            var totalNewVertices = splitTris.Count;
            if (totalNewVertices > 0)
            {
                InteropLogger.Debug($"Splitting {totalNewVertices} vertices");
                var newVertIndex = (uint)verts.Length;

                // Reallocate everything to fit the new set of vertices
                Reallocate(verts.Length + totalNewVertices, loopTris.Length, loopUVs.Count, loopCols != null);

                // Generate new vertices with any split data (normals, UVs, colors, etc)
                foreach (var tri in splitTris.Keys)
                {
                    var prevVertIndex = _triangles[tri]; // MVert index
                    var loopIndex     = splitTris[tri];  // MLoop index

                    // Same coordinates as the original vertex
                    _vertices[newVertIndex] = _vertices[prevVertIndex];

                    // TODO: If there were split normals, that'd be handled here.
                    _normals[newVertIndex] = _normals[prevVertIndex];

                    // Read UVs from loops again to handle any split UVs
                    for (int layer = 0; layer < loopUVs.Count; layer++)
                    {
                        var uv = loopUVs[layer][loopIndex].uv;

                        _uvs[layer][newVertIndex] = new InteropVector2(uv);
                    }

                    // Same deal for vertex colors - copy from the loop
                    if (loopCols != null)
                    {
                        var col = loopCols[loopIndex];
                        _colors[newVertIndex] = new InteropColor32(
                            col.r,
                            col.g,
                            col.b,
                            col.a
                            );
                    }

                    // And finally update the triangle to point to the new vertex
                    _triangles[tri] = newVertIndex;
                    newVertIndex++;
                }
            }
            #endif
        }