首页 > 关于directx11中读取obj文件的问题

关于directx11中读取obj文件的问题

问题已经解决,感谢@vczh 的帮助,最后锁定问题.原来是因为obj的索引 a/b/c 分别代表相应的pos、texture、normal。


原始问题在下方


有两个文件:
1.cube.obj: http://pan.baidu.com/s/1dEvjwnn
2.MianJu_2.obj: http://pan.baidu.com/s/1jHuZk9o

写了一个类将obj读取并转换。

1.顶点信息为Vector<VertexPos>:
struct VertexPos
{
    XMFLOAT3 pos;    
    XMFLOAT2 tex0;
    XMFLOAT3 nor;
};
2.索引信息为Vector<WORD>

读取之后,在绘制过程出现问题,第一个相对规模小的cube绘制成功:

但是另一个文件(一个面具的建模)却什么都显示:

请大家帮看看是哪里出了问题?

D3D部分代码:

HLSL:


Texture2D colorMap : register( t0 );
Texture2D secondMap : register(t1);
SamplerState colorSampler : register( s0 );
vector colorCube : register(t2);


cbuffer cbChangesEveryFrame : register( b0 )
{
    matrix worldMatrix;
};

cbuffer cbNeverChanges : register( b1 )
{
    matrix viewMatrix;
};

cbuffer cbChangeOnResize : register( b2 )
{
    matrix projMatrix;
};

cbuffer cbChangeRotationMatrix : register(b3)
{
    matrix rotationMatrix;
};


struct VS_Input
{
    float4 pos  : POSITION;
    float2 tex0 : TEXCOORD0;
    float3 nor  :  NORMAL;
};

struct PS_Input
{
    float4 pos  : SV_POSITION;
    float4 temp : POSITION;
    float2 tex0 : TEXCOORD0;
    float3 nor  : NORMAL;
};


PS_Input VS_Main( VS_Input vertex )
{
    PS_Input vsOut = ( PS_Input )0;

    //变换为世界坐标系
    vsOut.pos = mul(vertex.pos, rotationMatrix);
    vsOut.pos = mul(vsOut.pos, worldMatrix);
    vsOut.pos = mul( vsOut.pos, viewMatrix );
    vsOut.pos = mul( vsOut.pos, projMatrix );
   
    vsOut.tex0 = vertex.tex0;
    vsOut.nor = vertex.nor;

    return vsOut;
}


float4 PS_Main( PS_Input frag ) : SV_TARGET
{
    float4 col = colorMap.Sample(colorSampler, frag.tex0);
    float4 col2 = secondMap.Sample(colorSampler, frag.tex0);

    if(col.x - 0.0f < 0.035f)
    {
    }
    else
    {
        col.x = colorCube.x;
        col.y = colorCube.y;
        col.z = colorCube.z;
    }

    return col * col2;
}


technique11 ColorInversion
{
    pass P0
    {
        SetVertexShader( CompileShader( vs_5_0, VS_Main() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_5_0, PS_Main() ) );
    }
}

Render:

void Cube::Render()
{
    if (d3dContext_ == 0)
        return;

    //清屏
    float clearColor[4] = { 0.0f, 0.0f, 0.25f, 1.0f };
    d3dContext_->ClearRenderTargetView(backBufferTarget_, clearColor);

    //新增
    d3dContext_->ClearDepthStencilView(depthStencilView_, D3D11_CLEAR_DEPTH, 1.0f, 0);

    unsigned int stride = sizeof(NinoObj::VertexPos);
    unsigned int offset = 0;


    d3dContext_->IASetInputLayout(inputLayout_);
    d3dContext_->IASetVertexBuffers(0, 1, &vertexBuffer_, &stride, &offset);
    d3dContext_->IASetIndexBuffer(indexBuffer_, DXGI_FORMAT_R16_UINT, 0);
    d3dContext_->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

    XMMATRIX rotationMat = XMMatrixRotationRollPitchYaw(0.0f, 0.0f, 0.0f);
    XMMATRIX translationMat = XMMatrixTranslation(0.0f, 0.0f, 6.0f);
    XMMATRIX worldMat = rotationMat * translationMat;

    //更改effect内的外部变量

    ID3DX11EffectShaderResourceVariable* colorMap;
    colorMap = effect_->GetVariableByName("colorMap")->AsShaderResource();
    colorMap->SetResource(colorMap_);

    ID3DX11EffectShaderResourceVariable* secondMap;
    secondMap = effect_->GetVariableByName("secondMap")->AsShaderResource();
    secondMap->SetResource(secondMap_);

    ID3DX11EffectSamplerVariable* colorMapSampler;
    colorMapSampler = effect_->GetVariableByName("colorSampler")->AsSampler();
    colorMapSampler->SetSampler(0, colorMapSampler_);

    ID3DX11EffectMatrixVariable* worldMatrix;
    worldMatrix = effect_->GetVariableByName("worldMatrix")->AsMatrix();
    worldMatrix->SetMatrix((float*)&worldMat);

    ID3DX11EffectMatrixVariable* viewMatrix;
    viewMatrix = effect_->GetVariableByName("viewMatrix")->AsMatrix();
    viewMatrix->SetMatrix((float*)&viewMatrix_);

    ID3DX11EffectMatrixVariable* projMatrix;
    projMatrix = effect_->GetVariableByName("projMatrix")->AsMatrix();
    projMatrix->SetMatrix((float*)&projMatrix_);

    auto *rotationMatrix = effect_->GetVariableByName("rotationMatrix")->AsMatrix();
    rotationMatrix->SetMatrix((float*)&rotationMatrix_);

    ID3DX11EffectTechnique* colorInvTechnique;
    colorInvTechnique = effect_->GetTechniqueByName("ColorInversion");

    D3DX11_TECHNIQUE_DESC techDesc;
    colorInvTechnique->GetDesc(&techDesc);

    for (unsigned int p = 0; p < techDesc.Passes; p++)
    {
        ID3DX11EffectPass* pass = colorInvTechnique->GetPassByIndex(p);

        if (pass != 0)
        {
            pass->Apply(0, d3dContext_);
            d3dContext_->DrawIndexed(indices_.size(), 0, 0);
        }
    }

    //更改颜色

    auto* colorTemp = effect_->GetVariableByName("colorCube")->AsVector();
    colorTemp->SetFloatVector(colorArray_);

    swapChain_->Present(0, 0);
}

LoadContent:

bool Cube::LoadContent()
{
    /*************************Effect******************************/

    ID3DBlob* vsBuffer = 0;

    //创建effect对象
    if (CompileD3DShader(L"ColorInversion.fx", 0, "fx_5_0", &vsBuffer) == false)
    {
        MessageBox(0, "Error compile the effect shader!", "Compile Error", MB_OK);
    }
    if (FAILED(D3DX11CreateEffectFromMemory(vsBuffer->GetBufferPointer(), vsBuffer->GetBufferSize(), 0, d3dDevice_, &effect_)))
    {
        MessageBox(0, "Error Create the effect shader!", "Create Error", MB_OK);

        if (vsBuffer)
            vsBuffer->Release();
        return false;
    }

    /*************************顶点布局******************************/

    D3D11_INPUT_ELEMENT_DESC solidColorLayout[] =
    {
        { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },    //位置
        { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },        //纹理
        { "NORMAL" , 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0  }    //法线
    };

    unsigned int totalLayoutElements = ARRAYSIZE(solidColorLayout);

    ID3DX11EffectTechnique* colorInvTechnique;
    colorInvTechnique = effect_->GetTechniqueByName("ColorInversion");
    ID3DX11EffectPass* effectPass = colorInvTechnique->GetPassByIndex(0);

    D3DX11_PASS_SHADER_DESC passDesc;
    D3DX11_EFFECT_SHADER_DESC shaderDesc;
    effectPass->GetVertexShaderDesc(&passDesc);
    passDesc.pShaderVariable->GetShaderDesc(passDesc.ShaderIndex, &shaderDesc);

    if (FAILED(d3dDevice_->CreateInputLayout(solidColorLayout, totalLayoutElements,
        shaderDesc.pBytecode, shaderDesc.BytecodeLength, &inputLayout_)))
    {
        MessageBox(0, "Error Create the input layout!", "Create Error", MB_OK);
        return false;
    }

    vsBuffer->Release();

    /*************************顶点部分******************************/

    NinoObj ninoObj;

    ninoObj.CreateVertexAndIndex("MianJu_2.obj", vertices_, indices_);

    auto vertexVector = vertices_.GetVector();

    D3D11_BUFFER_DESC vertexDesc;
    ZeroMemory(&vertexDesc, sizeof(vertexDesc));
    vertexDesc.Usage = D3D11_USAGE_DEFAULT;
    vertexDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    vertexDesc.ByteWidth = sizeof(NinoObj::VertexPos) * vertexVector.size();

    D3D11_SUBRESOURCE_DATA resourceData;
    ZeroMemory(&resourceData, sizeof(resourceData));
    resourceData.pSysMem = &vertexVector[0];

    if (FAILED(d3dDevice_->CreateBuffer(&vertexDesc, &resourceData, &vertexBuffer_)))
    {
        MessageBox(0, "Failed to create vertex buffer!", "Create Error", MB_OK);
        return false;
    }

    /*************************索引部分******************************/

    D3D11_BUFFER_DESC indexDesc;
    ZeroMemory(&indexDesc, sizeof(indexDesc));
    indexDesc.Usage = D3D11_USAGE_DEFAULT;
    indexDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
    indexDesc.ByteWidth = sizeof(WORD) * indices_.size();
    indexDesc.CPUAccessFlags = 0;

    resourceData.pSysMem = &(indices_[0]);

    if (FAILED(d3dDevice_->CreateBuffer(&indexDesc, &resourceData, &indexBuffer_)))
    {
        MessageBox(0, "Failed to create index buffer!", "Create Error", MB_OK);
        return false;
    }

    //读取图片文件
    if (FAILED(CreateDDSTextureFromFile(d3dDevice_, L"magic.dds", nullptr, &colorMap_)))
    {
        MessageBox(0, "Failed to load the texture image!!", "Load Error", MB_OK);
        return false;
    }

    //读取图片文件
    if (FAILED(CreateDDSTextureFromFile(d3dDevice_, L"demo.dds", nullptr, &secondMap_)))
    {
        MessageBox(0, "Failed to load the texture image!!", "Load Error", MB_OK);
        return false;
    }

    D3D11_SAMPLER_DESC colorMapDesc;
    ZeroMemory(&colorMapDesc, sizeof(colorMapDesc));
    colorMapDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
    colorMapDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
    colorMapDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
    colorMapDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
    colorMapDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
    colorMapDesc.MaxLOD = D3D11_FLOAT32_MAX;

    if (FAILED(d3dDevice_->CreateSamplerState(&colorMapDesc, &colorMapSampler_)))
    {
        MessageBox(0, "Failed to create color map sampler state!", "Load Error", MB_OK);
        return false;
    }

    viewMatrix_ = XMMatrixIdentity();
    projMatrix_ = XMMatrixPerspectiveFovLH(XM_PIDIV4, 800.0f / 600.0f, 0.01f, 100.0f);

    rotationMatrix_ = GetRotationMartix(NinoVector3<float>(1.0f, 0.0f, 0.0f), 0.00f);

    return true;
}

根据我的经验,多半是你的坐标系统已经飞了。因为你第一个模型能显示,所以代码出问题的概率不大,太长我也不想看。我以前也遇到这样的问题,调试到最后发现,竟然是因为模型的坐标系和我想象的不一样,于是摄像机根本就没有对准。

我认为你应该在load完模型之后,自己算一个包围盒,再用一个球来覆盖他,得到球心和半径两个值,输出出来。然后你写代码对准他并调整好距离,对准并完全显示一个球是很容易的。这样你就能看到模型了。

【热门文章】
【热门文章】