المساعد الشخصي الرقمي

مشاهدة النسخة كاملة : دروس للمحرك الخارق Ogre على C++



modyKun
08-07-2009, 03:36 PM
السلام عليكم ورحمة الله وبركاته ..
هذا الموضوع بإذن الله متجدد .
وهو لدروس محرك Ogre من كتابتي ، المحرك الذي يجمع بين القوة والسهولة ، فهو يستغل التقنيات الحديثة لبطاقة الجرافكس بشكل رائع .

ملاحظة مهمة : الموضوع من كتابة modyKun واسمي الآخر mody-san يمنع النقل بتاتاً إلا مع ذكر المصدر وكاتب الموضوع ، وسوف أقوم بتتبع الموضوع ، ومن ينقله من دون هذا السطر فلن أتساهل معه ، شكراً.

نبذة عن المحرك:
محرك الأوغر (OGRE) هو محرك يمتاز بقوة الجرافكس وسهولة التعامل ، ويعني اسمه :
Object-Oriented Graphics Rendering Engine أو بالعربية محرك إظهار الجرافكس كائني التوجه ، يعد المحرك من أشهر المحركات مفتوحة المصدر المعروفة عالمياً، المحرك هو SDK تحمل بالـC++ ،وبالتالي البرمجة كلها بالـC++ ، ولكن لا داعي للخوف .


من يجب عليه أن يأخذ هذه الدورة؟:
لازم تكون جاد ..و يجب أن يكون لديك أولاً خبرة ولو لشهر في الـC++ .. وركز بالذات على البوينتر والفنكشن والكلاسات والجمل الشرطية..
ومن ثم بعدها تستطيع البدء ( ملاحظة:قريباً بإذن الله سوف أقوم بإصدار الدروس لمن لم يتعلموا الـC++ .. حيث أشرح جزئية من الـC++ ومعها جزئية من الأوغر)..

ما مدى صعوبة الأوغر؟:
حسناً .. لا أعرف لماذا نهرب بعيداً كلما سمعنا بالـC++ ؟ ..أنا لم أمضي الكثير من الوقت في تعلمها..
كمبرمج ألعاب .. يجب أن تتعلم الـC++ لأنها أساس الألعاب ، من أصغر شركة لأكبر شركة في برمجة الألعاب تتعامل معها يومياً ^^ ..ليس هناك ما تخاف منه ..
بالنسبة للأوغر .. فهو سهل جداً ^^ .. بضمان مني شخصياً ^^..


صور/ فيديو لقدرات أوغر:
فيديو الديمو لمحرك أوغر
- http://www.youtube.com/watch?v=woHZRUlOQqo

فيديو لعبة بأوغر
- http://www.youtube.com/watch?v=6fAaC6nyd5o
فيديو لعبة Torchlight .. لعبة مشهورة مبرمجة بأوغر .. حتى أنها ظهرت بـE3
http://www.youtube.com/watch?v=NhrNZZf-dOk

صور متنوعة :
http://farm4.static.flickr.com/3308/3263243817_e8f514a919_o.jpg

http://farm1.static.flickr.com/191/3264152654_1e7933fbf3_o.jpg

أعتقد قوة الأوغر إتضحت الآن :) ..

التحميل:
البيئة التي سنستخدمها بإذن الله في الدروس هي Visual C++ .. لكن يمكنك استخدام ما تريد
مثل Code::Blocks أو غيره ،، لكن البرمجة على الفيجوال تريحك من الهم ^^(رأيي)

ككل .. يمكنك تحميل الـVisual C++ من هنا:
http://www.microsoft.com/express/vc/

ثم يمكنك تحميل الـOgre SDK من هنا(اختر الاصدار المناسب لبيئة برمجتك ،
لو حملت Visual C++ من الرابط فوق حمل الإصدار آخر واحد من فوق - للفيجوال التاسع) :
http://www.ogre3d.org/download/sdk

وحبذاً لو حملت الـAppWiz الخاص بالفيجوال سي++ .. لتسهيل عملية عمل مشروع :
http://developer.berlios.de/project/showfiles.php?group_id=3423

سيتم وضع الدرس الأول بعد قليل في الرد القادم بإذن الله

modyKun
08-07-2009, 04:52 PM
ملاحظة 1 :سيتم قريباً بإذن الله عمل دروس لمن لم يقوموا بتعلم سي++ ، حيث يتم طرح جزئية من سي++ و جزئية من أوغر .. أما الآن فسنبدأ بالدورة التي تستهدف متقني سي++ ..
ملاحظة 2 : رابط الـAppWiz (وهو ضروري) في الرد الماضي وضعته خطأ (أتمنى من المشرفين تعديله لأنه مهم بدرجة عالية .. فمن دونه سيضطر الشخص إلى تعديل الـCompiler بشكل يدوي للتعامل مع الأوغر).. كنت أقصد هذا الرابط :
http://sourceforge.net/projects/ogreconglo/files/

ملاحظة 3 : أي سؤال أو استفسار ، ستجدوني بإذن الله حاضر في صالة المجموعة على المسنجر ^_^ ، أرحب بأي استفسار هناك ! وشكراً !

بسم الله الرحمن الرحيم
--
الدرس الأول - رسم كائن على الشاشة

ملاحظة مهمة عن الدرس : في هذا الدرس وقبل أن نتعلم كيفية إعداد الشاشة ، الخ ، فإننا سوف نستخدم ExampleApplication ..وهو أبلكيشن جاهز يقوم بإعداد الشاشة وتجهيزها للرسم ، وكما نرى لدين ميثود createScene والتي هي أساساً تابعة له ، وسوف نتعلم بإذن الله في درس لاحق كيفية إعداد الشاشة بأنفسنا . وشكراً.قم بعمل مشروع أوغر جديد من نوع Standard application
في السورس (الملف الذي يحتوي على .cpp )
قم بتبديل الكود الموجود فيه باللآتي :

#
include "ExampleApplication.h"

class TutorialApplication : public ExampleApplication
{
protected:
public:
TutorialApplication()
{
}

~TutorialApplication()
{
}
protected:
void createScene(void)
{
}
};

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"

INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
int main(int argc, char **argv)
#endif
{
// Create application object
TutorialApplication app;

try {
app.go();
} catch( Exception& e ) {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
MessageBox( NULL, e.what(), "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
fprintf(stderr, "An exception has occurred: %s\n",
e.what());
#endif
}

return 0;
}


أولاً لدينا ثلاث كلاسات رئيسية في الأوغر ..

1-SceneManager :
السيين ماناجير هو أساس الأوغر =) .. وهو الذي يمكن من خلاله فعل الأشياء الأساسية فيه
ولا يمكن أن يمر شئ إلى الذاكرة إلا بعد أن يمر من على الـSceneMgr
فأي كائن يتم تفقده من قبل الـSceneManager وأي كاميرا ، الخ =)
ويوجد أكثر من SceneManager للمهمات المختلفة .

2-Entity :
الـEntity هي عبارة عن أي شئ يرسم .. بمعنى أصح أي كائن ثلاثي/terrain ،، الخ .

3- SceneNode :
السيين نوود هي عبارة عن "حامل مواقع واتجاهات" ، وهو يحدد مكان رسم الكائن ، فلك أن تتخيل أن عالم اللعبة هو عالم بداخله ثلاث محاور X,Y,Z
ويتم وضع أي Entity فيه عن طريق تحديد إحداثي له ، ولا يتم رسم هذا الـEntity إلا بعد عمل Attach للـEntity إلى SceneNode ،،
بمعنى أصح ..ربما يمكننا تبسيط الأمر بأنك "تلصق" الـEntity في الـSceneNode (الموقع المحدد)
ونلاحظ أنه يمكن إلصاق أكثر من Entity وإضاءة وهكذا.. في نفس الموقع ، مثلاً يمكنك وضع مجسم في موقع ومعه ضوء في نفس الموقع ليضئ له المشهد .
ويلحظ أن الـSceneMgr يحتوي على SceneNode رئيسية ، وهي الـSceneNode التابعة لعالم اللعبة ، ولعمل SceneNode فيجب أن تقوم
بجعلها Child أو تابعة للسيين نوود الأولى =) لماذا؟ لأن السيين نوود الرئيسية تمثل نظام الإحداثيات في عالم اللعبة ، لذا فهي
الرابط الذي سيجمع كل الإحداثيات في اللعبة .. نقطة أخيرة عن الـSceneNode ، هي أنه يمكنك عمل أي عدد تريده من السيين نوودز التابعة(Child)
لأي سيين نوود فتصبح متحكم بها (Parent ) ، بمعنى أصح حينها نفترض عندنا سيين نوود إسمها A و أخرى B .. وB تابعة لـA .. حينها لو تم تحريك A في أي إتجاه فستتحرك B معها .. عادة تستخدم هذه التقنية إن أردت مثلاً الشخصية أن تحمل سكيناً فتجعلها في موضع مناسب مع السكين وتجعلها متحكمة في السكين


--
على كل =) الآن بدأ التطبيق..


إعثر على ميثود createScene .. وقم بوضع هذا الكود بداخلها في أول سطر :

mSceneMgr->setAmbientLight( ColourValue( 1, 1, 1 ) );
هذا سيمرر إلى ميثود setAmbientLight التابعة للسيين منجر قيمة لونية .. حيث أن الـAmbientLight هو الضوء العام في المشهد
لاحظ أيضاً أن الميثود تأخذ قيمة لونية يمكن حسابها من خلال ميثود ColourValue .. وهنا اعطتها قيمة (1،1،1)
حيث أن القيمة يتم حسابها بـR,G,B أو Red , Green,Blue إذاً أول قيمة تأخذها الميثود هي الأحمر والثانية الأخضر والثالثة الأزرق
وهي قيمة بين 0 و 1 .. لتحديد كمية اللون

بعد ذاك السطر .. أدخل السطر التالي :

Entity *ent1 = mSceneMgr->createEntity( "Robot", "robot.mesh" );
هنا نقوم بعمل مؤشر من نوع Entity ونسميه ent1 .. ونساويه بالقيمة التي سترجعها ميثود createEntity التي داخل الـmSceneMgr (شفت لما قلت
إن كل شئ لازم يمر على السيين منجر؟ :) ) على كل ميثود createEntity تقوم بإرجاع كائن ^^ .. وتأخذ قيمتين الأولى إسم و هو اسم عشوائي تسميه لها
وقد اخترنا هنا Robot ، ومكان ملف الكائن ، والملف موجود مع الـExampleApplication اللي نستخدمها واسمه robot.mesh (صيغته .mesh )
على كل المؤشر ent1 سوف يحتفظ بموقع الكائن بالذاكرة ^^

بعدها السطر التالي :

SceneNode *node1 = mSceneMgr->getRootSceneNode()->createChildSceneNode( "RobotNode" );
وهو هنا سننشئ مؤشر SceneNode بإسم node1 ..
على الطرف الآخر يمكنك أن تفهم ما كنت أقصده بإنشاء سيين نوود تابعة للسين الأصلي ^^ .. سأفصلها بالآتي :
أولاً يتم إستدعاء ميثود getRootSceneNode وهي ترجع الـSceneNode الـRoot أو الأصلية ^^ .. التي موجودة داخل كلاس mSceneMgr
ومن هنا يتم إستدعاء ميثود createChildSceneNode والتي ستقوم بعمل childSceneNode أي سيين نوود تابعة للسيين نوود الأصلية =) و
القيمة التي تأخذها هي اسم للسيين نوود الجديدة .. وهنا سميناها RobotNode سهلة صح ؟ ^^
على العموم المؤشر اللي حطيناه بيحتفظ بعنوان هاي السيين نوود في الذاكرة^^

الخطوة الأخيرة ^^ هي إضافة هذا السطر :

node1->attachObject( ent1 );
المؤشر node1 تتبعه ميثود attachObject والتي تربطه بكائن ^^ .. بمعنى أصح سيتم لصق الكائن المختار في موقع السيين نوود المختارة ..
لنعلن أن ent1 ستتحكم بها node1 =) وبهذا الكود الأخير .. سيقوم برسم الكائن على الشاشة في الموقع الذي حددناه =) ..
ولكننا لم نحدد أي موقع ^^ .. تماماً .. إذا فسيقوم بوضع الكائن في الموضع الـDefault ..أي نقطة الأصل .. (0،0،0) ^^
ونلاحظ أن attachObject هو الأمر الذي عندما يكتب سيتم رسم الكائن =)

حسناً ، يمكننا أن نعطي الآن مثالاً على كيفية وضع الكائن مع موقع محدد .. ضع هذا الكود بعد الكود الأول :

Entity *ent2 = mSceneMgr->createEntity( "Robot2", "robot.mesh" );
SceneNode *node2 = mSceneMgr->getRootSceneNode()->createChildSceneNode( "RobotNode2", Vector3( 50, 0, 0 ) );
node2->attachObject( ent2 );
يمكننا ملاحظة أن الفرق هنا هو أننا أعطينا لميثود createChildSceneNode قيمة ثانية (وهذه صيغة أخرى للميثود) ..
حيث في هذه الصيغة تأخذ قيمتين إسم وموقع
ونلاحظ أن قبل الموقع يكتب Vector3 ، والفكتور3 هو اسم نظام الاحداثيات الذي يتكون من X,Y,Z ^^ ..
على كل الكود الثاني سيضع الكائن الجديد بإحداثي 0 على محور Y و Z .. لكن بإحداثي 50 على محور X ^^ وبهذا سيكون الكائن الجديد على بعد 50 وحدة طول
عن نقطة الأصل =)
أتمنى الدرس أفاد ^^ .. ولنا لقاء آخر..

ملاحظة : يسمح بالرد حيث هنا سيختلط الدرس بالأسئلة ^^ .. وأرجو لمن واجهته المشاكل أن يدخل على مجموعة المسنجر وأنا حاضر ..
والتي تجدونها هنا :
http://www.montada.com/showthread.php?t=637776
ومجدداً ^^ إن لم تستطع أو أنا لم أكن موجوداً .. فاترك سؤالك هنا ^^..

alkhattab
08-07-2009, 08:32 PM
أكمل ونحن معك
لكن هل يمكن تطبيق الدروس على برنامج التيربو سي ++
أو أي كومبايلر من إصدار شركة بورلاند ؟
وهل يحتاج لتنصيب المكتبة ؟؟؟

modyKun
08-07-2009, 10:00 PM
أشكرك أخي عمر ^_____^ وسعيد تكون أول متابع معنا في الموضوع ^^
بالنسبة لسؤالك فلا اعتقد ان هناك مكتبة متوفرة لـCompiler بورلاند ^^ ..شخصياً أفضل الفيجوال سي++ ^^ أسهل شئ في عملية البرمجة ..

ننتظر تفاعلكم معنا ^_^ .. وأي سؤال أنا حاضر، شكراً.
+
في خطأ قاتل عملته هنا >< .. سميت الفنكشن ميثود مع إننا في C++ ، في كثير لغات تسميها
ميثود لكن في السي++ اسمها فنكشن مع ان ما في فرق .. بسبب تعودي على السي شارب لفترة سميتها ميثود XD ..
مب مهم ^^ خيرها في غيرها..
الدرس الثاني قريباً بإذن الله ^_^

رجل المخاطر
08-07-2009, 10:41 PM
بسم الله الرحمن الرحيم


رائع، ممتاز، مذهل ^_^

اشكرك اخي محمود على الدروس الذهبية ...

ان شاء الله من المتابعين اولا بأول لدروسك ^_^

جاري تطبيق الدرس الثاني، بانتظار المزيد ^_^

kakarot
08-07-2009, 11:45 PM
هل يلزم أن أكون عندي خلفية في ++C ؟؟

انا عندي خلفية في VB ولكن ليست جيدة كثيرة

يعني ما بقدر اتابعك إلا لما أدرس ++C ؟؟


شكراً

modyKun
08-07-2009, 11:49 PM
أشكرك عزيزي رجل المخاطر ^^ ، شرف لي .
و تفضحنا عشان عطيتك الدرس الثاني قبلهم هاه XD بيقولون واسطة :p ..
..
وأخي كاكاروت ^_^ في الواقع نعم ، تحتاج إلى خلفية عن الـC++ ، ولكن لا تخف المحرك
نفسه بسيط، بإذن الله قريباً سيكون هناك كم درس بسيط لإدخالك للسي++ ^^
--
حسناً ^^ أقدم الآن الدرس الثاني ..هناك عدة معلومات بسرعة ..
ملحوظة 1 : نظام الإحداثيات Vector3 والمكون من المحاور X,Y,Z إن لم يعرفه أحد ^^ فهو في الهندسة الفراغية ( س، ص، ع) وببساطة كل محور يتجه إلى إتجاه والإحداثي الذي تدخله سوف يشير إلى نقطة.
ملحوظة 2 : إلى الآن نحن نستخدم الموديلات الجاهزة القادمة مع محرك الأوغر ^^ ، مع العلم الأوغر يستخدم صيغة خاصة للموديلات هي .mesh ، هناك مصدرات خاصة للماكس والمايا والـXSI ،الخ للتصدير إلى هذه الصيغ .
ملحوظة 3 : حينما تصنع مشروع أوغر جديد ، فإنه وبشكل تلقائي يقوم بإضافة كود تحكم بالكاميرا بواسطة الكيبورد والفأرة بملف الهيدر ، أيضاً يقوم بإظهار كلمة "OGRE" و فاحص لحالة اللعبة في أسفل الشاشة ، أيضاً شاشة إعدادات قبل بدء اللعبة ولكن بالطبع يمكن إلغاء ذلك كله بالتعديل على كود الهيدر وهو شئ سنتطرق إليه لاحقاً في درس
ملحوظة 4 : سيتم عمل درس سريع لاساسيات السي++ لاحقاً بإذن الله . وهذا بدل تفسير كود السي++ المستخدم في الدروس
ملحوظة 5 : أشكر نقل الموضوع إلى قسم المواضيع المميزة ^^ هذا شرف لي .
----
بسم الله الرحمن الرحيم
الدرس الثاني -(الكاميرا / الظل / الإضاءة)

في البداية ، الكاميرا والظل والإضاءة من أهم عناصر برمجة الألعاب ، وهي جزء أساسي لا يتجزأ من اللعبة ، فمن دون الكاميرا لن يكون لدينا نقطة نرى منها المشهد ، والإضاءة تعطي واقعية على المشهد وتسمح لك بتحديد ما تريد
لللاعب أن يراه من المشهد ، والظل يعطي أيضاً واقعية على المشهد .

قم بعمل مشروع جديد واطلق عليه الاسم الذي تريد (لا تنسى أن تختار Standard Application ) .. ثم قم بإلصاق الكود التالي في ملف السورس (.cpp)


#include "ExampleApplication.h"

class TutorialApplication : public ExampleApplication
{
protected:
public:
TutorialApplication()
{
}

~TutorialApplication()
{
}
protected:
virtual void createCamera(void)
{
}

virtual void createViewports(void)
{
}

void createScene(void)
{
Entity *ent;
Light *light;
}
};

#if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"

INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
int main(int argc, char **argv)
#endif
{
// Create application object
TutorialApplication app;

try {
app.go();
} catch( Exception& e ) {
#if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32
MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
fprintf(stderr, "An exception has occurred: %s\n",
e.getFullDescription().c_str());
#endif
}

return 0;
}

الكاميرات :-

الكاميرا كما ذكرنا مسبقاً هي عين اللاعب على العالم ، ربما تخيل أن هناك حقاً عالم في اللعبة ، ستقوم هذه الكاميرا بتصوير المشهد ونقله لشاشتك ، طبعاً هناك Functions للكاميرا .. مثل setPosition لاختيار موقع للكاميرا وهناك Yaw و Pitch و Roll للتدوير (موجودين أيضاً بالسيين نوود) ، وهي محاور التدوير الثلاثة .. يمكنك رؤيتها في الرابط التالي:
http://www.ogre3d.org/wiki/images/d/d5/YawPitchRoll_5b_200px.png
كما نضيف أيضاً أنه يمكنك ربط الكاميرا بـSceneNode مع أنه كما هو واضح فبها خصائص السيين نوود ، لكن ربما مثلاً يمكنك إن أردت عمل لعبة FPS أن تربطها بنفس SceneNode المربوط بها موديل اللاعب

كفانا حديثاً ولنبدأ العمل.. ابحث عن فنكشن createCamera التي توفرها لنا الـExampleApplication ..
ومن ثم أدخل السطر التالي لكي نقوم بعمل أول كاميرا لنا :


mCamera = mSceneMgr->createCamera("PlayerCam");

لقد قمنا باستخدام فنكشن createCamera والتي تأخذ براميتر اسم لهذه الكاميرا ، وبالتالي أصبح لدينا كاميرا واسم لها .
مع العلم ، إن لم تكن لديك رغبة في استخدام بوينتر لتخزين الكاميرا ، فيمكنك استخدام فنكشن getCamera الموجود في SceneMgr وكل ما يطلب منك كتابة الاسم
وهذه هي فائدة الاسم على كل حال .

سنقوم بالسطرين التاليين اسناد موقع للكاميرا وموقع للنظر إليه

mCamera->setPosition(Vector3(0,10,500));
mCamera->lookAt(Vector3(0,0,0));ببساطة فنكشن setPosition ستحدد موقع الكاميرا وكالعادة فإنها تأخذ قيمة Vector3 ..

الجديد لدينا فنكشن lookAt .. lookAt سوف تقوم بتحديد موقع "تواجهه" الكاميرا ، بمعنى أصح ، الكاميرا سوف تنظر إلى الموقع الذي تحدده ، طبعاً لن تتوقف الكاميرا هناك وستعرض
ما خلف ذلك ، فهي ستعرض ما يوجد في إتجاه ذلك الموقع
وللعلم فنكشن lookAt موجودة بالسيين نوود ، لذا فالكاميرا هنا لا تنفرد بها .
الأمر التالي الذي سوف نحدده هو الـNear Clip Distance


mCamera->setNearClipDistance(5);

ببساطة ، هنا سوف تحدد بعد عن الكاميرا ، وسوف نضعه بـ5 مثلاً ، إن اقترب مجسم من الكاميرا مسافة أكثر من 5 وحدات
فإنه سوف يختفي ، لماذا نفعل ذلك؟ لكي نسهل رؤية المشهد ، تصور أنك اقتربت من مجسم كثيراً فإنه سوف يقوم بحجب الشاشة ولن يصبح بمقدورك رؤية ما خلفه .
جدير بالذكر أيضاً أن هناك فنكشن setFarClipDistance وهي تستخدم لوضع بعد عن الكاميرا إن ابتعد عنه أي مجسم فإنه سوف يختفي ، تستخدم هذه التقنية للتخفيف من
الحمل التي تلقيه اللعبة على عاتق المعالج ، ونحن لم نستخدمها لأنه لا يمكن استخدامها مع ظل الـStencil Additive ..والذي بإذن الله سوف نقوم بإستخدامه في هذا الدرس


الـViewport :-
يعمل الـOgre حينما يتم اظهار الكائنات بطريقة منظمة .. الكاميرات تلتقط المشهد(بالأحرى تقوم بالحسابات) ، ومن ثم تقوم بنقل المشهد إلى الـViewport .. والتي هي موجودة في الـRenderWindow ..
ولدينا هنا عدة مفاهيم جديدة ،
الفيوبورت هي قطعة الشاشة التي يظهر فيها المشهد ، من الممكن أن تقوم بعمل أكثر من كاميرا كلٌ منها يصور أمراً ما .. وتقسم الشاشة (مثل ألعاب سباق السيارات في نمط
اللاعبين المتعددين مثلاً) ..في هذه الحالة كل قسم من الشاشة سوف يعتبر Viewport منفرد .. والـRenderWindow هي النافذة نفسها التي تضم الـViewport الوحيدة ..
أو الـViewports المتعددة .. بمعنى أصح عادة ما ستقوم ببرمجة الكاميرا بحيث تنقل الصورة إلى كامل الـRenderWindow وبالتالي سيكون لديك Viewport واحدة ..

فالنعثر إذاً على فنكشن createViewports .. واضف هذا السطر :

Viewport* vp = mWindow->addViewport(mCamera);هنا ببساطة قمنا بمساواة بوينتر من نوع Viewport إلى فنكشن addViewport والتي تأخذ قيمة واحدة ..الكاميرا التي ستقوم بأخذ الصورة منها =) ..
ولاحظ أن addViewport موجودة داخل الكائن mWindow ( وهو كائن تم عمله من الكلاس RenderWindow )

والآن بعد أن حصلنا على بوينتر من الفيوبورت ، يمكننا التلاعب بلون الخلفية قليلاً =) ..


vp->setBackgroundColour(ColourValue(0,0,0));
ما فعلناه للتو هو أننا قمنا بتغيير لون الخلفية بإستخدام بوينتر الفيوبورت ، لون الخلفية هو اللون الذي يظهر في خلفية الشاشة ..(بالطبع لاحقاً بإذن الله سندرس أشياء مثل SkyBox لتغطية
السماء وجعلها واقعية قليلاً)
مجدداً الـColourValue تأخذ 3 قيم .. R,G,B .. أول قيمة لللون الأحمر والثانية للأخضر والثالثة للأزرق ، ويمكنك خلطهما معاً لتكوين ألوان جديدة ، وهي تأخذ أرقام من 0 إلى 1
حيث أنه لو كانت القيم 0،0،0 فهذا معناه أننا اخترنا اللون الأسود و القيم 1،1،1 معناها الأبيض ..
هنا اخترنا الأسود لأننا سنجرب الإضاءة
فالنقم بعمل الـAspectRatio


mCamera->setAspectRatio(Real(vp->getActualWidth()) / Real(vp->getActualHeight()));
الـAspectRatio هو العلاقة بين العرض والطول .. ويمكننا إيجادها بقسمة العرض على الطول .. وهي نوع الشاشة بشكل عام ، فيمكن
أن تكون مثلاً Wide Screen ،الخ،، .. ونلاحظ هنا أننا إستخدمنا قيماً حقيقية ..
ولاحظ أيضاً أن العرض والطول المستخدم هما عرض وطول الـviewport .. الهدف من هذا السطر هو مطابقة ما تعرضه الكاميرا مع الـViewport .. حتى لا يكون أكبر أو أصغر


الظل :-
هناك في الأوغر 3 تقنيات لرسم الظل .. كل منها مختلفة في الجودة وفي نفس الوقت مختلفة في الحمل الذي تلقيه على الـVGA والمعالج ..
يمكنك رؤية صورة للأنواع هنا:
http://xs841.xs.to/xs841/09283/ogreshadows884.jpg

أولاً :- Modulative Texture Shadows (SHADOWTYPE_TEXTURE_MODULATIVE) هو الأقل تكلفة على الجهاز من ناحية المجهود
مع عدم وضوح تام ، لكنه يكفي إن كانت اللعبة موجهة للأجهزة الضعيفة .. أو لو كانت هناك تفاصيل كثيرة في المشهد والأنواع الأخرى ستجعل اللعبة بطيئة ..

ثانياً :- Modulative Stencil Shadows (SHADOWTYPE_STENCIL_MODULATIVE) هو متوسط التكلفة ومتوسط الجودة

ثالثاً :- Additive Stencil Shadows (SHADOWTYPE_STENCIL_ADDITIVE) هو أعلى الأنواع جودة و تكلفة .. لأنه يقوم بعمل Pass خاص لكل ظل
في بطاقة الجرافكس ..

استخدام الظل في أوغر بسيط جداً .. كل الـSceneManager فيه فنكشن setShadowTechnique .. والتي نستطيع باستخدامها اختيار التقنية التي نريدها..
واستخدام setCastShadows لاختيار ما إذا كان الجسم يطرح ظلاً أم لا =)

ابحث عن فنكشن createScene .. ثم اضف إليها :

mSceneMgr->setAmbientLight(ColourValue(0, 0, 0));
mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_ADDITIVE);
هنا سنستدعي setAmbientLight ..التي ستأخذ ColourValue 0،0،0 أي أسود .. الـAmbientLight هي الإضاءة العامة .. إن أعطيتها قيمة لون أسود ، فإنها
لن تظهر أي كائن لا يلامس الضوء(ظلام تام) .. وإن أعطيتها قيمة لون أبيض .. فإن كل الكائنات ستظهر من البداية .. هنا طبعاً سنعطيها قيمة سوداء لنرى تأثير الإضاءة لاحقاً
في السطر الثاني قمنا باستدعاء setShadowTechnique والتي تأخذ في قيمتها نوع الظل المراد .. سنستخدم أعلى نوع SHADOWTYPE_STENCIL_ADDITIVE ..
قم بإضافة التالي :


ent = mSceneMgr->createEntity("Ninja", "ninja.mesh");
ent->setCastShadows(true);
mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);

كالعادة =) قمنا بعمل Entity .. وأظهرناها على الشاشة ،، هذه المرة سوف نستخدم موديل ninja.mesh بكل بساطة ^^.. الأمر الجديد هنا هو setCastShadows
والذي يأخذ قيمة بوول =) طبعاً نريد الكائن أن يطرح ظلاً..لذا اعطيناه قيمة true

نحن بالتأكيد سوف نحتاج شئ يسقط عليه الظل ، سوف نقوم بعمل plane .. وهو سطح مستوي ثلاثي الأبعاد .. لا أريد الدخول في تفاصيل عمله حالياً .. لذا تظاهر بأنني شرحته من قبل..
وبإذن الله سوف نشرحه في درس آخر ..لكن حالياً فقط نحتاج حضور plane لا غير.. قم بإضافة الكود التالي :


Plane plane(Vector3::UNIT_Y, 0);
MeshManager::getSingleton().createPlane("ground",
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, plane,
1500,1500,20,20,true,1,5,5,Vector3::UNIT_Z);


وهكذا نكون قد قمنا بعمل بلين بإسم ground ، بحجم 1500 *1500 ..كما قلت تجاهل الاسطر الماضية .. فهي لا تهمنا حالياً حقاً =)
أضف السطرين التاليين لعمل entity من البلين وعرضها على الشاشة:


ent = mSceneMgr->createEntity("GroundEntity", "ground");
mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);
لاحظ هنا اننا في مكان البراميتر الثاني لـcreateEntity قمنا بكتابة ground ..المسمى الذي أطلقناه على البلين في قطعة الكود السابقة .. ولم ندخل اسم ملف ..
ومن هنا يمكن أن نستنتج أننا حينما نقوم بصناعة الـentity لا يشترط عملها من ملف .. لكن يمكننا من خلال الـMeshManager كما فعلنا أن نقوم بعمل كائن جاهز ونضعه
كموديل للـEntity
المتبقي علينا قعله الآن هو أن نبرمج كائن الأرض الذي قمنا بصنعه لكي لا يعطي ظلاً لأنه لا حاجة لذلك كونه هو ما يعرض ظل الانتيتي التي عليه .. ومن ثم أن نضع ما يسمى Texture
أو Material عليها لتبدو كالأرض... لحظة؟؟ ما هو ذلك؟؟ ببساطة في الثري دي بدون الإكساء (Material / Texture ) سيكون الموديل كله عبارة عن لا شئ سوى لون واحد أو عدة
ألوان تم وضعها عليه من قبل خيارات برنامج التصميم الثري دي فحسب .. الإكساء هنا هو عبارة عن صورة.. هذه الصورة سوف تقوم بـ"فرش" نفسها على الموديل ..بحيث لا يصبح
الموديل ذو لون واحد لكن يمكنك أن تضيف عليه أي نوع من التفاصيل/الألوان التي تريد بالخامة .. هذا مثال من ويكيبيديا لموديل قبل وبعد الإكساء :
http://upload.wikimedia.org/wikipedia/commons/3/30/Texturedm1a2.png
كما ترى بالإكساء تم إضافة بعض النقوش على الدبابة .. وهو أمر لا يمكن عمله بدون الإكساء ..أعتقد صارت واضحة..
قم بإلصاق الكود التالي :


ent->setMaterialName("Examples/Rockwall");
ent->setCastShadows(false);

هنا استخدمنا setMaterialName لنختار التكستشر التي نريد ...القيمة التي أدخلناها هو اسم الملف الذي يحتوي معلومات الإكساء ..
ثم استخدمنا setCastShadow ووضعنا فيه قيمة false لنمنعه من طرح الظل ..

طبعاً الآن ستتوقع فور إنك تضغط F5 أن ترى الموديل والأرض وظل الموديل على الأرض ^^ .. هيا قم بالتحقق...
خطأ! لن ترى شيئاً لأننا وضعنا الـAmbientLight لونه أسود(ظلام) بالتالي لن ترى شيئاً إلا بعد أن تضع الإضاءة .. فالنقم بالدخول في الإضاءة إذاً ..
الإضاءة :-
كما ذكرنا مسبقاً فالإضاءة هي أساس أي مشهد .. لدينا 3 أنواع من الضوء أيضاً .. وتستخدم على حسب ما تريده :
أولاً :- Point (LT_POINT) ..
إضاءة النقطة المعروفة في برامج الثري دي بالـOmni .. هي نوع يقوم بنشر الضوء في كل مكان ويقوم بإضاءة كل شئ من حوله .. عبر نشر الضوء في كل اتجاه
ثانياً :- Spotlight (LT_SPOTLIGHT)
السبوت لايت هو تماماً مثل مصباح اليد (Flashlight) له نقطة بداية واتجاه يسري فيه.
ثالثاً:- Directional (LT_DIRECTIONAL)
الضوء المتجه هو ضوء ليس له بداية ولا نهاية .. هدفه هو أن يصيب عناصر المشهد من اتجاه .
فالنبدأ بعمل الضوء إذاً ..أول ما سنقوم بعمله الآن هو أن نقوم بعمل الضوء ، اختيار نوعه ، ثم تعديل موقعه


light = mSceneMgr->createLight("Light1");
light->setType(Light::LT_POINT);
light->setPosition(Vector3(0, 150, 250));
والآن يمكننا أن ندخل قيم الـDiffuse والـSpecular .. ألوان خاصة بالضوء ^^..على كلٍ..اخترت اللون الأحمر..


light->setDiffuseColour(1.0, 0.0, 0.0);
light->setSpecularColour(1.0, 0.0, 0.0);
يمكنك أن تجرب الآن =) نجحنا ! هناك نينجا وأرض وعليها ظله ^^ ..والأرض عليها التكستشر ..
إن لم يكن المشهد هكذا ^^ فراجع الكود الخاص بالجزء المختلف..
والآن لنجرب القليل من الدايركشنال لايت ^^ .. أترى كيف أن النينجا من الأمام مظلم؟ ..سنضيف دايركشنال لايت لونها أصفر( عبر مزج الأحمر والأخضر بقيمة صغيرة)
[
LEFT]light = mSceneMgr->createLight("Light3");
light->setType(Light::LT_DIRECTIONAL);
light->setDiffuseColour(ColourValue(.25, .25, 0));
light->setSpecularColour(ColourValue(.25, .25, 0));[/LEFT]بما أن الضوء الدايركشنال ليس له بداية أو نهاية ، فليس علينا أن نضيف موقعه ، فقط اتجاهه .. أضف السطر التالي:


light->setDirection(Vector3( 0, -1, 1 ));
لدينا الآن ظلين في المشهد ^^
آخر نوع سنقوم بتجربته هو السبوت لايت ^^ .. سوف نقوم بعمل الآن ضوء أزرق =)


light = mSceneMgr->createLight("Light2");
light->setType(Light::LT_SPOTLIGHT);
light->setDiffuseColour(0, 0, 1.0);
light->setSpecularColour(0, 0, 1.0);
ومن ثم نعدل الموقع والإتجاه .. بحيث يكون الضوء فوق كتف الموديل .. ويشع عليه مباشرة ^^..


light->setDirection(-1, -1, 0);
light->setPosition(Vector3(300, 300, 0));
السبوت لايت أيضاً تسمح لنا بتعديل مقدار الشعاع (كون شعاعها دائري الشكل) .. تخيل شعاع ضوئي خارج من مصباح يد ويسقط على حائط.. ستكون هناك نقطة في الوسط فيها الأشعة
أقوى ما يمكن ، وكلما ابتعدنا عن هذه النقطة يقل تأثير الضوء ، يمكننا تعديل ذلك باستخدام التالي :

light->setSpotlightRange(Degree(35), Degree(50));حسناً لقد انتهينا ^^ .. يمكنك الآن أن ترى النتيجة ..مذهل ..أليس كذلك؟

صورة ^^ :
http://xs841.xs.to/xs841/09283/shade945.jpg

The_source
09-07-2009, 09:21 AM
ماشاء الله عليك مذهل كعادتك يا أخي Mody
يبدو إنه ليس لدينا فرصه معك بالمسابقه ^^

alkhattab
09-07-2009, 12:58 PM
إذا لا مفر الفيجوال سي هو الحل
متابعك إلى النهاية

modyKun
09-07-2009, 03:32 PM
ماشاء الله عليك مذهل كعادتك يا أخي Mody
يبدو إنه ليس لدينا فرصه معك بالمسابقه ^^
هلا بيك أستاذي ^^ ، أشكرك ^^ والله احرجتني ، وعيب عليك يا رجل ^^ انا اللي ما لي فرصة لو انت دخلت ^_^ ..

إذا لا مفر الفيجوال سي هو الحل
متابعك إلى النهاية
^^ أشكرك عزيزي على متابعتي !.. وانتظر تطبيقك للدروس ^_^..

بالمناسبة سيتأخر الدرس القادم نوعاً ما ، كوني منشغل في مشروعين حالياً ^^

PrinceOfSorrow
10-07-2009, 05:47 AM
وعليكم السلام ورحمة الله وبركاته

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

Congrats + Voted 4 You

modyKun
12-07-2009, 03:22 AM
أشكرك أخي برنسو ^_^ ، سعيد بتواجدك في الموضوع =)
والله أخجلت تواضعي أخي ^^..
+ نعم هو مجاني ^^ .. مع أنه يحتوي ميزات ترشحه بأن يكون بآلاف الدولارات ^^ ..
ونورت الموضوع ^_^..

+
في شئ مهم ^^ .. تم اعتماد دورة أخي أحمد :
http://www.montada.com/showthread.php?t=640058
كدورة رسمية لتعلم السي++ بشكل مفصل ^^ .. طبعاً بيكون في دروس سريعة من كتابتي لادخالكم في السي++ بشكل سريع، لكن دورة أخي رجل المخاطر هي للسي++ بالتفصيل ^^ ..

تحياتي لكم ^^ وآسف لانشغالي مؤخراً ^^ لكن أشتغل على مشروعين مثل ما سبق وذكرت..

Evil Joker
12-07-2009, 06:06 AM
درس أكثر من رائع...بارك الله فيك ياأخوي صراحةً حمستنا كثير ...وشكراً لك سأستفيد من الدرس مستقبلاً^^ تابع واستمر...

modyKun
14-07-2009, 04:01 AM
درس أكثر من رائع...بارك الله فيك ياأخوي صراحةً حمستنا كثير ...وشكراً لك سأستفيد من الدرس مستقبلاً^^ تابع واستمر...
أشكرك عزيزي من كل قلبي على ردك ^_^..
وإلى الأمام =)

LiOn×HeaRt
31-08-2009, 03:03 AM
السلام عليكم
أخوي صاحب المشروع باين عليك خبرة ماشاء الله
انا نفسي أتعلم ال c++ وأنا جاد ومصمم على تعلمها لكن ماأعرف من فين أبدأ...
دورت على دروس كثيرة لكن يلخبطوك كلهم ماتدر مرة واحد يبدا بملف dll والثاني cmd وصارت حوادث فدماغي الله يرجهم
إذا مايثقل عليك أرجو انك تقلي طريقة تعلم ال سي بلس في مجال الألعاب فقط
ارسلي رسالة على الخاص ومشكور

LordOfShadows
03-09-2009, 08:09 PM
أنا حليا أتعلم ال c++ بسبب هذا الموضوع الرائع
وأريد حقا أن أتعلم الأوغر لكنني لن أقرء حرفا عنه حتى أتعلم ال c++

M.hocine
04-09-2009, 06:54 PM
السلام عليكم
الموضوع رائع جدا اخي modykun
الـ ogre قوي جدا في الرندر ، ومن يريد يعمل لعبة قوية و غير مكلفة عليه بتعلم بلندر و الـ ogre
http://www.ogre3d.org/wiki/index.php/Tools:_Blender
الشيء الوحيد الذي تركني لا اتعلم الـ ogre لحد الان هو عدم تصديره الالعاب للكونسول الاخرى ..( قبل مدة طويلة قالوا انه سيصدر للاكس بوكس وما زال لحد الساعة )..
عدا ذلك كل المميزات قوية جدا .
---------------------------
بالمناسبة لفت انتباهي بالـ features عبارة " manual bone control"
هل يمكن ان تكون HumanIK داخل الانجن نفسه ؟ لو كان كذلك فهذه ميزة رهيبة جدا جدا و لا تقدر بثمن .
http://usa.autodesk.com/adsk/servlet/item?siteID=123112&id=10316291&linkID=10225710
سابحث عن مدى قوة الـ ogre في هذه النقطة بالذات :33:

احييك اخي على الموضوع الرائع و بارك الله فيك.

DRAGON 45
07-09-2009, 08:46 PM
درس مذهل وأفكر في إستخدامه

عمر
26-09-2009, 12:40 AM
شكراً لك أخي الكريم، درس مذهل ورائع،
أنا زمان كنت خايف من برمجة الألعاب بالسي++ :D ربما لأنني لا أملك أي خبرة بتصميم 3دي، لكن مع درسك هذا تشجعت :).
سأتابع دروسك، فربما أستفيد منها بالمستقبل.
أنا حالياً أعمل كمبرمج مواقع ولكن لا بأس من زيادة المعرفة :).
--------------
بالمناسبة Ogre مفتوح المصدر وليس فقط مجاني!،
وكذلك ألعابه تعمل على win, mac, linux
وعلى وندوز تستطيع أن تعمل على Visual C++, Eclipse CDT, Code::Blocks والأخيرين إن كنت من محبي المصادر المفتوحة.