我使用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。
答案 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;
}
}