diff options
author | Jacek Antonelli | 2008-08-15 23:44:57 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:57 -0500 |
commit | da68d3a57ecb27eba5d7efb8ff77d9640c0be65e (patch) | |
tree | f2fa2b9ed6e8cf49c8a3cb2a1893c4e5c61916a1 /linden/indra/llmath | |
parent | Second Life viewer sources 1.15.1.3 (diff) | |
download | meta-impy-da68d3a57ecb27eba5d7efb8ff77d9640c0be65e.zip meta-impy-da68d3a57ecb27eba5d7efb8ff77d9640c0be65e.tar.gz meta-impy-da68d3a57ecb27eba5d7efb8ff77d9640c0be65e.tar.bz2 meta-impy-da68d3a57ecb27eba5d7efb8ff77d9640c0be65e.tar.xz |
Second Life viewer sources 1.16.0.5
Diffstat (limited to 'linden/indra/llmath')
-rw-r--r-- | linden/indra/llmath/llvolume.cpp | 278 | ||||
-rw-r--r-- | linden/indra/llmath/llvolume.h | 44 |
2 files changed, 282 insertions, 40 deletions
diff --git a/linden/indra/llmath/llvolume.cpp b/linden/indra/llmath/llvolume.cpp index 89644a5..fb745b8 100644 --- a/linden/indra/llmath/llvolume.cpp +++ b/linden/indra/llmath/llvolume.cpp | |||
@@ -454,9 +454,18 @@ LLProfile::Face* LLProfile::addHole(BOOL flat, F32 sides, F32 offset, F32 box_ho | |||
454 | return face; | 454 | return face; |
455 | } | 455 | } |
456 | 456 | ||
457 | BOOL LLProfile::generate(BOOL path_open,F32 detail, S32 split) | 457 | |
458 | F32 next_power_of_two(F32 value) | ||
458 | { | 459 | { |
459 | if (!mDirty) | 460 | S32 power = (S32)llceil((F32)log((double)value)/(F32)log(2.0)); |
461 | return pow(2.0f, power); | ||
462 | } | ||
463 | |||
464 | |||
465 | |||
466 | BOOL LLProfile::generate(BOOL path_open,F32 detail, S32 split, BOOL is_sculpted) | ||
467 | { | ||
468 | if ((!mDirty) && (!is_sculpted)) | ||
460 | { | 469 | { |
461 | return FALSE; | 470 | return FALSE; |
462 | } | 471 | } |
@@ -592,10 +601,14 @@ BOOL LLProfile::generate(BOOL path_open,F32 detail, S32 split) | |||
592 | circle_detail = llceil(circle_detail / 4.0f) * 4.0f; | 601 | circle_detail = llceil(circle_detail / 4.0f) * 4.0f; |
593 | } | 602 | } |
594 | } | 603 | } |
604 | |||
605 | S32 sides = (S32)circle_detail; | ||
606 | |||
607 | if (is_sculpted) | ||
608 | sides = (S32)next_power_of_two((F32)sides); | ||
609 | |||
610 | genNGon(sides); | ||
595 | 611 | ||
596 | //llinfos << "(CIRCLE) detail: " << detail << "; genNGon(" | ||
597 | // << llfloor(circle_detail) << ")" << llendl; | ||
598 | genNGon(llfloor(circle_detail)); | ||
599 | if (path_open) | 612 | if (path_open) |
600 | { | 613 | { |
601 | addCap (LL_FACE_PATH_BEGIN); | 614 | addCap (LL_FACE_PATH_BEGIN); |
@@ -844,7 +857,7 @@ BOOL LLProfileParams::importLegacyStream(std::istream& input_stream) | |||
844 | } | 857 | } |
845 | else | 858 | else |
846 | { | 859 | { |
847 | llwarns << "unknown keyword " << keyword << " in profile import" << llendl; | 860 | llwarns << "unknown keyword " << keyword << " in profile import" << llendl; |
848 | } | 861 | } |
849 | } | 862 | } |
850 | 863 | ||
@@ -1074,9 +1087,9 @@ const LLVector2 LLPathParams::getEndScale() const | |||
1074 | return end_scale; | 1087 | return end_scale; |
1075 | } | 1088 | } |
1076 | 1089 | ||
1077 | BOOL LLPath::generate(F32 detail, S32 split) | 1090 | BOOL LLPath::generate(F32 detail, S32 split, BOOL is_sculpted) |
1078 | { | 1091 | { |
1079 | if (!mDirty) | 1092 | if ((!mDirty) && (!is_sculpted)) |
1080 | { | 1093 | { |
1081 | return FALSE; | 1094 | return FALSE; |
1082 | } | 1095 | } |
@@ -1131,7 +1144,13 @@ BOOL LLPath::generate(F32 detail, S32 split) | |||
1131 | { | 1144 | { |
1132 | // Increase the detail as the revolutions and twist increase. | 1145 | // Increase the detail as the revolutions and twist increase. |
1133 | F32 twist_mag = fabs(mParams.getTwistBegin() - mParams.getTwist()); | 1146 | F32 twist_mag = fabs(mParams.getTwistBegin() - mParams.getTwist()); |
1134 | genNGon(llfloor(llfloor((MIN_DETAIL_FACES * detail + twist_mag * 3.5f * (detail-0.5f))) * mParams.getRevolutions())); | 1147 | |
1148 | S32 sides = (S32)llfloor(llfloor((MIN_DETAIL_FACES * detail + twist_mag * 3.5f * (detail-0.5f))) * mParams.getRevolutions()); | ||
1149 | |||
1150 | if (is_sculpted) | ||
1151 | sides = (S32)next_power_of_two((F32)sides); | ||
1152 | |||
1153 | genNGon(sides); | ||
1135 | } | 1154 | } |
1136 | break; | 1155 | break; |
1137 | 1156 | ||
@@ -1194,7 +1213,7 @@ BOOL LLPath::generate(F32 detail, S32 split) | |||
1194 | return TRUE; | 1213 | return TRUE; |
1195 | } | 1214 | } |
1196 | 1215 | ||
1197 | BOOL LLDynamicPath::generate(F32 detail, S32 split) | 1216 | BOOL LLDynamicPath::generate(F32 detail, S32 split, BOOL is_sculpted) |
1198 | { | 1217 | { |
1199 | mOpen = TRUE; // Draw end caps | 1218 | mOpen = TRUE; // Draw end caps |
1200 | if (getPathLength() == 0) | 1219 | if (getPathLength() == 0) |
@@ -1555,13 +1574,15 @@ LLProfile::~LLProfile() | |||
1555 | } | 1574 | } |
1556 | 1575 | ||
1557 | 1576 | ||
1558 | S32 LLVolume::mNumMeshPoints = 0; | 1577 | S32 LLVolume::sNumMeshPoints = 0; |
1559 | 1578 | ||
1560 | LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL generate_single_face, const BOOL is_unique) : mParams(params) | 1579 | LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL generate_single_face, const BOOL is_unique) : mParams(params) |
1561 | { | 1580 | { |
1562 | mUnique = is_unique; | 1581 | mUnique = is_unique; |
1563 | mFaceMask = 0x0; | 1582 | mFaceMask = 0x0; |
1564 | mDetail = detail; | 1583 | mDetail = detail; |
1584 | mSculptLevel = -2; | ||
1585 | |||
1565 | // set defaults | 1586 | // set defaults |
1566 | if (mParams.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE) | 1587 | if (mParams.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE) |
1567 | { | 1588 | { |
@@ -1578,7 +1599,10 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge | |||
1578 | mGenerateSingleFace = generate_single_face; | 1599 | mGenerateSingleFace = generate_single_face; |
1579 | 1600 | ||
1580 | generate(); | 1601 | generate(); |
1581 | createVolumeFaces(); | 1602 | if (mParams.getSculptID().isNull()) |
1603 | { | ||
1604 | createVolumeFaces(); | ||
1605 | } | ||
1582 | } | 1606 | } |
1583 | 1607 | ||
1584 | void LLVolume::regen() | 1608 | void LLVolume::regen() |
@@ -1589,7 +1613,7 @@ void LLVolume::regen() | |||
1589 | 1613 | ||
1590 | LLVolume::~LLVolume() | 1614 | LLVolume::~LLVolume() |
1591 | { | 1615 | { |
1592 | mNumMeshPoints -= mMesh.size(); | 1616 | sNumMeshPoints -= mMesh.size(); |
1593 | delete mPathp; | 1617 | delete mPathp; |
1594 | delete mProfilep; | 1618 | delete mProfilep; |
1595 | delete[] mVolumeFaces; | 1619 | delete[] mVolumeFaces; |
@@ -1640,9 +1664,9 @@ BOOL LLVolume::generate() | |||
1640 | 1664 | ||
1641 | if (regenPath || regenProf ) | 1665 | if (regenPath || regenProf ) |
1642 | { | 1666 | { |
1643 | mNumMeshPoints -= mMesh.size(); | 1667 | sNumMeshPoints -= mMesh.size(); |
1644 | mMesh.resize(mProfilep->mProfile.size() * mPathp->mPath.size()); | 1668 | mMesh.resize(mProfilep->mProfile.size() * mPathp->mPath.size()); |
1645 | mNumMeshPoints += mMesh.size(); | 1669 | sNumMeshPoints += mMesh.size(); |
1646 | 1670 | ||
1647 | S32 s = 0, t=0; | 1671 | S32 s = 0, t=0; |
1648 | S32 sizeS = mPathp->mPath.size(); | 1672 | S32 sizeS = mPathp->mPath.size(); |
@@ -1772,6 +1796,128 @@ void LLVolume::createVolumeFaces() | |||
1772 | } | 1796 | } |
1773 | 1797 | ||
1774 | 1798 | ||
1799 | // sculpt replaces generate() for sculpted surfaces | ||
1800 | void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level) | ||
1801 | { | ||
1802 | BOOL data_is_empty = FALSE; | ||
1803 | |||
1804 | if (sculpt_width == 0 || sculpt_height == 0 || sculpt_data == NULL) | ||
1805 | { | ||
1806 | sculpt_level = -1; | ||
1807 | data_is_empty = TRUE; | ||
1808 | } | ||
1809 | |||
1810 | mPathp->generate(mDetail, 0, TRUE); | ||
1811 | mProfilep->generate(mPathp->isOpen(), mDetail, 0, TRUE); | ||
1812 | |||
1813 | |||
1814 | S32 sizeS = mPathp->mPath.size(); | ||
1815 | S32 sizeT = mProfilep->mProfile.size(); | ||
1816 | |||
1817 | sNumMeshPoints -= mMesh.size(); | ||
1818 | mMesh.resize(sizeS * sizeT); | ||
1819 | sNumMeshPoints += mMesh.size(); | ||
1820 | |||
1821 | S32 vertex_change = 0; | ||
1822 | // first test to see if image has enough variation to create geometry | ||
1823 | if (!data_is_empty) | ||
1824 | { | ||
1825 | S32 last_index = 0; | ||
1826 | for (S32 s = 0; s < sizeS; s++) | ||
1827 | for (S32 t = 0; t < sizeT; t++) | ||
1828 | { | ||
1829 | U32 x = (U32) ((F32)s/(sizeS-1) * (F32) sculpt_width); | ||
1830 | U32 y = (U32) ((F32)t/(sizeT-1) * (F32) sculpt_height); | ||
1831 | |||
1832 | if (y == sculpt_height) // clamp to bottom row | ||
1833 | y = sculpt_height - 1; | ||
1834 | |||
1835 | if (x == sculpt_width) // stitch sides | ||
1836 | x = 0; | ||
1837 | |||
1838 | if ((y == 0) || (y == sculpt_height-1)) // stitch top and bottom | ||
1839 | x = sculpt_width / 2; | ||
1840 | |||
1841 | U32 index = (x + y * sculpt_width) * sculpt_components; | ||
1842 | |||
1843 | if (fabs((F32)(sculpt_data[index] - sculpt_data[last_index])) + | ||
1844 | fabs((F32)(sculpt_data[index+1] - sculpt_data[last_index+1])) + | ||
1845 | fabs((F32)(sculpt_data[index+2] - sculpt_data[last_index+2])) > 256 * 0.02) | ||
1846 | vertex_change++; | ||
1847 | |||
1848 | last_index = index; | ||
1849 | } | ||
1850 | } | ||
1851 | |||
1852 | |||
1853 | if ((F32)vertex_change / sizeS / sizeT < 0.05) // less than 5% | ||
1854 | data_is_empty = TRUE; | ||
1855 | |||
1856 | |||
1857 | //generate vertex positions | ||
1858 | // Run along the path. | ||
1859 | S32 s = 0, t = 0; | ||
1860 | S32 line = 0; | ||
1861 | while (s < sizeS) | ||
1862 | { | ||
1863 | t = 0; | ||
1864 | // Run along the profile. | ||
1865 | while (t < sizeT) | ||
1866 | { | ||
1867 | S32 i = t + line; | ||
1868 | Point& pt = mMesh[i]; | ||
1869 | |||
1870 | U32 x = (U32) ((F32)t/(sizeT-1) * (F32) sculpt_width); | ||
1871 | U32 y = (U32) ((F32)s/(sizeS-1) * (F32) sculpt_height); | ||
1872 | |||
1873 | if (y == sculpt_height) // clamp to bottom row | ||
1874 | y = sculpt_height - 1; | ||
1875 | |||
1876 | if (x == sculpt_width) // stitch sides | ||
1877 | x = 0; | ||
1878 | |||
1879 | if ((y == 0) || (y == sculpt_height-1)) // stitch top and bottom | ||
1880 | x = sculpt_width / 2; | ||
1881 | |||
1882 | |||
1883 | if (data_is_empty) // if empty, make a sphere | ||
1884 | { | ||
1885 | F32 u = (F32)s/(sizeS-1); | ||
1886 | F32 v = (F32)t/(sizeT-1); | ||
1887 | |||
1888 | const F32 RADIUS = (F32) 0.3; | ||
1889 | |||
1890 | pt.mPos.mV[0] = (F32)(sin(F_PI * v) * cos(2.0 * F_PI * u) * RADIUS); | ||
1891 | pt.mPos.mV[1] = (F32)(sin(F_PI * v) * sin(2.0 * F_PI * u) * RADIUS); | ||
1892 | pt.mPos.mV[2] = (F32)(cos(F_PI * v) * RADIUS); | ||
1893 | } | ||
1894 | |||
1895 | else | ||
1896 | { | ||
1897 | U32 index = (x + y * sculpt_width) * sculpt_components; | ||
1898 | pt.mPos.mV[0] = sculpt_data[index ] / 256.f - 0.5f; | ||
1899 | pt.mPos.mV[1] = sculpt_data[index+1] / 256.f - 0.5f; | ||
1900 | pt.mPos.mV[2] = sculpt_data[index+2] / 256.f - 0.5f; | ||
1901 | } | ||
1902 | |||
1903 | t++; | ||
1904 | } | ||
1905 | line += sizeT; | ||
1906 | s++; | ||
1907 | } | ||
1908 | |||
1909 | for (S32 i = 0; i < (S32)mProfilep->mFaces.size(); i++) | ||
1910 | { | ||
1911 | mFaceMask |= mProfilep->mFaces[i].mFaceID; | ||
1912 | } | ||
1913 | |||
1914 | mSculptLevel = sculpt_level; | ||
1915 | createVolumeFaces(); | ||
1916 | } | ||
1917 | |||
1918 | |||
1919 | |||
1920 | |||
1775 | BOOL LLVolume::isCap(S32 face) | 1921 | BOOL LLVolume::isCap(S32 face) |
1776 | { | 1922 | { |
1777 | return mProfilep->mFaces[face].mCap; | 1923 | return mProfilep->mFaces[face].mCap; |
@@ -1785,14 +1931,18 @@ BOOL LLVolume::isFlat(S32 face) | |||
1785 | 1931 | ||
1786 | bool LLVolumeParams::operator==(const LLVolumeParams ¶ms) const | 1932 | bool LLVolumeParams::operator==(const LLVolumeParams ¶ms) const |
1787 | { | 1933 | { |
1788 | return (getPathParams() == params.getPathParams()) && | 1934 | return ( (getPathParams() == params.getPathParams()) && |
1789 | (getProfileParams() == params.getProfileParams()); | 1935 | (getProfileParams() == params.getProfileParams()) && |
1936 | (mSculptID == params.mSculptID) && | ||
1937 | (mSculptType == params.mSculptType) ); | ||
1790 | } | 1938 | } |
1791 | 1939 | ||
1792 | bool LLVolumeParams::operator!=(const LLVolumeParams ¶ms) const | 1940 | bool LLVolumeParams::operator!=(const LLVolumeParams ¶ms) const |
1793 | { | 1941 | { |
1794 | return (getPathParams() != params.getPathParams()) || | 1942 | return ( (getPathParams() != params.getPathParams()) || |
1795 | (getProfileParams() != params.getProfileParams()); | 1943 | (getProfileParams() != params.getProfileParams()) || |
1944 | (mSculptID != params.mSculptID) || | ||
1945 | (mSculptType != params.mSculptType) ); | ||
1796 | } | 1946 | } |
1797 | 1947 | ||
1798 | bool LLVolumeParams::operator<(const LLVolumeParams ¶ms) const | 1948 | bool LLVolumeParams::operator<(const LLVolumeParams ¶ms) const |
@@ -1801,16 +1951,29 @@ bool LLVolumeParams::operator<(const LLVolumeParams ¶ms) const | |||
1801 | { | 1951 | { |
1802 | return getPathParams() < params.getPathParams(); | 1952 | return getPathParams() < params.getPathParams(); |
1803 | } | 1953 | } |
1804 | else | 1954 | |
1955 | if (getProfileParams() != params.getProfileParams()) | ||
1805 | { | 1956 | { |
1806 | return getProfileParams() < params.getProfileParams(); | 1957 | return getProfileParams() < params.getProfileParams(); |
1807 | } | 1958 | } |
1959 | |||
1960 | if (mSculptID != params.mSculptID) | ||
1961 | { | ||
1962 | return mSculptID < params.mSculptID; | ||
1963 | } | ||
1964 | |||
1965 | |||
1966 | return mSculptType < params.mSculptType; | ||
1967 | |||
1968 | |||
1808 | } | 1969 | } |
1809 | 1970 | ||
1810 | void LLVolumeParams::copyParams(const LLVolumeParams ¶ms) | 1971 | void LLVolumeParams::copyParams(const LLVolumeParams ¶ms) |
1811 | { | 1972 | { |
1812 | mProfileParams.copyParams(params.mProfileParams); | 1973 | mProfileParams.copyParams(params.mProfileParams); |
1813 | mPathParams.copyParams(params.mPathParams); | 1974 | mPathParams.copyParams(params.mPathParams); |
1975 | mSculptID = params.getSculptID(); | ||
1976 | mSculptType = params.getSculptType(); | ||
1814 | } | 1977 | } |
1815 | 1978 | ||
1816 | // Less restricitve approx 0 for volumes | 1979 | // Less restricitve approx 0 for volumes |
@@ -2070,6 +2233,13 @@ bool LLVolumeParams::setSkew(const F32 skew_value) | |||
2070 | return valid; | 2233 | return valid; |
2071 | } | 2234 | } |
2072 | 2235 | ||
2236 | bool LLVolumeParams::setSculptID(const LLUUID sculpt_id, U8 sculpt_type) | ||
2237 | { | ||
2238 | mSculptID = sculpt_id; | ||
2239 | mSculptType = sculpt_type; | ||
2240 | return true; | ||
2241 | } | ||
2242 | |||
2073 | bool LLVolumeParams::setType(U8 profile, U8 path) | 2243 | bool LLVolumeParams::setType(U8 profile, U8 path) |
2074 | { | 2244 | { |
2075 | bool result = true; | 2245 | bool result = true; |
@@ -2829,7 +2999,7 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices, | |||
2829 | segments.clear(); | 2999 | segments.clear(); |
2830 | 3000 | ||
2831 | //for each face | 3001 | //for each face |
2832 | for (S32 i = 0; i < getNumFaces(); i++) { | 3002 | for (S32 i = 0; i < getNumVolumeFaces(); i++) { |
2833 | LLVolumeFace face = this->getVolumeFace(i); | 3003 | LLVolumeFace face = this->getVolumeFace(i); |
2834 | 3004 | ||
2835 | if (face.mTypeMask & (LLVolumeFace::CAP_MASK)) { | 3005 | if (face.mTypeMask & (LLVolumeFace::CAP_MASK)) { |
@@ -4436,6 +4606,9 @@ BOOL LLVolumeFace::createSide() | |||
4436 | } | 4606 | } |
4437 | } | 4607 | } |
4438 | 4608 | ||
4609 | BOOL s_bottom_converges = ((mVertices[0].mPosition - mVertices[mNumS*(mNumT-2)].mPosition).magVecSquared() < 0.000001f); | ||
4610 | BOOL s_top_converges = ((mVertices[mNumS-1].mPosition - mVertices[mNumS*(mNumT-2)+mNumS-1].mPosition).magVecSquared() < 0.000001f); | ||
4611 | |||
4439 | if (mVolumep->getPath().isOpen() == FALSE) { //wrap normals on T | 4612 | if (mVolumep->getPath().isOpen() == FALSE) { //wrap normals on T |
4440 | for (S32 i = 0; i < mNumS; i++) { | 4613 | for (S32 i = 0; i < mNumS; i++) { |
4441 | LLVector3 norm = mVertices[i].mNormal + mVertices[mNumS*(mNumT-1)+i].mNormal; | 4614 | LLVector3 norm = mVertices[i].mNormal + mVertices[mNumS*(mNumT-1)+i].mNormal; |
@@ -4444,30 +4617,73 @@ BOOL LLVolumeFace::createSide() | |||
4444 | } | 4617 | } |
4445 | } | 4618 | } |
4446 | 4619 | ||
4447 | if (mVolumep->getProfile().isOpen() == FALSE) { //wrap normals on S | 4620 | if ((mVolumep->getProfile().isOpen() == FALSE) && |
4448 | for (S32 i = 0; i < mNumT; i++) { | 4621 | !(s_bottom_converges)) |
4449 | LLVector3 norm = mVertices[mNumS*i].mNormal + mVertices[mNumS*i+mNumS-1].mNormal; | 4622 | { //wrap normals on S |
4450 | mVertices[mNumS * i].mNormal = norm; | 4623 | for (S32 i = 0; i < mNumT; i++) { |
4451 | mVertices[mNumS * i+mNumS-1].mNormal = norm; | 4624 | LLVector3 norm = mVertices[mNumS*i].mNormal + mVertices[mNumS*i+mNumS-1].mNormal; |
4625 | mVertices[mNumS * i].mNormal = norm; | ||
4626 | mVertices[mNumS * i+mNumS-1].mNormal = norm; | ||
4627 | } | ||
4452 | } | 4628 | } |
4453 | } | ||
4454 | 4629 | ||
4455 | if (mVolumep->getPathType() == LL_PCODE_PATH_CIRCLE && ((mVolumep->getProfileType() & LL_PCODE_PROFILE_MASK) == LL_PCODE_PROFILE_CIRCLE_HALF)) { | 4630 | if (mVolumep->getPathType() == LL_PCODE_PATH_CIRCLE && |
4456 | if ((mVertices[0].mPosition - mVertices[mNumS*(mNumT-2)].mPosition).magVecSquared() < 0.000001f) | 4631 | ((mVolumep->getProfileType() & LL_PCODE_PROFILE_MASK) == LL_PCODE_PROFILE_CIRCLE_HALF)) |
4632 | { | ||
4633 | if (s_bottom_converges) | ||
4457 | { //all lower S have same normal | 4634 | { //all lower S have same normal |
4458 | for (S32 i = 0; i < mNumT; i++) { | 4635 | for (S32 i = 0; i < mNumT; i++) { |
4459 | mVertices[mNumS*i].mNormal = LLVector3(1,0,0); | 4636 | mVertices[mNumS*i].mNormal = LLVector3(1,0,0); |
4460 | } | 4637 | } |
4461 | } | 4638 | } |
4462 | 4639 | ||
4463 | if ((mVertices[mNumS-1].mPosition - mVertices[mNumS*(mNumT-2)+mNumS-1].mPosition).magVecSquared() < 0.000001f) | 4640 | if (s_top_converges) |
4464 | { //all upper T have same normal | 4641 | { //all upper S have same normal |
4465 | for (S32 i = 0; i < mNumT; i++) { | 4642 | for (S32 i = 0; i < mNumT; i++) { |
4466 | mVertices[mNumS*i+mNumS-1].mNormal = LLVector3(-1,0,0); | 4643 | mVertices[mNumS*i+mNumS-1].mNormal = LLVector3(-1,0,0); |
4467 | } | 4644 | } |
4468 | } | 4645 | } |
4469 | } | 4646 | } |
4470 | 4647 | ||
4648 | U8 sculpt_type = mVolumep->getParams().getSculptType(); | ||
4649 | |||
4650 | if (sculpt_type == LL_SCULPT_TYPE_SPHERE) | ||
4651 | { | ||
4652 | // average normals for north pole | ||
4653 | |||
4654 | LLVector3 average(0.0, 0.0, 0.0); | ||
4655 | for (S32 i = 0; i < mNumS; i++) | ||
4656 | { | ||
4657 | average += mVertices[i].mNormal; | ||
4658 | } | ||
4659 | |||
4660 | // set average | ||
4661 | for (S32 i = 0; i < mNumS; i++) | ||
4662 | { | ||
4663 | mVertices[i].mNormal = average; | ||
4664 | } | ||
4665 | } | ||
4666 | |||
4667 | |||
4668 | if (sculpt_type == LL_SCULPT_TYPE_SPHERE) | ||
4669 | { | ||
4670 | // average normals for south pole | ||
4671 | |||
4672 | LLVector3 average(0.0, 0.0, 0.0); | ||
4673 | for (S32 i = 0; i < mNumS; i++) | ||
4674 | { | ||
4675 | average += mVertices[i + mNumS * (mNumT - 1)].mNormal; | ||
4676 | } | ||
4677 | |||
4678 | // set average | ||
4679 | for (S32 i = 0; i < mNumS; i++) | ||
4680 | { | ||
4681 | mVertices[i + mNumS * (mNumT - 1)].mNormal = average; | ||
4682 | } | ||
4683 | } | ||
4684 | |||
4685 | |||
4686 | |||
4471 | //normalize normals and binormals here so the meshes that reference | 4687 | //normalize normals and binormals here so the meshes that reference |
4472 | //this volume data don't have to | 4688 | //this volume data don't have to |
4473 | for (U32 i = 0; i < mVertices.size(); i++) | 4689 | for (U32 i = 0; i < mVertices.size(); i++) |
diff --git a/linden/indra/llmath/llvolume.h b/linden/indra/llmath/llvolume.h index 7137346..a3e89ab 100644 --- a/linden/indra/llmath/llvolume.h +++ b/linden/indra/llmath/llvolume.h | |||
@@ -169,6 +169,16 @@ const LLFaceID LL_FACE_OUTER_SIDE_3 = 0x1 << 8; | |||
169 | 169 | ||
170 | //============================================================================ | 170 | //============================================================================ |
171 | 171 | ||
172 | // sculpt types | ||
173 | |||
174 | const U8 LL_SCULPT_TYPE_NONE = 0; | ||
175 | const U8 LL_SCULPT_TYPE_SPHERE = 1; | ||
176 | const U8 LL_SCULPT_TYPE_TORUS = 2; | ||
177 | const U8 LL_SCULPT_TYPE_PLAIN = 3; | ||
178 | const U8 LL_SCULPT_TYPE_CYLINDER = 4; | ||
179 | |||
180 | |||
181 | |||
172 | class LLProfileParams | 182 | class LLProfileParams |
173 | { | 183 | { |
174 | public: | 184 | public: |
@@ -512,8 +522,9 @@ public: | |||
512 | { | 522 | { |
513 | } | 523 | } |
514 | 524 | ||
515 | LLVolumeParams(LLProfileParams &profile, LLPathParams &path) | 525 | LLVolumeParams(LLProfileParams &profile, LLPathParams &path, |
516 | : mProfileParams(profile), mPathParams(path) | 526 | LLUUID sculpt_id = LLUUID::null, U8 sculpt_type = LL_SCULPT_TYPE_NONE) |
527 | : mProfileParams(profile), mPathParams(path), mSculptID(sculpt_id), mSculptType(sculpt_type) | ||
517 | { | 528 | { |
518 | } | 529 | } |
519 | 530 | ||
@@ -564,6 +575,7 @@ public: | |||
564 | bool setRevolutions(const F32 revolutions); // 1 to 4 | 575 | bool setRevolutions(const F32 revolutions); // 1 to 4 |
565 | bool setRadiusOffset(const F32 radius_offset); | 576 | bool setRadiusOffset(const F32 radius_offset); |
566 | bool setSkew(const F32 skew); | 577 | bool setSkew(const F32 skew); |
578 | bool setSculptID(const LLUUID sculpt_id, U8 sculpt_type); | ||
567 | 579 | ||
568 | static bool validate(U8 prof_curve, F32 prof_begin, F32 prof_end, F32 hollow, | 580 | static bool validate(U8 prof_curve, F32 prof_begin, F32 prof_end, F32 hollow, |
569 | U8 path_curve, F32 path_begin, F32 path_end, | 581 | U8 path_curve, F32 path_begin, F32 path_end, |
@@ -591,6 +603,8 @@ public: | |||
591 | const F32& getTaperY() const { return mPathParams.getTaperY(); } | 603 | const F32& getTaperY() const { return mPathParams.getTaperY(); } |
592 | const F32& getRevolutions() const { return mPathParams.getRevolutions(); } | 604 | const F32& getRevolutions() const { return mPathParams.getRevolutions(); } |
593 | const F32& getSkew() const { return mPathParams.getSkew(); } | 605 | const F32& getSkew() const { return mPathParams.getSkew(); } |
606 | const LLUUID& getSculptID() const { return mSculptID; } | ||
607 | const U8& getSculptType() const { return mSculptType; } | ||
594 | 608 | ||
595 | BOOL isConvex() const; | 609 | BOOL isConvex() const; |
596 | 610 | ||
@@ -613,6 +627,8 @@ public: | |||
613 | protected: | 627 | protected: |
614 | LLProfileParams mProfileParams; | 628 | LLProfileParams mProfileParams; |
615 | LLPathParams mPathParams; | 629 | LLPathParams mPathParams; |
630 | LLUUID mSculptID; | ||
631 | U8 mSculptType; | ||
616 | }; | 632 | }; |
617 | 633 | ||
618 | 634 | ||
@@ -635,7 +651,7 @@ public: | |||
635 | BOOL isFlat(S32 face) const { return (mFaces[face].mCount == 2); } | 651 | BOOL isFlat(S32 face) const { return (mFaces[face].mCount == 2); } |
636 | BOOL isOpen() const { return mOpen; } | 652 | BOOL isOpen() const { return mOpen; } |
637 | void setDirty() { mDirty = TRUE; } | 653 | void setDirty() { mDirty = TRUE; } |
638 | BOOL generate(BOOL path_open, F32 detail = 1.0f, S32 split = 0); | 654 | BOOL generate(BOOL path_open, F32 detail = 1.0f, S32 split = 0, BOOL is_sculpted = FALSE); |
639 | BOOL isConcave() const { return mConcave; } | 655 | BOOL isConcave() const { return mConcave; } |
640 | public: | 656 | public: |
641 | const LLProfileParams &mParams; | 657 | const LLProfileParams &mParams; |
@@ -704,7 +720,7 @@ public: | |||
704 | virtual ~LLPath(); | 720 | virtual ~LLPath(); |
705 | 721 | ||
706 | void genNGon(S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f); | 722 | void genNGon(S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f); |
707 | virtual BOOL generate(F32 detail=1.0f, S32 split = 0); | 723 | virtual BOOL generate(F32 detail=1.0f, S32 split = 0, BOOL is_sculpted = FALSE); |
708 | 724 | ||
709 | BOOL isOpen() const { return mOpen; } | 725 | BOOL isOpen() const { return mOpen; } |
710 | F32 getStep() const { return mStep; } | 726 | F32 getStep() const { return mStep; } |
@@ -731,7 +747,7 @@ class LLDynamicPath : public LLPath | |||
731 | { | 747 | { |
732 | public: | 748 | public: |
733 | LLDynamicPath(const LLPathParams ¶ms) : LLPath(params) { } | 749 | LLDynamicPath(const LLPathParams ¶ms) : LLPath(params) { } |
734 | BOOL generate(F32 detail=1.0f, S32 split = 0); | 750 | BOOL generate(F32 detail=1.0f, S32 split = 0, BOOL is_sculpted = FALSE); |
735 | }; | 751 | }; |
736 | 752 | ||
737 | // Yet another "face" class - caches volume-specific, but not instance-specific data for faces) | 753 | // Yet another "face" class - caches volume-specific, but not instance-specific data for faces) |
@@ -821,7 +837,7 @@ public: | |||
821 | U8 getProfileType() const { return mProfilep->mParams.getCurveType(); } | 837 | U8 getProfileType() const { return mProfilep->mParams.getCurveType(); } |
822 | U8 getPathType() const { return mPathp->mParams.getCurveType(); } | 838 | U8 getPathType() const { return mPathp->mParams.getCurveType(); } |
823 | S32 getNumFaces() const { return (S32)mProfilep->mFaces.size(); } | 839 | S32 getNumFaces() const { return (S32)mProfilep->mFaces.size(); } |
824 | 840 | S32 getNumVolumeFaces() const { return mNumVolumeFaces; } | |
825 | const F32 getDetail() const { return mDetail; } | 841 | const F32 getDetail() const { return mDetail; } |
826 | const LLVolumeParams & getParams() const { return mParams; } | 842 | const LLVolumeParams & getParams() const { return mParams; } |
827 | LLVolumeParams getCopyOfParams() const { return mParams; } | 843 | LLVolumeParams getCopyOfParams() const { return mParams; } |
@@ -839,6 +855,11 @@ public: | |||
839 | BOOL isFlat(S32 face); | 855 | BOOL isFlat(S32 face); |
840 | BOOL isUnique() const { return mUnique; } | 856 | BOOL isUnique() const { return mUnique; } |
841 | 857 | ||
858 | S32 getSculptLevel() const { return mSculptLevel; } | ||
859 | void setSculptLevel(S32 level) { mSculptLevel = level; } | ||
860 | |||
861 | U8 getSculptType() const { return mSculptType; } | ||
862 | |||
842 | S32 *getTriangleIndices(U32 &num_indices) const; | 863 | S32 *getTriangleIndices(U32 &num_indices) const; |
843 | void generateSilhouetteVertices(std::vector<LLVector3> &vertices, std::vector<LLVector3> &normals, std::vector<S32> &segments, const LLVector3& view_vec, | 864 | void generateSilhouetteVertices(std::vector<LLVector3> &vertices, std::vector<LLVector3> &normals, std::vector<S32> &segments, const LLVector3& view_vec, |
844 | const LLMatrix4& mat, | 865 | const LLMatrix4& mat, |
@@ -863,7 +884,7 @@ public: | |||
863 | LLFaceID generateFaceMask(); | 884 | LLFaceID generateFaceMask(); |
864 | 885 | ||
865 | BOOL isFaceMaskValid(LLFaceID face_mask); | 886 | BOOL isFaceMaskValid(LLFaceID face_mask); |
866 | static S32 mNumMeshPoints; | 887 | static S32 sNumMeshPoints; |
867 | 888 | ||
868 | friend std::ostream& operator<<(std::ostream &s, const LLVolume &volume); | 889 | friend std::ostream& operator<<(std::ostream &s, const LLVolume &volume); |
869 | friend std::ostream& operator<<(std::ostream &s, const LLVolume *volumep); // HACK to bypass Windoze confusion over | 890 | friend std::ostream& operator<<(std::ostream &s, const LLVolume *volumep); // HACK to bypass Windoze confusion over |
@@ -872,14 +893,19 @@ public: | |||
872 | 893 | ||
873 | U32 mFaceMask; // bit array of which faces exist in this volume | 894 | U32 mFaceMask; // bit array of which faces exist in this volume |
874 | LLVector3 mLODScaleBias; // vector for biasing LOD based on scale | 895 | LLVector3 mLODScaleBias; // vector for biasing LOD based on scale |
875 | 896 | ||
897 | void sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level); | ||
898 | |||
876 | protected: | 899 | protected: |
877 | BOOL generate(); | 900 | BOOL generate(); |
878 | void createVolumeFaces(); | 901 | void createVolumeFaces(); |
879 | 902 | ||
880 | protected: | 903 | protected: |
881 | BOOL mUnique; | 904 | BOOL mUnique; |
882 | F32 mDetail; | 905 | F32 mDetail; |
906 | S32 mSculptLevel; | ||
907 | U8 mSculptType; | ||
908 | |||
883 | LLVolumeParams mParams; | 909 | LLVolumeParams mParams; |
884 | LLPath *mPathp; | 910 | LLPath *mPathp; |
885 | LLProfile *mProfilep; | 911 | LLProfile *mProfilep; |