2014年8月26日星期二(DEMO8-9加载COB模型)
来源:互联网 发布:淘宝买家具哪个品牌好 编辑:程序博客网 时间:2024/05/22 23:14
步骤
1读取文件开头第一行
2读取名称、中心位置、X轴、Y轴和Z轴,用来定义局部矩阵
3读取局部坐标到世界坐标的变换矩阵
4,读取World Vertices行,并按照x,y,z顺序读取顶点列表
5,读取Texture Vertices行,然后读取每个顶点的<u,v>纹理坐标
6,读取Face行,然后读取每个多边形面(这里用三角形面),格式为 Face verts 3 flags 标记 mat 材质号,材质号说明了该面的材质。接下来读取多边形面本身,顶点索引格式为<该面三角形顶点的索引,纹理坐标>
7,加载材质,有alpha透明度,反射系数和着色方法。
Cob模型多边形有2种,一个是普通彩色多边形(即使用固定、恒定、Gouraud或Phong着色),Shader colors : color
Shader name:”Plain color”( plain )
另外一个就是贴纹理的多边形,
Shader colors:texture map
Shader name:”xxxxxx”(xxxxxx)
其中,xxxxxx代表设置的着色系统,如”constant”,”matte”,”plastic”,”phong”,”texture map”
先看看有什么区别,
首先与3DSMAX相比,多了个纹理。
并保留了局部矩阵和世界矩阵。
开始模式也变了:
if(parser.Pattern_Match(parser.buffer,"['Name'][s>0]" ) )
最明显的还是多了局部坐标和世界坐标
//计算临时变量
VECTOR4D temp_vector;
//现在使用局部和世界变换的COB格式解码
if( vertex_flags &VERTEX_FLAGS_TRANSFORM_LOCAL )
{
math2.Mat_Mul_VECTOR4D_4X4( &obj->vlist_local[vertex], &mat_local, &temp_vector );
math2.VECTOR4D_COPY( &obj->vlist_local[vertex]. &temp_vector );
}
if( vertex_flags &VERTEX_FLAGS_TRANSFORM_LOCAL_WORLD )
{
math2.Mat_Mul_VECTOR4D_4X4( &obj->vlist_local[vertex], &mat_world, &temp_vector );
math2.VECTOR4D_COPY( &obj->vlist_local[vertex]. &temp_vector );
}
现在继续进行,cob模型加入了材质
MATV1 materials[MAX_MATERIALS];
目前还没有加上MATV1的定义,回过头来看8.2.2定义材质1节,材质的提出,是替代以前用来记录多边形属性字段信息,也就是说,以后不在多边形中存储这些数据了,而是定义大量的材质。引擎根据多边形中的存储的ID或指针来找到相应的材质,并根据该材质而不是多边形的内部信息来渲染多边形。
再添加个材质类。
#pragmaonce
#include"common.h"
//材质属性
#defineMATV1_ATTR_2SIDED 0x0001
#defineMATV1_ATTR_TRANSPARENT 0x0002
#defineMATV1_ATTR_8BITCOLOR 0x0004
#defineMATV1_ATTR_RGB16 0x0008
#defineMATV1_ATTR_RGB24 0x0010
#defineMATV1_ATTR_SHADE_MODE_CONSTANT 0x0020
#defineMATV1_ATTR_SHADE_MODE_EMISSIVE 0x0020 //别名
#defineMATV1_ATTR_SHADE_MODE_FLAT 0x0040
#defineMATV1_ATTR_SHADE_MODE_GOURAUD 0x0080
#defineMATV1_ATTR_SHADE_MODE_FASTPHONG 0x0100
#defineMATV1_ATTR_SHADE_MODE_TEXTURE 0x0200
//材质状态
#define MATV1_STATE_ACTIVE 0x0001
#define MAX_MATERIALS 256
//材质数据结构
typedefstruct MATV1_TYP
{
int state; //材质的状态
int id; //材质id,指向材质数组的索引
char name[64]; //材质名称
int attr; //属性,着色模式、着色方法、环境、纹理以及其他特殊标记
RGBAV1 color; //材质颜色
float ka,kd, ks, power; //对环境光、散射光和镜面反射光的反射系数和镜面反射指数
RGBAV1 ra,rd, rs; //预先计算得到的颜色和反射系数的积
char texture_file[80]; //包含纹理的文件的位置
BITMAP_IMAGE texture; //纹理图
int iaux1, iaux2;
float faux1, faux2;
void * ptr;
}MATV1, *MATV1_PTR;
classDDRAW_Material
{
public:
DDRAW_Material(void);
~DDRAW_Material(void);
};
突然发现,有个变量,就是材质数num_materials没有赋给初值
if( parser.Pattern_Match(parser.buffer,"['rgb'][f][f][f]" ) )
{
materials[material_index +num_materials].color.r = ( int ) ( parser.pfloats[0] * 255 + 0.5 );
materials[material_index +num_materials].color.g = ( int ) ( parser.pfloats[1] * 255 + 0.5 );
materials[material_index +num_materials].color.b = ( int ) ( parser.pfloats[2] * 255 + 0.5 );
break;
}
这样,先在函数中加上个变量
int num_materials = 0;
具体核心代码如下:
intddraw_liushuixian::Load_OBJECT4DV1_COB(ddraw_math math2,OBJECT4DV1_PTR obj,char * filename,VECTOR4D_PTR scale,VECTOR4D_PTR pos,VECTOR4D_PTR rot,int vertex_flags)
{
CPARSERV1 parser;
char seps[16];
char token_buffer[256]; //缓冲区
char * token; //指向要分析的物体数据文本的指针
int r,g, b;
int num_materials = 0;
int material_index = 0;
VERTEX2DF texture_vertices[1024]; //纹理区域
int num_texture_vertices = 0;
MATRIX4X4 mat_local,mat_world; //局部坐标系和世界坐标系
MATV1 materials[MAX_MATERIALS];
//矩阵归一化
math2.Mat_IDENTITY_4X4( &mat_local );
math2.Mat_IDENTITY_4X4( &mat_world );
//先找到物体描述符
//第一步清空和初始化OBJ
memset( obj, 0,sizeof(OBJECT4DV1) );
//将物体状态设置为可见和活动的
obj->state = OBJECT4DV1_STATE_ACTIVE | OBJECT4DV1_STATE_VISIBLE;
if ( pos )
{
//设置物体的位置
obj->world_pos.x = pos->x;
obj->world_pos.y = pos->y;
obj->world_pos.z = pos->z;
obj->world_pos.w = pos->w;
}
else
{
//设置物体的位置
obj->world_pos.x = 0;
obj->world_pos.y = 0;
obj->world_pos.z = 0;
obj->world_pos.w = 1;
}
//第步,读取文件
parser.Open(filename );
//第步,读取物体描述符
while ( 1 )
{
parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS );
//检测模式
if( parser.Pattern_Match(parser.buffer,"['Name'][s>0]" ) )
{
strcpy( obj->name,parser.pstrings[1] );
break;
}
}
//第步,得到局部变换和世界变换并保存
while( 1 )
{
//下一行,寻找中心点,
parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS );
if( parser.Pattern_Match(parser.buffer,"['center'][f][f][f]" ) )
{
mat_local.M[3][0] = -parser.pfloats[0]; //中心点X
mat_local.M[3][1] = -parser.pfloats[1]; //中心点Y
mat_local.M[3][2] = -parser.pfloats[2]; //中心点Z
//寻找x轴平移矩阵
parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS );
parser.Pattern_Match(parser.buffer,"['x']['axis'][f][f][f]" );
mat_local.M[0][0] = parser.pfloats[0]; //rxx
mat_local.M[1][0] = parser.pfloats[1]; //rxy
mat_local.M[2][0] = parser.pfloats[2]; //rxz
//寻找y轴平移矩阵
parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS );
parser.Pattern_Match(parser.buffer,"['y']['axis'][f][f][f]" );
mat_local.M[0][1] = parser.pfloats[0]; //ryx
mat_local.M[1][1] = parser.pfloats[1]; //ryy
mat_local.M[2][1] = parser.pfloats[2]; //ryz
//寻找z轴平移矩阵
parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS );
parser.Pattern_Match(parser.buffer,"['z']['axis'][f][f][f]" );
mat_local.M[0][2] = parser.pfloats[0]; //rzx
mat_local.M[1][2] = parser.pfloats[1]; //rzy
mat_local.M[2][2] = parser.pfloats[2]; //rzz
break;
}
}
//现在是"Transform"字段
while( 1 )
{
parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS );
if( parser.Pattern_Match(parser.buffer,"['Transform']" ) )
{
//寻找x轴平移矩阵
parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS );
parser.Pattern_Match(parser.buffer,"[f][f][f]" );
mat_world.M[0][0] = parser.pfloats[0]; //rxx
mat_world.M[1][0] = parser.pfloats[1]; //rxy
mat_world.M[2][0] = parser.pfloats[2]; //rxz
//寻找y轴平移矩阵
parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS );
parser.Pattern_Match(parser.buffer,"[f][f][f]" );
mat_world.M[0][1] = parser.pfloats[0]; //ryx
mat_world.M[1][1] = parser.pfloats[1]; //ryy
mat_world.M[2][1] = parser.pfloats[2]; //ryz
//寻找z轴平移矩阵
parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS );
parser.Pattern_Match(parser.buffer,"[f][f][f]" );
mat_world.M[0][2] = parser.pfloats[0]; //rzx
mat_world.M[1][2] = parser.pfloats[1]; //rzy
mat_world.M[2][2] = parser.pfloats[2]; //rzz
break;
}
}
//第步,得到我图的顶点和边数目
while( 1 )
{
parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS );
//下一行,寻找Tri-Mesh,Vertices,提取顶点数目
if( parser.Pattern_Match(parser.buffer,"['World']['Vertices'][i]" ) )
{
obj->num_vertices = parser.pints[0];
break;
}
}
//第步:加载顶点列表
//现在读取顶点列表,格式"Vertex:d X:d.d Y:d.d Z:d.d"
for( int vertex = 0; vertex < obj->num_vertices; vertex ++ )
{
while( 1 )
{
parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS );
if( parser.Pattern_Match(parser.buffer,"[f][f][f]" ) )
{
obj->vlist_local[vertex].x = parser.pfloats[0];
obj->vlist_local[vertex].y = parser.pfloats[1];
obj->vlist_local[vertex].z = parser.pfloats[2];
obj->vlist_local[vertex].w = 1;
//计算临时变量
VECTOR4D temp_vector;
//现在使用局部和世界变换的COB格式解码
if( vertex_flags &VERTEX_FLAGS_TRANSFORM_LOCAL )
{
math2.Mat_Mul_VECTOR4D_4X4( &obj->vlist_local[vertex], &mat_local, &temp_vector );
math2.VECTOR4D_COPY( &obj->vlist_local[vertex], &temp_vector );
}
if( vertex_flags &VERTEX_FLAGS_TRANSFORM_LOCAL_WORLD )
{
math2.Mat_Mul_VECTOR4D_4X4( &obj->vlist_local[vertex], &mat_world, &temp_vector );
math2.VECTOR4D_COPY( &obj->vlist_local[vertex], &temp_vector );
}
//根据标志位来进行相应的旋转
float temp_f;
if( vertex_flags &VERTEX_FLAGS_INVERT_X )
obj->vlist_local[vertex].x = - obj->vlist_local[vertex].x;
if( vertex_flags &VERTEX_FLAGS_INVERT_Y )
obj->vlist_local[vertex].y = - obj->vlist_local[vertex].y;
if( vertex_flags &VERTEX_FLAGS_INVERT_Z )
obj->vlist_local[vertex].z = - obj->vlist_local[vertex].z;
if( vertex_flags &VERTEX_FLAGS_SWAP_YZ )
SWAP( obj->vlist_local[vertex].y,obj->vlist_local[vertex].z,temp_f );
if( vertex_flags &VERTEX_FLAGS_SWAP_XZ )
SWAP( obj->vlist_local[vertex].x,obj->vlist_local[vertex].z,temp_f );
if( vertex_flags &VERTEX_FLAGS_SWAP_XY )
SWAP( obj->vlist_local[vertex].x,obj->vlist_local[vertex].y,temp_f );
//放缩
if( scale )
{
obj->vlist_local[vertex].x *= scale->x;
obj->vlist_local[vertex].y *= scale->y;
obj->vlist_local[vertex].z *= scale->z;
}
break;
}
}
}
//计算平均和最大半径
Compute_OBJECT4DV1_RADIUS( obj );
//8,得到纹理顶点数目
while( 1 )
{
parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS );
//下一行,寻找Tri-Mesh,Vertices,提取顶点数目
if( parser.Pattern_Match(parser.buffer,"['Texture']['Vertices'][i]" ) )
{
num_texture_vertices = parser.pints[0];
break;
}
}
//第步:加载纹理UV列表
//现在读取顶点列表,格式"d.d.d.d"
for( int vertex = 0; vertex < obj->num_vertices; vertex ++ )
{
while( 1 )
{
parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS );
if( parser.Pattern_Match(parser.buffer,"[f][f]" ) )
{
texture_vertices[vertex].x = parser.pfloats[0];
texture_vertices[vertex].y = parser.pfloats[1];
break;
}
}
}
int poly_material[OBJECT4DV1_MAX_POLYS];
int material_index_referenced[MAX_MATERIALS];
memset( material_index_referenced, 0,sizeof( material_index_referenced ) );
//第步,加载面
while( 1 )
{
if( ! parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS ) )
{
return ( 0 );
}
if( parser.Pattern_Match(parser.buffer,"['Faces'][i]" ) )
{
obj->num_polys = parser.pints[0];
break;
}
}
int poly_surface_desc = 0;
int poly_num_verts = 0;
int num_materials_object = 0;
for( int poly = 0; poly < obj->num_polys; poly++ )
{
while ( 1 )
{
if( ! parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS ) )
{
return ( 0 );
}
if( parser.Pattern_Match(parser.buffer,"['Face']['verts'][i]['flags'][i]['mat'][i]" ) )
{
poly_material[poly] = parser.pints[2];
//
if( material_index_referenced[poly_material[poly]] == 0 )
{
material_index_referenced[poly_material[poly]] = 1;
num_materials_object++;
}
if( parser.pints[0] != 3 )
{
return 0;
}
parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS );
parser.ReplaceChars(parser.buffer,parser.buffer,",<>",' ' );
parser.Pattern_Match(parser.buffer,"[i][i][i][i][i][i]" );
if( vertex_flags &VERTEX_FLAGS_INVERT_WINDING_ORDER )
{
poly_num_verts = 3;
obj->plist[poly].vert[0] = parser.pints[4];
obj->plist[poly].vert[1] = parser.pints[2];
obj->plist[poly].vert[2] = parser.pints[0];
}
else
{
poly_num_verts = 3;
obj->plist[poly].vert[0] = parser.pints[0];
obj->plist[poly].vert[1] = parser.pints[2];
obj->plist[poly].vert[2] = parser.pints[4];
}
obj->plist[poly].vlist = obj->vlist_local;
obj->plist[poly].state = POLY4DV1_STATE_ACTIVE;
break;
}
}
}
//现在寻找材质
for( int curr_material = 0; curr_material < num_materials_object; curr_material++ )
{
// 寻找材质头"mat# ddd
while ( 1 )
{
if( ! parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS ) )
{
return ( 0 );
}
if( parser.Pattern_Match(parser.buffer,"['mat#'][i]" ) )
{
material_index = parser.pints[0];
//
while( 1 )
{
if( ! parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS ) )
{
return ( 0 );
}
parser.ReplaceChars(parser.buffer,parser.buffer,",", ' ', 1 );
if( parser.Pattern_Match(parser.buffer,"['rgb'][f][f][f]" ) )
{
materials[material_index +num_materials].color.r = ( int ) ( parser.pfloats[0] * 255 + 0.5 );
materials[material_index +num_materials].color.g = ( int ) ( parser.pfloats[1] * 255 + 0.5 );
materials[material_index +num_materials].color.b = ( int ) ( parser.pfloats[2] * 255 + 0.5 );
break;
}
}
while( 1 )
{
parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS );
if( parser.Pattern_Match(parser.buffer,"['alpha'][f]['ka'][f]['ks'][f]['exp'][f]" ) )
{
materials[material_index +num_materials].color.a = ( UCHAR ) ( parser.pfloats[0] * 255 + 0.5 );
materials[material_index +num_materials].ka = parser.pfloats[1];
materials[material_index +num_materials].kd = 1;
materials[material_index +num_materials].ks = parser.pfloats[2];
materials[material_index +num_materials].power = parser.pfloats[3];
//预先计算材质的反射系数
for( int rgb_index = 0; rgb_index < 3; rgb_index ++ )
{
//环境光反射系统
materials[material_index +num_materials].ra.rgba_M[rgb_index] =
( ( UCHAR ) ( materials[material_index + num_materials].ka *
( float )materials[material_index +num_materials].color.rgba_M[rgb_index] + 0.5 ) );
//散射光
materials[material_index +num_materials].rd.rgba_M[rgb_index] =
( ( UCHAR ) ( materials[material_index + num_materials].kd *
( float )materials[material_index +num_materials].color.rgba_M[rgb_index] + 0.5 ) );
//镜面光反射系数
materials[material_index +num_materials].rs.rgba_M[rgb_index] =
(( UCHAR ) ( materials[material_index + num_materials].ks *
( float )materials[material_index +num_materials].color.rgba_M[rgb_index] + 0.5 ) );
}
break;
}
}
while( 1 )
{
parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS );
if( parser.Pattern_Match(parser.buffer,"['Shader']['class:']['color']" ) )
{
break;
}
}
while( 1 )
{
parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS );
parser.ReplaceChars(parser.buffer,parser.buffer,"\"",' ', 1 );
if( parser.Pattern_Match(parser.buffer,"['Shader']['name:']['plain']['color']" ) )
{
break;
}
if( parser.Pattern_Match(parser.buffer,"['Shader']['name:']['texture']['map']" ) )
{
SET_BIT( materials[material_index +num_materials].attr,MATV1_ATTR_SHADE_MODE_TEXTURE );
while( 1 )
{
parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS );
parser.ReplaceChars(parser.buffer,parser.buffer,"\"",' ', 1 );
if( parser.Pattern_Match(parser.buffer,"['file']['name:']['string'][s>0]" ) )
{
parser.ReplaceChars(parser.pstrings[3],parser.pstrings[3],"\\", '/', 1 );
strcpy( materials[material_index +num_materials].texture_file,parser.pstrings[3] );
break;
}
}
break;
}
}
while( 1 )
{
parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS );
if( parser.Pattern_Match(parser.buffer,"['Shader']['class:']['reflectance']" ) )
{
break;
}
}
while( 1 )
{
parser.Getline(PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS );
parser.ReplaceChars(parser.buffer,parser.buffer,"\"", ' ', 1 );
if( parser.Pattern_Match(parser.buffer,"['Shader']['name:'][s>0]" ) )
{
if( strcmp(parser.pstrings[2],"constant" ) == 0 )
{
SET_BIT( materials[material_index +num_materials].attr,MATV1_ATTR_SHADE_MODE_CONSTANT );
}
else
if( strcmp(parser.pstrings[2],"matte" ) == 0 )
{
SET_BIT( materials[material_index +num_materials].attr,MATV1_ATTR_SHADE_MODE_FLAT );
}
else
if( strcmp(parser.pstrings[2],"plastic" ) == 0 )
{
SET_BIT( materials[material_index +num_materials].attr,MATV1_ATTR_SHADE_MODE_GOURAUD );
}
else
if( strcmp(parser.pstrings[2],"phong" ) == 0 )
{
SET_BIT( materials[material_index +num_materials].attr,MATV1_ATTR_SHADE_MODE_FASTPHONG );
}
else
{
SET_BIT( materials[material_index +num_materials].attr,MATV1_ATTR_SHADE_MODE_FLAT );
}
break;
}
}
break;
}
}
}
for( int curr_poly = 0; curr_poly < obj->num_polys; curr_poly++ )
{
poly_material[curr_poly] = poly_material[curr_poly] +num_materials;
SET_BIT( obj->plist[curr_poly].attr,POLY4DV1_ATTR_RGB16 );
obj->plist[curr_poly].color= _RGB16BIT565( materials[poly_material[curr_poly]].color.r,
materials[poly_material[curr_poly]].color.g,
materials[poly_material[curr_poly]].color.b );
if( materials[poly_material[curr_poly]].attr &MATV1_ATTR_SHADE_MODE_CONSTANT )
{
SET_BIT( obj->plist[curr_poly].attr,POLY4DV1_ATTR_SHADE_MODE_CONSTANT );
}
else
if( materials[poly_material[curr_poly]].attr &MATV1_ATTR_SHADE_MODE_FLAT )
{
SET_BIT( obj->plist[curr_poly].attr,POLY4DV1_ATTR_SHADE_MODE_FLAT );
}
else
if( materials[poly_material[curr_poly]].attr &MATV1_ATTR_SHADE_MODE_GOURAUD )
{
SET_BIT( obj->plist[curr_poly].attr,POLY4DV1_ATTR_SHADE_MODE_GOURAUD );
}
else
if( materials[poly_material[curr_poly]].attr &MATV1_ATTR_SHADE_MODE_FASTPHONG )
{
SET_BIT( obj->plist[curr_poly].attr,POLY4DV1_ATTR_SHADE_MODE_FASTPHONG );
}
else
{
SET_BIT( obj->plist[curr_poly].attr,POLY4DV1_ATTR_SHADE_MODE_GOURAUD );
}
if( materials[poly_material[curr_poly]].attr &MATV1_ATTR_SHADE_MODE_TEXTURE )
{
SET_BIT( obj->plist[curr_poly].attr,POLY4DV1_ATTR_SHADE_MODE_TEXTURE );
}
}
num_materials += num_materials_object;
return ( 1 );
}
- 2014年8月26日星期二(DEMO8-9加载COB模型)
- 2014年7月8日星期二(DEMO8-8加载3DSMAX ASCII格式模型.ASC)
- 2014年2月25日星期二(DEMO8-2,光照图调制)
- 2014年7月7日星期一(DEMO8-7使用新的模型格式)
- 2014年1月14日星期二(DEMO7-2,加载3D线框立方体物体模型)
- 2006年9月26日星期二
- 2014年3月9日星期日(DEMO8-6,画家算法)
- 2014年3月8日星期六(DEMO8-5恒定着色)
- 2013年11月26日星期二(四元数)
- 2014年2月22日星期六(DEMO8-1,颜色与放缩系数相乘)
- 2014年3月3日星期一(DEMO8-3,ALPHA混合)
- 2014年3月7日星期五(DEMO8-4,实体三角形着色)
- 2013年9月11日星期三(demo8-7,三角形)
- 2013年9月10日星期二(DEMO8_6矩阵)
- 2017年8月8日 星期二
- 2004年9月28日星期二
- 2006年9月12日星期二
- 2006年9月19日星期二
- 2014年7月7日星期一(DEMO8-7使用新的模型格式)
- 转载:Why does MYSQL higher LIMIT offset slow the query down?
- 2014年7月8日星期二(DEMO8-8加载3DSMAX ASCII格式模型.ASC)
- poj3253 Fence Repair(哈弗曼)
- win7下VC++6.0打开多个工作区间
- 2014年8月26日星期二(DEMO8-9加载COB模型)
- 机器视觉专题
- [LeetCode] Balanced Binary Tree 平衡二叉树
- 9-2加上光照计算的GOURAUD shader多边形)
- 去学隐身术吧
- 前端开发神器 Emmet 介绍
- 使用 Emmet 生成 HTML 的语法详解
- 使用 Emmet 提高编写 CSS 的效率
- Emmet 常用的高级功能