C++/Directx 11 Rotacja ściany wokół osi OX.

0

Mam pewne wyzwanie, otóż chcę sprawić aby jedna ściana kręciła się wokół swojej osi OX. Obecnie kręci się jedna ściana sześcianu wokół osi OX wspomnianego sześcianu... Co powinienem zmienić w kodzie poniżej?

	static RECT client;
	static double angle0 = 0.0, angle1 = 0.0, angle2 = 0.0;
	static long key1, key2;
	key1 = GetAsyncKeyState(VK_LEFT);
	key2 = GetAsyncKeyState(VK_RIGHT);
	static long move = 1;
	
	static XMMATRIX wvMatrix, vMatrix, wvpMatrix;

	switch (uMsg)
	{
	case WM_CREATE:
		GetClientRect(hwnd, &client);
		
		scDesc.BufferDesc.Width = client.right - client.left;
		scDesc.BufferDesc.Height = client.bottom - client.top;
		scDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
		scDesc.BufferDesc.RefreshRate.Numerator = 120;
		scDesc.BufferDesc.RefreshRate.Denominator = 1;
		scDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
		scDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
		scDesc.SampleDesc.Count = 1;
		scDesc.SampleDesc.Quality = 0;
		scDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
		scDesc.BufferCount = 1;
		scDesc.OutputWindow = hwnd;
		scDesc.Windowed = true;
		scDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
		scDesc.Flags = 0;

		hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, D3D11_CREATE_DEVICE_SINGLETHREADED, NULL, 0, D3D11_SDK_VERSION, &scDesc, &pSwapChain, &pD3D11Device, &d3dFeatureLevel, &pD3D11DeviceContext);

		if (hr != S_OK)
			MessageBox(NULL, "Nie udalo sie wywolac funkcji D3D11CreateDeviceAndSwapChain!", APPNAME, MB_ICONERROR);
		else
			hr = pSwapChain->GetBuffer(0, __uuidof(pBackBuffer), reinterpret_cast<void**>(&pBackBuffer));

		if (hr != S_OK)
			MessageBox(NULL, "Nie udalo sie wywolac metody IDXGISwapChain::GetBuffer!", APPNAME, MB_ICONERROR);
		else
			hr = pD3D11Device->CreateRenderTargetView(pBackBuffer, NULL, &pRenderTargetView);

		if (hr != S_OK)
			MessageBox(NULL, "Nie udalo sie wywolac metody ID3D11Device::CreateRenderTargetView!", APPNAME, MB_ICONERROR);
		else
		{
			vbDesc.ByteWidth = sizeof(vertices);
			vbDesc.Usage = D3D11_USAGE_DEFAULT;
			vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
			vbDesc.CPUAccessFlags = 0;
			vbDesc.MiscFlags = 0;
			vbDesc.StructureByteStride = 0;
			vbInit.pSysMem = vertices;
			vbInit.SysMemPitch = 0;
			vbInit.SysMemSlicePitch = 0;
			pD3D11Device->CreateBuffer(&vbDesc, &vbInit, &pVertexBuffer);

			ieDesc[0].SemanticName = "POSITION";
			ieDesc[0].SemanticIndex = 0;
			ieDesc[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
			ieDesc[0].InputSlot = 0;
			ieDesc[0].AlignedByteOffset = 0;
			ieDesc[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
			ieDesc[0].InstanceDataStepRate = 0;
			ieDesc[1].SemanticName = "NORMAL";
			ieDesc[1].SemanticIndex = 0;
			ieDesc[1].Format = DXGI_FORMAT_R32G32B32_FLOAT;
			ieDesc[1].InputSlot = 0;
			ieDesc[1].AlignedByteOffset = 12;
			ieDesc[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
			ieDesc[1].InstanceDataStepRate = 0;
			pD3D11Device->CreateInputLayout(ieDesc, 2, g_vs_main, sizeof(g_vs_main), &pInputLayout);

		        pD3D11Device->CreateVertexShader(g_vs_main, sizeof(g_vs_main), NULL, &pVertexShader);

			pD3D11Device->CreatePixelShader(g_ps_main, sizeof(g_ps_main), NULL, &pPixelShader);

			sViewport.Width = static_cast<float>(client.right - client.left);
			sViewport.Height = static_cast<float>(client.bottom - client.top);
			sViewport.TopLeftX = 0.0f;
			sViewport.TopLeftY = 0.0f;
			sViewport.MinDepth = 0.0f;
			sViewport.MaxDepth = 1.0f;

			sRastDesc.FillMode = D3D11_FILL_SOLID;
			sRastDesc.CullMode = D3D11_CULL_NONE;
			sRastDesc.FrontCounterClockwise = false;
			sRastDesc.DepthBias = 0;
			sRastDesc.DepthBiasClamp = 0.0f;
			sRastDesc.SlopeScaledDepthBias = 0.0f;
			sRastDesc.DepthClipEnable = true;
			sRastDesc.ScissorEnable = false;
			sRastDesc.MultisampleEnable = false;
			sRastDesc.AntialiasedLineEnable = false;
			pD3D11Device->CreateRasterizerState(&sRastDesc, &pRasterState);

			sDSDesc.Width = client.right - client.left;
			sDSDesc.Height = client.bottom - client.top;
			sDSDesc.MipLevels = 1;
			sDSDesc.ArraySize = 1;
			sDSDesc.Format = DXGI_FORMAT_D32_FLOAT;
			sDSDesc.SampleDesc.Count = 1;
			sDSDesc.SampleDesc.Quality = 0;
			sDSDesc.Usage = D3D11_USAGE_DEFAULT;
			sDSDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
			sDSDesc.CPUAccessFlags = 0;
			sDSDesc.MiscFlags = 0;
			pD3D11Device->CreateTexture2D(&sDSDesc, 0, &pDSBuffer);
			pD3D11Device->CreateDepthStencilView(pDSBuffer, NULL, &pDSView);

			sVSCBufferConst.colLight = XMFLOAT4(lightColor);
			sVSCBufferConst.dirLight = XMFLOAT4(lightDir);
			cbDesc.ByteWidth = sizeof(VS_CONSTANT_BUFFER_CONST);
			cbDesc.Usage = D3D11_USAGE_IMMUTABLE;
			cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
			cbDesc.CPUAccessFlags = 0;
			cbDesc.MiscFlags = 0;
			cbDesc.StructureByteStride = 0;
			cbInit.pSysMem = &sVSCBufferConst;
			cbInit.SysMemPitch = 0;
			cbInit.SysMemSlicePitch = 0;
			pD3D11Device->CreateBuffer(&cbDesc, &cbInit, &pVSCBuffers[0]);
			// - Var
			XMStoreFloat4x4(&sVSCBufferVar.matWorldView, XMMatrixIdentity());
			XMStoreFloat4x4(&sVSCBufferVar.matView, XMMatrixIdentity());
			XMStoreFloat4x4(&sVSCBufferVar.matWorldViewProj, XMMatrixIdentity());
			sVSCBufferVar.colMaterial = XMFLOAT4(materialColor);
			cbDesc.ByteWidth = sizeof(VS_CONSTANT_BUFFER_VAR);
			cbDesc.Usage = D3D11_USAGE_DYNAMIC;
			cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
			cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
			cbDesc.MiscFlags = 0;
			cbDesc.StructureByteStride = 0;
			cbInit.pSysMem = &sVSCBufferVar;
			cbInit.SysMemPitch = 0;
			cbInit.SysMemSlicePitch = 0;
			pD3D11Device->CreateBuffer(&cbDesc, &cbInit, &pVSCBuffers[1]);

			pD3D11DeviceContext->IASetVertexBuffers(0, 1, &pVertexBuffer, &stride, &offset);
			pD3D11DeviceContext->IASetInputLayout(pInputLayout);
			pD3D11DeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
			pD3D11DeviceContext->VSSetShader(pVertexShader, NULL, 0);
			pD3D11DeviceContext->VSSetConstantBuffers(0, 2, pVSCBuffers);
			pD3D11DeviceContext->RSSetViewports(1, &sViewport);
			pD3D11DeviceContext->RSSetState(pRasterState);
			pD3D11DeviceContext->PSSetShader(pPixelShader, NULL, 0);
			pD3D11DeviceContext->OMSetRenderTargets(1, &pRenderTargetView, pDSView);
		}
		SetTimer(hwnd, 1001, 16, NULL);
		return 0;

			case WM_TIMER:
				if(key1<0)
					move -= 1;
				if (key2<0)
					move += 1;
								
				if (move<0)
					angle0 += 0.05;

				if (move > 0 && move < 20)
					angle1 += 0.05;

				if (move > 20)
					angle2 += 0.05;
				
				InvalidateRect(hwnd, NULL, false);
				return 0;

	case WM_PAINT:
			pD3D11DeviceContext->ClearRenderTargetView(pRenderTargetView, backgroundColor);
			pD3D11DeviceContext->ClearDepthStencilView(pDSView, D3D11_CLEAR_DEPTH, 1.0f, 0);
				
				GetClientRect(hwnd, &client);
				
				//wvpMatrix = XMMatrixRotationY(2.5*angle/2);
				wvpMatrix = XMMatrixRotationX(2.5*angle1 / 2);
				wvMatrix = XMMatrixTranspose(wvpMatrix);
				vMatrix = XMMatrixTranslation(0.0f, 0.0f, 15.0f);
				wvpMatrix = XMMatrixMultiply(wvpMatrix, vMatrix);
				wvpMatrix = XMMatrixMultiply(wvpMatrix, XMMatrixPerspectiveFovLH(1.0f, static_cast<float>(client.right - client.left) / (client.bottom - client.top), 1.0f, 25.0f));
				wvpMatrix = XMMatrixTranspose(wvpMatrix);
				vMatrix = XMMatrixTranspose(vMatrix);

				pD3D11DeviceContext->Map(pVSCBuffers[1], 0, D3D11_MAP_WRITE_DISCARD, 0, &sMappedResource);
				pCBuffer = reinterpret_cast<VS_CONSTANT_BUFFER_VAR *>(sMappedResource.pData);
				XMStoreFloat4x4(&(pCBuffer->matWorldView), wvMatrix);
				XMStoreFloat4x4(&(pCBuffer->matView), vMatrix);
				XMStoreFloat4x4(&(pCBuffer->matWorldViewProj), wvpMatrix);
				pCBuffer->colMaterial = XMFLOAT4(materialColor1);
				pD3D11DeviceContext->Unmap(pVSCBuffers[1], 0);

				pD3D11DeviceContext->Draw(24, 0);

			pSwapChain->Present(0, 0);

			GetClientRect(hwnd, &client);

			//wvpMatrix = XMMatrixRotationY(2.5*angle/2);
			wvpMatrix = XMMatrixRotationX(2.5*angle2 / 2);
			wvMatrix = XMMatrixTranspose(wvpMatrix);
			vMatrix = XMMatrixTranslation(7.0f, 0.0f, 15.0f);
			wvpMatrix = XMMatrixMultiply(wvpMatrix, vMatrix);
			wvpMatrix = XMMatrixMultiply(wvpMatrix, XMMatrixPerspectiveFovLH(1.0f, static_cast<float>(client.right - client.left) / (client.bottom - client.top), 1.0f, 25.0f));
			wvpMatrix = XMMatrixTranspose(wvpMatrix);
			vMatrix = XMMatrixTranspose(vMatrix);

			pD3D11DeviceContext->Map(pVSCBuffers[1], 0, D3D11_MAP_WRITE_DISCARD, 0, &sMappedResource);
			pCBuffer = reinterpret_cast<VS_CONSTANT_BUFFER_VAR *>(sMappedResource.pData);
			XMStoreFloat4x4(&(pCBuffer->matWorldView), wvMatrix);
			XMStoreFloat4x4(&(pCBuffer->matView), vMatrix);
			XMStoreFloat4x4(&(pCBuffer->matWorldViewProj), wvpMatrix);
			pCBuffer->colMaterial = XMFLOAT4(materialColor2);
			pD3D11DeviceContext->Unmap(pVSCBuffers[1], 0);

			pD3D11DeviceContext->Draw(24, 0);
			pSwapChain->Present(0, 0);

			GetClientRect(hwnd, &client);

			//wvpMatrix = XMMatrixRotationY(2.5*angle/2);
			wvpMatrix = XMMatrixRotationX(2.5*angle0 / 2);
			wvMatrix = XMMatrixTranspose(wvpMatrix);
			vMatrix = XMMatrixTranslation(-7.0f, 0.0f, 15.0f);
			wvpMatrix = XMMatrixMultiply(wvpMatrix, vMatrix);
			wvpMatrix = XMMatrixMultiply(wvpMatrix, XMMatrixPerspectiveFovLH(1.0f, static_cast<float>(client.right - client.left) / (client.bottom - client.top), 1.0f, 25.0f));
			wvpMatrix = XMMatrixTranspose(wvpMatrix);
			vMatrix = XMMatrixTranspose(vMatrix);

			pD3D11DeviceContext->Map(pVSCBuffers[1], 0, D3D11_MAP_WRITE_DISCARD, 0, &sMappedResource);
			pCBuffer = reinterpret_cast<VS_CONSTANT_BUFFER_VAR *>(sMappedResource.pData);
			XMStoreFloat4x4(&(pCBuffer->matWorldView), wvMatrix);
			XMStoreFloat4x4(&(pCBuffer->matView), vMatrix);
			XMStoreFloat4x4(&(pCBuffer->matWorldViewProj), wvpMatrix);
			pCBuffer->colMaterial = XMFLOAT4(materialColor0);
			pD3D11DeviceContext->Unmap(pVSCBuffers[1], 0);

			pD3D11DeviceContext->Draw(24, 0);
			pSwapChain->Present(0, 0);

		ValidateRect(hwnd, NULL);
		return 0;

	case WM_DESTROY:
		KillTimer(hwnd, 1001);
		if (pRasterState) pRasterState->Release();
		if (pDSBuffer) pDSBuffer->Release();
		if (pDSView) pDSView->Release();
		if (pVSCBuffers[0]) pVSCBuffers[0]->Release();
		if (pVSCBuffers[1]) pVSCBuffers[1]->Release();
		if (pVertexBuffer) pVertexBuffer->Release();
		if (pInputLayout) pInputLayout->Release();
		if (pVertexShader) pVertexShader->Release();
		if (pPixelShader) pPixelShader->Release();
		if (pRenderTargetView) pRenderTargetView->Release();
		if (pSwapChain) pSwapChain->Release();
		if (pD3D11DeviceContext) pD3D11DeviceContext->Release();
		if (pD3D11Device) pD3D11Device->Release();

		PostQuitMessage(0);
		return 0;
	}
	return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

1

To jest kod klasy takiej, że ten kto go nie pisał będzie musiał spędzić tydzień aby w nim się połapać.

Musisz manipulować macierzą przekształceń dla tego boku, nie wiem czy to dobre podejście tutaj, ale w wypadku gdy oś obrotu jest położona poza środkiem obiektu a chcesz by przechodziła przez środek obiektu to musisz przestawić obiekt do położenia przez które przechodzi oś obrotu, obrócić obiekt, na końcu obiekt ponownie przestawić na miejsce.

A może masz tak że najpierw obracasz bok potem przesuwasz? W tym wypadku obiekt będzie się obracał wokół osi przechodzącej przez punkt przed przesunięciem, czyli najpierw trzeba obrócić potem przestawić, o ile dx mnoży macierze według kanonu, a ponieważ ma lewoskrętny układ współrzędnych to pewien nie jestem.

1 użytkowników online, w tym zalogowanych: 0, gości: 1