void App::LoadTessellatedTerrain()
{
	//D3DXVECTOR3 vEye(786.1f,  -86.5f,  62.2f);
	//D3DXVECTOR3  vAt(786.3f, -130.0f, 244.1f);
	D3DXVECTOR3 vEye(18595.1f,  200.4f,  -16347.6f);
	D3DXVECTOR3  vAt(18596.1f, 200.315f, -16348.f);

	ActiveCam_->setFrom((float*)vEye);
	ActiveCam_->setTo((float*)vAt);
	ActiveCam_->setFOV(RAD2DEG(noMath::PI / 3));
	ActiveCam_->setNear(CLIP_NEAR);
	ActiveCam_->setFar(CLIP_FAR);
	ActiveCam_->SetAspect(GetAspectRatio());
	ActiveCam_->computeModelView();	
	ActiveCam_->ComputeProjection();
	
	g_ResetTerrain = true;
	ReadStars();
	
	CreateAmplifiedHeights(device);
	
	CreateShaders(device, context);
	CreateDeformEffect(device);

	// This array defines the outer width of each successive ring.
	int widths[] = { 0, 16, 16, 16, 16 };
	g_nRings = sizeof(widths) / sizeof(widths[0]) - 1;		// widths[0] doesn't define a ring hence -1
	assert(g_nRings <= MAX_RINGS);

	float tileWidth = 0.125f;
	for (int i=0; i!=g_nRings && i!=MAX_RINGS; ++i)
	{
		g_pTileRings[i] = new TileRing(device, widths[i]/2, widths[i+1], tileWidth);
		tileWidth *= 2.0f;
	}
	CreateMeshes(device, context);

	OnSizeTerrain();
}
Asteroids::Asteroids(AsteroidsSimulation* asteroids, GUI* gui, bool warp)
    : mAsteroids(asteroids)
    , mGUI(gui)
    , mSwapChain(nullptr)
    , mDevice(nullptr)
    , mDeviceCtxt(nullptr)
    , mRenderTarget(nullptr)
    , mRenderTargetView(nullptr)
    , mDepthStencilView(nullptr)
    , mDepthStencilState(nullptr)
    , mInputLayout(nullptr)
    , mIndexBuffer(nullptr)
    , mVertexBuffer(nullptr)
    , mVertexShader(nullptr)
    , mPixelShader(nullptr)
    , mDrawConstantBuffer(nullptr)
    , mSkyboxVertexShader(nullptr)
    , mSkyboxPixelShader(nullptr)
    , mSkyboxConstantBuffer(nullptr)
    , mSamplerState(nullptr)
{
    memset(&mViewPort, 0, sizeof(mViewPort));
    memset(&mScissorRect, 0, sizeof(mScissorRect));
    memset(mTextures, 0, sizeof(mTextures));
    memset(mTextureSRVs, 0, sizeof(mTextureSRVs));

    // Create device and swap chain
    {
        IDXGIAdapter*       adapter             = nullptr;
        D3D_DRIVER_TYPE     driverType          =  ( warp ) ? D3D_DRIVER_TYPE_WARP : D3D_DRIVER_TYPE_HARDWARE;
        HMODULE             swModule            = NULL;
        UINT                flags               = 0;
        D3D_FEATURE_LEVEL   featureLevels[]     = { D3D_FEATURE_LEVEL_11_0 };
        UINT                numFeatureLevels    = ARRAYSIZE(featureLevels);
        UINT                sdkVersion          = D3D11_SDK_VERSION;

#ifdef _DEBUG
        flags = flags | D3D11_CREATE_DEVICE_DEBUG;
#endif

        auto hr = D3D11CreateDevice(adapter, driverType, swModule,
            flags, featureLevels, numFeatureLevels, sdkVersion, &mDevice, nullptr, &mDeviceCtxt);
        if (FAILED(hr)) {
            // Try again without the debug flag...
            flags = flags & ~D3D11_CREATE_DEVICE_DEBUG;
            ThrowIfFailed(D3D11CreateDevice(adapter, driverType, swModule,
                flags, featureLevels, numFeatureLevels, sdkVersion, &mDevice, nullptr, &mDeviceCtxt));
        }
    }
    
    // create pipeline state
    {
        D3D11_INPUT_ELEMENT_DESC inputDesc[] = {
            { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0,  0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
            { "NORMAL",   0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
        };

        ThrowIfFailed(mDevice->CreateInputLayout(inputDesc, ARRAYSIZE(inputDesc),
            g_asteroid_vs, sizeof(g_asteroid_vs), &mInputLayout));

        {
            D3D11_DEPTH_STENCIL_DESC desc = CD3D11_DEPTH_STENCIL_DESC(D3D11_DEFAULT);
            desc.DepthFunc = D3D11_COMPARISON_GREATER_EQUAL;
            ThrowIfFailed(mDevice->CreateDepthStencilState(&desc, &mDepthStencilState));
        }
        {
            CD3D11_BLEND_DESC desc = CD3D11_BLEND_DESC(CD3D11_DEFAULT());
            ThrowIfFailed(mDevice->CreateBlendState(&desc, &mBlendState));

            // Premultiplied over blend
            desc.RenderTarget[0].BlendEnable = TRUE;
            desc.RenderTarget[0].SrcBlend    = D3D11_BLEND_ONE;
            desc.RenderTarget[0].BlendOp     = D3D11_BLEND_OP_ADD;
            desc.RenderTarget[0].DestBlend   = D3D11_BLEND_INV_SRC_ALPHA;
            ThrowIfFailed(mDevice->CreateBlendState(&desc, &mSpriteBlendState));
        }
        
        ThrowIfFailed(mDevice->CreateVertexShader(g_asteroid_vs, sizeof(g_asteroid_vs), NULL, &mVertexShader));
        ThrowIfFailed(mDevice->CreatePixelShader(g_asteroid_ps_d3d11, sizeof(g_asteroid_ps_d3d11), NULL, &mPixelShader));
    }
    // create skybox pipeline state
    {
        D3D11_INPUT_ELEMENT_DESC inputDesc[] = {
            { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0,  0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
            { "UVFACE",   0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
        };

        ThrowIfFailed(mDevice->CreateInputLayout(inputDesc, ARRAYSIZE(inputDesc),
            g_skybox_vs, sizeof(g_skybox_vs), &mSkyboxInputLayout));

        ThrowIfFailed(mDevice->CreateVertexShader(g_skybox_vs, sizeof(g_skybox_vs), NULL, &mSkyboxVertexShader));
        ThrowIfFailed(mDevice->CreatePixelShader(g_skybox_ps, sizeof(g_skybox_ps), NULL, &mSkyboxPixelShader));
    }

    // Sprites and fonts
    {
        D3D11_INPUT_ELEMENT_DESC inputDesc[] = {
            { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0,  0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
            { "UV",       0, DXGI_FORMAT_R32G32_FLOAT, 0,  8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
        };

        ThrowIfFailed(mDevice->CreateInputLayout(inputDesc, ARRAYSIZE(inputDesc),
            g_sprite_vs, sizeof(g_sprite_vs), &mSpriteInputLayout));

        ThrowIfFailed(mDevice->CreateVertexShader(g_sprite_vs, sizeof(g_sprite_vs), NULL, &mSpriteVertexShader));
        ThrowIfFailed(mDevice->CreatePixelShader(g_sprite_ps, sizeof(g_sprite_ps), NULL, &mSpritePixelShader));
        ThrowIfFailed(mDevice->CreatePixelShader(g_font_ps, sizeof(g_font_ps), NULL, &mFontPixelShader));
    }
    
    // Create draw constant buffer
    {
        D3D11_BUFFER_DESC desc = {};
        desc.Usage = D3D11_USAGE_DYNAMIC;
        desc.ByteWidth = sizeof(DrawConstantBuffer);
        desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
        desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
        ThrowIfFailed(mDevice->CreateBuffer(&desc, nullptr, &mDrawConstantBuffer));
    }
    // Create skybox constant buffer
    {
        D3D11_BUFFER_DESC desc = {};
        desc.Usage = D3D11_USAGE_DYNAMIC;
        desc.ByteWidth = sizeof(SkyboxConstantBuffer);
        desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
        desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
        ThrowIfFailed(mDevice->CreateBuffer(&desc, nullptr, &mSkyboxConstantBuffer));
    }

    // Create sampler
    {
        D3D11_SAMPLER_DESC desc = {};
        desc.Filter         = D3D11_FILTER_ANISOTROPIC;
        desc.AddressU       = D3D11_TEXTURE_ADDRESS_WRAP;
        desc.AddressV       = D3D11_TEXTURE_ADDRESS_WRAP;
        desc.AddressW       = D3D11_TEXTURE_ADDRESS_WRAP;
        desc.MinLOD         = -D3D11_FLOAT32_MAX;
        desc.MaxLOD         = D3D11_FLOAT32_MAX;
        desc.MipLODBias     = 0.0f;
        desc.MaxAnisotropy  = TEXTURE_ANISO;
        desc.ComparisonFunc = D3D11_COMPARISON_NEVER;
        ThrowIfFailed(mDevice->CreateSamplerState(&desc, &mSamplerState));
    }

    CreateMeshes();
    InitializeTextureData();
    CreateGUIResources();

    // Load textures
    ThrowIfFailed(CreateDDSTextureFromFile(mDevice, L"starbox_1024.dds", &mSkyboxSRV, true));
}