Доступ к поплавкам XMMatrix - оператор () не работает

Я пытаюсь сделать некоторые 3D-материалы в DirectX (я перехожу с OpenGL), и я столкнулся с проблемой.

Я хочу получить доступ к значениям XMMATRIX, и, глядя на документацию Microsoft, должен быть оператор ():

    float&  operator ()(
  size_t Row,
  size_t Column
);

Итак, я попытался использовать как таковой:

XMMATRIX i = XMMatrixIdentity();
float j = i(0,0);

Но Intellisense выдает мне ошибку:

IntelliSense: вызов объекта типа класса без соответствующего оператора() или функций преобразования в тип указателя на функцию.

Если я игнорирую Intellisense и все равно компилирую, я получаю ошибку времени компиляции:

ошибка C2064: термин не оценивается как функция, принимающая 2 аргумента

Кто-нибудь знает, почему это происходит? Или другой способ доступа к элементам Матрицы?

Спасибо за ваше время.

P.S. Я создаю приложение C++/DirectX Modern UI для Windows 8, если эта информация вообще поможет.


person poncho    schedule 04.07.2013    source источник
comment
Что произойдет, если вы измените вызов на i.operator()(0,0)?   -  person Alex1985    schedule 04.07.2013
comment
@LuchianGrigore Посмотрите на мой вопрос - я тоже компилирую...   -  person poncho    schedule 05.07.2013


Ответы (5)


Проверьте эту ссылку MSDN, и вы увидите, что это зависит от того, какой математический заголовок DirectX или XNA у вас есть, и от действующих на данный момент определений препроцессора. По умолчанию и из соображений оптимизации матричные и векторные структуры будут реализованы с использованием SSE и встроенных функций, что усложняет и удорожает предоставление доступа к строкам/столбцам.

Попробуйте определить _XM_NO_INTRINSICS_ в директиве препроцессора записи C++ свойств вашего проекта или #define _XM_NO_INTRINSICS_ перед #include любыми заголовками DirectX.

Этот отрывок из DirectXMath.h в моей системе Windows 8 VS2012 показывает, почему вы получаете эту ошибку:

struct XMMATRIX
{
    // ... code removed for clarity

#ifdef _XM_NO_INTRINSICS_
    float       operator() (size_t Row, size_t Column) const { return m[Row][Column]; }
    float&      operator() (size_t Row, size_t Column) { return m[Row][Column]; }
#endif

    // ... code removed for clarity
};
person Roger Rowland    schedule 04.07.2013
comment
Единственная причина, по которой я хочу получить доступ к этому, заключается в учебнике здесь: braynzarsoft.net/index .php?p=D3D11PICKING, который делает это для 'camProjection', чтобы повернуть шнуры мыши X/Y из пространства экрана в пространство просмотра. Я действительно не понимаю математику, чтобы сделать это без использования camProjection (0,0) и т. Д. Если бы кто-нибудь мог дать мне быстрое объяснение / ссылку на учебник о том, почему мы должны сделать это для Z, я был бы очень признателен. - person poncho; 05.07.2013
comment
@poncho хорошо, но вам лучше поднять это как новый вопрос - ваш вопрос выше очень хорошо вписывается в формат вопроса/ответа SO, очень чистый, так почему бы не расширить свой комментарий в новый вопрос, возможно, с соответствующим кодом . - person Roger Rowland; 05.07.2013
comment
да ладно это имеет смысл. Большое спасибо за помощь до сих пор :) - person poncho; 05.07.2013

Доступ к отдельным элементам для XMVECTOR и XMMATRIX очень неэффективен из-за базового набора инструкций SIMD, поэтому библиотека DirectXMath не поддерживает его через методы-члены. Есть несколько способов добиться этого в зависимости от ваших потребностей.

Если вам просто нужен элемент (0,0), вы можете использовать:

float j = XMVectorGetX( i.r[0] );

Если вы собираетесь получить доступ к большинству или ко всем отдельным элементам XMMATRIX, лучшим решением будет выгрузить их в XMFLOAT4X4:

XMFLOAT4X4 tmp;
XMStoreFloat4x4( &tmp, i );
float j = tmp.m[0][0]; // or float j = tmp._11

Я зарегистрирую ошибку документа, потому что оператор(), упомянутый в MSDN, на самом деле является «XNAMath», а не «DirectXMath». См. эту запись в блоге для получения дополнительной информации. .

Если вы находите DirectXMath слишком жестким для ваших нужд, вы можете рассмотреть возможность использования SimpleMath в Набор инструментов DirectX.

person Chuck Walbourn    schedule 20.10.2014

Я обнаружил, что это работает, я тоже основывал свой код на том же учебнике по выбору лучей и перехожу от xnamath к directxmath.

Это позволит выбрать правильные значения из матрицы без необходимости отключения SSE Intrinsics.

«Проекция» — это XMMATRIX, содержащий матрицу вида с камеры.

    XMVECTOR xv = projection.r[0];
    XMVECTOR yv = projection.r[1];
    PRVecX =  ((( 2.0f * mouseX) / Window::ClientWidth) - 1 ) / XMVectorGetX(xv);
    PRVecY = -((( 2.0f * mouseY) / Window::ClientHeight) - 1 ) / XMVectorGetY(yv);

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

person braindigitalis    schedule 03.02.2015

Добавьте #define _XM_NO_INTRINSICS_ в начало файла。

#include <windows.h>
#define _XM_NO_INTRINSICS_//must before #include <DirectXMath.h>
#include <DirectXMath.h>
#include <iostream>
person jiangke    schedule 24.02.2017

Можешь попробовать:

XMMATRIX i = XMMatrixIdentity();
float j = i.r[0].m128_f32[0];
person user1827502    schedule 19.10.2014
comment
Это не будет переносимо на ARM-NEON. float j = XMVectorGetX( i.r[0] ); работает, но не является особенно эффективным способом кодирования. - person Chuck Walbourn; 20.10.2014