#include "Mesh.hpp"
#include
#include
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
enum VertexFormat
{
kVertexFormatFloat,
kVertexFormatFloat16,
kVertexFormatUNorm8,
kVertexFormatSNorm8,
kVertexFormatUNorm16,
kVertexFormatSNorm16,
kVertexFormatUInt8,
kVertexFormatSInt8,
kVertexFormatUInt16,
kVertexFormatSInt16,
kVertexFormatUInt32,
kVertexFormatSInt32
};
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 NULL;
}
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 NULL;
}
PyObject *res = PyBytes_FromStringAndSize(nullptr, componentBytesLength);
if (!res)
{
PyBuffer_Release(&vertexDataView);
return NULL;
}
uint8_t *componentBytes = (uint8_t *)PyBytes_AS_STRING(res);
for (uint32_t v = 0; v < m_VertexCount; v++)
{
uint32_t vertexOffset = m_StreamOffset + m_ChannelOffset + m_StreamStride * v;
for (uint32_t d = 0; d < m_ChannelDimension; d++)
{
uint32_t vertexDataOffset = vertexOffset + componentByteSize * d;
uint32_t componentOffset = componentByteSize * (v * m_ChannelDimension + d);
memcpy(componentBytes + componentOffset, vertexData + vertexDataOffset, componentByteSize);
}
}
if (swap) // swap bytes
{
if (componentByteSize == 2)
{
uint16_t *componentUints = (uint16_t *)componentBytes;
for (uint32_t i = 0; i < componentBytesLength; i += 2)
{
swap_any_inplace(componentUints++);
}
}
else if (componentByteSize == 4)
{
uint32_t *componentUints = (uint32_t *)componentBytes;
for (uint32_t i = 0; i < componentBytesLength; i += 4)
{
swap_any_inplace(componentUints++);
}
}
}
PyBuffer_Release(&vertexDataView);
return res;
// fast enough in Python
// uint32_t itemCount = componentBytesLength / componentByteSize;
// PyObject *lst = PyList_New(itemCount);
// if (!lst)
// return NULL;
// switch (format)
// {
// case kVertexFormatFloat:
// {
// float *items = (float *)componentBytes;
// for (uint32_t i = 0; i < itemCount; i++)
// {
// PyList_SetItem(lst, i, PyFloat_FromDouble((double)*items++));
// }
// // result[i] = BitConverter.ToSingle(inputBytes, i * 4);
// break;
// }
// case kVertexFormatFloat16:
// {
// uint16_t *items = (uint16_t *)componentBytes;
// for (uint32_t i = 0; i < itemCount; i++)
// {
// double x = _PyFloat_Unpack2(items++, 0);
// if (x == -1.0 && PyErr_Occurred())
// {
// return NULL;
// }
// PyList_SetItem(lst, i, PyFloat_FromDouble(x));
// }
// // result[i] = Half.ToHalf(inputBytes, i * 2);
// break;
// }
// case kVertexFormatUNorm8:
// {
// uint8_t *items = componentBytes;
// for (uint32_t i = 0; i < itemCount; i++)
// {
// PyList_SetItem(lst, i, PyFloat_FromDouble((double)(*items++ / 255.0f)));
// }
// // result[i] = inputBytes[i] / 255f;
// break;
// }
// case kVertexFormatSNorm8:
// {
// int8_t *items = (int8_t *)componentBytes;
// for (uint32_t i = 0; i < itemCount; i++)
// {
// PyList_SetItem(lst, i, PyFloat_FromDouble((double)MAX((*items++ / 127.0f), -1.0f)));
// }
// // result[i] = Math.Max((sbyte)inputBytes[i] / 127f, -1f);
// break;
// }
// case kVertexFormatUNorm16:
// {
// uint16_t *items = (uint16_t *)componentBytes;
// for (uint32_t i = 0; i < itemCount; i++)
// {
// PyList_SetItem(lst, i, PyFloat_FromDouble((double)(*items++ / 65535.0f)));
// }
// // result[i] = BitConverter.ToUInt16(inputBytes, i * 2) / 65535f;
// break;
// }
// case kVertexFormatSNorm16:
// {
// int16_t *items = (int16_t *)componentBytes;
// for (uint32_t i = 0; i < itemCount; i++)
// {
// PyList_SetItem(lst, i, PyFloat_FromDouble((double)MAX((*items++ / 32767.0f), -1.0f)));
// }
// // result[i] = Math.Max(BitConverter.ToInt16(inputBytes, i * 2) / 32767f, -1f);
// break;
// }
// case kVertexFormatUInt8:
// case kVertexFormatSInt8:
// {
// uint8_t *items = componentBytes;
// for (uint32_t i = 0; i < itemCount; i++)
// {
// PyList_SetItem(lst, i, PyLong_FromUnsignedLong((uint32_t)*items++));
// }
// // result[i] = inputBytes[i];
// break;
// }
// case kVertexFormatUInt16:
// case kVertexFormatSInt16:
// {
// uint16_t *items = (uint16_t *)componentBytes;
// for (uint32_t i = 0; i < itemCount; i++)
// {
// PyList_SetItem(lst, i, PyLong_FromUnsignedLong((uint32_t)*items++));
// }
// // result[i] = BitConverter.ToInt16(inputBytes, i * 2);
// break;
// }
// case kVertexFormatUInt32:
// case kVertexFormatSInt32:
// {
// uint32_t *items = (uint32_t *)componentBytes;
// for (uint32_t i = 0; i < itemCount; i++)
// {
// PyList_SetItem(lst, i, PyLong_FromUnsignedLong(*items++));
// }
// // result[i] = BitConverter.ToInt32(inputBytes, i * 4);
// break;
// }
// }
// free(componentBytes);
// return lst;
}