DirectX9:基础篇 第二章 建立3D场景的几何描述

一.简介

d3dx9mesh.h有关网格模型

 

二.灵活的顶点格式

Direct3D中的顶点不只有空间位置属性,还可以有颜色 法线向量属性等,所以可以自定义一个顶点结构

 

 

 

1.使用

struct ColorVertex{
    float _x,_y,_z;          //位置
    DWORD _color;      //颜色
};

#define FVF_COLOR(D3DFVF_XYZ | D3DFVF_DIFFUSE)  //包含位置属性和漫反射颜色属

 

struct NormaolTexVertex{
    float _x,_y,_z;           //位置
    float _nx,_ny,_nz;     //法线
    float _u,_v;               //纹理坐标
};

#define FVF_NORMAL_TEX(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1)

 

//灵活的顶点格式
struct Vertex{
 
    Vertex(){}
    Vertex(float x,float y,float z){
        _x=x;
        _y=y;
        _z=z;
    }
    float _x,_y,_z;
    static const DWORD FVF;
};
const DWORD Vertex::FVF=D3DFVF_XYZ;
 
bool Setup(){
    
    //根据灵活的顶点格式来创建顶点缓存
    Device->CreateVertexBuffer(
        3*sizeof(Vertex),
        D3DUSAGE_WRITEONLY,
        Vertex::FVF,
        D3DPOOL_MANAGED,
        &Triangle,
        0);
    
}
 
bool Display(float timeDelta){
    
    //根据灵活的顶点格式来绑定模型数据
    Device->SetFVF(Vertex::FVF);
}

 

2.FVF宏定义

#define D3DFVF_RESERVED0        0x001
#define D3DFVF_POSITION_MASK    0x400E
#define D3DFVF_XYZ              0x002        //包含三维坐标
#define D3DFVF_XYZRHW           0x004
#define D3DFVF_XYZB1            0x006
#define D3DFVF_XYZB2            0x008
#define D3DFVF_XYZB3            0x00a
#define D3DFVF_XYZB4            0x00c
#define D3DFVF_XYZB5            0x00e
#define D3DFVF_XYZW             0x4002
 
#define D3DFVF_NORMAL           0x010
#define D3DFVF_PSIZE            0x020
#define D3DFVF_DIFFUSE          0x040
#define D3DFVF_SPECULAR         0x080
 
#define D3DFVF_TEXCOUNT_MASK    0xf00
#define D3DFVF_TEXCOUNT_SHIFT   8
#define D3DFVF_TEX0             0x000
#define D3DFVF_TEX1             0x100
#define D3DFVF_TEX2             0x200
#define D3DFVF_TEX3             0x300
#define D3DFVF_TEX4             0x400
#define D3DFVF_TEX5             0x500
#define D3DFVF_TEX6             0x600
#define D3DFVF_TEX7             0x700
#define D3DFVF_TEX8             0x800
 
#define D3DFVF_LASTBETA_UBYTE4   0x1000
#define D3DFVF_LASTBETA_D3DCOLOR 0x8000
 
#define D3DFVF_RESERVED2         0x6000 

 

三.顶点缓存

一个顶点缓存是一个包含顶点数据的连续内存空间,存放在显存之中,比内存快(用于存储网格顶点)

1.CreateVertexBuffer

注意:静态缓存处理快,但是更新重绘慢.动态缓存处理慢,但是更新重绘快

 

HRESULT IDirect3DDevice9::CreatVertexBuffer(    //创建顶点缓存
     UINT Length,

  DWORD Usage,

    DWORD FVF,

    D3DPOOL Pool,

    IDirect3DVertexBuffer9** ppVertexBuffer,

    HANDLE* pSharedHandle

);

 

Length:为缓存分配的字节数,8个顶点需要8*sizeof(Vertex)

 

Usage:附加属性
 
      (1)D3DUSAGE_DYNAMIC  将缓存设为动态缓存
 
      (2)D3DUSAGE_POINTS   规定缓存将用于存储点图元
 
      (3)D3DUSAGE_SOFTWAREPROCESSING    指定软件顶点运算方法
 
      (4)D3DUSAGE_WRITEONLY    只写

 

FVF:存储在顶点缓冲的灵活顶点格式,参考宏定义

 

Pool:容纳缓存的内存池

 

ppVertexBuffer:用于接收所创建的顶点缓存的指针

 

pSharedHandle:不使用,设为0

 

//例子
 
IDirect3DVertexBuffer9* vb;
device->CreateVertexBuffer(
    8*sizeof(Vertex),
    0,
    D3DFVF_XYZ,
    D3DPOOL_MANAGED,
    &vb,
    0);

 

2.Lock/Unlock

HRESULT IDirect3DVertexBuffer9::Lock(

    UINT offsetToLock,

    UINT SizeToLock,

    BYTE** ppbData,
    DWORD Flags
);

 

OffsetToLock:自缓存的起始点到开始锁定的位置的偏移量,单位为字节

 

SizeToLock:所要锁定的字节数.
如果OffsetToLock和SizeToLock都为0表示锁定整个缓存

 

 //顶点缓存
IDirect3DVertexBuffer9* Triangle=0;
 
//访问顶点缓存内存
Vertex* vertices;
Triangle->Lock(0,0,(void**)&vertices,0);
...
 
Triangle->Unlock();

 

3.示例

//顶点缓存
IDirect3DVertexBuffer9* Triangle=0;
 
 
void Cleaup(){
    d3d::Release<IDirect3DVertexBuffer9*>(VB);
}
 
bool Setup{
 
    //用D3D设备类来创建顶点缓存内存
    Device->CreateVertexBuffer(
        3*sizeof(Vertex),
        D3DUSAGE_WRITEONLY,
        Vertex::FVF,
        D3DPOOL_MANAGED,   
        &Triangle,
       0);
 
    //访问顶点缓存内存
    Vertex* vertices;
    Triangle->Lock(0,0,(void**)&vertices,0);
    
    vertices[0]=Vertex(-1.0f,0.0f,2.0f);
    vertices[1]=Vertex(0.0f,1.0f,2.0f);
    vertices[2]=Vertex(1.0f,0.0f,2.0f);
 
    Triangle->Unlock();
    
}
 
 
bool Display(float timeDelta){
    
    Device->SetStreamSource(0,VB,0,sizeof(Vertex));
}

 

四.索引缓存

一个索引缓存是一个包含索引数据的连续内存空间,存放于显存之中,比内存快

构建一个3D物体的所有三角形单元中会共享许多公共顶点,为了解决重合顶点问题,用顶点列表(vertex list)和索引列表(index list)来记录坐标(决定顶点应以何种组合方式构成网格的三角形单元)

 

假设不用索引来表示一个正方形,Vectex v[6]={v0,v1,v2,v1,v2,v3},需要六个顶点坐标

加入索引之后,Vertect v[4]={v0,v1,v2,v3}  WORD indexList[6]={0,1,2,1,2,3};  只需要记录四个顶点坐标

因为索引坐标只是一个整数,用来获取顶点坐标的第几个,所以比三维坐标的Vertex更省内存

 

1.创建索引缓存

HRESULT IDirect3DDevice9::CreateIndexBuffer(
    UINT Length,
    DWORD Usage,
    D3DFORMAT Format,
    D3DPOOL Pool,
    IDirect3DIndexBuffer9** ppIndexBuffer,
    HANDLE* pSharedHandle);
 
Length:为缓存分配的字节数,8个顶点需要8*sizeof(Vertex)
Usage:附加属性
      (1)D3DUSAGE_DYNAMIC  将缓存设为动态缓存
      (2)D3DUSAGE_POINTS   规定缓存将用于存储点图元
      (3)D3DUSAGE_SOFTWAREPROCESSING    指定软件顶点运算方法
      (4)D3DUSAGE_WRITEONLY    只写
Format:指定索引的大小
       (1)D3DFMT_INDEX16 表示16位索引
       (2)D3DFMT_INDEX32 表示32位索引
Pool:容纳缓存的内存池
ppIndexBuffer:用于接收所创建的索引缓存的指针
pSharedHandle:不使用,设为0

 

IDirect3DIndexBuffer9* ib;
device->CreateIndexBuffer(
    36*sizeof(WORD),
    D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY,
    D3DFMT_INDEX16,
    D3DPOOL_MANAGED,
    &ib,
    0);

 

2.访问索引缓存

HRESULT IDirect3DIndexBuffer9::Lock(
    UINT OffsetToLock,
    UINT SizeToLock,
    BYTE** ppbData,
    DWORD Flags
);

 

3.示例

//索引缓存
IDirect3DIndexBuffer9* IB=0;
 
 
bool Setup(){
 
    //用D3D设备类来创建索引缓存    
    Device->CreateIndexBuffer(
        36*sizeof(WORD),
        D3DUSAGE_WRITEONLY,
        D3DFMT_INDEX16,    
        D3DPOOL_MANAGED,
        &IB,
        0);
    
    //访问索引缓存
    WORD* Iindices=0;
    IB->LOCK(0,0,(void**)&indices,0);
 
    indices[0]=0;indices[1]=1;indices[2]=2;
    indices[3]  = 0; indices[4]  = 2; indices[5]  = 3;
 
    // back side
    indices[6]  = 4; indices[7]  = 6; indices[8]  = 5;
    indices[9]  = 4; indices[10] = 7; indices[11] = 6;
 
    // left side
    indices[12] = 4; indices[13] = 5; indices[14] = 1;
    indices[15] = 4; indices[16] = 1; indices[17] = 0;
 
    // right side
    indices[18] = 3; indices[19] = 2; indices[20] = 6;
    indices[21] = 3; indices[22] = 6; indices[23] = 7;
 
    // top
    indices[24] = 1; indices[25] = 5; indices[26] = 6;
    indices[27] = 1; indices[28] = 6; indices[29] = 2;
 
    // bottom
    indices[30] = 4; indices[31] = 0; indices[32] = 3;
    indices[33] = 4; indices[34] = 3; indices[35] = 7;
 
    IB->Unlock();
}
 
void Cleanup(){
    d3d::Release<IDirect3DIndexBuffer9*>(IB);
}
 
bool Display(float timeDelta){
    //绑定模型的索引缓存
    Device->SetIndices(IB);
}

 

五.网格

1.网格简介

一个网格由一个或多个子集组成,一个子集(subsets)是网格中一组可用相同属性(材质/纹理/绘制状态)进行绘制的三角形单元

假设一个房子是网格,那么地板/墙/天花板/窗口各有自己的属性,都能用来绘制房子网格

为了区分不同的子集,给每个子集指定一个唯一的非负整数值,该值为DWORD类型所能容纳任何非负整数

网格中的每个三角形单元都被赋予了一个属性ID,该ID指定了该三角形单元所属的子集,这些三角形单元的属性ID被存储在网格的属性缓存(Attribute Buffer)中,该属性缓存实际上就是一个DWORD类型的数组.

由于每个面片(三角形)在属性缓存中都有对应项,所以属性缓存中元素的个数与网格中面皮的个数相等.

 

2.网格类(ID3DXMesh)的方法

HRESULT ID3DMesh::GetVertexBuffer(LPDIRECT3DVERTEXBUFFER9* ppVB)

HRESULT ID3DMesh::GetIndexBuffer(LPDIRECT3DVERTEXBUFFER9* ppIB)

DWORD GetFVF()

DWORD GetNumVertices()
DWORD GetNumBytesPerVertex()
DWORD GetNumFaces()

LockAttributeBuffer()

LockIndexBuffer()

LockVertexBuffer()

UnlockAttributeBuffer()

UnlockIndexBuffer()

UnlockVertexBuffer()

CloneMesh()
CloneMeshFVF()

 

DrawSubset(DWORD AttribID)   //用于绘制由参数AttribId指定的子集中的三角形单元
 
//例子
Mesh->DrawSubset(0);  //绘制子集0中的所有三角形单元
 
for(int i=0;i<numSubsets;i++){
    Device->SetMaterial(mtrls[i]);
    Device->SetTexture(0,textures[i]);
    Mesh->DrawSubset(i);
}

 

3.D3D支持网格(ID3DXMESH)的方法

HRESULT WINAPI D3DXCreateMeshFVF(
    DWORD NumFaces,        //网格所具有的面皮个数
    DWORD NumVertices,          //网格所具有的顶点个数
    DWORD Options,        //创建网格时所使用的创建标记
    DWORD FVF,             // 顶点的灵活格式
    LPDIRECT3DDEVICE9 pDevice,      // 与网格相关的设备指针
    LPD3DXMESH* ppMesh              // 所创建的网格对象的指针
);

D3DXCreateMesh()        //创建空网格

//绘制内置的网格模型
D3DXCreateTeapot()    //茶壶
D3DXCreateBox()       //正方体
D3DXCreateCylinder()
D3DXCreateTorus()
D3DXCreateSphere()
D3DXCreaetPolygon()

 

//多个模型一起绘制
 
 
ID3DXMesh* Objects[5] = {0, 0, 0, 0, 0};
 
// World matrices for each object.  These matrices
// specify the locations of the objects in the world.
D3DXMATRIX ObjWorldMatrices[5];
 
//
// Framework Functions
//
bool Setup()
{
 
	//
	//茶壶模型 
	//
 
	D3DXCreateTeapot(
		Device,
		&Objects[0],
		0);
 
        //
        //立方体
        //
 
	D3DXCreateBox(
		Device,
		2.0f, // width
		2.0f, // height
		2.0f, // depth
		&Objects[1],
		0);
        
        //
	//柱体
        //
        
	D3DXCreateCylinder(
		Device,
		1.0f, // radius at negative z end
		1.0f, // radius at positive z end
		3.0f, // length of cylinder
		10,   // slices
		10,   // stacks
		&Objects[2],
		0);
 
        //
        //圆环体
        //
 
	D3DXCreateTorus(
		Device,
		1.0f, // inner radius
		3.0f, // outer radius
		10,   // sides
		10,   // rings
		&Objects[3],
		0);
 
        //
        //球面体
        //
 
	D3DXCreateSphere(
		Device,
		1.0f, // radius
		10,   // slices
		10,   // stacks
		&Objects[4],
		0);
 
 
 
	//
        //多边形
        //D3DXCreatePolygon()
 
	D3DXMatrixTranslation(&ObjWorldMatrices[0],  0.0f, 0.0f,  0.0f);
	D3DXMatrixTranslation(&ObjWorldMatrices[1], -5.0f, 0.0f,  5.0f);
	D3DXMatrixTranslation(&ObjWorldMatrices[2],  5.0f, 0.0f,  5.0f);
	D3DXMatrixTranslation(&ObjWorldMatrices[3], -5.0f, 0.0f, -5.0f);
	D3DXMatrixTranslation(&ObjWorldMatrices[4],  5.0f, 0.0f, -5.0f);
 
	//
	// Set the projection matrix.
	//
 
	D3DXMATRIX proj;
	D3DXMatrixPerspectiveFovLH(
		&proj,
		D3DX_PI * 0.5f, // 90 - degree
		(float)Width / (float)Height,
		1.0f,
		1000.0f);
	Device->SetTransform(D3DTS_PROJECTION, &proj);
 
	//
	// Switch to wireframe mode.
	//
 
	Device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
 
	return true;
}
void Cleanup()
{
	for(int i = 0; i < 5; i++)
		d3d::Release<ID3DXMesh*>(Objects[i]);
}
 
bool Display(float timeDelta)
{
	if( Device )
	{
		// Animate the camera:
		// The camera will circle around the center of the scene.  We use the
		// sin and cos functions to generate points on the circle, then scale them
		// by 10 to further the radius.  In addition the camera will move up and down
		// as it circles about the scene.
		static float angle = (3.0f * D3DX_PI) / 2.0f;
		static float cameraHeight = 0.0f;
		static float cameraHeightDirection = 5.0f;
 
		D3DXVECTOR3 position( cosf(angle) * 10.0f, cameraHeight, sinf(angle) * 10.0f );
 
		// the camera is targetted at the origin of the world
		D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
 
		// the worlds up vector
		D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
 
		D3DXMATRIX V;
		D3DXMatrixLookAtLH(&V, &position, &target, &up);
		Device->SetTransform(D3DTS_VIEW, &V);
 
		// compute the position for the next frame
		angle += timeDelta;
		if( angle >= 6.28f )
			angle = 0.0f;
 
		// compute the height of the camera for the next frame
		cameraHeight += cameraHeightDirection * timeDelta;
		if( cameraHeight >= 10.0f )
			cameraHeightDirection = -5.0f;
 
		if( cameraHeight <= -10.0f )
			cameraHeightDirection = 5.0f;
 
		//
		// Draw the Scene:
		//
 
		Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
		Device->BeginScene();
 
		for(int i = 0; i < 5; i++)
		{
			// Set the world matrix that positions the object.
			Device->SetTransform(D3DTS_WORLD, &ObjWorldMatrices[i]);
 
			// Draw the object using the previously set world matrix.
			Objects[i]->DrawSubset(0);
		}
 
		Device->EndScene();
		Device->Present(0, 0, 0, 0);
	}
	return true;
}

 

转载于:https://www.cnblogs.com/k5bg/p/11136525.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值