diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llviewerjointmesh.cpp | |
parent | README.txt (diff) | |
download | meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2 meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz |
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/newview/llviewerjointmesh.cpp')
-rw-r--r-- | linden/indra/newview/llviewerjointmesh.cpp | 1620 |
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 | ||
59 | extern PFNGLWEIGHTPOINTERARBPROC glWeightPointerARB; | ||
60 | extern PFNGLWEIGHTFVARBPROC glWeightfvARB; | ||
61 | extern PFNGLVERTEXBLENDARBPROC glVertexBlendARB; | ||
62 | #endif | ||
63 | extern BOOL gRenderForSelect; | ||
64 | |||
65 | LLMatrix4 gBlendMat; | ||
66 | |||
67 | //----------------------------------------------------------------------------- | ||
68 | //----------------------------------------------------------------------------- | ||
69 | // LLViewerJointMesh::LLSkinJoint | ||
70 | //----------------------------------------------------------------------------- | ||
71 | //----------------------------------------------------------------------------- | ||
72 | |||
73 | //----------------------------------------------------------------------------- | ||
74 | // LLSkinJoint | ||
75 | //----------------------------------------------------------------------------- | ||
76 | LLSkinJoint::LLSkinJoint() | ||
77 | { | ||
78 | mJoint = NULL; | ||
79 | } | ||
80 | |||
81 | //----------------------------------------------------------------------------- | ||
82 | // ~LLSkinJoint | ||
83 | //----------------------------------------------------------------------------- | ||
84 | LLSkinJoint::~LLSkinJoint() | ||
85 | { | ||
86 | mJoint = NULL; | ||
87 | } | ||
88 | |||
89 | |||
90 | //----------------------------------------------------------------------------- | ||
91 | // LLSkinJoint::setupSkinJoint() | ||
92 | //----------------------------------------------------------------------------- | ||
93 | BOOL 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 | |||
125 | BOOL LLViewerJointMesh::sPipelineRender = FALSE; | ||
126 | EAvatarRenderPass LLViewerJointMesh::sRenderPass = AVATAR_RENDER_PASS_SINGLE; | ||
127 | U32 LLViewerJointMesh::sClothingMaskImageName = 0; | ||
128 | LLColor4 LLViewerJointMesh::sClothingInnerColor; | ||
129 | |||
130 | //----------------------------------------------------------------------------- | ||
131 | // LLViewerJointMesh() | ||
132 | //----------------------------------------------------------------------------- | ||
133 | LLViewerJointMesh::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 | //----------------------------------------------------------------------------- | ||
166 | LLViewerJointMesh::~LLViewerJointMesh() | ||
167 | { | ||
168 | mMesh = NULL; | ||
169 | mTexture = NULL; | ||
170 | freeSkinData(); | ||
171 | } | ||
172 | |||
173 | |||
174 | //----------------------------------------------------------------------------- | ||
175 | // LLViewerJointMesh::allocateSkinData() | ||
176 | //----------------------------------------------------------------------------- | ||
177 | BOOL LLViewerJointMesh::allocateSkinData( U32 numSkinJoints ) | ||
178 | { | ||
179 | mSkinJoints = new LLSkinJoint[ numSkinJoints ]; | ||
180 | mNumSkinJoints = numSkinJoints; | ||
181 | return TRUE; | ||
182 | } | ||
183 | |||
184 | //----------------------------------------------------------------------------- | ||
185 | // getSkinJointByIndex() | ||
186 | //----------------------------------------------------------------------------- | ||
187 | S32 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 | //----------------------------------------------------------------------------- | ||
229 | void LLViewerJointMesh::freeSkinData() | ||
230 | { | ||
231 | mNumSkinJoints = 0; | ||
232 | delete [] mSkinJoints; | ||
233 | mSkinJoints = NULL; | ||
234 | } | ||
235 | |||
236 | //-------------------------------------------------------------------- | ||
237 | // LLViewerJointMesh::getColor() | ||
238 | //-------------------------------------------------------------------- | ||
239 | void 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 | //-------------------------------------------------------------------- | ||
250 | void 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 | //-------------------------------------------------------------------- | ||
270 | void 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 | //-------------------------------------------------------------------- | ||
287 | void 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 | //-------------------------------------------------------------------- | ||
303 | LLPolyMesh *LLViewerJointMesh::getMesh() | ||
304 | { | ||
305 | return mMesh; | ||
306 | } | ||
307 | |||
308 | //----------------------------------------------------------------------------- | ||
309 | // LLViewerJointMesh::setMesh() | ||
310 | //----------------------------------------------------------------------------- | ||
311 | void 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 | //----------------------------------------------------------------------------- | ||
358 | void 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 == ¤t_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(¤t_joint->getParent()->getWorldMatrix(), NULL)); | ||
388 | // llinfos << "joint " << joint_count << current_joint->getParent()->getName() << llendl; | ||
389 | // joint_count++; | ||
390 | mMesh->mJointRenderData.put(new LLJointRenderData(¤t_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 | |||
405 | const 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 | |||
413 | static LLMatrix4 gJointMat[32]; | ||
414 | static LLMatrix3 gJointRot[32]; | ||
415 | static LLVector4 gJointPivot[32]; | ||
416 | |||
417 | //----------------------------------------------------------------------------- | ||
418 | // uploadJointMatrices() | ||
419 | //----------------------------------------------------------------------------- | ||
420 | void 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 | //-------------------------------------------------------------------- | ||
505 | void LLViewerJointMesh::drawBone() | ||
506 | { | ||
507 | } | ||
508 | |||
509 | //-------------------------------------------------------------------- | ||
510 | // LLViewerJointMesh::isTransparent() | ||
511 | //-------------------------------------------------------------------- | ||
512 | BOOL 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 | ||
522 | int 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 | |||
562 | void 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 | |||
705 | void 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 | |||
714 | static 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 | |||
723 | static 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 | |||
738 | void 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 | |||
894 | void 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 | |||
1051 | void 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 | //-------------------------------------------------------------------- | ||
1113 | U32 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 | //----------------------------------------------------------------------------- | ||
1441 | void 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 | //----------------------------------------------------------------------------- | ||
1460 | void 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 | //----------------------------------------------------------------------------- | ||
1510 | BOOL LLViewerJointMesh::updateLOD(F32 pixel_area, BOOL activate) | ||
1511 | { | ||
1512 | BOOL valid = mValid; | ||
1513 | setValid(activate, TRUE); | ||
1514 | return (valid != activate); | ||
1515 | } | ||
1516 | |||
1517 | void LLViewerJointMesh::dump() | ||
1518 | { | ||
1519 | if (mValid) | ||
1520 | { | ||
1521 | llinfos << "Usable LOD " << mName << llendl; | ||
1522 | } | ||
1523 | } | ||
1524 | |||
1525 | void 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 | ||