diff --git a/kernels/common/scene_subdiv_mesh.cpp b/kernels/common/scene_subdiv_mesh.cpp index 4181c0ac8f..0620975252 100644 --- a/kernels/common/scene_subdiv_mesh.cpp +++ b/kernels/common/scene_subdiv_mesh.cpp @@ -543,7 +543,7 @@ namespace embree { /* calculate if face is valid */ for (size_t t=0; tnumTimeSteps; t++) - mesh->invalidFace(f,t) = !edge->valid(mesh->vertices[t]) || mesh->holeSet->holeSet.lookup(unsigned(f)); + mesh->invalidFace(f,t) = !edge->valid(&mesh->vertices[t]) || mesh->holeSet->holeSet.lookup(unsigned(f)); } /* pin some edges and vertices */ @@ -566,8 +566,11 @@ namespace embree /* we have to calculate patch_type last! */ HalfEdge::PatchType patch_type = edge->patchType(); - for (size_t i=0; ifaceVertices[f]; i++) + bool valid = edge->valid(nullptr); + for (size_t i=0; ifaceVertices[f]; i++) { edge[i].patch_type = patch_type; + edge[i].valid_patch = valid; + } } }); } @@ -885,12 +888,25 @@ namespace embree bool has_P = P; bool has_dP = dPdu; assert(!has_dP || dPdv); bool has_ddP = ddPdudu; assert(!has_ddP || (ddPdvdv && ddPdudu)); + + const HalfEdge* halfEdge = topo->getHalfEdge(primID); + + /* invalid patches cannot get evaluated */ + if (unlikely(!halfEdge->valid_patch)) + { + for (unsigned int j=0; j(baseEntry->at(interpolationSlot(primID,i/4,stride)),commitCounter, - topo->getHalfEdge(primID),src+i*sizeof(float),stride,u,v, + halfEdge,src+i*sizeof(float),stride,u,v, has_P ? &Pt : nullptr, has_dP ? &dPdut : nullptr, has_dP ? &dPdvt : nullptr, @@ -975,11 +991,27 @@ namespace embree foreach_unique(valid1,primID,[&](const vbool4& valid1, const unsigned int primID) { + const HalfEdge* halfEdge = topo->getHalfEdge(primID); + + /* invalid patches cannot get evaluated */ + if (unlikely(!halfEdge->valid_patch)) + { + for (unsigned int j=0; j(baseEntry->at(interpolationSlot(primID,j/4,stride)),commitCounter, - topo->getHalfEdge(primID),src+j*sizeof(float),stride,valid1,uu,vv, + halfEdge,src+j*sizeof(float),stride,valid1,uu,vv, P ? P+j*N+i : nullptr, dPdu ? dPdu+j*N+i : nullptr, dPdv ? dPdv+j*N+i : nullptr, diff --git a/kernels/common/scene_subdiv_mesh.h b/kernels/common/scene_subdiv_mesh.h index 49bb8e769a..d99988f4da 100644 --- a/kernels/common/scene_subdiv_mesh.h +++ b/kernels/common/scene_subdiv_mesh.h @@ -169,6 +169,8 @@ namespace embree /*! check if the i'th primitive is valid in this topology */ __forceinline bool valid(size_t i) const { + if (unlikely(!getHalfEdge(i)->valid_patch)) + return false; if (unlikely(subdiv_mode == RTC_SUBDIVISION_MODE_NO_BOUNDARY)) { if (getHalfEdge(i)->faceHasBorder()) return false; } diff --git a/kernels/subdiv/half_edge.h b/kernels/subdiv/half_edge.h index 8cb4f24845..823a7bf3b0 100644 --- a/kernels/subdiv/half_edge.h +++ b/kernels/subdiv/half_edge.h @@ -48,7 +48,7 @@ namespace embree HalfEdge () : vtx_index(-1), next_half_edge_ofs(0), prev_half_edge_ofs(0), opposite_half_edge_ofs(0), edge_crease_weight(0), - vertex_crease_weight(0), edge_level(0), patch_type(COMPLEX_PATCH), vertex_type(REGULAR_VERTEX) + vertex_crease_weight(0), edge_level(0), patch_type(COMPLEX_PATCH), vertex_type(REGULAR_VERTEX), valid_patch(false) { static_assert(sizeof(HalfEdge) == 32, "invalid half edge size"); } @@ -201,8 +201,8 @@ namespace embree return bounds; } - /*! tests if this is a valid patch */ - __forceinline bool valid(const BufferView& vertices) const + /*! tests if this is a valid patch, the vertex check is skipped when vertices is NULL */ + __forceinline bool valid(const BufferView* vertices) const { size_t N = 1; if (!this->validRing(vertices)) return false; @@ -306,23 +306,33 @@ namespace embree return bounds; } - /*! tests if this is a valid face */ - __forceinline bool validFace(const BufferView& vertices, size_t& N) const + private: + + /*! Tests if this is a valid face topology. If vertices are + * provided these are also tested to have valid floating point + * numbers. */ + __forceinline bool validFace(const BufferView* vertices, size_t& N) const { - const Vec3fa v = vertices[getStartVertexIndex()]; - if (!isvalid(v)) return false; + if (vertices) { + const Vec3fa v = vertices->operator[](getStartVertexIndex()); + if (!isvalid(v)) return false; + } size_t n = 1; for (const HalfEdge* p = next(); p!=this; p=p->next(), n++) { - const Vec3fa v = vertices[p->getStartVertexIndex()]; - if (!isvalid(v)) return false; + if (vertices) { + const Vec3fa v = vertices->operator[](p->getStartVertexIndex()); + if (!isvalid(v)) return false; + } } if (n < 2) return false; N += n-2; return n >= 3 && n <= MAX_PATCH_VALENCE; } - - /*! tests if this is a valid ring */ - __forceinline bool validRing(const BufferView& vertices) const + + /*! Tests if this is a valid ring topology. If vertices are + * provided these are also tested to have valid floating point + * numbers. */ + __forceinline bool validRing(const BufferView* vertices) const { size_t faceValence = 0; size_t edgeValence = 0; @@ -331,7 +341,7 @@ namespace embree do { /* calculate bounds of current face */ - if (!p->validFace(vertices,edgeValence)) + if (!p->validFace(vertices,edgeValence)) return false; faceValence++; @@ -349,12 +359,12 @@ namespace embree while (p->hasOpposite()) p = p->opposite()->next(); } - + } while (p != this); - + return faceValence <= MAX_RING_FACE_VALENCE && edgeValence <= MAX_RING_EDGE_VALENCE; } - + private: unsigned int vtx_index; //!< index of edge start vertex int next_half_edge_ofs; //!< relative offset to next half edge of face @@ -367,6 +377,7 @@ namespace embree float edge_level; //!< subdivision factor for edge PatchType patch_type; //!< stores type of subdiv patch VertexType vertex_type; //!< stores type of the start vertex - char align[2]; + bool valid_patch; //!< stores if the patch can be evaluated + char align[1]; }; }