0 Replies Latest reply on Aug 23, 2011 3:00 PM by 884081

    facing problem while creating a Road/Pathway using Java3D

      Hello guys,

      I am newbie in Java3D and I am facing some problems while designing a 3d shape. Actually I have to design a 3d shape of a 'Carpet' placed on the ground in such a way, it looks like a Road or Pathway from "First-Person-View". That is, like a Trapezoid. The Carpet itself is made up of several segments or pieces, each of different color, width and height. Finally, exporting the final Carpet-shape as Buffered Image. Though I am able to do the later part very easily, that is, creating an image using BufferdImage from JFrame, On & Off Screen Canvas but the designing part is where I am facing some difficulties.

      I am creating a Group (carpetShapeGroup) of Polygons (with QuadArray: 4) for each segment/piece and place them one over another. so it looks like Rectangular Boxes placed one over another. Then with the Transformation3D (rot), I rotate this carpetShapeGroup with rot.rotX(-Math.PI/4) to make it like a Trapezoid shape. However, I am able to draw the image but there are several problems which I am not able to solve anymore and I need some help. I had uploaded the code on Pastie and attached it here as well with inline comments to illustrate the details. Following are the problems I am facing;

      I can create a Carpet with 3 segments/pieces successfully but as soon as I add fourth segment, the image gets distorted and the segments overlaps each other. I don't know why is it happening and how to resolve this issue. (Uncomment line:227)

      In order to display the Carpet from the bottom of the Screen i am setting a constant factor (*Transformation_Vector_Y*) but I am not able to derive it as Constant for different screen resolutions. I mean I had to make slight changes in Transformation_Vector_Y each time the Screen width and height is modified. (line:132)

      Please let me know if something is unclear here, I will try to explain my problem again. Looking forward to see your replies.

      thanks and regards
      package me.mmw.test.java3d;
      import java.awt.BorderLayout;
      import java.awt.Color;
      import java.awt.GraphicsConfiguration;
      import java.awt.GraphicsEnvironment;
      import java.awt.image.BufferedImage;
      import java.io.File;
      import java.io.IOException;
      import javax.imageio.ImageIO;
      import javax.media.j3d.AmbientLight;
      import javax.media.j3d.Appearance;
      import javax.media.j3d.BoundingSphere;
      import javax.media.j3d.BranchGroup;
      import javax.media.j3d.Canvas3D;
      import javax.media.j3d.ColoringAttributes;
      import javax.media.j3d.DirectionalLight;
      import javax.media.j3d.Group;
      import javax.media.j3d.ImageComponent;
      import javax.media.j3d.ImageComponent2D;
      import javax.media.j3d.QuadArray;
      import javax.media.j3d.Screen3D;
      import javax.media.j3d.Shape3D;
      import javax.media.j3d.Transform3D;
      import javax.media.j3d.TransformGroup;
      import javax.swing.JFrame;
      import javax.vecmath.Color3f;
      import javax.vecmath.Point3d;
      import javax.vecmath.Vector3f;
      import com.sun.j3d.utils.universe.SimpleUniverse;
      import com.sun.j3d.utils.universe.ViewingPlatform;
      public class CarpetImageRenderer {
      private double screenWidth;
      private double screenHeight;
      private SimpleUniverse universe;
      public double getScreenWidth() {
      return screenWidth;
      public void setScreenWidth(double screenWidth) {
      this.screenWidth = screenWidth;
      public double getScreenHeight() {
      return screenHeight;
      public void setScreenHeight(int screenHeight) {
      this.screenHeight = screenHeight;
      public BufferedImage render(int width, int height, PolygonDetails[] polygonDetails) {
      BranchGroup scene = createSceneGraph(polygonDetails);
      Canvas3D onScreenCanvas = new Canvas3D(
      universe = new SimpleUniverse(onScreenCanvas);
      ViewingPlatform viewingPlatform = universe.getViewingPlatform();
      OffScreenCanvas3D offScreenCanvas = createOffScreenCanvas();
      JFrame frame = new JFrame();
      frame.setLayout(new BorderLayout());
      frame.setTitle("3D Carpet Renderer");
      BufferedImage output = offScreenCanvas.doRender((int)getScreenWidth(), (int)getScreenHeight());
      frame.setSize(output.getWidth(), output.getHeight());
      return output;
      private OffScreenCanvas3D createOffScreenCanvas() {
      * Setup graphics
      GraphicsConfiguration configuration = SimpleUniverse
      * Create the capturing canvas
      OffScreenCanvas3D canvas = new OffScreenCanvas3D(configuration);
      * Set the size, width and height so that off-screen renderer knows at
      * what dimensions it needs to render.
      Screen3D screen3D = canvas.getScreen3D();
      screen3D.setSize((int)screenWidth, (int)screenHeight);
      * Physical dimension of the Screen3D is supposed to be size of the physical screen in meters.
      * The values are from the top of the Screen3D physical screen in meters.
      * The values are from the top of the Screen3D.
      * Setting the wrong physical dimension may also change the aspect ratio of the rendered image
      * and you are end up with a Blackboard
      screen3D.setPhysicalScreenWidth(0.0254 / 90.0 * screenWidth);
      screen3D.setPhysicalScreenHeight(0.0254 / 90.0 * screenHeight);
      return canvas;
      public BranchGroup createSceneGraph(PolygonDetails[] polygonDetails) {
      BranchGroup objRoot = new BranchGroup();
      Group carpetShapeGroup = new Group();
      * Setting Transformation/Postion Vector to display the Carpet from the Bottom of the screen
      * Problem-2: Not able to derive a constant factor for positioning the Carpet with
      * different Width and Height of Screen
      final float TRANSFORMATION_VECTOR_Y = -0.0014f;
      Vector3f vector = new Vector3f(0.0f, (float)(TRANSFORMATION_VECTOR_Y * getScreenHeight()), 0.0f);
      double previousElementHeight = 0.0d;
      double baseCoordinateY = 0.0d;
      double elementHeight = 0.0d;
      double elementWidth = 1.0d;
      for (PolygonDetails element : polygonDetails) {
      elementHeight = (double) getScreenHeight()/100 * element.getPercentage() /100 /2;
      previousElementHeight += elementHeight;
      //System.out.println("baseCoordinateY:"+baseCoordinateY+" previousElementHeight"+previousElementHeight);
      QuadArray polygon = new QuadArray(4, QuadArray.COORDINATES);
      polygon.setCoordinate(0, new Point3d(-elementWidth, baseCoordinateY, 0d));
      polygon.setCoordinate(1, new Point3d(elementWidth, baseCoordinateY, 0d));
      polygon.setCoordinate(2, new Point3d(elementWidth, previousElementHeight, 0d));
      polygon.setCoordinate(3, new Point3d(-elementWidth, previousElementHeight, 0d));
      Shape3D polygonShape = new Shape3D(polygon, createAppearance(element.getColor()));
      * Adding each polygon-shape in a group and finally add this group in the BranchGroup
      * Problem-3: Is there any way I can create set of polygons as One Shape?
      baseCoordinateY = elementHeight;
      TransformGroup tg = new TransformGroup();
      Transform3D transform = new Transform3D();
      Transform3D rot = new Transform3D();
      * transforming the final shape as Trapezoid
      rot.rotX(-Math.PI / 7);
      return objRoot;
      private Appearance createAppearance(Color color){
      Appearance polygon2Appearance = new Appearance();
      Color3f c = new Color3f ();
      ColoringAttributes yellowCA = new ColoringAttributes (c, 1);
      return polygon2Appearance;
      private void createLights(BranchGroup branchGroup) {
      BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0),
      Color3f ambientLightColour = new Color3f(0.9f, 0.9f, 0.9f);
      AmbientLight ambientLight = new AmbientLight(ambientLightColour);
      Color3f directionLightColour = new Color3f(1.0f, 1.0f, 1.0f);
      Vector3f directionLightDir = new Vector3f(4.0f, -7.0f, -12.0f);// (-1.0f,
      // -100.0f,
      // -1.0f);
      DirectionalLight directionLight = new DirectionalLight(
      directionLightColour, directionLightDir);
      public static void main(String... args) {
      * Segments/Pieces of Carpet
      * 1st arg: size of segment as %tage value
      * 2nd arg: Color of segment
      * Problem-1: when I add Fourth segment, the Image gets weird
      PolygonDetails[] polygonDetails = new PolygonDetails[] {
      new PolygonDetails(10, Color.YELLOW),
      new PolygonDetails(60, Color.GREEN),
      new PolygonDetails(5, Color.RED),
      new PolygonDetails(5, Color.YELLOW),
      //new PolygonDetails(10, Color.GREEN),
      * Create a Scene, render the Carpet and finally return a buffered image.
      * Takes screen width, height and set of carpet-segments as args
      BufferedImage bi = new CarpetImageRenderer().render(400, 400, polygonDetails);
      try {
      ImageIO.write(bi, "PNG", new File("carpet3d.png"));
      } catch (IOException e) {
      class OffScreenCanvas3D extends Canvas3D {
      public OffScreenCanvas3D(GraphicsConfiguration graphicsConfiguration) {
      super(graphicsConfiguration, true);
      public BufferedImage doRender(int width, int height) {
      BufferedImage bImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
      ImageComponent2D buffer = new ImageComponent2D(
      ImageComponent.FORMAT_RGB, bImage);
      bImage = getOffScreenBuffer().getImage();
      // Release the buffer
      return bImage;
      class PolygonDetails {
      private Color color;
      private double percentage;
      public PolygonDetails(double percentage, Color color) {
      this.color = color;
      this.percentage = percentage;
      public PolygonDetails() {
      public double getPercentage() {
      return percentage;
      public Color getColor() {
      return color;