تبليغاتX
Iranian Technology
 
آموزش برنامه نویسی
 
 
آموزش ویژوال بیسیک و ... برای دیدن تمامی مطالب به آرشیو ماهانه مراجعه کنید
 

بازم سلام دوستان. اول از همه باید بگم که من یک سری آموزش هایی که دادم درست نبود و اشکال داشت که اونها رو برطرف کردم . همچنین یه سروسامونی به پست ها دادم. امیدوارم راضی باشید .

 

برای اختصاص بافت به اشکال سه بعدی در OpenGL در ویژوال بیسیک ما باید کارهای زیادی کنیم و کدهای زیادی بنویسیم . اما برای نوشتن برنامه های معادل به زبانهای C یا Delphi خیلی راحت تر هستیم و نیاز به کد نویسی های زیادی نداریم.

غیبت در مورد ویژوال بیسیک رو فعلا کنار می گذاریم .

 

برای اختصاص بافت به اشکال سه بعدی ابتدا بدنه ی اصلی OpenGL رو مطابق با آموزش جلسه اول به پیش ببرید.

روشی که ما در امروز برای اختصاص بافت به اشکال به کار می بریم روشی ناکارامد است چرا که از سرعت پایینی برخوردار است. در جلسه بعد روشی را آموزش می دهم که سرعتش حداقل ده برابر روش امروزه.( فعلا بمونین تو کفش)

 

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

 

ابتدا خاصیت ScaleMode  فرم برنامتون رو به 3-Pixels تغییر بدین. من پیشنهاد می کنم همیشه خاصیت ScaleMode  فرم برنامتون رو به پیکسل تنظیم کنید. بعد هم یک عدد PictureBox به فرم اضافه کنید. خاصیت ScaleMode کنترل Picture1 رو به 3-Pixel ، خاصیت AutoRedra = True و AutoSize = True قرار بدین . خاصیت Visible = False. ممنون .

 

از منوی Project>Add Module  را بزنید تا پنجره Add Module با شود. روی Open کلیک کنید تا یک مدول(ماژول خودمون) جدید ایجاد بشه . خاصیت Name مدول جدید رو به LoadBitmap یا هر چیز دیگه تغییر بدین.

خوب میریم سراغ کد نویسی :

 

ابتدا ما باید یک تابع بنویسیم که آدرس یک عکس رو بگیره و اون عکس رو به Picture1 بفرسته. پس در مدول جدید بنویسید :

 

Global Texture(0) As Long

 

Public Function LoadBMP( FileName as String , Texture() as GLUint, Height as Long , Width as Long) as Boolean

 

Form1.Picture1.Picture = LoadPicture(FileName)

CreateMapImage Form1.Picture1 , Texture() , Height , Width

LoadBMP = True

 

End Function

 

اگه توجه کرده باشین در خط سه تابعی آوردیم که بعد آن را  می نویسیم . این تابع مقدار بازگشتی نداره اما آرگومان های خودشو مقدار دهی می کنه . آرگومان اول یک کنترل PictureBox  که به عنوان ورودی اصلی به تابع فرستاده میشه. تابع بعد از انجام دادن یک سری پردازش ها متغیرهای Texture() , Height , Width رو مقدار دهی می کنه.

 

بعد هم کدهای زیر رو بنویسید :

 

Public Sub CreateMapImage(Pict As PictureBox , TextureImg() as GLByte , Height as Long , Width as long)

 

Pict.ScaleMode = 3

Height = Pict.ScaleHeight

Width = Pict.ScleWidth

 

ReDim TextureImg(2 , Height -1 , Width -1)

 

Dim X as Long

Dim Y as Long

Dim C as Long

Dim YL as Long

 

For x = 0 to width – 1

          For y = 0 to height

                   C = pict.Point(x,y)

                   YL = Height – Y – 1

                   TextureImg(0 , x , YL) = C And &HFF

                   TextureImg(1 , x , YL) = (C \ 255) And &HFF

                   TextureImg(2 , x , YL) = (C \ 65536) And &HFF

          Next

Next

 

End Sub

 

به طور کل تابع بالا کار ذخیره سازی پیکسل ها ی تصویر مورد نظر به صورت BGR (Blue,Green,Red) در داخل یک آرایه به نام TextureImg() رو داره.

 

در آخر هم باید تا بعی رو بنویسیم که کار آن تبدیل تصویر به بافت texture است. کدهای زیر رو هم بع مدول جدید خود اضافه کنید.

Public Function LoadGLTextures() As Boolean

 

Dim W as Long , H as Long

Dim Status as Boolean

Dim TextureImage() As GLByte

 

Status = False

 

If LoadBMP("C:\Windows\Coffee Bean.bmp" , TextueImage() , H , W) Then

          Status = True

 

          GLGenTextures 1 , Texture(0)

          glBindTexture glTexture2D , Texture(0)

          glTexImage2D glTexture2D ,  0 , 3 , W , H , 0 , GL_RGB , GL_UNSIGNED_BYTE , TextureImage(0,0,0)

          glTexParameteri glTexture2D , tpnTextureMinFilter , GL_LINEAR

          glTexParaMeteri glTexture2D , tpnTextureMagFilter , GL_LINEAR

 

End If

 

Erase TextureImage

LoadGLTextures = Status

 

End Function

 

در خط  6 مشخص کردیم که اگر مقدار بازگشتی تابع LoadBMP برابر True بود کار تبدیل Bitmap  به Texture شروع بشه. همچنین شما می توانید در خط 6 به جای "C:\Windows\Coffee Bean.bmp" آدرس هر عکس دیگه ای رو بنویسید اما شرطش اینه که اندازه ی تصویر توانی از 2 باشه . مثل 128*128 یا 256*256 و ... .

خط 7 برای ایجاد بافت مورد استفاده قرار می گیرد که در glGenTexture حرف Gen مخفف کلمه ی Generate به معنی تولید کردن است. تابع glGenTextures دو آرگومان میگیره که آرگومان اولی تعداد بافتها(Textures) و آرگومان دوم آرایه ای است که تصویر در آن ذخیره شده است. در ادامه چند تا بافت رو به یک مکعب اختصاص میدیم.

در خط 8 کار تابع glBindTexture اینه که مشخص میکنه بافت ما از چه نوعی باشه 2بعدی یا 1بعدی. خط 9 هم برای ایجاد بافت texture به کار میره که آرگومان های اون معلومه و نیازی بع توضیح نداره .

خط های 10 و 11 هم برای چگونگی استفاده از Texture به کار میروند که شما می توانید به جای استفاده از GL_LINEAR از GL_NEAREST نیز استفاده کنید.

 

خوب کار ما با مدول LoadBitmap تمام شد.

اگر کارهای جلسه ی اول رو درست انجام داده باشین حالا باید در پنجره ی Project روی OpenGLMain دوبار کلیک کنید تا کدهای مربوط به اون باز بشه .

به دنبال تابع InitGL() بگردید و کدهای اون رو به صورت زیر تغییر بدید.

 

Public Function InitGL()As Boolean

         

          If LoadGLTextures = False Then

                   InitGL = False

                   Exit Function

          End If

 

          glEnable glcTexture2D

          glShadeModel smSmooth

 

          glClearColor 0,0,0,0

 

          glClearDepth 1

          glEnable glcDepthTest

          glDepthFunc cflEqual

 

          glHint htPerspectiveCorrentionHint , hmNicest

 

InitGL = True

End Function

 

خط دوم برای جلوگیری از خطا آورده شد و کار اون اینه که اگر تابع LoadGLTextures کار خود رو با موفقیت انجام نداد تابع InitGL = False بشه. در خط 6 با استفاده از تابع glEnable  کار اختصاص بافت رو فعال کردیم. خط 7 هم قبلا توضیح دادم که کارش یه جور دندانه ذداییه. خط 8 هم رنگ پس زمینه ی فرم رو مشخص می کنه.

اما خط 9 :

میدونید که اشکال سه بعدی دارای مختصات x,y,z هستند. هنگامی که یک شکل سه بعدی در OpenGL رسم میشه یک بافر مخصوص برای نگهداری مقدار Zها وجود داره که مختصات Z شکل ها در داخل آن ذخیره میشود. خط 9 بافر Zها (یا DepthBuffer یعنی بافر عمق) رو خالی میکنه . خط 10 هم تکنیک DepthTestingv رو فعال میکنه که در جلسه بعدی باید درموردش صحبت کنم. خط های 11 و 12 هم مربوط به جلسه ی بعد می شوند.

 

خوب دیگه خودتون رو برای رسم آماده کنید . در پنجره ی Project  روی مدول مربوط به تابع DrawGLScene() (فکر کنم اسم مدول اون DrawShape بود)دوبار کلیک کنید تا کدها ی اون به نمایش دربیاد. حالا اون رو به صورت زیر تغیر بدید :

 

Dim Rot(3) As GlFloat

 

Public function DrawGLScene()As Boolean

 

          glLoadIdentity

          glTransLatef 0,0, -5

          glrotatef Rot(0) , 1 ,0 ,0

          glRotatef Rot(1) , 0, 1,0

          glRotatef Rot(2) , 0, 0,1

 

          glBindTexture glTexture2D , Texture(0)

 

          glBegin bmQuads

                   gltexCoord2f  0,0 : glVerTex3f  -1, -1 ,1

                   glTexCoord2f  1,0 : glVertex3f 1, -1 ,1

                   glTexCoord2f 1,1 : glvertex3f 1,1,1

                   glTexCoord2f 0,1 : glVertex3f -1,1,1

          glEnd

 

Rot(0) = Rot(0) + 0.2

Rot(1) = Rot(1) + 0.3

Rot(2) = Rot(2) + 0.25

 

DrawGLScene = True

End Function

 

اگه این برنامه رو اجرا کنید شاید چیزی روی مانیتور نمایش داده نشه که شما میتونید glTranslatef 0,0,-5 رو ننویسید که این کار درستی نیست و من پیشنهاد می کنم این کار رو انجام ندید. برای رفع این مشکل ما یک تابع باید بنویسیم که با تغیر اندازه فرم برنامه اشکال سه بعدی ما هم تغییر اندازه بدن. پس در داخل مدول OpenGLMain در زیر همه ی کد ها قطعه کد زیر رو بنویسید :

 

Public sub ResizeGLScene(Width as GLSizei , Height as GLSizei)

 

          glViewPort 0,0,Width,Height

          glMatrixMode mmProjection

          glLoadIdentity

 

          gluPerspective 45 , width / Height , 0.1 , 100

          glMatrixMode mmModelView

          glLoadIdentity

 

End Sub

 

حالا سراغ فرم برنامه میریم و در رویداد Resize فرم کدهای زیر رو می نویسیم:

Private sub Form_Resize()       'x

          ResizeGLScene ScaleWidth , ScaleHeight

End sub

برای توضیحات بیشتر تابع ResizeGLScene میتونید به سایت PSWare برید و در قسمت دوم آموزش OpenGL توضیحات خوبی دریافت کنید.

 

اختصاص بافت به اشکال کلاس Quadric :

 

برای اختصاص بافت به اشکال کلاس Quadric در داخل تابع DrawGLScene به جای استفاده از بلوک GLBegin / glEnd همانند درس سوم باید یک کره رسم کنیم . برای بهتر فهمیدن قطعه کد زیر رو برای تابع DrawGLScene امتحان کنید:

 

Dim Rot(3)as GLFloat

 

Public function DrawGLScene()As Boolean

 

          glLoadIdentity

          glTransLatef 0 , 0 , -5

          glRotatef Rot(0) , 1 , 0 , 0

          glRotatef Rot(1) , 0 , 1 , 0

          glRotatef Rot(2) , 0 , 0 , 1

 

          glBindTexture glTexture2D , Texture(0)

 

          Dim Q As gluQuadricObj

          Q = gluNewQuadric

          gluQuadricTexture Q , True

          gluSphere Q , 1 , 16 , 16

 

          Rot(0) = Rot(0) + 0.2

          Rot(1) = Rot(1) + 0.3

          Rot(2) = Rot(2) + 0.25

         

DrawGLScene = True

End Function

 

اگه توجه کرده باشین میبینید که چه کار ساده ایه . تمامی کدهای بالا به جر یک خط (خط 11) توضیح داده شده . در خط 11 مشخص کردیم که خاصیت اختصاص بافت به اشکال کلاس Quadric فعال باشد یا غیر فعال .

شما می توانید به جای استفاده از تابع gluSphere هر یک از توابع دیگر مربوط رسم را به کار ببرید که در قسمت چهارم آموزش OpenGL گفته شد.

 

اینم سورسش : دانلود برنامه

 

خوب امروز هم من اومدم و یه عیدی به شما دادم و حالا به قول بروبچز اراک جاعیدونه می خوام(یعنی نظر می خوام) . ببنیم چه کار می کنید .

راستی قبل از خداحافظی باید بگم آموزش بعدی آموزش جالبیه . در پست بعدی روشی رو برای اختصاص بافت به اشکال آموزش میدم که حداقل 10 برابر سرعتش بیشتره. همچنین بعد از اون هم می ریم سراغ نورپردازی (Lighting) و حالت شیشه کردن (Blending) و فیلتر مه ( Foging) . پس تا بعد .

 نظر هم یادتون نره.

 |+| نوشته شده در  سه شنبه ششم فروردین 1387ساعت 10:52  توسط علی  | 
 
  بالا  

Free Counter