Directx Assimp错误的纹理坐标

时间:2017-05-23 12:07:25

标签: c++ directx textures assimp

我正在尝试将网格加载到我的directx应用中。我可以成功加载任何网格,但网格的一侧纹理坐标是错误的。 (只有一面。另一面的纹理被正确映射) ScreenShot

这是我的代码。

Model.h

#ifndef MODEL_H
#define MODEL_H

#include <vector>
#include <d3d11_1.h>
#include <DirectXMath.h>
#include <D3DX10.h>

#include <Importer.hpp>
#include <scene.h>
#include <postprocess.h>

#include "Mesh.h"

using namespace DirectX;

class CModel
{
public:
CModel();
~CModel();

bool Load(HWND hwnd, ID3D11Device* dev, ID3D11DeviceContext* devcon, std::string filename);
void Draw(ID3D11DeviceContext* devcon);

void Close();
private:
ID3D11Device *dev;
ID3D11DeviceContext *devcon;
std::vector<Mesh> meshes;
string directory;
vector<Texture> textures_loaded;
HWND hwnd;

void processNode(aiNode* node, const aiScene* scene);
Mesh processMesh(aiMesh* mesh, const aiScene* scene);
vector<Texture> loadMaterialTextures(aiMaterial* mat, aiTextureType type, string typeName, const aiScene* scene);
string determineTextureType(const aiScene* scene, aiMaterial* mat);
int getTextureIndex(aiString* str);
ID3D11ShaderResourceView* getTextureFromModel(const aiScene* scene, int textureindex);
};
#endif

Model.cpp

#include "Model.h"



CModel::CModel()
{
}


CModel::~CModel()
{
}

bool CModel::Load(HWND hwnd, ID3D11Device* dev, ID3D11DeviceContext* devcon, 
std::string filename)
{
Assimp::Importer importer;

const aiScene* pScene = importer.ReadFile(filename,
    aiProcess_Triangulate |
    aiProcess_ConvertToLeftHanded |
    aiProcess_FlipUVs);

if (pScene == NULL)
    return false;

this->directory = filename.substr(0, filename.find_last_of('/'));

this->dev = dev;
this->hwnd = hwnd;

processNode(pScene->mRootNode, pScene);

return true;
}

void CModel::processNode(aiNode* node, const aiScene* scene)
{
for (UINT i = 0; i < node->mNumMeshes; i++)
{
    aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
    meshes.push_back(this->processMesh(mesh, scene));
}

for (UINT i = 0; i < node->mNumChildren; i++)
{
    this->processNode(node->mChildren[i], scene);
}

}

string textype;

Mesh CModel::processMesh(aiMesh* mesh, const aiScene* scene)
{
// Data to fill
vector<VERTEX> vertices;
vector<DWORD> indices;
vector<Texture> textures;

if (mesh->mMaterialIndex >= 0)
{
    aiMaterial* mat = scene->mMaterials[mesh->mMaterialIndex];

    if(textype.empty()) textype = determineTextureType(scene, mat);
}

// Walk through each of the mesh's vertices
for (UINT i = 0; i < mesh->mNumVertices; i++)
{
    VERTEX vertex;

    vertex.X = mesh->mVertices[i].x;
    vertex.Y = mesh->mVertices[i].y;
    vertex.Z = mesh->mVertices[i].z;

    if (mesh->mTextureCoords[0])
    {
        vertex.TEXX = mesh->mTextureCoords[0][i].x;
        vertex.TEXY = mesh->mTextureCoords[0][i].y;
    }
    else
    {
        vertex.TEXX = 0.0f;
        vertex.TEXY = 0.0f;
    }

    vertices.push_back(vertex);
}

for (UINT i = 0; i < mesh->mNumFaces; i++)
{
    aiFace face = mesh->mFaces[i];

    for (UINT j = 0; j < face.mNumIndices; j++)
        indices.push_back(face.mIndices[j]);
}

if (mesh->mMaterialIndex >= 0)
{
    aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];

    vector<Texture> diffuseMaps = this->loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse", scene);
    textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());

    //vector<Texture> specularMaps = this->loadMaterialTextures(material, aiTextureType_SPECULAR, "texture_specular");
    //textures.insert(textures.end(), specularMaps.begin(), specularMaps.end());
}

return Mesh(dev, vertices, indices, textures);
}

vector<Texture> CModel::loadMaterialTextures(aiMaterial* mat, aiTextureType 
type, string typeName, const aiScene* scene)
{
vector<Texture> textures;
for (UINT i = 0; i < mat->GetTextureCount(type); i++)
{
    aiString str;
    mat->GetTexture(type, i, &str);
    // Check if texture was loaded before and if so, continue to next iteration: skip loading a new texture
    bool skip = false;
    for (UINT j = 0; j < textures_loaded.size(); j++)
    {
        if (std::strcmp(textures_loaded[j].path.C_Str(), str.C_Str()) == 0)
        {
            textures.push_back(textures_loaded[j]);
            skip = true; // A texture with the same filepath has already been loaded, continue to next one. (optimization)
            break;
        }
    }
    if (!skip)
    {   // If texture hasn't been loaded already, load it
        HRESULT hr;
        Texture texture;
        if (textype == "embedded compressed texture")
        {
            int textureindex = getTextureIndex(&str);
            texture.texture = getTextureFromModel(scene, textureindex);
        }
        else
        {
            string filename = string(str.C_Str());
            filename = directory + '/' + filename;
            hr = D3DX11CreateShaderResourceViewFromFile(dev, filename.c_str(), nullptr, nullptr, &texture.texture, nullptr);
            if (FAILED(hr))
                MessageBox(hwnd, "Texture couldn't be loaded", "Error!", MB_ICONERROR | MB_OK);
        }
        texture.type = typeName;
        texture.path = str;
        textures.push_back(texture);
        this->textures_loaded.push_back(texture);  // Store it as texture loaded for entire model, to ensure we won't unnecesery load duplicate textures.
    }
}
return textures;
}


void CModel::Draw(ID3D11DeviceContext* devcon)
{
for (int i = 0; i < meshes.size(); i++)
{
    meshes[i].Draw(devcon);
}
}

void CModel::Close()
{
for (int i = 0; i < meshes.size(); i++)
{
    meshes[i].Close();
}

dev->Release();
}

string CModel::determineTextureType(const aiScene* scene, aiMaterial* mat)
{
aiString textypeStr;
mat->GetTexture(aiTextureType_DIFFUSE, 0, &textypeStr);
string textypeteststr = textypeStr.C_Str();
if (textypeteststr == "*0" || textypeteststr == "*1" || textypeteststr == "*2" || textypeteststr == "*3" || textypeteststr == "*4" || textypeteststr == "*5")
{
    if (scene->mTextures[0]->mHeight == 0)
    {
        return "embedded compressed texture";
    }
    else
    {
        return "embedded non-compressed texture";
    }
}
if (textypeteststr.find('.') != string::npos)
{
    return "textures are on disk";
}
}

int CModel::getTextureIndex(aiString* str)
{
string tistr;
tistr = str->C_Str();
tistr = tistr.substr(1);
return stoi(tistr);
}

ID3D11ShaderResourceView * CModel::getTextureFromModel(const aiScene * scene, int textureindex)
{
HRESULT hr;
ID3D11ShaderResourceView *texture;

int* size = reinterpret_cast<int*>(&scene->mTextures[textureindex]->mWidth);

hr = D3DX11CreateShaderResourceViewFromMemory(dev, reinterpret_cast<unsigned char*>(scene->mTextures[textureindex]->pcData), *size, nullptr, nullptr, &texture, nullptr);
if (FAILED(hr))
    MessageBox(hwnd, "Texture couldn't be created from memory!", "Error!", MB_ICONERROR | MB_OK);

return texture;
}

Mesh.h(这是一个只有标题的类)

#ifndef MESH_H
#define MESH_H

#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <vector>
using namespace std;

#include <vector>
#include <d3d11_1.h>
#include <DirectXMath.h>
#include <D3DX11.h>
#include <D3DX10.h>
using namespace DirectX;

struct VERTEX {
FLOAT X, Y, Z;
D3DXCOLOR color;
FLOAT TEXX, TEXY;
};

struct Texture {
string type;
aiString path;
ID3D11ShaderResourceView *texture;
};

class Mesh {
public:
vector<VERTEX> vertices;
vector<DWORD> indices;
vector<Texture> textures;
ID3D11Device *dev;

Mesh(ID3D11Device *dev,vector<VERTEX> vertices, vector<DWORD> indices, vector<Texture> textures)
{
    this->vertices = vertices;
    this->indices = indices;
    this->textures = textures;

    this->dev = dev;

    this->setupMesh(dev);
}

void Draw(ID3D11DeviceContext *devcon)
{
    UINT stride = sizeof(VERTEX);
    UINT offset = 0;

    devcon->IASetVertexBuffers(0, 1, &VertexBuffer, &stride, &offset);
    devcon->IASetIndexBuffer(IndexBuffer, DXGI_FORMAT_R32_UINT, 0);

    devcon->PSSetShaderResources(0, 1, &textures[0].texture);

    devcon->DrawIndexed(indices.size(), 0, 0);
}

void Close()
{
    VertexBuffer->Release();
    IndexBuffer->Release();
}
private:
/*  Render data  */
ID3D11Buffer *VertexBuffer, *IndexBuffer;

/*  Functions    */
// Initializes all the buffer objects/arrays
bool setupMesh(ID3D11Device *dev)
{
    HRESULT hr;

    D3D11_BUFFER_DESC vbd;
    vbd.Usage = D3D11_USAGE_IMMUTABLE;
    vbd.ByteWidth = sizeof(VERTEX) * vertices.size();
    vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    vbd.CPUAccessFlags = 0;
    vbd.MiscFlags = 0;

    D3D11_SUBRESOURCE_DATA initData;
    initData.pSysMem = &vertices[0];

    hr = dev->CreateBuffer(&vbd, &initData, &VertexBuffer);
    if (FAILED(hr))
        return false;

    D3D11_BUFFER_DESC ibd;
    ibd.Usage = D3D11_USAGE_IMMUTABLE;
    ibd.ByteWidth = sizeof(DWORD) * indices.size();
    ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
    ibd.CPUAccessFlags = 0;
    ibd.MiscFlags = 0;

    initData.pSysMem = &indices[0];

    hr = dev->CreateBuffer(&ibd, &initData, &IndexBuffer);
    if (FAILED(hr))
        return false;
}
};

#endif

感谢。

1 个答案:

答案 0 :(得分:0)

我解决了。如果遇到此问题的任何其他人确定您已设置SamplerState。

相关问题