BGE VideoTexture: add depth buffer access to ImageViewport and ImageRender.
2 new attributes to ImageViewport and ImageRender object: depth: set to True to retrieve the depth buffer as an array of float (not suitable for texture source). zbuff: set to True to retrieve the depth buffer as a grey scale pixel array (suitable for texture source). A new mode 'F' is added to VideoTexture.imageToArray() to allow returning the image buffer as a one dimensional array of float. This mode should only be used to retrieve the depth buffer of ImageViewport and ImageRender objects. Example: viewport = VideoTexture.ImageViewport() viewport.depth = True depth = VideoTexture.imageToArray(viewport,'F') # show depth of bottom left pixel # 1.0 = infinite, 0.0 = on near clip plane. print(depth[0])
This commit is contained in:
@@ -351,6 +351,15 @@ When the texture object is deleted, the new texture is deleted and the old textu
|
|||||||
|
|
||||||
use whole viewport to render
|
use whole viewport to render
|
||||||
|
|
||||||
|
.. attribute:: depth
|
||||||
|
|
||||||
|
use depth component of render as array of float - not suitable for texture source,
|
||||||
|
should only be used with bge.texture.imageToArray(mode='F')
|
||||||
|
|
||||||
|
.. attribute:: zbuff
|
||||||
|
|
||||||
|
use depth component of render as grey scale color - suitable for texture source
|
||||||
|
|
||||||
.. class:: ImageViewport()
|
.. class:: ImageViewport()
|
||||||
|
|
||||||
Image source from viewport
|
Image source from viewport
|
||||||
@@ -399,6 +408,15 @@ When the texture object is deleted, the new texture is deleted and the old textu
|
|||||||
|
|
||||||
use whole viewport to capture
|
use whole viewport to capture
|
||||||
|
|
||||||
|
.. attribute:: depth
|
||||||
|
|
||||||
|
use depth component of viewport as array of float - not suitable for texture source,
|
||||||
|
should only be used with bge.texture.imageToArray(mode='F')
|
||||||
|
|
||||||
|
.. attribute:: zbuff
|
||||||
|
|
||||||
|
use depth component of viewport as grey scale color - suitable for texture source
|
||||||
|
|
||||||
.. class:: Texture(gameObj)
|
.. class:: Texture(gameObj)
|
||||||
|
|
||||||
Texture objects
|
Texture objects
|
||||||
@@ -518,13 +536,16 @@ When the texture object is deleted, the new texture is deleted and the old textu
|
|||||||
0 to force a fixed 0 color channel and 1 to force a fixed 255 color channel.
|
0 to force a fixed 0 color channel and 1 to force a fixed 255 color channel.
|
||||||
Example: "BGR" will return 3 bytes per pixel with the Blue, Green and Red channels in that order.
|
Example: "BGR" will return 3 bytes per pixel with the Blue, Green and Red channels in that order.
|
||||||
"RGB1" will return 4 bytes per pixel with the Red, Green, Blue channels in that order and the alpha channel forced to 255.
|
"RGB1" will return 4 bytes per pixel with the Red, Green, Blue channels in that order and the alpha channel forced to 255.
|
||||||
|
A special mode "F" allows to return the image as an array of float. This mode should only be used to retrieve
|
||||||
|
the depth buffer of the ImageViewport and ImageRender object.
|
||||||
The default mode is "RGBA".
|
The default mode is "RGBA".
|
||||||
|
|
||||||
|
|
||||||
:type mode: string
|
:type mode: string
|
||||||
:rtype: :class:`~bgl.buffer`
|
:rtype: :class:`~bgl.buffer`
|
||||||
:return: A object representing the image as one dimensional array of bytes of size (pixel_size*width*height),
|
:return: A object representing the image as one dimensional array of bytes of size (pixel_size*width*height),
|
||||||
line by line starting from the bottom of the image. The pixel size and format is determined by the mode
|
line by line starting from the bottom of the image. The pixel size and format is determined by the mode
|
||||||
parameter.
|
parameter. For mode 'F', the array is a one dimensional array of float of size (width*height).
|
||||||
|
|
||||||
.. function:: materialID(object,name)
|
.. function:: materialID(object,name)
|
||||||
|
|
||||||
|
@@ -95,6 +95,10 @@ protected:
|
|||||||
virtual unsigned int filter (unsigned int * src, short x, short y,
|
virtual unsigned int filter (unsigned int * src, short x, short y,
|
||||||
short * size, unsigned int pixSize, unsigned int val = 0)
|
short * size, unsigned int pixSize, unsigned int val = 0)
|
||||||
{ return val; }
|
{ return val; }
|
||||||
|
/// filter pixel, source float buffer
|
||||||
|
virtual unsigned int filter (float * src, short x, short y,
|
||||||
|
short * size, unsigned int pixSize, unsigned int val = 0)
|
||||||
|
{ return val; }
|
||||||
|
|
||||||
/// get source pixel size
|
/// get source pixel size
|
||||||
virtual unsigned int getPixelSize (void) { return 1; }
|
virtual unsigned int getPixelSize (void) { return 1; }
|
||||||
|
@@ -31,7 +31,6 @@ http://www.gnu.org/copyleft/lesser.txt.
|
|||||||
|
|
||||||
#include "FilterBase.h"
|
#include "FilterBase.h"
|
||||||
|
|
||||||
|
|
||||||
/// class for RGB24 conversion
|
/// class for RGB24 conversion
|
||||||
class FilterRGB24 : public FilterBase
|
class FilterRGB24 : public FilterBase
|
||||||
{
|
{
|
||||||
@@ -97,6 +96,65 @@ protected:
|
|||||||
{ VT_RGBA(val,src[2],src[1],src[0],0xFF); return val; }
|
{ VT_RGBA(val,src[2],src[1],src[0],0xFF); return val; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// class for Z_buffer conversion
|
||||||
|
class FilterZZZA : public FilterBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// constructor
|
||||||
|
FilterZZZA (void) {}
|
||||||
|
/// destructor
|
||||||
|
virtual ~FilterZZZA (void) {}
|
||||||
|
|
||||||
|
/// get source pixel size
|
||||||
|
virtual unsigned int getPixelSize (void) { return 1; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// filter pixel, source float buffer
|
||||||
|
virtual unsigned int filter (float * src, short x, short y,
|
||||||
|
short * size, unsigned int pixSize, unsigned int val)
|
||||||
|
{
|
||||||
|
// calculate gray value
|
||||||
|
// convert float to unsigned char
|
||||||
|
unsigned int depth = int(src[0] * 255);
|
||||||
|
// return depth scale value
|
||||||
|
VT_R(val) = depth;
|
||||||
|
VT_G(val) = depth;
|
||||||
|
VT_B(val) = depth;
|
||||||
|
VT_A(val) = 0xFF;
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/// class for Z_buffer conversion
|
||||||
|
class FilterDEPTH : public FilterBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// constructor
|
||||||
|
FilterDEPTH (void) {}
|
||||||
|
/// destructor
|
||||||
|
virtual ~FilterDEPTH (void) {}
|
||||||
|
|
||||||
|
/// get source pixel size
|
||||||
|
virtual unsigned int getPixelSize (void) { return 1; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// filter pixel, source float buffer
|
||||||
|
virtual unsigned int filter (float * src, short x, short y,
|
||||||
|
short * size, unsigned int pixSize, unsigned int val)
|
||||||
|
{
|
||||||
|
// Copy the float value straight away
|
||||||
|
// The user can retrieve the original float value by using
|
||||||
|
// 'F' mode in BGL buffer
|
||||||
|
memcpy(&val, src, sizeof (unsigned int));
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// class for YV12 conversion
|
/// class for YV12 conversion
|
||||||
class FilterYV12 : public FilterBase
|
class FilterYV12 : public FilterBase
|
||||||
{
|
{
|
||||||
|
@@ -49,6 +49,8 @@ extern "C" {
|
|||||||
// constructor
|
// constructor
|
||||||
ImageBase::ImageBase (bool staticSrc) : m_image(NULL), m_imgSize(0),
|
ImageBase::ImageBase (bool staticSrc) : m_image(NULL), m_imgSize(0),
|
||||||
m_avail(false), m_scale(false), m_scaleChange(false), m_flip(false),
|
m_avail(false), m_scale(false), m_scaleChange(false), m_flip(false),
|
||||||
|
m_zbuff(false),
|
||||||
|
m_depth(false),
|
||||||
m_staticSources(staticSrc), m_pyfilter(NULL)
|
m_staticSources(staticSrc), m_pyfilter(NULL)
|
||||||
{
|
{
|
||||||
m_size[0] = m_size[1] = 0;
|
m_size[0] = m_size[1] = 0;
|
||||||
@@ -402,6 +404,18 @@ PyObject *Image_getImage (PyImage *self, char * mode)
|
|||||||
{
|
{
|
||||||
buffer = BGL_MakeBuffer( GL_BYTE, 1, &dimensions, image);
|
buffer = BGL_MakeBuffer( GL_BYTE, 1, &dimensions, image);
|
||||||
}
|
}
|
||||||
|
else if (!strcasecmp(mode, "F"))
|
||||||
|
{
|
||||||
|
// this mode returns the image as an array of float.
|
||||||
|
// This makes sense ONLY for the depth buffer:
|
||||||
|
// source = VideoTexture.ImageViewport()
|
||||||
|
// source.depth = True
|
||||||
|
// depth = VideoTexture.imageToArray(source, 'F')
|
||||||
|
|
||||||
|
// adapt dimension from byte to float
|
||||||
|
dimensions /= sizeof(float);
|
||||||
|
buffer = BGL_MakeBuffer( GL_FLOAT, 1, &dimensions, image);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int i, c, ncolor, pixels;
|
int i, c, ncolor, pixels;
|
||||||
@@ -532,6 +546,52 @@ int Image_setFlip (PyImage *self, PyObject *value, void *closure)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get zbuff
|
||||||
|
PyObject * Image_getZbuff (PyImage * self, void * closure)
|
||||||
|
{
|
||||||
|
if (self->m_image != NULL && self->m_image->getZbuff()) Py_RETURN_TRUE;
|
||||||
|
else Py_RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set zbuff
|
||||||
|
int Image_setZbuff (PyImage * self, PyObject * value, void * closure)
|
||||||
|
{
|
||||||
|
// check parameter, report failure
|
||||||
|
if (value == NULL || !PyBool_Check(value))
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_TypeError, "The value must be a bool");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// set scale
|
||||||
|
if (self->m_image != NULL) self->m_image->setZbuff(value == Py_True);
|
||||||
|
// success
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get depth
|
||||||
|
PyObject * Image_getDepth (PyImage * self, void * closure)
|
||||||
|
{
|
||||||
|
if (self->m_image != NULL && self->m_image->getDepth()) Py_RETURN_TRUE;
|
||||||
|
else Py_RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set depth
|
||||||
|
int Image_setDepth (PyImage * self, PyObject * value, void * closure)
|
||||||
|
{
|
||||||
|
// check parameter, report failure
|
||||||
|
if (value == NULL || !PyBool_Check(value))
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_TypeError, "The value must be a bool");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// set scale
|
||||||
|
if (self->m_image != NULL) self->m_image->setDepth(value == Py_True);
|
||||||
|
// success
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// get filter source object
|
// get filter source object
|
||||||
PyObject *Image_getSource (PyImage *self, PyObject *args)
|
PyObject *Image_getSource (PyImage *self, PyObject *args)
|
||||||
|
@@ -78,6 +78,14 @@ public:
|
|||||||
bool getFlip (void) { return m_flip; }
|
bool getFlip (void) { return m_flip; }
|
||||||
/// set vertical flip
|
/// set vertical flip
|
||||||
void setFlip (bool flip) { m_flip = flip; }
|
void setFlip (bool flip) { m_flip = flip; }
|
||||||
|
/// get Z buffer
|
||||||
|
bool getZbuff (void) { return m_zbuff; }
|
||||||
|
/// set Z buffer
|
||||||
|
void setZbuff (bool zbuff) { m_zbuff = zbuff; }
|
||||||
|
/// get depth
|
||||||
|
bool getDepth (void) { return m_depth; }
|
||||||
|
/// set depth
|
||||||
|
void setDepth (bool depth) { m_depth = depth; }
|
||||||
|
|
||||||
/// get source object
|
/// get source object
|
||||||
PyImage * getSource (const char * id);
|
PyImage * getSource (const char * id);
|
||||||
@@ -111,6 +119,10 @@ protected:
|
|||||||
bool m_scaleChange;
|
bool m_scaleChange;
|
||||||
/// flip image vertically
|
/// flip image vertically
|
||||||
bool m_flip;
|
bool m_flip;
|
||||||
|
/// use the Z buffer as a texture
|
||||||
|
bool m_zbuff;
|
||||||
|
/// extract the Z buffer with unisgned int precision
|
||||||
|
bool m_depth;
|
||||||
|
|
||||||
/// source image list
|
/// source image list
|
||||||
ImageSourceList m_sources;
|
ImageSourceList m_sources;
|
||||||
@@ -347,7 +359,15 @@ int Image_setFlip (PyImage *self, PyObject *value, void *closure);
|
|||||||
PyObject *Image_getSource (PyImage *self, PyObject *args);
|
PyObject *Image_getSource (PyImage *self, PyObject *args);
|
||||||
// set filter source object
|
// set filter source object
|
||||||
PyObject *Image_setSource (PyImage *self, PyObject *args);
|
PyObject *Image_setSource (PyImage *self, PyObject *args);
|
||||||
|
// get Z buffer
|
||||||
|
PyObject * Image_getZbuff (PyImage * self, void * closure);
|
||||||
|
// set Z buffer
|
||||||
|
int Image_setZbuff (PyImage * self, PyObject * value, void * closure);
|
||||||
|
// get depth
|
||||||
|
PyObject * Image_getDepth (PyImage * self, void * closure);
|
||||||
|
// set depth
|
||||||
|
int Image_setDepth (PyImage * self, PyObject * value, void * closure);
|
||||||
|
|
||||||
// get pixel filter object
|
// get pixel filter object
|
||||||
PyObject *Image_getFilter (PyImage *self, void *closure);
|
PyObject *Image_getFilter (PyImage *self, void *closure);
|
||||||
// set pixel filter object
|
// set pixel filter object
|
||||||
|
@@ -385,6 +385,8 @@ static PyGetSetDef imageRenderGetSets[] =
|
|||||||
{(char*)"size", (getter)Image_getSize, NULL, (char*)"image size", NULL},
|
{(char*)"size", (getter)Image_getSize, NULL, (char*)"image size", NULL},
|
||||||
{(char*)"scale", (getter)Image_getScale, (setter)Image_setScale, (char*)"fast scale of image (near neighbor)", NULL},
|
{(char*)"scale", (getter)Image_getScale, (setter)Image_setScale, (char*)"fast scale of image (near neighbor)", NULL},
|
||||||
{(char*)"flip", (getter)Image_getFlip, (setter)Image_setFlip, (char*)"flip image vertically", NULL},
|
{(char*)"flip", (getter)Image_getFlip, (setter)Image_setFlip, (char*)"flip image vertically", NULL},
|
||||||
|
{(char*)"zbuff", (getter)Image_getZbuff, (setter)Image_setZbuff, (char*)"use depth buffer as texture", NULL},
|
||||||
|
{(char*)"depth", (getter)Image_getDepth, (setter)Image_setDepth, (char*)"get depth information from z-buffer using unsigned int precision", NULL},
|
||||||
{(char*)"filter", (getter)Image_getFilter, (setter)Image_setFilter, (char*)"pixel filter", NULL},
|
{(char*)"filter", (getter)Image_getFilter, (setter)Image_setFilter, (char*)"pixel filter", NULL},
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
@@ -547,6 +549,8 @@ static PyGetSetDef imageMirrorGetSets[] =
|
|||||||
{(char*)"size", (getter)Image_getSize, NULL, (char*)"image size", NULL},
|
{(char*)"size", (getter)Image_getSize, NULL, (char*)"image size", NULL},
|
||||||
{(char*)"scale", (getter)Image_getScale, (setter)Image_setScale, (char*)"fast scale of image (near neighbor)", NULL},
|
{(char*)"scale", (getter)Image_getScale, (setter)Image_setScale, (char*)"fast scale of image (near neighbor)", NULL},
|
||||||
{(char*)"flip", (getter)Image_getFlip, (setter)Image_setFlip, (char*)"flip image vertically", NULL},
|
{(char*)"flip", (getter)Image_getFlip, (setter)Image_setFlip, (char*)"flip image vertically", NULL},
|
||||||
|
{(char*)"zbuff", (getter)Image_getZbuff, (setter)Image_setZbuff, (char*)"use depth buffer as texture", NULL},
|
||||||
|
{(char*)"depth", (getter)Image_getDepth, (setter)Image_setDepth, (char*)"get depth information from z-buffer using unsigned int precision", NULL},
|
||||||
{(char*)"filter", (getter)Image_getFilter, (setter)Image_setFilter, (char*)"pixel filter", NULL},
|
{(char*)"filter", (getter)Image_getFilter, (setter)Image_setFilter, (char*)"pixel filter", NULL},
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
@@ -50,6 +50,8 @@ ImageViewport::ImageViewport (void) : m_alpha(false), m_texInit(false)
|
|||||||
|
|
||||||
//glGetIntegerv(GL_VIEWPORT, m_viewport);
|
//glGetIntegerv(GL_VIEWPORT, m_viewport);
|
||||||
// create buffer for viewport image
|
// create buffer for viewport image
|
||||||
|
// Warning: this buffer is also used to get the depth buffer as an array of
|
||||||
|
// float (1 float = 4 bytes per pixel)
|
||||||
m_viewportImage = new BYTE [4 * getViewportSize()[0] * getViewportSize()[1]];
|
m_viewportImage = new BYTE [4 * getViewportSize()[0] * getViewportSize()[1]];
|
||||||
// set attributes
|
// set attributes
|
||||||
setWhole(false);
|
setWhole(false);
|
||||||
@@ -57,7 +59,9 @@ ImageViewport::ImageViewport (void) : m_alpha(false), m_texInit(false)
|
|||||||
|
|
||||||
// destructor
|
// destructor
|
||||||
ImageViewport::~ImageViewport (void)
|
ImageViewport::~ImageViewport (void)
|
||||||
{ delete [] m_viewportImage; }
|
{
|
||||||
|
delete [] m_viewportImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// use whole viewport to capture image
|
// use whole viewport to capture image
|
||||||
@@ -131,7 +135,7 @@ void ImageViewport::calcImage (unsigned int texId, double ts)
|
|||||||
}
|
}
|
||||||
// if texture can be directly created
|
// if texture can be directly created
|
||||||
if (texId != 0 && m_pyfilter == NULL && m_capSize[0] == calcSize(m_capSize[0])
|
if (texId != 0 && m_pyfilter == NULL && m_capSize[0] == calcSize(m_capSize[0])
|
||||||
&& m_capSize[1] == calcSize(m_capSize[1]) && !m_flip)
|
&& m_capSize[1] == calcSize(m_capSize[1]) && !m_flip && !m_zbuff && !m_depth)
|
||||||
{
|
{
|
||||||
// just copy current viewport to texture
|
// just copy current viewport to texture
|
||||||
glBindTexture(GL_TEXTURE_2D, texId);
|
glBindTexture(GL_TEXTURE_2D, texId);
|
||||||
@@ -142,6 +146,32 @@ void ImageViewport::calcImage (unsigned int texId, double ts)
|
|||||||
// otherwise copy viewport to buffer, if image is not available
|
// otherwise copy viewport to buffer, if image is not available
|
||||||
else if (!m_avail)
|
else if (!m_avail)
|
||||||
{
|
{
|
||||||
|
if (m_zbuff)
|
||||||
|
{
|
||||||
|
// Use read pixels with the depth buffer
|
||||||
|
// *** misusing m_viewportImage here, but since it has the correct size
|
||||||
|
// (4 bytes per pixel = size of float) and we just need it to apply
|
||||||
|
// the filter, it's ok
|
||||||
|
glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1],
|
||||||
|
GL_DEPTH_COMPONENT, GL_FLOAT, m_viewportImage);
|
||||||
|
// filter loaded data
|
||||||
|
FilterZZZA filt;
|
||||||
|
filterImage(filt, (float *)m_viewportImage, m_capSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
|
||||||
|
if (m_depth)
|
||||||
|
{
|
||||||
|
// Use read pixels with the depth buffer
|
||||||
|
// See warning above about m_viewportImage.
|
||||||
|
glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1],
|
||||||
|
GL_DEPTH_COMPONENT, GL_FLOAT, m_viewportImage);
|
||||||
|
// filter loaded data
|
||||||
|
FilterDEPTH filt;
|
||||||
|
filterImage(filt, (float *)m_viewportImage, m_capSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
|
||||||
// get frame buffer data
|
// get frame buffer data
|
||||||
if (m_alpha)
|
if (m_alpha)
|
||||||
{
|
{
|
||||||
@@ -310,6 +340,8 @@ static PyGetSetDef imageViewportGetSets[] =
|
|||||||
{(char*)"size", (getter)Image_getSize, NULL, (char*)"image size", NULL},
|
{(char*)"size", (getter)Image_getSize, NULL, (char*)"image size", NULL},
|
||||||
{(char*)"scale", (getter)Image_getScale, (setter)Image_setScale, (char*)"fast scale of image (near neighbor)", NULL},
|
{(char*)"scale", (getter)Image_getScale, (setter)Image_setScale, (char*)"fast scale of image (near neighbor)", NULL},
|
||||||
{(char*)"flip", (getter)Image_getFlip, (setter)Image_setFlip, (char*)"flip image vertically", NULL},
|
{(char*)"flip", (getter)Image_getFlip, (setter)Image_setFlip, (char*)"flip image vertically", NULL},
|
||||||
|
{(char*)"zbuff", (getter)Image_getZbuff, (setter)Image_setZbuff, (char*)"use depth buffer as texture", NULL},
|
||||||
|
{(char*)"depth", (getter)Image_getDepth, (setter)Image_setDepth, (char*)"get depth information from z-buffer as array of float", NULL},
|
||||||
{(char*)"filter", (getter)Image_getFilter, (setter)Image_setFilter, (char*)"pixel filter", NULL},
|
{(char*)"filter", (getter)Image_getFilter, (setter)Image_setFilter, (char*)"pixel filter", NULL},
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user