aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llface.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llface.cpp
parentREADME.txt (diff)
downloadmeta-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.cpp1958
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
54extern BOOL gPickFaces;
55
56BOOL 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/*
62For each vertex, given:
63 B - binormal
64 T - tangent
65 N - normal
66 P - position
67
68The resulting texture coordinate <u,v> is:
69
70 u = 2(B dot P)
71 v = 2(T dot P)
72*/
73void 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
99void 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
110void 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
138void 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
169void 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
188void LLFace::initClass()
189{
190}
191
192void LLFace::setWorldMatrix(const LLMatrix4 &mat)
193{
194 llerrs << "Faces on this drawable are not independently modifiable\n" << llendl;
195}
196
197
198void LLFace::setDirty()
199{
200 mGeneration = DIRTY;
201}
202
203void 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
248void LLFace::setTEOffset(const S32 te_offset)
249{
250 mTEOffset = te_offset;
251}
252
253
254void LLFace::setFaceColor(const LLColor4& color)
255{
256 mFaceColor = color;
257 setState(USE_FACE_COLOR);
258}
259
260void LLFace::unsetFaceColor()
261{
262 clearState(USE_FACE_COLOR);
263}
264
265void LLFace::setDrawable(LLDrawable *drawable)
266{
267 mDrawablep = drawable;
268 mXform = &drawable->mXform;
269}
270
271S32 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
295void 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
319BOOL 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
347void 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
360S32 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
420S32 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
482S32 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
538S32 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
550S32 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
628void LLFace::updateCenterAgent()
629{
630 mCenterAgent = mCenterLocal * getRenderMatrix();
631}
632
633void 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
732void 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
863void 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
990void 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
1063S32 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
1141void 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.
1207static 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
1235BOOL 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
1246BOOL 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
1543BOOL 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
1610BOOL 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
1666BOOL 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
1718void LLFace::setViewerObject(LLViewerObject* objp)
1719{
1720 mVObjp = objp;
1721}
1722
1723void 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
1744const 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
1757void 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
1774S32 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
1833const LLMatrix4& LLFace::getRenderMatrix() const
1834{
1835 return mDrawablep->getRenderMatrix();
1836}
1837
1838S32 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
1857S32 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
1876S32 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
1904S32 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
1925S32 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
1940void LLFace::link(LLFace* facep)
1941{
1942#if ENABLE_FACE_LINKING
1943 mNextFace = facep;
1944 facep->mSkipRender = TRUE;
1945#endif
1946}
1947
1948LLVector3 LLFace::getPositionAgent() const
1949{
1950 if (mDrawablep->isStatic())
1951 {
1952 return mCenterAgent;
1953 }
1954 else
1955 {
1956 return mCenterLocal * getRenderMatrix();
1957 }
1958}