diff options
author | Jacek Antonelli | 2008-09-06 18:24:57 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-09-06 18:25:07 -0500 |
commit | 798d367d54a6c6379ad355bd8345fa40e31e7fe9 (patch) | |
tree | 1921f1708cd0240648c97bc02df2c2ab5f2fc41e /linden/indra/llmath/llvolume.cpp | |
parent | Second Life viewer sources 1.20.15 (diff) | |
download | meta-impy-798d367d54a6c6379ad355bd8345fa40e31e7fe9.zip meta-impy-798d367d54a6c6379ad355bd8345fa40e31e7fe9.tar.gz meta-impy-798d367d54a6c6379ad355bd8345fa40e31e7fe9.tar.bz2 meta-impy-798d367d54a6c6379ad355bd8345fa40e31e7fe9.tar.xz |
Second Life viewer sources 1.21.0-RC
Diffstat (limited to 'linden/indra/llmath/llvolume.cpp')
-rw-r--r-- | linden/indra/llmath/llvolume.cpp | 420 |
1 files changed, 292 insertions, 128 deletions
diff --git a/linden/indra/llmath/llvolume.cpp b/linden/indra/llmath/llvolume.cpp index f7c9286..7b6c6a9 100644 --- a/linden/indra/llmath/llvolume.cpp +++ b/linden/indra/llmath/llvolume.cpp | |||
@@ -82,11 +82,6 @@ const F32 TAPER_MAX = 1.f; | |||
82 | const F32 SKEW_MIN = -0.95f; | 82 | const F32 SKEW_MIN = -0.95f; |
83 | const F32 SKEW_MAX = 0.95f; | 83 | const F32 SKEW_MAX = 0.95f; |
84 | 84 | ||
85 | const S32 SCULPT_REZ_1 = 6; // changed from 4 to 6 - 6 looks round whereas 4 looks square | ||
86 | const S32 SCULPT_REZ_2 = 8; | ||
87 | const S32 SCULPT_REZ_3 = 16; | ||
88 | const S32 SCULPT_REZ_4 = 32; | ||
89 | |||
90 | const F32 SCULPT_MIN_AREA = 0.002f; | 85 | const F32 SCULPT_MIN_AREA = 0.002f; |
91 | 86 | ||
92 | BOOL check_same_clock_dir( const LLVector3& pt1, const LLVector3& pt2, const LLVector3& pt3, const LLVector3& norm) | 87 | BOOL check_same_clock_dir( const LLVector3& pt1, const LLVector3& pt2, const LLVector3& pt3, const LLVector3& norm) |
@@ -104,46 +99,128 @@ BOOL check_same_clock_dir( const LLVector3& pt1, const LLVector3& pt2, const LLV | |||
104 | } | 99 | } |
105 | } | 100 | } |
106 | 101 | ||
107 | // intersect test between triangle pt1,pt2,pt3 and line from linept to linept+vect | 102 | BOOL LLLineSegmentBoxIntersect(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size) |
108 | //returns TRUE if intersecting and moves linept to the point of intersection | 103 | { |
109 | BOOL LLTriangleLineSegmentIntersect( const LLVector3& pt1, const LLVector3& pt2, const LLVector3& pt3, LLVector3& linept, const LLVector3& vect) | 104 | float fAWdU[3]; |
105 | LLVector3 dir; | ||
106 | LLVector3 diff; | ||
107 | |||
108 | for (U32 i = 0; i < 3; i++) | ||
109 | { | ||
110 | dir.mV[i] = 0.5f * (end.mV[i] - start.mV[i]); | ||
111 | diff.mV[i] = (0.5f * (end.mV[i] + start.mV[i])) - center.mV[i]; | ||
112 | fAWdU[i] = fabsf(dir.mV[i]); | ||
113 | if(fabsf(diff.mV[i])>size.mV[i] + fAWdU[i]) return false; | ||
114 | } | ||
115 | |||
116 | float f; | ||
117 | f = dir.mV[1] * diff.mV[2] - dir.mV[2] * diff.mV[1]; if(fabsf(f)>size.mV[1]*fAWdU[2] + size.mV[2]*fAWdU[1]) return false; | ||
118 | f = dir.mV[2] * diff.mV[0] - dir.mV[0] * diff.mV[2]; if(fabsf(f)>size.mV[0]*fAWdU[2] + size.mV[2]*fAWdU[0]) return false; | ||
119 | f = dir.mV[0] * diff.mV[1] - dir.mV[1] * diff.mV[0]; if(fabsf(f)>size.mV[0]*fAWdU[1] + size.mV[1]*fAWdU[0]) return false; | ||
120 | |||
121 | return true; | ||
122 | } | ||
123 | |||
124 | |||
125 | // intersect test between triangle vert0, vert1, vert2 and a ray from orig in direction dir. | ||
126 | // returns TRUE if intersecting and returns barycentric coordinates in intersection_a, intersection_b, | ||
127 | // and returns the intersection point along dir in intersection_t. | ||
128 | |||
129 | // Moller-Trumbore algorithm | ||
130 | BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, const LLVector3& vert2, const LLVector3& orig, const LLVector3& dir, | ||
131 | F32* intersection_a, F32* intersection_b, F32* intersection_t, BOOL two_sided) | ||
110 | { | 132 | { |
111 | LLVector3 V1 = pt2-pt1; | 133 | F32 u, v, t; |
112 | LLVector3 V2 = pt3-pt2; | ||
113 | 134 | ||
114 | LLVector3 norm = V1 % V2; | 135 | /* find vectors for two edges sharing vert0 */ |
136 | LLVector3 edge1 = vert1 - vert0; | ||
115 | 137 | ||
116 | F32 dotprod = norm * vect; | 138 | LLVector3 edge2 = vert2 - vert0;; |
117 | 139 | ||
118 | if(dotprod < 0) | 140 | /* begin calculating determinant - also used to calculate U parameter */ |
141 | LLVector3 pvec = dir % edge2; | ||
142 | |||
143 | /* if determinant is near zero, ray lies in plane of triangle */ | ||
144 | F32 det = edge1 * pvec; | ||
145 | |||
146 | if (!two_sided) | ||
119 | { | 147 | { |
120 | //Find point of intersect to triangle plane. | 148 | if (det < F_APPROXIMATELY_ZERO) |
121 | //find t to intersect point | 149 | { |
122 | F32 t = -(norm * (linept-pt1))/dotprod; | 150 | return FALSE; |
151 | } | ||
152 | |||
153 | /* calculate distance from vert0 to ray origin */ | ||
154 | LLVector3 tvec = orig - vert0; | ||
123 | 155 | ||
124 | // if ds is neg line started past triangle so can't hit triangle. | 156 | /* calculate U parameter and test bounds */ |
125 | if (t > 0) | 157 | u = tvec * pvec; |
158 | |||
159 | if (u < 0.f || u > det) | ||
126 | { | 160 | { |
127 | return FALSE; | 161 | return FALSE; |
128 | } | 162 | } |
129 | 163 | ||
130 | LLVector3 pt_int = linept + (vect*t); | 164 | /* prepare to test V parameter */ |
165 | LLVector3 qvec = tvec % edge1; | ||
131 | 166 | ||
132 | if(check_same_clock_dir(pt1, pt2, pt_int, norm)) | 167 | /* calculate V parameter and test bounds */ |
168 | v = dir * qvec; | ||
169 | if (v < 0.f || u + v > det) | ||
133 | { | 170 | { |
134 | if(check_same_clock_dir(pt2, pt3, pt_int, norm)) | 171 | return FALSE; |
172 | } | ||
173 | |||
174 | /* calculate t, scale parameters, ray intersects triangle */ | ||
175 | t = edge2 * qvec; | ||
176 | F32 inv_det = 1.0 / det; | ||
177 | t *= inv_det; | ||
178 | u *= inv_det; | ||
179 | v *= inv_det; | ||
180 | } | ||
181 | |||
182 | else // two sided | ||
135 | { | 183 | { |
136 | if(check_same_clock_dir(pt3, pt1, pt_int, norm)) | 184 | if (det > -F_APPROXIMATELY_ZERO && det < F_APPROXIMATELY_ZERO) |
137 | { | 185 | { |
138 | // answer in pt_int is insde triangle | 186 | return FALSE; |
139 | linept.setVec(pt_int); | ||
140 | return TRUE; | ||
141 | } | 187 | } |
188 | F32 inv_det = 1.0 / det; | ||
189 | |||
190 | /* calculate distance from vert0 to ray origin */ | ||
191 | LLVector3 tvec = orig - vert0; | ||
192 | |||
193 | /* calculate U parameter and test bounds */ | ||
194 | u = (tvec * pvec) * inv_det; | ||
195 | if (u < 0.f || u > 1.f) | ||
196 | { | ||
197 | return FALSE; | ||
142 | } | 198 | } |
199 | |||
200 | /* prepare to test V parameter */ | ||
201 | LLVector3 qvec = tvec - edge1; | ||
202 | |||
203 | /* calculate V parameter and test bounds */ | ||
204 | v = (dir * qvec) * inv_det; | ||
205 | |||
206 | if (v < 0.f || u + v > 1.f) | ||
207 | { | ||
208 | return FALSE; | ||
143 | } | 209 | } |
210 | |||
211 | /* calculate t, ray intersects triangle */ | ||
212 | t = (edge2 * qvec) * inv_det; | ||
144 | } | 213 | } |
145 | 214 | ||
146 | return FALSE; | 215 | if (intersection_a != NULL) |
216 | *intersection_a = u; | ||
217 | if (intersection_b != NULL) | ||
218 | *intersection_b = v; | ||
219 | if (intersection_t != NULL) | ||
220 | *intersection_t = t; | ||
221 | |||
222 | |||
223 | return TRUE; | ||
147 | } | 224 | } |
148 | 225 | ||
149 | 226 | ||
@@ -198,9 +275,6 @@ void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F3 | |||
198 | F32 t, t_step, t_first, t_fraction, ang, ang_step; | 275 | F32 t, t_step, t_first, t_fraction, ang, ang_step; |
199 | LLVector3 pt1,pt2; | 276 | LLVector3 pt1,pt2; |
200 | 277 | ||
201 | mMaxX = 0.f; | ||
202 | mMinX = 0.f; | ||
203 | |||
204 | F32 begin = params.getBegin(); | 278 | F32 begin = params.getBegin(); |
205 | F32 end = params.getEnd(); | 279 | F32 end = params.getEnd(); |
206 | 280 | ||
@@ -236,15 +310,6 @@ void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F3 | |||
236 | if (t_fraction < 0.9999f) | 310 | if (t_fraction < 0.9999f) |
237 | { | 311 | { |
238 | LLVector3 new_pt = lerp(pt1, pt2, t_fraction); | 312 | LLVector3 new_pt = lerp(pt1, pt2, t_fraction); |
239 | F32 pt_x = new_pt.mV[VX]; | ||
240 | if (pt_x < mMinX) | ||
241 | { | ||
242 | mMinX = pt_x; | ||
243 | } | ||
244 | else if (pt_x > mMaxX) | ||
245 | { | ||
246 | mMaxX = pt_x; | ||
247 | } | ||
248 | mProfile.push_back(new_pt); | 313 | mProfile.push_back(new_pt); |
249 | } | 314 | } |
250 | 315 | ||
@@ -254,16 +319,6 @@ void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F3 | |||
254 | // Iterate through all the integer steps of t. | 319 | // Iterate through all the integer steps of t. |
255 | pt1.setVec(cos(ang)*scale,sin(ang)*scale,t); | 320 | pt1.setVec(cos(ang)*scale,sin(ang)*scale,t); |
256 | 321 | ||
257 | F32 pt_x = pt1.mV[VX]; | ||
258 | if (pt_x < mMinX) | ||
259 | { | ||
260 | mMinX = pt_x; | ||
261 | } | ||
262 | else if (pt_x > mMaxX) | ||
263 | { | ||
264 | mMaxX = pt_x; | ||
265 | } | ||
266 | |||
267 | if (mProfile.size() > 0) { | 322 | if (mProfile.size() > 0) { |
268 | LLVector3 p = mProfile[mProfile.size()-1]; | 323 | LLVector3 p = mProfile[mProfile.size()-1]; |
269 | for (S32 i = 0; i < split && mProfile.size() > 0; i++) { | 324 | for (S32 i = 0; i < split && mProfile.size() > 0; i++) { |
@@ -287,15 +342,6 @@ void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F3 | |||
287 | if (t_fraction > 0.0001f) | 342 | if (t_fraction > 0.0001f) |
288 | { | 343 | { |
289 | LLVector3 new_pt = lerp(pt1, pt2, t_fraction); | 344 | LLVector3 new_pt = lerp(pt1, pt2, t_fraction); |
290 | F32 pt_x = new_pt.mV[VX]; | ||
291 | if (pt_x < mMinX) | ||
292 | { | ||
293 | mMinX = pt_x; | ||
294 | } | ||
295 | else if (pt_x > mMaxX) | ||
296 | { | ||
297 | mMaxX = pt_x; | ||
298 | } | ||
299 | 345 | ||
300 | if (mProfile.size() > 0) { | 346 | if (mProfile.size() > 0) { |
301 | LLVector3 p = mProfile[mProfile.size()-1]; | 347 | LLVector3 p = mProfile[mProfile.size()-1]; |
@@ -472,31 +518,9 @@ LLProfile::Face* LLProfile::addHole(const LLProfileParams& params, BOOL flat, F3 | |||
472 | } | 518 | } |
473 | 519 | ||
474 | 520 | ||
475 | S32 sculpt_sides(F32 detail) | ||
476 | { | ||
477 | |||
478 | // detail is usually one of: 1, 1.5, 2.5, 4.0. | ||
479 | |||
480 | if (detail <= 1.0) | ||
481 | { | ||
482 | return SCULPT_REZ_1; | ||
483 | } | ||
484 | if (detail <= 2.0) | ||
485 | { | ||
486 | return SCULPT_REZ_2; | ||
487 | } | ||
488 | if (detail <= 3.0) | ||
489 | { | ||
490 | return SCULPT_REZ_3; | ||
491 | } | ||
492 | else | ||
493 | { | ||
494 | return SCULPT_REZ_4; | ||
495 | } | ||
496 | } | ||
497 | |||
498 | 521 | ||
499 | BOOL LLProfile::generate(const LLProfileParams& params, BOOL path_open,F32 detail, S32 split, BOOL is_sculpted) | 522 | BOOL LLProfile::generate(const LLProfileParams& params, BOOL path_open,F32 detail, S32 split, |
523 | BOOL is_sculpted, S32 sculpt_size) | ||
500 | { | 524 | { |
501 | LLMemType m1(LLMemType::MTYPE_VOLUME); | 525 | LLMemType m1(LLMemType::MTYPE_VOLUME); |
502 | 526 | ||
@@ -640,7 +664,7 @@ BOOL LLProfile::generate(const LLProfileParams& params, BOOL path_open,F32 detai | |||
640 | S32 sides = (S32)circle_detail; | 664 | S32 sides = (S32)circle_detail; |
641 | 665 | ||
642 | if (is_sculpted) | 666 | if (is_sculpted) |
643 | sides = sculpt_sides(detail); | 667 | sides = sculpt_size; |
644 | 668 | ||
645 | genNGon(params, sides); | 669 | genNGon(params, sides); |
646 | 670 | ||
@@ -1131,7 +1155,8 @@ const LLVector2 LLPathParams::getEndScale() const | |||
1131 | return end_scale; | 1155 | return end_scale; |
1132 | } | 1156 | } |
1133 | 1157 | ||
1134 | BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split, BOOL is_sculpted) | 1158 | BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split, |
1159 | BOOL is_sculpted, S32 sculpt_size) | ||
1135 | { | 1160 | { |
1136 | LLMemType m1(LLMemType::MTYPE_VOLUME); | 1161 | LLMemType m1(LLMemType::MTYPE_VOLUME); |
1137 | 1162 | ||
@@ -1194,7 +1219,7 @@ BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split, BOOL is | |||
1194 | S32 sides = (S32)llfloor(llfloor((MIN_DETAIL_FACES * detail + twist_mag * 3.5f * (detail-0.5f))) * params.getRevolutions()); | 1219 | S32 sides = (S32)llfloor(llfloor((MIN_DETAIL_FACES * detail + twist_mag * 3.5f * (detail-0.5f))) * params.getRevolutions()); |
1195 | 1220 | ||
1196 | if (is_sculpted) | 1221 | if (is_sculpted) |
1197 | sides = sculpt_sides(detail); | 1222 | sides = sculpt_size; |
1198 | 1223 | ||
1199 | genNGon(params, sides); | 1224 | genNGon(params, sides); |
1200 | } | 1225 | } |
@@ -1259,7 +1284,8 @@ BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split, BOOL is | |||
1259 | return TRUE; | 1284 | return TRUE; |
1260 | } | 1285 | } |
1261 | 1286 | ||
1262 | BOOL LLDynamicPath::generate(const LLPathParams& params, F32 detail, S32 split, BOOL is_sculpted) | 1287 | BOOL LLDynamicPath::generate(const LLPathParams& params, F32 detail, S32 split, |
1288 | BOOL is_sculpted, S32 sculpt_size) | ||
1263 | { | 1289 | { |
1264 | LLMemType m1(LLMemType::MTYPE_VOLUME); | 1290 | LLMemType m1(LLMemType::MTYPE_VOLUME); |
1265 | 1291 | ||
@@ -1979,6 +2005,12 @@ void LLVolume::sculptGeneratePlaceholder() | |||
1979 | // create the vertices from the map | 2005 | // create the vertices from the map |
1980 | void LLVolume::sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type) | 2006 | void LLVolume::sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type) |
1981 | { | 2007 | { |
2008 | U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK; | ||
2009 | BOOL sculpt_invert = sculpt_type & LL_SCULPT_FLAG_INVERT; | ||
2010 | BOOL sculpt_mirror = sculpt_type & LL_SCULPT_FLAG_MIRROR; | ||
2011 | BOOL reverse_horizontal = (sculpt_invert ? !sculpt_mirror : sculpt_mirror); // XOR | ||
2012 | |||
2013 | |||
1982 | LLMemType m1(LLMemType::MTYPE_VOLUME); | 2014 | LLMemType m1(LLMemType::MTYPE_VOLUME); |
1983 | 2015 | ||
1984 | S32 sizeS = mPathp->mPath.size(); | 2016 | S32 sizeS = mPathp->mPath.size(); |
@@ -1993,13 +2025,21 @@ void LLVolume::sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 | |||
1993 | S32 i = t + line; | 2025 | S32 i = t + line; |
1994 | Point& pt = mMesh[i]; | 2026 | Point& pt = mMesh[i]; |
1995 | 2027 | ||
1996 | U32 x = (U32) ((F32)t/(sizeT-1) * (F32) sculpt_width); | 2028 | S32 reversed_t = t; |
2029 | |||
2030 | if (reverse_horizontal) | ||
2031 | { | ||
2032 | reversed_t = sizeT - t - 1; | ||
2033 | } | ||
2034 | |||
2035 | U32 x = (U32) ((F32)reversed_t/(sizeT-1) * (F32) sculpt_width); | ||
1997 | U32 y = (U32) ((F32)s/(sizeS-1) * (F32) sculpt_height); | 2036 | U32 y = (U32) ((F32)s/(sizeS-1) * (F32) sculpt_height); |
1998 | 2037 | ||
2038 | |||
1999 | if (y == 0) // top row stitching | 2039 | if (y == 0) // top row stitching |
2000 | { | 2040 | { |
2001 | // pinch? | 2041 | // pinch? |
2002 | if (sculpt_type == LL_SCULPT_TYPE_SPHERE) | 2042 | if (sculpt_stitching == LL_SCULPT_TYPE_SPHERE) |
2003 | { | 2043 | { |
2004 | x = sculpt_width / 2; | 2044 | x = sculpt_width / 2; |
2005 | } | 2045 | } |
@@ -2008,7 +2048,7 @@ void LLVolume::sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 | |||
2008 | if (y == sculpt_height) // bottom row stitching | 2048 | if (y == sculpt_height) // bottom row stitching |
2009 | { | 2049 | { |
2010 | // wrap? | 2050 | // wrap? |
2011 | if (sculpt_type == LL_SCULPT_TYPE_TORUS) | 2051 | if (sculpt_stitching == LL_SCULPT_TYPE_TORUS) |
2012 | { | 2052 | { |
2013 | y = 0; | 2053 | y = 0; |
2014 | } | 2054 | } |
@@ -2018,7 +2058,7 @@ void LLVolume::sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 | |||
2018 | } | 2058 | } |
2019 | 2059 | ||
2020 | // pinch? | 2060 | // pinch? |
2021 | if (sculpt_type == LL_SCULPT_TYPE_SPHERE) | 2061 | if (sculpt_stitching == LL_SCULPT_TYPE_SPHERE) |
2022 | { | 2062 | { |
2023 | x = sculpt_width / 2; | 2063 | x = sculpt_width / 2; |
2024 | } | 2064 | } |
@@ -2027,9 +2067,9 @@ void LLVolume::sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 | |||
2027 | if (x == sculpt_width) // side stitching | 2067 | if (x == sculpt_width) // side stitching |
2028 | { | 2068 | { |
2029 | // wrap? | 2069 | // wrap? |
2030 | if ((sculpt_type == LL_SCULPT_TYPE_SPHERE) || | 2070 | if ((sculpt_stitching == LL_SCULPT_TYPE_SPHERE) || |
2031 | (sculpt_type == LL_SCULPT_TYPE_TORUS) || | 2071 | (sculpt_stitching == LL_SCULPT_TYPE_TORUS) || |
2032 | (sculpt_type == LL_SCULPT_TYPE_CYLINDER)) | 2072 | (sculpt_stitching == LL_SCULPT_TYPE_CYLINDER)) |
2033 | { | 2073 | { |
2034 | x = 0; | 2074 | x = 0; |
2035 | } | 2075 | } |
@@ -2041,12 +2081,69 @@ void LLVolume::sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 | |||
2041 | } | 2081 | } |
2042 | 2082 | ||
2043 | pt.mPos = sculpt_xy_to_vector(x, y, sculpt_width, sculpt_height, sculpt_components, sculpt_data); | 2083 | pt.mPos = sculpt_xy_to_vector(x, y, sculpt_width, sculpt_height, sculpt_components, sculpt_data); |
2084 | |||
2085 | if (sculpt_mirror) | ||
2086 | { | ||
2087 | pt.mPos.mV[VX] *= -1.f; | ||
2088 | } | ||
2044 | } | 2089 | } |
2090 | |||
2045 | line += sizeT; | 2091 | line += sizeT; |
2046 | } | 2092 | } |
2047 | } | 2093 | } |
2048 | 2094 | ||
2049 | 2095 | ||
2096 | const S32 SCULPT_REZ_1 = 6; // changed from 4 to 6 - 6 looks round whereas 4 looks square | ||
2097 | const S32 SCULPT_REZ_2 = 8; | ||
2098 | const S32 SCULPT_REZ_3 = 16; | ||
2099 | const S32 SCULPT_REZ_4 = 32; | ||
2100 | |||
2101 | S32 sculpt_sides(F32 detail) | ||
2102 | { | ||
2103 | |||
2104 | // detail is usually one of: 1, 1.5, 2.5, 4.0. | ||
2105 | |||
2106 | if (detail <= 1.0) | ||
2107 | { | ||
2108 | return SCULPT_REZ_1; | ||
2109 | } | ||
2110 | if (detail <= 2.0) | ||
2111 | { | ||
2112 | return SCULPT_REZ_2; | ||
2113 | } | ||
2114 | if (detail <= 3.0) | ||
2115 | { | ||
2116 | return SCULPT_REZ_3; | ||
2117 | } | ||
2118 | else | ||
2119 | { | ||
2120 | return SCULPT_REZ_4; | ||
2121 | } | ||
2122 | } | ||
2123 | |||
2124 | |||
2125 | |||
2126 | // determine the number of vertices in both s and t direction for this sculpt | ||
2127 | void sculpt_calc_mesh_resolution(U16 width, U16 height, U8 type, F32 detail, S32& s, S32& t) | ||
2128 | { | ||
2129 | S32 vertices = sculpt_sides(detail); | ||
2130 | |||
2131 | F32 ratio; | ||
2132 | if ((width == 0) || (height == 0)) | ||
2133 | ratio = 1.f; | ||
2134 | else | ||
2135 | ratio = (F32) width / (F32) height; | ||
2136 | |||
2137 | |||
2138 | s = (S32)(vertices / fsqrtf(ratio)); | ||
2139 | |||
2140 | s = llmax(s, 3); // no degenerate sizes, please | ||
2141 | t = vertices * vertices / s; | ||
2142 | |||
2143 | t = llmax(t, 3); // no degenerate sizes, please | ||
2144 | s = vertices * vertices / t; | ||
2145 | } | ||
2146 | |||
2050 | // sculpt replaces generate() for sculpted surfaces | 2147 | // sculpt replaces generate() for sculpted surfaces |
2051 | void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level) | 2148 | void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level) |
2052 | { | 2149 | { |
@@ -2061,11 +2158,16 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, | |||
2061 | data_is_empty = TRUE; | 2158 | data_is_empty = TRUE; |
2062 | } | 2159 | } |
2063 | 2160 | ||
2064 | mPathp->generate(mParams.getPathParams(), mDetail, 0, TRUE); | 2161 | S32 requested_sizeS = 0; |
2065 | mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(), mDetail, 0, TRUE); | 2162 | S32 requested_sizeT = 0; |
2066 | 2163 | ||
2067 | S32 sizeS = mPathp->mPath.size(); | 2164 | sculpt_calc_mesh_resolution(sculpt_width, sculpt_height, sculpt_type, mDetail, requested_sizeS, requested_sizeT); |
2068 | S32 sizeT = mProfilep->mProfile.size(); | 2165 | |
2166 | mPathp->generate(mParams.getPathParams(), mDetail, 0, TRUE, requested_sizeS); | ||
2167 | mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(), mDetail, 0, TRUE, requested_sizeT); | ||
2168 | |||
2169 | S32 sizeS = mPathp->mPath.size(); // we requested a specific size, now see what we really got | ||
2170 | S32 sizeT = mProfilep->mProfile.size(); // we requested a specific size, now see what we really got | ||
2069 | 2171 | ||
2070 | // weird crash bug - DEV-11158 - trying to collect more data: | 2172 | // weird crash bug - DEV-11158 - trying to collect more data: |
2071 | if ((sizeS == 0) || (sizeT == 0)) | 2173 | if ((sizeS == 0) || (sizeT == 0)) |
@@ -3405,47 +3507,99 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices, | |||
3405 | } | 3507 | } |
3406 | } | 3508 | } |
3407 | 3509 | ||
3408 | S32 LLVolume::lineSegmentIntersect(const LLVector3& start, LLVector3& end) const | 3510 | S32 LLVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, |
3511 | S32 face, | ||
3512 | LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal) | ||
3409 | { | 3513 | { |
3410 | S32 ret = -1; | 3514 | S32 hit_face = -1; |
3411 | 3515 | ||
3412 | LLVector3 vec = end - start; | 3516 | S32 start_face; |
3517 | S32 end_face; | ||
3413 | 3518 | ||
3414 | for (S32 i = 0; i < getNumFaces(); i++) | 3519 | if (face == -1) // ALL_SIDES |
3415 | { | 3520 | { |
3416 | const LLVolumeFace& face = getVolumeFace(i); | 3521 | start_face = 0; |
3522 | end_face = getNumFaces() - 1; | ||
3523 | } | ||
3524 | else | ||
3525 | { | ||
3526 | start_face = face; | ||
3527 | end_face = face; | ||
3528 | } | ||
3529 | |||
3530 | LLVector3 dir = end - start; | ||
3531 | |||
3532 | F32 closest_t = 2.f; // must be larger than 1 | ||
3533 | |||
3534 | for (S32 i = start_face; i <= end_face; i++) | ||
3535 | { | ||
3536 | const LLVolumeFace &face = getVolumeFace((U32)i); | ||
3537 | |||
3538 | LLVector3 box_center = (face.mExtents[0] + face.mExtents[1]) / 2.f; | ||
3539 | LLVector3 box_size = face.mExtents[1] - face.mExtents[0]; | ||
3540 | |||
3541 | if (LLLineSegmentBoxIntersect(start, end, box_center, box_size)) | ||
3542 | { | ||
3543 | if (bi_normal != NULL) // if the caller wants binormals, we may need to generate them | ||
3544 | { | ||
3545 | genBinormals(i); | ||
3546 | } | ||
3547 | |||
3548 | for (U32 tri = 0; tri < face.mIndices.size()/3; tri++) | ||
3549 | { | ||
3550 | S32 index1 = face.mIndices[tri*3+0]; | ||
3551 | S32 index2 = face.mIndices[tri*3+1]; | ||
3552 | S32 index3 = face.mIndices[tri*3+2]; | ||
3417 | 3553 | ||
3418 | for (U32 j = 0; j < face.mIndices.size()/3; j++) | 3554 | F32 a, b, t; |
3555 | |||
3556 | if (LLTriangleRayIntersect(face.mVertices[index1].mPosition, | ||
3557 | face.mVertices[index2].mPosition, | ||
3558 | face.mVertices[index3].mPosition, | ||
3559 | start, dir, &a, &b, &t, FALSE)) | ||
3560 | { | ||
3561 | if ((t >= 0.f) && // if hit is after start | ||
3562 | (t <= 1.f) && // and before end | ||
3563 | (t < closest_t)) // and this hit is closer | ||
3419 | { | 3564 | { |
3420 | //approximate normal | 3565 | closest_t = t; |
3421 | S32 v1 = face.mIndices[j*3+0]; | 3566 | hit_face = i; |
3422 | S32 v2 = face.mIndices[j*3+1]; | ||
3423 | S32 v3 = face.mIndices[j*3+2]; | ||
3424 | 3567 | ||
3425 | LLVector3 norm = (face.mVertices[v2].mPosition - face.mVertices[v1].mPosition) % | 3568 | if (intersection != NULL) |
3426 | (face.mVertices[v3].mPosition - face.mVertices[v2].mPosition); | 3569 | { |
3570 | *intersection = start + dir * closest_t; | ||
3571 | } | ||
3427 | 3572 | ||
3428 | if (norm.magVecSquared() >= 0.00000001f) | 3573 | if (tex_coord != NULL) |
3429 | { | 3574 | { |
3430 | //get view vector | 3575 | *tex_coord = ((1.f - a - b) * face.mVertices[index1].mTexCoord + |
3431 | //LLVector3 view = (start-face.mVertices[v1].mPosition); | 3576 | a * face.mVertices[index2].mTexCoord + |
3432 | //if (view * norm < 0.0f) | 3577 | b * face.mVertices[index3].mTexCoord); |
3578 | |||
3579 | } | ||
3580 | |||
3581 | if (normal != NULL) | ||
3433 | { | 3582 | { |
3434 | if (LLTriangleLineSegmentIntersect( face.mVertices[v1].mPosition, | 3583 | *normal = ((1.f - a - b) * face.mVertices[index1].mNormal + |
3435 | face.mVertices[v2].mPosition, | 3584 | a * face.mVertices[index2].mNormal + |
3436 | face.mVertices[v3].mPosition, | 3585 | b * face.mVertices[index3].mNormal); |
3437 | end, | 3586 | } |
3438 | vec)) | 3587 | |
3588 | if (bi_normal != NULL) | ||
3439 | { | 3589 | { |
3440 | vec = end-start; | 3590 | *bi_normal = ((1.f - a - b) * face.mVertices[index1].mBinormal + |
3441 | ret = (S32) i; | 3591 | a * face.mVertices[index2].mBinormal + |
3592 | b * face.mVertices[index3].mBinormal); | ||
3593 | } | ||
3594 | |||
3442 | } | 3595 | } |
3443 | } | 3596 | } |
3444 | } | 3597 | } |
3445 | } | 3598 | } |
3446 | } | 3599 | } |
3447 | 3600 | ||
3448 | return ret; | 3601 | |
3602 | return hit_face; | ||
3449 | } | 3603 | } |
3450 | 3604 | ||
3451 | class LLVertexIndexPair | 3605 | class LLVertexIndexPair |
@@ -4768,6 +4922,13 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) | |||
4768 | LLMemType m1(LLMemType::MTYPE_VOLUME); | 4922 | LLMemType m1(LLMemType::MTYPE_VOLUME); |
4769 | 4923 | ||
4770 | BOOL flat = mTypeMask & FLAT_MASK; | 4924 | BOOL flat = mTypeMask & FLAT_MASK; |
4925 | |||
4926 | U8 sculpt_type = volume->getParams().getSculptType(); | ||
4927 | U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK; | ||
4928 | BOOL sculpt_invert = sculpt_type & LL_SCULPT_FLAG_INVERT; | ||
4929 | BOOL sculpt_mirror = sculpt_type & LL_SCULPT_FLAG_MIRROR; | ||
4930 | BOOL sculpt_reverse_horizontal = (sculpt_invert ? !sculpt_mirror : sculpt_mirror); // XOR | ||
4931 | |||
4771 | S32 num_vertices, num_indices; | 4932 | S32 num_vertices, num_indices; |
4772 | 4933 | ||
4773 | const std::vector<LLVolume::Point>& mesh = volume->getMesh(); | 4934 | const std::vector<LLVolume::Point>& mesh = volume->getMesh(); |
@@ -4834,6 +4995,11 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) | |||
4834 | } | 4995 | } |
4835 | } | 4996 | } |
4836 | 4997 | ||
4998 | if (sculpt_reverse_horizontal) | ||
4999 | { | ||
5000 | ss = 1.f - ss; | ||
5001 | } | ||
5002 | |||
4837 | // Check to see if this triangle wraps around the array. | 5003 | // Check to see if this triangle wraps around the array. |
4838 | if (mBeginS + s >= max_s) | 5004 | if (mBeginS + s >= max_s) |
4839 | { | 5005 | { |
@@ -4995,9 +5161,7 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) | |||
4995 | 5161 | ||
4996 | BOOL s_bottom_converges = ((mVertices[0].mPosition - mVertices[mNumS*(mNumT-2)].mPosition).magVecSquared() < 0.000001f); | 5162 | BOOL s_bottom_converges = ((mVertices[0].mPosition - mVertices[mNumS*(mNumT-2)].mPosition).magVecSquared() < 0.000001f); |
4997 | BOOL s_top_converges = ((mVertices[mNumS-1].mPosition - mVertices[mNumS*(mNumT-2)+mNumS-1].mPosition).magVecSquared() < 0.000001f); | 5163 | BOOL s_top_converges = ((mVertices[mNumS-1].mPosition - mVertices[mNumS*(mNumT-2)+mNumS-1].mPosition).magVecSquared() < 0.000001f); |
4998 | U8 sculpt_type = volume->getParams().getSculptType(); | 5164 | if (sculpt_stitching == LL_SCULPT_TYPE_NONE) // logic for non-sculpt volumes |
4999 | |||
5000 | if (sculpt_type == LL_SCULPT_TYPE_NONE) // logic for non-sculpt volumes | ||
5001 | { | 5165 | { |
5002 | if (volume->getPath().isOpen() == FALSE) | 5166 | if (volume->getPath().isOpen() == FALSE) |
5003 | { //wrap normals on T | 5167 | { //wrap normals on T |
@@ -5046,15 +5210,15 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) | |||
5046 | BOOL wrap_s = FALSE; | 5210 | BOOL wrap_s = FALSE; |
5047 | BOOL wrap_t = FALSE; | 5211 | BOOL wrap_t = FALSE; |
5048 | 5212 | ||
5049 | if (sculpt_type == LL_SCULPT_TYPE_SPHERE) | 5213 | if (sculpt_stitching == LL_SCULPT_TYPE_SPHERE) |
5050 | average_poles = TRUE; | 5214 | average_poles = TRUE; |
5051 | 5215 | ||
5052 | if ((sculpt_type == LL_SCULPT_TYPE_SPHERE) || | 5216 | if ((sculpt_stitching == LL_SCULPT_TYPE_SPHERE) || |
5053 | (sculpt_type == LL_SCULPT_TYPE_TORUS) || | 5217 | (sculpt_stitching == LL_SCULPT_TYPE_TORUS) || |
5054 | (sculpt_type == LL_SCULPT_TYPE_CYLINDER)) | 5218 | (sculpt_stitching == LL_SCULPT_TYPE_CYLINDER)) |
5055 | wrap_s = TRUE; | 5219 | wrap_s = TRUE; |
5056 | 5220 | ||
5057 | if (sculpt_type == LL_SCULPT_TYPE_TORUS) | 5221 | if (sculpt_stitching == LL_SCULPT_TYPE_TORUS) |
5058 | wrap_t = TRUE; | 5222 | wrap_t = TRUE; |
5059 | 5223 | ||
5060 | 5224 | ||