package framework.test; import java.awt.Component; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.util.Map; import javax.media.j3d.Appearance; import javax.media.j3d.BoundingSphere; import javax.media.j3d.DirectionalLight; import javax.media.j3d.GraphicsConfigTemplate3D; import javax.media.j3d.Material; import javax.media.j3d.PolygonAttributes; import javax.media.j3d.QuadArray; import javax.media.j3d.RenderingAttributes; import javax.media.j3d.Shape3D; import javax.media.j3d.Transform3D; import javax.media.j3d.TransparencyAttributes; import javax.vecmath.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Vector3d; import javax.vecmath.Vector3f; import com.sun.j3d.utils.geometry.Cylinder; import framework.RWT.RWTFrame3D; import framework.RWT.RWTCanvas3D; import framework.model3D.Position3D; import framework.model3D.Universe; import framework.view3D.Camera3D; public class TestShadow { public TestShadow() { // TODO Auto-generated constructor stub RWTFrame3D frame = new RWTFrame3D(); // ステンシルバッファを使用する GraphicsConfiguration の生成 GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice gd = ge.getDefaultScreenDevice(); GraphicsConfigTemplate3D gct3D = new GraphicsConfigTemplate3D(); gct3D.setStencilSize(8); GraphicsConfiguration gc = gd.getBestConfiguration(gct3D); RWTCanvas3D canvas = new RWTCanvas3D(gc); frame.add(canvas); Map canvasProperty = canvas.queryProperties(); System.out.println(canvasProperty.get("stencilSize")); Universe universe = new Universe(); DirectionalLight light = new DirectionalLight(true, new Color3f(1.0f, 1.0f, 1.0f), new Vector3f(0.0f, -1.0f, -1.0f)); light.setInfluencingBounds(new BoundingSphere(new Point3d(), 1000.0)); universe.placeLight(light); // 地面全体を影の色で描画(距離情報をZバッファに書き込む) Appearance ap0 = new Appearance(); Material m0 = new Material(); m0.setDiffuseColor(0.5f, 0.5f, 0.5f); // 影の色を灰色に m0.setSpecularColor(0.0f, 0.0f, 0.0f); ap0.setMaterial(m0); RenderingAttributes ra0 = new RenderingAttributes(); // ra0.setCapability(RenderingAttributes.ALLOW_DEPTH_ENABLE_READ); // ra0.setCapability(RenderingAttributes.ALLOW_DEPTH_ENABLE_WRITE); // ra0.setCapability(RenderingAttributes.ALLOW_DEPTH_TEST_FUNCTION_READ); // ra0.setCapability(RenderingAttributes.ALLOW_DEPTH_TEST_FUNCTION_WRITE); // ra0.setCapability(RenderingAttributes.ALLOW_STENCIL_ATTRIBUTES_READ); // ra0.setCapability(RenderingAttributes.ALLOW_STENCIL_ATTRIBUTES_WRITE); ra0.setStencilEnable(false); ra0.setDepthBufferWriteEnable(true); ra0.setDepthTestFunction(RenderingAttributes.LESS_OR_EQUAL); ap0.setRenderingAttributes(ra0); PolygonAttributes pa0 = new PolygonAttributes(); pa0.setCullFace(PolygonAttributes.CULL_BACK); ap0.setPolygonAttributes(pa0); QuadArray quadArray0 = new QuadArray(4, QuadArray.COORDINATES | QuadArray.NORMALS); quadArray0.setCoordinates(0, new Point3d[]{new Point3d(-10.0, 0.0, -10.0), new Point3d(-10.0, 0.0, 10.0), new Point3d(10.0, 0.0, 10.0), new Point3d(10.0, 0.0, -10.0)}); quadArray0.setNormal(0, new Vector3f(0.0f, 1.0f, 0.0f)); quadArray0.setNormal(1, new Vector3f(0.0f, 1.0f, 0.0f)); quadArray0.setNormal(2, new Vector3f(0.0f, 1.0f, 0.0f)); quadArray0.setNormal(3, new Vector3f(0.0f, 1.0f, 0.0f)); Shape3D box0 = new Shape3D(quadArray0, ap0); universe.place(box0); // シャドウボリューム表面(ステンシルバッファを+1) Appearance ap1 = new Appearance(); // ap1.setMaterial(new Material()); RenderingAttributes ra1 = new RenderingAttributes(); // ra1.setCapability(RenderingAttributes.ALLOW_DEPTH_ENABLE_READ); // ra1.setCapability(RenderingAttributes.ALLOW_DEPTH_ENABLE_WRITE); // ra1.setCapability(RenderingAttributes.ALLOW_DEPTH_TEST_FUNCTION_READ); // ra1.setCapability(RenderingAttributes.ALLOW_DEPTH_TEST_FUNCTION_WRITE); // ra1.setCapability(RenderingAttributes.ALLOW_STENCIL_ATTRIBUTES_READ); // ra1.setCapability(RenderingAttributes.ALLOW_STENCIL_ATTRIBUTES_WRITE); ra1.setStencilEnable(true); ra1.setDepthBufferWriteEnable(false); ra1.setDepthTestFunction(RenderingAttributes.LESS_OR_EQUAL); ra1.setStencilFunction(RenderingAttributes.ALWAYS, 0, ~0); ra1.setStencilOp(RenderingAttributes.STENCIL_KEEP, RenderingAttributes.STENCIL_KEEP, RenderingAttributes.STENCIL_INCR); ap1.setRenderingAttributes(ra1); PolygonAttributes pa1 = new PolygonAttributes(); pa1.setCullFace(PolygonAttributes.CULL_BACK); ap1.setPolygonAttributes(pa1); TransparencyAttributes ta1 = new TransparencyAttributes(); // setVisible(false)だとステンシルバッファが更新されないので、透明に ta1.setTransparencyMode(TransparencyAttributes.BLENDED); ta1.setTransparency(1.0f); ap1.setTransparencyAttributes(ta1); Cylinder cyl1 = new Cylinder(1.0f, 10.0f, ap1); universe.place(cyl1); // シャドウボリューム裏面(ステンシルバッファを-1) Appearance ap2 = new Appearance(); // ap2.setMaterial(new Material()); RenderingAttributes ra2 = new RenderingAttributes(); // ra2.setCapability(RenderingAttributes.ALLOW_DEPTH_ENABLE_READ); // ra2.setCapability(RenderingAttributes.ALLOW_DEPTH_ENABLE_WRITE); // ra2.setCapability(RenderingAttributes.ALLOW_DEPTH_TEST_FUNCTION_READ); // ra2.setCapability(RenderingAttributes.ALLOW_DEPTH_TEST_FUNCTION_WRITE); // ra2.setCapability(RenderingAttributes.ALLOW_STENCIL_ATTRIBUTES_READ); // ra2.setCapability(RenderingAttributes.ALLOW_STENCIL_ATTRIBUTES_WRITE); ra2.setStencilEnable(true); ra2.setDepthBufferWriteEnable(false); ra2.setDepthTestFunction(RenderingAttributes.LESS_OR_EQUAL); ra2.setStencilFunction(RenderingAttributes.ALWAYS, 0, ~0); ra2.setStencilOp(RenderingAttributes.STENCIL_KEEP, RenderingAttributes.STENCIL_KEEP, RenderingAttributes.STENCIL_DECR); ap2.setRenderingAttributes(ra2); PolygonAttributes pa2 = new PolygonAttributes(); pa2.setCullFace(PolygonAttributes.CULL_FRONT); ap2.setPolygonAttributes(pa2); TransparencyAttributes ta2 = new TransparencyAttributes(); // setVisible(false)だとステンシルバッファが更新されないので、透明に ta2.setTransparencyMode(TransparencyAttributes.BLENDED); ta2.setTransparency(1.0f); ap2.setTransparencyAttributes(ta2); Cylinder cyl2 = new Cylinder(1.0f, 10.0f, ap2); universe.place(cyl2); // 影の部分を除いた地面 Appearance ap3 = new Appearance(); Material m3 = new Material(); ap3.setMaterial(m3); RenderingAttributes ra3 = new RenderingAttributes(); // ra3.setCapability(RenderingAttributes.ALLOW_DEPTH_ENABLE_READ); // ra3.setCapability(RenderingAttributes.ALLOW_DEPTH_ENABLE_WRITE); // ra3.setCapability(RenderingAttributes.ALLOW_DEPTH_TEST_FUNCTION_READ); // ra3.setCapability(RenderingAttributes.ALLOW_DEPTH_TEST_FUNCTION_WRITE); // ra3.setCapability(RenderingAttributes.ALLOW_STENCIL_ATTRIBUTES_READ); // ra3.setCapability(RenderingAttributes.ALLOW_STENCIL_ATTRIBUTES_WRITE); ra3.setStencilEnable(true); ra3.setDepthBufferWriteEnable(true); ra3.setDepthTestFunction(RenderingAttributes.LESS_OR_EQUAL); ra3.setStencilFunction(RenderingAttributes.GREATER_OR_EQUAL, 0, ~0); // ステンシルバッファの値が1以上のとき描画しない ra3.setStencilOp(RenderingAttributes.STENCIL_KEEP, RenderingAttributes.STENCIL_KEEP, RenderingAttributes.STENCIL_KEEP); ap3.setRenderingAttributes(ra3); PolygonAttributes pa3 = new PolygonAttributes(); pa3.setCullFace(PolygonAttributes.CULL_BACK); ap3.setPolygonAttributes(pa3); QuadArray quadArray1 = new QuadArray(4, QuadArray.COORDINATES); quadArray1.setCoordinates(0, new Point3d[]{new Point3d(-10.0, 0.0, -10.0), new Point3d(-10.0, 0.0, 10.0), new Point3d(10.0, 0.0, 10.0), new Point3d(10.0, 0.0, -10.0)}); Shape3D box1 = new Shape3D(quadArray1, ap3); universe.place(box1); frame.setSize(720, 480); frame.setVisible(true); // カメラの設定 Camera3D camera = new Camera3D(universe); camera.setViewPoint(new Position3D(20.0, 20.0, 20.0)); camera.addTarget(new Position3D(0.0, 0.0, 0.0)); canvas.attachCamera(camera); // 表示 universe.compile(); for (;;) { try { Thread.sleep(17); camera.adjust(17); // Force3D f = PhysicsFacade.getGravity(solid); // solid.move(17, f, applicationPoint); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static void main(String[] args) { new TestShadow(); } }