diff options
Diffstat (limited to 'linden/indra/llmath/llvolume.cpp')
-rw-r--r-- | linden/indra/llmath/llvolume.cpp | 278 |
1 files changed, 247 insertions, 31 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++) |