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

使用Java 3D在背景上覆盖半透明层,java,java-3d,Java,Java 3d,我正在使用Java3D来可视化一个包含一些基本元素的房间。我有一个图像背景,我用background.setImageScaleMode(background.SCALE\u REPEAT)平铺它,使它填充整个帧。现在,我想在这个背景上添加另一个半透明背景,我想用SCALE\u FIT\u ALL将它拉伸到屏幕上。这将创建一个我无法实现的图像效果。然而,当我尝试这样做时,Java 3D抱怨说Group.addChild:child已经有了父级 不使用背景做同样事情的其他方法(例如,在2D原语上绘

我正在使用Java3D来可视化一个包含一些基本元素的房间。我有一个图像背景,我用
background.setImageScaleMode(background.SCALE\u REPEAT)平铺它,使它填充整个帧。现在,我想在这个背景上添加另一个半透明背景,我想用
SCALE\u FIT\u ALL
将它拉伸到屏幕上。这将创建一个我无法实现的图像效果。然而,当我尝试这样做时,Java 3D抱怨说
Group.addChild:child已经有了父级

不使用背景做同样事情的其他方法(例如,在2D原语上绘制)也很有趣

所以我的问题是,如何使用Java3D实现我想要的


MWE:图像可用。我想画背景为
的bg-stars.png。缩放重复,然后在背景为
的bg-glow.png上缩放。缩放适合所有的
,可能不是你真正想要的,但是太长了,无法发表评论:

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

如果多个背景节点处于活动状态,则将使用距离眼睛“最近”的背景节点

因此,我假设根本不可能同时显示多个背景

根据您想要实现的目标,可能有几种可能性。以下是一种可能“接近”您想要的方法。但我对Java3D的背景并不熟悉,我认为有更优雅、高效、灵活(或者简单地说:更好)的方法(比如用叠加纹理创建一个巨大的半透明四边形等等)

然而,这里的想法是将背景创建为单个图像。编写BuffereImage相当简单,并提供了很多可能性。因此,我拍摄了
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;
    }
}
import java.applet.applet;
导入java.awt.BorderLayout;
导入java.awt.Frame;
导入java.awt.Graphics2D;
导入java.awt.image.buffereImage;
导入java.io.File;
导入java.io.IOException;
导入javax.imageio.imageio;
导入javax.media.j3d.Background;
导入javax.media.j3d.BoundingSphere;
导入javax.media.j3d.BranchGroup;
导入javax.media.j3d.Canvas3D;
导入javax.media.j3d.ImageComponent2D;
导入javax.media.j3d.Transform3D;
导入javax.media.j3d.TransformGroup;
导入com.sun.j3d.utils.applet.MainFrame;
导入com.sun.j3d.utils.geometry.ColorCube;
导入com.sun.j3d.utils.image.TextureLoader;
导入com.sun.j3d.utils.universe.SimpleUniverse;
公共类SimpleBackgroundTest扩展小程序
{
专用静态最终整数宽度=1200;
专用静态最终内部高度=1200;
公共静态void main(字符串[]args)引发IOException
{
System.setProperty(“sun.awt.noerasebackground”、“true”);
框架=新主机(新SimpleBackgroundTest(),宽度,高度);
}
公共SimpleBackgroundTest()
{
setLayout(新的BorderLayout());
Canvas3D c=新的Canvas3D(SimpleUniverse.getPreferredConfiguration());
添加(“中心”,c);
BranchGroup=新建BranchGroup();
addChild(createSomeCube());
BuffereImage stars=null;
BuffereImage发光=空;
尝试
{
stars=ImageIO.read(新文件(“bg stars.png”);
glow=ImageIO.read(新文件(“bg glow.png”);
}
捕获(IOE异常)
{
e、 printStackTrace();
}
BuffereImage平铺=创建平铺(星形、宽度、高度);
BuffereImage overlay=createOverlay(平铺、发光);
背景背景=创建背景(覆盖);
addChild组(背景);
简单宇宙=新的简单宇宙(c);
宇宙添加分支图(组);
universe.getViewingPlatform().setNominalViewingTransform();
}
私有静态缓冲区图像创建平铺(
BuffereImage图像,int-targetSizeX,int-targetSizeY)
{
BuffereImage结果=新的BuffereImage(
targetSizeX,targetSizeY,
BuffereImage.TYPE_INT_ARGB);
Graphics2D g=result.createGraphics();
对于(int x=0;x