Exemple #1
0
// return height of a sphere of given radius, located at center, in pixels
F32 LLCamera::heightInPixels(const LLVector3 &center, 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;
	}
}
Exemple #2
0
// 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();
	}
}
Exemple #4
0
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();
}
Exemple #5
0
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;
}
Exemple #7
0
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);
} 
Exemple #10
0
// 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;
}
Exemple #11
0
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 );
}
Exemple #13
0
//-----------------------------------------------------------------------------
// 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;
}
Exemple #15
0
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>
}
Exemple #17
0
//---------------------------------------------------------------------------------------------------------
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;
}