Skip to content

It would be nice to add a guide on primitive models. #526

Description

@w0wca7a

In Stride we can create our own Procedural Models's like in this example
I think it might be a good idea to add a page about custom primitives. Maybe here or as a separate page?

using Stride.Assets.Models;
using Stride.Core;
using Stride.Core.Assets;
using Stride.Core.Mathematics;
using Stride.Graphics;
using Stride.Rendering.ProceduralModels;
using System;

[DataContract("PrismModel")]
[Display("Prism")]
public class Prism : PrimitiveProceduralModelBase
{
    public float Height { get; set; } = 1f;

    protected override GeometricMeshData<VertexPositionNormalTexture> CreatePrimitiveMeshData()
    {
        float h = MathF.Sqrt(3f) / 2f;
        float halfH = Height / 2f;

        // Front face (z = -halfH)
        Vector3 p0 = new(-0.5f, -h / 3f, -halfH);
        Vector3 p1 = new( 0.5f, -h / 3f, -halfH);
        Vector3 p2 = new( 0.0f,  2f * h / 3f, -halfH);

        // Back face (z = +halfH)
        Vector3 p3 = new(-0.5f, -h / 3f,  halfH);
        Vector3 p4 = new( 0.5f, -h / 3f,  halfH);
        Vector3 p5 = new( 0.0f,  2f * h / 3f,  halfH);

        // 2 triangles × 3 + 3 quads × 6 = 6 + 18 = 24 vertices
        VertexPositionNormalTexture[] vertices = new VertexPositionNormalTexture[24];
        int[] indices = new int[24];

        int v = 0;
        int i = 0;

        void AddTriangle(Vector3 a, Vector3 b, Vector3 c)
        {
            var n = Vector3.Normalize(Vector3.Cross(b - a, c - a));
            vertices[v + 0] = new(a, n, new Vector2(0,    1));
            vertices[v + 1] = new(b, n, new Vector2(1,    1));
            vertices[v + 2] = new(c, n, new Vector2(0.5f, 0));
            indices[i++] = v; indices[i++] = v+1; indices[i++] = v+2;
            v += 3;
        }

        void AddQuad(Vector3 a, Vector3 b, Vector3 c, Vector3 d)
        {
            var n = Vector3.Normalize(Vector3.Cross(b - a, c - a));
            vertices[v + 0] = new(a, n, new Vector2(0, 0));
            vertices[v + 1] = new(b, n, new Vector2(1, 0));
            vertices[v + 2] = new(c, n, new Vector2(1, 1));
            vertices[v + 3] = new(d, n, new Vector2(0, 1));
            indices[i++] = v;   indices[i++] = v+1; indices[i++] = v+2;
            indices[i++] = v+2; indices[i++] = v+3; indices[i++] = v;
            v += 4;
        }

        // Front face — normal points toward -Z (CCW when viewed from the front)
        AddTriangle(p0, p1, p2);

        // Back face — normal points toward +Z (CW when viewed from the front = CCW when viewed from the back)
        AddTriangle(p3, p5, p4);

        // Side faces (CCW from outside)
        AddQuad(p0, p3, p4, p1); // bottom
        AddQuad(p1, p4, p5, p2); // right
        AddQuad(p2, p5, p3, p0); // left

        return new GeometricMeshData<VertexPositionNormalTexture>(vertices, indices, isLeftHanded: false)
        {
            Name = "Prism"
        };
    }
}

Then we can select in the procedural model type

Image

And for asset of this model we can create our Prism asset like in custom asset manual. In that case, the .sdtpl template would look like this:

!TemplateAssetFactory
Id: A1B2C3D4-E5F6-7890-ABCD-EF1234567890
AssetTypeName: ProceduralModelAsset
Name: Prism
Scope: Asset
Description: A triangular prism procedural model asset
Group: Model
Order: 25
DefaultOutputName: Prism
FactoryTypeName: ProceduralModelPrismFactory

add factory to procedural model file:

....
//code of Prism class
        return new GeometricMeshData<VertexPositionNormalTexture>(vertices, indices, isLeftHanded: false)
        {
            Name = "Prism"
        };
    }
}

public class ProceduralModelPrismFactory : AssetFactory<ProceduralModelAsset>
{
    public override ProceduralModelAsset New()
    {
        return new ProceduralModelAsset
        {
            Type = new Prism
            {
                Height = 1f
            }
        };
    }
}

And our model is available in Assets

Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions