stride3d / stride

Stride Game Engine (formerly Xenko)
https://stride3d.net
MIT License
6.45k stars 933 forks source link

LOD Epic #37

Open xen2 opened 6 years ago

xen2 commented 6 years ago

Nothing decided yet on that front. It seems like EmptyKeys have already something, maybe he could quickly describe what he did?

EmptyKeys commented 6 years ago

Hi, I created very simple ModelLodComponent for my game, no fancy cross fade effects, it's just switching model based on distance from camera.

using EmptyKeys.CoG.Input;
using Xenko.Core;
using Xenko.Core.Annotations;
using Xenko.Core.Mathematics;
using Xenko.Engine;
using Xenko.Rendering;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EmptyKeys.CoG.Components
{
    public class ModelLodComponent : AsyncScript
    {
        private readonly int updateFrequency = 10;
        private readonly float lod1DistanceSqrd = 30 * 30;
        private readonly float lod2DistanceSqrd = 45 * 45;
        private readonly float lod3DistanceSqrd = 60 * 60;

        private int currentUpdateFrame;

        [DataMemberCustomSerializer]
        [DataMember(10)]
        public Model ModelLod0 { get; set; }        

        [DataMemberCustomSerializer]
        [DataMember(20)]
        public Model ModelLod1 { get; set; }

        [DataMemberCustomSerializer]
        [DataMember(30)]
        public Model ModelLod2 { get; set; }

        [DataMemberCustomSerializer]
        [DataMember(40)]
        public Model ModelLod3 { get; set; }

        public ModelComponent ModelComponent { get; set; }

        public bool Enabled { get; set; }

        public override async Task Execute()
        {
            Random random = new Random();
            currentUpdateFrame = random.Next(0, 11);
            while (Game.IsRunning)
            {
                await Script.NextFrame();

                if (!Enabled)
                {
                    continue;
                }

                if (updateFrequency > currentUpdateFrame)
                {
                    currentUpdateFrame++;
                    continue;
                }

                currentUpdateFrame = 0;
                float distanceSqrd = Vector3.DistanceSquared(this.Entity.Transform.Position, InputHelper.Instance.FreeCameraViewPosition);
                if (distanceSqrd < lod1DistanceSqrd)
                {
                    ModelComponent.Model = ModelLod0;
                }
                else if (distanceSqrd >= lod1DistanceSqrd && distanceSqrd < lod2DistanceSqrd && ModelLod1 != null)
                {
                    ModelComponent.Model = ModelLod1;
                }
                else if (distanceSqrd >= lod2DistanceSqrd && distanceSqrd < lod3DistanceSqrd && ModelLod2 != null)
                {
                    ModelComponent.Model = ModelLod2;
                }
                else if (distanceSqrd >= lod3DistanceSqrd && ModelLod3 != null)
                {
                    ModelComponent.Model = ModelLod3;
                }                                
            }
        }
    }
}
xen2 commented 6 years ago

Thanks for sharing! While at some point we might want to have a LOD system more integrated with engine/editor, I like the idea of adding such a script in the asset templates so that people can still use LOD in the meantime.