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

در این درس در مورد روشهای ساخت انیمیشن در 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 می گذاریم و آنرا رندر می کنیم .



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