svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r17236:HEAD
This commit is contained in:
parent
5b205ce852
commit
3c9520f92f
@ -251,9 +251,9 @@ else:
|
|||||||
##
|
##
|
||||||
CC = 'gcc'
|
CC = 'gcc'
|
||||||
CXX = 'g++'
|
CXX = 'g++'
|
||||||
C_WARN = ' -Wall -Wno-long-double -Wdeclaration-after-statement '
|
C_WARN = ['-Wdeclaration-after-statement']
|
||||||
|
|
||||||
CC_WARN = ' -Wall -Wno-long-double'
|
CC_WARN = ['-Wall', '-Wno-long-double']
|
||||||
|
|
||||||
##FIX_STUBS_WARNINGS = -Wno-unused
|
##FIX_STUBS_WARNINGS = -Wno-unused
|
||||||
|
|
||||||
|
@ -145,9 +145,9 @@ REL_CCFLAGS = ['-O2']
|
|||||||
##
|
##
|
||||||
CC = 'gcc'
|
CC = 'gcc'
|
||||||
CXX = 'g++'
|
CXX = 'g++'
|
||||||
C_WARN = '-Wall -Wdeclaration-after-statement'
|
C_WARN = ['-Wdeclaration-after-statement']
|
||||||
|
|
||||||
CC_WARN = '-Wall'
|
CC_WARN = ['-Wall']
|
||||||
|
|
||||||
##FIX_STUBS_WARNINGS = -Wno-unused
|
##FIX_STUBS_WARNINGS = -Wno-unused
|
||||||
|
|
||||||
|
@ -159,9 +159,9 @@ REL_CCFLAGS = ['-O2']
|
|||||||
##ARFLAGS = ruv
|
##ARFLAGS = ruv
|
||||||
##ARFLAGSQUIET = ru
|
##ARFLAGSQUIET = ru
|
||||||
##
|
##
|
||||||
C_WARN = '-Wall -Wno-char-subscripts -Wdeclaration-after-statement'
|
C_WARN = ['-Wno-char-subscripts', '-Wdeclaration-after-statement']
|
||||||
|
|
||||||
CC_WARN = '-Wall'
|
CC_WARN = ['-Wall']
|
||||||
|
|
||||||
##FIX_STUBS_WARNINGS = -Wno-unused
|
##FIX_STUBS_WARNINGS = -Wno-unused
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ CXXFLAGS = ['-pipe', '-mwindows', '-funsigned-char', '-fno-strict-aliasing' ]
|
|||||||
REL_CFLAGS = [ '-O2' ]
|
REL_CFLAGS = [ '-O2' ]
|
||||||
REL_CCFLAGS = [ '-O2' ]
|
REL_CCFLAGS = [ '-O2' ]
|
||||||
|
|
||||||
C_WARN = [ '-Wall' , '-Wno-char-subscripts', '-Wdeclaration-after-statement' ]
|
C_WARN = [ '-Wno-char-subscripts', '-Wdeclaration-after-statement' ]
|
||||||
|
|
||||||
CC_WARN = [ '-Wall' ]
|
CC_WARN = [ '-Wall' ]
|
||||||
|
|
||||||
|
@ -161,6 +161,7 @@ CC = 'cl.exe'
|
|||||||
CXX = 'cl.exe'
|
CXX = 'cl.exe'
|
||||||
|
|
||||||
CCFLAGS = ['/nologo', '/Ob1', '/J', '/W3', '/Gd', '/MT']
|
CCFLAGS = ['/nologo', '/Ob1', '/J', '/W3', '/Gd', '/MT']
|
||||||
|
CXXFLAGS = ['/EHsc']
|
||||||
|
|
||||||
BF_DEBUG_CCFLAGS = ['/Zi', '/FR${TARGET}.sbr']
|
BF_DEBUG_CCFLAGS = ['/Zi', '/FR${TARGET}.sbr']
|
||||||
|
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
$Id$
|
$Id$
|
||||||
|
|
||||||
Note: The current official release of SCons is 0.98, but
|
|
||||||
our system still works for 0.97. However, this will be fixed
|
|
||||||
soon.
|
|
||||||
|
|
||||||
Blenders SCons build scripts
|
Blenders SCons build scripts
|
||||||
============================
|
============================
|
||||||
|
|
||||||
@ -31,7 +27,7 @@ $Id$
|
|||||||
|
|
||||||
To build Blender with the SCons scripts you need a full Python
|
To build Blender with the SCons scripts you need a full Python
|
||||||
install, version 2.4 or later (http://www.python.org) and a SCons
|
install, version 2.4 or later (http://www.python.org) and a SCons
|
||||||
installation, version v0.97 (http://www.scons.org).
|
installation, version v1.1.0 (http://www.scons.org).
|
||||||
|
|
||||||
Check from the page
|
Check from the page
|
||||||
http://www.blender.org/development/building-blender/getting-dependencies/
|
http://www.blender.org/development/building-blender/getting-dependencies/
|
||||||
|
@ -854,7 +854,7 @@ static int WeightPixelFormat(PIXELFORMATDESCRIPTOR& pfd) {
|
|||||||
static int EnumPixelFormats(HDC hdc) {
|
static int EnumPixelFormats(HDC hdc) {
|
||||||
int iPixelFormat;
|
int iPixelFormat;
|
||||||
int i, n, w, weight = 0;
|
int i, n, w, weight = 0;
|
||||||
PIXELFORMATDESCRIPTOR pfd, pfd_fallback;
|
PIXELFORMATDESCRIPTOR pfd;
|
||||||
|
|
||||||
/* we need a device context to do anything */
|
/* we need a device context to do anything */
|
||||||
if(!hdc) return 0;
|
if(!hdc) return 0;
|
||||||
|
@ -17,6 +17,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "blender", "blender.vcproj",
|
|||||||
{138DD16C-CC78-4F6C-A898-C8DA68D89067} = {138DD16C-CC78-4F6C-A898-C8DA68D89067}
|
{138DD16C-CC78-4F6C-A898-C8DA68D89067} = {138DD16C-CC78-4F6C-A898-C8DA68D89067}
|
||||||
{415BFD6E-64CF-422B-AF88-C07F040A7292} = {415BFD6E-64CF-422B-AF88-C07F040A7292}
|
{415BFD6E-64CF-422B-AF88-C07F040A7292} = {415BFD6E-64CF-422B-AF88-C07F040A7292}
|
||||||
{106AE171-0083-41D6-A949-20DB0E8DC251} = {106AE171-0083-41D6-A949-20DB0E8DC251}
|
{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}
|
{4C3AB78A-52CA-4276-A041-39776E52D8C8} = {4C3AB78A-52CA-4276-A041-39776E52D8C8}
|
||||||
{6B801390-5F95-4F07-81A7-97FBA046AACC} = {6B801390-5F95-4F07-81A7-97FBA046AACC}
|
{6B801390-5F95-4F07-81A7-97FBA046AACC} = {6B801390-5F95-4F07-81A7-97FBA046AACC}
|
||||||
{CAE37E91-6570-43AC-A4B4-7A37A4B0FC94} = {CAE37E91-6570-43AC-A4B4-7A37A4B0FC94}
|
{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
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
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
|
Global
|
||||||
GlobalSection(SolutionConfiguration) = preSolution
|
GlobalSection(SolutionConfiguration) = preSolution
|
||||||
3D Plugin Debug = 3D Plugin Debug
|
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}.Debug.Build.0 = BlenderPlayer Debug|Win32
|
||||||
{138DD16C-CC78-4F6C-A898-C8DA68D89067}.Release.ActiveCfg = BlenderPlayer Release|Win32
|
{138DD16C-CC78-4F6C-A898-C8DA68D89067}.Release.ActiveCfg = BlenderPlayer Release|Win32
|
||||||
{138DD16C-CC78-4F6C-A898-C8DA68D89067}.Release.Build.0 = 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
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
@ -124,7 +124,7 @@ ECHO Done
|
|||||||
Name="VCLinkerTool"
|
Name="VCLinkerTool"
|
||||||
AdditionalOptions="/MACHINE:I386
|
AdditionalOptions="/MACHINE:I386
|
||||||
"
|
"
|
||||||
AdditionalDependencies="SDL.lib freetype2ST.lib ftgl_static.lib gnu_gettext.lib qtmlClient.lib openal_static.lib libsoundsystem.lib libopenalsoundsystem.lib libdummysoundsystem.lib libguardedalloc.lib libbsp.lib libbmfont.lib libghost.lib libstring.lib ws2_32.lib dxguid.lib opengl32.lib libjpeg.lib glu32.lib vfw32.lib winmm.lib libdecimation.lib libiksolver.lib libpng_st.lib zlib.lib libmoto.lib solid.lib qhull.lib libopennl.lib Bullet.lib python25_d.lib libelbeem.lib libboolop.lib pthreadVSE2.lib pthreadVC2.lib libtiff.lib broad.lib complex.lib convex.lib memutil.lib verse.lib Half.lib Iex.lib Imath.lib IlmImf.lib IlmThread.lib avcodec-51.lib avformat-52.lib avutil-49.lib swscale-0.lib glew.lib"
|
AdditionalDependencies="SDL.lib freetype2ST.lib ftgl_static.lib gnu_gettext.lib qtmlClient.lib openal_static.lib libsoundsystem.lib libopenalsoundsystem.lib libdummysoundsystem.lib libguardedalloc.lib libbsp.lib libbmfont.lib libghost.lib libstring.lib ws2_32.lib dxguid.lib opengl32.lib libjpeg.lib glu32.lib vfw32.lib winmm.lib libdecimation.lib libiksolver.lib libpng_st.lib zlib.lib libmoto.lib solid.lib qhull.lib libopennl.lib Bullet.lib python25_d.lib libelbeem.lib libboolop.lib pthreadVSE2.lib pthreadVC2.lib libtiff.lib broad.lib complex.lib convex.lib memutil.lib verse.lib Half.lib Iex.lib Imath.lib IlmImf.lib IlmThread.lib avcodec-51.lib avformat-52.lib avdevice-52.lib avutil-49.lib swscale-0.lib glew.lib"
|
||||||
ShowProgress="0"
|
ShowProgress="0"
|
||||||
OutputFile="..\..\bin\debug\blender.exe"
|
OutputFile="..\..\bin\debug\blender.exe"
|
||||||
LinkIncremental="2"
|
LinkIncremental="2"
|
||||||
|
@ -382,6 +382,9 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\source\blender\blenlib\intern\freetypefont.c">
|
RelativePath="..\..\..\source\blender\blenlib\intern\freetypefont.c">
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\source\blender\blenlib\intern\graph.c">
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\source\blender\blenlib\intern\gsqueue.c">
|
RelativePath="..\..\..\source\blender\blenlib\intern\gsqueue.c">
|
||||||
</File>
|
</File>
|
||||||
@ -458,6 +461,9 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\source\blender\blenlib\BLI_ghash.h">
|
RelativePath="..\..\..\source\blender\blenlib\BLI_ghash.h">
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\source\blender\blenlib\BLI_graph.h">
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\source\blender\blenlib\BLI_heap.h">
|
RelativePath="..\..\..\source\blender\blenlib\BLI_heap.h">
|
||||||
</File>
|
</File>
|
||||||
|
@ -121,6 +121,9 @@
|
|||||||
<Filter
|
<Filter
|
||||||
Name="Source Files"
|
Name="Source Files"
|
||||||
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
|
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\source\blender\src\autoarmature.c">
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\source\blender\src\B.blend.c">
|
RelativePath="..\..\..\source\blender\src\B.blend.c">
|
||||||
</File>
|
</File>
|
||||||
|
@ -1245,9 +1245,11 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
avgSharpness /= sharpCount;
|
if(sharpCount) {
|
||||||
if (avgSharpness>1.0) {
|
avgSharpness /= sharpCount;
|
||||||
avgSharpness = 1.0;
|
if (avgSharpness>1.0) {
|
||||||
|
avgSharpness = 1.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (seam && seamEdges < 2)
|
if (seam && seamEdges < 2)
|
||||||
@ -1543,9 +1545,11 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
avgSharpness /= sharpCount;
|
if(sharpCount) {
|
||||||
if (avgSharpness>1.0) {
|
avgSharpness /= sharpCount;
|
||||||
avgSharpness = 1.0;
|
if (avgSharpness>1.0) {
|
||||||
|
avgSharpness = 1.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (seam && seamEdges < 2)
|
if (seam && seamEdges < 2)
|
||||||
|
@ -64,6 +64,7 @@
|
|||||||
#ifdef WITH_FFMPEG
|
#ifdef WITH_FFMPEG
|
||||||
#include <ffmpeg/avcodec.h>
|
#include <ffmpeg/avcodec.h>
|
||||||
#include <ffmpeg/avformat.h>
|
#include <ffmpeg/avformat.h>
|
||||||
|
//#include <ffmpeg/avdevice.h>
|
||||||
|
|
||||||
#if LIBAVFORMAT_VERSION_INT < (49 << 16)
|
#if LIBAVFORMAT_VERSION_INT < (49 << 16)
|
||||||
#define FFMPEG_OLD_FRAME_RATE 1
|
#define FFMPEG_OLD_FRAME_RATE 1
|
||||||
@ -236,6 +237,7 @@ void do_init_ffmpeg()
|
|||||||
if (!ffmpeg_init) {
|
if (!ffmpeg_init) {
|
||||||
ffmpeg_init = 1;
|
ffmpeg_init = 1;
|
||||||
av_register_all();
|
av_register_all();
|
||||||
|
//avdevice_register_all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,8 +246,8 @@ PyObject *Matrix_Invert(MatrixObject * self)
|
|||||||
/*calculate the classical adjoint*/
|
/*calculate the classical adjoint*/
|
||||||
if(self->rowSize == 2) {
|
if(self->rowSize == 2) {
|
||||||
mat[0] = self->matrix[1][1];
|
mat[0] = self->matrix[1][1];
|
||||||
mat[1] = -self->matrix[1][0];
|
mat[1] = -self->matrix[0][1];
|
||||||
mat[2] = -self->matrix[0][1];
|
mat[2] = -self->matrix[1][0];
|
||||||
mat[3] = self->matrix[0][0];
|
mat[3] = self->matrix[0][0];
|
||||||
} else if(self->rowSize == 3) {
|
} else if(self->rowSize == 3) {
|
||||||
Mat3Adj((float (*)[3]) mat,(float (*)[3]) *self->matrix);
|
Mat3Adj((float (*)[3]) mat,(float (*)[3]) *self->matrix);
|
||||||
|
@ -439,12 +439,19 @@ static void render_envmap(Render *re, EnvMap *env)
|
|||||||
|
|
||||||
if(re->test_break()==0) {
|
if(re->test_break()==0) {
|
||||||
RenderLayer *rl= envre->result->layers.first;
|
RenderLayer *rl= envre->result->layers.first;
|
||||||
|
int y;
|
||||||
|
char *alpha;
|
||||||
|
|
||||||
ibuf= IMB_allocImBuf(envre->rectx, envre->recty, 24, IB_rect, 0);
|
ibuf= IMB_allocImBuf(envre->rectx, envre->recty, 24, IB_rect, 0);
|
||||||
ibuf->rect_float= rl->rectf;
|
ibuf->rect_float= rl->rectf;
|
||||||
IMB_rect_from_float(ibuf);
|
IMB_rect_from_float(ibuf);
|
||||||
ibuf->rect_float= NULL;
|
ibuf->rect_float= NULL;
|
||||||
|
|
||||||
|
/* envmap renders without alpha */
|
||||||
|
alpha= ((char *)ibuf->rect)+3;
|
||||||
|
for(y= ibuf->x*ibuf->y - 1; y>=0; y--, alpha+=4)
|
||||||
|
*alpha= 255;
|
||||||
|
|
||||||
env->cube[part]= ibuf;
|
env->cube[part]= ibuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,13 +451,13 @@ static void compute_radiance(ScatterTree *tree, float *co, float *rad)
|
|||||||
VECCOPY(rdsum, result.rdsum);
|
VECCOPY(rdsum, result.rdsum);
|
||||||
VECADD(backrdsum, result.rdsum, result.backrdsum);
|
VECADD(backrdsum, result.rdsum, result.backrdsum);
|
||||||
|
|
||||||
if(rdsum[0] > 0.0f) rad[0]= tree->ss[0]->color*rad[0]/rdsum[0];
|
if(rdsum[0] > 1e-16f) rad[0]= tree->ss[0]->color*rad[0]/rdsum[0];
|
||||||
if(rdsum[1] > 0.0f) rad[1]= tree->ss[1]->color*rad[1]/rdsum[1];
|
if(rdsum[1] > 1e-16f) rad[1]= tree->ss[1]->color*rad[1]/rdsum[1];
|
||||||
if(rdsum[2] > 0.0f) rad[2]= tree->ss[2]->color*rad[2]/rdsum[2];
|
if(rdsum[2] > 1e-16f) rad[2]= tree->ss[2]->color*rad[2]/rdsum[2];
|
||||||
|
|
||||||
if(backrdsum[0] > 0.0f) backrad[0]= tree->ss[0]->color*backrad[0]/backrdsum[0];
|
if(backrdsum[0] > 1e-16f) backrad[0]= tree->ss[0]->color*backrad[0]/backrdsum[0];
|
||||||
if(backrdsum[1] > 0.0f) backrad[1]= tree->ss[1]->color*backrad[1]/backrdsum[1];
|
if(backrdsum[1] > 1e-16f) backrad[1]= tree->ss[1]->color*backrad[1]/backrdsum[1];
|
||||||
if(backrdsum[2] > 0.0f) backrad[2]= tree->ss[2]->color*backrad[2]/backrdsum[2];
|
if(backrdsum[2] > 1e-16f) backrad[2]= tree->ss[2]->color*backrad[2]/backrdsum[2];
|
||||||
|
|
||||||
rad[0]= MAX2(rad[0], backrad[0]);
|
rad[0]= MAX2(rad[0], backrad[0]);
|
||||||
rad[1]= MAX2(rad[1], backrad[1]);
|
rad[1]= MAX2(rad[1], backrad[1]);
|
||||||
@ -504,20 +504,20 @@ static void sum_leaf_radiance(ScatterTree *tree, ScatterNode *node)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(node->area > 0) {
|
if(node->area > 1e-16f) {
|
||||||
inv= 1.0/node->area;
|
inv= 1.0/node->area;
|
||||||
node->rad[0] *= inv;
|
node->rad[0] *= inv;
|
||||||
node->rad[1] *= inv;
|
node->rad[1] *= inv;
|
||||||
node->rad[2] *= inv;
|
node->rad[2] *= inv;
|
||||||
}
|
}
|
||||||
if(node->backarea > 0) {
|
if(node->backarea > 1e-16f) {
|
||||||
inv= 1.0/node->backarea;
|
inv= 1.0/node->backarea;
|
||||||
node->backrad[0] *= inv;
|
node->backrad[0] *= inv;
|
||||||
node->backrad[1] *= inv;
|
node->backrad[1] *= inv;
|
||||||
node->backrad[2] *= inv;
|
node->backrad[2] *= inv;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(totrad > 0.0f) {
|
if(totrad > 1e-16f) {
|
||||||
inv= 1.0/totrad;
|
inv= 1.0/totrad;
|
||||||
node->co[0] *= inv;
|
node->co[0] *= inv;
|
||||||
node->co[1] *= inv;
|
node->co[1] *= inv;
|
||||||
@ -578,20 +578,20 @@ static void sum_branch_radiance(ScatterTree *tree, ScatterNode *node)
|
|||||||
node->backarea += subnode->backarea;
|
node->backarea += subnode->backarea;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(node->area > 0) {
|
if(node->area > 1e-16f) {
|
||||||
inv= 1.0/node->area;
|
inv= 1.0/node->area;
|
||||||
node->rad[0] *= inv;
|
node->rad[0] *= inv;
|
||||||
node->rad[1] *= inv;
|
node->rad[1] *= inv;
|
||||||
node->rad[2] *= inv;
|
node->rad[2] *= inv;
|
||||||
}
|
}
|
||||||
if(node->backarea > 0) {
|
if(node->backarea > 1e-16f) {
|
||||||
inv= 1.0/node->backarea;
|
inv= 1.0/node->backarea;
|
||||||
node->backrad[0] *= inv;
|
node->backrad[0] *= inv;
|
||||||
node->backrad[1] *= inv;
|
node->backrad[1] *= inv;
|
||||||
node->backrad[2] *= inv;
|
node->backrad[2] *= inv;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(totrad > 0.0f) {
|
if(totrad > 1e-16f) {
|
||||||
inv= 1.0/totrad;
|
inv= 1.0/totrad;
|
||||||
node->co[0] *= inv;
|
node->co[0] *= inv;
|
||||||
node->co[1] *= inv;
|
node->co[1] *= inv;
|
||||||
|
@ -1808,7 +1808,7 @@ static int ui_do_but_TEX(uiBut *but)
|
|||||||
((G.qual & LR_COMMANDKEY) || (G.qual & LR_CTRLKEY)) &&
|
((G.qual & LR_COMMANDKEY) || (G.qual & LR_CTRLKEY)) &&
|
||||||
((dev==XKEY) || (dev==CKEY) || (dev==VKEY)) ) {
|
((dev==XKEY) || (dev==CKEY) || (dev==VKEY)) ) {
|
||||||
|
|
||||||
char buf[UI_MAX_DRAW_STR]={0};
|
char buf[UI_MAX_DRAW_STR+1]={0};
|
||||||
|
|
||||||
/* paste */
|
/* paste */
|
||||||
if (dev==VKEY) {
|
if (dev==VKEY) {
|
||||||
|
@ -364,6 +364,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
|
|||||||
initGameKeys();
|
initGameKeys();
|
||||||
initPythonConstraintBinding();
|
initPythonConstraintBinding();
|
||||||
initMathutils();
|
initMathutils();
|
||||||
|
initVideoTexture();
|
||||||
|
|
||||||
if (sceneconverter)
|
if (sceneconverter)
|
||||||
{
|
{
|
||||||
|
@ -40,6 +40,7 @@ SUBDIRS(
|
|||||||
SceneGraph
|
SceneGraph
|
||||||
Physics/Bullet
|
Physics/Bullet
|
||||||
Physics/Sumo
|
Physics/Sumo
|
||||||
|
VideoTexture
|
||||||
)
|
)
|
||||||
|
|
||||||
IF(WITH_PLAYER)
|
IF(WITH_PLAYER)
|
||||||
|
@ -59,6 +59,14 @@ public:
|
|||||||
void SetMapping(int mode);
|
void SetMapping(int mode);
|
||||||
void DisableUnit();
|
void DisableUnit();
|
||||||
void setTexEnv(BL_Material *mat, bool modulate=false);
|
void setTexEnv(BL_Material *mat, bool modulate=false);
|
||||||
|
unsigned int swapTexture (unsigned int newTex) {
|
||||||
|
// swap texture codes
|
||||||
|
unsigned int tmp = mTexture;
|
||||||
|
mTexture = newTex;
|
||||||
|
// return original texture code
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif//__BL_TEXTURE_H__
|
#endif//__BL_TEXTURE_H__
|
||||||
|
@ -67,6 +67,9 @@ public:
|
|||||||
|
|
||||||
MTFace* GetMTFace(void) const;
|
MTFace* GetMTFace(void) const;
|
||||||
unsigned int* GetMCol(void) const;
|
unsigned int* GetMCol(void) const;
|
||||||
|
BL_Texture * getTex (unsigned int idx) {
|
||||||
|
return (idx < MAXTEX) ? mTextures + idx : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// for ipos
|
// for ipos
|
||||||
void UpdateIPO(
|
void UpdateIPO(
|
||||||
|
@ -793,7 +793,7 @@ KX_PYMETHODDEF_DOC(KX_Camera, setOnTop,
|
|||||||
{
|
{
|
||||||
class KX_Scene* scene;
|
class KX_Scene* scene;
|
||||||
|
|
||||||
scene = PHY_GetActiveScene();
|
scene = KX_GetActiveScene();
|
||||||
MT_assert(scene);
|
MT_assert(scene);
|
||||||
scene->SetCameraOnTop(this);
|
scene->SetCameraOnTop(this);
|
||||||
Py_Return;
|
Py_Return;
|
||||||
|
@ -1027,7 +1027,7 @@ bool KX_GameObject::ConvertPythonVectorArgs(PyObject* args,
|
|||||||
|
|
||||||
PyObject* KX_GameObject::PyReplaceMesh(PyObject* self, PyObject* value)
|
PyObject* KX_GameObject::PyReplaceMesh(PyObject* self, PyObject* value)
|
||||||
{
|
{
|
||||||
KX_Scene *scene = PHY_GetActiveScene();
|
KX_Scene *scene = KX_GetActiveScene();
|
||||||
char* meshname;
|
char* meshname;
|
||||||
void* mesh_pt;
|
void* mesh_pt;
|
||||||
|
|
||||||
@ -1050,7 +1050,7 @@ PyObject* KX_GameObject::PyReplaceMesh(PyObject* self, PyObject* value)
|
|||||||
PyObject* KX_GameObject::PyEndObject(PyObject* self)
|
PyObject* KX_GameObject::PyEndObject(PyObject* self)
|
||||||
{
|
{
|
||||||
|
|
||||||
KX_Scene *scene = PHY_GetActiveScene();
|
KX_Scene *scene = KX_GetActiveScene();
|
||||||
scene->DelayedRemoveObject(this);
|
scene->DelayedRemoveObject(this);
|
||||||
|
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
@ -1447,7 +1447,7 @@ PyObject* KX_GameObject::PySetParent(PyObject* self, PyObject* value)
|
|||||||
// The object we want to set as parent
|
// The object we want to set as parent
|
||||||
CValue *m_ob = (CValue*)value;
|
CValue *m_ob = (CValue*)value;
|
||||||
KX_GameObject *obj = ((KX_GameObject*)m_ob);
|
KX_GameObject *obj = ((KX_GameObject*)m_ob);
|
||||||
KX_Scene *scene = PHY_GetActiveScene();
|
KX_Scene *scene = KX_GetActiveScene();
|
||||||
|
|
||||||
this->SetParent(scene, obj);
|
this->SetParent(scene, obj);
|
||||||
|
|
||||||
@ -1456,7 +1456,7 @@ PyObject* KX_GameObject::PySetParent(PyObject* self, PyObject* value)
|
|||||||
|
|
||||||
PyObject* KX_GameObject::PyRemoveParent(PyObject* self)
|
PyObject* KX_GameObject::PyRemoveParent(PyObject* self)
|
||||||
{
|
{
|
||||||
KX_Scene *scene = PHY_GetActiveScene();
|
KX_Scene *scene = KX_GetActiveScene();
|
||||||
this->RemoveParent(scene);
|
this->RemoveParent(scene);
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
@ -470,7 +470,7 @@ else
|
|||||||
m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
|
m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
|
||||||
// set Python hooks for each scene
|
// set Python hooks for each scene
|
||||||
PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment());
|
PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment());
|
||||||
PHY_SetActiveScene(scene);
|
KX_SetActiveScene(scene);
|
||||||
|
|
||||||
scene->GetPhysicsEnvironment()->endFrame();
|
scene->GetPhysicsEnvironment()->endFrame();
|
||||||
|
|
||||||
@ -568,7 +568,7 @@ else
|
|||||||
|
|
||||||
// set Python hooks for each scene
|
// set Python hooks for each scene
|
||||||
PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment());
|
PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment());
|
||||||
PHY_SetActiveScene(scene);
|
KX_SetActiveScene(scene);
|
||||||
|
|
||||||
m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
|
m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
|
||||||
scene->UpdateParents(m_clockTime);
|
scene->UpdateParents(m_clockTime);
|
||||||
@ -1540,6 +1540,11 @@ double KX_KetsjiEngine::GetAnimFrameRate()
|
|||||||
return m_anim_framerate;
|
return m_anim_framerate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double KX_KetsjiEngine::GetClockTime(void) const
|
||||||
|
{
|
||||||
|
return m_clockTime;
|
||||||
|
}
|
||||||
|
|
||||||
void KX_KetsjiEngine::SetAnimFrameRate(double framerate)
|
void KX_KetsjiEngine::SetAnimFrameRate(double framerate)
|
||||||
{
|
{
|
||||||
m_anim_framerate = framerate;
|
m_anim_framerate = framerate;
|
||||||
|
@ -253,6 +253,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool GetUseFixedTime(void) const;
|
bool GetUseFixedTime(void) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns current render frame clock time
|
||||||
|
*/
|
||||||
|
double GetClockTime(void) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the difference between the local time of the scene (when it
|
* Returns the difference between the local time of the scene (when it
|
||||||
* was running and not suspended) and the "curtime"
|
* was running and not suspended) and the "curtime"
|
||||||
|
@ -119,7 +119,7 @@ bool KX_ParentActuator::Update()
|
|||||||
return false; // do nothing on negative events
|
return false; // do nothing on negative events
|
||||||
|
|
||||||
KX_GameObject *obj = (KX_GameObject*) GetParent();
|
KX_GameObject *obj = (KX_GameObject*) GetParent();
|
||||||
KX_Scene *scene = PHY_GetActiveScene();
|
KX_Scene *scene = KX_GetActiveScene();
|
||||||
switch (m_mode) {
|
switch (m_mode) {
|
||||||
case KX_PARENT_SET:
|
case KX_PARENT_SET:
|
||||||
if (m_ob)
|
if (m_ob)
|
||||||
|
@ -1461,16 +1461,21 @@ PyObject* initMathutils()
|
|||||||
return Mathutils_Init("Mathutils"); // Use as a top level module in BGE
|
return Mathutils_Init("Mathutils"); // Use as a top level module in BGE
|
||||||
}
|
}
|
||||||
|
|
||||||
void PHY_SetActiveScene(class KX_Scene* scene)
|
void KX_SetActiveScene(class KX_Scene* scene)
|
||||||
{
|
{
|
||||||
gp_KetsjiScene = scene;
|
gp_KetsjiScene = scene;
|
||||||
}
|
}
|
||||||
|
|
||||||
class KX_Scene* PHY_GetActiveScene()
|
class KX_Scene* KX_GetActiveScene()
|
||||||
{
|
{
|
||||||
return gp_KetsjiScene;
|
return gp_KetsjiScene;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class KX_KetsjiEngine* KX_GetActiveEngine()
|
||||||
|
{
|
||||||
|
return gp_KetsjiEngine;
|
||||||
|
}
|
||||||
|
|
||||||
// utility function for loading and saving the globalDict
|
// utility function for loading and saving the globalDict
|
||||||
int saveGamePythonConfig( char **marshal_buffer)
|
int saveGamePythonConfig( char **marshal_buffer)
|
||||||
{
|
{
|
||||||
|
@ -45,6 +45,7 @@ PyObject* initGameKeys();
|
|||||||
PyObject* initRasterizer(class RAS_IRasterizer* rasty,class RAS_ICanvas* canvas);
|
PyObject* initRasterizer(class RAS_IRasterizer* rasty,class RAS_ICanvas* canvas);
|
||||||
PyObject* initGamePlayerPythonScripting(const STR_String& progname, TPythonSecurityLevel level);
|
PyObject* initGamePlayerPythonScripting(const STR_String& progname, TPythonSecurityLevel level);
|
||||||
PyObject* initMathutils();
|
PyObject* initMathutils();
|
||||||
|
PyObject* initVideoTexture(void);
|
||||||
void exitGamePlayerPythonScripting();
|
void exitGamePlayerPythonScripting();
|
||||||
PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level);
|
PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level);
|
||||||
void exitGamePythonScripting();
|
void exitGamePythonScripting();
|
||||||
@ -54,8 +55,12 @@ void pathGamePythonConfig( char *path );
|
|||||||
int saveGamePythonConfig( char **marshal_buffer);
|
int saveGamePythonConfig( char **marshal_buffer);
|
||||||
int loadGamePythonConfig(char *marshal_buffer, int marshal_length);
|
int loadGamePythonConfig(char *marshal_buffer, int marshal_length);
|
||||||
|
|
||||||
void PHY_SetActiveScene(class KX_Scene* scene);
|
class KX_KetsjiEngine;
|
||||||
class KX_Scene* PHY_GetActiveScene();
|
class KX_Scene;
|
||||||
|
|
||||||
|
void KX_SetActiveScene(class KX_Scene* scene);
|
||||||
|
class KX_Scene* KX_GetActiveScene();
|
||||||
|
class KX_KetsjiEngine* KX_GetActiveEngine();
|
||||||
#include "MT_Vector3.h"
|
#include "MT_Vector3.h"
|
||||||
|
|
||||||
void KX_RasterizerDrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,const MT_Vector3& color);
|
void KX_RasterizerDrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,const MT_Vector3& color);
|
||||||
|
@ -78,6 +78,7 @@ numberoffilters(0)
|
|||||||
m_gameObjects[passindex] = NULL;
|
m_gameObjects[passindex] = NULL;
|
||||||
}
|
}
|
||||||
texname[0] = texname[1] = texname[2] = -1;
|
texname[0] = texname[1] = texname[2] = -1;
|
||||||
|
errorprinted= false;
|
||||||
}
|
}
|
||||||
|
|
||||||
RAS_2DFilterManager::~RAS_2DFilterManager()
|
RAS_2DFilterManager::~RAS_2DFilterManager()
|
||||||
@ -85,76 +86,107 @@ RAS_2DFilterManager::~RAS_2DFilterManager()
|
|||||||
FreeTextures();
|
FreeTextures();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RAS_2DFilterManager::PrintShaderErrors(unsigned int shader, const char *task, const char *code)
|
||||||
|
{
|
||||||
|
GLcharARB log[5000];
|
||||||
|
GLsizei length = 0;
|
||||||
|
const char *c, *pos, *end;
|
||||||
|
int line = 1;
|
||||||
|
|
||||||
|
if(errorprinted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
errorprinted= true;
|
||||||
|
|
||||||
|
glGetInfoLogARB(shader, sizeof(log), &length, log);
|
||||||
|
end = code + strlen(code);
|
||||||
|
|
||||||
|
printf("2D Filter GLSL Shader: %s error:\n", task);
|
||||||
|
|
||||||
|
c = code;
|
||||||
|
while ((c < end) && (pos = strchr(c, '\n'))) {
|
||||||
|
printf("%2d ", line);
|
||||||
|
fwrite(c, (pos+1)-c, 1, stdout);
|
||||||
|
c = pos+1;
|
||||||
|
line++;
|
||||||
|
}
|
||||||
|
printf("%s", c);
|
||||||
|
|
||||||
|
printf("%s\n", log);
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int RAS_2DFilterManager::CreateShaderProgram(const char* shadersource)
|
unsigned int RAS_2DFilterManager::CreateShaderProgram(const char* shadersource)
|
||||||
{
|
{
|
||||||
GLuint program = 0;
|
GLuint program = 0;
|
||||||
GLuint fShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER);
|
GLuint fShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER);
|
||||||
GLint success;
|
GLint success;
|
||||||
|
|
||||||
glShaderSourceARB(fShader, 1, (const char**)&shadersource, NULL);
|
glShaderSourceARB(fShader, 1, (const char**)&shadersource, NULL);
|
||||||
|
|
||||||
glCompileShaderARB(fShader);
|
glCompileShaderARB(fShader);
|
||||||
|
|
||||||
glGetObjectParameterivARB(fShader, GL_COMPILE_STATUS, &success);
|
|
||||||
if(!success)
|
|
||||||
{
|
|
||||||
/*Shader Comile Error*/
|
|
||||||
std::cout << "2dFilters - Shader compile error" << std::endl;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
program = glCreateProgramObjectARB();
|
glGetObjectParameterivARB(fShader, GL_COMPILE_STATUS, &success);
|
||||||
glAttachObjectARB(program, fShader);
|
if(!success)
|
||||||
|
{
|
||||||
|
/*Shader Comile Error*/
|
||||||
|
PrintShaderErrors(fShader, "compile", shadersource);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
glLinkProgramARB(program);
|
program = glCreateProgramObjectARB();
|
||||||
glGetObjectParameterivARB(program, GL_LINK_STATUS, &success);
|
glAttachObjectARB(program, fShader);
|
||||||
if (!success)
|
|
||||||
{
|
|
||||||
/*Program Link Error*/
|
|
||||||
std::cout << "2dFilters - Shader program link error" << std::endl;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
glValidateProgramARB(program);
|
glLinkProgramARB(program);
|
||||||
glGetObjectParameterivARB(program, GL_VALIDATE_STATUS, &success);
|
glGetObjectParameterivARB(program, GL_LINK_STATUS, &success);
|
||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
/*Program Validation Error*/
|
/*Program Link Error*/
|
||||||
std::cout << "2dFilters - Shader program validation error" << std::endl;
|
PrintShaderErrors(fShader, "link", shadersource);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return program;
|
glValidateProgramARB(program);
|
||||||
|
glGetObjectParameterivARB(program, GL_VALIDATE_STATUS, &success);
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
/*Program Validation Error*/
|
||||||
|
PrintShaderErrors(fShader, "validate", shadersource);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int RAS_2DFilterManager::CreateShaderProgram(int filtermode)
|
unsigned int RAS_2DFilterManager::CreateShaderProgram(int filtermode)
|
||||||
{
|
{
|
||||||
switch(filtermode)
|
switch(filtermode)
|
||||||
{
|
{
|
||||||
case RAS_2DFILTER_BLUR:
|
case RAS_2DFILTER_BLUR:
|
||||||
return CreateShaderProgram(BlurFragmentShader);
|
return CreateShaderProgram(BlurFragmentShader);
|
||||||
case RAS_2DFILTER_SHARPEN:
|
case RAS_2DFILTER_SHARPEN:
|
||||||
return CreateShaderProgram(SharpenFragmentShader);
|
return CreateShaderProgram(SharpenFragmentShader);
|
||||||
case RAS_2DFILTER_DILATION:
|
case RAS_2DFILTER_DILATION:
|
||||||
return CreateShaderProgram(DilationFragmentShader);
|
return CreateShaderProgram(DilationFragmentShader);
|
||||||
case RAS_2DFILTER_EROSION:
|
case RAS_2DFILTER_EROSION:
|
||||||
return CreateShaderProgram(ErosionFragmentShader);
|
return CreateShaderProgram(ErosionFragmentShader);
|
||||||
case RAS_2DFILTER_LAPLACIAN:
|
case RAS_2DFILTER_LAPLACIAN:
|
||||||
return CreateShaderProgram(LaplacionFragmentShader);
|
return CreateShaderProgram(LaplacionFragmentShader);
|
||||||
case RAS_2DFILTER_SOBEL:
|
case RAS_2DFILTER_SOBEL:
|
||||||
return CreateShaderProgram(SobelFragmentShader);
|
return CreateShaderProgram(SobelFragmentShader);
|
||||||
case RAS_2DFILTER_PREWITT:
|
case RAS_2DFILTER_PREWITT:
|
||||||
return CreateShaderProgram(PrewittFragmentShader);
|
return CreateShaderProgram(PrewittFragmentShader);
|
||||||
case RAS_2DFILTER_GRAYSCALE:
|
case RAS_2DFILTER_GRAYSCALE:
|
||||||
return CreateShaderProgram(GrayScaleFragmentShader);
|
return CreateShaderProgram(GrayScaleFragmentShader);
|
||||||
case RAS_2DFILTER_SEPIA:
|
case RAS_2DFILTER_SEPIA:
|
||||||
return CreateShaderProgram(SepiaFragmentShader);
|
return CreateShaderProgram(SepiaFragmentShader);
|
||||||
case RAS_2DFILTER_INVERT:
|
case RAS_2DFILTER_INVERT:
|
||||||
return CreateShaderProgram(InvertFragmentShader);
|
return CreateShaderProgram(InvertFragmentShader);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
void RAS_2DFilterManager::AnalyseShader(int passindex, vector<STR_String>& propNames)
|
|
||||||
|
void RAS_2DFilterManager::AnalyseShader(int passindex, vector<STR_String>& propNames)
|
||||||
{
|
{
|
||||||
texflag[passindex] = 0;
|
texflag[passindex] = 0;
|
||||||
if(glGetUniformLocationARB(m_filters[passindex], "bgl_DepthTexture") != -1)
|
if(glGetUniformLocationARB(m_filters[passindex], "bgl_DepthTexture") != -1)
|
||||||
@ -249,11 +281,11 @@ void RAS_2DFilterManager::EndShaderProgram()
|
|||||||
|
|
||||||
void RAS_2DFilterManager::FreeTextures()
|
void RAS_2DFilterManager::FreeTextures()
|
||||||
{
|
{
|
||||||
if(texname[0]!=-1)
|
if(texname[0]!=(unsigned int)-1)
|
||||||
glDeleteTextures(1, (GLuint*)&texname[0]);
|
glDeleteTextures(1, (GLuint*)&texname[0]);
|
||||||
if(texname[1]!=-1)
|
if(texname[1]!=(unsigned int)-1)
|
||||||
glDeleteTextures(1, (GLuint*)&texname[1]);
|
glDeleteTextures(1, (GLuint*)&texname[1]);
|
||||||
if(texname[2]!=-1)
|
if(texname[2]!=(unsigned int)-1)
|
||||||
glDeleteTextures(1, (GLuint*)&texname[2]);
|
glDeleteTextures(1, (GLuint*)&texname[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,8 +332,8 @@ void RAS_2DFilterManager::UpdateOffsetMatrix(RAS_ICanvas* canvas)
|
|||||||
RAS_Rect canvas_rect = canvas->GetWindowArea();
|
RAS_Rect canvas_rect = canvas->GetWindowArea();
|
||||||
canvaswidth = canvas->GetWidth();
|
canvaswidth = canvas->GetWidth();
|
||||||
canvasheight = canvas->GetHeight();
|
canvasheight = canvas->GetHeight();
|
||||||
texturewidth = canvaswidth + canvas_rect.GetLeft();
|
texturewidth = canvaswidth;
|
||||||
textureheight = canvasheight + canvas_rect.GetBottom();
|
textureheight = canvasheight;
|
||||||
|
|
||||||
GLint i,j;
|
GLint i,j;
|
||||||
i = 0;
|
i = 0;
|
||||||
@ -365,17 +397,17 @@ void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas)
|
|||||||
if(need_depth){
|
if(need_depth){
|
||||||
glActiveTextureARB(GL_TEXTURE1);
|
glActiveTextureARB(GL_TEXTURE1);
|
||||||
glBindTexture(GL_TEXTURE_2D, texname[1]);
|
glBindTexture(GL_TEXTURE_2D, texname[1]);
|
||||||
glCopyTexImage2D(GL_TEXTURE_2D,0,GL_DEPTH_COMPONENT, 0, 0, texturewidth,textureheight, 0);
|
glCopyTexImage2D(GL_TEXTURE_2D,0,GL_DEPTH_COMPONENT, viewport[0], viewport[1], texturewidth,textureheight, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(need_luminance){
|
if(need_luminance){
|
||||||
glActiveTextureARB(GL_TEXTURE2);
|
glActiveTextureARB(GL_TEXTURE2);
|
||||||
glBindTexture(GL_TEXTURE_2D, texname[2]);
|
glBindTexture(GL_TEXTURE_2D, texname[2]);
|
||||||
glCopyTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE16, 0, 0 , texturewidth,textureheight, 0);
|
glCopyTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE16, viewport[0], viewport[1] , texturewidth,textureheight, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
glGetIntegerv(GL_VIEWPORT,(GLint *)viewport);
|
glGetIntegerv(GL_VIEWPORT,(GLint *)viewport);
|
||||||
glViewport(0,0, texturewidth, textureheight);
|
glViewport(viewport[0],viewport[1], texturewidth, textureheight);
|
||||||
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
glMatrixMode(GL_TEXTURE);
|
glMatrixMode(GL_TEXTURE);
|
||||||
@ -393,15 +425,20 @@ void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas)
|
|||||||
|
|
||||||
glActiveTextureARB(GL_TEXTURE0);
|
glActiveTextureARB(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, texname[0]);
|
glBindTexture(GL_TEXTURE_2D, texname[0]);
|
||||||
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, texturewidth, textureheight, 0);
|
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, viewport[0], viewport[1], texturewidth, textureheight, 0);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
float canvascoordx, canvascoordy;
|
||||||
|
|
||||||
|
canvascoordx = (GLfloat) texturewidth / canvaswidth;
|
||||||
|
canvascoordy = (GLfloat) textureheight / canvasheight;
|
||||||
|
|
||||||
glBegin(GL_QUADS);
|
glBegin(GL_QUADS);
|
||||||
glColor4f(1.f, 1.f, 1.f, 1.f);
|
glColor4f(1.f, 1.f, 1.f, 1.f);
|
||||||
glTexCoord2f(1.0, 1.0); glVertex2f(1,1);
|
glTexCoord2f(1.0, 1.0); glMultiTexCoord2fARB(GL_TEXTURE1_ARB, canvascoordx, canvascoordy); glVertex2f(1,1);
|
||||||
glTexCoord2f(0.0, 1.0); glVertex2f(-1,1);
|
glTexCoord2f(0.0, 1.0); glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.0, canvascoordy); glVertex2f(-1,1);
|
||||||
glTexCoord2f(0.0, 0.0); glVertex2f(-1,-1);
|
glTexCoord2f(0.0, 0.0); glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.0, 0.0); glVertex2f(-1,-1);
|
||||||
glTexCoord2f(1.0, 0.0); glVertex2f(1,-1);
|
glTexCoord2f(1.0, 0.0); glMultiTexCoord2fARB(GL_TEXTURE1_ARB, canvascoordx, 0.0); glVertex2f(1,-1);
|
||||||
glEnd();
|
glEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ private:
|
|||||||
void AnalyseShader(int passindex, vector<STR_String>& propNames);
|
void AnalyseShader(int passindex, vector<STR_String>& propNames);
|
||||||
void StartShaderProgram(int passindex);
|
void StartShaderProgram(int passindex);
|
||||||
void EndShaderProgram();
|
void EndShaderProgram();
|
||||||
|
void PrintShaderErrors(unsigned int shader, const char *task, const char *code);
|
||||||
|
|
||||||
void SetupTextures(bool depth, bool luminance);
|
void SetupTextures(bool depth, bool luminance);
|
||||||
void FreeTextures();
|
void FreeTextures();
|
||||||
@ -58,6 +59,7 @@ private:
|
|||||||
short texflag[MAX_RENDER_PASS];
|
short texflag[MAX_RENDER_PASS];
|
||||||
|
|
||||||
bool isshadersupported;
|
bool isshadersupported;
|
||||||
|
bool errorprinted;
|
||||||
|
|
||||||
unsigned int m_filters[MAX_RENDER_PASS];
|
unsigned int m_filters[MAX_RENDER_PASS];
|
||||||
short m_enabled[MAX_RENDER_PASS];
|
short m_enabled[MAX_RENDER_PASS];
|
||||||
|
@ -15,7 +15,8 @@ SConscript(['BlenderRoutines/SConscript',
|
|||||||
'Rasterizer/RAS_OpenGLRasterizer/SConscript',
|
'Rasterizer/RAS_OpenGLRasterizer/SConscript',
|
||||||
'SceneGraph/SConscript',
|
'SceneGraph/SConscript',
|
||||||
'Physics/Bullet/SConscript',
|
'Physics/Bullet/SConscript',
|
||||||
'Physics/Sumo/SConscript'
|
'Physics/Sumo/SConscript',
|
||||||
|
'VideoTexture/SConscript'
|
||||||
])
|
])
|
||||||
|
|
||||||
if env['WITH_BF_PLAYER']:
|
if env['WITH_BF_PLAYER']:
|
||||||
|
75
source/gameengine/VideoTexture/BlendType.h
Normal file
75
source/gameengine/VideoTexture/BlendType.h
Normal file
@ -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
|
61
source/gameengine/VideoTexture/CMakeLists.txt
Normal file
61
source/gameengine/VideoTexture/CMakeLists.txt
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
# $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)
|
||||||
|
ADD_DEFINITIONS(-D__STDC_CONSTANT_MACROS)
|
||||||
|
ENDIF(WITH_FFMPEG)
|
||||||
|
|
||||||
|
BLENDERLIB(bf_videotex "${SRC}" "${INC}")
|
||||||
|
#env.BlenderLib ( 'bf_videotex', sources, Split(incs), [], libtype=['game','player'], priority=[25, 72], compileflags = cflags )
|
55
source/gameengine/VideoTexture/Common.h
Normal file
55
source/gameengine/VideoTexture/Common.h
Normal file
@ -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>
|
209
source/gameengine/VideoTexture/Exception.cpp
Normal file
209
source/gameengine/VideoTexture/Exception.cpp
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
/* $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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void registerAllExceptions(void)
|
||||||
|
{
|
||||||
|
errGenerDesc.registerDesc();
|
||||||
|
errNFoundDesc.registerDesc();
|
||||||
|
MaterialNotAvailDesc.registerDesc();
|
||||||
|
ImageSizesNotMatchDesc.registerDesc();
|
||||||
|
SceneInvalidDesc.registerDesc();
|
||||||
|
CameraInvalidDesc.registerDesc();
|
||||||
|
SourceVideoEmptyDesc.registerDesc();
|
||||||
|
SourceVideoCreationDesc.registerDesc();
|
||||||
|
}
|
210
source/gameengine/VideoTexture/Exception.h
Normal file
210
source/gameengine/VideoTexture/Exception.h
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
/* $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 <algorithm>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void registerDesc(void)
|
||||||
|
{
|
||||||
|
if (std::find(m_expDescs.begin(), m_expDescs.end(), this) == m_expDescs.end())
|
||||||
|
m_expDescs.push_back(this);
|
||||||
|
}
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
extern ExpDesc MaterialNotAvailDesc;
|
||||||
|
extern ExpDesc ImageSizesNotMatchDesc;
|
||||||
|
extern ExpDesc SceneInvalidDesc;
|
||||||
|
extern ExpDesc CameraInvalidDesc;
|
||||||
|
extern ExpDesc SourceVideoEmptyDesc;
|
||||||
|
extern ExpDesc SourceVideoCreationDesc;
|
||||||
|
|
||||||
|
|
||||||
|
void registerAllExceptions(void);
|
||||||
|
#endif
|
150
source/gameengine/VideoTexture/FilterBase.cpp
Normal file
150
source/gameengine/VideoTexture/FilterBase.cpp
Normal file
@ -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;
|
||||||
|
}
|
132
source/gameengine/VideoTexture/FilterBase.h
Normal file
132
source/gameengine/VideoTexture/FilterBase.h
Normal file
@ -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
|
178
source/gameengine/VideoTexture/FilterBlueScreen.cpp
Normal file
178
source/gameengine/VideoTexture/FilterBlueScreen.cpp
Normal file
@ -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 */
|
||||||
|
};
|
||||||
|
|
98
source/gameengine/VideoTexture/FilterBlueScreen.h
Normal file
98
source/gameengine/VideoTexture/FilterBlueScreen.h
Normal file
@ -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
|
350
source/gameengine/VideoTexture/FilterColor.cpp
Normal file
350
source/gameengine/VideoTexture/FilterColor.cpp
Normal file
@ -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 */
|
||||||
|
};
|
||||||
|
|
164
source/gameengine/VideoTexture/FilterColor.h
Normal file
164
source/gameengine/VideoTexture/FilterColor.h
Normal file
@ -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
|
162
source/gameengine/VideoTexture/FilterNormal.cpp
Normal file
162
source/gameengine/VideoTexture/FilterNormal.cpp
Normal file
@ -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 */
|
||||||
|
};
|
||||||
|
|
98
source/gameengine/VideoTexture/FilterNormal.h
Normal file
98
source/gameengine/VideoTexture/FilterNormal.h
Normal file
@ -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
|
125
source/gameengine/VideoTexture/FilterSource.cpp
Normal file
125
source/gameengine/VideoTexture/FilterSource.cpp
Normal file
@ -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 */
|
||||||
|
};
|
||||||
|
|
233
source/gameengine/VideoTexture/FilterSource.h
Normal file
233
source/gameengine/VideoTexture/FilterSource.h
Normal file
@ -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
|
529
source/gameengine/VideoTexture/ImageBase.cpp
Normal file
529
source/gameengine/VideoTexture/ImageBase.cpp
Normal file
@ -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;
|
||||||
|
}
|
349
source/gameengine/VideoTexture/ImageBase.h
Normal file
349
source/gameengine/VideoTexture/ImageBase.h
Normal file
@ -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
|
166
source/gameengine/VideoTexture/ImageBuff.cpp
Normal file
166
source/gameengine/VideoTexture/ImageBuff.cpp
Normal file
@ -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 */
|
||||||
|
};
|
||||||
|
|
51
source/gameengine/VideoTexture/ImageBuff.h
Normal file
51
source/gameengine/VideoTexture/ImageBuff.h
Normal file
@ -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
|
||||||
|
|
205
source/gameengine/VideoTexture/ImageMix.cpp
Normal file
205
source/gameengine/VideoTexture/ImageMix.cpp
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExceptionID ImageSizesNotMatch;
|
||||||
|
|
||||||
|
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 */
|
||||||
|
};
|
||||||
|
|
123
source/gameengine/VideoTexture/ImageMix.h
Normal file
123
source/gameengine/VideoTexture/ImageMix.h
Normal file
@ -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
|
||||||
|
|
265
source/gameengine/VideoTexture/ImageRender.cpp
Normal file
265
source/gameengine/VideoTexture/ImageRender.cpp
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
/* $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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageRender::Render()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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");
|
||||||
|
|
||||||
|
|
||||||
|
ExceptionID SceneInvalid, CameraInvalid;
|
||||||
|
ExpDesc SceneInvalidDesc (SceneInvalid, "Scene object is invalid");
|
||||||
|
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 */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
90
source/gameengine/VideoTexture/ImageRender.h
Normal file
90
source/gameengine/VideoTexture/ImageRender.h
Normal file
@ -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
|
||||||
|
|
298
source/gameengine/VideoTexture/ImageViewport.cpp
Normal file
298
source/gameengine/VideoTexture/ImageViewport.cpp
Normal file
@ -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 */
|
||||||
|
};
|
84
source/gameengine/VideoTexture/ImageViewport.h
Normal file
84
source/gameengine/VideoTexture/ImageViewport.h
Normal file
@ -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
|
||||||
|
|
65
source/gameengine/VideoTexture/Makefile
Normal file
65
source/gameengine/VideoTexture/Makefile
Normal file
@ -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
|
||||||
|
|
||||||
|
|
83
source/gameengine/VideoTexture/PyTypeList.cpp
Normal file
83
source/gameengine/VideoTexture/PyTypeList.cpp
Normal file
@ -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());
|
||||||
|
}
|
||||||
|
}
|
85
source/gameengine/VideoTexture/PyTypeList.h
Normal file
85
source/gameengine/VideoTexture/PyTypeList.h
Normal file
@ -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
|
33
source/gameengine/VideoTexture/SConscript
Normal file
33
source/gameengine/VideoTexture/SConscript
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#!/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')
|
||||||
|
|
||||||
|
incs += ' ' + env['BF_PYTHON'] + '/lib/python' + env['BF_PYTHON_VERSION'] + "/site-packages/numpy/core/include"
|
||||||
|
incs += ' ' + env['BF_PYTHON_INC']
|
||||||
|
#incs += ' ' + env['BF_OPENGL_INC']
|
||||||
|
|
||||||
|
if env['WITH_BF_FFMPEG']:
|
||||||
|
defs += ' WITH_FFMPEG'
|
||||||
|
incs += ' ' + env['BF_FFMPEG_INC']
|
||||||
|
defs += ' __STDC_CONSTANT_MACROS'
|
||||||
|
|
||||||
|
env.BlenderLib ( 'bf_videotex', sources, Split(incs), Split(defs), libtype=['game','player'], priority=[25, 72], compileflags = cflags )
|
463
source/gameengine/VideoTexture/Texture.cpp
Normal file
463
source/gameengine/VideoTexture/Texture.cpp
Normal file
@ -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 != NULL && 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ExceptionID MaterialNotAvail;
|
||||||
|
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", ¶m) || !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 */
|
||||||
|
};
|
87
source/gameengine/VideoTexture/Texture.h
Normal file
87
source/gameengine/VideoTexture/Texture.h
Normal file
@ -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
|
183
source/gameengine/VideoTexture/VideoBase.cpp
Normal file
183
source/gameengine/VideoTexture/VideoBase.cpp
Normal file
@ -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;
|
||||||
|
}
|
185
source/gameengine/VideoTexture/VideoBase.h
Normal file
185
source/gameengine/VideoTexture/VideoBase.h
Normal file
@ -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
|
||||||
|
|
753
source/gameengine/VideoTexture/VideoFFmpeg.cpp
Normal file
753
source/gameengine/VideoTexture/VideoFFmpeg.cpp
Normal file
@ -0,0 +1,753 @@
|
|||||||
|
/* $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 (
|
||||||
|
#ifdef FFMPEG_PB_IS_POINTER
|
||||||
|
m_formatCtx->pb->is_streamed
|
||||||
|
#else
|
||||||
|
m_formatCtx->pb.is_streamed
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// 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
|
||||||
|
|
||||||
|
|
163
source/gameengine/VideoTexture/VideoFFmpeg.h
Normal file
163
source/gameengine/VideoTexture/VideoFFmpeg.h
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
/* $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
|
||||||
|
|
||||||
|
#if LIBAVFORMAT_VERSION_INT >= (52 << 16)
|
||||||
|
#define FFMPEG_PB_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
|
207
source/gameengine/VideoTexture/blendVideoTex.cpp
Normal file
207
source/gameengine/VideoTexture/blendVideoTex.cpp
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
/* $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();
|
||||||
|
registerAllExceptions();
|
||||||
|
|
||||||
|
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
|
Loading…
Reference in New Issue
Block a user