MS Kinect FaceTracker creating IFTResult - c++

I have a fairly simple application that contains the following:
context->mFaceTracker = FTCreateFaceTracker();
hr = context->mFaceTracker->Initialize( &mVideoCameraConfig, &mDepthCameraConfig, NULL, NULL );
which works fine and returns S_OK and mFaceTracker is (as far as I can tell) initialized properly. However, the next line is:
hr = context->mFaceTracker->CreateFTResult( &context->mFTResult );
which always returns FT_ERROR_UNINITIALIZED, doesn't allocate the pointer, and has me puzzled. I've tried many different strategies for getting this to work from changing how the threading for the device and detector works, to changing my FTcontext object from a class to a struct to match the samples, all with no success. The Kinect SDK samples all work fine, but trying to use them in my own application doesn't seem to, despite my closely mirroring how they initialize the device and the Face Tracker. I'm curious if anyone else has run into this or similar problems around initializing either IFTFaceTracker or the IFTResult. Also, I'm curious how else I can test the IFTFaceTracker for correct intialization, other than testing the HRESULT that Initialize() returns. Thanks in advance,
=== edit
I've had a few request for more code. It's built on Cinder and is using this block for Cinder: https://github.com/BanTheRewind/Cinder-KinectSdk
I can't post all of the code, but I've posted at least most of the relevant Kinect initialization code here:
void Kinect::start( const DeviceOptions &deviceOptions )
{
if ( !mCapture ) {
// Copy device options
mDeviceOptions = deviceOptions;
string deviceId = mDeviceOptions.getDeviceId();
int32_t index = mDeviceOptions.getDeviceIndex();
// Clamp device index
if ( index >= 0 ) {
index = math<int32_t>::clamp( index, 0, math<int32_t>::max( getDeviceCount() - 1, 0 ) );
}
// Initialize device instance
long hr = S_OK;
if ( index >= 0 ) {
hr = NuiCreateSensorByIndex( index, &mSensor );
if ( FAILED( hr ) ) {
trace( "Unable to create device instance " + toString( index ) + ": " );
error( hr );
return;
}
} else if ( deviceId.length() > 0 ) {
_bstr_t id = deviceId.c_str();
hr = NuiCreateSensorById( id, &mSensor );
if ( FAILED( hr ) ) {
trace( "Unable to create device instance " + deviceId + ":" );
error( hr );
return;
}
} else {
trace( "Invalid device name or index." );
return;
}
// Check device
hr = mSensor != 0 ? mSensor->NuiStatus() : E_NUI_NOTCONNECTED;
if ( hr == E_NUI_NOTCONNECTED ) {
error( hr );
return;
}
// Get device name and index
if ( mSensor != 0 ) {
mDeviceOptions.setDeviceIndex( mSensor->NuiInstanceIndex() );
BSTR id = ::SysAllocString( mSensor->NuiDeviceConnectionId() );
_bstr_t idStr( id );
if ( idStr.length() > 0 ) {
std::string str( idStr );
mDeviceOptions.setDeviceId( str );
}
::SysFreeString( id );
} else {
index = -1;
deviceId = "";
}
flags |= NUI_INITIALIZE_FLAG_USES_COLOR;
}
hr = mSensor->NuiInitialize( flags );
if ( FAILED( hr ) ) {
trace( "Unable to initialize device " + mDeviceOptions.getDeviceId() + ":" );
error( hr );
return;
}
hr = mSensor->NuiSkeletonTrackingEnable( 0, flags );
if ( FAILED( hr ) ) {
trace( "Unable to initialize skeleton tracking for device " + mDeviceOptions.getDeviceId() + ": " );
error( hr );
return;
}
mIsSkeletonDevice = true;
mThread = CreateThread(NULL, 0, &Kinect::StaticThread, (PVOID)this, 0, 0);
}
}
DWORD WINAPI Kinect::StaticThread(PVOID lpParam)
{
Kinect* device = static_cast<Kinect*>(lpParam);
if (device)
{
return device->run();
}
return 0;
}
void run() {
if(mSensor) {
if(mEnabledFaceTracking)
{
if(mNeedFaceTracker) {
mFaceTracker = new FaceTracker(
mDeviceOptions.getVideoSize().x,
mDeviceOptions.getVideoSize().y,
mDeviceOptions.getDepthSize().x,
mDeviceOptions.getDepthSize().y,
1.0,
1 );
mNeedFaceTracker = false;
}
// make sure we have both color && depth buffers to work with
if(newDepth || newVideo)
{
FT_SENSOR_DATA sensorData(mFTColorImage, mFTDepthImage);
FT_VECTOR3D hint[2]; // this is initialized elsewhere
mFaceTracker->checkFaces( (NUI_SKELETON_FRAME*) &skeletonFrame, mFTColorImage, mFTDepthImage, 1.0, 0);
if(mFaceTracker->getNumFaces() > 0) {
cout << " we have a face " << mFaceTracker->getNumFaces() << endl;
mNewFaceTrackData = true;
mFaceData.clear();
for( int i = 0; i < mFaceTracker->getNumFaces(); i++) {
Face newFace;
mFaceTracker->getProjectedShape(0, newFace.scale, newFace.rotation, newFace.transform, newFace.screenPositions);
mFaceData.push_back(newFace);
}
}
}
}
Sleep( 8 );
}
}

It looks like you never call (or omitted including in the code sample) NuiImageStreamOpen(), such as this code snippet from the SingleFace sample, KinectSensor.cpp in the Init method:
hr = NuiImageStreamOpen(
colorType,
colorRes,
0,
2,
m_hNextVideoFrameEvent,
&m_pVideoStreamHandle );
if (FAILED(hr))
{
return hr;
}
hr = NuiImageStreamOpen(
depthType,
depthRes,
(bNearMode)? NUI_IMAGE_STREAM_FLAG_ENABLE_NEAR_MODE : 0,
2,
m_hNextDepthFrameEvent,
&m_pDepthStreamHandle );
Calling those before you call CreateFTResult() may fix the uninitialized error.
Additionally, you call CreateThread() and then call run(), but there is no while loop so that thread will exit almost immediately, certainly without enough time for the Kinect to start providing data to the FaceTracking.
It doesn't look like you have included the Thread or event loop that is checking the sensor for new data, updating mFTColorImage and mFTDepthImage, and setting the newDepth and newVideo flags. This could be in the same thread that you create above (provided you create a while loop, and ignoring performance or other classes needing the Kinect data), or could be a different thread as in the SingleFace Kinect SDK sample.

Related

Crash in DuplicateOutput

I'm developing an application which captures frames using DXGI mechanism from an application.
First creation of the IDXGIOutputDuplication is correct. When the application changes its display (for example from fullscreen to windowed or vice versa), the frame acquire failed (expected behaviour), then I recreate the IDXGIOutputDuplication and regularly the call to DuplicateOutput crash.
Below creation of the D3d11 device:
D3D_FEATURE_LEVEL FeatureLevels[] =
{
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_1
};
UINT NumFeatureLevels = ARRAYSIZE( FeatureLevels );
D3D_FEATURE_LEVEL FeatureLevel = D3D_FEATURE_LEVEL_11_1;
D3D11CreateDevice( _pDxgiAdapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr, 0, FeatureLevels, NumFeatureLevels, D3D11_SDK_VERSION, &_pD3D11Device, &FeatureLevel, &_pD3D11DeviceCtx );
_pDxgiAdapter is created before the device.
Below creation of the IDXGIOutputDuplication:
int DxgiVideoCapture::open() {
findDxgiAdapter();
if( nullptr != _pDxgiAdapter ) {
// Duplicate output
uint32_t ui32OutputIndex = 0;
HRESULT hr = S_OK;
while( SUCCEEDED( hr ) ) {
IDXGIOutput* pDxgiOutput = nullptr;
hr = _pDxgiAdapter->EnumOutputs( ui32OutputIndex, &pDxgiOutput );
if( SUCCEEDED( hr ) ) {
IDXGIOutput1* pDxgiOutput1 = nullptr;
if( SUCCEEDED ( pDxgiOutput->QueryInterface( __uuidof( IDXGIOutput1 ), ( void** )&pDxgiOutput1 ) ) ) {
uint32_t ui32EnumMode = 0;
uint32_t ui32Flags = 0xffffffff;
}
if( SUCCEEDED ( pDxgiOutput->QueryInterface( __uuidof( IDXGIOutput1 ), ( void** )&_pDxgiOutput1 ) ) ) {
LOGI( "/!\\ Call which crash regularly /!\\" );
HRESULT hrDup = _pDxgiOutput1->DuplicateOutput( _pD3D11Device, &_pOutputDuplication );
if( SUCCEEDED( hrDup ) ) {
LOGI( "Output duplication created." );
} else {
switch( hrDup ) {
case E_INVALIDARG :
{
LOGW( "Invalid device or output already duplicated" );
}
break;
case E_ACCESSDENIED :
{
LOGW( "Access denied" );
}
break;
case DXGI_ERROR_UNSUPPORTED :
{
LOGW( "DXGI_ERROR_UNSUPPORTED" );
}
break;
case DXGI_ERROR_NOT_CURRENTLY_AVAILABLE :
{
LOGW( "DXGI_ERROR_NOT_CURRENTLY_AVAILABLE" );
}
break;
case DXGI_ERROR_SESSION_DISCONNECTED :
{
LOGW( "DXGI_ERROR_NOT_CURRENTLY_AVAILABLE" );
}
break;
default:
{
LOGW( "default" );
}
}
} else {
LOGE( "Unable to retrieve interface creating the ouput duplication" );
}
}
pDxgiOutput->Release();
}
ui32OutputIndex++;
}
return RET_OK;
}
Below the frame acquisition:
int DxgiVideoCapture::captureGameFrame() {
int iRet = RET_ERROR;
ID3D11Texture2D* pCapturedTexture = nullptr;
DXGI_OUTDUPL_FRAME_INFO frameInfo;
ZeroMemory(&frameInfo, sizeof(frameInfo));
HRESULT hr = _pOutputDuplication->AcquireNextFrame( 1000, &frameInfo, &_pDxgiResource );
if( FAILED( hr ) ) {
if( hr == DXGI_ERROR_WAIT_TIMEOUT ) {
LOGW( "Wait for %d ms timed out", 1000);
}
if (hr == DXGI_ERROR_INVALID_CALL) {
LOGW( "Invalid Call, previous frame not released?" );
}
if (hr == DXGI_ERROR_ACCESS_LOST) {
LOGW( "Error Access lost - is it a game end ?" );
}
iRet = RET_RESET_CAPTURE;
return iRet;
}
if( FAILED( hr = _pDxgiResource->QueryInterface( __uuidof( ID3D11Texture2D ), ( void** ) &pCapturedTexture ) ) ) {
LOGW( "unable to retrieve D3D11 texture 0x%x", hr );
return RET_WARNING;
} else {
// Store window of the game
D3D11_TEXTURE2D_DESC d3D11TextureDesc;
pCapturedTexture->GetDesc( &d3D11TextureDesc );
// Compute the zone to extract.
D3D11_BOX srcBox;
memset( &srcBox, 0, sizeof( srcBox ) );
if( _pGameWindow->getLeftPos() > 0 ) {
srcBox.left = _pGameWindow->getLeftPos();
}
if( _pGameWindow->getTopPos() > 0 ) {
srcBox.top = _pGameWindow->getTopPos();
}
srcBox.front = 0;
srcBox.right = _pGameWindow->getLeftPos() + _pGameWindow->getWidth();
if( srcBox.right > _pGameWindow->getMonitorWidth() ) {
srcBox.right = _pGameWindow->getMonitorWidth();
}
if( ( srcBox.right - srcBox.left ) % 2 != 0 ) {
srcBox.right--;
}
srcBox.bottom = _pGameWindow->getTopPos() + _pGameWindow->getHeight();
if( srcBox.bottom > _pGameWindow->getMonitorHeight() ) {
srcBox.bottom = _pGameWindow->getMonitorHeight();
}
if( ( srcBox.bottom - srcBox.top ) % 2 != 0 ) {
srcBox.bottom--;
}
srcBox.back = 1;
// AVFrame info are udpate just when the captured game window and the texture are diffrent.
// In the same time texture is reallocated.
if( ( ( srcBox.right - srcBox.left ) != _CapturedTextureDesc.Width )
|| ( ( srcBox.bottom - srcBox.top ) != _CapturedTextureDesc.Height )
) {
LOGD( "Game window: %dx%d ; %d->%d", _pGameWindow->getLeftPos(), _pGameWindow->getTopPos(), _pGameWindow->getWidth(), _pGameWindow->getHeight() );
LOGD( "Texture creation %dx%d -> %dx%d", srcBox.left, srcBox.top, srcBox.right, srcBox.bottom );
// Create the new texture
iRet = createCapturedTexture( srcBox.right - srcBox.left, srcBox.bottom - srcBox.top );
}
DirectX11Util::GetInstance()->getD3D11DeviceContext()->CopySubresourceRegion( _pGameTexture, 0, 0, 0, 0, pCapturedTexture, 0, &srcBox );
}
if( nullptr != _pDxgiResource ) {
_pOutputDuplication->ReleaseFrame();
pCapturedTexture->Release();
_pDxgiResource->Release();
_pDxgiResource = nullptr;
}
iRet = RET_OK;
return iRet;
}
Below the release of the D3d11 capture before recreation of the IDXGIOutputDuplication:
int DxgiVideoCapture::close() {
if( nullptr != _pGameTexture ) {
ZeroMemory( &_CapturedTextureDesc, sizeof( D3D11_TEXTURE2D_DESC ) );
_pGameTexture->Release();
_pGameTexture = nullptr;
}
if( nullptr != _pDxgiResource ){
_pOutputDuplication->ReleaseFrame();
_pDxgiResource->Release();
_pDxgiResource = nullptr;
}
if( nullptr != _pOutputDuplication ) {
_pOutputDuplication->Release();
_pOutputDuplication = nullptr;
}
return RET_OK;
}
What I would like to know is how can I invest this crash (application ends without any message). To be more accurate I cross compile my application, but the behaviour seems the same. Do you have any idea how to invest this issue ?
Tell me if you want more details.
Thanks in advance !

How to define an audio output programmatically on Windows 10?

I'm developing a C++ application which implements the Microsoft Speech API (SAPI). I developed numerous functions related to Text-To-Speech. Among them a function which allows the listing of the audio outputs, and a function that allows to define an audio output.
I started developing this program on Windows 7, but now I switched to Windows 10. However, the function that defines the audio output doesn't work anymore. I didn't edited a thing in my code, and on Windows 7 it worked perfectly.
Here is the code which lists the available audio outputs
int getAudioOut( int auOut ) //get audio outputs function
{
if( SUCCEEDED( hr ) )
{
//Enumerate Audio Outputs
hr = SpEnumTokens( SPCAT_AUDIOOUT, NULL, NULL, &cpEnum );
cpEnum->GetCount( &vCount );
cpEnum->Item( saveAudio, &cpAudioOutToken );
SpGetDescription( cpAudioOutToken, &dynStr );
printf( "Defined audio output is: %ls\n\n", dynStr );
dynStr.Clear();
//Loop through the audio output list and enumerate them all
for( audioOut = 0; audioOut <= vCount - 1; audioOut++ )
{
cpAudioOutToken.Release();
cpEnum->Item( audioOut, &cpAudioOutToken );
SpGetDescription( cpAudioOutToken, &dynStr );
printf( "Defined Audio Output %i - %ls\n", audioOut, dynStr );
dynStr.Clear();
}
printf( "\n" );
audioOut = saveAudio;
cpEnum.Release();
cpAudioOutToken.Release();
}
else
{
printf( "Could not enumerate available audio outputs\n" );
}
return true;
}
Here is the code which allows the definition of an audio output
int setAudioOut( int auOut ) //define audio output function
{
if( SUCCEEDED( hr ) )
{
hr = SpEnumTokens( SPCAT_AUDIOOUT, NULL, NULL, &cpEnum );
cpEnum->GetCount( &vCount );
size_t nOut = auOut;
if( nOut >= vCount )
{
cout << "Not so many audio outputs available! Try again\n" << endl;
}
else
{
cout << "Success" << endl;
}
ULONG audioOut = static_cast<ULONG>( nOut ); //convert nOut to ULONG audioOut
cpEnum->Item( audioOut, &cpAudioOutToken );
SpGetDescription( cpAudioOutToken, &dynStr );
printf( "You chose %ls\n\n", dynStr );
cpVoice->SetOutput( cpAudioOutToken, TRUE ); //Initialization of the Audio Output
dynStr.Clear();
cpEnum.Release();
cpAudioOutToken.Release();
saveAudio = audioOut; //define saveAudio to audioOut value
}
else
{
printf( "Could not set audio output\n" );
}
return true;
}
When I start my program and call the getAudioOut function, I get following listing:
The first line shows the default audio output, and the two below are the available outputs. On Windows 7, when I set the second audio output (Lautsprecher / Kopfhörer) as default, then no sound comes out from the first (Digitalaudio), which makes sense. However, on Windows 10 I have reproduced the same procedure but it doesn't work. The audio output is always defined according to the audio menu.
My question is, does anyone have experienced this issue? Is there an alternative to define an audio output programmatically?
I edited the code as #NikolayShmyrev suggested but it didn't change a thing. However, I continued to dig into the problem an found out that the issue came from another function. Indeed, when I switched from Windows 7 to Windows 10, I encountered other problems with the speech synthesis function and the speech to WAV file function. When I started the program and called the Text-To-Speech function, everything worked great. When I called the Speech2Wav function, it worked too. However, when I recalled the Text-To-Speech function, the variable HRESULT hr = S_OK; changed its value and no sound was played. The value of hr was set to -2147200968 which corresponds to Error 0x80045038: SPERR_STREAM_CLOSED (source/list of error codes)
To solve this issue I had to define an audio output like this cpVoice->SetOutput( cpAudioOutToken, TRUE ); in the Text-To-Speech function.
This brings us back to the problem I stated above. When I set the audio output in the function setAudioOut, I release its value at the end cpAudioOutToken.Release();
However, I reuse the same variable in the Text-To-Speech function. Its value was set to nothing because I released it when I defined the audio output. This is why the audio output was always set to default. In order to solve the problem, I assigned the value of cpAudioOutToken to another variable called cpSpeechOutToken.
Here is the code for the function setAudioOut
int setAudioOut( int auOut ) //define audio output function
{
if( SUCCEEDED( hr ) )
{
hr = SpEnumTokens( SPCAT_AUDIOOUT, NULL, NULL, &cpEnum );
cpEnum->GetCount( &vCount );
size_t nOut = auOut;
if( nOut >= vCount )
{
cout << "Not so many audio outputs available! Try again\n" << endl;
return 0;
}
else
{
cout << "Success" << endl;
}
ULONG audioOut = static_cast<ULONG>( nOut ); //convert nOut to ULONG audioOut
cpEnum->Item( audioOut, &cpAudioOutToken );
SpGetDescription( cpAudioOutToken, &dynStr );
printf( "You chose %ls\n\n", dynStr );
cpVoice->SetOutput( cpAudioOutToken, TRUE ); //Initialization of the Audio Output
dynStr.Clear();
cpEnum.Release();
cpSpeechOutToken = cpAudioOutToken;
cpAudioOutToken.Release();
saveAudio = audioOut; //define saveAudio to audioOut value
}
else
{
printf( "Could not set audio output\n" );
}
return true;
}
Here is the code from the Text-To-Speech function
int ttsSpeak( const char* text ) //Text to Speech speaking function
{
if( SUCCEEDED( hr ) )
{
string xmlSentence( text );
hr = SpEnumTokens( SPCAT_VOICES_WIN10, NULL, NULL, &cpEnum );
//Replace SPCAT_VOICES_WIN10 with SPCAT_VOICES if you want to use it on Windows 7
cpEnum->Item( saveVoice, &cpVoiceToken ); //get saveVoice token defined at line 175
cpVoice->SetVoice( cpVoiceToken ); //Initialization of the voice
//string strText( text );
int wchars_num = MultiByteToWideChar( CP_ACP, 0, xmlSentence.c_str(), -1, NULL, 0 );
wchar_t* wstr = new wchar_t[ wchars_num ];
MultiByteToWideChar( CP_ACP, 0, xmlSentence.c_str(), -1, wstr, wchars_num );
printf( "Text To Speech processing\n" );
cpVoice->SetOutput( cpSpeechOutToken, TRUE );
hr = cpVoice->Speak( wstr, SVSFIsXML, NULL );
saveText = xmlSentence.c_str();
cpEnum.Release();
cpVoiceToken.Release();
delete new wchar_t[ wchars_num ];
}
else
{
printf( "Could not speak entered text\n" );
}
return true;
}

How to get word list using ISpLexicon::GetWords?

I'm developping a Text-To-Speech application using Microsoft SAPI. I found out that it is possible to add customized prononciations of words in a dictionnary (correct me if I'm wrong). I implemented a function which allows to add words into this dictionnary. Here is my code:
int addPrononciation( const char* addPron, const char* phon )
{
hr = cpLexicon.CoCreateInstance( CLSID_SpLexicon );
hr = cpContainerLexicon.CoCreateInstance( CLSID_SpLexicon );
hr = SpEnumTokens( SPCAT_VOICES, NULL, NULL, &cpEnum );
cpEnum->Item( saveVoice, &cpVoiceToken ); //get saveVoice token defined at line 136
cpVoice->SetVoice( cpVoiceToken ); //Initialization of the voice
hr = cpContainerLexicon->AddLexicon( cpLexicon, eLEXTYPE_APP );
langId = MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US );
hr = SpCreatePhoneConverter( langId, NULL, NULL, &cpPhoneConv );
int wchars_num = MultiByteToWideChar( CP_ACP, 0, addPron, -1, NULL, 0 );
wchar_t* pronWstr = new wchar_t[ wchars_num ];
MultiByteToWideChar( CP_ACP, 0, addPron, -1, pronWstr, wchars_num );
int phonWchars_num = MultiByteToWideChar( CP_ACP, 0, phon, -1, NULL, 0 );
wchar_t* phonWstr = new wchar_t[ phonWchars_num ];
MultiByteToWideChar( CP_ACP, 0, phon, -1, phonWstr, phonWchars_num );
if(SUCCEEDED( hr ))
{
hr = cpPhoneConv->PhoneToId( phonWstr, wszId );
hr = cpVoice->Speak( phonWstr, SPF_DEFAULT, NULL );
hr = cpLexicon->AddPronunciation( pronWstr, langId, SPPS_Noun, wszId );
hr = cpVoice->Speak( pronWstr, SPF_DEFAULT, NULL );
if( SUCCEEDED( hr ) )
{
printf( "Success\n" );
}
else
{
printf( "Failed\n" );
}
}
cpEnum.Release();
cpVoiceToken.Release();
cpContainerLexicon.Release();
cpLexicon.Release();
cpPhoneConv.Release();
delete new wchar_t[ wchars_num ];
delete new wchar_t[ phonWchars_num ];
return true;
}
Now I would like to list these words using ISpLexicon::GetWords.
I already read the documentation on the Microsoft website and tried to implement the function, but I can't figure out how to initialize the variable spWordList.
Here is my code:
ZeroMemory( &spWordList, sizeof( spWordList ) );
if( SUCCEEDED( hr ) )
{
hr = cpLexicon->GetWords( eLEXTYPE_APP, &dwGeneration, &dwCookie, &spWordList );
printf( "Words: %ls\n", spWordList ); //print words but the output is null
}
CoTaskMemFree( spWordList.pvBuffer );
I'm triying to print the words, but the output is null. I think the spWordList variable is not initialized. Here is a screenshot of the variable values.
How can I initialize it?
I found out how to initialize spWordList. You have to replace eLEXTYPE_APP with eLEXTYPE_USER. However, you can keep both of them like I did. Below you will find an example on how it lists the words.
ZeroMemory( &spWordList, sizeof( spWordList ) );
hr = S_FALSE;
if( hr == S_FALSE )
{
hr = cpLexicon->GetWords( eLEXTYPE_USER | eLEXTYPE_APP, &dwGeneration, &dwCookie, &spWordList );
for( spWord = spWordList.pFirstWord; spWord != NULL; spWord = spWord->pNextWord )
{
for( spWordPron = spWord->pFirstWordPronunciation; spWordPron != NULL; spWordPron = spWordPron->pNextWordPronunciation )
{
printf( "Words in dictionnary: %i\n", dwGeneration );
printf( "Word: %ls\n", spWord->pszWord );
//you can also display the pronunciation of words if you wish
}
}
}
CoTaskMemFree( spWordList.pvBuffer );
In the code, I loop through the entire dictionnary. Notice that the listed words are displayed randomly. I'll update my answer if I find other important information about ISpLexicon::GetWords

Images and text not showing in SDL under Mac OSX

I got to compile, bundle and load resources under XCode 4.3 and SDL 1.2.15
I know resources are loading correctly because file handles are not null and no error is thrown.
I successfully load png's and ttf's, obtain and crop surfaces, and blit them.
But when I flip, the only thing I get to see are the lines I drew using SDL_Draw
I will put some bits of code, as I'm trying to keep an engine-ish structure so the code is everything but together.
Initialization:
void CEngine::Init() {
// Register SDL_Quit to be called at exit; makes sure things are cleaned up when we quit.
atexit( SDL_Quit );
// Initialize SDL's subsystems - in this case, only video.
if ( SDL_Init( SDL_INIT_EVERYTHING ) < 0 ) {
fprintf( stderr, "Unable to init SDL: %s\n", SDL_GetError() );
exit( 1 );
}
// Attempt to create a window with the specified height and width.
SetSize( m_iWidth, m_iHeight );
// If we fail, return error.
if ( m_pScreen == NULL ) {
fprintf( stderr, "Unable to set up video: %s\n", SDL_GetError() );
exit( 1 );
}
AdditionalInit();
}
and
void CTileEngine::AdditionalInit() {
SetTitle( "TileEngine - Loading..." );
PrintDebug("Initializing SDL_Image");
int flags = IMG_INIT_PNG;
int initted = IMG_Init( flags );
if( ( initted & flags ) != flags ) {
PrintDebug("IMG_Init: Failed to init required image support!");
PrintDebug(IMG_GetError());
// handle error
}
PrintDebug("Initializing SDL_TTF");
if( TTF_Init() == -1 ) {
PrintDebug("TTF_Init: Failed to init required ttf support!");
PrintDebug(TTF_GetError());
}
PrintDebug("Loading fonts");
font = TTF_OpenFont( OSXFileManager::GetResourcePath("Roboto-Regular.ttf"), 28 );
if( !font ) {
PrintDebug("Error loading fonts");
PrintDebug(TTF_GetError());
}
g_pGame = new CGame;
LoadGame( OSXFileManager::GetResourcePath( "test", "tmx") );
SetTitle( "TileEngine" );
PrintDebug("Finished AditionalInit()");
}
Main draw method
void CEngine::DoRender(){
++m_iFPSCounter;
if ( m_iFPSTickCounter >= 1000 ) {
m_iCurrentFPS = m_iFPSCounter;
m_iFPSCounter = 0;
m_iFPSTickCounter = 0;
}
SDL_FillRect( m_pScreen, 0, SDL_MapRGB( m_pScreen->format, 0, 0, 0 ) );
// Lock surface if needed
if ( SDL_MUSTLOCK( m_pScreen ) ){
if ( SDL_LockSurface( m_pScreen ) < 0 ){
return;
}
}
Render( GetSurface() );
// Render FPS
SDL_Color fpsColor = { 255, 255, 255 };
string fpsMessage = "FPS: ";
fpsMessage.append( SSTR(m_iCurrentFPS) );
SDL_Surface* fps = TTF_RenderText_Solid(font, fpsMessage.c_str(), fpsColor);
if( fps ) {
SDL_Rect destRect;
destRect.x = pDestSurface->w - fps->w;
destRect.y = pDestSurface->h - fps->h;
destRect.w = fps->w;
destRect.h = fps->h;
SDL_BlitSurface(fps, &fps->clip_rect, pDestSurface, &destRect);
SDL_FreeSurface(fps);
}
// Unlock if needed
if ( SDL_MUSTLOCK( m_pScreen ) )
SDL_UnlockSurface( m_pScreen );
// Tell SDL to update the whole gScreen
SDL_Flip( m_pScreen );
}
Image file loading
bool CEntity::VLoadImageFromFile( const string& sFile) {
if ( m_pSurface != 0 ){
SDL_FreeSurface( m_pSurface );
}
string nFile = string(OSXFileManager::APPNAME) + OSXFileManager::RESOURCEDIR + sFile;
SDL_Surface *pTempSurface;
pTempSurface = IMG_Load( nFile.c_str() );
m_sImage = sFile;
if ( pTempSurface == 0 ){
char czError[256];
sprintf( czError, "Image '%s' could not be opened. Reason: %s", nFile.c_str(), IMG_GetError() );
fprintf( stderr, "\nERROR: %s", czError );
return false;
} else {
pTempSurface = SDL_DisplayFormatAlpha(pTempSurface);
}
m_pSurface = pTempSurface;
return true;
}
Entity draw method
void CEntity::VRender( SDL_Surface *pDestSurface ) {
if ( ( m_pSurface == 0 ) || ( m_bVisible == false) || ( m_iAlpha == 0 ) ){
// If the surface is invalid or it's 100% transparent.
return;
}
SDL_Rect SDestRect;
SDestRect.x = m_iPosX;
SDestRect.y = m_iPosY;
SDestRect.w = m_pSurface->w;
SDestRect.h = m_pSurface->h;
if ( m_iAlpha != 255 )
SDL_SetAlpha( m_pSurface, SDL_SRCALPHA, m_iAlpha );
SDL_BlitSurface( m_pSurface, &m_pSurface->clip_rect, pDestSurface, &SDestRect );
}
I have checked and debugged million times and I don't get what's wrong here. As I told before, file loading seems to be OK.
But this part
void CTile::RenderGrid( SDL_Surface* pDestSurface ) {
Uint32 m_GridColor = SDL_MapRGB( pDestSurface->format, 0xFF, 0xFF, 0xFF );
Draw_Rect(pDestSurface, GetPosX(), GetPosY(), GetWidth(), GetHeight(), m_GridColor);
}
works like a charm.
I found out what was happening. Turns out that, from SDL version 1.1.18 SDL_Lock calls are recursive, so each lock must pair an unlock. That was not happening last time I used SDL, so I was not aware of it. Simply matching locks and unlocks did the job.

How do I get all the shader constants (uniforms) from a ID3DXEffect?

I'm creating an effect using
hr = D3DXCreateEffectFromFile( g_D3D_Device,
shaderPath.c_str(),
macros,
NULL,
0,
NULL,
&pEffect,
&pBufferErrors );
I would like to get all the uniforms that this shader is using. In OpenGL I used glGetActiveUniform and glGetUniformLocation to get constant's size, type, name etc. Is there a D3DX9 equivalent function?
D3DXHANDLE handle = m_pEffect->GetParameterByName( NULL, "Uniform Name" );
if ( handle != NULL )
{
D3DXPARAMETER_DESC desc;
if ( SUCCEEDED( m_pEffect->GetParameterDesc( handle, &desc ) ) )
{
// You now have pretty much all the details about the parameter there are in "desc".
}
}
You can also iterate through each parameter by doing the following:
UINT index = 0;
while( 1 )
{
D3DXHANDLE handle = m_pEffect->GetParameter( NULL, index );
if ( handle == NULL )
break;
// Get parameter desc as above.
index++;
}
Using
m_pEffect->GetParameter( NULL, index );
in while (1) cycle will result in
D3DX: ID3DXEffect::GetParameter: Invalid index
warning.
So we can use the D3DXEFFECT_DESC struct to find how many parameters an Effect has.
Something like this:
D3DXEFFECT_DESC fx_desc;
g_pEffect->GetDesc(&fx_desc);
for (UINT index=0;index<=fx_desc.Parameters;index++)
{
D3DXHANDLE handle = g_pEffect->GetParameter( NULL, index );
if ( handle == NULL )
break;
D3DXPARAMETER_DESC param_desc;
if ( S_OK == ( g_pEffect->GetParameterDesc( handle, &param_desc ) ) )
{
//check the details about the parameter in param_desc
}
}