在背景上覆盖半透明层与Java 3D

时间:2014-03-16 17:32:08

标签: java java-3d

我使用Java3D来显示其中包含一些基元的房间。我有一个图像背景,我将其平铺,以便使用background.setImageScaleMode(Background.SCALE_REPEAT);填充整个帧。现在我想在此背景上添加另一个半透明背景,我想使用SCALE_FIT_ALL将其拉伸到屏幕上。这将创建一个我无法实现的图像效果。但是,当我尝试这样做时,Java 3D会抱怨Group.addChild: child already has a parent

在不使用背景的情况下做同样事情的其他方式(例如在2D图元上绘制)也是一种兴趣。

所以我的问题是如何通过Java3D实现我想要的目标?

MWE:图片可供here。我想用Background.SCALE_REPEAT绘制bg-stars.png,然后用Background.SCALE_FIT_ALL绘制bg-glow.png。

1 个答案:

答案 0 :(得分:1)

可能不是你真正希望实现的目标,但是评论的时间太长了:

我做了一个添加多个背景的测试,它基本上“工作”(即:它没有导致错误消息)。但是Background的文档说

  

如果多个Background节点处于活动状态,则将使用“最接近”眼睛的Background节点。

因此,我认为根本不可能同时显示多个背景。

根据您想要实现的目标,可能存在多种可能性。以下是一种可能与您想要的“接近”的方法。但我熟悉Java3D中的背景,并假设有更优雅,高效,灵活(或简单:更好的)方法(如创建一个巨大的,半带覆盖纹理的透明四边形或其他......)

然而,这里的想法是将背景创建为单个图像。编写BufferedImages非常简单,并提供了很多可能性。所以我正在拍摄bg-stars.png图像并创建此图像的“平铺”版本(大到足以填充某个区域 - 实际上,这可以简单地做到与最大屏幕尺寸一样大)。然后我用“叠加”图像bg-glow.png组合它,只需将它绘制在平铺图像上。

然后可以使用生成的图像创建背景。

乍一看,结果可能看起来像你想要达到的目的,但当然,可能会有一些警告。例如。我们必须考虑如何实现这一点以适应窗口大小的变化。 (用ComponentListener听这个并更新图像会很容易,但是......好吧。

再次:肯定有更好的解决方案。但是,在您找到更好的解决方案之前,这可能至少可以作为一种解决方法。

import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.media.j3d.Background;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.ImageComponent2D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;

import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.ColorCube;
import com.sun.j3d.utils.image.TextureLoader;
import com.sun.j3d.utils.universe.SimpleUniverse;

public class SimpleBackgroundTest extends Applet
{
    private static final int WIDTH = 1200;
    private static final int HEIGHT = 1200;

    public static void main(String[] args) throws IOException
    {
        System.setProperty("sun.awt.noerasebackground", "true");
        Frame frame = new MainFrame(new SimpleBackgroundTest(), WIDTH, HEIGHT);
    }

    public SimpleBackgroundTest()
    {
        setLayout(new BorderLayout());
        Canvas3D c = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
        add("Center", c);

        BranchGroup group = new BranchGroup();
        group.addChild(createSomeCube());

        BufferedImage stars = null;
        BufferedImage glow = null;
        try
        {
            stars = ImageIO.read(new File("bg-stars.png"));
            glow = ImageIO.read(new File("bg-glow.png"));
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }

        BufferedImage tiled = createTiled(stars, WIDTH, HEIGHT);
        BufferedImage overlay = createOverlay(tiled, glow);

        Background background = createBackground(overlay);
        group.addChild(background);

        SimpleUniverse universe = new SimpleUniverse(c);
        universe.addBranchGraph(group);
        universe.getViewingPlatform().setNominalViewingTransform();
    }

    private static BufferedImage createTiled(
        BufferedImage image, int targetSizeX, int targetSizeY)
    {
        BufferedImage result = new BufferedImage(
            targetSizeX, targetSizeY,
            BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = result.createGraphics();
        for (int x = 0; x < targetSizeX; x += image.getWidth())
        {
            for (int y = 0; y < targetSizeY; y += image.getHeight())
            {
                g.drawImage(image, x, y, null);
            }
        }
        g.dispose();
        return result;
    }

    private static BufferedImage createOverlay(
        BufferedImage image, BufferedImage overlay)
    {
        BufferedImage result = new BufferedImage(
            image.getWidth(), image.getHeight(), 
            BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = result.createGraphics();
        g.drawImage(image, 0, 0, null);
        g.drawImage(overlay, 0, 0, image.getWidth(), image.getHeight(), null);
        g.dispose();
        return result;
    }

    private static Background createBackground(BufferedImage image)
    {
        TextureLoader textureLoader = new TextureLoader(image);
        ImageComponent2D imageComponent = textureLoader.getImage();
        Background background = new Background();
        background.setImage(imageComponent);
        background.setImageScaleMode(Background.SCALE_FIT_ALL);
        background.setCapability(Background.ALLOW_IMAGE_WRITE);
        background.setApplicationBounds(new BoundingSphere());
        return background;
    }

    private TransformGroup createSomeCube()
    {
        ColorCube cube = new ColorCube(0.5f);
        Transform3D t = new Transform3D();
        t.rotY(0.2);
        t.setScale(0.1);
        TransformGroup tg = new TransformGroup();
        tg.setTransform(t);
        tg.removeAllChildren();
        tg.addChild(cube);
        return tg;
    }
}