Пример #1
0
double nlerp(int n, double *xin, double *f) {
    if (n == 1)
        return (1.0 - xin[0]) * f[0] + xin[0] * f[1];
    else
        return (1.0 - xin[0]) * nlerp(n - 1, xin+1, f) +
            xin[0] * nlerp(n - 1, xin+1, f + (1LL << (n - 1)));
}
Пример #2
0
float Perlin::noise( float x, float y ) const
{
	int32_t X = ((int32_t)floorf(x)) & 255, Y = ((int32_t)floorf(y)) & 255;
	x -= floorf(x); y -= floorf(y);
	float	u = fade( x ), v = fade( y );
	int32_t A = mPerms[X  ]+Y, AA = mPerms[A], AB = mPerms[A+1],
	B = mPerms[X+1]+Y, BA = mPerms[B], BB = mPerms[B+1];

	return nlerp(v, nlerp(u, grad(mPerms[AA  ], x  , y   ),
							 grad(mPerms[BA  ], x-1, y   )),
					 nlerp(u, grad(mPerms[AB  ], x  , y-1   ),
							 grad(mPerms[BB  ], x-1, y-1   )));
}
Пример #3
0
/////////////////////////////////////////////////////////////////////////////////////////////////
// noise
float Perlin::noise( float x ) const
{
	int32_t X = ((int32_t)floorf(x)) & 255;
	x -= floorf(x);
	float u = fade( x );
	int32_t A = mPerms[X], AA = mPerms[A], B = mPerms[X+1], BA = mPerms[B];

	return nlerp( u, grad( mPerms[AA  ], x ), grad( mPerms[BA], x-1 ) );
}
Пример #4
0
//-----------------------------------------------------------------------------
// LLTargetingMotion::onUpdate()
//-----------------------------------------------------------------------------
BOOL LLTargetingMotion::onUpdate(F32 time, U8* joint_mask)
{
	F32 slerp_amt = LLCriticalDamp::getInterpolant(TORSO_TARGET_HALF_LIFE);

	LLVector3 target;
	LLVector3* lookAtPoint = (LLVector3*)mCharacter->getAnimationData("LookAtPoint");

	BOOL result = TRUE;

	if (!lookAtPoint)
	{
		return TRUE;
	}
	else
	{
		target = *lookAtPoint;
		target.normVec();
	}
	
	//LLVector3 target_plane_normal = LLVector3(1.f, 0.f, 0.f) * mPelvisJoint->getWorldRotation();
	//LLVector3 torso_dir = LLVector3(1.f, 0.f, 0.f) * (mTorsoJoint->getWorldRotation() * mTorsoState->getRotation());

	LLVector3 skyward(0.f, 0.f, 1.f);
	LLVector3 left(skyward % target);
	left.normVec();
	LLVector3 up(target % left);
	up.normVec();
	LLQuaternion target_aim_rot(target, left, up);

	LLQuaternion cur_torso_rot = mTorsoJoint->getWorldRotation();

	LLVector3 right_hand_at = LLVector3(0.f, -1.f, 0.f) * mRightHandJoint->getWorldRotation();
	left.setVec(skyward % right_hand_at);
	left.normVec();
	up.setVec(right_hand_at % left);
	up.normVec();
	LLQuaternion right_hand_rot(right_hand_at, left, up);

	LLQuaternion new_torso_rot = (cur_torso_rot * ~right_hand_rot) * target_aim_rot;

	// find ideal additive rotation to make torso point in correct direction
	new_torso_rot = new_torso_rot * ~cur_torso_rot;

	// slerp from current additive rotation to ideal additive rotation
	new_torso_rot = nlerp(slerp_amt, mTorsoState->getRotation(), new_torso_rot);

	// constraint overall torso rotation
	LLQuaternion total_rot = new_torso_rot * mTorsoJoint->getRotation();
	total_rot.constrain(F_PI_BY_TWO * 0.8f);
	new_torso_rot = total_rot * ~mTorsoJoint->getRotation();

	mTorsoState->setRotation(new_torso_rot);

	return result;
}
Пример #5
0
//-----------------------------------------------------------------------------
// interpolate()
//-----------------------------------------------------------------------------
void LLJointStateBlender::interpolate(F32 u)
{
	// only interpolate if we have a joint state
	if (!mJointStates[0])
	{
		return;
	}
	LLJoint* target_joint = mJointStates[0]->getJoint();

	if (!target_joint)
	{
		return;
	}

	target_joint->setPosition(lerp(target_joint->getPosition(), mJointCache.getPosition(), u));
	target_joint->setScale(lerp(target_joint->getScale(), mJointCache.getScale(), u));
	target_joint->setRotation(nlerp(u, target_joint->getRotation(), mJointCache.getRotation()));
}
Пример #6
0
void Animation::getPose(float time, Pose& pose, Model& model) const
{
	PROFILE_FUNCTION();
	if(model.isReady())
	{
		int frame = (int)(time * m_fps);
		frame = frame >= m_frame_count ? m_frame_count - 1 : frame;
		Vec3* pos = pose.getPositions();
		Quat* rot = pose.getRotations();
		int off = frame * m_bone_count;
		int off2 = off + m_bone_count;
		float t = (time - frame / (float)m_fps) / (1.0f / m_fps);
	
		if(frame < m_frame_count - 1)
		{
			for(int i = 0; i < m_bone_count; ++i)
			{
				Model::BoneMap::iterator iter = model.getBoneIndex(m_bones[i]);
				if (iter.isValid())
				{
					int model_bone_index = iter.value();
					lerp(m_positions[off + i], m_positions[off2 + i], &pos[model_bone_index], t);
					nlerp(m_rotations[off + i], m_rotations[off2 + i], &rot[model_bone_index], t);
				}
			}
		}
		else
		{
			for(int i = 0; i < m_bone_count; ++i)
			{
				Model::BoneMap::iterator iter = model.getBoneIndex(m_bones[i]);
				if (iter.isValid())
				{
					int model_bone_index = iter.value();
					pos[model_bone_index] = m_positions[off + i];
					rot[model_bone_index] = m_rotations[off + i];
				}
			}
		}
		pose.setIsRelative();
		pose.computeAbsolute(model);
	}
}
Пример #7
0
void LLAgentPilot::moveCamera()
{
	if (!getOverrideCamera())
		return;

	if (mCurrentAction<mActions.count())
	{
		S32 start_index = llmax(mCurrentAction-1,0);
		S32 end_index = mCurrentAction;
		F32 t = 0.0;
		F32 timedelta = mActions[end_index].mTime - mActions[start_index].mTime;
		F32 tickelapsed = mTimer.getElapsedTimeF32()-mActions[start_index].mTime;
		if (timedelta > 0.0)
		{
			t = tickelapsed/timedelta;
		}

		if ((t<0.0)||(t>1.0))
		{
			llwarns << "mCurrentAction is invalid, t = " << t << llendl;
			return;
		}
		
		Action& start = mActions[start_index];
		Action& end = mActions[end_index];

		F32 view = lerp(start.mCameraView, end.mCameraView, t);
		LLVector3 origin = lerp(start.mCameraOrigin, end.mCameraOrigin, t);
		LLQuaternion start_quat(start.mCameraXAxis, start.mCameraYAxis, start.mCameraZAxis);
		LLQuaternion end_quat(end.mCameraXAxis, end.mCameraYAxis, end.mCameraZAxis);
		LLQuaternion quat = nlerp(t, start_quat, end_quat);
		LLMatrix3 mat(quat);
	
		LLViewerCamera::getInstance()->setView(view);
		LLViewerCamera::getInstance()->setOrigin(origin);
		LLViewerCamera::getInstance()->mXAxis = LLVector3(mat.mMatrix[0]);
		LLViewerCamera::getInstance()->mYAxis = LLVector3(mat.mMatrix[1]);
		LLViewerCamera::getInstance()->mZAxis = LLVector3(mat.mMatrix[2]);
	}
}
Пример #8
0
float Perlin::noise( float x, float y, float z ) const
{
	// These floors need to remain that due to behavior with negatives.
	int32_t X = ((int32_t)floorf(x)) & 255, Y = ((int32_t)floorf(y)) & 255, Z = ((int32_t)floorf(z)) & 255;
	x -= floorf(x); y -= floorf(y); z -= floorf(z);
	float	u = fade(x), v = fade(y), w = fade(z);
	int32_t A = mPerms[X  ]+Y, AA = mPerms[A]+Z, AB = mPerms[A+1]+Z,
	B = mPerms[X+1]+Y, BA = mPerms[B]+Z, BB = mPerms[B+1]+Z;

	float a = grad(mPerms[AA  ], x  , y  , z   );
	float b = grad(mPerms[BA  ], x-1, y  , z   );
	float c = grad(mPerms[AB  ], x  , y-1, z   );
	float d = grad(mPerms[BB  ], x-1, y-1, z   );
	float e = grad(mPerms[AA+1], x  , y  , z-1 );
	float f = grad(mPerms[BA+1], x-1, y  , z-1 );
	float g = grad(mPerms[AB+1], x  , y-1, z-1 );
	float h = grad(mPerms[BB+1], x-1, y-1, z-1 );

	return	nlerp(w, nlerp( v, nlerp( u, a, b ),
							 nlerp( u, c, d ) ),
					nlerp(v, nlerp( u, e, f ),
							 nlerp( u, g, h ) ) );	
}
Пример #9
0
// -----------------------------------------------------------------------------
void LLViewerJoystick::moveFlycam(bool reset)
{
	static LLQuaternion 		sFlycamRotation;
	static LLVector3    		sFlycamPosition;
	static F32          		sFlycamZoom;
	
	if (!gFocusMgr.getAppHasFocus() || mDriverState != JDS_INITIALIZED
		|| !gSavedSettings.getBOOL("JoystickEnabled") || !gSavedSettings.getBOOL("JoystickFlycamEnabled"))
	{
		return;
	}

	S32 axis[] = 
	{
		gSavedSettings.getS32("JoystickAxis0"),
		gSavedSettings.getS32("JoystickAxis1"),
		gSavedSettings.getS32("JoystickAxis2"),
		gSavedSettings.getS32("JoystickAxis3"),
		gSavedSettings.getS32("JoystickAxis4"),
		gSavedSettings.getS32("JoystickAxis5"),
		gSavedSettings.getS32("JoystickAxis6")
	};

	bool in_build_mode = LLToolMgr::getInstance()->inBuildMode();
	if (reset || mResetFlag)
	{
		sFlycamPosition = LLViewerCamera::getInstance()->getOrigin();
		sFlycamRotation = LLViewerCamera::getInstance()->getQuaternion();
		sFlycamZoom = LLViewerCamera::getInstance()->getView();
		
		resetDeltas(axis);

		return;
	}

	F32 axis_scale[] =
	{
		gSavedSettings.getF32("FlycamAxisScale0"),
		gSavedSettings.getF32("FlycamAxisScale1"),
		gSavedSettings.getF32("FlycamAxisScale2"),
		gSavedSettings.getF32("FlycamAxisScale3"),
		gSavedSettings.getF32("FlycamAxisScale4"),
		gSavedSettings.getF32("FlycamAxisScale5"),
		gSavedSettings.getF32("FlycamAxisScale6")
	};

	F32 dead_zone[] =
	{
		gSavedSettings.getF32("FlycamAxisDeadZone0"),
		gSavedSettings.getF32("FlycamAxisDeadZone1"),
		gSavedSettings.getF32("FlycamAxisDeadZone2"),
		gSavedSettings.getF32("FlycamAxisDeadZone3"),
		gSavedSettings.getF32("FlycamAxisDeadZone4"),
		gSavedSettings.getF32("FlycamAxisDeadZone5"),
		gSavedSettings.getF32("FlycamAxisDeadZone6")
	};

	F32 time = gFrameIntervalSeconds;

	// avoid making ridiculously big movements if there's a big drop in fps 
	if (time > .2f)
	{
		time = .2f;
	}

	F32 cur_delta[7];
	F32 feather = gSavedSettings.getF32("FlycamFeathering");
	bool absolute = gSavedSettings.getBOOL("Cursor3D");
	bool is_zero = true;

	for (U32 i = 0; i < 7; i++)
	{
		cur_delta[i] = -getJoystickAxis(axis[i]);


		F32 tmp = cur_delta[i];
		if (absolute)
		{
			cur_delta[i] = cur_delta[i] - sLastDelta[i];
		}
		sLastDelta[i] = tmp;

		if (cur_delta[i] > 0)
		{
			cur_delta[i] = llmax(cur_delta[i]-dead_zone[i], 0.f);
		}
		else
		{
			cur_delta[i] = llmin(cur_delta[i]+dead_zone[i], 0.f);
		}

		// we need smaller camera movements in build mode
		// NOTE: this needs to remain after the deadzone calculation, otherwise
		// we have issues with flycam "jumping" when the build dialog is opened/closed  -Nyx
		if (in_build_mode)
		{
			if (i == X_I || i == Y_I || i == Z_I)
			{
				cur_delta[i] /= BUILDMODE_FLYCAM_T_SCALE;
			}
		}

		cur_delta[i] *= axis_scale[i];
		
		if (!absolute)
		{
			cur_delta[i] *= time;
		}

		sDelta[i] = sDelta[i] + (cur_delta[i]-sDelta[i])*time*feather;

		is_zero = is_zero && (cur_delta[i] == 0.f);

	}
	
	// Clear AFK state if moved beyond the deadzone
	if (!is_zero && gAwayTimer.getElapsedTimeF32() > MIN_AFK_TIME)
	{
		gAgent.clearAFK();
	}
	
	sFlycamPosition += LLVector3(sDelta) * sFlycamRotation;

	LLMatrix3 rot_mat(sDelta[3], sDelta[4], sDelta[5]);
	sFlycamRotation = LLQuaternion(rot_mat)*sFlycamRotation;

	if (gSavedSettings.getBOOL("AutoLeveling"))
	{
		LLMatrix3 level(sFlycamRotation);

		LLVector3 x = LLVector3(level.mMatrix[0]);
		LLVector3 y = LLVector3(level.mMatrix[1]);
		LLVector3 z = LLVector3(level.mMatrix[2]);

		y.mV[2] = 0.f;
		y.normVec();

		level.setRows(x,y,z);
		level.orthogonalize();
				
		LLQuaternion quat(level);
		sFlycamRotation = nlerp(llmin(feather*time,1.f), sFlycamRotation, quat);
	}

	if (gSavedSettings.getBOOL("ZoomDirect"))
	{
		sFlycamZoom = sLastDelta[6]*axis_scale[6]+dead_zone[6];
	}
	else
	{
		sFlycamZoom += sDelta[6];
	}

	LLMatrix3 mat(sFlycamRotation);

	LLViewerCamera::getInstance()->setView(sFlycamZoom);
	LLViewerCamera::getInstance()->setOrigin(sFlycamPosition);
	LLViewerCamera::getInstance()->mXAxis = LLVector3(mat.mMatrix[0]);
	LLViewerCamera::getInstance()->mYAxis = LLVector3(mat.mMatrix[1]);
	LLViewerCamera::getInstance()->mZAxis = LLVector3(mat.mMatrix[2]);
}
Пример #10
0
// Returns "distance" between target destination and resulting xfrom
F32 LLDrawable::updateXform(BOOL undamped)
{
	BOOL damped = !undamped;

	// Position
	LLVector3 old_pos(mXform.getPosition());
	LLVector3 target_pos;
	if (mXform.isRoot())
	{
		// get root position in your agent's region
		target_pos = mVObjp->getPositionAgent();
	}
	else
	{
		// parent-relative position
		target_pos = mVObjp->getPosition();
	}
	
	// Rotation
	LLQuaternion old_rot(mXform.getRotation());
	LLQuaternion target_rot = mVObjp->getRotation();
	//scaling
	LLVector3 target_scale = mVObjp->getScale();
	LLVector3 old_scale = mCurrentScale;
	LLVector3 dest_scale = target_scale;
	
	// Damping
	F32 dist_squared = 0.f;
	F32 camdist2 = (mDistanceWRTCamera * mDistanceWRTCamera);

	if (damped && isVisible())
	{
		F32 lerp_amt = llclamp(LLCriticalDamp::getInterpolant(OBJECT_DAMPING_TIME_CONSTANT), 0.f, 1.f);
		LLVector3 new_pos = lerp(old_pos, target_pos, lerp_amt);
		dist_squared = dist_vec_squared(new_pos, target_pos);

		LLQuaternion new_rot = nlerp(lerp_amt, old_rot, target_rot);
		dist_squared += (1.f - dot(new_rot, target_rot)) * 10.f;

		LLVector3 new_scale = lerp(old_scale, target_scale, lerp_amt);
		dist_squared += dist_vec_squared(new_scale, target_scale);

		if ((dist_squared >= MIN_INTERPOLATE_DISTANCE_SQUARED * camdist2) &&
			(dist_squared <= MAX_INTERPOLATE_DISTANCE_SQUARED))
		{
			// interpolate
			target_pos = new_pos;
			target_rot = new_rot;
			target_scale = new_scale;
		}
		else
		{
			// snap to final position
			dist_squared = 0.0f;
			if (getVOVolume() && !isRoot())
			{ //child prim snapping to some position, needs a rebuild
				gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE);
			}
		}
	}

	if ((mCurrentScale != target_scale) ||
		(!isRoot() && 
		 (dist_squared >= MIN_INTERPOLATE_DISTANCE_SQUARED || 
		 !mVObjp->getAngularVelocity().isExactlyZero() ||
		 target_pos != mXform.getPosition() ||
		 target_rot != mXform.getRotation())))
	{ //child prim moving or scale change requires immediate rebuild
		gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE);
	}
	else if (!getVOVolume() && !isAvatar())
	{
		movePartition();
	}

	// Update
	mXform.setPosition(target_pos);
	mXform.setRotation(target_rot);
	mXform.setScale(LLVector3(1,1,1)); //no scale in drawable transforms (IT'S A RULE!)
	mXform.updateMatrix();
	
	mCurrentScale = target_scale;
	
	if (mSpatialBridge)
	{
		gPipeline.markMoved(mSpatialBridge, FALSE);
	}
	return dist_squared;
}
Пример #11
0
//-----------------------------------------------------------------------------
// blendJointStates()
//-----------------------------------------------------------------------------
void LLJointStateBlender::blendJointStates(BOOL apply_now)
{
	// we need at least one joint to blend
	// if there is one, it will be in slot zero according to insertion logic
	// instead of resetting joint state to default, just leave it unchanged from last frame
	if (mJointStates[0].isNull())
	{
		return;
	}

	LLJoint* target_joint = apply_now ? mJointStates[0]->getJoint() : &mJointCache;

	const S32 POS_WEIGHT = 0;
	const S32 ROT_WEIGHT = 1;
	const S32 SCALE_WEIGHT = 2;

	F32				sum_weights[3];
	U32				sum_usage = 0;

	LLVector3		blended_pos = target_joint->getPosition();
	LLQuaternion	blended_rot = target_joint->getRotation();
	LLVector3		blended_scale = target_joint->getScale();

	LLVector3		added_pos;
	LLQuaternion	added_rot;
	LLVector3		added_scale;

	//S32				joint_state_index;

	sum_weights[POS_WEIGHT] = 0.f;
	sum_weights[ROT_WEIGHT] = 0.f;
	sum_weights[SCALE_WEIGHT] = 0.f;

	for(S32 joint_state_index = 0; 
		joint_state_index < JSB_NUM_JOINT_STATES && mJointStates[joint_state_index].notNull();
		joint_state_index++)
	{
		LLJointState* jsp = mJointStates[joint_state_index];
		U32 current_usage = jsp->getUsage();
		F32 current_weight = jsp->getWeight();

		if (current_weight == 0.f)
		{
			continue;
		}

		if (mAdditiveBlends[joint_state_index])
		{
			if(current_usage & LLJointState::POS)
			{
				F32 new_weight_sum = llmin(1.f, current_weight + sum_weights[POS_WEIGHT]);

				// add in pos for this jointstate modulated by weight
				added_pos += jsp->getPosition() * (new_weight_sum - sum_weights[POS_WEIGHT]);
			}

			if(current_usage & LLJointState::SCALE)
			{
				F32 new_weight_sum = llmin(1.f, current_weight + sum_weights[SCALE_WEIGHT]);

				// add in scale for this jointstate modulated by weight
				added_scale += jsp->getScale() * (new_weight_sum - sum_weights[SCALE_WEIGHT]);
			}

			if (current_usage & LLJointState::ROT)
			{
				F32 new_weight_sum = llmin(1.f, current_weight + sum_weights[ROT_WEIGHT]);

				// add in rotation for this jointstate modulated by weight
				added_rot = nlerp((new_weight_sum - sum_weights[ROT_WEIGHT]), added_rot, jsp->getRotation()) * added_rot;
			}
		}
		else
		{
			// blend two jointstates together
		
			// blend position
			if(current_usage & LLJointState::POS)
			{
				if(sum_usage & LLJointState::POS)
				{
					F32 new_weight_sum = llmin(1.f, current_weight + sum_weights[POS_WEIGHT]);

					// blend positions from both
					blended_pos = lerp(jsp->getPosition(), blended_pos, sum_weights[POS_WEIGHT] / new_weight_sum);
					sum_weights[POS_WEIGHT] = new_weight_sum;
				} 
				else
				{
					// copy position from current
					blended_pos = jsp->getPosition();
					sum_weights[POS_WEIGHT] = current_weight;
				}
			}
			
			// now do scale
			if(current_usage & LLJointState::SCALE)
			{
				if(sum_usage & LLJointState::SCALE)
				{
					F32 new_weight_sum = llmin(1.f, current_weight + sum_weights[SCALE_WEIGHT]);

					// blend scales from both
					blended_scale = lerp(jsp->getScale(), blended_scale, sum_weights[SCALE_WEIGHT] / new_weight_sum);
					sum_weights[SCALE_WEIGHT] = new_weight_sum;
				} 
				else
				{
					// copy scale from current
					blended_scale = jsp->getScale();
					sum_weights[SCALE_WEIGHT] = current_weight;
				}
			}

			// rotation
			if (current_usage & LLJointState::ROT)
			{
				if(sum_usage & LLJointState::ROT)
				{
					F32 new_weight_sum = llmin(1.f, current_weight + sum_weights[ROT_WEIGHT]);

					// blend rotations from both
					blended_rot = nlerp(sum_weights[ROT_WEIGHT] / new_weight_sum, jsp->getRotation(), blended_rot);
					sum_weights[ROT_WEIGHT] = new_weight_sum;
				} 
				else
				{
					// copy rotation from current
					blended_rot = jsp->getRotation();
					sum_weights[ROT_WEIGHT] = current_weight;
				}
			}

			// update resulting usage mask
			sum_usage = sum_usage | current_usage;
		}
	}

	if (!added_scale.isFinite())
	{
		added_scale.clearVec();
	}

	if (!blended_scale.isFinite())
	{
		blended_scale.setVec(1,1,1);
	}

	// apply transforms
	target_joint->setPosition(blended_pos + added_pos);
	target_joint->setScale(blended_scale + added_scale);
	target_joint->setRotation(added_rot * blended_rot);

	if (apply_now)
	{
		// now clear joint states
		for(S32 i = 0; i < JSB_NUM_JOINT_STATES; i++)
		{
			mJointStates[i] = NULL;
		}
	}
}
Пример #12
0
//-----------------------------------------------------------------------------
// LLHeadRotMotion::onUpdate()
//-----------------------------------------------------------------------------
BOOL LLHeadRotMotion::onUpdate(F32 time, U8* joint_mask)
{
	LLQuaternion	targetHeadRotWorld;
	LLQuaternion	currentRootRotWorld = mRootJoint->getWorldRotation();
	LLQuaternion	currentInvRootRotWorld = ~currentRootRotWorld;

	F32 head_slerp_amt = LLCriticalDamp::getInterpolant(HEAD_LOOKAT_LAG_HALF_LIFE);
	F32 torso_slerp_amt = LLCriticalDamp::getInterpolant(TORSO_LOOKAT_LAG_HALF_LIFE);

	LLVector3* targetPos = (LLVector3*)mCharacter->getAnimationData("LookAtPoint");

	if (targetPos)
	{
		LLVector3 headLookAt = *targetPos;

//		llinfos << "Look At: " << headLookAt + mHeadJoint->getWorldPosition() << llendl;

		F32 lookatDistance = headLookAt.normVec();

		if (lookatDistance < MIN_HEAD_LOOKAT_DISTANCE)
		{
			targetHeadRotWorld = mPelvisJoint->getWorldRotation();
		}
		else
		{
			LLVector3 root_up = LLVector3(0.f, 0.f, 1.f) * currentRootRotWorld;
			LLVector3 left(root_up % headLookAt);
			// if look_at has zero length, fail
			// if look_at and skyward are parallel, fail
			//
			// Test both of these conditions with a cross product.

			if (left.magVecSquared() < 0.15f)
			{
				LLVector3 root_at = LLVector3(1.f, 0.f, 0.f) * currentRootRotWorld;
				root_at.mV[VZ] = 0.f;
				root_at.normVec();

				headLookAt = lerp(headLookAt, root_at, 0.4f);
				headLookAt.normVec();

				left = root_up % headLookAt;
			}
			
			// Make sure look_at and skyward and not parallel
			// and neither are zero length
			LLVector3 up(headLookAt % left);

			targetHeadRotWorld = LLQuaternion(headLookAt, left, up);
		}
	}
	else
	{
		targetHeadRotWorld = currentRootRotWorld;
	}

	LLQuaternion head_rot_local = targetHeadRotWorld * currentInvRootRotWorld;
	head_rot_local.constrain(HEAD_ROTATION_CONSTRAINT);

	// set final torso rotation
	// Set torso target rotation such that it lags behind the head rotation
	// by a fixed amount.
	LLQuaternion torso_rot_local = nlerp(TORSO_LAG, LLQuaternion::DEFAULT, head_rot_local );
	mTorsoState->setRotation( nlerp(torso_slerp_amt, mTorsoState->getRotation(), torso_rot_local) );

	head_rot_local = nlerp(head_slerp_amt, mLastHeadRot, head_rot_local);
	mLastHeadRot = head_rot_local;

	// Set the head rotation.
	if (mNeckState->getJoint() && mNeckState->getJoint()->getParent())
	{
		LLQuaternion torsoRotLocal =  mNeckState->getJoint()->getParent()->getWorldRotation() * currentInvRootRotWorld;
		head_rot_local = head_rot_local * ~torsoRotLocal;
		mNeckState->setRotation(nlerp(NECK_LAG, LLQuaternion::DEFAULT, head_rot_local));
		mHeadState->setRotation(nlerp(1.f - NECK_LAG, LLQuaternion::DEFAULT, head_rot_local));
	}

	return TRUE;
}
Пример #13
0
// Returns "distance" between target destination and resulting xfrom
F32 LLDrawable::updateXform(BOOL undamped)
{
	BOOL damped = !undamped;

	// Position
	LLVector3 old_pos(mXform.getPosition());
	LLVector3 target_pos;
	if (mXform.isRoot())
	{
		// get root position in your agent's region
		target_pos = mVObjp->getPositionAgent();
	}
	else
	{
		// parent-relative position
		target_pos = mVObjp->getPosition();
	}
	
	// Rotation
	LLQuaternion old_rot(mXform.getRotation());
	LLQuaternion target_rot = mVObjp->getRotation();
	//scaling
	LLVector3 target_scale = mVObjp->getScale();
	LLVector3 old_scale = mCurrentScale;
	
	// Damping
	F32 dist_squared = 0.f;
	F32 camdist2 = (mDistanceWRTCamera * mDistanceWRTCamera);

	if (damped && isVisible())
	{
		F32 lerp_amt = llclamp(LLCriticalDamp::getInterpolant(OBJECT_DAMPING_TIME_CONSTANT), 0.f, 1.f);
		LLVector3 new_pos = lerp(old_pos, target_pos, lerp_amt);
		dist_squared = dist_vec_squared(new_pos, target_pos);

		LLQuaternion new_rot = nlerp(lerp_amt, old_rot, target_rot);
		// FIXME: This can be negative! It is be possible for some rots to 'cancel out' pos or size changes.
		dist_squared += (1.f - dot(new_rot, target_rot)) * 10.f;

		LLVector3 new_scale = lerp(old_scale, target_scale, lerp_amt);
		dist_squared += dist_vec_squared(new_scale, target_scale);

		if ((dist_squared >= MIN_INTERPOLATE_DISTANCE_SQUARED * camdist2) &&
			(dist_squared <= MAX_INTERPOLATE_DISTANCE_SQUARED))
		{
			// interpolate
			target_pos = new_pos;
			target_rot = new_rot;
			target_scale = new_scale;
		}
		else if (mVObjp->getAngularVelocity().isExactlyZero())
		{
			// snap to final position (only if no target omega is applied)
			dist_squared = 0.0f;
			if (getVOVolume() && !isRoot())
			{ //child prim snapping to some position, needs a rebuild
				gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE);
			}
		}
	}
	else
	{
		// The following fixes MAINT-1742 but breaks vehicles similar to MAINT-2275
		// dist_squared = dist_vec_squared(old_pos, target_pos);

		// The following fixes MAINT-2247 but causes MAINT-2275
		//dist_squared += (1.f - dot(old_rot, target_rot)) * 10.f;
		//dist_squared += dist_vec_squared(old_scale, target_scale);
	}

	LLVector3 vec = mCurrentScale-target_scale;
	
	if (vec*vec > MIN_INTERPOLATE_DISTANCE_SQUARED)
	{ //scale change requires immediate rebuild
		mCurrentScale = target_scale;
		gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE);
	}
	else if (!isRoot() && 
		 (!mVObjp->getAngularVelocity().isExactlyZero() ||
			dist_squared > 0.f))
	{ //child prim moving relative to parent, tag as needing to be rendered atomically and rebuild
		dist_squared = 1.f; //keep this object on the move list
		if (!isState(LLDrawable::ANIMATED_CHILD))
		{			
			setState(LLDrawable::ANIMATED_CHILD);
			gPipeline.markRebuild(this, LLDrawable::REBUILD_ALL, TRUE);
			mVObjp->dirtySpatialGroup();
		}
	}
	else if (!isRoot() &&
			((dist_vec_squared(old_pos, target_pos) > 0.f)
			|| (1.f - dot(old_rot, target_rot)) > 0.f))
	{ //fix for BUG-840, MAINT-2275, MAINT-1742, MAINT-2247
		gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE);
	}
	else if (!getVOVolume() && !isAvatar())
	{
		movePartition();
	}

	// Update
	mXform.setPosition(target_pos);
	mXform.setRotation(target_rot);
	mXform.setScale(LLVector3(1,1,1)); //no scale in drawable transforms (IT'S A RULE!)
	mXform.updateMatrix();

	if (mSpatialBridge)
	{
		gPipeline.markMoved(mSpatialBridge, FALSE);
	}
	return dist_squared;
}
Пример #14
0
	void llquat_test_object_t::test<8>()
	{
		F32 value1 = 15.0f;
		LLQuaternion quat1(1.0f, 2.0f, 4.0f, 1.0f);
		LLQuaternion quat2(4.0f, 3.0f, 6.5f, 9.7f);
		LLQuaternion res_lerp, res_slerp, res_nlerp;
		
		//test case for lerp(F32 t, const LLQuaternion &q) fn. 
		res_lerp = lerp(value1, quat1);
		ensure("1. LLQuaternion lerp(F32 t, const LLQuaternion &q) failed", 
										is_approx_equal_fraction(0.181355f, res_lerp.mQ[0], 16) &&
										is_approx_equal_fraction(0.362711f, res_lerp.mQ[1], 16) &&
										is_approx_equal_fraction(0.725423f, res_lerp.mQ[2], 16) &&				
										is_approx_equal_fraction(0.556158f, res_lerp.mQ[3], 16));				

		//test case for lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q) fn.
		res_lerp = lerp(value1, quat1, quat2);
		ensure("2. LLQuaternion lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q) failed",
										is_approx_equal_fraction(0.314306f, res_lerp.mQ[0], 16) &&
										is_approx_equal_fraction(0.116156f, res_lerp.mQ[1], 16) &&
										is_approx_equal_fraction(0.283559f, res_lerp.mQ[2], 16) &&				
										is_approx_equal_fraction(0.898506f, res_lerp.mQ[3], 16));				

		//test case for slerp( F32 u, const LLQuaternion &a, const LLQuaternion &b ) fn.
		res_slerp = slerp(value1, quat1, quat2);
		ensure("3. LLQuaternion slerp( F32 u, const LLQuaternion &a, const LLQuaternion &b) failed", 
										is_approx_equal_fraction(46.000f, res_slerp.mQ[0], 16) &&
										is_approx_equal_fraction(17.00f, res_slerp.mQ[1], 16) &&
										is_approx_equal_fraction(41.5f, res_slerp.mQ[2], 16) &&				
										is_approx_equal_fraction(131.5f, res_slerp.mQ[3], 16));				

		//test case for nlerp(F32 t, const LLQuaternion &a, const LLQuaternion &b) fn.
		res_nlerp = nlerp(value1, quat1, quat2);
		ensure("4. LLQuaternion nlerp(F32 t, const LLQuaternion &a, const LLQuaternion &b) failed",  
										is_approx_equal_fraction(0.314306f, res_nlerp.mQ[0], 16) &&
										is_approx_equal_fraction(0.116157f, res_nlerp.mQ[1], 16) &&
										is_approx_equal_fraction(0.283559f, res_nlerp.mQ[2], 16) &&				
										is_approx_equal_fraction(0.898506f, res_nlerp.mQ[3], 16));				

		//test case for nlerp(F32 t, const LLQuaternion &q) fn.
		res_slerp = slerp(value1, quat1);
		ensure("5. LLQuaternion slerp(F32 t, const LLQuaternion &q) failed", 
										is_approx_equal_fraction(1.0f, res_slerp.mQ[0], 16) &&
										is_approx_equal_fraction(2.0f, res_slerp.mQ[1], 16) &&
										is_approx_equal_fraction(4.0000f, res_slerp.mQ[2], 16) &&				
										is_approx_equal_fraction(1.000f, res_slerp.mQ[3], 16));				
										
		LLQuaternion quat3(2.0f, 1.0f, 5.5f, 10.5f);
		LLQuaternion res_nlerp1;
		value1 = 100.0f;
		res_nlerp1 = nlerp(value1, quat3);
		ensure("6. LLQuaternion nlerp(F32 t, const LLQuaternion &q)  failed", 
										is_approx_equal_fraction(0.268245f, res_nlerp1.mQ[0], 16) &&										is_approx_equal_fraction(0.134122f, res_nlerp1.mQ[1], 2) &&
										is_approx_equal_fraction(0.737673f, res_nlerp1.mQ[2], 16) &&				
										is_approx_equal_fraction(0.604892f, res_nlerp1.mQ[3], 16));				

		//test case for lerp(F32 t, const LLQuaternion &q) fn. 
		res_lerp = lerp(value1, quat2);
		ensure("7. LLQuaternion lerp(F32 t, const LLQuaternion &q) failed", 
										is_approx_equal_fraction(0.404867f, res_lerp.mQ[0], 16) &&
										is_approx_equal_fraction(0.303650f, res_lerp.mQ[1], 16) &&
										is_approx_equal_fraction(0.657909f, res_lerp.mQ[2], 16) &&				
										is_approx_equal_fraction(0.557704f, res_lerp.mQ[3], 16));				
		
	}