GameModel.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // GameModel.cs
  4. //
  5. // Microsoft XNA Community Game Platform
  6. // Copyright (C) Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #endregion
  9. #region Using Statements
  10. using System;
  11. using System.Collections.Generic;
  12. using System.Text;
  13. using Microsoft.Xna.Framework;
  14. using Microsoft.Xna.Framework.Content;
  15. using Microsoft.Xna.Framework.Graphics;
  16. using RobotGameData.Render;
  17. using RobotGameData.Resource;
  18. using RobotGameData.Collision;
  19. #endregion
  20. namespace RobotGameData.GameObject
  21. {
  22. /// <summary>
  23. /// It contains and processes the XNA’s “Model” variable.
  24. /// </summary>
  25. public class GameModel : GameSceneNode
  26. {
  27. #region Fields
  28. ModelData modelData = null;
  29. Vector3 veclocity = Vector3.Zero;
  30. Matrix rotateMatrix = Matrix.Identity;
  31. Matrix[] boneTransforms = null;
  32. ModelBone rootBone = null;
  33. RenderLighting[] lighting = null;
  34. RenderMaterial material = null;
  35. bool activeLighting = false;
  36. bool activeFog = false;
  37. bool enableCulling = false;
  38. CollideElement modelCollide = null;
  39. BoundingSphere cullingSphere = new BoundingSphere();
  40. Vector3 cullingSphereLocalCenter = Vector3.Zero;
  41. bool alphaTestEnable = false;
  42. bool alphaBlendEnable = false;
  43. CompareFunction alphaFunction = CompareFunction.Always;
  44. Blend sourceBlend = Blend.One;
  45. Blend destinationBlend = Blend.Zero;
  46. BlendFunction blendFunction = BlendFunction.Add;
  47. int referenceAlpha = 0;
  48. bool depthBufferEnable = true;
  49. bool depthBufferWriteEnable = true;
  50. CompareFunction depthBufferFunction = CompareFunction.LessEqual;
  51. CullMode cullMode = CullMode.CullCounterClockwiseFace;
  52. #endregion
  53. #region Events
  54. public class RenderingCustomEffectEventArgs : EventArgs
  55. {
  56. private RenderTracer renderTracer;
  57. public RenderTracer RenderTracer
  58. {
  59. get { return renderTracer; }
  60. }
  61. private ModelMesh mesh;
  62. public ModelMesh Mesh
  63. {
  64. get { return mesh; }
  65. }
  66. private Effect effect;
  67. public Effect Effect
  68. {
  69. get { return effect; }
  70. }
  71. private Matrix world;
  72. public Matrix World
  73. {
  74. get { return world; }
  75. }
  76. public RenderingCustomEffectEventArgs(RenderTracer renderTracer,
  77. ModelMesh mesh, Effect effect, Matrix world)
  78. : base()
  79. {
  80. this.renderTracer = renderTracer;
  81. this.mesh = mesh;
  82. this.effect = effect;
  83. this.world = world;
  84. }
  85. }
  86. public event EventHandler<RenderingCustomEffectEventArgs> RenderingCustomEffect;
  87. #endregion
  88. #region Properties
  89. public ModelData ModelData
  90. {
  91. get { return modelData; }
  92. protected set { modelData = value; }
  93. }
  94. public Matrix[] BoneTransforms
  95. {
  96. get { return boneTransforms; }
  97. protected set { boneTransforms = value; }
  98. }
  99. public ModelBone RootBone
  100. {
  101. get { return rootBone; }
  102. protected set { rootBone = value; }
  103. }
  104. public CollideElement Collide
  105. {
  106. get { return modelCollide; }
  107. protected set { modelCollide = value; }
  108. }
  109. public bool EnableCulling
  110. {
  111. get { return enableCulling; }
  112. set { enableCulling = value; }
  113. }
  114. public bool ActiveLighting
  115. {
  116. get { return activeLighting; }
  117. set { activeLighting = value; }
  118. }
  119. public bool ActiveFog
  120. {
  121. get { return activeFog; }
  122. set { activeFog = value; }
  123. }
  124. public Vector3 Velocity
  125. {
  126. get { return this.veclocity; }
  127. protected set { this.veclocity = value; }
  128. }
  129. public RenderLighting[] Lighting
  130. {
  131. get { return lighting; }
  132. protected set { lighting = value; }
  133. }
  134. public RenderMaterial Material
  135. {
  136. get { return material; }
  137. set { material = value; }
  138. }
  139. public bool AlphaTestEnable
  140. {
  141. get { return alphaTestEnable; }
  142. set { alphaTestEnable = value; }
  143. }
  144. public bool AlphaBlendEnable
  145. {
  146. get { return alphaBlendEnable; }
  147. set { alphaBlendEnable = value; }
  148. }
  149. public int ReferenceAlpha
  150. {
  151. get { return referenceAlpha; }
  152. set { referenceAlpha = value; }
  153. }
  154. public CompareFunction AlphaFunction
  155. {
  156. get { return alphaFunction; }
  157. set { alphaFunction = value; }
  158. }
  159. public bool DepthBufferEnable
  160. {
  161. get { return depthBufferEnable; }
  162. set { depthBufferEnable = value; }
  163. }
  164. public bool DepthBufferWriteEnable
  165. {
  166. get { return depthBufferWriteEnable; }
  167. set { depthBufferWriteEnable = value; }
  168. }
  169. public CompareFunction DepthBufferFunction
  170. {
  171. get { return depthBufferFunction; }
  172. set { depthBufferFunction = value; }
  173. }
  174. public Blend SourceBlend
  175. {
  176. get { return sourceBlend; }
  177. set { sourceBlend = value; }
  178. }
  179. public Blend DestinationBlend
  180. {
  181. get { return destinationBlend; }
  182. set { destinationBlend = value; }
  183. }
  184. public BlendFunction BlendFunction
  185. {
  186. get { return blendFunction; }
  187. set { blendFunction = value; }
  188. }
  189. public CullMode CullMode
  190. {
  191. get { return cullMode; }
  192. set { cullMode = value; }
  193. }
  194. #endregion
  195. /// <summary>
  196. /// Constructor.
  197. /// </summary>
  198. /// <param name="resource">model resource</param>
  199. public GameModel(GameResourceModel resource)
  200. : base()
  201. {
  202. if (resource == null)
  203. throw new ArgumentNullException("resource");
  204. BindModel(resource.ModelData);
  205. }
  206. public GameModel(string fileName)
  207. : base()
  208. {
  209. LoadModel(fileName);
  210. }
  211. protected override void OnUpdate(GameTime gameTime)
  212. {
  213. // model moves to the position
  214. if (this.veclocity != Vector3.Zero)
  215. {
  216. Vector3 velocityPerFrame =
  217. CalculateVelocityPerFrame(gameTime, this.veclocity);
  218. AddPosition(velocityPerFrame);
  219. }
  220. // Updates collision mesh
  221. if (modelCollide != null)
  222. {
  223. modelCollide.Transform(TransformedMatrix);
  224. }
  225. // If Animated bones
  226. if (this is GameAnimateModel)
  227. {
  228. // If this is root bone,
  229. // the world transformed matrix weight with only root bone
  230. this.ModelData.model.Root.Transform *= this.TransformedMatrix;
  231. }
  232. // If no animated bones (static bones)
  233. else
  234. { // Set the world matrix as the root transform of the model.
  235. this.ModelData.model.Root.Transform = this.TransformedMatrix;
  236. }
  237. // Look up combined bone matrices for the entire the model.
  238. this.ModelData.model.CopyAbsoluteBoneTransformsTo(this.boneTransforms);
  239. }
  240. protected override void OnDraw(RenderTracer renderTracer)
  241. {
  242. RenderState renderState = renderTracer.Device.RenderState;
  243. // Transform culling sphere
  244. if (enableCulling )
  245. {
  246. cullingSphere.Center = Vector3.Transform(cullingSphereLocalCenter,
  247. RootAxis * Collide.TransformMatrix);
  248. // Check if the the model is contained inside or intersecting
  249. // with the frustum.
  250. ContainmentType cullingResult =
  251. renderTracer.Frustum.Contains(cullingSphere);
  252. // Draw a the model If inside in the frustum
  253. if (cullingResult == ContainmentType.Disjoint)
  254. return;
  255. }
  256. renderState.AlphaTestEnable = alphaTestEnable;
  257. renderState.AlphaBlendEnable = alphaBlendEnable;
  258. renderState.AlphaFunction = alphaFunction;
  259. renderState.SourceBlend = sourceBlend;
  260. renderState.DestinationBlend = destinationBlend;
  261. renderState.BlendFunction = blendFunction;
  262. renderState.ReferenceAlpha = referenceAlpha;
  263. renderState.DepthBufferEnable = depthBufferEnable;
  264. renderState.DepthBufferWriteEnable = depthBufferWriteEnable;
  265. renderState.DepthBufferFunction = depthBufferFunction;
  266. renderState.CullMode = cullMode;
  267. // Draw the model.
  268. for( int i = 0; i < ModelData.model.Meshes.Count; i++)
  269. {
  270. ModelMesh mesh = ModelData.model.Meshes[i];
  271. for (int j = 0; j < mesh.Effects.Count; j++)
  272. {
  273. // call a entried custom effect processing
  274. if (RenderingCustomEffect != null)
  275. {
  276. // Shader custom processing
  277. RenderingCustomEffect(this,
  278. new RenderingCustomEffectEventArgs(renderTracer, mesh,
  279. mesh.Effects[j], BoneTransforms[mesh.ParentBone.Index]));
  280. }
  281. else if (mesh.Effects[j] is BasicEffect)
  282. {
  283. BasicEffect effect = (BasicEffect)mesh.Effects[j];
  284. // Apply fog
  285. if (renderTracer.Fog != null && ActiveFog )
  286. {
  287. RenderFog fog = renderTracer.Fog;
  288. effect.FogEnabled = fog.enabled;
  289. if (effect.FogEnabled )
  290. {
  291. effect.FogStart = fog.start;
  292. effect.FogEnd = fog.end;
  293. effect.FogColor = fog.color.ToVector3();
  294. }
  295. }
  296. else
  297. {
  298. effect.FogEnabled = false;
  299. }
  300. if (ActiveLighting )
  301. {
  302. // Apply lighting
  303. if (renderTracer.Lighting != null)
  304. {
  305. RenderLighting lighting = renderTracer.Lighting;
  306. effect.LightingEnabled = lighting.enabled;
  307. if (effect.LightingEnabled )
  308. {
  309. effect.AmbientLightColor =
  310. lighting.ambientColor.ToVector3();
  311. effect.DirectionalLight0.Enabled = true;
  312. effect.DirectionalLight0.Direction =
  313. lighting.direction;
  314. effect.DirectionalLight0.DiffuseColor =
  315. lighting.diffuseColor.ToVector3();
  316. effect.DirectionalLight0.SpecularColor =
  317. lighting.specularColor.ToVector3();
  318. }
  319. }
  320. if (Lighting != null)
  321. {
  322. effect.LightingEnabled = true;
  323. for (int cnt = 0; cnt < Lighting.Length; cnt++)
  324. {
  325. RenderLighting lighting = Lighting[cnt];
  326. BasicDirectionalLight basicLight = null;
  327. if (cnt == 0)
  328. basicLight = effect.DirectionalLight1;
  329. else if (cnt == 1)
  330. basicLight = effect.DirectionalLight2;
  331. else
  332. continue;
  333. if (lighting.enabled )
  334. {
  335. basicLight.Enabled = true;
  336. basicLight.Direction =
  337. lighting.direction;
  338. basicLight.DiffuseColor =
  339. lighting.diffuseColor.ToVector3();
  340. basicLight.SpecularColor =
  341. lighting.specularColor.ToVector3();
  342. }
  343. else
  344. {
  345. basicLight.Enabled = false;
  346. }
  347. }
  348. }
  349. if (renderTracer.Lighting == null && Lighting == null)
  350. {
  351. effect.LightingEnabled = false;
  352. }
  353. // Apply material
  354. if (Material != null)
  355. {
  356. effect.Alpha = Material.alpha;
  357. effect.DiffuseColor =
  358. Material.diffuseColor.ToVector3();
  359. effect.SpecularColor =
  360. Material.specularColor.ToVector3();
  361. effect.SpecularPower =
  362. Material.specularPower;
  363. effect.EmissiveColor =
  364. Material.emissiveColor.ToVector3();
  365. effect.VertexColorEnabled =
  366. Material.vertexColorEnabled;
  367. effect.PreferPerPixelLighting =
  368. Material.preferPerPixelLighting;
  369. }
  370. }
  371. else
  372. {
  373. effect.LightingEnabled = false;
  374. }
  375. // Apply transform
  376. effect.World = BoneTransforms[mesh.ParentBone.Index];
  377. effect.View = renderTracer.View;
  378. effect.Projection = renderTracer.Projection;
  379. }
  380. }
  381. mesh.Draw();
  382. }
  383. }
  384. protected override void OnReset()
  385. {
  386. this.veclocity = Vector3.Zero;
  387. // Reset the bone's transform by source transform
  388. this.ModelData.model.CopyBoneTransformsFrom(this.ModelData.boneTransforms);
  389. // Set the world matrix as the root transform of the model.
  390. ModelData.model.Root.Transform = Matrix.Identity;
  391. // Look up combined bone matrices for the entire the model.
  392. ModelData.model.CopyAbsoluteBoneTransformsTo(this.boneTransforms);
  393. base.OnReset();
  394. }
  395. public void LoadModel(string modelFileName)
  396. {
  397. // First, Find the model resource from ResourceManager by key
  398. GameResourceModel resource =
  399. FrameworkCore.ResourceManager.GetModel(modelFileName);
  400. if (resource == null)
  401. {
  402. // Load the model.
  403. FrameworkCore.ResourceManager.LoadContent<Model>(modelFileName,
  404. modelFileName);
  405. resource = FrameworkCore.ResourceManager.GetModel(modelFileName);
  406. }
  407. // Load and find resource failed.
  408. if (resource == null)
  409. {
  410. throw new ArgumentException("Cannot load the model : " +
  411. modelFileName);
  412. }
  413. BindModel(resource.ModelData);
  414. }
  415. public virtual void BindModel(ModelData modelData)
  416. {
  417. this.ModelData = modelData;
  418. this.rootBone = modelData.model.Root;
  419. // Set to bone transform matrix
  420. this.boneTransforms = new Matrix[this.ModelData.model.Bones.Count];
  421. this.ModelData.model.CopyAbsoluteBoneTransformsTo(this.boneTransforms);
  422. // Compute the bounding sphere of the ModelData.
  423. cullingSphere = new BoundingSphere();
  424. for (int i = 0; i < this.ModelData.model.Meshes.Count; i++)
  425. {
  426. ModelMesh mesh = this.ModelData.model.Meshes[i];
  427. cullingSphere = BoundingSphere.CreateMerged(cullingSphere,
  428. mesh.BoundingSphere);
  429. }
  430. cullingSphereLocalCenter = cullingSphere.Center;
  431. }
  432. public void Move(Vector3 velocity)
  433. {
  434. this.veclocity = velocity;
  435. }
  436. public void MoveStop()
  437. {
  438. this.veclocity = Vector3.Zero;
  439. }
  440. public Vector3 CalculateVelocity(Vector3 velocity)
  441. {
  442. Vector3 v = Vector3.Zero;
  443. if (velocity.Z != 0.0f)
  444. {
  445. v += Direction * velocity.Z;
  446. }
  447. if (velocity.X != 0.0f)
  448. {
  449. v += Right * velocity.X;
  450. }
  451. if (velocity.Y != 0.0f)
  452. {
  453. v += Up * velocity.Y;
  454. }
  455. return v;
  456. }
  457. public Vector3 CalculateVelocityPerFrame(GameTime gameTime, Vector3 velocity)
  458. {
  459. return CalculateVelocity(velocity) *
  460. (float)gameTime.ElapsedGameTime.TotalSeconds;
  461. }
  462. public void Rotate(Vector2 rotationAmount)
  463. {
  464. // Scale rotation amount to radians per second
  465. rotationAmount *= (float)FrameworkCore.ElapsedDeltaTime.TotalSeconds;
  466. // Create rotation matrix from rotation amount
  467. rotateMatrix = Matrix.CreateFromAxisAngle(
  468. Right,
  469. MathHelper.ToRadians(rotationAmount.Y)) *
  470. Matrix.CreateRotationY(
  471. MathHelper.ToRadians(rotationAmount.X));
  472. // Rotate orientation vectors
  473. Direction = Vector3.TransformNormal(Direction, rotateMatrix);
  474. Up = Vector3.TransformNormal(Up, rotateMatrix);
  475. // Re-normalize orientation vectors
  476. Direction.Normalize();
  477. Up.Normalize();
  478. // Re-calculate Right
  479. Right = Vector3.Cross(Direction, Up);
  480. // The same instability may cause the 3 orientation vectors may
  481. // also diverge. Either the Up or Direction vector needs to be
  482. // re-computed with a cross product to ensure orthagonality
  483. Up = Vector3.Cross(Right, Direction);
  484. }
  485. public void DumpTrace()
  486. {
  487. System.Diagnostics.Debug.WriteLine(WorldTransform.ToString());
  488. }
  489. public void SetRootAxis(Matrix rotation)
  490. {
  491. RootAxis = rotation;
  492. }
  493. public void SetPosition(Vector3 position)
  494. {
  495. Position = position;
  496. }
  497. public void SetPosition(float x, float y, float z)
  498. {
  499. Position = new Vector3(x, y, z);
  500. }
  501. public void AddPosition(Vector3 position)
  502. {
  503. Position += position;
  504. }
  505. public void AddPosition(float x, float y, float z)
  506. {
  507. Position += new Vector3(x, y, z);
  508. }
  509. public Matrix SetRotationX(float angle)
  510. {
  511. Vector3 position = Position;
  512. WorldTransform = Matrix.CreateRotationX(MathHelper.ToRadians(angle));
  513. Position = position;
  514. return WorldTransform;
  515. }
  516. public Matrix SetRotationY(float angle)
  517. {
  518. Vector3 position = Position;
  519. WorldTransform = Matrix.CreateRotationY(MathHelper.ToRadians(angle));
  520. Position = position;
  521. return WorldTransform;
  522. }
  523. public Matrix SetRotationZ(float angle)
  524. {
  525. Vector3 position = Position;
  526. WorldTransform = Matrix.CreateRotationZ(MathHelper.ToRadians(angle));
  527. Position = position;
  528. return WorldTransform;
  529. }
  530. public Matrix AddRotationX(float angle)
  531. {
  532. WorldTransform += Matrix.CreateRotationX(MathHelper.ToRadians(angle));
  533. return WorldTransform;
  534. }
  535. public Matrix AddRotationY(float angle)
  536. {
  537. WorldTransform += Matrix.CreateRotationY(MathHelper.ToRadians(angle));
  538. return WorldTransform;
  539. }
  540. public Matrix AddRotationZ(float angle)
  541. {
  542. WorldTransform += Matrix.CreateRotationZ(MathHelper.ToRadians(angle));
  543. return WorldTransform;
  544. }
  545. public Matrix SetRotationAxis(Vector3 axis, float angle)
  546. {
  547. Vector3 position = Position;
  548. WorldTransform =
  549. Matrix.CreateFromAxisAngle(axis, MathHelper.ToRadians(angle));
  550. Position = position;
  551. return WorldTransform;
  552. }
  553. public Matrix AddRotationAxis(Vector3 axis, float angle)
  554. {
  555. Vector3 position = Position;
  556. WorldTransform +=
  557. Matrix.CreateFromAxisAngle(axis, MathHelper.ToRadians(angle));
  558. Position = position;
  559. return WorldTransform;
  560. }
  561. public void SetCollide(CollideElement collide)
  562. {
  563. modelCollide = collide;
  564. modelCollide.Name = Name + "_Collide";
  565. modelCollide.Owner = (object)this;
  566. }
  567. public Vector3 GetMoveAt(Vector3 velocity)
  568. {
  569. Vector3 v = Vector3.Zero;
  570. if (velocity.Z != 0.0f)
  571. {
  572. v += Direction * velocity.Z;
  573. }
  574. if (velocity.X != 0.0f)
  575. {
  576. v += Right * velocity.X;
  577. }
  578. if (velocity.Y != 0.0f)
  579. {
  580. v += Up * velocity.Y;
  581. }
  582. if (v == Vector3.Zero)
  583. return Vector3.Zero;
  584. else
  585. return Vector3.Normalize(v);
  586. }
  587. }
  588. }