| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Windows.Controls;
- using Microsoft.Xna.Framework;
- using Microsoft.Xna.Framework.Graphics;
- using Microsoft.Xna.Framework.Input;
- using MonoGame.WpfCore.MonoGameControls;
- using MonoScene.Graphics;
- using SharpGLTF.Validation;
- namespace MonoGameViewer
- {
- public class MainScene : MonoGameViewModel
- {
- #region data
- bool _IsAssimp;
- SharpGLTF.Schema2.ModelRoot _Model;
- DeviceModelCollection _ModelTemplate;
- BoundingSphere _ModelSphere;
- private bool _UseClassicEffects;
- private ModelInstance _ModelInstance;
- private Quaternion _Rotation = Quaternion.Identity;
- private float _Zoom = 2.5f;
- private readonly GlobalLight _GlobalLight = new GlobalLight();
- private readonly PunctualLight[] _PunctualLights = new PunctualLight[] { PunctualLight.CreateDefault(0), PunctualLight.CreateDefault(1), PunctualLight.CreateDefault(2) };
- #endregion
- #region properties
- [PropertyTools.DataAnnotations.Description("If enabled, it will use BasicEffect and SkinnedEffect.\r\n⚠ Switching this checkbox will reload the model!")]
- public bool UseClassicEffects
- {
- get => _UseClassicEffects;
- set
- {
- if (value == _UseClassicEffects) return;
- _UseClassicEffects = value;
- _ProcessModel();
- }
- }
- [PropertyTools.DataAnnotations.Browsable(false)]
- public GlobalLight GlobalLight => _GlobalLight;
- [PropertyTools.DataAnnotations.Browsable(false)]
- public PunctualLight[] PunctualLights => _PunctualLights;
- #endregion
- #region API
- public void LoadModel(string filePath)
- {
- try
- {
- var fp = filePath.ToLower();
- if (fp.EndsWith(".zip"))
- {
- _Model = SharpGLTF.IO.ZipReader.LoadModelFromZip(filePath, ValidationMode.TryFix);
- _IsAssimp = false;
- }
- else if (fp.EndsWith(".glb") || fp.EndsWith(".gltf"))
- {
- _Model = SharpGLTF.Schema2.ModelRoot.Load(filePath, ValidationMode.TryFix);
- _IsAssimp = false;
- }
- else if (fp.EndsWith(".obj") || fp.EndsWith(".blend") || fp.EndsWith(".fbx"))
- {
- _IsAssimp = true;
- var assimpFactory = new MonoScene.Graphics.Pipeline.AssimpModelFactory(GraphicsDevice);
- assimpFactory.UseBasicEffects = _UseClassicEffects;
- _ModelTemplate = assimpFactory.LoadModel(filePath);
- _ModelSphere = _ModelTemplate.DefaultModel.ModelBounds;
- if (_ModelSphere.Radius == 0) throw new ArgumentException();
- _ModelInstance = null;
- }
- }
- catch(Exception ex) { System.Windows.MessageBox.Show(ex.Message, "Error", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error); return; }
-
- _ProcessModel();
- }
- private void _ProcessModel()
- {
- if (_IsAssimp) return;
- if (_Model == null) return;
- if (_ModelTemplate != null) { _ModelTemplate.Dispose(); _ModelTemplate = null; }
- var gltfFactory = new MonoScene.Graphics.Pipeline.GltfModelFactory(this.GraphicsDevice);
- gltfFactory.UseBasicEffects = _UseClassicEffects;
- _ModelTemplate = gltfFactory.ReadModel(_Model);
- _ModelSphere = _ModelTemplate.DefaultModel.ModelBounds;
- _ModelInstance = null;
- GC.Collect();
- }
- public override void UnloadContent()
- {
- base.UnloadContent();
- _ModelTemplate?.Dispose(); _ModelTemplate = null;
- }
- public void RotateModel(float x, float y)
- {
- _Rotation = Quaternion.CreateFromYawPitchRoll(x, y, 0) * _Rotation;
- _Rotation.Normalize();
- }
- public void ZoomModel(float z)
- {
- _Zoom += z * 0.001f;
- if (_Zoom < 0.0001f) _Zoom = 0.0001f;
- }
- public override void Update(GameTime gameTime)
- {
- if (_ModelInstance == null && _ModelTemplate != null)
- {
- _ModelInstance = _ModelTemplate.DefaultModel.CreateInstance();
- _Rotation = Quaternion.Identity;
- _Zoom = 2.5f;
- }
- }
- public override void Draw(GameTime gameTime)
- {
- GraphicsDevice.Clear(Color.CornflowerBlue);
- if (_ModelInstance == null) return;
- _ModelInstance.Armature.SetAnimationFrame(0, (float)gameTime.TotalGameTime.TotalSeconds);
- var lookAt = _ModelSphere.Center;
- var camPos = _ModelSphere.Center + new Vector3(0, 0, _ModelSphere.Radius * _Zoom);
- var camera = Matrix.CreateWorld(camPos, lookAt - camPos, Vector3.UnitY);
- var env = new PBREnvironment();
- env.SetExposure((float)_GlobalLight.Exposure / 10.0f);
- env.SetAmbientLight(_GlobalLight.ToXna());
- for(int i=0; i< _PunctualLights.Length; ++i)
- {
- env.SetDirectLight(i, _PunctualLights[i].Direction, _PunctualLights[i].XnaColor, _PunctualLights[i].Intensity / 10.0f);
- }
- if (_ModelInstance != null)
- {
- _ModelInstance.WorldMatrix = Matrix.CreateFromQuaternion(_Rotation);
- var ctx = new ModelDrawingContext(this.GraphicsDevice);
- ctx.NearPlane = Math.Min(1, _ModelSphere.Radius);
- ctx.SetCamera(camera);
- ctx.DrawModelInstance(env, _ModelInstance);
- }
- }
- #endregion
- }
- public class GlobalLight
- {
- [PropertyTools.DataAnnotations.Slidable(0,100)]
- [PropertyTools.DataAnnotations.WideProperty]
- public int Exposure { get; set; } = 25;
- public System.Windows.Media.Color AmbientColor { get; set; } = System.Windows.Media.Colors.Black;
- public Vector3 ToXna() { return new Vector3(AmbientColor.ScR, AmbientColor.ScG, AmbientColor.ScB); }
- }
- public class PunctualLight
- {
- public static PunctualLight CreateDefault(int idx)
- {
- var l = new PunctualLight();
- l.Intensity = 15;
- l.Color = System.Windows.Media.Colors.White;
- switch(idx)
- {
- case 0:
- l.DirectionAngle = 60;
- l.ElevationAngle = 30;
- l.Intensity = 40;
- break;
- case 1:
- l.DirectionAngle = -70;
- l.ElevationAngle = 60;
- l.Color = System.Windows.Media.Colors.DeepSkyBlue;
- break;
- case 2:
- l.DirectionAngle = 20;
- l.ElevationAngle = -50;
- l.Color = System.Windows.Media.Colors.OrangeRed;
- break;
- }
- return l;
- }
- [PropertyTools.DataAnnotations.Category("Source")]
- [PropertyTools.DataAnnotations.Slidable(-180,180)]
- // [PropertyTools.DataAnnotations.WideProperty]
- [PropertyTools.DataAnnotations.DisplayName("Direction")]
- public int DirectionAngle { get; set; }
- [PropertyTools.DataAnnotations.Category("Source")]
- [PropertyTools.DataAnnotations.Slidable(-90, 90)]
- //[PropertyTools.DataAnnotations.WideProperty]
- [PropertyTools.DataAnnotations.DisplayName("Elevation")]
- public int ElevationAngle { get; set; }
-
- [PropertyTools.DataAnnotations.Category("Properties")]
- public System.Windows.Media.Color Color { get; set; }
- [PropertyTools.DataAnnotations.Category("Properties")]
- [PropertyTools.DataAnnotations.Slidable(0,100)]
- [PropertyTools.DataAnnotations.WideProperty]
- public int Intensity { get; set; }
- [PropertyTools.DataAnnotations.Browsable(false)]
- public Vector3 Direction
- {
- get
- {
- float yaw = (float)(DirectionAngle * Math.PI) / 180.0f;
- float pitch = (float)(ElevationAngle * Math.PI) / 180.0f;
- var xform = Matrix.CreateFromYawPitchRoll(yaw + 3.141592f, pitch, 0);
- return Vector3.Transform(Vector3.UnitZ, xform);
- }
- }
- [PropertyTools.DataAnnotations.Browsable(false)]
- public Color XnaColor => new Color(Color.ScR, Color.ScG, Color.ScB);
- }
- }
|