Skip to content

Mesh loaders kevin #894

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 41 commits into from
Aug 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
4a37ba5
Implement createCylinder, createCone, createSphere, CreateArrow
Jun 25, 2025
2d8b7c4
Implement getIndexType convenience function for IPolygonGeometry
Jun 25, 2025
cdcaae9
Implement createIcosphere
Jun 28, 2025
2e063d7
Remove color parameter from create<Geometry>
Jun 28, 2025
f0b5064
Fix indentation
Jun 28, 2025
68a689c
Fix normal and uv type
Jun 29, 2025
ca7f182
Return nullptr if vertexCount overflow
Jun 29, 2025
a2b7b04
Remove simd vector from normal quantization cache
Jul 1, 2025
83f39d3
Fix SBuferRange to SBufferBinding conversion requirement
Jul 1, 2025
983ace9
createArrow multiple geometries
Jul 1, 2025
090dae2
DRY findLSB
Jul 2, 2025
9e9e233
Merge branch 'master' into mesh_loaders_kevin
Jul 3, 2025
d36687f
Add missing ECommonEnums.cpp to CMakelists.txt
Jul 3, 2025
bd3a266
Extract some common attribute view creation into its own function
Jul 18, 2025
489e2f2
Slight type naming improvement in geometry creator
Jul 18, 2025
de02323
Fix bug prone constant
Jul 18, 2025
1964b27
Accept tesselation as uint16_t parameter
Jul 18, 2025
2157235
Remove reciprocal_approxim usage
Jul 18, 2025
7728987
use hlsl::numbers instead of constant from core
Jul 18, 2025
53f81af
Reorder normal calculation so no need to normalize position
Jul 18, 2025
e29bbf9
Remove packSnorm
Jul 18, 2025
b957ca7
Small impovement on Icosphere index_t
Jul 18, 2025
75d486d
Remove unnecessary method on Icosphere
Jul 18, 2025
e0013cb
Fix normal quantization cache
Jul 21, 2025
4afd072
implement constexpr findLSB
Jul 23, 2025
a001472
Remove unused include
Jul 23, 2025
f8e837b
Fix createArrow to return ICPUGeometryCollection instead of vector of…
Jul 25, 2025
6552952
Add more ray tracing intersection query
Jul 25, 2025
e0b30d0
Add transform.hlsl to cmakelists
Jul 25, 2025
c6dd9ac
Transform data minimum alignment fix
Jul 25, 2025
c45f29c
Merge branch 'master' into mesh_loaders_kevin
Jul 25, 2025
86dae55
Fix after merge with master
Jul 25, 2025
c7caf76
Fix uninitialized bug in quantization cache
Jul 26, 2025
ae5a755
Add some comment in quantization cache
Jul 26, 2025
02d6c6d
Fix indentation in CGeometryCreator.cpp
Jul 28, 2025
bb45773
Fix indentation of CDirQuantCacheBase.h
Jul 28, 2025
1bedf2d
Fix indentation of CGeometryCreator.h
Jul 28, 2025
50b6493
Merge branch 'master' into mesh_loaders_kevin
Jul 30, 2025
b152755
Fix small things
Jul 31, 2025
daea0ad
Implement rotation_mat function on hlsl
Aug 4, 2025
a6ef74c
Small fixes on quantization cache.
Aug 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
287 changes: 4 additions & 283 deletions include/nbl/asset/ECommonEnums.h

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions include/nbl/asset/IAccelerationStructure.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ namespace nbl::asset
class IAccelerationStructure : public virtual core::IReferenceCounted
{
public:
static constexpr inline size_t TransformDataMinAlignment = 16;

// build flags, we don't expose flags that don't make sense for certain levels
enum class BUILD_FLAGS : uint8_t
{
Expand Down
2 changes: 1 addition & 1 deletion include/nbl/asset/IBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ struct SBufferRange
inline operator SBufferRange<const BufferType>&() {return *reinterpret_cast<SBufferRange<const BufferType>*>(this);}
inline operator const SBufferRange<const BufferType>&() const {return *reinterpret_cast<const SBufferRange<const BufferType>*>(this);}

template<typename BT> requires std::is_same_v<std::remove_const_t<BT>,BufferType>
template<typename BT> requires (std::is_const_v<BT> && std::is_base_of_v<IBuffer,std::remove_const_t<BT>>)
inline operator SBufferBinding<BT>() const { return {.offset=offset,.buffer=buffer}; }

explicit inline operator bool() const {return isValid();}
Expand Down
40 changes: 21 additions & 19 deletions include/nbl/asset/IPolygonGeometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,26 @@ class IPolygonGeometry : public IIndexableGeometry<BufferType>, public IPolygonG
// For User defined semantics
inline const core::vector<SDataView>& getAuxAttributeViews() const {return m_auxAttributeViews;}

inline E_INDEX_TYPE getIndexType() const
{
auto indexType = EIT_UNKNOWN;
// disallowed index format
if (base_t::m_indexView)
{
switch (base_t::m_indexView.composed.format)
{
case EF_R16_UINT:
indexType = EIT_16BIT;
break;
case EF_R32_UINT: [[fallthrough]];
indexType = EIT_32BIT;
break;
default:
break;
}
}
return indexType;
}

// Does not set the `transform` or `geometryFlags` fields, because it doesn't care about it.
// Also won't set second set of vertex data, opacity mipmaps, etc.
Expand All @@ -212,30 +232,12 @@ class IPolygonGeometry : public IIndexableGeometry<BufferType>, public IPolygonG
// must be a triangle list, but don't want to compare pointers
if (m_indexing && m_indexing->knownTopology()==EPT_TRIANGLE_LIST)// && m_indexing->degree() == TriangleList()->degree() && m_indexing->rate() == TriangleList->rate())
{
auto indexType = EIT_UNKNOWN;
// disallowed index format
if (base_t::m_indexView)
{
switch (base_t::m_indexView.composed.format)
{
case EF_R16_UINT:
indexType = EIT_16BIT;
break;
case EF_R32_UINT: [[fallthrough]];
indexType = EIT_32BIT;
break;
default:
break;
}
if (indexType==EIT_UNKNOWN)
return retval;
}
retval.vertexData[0] = base_t::m_positionView.src;
retval.indexData = base_t::m_indexView.src;
retval.maxVertex = base_t::m_positionView.getElementCount() - 1;
retval.vertexStride = base_t::m_positionView.composed.getStride();
retval.vertexFormat = base_t::m_positionView.composed.format;
retval.indexType = indexType;
retval.indexType = getIndexType();
}
return retval;
}
Expand Down
144 changes: 91 additions & 53 deletions include/nbl/asset/utils/CDirQuantCacheBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,25 +43,26 @@ class CDirQuantCacheBase

Vector8u3() : x(0u),y(0u),z(0u) {}
Vector8u3(const Vector8u3&) = default;
explicit Vector8u3(const core::vectorSIMDu32& val)
explicit Vector8u3(const hlsl::uint32_t4& val)
{
operator=(val);
}

Vector8u3& operator=(const Vector8u3&) = default;
Vector8u3& operator=(const core::vectorSIMDu32& val)
Vector8u3& operator=(const hlsl::uint32_t4& val)
{
x = val.x;
y = val.y;
z = val.z;
return *this;
}

inline core::vectorSIMDu32 getValue() const
hlsl::uint32_t4 getValue() const
{
return core::vectorSIMDu32(x,y,z);
return { x, y, z, 0 };
}


private:
uint8_t x;
uint8_t y;
Expand All @@ -74,13 +75,13 @@ class CDirQuantCacheBase

Vector8u4() : x(0u),y(0u),z(0u),w(0u) {}
Vector8u4(const Vector8u4&) = default;
explicit Vector8u4(const core::vectorSIMDu32& val)
explicit Vector8u4(const hlsl::uint32_t4& val)
{
operator=(val);
}

Vector8u4& operator=(const Vector8u4&) = default;
Vector8u4& operator=(const core::vectorSIMDu32& val)
Vector8u4& operator=(const hlsl::uint32_t4& val)
{
x = val.x;
y = val.y;
Expand All @@ -89,9 +90,9 @@ class CDirQuantCacheBase
return *this;
}

inline core::vectorSIMDu32 getValue() const
hlsl::uint32_t4 getValue() const
{
return core::vectorSIMDu32(x,y,z,w);
return { x, y, z, w };
}

private:
Expand All @@ -108,16 +109,16 @@ class CDirQuantCacheBase

Vector1010102() : storage(0u) {}
Vector1010102(const Vector1010102&) = default;
explicit Vector1010102(const core::vectorSIMDu32& val)
explicit Vector1010102(const hlsl::uint32_t4& val)
{
operator=(val);
}

Vector1010102& operator=(const Vector1010102&) = default;
Vector1010102& operator=(const core::vectorSIMDu32& val)
Vector1010102& operator=(const hlsl::uint32_t4& val)
{
constexpr auto storageBits = quantizationBits+1u;
storage = val.x|(val.y<<storageBits)|(val.z<<(storageBits*2u));
constexpr auto storageBits = quantizationBits + 1u;
storage = val.x | (val.y << storageBits) | (val.z << (storageBits * 2u));
return *this;
}

Expand All @@ -130,13 +131,13 @@ class CDirQuantCacheBase
return storage==other.storage;
}

inline core::vectorSIMDu32 getValue() const
hlsl::uint32_t4 getValue() const
{
constexpr auto storageBits = quantizationBits+1u;
const core::vectorSIMDu32 mask((0x1u<<storageBits)-1u);
return core::vectorSIMDu32(storage,storage>>storageBits,storage>>(storageBits*2u))&mask;
constexpr auto storageBits = quantizationBits + 1u;
const auto mask = (0x1u << storageBits) - 1u;
return { storage & mask, (storage >> storageBits) & mask, (storage >> (storageBits * 2)) & mask, 0};
}

private:
uint32_t storage;
};
Expand All @@ -149,25 +150,25 @@ class CDirQuantCacheBase

Vector16u3() : x(0u),y(0u),z(0u) {}
Vector16u3(const Vector16u3&) = default;
explicit Vector16u3(const core::vectorSIMDu32& val)
explicit Vector16u3(const hlsl::uint32_t4& val)
{
operator=(val);
}

Vector16u3& operator=(const Vector16u3&) = default;
Vector16u3& operator=(const core::vectorSIMDu32& val)
Vector16u3& operator=(const hlsl::uint32_t4& val)
{
x = val.x;
y = val.y;
z = val.z;
return *this;
}

inline core::vectorSIMDu32 getValue() const
hlsl::uint32_t4 getValue() const
{
return core::vectorSIMDu32(x,y,z);
return { x, y, z, 0 };
}

private:
uint16_t x;
uint16_t y;
Expand All @@ -180,13 +181,13 @@ class CDirQuantCacheBase

Vector16u4() : x(0u),y(0u),z(0u),w(0u) {}
Vector16u4(const Vector16u4&) = default;
explicit Vector16u4(const core::vectorSIMDu32& val)
explicit Vector16u4(const hlsl::uint32_t4& val)
{
operator=(val);
}

Vector16u4& operator=(const Vector16u4&) = default;
Vector16u4& operator=(const core::vectorSIMDu32& val)
Vector16u4& operator=(const hlsl::uint32_t4& val)
{
x = val.x;
y = val.y;
Expand All @@ -195,11 +196,11 @@ class CDirQuantCacheBase
return *this;
}

inline core::vectorSIMDu32 getValue() const
hlsl::float32_t4 getValue() const
{
return core::vectorSIMDu32(x,y,z,w);
return { x, y, z, w };
}

private:
uint16_t x;
uint16_t y;
Expand Down Expand Up @@ -377,11 +378,30 @@ class CDirQuantCacheBase : public virtual core::IReferenceCounted, public impl::
std::tuple<cache_type_t<Formats>...> cache;

template<uint32_t dimensions, E_FORMAT CacheFormat>
value_type_t<CacheFormat> quantize(const core::vectorSIMDf& value)
value_type_t<CacheFormat> quantize(const hlsl::vector<hlsl::float32_t, dimensions>& value)
{
const auto negativeMask = value < core::vectorSIMDf(0.0f);
using float32_tN = hlsl::vector<hlsl::float32_t, dimensions>;

auto to_vec_t4 = []<typename T>(hlsl::vector<T, dimensions> src, T padValue) -> hlsl::vector<T, 4>
{
if constexpr(dimensions == 1)
{
return {src.x, padValue, padValue, padValue};
} else if constexpr (dimensions == 2)
{
return {src.x, src.y, padValue, padValue};
} else if constexpr (dimensions == 3)
{
return {src.x, src.y, src.z, padValue};
} else if constexpr (dimensions == 4)
{
return {src.x, src.y, src.z, src.w};
}
};

const auto negativeMask = to_vec_t4(lessThan(value, float32_tN(0.0f)), false);

const core::vectorSIMDf absValue = abs(value);
const float32_tN absValue = abs(value);
const auto key = Key(absValue);

constexpr auto quantizationBits = quantization_bits_v<CacheFormat>;
Expand All @@ -393,32 +413,50 @@ class CDirQuantCacheBase : public virtual core::IReferenceCounted, public impl::
quantized = found->second;
else
{
const core::vectorSIMDf fit = findBestFit<dimensions,quantizationBits>(absValue);
const auto fit = findBestFit<dimensions,quantizationBits>(absValue);

const auto abs_fit = to_vec_t4(abs(fit), 0.f);
quantized = hlsl::uint32_t4(abs_fit.x, abs_fit.y, abs_fit.z, abs_fit.w);

quantized = core::vectorSIMDu32(core::abs(fit));
insertIntoCache<CacheFormat>(key,quantized);
}
}

const core::vectorSIMDu32 xorflag((0x1u<<(quantizationBits+1u))-1u);
auto restoredAsVec = quantized.getValue()^core::mix(core::vectorSIMDu32(0u),xorflag,negativeMask);
restoredAsVec += core::mix(core::vectorSIMDu32(0u),core::vectorSIMDu32(1u),negativeMask);
return value_type_t<CacheFormat>(restoredAsVec&xorflag);
auto select = [](hlsl::uint32_t4 val1, hlsl::uint32_t4 val2, hlsl::bool4 mask)
{
hlsl::uint32_t4 retval;
retval.x = mask.x ? val2.x : val1.x;
retval.y = mask.y ? val2.y : val1.y;
retval.z = mask.z ? val2.z : val1.z;
retval.w = mask.w ? val2.w : val1.w;
return retval;
};
;
// create all one bits
const hlsl::uint32_t4 xorflag((0x1u << (quantizationBits + 1u)) - 1u);

// for positive number xoring with 0 keep its value
// for negative number we xor with all one which will flip the bits, then we add one later. Flipping the bits then adding one will turn positive number into negative number
auto restoredAsVec = quantized.getValue() ^ select(hlsl::uint32_t4(0u), hlsl::uint32_t4(xorflag), negativeMask);
restoredAsVec += hlsl::uint32_t4(negativeMask);

return value_type_t<CacheFormat>(restoredAsVec);
}

template<uint32_t dimensions, uint32_t quantizationBits>
static inline core::vectorSIMDf findBestFit(const core::vectorSIMDf& value)
static inline hlsl::vector<hlsl::float32_t, dimensions> findBestFit(const hlsl::vector<hlsl::float32_t, dimensions>& value)
{
using float32_tN = hlsl::vector<hlsl::float32_t, dimensions>;
static_assert(dimensions>1u,"No point");
static_assert(dimensions<=4u,"High Dimensions are Hard!");
// precise normalize
const auto vectorForDots = value.preciseDivision(length(value));

const auto vectorForDots = hlsl::normalize(value);

//
core::vectorSIMDf fittingVector;
core::vectorSIMDf floorOffset;
float32_tN fittingVector;
float32_tN floorOffset = {};
constexpr uint32_t cornerCount = (0x1u<<(dimensions-1u))-1u;
core::vectorSIMDf corners[cornerCount] = {};
float32_tN corners[cornerCount] = {};
{
uint32_t maxDirCompIndex = 0u;
for (auto i=1u; i<dimensions; i++)
Expand All @@ -430,9 +468,9 @@ class CDirQuantCacheBase : public virtual core::IReferenceCounted, public impl::
if (maxDirectionComp < std::sqrtf(0.9998f / float(dimensions)))
{
_NBL_DEBUG_BREAK_IF(true);
return core::vectorSIMDf(0.f);
return float32_tN(0.f);
}
fittingVector = value.preciseDivision(core::vectorSIMDf(maxDirectionComp));
fittingVector = value / maxDirectionComp;
floorOffset[maxDirCompIndex] = 0.499f;
const uint32_t localCorner[7][3] = {
{1,0,0},
Expand All @@ -452,12 +490,12 @@ class CDirQuantCacheBase : public virtual core::IReferenceCounted, public impl::
}
}

core::vectorSIMDf bestFit;
float32_tN bestFit;
float closestTo1 = -1.f;
auto evaluateFit = [&](const core::vectorSIMDf& newFit) -> void
auto evaluateFit = [&](const float32_tN& newFit) -> void
{
auto newFitLen = core::length(newFit);
const float dp = core::dot<core::vectorSIMDf>(newFit,vectorForDots).preciseDivision(newFitLen)[0];
auto newFitLen = length(newFit);
const float dp = hlsl::dot(newFit,vectorForDots) / (newFitLen);
if (dp > closestTo1)
{
closestTo1 = dp;
Expand All @@ -466,18 +504,18 @@ class CDirQuantCacheBase : public virtual core::IReferenceCounted, public impl::
};

constexpr uint32_t cubeHalfSize = (0x1u << quantizationBits) - 1u;
const core::vectorSIMDf cubeHalfSizeND = core::vectorSIMDf(cubeHalfSize);
const float32_tN cubeHalfSizeND = hlsl::promote<float32_tN>(cubeHalfSize);
for (uint32_t n=cubeHalfSize; n>0u; n--)
{
//we'd use float addition in the interest of speed, to increment the loop
//but adding a small number to a large one loses precision, so multiplication preferrable
core::vectorSIMDf bottomFit = core::floor(fittingVector*float(n)+floorOffset);
if ((bottomFit<=cubeHalfSizeND).all())
const auto bottomFit = glm::floor(fittingVector * float(n) + floorOffset);
if (hlsl::all(glm::lessThanEqual(bottomFit, cubeHalfSizeND)))
evaluateFit(bottomFit);
for (auto i=0u; i<cornerCount; i++)
for (auto i = 0u; i < cornerCount; i++)
{
auto bottomFitTmp = bottomFit+corners[i];
if ((bottomFitTmp<=cubeHalfSizeND).all())
if (hlsl::all(glm::lessThanEqual(bottomFitTmp, cubeHalfSizeND)))
evaluateFit(bottomFitTmp);
}
}
Expand Down
Loading
Loading