Переместить объекты в указанные точки сцены? - PullRequest
4 голосов
/ 23 января 2011

Я пытался собрать игру в шахматы, используя модель 3dsmax.К этому моменту я смог импортировать модель, выделить выбранную часть игры, в которой я заинтересован, и выбрать квадрат, на который я хочу перейти.Вот скриншот текущего состояния:

http://img26.imageshack.us/img26/9555/chessk.png

Черный кружок показывает, где я нажал, и вы можете увидеть, куда ушла пешка.Я не делал конкретные расчеты о том, куда он должен идти.Всякий раз, когда я щелкаю по доске выбранной фигурой, она всегда движется в одном и том же направлении.Это потому, что для начала просто добавили этот фиктивный код:

if ( isObjectSelected && isSquareSelected && moveObject )
{
    glPushMatrix();
    glTranslatef(0.2f, 0.0f, 0.0f); //PLACEHOLDER-DUMMY CODE
}

glDrawElements( GL_TRIANGLES, pMaterial->triangleCount * 3, GL_UNSIGNED_INT, model.getIndexBuffer() + pMaterial->startIndex );

if ( isObjectSelected && isSquareSelected )
    glPopMatrix();

Что я хотел сделать, так это то, что после того, как модель закончила загрузку, я должен каким-то образом проверить, какой квадрат на доске занимает игровая фигура.Затем, когда фигура выбрана и выбран квадрат «перейти к», найдите x, y, z glTranslate3f, чтобы переместиться в этот центральный квадрат.

Это лучший способ?Похоже, что по ходу игры мне нужно будет хранить glTranslate каждого элемента в отдельности.И когда фигура переходит со 2-го на 3-е место, я должен вычислить glTranslate от исходной начальной точки до 3-го места, верно?

Но как бы вы выяснили, занимает ли игровой элемент квадрат или нети как бы вы выяснили glTranslate3f (X, Y, Z) между двумя квадратами?Вот пример квадрата из моего файла .OBJ

#
# object Square58
#

v  -37.1874 18.6313 80.7864
v  -67.0955 18.6313 91.4436
v  -56.4384 18.6313 121.3513
v  -26.5306 18.6313 110.6938
# 4 vertices

vn 0.0000 1.0000 -0.0000
# 1 vertex normals

vt 0.0000 0.0000 0.0000
# 1 texture coords

Я предполагаю, что мне нужно будет найти центр каждого квадрата и сказать, как только приложение узнает, что этот фрагмент находится в square1, и вы нажали наsqaure4, подсчитайте перевод и иди.Я просто не уверен, как рассчитать центр каждого квадрата и выяснить, какие координаты перевода должны быть из квадрата 1 -> квадрат 4.

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

Каждая часть квадрата и игры представляет собой структуру GroupObject, такую ​​как:

//A chess piece or square
struct GroupObject
{
    std::vector<Material *> materials;
    std::string             objectName;
    std::string             groupName;
    int                     index;
    std::vector<Vector3 *>  vertices;
    Vector3                 center;
};

И Vector3 выглядит так:

#ifndef VECTOR3_H
#define VECTOR3_H

#include <math.h>

class Vector3
{
public:
Vector3(float X = 0.0f, float Y = 0.0f, float Z = 0.0f)
{
    x = X;
    y = Y;
    z = Z;
}

Vector3 operator+=(const Vector3 &vec)
{
    return (*this = (*this + vec) );
}

Vector3 operator+(const Vector3 &vec)
{
    return Vector3(vec.x + x, vec.y + y, vec.z + z);
}

Vector3 operator-=(const Vector3 &vec)
{
    return (*this = (*this - vec) );
}

Vector3 operator-(const Vector3 &vec)
{
    return Vector3(x - vec.x, y - vec.y, z - vec.z);
}

Vector3 operator*=(float num)
{
    return (*this = (*this * num) );
}

Vector3 operator*(float num)
{
    return Vector3(x * num, y * num, z * num);
}

Vector3 operator/=(float num)
{
    return (*this = (*this / num) );
}

Vector3 operator/(float num)
{
    return Vector3(x / num, y / num, z / num);
}

Vector3 operator-(void)
{
    //invert direction of vector
    return Vector3(-x, -y, -z);
}

float Dot(Vector3 &vec)
{
    return (x * vec.x + y * vec.y + z * vec.z);
}

Vector3 operator*(const Vector3 &vec)
{
    //cross product
    return Vector3( y * vec.z - z * vec.y,
                    z * vec.x - x * vec.z,
                    x * vec.y - y * vec.x );
}

float Length(void)
{
    //length of vector
    return sqrt( x * x + y * y + z * z);
}

Vector3 Normalize(void)
{
    float length = Length();
    x /= length;
    y /= length;
    z /= length;

    return *this;
}

float Distance(Vector3 &vec)
{
    //find distance between two separate vectors
    float disX = vec.x - x;
    float disY = vec.y - y;
    float disZ = vec.z - z;

    return sqrt(disX * disX + disY * disY + disZ * disZ);
}

bool operator==(Vector3 &vec)
{
    return (vec.x == x && vec.y == y && vec.z == z);
}

bool operator!=(Vector3 &vec)
{
    return !(vec == *this);
}

public: float x, y, z;};

#endif

Я собирался использовать это для хранения центра каждого квадрата, например:

Vector3 square-> center = X, Y, Z

Надеюсьэто помогло бы ему определить, куда двигаться, и если что-то занимает это место, но подумал, что мне следует получить некоторую помощь, так как я раньше этого не делал.Я также не уверен, как мне рассчитать это, или все еще совершенно ясно, как выяснить, есть ли у квадрата игровая фигура, которая занимает ее в начале, или она пуста.

Любая и вся помощь приветствуется,Спасибо.

ОБНОВЛЕНИЕ

Прямо сейчас у меня был приятельский взгляд в 3ds max, и на свойствах квадратного объекта он сказал, что размеры были x: 40.565 y: 40.565

Затем я выбрал два квадрата, один перед другим.Я рассчитал центр каждого из них, сложив все вершины вместе и разделив их на сумму вершин.Я получил это:

#square 1
x: 111.12125
y: 18.631268
z: 78.286982

#square 2
x: 82.276817
y: 17.615297
z: 88.545845

Но из моего оригинального примера, единственный способ приблизиться к правильному месту - это перемещение glTranslatef (0.2f, 0.0f, 0.0f);

Разница между двумя центрами, перечисленными выше, намного больше.Я делаю что-то неправильно, но не вижу этого.

Ответы [ 2 ]

3 голосов
/ 23 января 2011

[a-bit-offtopic] Когда я кодировал свой университетский проект, я рисовал свой «мир» (который имеет нечто похожее с check-desk: он бесконечный и не имеет цветовых различий), используя простые математические формулы дляопределение каждой точки пересечения линии.Когда я получил эти точки, я смог просто определить, какой именно квадратный курсор указывает.Если честно, я использовал простую математику для определения этих центров в последней («производственной») версии.

Здесь и там - мои старые экраны.

Так в чем же проблема?Когда вы делаете glPushMatrix(), ваша матрица сбрасывается к значениям по умолчанию - положение становится (0, 0, 0), и вращения сбрасываются.Если вы хотите поместить свой объект в точку пересечения {линия, плоскость}, где линия - это луч от начала камеры до положения курсора (вспомните теорию камеры в OpenGL: фактически, экран - это плоскость перед точкой положения камеры)) и самолет что-то перед этим лучом. Примечание: если вы не определите плоскость - вы не сможете определить точку пересечения.

Теперь, когда у вас будет точка пересечения, просто выполните glTranslatef(<intersection_point>) изатем нарисуйте свою пешку или что-то в этом роде.

Если вас интересует чистый код для определения точки пересечения - просто сообщите мне в комментариях.

Надеюсь, это поможет.

UPD: вот код точки пересечения, который я упоминал ранее.Он использует sf::Vector3f структуру / класс - он взят из SFML (я использую его для всех моих проектов GL, чтобы обрабатывать входные события и забывать о создании окна).Вы можете определить его как простую структуру с 3 поплавками.Аргументы функции - это координаты курсора мыши.Вызов этого даст вам координаты точки пересечения.

sf::Vector3f ScreenToSpace(int x, int y)
{
    GLint viewport[4];
    GLdouble modelview[16];
    GLdouble projection[16];
    GLfloat winX, winY, winZ;
    GLdouble posX, posY, posZ;

    glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
    glGetDoublev(GL_PROJECTION_MATRIX, projection);
    glGetIntegerv(GL_VIEWPORT, viewport);

    winX = (float) x;
    winY = (float) viewport[3] - (float) y;
    glReadPixels(x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);

    gluUnProject(winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);

    return sf::Vector3f((float) posX, (float) posY, (float) posZ);
}

Вот пример того, как вы должны использовать это (насколько я понял вашу проблему):

sf::Vector3f v = ScreenToSpace(App.GetInput().GetMouseX(), App.GetInput().GetMouseY()); // get global coordinates
v = SpaceToDeskCorrection(v.x, v.y, v.z); // align v to the check-desk cell center

glPushMatrix(); // reset matrix state (incl. position and rotation) and save previous one
  glTranslatef(v.x, v.y, v.z); // set matrix position to the intersection point
  DrawPawn(); // well, you'll understand this line, right? =)
glPopMatrix();
2 голосов
/ 23 января 2011

Я недавно сделал игру в шашки, 2D, но применяются те же принципы. Прежде всего, я бы посоветовал вам сохранить массив с квадратами доски, который, как вы определили в вашей структуре, имеет центр var.

Чтобы узнать, где находится каждая часть, вы можете, например, добавить переменную, которая является указателем на данный квадрат, или просто представление, подобное «E4» или «A8» (квадратный код). Имея это, вы автоматически получите координаты x, y, где находится фигура, и, однажды определив, в какой квадрат вы хотите переместить ее, вы просто подставляете указатель на новую фигуру и получаете информацию о ее центре, где вы хотите перевести кусок в. Это также имеет дополнительное преимущество: теперь вам легче проверять, когда фигура захватывает другую у противника, или просто если она может переместиться на определенный квадрат (просмотрите все фигуры, если какая-либо из них лежит на площади, на которую вы хотите попасть, не разрешайте движение).

Чтобы узнать центр любого квадрата, предполагая, что вы не знаете его при создании доски (не так ли?), И сделайте среднее значение по всем составляющим вершинам координат x и y (если доска лежа на плоскости ху). Например, Square58 center = (v1 (x) + v2 (x) + v3 (x) + v4 (x); v1 (y) + v2 (y) + v3 (y) + v4 (y)).

Надеюсь, это было достаточно ясно, если не просто дайте мне знать, что вы не получили, и я постараюсь объяснить.

РЕДАКТИРОВАТЬ: Извините, я написал что-то не так. В центральной линии Square58 .... вы делите окончательную сумму на 4 (чтобы получить среднее значение) .. т.е.:

Square58 center = ((v1 (x) + v2 (x) + v3 (x) + v4 (x)) / 4; (v1 (y) + v2 (y) + v3 (y) + v4 (y )) / 4).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...