close
دانلود فیلم
مباحث پيشرفته Direct3D - بخش سوم

در درسهای قبلی در مورد 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(CreateKeyFrameFromFile.nMaterials) As D3DMATERIAL8
ReDim CreateKeyFrameFromFile.TexList(CreateKeyFrameFromFile.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(CreateKeyFrameFromFile.Mesh.GetNumVertices) As D3DVERTEX
hResult = D3DXMeshVertexBuffer8GetData(CreateKeyFrameFromFile.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 ها نگهداری کنیم .



لینک کوتاه پست
مطالب مرتبط با پست جاری
  • نکات مهم
    1- لطفا نظر خود را با زبان فارسی بیان کنید
    2- رایتم نظرات اسپم و تبلیغی شما را تایید نمی کند
    3- لطفا نظرات شما بدون ابهام و واضح باشد
  • نام
    ایمیل (منتشر نمی‌شود) (لازم)
    وبسایت
    :):(;):D;)):X:?:P:*=((:O@};-:B/:):S
    نظر خصوصی
    مشخصات شما ذخیره شود ؟[حذف مشخصات] [شکلک ها]
    کد امنیتی
به کانال تلگرام سایت ما بپیوندید