الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

مثال في الفيزياء للopengl

مغلق
بدأه hunterxhunter في 21 يوليو 2006 · 8 رد · 1,448 مشاهدة · في OpenGL
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم

أخواني الكرام وضعت هذا الموضوع لأني رأية نقص في مواضيع الفيزياء ولاسيما في المنتديات العربية

وهذا المثال مأخود من موقع nehe.gamedev

حمل المثال من هنا

http://nehe.gamedev.net/data/lessons/vc/lesson40.zip

طبعا سيكون الشرح فقط النقاط اللي يطلبوها الأعضاء عشان لانشرح شيء يعرفه كل الأعضاء

فإذا شخص عنده نقطة ماهو فاهممنها يحدد النقطة أو الكود وأنا متأكد إن أي شخص يعرفها حيجاوبه

وبكده نشرح أهم النقاط في الكود

وندخر جهدنا ولانضيع وقتنا في شرح أشياء معروفة

ننتضر الردود (لكي نعرف الأكواد اللي نشرحها)

وشكرا

#2

المثال متقدم جدا .

انا لم افهم الا vector و الكتلة .. بقية الكلاسات .. تدوخ .

لكن اعتقد اخي انه او تبدأ في الكلام النظري .. يعني ماهي القوانين الفيزيائية المستخدمة .. تكلم كلام عام عن تلك الفئات .

لا استطيع ان اقول اشرح الكود كاملا :) .

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#3

السلام عليكم

أخي الشمري سأحاول عمل مثل ماقلت

وشكرا على مرورك

#4

السلام عليكم

سنبدأ بشرح كلاس mass

لأن كلاس Vector3D

تستطيعوا فهمه إن شاء الله فقط يجب أن تعلم كيف تتعامل مع المعاملات وكتابتها

ملحوظة

أي دالة إسمها مثل إسم الصنف هي دالة بناءولكني سأكتب دالة

أي كائن من صنف Vector3D هو عبارة عن متجه

float m;								
	Vector3D pos;	
	Vector3D vel;								
	Vector3D force;
السطر الأول  أعلنا عن متغير للكتلة 
السطر الثاني أعلنا عن كائن من الصنف  Vector3D
وهو للمسافة
السطر الثالث أعلنا عن كائن للسرعة 
السطر الرابع أعلنا عن كائن للقوة 
وجميع الكائنات السابقة من الصنف نفسه
Mass(float m)								
	{
		this->m = m;
	}
الدالة السابق تأخد وسيط واحد وهو الكتلة 
this->m
تشير الى المتغير العام وليس المتغير الوسيط 
m
تشير الى المتغير الوسيط 
وفائدت الدالة السابقة هي تعين قيمة للكتلة

void applyForce(Vector3D force)
	{
		this->force += force;					
	}

الدالة السابقة تقبل وسيط واحد ولكن يجب أن يكون كائن من الصنف Vector3D

this->force += force;

هذا الصطر واضح فقط

+=

وهي المعامل اللي كتبناه للصنف Vector3D

void init()

{

force.x = 0;

force.y = 0;

force.z = 0;

}

هذه الدالة فائدتها تصفيرقيم إحداثيات الكائن force

	void simulate(float dt)
	{
		vel += (force /m) * dt;			


		pos += vel * dt;					

	}

الدالة السابقة هي دالة المحاكات وتقبل وسيط واحد وهو الزمن

vel += (force /m) * dt;

هذا السطر عبارة عن قانون من قوانين الحركة الخطية(على حد علمي بس كأنه غريب )

وهو

السرعة =السرعة +التسارع *الزمن

pos += vel * dt;
أما هذا السطر وهو قانون المسافة

الحين خلينا نروح الى كلاس Simulation

int numOfMasses;

Mass** masses;

السطر الأول أعلنا عن متغير ستعرف فائدته لاحقا

السطر الثاني أعلنا كائن مأشر يشير الى مأشر من الصنف Mass

وهذا الكائن للكتل أو الكتلة

Simulation(int numOfMasses, float m)			
	{
		this->numOfMasses = numOfMasses;

		masses = new Mass*[numOfMasses];			 

		for (int a = 0; a < numOfMasses; ++a)				masses[a] = new Mass(m);			 
	}

الدالة السابقة تأخد وسيطين وأعتقد أنهم واضحين ولها فائدتين

الأولى وضع قيمت الوسيط الأول في المتغير numOfMasses

الثانية متعلقة بالكائن masses

masses = new Mass*[numOfMasses];

حيث السطر السابق حجزنا للكائن مصفوفة مأشرات وحددنا حجم المصفوفة بقيمة المتغير

numOfMasses

	for (int a = 0; a < numOfMasses; ++a)		
			masses[a] = new Mass(m);

لست متأكد منهذا السطر

	virtual void release()							
	{
		for (int a = 0; a < numOfMasses; ++a)		
		{
			delete(masses[a]);
			masses[a] = NULL;
		}

		delete(masses);
		masses = NULL;
	}

الدالة السابقة هي دالة إفتراضية وفائدتها مسح المصفوفة السابقة وتحرير الذاكرة منها

Mass* getMass(int index)
	{

		if (index < 0 || index >= numOfMasses)		
			return NULL;						

		return masses[index];				

	}

هذه الدالة لها وسيط واحد دعنا ندهب الى فائدتها

فائدتها طباعة عنصر من عناصر المصفوفة طبعا العنصر اللي يشير له الوسيط الأول وهذا واضح في السطر الأخير في الدالة

الآن نستطيع معرفة العبارة الشرطية وهي إذا كانت قيمة الوسيط الأول أقل من صفر أو أكبر أو يساوي حجم المصفوفة يكون الناتج لاشيء

virtual void init()								
	{
		for (int a = 0; a < numOfMasses; ++a)		 
			masses[a]->init();						
	}

هذه الدالة أيضا دالة إفتراضية وفائدتها أن تمرر كل عنصر من عناصر المصفوفة

وترسلها الى الدالة init

لتقوم بعملها

طبعا هذه الدالة ليست الدالة اللي نحن فيها بل الدالة اللي في الصنف

Mass

لأن الكائن masses

من الصنف Mass

virtual void solve()							 
	{

	}

هده الدالة بصراحة لاأعرف لمذا لايوجد فيها أي أمر فللي يعرف أرجو أنه يقول السبب

virtual void simulate(float dt)		

{
		for (int a = 0; a < numOfMasses; ++a)	
	masses[a]->simulate(dt);	
	}

هذه الدالة دالة إفتراضية أخرى ولها وسيط واحد وهو الوقت

وشرحها مثل شرح الدالة init

فقط مررنا قيمة الوقت الى دالة المحاكاه للكائن (simulate)

	virtual void operate(float dt)					 
	{
		init();										
		solve();									
		simulate(dt);							
	}

هذه الدالة هي آخر دالة في هذا الصنف

وهي واضحا فقط مررنا الوسيط الأول في الدالة الى دالة simulate

نأتي الآن الى صنف ConstantVelocity

class ConstantVelocity : public Simulation
{
public:
	ConstantVelocity() : Simulation(1, 1.0f)					{
		masses[0]->pos = Vector3D(0.0f, 0.0f, 0.0f);				masses[0]->vel = Vector3D(1.0f, 0.0f, 0.0f);		 
	}

};

هذا الصنف يرث من الصنف Simulation

طبعا توارث عام

ConstantVelocity() : Simulation(1, 1.0f)

هذا الكود واضح فقط وضعنا قيمة الوسيط الأول واحد(وهو عدد عناصر المصفوفة ) والوسيط الثاني واحد (الكتلت )

إ

	masses[0]->pos = Vector3D(0.0f, 0.0f, 0.0f);		 
	masses[0]->vel = Vector3D(1.0f, 0.0f, 0.0f);

السطرين السطر الأول إستدعينا دالة المسافة للكائن masses[0]

ثم أستعملنا المعامل يساوي اللي في الصنف Vector3D

لكي نساوي كل أحداثي في الدالةpos

للكائن masses[0]

مع الإحداثي اللي يقابله في الدالة Vector3D

والسطر الثاني بنفس الطريقة

الآن نأتي الى الصنف MotionUnderGravitation

class MotionUnderGravitation : public Simulation
{
public:
	Vector3D gravitation;													

	MotionUnderGravitation(Vector3D gravitation) : Simulation(1,  1.0f)			{																			this->gravitation = gravitation;									
		masses[0]->pos = Vector3D(-10.0f, 0.0f, 0.0f);						
		masses[0]->vel = Vector3D(10.0f, 15.0f, 0.0f);							}

	virtual void solve()													{
		for (int a = 0; a < numOfMasses; ++a)										masses[a]->applyForce(gravitation * masses[a]->m);				}

};

في البداية جعنا الصنف يرث من الصنف Simulation

والوراثة أيضا وراثة عامة

Vector3D gravitation;

في السطر السابق عملنا كائن من الصنف Vector3D

وهو للجاذبيةالأرضية

أما بقيت الدالة واضحة وشرحنا مثلها

دعونا نذهب الى دالة solve

virtual void solve()													{
		for (int a = 0; a < numOfMasses; ++a)										masses[a]->applyForce(gravitation * masses[a]->m);				}

هذه الدالة دالة إفتراضية

السطر الثاني هو جملة تكرارية فائدتها المرور على جميع عناصر المصفوفة

masses[a]->applyForce(gravitation * masses[a]->m);

في هذا السطر مررنا لدالة applyForce

للكائن masses[a]

كائن الجاذبية * كتلت كل كائن من عناصر هذه المصفوفة

طيب لماذا مررنا هذه القيم ؟

لأن دالت applyForce

تأخد وسيط واحد وهو كائن القوة

بالنسبة الى الصنف الأخير لن أشرحه لأني لاأعلم مافائدة

springVector

و

connectionPos

و

springConstant;

ولكن الأخير

أعتقد أنه مقدار قوة التماسك أو الثبات

لذلك لاأستطيع أكمال شرح هذا الصنف وهو أيضا يشبه الصنف اللي قبله فقط الإختلاف في بعض الأشياء

سأحاول أن أكمل الشرح في وقت لاحق

ولكن أحب أسمع التعليقت أو الأسئلة طبعا مولازم أجاوكم لأني مبتدأولكن ستجدوا من يجاوب عليها من الأعضاء أو إذا حد حاب يشرح أو يصحح أويضيف فاليتفضل

تم تعديل هذه المشاركة بواسطة احمد صالح في 23 يوليو 2006 في 14:07

#5

هذا القانون

pos += vel * dt;

قادم من تكامل اويلر و هو تكامل تقريبي Numerical Intergral لمعادلات الحركة ; فنحن ناتي بتكامل تقريبي لها ; ليسهل علي المعالج معالجتها ، فإن كنت تريد محاكاة طبيعية حقاً تحتاج إلي اجهزة Super Computer لتطبيق معادلات الحركة المعروفة ( تخيل لتأتي بالسرعة لازم تكامل المسافة ! و عملية التكامل مرهقة للمعالج يعني هتكامل في كل اطار في اللعبة for every frame ، الا تعتقد انها مرهقة الان ؟ " .

المقالة هذه مفيدة حقاً : http://www.gaffer.org/articles/Integration.html

BEng , Electronics and communications.

Embedded systems engineer.

Graphics Programmer

عالم الكومبيوتر هو من لديه المعرفة في علوم الكومبيوتر ، الرياضيات ، هندسة الالكترونيات -احمد صالح

#6

السلام عليكم

فعلا شيء رائع أن ترى شخص يوضح لك بعض النقاط

وشكرا على المقالة

بس آسف أخي أحمد أتعبتك معاي لأني وضعت الشرح وكنت مستعجل ونسيت تعديل الأكواد

وأكرر أسفي

ولكن هل وجت الكثير من الأخطاء في شرحي(بدون مجاملة) ؟

إذا لم يعجبك السؤال مو لازم تجاوب عليه بس هو موجه للجميع ولكن يهمني رايك جدا

#7

قرأت كامل درسك .. طبعا ما اقدر اقيمك لاني معلوماتي صفر على الشمال ( لازلت انتظر طريقة التسارع :D )

لكن حاليا سأركز في مثالك على اول ثلاثة كلاسات هي الاساس .. وكنت اتمنى ان نبدأ في 2D اسهل .

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#8

السلام عليكم

أخي الشمري

شرفتنا بمرورك

أنا ححاول أكتب بقيت الشرح الآن وبوضعه أول ماخلص

صحيح بالنسبة الى الرسالة الخاصة أنا فكرت في عمل مثال بس أول ماخلص من مثانا الحالي

#9

السلام عليكم

class Spring		

{
public:
	Mass* mass1;										
	Mass* mass2;	
	float springConstant;				
	float springLength;			
	float frictionConstant;		
	Spring(Mass* mass1, Mass* mass2, 
		float springConstant, float springLength, float frictionConstant)			
{
		this->springConstant = springConstant;									
		this->springLength = springLength;										
		this->frictionConstant = frictionConstant;								

		this->mass1 = mass1;													
		this->mass2 = mass2;														}

السطر الثالث عملنا كائن مؤشر من الصنف Mass وهو للطرف الأول في الحبل

السطر الثاني نفس السطر الأول بس الكائن للطرف الآخر في الحبل

السطر الخامس كما قلت سابقا أعتقد أنه مقدار قوة التماسك أو الثبات(ثابت الصلابة للزبرنك)

السطر السادس هو لطول الحبل قبل الإستطالة

السطر السابع لمقدار لحتكاك

الآن ندهب الى دالة Spring

فائدتها فقط إسناد القيم اللي في المتغيرات الوسيطة الى المتغيرات العامة اللي في الصنف

	void solve()																
		{
		Vector3D springVector = mass1->pos - mass2->pos;						
		float r = springVector.length();											

		Vector3D force;																		
		if (r != 0)																			
	force += (springVector / r) * (r - springLength) * (-springConstant); 
		force += -(mass1->vel - mass2->vel) * frictionConstant;																										

		mass1->applyForce(force);															
mass2->applyForce(-force);													


	}

};

ندهب الى دالة solve

السطر الثاني عملنا كائن من الصنف Vector3D

وهو لأيجاد متجه الحبل ولكن أعتقد أنه يشير الى عكس الإتجاه (لأن النقطة الأولة هي آخر نقطة في الحبل)

السطر الثالث عملنا متغير وأسندنا له قيمت طول الكائن الاتلاحظ أن أستدعين دالة لم نشرحا من قبل

صحيح لأنها دالة من الصنف Vector3D

وأنا لم أشرحه ولكن هي دالة لإيجاد طول المتجه وهناك دوال أخرى في نفس الصنف ولكن لن أشرحها إلا عندما نتطرق اليها

السطر الرابع عملنا كائن للقوة

السطر الخامس عملنا جمله شرطية وهي إذا كان طول المتجه لايساوي صفر ينفد السطر

السادس

force += (springVector / r) * (r - springLength) * (-springConstant);

(springVector / r)=المتجه /طوله

إذهب الى المرشد الكامل الفصل الرابع لمزيد من المعلومات عن المتجهات

وايضا لديك موضوع حسن الجودي عن المتجهات

(r - springLength)

أعتقد أنوجه الشبه بين springLength و r

أنهما كليهما للطول ولكن الفرق springLength

هو الطول قبل الإستطالة

و r

بعد الإستطالة

وعندما نطرح

springLength

من

r

ينتج مقدار الإستطالة

ومن ثمة نضربه في ثابت الصلابة فينتج لنا القوة

ولكن هناك ملاحظة ماعلاقت (springVector / r)

في القانون هل يستطيع أحد توضيح هذه النقطة

ولكن قد يكون القانون مأخود من قانون شغل الزبرنك

بس مانا متأكد لأني من زمان ماتعاملة مع الزبرنك ولذلك نسيت قوانينه

	force += -(mass1->vel - mass2->vel) * frictionConstant;

هذا السطر لقانون القوة أيضا

ولكن هناك سؤال لماذا جعلنا سرعت النقطة الأولة –سرعة النقطة الثانية ؟

سنجاوب على السؤال لاحقا

الآن نضرب الناتج في مقدار الإحتكاك بصراحة هذا القانون أول مرة أشوفة

فإذا ممكن حد يشرحه أرجوا أن لايتردد

السطر الأخيرين في الدالة هي أرسال قيمة متجه القوة الى دالة applyForce

إذهب الى الدالة لتعرف فائدتها

هناك ملاحظة

السطر الثاني

Vector3D springVector = mass1->pos - mass2->pos;

تستطيع جعله هكذا

Vector3D springVector =  mass2->pos -mass1->pos;

ولكن لاتنسى أن تغير في هذا السطر

		force += -(mass1->vel - mass2->vel) * frictionConstant;

بحيث تجعله هكذا

 force += -( mass2->vel-mass1->vel ) * frictionConstant;

وأيضا تغير فيهذين السطرين

mass1->applyForce(force);														
mass2->applyForce(-force);

وتجعلهماهكذا

 mass1->applyForce(-force);														
mass2->applyForce(force);

لأن إشارت السالبة لقب عكس إتجاه المتجه

هل عرفتواالإجابة عن السؤال الآن إذا أرتوا أن تبدلوا في ترتيب المتجه يجب أن تغيروا كم حاجه في المعادلة

أنتهين منهذه الدالة

الآن نذهب الى صنف RopeSimulation

الدالة السابقة كانت ثقيلة نسبيا لأن فيها قوانين جديدة علينا وغامضه أيضا

الآن دعونا نشرح الصنف

class RopeSimulation : public Simulation				
{
public:
	Spring** springs;								
	Vector3D gravitation;								
	Vector3D ropeConnectionPos;								Vector3D ropeConnectionVel;																
	float groundRepulsionConstant;							
	float groundFrictionConstant;					

	float groundAbsorptionConstant;						

	float groundHeight;										float airFrictionConstant;

أول عملنا صنف جديد وهولإستعمال ماشرحناه سابقا من قوانين أو كائنات وغيرها

طبعا جعلناه يرث من صنف Simulation

ونوع الوراثة هنا عامة

ثم عملنا كائن من صنفSpring

وستعرف فائدته لاحقا

السطر الرابع عملنا كائن للجادبية

السطر الخامس هذا الكائن للمسافة اللي يقطعة الحبل أوبمعنا أصح موقعه

السطر السادس عملنا كائن لسرعة الحبل

الى الآن لدينا مسافة وسرعة الحبل

السطر السابع عملنا متغير لمقدار أو قيمت الإرتداد طبعا سيفيدنا عندما يسقط الحبل على الأرض لكي يرتد على حسب سرعت عند الإصطدام و كتلته والخ...

السطر الثامن عملنا متغير وهو مقدار معامل الإحتكاك للأرض

السطر التاسع عملنا متغير للمقدار إمتصاص الأرض للصدمات

السطر العاشر عملنا متغير لرتفاع الأرض

السطر الحادي عشر هو معامل الإحتكاك ولكن معامل إحتكاك الأجسام بالهواء

RopeSimulation(
												int numOfMasses,										float m,												float springConstant,									float springLength,								
		float springFrictionConstant,				 
		Vector3D gravitation,		
	float airFrictionConstant,		
	float groundRepulsionConstant,							float groundFrictionConstant,							float groundAbsorptionConstant,					
		float groundHeight		
		) : Simulation(numOfMasses, m)						{
		this->gravitation = gravitation;

		this->airFrictionConstant = airFrictionConstant;

		this->groundFrictionConstant = groundFrictionConstant;
		this->groundRepulsionConstant = groundRepulsionConstant;
		this->groundAbsorptionConstant = groundAbsorptionConstant;
		this->groundHeight = groundHeight;

		for (int a = 0; a < numOfMasses; ++a)					{
			masses[a]->pos.x = a * springLength;					masses[a]->pos.y = 0;								masses[a]->pos.z = 0;						
		}

		springs = new Spring*[numOfMasses - 1];																			
		for (a = 0; a < numOfMasses - 1; ++a)				{
						springs[a] = new Spring(masses[a], masses[a + 1], 
				springConstant, springLength, springFrictionConstant);
		}
	}

السطر الأول عملنا دالة بناء وتقبل إحدى عشر وسيطا ً

الوسيط الأول شرحناه سابقا ولكن ربما لم نقل فائدة هو عبارة عن حجم المصفوفة وهو عدد الكتل التي يتكون منها الحبل

الوسيط الثاني هو مقدار الكتلة

الوسيط الثالث هو معامل الصلابة(على ماأعتقد)

الوسيط الرابع هوالطول قبل الإستطالة(أي الطول الأصلي)

الوسيط الخامس هو معامل الإحتكاك للحبل

الوسيط السادس هو كائن الجادبة لاحضوا أنه متجه

الوسيط السابع هو معامل الإحتكاك للهواء

الوسيط الثامن هو مقدار الإرتداد عن الإصطدام بالأرض

الوسيط التاسع هو مقدار الإحتكاك بالأرض

الوسيط العاشر هو مقدار إمتصاص الأرض للصدمات

الوسيط الأخير هو لرتفاع الأرض

ثم إستدعين دالة Simulation

ووضعنا فيها فيم الوسائط

الآن سنترك الأسطر الستة القادمة و سندهب الى الجملة التكرارية الأولة

لأن تلك الأسر فقط قمنا إسناد قيمة المتغيرات الوسيطة الى المتغيرات العامة

هذه الحلقة هي المكان اللي حيرسم فيها كتل(نقاط) الحبل عند بداية البرنامج وبعد التشغيل حيتغير موقعهم بسبب الجادبية وغيرها من العوامل المأثرة على الحبل

أريدكم أن تلاحظوا أن الإحداثي الصادي والعيني ثابتين أي جميع النقاطأو الكتل سترسم على نفس العمق والإرتفاع أي أن الإحداثي السيني هو الدي سيحدد مكان الرسم طبعا هذه ليست قاعدة وللا قانون فأنت تستطيع التغير فيها مثلا ضع قبل حرف a

إشارة سالبة والترى الناتج

springs = new Spring*[numOfMasses - 1];

هذا السطر لتحجز مصفوفة مأشرات حجمها

numOfMasses – 1

ولكن السؤال لماذا numOfMasses – 1؟

الجواب ستعرفه بعد قليل

نذهب الآن الى الجملة التكرارية

for (a = 0; a < numOfMasses - 1; ++a)					{

springs[a] = new Spring(masses[a], masses[a + 1], 
				springConstant, springLength, springFrictionConstant);
		}

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

ولكن قبل أن أشرح سأقول لك شيء لم أقوله لكي لاتلخبط المعلومات

أن الحبل عبارة عن مجموعة من الحبال الصغيرة متصلة مع بعضها البعض ونحن نحاكي كل

من هذه الحبال الصغيرة لكي تضهر على أن نحاكي حركت الحبل يعني تخيلها مثل

السلسلة ولكن أنت لاترى فراغ بين هذه العقد(الحبال الصغيرة )

السبب أن لكل نهاية بداية ماعدى نهاية العقدة الأخيرةيعني بمعنى آخر نهاية الحبل

الأول هي بداية الحبل الثاني ونهاية الحبل الثاني هي بداية الحبل الثالث وهكذا

وكل نهاية أو بداية سنسميها نقطة

طيب السؤال يقول كم عدد النقط ؟

عددالنقاط = numOfMasses

طيب كم عدد الحبال الصغيرة لدينا ؟

عدد الحبال الصغيرة= numOfMasses – 1

هل عرفت الآن السبب جعل حجم مصفوفة springs

= numOfMasses – 1

هل تريد سبب آخر دعنا نأخد مثال لكي تتضح الصورة

لنفرض مثلا أن

NumOfMasses=5

و

springs[numOfMasses - 1]

إذا حجمها يساوي

Springs[4]

ولو عوضنا في الجملة التكرارية سترى أن آخر دورة وهي عندما يكون

a =3

سيكون الوسيط الثاني = a+1

يساوي 4

ولكن الجدير بالذكر هو أننا كنا في السابق نتكلم عن المتغيرات اللي تخص الحبل (مثل الوسيط الرابع)ونقول طول الحبل ككل مثلا لكي لاتحصل لخبطة

ولكن كنا نقصد طول كل واحد من الحبال الصغيرة اللي إدا إجتمع تكون لنا الحبل الكبير أرجوا أن تكون الفكرة وصلة

	void release()											{
		Simulation::release();									for (int a = 0; a < numOfMasses - 1; ++a)				{
			delete(springs[a]);
			springs[a] = NULL;
		}

		delete(springs);
		springs = NULL;
	}

هذه الدالة لمسح المصفوفة وتحرير الذاكرة منها

void solve()										
	{
		for (int a = 0; a < numOfMasses - 1; ++a)				{

			springs[a]->solve();						
		}

		for (a = 0; a < numOfMasses; ++a)				
		{
			masses[a]->applyForce(gravitation * masses[a]->m);				


	masses[a]->applyForce(-masses[a]->vel * airFrictionConstant);

الجملة التكرارية الأولى فائدتها تمرير عناصر المصفوف الى الدالة solve

التي في الصنف Spring

لكي توجد القوةوغيرها (إذهب الى الدالة لتعرف فائدتها ) لكل عنصر من عناصر المصفوفة ولاتنسا أن أي عنصر من عناصر المصفوفة هو عبارة عن حبل من حبال الصغيرة

الجملة التكرارية الثانية شبيهة بالأولى ولكن هذه المرة على مصفوفة الكتل (النقاط)

وقد حسبنا قوة كل عنصر بضرب الجاذبية الأرضية في كتلته

masses[a]->applyForce(-masses[a]->vel * airFrictionConstant);

هذا السطر هو لحساب قوة إحتكاك الهواء طيب تسأل لما سرعت كائن الكتلة (النقطة )بالسالب ؟

لأن قوى الإحتكاك يجب أن تكون بالسالب لكي تنقص السرعة

			if (masses[a]->pos.y < groundHeight)					{
				Vector3D v;								

				v = masses[a]->vel;						
				v.y = 0;								


				masses[a]->applyForce(-v * groundFrictionConstant);		

				v = masses[a]->vel;						
				v.x = 0;											v.z = 0;

العبارة الشرطية الأولى هي لكشف التصادم فإذا كان قيمت الإحداثي الصادي للكتلة(النقطة ) أقل من من إرتفاع الأرض

نعمل متجه ونسميه v

السطر اللي بعده نسند قيمت متجه السرعة لكائن الكتلة (النقطة ) الى المتجه v

	v.y = 0;

هذا السطر لجعل سرعة الحركة العمودية =0

masses[a]->applyForce(-v * groundFrictionConstant);

هذا السطر لأيجاد قوت الإحتكاك للأرض لاتنسو الناتج=سالب

طيب لماذا نوجد قوت الإحتكاك للأرض ؟

بما أن حدث تصادم للنقطة إذاً الكتلة (النقطة ) على الأرض وبما أنها على الأرض إذا حركتها أيضا على الأرض إلا إذا إرتفعت

	v = masses[a]->vel;						
				v.x = 0;											v.z = 0;

السطر الأول لأيجاد السرعة بعد الإحتكاك

السطر الثاني والثالث لاأعرف مالفائدة منهم ولكن يمكن لكي تقف الحركة

	if (v.y < 0)												masses[a]->applyForce(-v * groundAbsorptionConstant);		

Vector3D force = Vector3D(0, groundRepulsionConstant, 0) * 
					(groundHeight - masses[a]->pos.y);

				masses[a]->applyForce(force);						
			}

		}


	}

هذه الجملة إذا الإحداثي الصادي للمتجه أصغر من صفر ينفد هذا الكود

 masses[a]->applyForce(-v * groundAbsorptionConstant);

وهو لقوت الإرتداد

Vector3D force = Vector3D(0, groundRepulsionConstant, 0) * 

(groundHeight - masses[a]->pos.y);

أما هذا السطر فلم أفهم مابعد إشارت الضرب يعني لماذا أرتفاع الأرض-موقعالإحداثي الصادي

	masses[a]->applyForce(force);

هذا السطر لأيجاد القوة النهائية

void simulate(float dt)								
	{
		Simulation::simulate(dt);					

		ropeConnectionPos += ropeConnectionVel * dt;	
		if (ropeConnectionPos.y < groundHeight)		
		{

			ropeConnectionPos.y = groundHeight;
			ropeConnectionVel.y = 0;

		}

		masses[0]->pos  = ropeConnectionPos;						masses[0]->vel = ropeConnectionVel;				
	}

هذه الدالة لمحاكة حركة الحبل ولهاوسيط واحد وهو الزمن

السطر الثالث هو قانون

المسافة = السرعة *الزمن

ولكن للحبل

هل هو مثل القنون الأول للمسافة (أقصد مثل ماقال أخي أحمد)؟

الجملة الشرطية هي إذا كان موقع الحبل(بالنسبة للإحداثي الصادي ) أصغر من إرتفاع الأرض ينفد الكودين الآتين

ropeConnectionPos.y = groundHeight;

لمساوات إرتفاع الأرض مع إرتفاع الحبل

ropeConnectionVel.y = 0;

لمساوات سرعة الحبل بالصفر أي أن الحبل ثابت

masses[0]->pos  = ropeConnectionPos;						masses[0]->vel = ropeConnectionVel;

السطرين السابقين فقط إسناد للقيم

masses[0]

هي أول كتلة( نقطة) في الحبل

void setRopeConnectionVel(Vector3D ropeConnectionVel)		
{
		this->ropeConnectionVel = ropeConnectionVel;


	}

الدالة الأخيرة تقبل وسيط واحد وهو كائن سرعة الحبل

ثم تسند الكائن الوسيط الى الكائن المعرف في أعلى الصنف

إنتهينا الآن وسأحاول أكمل في وقت لاحق

ولكن هناك بعض الأخطاء لأن هناك بعض الأشياء غيرت معناها ولكن لاأدري إن غيرتها في كل الشرح أم لا فإذا هناك أي خطأ أرجوا منكم أن تضعوه لكي يتم تصحيحه وكما قلت سابقا إذا حد حاب يشرح أو يوضح أو يصحح أو يضيف فل يتفضل وإذا في شيء غامض مافهمته قول لي وإن شاء الله أستطيع مساعدتكوأشرحه بطريقة أخرى

وشكرا

هذا الموضوع مغلق.

مواضيع مشابهة