| 1669 | } |
| 1670 | |
| 1671 | static void solvePositions(Vector3* vertex_positions, size_t vertex_count, const Quadric* vertex_quadrics, const QuadricGrad* volume_gradients, const Quadric* attribute_quadrics, const QuadricGrad* attribute_gradients, size_t attribute_count, const unsigned int* remap, const unsigned int* wedge, const EdgeAdjacency& adjacency, const unsigned char* vertex_kind, const unsigned char* vertex_update) |
| 1672 | { |
| 1673 | #if TRACE |
| 1674 | size_t stats[6] = {}; |
| 1675 | #endif |
| 1676 | |
| 1677 | for (size_t i = 0; i < vertex_count; ++i) |
| 1678 | { |
| 1679 | if (!vertex_update[i]) |
| 1680 | continue; |
| 1681 | |
| 1682 | // moving vertices on an attribute discontinuity may result in extrapolating UV outside of the chart bounds |
| 1683 | // moving vertices on a border requires a stronger edge quadric to preserve the border geometry |
| 1684 | if (vertex_kind[i] == Kind_Locked || vertex_kind[i] == Kind_Seam || vertex_kind[i] == Kind_Border) |
| 1685 | continue; |
| 1686 | |
| 1687 | if (remap[i] != i) |
| 1688 | { |
| 1689 | vertex_positions[i] = vertex_positions[remap[i]]; |
| 1690 | continue; |
| 1691 | } |
| 1692 | |
| 1693 | TRACESTATS(0); |
| 1694 | |
| 1695 | const Vector3& vp = vertex_positions[i]; |
| 1696 | |
| 1697 | Quadric Q = vertex_quadrics[i]; |
| 1698 | QuadricGrad GV = {}; |
| 1699 | |
| 1700 | // add a point quadric for regularization to stabilize the solution |
| 1701 | Quadric R; |
| 1702 | quadricFromPoint(R, vp.x, vp.y, vp.z, Q.w * 1e-4f); |
| 1703 | quadricAdd(Q, R); |
| 1704 | |
| 1705 | if (attribute_count) |
| 1706 | { |
| 1707 | // optimal point simultaneously minimizes attribute quadrics for all wedges |
| 1708 | unsigned int v = unsigned(i); |
| 1709 | do |
| 1710 | { |
| 1711 | quadricReduceAttributes(Q, attribute_quadrics[v], &attribute_gradients[v * attribute_count], attribute_count); |
| 1712 | v = wedge[v]; |
| 1713 | } while (v != i); |
| 1714 | |
| 1715 | // minimizing attribute quadrics results in volume loss so we incorporate volume gradient as a constraint |
| 1716 | if (volume_gradients) |
| 1717 | GV = volume_gradients[i]; |
| 1718 | } |
| 1719 | |
| 1720 | Vector3 p; |
| 1721 | if (!quadricSolve(p, Q, GV)) |
| 1722 | { |
| 1723 | TRACESTATS(2); |
| 1724 | continue; |
| 1725 | } |
| 1726 | |
| 1727 | // reject updates that move the vertex too far from its neighborhood |
| 1728 | // this detects and fixes most cases when the quadric is not well-defined |
no test coverage detected