//---------------------------------------------------------------------------- void FMODSound::SetVelocity (const AVector &velocity) { FMOD_VECTOR vec; vec.x = velocity.X(); vec.y = velocity.Y(); vec.z = velocity.Z(); if (mChannel) mChannel->set3DAttributes(0, &vec); }
//---------------------------------------------------------------------------- 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); } } } }
//---------------------------------------------------------------------------- bool PushTransformController::Update(double applicationTime, double elapsedTime1) { if (!Controller::Update(applicationTime, elapsedTime1)) return false; if (mVelocity == AVector::ZERO) return true; float elapsedTime = (float)elapsedTime1; AVector velocityDis = mVelocity*elapsedTime; AVector movedDis; if (IsXY()) { movedDis.X() = velocityDis.X(); movedDis.Y() = velocityDis.Y(); } else { movedDis.X() = velocityDis.X(); movedDis.Z() = velocityDis.Z(); } OnMoving(movedDis); // 减小速度 AVector vecTemp = mVelocity; float vecLength = vecTemp.Normalize(); vecLength -= mFriction * elapsedTime; if (vecLength <= 0.0f) { SetVelocity(AVector::ZERO); } else { SetVelocity(vecTemp * vecLength); } return true; }
//---------------------------------------------------------------------------- AVector InputPushTransformController::GetSmallTransDir() { Movable *movable = DynamicCast<Movable>(mObject); if (!movable) AVector::ZERO; APoint curPos = movable->LocalTransform.GetTranslate(); AVector moveDir = AVector::ZERO; if (curPos.X() < mMinPosSmall.X()) { moveDir.X() = mMinPosSmall.X() - curPos.X(); } if (curPos.Y() < mMinPosSmall.Y()) { moveDir.Y() = mMinPosSmall.Y() - curPos.Y(); } if (curPos.Z() < mMinPosSmall.Z()) { moveDir.Z() = mMinPosSmall.Z() - curPos.Z(); } if (curPos.X()>mMaxPosSmall.X()) { moveDir.X() = mMaxPosSmall.X() - curPos.X(); } if (curPos.Y() > mMaxPosSmall.Y()) { moveDir.Y() = mMaxPosSmall.Y() - curPos.Y(); } if (curPos.Z() > mMaxPosSmall.Z()) { moveDir.Z() = mMaxPosSmall.Z() - curPos.Z(); } return moveDir; }
//---------------------------------------------------------------------------- void WindowApplication3::RotateTrackBall (float x0, float y0, float x1, float y1) { if ((x0 == x1 && y0 == y1) || !mCamera) { // Nothing to rotate. return; } // Get the first vector on the sphere. float length = Mathf::Sqrt(x0*x0 + y0*y0), invLength, z0, z1; if (length > 1.0f) { // Outside the unit disk, project onto it. invLength = 1.0f/length; x0 *= invLength; y0 *= invLength; z0 = 0.0f; } else { // Compute point (x0,y0,z0) on negative unit hemisphere. z0 = 1.0f - x0*x0 - y0*y0; z0 = (z0 <= 0.0f ? 0.0f : Mathf::Sqrt(z0)); } z0 *= -1.0f; // Use camera world coordinates, order is (D,U,R), so point is (z,y,x). AVector vec0(z0, y0, x0); // Get the second vector on the sphere. length = Mathf::Sqrt(x1*x1 + y1*y1); if (length > 1.0f) { // Outside unit disk, project onto it. invLength = 1.0f/length; x1 *= invLength; y1 *= invLength; z1 = 0.0f; } else { // Compute point (x1,y1,z1) on negative unit hemisphere. z1 = 1.0f - x1*x1 - y1*y1; z1 = (z1 <= 0.0f ? 0.0f : Mathf::Sqrt(z1)); } z1 *= -1.0f; // Use camera world coordinates, order is (D,U,R), so point is (z,y,x). AVector vec1(z1, y1, x1); // Create axis and angle for the rotation. AVector axis = vec0.Cross(vec1); float dot = vec0.Dot(vec1); float angle; if (axis.Normalize() > Mathf::ZERO_TOLERANCE) { angle = Mathf::ACos(dot); } else // Vectors are parallel. { if (dot < 0.0f) { // Rotated pi radians. invLength = Mathf::InvSqrt(x0*x0 + y0*y0); axis.X() = y0*invLength; axis.Y() = -x0*invLength; axis.Z() = 0.0f; angle = Mathf::PI; } else { // Rotation by zero radians. axis = AVector::UNIT_X; angle = 0.0f; } } // Compute the world rotation matrix implied by trackball motion. The // axis vector was computed in camera coordinates. It must be converted // to world coordinates. Once again, I use the camera ordering (D,U,R). AVector worldAxis = axis.X()*mCamera->GetDVector() + axis.Y()*mCamera->GetUVector() + axis.Z()*mCamera->GetRVector(); HMatrix trackRotate(worldAxis, angle); // Compute the new local rotation. If the object is the root of the // scene, the new rotation is simply the *incremental rotation* of the // trackball applied *after* the object has been rotated by its old // local rotation. If the object is not the root of the scene, you have // to convert the incremental rotation by a change of basis in the // parent's coordinate space. const Spatial* parent = mMotionObject->GetParent(); HMatrix localRot; if (parent) { const HMatrix& parWorRotate = parent->WorldTransform.GetRotate(); localRot = parWorRotate.TransposeTimes(trackRotate) * parWorRotate * mSaveRotate; } else { localRot = trackRotate*mSaveRotate; } localRot.Orthonormalize(); mMotionObject->LocalTransform.SetRotate(localRot); }
//---------------------------------------------------------------------------- bool InputPushTransformController::Update(double applicationTime, double elapsedTime1) { if (!Controller::Update(applicationTime, elapsedTime1)) return false; float elapsedTime = (float)elapsedTime1; if (mIsPressedValid) { mSampingTiming += elapsedTime; if (mSampingTiming >= 0.03f) { AVector deltaVec = mCurTouchPos - mLastSamplePos; mLastSamplePos = mCurTouchPos; mTouchMoveSpeed = deltaVec / 0.03f; mSampingTiming = 0.0f; } } if (!IsSmallTransScope()) { // 减小速度 AVector vecTemp = mVelocity; float vecLength = vecTemp.Normalize(); vecLength -= mFriction * elapsedTime; if (vecLength <= 0.0f) { SetVelocity(AVector::ZERO); } else { SetVelocity(vecTemp * vecLength); } } else { if (!mIsPressedValid) // 没有按下 { if (0.0f == mSideMoveLength) mSideMoveLength = 1.0f; AVector smallDir = GetSmallTransDir(); if (AVector::ZERO != smallDir) { float moveDirLength = smallDir.Normalize(); float adjuge = moveDirLength / mSideMoveLength; mVelocity += smallDir * mFriction * adjuge * adjuge * elapsedTime; } } else { mVelocity = AVector::ZERO; } } AVector velocityDis = mVelocity*elapsedTime; AVector movedDis; if (IsXY()) { movedDis.X() = velocityDis.X(); movedDis.Y() = velocityDis.Y(); } else { movedDis.X() = velocityDis.X(); movedDis.Z() = velocityDis.Z(); } AVector beforeSmallDir = GetSmallTransDir(); OnMoving(movedDis); if (IsSmallTransScope()) { AVector smallDir = GetSmallTransDir(); if (smallDir == AVector::ZERO && beforeSmallDir != AVector::ZERO) { SetVelocity(AVector::ZERO); } } return true; }
//---------------------------------------------------------------------------- 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; } }
//---------------------------------------------------------------------------- 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); }