stride3d/stride-community-toolkit

Example: GalaxyCreator - Add as example

オープン

#264 opened on 2025/03/19

 (0 件のコメント) (0 件のリアクション) (0 人の担当者)C# (31 件のフォーク)auto 404
examplegood first issuehelp wanted

Repository metrics

Stars
 (125 個のスター)
PR merge metrics
 (PR metrics pending)

説明

Source: https://gist.github.com/w0wca7a/202ccfcdf1b9e937fbfec599f251e90b

using System;
using System.Collections.Generic;
using Stride.Core.Mathematics;
using Stride.Engine;
using Stride.Core;
using Stride.Rendering;
using Stride.Core.Annotations;
using Stride.Rendering.ProceduralModels;

public class GalaxyCreator : StartupScript
{
    [DataMember]
    [DataMemberRange(10, 40, 1, 15, 0)]
    public int SphereRadiusFactor { get; set; } = 20; //10~30
    [DataMember]
    public int StarsCount { get; set; } = 8000;

    [DataMember]
    public int ArmsCount { get; set; } = 2;
    [DataMember]
    [DataMemberRange(0,5,0.5,1,1)]
    public float TwistValue { get; set; } = 4f;
    [DataMember]
    public List<Material> MaterialsList { get; set; } = [];
    [DataMember]
    public bool MaterialInstancePerObject { get; set; } = false;
    private Vector2[] points; // All objects will place in one plane, we use only two coordinates
    private Material[] materials; // Array for random using materials
    private static Vector2[] GenerateGalaxy(int numOfStars, int numOfArms, float spin, double armSpread, double starsAtCenterRatio)
    {
        List<Vector2> result = new(numOfStars);
        for (int i = 0; i < numOfArms; i++)
        {
            result.AddRange(ArmsCreator(numOfStars/numOfArms, i/numOfArms, spin, armSpread, starsAtCenterRatio));
        }
        return [.. result];
    }

    private static Vector2[] ArmsCreator(int numOfStars, float rotation, float spin, double armSpread, double starsAtCenterRatio)
    {
        Vector2[] result = new Vector2[numOfStars];
        Random r = new();

        for (int i = 0; i < numOfStars; i++)
        {
            double part = i/numOfStars;
            part = Math.Pow(part, starsAtCenterRatio);

            float distanceFromCenter = (float)part;
            double position = (part * spin + rotation) * Math.PI * 2;

            double xBeating = (Dispersal(r.NextDouble()) - Dispersal(r.NextDouble())) * armSpread;
            double yBeating = (Dispersal(r.NextDouble()) - Dispersal(r.NextDouble())) * armSpread;

            float resultX = (float)Math.Cos(position) * distanceFromCenter / 2 + 0.5f + (float)xBeating;
            float resultY = (float)Math.Sin(position) * distanceFromCenter / 2 + 0.5f + (float)yBeating;

            result[i] = new Vector2(resultX, resultY);
        }

        return result;
    }

    private static double Dispersal(double x)
    {
        double value = Math.Pow(x - 0.5, 3) * 4 + 0.5d;
        return Math.Max(Math.Min(1, value), 0);
    }

    private Model MModel()
    {
        var sphere = new SphereProceduralModel() { Radius = 0.02f / SphereRadiusFactor };
        var model = sphere.Generate(Services);
        return model;
    }

    public override void Start()
    {
        MaterialInstance materialInstance = null;
        // Initialization of the script.
        if (MaterialsList.Count != 0) { materials = [.. MaterialsList]; }
        else { return; } // If no materials skip generation

        if (!MaterialInstancePerObject)
        {
            materialInstance = new()
            {
                Material = materials[new Random().Next(materials.Length)]
            };
        }
        points = GenerateGalaxy(StarsCount, ArmsCount, TwistValue, 0.1d, 1);
        // fine looking, but need more VRAM -  GenerateGalaxy(80000, 2, 3f, 0.1d, 3); 
        for (int i = 0; i < points.Length; i++)
        {
            Entity e = new(name: i.ToString(), new Vector3(new Vector2(points[i].X,
                points[i].Y), 0.0f), rotation: null, scale: null);
            //Log.Debug(e.Name);
            SceneSystem.SceneInstance.RootScene.Entities.Add(e);
            //Entity.Scene.Entities.Add(e);
            if (MaterialInstancePerObject)
            {
                materialInstance = new()
                {
                    Material = materials[new Random().Next(materials.Length)]
                };
            }
            var Mats = MModel();
            Mats.Materials.Insert(0, materialInstance);
            //MModel().Materials.Add(materialInstance); 
            e.GetOrCreate<ModelComponent>().Model = Mats;
        }
    }
}

コントリビューターガイド