Исправлена ​​ошибка, из-за которой 3D-камера двигалась в направлении, в котором она стоит?

Короткая версия (TL; DR)

у меня естьCamera прикреплен кSceneNode и движение работает нормально, покаSceneNodeВращение / оси ориентированы на мир. Однако, когда объект вращается, чтобы «смотреть» в другом направлении, и ему приказывают двигаться «вперед», это делаетне двигаться по новому «прямому» направлению. Вместо этого он продолжает двигаться в том же направлении, что и переддо вращение было применено.

Детали и пример

У меня есть график сцены для управления 3D-сценой. Граф это деревоSceneNode объекты, которые знают о своих трансформациях относительно своего родителя и мира.

Согласно TL; DR; фрагмент, представьте, что у вас естьcameraNode с нулевым вращением (например, лицом к северу), а затем повернитеcameraNode На 90 градусов влево вокруг оси + «вверх», то есть на запад. Пока все хорошо. Если вы сейчас попытаетесь переместитьcameraNode «вперед», который сейчас на западе,cameraNode вместо этого двигается, как будто «вперед» все еще смотрят на север.

Короче, двигаетсякак будто он никогда не вращался в первую очередь.

Приведенный ниже код показывает, что я пытался сделать совсем недавно, и мое (текущее) лучшее предположение о сужении областей, наиболее вероятно связанных с проблемой.

СоответствующийSceneNode члены

SceneNode реализация имеет следующие поля (показаны только те, которые имеют отношение к этому вопросу):

class GenericSceneNode implements SceneNode {
    // this node's parent; always null for the root scene node in the graph
    private SceneNode parentNode;

    // transforms are relative to a parent scene node, if any
    private Vector3 relativePosition = Vector3f.createZeroVector();
    private Matrix3 relativeRotation = Matrix3f.createIdentityMatrix();
    private Vector3 relativeScale    = Vector3f.createFrom(1f, 1f, 1f);

    // transforms are derived by combining transforms from all parents;
    // these are relative to the world --in world space
    private Vector3 derivedPosition = Vector3f.createZeroVector();
    private Matrix3 derivedRotation = Matrix3f.createIdentityMatrix();
    private Vector3 derivedScale    = Vector3f.createFrom(1f, 1f, 1f);
    // ...
}

ДобавлениеCamera к сцене просто означает, что она привязана кSceneNode на графике. ПосколькуCamera не имеет собственной позиционной / вращательной информации, клиент просто обрабатываетSceneNode к которомуCamera прилагается и все.

За исключением проблемы, упомянутой в этом вопросе, все остальное работает как положено.

SceneNode Перевод

Математика для перевода узла в определенном направлении проста и в основном сводится к:

currentPosition = currentPosition + normalizedDirectionVector * offset;

SceneNode реализация следует:

@Override
public void moveForward(float offset) {
    translate(getDerivedForwardAxis().mult(-offset));
}

@Override
public void moveBackward(float offset) {
    translate(getDerivedForwardAxis().mult(offset));
}

@Override
public void moveLeft(float offset) {
    translate(getDerivedRightAxis().mult(-offset));
}

@Override
public void moveRight(float offset) {
    translate(getDerivedRightAxis().mult(offset));
}

@Override
public void moveUp(float offset) {
    translate(getDerivedUpAxis().mult(offset));
}

@Override
public void moveDown(float offset) {
    translate(getDerivedUpAxis().mult(-offset));
}

@Override
public void translate(Vector3 tv) {
    relativePosition = relativePosition.add(tv);
    isOutOfDate = true;
}

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

SceneNode вращение

Клиентское приложение вращаетcameraNode следующее:

final Angle rotationAngle = new Degreef(-90f);
// ...
cameraNode.yaw(rotationAngle);

ИSceneNode реализация также довольно проста:

@Override
public void yaw(Angle angle) {
    // FIXME?: rotate(angle, getDerivedUpAxis()) accumulates other rotations
    rotate(angle, Vector3f.createUnitVectorY());
}

@Override
public void rotate(Angle angle, Vector3 axis) {
    relativeRotation = relativeRotation.rotate(angle, axis);
    isOutOfDate = true;
}

Математический / код для вращения заключен в матричном объекте 3x3. Обратите внимание, что во время тестов вы можете видеть, что сцена вращается вокруг камеры, поэтому вращение действительно применяется, что делает эту проблему еще более загадочной для меня.

Векторы направления

Векторы направления - это просто столбцы, взятые из полученной матрицы вращения 3x3 относительно мира:

@Override
public Vector3 getDerivedRightAxis() {
    return derivedRotation.column(0);
}

@Override
public Vector3 getDerivedUpAxis() {
    return derivedRotation.column(1);
}

@Override
public Vector3 getDerivedForwardAxis() {
    return derivedRotation.column(2);
}
Вычисление производных преобразований

Если это актуально, то вот какparentNode преобразования объединяются для вычисления производных преобразованийthis пример:

private void updateDerivedTransforms() {
    if (parentNode != null) {
        /**
         * derivedRotation = parent.derivedRotation * relativeRotation
         * derivedScale    = parent.derivedScale    * relativeScale
         * derivedPosition = parent.derivedPosition + parent.derivedRotation * (parent.derivedScale * relativePosition)
         */
        derivedRotation = parentNode.getDerivedRotation().mult(relativeRotation);
        derivedScale = parentNode.getDerivedScale().mult(relativeScale);

        Vector3 scaledPosition = parentNode.getDerivedScale().mult(relativePosition);
        derivedPosition = parentNode.getDerivedPosition().add(parentNode.getDerivedRotation().mult(scaledPosition));
    } else {
        derivedPosition = relativePosition;
        derivedRotation = relativeRotation;
        derivedScale = relativeScale;
    }

    Matrix4 t, r, s;

    t = Matrix4f.createTranslationFrom(relativePosition);
    r = Matrix4f.createFrom(relativeRotation);
    s = Matrix4f.createScalingFrom(relativeScale);
    relativeTransform = t.mult(r).mult(s);

    t = Matrix4f.createTranslationFrom(derivedPosition);
    r = Matrix4f.createFrom(derivedRotation);
    s = Matrix4f.createScalingFrom(derivedScale);
    derivedTransform = t.mult(r).mult(s);
}

Это используется для распространения преобразований через граф сцены, так что дочернийSceneNodes может принять во внимание преобразования своих родителей.

Другие / связанные вопросы

За последние ~ 3 недели до публикации этого вопроса я прошел через несколько ответов внутри и за пределами SO (например,Вот, Вот, Вот, а такжеВотсреди нескольких других). Очевидно, что, хотя и связаны, они действительно не помогли в моем случае.

Ответы на вопросы в комментариях

Вы уверены, что при вычисленииderivedTransform ваши родителиderivedTransform уже вычислено?

Да, родительSceneNode всегда обновляется перед обновлением детей.update логика это:

@Override
public void update(boolean updateChildren, boolean parentHasChanged) {
    boolean updateRequired = parentHasChanged || isOutOfDate;

    // update this node's transforms before updating children
    if (updateRequired)
        updateFromParent();

    if (updateChildren)
        for (Node n : childNodesMap.values())
            n.update(updateChildren, updateRequired);

    emitNodeUpdated(this);
}

@Override
public void updateFromParent() {
    updateDerivedTransforms();  // implementation above
    isOutOfDate = false;
}

Этот кусок вызывает приватный метод в предыдущем разделе.

 code_dredd08 авг. 2016 г., 11:50
@FrancisCugler Я использую OpenGL 4.5. Вам нужно, чтобы я разместил шейдеры?
 code_dredd11 авг. 2016 г., 23:16
@kolenda, да, я уверен.SceneNode обновится, прежде чем пытаться обновить каких-либо дочерних элементов.
 Francis Cugler08 авг. 2016 г., 11:49
Какую версию OpenGL вы используете?
 kolenda11 авг. 2016 г., 17:48
Вы уверены, что при вычисленииderivedTransform производная-трансформация вашего родителя уже вычислена? Или, может быть, вы могли бы создать сцену с одним узлом и подключенной камерой и отладить ваши вычисления?
 code_dredd15 авг. 2016 г., 13:20
@kolenda Я сделал это за несколько дней до того, как опубликовал этот вопрос. Ничто не "выделялось" для меня как "ага !, есть проблема". Я стараюсь избегать публикации вопросов настолько, насколько могу ... У меня обычно заканчиваются идеи к тому времени, когда я публикуюсь (это было более 1,5 недель до попыток отладки).
 Francis Cugler08 авг. 2016 г., 12:01
Вы пытались просто визуализировать камеру отдельно вместо того, чтобы вложить ее узел в узел сцены?
 code_dredd08 авг. 2016 г., 12:03
@FrancisCugler Да, у меня есть отдельная ветка разработчика в моем репо, гдеCamera имеет свою собственную информацию и не нуждается вSceneNode для его положения / вращения и может двигаться самостоятельно. Он ведет себя точно так же, как и выше, с той же проблемой.
 kolenda12 авг. 2016 г., 17:08
Я хотел создать только один узел, прикрепить к нему камеру и вращать узел. Затем выйдите из системы или отладьте значения для локального / глобального вращения и вектора вперед. Вы должны получить некоторые неправильные значения, но в такой простой настройке должно быть легче обнаружить ошибку.
 code_dredd11 авг. 2016 г., 23:29
@kolenda, Кроме того, у меня уже есть 2 демонстрационные программы с узлами сцены и камерами, показывающими проблему. Можете ли вы уточнить свой второй вопрос?
 Francis Cugler08 авг. 2016 г., 11:55
Нет; просто хотел узнать, используете ли вы современный OpenGL или старые вызовы API 1.0. Я не знаком с Java, но я работал с OpenGL на C ++. Я знаю, что в OpenGL нет объекта Camera, и вам нужно создать его и прикрепить к сцене. Затем, когда вы отрендерите его, его перемещение и вращение зависит от полноты вашей заданной системы координат. Ваши расчеты матрицы MVP (Model View Projection) важны; и порядок, в котором вы делаете их для ротационного перевода и масштабирования, также важен.
 Francis Cugler08 авг. 2016 г., 12:04
 code_dredd08 авг. 2016 г., 11:58
@FrancisCugler я понимаю.Camera а такжеSceneNode объекты были определены мной. Даже если вы не знакомы с Java, вы знакомы с C ++ и OpenGL, так что вы, вероятно, уже понимаете семантику кода выше (перегрузка оператора без). Вы все еще можете заметить то, что я пропустил (например, математику или что-то еще). Если вы хотите, чтобы я добавил больше информации, дайте мне знать, что это будет.

Ответы на вопрос(1)

OpenGL v1.0 с использованием старых вызовов API: реализация объекта класса камеры при использовании его в классе сцены за пределами графа сцены класса сцены. Это написано на C ++

Camera.h

#ifndef CAMERA_H
#define CAMERA_H

#include "Core.h"

class Camera {    
private:
    Vector3 _v3EyePosition;
    Vector3 _v3LookCenter;
    Vector3 _v3Up;

public:
    Camera();
    ~Camera();    

    void Get3rdPersonLocation( Vector3 &v3Position, float &fAngle );
    void Set( Vector3 v3EyePosition, Vector3 v3LookCenter, Vector3 v3Up = Vector3( 0.0f, 1.0f, 0.0f ) );
    void Render();    
}; 

#endif

Camera.cpp

#include "stdafx.h"
#include "Camera.h"

Camera::Camera() {    
    _v3EyePosition = Vector3( 0.0f, 0.0f,  0.0f );
    _v3LookCenter  = Vector3( 0.0f, 0.0f, -1.0f );
    _v3Up          = Vector3( 0.0f, 1.0f,  0.0f );    
} 

Camera::~Camera() {
} 

void Camera::Get3rdPersonLocation( Vector3 &v3Position, float &fAngle ) {   
    v3Position._fX = _v3LookCenter._fX;
    v3Position._fY = _v3EyePosition._fY;
    v3Position._fZ = _v3LookCenter._fZ;

    // Find Angle
    float fX = _v3LookCenter._fX - _v3EyePosition._fX;
    float fZ = _v3LookCenter._fZ - _v3EyePosition._fZ;

    // Angle In Degrees
    fAngle = Math::Radian2Degree( atan2( fX, fZ ) );    
}     

void Camera::Set( Vector3 v3EyePosition, Vector3 v3LookCenter, Vector3 v3Up ) {    
    _v3EyePosition = v3EyePosition;
    _v3LookCenter  = v3LookCenter;
    _v3Up          = v3Up;    
}

void Camera::Render() {     
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();

    gluLookAt( _v3EyePosition._fX, _v3EyePosition._fY, _v3EyePosition._fZ,
               _v3LookCenter._fX,  _v3LookCenter._fY,  _v3LookCenter._fZ,
               _v3Up._fX,          _v3Up._fY,          _v3Up._fZ );     
}

вCamera«sRender функция, использующая старые вызовы API OpenGL, мы сначала загружаем в матрицу Modelview, затем загружаем матрицу тождеств; затем мы, наконец, используем метод gluLookAt (...) для glu, чтобы установить позиции нужных векторов.

Scene.h - имеет много членов и функций; но как в отношении сCamera Объект имеет камеру в качестве члена, а не указатель на камеру.

Scene.cpp - Render ()

void Scene::Render() {    
    // Update Camera
    _Camera.Set( _Player.GetPosition(), _Player.GetLookCenter() );

    // Position Camera
    _Camera.Render();    

    if ( UserSettings::Get()->_bQuit ) {
        return;
    }

    if ( _vpNodes.size() < 1 ) {
        // No SceneGraph To Render
        return;
    }

    EnableLights();

    // Send Items To Be Rendered
    // Clear 2nd Render Pass Container
    DeleteAllAlphaObjects();

    // Render All Opaque Objects (1st Pass) & Store 2nd Pass Objects
    _vpNodes[0]->RenderOGL( false, true );

    // Render All Objects With Alpha Values (2nd Pass)
    glEnable( GL_BLEND );
    glMatrixMode( GL_MODELVIEW );

    for ( std::vector<AlphaObject*>::iterator it = _vpAlphaObjects.begin(); it != _vpAlphaObjects.end(); ++it ) {
        // Set Model View Matrix
        glMatrixMode( GL_MODELVIEW );
        glPushMatrix();
        glLoadMatrixf( &(*it)->f16Matrix[0] );

        (*it)->pShape->RenderOGL( true, false );

        glMatrixMode( GL_MODELVIEW );
        glPopMatrix();
    }

    // Show Selected Weapon
    _Player.RenderWeapon();

    glDisable( GL_BLEND );

    DisableLights();

    return;    
} 

ЗдесьCamera не зависит отPlayer класс, а также иерархия сцены сцены, и мы используемCamera в сценеRender Вызов. Здесь мы устанавливаемCamera получивPlayerтекущее положение, аPlayer's LookCenter направление.

РЕДАКТИРОВАТЬ - Добавление класса игрока и связанного кода для расчета движения

enum Action {
    NO_ACTION = -1,
    MOVING_FORWARD = 0,
    MOVING_BACK,
    MOVING_LEFT,
    MOVING_RIGHT,
    LOOKING_LEFT,
    LOOKING_RIGHT,
    LOOKING_UP,
    LOOKING_DOWN,
}; // Action

Player.h

#ifndef PLAYER_H
#define PLAYER_H

#include "Core.h"

class Weapon;
class NodeTransform;

class Player {
private:
    enum MouseLook {
        ML_NORMAL = 1,
        ML_INVERT = -1,
    } _MouseLookState; // MouseLook

    Vector3 _v3Position;
    Vector3 _v3LookCenter;

    float _fLookDistance;
    float _fMaxUp;
    float _fMaxDown;

    float _fLinearSpeed;
    float _fAngularSpeed;

public:
    Player( float fLookDistance );
    ~Player();

    void    SetSpeed( float fLinear, float fAngular );

    void    SetMouseY( bool bInvert );
    void    SetLocation( Vector3 v3Position, Vector3 v3Direction = Vector3( 0.0f, 0.0f, -1.0f ) );
    void    Move( Action action, float fDeltaTime );

    bool    Update();   

    inline void     SetPosition( Vector3 v3Position );
    inline Vector3  GetPosition();
    inline Vector3  GetLookCenter();
    inline Vector3  GetLookDirection();         
};

inline void Player::SetPosition( Vector3 v3Position ) {
    Vector3 v3LookDirection;
    v3LookDirection = _v3LookCenter - _v3Position;

    _v3Position   = v3Position;
    _v3LookCenter = v3Position + v3LookDirection;
}

inline Vector3 Player::GetPosition() {  
    return _v3Position;
} 

inline Vector3 Player::GetLookCenter() {
    return _v3LookCenter;
} 

inline Vector3 Player::GetLookDirection() {    
    Vector3 v3LookDirection;
    v3LookDirection = _v3LookCenter - _v3Position;    
    v3LookDirection.Normalize();    
    return v3LookDirection;    
}

#endif

Player.cpp

#include "stdafx.h"
#include "Player.h"
#include "UserSettings.h"
#include "NodeTransform.h"

Player::Player( float fLookDistance ) {    
    _fLookDistance  = fLookDistance;    
    // Calculate Maximum Limits For Looking Up And Down
    _fMaxUp         = _fLookDistance * tan( Math::Degree2Radian( 50 ) );
    _fMaxDown       = _fLookDistance * tan( Math::Degree2Radian( 40 ) );

    _v3Position     = Vector3( 0.0f, 0.5f, 0.0f );
    _v3LookCenter   = Vector3( 0.0f, 0.5f, -fLookDistance );

    _fLinearSpeed   = 15.0f; // Units Per Second
    _fAngularSpeed  = 3.0f; // Radians Per Second

    SetMouseY( UserSettings::Get()->GetMouseInvert() );    
} 

Player::~Player() {
} // ~Player

void Player::SetMouseY( bool bInvert ) {    
    if ( bInvert ) {
        _MouseLookState = ML_INVERT;
    } else {
        _MouseLookState = ML_NORMAL;
    }       
} 

void Player::SetLocation( Vector3 v3Position, Vector3 v3Direction ) {    
    _v3Position   = v3Position;
    _v3LookCenter = v3Position + _fLookDistance*v3Direction;    
}

void Player::Move( Action action, float fDeltaTime ) {    
    Vector3 v3LookDirection;
    v3LookDirection = _v3LookCenter - _v3Position;

    switch ( action ) {
        case MOVING_FORWARD: {
            // Prevent Vertical Motion
            v3LookDirection._fY = 0.0f;
            _v3Position   += v3LookDirection*fDeltaTime*_fLinearSpeed;
            _v3LookCenter += v3LookDirection*fDeltaTime*_fLinearSpeed;
            break;
        }
        case MOVING_BACK: {
            // Prevent Vertical Motion
            v3LookDirection._fY = 0.0f;
            _v3Position   -= v3LookDirection*fDeltaTime*_fLinearSpeed;
            _v3LookCenter -= v3LookDirection*fDeltaTime*_fLinearSpeed;
            break;
        }
        case MOVING_LEFT: {
            // Get "Side" Direction & Prevent Vertical Motion
            v3LookDirection._fY = v3LookDirection._fX;
            v3LookDirection._fX = -v3LookDirection._fZ;
            v3LookDirection._fZ = v3LookDirection._fY;
            v3LookDirection._fY = 0.0f;

            _v3Position   -= v3LookDirection*fDeltaTime*_fLinearSpeed;
            _v3LookCenter -= v3LookDirection*fDeltaTime*_fLinearSpeed;
            break;
        }
        case MOVING_RIGHT: {
            // Get "Side" Direction & Prevent Vertical Motion
            v3LookDirection._fY = v3LookDirection._fX;
            v3LookDirection._fX = -v3LookDirection._fZ;
            v3LookDirection._fZ = v3LookDirection._fY;
            v3LookDirection._fY = 0.0f;

            _v3Position   += v3LookDirection*fDeltaTime*_fLinearSpeed;
            _v3LookCenter += v3LookDirection*fDeltaTime*_fLinearSpeed;
            break;
        }
        case LOOKING_LEFT: {

            /*float fSin = -sin( fDeltaTime*_fAngularSpeed );
            float fCos =  cos( fDeltaTime*_fAngularSpeed );

            _v3LookCenter._fX = _v3Position._fX + (-fSin * v3LookDirection._fZ + fCos * v3LookDirection._fX );
            _v3LookCenter._fZ = _v3Position._fZ + ( fCos * v3LookDirection._fZ + fSin * v3LookDirection._fX );
            break;*/

            // Third Person
            float fSin = sin( fDeltaTime*_fAngularSpeed );
            float fCos = -cos( fDeltaTime*_fAngularSpeed );

            _v3Position._fX = _v3LookCenter._fX + (-fSin * v3LookDirection._fZ + fCos * v3LookDirection._fX );
            _v3Position._fZ = _v3LookCenter._fZ + ( fCos * v3LookDirection._fZ + fSin * v3LookDirection._fX );
            break;
        }
        case LOOKING_RIGHT: {
            /*float fSin = sin( fDeltaTime*_fAngularSpeed );
            float fCos = cos( fDeltaTime*_fAngularSpeed );

            _v3LookCenter._fX = _v3Position._fX + (-fSin * v3LookDirection._fZ + fCos * v3LookDirection._fX );
            _v3LookCenter._fZ = _v3Position._fZ + ( fCos * v3LookDirection._fZ + fSin * v3LookDirection._fX );
            break;*/

            // Third Person
            float fSin = -sin( fDeltaTime*_fAngularSpeed );
            float fCos = -cos( fDeltaTime*_fAngularSpeed );

            _v3Position._fX = _v3LookCenter._fX + (-fSin * v3LookDirection._fZ + fCos * v3LookDirection._fX );
            _v3Position._fZ = _v3LookCenter._fZ + ( fCos * v3LookDirection._fZ + fSin * v3LookDirection._fX );
            break;
        }
        case LOOKING_UP: {
            _v3LookCenter._fY -= fDeltaTime*_fAngularSpeed*_MouseLookState;

            // Check Maximum Values
            if ( _v3LookCenter._fY > (_v3Position._fY + _fMaxUp ) ) {
                _v3LookCenter._fY = _v3Position._fY + _fMaxUp;
            } else if ( _v3LookCenter._fY < (_v3Position._fY - _fMaxDown) ) {
                _v3LookCenter._fY = _v3Position._fY - _fMaxDown;
            }
            break;
        }
    }    
}

bool Player::Update() {     
    // Stripped Down This Deals With Player's Weapons    
} 

void Player::SetSpeed( float fLinear, float fAngular ) {        
    _fLinearSpeed  = fLinear;
    _fAngularSpeed = fAngular;    
} 

Scene.h - То же самое, что и для камеры; есть объект Player, а не указатель на объект Player. Однако есть указатель на playerTransform, который является NodeTransform. Здесь слишком много функций, чтобы перечислять их из-за взаимодействия проигрывателя со сценой, поскольку это рабочая 3D-игра. Я могу предоставить несколько функций, которые могут представлять интерес.

Scene.cpp Scene::Update()

// -----------------------------------------------------------------------
// Update
// Animate Objects, Pickup Checks Etc. This All Happens At The
// Physics Refresh Rate
void Scene::Update() {

    UserSettings* pUserSettings = UserSettings::Get();
    AudioManager* pAudio = AudioManager::GetAudio();

    bool bPlayerMoving = false;

    // Movement
    if ( pUserSettings->IsAction( MOVING_FORWARD ) ) {
        _Player.Move( MOVING_FORWARD, GameOGL::GetPhysicsTimeStep() );
        bPlayerMoving = true;
    }

    if ( pUserSettings->IsAction( MOVING_BACK ) ) {
        _Player.Move( MOVING_BACK, GameOGL::GetPhysicsTimeStep() );
        bPlayerMoving = true;
    }

    if ( pUserSettings->IsAction( MOVING_LEFT ) ) {
        _Player.Move( MOVING_LEFT, GameOGL::GetPhysicsTimeStep() );
        bPlayerMoving = true;
    }

    if ( pUserSettings->IsAction( MOVING_RIGHT ) ) {
        _Player.Move( MOVING_RIGHT, GameOGL::GetPhysicsTimeStep() );
        bPlayerMoving = true;
    }    

    if ( bPlayerMoving && !_bPlayerWalking ) {
        pAudio->SetLooping( AUDIO_FOOTSTEPS, true );
        pAudio->Play( AUDIO_FOOTSTEPS );
        _bPlayerWalking = true;
    }
    else if ( !bPlayerMoving && _bPlayerWalking ) {
        pAudio->Stop( AUDIO_FOOTSTEPS );
        _bPlayerWalking = false;
    }  

    // ... Other Code Here    
}

РЕДАКТИРОВАТЬ - Добавление NodeTransform :: Render () - Показать порядок операций для MVP

// Move Model View Matrix M = (T C R S C^)
void NodeTransform::RenderOGL( bool bSecondPass, bool bRenderNext ) {    
    if ( _pIn && _bVisible ) {
        // Put Matrix Onto Stack For Later Retrieval
        glMatrixMode( GL_MODELVIEW );
        glPushMatrix();

        if ( _bHaveMatrix ) {
            // Use Transformation Matrix
            glMultMatrixf( &_f16Matrix[0] );
        }

        // Transalate
        glTranslatef( _v3Translate._fX, _v3Translate._fY, _v3Translate._fZ );

        // Move Back To Center
        glTranslatef( _v3Center._fX, _v3Center._fY, _v3Center._fZ );

        // Rotate
        glRotatef( _fRotateAngle, _v3RotateAxis._fX, _v3RotateAxis._fY, _v3RotateAxis._fZ );

        // Scale
        glScalef( _v3Scale._fX, _v3Scale._fY, _v3Scale._fZ );

        // Offset By -ve Center Value
        glTranslatef( -_v3Center._fX, -_v3Center._fY, -_v3Center._fZ );

        // Move Down The Tree
        _pIn->RenderOGL( bSecondPass, true );

        // Get Old Matrix
        glMatrixMode( GL_MODELVIEW );
        glPopMatrix();
    }

    if ( _pNext && bRenderNext ) {
        _pNext->RenderOGL( bSecondPass, true );
    }    
} // RenderOGL
 Francis Cugler09 авг. 2016 г., 15:46
Совершенно никаких проблем; Я не против помогать другим, где и когда я могу. Мне нравится помогать, чтобы однажды, когда мне понадобится помощь, другие сделали то же самое.
 code_dredd08 авг. 2016 г., 14:16
Ваше вычисление для перемещенияPlayer в том направлении, в котором он стоит, кажется похожим на мой.
 code_dredd09 авг. 2016 г., 01:56
Изучил довольно большой дамп кода более подробно, но, к сожалению, он не слишком помог мне понять, что я делаю неправильно. Математика действительно похожа на мою, особенно на движение игрока, но кроме этого, пост содержит много кода, который не слишком важен для основной проблемы, с которой я сталкиваюсь. Спасибо за то, что попробовали.

Ваш ответ на вопрос