Anyone used the fbxsdk? I want to load models into my engine but when I load them, something is wrong. I load a sphere made and triangulated with maya and it looks like only the bottom of the sphere gets into the program. I did a cube too and it looks like just one side gets in. What is going on in FBXImport and the dx11 related functions in source.cpp? IT looks ok to me. :(
Here is some code:
FBXImport.h
#pragma once
#include <fbxsdk.h>
#include <winerror.h>
#include <vector>
#include <d3d11.h>
#include <d3dx11.h>
#include <d3dx10.h>
#include <xnamath.h>
#include "wx/wx.h"
#include "wx/notebook.h"
#include <wx/timer.h>
#include <wx/time.h>
using namespace std;
struct Vertex
{
Vertex() {}
Vertex(float x, float y, float z,
float cr, float cg, float cb, float ca)
: pos(x, y, z), color(cr, cg, cb, ca) {}
XMFLOAT3 pos;
XMFLOAT4 color;
};
void InitFBX();
void DestroyManager();
HRESULT ImportFile(vector<Vertex>* pos, vector<DWORD>* indices, wxTextCtrl* ctrl);
FbxImport.cpp
#include "FBXImport.h"
#include <assert.h>
#include <xnamath.h>
FbxManager* fbxMgr = nullptr;
vector<Vertex> vrx_positions;
void InitFBX()
{
fbxMgr = FbxManager::Create();
}
void DestroyManager()
{
fbxMgr->Destroy();
}
HRESULT ImportFile(vector<Vertex>* pos, vector<DWORD>* indices, wxTextCtrl* console)
{
if(fbxMgr == nullptr)
InitFBX();
FbxIOSettings* ios = FbxIOSettings::Create(fbxMgr, IOSROOT);
fbxMgr->SetIOSettings(ios);
FbxImporter* importer = FbxImporter::Create(fbxMgr, "");
FbxScene* scene = FbxScene::Create(fbxMgr, "myScene");
bool success = importer->Initialize("C:\\Models\\sphere.fbx", -1, fbxMgr->GetIOSettings());
if (!success) return E_FAIL;
success = importer->Import(scene);
if (!success) return E_FAIL;
importer->Destroy();
FbxNode* root_node = scene->GetRootNode();
if (root_node)
{
for (int i = 0; i < root_node->GetChildCount(); i++)
{
FbxNode* child_node = root_node->GetChild(i);
if (child_node->GetNodeAttribute() == NULL)
continue;
FbxNodeAttribute::EType attribute_type = child_node->GetNodeAttribute()->GetAttributeType();
if (attribute_type != FbxNodeAttribute::eMesh)
continue;
FbxMesh* mesh = (FbxMesh*)child_node->GetNodeAttribute();
FbxVector4* verts = mesh->GetControlPoints();
for (int j = 0; j < mesh->GetPolygonCount(); j++)
{
int numVerts = mesh->GetPolygonSize(j);
assert(numVerts == 3);
for (int k = 0; k < numVerts; k++)
{
DWORD control_pt_index = mesh->GetPolygonVertex(j, k);
Vertex vrx((float)verts[control_pt_index].mData[0], (float)verts[control_pt_index].mData[1],
(float)verts[control_pt_index].mData[2], 0.6f, 0.8f, 0.6f, 1.0f);
pos->push_back(vrx);
indices->push_back(control_pt_index);
}
}
}
}
}
Source.cpp
#include <windows.h>
#include <d3d11.h>
#include <d3dx11.h>
#include <d3dx10.h>
#include <xnamath.h>
#include "Source.h"
#include "FBXImport.h"
//Global Declarations - Interfaces//
IDXGISwapChain* SwapChain;
ID3D11Device* d3d11Device;
ID3D11DeviceContext* d3d11DevCon;
ID3D11RenderTargetView* renderTargetView;
ID3D11Buffer* squareIndexBuffer;
ID3D11DepthStencilView* depthStencilView;
ID3D11Texture2D* depthStencilBuffer;
ID3D11Buffer* squareVertBuffer;
ID3D11VertexShader* VS;
ID3D11PixelShader* PS;
ID3D10Blob* VS_Buffer;
ID3D10Blob* PS_Buffer;
ID3D11InputLayout* vertLayout;
ID3D11Buffer* cbPerObjectBuffer;
ID3D11Buffer* fbx_index_buf;
ID3D11Buffer* fbx_vert_buf;
//Global Declarations - Others//
LPCTSTR WndClassName = L"firstwindow";
HWND hwnd = NULL;
HRESULT hr;
int Width = 300;
int Height = 300;
vector<Vertex> verts;
vector<DWORD> indices;
Vertex* positions;
DWORD* index;
XMMATRIX WVP;
///////////////**************new**************////////////////////
XMMATRIX cube1World;
XMMATRIX cube2World;
XMMATRIX cube_fbx;
///////////////**************new**************////////////////////
XMMATRIX camView;
XMMATRIX camProjection;
XMVECTOR camPosition;
XMVECTOR camTarget;
XMVECTOR camUp;
///////////////**************new**************////////////////////
XMMATRIX Rotation;
XMMATRIX Scale;
XMMATRIX Translation;
float rot = 0.01f;
///////////////**************new**************////////////////////
//Create effects constant buffer's structure//
struct cbPerObject
{
XMMATRIX WVP;
};
cbPerObject cbPerObj;
D3D11_INPUT_ELEMENT_DESC layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
UINT numElements = ARRAYSIZE(layout);
// Event table for MyFrame
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(wxID_EXIT, MyFrame::OnQuit)
EVT_CLOSE(MyFrame::OnClose)
wxEND_EVENT_TABLE()
// Implements MyApp& GetApp()
DECLARE_APP(MyApp)
// Give wxWidgets the means to create a MyApp object
IMPLEMENT_APP(MyApp)
bool MyApp::OnInit()
{
// Create the main application window
MyFrame *frame = new MyFrame(wxT("Worgen Engine Version 0"));
// Show it
frame->Show(true);
return true;
}
void MyFrame::OnQuit(wxCommandEvent& event)
{
// Destroy the frame
Close();
}
void MyFrame::OnClose(wxCloseEvent& event)
{
timer->Stop();
//Release the COM Objects we created
SwapChain->Release();
d3d11Device->Release();
d3d11DevCon->Release();
renderTargetView->Release();
VS->Release();
PS->Release();
VS_Buffer->Release();
PS_Buffer->Release();
vertLayout->Release();
depthStencilView->Release();
depthStencilBuffer->Release();
cbPerObjectBuffer->Release();
event.Skip();
}
MyFrame::MyFrame(const wxString& title)
: wxFrame(NULL, wxID_ANY, title, wxDefaultPosition)
{
// Create a menu bar
wxMenu *fileMenu = new wxMenu;
// The “About” item should be in the help menu
wxMenu *helpMenu = new wxMenu;
helpMenu->Append(wxID_ABOUT, wxT("&About...\tF1"),
wxT("ABout this program."));
fileMenu->Append(wxID_EXIT, wxT("E&xit\tAlt - X"),
wxT("Quit this program"));
// Now append the freshly created menu to the menu bar...
wxMenuBar *menuBar = new wxMenuBar();
menuBar->Append(fileMenu, wxT("&File"));
menuBar->Append(helpMenu, wxT("&Help"));
// ... and attach this menu bar to the frame
SetMenuBar(menuBar);
// Create a status bar just for fun
CreateStatusBar(2);
SetStatusText(wxT("Welcome to Worgen Engine!"));
nbHierarchy = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxSize(200, 300));
nbScene = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxSize(800, 600));
nbInspector = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxSize(200, 300));
console = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(800, 300), wxTE_MULTILINE | wxTE_READONLY);
timer = new RenderTimer();
timer->dxPanel = new MyDxPanel((MyFrame*)nbScene);
wxPanel* hierarchyWindow = new wxPanel(nbHierarchy, wxID_ANY);
nbHierarchy->AddPage(hierarchyWindow, "Hierarchy", false);
nbScene->AddPage(timer->dxPanel, "Game", false);
wxPanel* inspectorWindow = new wxPanel(nbInspector, wxID_ANY);
nbInspector->AddPage(inspectorWindow, "Inspector", false);
wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(nbHierarchy, 0, wxEXPAND, 0);
sizer->Add(nbScene, 1, wxEXPAND, 0);
sizer->Add(nbInspector, 0, wxEXPAND, 0);
wxBoxSizer* console_sizer = new wxBoxSizer(wxVERTICAL);
console_sizer->Add(sizer, 0, wxEXPAND, 0);
console_sizer->Add(console, 0, wxEXPAND, 0);
SetSizerAndFit(console_sizer);
HRESULT hr = ImportFile(&verts, &indices, console);
if (hr == E_FAIL)
{
wxMessageBox("Error importing fbx");
}
positions = &verts[0];
index = &indices[0];
timer->dxPanel->initDx(timer->dxPanel->GetHWND());
timer->dxPanel->initScene();
timer->Start();
}
MyFrame::~MyFrame()
{
delete timer;
}
wxBEGIN_EVENT_TABLE(MyDxPanel, wxPanel)
EVT_PAINT(MyDxPanel::OnPaint)
EVT_ERASE_BACKGROUND(MyDxPanel::OnEraseBackground)
wxEND_EVENT_TABLE()
MyDxPanel::MyDxPanel(MyFrame* parent) : wxPanel(parent)
{
parentFrame = parent;
}
MyDxPanel::~MyDxPanel()
{
}
void MyDxPanel::OnEraseBackground(wxEraseEvent &WXUNUSED(event))
{
//empty to avoid flashing
}
void MyDxPanel::updateScene()
{
rot += .05f;
if (rot > 6.26f)
rot = 0.0f;
XMVECTOR rotaxis = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
Rotation = XMMatrixRotationAxis(rotaxis, -rot);
cube_fbx = Rotation;
}
void MyDxPanel::render()
{
//Clear our backbuffer
float bgColor[4] = { (0.0f, 0.0f, 0.0f, 0.0f) };
d3d11DevCon->ClearRenderTargetView(renderTargetView, bgColor);
//Refresh the Depth/Stencil view
d3d11DevCon->ClearDepthStencilView(depthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
WVP = cube_fbx * camView * camProjection;
cbPerObj.WVP = XMMatrixTranspose(WVP);
d3d11DevCon->UpdateSubresource(cbPerObjectBuffer, 0, NULL, &cbPerObj, 0, 0);
d3d11DevCon->VSSetConstantBuffers(0, 1, &cbPerObjectBuffer);
d3d11DevCon->DrawIndexed(indices.size(), 0, 0);
//Present the backbuffer to the screen
SwapChain->Present(0, 0);
}
void MyDxPanel::OnPaint(wxPaintEvent& event)
{
wxPaintDC dc(this);
updateScene();
render();
}
void MyDxPanel::initDx(HWND wnd)
{
//Describe our SwapChain Buffer
DXGI_MODE_DESC bufferDesc;
ZeroMemory(&bufferDesc, sizeof(DXGI_MODE_DESC));
bufferDesc.Width = Width;
bufferDesc.Height = Height;
bufferDesc.RefreshRate.Numerator = 60;
bufferDesc.RefreshRate.Denominator = 1;
bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
//Describe our SwapChain
DXGI_SWAP_CHAIN_DESC swapChainDesc;
ZeroMemory(&swapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
swapChainDesc.BufferDesc = bufferDesc;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.BufferCount = 1;
swapChainDesc.OutputWindow = wnd;
swapChainDesc.Windowed = TRUE;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
//Create our SwapChain
hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, NULL, NULL,
D3D11_SDK_VERSION, &swapChainDesc, &SwapChain, &d3d11Device, NULL, &d3d11DevCon);
//Create our BackBuffer
ID3D11Texture2D* BackBuffer;
hr = SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&BackBuffer);
//Create our Render Target
hr = d3d11Device->CreateRenderTargetView(BackBuffer, NULL, &renderTargetView);
BackBuffer->Release();
//Describe our Depth/Stencil Buffer
D3D11_TEXTURE2D_DESC depthStencilDesc;
depthStencilDesc.Width = Width;
depthStencilDesc.Height = Height;
depthStencilDesc.MipLevels = 1;
depthStencilDesc.ArraySize = 1;
depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthStencilDesc.SampleDesc.Count = 1;
depthStencilDesc.SampleDesc.Quality = 0;
depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
depthStencilDesc.CPUAccessFlags = 0;
depthStencilDesc.MiscFlags = 0;
//Create the Depth/Stencil View
d3d11Device->CreateTexture2D(&depthStencilDesc, NULL, &depthStencilBuffer);
d3d11Device->CreateDepthStencilView(depthStencilBuffer, NULL, &depthStencilView);
//Set our Render Target
d3d11DevCon->OMSetRenderTargets(1, &renderTargetView, depthStencilView);
}
void MyDxPanel::initScene()
{
//Compile Shaders from shader file
hr = D3DX11CompileFromFile(L"Effects.fx", 0, 0, "VS", "vs_4_0", 0, 0, 0, &VS_Buffer, 0, 0);
hr = D3DX11CompileFromFile(L"Effects.fx", 0, 0, "PS", "ps_4_0", 0, 0, 0, &PS_Buffer, 0, 0);
//Create the Shader Objects
hr = d3d11Device->CreateVertexShader(VS_Buffer->GetBufferPointer(), VS_Buffer->GetBufferSize(), NULL, &VS);
hr = d3d11Device->CreatePixelShader(PS_Buffer->GetBufferPointer(), PS_Buffer->GetBufferSize(), NULL, &PS);
//Set Vertex and Pixel Shaders
d3d11DevCon->VSSetShader(VS, 0, 0);
d3d11DevCon->PSSetShader(PS, 0, 0);
D3D11_BUFFER_DESC indexBufferDesc;
ZeroMemory(&indexBufferDesc, sizeof(indexBufferDesc));
indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
indexBufferDesc.ByteWidth = sizeof(DWORD) * indices.size();
indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
indexBufferDesc.CPUAccessFlags = 0;
indexBufferDesc.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA iinitData;
iinitData.pSysMem = index;
d3d11Device->CreateBuffer(&indexBufferDesc, &iinitData, &fbx_index_buf);
d3d11DevCon->IASetIndexBuffer(fbx_index_buf, DXGI_FORMAT_R32_UINT, 0);
D3D11_BUFFER_DESC vertexBufferDesc;
ZeroMemory(&vertexBufferDesc, sizeof(vertexBufferDesc));
vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
vertexBufferDesc.ByteWidth = sizeof(Vertex) * verts.size();
vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexBufferDesc.CPUAccessFlags = 0;
vertexBufferDesc.MiscFlags = 0;
///////////////**************new**************////////////////////
D3D11_SUBRESOURCE_DATA vertexBufferData;
ZeroMemory(&vertexBufferData, sizeof(vertexBufferData));
vertexBufferData.pSysMem = positions;
hr = d3d11Device->CreateBuffer(&vertexBufferDesc, &vertexBufferData, &fbx_vert_buf);
//Set the vertex buffer
UINT stride = sizeof(Vertex);
UINT offset = 0;
d3d11DevCon->IASetVertexBuffers(0, 1, &fbx_vert_buf, &stride, &offset);
//Create the Input Layout
hr = d3d11Device->CreateInputLayout(layout, numElements, VS_Buffer->GetBufferPointer(),
VS_Buffer->GetBufferSize(), &vertLayout);
//Set the Input Layout
d3d11DevCon->IASetInputLayout(vertLayout);
//Set Primitive Topology
d3d11DevCon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
//Create the Viewport
D3D11_VIEWPORT viewport;
ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = Width;
viewport.Height = Height;
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
//Set the Viewport
d3d11DevCon->RSSetViewports(1, &viewport);
//Create the buffer to send to the cbuffer in effect file
D3D11_BUFFER_DESC cbbd;
ZeroMemory(&cbbd, sizeof(D3D11_BUFFER_DESC));
cbbd.Usage = D3D11_USAGE_DEFAULT;
cbbd.ByteWidth = sizeof(cbPerObject);
cbbd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
cbbd.CPUAccessFlags = 0;
cbbd.MiscFlags = 0;
hr = d3d11Device->CreateBuffer(&cbbd, NULL, &cbPerObjectBuffer);
//Camera information
///////////////**************new**************////////////////////
camPosition = XMVectorSet(0.0f, 3.0f, -8.0f, 0.0f);
///////////////**************new**************////////////////////
camTarget = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f);
camUp = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
//Set the View matrix
camView = XMMatrixLookAtLH(camPosition, camTarget, camUp);
//Set the Projection matrix
camProjection = XMMatrixPerspectiveFovLH(0.4f*3.14f, (float)Width / Height, 1.0f, 1000.0f);
}
RenderTimer::RenderTimer() : wxTimer()
{
}
void RenderTimer::Notify()
{
dxPanel->Refresh();
}
void RenderTimer::start()
{
wxTimer::Start(10);
}