Skip to content

Commit 0136b63

Browse files
make hash recompute optinal on all mesh manipulation functions
add primitive reversal modes to smooth unwelding and conversion to list indexing methods, this way we have
1 parent ef14edf commit 0136b63

3 files changed

Lines changed: 502 additions & 870 deletions

File tree

include/nbl/asset/utils/CPolygonGeometryManipulator.h

Lines changed: 36 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -128,27 +128,28 @@ class NBL_API2 CPolygonGeometryManipulator
128128
const_cast<IGeometryBase::SAABBStorage&>(geo->getAABBStorage()) = computeAABB(geo);
129129
}
130130

131-
static inline core::smart_refctd_ptr<ICPUPolygonGeometry> createTriangleListIndexing(const ICPUPolygonGeometry* geo)
131+
static inline core::smart_refctd_ptr<ICPUPolygonGeometry> createTriangleListIndexing(const ICPUPolygonGeometry* geo, const bool reverse=false, const bool recomputeHash=true)
132132
{
133133
const auto* indexing = geo->getIndexingCallback();
134-
if (!indexing) return nullptr;
135-
if (indexing->degree() != 3) return nullptr;
134+
if (!indexing || indexing->degree()!=3) // TODO: why just triangle?
135+
return nullptr;
136136

137137
const auto originalView = geo->getIndexView();
138-
const auto originalIndexSize = originalView ? originalView.composed.stride : 0;
138+
const auto originalIndexSize = originalView ? originalView.composed.stride:0;
139139
const auto primCount = geo->getPrimitiveCount();
140140
const auto maxIndex = geo->getPositionView().getElementCount() - 1;
141141
const uint8_t indexSize = maxIndex <= std::numeric_limits<uint16_t>::max() ? sizeof(uint16_t) : sizeof(uint32_t);
142142
const auto outGeometry = core::move_and_static_cast<ICPUPolygonGeometry>(geo->clone(0u));
143143

144-
if (indexing && indexing->knownTopology() == EPT_TRIANGLE_LIST)
144+
if (indexing->knownTopology()==EPT_TRIANGLE_LIST && !reverse)
145145
return outGeometry;
146146

147147

148148
auto* outGeo = outGeometry.get();
149149
const auto indexBufferUsages = [&]
150150
{
151-
if (originalView) return originalView.src.buffer->getUsageFlags();
151+
if (originalView)
152+
return originalView.src.buffer->getUsageFlags();
152153
return core::bitflag<IBuffer::E_USAGE_FLAGS>(IBuffer::EUF_INDEX_BUFFER_BIT);
153154
}();
154155
auto indexBuffer = ICPUBuffer::create({ primCount * indexing->degree() * indexSize, indexBufferUsages });
@@ -173,7 +174,8 @@ class NBL_API2 CPolygonGeometryManipulator
173174
.indexSize = originalIndexSize,
174175
.beginPrimitive = 0,
175176
.endPrimitive = primCount,
176-
.out = indexBufferPtr,
177+
.reversePrims = reverse,
178+
.out = indexBufferPtr
177179
};
178180
indexing->operator()(context);
179181

@@ -190,7 +192,8 @@ class NBL_API2 CPolygonGeometryManipulator
190192
.indexSize = originalIndexSize,
191193
.beginPrimitive = 0,
192194
.endPrimitive = primCount,
193-
.out = indexBufferPtr,
195+
.reversePrims = reverse,
196+
.out = indexBufferPtr
194197
};
195198
indexing->operator()(context);
196199

@@ -209,11 +212,35 @@ class NBL_API2 CPolygonGeometryManipulator
209212

210213
outGeo->setIndexing(IPolygonGeometryBase::TriangleList());
211214
outGeo->setIndexView(std::move(indexView));
212-
CGeometryManipulator::recomputeContentHash(outGeo->getIndexView());
215+
216+
if (recomputeHash)
217+
CGeometryManipulator::recomputeContentHash(outGeo->getIndexView());
213218

214219
return outGeometry;
215220
}
216221

222+
template <typename FetchVertexFn>
223+
requires (std::same_as<std::invoke_result_t<FetchVertexFn, size_t>, hlsl::float32_t3>)
224+
static inline hlsl::shapes::OBB<3, hlsl::float32_t> calculateOBB(size_t vertexCount, FetchVertexFn&& fetchFn, float epsilon = 1.525e-5f)
225+
{
226+
return COBBGenerator::compute(vertexCount, std::forward<FetchVertexFn>(fetchFn), epsilon);
227+
}
228+
229+
static core::smart_refctd_ptr<ICPUPolygonGeometry> createUnweldedList(const ICPUPolygonGeometry* inGeo, const bool reverse=false, const bool recomputeHash=true);
230+
231+
using SSNGVertexData = CSmoothNormalGenerator::VertexData;
232+
using SSNGVxCmpFunction = CSmoothNormalGenerator::VxCmpFunction;
233+
// NOTE: Requires unwelded mesh on input, TODO make it resillient against that (only unweld normals temporarily, maybe even avoid position unweld)
234+
static core::smart_refctd_ptr<ICPUPolygonGeometry> createSmoothVertexNormal(const ICPUPolygonGeometry* inbuffer, const bool enableWelding=false, float epsilon=1.525e-5f,
235+
SSNGVxCmpFunction vxcmp=[](const SSNGVertexData& v0, const SSNGVertexData& v1, const ICPUPolygonGeometry* buffer)
236+
{
237+
constexpr float cosOf45Deg = 0.70710678118f;
238+
return hlsl::dot(v0.weightedNormal,v1.weightedNormal)*hlsl::rsqrt(hlsl::dot(v0.weightedNormal,v0.weightedNormal)*hlsl::dot(v1.weightedNormal,v1.weightedNormal)) > cosOf45Deg;
239+
},
240+
const bool recomputeHash = true
241+
);
242+
243+
217244
//! Comparison methods
218245
enum E_ERROR_METRIC
219246
{
@@ -232,26 +259,6 @@ class NBL_API2 CPolygonGeometryManipulator
232259
EEM_QUATERNION,
233260
EEM_COUNT
234261
};
235-
236-
template <typename FetchVertexFn>
237-
requires (std::same_as<std::invoke_result_t<FetchVertexFn, size_t>, hlsl::float32_t3>)
238-
static inline hlsl::shapes::OBB<3, hlsl::float32_t> calculateOBB(size_t vertexCount, FetchVertexFn&& fetchFn, float epsilon = 1.525e-5f)
239-
{
240-
return COBBGenerator::compute(vertexCount, std::forward<FetchVertexFn>(fetchFn), epsilon);
241-
}
242-
243-
static core::smart_refctd_ptr<ICPUPolygonGeometry> createUnweldedList(const ICPUPolygonGeometry* inGeo);
244-
245-
using SSNGVertexData = CSmoothNormalGenerator::VertexData;
246-
using SSNGVxCmpFunction = CSmoothNormalGenerator::VxCmpFunction;
247-
248-
static core::smart_refctd_ptr<ICPUPolygonGeometry> createSmoothVertexNormal(const ICPUPolygonGeometry* inbuffer, bool enableWelding = false, float epsilon = 1.525e-5f,
249-
SSNGVxCmpFunction vxcmp = [](const SSNGVertexData& v0, const SSNGVertexData& v1, const ICPUPolygonGeometry* buffer)
250-
{
251-
constexpr float cosOf45Deg = 0.70710678118f;
252-
return dot(normalize(v0.weightedNormal),normalize(v1.weightedNormal)) > cosOf45Deg;
253-
});
254-
255262
#if 0 // TODO: REDO
256263
//! Struct used to pass chosen comparison method and epsilon to functions performing error metrics.
257264
/**
@@ -385,24 +392,6 @@ class NBL_API2 CPolygonGeometryManipulator
385392
*/
386393
static core::smart_refctd_ptr<ICPUBuffer> idxBufferFromLineStripsToLines(const void* _input, uint32_t& _idxCount, E_INDEX_TYPE _inIndexType, E_INDEX_TYPE _outIndexType);
387394

388-
//! Creates index buffer from input converting it to indices for triangle list primitives. Input is assumed to be indices for triangle strip.
389-
/**
390-
@param _input Input index buffer's data.
391-
@param _idxCount Index count.
392-
@param _inIndexType Type of input index buffer data (32bit or 16bit).
393-
@param _outIndexType Type of output index buffer data (32bit or 16bit).
394-
*/
395-
static core::smart_refctd_ptr<ICPUBuffer> idxBufferFromTriangleStripsToTriangles(const void* _input, uint32_t& _idxCount, E_INDEX_TYPE _inIndexType, E_INDEX_TYPE _outIndexType);
396-
397-
//! Creates index buffer from input converting it to indices for triangle list primitives. Input is assumed to be indices for triangle fan.
398-
/**
399-
@param _input Input index buffer's data.
400-
@param _idxCount Index count.
401-
@param _inIndexType Type of input index buffer data (32bit or 16bit).
402-
@param _outIndexType Type of output index buffer data (32bit or 16bit).
403-
*/
404-
static core::smart_refctd_ptr<ICPUBuffer> idxBufferFromTrianglesFanToTriangles(const void* _input, uint32_t& _idxCount, E_INDEX_TYPE _inIndexType, E_INDEX_TYPE _outIndexType);
405-
406395
//!
407396
static inline std::array<uint32_t,3u> getTriangleIndices(const ICPUMeshBuffer* mb, uint32_t triangleIx)
408397
{
@@ -606,40 +595,6 @@ class NBL_API2 CPolygonGeometryManipulator
606595
return aabb;
607596
}
608597

609-
//! Recalculates the cached bounding box of the meshbuffer
610-
static inline void recalculateBoundingBox(ICPUMeshBuffer* meshbuffer)
611-
{
612-
meshbuffer->setBoundingBox(calculateBoundingBox(meshbuffer,meshbuffer->getJointAABBs()));
613-
}
614-
615-
//! Flips the direction of surfaces.
616-
/** Changes backfacing triangles to frontfacing
617-
triangles and vice versa.
618-
\param mesh Mesh on which the operation is performed. */
619-
static void flipSurfaces(ICPUMeshBuffer* inbuffer);
620-
621-
//! Creates a copy of a mesh with all vertices unwelded
622-
/** \param mesh Input mesh
623-
\return Mesh consisting only of unique faces. All vertices
624-
which were previously shared are now duplicated. */
625-
static core::smart_refctd_ptr<ICPUMeshBuffer> createMeshBufferUniquePrimitives(ICPUMeshBuffer* inbuffer, bool _makeIndexBuf = false);
626-
627-
//
628-
static core::smart_refctd_ptr<ICPUMeshBuffer> calculateSmoothNormals(ICPUMeshBuffer* inbuffer, bool makeNewMesh = false, float epsilon = 1.525e-5f,
629-
uint32_t normalAttrID = 3u,
630-
VxCmpFunction vxcmp = [](const IMeshManipulator::SSNGVertexData& v0, const IMeshManipulator::SSNGVertexData& v1, ICPUMeshBuffer* buffer)
631-
{
632-
static constexpr float cosOf45Deg = 0.70710678118f;
633-
return dot(v0.parentTriangleFaceNormal,v1.parentTriangleFaceNormal)[0] > cosOf45Deg;
634-
});
635-
636-
637-
//! Creates a copy of a mesh with vertices welded
638-
/** \param mesh Input mesh
639-
\param errMetrics Array of size EVAI_COUNT. Describes error metric for each vertex attribute (used if attribute is of floating point or normalized type).
640-
\param tolerance The threshold for vertex comparisons.
641-
\return Mesh without redundant vertices. */
642-
static core::smart_refctd_ptr<ICPUMeshBuffer> createMeshBufferWelded(ICPUMeshBuffer *inbuffer, const SErrorMetric* errMetrics, const bool& optimIndexType = true, const bool& makeNewMesh = false);
643598

644599
//! Throws meshbuffer into full optimizing pipeline consisting of: vertices welding, z-buffer optimization, vertex cache optimization (Forsyth's algorithm), fetch optimization and attributes requantization. A new meshbuffer is created unless given meshbuffer doesn't own (getMeshDataAndFormat()==NULL) a data format descriptor.
645600
/**@return A new meshbuffer or NULL if an error occured. */
@@ -864,45 +819,6 @@ class CMeshManipulator : public IMeshManipulator
864819
return output;
865820
}
866821

867-
template<typename InType, typename OutType>
868-
static inline core::smart_refctd_ptr<ICPUBuffer> triangleStripsToTriangles(const void* _input, uint32_t& _idxCount)
869-
{
870-
const auto outputSize = _idxCount = (_idxCount - 2) * 3;
871-
872-
auto output = ICPUBuffer::create({ sizeof(OutType)*outputSize });
873-
const auto* iptr = reinterpret_cast<const InType*>(_input);
874-
auto* optr = reinterpret_cast<OutType*>(output->getPointer());
875-
for (uint32_t i = 0, j = 0; i < outputSize; j += 2)
876-
{
877-
optr[i++] = iptr[j + 0];
878-
optr[i++] = iptr[j + 1];
879-
optr[i++] = iptr[j + 2];
880-
if (i == outputSize)
881-
break;
882-
optr[i++] = iptr[j + 2];
883-
optr[i++] = iptr[j + 1];
884-
optr[i++] = iptr[j + 3];
885-
}
886-
return output;
887-
}
888-
889-
template<typename InType, typename OutType>
890-
static inline core::smart_refctd_ptr<ICPUBuffer> trianglesFanToTriangles(const void* _input, uint32_t& _idxCount)
891-
{
892-
const auto outputSize = _idxCount = (_idxCount - 2) * 3;
893-
894-
auto output = ICPUBuffer::create({ sizeof(OutType)*outputSize });
895-
const auto* iptr = reinterpret_cast<const InType*>(_input);
896-
auto* optr = reinterpret_cast<OutType*>(output->getPointer());
897-
for (uint32_t i = 0, j = 1; i < outputSize;)
898-
{
899-
optr[i++] = iptr[0];
900-
optr[i++] = iptr[j++];
901-
optr[i++] = iptr[j];
902-
}
903-
return output;
904-
}
905-
906822
private:
907823
CQuantNormalCache quantNormalCache;
908824
CQuantQuaternionCache quantQuaternionCache;

0 commit comments

Comments
 (0)