1// Copyright 2009-2021 Intel Corporation
2// SPDX-License-Identifier: Apache-2.0
3
4#include "scene_triangle_mesh.h"
5#include "scene.h"
6
7namespace embree
8{
9#if defined(EMBREE_LOWEST_ISA)
10
11 TriangleMesh::TriangleMesh (Device* device)
12 : Geometry(device,GTY_TRIANGLE_MESH,0,1)
13 {
14 vertices.resize(numTimeSteps);
15 }
16
17 void TriangleMesh::setMask (unsigned mask)
18 {
19 this->mask = mask;
20 Geometry::update();
21 }
22
23 void TriangleMesh::setNumTimeSteps (unsigned int numTimeSteps)
24 {
25 vertices.resize(numTimeSteps);
26 Geometry::setNumTimeSteps(numTimeSteps);
27 }
28
29 void TriangleMesh::setVertexAttributeCount (unsigned int N)
30 {
31 vertexAttribs.resize(N);
32 Geometry::update();
33 }
34
35 void TriangleMesh::setBuffer(RTCBufferType type, unsigned int slot, RTCFormat format, const Ref<Buffer>& buffer, size_t offset, size_t stride, unsigned int num)
36 {
37 /* verify that all accesses are 4 bytes aligned */
38 if (((size_t(buffer->getPtr()) + offset) & 0x3) || (stride & 0x3))
39 throw_RTCError(RTC_ERROR_INVALID_OPERATION, "data must be 4 bytes aligned");
40
41 if (type == RTC_BUFFER_TYPE_VERTEX)
42 {
43 if (format != RTC_FORMAT_FLOAT3)
44 throw_RTCError(RTC_ERROR_INVALID_OPERATION, "invalid vertex buffer format");
45
46 /* if buffer is larger than 16GB the premultiplied index optimization does not work */
47 if (stride*num > 16ll*1024ll*1024ll*1024ll)
48 throw_RTCError(RTC_ERROR_INVALID_OPERATION, "vertex buffer can be at most 16GB large");
49
50 if (slot >= vertices.size())
51 throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid vertex buffer slot");
52
53 vertices[slot].set(buffer, offset, stride, num, format);
54 vertices[slot].checkPadding16();
55 vertices0 = vertices[0];
56 }
57 else if (type == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE)
58 {
59 if (format < RTC_FORMAT_FLOAT || format > RTC_FORMAT_FLOAT16)
60 throw_RTCError(RTC_ERROR_INVALID_OPERATION, "invalid vertex attribute buffer format");
61
62 if (slot >= vertexAttribs.size())
63 throw_RTCError(RTC_ERROR_INVALID_OPERATION, "invalid vertex attribute buffer slot");
64
65 vertexAttribs[slot].set(buffer, offset, stride, num, format);
66 vertexAttribs[slot].checkPadding16();
67 }
68 else if (type == RTC_BUFFER_TYPE_INDEX)
69 {
70 if (slot != 0)
71 throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid buffer slot");
72 if (format != RTC_FORMAT_UINT3)
73 throw_RTCError(RTC_ERROR_INVALID_OPERATION, "invalid index buffer format");
74
75 triangles.set(buffer, offset, stride, num, format);
76 setNumPrimitives(num);
77 }
78 else
79 throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "unknown buffer type");
80 }
81
82 void* TriangleMesh::getBuffer(RTCBufferType type, unsigned int slot)
83 {
84 if (type == RTC_BUFFER_TYPE_INDEX)
85 {
86 if (slot != 0)
87 throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid buffer slot");
88 return triangles.getPtr();
89 }
90 else if (type == RTC_BUFFER_TYPE_VERTEX)
91 {
92 if (slot >= vertices.size())
93 throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid buffer slot");
94 return vertices[slot].getPtr();
95 }
96 else if (type == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE)
97 {
98 if (slot >= vertexAttribs.size())
99 throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid buffer slot");
100 return vertexAttribs[slot].getPtr();
101 }
102 else
103 {
104 throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "unknown buffer type");
105 return nullptr;
106 }
107 }
108
109 void TriangleMesh::updateBuffer(RTCBufferType type, unsigned int slot)
110 {
111 if (type == RTC_BUFFER_TYPE_INDEX)
112 {
113 if (slot != 0)
114 throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid buffer slot");
115 triangles.setModified();
116 }
117 else if (type == RTC_BUFFER_TYPE_VERTEX)
118 {
119 if (slot >= vertices.size())
120 throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid buffer slot");
121 vertices[slot].setModified();
122 }
123 else if (type == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE)
124 {
125 if (slot >= vertexAttribs.size())
126 throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid buffer slot");
127 vertexAttribs[slot].setModified();
128 }
129 else
130 {
131 throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "unknown buffer type");
132 }
133
134 Geometry::update();
135 }
136
137 void TriangleMesh::commit()
138 {
139 /* verify that stride of all time steps are identical */
140 for (unsigned int t=0; t<numTimeSteps; t++)
141 if (vertices[t].getStride() != vertices[0].getStride())
142 throw_RTCError(RTC_ERROR_INVALID_OPERATION,"stride of vertex buffers have to be identical for each time step");
143
144 Geometry::commit();
145 }
146
147 void TriangleMesh::addElementsToCount (GeometryCounts & counts) const
148 {
149 if (numTimeSteps == 1) counts.numTriangles += numPrimitives;
150 else counts.numMBTriangles += numPrimitives;
151 }
152
153 bool TriangleMesh::verify()
154 {
155 /*! verify size of vertex arrays */
156 if (vertices.size() == 0) return false;
157 for (const auto& buffer : vertices)
158 if (buffer.size() != numVertices())
159 return false;
160
161 /*! verify size of user vertex arrays */
162 for (const auto& buffer : vertexAttribs)
163 if (buffer.size() != numVertices())
164 return false;
165
166 /*! verify triangle indices */
167 for (size_t i=0; i<size(); i++) {
168 if (triangles[i].v[0] >= numVertices()) return false;
169 if (triangles[i].v[1] >= numVertices()) return false;
170 if (triangles[i].v[2] >= numVertices()) return false;
171 }
172
173 /*! verify vertices */
174 for (const auto& buffer : vertices)
175 for (size_t i=0; i<buffer.size(); i++)
176 if (!isvalid(buffer[i]))
177 return false;
178
179 return true;
180 }
181
182 void TriangleMesh::interpolate(const RTCInterpolateArguments* const args) {
183 interpolate_impl<4>(args);
184 }
185
186#endif
187
188 namespace isa
189 {
190 TriangleMesh* createTriangleMesh(Device* device) {
191 return new TriangleMeshISA(device);
192 }
193 }
194}
195