aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llviewerjointmesh.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/llviewerjointmesh.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 'linden/indra/newview/llviewerjointmesh.cpp')
-rw-r--r--linden/indra/newview/llviewerjointmesh.cpp1620
1 files changed, 1620 insertions, 0 deletions
diff --git a/linden/indra/newview/llviewerjointmesh.cpp b/linden/indra/newview/llviewerjointmesh.cpp
new file mode 100644
index 0000000..96cdb88
--- /dev/null
+++ b/linden/indra/newview/llviewerjointmesh.cpp
@@ -0,0 +1,1620 @@
1/**
2 * @file llviewerjointmesh.cpp
3 * @brief Implementation of LLViewerJointMesh class
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//-----------------------------------------------------------------------------
29// Header Files
30//-----------------------------------------------------------------------------
31#include "llviewerprecompiledheaders.h"
32
33#if LL_WINDOWS // For Intel vector classes
34 #include "fvec.h"
35#endif
36
37#include "imageids.h"
38#include "llfasttimer.h"
39
40#include "llagent.h"
41#include "llagparray.h"
42#include "llbox.h"
43#include "lldrawable.h"
44#include "lldrawpoolavatar.h"
45#include "lldrawpoolbump.h"
46#include "lldynamictexture.h"
47#include "llface.h"
48#include "llgldbg.h"
49#include "llglheaders.h"
50#include "lltexlayer.h"
51#include "llviewercamera.h"
52#include "llviewerimagelist.h"
53#include "llviewerjointmesh.h"
54#include "llvoavatar.h"
55#include "llsky.h"
56#include "pipeline.h"
57
58#if !LL_DARWIN && !LL_LINUX
59extern PFNGLWEIGHTPOINTERARBPROC glWeightPointerARB;
60extern PFNGLWEIGHTFVARBPROC glWeightfvARB;
61extern PFNGLVERTEXBLENDARBPROC glVertexBlendARB;
62#endif
63extern BOOL gRenderForSelect;
64
65LLMatrix4 gBlendMat;
66
67//-----------------------------------------------------------------------------
68//-----------------------------------------------------------------------------
69// LLViewerJointMesh::LLSkinJoint
70//-----------------------------------------------------------------------------
71//-----------------------------------------------------------------------------
72
73//-----------------------------------------------------------------------------
74// LLSkinJoint
75//-----------------------------------------------------------------------------
76LLSkinJoint::LLSkinJoint()
77{
78 mJoint = NULL;
79}
80
81//-----------------------------------------------------------------------------
82// ~LLSkinJoint
83//-----------------------------------------------------------------------------
84LLSkinJoint::~LLSkinJoint()
85{
86 mJoint = NULL;
87}
88
89
90//-----------------------------------------------------------------------------
91// LLSkinJoint::setupSkinJoint()
92//-----------------------------------------------------------------------------
93BOOL LLSkinJoint::setupSkinJoint( LLViewerJoint *joint)
94{
95 // find the named joint
96 mJoint = joint;
97 if ( !mJoint )
98 {
99 llinfos << "Can't find joint" << llendl;
100 }
101
102 // compute the inverse root skin matrix
103 mRootToJointSkinOffset.clearVec();
104
105 LLVector3 rootSkinOffset;
106 while (joint)
107 {
108 rootSkinOffset += joint->getSkinOffset();
109 joint = (LLViewerJoint*)joint->getParent();
110 }
111
112 mRootToJointSkinOffset = -rootSkinOffset;
113 mRootToParentJointSkinOffset = mRootToJointSkinOffset;
114 mRootToParentJointSkinOffset += mJoint->getSkinOffset();
115
116 return TRUE;
117}
118
119//-----------------------------------------------------------------------------
120//-----------------------------------------------------------------------------
121// LLViewerJointMesh
122//-----------------------------------------------------------------------------
123//-----------------------------------------------------------------------------
124
125BOOL LLViewerJointMesh::sPipelineRender = FALSE;
126EAvatarRenderPass LLViewerJointMesh::sRenderPass = AVATAR_RENDER_PASS_SINGLE;
127U32 LLViewerJointMesh::sClothingMaskImageName = 0;
128LLColor4 LLViewerJointMesh::sClothingInnerColor;
129
130//-----------------------------------------------------------------------------
131// LLViewerJointMesh()
132//-----------------------------------------------------------------------------
133LLViewerJointMesh::LLViewerJointMesh()
134 :
135 mTexture( NULL ),
136 mLayerSet( NULL ),
137 mTestImageName( 0 ),
138 mIsTransparent(FALSE)
139{
140
141 mColor[0] = 1.0f;
142 mColor[1] = 1.0f;
143 mColor[2] = 1.0f;
144 mColor[3] = 1.0f;
145 mShiny = 0.0f;
146 mCullBackFaces = TRUE;
147
148 mMesh = NULL;
149
150 mNumSkinJoints = 0;
151 mSkinJoints = NULL;
152
153 mFace = NULL;
154
155 mMeshID = 0;
156 mUpdateXform = FALSE;
157
158 mValid = FALSE;
159}
160
161
162//-----------------------------------------------------------------------------
163// ~LLViewerJointMesh()
164// Class Destructor
165//-----------------------------------------------------------------------------
166LLViewerJointMesh::~LLViewerJointMesh()
167{
168 mMesh = NULL;
169 mTexture = NULL;
170 freeSkinData();
171}
172
173
174//-----------------------------------------------------------------------------
175// LLViewerJointMesh::allocateSkinData()
176//-----------------------------------------------------------------------------
177BOOL LLViewerJointMesh::allocateSkinData( U32 numSkinJoints )
178{
179 mSkinJoints = new LLSkinJoint[ numSkinJoints ];
180 mNumSkinJoints = numSkinJoints;
181 return TRUE;
182}
183
184//-----------------------------------------------------------------------------
185// getSkinJointByIndex()
186//-----------------------------------------------------------------------------
187S32 LLViewerJointMesh::getBoundJointsByIndex(S32 index, S32 &joint_a, S32& joint_b)
188{
189 S32 num_joints = 0;
190 if (mNumSkinJoints == 0)
191 {
192 return num_joints;
193 }
194
195 joint_a = -1;
196 joint_b = -1;
197
198 LLPolyMesh *reference_mesh = mMesh->getReferenceMesh();
199
200 if (index < reference_mesh->mJointRenderData.count())
201 {
202 LLJointRenderData* render_datap = reference_mesh->mJointRenderData[index];
203 if (render_datap->mSkinJoint)
204 {
205 joint_a = render_datap->mSkinJoint->mJoint->mJointNum;
206 }
207 num_joints++;
208 }
209 if (index + 1 < reference_mesh->mJointRenderData.count())
210 {
211 LLJointRenderData* render_datap = reference_mesh->mJointRenderData[index + 1];
212 if (render_datap->mSkinJoint)
213 {
214 joint_b = render_datap->mSkinJoint->mJoint->mJointNum;
215 }
216
217 if (joint_a == -1)
218 {
219 joint_a = render_datap->mSkinJoint->mJoint->getParent()->mJointNum;
220 }
221 num_joints++;
222 }
223 return num_joints;
224}
225
226//-----------------------------------------------------------------------------
227// LLViewerJointMesh::freeSkinData()
228//-----------------------------------------------------------------------------
229void LLViewerJointMesh::freeSkinData()
230{
231 mNumSkinJoints = 0;
232 delete [] mSkinJoints;
233 mSkinJoints = NULL;
234}
235
236//--------------------------------------------------------------------
237// LLViewerJointMesh::getColor()
238//--------------------------------------------------------------------
239void LLViewerJointMesh::getColor( F32 *red, F32 *green, F32 *blue, F32 *alpha )
240{
241 *red = mColor[0];
242 *green = mColor[1];
243 *blue = mColor[2];
244 *alpha = mColor[3];
245}
246
247//--------------------------------------------------------------------
248// LLViewerJointMesh::setColor()
249//--------------------------------------------------------------------
250void LLViewerJointMesh::setColor( F32 red, F32 green, F32 blue, F32 alpha )
251{
252 mColor[0] = red;
253 mColor[1] = green;
254 mColor[2] = blue;
255 mColor[3] = alpha;
256}
257
258
259//--------------------------------------------------------------------
260// LLViewerJointMesh::getTexture()
261//--------------------------------------------------------------------
262//LLViewerImage *LLViewerJointMesh::getTexture()
263//{
264// return mTexture;
265//}
266
267//--------------------------------------------------------------------
268// LLViewerJointMesh::setTexture()
269//--------------------------------------------------------------------
270void LLViewerJointMesh::setTexture( LLViewerImage *texture )
271{
272 mTexture = texture;
273
274 // texture and dynamic_texture are mutually exclusive
275 if( texture )
276 {
277 mLayerSet = NULL;
278 //texture->bindTexture(0);
279 //texture->setClamp(TRUE, TRUE);
280 }
281}
282
283//--------------------------------------------------------------------
284// LLViewerJointMesh::setLayerSet()
285// Sets the shape texture (takes precedence over normal texture)
286//--------------------------------------------------------------------
287void LLViewerJointMesh::setLayerSet( LLTexLayerSet* layer_set )
288{
289 mLayerSet = layer_set;
290
291 // texture and dynamic_texture are mutually exclusive
292 if( layer_set )
293 {
294 mTexture = NULL;
295 }
296}
297
298
299
300//--------------------------------------------------------------------
301// LLViewerJointMesh::getMesh()
302//--------------------------------------------------------------------
303LLPolyMesh *LLViewerJointMesh::getMesh()
304{
305 return mMesh;
306}
307
308//-----------------------------------------------------------------------------
309// LLViewerJointMesh::setMesh()
310//-----------------------------------------------------------------------------
311void LLViewerJointMesh::setMesh( LLPolyMesh *mesh )
312{
313 // set the mesh pointer
314 mMesh = mesh;
315
316 // release any existing skin joints
317 freeSkinData();
318
319 if ( mMesh == NULL )
320 {
321 return;
322 }
323
324 // acquire the transform from the mesh object
325 setPosition( mMesh->getPosition() );
326 setRotation( mMesh->getRotation() );
327 setScale( mMesh->getScale() );
328
329 // create skin joints if necessary
330 if ( mMesh->hasWeights() && !mMesh->isLOD())
331 {
332 U32 numJointNames = mMesh->getNumJointNames();
333
334 allocateSkinData( numJointNames );
335 std::string *jointNames = mMesh->getJointNames();
336
337 U32 jn;
338 for (jn = 0; jn < numJointNames; jn++)
339 {
340 //llinfos << "Setting up joint " << jointNames[jn].c_str() << llendl;
341 LLViewerJoint* joint = (LLViewerJoint*)(getRoot()->findJoint(jointNames[jn]) );
342 mSkinJoints[jn].setupSkinJoint( joint );
343 }
344 }
345
346 // setup joint array
347 if (!mMesh->isLOD())
348 {
349 setupJoint((LLViewerJoint*)getRoot());
350 }
351
352// llinfos << "joint render entries: " << mMesh->mJointRenderData.count() << llendl;
353}
354
355//-----------------------------------------------------------------------------
356// setupJoint()
357//-----------------------------------------------------------------------------
358void LLViewerJointMesh::setupJoint(LLViewerJoint* current_joint)
359{
360// llinfos << "Mesh: " << getName() << llendl;
361
362// S32 joint_count = 0;
363 U32 sj;
364 for (sj=0; sj<mNumSkinJoints; sj++)
365 {
366 LLSkinJoint &js = mSkinJoints[sj];
367
368 if (js.mJoint != current_joint)
369 {
370 continue;
371 }
372
373 // we've found a skinjoint for this joint..
374
375 // is the last joint in the array our parent?
376 if(mMesh->mJointRenderData.count() && mMesh->mJointRenderData[mMesh->mJointRenderData.count() - 1]->mWorldMatrix == &current_joint->getParent()->getWorldMatrix())
377 {
378 // ...then just add ourselves
379 LLViewerJoint* jointp = js.mJoint;
380 mMesh->mJointRenderData.put(new LLJointRenderData(&jointp->getWorldMatrix(), &js));
381// llinfos << "joint " << joint_count << js.mJoint->getName() << llendl;
382// joint_count++;
383 }
384 // otherwise add our parent and ourselves
385 else
386 {
387 mMesh->mJointRenderData.put(new LLJointRenderData(&current_joint->getParent()->getWorldMatrix(), NULL));
388// llinfos << "joint " << joint_count << current_joint->getParent()->getName() << llendl;
389// joint_count++;
390 mMesh->mJointRenderData.put(new LLJointRenderData(&current_joint->getWorldMatrix(), &js));
391// llinfos << "joint " << joint_count << current_joint->getName() << llendl;
392// joint_count++;
393 }
394 }
395
396 // depth-first traversal
397 for (LLJoint *child_joint = current_joint->mChildren.getFirstData();
398 child_joint;
399 child_joint = current_joint->mChildren.getNextData())
400 {
401 setupJoint((LLViewerJoint*)child_joint);
402 }
403}
404
405const S32 NUM_AXES = 3;
406
407// register layoud
408// rotation X 0-n
409// rotation Y 0-n
410// rotation Z 0-n
411// pivot parent 0-n -- child = n+1
412
413static LLMatrix4 gJointMat[32];
414static LLMatrix3 gJointRot[32];
415static LLVector4 gJointPivot[32];
416
417//-----------------------------------------------------------------------------
418// uploadJointMatrices()
419//-----------------------------------------------------------------------------
420void LLViewerJointMesh::uploadJointMatrices()
421{
422 S32 joint_num;
423 LLPolyMesh *reference_mesh = mMesh->getReferenceMesh();
424 LLDrawPool *poolp = mFace ? mFace->getPool() : NULL;
425 BOOL hardware_skinning = (poolp && poolp->getVertexShaderLevel() > 0) ? TRUE : FALSE;
426
427 //calculate joint matrices
428 for (joint_num = 0; joint_num < reference_mesh->mJointRenderData.count(); joint_num++)
429 {
430 LLMatrix4 joint_mat = *reference_mesh->mJointRenderData[joint_num]->mWorldMatrix;
431
432 if (hardware_skinning)
433 {
434 joint_mat *= gCamera->getModelview();
435 }
436 gJointMat[joint_num] = joint_mat;
437 gJointRot[joint_num] = joint_mat.getMat3();
438 }
439
440 BOOL last_pivot_uploaded = FALSE;
441 S32 j = 0;
442
443 //upload joint pivots
444 for (joint_num = 0; joint_num < reference_mesh->mJointRenderData.count(); joint_num++)
445 {
446 LLSkinJoint *sj = reference_mesh->mJointRenderData[joint_num]->mSkinJoint;
447 if (sj)
448 {
449 if (!last_pivot_uploaded)
450 {
451 LLVector4 parent_pivot(sj->mRootToParentJointSkinOffset);
452 parent_pivot.mV[VW] = 0.f;
453 gJointPivot[j++] = parent_pivot;
454 }
455
456 LLVector4 child_pivot(sj->mRootToJointSkinOffset);
457 child_pivot.mV[VW] = 0.f;
458
459 gJointPivot[j++] = child_pivot;
460
461 last_pivot_uploaded = TRUE;
462 }
463 else
464 {
465 last_pivot_uploaded = FALSE;
466 }
467 }
468
469 //add pivot point into transform
470 for (S32 i = 0; i < j; i++)
471 {
472 LLVector3 pivot;
473 pivot = LLVector3(gJointPivot[i]);
474 pivot = pivot * gJointRot[i];
475 gJointMat[i].translate(pivot);
476 }
477
478 // upload matrices
479 if (hardware_skinning)
480 {
481 GLfloat mat[45*4];
482 memset(mat, 0, sizeof(GLfloat)*45*4);
483
484 for (joint_num = 0; joint_num < reference_mesh->mJointRenderData.count(); joint_num++)
485 {
486 gJointMat[joint_num].transpose();
487
488 for (S32 axis = 0; axis < NUM_AXES; axis++)
489 {
490 F32* vector = gJointMat[joint_num].mMatrix[axis];
491 //glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, LL_CHARACTER_MAX_JOINTS_PER_MESH * axis + joint_num+5, (GLfloat*)vector);
492 U32 offset = LL_CHARACTER_MAX_JOINTS_PER_MESH*axis+joint_num;
493 memcpy(mat+offset*4, vector, sizeof(GLfloat)*4);
494 //glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, LL_CHARACTER_MAX_JOINTS_PER_MESH * axis + joint_num+6, (GLfloat*)vector);
495 //cgGLSetParameterArray4f(gPipeline.mAvatarMatrix, offset, 1, vector);
496 }
497 }
498 glUniform4fvARB(gPipeline.mAvatarMatrixParam, 45, mat);
499 }
500}
501
502//--------------------------------------------------------------------
503// LLViewerJointMesh::drawBone()
504//--------------------------------------------------------------------
505void LLViewerJointMesh::drawBone()
506{
507}
508
509//--------------------------------------------------------------------
510// LLViewerJointMesh::isTransparent()
511//--------------------------------------------------------------------
512BOOL LLViewerJointMesh::isTransparent()
513{
514 return mIsTransparent;
515}
516
517//--------------------------------------------------------------------
518// DrawElementsBLEND and utility code
519//--------------------------------------------------------------------
520
521// compate_int is used by the qsort function to sort the index array
522int compare_int(const void *a, const void *b)
523{
524 if (*(U32*)a < *(U32*)b)
525 {
526 return -1;
527 }
528 else if (*(U32*)a > *(U32*)b)
529 {
530 return 1;
531 }
532 else return 0;
533}
534
535#if LL_WINDOWS || (LL_DARWIN && __i386__) // SSE optimizations in avatar code
536
537#if LL_DARWIN
538#include <xmmintrin.h>
539
540 // On Windows, this class is defined in fvec.h. I've only reproduced the parts of it we use here for now.
541 #pragma pack(push,16) /* Must ensure class & union 16-B aligned */
542 class F32vec4
543 {
544 protected:
545 __m128 vec;
546 public:
547
548 /* Constructors: __m128, 4 floats, 1 float */
549 F32vec4() {}
550
551 /* initialize 4 SP FP with __m128 data type */
552 F32vec4(__m128 m) { vec = m;}
553
554 /* Explicitly initialize each of 4 SP FPs with same float */
555 explicit F32vec4(float f) { vec = _mm_set_ps1(f); }
556 };
557 #pragma pack(pop) /* 16-B aligned */
558
559
560#endif
561
562void blend_SSE_32_32_batch(const int vert_offset, const int vert_count, float* output,
563 LLStrider<LLVector3>& vertices, LLStrider<LLVector2>& texcoords, LLStrider<LLVector3>& normals, LLStrider<F32>& weights)
564{
565 F32 last_weight = F32_MAX;
566 LLMatrix4 *blend_mat = &gBlendMat;
567
568 for (S32 index = vert_offset; index < vert_offset + vert_count; index++)
569 {
570 F32 w = weights [index]; // register copy of weight
571 F32 *vin = &vertices[index].mV[0]; // pointer to input vertex data, assumed to be V3+T2+N3+whatever
572 F32 *vout = output + index * (AVATAR_VERTEX_BYTES/sizeof(F32)); // pointer to the output vertex data, assumed to be 16 byte aligned
573
574 if (w == last_weight)
575 {
576 // load input and output vertices, and last blended matrix
577 __asm {
578 mov esi, vin
579 mov edi, vout
580
581 mov edx, blend_mat
582 movaps xmm4, [edx]
583 movaps xmm5, [edx+0x10]
584 movaps xmm6, [edx+0x20]
585 movaps xmm7, [edx+0x30]
586 }
587 }
588 else
589 {
590 last_weight = w;
591 S32 joint = llfloor(w);
592 w -= joint;
593
594 LLMatrix4 *m0 = &(gJointMat[joint+1]);
595 LLMatrix4 *m1 = &(gJointMat[joint+0]);
596
597 // some initial code to load Matrix 0 into SSE registers
598 __asm {
599 mov esi, vin
600 mov edi, vout
601
602 //matrix2
603 mov edx, m0
604 movaps xmm4, [edx]
605 movaps xmm5, [edx+0x10]
606 movaps xmm6, [edx+0x20]
607 movaps xmm7, [edx+0x30]
608 };
609
610 // if w == 1.0f, we don't need to blend.
611 // but since we do the trick of blending the matrices, here, if w != 1.0,
612 // we load Matrix 1 into the other 4 SSE registers and blend both matrices
613 // based on the weight (which we load ingo a 16-byte aligned vector: w,w,w,w)
614
615 if (w != 1.0f)
616 {
617 F32vec4 weight(w);
618
619 __asm { // do blending of matrices instead of verts and normals -- faster
620 mov edx, m1
621 movaps xmm0, [edx]
622 movaps xmm1, [edx+0x10]
623 movaps xmm2, [edx+0x20]
624 movaps xmm3, [edx+0x30]
625
626 subps xmm4, xmm0 // do blend for each matrix column
627 subps xmm5, xmm1 // diff, then multiply weight and re-add
628 subps xmm6, xmm2
629 subps xmm7, xmm3
630
631 mulps xmm4, weight
632 mulps xmm5, weight
633 mulps xmm6, weight
634 mulps xmm7, weight
635
636 addps xmm4, xmm0
637 addps xmm5, xmm1
638 addps xmm6, xmm2
639 addps xmm7, xmm3
640 };
641 }
642
643 __asm {
644 // save off blended matrix
645 mov edx, blend_mat;
646 movaps [edx], xmm4;
647 movaps [edx+0x10], xmm5;
648 movaps [edx+0x20], xmm6;
649 movaps [edx+0x30], xmm7;
650 }
651 }
652
653 // now, we have either a blended matrix in xmm4-7 or the original Matrix 0
654 // we then multiply each vertex and normal by this one matrix.
655
656 // For SSE2, we would try to keep the original two matrices in other registers
657 // and avoid reloading them. However, they should ramain in L1 cache in the
658 // current case.
659
660 // One possible optimization would be to sort the vertices by weight instead
661 // of just index (we still want to uniqify). If we note when two or more vertices
662 // share the same weight, we can avoid doing the middle SSE code above and just
663 // re-use the blended matrix for those vertices
664
665
666 // now, we do the actual vertex blending
667 __asm {
668 // load Vertex into xmm0.
669 movaps xmm0, [esi] // change aps to ups when input is no longer 16-baligned
670 movaps xmm1, xmm0 // copy vector into xmm0 through xmm2 (x,y,z)
671 movaps xmm2, xmm0
672 shufps xmm0, xmm0, _MM_SHUFFLE(0,0,0,0); // clone vertex (x) across vector
673 shufps xmm1, xmm1, _MM_SHUFFLE(1,1,1,1); // clone vertex (y) across vector
674 shufps xmm2, xmm2, _MM_SHUFFLE(2,2,2,2); // same for Z
675 mulps xmm0, xmm4 // do the actual matrix multipication for r0
676 mulps xmm1, xmm5 // for r1
677 mulps xmm2, xmm6 // for r2
678 addps xmm0, xmm1 // accumulate
679 addps xmm0, xmm2 // accumulate
680 addps xmm0, xmm7 // add in the row 4 which holds the x,y,z translation. assumes w=1 (vertex-w, not weight)
681
682 movaps [edi], xmm0 // store aligned in output array
683
684 // load Normal into xmm0.
685 movaps xmm0, [esi + 0x10] // change aps to ups when input no longer 16-byte aligned
686 movaps xmm1, xmm0 //
687 movaps xmm2, xmm0
688 shufps xmm0, xmm0, _MM_SHUFFLE(0,0,0,0); // since UV sits between vertex and normal, normal starts at element 1, not 0
689 shufps xmm1, xmm1, _MM_SHUFFLE(1,1,1,1);
690 shufps xmm2, xmm2, _MM_SHUFFLE(2,2,2,2);
691 mulps xmm0, xmm4 // multiply by matrix
692 mulps xmm1, xmm5 // multiply
693 mulps xmm2, xmm6 // multiply
694 addps xmm0, xmm1 // accumulate
695 addps xmm0, xmm2 // accumulate. note: do not add translation component to normals, save time too
696 movaps [edi + 0x10], xmm0 // store aligned
697 }
698
699 *(LLVector2*)(vout + (AVATAR_OFFSET_TEX0/sizeof(F32))) = texcoords[index]; // write texcoord into appropriate spot.
700 }
701}
702
703#elif LL_LINUX
704
705void blend_SSE_32_32_batch(const int vert_offset, const int vert_count, float* output,
706 LLStrider<LLVector3>& vertices, LLStrider<LLVector2>& texcoords, LLStrider<LLVector3>& normals, LLStrider<F32>& weights)
707{
708 assert(0);
709}
710
711#elif LL_DARWIN
712// AltiVec versions of the same...
713
714static inline vector float loadAlign(int offset, vector float *addr)
715{
716 vector float in0 = vec_ld(offset, addr);
717 vector float in1 = vec_ld(offset + 16, addr);
718 vector unsigned char perm = vec_lvsl(0, (unsigned char*)addr);
719
720 return(vec_perm(in0, in1, perm));
721}
722
723static inline void storeAlign(vector float v, int offset, vector float *addr)
724{
725 vector float in0 = vec_ld(offset, addr);
726 vector float in1 = vec_ld(offset + 16, addr);
727 vector unsigned char perm = vec_lvsr(0, (unsigned char *)addr);
728 vector float temp = vec_perm(v, v, perm);
729 vector unsigned char mask = (vector unsigned char)vec_cmpgt(perm, vec_splat_u8(15));
730
731 in0 = vec_sel(in0, temp, (vector unsigned int)mask);
732 in1 = vec_sel(temp, in1, (vector unsigned int)mask);
733
734 vec_st(in0, offset, addr);
735 vec_st(in1, offset + 16, addr);
736}
737
738void blend_SSE_32_32_batch(const int vert_offset, const int vert_count, float* output,
739 LLStrider<LLVector3>& vertices, LLStrider<LLVector2>& texcoords, LLStrider<LLVector3>& normals, LLStrider<F32>& weights)
740{
741 F32 last_weight = F32_MAX;
742// LLMatrix4 &blend_mat = gBlendMat;
743
744 vector float matrix0_0, matrix0_1, matrix0_2, matrix0_3;
745 vector unsigned char out0perm = (vector unsigned char) ( 0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17, 0x18,0x19,0x1A,0x1B, 0x0C,0x0D,0x0E,0x0F );
746// vector unsigned char out1perm = (vector unsigned char) ( 0x00,0x01,0x02,0x03, 0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17, 0x18,0x19,0x1A,0x1B );
747 vector unsigned char out1perm = (vector unsigned char) ( 0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17, 0x18,0x19,0x1A,0x1B, 0x0C,0x0D,0x0E,0x0F );
748
749 vector float zero = (vector float)vec_splat_u32(0);
750
751 for (U32 index = vert_offset; index < vert_offset + vert_count; index++)
752 {
753 F32 w = weights [index]; // register copy of weight
754 F32 *vin = &vertices[index].mV[0]; // pointer to input vertex data, assumed to be V3+T2+N3+whatever
755 F32 *vout = output + index * (AVATAR_VERTEX_BYTES/sizeof(F32)); // pointer to the output vertex data, assumed to be 16 byte aligned
756
757 // MBW -- XXX -- If this isn't the case, this code gets more complicated.
758 if(0x0000000F & (U32)vin)
759 {
760 llerrs << "blend_SSE_batch: input not 16-byte aligned!" << llendl;
761 }
762 if(0x0000000F & (U32)vout)
763 {
764 llerrs << "blend_SSE_batch: output not 16-byte aligned!" << llendl;
765 }
766// if(0x0000000F & (U32)&(blend_mat.mMatrix))
767// {
768// llerrs << "blend_SSE_batch: blend_mat not 16-byte aligned!" << llendl;
769// }
770
771 if (w == last_weight)
772 {
773 // load last blended matrix
774 // Still loaded from last time through the loop.
775// matrix0_0 = vec_ld(0x00, (vector float*)&(blend_mat.mMatrix));
776// matrix0_1 = vec_ld(0x10, (vector float*)&(blend_mat.mMatrix));
777// matrix0_2 = vec_ld(0x20, (vector float*)&(blend_mat.mMatrix));
778// matrix0_3 = vec_ld(0x30, (vector float*)&(blend_mat.mMatrix));
779 }
780 else
781 {
782 last_weight = w;
783 S32 joint = llfloor(w);
784 w -= joint;
785
786 LLMatrix4 &m0 = gJointMat[joint+1];
787 LLMatrix4 &m1 = gJointMat[joint+0];
788
789 // load Matrix 0 into vector registers
790 matrix0_0 = vec_ld(0x00, (vector float*)&(m0.mMatrix));
791 matrix0_1 = vec_ld(0x10, (vector float*)&(m0.mMatrix));
792 matrix0_2 = vec_ld(0x20, (vector float*)&(m0.mMatrix));
793 matrix0_3 = vec_ld(0x30, (vector float*)&(m0.mMatrix));
794
795 // if w == 1.0f, we don't need to blend.
796 // but since we do the trick of blending the matrices, here, if w != 1.0,
797 // we load Matrix 1 into the other 4 SSE registers and blend both matrices
798 // based on the weight (which we load ingo a 16-byte aligned vector: w,w,w,w)
799
800 if (w != 1.0f)
801 {
802 vector float matrix1_0, matrix1_1, matrix1_2, matrix1_3;
803
804 // This loads the weight somewhere in the vector register
805 vector float weight = vec_lde(0, &(w));
806 // and this splats it to all elements.
807 weight = vec_splat(vec_perm(weight, weight, vec_lvsl(0, &(w))), 0);
808
809 // do blending of matrices instead of verts and normals -- faster
810 matrix1_0 = vec_ld(0x00, (vector float*)&(m1.mMatrix));
811 matrix1_1 = vec_ld(0x10, (vector float*)&(m1.mMatrix));
812 matrix1_2 = vec_ld(0x20, (vector float*)&(m1.mMatrix));
813 matrix1_3 = vec_ld(0x30, (vector float*)&(m1.mMatrix));
814
815 // m0[col] = ((m0[col] - m1[col]) * weight) + m1[col];
816 matrix0_0 = vec_madd(vec_sub(matrix0_0, matrix1_0), weight, matrix1_0);
817 matrix0_1 = vec_madd(vec_sub(matrix0_1, matrix1_1), weight, matrix1_1);
818 matrix0_2 = vec_madd(vec_sub(matrix0_2, matrix1_2), weight, matrix1_2);
819 matrix0_3 = vec_madd(vec_sub(matrix0_3, matrix1_3), weight, matrix1_3);
820 }
821
822 // save off blended matrix
823// vec_st(matrix0_0, 0x00, (vector float*)&(blend_mat.mMatrix));
824// vec_st(matrix0_1, 0x10, (vector float*)&(blend_mat.mMatrix));
825// vec_st(matrix0_2, 0x20, (vector float*)&(blend_mat.mMatrix));
826// vec_st(matrix0_3, 0x30, (vector float*)&(blend_mat.mMatrix));
827 }
828
829 // now, we have either a blended matrix in matrix0_0-3 or the original Matrix 0
830 // we then multiply each vertex and normal by this one matrix.
831
832 // For SSE2, we would try to keep the original two matrices in other registers
833 // and avoid reloading them. However, they should ramain in L1 cache in the
834 // current case.
835
836 // One possible optimization would be to sort the vertices by weight instead
837 // of just index (we still want to uniqify). If we note when two or more vertices
838 // share the same weight, we can avoid doing the middle SSE code above and just
839 // re-use the blended matrix for those vertices
840
841
842 // now, we do the actual vertex blending
843
844 vector float in0 = vec_ld(AVATAR_OFFSET_POS, (vector float*)vin);
845 vector float in1 = vec_ld(AVATAR_OFFSET_NORMAL, (vector float*)vin);
846
847 // Matrix multiply vertex
848 vector float out0 = vec_madd
849 (
850 vec_splat(in0, 0),
851 matrix0_0,
852 vec_madd
853 (
854 vec_splat(in0, 1),
855 matrix0_1,
856 vec_madd
857 (
858 vec_splat(in0, 2),
859 matrix0_2,
860 matrix0_3
861 )
862 )
863 );
864
865 // Matrix multiply normal
866 vector float out1 = vec_madd
867 (
868 vec_splat(in1, 0),
869 matrix0_0,
870 vec_madd
871 (
872 vec_splat(in1, 1),
873 matrix0_1,
874 vec_madd
875 (
876 vec_splat(in1, 2),
877 matrix0_2,
878 // no translation for normals
879 (vector float)vec_splat_u32(0)
880 )
881 )
882 );
883
884 // indexed store
885 vec_stl(vec_perm(in0, out0, out0perm), AVATAR_OFFSET_POS, (vector float*)vout); // Pos
886 vec_stl(vec_perm(in1, out1, out1perm), AVATAR_OFFSET_NORMAL, (vector float*)vout); // Norm
887 *(LLVector2*)(vout + (AVATAR_OFFSET_TEX0/sizeof(F32))) = texcoords[index]; // write texcoord into appropriate spot.
888 }
889}
890
891#endif
892
893
894void llDrawElementsBatchBlend(const U32 vert_offset, const U32 vert_count, LLFace *face, const S32 index_count, const U32 *indices)
895{
896 U8* gAGPVertices = gPipeline.bufferGetScratchMemory();
897
898 if (gAGPVertices)
899 {
900 LLStrider<LLVector3> vertices;
901 LLStrider<LLVector3> normals;
902 LLStrider<LLVector2> tcoords0;
903 LLStrider<F32> weights;
904
905 LLStrider<LLVector3> o_vertices;
906 LLStrider<LLVector3> o_normals;
907 LLStrider<LLVector2> o_texcoords0;
908
909
910 LLStrider<LLVector3> binormals;
911 LLStrider<LLVector2> o_texcoords1;
912 // get the source vertices from the draw pool. We index these ourselves, as there was
913 // no guarantee the indices for a single jointmesh were contigious
914
915 LLDrawPool *pool = face->getPool();
916 pool->getVertexStrider (vertices, 0);
917 pool->getTexCoordStrider (tcoords0, 0, 0);
918 pool->getNormalStrider (normals, 0);
919 pool->getBinormalStrider (binormals, 0);
920 pool->getVertexWeightStrider(weights, 0);
921
922 // load the addresses of the output striders
923 o_vertices = (LLVector3*)(gAGPVertices + AVATAR_OFFSET_POS); o_vertices.setStride( AVATAR_VERTEX_BYTES);
924 o_normals = (LLVector3*)(gAGPVertices + AVATAR_OFFSET_NORMAL); o_normals.setStride( AVATAR_VERTEX_BYTES);
925 o_texcoords0= (LLVector2*)(gAGPVertices + AVATAR_OFFSET_TEX0); o_texcoords0.setStride(AVATAR_VERTEX_BYTES);
926 o_texcoords1= (LLVector2*)(gAGPVertices + AVATAR_OFFSET_TEX1); o_texcoords1.setStride(AVATAR_VERTEX_BYTES);
927
928#if !LL_LINUX // !!! *TODO: do the linux implementation
929 if (gGLManager.mSoftwareBlendSSE)
930 {
931 // do SSE blend without binormals or extra texcoords
932 blend_SSE_32_32_batch(vert_offset, vert_count, (float*)gAGPVertices,
933 vertices, tcoords0, normals, weights);
934 }
935 else // fully backwards compatible software blending, no SSE
936#endif
937 {
938 LLVector4 tpos0, tnorm0, tpos1, tnorm1, tbinorm0, tbinorm1;
939 F32 last_weight = F32_MAX;
940 LLMatrix3 gBlendRotMat;
941
942 {
943 for (U32 index=vert_offset; index < vert_offset + vert_count; index++)
944 {
945 // blend by first matrix
946 F32 w = weights [index];
947
948 if (w != last_weight)
949 {
950 last_weight = w;
951
952 S32 joint = llfloor(w);
953 w -= joint;
954
955 LLMatrix4 &m0 = gJointMat[joint+1];
956 LLMatrix4 &m1 = gJointMat[joint+0];
957 LLMatrix3 &n0 = gJointRot[joint+1];
958 LLMatrix3 &n1 = gJointRot[joint+0];
959
960 if (w == 1.0f)
961 {
962 gBlendMat = m0;
963 gBlendRotMat = n0;
964 }
965 else
966 {
967 gBlendMat.mMatrix[VX][VX] = lerp(m1.mMatrix[VX][VX], m0.mMatrix[VX][VX], w);
968 gBlendMat.mMatrix[VX][VY] = lerp(m1.mMatrix[VX][VY], m0.mMatrix[VX][VY], w);
969 gBlendMat.mMatrix[VX][VZ] = lerp(m1.mMatrix[VX][VZ], m0.mMatrix[VX][VZ], w);
970
971 gBlendMat.mMatrix[VY][VX] = lerp(m1.mMatrix[VY][VX], m0.mMatrix[VY][VX], w);
972 gBlendMat.mMatrix[VY][VY] = lerp(m1.mMatrix[VY][VY], m0.mMatrix[VY][VY], w);
973 gBlendMat.mMatrix[VY][VZ] = lerp(m1.mMatrix[VY][VZ], m0.mMatrix[VY][VZ], w);
974
975 gBlendMat.mMatrix[VZ][VX] = lerp(m1.mMatrix[VZ][VX], m0.mMatrix[VZ][VX], w);
976 gBlendMat.mMatrix[VZ][VY] = lerp(m1.mMatrix[VZ][VY], m0.mMatrix[VZ][VY], w);
977 gBlendMat.mMatrix[VZ][VZ] = lerp(m1.mMatrix[VZ][VZ], m0.mMatrix[VZ][VZ], w);
978
979 gBlendMat.mMatrix[VW][VX] = lerp(m1.mMatrix[VW][VX], m0.mMatrix[VW][VX], w);
980 gBlendMat.mMatrix[VW][VY] = lerp(m1.mMatrix[VW][VY], m0.mMatrix[VW][VY], w);
981 gBlendMat.mMatrix[VW][VZ] = lerp(m1.mMatrix[VW][VZ], m0.mMatrix[VW][VZ], w);
982
983 gBlendRotMat.mMatrix[VX][VX] = lerp(n1.mMatrix[VX][VX], n0.mMatrix[VX][VX], w);
984 gBlendRotMat.mMatrix[VX][VY] = lerp(n1.mMatrix[VX][VY], n0.mMatrix[VX][VY], w);
985 gBlendRotMat.mMatrix[VX][VZ] = lerp(n1.mMatrix[VX][VZ], n0.mMatrix[VX][VZ], w);
986
987 gBlendRotMat.mMatrix[VY][VX] = lerp(n1.mMatrix[VY][VX], n0.mMatrix[VY][VX], w);
988 gBlendRotMat.mMatrix[VY][VY] = lerp(n1.mMatrix[VY][VY], n0.mMatrix[VY][VY], w);
989 gBlendRotMat.mMatrix[VY][VZ] = lerp(n1.mMatrix[VY][VZ], n0.mMatrix[VY][VZ], w);
990
991 gBlendRotMat.mMatrix[VZ][VX] = lerp(n1.mMatrix[VZ][VX], n0.mMatrix[VZ][VX], w);
992 gBlendRotMat.mMatrix[VZ][VY] = lerp(n1.mMatrix[VZ][VY], n0.mMatrix[VZ][VY], w);
993 gBlendRotMat.mMatrix[VZ][VZ] = lerp(n1.mMatrix[VZ][VZ], n0.mMatrix[VZ][VZ], w);
994 }
995 }
996
997 // write result
998 o_vertices [index] = vertices[index] * gBlendMat;
999 o_normals [index] = normals [index] * gBlendRotMat;
1000 o_texcoords0[index] = tcoords0[index];
1001
1002 /*
1003 // Verification code. Leave this here. It's useful for keeping the SSE and non-SSE versions in sync.
1004 LLVector3 temp;
1005 temp = tpos0;
1006 if( (o_vertices[index] - temp).magVecSquared() > 0.001f )
1007 {
1008 llerrs << "V SSE: " << o_vertices[index] << " v. " << temp << llendl;
1009 }
1010
1011 temp = tnorm0;
1012 if( (o_normals[index] - temp).magVecSquared() > 0.001f )
1013 {
1014 llerrs << "N SSE: " << o_normals[index] << " v. " << temp << llendl;
1015 }
1016
1017 if( (o_texcoords0[index] - tcoords0[index]).magVecSquared() > 0.001f )
1018 {
1019 llerrs << "T0 SSE: " << o_texcoords0[index] << " v. " << tcoords0[index] << llendl;
1020 }
1021 */
1022 }
1023 }
1024 }
1025
1026#if LL_DARWIN
1027 // *HACK* *CHOKE* *PUKE*
1028 // No way does this belong here.
1029 glFlushVertexArrayRangeAPPLE(AVATAR_VERTEX_BYTES * vert_count, gAGPVertices + (AVATAR_VERTEX_BYTES * vert_offset));
1030#endif
1031 glDrawElements(GL_TRIANGLES, index_count, GL_UNSIGNED_INT, indices); // draw it!
1032 }
1033 else
1034 {
1035 glDrawElements(GL_TRIANGLES, index_count, GL_UNSIGNED_INT, indices);
1036 }
1037}
1038
1039
1040
1041//--------------------------------------------------------------------
1042// DrawElements
1043
1044// works just like glDrawElements, except it assumes GL_TRIANGLES and GL_UNSIGNED_INT indices
1045
1046// why? because the destination buffer may not be the AGP buffer and the eyes do not use blending
1047// separate the eyes into their own drawpools and this code goes away.
1048
1049//--------------------------------------------------------------------
1050
1051void llDrawElements(const S32 count, const U32 *indices, LLFace *face)
1052{
1053 U8* gAGPVertices = gPipeline.bufferGetScratchMemory();
1054
1055 if (gAGPVertices)
1056 {
1057#if LL_DARWIN
1058 U32 minIndex = indices[0];
1059 U32 maxIndex = indices[0];
1060#endif
1061 {
1062 LLStrider<LLVector3> vertices;
1063 LLStrider<LLVector3> normals;
1064 LLStrider<LLVector2> tcoords;
1065 LLStrider<F32> weights;
1066
1067 LLStrider<LLVector3> o_vertices;
1068 LLStrider<LLVector3> o_normals;
1069 LLStrider<LLVector2> o_texcoords0;
1070
1071 LLDrawPool *pool = face->getPool();
1072 pool->getVertexStrider (vertices,0);
1073 pool->getNormalStrider (normals, 0);
1074 pool->getTexCoordStrider (tcoords, 0);
1075
1076 o_vertices = (LLVector3*)(gAGPVertices + AVATAR_OFFSET_POS); o_vertices.setStride( AVATAR_VERTEX_BYTES);
1077 o_normals = (LLVector3*)(gAGPVertices + AVATAR_OFFSET_NORMAL); o_normals.setStride( AVATAR_VERTEX_BYTES);
1078 o_texcoords0= (LLVector2*)(gAGPVertices + AVATAR_OFFSET_TEX0); o_texcoords0.setStride(AVATAR_VERTEX_BYTES);
1079
1080 for (S32 i=0; i < count; i++)
1081 {
1082 U32 index = indices[i];
1083
1084 o_vertices [index] = vertices[index];
1085 o_normals [index] = normals [index];
1086 o_texcoords0[index] = tcoords [index];
1087
1088#if LL_DARWIN
1089 maxIndex = llmax(index, maxIndex);
1090 minIndex = llmin(index, minIndex);
1091#endif
1092 }
1093 }
1094
1095#if LL_DARWIN
1096 // *HACK* *CHOKE* *PUKE*
1097 // No way does this belong here.
1098 glFlushVertexArrayRangeAPPLE(AVATAR_VERTEX_BYTES * (maxIndex + 1 - minIndex), gAGPVertices + (AVATAR_VERTEX_BYTES * minIndex));
1099#endif
1100
1101 glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, indices);
1102 }
1103 else
1104 {
1105 glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, indices);
1106 }
1107}
1108
1109
1110//--------------------------------------------------------------------
1111// LLViewerJointMesh::drawShape()
1112//--------------------------------------------------------------------
1113U32 LLViewerJointMesh::drawShape( F32 pixelArea )
1114{
1115 if (!mValid || !mVisible) return 0;
1116
1117 U32 triangle_count = 0;
1118
1119 //----------------------------------------------------------------
1120 // if no mesh bail out now
1121 //----------------------------------------------------------------
1122 if ( !mMesh || !mFace)
1123 {
1124 return 0;
1125 }
1126
1127 //----------------------------------------------------------------
1128 // if we have no faces, bail out now
1129 //----------------------------------------------------------------
1130 if ( mMesh->getNumFaces() == 0 )
1131 {
1132 return 0;
1133 }
1134
1135 stop_glerror();
1136
1137 //----------------------------------------------------------------
1138 // setup current color
1139 //----------------------------------------------------------------
1140 if (gRenderForSelect)
1141 {
1142 S32 name = mFace->getDrawable() ? mFace->getDrawable()->getVObj()->mGLName : 0;
1143 LLColor4U color((U8)(name >> 16), (U8)(name >> 8), (U8)name, 0xff);
1144 LLColor4 color_float(color);
1145
1146 glColor4f(color_float.mV[0], color_float.mV[1], color_float.mV[2], 1.f);
1147 }
1148 else
1149 {
1150 if ((mFace->getPool()->getVertexShaderLevel() > 0))
1151 {
1152 glColor4f(0,0,0,1);
1153
1154 if (gPipeline.mMaterialIndex > 0)
1155 {
1156 glVertexAttrib4fvARB(gPipeline.mMaterialIndex, mColor.mV);
1157 }
1158
1159 if (mShiny && gPipeline.mSpecularIndex > 0)
1160 {
1161 glVertexAttrib4fARB(gPipeline.mSpecularIndex, 1,1,1,1);
1162 }
1163 }
1164 else
1165 {
1166 glColor4fv(mColor.mV);
1167 }
1168 }
1169
1170 stop_glerror();
1171
1172// LLGLSSpecular specular(mSpecular, gRenderForSelect ? 0.0f : mShiny);
1173 LLGLSSpecular specular(LLColor4(1.f,1.f,1.f,1.f), gRenderForSelect ? 0.0f : mShiny && !(mFace->getPool()->getVertexShaderLevel() > 0));
1174
1175 LLGLEnable texture_2d((gRenderForSelect && isTransparent()) ? GL_TEXTURE_2D : 0);
1176
1177 //----------------------------------------------------------------
1178 // setup current texture
1179 //----------------------------------------------------------------
1180 llassert( !(mTexture.notNull() && mLayerSet) ); // mutually exclusive
1181
1182 //GLuint test_image_name = 0;
1183
1184 //
1185 LLGLState force_alpha_test(GL_ALPHA_TEST, isTransparent());
1186
1187 if (mTestImageName)
1188 {
1189 LLImageGL::bindExternalTexture( mTestImageName, 0, GL_TEXTURE_2D );
1190
1191 if (mIsTransparent)
1192 {
1193 glColor4f(1.f, 1.f, 1.f, 1.f);
1194 }
1195 else
1196 {
1197 glColor4f(0.7f, 0.6f, 0.3f, 1.f);
1198 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
1199 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB);
1200
1201 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
1202 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
1203
1204 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
1205 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
1206
1207 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
1208 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_ONE_MINUS_SRC_ALPHA);
1209 }
1210 }
1211 else if( mLayerSet )
1212 {
1213 if( mLayerSet->hasComposite() )
1214 {
1215 mLayerSet->getComposite()->bindTexture();
1216 }
1217 else
1218 {
1219 llwarns << "Layerset without composite" << llendl;
1220 gImageList.getImage(IMG_DEFAULT)->bind();
1221 }
1222 }
1223 else
1224 if ( mTexture.notNull() )
1225 {
1226 mTexture->bind();
1227 if (!mTexture->getClampS()) {
1228 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1229 }
1230 if (!mTexture->getClampT()) {
1231 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1232 }
1233 }
1234 else
1235 {
1236 gImageList.getImage(IMG_DEFAULT_AVATAR)->bind();
1237 }
1238
1239 if (gRenderForSelect)
1240 {
1241 if (isTransparent())
1242 {
1243 //gGLSObjectSelectDepthAlpha.set();
1244 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
1245 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
1246 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
1247
1248 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
1249 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
1250
1251 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); // GL_TEXTURE_ENV_COLOR is set in renderPass1
1252 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
1253 }
1254 else
1255 {
1256 //gGLSObjectSelectDepth.set();
1257 }
1258 }
1259 else
1260 {
1261 //----------------------------------------------------------------
1262 // by default, backface culling is enabled
1263 //----------------------------------------------------------------
1264 if (sRenderPass == AVATAR_RENDER_PASS_CLOTHING_INNER)
1265 {
1266 //LLGLSPipelineAvatar gls_pipeline_avatar;
1267 LLImageGL::bindExternalTexture( sClothingMaskImageName, 1, GL_TEXTURE_2D );
1268
1269 glClientActiveTextureARB(GL_TEXTURE0_ARB);
1270 glActiveTextureARB(GL_TEXTURE0_ARB);
1271 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
1272 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
1273 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
1274
1275 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
1276 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
1277
1278 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
1279 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
1280
1281 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);
1282 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
1283
1284 glClientActiveTextureARB(GL_TEXTURE1_ARB);
1285 glEnable(GL_TEXTURE_2D); // Texture unit 1
1286 glActiveTextureARB(GL_TEXTURE1_ARB);
1287 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
1288 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, sClothingInnerColor.mV);
1289 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB);
1290 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
1291
1292 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB);
1293 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
1294
1295 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_CONSTANT_ARB);
1296 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
1297
1298 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
1299 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
1300
1301 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
1302 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);
1303 }
1304 else if (sRenderPass == AVATAR_RENDER_PASS_CLOTHING_OUTER)
1305 {
1306 //gGLSPipelineAvatarAlphaPass1.set();
1307 glAlphaFunc(GL_GREATER, 0.1f);
1308 LLImageGL::bindExternalTexture( sClothingMaskImageName, 1, GL_TEXTURE_2D );
1309
1310 glClientActiveTextureARB(GL_TEXTURE0_ARB);
1311 glActiveTextureARB(GL_TEXTURE0_ARB);
1312 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
1313 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
1314 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
1315
1316 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
1317 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
1318
1319 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
1320 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
1321
1322 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);
1323 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
1324
1325 glClientActiveTextureARB(GL_TEXTURE1_ARB);
1326 glEnable(GL_TEXTURE_2D); // Texture unit 1
1327 glActiveTextureARB(GL_TEXTURE1_ARB);
1328 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
1329 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
1330 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
1331
1332 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
1333 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
1334
1335 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
1336 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
1337 }
1338 else if ( isTransparent())
1339 {
1340 //gGLSNoCullFaces.set();
1341 }
1342 else
1343 {
1344 //gGLSCullFaces.set();
1345 }
1346 }
1347
1348 if (mMesh->hasWeights())
1349 {
1350 uploadJointMatrices();
1351
1352
1353 if ((mFace->getPool()->getVertexShaderLevel() > 0))
1354 {
1355 glMatrixMode(GL_MODELVIEW);
1356 glPushMatrix();
1357 glLoadIdentity();
1358
1359 glDrawElements(GL_TRIANGLES, mMesh->mFaceIndexCount, GL_UNSIGNED_INT, mMesh->getIndices());
1360
1361 glPopMatrix();
1362 }
1363 else
1364 {
1365 if (mFace->getGeomIndex() < 0)
1366 {
1367 llerrs << "Invalid geometry index in LLViewerJointMesh::drawShape() " << mFace->getGeomIndex() << llendl;
1368 }
1369
1370 if ((S32)(mMesh->mFaceVertexOffset + mMesh->mFaceVertexCount) > mFace->getGeomCount())
1371 {
1372 ((LLVOAvatar*)mFace->getDrawable()->getVObj())->mRoot.dump();
1373 llerrs << "Rendering outside of vertex bounds with mesh " << mName << " at pixel area " << pixelArea << llendl;
1374 }
1375 llDrawElementsBatchBlend(mMesh->mFaceVertexOffset, mMesh->mFaceVertexCount,
1376 mFace, mMesh->mFaceIndexCount, mMesh->getIndices());
1377 }
1378
1379 }
1380 else
1381 {
1382 glPushMatrix();
1383 LLMatrix4 jointToWorld = getWorldMatrix();
1384 jointToWorld *= gCamera->getModelview();
1385 glLoadMatrixf((GLfloat*)jointToWorld.mMatrix);
1386
1387 if ((mFace->getPool()->getVertexShaderLevel() > 0))
1388 {
1389 glDrawElements(GL_TRIANGLES, mMesh->mFaceIndexCount, GL_UNSIGNED_INT, mMesh->getIndices());
1390 }
1391 else // this else clause handles non-weighted vertices. llDrawElements just copies and draws
1392 {
1393 llDrawElements(mMesh->mFaceIndexCount, mMesh->getIndices(), mFace);
1394 }
1395
1396 glPopMatrix();
1397 }
1398
1399 triangle_count += mMesh->mFaceIndexCount;
1400
1401 if (gRenderForSelect)
1402 {
1403 glColor4fv(mColor.mV);
1404 }
1405
1406 if (mTestImageName)
1407 {
1408 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1409 }
1410
1411 if (sRenderPass != AVATAR_RENDER_PASS_SINGLE)
1412 {
1413 LLImageGL::unbindTexture(1, GL_TEXTURE_2D);
1414 glActiveTextureARB(GL_TEXTURE1_ARB);
1415 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
1416
1417 // Return to the default texture.
1418 LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
1419 glClientActiveTextureARB(GL_TEXTURE0_ARB);
1420 glActiveTextureARB(GL_TEXTURE0_ARB);
1421
1422 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
1423 glAlphaFunc(GL_GREATER, 0.01f);
1424 }
1425
1426 if (mTexture.notNull()) {
1427 if (!mTexture->getClampS()) {
1428 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1429 }
1430 if (!mTexture->getClampT()) {
1431 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1432 }
1433 }
1434
1435 return triangle_count;
1436}
1437
1438//-----------------------------------------------------------------------------
1439// updateFaceSizes()
1440//-----------------------------------------------------------------------------
1441void LLViewerJointMesh::updateFaceSizes(U32 &num_vertices, F32 pixel_area)
1442{
1443 // Do a pre-alloc pass to determine sizes of data.
1444 if (mMesh && mValid)
1445 {
1446 mMesh->mFaceVertexOffset = num_vertices;
1447 mMesh->mFaceVertexCount = mMesh->getNumVertices();
1448 mMesh->getReferenceMesh()->mCurVertexCount = mMesh->mFaceVertexCount;
1449 num_vertices += mMesh->getNumVertices();
1450
1451 mMesh->mFaceIndexCount = mMesh->getSharedData()->mNumTriangleIndices;
1452
1453 mMesh->getSharedData()->genIndices(mMesh->mFaceVertexOffset);
1454 }
1455}
1456
1457//-----------------------------------------------------------------------------
1458// updateFaceData()
1459//-----------------------------------------------------------------------------
1460void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind)
1461{
1462 U32 i;
1463
1464 if (!mValid) return;
1465
1466 mFace = face;
1467
1468 LLStrider<LLVector3> verticesp;
1469 LLStrider<LLVector3> normalsp;
1470 LLStrider<LLVector3> binormalsp;
1471 LLStrider<LLVector2> tex_coordsp;
1472 LLStrider<F32> vertex_weightsp;
1473 LLStrider<LLVector4> clothing_weightsp;
1474
1475 // Copy data into the faces from the polymesh data.
1476 if (mMesh)
1477 {
1478 if (mMesh->getNumVertices())
1479 {
1480 S32 index = face->getGeometryAvatar(verticesp, normalsp, binormalsp, tex_coordsp, vertex_weightsp, clothing_weightsp);
1481
1482 if (-1 == index)
1483 {
1484 return;
1485 }
1486
1487 for (i = 0; i < mMesh->getNumVertices(); i++)
1488 {
1489 verticesp[mMesh->mFaceVertexOffset + i] = *(mMesh->getCoords() + i);
1490 tex_coordsp[mMesh->mFaceVertexOffset + i] = *(mMesh->getTexCoords() + i);
1491 normalsp[mMesh->mFaceVertexOffset + i] = *(mMesh->getNormals() + i);
1492 binormalsp[mMesh->mFaceVertexOffset + i] = *(mMesh->getBinormals() + i);
1493 vertex_weightsp[mMesh->mFaceVertexOffset + i] = *(mMesh->getWeights() + i);
1494 if (damp_wind)
1495 {
1496 clothing_weightsp[mMesh->mFaceVertexOffset + i].setVec(0,0,0,0);
1497 }
1498 else
1499 {
1500 clothing_weightsp[mMesh->mFaceVertexOffset + i].setVec(*(mMesh->getClothingWeights() + i));
1501 }
1502 }
1503 }
1504 }
1505}
1506
1507//-----------------------------------------------------------------------------
1508// updateLOD()
1509//-----------------------------------------------------------------------------
1510BOOL LLViewerJointMesh::updateLOD(F32 pixel_area, BOOL activate)
1511{
1512 BOOL valid = mValid;
1513 setValid(activate, TRUE);
1514 return (valid != activate);
1515}
1516
1517void LLViewerJointMesh::dump()
1518{
1519 if (mValid)
1520 {
1521 llinfos << "Usable LOD " << mName << llendl;
1522 }
1523}
1524
1525void LLViewerJointMesh::writeCAL3D(apr_file_t* fp, S32 material_num, LLCharacter* characterp)
1526{
1527 apr_file_printf(fp, "\t<SUBMESH NUMVERTICES=\"%d\" NUMFACES=\"%d\" MATERIAL=\"%d\" NUMLODSTEPS=\"0\" NUMSPRINGS=\"0\" NUMTEXCOORDS=\"1\">\n", mMesh->getNumVertices(), mMesh->getNumFaces(), material_num);
1528
1529 const LLVector3* mesh_coords = mMesh->getCoords();
1530 const LLVector3* mesh_normals = mMesh->getNormals();
1531 const LLVector2* mesh_uvs = mMesh->getTexCoords();
1532 const F32* mesh_weights = mMesh->getWeights();
1533 LLVector3 mesh_offset;
1534 LLVector3 scale(1.f, 1.f, 1.f);
1535 S32 joint_a = -1;
1536 S32 joint_b = -1;
1537 S32 num_bound_joints = 0;
1538
1539 if(!mMesh->hasWeights())
1540 {
1541 num_bound_joints = 1;
1542 LLJoint* cur_joint = this;
1543 while(cur_joint)
1544 {
1545 if (cur_joint->mJointNum != -1 && joint_a == -1)
1546 {
1547 joint_a = cur_joint->mJointNum;
1548 }
1549 mesh_offset += cur_joint->getSkinOffset();
1550 cur_joint = cur_joint->getParent();
1551 }
1552 }
1553
1554 for (S32 i = 0; i < (S32)mMesh->getNumVertices(); i++)
1555 {
1556 LLVector3 coord = mesh_coords[i];
1557
1558 if (mMesh->hasWeights())
1559 {
1560 // calculate joint to which this skinned vertex is bound
1561 num_bound_joints = getBoundJointsByIndex(llfloor(mesh_weights[i]), joint_a, joint_b);
1562 LLJoint* first_joint = characterp->getCharacterJoint(joint_a);
1563 LLJoint* second_joint = characterp->getCharacterJoint(joint_b);
1564
1565 LLVector3 first_joint_offset;
1566 LLJoint* cur_joint = first_joint;
1567 while(cur_joint)
1568 {
1569 first_joint_offset += cur_joint->getSkinOffset();
1570 cur_joint = cur_joint->getParent();
1571 }
1572
1573 LLVector3 second_joint_offset;
1574 cur_joint = second_joint;
1575 while(cur_joint)
1576 {
1577 second_joint_offset += cur_joint->getSkinOffset();
1578 cur_joint = cur_joint->getParent();
1579 }
1580
1581 LLVector3 first_coord = coord - first_joint_offset;
1582 first_coord.scaleVec(first_joint->getScale());
1583 LLVector3 second_coord = coord - second_joint_offset;
1584 if (second_joint)
1585 {
1586 second_coord.scaleVec(second_joint->getScale());
1587 }
1588
1589 coord = lerp(first_joint_offset + first_coord, second_joint_offset + second_coord, fmodf(mesh_weights[i], 1.f));
1590 }
1591
1592 // add offset to move rigid mesh to target location
1593 coord += mesh_offset;
1594 coord *= 100.f;
1595
1596 apr_file_printf(fp, " <VERTEX ID=\"%d\" NUMINFLUENCES=\"%d\">\n", i, num_bound_joints);
1597 apr_file_printf(fp, " <POS>%.4f %.4f %.4f</POS>\n", coord.mV[VX], coord.mV[VY], coord.mV[VZ]);
1598 apr_file_printf(fp, " <NORM>%.6f %.6f %.6f</NORM>\n", mesh_normals[i].mV[VX], mesh_normals[i].mV[VY], mesh_normals[i].mV[VZ]);
1599 apr_file_printf(fp, " <TEXCOORD>%.6f %.6f</TEXCOORD>\n", mesh_uvs[i].mV[VX], 1.f - mesh_uvs[i].mV[VY]);
1600 if (num_bound_joints >= 1)
1601 {
1602 apr_file_printf(fp, " <INFLUENCE ID=\"%d\">%.2f</INFLUENCE>\n", joint_a + 1, 1.f - fmod(mesh_weights[i], 1.f));
1603 }
1604 if (num_bound_joints == 2)
1605 {
1606 apr_file_printf(fp, " <INFLUENCE ID=\"%d\">%.2f</INFLUENCE>\n", joint_b + 1, fmod(mesh_weights[i], 1.f));
1607 }
1608 apr_file_printf(fp, " </VERTEX>\n");
1609 }
1610
1611 LLPolyFace* mesh_faces = mMesh->getFaces();
1612 for (S32 i = 0; i < mMesh->getNumFaces(); i++)
1613 {
1614 apr_file_printf(fp, " <FACE VERTEXID=\"%d %d %d\" />\n", mesh_faces[i][0], mesh_faces[i][1], mesh_faces[i][2]);
1615 }
1616
1617 apr_file_printf(fp, " </SUBMESH>\n");
1618}
1619
1620// End