Table of Contents

用代码创建模型

初级 程序员

你可以在运行时的脚本中创建模型。有几种不同的方式可以做到这一点,包括:

  • 从资产创建模型
  • 使用内置几何图元(例如球体或立方体)创建程序化模型
  • 实例化包含模型的预制体(参阅使用预制体)

从资产创建模型

  1. 创建一个新的空同步脚本。完整说明请参阅创建脚本。

    创建脚本

  2. 在脚本中,使用模型的资产 URL(Asset URL)加载它。例如:

    // 创建一个新实体并将其添加到场景中。
    var entity = new Entity();
    SceneSystem.SceneInstance.RootScene.Entities.Add(entity);
    
    // 添加一个包含在游戏文件中的模型。
    var modelComponent = entity.GetOrCreate<ModelComponent>();
    modelComponent.Model = Content.Load<Model>("MyFolder/MyModel");
    
    Tip

    要查找模型的资产 URL,请在**资产视图(Asset View)**中将鼠标悬停在该模型上。

    (获取资产 URL

  3. 将该脚本作为脚本组件添加到场景中的任意实体上。使用哪个实体都可以。操作说明请参阅使用脚本。

    向实体添加脚本组件

  4. 在资产视图中,右键单击你想要在运行时创建的模型,然后选择 Include in build as root asset(作为根资产包含在构建中)。

    作为根资产包含在构建中

    这样可以确保脚本在运行时能使用该资产。更多信息请参阅资产编译。

创建程序化模型

  1. 创建一个新的空同步脚本。完整说明请参阅创建脚本。

    添加新脚本

  2. 将该脚本作为脚本组件添加到场景中的任意实体上。使用哪个实体都可以。操作说明请参阅使用脚本。

    向实体添加脚本组件

  3. 在脚本中,实例化一个空实体和一个空模型。例如:

    // 创建实体并将其添加到场景中。
    var entity = new Entity();
    SceneSystem.SceneInstance.RootScene.Entities.Add(entity);
    
    // 创建模型并将其赋给模型组件。
    var model = new Model();
    entity.GetOrCreate<ModelComponent>().Model = model;  
    
  4. 在脚本中,使用内置几何图元(例如球体或立方体)创建程序化模型。例如:

    // 使用几何图元(例如球体或立方体)添加一个或多个网格。
    var meshDraw = GeometricPrimitive.Sphere.New(GraphicsDevice).ToMeshDraw();
    
    var mesh = new Mesh { Draw = meshDraw }; 
    model.Meshes.Add(mesh);
    
    Note

    要使用上面的代码,请确保在脚本顶部添加 using Stride.Extensions。

    也可以使用你自己的顶点缓冲区和索引缓冲区创建网格。例如:

    // 使用自己的顶点缓冲区和索引缓冲区创建网格。
    
    mesh = new Mesh { Draw = new MeshDraw { /* 顶点缓冲区和索引缓冲区设置 */ } };
    model.Meshes.Add(mesh);
    
  5. 下面是一个更完整的示例,用于绘制一个自定义三角形。

    var vertices = new VertexPositionTexture[3];
    vertices[0].Position = new Vector3(0f,0f,1f);            
    vertices[1].Position = new Vector3(0f,1f,0f);
    vertices[2].Position = new Vector3(0f,1f,1f);
    var vertexBuffer = Stride.Graphics.Buffer.Vertex.New(GraphicsDevice, vertices,
                                                         GraphicsResourceUsage.Dynamic);
    int[] indices = { 0, 2, 1 };
    var indexBuffer = Stride.Graphics.Buffer.Index.New(GraphicsDevice, indices);
    
    var customMesh = new Stride.Rendering.Mesh
    { 
        Draw = new Stride.Rendering.MeshDraw
        { 
            /* 顶点缓冲区和索引缓冲区设置 */
            PrimitiveType = Stride.Graphics.PrimitiveType.TriangleList,
            DrawCount = indices.Length,
            IndexBuffer = new IndexBufferBinding(indexBuffer, true, indices.Length),
            VertexBuffers = new[] { new VertexBufferBinding(vertexBuffer, 
                                      VertexPositionTexture.Layout, vertexBuffer.ElementCount) },
        }
    };            
    // 将网格添加到模型中
    model.Meshes.Add(customMesh);
    
Note

有关如何设置顶点缓冲区和索引缓冲区的更多信息,请参阅绘制顶点。

最后,你需要为模型指定一个或多个材质。有两种做法。

选项 1:在代码中加载材质

  1. 在代码中,加载一个或多个材质并将它们添加到模型中。由于模型可以使用多个材质(模型中的每个网格对应一个),请使用 Mesh.MaterialIndex 指定列表中的哪些材质用于哪些网格。

    例如:

    // 添加一个或多个材质。由于模型可能需要多个材质(每个网格一个),
    // Mesh.MaterialIndex 用于指定列表中的哪个材质用于哪个网格。
    
    Material material = Content.Load<Material>("MyFolder/MyMaterial");
    model.Materials.Add(material);
    
  2. 在资产视图中,右键单击脚本使用的每个材质资产,然后选择 Include in build as root asset。

    作为根资产包含在构建中

    这样可以确保脚本在运行时能使用该资产。更多信息请参阅在代码中使用资产。

选项 2:在代码中创建新材质

例如:

// 创建材质(例如漫反射颜色为红色)。
var materialDescription = new MaterialDescriptor
{
    Attributes =
    {
        DiffuseModel = new MaterialDiffuseLambertModelFeature(),
        Diffuse = new MaterialDiffuseMapFeature(new ComputeColor { Key = MaterialKeys.DiffuseValue })
    }
};
var material = Material.New(GraphicsDevice, materialDescription);
material.Passes[0].Parameters.Set(MaterialKeys.DiffuseValue, Color.Red);
model.Materials.Add(0, material);

另请参阅