00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "llcape.h"
00035
00036 #include "llglheaders.h"
00037 #include "llsphere.h"
00038 #include "llrand.h"
00039 #include "llvoavatar.h"
00040 #include "llagent.h"
00041 #include "llviewerobject.h"
00042 #include "llimagegl.h"
00043 #include "llviewerimagelist.h"
00044 #include "llviewercontrol.h"
00045 #include "llflexibleobject.h"
00046
00047 const int _X_ = 0;
00048 const int _Y_ = 1;
00049 const int _Z_ = 2;
00050 const F32 ONE_HALF = 0.5f;
00051 const F32 STRAND_VISUALIZATION_ANCHOR_BALL_RADIUS = 0.01f;
00052
00053
00054
00055
00056 LLVOCloth::LLVOCloth(const LLUUID &id, const LLPCode type, LLViewerRegion *regionp)
00057 : LLViewerObject(id, type, regionp)
00058 {
00059 mAttributes.mTextureFileName = CLOTH_DEFAULT_TEXTURE_FILENAME;
00060 mAttributes.mTextureIndex = CLOTH_DEFAULT_TEXTURE_INDEX;
00061 mAttributes.mNumStrands = CLOTH_DEFAULT_NUM_STRANDS;
00062 mAttributes.mNumSegments = CLOTH_DEFAULT_NUM_SEGMENTS;
00063 mAttributes.mVisualizeStrands = CLOTH_DEFAULT_VISUALIZE_STRANDS;
00064 mAttributes.mVisualizeAvCollisionSphere = CLOTH_DEFAULT_VISUALIZE_COLLISION_SPHERE;
00065 mAttributes.mWidth = CLOTH_DEFAULT_WIDTH;
00066 mAttributes.mLength = CLOTH_DEFAULT_LENGTH;
00067 mAttributes.mPitch = CLOTH_DEFAULT_PITCH;
00068 mAttributes.mGravity = CLOTH_DEFAULT_GRAVITY;
00069 mAttributes.mTension = CLOTH_DEFAULT_TENSION;
00070 mAttributes.mAirFriction = CLOTH_DEFAULT_AIR_FRICTION;
00071 mAttributes.mWindSensitivity = CLOTH_DEFAULT_WIND_SENSITIVITY;
00072 mAttributes.mCircleWrapAmount = CLOTH_DEFAULT_CIRCLE_WRAP_AMOUNT;
00073 mAttributes.mUsingAvatarCollisionSphere = CLOTH_DEFAULT_USING_AVATAR_COLLISION_SPHERE;
00074
00075 mAttributes.mAvatarCollisionSphereRadius = CLOTH_DEFAULT_AVATAR_COLLISION_SPHERE_RADIUS;
00076 mAttributes.mAvatarCollisionSphereRightOffset = CLOTH_DEFAULT_AVATAR_COLLISION_SPHERE_RIGHT_OFFSET;
00077 mAttributes.mAvatarCollisionSphereUpOffset = CLOTH_DEFAULT_AVATAR_COLLISION_SPHERE_UP_OFFSET;
00078 mAttributes.mAvatarCollisionSphereForwardOffset = CLOTH_DEFAULT_AVATAR_COLLISION_SPHERE_FORWARD_OFFSET;
00079
00080 generateStrands();
00081
00082 }
00083
00084
00085
00086
00087
00088
00089 void LLVOCloth::generateStrands()
00090 {
00091 LLFlexibleObjectData strandAttributes;
00092
00093 bool oddNumStrands = (bool)( mAttributes.mNumStrands % 2 );
00094 F32 piOver180 = F_PI / 180.0f;
00095 F32 x = 0.0f;
00096 F32 y = 0.0f;
00097 F32 startAngle = -mAttributes.mCircleWrapAmount * 180.0f;
00098 F32 angleDelta = ( mAttributes.mCircleWrapAmount * 360.0f ) / (F32)( mAttributes.mNumStrands - 1 );
00099 F32 subWidth = mAttributes.mWidth / (F32)( mAttributes.mNumStrands - 1 );
00100
00101 F32 angle = 0.0f;
00102
00103 if ( mAttributes.mNumStrands > 2 )
00104 {
00105 angle = startAngle;
00106 }
00107
00108
00109
00110
00111
00112 if ( ! oddNumStrands )
00113 {
00114 y += subWidth * ONE_HALF;
00115 }
00116
00117 int half = mAttributes.mNumStrands / 2;
00118 for ( int s=0; s<half; s ++)
00119 {
00120 if ( mAttributes.mNumStrands > 2 )
00121 {
00122 angle += angleDelta;
00123 }
00124
00125 F32 r = angle * piOver180;
00126 x -= subWidth * sin(r);
00127 y -= subWidth * cos(r);
00128 }
00129
00130
00131 if ( mAttributes.mNumStrands > 2 )
00132 {
00133 angle = startAngle;
00134 }
00135 else
00136 {
00137 angle = 0.0f;
00138 }
00139
00140
00141 for ( int s=0; s<mAttributes.mNumStrands; s ++)
00142 {
00143
00144
00145 if ( mAttributes.mNumStrands > 2 )
00146 {
00147 angle += angleDelta;
00148 }
00149
00150 F32 r = angle * piOver180;
00151 F32 dX = subWidth * sin(r);
00152 F32 dY = subWidth * cos(r);
00153 x += dX;
00154 y += dY;
00155
00156
00157
00158
00159 LLVector3 perpendicular;
00160 perpendicular.setVec( -dY, dX, 0.0f );
00161 perpendicular.normVec();
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180 }
00181
00182 }
00183
00184
00185
00186
00187
00188
00189
00190 void LLVOCloth::update()
00191 {
00192 if ( mAttributes.mUsingAvatarCollisionSphere )
00193 {
00194 LLVector3 offset;
00195 offset.setVec
00196 (
00197 mAttributes.mAvatarCollisionSphereForwardOffset,
00198 mAttributes.mAvatarCollisionSphereRightOffset,
00199 mAttributes.mAvatarCollisionSphereUpOffset
00200 );
00201
00202
00203
00204
00205 offset *= gAgent.getAvatarObject()->getRenderRotation();
00206
00207 mAvatarCollisionSpherePosition = gAgent.getAvatarObject()->getRenderPosition() + offset;
00208 }
00209
00210 if ( mParent )
00211 {
00212
00213 for ( int s=0; s<mAttributes.mNumStrands; s++)
00214 {
00215 mStrand[s]->setParentPositionAndRotationDirectly( getRenderPosition(), getRenderRotation() );
00216
00217
00218 if ( mAttributes.mUsingAvatarCollisionSphere )
00219 {
00220
00221
00222 mStrand[s]->setCollisionSphere( mAvatarCollisionSpherePosition, mAttributes.mAvatarCollisionSphereRadius );
00223 }
00224 }
00225 }
00226
00227 }
00228
00229
00230
00231
00232
00233 void LLVOCloth::render()
00234 {
00235 if ( mAttributes.mTextureFileName != "not_specified" )
00236 {
00237 LLViewerImage* theTexture = gImageList.getImage( LLUUID( gViewerArt.getString( mAttributes.mTextureFileName ) ), MIPMAP_FALSE, TRUE);
00238 if ( theTexture )
00239 {
00240
00241
00242
00243
00244
00245
00246
00247
00248 if ( mAttributes.mVisualizeStrands )
00249 {
00250 for ( int s=0; s<mAttributes.mNumStrands; s++)
00251 {
00252
00253
00254
00255 glPushMatrix();
00256
00257 glTranslatef
00258 (
00259 mStrand[s]->getAnchorPosition().mV[_X_],
00260 mStrand[s]->getAnchorPosition().mV[_Y_],
00261 mStrand[s]->getAnchorPosition().mV[_Z_]
00262 );
00263
00264 glScalef
00265 (
00266 STRAND_VISUALIZATION_ANCHOR_BALL_RADIUS,
00267 STRAND_VISUALIZATION_ANCHOR_BALL_RADIUS,
00268 STRAND_VISUALIZATION_ANCHOR_BALL_RADIUS
00269 );
00270
00271 gSphere.render();
00272 glPopMatrix();
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288 if ( s > 0 )
00289 {
00290
00291
00292
00293 glBegin( GL_LINES );
00294 glVertex3fv( mStrand[s-1]->getAnchorPosition().mV );
00295 glVertex3fv( mStrand[s ]->getAnchorPosition().mV );
00296 glEnd();
00297
00298
00299
00300
00301 for ( int i=0; i<mAttributes.mNumSegments; i++)
00302 {
00303 glBegin( GL_LINES );
00304 glVertex3fv( mStrand[s-1]->getNodePosition(i).mV );
00305 glVertex3fv( mStrand[s ]->getNodePosition(i).mV );
00306 glEnd();
00307 }
00308 }
00309 }
00310 }
00311
00312
00313
00314
00315 glColor4fv( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ).mV );
00316
00317 for ( int s=1; s<mAttributes.mNumStrands; s++)
00318 {
00319
00320 F32 x0 = (F32)(s-1) / (F32)( mAttributes.mNumStrands - 1 );
00321 F32 x1 = (F32)s / (F32)( mAttributes.mNumStrands - 1 );
00322
00323 for ( int i=0; i<mAttributes.mNumSegments; i++)
00324 {
00325 LLVector3 leftBottom;
00326 LLVector3 rightBottom;
00327 LLVector3 leftTop;
00328 LLVector3 rightTop;
00329
00330 F32 y0 = (F32)i / (F32)mAttributes.mNumSegments;
00331 F32 y1 = (F32)(i+1) / (F32)mAttributes.mNumSegments;
00332
00333 y0 = 1.0f - y0;
00334 y1 = 1.0f - y1;
00335
00336 if ( i == 0 )
00337 {
00338 leftBottom = mStrand[ s-1 ]->getAnchorPosition();
00339 rightBottom = mStrand[ s ]->getAnchorPosition();
00340 }
00341 else
00342 {
00343 leftBottom = mStrand[ s-1 ]->getNodePosition( i-1 );
00344 rightBottom = mStrand[ s ]->getNodePosition( i-1 );
00345 }
00346
00347 leftTop = mStrand[ s-1 ]->getNodePosition( i );
00348 rightTop = mStrand[ s ]->getNodePosition( i );
00349
00350
00351 LLViewerImage::bindTexture(theTexture);
00352
00353 glBegin( GL_TRIANGLE_STRIP );
00354 glTexCoord2f( x0, y0 ); glVertex3fv( leftBottom.mV );
00355 glTexCoord2f( x1, y0 ); glVertex3fv( rightBottom.mV );
00356 glTexCoord2f( x0, y1 ); glVertex3fv( leftTop.mV );
00357 glEnd();
00358 glBegin( GL_TRIANGLE_STRIP );
00359 glTexCoord2f( x1, y0 ); glVertex3fv( rightBottom.mV );
00360 glTexCoord2f( x1, y1 ); glVertex3fv( rightTop.mV );
00361 glTexCoord2f( x0, y1 ); glVertex3fv( leftTop.mV );
00362 glEnd();
00363
00364 theTexture->unbindTexture(0, GL_TEXTURE_2D);
00365 }
00366 }
00367 }
00368 }
00369
00370 }
00371
00372
00373
00374
00375
00376 void LLVOCloth::setAttributes( LLClothAttributes a )
00377 {
00378 mAttributes.mTextureFileName = a.mTextureFileName;
00379 mAttributes.mTextureIndex = a.mTextureIndex;
00380 mAttributes.mNumSegments = a.mNumSegments;
00381 mAttributes.mNumStrands = a.mNumStrands;
00382 mAttributes.mVisualizeStrands = a.mVisualizeStrands;
00383 mAttributes.mVisualizeAvCollisionSphere = a.mVisualizeAvCollisionSphere;
00384 mAttributes.mWidth = a.mWidth;
00385 mAttributes.mLength = a.mLength;
00386 mAttributes.mPitch = a.mPitch;
00387 mAttributes.mTension = a.mTension;
00388 mAttributes.mGravity = a.mGravity;
00389 mAttributes.mAirFriction = a.mAirFriction;
00390 mAttributes.mWindSensitivity = a.mWindSensitivity;
00391 mAttributes.mCircleWrapAmount = a.mCircleWrapAmount;
00392 mAttributes.mUsingAvatarCollisionSphere = a.mUsingAvatarCollisionSphere;
00393
00394 mAttributes.mAvatarCollisionSphereRadius = a.mAvatarCollisionSphereRadius;
00395 mAttributes.mAvatarCollisionSphereRightOffset = a.mAvatarCollisionSphereRightOffset;
00396 mAttributes.mAvatarCollisionSphereUpOffset = a.mAvatarCollisionSphereUpOffset;
00397 mAttributes.mAvatarCollisionSphereForwardOffset = a.mAvatarCollisionSphereForwardOffset;
00398
00399
00400 if ( mAttributes.mTextureIndex < CLOTH_MIN_TEXTURE_INDEX ){ mAttributes.mTextureIndex = CLOTH_MIN_TEXTURE_INDEX; }
00401 else if ( mAttributes.mTextureIndex > CLOTH_MAX_TEXTURE_INDEX ){ mAttributes.mTextureIndex = CLOTH_MAX_TEXTURE_INDEX; }
00402 if ( mAttributes.mPitch < CLOTH_MIN_PITCH ){ mAttributes.mPitch = CLOTH_MIN_PITCH; }
00403 else if ( mAttributes.mPitch > CLOTH_MAX_PITCH ){ mAttributes.mPitch = CLOTH_MAX_PITCH; }
00404 if ( mAttributes.mWidth < CLOTH_MIN_WIDTH ){ mAttributes.mWidth = CLOTH_MIN_WIDTH; }
00405 else if ( mAttributes.mWidth > CLOTH_MAX_WIDTH ){ mAttributes.mWidth = CLOTH_MAX_WIDTH; }
00406 if ( mAttributes.mLength < CLOTH_MIN_LENGTH ){ mAttributes.mLength = CLOTH_MIN_LENGTH; }
00407 else if ( mAttributes.mLength > CLOTH_MAX_LENGTH ){ mAttributes.mLength = CLOTH_MAX_LENGTH; }
00408 if ( mAttributes.mNumSegments < CLOTH_MIN_SEGMENTS ){ mAttributes.mNumSegments = CLOTH_MIN_SEGMENTS; }
00409 else if ( mAttributes.mNumSegments > CLOTH_MAX_SEGMENTS ){ mAttributes.mNumSegments = CLOTH_MAX_SEGMENTS; }
00410 if ( mAttributes.mNumStrands < CLOTH_MIN_STRANDS ){ mAttributes.mNumStrands = CLOTH_MIN_STRANDS; }
00411 else if ( mAttributes.mNumStrands > CLOTH_MAX_STRANDS ){ mAttributes.mNumStrands = CLOTH_MAX_STRANDS; }
00412 if ( mAttributes.mTension < CLOTH_MIN_TENSION ){ mAttributes.mTension = CLOTH_MIN_TENSION; }
00413 else if ( mAttributes.mTension > CLOTH_MAX_TENSION ){ mAttributes.mTension = CLOTH_MAX_TENSION; }
00414 if ( mAttributes.mGravity < CLOTH_MIN_GRAVITY ){ mAttributes.mGravity = CLOTH_MIN_GRAVITY; }
00415 else if ( mAttributes.mGravity > CLOTH_MAX_GRAVITY ){ mAttributes.mGravity = CLOTH_MAX_GRAVITY; }
00416 if ( mAttributes.mAirFriction < CLOTH_MIN_AIR_FRICTION ){ mAttributes.mAirFriction = CLOTH_MIN_AIR_FRICTION; }
00417 else if ( mAttributes.mAirFriction > CLOTH_MAX_AIR_FRICTION ){ mAttributes.mAirFriction = CLOTH_MAX_AIR_FRICTION; }
00418 if ( mAttributes.mWindSensitivity < CLOTH_MIN_WIND_SENSITIVITY ){ mAttributes.mWindSensitivity = CLOTH_MIN_WIND_SENSITIVITY;}
00419 else if ( mAttributes.mWindSensitivity > CLOTH_MAX_WIND_SENSITIVITY ){ mAttributes.mWindSensitivity = CLOTH_MAX_WIND_SENSITIVITY;}
00420 if ( mAttributes.mCircleWrapAmount < CLOTH_MIN_CIRCLE_WRAP_AMOUNT ){ mAttributes.mCircleWrapAmount = CLOTH_MIN_CIRCLE_WRAP_AMOUNT;}
00421 else if ( mAttributes.mCircleWrapAmount > CLOTH_MAX_CIRCLE_WRAP_AMOUNT ){ mAttributes.mCircleWrapAmount = CLOTH_MAX_CIRCLE_WRAP_AMOUNT;}
00422
00423 if ( mAttributes.mAvatarCollisionSphereRadius < CLOTH_MIN_AVATAR_COLLISION_SPHERE_RADIUS ){ mAttributes.mAvatarCollisionSphereRadius = CLOTH_MIN_AVATAR_COLLISION_SPHERE_RADIUS;}
00424 else if ( mAttributes.mAvatarCollisionSphereRadius > CLOTH_MAX_AVATAR_COLLISION_SPHERE_RADIUS ){ mAttributes.mAvatarCollisionSphereRadius = CLOTH_MAX_AVATAR_COLLISION_SPHERE_RADIUS;}
00425 if ( mAttributes.mAvatarCollisionSphereRightOffset < CLOTH_MIN_AVATAR_COLLISION_SPHERE_RIGHT_OFFSET ){ mAttributes.mAvatarCollisionSphereRightOffset = CLOTH_MIN_AVATAR_COLLISION_SPHERE_RIGHT_OFFSET;}
00426 else if ( mAttributes.mAvatarCollisionSphereRightOffset > CLOTH_MAX_AVATAR_COLLISION_SPHERE_RIGHT_OFFSET ){ mAttributes.mAvatarCollisionSphereRightOffset = CLOTH_MAX_AVATAR_COLLISION_SPHERE_RIGHT_OFFSET;}
00427 if ( mAttributes.mAvatarCollisionSphereUpOffset < CLOTH_MIN_AVATAR_COLLISION_SPHERE_UP_OFFSET ){ mAttributes.mAvatarCollisionSphereUpOffset = CLOTH_MIN_AVATAR_COLLISION_SPHERE_UP_OFFSET;}
00428 else if ( mAttributes.mAvatarCollisionSphereUpOffset > CLOTH_MAX_AVATAR_COLLISION_SPHERE_UP_OFFSET ){ mAttributes.mAvatarCollisionSphereUpOffset = CLOTH_MAX_AVATAR_COLLISION_SPHERE_UP_OFFSET;}
00429 if ( mAttributes.mAvatarCollisionSphereForwardOffset < CLOTH_MIN_AVATAR_COLLISION_SPHERE_FORWARD_OFFSET ){ mAttributes.mAvatarCollisionSphereForwardOffset = CLOTH_MIN_AVATAR_COLLISION_SPHERE_FORWARD_OFFSET;}
00430 else if ( mAttributes.mAvatarCollisionSphereForwardOffset > CLOTH_MAX_AVATAR_COLLISION_SPHERE_FORWARD_OFFSET ){ mAttributes.mAvatarCollisionSphereForwardOffset = CLOTH_MAX_AVATAR_COLLISION_SPHERE_FORWARD_OFFSET;}
00431
00432
00433
00434
00435 generateStrands();
00436
00437 }
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448 void LLVOCloth::setNumStrands( int num )
00449 {
00450 mAttributes.mNumStrands = num;
00451 generateStrands();
00452 }
00453
00454 void LLVOCloth::setNumSegments( int num )
00455 {
00456 mAttributes.mNumSegments = num;
00457 generateStrands();
00458 }
00459
00460 void LLVOCloth::setLength( F32 le )
00461 {
00462 mAttributes.mLength = le;
00463 generateStrands();
00464 }
00465
00466 void LLVOCloth::setCircleWrapAmount( F32 n )
00467 {
00468 mAttributes.mCircleWrapAmount = n;
00469 generateStrands();
00470 }
00471
00472 void LLVOCloth::setGravity( F32 g )
00473 {
00474 mAttributes.mGravity = g;
00475 generateStrands();
00476 }
00477
00478 void LLVOCloth::setPitch( F32 p )
00479 {
00480 mAttributes.mPitch = p;
00481 generateStrands();
00482 }
00483
00484 void LLVOCloth::setAirFriction( F32 a )
00485 {
00486 mAttributes.mAirFriction = a;
00487 generateStrands();
00488 }
00489
00490 void LLVOCloth::setWindSensitivity( F32 w )
00491 {
00492 mAttributes.mWindSensitivity = w;
00493 generateStrands();
00494 }
00495
00496 void LLVOCloth::setTension( F32 t )
00497 {
00498 mAttributes.mTension = t;
00499 generateStrands();
00500 }
00501
00502 void LLVOCloth::setWidth( F32 n )
00503 {
00504 mAttributes.mWidth = n;
00505 generateStrands();
00506 }
00507
00508 void LLVOCloth::setVisualizingStrands( bool v )
00509 {
00510 mAttributes.mVisualizeStrands = v;
00511 }
00512 void LLVOCloth::setVisualizingAvCollisionSphere( bool v )
00513 {
00514 mAttributes.mVisualizeAvCollisionSphere = v;
00515 }
00516
00517 void LLVOCloth::setAvatarCollisionSphereRadius( F32 r )
00518 {
00519 mAttributes.mAvatarCollisionSphereRadius = r;
00520
00521 }
00522
00523 void LLVOCloth::setAvatarCollisionSphereRight( F32 r )
00524 {
00525 mAttributes.mAvatarCollisionSphereRightOffset = r;
00526
00527 }
00528
00529 void LLVOCloth::setAvatarCollisionSphereUp( F32 u )
00530 {
00531 mAttributes.mAvatarCollisionSphereUpOffset = u;
00532
00533 }
00534
00535 void LLVOCloth::setAvatarCollisionSphereForward( F32 f )
00536 {
00537 mAttributes.mAvatarCollisionSphereForwardOffset = f;
00538
00539 }
00540
00541
00542
00543
00544
00545
00546
00547 int LLVOCloth::getNumStrands()
00548 {
00549 return mAttributes.mNumStrands;
00550 }
00551
00552 int LLVOCloth::getNumSegments()
00553 {
00554 return mAttributes.mNumSegments;
00555 }
00556
00557 F32 LLVOCloth::getLength()
00558 {
00559 return mAttributes.mLength;
00560 }
00561
00562 F32 LLVOCloth::getWidth()
00563 {
00564 return mAttributes.mWidth;
00565 }
00566
00567 F32 LLVOCloth::getCircleWrapAmount()
00568 {
00569 return mAttributes.mCircleWrapAmount;
00570 }
00571
00572 F32 LLVOCloth::getPitch()
00573 {
00574 return mAttributes.mPitch;
00575 }
00576
00577 F32 LLVOCloth::getTension()
00578 {
00579 return mAttributes.mTension;
00580 }
00581
00582 F32 LLVOCloth::getGravity()
00583 {
00584 return mAttributes.mGravity;
00585 }
00586
00587 F32 LLVOCloth::getAirFriction()
00588 {
00589 return mAttributes.mAirFriction;
00590 }
00591
00592 F32 LLVOCloth::getWindSensitivity()
00593 {
00594 return mAttributes.mWindSensitivity;
00595 }
00596
00597 bool LLVOCloth::getVisualizingStrands() const
00598 {
00599 return mAttributes.mVisualizeStrands;
00600 }
00601
00602 bool LLVOCloth::getVisualizingAvCollisionSphere() const
00603 {
00604 return mAttributes.mVisualizeAvCollisionSphere;
00605 }
00606
00607 F32 LLVOCloth::getAvatarCollisionSphereRadius()
00608 {
00609 return mAttributes.mAvatarCollisionSphereRadius;
00610 }
00611
00612 F32 LLVOCloth::getAvatarCollisionSphereRight()
00613 {
00614 return mAttributes.mAvatarCollisionSphereRightOffset;
00615 }
00616
00617 F32 LLVOCloth::getAvatarCollisionSphereUp()
00618 {
00619 return mAttributes.mAvatarCollisionSphereUpOffset;
00620 }
00621
00622 F32 LLVOCloth::getAvatarCollisionSphereForward()
00623 {
00624 return mAttributes.mAvatarCollisionSphereForwardOffset;
00625 }
00626
00627
00628
00629
00630 void LLVOCloth::markAsDead()
00631 {
00632 mDead = TRUE;
00633
00634 }
00635
00636
00637
00638
00639
00640
00641
00642