Showing the changes to interface/src/MetavoxelSystem.cpp (1 of 2 files). Show all
Unified · Split
| @@ -964,6 +964,12 @@ void HeightfieldPreview::render(const glm::vec3& translation, float scale) const · 963 unmodified lines | ||
| 964 | 964 | Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false); |
| 965 | 965 | } |
| 966 | 966 | |
| 967 | +void VoxelPoint::setNormal(const glm::vec3& normal) { | |
| 968 | + this->normal[0] = (char)(normal.x * 127.0f); | |
| 969 | + this->normal[1] = (char)(normal.y * 127.0f); | |
| 970 | + this->normal[2] = (char)(normal.z * 127.0f); | |
| 971 | +} | |
| 972 | + | |
| 967 | 973 | VoxelBuffer::VoxelBuffer(const QVector<VoxelPoint>& vertices, const QVector<int>& indices, |
| 968 | 974 | const QVector<SharedObjectPointer>& materials) : |
| 969 | 975 | _vertices(vertices), |
| @@ -1535,6 +1541,14 @@ public: · 565 unmodified lines | ||
| 1535 | 1541 | glm::vec3 normal; |
| 1536 | 1542 | QRgb color; |
| 1537 | 1543 | char material; |
| 1544 | + int axis; | |
| 1545 | +}; | |
| 1546 | + | |
| 1547 | +class AxisIndex { | |
| 1548 | +public: | |
| 1549 | + int x, y, z; | |
| 1550 | + | |
| 1551 | + AxisIndex(int x = -1, int y = -1, int z = -1) : x(x), y(y), z(z) { } | |
| 1538 | 1552 | }; |
| 1539 | 1553 | |
| 1540 | 1554 | int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { |
| @@ -1575,10 +1589,10 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { · 34 unmodified lines | ||
| 1575 | 1589 | // as we scan down the cube generating vertices between grid points, we remember the indices of the last |
| 1576 | 1590 | // (element, line, section--x, y, z) so that we can connect generated vertices as quads |
| 1577 | 1591 | int expanded = size + 1; |
| 1578 | − QVector<int> lineIndices(expanded, -1); | |
| 1579 | − QVector<int> lastLineIndices(expanded, -1); | |
| 1580 | − QVector<int> planeIndices(expanded * expanded, -1); | |
| 1581 | − QVector<int> lastPlaneIndices(expanded * expanded, -1); | |
| 1592 | + QVector<AxisIndex> lineIndices(expanded); | |
| 1593 | + QVector<AxisIndex> lastLineIndices(expanded); | |
| 1594 | + QVector<AxisIndex> planeIndices(expanded * expanded); | |
| 1595 | + QVector<AxisIndex> lastPlaneIndices(expanded * expanded); | |
| 1582 | 1596 | |
| 1583 | 1597 | const int EDGES_PER_CUBE = 12; |
| 1584 | 1598 | EdgeCrossing crossings[EDGES_PER_CUBE]; |
| @@ -1589,7 +1603,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { · 4 unmodified lines | ||
| 1589 | 1603 | for (int z = 0; z < expanded; z++) { |
| 1590 | 1604 | const QRgb* colorY = colorZ; |
| 1591 | 1605 | for (int y = 0; y < expanded; y++) { |
| 1592 | − int lastIndex = 0; | |
| 1606 | + AxisIndex lastIndex; | |
| 1593 | 1607 | const QRgb* colorX = colorY; |
| 1594 | 1608 | for (int x = 0; x < expanded; x++) { |
| 1595 | 1609 | int alpha0 = colorX[0] >> ALPHA_OFFSET; |
| @@ -1663,6 +1677,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { · 67 unmodified lines | ||
| 1663 | 1677 | crossing.material = materialBase[0]; |
| 1664 | 1678 | } |
| 1665 | 1679 | crossing.point = glm::vec3(qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 0.0f, 0.0f); |
| 1680 | + crossing.axis = 0; | |
| 1666 | 1681 | } |
| 1667 | 1682 | if (middleY) { |
| 1668 | 1683 | if (alpha1 != alpha3) { |
| @@ -1677,6 +1692,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { · 8 unmodified lines | ||
| 1677 | 1692 | crossing.material = materialBase[1]; |
| 1678 | 1693 | } |
| 1679 | 1694 | crossing.point = glm::vec3(1.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 0.0f); |
| 1695 | + crossing.axis = 1; | |
| 1680 | 1696 | } |
| 1681 | 1697 | if (alpha2 != alpha3) { |
| 1682 | 1698 | QRgb hermite = hermiteBase[hermiteStride]; |
| @@ -1690,6 +1706,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { · 7 unmodified lines | ||
| 1690 | 1706 | crossing.material = materialBase[size]; |
| 1691 | 1707 | } |
| 1692 | 1708 | crossing.point = glm::vec3(qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 1.0f, 0.0f); |
| 1709 | + crossing.axis = 0; | |
| 1693 | 1710 | } |
| 1694 | 1711 | if (middleZ) { |
| 1695 | 1712 | if (alpha3 != alpha7) { |
| @@ -1704,6 +1721,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { · 8 unmodified lines | ||
| 1704 | 1721 | crossing.material = materialBase[offset3]; |
| 1705 | 1722 | } |
| 1706 | 1723 | crossing.point = glm::vec3(1.0f, 1.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL); |
| 1724 | + crossing.axis = 2; | |
| 1707 | 1725 | } |
| 1708 | 1726 | if (alpha5 != alpha7) { |
| 1709 | 1727 | QRgb hermite = hermiteBase[hermiteArea + VoxelHermiteData::EDGE_COUNT + 1]; |
| @@ -1717,6 +1735,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { · 7 unmodified lines | ||
| 1717 | 1735 | crossing.material = materialBase[offset5]; |
| 1718 | 1736 | } |
| 1719 | 1737 | crossing.point = glm::vec3(1.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 1.0f); |
| 1738 | + crossing.axis = 1; | |
| 1720 | 1739 | } |
| 1721 | 1740 | if (alpha6 != alpha7) { |
| 1722 | 1741 | QRgb hermite = hermiteBase[hermiteArea + hermiteStride]; |
| @@ -1730,6 +1749,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { · 7 unmodified lines | ||
| 1730 | 1749 | crossing.material = materialBase[offset6]; |
| 1731 | 1750 | } |
| 1732 | 1751 | crossing.point = glm::vec3(qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 1.0f, 1.0f); |
| 1752 | + crossing.axis = 0; | |
| 1733 | 1753 | } |
| 1734 | 1754 | } |
| 1735 | 1755 | } |
| @@ -1746,6 +1766,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { · 10 unmodified lines | ||
| 1746 | 1766 | crossing.material = materialBase[1]; |
| 1747 | 1767 | } |
| 1748 | 1768 | crossing.point = glm::vec3(1.0f, 0.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL); |
| 1769 | + crossing.axis = 2; | |
| 1749 | 1770 | } |
| 1750 | 1771 | if (alpha4 != alpha5) { |
| 1751 | 1772 | QRgb hermite = hermiteBase[hermiteArea]; |
| @@ -1759,6 +1780,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { · 7 unmodified lines | ||
| 1759 | 1780 | crossing.material = materialBase[area]; |
| 1760 | 1781 | } |
| 1761 | 1782 | crossing.point = glm::vec3(qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 0.0f, 1.0f); |
| 1783 | + crossing.axis = 0; | |
| 1762 | 1784 | } |
| 1763 | 1785 | } |
| 1764 | 1786 | } |
| @@ -1775,6 +1797,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { · 10 unmodified lines | ||
| 1775 | 1797 | crossing.material = materialBase[0]; |
| 1776 | 1798 | } |
| 1777 | 1799 | crossing.point = glm::vec3(0.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 0.0f); |
| 1800 | + crossing.axis = 1; | |
| 1778 | 1801 | } |
| 1779 | 1802 | if (middleZ) { |
| 1780 | 1803 | if (alpha2 != alpha6) { |
| @@ -1789,6 +1812,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { · 8 unmodified lines | ||
| 1789 | 1812 | crossing.material = materialBase[size]; |
| 1790 | 1813 | } |
| 1791 | 1814 | crossing.point = glm::vec3(0.0f, 1.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL); |
| 1815 | + crossing.axis = 2; | |
| 1792 | 1816 | } |
| 1793 | 1817 | if (alpha4 != alpha6) { |
| 1794 | 1818 | QRgb hermite = hermiteBase[hermiteArea + 1]; |
| @@ -1802,6 +1826,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { · 7 unmodified lines | ||
| 1802 | 1826 | crossing.material = materialBase[area]; |
| 1803 | 1827 | } |
| 1804 | 1828 | crossing.point = glm::vec3(0.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 1.0f); |
| 1829 | + crossing.axis = 1; | |
| 1805 | 1830 | } |
| 1806 | 1831 | } |
| 1807 | 1832 | } |
| @@ -1817,11 +1842,12 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { · 9 unmodified lines | ||
| 1817 | 1842 | crossing.material = materialBase[0]; |
| 1818 | 1843 | } |
| 1819 | 1844 | crossing.point = glm::vec3(0.0f, 0.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL); |
| 1845 | + crossing.axis = 2; | |
| 1820 | 1846 | } |
| 1821 | 1847 | // at present, we simply average the properties of each crossing as opposed to finding the vertex that |
| 1822 | 1848 | // minimizes the quadratic error function as described in the reference paper |
| 1823 | 1849 | glm::vec3 center; |
| 1824 | − glm::vec3 normal; | |
| 1850 | + glm::vec3 axisNormals[3]; | |
| 1825 | 1851 | const int MAX_MATERIALS_PER_VERTEX = 4; |
| 1826 | 1852 | quint8 materials[] = { 0, 0, 0, 0 }; |
| 1827 | 1853 | glm::vec4 materialWeights; |
| @@ -1830,7 +1856,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { · 2 unmodified lines | ||
| 1830 | 1856 | for (int i = 0; i < crossingCount; i++) { |
| 1831 | 1857 | const EdgeCrossing& crossing = crossings[i]; |
| 1832 | 1858 | center += crossing.point; |
| 1833 | − normal += crossing.normal; | |
| 1859 | + axisNormals[crossing.axis] += crossing.normal; | |
| 1834 | 1860 | red += qRed(crossing.color); |
| 1835 | 1861 | green += qGreen(crossing.color); |
| 1836 | 1862 | blue += qBlue(crossing.color); |
| @@ -1853,16 +1879,18 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { · 16 unmodified lines | ||
| 1853 | 1879 | } |
| 1854 | 1880 | } |
| 1855 | 1881 | } |
| 1856 | − normal = glm::normalize(normal); | |
| 1882 | + glm::vec3 normal = glm::normalize(axisNormals[0] + axisNormals[1] + axisNormals[2]); | |
| 1857 | 1883 | center /= crossingCount; |
| 1858 | 1884 | |
| 1859 | 1885 | // use a sequence of Givens rotations to perform a QR decomposition |
| 1860 | 1886 | // see http://www.cs.rice.edu/~jwarren/papers/techreport02408.pdf |
| 1861 | 1887 | glm::mat4 r(0.0f); |
| 1862 | 1888 | glm::vec4 bottom; |
| 1889 | + float smallestCosNormal = 1.0f; | |
| 1863 | 1890 | for (int i = 0; i < crossingCount; i++) { |
| 1864 | 1891 | const EdgeCrossing& crossing = crossings[i]; |
| 1865 | 1892 | bottom = glm::vec4(crossing.normal, glm::dot(crossing.normal, crossing.point - center)); |
| 1893 | + smallestCosNormal = qMin(smallestCosNormal, glm::dot(crossing.normal, normal)); | |
| 1866 | 1894 | |
| 1867 | 1895 | for (int j = 0; j < 4; j++) { |
| 1868 | 1896 | float angle = glm::atan(-bottom[j], r[j][j]); |
| @@ -1931,17 +1959,69 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { · 62 unmodified lines | ||
| 1931 | 1959 | { materials[0], materials[1], materials[2], materials[3] }, |
| 1932 | 1960 | { (quint8)materialWeights[0], (quint8)materialWeights[1], (quint8)materialWeights[2], |
| 1933 | 1961 | (quint8)materialWeights[3] } }; |
| 1934 | − int index = vertices.size(); | |
| 1935 | − vertices.append(point); | |
| 1962 | + | |
| 1963 | + // determine whether we must "crease" by generating directional normals | |
| 1964 | + const float CREASE_COS_NORMAL = glm::cos(glm::radians(40.0f)); | |
| 1965 | + AxisIndex index(vertices.size(), vertices.size(), vertices.size()); | |
| 1966 | + if (smallestCosNormal > CREASE_COS_NORMAL) { | |
| 1967 | + vertices.append(point); | |
| 1968 | + | |
| 1969 | + } else { | |
| 1970 | + axisNormals[0] = glm::normalize(axisNormals[0]); | |
| 1971 | + axisNormals[1] = glm::normalize(axisNormals[1]); | |
| 1972 | + axisNormals[2] = glm::normalize(axisNormals[2]); | |
| 1973 | + glm::vec3 normalXY(glm::normalize(axisNormals[0] + axisNormals[1])); | |
| 1974 | + glm::vec3 normalXZ(glm::normalize(axisNormals[0] + axisNormals[2])); | |
| 1975 | + glm::vec3 normalYZ(glm::normalize(axisNormals[1] + axisNormals[2])); | |
| 1976 | + if (glm::dot(axisNormals[0], normalXY) > CREASE_COS_NORMAL && | |
| 1977 | + glm::dot(axisNormals[1], normalXY) > CREASE_COS_NORMAL) { | |
| 1978 | + point.setNormal(normalXY); | |
| 1979 | + vertices.append(point); | |
| 1980 | + | |
| 1981 | + point.setNormal(axisNormals[2]); | |
| 1982 | + index.z = vertices.size(); | |
| 1983 | + vertices.append(point); | |
| 1984 | + | |
| 1985 | + } else if (glm::dot(axisNormals[0], normalXZ) > CREASE_COS_NORMAL && | |
| 1986 | + glm::dot(axisNormals[2], normalXZ) > CREASE_COS_NORMAL) { | |
| 1987 | + point.setNormal(normalXZ); | |
| 1988 | + vertices.append(point); | |
| 1989 | + | |
| 1990 | + point.setNormal(axisNormals[1]); | |
| 1991 | + index.y = vertices.size(); | |
| 1992 | + vertices.append(point); | |
| 1993 | + | |
| 1994 | + } else if (glm::dot(axisNormals[1], normalYZ) > CREASE_COS_NORMAL && | |
| 1995 | + glm::dot(axisNormals[2], normalYZ) > CREASE_COS_NORMAL) { | |
| 1996 | + point.setNormal(normalYZ); | |
| 1997 | + vertices.append(point); | |
| 1998 | + | |
| 1999 | + point.setNormal(axisNormals[0]); | |
| 2000 | + index.x = vertices.size(); | |
| 2001 | + vertices.append(point); | |
| 2002 | + | |
| 2003 | + } else { | |
| 2004 | + point.setNormal(axisNormals[0]); | |
| 2005 | + vertices.append(point); | |
| 2006 | + | |
| 2007 | + point.setNormal(axisNormals[1]); | |
| 2008 | + index.y = vertices.size(); | |
| 2009 | + vertices.append(point); | |
| 2010 | + | |
| 2011 | + point.setNormal(axisNormals[2]); | |
| 2012 | + index.z = vertices.size(); | |
| 2013 | + vertices.append(point); | |
| 2014 | + } | |
| 2015 | + } | |
| 1936 | 2016 | |
| 1937 | 2017 | // the first x, y, and z are repeated for the boundary edge; past that, we consider generating |
| 1938 | 2018 | // quads for each edge that includes a transition, using indices of previously generated vertices |
| 1939 | 2019 | if (x != 0 && y != 0 && z != 0) { |
| 1940 | 2020 | if (alpha0 != alpha1) { |
| 1941 | − indices.append(index); | |
| 1942 | − int index1 = lastLineIndices.at(x); | |
| 1943 | − int index2 = lastPlaneIndices.at((y - 1) * expanded + x); | |
| 1944 | − int index3 = lastPlaneIndices.at(y * expanded + x); | |
| 2021 | + indices.append(index.x); | |
| 2022 | + int index1 = lastLineIndices.at(x).x; | |
| 2023 | + int index2 = lastPlaneIndices.at((y - 1) * expanded + x).x; | |
| 2024 | + int index3 = lastPlaneIndices.at(y * expanded + x).x; | |
| 1945 | 2025 | if (alpha0 == 0) { // quad faces negative x |
| 1946 | 2026 | indices.append(index3); |
| 1947 | 2027 | indices.append(index2); |
| @@ -1954,10 +2034,10 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { · 6 unmodified lines | ||
| 1954 | 2034 | } |
| 1955 | 2035 | |
| 1956 | 2036 | if (alpha0 != alpha2) { |
| 1957 | − indices.append(index); | |
| 1958 | − int index1 = lastIndex; | |
| 1959 | − int index2 = lastPlaneIndices.at(y * expanded + x - 1); | |
| 1960 | − int index3 = lastPlaneIndices.at(y * expanded + x); | |
| 2037 | + indices.append(index.y); | |
| 2038 | + int index1 = lastIndex.y; | |
| 2039 | + int index2 = lastPlaneIndices.at(y * expanded + x - 1).y; | |
| 2040 | + int index3 = lastPlaneIndices.at(y * expanded + x).y; | |
| 1961 | 2041 | if (alpha0 == 0) { // quad faces negative y |
| 1962 | 2042 | indices.append(index1); |
| 1963 | 2043 | indices.append(index2); |
| @@ -1970,10 +2050,10 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { · 6 unmodified lines | ||
| 1970 | 2050 | } |
| 1971 | 2051 | |
| 1972 | 2052 | if (alpha0 != alpha4) { |
| 1973 | − indices.append(index); | |
| 1974 | − int index1 = lastIndex; | |
| 1975 | − int index2 = lastLineIndices.at(x - 1); | |
| 1976 | − int index3 = lastLineIndices.at(x); | |
| 2053 | + indices.append(index.z); | |
| 2054 | + int index1 = lastIndex.z; | |
| 2055 | + int index2 = lastLineIndices.at(x - 1).z; | |
| 2056 | + int index3 = lastLineIndices.at(x).z; | |
| 1977 | 2057 | if (alpha0 == 0) { // quad faces negative z |
| 1978 | 2058 | indices.append(index3); |
| 1979 | 2059 | indices.append(index2); |