Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 06.06.2020, 12:14   #1
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию если освободить курсор и захватить его снова, то при первом движении мыши камера опять развернётся в положение 90 градусов по Х. Почему так?

На хаброхабре есть статьи (не уголовные) про новый OpenGL: https://habr.com/en/post/310790/
Прочитал их с 1-ой по 9-ую. За некоторым исключением, всё понятно. Однако, не понятно про камеру.
В девятой части у них написано как сделать камеру. Если переписать код как есть, то камера работает. Но есть странный глюк. При первом движении мыши, камера резко разворачивается в положение 90 градусов по оси Х. А потом всё нормально. Не пойму, почему так происходит.
Вот мой код: https://pastebin.com/gQMdP7sp
Я его немного модифицировал для упрощения понимания. Ввёл структуру CAMERA. Переименовал некоторые переменные. Сделал, чтобы курсор захватывался при клике в окно и освобождался при нажатии ESC. Но суть осталась той же.
Кстати, если освободить курсор и захватить его снова, то при первом движении мыши камера опять развернётся в положение 90 градусов по Х. Почему так?
Оригинальный код с хаброхабра, без моих модификаций, так же глючит.
почему так?
BLACK_RAIN вне форума Ответить с цитированием
Старый 07.06.2020, 10:36   #2
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

В ходе длительных экспериментальных тыканий выяснилось, что после захвата курсора, при первом перемещении мыши камера разворачивается в положение, заданное в поле rotation структуры CAMERA.
почему так?
Код:
struct CAMERA
{
    glm::vec3 position = glm::vec3(0.0f, 0.0f, 10.0f);
    glm::vec3 rotation = glm::vec3(0.0f, 0.0f, 0.0f);
    glm::vec3 front = glm::vec3(cos(glm::radians(rotation.x)) * cos(glm::radians(rotation.y)),
                                sin(glm::radians(rotation.y)),
                                sin(glm::radians(rotation.x)) * cos(glm::radians(rotation.y)));
    glm::vec3 direction = glm::normalize(position - front);
    glm::vec3 upVector = glm::vec3(0.0f, 1.0f, 0.0f);
    glm::vec3 right = glm::normalize(glm::cross(upVector, direction));
    glm::vec3 cameraUp = glm::cross(direction, right);
}camera;

void glfw_mouse_pos_callback(GLFWwindow* window, double xPos, double yPos)
{
	if (!mouseGrabbed)
       {
		return;
	}

	glm::vec3 oldRotation = camera.rotation;

    static int lastX = 0;
    static int lastY = 0;
    static float yaw = camera.rotation.x;
    static float pitch = camera.rotation.y;
	static bool firstMouse = true;

    if (firstMouse)
    {
        lastX = (int)xPos;
        lastY = (int)yPos;
        firstMouse = false;
    }

    std::cout << "yaw = " << yaw << std::endl;
    std::cout << "xPos = " << xPos << std::endl;
    std::cout << "lastX= " << lastX << std::endl;

    float xOffset = xPos - lastX;
    float yOffset = lastY - yPos;
    lastX = (int)xPos;
    lastY = (int)yPos;

    float sensitivity = 0.05f;
    xOffset *= sensitivity;
    yOffset *= sensitivity;

    yaw   += xOffset;
    std::cout << "xOffset = " << xOffset << std::endl;
    std::cout << "yaw2 = " << yaw << std::endl;
    pitch += yOffset;

    if (pitch > 89.0f)  pitch = 89.0f;
    if (pitch < -89.0f) pitch = -89.0f;

    camera.rotation.x = yaw;
    std::cout << "camera.rotation.x = " << camera.rotation.x << std::endl;
    camera.rotation.y = pitch;

    glm::vec3 front;
    front.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
    front.y = sin(glm::radians(pitch));
    front.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
    camera.front = glm::normalize(front);

    if (camera.rotation.x != oldRotation.x ||
        camera.rotation.y != oldRotation.y ||
        camera.rotation.z != oldRotation.z)
    {
        CameraRotationChanged(camera);
    }
}

void key_callback(GLFWwindow* wnd, int key, int scancode, int action, int mode)
{
    if (action == GLFW_PRESS)
    {
        switch (key)
        {
            case GLFW_KEY_ESCAPE:
            case GLFW_KEY_ENTER:
                if (mouseGrabbed)
                {
                    glfwSetInputMode(wnd, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
                    mouseGrabbed = false;
                    std::cout << "Mouse is released" << std::endl;
                }
                else
                {
                    glfwSetWindowShouldClose(wnd, true);
                }
                return;
        }
        keys[key] = true;
    }
    else if (action == GLFW_RELEASE)
    {
        keys[key] = false;
    }
}

void callback_func_MouseClicked(GLFWwindow* wnd, int button, int action, int mods)
{
    if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
    {
        if (!mouseGrabbed)
        {
            glfwSetCursorPos(wnd, screenWidth / 2, screenHeight / 2);
            glfwSetInputMode(wnd, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
            mouseGrabbed = true;
            std::cout << "Mouse is grabbed" << std::endl;
        }
    }
}
BLACK_RAIN вне форума Ответить с цитированием
Старый 07.06.2020, 11:16   #3
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

Cтранно. Раньше мою другую тему с нормальным названием переименовали в "почему так?", а сейчас почему-то наоборот.

Последний раз редактировалось BLACK_RAIN; 07.06.2020 в 13:51.
BLACK_RAIN вне форума Ответить с цитированием
Старый 07.06.2020, 13:50   #4
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

Я разобрался. Проблема была из-за неправильного определения сдвига мыши (mouse delta). Надо
было создать две глобальные переменные. При клике в окно, сохранить в них центр экрана и программно переместить туда курсор. А потом просто искать разницу. В общем, как делали наши деды.
Однако, у меня есть старый проект для старого OpenGL и там написан код:
Код:
void glfw_mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {
	switch (button) {
	case GLFW_MOUSE_BUTTON_LEFT:
		switch (action) {
		case GLFW_PRESS:
			if (glfwGetInputMode(window, GLFW_CURSOR) != GLFW_CURSOR_DISABLED) {
				glfwSetCursorPos(window, glScreenWidth / 2, glScreenHeight / 2);
			}
			glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
			break;
		}
		break;
	}
}

void glfw_mouse_pos_callback(GLFWwindow* window, double xPos, double yPos) {
	if (glfwGetInputMode(glfw_window, GLFW_CURSOR) != GLFW_CURSOR_DISABLED) {
		//mouse is not grabbed
		return;
	}
	static double lastX = 0.0;
	static double lastY = 0.0;
	static float yaw = player.rotationX;
	static float pitch = player.rotationY;
	static bool firstMouse = true;

	if (firstMouse) {
		lastX = xPos;
		lastY = yPos;
		firstMouse = false;
	}

	float xoffset = xPos - lastX;
	float yoffset = lastY - yPos;
	lastX = xPos;
	lastY = yPos;

	float mouseCoef = 0.05;
	xoffset *= mouseSensitivity * mouseCoef;
	yoffset *= mouseSensitivity * mouseCoef;

	yaw += xoffset;
	pitch -= yoffset;

	if (pitch > 90.0)
		pitch = 90.0;
	if (pitch < -90.0)
		pitch = -90.0;

	static float oldRotationX = player.rotationX;
	static float oldRotationY = player.rotationY;

	player.rotationX = yaw;
	player.rotationY = pitch;

	while (player.rotationX < 0.0) {
		player.rotationX += 360.0;
	}
	while (player.rotationX >= 360.0) {
		player.rotationX -= 360.0;
	}

	if (player.rotationX != oldRotationX || player.rotationY != oldRotationY) {
		cameraChanged();
		oldRotationX = player.rotationX;
		oldRotationY = player.rotationY;
	}
}
Код был взят из интернета и немного модифицирован. В коде есть лишнее, так как проект не был допилен. Но это работало. Камера никуда не прыгала. И не были нужны никакие глобальные переменные. Сейчас запустить и проверить этот проект не могу, так как в вижуал студии почему-то перестало работать GLFW.
Если этот код работал раньше, почему он сейчас не работает? В чем разница?
BLACK_RAIN вне форума Ответить с цитированием
Старый 01.09.2020, 16:22   #5
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

Странная штука этот GLFW. Сейчас вставил этот же самый код (который глючил) в другой (еще один) новый проект. Ничего не менял. Только переименовал переменную player в camera. Он просто взял и заработал! Я не знаю, почему.
Есть предположение, что код почему-то не работает в MinGW, а в вижуал студии работает. Может ли быть такое? (вопрос не риторический)
Во время написания предыдущих постов я сидел на CodeBlocks + MinGW, потому что студия заглючила и перестала компилить GLFW. А сейчас я переустановил винду и студия снова заработала. И код в ней работает.
Вот допиленный код, из которого убрано всё лишнее:
Код:
struct CAMERA
{
    glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f);
    glm::vec3 rotation = glm::vec3(0.0f, 0.0f, 0.0f);
    glm::vec3 front = glm::vec3(
        cosf(glm::radians(rotation.x - 90.0f)) * cosf(glm::radians(rotation.y)),
        sinf(glm::radians(rotation.y)),
        sinf(glm::radians(rotation.x - 90.0f)) * cosf(glm::radians(rotation.y)));
    glm::vec3 upVector = glm::vec3(0.0f, 1.0f, 0.0f);
}camera;

void CameraRotationChanged(CAMERA& cam)
{
    glm::vec3 cameraFront(
        cosf(glm::radians(cam.rotation.x - 90.0f)) * cosf(glm::radians(cam.rotation.y)),
        sinf(glm::radians(cam.rotation.y)),
        sinf(glm::radians(cam.rotation.x - 90.0f)) * cosf(glm::radians(cam.rotation.y)));
    cam.front = glm::normalize(cameraFront);

    std::cout << "Rotation: [" << cam.rotation.x << " " << cam.rotation.y << "]" << std::endl;
}

void glfw_callback_MousePosition(GLFWwindow* wnd, double xPos, double yPos) 
{
    if (glfwGetInputMode(wnd, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)
    {
        static double lastX = xPos;
        static double lastY = yPos;

        float oldCameraRotationYaw   = camera.rotation.x;
        float oldCameraRotationPitch = camera.rotation.y;

        float mouseSensitivity = 0.1f;
        camera.rotation.x += (float)(xPos - lastX) * mouseSensitivity;
        camera.rotation.y -= (float)(yPos - lastY) * mouseSensitivity;

        lastX = xPos;
        lastY = yPos;

        float maxPitch = 89.9f;
        if (camera.rotation.y > maxPitch)
            camera.rotation.y = maxPitch;
        if (camera.rotation.y < -maxPitch)
            camera.rotation.y = -maxPitch;

        while (camera.rotation.x < 0.0f) {
            camera.rotation.x += 360.0f;
        }
        while (camera.rotation.x >= 360.0f) {
            camera.rotation.x -= 360.0f;
        }

        if (camera.rotation.x != oldCameraRotationYaw || camera.rotation.y != oldCameraRotationPitch) {
            CameraRotationChanged(camera);
        }
    }
}

void glfw_callback_MouseButtons(GLFWwindow* wnd, int button, int action, int mods)
{
    if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
    {
        if (glfwGetInputMode(wnd, GLFW_CURSOR) != GLFW_CURSOR_DISABLED)
        {
            glfwSetCursorPos(wnd, glScreenWidth / 2.0, glScreenHeight / 2.0);
            glfwSetInputMode(wnd, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
            std::cout << "Mouse is grabbed." << std::endl;
        }
    }
}
Никаких глобальнных переменных не требуется.
BLACK_RAIN вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
При движении курсора мыши над гридом значительно увеличивается загруженность процессора - Delphi БД ProRockX БД в Delphi 16 28.09.2015 02:57
веб-камера вместо мыши gunguru Помощь студентам 5 20.04.2012 17:21
опять Web-камера hiho Мультимедиа в Delphi 3 02.01.2012 13:15
Почему не обновляется курсор мыши? HunterMan Win Api 2 06.06.2008 01:39
Положение указателя мыши Viteef Общие вопросы Delphi 4 26.06.2007 15:59