//----------------------------------------------------------------------------
void TerrainPage::RemoveJunglerPoints (Jungler *jungler, APoint center, float radius, 
	int num)
{
	if (!jungler)
		return;

	// 范围内个数
	std::vector<int> indexs;
	for (int i=0; i<jungler->GetNum(); i++)
	{
		const APoint &pos = jungler->GetPos(i);
		AVector dir = pos - center;
		if (dir.Length() < radius)
		{
			indexs.push_back(i);
		}
	}

	std::vector<int> indexsRemoves;
	for (int i=0; i<(int)indexs.size(); i++)
	{
		float fRand = (float)num/(float)indexsRemoves.size();
		float fR = Mathf::IntervalRandom(0.0f, 1.0f);

		if (fR <= fRand)
		{
			indexsRemoves.push_back(indexs[i]);
		}
	}

	jungler->Remove(indexsRemoves);
}
Ejemplo n.º 2
0
//----------------------------------------------------------------------------
void SceneNodeCtrl::OnMouseWheel(RenderStep *renderStep, float wheelDelta)
{
	Camera *camera = renderStep->GetCamera();
	float rmax = camera->GetRMax();
	APoint camPosition = camera->GetPosition();
	APoint ctrlPosition = GetPosition();
	AVector diff = ctrlPosition - camPosition;
	float diffLength = diff.Length();

	if (mLookType != LT_PERSPECTIVE)
	{
		if (0.0f != rmax)
		{
			mCtrlsGroup->WorldTransform.SetUniformScale(rmax*0.11f);
			mCtrlsGroup->Update(Time::GetTimeInSeconds(), false);
		}
	}
	else
	{
		float scale = diffLength*0.04f;
		if (scale == 0.0f) scale = 0.0001f;
		if (scale < 1.0f) scale = 1.0f;
		mCtrlsGroup->WorldTransform.SetUniformScale(scale);
		mCtrlsGroup->Update(Time::GetTimeInSeconds(), false);
	}
}
Ejemplo n.º 3
0
//----------------------------------------------------------------------------
void Soundable::UpdateWorldData(double applicationTime, double elapsedTime)
{
	Movable::UpdateWorldData(applicationTime, elapsedTime);

	if (mSound)
		mSound->SetPosition(WorldTransform.GetTranslate());

	const APoint &listenPos = SoundSystem::GetSingleton().GetListenerPos();

	if (!Is3D())
	{
		AVector dir = WorldTransform.GetTranslate() - listenPos;

		if (!mDistanceUseX)
			dir.X() = 0.0f;

		if (!mDistanceUseY)
			dir.Y() = 0.0f;

		if (!mDistanceUseZ)
			dir.Z() = 0.0f;

		float dist = dir.Length();

		SoundableController *sCtrl = DynamicCast<SoundableController>(GetEffectableController());
		const SoundableObject *sObj = sCtrl->GetSoundableObject();
		if (sObj)
		{
			float curVolume = sObj->Volume;
			float volume = curVolume;

			if (dist < mMinDistance)
			{
				volume = curVolume;
			}
			else if (mMinDistance<=dist && dist<=mMaxDistance)
			{
				float range = mMaxDistance - mMinDistance;
				if (range <= 0.0f)
					range = 0.0f;

				volume = curVolume * (1.0f - (dist - mMinDistance)/range);
			}
			else if (dist > mMaxDistance)
			{
				volume = 0.0f;
			}

			if (mSound)
			{
				mSound->SetVolume(volume);
			}
		}
	}
}
Ejemplo n.º 4
0
//----------------------------------------------------------------------------
AVector SteeringBehavior::FollowPath ()
{
	AVector dist = mPath->GetCurrentWayPoint() - mActor->GetPosition();
	float length = dist.Length();

	if (length < mWayPointSeekDistSq)
		mPath->SetNextWayPoint();

	if (!mPath->IsFinished())
	{
		return Seek(mPath->GetCurrentWayPoint());
	}
	else
	{
		return Arrive(mPath->GetCurrentWayPoint(), DM_NORMAL);
	}
}
Ejemplo n.º 5
0
//----------------------------------------------------------------------------
AVector SteeringBehavior::Arrive (APoint toPosition, DecelerateMode mode)
{
	AVector toTarget = toPosition - mActor->GetPosition();
	float dist = toTarget.Length();

	if (dist > 0)
	{
		const double decelerationTweaker = 0.3f;
		double speed = dist / ((double)mode * decelerationTweaker);
		speed = min(speed, mActor->GetMaxSpeed());

		AVector desiredVelocity = toTarget * speed/dist;

		return (desiredVelocity - mActor->GetVelocity());
	}

	return AVector();
}
Ejemplo n.º 6
0
//----------------------------------------------------------------------------
float CurveSegment::Curvature (float u) const
{
    AVector velocity = PU(u);
    float speedSqr = velocity.SquaredLength();

    if (speedSqr >= Mathf::ZERO_TOLERANCE)
    {
        AVector acceleration = PUU(u);
        AVector cross = velocity.Cross(acceleration);
        float numer = cross.Length();
        float denom = Mathf::Pow(speedSqr, 1.5f);
        return numer/denom;
    }
    else
    {
        // Curvature is indeterminate, just return 0.
        return 0.0f;
    }
}
Ejemplo n.º 7
0
//----------------------------------------------------------------------------
void DlodNode::SelectLevelOfDetail (const Camera* camera)
{
    mWorldLodCenter = WorldTransform*mModelLodCenter;

    int i;
    for (i = 0; i < mNumLevelsOfDetail; ++i)
    {
        mWorldMinDist[i] = WorldTransform.GetUniformScale()*mModelMinDist[i];
        mWorldMaxDist[i] = WorldTransform.GetUniformScale()*mModelMaxDist[i];
    }

    SetActiveChild(SN_INVALID_CHILD);
    AVector diff = mWorldLodCenter - camera->GetPosition();
    float dist = diff.Length();
    for (i = 0; i < mNumLevelsOfDetail; ++i) 
    {
        if (mWorldMinDist[i] <= dist && dist < mWorldMaxDist[i])
        {
            SetActiveChild(i);
            break;
        }
    }
}
Ejemplo n.º 8
0
//----------------------------------------------------------------------------
void Picker::ExecuteRecursive (Movable* object, bool &hasMeshPicked)
{
	if (object)
	{
		if (!object->IsDoPick())
			return;

		if (!object->IsShow() && !object->IsPickIngoreCullingMode())
			return;
	}

	Triangles* mesh = DynamicCast<Triangles>(object);
	if (mesh)
	{
		if (!mesh->GetVertexBuffer())
			return;

		if (mesh->WorldBound.TestIntersection(mOrigin, mDirection, mTMin, mTMax))
		{
			if (mesh->IsUseBoundPick())
			{
				AVector dir = mesh->GetWorldTransform().GetTranslate() - mOrigin;
				float length = dir.Length();

				PickRecord record;
				record.Intersected = mesh;
				record.T = length;
				Records.push_back(record);
			}
			else
			{
				// 将射线从世界坐标系转换到模型坐标系。
				APoint ptmp;
				if (!mesh->IsSkinCtrlSetWroldTrans)
					ptmp = mesh->WorldTransform.Inverse()*mOrigin;
				else
					ptmp = mesh->BoundWorldTransform.Inverse()*mOrigin;
				Vector3f modelOrigin(ptmp[0], ptmp[1], ptmp[2]);

				AVector vtmp;
				if (!mesh->IsSkinCtrlSetWroldTrans)
					vtmp = mesh->WorldTransform.Inverse()*mDirection;
				else
					vtmp = mesh->BoundWorldTransform.Inverse()*mDirection;
				Vector3f modelDirection(vtmp[0], vtmp[1], vtmp[2]);

				Line3f line(modelOrigin, modelDirection);

				// 访问方位数据
				VertexBufferAccessor vba(mesh);

				int numTriangles = mesh->GetNumTriangles();
				for (int i = 0; i < numTriangles; ++i)
				{
					int v0, v1, v2;
					if (!mesh->GetTriangle(i, v0, v1, v2))
					{
						continue;
					}

					Vector3f vertex0 = vba.Position<Vector3f>(v0);
					Vector3f vertex1 = vba.Position<Vector3f>(v1);
					Vector3f vertex2 = vba.Position<Vector3f>(v2);
					Triangle3f triangle(vertex0, vertex1, vertex2);

					IntrLine3Triangle3f calc(line, triangle);
					if (calc.Find())
					{
						float lineParameter = calc.GetLineParameter();
						if (mTMin<=lineParameter && lineParameter<=mTMax)
						{
							PickRecord record;
							record.Intersected = mesh;
							record.T = calc.GetLineParameter();
							record.Triangle = i;
							record.Bary[0] = calc.GetTriBary0();
							record.Bary[1] = calc.GetTriBary1();
							record.Bary[2] = calc.GetTriBary2();

							Vector3f edg1 = vertex1 - vertex0;
							Vector3f edg2 = vertex2 - vertex0;
							Vector3f normal = edg1.UnitCross(edg2);
							float dotVal = line.Direction.Dot(normal);
							if (dotVal > Mathf::ZERO_TOLERANCE)
							{
								normal *= -1.0f;
							}
							record.LocalNormal = normal;
							record.WorldPos = mOrigin + mDirection * record.T;

							Records.push_back(record);

							if (mIsDoMovPickCall)
							{
								hasMeshPicked = true;
								mesh->OnPicked(mPickInfo);
							}
						}
					}
				}
			}
		}
		else
		{
			if (mIsDoMovPickCall)
				mesh->OnNotPicked(mPickInfo);
		}
		return;
	}

	SwitchNode* switchNode = DynamicCast<SwitchNode>(object);
	if (switchNode)
	{
		bool newHasChildPicked = false;

		int activeChild = switchNode->GetActiveChild();
		if (activeChild != SwitchNode::SN_INVALID_CHILD)
		{
			if (switchNode->WorldBound.TestIntersection(mOrigin, mDirection, mTMin, mTMax))
			{
				Movable* child = switchNode->GetChild(activeChild);
				if (child)
				{
					ExecuteRecursive(child, newHasChildPicked);
				}

				if (newHasChildPicked)
				{
					hasMeshPicked = true;
				}

				if (mIsDoMovPickCall)
				{
					if (hasMeshPicked)
					{
						switchNode->OnPicked(mPickInfo);
					}
					else
					{
						switchNode->OnNotPicked(mPickInfo);
					}
				}
			}
			else
			{
				if (mIsDoMovPickCall)
					switchNode->OnNotPicked(mPickInfo);
			}
		}
		return;
	}

	Node* node = DynamicCast<Node>(object);
	if (node)
	{
		bool newHasChildPicked = false;
		if (node->WorldBound.TestIntersection(mOrigin, mDirection, mTMin, mTMax))
		{
			Movable *movPriority = 0;
			if (node->IsDoPickPriority())
			{
				for (int i=0; i<node->GetNumChildren(); i++)
				{
					Movable *mov = node->GetChild(i);
					if (mov && mov->IsNotPickedParentChildrenNotPicked())
						movPriority = mov;
				}
			}

			// 做优先检测
			bool doLastPick = false;
			if (movPriority)
			{
				ExecuteRecursive (movPriority, doLastPick);		
			}
			else
			{
				doLastPick = true;
			}

			if (doLastPick)
			{
				for (int i = 0; i < node->GetNumChildren(); ++i)
				{
					Movable* child = node->GetChild(i);
					if (child && child!=movPriority)
					{
						ExecuteRecursive(child, newHasChildPicked);
					}
				}

				if (newHasChildPicked)
				{
					hasMeshPicked = true;
				}

				if (mIsDoMovPickCall)
				{
					if (newHasChildPicked)
					{
						node->OnPicked(mPickInfo);
					}
					else
					{
						node->OnNotPicked(mPickInfo);
					}
				}
			}
		}
		else
		{
			if (mIsDoMovPickCall)
				node->OnNotPicked(mPickInfo);
		}
	}
}
//----------------------------------------------------------------------------
void InputPushTransformController::OnEvent(Event *event)
{
	if (!Active) return;
	if (!IsPlaying()) return;

	Movable *mov = DynamicCast<Movable>(GetControlledable());
	if (!mov) return;

	if (InputEventSpace::IsEqual(event, InputEventSpace::LevelView))
	{
		mIsPressedValid = false;
	}
	else if (InputEventSpace::IsEqual(event, InputEventSpace::MousePressed) ||
		InputEventSpace::IsEqual(event,InputEventSpace::TouchPressed))
	{
		InputEventData data = event->GetData<InputEventData>();

		mIsPressedValid = true;
		mSampingTiming = 0.0f;

		mPressedTime = (float)Time::GetTimeInSeconds();
		mPressedPos = data.MTPos;

		if (mConvertCallback)
		{
			mConvertCallback(mPressedPos, (int)data.MTPos.X(), (int)data.MTPos.Z());
		}

		mCurTouchPos = mPressedPos;
		mLastTouchPos = mCurTouchPos;
		mLastSamplePos = mCurTouchPos;

		SetVelocity(AVector::ZERO);
	}
	else if (InputEventSpace::IsEqual(event, InputEventSpace::MouseReleased) ||
		InputEventSpace::IsEqual(event, InputEventSpace::TouchReleased))
	{
		InputEventData data = event->GetData<InputEventData>();

		mSampingTiming = 0.0f;

		if (!mIsPressedValid) return;

		mIsPressedValid = false;

		mReleasedTime = (float)Time::GetTimeInSeconds();
		mReleasedPos = data.MTPos;

		if (mConvertCallback)
		{
			mConvertCallback(mPressedPos, (int)data.MTPos.X(), (int)data.MTPos.Z());
		}

		float deltaTime = mReleasedTime - mPressedTime;
		if (deltaTime <= 0.0f) deltaTime = 1.0f;

		//AVector speed = mReleasedPos - mPressedPos;
		//speed /= deltaTime;
		AVector speed = mTouchMoveSpeed;
		float judge = 0.0f;
		if (mLockDir != AVector::ZERO)
		{
			judge = mLockDir.Dot(speed);
		}
		else
		{
			judge = speed.Length();
		}
		judge = Mathf::FAbs(judge);

		if (judge >= mPushTriggerSpeed)
		{
			if (mLockDir != AVector::ZERO)
			{
				speed.X() *= mLockDir.X();
				speed.Y() *= mLockDir.Y();
				speed.Z() *= mLockDir.Z();
			}

			SetReleaseVelocity(speed * judge);
		}

		if (IsSmallTransScope() && GetSmallTransDir() != AVector::ZERO)
		{
			SetReleaseVelocity(AVector::ZERO);
		}
	}
	else if (InputEventSpace::IsEqual(event, InputEventSpace::MouseMoved) ||
		InputEventSpace::IsEqual(event, InputEventSpace::TouchMoved))
	{
		InputEventData data = event->GetData<InputEventData>();

		if (!mIsPressedValid) return;

		mCurTouchPos = data.MTPos;

		if (mConvertCallback)
		{
			mConvertCallback(mPressedPos, (int)data.MTPos.X(), (int)data.MTPos.Z());
		}

		AVector moveDis = mCurTouchPos - mLastTouchPos;

		APoint pos = mov->LocalTransform.GetTranslate();
		pos += moveDis;
		TransScope(pos);
		mov->LocalTransform.SetTranslate(pos);

		mLastTouchPos = mCurTouchPos;
	}
	else if (InputEventSpace::IsEqual(event, InputEventSpace::TouchCancelled))
	{
		mIsPressedValid = false;
	}
}
Ejemplo n.º 10
0
//----------------------------------------------------------------------------
void SceneNodeCtrl::OnMotion(bool leftDown, RenderStep *renderStep,
	PX2::APoint posNow, PX2::APoint posBefore)
{
	PX2_UNUSED(leftDown);
	PX2_UNUSED(renderStep);

	Renderer *renderer = renderStep->GetRenderer();
	Camera *camera = renderStep->GetCamera();

	// 光标移动更新
	if (DT_NONE == mDragType)
	{
		GeoObjFactory factory;

		DragType dt = GetDragType(renderStep, posNow);
		Movable *ctrlMov = 0;
		Float4 colorYellowAlpha = Float4(1.0f, 1.0f, 0.0f, 0.3f);

		if (DT_X == dt)
		{
			ctrlMov = GetCurrentCtrlX();
			factory.UpdateCtrlColor(renderer, ctrlMov, Float4::YELLOW);
		}
		else if (DT_Y == dt)
		{
			ctrlMov = GetCurrentCtrlY();
			factory.UpdateCtrlColor(renderer, ctrlMov, Float4::YELLOW);
		}
		else if (DT_Z == dt)
		{
			ctrlMov = GetCurrentCtrlZ();
			factory.UpdateCtrlColor(renderer, ctrlMov, Float4::YELLOW);
		}
		else if (DT_XY == dt)
		{
			factory.UpdateCtrlColor1(renderer, GetCurrentCtrlXY(), colorYellowAlpha);
			factory.UpdateCtrlColor1(renderer, GetCurrentCtrlYZ(), Float4::ZERO);
			factory.UpdateCtrlColor1(renderer, GetCurrentCtrlXZ(), Float4::ZERO);
		}
		else if (DT_YZ == dt)
		{
			factory.UpdateCtrlColor1(renderer, GetCurrentCtrlYZ(), colorYellowAlpha);
			factory.UpdateCtrlColor1(renderer, GetCurrentCtrlXY(), Float4::ZERO);
			factory.UpdateCtrlColor1(renderer, GetCurrentCtrlXZ(), Float4::ZERO);
		}
		else if (DT_XZ == dt)
		{
			factory.UpdateCtrlColor1(renderer, GetCurrentCtrlXZ(), colorYellowAlpha);
			factory.UpdateCtrlColor1(renderer, GetCurrentCtrlXY(), Float4::ZERO);
			factory.UpdateCtrlColor1(renderer, GetCurrentCtrlYZ(), Float4::ZERO);
		}
		else if (DT_XYZ == dt)
		{
			factory.UpdateCtrlColor1(renderer, GetCurrentCtrlXYZ(), Float4::YELLOW);
		}
		else if (DT_NONE == dt)
		{
			factory.UpdateCtrlColor(renderer, GetCurrentCtrlX(), Float4::RED);
			factory.UpdateCtrlColor(renderer, GetCurrentCtrlY(), Float4::GREEN);
			factory.UpdateCtrlColor(renderer, GetCurrentCtrlZ(), Float4::BLUE);
			factory.UpdateCtrlColor1(renderer, GetCurrentCtrlXY(), Float4::ZERO);
			factory.UpdateCtrlColor1(renderer, GetCurrentCtrlYZ(), Float4::ZERO);
			factory.UpdateCtrlColor1(renderer, GetCurrentCtrlXZ(), Float4::ZERO);
			factory.UpdateCtrlColor1(renderer, GetCurrentCtrlXYZ(), Float4::WHITE);
		}

		if (DT_NONE == dt)
		{
			Event *ent = EditEventSpace::CreateEventX(EditEventSpace::SceneNodeDrag);
			ent->SetData<int>(0);
			EventWorld::GetSingleton().BroadcastingLocalEvent(ent);
		}
		else
		{
			Event *ent = EditEventSpace::CreateEventX(EditEventSpace::SceneNodeDrag);
			ent->SetData<int>(1);
			EventWorld::GetSingleton().BroadcastingLocalEvent(ent);
		}
	}

	if (DT_NONE == mDragType) return;
	else
	{
		Event *ent = EditEventSpace::CreateEventX(EditEventSpace::SceneNodeDrag);
		ent->SetData<int>(1);
		EventWorld::GetSingleton().BroadcastingLocalEvent(ent);
	}

	int numObjs = PX2_SELECTION.GetNumObjects();
	if (0 == numObjs) 
		return;

	// get pickPoint with the plane
	TriMesh *meshHelp = PX2_GR.GetXYPlane();
	if (DT_X == mDragType)
	{
		if (LT_PERSPECTIVE == mLookType || LT_TOP == mLookType)
			meshHelp = PX2_GR.GetXYPlane();
		else if (LT_FRONT == mLookType)
			meshHelp = PX2_GR.GetXZPlane();
	}
	else if (DT_Y == mDragType)
	{
		meshHelp = PX2_GR.GetXYPlane();
	}
	else if (DT_Z == mDragType)
	{
		AVector cameraDir = camera->GetDVector();
		cameraDir.Normalize();
		float dotVal = Mathf::FAbs(cameraDir.Dot(AVector::UNIT_X));
		if (dotVal > 0.7f)
		{
			meshHelp = PX2_GR.GetYZPlane();
		}
		else
		{
			meshHelp = PX2_GR.GetXZPlane();
		}
	}
	else if (DT_XY == mDragType)
	{
		meshHelp = PX2_GR.GetXYPlane();
	}
	else if (DT_YZ == mDragType)
	{
		meshHelp = PX2_GR.GetYZPlane();
	}
	else if (DT_XZ == mDragType)
	{
		meshHelp = PX2_GR.GetXZPlane();
	}
	else if (DT_XYZ == mDragType)
	{
		meshHelp = PX2_GR.GetXYPlane();
	}
	meshHelp->WorldTransform.SetTranslate(GetPosition());

	// get pick ray
	APoint rayOrigin_Now;
	AVector rayDir_Now;
	renderStep->GetPickRay(posNow.X(), posNow.Z(), rayOrigin_Now, rayDir_Now);

	APoint rayOrigin_Before;
	AVector rayDir_Before;
	renderStep->GetPickRay(posBefore.X(), posBefore.Z(), rayOrigin_Before, rayDir_Before);

	// pick
	Picker pickerNow;
	pickerNow.Execute(meshHelp, rayOrigin_Now, rayDir_Now, 0.0f, Mathf::MAX_REAL);
	float lengthNow = pickerNow.GetClosestToZero().T;
	APoint positionNow(rayOrigin_Now + rayDir_Now*lengthNow);

	Picker pickerOrigin;
	pickerOrigin.Execute(meshHelp, rayOrigin_Before, rayDir_Before, 0.0f, Mathf::MAX_REAL);
	float lengthBefore = pickerOrigin.GetClosestToZero().T;
	APoint positionBefore(rayOrigin_Before + rayDir_Before*lengthBefore);

	if (pickerNow.Records.empty() || pickerOrigin.Records.empty()) return;

	AVector transMoved = positionNow - positionBefore;
	AVector transDir = transMoved;
	transDir.Normalize();

	float transValue = 0.0f;
	float transValue1 = 0.0f;
	AVector transVec;
	AVector rolateVec;

	AVector dirX = mDirX;
	AVector dirY = mDirY;
	AVector dirZ = mDirZ;

	if (DT_X == mDragType)
	{
		transValue = transMoved.Dot(dirX);
		transVec = dirX * transValue;

		rolateVec.X() = transMoved.Length() *(1.0f - Mathf::FAbs(transDir.Dot(dirX)));

		AVector vec = transDir.Cross(dirX);
		rolateVec.X() *= Mathf::Sign(vec.Z());
	}
	else if (DT_Y == mDragType)
	{
		transValue = transMoved.Dot(dirY);
		transVec = dirY * transValue;

		rolateVec.Y() = transMoved.Length() *(1.0f - Mathf::FAbs(transDir.Dot(dirY)));

		AVector vec = transDir.Cross(dirY);
		rolateVec.Y() *= Mathf::Sign(vec.Z());
	}
	else if (DT_Z == mDragType)
	{
		transValue = transMoved.Dot(dirZ);
		transVec = dirZ * transValue;

		rolateVec.Z() = transMoved.Length() *(1.0f - Mathf::FAbs(transDir.Dot(dirZ)));

		rolateVec.Z() *= Mathf::Sign(posNow.X() - posBefore.X());
	}
	else if (DT_XY == mDragType)
	{
		transValue = transMoved.Dot(dirX);
		transValue1 = transMoved.Dot(dirY);
		transVec = dirX * transValue + dirY * transValue1;
	}
	else if (DT_YZ == mDragType)
	{
		transValue = transMoved.Dot(dirY);
		transValue1 = transMoved.Dot(dirZ);
		transVec = dirY * transValue + dirZ * transValue1;
	}
	else if (DT_XZ == mDragType)
	{
		transValue = transMoved.Dot(dirX);
		transValue1 = transMoved.Dot(dirZ);
		transVec = dirX * transValue + dirZ * transValue1;
	}
	else if (DT_XYZ == mDragType)
	{
		float transValue0 = Mathf::FAbs(transMoved.Dot(dirX));
		float transValue1 = Mathf::FAbs(transMoved.Dot(dirY));
		float transValue2 = Mathf::FAbs(transMoved.Dot(dirZ));

		float trans = (transValue0 + transValue1 + transValue2) / 3.0f;
		trans *= Mathf::Sign(transMoved.Y());

		transVec = AVector(trans, trans, trans);
	}

	if (CT_SCALE == mCtrlType)
		transVec *= 0.5f;

	HMatrix parentMat = mParentRotateMat.Inverse();
	transVec = parentMat * transVec;

	if (CT_TRANSLATE == mCtrlType)
	{
		PX2_SELECTION.Translate(transVec);

		UpdateCtrlTrans();
	}
	else if (CT_ROLATE == mCtrlType)
	{
		PX2_SELECTION.AddRolate(rolateVec);
	}
	else if (CT_SCALE == mCtrlType)
	{
		if (DT_XYZ == mDragType)
			PX2_SELECTION.AddScale(transVec);
	}

	Object *obj = PX2_SELECTION.GetFirstObject();
	if (obj)
	{
		Event *ent = EditEventSpace::CreateEventX(
			EditEventSpace::ObjectTransformChanged);
		ent->SetData<Object*>(obj);
		EventWorld::GetSingleton().BroadcastingLocalEvent(ent);
	}

	mCtrlsGroup->Update(Time::GetTimeInSeconds(), false);
}
//----------------------------------------------------------------------------
void FreeFormDeformation::OnMouseMove (int x, int y)
{
    // Change to right-handed coordinates.
    y = GetHeight() - 1 - y;

    // Construct a pick ray.  Te want to move the control point from its
    // current location to this ray.
    APoint origin;
    AVector direction;
    if (!mRenderer->GetPickRay(x, y, origin, direction))
    {
        return;
    }

    // Let E be the camera world origin, D be the camera world direction, and
    // U be the pick ray world direction.  Let C0 be the current location of
    // the picked point and let C1 be its desired new location.  We need to
    // choose t for which C1 = E + t*U.  Two possibilities are provided here,
    // both requiring computing: Diff = C0 - E.
    AVector diff = mOldWorldPos - mCamera->GetPosition();

    float t;
#if 0
    // The new world position is chosen to be at a distance along the pick
    // ray that is equal to the distance from the camera location to the old
    // world position.  That is, we require
    //   Length(C0-E) = Length(C1-E) = Length(t*U) = t.
    t = diff.Length();
#else
    // The new world position is in the same plane perpendicular to the
    // camera direction as the old world position is.  This plane is
    // Dot(D,X-C0) = 0, in which case we need
    //   0 = Dot(D,C1-C0) = Dot(D,E+t*U-C0) = Dot(D,E-C0) + t*Dot(D,U)
    // Solving for t, we have
    //   t = Dot(D,C0-E)/Dot(D,U)
    t = mCamera->GetDVector().Dot(diff)/mCamera->GetDVector().Dot(direction);
#endif
    APoint newWorldPos = origin + t*direction;

    // Move the control point to the new world location.  The technical
    // problem is that we need to modify the world coordinates for the
    // selected control point.  Thus, we need to determine how to change the
    // local translation in order to produce the correct world translation.
    Node* parent = (Node*)mSelected->GetParent();
    diff = newWorldPos - mOldWorldPos;
    AVector localDiff = parent->WorldTransform.Inverse()*diff;
    mSelected->LocalTransform.SetTranslate(
        mSelected->LocalTransform.GetTranslate() + localDiff);
    mSelected->Update();
    mOldWorldPos = newWorldPos;

    // Modify the control point itself.  It is known that the name string
    // has three single-digit numbers separated by blanks.
    const std::string& name = mSelected->GetName();
    int i0 = (int)(name[0] - '0');
    int i1 = (int)(name[2] - '0');
    int i2 = (int)(name[4] - '0');
    APoint trn = mSelected->LocalTransform.GetTranslate();
    mVolume->SetControlPoint(i0, i1, i2, Vector3f(trn[0], trn[1], trn[2]));

    // TO DO.  We need only update mesh vertices that are affected by the
    // change in one control point.  This requires working with the B-spline
    // basis function and knowing which (u,v,w) to evaluate at (i.e. determine
    // the local control region).
    UpdateMesh();

    // TO DO.  Only need to update neighboring lines.
    UpdatePolysegments();
}