【翻译】Managed DirectX(第九章)

DirectX学习笔记(三):利用线框模式绘制可旋转的正方体 前言: 一个场景中,任何物体都可以用三角形网格来逼近表示。也就是说,三角形网格是构成物体模型的基本单元。 如图: 利用线框模式绘制可旋转的正方体的具体操作: 1.顶点缓存和索引缓存: 一个多边形中相邻的交汇点称为顶点,描述三角形单元时,我们需要指定该三角形3个顶点的位置。那么如果我们要通过三角形单元来描述一个物体,就需要指定构成该物体的三角形单元。但是 阅读详情

第九章 使用其它Mesh类型

翻译:clayman

clayman_joe@yahoo.com.cn

仅供个人学习之用,勿用于任何商业用途,转载请注明作者^_^

简化Mesh(Simplifying Meshes)

         我们花了大量的时间来学习扩展库中的基本Mesh类,但实际上,还有3种其它Mesh类型我们没有讨论过,在这一章中,我们就来看看这几个对象。

         我们已经知道如何通过使用Mesh类的Simplify方法创建一个简化过的mesh。通常情况下,使用简化mesh只是为了显示低细节的模型,但在任何场景中,都不可能为一个mesh储存太多版本,特别是其中的很多版本你可能根本不会用到。

         SimplificationMesh方法可以用来压缩简化mesh的过程。但是,不能直接使用这个对象进行渲染你必须先通过simplification mesh创建一个真正的mesh。还记得先前简化mesh的例子吗,我们在例子里展示了两种情况。一种是在很近的情况下观察未经简化的mesh,另一种则是在比较远的的情况下显示简化了很多面和顶点的mesh。我们将再次做类似工作,不过这一次,我们将逐渐的移动摄像机。

         还是以第五章的例子为基础,逐渐添加代码。首先,添加SimplificationMesh对象的声明,同时还有控制摄像机位子的变量:

private SimplificationMesh simplifiedMesh = null;

     private float camreaPos = 580.0f ;

         把摄像机的深度位置作为变量,可以方便以后的修改。接下来更新观察变换 ,让他使用正确的位置信息。在SetupCamera方法中,添加更新如下代码:

device.Transform.View = Matrix.LookAtLH(new Vector3(0,0,cameraPos), new Vector3(), new Vector3(0,1,0));

显然,由于每一帧都会调用SetupCamera方法,因此任何对camera变量的改变都会马上得到更新,这正是我们想要的效果。SimplifiycationMesh中储存了我们将用于简化的mesh。注意到没,我们没有创建任何额外的Mesh对象。每次简化之后,只需用他代替原来的mesh就可以了。

修改LoadMesh方法确保mesh是经过了clean的,并且正确创建了simplifycationMesh对象。如下修改代码:

private void LoadMesh(string file)

{

     ExtendedMaterial[] mtrl;

     // Load our mesh

     mesh = Mesh.FromFile(file, MeshFlags.Managed, device, out mtrl);

     // If we have any materials, store them

     if ((mtrl != null) && (mtrl.Length > 0))

     {

         meshMaterials = new Material[mtrl.Length];

         meshTextures = new Texture[mtrl.Length];

         // Store each material and texture

         for (int i = 0; i < mtrl.Length; i++)

         {

             meshMaterials[i] = mtrl[i].Material3D;

             if ((mtrl[i].TextureFilename != null) && (mtrl[i].TextureFilename != string.Empty))

             {

                 // We have a texture, try to load it

                 meshTextures[i] = TextureLoader.FromFile(device, @"../../" + mtrl[i].TextureFilename);

              }

          }

      }

     //Clean our mesh

     Mesh tempMesh = Mesh.Clean(mesh,adj,adj);

     //replace extsting mesh with this one

     mesh.Dispose();

     mesh = tempMesh;

     //creat simiplification mesh

     simplificationMesh = new SimplificationMesh(mesh,adj);

}

(注:新版的MDX中应为Mesh tempMesh = Mesh.Clean(CleanType. Simplification,mesh,adj,adj); 另外,在使用了mesh.Dispose();之后程序有可能会出现异常。)

如你所见,在clean方法和simplificationMesh方法中都要用到邻接信息。在加载了mesh创建了纹理之后,我们就对mesh进行clean,准备简化。接下来,用clean过的mesh创建simplificationMesh对象。

事实上,现在不需要做任何修改,也能正确绘制mesh。但是,我们想添加一些代码让摄像机慢慢远离mesh,同时,减少mesh的细节。使用键盘来控制摄像机的移动,添加代码:

protected override void OnKeyPress(KeyPressEventArgs e)

{

     if(e.KeyChar == '+')

     {

         cameraPos += (MoveAmount * 2);

         simplifiedMesh.ReduceFaces(mesh.NumberFaces - MoveAmount);

         simplifiedMesh.ReduceVertices(mesh.NumberVertices - MoveAmount);

         mesh.Dispose();

         mesh = simplifiedMesh.Clone(simplifiedMesh.Options.Value,simplifiedMesh.VertexFormat,device);

     }

     if(e.KeyChar == 'w')

         device.RenderState.FillMode = FillMode.WireFrame;

     if(e.KeyChar == 's')

         device.RenderState.FillMode = FillMode.Solid;

     base.OnKeyPress (e);

}

注意到,这里使用了一个统一的常量来控制每次按下按键时移动的总数。你可以根据实际情况来设置这个常量,以下是我使用的值:

private const int MoveAmount = 100;

在这个方法里,按下W键的时候,跳转为线框模式,这样可以很容易看出实际绘制的三角形。按下S键则跳回填充模式。按下+键,则会使摄像机远离模型。移动摄像机的时候,根据指定的常理来减少mesh的顶点和面。然后释放原来的mesh。使用simplifiedMesh的克隆代替原mesh,并进行渲染。

         现在运行程序,可以使用+键来移动物体,并且在线框模式和填充模式之间转换,但离远了之后,几乎看不出模型是经过简化的。我们再添加一些文本来显示所渲染的面数和顶点数吧。添加字体变量:

private Microsoft.DirectX.Direct3D.Font font = null;

         在绘制文本前必须先初始化字体对象,在IntializeGraphics方法的LoadMesh之后,添加代码:

font = new Microsoft.DirectX.Direct3D.Font(device,new System.Drawing.Font("Arial", 14.0f ,FontStyle.Bold | FontStyle.Italic));

         可以根据自己的喜好来改变字体的类型和大小。现在可以绘制字体了。在调用DrawMesh方法之后,添加如下代码:

font.DrawText(null,string.Format("number vertices in mesh: {0}",mesh.NumberVertices),new Rectangle(10,10,0,0),DrawTextFormat.NoClip,Color.BlanchedAlmond);

font.DrawText(null,string.Format("number faces in mesh: {0}",mesh.NumberFaces),new Rectangle(10,30,0,0),DrawTextFormat.NoClip,Color.BlanchedAlmond);

         好了,现在可以方便的看到移动模型时顶点和面的数量都减少了。你应该可以获得如下的结果:

 

 

这个程序的主要缺点就在于我们不能恢复丢失的顶点。当然,我们可以出色的完成简化任务,但是,当我们需要再次近距离观察模型怎么办呢?没有RaiseVertices方法,调用ReduceVerctices方法,传入一个很大的顶点数也是没有用的。SimplificationMesh就是设计来简化mesh的,仅此而已,不能恢复。ProgressiveMesh对象就是用来处理这个问题的。

 

 

使用Progressive Meshes控制细节级别

有些情况下,你只需要简化mesh。但是,一味的简化,意味着无法再恢复对象的细节,而同时需要简化和增加对象细节的情况确是很常见的。我相信看到这里,你已经知道progressive mesh方法名字的来历了吧。

为了显示progressiveMesh方法的行为,我们将写一个和上一部分很类似的程序。这一次,我们不但可以简化mesh,还可以在摄像机靠近模型时,添加mesh的细节。还是从第五章的文件开始。

Progressivemesh类于Mesh类一样,都继承于BaseMesh类。与SimplificationMesh类相比,可以直接用progressiveMesh对象来绘制物体。这样,就可以用以下变量来代替Mesh对象了:

同样,你应该把原来所有的mesh变量都替换为这个变量。之后,更新LoadMesh方法,因为代码现在不能通过编译了。使用一个类似的方法;我们将在最后创建progressiveMesh对象。添加代码:

private void LoadMesh(string file)

{

     ExtendedMaterial[] mtrl;

     GraphicsStream adj;

     // Load our mesh

     using(Mesh mesh = Mesh.FromFile(file, MeshFlags.Managed, device, out mtrl)

     {

         // If we have any materials, store them

         if ((mtrl != null) && (mtrl.Length > 0))

         {

              meshMaterials = new Material[mtrl.Length];

              meshTextures = new Texture[mtrl.Length];

              // Store each material and texture

              for (int i = 0; i < mtrl.Length; i++)

              {

                   meshMaterials[i] = mtrl[i].Material3D;

                   if ((mtrl[i].TextureFilename != null) && (mtrl[i].TextureFilename != string.Empty))

                   {

                       // We have a texture, try to load it

                       meshTextures[i] = TextureLoader.FromFile(device, @"../../" + mtrl[i].TextureFilename);

                   }

              }

         }

         //clean our main mesh

         using(Mesh tempMesh = Mesh.Clean(mesh,adj,adj)

         {

              //create our progressive mesh

              progressiveMesh = new ProgressiveMesh(tempMesh,adj,null,1,MeshFlags.SimplifyVertex);

//set the initial mesh to the max

              progressiveMesh.NumberFaces = progressiveMesh.MaxFaces;

              progressiveMesh.NumberVertices = progressiveMesh.MaxVertices;

         }

     }

}

     注意,我们使用了两个临时mesh来创建progressiveMesh对象。其中一个clean过的mesh来完成真正的创建。对于progressiveMesh的构造函数来说,第四个参数是最重要的:根据所使用的MeshFlags选项,它是所创建mesh的顶点或面的最小值。显然,这只是一个近似值,即使不能把mesh简化到这个级别,这个方法还是会成功。

     你应该还注意到,我们马上就把面数和顶点数设置为了最大值。创建mesh并保留在简化状态(generating the mesh leaves it simplified)。设置progressiveMesh中面或顶点数中的任意一个,都可以在渲染时更改mesh的细节。因为我们想初始化时显示所有细节,自然把面和顶点值都设置为最大值。

     为了让程序通过编译,还需要修改DrawMesh中的DrawMesh方法:

     progressiveMesh.DrawSubset(i);

     现在运行程序,可以看到和原来一样的效果。显示了所有细节的模型不停旋转。现在来处理移动摄像机的键盘事件。这里的代码和之前simplification mesh例子里的很相似。先声明摄像机的位置变量以及每次移动的距离常量。

private float cameraPos = 580.0f ;

     private const int MoveAmount =  50;

     再次修改观察变换 以显示摄像机位置的更新。

     device.Transform.View = Matrix.LookAtLH(new Vector3(0,0,cameraPos), new Vector3(), new Vector3(0,1,0));

     最后,处理键盘事件:

protected override void OnKeyPress(KeyPressEventArgs e)

     {

         if(e.KeyChar == '+')

         {

              cameraPos += (MoveAmount * 2);

              progressiveMesh.NumberVertices = ((BaseMesh)progressiveMesh).NumberVertices - MoveAmount;

              progressiveMesh.NumberFaces = ((BaseMesh)progressiveMesh).NumberFaces - MoveAmount;

         }

         if(e.KeyChar == '-')

         {

              cameraPos -= (MoveAmount * 2);

              progressiveMesh.NumberVertices = ((BaseMesh)progressiveMesh).NumberVertices + MoveAmount;

              progressiveMesh.NumberFaces = ((BaseMesh)progressiveMesh).NumberFaces + MoveAmount;

         }

         if(e.KeyChar == 'w')

              device.RenderState.FillMode = FillMode.WireFrame;

         if(e.KeyChar == 's')

              device.RenderState.FillMode = FillMode.Solid;

              base.OnKeyPress (e);

         }

     运行程序来看看结果吧。另外,注意到,当需要获得面数和顶点数时,必须先把progressiveMesh对象转换为BaseMesh对象。应为progressiveMesh对象只有set属性,而get属性只在基类才有,所以这个转换是必须的。

     再添加一些文本来显示当前的面数和顶点数。为了不在重复,参照上一个例子中添加字体变量的代码。之后,添加如下代码:

font.DrawText(null,string.Format("number vertices in mesh: {0}",((BaseMesh)progressiveMesh).NumberVertices),

                   new Rectangle(10,10,0,0), DrawTextFormat.NoClip,Color.BlanchedAlmond);

font.DrawText(null,string.Format("number faces in mesh: {0}",((BaseMesh)progressiveMesh).NumberFaces),

                   new Rectangle(10,30,0,0),DrawTextFormat.NoClip,Color.BlanchedAlmond);

特别提示:储存多个细节级别

更常见的做法是储存多个细节级别的mesh,而不是使用一个单独的progressiveMesh对象来控制整个细节范围。如果你查找SDK中Progressive Mesh的示例,可以看到这种方法的实现。可以使用ProgressiveMesh对象上的TrimByFaces和TrimByVertices方法来改变细节的级别。

 

Rendering Patch Meshes

         简化mesh是一个常见的操作,但万一你获得的mesh太简单了怎办?虽然增加模型细节的情况不多见,但却是可能的,patch mesh就是用来完成这个任务的。大多数现代的三维建模程序都有patch mesh的影子,或其他一些高要求的图元,比如NURBS或细分面。

         本书的目的不是讲解patch mesh背后的原理。因此,我们所做的只是知道如何使用它,以及如何增加模型的细节级别。为此,我们将创建一个程序通过细分(subdivide)顶点创建一个复杂模型。

         好了,还是从第五章的程序开始。代码将会用到SDK中的两个模型(tiger.x 和cube.x),除此之外,还有个一小球体的模型。确保你把老虎模型的纹理一起拷贝到了当前目录下。添加如下变量:

    private float tessLevel = 
    
     1.0f
    ;

    private const float tessIncrement = 
    
     1.0f
    ;

    private string filename = @"../../sphere.x";

    private Microsoft.DirectX.Direct3D.Font font = null;

         先保存了当前的细分级别(tessellation level)(初始化为 1.0f ),同时也包括我们每次增加细节的增量。可以任意的修改这个常量,对这个例子来说,默认的值就可以了。另外我们还声明了当前模型的名字和渲染时使用的字体。

         还需要修改一下SetupCamera方法,上一次使用了一个非常大的模型,而这次的却小得多。做如下更新:

private void SetupCamera()

     {

         device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, this.Width / this.Height, 1.0f , 100.0f );

         device.Transform.View = Matrix.LookAtLH(new Vector3(0,0, 5.0f ), new Vector3(), new Vector3(0,1,0));

         //device.RenderState.Ambient = Color.DarkBlue;

         device.Lights[0].Type = LightType.Directional;

         device.Lights[0].Diffuse = Color.DarkKhaki;

         device.Lights[0].Direction = new Vector3(0, -1, -1);

         device.Lights[0].Commit();

         device.Lights[0].Enabled = true;

        }

         这里简单的设置了摄像机和灯光。虽然每一帧都这么做不是很高效,但为了简单明了,例子里暂时这么做。当然,还应该检查图形卡是否支持方向光,不过这里也省略了。在InitializeGraphics()里使用如下代码替代之前加载mesh的LoadMesh方法:

     CreatePatchMesh(filename,tessLevel);

     font = new Microsoft.DirectX.Direct3D.Font(device,new System.Drawing.Font("Arial", 14.0f ,FontStyle.Bold | FontStyle.Italic));

device.RenderState.FillMode = FillMode.WireFrame;

         显然,我们创建了patch mesh以及字体。同时把默认的现实模式设置为线框模式,这样能清楚的看到增加的三角形。还没有定义创建patch mesh的方法呢,添加代码:

private void CreatPatchMesh(string file,float tessLevel)

     {

         if(tessLevel < 1.0f )        //nothing to do

              return;

         if(mesh != null)

              mesh.Dispose();

         using(Mesh tempMesh = LoadMesh(file))

         {

              using(PatchMesh patch = PatchMesh.CreateNPatchMesh(tempMesh))

              {

                   //calculate the neew number of faces/vertices

                   int numberFaces = (int)(tempMesh.NumberFaces * Math.Pow(tessLevel,3));

                   int numberVerts = (int)(tempMesh.NumberVertices * Math.Pow(tessLevel,3));

                   mesh = new Mesh(numberFaces,numberVerts,MeshFlags.Managed | MeshFlags.Use32Bit,tempMesh.VertexFormat,device);

                   patch.Tessellate(tessLevel,mesh);

              }

         }

     }

         如果当前细分级别小于 1.0f (默认值),那么就什么都不作。否则,创建新的细分mesh。因为我们要取代已有的mesh,所以先调用dispose方法。当前的LoadMesh方法还不会返回任何值,更新代码:

private Mesh LoadMesh(string file)

     {

         ExtendedMaterial[] mtrl;

Mesh mesh = Mesh.FromFile(file, MeshFlags.Managed, device, out mtrl);

         if ((mtrl != null) && (mtrl.Length > 0))

         {

              meshMaterials = new Material[mtrl.Length];

              meshTextures = new Texture[mtrl.Length];

              // Store each material and texture

              for (int i = 0; i < mtrl.Length; i++)

              {

                   meshMaterials[i] = mtrl[i].Material3D;

                   if ((mtrl[i].TextureFilename != null) && (mtrl[i].TextureFilename != string.Empty))

                   {

                       // We have a texture, try to load it

                       meshTextures[i] = TextureLoader.FromFile(device, @"../../" + mtrl[i].TextureFilename);

                   }

              }

         }

         if((mesh.VertexFormat & VertexFormats.Normal) != VertexFormats.Normal)

         {

              Mesh tempMesh = mesh.Clone(mesh.Options.Value,mesh.VertexFormat | VertexFormats.Normal,device);

              tempMesh.ComputeNormals();

              mesh.Dispose();

              mesh = tempMesh;

         }

         return mesh;

}

这里没有什么新内容。我们创建mesh,如果他没有法线信息,我们就克隆mesh,计算法线。因为在对patch mesh细分时需要用到法线信息。最后,返回mesh。

         特别提示:使用using语句

         注意,我们在返回的meh和创建的patch mesh都使用了using语句,这将保证在完成操作之后自动释放资源。

         之后,使用新返回的mesh对象创建patch mesh。因为要把patch mesh细分为一个新的mesh,我们还需要知道这个mesh将有多少面和顶点。在计算了这2个值之后,终于可以创建新的细分之后的mesh了。注意到我使用了MeshFlags.Use32Bit标志。在细分之后,我们很有可能获得一个很大的mesh,必须确保可以支持大的mesh。现在可以运行程序来看看了,不过实在是有些单调。先添加一些文本吧:

font.DrawText(null, string.Format("Number Vertices: {0}/r/nNumber Faces: {1}",mesh.NumberVertices,mesh.NumberFaces),new Rectangle(10,10,0,0), DrawTextFormat.NoClip, Color.Black);

最后,添加键盘事件来控制增加或减少细分层次。

protected override void OnKeyPress(KeyPressEventArgs e)

{

    if (e.KeyChar == '+')

    {

        tessLevel += tessIncrement;

        CreatePatchMesh(filename, tessLevel);

    }

    if (e.KeyChar == '-')

    {

        tessLevel -= tessIncrement;

        CreatePatchMesh(filename, tessLevel);

    }

    if (e.KeyChar == 'c')

    {

        filename = @"../../cube.x";

        tessLevel = 
    
     1.0f
    ;

        CreatePatchMesh(filename, tessLevel);

    }

    if (e.KeyChar == 'o')

    {

        filename = @"../../sphere.x";

        tessLevel = 
    
     1.0f
    ;

        CreatePatchMesh(filename, tessLevel);

    }

    if (e.KeyChar == 't')

    {

        filename = @"../../tiger.x";

        tessLevel = 
    
     1.0f
    ;

        CreatePatchMesh(filename, tessLevel);

    }

    if (e.KeyChar == 'w')

        device.RenderState.FillMode = FillMode.WireFrame;

    if (e.KeyChar == 's')

        device.RenderState.FillMode = FillMode.Solid;

}

现在可以用“w”和“s”键来切换线框或实心模式,使用“c”切换到立法体模型,使用“t”切换到老虎模型,使用“o”回到球体。

需要源码的同志可以到这个地方去下http://bbs.gameres.com/showthread.asp?threadid=37943

DirectX11进阶1_混合与深度/模板(平面镜实现) 1 阅读详情

相关推荐

从人眼到Sensor:手把手教你理解并配置ISP中的CCM(以IMX415C为例)

本文以Sony IMX415C图像传感器为例,详细解析了ISP中颜色校正矩阵(CCM)的原理与配置方法。从人眼与传感器的色彩感知差异出发,通过实战案例演示如何采集数据、构建目标空间并求解优化CCM矩阵,最终实现精准的色彩还原。文章还提供了IMX415C的调优策略和常见问题排查指南,帮助开发者解决实际工程中的色彩校正难题。

weixin_30423977的博客 390

深入Managed DirectX9(一)

         Device类是DirectX里的所有绘图操作所必须的。可以把这个类假想为真实的图形卡。场景里所有其他图形对象都依赖于device。你的计算机里可以有一个到几个device,在Mnaged DirctX3D里,你可以控制任意多个device。  Device共有三个构造函数,现在我们只讨论其中的一个,但我们会在后边的内容里讨论其他的。先来看看具有如下函数签名的构造函数public

屋檐滴雨 1150

DirectX学习笔记(十):3D字体的实现及用ID3DXFont接口绘制文本

1

lishuzhai的专栏 8413

使用mesh渲染复杂模型(调用.x 文件)

前面我们学了使用简单的类库中的mesh建立了一个茶壶,但在实际操作中,我们的模型恐怕不只是茶壶这么简单吧?其实有很多复杂3d模型是通过建模软件制作的,如3dmax等。D3D支持.x模型文件,.x文件包括模型数据,如vertexbuffer,indexbuffer,以及材质等信息。而且材质信息还可能包括纹理等信息,在获取这些文件的同时,你也同时可以获得HighLevel Shader Languag

Shutely@Xu.Dening的专栏 1977

fibplus-8.0.0.zip

FIBPlus 是一套面向 Delphi / C++Builder 的 Firebird、InterBase 数据库访问组件,特点是直接走原生客户端 API,不经 BDE/ODBC,速度快且可控性强。8.0.0 版本主要适配 Delphi 2009 及以后的版本(Delphi 6–2007 需用 7.9.x),核心组件包括 TpFIBDatabase、TpFIBTransaction、TpFIBDataSet 等,支持精细事务管理、本地缓存、BLOB 处理和备份恢复等数据库服务。该库原为 Devrace 的商业组件,现由社区在 GitHub 的 madorin/fibplus 项目开源维护,建议从官方仓库获取源码而非第三方网盘压缩包。安装时解压后用对应版本的工程组(10.4+ 统一为 `FIB.groupproj`)Build 全部包,再 Install `dclFIB` 并在 Library 路径加入 Source 目录即可。新项目中若需官方技术支持,也可考虑 FireDAC、IBDAC 等更现代的替代方案。

基于K8S + apisix/istio 实现云原生模块化微服务.自带代码生成器,能够生成对表的增删改查的逻辑代码

基于K8S + apisix/istio 实现云原生模块化微服务.自带代码生成器,能够生成对表的增删改查的逻辑代码.是标准Maven项目,只依赖springboot,没有hibernate,struts,ibatis,数据库调优可以使用druid输出慢sql,比分析xml中的语句更直观,springrain所有的sql语句都使用Finder封装管理,只要查看Finder的引用即可.

DirectX渲染状态设置

1)设置着色模式: SetRenderState( D3DRS_SHADEMODE, D3DSHADE_FALT ) // 设置平面着色模式 SetRenderState ( D3DRS_SHADEMODE, D3DSHADE_GOURAUD ) // 设置格劳德着色模式 2)设置多边形填充模式 SetRenderState( D3DRS_FILLMODE, D3DFILL_POINT

lbq09047128的专栏 1397

工艺部2026年终总结及2027工作规划PPT.pptx

制造业生产、工艺、设备、质量全套 PPT 资料,包含月度经营复盘、季度数据分析、部门年终总结规划、产线与检验规范、TPM 设备保全、质量意识、质量总监高阶培训等课件。内容兼顾经营指标偏差分析、述职汇报、现场制度宣贯、岗位技能教学。 适合操作工、检验员、设备维保员、工艺 / 品质 / 设备工程师、生产主管、各部门部长、质量总监、厂长、内部培训师、精益专员使用,覆盖一线执行、骨干分析、部门负责人述职、高管进阶全层级,可直接用于工厂汇报、内部培训、述职复盘。

DirectX三维地

游戏开发笔记四十八浅墨DirectX教程十六三维地形系统的实现上个星期浅墨写的介绍三维摄像机的文章 提问者:haogreey(ID:110140) | 悬赏 0.0 希赛币 | 回答数:0 | 关注度:4 | 提问时间:2014-07-22 游戏开发笔记四十八 浅墨DirectX教程十六 三维地形系统的实现   上个星期浅墨写的介绍三维摄像机的文章和示例程序放

linuxheik的专栏 954

wordbuddy破甲经验分享

wordbuddy破甲经验分享

双闭环PWM整流器VOC控制 +SVPWM调制仿真(Simulink仿真实现)

内容概要:本文详细介绍了一种基于Simulink的双闭环PWM整流器采用虚拟同步发电机控制(VOC)策略与空间矢量脉宽调制(SVPWM)技术的仿真模型。该模型在dq同步旋转坐标系下构建电压定向控制系统,实现了电压外环与电流内环的双闭环控制结构,重点阐述了VOC控制原理、SVPWM调制算法的实现方法及其在Simulink环境中的模块化搭建过程。通过该仿真平台,能够有效实现单位功率因数运行、直流母线电压稳定控制以及优异的动态响应性能,适用于电力电子变换器、新能源并网系统及电机驱动等领域的控制策略验证与性能评估。; 适合人群:电气工程、自动化、电力电子与电力传动等相关专业的高年级本科生、研究生,以及从事电力电子系统仿真、新能源并网控制研究的科研人员和技术工程师。; 使用场景及目标:①深入理解三相PWM整流器在dq坐标系下的数学建模与控制机理;②掌握VOC控制策略的核心思想及其相较于传统矢量控制的优势;③学习SVPWM调制技术的实现流程与Simulink建模技巧;④通过仿真实验验证双闭环控制系统的静态精度与动态稳定性,提升对先进电力电子控制系统的分析与设计能力。; 阅读建议:建议结合电力电子技术、现代控制理论和电机控制相关基础知识进行学习,按照仿真模型的结构逐步分析各功能模块的信号流向与参数配置,重点关注锁相环(PLL)、坐标变换、PI控制器设计及SVPWM模块的实现细节,并可通过调整控制参数观察系统响应变化,以深化对控制策略动态特性的理解。

【Visual C++】游戏开发笔记四十 浅墨DirectX教程之八 绘制真实质感的三维世界:光照与材质专场...

本系列文章由zhmxy555(毛星云)编写,转载请注明出处。 文章链接:http://blog.youkuaiyun.com/zhmxy555/article/details/8499438 作者:毛星云(浅墨)邮箱:happylifemxy@163.com 本篇文章里,我们对Direct3D之中固定功能流水线中的3D光照编程相关的知识进行了详尽的剖析,文章末尾依旧是提供文章配套的详细注释的demo...

轻轻草原 691

储能双向Buck-Boost+模型预测电流控制+电压下垂控制仿真【附参考文献】(Simulink仿真实现)

内容概要:本文系统介绍了基于Simulink平台构建的储能双向Buck-Boost变换器仿真模型,融合模型预测电流控制与电压下垂控制策略,面向锂电池储能系统的高效充放电管理。该模型深入实现了双闭环控制架构的设计与动态性能分析,涵盖系统建模、关键控制算法实现及稳定性验证,并配套提供参考文献以支撑理论深度与技术复现性。资源包还整合了多种典型电力电子拓扑的仿真案例,如各类DC-DC变换器、谐振变换器、PWM整流器等,充分体现了其在新能源发电、微电网能量调度及电力系统稳定控制中的广泛应用价值和技术延展性。; 适合人群:适用于电气工程、自动化、电力电子及相关专业的高校研究生、科研人员以及从事能源系统仿真与控制设计的工程技术人员;要求具备一定的Simulink/MATLAB操作能力及电力电子与自动控制基础知识;; 使用场景及目标:①深入理解双向Buck-Boost电路在储能系统中的工作机理与能量双向流动控制方法;②掌握模型预测控制(MPC)与下垂控制在实际电力变换系统中的建模流程与参数整定技巧;③为科研课题、学位论文或工程项目提供高可靠性、可复用的仿真原型与技术参考方案; 阅读建议:建议结合文中列出的参考文献与网盘提供的完整仿真资源,按照目录结构循序渐进地学习各模块案例,重点剖析控制逻辑搭建、调节器设计与系统动态响应特性,通过动手仿真与参数调试深化对控制策略性能与鲁棒性的理解。

DirectX11编程5 渲染动态顶点

环境:VS2017  语言:C++   总起: 第六章剩下的Demo差别不是很大,基本没什么新的知识点,不过我都将其实现了,今天就专门针对Waves这个Demo说一些特别的东西。   工程在此:https://github.com/anguangzhihen/Dx11。   如果遇到工程不能运行的情况,请留言,我会尽快查明原因。   Waves Deme: 该Demo主要是实现...

暗光之痕的博客 956

产业园区在推动科技成果落地时,如何高效匹配企业与技术供给方.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

全桥LLC谐振(变频+移相混合控制)变换器闭环仿真模型(Simulink仿真实现)

内容概要:本文详细介绍了基于Simulink平台构建的全桥LLC谐振变换器闭环仿真模型,采用变频控制与移相控制相结合的混合调制策略,实现高效电能转换与高精度输出稳压。模型完整涵盖了系统建模、谐振腔参数设计、软开关技术实现、双闭环控制系统(如电压外环与频率/相位内环)设计及仿真验证全过程,重点突出零电压开通(ZVS)与零电流关断(ZCS)的实现机制,以显著降低开关损耗,提升变换器效率与动态响应性能。配套资源包含完整的Simulink仿真文件、详细的参数设计报告及核心参考文献,为深入理解LLC谐振变换器的工作机理、控制策略优化及其在开关电源、新能源发电等领域的工程应用提供了坚实的技术支撑。; 适合人群:具备电力电子技术、自动控制理论基础,从事高频开关电源、新能源变换器、车载充电机或相关方向研究的研究生、科研人员及电气工程师。; 使用场景及目标:①系统学习全桥LLC谐振变换器的精确建模与仿真方法;②掌握变频+移相混合控制策略的设计原理与实现技巧;③开展高效率、高功率密度电源变换器的科研攻关与工程项目开发;④深入理解软开关技术在实际电路中的应用与优势; 阅读建议:建议结合所提供的仿真模型与设计报告进行动手实践,重点分析控制器参数整定过程、谐振元件(Lr, Cr, Lm)的参数匹配关系,并仔细观察仿真波形,以深刻把握系统的稳态特性、瞬态响应能力及控制稳定性,从而全面提升对复杂谐振变换器系统的设计与分析水平。

DirectX Directdraw 用一种 颜色 填充 满屏 画面

<br />//平时填充画面都是黑色,其实directdraw 刷新画面 填充 背景等可以一种颜色,R(红色) G(绿色) B(蓝色)皆可 <br /> DDPIXELFORMAT ddpf;<br /> <br /> ddpf.dwSize = sizeof(ddpf);<br /> if (SUCCEEDED(g_lpddsBack->GetPixelFormat(&ddpf)))  //得到点格式<br /> {<br />  DDBLTFX ddbltfx;<br />  //ddbltfx.dwS

Done Lin的专栏 1896

STM32CubeMX最新版下载安装全攻略(附官网访问问题解决方案)

本文提供了STM32CubeMX最新版的详细下载与安装指南,并针对国内开发者常见的官网访问缓慢、注册验证邮件延迟等问题,给出了实用的解决方案和备选策略。通过清晰的步骤解析,帮助用户快速部署这一强大的STM32图形化配置工具,从而高效启动嵌入式开发项目。

weixin_28256233的博客 193
上一篇: 【翻译】Managed DirectX(第八章)
下一篇: 使用Managed DirectX编写游戏(-)
soilwork
博客等级 码龄23年 290粉丝 116原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值