From cd6beca5488430b1150ad9a0c1c97a49c4d3e328 Mon Sep 17 00:00:00 2001 From: tentacle Date: Fri, 3 Mar 2006 19:00:47 +0000 Subject: [PATCH] little tenfex interface change + moved FexTracker to OPEN SOURCE :) Originally committed to SVN as r194. --- FexTrackerSource/FexGenericFilter.cpp | 78 +++ .../FexGenericFilter_BaseFloatImage.cpp | 91 ++++ .../FexGenericFilter_BaseFloatImageApply.h | 46 ++ .../FexGenericFilter_Contribution.h | 38 ++ .../FexGenericFilter_FexImage.cpp | 47 ++ .../FexGenericFilter_FexImageApply.h | 46 ++ .../FexGenericFilter_FilteringCore.h | 53 ++ FexTrackerSource/FexGenericFilter_Include.h | 38 ++ FexTrackerSource/FexGenericFilter_StaticFor.h | 10 + FexTrackerSource/FexImgPyramid.cpp | 109 ++++ FexTrackerSource/FexImgPyramid.h | 42 ++ FexTrackerSource/FexMovement.cpp | 94 ++++ FexTrackerSource/FexMovement.h | 37 ++ FexTrackerSource/FexTracker.cpp | 479 ++++++++++++++++++ FexTrackerSource/FexTracker.h | 131 +++++ FexTrackerSource/FexTrackerMovement.cpp | 248 +++++++++ FexTrackerSource/FexTrackingFeature.cpp | 19 + FexTrackerSource/FexTrackingFeature.h | 27 + FexTrackerSource/StdAfx.cpp | 8 + FexTrackerSource/StdAfx.h | 34 ++ FexTrackerSource/tenlist.h | 65 +++ core/ass_dialogue.cpp | 9 + core/fextracker_main_events.cpp | 47 ++ core/frame_main.h | 4 + core/frame_main_events.cpp | 2 + 25 files changed, 1802 insertions(+) create mode 100644 FexTrackerSource/FexGenericFilter.cpp create mode 100644 FexTrackerSource/FexGenericFilter_BaseFloatImage.cpp create mode 100644 FexTrackerSource/FexGenericFilter_BaseFloatImageApply.h create mode 100644 FexTrackerSource/FexGenericFilter_Contribution.h create mode 100644 FexTrackerSource/FexGenericFilter_FexImage.cpp create mode 100644 FexTrackerSource/FexGenericFilter_FexImageApply.h create mode 100644 FexTrackerSource/FexGenericFilter_FilteringCore.h create mode 100644 FexTrackerSource/FexGenericFilter_Include.h create mode 100644 FexTrackerSource/FexGenericFilter_StaticFor.h create mode 100644 FexTrackerSource/FexImgPyramid.cpp create mode 100644 FexTrackerSource/FexImgPyramid.h create mode 100644 FexTrackerSource/FexMovement.cpp create mode 100644 FexTrackerSource/FexMovement.h create mode 100644 FexTrackerSource/FexTracker.cpp create mode 100644 FexTrackerSource/FexTracker.h create mode 100644 FexTrackerSource/FexTrackerMovement.cpp create mode 100644 FexTrackerSource/FexTrackingFeature.cpp create mode 100644 FexTrackerSource/FexTrackingFeature.h create mode 100644 FexTrackerSource/StdAfx.cpp create mode 100644 FexTrackerSource/StdAfx.h create mode 100644 FexTrackerSource/tenlist.h diff --git a/FexTrackerSource/FexGenericFilter.cpp b/FexTrackerSource/FexGenericFilter.cpp new file mode 100644 index 000000000..5ca377cb1 --- /dev/null +++ b/FexTrackerSource/FexGenericFilter.cpp @@ -0,0 +1,78 @@ +#include +#include "FexGenericFilter_Include.h" + +FexFilter::FexFilter() +{ + Width = 3; +} +FexFilter::~FexFilter() +{ +} +double FexFilter::Filter( double t ) +{ + return t/Width; +} + + +/* +f(x) = e^(-x^2 / (2 s^2) ) +f(x) = e^(-x^2 / t) + +width: +SOLVE(0.1 = f(x), x, Real) +x = - sqrt(t LN(10) ? x = sqrt(t LN(10) + +sum: + +Integral from -sqrt(t LN(10) to sqrt(t LN(10) of f(x) dx +1.715955662·sqrt(t) +*/ + +FexFilter_Gauss::FexFilter_Gauss( double sigma ) +{ + Sigma = sigma; + TwoSigmaSq = 2*sigma*sigma; + Width = sqrt( TwoSigmaSq*log(10) ); + Normalize = 1.0 / (1.715955662 * sqrt( TwoSigmaSq )); +} +FexFilter_Gauss::~FexFilter_Gauss() +{ +} + +double FexFilter_Gauss::Filter( double t ) +{ + return exp( -t*t / TwoSigmaSq ) * Normalize; +} + + + + +/* +f(x) = -x * e^(-x^2 / (2 s^2) ) +f(x) = -x * e^(-x^2 / t) + +width: +use the width of gauss since i'm clueless here + +sum: + +Integral from -sqrt(t LN(10) to sqrt(t LN(10) of -x*f(x) dx +0.7062351183·t^1.5 +*/ + +FexFilter_GaussDerivation::FexFilter_GaussDerivation( double sigma ) +{ + Sigma = sigma; + TwoSigmaSq = 2*sigma*sigma; + Width = sqrt( TwoSigmaSq*log(10) ); + Normalize = 1.0 / (0.7062351183 * pow( TwoSigmaSq, 1.5 )); +} + +FexFilter_GaussDerivation::~FexFilter_GaussDerivation() +{ +} + +double FexFilter_GaussDerivation::Filter( double t ) +{ + return -t * exp( -t*t / TwoSigmaSq ) * Normalize; +} diff --git a/FexTrackerSource/FexGenericFilter_BaseFloatImage.cpp b/FexTrackerSource/FexGenericFilter_BaseFloatImage.cpp new file mode 100644 index 000000000..edd4caabc --- /dev/null +++ b/FexTrackerSource/FexGenericFilter_BaseFloatImage.cpp @@ -0,0 +1,91 @@ +#include "stdio.h" +#include "math.h" +#include "memory.h" +#include "FexGenericFilter_Include.h" + + +void BaseFloatImage_Filter( float* in, int inSx, int inSy, FexFilter* filter, float* out, int outSx, int outSy ) +{ +#define FilterWidth (filter->Width) +#define FilterWeight(t) (filter->Filter(t)) + + float* tmp = new float[outSx*inSy]; +#include "FexGenericFilter_BaseFloatImageApply.h" + delete []tmp; + +#undef FilterWidth +#undef FilterWeight +} + +void BaseFloatImage_FilterSeperate( float* in, int inSx, int inSy, FexFilter* filterX, FexFilter* filterY, float* out, int outSx, int outSy ) +{ + float* tmp = new float[outSx*inSy]; + +#define FilterWidth (filterX->Width) +#define FilterWeight(t) (filterX->Filter(t)) +#define FILTER_NO_Y + +#include "FexGenericFilter_BaseFloatImageApply.h" + +#undef FilterWidth +#undef FilterWeight +#undef FILTER_NO_Y + +#define FilterWidth (filterY->Width) +#define FilterWeight(t) (filterY->Filter(t)) +#define FILTER_NO_X + +#include "FexGenericFilter_BaseFloatImageApply.h" + +#undef FilterWidth +#undef FilterWeight +#undef FILTER_NO_X + + delete []tmp; +} + + +void BaseFloatImage_GaussEdgeDetect( float* Img, int sizx, int sizy, float sigma, float* GradX, float* GradY ) +{ + FexFilter_Gauss gauss (sigma); + FexFilter_GaussDerivation gaussDeriv (sigma); + + BaseFloatImage_FilterSeperate( Img, sizx, sizy, &gaussDeriv, &gauss, GradX, sizx, sizy ); + BaseFloatImage_FilterSeperate( Img, sizx, sizy, &gauss, &gaussDeriv, GradY, sizx, sizy ); +} + +void BaseFloatImage_GaussSmooth( float* Img, int sizx, int sizy, float sigma, float* Out ) +{ + FexFilter_Gauss gauss (sigma); + BaseFloatImage_Filter( Img, sizx,sizy, &gauss, Out, sizx, sizy ); +} + +#include +inline double sinc( double x ) +{ + x *= 3.1415; + if( x != 0 ) + return( sin(x) / x ); + return( 1.0 ); +} +inline double RescaleFilter( double t ) +{ + if( t < 0 ) + t = -t; + if( t < 3.0 ) + return( sinc(t) * sinc(t/3.0) ); + return( 0.0 ); +} + +void BaseFloatImage_LanczosRescale( float* in, int inSx, int inSy, float* out, int outSx, int outSy ) +{ +#define FilterWidth (3) +#define FilterWeight(t) (RescaleFilter(t)) + + float* tmp = new float[outSx*inSy]; +#include "FexGenericFilter_BaseFloatImageApply.h" + delete []tmp; + +#undef FilterWidth +#undef FilterWeight +} \ No newline at end of file diff --git a/FexTrackerSource/FexGenericFilter_BaseFloatImageApply.h b/FexTrackerSource/FexGenericFilter_BaseFloatImageApply.h new file mode 100644 index 000000000..aff908fc9 --- /dev/null +++ b/FexTrackerSource/FexGenericFilter_BaseFloatImageApply.h @@ -0,0 +1,46 @@ +{ +#define PixelType float +#define PixelMin 0 +#define PixelMax 255 +#define ImagePlanes 1 + + //do filtering + scaling in x-dir +#define ImageInSX (inSx) +#define ImageInSY (inSy) +#define ImageIn(x,y,p) (in[ (y*inSx+x) ]) +#define ImageOutSX (outSx) +#define ImageOut(x,y,p) (tmp[ (y*outSx+x) ]) + +#ifndef FILTER_NO_X +#include "FexGenericFilter_FilteringCore.h" +#endif + +#undef ImageInSX +#undef ImageInSY +#undef ImageIn +#undef ImageOutSX +#undef ImageOut + + //do filtering + scaling in y-dir by using transposed image + +#define ImageInSX (inSy) +#define ImageInSY (outSx) +#define ImageIn(y,x,p) (tmp[ (y*outSx+x) ]) +#define ImageOutSX (outSy) +#define ImageOut(y,x,p) (out[ (y*outSx+x) ]) + +#ifndef FILTER_NO_Y +#include "FexGenericFilter_FilteringCore.h" +#endif + +#undef ImageInSX +#undef ImageInSY +#undef ImageIn +#undef ImageOutSX +#undef ImageOut + +#undef PixelType +#undef PixelMin +#undef PixelMax +#undef ImagePlanes +} \ No newline at end of file diff --git a/FexTrackerSource/FexGenericFilter_Contribution.h b/FexTrackerSource/FexGenericFilter_Contribution.h new file mode 100644 index 000000000..13e8a4dcb --- /dev/null +++ b/FexTrackerSource/FexGenericFilter_Contribution.h @@ -0,0 +1,38 @@ +{ + double width = FilterWidth; +#ifdef CONTRIB_XSCALE + width /= XScale; + double fscale = 1.0 / XScale; +#endif + + for(int i=0;ixMin = left; + cc->xMax = right; + if( cc->xMin < 0 ) cc->xMin = 0; + if( cc->xMax > ImageInSX-1 ) cc->xMax = ImageInSX - 1; + + int len = cc->xMax-cc->xMin+1; + cc->Weight = new double[ len ]; + memset( cc->Weight, 0x00, sizeof(double)*len ); + + for(int j=left;j<=right;++j) { + double weight = center - (double) j; +#ifdef CONTRIB_XSCALE + weight = FilterWeight(weight / fscale) / fscale; +#else + weight = FilterWeight(weight); +#endif + int n; + if(j < 0) n=0; + else if(j >= ImageInSX) n = ImageInSX - 1; + else n = j; + cc->Weight[n-cc->xMin] += weight; + } + } +} \ No newline at end of file diff --git a/FexTrackerSource/FexGenericFilter_FexImage.cpp b/FexTrackerSource/FexGenericFilter_FexImage.cpp new file mode 100644 index 000000000..1c7489d13 --- /dev/null +++ b/FexTrackerSource/FexGenericFilter_FexImage.cpp @@ -0,0 +1,47 @@ +#include "stdafx.h" +#include "FexSystem.h" +#include "ext\imdebug.h" + + +void FexImage_Filter( FexImage* in, FexFilter* filter, FexImage* out ) +{ +#define FilterWidth (filter->Width) +#define FilterWeight(t) (filter->Filter(t)) + +#include "FexGenericFilter_FexImageApply.h" + +#undef FilterWidth +#undef FilterWeight +} + + + + +#include +inline double sinc( double x ) +{ + x *= 3.1415; + if( x != 0 ) + return( sin(x) / x ); + return( 1.0 ); +} +inline double RescaleFilter( double t ) +{ + if( t < 0 ) + t = -t; + if( t < 3.0 ) + return( sinc(t) * sinc(t/3.0) ); + return( 0.0 ); +} + + +void FexImage_Rescale( FexImage* in, FexImage* out ) +{ +#define FilterWidth (3) +#define FilterWeight(t) (RescaleFilter(t)) + +#include "FexGenericFilter_FexImageApply.h" + +#undef FilterWidth +#undef FilterWeight +} diff --git a/FexTrackerSource/FexGenericFilter_FexImageApply.h b/FexTrackerSource/FexGenericFilter_FexImageApply.h new file mode 100644 index 000000000..0f7b515b4 --- /dev/null +++ b/FexTrackerSource/FexGenericFilter_FexImageApply.h @@ -0,0 +1,46 @@ +{ +#define PixelType BYTE +#define PixelMin 0 +#define PixelMax 255.9 +#define ImagePlanes 4 + + FexImage* tmp = new FexImage(out->sx,in->sy); + + //do filtering + scaling in x-dir +#define ImageInSX (in->sx) +#define ImageInSY (in->sy) +#define ImageIn(x,y,p) (in->data[ (y*in->sx+x)*4 + p ]) +#define ImageOutSX (tmp->sx) +#define ImageOut(x,y,p) (tmp->data[ (y*tmp->sx+x)*4 + p ]) + +#include "FexGenericFilter_FilteringCore.h" + +#undef ImageInSX +#undef ImageInSY +#undef ImageIn +#undef ImageOutSX +#undef ImageOut + + //do filtering + scaling in y-dir by using transposed image + +#define ImageInSX (tmp->sy) +#define ImageInSY (tmp->sx) +#define ImageIn(y,x,p) (tmp->data[ (y*tmp->sx+x)*4 + p ]) +#define ImageOutSX (out->sy) +#define ImageOut(y,x,p) (out->data[ (y*out->sx+x)*4 + p ]) + +#include "FexGenericFilter_FilteringCore.h" + +#undef ImageInSX +#undef ImageInSY +#undef ImageIn +#undef ImageOutSX +#undef ImageOut + + delete tmp; + +#undef PixelType +#undef PixelMin +#undef PixelMax +#undef ImagePlanes +} \ No newline at end of file diff --git a/FexTrackerSource/FexGenericFilter_FilteringCore.h b/FexTrackerSource/FexGenericFilter_FilteringCore.h new file mode 100644 index 000000000..28cce3174 --- /dev/null +++ b/FexTrackerSource/FexGenericFilter_FilteringCore.h @@ -0,0 +1,53 @@ +{ + FexFilterContribution* Contrib = new FexFilterContribution[ ImageOutSX ]; + double XScale = (double)ImageOutSX / (double) ImageInSX; + +//calculate contributions + + if( XScale < 1.0 ) + { + #define CONTRIB_XSCALE + #include "FexGenericFilter_Contribution.h" + #undef CONTRIB_XSCALE + } + else + { + #include "FexGenericFilter_Contribution.h" + } + + + #include "FexGenericFilter_StaticFor.h" +//apply filter + + for( int y=0;yxMin;lx<=cc->xMax;++lx ) + { + #define DOFOR(i) Sum[i] += ((double)ImageIn(lx,y,i))*cc->Weight[lx-cc->xMin]; + STATIC_FOR + #undef DOFOR + } + + #define DOFOR(i) {if(Sum[i]PixelMax)Sum[i]=PixelMax;} + STATIC_FOR + #undef DOFOR + + #define DOFOR(i) ImageOut(x,y,i) = (PixelType) Sum[i]; + STATIC_FOR + #undef DOFOR + } + } + + for( int x=0;xsx, old->sy, old->Img); + BaseFloatImage_LanczosRescale( old->Img, old->sx, old->sy, Img, sx, sy ); + imdebug("lum b=32f w=%d h=%d %p /255", sx, sy, Img); +} + +void FexImgPyramidLevel::Calc( float EdgeDetectSigma ) +{ + imdebug("lum b=32f w=%d h=%d %p /255", sx, sy, Img); + BaseFloatImage_GaussEdgeDetect( Img, sx, sy, EdgeDetectSigma, GradX, GradY ); + imdebug("lum b=32f w=%d h=%d %p /2", sx, sy, GradX); + imdebug("lum b=32f w=%d h=%d %p /2", sx, sy, GradY); +} + + + +FexImgPyramid::FexImgPyramid( float* Img, int SizX, int SizY, float EdgeDetectSigma, float DetectSmoothSigma, int iSubsampling, int Levels ) +{ + int i; + + Subsampling = iSubsampling; + + if( Levels == -1 ) Levels = 999; + int mLvl = 0; + int tsm = min(SizX,SizY); + while( tsm>1 && tsm%2==0 ) + { + tsm/=Subsampling; + ++mLvl; + } + if( Levels > mLvl ) Levels = mLvl; + if( Levels < 1 ) Levels = 1; + + nLevels = Levels; + lLevels = new FexImgPyramidLevel*[ nLevels ]; + + lLevels[0] = new FexImgPyramidLevel( SizX, SizY ); + lLevels[0]->Fill( Img, DetectSmoothSigma ); + for( i=1;iScale( lLevels[i-1] ); + } + + float cmul = 1.f; + for( i=0;iCoordMul = cmul; + lLevels[i]->Calc( EdgeDetectSigma ); + cmul /= Subsampling; + } +} + +FexImgPyramid::~FexImgPyramid() +{ + for( int i=0;i 1000 +#pragma once +#endif // _MSC_VER > 1000 + +class FexImgPyramidLevel +{ +public: + FexImgPyramidLevel( int sx, int sy ); + ~FexImgPyramidLevel(); + + int sx, sy; + float CoordMul; + + float* Img; + float* GradX; + float* GradY; + + void Fill( float* Img, float DetectSmoothSigma ); + void Scale( FexImgPyramidLevel* old ); + void Calc( float EdgeDetectSigma ); +}; + +class FexImgPyramid +{ +public: + FexImgPyramid( float* Img, int SizX, int SizY, float EdgeDetectSigma, float DetectSmoothSigma, int Subsampling, int Levels ); + ~FexImgPyramid(); + + int Subsampling; + + FexImgPyramidLevel** lLevels; + int nLevels; +}; + +#endif // !defined(AFX_FEXIMGPYRAMID_H__B289955E_6660_483D_AF51_CE78F2D03944__INCLUDED_) diff --git a/FexTrackerSource/FexMovement.cpp b/FexTrackerSource/FexMovement.cpp new file mode 100644 index 000000000..0b6d346a1 --- /dev/null +++ b/FexTrackerSource/FexMovement.cpp @@ -0,0 +1,94 @@ +// FexMovement.cpp: implementation of the FexMovement class. +// +////////////////////////////////////////////////////////////////////// + +#include "StdAfx.h" +#include "stdio.h" +#include +#include +#include +#include +//#include + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +FexMovement::FexMovement() +{ + FileName = 0; +} + +FexMovement::~FexMovement() +{ + if( FileName ) delete []FileName; +} + +FEXTRACKER_API FexMovement* CreateMovement() +{ + return new FexMovement(); +} + +FEXTRACKER_API void LoadMovement( FexMovement* me, const unsigned short* Filename ) +{ + me->Frames.nVal = 0; + + me->FileName = new WCHAR[ wcslen(Filename)+1 ]; + wcscpy( me->FileName, Filename ); + + FILE *fi = _wfopen( Filename, L"rt" ); + if( !fi ) return; + int CurFeat = -1; + char Line[512]; + while( !feof(fi) ) + { + Line[0]=0; + fgets( Line, 510, fi ); + if( !Line[0] ) break; + FexMovementFrame f; + int r = sscanf( Line, "(%f %f)(%f %f %f)(%f %f)", + &f.Pos.x, &f.Pos.y, + &f.Rot.x, &f.Rot.y, &f.Rot.z, + &f.Scale.x, &f.Scale.y ); + if( r != 7 ) continue; + me->Frames.Add( f ); + } + fclose( fi ); +} +FEXTRACKER_API void SaveMovement( FexMovement* me, const unsigned short* Filename ) +{ + FILE *fi = _wfopen( Filename, L"wt" ); + if( !fi ) return; + for( int i=0;iFrames.size();i++ ) + { + const FexMovementFrame f = me->Frames[i]; + fprintf( fi, "(%f %f)(%f %f %f)(%f %f)\n", + f.Pos.x, f.Pos.y, + f.Rot.x, f.Rot.y, f.Rot.z, + f.Scale.x, f.Scale.y ); + } + fclose( fi ); +} +/* +const WCHAR* FEXTRACKER_API GetUniqueName() +{ + static WCHAR Name[512]; + time_t long_time; + time( &long_time ); + + swprintf( Name, L"%x%x\n", timeGetTime(), long_time ); + + for( DWORD i=0;i'z' ) + Name[i] = '_'; + } + wcscat( Name, L".fexmove" ); + return Name; +} +*/ +FEXTRACKER_API void DeleteMovement( FexMovement* delme ) +{ + delete delme; +} diff --git a/FexTrackerSource/FexMovement.h b/FexTrackerSource/FexMovement.h new file mode 100644 index 000000000..897300d3b --- /dev/null +++ b/FexTrackerSource/FexMovement.h @@ -0,0 +1,37 @@ +// FexMovement.h: interface for the FexMovement class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_FEXMOVEMENT_H__63D8ADD8_4EA1_4C56_8D6F_7B587A1A61A4__INCLUDED_) +#define AFX_FEXMOVEMENT_H__63D8ADD8_4EA1_4C56_8D6F_7B587A1A61A4__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +typedef struct +{ + vec2 Pos; + vec3 Rot; + vec2 Scale; +}FexMovementFrame; + +#include "tenlist.h" + +class FexMovement +{ +public: + FexMovement(); + ~FexMovement(); + WCHAR* FileName; + + tenlist Frames; +}; + +FEXTRACKER_API FexMovement* CreateMovement(); +FEXTRACKER_API void LoadMovement( FexMovement* me, const unsigned short* Filename ); +FEXTRACKER_API void SaveMovement( FexMovement* me, const unsigned short* Filename ); +FEXTRACKER_API void DeleteMovement( FexMovement* delme ); +//WCHAR* FEXTRACKER_API GetUniqueName(); + +#endif // !defined(AFX_FEXMOVEMENT_H__63D8ADD8_4EA1_4C56_8D6F_7B587A1A61A4__INCLUDED_) diff --git a/FexTrackerSource/FexTracker.cpp b/FexTrackerSource/FexTracker.cpp new file mode 100644 index 000000000..8c45e3364 --- /dev/null +++ b/FexTrackerSource/FexTracker.cpp @@ -0,0 +1,479 @@ +// FexTracker.cpp : Defines the entry point for the DLL application. +// + +#include "StdAfx.h" +#include "stdio.h" +//#include "mmsystem.h" + +FexTracker::FexTracker( int sx, int sy, int inFeatures ) +{ + printf( "[ using FexTracker (c)2006 Hajo Krabbenhoft ]\n" ); + + nFeatures = inFeatures; + minFeatures = 0; + mFeatures = 8; + lFeatures = (FexTrackingFeature*) new FexTrackingFeature[mFeatures]; + SizX = sx; + SizY = sy; + CurImg = 0; + CurFrame = 0; + + bDebug = 0; + + float subsampling = float(Cfg.SearchRange) / min(Cfg.WindowX,Cfg.WindowY); + + if (subsampling < 1.0) { /* 1.0 = 0+1 */ + PyramidMaxLevels = 1; + } else if (subsampling <= 3.0) { /* 3.0 = 2+1 */ + PyramidMaxLevels = 2; + PyramidSubsampling = 2; + } else if (subsampling <= 5.0) { /* 5.0 = 4+1 */ + PyramidMaxLevels = 2; + PyramidSubsampling = 4; + } else if (subsampling <= 9.0) { /* 9.0 = 8+1 */ + PyramidMaxLevels = 2; + PyramidSubsampling = 8; + } else { + /* The following lines are derived from the formula: + search_range = + window_halfwidth * \sum_{i=0}^{nPyramidLevels-1} 8^i, + which is the same as: + search_range = + window_halfwidth * (8^nPyramidLevels - 1)/(8 - 1). + Then, the value is rounded up to the nearest integer. */ + float val = (float) (log(7.0*subsampling+1.0)/log(8.0)); + PyramidMaxLevels = (int) (val + 0.99); + PyramidSubsampling = 8; + } +/* + PyramidMaxLevels = 2; + PyramidSubsampling = 2; +*/ +} +FexTracker::~FexTracker() +{ + delete [] lFeatures; + if( CurImg ) delete CurImg; +} + +void FexTracker::ProcessImage( float *Img, bool bFirst ) +{ +//DWORD t = timeGetTime(); + if( bFirst || !CurImg ) + { + CurFrame = 0; + CurImg = new FexImgPyramid( Img, SizX, SizY, Cfg.EdgeDetectSigma, Cfg.DetectSmoothSigma, PyramidSubsampling, PyramidMaxLevels ); + nActiveFeatures = 0; + int tmp = nFeatures; + nFeatures = 0; + FindFeatures( tmp ); + } + else + { + CountActiveFeatures(); + if( nActiveFeatures= CurFrame ) + nActiveFeatures++; + } +} + +FexTrackingFeature* FexTracker::operator [] ( int i ) +{ + if( i<0 || i>=nFeatures ) return 0; + return & lFeatures[i]; +} + +int FexTracker::GetEigenvalueForPoint( int px, int py ) +{ + int sx = px - Cfg.WindowX; + int ex = px + Cfg.WindowX; + int sy = py - Cfg.WindowY; + int ey = py + Cfg.WindowY; + if( sx<0 )sx=0; + if( sy<0 )sy=0; + if( ex>SizX-1 )ex=SizX-1; + if( ey>SizY-1 )ey=SizY-1; + + int imgSX = CurImg->lLevels[0]->sx; + float* gradx = CurImg->lLevels[0]->GradX; + float* grady = CurImg->lLevels[0]->GradY; + + register float gxx = 0, gyy = 0, gxy = 0; + for( int y=sy;y(1<<30) ) val=(1<<30); + return (int) val; +} + + +typedef struct{ + int val, x, y; +}littleFeature; + + + +#define SWAP3(list, i, j) \ +{register int *pi, *pj, tmp; \ + pi=list+3*(i); pj=list+3*(j); \ + \ + tmp=*pi; \ + *pi++=*pj; \ + *pj++=tmp; \ + \ + tmp=*pi; \ + *pi++=*pj; \ + *pj++=tmp; \ + \ + tmp=*pi; \ + *pi=*pj; \ + *pj=tmp; \ +} + +void _quicksort(int *pointlist, int n) +{ + unsigned int i, j, ln, rn; + + while (n > 1) + { + SWAP3(pointlist, 0, n/2); + for (i = 0, j = n; ; ) + { + do + --j; + while (pointlist[3*j] < pointlist[0]); + do + ++i; + while (i < j && pointlist[3*i] > pointlist[0]); + if (i >= j) + break; + SWAP3(pointlist, i, j); + } + SWAP3(pointlist, j, 0); + ln = j; + rn = n - ++j; + if (ln < rn) + { + _quicksort(pointlist, ln); + pointlist += 3*j; + n = rn; + } + else + { + _quicksort(pointlist + 3*j, rn); + n = ln; + } + } +} +#undef SWAP3 + + +void FexTracker::FindFeatures( int minFeatures ) +{ + int nli=0; + littleFeature *list = new littleFeature[SizX*SizY]; + for( int y=0;y0 ) + { + list[nli].val = v; + list[nli].x = x; + list[nli].y = y; + nli++; + } + } + } + + _quicksort( (int*)list, nli ); + + int oldN = nFeatures; + + for( int i=0;i= mFeatures ) + { + mFeatures = nFeatures+9; + mFeatures -= mFeatures%8; + FexTrackingFeature * nlFeatures = (FexTrackingFeature*) new FexTrackingFeature[mFeatures]; + for( int cpy=0;cpylLevels[ CurImg->nLevels-1 ]->CoordMul / CurImg->Subsampling; + op.y = orig_py * CurImg->lLevels[ CurImg->nLevels-1 ]->CoordMul / CurImg->Subsampling; + vec2 np; + np = op; + + for( int l=CurImg->nLevels-1;l>=0;l-- ) + { + op.x *= CurImg->Subsampling; + op.y *= CurImg->Subsampling; + np.x *= CurImg->Subsampling; + np.y *= CurImg->Subsampling; + if( !TrackOneFeature( l, op, np ) ) break; + } + if( l!=-1 ) continue; //we aborted + + if( np.x<0 || np.y<0 || np.x>SizX || np.y>SizY ) continue; + + lFeatures[i].Pos.Add( np ); + } +} + +bool FexTracker::TrackOneFeature( int lvl, vec2 op, vec2& np ) +{ + static float bordereps = 1.1f; + if( op.x - Cfg.WindowX < bordereps || op.x + Cfg.WindowX > CurImg->lLevels[lvl]->sx - bordereps ) return 0; + if( op.y - Cfg.WindowY < bordereps || op.y + Cfg.WindowY > CurImg->lLevels[lvl]->sy - bordereps ) return 0; + if( np.x - Cfg.WindowX < bordereps || np.x + Cfg.WindowX > CurImg->lLevels[lvl]->sx - bordereps ) return 0; + if( np.y - Cfg.WindowY < bordereps || np.y + Cfg.WindowY > CurImg->lLevels[lvl]->sy - bordereps ) return 0; + + int isx = (Cfg.WindowX*2+1); + int imsiz = isx*(Cfg.WindowY*2+1); + float *diff = new float[imsiz]; + float *gradx = new float[imsiz]; + float *grady = new float[imsiz]; + + bool bOk = 1; + for( int iteration=0;iteration CurImg->lLevels[lvl]->sx - bordereps ) + || ( np.y - Cfg.WindowY < bordereps || np.y + Cfg.WindowY > CurImg->lLevels[lvl]->sy - bordereps ) ) + { + bOk = 0; + break; + } + + if( fabs(dx) < Cfg.MinDisplacement && fabs(dy) < Cfg.MinDisplacement )break; + } + delete [] gradx; + delete [] grady; + + if( bOk ) + { + GetDiffForPointset( lvl, op, np, diff ); + + float sum = 0; + for( int i=0;i Cfg.MaxResidue ) bOk = 0; + } + + delete [] diff; + return bOk; +} + +inline float Interpolate( float *img, int ImgSX, float x, float y ) +{ + int xt = (int) x; /* coordinates of top-left corner */ + int yt = (int) y; + float ax = x - xt; + float ay = y - yt; + float *ptr = img + (ImgSX*yt) + xt; + + return ( (1-ax) * (1-ay) * *ptr + + ax * (1-ay) * *(ptr+1) + + (1-ax) * ay * *(ptr+(ImgSX)) + + ax * ay * *(ptr+(ImgSX)+1) ); +} + +void FexTracker::GetDiffForPointset( int lvl, vec2 op, vec2 np, float* diff ) +{ + float* img1 = CurImg->lLevels[lvl]->Img; + int isx1 = CurImg->lLevels[lvl]->sx; + float* img2 = NextImg->lLevels[lvl]->Img; + int isx2 = NextImg->lLevels[lvl]->sx; + for( int y = -Cfg.WindowY; y <= Cfg.WindowY; y++ ) + { + for( int x = -Cfg.WindowX; x <= Cfg.WindowX; x++ ) + { + *diff++ = Interpolate(img1,isx1,op.x+x,op.y+y) - Interpolate(img2,isx2,np.x+x,np.y+y); + } + } +} +void FexTracker::GetGradForPointset( int lvl, vec2 op, vec2 np, float* gradx, float* grady ) +{ + int isx = CurImg->lLevels[lvl]->sx; + + float* gx1 = CurImg->lLevels[lvl]->GradX; + float* gx2 = NextImg->lLevels[lvl]->GradX; + + float* gy1 = CurImg->lLevels[lvl]->GradY; + float* gy2 = NextImg->lLevels[lvl]->GradY; + + for( int y = -Cfg.WindowY; y <= Cfg.WindowY; y++ ) + { + for( int x = -Cfg.WindowX; x <= Cfg.WindowX; x++ ) + { + *gradx++ = Interpolate(gx1,isx,op.x+x,op.y+y) + Interpolate(gx2,isx,np.x+x,np.y+y); + *grady++ = Interpolate(gy1,isx,op.x+x,op.y+y) + Interpolate(gy2,isx,np.x+x,np.y+y); + } + } +} + + +/* + + static float _minEigenvalue(float gxx, float gxy, float gyy) +{ + return (float) ((gxx + gyy - sqrt((gxx - gyy)*(gxx - gyy) + 4*gxy*gxy))/2.0f); +} + +//gen eigenvalue matrix: +gxx = 0; gxy = 0; gyy = 0; +for (yy = y-window_hh ; yy <= y+window_hh ; yy++) +{ + for (xx = x-window_hw ; xx <= x+window_hw ; xx++) + { + gx = *(gradx->data + ncols*yy+xx); + gy = *(grady->data + ncols*yy+xx); + gxx += gx * gx; + gxy += gx * gy; + gyy += gy * gy; + } +} + + +//get eigenvalue number +val = _minEigenvalue(gxx, gxy, gyy); + + +for every frame: +for every feature: +through all pyramid levels from lowres to highres: + +calculate diff, gradx, grady +gen eigenvalue matrix +error vector = [gradx, grady]*imdiff + +float det = gxx*gyy - gxy*gxy; +if (det < small) return KLT_SMALL_DET; +*dx = (gyy*ex - gxy*ey)/det; +*dy = (gxx*ey - gxy*ex)/det; + +add [dx,dy] to search position + + +*/ + diff --git a/FexTrackerSource/FexTracker.h b/FexTrackerSource/FexTracker.h new file mode 100644 index 000000000..7e82b238b --- /dev/null +++ b/FexTrackerSource/FexTracker.h @@ -0,0 +1,131 @@ + +// The following ifdef block is the standard way of creating macros which make exporting +// from a DLL simpler. All files within this DLL are compiled with the FEXTRACKER_EXPORTS +// symbol defined on the command line. this symbol should not be defined on any project +// that uses this DLL. This way any other project whose source files include this file see +// FEXTRACKER_API functions as being imported from a DLL, wheras this DLL sees symbols +// defined with this macro as being exported. +#ifdef FEXTRACKER_EXPORTS +#define FEXTRACKER_API __declspec(dllexport) +#else +#define FEXTRACKER_API __declspec(dllimport) +#endif + + + +class FEXTRACKER_API FexTrackerConfig +{ +public: + inline FexTrackerConfig() : + FeatureNumber(0), + EdgeDetectSigma(1.f), + WindowX(3), WindowY(3), + SearchRange(15), + MaxIterations(10), + MinDeterminant(0.01f), + MinDisplacement(0.1f), + MaxResidue(10.f), + IgnoreLightning(0), + DetectSmoothSigma(0.9f), + MinDistanceSquare(100.f) + {}; + + int FeatureNumber; + + int WindowX, WindowY; //static const int window_size = 7; + int SearchRange; + + float DetectSmoothSigma; //static const float pyramid_sigma_fact = 0.9f; + float EdgeDetectSigma; //static const float grad_sigma = 1.0f; + + int MaxIterations; //static const int max_iterations = 10; + float MinDeterminant; //static const float min_determinant = 0.01f; + float MinDisplacement; //static const float min_displacement = 0.1f; + float MaxResidue; //static const float max_residue = 10.0f; + + bool IgnoreLightning; //static const KLT_BOOL lighting_insensitive = FALSE; + + float MinDistanceSquare; //static const int mindist = 10; + + //static const int min_eigenvalue = 1; + //static const float smooth_sigma_fact = 0.1f; + //static const KLT_BOOL sequentialMode = FALSE; + ///* for affine mapping*/ + //static const int affineConsistencyCheck = -1; + //static const int affine_window_size = 15; + //static const int affine_max_iterations = 10; + //static const float affine_max_residue = 10.0; + //static const float affine_min_displacement = 0.02f; + //static const float affine_max_displacement_differ = 1.5f; +}; + +typedef struct{ + float x, y; +}vec2; + +typedef struct{ + float x, y, z; +}vec3; + +class FexImgPyramid; +class FexTrackingFeature; +class FexMovement; + +class FEXTRACKER_API FexTracker +{ +public: + FexTracker( int sx, int sy, int nFeatures ); + ~FexTracker(); +//config + FexTrackerConfig Cfg; +//work + void ProcessImage( float *Img, bool bFirst=0 ); //we assume grayscale image here + void ProcessingDone(); // call after last call to ProcessImage to clear temporary storage + +//point -> movement + void InfluenceFeatures( int Frame, float x, float y, float off ); + FexMovement* GetMovement(); + +//feature access + FexTrackingFeature* operator [] ( int i ); + inline int GetCount(){ return nFeatures; }; + inline int GetFrame(){ return CurFrame; }; + inline int GetSizeX(){ return SizX; }; + inline int GetSizeY(){ return SizY; }; + + bool bDebug; + int minFeatures; +private: + int SizX, SizY; + int PyramidSubsampling; + int PyramidMaxLevels; + FexImgPyramid* CurImg; + FexImgPyramid* NextImg; + + void FindFeatures( int minFeatures ); + void TrackFeatures(); + + bool TrackOneFeature( int lvl, vec2 op, vec2& np ); + int GetEigenvalueForPoint( int px, int py ); + void GetDiffForPointset( int lvl, vec2 op, vec2 np, float* diff ); + void GetGradForPointset( int lvl, vec2 op, vec2 np, float* gradx, float* grady ); + + void CountActiveFeatures(); + +//result + FexTrackingFeature* lFeatures; + int nFeatures; + int nActiveFeatures; + int mFeatures; + + int CurFrame; +}; + + + +FEXTRACKER_API void FexBaseResize( float* out, int newx, int newy, float* in, int sizx, int sizy ); +FEXTRACKER_API void GaussKernelWidths( float sigma, int *gauss_width, int *gaussderiv_width ); +FEXTRACKER_API void GaussEdgeDetect( float* Img, int sizx, int sizy, float sigma, float* GradX, float* GradY ); +FEXTRACKER_API void GaussSmooth( float* Img, int sizx, int sizy, float sigma, float* Out ); + + diff --git a/FexTrackerSource/FexTrackerMovement.cpp b/FexTrackerSource/FexTrackerMovement.cpp new file mode 100644 index 000000000..82ab8d98a --- /dev/null +++ b/FexTrackerSource/FexTrackerMovement.cpp @@ -0,0 +1,248 @@ +// FexTrackerMovement.cpp +// + +#include "StdAfx.h" +#include "stdio.h" +//#include "mmsystem.h" + + + +void FexTracker::InfluenceFeatures( int Frame, float x, float y, float off ) +{ + for( int i=0;i1 ) lFeatures[i].Influence = 1; + } +} + +/* +void LineTracing( haAssLine *c, vec2& TracePos, vec2& TraceScale, int Frame, vec2 InScreenPlace ) +{ + TracePos = vec2(0,0); + TraceScale = vec2(0,0); + + vec2 Sum1Pos = vec2(0,0); + vec2 Sum2Pos = vec2(0,0); + float TraceScaleV=0; + + float wsum = 0; + + for( int i=0;iFeatureIdList.GetSize();i++ ) + { + tenFeatureLink l = c->FeatureIdList[i]; + tenFeature f = Trace_GetFeatureByID( l.id, Frame ); + if( f.id < 0 || l.weight<0.01 ) + continue; + Sum1Pos += vec2( + (f.x)/float(ncols)*float(AssRes[0]), + (f.y)/float(nrows)*float(AssRes[1]) + )*l.weight; + Sum2Pos += vec2( + (l.sub.x)/float(ncols)*float(AssRes[0]), + (l.sub.y)/float(nrows)*float(AssRes[1]) + )*l.weight; + wsum += l.weight; + } + if( wsum>0.01 ) + { + Sum1Pos /= wsum; + Sum2Pos /= wsum; + TracePos = Sum1Pos - Sum2Pos; + + wsum = 0; + CArray DistList; + CArray WeightList; + +//now we know weighted mid point, gen vectors from points to mid + for( int i=0;iFeatureIdList.GetSize();i++ ) + { + tenFeatureLink l = c->FeatureIdList[i]; + tenFeature f = Trace_GetFeatureByID( l.id, Frame ); + if( f.id < 0 || l.weight<0.01 ) + continue; + vec2 mid = vec2( + (f.x)/float(ncols)*float(AssRes[0]), + (f.y)/float(nrows)*float(AssRes[1]) + ); + vec2 midToMe = mid - Sum1Pos; + vec2 stdMidToMe = vec2( + (l.sub.x)/float(ncols)*float(AssRes[0]), + (l.sub.y)/float(nrows)*float(AssRes[1]) + ) - Sum2Pos; + + float stdlen = sqrtf( stdMidToMe.x*stdMidToMe.x + stdMidToMe.y*stdMidToMe.y ); + if( stdlen < 3 ) + {//too much error amplification.skip + continue; + } + + float len = sqrtf( midToMe.x*midToMe.x + midToMe.y*midToMe.y ); + float scale = len/stdlen; + // TRACE( "%f\n", scale ); + float addme = scale*l.weight; + TraceScaleV += addme; + DistList.Add( scale ); + WeightList.Add( l.weight ); + wsum += l.weight; + } + TraceScaleV /= wsum; + + float TraceScaleV2=0; + for( i=0;i0.01 ) + fprintf( log, "Feature(%.2f): %d - %d\n", lFeatures[i].Influence, lFeatures[i].StartTime, lFeatures[i].StartTime+lFeatures[i].Pos.size() ); + } + + FexMovement *m = new FexMovement(); + FexMovementFrame f; + + float FirstInfluenceSum = 0; + vec2 FirstPos; + FirstPos.x = FirstPos.y = 0; + + for( i=0;i MidOffLen /= FirstLen; + MidOffset[i].x /= FirstLen; + MidOffset[i].y /= FirstLen; + MidOffsetLen[i] = VEC2LEN( MidOffset[i] ); + } + } + + //accumulate position + float NextLen = 0; + float NextInfluenceSum = 0; + vec2 NextPos; + NextPos.x = NextPos.y = 0; + + for( i=0;i 0.01 ) + { + NextPos.x /= NextInfluenceSum; + NextPos.y /= NextInfluenceSum; + } + else + NextPos = FirstPos; //take over last one + + for( i=0;i 0.01 ) + { + NextLen /= NextInfluenceSum; + } + else + NextLen = FirstLen; //take over last one + + f.Pos = NextPos; + f.Rot.x = 0; + f.Rot.y = 0; + f.Rot.z = 0; + f.Scale.x = NextLen; + f.Scale.y = NextLen; + m->Frames.Add( f ); + + FirstPos = NextPos; + FirstLen = NextLen; + } + + delete []MidOffset; + delete []MidOffsetLen; + + fclose( log ); + + return m; +} + diff --git a/FexTrackerSource/FexTrackingFeature.cpp b/FexTrackerSource/FexTrackingFeature.cpp new file mode 100644 index 000000000..74352b92b --- /dev/null +++ b/FexTrackerSource/FexTrackingFeature.cpp @@ -0,0 +1,19 @@ +// FexTrackingFeature.cpp: implementation of the FexTrackingFeature class. +// +////////////////////////////////////////////////////////////////////// + +#include "StdAfx.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +FexTrackingFeature::FexTrackingFeature() +{ +} + +FexTrackingFeature::~FexTrackingFeature() +{ + +} + \ No newline at end of file diff --git a/FexTrackerSource/FexTrackingFeature.h b/FexTrackerSource/FexTrackingFeature.h new file mode 100644 index 000000000..f0371274e --- /dev/null +++ b/FexTrackerSource/FexTrackingFeature.h @@ -0,0 +1,27 @@ +// FexTrackingFeature.h: interface for the FexTrackingFeature class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_FEXTRACKINGFEATURE_H__23B42013_9F11_467C_A0F6_F9E647D45CEB__INCLUDED_) +#define AFX_FEXTRACKINGFEATURE_H__23B42013_9F11_467C_A0F6_F9E647D45CEB__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "tenlist.h" +class FexTrackingFeature +{ +public: + FexTrackingFeature(); + ~FexTrackingFeature(); + + int Eigenvalue; + tenlist Pos; + + int StartTime; + + float Influence; +}; + +#endif // !defined(AFX_FEXTRACKINGFEATURE_H__23B42013_9F11_467C_A0F6_F9E647D45CEB__INCLUDED_) diff --git a/FexTrackerSource/StdAfx.cpp b/FexTrackerSource/StdAfx.cpp new file mode 100644 index 000000000..d00d66a44 --- /dev/null +++ b/FexTrackerSource/StdAfx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// FexTracker.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "StdAfx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/FexTrackerSource/StdAfx.h b/FexTrackerSource/StdAfx.h new file mode 100644 index 000000000..2f66eda09 --- /dev/null +++ b/FexTrackerSource/StdAfx.h @@ -0,0 +1,34 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__7E36ECD6_3192_4C7E_88C9_742CCCFA5057__INCLUDED_) +#define AFX_STDAFX_H__7E36ECD6_3192_4C7E_88C9_742CCCFA5057__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +// Insert your headers here +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +#include +#include +#include +#include + +#include "FexTracker.h" +#include "FexImgPyramid.h" +#include "FexTrackingFeature.h" +#include "FexMovement.h" + +#include "ext/imdebug.h" + +// TODO: reference additional headers your program requires here + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__7E36ECD6_3192_4C7E_88C9_742CCCFA5057__INCLUDED_) diff --git a/FexTrackerSource/tenlist.h b/FexTrackerSource/tenlist.h new file mode 100644 index 000000000..1bbd0029e --- /dev/null +++ b/FexTrackerSource/tenlist.h @@ -0,0 +1,65 @@ +#pragma once + +template< class type > + class tenlist { +public: + int nVal; + int mVal; + type* lVal; + + inline tenlist() + { + mVal = 0; + nVal = 0; + lVal = 0; + //zero everything since we well over-zero it anyway + } + inline ~tenlist() + { + free( lVal ); + } + + inline int size() + { + return nVal; + } + + inline void Add( type t ) + { + if( nVal+1 >= mVal ) + { + mVal += 8; + lVal = (type*)realloc( lVal, sizeof(type)*mVal ); + memset( lVal+nVal, 0x00, sizeof(type)*(mVal-nVal) ); //lVal+nVal, since it'll be multiplied by sizeof(type) due to lVal being a type* + } + lVal[nVal++] = t; + } + + inline void AddStr( type t ) + { + if( nVal+1 >= mVal ) + { + mVal += 8; + lVal = (type*)realloc( lVal, sizeof(type)*mVal ); + memset( lVal+nVal, 0x00, sizeof(type)*(mVal-nVal) ); //lVal+nVal, since it'll be multiplied by sizeof(type) due to lVal being a type* + } + strcpy( lVal[nVal++], t ); + } + + inline void Rem( int n ) + { + if( n>=nVal ) + { + nVal = 0; + return; + } + + for( int i=0;iGetDialogue(EditBox->linen); + if (!curline) return; + if( curline->Movement ) DeleteMovement( curline->Movement ); + curline->Movement = CreateMovement(); + + // Create split lines + int StartFrame = VFR_Output.GetFrameAtTime(curline->Start.GetMS(),true); + int EndFrame = VFR_Output.GetFrameAtTime(curline->End.GetMS(),false); + + FexMovementFrame f; + memset( &f, 0x00, sizeof(f) ); + f.Scale.x = f.Scale.y = 1; + + for( int i=StartFrame;iMovement->Frames.Add( f ); +} + + +/////////////////// +// link line to move file +void FrameMain::OnVideoTrackLinkFile(wxCommandEvent &event) { + videoBox->videoDisplay->Stop(); + + // Get line + AssDialogue *curline = SubsBox->GetDialogue(EditBox->linen); + if (!curline) return; + + wxString link = wxGetTextFromUser(_("Link name:"), _("Link line to movement file"), curline->Movement?curline->Movement->FileName:_T(""), this); + if( link.empty() ) curline->Effect = _T(""); + else curline->Effect = _T("FexMovement:")+link; + + curline->UpdateData(); + + if( !curline->Effect.empty() && curline->Movement ) + SaveMovement( curline->Movement, (unsigned short*) curline->Effect.AfterFirst(':').c_str() ); +} + + /////////////////// // Increase Influence void FrameMain::OnVideoTrackPointAdd(wxCommandEvent &event) { diff --git a/core/frame_main.h b/core/frame_main.h index 1c5f920b0..8d8013135 100644 --- a/core/frame_main.h +++ b/core/frame_main.h @@ -118,6 +118,8 @@ private: void OnVideoTrackMovementMoveBefore(wxCommandEvent &event); void OnVideoTrackMovementMoveAfter(wxCommandEvent &event); void OnVideoTrackSplitLine(wxCommandEvent &event); + void OnVideoTrackLinkFile(wxCommandEvent &event); + void OnVideoTrackMovementEmpty(wxCommandEvent &event); void OnKeyDown(wxKeyEvent &event); @@ -352,6 +354,8 @@ enum { Video_Track_Movement_MoveBefore, Video_Track_Movement_MoveAfter, Video_Track_Split_Line, + Video_Track_Link_File, + Video_Track_Movement_Empty, Menu_File_Recent = 2000, Menu_Video_Recent = 2200, diff --git a/core/frame_main_events.cpp b/core/frame_main_events.cpp index fbfbf7aa4..f572c9f8b 100644 --- a/core/frame_main_events.cpp +++ b/core/frame_main_events.cpp @@ -104,6 +104,8 @@ BEGIN_EVENT_TABLE(FrameMain, wxFrame) EVT_MENU(Video_Track_Movement_MoveBefore, FrameMain::OnVideoTrackMovementMoveBefore) EVT_MENU(Video_Track_Movement_MoveAfter, FrameMain::OnVideoTrackMovementMoveAfter) EVT_MENU(Video_Track_Split_Line, FrameMain::OnVideoTrackSplitLine) + EVT_MENU(Video_Track_Link_File, FrameMain::OnVideoTrackLinkFile) + EVT_MENU(Video_Track_Movement_Empty, FrameMain::OnVideoTrackMovementEmpty) #endif EVT_CLOSE(FrameMain::OnCloseWindow)