aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llmath/llvolume.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-09-06 18:24:57 -0500
committerJacek Antonelli2008-09-06 18:25:07 -0500
commit798d367d54a6c6379ad355bd8345fa40e31e7fe9 (patch)
tree1921f1708cd0240648c97bc02df2c2ab5f2fc41e /linden/indra/llmath/llvolume.cpp
parentSecond Life viewer sources 1.20.15 (diff)
downloadmeta-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.cpp420
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;
82const F32 SKEW_MIN = -0.95f; 82const F32 SKEW_MIN = -0.95f;
83const F32 SKEW_MAX = 0.95f; 83const F32 SKEW_MAX = 0.95f;
84 84
85const S32 SCULPT_REZ_1 = 6; // changed from 4 to 6 - 6 looks round whereas 4 looks square
86const S32 SCULPT_REZ_2 = 8;
87const S32 SCULPT_REZ_3 = 16;
88const S32 SCULPT_REZ_4 = 32;
89
90const F32 SCULPT_MIN_AREA = 0.002f; 85const F32 SCULPT_MIN_AREA = 0.002f;
91 86
92BOOL check_same_clock_dir( const LLVector3& pt1, const LLVector3& pt2, const LLVector3& pt3, const LLVector3& norm) 87BOOL 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 102BOOL 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{
109BOOL 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
130BOOL 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
475S32 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
499BOOL LLProfile::generate(const LLProfileParams& params, BOOL path_open,F32 detail, S32 split, BOOL is_sculpted) 522BOOL 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
1134BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split, BOOL is_sculpted) 1158BOOL 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
1262BOOL LLDynamicPath::generate(const LLPathParams& params, F32 detail, S32 split, BOOL is_sculpted) 1287BOOL 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
1980void LLVolume::sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type) 2006void 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
2096const S32 SCULPT_REZ_1 = 6; // changed from 4 to 6 - 6 looks round whereas 4 looks square
2097const S32 SCULPT_REZ_2 = 8;
2098const S32 SCULPT_REZ_3 = 16;
2099const S32 SCULPT_REZ_4 = 32;
2100
2101S32 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
2127void 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
2051void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level) 2148void 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
3408S32 LLVolume::lineSegmentIntersect(const LLVector3& start, LLVector3& end) const 3510S32 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
3451class LLVertexIndexPair 3605class 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