OpenGL ES, анимирующий 2D StickMan - PullRequest
0 голосов
/ 28 июля 2011

Я хочу нарисовать крупье на основе скелетной анимации.По сути, крупье должно уметь воспроизводить движения, подобные человеческим, такие как ходьба ... Я создал код под следующей логикой: в крупье есть разные типы суставов:детский сустав тоже должен двигаться.Аналогия может состоять в том, что если вы поворачиваете свой локтевой сустав (то есть родительский сустав), сустав запястья (детский сустав) также всегда будет двигаться.У меня есть нерабочий код, который предполагает рисовать суставы левой ноги.

package org.example.pointtest;


import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;

public class SimplePoint 
{   
public  FloatBuffer hipVertexBuffer;
public  FloatBuffer kneeVertexBuffer;
public  FloatBuffer ankleVertexBuffer;

float[]hip={1.75f,-2.75f,0.0f};//0 hip
float[]knee={1.75f,-6.75f,0.0f};//1 knee
float[]ankle={1.75f,-10.75f,0.0f};//2 ankle
float[][]leftleg={hip,knee,ankle};
FloatBuffer []VertexBuffers={kneeVertexBuffer,ankleVertexBuffer};
FloatBuffer[]CompleteVertexBuffers={hipVertexBuffer,kneeVertexBuffer};
public float distance2D(float[]origin,float[]extremity)
{
    float a=extremity[0]-origin[0];
    float b=extremity[1]-origin[1];
    float c=extremity[2]-origin[2];
    float[] d={a,b,c};
    return d[1];
}
public SimplePoint()
{

    float []hippoint=
    {1.75f,-2.75f,0.0f};//0 hip
    float[]kneepoint=       
    {1.75f,-6.75f,0.0f};//1 knee        
    float[]anklepoint=
    {1.75f,-10.75f,0.0f};//2 ankle

    ByteBuffer vbb = ByteBuffer.allocateDirect(1*3*4);
    vbb.order(ByteOrder.nativeOrder());
    hipVertexBuffer=vbb.asFloatBuffer();
    hipVertexBuffer.put(hippoint);
    hipVertexBuffer.position(0);

    ByteBuffer kbb = ByteBuffer.allocateDirect(1*3*4);
    kbb.order(ByteOrder.nativeOrder());
    kneeVertexBuffer=kbb.asFloatBuffer();
    kneeVertexBuffer.put(kneepoint);
    kneeVertexBuffer.position(0);

    ByteBuffer abb = ByteBuffer.allocateDirect(1*3*4);
    abb.order(ByteOrder.nativeOrder());
    ankleVertexBuffer=abb.asFloatBuffer();
    ankleVertexBuffer.put(anklepoint);
    ankleVertexBuffer.position(0);

}

public void draw(GL10 gl)
{

    /*gl.glPushMatrix();
    gl.glTranslatef(0, 1, 0);
    gl.glDrawArrays(GL10.GL_POINTS, 2, 1);
    gl.glPopMatrix();
    */
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0,hipVertexBuffer);// root joint transformation matrix(supposition)
    gl.glColor4f(1f, 0f, 0f, 1f);
    gl.glDrawArrays(GL10.GL_POINTS, 0, 1);
    gl.glPushMatrix();

    int i=0;
    while(leftleg[i]!=leftleg[leftleg.length-1])
    {   


        if (leftleg[i]!=leftleg[leftleg.length-1])
        {
            gl.glTranslatef(0, distance2D(hip, knee), 0);
            gl.glVertexPointer(3, GL10.GL_FLOAT, 0,VertexBuffers[i]);
            gl.glDrawArrays(GL10.GL_POINTS, 0, 1);
            gl.glMultMatrixf(CompleteVertexBuffers[i]);
            gl.glPushMatrix();



        }
        if(leftleg[i]==leftleg[leftleg.length-1])
        {
            gl.glPopMatrix();

        }
        i++;
    }

}

}

1 Ответ

1 голос
/ 28 июля 2011

То, что вы описываете, называется Прямая кинематика . В сети достаточно информации об этом.

Что вам в основном нужно сделать, это указать следующую кость в структуре скелета как относящуюся к родительской кости. На практике это означает, что каждая «кость» будет начинаться с 0,0 и растягиваться до другой точки (где будет прикреплена следующая кость).

Затем вы можете умножить вверх от корня все эти «локальные» преобразования в «мировое» преобразование, чтобы получить ваши окончательные позиции.

Это, например, файл заголовка из моей системы 3D анимации костей:

#ifndef THE__MESH_SKELETON_NODE_H_
#define THE__MESH_SKELETON_NODE_H_

/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/

#include "String/String.h"
#include "Utils/Crc.h"
#include "Maths/Matrix4x4.h"

/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/

class XMLElement;

/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/

enum MeshSkeletonNodeFlags
{
    MSN_Root        = 0x00000001,
    MSN_Dirty       = 0x00000002,
    MSN_NoRender    = 0x00000004,       // Not entirely sure about this one as it buggers up my render table.
};

/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/

class MeshSkeletonNode
{
protected:
    MathsLib::Matrix4x4*    mpRestToLocalTransform;
    MathsLib::Matrix4x4*    mpLocalTransform;
    MathsLib::Matrix4x4*    mpWorldTransform;

    unsigned int                    mFlags;
    CRCVAL                          mBoneCRC;
    StringT                         mBoneName;

    MeshSkeletonNode*               mpParent;
    MeshSkeletonNode*               mpChild;
    MeshSkeletonNode*               mpNextSibling;
    MeshSkeletonNode*               mpPrevSibling;

    bool UpdateWorldTransform( MathsLib::Matrix4x4* pParentWorld );
public:
    MeshSkeletonNode();
    ~MeshSkeletonNode();

    //bool Load( XMLElement* pBone, MeshSkeletonNode* pParent, MeshSkeletonNode* pPrevSibling, 
    //         MathsLib::Matrix4x4* pRestToLocal, MathsLib::Matrix4x4* pLocal, MathsLib::Matrix4x4* pWorld );

    unsigned int    GetFlags();
    void            SetFlags( unsigned int flags );
    void            ClearFlags( unsigned int flags );

    bool UpdateWorldTransform();

    MathsLib::Matrix4x4*    GetRestToLocalTransform();
    MathsLib::Matrix4x4*    GetLocalTransform();
    MathsLib::Matrix4x4*    GetWorldTransform();

    void SetLocalTransform( MathsLib::Matrix4x4* pTransform );

    bool AttachSiblingNode( MeshSkeletonNode* pNode );
    bool DetachSiblingNode( MeshSkeletonNode* pNode );

    bool AttachChildNode( MeshSkeletonNode* pNode );
    bool DetachChildNode( MeshSkeletonNode* pNode );

    MeshSkeletonNode*& Child();
    MeshSkeletonNode*& Parent();
    MeshSkeletonNode*& NextSibling();
    MeshSkeletonNode*& PrevSibling();

    MeshSkeletonNode*   FindNodeByName( StringT& boneName );
    MeshSkeletonNode*   FindNodeByCRC( CRCVAL crc );

    CRCVAL              GetBoneCRC();
    const StringT&      GetBoneName();
};

/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/

inline unsigned int MeshSkeletonNode::GetFlags()
{
    return mFlags;
}

/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/

inline void MeshSkeletonNode::SetFlags( unsigned int flags )
{
    mFlags |= flags;
}

/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/

inline void MeshSkeletonNode::ClearFlags( unsigned int flags )
{
    mFlags &= ~flags;
}

/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/

inline MathsLib::Matrix4x4* MeshSkeletonNode::GetRestToLocalTransform()
{
    return mpRestToLocalTransform;
}

/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/

inline MathsLib::Matrix4x4* MeshSkeletonNode::GetLocalTransform()
{
    return mpLocalTransform;
}

/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/

inline MathsLib::Matrix4x4* MeshSkeletonNode::GetWorldTransform()
{
    return mpWorldTransform;
}

/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/

inline void MeshSkeletonNode::SetLocalTransform( MathsLib::Matrix4x4* pTransform )
{
    *mpLocalTransform   = *pTransform;
    SetFlags( MSN_Dirty );
}

/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/

inline MeshSkeletonNode*& MeshSkeletonNode::Child()
{
    return mpChild;
}

/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/

inline MeshSkeletonNode*& MeshSkeletonNode::Parent()
{
    return mpParent;
}

/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/

inline MeshSkeletonNode*& MeshSkeletonNode::NextSibling()
{
    return mpNextSibling;
}

/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/

inline MeshSkeletonNode*& MeshSkeletonNode::PrevSibling()
{
    return mpPrevSibling;
}

/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/

inline CRCVAL MeshSkeletonNode::GetBoneCRC()
{
    return mBoneCRC;
}

/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/

inline const StringT& MeshSkeletonNode::GetBoneName()
{
    return mBoneName;
}

/*+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+*/
#endif

Редактировать : Чтобы дать вам лучшее представление, вы должны определить корневую кость (экземпляр класса). Затем вы должны добавить n (где n - это значение от 0 до бесконечности) дочерних костей к этой корневой кости. Эти кости будут иметь преобразование, которое представляет их смещение от этой корневой позиции. Затем вы должны определить еще n костей, которые имеют локальное преобразование смещения от одной из этих дочерних костей. Как только вы определили, вы обнаружите, что преобразование мира любой кости является матричным умножением преобразования мира родителя и локального преобразования кости. Затем вы сможете распространять преобразования к корневому узлу на листья через кости между ними (это передняя часть прямой кинематики). Когда у вас все получится, вам нужно определить набор ключевых кадров анимации, которые определяют преобразования, применяемые к состоянию «покоя», которое вы определили при построении костей. Каждое преобразование остается относительно кости родителя, чтобы позволить преобразованиям распространяться должным образом. Таким образом, вы можете определить, что кость запястья отклоняется на 20 градусов вправо, и независимо от положения кости родителя запястье будет отклоняться относительно костей над ней в иерархии.

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