Example #1
0
        public MeshPrimitiveReader(MeshPrimitive srcPrim, bool doubleSided, MeshNormalsFallback fallbackNormals)
        {
            _Positions = srcPrim.GetVertexAccessor("POSITION")?.AsVector3Array();
            _Normals   = srcPrim.GetVertexAccessor("NORMAL")?.AsVector3Array();

            if (_Normals == null)
            {
                _Normals = new XYZ[_Positions.Count];

                for (int i = 0; i < _Normals.Count; ++i)
                {
                    _Normals[i] = fallbackNormals.GetNormal(_Positions[i]);
                }
            }

            _Color0    = srcPrim.GetVertexAccessor("COLOR_0")?.AsColorArray();
            _TexCoord0 = srcPrim.GetVertexAccessor("TEXCOORD_0")?.AsVector2Array();

            _Joints0  = srcPrim.GetVertexAccessor("JOINTS_0")?.AsVector4Array();
            _Joints1  = srcPrim.GetVertexAccessor("JOINTS_1")?.AsVector4Array();
            _Weights0 = srcPrim.GetVertexAccessor("WEIGHTS_0")?.AsVector4Array();
            _Weights1 = srcPrim.GetVertexAccessor("WEIGHTS_1")?.AsVector4Array();

            if (_Joints0 == null || _Weights0 == null)
            {
                _Joints0 = _Joints1 = _Weights0 = _Weights1 = null;
            }
            if (_Joints1 == null || _Weights1 == null)
            {
                _Joints1 = _Weights1 = null;
            }

            if (_Weights0 != null)
            {
                _Weights0 = _Weights0.ToArray(); // isolate memory to prevent overwriting source glTF.

                for (int i = 0; i < _Weights0.Count; ++i)
                {
                    var r = XYZW.Dot(_Weights0[i], XYZW.One);
                    _Weights0[i] /= r;
                }
            }

            if (doubleSided) // Monogame's effect material does not support double sided materials, so we simulate it by adding reverse faces
            {
                var front = srcPrim.GetTriangleIndices();
                var back  = front.Select(item => (item.A, item.C, item.B));
                _Triangles = front.Concat(back).ToArray();
            }
            else
            {
                _Triangles = srcPrim.GetTriangleIndices().ToArray();
            }
        }
Example #2
0
        private float SolveLeastSquares(out Vec4 start, out Vec4 end)
        {
            // accumulate all the quantities we need
            int count = m_colours.Count;

            float alpha2_sum    = 0;
            float beta2_sum     = 0;
            float alphabeta_sum = 0;

            var alphax_sum = Vec4.Zero;
            var betax_sum  = Vec4.Zero;

            for (int i = 0; i < count; ++i)
            {
                var alpha = m_alpha[i];
                var beta  = m_beta[i];
                var x     = m_weighted[i];

                alpha2_sum    += alpha * alpha;
                beta2_sum     += beta * beta;
                alphabeta_sum += alpha * beta;
                alphax_sum    += alpha * x;
                betax_sum     += beta * x;
            }

            // zero where non-determinate
            Vec4 a, b;

            if (beta2_sum == 0)
            {
                a = alphax_sum / alpha2_sum;
                b = Vec4.Zero;
            }
            else if (alpha2_sum == 0)
            {
                a = Vec4.Zero;
                b = betax_sum / beta2_sum;
            }
            else
            {
                var factor = 1.0f / (alpha2_sum * beta2_sum - alphabeta_sum * alphabeta_sum);

                a = (alphax_sum * beta2_sum - betax_sum * alphabeta_sum) * factor;
                b = (betax_sum * alpha2_sum - alphax_sum * alphabeta_sum) * factor;
            }

            // clamp the output to [0, 1]
            a = a.Clamp(Vec4.Zero, Vec4.One);
            b = b.Clamp(Vec4.Zero, Vec4.One);

            // clamp to the grid
            a = GRID.MultiplyAdd(a, HALF).Truncate() * GRIDRCP;
            b = GRID.MultiplyAdd(b, HALF).Truncate() * GRIDRCP;

            // compute the error
            var e1 = a * a * alpha2_sum + b * b * beta2_sum /*+ m_xxsum*/
                     + 2 * (a * b * alphabeta_sum - a * alphax_sum - b * betax_sum);

            // apply the metric to the error term
            float error = Vec4.Dot(e1, m_metricSqr);

            // save the start and end
            start = a;
            end   = b;
            return(error);
        }