aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llmath/llvolume.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llmath/llvolume.cpp')
-rw-r--r--linden/indra/llmath/llvolume.cpp278
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
457BOOL LLProfile::generate(BOOL path_open,F32 detail, S32 split) 457
458F32 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
466BOOL 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
1077BOOL LLPath::generate(F32 detail, S32 split) 1090BOOL 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
1197BOOL LLDynamicPath::generate(F32 detail, S32 split) 1216BOOL 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
1558S32 LLVolume::mNumMeshPoints = 0; 1577S32 LLVolume::sNumMeshPoints = 0;
1559 1578
1560LLVolume::LLVolume(const LLVolumeParams &params, const F32 detail, const BOOL generate_single_face, const BOOL is_unique) : mParams(params) 1579LLVolume::LLVolume(const LLVolumeParams &params, 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 &params, 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
1584void LLVolume::regen() 1608void LLVolume::regen()
@@ -1589,7 +1613,7 @@ void LLVolume::regen()
1589 1613
1590LLVolume::~LLVolume() 1614LLVolume::~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
1800void 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
1775BOOL LLVolume::isCap(S32 face) 1921BOOL 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
1786bool LLVolumeParams::operator==(const LLVolumeParams &params) const 1932bool LLVolumeParams::operator==(const LLVolumeParams &params) 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
1792bool LLVolumeParams::operator!=(const LLVolumeParams &params) const 1940bool LLVolumeParams::operator!=(const LLVolumeParams &params) 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
1798bool LLVolumeParams::operator<(const LLVolumeParams &params) const 1948bool LLVolumeParams::operator<(const LLVolumeParams &params) const
@@ -1801,16 +1951,29 @@ bool LLVolumeParams::operator<(const LLVolumeParams &params) 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
1810void LLVolumeParams::copyParams(const LLVolumeParams &params) 1971void LLVolumeParams::copyParams(const LLVolumeParams &params)
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
2236bool LLVolumeParams::setSculptID(const LLUUID sculpt_id, U8 sculpt_type)
2237{
2238 mSculptID = sculpt_id;
2239 mSculptType = sculpt_type;
2240 return true;
2241}
2242
2073bool LLVolumeParams::setType(U8 profile, U8 path) 2243bool 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++)