//******************************************************************************
//
// OpenGL Utility / OGLRenderer
//
// レンダラクラス
//
// Copyright (C) 2010-2019 WADA Masashi. All Rights Reserved.
//
//******************************************************************************

#include "YNBaseLib.h"
#include "OGLRenderer.h"
#include <new>


//******************************************************************************
// コンストラクタ
//******************************************************************************
OGLRenderer::OGLRenderer()
{
	m_pOGLDevice = NULL;
	m_pView = NULL;
}

//******************************************************************************
// デストラクタ
//******************************************************************************
OGLRenderer::~OGLRenderer()
{
	Terminate();
}

//******************************************************************************
// 初期化
//******************************************************************************
int OGLRenderer::Initialize(
		UIView* pView,
		OGLRedererParam rendererParam
	)
{
	int result = 0;
	CGRect baseRect;
	OGLVIEWPORT viewPort;
	
	m_pView = pView;
	
	//ディスプレイデバイス作成（ダミー）
	try {
		m_pOGLDevice = new OGLDevice();
	}
	catch (std::bad_alloc) {
		result = YN_SET_ERR(@"Could not allocate memory.", 0, 0);
		goto EXIT;
	}
	
	//ディスプレイデバイス初期化
	result = m_pOGLDevice->Initialize();
	if (result != 0) goto EXIT;
	
	//ビューポート情報作成
	baseRect = m_pView.frame;
	baseRect.origin = CGPointZero;	
	viewPort.originx = baseRect.origin.x;
	viewPort.originy = baseRect.origin.y;
	viewPort.width   = baseRect.size.width;
	viewPort.height  = baseRect.size.height;
	m_pOGLDevice->SetViewPort(viewPort);
	
	//アンチエイリアス有効化
	//  ハードウェアによって無視される場合があるため気休め程度の設定である
	//  アンチエイリアスの有効化はNSView生成時に指定するピクセルフォーマットで確定するようだ
	if (rendererParam.isEnableAntialiasing) {
		glEnable(GL_MULTISAMPLE);
	}
	
EXIT:;
	return result;
}

//******************************************************************************
// デバイス取得
//******************************************************************************
OGLDevice* OGLRenderer::GetDevice()
{
	return m_pOGLDevice;
}

//*****************************************************************************
// シーン描画
//******************************************************************************
int OGLRenderer::RenderScene(
		OGLScene* pScene,
		bool isVRViewDualLens
	)
{
	int result = 0;
	CGRect baseRect;
	OGLVIEWPORT viewPort;
	
	//バッファ初期化色の指定：RGBA
	glClearColor(0.0, 0.0, 0.0, 0.0);
	
	//バッファクリア：色バッファ＋深度バッファ
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	
	baseRect = m_pView.frame;
	baseRect.origin = CGPointZero;
	
	//描画
	if (pScene != NULL) {
		
		//VRビュー
		if (isVRViewDualLens) {
			//左目用の描画
			viewPort.originx = baseRect.origin.x;
			viewPort.originy = baseRect.origin.y;
			viewPort.width   = baseRect.size.width / 2;
			viewPort.height  = baseRect.size.height;
			m_pOGLDevice->SetViewPort(viewPort);
			result = pScene->Draw(m_pOGLDevice, OGLScene::CameraLeftEye);
			if (result != 0) {
				//失敗しても描画定型処理を続行する
				YN_SHOW_ERR();
			}
			//右目用の描画
			viewPort.originx = baseRect.origin.x + (baseRect.size.width / 2);
			viewPort.originy = baseRect.origin.y;
			viewPort.width   = baseRect.size.width / 2;
			viewPort.height  = baseRect.size.height;
			m_pOGLDevice->SetViewPort(viewPort);
			result = pScene->Draw(m_pOGLDevice, OGLScene::CameraRightEye);
			if (result != 0) {
				//失敗しても描画定型処理を続行する
				YN_SHOW_ERR();
			}
		}
		//通常ビュー
		else {
			viewPort.originx = baseRect.origin.x;
			viewPort.originy = baseRect.origin.y;
			viewPort.width   = baseRect.size.width;
			viewPort.height  = baseRect.size.height;
			m_pOGLDevice->SetViewPort(viewPort);
			result = pScene->Draw(m_pOGLDevice, OGLScene::CameraNormal);
			if (result != 0) {
				//失敗しても描画定型処理を続行する
				YN_SHOW_ERR();
			}
		}
	}
	
	//描画処理終了
	//  キューに残っている全てのOpenGLコマンドをハードウェアに送信して制御を戻す
	//  コマンド実行完了まで待機したければglFinishを使う
	glFlush();
	
EXIT:;
	return result;
}

//*****************************************************************************
// 終了処理
//******************************************************************************
void OGLRenderer::Terminate()
{
	if (m_pOGLDevice != NULL) {
		m_pOGLDevice->Release();
		m_pOGLDevice = NULL;
	}
}


