See More

#include "AnimationClip.hpp" #include #define MIN(x, y) (((x) < (y)) ? (x) : (y)) /* AnimationClip.py */ static float *UnpackFloats(uint32_t m_NumItems, float m_Range, float m_Start, uint8_t *m_Data, char m_BitSize, int itemCountInChunk, int chunkStride, int start, int numChunks) { int bitPos = m_BitSize * start; int indexPos = bitPos / 8; bitPos %= 8; float scale = 1.0f / m_Range; if (numChunks == -1) numChunks = (int)m_NumItems / itemCountInChunk; // TODO: might be better to use ulong instead of uint uint32_t end = chunkStride * numChunks / 4; // TODO: check if this is correct float *data = (float *)malloc(sizeof(float) * numChunks * itemCountInChunk); float *dataStart = data; for (uint32_t index = 0; index != end; index += chunkStride / 4) { for (int i = 0; i < itemCountInChunk; ++i) { uint32_t x = 0; int bits = 0; while (bits < m_BitSize) { x |= (uint32_t)((m_Data[indexPos] >> bitPos) << bits); int num = MIN(m_BitSize - bits, 8 - bitPos); bitPos += num; bits += num; if (bitPos == 8) { indexPos++; bitPos = 0; } } x &= (uint32_t)(1 << m_BitSize) - 1u; *data++ = (x / (scale * ((1 << m_BitSize) - 1)) + m_Start); } } return dataStart; } // TODO: check if bitPos, bits, and num can be reduced to chars static int *UnpackInts(uint32_t m_NumItems, uint8_t *m_Data, char m_BitSize) { int *data = (int *)malloc(m_NumItems * sizeof(int)); int indexPos = 0; int bitPos = 0; for (uint32_t i = 0; i < m_NumItems; i++) { int bits = 0; data[i] = 0; while (bits < m_BitSize) { data[i] |= (m_Data[indexPos] >> bitPos) << bits; int num = MIN(m_BitSize - bits, 8 - bitPos); bitPos += num; bits += num; if (bitPos == 8) { indexPos++; bitPos = 0; } } data[i] &= (1 << m_BitSize) - 1; } return data; } // TODO: implement unpack quaternions PyObject *unpack_floats(PyObject *self, PyObject *args) { // define vars uint32_t m_NumItems; float m_Range; float m_Start; uint8_t *m_Data; char m_BitSize; int itemCountInChunk; int chunkStride; int start; int numChunks; Py_ssize_t data_size; start = 0; numChunks = -1; if (!PyArg_ParseTuple(args, "Iffy#bii|ii", &m_NumItems, &m_Range, &m_Start, &m_Data, &data_size, &m_BitSize, &itemCountInChunk, &chunkStride, &start, &numChunks)) return NULL; // decode float *array = UnpackFloats(m_NumItems, m_Range, m_Start, m_Data, m_BitSize, itemCountInChunk, chunkStride, start, numChunks); if (numChunks == -1) numChunks = (int)m_NumItems / itemCountInChunk; Py_ssize_t array_len = numChunks * itemCountInChunk; // return PyObject *lst = PyList_New(array_len); if (!lst) return NULL; for (Py_ssize_t i = 0; i < array_len; i++) { PyObject *num = PyFloat_FromDouble(array[i]); if (!num) { Py_DECREF(lst); return NULL; } PyList_SET_ITEM(lst, i, num); // reference to num stolen } free(array); return lst; } PyObject *unpack_ints(PyObject *self, PyObject *args) { // define vars uint32_t m_NumItems; uint8_t *m_Data; char m_BitSize; Py_ssize_t data_size; if (!PyArg_ParseTuple(args, "Iy#b", &m_NumItems, &m_Data, &data_size, &m_BitSize)) return NULL; // decode int *array = UnpackInts(m_NumItems, m_Data, m_BitSize); // return PyObject *lst = PyList_New(m_NumItems); if (!lst) return NULL; for (uint32_t i = 0; i < m_NumItems; i++) { PyObject *num = PyLong_FromLong(array[i]); if (!num) { Py_DECREF(lst); return NULL; } PyList_SET_ITEM(lst, i, num); // reference to num stolen } free(array); return lst; }