Перейти к содержанию
alexbrez

Помощь с поиском MVP матрицы

Рекомендуемые сообщения

Собственно финальная цель отрисовки чего-то на экране по (x,y,z) координатам из игры, например, подсветка лута, добавление хп бара над персонажем и так далее. Собираюсь читать память из игры и использовать его в своем софте. По ощущениям удалось найти View матрицу, но я так понял, что в памяти должно храниться еще две -  Projection и World матрицы. Собственно нужна помощь с поиском из памяти и, возможно, c написанием world 2 screen функции на любом языке, если моя окажется нерабочей. Конечно, не за бесплатно. 

P.S. Интересует именно external подход, инжектить или хукать что-то напрямую  в игре не хочется.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Определение World, View и Projection матриц:
World Matrix: Определяет положение и ориентацию объектов в игровом мире.
View Matrix: Определяет, как сцена будет отображаться из точки зрения камеры.
Projection Matrix: Определяет, как 3D-координаты будут проецироваться на 2D-экран.

Для d3dx9.h

#include <d3dx9.h>
struct Vector3 {
    float x, y, z;
};
struct Vector2 {
    float x, y;
};
Vector2 WorldToScreen(const Vector3& worldPosition, const D3DXMATRIX& viewMatrix, const D3DXMATRIX& projectionMatrix, int screenWidth, int screenHeight) {
    // Преобразуем мировые координаты в координаты клипа
    D3DXVECTOR4 clipSpace;
    clipSpace.x = worldPosition.x * viewMatrix._11 + worldPosition.y * viewMatrix._21 + worldPosition.z * viewMatrix._31 + viewMatrix._41;
    clipSpace.y = worldPosition.x * viewMatrix._12 + worldPosition.y * viewMatrix._22 + worldPosition.z * viewMatrix._32 + viewMatrix._42;
    clipSpace.z = worldPosition.x * viewMatrix._13 + worldPosition.y * viewMatrix._23 + worldPosition.z * viewMatrix._33 + viewMatrix._43;
    clipSpace.w = worldPosition.x * viewMatrix._14 + worldPosition.y * viewMatrix._24 + worldPosition.z * viewMatrix._34 + viewMatrix._44;
    // Преобразуем координаты клипа в нормализованные координаты устройства
    if (clipSpace.w != 0.0f) {
        clipSpace.x /= clipSpace.w;
        clipSpace.y /= clipSpace.w;
        clipSpace.z /= clipSpace.w;
    }
    // Преобразуем нормализованные координаты устройства в экранные координаты
    Vector2 screenPosition;
    screenPosition.x = (clipSpace.x + 1.0f) * 0.5f * screenWidth;
    screenPosition.y = (1.0f - (clipSpace.y + 1.0f) * 0.5f) * screenHeight;
    return screenPosition;
}

Для современных версией есть DirectXMath.h:

#include <DirectXMath.h>
#include <iostream>
using namespace DirectX;
struct Vector3 {
    float x, y, z;
};
struct Vector2 {
    float x, y;
};
Vector2 WorldToScreen(const Vector3& worldPosition, const XMMATRIX& viewMatrix, const XMMATRIX& projectionMatrix, int screenWidth, int screenHeight) {
    // Преобразуем мировые координаты в координаты клипа
    XMVECTOR worldPos = XMLoadFloat3(reinterpret_cast<const XMFLOAT3*>(&worldPosition));
    XMVECTOR clipSpace = XMVector3Transform(worldPos, XMMatrixMultiply(viewMatrix, projectionMatrix));
    // Преобразуем координаты клипа в нормализованные координаты устройства
    XMFLOAT4 clipSpaceFloat;
    XMStoreFloat4(&clipSpaceFloat, clipSpace);
    if (clipSpaceFloat.w != 0.0f) {
        clipSpaceFloat.x /= clipSpaceFloat.w;
        clipSpaceFloat.y /= clipSpaceFloat.w;
        clipSpaceFloat.z /= clipSpaceFloat.w;
    }
    // Преобразуем нормализованные координаты устройства в экранные координаты
    Vector2 screenPosition;
    screenPosition.x = (clipSpaceFloat.x + 1.0f) * 0.5f * screenWidth;
    screenPosition.y = (1.0f - (clipSpaceFloat.y + 1.0f) * 0.5f) * screenHeight;
    return screenPosition;
}

 

Для поиска матриц, лучше использовать готовые мощные инструменты, либо пытаться писать и анализировать самому, чего-то такого:

#include <iostream>
#include <fstream>
#include <iomanip>

void ReadMemory(HANDLE hProcess, uintptr_t address) {
	std::ofstream logFile("l2memory.log", std::ios::app);
	if (!logFile.is_open()) {
		std::cerr << "Failed to open the file for writing" << std::endl;
		return;
	}
	int value;
	SIZE_T bytesRead;
	if (ReadProcessMemory(hProcess, (LPCVOID)address, &value, sizeof(value), &bytesRead) && bytesRead == sizeof(value)) {
		std::cout << "Address: " << std::hex << address << " Value (int): " << value << std::dec << std::endl;
		logFile << "Адрес: " << std::hex << address << " Значения (int): " << value << std::dec << std::endl;
		if (value > 0 && value < 256) {
			char buffer[2] = { static_cast<char>(value), '\0' };
			std::cout << "Interpreted as char: " << buffer << std::endl;
			logFile << "Интерпретировано как символ: " << buffer << std::endl;
		}
	}
	else {
		std::cerr << "Failed to read memory at the address: " << std::hex << address << std::dec << std::endl;
		logFile << "Не удалось прочитать память по адресу: " << std::hex << address << std::dec << std::endl;
		logFile.close();
		return;
	}
	char buffer[256];
	if (ReadProcessMemory(hProcess, (LPCVOID)(address + sizeof(value)), buffer, sizeof(buffer) - 1, &bytesRead) && bytesRead > 0) {
		buffer[bytesRead] = '\0';
		std::cout << "Address: " << std::hex << (address + sizeof(value)) << " Value (string): " << buffer << std::dec << std::endl;
		logFile << "Адрес: " << std::hex << (address + sizeof(value)) << " Значение (string): " << buffer << std::dec << std::endl;
	}
	else {
		std::cerr << "Failed to read the string at the address: " << std::hex << (address + sizeof(value)) << std::dec << std::endl;
		logFile << "Не удалось прочитать строку по адресу: " << std::hex << (address + sizeof(value)) << std::dec << std::endl;
	}
	std::cout << "Bytes in hex: ";
	logFile << "Вывод байтов в шестнадцатеричном формате: ";
	for (SIZE_T i = 0; i < sizeof(value); ++i) {
		std::cout << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(reinterpret_cast<unsigned char*>(&value)[i]) << " ";
		logFile << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(reinterpret_cast<unsigned char*>(&value)[i]) << " ";
	}
	for (SIZE_T i = 0; i < bytesRead; ++i) {
		std::cout << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(reinterpret_cast<unsigned char*>(buffer)[i]) << " ";
		logFile << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(reinterpret_cast<unsigned char*>(buffer)[i]) << " ";
	}
	std::cout << std::dec << std::endl;
	logFile << std::dec << std::endl;
	std::cout << "Filtered bytes: ";
	logFile << "Фильтрация нулевых байтов: ";
	for (SIZE_T i = 0; i < sizeof(value) + bytesRead; ++i) {
		unsigned char byte = (i < sizeof(value)) ? reinterpret_cast<unsigned char*>(&value)[i] : reinterpret_cast<unsigned char*>(buffer)[i - sizeof(value)];
		if (byte != 0) {
			std::cout << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(byte) << " ";
			logFile << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(byte) << " ";
		}
	}
	std::cout << std::dec << std::endl;
	logFile << std::dec << std::endl;
	logFile.close();
}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
В 15.01.2025 в 20:39, Saltfire сказал:

Определение World, View и Projection матриц:
World Matrix: Определяет положение и ориентацию объектов в игровом мире.
View Matrix: Определяет, как сцена будет отображаться из точки зрения камеры.
Projection Matrix: Определяет, как 3D-координаты будут проецироваться на 2D-экран.

Для d3dx9.h


#include <d3dx9.h>
struct Vector3 {
    float x, y, z;
};
struct Vector2 {
    float x, y;
};
Vector2 WorldToScreen(const Vector3& worldPosition, const D3DXMATRIX& viewMatrix, const D3DXMATRIX& projectionMatrix, int screenWidth, int screenHeight) {
    // Преобразуем мировые координаты в координаты клипа
    D3DXVECTOR4 clipSpace;
    clipSpace.x = worldPosition.x * viewMatrix._11 + worldPosition.y * viewMatrix._21 + worldPosition.z * viewMatrix._31 + viewMatrix._41;
    clipSpace.y = worldPosition.x * viewMatrix._12 + worldPosition.y * viewMatrix._22 + worldPosition.z * viewMatrix._32 + viewMatrix._42;
    clipSpace.z = worldPosition.x * viewMatrix._13 + worldPosition.y * viewMatrix._23 + worldPosition.z * viewMatrix._33 + viewMatrix._43;
    clipSpace.w = worldPosition.x * viewMatrix._14 + worldPosition.y * viewMatrix._24 + worldPosition.z * viewMatrix._34 + viewMatrix._44;
    // Преобразуем координаты клипа в нормализованные координаты устройства
    if (clipSpace.w != 0.0f) {
        clipSpace.x /= clipSpace.w;
        clipSpace.y /= clipSpace.w;
        clipSpace.z /= clipSpace.w;
    }
    // Преобразуем нормализованные координаты устройства в экранные координаты
    Vector2 screenPosition;
    screenPosition.x = (clipSpace.x + 1.0f) * 0.5f * screenWidth;
    screenPosition.y = (1.0f - (clipSpace.y + 1.0f) * 0.5f) * screenHeight;
    return screenPosition;
}

Для современных версией есть DirectXMath.h:


#include <DirectXMath.h>
#include <iostream>
using namespace DirectX;
struct Vector3 {
    float x, y, z;
};
struct Vector2 {
    float x, y;
};
Vector2 WorldToScreen(const Vector3& worldPosition, const XMMATRIX& viewMatrix, const XMMATRIX& projectionMatrix, int screenWidth, int screenHeight) {
    // Преобразуем мировые координаты в координаты клипа
    XMVECTOR worldPos = XMLoadFloat3(reinterpret_cast<const XMFLOAT3*>(&worldPosition));
    XMVECTOR clipSpace = XMVector3Transform(worldPos, XMMatrixMultiply(viewMatrix, projectionMatrix));
    // Преобразуем координаты клипа в нормализованные координаты устройства
    XMFLOAT4 clipSpaceFloat;
    XMStoreFloat4(&clipSpaceFloat, clipSpace);
    if (clipSpaceFloat.w != 0.0f) {
        clipSpaceFloat.x /= clipSpaceFloat.w;
        clipSpaceFloat.y /= clipSpaceFloat.w;
        clipSpaceFloat.z /= clipSpaceFloat.w;
    }
    // Преобразуем нормализованные координаты устройства в экранные координаты
    Vector2 screenPosition;
    screenPosition.x = (clipSpaceFloat.x + 1.0f) * 0.5f * screenWidth;
    screenPosition.y = (1.0f - (clipSpaceFloat.y + 1.0f) * 0.5f) * screenHeight;
    return screenPosition;
}

 

Для поиска матриц, лучше использовать готовые мощные инструменты, либо пытаться писать и анализировать самому, чего-то такого:


#include <iostream>
#include <fstream>
#include <iomanip>

void ReadMemory(HANDLE hProcess, uintptr_t address) {
	std::ofstream logFile("l2memory.log", std::ios::app);
	if (!logFile.is_open()) {
		std::cerr << "Failed to open the file for writing" << std::endl;
		return;
	}
	int value;
	SIZE_T bytesRead;
	if (ReadProcessMemory(hProcess, (LPCVOID)address, &value, sizeof(value), &bytesRead) && bytesRead == sizeof(value)) {
		std::cout << "Address: " << std::hex << address << " Value (int): " << value << std::dec << std::endl;
		logFile << "Адрес: " << std::hex << address << " Значения (int): " << value << std::dec << std::endl;
		if (value > 0 && value < 256) {
			char buffer[2] = { static_cast<char>(value), '\0' };
			std::cout << "Interpreted as char: " << buffer << std::endl;
			logFile << "Интерпретировано как символ: " << buffer << std::endl;
		}
	}
	else {
		std::cerr << "Failed to read memory at the address: " << std::hex << address << std::dec << std::endl;
		logFile << "Не удалось прочитать память по адресу: " << std::hex << address << std::dec << std::endl;
		logFile.close();
		return;
	}
	char buffer[256];
	if (ReadProcessMemory(hProcess, (LPCVOID)(address + sizeof(value)), buffer, sizeof(buffer) - 1, &bytesRead) && bytesRead > 0) {
		buffer[bytesRead] = '\0';
		std::cout << "Address: " << std::hex << (address + sizeof(value)) << " Value (string): " << buffer << std::dec << std::endl;
		logFile << "Адрес: " << std::hex << (address + sizeof(value)) << " Значение (string): " << buffer << std::dec << std::endl;
	}
	else {
		std::cerr << "Failed to read the string at the address: " << std::hex << (address + sizeof(value)) << std::dec << std::endl;
		logFile << "Не удалось прочитать строку по адресу: " << std::hex << (address + sizeof(value)) << std::dec << std::endl;
	}
	std::cout << "Bytes in hex: ";
	logFile << "Вывод байтов в шестнадцатеричном формате: ";
	for (SIZE_T i = 0; i < sizeof(value); ++i) {
		std::cout << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(reinterpret_cast<unsigned char*>(&value)[i]) << " ";
		logFile << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(reinterpret_cast<unsigned char*>(&value)[i]) << " ";
	}
	for (SIZE_T i = 0; i < bytesRead; ++i) {
		std::cout << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(reinterpret_cast<unsigned char*>(buffer)[i]) << " ";
		logFile << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(reinterpret_cast<unsigned char*>(buffer)[i]) << " ";
	}
	std::cout << std::dec << std::endl;
	logFile << std::dec << std::endl;
	std::cout << "Filtered bytes: ";
	logFile << "Фильтрация нулевых байтов: ";
	for (SIZE_T i = 0; i < sizeof(value) + bytesRead; ++i) {
		unsigned char byte = (i < sizeof(value)) ? reinterpret_cast<unsigned char*>(&value)[i] : reinterpret_cast<unsigned char*>(buffer)[i - sizeof(value)];
		if (byte != 0) {
			std::cout << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(byte) << " ";
			logFile << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(byte) << " ";
		}
	}
	std::cout << std::dec << std::endl;
	logFile << std::dec << std::endl;
	logFile.close();
}

 

Привет! Спасибо, в моём случае проблема больше с определением view матрицы и нахождение её в памяти, т.к. непонятно в каком формате она хранится в линейке, раздельно или сразу в виде MVP. А есть понимание почему в первом примере не используется projection матрица и что конкретно закодировано во view матрице?

Изменено пользователем alexbrez

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
В 17.01.2025 в 05:19, alexbrez сказал:

Привет! Спасибо, в моём случае проблема больше с определением view матрицы и нахождение её в памяти, т.к. непонятно в каком формате она хранится в линейке, раздельно или сразу в виде MVP. 

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

В 17.01.2025 в 05:19, alexbrez сказал:

А есть понимание почему в первом примере не используется projection матрица и что конкретно закодировано во view матрице?

Потерял, ты хотел просто пример.

Vector2 WorldToScreen(const Vector3& worldPosition, const D3DXMATRIX& viewMatrix, const D3DXMATRIX& projectionMatrix, int screenWidth, int screenHeight) {
    // Преобразуем мировые координаты в координаты клипа с использованием матрицы вида
    D3DXVECTOR4 clipSpace;
    clipSpace.x = worldPosition.x * viewMatrix._11 + worldPosition.y * viewMatrix._21 + worldPosition.z * viewMatrix._31 + viewMatrix._41;
    clipSpace.y = worldPosition.x * viewMatrix._12 + worldPosition.y * viewMatrix._22 + worldPosition.z * viewMatrix._32 + viewMatrix._42;
    clipSpace.z = worldPosition.x * viewMatrix._13 + worldPosition.y * viewMatrix._23 + worldPosition.z * viewMatrix._33 + viewMatrix._43;
    clipSpace.w = worldPosition.x * viewMatrix._14 + worldPosition.y * viewMatrix._24 + worldPosition.z * viewMatrix._34 + viewMatrix._44;
    // Применяем матрицу проекции
    D3DXVECTOR4 projectedSpace;
    projectedSpace.x = clipSpace.x * projectionMatrix._11 + clipSpace.y * projectionMatrix._21 + clipSpace.z * projectionMatrix._31 + clipSpace.w * projectionMatrix._41;
    projectedSpace.y = clipSpace.x * projectionMatrix._12 + clipSpace.y * projectionMatrix._22 + clipSpace.z * projectionMatrix._32 + clipSpace.w * projectionMatrix._42;
    projectedSpace.z = clipSpace.x * projectionMatrix._13 + clipSpace.y * projectionMatrix._23 + clipSpace.z * projectionMatrix._33 + clipSpace.w * projectionMatrix._43;
    projectedSpace.w = clipSpace.x * projectionMatrix._14 + clipSpace.y * projectionMatrix._24 + clipSpace.z * projectionMatrix._34 + clipSpace.w * projectionMatrix._44;
    // Преобразуем координаты клипа в нормализованные координаты устройства
    if (projectedSpace.w != 0.0f) {
        projectedSpace.x /= projectedSpace.w;
        projectedSpace.y /= projectedSpace.w;
        projectedSpace.z /= projectedSpace.w;
    }
    // Преобразуем нормализованные координаты устройства в экранные координаты
    Vector2 screenPosition;
    screenPosition.x = (projectedSpace.x + 1.0f) * 0.5f * screenWidth;
    screenPosition.y = (1.0f - (projectedSpace.y + 1.0f) * 0.5f) * screenHeight;
    return screenPosition;
}

Если ты хочешь это делать на уровне ладвы "без как ты хочешь хуков и адских калбеков", то пример для UE2.5 будет выглядеть так:

FVector2D WorldToScreen(const FVector& WorldPosition, APlayerController* PlayerController) {
    FVector2D ScreenPosition;
    // Проверяем, что PlayerController не равен nullptr
    if (PlayerController) {
        // Получаем размер окна
        int32 ScreenWidth = GEngine->GameViewport->Viewport->GetSizeXY().X;
        int32 ScreenHeight = GEngine->GameViewport->Viewport->GetSizeXY().Y;
        // Преобразуем мировую позицию в экранные координаты
        PlayerController->ProjectWorldLocationToScreen(WorldPosition, ScreenPosition);
        // Теперь ScreenPosition содержит координаты в диапазоне от (0, 0) до (ScreenWidth, ScreenHeight)
    }
    return ScreenPosition;
}

С учетом, что ты понимаешь как устроен UE2.5.
Но тебе еще придется очень сильно постараться, чтобы сие чудо запустить.
Шары сурсов для l2 не было, все приватное.

Но если ты хочешь это делать на D3 - то без хуков ты не справишься.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти

  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу

×
×
  • Создать...