// return height of a sphere of given radius, located at center, in pixels F32 LLCamera::heightInPixels(const LLVector3 ¢er, F32 radius ) const { if (radius == 0.f) return 0.f; // If height initialized if (mViewHeightInPixels > -1) { // Convert sphere to coord system with 0,0,0 at camera LLVector3 vec = center - mOrigin; // Compute distance to sphere F32 dist = vec.magVec(); // Calculate angle of whole object F32 angle = 2.0f * (F32) atan2(radius, dist); // Calculate fraction of field of view F32 fraction_of_fov = angle / mView; // Compute number of pixels tall, based on vertical field of view return (fraction_of_fov * mViewHeightInPixels); } else { // return invalid height return -1.0f; } }
// If pos is visible, return the distance from pos to the camera. // Use fudge distance to scale rad against top/bot/left/right planes // Otherwise, return -distance F32 LLCamera::visibleDistance(const LLVector3 &pos, F32 rad, F32 fudgedist, U32 planemask) const { if (mFixedDistance > 0) { return mFixedDistance; } LLVector3 dvec = pos - mOrigin; // Check visibility F32 dist = dvec.magVec(); if (dist > rad) { F32 dp,tdist; dp = dvec * mXAxis; if (dp < -rad) return -dist; rad *= fudgedist; LLVector3 tvec(pos); for (int p=0; p<PLANE_NUM; p++) { if (!(planemask & (1<<p))) continue; tdist = -(mWorldPlanes[p].dist(tvec)); if (tdist > rad) return -dist; } } return dist; }
void LLDrawable::updateDistance(LLCamera& camera, bool force_update) { if (LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD) { llwarns << "Attempted to update distance for non-world camera." << llendl; return; } //switch LOD with the spatial group to avoid artifacts //LLSpatialGroup* sg = getSpatialGroup(); LLVector3 pos; //if (!sg || sg->changeLOD()) { LLVOVolume* volume = getVOVolume(); if (volume) { if (getSpatialGroup()) { pos.set(getPositionGroup().getF32ptr()); } else { pos = getPositionAgent(); } if (isState(LLDrawable::HAS_ALPHA)) { for (S32 i = 0; i < getNumFaces(); i++) { LLFace* facep = getFace(i); if (force_update || facep->getPoolType() == LLDrawPool::POOL_ALPHA) { LLVector4a box; box.setSub(facep->mExtents[1], facep->mExtents[0]); box.mul(0.25f); LLVector3 v = (facep->mCenterLocal-camera.getOrigin()); const LLVector3& at = camera.getAtAxis(); for (U32 j = 0; j < 3; j++) { v.mV[j] -= box[j] * at.mV[j]; } facep->mDistance = v * camera.getAtAxis(); } } } } else { pos = LLVector3(getPositionGroup().getF32ptr()); } pos -= camera.getOrigin(); mDistanceWRTCamera = llround(pos.magVec(), 0.01f); mVObjp->updateLOD(); } }
void LLSpatialBridge::updateSpatialExtents() { LLSpatialGroup* root = (LLSpatialGroup*) mOctree->getListener(0); { LLFastTimer ftm(LLFastTimer::FTM_CULL_REBOUND); root->rebound(); } LLXformMatrix* mat = mDrawable->getXform(); LLVector3 offset = root->mBounds[0]; LLVector3 size = root->mBounds[1]; LLVector3 center = LLVector3(0,0,0) * mat->getWorldMatrix(); LLQuaternion rotation = LLQuaternion(mat->getWorldMatrix()); offset *= rotation; center += offset; LLVector3 v[4]; //get 4 corners of bounding box v[0] = (size * rotation); v[1] = (LLVector3(-size.mV[0], -size.mV[1], size.mV[2]) * rotation); v[2] = (LLVector3(size.mV[0], -size.mV[1], -size.mV[2]) * rotation); v[3] = (LLVector3(-size.mV[0], size.mV[1], -size.mV[2]) * rotation); LLVector3& newMin = mExtents[0]; LLVector3& newMax = mExtents[1]; newMin = newMax = center; for (U32 i = 0; i < 4; i++) { for (U32 j = 0; j < 3; j++) { F32 delta = fabsf(v[i].mV[j]); F32 min = center.mV[j] - delta; F32 max = center.mV[j] + delta; if (min < newMin.mV[j]) { newMin.mV[j] = min; } if (max > newMax.mV[j]) { newMax.mV[j] = max; } } } LLVector3 diagonal = newMax - newMin; mRadius = diagonal.magVec() * 0.5f; mPositionGroup.setVec((newMin + newMax) * 0.5f); updateBinRadius(); }
void LLSurfacePatch::updateCameraDistanceRegion(const LLVector3 &pos_region) { if (LLPipeline::sDynamicLOD) { LLVector3 dv = pos_region; dv -= mCenterRegion; mVisInfo.mDistance = llmax(0.f, (F32)(dv.magVec() - mRadius))/ llmax(LLVOSurfacePatch::sLODFactor, 0.1f); } else { mVisInfo.mDistance = 0.f; } }
//------------------------------------------------------------------------------------- BOOL LLFollowCam::updateBehindnessConstraint(LLVector3 focus, LLVector3& cam_position) { BOOL constraint_active = FALSE; // only apply this stuff if the behindness angle is something other than opened up all the way if ( mBehindnessMaxAngle < FOLLOW_CAM_MAX_BEHINDNESS_ANGLE - FOLLOW_CAM_BEHINDNESS_EPSILON ) { //-------------------------------------------------------------- // horizontalized vector from focus to camera //-------------------------------------------------------------- LLVector3 horizontalVectorFromFocusToCamera; horizontalVectorFromFocusToCamera.setVec(cam_position - focus); horizontalVectorFromFocusToCamera.mV[ VZ ] = 0.0f; F32 cameraZ = cam_position.mV[ VZ ]; //-------------------------------------------------------------- // distance of horizontalized vector //-------------------------------------------------------------- F32 horizontalDistance = horizontalVectorFromFocusToCamera.magVec(); //-------------------------------------------------------------------------------------------------- // calculate horizontalized back vector of the subject and scale by horizontalDistance //-------------------------------------------------------------------------------------------------- LLVector3 horizontalSubjectBack( -1.0f, 0.0f, 0.0f ); horizontalSubjectBack *= mSubjectRotation; horizontalSubjectBack.mV[ VZ ] = 0.0f; horizontalSubjectBack.normVec(); // because horizontalizing might make it shorter than 1 horizontalSubjectBack *= horizontalDistance; //-------------------------------------------------------------------------------------------------- // find the angle (in degrees) between these vectors //-------------------------------------------------------------------------------------------------- F32 cameraOffsetAngle = 0.f; LLVector3 cameraOffsetRotationAxis; LLQuaternion camera_offset_rotation; camera_offset_rotation.shortestArc(horizontalSubjectBack, horizontalVectorFromFocusToCamera); camera_offset_rotation.getAngleAxis(&cameraOffsetAngle, cameraOffsetRotationAxis); cameraOffsetAngle *= RAD_TO_DEG; if ( cameraOffsetAngle > mBehindnessMaxAngle ) { F32 fraction = ((cameraOffsetAngle - mBehindnessMaxAngle) / cameraOffsetAngle) * LLCriticalDamp::getInterpolant(mBehindnessLag); cam_position = focus + horizontalSubjectBack * (slerp(fraction, camera_offset_rotation, LLQuaternion::DEFAULT)); cam_position.mV[VZ] = cameraZ; // clamp z value back to what it was before we started messing with it constraint_active = TRUE; } } return constraint_active; }
void LLDrawable::updateDistance(LLCamera& camera, bool force_update) { //switch LOD with the spatial group to avoid artifacts //LLSpatialGroup* sg = getSpatialGroup(); LLVector3 pos; //if (!sg || sg->changeLOD()) { LLVOVolume* volume = getVOVolume(); if (volume) { volume->updateRelativeXform(); pos = volume->getRelativeXform().getTranslation(); if (isStatic()) { pos += volume->getRegion()->getOriginAgent(); } if (isState(LLDrawable::HAS_ALPHA)) { for (S32 i = 0; i < getNumFaces(); i++) { LLFace* facep = getFace(i); if (facep->getPoolType() == LLDrawPool::POOL_ALPHA) { LLVector3 box = (facep->mExtents[1] - facep->mExtents[0]) * 0.25f; LLVector3 v = (facep->mCenterLocal-camera.getOrigin()); const LLVector3& at = camera.getAtAxis(); for (U32 j = 0; j < 3; j++) { v.mV[j] -= box.mV[j] * at.mV[j]; } facep->mDistance = v * camera.getAtAxis(); } } } } else { pos = LLVector3(getPositionGroup()); } pos -= camera.getOrigin(); mDistanceWRTCamera = llround(pos.magVec(), 0.01f); mVObjp->updateLOD(); } }
BOOL LLVOTree::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, S32 face, BOOL pick_transparent, S32 *face_hitp, LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal) { if (!lineSegmentBoundingBox(start, end)) { return FALSE; } const LLVector4a* exta = mDrawable->getSpatialExtents(); //VECTORIZE THIS LLVector3 ext[2]; ext[0].set(exta[0].getF32ptr()); ext[1].set(exta[1].getF32ptr()); LLVector3 center = (ext[1]+ext[0])*0.5f; LLVector3 size = (ext[1]-ext[0]); LLQuaternion quat = getRotation(); center -= LLVector3(0,0,size.magVec() * 0.25f)*quat; size.scaleVec(LLVector3(0.25f, 0.25f, 1.f)); size.mV[0] = llmin(size.mV[0], 1.f); size.mV[1] = llmin(size.mV[1], 1.f); LLVector3 pos, norm; if (linesegment_tetrahedron(start, end, center, size, quat, pos, norm)) { if (intersection) { *intersection = pos; } if (normal) { *normal = norm; } return TRUE; } return FALSE; }
F64 LLAudioEngine::mapWindVecToGain(LLVector3 wind_vec) { F64 gain = 0.0; gain = wind_vec.magVec(); if (gain) { if (gain > 20) { gain = 20; } gain = gain/20.0; } return (gain); }
// Like visibleDistance, except uses mHorizPlanes[], which are left and right // planes perpindicular to (0,0,1) in world space F32 LLCamera::visibleHorizDistance(const LLVector3 &pos, F32 rad, F32 fudgedist, U32 planemask) const { if (mFixedDistance > 0) { return mFixedDistance; } LLVector3 dvec = pos - mOrigin; // Check visibility F32 dist = dvec.magVec(); if (dist > rad) { rad *= fudgedist; LLVector3 tvec(pos); for (int p=0; p<HORIZ_PLANE_NUM; p++) { if (!(planemask & (1<<p))) continue; F32 tdist = -(mHorizPlanes[p].dist(tvec)); if (tdist > rad) return -dist; } } return dist; }
void LLHoverView::updateText() { LLViewerObject* hit_object = getLastHoverObject(); std::string line; mText.clear(); if ( hit_object ) { if ( hit_object->isHUDAttachment() ) { // no hover tips for HUD elements, since they can obscure // what the HUD is displaying return; } if ( hit_object->isAttachment() ) { // get root of attachment then parent, which is avatar LLViewerObject* root_edit = hit_object->getRootEdit(); if (!root_edit) { // Strange parenting issue, don't show any text return; } hit_object = (LLViewerObject*)root_edit->getParent(); if (!hit_object) { // another strange parenting issue, bail out return; } } line.clear(); if (hit_object->isAvatar()) { LLNameValue* title = hit_object->getNVPair("Title"); LLNameValue* firstname = hit_object->getNVPair("FirstName"); LLNameValue* lastname = hit_object->getNVPair("LastName"); if (firstname && lastname) { // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) { line = RlvStrings::getAnonym(line.append(firstname->getString()).append(1, ' ').append(lastname->getString())); } else { // [/RLVa:KB] if (title) { line.append(title->getString()); line.append(1, ' '); } line.append(firstname->getString()); line.append(1, ' '); line.append(lastname->getString()); // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) } // [/RLVa:KB] } else { line.append(LLTrans::getString("TooltipPerson")); } mText.push_back(line); } else { // // We have hit a regular object (not an avatar or attachment) // // // Default prefs will suppress display unless the object is interactive // BOOL suppressObjectHoverDisplay = !gSavedSettings.getBOOL("ShowAllObjectHoverTip"); LLSelectNode *nodep = LLSelectMgr::getInstance()->getHoverNode();; if (nodep) { line.clear(); if (nodep->mName.empty()) { line.append(LLTrans::getString("TooltipNoName")); } else { line.append( nodep->mName ); } mText.push_back(line); if (!nodep->mDescription.empty() && nodep->mDescription != DEFAULT_DESC) { mText.push_back( nodep->mDescription ); } // Line: "Owner: James Linden" line.clear(); line.append(LLTrans::getString("TooltipOwner") + " "); if (nodep->mValid) { LLUUID owner; std::string name; if (!nodep->mPermissions->isGroupOwned()) { owner = nodep->mPermissions->getOwner(); if (LLUUID::null == owner) { line.append(LLTrans::getString("TooltipPublic")); } else if(gCacheName->getFullName(owner, name)) { // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) { name = RlvStrings::getAnonym(name); } // [/RLVa:KB] line.append(name); } else { line.append(LLTrans::getString("RetrievingData")); } } else { std::string name; owner = nodep->mPermissions->getGroup(); if (gCacheName->getGroupName(owner, name)) { line.append(name); line.append(LLTrans::getString("TooltipIsGroup")); } else { line.append(LLTrans::getString("RetrievingData")); } } } else { line.append(LLTrans::getString("RetrievingData")); } mText.push_back(line); // Build a line describing any special properties of this object. LLViewerObject *object = hit_object; LLViewerObject *parent = (LLViewerObject *)object->getParent(); if (object && (object->usePhysics() || object->flagScripted() || object->flagHandleTouch() || (parent && parent->flagHandleTouch()) || object->flagTakesMoney() || (parent && parent->flagTakesMoney()) || object->flagAllowInventoryAdd() || object->flagTemporary() || object->flagPhantom()) ) { line.clear(); if (object->flagScripted()) { line.append(LLTrans::getString("TooltipFlagScript") + " "); } if (object->usePhysics()) { line.append(LLTrans::getString("TooltipFlagPhysics") + " "); } if (object->flagHandleTouch() || (parent && parent->flagHandleTouch()) ) { line.append(LLTrans::getString("TooltipFlagTouch") + " "); suppressObjectHoverDisplay = FALSE; // Show tip } if (object->flagTakesMoney() || (parent && parent->flagTakesMoney()) ) { line.append(LLTrans::getString("TooltipFlagL$") + " "); suppressObjectHoverDisplay = FALSE; // Show tip } if (object->flagAllowInventoryAdd()) { line.append(LLTrans::getString("TooltipFlagDropInventory") + " "); suppressObjectHoverDisplay = FALSE; // Show tip } if (object->flagPhantom()) { line.append(LLTrans::getString("TooltipFlagPhantom") + " "); } if (object->flagTemporary()) { line.append(LLTrans::getString("TooltipFlagTemporary") + " "); } if (object->usePhysics() || object->flagHandleTouch() || (parent && parent->flagHandleTouch()) ) { line.append(LLTrans::getString("TooltipFlagRightClickMenu") + " "); } mText.push_back(line); } // Free to copy / For Sale: L$ line.clear(); if (nodep->mValid) { BOOL for_copy = nodep->mPermissions->getMaskEveryone() & PERM_COPY && object->permCopy(); BOOL for_sale = nodep->mSaleInfo.isForSale() && nodep->mPermissions->getMaskOwner() & PERM_TRANSFER && (nodep->mPermissions->getMaskOwner() & PERM_COPY || nodep->mSaleInfo.getSaleType() != LLSaleInfo::FS_COPY); if (for_copy) { line.append(LLTrans::getString("TooltipFreeToCopy")); suppressObjectHoverDisplay = FALSE; // Show tip } else if (for_sale) { LLStringUtil::format_map_t args; args["[AMOUNT]"] = llformat("%d", nodep->mSaleInfo.getSalePrice()); line.append(LLTrans::getString("TooltipForSaleL$", args)); suppressObjectHoverDisplay = FALSE; // Show tip } else { // Nothing if not for sale // line.append("Not for sale"); } } else { LLStringUtil::format_map_t args; args["[MESSAGE]"] = LLTrans::getString("RetrievingData"); line.append(LLTrans::getString("TooltipForSaleMsg", args)); } mText.push_back(line); } line.clear(); S32 prim_count = LLSelectMgr::getInstance()->getHoverObjects()->getObjectCount(); line.append(llformat("Prims: %d", prim_count)); mText.push_back(line); line.clear(); line.append("Position: "); LLViewerRegion *region = gAgent.getRegion(); LLVector3 position = region->getPosRegionFromGlobal(hit_object->getPositionGlobal());//regionp->getOriginAgent(); LLVector3 mypos = region->getPosRegionFromGlobal(gAgent.getPositionGlobal()); LLVector3 delta = position - mypos; F32 distance = (F32)delta.magVec(); line.append(llformat("<%.02f,%.02f,%.02f>",position.mV[0],position.mV[1],position.mV[2])); mText.push_back(line); line.clear(); line.append(llformat("Distance: %.02fm",distance)); mText.push_back(line); // If the hover tip shouldn't be shown, delete all the object text if (suppressObjectHoverDisplay) { mText.clear(); } } } else if ( mHoverLandGlobal != LLVector3d::zero ) { // // Do not show hover for land unless prefs are set to allow it. // if (!gSavedSettings.getBOOL("ShowLandHoverTip")) return; // Didn't hit an object, but since we have a land point we // must be hovering over land. LLParcel* hover_parcel = LLViewerParcelMgr::getInstance()->getHoverParcel(); LLUUID owner; S32 width = 0; S32 height = 0; if ( hover_parcel ) { owner = hover_parcel->getOwnerID(); width = S32(LLViewerParcelMgr::getInstance()->getHoverParcelWidth()); height = S32(LLViewerParcelMgr::getInstance()->getHoverParcelHeight()); } // Line: "Land" line.clear(); line.append(LLTrans::getString("TooltipLand")); if (hover_parcel) { // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | Added: RLVa-0.2.0b line.append( (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ? hover_parcel->getName() : RlvStrings::getString(RLV_STRING_HIDDEN_PARCEL) ); // [/RLVa:KB] //line.append(hover_parcel->getName()); } mText.push_back(line); // Line: "Owner: James Linden" line.clear(); line.append(LLTrans::getString("TooltipOwner") + " "); if ( hover_parcel ) { std::string name; if (LLUUID::null == owner) { line.append(LLTrans::getString("TooltipPublic")); } else if (hover_parcel->getIsGroupOwned()) { if (gCacheName->getGroupName(owner, name)) { line.append(name); line.append(LLTrans::getString("TooltipIsGroup")); } else { line.append(LLTrans::getString("RetrievingData")); } } else if(gCacheName->getFullName(owner, name)) { // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.0b line.append( (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) ? name : RlvStrings::getAnonym(name)); // [/RLVa:KB] //line.append(name); } else { line.append(LLTrans::getString("RetrievingData")); } } else { line.append(LLTrans::getString("RetrievingData")); } mText.push_back(line); // Line: "no fly, not safe, no build" // Don't display properties for your land. This is just // confusing, because you can do anything on your own land. if ( hover_parcel && owner != gAgent.getID() ) { S32 words = 0; line.clear(); // JC - Keep this in the same order as the checkboxes // on the land info panel if ( !hover_parcel->getAllowModify() ) { if ( hover_parcel->getAllowGroupModify() ) { line.append(LLTrans::getString("TooltipFlagGroupBuild")); } else { line.append(LLTrans::getString("TooltipFlagNoBuild")); } words++; } if ( !hover_parcel->getAllowTerraform() ) { if (words) line.append(", "); line.append(LLTrans::getString("TooltipFlagNoEdit")); words++; } if ( hover_parcel->getAllowDamage() ) { if (words) line.append(", "); line.append(LLTrans::getString("TooltipFlagNotSafe")); words++; } // Maybe we should reflect the estate's block fly bit here as well? DK 12/1/04 if ( !hover_parcel->getAllowFly() ) { if (words) line.append(", "); line.append(LLTrans::getString("TooltipFlagNoFly")); words++; } if ( !hover_parcel->getAllowOtherScripts() ) { if (words) line.append(", "); if ( hover_parcel->getAllowGroupScripts() ) { line.append(LLTrans::getString("TooltipFlagGroupScripts")); } else { line.append(LLTrans::getString("TooltipFlagNoScripts")); } words++; } if (words) { mText.push_back(line); } } // Line: "Size: 1x4" // Only show for non-public land /* if ( hover_parcel && LLUUID::null != owner) { line = llformat("Size: %dx%d", width, height ); mText.push_back(line); } */ if (hover_parcel && hover_parcel->getParcelFlag(PF_FOR_SALE)) { LLStringUtil::format_map_t args; args["[AMOUNT]"] = llformat("%d", hover_parcel->getSalePrice()); line = LLTrans::getString("TooltipForSaleL$", args); mText.push_back(line); } } }
//----------------------------------------------------------------------------- // solve() //----------------------------------------------------------------------------- void LLJointSolverRP3::solve() { // llinfos << llendl; // llinfos << "LLJointSolverRP3::solve()" << llendl; //------------------------------------------------------------------------- // setup joints in their base rotations //------------------------------------------------------------------------- mJointA->setRotation( mJointABaseRotation ); mJointB->setRotation( mJointBBaseRotation ); //------------------------------------------------------------------------- // get joint positions in world space //------------------------------------------------------------------------- LLVector3 aPos = mJointA->getWorldPosition(); LLVector3 bPos = mJointB->getWorldPosition(); LLVector3 cPos = mJointC->getWorldPosition(); LLVector3 gPos = mJointGoal->getWorldPosition(); // llinfos << "bPosLocal = " << mJointB->getPosition() << llendl; // llinfos << "cPosLocal = " << mJointC->getPosition() << llendl; // llinfos << "bRotLocal = " << mJointB->getRotation() << llendl; // llinfos << "cRotLocal = " << mJointC->getRotation() << llendl; // llinfos << "aPos : " << aPos << llendl; // llinfos << "bPos : " << bPos << llendl; // llinfos << "cPos : " << cPos << llendl; // llinfos << "gPos : " << gPos << llendl; //------------------------------------------------------------------------- // get the poleVector in world space //------------------------------------------------------------------------- LLVector3 poleVec = mPoleVector; if ( mJointA->getParent() ) { LLVector4a pole_veca; pole_veca.load3(mPoleVector.mV); mJointA->getParent()->getWorldMatrix().rotate(pole_veca,pole_veca); poleVec.set(pole_veca.getF32ptr()); } //------------------------------------------------------------------------- // compute the following: // vector from A to B // vector from B to C // vector from A to C // vector from A to G (goal) //------------------------------------------------------------------------- LLVector3 abVec = bPos - aPos; LLVector3 bcVec = cPos - bPos; LLVector3 acVec = cPos - aPos; LLVector3 agVec = gPos - aPos; // llinfos << "abVec : " << abVec << llendl; // llinfos << "bcVec : " << bcVec << llendl; // llinfos << "acVec : " << acVec << llendl; // llinfos << "agVec : " << agVec << llendl; //------------------------------------------------------------------------- // compute needed lengths of those vectors //------------------------------------------------------------------------- F32 abLen = abVec.magVec(); F32 bcLen = bcVec.magVec(); F32 agLen = agVec.magVec(); // llinfos << "abLen : " << abLen << llendl; // llinfos << "bcLen : " << bcLen << llendl; // llinfos << "agLen : " << agLen << llendl; //------------------------------------------------------------------------- // compute component vector of (A->B) orthogonal to (A->C) //------------------------------------------------------------------------- LLVector3 abacCompOrthoVec = abVec - acVec * ((abVec * acVec)/(acVec * acVec)); // llinfos << "abacCompOrthoVec : " << abacCompOrthoVec << llendl; //------------------------------------------------------------------------- // compute the normal of the original ABC plane (and store for later) //------------------------------------------------------------------------- LLVector3 abcNorm; if (!mbUseBAxis) { if( are_parallel(abVec, bcVec, 0.001f) ) { // the current solution is maxed out, so we use the axis that is // orthogonal to both poleVec and A->B if ( are_parallel(poleVec, abVec, 0.001f) ) { // ACK! the problem is singular if ( are_parallel(poleVec, agVec, 0.001f) ) { // the solutions is also singular return; } else { abcNorm = poleVec % agVec; } } else { abcNorm = poleVec % abVec; } } else { abcNorm = abVec % bcVec; } } else { abcNorm = mBAxis * mJointB->getWorldRotation(); } //------------------------------------------------------------------------- // compute rotation of B //------------------------------------------------------------------------- // angle between A->B and B->C F32 abbcAng = angle_between(abVec, bcVec); // vector orthogonal to A->B and B->C LLVector3 abbcOrthoVec = abVec % bcVec; if (abbcOrthoVec.magVecSquared() < 0.001f) { abbcOrthoVec = poleVec % abVec; abacCompOrthoVec = poleVec; } abbcOrthoVec.normVec(); F32 agLenSq = agLen * agLen; // angle arm for extension F32 cosTheta = (agLenSq - abLen*abLen - bcLen*bcLen) / (2.0f * abLen * bcLen); if (cosTheta > 1.0f) cosTheta = 1.0f; else if (cosTheta < -1.0f) cosTheta = -1.0f; F32 theta = acos(cosTheta); LLQuaternion bRot(theta - abbcAng, abbcOrthoVec); // llinfos << "abbcAng : " << abbcAng << llendl; // llinfos << "abbcOrthoVec : " << abbcOrthoVec << llendl; // llinfos << "agLenSq : " << agLenSq << llendl; // llinfos << "cosTheta : " << cosTheta << llendl; // llinfos << "theta : " << theta << llendl; // llinfos << "bRot : " << bRot << llendl; // llinfos << "theta abbcAng theta-abbcAng: " << theta*180.0/F_PI << " " << abbcAng*180.0f/F_PI << " " << (theta - abbcAng)*180.0f/F_PI << llendl; //------------------------------------------------------------------------- // compute rotation that rotates new A->C to A->G //------------------------------------------------------------------------- // rotate B->C by bRot bcVec = bcVec * bRot; // update A->C acVec = abVec + bcVec; LLQuaternion cgRot; cgRot.shortestArc( acVec, agVec ); // llinfos << "bcVec : " << bcVec << llendl; // llinfos << "acVec : " << acVec << llendl; // llinfos << "cgRot : " << cgRot << llendl; // update A->B and B->C with rotation from C to G abVec = abVec * cgRot; bcVec = bcVec * cgRot; abcNorm = abcNorm * cgRot; acVec = abVec + bcVec; //------------------------------------------------------------------------- // compute the normal of the APG plane //------------------------------------------------------------------------- if (are_parallel(agVec, poleVec, 0.001f)) { // the solution plane is undefined ==> we're done return; } LLVector3 apgNorm = poleVec % agVec; apgNorm.normVec(); if (!mbUseBAxis) { //--------------------------------------------------------------------- // compute the normal of the new ABC plane // (only necessary if we're NOT using mBAxis) //--------------------------------------------------------------------- if( are_parallel(abVec, bcVec, 0.001f) ) { // G is either too close or too far away // we'll use the old ABCnormal } else { abcNorm = abVec % bcVec; } abcNorm.normVec(); } //------------------------------------------------------------------------- // calcuate plane rotation //------------------------------------------------------------------------- LLQuaternion pRot; if ( are_parallel( abcNorm, apgNorm, 0.001f) ) { if (abcNorm * apgNorm < 0.0f) { // we must be PI radians off ==> rotate by PI around agVec pRot.setQuat(F_PI, agVec); } else { // we're done } } else { pRot.shortestArc( abcNorm, apgNorm ); } // llinfos << "abcNorm = " << abcNorm << llendl; // llinfos << "apgNorm = " << apgNorm << llendl; // llinfos << "pRot = " << pRot << llendl; //------------------------------------------------------------------------- // compute twist rotation //------------------------------------------------------------------------- LLQuaternion twistRot( mTwist, agVec ); // llinfos << "twist : " << mTwist*180.0/F_PI << llendl; // llinfos << "agNormVec: " << agNormVec << llendl; // llinfos << "twistRot : " << twistRot << llendl; //------------------------------------------------------------------------- // compute rotation of A //------------------------------------------------------------------------- LLQuaternion aRot = cgRot * pRot * twistRot; //------------------------------------------------------------------------- // apply the rotations //------------------------------------------------------------------------- mJointB->setWorldRotation( mJointB->getWorldRotation() * bRot ); mJointA->setWorldRotation( mJointA->getWorldRotation() * aRot ); }
//----------------------------------------------------------------------------- // loadBVH() //----------------------------------------------------------------------------- BOOL LLFloaterAnimPreview::loadBVH() { LLKeyframeMotion* motionp = NULL; LLBVHLoader* loaderp = NULL; mPlayButton->setVisible(true); mPauseButton->setVisible(false); getChildView("bad_animation_text")->setVisible(FALSE); std::string exten = gDirUtilp->getExtension(mFilename); if (exten == "bvh") { // loading a bvh file // now load bvh file S32 file_size; LLAPRFile infile ; infile.open(mFilenameAndPath, LL_APR_RB, NULL, &file_size); if (!infile.getFileHandle()) { llwarns << "Can't open BVH file:" << mFilename << llendl; } else { char* file_buffer; file_buffer = new char[file_size + 1]; if (file_size == infile.read(file_buffer, file_size)) { file_buffer[file_size] = '\0'; llinfos << "Loading BVH file " << mFilename << llendl; ELoadStatus load_status = E_ST_OK; S32 line_number = 0; loaderp = new LLBVHLoader(file_buffer, load_status, line_number); std::string status = getString(STATUS[load_status]); if(load_status == E_ST_NO_XLT_FILE) { llwarns << "NOTE: No translation table found." << llendl; } else { llwarns << "ERROR: [line: " << line_number << "] " << status << llendl; } } infile.close() ; delete[] file_buffer; } } if (loaderp && loaderp->isInitialized() && loaderp->getDuration() <= MAX_ANIM_DURATION) { // generate unique id for this motion mTransactionID.generate(); mMotionID = mTransactionID.makeAssetID(gAgent.getSecureSessionID()); mAnimPreview = new LLPreviewAnimation(256, 256); // motion will be returned, but it will be in a load-pending state, as this is a new motion // this motion will not request an asset transfer until next update, so we have a chance to // load the keyframe data locally motionp = (LLKeyframeMotion*)mAnimPreview->getPreviewAvatar()->createMotion(mMotionID); // create data buffer for keyframe initialization S32 buffer_size = loaderp->getOutputSize(); U8* buffer = new U8[buffer_size]; LLDataPackerBinaryBuffer dp(buffer, buffer_size); // pass animation data through memory buffer loaderp->serialize(dp); dp.reset(); BOOL success = motionp && motionp->deserialize(dp); delete []buffer; if (success) { setAnimCallbacks() ; const LLBBoxLocal &pelvis_bbox = motionp->getPelvisBBox(); LLVector3 temp = pelvis_bbox.getCenter(); // only consider XY? //temp.mV[VZ] = 0.f; F32 pelvis_offset = temp.magVec(); temp = pelvis_bbox.getExtent(); //temp.mV[VZ] = 0.f; F32 pelvis_max_displacement = pelvis_offset + (temp.magVec() * 0.5f) + 1.f; F32 camera_zoom = LLViewerCamera::getInstance()->getDefaultFOV() / (2.f * atan(pelvis_max_displacement / PREVIEW_CAMERA_DISTANCE)); mAnimPreview->setZoom(camera_zoom); motionp->setName(getChild<LLUICtrl>("name_form")->getValue().asString()); mAnimPreview->getPreviewAvatar()->startMotion(mMotionID); getChild<LLSlider>("playback_slider")->setMinValue(0.0); getChild<LLSlider>("playback_slider")->setMaxValue(1.0); getChild<LLUICtrl>("loop_check")->setValue(LLSD(motionp->getLoop())); getChild<LLUICtrl>("loop_in_point")->setValue(LLSD(motionp->getLoopIn() / motionp->getDuration() * 100.f)); getChild<LLUICtrl>("loop_out_point")->setValue(LLSD(motionp->getLoopOut() / motionp->getDuration() * 100.f)); getChild<LLUICtrl>("priority")->setValue(LLSD((F32)motionp->getPriority())); getChild<LLUICtrl>("hand_pose_combo")->setValue(LLHandMotion::getHandPoseName(motionp->getHandPose())); getChild<LLUICtrl>("ease_in_time")->setValue(LLSD(motionp->getEaseInDuration())); getChild<LLUICtrl>("ease_out_time")->setValue(LLSD(motionp->getEaseOutDuration())); setEnabled(TRUE); std::string seconds_string; seconds_string = llformat(" - %.2f seconds", motionp->getDuration()); setTitle(mFilename + std::string(seconds_string)); } else { mAnimPreview = NULL; mMotionID.setNull(); getChild<LLUICtrl>("bad_animation_text")->setValue(getString("failed_to_initialize")); } } else { if ( loaderp ) { if (loaderp->getDuration() > MAX_ANIM_DURATION) { LLUIString out_str = getString("anim_too_long"); out_str.setArg("[LENGTH]", llformat("%.1f", loaderp->getDuration())); out_str.setArg("[MAX_LENGTH]", llformat("%.1f", MAX_ANIM_DURATION)); getChild<LLUICtrl>("bad_animation_text")->setValue(out_str.getString()); } else { LLUIString out_str = getString("failed_file_read"); out_str.setArg("[STATUS]", getString(STATUS[loaderp->getStatus()])); getChild<LLUICtrl>("bad_animation_text")->setValue(out_str.getString()); } } //setEnabled(FALSE); mMotionID.setNull(); mAnimPreview = NULL; } refresh(); delete loaderp; return TRUE; }
//----------------------------------------------------------------------------- // postBuild() //----------------------------------------------------------------------------- BOOL LLFloaterAnimPreview::postBuild() { LLRect r; LLKeyframeMotion* motionp = NULL; LLBVHLoader* loaderp = NULL; if (!LLFloaterNameDesc::postBuild()) { return FALSE; } childSetCommitCallback("name_form", onCommitName, this); childSetLabelArg("ok_btn", "[AMOUNT]", llformat("%d",sUploadAmount)); childSetAction("ok_btn", onBtnOK, this); setDefaultBtn(); mPreviewRect.set(PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT, getRect().getWidth() - PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); mPreviewImageRect.set(0.f, 1.f, 1.f, 0.f); S32 y = mPreviewRect.mTop + BTN_HEIGHT; S32 btn_left = PREVIEW_HPAD; r.set( btn_left, y, btn_left + 32, y - BTN_HEIGHT ); mPlayButton = getChild<LLButton>( "play_btn"); if (!mPlayButton) { mPlayButton = new LLButton(std::string("play_btn"), LLRect(0,0,0,0)); } mPlayButton->setClickedCallback(onBtnPlay); mPlayButton->setCallbackUserData(this); mPlayButton->setImages(std::string("button_anim_play.tga"), std::string("button_anim_play_selected.tga")); mPlayButton->setDisabledImages(LLStringUtil::null,LLStringUtil::null); mPlayButton->setScaleImage(TRUE); mStopButton = getChild<LLButton>( "stop_btn"); if (!mStopButton) { mStopButton = new LLButton(std::string("stop_btn"), LLRect(0,0,0,0)); } mStopButton->setClickedCallback(onBtnStop); mStopButton->setCallbackUserData(this); mStopButton->setImages(std::string("button_anim_stop.tga"), std::string("button_anim_stop_selected.tga")); mStopButton->setDisabledImages(LLStringUtil::null,LLStringUtil::null); mStopButton->setScaleImage(TRUE); r.set(r.mRight + PREVIEW_HPAD, y, getRect().getWidth() - PREVIEW_HPAD, y - BTN_HEIGHT); //childSetCommitCallback("playback_slider", onSliderMove, this); childHide("bad_animation_text"); //childSetCommitCallback("preview_base_anim", onCommitBaseAnim, this); //childSetValue("preview_base_anim", "Standing"); //childSetCommitCallback("priority", onCommitPriority, this); //childSetCommitCallback("loop_check", onCommitLoop, this); //childSetCommitCallback("loop_in_point", onCommitLoopIn, this); //childSetValidate("loop_in_point", validateLoopIn); //childSetCommitCallback("loop_out_point", onCommitLoopOut, this); //childSetValidate("loop_out_point", validateLoopOut); //childSetCommitCallback("hand_pose_combo", onCommitHandPose, this); //childSetCommitCallback("emote_combo", onCommitEmote, this); //childSetValue("emote_combo", "[None]"); //childSetCommitCallback("ease_in_time", onCommitEaseIn, this); //childSetValidate("ease_in_time", validateEaseIn); //childSetCommitCallback("ease_out_time", onCommitEaseOut, this); //childSetValidate("ease_out_time", validateEaseOut); std::string exten = gDirUtilp->getExtension(mFilename); if (exten == "bvh") { // loading a bvh file // now load bvh file S32 file_size; LLAPRFile infile ; infile.open(mFilenameAndPath, LL_APR_RB, LLAPRFile::global, &file_size); if (!infile.getFileHandle()) { llwarns << "Can't open BVH file:" << mFilename << llendl; } else { char* file_buffer; file_buffer = new char[file_size + 1]; if (file_size == infile.read(file_buffer, file_size)) { file_buffer[file_size] = '\0'; llinfos << "Loading BVH file " << mFilename << llendl; loaderp = new LLBVHLoader(file_buffer); } infile.close() ; delete[] file_buffer; } } if (loaderp && loaderp->isInitialized() && loaderp->getDuration() <= MAX_ANIM_DURATION) { // generate unique id for this motion mTransactionID.generate(); mMotionID = mTransactionID.makeAssetID(gAgent.getSecureSessionID()); mAnimPreview = new LLPreviewAnimation(256, 256); // motion will be returned, but it will be in a load-pending state, as this is a new motion // this motion will not request an asset transfer until next update, so we have a chance to // load the keyframe data locally motionp = (LLKeyframeMotion*)mAnimPreview->getDummyAvatar()->createMotion(mMotionID); // create data buffer for keyframe initialization S32 buffer_size = loaderp->getOutputSize(); U8* buffer = new U8[buffer_size]; LLDataPackerBinaryBuffer dp(buffer, buffer_size); // pass animation data through memory buffer loaderp->serialize(dp); dp.reset(); BOOL success = motionp && motionp->deserialize(dp); delete []buffer; if (success) { setAnimCallbacks() ; const LLBBoxLocal &pelvis_bbox = motionp->getPelvisBBox(); LLVector3 temp = pelvis_bbox.getCenter(); // only consider XY? //temp.mV[VZ] = 0.f; F32 pelvis_offset = temp.magVec(); temp = pelvis_bbox.getExtent(); //temp.mV[VZ] = 0.f; F32 pelvis_max_displacement = pelvis_offset + (temp.magVec() * 0.5f) + 1.f; F32 camera_zoom = LLViewerCamera::getInstance()->getDefaultFOV() / (2.f * atan(pelvis_max_displacement / PREVIEW_CAMERA_DISTANCE)); mAnimPreview->setZoom(camera_zoom); motionp->setName(childGetValue("name_form").asString()); mAnimPreview->getDummyAvatar()->startMotion(mMotionID); childSetMinValue("playback_slider", 0.0); childSetMaxValue("playback_slider", 1.0); childSetValue("loop_check", LLSD(motionp->getLoop())); childSetValue("loop_in_point", LLSD(motionp->getLoopIn() / motionp->getDuration() * 100.f)); childSetValue("loop_out_point", LLSD(motionp->getLoopOut() / motionp->getDuration() * 100.f)); childSetValue("priority", LLSD((F32)motionp->getPriority())); childSetValue("hand_pose_combo", LLHandMotion::getHandPoseName(motionp->getHandPose())); childSetValue("ease_in_time", LLSD(motionp->getEaseInDuration())); childSetValue("ease_out_time", LLSD(motionp->getEaseOutDuration())); setEnabled(TRUE); std::string seconds_string; seconds_string = llformat(" - %.2f seconds", motionp->getDuration()); setTitle(mFilename + std::string(seconds_string)); } else { delete mAnimPreview; mAnimPreview = NULL; mMotionID.setNull(); childSetValue("bad_animation_text", getString("failed_to_initialize")); } } else { if ( loaderp ) { if (loaderp->getDuration() > MAX_ANIM_DURATION) { LLUIString out_str = getString("anim_too_long"); out_str.setArg("[LENGTH]", llformat("%.1f", loaderp->getDuration())); out_str.setArg("[MAX_LENGTH]", llformat("%.1f", MAX_ANIM_DURATION)); childSetValue("bad_animation_text", out_str.getString()); } else { LLUIString out_str = getString("failed_file_read"); out_str.setArg("[STATUS]", loaderp->getStatus()); // *TODO:Translate childSetValue("bad_animation_text", out_str.getString()); } } //setEnabled(FALSE); mMotionID.setNull(); mAnimPreview = NULL; } refresh(); delete loaderp; return TRUE; }
S32 LLGlobalEconomy::calculateLightRent(const LLVector3& object_size) const { F32 intensity_mod = llmax(object_size.magVec(), 1.f); return (S32)(intensity_mod * getPriceRentLight()); }
void LLHoverView::updateText() { LLViewerObject* hit_object = getLastHoverObject(); std::string line; //<singu> if (hit_object == mLastTextHoverObject && !(mLastTextHoverObjectTimer.getStarted() && mLastTextHoverObjectTimer.hasExpired())) { // mText is already up to date. return; } mLastTextHoverObject = hit_object; mLastTextHoverObjectTimer.stop(); bool retrieving_data = false; //</singu> mText.clear(); if ( hit_object ) { if ( hit_object->isHUDAttachment() ) { // no hover tips for HUD elements, since they can obscure // what the HUD is displaying return; } if ( hit_object->isAttachment() ) { // get root of attachment then parent, which is avatar LLViewerObject* root_edit = hit_object->getRootEdit(); if (!root_edit) { // Strange parenting issue, don't show any text return; } hit_object = (LLViewerObject*)root_edit->getParent(); if (!hit_object) { // another strange parenting issue, bail out return; } } line.clear(); if (hit_object->isAvatar()) { LLNameValue* title = hit_object->getNVPair("Title"); LLNameValue* firstname = hit_object->getNVPair("FirstName"); LLNameValue* lastname = hit_object->getNVPair("LastName"); if (firstname && lastname) { // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) { line = RlvStrings::getAnonym(line.append(firstname->getString()).append(1, ' ').append(lastname->getString())); } else { // [/RLVa:KB] std::string complete_name; if (!LLAvatarNameCache::getNSName(hit_object->getID(), complete_name)) complete_name = firstname->getString() + std::string(" ") + lastname->getString(); if (title) { line.append(title->getString()); line.append(1, ' '); } line += complete_name; // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) } // [/RLVa:KB] } else { line.append(LLTrans::getString("TooltipPerson")); } mText.push_back(line); } else { // // We have hit a regular object (not an avatar or attachment) // // // Default prefs will suppress display unless the object is interactive // BOOL suppressObjectHoverDisplay = !gSavedSettings.getBOOL("ShowAllObjectHoverTip"); LLSelectNode *nodep = LLSelectMgr::getInstance()->getHoverNode(); if (nodep) { line.clear(); bool for_copy = nodep->mValid && nodep->mPermissions->getMaskEveryone() & PERM_COPY && hit_object && hit_object->permCopy(); bool for_sale = nodep->mValid && for_sale_selection(nodep); bool has_media = false; bool is_time_based_media = false; bool is_web_based_media = false; bool is_media_playing = false; bool is_media_displaying = false; // Does this face have media? const LLTextureEntry* tep = hit_object ? hit_object->getTE(mLastPickInfo.mObjectFace) : NULL; if(tep) { has_media = tep->hasMedia(); const LLMediaEntry* mep = has_media ? tep->getMediaData() : NULL; if (mep) { viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()); LLPluginClassMedia* media_plugin = NULL; if (media_impl.notNull() && (media_impl->hasMedia())) { is_media_displaying = true; //LLStringUtil::format_map_t args; media_plugin = media_impl->getMediaPlugin(); if(media_plugin) { if(media_plugin->pluginSupportsMediaTime()) { is_time_based_media = true; is_web_based_media = false; //args["[CurrentURL]"] = media_impl->getMediaURL(); is_media_playing = media_impl->isMediaPlaying(); } else { is_time_based_media = false; is_web_based_media = true; //args["[CurrentURL]"] = media_plugin->getLocation(); } //tooltip_msg.append(LLTrans::getString("CurrentURL", args)); } } } } // Avoid showing tip over media that's displaying unless it's for sale // also check the primary node since sometimes it can have an action even though // the root node doesn't if(!suppressObjectHoverDisplay || !is_media_displaying || for_sale) { if (nodep->mName.empty()) { line.append(LLTrans::getString("TooltipNoName")); } else { line.append( nodep->mName ); } mText.push_back(line); if (!nodep->mDescription.empty() && nodep->mDescription != DEFAULT_DESC) { mText.push_back( nodep->mDescription ); } // Line: "Owner: James Linden" line.clear(); line.append(LLTrans::getString("TooltipOwner") + " "); if (nodep->mValid) { LLUUID owner; std::string name; if (!nodep->mPermissions->isGroupOwned()) { owner = nodep->mPermissions->getOwner(); if (LLUUID::null == owner) { line.append(LLTrans::getString("TooltipPublic")); } else if (LLAvatarNameCache::getNSName(owner, name)) { // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) { name = RlvStrings::getAnonym(name); } // [/RLVa:KB] line.append(name); } else { line.append(LLTrans::getString("RetrievingData")); retrieving_data = true; } } else { std::string name; owner = nodep->mPermissions->getGroup(); if (gCacheName->getGroupName(owner, name)) { line.append(name); line.append(LLTrans::getString("TooltipIsGroup")); } else { line.append(LLTrans::getString("RetrievingData")); retrieving_data = true; } } } else { line.append(LLTrans::getString("RetrievingData")); retrieving_data = true; } mText.push_back(line); // Build a line describing any special properties of this object. LLViewerObject *object = hit_object; LLViewerObject *parent = (LLViewerObject *)object->getParent(); if (object && (object->flagUsePhysics() || object->flagScripted() || object->flagHandleTouch() || (parent && parent->flagHandleTouch()) || object->flagTakesMoney() || (parent && parent->flagTakesMoney()) || object->flagAllowInventoryAdd() || object->flagTemporary() || object->flagPhantom()) ) { line.clear(); if (object->flagScripted()) { line.append(LLTrans::getString("TooltipFlagScript") + " "); } if (object->flagUsePhysics()) { line.append(LLTrans::getString("TooltipFlagPhysics") + " "); } if (object->flagHandleTouch() || (parent && parent->flagHandleTouch()) ) { line.append(LLTrans::getString("TooltipFlagTouch") + " "); suppressObjectHoverDisplay = FALSE; // Show tip } if (object->flagTakesMoney() || (parent && parent->flagTakesMoney()) ) { line.append(gHippoGridManager->getConnectedGrid()->getCurrencySymbol() + " "); suppressObjectHoverDisplay = FALSE; // Show tip } if (object->flagAllowInventoryAdd()) { line.append(LLTrans::getString("TooltipFlagDropInventory") + " "); suppressObjectHoverDisplay = FALSE; // Show tip } if (object->flagPhantom()) { line.append(LLTrans::getString("TooltipFlagPhantom") + " "); } if (object->flagTemporary()) { line.append(LLTrans::getString("TooltipFlagTemporary") + " "); } if (object->flagUsePhysics() || object->flagHandleTouch() || (parent && parent->flagHandleTouch()) ) { line.append(LLTrans::getString("TooltipFlagRightClickMenu") + " "); } mText.push_back(line); } // Free to copy / For Sale: L$ line.clear(); if (nodep->mValid) { if (for_copy) { line.append(LLTrans::getString("TooltipFreeToCopy")); suppressObjectHoverDisplay = FALSE; // Show tip } else if (for_sale) { LLStringUtil::format_map_t args; args["[AMOUNT]"] = llformat("%d", nodep->mSaleInfo.getSalePrice()); line.append(LLTrans::getString("TooltipForSaleL$", args)); suppressObjectHoverDisplay = FALSE; // Show tip } else { // Nothing if not for sale // line.append("Not for sale"); } } else { LLStringUtil::format_map_t args; args["[MESSAGE]"] = LLTrans::getString("RetrievingData"); retrieving_data = true; line.append(LLTrans::getString("TooltipForSaleMsg", args)); } mText.push_back(line); line.clear(); S32 prim_count = LLSelectMgr::getInstance()->getHoverObjects()->getObjectCount(); line.append(llformat("Prims: %d", prim_count)); mText.push_back(line); line.clear(); line.append("Position: "); LLViewerRegion *region = gAgent.getRegion(); LLVector3 position = region->getPosRegionFromGlobal(hit_object->getPositionGlobal());//regionp->getOriginAgent(); LLVector3 mypos = region->getPosRegionFromGlobal(gAgent.getPositionGlobal()); LLVector3 delta = position - mypos; F32 distance = (F32)delta.magVec(); line.append(llformat("<%.02f,%.02f,%.02f>",position.mV[0],position.mV[1],position.mV[2])); mText.push_back(line); line.clear(); line.append(llformat("Distance: %.02fm",distance)); mText.push_back(line); } else { suppressObjectHoverDisplay = TRUE; } // If the hover tip shouldn't be shown, delete all the object text if (suppressObjectHoverDisplay) { mText.clear(); } } } } else if ( mHoverLandGlobal != LLVector3d::zero ) { // // Do not show hover for land unless prefs are set to allow it. // if (!gSavedSettings.getBOOL("ShowLandHoverTip")) return; // Didn't hit an object, but since we have a land point we // must be hovering over land. LLParcel* hover_parcel = LLViewerParcelMgr::getInstance()->getHoverParcel(); LLUUID owner; if ( hover_parcel ) { owner = hover_parcel->getOwnerID(); } // Line: "Land" line.clear(); line.append(LLTrans::getString("TooltipLand")); if (hover_parcel) { // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | Added: RLVa-0.2.0b line.append( (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ? hover_parcel->getName() : RlvStrings::getString(RLV_STRING_HIDDEN_PARCEL) ); // [/RLVa:KB] //line.append(hover_parcel->getName()); } mText.push_back(line); // Line: "Owner: James Linden" line.clear(); line.append(LLTrans::getString("TooltipOwner") + " "); if ( hover_parcel ) { std::string name; if (LLUUID::null == owner) { line.append(LLTrans::getString("TooltipPublic")); } else if (hover_parcel->getIsGroupOwned()) { if (gCacheName->getGroupName(owner, name)) { line.append(name); line.append(LLTrans::getString("TooltipIsGroup")); } else { line.append(LLTrans::getString("RetrievingData")); retrieving_data = true; } } else if(gCacheName->getFullName(owner, name)) { // [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.0b line.append( (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) ? name : RlvStrings::getAnonym(name)); // [/RLVa:KB] //line.append(name); } else { line.append(LLTrans::getString("RetrievingData")); retrieving_data = true; } } else { line.append(LLTrans::getString("RetrievingData")); retrieving_data = true; } mText.push_back(line); // Line: "no fly, not safe, no build" // Don't display properties for your land. This is just // confusing, because you can do anything on your own land. if ( hover_parcel && owner != gAgent.getID() ) { S32 words = 0; line.clear(); // JC - Keep this in the same order as the checkboxes // on the land info panel if ( !hover_parcel->getAllowModify() ) { if ( hover_parcel->getAllowGroupModify() ) { line.append(LLTrans::getString("TooltipFlagGroupBuild")); } else { line.append(LLTrans::getString("TooltipFlagNoBuild")); } words++; } if ( !hover_parcel->getAllowTerraform() ) { if (words) line.append(", "); line.append(LLTrans::getString("TooltipFlagNoEdit")); words++; } if ( hover_parcel->getAllowDamage() ) { if (words) line.append(", "); line.append(LLTrans::getString("TooltipFlagNotSafe")); words++; } // Maybe we should reflect the estate's block fly bit here as well? DK 12/1/04 if ( !hover_parcel->getAllowFly() ) { if (words) line.append(", "); line.append(LLTrans::getString("TooltipFlagNoFly")); words++; } if ( !hover_parcel->getAllowOtherScripts() ) { if (words) line.append(", "); if ( hover_parcel->getAllowGroupScripts() ) { line.append(LLTrans::getString("TooltipFlagGroupScripts")); } else { line.append(LLTrans::getString("TooltipFlagNoScripts")); } words++; } if (words) { mText.push_back(line); } } if (hover_parcel && hover_parcel->getParcelFlag(PF_FOR_SALE)) { LLStringUtil::format_map_t args; args["[AMOUNT]"] = llformat("%d", hover_parcel->getSalePrice()); line = LLTrans::getString("TooltipForSaleL$", args); mText.push_back(line); } } //<singu> if (retrieving_data) { // Keep doing this twice per second, until all data was retrieved. mLastTextHoverObjectTimer.start(DELAY_BEFORE_REFRESH_TIP); } //</singu> }
//--------------------------------------------------------------------------------------------------------- void LLFollowCam::update() { //#################################################################################### // update Focus //#################################################################################### LLVector3 offsetSubjectPosition = mSubjectPosition + (mFocusOffset * mSubjectRotation); LLVector3 simulated_pos_agent = gAgent.getPosAgentFromGlobal(mSimulatedPositionGlobal); LLVector3 vectorFromCameraToSubject = offsetSubjectPosition - simulated_pos_agent; F32 distanceFromCameraToSubject = vectorFromCameraToSubject.magVec(); LLVector3 whereFocusWantsToBe = mFocus; LLVector3 focus_pt_agent = gAgent.getPosAgentFromGlobal(mSimulatedFocusGlobal); if ( mFocusLocked ) // if focus is locked, only relative focus needs to be updated { mRelativeFocus = (focus_pt_agent - mSubjectPosition) * ~mSubjectRotation; } else { LLVector3 focusOffset = offsetSubjectPosition - focus_pt_agent; F32 focusOffsetDistance = focusOffset.magVec(); LLVector3 focusOffsetDirection = focusOffset / focusOffsetDistance; whereFocusWantsToBe = focus_pt_agent + (focusOffsetDirection * (focusOffsetDistance - mFocusThreshold)); if ( focusOffsetDistance > mFocusThreshold ) { // this version normalizes focus threshold by distance // so that the effect is not changed with distance /* F32 focusThresholdNormalizedByDistance = distanceFromCameraToSubject * mFocusThreshold; if ( focusOffsetDistance > focusThresholdNormalizedByDistance ) { LLVector3 focusOffsetDirection = focusOffset / focusOffsetDistance; F32 force = focusOffsetDistance - focusThresholdNormalizedByDistance; */ F32 focusLagLerp = LLCriticalDamp::getInterpolant( mFocusLag ); focus_pt_agent = lerp( focus_pt_agent, whereFocusWantsToBe, focusLagLerp ); mSimulatedFocusGlobal = gAgent.getPosGlobalFromAgent(focus_pt_agent); } mRelativeFocus = lerp(mRelativeFocus, (focus_pt_agent - mSubjectPosition) * ~mSubjectRotation, LLCriticalDamp::getInterpolant(0.05f)); }// if focus is not locked --------------------------------------------- LLVector3 whereCameraPositionWantsToBe = gAgent.getPosAgentFromGlobal(mSimulatedPositionGlobal); if ( mPositionLocked ) { mRelativePos = (whereCameraPositionWantsToBe - mSubjectPosition) * ~mSubjectRotation; } else { //#################################################################################### // update Position //#################################################################################### //------------------------------------------------------------------------- // I determine the horizontal vector from the camera to the subject //------------------------------------------------------------------------- LLVector3 horizontalVectorFromCameraToSubject = vectorFromCameraToSubject; horizontalVectorFromCameraToSubject.mV[VZ] = 0.0f; //--------------------------------------------------------- // Now I determine the horizontal distance //--------------------------------------------------------- F32 horizontalDistanceFromCameraToSubject = horizontalVectorFromCameraToSubject.magVec(); //--------------------------------------------------------- // Then I get the (normalized) horizontal direction... //--------------------------------------------------------- LLVector3 horizontalDirectionFromCameraToSubject; if ( horizontalDistanceFromCameraToSubject < DISTANCE_EPSILON ) { // make sure we still have a normalized vector if distance is really small // (this case is rare and fleeting) horizontalDirectionFromCameraToSubject = LLVector3::z_axis; } else { // I'm not using the "normalize" method, because I can just divide by horizontalDistanceFromCameraToSubject horizontalDirectionFromCameraToSubject = horizontalVectorFromCameraToSubject / horizontalDistanceFromCameraToSubject; } //------------------------------------------------------------------------------------------------------------ // Here is where I determine an offset relative to subject position in oder to set the ideal position. //------------------------------------------------------------------------------------------------------------ if ( mPitchSineAndCosineNeedToBeUpdated ) { calculatePitchSineAndCosine(); mPitchSineAndCosineNeedToBeUpdated = false; } LLVector3 positionOffsetFromSubject; positionOffsetFromSubject.setVec ( horizontalDirectionFromCameraToSubject.mV[ VX ] * mPitchCos, horizontalDirectionFromCameraToSubject.mV[ VY ] * mPitchCos, -mPitchSin ); positionOffsetFromSubject *= mSimulatedDistance; //---------------------------------------------------------------------- // Finally, ideal position is set by taking the subject position and // extending the positionOffsetFromSubject from that //---------------------------------------------------------------------- LLVector3 idealCameraPosition = offsetSubjectPosition - positionOffsetFromSubject; //-------------------------------------------------------------------------------- // Now I prepare to move the current camera position towards its ideal position... //-------------------------------------------------------------------------------- LLVector3 vectorFromPositionToIdealPosition = idealCameraPosition - simulated_pos_agent; F32 distanceFromPositionToIdealPosition = vectorFromPositionToIdealPosition.magVec(); //put this inside of the block? LLVector3 normalFromPositionToIdealPosition = vectorFromPositionToIdealPosition / distanceFromPositionToIdealPosition; whereCameraPositionWantsToBe = simulated_pos_agent + (normalFromPositionToIdealPosition * (distanceFromPositionToIdealPosition - mPositionThreshold)); //------------------------------------------------------------------------------------------------- // The following method takes the target camera position and resets it so that it stays "behind" the subject, // using behindness angle and behindness force as parameters affecting the exact behavior //------------------------------------------------------------------------------------------------- if ( distanceFromPositionToIdealPosition > mPositionThreshold ) { F32 positionPullLerp = LLCriticalDamp::getInterpolant( mPositionLag ); simulated_pos_agent = lerp( simulated_pos_agent, whereCameraPositionWantsToBe, positionPullLerp ); } //-------------------------------------------------------------------- // don't let the camera get farther than its official max distance //-------------------------------------------------------------------- if ( distanceFromCameraToSubject > mMaxCameraDistantFromSubject ) { LLVector3 directionFromCameraToSubject = vectorFromCameraToSubject / distanceFromCameraToSubject; simulated_pos_agent = offsetSubjectPosition - directionFromCameraToSubject * mMaxCameraDistantFromSubject; } ////------------------------------------------------------------------------------------------------- //// The following method takes mSimulatedPositionGlobal and resets it so that it stays "behind" the subject, //// using behindness angle and behindness force as parameters affecting the exact behavior ////------------------------------------------------------------------------------------------------- updateBehindnessConstraint(gAgent.getPosAgentFromGlobal(mSimulatedFocusGlobal), simulated_pos_agent); mSimulatedPositionGlobal = gAgent.getPosGlobalFromAgent(simulated_pos_agent); mRelativePos = lerp(mRelativePos, (simulated_pos_agent - mSubjectPosition) * ~mSubjectRotation, LLCriticalDamp::getInterpolant(0.05f)); } // if position is not locked ----------------------------------------------------------- //#################################################################################### // update UpVector //#################################################################################### // this just points upward for now, but I anticipate future effects requiring // some rolling ("banking" effects for fun, swoopy vehicles, etc.) mUpVector = LLVector3::z_axis; }