scene_subdiv_mesh.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900
  1. // ======================================================================== //
  2. // Copyright 2009-2017 Intel Corporation //
  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. // ======================================================================== //
  16. #include "scene_subdiv_mesh.h"
  17. #include "scene.h"
  18. #include "../subdiv/patch_eval.h"
  19. #include "../subdiv/patch_eval_simd.h"
  20. #include "../../common/algorithms/parallel_sort.h"
  21. #include "../../common/algorithms/parallel_prefix_sum.h"
  22. #include "../../common/algorithms/parallel_for.h"
  23. namespace embree
  24. {
  25. SubdivMesh::SubdivMesh (Scene* parent, RTCGeometryFlags flags, size_t numFaces, size_t numEdges, size_t numVertices,
  26. size_t numEdgeCreases, size_t numVertexCreases, size_t numHoles, size_t numTimeSteps)
  27. : Geometry(parent,SUBDIV_MESH,numFaces,numTimeSteps,flags),
  28. displFunc(nullptr),
  29. displFunc2(nullptr),
  30. displBounds(empty),
  31. tessellationRate(2.0f),
  32. numHalfEdges(0),
  33. faceStartEdge(parent->device),
  34. invalid_face(parent->device)
  35. {
  36. vertices.resize(numTimeSteps);
  37. vertex_buffer_tags.resize(numTimeSteps);
  38. for (size_t i=0; i<numTimeSteps; i++)
  39. vertices[i].init(parent->device,numVertices,sizeof(Vec3fa));
  40. faceVertices.init(parent->device,numFaces,sizeof(unsigned int));
  41. holes.init(parent->device,numHoles,sizeof(int));
  42. levels.init(parent->device,numEdges,sizeof(float));
  43. edge_creases.init(parent->device,numEdgeCreases,2*sizeof(unsigned int));
  44. edge_crease_weights.init(parent->device,numEdgeCreases,sizeof(float));
  45. vertex_creases.init(parent->device,numVertexCreases,sizeof(unsigned int));
  46. vertex_crease_weights.init(parent->device,numVertexCreases,sizeof(float));
  47. topology.resize(1);
  48. topology[0] = Topology(this,numEdges);
  49. enabling();
  50. }
  51. void SubdivMesh::enabling()
  52. {
  53. parent->numSubdivEnableDisableEvents++;
  54. if (numTimeSteps == 1) parent->world.numSubdivPatches += size();
  55. else parent->worldMB.numSubdivPatches += size();
  56. }
  57. void SubdivMesh::disabling()
  58. {
  59. parent->numSubdivEnableDisableEvents++;
  60. if (numTimeSteps == 1) parent->world.numSubdivPatches -= size();
  61. else parent->worldMB.numSubdivPatches -= size();
  62. }
  63. void SubdivMesh::setMask (unsigned mask)
  64. {
  65. if (parent->isStatic() && parent->isBuild())
  66. throw_RTCError(RTC_INVALID_OPERATION,"static scenes cannot get modified");
  67. this->mask = mask;
  68. Geometry::update();
  69. }
  70. void SubdivMesh::setSubdivisionMode (unsigned topologyID, RTCSubdivisionMode mode)
  71. {
  72. if (parent->isStatic() && parent->isBuild())
  73. throw_RTCError(RTC_INVALID_OPERATION,"static scenes cannot get modified");
  74. if (topologyID >= topology.size())
  75. throw_RTCError(RTC_INVALID_OPERATION,"invalid topology ID");
  76. topology[topologyID].setSubdivisionMode(mode);
  77. }
  78. void SubdivMesh::setIndexBuffer(RTCBufferType vertexBuffer, RTCBufferType indexBuffer)
  79. {
  80. if (vertexBuffer >= RTC_USER_VERTEX_BUFFER0 && vertexBuffer < RTC_USER_VERTEX_BUFFER0+(int)userbuffers.size()) {
  81. if (indexBuffer >= RTC_INDEX_BUFFER && indexBuffer < RTC_INDEX_BUFFER+(int)topology.size()) {
  82. unsigned vid = vertexBuffer & 0xFFFF;
  83. unsigned iid = indexBuffer & 0xFFFF;
  84. if ((unsigned)userbuffers[vid].userdata != iid) {
  85. userbuffers[vid].userdata = iid;
  86. parent->commitCounterSubdiv++; // triggers recalculation of cached interpolation data
  87. }
  88. } else {
  89. throw_RTCError(RTC_INVALID_OPERATION,"invalid index buffer specified");
  90. }
  91. } else {
  92. throw_RTCError(RTC_INVALID_OPERATION,"invalid vertex buffer specified");
  93. }
  94. }
  95. void SubdivMesh::setBuffer(RTCBufferType type, void* ptr, size_t offset, size_t stride, size_t size)
  96. {
  97. if (parent->isStatic() && parent->isBuild())
  98. throw_RTCError(RTC_INVALID_OPERATION,"static scenes cannot get modified");
  99. /* verify that all accesses are 4 bytes aligned */
  100. if (((size_t(ptr) + offset) & 0x3) || (stride & 0x3))
  101. throw_RTCError(RTC_INVALID_OPERATION,"data must be 4 bytes aligned");
  102. if (type != RTC_LEVEL_BUFFER)
  103. parent->commitCounterSubdiv++;
  104. unsigned bid = type & 0xFFFF;
  105. if (type >= RTC_VERTEX_BUFFER0 && type < RTC_VERTEX_BUFFER0+(int)numTimeSteps)
  106. {
  107. vertices[bid].set(ptr,offset,stride,size);
  108. vertices[bid].checkPadding16();
  109. }
  110. else if (type >= RTC_USER_VERTEX_BUFFER0 && type < RTC_USER_VERTEX_BUFFER0+RTC_MAX_USER_VERTEX_BUFFERS)
  111. {
  112. if (bid >= userbuffers.size()) {
  113. userbuffers.resize(bid+1);
  114. user_buffer_tags.resize(bid+1);
  115. }
  116. userbuffers[bid] = APIBuffer<char>(parent->device,numVertices(),stride); // FIXME: numVertices for compatibility
  117. userbuffers[bid].set(ptr,offset,stride,size);
  118. userbuffers[bid].checkPadding16();
  119. }
  120. else if (type == RTC_FACE_BUFFER)
  121. {
  122. if (size != (size_t)-1) disabling();
  123. faceVertices.set(ptr,offset,stride,size);
  124. setNumPrimitives(size);
  125. if (size != (size_t)-1) enabling();
  126. }
  127. else if (type >= RTC_INDEX_BUFFER && type < RTC_INDEX_BUFFER+RTC_MAX_INDEX_BUFFERS)
  128. {
  129. int begin = (int)topology.size();
  130. if (bid >= topology.size()) {
  131. topology.resize(bid+1);
  132. for (size_t i=begin; i<topology.size(); i++)
  133. topology[i] = Topology(this,numEdges());
  134. }
  135. topology[bid].vertexIndices.set(ptr,offset,stride,size);
  136. }
  137. else if (type == RTC_EDGE_CREASE_INDEX_BUFFER)
  138. edge_creases.set(ptr,offset,stride,size);
  139. else if (type == RTC_EDGE_CREASE_WEIGHT_BUFFER)
  140. edge_crease_weights.set(ptr,offset,stride,size);
  141. else if (type == RTC_VERTEX_CREASE_INDEX_BUFFER)
  142. vertex_creases.set(ptr,offset,stride,size);
  143. else if (type == RTC_VERTEX_CREASE_WEIGHT_BUFFER)
  144. vertex_crease_weights.set(ptr,offset,stride,size);
  145. else if (type == RTC_HOLE_BUFFER)
  146. holes.set(ptr,offset,stride,size);
  147. else if (type == RTC_LEVEL_BUFFER)
  148. levels.set(ptr,offset,stride,size);
  149. else
  150. throw_RTCError(RTC_INVALID_ARGUMENT,"unknown buffer type");
  151. }
  152. void* SubdivMesh::map(RTCBufferType type)
  153. {
  154. if (parent->isStatic() && parent->isBuild())
  155. throw_RTCError(RTC_INVALID_OPERATION,"static scenes cannot get modified");
  156. unsigned bid = type & 0xFFFF;
  157. if (type >= RTC_VERTEX_BUFFER0 && type < RTC_VERTEX_BUFFER0+int(numTimeSteps))
  158. return vertices[bid].map(parent->numMappedBuffers);
  159. else if (type >= RTC_INDEX_BUFFER && type < RTC_INDEX_BUFFER+RTC_MAX_INDEX_BUFFERS)
  160. return topology[bid].vertexIndices.map(parent->numMappedBuffers);
  161. else if (type == RTC_FACE_BUFFER)
  162. return faceVertices.map(parent->numMappedBuffers);
  163. else if (type == RTC_EDGE_CREASE_INDEX_BUFFER)
  164. return edge_creases.map(parent->numMappedBuffers);
  165. else if (type == RTC_EDGE_CREASE_WEIGHT_BUFFER)
  166. return edge_crease_weights.map(parent->numMappedBuffers);
  167. else if (type == RTC_VERTEX_CREASE_INDEX_BUFFER)
  168. return vertex_creases.map(parent->numMappedBuffers);
  169. else if (type == RTC_VERTEX_CREASE_WEIGHT_BUFFER)
  170. return vertex_crease_weights.map(parent->numMappedBuffers);
  171. else if (type == RTC_HOLE_BUFFER)
  172. return holes.map(parent->numMappedBuffers);
  173. else if (type == RTC_LEVEL_BUFFER)
  174. return levels.map(parent->numMappedBuffers);
  175. else
  176. throw_RTCError(RTC_INVALID_ARGUMENT,"unknown buffer type");
  177. return nullptr;
  178. }
  179. void SubdivMesh::unmap(RTCBufferType type)
  180. {
  181. if (parent->isStatic() && parent->isBuild())
  182. throw_RTCError(RTC_INVALID_OPERATION,"static scenes cannot get modified");
  183. unsigned bid = type & 0xFFFF;
  184. if (type >= RTC_VERTEX_BUFFER0 && type < RTC_VERTEX_BUFFER0+(int)numTimeSteps)
  185. vertices[bid].unmap(parent->numMappedBuffers);
  186. else if (type >= RTC_INDEX_BUFFER && type < RTC_INDEX_BUFFER+RTC_MAX_INDEX_BUFFERS)
  187. topology[bid].vertexIndices.unmap(parent->numMappedBuffers);
  188. else if (type == RTC_FACE_BUFFER)
  189. faceVertices.unmap(parent->numMappedBuffers);
  190. else if (type == RTC_EDGE_CREASE_INDEX_BUFFER)
  191. edge_creases.unmap(parent->numMappedBuffers);
  192. else if (type == RTC_EDGE_CREASE_WEIGHT_BUFFER)
  193. edge_crease_weights.unmap(parent->numMappedBuffers);
  194. else if (type == RTC_VERTEX_CREASE_INDEX_BUFFER)
  195. vertex_creases.unmap(parent->numMappedBuffers);
  196. else if (type == RTC_VERTEX_CREASE_WEIGHT_BUFFER)
  197. vertex_crease_weights.unmap(parent->numMappedBuffers);
  198. else if (type == RTC_HOLE_BUFFER)
  199. holes.unmap(parent->numMappedBuffers);
  200. else if (type == RTC_LEVEL_BUFFER)
  201. levels.unmap(parent->numMappedBuffers);
  202. else
  203. throw_RTCError(RTC_INVALID_ARGUMENT,"unknown buffer type");
  204. }
  205. void SubdivMesh::update ()
  206. {
  207. faceVertices.setModified(true);
  208. holes.setModified(true);
  209. for (auto& buffer : vertices) buffer.setModified(true);
  210. levels.setModified(true);
  211. edge_creases.setModified(true);
  212. edge_crease_weights.setModified(true);
  213. vertex_creases.setModified(true);
  214. vertex_crease_weights.setModified(true);
  215. for (auto& t : topology) t.update();
  216. Geometry::update();
  217. }
  218. void SubdivMesh::updateBuffer (RTCBufferType type)
  219. {
  220. if (type != RTC_LEVEL_BUFFER)
  221. parent->commitCounterSubdiv++;
  222. unsigned bid = type & 0xFFFF;
  223. if (type >= RTC_VERTEX_BUFFER0 && type < RTC_VERTEX_BUFFER0+(int)numTimeSteps)
  224. vertices[bid].setModified(true);
  225. else if (type >= RTC_USER_VERTEX_BUFFER0 && type < RTC_USER_VERTEX_BUFFER0+2)
  226. userbuffers[bid].setModified(true);
  227. else if (type == RTC_FACE_BUFFER)
  228. faceVertices.setModified(true);
  229. else if (type >= RTC_INDEX_BUFFER && type < RTC_INDEX_BUFFER+RTC_MAX_INDEX_BUFFERS)
  230. topology[bid].vertexIndices.setModified(true);
  231. else if (type == RTC_EDGE_CREASE_INDEX_BUFFER)
  232. edge_creases.setModified(true);
  233. else if (type == RTC_EDGE_CREASE_WEIGHT_BUFFER)
  234. edge_crease_weights.setModified(true);
  235. else if (type == RTC_VERTEX_CREASE_INDEX_BUFFER)
  236. vertex_creases.setModified(true);
  237. else if (type == RTC_VERTEX_CREASE_WEIGHT_BUFFER)
  238. vertex_crease_weights.setModified(true);
  239. else if (type == RTC_HOLE_BUFFER)
  240. holes.setModified(true);
  241. else if (type == RTC_LEVEL_BUFFER)
  242. levels.setModified(true);
  243. else
  244. throw_RTCError(RTC_INVALID_ARGUMENT,"unknown buffer type");
  245. Geometry::update();
  246. }
  247. void SubdivMesh::setDisplacementFunction (RTCDisplacementFunc func, RTCBounds* bounds)
  248. {
  249. if (parent->isStatic() && parent->isBuild())
  250. throw_RTCError(RTC_INVALID_OPERATION,"static scenes cannot get modified");
  251. this->displFunc = func;
  252. if (bounds) this->displBounds = *(BBox3fa*)bounds;
  253. else this->displBounds = empty;
  254. }
  255. void SubdivMesh::setDisplacementFunction2 (RTCDisplacementFunc2 func, RTCBounds* bounds)
  256. {
  257. if (parent->isStatic() && parent->isBuild())
  258. throw_RTCError(RTC_INVALID_OPERATION,"static scenes cannot get modified");
  259. this->displFunc2 = func;
  260. if (bounds) this->displBounds = *(BBox3fa*)bounds;
  261. else this->displBounds = empty;
  262. }
  263. void SubdivMesh::setTessellationRate(float N)
  264. {
  265. if (parent->isStatic() && parent->isBuild())
  266. throw_RTCError(RTC_INVALID_OPERATION,"static geometries cannot get modified");
  267. tessellationRate = N;
  268. levels.setModified(true);
  269. }
  270. void SubdivMesh::immutable ()
  271. {
  272. const bool freeVertices = !parent->needSubdivVertices;
  273. faceVertices.free();
  274. if (freeVertices )
  275. for (auto& buffer : vertices)
  276. buffer.free();
  277. levels.free();
  278. holes.free();
  279. edge_creases.free();
  280. edge_crease_weights.free();
  281. vertex_creases.free();
  282. vertex_crease_weights.free();
  283. for (auto& t : topology)
  284. t.immutable();
  285. }
  286. __forceinline uint64_t pair64(unsigned int x, unsigned int y)
  287. {
  288. if (x<y) std::swap(x,y);
  289. return (((uint64_t)x) << 32) | (uint64_t)y;
  290. }
  291. SubdivMesh::Topology::Topology(SubdivMesh* mesh, size_t numEdges)
  292. : mesh(mesh), subdiv_mode(RTC_SUBDIV_SMOOTH_BOUNDARY), halfEdges(mesh->parent->device)
  293. {
  294. vertexIndices.init(mesh->parent->device,numEdges,sizeof(unsigned int));
  295. }
  296. void SubdivMesh::Topology::setSubdivisionMode (RTCSubdivisionMode mode)
  297. {
  298. if (subdiv_mode == mode) return;
  299. subdiv_mode = mode;
  300. mesh->updateBuffer(RTC_VERTEX_CREASE_WEIGHT_BUFFER);
  301. }
  302. void SubdivMesh::Topology::update () {
  303. vertexIndices.setModified(true);
  304. }
  305. void SubdivMesh::Topology::immutable ()
  306. {
  307. const bool freeIndices = !mesh->parent->needSubdivIndices;
  308. if (freeIndices) vertexIndices.free();
  309. }
  310. bool SubdivMesh::Topology::verify (size_t numVertices)
  311. {
  312. size_t ofs = 0;
  313. for (size_t i=0; i<mesh->faceVertices.size(); i++)
  314. {
  315. int valence = mesh->faceVertices[i];
  316. for (size_t j=ofs; j<ofs+valence; j++)
  317. {
  318. if (j >= vertexIndices.size())
  319. return false;
  320. if (vertexIndices[j] >= numVertices)
  321. return false;
  322. }
  323. ofs += valence;
  324. }
  325. return true;
  326. }
  327. void SubdivMesh::Topology::calculateHalfEdges()
  328. {
  329. const size_t blockSize = 4096;
  330. const size_t numEdges = mesh->numEdges();
  331. const size_t numFaces = mesh->numFaces();
  332. const size_t numHalfEdges = mesh->numHalfEdges;
  333. /* allocate temporary array */
  334. halfEdges0.resize(numEdges);
  335. halfEdges1.resize(numEdges);
  336. /* create all half edges */
  337. parallel_for( size_t(0), numFaces, blockSize, [&](const range<size_t>& r)
  338. {
  339. for (size_t f=r.begin(); f<r.end(); f++)
  340. {
  341. const unsigned N = mesh->faceVertices[f];
  342. const unsigned e = mesh->faceStartEdge[f];
  343. for (unsigned de=0; de<N; de++)
  344. {
  345. HalfEdge* edge = &halfEdges[e+de];
  346. int nextOfs = (de == (N-1)) ? -int(N-1) : +1;
  347. int prevOfs = (de == 0) ? +int(N-1) : -1;
  348. const unsigned int startVertex = vertexIndices[e+de];
  349. const unsigned int endVertex = vertexIndices[e+de+nextOfs];
  350. const uint64_t key = SubdivMesh::Edge(startVertex,endVertex);
  351. /* we always have to use the geometry topology to lookup creases */
  352. const unsigned int startVertex0 = mesh->topology[0].vertexIndices[e+de];
  353. const unsigned int endVertex0 = mesh->topology[0].vertexIndices[e+de+nextOfs];
  354. const uint64_t key0 = SubdivMesh::Edge(startVertex0,endVertex0);
  355. edge->vtx_index = startVertex;
  356. edge->next_half_edge_ofs = nextOfs;
  357. edge->prev_half_edge_ofs = prevOfs;
  358. edge->opposite_half_edge_ofs = 0;
  359. edge->edge_crease_weight = mesh->edgeCreaseMap.lookup(key0,0.0f);
  360. edge->vertex_crease_weight = mesh->vertexCreaseMap.lookup(startVertex0,0.0f);
  361. edge->edge_level = mesh->getEdgeLevel(e+de);
  362. edge->patch_type = HalfEdge::COMPLEX_PATCH; // type gets updated below
  363. edge->vertex_type = HalfEdge::REGULAR_VERTEX;
  364. if (unlikely(mesh->holeSet.lookup(unsigned(f))))
  365. halfEdges1[e+de] = SubdivMesh::KeyHalfEdge(std::numeric_limits<uint64_t>::max(),edge);
  366. else
  367. halfEdges1[e+de] = SubdivMesh::KeyHalfEdge(key,edge);
  368. }
  369. }
  370. });
  371. /* sort half edges to find adjacent edges */
  372. radix_sort_u64(halfEdges1.data(),halfEdges0.data(),numHalfEdges);
  373. /* link all adjacent pairs of edges */
  374. parallel_for( size_t(0), numHalfEdges, blockSize, [&](const range<size_t>& r)
  375. {
  376. /* skip if start of adjacent edges was not in our range */
  377. size_t e=r.begin();
  378. if (e != 0 && (halfEdges1[e].key == halfEdges1[e-1].key)) {
  379. const uint64_t key = halfEdges1[e].key;
  380. while (e<r.end() && halfEdges1[e].key == key) e++;
  381. }
  382. /* process all adjacent edges starting in our range */
  383. while (e<r.end())
  384. {
  385. const uint64_t key = halfEdges1[e].key;
  386. if (key == std::numeric_limits<uint64_t>::max()) break;
  387. size_t N=1; while (e+N<numHalfEdges && halfEdges1[e+N].key == key) N++;
  388. /* border edges are identified by not having an opposite edge set */
  389. if (N == 1) {
  390. halfEdges1[e].edge->edge_crease_weight = float(inf);
  391. }
  392. /* standard edge shared between two faces */
  393. else if (N == 2)
  394. {
  395. /* create edge crease if winding order mismatches between neighboring patches */
  396. if (halfEdges1[e+0].edge->next()->vtx_index != halfEdges1[e+1].edge->vtx_index)
  397. {
  398. halfEdges1[e+0].edge->edge_crease_weight = float(inf);
  399. halfEdges1[e+1].edge->edge_crease_weight = float(inf);
  400. }
  401. /* otherwise mark edges as opposites of each other */
  402. else {
  403. halfEdges1[e+0].edge->setOpposite(halfEdges1[e+1].edge);
  404. halfEdges1[e+1].edge->setOpposite(halfEdges1[e+0].edge);
  405. }
  406. }
  407. /* non-manifold geometry is handled by keeping vertices fixed during subdivision */
  408. else {
  409. for (size_t i=0; i<N; i++) {
  410. halfEdges1[e+i].edge->vertex_crease_weight = inf;
  411. halfEdges1[e+i].edge->vertex_type = HalfEdge::NON_MANIFOLD_EDGE_VERTEX;
  412. halfEdges1[e+i].edge->edge_crease_weight = inf;
  413. halfEdges1[e+i].edge->next()->vertex_crease_weight = inf;
  414. halfEdges1[e+i].edge->next()->vertex_type = HalfEdge::NON_MANIFOLD_EDGE_VERTEX;
  415. halfEdges1[e+i].edge->next()->edge_crease_weight = inf;
  416. }
  417. }
  418. e+=N;
  419. }
  420. });
  421. /* set subdivision mode and calculate patch types */
  422. parallel_for( size_t(0), numFaces, blockSize, [&](const range<size_t>& r)
  423. {
  424. for (size_t f=r.begin(); f<r.end(); f++)
  425. {
  426. HalfEdge* edge = &halfEdges[mesh->faceStartEdge[f]];
  427. /* for vertex topology we also test if vertices are valid */
  428. if (this == &mesh->topology[0])
  429. {
  430. /* calculate if face is valid */
  431. for (size_t t=0; t<mesh->numTimeSteps; t++)
  432. mesh->invalidFace(f,t) = !edge->valid(mesh->vertices[t]) || mesh->holeSet.lookup(unsigned(f));
  433. }
  434. /* pin some edges and vertices */
  435. for (size_t i=0; i<mesh->faceVertices[f]; i++)
  436. {
  437. /* pin corner vertices when requested by user */
  438. if (subdiv_mode == RTC_SUBDIV_PIN_CORNERS && edge[i].isCorner())
  439. edge[i].vertex_crease_weight = float(inf);
  440. /* pin all border vertices when requested by user */
  441. else if (subdiv_mode == RTC_SUBDIV_PIN_BOUNDARY && edge[i].vertexHasBorder())
  442. edge[i].vertex_crease_weight = float(inf);
  443. /* pin all edges and vertices when requested by user */
  444. else if (subdiv_mode == RTC_SUBDIV_PIN_ALL) {
  445. edge[i].edge_crease_weight = float(inf);
  446. edge[i].vertex_crease_weight = float(inf);
  447. }
  448. }
  449. /* we have to calculate patch_type last! */
  450. HalfEdge::PatchType patch_type = edge->patchType();
  451. for (size_t i=0; i<mesh->faceVertices[f]; i++)
  452. edge[i].patch_type = patch_type;
  453. }
  454. });
  455. }
  456. void SubdivMesh::Topology::updateHalfEdges()
  457. {
  458. /* we always use the geometry topology to lookup creases */
  459. mvector<HalfEdge>& halfEdgesGeom = mesh->topology[0].halfEdges;
  460. /* assume we do no longer recalculate in the future and clear these arrays */
  461. halfEdges0.clear();
  462. halfEdges1.clear();
  463. /* calculate which data to update */
  464. const bool updateEdgeCreases = mesh->topology[0].vertexIndices.isModified() || mesh->edge_creases.isModified() || mesh->edge_crease_weights.isModified();
  465. const bool updateVertexCreases = mesh->topology[0].vertexIndices.isModified() || mesh->vertex_creases.isModified() || mesh->vertex_crease_weights.isModified();
  466. const bool updateLevels = mesh->levels.isModified();
  467. /* parallel loop over all half edges */
  468. parallel_for( size_t(0), mesh->numHalfEdges, size_t(4096), [&](const range<size_t>& r)
  469. {
  470. for (size_t i=r.begin(); i!=r.end(); i++)
  471. {
  472. HalfEdge& edge = halfEdges[i];
  473. if (updateLevels)
  474. edge.edge_level = mesh->getEdgeLevel(i);
  475. if (updateEdgeCreases) {
  476. if (edge.hasOpposite()) // leave weight at inf for borders
  477. edge.edge_crease_weight = mesh->edgeCreaseMap.lookup((uint64_t)halfEdgesGeom[i].getEdge(),0.0f);
  478. }
  479. /* we only use user specified vertex_crease_weight if the vertex is manifold */
  480. if (updateVertexCreases && edge.vertex_type != HalfEdge::NON_MANIFOLD_EDGE_VERTEX)
  481. {
  482. edge.vertex_crease_weight = mesh->vertexCreaseMap.lookup(halfEdgesGeom[i].vtx_index,0.0f);
  483. /* pin corner vertices when requested by user */
  484. if (subdiv_mode == RTC_SUBDIV_PIN_CORNERS && edge.isCorner())
  485. edge.vertex_crease_weight = float(inf);
  486. /* pin all border vertices when requested by user */
  487. else if (subdiv_mode == RTC_SUBDIV_PIN_BOUNDARY && edge.vertexHasBorder())
  488. edge.vertex_crease_weight = float(inf);
  489. /* pin every vertex when requested by user */
  490. else if (subdiv_mode == RTC_SUBDIV_PIN_ALL) {
  491. edge.edge_crease_weight = float(inf);
  492. edge.vertex_crease_weight = float(inf);
  493. }
  494. }
  495. /* update patch type */
  496. if (updateEdgeCreases || updateVertexCreases) {
  497. edge.patch_type = edge.patchType();
  498. }
  499. }
  500. });
  501. }
  502. void SubdivMesh::Topology::initializeHalfEdgeStructures ()
  503. {
  504. /* if vertex indices not set we ignore this topology */
  505. if (!vertexIndices)
  506. return;
  507. /* allocate half edge array */
  508. halfEdges.resize(mesh->numEdges());
  509. /* check if we have to recalculate the half edges */
  510. bool recalculate = false;
  511. recalculate |= vertexIndices.isModified();
  512. recalculate |= mesh->faceVertices.isModified();
  513. recalculate |= mesh->holes.isModified();
  514. /* check if we can simply update the half edges */
  515. bool update = false;
  516. update |= mesh->topology[0].vertexIndices.isModified(); // we use this buffer to copy creases to interpolation topologies
  517. update |= mesh->edge_creases.isModified();
  518. update |= mesh->edge_crease_weights.isModified();
  519. update |= mesh->vertex_creases.isModified();
  520. update |= mesh->vertex_crease_weights.isModified();
  521. update |= mesh->levels.isModified();
  522. /* now either recalculate or update the half edges */
  523. if (recalculate) calculateHalfEdges();
  524. else if (update) updateHalfEdges();
  525. /* cleanup some state for static scenes */
  526. if (mesh->parent->isStatic())
  527. {
  528. halfEdges0.clear();
  529. halfEdges1.clear();
  530. }
  531. /* clear modified state of all buffers */
  532. vertexIndices.setModified(false);
  533. }
  534. void SubdivMesh::printStatistics()
  535. {
  536. size_t numBilinearFaces = 0;
  537. size_t numRegularQuadFaces = 0;
  538. size_t numIrregularQuadFaces = 0;
  539. size_t numComplexFaces = 0;
  540. for (size_t e=0, f=0; f<numFaces(); e+=faceVertices[f++])
  541. {
  542. switch (topology[0].halfEdges[e].patch_type) {
  543. case HalfEdge::BILINEAR_PATCH : numBilinearFaces++; break;
  544. case HalfEdge::REGULAR_QUAD_PATCH : numRegularQuadFaces++; break;
  545. case HalfEdge::IRREGULAR_QUAD_PATCH: numIrregularQuadFaces++; break;
  546. case HalfEdge::COMPLEX_PATCH : numComplexFaces++; break;
  547. }
  548. }
  549. std::cout << "numFaces = " << numFaces() << ", "
  550. << "numBilinearFaces = " << numBilinearFaces << " (" << 100.0f * numBilinearFaces / numFaces() << "%), "
  551. << "numRegularQuadFaces = " << numRegularQuadFaces << " (" << 100.0f * numRegularQuadFaces / numFaces() << "%), "
  552. << "numIrregularQuadFaces " << numIrregularQuadFaces << " (" << 100.0f * numIrregularQuadFaces / numFaces() << "%) "
  553. << "numComplexFaces " << numComplexFaces << " (" << 100.0f * numComplexFaces / numFaces() << "%) "
  554. << std::endl;
  555. }
  556. void SubdivMesh::initializeHalfEdgeStructures ()
  557. {
  558. double t0 = getSeconds();
  559. invalid_face.resize(numFaces()*numTimeSteps);
  560. /* calculate start edge of each face */
  561. faceStartEdge.resize(numFaces());
  562. if (faceVertices.isModified())
  563. numHalfEdges = parallel_prefix_sum(faceVertices,faceStartEdge,numFaces(),0,std::plus<unsigned>());
  564. /* create set with all vertex creases */
  565. if (vertex_creases.isModified() || vertex_crease_weights.isModified())
  566. vertexCreaseMap.init(vertex_creases,vertex_crease_weights);
  567. /* create map with all edge creases */
  568. if (edge_creases.isModified() || edge_crease_weights.isModified())
  569. edgeCreaseMap.init(edge_creases,edge_crease_weights);
  570. /* create set with all holes */
  571. if (holes.isModified())
  572. holeSet.init(holes);
  573. /* create topology */
  574. for (auto& t: topology)
  575. t.initializeHalfEdgeStructures();
  576. /* create interpolation cache mapping for interpolatable meshes */
  577. if (parent->isInterpolatable())
  578. {
  579. #if defined (__TARGET_AVX__)
  580. auto numInterpolationSlots = [&] (size_t stride) {
  581. if (parent->device->hasISA(AVX)) return numInterpolationSlots8(stride); else return numInterpolationSlots4(stride);
  582. };
  583. #else
  584. auto numInterpolationSlots = [] (size_t stride) {
  585. return numInterpolationSlots4(stride);
  586. };
  587. #endif
  588. for (size_t i=0; i<vertex_buffer_tags.size(); i++)
  589. vertex_buffer_tags[i].resize(numFaces()*numInterpolationSlots(vertices[i].getStride()));
  590. for (size_t i=0; i<userbuffers.size(); i++)
  591. if (userbuffers[i]) user_buffer_tags[i].resize(numFaces()*numInterpolationSlots(userbuffers[i].getStride()));
  592. }
  593. /* cleanup some state for static scenes */
  594. if (parent->isStatic())
  595. {
  596. vertexCreaseMap.clear();
  597. edgeCreaseMap.clear();
  598. }
  599. /* clear modified state of all buffers */
  600. faceVertices.setModified(false);
  601. holes.setModified(false);
  602. for (auto& buffer : vertices) buffer.setModified(false);
  603. levels.setModified(false);
  604. edge_creases.setModified(false);
  605. edge_crease_weights.setModified(false);
  606. vertex_creases.setModified(false);
  607. vertex_crease_weights.setModified(false);
  608. double t1 = getSeconds();
  609. /* print statistics in verbose mode */
  610. if (parent->device->verbosity(2)) {
  611. std::cout << "half edge generation = " << 1000.0*(t1-t0) << "ms, " << 1E-6*double(numHalfEdges)/(t1-t0) << "M/s" << std::endl;
  612. printStatistics();
  613. }
  614. }
  615. bool SubdivMesh::verify ()
  616. {
  617. /*! verify consistent size of vertex arrays */
  618. if (vertices.size() == 0) return false;
  619. for (const auto& buffer : vertices)
  620. if (buffer.size() != numVertices())
  621. return false;
  622. /*! verify vertex indices */
  623. if (!topology[0].verify(numVertices()))
  624. return false;
  625. for (auto& b : userbuffers)
  626. if (!topology[b.userdata].verify(b.size()))
  627. return false;
  628. /*! verify vertices */
  629. for (const auto& buffer : vertices)
  630. for (size_t i=0; i<buffer.size(); i++)
  631. if (!isvalid(buffer[i]))
  632. return false;
  633. return true;
  634. }
  635. void SubdivMesh::interpolate(unsigned primID, float u, float v, RTCBufferType buffer, float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv, size_t numFloats)
  636. {
  637. /* test if interpolation is enabled */
  638. #if defined(DEBUG)
  639. if ((parent->aflags & RTC_INTERPOLATE) == 0)
  640. throw_RTCError(RTC_INVALID_OPERATION,"rtcInterpolate can only get called when RTC_INTERPOLATE is enabled for the scene");
  641. #endif
  642. /* calculate base pointer and stride */
  643. assert((buffer >= RTC_VERTEX_BUFFER0 && buffer < RTCBufferType(RTC_VERTEX_BUFFER0 + RTC_MAX_TIME_STEPS)) ||
  644. (buffer >= RTC_USER_VERTEX_BUFFER0 && RTCBufferType(RTC_USER_VERTEX_BUFFER0 + RTC_MAX_USER_VERTEX_BUFFERS)));
  645. const char* src = nullptr;
  646. size_t stride = 0;
  647. size_t bufID = buffer&0xFFFF;
  648. std::vector<SharedLazyTessellationCache::CacheEntry>* baseEntry = nullptr;
  649. Topology* topo = nullptr;
  650. if (buffer >= RTC_USER_VERTEX_BUFFER0) {
  651. assert(bufID < userbuffers.size());
  652. src = userbuffers[bufID].getPtr();
  653. stride = userbuffers[bufID].getStride();
  654. baseEntry = &user_buffer_tags[bufID];
  655. int topologyID = userbuffers[bufID].userdata;
  656. topo = &topology[topologyID];
  657. } else {
  658. assert(bufID < numTimeSteps);
  659. src = vertices[bufID].getPtr();
  660. stride = vertices[bufID].getStride();
  661. baseEntry = &vertex_buffer_tags[bufID];
  662. topo = &topology[0];
  663. }
  664. bool has_P = P;
  665. bool has_dP = dPdu; assert(!has_dP || dPdv);
  666. bool has_ddP = ddPdudu; assert(!has_ddP || (ddPdvdv && ddPdudu));
  667. for (size_t i=0; i<numFloats; i+=4)
  668. {
  669. vfloat4 Pt, dPdut, dPdvt, ddPdudut, ddPdvdvt, ddPdudvt;
  670. isa::PatchEval<vfloat4,vfloat4>(baseEntry->at(interpolationSlot(primID,i/4,stride)),parent->commitCounterSubdiv,
  671. topo->getHalfEdge(primID),src+i*sizeof(float),stride,u,v,
  672. has_P ? &Pt : nullptr,
  673. has_dP ? &dPdut : nullptr,
  674. has_dP ? &dPdvt : nullptr,
  675. has_ddP ? &ddPdudut : nullptr,
  676. has_ddP ? &ddPdvdvt : nullptr,
  677. has_ddP ? &ddPdudvt : nullptr);
  678. if (has_P) {
  679. for (size_t j=i; j<min(i+4,numFloats); j++)
  680. P[j] = Pt[j-i];
  681. }
  682. if (has_dP)
  683. {
  684. for (size_t j=i; j<min(i+4,numFloats); j++) {
  685. dPdu[j] = dPdut[j-i];
  686. dPdv[j] = dPdvt[j-i];
  687. }
  688. }
  689. if (has_ddP)
  690. {
  691. for (size_t j=i; j<min(i+4,numFloats); j++) {
  692. ddPdudu[j] = ddPdudut[j-i];
  693. ddPdvdv[j] = ddPdvdvt[j-i];
  694. ddPdudv[j] = ddPdudvt[j-i];
  695. }
  696. }
  697. }
  698. }
  699. void SubdivMesh::interpolateN(const void* valid_i, const unsigned* primIDs, const float* u, const float* v, size_t numUVs,
  700. RTCBufferType buffer, float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv, size_t numFloats)
  701. {
  702. /* test if interpolation is enabled */
  703. #if defined(DEBUG)
  704. if ((parent->aflags & RTC_INTERPOLATE) == 0)
  705. throw_RTCError(RTC_INVALID_OPERATION,"rtcInterpolate can only get called when RTC_INTERPOLATE is enabled for the scene");
  706. #endif
  707. /* calculate base pointer and stride */
  708. assert((buffer >= RTC_VERTEX_BUFFER0 && buffer < RTCBufferType(RTC_VERTEX_BUFFER0 + RTC_MAX_TIME_STEPS)) ||
  709. (buffer >= RTC_USER_VERTEX_BUFFER0 && RTCBufferType(RTC_USER_VERTEX_BUFFER0 + RTC_MAX_USER_VERTEX_BUFFERS)));
  710. const char* src = nullptr;
  711. size_t stride = 0;
  712. size_t bufID = buffer&0xFFFF;
  713. std::vector<SharedLazyTessellationCache::CacheEntry>* baseEntry = nullptr;
  714. Topology* topo = nullptr;
  715. if (buffer >= RTC_USER_VERTEX_BUFFER0) {
  716. assert(bufID < userbuffers.size());
  717. src = userbuffers[bufID].getPtr();
  718. stride = userbuffers[bufID].getStride();
  719. baseEntry = &user_buffer_tags[bufID];
  720. int topologyID = userbuffers[bufID].userdata;
  721. topo = &topology[topologyID];
  722. } else {
  723. assert(bufID < numTimeSteps);
  724. src = vertices[bufID].getPtr();
  725. stride = vertices[bufID].getStride();
  726. baseEntry = &vertex_buffer_tags[bufID];
  727. topo = &topology[0];
  728. }
  729. const int* valid = (const int*) valid_i;
  730. for (size_t i=0; i<numUVs; i+=4)
  731. {
  732. vbool4 valid1 = vint4(i)+vint4(step) < vint4(numUVs);
  733. if (valid) valid1 &= vint4::loadu(&valid[i]) == vint4(-1);
  734. if (none(valid1)) continue;
  735. const vint4 primID = vint4::loadu(&primIDs[i]);
  736. const vfloat4 uu = vfloat4::loadu(&u[i]);
  737. const vfloat4 vv = vfloat4::loadu(&v[i]);
  738. foreach_unique(valid1,primID,[&](const vbool4& valid1, const int primID)
  739. {
  740. for (size_t j=0; j<numFloats; j+=4)
  741. {
  742. const size_t M = min(size_t(4),numFloats-j);
  743. isa::PatchEvalSimd<vbool4,vint4,vfloat4,vfloat4>(baseEntry->at(interpolationSlot(primID,j/4,stride)),parent->commitCounterSubdiv,
  744. topo->getHalfEdge(primID),src+j*sizeof(float),stride,valid1,uu,vv,
  745. P ? P+j*numUVs+i : nullptr,
  746. dPdu ? dPdu+j*numUVs+i : nullptr,
  747. dPdv ? dPdv+j*numUVs+i : nullptr,
  748. ddPdudu ? ddPdudu+j*numUVs+i : nullptr,
  749. ddPdvdv ? ddPdvdv+j*numUVs+i : nullptr,
  750. ddPdudv ? ddPdudv+j*numUVs+i : nullptr,
  751. numUVs,M);
  752. }
  753. });
  754. }
  755. }
  756. }