現状:FBXで作成したキャラクターの表示は成功。
スケルトンを使いボーン名の取得に成功。
FbxCulusterを使いボーン数の取得に成功。
そのボーンに対するウェイト取得にも成功。
Kinectからの情報も取得完了。
Fbxmatrixをxmmatrixに変換しその値を返すことに成功。
ボーン情報入りのhlslの作成にも成功。(たぶん)
まではできました。
あとは、キャラクターの持つ各ボーンに情報を与えてやれば動くはず。
そこで、まずはkinectを使わず内部的に値を与えて動かそうとしました。
しかし、キャラクターが動くどころかピクリともしません。
返ってきた値はちゃんと正しく入っていました。
動かないのは返ってきた値がちゃんとシェーダーに渡されていないからなのでしょうか・・・・・・・。
追記1/30>g_pImmediateContext->PSSetShader(g_ppsFBX_skin, NULL, 0);
と新たにシェーダーを追加するとキャラが表示されなくなってしまいます・・・。
主軸となる部分
#pragma once
#include <d3dcompiler.h>
#include <SpriteFont.h>
#include <d3d11.h>
#include "DDSTextureLoader.h"
#include "resource.h"
#include "stdafx.h"
#include "SimpleMath.h"
//#include "BoneInfo.h"
#include "CFBXRendererDX11.h"
#include "FBXanim.h"
using namespace DirectX;
#include "Model.h"
//--------------------------------------------------------------------------------------
// Global Variables
//--------------------------------------------------------------------------------------
HINSTANCE g_hInst = NULL;
HWND g_hWnd = NULL;
D3D_DRIVER_TYPE g_driverType = D3D_DRIVER_TYPE_NULL;
D3D_FEATURE_LEVEL g_featureLevel = D3D_FEATURE_LEVEL_11_0;
ID3D11Device* g_pd3dDevice = NULL;
ID3D11DeviceContext* g_pImmediateContext = NULL;
IDXGISwapChain* g_pSwapChain = NULL;
ID3D11RenderTargetView* g_pRenderTargetView = NULL;
ID3D11Texture2D* g_pDepthStencil = NULL;
ID3D11DepthStencilView* g_pDepthStencilView = NULL;
ID3D11DepthStencilState* g_pDepthStencilState = NULL;
XMMATRIX g_World;
XMMATRIX g_View;
XMMATRIX g_Projection;
XMFLOAT4 g_vMeshColor(0.7f, 0.7f, 0.7f, 1.0f);
// グラフィックス診断用
ID3DUserDefinedAnnotation* g_pUserAnotation = nullptr;
//--------------------------------------------------------------------------------------
// Forward declarations
//--------------------------------------------------------------------------------------
HRESULT InitWindow(HINSTANCE hInstance, int nCmdShow);
HRESULT InitDevice();
void CleanupDevice();
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void Render();
// 追加記述
const DWORD NUMBER_OF_MODELS = 1;
HRESULT InitApp();
void CleanupApp();
void UpdateApp();
HRESULT SetupTransformSRV();
void SetMatrix();
FBX_LOADER::MATERIAL_DATA* lm_p;
FBX_LOADER::CFBXRenderDX11* g_pFbxDX11[NUMBER_OF_MODELS];
char g_files[NUMBER_OF_MODELS][256] =
{
"Assets\\bonebox.FBX",
//"Assets\\minorin.fbx",
//"Assets\\model3.fbx",
};
struct CBFBXMATRIX
{
XMMATRIX mWorld;
XMMATRIX mView;
XMMATRIX mProj;
XMMATRIX mWVP;
};
ID3D11BlendState* g_pBlendState = nullptr;
ID3D11RasterizerState* g_pRS = nullptr;
ID3D11Buffer* g_pcBuffer = nullptr;
ID3D11VertexShader* g_pvsFBX = nullptr;
ID3D11PixelShader* g_ppsFBX = nullptr;
ID3D11PixelShader* g_ppsFBX_skin = nullptr;
// Instancing
bool g_bInstancing = false;
struct SRVPerInstanceData
{
XMMATRIX mWorld;
};
//ポリゴン頂点構造体
struct Vertex3D {
float pos[3]; //x-y-z
float col[4]; //r-g-b-a
};
const int TYOUTEN = 3; //ポリゴンの頂点数
//頂点データ(三角ポリゴン1枚)
Vertex3D hVectorData[TYOUTEN] = {
{ { +0.0f, +0.5f, +0.5f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { +0.5f, -0.5f, +0.5f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
{ { -0.5f, -0.5f, +0.5f }, { 1.0f, 1.0f, 1.0f, 1.0f } }
};
const uint32_t g_InstanceMAX = 32;
ID3D11VertexShader* g_pvsFBXInstancing = nullptr;
//---------------------
//
//各種バッファ
//
//---------------------
ID3D11Buffer* g_pTransformStructuredBuffer = nullptr;
ID3D11Buffer* g_pConstantBuffer0 = NULL;//アプリ←→シェーダー架け橋 コンスタントバッファー ライト、カメラ
ID3D11Buffer* g_pConstantBuffer1 = NULL;//アプリ←→シェーダー架け橋 コンスタントバッファー 変換行列、マテリアル
ID3D11Buffer* g_pConstantBufferBone = NULL;//アプリ←→シェーダー架け橋 コンスタントバッファー ボーン
ID3D11ShaderResourceView* g_pTransformSRV = nullptr;
DirectX::SpriteBatch* g_pSpriteBatch = nullptr;
DirectX::SpriteFont* g_pFont = nullptr;
//-----------------------------
//
//スキンメッシュ用シェーダー(アプリ側の構造体)
//
//-----------------------------
//XMFLOAT ◯ ← Vector ◯
//シェーダーに渡す値
struct SHADER_GLOBAL0
{
XMFLOAT4 vLightDir;//ライト方向
XMFLOAT4 vEye;//カメラ位置
};
struct SHADER_GLOBAL1
{
XMMATRIX mW;//ワールド行列
XMMATRIX mWVP;//ワールドから射影までの変換行列
XMFLOAT4 vAmbient;//アンビエント光
XMFLOAT4 vDiffuse;//ディフューズ色
XMFLOAT4 vSpecular;//鏡面反射
};
#define MAX_BONES 255
//シェーダーに渡すボーン行列配列
struct SHADER_GLOBAL_BONES
{
XMMATRIX mBone[MAX_BONES];
SHADER_GLOBAL_BONES()
{
for (int i = 0; i < MAX_BONES; i++)
{
XMMatrixIdentity();
}
}
};
//---------------------------------------------
// オリジナル マテリアル構造体
struct MY_MATERIAL
{
CHAR szName[100];
XMFLOAT4 Ka;//アンビエント
XMFLOAT4 Kd;//ディフューズ
XMFLOAT4 Ks;//スペキュラー
CHAR szTextureName[100];//テクスチャーファイル名
ID3D11ShaderResourceView* pTexture;
DWORD dwNumFace;//そのマテリアルであるポリゴン数
MY_MATERIAL()
{
ZeroMemory(this, sizeof(MY_MATERIAL));
}
~MY_MATERIAL()
{
}
};
MY_MATERIAL *m_pMaterial;
XMFLOAT3 g_vLightDir(1, -1, 1);
//XMFLOAT4 g_vEyeDir(1.0f, -1.0f, 1.0f, 1.0f);
BoneInfo* boneifo = nullptr;
BoneInfo::BONE* boneinfo_to_BONEp;
//--------------------------------------------------------------------------------------
// Entry point to the program. Initializes everything and goes into a message processing
// loop. Idle time is used to render the scene.
//--------------------------------------------------------------------------------------
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
if (FAILED(InitWindow(hInstance, nCmdShow)))
return 0;
int posP = 0;
if (FAILED(InitDevice()))
{
CleanupApp();
CleanupDevice();
return 0;
}
static int iFrame = 0;
// Main message loop
MSG msg = { 0 };
while (WM_QUIT != msg.message)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
Render();
}
}
CleanupApp();
CleanupDevice();
return (int) msg.wParam;
}
//--------------------------------------------------------------------------------------
// Register class and create window
//--------------------------------------------------------------------------------------
HRESULT InitWindow(HINSTANCE hInstance, int nCmdShow)
{
// Register class
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR) IDI_FBX2015LOADER4DX11);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = L"TutorialWindowClass";
wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR) IDI_FBX2015LOADER4DX11);
if (!RegisterClassEx(&wcex))
return E_FAIL;
// Create window
g_hInst = hInstance;
RECT rc = { 0, 0, 1920, 1080 };
AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
g_hWnd = CreateWindow(L"TutorialWindowClass", L"Direct3D 11 FBX Sample", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance,
NULL);
if (!g_hWnd)
return E_FAIL;
ShowWindow(g_hWnd, nCmdShow);
return S_OK;
}
//--------------------------------------------------------------------------------------
// Helper for compiling shaders with FBX_LOADER::CFBXRenderDX11D3DCompile
//
// With VS 11, we could load up prebuilt .cso files instead...
//--------------------------------------------------------------------------------------
HRESULT CompileShaderFromFile(WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut)
{
HRESULT hr = S_OK;
DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
#if defined( DEBUG ) || defined( _DEBUG )
// Set the D3DCOMPILE_DEBUG flag to embed debug information in the shaders.
// Setting this flag improves the shader debugging experience, but still allows
// the shaders to be optimized and to run exactly the way they will run in
// the release configuration of this program.
dwShaderFlags |= D3DCOMPILE_DEBUG;
#endif
ID3DBlob* pErrorBlob;
hr = D3DCompileFromFile(szFileName, NULL, NULL, szEntryPoint, szShaderModel,
dwShaderFlags, 0, ppBlobOut, &pErrorBlob);
if (FAILED(hr))
{
if (pErrorBlob != NULL)
OutputDebugStringA((char*) pErrorBlob->GetBufferPointer());
if (pErrorBlob) pErrorBlob->Release();
return hr;
}
if (pErrorBlob) pErrorBlob->Release();
return S_OK;
}
//--------------------------------------------------------------------------------------
// Create Direct3D device and swap chain
//--------------------------------------------------------------------------------------
HRESULT InitDevice()
{
HRESULT hr = S_OK;
RECT rc;
GetClientRect(g_hWnd, &rc);
UINT width = rc.right - rc.left;
UINT height = rc.bottom - rc.top;
UINT createDeviceFlags = 0;
#ifdef _DEBUG
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
D3D_DRIVER_TYPE driverTypes [] =
{
D3D_DRIVER_TYPE_HARDWARE,
D3D_DRIVER_TYPE_WARP,
D3D_DRIVER_TYPE_REFERENCE,
};
UINT numDriverTypes = ARRAYSIZE(driverTypes);
D3D_FEATURE_LEVEL featureLevels [] =
{
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
};
UINT numFeatureLevels = ARRAYSIZE(featureLevels);
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = 1;
sd.BufferDesc.Width = width;
sd.BufferDesc.Height = height;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = g_hWnd;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.Windowed = TRUE;
for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++)
{
g_driverType = driverTypes[driverTypeIndex];
hr = D3D11CreateDeviceAndSwapChain(NULL, g_driverType, NULL, createDeviceFlags, featureLevels, numFeatureLevels,
D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext);
if (SUCCEEDED(hr))
break;
}
if (FAILED(hr))
return hr;
//
g_pImmediateContext->QueryInterface( __uuidof(ID3DUserDefinedAnnotation), (void**)&g_pUserAnotation);
// Create a render target view
ID3D11Texture2D* pBackBuffer = NULL;
hr = g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*) &pBackBuffer);
if (FAILED(hr))
return hr;
hr = g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_pRenderTargetView);
pBackBuffer->Release();
if (FAILED(hr))
return hr;
// Create depth stencil texture
D3D11_TEXTURE2D_DESC descDepth;
ZeroMemory(&descDepth, sizeof(descDepth));
descDepth.Width = width;
descDepth.Height = height;
descDepth.MipLevels = 1;
descDepth.ArraySize = 1;
descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
descDepth.SampleDesc.Count = 1;
descDepth.SampleDesc.Quality = 0;
descDepth.Usage = D3D11_USAGE_DEFAULT;
descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
descDepth.CPUAccessFlags = 0;
descDepth.MiscFlags = 0;
hr = g_pd3dDevice->CreateTexture2D(&descDepth, NULL, &g_pDepthStencil);
if (FAILED(hr))
return hr;
// Create the depth stencil view
D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;
ZeroMemory(&descDSV, sizeof(descDSV));
descDSV.Format = descDepth.Format;
descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
descDSV.Texture2D.MipSlice = 0;
hr = g_pd3dDevice->CreateDepthStencilView(g_pDepthStencil, &descDSV, &g_pDepthStencilView);
if (FAILED(hr))
return hr;
g_pImmediateContext->OMSetRenderTargets(1, &g_pRenderTargetView, g_pDepthStencilView);
// Create depth stencil state
D3D11_DEPTH_STENCIL_DESC descDSS;
ZeroMemory(&descDSS, sizeof(descDSS));
descDSS.DepthEnable = TRUE;
descDSS.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
descDSS.DepthFunc = D3D11_COMPARISON_LESS;
descDSS.StencilEnable = FALSE;
hr = g_pd3dDevice->CreateDepthStencilState(&descDSS, &g_pDepthStencilState);
// Setup the viewport
D3D11_VIEWPORT vp;
vp.Width = (FLOAT) width;
vp.Height = (FLOAT) height;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = 0;
vp.TopLeftY = 0;
g_pImmediateContext->RSSetViewports(1, &vp);
// Initialize the world matrices
g_World = XMMatrixIdentity();
hr = InitApp();
if (FAILED(hr))
return hr;
hr = SetupTransformSRV();
if (FAILED(hr))
return hr;
return S_OK;
}
// FBX描画用初期化
HRESULT InitApp()
{
HRESULT hr = S_OK;
FbxNode * pnode = nullptr;
// FBXの読み取り
// 注:頂点バッファやインデックスバッファはこの時点で生成されるがInputLayoutは作成しない
for (DWORD i = 0; i<NUMBER_OF_MODELS; i++)
{
g_pFbxDX11[i] = new FBX_LOADER::CFBXRenderDX11;
hr = g_pFbxDX11[i]->LoadFBX(g_files[i], g_pd3dDevice);
}
if (FAILED(hr))
{
MessageBox(NULL,
L"FBX Error", L"Error", MB_OK);
return hr;
}
// Compile the vertex shader
ID3DBlob* pVSBlob = NULL;
hr = CompileShaderFromFile(L"simpleRenderVS.hlsl", "vs_main", "vs_4_0", &pVSBlob);
if (FAILED(hr))
{
MessageBox(NULL,
L"The FX file cannot be compiled. Please run this executable from the directory that contains the FX file.", L"Error", MB_OK);
return hr;
}
// Create the vertex shader
hr = g_pd3dDevice->CreateVertexShader(pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &g_pvsFBX);
if (FAILED(hr))
{
pVSBlob->Release();
return hr;
}
// Compile the vertex shader
pVSBlob->Release();
hr = CompileShaderFromFile(L"simpleRenderInstancingVS.hlsl", "vs_main", "vs_4_0", &pVSBlob);
if (FAILED(hr))
{
MessageBox(NULL,
L"The FX file cannot be compiled. Please run this executable from the directory that contains the FX file.", L"Error", MB_OK);
return hr;
}
// Create the vertex shader
hr = g_pd3dDevice->CreateVertexShader(pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &g_pvsFBXInstancing);
if (FAILED(hr))
{
pVSBlob->Release();
return hr;
}
pVSBlob->Release();
hr = CompileShaderFromFile(L"cubeMP.hlsl", "VS", "vs_4_0", &pVSBlob);
if (FAILED(hr))
{
pVSBlob->Release();
return hr;
}
// Define the 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 },
{ "TEXCOORD" , 0, DXGI_FORMAT_R32G32_FLOAT , 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "BONE_INDEX" , 0, DXGI_FORMAT_R32G32B32A32_UINT , 0, 32, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "BONE_WEIGHT" , 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 48, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
UINT numElements = ARRAYSIZE(layout);
for (DWORD i = 0; i<NUMBER_OF_MODELS; i++)
{
hr = g_pFbxDX11[i]->CreateInputLayout(g_pd3dDevice, pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), layout, numElements);
}
pVSBlob->Release();
if (FAILED(hr))
return hr;
// Compile the pixel shader
ID3DBlob* pPSBlob = NULL;
hr = CompileShaderFromFile(L"simpleRenderPS.hlsl", "PS", "ps_4_0", &pPSBlob);
if (FAILED(hr))
{
MessageBox(NULL,
L"The FX file cannot be compiled. Please run this executable from the directory that contains the FX file.", L"Error", MB_OK);
return hr;
}
// Create the pixel shader
hr = g_pd3dDevice->CreatePixelShader(pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, &g_ppsFBX);
pPSBlob->Release();
if (FAILED(hr))
return hr;
//Compile the pixel shader
ID3DBlob* pPSBlob2 = NULL;
hr = CompileShaderFromFile(L"SkinmeshforPixelShaders.hlsl", "PS", "ps_4_0", &pPSBlob2);
if (FAILED(hr))
{
MessageBox(NULL,
L"The FX file cannot be compiled. Please run this executable from the directory that contains the FX file.", L"Error", MB_OK);
return hr;
}
// Create the pixel shader
hr = g_pd3dDevice->CreatePixelShader(pPSBlob2->GetBufferPointer(), pPSBlob2->GetBufferSize(), NULL, &g_ppsFBX_skin);
pPSBlob2->Release();
if (FAILED(hr))
return hr;
// Create Constant Buffer
D3D11_BUFFER_DESC bd;
ZeroMemory(&bd, sizeof(bd));
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.ByteWidth = sizeof(CBFBXMATRIX);
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
hr = g_pd3dDevice->CreateBuffer(&bd, NULL, &g_pcBuffer);
if (FAILED(hr))
return hr;
//------------------------------------------------------------------------------------------------
//-------------------------------------------
//
//ボーン情報入りシェーダ用各種バッファ
//
//-------------------------------------------
//コンスタントバッファー0作成
D3D11_BUFFER_DESC cb;
cb.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
cb.ByteWidth = sizeof(SHADER_GLOBAL0);
cb.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
cb.MiscFlags = 0;
cb.StructureByteStride = 0;
cb.Usage = D3D11_USAGE_DYNAMIC;
g_pd3dDevice->CreateBuffer(&cb, NULL, &g_pConstantBuffer0);
//コンスタントバッファー1作成
cb.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
cb.ByteWidth = sizeof(SHADER_GLOBAL1);
cb.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
cb.MiscFlags = 0;
cb.StructureByteStride = 0;
cb.Usage = D3D11_USAGE_DYNAMIC;
g_pd3dDevice->CreateBuffer(&cb, NULL, &g_pConstantBuffer1);
//コンスタントバッファーボーン用 作成
cb.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
cb.ByteWidth = sizeof(SHADER_GLOBAL_BONES);
cb.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
cb.MiscFlags = 0;
cb.StructureByteStride = 0;
cb.Usage = D3D11_USAGE_DYNAMIC;
if (FAILED(g_pd3dDevice->CreateBuffer(&cb, NULL, &g_pConstantBufferBone)))
{
return E_FAIL;
}
//---------------------------------------------
D3D11_RASTERIZER_DESC rsDesc;
ZeroMemory(&rsDesc, sizeof(D3D11_RASTERIZER_DESC));
rsDesc.FillMode = D3D11_FILL_SOLID;
rsDesc.CullMode = D3D11_CULL_BACK;
rsDesc.FrontCounterClockwise = false;
rsDesc.DepthClipEnable = FALSE;
g_pd3dDevice->CreateRasterizerState(&rsDesc, &g_pRS);
g_pImmediateContext->RSSetState(g_pRS);
D3D11_BLEND_DESC blendDesc;
ZeroMemory(&blendDesc, sizeof(D3D11_BLEND_DESC));
blendDesc.AlphaToCoverageEnable = false;
blendDesc.IndependentBlendEnable = false;
blendDesc.RenderTarget[0].BlendEnable = true;
blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
blendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO; ///tryed D3D11_BLEND_ONE ... (and others desperate combinations ... )
blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; ///tryed D3D11_BLEND_ONE ... (and others desperate combinations ... )
blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
g_pd3dDevice->CreateBlendState(&blendDesc, &g_pBlendState);
/*boneifo->m_pDevice = g_pd3dDevice;
boneifo->m_pDeviceContext = g_pImmediateContext;
boneifo->m_pSampleLinear = lm_p->pSampler;
boneifo->m_pConstantBuffer = g_pConstantBuffer1;*/
// SpriteBatch
g_pSpriteBatch = new DirectX::SpriteBatch(g_pImmediateContext);
// SpriteFont
g_pFont = new DirectX::SpriteFont(g_pd3dDevice, L"Assets\\Arial.spritefont");
return hr;
}
HRESULT SetupTransformSRV()
{
HRESULT hr = S_OK;
const uint32_t count = g_InstanceMAX;
const uint32_t stride = static_cast<uint32_t>(sizeof(SRVPerInstanceData));
// Create StructuredBuffer
D3D11_BUFFER_DESC bd;
ZeroMemory(&bd, sizeof(bd));
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.ByteWidth = stride * count;
bd.BindFlags = D3D11_BIND_SHADER_RESOURCE;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
bd.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
bd.StructureByteStride = stride;
hr = g_pd3dDevice->CreateBuffer(&bd, NULL, &g_pTransformStructuredBuffer);
if (FAILED(hr))
return hr;
// Create ShaderResourceView
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
ZeroMemory(&srvDesc, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX; // 拡張されたバッファーであることを指定する
srvDesc.BufferEx.FirstElement = 0;
srvDesc.Format = DXGI_FORMAT_UNKNOWN;
srvDesc.BufferEx.NumElements = count; // リソース内の要素の数
// 構造化バッファーをもとにシェーダーリソースビューを作成する
hr = g_pd3dDevice->CreateShaderResourceView(g_pTransformStructuredBuffer, &srvDesc, &g_pTransformSRV);
if (FAILED(hr))
return hr;
return hr;
}
//
void CleanupApp()
{
if (g_pUserAnotation)
{
g_pUserAnotation->Release();
g_pUserAnotation = nullptr;
}
if (g_pSpriteBatch)
{
delete g_pSpriteBatch;
g_pSpriteBatch = nullptr;
}
if (g_pFont)
{
delete g_pFont;
g_pFont = nullptr;
}
if (g_pTransformSRV)
{
g_pTransformSRV->Release();
g_pTransformSRV = nullptr;
}
if (g_pTransformStructuredBuffer)
{
g_pTransformStructuredBuffer->Release();
g_pTransformStructuredBuffer = nullptr;
}
if (g_pBlendState)
{
g_pBlendState->Release();
g_pBlendState = nullptr;
}
for (DWORD i = 0; i<NUMBER_OF_MODELS; i++)
{
if (g_pFbxDX11[i])
{
delete g_pFbxDX11[i];
g_pFbxDX11[i] = nullptr;
}
}
if (g_pRS)
{
g_pRS->Release();
g_pRS = nullptr;
}
if (g_pvsFBXInstancing)
{
g_pvsFBX->Release();
g_pvsFBX = nullptr;
}
if (g_pvsFBX)
{
g_pvsFBX->Release();
g_pvsFBX = nullptr;
}
if (g_ppsFBX)
{
g_ppsFBX->Release();
g_ppsFBX = nullptr;
}
if (g_ppsFBX_skin)
{
g_ppsFBX_skin->Release();
g_ppsFBX_skin = nullptr;
}
if (g_pcBuffer)
{
g_pcBuffer->Release();
g_pcBuffer = nullptr;
}
}
//--------------------------------------------------------------------------------------
// Clean up the objects we've created
//--------------------------------------------------------------------------------------
void CleanupDevice()
{
if (g_pImmediateContext) g_pImmediateContext->ClearState();
if (g_pDepthStencilState) g_pDepthStencilState->Release();
if (g_pDepthStencil) g_pDepthStencil->Release();
if (g_pDepthStencilView) g_pDepthStencilView->Release();
if (g_pRenderTargetView) g_pRenderTargetView->Release();
if (g_pSwapChain) g_pSwapChain->Release();
if (g_pImmediateContext) g_pImmediateContext->Release();
if (g_pd3dDevice) g_pd3dDevice->Release();
}
//--------------------------------------------------------------------------------------
// Called every time the application receives a message
//--------------------------------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_KEYUP:
if (wParam == VK_F2)
{
g_bInstancing = !g_bInstancing;
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
//
void SetMatrix()
{
HRESULT hr = S_OK;
const uint32_t count = g_InstanceMAX;
const float offset = -(g_InstanceMAX*60.0f / 2.0f);
XMMATRIX mat;
D3D11_MAPPED_SUBRESOURCE MappedResource;
hr = g_pImmediateContext->Map(g_pTransformStructuredBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource);
SRVPerInstanceData* pSrvInstanceData = (SRVPerInstanceData*) MappedResource.pData;
for (uint32_t i = 0; i<count; i++)
{
mat = XMMatrixTranslation(0, 0, i*60.0f + offset);
pSrvInstanceData[i].mWorld = (mat);
}
g_pImmediateContext->Unmap(g_pTransformStructuredBuffer, 0);
}
//--------------------------------------------------------------------------------------
// Render a frame
//--------------------------------------------------------------------------------------
void Render()
{
RECT rc;
GetClientRect(g_hWnd, &rc);
UINT width = rc.right - rc.left;
UINT height = rc.bottom - rc.top;
int kval = 0;
// Initialize the world matrices
g_World = XMMatrixIdentity();
// Initialize the view matrix
XMVECTOR Eye = XMVectorSet(0.0f, 200.0f, -500.0f, 0.0f);
XMVECTOR At = XMVectorSet(0.0f, 150.0f, 0.0f, 0.0f);
XMVECTOR Up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
//---------------------------------------------------
//
//モデル確認用(雑)色々とおかしい所があるが
//まぁ確認はできるでしょう。
//
//
//機能概要:Ctrキーで左回転:Altキーで右回転
//
//---------------------------------------------------
if (GetKeyState(VK_ADD))
{
XMVECTOR Eye = XMVectorSet(0.0f, 150.0f, -350.0f, 0.0f);
}
if (GetKeyState(VK_SUBTRACT))
{
XMVECTOR Eye = XMVectorSet(0.0f, 150.0f, -350.0f, 0.0f);
}
if (GetKeyState(VK_NUMPAD2)) //テンキー2番 下
{
Eye = XMVectorSet(0.0f, 150.0f, -650.0f, 0.0f);
}
if (GetKeyState(VK_NUMPAD4)) //テンキー4番 左
{
Eye = XMVectorSet(300 + 150.0f, 150.0f, -350.0f, 0.0f);
}
if (GetKeyState(VK_NUMPAD6)) //テンキー6番 右
{
Eye = XMVectorSet(-300 - 150.0f, 150.0f, -350.0f, 0.0f);
}
if (GetKeyState(VK_NUMPAD8)) //テンキー8番 上
{
Eye = XMVectorSet(0.0f, 150.0f, 650.0f, 0.0f);
}
g_View = XMMatrixLookAtLH(Eye, At, Up);
// Initialize the projection matrix
g_Projection = XMMatrixPerspectiveFovLH(XM_PIDIV4, width / (FLOAT)height, 0.01f, 10000.0f);
// Update our time
static float t = 0.0f;
if (g_driverType == D3D_DRIVER_TYPE_REFERENCE)
{
if (GetKeyState(VK_MENU))
{
//t += (float)XM_PI * 0.0125f;
}
//if (GetKeyState(VK_CONTROL))
//{
// //t += (float)XM_PI * 0.0125f;
//}
}
else
{
static DWORD dwTimeStart = 0;
DWORD dwTimeCur = GetTickCount();
if (dwTimeStart == 0)
dwTimeStart = dwTimeCur;
if (GetKeyState(VK_MENU) < 0)
{
t = (dwTimeCur + dwTimeStart) / 1000.0f;
// Rotate cube around the origin
g_World = XMMatrixRotationY(-t);
}
else
{
g_World = g_World;
}
if (GetKeyState(VK_CONTROL) < 0)
{
t = (dwTimeCur - dwTimeStart) / 1000.0f;
// Rotate cube around the origin
g_World = XMMatrixRotationY(t);
}
}
//---------------------------------------------------------
//
// Clear the back buffer
//
float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; // red, green, blue, alpha
g_pImmediateContext->ClearRenderTargetView(g_pRenderTargetView, ClearColor);
//
// Clear the depth buffer to 1.0 (max depth)
//
g_pImmediateContext->ClearDepthStencilView(g_pDepthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);
float blendFactors[4] = { D3D11_BLEND_ZERO, D3D11_BLEND_ZERO, D3D11_BLEND_ZERO, D3D11_BLEND_ZERO };
g_pImmediateContext->RSSetState(g_pRS);
g_pImmediateContext->OMSetBlendState(g_pBlendState, blendFactors, 0xffffffff);
g_pImmediateContext->OMSetDepthStencilState(g_pDepthStencilState, 0);
g_pUserAnotation->BeginEvent(L"ModelDraw");
// モデルを順番に描画
for (DWORD i = 0; i < NUMBER_OF_MODELS; i++)
{
// FBX Modelのnode数を取得
size_t nodeCount = g_pFbxDX11[i]->GetNodeCount();
WCHAR wstr[256];
swprintf_s(wstr, L"Model0%d", i);
g_pUserAnotation->BeginEvent(wstr);
ID3D11VertexShader* pVS = g_bInstancing ? g_pvsFBXInstancing : g_pvsFBX;
g_pImmediateContext->VSSetShader(pVS, NULL, 0);
g_pImmediateContext->VSSetConstantBuffers(0, 1, &g_pcBuffer);
g_pImmediateContext->PSSetShader(g_ppsFBX_skin, NULL, 0);
g_pImmediateContext->PSSetShader(g_ppsFBX, NULL, 0);
// 全ノードを描画
for (size_t j = 0; j < nodeCount; j++)
{
int brcnt = 0;
XMMATRIX mLocal;
g_pFbxDX11[i]->GetNodeMatrix(j, &mLocal.r[0].m128_f32[0]); // このnodeのMatrix
D3D11_MAPPED_SUBRESOURCE MappedResource;
if (j == 0)
{
FBX_LOADER::MATERIAL_DATA material = g_pFbxDX11[i]->GetNodeMaterial(j);
g_pImmediateContext->Map(g_pcBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource);
SHADER_GLOBAL1 sg;
sg.mW = g_World;
sg.mWVP = XMMatrixTranspose(mLocal*g_World*g_View*g_Projection);
XMMatrixTranspose(sg.mWVP * sg.mWVP);
sg.vAmbient = material.ambient;
sg.vDiffuse = material.diffuse;
sg.vSpecular = material.specular;
memcpy_s(MappedResource.pData, MappedResource.RowPitch, (void*)&sg, sizeof(SHADER_GLOBAL1));
g_pImmediateContext->Unmap(g_pcBuffer, 0);
}
CBFBXMATRIX* cbFBX = (CBFBXMATRIX*)MappedResource.pData;
// 左手系
cbFBX->mWorld = (g_World);
cbFBX->mView = (g_View);
cbFBX->mProj = (g_Projection);
cbFBX->mWVP = XMMatrixTranspose(mLocal*g_World*g_View*g_Projection);
g_pImmediateContext->Unmap(g_pcBuffer, 0);
SetMatrix();
FBX_LOADER::MATERIAL_DATA material = g_pFbxDX11[i]->GetNodeMaterial(j);
if (material.pMaterialCb)
g_pImmediateContext->UpdateSubresource(material.pMaterialCb, 0, NULL, &material.materialConstantData, 0, 0);
g_pImmediateContext->VSSetShaderResources(0, 1, &g_pTransformSRV);
g_pImmediateContext->PSSetShaderResources(0, 1, &material.pSRV);
g_pImmediateContext->PSSetConstantBuffers(0, 1, &material.pMaterialCb);
g_pImmediateContext->PSSetSamplers (0, 1, &material.pSampler);
if (g_bInstancing)
g_pFbxDX11[i]->RenderNodeInstancing(g_pImmediateContext, j, g_InstanceMAX);
else
g_pFbxDX11[i]->RenderNode(g_pImmediateContext, j);
brcnt = boneifo->BoneNumReturn();
//フレームを進めたことにより変化したポーズ(ボーンの行列)をシェーダーに渡す
g_pImmediateContext->Map(g_pConstantBufferBone, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource);
SHADER_GLOBAL_BONES sg;
for (int i = 0; i < brcnt; i++)
{
XMMATRIX mat = boneifo->GetCurrentPoseMatrix(i);
XMMatrixTranspose(mat);
sg.mBone[i] = mat;
}
memcpy_s(MappedResource.pData, MappedResource.RowPitch, (void*)&sg, sizeof(SHADER_GLOBAL_BONES));
g_pImmediateContext->Unmap(g_pConstantBufferBone, 0);
g_pImmediateContext->PSSetConstantBuffers(2, 1, &g_pConstantBufferBone);
//g_pImmediateContext->VSSetConstantBuffers(2, 1, &g_pConstantBufferBone);
//使用するシェーダーの登録 (effectの”テクニック”に相当)
//g_pImmediateContext->VSSetShader(g_pvsFBX, NULL, 0);
//g_pImmediateContext->PSSetShader(g_ppsFBX_skin, NULL, 0);
g_pUserAnotation->EndEvent();
}
/* static int iFrame = 24;
iFrame++;*/
// boneifo->Get_Bone_frame();
//メッシュをレンダー
//FbxVector4* fvec = nullptr;
static float fAngle = 0;
fAngle += 0.0002f;
XMMATRIX* mWorld = nullptr;
//XMMatrixRotationY(fAngle);
g_pUserAnotation->EndEvent();
g_pUserAnotation->BeginEvent(L"RenderText");
// Text
//WCHAR wstr[512];
g_pSpriteBatch->Begin();
g_pFont->DrawString(g_pSpriteBatch, L"FBX Loader : F2 Change Render Mode", XMFLOAT2(0, 0), DirectX::Colors::Yellow, 0, XMFLOAT2(0, 0), 0.5f);
if (g_bInstancing)
swprintf_s(wstr, L"Render Mode: Instancing");
else
swprintf_s(wstr, L"Render Mode: Single Draw");
g_pFont->DrawString(g_pSpriteBatch, wstr, XMFLOAT2(0, 16), DirectX::Colors::Yellow, 0, XMFLOAT2(0, 0), 0.5f);
g_pSpriteBatch->End();
g_pUserAnotation->EndEvent();
g_pImmediateContext->VSSetShader(NULL, NULL, 0);
g_pImmediateContext->PSSetShader(NULL, NULL, 0);
//g_pImmediateContext->PSSetShader(NULL, NULL, 0);
//g_pImmediateContext->PSSetShader(g_ppsFBX_skin, NULL, 0);
//
// Present our back buffer to our front buffer
//
// boneifo->Render(mWorld);
//-----------------------
//
//ボーンの初期姿勢を取る
//
//-----------------------
bool attitubleSW = false;
if (attitubleSW = false)
{
boneifo->GetInitial_attitude();
attitubleSW = true;
}
//-------------------------
boneifo->GetCurrentPoseMatrix(0);
//boneinfo_to_BONEp->mNewPose[2].mData[1];
//mWorld = XMMatrixRotationY(fAngle);
g_pSwapChain->Present(0, 0);
}
}
#include <vector>
#include <set>
#include <string>
#include "BoneInfo.h"
#pragma warning(disable : 4996)
using namespace DirectX;
DWORD m_dwNumVert = NULL;
DWORD m_dwNumUV = NULL;
int iNumBone = 0;
FbxCluster** ppCluster;
float angle = 1.0f;
BoneInfo::BoneInfo()
{
//mesh = nullptr;
//iNumVertex = 0;
}
BoneInfo::~BoneInfo()
{
mesh->Reset();
}
//-----------------------------------
//
//FbxMatrixをXMMATRIXにキャストする関数(これ重要)
//作成者:
//作成日1月26日
//-----------------------------------
XMMATRIX BoneInfo::Convert_from_FbxMatrix_to_XMMATRIX(FbxAMatrix& pSrc)
{
XMMATRIX mmx;
mmx =
XMMatrixSet(
static_cast<FLOAT>(pSrc.Get(0, 0)), static_cast<FLOAT>(pSrc.Get(0, 1)), static_cast<FLOAT>(pSrc.Get(0, 2)), static_cast<FLOAT>(pSrc.Get(0, 3)),
static_cast<FLOAT>(pSrc.Get(1, 0)), static_cast<FLOAT>(pSrc.Get(1, 1)), static_cast<FLOAT>(pSrc.Get(1, 2)), static_cast<FLOAT>(pSrc.Get(1, 3)),
static_cast<FLOAT>(pSrc.Get(2, 0)), static_cast<FLOAT>(pSrc.Get(2, 1)), static_cast<FLOAT>(pSrc.Get(2, 2)), static_cast<FLOAT>(pSrc.Get(2, 3)),
static_cast<FLOAT>(pSrc.Get(3, 0)), static_cast<FLOAT>(pSrc.Get(3, 1)), static_cast<FLOAT>(pSrc.Get(3, 2)), static_cast<FLOAT>(pSrc.Get(3, 3)));
return mmx;
}
//-----------------------------------------------------------
//機能概要:クラスター(ボーン一本)の情報を取り出す
//追加日2014/12/18
//
//-----------------------------------------------------------
void BoneInfo::GetCluster(int vxCnt, FbxMesh* lMesh, FBX_VERTEX* pvVB)
{
m_dwNumVert = lMesh->GetControlPointsCount();
//一時的なメモリ確保(頂点バッファとインデックスバッファ)
pvVB = new FBX_VERTEX[m_dwNumVert];
//FBXから抽出すべき情報は、頂点ごとのボーンインデックス、頂点ごとのボーンウェイト、バインド行列、ポーズ行列 の4項目
int* piReadCount = new int[vxCnt];
ZeroMemory(piReadCount, sizeof(int)*vxCnt);
//FbxSkin* pSkinInfo = static_cast<FbxSkin*>(lMesh->GetDeformer(0, FbxDeformer::eSkin));
FbxSkin* pSkinInfo = nullptr;
//
int DeformerCount = lMesh->GetDeformerCount(FbxDeformer::eSkin);
for (int i = 0; i < DeformerCount; ++i)
{
pSkinInfo = static_cast<FbxSkin*>(lMesh->GetDeformer(i, FbxDeformer::eSkin));
}
if (DeformerCount == 1)
{
//ボーンを得る
iNumBone = pSkinInfo->GetClusterCount();
FbxCluster* clusterTmp = nullptr;
ppCluster = new FbxCluster*[iNumBone];
for (int ib = 0; ib < iNumBone; ib++)
{
ppCluster[ib] = pSkinInfo->GetCluster(ib);
}
//それぞれのボーンに影響を受ける頂点を調べる そこから逆に、頂点ベースでボーンインデックス・重みを整頓する
for (int inb = 0; inb < iNumBone; inb++)
{
int iNumIndex = ppCluster[inb]->GetControlPointIndicesCount();//このボーンに影響を受ける頂点数
int* piIndex = ppCluster[inb]->GetControlPointIndices();
double* pdWeight = ppCluster[inb]->GetControlPointWeights();
//頂点側からインデックスをたどって、頂点サイドで整理する
for (int k = 0; k < iNumIndex; k++)
{
for (int m = 0; m < 4; m++)//FBXやCGソフトがボーン4本以内とは限らない。5本以上の場合は、重みの大きい順に4本に絞る
{
int tmpk = k;
if (pdWeight[tmpk] > pvVB[piIndex[tmpk]].bBoneWeight[m])
{
pvVB[piIndex[tmpk]].bBoneIndex [m] = inb;
pvVB[piIndex[tmpk]].bBoneWeight[m] = pdWeight[tmpk];
break;
}
}
if (piReadCount[piIndex[k]] < 3)
{
piReadCount[piIndex[k]]++;
}
}
}
//
//ボーンを生成
int m_iNumBone = iNumBone;
//ボーン構造体アクセス用ポインター
BONE * m_BoneArray = new BONE[iNumBone];
for (int i = 0; i < m_iNumBone; i++)
{
FbxAMatrix mat;
ppCluster[i]->GetTransformLinkMatrix(mat);
for (int x = 0; x < 4; x++)
{
for (int y = 0; y < 4; y++)
{
m_BoneArray->mBindPose[i] = mat.Get(y, x);
}
}
}
//delete
delete[] piReadCount;
}
}
//-------------------------------------------------------------
//-------------------------------------------
//機能概要:ボーン数を返す
//追加日2014/12/18
//
//-------------------------------------------
int BoneInfo::BoneNumReturn()
{
int bnum = iNumBone;
return bnum;
}
//-------------------------------------------
//機能概要:ボーンの初期姿勢を取得する
//追加日2014/12/18
//
//-------------------------------------------
void BoneInfo::GetInitial_attitude()
{
FbxAMatrix initMat;
cluster->GetTransformLinkMatrix(initMat);
}
//-------------------------------------------
//-------------------------------------------
//機能概要:○○フレームの骨の姿勢を取得する 手法1(たぶん使わないかな)
//追加日2014/12/18
//
//-------------------------------------------
void BoneInfo::Get_Bone_frame()
{
FbxAMatrix initMat;
cluster->GetTransformLinkMatrix(initMat);
//int frameNum = 24; // フレーム数(ここでは適当です)
//FbxTime start, period; // スタート時間と単位時間
//for (int i = 0; i < frameNum; ++i) {
// FbxMatrix mat;
// FbxTime time = start + period * i;
// mat = cluster->GetLink()->EvaluateGlobalTransform(time);
//}
}
//-------------------------------------------
//機能概要:○○フレームの骨の姿勢を取得する 手法2
//追加日2014/12/18
//
//-------------------------------------------
void BoneInfo::SetNewPoseMatrices(int frame)
{
int i;
FbxTime time;
frame = 24;
BONE * m_BoneArray = new BONE[iNumBone];
time.SetTime(0, 0, 0, frame, 0, FbxTime::eFrames30);//30フレーム/秒 と推定 厳密には状況ごとに調べる必要あり
for (i = 0; i < iNumBone; i++)
{
FbxAMatrix mat = ppCluster[i]->GetLink()->EvaluateGlobalTransform(time);
for (int x = 0; x < 4; x++)
{
for (int y = 0; y < 4; y++)
{
m_BoneArray->mBindPose[i] = mat.Get(y, x);
}
}
}
}
//-------------------------------------------
//機能概要:ボーン行列を変化させる(後にキネクトの情報とリンクさせる形に変える)
//追加日2015/01/22
//
//-------------------------------------------
void BoneInfo::TransformBorneMatrix()
{
//BONE * m_BoneArray = new BONE[iNumBone];
}
//-------------------------------------------
//機能概要:ボーン行列を返す
//追加日2015/01/22
//
//-------------------------------------------
XMMATRIX BoneInfo::GetCurrentPoseMatrix(int index)
{
BONE * m_BoneArray = new BONE[iNumBone];
FbxAMatrix newMat = m_BoneArray[index].mNewPose;
XMMATRIX invmat = Convert_from_FbxMatrix_to_XMMATRIX(m_BoneArray[index].mBindPose);
XMVECTOR * inv = nullptr;
/*static float fAngle = 0;
fAngle +=1.0f;
XMMATRIX* mWorld = nullptr;
*/
//Convert_from_FbxMatrix_to_XMMATRIX(m_BoneArray[index].mNewPose) = XMMatrixRotationY(fAngle);
XMMatrixInverse(inv,invmat);
XMMATRIX ret = invmat * Convert_from_FbxMatrix_to_XMMATRIX(m_BoneArray[index].mNewPose);//バインドポーズの逆行列とフレーム姿勢行列をかける。なお、バインドポーズ自体が既に逆行列であるとする考えもある。(FBXの場合は違うが)
angle += 1.0f;
if (angle == 10.0f)
{
angle = 0.0f;
}
ret = XMMatrixRotationX(angle);
return ret;
}
#include "BoneInfo.h"
#include "CFBXLoader.h"
#include "SkeltonAdminister.h"
#include <string.h>
#include <tchar.h>
BoneInfo * binfo;
SkeletonInfo * sinfo;
FBXSkeletonAnalizer * finfo;
FBX_VERTEX* pvVB = nullptr;
namespace FBX_LOADER
{
CFBXLoader::CFBXLoader()
{
mSdkManager = nullptr;
mScene = nullptr;
}
CFBXLoader::~CFBXLoader()
{
Release();
}
//
void CFBXLoader::Release()
{
m_meshNodeArray.clear();
if(mImporter)
{
mImporter->Destroy();
mImporter = nullptr;
}
if(mScene)
{
mScene->Destroy();
mScene = nullptr;
}
if( mSdkManager )
{
mSdkManager->Destroy();
mSdkManager = nullptr;
}
}
HRESULT CFBXLoader::LoadFBX(const char* filename, const eAXIS_SYSTEM axis)
{
if(!filename)
return E_FAIL;
HRESULT hr = S_OK;
InitializeSdkObjects( mSdkManager, mScene );
if(!mSdkManager)
return E_FAIL;
// インポータ作成
int lFileFormat = -1;
mImporter = FbxImporter::Create(mSdkManager,"");
if (!mSdkManager->GetIOPluginRegistry()->DetectReaderFileFormat(filename, lFileFormat) )
{
// Unrecognizable file format. Try to fall back to FbxImporter::eFBX_BINARY
lFileFormat = mSdkManager->GetIOPluginRegistry()->FindReaderIDByDescription( "FBX binary (*.fbx)" );;
}
// Initialize the importer by providing a filename.
if(!mImporter || mImporter->Initialize(filename, lFileFormat) == false)
return E_FAIL;
//
if( !mImporter || mImporter->Import(mScene) == false )
return E_FAIL;
FbxAxisSystem OurAxisSystem = FbxAxisSystem::DirectX;
if(axis==eAXIS_OPENGL)
OurAxisSystem = FbxAxisSystem::OpenGL;
// DirectX系
FbxAxisSystem SceneAxisSystem = mScene->GetGlobalSettings().GetAxisSystem();
if(SceneAxisSystem != OurAxisSystem)
{
FbxAxisSystem::DirectX.ConvertScene(mScene);
}
// 単位系の統一
// 不要でもいいかも
FbxSystemUnit SceneSystemUnit = mScene->GetGlobalSettings().GetSystemUnit();
if( SceneSystemUnit.GetScaleFactor() != 1.0 )
{
// センチメーター単位にコンバートする
FbxSystemUnit::cm.ConvertScene( mScene );
}
// 三角形化(三角形以外のデータでもコレで安心)
TriangulateRecursive(mScene->GetRootNode());
Setup();
return hr;
}
//
void CFBXLoader::InitializeSdkObjects(FbxManager*& pManager, FbxScene*& pScene)
{
//The first thing to do is to create the FBX Manager which is the object allocator for almost all the classes in the SDK
pManager = FbxManager::Create();
if( !pManager )
{
FBXSDK_printf("Error: Unable to create FBX Manager!\n");
exit(1);
}
else FBXSDK_printf("Autodesk FBX SDK version %s\n", pManager->GetVersion());
//Create an IOSettings object. This object holds all import/export settings.
FbxIOSettings* ios = FbxIOSettings::Create(pManager, IOSROOT);
pManager->SetIOSettings(ios);
//Load plugins from the executable directory (optional)
FbxString lPath = FbxGetApplicationDirectory();
pManager->LoadPluginsDirectory(lPath.Buffer());
//Create an FBX scene. This object holds most objects imported/exported from/to files.
pScene = FbxScene::Create(pManager, "My Scene");
if( !pScene )
{
FBXSDK_printf("Error: Unable to create FBX scene!\n");
exit(1);
}
}
// 三角形化
void CFBXLoader::TriangulateRecursive(FbxNode* pNode)
{
FbxNodeAttribute* lNodeAttribute = pNode->GetNodeAttribute();
if (lNodeAttribute)
{
if (lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eSkeleton)
{
const FbxSkeleton* skeleton = (const FbxSkeleton*)(lNodeAttribute);
finfo->analize(pNode, skeleton);
}
}
if (lNodeAttribute)
{
if (lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eMesh ||
lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eNurbs ||
lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eNurbsSurface ||
lNodeAttribute->GetAttributeType() == FbxNodeAttribute::ePatch)
{
FbxGeometryConverter lConverter(pNode->GetFbxManager());
// これでどんな形状も三角形化
#if 0
lConverter.TriangulateInPlace(pNode); // 古い手法
#endif // 0
lConverter.Triangulate( mScene, true );
}
}
const int lChildCount = pNode->GetChildCount();
for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex)
{
// 子ノードを探索
TriangulateRecursive(pNode->GetChild(lChildIndex));
}
}
//
FbxNode& CFBXLoader::GetRootNode()
{
return *mScene->GetRootNode();
}
void CFBXLoader::Setup()
{
// RootNodeから探索していく
if(mScene->GetRootNode())
{
SetupNode(mScene->GetRootNode(), "null");
}
}
void CFBXLoader::SetupNode(FbxNode* pNode, std::string parentName)
{
int Bonenum = 0;
int CulusterCnt = 0;
FbxMesh* lMesh = pNode->GetMesh();
FbxSkin* lSkin = nullptr;
//CulusterCnt = lSkin->GetClusterCount();
if(!pNode)
return ;
FBX_MESH_NODE meshNode;
HRESULT vertexCheck = S_OK;
meshNode.name = pNode->GetName();
meshNode.parentName = parentName;
ZeroMemory( &meshNode.elements, sizeof(MESH_ELEMENTS) );
if(lMesh)
{
int lVertexCount = lMesh->GetControlPointsCount();
//m_dwNumUV = lMesh->GetTextureUVCount();
//if (m_dwNumVert<m_dwNumUV)//本サンプルではUVの数だけ頂点が必要
//{
// //共有頂点等で、頂点数が足りない時
// MessageBox(0, L"UVの数だけ頂点が必要です(UVを置く場所が必要です)テクスチャーは正しく貼られないと思われます", NULL, MB_OK);
//}
if (lVertexCount > 0)
{
//スキンを取得
// 頂点があるならノードにコピー
CopyVertexData(lMesh, &meshNode);
const int lChildCount = pNode->GetChildCount();
for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex)
{
// 子ノードを探索
TriangulateRecursive(pNode->GetChild(lChildIndex));
}
}
binfo->GetCluster(lVertexCount, lMesh, pvVB);
}
// マテリアル
const int lMaterialCount = pNode->GetMaterialCount();
for(int i=0;i<lMaterialCount;i++)
{
FbxSurfaceMaterial* mat = pNode->GetMaterial(i);
if(!mat)
continue;
FBX_MATERIAL_NODE destMat;
CopyMatrialData(mat, &destMat);
meshNode.m_materialArray.push_back(destMat);
}
//
ComputeNodeMatrix(pNode, &meshNode);
m_meshNodeArray.push_back(meshNode);
const int lCount = pNode->GetChildCount();
for (int i = 0; i < lCount; i++)
{
SetupNode(pNode->GetChild(i), meshNode.name);
}
}
//
void CFBXLoader::SetFbxColor(FBX_MATRIAL_ELEMENT& destColor,const FbxDouble3 srcColor)
{
destColor.a = 1.0f;
destColor.r = static_cast<float>(srcColor[0]);
destColor.g = static_cast<float>(srcColor[1]);
destColor.b = static_cast<float>(srcColor[2]);
}
//
FbxDouble3 CFBXLoader::GetMaterialProperty(
const FbxSurfaceMaterial * pMaterial,
const char * pPropertyName,
const char * pFactorPropertyName,
FBX_MATRIAL_ELEMENT* pElement)
{
pElement->type = FBX_MATRIAL_ELEMENT::ELEMENT_NONE;
FbxDouble3 lResult(0, 0, 0);
const FbxProperty lProperty = pMaterial->FindProperty(pPropertyName);
const FbxProperty lFactorProperty = pMaterial->FindProperty(pFactorPropertyName);
if (lProperty.IsValid() && lFactorProperty.IsValid())
{
lResult = lProperty.Get<FbxDouble3>();
double lFactor = lFactorProperty.Get<FbxDouble>();
if (lFactor != 1)
{
lResult[0] *= lFactor;
lResult[1] *= lFactor;
lResult[2] *= lFactor;
}
pElement->type = FBX_MATRIAL_ELEMENT::ELEMENT_COLOR;
}
if (lProperty.IsValid())
{
int existTextureCount = 0;
const int lTextureCount = lProperty.GetSrcObjectCount<FbxFileTexture>();
for(int i=0;i<lTextureCount;i++)
{
FbxFileTexture* lFileTexture = lProperty.GetSrcObject<FbxFileTexture>(i);
if(!lFileTexture)
continue;
FbxString uvsetName = lFileTexture->UVSet.Get();
std::string uvSetString = uvsetName.Buffer();
std::string filepath = lFileTexture->GetFileName();
pElement->textureSetArray[uvSetString].push_back(filepath);
existTextureCount++;
}
const int lLayeredTextureCount = lProperty.GetSrcObjectCount<FbxLayeredTexture>();
for(int i=0;i<lLayeredTextureCount;i++)
{
FbxLayeredTexture* lLayeredTexture = lProperty.GetSrcObject<FbxLayeredTexture>(i);
const int lTextureFileCount = lLayeredTexture->GetSrcObjectCount<FbxFileTexture>();
for(int j=0;j<lTextureFileCount;j++)
{
FbxFileTexture* lFileTexture = lLayeredTexture->GetSrcObject<FbxFileTexture>(j);
if(!lFileTexture)
continue;
FbxString uvsetName = lFileTexture->UVSet.Get();
std::string uvSetString = uvsetName.Buffer();
std::string filepath = lFileTexture->GetFileName();
pElement->textureSetArray[uvSetString].push_back(filepath);
existTextureCount++;
}
}
if(existTextureCount > 0)
{
if(pElement->type == FBX_MATRIAL_ELEMENT::ELEMENT_COLOR)
pElement->type = FBX_MATRIAL_ELEMENT::ELEMENT_BOTH;
else
pElement->type = FBX_MATRIAL_ELEMENT::ELEMENT_TEXTURE;
}
}
return lResult;
}
//
void CFBXLoader::CopyMatrialData(FbxSurfaceMaterial* mat, FBX_MATERIAL_NODE* destMat)
{
if(!mat)
return ;
if ( mat->GetClassId().Is( FbxSurfaceLambert::ClassId ) )
{
destMat->type = FBX_MATERIAL_NODE::MATERIAL_LAMBERT;
}
else if ( mat->GetClassId().Is( FbxSurfacePhong::ClassId ) )
{
destMat->type = FBX_MATERIAL_NODE::MATERIAL_PHONG;
}
const FbxDouble3 lEmissive = GetMaterialProperty(mat,
FbxSurfaceMaterial::sEmissive, FbxSurfaceMaterial::sEmissiveFactor, &destMat->emmisive);
SetFbxColor(destMat->emmisive, lEmissive );
const FbxDouble3 lAmbient = GetMaterialProperty(mat,
FbxSurfaceMaterial::sAmbient, FbxSurfaceMaterial::sAmbientFactor, &destMat->ambient);
SetFbxColor(destMat->ambient, lAmbient );
const FbxDouble3 lDiffuse = GetMaterialProperty(mat,
FbxSurfaceMaterial::sDiffuse, FbxSurfaceMaterial::sDiffuseFactor, &destMat->diffuse);
SetFbxColor(destMat->diffuse, lDiffuse );
const FbxDouble3 lSpecular = GetMaterialProperty(mat,
FbxSurfaceMaterial::sSpecular, FbxSurfaceMaterial::sSpecularFactor, &destMat->specular);
SetFbxColor(destMat->specular, lSpecular );
//
FbxProperty lTransparencyFactorProperty = mat->FindProperty(FbxSurfaceMaterial::sTransparencyFactor);
if(lTransparencyFactorProperty.IsValid())
{
double lTransparencyFactor = lTransparencyFactorProperty.Get<FbxDouble>();
destMat->TransparencyFactor = static_cast<float>(lTransparencyFactor);
}
// Specular Power
FbxProperty lShininessProperty = mat->FindProperty(FbxSurfaceMaterial::sShininess);
if (lShininessProperty.IsValid())
{
double lShininess = lShininessProperty.Get<FbxDouble>();
destMat->shininess = static_cast<float>(lShininess);
}
}
//
void CFBXLoader::ComputeNodeMatrix(FbxNode* pNode, FBX_MESH_NODE* meshNode)
{
if(!pNode || !meshNode)
{
return ;
}
FbxAnimEvaluator* lEvaluator = mScene->GetAnimationEvaluator();
FbxMatrix lGlobal;
lGlobal.SetIdentity();
if(pNode != mScene->GetRootNode())
{
lGlobal= lEvaluator->GetNodeGlobalTransform(pNode);
FBXMatrixToFloat16( &lGlobal, meshNode->mat4x4 );
}
else
{
FBXMatrixToFloat16( &lGlobal, meshNode->mat4x4 );
}
}
//
void CFBXLoader::CopyVertexData(FbxMesh* pMesh, FBX_MESH_NODE* meshNode)
{
if(!pMesh)
return ;
int lPolygonCount = pMesh->GetPolygonCount();
FbxVector4 pos, nor;
meshNode->elements.numPosition = 1;
meshNode->elements.numNormal = 1;
unsigned int indx = 0;
for(int i=0;i<lPolygonCount;i++)
{
// ポリゴン内の頂点数(一応、三角形化してるので3点のはずだがチェック)
int lPolygonsize = pMesh->GetPolygonSize(i);
for(int pol=0;pol<lPolygonsize;pol++)
{
int index = pMesh->GetPolygonVertex(i, pol);
meshNode->indexArray.push_back(indx);
pos = pMesh->GetControlPointAt(index);
pMesh->GetPolygonVertexNormal(i,pol,nor);
meshNode->m_positionArray.push_back( pos );
meshNode->m_normalArray.push_back( nor );
++indx;
}
/*if (lVertexCount == lMesh->GetControlPointsCount)
{
}
else
{
MessageBox(nullptr, _T("頂点数が一致しません"), nullptr, MB_OK);
}*/
}
// UV処理(UVは2つ以上ある場合があるので別処理)
FbxStringList uvsetName;
pMesh->GetUVSetNames(uvsetName);
int numUVSet = uvsetName.GetCount();
meshNode->elements.numUVSet = numUVSet;
bool unmapped = false;
for(int uv=0;uv<numUVSet;uv++)
{
meshNode->uvsetID[uvsetName.GetStringAt(uv)] = uv;
for(int i=0;i<lPolygonCount;i++)
{
int lPolygonsize = pMesh->GetPolygonSize(i);
for(int pol=0;pol<lPolygonsize;pol++)
{
FbxString name = uvsetName.GetStringAt(uv);
FbxVector2 texCoord;
pMesh->GetPolygonVertexUV( i, pol, name, texCoord, unmapped);
meshNode->m_texcoordArray.push_back(texCoord);
}
}
}
}
FBX_MESH_NODE& CFBXLoader::GetNode(const unsigned int id)
{
return m_meshNodeArray[id];
}
} // FBX_LOADER
よろしくお願いします。