Added topology convert utility function.

This commit is contained in:
Branimir Karadžić 2016-02-21 23:12:13 -08:00
parent 6fd77942ac
commit de08904b62
3 changed files with 259 additions and 0 deletions

View file

@ -20,4 +20,5 @@
#include "shader_dxbc.cpp" #include "shader_dxbc.cpp"
#include "shader_dx9bc.cpp" #include "shader_dx9bc.cpp"
#include "shader_spirv.cpp" #include "shader_spirv.cpp"
#include "topology.cpp"
#include "vertexdecl.cpp" #include "vertexdecl.cpp"

215
src/topology.cpp Normal file
View file

@ -0,0 +1,215 @@
/*
* Copyright 2011-2016 Branimir Karadzic. All rights reserved.
* License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
*/
#include <bx/debug.h>
#include <bx/radixsort.h>
#include "config.h"
#include "topology.h"
namespace bgfx
{
template<typename IndexT>
static uint32_t toplogyConvertTriListFlipWinding(void* _dst, uint32_t _dstSize, const IndexT* _indices, uint32_t _numIndices)
{
if (NULL == _dst)
{
return _numIndices;
}
IndexT* dst = (IndexT*)_dst;
IndexT* end = &dst[_dstSize/sizeof(IndexT)];
for (uint32_t ii = 0; ii < _numIndices && dst < end; ii += 3, dst += 3)
{
const IndexT* tri = &_indices[ii];
IndexT i0 = tri[0], i1 = tri[1], i2 = tri[2];
dst[0] = i0;
dst[1] = i2;
dst[2] = i1;
}
return _numIndices;
}
template<typename IndexT, typename SortT>
static uint32_t toplogyConvertTriListToLineList(void* _dst, uint32_t _dstSize, const IndexT* _indices, uint32_t _numIndices, IndexT* _temp, SortT* _tempSort)
{
// Create all line pairs and sort indices.
IndexT* dst = _temp;
for (uint32_t ii = 0; ii < _numIndices; ii += 3)
{
const IndexT* tri = &_indices[ii];
IndexT i0 = tri[0], i1 = tri[1], i2 = tri[2];
if (i0 > i1) { bx::xchg(i0, i1); }
if (i1 > i2) { bx::xchg(i1, i2); }
if (i0 > i1) { bx::xchg(i0, i1); }
BX_CHECK(i0 < i1 < i2, "");
dst[0] = i0; dst[1] = i1;
dst[2] = i1; dst[3] = i2;
dst[4] = i0; dst[5] = i2;
dst += 6;
}
// Sort all line pairs.
SortT* sorted = (SortT*)_temp;
bx::radixSort(sorted, _tempSort, _numIndices);
uint32_t num = 0;
// Remove all line pair duplicates.
if (NULL == _dst)
{
SortT last = sorted[0];
for (uint32_t ii = 1; ii < _numIndices; ++ii)
{
if (last != sorted[ii])
{
num += 2;
last = sorted[ii];
}
}
num += 2;
}
else
{
dst = (IndexT*)_dst;
IndexT* end = &dst[_dstSize/sizeof(IndexT)];
SortT last = sorted[0];
for (uint32_t ii = 1; ii < _numIndices && dst < end; ++ii)
{
if (last != sorted[ii])
{
union Un { SortT key; struct { IndexT i0; IndexT i1; } u16; } un = { last };
dst[0] = un.u16.i0;
dst[1] = un.u16.i1;
dst += 2;
last = sorted[ii];
}
}
if (dst < end)
{
union Un { SortT key; struct { IndexT i0; IndexT i1; } u16; } un = { last };
dst[0] = un.u16.i0;
dst[1] = un.u16.i1;
dst += 2;
}
num = uint32_t(dst - (IndexT*)_dst);
}
return num;
}
template<typename IndexT, typename SortT>
static uint32_t toplogyConvertTriListToLineList(void* _dst, uint32_t _dstSize, const IndexT* _indices, uint32_t _numIndices, bx::AllocatorI* _allocator)
{
IndexT* temp = (IndexT*)BX_ALLOC(_allocator, _numIndices*2*sizeof(IndexT)*2);
SortT* tempSort = (SortT*)&temp[_numIndices*2];
uint32_t num = toplogyConvertTriListToLineList(_dst, _dstSize, _indices, _numIndices, temp, tempSort);
BX_FREE(_allocator, temp);
return num;
}
template<typename IndexT>
static uint32_t toplogyConvertTriStripToTriList(void* _dst, uint32_t _dstSize, const IndexT* _indices, uint32_t _numIndices)
{
IndexT* dst = (IndexT*)_dst;
IndexT* end = &dst[_dstSize/sizeof(IndexT)];
for (uint32_t ii = 0, num = _numIndices-2; ii < num && dst < end; ++ii)
{
IndexT i0 = _indices[ii+0];
IndexT i1 = _indices[ii+1];
IndexT i2 = _indices[ii+2];
if (i0 != i1
&& i1 != i2)
{
dst[0] = i0;
dst[1] = i1;
dst[2] = i2;
dst += 3;
}
}
return uint32_t(dst - (IndexT*)_dst);
}
template<typename IndexT>
static uint32_t toplogyConvertLineStripToLineList(void* _dst, uint32_t _dstSize, const IndexT* _indices, uint32_t _numIndices)
{
IndexT* dst = (IndexT*)_dst;
IndexT* end = &dst[_dstSize/sizeof(IndexT)];
IndexT i0 = _indices[0];
for (uint32_t ii = 1; ii < _numIndices && dst < end; ++ii)
{
IndexT i1 = _indices[ii];
if (i0 != i1)
{
dst[0] = i0;
dst[1] = i1;
dst += 2;
i0 = i1;
}
}
return uint32_t(dst - (IndexT*)_dst);
}
uint32_t toplogyConvert(TopologyConvert::Enum _conversion, void* _dst, uint32_t _dstSize, const void* _indices, uint32_t _numIndices, bool _index32, bx::AllocatorI* _allocator)
{
switch (_conversion)
{
case TopologyConvert::TriStripToTriList:
if (_index32)
{
return toplogyConvertTriStripToTriList(_dst, _dstSize, (const uint32_t*)_indices, _numIndices);
}
return toplogyConvertTriStripToTriList(_dst, _dstSize, (const uint16_t*)_indices, _numIndices);
case TopologyConvert::TriListFlipWinding:
if (_index32)
{
return toplogyConvertTriListFlipWinding(_dst, _dstSize, (const uint32_t*)_indices, _numIndices);
}
return toplogyConvertTriListFlipWinding(_dst, _dstSize, (const uint16_t*)_indices, _numIndices);
case TopologyConvert::TriListToLineList:
if (NULL == _allocator)
{
return 0;
}
if (_index32)
{
return toplogyConvertTriListToLineList<uint32_t, uint64_t>(_dst, _dstSize, (const uint32_t*)_indices, _numIndices, _allocator);
}
return toplogyConvertTriListToLineList<uint16_t, uint32_t>(_dst, _dstSize, (const uint16_t*)_indices, _numIndices, _allocator);
case TopologyConvert::LineStripToLineList:
if (_index32)
{
return toplogyConvertLineStripToLineList(_dst, _dstSize, (const uint32_t*)_indices, _numIndices);
}
return toplogyConvertLineStripToLineList(_dst, _dstSize, (const uint16_t*)_indices, _numIndices);
default:
break;
}
return 0;
}
} //namespace bgfx

43
src/topology.h Normal file
View file

@ -0,0 +1,43 @@
/*
* Copyright 2011-2016 Branimir Karadzic. All rights reserved.
* License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
*/
#ifndef BGFX_TOPOLOGY_H_HEADER_GUARD
#define BGFX_TOPOLOGY_H_HEADER_GUARD
#include <bgfx/bgfx.h>
#include <bx/allocator.h>
namespace bgfx
{
///
struct TopologyConvert
{
enum Enum
{
TriListFlipWinding,
TriListToLineList,
TriStripToTriList,
LineStripToLineList,
Count
};
};
/// Converts topology from triangle list to line list.
///
/// @param[in] _conversion
/// @param[in] _dst
/// @param[in] _dstSize
/// @param[in] _indices
/// @param[in] _numIndices
/// @param[in] _index32
///
/// @returns
///
uint32_t toplogyConvert(TopologyConvert::Enum _conversion, void* _dst, uint32_t _dstSize, const void* _indices, uint32_t _numIndices, bool _index32, bx::AllocatorI* _allocator);
} // namespace bgfx
#endif // BGFX_TOPOLOGY_H_HEADER_GUARD