Skip to main content

facing problem while creating a road/pathway in Java3D

No replies
mfharis
Offline
Joined: 2011-04-19
Points: 0

Hello guys,

I am creating a Group of Polygons to form a Carpet (with QuadArray: 4) for each segment/piece of the Carpet and place them one over another. so it looks like Rectangular Boxes placed one over another. Then with the Transformation3D (rot), I rotate the group with rot.rotX(-Math.PI/4) to make it like a Trapezoid shape that is like a Road from First-Person-View. But I am facing a problem here;

  1. 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)

I had uploaded the code on Pastie as well with inline comments

thanks and regards

<code>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) {
setScreenWidth(width);
setScreenHeight(height);

BranchGroup scene = createSceneGraph(polygonDetails);
Canvas3D onScreenCanvas = new Canvas3D(
SimpleUniverse.getPreferredConfiguration());

universe = new SimpleUniverse(onScreenCanvas);
ViewingPlatform viewingPlatform = universe.getViewingPlatform();
viewingPlatform.setNominalViewingTransform();
scene.compile();
universe.addBranchGraph(scene);

OffScreenCanvas3D offScreenCanvas = createOffScreenCanvas();

JFrame frame = new JFrame();
frame.setLayout(new BorderLayout());
frame.setLocation(GraphicsEnvironment.getLocalGraphicsEnvironment().getCenterPoint());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setTitle("3D Carpet Renderer");
frame.add(onScreenCanvas);

BufferedImage output = offScreenCanvas.doRender((int)getScreenWidth(), (int)getScreenHeight());
frame.setSize(output.getWidth(), output.getHeight());
setScreenWidth(output.getWidth());
setScreenHeight(output.getHeight());

return output;
}

private OffScreenCanvas3D createOffScreenCanvas() {
/**
* Setup graphics
*/
GraphicsConfiguration configuration = SimpleUniverse
.getPreferredConfiguration();

/**
* 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);

universe.getViewer().getView().addCanvas3D(canvas);

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);
// X:WIDTH, Y:HEIGHT, Z:LENGTH
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()));
polygonShape.setGeometry(polygon);
//System.out.println(polygonShape.getBounds());
polygonShape.setCollidable(false);
/**
* 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?
*/
carpetShapeGroup.addChild(polygonShape);
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);
transform.mul(rot);
//transform.setScale(0.7);

transform.setTranslation(vector);
tg.setTransform(transform);
tg.addChild(carpetShapeGroup);

objRoot.addChild(tg);

createLights(objRoot);
return objRoot;
}
private Appearance createAppearance(Color color){

Appearance polygon2Appearance = new Appearance();
Color3f c = new Color3f ();
c.set(color);
ColoringAttributes yellowCA = new ColoringAttributes (c, 1);
polygon2Appearance.setColoringAttributes(yellowCA);
return polygon2Appearance;

}
private void createLights(BranchGroup branchGroup) {

BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0),
100.0);

Color3f ambientLightColour = new Color3f(0.9f, 0.9f, 0.9f);
AmbientLight ambientLight = new AmbientLight(ambientLightColour);
ambientLight.setInfluencingBounds(bounds);

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);
directionLight.setInfluencingBounds(bounds);

branchGroup.addChild(ambientLight);
branchGroup.addChild(directionLight);
}

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) {
e.printStackTrace();
}
}
}

@SuppressWarnings("serial")
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);
buffer.setCapability(ImageComponent.ALLOW_FORMAT_READ);

setOffScreenBuffer(buffer);
renderOffScreenBuffer();
waitForOffScreenRendering();
bImage = getOffScreenBuffer().getImage();

// Release the buffer
setOffScreenBuffer(null);

return bImage;
}
}

class PolygonDetails {

private Color color;
private double percentage;

public PolygonDetails(double percentage, Color color) {
super();
this.color = color;
this.percentage = percentage;
}

public PolygonDetails() {
}

public double getPercentage() {
return percentage;
}

public Color getColor() {
return color;
}
}</code>