XNA - Рендеринг деревьев поворотов и переводов - PullRequest
1 голос
/ 19 апреля 2011

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

Я не могу завершить свое дерево рендеринга, потому что не знаю, как кодировать следующее:

(я привык много работать с OpenGL, поэтому я ищу самый быстрый эквивалент этого кода)

public void DrawRecursively( GameTime deltaTime )
{
    glPushMatrix();

    /* these 3 lines are what i didn't figure out with XNA */
    glTranslate3f( position[0], position[1], position[2] );
    glRotatef( theta, 0.0f, 1.0f, 0.0f );
    glRotatef( phi, 1.0f, 0.0f, 0.0f );

    this.Draw( deltaTime );

    foreach ( ComponentInterface child in childs )
    {
        child.DrawRecursively( deltaTime );
    }

    glPopMatrix();
}

Моя текущая попытка выглядит примерно так:

public void DrawRecursively( GameTime deltaTime, Matrix worldMatrix )
{
    Matrix backup = worldMatrix;

    // TRANSLATE HERE.
    // ROTATE HERE.

    this.Draw( deltaTime );

    foreach ( ComponentInterface child in childs )
    {
        child.DrawRecursively( deltaTime, worldMatrix );
    }

    worldMatrix = backup;
}

Я понимаю, что к worldMatrix нельзя получить неявный доступ откуда угодно, и что вы должны иметь ссылку на него. Как мне тогда перевести и повернуть? И является ли моя worldMatrix резервная копия правильным способом, эквивалентным блоку glPushMatrix / PopMatrix?

Спасибо

Ник


EDIT:

Я думаю, что мне удалось сделать несколько шагов вперед, как говорится, все еще не работает. Боже, я скучаю по openGL и всей подробной документации, MSDN не даст мне много информации ... Вот мой последний подход:

public void DrawRecursively( GameTime deltaTime, BasicEffect effect )
{
    Matrix worldMatrix = effect.World;
    Matrix backup = worldMatrix;

    worldMatrix = worldMatrix * Matrix.CreateTranslation( position.ToVector3() );
    worldMatrix = worldMatrix * Matrix.CreateRotationY( theta );
    worldMatrix = worldMatrix * Matrix.CreateRotationX( phi );
    effect.Parameters["xWorld"].SetValue( worldMatrix );

    this.Draw( deltaTime );

    foreach ( ComponentInterface child in childs )
    {
        child.DrawRecursively( deltaTime, effect );
    }

    effect.Parameters["xWorld"].SetValue( backup );
}

effect.Parameters["xWorld"] возвращает мне нулевой указатель, поэтому SetValue, очевидно, выдает ошибку нарушения доступа. Я дважды проверил, и экземпляр эффекта правильно инициализируется, согласно отладчику.

Это правильный способ сделать это?


ИЗМЕНИТЬ СНОВА:

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

public void DrawRecursively( GameTime deltaTime, BasicEffect effect )
    {
        Matrix worldMatrix = effect.World;
        Matrix backup = worldMatrix;

        effect.World = worldMatrix  * Matrix.CreateScale( scale )
                                    * Matrix.CreateRotationX( orientation.X )
                                    * Matrix.CreateRotationX( orientation.Y )
                                    * Matrix.CreateRotationX( orientation.Z )
                                    * Matrix.CreateTranslation( position.ToVector3() );

        this.Draw( deltaTime );

        foreach ( ComponentInterface child in childs )
        {
            child.DrawRecursively( deltaTime, effect );
        }

        effect.World = backup;
    }

1 Ответ

0 голосов
/ 19 апреля 2011

BasicEffect имеет методы получения и установки для матриц World, View и Projection, но сам шейдер поддерживает единственную матрицу WorldViewProj, поэтому effect.Parameters["xWorld"] дает сбой.Придерживайтесь сеттеров, а BasicEffect должен позаботиться об остальном.

Matrix worldMatrix = effect.World;
Matrix backup = worldMatrix;

worldMatrix *= Matrix.CreateTranslation( position.ToVector3() );
worldMatrix *= Matrix.CreateRotationY( theta );
worldMatrix *=  Matrix.CreateRotationX( phi );
effect.World = worldMatrix;
...