2011年3月5日 星期六

BoneEdit - 模型

c:我說明一下,這邊使用到的模型檔為MMD
路人:哦,有什麼意義嗎?
c:沒什麼,就只是一個副檔名
路人:之前你有提到,是從warcraft III提取出來的,
     我記得是叫MDX的模型檔,那從MDX轉MMD是怎麼弄啊?
c:就...一個小工具,然後.....你先看看吧.
路人:怎麼回事啊...
c:你看了就明白了.

路人:這是在做啥?為什麼不是那種按一個鈕就完成的
c:呃,手工的,要自己開檔找出檔案內有VRTX,PUTX,UVBX等標籤,後面會跟著資料的位址.
路人:哇,真是辛苦你了啊,但也太爛了吧,不用介紹了.
C:所以重點不在這裡,還是來看看BoneEdit的模型類別吧.

class CMmd
{
public:
    CMmd();
    virtual ~CMmd();
    bool Load( char *filename );
    void Destroy( void );
    int MeshCount; //頂點資料數量
    int UVCount; //貼圖資料數量
    Vector *Mesh;      //頂點資料
    Vector *MeshCopy;      //頂點資料
    gUV *UV;   //貼圖資料
    Vector *Normal;//向量資料
    char FileName[256];//檔案名稱
}

最主要的功能其實就是把模型載入,附上Load的程式碼

bool CMmd::Load( char *filename ){
    FILE *f;
    strcpy(FileName, filename);
    f = fopen( filename, "rb" );
    char *p;

    if( f )
    {
        int i;
        if( Mesh )
            free( Mesh );
        if( MeshCopy )
            free( MeshCopy );
        if( UV )
            free( UV );
        if( Normal )
            free( Normal );
        fread( &MeshCount, sizeof(int), 1, f );
        Mesh = (Vector *)malloc(sizeof(Vector) * MeshCount );
        MeshCopy = (Vector *)malloc(sizeof(Vector) * MeshCount );
        for( i=0;i<MeshCount;i++)
            fread( Mesh[i], sizeof(Vector), 1, f );
        memcpy( MeshCopy, Mesh, sizeof(Vector) * MeshCount );
        fread( &UVCount, sizeof(int), 1, f );
        UV = (gUV *)malloc(sizeof(gUV) * UVCount );
        for( i=0;i<UVCount;i++)
        {
            fread( &UV[i].u, sizeof(float), 1, f );
            fread( &UV[i].v, sizeof(float), 1, f );
        }
        fclose( f );
        Normal = (Vector *)malloc(sizeof(Vector) * MeshCount );
        memcpy(Normal,Mesh,sizeof(Vector) * MeshCount);
        for( i=0;i<MeshCount;i++)
        {
            Normal[i].Normalize();
        }
    }
    return true;
}

2011年3月4日 星期五

BoneEdit-Camera

我們需要一個攝影機的功能,方便視角轉來轉去,像下面的影片

class CCamera
{
public:
    CCamera();
    virtual ~CCamera();
    void UpData();//更新
    void Move(float vec);//前後移動
    void Strafe(float vec);//左右平移
    void SetPosition(Vector pos);//設定位置(觀看點隨位罝移動)
    Vector Position;//位置
    Vector ViewPoint;//觀看的目標
    Vector UpVector;//頭頂的位置
};

Vector是個向量的類別,包含了xyz的值.
最重要的Updata為
void CCamera::UpData()
{
    gluLookAt(  (GLfloat)Position[0], (GLfloat)Position[1], (GLfloat)Position[2],
                (GLfloat)ViewPoint[0], (GLfloat)ViewPoint[1], (GLfloat)ViewPoint[2],
                (GLfloat)UpVector[0], (GLfloat)UpVector[1], (GLfloat)UpVector[2] );
}
直接使用gluLookAt設定攝影機的參數,其它的函式都是一些數學運算,像是
void CCamera::SetPosition(Vector pos)//設定位置
{
    Vector v;
    v = pos - Position;
    ViewPoint += v;
    Position = pos;
}
其它的函式就不貼程式碼了.

2011年3月3日 星期四

工具BoneEdit

路人:這個工具是用BCB寫的吧,看附圖左上角的LOGO就知了.
c:是啊
路人:看起來沒什麼.
c:雖然這個BoneEdit只是個小軟體,但內容也不少,你看看用到的元件

路人:哇,那程式碼貼出來不就一狗票.
c:這樣好了,先別管元件,我主要介紹類別的功能,有需要的,我再說明裡面程式的寫法.

OpenGL的類別,主要是初始OpenGL
class CGL
{
public:
CGL();
virtual ~CGL();
void Resize(GLsizei width, GLsizei height, GLsizei depth);//視窗大小更動時呼叫
        bool Initial(HWND hWnd, unsigned int Width, unsigned int Height, int bits );//初始化
        void NowDC(void);//建立dc
        HDC m_hDC;
private:
int m_ScrWidth;//寬
int m_ScrHeight;//高
        int m_Depth;//深度
HGLRC m_hRC;//渲染環境
HWND m_hWnd;//渲染環境對應的視窗
};

其實看了上一篇的附圖,就可以知道,這個工具是BCB寫的.
在BCB內的用法為:
CGL *GL;  <--在Unit1.h內的TForm1宣告

Unit1.cpp
void __fastcall TForm1::FormCreate(TObject *Sender)//初始化
{
    GL = new CGL();
    if( GL->Initial( Panel1->Handle, Panel1->ClientWidth, Panel1->ClientHeight, 32 ) )
    {
Timer1->Enabled = true;
    }
}
//更新就如下使用(用到了Timer元件,至於Timer的Interval,就設為1)
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
    GL->NowDC();  //視窗移動時,會破壞畫面,用DC重建RC
    GL->Resize( Panel1->ClientWidth, Panel1->ClientHeight, 50000 );
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    glClearColor (0, 0, 0, 0.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    //*******************
    //這裡處理繪製
    //*******************

    SwapBuffers(GL->m_hDC);//繪製好的圖案顯示出來
}

路人:感覺不是很高明耶,而且效率應該很差吧...
c:真是不好意思,就寫寫程式...好玩嘛,
  順便補上使用的到.h

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <math.h>    
#include <iostream.h>
#include <commctrl.h>
#include <windowsx.h>
#include <mmsystem.h>

#include <gl\gl.h> // Header File For The OpenGL32 Library
#include <gl\glu.h> // Header File For The GLu32 Library
#include <gl\glaux.h> // Header File For The GLaux Library

typedef struct
{
    float x,y,z;
} gVector;

typedef struct
{
    float u,v;
} gUV;

typedef struct
{
float m[16];
} gMatrix;

#define SafeDelete(pObject) if(pObject!=NULL) {delete pObject; pObject=NULL;}

2011年3月2日 星期三

一段對話

c:看了上一篇武器光影的效果後,應該會覺得模型很眼熟吧...
路人:哦,這不是Warcraft III的模型嗎.
c:沒錯,就是Warcraft III的模型.
路人:這沒什麼啊,網路上有一堆工具都把資料都解出來了,沒什麼特別的
c:呃,的確是沒什麼特別,不過再看仔細一點,一定會覺得奇怪.
路人:那個動作怎麼怪怪的啊...,好像跟原廠不太一樣耶!Arthas王子有這一招旋風大鐵鎚嗎?
     而且跑步的姿勢也不太一樣了,是把資料導回3DMAX再做新的嗎?
c:唉,若是這樣就好了,我用了最笨的做法,做了一個工具,自己要重建骨架,設定頂點權重,
    再調新的動作,你看,工具長這個樣子

路人:你有病啊,是不是太閒了...
c:知道了,以後會少幹這種傻事了...
路人:那至少交代一下怎麼做的,不要讓以後的人跟著你走錯了.

c:嗯,等我有空吧...
路人:&^%$#$%^&$$@$#$#


下次就從這個工具再往下介紹.


OpenGL 武器光影的效果

先看一下效果:

哦,感覺有點差哩,武器劃出的光影怎麼跟市面上的遊戲差那麼多...
這個嘛,以前練習的作品,就不用太再意了.

順便補上之前的物體發光效果,看影片比較有感覺...
細節是如何做的呢?有時間再慢慢介紹了.