如何在Vuforia AR库上呈现LibGDX modelInstance?

时间:2016-04-06 14:18:20

标签: java libgdx augmented-reality vuforia

我知道社区上的大多数问题都应该至少使用一些代码来完成。但我完全迷失在这里,我甚至不知道从哪里开始。我想要做的是使用Vuforia AR库来渲染LibGDX 3D模型实例。但是,我不知道如何让Vuforia渲染modelInstances或使用libGDX相机作为相机。

我做过外部研究,但我找不到有用的信息。有没有人可以帮助我开始这个?

3 个答案:

答案 0 :(得分:1)

请注意,我并不专注于Vuforia AR,但问题暂时没有得到答复,所以我会试一试。

LibGDX中的相机基本上只是两个4x4矩阵的包装器,视图矩阵Camera#view和投影矩阵Camer#projection(还有另一个矩阵,模型矩阵,用于世界空间变换但是我相信[但不是100%肯定]在LibGDX中,这个矩阵已经被合并到视图矩阵中[所以Camera#view实际上是模型视图矩阵]。

无论如何,除此之外,除非有一个我不知道的更简单的解决方案,否则你应该能够使用这些基础矩阵来处理Vuforia和LibGDX apis之间的预测。

(建议进一步阅读:3D图形中的模型,视图,投影矩阵)

接下来是使用Vuforia渲染LibGDX 3D ModelInstances。这个问题的一般解决方案是将ModelInstance转换为Vuforia可以识别的东西。这可以通过获取LibGDX模型表示的网格/顶点数据并将其直接输入Vuforia来完成。

IMO,最好的解决方法是使用模型数据的核心表示,可以很容易地将其提供给Vuforia和LibGDX(例如,某种文件格式既可以识别也可以作为原始格式FloatBuffers应该很容易包装并提供给任何API)。作为参考,LibGDX将模型作为顶点信息存储在FloatBuffers集合中,可通过Model#meshesModelInstance#model#meshes访问。

答案 1 :(得分:1)

确定。所以我完成了两个库的组合。我不确定我所做的是最有效的工作方式,但它对我有用。

首先,我基于Vuforia的示例应用程序。特别是使用FrameMarkers示例。

我打开了一个空的LibGDX项目,导入了Vuforia jar并复制了SampleApplicationControl,SampleApplicationException,SampleApplicationGLView,SampleApplicationSession,FrameMarkerRenderer和FrameMarker。

接下来,我在LibLDX的AndroidLauncher类上创建了一些属性并初始化了所有Vuforia Stuff:

public class AndroidLauncher extends AndroidApplication implements SampleApplicationControl{
    private static final String LOGTAG = "FrameMarkers";


    // Our OpenGL view:
    public SampleApplicationGLView mGlView;
    public SampleApplicationSession vuforiaAppSession;
    // Our renderer:
    public FrameMarkerRenderer mRenderer;
    MyGDX gdxRender;
    // The textures we will use for rendering:
    public Vector<Texture> mTextures;
    public RelativeLayout mUILayout;

    public Marker dataSet[];

    public GestureDetector mGestureDetector;


    public LoadingDialogHandler loadingDialogHandler = new LoadingDialogHandler(
        this);

    // Alert Dialog used to display SDK errors
    private AlertDialog mErrorDialog;

    boolean mIsDroidDevice = false;
    @Override
    protected void onCreate (Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        vuforiaAppSession = new SampleApplicationSession(this);
        vuforiaAppSession.setmActivity(this);
        AndroidApplicationConfiguration config = new      AndroidApplicationConfiguration();


        // Load any sample specific textures:
        mTextures = new Vector<Texture>();
        loadTextures();
        startLoadingAnimation();
        vuforiaAppSession.initAR(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        gdxRender = new MyGDX (vuforiaAppSession);
        gdxRender.setTextures(mTextures);
        initialize(gdxRender, config);

        mGestureDetector = new GestureDetector(this, new GestureListener());

        mIsDroidDevice = android.os.Build.MODEL.toLowerCase().startsWith(
            "droid");    
}

我需要设置活动,所以我在SampleApplicationSession上创建了setmActivity()

之后,我实现了Libgdx ApplicationAdapter类,并将vuforiaAppSession作为属性传递,以访问我初始化的所有内容。

public class MyGDX extends ApplicationAdapter  {
    ModelInstance modelInstanceHouse;
    private AnimationController controller;
    Matrix4 lastTransformCube;
    // Constants:
    static private float kLetterScale = 25.0f;
    static private float kLetterTranslate = 25.0f;
    // OpenGL ES 2.0 specific:
    private static final String LOGTAG = "FrameMarkerRenderer";
    private int shaderProgramID = 0;
    private Vector<com.mygdx.robot.Texture> mTextures;
    //SampleApplicationSession vuforiaAppSession;
    PerspectiveCamera cam;
    ModelBuilder modelBuilder;
    Model model;
    ModelInstance instance;
    ModelBatch modelBatch;
    static boolean render;
    public SampleApplicationSession vuforiaAppSession;

    public MyGDX ( SampleApplicationSession vuforiaAppSession){
        super();
        this.vuforiaAppSession = vuforiaAppSession;

    }

要记住的最后一件重要事情是render()方法。我基于FrameMarkerRenderer的render方法。它有一个布尔值,在相机启动时被激活。所以我简单地在vuforia AR初始化和render()方法上更改了变量。我不得不把相机放在身份矩阵上,并将模型乘以modelViewMatrix。

@Override
public void render() {
    if (render) {
        // Clear color and depth buffer
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
        // Get the state from Vuforia and mark the beginning of a rendering
        // section
        State state = Renderer.getInstance().begin();
        // Explicitly render the Video Background
        Renderer.getInstance().drawVideoBackground();

        GLES20.glEnable(GLES20.GL_DEPTH_TEST);

        // We must detect if background reflection is active and adjust the
        // culling direction.
        // If the reflection is active, this means the post matrix has been
        // reflected as well,
        // therefore standard counter clockwise face culling will result in
        // "inside out" models.
        GLES20.glEnable(GLES20.GL_CULL_FACE);
        GLES20.glCullFace(GLES20.GL_BACK);
        cam.update();
        modelBatch.begin(cam);

        if (Renderer.getInstance().getVideoBackgroundConfig().getReflection() == VIDEO_BACKGROUND_REFLECTION.VIDEO_BACKGROUND_REFLECTION_ON)

                        GLES20.glFrontFace(GLES20.GL_CW);  // Front camera
        else
            GLES20.glFrontFace(GLES20.GL_CCW);   // Back camera

        // Set the viewport
        int[] viewport = vuforiaAppSession.getViewport();
        GLES20.glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);

        // Did we find any trackables this frame?
        for (int tIdx = 0; tIdx < state.getNumTrackableResults(); tIdx++)
        {
            // Get the trackable:
            TrackableResult trackableResult = state.getTrackableResult(tIdx);
            float[] modelViewMatrix = Tool.convertPose2GLMatrix(
                    trackableResult.getPose()).getData();

            // Choose the texture based on the target name:
            int textureIndex = 0;

            // Check the type of the trackable:
            assert (trackableResult.getType() == MarkerTracker.getClassType());
            MarkerResult markerResult = (MarkerResult) (trackableResult);
            Marker marker = (Marker) markerResult.getTrackable();
            textureIndex = marker.getMarkerId();
            float[] modelViewProjection = new float[16];
            Matrix.translateM(modelViewMatrix, 0, -kLetterTranslate, -kLetterTranslate, 0.f);
            Matrix.scaleM(modelViewMatrix, 0, kLetterScale, kLetterScale, kLetterScale);
            Matrix.multiplyMM(modelViewProjection, 0, vuforiaAppSession.getProjectionMatrix().getData(), 0, modelViewMatrix, 0);
            SampleUtils.checkGLError("FrameMarkers render frame");
            cam.view.idt();
            cam.projection.idt();
            cam.combined.idt();
            Matrix4 temp3 = new Matrix4(modelViewProjection);
            modelInstanceHouse.transform.set(temp3);
            modelInstanceHouse.transform.scale(0.05f, 0.05f, 0.05f);
            controller.update(Gdx.graphics.getDeltaTime());
            modelBatch.render(modelInstanceHouse);
        }
        GLES20.glDisable(GLES20.GL_DEPTH_TEST);
        modelBatch.end();

}

这是很多代码,但我希望它能帮助尝试开始集成两个库的人们。我不认为这是有效的,但它是我带来的唯一解决方案。

答案 2 :(得分:0)

Pablo的答案非常好,但是,如果你对一种不同的方法感兴趣(从LibGDX调用Vuforia,而不是另一种方式)和一个更完整的例子,这里是一个github repo一个简单的3D模型渲染器。