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(); } }
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); }