Hello, as I posted before, I'm trying to implement a portal engine. The solution I found to do it is to have a offscreen canvas (with the same size than the real canvas), draw the portal image in the portal canvas and the project it to the real canvas using the clip utilities from graphics2D.
Here I have a code where I try to do that but I'm sure there is something wrong.
The application has three canvas, two visibles and one offscreen. One of the visibles is rendered using the j3d renderer, the other one is rendered using the renderField canvas method. I want to have the same result in both canvas.
In the second one I draw two rectangles, the yellow one represents the portal (and the shape) position in the offscreen canvas, the green one represents where the portal (and the shape) position should be in the canvas manually rendered, they should be the same but they don't.
Could any body help me??
Thanks,
Marc
---------------------------------------------------------------------------------------------------------
package Walk;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JScrollBar;
import javax.swing.JPanel;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.image.TextureLoader;
import java.awt.image.BufferedImage;
public class Test extends JFrame{
private SimpleUniverse u = null;
private SimpleUniverse u2 = null;
public Test(){
super("new Window");
}
public static void main(String[] args) {
Test w = new Test();
w.init();
w.setSize(800,400);
w.setLocation(30,30);
//w.setResizable(false);
w.show();
}
public void destroy() {
u.removeAllLocales();
u2.removeAllLocales();
}
public void init() {
getContentPane().setLayout(new
GridLayout(0,2));
GraphicsConfiguration
config = SimpleUniverse.getPreferredConfiguration();
BranchGroup scene = createSceneGraph();
Shape3D picture = createObject();
Canvas3D c = new Canvas3D(config);
TestOwnCanvas oc = new TestOwnCanvas(config, picture);
TestPortalCanvas pc
= new TestPortalCanvas(config, picture, oc);
getContentPane().add(c);
getContentPane().add(oc);
oc.setOffScreenCanvas(pc);
u = new SimpleUniverse(c);
u2 = new SimpleUniverse(oc);
u2.getViewer().getView().addCanvas3D(pc);
Transform3D t3d = new
Transform3D();
t3d.set(new Vector3d(0.0,
1.0, 5.0));
//t3d.rotY(4.5);
u.getViewingPlatform().getViewPlatformTransform().setTransform(t3d);
u2.getViewingPlatform().getViewPlatformTransform().setTransform(t3d);
u.addBranchGraph(scene);
}
public Shape3D createObject() {
//Loading the texture
TextureLoader loader=new
TextureLoader("fondo.jpg",null);
ImageComponent2D ic=loader.getImage();
Texture2D t = new Texture2D(Texture.BASE_LEVEL,
Texture.RGB, 1, 1);
t.setBoundaryModeT(Texture.WRAP);
t.setBoundaryModeS(Texture.WRAP);
t.setImage(0,ic);
//Creating two appearances
with the same texture
Appearance a = new Appearance();
Appearance a2 = new
Appearance();
a.setTexture(t);
a2.setTexture(t);
QuadArray qa=new QuadArray(4,GeometryArray.COORDINATES
| GeometryArray.TEXTURE_COORDINATE_2);
Point3d ps[] = new Point3d[4];
ps[0]=new
Point3d(-2.5,0,-10);
ps[1]=new
Point3d(2.5,0,-10);
ps[2]=new
Point3d(2.5,5,-10);
ps[3]=new
Point3d(-2.5,5,-10);
TexCoord2f
q = new TexCoord2f( 0.0f, 0.0f);
qa.setTextureCoordinate(0,
0, q);
q.x=1; //dimX, 0
qa.setTextureCoordinate(0,
1, q);
q.y=1; //dimX, dimY
qa.setTextureCoordinate(0,
2, q);
q.x=0; //0, dimY
qa.setTextureCoordinate(0,
3, q);
qa.setCoordinates(0,
ps);
Shape3D os = new
Shape3D(qa,a);
os.setCapability(os.ALLOW_APPEARANCE_READ);
os.setCapability(os.ALLOW_GEOMETRY_READ);
return os;
}
public BranchGroup createSceneGraph() {
BranchGroup objRoot
= new BranchGroup();
objRoot.addChild(createObject());
objRoot.compile();
return objRoot;
}
}
class TestPortalCanvas extends Canvas3D {
Shape3D picture;
Canvas3D rc;
BufferedImage bImage;
ImageComponent2D buffer;
public TestPortalCanvas(GraphicsConfiguration
gc, Shape3D p, Canvas3D aux_c) {
super(gc, true);
picture=p;
rc=aux_c;
getScreen3D().setPhysicalScreenHeight(aux_c.getScreen3D().getPhysicalScreenHeight());
getScreen3D().setPhysicalScreenWidth(aux_c.getScreen3D().getPhysicalScreenWidth());
getScreen3D().setSize(aux_c.getScreen3D().getSize());
bImage = new BufferedImage(400, 300
, BufferedImage.TYPE_INT_ARGB);
buffer = new ImageComponent2D(ImageComponent.FORMAT_RGBA,
bImage);
buffer.setCapability(ImageComponent2D.ALLOW_IMAGE_READ);
setOffScreenBuffer(buffer);
}
public void renderField(int aux) {
GraphicsContext3D gc = getGraphicsContext3D();
gc.draw(picture);
gc.flush(true);
}
public void preRender() {}
public void postRender() {}
public void postSwap() {}
public BufferedImage getImage() {
BufferedImage bImage = this.getOffScreenBuffer().getImage();
return bImage;
}
}
class TestOwnCanvas extends Canvas3D {
TestPortalCanvas pc;
Shape3D picture;
public void setOffScreenCanvas(TestPortalCanvas
aux_c) {
pc = aux_c;
}
public void setBounds(int x, int y, int w, int
h) {
super.setBounds(x,y,w,h);
pc.setSize(w,h);
}
public TestOwnCanvas(GraphicsConfiguration gc,
Shape3D p) {
super(gc);
picture = p;
}
public void preRender() {
pc.renderOffScreenBuffer();
pc.waitForOffScreenRendering();
}
public void postRender() {}
public void postSwap() {}
public void renderField(int aux) {
J3DGraphics2D j3dg2D = getGraphics2D();
j3dg2D.drawImage(pc.getImage(),
0,0, (int)getSize().getWidth(), (int)getSize().getHeight(), null);
//Obtaining transformations
Transform3D auxtt = new Transform3D();
getVworldToImagePlate(auxtt);
Transform3D auxttc = new Transform3D();
pc.getVworldToImagePlate(auxttc);
TestPortal port = new TestPortal();
//drawing portal
Point2d cp = port.getCenter(auxtt,
this);
j3dg2D.setColor(Color.green);
j3dg2D.draw(new Rectangle((int)cp.x,(int)cp.y,3,3));
j3dg2D.draw(port.getPortalProjection(auxtt,
this));
//drawing portal from portal
cp = port.getCenter(auxttc, pc);
j3dg2D.setColor(Color.yellow);
j3dg2D.draw(new Rectangle((int)cp.x,(int)cp.y,6,6));
j3dg2D.draw(port.getPortalProjection(auxttc,
pc));
j3dg2D.flush(true);
}
}
// Portal class
class TestPortal {
Point3d ps[] = new Point3d[4];
Point3d psproj[] = new Point3d[4];
Point2d psp[] = new Point2d[4];
Point3d center;
public TestPortal () {
ps[0]=new Point3d(-2.5,0,-10);
ps[1]=new Point3d(2.5,0,-10);
ps[2]=new Point3d(2.5,5,-10);
ps[3]=new Point3d(-2.5,5,-10);
psproj[0]=new Point3d();
psproj[1]=new Point3d();
psproj[2]=new Point3d();
psproj[3]=new Point3d();
psp[0]=new Point2d();
psp[1]=new Point2d();
psp[2]=new Point2d();
psp[3]=new Point2d();
center = new Point3d(0,2.5,-10);
}
public Point2d getCenter(Transform3D t, Canvas3D
c) {
Point3d auxCenter = new Point3d();
t.transform(center, auxCenter);
Point2d ret = new Point2d();
c.getPixelLocationFromImagePlate(auxCenter,
ret);
return ret;
}
public Shape getPortalProjection(Transform3D
t, Canvas3D c) {
t.transform(ps[0], psproj[0]);
t.transform(ps[1], psproj[1]);
t.transform(ps[2], psproj[2]);
t.transform(ps[3], psproj[3]);
c.getPixelLocationFromImagePlate(psproj[0],
psp[0]);
c.getPixelLocationFromImagePlate(psproj[1],
psp[1]);
c.getPixelLocationFromImagePlate(psproj[2],
psp[2]);
c.getPixelLocationFromImagePlate(psproj[3],
psp[3]);
Polygon p = new Polygon();
p.addPoint((int)psp[0].x, (int)psp[0].y);
p.addPoint((int)psp[1].x, (int)psp[1].y);
p.addPoint((int)psp[2].x, (int)psp[2].y);
p.addPoint((int)psp[3].x, (int)psp[3].y);
return p;
}
}
