mirror of
https://github.com/H-uru/korman.git
synced 2025-07-14 02:27:36 -04:00
Flip the flopped images
Export all images right-side up. OpenGL flips them because fail, so we have to do a bit of work to correct that. Thankfully, this operation is not as slow as I thought. NOTE TO SELF: remember, texture page updating would be nice to have...
This commit is contained in:
@ -126,7 +126,19 @@ static PyObject* pyGLTexture_generate_mipmap(pyGLTexture* self) {
|
|||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t* _get_level_data(pyGLTexture* self, GLint level, bool bgra, bool quiet, size_t* size) {
|
struct _LevelData
|
||||||
|
{
|
||||||
|
GLint m_width;
|
||||||
|
GLint m_height;
|
||||||
|
uint8_t* m_data;
|
||||||
|
size_t m_dataSize;
|
||||||
|
|
||||||
|
_LevelData(GLint w, GLint h, uint8_t* ptr, size_t sz)
|
||||||
|
: m_width(w), m_height(h), m_data(ptr), m_dataSize(sz)
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
static _LevelData _get_level_data(pyGLTexture* self, GLint level, bool bgra, bool quiet) {
|
||||||
GLint width, height;
|
GLint width, height;
|
||||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_WIDTH, &width);
|
glGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_WIDTH, &width);
|
||||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_HEIGHT, &height);
|
glGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_HEIGHT, &height);
|
||||||
@ -137,32 +149,46 @@ static uint8_t* _get_level_data(pyGLTexture* self, GLint level, bool bgra, bool
|
|||||||
|
|
||||||
size_t bufsz;
|
size_t bufsz;
|
||||||
bufsz = (width * height * 4);
|
bufsz = (width * height * 4);
|
||||||
if (size) *size = bufsz;
|
|
||||||
uint8_t* buf = new uint8_t[bufsz];
|
uint8_t* buf = new uint8_t[bufsz];
|
||||||
glGetTexImage(GL_TEXTURE_2D, level, fmt, GL_UNSIGNED_BYTE, reinterpret_cast<GLvoid*>(buf));
|
glGetTexImage(GL_TEXTURE_2D, level, fmt, GL_UNSIGNED_BYTE, reinterpret_cast<GLvoid*>(buf));
|
||||||
return buf;
|
return _LevelData(width, height, buf, bufsz);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject* pyGLTexture_get_level_data(pyGLTexture* self, PyObject* args, PyObject* kwargs) {
|
static PyObject* pyGLTexture_get_level_data(pyGLTexture* self, PyObject* args, PyObject* kwargs) {
|
||||||
static char* kwlist[] = { _pycs("level"), _pycs("calc_alpha"), _pycs("bgra"),
|
static char* kwlist[] = { _pycs("level"), _pycs("calc_alpha"), _pycs("bgra"),
|
||||||
_pycs("quiet"), NULL };
|
_pycs("quiet"), _pycs("fast"), NULL };
|
||||||
GLint level = 0;
|
GLint level = 0;
|
||||||
bool calc_alpha = false;
|
bool calc_alpha = false;
|
||||||
bool bgra = false;
|
bool bgra = false;
|
||||||
bool quiet = false;
|
bool quiet = false;
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ibbb", kwlist, &level, &calc_alpha, &bgra, &quiet)) {
|
bool fast = false;
|
||||||
PyErr_SetString(PyExc_TypeError, "get_level_data expects an optional int, bool, bool, bool");
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ibbbb", kwlist, &level, &calc_alpha, &bgra, &quiet, &fast)) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "get_level_data expects an optional int, bool, bool, bool, bool");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t bufsz;
|
_LevelData data = _get_level_data(self, level, bgra, quiet);
|
||||||
uint8_t* buf = _get_level_data(self, level, bgra, quiet, &bufsz);
|
if (fast)
|
||||||
|
return pyBuffer_Steal(data.m_data, data.m_dataSize);
|
||||||
|
|
||||||
|
// OpenGL returns a flipped image, so we must reflip it.
|
||||||
|
size_t row_stride = data.m_width * 4;
|
||||||
|
uint8_t* sptr = data.m_data;
|
||||||
|
uint8_t* eptr = data.m_data + (data.m_dataSize - row_stride);
|
||||||
|
uint8_t* temp = new uint8_t[row_stride];
|
||||||
|
do {
|
||||||
|
memcpy(temp, sptr, row_stride);
|
||||||
|
memcpy(sptr, eptr, row_stride);
|
||||||
|
memcpy(eptr, temp, row_stride);
|
||||||
|
} while ((sptr += row_stride) < (eptr -= row_stride));
|
||||||
|
delete[] temp;
|
||||||
|
|
||||||
if (calc_alpha) {
|
if (calc_alpha) {
|
||||||
for (size_t i = 0; i < bufsz; i += 4)
|
for (size_t i = 0; i < data.m_dataSize; i += 4)
|
||||||
buf[i + 3] = (buf[i + 0] + buf[i + 1] + buf[i + 2]) / 3;
|
data.m_data[i + 3] = (data.m_data[i + 0] + data.m_data[i + 1] + data.m_data[i + 2]) / 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pyBuffer_Steal(buf, bufsz);
|
return pyBuffer_Steal(data.m_data, data.m_dataSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject* pyGLTexture_store_in_mipmap(pyGLTexture* self, PyObject* args) {
|
static PyObject* pyGLTexture_store_in_mipmap(pyGLTexture* self, PyObject* args) {
|
||||||
@ -208,15 +234,14 @@ static PyMethodDef pyGLTexture_Methods[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static PyObject* pyGLTexture_get_has_alpha(pyGLTexture* self, void*) {
|
static PyObject* pyGLTexture_get_has_alpha(pyGLTexture* self, void*) {
|
||||||
size_t bufsz;
|
_LevelData data = _get_level_data(self, 0, false, true);
|
||||||
uint8_t* buf = _get_level_data(self, 0, false, true, &bufsz);
|
for (size_t i = 3; i < data.m_dataSize; i += 4) {
|
||||||
for (size_t i = 3; i < bufsz; i += 4) {
|
if (data.m_data[i] != 255) {
|
||||||
if (buf[i] != 255) {
|
delete[] data.m_data;
|
||||||
delete[] buf;
|
|
||||||
return PyBool_FromLong(1);
|
return PyBool_FromLong(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete[] buf;
|
delete[] data.m_data;
|
||||||
return PyBool_FromLong(0);
|
return PyBool_FromLong(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,7 +224,7 @@ class MeshConverter:
|
|||||||
geoVertex.position = hsVector3(*source.co)
|
geoVertex.position = hsVector3(*source.co)
|
||||||
geoVertex.normal = hsVector3(*source.normal)
|
geoVertex.normal = hsVector3(*source.normal)
|
||||||
geoVertex.color = hsColor32(*vertex_color)
|
geoVertex.color = hsColor32(*vertex_color)
|
||||||
geoVertex.uvs = [hsVector3(uv[0], uv[1], 0.0) for uv in uvws]
|
geoVertex.uvs = [hsVector3(uv[0], 1.0 - uv[1], 0.0) for uv in uvws]
|
||||||
data.blender2gs[vertex][coluv] = len(data.vertices)
|
data.blender2gs[vertex][coluv] = len(data.vertices)
|
||||||
data.vertices.append(geoVertex)
|
data.vertices.append(geoVertex)
|
||||||
face_verts.append(data.blender2gs[vertex][coluv])
|
face_verts.append(data.blender2gs[vertex][coluv])
|
||||||
|
@ -58,7 +58,7 @@ class GLTexture:
|
|||||||
# It will simplify our state tracking a bit.
|
# It will simplify our state tracking a bit.
|
||||||
bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_GENERATE_MIPMAP, 1)
|
bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_GENERATE_MIPMAP, 1)
|
||||||
|
|
||||||
def get_level_data(self, level=0, calc_alpha=False, bgra=False, quiet=False):
|
def get_level_data(self, level=0, calc_alpha=False, bgra=False, quiet=False, fast=False):
|
||||||
"""Gets the uncompressed pixel data for a requested mip level, optionally calculating the alpha
|
"""Gets the uncompressed pixel data for a requested mip level, optionally calculating the alpha
|
||||||
channel from the image color data
|
channel from the image color data
|
||||||
"""
|
"""
|
||||||
@ -72,15 +72,21 @@ class GLTexture:
|
|||||||
buf = bgl.Buffer(bgl.GL_BYTE, size)
|
buf = bgl.Buffer(bgl.GL_BYTE, size)
|
||||||
fmt = bgl.GL_BGRA if bgra else bgl.GL_RGBA
|
fmt = bgl.GL_BGRA if bgra else bgl.GL_RGBA
|
||||||
bgl.glGetTexImage(bgl.GL_TEXTURE_2D, level, fmt, bgl.GL_UNSIGNED_BYTE, buf);
|
bgl.glGetTexImage(bgl.GL_TEXTURE_2D, level, fmt, bgl.GL_UNSIGNED_BYTE, buf);
|
||||||
|
if fast:
|
||||||
|
return bytes(buf)
|
||||||
|
|
||||||
# Calculate le alphas
|
# OpenGL returns the images upside down, so we're going to rotate it in memory.
|
||||||
# NOTE: the variable names are correct for GL_RGBA. We'll still get the right values for
|
finalBuf = bytearray(size)
|
||||||
# BGRA, obviously, but red will suddenly be... blue. Yeah.
|
row_stride = width * 4
|
||||||
|
for i in range(height):
|
||||||
|
src, dst = i * row_stride, (height - (i+1)) * row_stride
|
||||||
|
finalBuf[dst:dst+row_stride] = buf[src:src+row_stride]
|
||||||
|
|
||||||
|
# Do we need to calculate the alpha component?
|
||||||
if calc_alpha:
|
if calc_alpha:
|
||||||
for i in range(0, size, 4):
|
for i in range(0, size, 4):
|
||||||
r, g, b = buf[i:i+3]
|
finalBuf[i+3] = int(sum(finalBuf[i:i+3]) / 3)
|
||||||
buf[i+3] = int((r + g + b) / 3)
|
return bytes(finalBuf)
|
||||||
return bytes(buf)
|
|
||||||
|
|
||||||
def _get_integer(self, arg):
|
def _get_integer(self, arg):
|
||||||
buf = bgl.Buffer(bgl.GL_INT, 1)
|
buf = bgl.Buffer(bgl.GL_INT, 1)
|
||||||
@ -97,7 +103,7 @@ class GLTexture:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def has_alpha(self):
|
def has_alpha(self):
|
||||||
data = self.get_level_data(quiet=True)
|
data = self.get_level_data(quiet=True, fast=True)
|
||||||
for i in range(3, len(data), 4):
|
for i in range(3, len(data), 4):
|
||||||
if data[i] != 255:
|
if data[i] != 255:
|
||||||
return True
|
return True
|
||||||
|
Reference in New Issue
Block a user