diff options
Diffstat (limited to 'source/gameengine/VideoTexture/ImageViewport.cpp')
-rw-r--r-- | source/gameengine/VideoTexture/ImageViewport.cpp | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/source/gameengine/VideoTexture/ImageViewport.cpp b/source/gameengine/VideoTexture/ImageViewport.cpp new file mode 100644 index 00000000000..deb66ffb6ba --- /dev/null +++ b/source/gameengine/VideoTexture/ImageViewport.cpp @@ -0,0 +1,297 @@ +/* $Id$ +----------------------------------------------------------------------------- +This source file is part of VideoTexture library + +Copyright (c) 2007 The Zdeno Ash Miklas + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU Lesser General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place - Suite 330, Boston, MA 02111-1307, USA, or go to +http://www.gnu.org/copyleft/lesser.txt. +----------------------------------------------------------------------------- +*/ + +// implementation + +#include <PyObjectPlus.h> +#include <structmember.h> + +#include <BIF_gl.h> + +#include "Texture.h" +#include "ImageBase.h" +#include "FilterSource.h" +#include "ImageViewport.h" + + +// constructor +ImageViewport::ImageViewport (void) : m_texInit(false) +{ + // get viewport rectangle + glGetIntegerv(GL_VIEWPORT, m_viewport); + // create buffer for viewport image + m_viewportImage = new BYTE [3 * getViewportSize()[0] * getViewportSize()[1]]; + // set attributes + setWhole(false); +} + +// destructor +ImageViewport::~ImageViewport (void) +{ delete m_viewportImage; } + + +// use whole viewport to capture image +void ImageViewport::setWhole (bool whole) +{ + // set whole + m_whole = whole; + // set capture size to viewport size, if whole, + // otherwise place area in the middle of viewport + for (int idx = 0; idx < 2; ++idx) + { + // capture size + m_capSize[idx] = whole ? short(getViewportSize()[idx]) + : calcSize(short(getViewportSize()[idx])); + // position + m_position[idx] = whole ? 0 : (getViewportSize()[idx] - m_capSize[idx]) >> 1; + } + // init image + init(m_capSize[0], m_capSize[1]); + // set capture position + setPosition(); +} + +void ImageViewport::setCaptureSize (short * size) +{ + m_whole = false; + if (size == NULL) + size = m_capSize; + for (int idx = 0; idx < 2; ++idx) + { + if (size[idx] < 1) + m_capSize[idx] = 1; + else if (size[idx] > getViewportSize()[idx]) + m_capSize[idx] = short(getViewportSize()[idx]); + else + m_capSize[idx] = size[idx]; + } + init(m_capSize[0], m_capSize[1]); + // set capture position + setPosition(); +} + +// set position of capture rectangle +void ImageViewport::setPosition (GLint * pos) +{ + // if new position is not provided, use existing position + if (pos == NULL) pos = m_position; + // save position + for (int idx = 0; idx < 2; ++idx) + m_position[idx] = pos[idx] < 0 ? 0 : pos[idx] >= getViewportSize()[idx] + - m_capSize[idx] ? getViewportSize()[idx] - m_capSize[idx] : pos[idx]; + // recalc up left corner + for (int idx = 0; idx < 2; ++idx) + m_upLeft[idx] = m_position[idx] + m_viewport[idx]; +} + + +// capture image from viewport +void ImageViewport::calcImage (unsigned int texId) +{ + // if scale was changed + if (m_scaleChange) + // reset image + init(m_capSize[0], m_capSize[1]); + // if texture wasn't initialized + if (!m_texInit) + { + // initialize it + loadTexture(texId, m_image, m_size); + m_texInit = true; + } + // if texture can be directly created + if (texId != 0 && m_pyfilter == NULL && m_capSize[0] == calcSize(m_capSize[0]) + && m_capSize[1] == calcSize(m_capSize[1]) && !m_flip) + { + // just copy current viewport to texture + glBindTexture(GL_TEXTURE_2D, texId); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1]); + // image is not available + m_avail = false; + } + // otherwise copy viewport to buffer, if image is not available + else if (!m_avail) + { + // get frame buffer data + glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1], GL_RGB, + GL_UNSIGNED_BYTE, m_viewportImage); + // filter loaded data + FilterRGB24 filt; + filterImage(filt, m_viewportImage, m_capSize); + } +} + + + +// cast Image pointer to ImageViewport +inline ImageViewport * getImageViewport (PyImage * self) +{ return static_cast<ImageViewport*>(self->m_image); } + + +// python methods + + +// get whole +static PyObject * ImageViewport_getWhole (PyImage * self, void * closure) +{ + if (self->m_image != NULL && getImageViewport(self)->getWhole()) Py_RETURN_TRUE; + else Py_RETURN_FALSE; +} + +// set whole +static int ImageViewport_setWhole (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 whole + if (self->m_image != NULL) getImageViewport(self)->setWhole(value == Py_True); + // success + return 0; +} + + +// get position +static PyObject * ImageViewport_getPosition (PyImage * self, void * closure) +{ + return Py_BuildValue("(ii)", getImageViewport(self)->getPosition()[0], + getImageViewport(self)->getPosition()[1]); +} + +// set position +static int ImageViewport_setPosition (PyImage * self, PyObject * value, void * closure) +{ + // check validity of parameter + if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 2 + || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 0)) + || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 1))) + { + PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 ints"); + return -1; + } + // set position + GLint pos [] = { + GLint(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 0))), + GLint(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 1))) + }; + getImageViewport(self)->setPosition(pos); + // success + return 0; +} + +// get capture size +static PyObject * ImageViewport_getCaptureSize (PyImage * self, void * closure) +{ + return Py_BuildValue("(ii)", getImageViewport(self)->getCaptureSize()[0], + getImageViewport(self)->getCaptureSize()[1]); +} + +// set capture size +static int ImageViewport_setCaptureSize (PyImage * self, PyObject * value, void * closure) +{ + // check validity of parameter + if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 2 + || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 0)) + || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 1))) + { + PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 ints"); + return -1; + } + // set capture size + short size [] = { + short(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 0))), + short(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 1))) + }; + getImageViewport(self)->setCaptureSize(size); + // success + return 0; +} + + +// methods structure +static PyMethodDef imageViewportMethods[] = +{ // methods from ImageBase class + {"refresh", (PyCFunction)Image_refresh, METH_NOARGS, "Refresh image - invalidate its current content"}, + {NULL} +}; +// attributes structure +static PyGetSetDef imageViewportGetSets[] = +{ + {(char*)"whole", (getter)ImageViewport_getWhole, (setter)ImageViewport_setWhole, (char*)"use whole viewport to capture", NULL}, + {(char*)"position", (getter)ImageViewport_getPosition, (setter)ImageViewport_setPosition, (char*)"upper left corner of captured area", NULL}, + {(char*)"capsize", (getter)ImageViewport_getCaptureSize, (setter)ImageViewport_setCaptureSize, (char*)"size of viewport area being captured", NULL}, + // attributes from ImageBase class + {(char*)"image", (getter)Image_getImage, NULL, (char*)"image data", 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 neighbour)", NULL}, + {(char*)"flip", (getter)Image_getFlip, (setter)Image_setFlip, (char*)"flip image vertically", NULL}, + {(char*)"filter", (getter)Image_getFilter, (setter)Image_setFilter, (char*)"pixel filter", NULL}, + {NULL} +}; + + +// define python type +PyTypeObject ImageViewportType = +{ + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "VideoTexture.ImageViewport", /*tp_name*/ + sizeof(PyImage), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)Image_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + "Image source from viewport", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + imageViewportMethods, /* tp_methods */ + 0, /* tp_members */ + imageViewportGetSets, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)Image_init<ImageViewport>, /* tp_init */ + 0, /* tp_alloc */ + Image_allocNew, /* tp_new */ +}; |