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(a: begin+M,b: _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(i: geomID); |
56 | const unsigned vtxID = mesh->curve(i: primID); |
57 | Vec3fa::storeu(ptr: &this->vertices(i,N)[0],v: mesh->vertex(i: vtxID+0)); |
58 | Vec3fa::storeu(ptr: &this->vertices(i,N)[1],v: mesh->vertex(i: vtxID+1)); |
59 | Vec3fa::storeu(ptr: &this->vertices(i,N)[2],v: mesh->vertex(i: vtxID+2)); |
60 | Vec3fa::storeu(ptr: &this->vertices(i,N)[3],v: mesh->vertex(i: 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(N: set.size()); |
81 | size_t numbytes = CurveNv::bytes(N: 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 | |