D3D的第一个例子

玩了2天NBA live08,最后一场和网友打了4个加时,还是输了。吃完饭时在想,我玩NBA到底收获了什么,感觉虚度了2天光阴啊~ 好好学习吧!我如是想到。

今天看书写了第一个D3D的例子,写篇博客以示纪念,一个旋转的立方体,没什么技术含量,无非是调用一些MS的API,可是内部怎么执行的我还是不知道,打算这学期看完LaMothe的<<3D游戏编程大师技巧>>搞清楚相关数学原理,任重而道远啊!

代码清单:

  1. //
  2. //
  3. // File: cube.cpp
  4. // by tianzhihen 
  5. // 2008.10.12
  6. // MSVC++ 8.0
  7. //
  8. #include "d3dUtility.h"
  9. //
  10. //  全局变量
  11. //
  12. IDirect3DDevice9* Device = 0;
  13. const int Width  = 640;
  14. const int Height = 480;
  15. IDirect3DVertexBuffer9* VB = 0;
  16. IDirect3DIndexBuffer9*  IB = 0;
  17. //
  18. // 类和结构体
  19. //
  20. struct Vertex 
  21. {
  22.     Vertex(){}
  23.     Vertex(float x,float y,float z)
  24.     {
  25.         _x = x; _y = y; _z = z;
  26.     }
  27.     float _x,_y,_z;
  28.     static const DWORD FVF;
  29. };
  30. const DWORD Vertex::FVF = D3DFVF_XYZ;
  31. //
  32. // 框架函数
  33. //
  34. bool Setup()
  35. {
  36.     //
  37.     // 创建顶点/索引缓存
  38.     //  
  39.     Device->CreateVertexBuffer(
  40.         8*sizeof(Vertex),
  41.         D3DUSAGE_WRITEONLY, // 只写
  42.         Vertex::FVF,
  43.         D3DPOOL_MANAGED,
  44.         &VB,
  45.         0);
  46.     Device->CreateIndexBuffer(
  47.         36*sizeof(WORD),
  48.         D3DUSAGE_WRITEONLY,
  49.         D3DFMT_INDEX16,
  50.         D3DPOOL_MANAGED,
  51.         &IB,
  52.         0);
  53.     //
  54.     // 用立方体数据填充缓存
  55.     //
  56.     Vertex* vertices;
  57.     VB->Lock(0,0,(void**)&vertices,0);
  58.         
  59.     vertices[0] = Vertex(-1.0f, -1.0f, -1.0f);
  60.     vertices[1] = Vertex(-1.0f,  1.0f, -1.0f);
  61.     vertices[2] = Vertex( 1.0f,  1.0f, -1.0f);
  62.     vertices[3] = Vertex( 1.0f, -1.0f, -1.0f);
  63.     vertices[4] = Vertex(-1.0f, -1.0f,  1.0f);
  64.     vertices[5] = Vertex(-1.0f,  1.0f,  1.0f);
  65.     vertices[6] = Vertex( 1.0f,  1.0f,  1.0f);
  66.     vertices[7] = Vertex( 1.0f, -1.0f,  1.0f);
  67.     VB->Unlock();
  68.     WORD* indices = 0;
  69.     IB->Lock(0,0,(void**)&indices,0);
  70.     // front side
  71.     indices[0]  = 0; indices[1]  = 1; indices[2]  = 2;
  72.     indices[3]  = 0; indices[4]  = 2; indices[5]  = 3;
  73.     // back side
  74.     indices[6]  = 4; indices[7]  = 6; indices[8]  = 5;
  75.     indices[9]  = 4; indices[10] = 7; indices[11] = 6;
  76.     // left side
  77.     indices[12] = 4; indices[13] = 5; indices[14] = 1;
  78.     indices[15] = 4; indices[16] = 1; indices[17] = 0;
  79.     // right side
  80.     indices[18] = 3; indices[19] = 2; indices[20] = 6;
  81.     indices[21] = 3; indices[22] = 6; indices[23] = 7;
  82.     // top
  83.     indices[24] = 1; indices[25] = 5; indices[26] = 6;
  84.     indices[27] = 1; indices[28] = 6; indices[29] = 2;
  85.     // bottom
  86.     indices[30] = 4; indices[31] = 0; indices[32] = 3;
  87.     indices[33] = 4; indices[34] = 3; indices[35] = 7;
  88.     IB->Unlock();
  89.     //
  90.     // 创建取景变换矩阵
  91.     //
  92.     D3DXVECTOR3 position(0.0f,0.0f,-5.0f);
  93.     D3DXVECTOR3 target(0.0f,0.0f,0.0f);
  94.     D3DXVECTOR3 up(0.0f,1.0f,0.0f);
  95.     D3DXMATRIX V;
  96.     D3DXMatrixLookAtLH(&V,&position,&target,&up);
  97.     Device->SetTransform(D3DTS_VIEW,&V);
  98.     //
  99.     // 设置投影矩阵
  100.     //
  101.     D3DXMATRIX proj;
  102.     D3DXMatrixPerspectiveFovLH(
  103.                 &proj,
  104.                 D3DX_PI*0.5f,
  105.                 (float)Width/(float)Height,
  106.                 1.0f,
  107.                 1000.0f);
  108.     Device->SetTransform(D3DTS_PROJECTION,&proj);
  109.     //
  110.     // 选择绘制状态(线框状态)
  111.     //
  112.     Device->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME);
  113.     return true;
  114. }
  115. void Cleanup()
  116. {
  117.     d3d::Release<IDirect3DVertexBuffer9*>(VB);
  118.     d3d::Release<IDirect3DIndexBuffer9*>(IB);
  119. }
  120. bool Display(float timeDelta)
  121. {
  122.     if (Device)
  123.     {
  124.         //
  125.         // 旋转矩阵
  126.         //
  127.         D3DXMATRIX Rx,Ry;
  128.         // 绕 x 方向每帧转45度
  129.         D3DXMatrixRotationX(&Rx,3.14f/4.0f);
  130.         // 绕 y 方向每帧递增角度
  131.         static float y = 0.0f;
  132.         D3DXMatrixRotationY(&Ry,y);
  133.         y += timeDelta;
  134.         // 角度达到360度后归零
  135.         if (y>=6.28f)
  136.         {
  137.             y = 0.0f;
  138.         }
  139.         // 结合x and y 方向的旋转角度
  140.         D3DXMATRIX p = Rx * Ry;
  141.         Device->SetTransform(D3DTS_WORLD,&p);
  142.         //
  143.         // 绘制场景
  144.         //
  145.         Device->Clear(0,0,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER , 0xffffffff,1.0f,0);
  146.         Device->BeginScene();
  147.         Device->SetStreamSource(0,VB,0,sizeof(Vertex));
  148.         Device->SetIndices(IB);
  149.         Device->SetFVF(Vertex::FVF);
  150.         // 绘制立方体
  151.         Device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,8,0,12);
  152.         Device->EndScene();
  153.         Device->Present(0,0,0,0);
  154.     }
  155.     return true;
  156. }
  157. //
  158. // WndProc
  159. //
  160. LRESULT CALLBACK d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
  161. {
  162.     switch(msg)
  163.     {
  164.     case WM_DESTROY:
  165.         ::PostQuitMessage(0);
  166.         break;
  167.     case WM_KEYDOWN:
  168.         if(wParam == VK_ESCAPE)
  169.             ::DestroyWindow(hwnd);
  170.         break;
  171.     }
  172.     return ::DefWindowProc(hwnd,msg,wParam,lParam);
  173. }
  174. //
  175. //  WinMain
  176. //
  177. int WINAPI WinMain(HINSTANCE hInstance,
  178.                    HINSTANCE hPrevInstance, 
  179.                    LPSTR lpCmdLine,
  180.                    int nShowCmd )
  181. {
  182.     //程序入口地址
  183.     //初始化D3D
  184.     if (!d3d::InitD3D(hInstance,640,480,true,D3DDEVTYPE_HAL,&Device))
  185.     {
  186.         ::MessageBox(0, "InitD3D() - FAILED", 0, 0);
  187.         return 0;
  188.     }
  189.     //分配资源
  190.     if (!Setup())
  191.     {
  192.         ::MessageBox(0, "Setup() - FAILED", 0, 0);
  193.         return 0;
  194.     }
  195.     //进入消息循环
  196.     d3d::EnterMsgLoop(Display);
  197.     //清理资源
  198.     Cleanup();
  199.     Device->Release();
  200.     return 0;
  201. }

需要注意的一点是: 本例中是用世界变换来指定立方体的方向。因为设置顶点格式时将顶点的位置属性设置为不能改变。

                                    const DWORD Vertex::FVF = D3DFVF_XYZ;

 

用的是上一篇文章中的框架,只是修改了d3dUtility.cpp里面的三个函数:Setup() Display() Clean() ,框架确实好用。过段时间研究下MS的DXUT。附图:

 

<think>好的,用户想要一个使用Go语言导出Excel的例子。首先,我需要确定用户的需求是什么。他们可能需要生成Excel文件,可能包含数据导出、报表生成等功能。常见的库有哪些呢?Go语言中常用的Excel处理库有tealeg/xlsx和excelize。其中,excelize比较流行,支持读写XLSX文件,功能更全面,所以推荐使用这个。 接下来,我需要考虑用户可能的水平。他们可能是刚开始学习Go,所以例子要简单明了,步骤清晰。需要包括安装库、创建文件、写入数据、保存文件这些基本步骤。同时,可能需要解释代码结构,确保用户理解每个部分的作用。 然后,代码示例的结构。首先安装excelize库,然后创建一个新文件,添加工作表,设置表头,填充数据,最后保存。还要处理可能的错误,比如文件创建失败、保存失败等,这样用户在实际使用中能处理异常情况。 用户可能想知道如何调整样式,比如设置列宽、字体加粗等。虽然基础示例可能不需要,但提供一个扩展说明会更好,满足进阶需求。同时,提醒用户注意路径权限问题,避免保存文件时出现错误。 另外,是否需要处理不同的数据类型?比如数字、日期,或者公式?但用户可能只需要基础的数据导出,所以先保持简单。如果有更复杂的需求,可以建议查阅excelize的文档。 最后,检查示例代码是否正确,语法是否有误,确保用户能够直接复制运行。同时,测试代码是否真的能生成Excel文件,避免出现错误。</think>我将为您演示如何使用Go语言通过`excelize`库导出Excel文件,包含详细步骤说明和代码示例: 1. **安装依赖库** ```bash go get github.com/xuri/excelize/v2 ``` 2. **完整代码示例** ```go package main import ( "fmt" "github.com/xuri/excelize/v2" ) func main() { // 创建新Excel文件 f := excelize.NewFile() // 创建工作表(默认会创建Sheet1,这里创建第二个工作表) index, _ := f.NewSheet("SalesData") // 设置表头 headers := []string{"商品ID", "商品名称", "销量", "单价", "销售额"} for col, h := range headers { cell, _ := excelize.CoordinatesToCellName(col+1, 1) f.SetCellValue("SalesData", cell, h) } // 填充示例数据 data := [][]interface{}{ {1001, "无线鼠标", 150, 299.00, "=C2*D2"}, {1002, "机械键盘", 80, 699.00, "=C3*D3"}, {1003, "游戏耳机", 200, 399.00, "=C4*D4"}, } for rowIdx, row := range data { for colIdx, val := range row { cell, _ := excelize.CoordinatesToCellName(colIdx+1, rowIdx+2) f.SetCellValue("SalesData", cell, val) } } // 设置活动工作表 f.SetActiveSheet(index) // 设置列宽 f.SetColWidth("SalesData", "A", "E", 15) // 保存文件 if err := f.SaveAs("sales_report.xlsx"); err != nil { fmt.Println("导出失败:", err) return } fmt.Println("成功生成 sales_report.xlsx") } ``` 3. **关键功能说明** - `excelize.NewFile()`: 创建新的Excel工作簿 - `NewSheet()`: 创建工作表 - `SetCellValue()`: 设置单元格值 - `CoordinatesToCellName()`: 行列号转单元格地址(如(1,1)->A1) - 支持公式计算(示例中的销售额列) - 设置列宽提升可读性 4. **扩展功能建议** ```go // 设置表头样式(加粗+居中) styleID, _ := f.NewStyle(&excelize.Style{ Font: &excelize.Font{Bold: true}, Alignment: &excelize.Alignment{Horizontal: "center"}, }) f.SetCellStyle("SalesData", "A1", "E1", styleID) // 添加条件格式(高亮销量>100) formatID, _ := f.NewConditionalStyle(`{ "fill": {"type": "pattern", "color": ["#DFF0D8"], "pattern": 1} }`) f.SetConditionalFormat("SalesData", "C2:C4", fmt.Sprintf(`[{"type": "cell", "criteria": ">", "format": %d, "value": "100"}]`, formatID)) // 添加图表(柱状图) if err := f.AddChart("SalesData", "F1", `{ "type": "col", "series": [ {"name": "SalesData!$B$1", "categories": "SalesData!$B$2:$B$4", "values": "SalesData!$C$2:$C$4"} ], "title": {"name": "商品销量统计"} }`); err != nil { fmt.Println("添加图表失败:", err) } ``` 5. **运行注意事项** - 需要写入权限的目标目录 - 关闭Excel程序后再运行,避免文件占用冲突 - 处理大文件时建议使用`StreamWriter`进行流式写入 该示例实现了: - 创建多工作表 - 基本数据填充 - 公式计算 - 样式设置 - 条件格式 - 图表生成 可通过`go doc excelize`查看完整文档,或访问官方仓库:https://github.com/xuri/excelize
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值