VoxelModelImporter.cs 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. #region License
  2. // Copyright 2015-2016 Kastellanos Nikolaos
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. #endregion
  16. using System;
  17. using System.Collections.Generic;
  18. using System.IO;
  19. using Microsoft.Xna.Framework;
  20. using Microsoft.Xna.Framework.Content.Pipeline;
  21. using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
  22. using Microsoft.Xna.Framework.Graphics;
  23. namespace nkast.Aether.Content.Pipeline
  24. {
  25. [ContentImporter(".vox", DisplayName = "Voxel Model Importer - Aether", DefaultProcessor = "ModelProcessor")]
  26. public class VoxelModelImporter : ContentImporter<NodeContent>
  27. {
  28. public override NodeContent Import(string filename, ContentImporterContext context)
  29. {
  30. VoxelContent voxel = null;
  31. if (Path.GetExtension(filename) == ".vox")
  32. {
  33. VoxImporter voxelImporter = new VoxImporter();
  34. voxel = voxelImporter.ImportVox(filename, context);
  35. }
  36. else
  37. {
  38. throw new InvalidContentException("File type not supported.");
  39. }
  40. voxel.MarkSharedSides();
  41. voxel.RemoveHiddenBlocks();
  42. NodeContent output = VoxelProcess(voxel, context);
  43. return output;
  44. }
  45. /// <summary>
  46. /// Import a VOX file as Model
  47. /// </summary>
  48. private NodeContent VoxelProcess(VoxelContent voxel, ContentImporterContext context)
  49. {
  50. XYZI[] voxels = voxel.Voxels;
  51. uint[] palette = voxel.Palette;
  52. Vector3 scale = voxel.RealSize / voxel.GridSize;
  53. Vector3 centerOffset = new Vector3(1f, 1f, 1f) * (voxel.RealSize / -2f);
  54. Point3 corner000 = new Point3(0, 0, 0);
  55. Point3 corner100 = new Point3(1, 0, 0);
  56. Point3 corner010 = new Point3(0, 1, 0);
  57. Point3 corner110 = new Point3(1, 1, 0);
  58. Point3 corner001 = new Point3(0, 0, 1);
  59. Point3 corner101 = new Point3(1, 0, 1);
  60. Point3 corner011 = new Point3(0, 1, 1);
  61. Point3 corner111 = new Point3(1, 1, 1);
  62. Vector3 Forward = Vector3.Forward;
  63. Vector3 Backward = Vector3.Backward;
  64. Vector3 Left = Vector3.Left;
  65. Vector3 Right = Vector3.Right;
  66. Vector3 Up = Vector3.Up;
  67. Vector3 Down = Vector3.Down;
  68. for (int i = 0; i < voxels.Length; i++)
  69. {
  70. Point3 pt000 = voxels[i].Point.Add(ref corner000);
  71. Point3 pt100 = voxels[i].Point.Add(ref corner100);
  72. Point3 pt010 = voxels[i].Point.Add(ref corner010);
  73. Point3 pt110 = voxels[i].Point.Add(ref corner110);
  74. Point3 pt001 = voxels[i].Point.Add(ref corner001);
  75. Point3 pt101 = voxels[i].Point.Add(ref corner101);
  76. Point3 pt011 = voxels[i].Point.Add(ref corner011);
  77. Point3 pt111 = voxels[i].Point.Add(ref corner111);
  78. // back
  79. Vector3 p0 = pt000.ToVector3();
  80. Vector3 p1 = pt100.ToVector3();
  81. Vector3 p2 = pt010.ToVector3();
  82. Vector3 p3 = pt110.ToVector3();
  83. // front
  84. Vector3 p4 = pt001.ToVector3();
  85. Vector3 p5 = pt101.ToVector3();
  86. Vector3 p6 = pt011.ToVector3();
  87. Vector3 p7 = pt111.ToVector3();
  88. Vector3.Multiply(ref p0, ref scale, out p0); Vector3.Add(ref p0, ref centerOffset, out p0);
  89. Vector3.Multiply(ref p1, ref scale, out p1); Vector3.Add(ref p1, ref centerOffset, out p1);
  90. Vector3.Multiply(ref p2, ref scale, out p2); Vector3.Add(ref p2, ref centerOffset, out p2);
  91. Vector3.Multiply(ref p3, ref scale, out p3); Vector3.Add(ref p3, ref centerOffset, out p3);
  92. Vector3.Multiply(ref p4, ref scale, out p4); Vector3.Add(ref p4, ref centerOffset, out p4);
  93. Vector3.Multiply(ref p5, ref scale, out p5); Vector3.Add(ref p5, ref centerOffset, out p5);
  94. Vector3.Multiply(ref p6, ref scale, out p6); Vector3.Add(ref p6, ref centerOffset, out p6);
  95. Vector3.Multiply(ref p7, ref scale, out p7); Vector3.Add(ref p7, ref centerOffset, out p7);
  96. vertex.Color.PackedValue = palette[voxels[i].ColorIndex];
  97. if ((voxels[i].SharedSides & Sides.Forward) == 0)
  98. {
  99. vertex.Normal = Forward;
  100. AddVertex(ref p1);
  101. AddVertex(ref p3);
  102. AddVertex(ref p0);
  103. AddVertex(ref p0);
  104. AddVertex(ref p3);
  105. AddVertex(ref p2);
  106. }
  107. if ((voxels[i].SharedSides & Sides.Backward) == 0)
  108. {
  109. vertex.Normal = Backward;
  110. AddVertex(ref p4);
  111. AddVertex(ref p6);
  112. AddVertex(ref p5);
  113. AddVertex(ref p5);
  114. AddVertex(ref p6);
  115. AddVertex(ref p7);
  116. }
  117. if ((voxels[i].SharedSides & Sides.Left) == 0)
  118. {
  119. vertex.Normal = Left;
  120. AddVertex(ref p2);
  121. AddVertex(ref p6);
  122. AddVertex(ref p0);
  123. AddVertex(ref p0);
  124. AddVertex(ref p6);
  125. AddVertex(ref p4);
  126. }
  127. if ((voxels[i].SharedSides & Sides.Right) == 0)
  128. {
  129. vertex.Normal = Right;
  130. AddVertex(ref p1);
  131. AddVertex(ref p5);
  132. AddVertex(ref p3);
  133. AddVertex(ref p3);
  134. AddVertex(ref p5);
  135. AddVertex(ref p7);
  136. }
  137. if ((voxels[i].SharedSides & Sides.Up) == 0)
  138. {
  139. vertex.Normal = Up;
  140. AddVertex(ref p7);
  141. AddVertex(ref p6);
  142. AddVertex(ref p3);
  143. AddVertex(ref p3);
  144. AddVertex(ref p6);
  145. AddVertex(ref p2);
  146. }
  147. if ((voxels[i].SharedSides & Sides.Down) == 0)
  148. {
  149. vertex.Normal = Down;
  150. AddVertex(ref p5);
  151. AddVertex(ref p1);
  152. AddVertex(ref p4);
  153. AddVertex(ref p4);
  154. AddVertex(ref p1);
  155. AddVertex(ref p0);
  156. }
  157. }
  158. MeshContent mesh = new MeshContent();
  159. mesh.Name = "voxel";
  160. for (int pi = 0; pi < this.vertices.Count; pi++)
  161. {
  162. mesh.Positions.Add(this.vertices[pi].Position);
  163. }
  164. GeometryContent geom = new GeometryContent();
  165. mesh.Geometry.Add(geom);
  166. BasicMaterialContent material = new BasicMaterialContent();
  167. geom.Material = material;
  168. for (int pi = 0; pi < this.vertices.Count; pi++)
  169. {
  170. geom.Vertices.Add(pi);
  171. }
  172. for (int ii = 0; ii < this.indices.Count; ii++)
  173. {
  174. geom.Indices.Add(this.indices[ii]);
  175. }
  176. List<Vector3> normals = new List<Vector3>();
  177. List<Color> colors = new List<Color>();
  178. for (int vi = 0; vi < this.vertices.Count; vi++)
  179. {
  180. var vertex = vertices[vi];
  181. normals.Add(vertex.Normal);
  182. colors.Add(vertex.Color);
  183. }
  184. geom.Vertices.Channels.Add<Vector3>(VertexChannelNames.Normal(0), normals);
  185. geom.Vertices.Channels.Add<Color>(VertexChannelNames.Color(0), colors);
  186. return mesh;
  187. }
  188. List<VertexPositionNormalColor> vertices = new List<VertexPositionNormalColor>();
  189. List<int> indices = new List<int>();
  190. Dictionary<VertexPositionNormalColor, int> vertexMap = new Dictionary<VertexPositionNormalColor, int>();
  191. VertexPositionNormalColor vertex;
  192. private int AddVertex(ref Vector3 position)
  193. {
  194. vertex.Position = position;
  195. int vertIndx;
  196. if (!vertexMap.TryGetValue(vertex, out vertIndx))
  197. {
  198. vertIndx = vertices.Count;
  199. vertices.Add(vertex);
  200. vertexMap.Add(vertex, vertIndx);
  201. }
  202. indices.Add(vertIndx);
  203. return vertIndx;
  204. }
  205. }
  206. }