Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
MeshProcessor.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Collections.Generic;
5 using System.Collections.Specialized;
6 using System.Linq;
7 using System.Threading.Tasks;
8 using SiliconStudio.Core.Mathematics;
9 using SiliconStudio.Paradox.Effects;
10 using SiliconStudio.Paradox.Effects.Data;
11 using SiliconStudio.Paradox.EntityModel;
12 using SiliconStudio.Paradox.Games;
13 using SiliconStudio.Core.Extensions;
14 using SiliconStudio.Core;
15 using SiliconStudio.Core.Collections;
16 using SiliconStudio.Core.Serialization.Assets;
17 using SiliconStudio.Core.Serialization.Contents;
18 
19 namespace SiliconStudio.Paradox.Engine
20 {
21  public class MeshProcessor : EntityProcessor<MeshProcessor.AssociatedData>
22  {
23  private RenderSystem renderSystem;
24 
25  /// <summary>
26  /// The link transformation to update.
27  /// </summary>
28  /// <remarks>The collection is declared globally only to avoid allocation at each frames</remarks>
29  private FastCollection<TransformationComponent> linkTransformationToUpdate = new FastCollection<TransformationComponent>();
30 
31  public MeshProcessor()
32  : base(new PropertyKey[] { ModelComponent.Key, TransformationComponent.Key })
33  {
34  }
35 
36  protected internal override void OnSystemAdd()
37  {
38  renderSystem = Services.GetSafeServiceAs<RenderSystem>();
39  }
40 
41  protected override AssociatedData GenerateAssociatedData(Entity entity)
42  {
43  return new AssociatedData { ModelComponent = entity.Get(ModelComponent.Key), TransformationComponent = entity.Transformation };
44  }
45 
46  protected override void OnEntityAdding(Entity entity, AssociatedData associatedData)
47  {
48  associatedData.RenderModels = new List<KeyValuePair<ModelRendererState, RenderModel>>();
49 
50  // Initialize a RenderModel for every pipeline
51  // TODO: Track added/removed pipelines?
52  var modelInstance = associatedData.ModelComponent;
53 
54  foreach (var pipeline in renderSystem.Pipelines)
55  {
56  var modelRenderState = pipeline.GetOrCreateModelRendererState();
57 
58  // If the model is not accepted
59  if (!modelRenderState.IsValid || !modelRenderState.AcceptModel(modelInstance))
60  {
61  continue;
62  }
63 
64  var renderModel = new RenderModel(pipeline, modelInstance);
65  if (renderModel.RenderMeshes == null)
66  {
67  continue;
68  }
69 
70  // Register RenderModel
71  associatedData.RenderModels.Add(new KeyValuePair<ModelRendererState, RenderModel>(modelRenderState, renderModel));
72  }
73  }
74 
75  protected override void OnEntityRemoved(Entity entity, AssociatedData data)
76  {
77  base.OnEntityRemoved(entity, data);
78  }
79 
80  public EntityLink LinkEntity(Entity linkedEntity, ModelComponent modelComponent, string boneName)
81  {
82  var modelEntityData = matchingEntities[modelComponent.Entity];
83  var nodeIndex = modelEntityData.ModelComponent.ModelViewHierarchy.Nodes.IndexOf(x => x.Name == boneName);
84 
85  var entityLink = new EntityLink { Entity = linkedEntity, ModelComponent = modelComponent, NodeIndex = nodeIndex };
86  if (nodeIndex == -1)
87  return entityLink;
88 
89  linkedEntity.Transformation.isSpecialRoot = true;
90  linkedEntity.Transformation.UseTRS = false;
91 
92  if (modelEntityData.Links == null)
93  modelEntityData.Links = new List<EntityLink>();
94 
95  modelEntityData.Links.Add(entityLink);
96 
97  return entityLink;
98  }
99 
100  public bool UnlinkEntity(EntityLink entityLink)
101  {
102  if (entityLink.NodeIndex == -1)
103  return false;
104 
105  AssociatedData modelEntityData;
106  if (!matchingEntities.TryGetValue(entityLink.ModelComponent.Entity, out modelEntityData))
107  return false;
108 
109  return modelEntityData.Links.Remove(entityLink);
110  }
111 
112  public override void Draw(GameTime time)
113  {
114  // Clear all pipelines from previously collected models
115  foreach (var pipeline in renderSystem.Pipelines)
116  {
117  var renderMeshState = pipeline.GetOrCreateModelRendererState();
118  renderMeshState.RenderModels.Clear();
119  }
120 
121  // Collect models for this frame
122  foreach (var matchingEntity in enabledEntities)
123  {
124  // Skip model not enabled
125  if (!matchingEntity.Value.ModelComponent.Enabled)
126  {
127  continue;
128  }
129 
130  var modelViewHierarchy = matchingEntity.Value.ModelComponent.ModelViewHierarchy;
131 
132  var transformationComponent = matchingEntity.Value.TransformationComponent;
133 
134  var links = matchingEntity.Value.Links;
135 
136  // Update model view hierarchy node matrices
137  modelViewHierarchy.NodeTransformations[0].LocalMatrix = transformationComponent.WorldMatrix;
138  modelViewHierarchy.UpdateMatrices();
139 
140  if (links != null)
141  {
142  // Update links: transfer node/bone transformation to a specific entity transformation
143  // Then update this entity transformation tree
144  // TODO: Ideally, we should order update (matchingEntities?) to avoid updating a ModelViewHierarchy before its transformation is updated.
145  foreach (var link in matchingEntity.Value.Links)
146  {
147  var linkTransformation = link.Entity.Transformation;
148  linkTransformation.LocalMatrix = modelViewHierarchy.NodeTransformations[link.NodeIndex].WorldMatrix;
149 
150  linkTransformationToUpdate.Clear();
151  linkTransformationToUpdate.Add(linkTransformation);
152  TransformationProcessor.UpdateTransformations(linkTransformationToUpdate, false);
153  }
154  }
155 
156  foreach (var renderModelEntry in matchingEntity.Value.RenderModels)
157  {
158  var renderModelState = renderModelEntry.Key;
159  var renderModel = renderModelEntry.Value;
160 
161  if (!renderModelState.AcceptRenderModel(renderModel))
162  {
163  continue;
164  }
165 
166  // Add model to rendering
167  renderModelState.RenderModels.Add(renderModel);
168 
169  // Upload matrices to TransformationKeys.World
170  modelViewHierarchy.UpdateToRenderModel(renderModel);
171 
172  // Upload skinning blend matrices
173  MeshSkinningUpdater.Update(modelViewHierarchy, renderModel);
174  }
175  }
176  }
177 
178  public class AssociatedData
179  {
181 
183 
184  internal List<KeyValuePair<ModelRendererState, RenderModel>> RenderModels;
185 
186  public List<EntityLink> Links;
187  }
188 
189  public struct EntityLink
190  {
191  public int NodeIndex;
192  public Entity Entity;
194  }
195  }
196 }
override AssociatedData GenerateAssociatedData(Entity entity)
override void OnEntityRemoved(Entity entity, AssociatedData data)
Game entity. It usually aggregates multiple EntityComponent
Definition: Entity.cs:28
Defines Position, Rotation and Scale of its Entity.
TransformationComponent Transformation
Gets or sets the Transformation associated to this entity. Added for convenience over usual Get/Set m...
Definition: Entity.cs:74
Entity Entity
Gets or sets the owner entity.
Entity processor, triggered on various EntitySystem events such as Entity and Component additions and...
bool UnlinkEntity(EntityLink entityLink)
override void OnEntityAdding(Entity entity, AssociatedData associatedData)
EntityLink LinkEntity(Entity linkedEntity, ModelComponent modelComponent, string boneName)
Current timing used for variable-step (real time) or fixed-step (game time) games.
Definition: GameTime.cs:31
Renders its RenderSystem.Pipeline, which will usually result in drawing all meshes, UI, etc...
Definition: RenderSystem.cs:18
Add a Model to an Entity, that will be used during rendering.
Instantiation of a Model through a RenderPipeline.
Definition: RenderModel.cs:11
A class that represents a tag propety.
Definition: PropertyKey.cs:17
override void Draw(GameTime time)