PDA

نسخه کامل مشاهده نسخه کامل : مباحث پیشرفته و کاربردی در Vb



A_M_IT2005
14-08-2006, 07:39
سلام

منبع همه مقالات : [ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]

================================================== ===============
فهرست مقالات و جلسات (این تاپیک)

مقالات

1. API های ویندوز ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])
2. تشخیص فشرده شدن کليدهای کيبرد ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])
3. استخراج مشخصات سخت افزاری یک سیستم در VB ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])
4. اضافه کردن آیکون به منو ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])
5. آشنايي با BitBlt ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])

جلسات

آموزش DirectX Input
1. جلسه اول ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])
2. جلسه دوم ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])
3. جلسه آخر ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])

مباحث پيشرفته Direct3D
1. جلسه اول ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])
2. جلسه دوم ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])
3. جلسه سوم ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])
4. جلسه چهارم ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])
5. جلسه آخر ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])

TAPI در ويژوال بيسيک
1. مقدمه ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])
2. جلسه اول ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])
3. جلسه دوم ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])
4. جلسه سوم ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])
5. جلسه چهارم ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])
6. جلسه پنجم ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])
7. جلسه آخر ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])

آشنايي با شی پرينتر در ويژوال بيسيک
1. جلسه اول ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])
2. جلسه دوم ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])
3. جلسه آخر ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])

آموزش DirectX-Graphic
1. جلسه اول ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])
2. جلسه دوم ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])
3. جلسه سوم ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])
4. جلسه چهارم ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])
5. جلسه پنجم ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])
6. جلسه ششم ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])
7. جلسه هفتم ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])
8. جلسه هشتم ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])
9. جلسه نهم ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])
10. جلسه آخر ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])

A_M_IT2005
14-08-2006, 07:48
سلام

API های ویندوز

امروز قصد دارم در مورد API هاي ويندوز و چگونگي استفاده از آنها در ويژوال بيسيک بطور خلاصه توضيح دهم و همچنين دو مثال پراستفاده را نيز در اين زمينه بيان کنم که عبارتند از چگونگي پخش فايلهاي Wav و ساخت يک تايمر با دقت بالا :

۱ - آشنايي با Windows API : واژه API مخفف Application Programming Interface مي باشد . API هاي ويندوز مجموعه اي از توابع از پيش آماده موجود در سيستم عامل هستند که شما مي توانيد آنها را در برنامه هاي خود فراخواني کنيد . اين توابع در چندين کتابخانه DLL ويندوز ذخيره شده اند . براي دسترسي به اين توابع در ويژوال بيسيک ابتدا بايد آنها را برنامه خود declare کنيد . براي مثال :

Declare Function sndPlaySound Lib "winmm.dll" Alias "sndPlaySoundA" (ByVal lpszSoundName As String, ByVal uFlags As Long) As Long

همانطور که مي بينيد مثال فوق يک Declare از تابع sndPlaySound مي باشد که اين تابع در کتابخانه Winmm.dll موجود است . کلمه Alias نشان مي دهد که اين تابع نام ديگري در dll دارد . ساير بخشها مربوط به تعريف پارامترهاي تابع مي باشند که در مورد مثال فوق ، اين تابع دو پارامتر ورودي و يک خروجي از نوع Long دارد .
پس از Delare کردن API در برنامه مي توانيد از آن استفاده نمائيد .

۲ - پخش فايلهاي Wav : تابعي که براي پخش فايلهاي Wav استفاده مي شود تابع sndPlaySound است که در بالا با آن آشنا شديد . پارامتر lpzSoundName نام و مسير فايل Wavو پارامتر uFlags چگونگي پخش فايل را مشخص مي کند . مقادير ممکن اين پارامتر عبارتند از :
- SND_ASYNC : اجازه مي دهد طوري فايل Wav پخش شود که آنرا بتوان وقفه داد . بعبارت ديگر قادر خواهيد بود فايل Wav تان را هر زمان که بخواهيد پخش کنيد و مطمئن باشيد که حتماً شنيده مي شود .
- SND_LOOP : فايل Wav را بطور ممتد پخش مي کند .
- SND_NODEFAULT : اگر فايل Wav پيدا نشود صداي ديگري پخش نخواهد شد ( مثلاً برخي صداهاي default ويندوز )
- SND_SYNC : در طول پخش فايل Wav کنترل به برنامه داده نمي شود . اين پارامتر در زمانيکه مي خواهيد فايل Wav اي را در پس زمينه برنامه تان پخش کنيد مناسب نمي باشد .
- SND_NOSTOP : اگر فايل Wav اي قبلاً در حال پخش باشد ، فايل Wav شما آنرا دچار وقفه نمي کند . از اين پارامتر زماني استفاده مي شود که بخواهيم فايل Wav مان هيچوقت در وسط کار قطع نشود .
اگر بخواهيد از بيش از يکي از اين پارامترها استفاده کنيد توسط Or آنها را ترکيب نمائيد مثال :

sndPlaySound App.path & "\ding.wav", SND_ASYNC or SND_LOOP


نکته : براي استفاده از توابع صوتي پيچيده تر بايستي از DirectSound که يکي از اجزاي DirectX مي باشد استفاده کنيد . در مورد DirectSound بعداً صحبت خواهم کرد .

۳ - ساخت يک تايمر با دقت بالا : شايد تا بحال از کنترل تايمر موجود در نوار ابزار ويژوال بيسيک استفاده کرده باشيد . اين تايمر داراي دقت حدود ۵۵ ميلي ثانيه است . براي دستيابي به زمانهاي با دقت بالاتر اين کنترل مفيد نخواهد بود .
تابع GetTickCount يک API موجود در کتابخانه Kernel32.dll است . اين تابع طول زماني را که سيستم شروع به کار کرده است را برحسب ميلي ثانيه برمي گرداند :

Private Declare Function GetTickCount Lib "kernel32" () As Long
براي بررسي طي شدن يک مدت زماني خاص شما ابتدا بايد مقدار اين تابع را در يک متغير کمکي مثل TempTime قرار دهيد سپس در يک حلقه Do-Loop بايد اختلاف زمان GetTickCount جديد و زمان TempTime را با مقدار زماني که مي خواهيد سپري شود مقايسه کنيد :

TempTime = GetTickCount()x
Do While DesiredTime < GetTickCount() - TempTime
Do some things'
Loop

توسط کد بالا مي توان يک عمليات خاص را براي يک مدت زماني مشخص اجرا کرد .
کد زير نشان مي دهد که چگونه مي توان دستورات خاصي را در فواصل زماني خاص اجرار کرد :

ExitFunction = False
TempTime = GetTickCount()x
Do While not(ExitFunction)x
If DesiredTime < GetTickCount() - TempTime then
Reset the temporary variable'
TempTime = GetTickCount()x
Do some things'
End If
Loop

همچنين از تابع GetTickCount مي توان براي benchmark برنامه ها استفاده کرد . بعبارت ديگر مي توان زمان اجراي يکسري دستورات خاص را بدست آورد .

فهرست ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])

A_M_IT2005
14-08-2006, 07:56
سلام

آموزش DirectX Input

جلسه اول :

گرفتن اطلاعات ورودی از کيبرد - ۱

مقدمه

Direct Input 8 همانطور که از نامش مشخص است به شما اجازه می دهد که بتوانيد برنامه هايي بنويسيد که توسط هر نوع دستگاه ورودی کنترل شود .
Direct Input 8 دارای چندين مزيت نسبت به استفاده از کنترلهای ورودی خود ويژوال بيسيک دارد – کنترلهايي مثل Form_KeyUp, Form_KeyDown, Form_MouseMove - و همچنين قابليت کنترل بيشتری نسبت به توابع استاندارد Win32 از قبيل GetCursorPos, GetKeyState دارد .
Direct Input 8 سريعتر ، کاراتر و قدرتمند تر بوده و برای ساخت بازيها طراحی شده بنابراين باعث کندی برنامه ها نخواهد شد .

چگونگی کار با Direct Input 8 برای گرفتن ورودی از کيبرد

دو روش برای استفاده از کيبرد در DirectX8 وجود دارد : روش polling و روش event-based که هر دو دارای مزايا و معايبی هستند .
بطور کلی در اغلب طراحيها از روش event-based استفاده می شود زيرا کار با آن راحت تر اسن . در اين روش هر پيغام فرستاده شده ازطرف دستگاه ورودی log می شود و برنامه نيازی به هيچگونه پردازشی بمنظور منتظر ماندن برای يک پيغام از طرف ورودی ندارد ، بنابر اين کاراتر است . در روش polling کنترل کمی دقيقتر و راحتر است .
اگر در مورد برنامه نويسی بر مبنای polling و بر مبنای event اطلاعات کافی نداريد می توانيد از منابع موجود در سايتهايي چون Gamasutra و GameDev استفاده کنيد .

روش Polling

مراحل اين روش عبارتند از :

1 – تعريفات Declerations : يک فرم ايجاد کرده و يک TextBox به نام txtOutput با خصوصيات Multiline ، Locked و Vertical Scroll Bar در آن قرار دهيد . کدهای زير را در بخش کدنويسی اين فرم بنويسيد :

Private Const UsePollingMethod As Boolean = True
Private Const UseEventMethod As Boolean = False
‘نکته مهم اينست که تنها يکی از دو ثابت فوق بايستی True باشد .
Private bRunning As Boolean
‘اين متغير برای polling استفاده می شود
Private DX As DirectX8
Private DI As DirectInput8
‘تعريف شی اصلی DirectX و شی DirectInput
Private DIDevice As DirectInputDevice8
Private DIState As DIKEYBOARDSTATE
‘اين دو شی برای دسترسی به دستگاه ورودی ( کيبرد ) استفاده می شوند
Private KeyState(0 To 255) As Boolean
‘آرايه ای برای تشخيص فشرده شدن کليد
Private Const BufferSize As Long = 10
‘ سايز بافر نگهدارنده event ها . در روش event-based اين مقدار برابر يک و در روش polling برابر 10 تا 20 است ( بسته به سرعت حلقه بازی )
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)x
‘ تابع Sleep برای متوقف کردن حلقه polling در صورت بالا بودن نرخ ورودی


2- مقدار دهی اوليه Initialisation : اين بخش سه مرحله دارد :
در مرحله اول اشيا و Device ها ساخته می شوند .
در مرحله دوم تنظيمات مربوط به Device انجام می شود .
در مرحله سوم به Device می گوئيم که می خواهيم شروع به استفاده از آن کنيم .

در Form_Load کدهای زير را بنويسيد :

Me.Show
Dim I As Long
Dim DevProp As DIPROPLONG
Dim DevInfo As DirectInputDeviceInstance8
Dim pBuffer(0 To BufferSize) As DIDEVICEOBJECTDATA
If UsePollingMethod And UseEventMethod Then
MsgBox "You must select only one of the constants before running"x
Unload Me
End
End If

If UsePollingMethod Then txtOutput.Text = "Using Polling Method" & vbCrLf
If UseEventMethod Then txtOutput.Text = "Using Event Based Method" & vbCrLf

‘مقداردهی اوليه روش انتخاب شده
Set DX = New DirectX8
Set DI = DX.DirectInputCreate
Set DIDevice = DI.CreateDevice("GUID_SysKeyboard")x

DIDevice.SetCommonDataFormat DIFORMAT_KEYBOARD
DIDevice.SetCooperativeLevel frmMain.hWnd, DISCL_BACKGROUND Or ISCL_NONEXCLUSIVE

‘برپاسازی بافر
DevProp.lHow = DIPH_DEVICE
DevProp.lData = BufferSize
DIDevice.SetProperty DIPROP_BUFFERSIZE, DevProp

‘ به دايرکت ايکس می گوئيم که می خواهيم از دستگاه ورودی استفاده کنيم
DIDevice.Acquire

‘استخراج اطلاعاتی در مورد دستگاه ورودی
Set DevInfo = DIDevice.GetDeviceInfo()x
txtOutput.Text = txtOutput.Text & "Product Name: " & DevInfo.GetProductName & vbCrLf
txtOutput.Text = txtOutput.Text & "Device Type: " & DevInfo.GetDevType & vbCrLf
txtOutput.Text = txtOutput.Text & "GUID: " & DevInfo.GetGuidInstance & vbCrLf


‘در صورتی که بخواهيم به برنامه خاتمه بدهيم کدهای زير را می نويسيم
DIDevice.Unacquire
Set DIDevice = Nothing
Set DI = Nothing
Set DX = Nothing
Unload Me
End


3 – گرفتن ورودی از کيبرد : در اين بخش فرض کنيد بخواهيم يک بازی را در يک حلقه Do-Loop شبيه سازی کنيم . در اين حلقه هر بار فشرده شدن کليدهای کيبرد را چک می کنيم :

If Not Err.Number Then bRunning = True

Do While bRunning

‘دريافت اطلاعات شامل خواندن وضعيت کيبرد ، خواندن اطلاعات بافر و سپس خطا
DIDevice.GetDeviceStateKeyboard DIState
DIDevice.GetDeviceData pBuffer, DIGDD_DEFAULT
If Err.Number = DI_BUFFEROVERFLOW Then
Msgbox(“BUFFER OVERFLOW (Compensating)...")x
GoTo ENDOFLOOP:
End If
‘بررسی فشرده شدن کليدها
For I = 0 To 255
If DIState.Key(I) = 128 And (Not KeyState(I) = True) Then
txtOutput.Text = txtOutput.Text & "{ DOWN } " & KeyNames(CInt(I))& vbCrLf
txtOutput.SelStart = Len(txtOutput.Text)x
KeyState(I) = True
End If
Next I

‘بررسی رها شدن کليد
For I = 0 To BufferSize
If KeyState(pBuffer(I).lOfs) = True And pBuffer(I).lData = 0 Then
KeyState(pBuffer(I).lOfs) = False
txtOutput.Text = txtOutput.Text & "{ UP } " & KeyNames(CInt(pBuffer(I).lOfs)) & vbCrLf
txtOutput.SelStart = Len(txtOutput.Text)x
End If
Next I

Sleep (50)x
DoEvents
ENDOFLOOP:
Loop

در کد فوق يک تابع KeyName وجود دارد که نام کليد فشارداده شده را بر می گرداند . بخشی از اين تابع را در زير می بينيد :


Function KeyNames(iNum As Integer) As String

Dim aKeys(0 To 255) As String

aKeys(1) = "DIK_ESCAPE"
aKeys(2) = "DIK_1 On main keyboard"x
aKeys(3) = "DIK_2 On main keyboard"x
aKeys(4) = "DIK_3 On main keyboard"x
aKeys(5) = "DIK_4 On main keyboard"x
aKeys(6) = "DIK_5 On main keyboard"x
aKeys(7) = "DIK_6 On main keyboard"x
aKeys(8) = "DIK_7 On main keyboard"x
aKeys(9) = "DIK_8 On main keyboard"x
aKeys(10) = "DIK_9 On main keyboard"x
aKeys(11) = "DIK_0 On main keyboard"x
aKeys(12) = "DIK_MINUS On main keyboard"x
aKeys(13) = "DIK_EQUALS On main keyboard"x
aKeys(14) = "DIK_BACK BACKSPACE"x
aKeys(15) = "DIK_TAB"x
aKeys(16) = "DIK_Q"x
aKeys(17) = "DIK_W"x
aKeys(18) = "DIK_E"x
aKeys(19) = "DIK_R"x
aKeys(20) = "DIK_T"x
.
.
.
KeyNames = aKeys(iNum)x

End Function
فهرست ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])

A_M_IT2005
15-08-2006, 02:28
سلام

آموزش DirectX Input

جلسه دوم :

موضوع : کنترل کيبرد با روش Event-Based

مقداردهی اوليه و مفاهيم اصلی در روش Event-Based مشابه روش Polling است و تنها بايستی ساختار بخش جمع آوری داده و حلقه پردازشی را تغيير دهيم . مراحل کار با روش Event-Based بصورت زير می باشد :

۱ - تعاريف و مقداردهی اوليه : در بخش تعاريف دو تعريف جديد بصورت زير داريم :

Dim hEvent As Long
Implements DirectXEvent8


hEvent يک پارامتر هندل برای يک می باشد .
نکته : زمانی که کليدی فشرده يا رها می شود ، DirectX اين امر با فراخوانی تابعی به اسم DirectXEvent8_DXCallback به برنامه شما اطلاع می دهد . ( اين نوع توابع را Call Back Function گويند ) . اين تابع به برنامه شما می گويد که يک رويداد اتفق افتاده است و بايستی بافرها را چک کند .

تنها تغييری که در بخش مقداردهی اوليه نياز است ، برپاسازی يک event می باشد :

If UseEventMethod Then
hEvent = DX.CreateEvent(frmMain)x
DIDevice.SetEventNotification hEvent
End If


در انتهای برنامه نيز کد زير را برای از بين بردن event اضافه کنيد :

If hEvent <> 0 Then DX.DestroyEvent hEvent



۲ - استفاده از event : برای اين بخش کدهايي را در داخل تابع DirectXEvent8_DXCallback می نويسيم :

Private Sub DirectXEvent8_DXCallback(ByVal eventid As Long)x
'متغيرهای موردنياز
Dim I As Long
Dim pBuffer(0 To BufferSize) As DIDEVICEOBJECTDATA
If eventid = hEvent Then
If DIDevice Is Nothing Then Exit Sub
'درصورت رخ دادن event داده را از کيبرد می گيريم
DIDevice.GetDeviceStateKeyboard DIState
DIDevice.GetDeviceData pBuffer, DIGDD_DEFAULT
'چک کردن تمام کليدها برای اينکه متوجه شويم چه اتفاقی افتاده است
For I = 0 To 255
'عدد ۱۲۸ نشان دهنده key_down event است .
If DIState.Key(I) = 128 Then
If pBuffer(0).lData = 128 Then
txtOutput.Text = txtOutput.Text & "{ DOWN } " & KeyNames(CInt(I)) & vbCrLf
End If
End If
'کد فوق برای بررسی فشرده شدن يک کليد بود . کد زير رها شدن کليد را بررسی می کند
If (pBuffer(0).lData = 0 And pBuffer(0).lOfs = I) Then
txtOutput.Text = txtOutput.Text & "{ UP }" & KeyNames(CInt(I)) & vbCrLf
End If

txtOutput.SelStart = Len(txtOutput.Text)x
Next I
End If
End Sub

فهرست ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])

A_M_IT2005
17-08-2006, 02:05
سلام

آموزش DirectX Input

جلسه آخر :

موضوع : کنترل ماوس با DirectX Input

مقدمه :

برای استفاده از ماوس در برنامه های مالتی مديا و بازيها همانند کی برد می توانيم از امکانات دايرکت ايکس استفاده کنيم . روش کنترل ماوس توسط DirectX Input بسيار ساده بوده و مشابه کنترل کيبرد می باشد بنابراين درصورتی که دو درس گذشته را نخوانده اين پيشنهاد می کنم ابتدا آنها را مطالعه کنيد .

برپاسازی Device :

علاوه بر متغيرهايي که در بخش کنترل کيبرد تعريف شد بايستی متغيرهای جديد زير را نيز در ابتدای برنامه تان تعريف کنيد :

Private Const mSpeed As Single = 2
Private Const BufferSize As Long = 10
Private mPosition As Point


mSpeed مقدار سرعت حرکت کرسر ماوس را مشخص می کند .
BufferSize سايز بافر DI می باشد .
mPosition موقعيت جاری کرسر ماوس را نشان می دهد .

در مرحله بعدی بايستی مقداردهي های اوليه لازم را انجام دهيد :

Set DIDevice = DI.CreateDevice("guid_SysMouse")x
Call DIDevice.SetCommonDataFormat(DIFORMAT_MOUSE)x
Call DIDevice.SetCooperativeLevel(frmMain.hWnd, DISCL_FOREGROUND Or DISCL_EXCLUSIVE)x


تفاوت عمده کدهای فوق با کدهای مقداردهی اوليه در بخش کی برد آنست که cooperativelevel تغيير کرده است . در اينجا گفته شده که ما می خواهيم از ماوس بصورت انحصاری در برنامه استفاده کنيم . اين حالت برای برنامه های window-base مناسب نيست و بهترست از آن در بازيهايي که بصورت full screan هستند استفاده کنيد .

خواندن ورودی از ماوس :

در اين بخش می توانيد هم از روش polling و هم event-based استفاده کنيد . نکته مهمی که در اينجا وجود دارد آنست که Direct Input فقط حرکت داده شدن ماوس و کليک شدن يک دکمه را به شما اطلاع می دهد و برای تشخيص حالتهای double click و single click خودتان بايستی کد بنويسيد برای مثال اگر فاصله زمانی بين دو کليک کمتر از ۴۰ ميلی ثانيه باشد آنگاه اين يک double click بوده است .
کد زير حرکت داده شدن ماوس و کليک يکی از سه دکمه آنرا اطلاع می دهد :

Dim DevData(1 To BufferSize) As DIDEVICEOBJECTDATA
Dim nEvents As Long
Dim I As Long
nEvents = DIDevice.GetDeviceData(DevData, DIGDD_DEFAULT)x
For I = 1 To nEvents
Select Case DevData(I).lOfs
Case DIMOFS_X
mPosition.x = mPosition.x + (DevData(I).lData * mSpeed)x
If mPosition.x < 0 Then mPosition.x = 0
If mPosition.x > frmMain.ScaleWidth Then mPosition.x = frmMain.ScaleWidth
imgCursor.Top = mPosition.y
imgCursor.Left = mPosition.x
lablel(1).Caption = "Mouse Coordinates: [" & mPosition.x & ", " & mPosition.y & "]"x
Case DIMOFS_Y
mPosition.y = mPosition.y + (DevData(I).lData * mSpeed)x
If mPosition.y < 0 Then mPosition.y = 0
If mPosition.y > frmMain.ScaleHeight Then mPosition.y = frmMain.ScaleHeight
imgCursor.Top = mPosition.y
imgCursor.Left = mPosition.x
lablel(1).Caption = "Mouse Coordinates: [" & mPosition.x & ", " & mPosition.y & "]"x
Case DIMOFS_BUTTON0
label(2).Caption = "Button 0 State: " & IIf(DevData(I).lData = 0, "Up", "Down")x
Case DIMOFS_BUTTON1
label(3).Caption = "Button 1 State: " & IIf(DevData(I).lData = 0, "Up", "Down")x
Case DIMOFS_BUTTON2
label(4).Caption = "Button 2 State: " & IIf(DevData(I).lData = 0, "Up", "Down")x
Case DIMOFS_BUTTON3
label(5).Caption = "Button 3 State: " & IIf(DevData(I).lData = 0, "Up", "Down")x
End Select
Next I


برای استفاده از کد فوق در روش Polling ، بايستی آنرا در يک حلقه Do while-Loop قرار دهيد .
برای استفاده از کد فوق در روش Event-Based ، بايستی آنرا درون روتين DirectXEvent8_DXCallback قرار دهيد .

فهرست ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])

A_M_IT2005
17-08-2006, 02:38
سلام

مباحث پيشرفته Direct3D

جلسه اول

موضوع : ساخت يک موتور گرافيکي سه بعدي

در اين درس يک Engine سه بعدي ساخته و از امکانات آن در يک برنامه نمونه استفاده خواهيم کرد .
اين engine داراي دو کلاس است :
1 – کلاس MainD3D
2 – کلاس D3Dobject
در کلاس MainD3D متغيرها و توابع لازم براي ساخت يک device سه بعدي ، تنظيمات ماتريسي ، تابع رندر و غيره موجود مي باشد .
متغيرهاي عمومي اين کلاس عبارتند از :
Public g_DX As New DirectX8
Public g_D3D As Direct3D8
Public g_D3DX As New D3DX8
Public g_D3DDevice As Direct3DDevice8
Public NTextures As Long
روتين ها و توابع اين کلاس عبارتند از :
1 - InitD3D : اين روتين ، اشيا D3D و D3Ddevice را مي سازد و پارامترهاي آنها را تنظيم مي کند .
2 – ApplyCameraChanges : روتين ايجاد ماتريس View
3 – SetupMatrices : روتين ايجاد ماتريس Projection
4 – StartRender : در اين روتين عمليات لازم براي شروع عمل رندر صورت مي گيرد .
5 – RenderObject : اين تابع ، يک شي سه بعدي از نوع کلاس D3Dobject را مي گيرد و بردارهاي مورد نياز و نيز بافت شي را تنظيم مي کند و در پايان شي را ترسيم مي کند .
6 – FinishRender : در اين روتين به عمليات رندر پايان داده مي شود .
7 – Cleanup: روتين از بين بردن اشيا Direct3D
8 – CreateVector : تابع ساخت يک بردار سه بعدي
9 – CreateTextures : روتين ساخت يک بافت جديد
10 – InitTexture: تابع مقداردهي به يک بافت
در کلاس D3Dobject متغيرها و توابع لازم براي ايجاد يک شي سه بعدي و اختصاص بافت به آن موجود مي باشد .
در اين کلاس دو type عمومي تعريف شده است :
1 - NormalVERTEX
2 - TeturedVERTEX
همچنين روتين ها و توابع اين کلاس عبارتند از :
1 – InitObject : تابعي که تنظيمات اوليه vertex ها و بافت شي را انجام مي دهد .
2 – Vertex : روتين ايجاد vertex هاي مورد نياز
3 – GetRenderingMode: تابعي که مد رندر را مشخص مي کند .
و نيز يکسري تابع ساخت vertex نرمال و ساخت vertex داراي بافت و غيره

اين دو کلاس در يک پروژه ويژوال بيسيک قرارداده شده و پروژه با نام D3Dengine.dll کامپايل شده است .
حال با استفاده از اين engine مي خواهيم يک منظره سه بعدي را ايجاد کنيم :
اين منظره شامل سه object است : ديوار ، آسمان و زمين.

ابتدا بايد يک شي از کلاس MainD3D تعريف کنيم :

Dim D3D8Main As MainD3D8
در متد Form Load نيز سه شي Floor ، Sky و Wall را بصورت زير تعريف مي کنيم :

Dim Floor As D3DObject
Dim Sky As D3DObject
Dim Walls As D3Dobject

سپس اين سه شي را به اضافه شي D3D8Main ، ايجاد مي کنيم :

Set D3D8Main = New D3DEngine.MainD3D8
Set Floor = New D3DEngine.D3DObject
Set Sky = New D3DEngine.D3DObject
Set Walls = New D3DEngine.D3Dobject
در ابتدا شي MainD3D را Initial مي کنيم و سپس بافتهاي مورد نيز خود را مي سازيم :

D3D8Main.InitD3D True, Me.hWnd
D3D8Main.CreateTextures 3
D3D8Main.InitTexture 1, App.Path + "\floor.jpg"
D3D8Main.InitTexture 2, App.Path + "\sky.bmp"
D3D8Main.InitTexture 3, App.Path + "\wall.bmp"

حال به سراغ ايجاد و مقداردهي vertex هاي floor مي رويم . floor شامل شش vertex مي باشد و بنابراين دو face مثلثي دارد :

Floor.InitObject 6, 2, TriangleList, True, 1

Floor.Vertex 0, -55, -2, -55, vbWhite, 0, 10
Floor.Vertex 1, 55, -2, -55, vbWhite, 10, 10
Floor.Vertex 2, 55, -2, 55, vbWhite, 10, 0
Floor.Vertex 3, -55, -2, -55, vbWhite, 0, 10
Floor.Vertex 4, 55, -2, 55, vbWhite, 10, 0
Floor.Vertex 5, -55, -2, 55, vbWhite, 0, 0
سپس به سراغ ايجاد و مقداردهي vertex هاي wall مي رويم . wall شامل بيست و چهار vertex مي باشد و بنابراين هشت face مثلثي دارد :

Walls.InitObject 24, 8, TriangleList, True, 3

Walls.Vertex 0, -55, -2, -55, &HBCE8FC, 0, 1
Walls.Vertex 1, 55, -2, -55, &HBCE8FC, 5, 1
Walls.Vertex 2, 55, 8, -55, &HBCE8FC, 5, 0
Walls.Vertex 3, -55, -2, -55, &HBCE8FC, 0, 1
Walls.Vertex 4, 55, 8, -55, &HBCE8FC, 5, 0
Walls.Vertex 5, -55, 8, -55, &HBCE8FC, 0, 0

Walls.Vertex 6, -55, -2, 55, &HBCE8FC, 0, 1
Walls.Vertex 7, 55, -2, 55, &HBCE8FC, 5, 1
Walls.Vertex 8, 55, 8, 55, &HBCE8FC, 5, 0
Walls.Vertex 9, -55, -2, 55, &HBCE8FC, 0, 1
Walls.Vertex 10, 55, 8, 55, &HBCE8FC, 5, 0
Walls.Vertex 11, -55, 8, 55, &HBCE8FC, 0, 0

Walls.Vertex 12, -55, -2, 55, &HBCE8FC, 0, 1
Walls.Vertex 13, -55, -2, -55, &HBCE8FC, 5, 1
Walls.Vertex 14, -55, 8, -55, &HBCE8FC, 5, 0
Walls.Vertex 15, -55, -2, 55, &HBCE8FC, 0, 1
Walls.Vertex 16, -55, 8, -55, &HBCE8FC, 5, 0
Walls.Vertex 17, -55, 8, 55, &HBCE8FC, 0, 0

Walls.Vertex 18, 55, -2, 55, &HBCE8FC, 0, 1
Walls.Vertex 19, 55, -2, -55, &HBCE8FC, 5, 1
Walls.Vertex 20, 55, 8, -55, &HBCE8FC, 5, 0
Walls.Vertex 21, 55, -2, 55, &HBCE8FC, 0, 1
Walls.Vertex 22, 55, 8, -55, &HBCE8FC, 5, 0
Walls.Vertex 23, 55, 8, 55, &HBCE8FC, 0, 0

حال به سراغ ايجاد و مقداردهي vertex هاي sky مي رويم . sky شامل شش vertex مي باشد و بنابراين دو face مثلثي دارد :

Sky.InitObject 6, 2, TriangleList, True, 2

Sky.Vertex 0, -55, 8, -55, &HBCE8FC, 0, 1
Sky.Vertex 1, 55, 8, -55, &HBCE8FC, 0, 1
Sky.Vertex 2, 55, 8, 55, &HBCE8FC, 0, 1
Sky.Vertex 3, -55, 8, -55, &HBCE8FC, 0, 1
Sky.Vertex 4, 55, 8, 55, &HBCE8FC, 0, 1
Sky.Vertex 5, -55, 8, 55, &HBCE8FC, 0, 1

در پايان تابع رندر را صدا مي کنيم . البته در هر بار عمل رندر کردن ، دوربين يک درجه در صفحه X-Z دوران مي کند تا کل ديوار قابل مشاهده باشد :

Dim Angle As Double
PI = 3.1415
Angle = 0
Do
DoEvents
D3D8Main.StartRender vbBlack
D3D8Main.RenderObject Sky
D3D8Main.RenderObject Floor
D3D8Main.RenderObject Walls
D3D8Main.FinishRender
If Sqr(Angle ^ 2) = 360 Then Angle = 0
Angle = Angle + 1
D3D8Main.CamLookAtX = Sin((Angle * 2 * PI) / 360)
D3D8Main.CamLookAtZ = Cos((Angle * 2 * PI) / 360)
D3D8Main.ApplyCameraChanges
Loop

فهرست ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])

A_M_IT2005
18-08-2006, 03:18
سلام

مباحث پيشرفته Direct3D

جلسه دوم :

موضوع : استفاده از object هاي 3D Studio Max در Direct3D
تا بحال ما هر شيي را که مي خواستيم در Direct3D بسازيم خودمان بوسيله کد نويسي آنرا توصيف کرده ايم . ممکنست اين سوال برايتان پيش آمده باشد که بازيهاي تجاري براي توليد کاراکترهاي و اشيا پيچيده سه بعدي چگونه عمل مي کنند ؟
منطقي بنظر نمي رسد که اينگونه مدلهاي پيچيده بصورت کد وارد برنامه شده اند زيرا نياز به هزاران خط برنامه براي هر فريم خواهد بود . بجاي اينکار ما object هاي خود را توسط برنامه هاي ديگري مي سازيم و آنها را در برنامه خودمان load مي کنيم سپس بافتها و material هاي مورد نظر را به آنها اختصاص داده و در پايان آنها را رندر مي کنيم . مزيت ديگر اينکار اينست که شما مي توانيد براحتي فايل object خود را تغيير دهيد و مدلهايي با جزئيات متفاوت براي برنامه خود قرار دهيد .
مراحل ساخت چنين برنامه هايي بصورت زير است :

۱ - ساخت object سه بعدي :
اولين چيزي که بايستي بدانيد داشتن دانش پايه اي از چگونگي مدلسازي سه بعدي است . همچنين نياز به يک نرم افزار مدلسازي مثل 3D Studio Max داريد .

بعد از ساخت مدل خود در Max نياز به يک Convertor داريد تا فايلهاي Max را به فايلهاي Direct3D که با فرمت "X." هستند تبديل کنيد .
Convertor هاي زيادي براي تبديل فايلهاي نرم افزارهاي مدلسازي به فايلهاي "X." وجود دارند که برخي از آنها عبارتند از :
- برنامه PolyTrans3D System Translation
- برنامه Deep Exploration 2.0
- برنامه Quick3D
- برنامه 3DWin
- DirectX Explorer Plugin
- ابزارهاي موجود در DirectX 8.0 SDK که عبارتند از :
برنامه Conv3DS براي تبديل فايلهاي 3DS به فايلهاي X
DX SDK Exporter Plugin براي تبديل فايلهاي 3DS و Max به فايلهاي X
از بين اين برنامه ها و plugin ها من برنامه Deep Exploration را به شما پيشنهاد مي کنم .

در آدرس زير مي توانيد اطلاعات بيشتري در مورد اين برنامه بدست آوريد و همچنين آنرا Download کنيد :
[ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]
s/n: 0XE2A0000000000
Authorization s/n: REJ1HYXSR1A77Q10

2 - Load کردن يک Object ساخته شده :
زمانيکه فايل X شي مورد نظر را ساختيد ، load کردن آن در direct3D ساده است . براي اينکار نياز به يک مش داريم که اطلاعات شي ما را نگهداري کند :

Dim Mesh As D3DXMesh
همچنين براي اختصاص material و texture به شي ، نياز به تعريف متغيرهاي زير داريم :

Dim MeshMaterial As D3DMATERIAL8
Dim MeshTexture As Direct3DTexture8

حال به سراغ بازنويسي روتين InitGeometry مي رويم :
- تعريف متغيرهاي مورد نياز :

Dim mtrlBuffer as D3DXBuffer
Dim TextureFile as String
Dim n as Long

- گرفتن داده هاي شي از فايل X :

Set Mesh=D3DX.LoadMeshFromX app.path&"\"&"yourfilename",D3DMESH_MANAGED,D3DDevice,Nothing,mtrlBuffer,n

- استخراج اطلاعات materiasl شي و تنظيم پارامتر Ambient :

D3DX.BufferGetMaterial mtrlBuffer,0,MeshMaterial
MeshMaterial.Ambient=MeshMaterial.Diffuse

- استخراج نام بافت بکار رفته براي شي :

TextureFile=D3DX.BufferGetTextureName(mtrlBuffer,0 )x
- ساخت بافت :

If TextureFile<>"" Then
Set MeshTexture=D3DX.CreateTextureFromFile D3DDevice,app.path&"\"&TextureFile,128,128,D3DX_DEFAULT,0,
D3DFMT_UNKNOWN,D3DPOOL_MANAGED,D3DX_FILTER_LINEAR, D3DX_FILTER_LINEAR,0,Byval 0,Byval 0
End If

۳ - رندر نمودن شي : رندر نمودن شي چندان مشکل نيست اما همچنان بايد ماتريسها و تبديلاتي را که مي خواهيد ، خودتان مديريت کنيد .

D3DDevice.SetMaterial MeshMaterial
D3DDevice.SetTexture 0,MeshTexture
Mesh.DrawSubset 0

فهرست ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])

A_M_IT2005
21-08-2006, 03:17
سلام
اگه زحمتی نیست یه نظری هم بدین که من بفهمم به درد کسی خورده یا نه.

مباحث پيشرفته Direct3D

جلسه سوم :

موضوع : مباحث تکميلي نورپردازي در Direct3D

در بخش اول آموزش Direct3D با مباني نورپردازي آشنا شديد . در اين درس قصد دارم آن مباحث را کاملتر برايتان مطرح کنم .
نورپردازي يکي از بخشهاي مهم طراحي يک بازي و يا يک انيميشن سه بعدي است . بمنظور پياده سازي نورپردازي يک صحنه ابتدا بايد با تئوري آن آشنا شويد .
تئوري نورپردازي : نورپردازي در Direct3D تخميني از چگونگي عملکرد نور در دنياي واقعي مي باشد . چهار نوع اصلي نور در Direct3D قابل استفاده است ( همچنين شما مي توانيد خودتان انواع جديدي از نور ايجاد کنيد که موضوع ما نيست ) :
۱ - Point Light : توسط يک نقطه در فضاي سه بعدي ايجاد مي شود و داراي سه پارامتر رنگ ، دامنه و تضعيف مي باشد . دامنه يک نور مسافتي است که نور مي تواند طي کند . تضعيف ، مقدار کاهش نور در اثر افزايش مسافت مي باشد . نور نقطه اي در تمام جهات تششع مي کند - شبيه يک لامپ حبابي و يا يک شمع
۲ - Spot Light : داراي يک موقعيت و يک جهت است و تنها نور را در يک جهت خاص مي تاباند - شبيه يک چراغ قوه . اين نور داراي يک زاويه مخروطي و يک دامنه است .
۳ - Directional Light : داراي موقعيت نيست و براي پياده سازي نورهايي که از فاصله بسيار دور مي آيند - مثل خورشيد - مناسب است .
۴ - Ambient Light : اين نور تضمين مي کند که تمام vertex هاي يک صحنه تاريکتر از يک رنگ خاص نباشند .
عملي کردن نورپردازي : ضمن اينکه اغلب کارت هاي گرافيک سه بعدي از نورپردازي پشتيباني مي کنند اما اين نکته بايد مورد توجه قرار گيرد که با افزايش تعداد نور در يک صحنه محاسبات Direct3D بيشتر مي شود و اين باعث کند شدن رندر صحنه خواهد شد و بنابراين کارت هاي گرافيکي سه بعدي نيز داراي يک ماکزيمم تعداد نور هستند - مثلاً ۱۶ نور در GeForce 2 - همچنين توجه داشته باشيد که نورهاي مختلف داراي زمان پردازشي متفاوتي هستند . نور ambient سريعترين زمان پردازشي را دارد ، سپس نورdirectional ، سپس نور point و کندترين آنها Spot Light است .
همچنين نکته ديگري که بايد توجه کنيد دامنه نور است . اگر نور ، يک منطقه بزرگي را پوشش دهد بر تعداد زيادي از vertex ها تاثير مي گذارد و اين باعث افزايش محاسبات مي شود .
نورپردازي Specular - که در درسهاي بعدي در مورد آن صحبت مي کنم و براي ايجاد اشيا درخشان استفاده مي شود - نيز زمان پردازشي زيادي دارد و بهتر است کمتر از آن استفاده شود .
پارامتر ديگري که بايد در نظر بگيريد جزئيات هندسه شما مي باشد . هر چه پيچيدگي صحنه بيشتر باشد ، نورپردازي نيز زمان بيشتري را مصرف مي کند .
سايه زني نيز يک بخش بسيار پيچيده در مدل سازي نور است و محاسبات آن بسيار زمان گير خواهد بود بنابراين Direct3D مستقيماً محاسبات سايه زني را انجام نمي دهد بلکه رنگ نور را بر مبناي جهت هر مثلث scale مي کند بنابراين قسمت پشتي يک شي که رو به نور نيست ، هيچ نوري را دريافت نمي کند .

بردار نرمال : Direct3D هر vertex را بر مبناي بک بردار نرمال نورپردازي مي کند و نوري که يک vertex دريافت مي کند به زاويه بين نور و بردار نرمال آن vertex بستگي دارد . بردار نرمال توسط سه vertex يک face مثلثي ايجاد مي شود و اين بردار نرمال ساخته شده به vertex ها اختصاص مي يابد . بردار نرمال در واقع سمت يک مثلث را مشخص مي کند بنابراين اگر نور پشت مثلث باشد ، مثلث هيچ نوري را دريافت نميکند . بردار نرمال بايستي داراي طول ۱ باشد .
مراحل توليد بردار نرمال يک face مثلثي :
۱ - مطمئن شويد که face در جهت عقربه هاي ساعت ساخته شده است .
۲ - يک بردار از vertex شماره صفر به vertex شماره يک بسازيد .
۳ - يک بردار از vertex شماره صفر به vertex شماره دو بسازيد .
۴ - حاصلضرب برداري ( cross droduct ) اين دو بردار را بدست آوريد .
۵ - نتيجه حاصلضرب را نرمال کنيد .

Private Function GenerateTriangleNormals(p0 As UnlitVertex, p1 As UnlitVertex, p2 As UnlitVertex) As D3DVECTOR
Dim v01 As D3DVECTOR
Dim v02 As D3DVECTOR
Dim vNorm As D3DVECTOR
D3DXVec3Subtract v01, MakeVector(p1.X, p1.Y, p1.Z), MakeVector(p0.X, p0.Y, p0.Z)x
D3DXVec3Subtract v02, MakeVector(p2.X, p2.Y, p2.Z), MakeVector(p0.X, p0.Y, p0.Z)x
D3DXVec3Cross vNorm, v01, v02
D3DXVec3Normalize vNorm, vNorm
GenerateTriangleNormals.X = vNorm.X
GenerateTriangleNormals.Y = vNorm.Y
GenerateTriangleNormals.Z = vNorm.Z
End Function


اگر دو face در يک vertex مشترک باشند ( مثل گوشه دو ديوار ) براي توليد نرمال اين vertex ابتدا نرمال دو face را با روش فوق بدست آوريد سپس دو بردار نرمال را با هم جمع کنيد و در پايان بردار حاصلجمع را نرمال کنيد .

برپاسازي نورپردازي : اولين چيزي که قبل از برپاسازي نورپردازي بايستي اعمال کنيم تغيير ساختار vertex است . براي اينکار بايد پارامتر color را از ساختار vertex حذف و سه پارامتر را براي نگهداري نرمال اضافه کنيم :

Private Type UnlitVertex
X As Single
Y As Single
Z As Single
nx As Single
ny As Single
nz As Single
tu As Single
tv As Single
End Type
Const Unlit_FVF = (D3DFVF_XYZ Or D3DFVF_NORMAL Or D3DFVF_TEX1)x

همچنين بايد براي تمام vertex هاي شي خود بردار نرمال را محاسبه کنيد براي مثال اگر شي شما يک مکعب است براي هر ۱۲ face آن بردار نرمال را بدست آوريد . در زير من کد لازم براي ساخت نرمال يکي از اين face ها را نوشته ام :

Cube2(0) = CreateVertex(-1, -1, 1, 0, 0, 0, 0, 0)x
Cube2(1) = CreateVertex(1, 1, 1, 0, 0, 0, 1, 1)x
Cube2(2) = CreateVertex(-1, 1, 1, 0, 0, 0, 0, 1)x
vN = GenerateTriangleNormals(Cube2(0), Cube2(1), Cube2(2))x
Cube2(0).nx = vN.X: Cube2(0).ny = vN.Y: Cube2(0).nz = vN.Z
Cube2(1).nx = vN.X: Cube2(1).ny = vN.Y: Cube2(1).nz = vN.Z
Cube2(2).nx = vN.X: Cube2(2).ny = vN.Y: Cube2(2).nz = vN.Z

براي برپا سازي نور ابتدا بايستي يک material به device خود اضافه کنيد :

Dim Mtrl As D3DMATERIAL8, Col As D3DCOLORVALUE
Col.a = 1: Col.r = 1: Col.g = 1: Col.b = 1
Mtrl.Ambient = Col
Mtrl.diffuse = Col
D3DDevice.SetMaterial Mtrl

سپس بايستي طوري device خود را تنظيم کنيد که نور شما را بشناسد - lights يک شي از نوع D3DLight8 است - يکبار که اين خط را بنويسيد مي توانيد از نور استفاده کنيد اما اگر خصوصيات نور را تغيير دهيد بايستي دوباره اين دستور را فراخواني کنيد :

D3DDevice.SetLight 0, Lights

حال بايد نور را روشن کنيد :

D3DDevice.LightEnable 0, 1

و در پايان بايد به Direct3D بگوئيد که نورپردازي را براي شما انجام دهد :

D3DDevice.SetRenderState D3DRS_LIGHTING, 1

چگونگي ايجاد يک نور : براي ايجاد هر يک از ۴ نوع اصلي نور بايد به روشي خاص عمل کنيد :
۱ - نورپردازي Ambient : اين نوع نورپردازي بسيار ساده است و تنها با فراخواني تابع SetRenderState ايجاد مي شود . رنگ ambient يک عدد هگزادسيمال بصورت RRGGBB است :

D3DDevice.SetRenderState D3DRS_AMBIENT, &H202020

۲ - نورپردازي Directional : داراي دو پارامتر رنگ و جهت مي باشد :

Lights.Type = D3DLIGHT_DIRECTIONAL
Lights.diffuse.r = 1
Lights.diffuse.g = 1
Lights.diffuse.b = 1
Lights.Direction = MakeVector(0, -1, 0)x

3 - نورپردازي Point : داراي سه پارامتر موقعيت ، رنگ و تضعيف مي باشد :

Lights.Type = D3DLIGHT_POINT
Lights.position = MakeVector(5, 0, 2)x
Lights.diffuse.b = 1
Lights.Range = 100
Lights.Attenuation1 = 0.05

۴ - نورپردازي Spot : اين نور داراي دو مخروط است که نقاط خارج مخروط اول روشنتر از نقاط داخل آن هستند . دو زاويه براي مخروط وجود دارد - زاويه داخلي theta و زاويه خارجي phi - که برحسب راديان هستند :


Lights.Type = D3DLIGHT_SPOT
Lights.position = MakeVector(-4, 0, 0)x
Lights.Range = 100
Lights.Direction = MakeVector(1, 0, 0)x
Lights.Theta = 30 * (Pi / 180)x
Lights.Phi = 50 * (Pi / 180)x
Lights.diffuse.g = 1
Lights.Attenuation1 = 0.05

A_M_IT2005
22-08-2006, 02:31
سلام

مباحث پيشرفته Direct3D

جلسه چهارم :

موضوع : استفاده از Index Buffer براي ذخيره سازي اشکال سه بعدي

مقدمه : مکعبي که در درسهاي قبلي ساختيم را درنظر بگيريد . با دانشي که اکنون داريد ، دو راه براي ساخت يک مکعب داريم : ۱ - استفاده از 36 عدد vertex براي تعريف face هاي مکعب ۲ - ساخت مکعب با استفاده از يک مدلساز و ذخيره آن با فرمت X
روش اول غيرکارامد است زيرا شما بايستي از تعداد زيادي vertex براي يک شکل بسيار ساده استفاده کنيد . روش دوم مناسب است اما زمانيکه بخواهيم رنگها و بافتها را تغيير دهيم دچار مشکل خواهيم شد . روش جديدي که امروز در مورد آن صحبت مي کنم استفاده ار Index Buffer است .
Index Buffer شامل يکسري عدد integer است که اين اعداد مرجعي براي vertex هاي ذخيره شده در يک Vertex Buffer هستند . براي مثال فرض کنيد يک Vertex Buffer شامل 8 عدد vertex داريم که يک مکعب را براي ما توصيف مي کند . ما مي توانيم يک Index Buffer با ۳۶ عضو بسازيم بطوريکه ترتيب اتصال vertex ها را براي ما مشخص کنند . مثلاً Index هاي ۰ و ۱و ۳ براي مشخص کردن face شماره ۱ مکعب بکار مي روند . بنابراين بجاي استفاده از ۳۶ عدد vertex مي توانيم مکعب را با ۸ عدد vertex و يک Index Buffer بسازيم .
گرچه استفاده از Index Buffer بسيار کارامد است اما چندين محدوديت در استفاده از آن وجود دارد . مهمترين آنها اينست که تمام انديسهايي که يک vertex مشابه را share مي کنند بايستي خصوصيات مشابهي داشته باشند - موقعيت ، رنگ ، بافت و نرمال يکسان - براي مثال نمي توانيد مکعبي بسازيد که هر face آن يک رنگ داشته باشد .

ساخت Index Buffer : ابتدا به متغيرهاي زير نياز داريم :

Dim VBuffer as Direct3DVertexBuffer8
Dim IBuffer as Direct3DIndexBuffer8
Dim Vlist(0 to 7) as LITVERTEX
Dim Ilist(0 to 35) as Integer


تابع InitGeometry بصورت زير بازنويسي مي شود:
۱- توليد هشت vertex براي مکعب :

Vlist(0) = CreateLitVertex(-1, -1, -1, &HFF0000, 0, 0, 0)x
Vlist(1) = CreateLitVertex(-1, 1, -1, &HFF00&, 0, 0, 0)x
Vlist(2) = CreateLitVertex(1, -1, -1, &HFF&, 0, 0, 0)x
Vlist(3) = CreateLitVertex(1, 1, -1, &HFF00FF, 0, 0, 0)x
Vlist(4) = CreateLitVertex(-1, -1, 1, &HFFFF00, 0, 0, 0)x
Vlist(5) = CreateLitVertex(-1, 1, 1, &HFFFF, 0, 0, 0)x
Vlist(6) = CreateLitVertex(1, -1, 1, &HFFCC00, 0, 0, 0)x
Vlist(7) = CreateLitVertex(1, 1, 1, &HFFFFFF, 0, 0, 0)x


۲ - ايجاد Vertex Buffer توسط تابع CreateVertexBuffer :

Set VBuffer = D3DDevice.CreateVertexBuffer(Len(Vlist(0)) * 8, 0, Lit_FVF, D3DPOOL_DEFAULT)x
D3DVertexBuffer8SetData VBuffer, 0, Len(Vlist(0)) * 8, 0, Vlist(0)x


۳ - توليد index ها :

front '
Ilist(0) = 0: Ilist(1) = 1: Ilist(2) = 2
Ilist(3) = 1: Ilist(4) = 3: Ilist(5) = 2
Right '
Ilist(6) = 2: Ilist(7) = 3: Ilist(8) = 6
Ilist(9) = 3: Ilist(10) = 7: Ilist(11) = 6
Back '
Ilist(12) = 6: Ilist(13) = 7: Ilist(14) = 4
Ilist(15) = 7: Ilist(16) = 5: Ilist(17) = 4
Left '
Ilist(18) = 4: Ilist(19) = 5: Ilist(20) = 0
Ilist(21) = 5: Ilist(22) = 1: Ilist(23) = 0
Top '
Ilist(24) = 1: Ilist(25) = 5: Ilist(26) = 3
Ilist(27) = 5: Ilist(28) = 7: Ilist(29) = 3
Bottom '
Ilist(30) = 2: Ilist(31) = 6: Ilist(32) = 0
Ilist(33) = 6: Ilist(34) = 4: Ilist(35) = 0


۴ - ايجاد Index Buffer توسط تابع CreateIndexBuffer :

Set IBuffer = D3DDevice.CreateIndexBuffer(Len(Ilist(0)) * 36, 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT)x
D3DIndexBuffer8SetData IBuffer, 0, Len(Ilist(0)) * 36, 0, Ilist(0)x


تابع Render : براي رندر کردن اين مکعب دو روش وجود دارد :
۱ - استفاده از تابع DrawIndexedPrimitive : در اين روش از VBuffer و IBUffer و آرايه vertex ها استفاده مي شود :

Public Sub Render()x
D3DDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET Or D3DCLEAR_ZBUFFER, 0, 1#, 0
D3DDevice.BeginScene
D3DDevice.SetStreamSource 0, VBuffer, Len(Vlist(0))x
D3DDevice.SetIndices IBuffer, 0
D3DDevice.DrawIndexedPrimitive D3DPT_TRIANGLELIST, 0, 36, 0, 12
D3DDevice.EndScene
D3DDevice.Present ByVal 0, ByVal 0, 0, ByVal 0
End Sub


۲ - استفاده از تابع DrawIndexedPrimitiveUP : در اين روش از آرايه هاي vertex و index استفاده مي شود :

Public Sub Render()x
D3DDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET Or D3DCLEAR_ZBUFFER, 0, 1#, 0
D3DDevice.BeginScene
D3DDevice.DrawIndexedPrimitiveUP D3DPT_TRIANGLELIST, 0, 8, 12, Ilist(0), D3DFMT_INDEX16, Vlist(0), Len(Vlist(0))x
D3DDevice.EndScene
D3DDevice.Present ByVal 0, ByVal 0, 0, ByVal 0
End Sub

A_M_IT2005
22-08-2006, 02:35
سلام

مباحث پيشرفته Direct3D

جلسه آخر :

موضوع : Vertex/Mesh Animation
در اين درس در مورد روشهاي ساخت انيميشن در Direct3D صحبت خواهيم کرد . انيميشن در فضاي سه بعدي در حالتهاي مختلفي مي تواند ايجاد شود که بسته به engine گرافيکي شما و ابزارهايي که ايجاد کرده ايد ، دارد . سه روش اصلي ساخت انيميشن وجود دارد که عبارتند از :
- Tween سازي دستي / درون يابي خطي ( manual tweening/linear interpolation )
- درون بابي برداري ( vector interpolation )
- درون يابي بر اساس فريم کليدي ( keyframe interpolation )

1 – روش اول يکي از ساده ترين راههاي ساخت انيميشن است . اين روش در زمانيکه با مدلهاي پيچيده سر و کار داريد مناسب نيست – و يا مدلهايي با تعداد زيادي vertex – اين روش نوعي tween کردن است که از مزيت index buffer ها استفاده مي کند .
درون يابي ، چگونگي تغييرات شيي در طول يک زمان مشخص مي باشد . در درسهاي قبلي شما درون يابي رنگ را روي يک شي ديديد که در آن يک رنگ بطور ملايم به رنگ ديگري تبديل مي شد ( fadeشدن ( . درون يابي خطي نيز مشابه آن است . براي درون يابي خطي از موقعيت A به موقعيت B از فرمول زير استفاده مي شود :
(B*V)+A*(1-V)
که A و B مختصاتهاي مبدا و مقصد هستند و V ضريب درون يابي است که عددي بين صفر و يک مي باشد . اين فرمول مختصات نقطه tween را در هر لحظه مشخص مي کند .
همانطور که مي بينيد بکار بردن اين فرمول براي يک شي با تعداد زيادي vertex بسيار وقت گير بوده و fram rate را پايين مي آورد .
تابع زير دو vertex و يک مقدار ضريب درون يابي را مي گيرد تا نقطه tween را محاسبه کند :

Private Function TweenVertices(Source As LITVERTEX, Dest As LITVERTEX, TweenAmount As Single) As LITVERTEX
TweenVertices.X = (Dest.X * TweenAmount) + Source.X * (1# - TweenAmount)x
TweenVertices.Y = (Dest.Y * TweenAmount) + Source.Y * (1# - TweenAmount)x
TweenVertices.Z = (Dest.Z * TweenAmount) + Source.Z * (1# - TweenAmount)x
TweenVertices.color = Source.color
End Function


اگر شما از vertex هاي UNLIT استفاده کنيد – vertex هايي با بردار نرمال – در اينصورت بايد کد فوق را تغيير دهيد و بايد tween را از نرمال مبدا به نرمال مقصد نيز انجام دهيد .
همانطور که مي بينيد رنگ tween vertex نيز تنظيم شده است . در يک تابع tweening مناسبتر مي توانيد رنگها ، مختصات بافت و مقادير specular را نيز tween کنيد .
محدوديتي که اين روش دارد اينست که خطي است و براي مدل کردن حرکتهاي غير خطي درست کار نمي کند .
حال مي خواهيم از تابع tween استفاده کنيم تا يک مکعب را در يک انيميشن به يک هرم تبديل کنيم . ابتدا سه شي را بصورت زير تعريف مي کنيم :

در ابتداي انيميشن ، شي current cube همان source cube است’
CubeVertices(0) = CreateLitVertex(-1, -1, -1, &HFF0000, 0, 0, 0)x
CubeVertices(1) = CreateLitVertex(-1, 1, -1, &HFF00&, 0, 0, 0)x
CubeVertices(2) = CreateLitVertex(1, -1, -1, &HFF&, 0, 0, 0)x
CubeVertices(3) = CreateLitVertex(1, 1, -1, &HFF00FF, 0, 0, 0)x
CubeVertices(4) = CreateLitVertex(-1, -1, 1, &HFFFF00, 0, 0, 0)x
CubeVertices(5) = CreateLitVertex(-1, 1, 1, &HFFFF, 0, 0, 0)x
CubeVertices(6) = CreateLitVertex(1, -1, 1, &HFFCC00, 0, 0, 0)x
CubeVertices(7) = CreateLitVertex(1, 1, 1, &HFFFFFF, 0, 0, 0)x
مکعب اوليه’
CubeVerticesSource(0) = CreateLitVertex(-1, -1, -1, &HFF0000, 0, 0, 0)x
CubeVerticesSource(1) = CreateLitVertex(-1, 1, -1, &HFF00&, 0, 0, 0)x
CubeVerticesSource(2) = CreateLitVertex(1, -1, -1, &HFF&, 0, 0, 0)x
CubeVerticesSource(3) = CreateLitVertex(1, 1, -1, &HFF00FF, 0, 0, 0)x
CubeVerticesSource(4) = CreateLitVertex(-1, -1, 1, &HFFFF00, 0, 0, 0)x
CubeVerticesSource(5) = CreateLitVertex(-1, 1, 1, &HFFFF, 0, 0, 0)x
CubeVerticesSource(6) = CreateLitVertex(1, -1, 1, &HFFCC00, 0, 0, 0)x
CubeVerticesSource(7) = CreateLitVertex(1, 1, 1, &HFFFFFF, 0, 0, 0)x
هرم مقصد’
CubeVerticesDest(0) = CreateLitVertex(-1, -1, -1, &HFF0000, 0, 0, 0)x
CubeVerticesDest(1) = CreateLitVertex(-0.1, 1, -0.1, &HFF00&, 0, 0, 0)x
CubeVerticesDest(2) = CreateLitVertex(1, -1, -1, &HFF&, 0, 0, 0)x
CubeVerticesDest(3) = CreateLitVertex(0.1, 1, -0.1, &HFF00FF, 0, 0, 0)x
CubeVerticesDest(4) = CreateLitVertex(-1, -1, 1, &HFFFF00, 0, 0, 0)x
CubeVerticesDest(5) = CreateLitVertex(-0.1, 1, 0.1, &HFFFF, 0, 0, 0)x
CubeVerticesDest(6) = CreateLitVertex(1, -1, 1, &HFFCC00, 0, 0, 0)x
CubeVerticesDest(7) = CreateLitVertex(0.1, 1, 0.1, &HFFFFFF, 0, 0, 0)x


حال بايد در يک حلقه با استفاده از تابع twen پيکسلهاي CubeVertices را update کنيم :

Private Sub UpdateAnimation()x
Dim I As Integer
به روز کردن پارامترهاي زمان و جهت'
If AnimTweenDir = True Then
AnimTweenFactor = AnimTweenFactor + (((GetTickCount() - LastTimeTweened) / 1000)*1#)
LastTimeTweened = GetTickCount
If AnimTweenFactor >= 1# Then
AnimTweenFactor = 1#
AnimTweenDir = False
End If
Else
AnimTweenFactor = AnimTweenFactor - (((GetTickCount() - LastTimeTweened) / 1000)*1#)
LastTimeTweened = GetTickCount
If AnimTweenFactor <= 0# Then
AnimTweenFactor = 0#
AnimTweenDir = True
End If
End If
به روز کردن اطلاعات vertex ها '
For I = 0 To 7
CubeVertices(I) = TweenVertices(CubeVerticesSource(I), CubeVerticesDest(I), AnimTweenFactor)x
Next I
به روز کردن بافر vertex’
If D3DVertexBuffer8SetData(VBuffer, 0, Len(CubeVertices(0)) * 8, 0, CubeVertices(0)) = D3DERR_INVALIDCALL Then GoTo Error:
Exit Sub
Error:
Debug.Print “Error occured whilst updating the animation…”x
End Sub


زمان پايه انيميشن توسط عبارت زير تنظيم مي شود :
(((GetTickCount() - LastTimeTweened) / 1000) * 1#)
همانطور که مي دانيد دو نوع انيميشن وجود دارد : انيميشن بر مبناي frame و انيميشن بر مبناي زمان . در انيميشن بر مبناي frame شماره فريم با يک مقدار ثابت در زمان افزايش مي يابد اما اگر اينکار باعث مي شود کيفيت انيميشن در کامپيوترهاي با سرعت متفاوت تغيير کند . بنابراين انيميشن را بر مبناي زمان توليد کرده ايم . انيميشن هاي بر مبناي زمان بجاي " 1 فريم در هر سيکل " ، " 30 فريم در هر ثانيه " هستند .

2 – روش دوم از توابع کتابخانه D3DX براي انجام عمل tweening استفاده مي کند و بنابراين بهبودي در سرعت انيميشن نسبت به روش بالا حاصل مي شود . با استفاده از کتابخانه D3DX مي توانيم عمل درون يابي خطي را براي تمام اجزا اصلي يک vertex انجام دهيم . ليست زير توابعي را براي اينکار نشان مي دهد :
- تابع D3DXVec3Lerp : انجام درون يابي براي موقعيت و نرمال :

D3DXVec3Lerp( VOut as D3DVECTOR, V1 as D3DVECTOR, V2 as D3DVECTOR, S as Single)x
- VOut = The result of the interpolation
- V1 = The source coordinates
- V2 = The destination coordinates
- S = The interpolation amount - between, but not limited to, 0.0 - 1.0 scale; where 0 is the source and 1 is the destination


- تابع D3DXColorLerp : انجام درون يابي براي رنگهاي vertex :

D3DXColorLerp( COut as D3DCOLORVALUE, C1 as D3DCOLORVALUE, C2 as D3DCOLORVALUE, S as Single)x
- COut = The resulting colour
- C1 = The source colour
- C2 = The destination colour
- S = The interpolant,

on a 0.0 to 1.0 scale
- تابع D3DXVec2Lerp : انجام درون يابي براي مختصاتهاي دوبعدي :

- VOut = The result of this interpolation
- V1 = The source coordinates
- V2 = The destination coordinates
- S = The interpolant on a 0.0 to 1.0 scale

- تابع D3DXVec3Hermite : توليد يک مسير منحني که از دو نقطه کنترل عبور مي کند :

D3DXVec3Hermite( VOut as D3DVECTOR, V1 as D3DVECTOR, T1 as D3DVECTOR, V2 as D3DVECTOR, T2 as D3DVECTOR, S as Single)x
- VOut = The Result
- V1 = The Source Coordinate
- T1 = The Tangent at the Source coordinate, this is the direction and speed the line will leave the source point.
- V2 = The Destination Coordinate
- T2 = The Tangent at the Destination coordinate, this is the direction and speed the line will enter the destination point.
- S = The Interpolant Value

براي اينکه بتوانيم از کتابخانه D3DX استفاده کنيم بايد توصيف vertex هايمان را تغيير دهيم و بايستي يکسري مقادير ARGB اضافي را به ساختار vertex اضافه کنيم :

Private Type LITVERTEX
X As Single
Y As Single
Z As Single
color As Long
specular As Long
tu As Single
tv As Single
ColorEx As D3DCOLORVALUE
End Type


حال تابع tween را بصورت زير مي نويسيم :

Private Function TweenVertices(Source As LITVERTEX, Dest As LITVERTEX, TweenAmount As Single) As LITVERTEX
Dim vResult As D3DVECTOR
Dim vResult2 As D3DVECTOR2
Tween کردن موقعيت vertex ها ‘
D3DXVec3Lerp vResult, MakeVector(Source.X, Source.Y, Source.Z), MakeVector(Dest.X, Dest.Y, Dest.Z), TweenAmount
TweenVertices.X = vResult.X
TweenVertices.Y = vResult.Y
TweenVertices.Z = vResult.Z
Tween کردن اطلاعات texture ’
D3DXVec2Lerp vResult2, MakeVector2D(Source.tu, Source.tv), MakeVector2D(Dest.tu, Dest.tv), TweenAmount
TweenVertices.tu = vResult2.X
TweenVertices.tv = vResult2.Y
Tween کردن اطلاعات رنگ ‘
D3DXColorLerp TweenVertices.ColorEx, Source.ColorEx, Dest.ColorEx, TweenAmount
With TweenVertices.ColorEx
TweenVertices.color = RGB(.B * 255, .G * 255, .R * 255)x
End With
End Function

نکته اي که بايد به آن توجه کنيد اينست که در تابع فوق براي اشاره به vertex ، يک بردار ساخته شده است ( توسط تابع MakeVector ) .

3 – روش سوم پر استفاده ترين روش انيميشن سازي است . اگر شما انيميشن هاي پيچيده با تعداد زيادي شي در آن داشته باشيد و اگر بخواهيد تغييرات اشيا را در هر فريم ذخيره کنيد ، به حجم بالايي از منابع ذخيره سازي نياز است . بجاي آن ما با استفاده از يکسري فريم کليدي ، فريمهاي مياني را پيش بيني مي کنيم .
براي انجام درون يابي فريم کليدي ، بايستي مقدار vertex را در هر فريم کليدي بدانيم و نيز بدانيم هر فريم کليدي در چه زماني ظاهر مي شود . بنابراين بايد براي هر انيميشن چند فايل را بعنوان فريم کليدي ذخيره کنيم .
در اين درس ما داده هاي کليدي انيميشن را از يکسري فايل load مي کنيم بنابراين تمام ثابتهاي زمان keyframe درون برنامه قرار داده مي شود ( شما مي توانيد خودتان يک ماژول بنويسيد که انيميشن هاي عمومي تر را نيز مديريت کند . اين ماژول بايد قادر باشد که يک فرمت استاندارد فايل را import کند ، اشيا و texture هاي مربوطه را load نمايد و سپس خودش ساخت انيميشن را بطور اتوماتيک انجام دهد و برنامه اصلي فقط روتين render و يا update را فراخواني کند ) . پس از جمع آوري اطلاعات فريم هاي کليدي ، بايد در هر زمان محاسبه کنيم که چه مدتي از شروع انيميشن گذشته است و بنابراين انيميشن در چه موقعيتي قرار دارد . سپس محاسبه مي کنيم که فريم کليدي قبلي و فريم کليدي بعدي چيست همچنين حساب مي کنيم در چه فاصله زماني از ايندو قرار داريم . سرانجام يک درون يابي نرمال را انجام مي دهيم تا اطلاعات فريم جاري بدست آيد و اين اطلاعات را درون يک شي Mesh مي گذاريم و آنرا رندر مي کنيم .
در درسهاي قبلي در مورد load کردن اشيا از يک فايل X صحبت کردم اما در مورد چگونگي گرفتن اطلاعات vertex از يک شي Mesh صحبت نشد . کتابخانه D3DX براي اينکار دو تابع دارد :
- تابع D3DXMeshVertexBuffer8GetData : اطلاعات يک شي D3DXMesh را گرفته و در يک آرايه از D3DVERTEX ذخيره مي کند :

D3DXMeshVertexBuffer8GetData( D3DXMeshobj As Unknown, Offset As Long, Size As Long, Flags As Long, Data As Any) As Long
- D3DXMeshobj As Unknown = A D3DXMESH object that you want to extract the data from.
- Offset As Long = How far into the vertex buffer we want to start reading, 0 is the beginning
- Size As Long = Size of the vertex buffer, this will be Len(D3DVERTEX) * Mesh.GetNumVertices
- Flags As Long = A combination of the CONST_D3DLOCKFLAGS, leave as 0.
- Data As Any = The first element in the array that you want the data to be read into, should be an array of D3DVERTEX vertices
- Return Code As Long = Returns D3D_OK for success, or either of D3DERR_INVALIDCALL or E_INVALIDARG for an error


- تابع D3DXMeshVertexBuffer8SetData : اطلاعات يک بافر vertex را در يک شي D3DXMesh قرار مي دهد :

D3DXMeshVertexBuffer8SetData( D3DXMeshobj As Unknown, Offset As Long, Size As Long, Flags As Long, Data As Any) As Long
- D3DXMeshobj As Unknown = The D3DXMESH object that defines where you want the data to be placed
- Offset As Long = How far into the Destination vertex buffer you want to place the data
- Size As Long = The Size of the buffer in bytes, this will be Len(D3DVERTEX) * Mesh.GetNumVertices
- Flags As Long = A Combination of the CONST_D3DLOCKFLAGS, leave as 0
- Data As Any = The first element in the array of data you want placed in the mesh's vertex buffer
- Return Code As Long = D3D_OK for success or D3DERR_INVALIDCALL or E_INVALIDARG for failure


عمليات انجام انيميشن فريم کليدي بصورت زير است :
- load کردن اشيا از فايلهاي X به درون شي D3DXMesh
- استخراج اطلاعات vertex از اين شي
- انجام درون يابي بين فريمهاي کليدي
- قرار دادن اطلاعات vertex هاي درون يابي در يک شي D3DXMesh
فرض مي کنيم که انيميشن ما هميشه از زمان صفر تا زمان n باشد – برحيب ميلي ثانيه – بنابراين مي توانيم از GetTickCount براي توابع زماني خود استفاده کنيم . همچنين يک ساختار را براي هر فريم کليدي بصورت زير تعريف مي کنيم :

Private Type KeyFrame
شي load شده از يک فايل’ Mesh As D3DXMesh
آرايه material براي هر شي’ MatList() As D3DMATERIAL8
آرايه Texture’ TexList() As Direct3DTexture8
تعداد material ها و texture هايي که استفاده مي کنيم’ nMaterials As Long
داده هاي vertex براي اين فريم کليدي’ VertexList() As D3DVERTEX
موقعيت اين فريم کليدي در انيميشن’ TimeIndex As Long
End Type


حال بايد تابعي بنويسيم که اطلاعات را از يک فايل X استخراج کرده و درون فريم کليدي قرار دهد :

Private Function CreateKeyFrameFromFile(Filename As String, TexturePrefix As String, Time As Long) As KeyFrame
نام فايل X براي شي سه بعدي: Filename ’
پوشه اي که اطلاعات texture اين شي در آن قرار دارد : TexturePrefix ’
انديس زمان براي اين فريم کليدي : Time '
Dim I As Long
Dim XBuffer As D3DXBuffer
Dim TextureFile As String
Dim hResult As Long
'خواندن اطلاعات از فايل ورودي به حافظه
Set CreateKeyFrameFromFile.Mesh = D3DX.LoadMeshFromX(Filename, D3DXMESH_MANAGED, D3DDevice, Nothing, XBuffer, CreateKeyFrameFromFile.nMaterials)x
توليد material ها و texture ها ‘
ReDim CreateKeyFrameFromFile.MatList(CreateKeyFrameFromF ile.nMaterials) As D3DMATERIAL8
ReDim CreateKeyFrameFromFile.TexList(CreateKeyFrameFromF ile.nMaterials) As Direct3DTexture8
For I = 0 To CreateKeyFrameFromFile.nMaterials - 1
D3DX.BufferGetMaterial XBuffer, I, CreateKeyFrameFromFile.MatList(I)x
CreateKeyFrameFromFile.MatList(I).Ambient = CreateKeyFrameFromFile.MatList (I).diffuse
TextureFile = D3DX.BufferGetTextureName(XBuffer, I)x
If TextureFile <> "" Then
Set CreateKeyFrameFromFile.TexList(I) = D3DX.CreateTextureFromFileEx(D3DDevice, TexturePrefix & TextureFile, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED,
D3DX_FILTER_LINEAR, D3DX_FILTER_LINEAR, 0, ByVal 0, ByVal 0)x
End If
Next I
استخراج داده هاي vertex’
ReDim CreateKeyFrameFromFile.VertexList(CreateKeyFrameFr omFile.Mesh.GetNumVertices) As D3DVERTEX
hResult = D3DXMeshVertexBuffer8GetData(CreateKeyFrameFromFil e.Mesh, 0, Len(CreateKeyFrameFromFile.VertexList(0)) * reateKeyFrameFromFile.Mesh.GetNumVertices, 0, CreateKeyFrameFromFile.VertexList(0))
CreateKeyFrameFromFile.TimeIndex = Time
End Function


در تابع Initialize خطوط زير را براي ساخت فريم هاي کليدي اضافه مي کنيم :

nKeyFrames = 4
kfAnimLength = 2500
AnimLastStartAt = GetTickCount()x
ReDim kfAnim(nKeyFrames - 1) As KeyFrame
kfAnim(0) = CreateKeyFrameFromFile(App.Path & "\frame0.x", App.Path & "\", 0)x
kfAnim(1) = CreateKeyFrameFromFile(App.Path & "\frame1.x", App.Path & "\", kfAnimLength * (1 / 3))x
kfAnim(2) = CreateKeyFrameFromFile(App.Path & "\frame2.x", App.Path & "\", kfAnimLength * (2 / 3))x
kfAnim(3) = CreateKeyFrameFromFile(App.Path & "\frame3.x", App.Path & "\", kfAnimLength)x
kfCurrent = CreateKeyFrameFromFile(App.Path & "\frame0.x", App.Path & "\", 0)


دقت کنيد که از يک انديس زمان براي ساخت فريم هاي کليدي استفاده شده است .
حال بايد کدي براي نمايش دادن انيميشن بنويسيم . ابتدا بايد به روشي تغييرات فريمها را کنترل کنيم :

For I = 0 To nKeyFrames - 2
If CurrentTimeIndex >= kfAnim(I).TimeIndex Then
PrevFrame = I
NextFrame = I + 1
End If
Next I


سپس بايد با توجه به زمان index دو فريم کليدي و زمان جاري ، پارامتر درون يابي را محاسبه کنيم :

sTime = kfAnim(PrevFrame).TimeIndex
eTime = kfAnim(NextFrame).TimeIndex
cTime = CurrentTimeIndex
eTime = eTime - sTime
cTime = cTime - sTime
sTime = sTime - sTime
InterpolateAmount = cTime / eTime


سپس بايد بر اساس اين پارامتر عمل درون يابي را روي داده هاي vertex انجام دهيم :

For I = 0 To kfCurrent.Mesh.GetNumVertices
'درون يابي مختصاتها
D3DXVec3Lerp vTemp3D, MakeVector(kfAnim(PrevFrame).VertexList(I).X, kfAnim(PrevFrame).VertexList(I).Y, _
kfAnim(PrevFrame).VertexList(I).Z), MakeVector(kfAnim(NextFrame).VertexList(I).X, kfAnim(NextFrame).VertexList(I).Y, _
kfAnim(NextFrame).VertexList(I).Z), InterpolateAmount
kfCurrent.VertexList(I).X = vTemp3D.X
kfCurrent.VertexList(I).Y = vTemp3D.Y
kfCurrent.VertexList(I).Z = vTemp3D.Z

'درون يابي نرمالها
D3DXVec3Lerp vTemp3D, MakeVector(kfAnim(PrevFrame).VertexList(I).nx, kfAnim(PrevFrame).VertexList(I).ny, _
kfAnim(PrevFrame).VertexList(I).nz), MakeVector(kfAnim(NextFrame).VertexList(I).nx, kfAnim(NextFrame).VertexList(I).ny, _
kfAnim(NextFrame).VertexList(I).nz), InterpolateAmount
kfCurrent.VertexList(I).nx = vTemp3D.X
kfCurrent.VertexList(I).ny = vTemp3D.Y
kfCurrent.VertexList(I).nz = vTemp3D.Z

'درون يابي اطلاعات بافت
D3DXVec2Lerp vTemp2D, MakeVector2D(kfAnim(PrevFrame).VertexList(I).tu, kfAnim(PrevFrame).VertexList(I).tv), _
MakeVector2D(kfAnim(NextFrame).VertexList(I).tu, kfAnim(NextFrame).VertexList(I).tv), InterpolateAmount
kfCurrent.VertexList(I).tu = vTemp2D.X
kfCurrent.VertexList(I).tv = vTemp2D.Y
Next I


حال بايد داده توليد شده را به فرمت Mesh برگردانيم :

hResult = D3DXMeshVertexBuffer8SetData(kfCurrent.Mesh, 0, Len(kfCurrent.VertexList(0)) * kfCurrent.Mesh.GetNumVertices, 0, kfCurrent.VertexList(0))x


با استفاده از روش فوق مي توانيد هر تعداد فريم کليدي را به انيميشنتان اضافه کنيد . اشکالي که روش فوق دارد اينست که اطلاعات texture براي تمام فريمهاي کليدي جداگانه ذخيره شده است در حاليکه texture در تمام فريمها ثابت است . در درسهاي بعدي از روشي بنام texture pooling استفاده مي کنيم تا تنها يک کپي از texture ها نگهداري کنيم .

A_M_IT2005
24-08-2006, 05:44
سلام

تشخیص فشرده شدن کليدهای کيبرد

من دو روش زیر را برای اینکار پيشنهاد می کنم :

۱ - استفاده از یک تابع کتابخانه ای به اسم GetAsyncKeyState موجود در کتابخانه user32.dll . این تابع ، فشرده شدن یا رها شدن یک کلید را تشخیص می دهد . نحوه declare کردن این تابع بصورت زیر است :

Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer

حال در برنامه تان یک timer قرار داده و در event آن کد زیر را قرار دهید :

For i = 1 To 255
results = 0
results = GetAsyncKeyState(i)
If results <> 0 Then
Msgbox(Chr(i))
End If
Next

برای مشاهده یک برنامه نمونه به این آدرس مراجعه کنید .
[ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]

۲ - استفاده از قلاب یا Hook : قلاب ، یک ابزار در مکانیزم مدیریت پیغام سیستم ویندوز است که توسط آن برنامه ها می توانند یک روتین را برای مدیریت و پردازش پیغامهای خاصی قبل از اینکه آن پیغامها به برنامه مقصد برسند نصب نمایند . قلابها باعث کندی سیستم می شوند زیرا حجم پردازشی سیستم روی هر پیغام را افزایش می دهند بنابراین بایستی زمانیکه واقعاً به قلاب نیاز دارید آنرا نصب نموده و هر چه زودتر آنرا حذف نمایید . سیستم ویندوز از انواع زیادی از قلابها پشتیبانی می کند که هر کدام امکان دستیابی به پیغامهای خاصی را مهیا می نمایند برای مثال یک برنامه کاربردی می تواند با استفاده از قلاب کیبرد برای مدیریت و پردازش پیغامهای مربوط به آن ( مثل فشرده شدن یک کلید خاص یا رها شدن آن ) استفاده کند .
برای نصب یک قلاب در برنامه از یک تابع کتابخانه ای به اسم SetWindowsHookEx استفاده می شود . این تابع یک قلاب را به زنجیره قلابهای سیستم اضافه می کند . نحوه declare کردن این تابع بصورت زیر است :

Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long

همچنین برای آزاد کردن یک قلاب و حذف آن از زنجیره قلابها از تابع کتابخانه ای UnhookWindowsHookEx استفاده می گردد . نحوه declare کردن این تابع بصورت زیر است :

Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long

برای ایجاد قلاب کیبرد همچنین نیاز به تعریف یک ثابت است که شماره قلاب کیبرد در آن قرار دارد :

Public Const WH_KEYBOARD = 2

حال بایستی یک تابع پس زمینه یا Callback Function نوشت که به ازای فشرده شدن کیبرد اجرا شود و آدرس آنرا ( با استفاده از کلمه کلیدی Address Of ) بهمراه ثابت فوق به تابع SetWindowsHookEx فرستاد .

برای اطلاعات بیشتر و مشاهده یک نمونه برنامه به این آدرس مراجعه کنید .
[ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]

فهرست ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])

A_M_IT2005
24-08-2006, 05:49
سلام

استخراج مشخصات سخت افزاری یک سیستم در VB

در این بخش یک کنترل Ocx معرفی می شود که بوسیله آن می توانید مشخصات سخت افزاری سیستم خود را استحراج کنید .
این کنترل را که Hardware Info نام دارد می توانید از آدرس زیر دانلود نمایید .
[ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]

پس از باز نمودن فایل zip دانلود شده مشاهده خواهید کرد که دو فایل dll و یک فایل ocx در آن وجود دارد . همچنین یگ فایل راهنما نیز بهمراه آنها وجود دارد که طریقه استفاده از کنترل را نشان می دهد . برای استفاده از کنترل فوق وارد محیط ویژال بیسیک شده و سپس وارد منوی Components شوید . در آنجا روی دکمه Browse کلیک کنید . وارد پوشه ای که فایل zip را در آنجا باز کرده اید شده و فایل HWInfo.ocx را انتخاب کنید تا این کنترل به لیست کنترلهای نوار ابزار شما اضافه شود . حال می توانید از کنترل را روی فرم خود قرار دهید و از امکانات آن استفاده کنید .
این کنترل دارای خصوصیات زیر است :
BaseBoardManufacturer : مشخصات سازنده مادربورد
BaseBoardProduct : نوع چیپ ست مادربورد
BiosVendor : سازنده بایوس
BiosReleaseDate : تاریخ انتشار بایوس
BiosVersion : ورژن بایوس
BiosROMSize : سایز حافظه رام بایوس
SocketDesignation : نوع سوکت پردازنده
ProcessorType : نوع پردازنده
ProcessorManufactor : سازنده پردازنده
ProcessorID : شماره ID پردازنده
ProcessorSerialNumber : شماره سریال پردازنده
با استفاده از این کنترل همچنین می توان اطلاعات هر چهار هارد دیسک IDE سیستم را استخراج نمود برای مثال اگر بخواهید اطلاعات Primary Hard ( شماره یک ) را بدست آورید از خصوصیات زیر استفاده کنید :
HardDisk1ModelNumber : شماره مدل هارددیسک
HardDisk1SerialNumber : شماره سریال هارد دیسک ( شماره سریال کارخانه )
خصوصیات دیگری نیز در این کنترل وجود دارد که برای اطلاعات بیشتر به راهنمای آن مراجعه کنید .

فهرست ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])

A_M_IT2005
24-08-2006, 06:02
سلام

اضافه کردن آیکون به منو

براي اضافه آيکون به منوهاي موجود در يک برنامه visual basic بايستي از توابع زير که موجود در کتابخانه User32 هستند استفاده کنيد :
۱ - GetMenu
۲ - GetSubMenu
۳ - GetMenuItemID
۴ - SetMenuIcon
ابتدا يک ماژول ايجاد کنيد و توابع فوق را در آن declare کنيد :


Public Declare Function GetMenu Lib "user32" (ByVal hwnd As Long) As Long

Public Declare Function GetSubMenu Lib "user32" (ByVal hMenu As Long, ByVal nPos As Long) As Long

Public Declare Function GetMenuItemID Lib "user32" (ByVal hMenu As Long, ByVal nPos As Long) As Long

Public Declare Function SetMenuItemBitmaps Lib "user32" (ByVal hMenu As Long, ByVal nPosition As Long, ByVal wFlags As Long, ByVal hBitmapUnchecked As Long, ByVal hBitmapChecked As Long) As Long


براي قرار دادن يک آيکون در کنار يکي از آيتمهاي منو نياز به handle فرم ، شماره منو ، شماره آيتم مورد نظر و نيز يک picture داريم :


Public Function SetMenuIcon(FrmHwnd As Long, MainMenuNumber As Long, MenuItemNumber As Long, Flags As Long, BitmapUncheckedHandle As Long, BitmapCheckedHandle As Long)x
Dim lngMenu As Long
Dim lngSubMenu As Long
Dim lngMenuItemID As Long
lngMenu = GetMenu(FrmHwnd)x
lngSubMenu = GetSubMenu(lngMenu, MainMenuNumber)x
lngMenuItemID = GetMenuItemID(lngSubMenu, MenuItemNumber)x
,SetMenuIcon = SetMenuItemBitmaps(lngMenu, lngMenuItemID, Flags
BitmapUncheckedHandle, BitmapCheckedHandle)x
End Function


image هاي مورد نظر خود را با ابعادي حدود 16*16 پيکسل و بصورت PictureBox در فرم خود قرار دهيد و خاصيت Visible مربوط به PictureBox ها را False کنيد .
سپس منوهاي خود را توسط Menu Editor طراحي کنيد .



File و Edit منوهاي اصلي هستند . پارامتر MainMenuNumber در تابع فوق شماره منوي اصلي است که براي File برابر صفر و براي Edit برابر يک مي باشد . پارامتر MenuItemNumber شماره هر آيتم در يک منو است که اين پارامتر نيز از صفر شروع مي شود .
اکنون براي اضافه کردن سه آيکون به سه آيتم منوي File کدهاي زير را در Form_Load بنويسيد :


Private Sub Form_Load()x
SetMenuIcon Me.hwnd, 0, 0, 0, pic1.Picture, pic1.Picture
SetMenuIcon Me.hwnd, 0, 1, 0, pic2.Picture, pic2.Picture
SetMenuIcon Me.hwnd, 0, 2, 0, pic3.Picture, pic3.Picture

فهرست ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])

A_M_IT2005
24-08-2006, 06:24
سلام

TAPI در ويژوال بيسيک

مقدمه:

TAPI چيست ؟

TAPI يا Telephony API يک کتابخانه استاندارد برای کار با مودم و نوشتن برنامه های تلفنی می باشد . برای نمونه می توان از برنامه های Phone Dialer ( شماره گير تلفن ) ، برنامه شبکه سازی تلفنی ( Dialup Networking ) ، برنامه تشخيص پالس مودم برای ضبط اطلاعات وارد شده از طرف کاربران و کاربردهای ديگر در اين زمينه نام برد . اين کتابخانه به شما کمک کمک می کند تا بدون درگير شدن با برنامه نويسی سخت افزار مودم و درايور آن بطور مستقيم بتوانيد برنامه های کاربردیي در اين زمينه بنويسيد .
مروری بر Microsoft Telephony :

Telephony امکان مجتمع سازی کامپيوترها با دستگاههای ارتباطی و شبکه ها را فراهم نموده است . معمولاً دستگاه ارتباطی يک مودم و خط ارتباطی نيز شبکه PSTN ( شبکه عمومی تلفن سوئيچينگ ) می باشد . برخی از کاربردهای Telephony عبارتند از :

۱ - کنفرانسهای مالتی مديا بصورت Multicast
۲ - VoIP
۳ - مرکز پاسخ گويي اتوماتيک
۴ - تماس تلفنی از طريق کامپيوتر روی شبکه PSTN

دياگرام زير معماری Microsoft Telephony را نشان می دهد :
برنامه های TAPI :

برای نوشتن برنامه های کاربردی با استفاده از TAPI بايستی ابتدا در مورد سطح سرويسی که می خواهيم ارائه دهيم تصميم گيری کنيم . برای مثال برای نوشتن يک برنامه شماره گير تلفن نياز به استفاده کامل از TAPI نيست و می توان از قابليتهای خود ويندوز در اين زمينه استفاده کرد ( Assisted Telephony ) . در بخشهای بعدی در مورد سطوح مختلف سرويس در TAPI بيشتر صحبت خواهم کرد .
دومين مطلبی که بايد مورد توجه قرار داد اينست که می خواهيم از TAPI 2.x استفاده کنيم يا از TAPI 3.x . تفاوت ايندو آنست که TAPI ورژن ۲ يک API برمبنای C است در حاليکه ورژن ۳ آن بر مبنای تکنولوژی COM می باشد . در بخشهای بعدی مطالب بيشتری در مورد تفاوتهای اين دو نسخه بيان خواهم کرد .
بخشهای اصلی يک برنامه کامل TAPI عبارتند از :

۱ - TAPI Initialization : شامل load کردن TAPI dll ، اتصال به TAPI Server ، مذاکره در مورد ورژن TAPI و برپاسازی سيستم اطلاع رسانی event می باشد .

۲ - Session Control : مقداردهی اوليه ، دريافت و کنترل تماسها

۳ - Device Control : دريافت و تنظيم اطلاعات دستگاه

۴ - Media Control : تشخيص و يا توليد تونها و ارقام ، کنترل stream

۵ - TAPI Shutdown : آزاد سازی منابع
مقداردهی اوليه TAPI :

عملکرد درست اجزای TAPI نياز به برپاسازی محيط ارتباطی روی کامپيوتر مورد نظر دارد . مراحل اين امر عبارتند از :

۱ - نصب TAPI : زمانيکه سخت افزار و يا نرم افزار برای اولين بار به کامپيوتر اضافه می شود انجام می گيرد . جزئيات کار به سيستم عامل و نرم افزار بستگی دارد .

۲ - مقداردهی ابتدائی : ساخت اشيا و مسيرهای ارتباطی

۳ - مذاکره در مورد ورژن TAPI : برای اطمينان از اينکه اجزای TAPI قادر به تبادل داده ها باشند .

۴ - استخراج اطلاعات منابع : بدست آوردن اطلاعاتی در مورد دستگاهی که می توان از آن در برنامه TAPI مورد نظرمان استفاده نمود .

۵ - Event notification : برپاسازی سيستم اطلاع رسانی event

A_M_IT2005
24-08-2006, 06:31
سلام

TAPI در ويژوال بيسيک

جلسه اول :

مقداردهی اوليه TAPI در ويژوال بيسيک :

از منوی Project گزينه References را انتخاب کرده و از ليست مربوطه مورد Microsoft TAPI 3.0 Type Library را انتخاب کنيد .
حال وارد بخش کد نويسی فرمتان شويد و متغير objTAPI را بصورت زير تعريف کنيد :

Dim objTapi As TAPI

سپس در بخش مربوط به Form Load شی objTAPI را بصورت زير ايجاد می کنيم :

Set objTapi = New TAPI

همانطور که در بخشهای قبلی گفته شد ، قبل از فراخوانی هر تابع TAPI ابتدا بايستی آنرا مقداردهی اوليه کنيم . برای مقداردهی اوليه کردن شی TAPI عبارت زير را بنويسيد :

Call objTapi.Initialize

A_M_IT2005
24-08-2006, 07:45
سلام

TAPI در ويژوال بيسيک

جلسه دوم :

انتخاب يک آدرس :
کد زير نشان می دهد که چگونه می توان با استفاده از شی TAPI در ويژوال بيسيک منابع تلفنی در دسترس را برای يک آدرس که بتواند يک مجموعه مشخص از نيازها را مديريت کند ، بررسی کرد .
توجه داشته باشيد که قبل از انجام اين کار بايستی عمل مقداردهی اوليه TAPI را که در بخش قبل ررسی شد ، انجام دهيد .

نکته : در کد زير عمل error checking انجام نگرفته است و برای استفاده از کد زير در برنامه های واقعی بايستی بخش بررسی خطا را به آن اضافه کنيد .
۱ - تعريف يک شی آدرس و يک شی مجموعه آدرس :

Dim gobjAddress As ITAddress
Dim objCollAddresses As ITCollection

۲ - تنظيم شی objCollAddress بعنوان يک مجموعه آدرس از شی objTapi :

Set objCollAddresses = objTapi.Addresses

۳ - پيدا کردن آدرسی که بتواند از واسط مورد نظر ما پشتيبانی کند :

bFound = False
For indexAddr = 1 To objCollAddresses.Count
Set objCrtAddress = objCollAddresses.Item(indexAddr)x
Set objMediaSupport = objCrtAddress
Set objAddressCapabilities = objCrtAddress

If objMediaSupport.QueryMediaType( nSelectedType ) x
bFound = True
End If

Set objAddressCapabilities = Nothing
Set objMediaSupport = Nothing
Set objCrtAddress = Nothing

If bFound = True Then Exit For
Next indexAddr


در صورتيکه آدرس مورد نظزر پيدا شود برنامه از حلقه خارج شده و gobjAddress يک آدرس قابل استفاده خواهد بود :

Set gobjAddress = objcollAddresses.Item(indexAddr)x

A_M_IT2005
24-08-2006, 08:17
سلام

TAPI در ويژوال بيسيک

جلسه سوم :

انجام Event Handling در TAPI :

کد زير شامل يک event handler ساده برای TAPI ، رجيستر کردن واسط event ، تنظيم ----- event و رجيستر کردن تمام فراخوانيهای دادن اخطار است . هدف اصلی از اين کد اينست که مطمئن شويم بخشی از TAPI که event ها را دريافت می کند پردازشی را قبل از انتقال به بخشهای ديگر انجام دهد .

تعاريفها :

Dim WithEvents gobjTapiWithEvents As TAPI
Attribute gobjTapiWithEvents.VB_VarHelpID = -1
Dim glRegistrationToken As Long


Const TAPI3_CALL_EVENTS =TE_CALLMEDIA Or
TE_CALLNOTIFICATION Or TE_CALLSTATE


تنظيم eventfilter بصورتيکه تمام event های تعريف شده برای TAPI را بپذيرد :

objTapi.EventFilter = TAPI3_CALL_EVENTS

رجيستر کردن event ها :

Set gobjTapiWithEvents = objTapi
Dim fOwner As Boolean, fMonitor As Boolean
Dim lMediaTypes As Long, lCallbackInstance As Long

fOwner = True
fOwner = True
fMonitor = False
lMediaTypes = TAPIMEDIATYPE_AUDIO
lCallbackInstance = 1

glRegistrationToken = gobjTapi.RegisterCallNotifications(gobjAddress,fMo nitor,
fOwner,lMediaTypes,lCallbackInstance)x

A_M_IT2005
24-08-2006, 09:41
سلام

TAPI در ويژوال بيسيک

جلسه چهارم :

انتخاب يک ترمينال :

+ قبل از اينکه يک ترمينال را برای برقراری ارتباط انتخاب کنيد بايستی TAPI Initialization و عمل انتخاب آدرس را انجام داده باشيد .

ابتدا يک متغير از نوع ITBasicCallControl ( واسط کنترل تماس ) تعريف می کنيم :

Dim objCallControl As ITBasicCallControl
Set objCallControl = gobjReceivedCallInfo

سپس يک متغير از نوع ITTerminalSupport ( کوئری از شی آدرس ) تعريف می کنيم :

Dim objTerminalSupport As ITTerminalSupport
Set objTerminalSupport = gobjAddress

سپس متغير ترمينال را تعريف کرده و توسط شی objTerminalSupport يک ترمينال را برای آن استخراج می کنيم :

Dim objTerminal As ITTerminal
Set objTerminal = objTerminalSupport.GetDefaultStaticTerminal(lMedia Type, dir)x

در اينجا ديگر نيازی به شی objTerminalSupport نيست بنابراين آنرا آزاد می کنيم :

Set objTerminalSupport = Nothing

سپس نياز به تعريف شی objStreamControl برای کنترل ترمينال است :

Dim objStreamControl As ITStreamControl
Set objStreamControl = objCallControl

در صورتيکه اين شی ايجاد شود ، به ازای استريم های موجود در ITCollection امکان ايجاد ترمينال در يک حلقه for بررسی می شود و ترمينال مناسب انتخاب می گردد :

If Not (objStreamControl Is Nothing) Then
Dim objITCollStreams As ITCollection

Set objITCollStreams = objStreamControl.Streams

Dim nIndex As Long, objCrtStream As ITStream

For nIndex = 1 To objITCollStreams.Count
Set objCrtStream = objITCollStreams.Item(nIndex)x
If objCrtStream.MediaType = lMediaType Then
If objCrtStream.Direction = dir Then
Call objCrtStream.SelectTerminal(objTerminal)x
End If
End If
Set objCrtStream = Nothing
Next nIndex

Set objITCollStreams = Nothing
Set objStreamControl = Nothing
End If

A_M_IT2005
26-08-2006, 02:00
سلام

TAPI در ويژوال بيسيک

جلسه پنجم:

ايجاد يک تماس ( Make a Call ) :
+ قبل از اين بخش بايستی مراحل TAPI Initialization و عمل انتخاب آدرس انجام شده باشد .
اين بخش برای ايجاد يک شی تماس ، بررسی و مشخص کردن استريمی که با اين تماس در ارتباط است ، انتخاب و ايجاد ترمينالهای مناسب و کامل کردن ارتباط استفاده می شود .
قبل TAPI Initialization و عمل انتخاب آدرس و انتخاب ترمينال انجام شده باشد .
در ابتدا با استفاده از متد CreateCall يک شی تماس ساخته می شود :

Set gobjCall = gobjOrigAddress.CreateCall(strDestAddress, nSelectedType,lMediaTypes)x

سپس در اينجا بايستی کدی که در بخش اول اين درس برای انتخاب ترمينال نوشته شد آورده شود :

}
Select Terminal Code
{

سپس بايستی دستور Connect اجرا شود :

gobjCall.Connect (False)x

False بدين معناست که ارتباط بصورت آسنکرون برقرار می شود .

A_M_IT2005
26-08-2006, 02:38
سلام

TAPI در ويژوال بيسيک

جلسه آخر :

دريافت يک تماس :

کد زير برای يافتن و يا ايجاد يک ترمينال مناسب برای دريافت يک تماس بکار می رود . بايستی توجه داشته باشيد که قبل از اجرای کد زير بايستی مراحل مقداردهی اوليه ، انتخاب يک آدرس و رجيسر کردن event ها را انجام دهيد . همچنين در کد زير بايستی مرحله انتخاب ترمينال را نيز انجام دهيد . توجه داشته باشيد که در کد زير متغير pEvent يک اشاره گر برای واسط ITCallNotificationEvent است که توسط TAPI به event Handler داده می شود :

If TapiEvent = TE_CALLNOTIFICATION Then
Dim objCallNotificationEvent As ITCallNotificationEvent
Set objCallNotificationEvent = pEvent
Dim gobjReceivedCallInfo As ITCallInfo
Set gobjReceivedCallInfo = objCallNotificationEvent.Call
Dim objCallControl As ITBasicCallControl
Set objCallControl = gobjReceivedCallInfo
objCallControl.Answer
End If



+ بخاطر طولانی شدن اين سری مطالب و نيز تخصصی بودن آن که باعث می شود مخاطبين کمتری داشته باشد بحث TAPI را به همين جا خاتمه می دهم . اما برای دوستان علاقمند که بخواهند مطالب بيشتری در اين زمينه آموخته و نيز مثالهای عملی از نوشتن برنامه های TAPI را در اختيار داشته باشند لينکهای زير را معرفی می کنم :

آموزش TAPI در سايت MSDN:
[ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]

سوالات مختلف در مورد TAPI :
[ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]

سوالات مختلف در مورد TAPI :
[ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]

Active Call Center:
[ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]

يک کنترل ActiveX برای استفاده از TAPI:
[ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]

نمونه ای از يک برنامه کامل TAPI در ويژوال بيسيک:
[ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]

TAPI در ويژوال بيسيک:
[ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]

کتابی در مورد برنامه نويسی TAPI در ويژوال بيسيک:
[ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]

ممکنه بعضی لینکها به دلیل قدیمی بودن خراب باشه !!!

A_M_IT2005
16-09-2006, 12:03
سلام

آشنايي با BitBlt

هدف از اين مبحث آموزشي ، آشنايي با تابع BitBlt و برخي ديگر از توابع کتابخانه Win32 GDI براي انجام برخي عمليات گرافيکي مثل double buffering و خواندن sprite از فايل است .
نکته : sprite به کاراکترهاي متحرکي گفته مي شود که در بازيها وجود دارد .
اولين چيزي که به آن نياز داريد ايجاد يک فرم است . خاصيت ScaleMode آنرا برابر 3-Pixel قرار دهيد . پيشنهاد مي کنم که هميشه در هنگام استفاده از فرم بهمراه API از pixel براي scalemode استفاده کنيد .
سپس سايز فرم را به اندازه اي افزايش دهيد تا ScaleWidth برابر 320 و ScaleHeight برابر 256 شود . توجه کنيد که خاصيت HasDC فرم را True قرار دهيد . همچنين از خاصيت AutoRedraw براي فرم استفاده نمي کنيم زيرا مي خواهيم از Double Buffering استفاده کنيم که بسيار سريعتر و کارامدتر مي باشد .
مرحله بعدي declare کردن API هايي است که به آنها نياز داريم :

'blitting
Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
'code timer
Private Declare Function GetTickCount Lib "kernel32" () As Long
'creating buffers / loading sprites
Private Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
'loading sprites
Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
'cleanup
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long

سوال : DC چيست ؟ DC و يا بعبارت ديگر Device Context ، hDC يک عدد است که به يک آدرس در حافظه اشاره مي کند که داده اي در آن ذخيره شده است . در هنگام استفاده از BitBlt براي اشاره کردن به آدرسي که داده گرافيکي در آنجا ذخيره شده ، استفاده مي شود .
در مرحله بعدي نياز به ذخيره آدرسهاي DC داريم که مي سازيم . آدرسهاي DC مقادير Long هستند همچنين آنها را بصورت Public تعريف مي کنيم :

'our Buffer's DC
Public myBackBuffer As Long
Public myBufferBMP As Long
'The DC of our sprite/graphic
Public mySprite As Long
'coordinates of our sprite/graphic on the screen
Public SpriteX As Long
Public SpriteY As Long

حال بايد تابعي بسازيم که تصاوير گرافيکي درون حافظه load کند . نکته مهمي که بايد به آن توجه کنيد اينست که يک device context خودش به تنهايي هيچ داده گرافيکي ندارد و بايستي يک bitmap موجود باشد تا درون آن load شود براي مثال يک فايل bmp يا يک bitmap خالي که از آن بعنوان back buffer استفاده مي کنيد .
تابعي که خواهيم نوشت يک device context منطبق با صفحه مي سازد سپس فايلهاي گرافيکي مورد نظر را درون device context قرار مي دهد :

Public Function LoadGraphicDC(sFileName As String) As Long
'temp variable to hold our DC address
Dim LoadGraphicDCTEMP As Long
'create the DC address compatible with
'the DC of the screen
LoadGraphicDCTEMP = CreateCompatibleDC(GetDC(0))
'load the graphic file into the DC...
SelectObject LoadGraphicDCTEMP, LoadPicture(sFileName)
'return the address of the file
LoadGraphicDC = LoadGraphicDCTEMP
End Function

سوال : double-buffering چيست ؟ زمانيکه يک محيط گرافيکي مي سازيد تا درون آن چيزي را ترسيم کنيد ، شما sprite ها / گرافيکها / متن را درون حافظه blit مي کنيد ( offscrean ) سپس نتيجه نهايي را روي صفحه blit مي کنيد . اين عمل از لرزش تصوير يا flickering جلوگيري مي کند ( زماني رخ مي دهد که چندين sprite مستقيماً روي صفحه blit شوند ) و بسيار سريعتر از AutoRedraw است .
قبل از اينکه مثالي براي اين تابع ذکر کنم تابع BitBlt را توضيح خواهم داد :
BitBlt تابعي از کتابخانه dll “gdi32” است . اين تابع يک انتقال bit-block از داده هاي مرتبط به يک مستطيل از پيکسلها به يک device context مقصد انجام مي دهد . بعبارت ديگر داده هاي گرافيکي را از محيط گرافيکي ( يک bitmap ) به محيط گرافيکي ديگري ( screen يا يک form ) کپي مي کند . فرم کلي اين تابع بصورت زير است :

Declare Function BitBlt Lib "gdi32" Alias "BitBlt" _
(ByVal hDestDC As Long, _
ByVal x As Long, _
ByVal y As Long, _
ByVal nWidth As Long, _
ByVal nHeight As Long, _
ByVal hSrcDC As Long, _
ByVal xSrc As Long, _
ByVal ySrc As Long, _
ByVal dwRop As Long) As Long

اولين خط بيان مي کند که ما بوسيله gdi32 DLL به تابع BitBlt دسترسي خواهيم داشت . خطوط ديگر پارامترهايي هستند که اين تابع مي گيرد :
hDestDC : hDC مربوط به محيط مقصد ( اگر مي خواهيد مقصد يک فرم باشد از form.hDC استفاده کنيد و يا اينکه آدرس يک backbuffer را که ساخته ايد بدهيد )
x : مختصات افقي محلي که مي خواهيد گرافيک شما ظاهر شود .
y : مختصات عمدي محلي که مي خواهيد گرافيک شما ظاهر شود .
nWidth : عرض گرافيک شما
nHeight : ارتفاع گرافيک شما
hSrcDC : hDC مربوط به محيط مبدا
xSrc : افست x . 0 زماني استفاده مي شود که بخواهيد از سمت چپترين گوشه گرافيک مبدا عمل blit را انجام دهيد .
ySrc : افست y
dwRop : مد draw اي که در زمان blitting گرافيکتان مي خواهيد استفاده کنيد ( Raster Operations يا ROP ) . اين پارامتر مقادير زير را مي تواند بگيرد :
- vbSrcCopy : داده تصوير مبدا را مستقيماً در مقصد کپي مي کند .
- vbSrcPaint : داده هاي تصاوير مبدا و مقصد را با هم OR مي کند ( pseudo-alphablending effect )
- vbSrcAnd : داده هاي تصاوير مبدا و مقصد را با هم AND مي کند ( pseudo-gamma effect )
- vbSrcInvert : داده هاي تصاوير مبدا و مقصد را با هم XOR مي کند
- vbSrcErase : ابتدا داده تصوير مقصد را invert مي کند سپس آنرا با داده تصوير مبدا AND مي کند .
- vbDstInvert : داده تصوير مقصد را invert مي کند و داده تصوير مبدا را در نظر نمي گيرد .
- vbNotSrcCopy : داده تصوير مبدا را invert مي کند و آنرا مستقيماً در مقصد کپي مي کند .
- vbNotSrcErase : داده تصاوير مبدا و مقصد را OR کرده و نتيجه را invert مي کند .

مثالي از کاربرد BitBlt :
BitBlt Form1.hDC, PlayerX, PlayerY, 48, 48, picPlayer.hDC, 0, 0, vbSrcCopy

حال مي خواهيم از BitBlt در يک حلقه استفاده کنيم تا يک image را در فرم حرکت دهيم :
1 – يک فايل bmp با ابعاد 32x32 بسازيد و با نام sprite1.bmp در دايرکتوري پروژه ذخيره کنيد .
2 – يک دکمه در فرم قرار دهيد و نام آنرا cmdTest بگذاريد .
3 – دکمه را در گوشه بالايي فرم و در سمت راست قرار دهيد .
4 – کد زير را براي event مربوط به کليک شدن دکمه بنويسيد :

'Timer variables...
Dim T1 As Long, T2 As Long
ساخت DC براي backbuffer’
myBackBuffer = CreateCompatibleDC(GetDC(0))
ساخت يک سطح bitmap براي DC’
myBufferBMP = CreateCompatibleBitmap(GetDC(0), 320, 256)
load کردن سطح bitmap خالي درون buffer’
SelectObject myBackBuffer, myBufferBMP
قبل از blit کردن درون بافر بايد آنرا با black پر کنيم’
BitBlt myBackBuffer, 0, 0, 320, 256, 0, 0, 0, vbWhiteness
load کردن split توسط تابعي که در بالا نوشتيم’
mySprite = LoadGraphicDC(App.Path & "\sprite1.bmp")
cmdTest.Enabled = False
== شروع حلقه اصلي ==’
خواندن tickcount جاري’
T2 = GetTickCount
Do
DoEvents
T1 = GetTickCount
اگر 15 ميلي ثانيه گذشته بود فريم بعدي شروع شود’
If (T1 - T2) >= 15 Then
پاک کردن محل قبلي sprite بوسيله پر کردن آنجا با black ‘
BitBlt myBackBuffer, SpriteX - 1, SpriteY - 1,32, 32, 0, 0, 0, vbBlackness
Blit کردن sprite درون back buffer’
BitBlt myBackBuffer, SpriteX, SpriteY, 32, 32,mySprite, 0, 0, vbSrcPaint
Blit کردن backbuffer روي فرم’
BitBlt Me.hdc, 0, 0, 320, 256, myBackBuffer,0, 0, vbSrcCopy
حرکت دادن sprite روي صفحه’
SpriteX = SpriteX + 1
SpriteY = SpriteY + 1
'update timer
T2 = GetTickCount
End If
Loop Until SpriteX = 320
سپس بايد يک cleanup code بنويسيد تا حافظه هاي را که براي نگهداري تصاوير گرافيکي و buffer ها استفاده کرده ايد آزاد کنيد :

Private Sub Form_Unload(Cancel As Integer)
DeleteObject myBufferBMP
DeleteDC myBackBuffer
DeleteDC mySprite
End
End Sub

فهرست ([ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ])

A_M_IT2005
18-09-2006, 08:50
سلام

آشنايي با شی پرينتر در ويژوال بيسيک

جلسه اول :

مقدمه

شی پرينتر ، شیي است که پرينتر پيش فرض سيستم را کنترل می کند . استفاده از شی پرينتر در ويژوال بيسيک 6 مانند کار با ساير اشيا است و بايستی از خواص و متدهای آن استفاده کرد . در ادامه با برخی از اين خواص و متدها آشنا خواهيد شد .

چاپ متن توسط شی پرينتر

برای چاپ متن توسط شی پرينتر کافيست خواص CurrentX و CurrentY که محل قرار گرفتن کرسر می باشد را تنظيم نوده و سپس با استفاده از متد Print متن مورد نظر را چاپ نموده و در پايان با استفاده از متد EndDoc صفحه چاپی را از پرينتر بيرون بدهيم . مثال :


Printer.CurrentX=150
Printer.CurrentY=200
Printer.Print "Visual Basic Printer Object Test"
Printer.EndDoc


در مثال فوق فرض شده که ScaleMode برابر Pixel قرار داده شده است . توجه داشته باشيد که تا قبل از اجرای متد EndDoc عمل چاپ انجام نمی شود و فقط بعد از اين متد است که چاپ انجام شده و کاغذ بيرون می آيد .

اگر پس از يک دستور Print ، دستور Print ديگری را استفاده کنيم متن روی خط بعدی چاپ خواهد شد . اگر بخواهيم متن بلافاصله بعد از متن اول چاپ شود بايد بعد از دستور Print اول از علامت ; استفاده کنيم .

نکته : برای کنترل دقيق محل چاپ از CurrentX و CurrentY استفاده نمائيد .

A_M_IT2005
19-09-2006, 05:10
سلام

آشنايي با شی پرينتر در ويژوال بيسيک

جلسه دوم :

چاپ گرافيک توسط شی پرينتر

به 4 روش می توان اشکال گرافيکی را توسط شی پرينتر چاپ کنيد :
1 – چاپ دايره : با استفاده از متد Circle می توان يک دايره ، قوس و يا بيضی را در صفحه چاپ کرد . فرمت کلی اين متد بصورت زير است :

Circle (x,y),radius,[color],[start],[end],[aspect]

که x و y مختصات مرکز دايره و radius شعاع آن می باشد .
پارامترهای color ، start ، end و aspect اختياری هستند و بترتيب رنگ ، محل شروع قوس ، محل خاتمه قوس و نسبت شعاع بيضی را نشان می دهند .

2 – چاپ خط : با استفاده از متد Line می توان يک خط و مستطيل را در صفحه چاپ کرد . فرمت کلی اين متد بصورت زير است :

Line (x1,y1)-(x2,y2),[color],[B[F]]

که x1 و y1 مختصات شروع خط ( يا مستطيل ) و x2 و y2 مختصات انتهای خط ( يا مستطيل ) هستند .
پارامتر color اختياری بوده و رنگ خط ( يا مستتطيل ) را نشان می دهد .
پارامتر B اختياری بوده و نشان می دهد يک مستيل رسم شود .
پارامتر F اختياری بوده و بهمراه B می آيد و نشان می دهد يک مستطيل توپر رسم شود .

3 – چاپ نقطه : با استفاده از متد PSet می توان نقطه ای روی صفحه چاپ کرد و فرمت کلی آن بصورت زير است :

PSet (x,y),[color]

که x و y مختصات نقطه می باشند .
پارامتر color اختياری بوده و رنگ نقطه را نشان می دهد .

4 – چاپ تصوير : با استفاده از متد PaintPicture می توان محتويات يک فايل گرافيکی را چاپ کرد . فرمت کلی اين متد بصورت زير است :

Printer.PaintPicture picture, x1, y1, [width1], [height1], [x2], [y2], [width2], [height2], [opcode]

x1 و y1 مختصات قرارگرفتن تصوير در صفحه بوده و picture يک شی از کلاس IPictureDisp است . اين شی را می توان از يک PictureBox يا از خاصيت Picture فرم گرفت و يا از دستور LoadPicture استفاده کرد .

مثال 1 :


Printer.PaintPicture Picture1.Picture, 100, 100

مثال 2 :

PaintPicture LoadPicture("C:\sample.jpg"), 100, 100

width1 و height1 طول و عرض تصوير چاپی می باشند . x2 و y2 نيز بهمراه width2 و height2 می توانند ميزان برش از تصوير اصلی برای چاپ را مشخص کنند .

A_M_IT2005
19-09-2006, 05:21
سلام

آشنايي با شی پرينتر در ويژوال بيسيک

جلسه آخر :

ساير خواص مهم شی پرينتر

ColorMode : اگر پرينتر رنگی باشد ، رنگی يا تک رنگ بودن چاپ را تعيين می کند .
Copies : تعداد چاپ را مشخص می کند .
Font : نوع فونت چاپ متن را مشخص می کند .
FontSize : سايز فونت چاپ متن را مشخص می کند .
PrintQuality : کيفيت چاپ را مشخص می کند .

ساير متدهای مهم شی پرينتر

KillDoc : پرينت در حال چاپ را از صف چاپ حذف می کند .
NewPage : صفحه جاری را به پايان برده و صفحه جديدی را برای چاپ آماده می کند .
Scale : سيستم مختصات کاربر را تعيين می کند .
TextHeight : ارتفاع متن پس از چاپ شدن در مختصات Scale را تعيين می کند .
TextWidth : عرض متن پس از چاپ شدن در مختصات Scale را تعيين می کند

A_M_IT2005
27-09-2006, 06:03
سلام

آموزش DirectX-Graphic

جلسه اول :

DirectX8 ابزاري براي ساخت تصاوير ثابت و متحرک دو بعدي و سه بعدي مي باشد .
براي کار با DirectX8 ابتدا بايستي آنرا روي سيستم خود نصب کنيد . سپس در محيط vb از منوي project گزينه References را انتخاب کنيد . در فرمي که ظاهر مي شود اطمينان حاصل کنيد که گزينه DirectX8 for VB type library فعال باشد .
براي کار با DirectX8 بايستي از تعريف نمودن شي پايه DirectX8 شروع نمود :


Dim Dx as DirectX8


شي Direct3D8 براي کنترل اشيا‌‌ سه بعدي بکار مي رود :


Dim D3D as Direct3D8


شي Direct3DDevice8 ، سخت افزار مربوط به رندر تصاوير را مشخص مي کند :


Dim D3DDevice as Direct3DDevice8


حال براي شروع کار با Direct3D ، تابع ( ) initialise را تعريف مي کنيم . اگر اينکار درست انجام شود تابع ، مقدار true را برمي گرداند :


public function initialise () as boolean
Dim DispMode as D3DISPLAYMODE


شي D3DISPLAYMODE حالت نمايش را مشخص مي نمايد .


Dim D3Dwindow as D3DPRESENT_PARAMETERS


شي فوق مشخص مي کند که viewport شما چگونه باشد .
حال شي اصلي DirectX8 را مي سازيم :


Set Dx=New DirectX8


سپس شي اصلي ساخت واسط سه بعدي را مي سازيم :


()set D3D.Dx.Direct3Dcreate


سپس حالت فعلي نمايش را با دستور زير استخراج مي کنيم :


D3D.getadapterdisplaymode D3DADAPTER_DEFAULT,dispmode


حال دو حالت براي کار با DirectX داريم :
1 - windowed mode
2 - fullscrean mode
1 - براي کار با حالت پنجره اي ابتدا اين موضوع را به DirectX اطلاع مي دهيم :


D3Dwindow.windowed=1


سپس نوع referesh تصوير را مشخص مي کنيم ( در اينجا چند انتخاب وجود دارد که در صورت نياز به اطلاعات بيشتر با من تماس بگيريد . ) :


D3Dwindow.swapeffect=D3DSWAPEFFECT_COPY_VSYNC


سپس بايستي فرمت بافر نگهدارنده تصاوير را مشخص کنيم :


D3Dwindow.backbufferformat=dispmode.format


2 - براي کار با حالت تمام صفحه ، ابتدا نوع refresh را مشخص کرده سپس تعداد بافر هاي تصوير و سرانجام نوع و سايز بافر را مشخص مي نمائيم :


D3Dwindow.swapeffect=D3DSWAPEFFECT_DISCARD
D3Dwindow.backbuffercount=1
D3Dwindow.backbufferformat=dispmode.format
D3Dwindow.backbufferheight=dispmode.height
D3Dwindow.backbufferwidth=dispmode.width


سپس پنجره نمايش مشخص مي گردد :


D3Dwindow.hdevicewindow=frmMain.hwnd



@حال بايستی يک device ساخته شود که يا از طريق سخت افزار و يا نرم افزار تصاوير را رندر نمايد :


Set D3DDevice=D3Dcreatedevice(D3DADAPTER_DEFAULT
,D3DDEVTYPE_HAL,
frmMain.hwnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING,
D3Dwindow)x,
end sub


درصورتي که کارت گرافيک شما امکانات رندر سخت افزاري تصاوير را ندارد از D3DDEVTYPE_REF بجاي D3DDEVTYPE_HAL استفاده کنيد .
حال بايستي روتين render را بنويسيم . البته در اين درس تصويري براي رندر نداريم و تنها چگونگي نوشتن اين روتين را بيان خواهم کرد :
۱ - ابتدا بايستي device مربوط به رندر ، قبل از کشيدن تصوير در آن پاک شود :


D3DDevice.clear 0,byval 0,D3DCLEAR_TARGET,&H0,1#,0


عدد hex اي که در دستور فوق آمده رنگ زمينه صفحه را مشخص مي کند
۲ - سپس بايستي تصاوير مورد نظر را رندر کنيم . اينکار توسط دستورات زير انجام مي شود :


D3DDevice.beginscence
all rendering calls go between these two lines '
D3DDEvice.endscence


3 - در پايان بايستي صفحه را update کنيد :


D3DDevice.present byval 0,byval 0,0,byval 0

A_M_IT2005
30-09-2006, 04:24
سلام

آموزش DirectX-Graphic

جلسه دوم :

موضوع : بدست آوردن مشخصات و تواناييهاي گرافيکي يک سيستم توسط DirectX-Graphic


1 - شمارش تعداد آداپتورهاي گرافيکي يک سيستم : فرض کنيد متغير nAdapters متغيري از نوع long باشد . همچنين شي D3DADAPTER_IDENTIFIER8 يک ساختار است که اطلاعات مربوط به آداپتور را نگه مي دارد . در اينصورت روتين enumerateAdapters بصورت زير خواهد بود :


Dim adapterinfo as D3DADAPTER_IDENTIFIER8
Private Sub EnumerateAdapters
Dim i as integer
nadapters=D3D.Getadaptercount


براي بدست آوردن جزئيات آداپبورها بصورت زير عمل مي کنيم :


for i=0 to nadapters-1
D3D.GetadapterIdentifier i ,0,adapterinfo


نام اين آداپتور بصورت ليستي از کدهاي اسکي است که بايستي آنها را درون يک string قرار دهيم :


for j=0 to 511
name=name & chr$(adapterinfo.description(j)) x
next j
name=replace(name,chr$(0)," ") x
end sub


بنابراين در متغير name نام آداپتور قرار خواهد گرفت .

۲ - مشخص کردن نوع Rendering : فرض کنيد شي D3DCAPS8 توانايي rendering آداپتور را نشان دهد . در اينصورت روتين EnumerateDevices بصورت زير خواهد بود :


Private EnumerateDevices
On Local Error resume next
Dim Caps as D3DCAPS8
deviceindex=0 'For Example
D3D.Getdevicecaps deviceindex,D3DDEVTYPE_HAL,caps
if err.number=D3DERR_NOTAVAILABLE then


اگر آداپتور امکان رندر سخت افزاري نداشته باشد در اينصورت :


MsgBox("Reference Rasterizer(REF)") x
else
MsgBox("Hardware Acceleration(HAL)+Reference Rasterizer(REF)") x
end if
end sub


3 - شمارش تعداد Mode نمايشي آداپتور :
فرض کنيد در صورت REF بودن امکان رندر ، متغير r=2 و در غيراينصورت r=1
باشد . همچنين شي D3DDISPLAYMODE اطلاعات مدهاي نمايشي را در خود
دارد . همچنين فرض کنيد متغير nModes از نوع longباشد . در اينصورت روتين enumeratedispmodes بصورت زير خواهد بود :


Private Sub EnumerateDispModes(r as Long,n as Long) x
Dim i as integer
Dim mode_tmp as D3DDISPLAYMODE
deviceindex=0 'For Example
nModes=D3D.Getadaptermodecount(deviceindex) x
for i=0 to nModes-1
D3D.EnumAdapterModes(deviceindex,i,mode_tmp) x


ابتدا Mode ها را به دو گروه ۱۶ بيتي و ۳۲ بيتي تقسيم مي کنيم :


if mode_tmp.format=D3DFMT_R8G8B8 or mode_tmp=D3DFMT_X8R8G8B8 or mode_tmp=D3DFMT_A8R8G8B8 then


حال چک مي کنيم که device قابل پذيرش و معتبر است يا نه :


if D3D.checkdevicetype(deviceindex,r,mode_tmp.format, mode_tmp.format,Flase)>=0 then
MsgBox(mode_tmp.width & "X" & mode_tmp.height & "32 Bit
FMT:" & mode_tmp.format ) x & "
end if
else
if D3D.checkdevicetype(deviceindex,r,mode_tmp.format, mode_tmp.format,Flase)>=0 then
MsgBox(mode_tmp.width & "X" & mode_tmp.height & "16 Bit
FMT:" & mode_tmp.format ) x & "
end if
end if
next i


4 - مشخص کردن توانايي هاي آداپتور گرافيکي : فرض کنيد در صورت REF بودن امکان رندر ، متغير r=2 و در غيراينصورت r=1 باشد :


Private Sub EnumerateHardware(r as long) x
Dim caps as D3DCAPS8
D3D.Getdevicecaps deviceindex,r,caps
If Caps.MaxActiveLights = -1 Then
MsgBox "Maximum Active Lights: Unlimited" x
Else
MsgBox "Maximum Active Lights: " & Caps.MaxActiveLights
End If
MsgBox "Maximum Point Vertex size: " & Caps.MaxPointSize
MsgBox "Maximum Texture Size: " & Caps.MaxTextureWidth & "X" & Caps.MaxTextureHeight
MsgBox "Maximum Primatives in one call: " & Caps.MaxPrimitiveCount
If Caps.TextureCaps And D3DPTEXTURECAPS_SQUAREONLY Then
MsgBox "Textures must always be square" x
End If
If Caps.TextureCaps And D3DPTEXTURECAPS_CUBEMAP Then
MsgBox "Device Supports Cube Mapping" x
End If
If Caps.TextureCaps And D3DPTEXTURECAPS_VOLUMEMAP Then
MsgBox "Device Supports Volume Mapping" x
End If
If Caps.DevCaps And D3DDEVCAPS_PUREDEVICE Then
MsgBox "Device supports the Pure Device Option" x
End If
If Caps.DevCaps And D3DDEVCAPS_HWTRANSFORMANDLIGHT Then
MsgBox "Device supports hardware transform and lighting" x
End If
If Caps.DevCaps And D3DDEVCAPS_HWRASTERIZATION Then
MsgBox "Device can use Hardware Rasterization" x
End If
If Caps.Caps2 And D3DCAPS2_CANCALIBRATEGAMMA Then
MsgBox "Device can Calibrate Gamma" x
End If
If Caps.Caps2 And D3DCAPS2_CANRENDERWINDOWED Then
MsgBox "Device can Render in Windowed Mode" x
End If
If Caps.Caps2 And D3DCAPS2_FULLSCREENGAMMA Then
MsgBox "Device can calibrate gamma in fullscreen mode" x
End If
If Caps.RasterCaps And D3DPRASTERCAPS_FOGRANGE Then
MsgBox "Device supports range based fog calculations" x
End If
If Caps.RasterCaps And D3DPRASTERCAPS_ANISOTROPY Then
MsgBox "Device supports Anisotropic Filtering" x
End If
If Caps.RasterCaps And D3DPRASTERCAPS_ZBUFFERLESSHSR Then
MsgBox "Device does not require a Z-Buffer/Depth Buffer" x
End If

A_M_IT2005
06-10-2006, 06:43
سلام

آموزش DirectX-Graphic

جلسه سوم :

موضوع : رسم اشکال دو بعدي

مروري بر object هاي DirectX8
1 - DirectX8 : اين شي ، شي مرکزي براي directX است و به شما امکان دسترسي به توابع و اشيا DirectX را مي دهد .
۲ - Direct3D8 : شي اصلي براي کار با محيط سه بعدي مي باشد . هدف از آن ، ساخت Direct3DDevice8 است و همچنين شامل توابعي براي مشخص کردن توانايي هاي کارت گرافيک است .
۳ - Direct3DDevice8 : اين شي مسئول ساخت بافتها textures ، مديريت نورها در يک صحنه ، مديريت مواد materials و همچنين render صحنه است . در واقع اين شي ، قلب نمايشي کار شماست .
4 - D3DX8 : گر چه هميشه نيازي به استفاده از اين شي نيست ، اما اين شي شامل توابعي براي ساخت برنامه هاي userfriendly تر توسط DirectX است . مثلاً ساخت اشيا سه بعدي ( مثل کره ، مکعب و ... ) ، ساخت بافتها ، ساخت سطوح و غيره
شروع کار براي رسم اشيا دوبعدي
ابتدا ثابت FVF را تعريف مي کنيم . اين ثابت توصيف " فرمت قابل انعطاف نقطه flexible-vertex-format " براي يک vertex دو بعدي انتقال يافته و ساده شده مي باشد .
سپس بايستي يک ساختار براي توصيف اين vertex معرفي کنيم :


Const FVF = D3DFVF_XYZRHW Or D3DFVF_TEX1 Or D3DFVF_DIFFUSE Or D3DFVF_SPECULAR
Private Type TLVERTEX
X As Single
Y As Single
Z As Single
rhw As Single
color As Long
specular As Long
tu As Single
tv As Single
End Type


فرض کنيد بخواهيم يک مربع را در صفحه رسم کنيم . براي رسم آن نياز به 4 عدد vertex داريم . بنابراين آرايه TriStrip را از نوع TLVERTEX تعريف ميکنيم :


Dim TriStrip (0 To 3) As TLVERTEX


حال به سراغ تابع initialize که در درس ۱ با آن آشنا شديد مي رويم و دستورات زير را به آن اضافه مي کنيم :


Private Function Initialize as boolean
.
.
.


ابتدا سيستم سايه زني vertex را طوري تنظيم مي کنيم که از FVF استفاده کند .


D3DDevice.SetVertexShader FVF


حال سيستم lighting را براي vertex هاي دو بعدي غير فعال مي کنيم زيرا نيازي به آن نداريم :


D3DDevice.SetRenderState D3DRS_LIGHTING,false


حال بايستي تابع initializeGeometry را اجرا کنيم . اين تابع را در ادامه توضيح خواهم داد . اگر نتيجه اين تابع true باشد دراينصورت initialize به درستي انجام شده است :


if initializeGeometry()=true then initialize=true
end function


تابع initializeGeometry در اين درس ، تابعي ساده است که تنها آرايه Vertex ها را مقدار دهي مي کند . براي رسم يک مربع نياز به مقداردهي ۴ vertex در جهت عقربه هاي ساعت داريم ( اين مربع شامل ۲ مثلث است )



Private Function InitialiseGeometry() As Boolean
On Error GoTo BOut:
color = RGB(200, 100, 0)
TriStrip(0) = CreateTLVertex(100, 100, 0, 1, color, 0, 0, 0)
TriStrip(1) = CreateTLVertex(300, 100, 0, 1, color, 0, 0, 0)
TriStrip(2) = CreateTLVertex(100, 300, 0, 1, color, 0, 0, 0)
TriStrip(3) = CreateTLVertex(300, 300, 0, 1, color, 0, 0, 0)
InitialiseGeometry = True
Exit Function
BOut:
InitialiseGeometry = False
End Function


همانطور که مشاهده مي کنيد براي تعريف vertex از تابع CreateTLVERTEX استفاده شده است . اين تابع صرفاً مقادير ساختار TLVERTEX را مقداردهي مي کند :


Private Function CreateTLVertex(X As Single, Y As Single, Z As Single, rhw As Single, color As Long, specular As Long, tu As Single, tv As Single) As TLVERTEX


نکته : ضمن اينکه شما مي توانيد مقادير اعشاري floating point را براي مختصاتهاي x و y و z بکار ببريد ، Direct3D مختصاتها را با گردکردن آنها تخمين مي زند و بنابراين ممکنست باعث ايجاد نتايج ناخواسته شود .


CreateTLVertex.X = X
CreateTLVertex.Y = Y
CreateTLVertex.Z = Z
CreateTLVertex.rhw = rhw
CreateTLVertex.color = color
CreateTLVertex.specular = specular
CreateTLVertex.tu = tu
CreateTLVertex.tv = tv
End Function
حال بايستي تابع Render را بنويسيم :
Public Sub Render()
D3DDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET, 0, 1#, 0
D3DDevice.BeginScene
D3DDevice.DrawPrimitiveUP D3DPT_TRIANGLESTRIP, 2, TriStrip(0), Len(TriStrip(0))x
D3DDevice.EndScene
D3DDevice.Present ByVal 0, ByVal 0, 0, ByVal 0
End Sub


ساختار اصلي براي اجراي توابع فوق بصورت زير است :


--Main part--
Initialize
Do While yourevent=true
Render
DoEvents
Loop

A_M_IT2005
10-10-2006, 07:12
سلام

آموزشDirectX-Graphic

جلسه چهارم :

موضوع : آشنايي با برخي اصطلاحات

1- Mesh : مش ، مجموعه اي از face ها است که يک شي سه بعدي را روي صفحه تشکيل مي دهند .

۲ - Face : يک چند ضلعی است که توسط مجموعه ای از نقاط به نام vertex ساخته مي شود .

۳ - Vertex : يک نقطه در فضاي سه بعدي است که براي دادن موقعيت ، scale و زاويه يک face استفاده مي شود .

۴ - Direct3D از شيي بنام D3DVERTEX براي نمايش يک Vertex استفاده مي کند . براي ساخت face نيز از آرايه اي از vertex ها استفاده مي شود . آرايه هميشه بايستي قابل تقسيم به سه باشد زيرا اشکال از face هاي مثلثي ساخته مي شوند . هنگاميکه اين مثلثها کنار هم گذاشته شوند ، شي سه بعدي را مي سازند . Direct3D از بافري با نام Index Buffer استفاده مي کند که با direct3D مي گويد که با چه ترتيبي vertex ها را رسم نمايد . index ها بايستي هميشه در جهت عقربه هاي ساعت مشخص شوند .

A_M_IT2005
10-10-2006, 07:16
سلام

آموزشDirectX-Graphic

جلسه پنجم :

موضوع : اختصاص بافت Texture به اشکال دو بعدي

در اين درس مي خواهيم يک مربع که داراي بافت مي باشد را رسم کنيم . براي اينکار از کتابخانه کمکي D3DX8 استفاده مي کنيم . همچنين شي Direct3DTexture8 را نيز استفاده مي نمائيم .


Dim D3DX as D3DX8
Dim Texture as Direct3DTexture8


حال بايستي در تابع Initialize بافت مربوطه را از روي يک فايل تصويري load کنيم :


Private Function Initialize as boolean
.
.
.
Set Texture=D3DX8.CreateTextureFromFile(D3DDevice,app. path & yourfilename) x
end function


تابع Render نيز بصورت زير خواهد بود :


Private Sub Render
D3DDevice.clear 0,byval 0,D3DCLEAR_TARGET,0,1#,0
D3DDevice.beginscence
D3DDevice.SetTexture 0,Texture
D3DDevice.DrawprimitiveUP D3DPT_TRIANGLESTRIP,2,Tripstrip(0),len(Tristrip(0) )x
.
.
.
end function

A_M_IT2005
28-11-2006, 03:59
سلام

آموزش DirectX-Graphic

جلسه ششم :

موضوع : مفاهيم اوليه رسم اشکال سه بعدي در DirectX 8

در اين درس با استفاده از Direct3D يک مکعب را رسم مي کنيم . براي اين منظور ابتدا نياز به يک بافر داريم که بتوانيم شکل مورد نظر خود را در آن ذخيره کنيم :


Dim VBuffer as Direct3DVertexBuffer8


براي رسم مکعب از vertex هاي سه بعدي استفاده مي کنيم . براي اينکار نياز به تعريف يک تايپ جديد داريم :


Private Type LITVERTEX
x as single
y as single
z as single
color as long
specular as long
tu as single
tv as single
end type


توصيف گر اين فرمت ، بصورت زير است :


Const Lit_FVF = (D3DFVF_XYZ Or D3DFVF_DIFFUSE Or D3DFVF_SPECULAR Or D3DFVF_TEX1)x


براي توصيف مکعب در اين درس از روشي غيرکارامد استفاده شده است . به اين ترتيب که از ۳۶ عدد vertex استفاده شده ( در درسهاي بعدي متدهايي معرفي خواهند شد که اجازه مي دهند از ۸ عدد vertex باري توصيف مکعب استفاده کنيد ) .


Dim cube(35) as LITVERTEX


سپس بايد يکسري ماتريس سه بعدي تعريف کنيم :
اولين ماتريس ، matworld است که نشان مي دهد چگونه vertex ها در فضاي سه بعدي قرار گرفته اند . دومين ماتريس ، matview است که نشان مي دهد دوربين ( نقطه ديد ) در کجا قرار گرفته و سومين ماتريس ، matproj است که نشان مي دهد دوربين چگونه دنياي سه بعدي را روي صفحه دو بعدي نشان مي دهد :


Dim matworld as D3DMATRIX
Dim matview as D3DMATRIX
Dim matproj as D3DMATRIX


در تابع Initialize قبل از ساخت device بايستي چک کنيم که آيا مي توانيم از يک بافر Z شانزده بيتي استفاده کنيم يا نه ؟


If D3D.CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, DispMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16) = D3D_OK Then
D3DWindow.AutoDepthStencilFormat = D3DFMT_D16 '16 bit Z-Buffer


حال بايستي متد D3DCreateDevice را اجرا کنيد . سپس بايد سيستم سايه زني vertex را با فرمت vertex مان تنظيم کنيم :


D3DDevice.SetVertexShader Lit_FVF


همچنين سيستم نورپردازي را غير فعال مي کنيم :


D3DDevice.SetRenderState D3DRS_LIGHTING, False


Direct3D هيچ مثلثي را که در ديد شما نباشد رسم نخواهد کرد . براي متوقف کردن اين امر بايستي حالت culling آنرا متوقف کنيد همچنين vertex ها را بترتيب عقربه هاي ساعت معرفي کنيد :


D3DDevice.SetRenderState D3DRS_CULLMODE, D3DCULL_NONE


سپس بايد فرمت بافر Z را فعال سازيد :


D3DDevice.SetRenderState D3DRS_ZENABLE, 1

A_M_IT2005
28-11-2006, 04:14
سلام

آموزشDirectX-Graphic

جلسه هفتم :

تعريف ماترسها

1 - World Matrix : اين ماتريس براي نگهداري تمام vertex هايي که براي رندر فرستاده مي شوند بکار مي رود . مقادير موجود در اين ماتريس ، موقعيت يک vertex را مي تواند تغيير دهد . يکي از کاربردهاي آن انجام دورانrotation ، انتقال transmittion و تغییر اندازه scaling است .
برای ساخت اين ماتريس از دستور زير استفاده می کنيم :


D3DXMatrixIdentify matworld


حال اين ماتريس را براي device مربوطه تاييد مي کنيم :


D3DDevice.SetTransform D3DTS_WORLD,matworld


۲ - View Matrix : اين ماتريس را بعنوان يک دوربين در نظر بگيريد که بوسيله يک نقطه شروع و يک نقطه پاياني مشخص مي شود ( مشابه يک up vector که معمولاً در طول محور y رو به بالاست ) :


D3DXMatrixLookAtLH matView, MakeV(0, 5, 9), MakeV(0, 0, 0),MakeV(0, 1, 0) x
D3DDevice.SetTransform D3DTS_VIEW, matView


تابع MakeV که در اينجا استفاده شده بصورت زير است :


Private Function MakeV(x As Single, y As Single, z As Single) As D3DVECTOR
MakeV.x = x
MakeV.y = y
MakeV.z = z
End Function


۳ - Projection Matrix : اين ماتريس مشخص مي کند چه منطقه اي از فضاي جهاني براي رندر کردن visible باشد . همچنين مشخص مي کند چه مقدار مي توانيم بطور افقي ببينيم ( زاويه ديد بزرگتر منجر به ديد بزرگتر مي شود ) :


D3DXMatrixPerspectiveFovLH matProj, pi / 4, 1, 0.1, 500


در دستور فوق از زاويه ديد pi/4 راديان استفاده شده همچنين نسبت 1:1 استفاده شده است . قسمتهاي سوم و چهارم مشخص مي کنند فقط مثلثهايي کشيده شوند که با ابعاد بزرگتر از يکدهم دوربين و کوچکتر از ۵۰۰ برابر دوربين هستند .
حال دستور اختصاص به device را خواهيم داشت :


D3DDevice.SetTransform D3DTS_PROJECTION, matProj


بعد از تعريف ماتريسها بايستي تابع InitializeGeometry را صدا کنيم . در اين تابع از يک ثابت با نام DFC استفاده شده است . اگر DFC=1 باشد مکعب بطور کامل کشيده مي شود و اگر بزرگتر از يک باشد ، face هاي آن جدا از هم ديده خواهند شد . همچنين توجه کنيد که از بافرهاي vertex براي ذخيره داده vertex ها استفاده شده است . ساختار اين تابع بصورت زير خواهد بود :
۱ - پر کردن ساختارهاي vertex


'Front
Cube(0) = CreateLitVertex(-1, 1, DFC, color, 0, 0, 0)x
Cube(1) = CreateLitVertex(1, 1, DFC, color, 0, 0, 0)x
Cube(2) = CreateLitVertex(-1, -1, DFCcolor, 0, 0, 0)x
Cube(4) = CreateLitVertex(-1, -1, DFC, color, 0, 0, 0)x
Cube(5) = CreateLitVertex(1, -1, DFC, color, 0, 0, 0)x
'Back
Cube(6) = CreateLitVertex(-1, 1, -DFC, color, 0, 0, 0)x
Cube(7) = CreateLitVertex(1, 1, -DFC, color, 0, 0, 0)x
Cube(8) = CreateLitVertex(-1, -1, -DFC, color, 0, 0, 0)x
Cube(9) = CreateLitVertex(1, 1, -DFC, color, 0, 0, 0)x
Cube(10) = CreateLitVertex(-1, -1, -DFC, color, 0, 0, 0)x
Cube(11) = CreateLitVertex(1, -1, -DFC, color, 0, 0, 0)x
'Right
Cube(12) = CreateLitVertex(-DFC, 1, -1, color, 0, 0, 0)x
Cube(13) = CreateLitVertex(-DFC, 1, 1, color, 0, 0, 0)x
Cube(14) = CreateLitVertex(-DFC, -1, -1, color, 0, 0, 0)x
Cube(15) = CreateLitVertex(-DFC, 1, 1, color, 0, 0, 0)x
Cube(16) = CreateLitVertex(-DFC, -1, -1, color, 0, 0, 0)x
Cube(17) = CreateLitVertex(-DFC, -1, 1, color, 0, 0, 0)x
'Left
Cube(18) = CreateLitVertex(DFC, 1, -1, color, 0, 0, 0)x
Cube(20) = CreateLitVertex(DFC, -1, -1, color, 0, 0, 0)x
Cube(21) = CreateLitVertex(DFC, 1, 1, color, 0, 0, 0)x
Cube(22) = CreateLitVertex(DFC, -1, -1, color, 0, 0, 0)x
Cube(23) = CreateLitVertex(DFC, -1, 1, color, 0, 0, 0)x
'Top
Cube(24) = CreateLitVertex(-1, DFC, 1, color, 0, 0, 0)x
Cube(25) = CreateLitVertex(1, DFC, 1, color, 0, 0, 0)x
Cube(26) = CreateLitVertex(-1, DFC, -1, color, 0, 0, 0)x
Cube(27) = CreateLitVertex(1, DFC, 1, cocolor, 0, 0, 0)x
Cube(29) = CreateLitVertex(1, DFC, -1, color, 0, 0, 0)x
'Bottom
Cube(30) = CreateLitVertex(-1, -DFC, 1, color, 0, 0, 0)x
Cube(31) = CreateLitVertex(1, -DFC, 1, color, 0, 0, 0)x
Cube(32) = CreateLitVertex(-1, -DFC, -1, color, 0, 0, 0)x
Cube(33) = CreateLitVertex(1, -DFC, 1, color, 0, 0, 0)x
Cube(34) = CreateLitVertex(-1, -DFC, -1, color, 0, 0, 0)x
Cube(35) = CreateLitVertex(1, -DFC, -1, color, 0, 0, 0)x


2 - ساخت يک بافر vertex خالي با سايز مورد نظر :


Set VBuffer = D3DDevice.CreateVertexBuffer(Len(Cube(0)) * 36, 0, Lit_FVF, D3DPOOL_DEFAULT)x


3 - پر کردن بافر مربوطه با داده ها :


D3DVertexBuffer8SetData VBuffer, 0, Len(Cube(0)) * 36, 0, Cube(0)x


حال به سراغ روتين Render مي رويم :


Public Sub Render
D3DDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET Or D3DCLEAR_ZBUFFER, 0, 1#, 0 '//Clear the screen black
D3DDevice.BeginScene
D3DDevice.SetStreamSource 0, VBuffer, Len(Cube(0))x
D3DDevice.DrawPrimitive D3DPT_TRIANGLELIST, 0, 12
D3DDevice.EndScene
D3DDevice.Present ByVal 0, ByVal 0, 0, ByVal 0
End Sub


ساختار اصلي برنامه بصورت زير خواهد بود :


Dim RotateAngle As Single
Dim matTemp As D3DMATRIX '//To hold temporary
call Initialize
Do While bRunning
RotateAngle = RotateAngle + 0.1
If RotateAngle >= 360 Then RotateAngle = RotateAngle - 360
D3DXMatrixIdentity matWorld '//Reset our world matrix
D3DXMatrixIdentity matTemp
D3DXMatrixRotationX matTemp, RotateAngle * (pi / 180) x
D3DXMatrixMultiply matWorld, matWorld, matTemp
D3DXMatrixIdentity matTemp
D3DXMatrixRotationZ matTemp, RotateAngle * (pi / 180) x
D3DXMatrixMultiply matWorld, matWorld, matTemp
D3DDevice.SetTransform D3DTS_WORLD, matWorld
Render
DoEvents
Loop

A_M_IT2005
28-11-2006, 04:22
سلام

آموزشDirectX-Graphic

جلسه هشتم :

موضوع : نورپردازي و اختصاص بافت به اشيا سه بعدي
در اين درس مي خواهيم به مکعب درس قبل بافت اختصاص داده و نيز آنرا با يک منبع نور ، نورپردازي کنيم .
ابتدا تايپ vertex ها را بصورت زير تعريف مي کنيم :


Private Type UnlitVertex
X As Single
Y As Single
Z As Single
nx As Single
ny As Single
nz As Single
tu As Single
tv As Single
End Type


توصيفگر اين فرمت بصورت زير خواهد بود :


Const Unlit_FVF = (D3DFVF_XYZ Or D3DFVF_NORMAL Or D3DFVF_TEX1)


همچنين مکعب ما توسط ارايه زير مشخص مي شود :


Dim Cube2(35) As UnlitVertex


دو ثابت pi و rad را نيز بصورت زير تعريف مي کنيم :


Const pi As Single = 3.141592
Const Rad = pi / 180


براي اختصاص بافت به مکعب ، از شي Direct3DTexture8 استفاده مي شود :


Dim CubeTexture As Direct3DTexture8


براي نورپردازي ، از شي D3DLIGHT8 استفاده مي شود :


Dim Lights As D3DLIGHT8



تغييرات مورد نياز در تابع Initialize
بعد از ساخت شي D3DDevice در اين تابع ، پارامترهاي آنرا بصورت زير تنظيم مي کنيم :


D3DDevice.SetVertexShader Unlit_FVF
D3DDevice.SetRenderState D3DRS_LIGHTING, 1
D3DDevice.SetRenderState D3DRS_ZENABLE, 1
D3DDevice.SetRenderState D3DRS_AMBIENT, &H202020


مقدار ambient يک کد هگزا RRGGBB است .
بعد از دستورات فوق ماتريسهاي matworld ، matview و matproj مطابق مطابل درس قبل تعريف مي شوند . پس از آن بايستي بافت مکعب را از درون فايل تصويري مورد نظرتان load کنيد :


Set CubeTexture = D3DX.CreateTextureFromFileEx(D3DDevice, yourfilename, 128, 128, D3DX_DEFAULT, 0, DispMode.Format, D3DPOOL_MANAGED, D3DX_FILTER_LINEAR, D3DX_FILTER_LINEAR, 0, ByVal 0, ByVal 0)x


حال بايستي تابع InitializeGeometry صدا زده شود و سپس تابع SetupLights فراخواني شوند . ابتدا به توضيح تابع InitializeGeometry مي پردازيم :


Private Function InitialiseGeometry() As Boolean


ابتدا يک بردار نرمال تعريف مي کنيم :


Dim vN As D3DVECTOR


سپس آرايه cube2 را با مقادير عددي پر مي کنيم . نرمالهاي تمام vertex ها را ابتدا با بردار
[0,0,0 ] تعريف مي کنيم . اين مقدا بعداً تغيير خواهد کرد :


Cube2(0) = CreateVertex(-1, -1, 1, 0, 0, 0, 0, 0)
Cube2(1) = CreateVertex(1, 1, 1, 0, 0, 0, 1, 1)
Cube2(2) = CreateVertex(-1, 1, 1, 0, 0, 0, 0, 1)
vN = GenerateTriangleNormals(Cube2(0), Cube2(1), Cube2(2))
Cube2(0).nx = vN.X: Cube2(0).ny = vN.Y: Cube2(0).nz = vN.Z
Cube2(1).nx = vN.X: Cube2(1).ny = vN.Y: Cube2(1).nz = vN.Z
Cube2(2).nx = vN.X: Cube2(2).ny = vN.Y: Cube2(2).nz = vN.Z


Cube2(3) = CreateVertex(1, 1, 1, 0, 0, 0, 1, 1)
Cube2(4) = CreateVertex(-1, -1, 1, 0, 0, 0, 0, 0)
Cube2(5) = CreateVertex(1, -1, 1, 0, 0, 0, 1, 0)
vN = GenerateTriangleNormals(Cube2(3), Cube2(4), Cube2(5))
Cube2(3).nx = vN.X: Cube2(3).ny = vN.Y: Cube2(3).nz = vN.Z
Cube2(4).nx = vN.X: Cube2(4).ny = vN.Y: Cube2(4).nz = vN.Z
Cube2(5).nx = vN.X: Cube2(5).ny = vN.Y: Cube2(5).nz = vN.Z

'Back
Cube2(6) = CreateVertex(-1, 1, -1, 0, 0, 0, 0, 1)
Cube2(7) = CreateVertex(1, 1, -1, 0, 0, 0, 1, 1)
Cube2(8) = CreateVertex(-1, -1, -1, 0, 0, 0, 0, 0)
vN = GenerateTriangleNormals(Cube2(6), Cube2(7), Cube2(8))
Cube2(6).nx = vN.X: Cube2(6).ny = vN.Y: Cube2(6).nz = vN.Z
Cube2(7).nx = vN.X: Cube2(7).ny = vN.Y: Cube2(7).nz = vN.Z
Cube2(8).nx = vN.X: Cube2(8).ny = vN.Y: Cube2(8).nz = vN.Z

Cube2(9) = CreateVertex(1, -1, -1, 0, 0, 0, 1, 0)
Cube2(10) = CreateVertex(-1, -1, -1, 0, 0, 0, 0, 0)
Cube2(11) = CreateVertex(1, 1, -1, 0, 0, 0, 1, 1)
vN = GenerateTriangleNormals(Cube2(9), Cube2(10), Cube2(11))
Cube2(9).nx = vN.X: Cube2(9).ny = vN.Y: Cube2(9).nz = vN.Z
Cube2(10).nx = vN.X: Cube2(10).ny = vN.Y: Cube2(10).nz = vN.Z
Cube2(11).nx = vN.X: Cube2(11).ny = vN.Y: Cube2(11).nz = vN.Z

'Right
Cube2(12) = CreateVertex(-1, -1, -1, 0, 0, 0, 0, 0)
Cube2(13) = CreateVertex(-1, 1, 1, 0, 0, 0, 1, 1)
Cube2(14) = CreateVertex(-1, 1, -1, 0, 0, 0, 1, 0)
vN = GenerateTriangleNormals(Cube2(12), Cube2(13), Cube2(14))
Cube2(12).nx = vN.X: Cube2(12).ny = vN.Y: Cube2(12).nz = vN.Z
Cube2(13).nx = vN.X: Cube2(13).ny = vN.Y: Cube2(13).nz = vN.Z
Cube2(14).nx = vN.X: Cube2(14).ny = vN.Y: Cube2(14).nz = vN.Z

Cube2(15) = CreateVertex(-1, 1, 1, 0, 0, 0, 1, 1)
Cube2(16) = CreateVertex(-1, -1, -1, 0, 0, 0, 0, 0)
Cube2(17) = CreateVertex(-1, -1, 1, 0, 0, 0, 0, 1)
vN = GenerateTriangleNormals(Cube2(15), Cube2(16), Cube2(17))
Cube2(15).nx = vN.X: Cube2(15).ny = vN.Y: Cube2(15).nz = vN.Z
Cube2(16).nx = vN.X: Cube2(16).ny = vN.Y: Cube2(16).nz = vN.Z
Cube2(17).nx = vN.X: Cube2(17).ny = vN.Y: Cube2(17).nz = vN.Z

'Left
Cube2(18) = CreateVertex(1, 1, -1, 0, 0, 0, 1, 0)
Cube2(19) = CreateVertex(1, 1, 1, 0, 0, 0, 1, 1)
Cube2(20) = CreateVertex(1, -1, -1, 0, 0, 0, 0, 0)
vN = GenerateTriangleNormals(Cube2(18), Cube2(19), Cube2(20))
Cube2(18).nx = vN.X: Cube2(18).ny = vN.Y: Cube2(18).nz = vN.Z
Cube2(19).nx = vN.X: Cube2(19).ny = vN.Y: Cube2(19).nz = vN.Z
Cube2(20).nx = vN.X: Cube2(20).ny = vN.Y: Cube2(20).nz = vN.Z

Cube2(21) = CreateVertex(1, -1, 1, 0, 0, 0, 0, 1)
Cube2(22) = CreateVertex(1, -1, -1, 0, 0, 0, 0, 0)
Cube2(23) = CreateVertex(1, 1, 1, 0, 0, 0, 1, 1)
vN = GenerateTriangleNormals(Cube2(21), Cube2(22), Cube2(23))
Cube2(21).nx = vN.X: Cube2(21).ny = vN.Y: Cube2(21).nz = vN.Z
Cube2(22).nx = vN.X: Cube2(22).ny = vN.Y: Cube2(22).nz = vN.Z
Cube2(23).nx = vN.X: Cube2(23).ny = vN.Y: Cube2(23).nz = vN.Z

'Top
Cube2(24) = CreateVertex(-1, 1, 1, 0, 0, 0, 0, 1)
Cube2(25) = CreateVertex(1, 1, 1, 0, 0, 0, 1, 1)
Cube2(26) = CreateVertex(-1, 1, -1, 0, 0, 0, 0, 0)
vN = GenerateTriangleNormals(Cube2(24), Cube2(25), Cube2(26))
Cube2(24).nx = vN.X: Cube2(24).ny = vN.Y: Cube2(24).nz = vN.Z
Cube2(25).nx = vN.X: Cube2(25).ny = vN.Y: Cube2(25).nz = vN.Z
Cube2(26).nx = vN.X: Cube2(26).ny = vN.Y: Cube2(26).nz = vN.Z

Cube2(27) = CreateVertex(1, 1, -1, 0, 0, 0, 1, 0)
Cube2(28) = CreateVertex(-1, 1, -1, 0, 0, 0, 0, 0)
Cube2(29) = CreateVertex(1, 1, 1, 0, 0, 0, 1, 1)
vN = GenerateTriangleNormals(Cube2(27), Cube2(28), Cube2(29))
Cube2(27).nx = vN.X: Cube2(27).ny = vN.Y: Cube2(27).nz = vN.Z
Cube2(28).nx = vN.X: Cube2(28).ny = vN.Y: Cube2(28).nz = vN.Z
Cube2(29).nx = vN.X: Cube2(29).ny = vN.Y: Cube2(29).nz = vN.Z

'Top
Cube2(30) = CreateVertex(-1, -1, -1, 0, 0, 0, 0, 0)
Cube2(31) = CreateVertex(1, -1, 1, 0, 0, 0, 1, 1)
Cube2(32) = CreateVertex(-1, -1, 1, 0, 0, 0, 0, 1)
vN = GenerateTriangleNormals(Cube2(30), Cube2(31), Cube2(32))
Cube2(30).nx = vN.X: Cube2(30).ny = vN.Y: Cube2(30).nz = vN.Z
Cube2(31).nx = vN.X: Cube2(31).ny = vN.Y: Cube2(31).nz = vN.Z
Cube2(32).nx = vN.X: Cube2(32).ny = vN.Y: Cube2(32).nz = vN.Z

Cube2(33) = CreateVertex(1, -1, 1, 0, 0, 0, 1, 1)
Cube2(34) = CreateVertex(-1, -1, -1, 0, 0, 0, 0, 0)
Cube2(35) = CreateVertex(1, -1, -1, 0, 0, 0, 1, 0)
vN = GenerateTriangleNormals(Cube2(33), Cube2(34), Cube2(35))
Cube2(33).nx = vN.X: Cube2(33).ny = vN.Y: Cube2(33).nz = vN.Z
Cube2(34).nx = vN.X: Cube2(34).ny = vN.Y: Cube2(34).nz = vN.Z
Cube2(35).nx = vN.X: Cube2(35).ny = vN.Y: Cube2(35).nz = vN.Z


سپس يک بافر vertex خالي با ساير موردنظر مي سازيم :


Set VBuffer = D3DDevice.CreateVertexBuffer(Len(Cube2(0)) * 36, 0, Unlit_FVF, D3DPOOL_DEFAULT)x


سپس اين بافر vertex ساخته شده را با داده هاي cube2 پر مي کنيم :


D3DVertexBuffer8SetData VBuffer, 0, Len(Cube2(0)) * 36, 0, Cube2(0)x


در دستورات فوق تابعي با نام GenerateTraingleNormals استفاده شده است . اين تابع دو بردار را از روي سه vertex داده شده با آن مي سازد و سپس ضرب برداري ايندو را حساب مي کند و سپس بردار حاصله را نرمال مي نمايد :


Private Function GenerateTriangleNormals(p0 As UnlitVertex, p1 As UnlitVertex, p2 As UnlitVertex) As D3DVECTOR
Dim v01 As D3DVECTOR 'Vector from points 0 to 1
Dim v02 As D3DVECTOR 'Vector from points 0 to 2
Dim vNorm As D3DVECTOR 'The final vector

'Create the vectors from points 0 to 1 and 0 to 2
D3DXVec3Subtract v01, MakeVector(p1.X, p1.Y, p1.Z), MakeVector(p0.X, p0.Y, p0.Z)
D3DXVec3Subtract v02, MakeVector(p2.X, p2.Y, p2.Z), MakeVector(p0.X, p0.Y, p0.Z)

'Get the cross product
D3DXVec3Cross vNorm, v01, v02

'Normalize this vector
D3DXVec3Normalize vNorm, vNorm

'Return the value
GenerateTriangleNormals.X = vNorm.X
GenerateTriangleNormals.Y = vNorm.Y
GenerateTriangleNormals.Z = vNorm.Z
End Function



حال به توضيح تابع SetupLights مي پردازيم . در اين تابع دو شي D3DMATERIAL8 و D3DCOLORVALUE استفاده شده است :


Private Function SetupLights() As Boolean
Dim Mtrl As D3DMATERIAL8, Col As D3DCOLORVALUE
Col.a = 1: Col.r = 1: Col.g = 1: Col.b = 1
Mtrl.Ambient = Col
Mtrl.diffuse = Col
D3DDevice.SetMaterial Mtrl

Lights.Type = D3DLIGHT_DIRECTIONAL
Lights.diffuse.r = 1
Lights.diffuse.g = 1
Lights.diffuse.b = 1
Lights.Direction = MakeVector(1, -1, 0)

D3DDevice.SetLight 0, Lights

SetupLights = True
End Function



تابع Render بصورت زير است :


Public Sub Render()
D3DDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET Or D3DCLEAR_ZBUFFER, 0, 1#, 0 '//Clear the screen black
D3DDevice.BeginScene
'Draw the cube
D3DDevice.SetTexture 0, CubeTexture
D3DDevice.SetStreamSource 0, VBuffer, Len(Cube2(0))
D3DDevice.DrawPrimitive D3DPT_TRIANGLELIST, 0, 12
D3DDevice.EndScene
D3DDevice.Present ByVal 0, ByVal 0, 0, ByVal 0
End Sub



ساختار اصلي برنامه بصورت زير است :


Call Initialise
Do While bRunning
RotateAngle = RotateAngle + 0.1
If RotateAngle >= 360 Then RotateAngle = RotateAngle - 360

D3DXMatrixIdentity matWorld

D3DXMatrixIdentity matTemp
D3DXMatrixRotationX matTemp, RotateAngle * (pi / 180)
D3DXMatrixMultiply matWorld, matWorld, matTemp

D3DXMatrixIdentity matTemp
D3DXMatrixRotationY matTemp, RotateAngle * (pi / 180)
D3DXMatrixMultiply matWorld, matWorld, matTemp

D3DXMatrixIdentity matTemp
D3DXMatrixRotationZ matTemp, RotateAngle * (pi / 180)
D3DXMatrixMultiply matWorld, matWorld, matTemp


D3DDevice.SetTransform D3DTS_WORLD, matWorld

D3DDevice.LightEnable 0, 0 خاموش کردن light

D3DDevice.LightEnable 0, 1 روشن کردن light

Render
DoEvents
Loop


در متد D3DDevice.LightEnable پارامتر اول شماره منبع نور و پارمتر دوم enable بودن آنرا نشان مي دهد .

A_M_IT2005
13-12-2006, 12:33
سلام

آموزش DirectX-Graphic

جلسه نهم :

موضوع :‌ترسيم متن دو بعدي در DirectX

در اين درس روش ترسيم متن با دو نوع فونت را نشان خواهم داد :
براي رسم يک متن با فونت تعريف شده در سيستم از شي D3DXFont استفاده مي کنيم :


Dim MainFont as D3DXFont
Dim MainFontDesc as IFont
Dim TextRect as RECT
Dim fnt as new stdFont


در حاليکه براي ايجاد يک متن با فونت custom ابتدا يک texture تعريف مي کنيم :


Dim fntTex as Direct3DTexture8


همچنين براي ترسيم هر کاراکتر يک آرايه vertex اي را از نوع TLVERTEX تعريف مي نمائيم :


Dim vertchar(3) as TLVERTEX


حال به سراغ تابع Initialize مي رويم . در اين تابع ابتدا دستورات مربوط به ايجاد اشيا D3D و D3Dx را قرا دهيد سپس دستورات مربوط به اختصاص آداپتور و نيز ايجاد شي D3DDevice را انجام مي دهيم . حال دستورات تنظيم shader و rendering را مي آوريم :


D3DDevice.SetVertexShader TL_FVF
D3DDevice.SetRenderState D3DRS_LIGHTING, False


سپس تنظيمات پارامترهاي transparency براي rendering را انجام مي دهيم :


D3DDevice.SetRenderState D3DRS_SRCBLEND, D3DBLEND_SRCALPHA
D3DDevice.SetRenderState D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA
D3DDevice.SetRenderState D3DRS_ALPHABLENDENABLE, True


حال بايستي textureرا طوري ----- کنيم که در زمان stretch شدن يا squash شدن بهتر بنظر برسد :


D3DDevice.SetTextureStageState 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR
D3DDevice.SetTextureStageState 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR


حال ----- Z را فعال مي کنيم :


D3DDevice.SetRenderState D3DRS_ZENABLE, 1


سپس ماتريسهاي world ، view و projection را تنظيم مي کنيم :


D3DXMatrixIdentity matWorld
D3DDevice.SetTransform D3DTS_WORLD, matWorld
D3DXMatrixLookAtLH matView, MakeVector(0, 9, -9), MakeVector(0, 0, 0), MakeVector(0, 1, 0)
D3DDevice.SetTransform D3DTS_VIEW, matView
D3DXMatrixPerspectiveFovLH matProj, pi / 4, 1, 0.1, 500
D3DDevice.SetTransform D3DTS_PROJECTION, matProj


حال به بخش تنظيم پارامترهاي فونت مي رسيم . در مورد فونت دو بعدي عادي :


fnt.Name = "Verdana"x
fnt.Size = 18
fnt.Bold = True
Set MainFontDesc = fnt
Set MainFont = D3DX.CreateFont(D3DDevice, MainFontDesc.hFont)x


و در مورد فونت custom :


Set fntTex = D3DX.CreateTextureFromFileEx(D3DDevice, yourfilename, 256, 128, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_FILTER_POINT, D3DX_FILTER_POINT, &HFF00FF00, ByVal 0, ByVal 0)x
end function


روتين Render بصورت زير خواهد بود :


Public Sub Render()x
D3DDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET Or D3DCLEAR_ZBUFFER, 0, 1#, 0
D3DDevice.BeginScene


براي رندر متن با فونت عادي بصورت زير عمل مي کنيم :


TextRect.Top = 440
TextRect.Left = 1
TextRect.bottom = 480
TextRect.Right = 640
D3DX.DrawText MainFont, &HFFCCCCFF, "Current Frame Rate: " & FPS_Current, TextRect, DT_TOP Or DT_CENTER


براي رندر متن با فونت custom بصورت زير عمل مي کنيم :


RenderStringFromCustomFont_2D "Hamed Sheidaian", 1, 1, 16, 16
D3DDevice.EndScene
D3DDevice.Present ByVal 0, ByVal 0, 0, ByVal 0
End Sub


همانطور که مشاهده مي کنيد از روتيني با نام RenderStringFromCustomFont_2D استفاده شده است :


Private Sub RenderStringFromCustomFont_2D(strText As String, startX As Single, StartY As Single, Height As Integer, Width As Integer)x
Dim I As Integer
Dim CharX As Integer, CharY As Integer
Dim Char As String
Dim LinearEntry As Integer
If Len(strText) = 0 Then Exit Sub
For I = 1 To Len(strText)x


1 - ابتدا بايستي مختصات texture را انتخاب کنيم . براي اينکار بايستي هر entry را در texture جدا کنيم :


Char = Mid$(strText, I, 1)x
If Asc(Char) >= 65 And Asc(Char) <= 90 Then
LinearEntry = Asc(Char) - 65
ElseIf Asc(Char) >= 97 And Asc(Char) <= 122 Then
LinearEntry = Asc(Char) - 71
ElseIf Asc(Char) >= 48 And Asc(Char) <= 57 Then
LinearEntry = Asc(Char) + 4
ElseIf Char = " " Then
LinearEntry = 63
ElseIf Char = "." Then
LinearEntry = 62
ElseIf Char = ";" Then
LinearEntry = 66
ElseIf Char = "/" Then
LinearEntry = 64
ElseIf Char = "," Then
LinearEntry = 65
End If


بعد از مقداردهي LinearEntry بايستي مختصات grid کاراکتر را پردازش کنيم :


If LinearEntry <= 15 Then
CharY = 0
CharX = LinearEntry
End If
If LinearEntry >= 16 And LinearEntry <= 31 Then
CharY = 1
CharX = LinearEntry - 16
End If
If LinearEntry >= 32 And LinearEntry <= 47 Then
CharY = 2
CharX = LinearEntry - 32
End If
If LinearEntry >= 48 And LinearEntry <= 63 Then
CharY = 3
CharX = LinearEntry - 48
End If
If LinearEntry >= 64 And LinearEntry <= 79 Then
CharY = 4
CharX = LinearEntry - 64
End If


۲ - حال بايستي vertex هاي مورد نياز براي رسم کاراکتر را توليد کنيم :


vertChar(0) = CreateTLVertex(startX + (Width * I), StartY, 0, 1, &HFFFFF
(F,0,(1/16)*CharX,(1/8)*CharY
vertChar(1) = CreateTLVertex(startX + (Width * I) + Width, StartY, 0, 1, &HFFFFF
(F, 0,((1 / 16) * CharX) + (1 / 16), (1 / 8) * CharY
vertChar(2) = CreateTLVertex(startX + (Width * I), StartY + Height, 0, 1, &HFFFFF
((F, 0, (1 / 16) * CharX, ((1 / 8) * CharY) + (1 / 8
vertChar(3) = CreateTLVertex(startX + (Width * I) + Width, StartY + Height, 0, 1, HFFFFFF, 0, ((1 / 16) * CharX) + (1 / 16), ((1 / 8) * CharY) + (1 / 8))x


۳ - رندر vertex ها :


D3DDevice.SetTexture 0, fntTex
D3DDevice.DrawPrimitiveUP D3DPT_TRIANGLESTRIP, 2, vertChar(0), Len(vertChar(0))x
Next I
End Sub

A_M_IT2005
13-12-2006, 12:57
سلام

آموزشDirectX-Graphic

جلسه دهم (پایان)

موضوع : ترسيم اشيا سه بعدي با استفاده از شي Mesh
شي Mesh که جزو اشيا D3DX مي باشد امکان ترسيم اشيا سه بعدي پايه و همچنين ترسيم مش هاي custom دلخواه را به شما مي دهد . در اين درس از شي Mesh براي ترسيم يک کره ( sphere ) استفاده مي کنيم . ابتدا متغير sphere را بصورت زير تعريف کنيد :


Dim sphere as D3DXMesh


همچنين براي نورپردازي و اختصاص material به کره به متغيرهاي زير نياز داريم :


Dim d3dLight As D3DLIGHT8
Dim material As D3DMATERIAL8
Dim Col As D3DCOLORVALUE


در تابع Initial پس از ساخت اشيا D3D و D3DX و D3DDevice بايستي پارامترهاي رنگ ، نورپردازي و اختصاص ماده ( material ) به کره را بصورت زير تنظيم کنيد :


Col.a = 1
Col.b = 1
Col.g = 1
Col.r = 1
d3dLight.Type = D3DLIGHT_DIRECTIONAL
d3dLight.diffuse = Col
d3dLight.Direction = vec(-1, -1, -1)x


نورپردازي از نوع جهت دار با رنگ col و بردار جهت (1-,1-,1-) است .
نکته :
رنگ ambient رنگي است که هنگاميکه جسم در سايه باشد به خود مي گيرد . بعبارت ديگر اين رنگ را جسم وقتي که در معرض يک نور ambient باشد از خود منعکس مي کند .
رنگ diffuse رنگي است که هنگاميکه جسم در معرض نور مستقيم قرار بگيرد از خود منعکس مي کند .


material.Ambient = Col
material.diffuse = Col
d3dDevice.SetMaterial material
d3dDevice.SetLight 0, d3dLight
d3dDevice.LightEnable 0, 1


سپس بايستي پارامترهاي rendering را تنظيم کنيد :


d3dDevice.SetRenderState D3DRS_LIGHTING, 1
d3dDevice.SetRenderState D3DRS_ZENABLE, 1
d3dDevice.SetRenderState D3DRS_LIGHTING, 1
d3dDevice.SetRenderState D3DRS_ZENABLE, 1
d3dDevice.SetRenderState D3DRS_SHADEMODE, D3DSHADE_GOURAUD
d3dDevice.SetRenderState D3DRS_AMBIENT, &H202020
d3dDevice.SetTextureStageState 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR
d3dDevice.SetTextureStageState 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR


حال بايستي شي sphere را بسازيم :


Set Sphere = d3dx.CreateSphere(d3dDevice, 2, 1000, 20, Nothing)x


که ۲ شعاع کره و ۱۰۰۰ تعداد slice هايي است که کره با آن ساخته مي شود .
سپس بردارهاي نقطه ديد و مکان دوربين و رنگ زمينه را تنظيم کنيد ( viewpoint و camerapoint از نوع D3DVECTOR هستند ) .


ViewPoint = vec(0, 0, 0)
CameraPoint = vec(4, 4, 4)
BackColor = &H404040


در روتين Render ابتدا ماتريسها و بردارهاي صحنه را تنظيم مي کنيم :


D3DXMatrixIdentity matWorld
d3dDevice.SetTransform D3DTS_WORLD, matWorld
D3DXMatrixRotationY matView, Rotation
D3DXMatrixLookAtLH matTemp, CameraPoint, ViewPoint, vec(0, 1, 0)
D3DXMatrixMultiply matView, matView, matTemp
d3dDevice.SetTransform D3DTS_VIEW, matView
D3DXMatrixPerspectiveFovLH matProj, pi / 4, 1, 0.1, 500
d3dDevice.SetTransform D3DTS_PROJECTION, matProj


در پايان نيز شروع به رندر صحنه مي کنيم :


d3dDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET Or D3DCLEAR_ZBUFFER, BackColor, 1, 0
d3dDevice.BeginScene
Sphere.DrawSubset 0
d3dDevice.EndScene
d3dDevice.Present ByVal 0, ByVal 0, 0, ByVal 0

siadate
19-12-2006, 23:02
با تشکر ا زشما دوست عزیز : A_M_IT2005

امیدوارم ادامه داشته باشد :cool:

mehrdad-xvc
08-01-2007, 00:14
چطوری میشه داخل رجیستری اطلاعات را ذخیره کرد حذف کرد و دریافت کرد؟

این همه کار ؟میخواهم براتون یک مطلب توپ آموزش بدم که شاید هیچ کدوم از شما ندونید که چطوری میشه بدون API))و توابع چند صد خطی با سه خط برنامه بدون تعریف هیچ تابعی و... با یک دستور داخلی ویژوال بیسیک اطلاعات برنامه هاتون را داخل رجیستری که امن ترین مکان هست ذخیره کنید بازیابی کنید و حتی حذف کنید.خب شما باید از تابع (((SaveSetting))) برای ذخیره اطلاعات استفاده کنید . از تابع (((GetSetting))) اطلاعات را دریافت کنید و از طریق (((DeleteSetting))) آن را حذف کنید تعجب نکنید به همین راحتی خب برنامه هم به این شرح است(ذخیره کردن):





SaveSetting App.Title, "Startup", "Message", "mehrdad-xvc"


چون وقت ندارم که بگم اطلاعات کجا ذخیره میشوند داخل رجیستری شده روی اولین گزینه کلیک کرده و کلمه mehrdad-xvc را جستجو کنید حتما خواهید فهمید چه اتفاقاتی رخ داده !


بعد از درک مطلب بالا این هم توابع خواندن و حذف کردن خیلی ساده و راحت!





دریافت

MsgBox GetSetting(App.Title, "Startup", "Message", "Hello")

حذف

DeleteSetting App.Title, "Startup", "Message"

این تابع خیلی ساده هست ولی ایرادهایی هم داره خودتون خواهید فهمید.

کارش برگرداندن نام پروژه هست.App.titleتابع

shahrdartoope
19-01-2007, 01:11
عزیز چه کردی!!!! کارت حرف نداره ادامه لطفا :)

A_M_IT2005
19-01-2007, 19:32
سلام دوستان
واقعا خوشحالم که مطالب و جلسات برای شما مفید بوده.
از mehrdad-xvc هم به خاطر مطلبی که قرار دادند تشکر میکنم.
از همه وی بی کاران عزیز درخواست میکنم که سوالاشونو در این تاپیک نپرسن.
این تاپیک مثل یک کتابه. من این تاپیکو برای همین زدم که مطالب در مورد وی بی جامع و کامل باشه.
اگه سوالی دارید :
1. اول در سایت جستجو کنید.
2. اگه سوال شما پرسیده نشده بود و جواب خودتونو پیدا نکردید ، یه تاپیک ایجاد کنید.
ممنون.

A_M_IT2005
12-02-2007, 16:43
سلام

ايجاد ساختارهاي داده اي در ويژوال بيسيک

جلسه اول :

مقدمه :

ساختارهاي داده اي از نظر تعداد اعضا به دو دسته استاتيک و ديناميک تقسيم مي شوند . ساختارهاي استاتيک مثل آرايه هاي يک بعدي و آرايه هاي دو بعدي ، تعداد اعضاي آنها در زمان طراحي برنامه مشخص مي شود و در طول اجراي برنامه ثابت است اما تعداد اعضاي ساختارهاي داده اي ديناميک در طول اجراي برنامه تغيير مي کند . ليست پيوندي ( LinkList ) ، پشته ( Stack ) ، صف ( Queue ) و درختهاي باينري ( Tree Binary) ، نمونه هايي از ساختارهاي داده اي ديناميک هستند .
ليست پيوندي شامل مجموعه اي از عناصر داده اي است که اضافه و حذف اعضا در هر جاي ليست ممکن است .
پشته يک ساختار داده اي مهم در کامپايلرها و سيستم هاي عامل است که عمل اضافه و حذف عناصر از ابتداي آن انجام مي شود .
صف يک ساختار داده اي است که عمل اضافه کردن از انتها و عمل حذف کردن از ابتداي آن انجام مي شود .
درختهاي دودويي براي جستجوي بسيار سريع ، ذخيره سازي داده ها و کامپايل عبارات استفاده مي شوند .

نوع داده Variant :

نوع داده variant براي متغيرهايي بکار مي رود که بطور صريح نوع آنها تعريف نشده است مثال :
Dim value As Variant
اين نوع داده مي تواند هر نوع داده اي را در خود ذخيره کند . همچنين براي ايجاد ساختارهاي داده اي مثل ليست هاي پيوندي ، صف ، پشته و درخت مناسب است .
نوع داده موجود در variant مي توان توسط توابع VarType و TypeName تعيين کرد . تابع VarType يک مقدار صحيح برمي گرداند که نشان دهنده نوع ذخيره شده در variant است .
مثال :
Dim value as Variant
value=”Hello”x
در اينصورت مقدار بازگشتي ( VarType( value برابر 4 خواهد بود .
تابع TypeName يک رشته برمي گرداند که نشان دهنده نام نوع داده ذخيره شده در variant است .

اخذ حافظه بطور ديناميک Dynamic Memory Allocation :

براي ايجاد و نگهداري ساختارهاي داده اي ديناميک بايستي در هنگام اجراي برنامه بتوان فضاي بيشتري براي نگهداري داده هاي جديد بدست آورد . با استفاده از کلمه کليدي New مي توان در ويژوال بيسيک حاقظه ديناميک گرفت :
Set NewNode=New ListNode
که ListNode يک شي از ساختار داده اي مورد نظر ماست .

کلاسهاي خود ارجاعي :

کلاس خودارجاعي نوعي کلاس است که داراي يک اشاره گر ( Pointer ) به يک شي از همان نوع کلاس باشد . براي مثال اگر کلاس ما به اسم ClistNode باشد و متغير زير را در آن تعريف کنيم ، اين کلاس يک کلاس خود ارجاعي است :
Private mNextNode as ClistNode
از mNextNode براي لينک دادن اعضاي يک ساختار داده اي ديناميک بهم استفاده مي شود ( بعبارت ديگر گره زدن يک شي از کلاس ClistNode به يک شي ديگر از همان کلاس ) . شي هاي خودارجاعي مي توانند به همديگر لينک شوند و ساختارهاي داده اي مثل ليست پيوندي ، صف ، پشته و درخت را ايجاد کنند .
شکل زير دو شي خود ارجاعي را نشان مي دهد که بصورت يک ليست بهم لينک شده اند . عبارت NULL بدين معنا است که شي خودارجاعي به شي ديگري اشاره نمي کند ( Nothing ) و نشان دهنده انتهاي ساختار داده است .

mazi_z_PSP
14-04-2007, 10:00
ببخشيد از افراد این تاپيک خواهش ميکنم که متالبشون رو به صورت پی دی اف بزارند که راهتّر بشه ازشون استفاده کرد ممنون

CrazyTux
05-05-2007, 05:31
لطفا اگه میشه یک فایل Pdf از همه این جلسات درست کنید!:18:

aminjan0098
15-06-2007, 10:23
واقعا که....:13:
مطالب رو از وبلاگ مهندس شیداییان ور می داری می ذاری اینجا به اسم خودت...:grrr: :grrr:

تکنیک برتر
15-06-2007, 11:59
aminjan0098 سلام عزیزم به احتمال زیاد سوء تفاهم شده این دوست ما اگر مطالب رو از سایت های دیگه برداشته بود حتما منبع میزد حالا اگر شما آدر این وبلایگ و بزارین ممنون می شوم بنده برم ببینم گفته شما صحت داره یا خیر!؟
ممنون

aminjan0098
15-06-2007, 20:49
بفرمایید:
[ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]

آخرین مطلب آن هم تشخیص فشرده شدن کلید های کیبرد هست که در صفحات قبل کپی شده!
بیچاره اقای شیداییان که مطلب می نویسه بقیه سو استفاده میکنن

A_M_IT2005
16-06-2007, 08:41
aminjan0098 اگه پست اول رو بخونی میبینی که من منبع رو نوشتم.
از این به بعد با دقت بیشتری نگاه کن .
[ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]

aminjan0098
16-06-2007, 14:31
aminjan0098 اگه پست اول رو بخونی میبینی که من منبع رو نوشتم.
از این به بعد با دقت بیشتری نگاه کن .
[ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]

واقعا عجب رویی داری !

دیروز خودم نگاه کردم نبود اونوقت خیال میکنی پست رو ادیت کنی جماعت خرن؟ خیلی ضایعی

تکنیک برتر
17-06-2007, 12:15
aminjan0098 خواهشن درست صحبت کنید اینجا مگه چت رومه که شما اینجوری بیان نوشتار می کنید واقعا خجالت داره برای یک کاربر

A_M_IT2005
18-06-2007, 02:30
aminjan0098
شما که انقدر باهوشی که به ویرایش پست نگاه کنی ، پس چرا بی دقتی و به تاریخ ویرایش نگاه نمیکنی.
تاریخ ویرایش تقریبا 6 - 7 ماه پیشه. یعنی تو دی یا بهمن 85 .
در ضمن از همون اول که این تاپیکو زدم ، اولین چیزی که نوشتم منبع مقالات بود که اینو میتونی از بچه هایی که مطالب رو دنبال میکنن بپرسی.
اینم یادت باشه که با این بی دقتی و زود قضاوت کردن و توهین کردن ، هم تو سایت ضربه میخوری و هم تو زندگی.

aminjan0098
18-06-2007, 18:56
aminjan0098
شما که انقدر باهوشی که به ویرایش پست نگاه کنی ، پس چرا بی دقتی و به تاریخ ویرایش نگاه نمیکنی.
تاریخ ویرایش تقریبا 6 - 7 ماه پیشه. یعنی تو دی یا بهمن 85 .
در ضمن از همون اول که این تاپیکو زدم ، اولین چیزی که نوشتم منبع مقالات بود که اینو میتونی از بچه هایی که مطالب رو دنبال میکنن بپرسی.
اینم یادت باشه که با این بی دقتی و زود قضاوت کردن و توهین کردن ، هم تو سایت ضربه میخوری و هم تو زندگی.

عجب !
چی شد روز قبلش که نگاه کردم مطلب دزدی فشرده شدن صفحه کلید تو ص 2 بود الان رفته تو صفحه 1
:evil2: :grrr: :angry:
در ضمن من صفحه اول را هم همان روز نگاه کردم به وضوح یادم هست که چیزی راجع به منبع نبود

A_M_IT2005
19-06-2007, 15:10
ببین واسه اینکه اشتباه خودتو قبول نکنی، داری بحث رو ادامه میدی.
خودتم میدونی که اشتباه کردی.
این که چرا ص 2 بوده و رفته ص 1 دست من نیست. باید از همکار یا مدیر انجمن بپرسی.
منبع هم از اول بوده . بهتره به جای اینکه بحثو ادامه بدی تا حرف خودتو به کرسی بنشونی یا تعداد پستهاتو زیاد کنی و یا هر کاری طبق قوانین سایت نیست ، چند تا مطلب بزاری که دیگران استفاده کنند.

در ضمن بهت توصیه میکنم که بحث رو ادامه ندی ، وگرنه باهات برخورد میشه.

Payman_62
03-02-2009, 18:52
سلام.
ضمن تشکر از زحمات a_m_it2005 به خاطر تاپیک مفیدتشون تمامی پست های بی ارتباط با تاپیک پاک شدند.
دوستان عزیز لطفا قوانین سایت رو رعایت فرمایید و در تاپیک مربوطه پست بدید و سوال مطرح کنید.