Skip to main content
added 190 characters in body
Source Link
thalm
  • 257
  • 1
  • 11

EDIT: Full sources - including model update per frame - are now available here: github.com/tebjan/StrideProceduralModel

Code of the custom model:

Code of the custom model:

EDIT: Full sources - including model update per frame - are now available here: github.com/tebjan/StrideProceduralModel

Code of the custom model:

Source Link
thalm
  • 257
  • 1
  • 11

You can also make your own procedural model by inheriting from PrimitiveProceduralModelBase. This has several advantages:

  • Write less code
  • Available in Game Studio with preview and gizmo in scene editor
  • Properties (including material) are editable in Game Studio
  • Auto-generate tangents and bi-tangents required for advanced lighting
  • Auto-generate bounding box and bounding sphere for correct shadow map bias
  • Auto-generate additional texture coordinate channels
  • Model space position offset
  • Better upload/render performance due to correct data types

enter image description here

The workflow to add the model in Game Studio is then:

  • Add any procedural model (Cube, Plane, etc.)
  • Change the dropdown to your custom procedural model implementation

The workflow in code or script is:

  • Add an instance of the script below to any entity

Code of the custom model:

[DataContract("MyProceduralModel")]
[Display("MyModel")] // This name shows up in the procedural model dropdown list
public class MyProceduralModel : PrimitiveProceduralModelBase
{
    // A custom property that shows up in Game Studio
    /// <summary>
    /// Gets or sets the size of the model.
    /// </summary>
    public Vector3 Size { get; set; } = Vector3.One;

    protected override GeometricMeshData<VertexPositionNormalTexture> CreatePrimitiveMeshData()
    {
        // First generate the arrays for vertices and indices with the correct size
        var vertexCount = 4;
        var indexCount = 6;
        var vertices = new VertexPositionNormalTexture[vertexCount];
        var indices = new int[indexCount];

        // Create custom vertices, in this case just a quad facing in Y direction
        var normal = Vector3.UnitZ;
        vertices[0] = new VertexPositionNormalTexture(new Vector3(-0.5f, 0.5f, 0) * Size, normal, new Vector2(0, 0));
        vertices[1] = new VertexPositionNormalTexture(new Vector3(0.5f, 0.5f, 0) * Size, normal, new Vector2(1, 0));
        vertices[2] = new VertexPositionNormalTexture(new Vector3(-0.5f, -0.5f, 0) * Size, normal, new Vector2(0, 1));
        vertices[3] = new VertexPositionNormalTexture(new Vector3(0.5f, -0.5f, 0) * Size, normal, new Vector2(1, 1));

        // Create custom indices
        indices[0] = 0;
        indices[1] = 1;
        indices[2] = 2;
        indices[3] = 1;
        indices[4] = 3;
        indices[5] = 2;

        // Create the primitive object for further processing by the base class
        return new GeometricMeshData<VertexPositionNormalTexture>(vertices, indices, isLeftHanded: false) { Name = "MyModel" };
    }
}

Code of the script that adds the model by code:

public class AddMyModelScript : AsyncScript
{
    // Declared public member fields and properties will show in the game studio
    public float RotationSpeed { get; set; } = 1;

    public override async Task Execute()
    {
        // Setup the custom model
        await CreateMyModel();

        while (Game.IsRunning)
        {
            // Do stuff every new frame
            Entity.Transform.Rotation *= Quaternion.RotationY(MathUtil.DegreesToRadians(RotationSpeed));

            await Script.NextFrame();
        }
    }

    async Task CreateMyModel()
    {
        // The model classes
        var myModel = new MyProceduralModel();
        var model = new Model();
        var modelComponent = new ModelComponent(model);

        // Generate the procedual model
        myModel.Generate(Services, model);

        // Add a meterial
        var material = Content.Load<Material>("MyModel Material");
        model.Add(material);

        // Add everything to the entity
        Entity.Add(modelComponent);
    }
}