See More

#include "Mesh.hpp" #include #include #include #define MAX(x, y) (((x) > (y)) ? (x) : (y)) enum VertexFormat { kVertexFormatFloat, kVertexFormatFloat16, kVertexFormatUNorm8, kVertexFormatSNorm8, kVertexFormatUNorm16, kVertexFormatSNorm16, kVertexFormatUInt8, kVertexFormatSInt8, kVertexFormatUInt16, kVertexFormatSInt16, kVertexFormatUInt32, kVertexFormatSInt32 }; template void unpack_vertexdata_template(uint8_t *componentBytes, uint8_t *vertexData, uint32_t m_VertexCount, uint32_t m_StreamOffset, uint32_t m_StreamStride, uint32_t m_ChannelOffset, uint32_t m_ChannelDimension) { const auto channelSize = componentByteSize * m_ChannelDimension; uint8_t *componentCur = componentBytes; uint8_t *vertexCur = vertexData; // move vertexCur to the first vertex vertexCur += m_StreamOffset + m_ChannelOffset; for (uint32_t v = 0; v < m_VertexCount; v++) { memcpy(componentCur, vertexCur, channelSize); componentCur += channelSize; vertexCur += m_StreamStride; } } template void swap_vertexdata(uint8_t *componentBytes, uint32_t m_VertexCount, uint32_t m_ChannelDimension) { if constexpr (componentByteSize == 1) { // do nothing } else if constexpr (componentByteSize == 2) { uint16_t *componentUints = (uint16_t *)componentBytes; for (uint32_t i = 0; i < m_VertexCount * m_ChannelDimension; i++) { swap_any_inplace(componentUints++); } } else if constexpr (componentByteSize == 4) { uint32_t *componentUints = (uint32_t *)componentBytes; for (uint32_t i = 0; i < m_VertexCount * m_ChannelDimension; i++) { swap_any_inplace(componentUints++); } } else if constexpr (componentByteSize == 8) { uint64_t *componentUints = (uint64_t *)componentBytes; for (uint32_t i = 0; i < m_VertexCount * m_ChannelDimension; i++) { swap_any_inplace(componentUints++); } } else { const auto compoentByteSizeStr = std::to_string(componentByteSize); const auto error_message = "Swap not implemented for this size: " + compoentByteSizeStr; PyErr_SetString(PyExc_ValueError, error_message.c_str()); } } PyObject *unpack_vertexdata(PyObject *self, PyObject *args) { // define vars int componentByteSize; uint32_t m_VertexCount; uint8_t swap; // char format; Py_buffer vertexDataView; uint32_t m_StreamOffset; uint32_t m_StreamStride; uint32_t m_ChannelOffset; uint32_t m_ChannelDimension; if (!PyArg_ParseTuple(args, "y*iIIIIIb", &vertexDataView, &componentByteSize, &m_VertexCount, &m_StreamOffset, &m_StreamStride, &m_ChannelOffset, &m_ChannelDimension, &swap)) { if (vertexDataView.buf) { PyBuffer_Release(&vertexDataView); } return nullptr; } uint8_t *vertexData = (uint8_t *)vertexDataView.buf; Py_ssize_t componentBytesLength = m_VertexCount * m_ChannelDimension * componentByteSize; // check if max values are ok uint32_t maxVertexDataAccess = (m_VertexCount - 1) * m_StreamStride + m_ChannelOffset + m_StreamOffset + componentByteSize * (m_ChannelDimension - 1) + componentByteSize; if (maxVertexDataAccess > vertexDataView.len) { PyBuffer_Release(&vertexDataView); PyErr_SetString(PyExc_ValueError, "Vertex data access out of bounds"); return nullptr; } PyObject *res = PyBytes_FromStringAndSize(nullptr, componentBytesLength); if (!res) { PyBuffer_Release(&vertexDataView); return nullptr; } uint8_t *componentBytes = (uint8_t *)PyBytes_AS_STRING(res); switch (componentByteSize) { case 1: unpack_vertexdata_template<1>(componentBytes, vertexData, m_VertexCount, m_StreamOffset, m_StreamStride, m_ChannelOffset, m_ChannelDimension); break; case 2: unpack_vertexdata_template<2>(componentBytes, vertexData, m_VertexCount, m_StreamOffset, m_StreamStride, m_ChannelOffset, m_ChannelDimension); if (swap) { swap_vertexdata<2>(componentBytes, m_VertexCount, m_ChannelDimension); } break; case 4: unpack_vertexdata_template<4>(componentBytes, vertexData, m_VertexCount, m_StreamOffset, m_StreamStride, m_ChannelOffset, m_ChannelDimension); if (swap) { swap_vertexdata<4>(componentBytes, m_VertexCount, m_ChannelDimension); } break; case 8: unpack_vertexdata_template<8>(componentBytes, vertexData, m_VertexCount, m_StreamOffset, m_StreamStride, m_ChannelOffset, m_ChannelDimension); if (swap) { swap_vertexdata<8>(componentBytes, m_VertexCount, m_ChannelDimension); } break; default: PyBuffer_Release(&vertexDataView); PyErr_SetString(PyExc_ValueError, "Unsupported component byte size"); return nullptr; } PyBuffer_Release(&vertexDataView); return res; }