| 1 | // Copyright 2009-2021 Intel Corporation |
| 2 | // SPDX-License-Identifier: Apache-2.0 |
| 3 | |
| 4 | #pragma once |
| 5 | |
| 6 | #include "curveNi.h" |
| 7 | |
| 8 | namespace embree |
| 9 | { |
| 10 | template<int M> |
| 11 | struct CurveNv : public CurveNi<M> |
| 12 | { |
| 13 | using CurveNi<M>::N; |
| 14 | |
| 15 | struct Type : public PrimitiveType { |
| 16 | const char* name() const; |
| 17 | size_t sizeActive(const char* This) const; |
| 18 | size_t sizeTotal(const char* This) const; |
| 19 | size_t getBytes(const char* This) const; |
| 20 | }; |
| 21 | static Type type; |
| 22 | |
| 23 | public: |
| 24 | |
| 25 | /* Returns maximum number of stored primitives */ |
| 26 | static __forceinline size_t max_size() { return M; } |
| 27 | |
| 28 | /* Returns required number of primitive blocks for N primitives */ |
| 29 | static __forceinline size_t blocks(size_t N) { return (N+M-1)/M; } |
| 30 | |
| 31 | static __forceinline size_t bytes(size_t N) |
| 32 | { |
| 33 | const size_t f = N/M, r = N%M; |
| 34 | static_assert(sizeof(CurveNv) == 22+25*M+4*16*M, "internal data layout issue" ); |
| 35 | return f*sizeof(CurveNv) + (r!=0)*(22 + 25*r + 4*16*r); |
| 36 | } |
| 37 | |
| 38 | public: |
| 39 | |
| 40 | /*! Default constructor. */ |
| 41 | __forceinline CurveNv () {} |
| 42 | |
| 43 | /*! fill curve from curve list */ |
| 44 | __forceinline void fill(const PrimRef* prims, size_t& begin, size_t _end, Scene* scene) |
| 45 | { |
| 46 | size_t end = min(begin+M,_end); |
| 47 | size_t N = end-begin; |
| 48 | |
| 49 | /* encode all primitives */ |
| 50 | for (size_t i=0; i<N; i++) |
| 51 | { |
| 52 | const PrimRef& prim = prims[begin+i]; |
| 53 | const unsigned int geomID = prim.geomID(); |
| 54 | const unsigned int primID = prim.primID(); |
| 55 | CurveGeometry* mesh = (CurveGeometry*) scene->get(geomID); |
| 56 | const unsigned vtxID = mesh->curve(primID); |
| 57 | Vec3fa::storeu(&this->vertices(i,N)[0],mesh->vertex(vtxID+0)); |
| 58 | Vec3fa::storeu(&this->vertices(i,N)[1],mesh->vertex(vtxID+1)); |
| 59 | Vec3fa::storeu(&this->vertices(i,N)[2],mesh->vertex(vtxID+2)); |
| 60 | Vec3fa::storeu(&this->vertices(i,N)[3],mesh->vertex(vtxID+3)); |
| 61 | } |
| 62 | } |
| 63 | |
| 64 | template<typename BVH, typename Allocator> |
| 65 | __forceinline static typename BVH::NodeRef createLeaf (BVH* bvh, const PrimRef* prims, const range<size_t>& set, const Allocator& alloc) |
| 66 | { |
| 67 | if (set.size() == 0) |
| 68 | return BVH::emptyNode; |
| 69 | |
| 70 | /* fall back to CurveNi for oriented curves */ |
| 71 | unsigned int geomID = prims[set.begin()].geomID(); |
| 72 | if (bvh->scene->get(geomID)->getCurveType() == Geometry::GTY_SUBTYPE_ORIENTED_CURVE) { |
| 73 | return CurveNi<M>::createLeaf(bvh,prims,set,alloc); |
| 74 | } |
| 75 | if (bvh->scene->get(geomID)->getCurveBasis() == Geometry::GTY_BASIS_HERMITE) { |
| 76 | return CurveNi<M>::createLeaf(bvh,prims,set,alloc); |
| 77 | } |
| 78 | |
| 79 | size_t start = set.begin(); |
| 80 | size_t items = CurveNv::blocks(set.size()); |
| 81 | size_t numbytes = CurveNv::bytes(set.size()); |
| 82 | CurveNv* accel = (CurveNv*) alloc.malloc1(numbytes,BVH::byteAlignment); |
| 83 | for (size_t i=0; i<items; i++) { |
| 84 | accel[i].CurveNv<M>::fill(prims,start,set.end(),bvh->scene); |
| 85 | accel[i].CurveNi<M>::fill(prims,start,set.end(),bvh->scene); |
| 86 | } |
| 87 | return bvh->encodeLeaf((char*)accel,items); |
| 88 | }; |
| 89 | |
| 90 | public: |
| 91 | unsigned char data[4*16*M]; |
| 92 | __forceinline Vec3fa* vertices(size_t i, size_t N) { return (Vec3fa*)CurveNi<M>::end(N)+4*i; } |
| 93 | __forceinline const Vec3fa* vertices(size_t i, size_t N) const { return (Vec3fa*)CurveNi<M>::end(N)+4*i; } |
| 94 | }; |
| 95 | |
| 96 | template<int M> |
| 97 | typename CurveNv<M>::Type CurveNv<M>::type; |
| 98 | |
| 99 | typedef CurveNv<4> Curve4v; |
| 100 | typedef CurveNv<8> Curve8v; |
| 101 | } |
| 102 | |