llgltfprimitive.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. /**
  2. * @file llgltfprimitive.cpp
  3. * @brief LL GLTF Implementation
  4. *
  5. * $LicenseInfo:firstyear=2024&license=viewergpl$
  6. *
  7. * Copyright (c) 2024, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #include "linden_common.h"
  33. #include "tinygltf/tiny_gltf.h"
  34. #include "llgltfprimitive.h"
  35. #include "llgltfasset.h"
  36. #include "llgltfbufferutil.h"
  37. using namespace LLGLTF;
  38. Primitive::Primitive()
  39. : mMaterial(-1),
  40. mMode(TINYGLTF_MODE_TRIANGLES),
  41. mGLMode(LLRender::TRIANGLES),
  42. mIndices(-1)
  43. {
  44. }
  45. Primitive::~Primitive()
  46. {
  47. mOctree = NULL;
  48. }
  49. // Allocates a vertex buffer. We diverge from the intent of the GLTF format
  50. // here to work with our existing render pipeline. GLTF wants us to copy the
  51. // buffer views into GPU storage as is and build render commands that source
  52. // that data. For our engine, though, it is better to rearrange the buffers at
  53. // load time into a layout which is more consistent. The GLTF native approach
  54. // undoubtedly works well if you can count on VAOs, but VAOs perform much worse
  55. // with our scenes.
  56. // Returns true on success, or false on failure. HB
  57. bool Primitive::allocateGLResources(Asset& asset)
  58. {
  59. // Load vertex data
  60. for (auto& it : mAttributes)
  61. {
  62. const std::string& attribName = it.first;
  63. Accessor& accessor = asset.mAccessors[it.second];
  64. // load vertex data
  65. if (attribName == "POSITION")
  66. {
  67. copy(asset, accessor, mPositions);
  68. }
  69. else if (attribName == "NORMAL")
  70. {
  71. copy(asset, accessor, mNormals);
  72. }
  73. else if (attribName == "TANGENT")
  74. {
  75. copy(asset, accessor, mTangents);
  76. }
  77. else if (attribName == "COLOR_0")
  78. {
  79. copy(asset, accessor, mColors);
  80. }
  81. else if (attribName == "TEXCOORD_0")
  82. {
  83. copy(asset, accessor, mTexCoords);
  84. }
  85. else if (attribName == "JOINTS_0")
  86. {
  87. copy(asset, accessor, mJoints);
  88. }
  89. else if (attribName == "WEIGHTS_0")
  90. {
  91. copy(asset, accessor, mWeights);
  92. }
  93. }
  94. if (mPositions.size() > 65536)
  95. {
  96. // This would trigger an llerrs in LLVertexBuffer::allocateBuffer(). HB
  97. llwarns << "Too many vertices: " << mPositions.size() << ". Aborted."
  98. << llendl
  99. return false;
  100. }
  101. // Copy index buffer
  102. if (mIndices != INVALID_INDEX)
  103. {
  104. Accessor& accessor = asset.mAccessors[mIndices];
  105. copy(asset, accessor, mIndexArray);
  106. }
  107. U32 mask = ATTRIBUTE_MASK;
  108. if (!mWeights.empty())
  109. {
  110. mask |= LLVertexBuffer::MAP_WEIGHT4;
  111. }
  112. mVertexBuffer = new LLVertexBuffer(mask);
  113. // Double the size of the index buffer for 32-bit indices
  114. mVertexBuffer->allocateBuffer(mPositions.size(), mIndexArray.size() * 2);
  115. mVertexBuffer->setBuffer();
  116. mVertexBuffer->setPositionData(mPositions.data());
  117. if (!mIndexArray.empty())
  118. {
  119. mVertexBuffer->setIndexData(mIndexArray.data());
  120. }
  121. if (mTexCoords.empty())
  122. {
  123. mTexCoords.resize(mPositions.size());
  124. }
  125. // Flip texcoord y, upload, then flip back (keep the off-spec data in VRAM
  126. //only)
  127. for (auto& tc : mTexCoords)
  128. {
  129. tc[1] = 1.f - tc[1];
  130. }
  131. mVertexBuffer->setTexCoord0Data(mTexCoords.data());
  132. for (auto& tc : mTexCoords)
  133. {
  134. tc[1] = 1.f - tc[1];
  135. }
  136. if (mColors.empty())
  137. {
  138. mColors.resize(mPositions.size(), LLColor4U::white);
  139. }
  140. // bake material basecolor into color array
  141. if (mMaterial != INVALID_INDEX)
  142. {
  143. const Material& material = asset.mMaterials[mMaterial];
  144. LLColor4 baseColor = material.mMaterial->mBaseColor;
  145. for (auto& dst : mColors)
  146. {
  147. dst = LLColor4U(baseColor * LLColor4(dst));
  148. }
  149. }
  150. mVertexBuffer->setColorData(mColors.data());
  151. if (mNormals.empty())
  152. {
  153. mNormals.resize(mPositions.size(), LLVector4a(0, 0, 1, 0));
  154. }
  155. mVertexBuffer->setNormalData(mNormals.data());
  156. if (mTangents.empty())
  157. {
  158. // TODO: generate tangents if needed
  159. mTangents.resize(mPositions.size(), LLVector4a(1, 0, 0, 1));
  160. }
  161. mVertexBuffer->setTangentData(mTangents.data());
  162. if (!mWeights.empty())
  163. {
  164. std::vector<LLVector4a> weight_data;
  165. weight_data.resize(mWeights.size());
  166. F32 max_weight = 1.f - FLT_EPSILON * 100.f;
  167. LLVector4a maxw(max_weight, max_weight, max_weight, max_weight);
  168. for (U32 i = 0; i < mWeights.size(); ++i)
  169. {
  170. LLVector4a& w = weight_data[i];
  171. w.setMin(mWeights[i], maxw);
  172. w.add(mJoints[i]);
  173. }
  174. mVertexBuffer->setWeight4Data(weight_data.data());
  175. }
  176. createOctree();
  177. mVertexBuffer->unbind();
  178. return true;
  179. }
  180. static void init_octree_triangle(LLVolumeTriangle* trianglep, S32 i0, S32 i1,
  181. S32 i2, const LLVector4a& v0,
  182. const LLVector4a& v1, const LLVector4a& v2)
  183. {
  184. // Store pointers to vertex data
  185. trianglep->mV[0] = &v0;
  186. trianglep->mV[1] = &v1;
  187. trianglep->mV[2] = &v2;
  188. // Store indices
  189. trianglep->mIndex[0] = i0;
  190. trianglep->mIndex[1] = i1;
  191. trianglep->mIndex[2] = i2;
  192. // Get minimum point
  193. LLVector4a min = v0;
  194. min.setMin(min, v1);
  195. min.setMin(min, v2);
  196. // Get maximum point
  197. LLVector4a max = v0;
  198. max.setMax(max, v1);
  199. max.setMax(max, v2);
  200. // Compute center
  201. LLVector4a center;
  202. center.setAdd(min, max);
  203. center.mul(0.5f);
  204. trianglep->mPositionGroup = center;
  205. // Compute "radius"
  206. LLVector4a size;
  207. size.setSub(max, min);
  208. constexpr F32 scaler = 0.25f;
  209. trianglep->mRadius = size.getLength3().getF32() * scaler;
  210. }
  211. void Primitive::createOctree()
  212. {
  213. mOctree = new LLVolumeOctree();
  214. const U32 num_indices = mVertexBuffer->getNumIndices();
  215. if (num_indices < 3)
  216. {
  217. // Degenerate triangle: no volume ! HB
  218. llwarns << "Degenerate triangle found" << llendl;
  219. }
  220. else if (mMode == TINYGLTF_MODE_TRIANGLES)
  221. {
  222. const U32 num_triangles = num_indices / 3;
  223. // Initialize all the triangles we need
  224. mOctreeTriangles.resize(num_triangles);
  225. for (U32 tri_idx = 0; tri_idx < num_triangles; ++tri_idx)
  226. {
  227. const U32 index = tri_idx * 3;
  228. S32 i0 = mIndexArray[index];
  229. S32 i1 = mIndexArray[index + 1];
  230. S32 i2 = mIndexArray[index + 2];
  231. const LLVector4a& v0 = mPositions[i0];
  232. const LLVector4a& v1 = mPositions[i1];
  233. const LLVector4a& v2 = mPositions[i2];
  234. LLVolumeTriangle* trianglep = &mOctreeTriangles[tri_idx];
  235. init_octree_triangle(trianglep, i0, i1, i2, v0, v1, v2);
  236. mOctree->insert(trianglep);
  237. }
  238. }
  239. else if (mMode == TINYGLTF_MODE_TRIANGLE_STRIP)
  240. {
  241. const U32 num_triangles = num_indices - 2;
  242. // Initialize all the triangles we need
  243. mOctreeTriangles.resize(num_triangles);
  244. for (U32 tri_idx = 0; tri_idx < num_triangles; ++tri_idx)
  245. {
  246. const U32 index = tri_idx + 2;
  247. S32 i0 = mIndexArray[index];
  248. S32 i1 = mIndexArray[index - 1];
  249. S32 i2 = mIndexArray[index - 2];
  250. const LLVector4a& v0 = mPositions[i0];
  251. const LLVector4a& v1 = mPositions[i1];
  252. const LLVector4a& v2 = mPositions[i2];
  253. LLVolumeTriangle* trianglep = &mOctreeTriangles[tri_idx];
  254. init_octree_triangle(trianglep, i0, i1, i2, v0, v1, v2);
  255. mOctree->insert(trianglep);
  256. }
  257. }
  258. else if (mMode == TINYGLTF_MODE_TRIANGLE_FAN)
  259. {
  260. const U32 num_triangles = num_indices - 2;
  261. // Initialize all the triangles we need
  262. mOctreeTriangles.resize(num_triangles);
  263. for (U32 tri_idx = 0; tri_idx < num_triangles; ++tri_idx)
  264. {
  265. const U32 index = tri_idx + 2;
  266. S32 i0 = mIndexArray[0];
  267. S32 i1 = mIndexArray[index - 1];
  268. S32 i2 = mIndexArray[index - 2];
  269. const LLVector4a& v0 = mPositions[i0];
  270. const LLVector4a& v1 = mPositions[i1];
  271. const LLVector4a& v2 = mPositions[i2];
  272. LLVolumeTriangle* trianglep = &mOctreeTriangles[tri_idx];
  273. init_octree_triangle(trianglep, i0, i1, i2, v0, v1, v2);
  274. mOctree->insert(trianglep);
  275. }
  276. }
  277. else
  278. {
  279. llwarns << "Unsupported primitive mode: " << mMode << llendl;
  280. }
  281. // Remove unneeded octree layers
  282. while (!mOctree->balance()) ;
  283. // Calculate AABB for each node
  284. LLVolumeOctreeRebound rebound;
  285. rebound.traverse(mOctree);
  286. }
  287. const LLVolumeTriangle* Primitive::lineSegmentIntersect(const LLVector4a& start,
  288. const LLVector4a& end,
  289. LLVector4a* interp,
  290. LLVector2* tcoordp,
  291. LLVector4a* normp,
  292. LLVector4a* tgtp)
  293. {
  294. if (mOctree.isNull())
  295. {
  296. return NULL;
  297. }
  298. LLVector4a dir;
  299. dir.setSub(end, start);
  300. F32 closest_t = 2.f; // Must be larger than 1
  301. // Create a proxy LLVolumeFace for the raycast
  302. LLVolumeFace face;
  303. face.mPositions = mPositions.data();
  304. face.mTexCoords = mTexCoords.data();
  305. face.mNormals = mNormals.data();
  306. face.mTangents = mTangents.data();
  307. face.mIndices = NULL; // unreferenced
  308. face.mNumIndices = mIndexArray.size();
  309. face.mNumVertices = mPositions.size();
  310. LLOctreeTriangleRayIntersectNoOwnership intersect(start, dir, &face,
  311. &closest_t, interp,
  312. tcoordp, normp, tgtp);
  313. intersect.traverse(mOctree);
  314. // Null out proxy data so it does not get freed
  315. face.mPositions = face.mNormals = face.mTangents = NULL;
  316. face.mIndices = NULL;
  317. face.mTexCoords = NULL;
  318. return intersect.mHitTriangle;
  319. }
  320. const Primitive& Primitive::operator=(const tinygltf::Primitive& src)
  321. {
  322. // Load material
  323. mMaterial = src.material;
  324. // Load mode
  325. mMode = src.mode;
  326. // Load indices
  327. mIndices = src.indices;
  328. // Load attributes
  329. for (auto& it : src.attributes)
  330. {
  331. mAttributes[it.first] = it.second;
  332. }
  333. switch (mMode)
  334. {
  335. case TINYGLTF_MODE_POINTS:
  336. mGLMode = LLRender::POINTS;
  337. break;
  338. case TINYGLTF_MODE_LINE:
  339. mGLMode = LLRender::LINES;
  340. break;
  341. case TINYGLTF_MODE_LINE_LOOP:
  342. mGLMode = LLRender::LINE_LOOP;
  343. break;
  344. case TINYGLTF_MODE_LINE_STRIP:
  345. mGLMode = LLRender::LINE_STRIP;
  346. break;
  347. case TINYGLTF_MODE_TRIANGLES:
  348. mGLMode = LLRender::TRIANGLES;
  349. break;
  350. case TINYGLTF_MODE_TRIANGLE_STRIP:
  351. mGLMode = LLRender::TRIANGLE_STRIP;
  352. break;
  353. case TINYGLTF_MODE_TRIANGLE_FAN:
  354. mGLMode = LLRender::TRIANGLE_FAN;
  355. break;
  356. default:
  357. mGLMode = GL_TRIANGLES;
  358. }
  359. return *this;
  360. }