VideoTexture module.
authorBenoit Bolsee <benoit.bolsee@online.be>
Fri, 31 Oct 2008 22:35:52 +0000 (22:35 +0000)
committerBenoit Bolsee <benoit.bolsee@online.be>
Fri, 31 Oct 2008 22:35:52 +0000 (22:35 +0000)
The only compilation system that works for sure is the MSVC project files. I've tried my best to
update the other compilation system but I count on the community to check and fix them.

This is Zdeno Miklas video texture plugin ported to trunk.
The original plugin API is maintained (can be found here http://home.scarlet.be/~tsi46445/blender/blendVideoTex.html)
EXCEPT for the following:

The module name is changed to VideoTexture (instead of blendVideoTex).

A new (and only) video source is now available: VideoFFmpeg()
You must pass 1 to 4 arguments when you create it (you can use named arguments):

VideoFFmpeg(file) : play a video file
VideoFFmpeg(file, capture, rate, width, height) : start a live video capture

file:
In the first form, file is a video file name, relative to startup directory.
It can also be a URL, FFmpeg will happily stream a video from a network source.
In the second form, file is empty or is a hint for the format of the video capture.
In Windows, file is ignored and should be empty or not specified.
In Linux, ffmpeg supports two types of device: VideoForLinux and DV1394.
The user specifies the type of device with the file parameter:
   [<device_type>][:<standard>]
   <device_type> : 'v4l' for VideoForLinux, 'dv1394' for DV1394; default to 'v4l'
   <standard>    : 'pal', 'secam' or 'ntsc', default to 'ntsc'
The driver name is constructed automatically from the device types:
   v4l   : /dev/video<capture>
   dv1394: /dev/dv1394/<capture>
If you have different driver name, you can specify the driver name explicitely
instead of device type. Examples of valid file parameter:
   /dev/v4l/video0:pal
   /dev/ieee1394/1:ntsc
   dv1394:ntsc
   v4l:pal
   :secam

capture:
Defines the index number of the capture source, starting from 0. The first capture device is always 0.
The VideoTexutre modules knows that you want to start a live video capture when you set this parameter to a number >= 0. Setting this parameter < 0 indicates a video file playback. Default value is -1.

rate:
the capture frame rate, by default 25 frames/sec

width:
height:
Width and height of the video capture in pixel, default value 0.
In Windows you must specify these values and they must fit with the capture device capability.
For example, if you have a webcam that can capture at 160x120, 320x240 or 640x480,
you must specify one of these couple of values or the opening of the video source will fail.
In Linux, default values are provided by the VideoForLinux driver if you don't specify width and height.

Simple example
**************
1. Texture definition script:

import VideoTexture

contr = GameLogic.getCurrentController()
obj = contr.getOwner()
if not hasattr(GameLogic, 'video'):
matID = VideoTexture.materialID(obj, 'MAVideoMat')
GameLogic.video = VideoTexture.Texture(obj, matID)
GameLogic.vidSrc = VideoTexture.VideoFFmpeg('trailer_400p.ogg')
# Streaming is also possible:
#GameLogic.vidSrc = VideoTexture.VideoFFmpeg('http://10.32.1.10/trailer_400p.ogg')
GameLogic.vidSrc.repeat = -1
# If the video dimensions are not a power of 2, scaling must be done before
# sending the texture to the GPU. This is done by default with gluScaleImage()
# but you can also use a faster, but less precise, scaling by setting scale
# to True. Best approach is to convert the video offline and set the dimensions right.
GameLogic.vidSrc.scale = True
# FFmpeg always delivers the video image upside down, so flipping is enabled automatically
#GameLogic.vidSrc.flip = True

if contr.getSensors()[0].isPositive():
GameLogic.video.source = GameLogic.vidSrc
GameLogic.vidSrc.play()

2. Texture refresh script:

obj = GameLogic.getCurrentController().getOwner()
if hasattr(GameLogic, 'video') != 0:
  GameLogic.video.refresh(True)

You can download this demo here:
http://home.scarlet.be/~tsi46445/blender/VideoTextureDemo.blend
http://home.scarlet.be/~tsi46445/blender/trailer_400p.ogg

40 files changed:
projectfiles_vc7/blender/blender.sln
source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
source/gameengine/CMakeLists.txt
source/gameengine/SConscript
source/gameengine/VideoTexture/BlendType.h [new file with mode: 0644]
source/gameengine/VideoTexture/CMakeLists.txt [new file with mode: 0644]
source/gameengine/VideoTexture/Common.h [new file with mode: 0644]
source/gameengine/VideoTexture/Exception.cpp [new file with mode: 0644]
source/gameengine/VideoTexture/Exception.h [new file with mode: 0644]
source/gameengine/VideoTexture/FilterBase.cpp [new file with mode: 0644]
source/gameengine/VideoTexture/FilterBase.h [new file with mode: 0644]
source/gameengine/VideoTexture/FilterBlueScreen.cpp [new file with mode: 0644]
source/gameengine/VideoTexture/FilterBlueScreen.h [new file with mode: 0644]
source/gameengine/VideoTexture/FilterColor.cpp [new file with mode: 0644]
source/gameengine/VideoTexture/FilterColor.h [new file with mode: 0644]
source/gameengine/VideoTexture/FilterNormal.cpp [new file with mode: 0644]
source/gameengine/VideoTexture/FilterNormal.h [new file with mode: 0644]
source/gameengine/VideoTexture/FilterSource.cpp [new file with mode: 0644]
source/gameengine/VideoTexture/FilterSource.h [new file with mode: 0644]
source/gameengine/VideoTexture/ImageBase.cpp [new file with mode: 0644]
source/gameengine/VideoTexture/ImageBase.h [new file with mode: 0644]
source/gameengine/VideoTexture/ImageBuff.cpp [new file with mode: 0644]
source/gameengine/VideoTexture/ImageBuff.h [new file with mode: 0644]
source/gameengine/VideoTexture/ImageMix.cpp [new file with mode: 0644]
source/gameengine/VideoTexture/ImageMix.h [new file with mode: 0644]
source/gameengine/VideoTexture/ImageRender.cpp [new file with mode: 0644]
source/gameengine/VideoTexture/ImageRender.h [new file with mode: 0644]
source/gameengine/VideoTexture/ImageViewport.cpp [new file with mode: 0644]
source/gameengine/VideoTexture/ImageViewport.h [new file with mode: 0644]
source/gameengine/VideoTexture/Makefile [new file with mode: 0644]
source/gameengine/VideoTexture/PyTypeList.cpp [new file with mode: 0644]
source/gameengine/VideoTexture/PyTypeList.h [new file with mode: 0644]
source/gameengine/VideoTexture/SConscript [new file with mode: 0644]
source/gameengine/VideoTexture/Texture.cpp [new file with mode: 0644]
source/gameengine/VideoTexture/Texture.h [new file with mode: 0644]
source/gameengine/VideoTexture/VideoBase.cpp [new file with mode: 0644]
source/gameengine/VideoTexture/VideoBase.h [new file with mode: 0644]
source/gameengine/VideoTexture/VideoFFmpeg.cpp [new file with mode: 0644]
source/gameengine/VideoTexture/VideoFFmpeg.h [new file with mode: 0644]
source/gameengine/VideoTexture/blendVideoTex.cpp [new file with mode: 0644]

index eb2355319847756f5b87981a623ad06d73a9a2f3..c1628614642c6b88e4272b9999ca11f38d137350 100644 (file)
@@ -17,6 +17,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "blender", "blender.vcproj",
                {138DD16C-CC78-4F6C-A898-C8DA68D89067} = {138DD16C-CC78-4F6C-A898-C8DA68D89067}
                {415BFD6E-64CF-422B-AF88-C07F040A7292} = {415BFD6E-64CF-422B-AF88-C07F040A7292}
                {106AE171-0083-41D6-A949-20DB0E8DC251} = {106AE171-0083-41D6-A949-20DB0E8DC251}
+               {670EC17A-0548-4BBF-A27B-636C7C188139} = {670EC17A-0548-4BBF-A27B-636C7C188139}
                {4C3AB78A-52CA-4276-A041-39776E52D8C8} = {4C3AB78A-52CA-4276-A041-39776E52D8C8}
                {6B801390-5F95-4F07-81A7-97FBA046AACC} = {6B801390-5F95-4F07-81A7-97FBA046AACC}
                {CAE37E91-6570-43AC-A4B4-7A37A4B0FC94} = {CAE37E91-6570-43AC-A4B4-7A37A4B0FC94}
@@ -239,6 +240,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BL_gpu", "gpu\BL_gpu.vcproj
        ProjectSection(ProjectDependencies) = postProject
        EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TEX_Video", "..\gameengine\videotexture\TEX_Video.vcproj", "{670EC17A-0548-4BBF-A27B-636C7C188139}"
+       ProjectSection(ProjectDependencies) = postProject
+       EndProjectSection
+EndProject
 Global
        GlobalSection(SolutionConfiguration) = preSolution
                3D Plugin Debug = 3D Plugin Debug
@@ -815,6 +820,18 @@ Global
                {138DD16C-CC78-4F6C-A898-C8DA68D89067}.Debug.Build.0 = BlenderPlayer Debug|Win32
                {138DD16C-CC78-4F6C-A898-C8DA68D89067}.Release.ActiveCfg = BlenderPlayer Release|Win32
                {138DD16C-CC78-4F6C-A898-C8DA68D89067}.Release.Build.0 = BlenderPlayer Release|Win32
+               {670EC17A-0548-4BBF-A27B-636C7C188139}.3D Plugin Debug.ActiveCfg = Debug|Win32
+               {670EC17A-0548-4BBF-A27B-636C7C188139}.3D Plugin Release.ActiveCfg = Release|Win32
+               {670EC17A-0548-4BBF-A27B-636C7C188139}.Blender Debug.ActiveCfg = Debug|Win32
+               {670EC17A-0548-4BBF-A27B-636C7C188139}.Blender Debug.Build.0 = Debug|Win32
+               {670EC17A-0548-4BBF-A27B-636C7C188139}.Blender Release.ActiveCfg = Release|Win32
+               {670EC17A-0548-4BBF-A27B-636C7C188139}.Blender Release.Build.0 = Release|Win32
+               {670EC17A-0548-4BBF-A27B-636C7C188139}.BlenderPlayer Debug.ActiveCfg = Debug|Win32
+               {670EC17A-0548-4BBF-A27B-636C7C188139}.BlenderPlayer Debug.Build.0 = Debug|Win32
+               {670EC17A-0548-4BBF-A27B-636C7C188139}.BlenderPlayer Release.ActiveCfg = Release|Win32
+               {670EC17A-0548-4BBF-A27B-636C7C188139}.BlenderPlayer Release.Build.0 = Release|Win32
+               {670EC17A-0548-4BBF-A27B-636C7C188139}.Debug.ActiveCfg = Debug|Win32
+               {670EC17A-0548-4BBF-A27B-636C7C188139}.Release.ActiveCfg = Release|Win32
        EndGlobalSection
        GlobalSection(ExtensibilityGlobals) = postSolution
        EndGlobalSection
index 2b3ef1b31e3aa5123c02a9c2f1089d479c944b02..2d91bbcd7c1264247915a25ba2b36067fae0c85a 100644 (file)
@@ -364,7 +364,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
                        initGameKeys();
                        initPythonConstraintBinding();
                        initMathutils();
-                       //initVideoTexture();
+                       initVideoTexture();
 
                        if (sceneconverter)
                        {
index 93de588ba002e8a48934f4044d3d25a96454110a..3ea788791e2ca16b2c17eec462c44443ff668719 100644 (file)
@@ -40,6 +40,7 @@ SUBDIRS(
   SceneGraph
   Physics/Bullet
   Physics/Sumo
+  VideoTexture
 )
 
 IF(WITH_PLAYER)
index c2750d19706c0f1aef58969af372b69d6ea4a07e..e841f206eee47cb1bf5feb9e0eb3b93853aebed5 100644 (file)
@@ -15,7 +15,8 @@ SConscript(['BlenderRoutines/SConscript',
             'Rasterizer/RAS_OpenGLRasterizer/SConscript',
             'SceneGraph/SConscript',
             'Physics/Bullet/SConscript',
-            'Physics/Sumo/SConscript'
+            'Physics/Sumo/SConscript',
+            'VideoTexture/SConscript'
             ])
 
 if env['WITH_BF_PLAYER']:
diff --git a/source/gameengine/VideoTexture/BlendType.h b/source/gameengine/VideoTexture/BlendType.h
new file mode 100644 (file)
index 0000000..ac3ed88
--- /dev/null
@@ -0,0 +1,75 @@
+/* $Id$
+-----------------------------------------------------------------------------
+This source file is part of VideoTexture library
+
+Copyright (c) 2006 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.
+-----------------------------------------------------------------------------
+*/
+
+#if !defined BLENDTYPE_H
+#define BLENDTYPE_H
+
+
+/// class allows check type of blender python object and access its contained object
+template <class PyObj> class BlendType
+{
+public:
+       /// constructor
+       BlendType (char * name) : m_name(name) {}
+
+       /// check blender type and return pointer to contained object or NULL (if type is not valid)
+       PyObj * checkType (PyObject * obj)
+       {
+               // if pointer to type isn't set 
+               if (m_objType == NULL)
+               {
+                       // compare names of type
+                       if (strcmp(obj->ob_type->tp_name, m_name) == 0)
+                               // if name of type match, save pointer to type
+                               m_objType = obj->ob_type;
+                       else
+                               // if names of type don't match, return NULL
+                               return NULL;
+               }
+               // if pointer to type is set and don't match to type of provided object, return NULL
+               else if (obj->ob_type != m_objType) 
+                       return NULL;
+               // return pointer to object
+               return (PyObj*)obj;
+       }
+
+       /// parse arguments to get object
+       PyObj * parseArg (PyObject * args)
+       {
+               // parse arguments
+               PyObject * obj;
+               if (PyArg_ParseTuple(args, "O", &obj))
+                       // if successfully parsed, return pointer to object
+                       return checkType(obj);
+               // otherwise return NULL
+               return NULL;
+       }
+
+protected:
+       /// name of Python type
+       char * m_name;
+       /// pointer to Python type
+       PyTypeObject * m_objType;
+};
+
+
+#endif
diff --git a/source/gameengine/VideoTexture/CMakeLists.txt b/source/gameengine/VideoTexture/CMakeLists.txt
new file mode 100644 (file)
index 0000000..fbae66e
--- /dev/null
@@ -0,0 +1,60 @@
+# $Id$
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU 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.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Jacques Beaurain.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+FILE(GLOB SRC *.cpp)
+
+SET(INC
+  .
+  ../../../source/gameengine/Ketsji
+  ../../../source/gameengine/Expressions
+  ../../../source/gameengine/GameLogic
+  ../../../source/gameengine/SceneGraph
+  ../../../source/gameengine/Rasterizer
+  ../../../source/gameengine/Rasterizer/RAS_OpenGLRasterizer
+  ../../../source/gameengine/BlenderRoutines
+  ../../../source/blender/include
+  ../../../source/blender/blenlib
+  ../../../source/blender/blenkernel
+  ../../../source/blender/makesdna
+  ../../../source/blender/imbuf
+  ../../../source/blender/python
+  ../../../source/blender/gpu
+  ../../../source/kernel/gen_system
+  ../../../intern/string
+  ../../../intern/moto/include
+  ../../../intern/guardedalloc
+  ../../../intern/SoundSystem
+  ../../../extern/glew/include
+  ${PYTHON_INC}
+)
+
+IF(WITH_FFMPEG)
+  SET(INC ${INC} ${FFMPEG_INC})
+  ADD_DEFINITIONS(-DWITH_FFMPEG)
+ENDIF(WITH_FFMPEG)
+
+BLENDERLIB(bf_videotex "${SRC}" "${INC}")
+#env.BlenderLib ( 'bf_videotex', sources, Split(incs), [], libtype=['game','player'], priority=[25, 72], compileflags = cflags )
diff --git a/source/gameengine/VideoTexture/Common.h b/source/gameengine/VideoTexture/Common.h
new file mode 100644 (file)
index 0000000..f771077
--- /dev/null
@@ -0,0 +1,55 @@
+/* $Id$
+-----------------------------------------------------------------------------
+This source file is part of VideoTexture library
+
+Copyright (c) 2006 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.
+-----------------------------------------------------------------------------
+*/
+
+#if defined WIN32
+#define WINDOWS_LEAN_AND_MEAN
+#endif
+
+#if !defined NULL
+#define NULL 0
+#endif
+
+#if !defined HRESULT
+#define HRESULT long
+#endif
+
+#if !defined DWORD
+#define DWORD unsigned long
+#endif
+
+#if !defined S_OK
+#define S_OK ((HRESULT)0L)
+#endif
+
+#if !defined BYTE
+#define BYTE unsigned char
+#endif
+
+#if !defined WIN32
+#define Sleep(time) sleep(time)
+#endif
+
+#if !defined FAILED
+#define FAILED(Status) ((HRESULT)(Status)<0)
+#endif
+
+#include <iostream>
diff --git a/source/gameengine/VideoTexture/Exception.cpp b/source/gameengine/VideoTexture/Exception.cpp
new file mode 100644 (file)
index 0000000..a326430
--- /dev/null
@@ -0,0 +1,198 @@
+/* $Id$
+-----------------------------------------------------------------------------
+This source file is part of VideoTexture library
+
+Copyright (c) 2006 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.
+-----------------------------------------------------------------------------
+*/
+
+
+#include <strstream>
+#include <fstream>
+
+#include <Python.h>
+
+#include "Exception.h"
+
+
+// exception identificators
+ExceptionID ErrGeneral, ErrNotFound;
+
+// exception descriptions
+ExpDesc errGenerDesc (ErrGeneral, "General Error");
+ExpDesc errNFoundDesc (ErrNotFound, "Error description not found");
+
+
+
+// implementation of ExpDesc
+
+// constructor
+ExpDesc::ExpDesc (ExceptionID & exp, char * desc, RESULT hres) 
+: m_expID(exp), m_hRslt(hres), m_description(desc)
+{
+       m_expDescs.push_back(this);
+}
+
+// destructor
+ExpDesc::~ExpDesc (void) {}
+
+// list of descriptions
+std::vector<ExpDesc*> ExpDesc::m_expDescs;
+
+
+// class Exception
+
+
+// last exception description
+std::string Exception::m_lastError;
+
+// log file name
+char * Exception::m_logFile = NULL;
+
+
+// basic constructor
+Exception::Exception ()
+{
+       // default values
+       m_expID = &ErrNotFound;
+       m_hRslt = S_OK;
+       m_line = 0;
+}
+
+
+// destructor
+Exception::~Exception () throw() { }
+
+
+// copy constructor
+Exception::Exception (const Exception & xpt)
+{ copy (xpt); }
+
+
+// assignment operator
+Exception & Exception::operator= (const Exception & xpt)
+{ copy (xpt); return *this; }
+
+
+// get exception description
+const char * Exception::what()
+{
+       // set exception description
+       setXptDesc();
+       // return c string
+       return m_desc.c_str();
+}
+
+
+// debug version - with file and line of exception
+Exception::Exception (ExceptionID & expID, RESULT rslt, char * fil, int lin)
+: m_expID (&expID), m_hRslt (rslt)
+{
+       // set file and line
+       if (strlen(fil) > 0 || lin > 0)
+               setFileLine (fil, lin);
+}
+
+
+// set file and line
+void Exception::setFileLine (char * fil, int lin)
+{
+       if (fil != NULL) m_fileName = fil;
+       m_line = lin;
+}
+
+
+// report exception
+void Exception::report(void)
+{
+       // set exception description
+       setXptDesc();
+       // set python error
+       PyErr_SetString(PyExc_RuntimeError, what());
+       // if log file is set
+       if (m_logFile != NULL)
+       {
+               // write description to log
+               std::ofstream logf (m_logFile, std::ios_base::app);
+               logf << m_fileName << ':' << m_line << ':' << m_desc << std::endl;
+               logf.flush();
+               logf.close();
+       }
+}
+
+
+// set exception description
+void Exception::setXptDesc (void)
+{
+       // if description is not set
+       if (m_desc.size() == 0)
+       {
+               // start of search                           -1
+               // found description "NotFound"               0
+               // found description without matching result  1
+               // found description with matching result     2
+               int best = -1;
+               // find exception description
+               for (std::vector<ExpDesc*>::iterator it = ExpDesc::m_expDescs.begin(); it != ExpDesc::m_expDescs.end(); ++it)
+               {
+                       // use "NotFound", if there is not better
+                       if (best < 0 && (*it)->isExp(&ErrNotFound) > 0)
+                       {
+                               (*it)->loadDesc(m_desc);
+                               best = 0;
+                       }
+                       // match exception
+                       int nBest = (*it)->isExp(m_expID, m_hRslt);
+                       // if exception is matching better
+                       if (nBest > 0 && best < nBest)
+                       {
+                               // set description
+                               (*it)->loadDesc(m_desc);
+                               best = nBest;
+                               // if matching exactly, finish search
+                               if (best == 2) break;
+                       }
+               }
+               // add result code
+               // length of result code
+               const size_t rsltSize = 10;
+               // delimit description
+               const char delimRslt[] = ": ";
+               // set text of description
+               char rsltTxt[rsltSize];
+               std::ostrstream os(rsltTxt, rsltSize);
+               os << std::hex << m_hRslt << delimRslt;
+               // copy result to description
+               m_desc.insert(0, rsltTxt, rsltSize);
+               // copy exception description to last exception string
+               m_lastError = m_desc;
+       }
+}
+
+
+// copy exception data
+void Exception::copy (const Exception & xpt)
+{
+       // standard data
+       m_expID = xpt.m_expID;
+       m_hRslt = xpt.m_hRslt;
+       m_desc = xpt.m_desc;
+
+       // debug data
+       m_fileName = xpt.m_fileName;
+       m_line = xpt.m_line;
+}
diff --git a/source/gameengine/VideoTexture/Exception.h b/source/gameengine/VideoTexture/Exception.h
new file mode 100644 (file)
index 0000000..85865fb
--- /dev/null
@@ -0,0 +1,195 @@
+/* $Id$
+-----------------------------------------------------------------------------
+This source file is part of VideoTexture library
+
+Copyright (c) 2006 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.
+-----------------------------------------------------------------------------
+*/
+
+
+#if !defined EXCEPTION_H
+#define EXCEPTION_H
+
+#include <exception>
+#include <vector>
+#include <string>
+
+#include "Common.h"
+
+
+#define CHCKHRSLTV(fnc,val,err) \
+{ \
+       HRESULT macroHRslt = (fnc); \
+       if (macroHRslt != val) \
+       throw Exception (err, macroHRslt, __FILE__, __LINE__); \
+}
+
+#define THRWEXCP(err,hRslt) throw Exception (err, hRslt, __FILE__, __LINE__);
+
+
+#if defined WIN32
+
+#define CHCKHRSLT(fnc,err) \
+{ \
+       HRESULT macroHRslt = (fnc); \
+       if (FAILED(macroHRslt)) \
+       throw Exception (err, macroHRslt, __FILE__, __LINE__); \
+}
+
+#else
+
+#define CHCKHRSLT(fnc,err) CHCKHRSLTV(fnc,S_OK,err)
+
+#endif
+
+
+// forward declarations
+class ExceptionID;
+class Exception;
+
+
+// exception identificators
+extern ExceptionID ErrGeneral, ErrNotFound;
+
+
+// result type
+typedef long RESULT;
+
+
+// class ExceptionID for exception identification
+class ExceptionID
+{
+public:
+       // constructor a destructor
+       ExceptionID (void) {}
+       ~ExceptionID (void) {}
+
+private:
+       // not allowed 
+       ExceptionID (const ExceptionID & obj) throw() {}
+       ExceptionID & operator= (const ExceptionID & obj) throw() { return *this; }
+};
+
+
+// class ExpDesc for exception description
+class ExpDesc
+{
+public:
+       // constructor a destructor
+       ExpDesc (ExceptionID & exp, char * desc, RESULT hres = S_OK);
+       ~ExpDesc (void);
+
+       // comparision function
+       // returns 0, if exception identification don't match at all
+       // returns 1, if only exception identification is matching
+       // returns 2, if both exception identification and result are matching
+       int isExp (ExceptionID * exp, RESULT hres = S_OK) throw()
+       {
+               // check exception identification
+               if (&m_expID == exp)
+               {
+                       // check result value
+                       if (m_hRslt == hres) return 2;
+                       // only identification match
+                       if (m_hRslt == S_OK) return 1;
+               }
+               // no match
+               return 0;
+       }
+
+       // get exception description
+       void loadDesc (std::string & desc) throw()
+       {
+               desc = m_description;
+       }
+
+       // list of exception descriptions
+       static std::vector<ExpDesc*> m_expDescs;
+
+private:
+       // exception ID
+       ExceptionID & m_expID;
+       // result
+       RESULT m_hRslt;
+       // description
+       char * m_description;
+
+       // not allowed
+       ExpDesc (const ExpDesc & obj) : m_expID (ErrNotFound) {}
+       ExpDesc & operator= (const ExpDesc & obj) { return *this; }
+};
+
+
+
+// class Exception
+class Exception : public std::exception  
+{
+public:
+       // constructor
+       Exception ();
+       // destructor
+       virtual ~Exception () throw();
+       // copy constructor
+       Exception (const Exception & xpt);
+       // assignment operator
+       Exception & operator= (const Exception & xpt);
+       // get exception description
+       virtual const char * what(void);
+
+       // debug version of constructor
+       Exception (ExceptionID & expID, RESULT rslt, char * fil, int lin);
+       // set source file and line of exception
+       void setFileLine (char * fil, int lin);
+
+       // get description in string
+       std::string & getDesc (void) throw() { return m_desc; }
+
+       // report exception
+       virtual void report (void);
+
+       // get exception id
+       ExceptionID * getID (void) throw() { return m_expID; }
+
+       /// last exception description
+       static std::string m_lastError;
+
+       /// log file name
+       static char * m_logFile;
+
+protected:
+       // exception identification
+       ExceptionID * m_expID;
+       // RESULT code
+       RESULT m_hRslt;
+
+       // exception description
+       std::string m_desc;
+
+       // set exception description
+       virtual void setXptDesc (void);
+
+       // copy exception
+       void copy (const Exception & xpt);
+
+       // file name where exception was thrown
+       std::string m_fileName;
+       // line number in file
+       int m_line;
+
+};
+
+#endif
diff --git a/source/gameengine/VideoTexture/FilterBase.cpp b/source/gameengine/VideoTexture/FilterBase.cpp
new file mode 100644 (file)
index 0000000..078a096
--- /dev/null
@@ -0,0 +1,150 @@
+/* $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.
+-----------------------------------------------------------------------------
+*/
+
+#include "FilterBase.h"
+
+#include <Python.h>
+#include <structmember.h>
+
+
+// FilterBase class implementation
+
+// constructor
+FilterBase::FilterBase (void) : m_previous(NULL) {}
+
+
+// destructor
+FilterBase::~FilterBase (void)
+{
+       // release Python objects, if not released yet
+       release();
+}
+
+
+// release python objects
+void FilterBase::release (void)
+{
+       // release previous filter object
+       setPrevious(NULL);
+}
+
+
+// set new previous filter
+void FilterBase::setPrevious (PyFilter * filt, bool useRefCnt)
+{
+       // if reference counting has to be used
+       if (useRefCnt)
+       {
+               // reference new filter
+               if (filt != NULL) Py_INCREF(filt);
+               // release old filter
+               Py_XDECREF(m_previous);
+       }
+       // set new previous filter
+       m_previous = filt;
+}
+
+
+// find first filter
+FilterBase * FilterBase::findFirst (void)
+{
+       // find first filter in chain
+       FilterBase * frst;
+       for (frst = this; frst->m_previous != NULL; frst = frst->m_previous->m_filter);
+       // set first filter
+       return frst;
+}
+
+
+
+// list offilter types
+PyTypeList pyFilterTypes;
+
+
+
+// functions for python interface
+
+
+// object allocation
+PyObject * Filter_allocNew (PyTypeObject * type, PyObject * args, PyObject * kwds)
+{
+       // allocate object
+       PyFilter * self = reinterpret_cast<PyFilter*>(type->tp_alloc(type, 0));
+       // initialize object structure
+       self->m_filter = NULL;
+       // return allocated object
+       return reinterpret_cast<PyObject*>(self);
+}
+
+// object deallocation
+void Filter_dealloc (PyFilter * self)
+{
+       // release object attributes
+       if (self->m_filter != NULL)
+       {
+               self->m_filter->release();
+               delete self->m_filter;
+               self->m_filter = NULL;
+       }
+}
+
+
+// get previous pixel filter object
+PyObject * Filter_getPrevious (PyFilter * self, void * closure)
+{
+       // if filter object is available
+       if (self->m_filter != NULL)
+       {
+               // pixel filter object
+               PyObject * filt = reinterpret_cast<PyObject*>(self->m_filter->getPrevious());
+               // if filter is present
+               if (filt != NULL)
+               {
+                       // return it
+                       Py_INCREF(filt);
+                       return filt;
+               }
+       }
+       // otherwise return none
+       Py_RETURN_NONE;
+}
+
+
+// set previous pixel filter object
+int Filter_setPrevious (PyFilter * self, PyObject * value, void * closure)
+{
+       // if filter object is available
+       if (self->m_filter != NULL)
+       {
+               // check new value
+               if (value == NULL || !pyFilterTypes.in(value->ob_type))
+               {
+                       // report value error
+                       PyErr_SetString(PyExc_TypeError, "Invalid type of value");
+                       return -1;
+               }
+               // set new value
+               self->m_filter->setPrevious(reinterpret_cast<PyFilter*>(value));
+       }
+       // return success
+       return 0;
+}
diff --git a/source/gameengine/VideoTexture/FilterBase.h b/source/gameengine/VideoTexture/FilterBase.h
new file mode 100644 (file)
index 0000000..fa6f9a7
--- /dev/null
@@ -0,0 +1,132 @@
+/* $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.
+-----------------------------------------------------------------------------
+*/
+
+#if !defined FILTERBASE_H
+#define FILTERBASE_H
+
+#include "Common.h"
+
+#include <Python.h>
+
+#include "PyTypeList.h"
+
+
+// forward declaration
+class FilterBase;
+
+
+// python structure for filter
+struct PyFilter
+{
+       PyObject_HEAD
+       // source object
+       FilterBase * m_filter;
+};
+
+
+/// base class for pixel filters
+class FilterBase
+{
+public:
+       /// constructor
+       FilterBase (void);
+       /// destructor
+       virtual ~FilterBase (void);
+       // release python objects
+       virtual void release (void);
+
+       /// convert pixel
+       template <class SRC> unsigned int convert (SRC src, short x, short y,
+               short * size, unsigned int pixSize)
+       {
+               return filter(src, x, y, size, pixSize,
+                       convertPrevious(src, x, y, size, pixSize));
+       }
+
+       /// get previous filter
+       PyFilter * getPrevious (void) { return m_previous; }
+       /// set previous filter
+       void setPrevious (PyFilter * filt, bool useRefCnt = true);
+
+       /// find first filter in chain
+       FilterBase * findFirst (void);
+
+       /// get first filter's source pixel size
+       unsigned int firstPixelSize (void) { return findFirst()->getPixelSize(); }
+
+protected:
+       /// previous pixel filter
+       PyFilter * m_previous;
+
+       /// filter pixel, source byte buffer
+       virtual unsigned int filter (unsigned char * src, short x, short y,
+               short * size, unsigned int pixSize, unsigned int val = 0)
+       { return val; }
+       /// filter pixel, source int buffer
+       virtual unsigned int filter (unsigned int * src, short x, short y,
+               short * size, unsigned int pixSize, unsigned int val = 0)
+       { return val; }
+
+       /// get source pixel size
+       virtual unsigned int getPixelSize (void) { return 1; }
+
+       /// get converted pixel from previous filters
+       template <class SRC> unsigned int convertPrevious (SRC src, short x, short y,
+               short * size, unsigned int pixSize)
+       {
+               // if previous filter doesn't exists, return source pixel
+               if (m_previous == NULL) return *src;
+               // otherwise return converted pixel
+               return m_previous->m_filter->convert(src, x, y, size, pixSize);
+       }
+};
+
+
+// list of python filter types
+extern PyTypeList pyFilterTypes;
+
+
+// functions for python interface
+
+// object initialization
+template <class T> static int Filter_init (PyObject * pySelf, PyObject * args, PyObject * kwds)
+{
+       PyFilter * self = reinterpret_cast<PyFilter*>(pySelf);
+       // create filter object
+       if (self->m_filter != NULL) delete self->m_filter;
+       self->m_filter = new T();
+       // initialization succeded
+       return 0;
+}
+
+// object allocation
+PyObject * Filter_allocNew (PyTypeObject * type, PyObject * args, PyObject * kwds);
+// object deallocation
+void Filter_dealloc (PyFilter * self);
+
+// get previous pixel filter object
+PyObject * Filter_getPrevious (PyFilter * self, void * closure);
+// set previous pixel filter object
+int Filter_setPrevious (PyFilter * self, PyObject * value, void * closure);
+
+
+#endif
\ No newline at end of file
diff --git a/source/gameengine/VideoTexture/FilterBlueScreen.cpp b/source/gameengine/VideoTexture/FilterBlueScreen.cpp
new file mode 100644 (file)
index 0000000..d911b1d
--- /dev/null
@@ -0,0 +1,178 @@
+/* $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.
+-----------------------------------------------------------------------------
+*/
+
+
+#include <Python.h>
+#include <structmember.h>
+
+#include "FilterBlueScreen.h"
+
+#include "FilterBase.h"
+#include "PyTypeList.h"
+
+// implementation FilterBlueScreen
+
+// constructor
+FilterBlueScreen::FilterBlueScreen (void)
+{
+       // set color to blue
+       setColor(0, 0, 255);
+       // set limits
+       setLimits(64, 64);
+}
+
+// set color
+void FilterBlueScreen::setColor (unsigned char red, unsigned char green, unsigned char blue)
+{
+       m_color[0] = red;
+       m_color[1] = green;
+       m_color[2] = blue;
+}
+
+// set limits for color variation
+void FilterBlueScreen::setLimits (unsigned short minLimit, unsigned short maxLimit)
+{
+       m_limits[0] = minLimit;
+       m_limits[1] = maxLimit > minLimit ? maxLimit : minLimit;
+       // calculate square values
+       for (short idx = 0; idx < 2; ++idx)
+               m_squareLimits[idx] = m_limits[idx] * m_limits[idx];
+       // limits distance
+       m_limitDist = m_squareLimits[1] - m_squareLimits[0];
+}
+
+
+
+// cast Filter pointer to FilterBlueScreen
+inline FilterBlueScreen * getFilter (PyFilter * self)
+{ return static_cast<FilterBlueScreen*>(self->m_filter); }
+
+
+// python methods and get/sets
+
+// get color
+static PyObject * getColor (PyFilter * self, void * closure)
+{
+       return Py_BuildValue("[BBB]", getFilter(self)->getColor()[0],
+               getFilter(self)->getColor()[1], getFilter(self)->getColor()[2]);
+}
+
+// set color
+static int setColor (PyFilter * self, PyObject * value, void * closure)
+{
+       // check validity of parameter
+       if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 3
+               || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 0))
+               || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 1))
+               || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 2)))
+       {
+               PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 3 ints");
+               return -1;
+       }
+       // set color
+       getFilter(self)->setColor((unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 0))),
+               (unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 1))),
+               (unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 2))));
+       // success
+       return 0;
+}
+
+// get limits
+static PyObject * getLimits (PyFilter * self, void * closure)
+{
+       return Py_BuildValue("[II]", getFilter(self)->getLimits()[0],
+               getFilter(self)->getLimits()[1]);
+}
+
+// set limit
+static int setLimits (PyFilter * 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 limits
+       getFilter(self)->setLimits((unsigned short)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 0))),
+               (unsigned short)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 1))));
+       // success
+       return 0;
+}
+
+
+// attributes structure
+static PyGetSetDef filterBSGetSets[] =
+{ 
+       {"color", (getter)getColor, (setter)setColor, "blue screen color", NULL},
+       {"limits", (getter)getLimits, (setter)setLimits, "blue screen color limits", NULL},
+       // attributes from FilterBase class
+       {"previous", (getter)Filter_getPrevious, (setter)Filter_setPrevious, "previous pixel filter", NULL},
+       {NULL}
+};
+
+// define python type
+PyTypeObject FilterBlueScreenType =
+{ 
+       PyObject_HEAD_INIT(NULL)
+       0,                         /*ob_size*/
+       "VideoTexture.FilterBlueScreen",   /*tp_name*/
+       sizeof(PyFilter),          /*tp_basicsize*/
+       0,                         /*tp_itemsize*/
+       (destructor)Filter_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*/
+       "Filter for Blue Screen objects",       /* tp_doc */
+       0,                             /* tp_traverse */
+       0,                             /* tp_clear */
+       0,                             /* tp_richcompare */
+       0,                             /* tp_weaklistoffset */
+       0,                             /* tp_iter */
+       0,                             /* tp_iternext */
+       NULL,                /* tp_methods */
+       0,                   /* tp_members */
+       filterBSGetSets,           /* tp_getset */
+       0,                         /* tp_base */
+       0,                         /* tp_dict */
+       0,                         /* tp_descr_get */
+       0,                         /* tp_descr_set */
+       0,                         /* tp_dictoffset */
+       (initproc)Filter_init<FilterBlueScreen>,     /* tp_init */
+       0,                         /* tp_alloc */
+       Filter_allocNew,           /* tp_new */
+};
+
diff --git a/source/gameengine/VideoTexture/FilterBlueScreen.h b/source/gameengine/VideoTexture/FilterBlueScreen.h
new file mode 100644 (file)
index 0000000..1871fbc
--- /dev/null
@@ -0,0 +1,98 @@
+/* $Id$
+-----------------------------------------------------------------------------
+This source file is part of blendTex 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.
+-----------------------------------------------------------------------------
+*/
+
+#if !defined FILTERBLUESCREEN_H
+#define FILTERBLUESCREEN_H
+
+#include "Common.h"
+
+#include "FilterBase.h"
+
+
+/// pixel filter for blue screen
+class FilterBlueScreen : public FilterBase
+{
+public:
+       /// constructor
+       FilterBlueScreen (void);
+       /// destructor
+       virtual ~FilterBlueScreen (void) {}
+
+       /// get color
+       unsigned char * getColor (void) { return m_color; }
+       /// set color
+       void setColor (unsigned char red, unsigned char green, unsigned char blue);
+
+       /// get limits for color variation
+       unsigned short * getLimits (void) { return m_limits; }
+       /// set limits for color variation
+       void setLimits (unsigned short minLimit, unsigned short maxLimit);
+
+protected:
+       ///  blue screen color (red component first)
+       unsigned char m_color[3];
+       /// limits for color variation - first defines, where ends fully transparent
+       /// color, second defines, where begins fully opaque color
+       unsigned short m_limits[2];
+       /// squared limits for color variation
+       unsigned int m_squareLimits[2];
+       /// distance between squared limits
+       unsigned int m_limitDist;
+
+       /// filter pixel template, source int buffer
+       template <class SRC> unsigned int tFilter (SRC src, short x, short y,
+               short * size, unsigned int pixSize, unsigned int val)
+       {
+               // calculate differences
+               int difRed = int((val >> 16) & 0xFF) - int(m_color[0]);
+               int difGreen = int((val >> 8) & 0xFF) - int(m_color[1]);
+               int difBlue = int(val & 0xFF) - int(m_color[2]);
+               // calc distance from "blue screen" color
+               unsigned int dist = (unsigned int)(difRed * difRed + difGreen * difGreen
+                       + difBlue * difBlue);
+               // condition for fully transparent color
+               if (m_squareLimits[0] >= dist) 
+                       // return color with zero alpha
+                       //return 0xFF000000;
+                       return val & 0x00FFFFFF;
+               // condition for fully opaque color
+               else if (m_squareLimits[1] <= dist)
+                       // return normal colour
+                       return val | 0xFF000000;
+               // otherwise calc alpha
+               else
+                       return (val & 0x00FFFFFF) | ((((dist - m_squareLimits[0]) << 8)
+                       / m_limitDist) << 24);
+       }
+
+       /// virtual filtering function for byte source
+       virtual unsigned int filter (unsigned char * src, short x, short y,
+               short * size, unsigned int pixSize, unsigned int val = 0)
+       { return tFilter(src, x, y, size, pixSize, val); }
+       /// virtual filtering function for unsigned int source
+       virtual unsigned int filter (unsigned int * src, short x, short y,
+               short * size, unsigned int pixSize, unsigned int val = 0)
+       { return tFilter(src, x, y, size, pixSize, val); }
+};
+
+
+#endif
\ No newline at end of file
diff --git a/source/gameengine/VideoTexture/FilterColor.cpp b/source/gameengine/VideoTexture/FilterColor.cpp
new file mode 100644 (file)
index 0000000..c45804c
--- /dev/null
@@ -0,0 +1,350 @@
+/* $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.
+-----------------------------------------------------------------------------
+*/
+
+
+#include <Python.h>
+#include <structmember.h>
+
+#include "FilterColor.h"
+
+#include "FilterBase.h"
+#include "PyTypeList.h"
+
+// implementation FilterGray
+
+// attributes structure
+static PyGetSetDef filterGrayGetSets[] =
+{ // attributes from FilterBase class
+       {"previous", (getter)Filter_getPrevious, (setter)Filter_setPrevious, "previous pixel filter", NULL},
+       {NULL}
+};
+
+// define python type
+PyTypeObject FilterGrayType =
+{ 
+       PyObject_HEAD_INIT(NULL)
+       0,                         /*ob_size*/
+       "VideoTexture.FilterGray",   /*tp_name*/
+       sizeof(PyFilter),          /*tp_basicsize*/
+       0,                         /*tp_itemsize*/
+       (destructor)Filter_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*/
+       "Filter for gray scale effect",       /* tp_doc */
+       0,                             /* tp_traverse */
+       0,                             /* tp_clear */
+       0,                             /* tp_richcompare */
+       0,                             /* tp_weaklistoffset */
+       0,                             /* tp_iter */
+       0,                             /* tp_iternext */
+       NULL,                /* tp_methods */
+       0,                   /* tp_members */
+       filterGrayGetSets,           /* tp_getset */
+       0,                         /* tp_base */
+       0,                         /* tp_dict */
+       0,                         /* tp_descr_get */
+       0,                         /* tp_descr_set */
+       0,                         /* tp_dictoffset */
+       (initproc)Filter_init<FilterGray>,     /* tp_init */
+       0,                         /* tp_alloc */
+       Filter_allocNew,           /* tp_new */
+};
+
+
+// implementation FilterColor
+
+// constructor
+FilterColor::FilterColor (void)
+{
+       // reset color matrix to identity
+       for (int r = 0; r < 4; ++r)
+               for (int c = 0; c < 5; ++c)
+                       m_matrix[r][c] = (r == c) ? 256 : 0; 
+}
+
+// set color matrix
+void FilterColor::setMatrix (ColorMatrix & mat)
+{
+       // copy matrix
+       for (int r = 0; r < 4; ++r)
+               for (int c = 0; c < 5; ++c)
+                       m_matrix[r][c] = mat[r][c]; 
+}
+
+
+
+// cast Filter pointer to FilterColor
+inline FilterColor * getFilterColor (PyFilter * self)
+{ return static_cast<FilterColor*>(self->m_filter); }
+
+
+// python methods and get/sets
+
+// get color matrix
+static PyObject * getMatrix (PyFilter * self, void * closure)
+{
+       ColorMatrix & mat = getFilterColor(self)->getMatrix();
+       return Py_BuildValue("((hhhhh)(hhhhh)(hhhhh)(hhhhh))",
+               mat[0][0], mat[0][1], mat[0][2], mat[0][3], mat[0][4],
+               mat[1][0], mat[1][1], mat[1][2], mat[1][3], mat[1][4],
+               mat[2][0], mat[2][1], mat[2][2], mat[2][3], mat[2][4],
+               mat[3][0], mat[3][1], mat[3][2], mat[3][3], mat[3][4]);
+}
+
+// set color matrix
+static int setMatrix (PyFilter * self, PyObject * value, void * closure)
+{
+       // matrix to store items
+       ColorMatrix mat;
+       // check validity of parameter
+       bool valid = value != NULL && PySequence_Check(value)
+               && PySequence_Length(value) == 4;
+       // check rows
+       for (int r = 0; valid && r < 4; ++r)
+       {
+               // get row object
+               PyObject * row = PySequence_Fast_GET_ITEM(value, r);
+               // check sequence
+               valid = PySequence_Check(row) && PySequence_Length(row) == 5;
+               // check items
+               for (int c = 0; valid && c < 5; ++c)
+               {
+                       // item must be int
+                       valid = PyInt_Check(PySequence_Fast_GET_ITEM(row, c));
+                       // if it is valid, save it in matrix
+                       if (valid)
+                               mat[r][c] = short(PyInt_AsLong(PySequence_Fast_GET_ITEM(row, c)));
+               }
+       }
+       // if parameter is not valid, report error
+       if (!valid)
+       {
+               PyErr_SetString(PyExc_TypeError, "The value must be a matrix [4][5] of ints");
+               return -1;
+       }
+       // set color matrix
+       getFilterColor(self)->setMatrix(mat);
+       // success
+       return 0;
+}
+
+
+// attributes structure
+static PyGetSetDef filterColorGetSets[] =
+{ 
+       {"matrix", (getter)getMatrix, (setter)setMatrix, "matrix [4][5] for color calculation", NULL},
+       // attributes from FilterBase class
+       {"previous", (getter)Filter_getPrevious, (setter)Filter_setPrevious, "previous pixel filter", NULL},
+       {NULL}
+};
+
+// define python type
+PyTypeObject FilterColorType =
+{ 
+       PyObject_HEAD_INIT(NULL)
+       0,                         /*ob_size*/
+       "VideoTexture.FilterColor",   /*tp_name*/
+       sizeof(PyFilter),          /*tp_basicsize*/
+       0,                         /*tp_itemsize*/
+       (destructor)Filter_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*/
+       "Filter for color calculations",       /* tp_doc */
+       0,                             /* tp_traverse */
+       0,                             /* tp_clear */
+       0,                             /* tp_richcompare */
+       0,                             /* tp_weaklistoffset */
+       0,                             /* tp_iter */
+       0,                             /* tp_iternext */
+       NULL,                /* tp_methods */
+       0,                   /* tp_members */
+       filterColorGetSets,           /* tp_getset */
+       0,                         /* tp_base */
+       0,                         /* tp_dict */
+       0,                         /* tp_descr_get */
+       0,                         /* tp_descr_set */
+       0,                         /* tp_dictoffset */
+       (initproc)Filter_init<FilterColor>,     /* tp_init */
+       0,                         /* tp_alloc */
+       Filter_allocNew,           /* tp_new */
+};
+
+// implementation FilterLevel
+
+// constructor
+FilterLevel::FilterLevel (void)
+{
+       // reset color levels
+       for (int r = 0; r < 4; ++r)
+       {
+               levels[r][0] = 0;
+               levels[r][1] = 0xFF << (r << 3);
+               levels[r][2] = 0xFF;
+       }
+}
+
+// set color levels
+void FilterLevel::setLevels (ColorLevel & lev)
+{
+       // copy levels
+       for (int r = 0; r < 4; ++r)
+       {
+               for (int c = 0; c < 2; ++c)
+                       levels[r][c] = lev[r][c] << (r << 3);
+               levels[r][2] = lev[r][0] < lev[r][1] ? lev[r][1] - lev[r][0] : 1;
+       }
+}
+
+
+// cast Filter pointer to FilterLevel
+inline FilterLevel * getFilterLevel (PyFilter * self)
+{ return static_cast<FilterLevel*>(self->m_filter); }
+
+
+// python methods and get/sets
+
+// get color levels
+static PyObject * getLevels (PyFilter * self, void * closure)
+{
+       ColorLevel & lev = getFilterLevel(self)->getLevels();
+       return Py_BuildValue("((kk)(kk)(kk)(kk))",
+               lev[0][0], lev[0][1], lev[1][0] >> 8, lev[1][1] >> 8,
+               lev[2][0] >> 16, lev[2][1] >> 16, lev[3][0] >> 24, lev[3][1] >> 24);
+}
+
+// set color levels
+static int setLevels (PyFilter * self, PyObject * value, void * closure)
+{
+       // matrix to store items
+       ColorLevel lev;
+       // check validity of parameter
+       bool valid = value != NULL && PySequence_Check(value)
+               && PySequence_Length(value) == 4;
+       // check rows
+       for (int r = 0; valid && r < 4; ++r)
+       {
+               // get row object
+               PyObject * row = PySequence_Fast_GET_ITEM(value, r);
+               // check sequence
+               valid = PySequence_Check(row) && PySequence_Length(row) == 2;
+               // check items
+               for (int c = 0; valid && c < 2; ++c)
+               {
+                       // item must be int
+                       valid = PyInt_Check(PySequence_Fast_GET_ITEM(row, c));
+                       // if it is valid, save it in matrix
+                       if (valid)
+                               lev[r][c] = (unsigned long)(PyInt_AsLong(PySequence_Fast_GET_ITEM(row, c)));
+               }
+       }
+       // if parameter is not valid, report error
+       if (!valid)
+       {
+               PyErr_SetString(PyExc_TypeError, "The value must be a matrix [4][2] of ints");
+               return -1;
+       }
+       // set color matrix
+       getFilterLevel(self)->setLevels(lev);
+       // success
+       return 0;
+}
+
+
+// attributes structure
+static PyGetSetDef filterLevelGetSets[] =
+{ 
+       {"levels", (getter)getLevels, (setter)setLevels, "levels matrix [4] (min, max)", NULL},
+       // attributes from FilterBase class
+       {"previous", (getter)Filter_getPrevious, (setter)Filter_setPrevious, "previous pixel filter", NULL},
+       {NULL}
+};
+
+// define python type
+PyTypeObject FilterLevelType =
+{ 
+       PyObject_HEAD_INIT(NULL)
+       0,                         /*ob_size*/
+       "VideoTexture.FilterLevel",   /*tp_name*/
+       sizeof(PyFilter),          /*tp_basicsize*/
+       0,                         /*tp_itemsize*/
+       (destructor)Filter_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*/
+       "Filter for levels calculations",       /* tp_doc */
+       0,                             /* tp_traverse */
+       0,                             /* tp_clear */
+       0,                             /* tp_richcompare */
+       0,                             /* tp_weaklistoffset */
+       0,                             /* tp_iter */
+       0,                             /* tp_iternext */
+       NULL,                /* tp_methods */
+       0,                   /* tp_members */
+       filterLevelGetSets,           /* tp_getset */
+       0,                         /* tp_base */
+       0,                         /* tp_dict */
+       0,                         /* tp_descr_get */
+       0,                         /* tp_descr_set */
+       0,                         /* tp_dictoffset */
+       (initproc)Filter_init<FilterLevel>,     /* tp_init */
+       0,                         /* tp_alloc */
+       Filter_allocNew,           /* tp_new */
+};
+
diff --git a/source/gameengine/VideoTexture/FilterColor.h b/source/gameengine/VideoTexture/FilterColor.h
new file mode 100644 (file)
index 0000000..4465df9
--- /dev/null
@@ -0,0 +1,164 @@
+/* $Id$
+-----------------------------------------------------------------------------
+This source file is part of blendTex 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.
+-----------------------------------------------------------------------------
+*/
+
+#if !defined FILTERCOLOR_H
+#define FILTERCOLOR_H
+
+#include "Common.h"
+
+#include "FilterBase.h"
+
+
+/// pixel filter for gray scale
+class FilterGray : public FilterBase
+{
+public:
+       /// constructor
+       FilterGray (void) {}
+       /// destructor
+       virtual ~FilterGray (void) {}
+
+protected:
+       /// filter pixel template, source int buffer
+       template <class SRC> unsigned int tFilter (SRC src, short x, short y,
+               short * size, unsigned int pixSize, unsigned int val)
+       {
+               // calculate gray value
+               unsigned int gray = (28 * ((val >> 16) & 0xFF) + 151 * ((val >> 8) & 0xFF)
+                       + 77 * (val & 0xFF)) & 0xFF00;
+               // return gray scale value
+               return (val & 0xFF000000) | gray << 8 | gray | gray >> 8;
+       }
+
+       /// virtual filtering function for byte source
+       virtual unsigned int filter (unsigned char * src, short x, short y,
+               short * size, unsigned int pixSize, unsigned int val = 0)
+       { return tFilter(src, x, y, size, pixSize, val); }
+       /// virtual filtering function for unsigned int source
+       virtual unsigned int filter (unsigned int * src, short x, short y,
+               short * size, unsigned int pixSize, unsigned int val = 0)
+       { return tFilter(src, x, y, size, pixSize, val); }
+};
+
+
+/// type for color matrix
+typedef short ColorMatrix[4][5];
+
+/// pixel filter for color calculation
+class FilterColor : public FilterBase
+{
+public:
+       /// constructor
+       FilterColor (void);
+       /// destructor
+       virtual ~FilterColor (void) {}
+
+       /// get color matrix
+       ColorMatrix & getMatrix (void) { return m_matrix; }
+       /// set color matrix
+       void setMatrix (ColorMatrix & mat);
+
+protected:
+       ///  color calculation matrix
+       ColorMatrix m_matrix;
+
+       /// calculate one color component
+       unsigned int calcColor (unsigned int val, short idx)
+       {
+               return (((m_matrix[idx][0]  * (val & 0xFF) + m_matrix[idx][1] * ((val >> 8) & 0xFF)
+                       + m_matrix[idx][2] * ((val >> 16) & 0xFF) + m_matrix[idx][3] * ((val >> 24) & 0xFF)
+                       + m_matrix[idx][4]) >> 8) & 0xFF) << (idx << 3);
+       }
+
+       /// filter pixel template, source int buffer
+       template <class SRC> unsigned int tFilter (SRC src, short x, short y,
+               short * size, unsigned int pixSize, unsigned int val)
+       {
+               // return calculated color
+               return calcColor(val, 0) | calcColor(val, 1) | calcColor(val, 2)
+                       | calcColor(val, 3);
+       }
+
+       /// virtual filtering function for byte source
+       virtual unsigned int filter (unsigned char * src, short x, short y,
+               short * size, unsigned int pixSize, unsigned int val = 0)
+       { return tFilter(src, x, y, size, pixSize, val); }
+       /// virtual filtering function for unsigned int source
+       virtual unsigned int filter (unsigned int * src, short x, short y,
+               short * size, unsigned int pixSize, unsigned int val = 0)
+       { return tFilter(src, x, y, size, pixSize, val); }
+};
+
+
+/// type for color levels
+typedef unsigned long ColorLevel[4][3];
+
+/// pixel filter for color calculation
+class FilterLevel : public FilterBase
+{
+public:
+       /// constructor
+       FilterLevel (void);
+       /// destructor
+       virtual ~FilterLevel (void) {}
+
+       /// get color matrix
+       ColorLevel & getLevels (void) { return levels; }
+       /// set color matrix
+       void setLevels (ColorLevel & lev);
+
+protected:
+       ///  color calculation matrix
+       ColorLevel levels;
+
+       /// calculate one color component
+       unsigned int calcColor (unsigned int val, short idx)
+       {
+               unsigned int col = val & (0xFF << (idx << 3));
+               if (col <= levels[idx][0]) col = 0;
+               else if (col >= levels[idx][1]) col = 0xFF << (idx << 3);
+               else if (idx < 3) col = (((col - levels[idx][0]) << 8) / levels[idx][2]) & (0xFF << (idx << 3));
+               else col = (((col - levels[idx][0]) / levels[idx][2]) << 8) & (0xFF << (idx << 3));
+               return col; 
+       }
+
+       /// filter pixel template, source int buffer
+       template <class SRC> unsigned int tFilter (SRC src, short x, short y,
+               short * size, unsigned int pixSize, unsigned int val)
+       {
+               // return calculated color
+               return calcColor(val, 0) | calcColor(val, 1) | calcColor(val, 2)
+                       | calcColor(val, 3);
+       }
+
+       /// virtual filtering function for byte source
+       virtual unsigned int filter (unsigned char * src, short x, short y,
+               short * size, unsigned int pixSize, unsigned int val = 0)
+       { return tFilter(src, x, y, size, pixSize, val); }
+       /// virtual filtering function for unsigned int source
+       virtual unsigned int filter (unsigned int * src, short x, short y,
+               short * size, unsigned int pixSize, unsigned int val = 0)
+       { return tFilter(src, x, y, size, pixSize, val); }
+};
+
+
+#endif
\ No newline at end of file
diff --git a/source/gameengine/VideoTexture/FilterNormal.cpp b/source/gameengine/VideoTexture/FilterNormal.cpp
new file mode 100644 (file)
index 0000000..5eeb63b
--- /dev/null
@@ -0,0 +1,162 @@
+/* $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.
+-----------------------------------------------------------------------------
+*/
+
+
+#include <Python.h>
+#include <structmember.h>
+
+#include "FilterNormal.h"
+
+#include "FilterBase.h"
+#include "PyTypeList.h"
+
+// implementation FilterNormal
+
+// constructor
+FilterNormal::FilterNormal (void) : m_colShift(0)
+{
+       // set default depth
+       setDepth(4);
+}
+
+// set color shift
+void FilterNormal::setColor (unsigned short colIdx)
+{
+       // check validity of index
+       if (colIdx < 3)
+               // set color shift
+               m_colShift = colIdx << 3;
+}
+
+// set depth
+void FilterNormal::setDepth (float depth)
+{
+       m_depth = depth;
+       m_depthScale = depth / depthScaleKoef;
+}
+
+
+// cast Filter pointer to FilterNormal
+inline FilterNormal * getFilter (PyFilter * self)
+{ return static_cast<FilterNormal*>(self->m_filter); }
+
+
+// python methods and get/sets
+
+// get index of color used to calculate normal
+static PyObject * getColor (PyFilter * self, void * closure)
+{
+       return Py_BuildValue("H", getFilter(self)->getColor());
+}
+
+// set index of color used to calculate normal
+static int setColor (PyFilter * self, PyObject * value, void * closure)
+{
+       // check validity of parameter
+       if (value == NULL || !PyInt_Check(value))
+       {
+               PyErr_SetString(PyExc_TypeError, "The value must be a int");
+               return -1;
+       }
+       // set color index
+       getFilter(self)->setColor((unsigned short)(PyInt_AsLong(value)));
+       // success
+       return 0;
+}
+
+
+// get depth
+static PyObject * getDepth (PyFilter * self, void * closure)
+{
+       return Py_BuildValue("f", getFilter(self)->getDepth());
+}
+
+// set depth
+static int setDepth (PyFilter * self, PyObject * value, void * closure)
+{
+       // check validity of parameter
+       if (value == NULL || !PyFloat_Check(value))
+       {
+               PyErr_SetString(PyExc_TypeError, "The value must be a float");
+               return -1;
+       }
+       // set depth
+       getFilter(self)->setDepth(float(PyFloat_AsDouble(value)));
+       // success
+       return 0;
+}
+
+
+// attributes structure
+static PyGetSetDef filterNormalGetSets[] =
+{ 
+       {"colorIdx", (getter)getColor, (setter)setColor, "index of color used to calculate normal (0 - red, 1 - green, 2 - blue)", NULL},
+       {"depth", (getter)getDepth, (setter)setDepth, "depth of relief", NULL},
+       // attributes from FilterBase class
+       {"previous", (getter)Filter_getPrevious, (setter)Filter_setPrevious, "previous pixel filter", NULL},
+       {NULL}
+};
+
+// define python type
+PyTypeObject FilterNormalType =
+{ 
+       PyObject_HEAD_INIT(NULL)
+       0,                         /*ob_size*/
+       "VideoTexture.FilterNormal",   /*tp_name*/
+       sizeof(PyFilter),          /*tp_basicsize*/
+       0,                         /*tp_itemsize*/
+       (destructor)Filter_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*/
+       "Filter for Blue Screen objects",       /* tp_doc */
+       0,                             /* tp_traverse */
+       0,                             /* tp_clear */
+       0,                             /* tp_richcompare */
+       0,                             /* tp_weaklistoffset */
+       0,                             /* tp_iter */
+       0,                             /* tp_iternext */
+       NULL,                /* tp_methods */
+       0,                   /* tp_members */
+       filterNormalGetSets,           /* tp_getset */
+       0,                         /* tp_base */
+       0,                         /* tp_dict */
+       0,                         /* tp_descr_get */
+       0,                         /* tp_descr_set */
+       0,                         /* tp_dictoffset */
+       (initproc)Filter_init<FilterNormal>,     /* tp_init */
+       0,                         /* tp_alloc */
+       Filter_allocNew,           /* tp_new */
+};
+
diff --git a/source/gameengine/VideoTexture/FilterNormal.h b/source/gameengine/VideoTexture/FilterNormal.h
new file mode 100644 (file)
index 0000000..fa61f04
--- /dev/null
@@ -0,0 +1,98 @@
+/* $Id$
+-----------------------------------------------------------------------------
+This source file is part of blendTex 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.
+-----------------------------------------------------------------------------
+*/
+
+#if !defined FILTERNORMAL_H
+#define FILTERNORMAL_H
+
+#include "Common.h"
+
+#include "FilterBase.h"
+
+
+// scale constants for normals
+const float depthScaleKoef = 255.0;
+const float normScaleKoef = float(depthScaleKoef / 2.0);
+
+
+/// pixel filter for normal mapping
+class FilterNormal : public FilterBase
+{
+public:
+       /// constructor
+       FilterNormal (void);
+       /// destructor
+       virtual ~FilterNormal (void) {}
+
+       /// get index of color used to calculate normals
+       unsigned short getColor (void) { return m_colShift >> 3; }
+       /// set index of color used to calculate normals
+       void setColor (unsigned short colIdx);
+
+       /// get depth
+       float getDepth (void) { return m_depth; }
+       /// set depth
+       void setDepth (float depth);
+
+protected:
+       /// depth of normal relief
+       float m_depth;
+       /// scale to calculate normals
+       float m_depthScale;
+
+       /// shift to used color component
+       unsigned short m_colShift;
+
+       /// filter pixel, source int buffer
+       template <class SRC> unsigned int tFilter (SRC * src, short x, short y,
+               short * size, unsigned int pixSize, unsigned int val = 0)
+       {
+               // get value of required color
+               int actPix = int((val >> m_colShift) & 0xFF);
+               // get upper and left pixel from actual pixel
+               int upPix = y > 0 ? int((convertPrevious(src - pixSize * size[0], x, y - 1,
+                       size, pixSize) >> m_colShift) & 0xFF) : actPix;
+               int leftPix = x > 0 ? int((convertPrevious(src - pixSize, x - 1, y, size, pixSize)
+                       >> m_colShift) & 0xFF) : actPix;
+               // height differences (from blue color)
+               float dx = (actPix - leftPix) * m_depthScale;
+               float dy = (actPix - upPix) * m_depthScale;
+               // normalize vector
+               float dz = float(normScaleKoef / sqrt(dx * dx + dy * dy + 1.0));
+               dx = dx * dz + normScaleKoef;
+               dy = dy * dz + normScaleKoef;
+               dz += normScaleKoef;
+               // return normal vector converted to color
+               return 0xFF000000 | int(dz) << 16 | int(dy) << 8 | int(dx);
+       }
+
+       /// filter pixel, source byte buffer
+       virtual unsigned int filter (unsigned char * src, short x, short y,
+               short * size, unsigned int pixSize, unsigned int val = 0)
+       { return tFilter(src, x, y, size, pixSize, val); }
+       /// filter pixel, source int buffer
+       virtual unsigned int filter (unsigned int * src, short x, short y,
+               short * size, unsigned int pixSize, unsigned int val = 0)
+       { return tFilter(src, x, y, size, pixSize, val); }
+};
+
+
+#endif
\ No newline at end of file
diff --git a/source/gameengine/VideoTexture/FilterSource.cpp b/source/gameengine/VideoTexture/FilterSource.cpp
new file mode 100644 (file)
index 0000000..4b96a97
--- /dev/null
@@ -0,0 +1,125 @@
+/* $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 <Python.h>
+#include <structmember.h>
+
+#include "FilterSource.h"
+
+#include "FilterBase.h"
+#include "PyTypeList.h"
+
+
+// FilterRGB24
+
+// define python type
+PyTypeObject FilterRGB24Type =
+{ 
+       PyObject_HEAD_INIT(NULL)
+       0,                         /*ob_size*/
+       "VideoTexture.FilterRGB24",   /*tp_name*/
+       sizeof(PyFilter),          /*tp_basicsize*/
+       0,                         /*tp_itemsize*/
+       (destructor)Filter_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*/
+       "Source filter RGB24 objects",       /* tp_doc */
+       0,                             /* tp_traverse */
+       0,                             /* tp_clear */
+       0,                             /* tp_richcompare */
+       0,                             /* tp_weaklistoffset */
+       0,                             /* tp_iter */
+       0,                             /* tp_iternext */
+       NULL,                /* tp_methods */
+       0,                   /* tp_members */
+       NULL,             /* tp_getset */
+       0,                         /* tp_base */
+       0,                         /* tp_dict */
+       0,                         /* tp_descr_get */
+       0,                         /* tp_descr_set */
+       0,                         /* tp_dictoffset */
+       (initproc)Filter_init<FilterRGB24>,     /* tp_init */
+       0,                         /* tp_alloc */
+       Filter_allocNew,           /* tp_new */
+};
+
+// FilterBGR24
+
+// define python type
+PyTypeObject FilterBGR24Type =
+{ 
+       PyObject_HEAD_INIT(NULL)
+       0,                         /*ob_size*/
+       "VideoTexture.FilterBGR24",   /*tp_name*/
+       sizeof(PyFilter),          /*tp_basicsize*/
+       0,                         /*tp_itemsize*/
+       (destructor)Filter_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*/
+       "Source filter BGR24 objects",       /* tp_doc */
+       0,                             /* tp_traverse */
+       0,                             /* tp_clear */
+       0,                             /* tp_richcompare */
+       0,                             /* tp_weaklistoffset */
+       0,                             /* tp_iter */
+       0,                             /* tp_iternext */
+       NULL,                /* tp_methods */
+       0,                   /* tp_members */
+       NULL,             /* tp_getset */
+       0,                         /* tp_base */
+       0,                         /* tp_dict */
+       0,                         /* tp_descr_get */
+       0,                         /* tp_descr_set */
+       0,                         /* tp_dictoffset */
+       (initproc)Filter_init<FilterBGR24>,     /* tp_init */
+       0,                         /* tp_alloc */
+       Filter_allocNew,           /* tp_new */
+};
+
diff --git a/source/gameengine/VideoTexture/FilterSource.h b/source/gameengine/VideoTexture/FilterSource.h
new file mode 100644 (file)
index 0000000..b181862
--- /dev/null
@@ -0,0 +1,233 @@
+/* $Id$
+-----------------------------------------------------------------------------
+This source file is part of blendTex 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.
+-----------------------------------------------------------------------------
+*/
+
+#if !defined FILTERSOURCE_H
+#define FILTERSOURCE_H
+
+#include "Common.h"
+
+#include "FilterBase.h"
+
+
+/// class for RGB24 conversion
+class FilterRGB24 : public FilterBase
+{
+public:
+       /// constructor
+       FilterRGB24 (void) {}
+       /// destructor
+       virtual ~FilterRGB24 (void) {}
+
+       /// get source pixel size
+       virtual unsigned int getPixelSize (void) { return 3; }
+
+protected:
+       /// filter pixel, source byte buffer
+       virtual unsigned int filter (unsigned char * src, short x, short y,
+               short * size, unsigned int pixSize, unsigned int val)
+       { return 0xFF000000 | src[0] << 16 | src[1] << 8 | src[2]; }
+};
+
+
+/// class for BGR24 conversion
+class FilterBGR24 : public FilterBase
+{
+public:
+       /// constructor
+       FilterBGR24 (void) {}
+       /// destructor
+       virtual ~FilterBGR24 (void) {}
+
+       /// get source pixel size
+       virtual unsigned int getPixelSize (void) { return 3; }
+
+protected:
+       /// filter pixel, source byte buffer
+       virtual unsigned int filter (unsigned char * src, short x, short y,
+               short * size, unsigned int pixSize, unsigned int val)
+       { return 0xFF000000 | src[2] << 16 | src[1] << 8 | src[0]; }
+};
+
+
+/// class for YV12 conversion
+class FilterYV12 : public FilterBase
+{
+public:
+       /// constructor
+       FilterYV12 (void) {}
+       /// destructor
+       virtual ~FilterYV12 (void) {}
+
+       /// get source pixel size
+       virtual unsigned int getPixelSize (void) { return 1; }
+
+       /// set pointers to color buffers
+       void setBuffs (unsigned char * buff, short * size)
+       {
+               unsigned int buffSize = size[0] * size[1];
+               m_buffV = buff + buffSize;
+               m_buffU = m_buffV + (buffSize >> 2);
+               m_pitchUV = size[0] >> 1;
+       }
+
+protected:
+       /// begin of V buffer
+       unsigned char * m_buffV;
+       /// begin of U buffer
+       unsigned char * m_buffU;
+       /// pitch for V & U buffers
+       short m_pitchUV;
+
+       /// interpolation function
+       int interpol (int a, int b, int c, int d)
+       { return (9 * (b + c) - a - d + 8) >> 4; }
+
+       /// common horizontal interpolation
+       int interpolH (unsigned char * src)
+       { return interpol(*(src-1), *src, *(src+1), *(src+2)); }
+
+       /// common vertical interpolation
+       int interpolV (unsigned char * src)
+       { return interpol(*(src-m_pitchUV), *src, *(src+m_pitchUV), *(src+2*m_pitchUV)); }
+
+       /// common joined vertical and horizontal interpolation
+       int interpolVH (unsigned char * src)
+       {
+               return interpol(interpolV(src-1), interpolV(src), interpolV(src+1),
+                       interpolV(src+2));
+       }
+
+       /// is pixel on edge
+       bool isEdge (short x, short y, short * size)
+       { return x <= 1 || x >= size[0] - 4 || y <= 1 || y >= size[1] - 4; }
+
+       /// get the first parameter on the low edge
+       unsigned char * interParA (unsigned char * src, short x, short size, short shift)
+       { return x > 1 ? src - shift : src; }
+       /// get the third parameter on the high edge
+       unsigned char * interParC (unsigned char * src, short x, short size, short shift)
+       { return x < size - 2 ? src + shift : src; }
+       /// get the fourth parameter on the high edge
+       unsigned char * interParD (unsigned char * src, short x, short size, short shift)
+       { return x < size - 4 ? src + 2 * shift : x < size - 2 ? src + shift : src; }
+
+       /// horizontal interpolation on edges
+       int interpolEH (unsigned char * src, short x, short size)
+       { 
+               return interpol(*interParA(src, x, size, 1), *src,
+                       *interParC(src, x, size, 1), *interParD(src, x, size, 1));
+       }
+
+       /// vertical interpolation on edges
+       int interpolEV (unsigned char * src, short y, short size)
+       { 
+               return interpol(*interParA(src, y, size, m_pitchUV), *src,
+                       *interParC(src, y, size, m_pitchUV), *interParD(src, y, size, m_pitchUV));
+       }
+
+       /// joined vertical and horizontal interpolation on edges
+       int interpolEVH (unsigned char * src, short x, short y, short * size)
+       {
+               return interpol(interpolEV(interParA(src, x, size[0], 1), y, size[1]),
+                       interpolEV(src, y, size[1]), interpolEV(interParC(src, x, size[0], 1), y, size[1]),
+                       interpolEV(interParD(src, x, size[0], 1), y, size[1]));
+       }
+
+
+       /// filter pixel, source byte buffer
+       virtual unsigned int filter (unsigned char * src, short x, short y,
+               short * size, unsigned int pixSize, unsigned int val)
+       {
+               // V & U offset
+               long offset = (x >> 1) + m_pitchUV * (y >> 1);
+               // get modified YUV -> CDE: C = Y - 16; D = U - 128; E = V - 128
+               int c = *src - 16;
+               int d = m_buffU[offset] - 128;
+               int e = m_buffV[offset] - 128;
+               // if horizontal interpolation is needed
+               if ((x & 1) == 1)
+                       // if vertical interpolation is needed too
+                       if ((y & 1) == 1)
+                               // if this pixel is on the edge
+                               if (isEdge(x, y, size))
+                               {
+                                       // get U & V from edge
+                                       d = interpolEVH(m_buffU + offset, x, y, size) - 128;
+                                       e = interpolEVH(m_buffV + offset, x, y, size) - 128;
+                               }
+                               // otherwise get U & V from inner range
+                               else
+                               {
+                                       d = interpolVH(m_buffU + offset) - 128;
+                                       e = interpolVH(m_buffV + offset) - 128;
+                               }
+                               // otherwise use horizontal interpolation only
+                       else
+                               // if this pixel is on the edge
+                               if (isEdge(x, y, size))
+                               {
+                                       // get U & V from edge
+                                       d = interpolEH(m_buffU + offset, x, size[0]) - 128;
+                                       e = interpolEH(m_buffV + offset, x, size[0]) - 128;
+                               }
+                               // otherwise get U & V from inner range
+                               else
+                               {
+                                       d = interpolH(m_buffU + offset) - 128;
+                                       e = interpolH(m_buffV + offset) - 128;
+                               }
+                               // otherwise if only vertical interpolation is needed
+               else if ((y & 1) == 1)
+                       // if this pixel is on the edge
+                       if (isEdge(x, y, size))
+                       {
+                               // get U & V from edge
+                               d = interpolEV(m_buffU + offset, y, size[1]) - 128;
+                               e = interpolEV(m_buffV + offset, y, size[1]) - 128;
+                       }
+                       // otherwise get U & V from inner range
+                       else
+                       {
+                               d = interpolV(m_buffU + offset) - 128;
+                               e = interpolV(m_buffV + offset) - 128;
+                       }
+               // convert to RGB
+               // R = clip(( 298 * C           + 409 * E + 128) >> 8)
+               // G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8)
+               // B = clip(( 298 * C + 516 * D           + 128) >> 8)
+               int red = (298 * c + 409 * e + 128) >> 8;
+               if (red >= 0x100) red = 0xFF;
+               else if (red < 0) red = 0;
+               int green = 298 * c - 100 * d - 208 * e;
+               if (green > 0x10000) green = 0xFF00;
+               else if (green < 0) green = 0;
+               int blue = (298 * c + 516 * d + 128) << 8;
+               if (blue > 0x1000000) blue = 0xFF0000;
+               else if (blue < 0) blue = 0;
+               // return result
+               return 0xFF000000 | blue & 0xFF0000 | green & 0xFF00
+                       | red & 0xFF;
+       }
+};
+
+
+#endif
\ No newline at end of file
diff --git a/source/gameengine/VideoTexture/ImageBase.cpp b/source/gameengine/VideoTexture/ImageBase.cpp
new file mode 100644 (file)
index 0000000..28e7ad4
--- /dev/null
@@ -0,0 +1,529 @@
+/* $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.
+-----------------------------------------------------------------------------
+*/
+
+#include "ImageBase.h"
+
+#include <vector>
+#include <string.h>
+
+#include <Python.h>
+#include <structmember.h>
+
+#include "FilterBase.h"
+
+#include "Exception.h"
+
+
+
+// ImageBase class implementation
+
+// constructor
+ImageBase::ImageBase (bool staticSrc) : m_image(NULL), m_imgSize(0),
+m_avail(false), m_scale(false), m_scaleChange(false), m_flip(false),
+m_staticSources(staticSrc), m_pyfilter(NULL)
+{
+       m_size[0] = m_size[1] = 0;
+}
+
+
+// destructor
+ImageBase::~ImageBase (void)
+{
+       // release image
+       delete [] m_image;
+}
+
+
+// release python objects
+bool ImageBase::release (void)
+{
+       // iterate sources
+       for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
+       {
+               // release source object
+               delete *it;
+               *it = NULL;
+       }
+       // release filter object
+       Py_XDECREF(m_pyfilter);
+       m_pyfilter = NULL;
+       return true;
+}
+
+
+// get image
+unsigned int * ImageBase::getImage (unsigned int texId)
+{
+       // if image is not available
+       if (!m_avail)
+       {
+               // if there are any sources
+               if (!m_sources.empty())
+               {
+                       // get images from sources
+                       for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
+                               // get source image
+                               (*it)->getImage();
+                       // init image
+                       init(m_sources[0]->getSize()[0], m_sources[0]->getSize()[1]);
+               }
+               // calculate new image
+               calcImage(texId);
+       }
+       // if image is available, return it, otherwise NULL
+       return m_avail ? m_image : NULL;
+}
+
+
+// refresh image source
+void ImageBase::refresh (void)
+{
+       // invalidate this image
+       m_avail = false;
+       // refresh all sources
+       for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
+               (*it)->refresh();
+}
+
+
+// get source object
+PyImage * ImageBase::getSource (const char * id)
+{
+       // find source
+       ImageSourceList::iterator src = findSource(id);
+       // return it, if found
+       return src != m_sources.end() ? (*src)->getSource() : NULL;
+}
+
+
+// set source object
+bool ImageBase::setSource (const char * id, PyImage * source)
+{
+       // find source
+       ImageSourceList::iterator src = findSource(id);
+       // check source loop
+       if (source != NULL && source->m_image->loopDetect(this))
+               return false;
+       // if found, set new object
+       if (src != m_sources.end())
+               // if new object is not empty or sources are static
+               if (source != NULL || m_staticSources)
+                       // replace previous source
+                       (*src)->setSource(source);
+               // otherwise delete source
+               else
+                       m_sources.erase(src);
+       // if source is not found and adding is allowed
+       else
+               if (!m_staticSources)
+               {
+                       // create new source
+                       ImageSource * newSrc = newSource(id);
+                       newSrc->setSource(source);
+                       // if source was created, add it to source list
+                       if (newSrc != NULL) m_sources.push_back(newSrc);
+               }
+               // otherwise source wasn't set
+               else 
+                       return false;
+       // source was set
+       return true;
+}
+
+
+// set pixel filter
+void ImageBase::setFilter (PyFilter * filt)
+{
+       // reference new filter
+       if (filt != NULL) Py_INCREF(filt);
+       // release previous filter
+       Py_XDECREF(m_pyfilter);
+       // set new filter
+       m_pyfilter = filt;
+}
+
+
+// initialize image data
+void ImageBase::init (short width, short height)
+{
+       // if image has to be scaled
+       if (m_scale)
+       {
+               // recalc sizes of image
+               width = calcSize(width);
+               height = calcSize(height);
+       }
+       // if sizes differ
+       if (width != m_size[0] || height != m_size[1])
+       {
+               // new buffer size
+               unsigned int newSize = width * height;
+               // if new buffer is larger than previous
+               if (newSize > m_imgSize)
+               {
+                       // set new buffer size
+                       m_imgSize = newSize;
+                       // release previous and create new buffer
+                       delete [] m_image;
+                       m_image = new unsigned int[m_imgSize];
+               }
+               // new image size
+               m_size[0] = width;
+               m_size[1] = height;
+               // scale was processed
+               m_scaleChange = false;
+       }
+}
+
+
+// find source
+ImageSourceList::iterator ImageBase::findSource (const char * id)
+{
+       // iterate sources
+       ImageSourceList::iterator it;
+       for (it = m_sources.begin(); it != m_sources.end(); ++it)
+               // if id matches, return iterator
+               if ((*it)->is(id)) return it;
+       // source not found
+       return it;
+}
+
+
+// check sources sizes
+bool ImageBase::checkSourceSizes (void)
+{
+       // reference size
+       short * refSize = NULL;
+       // iterate sources
+       for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
+       {
+               // get size of current source
+               short * curSize = (*it)->getSize();
+               // if size is available and is not empty
+               if (curSize[0] != 0 && curSize[1] != 0)
+                       // if reference size is not set
+                       if (refSize == NULL)
+                               // set current size as reference
+                               refSize = curSize;
+               // otherwise check with current size
+                       else if (curSize[0] != refSize[0] || curSize[1] != refSize[1])
+                               // if they don't match, report it
+                               return false;
+       }
+       // all sizes match
+       return true;
+}
+
+
+// compute nearest power of 2 value
+short ImageBase::calcSize (short size)
+{
+       // while there is more than 1 bit in size value
+       while ((size & (size - 1)) != 0)
+               // clear last bit
+               size = size & (size - 1);
+       // return result
+       return size;
+}
+
+
+// perform loop detection
+bool ImageBase::loopDetect (ImageBase * img)
+{
+       // if this object is the same as parameter, loop is detected
+       if (this == img) return true;
+       // check all sources
+       for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
+               // if source detected loop, return this result
+               if ((*it)->getSource() != NULL && (*it)->getSource()->m_image->loopDetect(img))
+                       return true;
+       // no loop detected
+       return false;
+}
+
+
+// ImageSource class implementation
+
+// constructor
+ImageSource::ImageSource (const char * id) : m_source(NULL), m_image(NULL)
+{
+       // copy id
+       int idx;
+       for (idx = 0; id[idx] != '\0' && idx < SourceIdSize - 1; ++idx)
+               m_id[idx] = id[idx];
+       m_id[idx] = '\0';
+}
+
+// destructor
+ImageSource::~ImageSource (void)
+{
+       // release source
+       setSource(NULL);
+}
+
+
+// compare id
+bool ImageSource::is (const char * id)
+{
+       for (char * myId = m_id; *myId != '\0'; ++myId, ++id)
+               if (*myId != *id) return false;
+       return *id == '\0';
+}
+
+
+// set source object
+void ImageSource::setSource (PyImage * source)
+{
+       // reference new source
+       if (source != NULL) Py_INCREF(source);
+       // release previous source
+       Py_XDECREF(m_source);
+       // set new source
+       m_source = source;
+}
+
+
+// get image from source
+unsigned int * ImageSource::getImage (void)
+{
+       // if source is available
+       if (m_source != NULL)
+               // get image from source
+               m_image = m_source->m_image->getImage();
+       // otherwise reset buffer
+       else
+               m_image = NULL;
+       // return image
+       return m_image;
+}
+
+
+// refresh source
+void ImageSource::refresh (void)
+{
+       // if source is available, refresh it
+       if (m_source != NULL) m_source->m_image->refresh();
+}
+
+
+
+// list of image types
+PyTypeList pyImageTypes;
+
+
+
+// functions for python interface
+
+// object allocation
+PyObject * Image_allocNew (PyTypeObject * type, PyObject * args, PyObject * kwds)
+{
+       // allocate object
+       PyImage * self = reinterpret_cast<PyImage*>(type->tp_alloc(type, 0));
+       // initialize object structure
+       self->m_image = NULL;
+       // return allocated object
+       return reinterpret_cast<PyObject*>(self);
+}
+
+// object deallocation
+void Image_dealloc (PyImage * self)
+{
+       // release object attributes
+       if (self->m_image != NULL)
+       {
+               // if release requires deleting of object, do it
+               if (self->m_image->release())
+                       delete self->m_image;
+               self->m_image = NULL;
+       }
+}
+
+// get image data
+PyObject * Image_getImage (PyImage * self, void * closure)
+{
+       try
+       {
+               // get image
+               unsigned int * image = self->m_image->getImage();
+               return Py_BuildValue("s#", image, self->m_image->getBuffSize());
+       }
+       catch (Exception & exp)
+       {
+               exp.report();
+       }
+       Py_RETURN_NONE;
+}
+
+// get image size
+PyObject * Image_getSize (PyImage * self, void * closure)
+{
+       return Py_BuildValue("(hh)", self->m_image->getSize()[0],
+               self->m_image->getSize()[1]);
+}
+
+// refresh image
+PyObject * Image_refresh (PyImage * self)
+{
+       self->m_image->refresh();
+       Py_RETURN_NONE;
+}
+
+// get scale
+PyObject * Image_getScale (PyImage * self, void * closure)
+{
+       if (self->m_image != NULL && self->m_image->getScale()) Py_RETURN_TRUE;
+       else Py_RETURN_FALSE;
+}
+
+// set scale
+int Image_setScale (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->setScale(value == Py_True);
+       // success
+       return 0;
+}
+
+// get flip
+PyObject * Image_getFlip (PyImage * self, void * closure)
+{
+       if (self->m_image != NULL && self->m_image->getFlip()) Py_RETURN_TRUE;
+       else Py_RETURN_FALSE;
+}
+
+// set flip
+int Image_setFlip (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->setFlip(value == Py_True);
+       // success
+       return 0;
+}
+
+
+// get filter source object
+PyObject * Image_getSource (PyImage * self, PyObject * args)
+{
+       // get arguments
+       char * id;
+       if (self->m_image != NULL && PyArg_ParseTuple(args, "s", &id))
+       {
+               // get source object
+               PyObject * src = reinterpret_cast<PyObject*>(self->m_image->getSource(id));
+               // if source is available
+               if (src != NULL)
+               {
+                       // return source
+                       Py_INCREF(src);
+                       return src;
+               }
+       }
+       // source was not found
+       Py_RETURN_NONE;
+}
+
+
+// set filter source object
+PyObject * Image_setSource (PyImage * self, PyObject * args)
+{
+       // get arguments
+       char * id;
+       PyObject * obj;
+       if (self->m_image != NULL && PyArg_ParseTuple(args, "sO", &id, &obj))
+       {
+               // check type of object
+               if (pyImageTypes.in(obj->ob_type))
+               {
+                       // convert to image struct
+                       PyImage * img = reinterpret_cast<PyImage*>(obj);
+                       // set source
+                       if (!self->m_image->setSource(id, img))
+                       {
+                               // if not set, retport error
+                               PyErr_SetString(PyExc_RuntimeError, "Invalid source or id");
+                               return NULL;
+                       }
+               }
+               // else report error
+               else
+               {
+                       PyErr_SetString(PyExc_RuntimeError, "Invalid type of object");
+                       return NULL;
+               }
+       }
+       // return none
+       Py_RETURN_NONE;
+}
+
+
+// get pixel filter object
+PyObject * Image_getFilter (PyImage * self, void * closure)
+{
+       // if image object is available
+       if (self->m_image != NULL)
+       {
+               // pixel filter object
+               PyObject * filt = reinterpret_cast<PyObject*>(self->m_image->getFilter());
+               // if filter is present
+               if (filt != NULL)
+               {
+                       // return it
+                       Py_INCREF(filt);
+                       return filt;
+               }
+       }
+       // otherwise return none
+       Py_RETURN_NONE;
+}
+
+
+// set pixel filter object
+int Image_setFilter (PyImage * self, PyObject * value, void * closure)
+{
+       // if image object is available
+       if (self->m_image != NULL)
+       {
+               // check new value
+               if (value == NULL || !pyFilterTypes.in(value->ob_type))
+               {
+                       // report value error
+                       PyErr_SetString(PyExc_TypeError, "Invalid type of value");
+                       return -1;
+               }
+               // set new value
+               self->m_image->setFilter(reinterpret_cast<PyFilter*>(value));
+       }
+       // return success
+       return 0;
+}
\ No newline at end of file
diff --git a/source/gameengine/VideoTexture/ImageBase.h b/source/gameengine/VideoTexture/ImageBase.h
new file mode 100644 (file)
index 0000000..817223c
--- /dev/null
@@ -0,0 +1,349 @@
+/* $Id$
+-----------------------------------------------------------------------------
+This source file is part of blendTex 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.
+-----------------------------------------------------------------------------
+*/
+
+#if !defined IMAGEBASE_H
+#define IMAGEBASE_H
+
+#include "Common.h"
+
+#include <vector>
+#include <Python.h>
+
+#include "PyTypeList.h"
+
+#include "FilterBase.h"
+
+
+// forward declarations
+struct PyImage;
+class ImageSource;
+
+
+/// type for list of image sources
+typedef std::vector<ImageSource*> ImageSourceList;
+
+
+/// base class for image filters
+class ImageBase
+{
+public:
+       /// constructor
+       ImageBase (bool staticSrc = false);
+       /// destructor
+       virtual ~ImageBase (void);
+       /// release contained objects, if returns true, object should be deleted
+       virtual bool release (void);
+
+       /// get image
+       unsigned int * getImage (unsigned int texId = 0);
+       /// get image size
+       short * getSize (void) { return m_size; }
+       /// get image buffer size
+       unsigned long getBuffSize (void)
+       { return m_size[0] * m_size[1] * sizeof(unsigned int); }
+       /// refresh image - invalidate its current content
+       virtual void refresh (void);
+
+       /// get scale
+       bool getScale (void) { return m_scale; }
+       /// set scale
+       void setScale (bool scale) { m_scale = scale; m_scaleChange = true; }
+       /// get vertical flip
+       bool getFlip (void) { return m_flip; }
+       /// set vertical flip
+       void setFlip (bool flip) { m_flip = flip; }
+
+       /// get source object
+       PyImage * getSource (const char * id);
+       /// set source object, return true, if source was set
+       bool setSource (const char * id, PyImage * source);
+
+       /// get pixel filter
+       PyFilter * getFilter (void) { return m_pyfilter; }
+       /// set pixel filter
+       void setFilter (PyFilter * filt);
+
+       /// calculate size (nearest power of 2)
+       static short calcSize (short size);
+
+protected:
+       /// image buffer
+       unsigned int * m_image;
+       /// image buffer size
+       unsigned int m_imgSize;
+       /// image size
+       short m_size[2];
+       /// image is available
+       bool m_avail;
+
+       /// scale image to power 2 sizes
+       bool m_scale;
+       /// scale was changed
+       bool m_scaleChange;
+       /// flip image vertically
+       bool m_flip;
+
+       /// source image list
+       ImageSourceList m_sources;
+       /// flag for disabling addition and deletion of sources
+       bool m_staticSources;
+
+       /// pixel filter
+       PyFilter * m_pyfilter;
+
+       /// initialize image data
+       void init (short width, short height);
+
+       /// find source
+       ImageSourceList::iterator findSource (const char * id);
+
+       /// create new source
+       virtual ImageSource * newSource (const char * id) { return NULL; }
+
+       /// check source sizes
+       bool checkSourceSizes (void);
+
+       /// calculate image from sources and set its availability
+       virtual void calcImage (unsigned int texId) {}
+
+       /// perform loop detection
+       bool loopDetect (ImageBase * img);
+
+       /// template for image conversion
+       template<class FLT, class SRC> void convImage (FLT & filter, SRC srcBuff,
+               short * srcSize)
+       {
+               // destination buffer
+               unsigned int * dstBuff = m_image;
+               // pixel size from filter
+               unsigned int pixSize = filter.firstPixelSize();
+               // if no scaling is needed
+               if (srcSize[0] == m_size[0] && srcSize[1] == m_size[1])
+                       // if flipping isn't required
+                       if (!m_flip)
+                               // copy bitmap
+                               for (short y = 0; y < m_size[1]; ++y)
+                                       for (short x = 0; x < m_size[0]; ++x, ++dstBuff, srcBuff += pixSize)
+                                               // copy pixel
+                                               *dstBuff = filter.convert(srcBuff, x, y, srcSize, pixSize);
+               // otherwise flip image top to bottom
+                       else
+                       {
+                               // go to last row of image
+                               srcBuff += srcSize[0] * (srcSize[1] - 1) * pixSize;
+                               // copy bitmap
+                               for (short y = m_size[1] - 1; y >= 0; --y, srcBuff -= 2 * srcSize[0] * pixSize)
+                                       for (short x = 0; x < m_size[0]; ++x, ++dstBuff, srcBuff += pixSize)
+                                               // copy pixel
+                                               *dstBuff = filter.convert(srcBuff, x, y, srcSize, pixSize);
+                       }
+                       // else scale picture (nearest neighbour)
+               else
+               {
+                       // interpolation accumulator
+                       int accHeight = srcSize[1] >> 1;
+                       // if flipping is required
+                       if (m_flip)
+                               // go to last row of image
+                               srcBuff += srcSize[0] * (srcSize[1] - 1) * pixSize;
+                       // process image rows
+                       for (int y = 0; y < srcSize[1]; ++y)
+                       {
+                               // increase height accum
+                               accHeight += m_size[1];
+                               // if pixel row has to be drawn
+                               if (accHeight >= srcSize[1])
+                               {
+                                       // decrease accum
+                                       accHeight -= srcSize[1];
+                                       // width accum
+                                       int accWidth = srcSize[0] >> 1;
+                                       // process row
+                                       for (int x = 0; x < srcSize[0]; ++x)
+                                       {
+                                               // increase width accum
+                                               accWidth += m_size[0];
+                                               // if pixel has to be drawn
+                                               if (accWidth >= srcSize[0])
+                                               {
+                                                       // decrease accum
+                                                       accWidth -= srcSize[0];
+                                                       // convert pixel
+                                                       *dstBuff = filter.convert(srcBuff, x, m_flip ? srcSize[1] - y - 1 : y,
+                                                               srcSize, pixSize);
+                                                       // next pixel
+                                                       ++dstBuff;
+                                               }
+                                               // shift source pointer
+                                               srcBuff += pixSize;
+                                       }
+                               }
+                               // if pixel row will not be drawn
+                               else
+                                       // move source pointer to next row
+                                       srcBuff += pixSize * srcSize[0];
+                               // if y flipping is required
+                               if (m_flip)
+                                       // go to previous row of image
+                                       srcBuff -= 2 * pixSize * srcSize[0];
+                       }
+               }
+       }
+
+       // template for specific filter preprocessing
+       template <class F, class SRC> void filterImage (F & filt, SRC srcBuff, short * srcSize)
+       {
+               // find first filter in chain
+               FilterBase * firstFilter = NULL;
+               if (m_pyfilter != NULL) firstFilter = m_pyfilter->m_filter->findFirst();
+               // if first filter is available
+               if (firstFilter != NULL)
+               {
+                       // python wrapper for filter
+                       PyFilter pyFilt;
+                       pyFilt.m_filter = &filt;
+                       // set specified filter as first in chain
+                       firstFilter->setPrevious(&pyFilt, false);
+                       // convert video image
+                       convImage(*(m_pyfilter->m_filter), srcBuff, srcSize);
+                       // delete added filter
+                       firstFilter->setPrevious(NULL, false);
+               }
+               // otherwise use given filter for conversion
+               else convImage(filt, srcBuff, srcSize);
+               // source was processed
+               m_avail = true;
+       }
+};
+
+
+// python structure for image filter
+struct PyImage
+{
+       PyObject_HEAD
+       // source object
+       ImageBase * m_image;
+};
+
+
+// size of id
+const int SourceIdSize = 32;
+
+
+/// class for source of image
+class ImageSource
+{
+public:
+       /// constructor
+       ImageSource (const char * id);
+       /// destructor
+       virtual ~ImageSource (void);
+
+       /// get id
+       const char * getId (void) { return m_id; }
+       /// compare id to argument
+       bool is (const char * id);
+
+       /// get source object
+       PyImage * getSource (void) { return m_source; }
+       /// set source object
+       void setSource (PyImage * source);
+
+       /// get image from source
+       unsigned int * getImage (void);
+       /// get buffered image
+       unsigned int * getImageBuf (void) { return m_image; }
+       /// refresh source
+       void refresh (void);
+
+       /// get image size
+       short * getSize (void)
+       { 
+               static short defSize [] = {0, 0};
+               return m_source != NULL ? m_source->m_image->getSize() : defSize;
+       }
+
+protected:
+       /// id of source
+       char m_id [SourceIdSize];
+       /// pointer to source structure
+       PyImage * m_source;
+       /// buffered image from source
+       unsigned int * m_image;
+
+private:
+       /// default constructor is forbidden
+       ImageSource (void) {}
+};
+
+
+
+// list of python image types
+extern PyTypeList pyImageTypes;
+
+
+// functions for python interface
+
+// object initialization
+template <class T> static int Image_init (PyObject * pySelf, PyObject * args, PyObject * kwds)
+{
+       PyImage * self = reinterpret_cast<PyImage*>(pySelf);
+       // create source object
+       if (self->m_image != NULL) delete self->m_image;
+       self->m_image = new T();
+       // initialization succeded
+       return 0;
+}
+
+// object allocation
+PyObject * Image_allocNew (PyTypeObject * type, PyObject * args, PyObject * kwds);
+// object deallocation
+void Image_dealloc (PyImage * self);
+
+// get image data
+PyObject * Image_getImage (PyImage * self, void * closure);
+// get image size
+PyObject * Image_getSize (PyImage * self, void * closure);
+// refresh image - invalidate current content
+PyObject * Image_refresh (PyImage * self);
+
+// get scale
+PyObject * Image_getScale (PyImage * self, void * closure);
+// set scale
+int Image_setScale (PyImage * self, PyObject * value, void * closure);
+// get flip
+PyObject * Image_getFlip (PyImage * self, void * closure);
+// set flip
+int Image_setFlip (PyImage * self, PyObject * value, void * closure);
+
+// get filter source object
+PyObject * Image_getSource (PyImage * self, PyObject * args);
+// set filter source object
+PyObject * Image_setSource (PyImage * self, PyObject * args);
+
+// get pixel filter object
+PyObject * Image_getFilter (PyImage * self, void * closure);
+// set pixel filter object
+int Image_setFilter (PyImage * self, PyObject * value, void * closure);
+
+
+#endif
\ No newline at end of file
diff --git a/source/gameengine/VideoTexture/ImageBuff.cpp b/source/gameengine/VideoTexture/ImageBuff.cpp
new file mode 100644 (file)
index 0000000..f09514a
--- /dev/null
@@ -0,0 +1,166 @@
+/* $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 <Python.h>
+#include <structmember.h>
+
+#include "ImageBuff.h"
+
+#include "ImageBase.h"
+#include "FilterSource.h"
+
+
+// default filter
+FilterBGR24 defFilter;
+
+
+// load image from buffer
+void ImageBuff::load (unsigned char * img, short width, short height)
+{
+       // initialize image buffer
+       init(width, height);
+       // original size
+       short orgSize[2] = {width, height};
+       // is filter available
+       if (m_pyfilter != NULL)
+               // use it to process image
+               convImage(*(m_pyfilter->m_filter), img, orgSize);
+       else
+               // otherwise use default filter
+               convImage(defFilter, img, orgSize);
+       // image is available
+       m_avail = true;
+}
+
+
+
+// cast Image pointer to ImageBuff
+inline ImageBuff * getImageBuff (PyImage * self)
+{ return static_cast<ImageBuff*>(self->m_image); }
+
+
+// python methods
+
+// load image
+static PyObject * load (PyImage * self, PyObject * args)
+{
+       // parameters: string image buffer, its size, width, height
+       unsigned char * buff;
+       unsigned int buffSize;
+       short width;
+       short height;
+       // parse parameters
+       if (!PyArg_ParseTuple(args, "s#hh", &buff, &buffSize, &width, &height))
+       {
+               // report error
+               PyErr_SetString(PyExc_TypeError, "Parameters are not correct");
+               return NULL;
+       }
+       // else check buffer size
+       else
+       {
+               // calc proper buffer size
+               unsigned int propSize = width * height;
+               // use pixel size from filter
+               if (self->m_image->getFilter() != NULL)
+                       propSize *= self->m_image->getFilter()->m_filter->firstPixelSize();
+               else
+                       propSize *= defFilter.firstPixelSize();
+               // check if buffer size is correct
+               if (propSize != buffSize)
+               {
+                       // if not, report error
+                       PyErr_SetString(PyExc_TypeError, "Buffer hasn't correct size");
+                       return NULL;
+               }
+               else
+                       // if correct, load image
+                       getImageBuff(self)->load(buff, width, height);
+       }
+       Py_RETURN_NONE; 
+}
+
+
+// methods structure
+static PyMethodDef imageBuffMethods[] =
+{ 
+       {"load", (PyCFunction)load, METH_VARARGS, "Load image from buffer"},
+       {NULL}
+};
+// attributes structure
+static PyGetSetDef imageBuffGetSets[] =
+{      // attributes from ImageBase class
+       {"image", (getter)Image_getImage, NULL, "image data", NULL},
+       {"size", (getter)Image_getSize, NULL, "image size", NULL},
+       {"scale", (getter)Image_getScale, (setter)Image_setScale, "fast scale of image (near neighbour)", NULL},
+       {"flip", (getter)Image_getFlip, (setter)Image_setFlip, "flip image vertically", NULL},
+       {"filter", (getter)Image_getFilter, (setter)Image_setFilter, "pixel filter", NULL},
+       {NULL}
+};
+
+
+// define python type
+PyTypeObject ImageBuffType =
+{ 
+       PyObject_HEAD_INIT(NULL)
+       0,                         /*ob_size*/
+       "VideoTexture.ImageBuff",   /*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 image buffer",       /* tp_doc */
+       0,                             /* tp_traverse */
+       0,                             /* tp_clear */
+       0,                             /* tp_richcompare */
+       0,                             /* tp_weaklistoffset */
+       0,                             /* tp_iter */
+       0,                             /* tp_iternext */
+       imageBuffMethods,    /* tp_methods */
+       0,                   /* tp_members */
+       imageBuffGetSets,          /* tp_getset */
+       0,                         /* tp_base */
+       0,                         /* tp_dict */
+       0,                         /* tp_descr_get */
+       0,                         /* tp_descr_set */
+       0,                         /* tp_dictoffset */
+       (initproc)Image_init<ImageBuff>,     /* tp_init */
+       0,                         /* tp_alloc */
+       Image_allocNew,           /* tp_new */
+};
+
diff --git a/source/gameengine/VideoTexture/ImageBuff.h b/source/gameengine/VideoTexture/ImageBuff.h
new file mode 100644 (file)
index 0000000..fa2025f
--- /dev/null
@@ -0,0 +1,51 @@
+/* $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.
+-----------------------------------------------------------------------------
+*/
+
+#if !defined IMAGEBUFF_H
+#define IMAGEBUFF_H
+
+
+#include "Common.h"
+
+#include "ImageBase.h"
+
+
+/// class for image buffer
+class ImageBuff : public ImageBase
+{
+public:
+       /// constructor
+       ImageBuff (void) : ImageBase(true) {}
+
+       /// destructor
+       virtual ~ImageBuff (void) {}
+
+       /// load image from buffer
+       void load (unsigned char * img, short width, short height);
+
+       /// refresh image - do nothing
+       virtual void refresh (void) {}
+};
+
+
+#endif
+
diff --git a/source/gameengine/VideoTexture/ImageMix.cpp b/source/gameengine/VideoTexture/ImageMix.cpp
new file mode 100644 (file)
index 0000000..5650306
--- /dev/null
@@ -0,0 +1,205 @@
+/* $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 <Python.h>
+#include <structmember.h>
+
+#include "ImageMix.h"
+
+#include "ImageBase.h"
+
+#include "Exception.h"
+
+
+// cast ImageSource pointer to ImageSourceMix
+inline ImageSourceMix * getImageSourceMix (ImageSource * src)
+{ return static_cast<ImageSourceMix*>(src); }
+
+
+// get weight
+short ImageMix::getWeight (const char * id)
+{
+       // find source
+       ImageSourceList::iterator src = findSource(id);
+       // if found, return its weight
+       return src != m_sources.end() ? getImageSourceMix(*src)->getWeight() : 0;
+}
+
+// set weight
+bool ImageMix::setWeight (const char * id, short weight)
+{
+       // find source
+       ImageSourceList::iterator src = findSource(id);
+       // if source isn't found, report it
+       if (src == m_sources.end()) return false;
+       // set its weight
+       getImageSourceMix(*src)->setWeight(weight);
+       return true;
+}
+
+static ExceptionID ImageSizesNotMatch;
+
+static ExpDesc ImageSizesNotMatchDesc (ImageSizesNotMatch, "Image sizes of sources are different");
+
+// calculate image from sources and set its availability
+void ImageMix::calcImage (unsigned int texId)
+{
+       // check source sizes
+       if (!checkSourceSizes()) THRWEXCP(ImageSizesNotMatch, S_OK);
+       // set offsets to image buffers
+       for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
+               // if image buffer is available
+               if ((*it)->getImageBuf() != NULL)
+                       // set its offset
+                       getImageSourceMix(*it)->setOffset(m_sources[0]->getImageBuf());
+               // otherwise don't calculate image
+               else 
+                       return;
+       // if there is only single source
+       if (m_sources.size() == 1)
+       {
+               // use single filter
+               FilterBase mixFilt;
+               // fiter and convert image
+               filterImage(mixFilt, m_sources[0]->getImageBuf(), m_sources[0]->getSize());
+       }
+       // otherwise use mix filter to merge source images
+       else
+       {
+               FilterImageMix mixFilt (m_sources);
+               // fiter and convert image
+               filterImage(mixFilt, m_sources[0]->getImageBuf(), m_sources[0]->getSize());
+       }
+}
+
+
+
+// cast Image pointer to ImageMix
+inline ImageMix * getImageMix (PyImage * self)
+{ return static_cast<ImageMix*>(self->m_image); }
+
+
+// python methods
+
+// get source weight
+PyObject * getWeight (PyImage * self, PyObject * args)
+{
+       // weight
+       short weight = 0;
+       // get arguments
+       char * id;
+       if (self->m_image != NULL && PyArg_ParseTuple(args, "s", &id))
+               // get weight
+               weight = getImageMix(self)->getWeight(id);
+       // return weight
+       return Py_BuildValue("h", weight);
+}
+
+
+// set source weight
+PyObject * setWeight (PyImage * self, PyObject * args)
+{
+       // get arguments
+       char * id;
+       short weight = 0;
+       if (self->m_image != NULL && PyArg_ParseTuple(args, "sh", &id, &weight))
+               // set weight
+               if (!getImageMix(self)->setWeight(id, weight))
+               {
+                       // if not set, report error
+                       PyErr_SetString(PyExc_RuntimeError, "Invalid id of source");;
+                       return NULL;
+               }
+       // return none
+       Py_RETURN_NONE;
+}
+
+
+// methods structure
+static PyMethodDef imageMixMethods[] =
+{ 
+       {"getSource", (PyCFunction)Image_getSource, METH_VARARGS, "get image source"},
+       {"setSource", (PyCFunction)Image_setSource, METH_VARARGS, "set image source"},
+       {"getWeight", (PyCFunction)getWeight, METH_VARARGS, "get image source weight"},
+       {"setWeight", (PyCFunction)setWeight, METH_VARARGS, "set image source weight"},
+       // methods from ImageBase class
+       {"refresh", (PyCFunction)Image_refresh, METH_NOARGS, "Refresh image - invalidate its current content"},
+       {NULL}
+};
+// attributes structure
+static PyGetSetDef imageMixGetSets[] =
+{ // attributes from ImageBase class
+       {"image", (getter)Image_getImage, NULL, "image data", NULL},
+       {"size", (getter)Image_getSize, NULL, "image size", NULL},
+       {"scale", (getter)Image_getScale, (setter)Image_setScale, "fast scale of image (near neighbour)", NULL},
+       {"flip", (getter)Image_getFlip, (setter)Image_setFlip, "flip image vertically", NULL},
+       {"filter", (getter)Image_getFilter, (setter)Image_setFilter, "pixel filter", NULL},
+       {NULL}
+};
+
+
+// define python type
+PyTypeObject ImageMixType =
+{ 
+       PyObject_HEAD_INIT(NULL)
+       0,                         /*ob_size*/
+       "VideoTexture.ImageMix",   /*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 mixer",       /* tp_doc */
+       0,                             /* tp_traverse */
+       0,                             /* tp_clear */
+       0,                             /* tp_richcompare */
+       0,                             /* tp_weaklistoffset */
+       0,                             /* tp_iter */
+       0,                             /* tp_iternext */
+       imageMixMethods,    /* tp_methods */
+       0,                   /* tp_members */
+       imageMixGetSets,          /* tp_getset */
+       0,                         /* tp_base */
+       0,                         /* tp_dict */
+       0,                         /* tp_descr_get */
+       0,                         /* tp_descr_set */
+       0,                         /* tp_dictoffset */
+       (initproc)Image_init<ImageMix>,     /* tp_init */
+       0,                         /* tp_alloc */
+       Image_allocNew,           /* tp_new */
+};
+
diff --git a/source/gameengine/VideoTexture/ImageMix.h b/source/gameengine/VideoTexture/ImageMix.h
new file mode 100644 (file)
index 0000000..b4842bd
--- /dev/null
@@ -0,0 +1,123 @@
+/* $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.
+-----------------------------------------------------------------------------
+*/
+
+#if !defined IMAGEMIX_H
+#define IMAGEMIX_H
+
+
+#include "Common.h"
+
+#include "ImageBase.h"
+#include "FilterBase.h"
+
+
+/// class for source mixing
+class ImageSourceMix : public ImageSource
+{
+public:
+       /// constructor
+       ImageSourceMix (const char * id) : ImageSource(id), m_weight(0x100) {}
+       /// destructor
+       virtual ~ImageSourceMix (void) {}
+
+       /// get offset
+       long long getOffset (void) { return m_offset; }
+       /// set offset
+       void setOffset (unsigned int * firstImg) { m_offset = m_image - firstImg; }
+
+       /// get weight
+       short getWeight (void) { return m_weight; }
+       /// set weight
+       void setWeight (short weight) { m_weight = weight; }
+
+protected:
+       /// buffer offset to the first source buffer
+       long long m_offset;
+       /// source weight
+       short m_weight;
+};
+
+
+/// class for image mixer
+class ImageMix : public ImageBase
+{
+public:
+       /// constructor
+       ImageMix (void) : ImageBase(false) {}
+
+       /// destructor
+       virtual ~ImageMix (void) {}
+
+       /// get weight
+       short getWeight (const char * id);
+       /// set weight
+       bool setWeight (const char * id, short weight);
+
+protected:
+
+       /// create new source
+       virtual ImageSource * newSource (const char * id) { return new ImageSourceMix(id); }
+
+       /// calculate image from sources and set its availability
+       virtual void calcImage (unsigned int texId);
+};
+
+
+/// pixel filter for image mixer
+class FilterImageMix : public FilterBase
+{
+public:
+       /// constructor
+       FilterImageMix (ImageSourceList & sources) : m_sources(sources) {}
+       /// destructor
+       virtual ~FilterImageMix (void) {}
+
+protected:
+       /// source list
+       ImageSourceList & m_sources;
+
+       /// filter pixel, source int buffer
+       virtual unsigned int filter (unsigned int * src, short x, short y,
+               short * size, unsigned int pixSize, unsigned int val = 0)
+       {
+               // resulting pixel color
+               int color[] = {0, 0, 0, 0};
+               // iterate sources
+               for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
+               {
+                       // get pointer to mixer source
+                       ImageSourceMix * mixSrc = static_cast<ImageSourceMix*>(*it);
+                       // add weighted source pixel to result
+                       color[0] += mixSrc->getWeight() * (src[mixSrc->getOffset()] & 0xFF);
+                       color[1] += mixSrc->getWeight() * ((src[mixSrc->getOffset()] >> 8) & 0xFF);
+                       color[2] += mixSrc->getWeight() * ((src[mixSrc->getOffset()] >> 16) & 0xFF);
+                       color[3] += mixSrc->getWeight() * ((src[mixSrc->getOffset()] >> 24) & 0xFF);
+               }
+               // return resulting color
+               return ((color[0] >> 8) & 0xFF) | (color[1] & 0xFF00)
+                       | ((color[2] << 8) & 0xFF0000) | ((color[3] << 16) & 0xFF000000);
+       }
+};
+
+
+#endif
+
diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp
new file mode 100644 (file)
index 0000000..c800b92
--- /dev/null
@@ -0,0 +1,261 @@
+/* $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 <Python.h>
+#include <structmember.h>
+
+#include <KX_BlenderCanvas.h>
+#include <KX_BlenderRenderTools.h>
+#include <RAS_IRasterizer.h>
+#include <RAS_OpenGLRasterizer.h>
+#include <KX_WorldInfo.h>
+#include <KX_Light.h>
+
+#include "ImageRender.h"
+
+#include "ImageBase.h"
+#include "BlendType.h"
+#include "Exception.h"
+
+
+// constructor
+ImageRender::ImageRender (KX_Scene * scene, KX_Camera * camera) : m_scene(scene),
+m_camera(camera)
+{
+       // create screen area
+       m_area.winrct.xmin = m_upLeft[0];
+       m_area.winrct.ymin = m_upLeft[1];
+       m_area.winx = m_size[0];
+       m_area.winy = m_size[1];
+       // create canvas
+       m_canvas = new KX_BlenderCanvas(&m_area);
+       // create render tools
+       m_rendertools = new KX_BlenderRenderTools();
+       // create rasterizer
+       m_rasterizer = new RAS_OpenGLRasterizer(m_canvas);
+       m_rasterizer->Init();
+       // initialize background colour
+       setBackground(0, 0, 255);
+       // refresh lights
+       refreshLights();
+}
+
+// destructor
+ImageRender::~ImageRender (void)
+{
+       // release allocated objects
+       delete m_rasterizer;
+       delete m_rendertools;
+       delete m_canvas;
+}
+
+
+// set background color
+void ImageRender::setBackground (unsigned char red, unsigned char green, unsigned char blue)
+{
+       m_background[0] = red;
+       m_background[1] = green;
+       m_background[2] = blue;
+       m_rasterizer->SetBackColor(m_background[0], m_background[1], m_background[2], 1.0);
+}
+
+
+// capture image from viewport
+void ImageRender::calcImage (unsigned int texId)
+{
+       // setup camera
+       bool cameraPasive = !m_camera->GetViewport();
+       // render scene
+       Render();
+       // reset camera
+       if (cameraPasive) m_camera->EnableViewport(false);
+       // get image from viewport
+       ImageViewport::calcImage(texId);
+}
+
+
+// refresh lights
+void ImageRender::refreshLights (void)
+{
+       // clear lights list
+       //m_rendertools->RemoveAllLights();
+       // set lights
+       //for (int idx = 0; idx < scene->GetLightList()->GetCount(); ++idx)
+       //  m_rendertools->AddLight(((KX_LightObject*)(scene->GetLightList()->GetValue(idx)))->GetLightData());
+}
+
+
+
+// cast Image pointer to ImageRender
+inline ImageRender * getImageRender (PyImage * self)
+{ return static_cast<ImageRender*>(self->m_image); }
+
+
+// python methods
+
+// Blender Scene type
+BlendType<KX_Scene> sceneType ("KX_Scene");
+// Blender Camera type
+BlendType<KX_Camera> cameraType ("KX_Camera");
+
+
+static ExceptionID SceneInvalid, CameraInvalid;
+static ExpDesc SceneInvalidDesc (SceneInvalid, "Scene object is invalid");
+static ExpDesc CameraInvalidDesc (CameraInvalid, "Camera object is invalid");
+
+// object initialization
+static int ImageRender_init (PyObject * pySelf, PyObject * args, PyObject * kwds)
+{
+       // parameters - scene object
+       PyObject * scene;
+       // camera object
+       PyObject * camera;
+       // parameter keywords
+       static char *kwlist[] = {"sceneObj", "cameraObj", NULL};
+       // get parameters
+       if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &scene, &camera))
+               return -1;
+       try
+       {
+               // get scene pointer
+               KX_Scene * scenePtr (NULL);
+               if (scene != NULL) scenePtr = sceneType.checkType(scene);
+               // throw exception if scene is not available
+               if (scenePtr == NULL) THRWEXCP(SceneInvalid, S_OK);
+
+               // get camera pointer
+               KX_Camera * cameraPtr (NULL);
+               if (camera != NULL) cameraPtr = cameraType.checkType(camera);
+               // throw exception if camera is not available
+               if (cameraPtr == NULL) THRWEXCP(CameraInvalid, S_OK);
+
+               // get pointer to image structure
+               PyImage * self = reinterpret_cast<PyImage*>(pySelf);
+               // create source object
+               if (self->m_image != NULL) delete self->m_image;
+               self->m_image = new ImageRender(scenePtr, cameraPtr);
+       }
+       catch (Exception & exp)
+       {
+               exp.report();
+               return -1;
+       }
+       // initialization succeded
+       return 0;
+}
+
+
+// get background color
+PyObject * getBackground (PyImage * self, void * closure)
+{
+       return Py_BuildValue("[BBB]", getImageRender(self)->getBackground()[0],
+               getImageRender(self)->getBackground()[1], getImageRender(self)->getBackground()[2]);
+}
+
+// set color
+static int setBackground (PyImage * self, PyObject * value, void * closure)
+{
+       // check validity of parameter
+       if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 3
+               || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 0))
+               || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 1))
+               || !PyInt_Check(PySequence_Fast_GET_ITEM(value, 2)))
+       {
+               PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 3 ints");
+               return -1;
+       }
+       // set background color
+       getImageRender(self)->setBackground((unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 0))),
+               (unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 1))),
+               (unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 2))));
+       // success
+       return 0;
+}
+
+
+// methods structure
+static PyMethodDef imageRenderMethods[] =
+{ // methods from ImageBase class
+       {"refresh", (PyCFunction)Image_refresh, METH_NOARGS, "Refresh image - invalidate its current content"},
+       {NULL}
+};
+// attributes structure
+static PyGetSetDef imageRenderGetSets[] =
+{ 
+       {"background", (getter)getBackground, (setter)setBackground, "background color", NULL},
+       // attributes from ImageBase class
+       {"image", (getter)Image_getImage, NULL, "image data", NULL},
+       {"size", (getter)Image_getSize, NULL, "image size", NULL},
+       {"scale", (getter)Image_getScale, (setter)Image_setScale, "fast scale of image (near neighbour)",       NULL},
+       {"flip", (getter)Image_getFlip, (setter)Image_setFlip, "flip image vertically", NULL},
+       {"filter", (getter)Image_getFilter, (setter)Image_setFilter, "pixel filter", NULL},
+       {NULL}
+};
+
+
+// define python type
+PyTypeObject ImageRenderType =
+{ 
+       PyObject_HEAD_INIT(NULL)
+       0,                         /*ob_size*/
+       "VideoTexture.ImageRender",   /*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 render",       /* tp_doc */
+       0,                             /* tp_traverse */
+       0,                             /* tp_clear */
+       0,                             /* tp_richcompare */
+       0,                             /* tp_weaklistoffset */
+       0,                             /* tp_iter */
+       0,                             /* tp_iternext */
+       imageRenderMethods,    /* tp_methods */
+       0,                   /* tp_members */
+       imageRenderGetSets,          /* tp_getset */
+       0,                         /* tp_base */
+       0,                         /* tp_dict */
+       0,                         /* tp_descr_get */
+       0,                         /* tp_descr_set */
+       0,                         /* tp_dictoffset */
+       (initproc)ImageRender_init,     /* tp_init */
+       0,                         /* tp_alloc */
+       Image_allocNew,           /* tp_new */
+};
+
+
diff --git a/source/gameengine/VideoTexture/ImageRender.h b/source/gameengine/VideoTexture/ImageRender.h
new file mode 100644 (file)
index 0000000..66255f0
--- /dev/null
@@ -0,0 +1,90 @@
+/* $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.
+-----------------------------------------------------------------------------
+*/
+
+#if !defined IMAGERENDER_H
+#define IMAGERENDER_H
+
+
+#include "Common.h"
+
+#include <KX_Scene.h>
+#include <KX_Camera.h>
+#include <DNA_screen_types.h>
+#include <RAS_ICanvas.h>
+#include <RAS_IRasterizer.h>
+#include <RAS_IRenderTools.h>
+
+#include "ImageViewport.h"
+
+
+/// class for render 3d scene
+class ImageRender : public ImageViewport
+{
+public:
+       /// constructor
+       ImageRender (KX_Scene * scene, KX_Camera * camera);
+
+       /// destructor
+       virtual ~ImageRender (void);
+
+       /// get background color
+       unsigned char * getBackground (void) { return m_background; }
+       /// set background color
+       void setBackground (unsigned char red, unsigned char green, unsigned char blue);
+
+protected:
+       /// rendered scene
+       KX_Scene * m_scene;
+       /// camera for render
+       KX_Camera * m_camera;
+
+       /// screen area for rendering
+       ScrArea m_area;
+       /// rendering device
+       RAS_ICanvas * m_canvas;
+       /// rasterizer
+       RAS_IRasterizer * m_rasterizer;
+       /// render tools
+       RAS_IRenderTools * m_rendertools;
+
+       /// background colour
+       unsigned char m_background[3];
+
+
+       /// render 3d scene to image
+       virtual void calcImage (unsigned int texId);
+
+       /// refresh lights
+       void refreshLights (void);
+       /// methods from KX_KetsjiEngine
+       bool BeginFrame();
+       void EndFrame();
+       void Render();
+       void SetupRenderFrame(KX_Scene *scene, KX_Camera* cam);
+       void RenderFrame(KX_Scene* scene, KX_Camera* cam);
+       void SetBackGround(KX_WorldInfo* wi);
+       void SetWorldSettings(KX_WorldInfo* wi);
+};
+
+
+#endif
+
diff --git a/source/gameengine/VideoTexture/ImageViewport.cpp b/source/gameengine/VideoTexture/ImageViewport.cpp
new file mode 100644 (file)
index 0000000..e1d3316
--- /dev/null
@@ -0,0 +1,298 @@
+/* $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 <Python.h>
+#include <structmember.h>
+
+#include "ImageViewport.h"
+
+#include <BIF_gl.h>
+
+#include "Texture.h"
+#include "ImageBase.h"
+#include "FilterSource.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] = 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 (int * 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], m_capSize[0], 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], m_capSize[0], m_capSize[1], GL_RGB,
+                       GL_UNSIGNED_BYTE, m_viewportImage);
+               // filter loaded data
+               FilterBGR24 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
+       int pos [] = {
+               int(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 0))),
+                       int(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[] =
+{ 
+       {"whole", (getter)ImageViewport_getWhole, (setter)ImageViewport_setWhole, "use whole viewport to capture", NULL},
+       {"position", (getter)ImageViewport_getPosition, (setter)ImageViewport_setPosition, "upper left corner of captured area", NULL},
+       {"capsize", (getter)ImageViewport_getCaptureSize, (setter)ImageViewport_setCaptureSize, "size of viewport area being captured", NULL},
+       // attributes from ImageBase class
+       {"image", (getter)Image_getImage, NULL, "image data", NULL},
+       {"size", (getter)Image_getSize, NULL, "image size", NULL},
+       {"scale", (getter)Image_getScale, (setter)Image_setScale, "fast scale of image (near neighbour)", NULL},
+       {"flip", (getter)Image_getFlip, (setter)Image_setFlip, "flip image vertically", NULL},
+       {"filter", (getter)Image_getFilter, (setter)Image_setFilter, "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 */
+};
diff --git a/source/gameengine/VideoTexture/ImageViewport.h b/source/gameengine/VideoTexture/ImageViewport.h
new file mode 100644 (file)
index 0000000..9fd3aeb
--- /dev/null
@@ -0,0 +1,84 @@
+/* $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.
+-----------------------------------------------------------------------------
+*/
+
+#if !defined IMAGEVIEWPORT_H
+#define IMAGEVIEWPORT_H
+
+
+#include "Common.h"
+
+#include "ImageBase.h"
+
+
+/// class for viewport access
+class ImageViewport : public ImageBase
+{
+public:
+       /// constructor
+       ImageViewport (void);
+
+       /// destructor
+       virtual ~ImageViewport (void);
+
+       /// is whole buffer used
+       bool getWhole (void) { return m_whole; }
+       /// set whole buffer use
+       void setWhole (bool whole);
+       /// get capture size in viewport
+       short * getCaptureSize (void) { return m_capSize; }
+       /// set capture size in viewport
+       void setCaptureSize (short * size = NULL);
+
+       /// get position in viewport
+       int * getPosition (void) { return m_position; }
+       /// set position in viewport
+       void setPosition (int * pos = NULL);
+
+protected:
+       /// frame buffer rectangle
+       int m_viewport[4];
+
+       /// size of captured area
+       short m_capSize[2];
+       /// use whole viewport
+       bool m_whole;
+
+       /// position of capture rectangle in viewport
+       int m_position[2];
+       /// upper left point for capturing
+       int m_upLeft[2];
+
+       /// buffer to copy viewport
+       BYTE * m_viewportImage;
+       /// texture is initialized
+       bool m_texInit;
+
+       /// capture image from viewport
+       virtual void calcImage (unsigned int texId);
+
+       /// get viewport size
+       int * getViewportSize (void) { return m_viewport + 2; }
+};
+
+
+#endif
+
diff --git a/source/gameengine/VideoTexture/Makefile b/source/gameengine/VideoTexture/Makefile
new file mode 100644 (file)
index 0000000..bead176
--- /dev/null
@@ -0,0 +1,65 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU 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.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+#
+
+LIBNAME = videotex
+DIR = $(OCGDIR)/gameengine/$(LIBNAME)
+SOURCEDIR = source/gameengine/VideoTexture
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+
+CPPFLAGS += $(OGL_CPPFLAGS)
+CPPFLAGS += -I$(NAN_GLEW)/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
+CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) 
+CPPFLAGS += -I../../blender/python
+CPPFLAGS += -I$(NAN_STRING)/include    
+CPPFLAGS += -I$(NAN_SOUNDSYSTEM)/include    
+CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I../Rasterizer/RAS_OpenGLRasterizer
+CPPFLAGS += -I../Rasterizer -I../GameLogic -I../SceneGraph
+CPPFLAGS += -I../BlenderRoutines -I../Expressions -I../Ketsji
+CPPFLAGS += -I../../kernel/gen_system
+CPPFLAGS += -I.
+CPPFLAGS += -I../../blender/blenkernel
+CPPFLAGS += -I../../blender/blenlib
+CPPFLAGS += -I../../blender/include
+CPPFLAGS += -I../../blender/makesdna
+CPPFLAGS += -I../../blender/imbuf
+CPPFLAGS += -I../../blender/gpu
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+
+ifeq ($(WITH_FFMPEG),true)
+    CPPFLAGS += -DWITH_FFMPEG
+    CPPFLAGS += $(NAN_FFMPEGCFLAGS)
+endif
+
+
diff --git a/source/gameengine/VideoTexture/PyTypeList.cpp b/source/gameengine/VideoTexture/PyTypeList.cpp
new file mode 100644 (file)
index 0000000..b8c4005
--- /dev/null
@@ -0,0 +1,83 @@
+/* $Id$
+-----------------------------------------------------------------------------
+This source file is part of blendTex 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.
+-----------------------------------------------------------------------------
+*/
+
+
+#include "PyTypeList.h"
+
+#include <memory>
+#include <vector>
+
+#include <Python.h>
+
+
+/// check, if type is in list
+bool PyTypeList::in (PyTypeObject * type)
+{
+       // if list exists
+       if (m_list.get() != NULL)
+               // iterate items in list
+               for (PyTypeListType::iterator it = m_list->begin(); it != m_list->end(); ++it)
+                       // if item is found, return with success
+                       if ((*it)->getType() == type) return true;
+       // otherwise return not found
+       return false;
+}
+
+/// add type to list
+void PyTypeList::add (PyTypeObject * type, const char * name)
+{
+       PyTypeListItem * typeItem;
+       // if list doesn't exist, create it
+       if (m_list.get() == NULL) 
+               m_list.reset(new PyTypeListType());
+       if (!in(type))
+               // add new item to list
+               m_list->push_back(new PyTypeListItem(type, name));
+}
+
+/// prepare types
+bool PyTypeList::ready (void)
+{
+       // if list exists
+       if (m_list.get() != NULL)
+               // iterate items in list
+               for (PyTypeListType::iterator it = m_list->begin(); it != m_list->end(); ++it)
+                       // if preparation failed, report it
+                       if (PyType_Ready((*it)->getType()) < 0) return false;
+       // success
+       return true;
+}
+
+/// register types to module
+void PyTypeList::reg (PyObject * module)
+{
+       // if list exists
+       if (m_list.get() != NULL)
+               // iterate items in list
+               for (PyTypeListType::iterator it = m_list->begin(); it != m_list->end(); ++it)
+               {
+                       // increase ref count
+                       Py_INCREF((*it)->getType());
+                       // add type to module
+                       PyModule_AddObject(module, (*it)->getName(), (PyObject*)(*it)->getType());
+               }
+}
diff --git a/source/gameengine/VideoTexture/PyTypeList.h b/source/gameengine/VideoTexture/PyTypeList.h
new file mode 100644 (file)
index 0000000..7069cf8
--- /dev/null
@@ -0,0 +1,85 @@
+/* $Id$
+-----------------------------------------------------------------------------
+This source file is part of blendTex 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.
+-----------------------------------------------------------------------------
+*/
+
+#if !defined PYTYPELIST_H
+#define PYTYPELIST_H
+
+#include "Common.h"
+
+#include <memory>
+#include <vector>
+
+#include <Python.h>
+
+// forward declaration
+class PyTypeListItem;
+
+// type for list of types
+typedef std::vector<PyTypeListItem*> PyTypeListType;
+
+
+/// class to store list of python types
+class PyTypeList
+{
+public:
+       /// check, if type is in list
+       bool in (PyTypeObject * type);
+
+       /// add type to list
+       void add (PyTypeObject * type, const char * name);
+
+       /// prepare types
+       bool ready (void);
+
+       /// register types to module
+       void reg (PyObject * module);
+
+protected:
+       /// pointer to list of types
+       std::auto_ptr<PyTypeListType> m_list;
+};
+
+
+/// class for item of python type list
+class PyTypeListItem
+{
+public:
+       /// constructor adds type into list
+       PyTypeListItem (PyTypeObject * type, const char * name)
+               : m_type(type), m_name(name)
+       { }
+
+       /// does type match
+       PyTypeObject * getType (void) { return m_type; }
+
+       /// get name of type
+       const char * getName (void) { return m_name; }
+
+protected:
+       /// pointer to type object
+       PyTypeObject * m_type;
+       /// name of type
+       const char * m_name;
+};
+
+
+#endif
\ No newline at end of file
diff --git a/source/gameengine/VideoTexture/SConscript b/source/gameengine/VideoTexture/SConscript
new file mode 100644 (file)
index 0000000..e0972e0
--- /dev/null
@@ -0,0 +1,32 @@
+#!/usr/bin/python
+import sys
+
+Import ('env')
+
+sources = env.Glob('*.cpp')
+
+incs = '. #source/gameengine/Ketsji #source/gameengine/Expressions'
+incs += ' #source/gameengine/GameLogic #source/gameengine/SceneGraph #source/gameengine/Rasterizer'
+incs += ' #source/gameengine/Rasterizer/RAS_OpenGLRasterizer'
+incs += ' #source/gameengine/BlenderRoutines'
+incs += ' #source/blender/include #source/blender/blenlib #source/blender/blenkernel'
+incs += ' #source/blender/makesdna #source/blender/imbuf #source/blender/python'
+incs += ' #source/blender/gpu #source/kernel/gen_system #intern/string #intern/moto/include'
+incs += ' #intern/guardedalloc #intern/SoundSystem'
+incs += ' #extern/glew/include'
+
+cflags = []
+defs = ''
+if env['OURPLATFORM'] == 'win32-vc':
+       cflags.append('/GR')
+       cflags.append('/Ox')
+       defs += ' __STDC_CONSTANT_MACROS'
+
+incs += ' ' + env['BF_PYTHON_INC']
+#incs += ' ' + env['BF_OPENGL_INC']
+
+if env['WITH_BF_FFMPEG']:
+    defs += ' WITH_FFMPEG'
+    incs += ' ' + env['BF_FFMPEG_INC']
+
+env.BlenderLib ( 'bf_videotex', sources, Split(incs), Split(defs), libtype=['game','player'], priority=[25, 72], compileflags = cflags )
diff --git a/source/gameengine/VideoTexture/Texture.cpp b/source/gameengine/VideoTexture/Texture.cpp
new file mode 100644 (file)
index 0000000..d208802
--- /dev/null
@@ -0,0 +1,463 @@
+/* $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 <Python.h>
+#include <structmember.h>
+
+#include <KX_GameObject.h>
+#include <RAS_MeshObject.h>
+#include <DNA_mesh_types.h>
+#include <DNA_meshdata_types.h>
+#include <DNA_image_types.h>
+#include <IMB_imbuf_types.h>
+#include <BDR_drawmesh.h>
+#include <KX_PolygonMaterial.h>
+
+#include <MEM_guardedalloc.h>
+
+#include <KX_BlenderMaterial.h>
+#include <BL_Texture.h>
+
+#include "KX_KetsjiEngine.h"
+#include "KX_PythonInit.h"
+#include "Texture.h"
+#include "ImageBase.h"
+#include "Exception.h"
+
+#include <memory.h>
+#include <BIF_gl.h>
+
+
+// macro for exception handling and logging
+#define CATCH_EXCP catch (Exception & exp) \
+{ exp.report(); }
+
+
+// are Blender materials used
+bool blendMats = false;
+
+// Blender GameObject type
+BlendType<KX_GameObject> gameObjectType ("KX_GameObject");
+
+
+// load texture
+void loadTexture (unsigned int texId, unsigned int * texture, short * size,
+                                 bool mipmap)
+{
+       // load texture for rendering
+       glBindTexture(GL_TEXTURE_2D, texId);
+       if (mipmap)
+       {
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+               gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE, texture);
+       } 
+       else
+       {
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+               glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, size[0], size[1], 0, GL_RGBA, GL_UNSIGNED_BYTE, texture);
+       }
+       glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+}
+
+
+// get pointer to material
+RAS_IPolyMaterial * getMaterial (PyObject *obj, short matID)
+{
+       // if object is available
+       if (obj != NULL)
+       {
+               // get pointer to texture image
+               KX_GameObject * gameObj = gameObjectType.checkType(obj);
+               if (gameObj != NULL && gameObj->GetMeshCount() > 0)
+               {
+                       // get material from mesh
+                       RAS_MeshObject * mesh = gameObj->GetMesh(0);
+                       RAS_MeshMaterial *meshMat = mesh->GetMeshMaterial(matID);
+                       if (meshMat->m_bucket != NULL)
+                               // return pointer to polygon or blender material
+                               return meshMat->m_bucket->GetPolyMaterial();
+               }
+       }
+       // otherwise material was not found
+       return NULL;
+}
+
+
+// get material ID
+short getMaterialID (PyObject * obj, char * name)
+{
+       // search for material
+       for (short matID = 0;; ++matID)
+       {
+               // get material
+               RAS_IPolyMaterial * mat = getMaterial(obj, matID);
+               // if material is not available, report that no material was found
+               if (mat == NULL) break;
+               // if material name matches
+               if (strcmp(mat->GetMaterialName().ReadPtr(), name) == 0)
+                       // matID is found
+                       return matID;
+       }
+       // material was not found
+       return -1;
+}
+
+
+// Texture object allocation
+PyObject * Texture_new (PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+       // allocate object
+       Texture * self = reinterpret_cast<Texture*>(type->tp_alloc(type, 0));
+       // initialize object structure
+       self->m_actTex = 0;
+       self->m_orgSaved = false;
+       self->m_imgTexture = NULL;
+       self->m_matTexture = NULL;
+       self->m_mipmap = false;
+       self->m_scaledImg = NULL;
+       self->m_scaledImgSize = 0;
+       self->m_source = NULL;
+       self->m_lastClock = 0.0;
+       // return allocated object
+       return reinterpret_cast<PyObject*>(self);
+}
+
+
+// forward declaration
+PyObject * Texture_close(Texture * self);
+int Texture_setSource (Texture * self, PyObject * value, void * closure);
+
+
+// Texture object deallocation
+void Texture_dealloc (Texture * self)
+{
+       // release renderer
+       Py_XDECREF(self->m_source);
+       // close texture
+       Texture_close(self);
+       // release scaled image buffer
+       delete [] self->m_scaledImg;
+       // release object
+       self->ob_type->tp_free((PyObject*)self);
+}
+
+
+static ExceptionID MaterialNotAvail;
+static ExpDesc MaterialNotAvailDesc (MaterialNotAvail, "Texture material is not available");
+
+// Texture object initialization
+int Texture_init (Texture *self, PyObject *args, PyObject *kwds)
+{
+       // parameters - game object with video texture
+       PyObject * obj = NULL;
+       // material ID
+       short matID = 0;
+       // texture ID
+       short texID = 0;
+       // texture object with shared texture ID
+       Texture * texObj = NULL;
+
+       static char *kwlist[] = {"gameObj", "materialID", "textureID", "textureObj", NULL};
+
+       // get parameters
+       if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|hhO!", kwlist, &obj, &matID,
+               &texID, &TextureType, &texObj))
+               return -1; 
+
+       // if parameters are available
+       if (obj != NULL)
+       {
+               // process polygon material or blender material
+               try
+               {
+                       // get pointer to texture image
+                       RAS_IPolyMaterial * mat = getMaterial(obj, matID);
+                       if (mat != NULL)
+                       {
+                               // is it blender material or polygon material
+                               blendMats = (mat->GetFlag() & RAS_BLENDERMAT) != 0;
+                               if (blendMats)
+                                       // get blender material texture
+                                       self->m_matTexture = static_cast<KX_BlenderMaterial*>(mat)->getTex(texID);
+                               else
+                               {
+                                       // get texture pointer from polygon material
+                                       MTFace * tface = static_cast<KX_PolygonMaterial*>(mat)->GetMTFace();
+                                       self->m_imgTexture = (Image*)tface->tpage;
+                               }
+                       }
+                       // check if texture is available, if not, initialization failed
+                       if (self->m_imgTexture == NULL && self->m_matTexture == NULL)
+                               // throw exception if initialization failed
+                               THRWEXCP(MaterialNotAvail, S_OK);
+
+                       // if texture object is provided
+                       if (texObj != NULL)
+                       {
+                               // copy texture code
+                               self->m_actTex = texObj->m_actTex;
+                               self->m_mipmap = texObj->m_mipmap;
+                               if (texObj->m_source != NULL)
+                                       Texture_setSource(self, reinterpret_cast<PyObject*>(texObj->m_source), NULL);
+                       }
+                       else
+                               // otherwise generate texture code
+                               glGenTextures(1, (GLuint*)&self->m_actTex);
+               }
+               catch (Exception & exp)
+               {
+                       exp.report();
+                       return -1;
+               }
+       }
+       // initialization succeded
+       return 0;
+}
+
+
+// close added texture
+PyObject * Texture_close(Texture * self)
+{
+       // restore texture
+       if (self->m_orgSaved)
+       {
+               self->m_orgSaved = false;
+               // restore original texture code
+               if (blendMats)
+                       self->m_matTexture->swapTexture(self->m_orgTex);
+               else
+                       self->m_imgTexture->bindcode = self->m_orgTex;
+               // drop actual texture
+               if (self->m_actTex != 0)
+               {
+                       glDeleteTextures(1, (GLuint *)&self->m_actTex);
+                       self->m_actTex = 0;
+               }
+       }
+       Py_RETURN_NONE;
+}
+
+
+// refresh texture
+PyObject * Texture_refresh (Texture * self, PyObject * args)
+{
+       // get parameter - refresh source
+       PyObject * param;
+       if (!PyArg_ParseTuple(args, "O", &param) || !PyBool_Check(param))
+       {
+               // report error
+               PyErr_SetString(PyExc_TypeError, "The value must be a bool");
+               return NULL;
+       }
+       // some trick here: we are in the business of loading a texture,
+       // no use to do it if we are still in the same rendering frame.
+       // We find this out by looking at the engine current clock time
+       KX_KetsjiEngine* engine = KX_GetActiveEngine();
+       if (engine->GetClockTime() != self->m_lastClock) 
+       {
+               self->m_lastClock = engine->GetClockTime();
+               // set source refresh
+               bool refreshSource = (param == Py_True);
+               // try to proces texture from source
+               try
+               {
+                       // if source is available
+                       if (self->m_source != NULL)
+                       {
+                               // check texture code
+                               if (!self->m_orgSaved)
+                               {
+                                       self->m_orgSaved = true;
+                                       // save original image code
+                                       if (blendMats)
+                                               self->m_orgTex = self->m_matTexture->swapTexture(self->m_actTex);
+                                       else
+                                       {
+                                               self->m_orgTex = self->m_imgTexture->bindcode;
+                                               self->m_imgTexture->bindcode = self->m_actTex;
+                                       }
+                               }
+
+                               // get texture
+                               unsigned int * texture = self->m_source->m_image->getImage(self->m_actTex);
+                               // if texture is available
+                               if (texture != NULL)
+                               {
+                                       // get texture size
+                                       short * orgSize = self->m_source->m_image->getSize();
+                                       // calc scaled sizes
+                                       short size[] = {ImageBase::calcSize(orgSize[0]), ImageBase::calcSize(orgSize[1])};
+                                       // scale texture if needed
+                                       if (size[0] != orgSize[0] || size[1] != orgSize[1])
+                                       {
+                                               // if scaled image buffer is smaller than needed
+                                               if (self->m_scaledImgSize < (unsigned int)(size[0] * size[1]))
+                                               {
+                                                       // new size
+                                                       self->m_scaledImgSize = size[0] * size[1];
+                                                       // allocate scaling image
+                                                       delete [] self->m_scaledImg;
+                                                       self->m_scaledImg = new unsigned int[self->m_scaledImgSize];
+                                               }
+                                               // scale texture
+                                               gluScaleImage(GL_RGBA, orgSize[0], orgSize[1], GL_UNSIGNED_BYTE, texture,
+                                                       size[0], size[1], GL_UNSIGNED_BYTE, self->m_scaledImg);
+                                               // use scaled image instead original
+                                               texture = self->m_scaledImg;
+                                       }
+                                       // load texture for rendering
+                                       loadTexture (self->m_actTex, texture, size, self->m_mipmap);
+
+                                       // refresh texture source, if required
+                                       if (refreshSource) self->m_source->m_image->refresh();
+                               }
+                       }
+               }
+               CATCH_EXCP;
+       }
+       Py_RETURN_NONE;
+}
+
+
+// get mipmap value
+PyObject * Texture_getMipmap (Texture * self, void * closure)
+{
+       // return true if flag is set, otherwise false
+       if (self->m_mipmap) Py_RETURN_TRUE;
+       else Py_RETURN_FALSE;
+}
+
+// set mipmap value
+int Texture_setMipmap (Texture * 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 mipmap
+       self->m_mipmap = value == Py_True;
+       // success
+       return 0;
+}
+
+
+// get source object
+PyObject * Texture_getSource (Texture * self, PyObject * value, void * closure)
+{
+       // if source exists
+       if (self->m_source != NULL)
+       {
+               Py_INCREF(self->m_source);
+               return reinterpret_cast<PyObject*>(self->m_source);
+       }
+       // otherwise return None
+       Py_RETURN_NONE;
+}
+
+
+// set source object
+int Texture_setSource (Texture * self, PyObject * value, void * closure)
+{
+       // check new value
+       if (value == NULL || !pyImageTypes.in(value->ob_type))
+       {
+               // report value error
+               PyErr_SetString(PyExc_TypeError, "Invalid type of value");
+               return -1;
+       }
+       // increase ref count for new value
+       Py_INCREF(value);
+       // release previous
+       Py_XDECREF(self->m_source);
+       // set new value
+       self->m_source = reinterpret_cast<PyImage*>(value);
+       // return success
+       return 0;
+}
+
+
+// class Texture methods
+static PyMethodDef textureMethods[] =
+{
+       { "close", (PyCFunction)Texture_close, METH_NOARGS, "Close dynamic texture and restore original"},
+       { "refresh", (PyCFunction)Texture_refresh, METH_VARARGS, "Refresh texture from source"},
+       {NULL}  /* Sentinel */
+};
+
+// class Texture attributes
+static PyGetSetDef textureGetSets[] =
+{ 
+       {"source", (getter)Texture_getSource, (setter)Texture_setSource, "source of texture", NULL},
+       {"mipmap", (getter)Texture_getMipmap, (setter)Texture_setMipmap, "mipmap texture", NULL},
+       {NULL}
+};
+
+
+// class Texture declaration
+PyTypeObject TextureType =
+{
+       PyObject_HEAD_INIT(NULL)
+       0,                         /*ob_size*/
+       "VideoTexture.Texture",   /*tp_name*/
+       sizeof(Texture),           /*tp_basicsize*/
+       0,                         /*tp_itemsize*/
+       (destructor)Texture_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*/
+       "Texture objects",       /* tp_doc */
+       0,                             /* tp_traverse */
+       0,                             /* tp_clear */
+       0,                             /* tp_richcompare */
+       0,                             /* tp_weaklistoffset */
+       0,                             /* tp_iter */
+       0,                             /* tp_iternext */
+       textureMethods,      /* tp_methods */
+       0,                   /* tp_members */
+       textureGetSets,            /* tp_getset */
+       0,                         /* tp_base */
+       0,                         /* tp_dict */
+       0,                         /* tp_descr_get */
+       0,                         /* tp_descr_set */
+       0,                         /* tp_dictoffset */
+       (initproc)Texture_init,    /* tp_init */
+       0,                         /* tp_alloc */
+       Texture_new,               /* tp_new */
+};
diff --git a/source/gameengine/VideoTexture/Texture.h b/source/gameengine/VideoTexture/Texture.h
new file mode 100644 (file)
index 0000000..f19f8da
--- /dev/null
@@ -0,0 +1,87 @@
+/* $Id$
+-----------------------------------------------------------------------------
+This source file is part of VideoTexture library
+
+Copyright (c) 2006 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.
+-----------------------------------------------------------------------------
+*/
+
+#if !defined TEXTURE_H
+#define TEXTURE_H
+
+#include <Python.h>
+#include <structmember.h>
+
+#include <DNA_image_types.h>
+#include <BL_Texture.h>
+#include <KX_BlenderMaterial.h>
+
+#include "ImageBase.h"
+#include "BlendType.h"
+
+
+// type Texture declaration
+struct Texture
+{
+       PyObject_HEAD
+
+       // video texture bind code
+       unsigned int m_actTex;
+
+       // original texture bind code
+       unsigned int m_orgTex;
+       // original texture saved
+       bool m_orgSaved;
+
+       // texture image for game materials
+       Image * m_imgTexture;
+       // texture for blender materials
+       BL_Texture * m_matTexture;
+
+       // use mipmapping
+       bool m_mipmap;
+
+       // scaled image buffer
+       unsigned int * m_scaledImg;
+       // scaled image buffer size
+       unsigned int m_scaledImgSize;
+       // last refresh
+       double m_lastClock;
+
+       // image source
+       PyImage * m_source;
+};
+
+
+// Texture type description
+extern PyTypeObject TextureType;
+
+// usage of Blender materials
+extern bool blendMats;
+
+// load texture
+void loadTexture (unsigned int texId, unsigned int * texture, short * size,
+                                 bool mipmap = false);
+
+// get material
+RAS_IPolyMaterial * getMaterial (PyObject *obj, short matID);
+
+// get material ID
+short getMaterialID (PyObject * obj, char * name);
+
+
+#endif
diff --git a/source/gameengine/VideoTexture/VideoBase.cpp b/source/gameengine/VideoTexture/VideoBase.cpp
new file mode 100644 (file)
index 0000000..038a04a
--- /dev/null
@@ -0,0 +1,183 @@
+/* $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.
+-----------------------------------------------------------------------------
+*/
+
+#if defined WIN32
+#define WINDOWS_LEAN_AND_MEAN
+#include <Windows.h>
+#endif
+
+#include "VideoBase.h"
+
+#include "FilterSource.h"
+
+// VideoBase implementation
+
+
+// initialize image data
+void VideoBase::init(short width, short height)
+{
+       // save original sizes
+       m_orgSize[0] = width;
+       m_orgSize[1] = height;
+       // call base class initialization
+       ImageBase::init(width, height);
+}
+
+
+// process video frame
+void VideoBase::process (BYTE * sample)
+{
+       // if scale was changed
+       if (m_scaleChange)
+               // reset image
+               init(m_orgSize[0], m_orgSize[1]);
+       // if image is allocated and is able to store new image
+       if (m_image != NULL && !m_avail)
+       {
+               // filters used
+               FilterRGB24 filtRGB;
+               FilterYV12 filtYUV;
+               // convert video format to image
+               switch (m_format)
+               {
+               case RGB24:
+                       // use filter object for format to convert image
+                       filterImage(filtRGB, sample, m_orgSize);
+                       // finish
+                       break;
+               case YV12:
+                       // use filter object for format to convert image
+                       filtYUV.setBuffs(sample, m_orgSize);
+                       filterImage(filtYUV, sample, m_orgSize);
+                       // finish
+                       break;
+               }
+       }
+}
+
+
+// python functions
+
+
+// exceptions for video source initialization
+ExceptionID SourceVideoEmpty, SourceVideoCreation;
+ExpDesc SourceVideoEmptyDesc (SourceVideoEmpty, "Source Video is empty");
+ExpDesc SourceVideoCreationDesc (SourceVideoCreation, "SourceVideo object was not created");
+
+// open video source
+void Video_open (VideoBase * self, char * file, short captureID)
+{
+       // if file is empty, throw exception
+       if (file == NULL) THRWEXCP(SourceVideoEmpty, S_OK);
+
+       // open video file or capture device
+       if (captureID >= 0) 
+               self->openCam(file, captureID);
+       else 
+               self->openFile(file);
+}
+
+
+// play video
+PyObject * Video_play (PyImage * self)
+{ if (getVideo(self)->play()) Py_RETURN_TRUE; else Py_RETURN_FALSE; }
+
+// stop video
+PyObject * Video_stop (PyImage * self)
+{ if (getVideo(self)->stop()) Py_RETURN_TRUE; else Py_RETURN_FALSE; }
+
+// get status
+PyObject * Video_getStatus (PyImage * self, void * closure)
+{
+       return Py_BuildValue("h", getVideo(self)->getStatus());
+}
+
+// refresh video
+PyObject * Video_refresh (PyImage * self)
+{
+       getVideo(self)->refresh();
+       return Video_getStatus(self, NULL);
+}
+
+
+// get range
+PyObject * Video_getRange (PyImage * self, void * closure)
+{
+       return Py_BuildValue("[ff]", getVideo(self)->getRange()[0],
+               getVideo(self)->getRange()[1]);
+}
+
+// set range
+int Video_setRange (PyImage * self, PyObject * value, void * closure)
+{
+       // check validity of parameter
+       if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 2
+               || !PyFloat_Check(PySequence_Fast_GET_ITEM(value, 0))
+               || !PyFloat_Check(PySequence_Fast_GET_ITEM(value, 1)))
+       {
+               PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 longs");
+               return -1;
+       }
+       // set range
+       getVideo(self)->setRange(PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0)),
+               PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1)));
+       // success
+       return 0;
+}
+
+// get repeat
+PyObject * Video_getRepeat (PyImage * self, void * closure)
+{ return Py_BuildValue("h", getVideo(self)->getRepeat()); }
+
+// set repeat
+int Video_setRepeat (PyImage * self, PyObject * value, void * closure)
+{
+       // check validity of parameter
+       if (value == NULL || !PyInt_Check(value))
+       {
+               PyErr_SetString(PyExc_TypeError, "The value must be an int");
+               return -1;
+       }
+       // set repeat
+       getVideo(self)->setRepeat(int(PyInt_AsLong(value)));
+       // success
+       return 0;
+}
+
+// get frame rate
+PyObject * Video_getFrameRate (PyImage * self, void * closure)
+{ return Py_BuildValue("f", double(getVideo(self)->getFrameRate())); }
+
+// set frame rate
+int Video_setFrameRate (PyImage * self, PyObject * value, void * closure)
+{
+       // check validity of parameter
+       if (value == NULL || !PyFloat_Check(value))
+       {
+               PyErr_SetString(PyExc_TypeError, "The value must be a float");
+               return -1;
+       }
+       // set repeat
+       getVideo(self)->setFrameRate(float(PyFloat_AsDouble(value)));
+       // success
+       return 0;
+}
diff --git a/source/gameengine/VideoTexture/VideoBase.h b/source/gameengine/VideoTexture/VideoBase.h
new file mode 100644 (file)
index 0000000..78e8ba6
--- /dev/null
@@ -0,0 +1,185 @@
+/* $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.
+-----------------------------------------------------------------------------
+*/
+
+#if !defined VIDEOBASE_H
+#define VIDEOBASE_H
+
+
+#include <Python.h>
+
+#include "ImageBase.h"
+
+#include "Exception.h"
+
+// source states
+const int SourceError = -1;
+const int SourceEmpty = 0;
+const int SourceReady = 1;
+const int SourcePlaying = 2;
+const int SourceStopped = 3;
+
+
+// video source formats
+enum VideoFormat { None, RGB24, YV12 };
+
+
+/// base class for video source
+class VideoBase : public ImageBase
+{
+public:
+       /// constructor
+       VideoBase (void) : ImageBase(true), m_format(None), m_status(SourceEmpty),
+               m_repeat(0), m_frameRate(1.0)
+       {
+               m_orgSize[0] = m_orgSize[1] = 0;
+               m_range[0] = m_range[1] = 0.0;
+       }
+
+       /// destructor
+       virtual ~VideoBase (void) {}
+
+       /// open video file
+       virtual void openFile (char * file)
+       {
+               m_isFile = true;
+               m_status = SourceReady;
+       }
+       /// open video capture device
+       virtual void openCam (char * file, short camIdx)
+       {
+               m_isFile = false;
+               m_status = SourceReady;
+       }
+
+       /// play video
+       virtual bool play (void)
+       {
+               if (m_status == SourceReady || m_status == SourceStopped)
+               {
+                       m_status = SourcePlaying;
+                       return true;
+               }
+               return false;
+       }
+       /// stop/pause video
+       virtual bool stop (void)
+       {
+               if (m_status == SourcePlaying)
+               {
+                       m_status = SourceStopped;
+                       return true;
+               }
+               return false;
+       }
+
+       // get video status
+       int getStatus (void) { return m_status; }
+
+       /// get play range
+       const double * getRange (void) { return m_range; }
+       /// set play range
+       virtual void setRange (double start, double stop)
+       {
+               if (m_isFile)
+               {
+                       m_range[0] = start;
+                       m_range[1] = stop;
+               }
+       }
+
+       // get video repeat
+       int getRepeat (void) { return m_repeat; }
+       /// set video repeat
+       virtual void setRepeat (int rep)
+       { if (m_isFile) m_repeat = rep; }
+
+       /// get frame rate
+       float getFrameRate (void) { return m_frameRate; }
+       /// set frame rate
+       virtual void setFrameRate (float rate)
+       { if (m_isFile) m_frameRate = rate > 0.0 ? rate : 1.0f; }
+
+protected:
+       /// video format
+       VideoFormat m_format;
+       /// original video size
+       short m_orgSize[2];
+
+       /// video status
+       int m_status;
+
+       /// is source file
+       bool m_isFile;
+
+       /// replay range
+       double m_range[2];
+       /// repeat count
+       int m_repeat;
+       /// frame rate
+       float m_frameRate;
+
+       /// initialize image data
+       void init (short width, short height);
+
+       /// process source data
+       void process (BYTE * sample);
+};
+
+
+
+// python fuctions
+
+
+// cast Image pointer to Video
+inline VideoBase * getVideo (PyImage * self)
+{ return static_cast<VideoBase*>(self->m_image); }
+
+
+extern ExceptionID SourceVideoCreation;
+
+// object initialization
+template <class T> void Video_init (PyImage * self)
+{
+       // create source video object
+       if (self->m_image != NULL) delete self->m_image;
+       HRESULT hRslt = S_OK;
+       self->m_image = new T(&hRslt);
+       CHCKHRSLT(hRslt, SourceVideoCreation);
+}
+
+
+// video functions
+void Video_open (VideoBase * self, char * file, short captureID);
+PyObject * Video_play (PyImage * self);
+PyObject * Video_stop (PyImage * self);
+PyObject * Video_refresh (PyImage * self);
+PyObject * Video_getStatus (PyImage * self, void * closure);
+PyObject * Video_getRange (PyImage * self, void * closure);
+int Video_setRange (PyImage * self, PyObject * value, void * closure);
+PyObject * Video_getRepeat (PyImage * self, void * closure);
+int Video_setRepeat (PyImage * self, PyObject * value, void * closure);
+PyObject * Video_getFrameRate (PyImage * self, void * closure);
+int Video_setFrameRate (PyImage * self, PyObject * value, void * closure);
+
+
+#endif
+
diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.cpp b/source/gameengine/VideoTexture/VideoFFmpeg.cpp
new file mode 100644 (file)
index 0000000..b12bad4
--- /dev/null
@@ -0,0 +1,747 @@
+/* $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.
+-----------------------------------------------------------------------------
+*/
+
+#include "MEM_guardedalloc.h"
+#include "PIL_time.h"
+
+#include <string>
+
+#include "Exception.h"
+#include "VideoFFmpeg.h"
+
+#ifdef WITH_FFMPEG
+
+// default framerate
+const double defFrameRate = 25.0;
+// time scale constant
+const long timeScale = 1000;
+
+// macro for exception handling and logging
+#define CATCH_EXCP catch (Exception & exp) \
+{ exp.report(); m_status = SourceError; }
+
+extern "C" void do_init_ffmpeg();
+
+// class RenderVideo
+
+// constructor
+VideoFFmpeg::VideoFFmpeg (HRESULT * hRslt) : VideoBase(), 
+m_codec(NULL), m_formatCtx(NULL), m_codecCtx(NULL), 
+m_frame(NULL), m_frameDeinterlaced(NULL), m_frameBGR(NULL), m_imgConvertCtx(NULL),
+m_deinterlace(false), m_preseek(0),    m_videoStream(-1), m_baseFrameRate(25.0),
+m_lastFrame(-1),  m_curPosition(-1), m_startTime(0), 
+m_captWidth(0), m_captHeight(0), m_captRate(0.f)
+{
+       // set video format
+       m_format = RGB24;
+       // force flip because ffmpeg always return the image in the wrong orientation for texture
+       setFlip(true);
+       // construction is OK
+       *hRslt = S_OK;
+}
+
+// destructor
+VideoFFmpeg::~VideoFFmpeg () 
+{
+}
+
+
+// release components
+bool VideoFFmpeg::release()
+{
+       // release
+       if (m_codecCtx)
+       {
+               avcodec_close(m_codecCtx);
+       }
+       if (m_formatCtx)
+       {
+               av_close_input_file(m_formatCtx);
+       }
+       if (m_frame)
+       {
+               av_free(m_frame);
+       }
+       if (m_frameDeinterlaced)
+       {
+               MEM_freeN(m_frameDeinterlaced->data[0]);
+               av_free(m_frameDeinterlaced);
+       }
+       if (m_frameBGR)
+       {
+               MEM_freeN(m_frameBGR->data[0]);
+               av_free(m_frameBGR);
+       }
+       if (m_imgConvertCtx)
+       {
+               sws_freeContext(m_imgConvertCtx);
+       }
+
+       m_codec = NULL;
+       m_codecCtx = NULL;
+       m_formatCtx = NULL;
+       m_frame = NULL;
+       m_frame = NULL;
+       m_frameBGR = NULL;
+       m_imgConvertCtx = NULL;
+
+       // object will be deleted after that
+       return true;
+}
+
+
+// set initial parameters
+void VideoFFmpeg::initParams (short width, short height, float rate)
+{
+       m_captWidth = width;
+       m_captHeight = height;
+       m_captRate = rate;
+}
+
+int VideoFFmpeg::openStream(const char *filename, AVInputFormat *inputFormat, AVFormatParameters *formatParams)
+{
+       AVFormatContext *formatCtx;
+       int                             i, videoStream;
+       AVCodec                 *codec;
+       AVCodecContext  *codecCtx;
+
+       if(av_open_input_file(&formatCtx, filename, inputFormat, 0, formatParams)!=0)
+               return -1;
+
+       if(av_find_stream_info(formatCtx)<0) 
+       {
+               av_close_input_file(formatCtx);
+               return -1;
+       }
+
+       /* Find the first video stream */
+       videoStream=-1;
+       for(i=0; i<formatCtx->nb_streams; i++)
+       {
+               if(formatCtx->streams[i] &&
+                       get_codec_from_stream(formatCtx->streams[i]) && 
+                       (get_codec_from_stream(formatCtx->streams[i])->codec_type==CODEC_TYPE_VIDEO))
+               {
+                       videoStream=i;
+                       break;
+               }
+       }
+
+       if(videoStream==-1) 
+       {
+               av_close_input_file(formatCtx);
+               return -1;
+       }
+
+       codecCtx = get_codec_from_stream(formatCtx->streams[videoStream]);
+
+       /* Find the decoder for the video stream */
+       codec=avcodec_find_decoder(codecCtx->codec_id);
+       if(codec==NULL) 
+       {
+               av_close_input_file(formatCtx);
+               return -1;
+       }
+       codecCtx->workaround_bugs = 1;
+       if(avcodec_open(codecCtx, codec)<0) 
+       {
+               av_close_input_file(formatCtx);
+               return -1;
+       }
+
+#ifdef FFMPEG_OLD_FRAME_RATE
+       if(codecCtx->frame_rate>1000 && codecCtx->frame_rate_base==1)
+               codecCtx->frame_rate_base=1000;
+       m_baseFrameRate = (double)codecCtx->frame_rate / (double)codecCtx->frame_rate_base;
+#else
+       m_baseFrameRate = av_q2d(formatCtx->streams[videoStream]->r_frame_rate);
+#endif
+       if (m_baseFrameRate <= 0.0) 
+               m_baseFrameRate = defFrameRate;
+
+       m_codec = codec;
+       m_codecCtx = codecCtx;
+       m_formatCtx = formatCtx;
+       m_videoStream = videoStream;
+       m_frame = avcodec_alloc_frame();
+       m_frameDeinterlaced = avcodec_alloc_frame();
+       m_frameBGR = avcodec_alloc_frame();
+
+
+       // allocate buffer if deinterlacing is required
+       avpicture_fill((AVPicture*)m_frameDeinterlaced, 
+               (uint8_t*)MEM_callocN(avpicture_get_size(
+               m_codecCtx->pix_fmt,
+               m_codecCtx->width, m_codecCtx->height), 
+               "ffmpeg deinterlace"), 
+               m_codecCtx->pix_fmt, m_codecCtx->width, m_codecCtx->height);
+
+       // allocate buffer to store final decoded frame
+       avpicture_fill((AVPicture*)m_frameBGR, 
+               (uint8_t*)MEM_callocN(avpicture_get_size(
+               PIX_FMT_BGR24,
+               m_codecCtx->width, m_codecCtx->height),
+               "ffmpeg bgr"),
+               PIX_FMT_BGR24, m_codecCtx->width, m_codecCtx->height);
+       // allocate sws context
+       m_imgConvertCtx = sws_getContext(
+               m_codecCtx->width,
+               m_codecCtx->height,
+               m_codecCtx->pix_fmt,
+               m_codecCtx->width,
+               m_codecCtx->height,
+               PIX_FMT_BGR24,
+               SWS_FAST_BILINEAR,
+               NULL, NULL, NULL);
+
+       if (!m_imgConvertCtx) {
+               avcodec_close(m_codecCtx);
+               av_close_input_file(m_formatCtx);
+               av_free(m_frame);
+               MEM_freeN(m_frameDeinterlaced->data[0]);
+               av_free(m_frameDeinterlaced);
+               MEM_freeN(m_frameBGR->data[0]);
+               av_free(m_frameBGR);
+               return -1;
+       }
+       return 0;
+}
+
+// open video file
+void VideoFFmpeg::openFile (char * filename)
+{
+       do_init_ffmpeg();
+
+       if (openStream(filename, NULL, NULL) != 0)
+               return;
+
+       if (m_codecCtx->gop_size)
+               m_preseek = (m_codecCtx->gop_size < 25) ? m_codecCtx->gop_size+1 : 25;
+       else if (m_codecCtx->has_b_frames)              
+               m_preseek = 25; // should determine gopsize
+       else
+               m_preseek = 0;
+
+       // get video time range
+       m_range[0] = 0.0;
+       m_range[1] = (double)m_formatCtx->duration / AV_TIME_BASE;
+
+       // open base class
+       VideoBase::openFile(filename);
+
+       if (m_formatCtx->pb->is_streamed)
+       {
+               // the file is in fact a streaming source, prevent seeking
+               m_isFile = false;
+               // for streaming it is important to do non blocking read
+               m_formatCtx->flags |= AVFMT_FLAG_NONBLOCK;
+       }
+}
+
+
+// open video capture device
+void VideoFFmpeg::openCam (char * file, short camIdx)
+{
+       // open camera source
+       AVInputFormat           *inputFormat;
+       AVFormatParameters      formatParams;
+       AVRational                      frameRate;
+       char                            *p, filename[28], rateStr[20];
+
+       do_init_ffmpeg();
+
+       memset(&formatParams, 0, sizeof(formatParams));
+#ifdef WIN32
+       // video capture on windows only through Video For Windows driver
+       inputFormat = av_find_input_format("vfwcap");
+       if (!inputFormat)
+               // Video For Windows not supported??
+               return;
+       sprintf(filename, "%d", camIdx);
+#else
+       // In Linux we support two types of devices: VideoForLinux and DV1394. 
+       // the user specify it with the filename:
+       // [<device_type>][:<standard>]
+       // <device_type> : 'v4l' for VideoForLinux, 'dv1394' for DV1394. By default 'v4l'
+       // <standard>    : 'pal', 'secam' or 'ntsc'. By default 'ntsc'
+       // The driver name is constructed automatically from the device type:
+       // v4l   : /dev/video<camIdx>
+       // dv1394: /dev/dv1394/<camIdx>
+       // If you have different driver name, you can specify the driver name explicitely 
+       // instead of device type. Examples of valid filename:
+       //    /dev/v4l/video0:pal
+       //    /dev/ieee1394/1:ntsc
+       //    dv1394:secam
+       //    v4l:pal
+       if (file && strstr(file, "1394") != NULL) 
+       {
+               // the user specifies a driver, check if it is v4l or d41394
+               inputFormat = av_find_input_format("dv1394");
+               sprintf(filename, "/dev/dv1394/%d", camIdx);
+       } else 
+       {
+               inputFormat = av_find_input_format("video4linux");
+               sprintf(filename, "/dev/video%d", camIdx);
+       }
+       if (!inputFormat)
+               // these format should be supported, check ffmpeg compilation
+               return;
+       if (file && strncmp(file, "/dev", 4) == 0) 
+       {
+               // user does not specify a driver
+               strncpy(filename, file, sizeof(filename));
+               filename[sizeof(filename)-1] = 0;
+               if ((p = strchr(filename, ':')) != 0)
+                       *p = 0;
+       }
+       if (file && (p = strchr(file, ":")) != NULL)
+               formatParams.standard = p+1;
+#endif
+       //frame rate
+       if (m_captRate <= 0.f)
+               m_captRate = defFrameRate;
+       sprintf(rateStr, "%f", m_captRate);
+       av_parse_video_frame_rate(&frameRate, rateStr);
+       // populate format parameters
+       // need to specify the time base = inverse of rate
+       formatParams.time_base.num = frameRate.den;
+       formatParams.time_base.den = frameRate.num;
+       formatParams.width = m_captWidth;
+       formatParams.height = m_captHeight;
+
+       if (openStream(filename, inputFormat, &formatParams) != 0)
+               return;
+
+       // for video capture it is important to do non blocking read
+       m_formatCtx->flags |= AVFMT_FLAG_NONBLOCK;
+       // open base class
+       VideoBase::openCam(file, camIdx);
+}
+
+
+// play video
+bool VideoFFmpeg::play (void)
+{
+       try
+       {
+               // if object is able to play
+               if (VideoBase::play())
+               {
+                       // set video position
+                       setPositions();
+                       // return success
+                       return true;
+               }
+       }
+       CATCH_EXCP;
+       return false;
+}
+
+
+// stop video
+bool VideoFFmpeg::stop (void)
+{
+       try
+       {
+               if (VideoBase::stop())
+               {
+                       return true;
+               }
+       }
+       CATCH_EXCP;
+       return false;
+}
+
+
+// set video range
+void VideoFFmpeg::setRange (double start, double stop)
+{
+       try
+       {
+               // set range
+               VideoBase::setRange(start, stop);
+               // set range for video
+               setPositions();
+       }
+       CATCH_EXCP;
+}
+
+// set framerate
+void VideoFFmpeg::setFrameRate (float rate)
+{
+       VideoBase::setFrameRate(rate);
+}
+
+
+// image calculation
+void VideoFFmpeg::calcImage (unsigned int texId)
+{
+       loadFrame();
+}
+
+
+// load frame from video
+void VideoFFmpeg::loadFrame (void)
+{
+       // get actual time
+       double actTime = PIL_check_seconds_timer() - m_startTime;
+       // if video has ended
+       if (m_isFile && actTime * m_frameRate >= m_range[1])
+       {
+               // if repeats are set, decrease them
+               if (m_repeat > 0) 
+                       --m_repeat;
+               // if video has to be replayed
+               if (m_repeat != 0)
+               {
+                       // reset its position
+                       actTime -= (m_range[1] - m_range[0]) / m_frameRate;
+                       m_startTime += (m_range[1] - m_range[0]) / m_frameRate;
+               }
+               // if video has to be stopped, stop it
+               else 
+                       m_status = SourceStopped;
+       }
+       // if video is playing
+       if (m_status == SourcePlaying)
+       {
+               // actual frame
+               long actFrame = m_isFile ? long(actTime * actFrameRate()) : m_lastFrame + 1;
+               // if actual frame differs from last frame
+               if (actFrame != m_lastFrame)
+               {
+                       // get image
+                       if(grabFrame(actFrame))
+                       {
+                               AVFrame* frame = getFrame();
+                               // save actual frame
+                               m_lastFrame = actFrame;
+                               // init image, if needed
+                               init(short(m_codecCtx->width), short(m_codecCtx->height));
+                               // process image
+                               process((BYTE*)(frame->data[0]));
+                       }
+               }
+       }
+}
+
+
+// set actual position
+void VideoFFmpeg::setPositions (void)
+{
+       // set video start time
+       m_startTime = PIL_check_seconds_timer();
+       // if file is played and actual position is before end position
+       if (m_isFile && m_lastFrame >= 0 && m_lastFrame < m_range[1] * actFrameRate())
+               // continue from actual position
+               m_startTime -= double(m_lastFrame) / actFrameRate();
+       else
+               m_startTime -= m_range[0];
+}
+
+// position pointer in file, position in second
+bool VideoFFmpeg::grabFrame(long position)
+{
+       AVPacket packet;
+       int frameFinished;
+       int posFound = 1;
+       bool frameLoaded = false;
+       long long targetTs = 0;
+
+       // first check if the position that we are looking for is in the preseek range
+       // if so, just read the frame until we get there
+       if (position > m_curPosition + 1 
+               && m_preseek 
+               && position - (m_curPosition + 1) < m_preseek) 
+       {
+               while(av_read_frame(m_formatCtx, &packet)>=0) 
+               {
+                       if (packet.stream_index == m_videoStream) 
+                       {
+                               avcodec_decode_video(
+                                       m_codecCtx, 
+                                       m_frame, &frameFinished, 
+                                       packet.data, packet.size);
+                               if (frameFinished)
+                                       m_curPosition++;
+                       }
+                       av_free_packet(&packet);
+                       if (position == m_curPosition+1)
+                               break;
+               }
+       }
+       // if the position is not in preseek, do a direct jump
+       if (position != m_curPosition + 1) { 
+               double timeBase = av_q2d(m_formatCtx->streams[m_videoStream]->time_base);
+               long long pos = (long long)
+                       ((long long) (position - m_preseek) * AV_TIME_BASE / m_baseFrameRate);
+               long long startTs = m_formatCtx->streams[m_videoStream]->start_time;
+
+               if (pos < 0)
+                       pos = 0;
+
+               if (startTs != AV_NOPTS_VALUE)
+                       pos += (long long)(startTs * AV_TIME_BASE * timeBase);
+
+               av_seek_frame(m_formatCtx, -1, pos, AVSEEK_FLAG_BACKWARD);
+               // current position is now lost, guess a value. 
+               // It's not important because it will be set at this end of this function
+               m_curPosition = position - m_preseek - 1;
+               // this is the timestamp of the frame we're looking for
+               targetTs = (long long)(((double) position) / m_baseFrameRate / timeBase);
+               if (startTs != AV_NOPTS_VALUE)
+                       targetTs += startTs;
+
+               posFound = 0;
+               avcodec_flush_buffers(m_codecCtx);
+       }
+
+       while(av_read_frame(m_formatCtx, &packet)>=0) 
+       {
+               if(packet.stream_index == m_videoStream) 
+               {
+                       avcodec_decode_video(m_codecCtx, 
+                               m_frame, &frameFinished, 
+                               packet.data, packet.size);
+
+                       if (frameFinished && !posFound) 
+                       {
+                               if (packet.dts >= targetTs)
+                                       posFound = 1;
+                       } 
+
+                       if(frameFinished && posFound == 1) 
+                       {
+                               AVFrame * input = m_frame;
+
+                               /* This means the data wasnt read properly, 
+                               this check stops crashing */
+                               if (   input->data[0]==0 && input->data[1]==0 
+                                       && input->data[2]==0 && input->data[3]==0)
+                               {
+                                       av_free_packet(&packet);
+                                       break;
+                               }
+
+                               if (m_deinterlace) 
+                               {
+                                       if (avpicture_deinterlace(
+                                               (AVPicture*) m_frameDeinterlaced,
+                                               (const AVPicture*) m_frame,
+                                               m_codecCtx->pix_fmt,
+                                               m_codecCtx->width,
+                                               m_codecCtx->height) >= 0)
+                                       {
+                                               input = m_frameDeinterlaced;
+                                       }
+                               }
+                               // convert to BGR24
+                               sws_scale(m_imgConvertCtx,
+                                       input->data,
+                                       input->linesize,
+                                       0,
+                                       m_codecCtx->height,
+                                       m_frameBGR->data,
+                                       m_frameBGR->linesize);
+                               av_free_packet(&packet);
+                               frameLoaded = true;
+                               break;
+                       }
+               }
+               av_free_packet(&packet);
+       }
+       if (frameLoaded)
+               m_curPosition = position;
+       return frameLoaded;
+}
+
+
+// python methods
+
+
+// cast Image pointer to VideoFFmpeg
+inline VideoFFmpeg * getVideoFFmpeg (PyImage * self)
+{ return static_cast<VideoFFmpeg*>(self->m_image); }
+
+
+// object initialization
+static int VideoFFmpeg_init (PyObject * pySelf, PyObject * args, PyObject * kwds)
+{
+       PyImage * self = reinterpret_cast<PyImage*>(pySelf);
+       // parameters - video source
+       // file name or format type for capture (only for Linux: video4linux or dv1394)
+       char * file = NULL;
+       // capture device number
+       short capt = -1;
+       // capture width, only if capt is >= 0
+       short width = 0;
+       // capture height, only if capt is >= 0
+       short height = 0;
+       // capture rate, only if capt is >= 0
+       float rate = 25.f;
+
+       static char *kwlist[] = {"file", "capture", "rate", "width", "height", NULL};
+
+       // get parameters
+       if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|hfhh", kwlist, &file, &capt,
+               &rate, &width, &height))
+               return -1; 
+
+       try
+       {
+               // create video object
+               Video_init<VideoFFmpeg>(self);
+
+               // set thread usage
+               getVideoFFmpeg(self)->initParams(width, height, rate);
+
+               // open video source
+               Video_open(getVideo(self), file, capt);
+       }
+       catch (Exception & exp)
+       {
+               exp.report();
+               return -1;
+       }
+       // initialization succeded
+       return 0;
+}
+
+PyObject * VideoFFmpeg_getPreseek (PyImage *self, void * closure)
+{
+       return Py_BuildValue("h", getFFmpeg(self)->getPreseek());
+}
+
+// set range
+int VideoFFmpeg_setPreseek (PyImage * self, PyObject * value, void * closure)
+{
+       // check validity of parameter
+       if (value == NULL || !PyInt_Check(value))
+       {
+               PyErr_SetString(PyExc_TypeError, "The value must be an integer");
+               return -1;
+       }
+       // set preseek
+       getFFmpeg(self)->setPreseek(PyInt_AsLong(value));
+       // success
+       return 0;
+}
+
+// get deinterlace
+PyObject * VideoFFmpeg_getDeinterlace (PyImage * self, void * closure)
+{
+       if (getFFmpeg(self)->getDeinterlace())
+               Py_RETURN_TRUE;
+       else
+               Py_RETURN_FALSE;
+}
+
+// set flip
+int VideoFFmpeg_setDeinterlace (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 deinterlace
+       getFFmpeg(self)->setDeinterlace(value == Py_True);
+       // success
+       return 0;
+}
+
+// methods structure
+static PyMethodDef videoMethods[] =
+{ // methods from VideoBase class
+       {"play", (PyCFunction)Video_play, METH_NOARGS, "Play video"},
+       {"stop", (PyCFunction)Video_stop, METH_NOARGS, "Stop (pause) video"},
+       {"refresh", (PyCFunction)Video_refresh, METH_NOARGS, "Refresh video - get its status"},
+       {NULL}
+};
+// attributes structure
+static PyGetSetDef videoGetSets[] =
+{ // methods from VideoBase class
+       {"status", (getter)Video_getStatus, NULL, "video status", NULL},
+       {"range", (getter)Video_getRange, (setter)Video_setRange, "replay range", NULL},
+       {"repeat", (getter)Video_getRepeat, (setter)Video_setRepeat, "repeat count, -1 for infinite repeat", NULL},
+       {"framerate", (getter)Video_getFrameRate, (setter)Video_setFrameRate, "frame rate", NULL},
+       // attributes from ImageBase class
+       {"image", (getter)Image_getImage, NULL, "image data", NULL},
+       {"size", (getter)Image_getSize, NULL, "image size", NULL},
+       {"scale", (getter)Image_getScale, (setter)Image_setScale, "fast scale of image (near neighbour)", NULL},
+       {"flip", (getter)Image_getFlip, (setter)Image_setFlip, "flip image vertically", NULL},
+       {"filter", (getter)Image_getFilter, (setter)Image_setFilter, "pixel filter", NULL},
+       {"preseek", (getter)VideoFFmpeg_getPreseek, (setter)VideoFFmpeg_setPreseek, "nb of frames of preseek", NULL},
+       {"deinterlace", (getter)VideoFFmpeg_getDeinterlace, (setter)VideoFFmpeg_setDeinterlace, "deinterlace image", NULL},
+       {NULL}
+};
+
+// python type declaration
+PyTypeObject VideoFFmpegType =
+{ 
+       PyObject_HEAD_INIT(NULL)
+       0,                         /*ob_size*/
+       "VideoTexture.VideoFFmpeg",   /*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*/
+       "FFmpeg video source",       /* tp_doc */
+       0,                             /* tp_traverse */
+       0,                             /* tp_clear */
+       0,                             /* tp_richcompare */
+       0,                             /* tp_weaklistoffset */
+       0,                             /* tp_iter */
+       0,                             /* tp_iternext */
+       videoMethods,    /* tp_methods */
+       0,                   /* tp_members */
+       videoGetSets,          /* tp_getset */
+       0,                         /* tp_base */
+       0,                         /* tp_dict */
+       0,                         /* tp_descr_get */
+       0,                         /* tp_descr_set */
+       0,                         /* tp_dictoffset */
+       (initproc)VideoFFmpeg_init,     /* tp_init */
+       0,                         /* tp_alloc */
+       Image_allocNew,           /* tp_new */
+};
+
+
+
+#endif //WITH_FFMPEG
+
+
diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.h b/source/gameengine/VideoTexture/VideoFFmpeg.h
new file mode 100644 (file)
index 0000000..7980e06
--- /dev/null
@@ -0,0 +1,159 @@
+/* $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.
+-----------------------------------------------------------------------------
+*/
+#if !defined VIDEOFFMPEG_H
+#define VIDEOFFMPEG_H
+
+#ifdef WITH_FFMPEG
+extern "C" {
+#include <ffmpeg/avformat.h>
+#include <ffmpeg/avcodec.h>
+#include <ffmpeg/rational.h>
+#include <ffmpeg/swscale.h>
+}
+
+#if LIBAVFORMAT_VERSION_INT < (49 << 16)
+#define FFMPEG_OLD_FRAME_RATE 1
+#else
+#define FFMPEG_CODEC_IS_POINTER 1
+#endif
+
+#ifdef FFMPEG_CODEC_IS_POINTER
+static inline AVCodecContext* get_codec_from_stream(AVStream* stream)
+{
+       return stream->codec;
+}
+#else
+static inline AVCodecContext* get_codec_from_stream(AVStream* stream)
+{
+       return &stream->codec;
+}
+#endif
+
+#include "VideoBase.h"
+
+
+// type VideoFFmpeg declaration
+class VideoFFmpeg : public VideoBase
+{
+public:
+       /// constructor
+       VideoFFmpeg (HRESULT * hRslt);
+       /// destructor
+       virtual ~VideoFFmpeg ();
+
+       /// set initial parameters
+       void initParams (short width, short height, float rate);
+       /// open video file
+       virtual void openFile (char * file);
+       /// open video capture device
+       virtual void openCam (char * driver, short camIdx);
+
+       /// release video source
+       virtual bool release (void);
+
+       /// play video
+       virtual bool play (void);
+       /// stop/pause video
+       virtual bool stop (void);
+
+       /// set play range
+       virtual void setRange (double start, double stop);
+       /// set frame rate
+       virtual void setFrameRate (float rate);
+       // some specific getters and setters
+       int getPreseek(void) { return m_preseek; }
+       void setPreseek(int preseek) { if (preseek >= 0) m_preseek = preseek; }
+       bool getDeinterlace(void) { return m_deinterlace; }
+       void setDeinterlace(bool deinterlace) { m_deinterlace = deinterlace; }
+
+protected:
+
+       // format and codec information
+       AVCodec *m_codec;
+       AVFormatContext *m_formatCtx;
+       AVCodecContext *m_codecCtx;
+       // raw frame extracted from video file
+       AVFrame *m_frame;
+       // deinterlaced frame if codec requires it
+       AVFrame *m_frameDeinterlaced;
+       // decoded RGB24 frame if codec requires it
+       AVFrame *m_frameBGR;
+       // conversion from raw to RGB is done with sws_scale
+       struct SwsContext *m_imgConvertCtx;
+       // should the codec be deinterlaced?
+       bool m_deinterlace;
+       // number of frame of preseek
+       int m_preseek;
+       // order number of stream holding the video in format context
+       int m_videoStream;
+
+       // the actual frame rate
+       double m_baseFrameRate;
+
+       /// last displayed frame
+       long m_lastFrame;
+
+       /// current file pointer position in file expressed in frame number
+       long m_curPosition;
+
+       /// time of video play start
+       double m_startTime;
+
+       /// width of capture in pixel
+       short m_captWidth;
+       
+       /// height of capture in pixel
+       short m_captHeight;
+
+       /// frame rate of capture in frames per seconds
+       float m_captRate;
+
+       /// image calculation
+       virtual void calcImage (unsigned int texId);
+
+       /// load frame from video
+       void loadFrame (void);
+
+       /// set actual position
+       void setPositions (void);
+
+       /// get actual framerate
+       double actFrameRate (void) { return m_frameRate * m_baseFrameRate; }
+
+       /// common function to video file and capture
+       int openStream(const char *filename, AVInputFormat *inputFormat, AVFormatParameters *formatParams);
+
+       /// check if a frame is available and load it in pFrame, return true if a frame could be retrieved
+       bool grabFrame(long frame);
+
+       /// return the frame in RGB24 format, the image data is found in AVFrame.data[0]
+       AVFrame* getFrame(void) { return m_frameBGR; }
+};
+
+inline VideoFFmpeg * getFFmpeg (PyImage * self) 
+{
+       return static_cast<VideoFFmpeg*>(self->m_image); 
+}
+
+#endif //WITH_FFMPEG
+
+#endif
diff --git a/source/gameengine/VideoTexture/blendVideoTex.cpp b/source/gameengine/VideoTexture/blendVideoTex.cpp
new file mode 100644 (file)
index 0000000..0f15a26
--- /dev/null
@@ -0,0 +1,206 @@
+/* $Id$
+-----------------------------------------------------------------------------
+This source file is part of VideoTexure library
+
+Copyright (c) 2006 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.
+-----------------------------------------------------------------------------
+*/
+
+#define PY_ARRAY_UNIQUE_SYMBOL numpyPtr
+
+#include <Python.h>
+
+#include <RAS_GLExtensionManager.h>
+
+#include <RAS_IPolygonMaterial.h>
+
+#include <numpy/arrayobject.h>
+
+//Old API
+//#include "TexPlayer.h"
+//#include "TexImage.h"
+//#include "TexFrameBuff.h"
+
+//#include "TexPlayerGL.h"
+
+#include "ImageBase.h"
+#include "FilterBase.h"
+#include "Texture.h"
+
+#include "Exception.h"
+
+
+// get material id
+static PyObject * getMaterialID (PyObject *self, PyObject *args)
+{
+       // parameters - game object with video texture
+       PyObject * obj = NULL;
+       // material name
+       char * matName;
+
+       // get parameters
+       if (!PyArg_ParseTuple(args, "Os", &obj, &matName))
+               return NULL;
+       // get material id
+       short matID = getMaterialID(obj, matName);
+       // if material was not found, report errot
+       if (matID < 0)
+       {
+               PyErr_SetString(PyExc_RuntimeError, "object doesn't have material with given name");
+               return NULL;
+       }
+       // return material ID
+       return Py_BuildValue("h", matID);
+}
+
+
+// get last error description
+static PyObject * getLastError (PyObject *self, PyObject *args)
+{
+       return Py_BuildValue("s", Exception::m_lastError.c_str());
+}
+
+// set log file
+static PyObject * setLogFile (PyObject *self, PyObject *args)
+{
+       // get parameters
+       if (!PyArg_ParseTuple(args, "s", &Exception::m_logFile))
+               return Py_BuildValue("i", -1);
+       // log file was loaded
+       return Py_BuildValue("i", 0);
+}
+
+
+// function to initialize numpy structures
+static bool initNumpy (void)
+{
+       // init module and report failure
+       import_array1(false);
+       // report success
+       return true;
+}
+
+// image to numpy array
+static PyObject * imageToArray (PyObject * self, PyObject *args)
+{
+       // parameter is Image object
+       PyObject * pyImg;
+       if (!PyArg_ParseTuple(args, "O", &pyImg) || !pyImageTypes.in(pyImg->ob_type))
+       {
+               // if object is incorect, report error
+               PyErr_SetString(PyExc_TypeError, "The value must be a image source object");
+               return NULL;
+       }
+       // get image structure
+       PyImage * img = reinterpret_cast<PyImage*>(pyImg);
+       // check initialization of numpy interface, and initialize it if needed
+       if (numpyPtr == NULL && !initNumpy()) Py_RETURN_NONE;
+       // create array object
+       npy_intp dim[1];
+       dim[0] = img->m_image->getBuffSize() / sizeof(unsigned int);
+       unsigned int * imgBuff = img->m_image->getImage();
+       // if image is available, convert it to array
+       if (imgBuff != NULL)
+               return PyArray_SimpleNewFromData(1, dim, NPY_UBYTE, imgBuff);
+       // otherwise return None
+       Py_RETURN_NONE;
+}
+
+
+// metody modulu
+static PyMethodDef moduleMethods[] =
+{
+       {"materialID", getMaterialID, METH_VARARGS, "Gets object's Blender Material ID"},
+       {"getLastError", getLastError, METH_NOARGS, "Gets last error description"},
+       {"setLogFile", setLogFile, METH_VARARGS, "Sets log file name"},
+       {"imageToArray", imageToArray, METH_VARARGS, "get array from image source"},
+       {NULL}  /* Sentinel */
+};
+
+#if WITH_FFMPEG
+extern PyTypeObject VideoFFmpegType;
+#endif
+extern PyTypeObject FilterBlueScreenType;
+extern PyTypeObject FilterGrayType;
+extern PyTypeObject FilterColorType;
+extern PyTypeObject FilterLevelType;
+extern PyTypeObject FilterNormalType;
+extern PyTypeObject FilterRGB24Type;
+extern PyTypeObject FilterBGR24Type;
+extern PyTypeObject ImageBuffType;
+extern PyTypeObject ImageMixType;
+extern PyTypeObject ImageRenderType;
+extern PyTypeObject ImageViewportType;
+extern PyTypeObject ImageViewportType;
+
+
+static void registerAllTypes(void)
+{
+#if WITH_FFMPEG
+       pyImageTypes.add(&VideoFFmpegType, "VideoFFmpeg");
+#endif
+       pyImageTypes.add(&ImageBuffType, "ImageBuff");
+       pyImageTypes.add(&ImageMixType, "ImageMix");
+       //pyImageTypes.add(&ImageRenderType, "ImageRender");
+       pyImageTypes.add(&ImageViewportType, "ImageViewport");
+
+       pyFilterTypes.add(&FilterBlueScreenType, "FilterBlueScreen");
+       pyFilterTypes.add(&FilterGrayType, "FilterGray");
+       pyFilterTypes.add(&FilterColorType, "FilterColor");
+       pyFilterTypes.add(&FilterLevelType, "FilterLevel");
+       pyFilterTypes.add(&FilterNormalType, "FilterNormal");
+       pyFilterTypes.add(&FilterRGB24Type, "FilterRGB24");
+       pyFilterTypes.add(&FilterBGR24Type, "FilterBGR24");
+}
+
+PyObject* initVideoTexture(void) 
+{
+       // initialize GL extensions
+       //bgl::InitExtensions(0);
+
+       // prepare classes
+       registerAllTypes();
+
+       if (!pyImageTypes.ready()) 
+               return NULL;
+       if (!pyFilterTypes.ready()) 
+               return NULL;
+       if (PyType_Ready(&TextureType) < 0) 
+               return NULL;
+
+       PyObject * m = Py_InitModule4("VideoTexture", moduleMethods,
+               "Module that allows to play video files on textures in GameBlender.",
+               (PyObject*)NULL,PYTHON_API_VERSION);
+       if (m == NULL) 
+               return NULL;
+
+       // prepare numpy array
+       numpyPtr = NULL;
+
+       // initialize classes
+       pyImageTypes.reg(m);
+       pyFilterTypes.reg(m);
+
+       Py_INCREF(&TextureType);
+       PyModule_AddObject(m, "Texture", (PyObject*)&TextureType);
+
+       // init last error description
+       Exception::m_lastError[0] = '\0';
+       return m;
+}
+
+// registration to Image types, put here because of silly linker bug