最近实验室接了一个项目,开发一个虚拟现实平台,用来展示海底场景,能够对海洋各种环境进行实时渲染,并对以鱼类为主的生物进行形态和行为仿真,设计并实现其基本动作.主要内容有用三维建模,雾化,粒子系统等模拟海底空间效果,对光,影,雾,浪,水流等进行实时渲染.
技术关键问题及解决途径:1) 虚拟海底场景实时生成:通过借助图形处理器(GPU),利用NVIDIA推出的Cg语言编程对海底场景相关的水体、光影效果进行实时渲染;2) 鱼类表面纹理的细节表现:通过使用动态纹理,光影计算以及OpenGL库的纹理映射方法等表现鱼类等的表面纹理细节,使其与所在的海底环境相配合;
平台中对鱼类的动作仿真是难点之一,打算采用ms3d文件,从模型中读取数据,进行渲染.
// MilkShape 3D 1.8.2 File Format Specification
//
//
// This specifcation is written in C style.
//
//
// The data structures are defined in the order as they appear in the .ms3d file.
//
//
//
//
//
//
// max values
//
#define MAX_VERTICES 65534
#define MAX_TRIANGLES 65534
#define MAX_GROUPS 255
#define MAX_MATERIALS 128
#define MAX_JOINTS 128
//
// flags
//
#define SELECTED 1
#define HIDDEN 2
#define SELECTED2 4
#define DIRTY 8
//
// types
//
#ifndef byte
typedef unsigned char byte;
#endif // byte
#ifndef word
typedef unsigned short word;
#endif // word
// force one byte alignment
#include
//
// First comes the header (sizeof(ms3d_header_t) == 14)
//
typedef struct
{
char id[10]; // always "MS3D000000"
int version; // 4
} ms3d_header_t;
//
// Then comes the number of vertices
//
word nNumVertices; // 2 bytes
//
// Then come nNumVertices times ms3d_vertex_t structs (sizeof(ms3d_vertex_t) == 15)
//
typedef struct
{
byte flags; // SELECTED | SELECTED2 | HIDDEN
float vertex[3]; //
char boneId; // -1 = no bone
byte referenceCount;
} ms3d_vertex_t;
//
// Then comes the number of triangles
//
word nNumTriangles; // 2 bytes
//
// Then come nNumTriangles times ms3d_triangle_t structs (sizeof(ms3d_triangle_t) == 70)
//
typedef struct
{
word flags; // SELECTED | SELECTED2 | HIDDEN
word vertexIndices[3]; //
float vertexNormals[3][3]; //
float s[3]; //
float t[3]; //
byte smoothingGroup; // 1 - 32
byte groupIndex; //
} ms3d_triangle_t;
//
// Then comes the number of groups
//
word nNumGroups; // 2 bytes
//
// Then come nNumGroups times groups (the sizeof a group is dynamic, because of triangleIndices is numtriangles long)
//
typedef struct
{
byte flags; // SELECTED | HIDDEN
char name[32]; //
word numtriangles; //
word triangleIndices[numtriangles]; // the groups group the triangles
char materialIndex; // -1 = no material
} ms3d_group_t;
//
// number of materials
//
word nNumMaterials; // 2 bytes
//
// Then come nNumMaterials times ms3d_material_t structs (sizeof(ms3d_material_t) == 361)
//
typedef struct
{
char name[32]; //
float ambient[4]; //
float diffuse[4]; //
float specular[4]; //
float emissive[4]; //
float shininess; // 0.0f - 128.0f
float transparency; // 0.0f - 1.0f
char mode; // 0, 1, 2 is unused now
char texture[128]; // texture.bmp
char alphamap[128]; // alpha.bmp
} ms3d_material_t;
//
// save some keyframer data
//
float fAnimationFPS; // 4 bytes
float fCurrentTime; // 4 bytes
int iTotalFrames; // 4 bytes
//
// number of joints
//
word nNumJoints; // 2 bytes
//
// Then come nNumJoints joints (the size of joints are dynamic, because each joint has a differnt count of keys
//
typedef struct // 16 bytes
{
float time; // time in seconds
float rotation[3]; // x, y, z angles
} ms3d_keyframe_rot_t;
typedef struct // 16 bytes
{
float time; // time in seconds
float position[3]; // local position
} ms3d_keyframe_pos_t;
typedef struct
{
byte flags; // SELECTED | DIRTY
char name[32]; //
char parentName[32]; //
float rotation[3]; // local reference matrix
float position[3];
word numKeyFramesRot; //
word numKeyFramesTrans; //
ms3d_keyframe_rot_t keyFramesRot[numKeyFramesRot]; // local animation matrices
ms3d_keyframe_pos_t keyFramesTrans[numKeyFramesTrans]; // local animation matrices
} ms3d_joint_t;
//
// Then comes the subVersion of the comments part, which is not available in older files
//
int subVersion; // subVersion is = 1, 4 bytes
// Then comes the numer of group comments
unsigned int nNumGroupComments; // 4 bytes
//
// Then come nNumGroupComments times group comments, which are dynamic, because the comment can be any length
//
typedef struct
{
int index; // index of group, material or joint
int commentLength; // length of comment (terminating '\0' is not saved), "MC" has comment length of 2 (not 3)
char comment[commentLength]; // comment
} ms3d_comment_t;
// Then comes the number of material comments
int nNumMaterialComments; // 4 bytes
//
// Then come nNumMaterialComments times material comments, which are dynamic, because the comment can be any length
//
// Then comes the number of joint comments
int nNumJointComments; // 4 bytes
//
// Then come nNumJointComments times joint comments, which are dynamic, because the comment can be any length
//
// Then comes the number of model comments, which is always 0 or 1
int nHasModelComment; // 4 bytes
//
// Then come nHasModelComment times model comments, which are dynamic, because the comment can be any length
//
// Then comes the subversion of the vertex extra information like bone weights, extra etc.
int subVersion; // subVersion is = 2, 4 bytes
// ms3d_vertex_ex_t for subVersion == 1
typedef struct
{
char boneIds[3]; // index of joint or -1, if -1, then that weight is ignored, since subVersion 1
byte weights[3]; // vertex weight ranging from 0 - 255, last weight is computed by 1.0 - sum(all weights), since subVersion 1
// weight[0] is the weight for boneId in ms3d_vertex_t
// weight[1] is the weight for boneIds[0]
// weight[2] is the weight for boneIds[1]
// 1.0f - weight[0] - weight[1] - weight[2] is the weight for boneIds[2]
} ms3d_vertex_ex_t;
// ms3d_vertex_ex_t for subVersion == 2
typedef struct
{
char boneIds[3]; // index of joint or -1, if -1, then that weight is ignored, since subVersion 1
byte weights[3]; // vertex weight ranging from 0 - 100, last weight is computed by 1.0 - sum(all weights), since subVersion 1
// weight[0] is the weight for boneId in ms3d_vertex_t
// weight[1] is the weight for boneIds[0]
// weight[2] is the weight for boneIds[1]
// 1.0f - weight[0] - weight[1] - weight[2] is the weight for boneIds[2]
unsigned int extra; // vertex extra, which can be used as color or anything else, since subVersion 2
} ms3d_vertex_ex_t;
// Then comes nNumVertices times ms3d_vertex_ex_t structs (sizeof(ms3d_vertex_ex_t) == 10)
// Then comes the subversion of the joint extra information like color etc.
int subVersion; // subVersion is = 2, 4 bytes
// ms3d_joint_ex_t for subVersion == 1
typedef struct
{
float color[3]; // joint color, since subVersion == 1
} ms3d_joint_ex_t;
// Then comes nNumJoints times ms3d_joint_ex_t structs (sizeof(ms3d_joint_ex_t) == 12)
// Then comes the subversion of the model extra information
int subVersion; // subVersion is = 1, 4 bytes
// ms3d_model_ex_t for subVersion == 1
typedef struct
{
float jointSize; // joint size, since subVersion == 1
int transparencyMode; // 0 = simple, 1 = depth buffered with alpha ref, 2 = depth sorted triangles, since subVersion == 1
float alphaRef; // alpha reference value for transparencyMode = 1, since subVersion == 1
} ms3d_model_ex_t;
#include
//
// Mesh Transformation:
//
// 0. Build the transformation matrices from the rotation and position
// 1. Multiply the vertices by the inverse of local reference matrix (lmatrix0)
// 2. then translate the result by (lmatrix0 * keyFramesTrans)
// 3. then multiply the result by (lmatrix0 * keyFramesRot)
//
// For normals skip step 2.
//
//
//
// NOTE: this file format may change in future versions!
//
//
// - Mete Ciragan
//
读取程序:
文件头:ms3dfile.H
#ifndef word
typedef unsigned short word;
#endif // word
typedef struct
{
char id[10]; // always "MS3D000000"
int version; // 4
} ms3d_header_t;
typedef struct
{
byte flags; // SELECTED | SELECTED2 | HIDDEN
float vertex[3]; //
char boneId; // -1 = no bone
byte referenceCount;
} ms3d_vertex_t;
typedef struct
{
word flags; // SELECTED | SELECTED2 | HIDDEN
word vertexIndices[3]; //
float vertexNormals[3][3]; //
float s[3]; //
float t[3]; //
byte smoothingGroup; // 1 - 32
byte groupIndex; //
} ms3d_triangle_t;
typedef struct
{
word edgeIndices[2];
} ms3d_edge_t;
typedef struct
{
byte flags; // SELECTED | HIDDEN
char name[32]; //
word numtriangles; //
word* triangleIndices; // the groups group the triangles
char materialIndex; // -1 = no material
} ms3d_group_t;
typedef struct
{
char name[32]; //
float ambient[4]; //
float diffuse[4]; //
float specular[4]; //
float emissive[4]; //
float shininess; // 0.0f - 128.0f
float transparency; // 0.0f - 1.0f
char mode; // 0, 1, 2 is unused now
char texture[128]; // texture.bmp
char alphamap[128]; // alpha.bmp
} ms3d_material_t;
typedef struct
{
float time; // time in seconds
float rotation[3]; // x, y, z angles
} ms3d_keyframe_rot_t;
typedef struct
{
float time; // time in seconds
float position[3]; // local position
} ms3d_keyframe_pos_t;
typedef struct
{
byte flags; // SELECTED | DIRTY
char name[32]; //
char parentName[32]; //
float rotation[3]; // local reference matrix
float position[3];
word numKeyFramesRot; //
word numKeyFramesTrans; //
ms3d_keyframe_rot_t* keyFramesRot; // local animation matrices
ms3d_keyframe_pos_t* keyFramesTrans; // local animation matrices
} ms3d_joint_t;
#include
class CMS3DFileI;
class CMS3DFile
{
public:
CMS3DFile();
virtual ~CMS3DFile();
public:
bool LoadFromFile(const char* lpszFileName);
void Clear();
int GetNumVertices();
void GetVertexAt(int nIndex, ms3d_vertex_t **ppVertex);
int GetNumTriangles();
void GetTriangleAt(int nIndex, ms3d_triangle_t **ppTriangle);
int GetNumEdges();
void GetEdgeAt(int nIndex, ms3d_edge_t **ppEdge);
int GetNumGroups();
void GetGroupAt(int nIndex, ms3d_group_t **ppGroup);
int GetNumMaterials();
void GetMaterialAt(int nIndex, ms3d_material_t **ppMaterial);
int GetNumJoints();
void GetJointAt(int nIndex, ms3d_joint_t **ppJoint);
int FindJointByName(const char* lpszName);
float GetAnimationFPS();
float _GetCurrentTime();
int GetTotalFrames();
private:
CMS3DFileI *_i;
private:
CMS3DFile(const CMS3DFile& rhs);
CMS3DFile& operator=(const CMS3DFile& rhs);
};
#endif // _MS3DFILE_H_
文件ms3dfile.CPP
#pragma warning(disable : 4786)
#include "MS3DFile.h"
#include
#include
#define MAKEDWORD(a, b) ((unsigned int)(((word)(a)) | ((word)((word)(b))) << 16))
class CMS3DFileI
{
public:
std::vector arrVertices;
std::vector arrTriangles;
std::vector arrEdges;
std::vector arrGroups;
std::vector arrMaterials;
float fAnimationFPS;
float fCurrentTime;
int iTotalFrames;
std::vector arrJoints;
public:
CMS3DFileI()
: fAnimationFPS(24.0f),
fCurrentTime(0.0f),
iTotalFrames(0)
{
}
};
CMS3DFile::CMS3DFile()
{
_i = new CMS3DFileI();
}
CMS3DFile::~CMS3DFile()
{
delete _i;
}
bool CMS3DFile::LoadFromFile(const char* lpszFileName)
{
FILE *fp = fopen(lpszFileName, "rb");
if (!fp)
return false;
size_t i;
ms3d_header_t header;
fread(&header, 1, sizeof(ms3d_header_t), fp);
if (strncmp(header.id, "MS3D000000", 10) != 0)
return false;
if (header.version != 4)
return false;
// vertices
word nNumVertices;
fread(&nNumVertices, 1, sizeof(word), fp);
_i->arrVertices.resize(nNumVertices);
fread(&_i->arrVertices[0], nNumVertices, sizeof(ms3d_vertex_t), fp);
// triangles
word nNumTriangles;
fread(&nNumTriangles, 1, sizeof(word), fp);
_i->arrTriangles.resize(nNumTriangles);
fread(&_i->arrTriangles[0], nNumTriangles, sizeof(ms3d_triangle_t), fp);
// edges
std::set setEdgePair;
for (i = 0; i < _i->arrTriangles.size(); i++)
{
word a, b;
a = _i->arrTriangles[i].vertexIndices[0];
b = _i->arrTriangles[i].vertexIndices[1];
if (a > b)
std::swap(a, b);
if (setEdgePair.find(MAKEDWORD(a, b)) == setEdgePair.end())
setEdgePair.insert(MAKEDWORD(a, b));
a = _i->arrTriangles[i].vertexIndices[1];
b = _i->arrTriangles[i].vertexIndices[2];
if (a > b)
std::swap(a, b);
if (setEdgePair.find(MAKEDWORD(a, b)) == setEdgePair.end())
setEdgePair.insert(MAKEDWORD(a, b));
a = _i->arrTriangles[i].vertexIndices[2];
b = _i->arrTriangles[i].vertexIndices[0];
if (a > b)
std::swap(a, b);
if (setEdgePair.find(MAKEDWORD(a, b)) == setEdgePair.end())
setEdgePair.insert(MAKEDWORD(a, b));
}
for(std::set::iterator it = setEdgePair.begin(); it != setEdgePair.end(); ++it)
{
unsigned int EdgePair = *it;
ms3d_edge_t Edge;
Edge.edgeIndices[0] = (word) EdgePair;
Edge.edgeIndices[1] = (word) ((EdgePair >> 16) & 0xFFFF);
_i->arrEdges.push_back(Edge);
}
// groups
word nNumGroups;
fread(&nNumGroups, 1, sizeof(word), fp);
_i->arrGroups.resize(nNumGroups);
for (i = 0; i < nNumGroups; i++)
{
fread(&_i->arrGroups[i].flags, 1, sizeof(byte), fp);
fread(&_i->arrGroups[i].name, 32, sizeof(char), fp);
fread(&_i->arrGroups[i].numtriangles, 1, sizeof(word), fp);
_i->arrGroups[i].triangleIndices = new word[_i->arrGroups[i].numtriangles];
fread(_i->arrGroups[i].triangleIndices, _i->arrGroups[i].numtriangles, sizeof(word), fp);
fread(&_i->arrGroups[i].materialIndex, 1, sizeof(char), fp);
}
// materials
word nNumMaterials;
fread(&nNumMaterials, 1, sizeof(word), fp);
_i->arrMaterials.resize(nNumMaterials);
fread(&_i->arrMaterials[0], nNumMaterials, sizeof(ms3d_material_t), fp);
fread(&_i->fAnimationFPS, 1, sizeof(float), fp);
fread(&_i->fCurrentTime, 1, sizeof(float), fp);
fread(&_i->iTotalFrames, 1, sizeof(int), fp);
// joints
word nNumJoints;
fread(&nNumJoints, 1, sizeof(word), fp);
_i->arrJoints.resize(nNumJoints);
for (i = 0; i < nNumJoints; i++)
{
fread(&_i->arrJoints[i].flags, 1, sizeof(byte), fp);
fread(&_i->arrJoints[i].name, 32, sizeof(char), fp);
fread(&_i->arrJoints[i].parentName, 32, sizeof(char), fp);
fread(&_i->arrJoints[i].rotation, 3, sizeof(float), fp);
fread(&_i->arrJoints[i].position, 3, sizeof(float), fp);
fread(&_i->arrJoints[i].numKeyFramesRot, 1, sizeof(word), fp);
fread(&_i->arrJoints[i].numKeyFramesTrans, 1, sizeof(word), fp);
_i->arrJoints[i].keyFramesRot = new ms3d_keyframe_rot_t[_i->arrJoints[i].numKeyFramesRot];
_i->arrJoints[i].keyFramesTrans = new ms3d_keyframe_pos_t[_i->arrJoints[i].numKeyFramesTrans];
fread(_i->arrJoints[i].keyFramesRot, _i->arrJoints[i].numKeyFramesRot, sizeof(ms3d_keyframe_rot_t), fp);
fread(_i->arrJoints[i].keyFramesTrans, _i->arrJoints[i].numKeyFramesTrans, sizeof(ms3d_keyframe_pos_t), fp);
}
fclose(fp);
return true;
}
void CMS3DFile::Clear()
{
_i->arrVertices.clear();
_i->arrTriangles.clear();
_i->arrEdges.clear();
_i->arrGroups.clear();
_i->arrMaterials.clear();
_i->arrJoints.clear();
}
int CMS3DFile::GetNumVertices()
{
return (int) _i->arrVertices.size();
}
void CMS3DFile::GetVertexAt(int nIndex, ms3d_vertex_t **ppVertex)
{
if (nIndex >= 0 && nIndex < (int) _i->arrVertices.size())
*ppVertex = &_i->arrVertices[nIndex];
}
int CMS3DFile::GetNumTriangles()
{
return (int) _i->arrTriangles.size();
}
void CMS3DFile::GetTriangleAt(int nIndex, ms3d_triangle_t **ppTriangle)
{
if (nIndex >= 0 && nIndex < (int) _i->arrTriangles.size())
*ppTriangle = &_i->arrTriangles[nIndex];
}
int CMS3DFile::GetNumEdges()
{
return (int) _i->arrEdges.size();
}
void CMS3DFile::GetEdgeAt(int nIndex, ms3d_edge_t **ppEdge)
{
if (nIndex >= 0 && nIndex < (int) _i->arrEdges.size())
*ppEdge = &_i->arrEdges[nIndex];
}
int CMS3DFile::GetNumGroups()
{
return (int) _i->arrGroups.size();
}
void CMS3DFile::GetGroupAt(int nIndex, ms3d_group_t **ppGroup)
{
if (nIndex >= 0 && nIndex < (int) _i->arrGroups.size())
*ppGroup = &_i->arrGroups[nIndex];
}
int CMS3DFile::GetNumMaterials()
{
return (int) _i->arrMaterials.size();
}
void CMS3DFile::GetMaterialAt(int nIndex, ms3d_material_t **ppMaterial)
{
if (nIndex >= 0 && nIndex < (int) _i->arrMaterials.size())
*ppMaterial = &_i->arrMaterials[nIndex];
}
int CMS3DFile::GetNumJoints()
{
return (int) _i->arrJoints.size();
}
void CMS3DFile::GetJointAt(int nIndex, ms3d_joint_t **ppJoint)
{
if (nIndex >= 0 && nIndex < (int) _i->arrJoints.size())
*ppJoint = &_i->arrJoints[nIndex];
}
int CMS3DFile::FindJointByName(const char* lpszName)
{
for (size_t i = 0; i < _i->arrJoints.size(); i++)
{
if (!strcmp(_i->arrJoints[i].name, lpszName))
return i;
}
return -1;
}
float CMS3DFile::GetAnimationFPS()
{
return _i->fAnimationFPS;
}
float CMS3DFile::_GetCurrentTime()
{
return _i->fCurrentTime;
}
int CMS3DFile::GetTotalFrames()
{
return _i->iTotalFrames;
}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/whoismickey/archive/2009/01/13/3767899.aspx
http://blog.csdn.net/guokeno1/archive/2006/10/11/1330764.aspx