package org.vorthmann.zome.render.java3d;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Collection;
import javax.media.j3d.BoundingBox;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.ImageComponent;
import javax.media.j3d.ImageComponent2D;
import javax.media.j3d.LinearFog;
import javax.media.j3d.Node;
import javax.media.j3d.PhysicalBody;
import javax.media.j3d.PhysicalEnvironment;
import javax.media.j3d.Screen3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.View;
import javax.media.j3d.ViewPlatform;
import javax.vecmath.Matrix4d;
import javax.vecmath.Point3d;
import com.sun.j3d.utils.picking.PickCanvas;
import com.sun.j3d.utils.picking.PickResult;
import com.sun.j3d.utils.picking.PickTool;
import com.vzome.core.render.RenderedManifestation;
import com.vzome.core.render.RenderingChanges;
import com.vzome.desktop.controller.RenderingViewer;
public class Java3dRenderingViewer implements RenderingViewer
{
public Java3dRenderingViewer( Java3dSceneGraph scene, CapturingCanvas3D canvas )
{
super();
// GraphicsConfiguration gc = SimpleUniverse .getPreferredConfiguration();
mCanvas = canvas; // new CapturingCanvas3D( gc );
mScene = scene;
viewTransform = new TransformGroup();
view = new View();
mScene .addView( initView( view, viewTransform, mCanvas ) );
mLights = mScene .getLightsGroup();
mFog = mScene .getFog();
mPickCanvas = new PickCanvas( mCanvas, mScene .getRoot() );
mPickCanvas .setMode( PickTool.GEOMETRY );
mPickCanvas .setTolerance( 0.1f );
}
@Override
public void setEye( int eye )
{
this .eye = eye;
}
private int eye = MONOCULAR;
private Java3dSceneGraph mScene;
protected View view;
protected TransformGroup mLights, viewTransform;
protected LinearFog mFog;
private CapturingCanvas3D mCanvas;
private PickCanvas mPickCanvas;
private static BranchGroup initView( View view, TransformGroup trans, Canvas3D canvas )
{
ViewPlatform vp = new ViewPlatform();
trans .setCapability( TransformGroup .ALLOW_TRANSFORM_WRITE );
BranchGroup bg = new BranchGroup();
bg .addChild( trans );
trans .addChild( vp );
view .addCanvas3D( canvas );
view .setPhysicalBody( new PhysicalBody() );
view .setPhysicalEnvironment( new PhysicalEnvironment() );
view .attachViewPlatform( vp );
view .setFrontClipPolicy( View.VIRTUAL_EYE );
view .setBackClipPolicy( View.VIRTUAL_EYE );
view .setScreenScalePolicy( View .SCALE_EXPLICIT );
return bg;
}
/* (non-Javadoc)
* @see org.vorthmann.zome.render.java3d.RenderingViewer#getCanvas()
*/
public Component getCanvas()
{
return mCanvas;
}
/* (non-Javadoc)
* @see org.vorthmann.zome.render.java3d.RenderingViewer#getRenderingChanges()
*/
@Override
public RenderingChanges getRenderingChanges()
{
return mScene;
}
@Override
public void setViewTransformation( Matrix4d matrix, int eye )
{
if ( eye == this.eye )
{
Transform3D trans = new Transform3D( matrix );
viewTransform .setTransform( trans );
mLights .setTransform( trans );
}
}
// public void setLeftEyeViewTransformation( Transform3D trans )
// {
// mLeftEyeViewTransform .setTransform( trans );
// }
@Override
public void setPerspective( double fov, double aspectRatio, double near, double far )
{
view .setProjectionPolicy( View.PERSPECTIVE_PROJECTION );
view .setScreenScale( 1d );
view .setFieldOfView( fov );
// mLeftEyeView .setProjectionPolicy( View.PERSPECTIVE_PROJECTION );
// mLeftEyeView .setScreenScale( 1d );
// mLeftEyeView .setFieldOfView( fov );
setDistances( near, far );
}
@Override
public void setOrthographic( double halfEdge, double near, double far )
{
view .setProjectionPolicy( View.PARALLEL_PROJECTION );
view .setScreenScale( 1 / ( 6 * halfEdge ) ); // WHY 6???
// mLeftEyeView .setProjectionPolicy( View.PARALLEL_PROJECTION );
// mLeftEyeView .setScreenScale( 1 / ( 6 * halfEdge ) ); // WHY 6???
setDistances( near, far );
}
protected void setDistances( double near, double far )
{
view .setFrontClipDistance( near );
view .setBackClipDistance( far );
// mLeftEyeView .setFrontClipDistance( near );
// mLeftEyeView .setBackClipDistance( far );
double diff = (far-near)/5; // offset from near and far by 20%
mFog .setBackDistance( far );
mFog .setFrontDistance( near + 2 * diff );
}
@Override
public void pickPoint( MouseEvent e, Point3d virtualCursor, Point3d eyePt )
{
Transform3D imagePlateToVworld = new Transform3D();
mCanvas .getImagePlateToVworld( imagePlateToVworld );
mCanvas .getPixelLocationInImagePlate( e .getX(), e .getY(), virtualCursor );
imagePlateToVworld .transform( virtualCursor );
mCanvas .getCenterEyeInImagePlate( eyePt );
imagePlateToVworld .transform( eyePt );
}
@Override
public RenderedManifestation pickManifestation( MouseEvent e )
{
PickResult pickResult = null;
try {
mPickCanvas .setShapeLocation( e );
pickResult = mPickCanvas .pickClosest();
} catch( Throwable t ) {
t .printStackTrace();
}
Node node = pickResult == null? null : pickResult .getObject();
// for scenegraph.Factory approach
// Node node = pickResult == null? null : pickResult .getNode( PickResult.BRANCH_GROUP );
RenderedManifestation picked = node == null? null : (RenderedManifestation) node .getUserData();
return picked;
}
@Override
public void captureImage( int maxSize, RenderingViewer.ImageCapture capture )
{
if ( mCanvas .isOffScreen() )
{
BufferedImage bImage = new BufferedImage( maxSize, maxSize * 4 / 5, BufferedImage.TYPE_INT_ARGB );
ImageComponent2D buffer = new ImageComponent2D( ImageComponent.FORMAT_RGB, bImage );
Screen3D sOff = mCanvas .getScreen3D();
Dimension dim = new Dimension( 1024, 768 );
sOff .setSize( dim );
sOff .setPhysicalScreenWidth( 1024 );
sOff .setPhysicalScreenHeight( 768 );
mCanvas .setOffScreenLocation( 0, 0 );
mCanvas .setOffScreenBuffer( buffer );
mCanvas .renderOffScreenBuffer();
mCanvas .waitForOffScreenRendering();
capture .captureImage( mCanvas .getOffScreenBuffer() .getImage() );
}
else
{
mCanvas .maxImageSize = maxSize;
mCanvas .m_imageHandler = capture;
mCanvas .repaint();
}
//mCanvas .m_imageHandler = null; mCanvas .maxImageSize = -1; // will be done by canvas, on another thread
}
@Override
public Collection<RenderedManifestation> pickCube()
{
PickResult[] pickResult = null;
try {
mPickCanvas .setShapeBounds( new BoundingBox( new Point3d(0,0,-50), new Point3d(50,50,50) ), new Point3d(1d,1d,1d) );
pickResult = mPickCanvas .pickAll();
} catch( Throwable t ) {
t .printStackTrace();
}
Collection<RenderedManifestation> result = new ArrayList<>();
for ( int i = 0; i < pickResult.length; i++ )
{
Node node = pickResult[ i ] .getObject();
RenderedManifestation picked = (RenderedManifestation) node .getUserData();
result .add( picked );
}
// for scenegraph.Factory approach
// Node node = pickResult == null? null : pickResult .getNode( PickResult.BRANCH_GROUP );
return result;
}
}