Esempio n. 1
0
//! Loads the  model from a file.[TODO]
void SkinnedModel::Load(string filename)
{
	ifstream fin(filename, ios::binary | ios::in);

	string ignore;
	int numMeshes;
	fin >> ignore >> numMeshes;

	for(int i =  0; i < numMeshes; i++)
	{
		SkinnedMesh* mesh = new SkinnedMesh();
		mesh->Load(fin);
		AddMesh(mesh);
	}

	// The space after the last index.
	fin >> ignore;	

	// Make sure to start loading animation data from the right place.
	// [NOTE] After some investigation it seems like it should be at the first '\f' character.
	char x = fin.peek(); 
	while(x != '\f') {
		fin >> ignore;	
		x = fin.peek(); 
	}

	mAnimator = new SceneAnimator();
	mAnimator->Load(fin);

	fin.close();
}
Esempio n. 2
0
void Application::Render() {
    if (!m_deviceLost) {
        try {
            //Create Matrices
            D3DXMATRIX identity, view, proj, shadow;
            D3DXMatrixIdentity(&identity);
            D3DXMatrixLookAtLH(&view, &D3DXVECTOR3(cos(m_time) * m_radius, m_height, sin(m_time) * m_radius), &D3DXVECTOR3(0.0f, 1.0f, 0.0f), &D3DXVECTOR3(0.0f, 1.0f, 0.0f));
            D3DXMatrixPerspectiveFovLH(&proj, D3DX_PI / 4.0f, (float)WINDOW_WIDTH / (float)WINDOW_HEIGHT, 1.0f, 1000.0f);
            D3DXPLANE ground(0.0f, 1.0f, 0.0f, 0.0f);
            D3DXVECTOR4 lightPos(-50.0f, 75.0f, -150.0f, 0.0f); // 点光源, 光照计算在 shader 中
            D3DXMatrixShadow(&shadow, &lightPos, &ground);

            g_pDevice->SetTransform(D3DTS_WORLD, &identity);
            g_pDevice->SetTransform(D3DTS_VIEW, &view);
            g_pDevice->SetTransform(D3DTS_PROJECTION, &proj);

            // Clear the viewport
            g_pDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0xff, 0x40, 0x40, 0x40), 1.0f, 0);

            // Begin the scene
            if (SUCCEEDED(g_pDevice->BeginScene())) {
                //Render Drone
                {
                    g_pEffect->SetMatrix("matW", &identity);
                    g_pEffect->SetMatrix("matVP", &(view * proj));
                    g_pEffect->SetVector("lightPos", &lightPos);

                    m_drone.Render(NULL);
                }

                if (KeyDown(VK_SPACE)) {
                    g_pDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0xff, 0x40, 0x40, 0x40), 1.0f, 0);
                    m_drone.RenderSkeleton(NULL, NULL, identity);
                }

                RECT rc = {10, 10, 0, 0};
                g_pFont->DrawText(NULL, "Press Space to Toggle Skeleton", -1, &rc, DT_LEFT | DT_TOP | DT_NOCLIP, D3DCOLOR_ARGB(0xff, 0, 0x80, 0));

                // End the scene.
                g_pDevice->EndScene();
                g_pDevice->Present(0, 0, 0, 0);
            }
        }
        catch(...) {
            g_debug << "Error in Application::Render() \n";
        }
    }
}
Esempio n. 3
0
void Application::Render() {
    if (!m_deviceLost) {
        try {
            //Create Matrices
            D3DXMATRIX identity, world, view, proj;
            D3DXMatrixIdentity(&identity);
            D3DXMatrixLookAtLH(&view, &D3DXVECTOR3(0.0f, 1.5f, -3.0f), &D3DXVECTOR3(0.0f, 1.0f, 0.0f), &D3DXVECTOR3(0.0f, 1.0f, 0.0f));
            D3DXMatrixPerspectiveFovLH(&proj, D3DX_PI / 4.0f, (float)WINDOW_WIDTH / (float)WINDOW_HEIGHT, 1.0f, 1000.0f);
            D3DXVECTOR4 lightPos(-50.0f, 75.0f, -150.0f, 0.0f);

            g_pDevice->SetTransform(D3DTS_WORLD, &identity);
            g_pDevice->SetTransform(D3DTS_VIEW, &view);
            g_pDevice->SetTransform(D3DTS_PROJECTION, &proj);

            // Clear the viewport
            g_pDevice->Clear(0L, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0L);

            // Begin the scene
            if (SUCCEEDED(g_pDevice->BeginScene())) {
                //Render Drone
                {
                    g_pEffect->SetMatrix("matW", &identity);
                    g_pEffect->SetMatrix("matVP", &(view * proj));
                    g_pEffect->SetVector("lightPos", &lightPos);

                    //Update skeletal animation
                    m_drone.SetPose(identity);

                    //Update IK
                    if (m_pIK) {
                        m_pIK->UpdateHeadIK();
                        m_pIK->UpdateArmIK();
                    }

                    m_drone.Render(NULL);
                }

                // End the scene.
                g_pDevice->EndScene();
                g_pDevice->Present(0, 0, 0, 0);
            }
        }
        catch(...) {
            g_debug << "Error in Application::Render() \n";
        }
    }
}
Esempio n. 4
0
void Destroy()
{
    axis.Destroy();
    cube.Destroy();
    skinMesh.Destroy();

    GraphicsDevice::ReleaseInstance();
}
Esempio n. 5
0
void Render( unsigned int _dt )
{
    //DebugPrintf("Frame count: %d\n", FrameCount);
    HRESULT hr = S_OK;

    //清除视区
    pGDevice->Clear();

    //开始场景
    pGDevice->BeginScene();

    //Render skinmesh
    skinMesh.Render(pGDevice->m_pD3DDevice, identity, view, proj, eyePoint);

    //Render cube
    {
        pGDevice->SetViewport(pGDevice->mCubeViewport);
        cube.SetConstants(pGDevice->m_pD3DDevice, identity, fixedView, pGDevice->m_matCubeProj);
        cube.Draw(pGDevice->m_pD3DDevice);
        if (hovering || moving)
        {
            //将cube所在的viewport的位置(top-left)处的屏幕坐标变换到(0,0)
            D3DXVECTOR2 tmp(currentCursorPos);
            tmp.x -= pGDevice->mCubeViewport.X;
            tmp.y -= pGDevice->mCubeViewport.Y;
            cube.DrawRay(tmp, identity, fixedView, pGDevice->m_matCubeProj);
        }
        pGDevice->ResetViewport();
    }

    //Render axis
    {
        pGDevice->SetViewport(pGDevice->mAxisViewport);
        axis.SetConstants(pGDevice->m_pD3DDevice, identity, fixedView, pGDevice->m_matAxisProj);
        axis.Draw(pGDevice->m_pD3DDevice);
        //axis.DrawXYZ();
        pGDevice->ResetViewport();
	}

    //结束场景
    pGDevice->EndScene();

    //显示场景
    pGDevice->Present();
}
Esempio n. 6
0
void Update( unsigned int _dt )
{
    //Update camera    
    D3DXMatrixLookAtLH(&view, &eyePoint, &lookAt, &up);
    D3DXMatrixLookAtLH(&fixedView, &fixedEyePoint, &fixedLookAt, &fixedUp);
    cube.Update(currentCursorPos, identity, fixedView, pGDevice->m_matCubeProj);
    if (dragging)
    {
        //拖动时进行旋转
        D3DXVECTOR2 mousePosDetla(currentCursorPos-lastCursorPos);
        RotateCameraHorizontally(D3DX_PI/50*mousePosDetla.x);
        RotateCameraVertically(D3DX_PI/50*mousePosDetla.y);
    }
    axis.Update();
    //axis.UpdateXYZ(fixedEyePoint);
    
    skinMesh.Update(identity, _dt);
}
Esempio n. 7
0
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
    hInst = hInstance; // 将实例句柄存储在全局变量中
    
    //创建并将主窗口句柄存储在全局变量中
    hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
       CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
    
    if (!hWnd)
    {
       return FALSE;
    }
    
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);


    /*
     timer
    */
    //创建WaitableTimer
    HTimer = CreateWaitableTimer(NULL,FALSE,NULL);
    DebugAssert(NULL!=HTimer, "CreateWaitableTimer 失败: %d", GetLastError());
    //初始化WaitableTimer
    LARGE_INTEGER liDueTime;
    liDueTime.QuadPart = -1i64;   //1秒后开始计时
    SetWaitableTimer(HTimer, &liDueTime, 100, NULL, NULL, 0);  //周期200ms = 0.2s
    FrameCount = 0;

    /*
        GraphicsDevice
    */
    pGDevice = GraphicsDevice::getInstance(hWnd);
    pGDevice->BuildViewports();
    /*
        Camera
    */
    InitCamera();
    cube.SetVertexData(0);
    cube.Create(pGDevice->m_pD3DDevice);
    /*
        Axis
    */
	axis.SetVertexData(0);  //参数实际上不起作用 TODO: 改进设计
    axis.Create(pGDevice->m_pD3DDevice);
    //axis.CreateXYZ(pGDevice->m_pD3DDevice);
    //axis.UpdateXYZ(fixedEyePoint);
    /*
        读取fbx,加载Skinned mesh
    */
    // 获取输出文件路径 测试用
    char fileSrc[MAX_PATH];
    GetTestFileName(fileSrc);
    skinMesh.Load(fileSrc, pGDevice->m_pD3DDevice);
    /*
        Matrix
    */
    D3DXMatrixIdentity(&identity);    
    D3DXMatrixPerspectiveFovLH(&proj, D3DX_PI / 4.0f,
        (float)pGDevice->mDefaultViewport.Width / (float)pGDevice->mDefaultViewport.Height, 1.0f, 1000.0f);    
    return TRUE;
}
Esempio n. 8
0
HRESULT Application::Init(HINSTANCE hInstance, bool windowed) {
    g_debug << "Application Started \n";

    //Create Window Class
    WNDCLASS wc;
    memset(&wc, 0, sizeof(WNDCLASS));
    wc.style         = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc   = (WNDPROC)WndProc;
    wc.hInstance     = hInstance;
    wc.lpszClassName = "D3DWND";

    RECT rc = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT};
    AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, false);

    //Register Class and Create new Window
    RegisterClass(&wc);
    m_mainWindow = ::CreateWindow("D3DWND", "Character Animation with Direct3D: Example 3.3", WS_OVERLAPPEDWINDOW, 0, 0, rc.right - rc.left, rc.bottom - rc.top, 0, 0, hInstance, 0);
    SetCursor(NULL);
    ::ShowWindow(m_mainWindow, SW_SHOW);
    ::UpdateWindow(m_mainWindow);

    //Create IDirect3D9 Interface
    IDirect3D9* d3d9 = Direct3DCreate9(D3D_SDK_VERSION);

    if (d3d9 == NULL) {
        g_debug << "Direct3DCreate9() - FAILED \n";
        return E_FAIL;
    }

    //Check that the Device supports what we need from it
    D3DCAPS9 caps;
    d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);

    //Check vertex & pixelshader versions
    if (caps.VertexShaderVersion < D3DVS_VERSION(2, 0) || caps.PixelShaderVersion < D3DPS_VERSION(2, 0)) {
        g_debug << "Warning - Your graphic card does not support vertex and pixelshaders version 2.0 \n";
    }

    //Set D3DPRESENT_PARAMETERS
    m_present.BackBufferWidth            = WINDOW_WIDTH;
    m_present.BackBufferHeight           = WINDOW_HEIGHT;
    m_present.BackBufferFormat           = D3DFMT_A8R8G8B8;
    m_present.BackBufferCount            = 2;
    m_present.MultiSampleType            = D3DMULTISAMPLE_NONE;
    m_present.MultiSampleQuality         = 0;
    m_present.SwapEffect                 = D3DSWAPEFFECT_DISCARD;
    m_present.hDeviceWindow              = m_mainWindow;
    m_present.Windowed                   = windowed;
    m_present.EnableAutoDepthStencil     = true;
    m_present.AutoDepthStencilFormat     = D3DFMT_D24S8;
    m_present.Flags                      = 0;
    m_present.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
    m_present.PresentationInterval       = D3DPRESENT_INTERVAL_IMMEDIATE;

    //Hardware Vertex Processing
    int vp = 0;
    if (caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
        vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
    else vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;

    //Create the IDirect3DDevice9
    if (FAILED(d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_mainWindow, vp, &m_present, &g_pDevice))) {
        g_debug << "Failed to create IDirect3DDevice9 \n";
        return E_FAIL;
    }

    //Release IDirect3D9 interface
    d3d9->Release();

    //Load Application Specific resources here...
    D3DXCreateFont(g_pDevice, 20, 0, FW_BOLD, 1, false,
                   DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY,
                   DEFAULT_PITCH | FF_DONTCARE, "Arial", &g_pFont);

    //Create Sprite
    D3DXCreateSprite(g_pDevice, &g_pSprite);

    //Load Effect
    ID3DXBuffer *pErrorMsgs = NULL;
    HRESULT hRes = D3DXCreateEffectFromFile(g_pDevice, "resources/fx/lighting.fx", NULL, NULL, D3DXSHADER_DEBUG, NULL, &g_pEffect, &pErrorMsgs);

    if (FAILED(hRes) && (pErrorMsgs != NULL)) {      //Failed to create Effect
        g_debug << (char*)pErrorMsgs->GetBufferPointer() << "\n";
        return E_FAIL;
    }

    m_deviceLost = false;

    m_drone.Load("resources/meshes/soldier.x");

    return S_OK;
}
Esempio n. 9
0
//! Loads and returns a skinned model from a file.
SkinnedModel* ModelImporter::LoadSkinnedModel(string filename)
{
	// Is the model already loaded?
	if(mSkinnedModelMap.find(filename) != mSkinnedModelMap.end())
		return mSkinnedModelMap[filename];

	Assimp::Importer importer;
	mFilename =	filename;
	SkinnedModel* model = NULL;

	// Important! Makes sure that if the angle between two face normals is > 80 they are not smoothed together.
	// Since the angle between a cubes face normals is 90 the lighting looks very bad if we don't specify this.
	importer.SetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE, 80.0f);	
	importer.SetPropertyInteger(AI_CONFIG_IMPORT_TER_MAKE_UVS, 1);
	importer.SetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, aiPrimitiveType_LINE);

	// Load scene from the file.
	const aiScene* scene = importer.ReadFile(filename, 
		aiProcess_CalcTangentSpace | 
		aiProcess_Triangulate | 
		aiProcess_GenSmoothNormals | 
		aiProcess_SplitLargeMeshes | 
		aiProcess_ConvertToLeftHanded | 
		aiProcess_SortByPType);

	if(scene)
	{
		// Create the model that is getting filled out.
		model = new SkinnedModel();

		// Create the animator.
		SceneAnimator* animator = new SceneAnimator();
		animator->Init(scene);
		model->SetAnimator(animator);

		// Loop through all meshes.
		for(int j = 0; j < scene->mNumMeshes; j++)
		{
			aiMesh* assimpMesh = scene->mMeshes[j];

			// Calculate vertex weight and bone indices.
			vector<Weights> weights = CalculateWeights(assimpMesh, animator);

			vector<SkinnedVertex> vertices;
			vector<UINT> indices;

			// Add vertices to the vertex list.
			for(int i = 0; i < assimpMesh->mNumVertices; i++) 
			{
				aiVector3D v = assimpMesh->mVertices[i];
				aiVector3D n = assimpMesh->mNormals[i];
				aiVector3D t = aiVector3D(0, 0, 0);
				if(assimpMesh->HasTextureCoords(0))
					t = assimpMesh->mTextureCoords[0][i];

				n = n.Normalize();

				// Pos, normal and texture coordinates.
				SkinnedVertex vertex(v.x, v.y, v.z, n.x, n.y, n.z, 0, 0, 1, t.x, t.y);

				// Bone indices and weights.
				for(int k = 0; k < weights[i].boneIndices.size(); k++) 
					vertex.BoneIndices[k] = weights[i].boneIndices[k];

				vertex.Weights.x = weights[i].weights.size() >= 1 ? weights[i].weights[0] : 0;
				vertex.Weights.y = weights[i].weights.size() >= 2 ? weights[i].weights[1] : 0;
				vertex.Weights.z = weights[i].weights.size() >= 3 ? weights[i].weights[2] : 0;

				vertices.push_back(vertex);
			}

			// Add indices to the index list.
			for(int i = 0; i < assimpMesh->mNumFaces; i++) 
				for(int k = 0; k < assimpMesh->mFaces[i].mNumIndices; k++) 
					indices.push_back(assimpMesh->mFaces[i].mIndices[k]);

			// Get the path to the texture in the directory.
			aiString path;
			aiMaterial* material = scene->mMaterials[assimpMesh->mMaterialIndex];
			material->Get(AI_MATKEY_TEXTURE_DIFFUSE(0), path);
			FindValidPath(&path);

			// Extract all the ambient, diffuse and specular colors.
			aiColor4D ambient, diffuse, specular;
			material->Get(AI_MATKEY_COLOR_AMBIENT, ambient);
			material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse);
			material->Get(AI_MATKEY_COLOR_SPECULAR, specular);
				
			// Create the mesh and its primitive.
			SkinnedMesh* mesh = new SkinnedMesh();

			Primitive* primitive = new Primitive(GlobalApp::GetD3DDevice(), vertices, indices);
			mesh->SetPrimitive(primitive);
			mesh->SetVertices(vertices);
			mesh->SetIndices(indices);
			mPrimtiveFactory->AddPrimitive(path.C_Str(), primitive);

			// Replace .tga with .bmp [HACK].
			string texturePath = path.C_Str();
			int tgaPos = texturePath.find_first_of(".tga");
			if(tgaPos != string::npos) {
				texturePath.replace(texturePath.size()-4, 4, ".bmp");
				path = texturePath;
			}

			// Any texture?
			if(_stricmp(path.C_Str(), "") != 0)
				mesh->LoadTexture(path.C_Str());

			// Any normal map?
			aiString nmap;
			material->Get(AI_MATKEY_TEXTURE_HEIGHT(0), nmap);
			FindValidPath(&nmap);
			if(_stricmp(nmap.C_Str(), "") != 0)	
				mesh->SetNormalMap(GlobalApp::GetGraphics()->LoadTexture(nmap.C_Str()));

			// [NOTE] The material is set to white.
			mesh->SetMaterial(Material(Colors::White));
			//mesh->SetMaterial(Material(diffuse, diffuse, diffuse));

			model->SetFilename(filename);

			// Add the mesh to the model.
			model->AddMesh(mesh);
		}

		// Pre-calculate the bounding box.
		model->CalculateAABB();

		// Add the newly created mesh to the map and return it.
		mSkinnedModelMap[filename] = model;
		return mSkinnedModelMap[filename];
	}
	else {
		char buffer[246];
		sprintf(buffer, "Error loading model: %s", filename.c_str());
		MessageBox(0, buffer, "Error!", 0);
		mSkinnedModelMap[filename] = LoadSkinnedModel("models/box.obj");
		return mSkinnedModelMap[filename];
	}
}
Esempio n. 10
0
bool SkinnedModel::Init(std::string filename, VulkanInterface * vulkan, VulkanCommandBuffer * cmdBuffer)
{
	VulkanDevice * vulkanDevice = vulkan->GetVulkanDevice();

	// Uniform buffer init
	vertexUniformBuffer.worldMatrix = glm::mat4(1.0f);
	vertexUniformBuffer.MVP = glm::mat4();
	for (unsigned int i = 0; i < MAX_BONES; i++)
		boneUniformBufferData.bones[i] = glm::mat4();

	// Vertex shader - Uniform buffer
	skinnedVS_UBO = new VulkanBuffer();
	if (!skinnedVS_UBO->Init(vulkanDevice, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, &vertexUniformBuffer,
		sizeof(vertexUniformBuffer), false))
		return false;

	// Vertex shader - Bone Uniform buffer
	skinnedVS_bone_UBO = new VulkanBuffer();
	if (!skinnedVS_bone_UBO->Init(vulkanDevice, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, &boneUniformBufferData,
		sizeof(boneUniformBufferData), false))
		return false;

	// Open .rcs file
	FILE * file = fopen(filename.c_str(), "rb");
	if (file == NULL)
	{
		gLogManager->AddMessage("ERROR: Model file not found! (" + filename + ")");
		return false;
	}

	// Open .mat file
	size_t pos = filename.rfind('.');
	filename.replace(pos, 4, ".mat");

	std::ifstream matFile(filename.c_str());
	if (!matFile.is_open())
	{
		gLogManager->AddMessage("ERROR: Model .mat file not found! (" + filename + ")");
		return false;
	}

	unsigned int meshCount;
	fread(&meshCount, sizeof(unsigned int), 1, file);

	for (unsigned int i = 0; i < meshCount; i++)
	{
		// Create and read mesh data
		char meshIdentifier[16];
		sprintf(meshIdentifier, "_mesh%d", i);

		SkinnedMesh * mesh = new SkinnedMesh();
		if (!mesh->Init(vulkan, file, filename + meshIdentifier))
		{
			gLogManager->AddMessage("ERROR: Failed to init a mesh!");
			return false;
		}
		meshes.push_back(mesh);

		std::string texturePath;
		char diffuseTextureName[64];
		char normalTextureName[64];

		// Init mesh material
		Material * material = new Material();

		// Read diffuse texture
		fread(diffuseTextureName, sizeof(char), 64, file);
		if (strcmp(diffuseTextureName, "NONE") == 0)
			texturePath = "data/textures/default_diffuse.rct";
		else
			texturePath = "data/textures/" + std::string(diffuseTextureName);

		Texture * diffuse = gTextureManager->RequestTexture(texturePath, vulkan->GetVulkanDevice(), cmdBuffer);
		if (diffuse == nullptr)
			return false;

		textures.push_back(diffuse);

		material->SetDiffuseTexture(diffuse);

		// Read normal texture if available
		fread(normalTextureName, sizeof(char), 64, file);
		if (strcmp(normalTextureName, "NONE") != 0)
		{
			texturePath = "data/textures/" + std::string(normalTextureName);

			Texture * normal = gTextureManager->RequestTexture(texturePath, vulkan->GetVulkanDevice(), cmdBuffer);
			if (normal == nullptr)
				return false;

			textures.push_back(normal);

			material->SetNormalTexture(normal);
		}

		std::string matName, matTextureName;
		float metallicOffset, roughnessOffset;
		matFile >> matName >> matTextureName >> metallicOffset >> roughnessOffset;
		
		// Read material texture
		if (matTextureName == "NONE")
			texturePath = "data/textures/default_material.rct";
		else
			texturePath = "data/textures/" + matTextureName;

		Texture * matTexture = gTextureManager->RequestTexture(texturePath, vulkan->GetVulkanDevice(), cmdBuffer);
		if (matTexture == nullptr)
			return false;

		textures.push_back(matTexture);

		material->SetMaterialTexture(matTexture);
		material->SetMetallicOffset(metallicOffset);
		material->SetRoughnessOffset(roughnessOffset);

		materials.push_back(material);
		meshes[i]->SetMaterial(material);

		// Init draw command buffers for each meash
		VulkanCommandBuffer * drawCmdBuffer = new VulkanCommandBuffer();
		if (!drawCmdBuffer->Init(vulkanDevice, vulkan->GetVulkanCommandPool(), false))
		{
			gLogManager->AddMessage("ERROR: Failed to create a draw command buffer!");
			return false;
		}
		drawCmdBuffers.push_back(drawCmdBuffer);
	}

	matFile.close();

	// Read bone offsets
	fread(&numBones, sizeof(unsigned int), 1, file);
	boneOffsets.resize(numBones);
	fread(boneOffsets.data(), sizeof(aiMatrix4x4), numBones, file);

	// Read bone mappings
	for (unsigned int i = 0; i < numBones; i++)
	{
		unsigned int strSize;
		char * str;
		std::string boneName;
		uint32_t id;

		fread(&strSize, sizeof(unsigned int), 1, file);
		str = new char[strSize+1];
		fread(str, sizeof(char), strSize, file);
		fread(&id, sizeof(uint32_t), 1, file);

		str[strSize] = 0;
		boneName = str;
		boneMapping[boneName] = id;
	}

	fclose(file);

	return true;
}