AkGeometryData.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. /*******************************************************************************
  2. The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
  3. Technology released in source code form as part of the game integration package.
  4. The content of this file may not be used without valid licenses to the
  5. AUDIOKINETIC Wwise Technology.
  6. Note that the use of the game engine is subject to the Unreal(R) Engine End User
  7. License Agreement at https://www.unrealengine.com/en-US/eula/unreal
  8. License Usage
  9. Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
  10. this file in accordance with the end user license agreement provided with the
  11. software or, alternatively, in accordance with the terms contained
  12. in a written agreement between you and Audiokinetic Inc.
  13. Copyright (c) 2023 Audiokinetic Inc.
  14. *******************************************************************************/
  15. #include "AkGeometryData.h"
  16. #include "PhysicalMaterials/PhysicalMaterial.h"
  17. void GetBasicBoxGeometryData(TArray<FVector>& Vertices, TArray<FAkTriangle>& Triangles)
  18. {
  19. Vertices.Init(FVector(0, 0, 0), 8);
  20. Vertices[0] = FVector(-1, -1, -1);
  21. Vertices[1] = FVector(-1, -1, 1);
  22. Vertices[2] = FVector(-1, 1, -1);
  23. Vertices[3] = FVector(-1, 1, 1);
  24. Vertices[4] = FVector(1, -1, -1);
  25. Vertices[5] = FVector(1, -1, 1);
  26. Vertices[6] = FVector(1, 1, -1);
  27. Vertices[7] = FVector(1, 1, 1);
  28. Triangles.Init(FAkTriangle(), 12);
  29. Triangles[0] = { 0, 1, 3, AK_INVALID_SURFACE };
  30. Triangles[1] = { 0, 1, 5, AK_INVALID_SURFACE };
  31. Triangles[2] = { 0, 2, 3, AK_INVALID_SURFACE };
  32. Triangles[3] = { 0, 2, 6, AK_INVALID_SURFACE };
  33. Triangles[4] = { 0, 4, 5, AK_INVALID_SURFACE };
  34. Triangles[5] = { 0, 4, 6, AK_INVALID_SURFACE };
  35. Triangles[6] = { 1, 3, 7, AK_INVALID_SURFACE };
  36. Triangles[7] = { 1, 5, 7, AK_INVALID_SURFACE };
  37. Triangles[8] = { 2, 3, 7, AK_INVALID_SURFACE };
  38. Triangles[9] = { 2, 6, 7, AK_INVALID_SURFACE };
  39. Triangles[10] = { 4, 5, 7, AK_INVALID_SURFACE };
  40. Triangles[11] = { 4, 6, 7, AK_INVALID_SURFACE };
  41. }
  42. void GetBasicXYPlaneGeometryData(TArray<FVector>& Vertices, TArray<FAkTriangle>& Triangles)
  43. {
  44. Vertices.Init(FVector(0, 0, 0), 4);
  45. Vertices[0] = FVector(-1, -1, 1);
  46. Vertices[1] = FVector(-1, 1, 1);
  47. Vertices[2] = FVector(1, -1, 1);
  48. Vertices[3] = FVector(1, 1, 1);
  49. Triangles.Init(FAkTriangle(), 2);
  50. Triangles[0] = { 0, 1, 2, AK_INVALID_SURFACE };
  51. Triangles[1] = { 1, 3, 2, AK_INVALID_SURFACE };
  52. }
  53. void GetBasicXZPlaneGeometryData(TArray<FVector>& Vertices, TArray<FAkTriangle>& Triangles)
  54. {
  55. Vertices.Init(FVector(0, 0, 0), 4);
  56. Vertices[0] = FVector(-1, 1, -1);
  57. Vertices[1] = FVector(-1, 1, 1);
  58. Vertices[2] = FVector(1, 1, -1);
  59. Vertices[3] = FVector(1, 1, 1);
  60. Triangles.Init(FAkTriangle(), 2);
  61. Triangles[0] = { 0, 1, 2, AK_INVALID_SURFACE };
  62. Triangles[1] = { 1, 3, 2, AK_INVALID_SURFACE };
  63. }
  64. void GetBasicYZPlaneGeometryData(TArray<FVector>& Vertices, TArray<FAkTriangle>& Triangles)
  65. {
  66. Vertices.Init(FVector(0, 0, 0), 4);
  67. Vertices[0] = FVector(1, -1, -1);
  68. Vertices[1] = FVector(1, -1, 1);
  69. Vertices[2] = FVector(1, 1, -1);
  70. Vertices[3] = FVector(1, 1, 1);
  71. Triangles.Init(FAkTriangle(), 2);
  72. Triangles[0] = { 0, 1, 2, AK_INVALID_SURFACE };
  73. Triangles[1] = { 1, 3, 2, AK_INVALID_SURFACE };
  74. }
  75. /** Taken from GetOrientedHalfSphereMesh in PrimitiveDrawingUtils.cpp. See original for adding tangents and texture coords. */
  76. void GenerateHalfSphereVerts(AkSurfIdx surfIdx, const FVector& Center, const FRotator& Orientation, const float Radius, int32 NumSides, int32 NumRings, float StartAngle, float EndAngle, FAkGeometryData& GeometryData)
  77. {
  78. if (NumSides <= 0 || NumRings <= 0)
  79. return;
  80. // The first/last arc are on top of each other.
  81. int32 numVerts = (NumSides + 1) * (NumRings + 1);
  82. TArray<FVector> vertices;
  83. vertices.AddDefaulted(numVerts);
  84. TArray<FAkTriangle> triangles;
  85. int32 BaseVertIndex = GeometryData.Vertices.Num();
  86. // Calculate verts for one arc
  87. TArray<FVector> arcVertices;
  88. for (int32 i = 0; i < NumRings + 1; i++)
  89. {
  90. float angle = StartAngle + ((float)i / NumRings) * (EndAngle - StartAngle);
  91. arcVertices.Add(FVector(0.0f, FMath::Sin(angle) * Radius, FMath::Cos(angle) * Radius) + Center);
  92. }
  93. // Then rotate this arc NumSides+1 times.
  94. for (int32 s = 0; s < NumSides + 1; s++)
  95. {
  96. FRotator ArcRotator(0, 360.f * (float)s / NumSides, 0);
  97. FRotationMatrix ArcRot(ArcRotator);
  98. for (int32 v = 0; v < NumRings + 1; v++)
  99. {
  100. int32 VIx = (NumRings + 1) * s + v;
  101. vertices[VIx] = ArcRot.TransformPosition(arcVertices[v]);
  102. }
  103. }
  104. // Add all of the vertices we generated to the geometry data.
  105. for (int32 vertIdx = 0; vertIdx < numVerts; vertIdx++)
  106. {
  107. GeometryData.Vertices.Add(vertices[vertIdx]);
  108. }
  109. // If StartAngle is 0, the top-most ring is the top pole, and all sides will start on the same vertex.
  110. const bool sidesStartAtTopPole = StartAngle < PI * 0.1f;
  111. // Similarly, if EndAngle is PI, the bottom-most ring is the bottom pole, and all sides will end on the same vertex.
  112. const bool sidesEndAtBottomPole = EndAngle >= PI * 0.9f;
  113. // Add all of the triangles we generated to the geometry data.
  114. for (uint16 s = 0; s < NumSides; s++)
  115. {
  116. // Add triangles between consecutive sides, from the top-most ring to the bottom.
  117. uint16 side0Start = (s + 0) * (NumRings + 1) + BaseVertIndex;
  118. uint16 side1Start = (s + 1) * (NumRings + 1) + BaseVertIndex;
  119. uint16 s0 = side0Start;
  120. uint16 s1 = side1Start;
  121. // s0 and s1 refer to the vertices running up and down the 'sides' of the sphere.
  122. // the line from vertex s0 to vertex s0 + 1 runs down one 'side'
  123. // the line from vertex s0 to vertex s1 runs along one 'ring' (from one 'side' to the other).
  124. // the line from vertex s0 to vertex s1 + 1 runs diagonally down a side and along a ring.
  125. // Add the initial triangle for this side strip (or triangles, if we're not starting on a pole)
  126. if (sidesStartAtTopPole)
  127. {
  128. GeometryData.Triangles.Add({ s0, uint16(s1 + 1), uint16(s0 + 1), surfIdx });
  129. }
  130. else
  131. {
  132. GeometryData.Triangles.Add({ s0, s1, uint16(s0 + 1), surfIdx });
  133. GeometryData.Triangles.Add({ s1, uint16(s1 + 1), uint16(s0 + 1), surfIdx });
  134. }
  135. for (uint16 r = 1; r < NumRings - 1; r++)
  136. {
  137. s0 = side0Start + r;
  138. s1 = side1Start + r;
  139. GeometryData.Triangles.Add({ s0, s1, uint16(s0 + 1), surfIdx });
  140. GeometryData.Triangles.Add({ s1, uint16(s1 + 1), uint16(s0 + 1), surfIdx });
  141. }
  142. // Add the final triangle for this side strip (or triangles if we're not ending on a pole)
  143. s0 = side0Start + (NumRings - 1);
  144. s1 = side1Start + (NumRings - 1);
  145. GeometryData.Triangles.Add({ s0, s1, uint16(s0 + 1), surfIdx });
  146. if (!sidesEndAtBottomPole)
  147. {
  148. GeometryData.Triangles.Add({ s1, uint16(s1 + 1), uint16(s0 + 1), surfIdx });
  149. }
  150. }
  151. }
  152. /** Taken from BuildCylinderVerts in PrimitiveDrawingUtils.cpp. See original for adding tangents and texture coords. */
  153. void GenerateCylinderVerts(AkSurfIdx surfIdx, const FVector& Base, const FVector& XAxis, const FVector& YAxis, const FVector& ZAxis, float Radius, float HalfHeight, uint32 Sides, FAkGeometryData& GeometryData)
  154. {
  155. const float AngleDelta = 2.0f * PI / Sides;
  156. FVector LastVertex = Base + XAxis * Radius;
  157. FVector2D TC = FVector2D(0.0f, 0.0f);
  158. float TCStep = 1.0f / Sides;
  159. FVector TopOffset = HalfHeight * ZAxis;
  160. int32 BaseVertIndex = GeometryData.Vertices.Num();
  161. //Compute vertices for base circle.
  162. for (uint32 SideIndex = 0; SideIndex < Sides; SideIndex++)
  163. {
  164. const FVector Vertex = Base + (XAxis * FMath::Cos(AngleDelta * (SideIndex + 1)) + YAxis * FMath::Sin(AngleDelta * (SideIndex + 1))) * Radius;
  165. FVector Normal = Vertex - Base;
  166. Normal.Normalize();
  167. GeometryData.Vertices.Add(Vertex - TopOffset);
  168. LastVertex = Vertex;
  169. TC.X += TCStep;
  170. }
  171. LastVertex = Base + XAxis * Radius;
  172. TC = FVector2D(0.0f, 1.0f);
  173. //Compute vertices for the top circle
  174. for (uint16 SideIndex = 0; SideIndex < Sides; SideIndex++)
  175. {
  176. const FVector Vertex = Base + (XAxis * FMath::Cos(AngleDelta * (SideIndex + 1)) + YAxis * FMath::Sin(AngleDelta * (SideIndex + 1))) * Radius;
  177. FVector Normal = Vertex - Base;
  178. Normal.Normalize();
  179. GeometryData.Vertices.Add(Vertex + TopOffset);
  180. LastVertex = Vertex;
  181. TC.X += TCStep;
  182. }
  183. //Add sides.
  184. for (uint16 SideIndex = 0; SideIndex < Sides; SideIndex++)
  185. {
  186. uint16 V0 = BaseVertIndex + SideIndex;
  187. uint16 V1 = BaseVertIndex + ((SideIndex + 1) % Sides);
  188. uint16 V2 = V0 + Sides;
  189. uint16 V3 = V1 + Sides;
  190. GeometryData.Triangles.Add({ V0, V2, V1, surfIdx });
  191. GeometryData.Triangles.Add({ V2, V3, V1, surfIdx });
  192. }
  193. }
  194. void FAkGeometryData::AddBox(AkSurfIdx surfIdx, FVector center, FVector extent, FRotator rotation)
  195. {
  196. TArray<FVector> boxVertices;
  197. TArray<FAkTriangle> boxTriangles;
  198. if (extent.Z == 0.0f)
  199. GetBasicXYPlaneGeometryData(boxVertices, boxTriangles);
  200. else if (extent.Y == 0.0f)
  201. GetBasicXZPlaneGeometryData(boxVertices, boxTriangles);
  202. else if (extent.X == 0.0f)
  203. GetBasicYZPlaneGeometryData(boxVertices, boxTriangles);
  204. else
  205. GetBasicBoxGeometryData(boxVertices, boxTriangles);
  206. AkVertIdx initialVertIdx = Vertices.Num();
  207. // move vertices according to the center and extents
  208. for (AkVertIdx idx = 0; idx < boxVertices.Num(); idx++)
  209. {
  210. FTransform transform(rotation, center, extent);
  211. FVector v = transform.TransformPosition(boxVertices[idx]);
  212. Vertices.Add(v);
  213. }
  214. for (AkTriIdx idx = 0; idx < boxTriangles.Num(); idx++)
  215. {
  216. boxTriangles[idx].Point0 += initialVertIdx;
  217. boxTriangles[idx].Point1 += initialVertIdx;
  218. boxTriangles[idx].Point2 += initialVertIdx;
  219. boxTriangles[idx].Surface = surfIdx;
  220. Triangles.Add(boxTriangles[idx]);
  221. }
  222. }
  223. void FAkGeometryData::AddSphere(AkSurfIdx surfIdx, const FVector& Center, const float Radius, int32 NumSides, int32 NumRings)
  224. {
  225. GenerateHalfSphereVerts(surfIdx, Center, FRotator::ZeroRotator, Radius, NumSides, NumRings, 0, PI, *this);
  226. }
  227. void FAkGeometryData::AddCapsule(AkSurfIdx surfIdx, const FVector& Origin, const FVector& XAxis, const FVector& YAxis, const FVector& ZAxis, float Radius, float HalfHeight, int32 NumSides)
  228. {
  229. const FVector BottomEnd = Origin - HalfHeight * ZAxis;
  230. const FVector TopEnd = Origin + HalfHeight * ZAxis;
  231. GenerateHalfSphereVerts(surfIdx, TopEnd, FRotationMatrix::MakeFromXY(XAxis, YAxis).Rotator(), Radius, NumSides, NumSides, 0, PI / 2, *this);
  232. GenerateCylinderVerts(surfIdx, Origin, XAxis, YAxis, ZAxis, Radius, HalfHeight, NumSides, *this);
  233. GenerateHalfSphereVerts(surfIdx, BottomEnd, FRotationMatrix::MakeFromXY(XAxis, YAxis).Rotator(), Radius, NumSides, NumSides, PI / 2, PI, *this);
  234. }