路人:那個骨骼資料從那裡來的啊?
c:自己先定義一個文字檔,填入編號、位置、相依關係等...
主要是得到骨架的資料,載入工具後,就可以自由調整了.
路人:這種事用3DMAX來做,再導出骨骼不是更好?
c:沒錯,那這個工具也不用寫了,直接寫3DMAX外掛就好啦.
反正不是為工作而做的,從無到有弄個編輯器也是有其中的樂趣嘛.
路人:嗯,那就抓些重點出來吧.
c:先看一些定義吧.
typedef struct
{
float r,g,b;
} gColor;
struct gBone//一根骨骼
{
long id; // BONE ID
char name[32]; // BONE NAME
gBone *parent; // POINTER TO PARENT BONE
int childCnt;//子骨骼數量 // COUNT OF CHILD BONES
gBone *children;//指向的子骨骼位置 // POINTER TO CHILDREN
int childrenidx;//指向的子骨骼位置索引
gMatrix matrix;//矩形的值
Vector pos;
Vector rot;
Vector startrot;//初始旋轉量
Vector startpos;//初始位置
Vector wpos;//真實的世界位置
int length;//長
int width; //寬
gColor color;
};
最重要的變數就是matrix了,模型的頂點都要乘上這個值,這樣模型就會跟著骨骼動作了,
它的定義前幾篇就有貼出來了,這裡我再貼一次.
typedef struct
{
float m[16];
} gMatrix;
class CBone
{
public:
CBone();
virtual ~CBone();
bool LoadBone( char *filename );//載入文字檔
bool LoadBone_b( char *filename );//載入位元檔
bool SaveBone_b( char *filename );//存入位元檔
void Draw( GLenum mode );
void Destroy( void );
bool flag( void ){ if( Bone ) return true; else return false; }
void AllColor( float r, float g, float b );//設定所有骨骼顏色
void Color( int id, float r, float g, float b );//設定骨骼顏色
void ComputeWPos( void );//算出每個骨骼的世界位置
Vector CameraPoint;
Vector CameraView;
int BoneCount, Selectid;
bool Show; //是否顥示出來
gBone *Bone;
protected:
void DrawSkeleton( gBone *rootBone, GLenum mode );
void BoneBox( gBone *curBone );
void CWPos( gBone *rootBone );//算出每個骨骼的世界位置
};
matrix怎麼算出來的呢?呼叫DrawSkeleton就可得到
void CBone::Draw( GLenum mode )
{
if( !Bone )
return;
glPushMatrix();
glTranslatef(Bone->startpos[0]+Bone->pos[0],
Bone->startpos[1]+Bone->pos[1],
Bone->startpos[2]+Bone->pos[2]);
glRotatef(Bone->rot[2], 0.0f, 0.0f, 1.0f);
glRotatef(Bone->rot[1], 0.0f, 1.0f, 0.0f);
glRotatef(Bone->rot[0], 1.0f, 0.0f, 0.0f);
DrawSkeleton(Bone,mode);
glPopMatrix();
}
DrawSkeleton是個遞迴函式,因為骨頭是一層一層的
void CBone::DrawSkeleton( gBone *rootBone, GLenum mode )
{
int loop;
gBone *curBone;
curBone = rootBone->children;
for (loop = 0; loop < rootBone->childCnt; loop++)
{
glPushMatrix();
glTranslatef(curBone->startpos[0]+curBone->pos[0],
curBone->startpos[1]+curBone->pos[1],
curBone->startpos[2]+curBone->pos[2]);
glRotatef(curBone->rot[2], 0.0f, 0.0f, 1.0f);
glRotatef(curBone->rot[1], 0.0f, 1.0f, 0.0f);
glRotatef(curBone->rot[0], 1.0f, 0.0f, 0.0f);
if( mode == GL_SELECT )
{
if( Show )
{
glLoadName(curBone->id);
BoneBox( curBone );
}
}
else
{
if( Show )
BoneBox( curBone );
}
glGetFloatv(GL_MODELVIEW_MATRIX,curBone->matrix.m);///在這裡取得的矩陣就可以給模型用了
if (curBone->childCnt > 0)
DrawSkeleton( curBone, mode );
glPopMatrix();
curBone++;
}
}
沒有留言:
張貼留言