DirectX/C++: координаты текстуры неправильно корректируются в движке после экспорта Obj

Если я рисую одну плоскость, координаты текстуры отображаются правильно. (4 Verts, 4 TC, 6 индексов (2 полигона))

Даже если она разделена (9 Verts, 9 TC, 27 индексов (8 полигонов)) текстура будет отображаться: enter image  описание здесь

(сложный план майя) введите здесь описание изображения

Я могу взять свой [написанный] конвертер Obj и загрузить координаты Текстуры в буфер. Однако, если я выдавливаю лицо в Maya и даже применяю планарную UV-карту для «восстановления» сломанной UV-карты (выше), координаты текстуры становятся действительно дикими в движке. (ниже) введите здесь описание изображения

Есть ли проблема с форматом координат текстуры Obj?

Обновление: я рисовал с помощью D3D11_PRIMITIVE_TOPOLOGY_LINELIST и также заметил изменения в индексации..введите описание изображения здесь в этом проблема? или мне следует реконструировать координаты текстуры, как показано на странице http://www.gamedev.net/topic/600234-texcoord-count-is-Different-than-vertex-count/


person Rashid Ellis    schedule 14.11.2014    source источник
comment
Проверьте свои координаты TU/TV после того, как вы загрузили файл .obj в свою программу. Похоже, с ними что-то не так.   -  person Mikael Törnqvist    schedule 14.11.2014
comment
Я устанавливаю часы для массива структур vertex, прежде чем он будет отправлен в шейдер. Значения кажутся законными. Я заметил, что некоторые значения превышали 1 на чуть-чуть. (1.000671) Я думаю, что это результат хранения как float, было бы это слишком важно, если бы SamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;...?   -  person Rashid Ellis    schedule 14.11.2014


Ответы (3)


Эта проблема была вызвана тем, что индекс координат текстуры не был равен индексу вершины. Чтобы решить эту проблему, индекс координат текстуры нужно было упорядочить таким образом, чтобы он совпадал с индексом вершины.

Для этой проблемы я смог решить, используя метод грубой силы, который соответствует моему пониманию, который является медленным, который каталогизирует все координаты вершины/текстуры как ключ и восстанавливает полный явный массив вершин и координат текстуры из их индексов, заполняя пользовательская структура, которая соответствует потребностям моего приложения.

введите здесь описание изображения

Есть и другие более быстрые решения, в которых используется хэш http://programminglinuxgames.blogspot.com/2010/03/wavefront-obj-file-format-opengl-vertex.html

Связанная проблема с нормалями: OpenGL — проблемы с буферизацией индексов

И 3 индексных буфера

И хорошее объяснение: Почему мой парсер OBJ визуализировать сетки вот так?

И дополнительные ресурсы по формату obj: http://en.wikipedia.org/wiki/Wavefront_.obj_file

Ресурсы OBJ: http://www.martinreddy.net/gfx/3d/OBJ.spec http://www.fileformat.info/format/wavefrontobj/egff.htm

Кроме того, учебная программа MeshFromObj10 из библиотеки DirectX помогает некоторым, делая это эффективным способом. Нет простого способа закодировать его, кроме как найти сторонний источник.

person Rashid Ellis    schedule 18.11.2014

Проверьте эти вещи, это может вам помочь:

DirectX использует левые системы координат. Я думаю, вы получите правостороннюю систему координат из Maya/3ds Max при экспорте в файлы .obj ://msdn.microsoft.com/en-us/library/windows/desktop/bb204853(v=vs.85). aspx

Сравните количество вершин в Maya и в вашей программе.

Выясните причину, по которой вы получаете 1.000671 в своих координатах TU/TV, это выглядит немного высоко.

Убедитесь, что вы экспортируете как треугольники, а не как прямоугольники.

Покажите свои нормали в Maya, похоже, что часть земли/прямоугольника, на котором стоит этот объект, отсутствует. Или вы можете попробовать отключить отбраковку в файле D3D11_RASTERIZER_DESC.

У меня сейчас на компьютере не установлена ​​Maya, но я думаю, вы можете получить там графическое представление, которое покажет вам точные координаты TU/TV на вашей текстуре.

http://www.youtube.com/watch?v=T-fFpmBYP_Q Этот вид показан в этом видео на 4,21.

РЕДАКТИРОВАТЬ:

Предоставление некоторых примеров кода:

struct D3D11TextureVertexType
{
    XMFLOAT3 Position;
    XMFLOAT2 TX;
};

Вот как вы можете разместить вершины на трубе:

hr = m_pd3dImmediateContext->Map(MyID3D11Buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
    if (FAILED(hr)) return hr;

    pData = (D3D11TextureVertexType*)mappedResource.pData;
    memcpy(pData, MYOBJECTVERTICES/*this is D3D11TextureVertexType*/, sizeof(D3D11TextureVertexType) * VertexCount);

    m_pd3dImmediateContext->Unmap(MyID3D11Buffer, 0);

    stride = sizeof(D3D11TextureVertexType);
    offset = 0;

    m_pd3dImmediateContext->IASetVertexBuffers(0, 1, &MyID3D11Buffer, &stride, &offset);
    m_pd3dImmediateContext->IASetIndexBuffer(m_AdjRectangleIBuffer, DXGI_FORMAT_R32_UINT, 0);
    m_pd3dImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

    result = m_TextureShader->Render(m_pd3dImmediateContext, 6, worldMatrix, viewMatrix, orthoMatrix, m_Textures[Q.textureID]->pSRV);           if (!result)
    {
        return S_FALSE;
    }

Это некоторые интересные функции в TextureShaderClass.

bool Render(ID3D11DeviceContext* deviceContext, int indexCount, DirectX::CXMMATRIX worldMatrix, DirectX::CXMMATRIX viewMatrix, DirectX::CXMMATRIX projectionMatrix, ID3D11ShaderResourceView* texture)
{
    bool result;

    result = SetShaderParameters(deviceContext, worldMatrix, viewMatrix, projectionMatrix, texture);
    if (!result)
    {
        return false;
    }

    RenderShader(deviceContext, indexCount);

    return true;
}

bool InitializeShader(ID3D11Device* device, const WCHAR* filename)
{
    HRESULT result;
    ID3D10Blob* errorMessage;
    ID3D10Blob* vertexShaderBuffer;
    ID3D10Blob* pixelShaderBuffer;
    D3D11_INPUT_ELEMENT_DESC polygonLayout[2];
    unsigned int numElements;
    D3D11_BUFFER_DESC matrixBufferDesc;
    D3D11_SAMPLER_DESC samplerDesc;

    errorMessage = 0;
    vertexShaderBuffer = 0;
    pixelShaderBuffer = 0;



    result = D3DCompileFromFile(filename, NULL, NULL, "TextureVertexShader", "vs_5_0", 0, 0, &vertexShaderBuffer, &errorMessage);
    if (FAILED(result))
    {
        if (errorMessage)
        {
            //OutputShaderErrorMessage(errorMessage, hwnd, filename);
        }
        else
        {
            MessageBox(0, filename, L"Missing Shader File", MB_OK);
        }

        return false;
    }

    result = D3DCompileFromFile(filename, NULL, NULL, "TexturePixelShader", "ps_5_0", 0, 0, &pixelShaderBuffer, &errorMessage);
    if (FAILED(result))
    {
        if (errorMessage)
        {
            //OutputShaderErrorMessage(errorMessage, hwnd, psFilename);
        }
        else
        {
            MessageBox(0, filename, L"Missing Shader File", MB_OK);
        }

        return false;
    }

    result = device->CreateVertexShader(vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), NULL, &m_vertexShader);
    if (FAILED(result))
    {
        return false;
    }

    result = device->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), NULL, &m_pixelShader);
    if (FAILED(result))
    {
        return false;
    }

    polygonLayout[0].SemanticName = "POSITION";
    polygonLayout[0].SemanticIndex = 0;
    polygonLayout[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
    polygonLayout[0].InputSlot = 0;
    polygonLayout[0].AlignedByteOffset = 0;
    polygonLayout[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
    polygonLayout[0].InstanceDataStepRate = 0;

    polygonLayout[1].SemanticName = "TEXCOORD";
    polygonLayout[1].SemanticIndex = 0;
    polygonLayout[1].Format = DXGI_FORMAT_R32G32_FLOAT;
    polygonLayout[1].InputSlot = 0;
    polygonLayout[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
    polygonLayout[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
    polygonLayout[1].InstanceDataStepRate = 0;

    numElements = sizeof(polygonLayout) / sizeof(polygonLayout[0]);

    result = device->CreateInputLayout(polygonLayout, numElements, vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), &m_layout);
    if (FAILED(result))
    {
        return false;
    }

    vertexShaderBuffer->Release();
    vertexShaderBuffer = 0;

    pixelShaderBuffer->Release();
    pixelShaderBuffer = 0;

    matrixBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
    matrixBufferDesc.ByteWidth = sizeof(MatrixBufferType);
    matrixBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
    matrixBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    matrixBufferDesc.MiscFlags = 0;
    matrixBufferDesc.StructureByteStride = 0;

    result = device->CreateBuffer(&matrixBufferDesc, NULL, &m_matrixBuffer);
    if (FAILED(result))
    {
        return false;
    }

    samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
    samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
    samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
    samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
    samplerDesc.MipLODBias = 0.0f;
    samplerDesc.MaxAnisotropy = 1;
    samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
    samplerDesc.BorderColor[0] = 0;
    samplerDesc.BorderColor[1] = 0;
    samplerDesc.BorderColor[2] = 0;
    samplerDesc.BorderColor[3] = 0;
    samplerDesc.MinLOD = 0;
    samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;

    result = device->CreateSamplerState(&samplerDesc, &m_sampleState);
    if (FAILED(result))
    {
        return false;
    }

    return true;
}
bool SetShaderParameters(ID3D11DeviceContext* deviceContext, DirectX::CXMMATRIX worldMatrix, DirectX::CXMMATRIX  viewMatrix, DirectX::CXMMATRIX  projectionMatrix, ID3D11ShaderResourceView* texture)
{
    HRESULT result;
    D3D11_MAPPED_SUBRESOURCE mappedResource;
    MatrixBufferType* dataPtr;
    unsigned int bufferNumber;

    result = deviceContext->Map(m_matrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
    if (FAILED(result))
    {
        return false;
    }

    dataPtr = (MatrixBufferType*)mappedResource.pData;

    DirectX::XMMATRIX world = worldMatrix;
    world = XMMatrixTranspose(world);
    DirectX::XMMATRIX view = viewMatrix;
    view = XMMatrixTranspose(view);
    DirectX::XMMATRIX projection = projectionMatrix;
    projection = XMMatrixTranspose(projection);

    dataPtr->world = world;
    dataPtr->view = view;
    dataPtr->projection = projection;

    deviceContext->Unmap(m_matrixBuffer, 0);

    bufferNumber = 0;

    deviceContext->VSSetConstantBuffers(bufferNumber, 1, &m_matrixBuffer);

    deviceContext->PSSetShaderResources(0, 1, &texture);

    return true;
}

void RenderShader(ID3D11DeviceContext* deviceContext, int indexCount)
{
    deviceContext->IASetInputLayout(m_layout);

    deviceContext->VSSetShader(m_vertexShader, NULL, 0);
    deviceContext->PSSetShader(m_pixelShader, NULL, 0);

    deviceContext->PSSetSamplers(0, 1, &m_sampleState);

    deviceContext->DrawIndexed(indexCount, 0, 0);

    return;
}
person Mikael Törnqvist    schedule 14.11.2014
comment
Вау, это здорово! Я думаю, что нашел проблему: я запустил цикл for для vertex.size(), а не для размера массива tex/coord при копировании значений, кажется, что если общее количество элементов в массиве tex/coord = num_Elements в вершине массив, объект отображается нормально. Если количество tex/coords больше, чем количество вершин, то некоторые значения будут неопределенными в виде неприятного указателя. Я собираюсь переписать, чтобы проверить. - person Rashid Ellis; 14.11.2014
comment
Думали, что количество элементов координат текстуры всегда будет равно количеству вершин...? - person Rashid Ellis; 14.11.2014
comment
Это моя структура, которую я отправляю на свою видеокарту: struct VertexType { XMFLOAT3 position; текстура XMFLOAT2; XMFLOAT3 нормальный; }; поэтому 3 координаты для положения, 2 координаты для TU/TV и 3 координаты для нормалей. На вершину. 3 вершины на треугольник, 6 вершин на прямоугольник. И так далее. - person Mikael Törnqvist; 14.11.2014
comment
Здесь то же самое, только нормалей нет, хотя данные у меня есть. (Я написал программу чтения файлов obj с выводом raw vector< vector <float> >. Он скопирован в стандартную структуру вершин) - person Rashid Ellis; 14.11.2014
comment
Вам не нужны обычные данные, если вы не хотите использовать BumpMapping и Lightning и т. д., или CULL_BACK. Сначала заставьте это работать. Создайте новый Obj всего из 4-6 треугольников. Проверьте результат. Я уверен, что это облегчит отладку :) - person Mikael Törnqvist; 14.11.2014
comment
Я не уверен, как реализовать дополнительный размер, чтобы учесть размер текстурных координат. Если я увеличу размер массива вершин до числа координат текстуры, не приведет ли это к ошибочным значениям вершин? Есть ли способ определить BufferDescription.ByteWidth = sizeof(vtest) * sz_Texcoord; для учета обеих записей? или еще лучше иметь структуру вершин с двумя отдельными элементами данных массива? Я протестировал некоторую реализацию этого, но ничего не прошло. - person Rashid Ellis; 15.11.2014
comment
Похоже, что объектный файл имеет несколько индексов для каждой вершины/координаты текстуры/нормали. Я собираюсь поработать над этим и вернуться. - person Rashid Ellis; 16.11.2014

Из Maya попробуйте реэкспортировать текстуру после выполнения экструдирования для правильного отображения UV.

Выдавливание создает новые грани, а существующее УФ-отображение к ним не применяется. Попробуйте использовать инструмент очистки геометрии.

Насколько я понимаю, вы редактируете модель после создания УФ-карты и не обновляете УФ-карту до экструдированного объекта (который все еще является планировщиком).

Вы также можете попробовать вариант Expert all, который включает текстуру, а не только модель в .obj.

Давно не пользовался Maya :(

person Abdullah Leghari    schedule 14.11.2014
comment
Я думаю, что я попытаюсь импортировать вывод obj в Blender; Если импорт работает, вероятно, это мой импортер obj. - person Rashid Ellis; 14.11.2014
comment
Хорошо, импорт в Blender идет нормально, и это хорошо. Я должен делать что-то с кодом. Я рассмотрю проблему с плавающей запятой с бесконечно малыми. - person Rashid Ellis; 14.11.2014