سلام
الان سوالت خوب واضح شد.
ببین برای این کار باید ray picking انجام بدی. چون ماوس روی یک محیط 2 بعدی حرکت می کند و محیط تو سه بعدی هست و پس وقتی که کلیک می کنی باید یک خط بسازی که از مکان دوربین تا ته صحنه باشه.
بعد باید این خط رو با یک صفحه برخوردشو حساب کنی.
این کدی هست که یک خط بر اساس ماتریس projection می سازه.
void CalcPickingRay(int x, int y, sn::Camera* pCam)
{
Matrix m = pCam->GetProjectionMatrix();
core::RectI vp = pCam->GetViewPort();
float fx, fy;
fx = (2.0f * x / vp.Width - 1.0f) / m.m_fMat[0];//(vp.Width / 2.0f);//
fy = (-2.0f * y / vp.Height + 1.0f) / m.m_fMat[5];//(vp.Height / -2.0f);//
Position.set(0.0f, 0.0f, 0.0f);
Target.set(fx, fy, 1.0f);
Direction.set(fx, fy, 1.0f);
} // CalcPickingRay
بعد ماتریس view رو می فرستی و این خط رو به فضای دوربین می بری.
void TransformRayInverse(Matrix* mat)
{
mat->Inverse();
mat->TranslateVec(Position);
mat->RotateVec(Target);
mat->TranslateVec(Target);
Direction = Target - Position;
Target = Target + (Direction * 2000.0f);
Direction = Target - Position;
} // TransformRayInverse
این هم کدی هست که برخورد یک خط رو با یک مثلث حساب می کنه می تونی یه صفحه با دو تا مثلث بسازی و مکعبت رو بر روی ان صفحه با حرکت ماوس تکون بدی.
من کد برخورد خط با صفحه رو ننوشتم و بلد هم نیستم ولی راحتتر و سریع تر از برخورد با یک مثلث هست.
//! Checks if the ray and triangle intersects and store the intersection point in the Out parameter.
CollisionType IntersectRay(Ray* pRay, kge::math::Vector& Out)
{
Edge1 = (*Point2) - (*Point1);
Edge2 = (*Point3) - (*Point1);
Normal.Cross(Edge1, Edge2);
float fGama = -(pRay->Direction * Normal);
if (fGama < fEpsilon)
return ECT_NotIntersect;
Vector b = pRay->Position - (*Point1);
float fLanda = (b * Normal) / fGama;
if (fLanda >= 0.0f && fLanda <= 1.0f)
{
Vector u;
u.Cross(b, pRay->Direction);
float u1, u2;
u1 = (Edge2.ToVector() * u) / fGama;
u2 = (-(Edge1.ToVector() * u)) / fGama;
if (u1 + u2 <= 1.0f && u1 >= 0.0f && u2 >= 0.0f)
{
Out = pRay->Position + (pRay->Direction * fLanda);
return ECT_Intersect;
}
}
return ECT_NotIntersect;
} // IntersectRay