Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

3d - libgdx draw text via project draws twice?

I try to draw 2D texts for my 3D world objects with libgdx's camera.project function but have a weird problem.

See the pics below: enter image description here

enter image description here

As you can see in the pictures, all is well in picture 1 but when I turn around 180 degrees the ball's name (codename 1) is be drawing the blank space also (picture 2). I couldn't get what the problem is and after hours of thinking decided to ask here. Please help me.

My code is:

public static void drawNames(){
    TheGame.spriteBatch.begin();
    for(int i = 0; i < TheGame.playerMap.size; i++){
        Player ply = TheGame.playerMap.getValueAt(i);
        if(!ply.isAlive)
            continue;
        TheGame.tmpVec.set(ply.getPos().x, ply.getPos().y, ply.getPos().z);
        TheGame.cam.project(TheGame.tmpVec);
        TheGame.fontArialM.draw(TheGame.spriteBatch, ply.name, TheGame.tmpVec.x, TheGame.tmpVec.y, 0, Align.center, false);
    }
    TheGame.spriteBatch.end();
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is because if you project something that is behind the camera it still gets valid screen coordinates from the project method. Consider the following that prints the screen coordinates of two world coordinates

        PerspectiveCamera camera = new PerspectiveCamera(60, 800, 600);
        camera.position.set(0, 0, -10);
        camera.lookAt(0, 0, 0);
        camera.update();

        Vector3 temp = new Vector3();
        Vector3 p1 = new Vector3(1, 0, 10); // This is in front of the camera, slightly to the right
        Vector3 p2 = new Vector3(0, 0, -100); // This is behind of the camera

        camera.project(temp.set(p1));
        System.out.println("p1 is at screen " + temp);
        if (camera.frustum.pointInFrustum(p1))
            System.out.println("p1 is visible to the camera");
        else
            System.out.println("p1 is not visible to the camera");

        camera.project(temp.set(p2));
        System.out.println("p2 is at screen " + temp);
        if (camera.frustum.pointInFrustum(p2))
            System.out.println("p2 is visible to the camera");
        else
            System.out.println("p2 is not visible to the camera");

In your code, before rendering the text you need to check if the ply.getPos() vector is visible to the camera, and only render the text if it is.

if (TheGame.cam.frustum.pointInFrustum(ply.getPos()) {
    TheGame.tmpVec.set(ply.getPos().x, ply.getPos().y, ply.getPos().z);
    TheGame.cam.project(TheGame.tmpVec);
    TheGame.fontArialM.draw(TheGame.spriteBatch, ply.name, TheGame.tmpVec.x, TheGame.tmpVec.y, 0, Align.center, false);
}

Note that there are other ways to cull things behind the camera that might be more efficient for you.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...