تعلم كيفية تصميم Class لكاميرا سهله ومرنة الاستخدام على طريقة Frank.Luna

الناقل : elmasry | الكاتب الأصلى : time1 | المصدر : www.arabteam2000-forum.com

بسم الله الرحمن الرحيم

اخواني الاعزاء , اقدم لكم اليوم درس حول كيفية تصميم كاميرا على طريقة Frank.Luna

بداية سنقوم بتعريف نوعين من الكاميرا , وهي AirCraft والتي تسمح للمستخدم التحرك والانتقال بكل حرية داخل فضاء المشهد وتستخدم في الالعاب التي تحاكي الطيران , وLandObject والتي تحاكي الانتقال المقيد وهي مفيدة وتستخدم في ألعاب الرماية واطلاق الرصاصات ...إلخ

الخطوة رقم 1


نبدأ الـClass بتعريف نوعين من الكاميرا ,

        enum CameraType{AirCraft,LandObject};


يتم تعريف الكاميرا من خلال ثلاثة متجهات , Right,Up,Look
واخيرا نقوم بتعريف متجه يحدد لنا موضع الكاميرا Pos

ارفق صورة : monthly_10_2008/post-82612-1224201077.jpg

وتحديد القيم هذه جميعا سنقوم بها من خلال الباني حيث سياخذ وسيط واحد يقوم بتحديد نوع الكاميرا وبعدها يقوم بإعطاء القيم للمتجهات


Camera::Camera(CameraType t)
{
        Type=t;

        Pos=D3DXVECTOR3(0.0f,1.0f,10.0f);
        Look=D3DXVECTOR3(0.0f,0.0f,-1.0f);
        Right=D3DXVECTOR3(-1.0f,0.0f,0.0f);
        Up=D3DXVECTOR3(0.0f,1.0f,0.0f);
}






الخطوة رقم 2 : تكوين مصفوفة العرض

مصفوفة العرض ستكون على الشكل التالي :

ارفق صورة : monthly_10_2008/post-82612-1224201105.jpg

ولتحقيق ذلك سنقوم بالخطوات التالية :

1- تنظيم المتجهات وجعلها متعامدة:

نقوم بتنظيم متجه وضربه ضرب اتجاهي مع متجه اخر ونعلم عندها بأن ناتج هذه العملية سيكون متجه ثالث عمودي على المتجهين , نقوم بتنظيم المتجه الناتج ونكرر الخطوة على المتجهات الاخرى .

        D3DXVec3Normalize(&Look,&Look);
        D3DXVec3Cross(&Up,&Look,&Right);
        D3DXVec3Normalize(&Up,&Up);
        D3DXVec3Cross(&Right,&Up,&Look);
        D3DXVec3Normalize(&Right,&Right);


2- نوجد الانسحاب من خلال p- لانه p-p=0 للموقع pos

        float x=-D3DXVec3Dot(&Right,&Pos);
        float y=-D3DXVec3Dot(&Up,&Pos);
        float z=-D3DXVec3Dot(&Look,&Pos);


3- نكون بعدها المصفوفة على الشكل السابق:

(*V)(0,0)=Right.x;(*V)(0,1)=Up.x;(*V)(0,2)=Look.x;(*V)(0,3)=0;
(*V)(1,0)=Right.y;(*V)(1,1)=Up.y;(*V)(1,2)=Look.y;(*V)(1,3)=0;
(*V)(2,0)=Right.z;(*V)(2,1)=Up.z;(*V)(2,2)=Look.z;(*V)(2,3)=0;
(*V)(3,0)=              x;(*V)(3,1)=   y;(*V)(3,2)=             z;(*V)(3,3)=1;



الخطوة رقم 3 :الدوران حول المحاور

وهناك ثلاثة انواع من الدوران وهي :
Pitch : الدوران حول محور Right
Yaw: الدوران حول محور Up
Roll: الدوران حول محور Look




اولا الدوران نحو اليمين Pitch

نقوم بكتابة التابع الذي يمثل لنا الدوران حول اليمين Pitch وذلك من خلال الدوران حول محور Right باستخدام التابع D3DXMatrixRotationAxis والذي يأخذ الوسيط الاول مصفوفة الدوران والثاني الشعاع او المتجه المراد الدوران حوله والثالث مقدار الدوران .

بعد ذلك نجري التحويل على المتجهات الاخرى كما يلي :
        D3DXMATRIX T;
        D3DXMatrixRotationAxis(&T,&Right,angle);

        D3DXVec3TransformCoord(&Look,&Look,&T);
        D3DXVec3TransformCoord(&Up,&Up,&T);


ارفق صورة : monthly_10_2008/post-82612-1224201146.jpg

ثانيا الدوران حول محورUp والذي يسمى Yaw


وهو مشابه للسابق باختلاف اننا سنضع قيدا على الكاميرا LandObject كما يلي

        D3DXMATRIX T;
        if(Type==LandObject)
                D3DXMatrixRotationY(&T,angle);
        else
                D3DXMatrixRotationAxis(&T,&Up,angle);

        D3DXVec3TransformCoord(&Right,&Right,&T);
        D3DXVec3TransformCoord(&Look,&Look,&T);


ثالثا الدوران حول محور Look والذي يسمى Roll


هذا الدوران فقط اذا كانت الكاميرا AirCraft وهو ايضا مشابه لسابقيه , كما يلي :


        D3DXMATRIX T;
        if(Type==AirCraft)
        {
                D3DXMatrixRotationAxis(&T,&Look,angle);

                D3DXVec3TransformCoord(&Up,&Up,&T);
                D3DXVec3TransformCoord(&Right,&Right,&T);
        }



الخطوة رقم 4 :المشي والطيران

اولا المشي Walk

يتم التعامل هنا في هذه الخطوة بأكملها مع المتجه Pos ( موضع الكاميرا ) فعلى سبيل المثال , اذا كانت الكاميرا AirCraft وكنا نرغب بالتقدم او المشي بمقدار Z فأننا سنقوم بضرب المتجه Look في المقدار z ونجعل المتجه Pos يساوي Pos+حاصل الضرب .

        if(Type==AirCraft)
                Pos+=Look*z;
        else
                Pos+=D3DXVECTOR3(Look.x,0.0f,Look.z);


اما اذا كانت الكاميرا LandObject عندها كما رأينا فأننا نفرض قيد على الكاميرا بعدم التحرك بحرية في الفضاء عند المشي وانما تبقى مسايرة للارض .

ثانيا الطيران :

كذلك الامر في الطيران فأن الكاميرا AirCraft تأخذ الحرية في الطيران والتحليق في الفضاء , بينما الكاميرا LandObject فالطيران يمثل الارتفاع فقط .

        if(Type==AirCraft)
                Pos+=Up*u;
        else
                Pos.y+=u;





واخيرا سنقوم بعرض الكود كاملا :


class Camera
{
public:
        enum CameraType{AirCraft,LandObject};
        Camera(CameraType);
        void Set_Camera(CameraType);
        void Set_VeiwMatrix(D3DXMATRIX *V);
////////////////////////////////////////////
        void Pitch(float);
        void Yaw(float );
        void Roll(float);
/////////////////////////////////////////
        void Walk(float);
        void Fly(float);
        void Strafe(float);
private:
        D3DXVECTOR3 Pos;
        D3DXVECTOR3 Look;
        D3DXVECTOR3 Right;
        D3DXVECTOR3 Up;
        CameraType Type;
};


Camera::Camera(CameraType t)
{
        Type=t;

        Pos=D3DXVECTOR3(0.0f,1.0f,10.0f);
        Look=D3DXVECTOR3(0.0f,0.0f,-1.0f);
        Right=D3DXVECTOR3(-1.0f,0.0f,0.0f);
        Up=D3DXVECTOR3(0.0f,1.0f,0.0f);
}

void Camera::Set_Camera(CameraType t)
{
        Type=t;
}

void Camera::Set_VeiwMatrix(D3DXMATRIX *V)
{
        D3DXVec3Normalize(&Look,&Look);
        D3DXVec3Cross(&Up,&Look,&Right);
        D3DXVec3Normalize(&Up,&Up);
        D3DXVec3Cross(&Right,&Up,&Look);
        D3DXVec3Normalize(&Right,&Right);
///////////////////////////////////////////////
        float x=-D3DXVec3Dot(&Right,&Pos);
        float y=-D3DXVec3Dot(&Up,&Pos);
        float z=-D3DXVec3Dot(&Look,&Pos);
///////////////////////////////////////////////
(*V)(0,0)=Right.x;(*V)(0,1)=Up.x;(*V)(0,2)=Look.x;(*V)(0,3)=0;
(*V)(1,0)=Right.y;(*V)(1,1)=Up.y;(*V)(1,2)=Look.y;(*V)(1,3)=0;
(*V)(2,0)=Right.z;(*V)(2,1)=Up.z;(*V)(2,2)=Look.z;(*V)(2,3)=0;
(*V)(3,0)=              x;(*V)(3,1)=   y;(*V)(3,2)=             z;(*V)(3,3)=1;

}

///////////////////////////////////////////////////////////////

void Camera::Pitch(float angle)
{
        D3DXMATRIX T;
        D3DXMatrixRotationAxis(&T,&Right,angle);

        D3DXVec3TransformCoord(&Look,&Look,&T);
        D3DXVec3TransformCoord(&Up,&Up,&T);
}

void Camera::Yaw(float angle)
{
        D3DXMATRIX T;
        if(Type==LandObject)
                D3DXMatrixRotationY(&T,angle);
        else
                D3DXMatrixRotationAxis(&T,&Up,angle);

        D3DXVec3TransformCoord(&Right,&Right,&T);
        D3DXVec3TransformCoord(&Look,&Look,&T);
}

void Camera::Roll(float angle)
{
        D3DXMATRIX T;
        if(Type==AirCraft)
        {
                D3DXMatrixRotationAxis(&T,&Look,angle);

                D3DXVec3TransformCoord(&Up,&Up,&T);
                D3DXVec3TransformCoord(&Right,&Right,&T);
        }
}

void Camera::Walk(float z)
{
        if(Type==AirCraft)
                Pos+=Look*z;
        else
                Pos+=D3DXVECTOR3(Look.x,0.0f,Look.z);
}

void Camera::Fly(float u)
{
        if(Type==AirCraft)
                Pos+=Up*u;
        else
                Pos.y+=u;

}




واخيرا , تستطيع التعديل على الClass السابق كما تشاء وابتكار انواع جديدة من الكاميرات مناسبة لاحتياجاتك , لتكون في النهاية كاميرا تخدم لعبتك بشكل مناسب كما في الصورة :

ارفق صورة : monthly_10_2008/post-82612-1224201872.jpg

,اتمنى ان اكون قد وفقت في هذا الدرس ,

تمنياتي لكم بالتوفيق ..