当前位置: 首页 > 编程日记 > 正文

DirectX10 学习笔记2:在多文档框架中初始化DirectX 10

显示功能是在视图类中完成的,所以DX10的初始化及绘制工作都是视图类中完成。

首先建立一个多文档工程,工程名为02_01,在视图类头文件中加载相关的库,并包含头文件:

lib and includes

在视图类的头文件中添加DX10相关的成员:

member variables for dx

其中三个变换矩阵、m_device以及显卡有关信息通过五个公有函数访问:

access function

下面是DX具体的初始化过程,封装为一个视图类的成员函数InitDX()。

DX初始化过程中需要创建设备和交换链,在创建交换链的时候用到和视图窗口有关的几个参数:窗口的宽、高和窗口的句柄:

width-height-hwnd

接下来是交换链、纹理资源、2D纹理描述结构体等,其中screenNear和screenDepth是渲染的深度范围,m_vsync_enabled设置为真,表明后面会根据实际的硬件设备设置刷新率,否则是尽可能快地刷新:

variables

以下代码填充DXGI_SWAP_CHAIN_DESC结构体中在初始化过程中用到的一些成员:

 
    // Initialize the swap chain description.
    ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
 
    // Set to a single back buffer.
    swapChainDesc.BufferCount = 1;
 
    // Set the width and height of the back buffer.
    swapChainDesc.BufferDesc.Width = screenWidth;
    swapChainDesc.BufferDesc.Height = screenHeight;
 
    // Set regular 32-bit surface for the back buffer.
    swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
 
    // Set the refresh rate of the back buffer.
    if(m_vsync_enabled)
    {
        swapChainDesc.BufferDesc.RefreshRate.Numerator = 1;
        swapChainDesc.BufferDesc.RefreshRate.Denominator = 60;
    }
    else
    {
        swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
        swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
    }
 
    // Set the usage of the back buffer.
    swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
 
    // Set the handle for the window to render to.
    swapChainDesc.OutputWindow = hwnd;
 
    // Turn multisampling off.
    swapChainDesc.SampleDesc.Count = 1;
    swapChainDesc.SampleDesc.Quality = 0;
 
    // Set to full screen or windowed mode.
    swapChainDesc.Windowed = true;
 
    // Set the scan line ordering and scaling to unspecified.
    swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
    swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
 
    // Discard the back buffer contents after presenting.
    swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
 
    // Don't set the advanced flags.
    swapChainDesc.Flags = 0;

DXGI_SWAP_CHAIN_DESC结构体填充好后,创建交换链和Direct3D Device。Direct3D Device是调用所有D3D函数的接口。

// Create the swap chain and the Direct3D device.
    result = D3D10CreateDeviceAndSwapChain(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL, 0, D3D10_SDK_VERSION, 
        &swapChainDesc, &m_swapChain, &m_device);
    if(FAILED(result))
    {
        return false;
    }

现在device和swap chain都有了,接下来需要back buffer的指针挂到swap chain上。通过CreateRenderTargetView函数来实现。

// Get the pointer to the back buffer.
    result = m_swapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (LPVOID*)&backBufferPtr);
    if(FAILED(result))
    {
        return false;
    }
// Create the render target view with the back buffer pointer.
    result = m_device->CreateRenderTargetView(backBufferPtr, NULL, &m_renderTargetView);
    if(FAILED(result))
    {
        return false;
    }
// Release pointer to the back buffer as we no longer need it.
    backBufferPtr->Release();
    backBufferPtr = NULL;

此外还需要设置depth buffer的描述结构体,通过这个深度缓冲区描述结构体创建depth buffer,以实现多边形在三维空间的绘制。同时还要把stencil buffer挂在depth buffer上。stencil buffer用来实现一些特效的,比如运动模糊,阴影体等。

// Initialize the description of the depth buffer.
    ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc));
 
    // Set up the description of the depth buffer.
    depthBufferDesc.Width = screenWidth;
    depthBufferDesc.Height = screenHeight;
    depthBufferDesc.MipLevels = 1;
    depthBufferDesc.ArraySize = 1;
    depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
    depthBufferDesc.SampleDesc.Count = 1;
    depthBufferDesc.SampleDesc.Quality = 0;
    depthBufferDesc.Usage = D3D10_USAGE_DEFAULT;
    depthBufferDesc.BindFlags = D3D10_BIND_DEPTH_STENCIL;
    depthBufferDesc.CPUAccessFlags = 0;
    depthBufferDesc.MiscFlags = 0;

现在可以创建depth/stencil buffer。实际上buffer只是一块2D纹理,所以这里使用CreateTexture2D函数创建这两个buffer。

// Create the texture for the depth buffer using the filled out description.
    result = m_device->CreateTexture2D(&depthBufferDesc, NULL, &m_depthStencilBuffer);
    if(FAILED(result))
    {
        return false;
    }

下面设置depth stencil的描述结构体,该结构体指定对每个像素使用的深度测试类型。

// Initialize the description of the stencil state.
    ZeroMemory(&depthStencilDesc, sizeof(depthStencilDesc));
 
    // Set up the description of the stencil state.
    depthStencilDesc.DepthEnable = true;
    depthStencilDesc.DepthWriteMask = D3D10_DEPTH_WRITE_MASK_ALL;
    depthStencilDesc.DepthFunc = D3D10_COMPARISON_LESS;
 
    depthStencilDesc.StencilEnable = true;
    depthStencilDesc.StencilReadMask = 0xFF;
    depthStencilDesc.StencilWriteMask = 0xFF;
 
    // Stencil operations if pixel is front-facing.
    depthStencilDesc.FrontFace.StencilFailOp = D3D10_STENCIL_OP_KEEP;
    depthStencilDesc.FrontFace.StencilDepthFailOp = D3D10_STENCIL_OP_INCR;
    depthStencilDesc.FrontFace.StencilPassOp = D3D10_STENCIL_OP_KEEP;
    depthStencilDesc.FrontFace.StencilFunc = D3D10_COMPARISON_ALWAYS;
 
    // Stencil operations if pixel is back-facing.
    depthStencilDesc.BackFace.StencilFailOp = D3D10_STENCIL_OP_KEEP;
    depthStencilDesc.BackFace.StencilDepthFailOp = D3D10_STENCIL_OP_DECR;
    depthStencilDesc.BackFace.StencilPassOp = D3D10_STENCIL_OP_KEEP;
    depthStencilDesc.BackFace.StencilFunc = D3D10_COMPARISON_ALWAYS;

下面用上述结构体创建一个depth stencil state:

// Create the depth stencil state.
    result = m_device->CreateDepthStencilState(&depthStencilDesc, &m_depthStencilState);
    if(FAILED(result))
    {
        return false;
    }

接下来让这个depth stencil state在device上生效:

// Set the depth stencil state on the D3D device.
    m_device->OMSetDepthStencilState(m_depthStencilState, 1);

最后要创建的是depth stencil buffer视图的描述结构体,然后调用CreateDepthStencilView创建depth stencil buffer视图。

// Initailze the depth stencil view.
    ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc));
 
    // Set up the depth stencil view description.
    depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
    depthStencilViewDesc.ViewDimension = D3D10_DSV_DIMENSION_TEXTURE2D;
    depthStencilViewDesc.Texture2D.MipSlice = 0;
 
    // Create the depth stencil view.
    result = m_device->CreateDepthStencilView(m_depthStencilBuffer, &depthStencilViewDesc, &m_depthStencilView);
    if(FAILED(result))
    {
        return false;
    }

现在要把render target view和depth stencil buffer绑定到输出渲染管线。这样一来管线中渲染的图形才能输出到前面我们创建的back buffer中去。back buffer里的图形绘制完成后,会被交换到前端,输出到显示器上。

// Bind the render target view and depth stencil buffer to the output render pipeline.
    m_device->OMSetRenderTargets(1, &m_renderTargetView, m_depthStencilView);

至此render target已经设置完毕。下面还要设置一些额外的功能,将来可能会用到。首先要创建的是光栅化状态rasterizer state,该状态用来控制多边形的绘制方式,比如用线框模式绘制或是双面绘制之类的。默认情况下rasterizer state是下面这样:

// Setup the raster description which will determine how and what polygons will be drawn.
    rasterDesc.AntialiasedLineEnable = false;
    rasterDesc.CullMode = D3D10_CULL_BACK;
    rasterDesc.DepthBias = 0;
    rasterDesc.DepthBiasClamp = 0.0f;
    rasterDesc.DepthClipEnable = true;
    rasterDesc.FillMode = D3D10_FILL_SOLID;
    rasterDesc.FrontCounterClockwise = false;
    rasterDesc.MultisampleEnable = false;
    rasterDesc.ScissorEnable = false;
    rasterDesc.SlopeScaledDepthBias = 0.0f;
 
// Create the rasterizer state from the description we just filled out.
    result = m_device->CreateRasterizerState(&rasterDesc, &m_rasterState);
    if(FAILED(result))
    {
        return false;
    }
 
    // Now set the rasterizer state.
    m_device->RSSetState(m_rasterState);

接下来还要设置viewport,让D3D能够把裁剪空间坐标映射到render target空间里去。这里把视口设置为窗口大小。

// Setup the viewport for rendering.
    viewport.Width = screenWidth;
    viewport.Height = screenHeight;
    viewport.MinDepth = 0.0f;
    viewport.MaxDepth = 1.0f;
    viewport.TopLeftX = 0;
    viewport.TopLeftY = 0;
 
    // Create the viewport.
    m_device->RSSetViewports(1, &viewport);

然后是投影矩阵,该矩阵用来把三维场景映射到刚刚设置好的二维视口空间上。今后渲染场景的时候需要把这个矩阵的副本传给shader。

// Setup the projection matrix.
    fieldOfView = (float)D3DX_PI / 4.0f;
    screenAspect = (float)screenWidth / (float)screenHeight;
 
    // Create the projection matrix for 3D rendering.
    D3DXMatrixPerspectiveFovLH(&m_projectionMatrix, fieldOfView, screenAspect, screenNear, screenDepth);

另外还要创建一个世界矩阵。该矩阵用来把一个对象上的顶点变换到我们创建的三维场景中去。同时这个矩阵也用来对三维场景中的对象进行旋转、缩放和平移。初始化的时候可以用一个单位矩阵作为世界矩阵。在渲染的时候也需要把该矩阵的副本传给shader。

// Initialize the world matrix to the identity matrix.
    D3DXMatrixIdentity(&m_worldMatrix);

下面实际应该创建一个视点矩阵。视点矩阵用来计算我们观察场景所处的位置。可以认为视点矩阵描述了摄像机的位置。视点矩阵的创建放在摄像机类中完成。

D3D初始化的最后一步是创建正交投影矩阵orthographic projection matrix。这个矩阵是用来渲染二维元素的。

// Create an orthographic projection matrix for 2D rendering.
    D3DXMatrixOrthoLH(&m_orthoMatrix, (float)screenWidth, (float)screenHeight, screenNear, screenDepth);

最后的最后。。

return true;

InitDX函数在初始化DX环境的时候需要知道窗口大小等参数,这个时候视图的尺寸需要有明确的值,所以InitDX函数要在OnInitialUpdate虚函数里调用。

最后测试一下DX初始化是否成功。可以逐步跟踪一下看各个COM接口调用的返回值,或者在OnPaint函数里简单写两行:

float color[4];
 
 
    // Setup the color to clear the buffer to.
    color[0] = 0.0f;
    color[1] = 0.0f;
    color[2] = 0.0f;
    color[3] = 1.0f;
 
    // Clear the back buffer.
    m_device->ClearRenderTargetView(m_renderTargetView, color);
 
    // Clear the depth buffer.
    m_device->ClearDepthStencilView(m_depthStencilView, D3D10_CLEAR_DEPTH, 1.0f, 0);
 
    if(m_vsync_enabled)
    {
        // Lock to screen refresh rate.
        m_swapChain->Present(1, 0);
    }
    else
    {
        // Present as fast as possible.
        m_swapChain->Present(0, 0);
    }

三个矩阵的get函数:

void CMy02_01View::GetProjectionMatrix(D3DXMATRIX& projectionMatrix)
{
    projectionMatrix = m_projectionMatrix;
    return;
}
 
 
void CMy02_01View::GetWorldMatrix(D3DXMATRIX& worldMatrix)
{
    worldMatrix = m_worldMatrix;
    return;
}
 
 
void CMy02_01View::GetOrthoMatrix(D3DXMATRIX& orthoMatrix)
{
    orthoMatrix = m_orthoMatrix;
    return;
}

最后的最后的最后,释放资源,在视图类中添加一个ReleaseDX()函数,在视图类的析构中调用它:

void CMy02_01View::ReleaseDX()
{
    if(m_rasterState)
    {
        m_rasterState->Release();
        m_rasterState = NULL;
    }
 
    if(m_depthStencilView)
    {
        m_depthStencilView->Release();
        m_depthStencilView = NULL;
    }
 
    if(m_depthStencilState)
    {
        m_depthStencilState->Release();
        m_depthStencilState = NULL;
    }
 
    if(m_depthStencilBuffer)
    {
        m_depthStencilBuffer->Release();
        m_depthStencilBuffer = NULL;
    }
 
    if(m_renderTargetView)
    {
        m_renderTargetView->Release();
        m_renderTargetView = NULL;
    }
 
    if(m_swapChain)
    {
        m_swapChain->Release();
        m_swapChain = NULL;
    }
 
    if(m_device)
    {
        m_device->Release();
        m_device = NULL;
    }
 
    return;
}

完毕。

PS:英文原文教程地址http://www.rastertek.com/dx10tut03.html,根据自己的需要进行了小小改动。

刚刚接触DX,很多背景知识不懂,希望过路的朋友不吝指教,帮我进步。谢谢。

转载于:https://www.cnblogs.com/youthlion/archive/2012/11/19/2778151.html

相关文章:

碾压Bert?“屠榜”的XLnet对NLP任务意味着什么

作者张俊林,中国中文信息学会理事,中科院软件所博士。目前担任新浪微博机器学习团队 AI Lab 负责人。在此之前,张俊林曾经在阿里巴巴任资深技术专家并负责新技术团队,以及在百度和用友担任技术经理及技术总监等职务。他是技术书籍…

ORACLE中通过DBMS_CRYPTO包对表敏感字段进行加密

http://doc.primeton.com/pages/viewpage.action?pageId4917998

02 使用百度地图获得当前位置的经纬度

O 需求 通过百度地图,获取用户当前位置的经纬度 一 准备 确保你已按照上篇《01 如何将百度地图加入IOS应用程序?》完成了相关功能。本篇将在上一篇的基础上进行修改。 二 编码 (New标示本次新添加的代码;Delete表示本次需要删除的代码&#x…

中文NLP的分词真有必要吗?李纪为团队四项任务评测一探究竟 | ACL 2019

作者| Yuxian Meng、Xiaoya Li、Xiaofei Sun、Qinghong Han、Arianna Yuan、 Jiwei Li译者 | Rachel责编 | Jane出品 | AI科技大本营(ID: rgznai100)【导读】通常,中文文本处理的第一步称为分词,这好像已经成为一种“共识”&#…

Netty 粘包 拆包 编码 解码 序列化 介绍

目录: 粘包 & 拆包及解决方案 ByteToMessageDecoder基于长度编解码器基于分割符的编解码器google 的 Protobuf 序列化介绍其他的前言 Netty 作为一个网络框架,对 TCP 连接中的问题都做了全面的考虑,比如粘包拆包导致的半包问题&#xff0…

matlab 全局变量

转自:http://matlab.net.cn/matlabjichu/2010/201005/265.html 如果你要多于一个函数共用一个简单的变量,简单的处理方法就是把这个变量在所有函数中定义为global全局变量。在命令行做同样的事情,如果你要工作空间访问上述变量。这个全局变量…

java 解决Html table的rowspan问题(osc处女作)

2019独角兽企业重金招聘Python工程师标准>>> 假如有如下html代码需要解析 <table border"1"><tr><td rowspan"3">1</td><td>1</td><td>1</td><td>1</td></tr><tr>&l…

基于C++的OpenCV常用函数

C版本的好处&#xff1a; 1、在于可以尽量避免使用指针这种危险的东西&#xff1b; 2、不用费心去release资源了&#xff0c;因为在其destructor里面&#xff0c;系统会自动帮你搞定。 3、在某些情况下会比C版本运行速度快。 在文件中包含 using namespace cv; 1. i…

基于GAN的图像水印去除器,效果堪比PS高手

作者 | 李翔转载自视说AI&#xff08;ID:techtalkai&#xff09;简介&#xff1a;李翔&#xff0c;国内某互联网大厂AI民工&#xff0c;前携程酒店图像技术负责人&#xff0c;计算机视觉和深度学习重度爱好者&#xff0c;在ICCV和CVPR等会议上发表论文十余篇。写在前面当前互联…

Flink最锋利的武器:Flink SQL入门和实战 | 附完整实现代码

作者 | 机智的王知无转载自大数据技术与架构&#xff08;ID: import_bigdata&#xff09;一、Flink SQL 背景Flink SQL 是 Flink 实时计算为简化计算模型&#xff0c;降低用户使用实时计算门槛而设计的一套符合标准 SQL 语义的开发语言。自 2015 年开始&#xff0c;阿里巴巴开始…

SQL SERVER中ROLLUP的用法

cube操作符 要使用cube&#xff0c;首先要了解group by 其实cube和rollup区别不太大&#xff0c;只是在基于group by 子句创建和汇总分组的可能的组合上有一定差别&#xff0c; cube将返回的更多的可能组合。如果在 group by 子句中有n个列或者是有n个表达式的话&#xff0c; s…

Mybait缓存机制

MyBatis同大多数ORM框架一样&#xff0c;提供了一级缓存和二级缓存的支持。 一级缓存&#xff1a;其作用域为session范围内&#xff0c;当session执行flush或close方法后&#xff0c;一级缓存会被清空。 二级缓存&#xff1a;二级缓存和一级缓存机制相同&#xff0c;但是可以自…

vs2008常用操作汇总

1、OpenCV2.1环境配置&#xff1a; (1)、Tools-->Options-->Projects and Solutions-->VCDrectories&#xff1a; Show directories for选择include files&#xff0c;加入目录 D:/Program Files/OpenCV2.1/include/opencv &#xff1b;Show directories for选择libra…

深度学习已至“瓶颈”?英特尔:数据处理是一剂良药

【导读】霍金弟子Alan Yuille在前不久发表言论称&#xff0c;至少在计算机视觉领域&#xff0c;深度学习的瓶颈已至。然而&#xff0c;人工智能与大数据的发展相辅相成&#xff0c;数据将会推动人工智能的发展&#xff0c;促进更多技术应用落地&#xff0c;将人工智能带入一个新…

WIN32 C++ 遍历文件夹

转自&#xff1a;http://blog.csdn.net/lizhigang770/archive/2010/11/30/6045242.aspx 一、先介绍一个结构 WIN32_FIND_DATA typedef struct _WIN32_FIND_DATA { DWORD dwFileAttributes; // 文件属性 FILETIME ftCreationTime; // 文件创建时间 FILETIME ft…

UIView淡入淡出动画

小小原创&#xff0c;转载请注明出处&#xff1a;http://iphone.xiaoxiaostudio.net 如果你觉得为某个UIView 加载一个全新的View在这个UIView上面时&#xff0c;想要隐藏时setHidden显得太突兀了&#xff0c;我们可以给它增加一些动画&#xff0c;iOS上默认提供了一些动画&…

sass的继承,混合宏,占位符的用法总结

SCSS中混合宏使用 mixin mt($var){ margin-top: $var; }.block { include mt(5px);span { display:block; include mt(5px); } }extend如何工作 .icon {transition: background-color ease .2s;margin: 0 .5em;}.error-icon {extend .icon;/*错误图标指定的样式... */}.info-i…

js中cookie的使用详细分析

2019独角兽企业重金招聘Python工程师标准>>> JavaScript中的另一个机制&#xff1a;cookie&#xff0c;则可以达到真正全局变量的要求。 cookie是浏览器 提供的一种机制&#xff0c;它将document 对象的cookie属性提供给JavaScript。可以由JavaScript对其进行控制&a…

从事JAVA 20年最终却败给了Python,哭了!

之前遇到一个老师&#xff0c;他从事Java行业20年了&#xff0c;在Python兴起的时候&#xff0c;他周围的其他同行们都在纷纷学习Python方面的知识&#xff0c;连他的学生也问他“老师&#xff0c;你为什么不学Python呢&#xff1f;”。当这位听到学生这个问题的时候&#xff0…

c++删除文件夹

转自&#xff1a;http://blog.csdn.net/sshhbb/archive/2010/12/07/6061029.aspx c语言本身是不能删除文件或文件夹的&#xff0c;他们是windows操作系统里的东西&#xff0c;所以得借助其api函数。 其一&#xff1a;使用shell 接口&#xff1a; void FileDelete(CString di…

解决bootstrap下的图片自适应问题

.img-responsive {display: block; height: auto; max-width: 100%; }转载于:https://www.cnblogs.com/qjuly/p/9809910.html

边缘检测、Hough变换、轮廓提取、种子填充、轮廓跟踪

转自&#xff1a;http://blog.sina.com.cn/s/blog_6c083cdd0100nm4s.html 7.1 边沿检测 我们给出一个模板 和一幅图象 。不难发现原图中左边暗&#xff0c;右边亮&#xff0c;中间存在着一条明显的边界。进行模板操作后的结果如下&#xff1a; 。 可以看出&#xff0c;第3…

JS Array 中 shift 和 pop 的妙用

在 JS Array 中支持两个方法&#xff0c;shift() 和 pop()&#xff0c;分别是指从一个数据中的最前面和最后面删除一个值&#xff0c;并返删除值。看一个示例就明白了&#xff1a; var arr [s,o,f,i,s,h]; arr.shift(); // 返回 s arr; // 目前是 [o,f,i,s,h…

当今主流分割网络有哪些?12篇文章一次带你看完

作者 | 孙叔桥来源 | 转载自有三AI&#xff08;ID: yanyousan_ai&#xff09;本文的12篇文章总结了当前主流的分割网络及其结构&#xff0c;涵盖从编解码结构到解码器设计&#xff1b;从感受野到多尺度融合&#xff1b;从CNN到RNN与CRF&#xff1b;从2D分割到3D分割&#xff1b…

正确生成浮点型的方法,解决sqlachemy Float浮点型的坑,生成float类型时,长度和精度均为0,导致查询不到结果!...

问题描述 在使用flask_sqlachemy时&#xff0c;给price字段选择了Float类型&#xff0c;数据库用的mysql&#xff0c;生成数据库表后&#xff0c;发现 from sqlalchemy import Float,Column price Column(Float,default0.00) 虽然能存储float类型&#xff0c;结果如下 但是查询…

图像轮廓的提取和绘制

转自&#xff1a;http://blog.csdn.net/gnuhpc/archive/2009/06/18/4278105.aspx <>var ultimaFecha ; <>document.write(ultimaFecha); #include "highgui.h" #include "cv.h" #include <iostream> #include <iomanip> using …

上海交大张拳石:神经网络的可解释性,从经验主义到数学建模

作者 | 张拳石来源 | 转载自知乎Qs.Zhang张拳石本来想把题目取为“从炼丹到化学”&#xff0c;但是这样的题目太言过其实&#xff0c;远不是近期可以做到的&#xff0c;学术研究需要严谨。但是&#xff0c;寻找适当的数学工具去建模深度神经网络表达能力和训练能力&#xff0c;…

计算机网络模型到底是七层?五层?四层?

1.Introduction 本篇文章的初衷是在做Android网络开发时经常接触各种协议&#xff0c;比如HTTP、XMPP、HLS、RTSP、TCP等协议&#xff0c;对网络的模型和层次有个直观的了解可以做到心中有数。OSI参考模型是七层&#xff0c;TCP/IP模型是四层&#xff0c;计算机网络&#xff08…

【推荐】使用Ultrapico Expresso学习正则表达式

推荐理由Ultrapico Expresso是我工作中经常使用的一个非常强大的正则表达式构建、测试以及代码生成工具。它能够对你构建的正则表达式进行解析、验证&#xff0c;并输出解析结果&#xff0c;提供性能测试工具&#xff0c;支持C#、VB等代码生成&#xff0c;最重要的是&#xff0…

OpenCV中常用到的轮廓处理函数汇总

转自&#xff1a;http://fsa.ia.ac.cn/opencv-doc-cn/opencv-doc-cn-0.9.7/ref/opencvref_cv.cn.htm ApproxChains 用多边形曲线逼近 Freeman 链 CvSeq* cvApproxChains( CvSeq* src_seq, CvMemStorage* storage,int methodCV_CHAIN_APPROX_SIMPLE,double parameter0, int mi…