GamePointSprite.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // GamePointSprite.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. using RobotGameData.GameInterface;
  20. using RobotGameData.Helper;
  21. #endregion
  22. namespace RobotGameData.GameObject
  23. {
  24. /// <summary>
  25. /// This sprite constantly looks at the view matrix at anywhere in the 3D world.
  26. /// A rotation feature is not provided.
  27. /// </summary>
  28. public class GamePointSprite : GameMesh
  29. {
  30. #region PointSpriteObject
  31. public class PointSpriteObject : INamed
  32. {
  33. [Flags]
  34. public enum UpdateTypes
  35. {
  36. None = 0x00000000,
  37. Position = 0x00000001,
  38. Texturecoord = 0x00000002,
  39. Color = 0x00000004,
  40. Rotation = 0x00000010,
  41. }
  42. public enum RotationAngle
  43. {
  44. Angle0 = 0,
  45. Angle90,
  46. Angle180,
  47. Angle270,
  48. }
  49. String name = String.Empty;
  50. bool enable = true;
  51. Vector3 center = Vector3.Zero;
  52. float width = 1.0f;
  53. float height = 1.0f;
  54. Color color = new Color(255, 255, 255, 255);
  55. RotationAngle rotation = RotationAngle.Angle0;
  56. Vector2[] uv = new Vector2[2]
  57. {
  58. Vector2.Zero,
  59. Vector2.One,
  60. };
  61. bool flipX = false;
  62. bool flipY = false;
  63. uint updateFlag = 0;
  64. public string Name
  65. {
  66. get { return name; }
  67. set { name = value; }
  68. }
  69. public bool Enable
  70. {
  71. get { return this.enable; }
  72. set { this.enable = value; }
  73. }
  74. public Vector3 Center
  75. {
  76. get { return this.center; }
  77. set { this.center = value; }
  78. }
  79. public float Width
  80. {
  81. get { return this.width; }
  82. set { this.width = value; }
  83. }
  84. public float Height
  85. {
  86. get { return this.height; }
  87. set { this.height = value; }
  88. }
  89. public Color Color
  90. {
  91. get { return this.color; }
  92. set { this.color = value; }
  93. }
  94. public RotationAngle Rotation
  95. {
  96. get { return this.rotation; }
  97. set { this.rotation = value; }
  98. }
  99. public bool FlipX
  100. {
  101. get { return this.flipX; }
  102. set { this.flipX = value; }
  103. }
  104. public bool FlipY
  105. {
  106. get { return this.flipY; }
  107. set { this.flipY = value; }
  108. }
  109. public void AddUpdateType(UpdateTypes updateType)
  110. {
  111. this.updateFlag |= (uint)updateType;
  112. }
  113. public void RemoveUpdateType(UpdateTypes updateType)
  114. {
  115. this.updateFlag &= ~(uint)updateType;
  116. }
  117. public Vector2 MinUV
  118. {
  119. get { return this.uv[0]; }
  120. set { this.uv[0] = value; }
  121. }
  122. public Vector2 MaxUV
  123. {
  124. get { return this.uv[1]; }
  125. set { this.uv[1] = value; }
  126. }
  127. }
  128. #endregion
  129. #region Fields
  130. const int vertexStride = 4;
  131. const int indexStride = 6;
  132. List<PointSpriteObject> pointSpriteList = new List<PointSpriteObject>();
  133. RenderingSpace space = RenderingSpace.World;
  134. Matrix lastViewMatrix;
  135. int count = 0;
  136. bool needToUpdate = false;
  137. bool alwaysUpdate = false;
  138. #endregion
  139. #region Properties
  140. public int Count
  141. {
  142. get { return this.count; }
  143. }
  144. #endregion
  145. /// <summary>
  146. /// updates the vertex data and draws
  147. /// </summary>
  148. /// <param name="renderTracer">render information</param>
  149. protected override void OnDraw(RenderTracer renderTracer)
  150. {
  151. int objectCount = 0;
  152. for (int i = 0; i < this.count; i++)
  153. {
  154. if (pointSpriteList[i].Enable == false) continue;
  155. objectCount++;
  156. }
  157. if (objectCount == 0) return;
  158. PrimitiveCount = objectCount * 2;
  159. UpdateVertexCount = this.count * vertexStride;
  160. this.alwaysUpdate = true;
  161. // needs to update?
  162. if (renderTracer.View != lastViewMatrix)
  163. {
  164. needToUpdate = true;
  165. this.lastViewMatrix = renderTracer.View;
  166. }
  167. if (this.alwaysUpdate || needToUpdate)
  168. {
  169. int vertexOffset = 0;
  170. int indexOffset = 0;
  171. // calculates inverse view matrix.
  172. Matrix transformMatrix =
  173. Helper3D.Transpose(this.TransformedMatrix * renderTracer.View);
  174. for (int i = 0; i < this.count; i++)
  175. {
  176. PointSpriteObject obj = pointSpriteList[i];
  177. if (obj.Enable == false) continue;
  178. // updates vertex positions.
  179. SetBufferPosition(ref vertexData, obj, vertexOffset,
  180. transformMatrix, this.space);
  181. // updates texture coordinates.
  182. SetBufferTextureCoord(ref vertexData, obj,
  183. vertexOffset, this.space);
  184. // updates vertex colors.
  185. SetBufferColor(ref vertexData, obj, vertexOffset);
  186. indexData[indexOffset + 0] = (short)(vertexOffset + 0);
  187. indexData[indexOffset + 1] = (short)(vertexOffset + 1);
  188. indexData[indexOffset + 2] = (short)(vertexOffset + 2);
  189. indexData[indexOffset + 3] = (short)(vertexOffset + 3);
  190. indexData[indexOffset + 4] = (short)(vertexOffset + 0);
  191. indexData[indexOffset + 5] = (short)(vertexOffset + 2);
  192. vertexOffset += vertexStride;
  193. indexOffset += indexStride;
  194. }
  195. if (userPrimitive == false)
  196. {
  197. // binds the vertex buffer.
  198. BindVertexBuffer();
  199. // binds the index buffer.
  200. BindIndexBuffer();
  201. }
  202. if (needToUpdate)
  203. needToUpdate = false;
  204. }
  205. // draws mesh
  206. base.OnDraw(renderTracer);
  207. }
  208. /// <summary>
  209. /// create point sprite objects using the texture.
  210. /// </summary>
  211. /// <param name="count">sprite object count</param>
  212. /// <param name="fileName">texture file name</param>
  213. /// <param name="space">3D render space</param>
  214. /// <param name="alwaysUpdate"></param>
  215. public void Create(int count, string fileName,
  216. RenderingSpace space, bool alwaysUpdate)
  217. {
  218. // load a texture.
  219. GameResourceTexture2D resource =
  220. FrameworkCore.ResourceManager.LoadTexture(fileName);
  221. Create(count, resource.Texture2D, space, alwaysUpdate);
  222. }
  223. /// <summary>
  224. /// create point sprite objects using the texture.
  225. /// </summary>
  226. /// <param name="count">sprite object count</param>
  227. /// <param name="texture">rexture resource</param>
  228. /// <param name="space">3D render space</param>
  229. /// <param name="alwaysUpdate"></param>
  230. public void Create(int count, Texture2D texture,
  231. RenderingSpace space, bool alwaysUpdate)
  232. {
  233. this.count = count;
  234. this.space = space;
  235. this.alwaysUpdate = alwaysUpdate;
  236. // create sprite objects.
  237. for (int i = 0; i < count; i++)
  238. pointSpriteList.Add(new PointSpriteObject());
  239. base.Create(this.count * vertexStride, this.count * indexStride, texture);
  240. }
  241. protected override void UnloadContent()
  242. {
  243. pointSpriteList.Clear();
  244. base.UnloadContent();
  245. }
  246. /// <summary>
  247. /// enables/disables all sprite objects.
  248. /// </summary>
  249. public void SetObjectEnable(bool enable)
  250. {
  251. for (int i = 0; i < pointSpriteList.Count; i++)
  252. SetObjectEnable(i, enable);
  253. }
  254. /// <summary>
  255. /// enables/disables an individual sprite object.
  256. /// </summary>
  257. public void SetObjectEnable(int index, bool enable)
  258. {
  259. if (pointSpriteList.Count <= index || 0 > index)
  260. throw new ArgumentException("Invalid index.");
  261. if (pointSpriteList[index].Enable != enable)
  262. {
  263. pointSpriteList[index].Enable = enable;
  264. needToUpdate = true;
  265. }
  266. }
  267. /// <summary>
  268. /// configures a center position of each sprite object.
  269. /// </summary>
  270. /// <param name="index">an index of sprite object</param>
  271. /// <param name="position">a center position</param>
  272. public void SetCenter(int index, Vector3 position)
  273. {
  274. if (pointSpriteList.Count <= index || 0 > index)
  275. throw new ArgumentException("Invalid index.");
  276. pointSpriteList[index].Center = position;
  277. pointSpriteList[index].AddUpdateType(PointSpriteObject.UpdateTypes.Position);
  278. needToUpdate = true;
  279. }
  280. /// <summary>
  281. /// configures a center position of each sprite object.
  282. /// </summary>
  283. /// <param name="index">an index of sprite object</param>
  284. /// <param name="x">x-component of center position of the sprite object</param>
  285. /// <param name="y">y-component of center position of the sprite object</param>
  286. /// <param name="z">z-component of center position of the sprite object</param>
  287. public void SetCenter(int index, float x, float y, float z)
  288. {
  289. SetCenter(index, new Vector3(x, y, z));
  290. }
  291. /// <summary>
  292. /// gets a left top position of each sprite object.
  293. /// </summary>
  294. /// <param name="index">an index of sprite object</param>
  295. /// <param name="vec">out vector</param>
  296. public void GetLeftTop(int index, ref Vector3 vec)
  297. {
  298. if (pointSpriteList.Count <= index || 0 > index)
  299. throw new ArgumentException("Invalid index.");
  300. PointSpriteObject obj = pointSpriteList[index];
  301. vec.X = obj.Center.X - (obj.Width * 0.5f);
  302. vec.Y = obj.Center.Y - (obj.Height * 0.5f);
  303. vec.Z = obj.Center.Z;
  304. }
  305. /// <summary>
  306. /// gets a right down position of each sprite object.
  307. /// </summary>
  308. /// <param name="index">an index of sprite object</param>
  309. /// <param name="vec">out vector</param>
  310. public void GetRightBottom(int index, ref Vector3 vec)
  311. {
  312. if (pointSpriteList.Count <= index || 0 > index)
  313. throw new ArgumentException("Invalid index.");
  314. PointSpriteObject obj = pointSpriteList[index];
  315. vec.X = obj.Center.X + (obj.Width * 0.5f);
  316. vec.Y = obj.Center.Y + (obj.Height * 0.5f);
  317. vec.Z = obj.Center.Z;
  318. }
  319. /// <summary>
  320. /// configures a rotation value of each sprite object.
  321. /// </summary>
  322. /// <param name="index">an index of sprite object</param>
  323. /// <param name="rotation">rotation angle</param>
  324. public void SetRotation(int index, PointSpriteObject.RotationAngle rotation)
  325. {
  326. if (pointSpriteList.Count <= index || 0 > index)
  327. throw new ArgumentException("Invalid index.");
  328. pointSpriteList[index].Rotation = rotation;
  329. needToUpdate = true;
  330. }
  331. /// <summary>
  332. /// flips each sprite object around x-axis and/or y-axis.
  333. /// </summary>
  334. /// <param name="index">an index of sprite object</param>
  335. /// <param name="flipX">specifies whether to rotate around x-axis</param>
  336. /// <param name="flipY">specifies whether to rotate around y-axis</param>
  337. public void SetFlip(int index, bool flipX, bool flipY)
  338. {
  339. if (pointSpriteList.Count <= index || 0 > index)
  340. throw new ArgumentException("Invalid index.");
  341. pointSpriteList[index].FlipX = flipX;
  342. pointSpriteList[index].FlipY = flipY;
  343. needToUpdate = true;
  344. }
  345. /// <summary>
  346. /// configures the size of each sprite object.
  347. /// </summary>
  348. /// <param name="index">an index of sprite object</param>
  349. /// <param name="size">size vector</param>
  350. public void SetSize(int index, Vector2 size)
  351. {
  352. if (pointSpriteList.Count <= index || 0 > index)
  353. throw new ArgumentException("Invalid index.");
  354. pointSpriteList[index].Width = size.X;
  355. pointSpriteList[index].Height = size.Y;
  356. pointSpriteList[index].AddUpdateType(PointSpriteObject.UpdateTypes.Position);
  357. needToUpdate = true;
  358. }
  359. /// <summary>
  360. /// configures the size of each sprite object.
  361. /// </summary>
  362. /// <param name="index">an index of sprite object</param>
  363. /// <param name="width">size of width</param>
  364. /// <param name="height">size of height</param>
  365. public void SetSize(int index, float width, float height)
  366. {
  367. SetSize(index, new Vector2(width, height));
  368. }
  369. /// <summary>
  370. /// gets the size of each sprite object
  371. /// </summary>
  372. /// <param name="index">an index of sprite object</param>
  373. /// <returns>size vector</returns>
  374. public Vector2 GetSize(int index)
  375. {
  376. if (pointSpriteList.Count <= index || 0 > index)
  377. throw new ArgumentException("Invalid index.");
  378. return new Vector2(pointSpriteList[index].Width,
  379. pointSpriteList[index].Height);
  380. }
  381. /// <summary>
  382. /// configures the texture coordinates of each sprite object.
  383. /// </summary>
  384. /// <param name="index">an index of sprite object</param>
  385. /// <param name="min">texture coordinates of minimum</param>
  386. /// <param name="max">texture coordinates of maximum</param>
  387. public void SetTextureCoord(int index, Vector2 min, Vector2 max)
  388. {
  389. if (pointSpriteList.Count <= index || 0 > index)
  390. throw new ArgumentException("Invalid index.");
  391. pointSpriteList[index].MinUV = min;
  392. pointSpriteList[index].MaxUV = max;
  393. pointSpriteList[index].AddUpdateType(
  394. PointSpriteObject.UpdateTypes.Texturecoord);
  395. needToUpdate = true;
  396. }
  397. /// <summary>
  398. /// configures the texture coordinates of each sprite object.
  399. /// </summary>
  400. /// <param name="index">an index of sprite object</param>
  401. /// <param name="u1">texture "u1" coordinate</param>
  402. /// <param name="v1">texture "v1" coordinate</param>
  403. /// <param name="u2">texture "u2" coordinate</param>
  404. /// <param name="v2">texture "v2" coordinate</param>
  405. public void SetTextureCoord(int index, float u1, float v1, float u2, float v2)
  406. {
  407. SetTextureCoord(index, new Vector2(u1, v1), new Vector2(u2, v2));
  408. }
  409. /// <summary>
  410. /// configures the vertex color of each sprite object.
  411. /// </summary>
  412. /// <param name="index">an index of sprite object</param>
  413. /// <param name="color">color</param>
  414. public void SetColor(int index, Color color)
  415. {
  416. if (pointSpriteList.Count <= index || 0 > index)
  417. throw new ArgumentException("Invalid index.");
  418. pointSpriteList[index].Color = color;
  419. pointSpriteList[index].AddUpdateType(PointSpriteObject.UpdateTypes.Color);
  420. needToUpdate = true;
  421. }
  422. /// <summary>
  423. /// configures the vertex color of each sprite object.
  424. /// </summary>
  425. /// <param name="index">an index of sprite object</param>
  426. /// <param name="r">a red component of color</param>
  427. /// <param name="g">a green component of color</param>
  428. /// <param name="b">a blue component of color</param>
  429. /// <param name="a">an alpha component of color</param>
  430. public void SetColor(int index, byte r, byte g, byte b, byte a)
  431. {
  432. SetColor(index, new Color(r, g, b, a));
  433. }
  434. /// <summary>
  435. /// configures a transformed matrix to the vertex component data
  436. /// using the sprite object.
  437. /// </summary>
  438. /// <param name="vertexData">target vertex component data</param>
  439. /// <param name="obj">source sprite object</param>
  440. /// <param name="startIndex">start index of the vertex component data</param>
  441. /// <param name="transformMatrix">transformed matrix</param>
  442. /// <param name="space">3D render space</param>
  443. private static void SetBufferPosition(
  444. ref VertexPositionColorTexture[] vertexData, PointSpriteObject obj,
  445. int startIndex, Matrix transformMatrix, RenderingSpace space)
  446. {
  447. float cx = obj.Width * 0.5f;
  448. float cy = obj.Height * 0.5f;
  449. switch (obj.Rotation)
  450. {
  451. case PointSpriteObject.RotationAngle.Angle0:
  452. {
  453. vertexData[startIndex + 0].Position =
  454. new Vector3(-cx, -cy, 0.0f);
  455. vertexData[startIndex + 1].Position =
  456. new Vector3(+cx, -cy, 0.0f);
  457. vertexData[startIndex + 2].Position =
  458. new Vector3(+cx, +cy, 0.0f);
  459. vertexData[startIndex + 3].Position =
  460. new Vector3(-cx, +cy, 0.0f);
  461. }
  462. break;
  463. case PointSpriteObject.RotationAngle.Angle90:
  464. {
  465. vertexData[startIndex + 0].Position =
  466. new Vector3(+cx, -cy, 0.0f);
  467. vertexData[startIndex + 1].Position =
  468. new Vector3(+cx, +cy, 0.0f);
  469. vertexData[startIndex + 2].Position =
  470. new Vector3(-cx, +cy, 0.0f);
  471. vertexData[startIndex + 3].Position =
  472. new Vector3(-cx, -cy, 0.0f);
  473. }
  474. break;
  475. case PointSpriteObject.RotationAngle.Angle180:
  476. {
  477. vertexData[startIndex + 0].Position =
  478. new Vector3(+cx, +cy, 0.0f);
  479. vertexData[startIndex + 1].Position =
  480. new Vector3(-cx, +cy, 0.0f);
  481. vertexData[startIndex + 2].Position =
  482. new Vector3(-cx, -cy, 0.0f);
  483. vertexData[startIndex + 3].Position =
  484. new Vector3(+cx, -cy, 0.0f);
  485. }
  486. break;
  487. case PointSpriteObject.RotationAngle.Angle270:
  488. {
  489. vertexData[startIndex + 0].Position =
  490. new Vector3(-cx, +cy, 0.0f);
  491. vertexData[startIndex + 1].Position =
  492. new Vector3(-cx, -cy, 0.0f);
  493. vertexData[startIndex + 2].Position =
  494. new Vector3(+cx, -cy, 0.0f);
  495. vertexData[startIndex + 3].Position =
  496. new Vector3(+cx, +cy, 0.0f);
  497. }
  498. break;
  499. }
  500. for (int i = 0; i < 4; i++)
  501. {
  502. int arrayIndex = startIndex + i;
  503. Vector3.TransformNormal(ref vertexData[arrayIndex].Position,
  504. ref transformMatrix,
  505. out vertexData[arrayIndex].Position);
  506. vertexData[arrayIndex].Position += obj.Center;
  507. if (space == RenderingSpace.Screen)
  508. {
  509. vertexData[arrayIndex].Position =
  510. HelperMath.Make2DCoord(vertexData[arrayIndex].Position);
  511. }
  512. }
  513. }
  514. /// <summary>
  515. /// configures texture coordinates to the vertex component data
  516. /// using the sprite object.
  517. /// </summary>
  518. /// <param name="vertexData">target vertex component data</param>
  519. /// <param name="obj">source sprite object</param>
  520. /// <param name="startIndex">start index of the vertex component data</param>
  521. /// <param name="space">3D render space</param>
  522. private static void SetBufferTextureCoord(
  523. ref VertexPositionColorTexture[] vertexData, PointSpriteObject obj,
  524. int startIndex, RenderingSpace space)
  525. {
  526. float u1 = 0.0f, v1 = 0.0f, u2 = 0.0f, v2 = 0.0f;
  527. // Differ Y axis of the 3D and 2D
  528. bool flipY = (space == RenderingSpace.Screen ? !obj.FlipY : obj.FlipY);
  529. if (obj.FlipX)
  530. {
  531. if (flipY)
  532. {
  533. u1 = obj.MaxUV.X;
  534. v1 = obj.MaxUV.Y;
  535. u2 = obj.MinUV.X;
  536. v2 = obj.MinUV.Y;
  537. }
  538. else
  539. {
  540. u1 = obj.MaxUV.X;
  541. v1 = obj.MinUV.Y;
  542. u2 = obj.MinUV.X;
  543. v2 = obj.MaxUV.Y;
  544. }
  545. }
  546. else
  547. {
  548. if (flipY)
  549. {
  550. u1 = obj.MinUV.X;
  551. v1 = obj.MaxUV.Y;
  552. u2 = obj.MaxUV.X;
  553. v2 = obj.MinUV.Y;
  554. }
  555. else
  556. {
  557. u1 = obj.MinUV.X;
  558. v1 = obj.MinUV.Y;
  559. u2 = obj.MaxUV.X;
  560. v2 = obj.MaxUV.Y;
  561. }
  562. }
  563. vertexData[startIndex + 0].TextureCoordinate = new Vector2(u1, v1);
  564. vertexData[startIndex + 1].TextureCoordinate = new Vector2(u2, v1);
  565. vertexData[startIndex + 2].TextureCoordinate = new Vector2(u2, v2);
  566. vertexData[startIndex + 3].TextureCoordinate = new Vector2(u1, v2);
  567. }
  568. /// <summary>
  569. /// configures vertex color to the vertex component data using the sprite object.
  570. /// </summary>
  571. /// <param name="vertexData">target vertex component data</param>
  572. /// <param name="obj">source sprite object</param>
  573. /// <param name="startIndex">start index of the vertex component data</param>
  574. private static void SetBufferColor(ref VertexPositionColorTexture[] vertexData,
  575. PointSpriteObject obj, int startIndex)
  576. {
  577. for (int i = 0; i < 4; i++)
  578. vertexData[startIndex + i].Color = obj.Color;
  579. }
  580. }
  581. }