2019년 6월 14일 금요일

윈도우 동영상 재생

#include <new>
#include <windows.h>
#include <windowsx.h>
#include <mfplay.h>
#include <mferror.h>
#include <shobjidl.h>   // defines IFileOpenDialog
#include <strsafe.h>
#include <Shlwapi.h>

#include <ctime>
#include "ELApplication.h"
#include "basic/ELAutoReleasePool.h"
#include "app_control/ELDirector.h"
#include "app_control/ELOpenGLView.h"


NS_BEGIN(elloop);

#pragma comment(lib,"Mfplay.lib")





Application* Application::_instance = nullptr;



// Implements the callback interface for MFPlay events.

class MediaPlayerCallback : public IMFPMediaPlayerCallback
{
long m_cRef; // Reference count

public:

MediaPlayerCallback() : m_cRef(1)
{
}

IFACEMETHODIMP QueryInterface(REFIID riid, void** ppv)
{
static const QITAB qit[] =
{
QITABENT(MediaPlayerCallback, IMFPMediaPlayerCallback),
{ 0 },
};
return QISearch(this, qit, riid, ppv);
}

IFACEMETHODIMP_(ULONG) AddRef()
{
return InterlockedIncrement(&m_cRef);
}

IFACEMETHODIMP_(ULONG) Release()
{
ULONG count = InterlockedDecrement(&m_cRef);
if (count == 0)
{
delete this;
return 0;
}
return count;
}

// IMFPMediaPlayerCallback methods
IFACEMETHODIMP_(void) OnMediaPlayerEvent(MFP_EVENT_HEADER *pEventHeader);
};


IMFPMediaPlayer         *g_pPlayer = NULL;      // The MFPlay player object.
MediaPlayerCallback     *g_pPlayerCB = NULL;    // Application callback object.

BOOL                    g_bHasVideo = FALSE;


template <class T> void SafeRelease(T **ppT)
{
if (*ppT)
{
(*ppT)->Release();
*ppT = NULL;
}
}


void OnMediaItemCreated(MFP_MEDIAITEM_CREATED_EVENT *pEvent)
{
// The media item was created successfully.

if (g_pPlayer)
{
BOOL    bHasVideo = FALSE;
BOOL    bIsSelected = FALSE;

// Check if the media item contains video.
HRESULT hr = pEvent->pMediaItem->HasVideo(&bHasVideo, &bIsSelected);
if (SUCCEEDED(hr))
{
g_bHasVideo = bHasVideo && bIsSelected;

// Set the media item on the player. This method completes
// asynchronously.
hr = g_pPlayer->SetMediaItem(pEvent->pMediaItem);
}

if (FAILED(hr))
{

MessageBox(NULL, L"", L"Error playing this file.", 0);
//ShowErrorMessage(L"Error playing this file.", hr);
}
}
}

void OnMediaItemSet(MFP_MEDIAITEM_SET_EVENT * /*pEvent*/)
{
HRESULT hr = g_pPlayer->Play();
if (FAILED(hr))
{
MessageBox(NULL, L"", L"IMFPMediaPlayer::Play failed.", 0);
//ShowErrorMessage(L"IMFPMediaPlayer::Play failed.", hr);
}
}


void MediaPlayerCallback::OnMediaPlayerEvent(MFP_EVENT_HEADER * pEventHeader)
{
if (FAILED(pEventHeader->hrEvent))
{
MessageBox(NULL, L"", L"Playback error", 0);
//ShowErrorMessage(L"Playback error", pEventHeader->hrEvent);

return;
}

switch (pEventHeader->eEventType)
{
case MFP_EVENT_TYPE_MEDIAITEM_CREATED:
OnMediaItemCreated(MFP_GET_MEDIAITEM_CREATED_EVENT(pEventHeader));
break;

case MFP_EVENT_TYPE_MEDIAITEM_SET:
OnMediaItemSet(MFP_GET_MEDIAITEM_SET_EVENT(pEventHeader));
break;
}
}



bool Application::init()
{

    auto director = Director::getInstance();
    auto glView = director->getGLView();
    if (!glView)
    {
        auto view = OpenGLView::create(_hInstance, _T("OpenGL ES 2.0"));
        assert(view);
        view->setWindowEventListener(this);
        director->setGLView(view);



    }
    return true;
}

int Application::run()
{

auto director = Director::getInstance();



    if (!applicationDidFinishLaunching())
    {
        return -1;
    }



    if (!director->getGLView())
    {
        return -1;
    }

   director->getGLView()->show();
 


    MSG msg = { 0 };

    while (msg.message != WM_QUIT)
    {
        if (WM_CLOSE == msg.message || WM_DESTROY == msg.message)
        {
            break;
        }
        if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
        {
            // clean autorelease objects.
            PoolManager::getInstance()->recycle();

director->mainLoop();           
        }
    }

    director->end();
    PoolManager::getInstance()->purge();

    return 0;
}

Application::Application() :
_hInstance(nullptr)
{
    _hInstance = GetModuleHandle(nullptr);
    init();
    _instance = this;
}

HRESULT PlayMediaFile(HWND hwnd, PCWSTR pszURL)
{
HRESULT hr = S_OK;

// Create the MFPlayer object.
if (g_pPlayer == NULL)
{
g_pPlayerCB = new (std::nothrow) MediaPlayerCallback();

if (g_pPlayerCB == NULL)
{
return E_OUTOFMEMORY;
}

hr = MFPCreateMediaPlayer(
NULL,
FALSE,          // Start playback automatically?
0,              // Flags
g_pPlayerCB,    // Callback pointer
hwnd,           // Video window
&g_pPlayer
);
}

// Create a new media item for this URL.

if (SUCCEEDED(hr))
{
hr = g_pPlayer->CreateMediaItemFromURL(pszURL, FALSE, 0, NULL);
}

// The CreateMediaItemFromURL method completes asynchronously.
// The application will receive an MFP_EVENT_TYPE_MEDIAITEM_CREATED
// event. See MediaPlayerCallback::OnMediaPlayerEvent().

return hr;
}


void OnFileOpen(HWND hwnd)
{
IFileOpenDialog *pFileOpen = NULL;
IShellItem *pItem = NULL;
PWSTR pwszFilePath = NULL;

// Create the FileOpenDialog object.
HRESULT hr = CoCreateInstance(__uuidof(FileOpenDialog), NULL,
CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pFileOpen));
if (SUCCEEDED(hr))
{
hr = pFileOpen->SetTitle(L"Select a File to Play");
}

// Show the file-open dialog.
if (SUCCEEDED(hr))
{
hr = pFileOpen->Show(hwnd);
}

if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED))
{
// User canceled.
SafeRelease(&pFileOpen);
return;
}

// Get the file name from the dialog.
if (SUCCEEDED(hr))
{
hr = pFileOpen->GetResult(&pItem);
}

if (SUCCEEDED(hr))
{
hr = pItem->GetDisplayName(SIGDN_URL, &pwszFilePath);
}

// Open the media file.
if (SUCCEEDED(hr))
{
hr = PlayMediaFile(hwnd, pwszFilePath);
}

if (FAILED(hr))
{
MessageBox(hwnd,L"", L"Could not open file.", 0);
}

CoTaskMemFree(pwszFilePath);
SafeRelease(&pItem);
SafeRelease(&pFileOpen);
}

LRESULT Application::onEvent(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
        case WM_CREATE:
            MessageBox(nullptr, _T("hello"), _T("title"), 0);
            break;
case WM_LBUTTONUP:
{
OnFileOpen(hWnd);
break;
}
case WM_RBUTTONUP:
{
break;
}
case WM_PAINT:
{
/*
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);

if (g_pPlayer && g_bHasVideo)
{
// Playback has started and there is video.

// Do not draw the window background, because the video
// frame fills the entire client area.

g_pPlayer->UpdateVideo();
}
else
{
// There is no video stream, or playback has not started.
// Paint the entire client area.
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
}

EndPaint(hWnd, &ps);
*/


break;
}
case WM_SIZE:
{
//if (state == SIZE_RESTORED)
{
if (g_pPlayer)
{
// Resize the video.
g_pPlayer->UpdateVideo();
}
}

break;
}
        case WM_CLOSE:
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hWnd, msg, wParam, lParam);
            break;
    }
    return S_OK;
}

Application* Application::getInstance()
{
    return _instance;
}

NS_END(elloop);

2019년 3월 12일 화요일

발사체 코드



namespace physics
{
typedef CELL::float3 vec3;
typedef CELL::matrix4 mat4;

class force
{
private:

vec3 forceVector;
vec3 forceLocation;

public:

force() : forceVector(vec3(0,0,0)), forceLocation(vec3(0, 0, 0)) {}

void Force(const vec3& theForce) { forceVector = theForce; }
vec3& Force() { return forceVector; }

void ApplicationPoint(const vec3& forceApplicationPoint) { forceLocation = forceApplicationPoint; }
vec3& ApplicationPoint() { return forceLocation; }
};


class CPhysicsObject
{
private:
// 월드 좌표
mat4 worldMatrix;

// 물리적 속성과 선형 운동 속성
float mass;

vec3 centerOfMassLocation;
vec3 linearVelocity;
vec3 linearAcceleration;

force constantForce; // 지속력
force impulseForce; // 충격력

public:

const mat4& WorldMatrix() { return worldMatrix;}

void Mass(float _mass) { mass = _mass; }
float Mass() { return mass; }

void Location(const vec3& locationCenterOfMass) {
centerOfMassLocation = locationCenterOfMass ;
worldMatrix.translate(centerOfMassLocation.x, centerOfMassLocation.y, centerOfMassLocation.z);}

const vec3& Location() { return centerOfMassLocation; }

void LinearVelocity(const vec3& newVelocity) { linearVelocity = newVelocity; }
const vec3& LinearVelocity() { return linearVelocity; }

void LinearAcceleration(const vec3& newAcceleration) { linearAcceleration = newAcceleration; }
const vec3& LinearAcceleration() { return linearAcceleration; }

void ConstantForce(const force& sumOfConstantForces) { constantForce = sumOfConstantForces; };
force& ConstantForce() { return constantForce; }

void ImpulseForce(const force& sumImpulseForces) { impulseForce = sumImpulseForces; };
force& ImpulseForce() { return impulseForce; }

void Update(float changeInTime)
{
force sumForces;

sumForces.Force(constantForce.Force() + impulseForce.Force());

assert(mass != 0);

// 선형 가속도를 구한다.
linearAcceleration = sumForces.Force() / mass;

// 선형 속도를 구한다.
linearVelocity += linearAcceleration * changeInTime;

// 무게 중심의 새로운 위치를 구한다.
centerOfMassLocation += linearVelocity * changeInTime;

// 평행 이동 행렬을 생성한다.
worldMatrix.translate(centerOfMassLocation.x, centerOfMassLocation.y, centerOfMassLocation.z);

// 0으로 리셋
impulseForce.Force(vec3(0, 0, 0));
impulseForce.ApplicationPoint(vec3(0, 0, 0));
}
};


class CPhysicsObjectController
{
std::vector<CPhysicsObject> list;

public:

vec3 GetRandomFireForce()
{
vec3 frontVec = vec3(.0f, .0f, 1.0f);
mat4 mat;

mat.identify();
mat.rotateX(-45);
frontVec = frontVec * mat;

mat.identify();
mat.rotateY(rand() % 180);
frontVec = frontVec * mat;

mat.identify();
mat.scale(rand() % 360);
frontVec = frontVec * mat;

return frontVec;
}

void Fire()
{
vec3 tmp = vec3(0.0f, 5.0f, 0.0f);

CPhysicsObject p;
p.Mass(1.0f);
p.Location(tmp);

force theForce;
theForce.Force(vec3(0.0f, -9.8f, 0.0f));
theForce.ApplicationPoint(tmp);
p.ConstantForce(theForce);

for (int i = 0; i < 10; i++)
{
theForce.Force(GetRandomFireForce());
theForce.ApplicationPoint(vec3(0.0f, 0.0f, 0.0f));

p.ImpulseForce(theForce);
p.LinearVelocity(tmp);
p.LinearAcceleration(tmp);

list.push_back(p);
}
}

std::vector<CPhysicsObject>& get() { return list; }

void Update(float changeInTime)
{
for (auto itr = list.begin(); itr != list.end(); ++itr)
{
itr->Update(changeInTime);
}
}
};
};