//---------------------------------------------------------------------------- void AVector::Orthonormalize (AVector& vec0, AVector& vec1, AVector& vec2) { // If the input vectors are v0, v1, and v2, then the Gram-Schmidt // orthonormalization produces vectors u0, u1, and u2 as follows, // // u0 = v0/|v0| // u1 = (v1-(u0*v1)u0)/|v1-(u0*v1)u0| // u2 = (v2-(u0*v2)u0-(u1*v2)u1)/|v2-(u0*v2)u0-(u1*v2)u1| // // where |A| indicates length of vector A and A*B indicates dot // product of vectors A and B. // Compute u0. vec0.Normalize(); // Compute u1. float dot0 = vec0.Dot(vec1); vec1 -= dot0*vec0; vec1.Normalize(); // Compute u2. float dot1 = vec1.Dot(vec2); dot0 = vec0.Dot(vec2); vec2 -= dot0*vec0 + dot1*vec1; vec2.Normalize(); }
//---------------------------------------------------------------------------- bool Camera::GetPickRay(float posSizePercentWdith, float posSizePercentHeight, APoint& origin, AVector& direction) { // Get the [0,1]^2-normalized coordinates of (x,y). float r = posSizePercentWdith; float u = posSizePercentHeight; // Get the relative coordinates in [rmin,rmax]x[umin,umax]. float rBlend = (1.0f - r)*GetRMin() + r*GetRMax(); float uBlend = (1.0f - u)*GetUMin() + u*GetUMax(); if (IsPerspective()) { origin = GetPosition(); direction = GetDMin()*GetDVector() + rBlend*GetRVector() + uBlend*GetUVector(); direction.Normalize(); } else { origin = GetPosition() + rBlend*GetRVector() + uBlend*GetUVector(); direction = GetDVector(); direction.Normalize(); } return true; }
//---------------------------------------------------------------------------- void PhysicsModule::GetData (APoint& center, HMatrix& incrRot) const { // Position is a point exactly on the hill. APoint position; position[0] = (float)(A1*mState[0]); position[1] = (float)(A2*mState[2]); position[2] = (float)(A3 - mState[0]*mState[0] - mState[2]*mState[2]); // Lift this point off the hill in the normal direction by the radius of // the ball so that the ball just touches the hill. The hill is // implicitly specified by F(x,y,z) = z - [a3 - (x/a1)^2 - (y/a2)^2] // where (x,y,z) is the position on the hill. The gradient of F is a // normal vector, Grad(F) = (2*x/a1^2,2*y/a2^2,1). AVector normal; normal[0] = 2.0f*position[0]/(float)mAux[0]; normal[1] = 2.0f*position[1]/(float)mAux[1]; normal[2] = 1.0f; normal.Normalize(); center = position + ((float)Radius)*normal; // Let the ball rotate as it rolls down hill. The axis of rotation is // the perpendicular to hill normal and ball velocity. The angle of // rotation from the last position is A = speed*deltaTime/radius. AVector velocity; velocity[0] = (float)(A1*mState[1]); velocity[1] = (float)(A1*mState[3]); velocity[2] = -2.0f*(velocity[0]*(float)mState[0] + velocity[1]*(float)mState[2]); float speed = velocity.Normalize(); float angle = speed*((float)mDeltaTime)/((float)Radius); AVector axis = normal.UnitCross(velocity); incrRot = HMatrix(axis, angle); }
//---------------------------------------------------------------------------- void Actor::SetFace(const AVector &dir, const AVector &uping) { AVector right = dir.Cross(uping); right.Normalize(); AVector up = right.Cross(dir); up.Normalize(); Matrix3f matRot(right, dir, up, true); LocalTransform.SetRotate(matRot); }
//---------------------------------------------------------------------------- AVector CurveSegment::Binormal (float u) const { AVector velocity = PU(u); AVector acceleration = PUU(u); float VDotV = velocity.Dot(velocity); float VDotA = velocity.Dot(acceleration); AVector normal = VDotV*acceleration - VDotA*velocity; normal.Normalize(); velocity.Normalize(); AVector binormal = velocity.Cross(normal); return binormal; }
//---------------------------------------------------------------------------- void CurveSegment::GetFrame (float u, APoint& position, AVector& tangent, AVector& normal, AVector& binormal) const { position = P(u); AVector velocity = PU(u); AVector acceleration = PUU(u); float VDotV = velocity.Dot(velocity); float VDotA = velocity.Dot(acceleration); normal = VDotV*acceleration - VDotA*velocity; normal.Normalize(); tangent = velocity; tangent.Normalize(); binormal = tangent.Cross(normal); }
//---------------------------------------------------------------------------- AVector SteeringBehavior::Flee (APoint fromPosition) { AVector desiredVelocity = mActor->GetPosition() - fromPosition; desiredVelocity.Normalize(); return (desiredVelocity - mActor->GetVelocity()); }
//---------------------------------------------------------------------------- bool ShadowMaps::OnInitialize () { if (!WindowApplication3::OnInitialize()) { return false; } // Set up the camera. mCamera->SetFrustum(60.0f, 1.0f, 0.1f, 100.0f); APoint camPosition(8.0f, 0.0f, 4.0f); AVector camDVector = APoint::ORIGIN - camPosition; // look at origin camDVector.Normalize(); AVector camUVector(camDVector[2], 0, -camDVector[0]); AVector camRVector(0.0f, 1.0f, 0.0f); mCamera->SetFrame(camPosition, camDVector, camUVector, camRVector); CreateScene(); // Initial update of objects. mScene->Update(); // Initial culling of scene. mCuller.SetCamera(mCamera); mCuller.ComputeVisibleSet(mScene); InitializeCameraMotion(0.01f, 0.001f); InitializeObjectMotion(mScene); return true; }
//---------------------------------------------------------------------------- void CurveCtrlFloat::OnCtrlChanged (bool updateCurve) { if (mIndex >= (int)(mCurveFloat->mCurve->Points.size())) return; float inVal = mCurveFloat->mCurve->Points[mIndex].InVal; float outVal = mCurveFloat->mCurve->Points[mIndex].OutVal; float arriveTangent = mCurveFloat->mCurve->Points[mIndex].ArriveTangent; float leaveTangent = mCurveFloat->mCurve->Points[mIndex].LeaveTangent; InterpCurveMode mode = mCurveFloat->mCurve->Points[mIndex].InterpMode; mInVal = inVal; mOutVal = Float3(inVal, 0.0f, outVal); AVector at(1.0f, 0.0f, arriveTangent); at.Normalize(); mArriveTangent = at; AVector lt (1.0f, 0.0f, leaveTangent); lt.Normalize(); mLeaveTangent = lt; mInterpCurveMode = mode; CurveCtrl::OnCtrlChanged(updateCurve); }
//---------------------------------------------------------------------------- void EditRenderView_Scene::_RolateCamera(float horz, float vert) { Scene *scene = PX2_PROJ.GetScene(); CameraActor *camActor = scene->GetUseCameraActor(); if (VT_PERSPECTIVE == mViewType) { AVector rVector; AVector dVector; AVector uVector; camActor->GetRDUVector(rVector, dVector, uVector); // horz HMatrix incrH(AVector::UNIT_Z, -horz*0.5f); dVector = incrH * dVector; uVector = incrH * uVector; rVector = incrH * rVector; // vert Matrix3f kIncrV(rVector, -vert*0.5f); dVector = kIncrV * dVector; uVector = kIncrV * uVector; dVector.Normalize(); float dVectorAdj = dVector.Dot(AVector::UNIT_Z); float dVectorAdj1 = dVector.Dot(-AVector::UNIT_Z); if (dVectorAdj > 0.9f || dVectorAdj1 > 0.9f) return; AVector::Orthonormalize(dVector, uVector, rVector); camActor->LocalTransform.SetRotate(HMatrix(rVector, dVector, uVector, AVector::ZERO, true)); } }
AVector SteeringBehavior::Seek (APoint toPosition) { AVector desiredVelocity = mActor->GetPosition() - actorPosition; desiredVelocity.Normalize(); desiredVelocity *= mActor->GetMaxSpeed(); return (desiredVelocity - mActor->GetVelocity()); }
//---------------------------------------------------------------------------- void EU_CanvasStage::_MoveCamera(float horz, float vert) { if (!Project::GetSingletonPtr()) return; Scene *scene = PX2_PROJ.GetScene(); if (!scene) return; if (mStageCameraNode) { APoint position = mStageCameraNode->LocalTransform.GetTranslate(); AVector rVector; AVector dVector; AVector uVector; mStageCameraNode->LocalTransform.GetRDUVector(rVector, dVector, uVector); if (mViewType == VT_PERSPECTIVE) { dVector.Z() = 0.0f; dVector.Normalize(); rVector.Z() = 0.0f; rVector.Normalize(); position += dVector * vert; position -= rVector * horz; } else if (mViewType == VT_TOP) { position.Y() += vert * 1.0f; position.X() -= horz * 1.0f; } else if (mViewType == VT_LEFT) { position.Z() += vert * 1.0f; position.Y() += horz * 1.0f; } else if (mViewType == VT_FRONT) { position.Z() += vert * 1.0f; position.X() -= horz * 1.0f; } mStageCameraNode->LocalTransform.SetTranslate(position); } }
//---------------------------------------------------------------------------- void EditRenderView_Scene::_MoveCamera(float horz, float vert) { Scene *scene = PX2_PROJ.GetScene(); if (!scene) return; CameraActor *camActor = scene->GetUseCameraActor(); if (camActor) { APoint position = camActor->LocalTransform.GetTranslate(); AVector rVector; AVector dVector; AVector uVector; camActor->GetRDUVector(rVector, dVector, uVector); if (mViewType == VT_PERSPECTIVE) { dVector.Z() = 0.0f; dVector.Normalize(); rVector.Z() = 0.0f; rVector.Normalize(); position += dVector * vert; position -= rVector * horz; } else if (mViewType == VT_TOP) { position.Y() += vert * 1.0f; position.X() -= horz * 1.0f; } else if (mViewType == VT_LEFT) { position.Z() += vert * 1.0f; position.Y() += horz * 1.0f; } else if (mViewType == VT_FRONT) { position.Z() += vert * 1.0f; position.X() -= horz * 1.0f; } camActor->LocalTransform.SetTranslate(position); } }
//---------------------------------------------------------------------------- void GamePlayApp::MoveCamera (Camera *cam, const float &horz, const float &vert) { if (!cam) return; Vector3f position = cam->GetPosition(); AVector dVector = cam->GetDVector(); AVector uVector = cam->GetUVector(); AVector rVector = cam->GetRVector(); dVector.Z() = 0.0f; dVector.Normalize(); rVector.Z() = 0.0f; rVector.Normalize(); position += dVector * vert; position += rVector * horz; cam->SetPosition(position); }
//---------------------------------------------------------------------------- AVector Actor::GetFace() { HMatrix matRot = LocalTransform.GetRotate(); HPoint dir; matRot.GetColumn(1, dir); AVector vecDir = AVector(dir[0], dir[1], dir[2]); vecDir.Normalize(); return vecDir; }
//---------------------------------------------------------------------------- bool RenderStep::GetPickRay(float x, float y, APoint& origin, AVector& direction) { if (!mCamera) return false; Rectf viewPort = mViewPort; if (viewPort.IsEmpty()) viewPort = Rectf(0.0f, 0.0f, mSize.Width, mSize.Height); if (viewPort.IsEmpty()) return false; // Get the current viewport and test whether (x,y) is in it. float viewX = viewPort.Left; float viewY = viewPort.Bottom; float viewW = viewPort.Width(); float viewH = viewPort.Height(); // Get the [0,1]^2-normalized coordinates of (x,y). float r = ((float)(x - viewX)) / (float)viewW; float u = ((float)(y - viewY)) / (float)viewH; // Get the relative coordinates in [rmin,rmax]x[umin,umax]. float rBlend = (1.0f - r)*mCamera->GetRMin() + r*mCamera->GetRMax(); float uBlend = (1.0f - u)*mCamera->GetUMin() + u*mCamera->GetUMax(); if (mCamera->IsPerspective()) { origin = mCamera->GetPosition(); direction = mCamera->GetDMin()*mCamera->GetDVector() + rBlend*mCamera->GetRVector() + uBlend*mCamera->GetUVector(); direction.Normalize(); } else { origin = mCamera->GetPosition() + rBlend*mCamera->GetRVector() + uBlend*mCamera->GetUVector(); direction = mCamera->GetDVector(); direction.Normalize(); } return true; }
//---------------------------------------------------------------------------- void AmbientRegionActor::_UpdateDirLightCamera() { AVector dir = AVector::AnglesToDirection(Mathf::DEG_TO_RAD*mHorAngle, Mathf::DEG_TO_RAD*mVerAngle); dir.Normalize(); Scene *scene = DynamicCast<Scene>(GetTopestParent()); if (scene) { EnvirParam *envirParam = scene->GetEnvirParam(); Light *lightDir = envirParam->GetLight_Dir(); Projector *projector = envirParam->GetLight_Dir_Projector(); lightDir->Ambient = Float4(mAmbientColor[0], mAmbientColor[1], mAmbientColor[2], mIntensity); lightDir->Intensity = mIntensity; lightDir->Diffuse = Float4(mDiffuseColor[0], mDiffuseColor[1], mDiffuseColor[2], 1.0f); lightDir->Specular = Float4(mSpecularColor[0], mSpecularColor[1], mSpecularColor[2], mSpecularPow); float upDot = dir.Dot(-AVector::UNIT_Z); if (upDot >= 0.99f) { } else { AVector upTemp = AVector::UNIT_Z; AVector right = dir.UnitCross(upTemp); AVector up = right.UnitCross(dir); lightDir->DVector = dir; lightDir->UVector = up; lightDir->RVector = right; APoint camPos = mLightCameraLookPosition - dir*mLightCameraLookDistance; projector->SetFrame(camPos, lightDir->DVector, lightDir->UVector, lightDir->RVector); } if (!projector->IsPerspective()) { projector->SetFrustum(0.1f, 100.0f, -mLightCameraExtent, mLightCameraExtent, -mLightCameraExtent, mLightCameraExtent); } else { projector->SetFrustum(mLightCameraExtent, 1.0f, 1.0f, 100.0f); } } }
//---------------------------------------------------------------------------- void GamePlayApp::ZoomCamera (Camera *cam, float zoom) { if (!cam) return; Vector3f position = cam->GetPosition(); AVector dir = cam->GetDVector(); dir.Normalize(); position += dir*zoom; cam->SetPosition(position); }
//---------------------------------------------------------------------------- void PushTransformController::SetVelocity (const AVector &vec) { AVector vecTemp = vec; float vecLength = vecTemp.Normalize(); if (vecLength > mMaxVelocity) { vecLength = mMaxVelocity; } mVelocity = vecTemp*vecLength; }
//---------------------------------------------------------------------------- AVector AVector::UnitCross (const AVector& vec) const { AVector cross ( mTuple[1]*vec.mTuple[2] - mTuple[2]*vec.mTuple[1], mTuple[2]*vec.mTuple[0] - mTuple[0]*vec.mTuple[2], mTuple[0]*vec.mTuple[1] - mTuple[1]*vec.mTuple[0] ); cross.Normalize(); return cross; }
//---------------------------------------------------------------------------- void EU_CanvasStage::_RoundCamera(float horz, float vert) { if (!Project::GetSingletonPtr()) return; Scene *scene = PX2_PROJ.GetScene(); if (!scene) return; if (mViewType == VT_PERSPECTIVE) { PX2::Object *obj = PX2_SELECTM_E->GetFirstObject(); bool hasTarget = false; APoint pos; Movable *mov = DynamicCast<Movable>(obj); if (mov) { pos = mov->WorldTransform.GetTranslate(); hasTarget = true; } if (hasTarget) { const APoint &camPos = mStageCameraNode->LocalTransform.GetTranslate(); AVector rVector; AVector dVector; AVector uVector; mStageCameraNode->LocalTransform.GetRDUVector(rVector, dVector, uVector); AVector targetDir = pos - camPos; float targetLength = targetDir.Normalize(); // horz HMatrix incrH(AVector::UNIT_Z, -horz*0.1f); targetDir = incrH * targetDir; dVector = incrH * dVector; uVector = incrH * uVector; rVector = incrH * rVector; HMatrix incrV(rVector, -vert*0.1f); targetDir = incrV * targetDir; dVector = incrV * dVector; uVector = incrV * uVector; APoint newPos = pos - targetDir*targetLength; mStageCameraNode->LocalTransform.SetTranslate(newPos); AVector::Orthonormalize(dVector, uVector, rVector); mStageCameraNode->LocalTransform.SetRotate( HMatrix(rVector, dVector, uVector, AVector::ZERO, true)); } } }
//---------------------------------------------------------------------------- void EditRenderView_Scene::_RoundCamera(float horz, float vert) { Scene *scene = PX2_PROJ.GetScene(); CameraActor *camActor = scene->GetUseCameraActor(); if (mViewType == VT_PERSPECTIVE) { PX2::Object *obj = PX2_SELECTION.GetFirstObject(); bool hasTarget = false; APoint pos; Movable *mov = DynamicCast<Movable>(obj); if (mov) { pos = mov->WorldTransform.GetTranslate(); hasTarget = true; } if (hasTarget) { const APoint &camPos = camActor->LocalTransform.GetTranslate(); AVector rVector; AVector dVector; AVector uVector; camActor->GetRDUVector(rVector, dVector, uVector); AVector targetDir = pos - camPos; float targetLength = targetDir.Normalize(); // horz HMatrix incrH(AVector::UNIT_Z, -horz*0.1f); targetDir = incrH * targetDir; dVector = incrH * dVector; uVector = incrH * uVector; rVector = incrH * rVector; HMatrix incrV(rVector, -vert*0.1f); targetDir = incrV * targetDir; dVector = incrV * dVector; uVector = incrV * uVector; APoint newPos = pos - targetDir*targetLength; camActor->LocalTransform.SetTranslate(newPos); AVector::Orthonormalize(dVector, uVector, rVector); camActor->LocalTransform.SetRotate( HMatrix(rVector, dVector, uVector, AVector::ZERO, true)); } } }
//---------------------------------------------------------------------------- void CameraActor::LookAt(const APoint &pos) { APoint localPos = LocalTransform.GetTranslate(); AVector dir = pos - localPos; float length = dir.Normalize(); if (length > 0.0f) { AVector right = dir.UnitCross(AVector::UNIT_Z); AVector up = right.UnitCross(dir); LocalTransform.SetRotate(HMatrix(right, dir, up, AVector::ZERO, true)); } }
//---------------------------------------------------------------------------- void SurfacePatch::GetFrame (float u, float v, APoint& position, AVector& tangent0, AVector& tangent1, AVector& normal) const { position = P(u, v); tangent0 = PU(u, v); tangent1 = PV(u, v); tangent0.Normalize(); normal = tangent0.UnitCross(tangent1); // The normalized first derivatives are not necessarily orthogonal. // Recompute T1 so that {T0,T1,N} is an orthonormal set. tangent1 = normal.Cross(tangent0); }
//---------------------------------------------------------------------------- void AVector::Orthonormalize (AVector& vec0, AVector& vec1, AVector& vec2) { // 输入的向量为v0,v1,v2,按照下面的方式进行Gram-Schmidt正交化 // // u0 = v0/|v0| // u1 = (v1-(u0*v1)u0)/|v1-(u0*v1)u0| // u2 = (v2-(u0*v2)u0-(u1*v2)u1)/|v2-(u0*v2)u0-(u1*v2)u1| // // |A|代表向量A的长度;A*B代表两个向量“点乘” // 单位化 vec0.Normalize(); // 计算 u1 float dot0 = vec0.Dot(vec1); vec1 -= dot0*vec0; vec1.Normalize(); // 计算 u2 float dot1 = vec1.Dot(vec2); dot0 = vec0.Dot(vec2); vec2 -= dot0*vec0 + dot1*vec1; vec2.Normalize(); }
//---------------------------------------------------------------------------- void InterpCurveSpeedController::_Update (double applicationTime) { InterpCurveFloat3Controller::_Update(applicationTime); if (0.0f >= GetPlayedTimeMinusDelay()) return; const AVector &curValue = GetCurValueRelatived(); float elapsedTime = (float)GetElapsedTime(); AVector dis = curValue * elapsedTime; float disLength = dis.Normalize(); float allLengthTemp = mAllLength; allLengthTemp += disLength; if (mMaxLength >= 0.0f) { if (allLengthTemp >= mMaxLength) { disLength = mMaxLength - mAllLength; mAllLength = mMaxLength; Stop(); } else { mAllLength = allLengthTemp; } Movable* movable = StaticCast<Movable>(mObject); if (movable) { APoint curPos = movable->LocalTransform.GetTranslate() + dis * disLength; movable->LocalTransform.SetTranslate(curPos); } } else { Movable* movable = StaticCast<Movable>(mObject); if (movable) { APoint curPos = movable->LocalTransform.GetTranslate() + dis * disLength; movable->LocalTransform.SetTranslate(curPos); } } }
//---------------------------------------------------------------------------- int FramesMesh::_GetDirIndex(const AVector &dir) { AVector animVec = dir; animVec.Normalize(); AVector up = AVector::UNIT_Y; float dotVal = up.Dot(animVec); float rad = Mathf::ACos(dotVal); float degree = Mathf::RAD_TO_DEG * rad; bool isRight = (dir.X() > 0.0f); if (0 <= degree && degree < 22.5f) { return 0; } else if (22.5f <= degree && degree < 67.5f) { if (isRight) return 1; else return 7; } else if (67.5 <= degree && degree < 112.5f) { if (isRight) return 2; else return 6; } else if (112.5f <= degree && degree < 157.5f) { if (isRight) return 3; else return 5; } else if (157.5f <= degree && degree <= 180.0f) { return 4; } return 0; }
//---------------------------------------------------------------------------- void LODTerrain::Simplify () { if (!mStitched) { StitchAll(); } const Camera *camera = GraphicsRoot::GetSingleton().GetCamera(); APoint worldEye = camera->GetPosition(); AVector worldDir = camera->GetDVector(); APoint modelEye = WorldTransform.GetMatrix().Inverse() * worldEye; AVector modelDir = WorldTransform.GetRotate().Inverse() * worldDir; modelDir.Normalize(); int row, col; for (row=0; row<mNumRows; row++) { for (col=0; col<mNumCols; col++) { LODTerrainPage *page = DynamicCast<LODTerrainPage>( mPages[row][col]); page->ResetBlocks(); } } for (row=0; row<mNumRows; row++) { for (col=0; col<mNumCols; col++) { LODTerrainPage *page = DynamicCast<LODTerrainPage>(mPages[row][col]); if (page->IntersectFrustum(camera)) { modelEye = page->WorldTransform.GetMatrix().Inverse() * worldEye; modelDir = page->WorldTransform.GetMatrix().Inverse() * worldDir; page->Simplify(modelEye,modelDir,mIsCloseAssumption); } } } }
//---------------------------------------------------------------------------- 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; }
//---------------------------------------------------------------------------- // 计算选择射线 //---------------------------------------------------------------------------- bool Renderer::GetPickRay (int x, int y, APoint& origin, AVector& direction) const { if (!mCamera) { return false; } // Get the current viewport and test whether (x,y) is in it. int viewX, viewY, viewW, viewH; GetViewport(viewX, viewY, viewW, viewH); if (x < viewX || x > viewX + viewW || y < viewY || y > viewY + viewH) { return false; } // Get the [0,1]^2-normalized coordinates of (x,y). float r = ((float)(x - viewX))/(float)viewW; float u = ((float)(y - viewY))/(float)viewH; // Get the relative coordinates in [rmin,rmax]x[umin,umax]. float rBlend = (1.0f - r)*mCamera->GetRMin() + r*mCamera->GetRMax(); float uBlend = (1.0f - u)*mCamera->GetUMin() + u*mCamera->GetUMax(); if (mCamera->IsPerspective()) { origin = mCamera->GetPosition(); direction = mCamera->GetDMin()*mCamera->GetDVector() + rBlend*mCamera->GetRVector() + uBlend*mCamera->GetUVector(); direction.Normalize(); } else { origin = mCamera->GetPosition() + rBlend*mCamera->GetRVector() + uBlend*mCamera->GetUVector(); direction = mCamera->GetDVector(); } return true; }