diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llface.cpp | |
parent | README.txt (diff) | |
download | meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2 meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz |
Second Life viewer sources 1.13.2.12
Diffstat (limited to '')
-rw-r--r-- | linden/indra/newview/llface.cpp | 1958 |
1 files changed, 1958 insertions, 0 deletions
diff --git a/linden/indra/newview/llface.cpp b/linden/indra/newview/llface.cpp new file mode 100644 index 0000000..a6de94b --- /dev/null +++ b/linden/indra/newview/llface.cpp | |||
@@ -0,0 +1,1958 @@ | |||
1 | /** | ||
2 | * @file llface.cpp | ||
3 | * @brief LLFace class implementation | ||
4 | * | ||
5 | * Copyright (c) 2001-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
8 | * to you under the terms of the GNU General Public License, version 2.0 | ||
9 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
10 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
11 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
12 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
13 | * | ||
14 | * There are special exceptions to the terms and conditions of the GPL as | ||
15 | * it is applied to this Source Code. View the full text of the exception | ||
16 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
17 | * online at http://secondlife.com/developers/opensource/flossexception | ||
18 | * | ||
19 | * By copying, modifying or distributing this software, you acknowledge | ||
20 | * that you have read and understood your obligations described above, | ||
21 | * and agree to abide by those obligations. | ||
22 | * | ||
23 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
24 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
25 | * COMPLETENESS OR PERFORMANCE. | ||
26 | */ | ||
27 | |||
28 | #include "llviewerprecompiledheaders.h" | ||
29 | |||
30 | #include "lldrawable.h" // lldrawable needs to be included before llface | ||
31 | #include "llface.h" | ||
32 | |||
33 | #include "llviewercontrol.h" | ||
34 | #include "llvolume.h" | ||
35 | #include "m3math.h" | ||
36 | #include "v3color.h" | ||
37 | |||
38 | #include "llagparray.h" | ||
39 | #include "lldrawpoolsimple.h" | ||
40 | #include "lldrawpoolbump.h" | ||
41 | #include "llgl.h" | ||
42 | #include "lllightconstants.h" | ||
43 | #include "llsky.h" | ||
44 | #include "llviewercamera.h" | ||
45 | #include "llviewerimagelist.h" | ||
46 | #include "llvosky.h" | ||
47 | #include "llvovolume.h" | ||
48 | #include "pipeline.h" | ||
49 | |||
50 | #include "llagparray.inl" | ||
51 | |||
52 | #define LL_MAX_INDICES_COUNT 1000000 | ||
53 | |||
54 | extern BOOL gPickFaces; | ||
55 | |||
56 | BOOL LLFace::sSafeRenderSelect = TRUE; // FALSE | ||
57 | |||
58 | #define DOTVEC(a,b) (a.mV[0]*b.mV[0] + a.mV[1]*b.mV[1] + a.mV[2]*b.mV[2]) | ||
59 | |||
60 | |||
61 | /* | ||
62 | For each vertex, given: | ||
63 | B - binormal | ||
64 | T - tangent | ||
65 | N - normal | ||
66 | P - position | ||
67 | |||
68 | The resulting texture coordinate <u,v> is: | ||
69 | |||
70 | u = 2(B dot P) | ||
71 | v = 2(T dot P) | ||
72 | */ | ||
73 | void planarProjection(LLVector2 &tc, const LLVolumeFace::VertexData &vd, const LLVector3 &mCenter, const LLVector3& vec) | ||
74 | { //DONE! | ||
75 | LLVector3 binormal; | ||
76 | float d = vd.mNormal * LLVector3(1,0,0); | ||
77 | if (d >= 0.5f || d <= -0.5f) | ||
78 | { | ||
79 | binormal = LLVector3(0,1,0); | ||
80 | if (vd.mNormal.mV[0] < 0) | ||
81 | { | ||
82 | binormal = -binormal; | ||
83 | } | ||
84 | } | ||
85 | else | ||
86 | { | ||
87 | binormal = LLVector3(1,0,0); | ||
88 | if (vd.mNormal.mV[1] > 0) | ||
89 | { | ||
90 | binormal = -binormal; | ||
91 | } | ||
92 | } | ||
93 | LLVector3 tangent = binormal % vd.mNormal; | ||
94 | |||
95 | tc.mV[1] = -((tangent*vec)*2 - 0.5f); | ||
96 | tc.mV[0] = 1.0f+((binormal*vec)*2 - 0.5f); | ||
97 | } | ||
98 | |||
99 | void sphericalProjection(LLVector2 &tc, const LLVolumeFace::VertexData &vd, const LLVector3 &mCenter, const LLVector3& vec) | ||
100 | { //BROKEN | ||
101 | /*tc.mV[0] = acosf(vd.mNormal * LLVector3(1,0,0))/3.14159f; | ||
102 | |||
103 | tc.mV[1] = acosf(vd.mNormal * LLVector3(0,0,1))/6.284f; | ||
104 | if (vd.mNormal.mV[1] > 0) | ||
105 | { | ||
106 | tc.mV[1] = 1.0f-tc.mV[1]; | ||
107 | }*/ | ||
108 | } | ||
109 | |||
110 | void cylindricalProjection(LLVector2 &tc, const LLVolumeFace::VertexData &vd, const LLVector3 &mCenter, const LLVector3& vec) | ||
111 | { //BROKEN | ||
112 | /*LLVector3 binormal; | ||
113 | float d = vd.mNormal * LLVector3(1,0,0); | ||
114 | if (d >= 0.5f || d <= -0.5f) | ||
115 | { | ||
116 | binormal = LLVector3(0,1,0); | ||
117 | } | ||
118 | else{ | ||
119 | binormal = LLVector3(1,0,0); | ||
120 | } | ||
121 | LLVector3 tangent = binormal % vd.mNormal; | ||
122 | |||
123 | tc.mV[1] = -((tangent*vec)*2 - 0.5f); | ||
124 | |||
125 | tc.mV[0] = acosf(vd.mNormal * LLVector3(1,0,0))/6.284f; | ||
126 | |||
127 | if (vd.mNormal.mV[1] < 0) | ||
128 | { | ||
129 | tc.mV[0] = 1.0f-tc.mV[0]; | ||
130 | }*/ | ||
131 | } | ||
132 | |||
133 | //////////////////// | ||
134 | // | ||
135 | // LLFace implementation | ||
136 | // | ||
137 | |||
138 | void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) | ||
139 | { | ||
140 | mGeneration = DIRTY; | ||
141 | mState = GLOBAL; | ||
142 | mDrawPoolp = NULL; | ||
143 | mGeomIndex = -1; | ||
144 | mSkipRender = FALSE; | ||
145 | mNextFace = NULL; | ||
146 | // mCenterLocal | ||
147 | // mCenterAgent | ||
148 | mDistance = 0.f; | ||
149 | |||
150 | mPrimType = LLTriangles; | ||
151 | mGeomCount = 0; | ||
152 | mIndicesCount = 0; | ||
153 | mIndicesIndex = -1; | ||
154 | mTexture = NULL; | ||
155 | mTEOffset = -1; | ||
156 | |||
157 | mBackupMem = NULL; | ||
158 | |||
159 | setDrawable(drawablep); | ||
160 | mVObjp = objp; | ||
161 | |||
162 | mReferenceIndex = -1; | ||
163 | mAlphaFade = 0.f; | ||
164 | |||
165 | mFaceColor = LLColor4(1,0,0,1); | ||
166 | } | ||
167 | |||
168 | |||
169 | void LLFace::destroy() | ||
170 | { | ||
171 | mDrawablep = NULL; | ||
172 | mVObjp = NULL; | ||
173 | |||
174 | if (mDrawPoolp) | ||
175 | { | ||
176 | mDrawPoolp->removeFace(this); | ||
177 | mDrawPoolp = NULL; | ||
178 | } | ||
179 | |||
180 | // Remove light and blocker list references | ||
181 | |||
182 | delete[] mBackupMem; | ||
183 | mBackupMem = NULL; | ||
184 | } | ||
185 | |||
186 | |||
187 | // static | ||
188 | void LLFace::initClass() | ||
189 | { | ||
190 | } | ||
191 | |||
192 | void LLFace::setWorldMatrix(const LLMatrix4 &mat) | ||
193 | { | ||
194 | llerrs << "Faces on this drawable are not independently modifiable\n" << llendl; | ||
195 | } | ||
196 | |||
197 | |||
198 | void LLFace::setDirty() | ||
199 | { | ||
200 | mGeneration = DIRTY; | ||
201 | } | ||
202 | |||
203 | void LLFace::setPool(LLDrawPool* new_pool, LLViewerImage *texturep) | ||
204 | { | ||
205 | LLMemType mt1(LLMemType::MTYPE_DRAWABLE); | ||
206 | |||
207 | if (!new_pool) | ||
208 | { | ||
209 | llerrs << "Setting pool to null!" << llendl; | ||
210 | } | ||
211 | |||
212 | if (new_pool != mDrawPoolp) | ||
213 | { | ||
214 | // Remove from old pool | ||
215 | if (mDrawPoolp) | ||
216 | { | ||
217 | mDrawPoolp->removeFace(this); | ||
218 | mSkipRender = FALSE; | ||
219 | mNextFace = NULL; | ||
220 | |||
221 | // Invalidate geometry (will get rebuilt next frame) | ||
222 | setDirty(); | ||
223 | if (mDrawablep) | ||
224 | { | ||
225 | gPipeline.markRebuild(mDrawablep, LLDrawable::REBUILD_ALL, TRUE); | ||
226 | } | ||
227 | } | ||
228 | if (isState(BACKLIST)) | ||
229 | { | ||
230 | delete[] mBackupMem; | ||
231 | mBackupMem = NULL; | ||
232 | clearState(BACKLIST); | ||
233 | } | ||
234 | mGeomIndex = -1; | ||
235 | |||
236 | // Add to new pool | ||
237 | if (new_pool) | ||
238 | { | ||
239 | new_pool->addFace(this); | ||
240 | } | ||
241 | mDrawPoolp = new_pool; | ||
242 | |||
243 | } | ||
244 | mTexture = texturep; | ||
245 | } | ||
246 | |||
247 | |||
248 | void LLFace::setTEOffset(const S32 te_offset) | ||
249 | { | ||
250 | mTEOffset = te_offset; | ||
251 | } | ||
252 | |||
253 | |||
254 | void LLFace::setFaceColor(const LLColor4& color) | ||
255 | { | ||
256 | mFaceColor = color; | ||
257 | setState(USE_FACE_COLOR); | ||
258 | } | ||
259 | |||
260 | void LLFace::unsetFaceColor() | ||
261 | { | ||
262 | clearState(USE_FACE_COLOR); | ||
263 | } | ||
264 | |||
265 | void LLFace::setDrawable(LLDrawable *drawable) | ||
266 | { | ||
267 | mDrawablep = drawable; | ||
268 | mXform = &drawable->mXform; | ||
269 | } | ||
270 | |||
271 | S32 LLFace::allocBackupMem() | ||
272 | { | ||
273 | LLMemType mt1(LLMemType::MTYPE_DRAWABLE); | ||
274 | |||
275 | S32 size = 0; | ||
276 | size += mIndicesCount * 4; | ||
277 | size += mGeomCount * mDrawPoolp->getStride(); | ||
278 | |||
279 | if (mDrawPoolp->mDataMaskNIL & LLDrawPool::DATA_VERTEX_WEIGHTS_MASK) | ||
280 | { | ||
281 | size += mGeomCount * mDrawPoolp->sDataSizes[LLDrawPool::DATA_VERTEX_WEIGHTS]; | ||
282 | } | ||
283 | |||
284 | if (mDrawPoolp->mDataMaskNIL & LLDrawPool::DATA_CLOTHING_WEIGHTS_MASK) | ||
285 | { | ||
286 | size += mGeomCount * mDrawPoolp->sDataSizes[LLDrawPool::DATA_CLOTHING_WEIGHTS]; | ||
287 | } | ||
288 | |||
289 | delete[] mBackupMem; | ||
290 | mBackupMem = new U8[size]; | ||
291 | return size; | ||
292 | } | ||
293 | |||
294 | |||
295 | void LLFace::setSize(const S32 num_vertices, const S32 num_indices) | ||
296 | { | ||
297 | LLMemType mt1(LLMemType::MTYPE_DRAWABLE); | ||
298 | |||
299 | if (getState() & SHARED_GEOM) | ||
300 | { | ||
301 | mGeomCount = num_vertices; | ||
302 | mIndicesCount = num_indices; | ||
303 | return; // Shared, don't allocate or do anything with memory | ||
304 | } | ||
305 | if (num_vertices != (S32)mGeomCount || num_indices != (S32)mIndicesCount) | ||
306 | { | ||
307 | setDirty(); | ||
308 | |||
309 | delete[] mBackupMem; | ||
310 | mBackupMem = NULL; | ||
311 | clearState(BACKLIST); | ||
312 | |||
313 | mGeomCount = num_vertices; | ||
314 | mIndicesCount = num_indices; | ||
315 | } | ||
316 | |||
317 | } | ||
318 | |||
319 | BOOL LLFace::reserveIfNeeded() | ||
320 | { | ||
321 | LLMemType mt1(LLMemType::MTYPE_DRAWABLE); | ||
322 | |||
323 | if (getDirty()) | ||
324 | { | ||
325 | if (isState(BACKLIST)) | ||
326 | { | ||
327 | llwarns << "Reserve on backlisted object!" << llendl; | ||
328 | } | ||
329 | |||
330 | if (0 == mGeomCount) | ||
331 | { | ||
332 | //llwarns << "Reserving zero bytes for face!" << llendl; | ||
333 | mGeomCount = 0; | ||
334 | mIndicesCount = 0; | ||
335 | return FALSE; | ||
336 | } | ||
337 | |||
338 | mGeomIndex = mDrawPoolp->reserveGeom(mGeomCount); | ||
339 | // (reserveGeom() always returns a valid index) | ||
340 | mIndicesIndex = mDrawPoolp->reserveInd (mIndicesCount); | ||
341 | mGeneration = mDrawPoolp->mGeneration; | ||
342 | } | ||
343 | |||
344 | return TRUE; | ||
345 | } | ||
346 | |||
347 | void LLFace::unReserve() | ||
348 | { | ||
349 | LLMemType mt1(LLMemType::MTYPE_DRAWABLE); | ||
350 | |||
351 | if (!(isState(SHARED_GEOM))) | ||
352 | { | ||
353 | mGeomIndex = mDrawPoolp->unReserveGeom(mGeomIndex, mGeomCount); | ||
354 | mIndicesIndex = mDrawPoolp->unReserveInd(mIndicesIndex, mIndicesCount); | ||
355 | } | ||
356 | } | ||
357 | |||
358 | //============================================================================ | ||
359 | |||
360 | S32 LLFace::getGeometryAvatar( | ||
361 | LLStrider<LLVector3> &vertices, | ||
362 | LLStrider<LLVector3> &normals, | ||
363 | LLStrider<LLVector3> &binormals, | ||
364 | LLStrider<LLVector2> &tex_coords, | ||
365 | LLStrider<F32> &vertex_weights, | ||
366 | LLStrider<LLVector4> &clothing_weights) | ||
367 | { | ||
368 | LLMemType mt1(LLMemType::MTYPE_DRAWABLE); | ||
369 | |||
370 | if (mGeomCount <= 0) | ||
371 | { | ||
372 | return -1; | ||
373 | } | ||
374 | |||
375 | if (isState(BACKLIST)) | ||
376 | { | ||
377 | if (!mBackupMem) | ||
378 | { | ||
379 | llerrs << "No backup memory for backlist" << llendl; | ||
380 | } | ||
381 | |||
382 | vertices = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_VERTICES]); | ||
383 | normals = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_NORMALS]); | ||
384 | binormals = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_BINORMALS]); | ||
385 | tex_coords = (LLVector2*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_TEX_COORDS0]); | ||
386 | clothing_weights = (LLVector4*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_CLOTHING_WEIGHTS]); | ||
387 | vertex_weights = (F32*)(mBackupMem + (4 * mIndicesCount) + (mGeomCount * mDrawPoolp->getStride())); | ||
388 | tex_coords.setStride( mDrawPoolp->getStride()); | ||
389 | vertices.setStride( mDrawPoolp->getStride()); | ||
390 | normals.setStride( mDrawPoolp->getStride()); | ||
391 | binormals.setStride( mDrawPoolp->getStride()); | ||
392 | clothing_weights.setStride( mDrawPoolp->getStride()); | ||
393 | |||
394 | return 0; | ||
395 | } | ||
396 | else | ||
397 | { | ||
398 | if (!reserveIfNeeded()) | ||
399 | { | ||
400 | return -1; | ||
401 | } | ||
402 | |||
403 | llassert(mGeomIndex >= 0); | ||
404 | llassert(mIndicesIndex >= 0); | ||
405 | |||
406 | mDrawPoolp->getVertexStrider (vertices, mGeomIndex); | ||
407 | mDrawPoolp->getNormalStrider (normals, mGeomIndex); | ||
408 | mDrawPoolp->getBinormalStrider (binormals, mGeomIndex); | ||
409 | mDrawPoolp->getTexCoordStrider (tex_coords, mGeomIndex); | ||
410 | mDrawPoolp->getVertexWeightStrider(vertex_weights, mGeomIndex); | ||
411 | mDrawPoolp->getClothingWeightStrider(clothing_weights, mGeomIndex); | ||
412 | |||
413 | mDrawPoolp->setDirty(); | ||
414 | |||
415 | llassert(mGeomIndex >= 0); | ||
416 | return mGeomIndex; | ||
417 | } | ||
418 | } | ||
419 | |||
420 | S32 LLFace::getGeometryTerrain( | ||
421 | LLStrider<LLVector3> &vertices, | ||
422 | LLStrider<LLVector3> &normals, | ||
423 | LLStrider<LLColor4U> &colors, | ||
424 | LLStrider<LLVector2> &texcoords0, | ||
425 | LLStrider<LLVector2> &texcoords1, | ||
426 | U32 *&indicesp) | ||
427 | { | ||
428 | LLMemType mt1(LLMemType::MTYPE_DRAWABLE); | ||
429 | |||
430 | if (mGeomCount <= 0) | ||
431 | { | ||
432 | return -1; | ||
433 | } | ||
434 | |||
435 | if (isState(BACKLIST)) | ||
436 | { | ||
437 | if (!mBackupMem) | ||
438 | { | ||
439 | printDebugInfo(); | ||
440 | llerrs << "No backup memory for face" << llendl; | ||
441 | } | ||
442 | vertices = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_VERTICES]); | ||
443 | normals = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_NORMALS]); | ||
444 | colors = (LLColor4U*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_COLORS]); | ||
445 | texcoords0= (LLVector2*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_TEX_COORDS0]); | ||
446 | texcoords1= (LLVector2*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_TEX_COORDS1]); | ||
447 | texcoords0.setStride(mDrawPoolp->getStride()); | ||
448 | texcoords1.setStride(mDrawPoolp->getStride()); | ||
449 | vertices.setStride( mDrawPoolp->getStride()); | ||
450 | normals.setStride( mDrawPoolp->getStride()); | ||
451 | colors.setStride( mDrawPoolp->getStride()); | ||
452 | indicesp = (U32*)mBackupMem; | ||
453 | |||
454 | return 0; | ||
455 | } | ||
456 | else | ||
457 | { | ||
458 | if (!reserveIfNeeded()) | ||
459 | { | ||
460 | llinfos << "Get geometry failed!" << llendl; | ||
461 | return -1; | ||
462 | } | ||
463 | |||
464 | llassert(mGeomIndex >= 0); | ||
465 | llassert(mIndicesIndex >= 0); | ||
466 | |||
467 | mDrawPoolp->getVertexStrider(vertices, mGeomIndex); | ||
468 | mDrawPoolp->getNormalStrider(normals, mGeomIndex); | ||
469 | mDrawPoolp->getColorStrider(colors, mGeomIndex); | ||
470 | mDrawPoolp->getTexCoordStrider(texcoords0, mGeomIndex, 0); | ||
471 | mDrawPoolp->getTexCoordStrider(texcoords1, mGeomIndex, 1); | ||
472 | |||
473 | indicesp = mDrawPoolp->getIndices(mIndicesIndex); | ||
474 | |||
475 | mDrawPoolp->setDirty(); | ||
476 | |||
477 | llassert(mGeomIndex >= 0); | ||
478 | return mGeomIndex; | ||
479 | } | ||
480 | } | ||
481 | |||
482 | S32 LLFace::getGeometry(LLStrider<LLVector3> &vertices, LLStrider<LLVector3> &normals, | ||
483 | LLStrider<LLVector2> &tex_coords, U32 *&indicesp) | ||
484 | { | ||
485 | LLMemType mt1(LLMemType::MTYPE_DRAWABLE); | ||
486 | |||
487 | if (mGeomCount <= 0) | ||
488 | { | ||
489 | return -1; | ||
490 | } | ||
491 | |||
492 | if (isState(BACKLIST)) | ||
493 | { | ||
494 | if (!mBackupMem) | ||
495 | { | ||
496 | printDebugInfo(); | ||
497 | llerrs << "No backup memory for face" << llendl; | ||
498 | } | ||
499 | vertices = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_VERTICES]); | ||
500 | normals = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_NORMALS]); | ||
501 | tex_coords= (LLVector2*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_TEX_COORDS0]); | ||
502 | tex_coords.setStride(mDrawPoolp->getStride()); | ||
503 | vertices.setStride( mDrawPoolp->getStride()); | ||
504 | normals.setStride( mDrawPoolp->getStride()); | ||
505 | indicesp = (U32*)mBackupMem; | ||
506 | |||
507 | return 0; | ||
508 | } | ||
509 | else | ||
510 | { | ||
511 | if (!reserveIfNeeded()) | ||
512 | { | ||
513 | return -1; | ||
514 | } | ||
515 | |||
516 | llassert(mGeomIndex >= 0); | ||
517 | llassert(mIndicesIndex >= 0); | ||
518 | |||
519 | mDrawPoolp->getVertexStrider(vertices, mGeomIndex); | ||
520 | if (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_NORMALS_MASK) | ||
521 | { | ||
522 | mDrawPoolp->getNormalStrider(normals, mGeomIndex); | ||
523 | } | ||
524 | if (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_TEX_COORDS0_MASK) | ||
525 | { | ||
526 | mDrawPoolp->getTexCoordStrider(tex_coords, mGeomIndex); | ||
527 | } | ||
528 | |||
529 | indicesp =mDrawPoolp->getIndices (mIndicesIndex); | ||
530 | |||
531 | mDrawPoolp->setDirty(); | ||
532 | |||
533 | llassert(mGeomIndex >= 0); | ||
534 | return mGeomIndex; | ||
535 | } | ||
536 | } | ||
537 | |||
538 | S32 LLFace::getGeometryColors(LLStrider<LLVector3> &vertices, LLStrider<LLVector3> &normals, | ||
539 | LLStrider<LLVector2> &tex_coords, LLStrider<LLColor4U> &colors, | ||
540 | U32 *&indicesp) | ||
541 | { | ||
542 | S32 res = getGeometry(vertices, normals, tex_coords, indicesp); | ||
543 | if (res >= 0) | ||
544 | { | ||
545 | getColors(colors); | ||
546 | } | ||
547 | return res; | ||
548 | } | ||
549 | |||
550 | S32 LLFace::getGeometryMultiTexture( | ||
551 | LLStrider<LLVector3> &vertices, | ||
552 | LLStrider<LLVector3> &normals, | ||
553 | LLStrider<LLVector3> &binormals, | ||
554 | LLStrider<LLVector2> &tex_coords0, | ||
555 | LLStrider<LLVector2> &tex_coords1, | ||
556 | U32 *&indicesp) | ||
557 | { | ||
558 | LLMemType mt1(LLMemType::MTYPE_DRAWABLE); | ||
559 | |||
560 | if (mGeomCount <= 0) | ||
561 | { | ||
562 | return -1; | ||
563 | } | ||
564 | |||
565 | if (isState(BACKLIST)) | ||
566 | { | ||
567 | if (!mBackupMem) | ||
568 | { | ||
569 | printDebugInfo(); | ||
570 | llerrs << "No backup memory for face" << llendl; | ||
571 | } | ||
572 | vertices = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_VERTICES]); | ||
573 | normals = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_NORMALS]); | ||
574 | tex_coords0 = (LLVector2*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_TEX_COORDS0]); | ||
575 | tex_coords0.setStride( mDrawPoolp->getStride() ); | ||
576 | vertices.setStride( mDrawPoolp->getStride() ); | ||
577 | normals.setStride( mDrawPoolp->getStride() ); | ||
578 | if (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_BINORMALS_MASK) | ||
579 | { | ||
580 | binormals = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_BINORMALS]); | ||
581 | binormals.setStride( mDrawPoolp->getStride() ); | ||
582 | } | ||
583 | if (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_TEX_COORDS1_MASK) | ||
584 | { | ||
585 | tex_coords1 = (LLVector2*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_TEX_COORDS1]); | ||
586 | tex_coords1.setStride( mDrawPoolp->getStride() ); | ||
587 | } | ||
588 | indicesp = (U32*)mBackupMem; | ||
589 | |||
590 | return 0; | ||
591 | } | ||
592 | else | ||
593 | { | ||
594 | if (!reserveIfNeeded()) | ||
595 | { | ||
596 | return -1; | ||
597 | } | ||
598 | |||
599 | llassert(mGeomIndex >= 0); | ||
600 | llassert(mIndicesIndex >= 0); | ||
601 | |||
602 | mDrawPoolp->getVertexStrider(vertices, mGeomIndex); | ||
603 | if (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_NORMALS_MASK) | ||
604 | { | ||
605 | mDrawPoolp->getNormalStrider(normals, mGeomIndex); | ||
606 | } | ||
607 | if (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_TEX_COORDS0_MASK) | ||
608 | { | ||
609 | mDrawPoolp->getTexCoordStrider(tex_coords0, mGeomIndex); | ||
610 | } | ||
611 | if (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_BINORMALS_MASK) | ||
612 | { | ||
613 | mDrawPoolp->getBinormalStrider(binormals, mGeomIndex); | ||
614 | } | ||
615 | if (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_TEX_COORDS1_MASK) | ||
616 | { | ||
617 | mDrawPoolp->getTexCoordStrider(tex_coords1, mGeomIndex, 1); | ||
618 | } | ||
619 | indicesp = mDrawPoolp->getIndices(mIndicesIndex); | ||
620 | |||
621 | mDrawPoolp->setDirty(); | ||
622 | |||
623 | llassert(mGeomIndex >= 0); | ||
624 | return mGeomIndex; | ||
625 | } | ||
626 | } | ||
627 | |||
628 | void LLFace::updateCenterAgent() | ||
629 | { | ||
630 | mCenterAgent = mCenterLocal * getRenderMatrix(); | ||
631 | } | ||
632 | |||
633 | void LLFace::renderForSelect() const | ||
634 | { | ||
635 | if(mGeomIndex < 0 || mDrawablep.isNull()) | ||
636 | { | ||
637 | return; | ||
638 | } | ||
639 | if (mVObjp->mGLName) | ||
640 | { | ||
641 | S32 name = mVObjp->mGLName; | ||
642 | |||
643 | LLColor4U color((U8)(name >> 16), (U8)(name >> 8), (U8)name); | ||
644 | #if 0 // *FIX: Postponing this fix until we have texcoord pick info... | ||
645 | if (mTEOffset != -1) | ||
646 | { | ||
647 | color.mV[VALPHA] = (U8)(getTextureEntry()->getColor().mV[VALPHA] * 255.f); | ||
648 | } | ||
649 | #endif | ||
650 | glColor4ubv(color.mV); | ||
651 | |||
652 | if (mVObjp->getPCode() == LL_PCODE_VOLUME) | ||
653 | { | ||
654 | LLVOVolume *volp; | ||
655 | volp = (LLVOVolume *)(LLViewerObject*)mVObjp; | ||
656 | if (volp->getNumFaces() == 1 && !volp->getVolumeChanged()) | ||
657 | { | ||
658 | // We need to special case the coalesced face model. | ||
659 | S32 num_vfs = volp->getVolume()->getNumFaces(); | ||
660 | S32 offset = 0; | ||
661 | S32 i; | ||
662 | |||
663 | for (i = 0; i < num_vfs; i++) | ||
664 | { | ||
665 | if (gPickFaces) | ||
666 | { | ||
667 | // mask off high 4 bits (16 total possible faces) | ||
668 | color.mV[0] &= 0x0f; | ||
669 | color.mV[0] |= (i & 0x0f) << 4; | ||
670 | glColor4ubv(color.mV); | ||
671 | } | ||
672 | S32 count = volp->getVolume()->getVolumeFace(i).mIndices.size(); | ||
673 | if (isState(GLOBAL)) | ||
674 | { | ||
675 | glDrawElements(mPrimType, count, GL_UNSIGNED_INT, getRawIndices() + offset); | ||
676 | } | ||
677 | else | ||
678 | { | ||
679 | glPushMatrix(); | ||
680 | glMultMatrixf((float*)getRenderMatrix().mMatrix); | ||
681 | glDrawElements(mPrimType, count, GL_UNSIGNED_INT, getRawIndices() + offset); | ||
682 | glPopMatrix(); | ||
683 | } | ||
684 | offset += count; | ||
685 | } | ||
686 | // We're done, return. | ||
687 | return; | ||
688 | } | ||
689 | |||
690 | // We don't have coalesced faces, do this the normal way. | ||
691 | } | ||
692 | |||
693 | if (gPickFaces && mTEOffset != -1) | ||
694 | { | ||
695 | // mask off high 4 bits (16 total possible faces) | ||
696 | color.mV[0] &= 0x0f; | ||
697 | color.mV[0] |= (mTEOffset & 0x0f) << 4; | ||
698 | glColor4ubv(color.mV); | ||
699 | } | ||
700 | |||
701 | if (mIndicesCount) | ||
702 | { | ||
703 | if (isState(GLOBAL)) | ||
704 | { | ||
705 | glDrawElements(mPrimType, mIndicesCount, GL_UNSIGNED_INT, getRawIndices()); | ||
706 | } | ||
707 | else | ||
708 | { | ||
709 | glPushMatrix(); | ||
710 | glMultMatrixf((float*)getRenderMatrix().mMatrix); | ||
711 | glDrawElements(mPrimType, mIndicesCount, GL_UNSIGNED_INT, getRawIndices()); | ||
712 | glPopMatrix(); | ||
713 | } | ||
714 | } | ||
715 | else if (mGeomCount > 0) | ||
716 | { | ||
717 | if (isState(GLOBAL)) | ||
718 | { | ||
719 | glDrawArrays(mPrimType, mGeomIndex, mGeomCount); | ||
720 | } | ||
721 | else | ||
722 | { | ||
723 | glPushMatrix(); | ||
724 | glMultMatrixf((float*)getRenderMatrix().mMatrix); | ||
725 | glDrawArrays(mPrimType, mGeomIndex, mGeomCount); | ||
726 | glPopMatrix(); | ||
727 | } | ||
728 | } | ||
729 | } | ||
730 | } | ||
731 | |||
732 | void LLFace::renderSelected(LLImageGL *imagep, const LLColor4& color, const S32 offset, const S32 count) | ||
733 | { | ||
734 | if(mGeomIndex < 0 || mDrawablep.isNull()) | ||
735 | { | ||
736 | return; | ||
737 | } | ||
738 | if (mGeomCount > 0) | ||
739 | { | ||
740 | LLGLSPipelineAlpha gls_pipeline_alpha; | ||
741 | glColor4fv(color.mV); | ||
742 | |||
743 | LLViewerImage::bindTexture(imagep); | ||
744 | if (!isState(GLOBAL)) | ||
745 | { | ||
746 | // Apply the proper transform for non-global objects. | ||
747 | glPushMatrix(); | ||
748 | glMultMatrixf((float*)getRenderMatrix().mMatrix); | ||
749 | } | ||
750 | |||
751 | if (sSafeRenderSelect) | ||
752 | { | ||
753 | glBegin(mPrimType); | ||
754 | if (count) | ||
755 | { | ||
756 | for (S32 i = offset; i < offset + count; i++) | ||
757 | { | ||
758 | LLVector2 tc = mDrawPoolp->getTexCoord(mDrawPoolp->getIndex(getIndicesStart() + i), 0); | ||
759 | glTexCoord2fv(tc.mV); | ||
760 | LLVector3 normal = mDrawPoolp->getNormal(mDrawPoolp->getIndex(getIndicesStart() + i)); | ||
761 | glNormal3fv(normal.mV); | ||
762 | LLVector3 vertex = mDrawPoolp->getVertex(mDrawPoolp->getIndex(getIndicesStart() + i)); | ||
763 | glVertex3fv(vertex.mV); | ||
764 | } | ||
765 | } | ||
766 | else | ||
767 | { | ||
768 | for (U32 i = 0; i < getIndicesCount(); i++) | ||
769 | { | ||
770 | LLVector2 tc = mDrawPoolp->getTexCoord(mDrawPoolp->getIndex(getIndicesStart() + i), 0); | ||
771 | glTexCoord2fv(tc.mV); | ||
772 | LLVector3 normal = mDrawPoolp->getNormal(mDrawPoolp->getIndex(getIndicesStart() + i)); | ||
773 | glNormal3fv(normal.mV); | ||
774 | LLVector3 vertex = mDrawPoolp->getVertex(mDrawPoolp->getIndex(getIndicesStart() + i)); | ||
775 | glVertex3fv(vertex.mV); | ||
776 | } | ||
777 | } | ||
778 | glEnd(); | ||
779 | |||
780 | if( gSavedSettings.getBOOL("ShowTangentBasis") ) | ||
781 | { | ||
782 | S32 start; | ||
783 | S32 end; | ||
784 | if (count) | ||
785 | { | ||
786 | start = offset; | ||
787 | end = offset + count; | ||
788 | } | ||
789 | else | ||
790 | { | ||
791 | start = 0; | ||
792 | end = getIndicesCount(); | ||
793 | } | ||
794 | |||
795 | LLGLSNoTexture gls_no_texture; | ||
796 | glColor4f(1, 1, 1, 1); | ||
797 | glBegin(GL_LINES); | ||
798 | for (S32 i = start; i < end; i++) | ||
799 | { | ||
800 | LLVector3 vertex = mDrawPoolp->getVertex(mDrawPoolp->getIndex(getIndicesStart() + i)); | ||
801 | glVertex3fv(vertex.mV); | ||
802 | LLVector3 normal = mDrawPoolp->getNormal(mDrawPoolp->getIndex(getIndicesStart() + i)); | ||
803 | glVertex3fv( (vertex + normal * 0.1f).mV ); | ||
804 | } | ||
805 | glEnd(); | ||
806 | |||
807 | if (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_BINORMALS_MASK) | ||
808 | { | ||
809 | glColor4f(0, 1, 0, 1); | ||
810 | glBegin(GL_LINES); | ||
811 | for (S32 i = start; i < end; i++) | ||
812 | { | ||
813 | LLVector3 vertex = mDrawPoolp->getVertex(mDrawPoolp->getIndex(getIndicesStart() + i)); | ||
814 | glVertex3fv(vertex.mV); | ||
815 | LLVector3 binormal = mDrawPoolp->getBinormal(mDrawPoolp->getIndex(getIndicesStart() + i)); | ||
816 | glVertex3fv( (vertex + binormal * 0.1f).mV ); | ||
817 | } | ||
818 | glEnd(); | ||
819 | } | ||
820 | } | ||
821 | } | ||
822 | else | ||
823 | { | ||
824 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); | ||
825 | glEnableClientState(GL_VERTEX_ARRAY); | ||
826 | glEnableClientState(GL_NORMAL_ARRAY); | ||
827 | if (count) | ||
828 | { | ||
829 | if (mIndicesCount > 0) | ||
830 | { | ||
831 | glDrawElements(mPrimType, count, GL_UNSIGNED_INT, getRawIndices() + offset); | ||
832 | } | ||
833 | else | ||
834 | { | ||
835 | llerrs << "Rendering non-indexed volume face!" << llendl; | ||
836 | glDrawArrays(mPrimType, mGeomIndex, mGeomCount); | ||
837 | } | ||
838 | } | ||
839 | else | ||
840 | { | ||
841 | if (mIndicesCount > 0) | ||
842 | { | ||
843 | glDrawElements(mPrimType, mIndicesCount, GL_UNSIGNED_INT, getRawIndices()); | ||
844 | } | ||
845 | else | ||
846 | { | ||
847 | glDrawArrays(mPrimType, mGeomIndex, mGeomCount); | ||
848 | } | ||
849 | } | ||
850 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); | ||
851 | glDisableClientState(GL_VERTEX_ARRAY); | ||
852 | glDisableClientState(GL_NORMAL_ARRAY); | ||
853 | } | ||
854 | |||
855 | if (!isState(GLOBAL)) | ||
856 | { | ||
857 | // Restore the tranform for non-global objects | ||
858 | glPopMatrix(); | ||
859 | } | ||
860 | } | ||
861 | } | ||
862 | |||
863 | void LLFace::renderSelectedUV(const S32 offset, const S32 count) | ||
864 | { | ||
865 | LLUUID uv_img_red_blue_id(gViewerArt.getString("uv_test1.tga")); | ||
866 | LLUUID uv_img_green_id(gViewerArt.getString("uv_test2.tga")); | ||
867 | LLViewerImage* red_blue_imagep = gImageList.getImage(uv_img_red_blue_id, TRUE, TRUE); | ||
868 | LLViewerImage* green_imagep = gImageList.getImage(uv_img_green_id, TRUE, TRUE); | ||
869 | |||
870 | LLGLSObjectSelect object_select; | ||
871 | LLGLEnable blend(GL_BLEND); | ||
872 | LLGLEnable texture(GL_TEXTURE_2D); | ||
873 | |||
874 | if (!mDrawPoolp || !getIndicesCount() || getIndicesStart() < 0) | ||
875 | { | ||
876 | return; | ||
877 | } | ||
878 | for (S32 pass = 0; pass < 2; pass++) | ||
879 | { | ||
880 | static F32 bias = 0.f; | ||
881 | static F32 factor = -10.f; | ||
882 | if (mGeomCount > 0) | ||
883 | { | ||
884 | glColor4fv(LLColor4::white.mV); | ||
885 | |||
886 | if (pass == 0) | ||
887 | { | ||
888 | LLViewerImage::bindTexture(red_blue_imagep); | ||
889 | } | ||
890 | else // pass == 1 | ||
891 | { | ||
892 | glBlendFunc(GL_ONE, GL_ONE); | ||
893 | LLViewerImage::bindTexture(green_imagep); | ||
894 | glMatrixMode(GL_TEXTURE); | ||
895 | glPushMatrix(); | ||
896 | glScalef(256.f, 256.f, 1.f); | ||
897 | } | ||
898 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | ||
899 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | ||
900 | |||
901 | |||
902 | if (!isState(GLOBAL)) | ||
903 | { | ||
904 | // Apply the proper transform for non-global objects. | ||
905 | glMatrixMode(GL_MODELVIEW); | ||
906 | glPushMatrix(); | ||
907 | glMultMatrixf((float*)getRenderMatrix().mMatrix); | ||
908 | } | ||
909 | |||
910 | glEnable(GL_POLYGON_OFFSET_FILL); | ||
911 | glPolygonOffset(factor, bias); | ||
912 | if (sSafeRenderSelect) | ||
913 | { | ||
914 | glBegin(mPrimType); | ||
915 | if (count) | ||
916 | { | ||
917 | for (S32 i = offset; i < offset + count; i++) | ||
918 | { | ||
919 | LLVector2 tc = mDrawPoolp->getTexCoord(mDrawPoolp->getIndex(getIndicesStart() + i), 0); | ||
920 | glTexCoord2fv(tc.mV); | ||
921 | LLVector3 vertex = mDrawPoolp->getVertex(mDrawPoolp->getIndex(getIndicesStart() + i)); | ||
922 | glVertex3fv(vertex.mV); | ||
923 | } | ||
924 | } | ||
925 | else | ||
926 | { | ||
927 | for (U32 i = 0; i < getIndicesCount(); i++) | ||
928 | { | ||
929 | LLVector2 tc = mDrawPoolp->getTexCoord(mDrawPoolp->getIndex(getIndicesStart() + i), 0); | ||
930 | glTexCoord2fv(tc.mV); | ||
931 | LLVector3 vertex = mDrawPoolp->getVertex(mDrawPoolp->getIndex(getIndicesStart() + i)); | ||
932 | glVertex3fv(vertex.mV); | ||
933 | } | ||
934 | } | ||
935 | glEnd(); | ||
936 | } | ||
937 | else | ||
938 | { | ||
939 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); | ||
940 | glEnableClientState(GL_VERTEX_ARRAY); | ||
941 | llassert(mGeomIndex >= 0); | ||
942 | if (count) | ||
943 | { | ||
944 | if (mIndicesCount > 0) | ||
945 | { | ||
946 | glDrawElements(mPrimType, count, GL_UNSIGNED_INT, getRawIndices() + offset); | ||
947 | } | ||
948 | else | ||
949 | { | ||
950 | llerrs << "Rendering non-indexed volume face!" << llendl; | ||
951 | glDrawArrays(mPrimType, mGeomIndex, mGeomCount); | ||
952 | } | ||
953 | } | ||
954 | else | ||
955 | { | ||
956 | if (mIndicesCount > 0) | ||
957 | { | ||
958 | glDrawElements(mPrimType, mIndicesCount, GL_UNSIGNED_INT, getRawIndices()); | ||
959 | } | ||
960 | else | ||
961 | { | ||
962 | glDrawArrays(mPrimType, mGeomIndex, mGeomCount); | ||
963 | } | ||
964 | } | ||
965 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); | ||
966 | glDisableClientState(GL_VERTEX_ARRAY); | ||
967 | } | ||
968 | |||
969 | glDisable(GL_POLYGON_OFFSET_FILL); | ||
970 | if (!isState(GLOBAL)) | ||
971 | { | ||
972 | // Restore the tranform for non-global objects | ||
973 | glPopMatrix(); | ||
974 | } | ||
975 | if (pass == 1) | ||
976 | { | ||
977 | glMatrixMode(GL_TEXTURE); | ||
978 | glPopMatrix(); | ||
979 | glMatrixMode(GL_MODELVIEW); | ||
980 | glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA); | ||
981 | } | ||
982 | } | ||
983 | } | ||
984 | |||
985 | //restore blend func | ||
986 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | ||
987 | } | ||
988 | |||
989 | |||
990 | void LLFace::printDebugInfo() const | ||
991 | { | ||
992 | LLDrawPool *poolp = getPool(); | ||
993 | llinfos << "Object: " << getViewerObject()->mID << llendl; | ||
994 | if (getDrawable()) | ||
995 | { | ||
996 | llinfos << "Type: " << LLPrimitive::pCodeToString(getDrawable()->getVObj()->getPCode()) << llendl; | ||
997 | } | ||
998 | if (getTexture()) | ||
999 | { | ||
1000 | llinfos << "Texture: " << getTexture() << " Comps: " << (U32)getTexture()->getComponents() << llendl; | ||
1001 | } | ||
1002 | else | ||
1003 | { | ||
1004 | llinfos << "No texture: " << llendl; | ||
1005 | } | ||
1006 | |||
1007 | llinfos << "Face: " << this << llendl; | ||
1008 | if (isState(BACKLIST)) | ||
1009 | { | ||
1010 | llinfos << "Backlisted!" << llendl; | ||
1011 | } | ||
1012 | llinfos << "State: " << getState() << llendl; | ||
1013 | llinfos << "Geom Index Data:" << llendl; | ||
1014 | llinfos << "--------------------" << llendl; | ||
1015 | llinfos << "GI: " << mGeomIndex << " Count:" << mGeomCount << llendl; | ||
1016 | llinfos << "Face Index Data:" << llendl; | ||
1017 | llinfos << "--------------------" << llendl; | ||
1018 | llinfos << "II: " << mIndicesIndex << " Count:" << mIndicesCount << llendl; | ||
1019 | llinfos << llendl; | ||
1020 | |||
1021 | poolp->printDebugInfo(); | ||
1022 | |||
1023 | S32 pool_references = 0; | ||
1024 | for (std::vector<LLFace*>::iterator iter = poolp->mReferences.begin(); | ||
1025 | iter != poolp->mReferences.end(); iter++) | ||
1026 | { | ||
1027 | LLFace *facep = *iter; | ||
1028 | if (facep == this) | ||
1029 | { | ||
1030 | llinfos << "Pool reference: " << pool_references << llendl; | ||
1031 | pool_references++; | ||
1032 | } | ||
1033 | } | ||
1034 | |||
1035 | if (pool_references != 1) | ||
1036 | { | ||
1037 | llinfos << "Incorrect number of pool references!" << llendl; | ||
1038 | } | ||
1039 | |||
1040 | |||
1041 | llinfos << "Indices:" << llendl; | ||
1042 | llinfos << "--------------------" << llendl; | ||
1043 | |||
1044 | const U32 *indicesp = getRawIndices(); | ||
1045 | S32 indices_count = getIndicesCount(); | ||
1046 | S32 geom_start = getGeomStart(); | ||
1047 | |||
1048 | for (S32 i = 0; i < indices_count; i++) | ||
1049 | { | ||
1050 | llinfos << i << ":" << indicesp[i] << ":" << (S32)(indicesp[i] - geom_start) << llendl; | ||
1051 | } | ||
1052 | llinfos << llendl; | ||
1053 | |||
1054 | llinfos << "Vertices:" << llendl; | ||
1055 | llinfos << "--------------------" << llendl; | ||
1056 | for (S32 i = 0; i < mGeomCount; i++) | ||
1057 | { | ||
1058 | llinfos << mGeomIndex + i << ":" << poolp->getVertex(mGeomIndex + i) << llendl; | ||
1059 | } | ||
1060 | llinfos << llendl; | ||
1061 | } | ||
1062 | |||
1063 | S32 LLFace::backup() | ||
1064 | { | ||
1065 | LLMemType mt1(LLMemType::MTYPE_DRAWABLE); | ||
1066 | |||
1067 | if (isState(BACKLIST)) | ||
1068 | { | ||
1069 | llwarns << "Face is already backed up in LLFace::backup!" << llendl; | ||
1070 | return mGeomCount; | ||
1071 | } | ||
1072 | if (mGeomIndex < 0) | ||
1073 | { | ||
1074 | // flexible objects can cause this | ||
1075 | //llwarns << "No geometry to back-up" << llendl; | ||
1076 | return 0; | ||
1077 | } | ||
1078 | |||
1079 | S32 size = 0; | ||
1080 | if (!mBackupMem) | ||
1081 | { | ||
1082 | size = allocBackupMem(); | ||
1083 | } | ||
1084 | else | ||
1085 | { | ||
1086 | llerrs << "Memory already backed up!" << llendl; | ||
1087 | } | ||
1088 | |||
1089 | // Need to flag this, because we can allocate a non-zero backup mem if we have indices and no geometry. | ||
1090 | |||
1091 | if (mGeomCount || mIndicesCount) | ||
1092 | { | ||
1093 | setState(BACKLIST); | ||
1094 | #if !RELEASE_FOR_DOWNLOAD | ||
1095 | if (mGeomIndex < 0 || mIndicesIndex < 0) | ||
1096 | { | ||
1097 | llerrs << "LLFace::backup" << llendl; | ||
1098 | } | ||
1099 | #endif | ||
1100 | |||
1101 | U32 *backup = (U32*)mBackupMem; | ||
1102 | S32 stride = mDrawPoolp->getStride(); | ||
1103 | |||
1104 | U32 *index = mDrawPoolp->getIndices(mIndicesIndex); | ||
1105 | for (U32 i=0;i<mIndicesCount;i++) | ||
1106 | { | ||
1107 | *backup++ = index[i] - mGeomIndex; | ||
1108 | index[i] = 0; | ||
1109 | } | ||
1110 | |||
1111 | if (!mGeomCount) | ||
1112 | { | ||
1113 | return mGeomCount; | ||
1114 | } | ||
1115 | // | ||
1116 | // Don't change the order of these unles you change the corresponding getGeometry calls that read out of | ||
1117 | // backup memory, and also the other of the backup/restore pair! | ||
1118 | // | ||
1119 | memcpy(backup, (mDrawPoolp->mMemory.getMem() + mGeomIndex * stride), mGeomCount * stride); | ||
1120 | backup += mGeomCount * stride / 4; | ||
1121 | |||
1122 | if (mDrawPoolp->mDataMaskNIL & LLDrawPool::DATA_CLOTHING_WEIGHTS_MASK) | ||
1123 | { | ||
1124 | memcpy(backup, &mDrawPoolp->getClothingWeight(mGeomIndex), mGeomCount * sizeof(LLVector4)); | ||
1125 | backup += mGeomCount*4; | ||
1126 | } | ||
1127 | |||
1128 | if (mDrawPoolp->mDataMaskNIL & LLDrawPool::DATA_VERTEX_WEIGHTS_MASK) | ||
1129 | { | ||
1130 | memcpy(backup, &mDrawPoolp->getVertexWeight(mGeomIndex), mGeomCount * sizeof(F32)); | ||
1131 | backup += mGeomCount; | ||
1132 | } | ||
1133 | |||
1134 | llassert((U8*)backup - mBackupMem == size); | ||
1135 | |||
1136 | unReserve(); | ||
1137 | } | ||
1138 | return mGeomCount; | ||
1139 | } | ||
1140 | |||
1141 | void LLFace::restore() | ||
1142 | { | ||
1143 | LLMemType mt1(LLMemType::MTYPE_DRAWABLE); | ||
1144 | |||
1145 | if (!isState(BACKLIST)) | ||
1146 | { | ||
1147 | // flexible objects can cause this | ||
1148 | // printDebugInfo(); | ||
1149 | // llwarns << "not backlisted for restore" << llendl; | ||
1150 | return; | ||
1151 | } | ||
1152 | if (!mGeomCount || !mBackupMem) | ||
1153 | { | ||
1154 | if (!mBackupMem) | ||
1155 | { | ||
1156 | printDebugInfo(); | ||
1157 | llwarns << "no backmem for restore" << llendl; | ||
1158 | } | ||
1159 | |||
1160 | clearState(BACKLIST); | ||
1161 | return; | ||
1162 | } | ||
1163 | |||
1164 | S32 stride = mDrawPoolp->getStride(); | ||
1165 | mGeomIndex = mDrawPoolp->reserveGeom(mGeomCount); | ||
1166 | mIndicesIndex = mDrawPoolp->reserveInd (mIndicesCount); | ||
1167 | mGeneration = mDrawPoolp->mGeneration; | ||
1168 | |||
1169 | llassert(mGeomIndex >= 0); | ||
1170 | llassert(mIndicesIndex >= 0); | ||
1171 | |||
1172 | U32 *backup = (U32*)mBackupMem; | ||
1173 | U32 *index = mDrawPoolp->getIndices(mIndicesIndex); | ||
1174 | |||
1175 | for (U32 i=0;i<mIndicesCount;i++) | ||
1176 | { | ||
1177 | S32 ind = mGeomIndex + *backup; | ||
1178 | index[i] = ind; | ||
1179 | backup++; | ||
1180 | } | ||
1181 | |||
1182 | mDrawPoolp->mMemory.copyToMem(mGeomIndex * stride, (U8 *)backup, mGeomCount * stride); | ||
1183 | backup += mGeomCount * stride / 4; | ||
1184 | |||
1185 | // | ||
1186 | // Don't change the order of these unles you change the corresponding getGeometry calls that read out of | ||
1187 | // backup memory, and also the other of the backup/restore pair! | ||
1188 | // | ||
1189 | if (mDrawPoolp->mDataMaskNIL & LLDrawPool::DATA_CLOTHING_WEIGHTS_MASK) | ||
1190 | { | ||
1191 | mDrawPoolp->mClothingWeights.copyToMem(mGeomIndex, (U8 *)backup, mGeomCount); | ||
1192 | backup += mGeomCount*4; | ||
1193 | } | ||
1194 | |||
1195 | if (mDrawPoolp->mDataMaskNIL & LLDrawPool::DATA_VERTEX_WEIGHTS_MASK) | ||
1196 | { | ||
1197 | mDrawPoolp->mWeights.copyToMem(mGeomIndex, (U8 *)backup, mGeomCount); | ||
1198 | backup += mGeomCount; | ||
1199 | } | ||
1200 | |||
1201 | delete[] mBackupMem; | ||
1202 | mBackupMem = NULL; | ||
1203 | clearState(BACKLIST); | ||
1204 | } | ||
1205 | |||
1206 | // Transform the texture coordinates for this face. | ||
1207 | static void xform(LLVector2 &tex_coord, F32 cosAng, F32 sinAng, F32 offS, F32 offT, F32 magS, F32 magT) | ||
1208 | { | ||
1209 | // New, good way | ||
1210 | F32 s = tex_coord.mV[0]; | ||
1211 | F32 t = tex_coord.mV[1]; | ||
1212 | |||
1213 | // Texture transforms are done about the center of the face. | ||
1214 | s -= 0.5; | ||
1215 | t -= 0.5; | ||
1216 | |||
1217 | // Handle rotation | ||
1218 | F32 temp = s; | ||
1219 | s = s * cosAng + t * sinAng; | ||
1220 | t = -temp * sinAng + t * cosAng; | ||
1221 | |||
1222 | // Then scale | ||
1223 | s *= magS; | ||
1224 | t *= magT; | ||
1225 | |||
1226 | // Then offset | ||
1227 | s += offS + 0.5f; | ||
1228 | t += offT + 0.5f; | ||
1229 | |||
1230 | tex_coord.mV[0] = s; | ||
1231 | tex_coord.mV[1] = t; | ||
1232 | } | ||
1233 | |||
1234 | |||
1235 | BOOL LLFace::genVolumeTriangles(const LLVolume &volume, S32 f, | ||
1236 | const LLMatrix4& mat, const LLMatrix3& inv_trans_mat, BOOL global_volume) | ||
1237 | { | ||
1238 | const LLVolumeFace &vf = volume.getVolumeFace(f); | ||
1239 | S32 num_vertices = (S32)vf.mVertices.size(); | ||
1240 | S32 num_indices = (S32)vf.mIndices.size(); | ||
1241 | setSize(num_vertices, num_indices); | ||
1242 | |||
1243 | return genVolumeTriangles(volume, f, f, mat, inv_trans_mat, global_volume); | ||
1244 | } | ||
1245 | |||
1246 | BOOL LLFace::genVolumeTriangles(const LLVolume &volume, S32 fstart, S32 fend, | ||
1247 | const LLMatrix4& mat_vert, const LLMatrix3& mat_normal, const BOOL global_volume) | ||
1248 | { | ||
1249 | LLMemType mt1(LLMemType::MTYPE_DRAWABLE); | ||
1250 | |||
1251 | if (!mDrawablep) | ||
1252 | { | ||
1253 | return TRUE; | ||
1254 | } | ||
1255 | |||
1256 | S32 index_offset; | ||
1257 | F32 r, os, ot, ms, mt, cos_ang, sin_ang; | ||
1258 | LLStrider<LLVector3> vertices; | ||
1259 | LLStrider<LLVector3> normals; | ||
1260 | LLStrider<LLVector3> binormals; | ||
1261 | LLStrider<LLVector2> tex_coords; | ||
1262 | LLStrider<LLVector2> tex_coords2; | ||
1263 | U32 *indicesp = NULL; | ||
1264 | |||
1265 | BOOL bump = mDrawPoolp && (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_BINORMALS_MASK); | ||
1266 | BOOL is_static = mDrawablep->isStatic(); | ||
1267 | BOOL is_global = is_static; | ||
1268 | |||
1269 | if (bump) | ||
1270 | { | ||
1271 | index_offset = getGeometryMultiTexture(vertices, normals, binormals, tex_coords, tex_coords2, indicesp); | ||
1272 | } | ||
1273 | else | ||
1274 | { | ||
1275 | index_offset = getGeometry(vertices, normals, tex_coords, indicesp); | ||
1276 | } | ||
1277 | if (-1 == index_offset) | ||
1278 | { | ||
1279 | return TRUE; | ||
1280 | } | ||
1281 | |||
1282 | LLVector3 center_sum(0.f, 0.f, 0.f); | ||
1283 | |||
1284 | LLVector3 render_pos; | ||
1285 | |||
1286 | if (mDrawablep->isState(LLDrawable::REBUILD_TCOORD) && | ||
1287 | global_volume) | ||
1288 | { | ||
1289 | render_pos = mVObjp->getRenderPosition(); | ||
1290 | } | ||
1291 | |||
1292 | setPrimType(LLTriangles); | ||
1293 | |||
1294 | if (is_global) | ||
1295 | { | ||
1296 | setState(GLOBAL); | ||
1297 | } | ||
1298 | else | ||
1299 | { | ||
1300 | clearState(GLOBAL); | ||
1301 | } | ||
1302 | |||
1303 | LLVector3 min, max; | ||
1304 | LLVector2 tmin, tmax; | ||
1305 | |||
1306 | BOOL grab_first_vert = TRUE; | ||
1307 | BOOL grab_first_tcoord = TRUE; | ||
1308 | |||
1309 | for (S32 vol_face = fstart; vol_face <= fend; vol_face++) | ||
1310 | { | ||
1311 | const LLVolumeFace &vf = volume.getVolumeFace(vol_face); | ||
1312 | S32 num_vertices = (S32)vf.mVertices.size(); | ||
1313 | S32 num_indices = (S32)vf.mIndices.size(); | ||
1314 | llassert(num_indices > 0); | ||
1315 | |||
1316 | U8 bump_code; | ||
1317 | const LLTextureEntry *tep = mVObjp->getTE(vol_face); | ||
1318 | |||
1319 | if (tep) | ||
1320 | { | ||
1321 | bump_code = tep->getBumpmap(); | ||
1322 | r = tep->getRotation(); | ||
1323 | os = tep->mOffsetS; | ||
1324 | ot = tep->mOffsetT; | ||
1325 | ms = tep->mScaleS; | ||
1326 | mt = tep->mScaleT; | ||
1327 | cos_ang = cos(r); | ||
1328 | sin_ang = sin(r); | ||
1329 | } | ||
1330 | else | ||
1331 | { | ||
1332 | bump_code = 0; | ||
1333 | cos_ang = 1.0f; | ||
1334 | sin_ang = 0.0f; | ||
1335 | os = 0.0f; | ||
1336 | ot = 0.0f; | ||
1337 | ms = 1.0f; | ||
1338 | mt = 1.0f; | ||
1339 | } | ||
1340 | |||
1341 | if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME)) | ||
1342 | { | ||
1343 | // VERTICES & NORMALS | ||
1344 | for (S32 i = 0; i < num_vertices; i++) | ||
1345 | { | ||
1346 | LLVector3 v; | ||
1347 | v = vf.mVertices[i].mPosition * mat_vert; | ||
1348 | |||
1349 | LLVector3 normal = vf.mVertices[i].mNormal * mat_normal; | ||
1350 | normal.normVec(); | ||
1351 | *normals++ = normal; | ||
1352 | |||
1353 | *vertices++ = v; | ||
1354 | |||
1355 | if (grab_first_vert) | ||
1356 | { | ||
1357 | grab_first_vert = FALSE; | ||
1358 | min = max = v; | ||
1359 | } | ||
1360 | else | ||
1361 | { | ||
1362 | for (U32 j = 0; j < 3; j++) | ||
1363 | { | ||
1364 | if (v.mV[j] < min.mV[j]) | ||
1365 | { | ||
1366 | min.mV[j] = v.mV[j]; | ||
1367 | } | ||
1368 | if (v.mV[j] > max.mV[j]) | ||
1369 | { | ||
1370 | max.mV[j] = v.mV[j]; | ||
1371 | } | ||
1372 | } | ||
1373 | } | ||
1374 | } | ||
1375 | for (S32 i = 0; i < num_indices; i++) | ||
1376 | { | ||
1377 | S32 index = vf.mIndices[i] + index_offset; | ||
1378 | llassert(index >= 0 && (i != 1 || *(indicesp-1)!=(U32)index)); | ||
1379 | *indicesp++ = index; | ||
1380 | } | ||
1381 | } | ||
1382 | |||
1383 | if ((mDrawablep->isState(LLDrawable::REBUILD_TCOORD)) || | ||
1384 | ((bump || getTextureEntry()->getTexGen() != 0) && mDrawablep->isState(LLDrawable::REBUILD_VOLUME))) | ||
1385 | { | ||
1386 | // TEX COORDS AND BINORMALS | ||
1387 | LLVector3 binormal_dir( -sin_ang, cos_ang, 0 ); | ||
1388 | LLVector3 bump_s_primary_light_ray; | ||
1389 | LLVector3 bump_t_primary_light_ray; | ||
1390 | if (bump) | ||
1391 | { | ||
1392 | F32 offset_multiple; | ||
1393 | switch( bump_code ) | ||
1394 | { | ||
1395 | case BE_NO_BUMP: | ||
1396 | offset_multiple = 0.f; | ||
1397 | break; | ||
1398 | case BE_BRIGHTNESS: | ||
1399 | case BE_DARKNESS: | ||
1400 | if( mTexture.notNull() && mTexture->getHasGLTexture()) | ||
1401 | { | ||
1402 | // Offset by approximately one texel | ||
1403 | S32 cur_discard = mTexture->getDiscardLevel(); | ||
1404 | S32 max_size = llmax( mTexture->getWidth(), mTexture->getHeight() ); | ||
1405 | max_size <<= cur_discard; | ||
1406 | const F32 ARTIFICIAL_OFFSET = 2.f; | ||
1407 | offset_multiple = ARTIFICIAL_OFFSET / (F32)max_size; | ||
1408 | } | ||
1409 | else | ||
1410 | { | ||
1411 | offset_multiple = 1.f/256; | ||
1412 | } | ||
1413 | break; | ||
1414 | |||
1415 | default: // Standard bumpmap textures. Assumed to be 256x256 | ||
1416 | offset_multiple = 1.f / 256; | ||
1417 | break; | ||
1418 | } | ||
1419 | |||
1420 | F32 s_scale = 1.f; | ||
1421 | F32 t_scale = 1.f; | ||
1422 | if( tep ) | ||
1423 | { | ||
1424 | tep->getScale( &s_scale, &t_scale ); | ||
1425 | } | ||
1426 | LLVector3 sun_ray = gSky.getSunDirection(); | ||
1427 | LLVector3 moon_ray = gSky.getMoonDirection(); | ||
1428 | LLVector3& primary_light_ray = (sun_ray.mV[VZ] > 0) ? sun_ray : moon_ray; | ||
1429 | bump_s_primary_light_ray = offset_multiple * s_scale * primary_light_ray; | ||
1430 | bump_t_primary_light_ray = offset_multiple * t_scale * primary_light_ray; | ||
1431 | } | ||
1432 | |||
1433 | for (S32 i = 0; i < num_vertices; i++) | ||
1434 | { | ||
1435 | LLVector2 tc = vf.mVertices[i].mTexCoord; | ||
1436 | |||
1437 | U8 texgen = getTextureEntry()->getTexGen(); | ||
1438 | if (texgen != LLTextureEntry::TEX_GEN_DEFAULT) | ||
1439 | { | ||
1440 | |||
1441 | LLVector3 vec = vf.mVertices[i].mPosition; //-vf.mCenter; | ||
1442 | |||
1443 | if (global_volume) | ||
1444 | { | ||
1445 | vec -= render_pos; | ||
1446 | } | ||
1447 | else | ||
1448 | { | ||
1449 | vec.scaleVec(mVObjp->getScale()); | ||
1450 | } | ||
1451 | |||
1452 | switch (texgen) | ||
1453 | { | ||
1454 | case LLTextureEntry::TEX_GEN_PLANAR: | ||
1455 | planarProjection(tc, vf.mVertices[i], vf.mCenter, vec); | ||
1456 | break; | ||
1457 | case LLTextureEntry::TEX_GEN_SPHERICAL: | ||
1458 | sphericalProjection(tc, vf.mVertices[i], vf.mCenter, vec); | ||
1459 | break; | ||
1460 | case LLTextureEntry::TEX_GEN_CYLINDRICAL: | ||
1461 | cylindricalProjection(tc, vf.mVertices[i], vf.mCenter, vec); | ||
1462 | break; | ||
1463 | default: | ||
1464 | break; | ||
1465 | } | ||
1466 | } | ||
1467 | xform(tc, cos_ang, sin_ang, os, ot, ms, mt); | ||
1468 | *tex_coords++ = tc; | ||
1469 | if (grab_first_tcoord) | ||
1470 | { | ||
1471 | grab_first_tcoord = FALSE; | ||
1472 | tmin = tmax = tc; | ||
1473 | } | ||
1474 | else | ||
1475 | { | ||
1476 | for (U32 j = 0; j < 2; j++) | ||
1477 | { | ||
1478 | if (tmin.mV[j] > tc.mV[j]) | ||
1479 | { | ||
1480 | tmin.mV[j] = tc.mV[j]; | ||
1481 | } | ||
1482 | else if (tmax.mV[j] < tc.mV[j]) | ||
1483 | { | ||
1484 | tmax.mV[j] = tc.mV[j]; | ||
1485 | } | ||
1486 | } | ||
1487 | } | ||
1488 | if (bump) | ||
1489 | { | ||
1490 | LLVector3 tangent = vf.mVertices[i].mBinormal % vf.mVertices[i].mNormal; | ||
1491 | LLMatrix3 tangent_to_object; | ||
1492 | tangent_to_object.setRows(tangent, vf.mVertices[i].mBinormal, vf.mVertices[i].mNormal); | ||
1493 | LLVector3 binormal = binormal_dir * tangent_to_object; | ||
1494 | |||
1495 | if (!global_volume) | ||
1496 | { | ||
1497 | binormal = binormal * mat_normal; | ||
1498 | } | ||
1499 | binormal.normVec(); | ||
1500 | tangent.normVec(); | ||
1501 | |||
1502 | tc += LLVector2( bump_s_primary_light_ray * tangent, bump_t_primary_light_ray * binormal ); | ||
1503 | *tex_coords2++ = tc; | ||
1504 | |||
1505 | *binormals++ = binormal; | ||
1506 | } | ||
1507 | } | ||
1508 | } | ||
1509 | |||
1510 | index_offset += num_vertices; | ||
1511 | |||
1512 | center_sum += vf.mCenter * mat_vert; | ||
1513 | } | ||
1514 | |||
1515 | center_sum /= (F32)(fend-fstart+1); | ||
1516 | |||
1517 | if (is_static) | ||
1518 | { | ||
1519 | mCenterAgent = center_sum; | ||
1520 | mCenterLocal = mCenterAgent - mDrawablep->getPositionAgent(); | ||
1521 | } | ||
1522 | else | ||
1523 | { | ||
1524 | mCenterLocal = center_sum; | ||
1525 | updateCenterAgent(); | ||
1526 | } | ||
1527 | |||
1528 | if (!grab_first_vert && mDrawablep->isState(LLDrawable::REBUILD_VOLUME)) | ||
1529 | { | ||
1530 | mExtents[0] = min; | ||
1531 | mExtents[1] = max; | ||
1532 | } | ||
1533 | |||
1534 | if (!grab_first_tcoord && mDrawablep->isState(LLDrawable::REBUILD_TCOORD)) | ||
1535 | { | ||
1536 | mTexExtents[0] = tmin; | ||
1537 | mTexExtents[1] = tmax; | ||
1538 | } | ||
1539 | |||
1540 | return TRUE; | ||
1541 | } | ||
1542 | |||
1543 | BOOL LLFace::genLighting(const LLVolume* volume, const LLDrawable* drawablep, S32 fstart, S32 fend, | ||
1544 | const LLMatrix4& mat_vert, const LLMatrix3& mat_normal, BOOL do_lighting) | ||
1545 | { | ||
1546 | if (drawablep->isLight()) | ||
1547 | { | ||
1548 | do_lighting = FALSE; | ||
1549 | } | ||
1550 | |||
1551 | if (!((mDrawPoolp->mDataMaskIL) & LLDrawPool::DATA_COLORS_MASK)) | ||
1552 | { | ||
1553 | return FALSE; | ||
1554 | } | ||
1555 | if (mGeomIndex < 0) | ||
1556 | { | ||
1557 | return FALSE; // no geometry | ||
1558 | } | ||
1559 | LLStrider<LLColor4U> colorsp; | ||
1560 | S32 idx = getColors(colorsp); | ||
1561 | if (idx < 0) | ||
1562 | { | ||
1563 | return FALSE; | ||
1564 | } | ||
1565 | |||
1566 | for (S32 vol_face = fstart; vol_face <= fend; vol_face++) | ||
1567 | { | ||
1568 | const LLVolumeFace &vf = volume->getVolumeFace(vol_face); | ||
1569 | S32 num_vertices = (S32)vf.mVertices.size(); | ||
1570 | |||
1571 | if (isState(FULLBRIGHT) || !do_lighting) | ||
1572 | { | ||
1573 | for (S32 i = 0; i < num_vertices; i++) | ||
1574 | { | ||
1575 | (*colorsp++).setToBlack(); | ||
1576 | } | ||
1577 | } | ||
1578 | else | ||
1579 | { | ||
1580 | for (S32 i = 0; i < num_vertices; i++) | ||
1581 | { | ||
1582 | LLVector3 vertex = vf.mVertices[i].mPosition * mat_vert; | ||
1583 | LLVector3 normal = vf.mVertices[i].mNormal * mat_normal; | ||
1584 | normal.normVec(); | ||
1585 | |||
1586 | LLColor4 color; | ||
1587 | for (LLDrawable::drawable_set_t::const_iterator iter = drawablep->mLightSet.begin(); | ||
1588 | iter != drawablep->mLightSet.end(); ++iter) | ||
1589 | { | ||
1590 | LLDrawable* light_drawable = *iter; | ||
1591 | LLVOVolume* light = light_drawable->getVOVolume(); | ||
1592 | if (!light) | ||
1593 | { | ||
1594 | continue; | ||
1595 | } | ||
1596 | LLColor4 light_color; | ||
1597 | light->calcLightAtPoint(vertex, normal, light_color); | ||
1598 | color += light_color; | ||
1599 | } | ||
1600 | |||
1601 | color.mV[3] = 1.0f; | ||
1602 | |||
1603 | (*colorsp++).setVecScaleClamp(color); | ||
1604 | } | ||
1605 | } | ||
1606 | } | ||
1607 | return TRUE; | ||
1608 | } | ||
1609 | |||
1610 | BOOL LLFace::genShadows(const LLVolume* volume, const LLDrawable* drawablep, S32 fstart, S32 fend, | ||
1611 | const LLMatrix4& mat_vert, const LLMatrix3& mat_normal, BOOL use_shadow_factor) | ||
1612 | { | ||
1613 | if (drawablep->isLight()) | ||
1614 | { | ||
1615 | return FALSE; | ||
1616 | } | ||
1617 | |||
1618 | if (!((mDrawPoolp->mDataMaskIL) & LLDrawPool::DATA_COLORS_MASK)) | ||
1619 | { | ||
1620 | return FALSE; | ||
1621 | } | ||
1622 | if (mGeomIndex < 0) | ||
1623 | { | ||
1624 | return FALSE; // no geometry | ||
1625 | } | ||
1626 | LLStrider<LLColor4U> colorsp; | ||
1627 | S32 idx = getColors(colorsp); | ||
1628 | if (idx < 0) | ||
1629 | { | ||
1630 | return FALSE; | ||
1631 | } | ||
1632 | |||
1633 | for (S32 vol_face = fstart; vol_face <= fend; vol_face++) | ||
1634 | { | ||
1635 | const LLVolumeFace &vf = volume->getVolumeFace(vol_face); | ||
1636 | S32 num_vertices = (S32)vf.mVertices.size(); | ||
1637 | |||
1638 | if (isState(FULLBRIGHT)) | ||
1639 | { | ||
1640 | continue; | ||
1641 | } | ||
1642 | |||
1643 | for (S32 i = 0; i < num_vertices; i++) | ||
1644 | { | ||
1645 | LLVector3 vertex = vf.mVertices[i].mPosition * mat_vert; | ||
1646 | LLVector3 normal = vf.mVertices[i].mNormal * mat_normal; | ||
1647 | normal.normVec(); | ||
1648 | |||
1649 | U8 shadow; | ||
1650 | |||
1651 | if (use_shadow_factor) | ||
1652 | { | ||
1653 | shadow = (U8) (drawablep->getSunShadowFactor() * 255); | ||
1654 | } | ||
1655 | else | ||
1656 | { | ||
1657 | shadow = 255; | ||
1658 | } | ||
1659 | |||
1660 | (*colorsp++).mV[3] = shadow; | ||
1661 | } | ||
1662 | } | ||
1663 | return TRUE; | ||
1664 | } | ||
1665 | |||
1666 | BOOL LLFace::verify(const U32* indices_array) const | ||
1667 | { | ||
1668 | BOOL ok = TRUE; | ||
1669 | // First, check whether the face data fits within the pool's range. | ||
1670 | if ((mGeomIndex < 0) || (mGeomIndex + mGeomCount) > (S32)getPool()->getVertexCount()) | ||
1671 | { | ||
1672 | ok = FALSE; | ||
1673 | llinfos << "Face not within pool range!" << llendl; | ||
1674 | } | ||
1675 | |||
1676 | S32 indices_count = (S32)getIndicesCount(); | ||
1677 | S32 geom_start = getGeomStart(); | ||
1678 | S32 geom_count = mGeomCount; | ||
1679 | |||
1680 | if (!indices_count) | ||
1681 | { | ||
1682 | return TRUE; | ||
1683 | } | ||
1684 | |||
1685 | if (indices_count > LL_MAX_INDICES_COUNT) | ||
1686 | { | ||
1687 | ok = FALSE; | ||
1688 | llinfos << "Face has bogus indices count" << llendl; | ||
1689 | } | ||
1690 | |||
1691 | const U32 *indicesp = indices_array ? indices_array + mIndicesIndex : getRawIndices(); | ||
1692 | |||
1693 | for (S32 i = 0; i < indices_count; i++) | ||
1694 | { | ||
1695 | S32 delta = indicesp[i] - geom_start; | ||
1696 | if (0 > delta) | ||
1697 | { | ||
1698 | llwarns << "Face index too low!" << llendl; | ||
1699 | llinfos << "i:" << i << " Index:" << indicesp[i] << " GStart: " << geom_start << llendl; | ||
1700 | ok = FALSE; | ||
1701 | } | ||
1702 | else if (delta >= geom_count) | ||
1703 | { | ||
1704 | llwarns << "Face index too high!" << llendl; | ||
1705 | llinfos << "i:" << i << " Index:" << indicesp[i] << " GEnd: " << geom_start + geom_count << llendl; | ||
1706 | ok = FALSE; | ||
1707 | } | ||
1708 | } | ||
1709 | |||
1710 | if (!ok) | ||
1711 | { | ||
1712 | printDebugInfo(); | ||
1713 | } | ||
1714 | return ok; | ||
1715 | } | ||
1716 | |||
1717 | |||
1718 | void LLFace::setViewerObject(LLViewerObject* objp) | ||
1719 | { | ||
1720 | mVObjp = objp; | ||
1721 | } | ||
1722 | |||
1723 | void LLFace::enableLights() const | ||
1724 | { | ||
1725 | if (isState(FULLBRIGHT|HUD_RENDER)) | ||
1726 | { | ||
1727 | gPipeline.enableLightsFullbright(LLColor4::white); | ||
1728 | } | ||
1729 | else if (mDrawablep->isState(LLDrawable::LIGHTING_BUILT)) | ||
1730 | { | ||
1731 | gPipeline.enableLightsStatic(1.f); | ||
1732 | } | ||
1733 | else | ||
1734 | { | ||
1735 | gPipeline.enableLightsDynamic(1.f); | ||
1736 | } | ||
1737 | if (isState(LIGHT)) | ||
1738 | { | ||
1739 | const LLVOVolume* vovolume = (const LLVOVolume*)(mDrawablep->getVObj()); | ||
1740 | gPipeline.setAmbient(vovolume->getLightColor()); | ||
1741 | } | ||
1742 | } | ||
1743 | |||
1744 | const LLColor4& LLFace::getRenderColor() const | ||
1745 | { | ||
1746 | if (isState(USE_FACE_COLOR)) | ||
1747 | { | ||
1748 | return mFaceColor; // Face Color | ||
1749 | } | ||
1750 | else | ||
1751 | { | ||
1752 | const LLTextureEntry* tep = getTextureEntry(); | ||
1753 | return (tep ? tep->getColor() : LLColor4::white); | ||
1754 | } | ||
1755 | } | ||
1756 | |||
1757 | void LLFace::renderSetColor() const | ||
1758 | { | ||
1759 | if (!LLDrawPool::LLOverrideFaceColor::sOverrideFaceColor) | ||
1760 | { | ||
1761 | const LLColor4* color = &(getRenderColor()); | ||
1762 | |||
1763 | if ((mDrawPoolp->mVertexShaderLevel > 0) && (mDrawPoolp->getMaterialAttribIndex() != 0)) | ||
1764 | { | ||
1765 | glVertexAttrib4fvARB(mDrawPoolp->getMaterialAttribIndex(), color->mV); | ||
1766 | } | ||
1767 | else | ||
1768 | { | ||
1769 | glColor4fv(color->mV); | ||
1770 | } | ||
1771 | } | ||
1772 | } | ||
1773 | |||
1774 | S32 LLFace::pushVertices(const U32* index_array) const | ||
1775 | { | ||
1776 | U32 indices_count = mIndicesCount; | ||
1777 | S32 ret = 0; | ||
1778 | #if ENABLE_FACE_LINKING | ||
1779 | LLFace* next = mNextFace; | ||
1780 | #endif | ||
1781 | |||
1782 | if (mGeomCount < gGLManager.mGLMaxVertexRange && (S32) indices_count < gGLManager.mGLMaxIndexRange) | ||
1783 | { | ||
1784 | LLFace* current = (LLFace*) this; | ||
1785 | S32 geom_count = mGeomCount; | ||
1786 | #if ENABLE_FACE_LINKING | ||
1787 | while (current) | ||
1788 | { | ||
1789 | //chop up batch into implementation recommended sizes | ||
1790 | while (next && | ||
1791 | (current == next || | ||
1792 | ((S32) (indices_count + next->mIndicesCount) < gGLManager.mGLMaxIndexRange && | ||
1793 | geom_count + next->mGeomCount < gGLManager.mGLMaxVertexRange))) | ||
1794 | { | ||
1795 | indices_count += next->mIndicesCount; | ||
1796 | geom_count += next->mGeomCount; | ||
1797 | next = next->mNextFace; | ||
1798 | } | ||
1799 | #endif | ||
1800 | if (indices_count) | ||
1801 | { | ||
1802 | glDrawRangeElements(mPrimType, current->mGeomIndex, current->mGeomIndex + geom_count, indices_count, | ||
1803 | GL_UNSIGNED_INT, index_array + current->mIndicesIndex); | ||
1804 | } | ||
1805 | ret += (S32) indices_count; | ||
1806 | indices_count = 0; | ||
1807 | geom_count = 0; | ||
1808 | #if ENABLE_FACE_LINKING | ||
1809 | current = next; | ||
1810 | } | ||
1811 | #endif | ||
1812 | } | ||
1813 | else | ||
1814 | { | ||
1815 | #if ENABLE_FACE_LINKING | ||
1816 | while (next) | ||
1817 | { | ||
1818 | indices_count += next->mIndicesCount; | ||
1819 | next = next->mNextFace; | ||
1820 | } | ||
1821 | #endif | ||
1822 | if (indices_count) | ||
1823 | { | ||
1824 | glDrawElements(mPrimType, indices_count, GL_UNSIGNED_INT, index_array + mIndicesIndex); | ||
1825 | } | ||
1826 | ret += (S32) indices_count; | ||
1827 | } | ||
1828 | |||
1829 | return ret; | ||
1830 | |||
1831 | } | ||
1832 | |||
1833 | const LLMatrix4& LLFace::getRenderMatrix() const | ||
1834 | { | ||
1835 | return mDrawablep->getRenderMatrix(); | ||
1836 | } | ||
1837 | |||
1838 | S32 LLFace::renderElements(const U32 *index_array) const | ||
1839 | { | ||
1840 | S32 ret = 0; | ||
1841 | |||
1842 | if (isState(GLOBAL)) | ||
1843 | { | ||
1844 | ret = pushVertices(index_array); | ||
1845 | } | ||
1846 | else | ||
1847 | { | ||
1848 | glPushMatrix(); | ||
1849 | glMultMatrixf((float*)getRenderMatrix().mMatrix); | ||
1850 | ret = pushVertices(index_array); | ||
1851 | glPopMatrix(); | ||
1852 | } | ||
1853 | |||
1854 | return ret; | ||
1855 | } | ||
1856 | |||
1857 | S32 LLFace::renderIndexed(const U32 *index_array) const | ||
1858 | { | ||
1859 | if (mSkipRender) | ||
1860 | { | ||
1861 | return 0; | ||
1862 | } | ||
1863 | |||
1864 | if(mGeomIndex < 0 || mDrawablep.isNull()) | ||
1865 | { | ||
1866 | return 0; | ||
1867 | } | ||
1868 | |||
1869 | renderSetColor(); | ||
1870 | return renderElements(index_array); | ||
1871 | } | ||
1872 | |||
1873 | //============================================================================ | ||
1874 | // From llface.inl | ||
1875 | |||
1876 | S32 LLFace::getVertices(LLStrider<LLVector3> &vertices) | ||
1877 | { | ||
1878 | if (!mGeomCount) | ||
1879 | { | ||
1880 | return -1; | ||
1881 | } | ||
1882 | if (isState(BACKLIST)) | ||
1883 | { | ||
1884 | if (!mBackupMem) | ||
1885 | { | ||
1886 | printDebugInfo(); | ||
1887 | llerrs << "No backup memory for face" << llendl; | ||
1888 | } | ||
1889 | vertices = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_VERTICES]); | ||
1890 | vertices.setStride( mDrawPoolp->getStride()); | ||
1891 | return 0; | ||
1892 | } | ||
1893 | else | ||
1894 | { | ||
1895 | if (mGeomIndex >= 0) // flexible objects may not have geometry | ||
1896 | { | ||
1897 | mDrawPoolp->getVertexStrider(vertices, mGeomIndex); | ||
1898 | mDrawPoolp->setDirty(); | ||
1899 | } | ||
1900 | return mGeomIndex; | ||
1901 | } | ||
1902 | } | ||
1903 | |||
1904 | S32 LLFace::getColors(LLStrider<LLColor4U> &colors) | ||
1905 | { | ||
1906 | if (!mGeomCount) | ||
1907 | { | ||
1908 | return -1; | ||
1909 | } | ||
1910 | if (isState(BACKLIST)) | ||
1911 | { | ||
1912 | llassert(mBackupMem); | ||
1913 | colors = (LLColor4U*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_COLORS]); | ||
1914 | colors.setStride( mDrawPoolp->getStride()); | ||
1915 | return 0; | ||
1916 | } | ||
1917 | else | ||
1918 | { | ||
1919 | llassert(mGeomIndex >= 0); | ||
1920 | mDrawPoolp->getColorStrider(colors, mGeomIndex); | ||
1921 | return mGeomIndex; | ||
1922 | } | ||
1923 | } | ||
1924 | |||
1925 | S32 LLFace::getIndices(U32* &indicesp) | ||
1926 | { | ||
1927 | if (isState(BACKLIST)) | ||
1928 | { | ||
1929 | indicesp = (U32*)mBackupMem; | ||
1930 | return 0; | ||
1931 | } | ||
1932 | else | ||
1933 | { | ||
1934 | indicesp = mDrawPoolp->getIndices(mIndicesIndex); | ||
1935 | llassert(mGeomIndex >= 0 && indicesp[0] != indicesp[1]); | ||
1936 | return mGeomIndex; | ||
1937 | } | ||
1938 | } | ||
1939 | |||
1940 | void LLFace::link(LLFace* facep) | ||
1941 | { | ||
1942 | #if ENABLE_FACE_LINKING | ||
1943 | mNextFace = facep; | ||
1944 | facep->mSkipRender = TRUE; | ||
1945 | #endif | ||
1946 | } | ||
1947 | |||
1948 | LLVector3 LLFace::getPositionAgent() const | ||
1949 | { | ||
1950 | if (mDrawablep->isStatic()) | ||
1951 | { | ||
1952 | return mCenterAgent; | ||
1953 | } | ||
1954 | else | ||
1955 | { | ||
1956 | return mCenterLocal * getRenderMatrix(); | ||
1957 | } | ||
1958 | } | ||