/// <summary> /// Model initialization /// </summary> /// <param name="game">Game</param> /// <param name="bufferManager">Buffer manager</param> /// <param name="modelContent">Model content</param> /// <param name="description">Data description</param> /// <returns>Returns the generated drawing data objects</returns> public static DrawingData Build(Game game, BufferManager bufferManager, ModelContent modelContent, DrawingDataDescription description) { DrawingData res = new DrawingData(bufferManager); //Animation if (description.LoadAnimation) { InitializeSkinningData(ref res, modelContent); } //Images InitializeTextures(ref res, game, modelContent, description.TextureCount); //Materials InitializeMaterials(ref res, modelContent); //Skins & Meshes InitializeGeometry(ref res, modelContent, description); //Update meshes into device InitializeMeshes(ref res, bufferManager, description.Instanced ? description.Instances : 0); //Lights InitializeLights(ref res, modelContent); return(res); }
/// <summary> /// Initialize materials /// </summary> /// <param name="drw">Drawing data</param> /// <param name="modelContent">Model content</param> private static void InitializeMaterials(ref DrawingData drw, ModelContent modelContent) { foreach (string mat in modelContent.Materials?.Keys) { var effectInfo = modelContent.Materials[mat]; MeshMaterial meshMaterial = new MeshMaterial() { Material = new Material(effectInfo), EmissionTexture = drw.Textures[effectInfo.EmissionTexture], AmbientTexture = drw.Textures[effectInfo.AmbientTexture], DiffuseTexture = drw.Textures[effectInfo.DiffuseTexture], SpecularTexture = drw.Textures[effectInfo.SpecularTexture], ReflectiveTexture = drw.Textures[effectInfo.ReflectiveTexture], NormalMap = drw.Textures[effectInfo.NormalMapTexture], }; drw.Materials.Add(mat, meshMaterial); } }
/// <summary> /// Initialize lights /// </summary> /// <param name="drw">Drawing data</param> /// <param name="modelContent">Model content</param> private static void InitializeLights(ref DrawingData drw, ModelContent modelContent) { List <SceneLight> lights = new List <SceneLight>(); foreach (var key in modelContent.Lights.Keys) { var l = modelContent.Lights[key]; if (l.LightType == LightContentTypes.Point) { lights.Add(l.CreatePointLight()); } else if (l.LightType == LightContentTypes.Spot) { lights.Add(l.CreateSpotLight()); } } drw.Lights = lights.ToArray(); }
/// <summary> /// Initialize mesh buffers in the graphics device /// </summary> /// <param name="drw">Drawing data</param> /// <param name="game">Game</param> private static void InitializeMeshes(ref DrawingData drw, BufferManager bufferManager, int instances) { foreach (var dictionary in drw.Meshes.Values) { foreach (var mesh in dictionary.Values) { //Vertices mesh.VertexBuffer = bufferManager.Add(mesh.Name, mesh.Vertices.ToArray(), false, instances); if (mesh.Indexed) { //Indices mesh.IndexBuffer = bufferManager.Add(mesh.Name, mesh.Indices.ToArray(), false); } else { mesh.IndexBuffer = new BufferDescriptor(-1, -1, 0); } } } }
/// <summary> /// Initialize skinning data /// </summary> /// <param name="drw">Drawing data</param> /// <param name="modelContent">Model content</param> private static void InitializeSkinningData(ref DrawingData drw, ModelContent modelContent) { if (modelContent.SkinningInfo?.Count > 0) { //Use the definition to read animation data into a clip dictionary foreach (var sInfo in modelContent.SkinningInfo.Values) { if (drw.SkinningData != null) { continue; } drw.SkinningData = new SkinningData(sInfo.Skeleton); var animations = InitializeJoints(modelContent, sInfo.Skeleton.Root, sInfo.Controllers); drw.SkinningData.Initialize( animations, modelContent.Animations.Definition); } } }
/// <summary> /// Initialize textures /// </summary> /// <param name="drw">Drawing data</param> /// <param name="game">Game</param> /// <param name="modelContent">Model content</param> /// <param name="textureCount">Texture count</param> private static void InitializeTextures(ref DrawingData drw, Game game, ModelContent modelContent, int textureCount) { if (modelContent.Images != null) { foreach (string images in modelContent.Images.Keys) { var info = modelContent.Images[images]; var view = game.ResourceManager.CreateResource(info); if (view != null) { drw.Textures.Add(images, view); //Set the maximum texture index in the model if (info.Count > textureCount) { textureCount = info.Count; } } } } }
/// <summary> /// Initilize geometry /// </summary> /// <param name="drw">Drawing data</param> /// <param name="modelContent">Model content</param> /// <param name="description">Description</param> private static void InitializeGeometry(ref DrawingData drw, ModelContent modelContent, DrawingDataDescription description) { List <Triangle> volumeMesh = new List <Triangle>(); foreach (string meshName in modelContent.Geometry.Keys) { //Get skinning data var isSkinned = ReadSkinningData( description, modelContent, meshName, out var bindShapeMatrix, out var weights, out var jointNames); //Process the mesh geometry material by material var dictGeometry = modelContent.Geometry[meshName]; foreach (string material in dictGeometry.Keys) { var geometry = dictGeometry[material]; if (geometry.IsVolume) { //If volume, store position only volumeMesh.AddRange(geometry.GetTriangles()); } else { //Get vertex type var vertexType = GetVertexType(description, drw.Materials, geometry.VertexType, isSkinned, material); //Process the vertex data ProcessVertexData( description, geometry, vertexType, out var vertices, out var indices); for (int i = 0; i < vertices.Length; i++) { vertices[i] = vertices[i].Transform(bindShapeMatrix); } //Convert the vertex data to final mesh data var vertexList = VertexData.Convert( vertexType, vertices, weights, jointNames); if (vertexList.Any()) { //Create and store the mesh into the drawing data Mesh nMesh = new Mesh( meshName, geometry.Topology, vertexList.ToArray(), indices); drw.Meshes.Add(meshName, geometry.Material, nMesh); } } } } drw.VolumeMesh = volumeMesh.ToArray(); }
/// <summary> /// Base model /// </summary> /// <param name="scene">Scene</param> /// <param name="description">Object description</param> protected BaseModel(Scene scene, BaseModelDescription description) : base(scene, description) { var desc = new DrawingDataDescription() { Instanced = description.Instanced, Instances = description.Instances, LoadAnimation = description.LoadAnimation, LoadNormalMaps = description.LoadNormalMaps, TextureCount = this.TextureCount, DynamicBuffers = description.Dynamic, }; IEnumerable <ModelContent> geo; if (!string.IsNullOrEmpty(description.Content.ModelContentFilename)) { string contentFile = Path.Combine(description.Content.ContentFolder, description.Content.ModelContentFilename); var contentDesc = Helper.DeserializeFromFile <ModelContentDescription>(contentFile); var loader = contentDesc.GetLoader(); geo = loader.Load(description.Content.ContentFolder, contentDesc); } else if (description.Content.ModelContentDescription != null) { var loader = description.Content.ModelContentDescription.GetLoader(); geo = loader.Load(description.Content.ContentFolder, description.Content.ModelContentDescription); } else if (description.Content.ModelContent != null) { geo = new[] { description.Content.ModelContent }; } else { throw new EngineException("No geometry found in description."); } if (geo.Count() == 1) { var iGeo = geo.First(); if (description.Optimize) { iGeo.Optimize(); } var drawable = DrawingData.Build(this.Game, this.BufferManager, iGeo, desc); this.meshesByLOD.Add(LevelOfDetail.High, drawable); } else { var content = new LevelOfDetailModelContent(geo, description.Optimize); foreach (var lod in content.Keys) { if (this.defaultLevelOfDetail == LevelOfDetail.None) { this.defaultLevelOfDetail = lod; } var drawable = DrawingData.Build(this.Game, this.BufferManager, content[lod], desc); this.meshesByLOD.Add(lod, drawable); } } this.UseAnisotropicFiltering = description.UseAnisotropicFiltering; }