我在使用 DirectX 在打开的窗口中显示模型时遇到问题。
这是我的代码:
struct MatrixBufferType
{
XMMATRIX worldViewProjection;
};
// Definition der ConstantBuffer-Klasse
template <typename T>
class ConstantBuffer
{
private:
Microsoft::WRL::ComPtr<ID3D11Buffer> buffer;
public:
T data;
ConstantBuffer() : buffer(nullptr), data()
{
}
// Constructor with device pointer
ConstantBuffer(ID3D11Device* device) : buffer(nullptr), data()
{
// Create the buffer
D3D11_BUFFER_DESC bufferDesc = { sizeof(T), D3D11_USAGE_DEFAULT, D3D11_BIND_CONSTANT_BUFFER, 0, 0, 0 };
device->CreateBuffer(&bufferDesc, nullptr, buffer.GetAddressOf());
}
void ApplyChanges(ID3D11DeviceContext* context)
{
// Kopiere die Daten in den Puffer
context->UpdateSubresource(buffer.Get(), 0, nullptr, &data, 0, 0);
}
void SetVSBuffer(ID3D11DeviceContext* context, UINT slot)
{
// Setze den Puffer im Vertex-Shader
context->VSSetConstantBuffers(slot, 1, buffer.GetAddressOf());
}
};
// Definiere notwendige Datenstrukturen für das Modell
struct Vertex {
DirectX::XMFLOAT3 Position;
Vertex(float x = 0.0f, float y = 0.0f, float z = 0.0f)
: Position(x, y, z) {}
};
struct Model
{
std::vector<Vertex> vertices;
std::vector<unsigned int> indices;
ID3D11Buffer* vertexBuffer = nullptr;
ID3D11Buffer* indexBuffer = nullptr;
};
// Function to create a vertex buffer from vertex data
bool CreateVertexBuffer(ID3D11Device* device, const std::vector<Vertex>& vertices, ID3D11Buffer*& vertexBuffer)
{
D3D11_BUFFER_DESC desc;
ZeroMemory(&desc, sizeof(desc));
desc.Usage = D3D11_USAGE_DEFAULT;
desc.ByteWidth = sizeof(Vertex) * vertices.size();
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
D3D11_SUBRESOURCE_DATA initData;
ZeroMemory(&initData, sizeof(initData));
initData.pSysMem = vertices.data();
HRESULT hr = device->CreateBuffer(&desc, &initData, &vertexBuffer);
if (FAILED(hr)) {
// Handle error: failed to create vertex buffer
return false;
}
return true;
}
bool CreateIndexBuffer(ID3D11Device* device, const std::vector<unsigned int>& indices, ID3D11Buffer*& indexBuffer)
{
D3D11_BUFFER_DESC desc;
ZeroMemory(&desc, sizeof(desc));
desc.Usage = D3D11_USAGE_DEFAULT;
desc.ByteWidth = sizeof(unsigned int) * indices.size();
desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
D3D11_SUBRESOURCE_DATA initData;
ZeroMemory(&initData, sizeof(initData));
initData.pSysMem = indices.data();
HRESULT hr = device->CreateBuffer(&desc, &initData, &indexBuffer);
if (FAILED(hr)) {
// Handle error: failed to create index buffer
return false;
}
return true;
}
// Load model data from file and create vertex and index buffers
Model LoadModel(ID3D11Device* device, const char* absoluteModelFilePath)
{
Model model; // Create an empty model
// Open the model file
std::ifstream inputFile(absoluteModelFilePath);
if (!inputFile.is_open()) {
// Handle error: unable to open file
std::cerr << "Error: Unable to open file " << absoluteModelFilePath << std::endl;
return model; // Return empty model
}
std::vector<Vertex> vertices;
std::vector<unsigned int> indices;
std::string line;
while (std::getline(inputFile, line))
{
std::istringstream iss(line);
std::string type;
iss >> type;
if (type == "v") // Vertex data
{
Vertex vertex;
iss >> vertex.Position.x >> vertex.Position.y >> vertex.Position.z;
vertices.push_back(vertex);
}
else if (type == "f") // Face (index) data
{
unsigned int index;
while (iss >> index)
{
// Subtract 1 from index to convert to zero-based indexing
indices.push_back(index - 1);
}
}
}
// Close the file
inputFile.close();
// Check if vertices and indices are empty
if (vertices.empty() || indices.empty()) {
// Handle error: no vertex or index data loaded
return model; // Return empty model
}
// Initialize the model's vertices and indices with the loaded data
model.vertices = std::move(vertices);
model.indices = std::move(indices);
// Create vertex buffer
if (!CreateVertexBuffer(device, model.vertices, model.vertexBuffer)) {
// Handle error: failed to create vertex buffer
return model; // Return empty model
}
// Create index buffer
if (!CreateIndexBuffer(device, model.indices, model.indexBuffer)) {
// Handle error: failed to create index buffer
return model; // Return empty model
}
// Return the loaded model
return model;
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_PAINT:
{
// Handle painting of the window
// This message is typically handled by calling BeginPaint and EndPaint
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// Add your painting code here
EndPaint(hWnd, &ps);
break;
}
case WM_SIZE:
{
// Handle resizing of the window
// This message is sent when the size of the window is changed
UINT width = LOWORD(lParam);
UINT height = HIWORD(lParam);
// Add your resizing code here
break;
}
case WM_KEYDOWN:
{
// Handle key down events
// This message is sent when a key is pressed
// wParam contains the virtual-key code of the key that was pressed
// Add your key down handling code here
break;
}
case WM_KEYUP:
{
// Handle key up events
// This message is sent when a key is released
// wParam contains the virtual-key code of the key that was released
// Add your key up handling code here
break;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
struct Joint
{
DirectX::XMFLOAT4X4 bindPoseMatrix; // Bind-Pose-Matrix
DirectX::XMFLOAT4X4 localMatrix; // Lokale Transformationsmatrix
DirectX::XMFLOAT4X4 globalMatrix; // Globale Transformationsmatrix für den Joint
int parentIndex; // Index des Eltern-Joints
};
// Hierarchie der Joints
std::vector<Joint> skeletonHierarchy;
// Beispiel für die Initialisierung der skeletonHierarchy
void InitializeSkeletonHierarchy()
{
// Initialize root joint
Joint rootJoint;
rootJoint.parentIndex = -1; // Root joint has no parent
// Initialize other properties of the root joint
rootJoint.bindPoseMatrix = DirectX::XMFLOAT4X4(); // Identity matrix
rootJoint.localMatrix = DirectX::XMFLOAT4X4(); // Identity matrix
rootJoint.globalMatrix = rootJoint.localMatrix; // Initially same as local matrix
// Add the root joint to the hierarchy
skeletonHierarchy.push_back(rootJoint);
// Add more joints to the hierarchy as needed
Joint childJoint;
childJoint.parentIndex = 0; // Index of the parent joint in the hierarchy (root joint here)
// Initialize other properties of the child joint
childJoint.bindPoseMatrix = DirectX::XMFLOAT4X4(); // Initialize as needed
childJoint.localMatrix = DirectX::XMFLOAT4X4(); // Initialize as needed
childJoint.globalMatrix = childJoint.localMatrix; // Initially same as local matrix
// Add the child joint to the hierarchy
skeletonHierarchy.push_back(childJoint);
// Repeat this process for all joints in the hierarchy
}
// Funktion zur Berechnung der globalen Transformationen für alle Joints im Skelett
void UpdateGlobalTransformations(Model& model)
{
for (size_t i = 0; i < skeletonHierarchy.size(); ++i)
{
if (skeletonHierarchy[i].parentIndex != -1)
{
// Calculate the global transformation by multiplying with the parent joint's transformation
DirectX::XMMATRIX parentGlobalMatrix = DirectX::XMLoadFloat4x4(&skeletonHierarchy[skeletonHierarchy[i].parentIndex].globalMatrix);
DirectX::XMMATRIX localMatrix = DirectX::XMLoadFloat4x4(&skeletonHierarchy[i].localMatrix);
DirectX::XMMATRIX globalMatrix = localMatrix * parentGlobalMatrix;
// Update the global matrix back into the hierarchy
DirectX::XMFLOAT4X4 tempMatrix;
DirectX::XMStoreFloat4x4(&tempMatrix, globalMatrix);
skeletonHierarchy[i].globalMatrix = tempMatrix;
// Update the vertex positions based on the new global transformation
for (size_t j = 0; j < model.vertices.size(); ++j)
{
// Transform the vertex position using the joint's global matrix
DirectX::XMVECTOR position = DirectX::XMLoadFloat3(&model.vertices[j].Position);
position = DirectX::XMVector3Transform(position, globalMatrix);
DirectX::XMStoreFloat3(&model.vertices[j].Position, position);
}
}
else
{
// If it's the root joint, its global matrix is the same as its local matrix
skeletonHierarchy[i].globalMatrix = skeletonHierarchy[i].localMatrix;
}
}
}
// Funktion zur Änderung der lokalen Transformationsmatrix eines Joints
void SetLocalTransformationMatrix(int jointIndex, const DirectX::XMFLOAT4X4& newLocalMatrix)
{
skeletonHierarchy[jointIndex].localMatrix = newLocalMatrix;
}
void CleanupDirectX(IDXGISwapChain* pSwapChain, ID3D11Device* pDevice, ID3D11DeviceContext* pDeviceContext)
{
if (pSwapChain) pSwapChain->Release();
if (pDeviceContext) pDeviceContext->Release();
if (pDevice) pDevice->Release();
}
ID3D11RenderTargetView* g_pRenderTargetView = nullptr;
ID3D11Device* g_pd3dDevice = nullptr;
ConstantBuffer<MatrixBufferType> g_MatrixConstantBuffer;
ID3D11InputLayout* g_pVertexLayout = nullptr;
HRESULT InitDirectX(HWND hWnd, ID3D11Device** ppDevice, ID3D11DeviceContext** ppDeviceContext, IDXGISwapChain** ppSwapChain, UINT windowWidth, UINT windowHeight)
{
HRESULT hr = S_OK;
DXGI_SWAP_CHAIN_DESC sd = {};
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = 2; // Update BufferCount to be within the required range
sd.BufferDesc.Width = windowWidth;
sd.BufferDesc.Height = windowHeight;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.Flags = 0;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = hWnd;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.Windowed = TRUE;
sd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // Use flip-model swap effect
UINT createDeviceFlags = 0;
#ifdef _DEBUG
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0 };
D3D_FEATURE_LEVEL featureLevel;
hr = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags, featureLevels, ARRAYSIZE(featureLevels),
D3D11_SDK_VERSION, &sd, ppSwapChain, ppDevice, &featureLevel, ppDeviceContext);
if (FAILED(hr))
{
OutputDebugString(L"DirectX initialization failed!\n");
return hr;
}
// Erstellen Sie die Render-Target-View
ID3D11Texture2D* pBackBuffer = nullptr;
hr = (*ppSwapChain)->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&pBackBuffer));
if (SUCCEEDED(hr)) {
hr = (*ppDevice)->CreateRenderTargetView(pBackBuffer, nullptr, &g_pRenderTargetView);
pBackBuffer->Release(); // Da die View erstellt wurde, kann der Backbuffer freigegeben werden
if (FAILED(hr)) {
return hr; // Fehlerbehandlung, falls das Erstellen der Render-Target-View fehlschlägt
}
}
return hr;
}
HRESULT CompileShaderFromFile(const WCHAR* fileName, LPCSTR entryPoint, LPCSTR shaderModel, ID3DBlob** blobOut)
{
// Define shader compilation flags
DWORD shaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
// Append debug flag if in debug mode
#ifdef _DEBUG
shaderFlags |= D3DCOMPILE_DEBUG;
#endif
// Initialize variables to hold the compiled shader code and error messages
ID3DBlob* errorBlob = nullptr;
HRESULT hr = D3DCompileFromFile(fileName, nullptr, nullptr, entryPoint, shaderModel,
shaderFlags, 0, blobOut, &errorBlob);
// Check if shader compilation failed
if (FAILED(hr))
{
// If an error blob is available, output the error message
if (errorBlob)
{
OutputDebugStringA(reinterpret_cast<const char*>(errorBlob->GetBufferPointer()));
errorBlob->Release(); // Release the error blob
}
return hr; // Return the error code
}
// Check if the compiled shader blob is nullptr
if (*blobOut == nullptr)
{
// Handle the case where the shader compilation succeeded but the blob is nullptr
OutputDebugString(L"Shader compilation succeeded, but the compiled shader blob is nullptr.\n");
return E_FAIL; // Return a failure code
}
// Release the error blob if it was allocated
if (errorBlob) errorBlob->Release();
return S_OK; // Return success code if compilation was successful
}
ID3D11VertexShader* g_pVertexShader = nullptr;
ID3D11PixelShader* g_pPixelShader = nullptr;
HRESULT InitShaders(ID3D11Device* pDevice)
{
HRESULT hr = S_OK;
// Vertex Shader
ID3DBlob* pVertexShaderBlob = nullptr;
hr = CompileShaderFromFile(L"VertexShader.hlsl", "VSMain", "vs_5_0", &pVertexShaderBlob);
if (FAILED(hr))
{
// Handle shader compilation failure
return hr;
}
hr = pDevice->CreateVertexShader(pVertexShaderBlob->GetBufferPointer(), pVertexShaderBlob->GetBufferSize(), nullptr, &g_pVertexShader);
if (FAILED(hr))
{
// Handle shader creation failure
pVertexShaderBlob->Release(); // Release the blob before returning
return hr;
}
// Input Layout
D3D11_INPUT_ELEMENT_DESC layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
UINT numElements = ARRAYSIZE(layout);
hr = pDevice->CreateInputLayout(layout, numElements, pVertexShaderBlob->GetBufferPointer(),
pVertexShaderBlob->GetBufferSize(), &g_pVertexLayout);
pVertexShaderBlob->Release(); // Release the blob after creating the input layout
if (FAILED(hr))
{
// Handle input layout creation failure
return hr;
}
// Pixel Shader
ID3DBlob* pPixelShaderBlob = nullptr;
hr = CompileShaderFromFile(L"PixelShader.hlsl", "PSMain", "ps_5_0", &pPixelShaderBlob);
if (FAILED(hr))
{
// Handle shader compilation failure
return hr;
}
hr = pDevice->CreatePixelShader(pPixelShaderBlob->GetBufferPointer(), pPixelShaderBlob->GetBufferSize(), nullptr, &g_pPixelShader);
pPixelShaderBlob->Release();
if (FAILED(hr))
{
// Handle shader creation failure
return hr;
}
return S_OK;
}
void Render(ID3D11DeviceContext* pDeviceContext, Model& model, UINT windowWidth, UINT windowHeight)
{
// Check if both vertex and index buffers are valid
if (model.vertexBuffer && model.indexBuffer)
{
// Set the primitive topology
pDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
// Set up the viewport
D3D11_VIEWPORT viewport;
ZeroMemory(&viewport, sizeof(viewport));
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = static_cast<float>(windowWidth); // Use window width
viewport.Height = static_cast<float>(windowHeight); // Use window height
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
pDeviceContext->RSSetViewports(1, &viewport);
// Set the input layout
pDeviceContext->IASetInputLayout(g_pVertexLayout);
// Set the vertex buffer
UINT stride = sizeof(Vertex);
UINT offset = 0;
pDeviceContext->IASetVertexBuffers(0, 1, &model.vertexBuffer, &stride, &offset);
// Set the index buffer
pDeviceContext->IASetIndexBuffer(model.indexBuffer, DXGI_FORMAT_R32_UINT, 0);
// Set the Vertex and Pixel Shaders
pDeviceContext->VSSetShader(g_pVertexShader, nullptr, 0);
// Set the Pixel Shader
pDeviceContext->PSSetShader(g_pPixelShader, nullptr, 0);
// Update view matrix for camera position
XMFLOAT3 cameraPosition = XMFLOAT3(0.0f, 0.0f, -5.0f); // Adjust camera position as needed
XMFLOAT3 cameraTarget = XMFLOAT3(0.0f, 0.0f, 0.0f); // Adjust target position as needed
XMFLOAT3 cameraUp = XMFLOAT3(0.0f, 1.0f, 0.0f); // Adjust up vector as needed
XMMATRIX viewMatrix = XMMatrixLookAtLH(XMLoadFloat3(&cameraPosition), XMLoadFloat3(&cameraTarget), XMLoadFloat3(&cameraUp));
// Update projection matrix (Ensure it's correctly configured)
float fovAngleY = XM_PIDIV2;
float aspectRatio = static_cast<float>(windowWidth) / static_cast<float>(windowHeight);
float nearZ = 0.1f;
float farZ = 1000.0f;
XMMATRIX projectionMatrix = XMMatrixPerspectiveFovLH(fovAngleY, aspectRatio, nearZ, farZ);
// Combine view and projection matrices
XMMATRIX viewProjectionMatrix = viewMatrix * projectionMatrix;
// Adjust the translation and scaling factors as needed
XMFLOAT3 modelPosition = XMFLOAT3(0.0f, 0.0f, 0.0f); // Position the model at the origin
XMFLOAT3 modelScale = XMFLOAT3(1.0f, 1.0f, 1.0f); // Scale the model uniformly (no scaling)
// Create translation and scaling matrices
XMMATRIX translationMatrix = XMMatrixTranslation(modelPosition.x, modelPosition.y, modelPosition.z);
XMMATRIX scalingMatrix = XMMatrixScaling(modelScale.x, modelScale.y, modelScale.z);
// Combine translation, scaling, and other transformations as needed
XMMATRIX worldMatrix = scalingMatrix * translationMatrix; // Apply scaling first, then translation
// Set the worldViewProjection matrix in the constant buffer
g_MatrixConstantBuffer.data.worldViewProjection = XMMatrixTranspose(worldMatrix * viewProjectionMatrix);
g_MatrixConstantBuffer.ApplyChanges(pDeviceContext);
g_MatrixConstantBuffer.SetVSBuffer(pDeviceContext, 0);
if (model.indexBuffer) { // Check if indexBuffer is not nullptr
D3D11_BUFFER_DESC desc;
model.indexBuffer->GetDesc(&desc);
UINT numIndices = desc.ByteWidth / sizeof(unsigned int); // For 32-bit indices
pDeviceContext->IASetVertexBuffers(0, 1, &model.vertexBuffer, &stride, &offset);
// Set the Index Buffer
pDeviceContext->IASetIndexBuffer(model.indexBuffer, DXGI_FORMAT_R32_UINT, 0);
UpdateGlobalTransformations(model);
// Iteriere über die Joints und rendere das Modell für jeden Joint
for (size_t i = 0; i < skeletonHierarchy.size(); ++i)
{
// Setze die Welttransformation für jeden Joint
XMMATRIX worldMatrix = XMLoadFloat4x4(&skeletonHierarchy[i].globalMatrix);
g_MatrixConstantBuffer.data.worldViewProjection = XMMatrixTranspose(worldMatrix * viewProjectionMatrix);
g_MatrixConstantBuffer.ApplyChanges(pDeviceContext);
g_MatrixConstantBuffer.SetVSBuffer(pDeviceContext, 0);
// Draw the model
pDeviceContext->DrawIndexed(numIndices, 0, 0);
}
}
}
}
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow)
{
// Initialize variables
HWND hWnd = nullptr;
DXGI_SWAP_CHAIN_DESC sd = {};
HRESULT hr = S_OK;
// Fensterklasse registrieren
WNDCLASSEX wc = {};
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = L"DirectX11WindowClass";
RegisterClassEx(&wc);
// Fenster erstellen
hWnd = CreateWindowEx(
0,
L"DirectX11WindowClass",
L"DirectX 11 Window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 2400, 1800,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
{
// Handle window creation failure
OutputDebugString(L"Failed to create window!\n");
return E_FAIL;
}
// Initialize DXGI_SWAP_CHAIN_DESC after creating the window
sd = {};
sd.BufferCount = 2;
sd.BufferDesc.Width = 2400;
sd.BufferDesc.Height = 1800;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = hWnd;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.Windowed = TRUE;
// Initialisierung von DirectX 11
ID3D11Device* device = nullptr;
ID3D11DeviceContext* deviceContext = nullptr;
IDXGISwapChain* swapChain = nullptr;
// Initialize DirectX
hr = InitDirectX(hWnd, &device, &deviceContext, &swapChain, sd.BufferDesc.Width, sd.BufferDesc.Height);
if (FAILED(hr))
{
// Handle DirectX initialization failure
OutputDebugString(L"DirectX initialization failed!\n");
return hr;
}
g_pd3dDevice = device; // Setze den globalen Zeiger auf das Gerät
g_MatrixConstantBuffer = ConstantBuffer<MatrixBufferType>(g_pd3dDevice);
// Initialisierung der Shader
hr = InitShaders(device);
if (FAILED(hr)) {
// Handle shader initialization failure
OutputDebugString(L"Shader initialization failed!\n");
CleanupDirectX(swapChain, device, deviceContext);
return hr;
}
else {
OutputDebugString(L"Shaders initialized successfully.\n");
}
// Load the 3D model
Model myModel = LoadModel(device, "C:/Users/zizoa/Desktop/RTR/ZiZo_Animation/Marsienne_OBJ/Marsienne_Base.obj");
if (myModel.vertices.empty() || myModel.indices.empty())
{
OutputDebugString(L"Failed to load model or model data is empty!\n");
CleanupDirectX(swapChain, device, deviceContext);
return E_FAIL; // Indicate model loading failure
}
else
{
// Output the size of vertices and indices
std::wstringstream logStream;
logStream << L"Number of Vertices: " << myModel.vertices.size() << L"\n";
logStream << L"Number of Indices: " << myModel.indices.size() << L"\n";
OutputDebugString(logStream.str().c_str());
OutputDebugString(L"Model loaded successfully.\n");
}
// Create vertex buffer
if (!CreateVertexBuffer(device, myModel.vertices, myModel.vertexBuffer))
{
// Handle vertex buffer creation failure
CleanupDirectX(swapChain, device, deviceContext);
return E_FAIL;
}
else
{
OutputDebugString(L"CreateVertexBuffer True.\n");
}
// Create index buffer
if (!CreateIndexBuffer(device, myModel.indices, myModel.indexBuffer))
{
// Handle index buffer creation failure
CleanupDirectX(swapChain, device, deviceContext);
return E_FAIL;
}
else
{
OutputDebugString(L"CreateIndexBuffer True.\n");
}
// Zeige das Fenster an
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
// Nachrichtenverarbeitungsschleife
MSG msg = {};
while (true)
{
// Peek and process messages
while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
{
// Check for quit message
if (msg.message == WM_QUIT || msg.message == WM_CLOSE)
return static_cast<int>(msg.wParam); // Return exit code
// Translate and dispatch the message
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Rendering
if (!CheckForWindowClose())
{
// Update global transformations
UpdateGlobalTransformations(myModel);
// Clear the back buffer
deviceContext->ClearRenderTargetView(g_pRenderTargetView, DirectX::Colors::CornflowerBlue);
// Render the model
Render(deviceContext, myModel, sd.BufferDesc.Width, sd.BufferDesc.Height);
UpdateWindow(hWnd);
// Present the frame
hr = swapChain->Present(0, 0);
if (FAILED(hr))
{
OutputDebugString(L"Failed to present frame!\n");
CleanupDirectX(swapChain, device, deviceContext);
return hr;
}
}
else
{
// Handle window close
break;
}
}
// Cleanup DirectX objects
CleanupDirectX(swapChain, device, deviceContext);
return static_cast<int>(msg.wParam);
}
这是控制台返回的内容:
Shaders initialized successfully.
Number of Vertices: 13235
Number of Indices: 16422
Model loaded successfully.
CreateVertexBuffer True.
CreateIndexBuffer True.
我尝试过更改相机位置,但没有成功。有什么想法吗?
我不确定对象是否被渲染,我还没有深入研究你的 D3D 代码。但我确信,一个可能的问题在于您的查看体积定义和正在渲染的对象。要么您的对象太大而无法包含在查看体积 d 内,要么太小而无法看到。尝试调整观看音量。取顶点缓冲区中指定的坐标的极限,并使用此限制来定义查看体积(正交或透视查看体积)
另一个问题与您指定的相机坐标有关。相机可能会看到某个方向,而您的物体在该方向上不可用。尝试调整相机坐标并检查物体是否可见。
以上建议只是我的猜测。代码中可能存在其他问题。