[lib3ds] 开源3ds文件解析库(一):基础
3ds 文件是 3D Max 的一种二进制存储格式,用来存储 3D 模型场景。关于这种格式官方的资料很少,从二进制角度解析文件很困难,幸好有个开源的项目lib3ds已经提供了解析的库。
- 用 ANSI-C 编写
- 支持的框架:
- GNU build tools (autoconf, automake, libtool)
- UNIX
- Mac OS X
- Microsoft Visual C++ 8.0
- 支持小端和大端字节序的 cpu
- 载入和保存:
- Atmosphere settings
- 背景设置 (Background settings)
- 阴影贴图设置 (Shadow map settings)
- 视口设置 (Viewport setting)
- 材质 (Materials)
- 摄像机 (Cameras)
- 灯光 (Lights)
- 网格 (Meshes)
- 层次结构 (Hierarchy)
- 关键祯 (Keyframes)
- 计算动画(关键祯)数据
- 简单容易操作的数据结构
- 矢量数学模块
- 四元数数学模块
- 矩阵数学模块
- 与 OpenGL 无缝集成
(1) 坐标系
在 3ds 文件中使用的坐标系是左手坐标系,从左到右,x 递增;从下到上,z 递增;从近到远,y 递增。
在 lib3ds 库中,经过解析,把 3ds 文件中的数据转换成了 OpenGL 采用的右手坐标系,从左到右,x 递增,从下到上 y 递增,从远到近,z 递增。

(2) 数学模块
// 矢量数学函数
extern LIB3DSAPI void lib3ds_vector_make(
float c[3],
float x,
float y,
float z);
/**
Sets all components of a vector to zero.
\param c
The Pointer to the vector.
*/
extern LIB3DSAPI void lib3ds_vector_zero(
float c[3]);
/**
Copies all components of a vector to another vector.
\param dst
[out] The destination vector.
\param src
[in] The source vector.
*/
extern LIB3DSAPI void lib3ds_vector_copy(
float dst[3],
float src[3]);
/**
Negates all components of a vector.
\param c
The Pointer to the vector.
*/
extern LIB3DSAPI void lib3ds_vector_neg(
float c[3]);
extern LIB3DSAPI void lib3ds_vector_make(float c[3], float x, float y, float z);
extern LIB3DSAPI void lib3ds_vector_zero(float c[3]);
extern LIB3DSAPI void lib3ds_vector_add(float c[3], float a[3], float b[3]);
extern LIB3DSAPI void lib3ds_vector_sub(float c[3], float a[3], float b[3]);
extern LIB3DSAPI void lib3ds_vector_scalar_mul(float c[3], float a[3], float k);
extern LIB3DSAPI void lib3ds_vector_cross(float c[3], float a[3], float b[3]);
extern LIB3DSAPI float lib3ds_vector_dot(float a[3], float b[3]);
extern LIB3DSAPI float lib3ds_vector_length(float c[3]);
extern LIB3DSAPI void lib3ds_vector_normalize(float c[3]);
extern LIB3DSAPI void lib3ds_vector_normal(float n[3], float a[3], float b[3], float c[3]);
extern LIB3DSAPI void lib3ds_vector_min(float c[3], float a[3]);
extern LIB3DSAPI void lib3ds_vector_max(float c[3], float a[3]);
extern LIB3DSAPI void lib3ds_vector_transform(float c[3], float m[4][4], float a[3]);
extern LIB3DSAPI void lib3ds_quat_identity(float c[4]);
extern LIB3DSAPI void lib3ds_quat_copy(float dest[4], float src[4]);
extern LIB3DSAPI void lib3ds_quat_axis_angle(float c[4], float axis[3], float angle);
extern LIB3DSAPI void lib3ds_quat_neg(float c[4]);
extern LIB3DSAPI void lib3ds_quat_cnj(float c[4]);
extern LIB3DSAPI void lib3ds_quat_mul(float c[4], float a[4], float b[4]);
extern LIB3DSAPI void lib3ds_quat_scalar(float c[4], float k);
extern LIB3DSAPI void lib3ds_quat_normalize(float c[4]);
extern LIB3DSAPI void lib3ds_quat_inv(float c[4]);
extern LIB3DSAPI float lib3ds_quat_dot(float a[4], float b[4]);
extern LIB3DSAPI float lib3ds_quat_norm(float c[4]);
extern LIB3DSAPI void lib3ds_quat_ln(float c[4]);
extern LIB3DSAPI void lib3ds_quat_ln_dif(float c[4], float a[4], float b[4]);
extern LIB3DSAPI void lib3ds_quat_exp(float c[4]);
extern LIB3DSAPI void lib3ds_quat_slerp(float c[4], float a[4], float b[4], float t);
extern LIB3DSAPI void lib3ds_quat_squad(float c[4], float a[4], float p[4], float q[4], float b[4], float t);
extern LIB3DSAPI void lib3ds_quat_tangent(float c[4], float p[4], float q[4], float n[4]);
// 四元数数学函数
extern LIB3DSAPI void lib3ds_quat_identity(float c[4]);
extern LIB3DSAPI void lib3ds_quat_copy(float dest[4], float src[4]);
extern LIB3DSAPI void lib3ds_quat_axis_angle(float c[4], float axis[3], float angle);
extern LIB3DSAPI void lib3ds_quat_neg(float c[4]);
extern LIB3DSAPI void lib3ds_quat_cnj(float c[4]);
extern LIB3DSAPI void lib3ds_quat_mul(float c[4], float a[4], float b[4]);
extern LIB3DSAPI void lib3ds_quat_scalar(float c[4], float k);
extern LIB3DSAPI void lib3ds_quat_normalize(float c[4]);
extern LIB3DSAPI void lib3ds_quat_inv(float c[4]);
extern LIB3DSAPI float lib3ds_quat_dot(float a[4], float b[4]);
extern LIB3DSAPI float lib3ds_quat_norm(float c[4]);
extern LIB3DSAPI void lib3ds_quat_ln(float c[4]);
extern LIB3DSAPI void lib3ds_quat_ln_dif(float c[4], float a[4], float b[4]);
extern LIB3DSAPI void lib3ds_quat_exp(float c[4]);
extern LIB3DSAPI void lib3ds_quat_slerp(float c[4], float a[4], float b[4], float t);
extern LIB3DSAPI void lib3ds_quat_squad(float c[4], float a[4], float p[4], float q[4], float b[4], float t);
extern LIB3DSAPI void lib3ds_quat_tangent(float c[4], float p[4], float q[4], float n[4]);
// 矩阵数学函数
extern LIB3DSAPI void lib3ds_matrix_zero(float m[4][4]);
extern LIB3DSAPI void lib3ds_matrix_identity(float m[4][4]);
extern LIB3DSAPI void lib3ds_matrix_copy(float dest[4][4], float src[4][4]);
extern LIB3DSAPI void lib3ds_matrix_neg(float m[4][4]);
extern LIB3DSAPI void lib3ds_matrix_transpose(float m[4][4]);
extern LIB3DSAPI void lib3ds_matrix_add(float m[4][4], float a[4][4], float b[4][4]);
extern LIB3DSAPI void lib3ds_matrix_sub(float m[4][4], float a[4][4], float b[4][4]);
extern LIB3DSAPI void lib3ds_matrix_mult(float m[4][4], float a[4][4], float b[4][4]);
extern LIB3DSAPI void lib3ds_matrix_scalar(float m[4][4], float k);
extern LIB3DSAPI float lib3ds_matrix_det(float m[4][4]);
extern LIB3DSAPI int lib3ds_matrix_inv(float m[4][4]);
extern LIB3DSAPI void lib3ds_matrix_translate(float m[4][4], float x, float y, float z);
extern LIB3DSAPI void lib3ds_matrix_scale(float m[4][4], float x, float y, float z);
extern LIB3DSAPI void lib3ds_matrix_rotate_quat(float m[4][4], float q[4]);
extern LIB3DSAPI void lib3ds_matrix_rotate(float m[4][4], float angle, float ax, float ay, float az);
extern LIB3DSAPI void lib3ds_matrix_camera(float m[4][4], float pos[3], float tgt[3], float roll);
关于 3D 数学基础知识,大家可以参考下这本书—《3D 数学基础:图形与游戏开发》。
(3) 3DS 文件数据结构
// Lib3dsFile
typedef struct Lib3dsFile {
unsigned user_id;
void* user_ptr;
unsigned mesh_version;
unsigned keyf_revision;
char name[12+1];
float master_scale;
float construction_plane[3];
float ambient[3];
Lib3dsShadow shadow;
Lib3dsBackground background;
Lib3dsAtmosphere atmosphere;
Lib3dsViewport viewport;
Lib3dsViewport viewport_keyf;
int frames;
int segment_from;
int segment_to;
int current_frame;
int materials_size;
int nmaterials;
Lib3dsMaterial** materials;
int cameras_size;
int ncameras;
Lib3dsCamera** cameras;
int lights_size;
int nlights;
Lib3dsLight** lights;
int meshes_size;
int nmeshes;
Lib3dsMesh** meshes;
Lib3dsNode* nodes;
} Lib3dsFile;
extern LIB3DSAPI Lib3dsFile* lib3ds_file_open(const char *filename);
extern LIB3DSAPI int lib3ds_file_save(Lib3dsFile *file, const char *filename);
extern LIB3DSAPI Lib3dsFile* lib3ds_file_new();
extern LIB3DSAPI void lib3ds_file_free(Lib3dsFile *file);
通过 lib3ds_file_open 函数打开 3ds 文件后,Lib3dsFile 结构包含了解析完成的所有 3d 数据。