import org.jagatoo.input.InputSystem;
import org.jagatoo.input.devices.components.DeviceComponent;
import org.jagatoo.input.devices.components.Key;
import org.jagatoo.input.devices.components.MouseAxis;
import org.jagatoo.input.events.KeyReleasedEvent;
import org.jagatoo.opengl.enums.TextureBoundaryMode;
import org.openmali.FastMath;
import org.openmali.vecmath2.Point3f;
import org.openmali.vecmath2.TexCoord2f;
import org.openmali.vecmath2.Vector3f;
import org.openmali.vecmath2.util.MatrixUtils;
import org.xith3d.base.Xith3DEnvironment;
import org.xith3d.input.ObjectRotationInputHandler;
import org.xith3d.loaders.texture.TextureLoader;
import org.xith3d.loop.CanvasFPSListener;
import org.xith3d.render.Canvas3D;
import org.xith3d.resources.ResourceLocator;
import org.xith3d.scenegraph.Appearance;
import org.xith3d.scenegraph.BranchGroup;
import org.xith3d.scenegraph.Shape3D;
import org.xith3d.scenegraph.Texture2D;
import org.xith3d.scenegraph.TransformGroup;
import org.xith3d.scenegraph.TriangleArray;
import org.xith3d.test.Xith3DTest;
import org.xith3d.test.util.TestUtils;
import org.xith3d.utility.commandline.BasicApplicationArguments;
import org.xith3d.utility.events.WindowClosingRenderLoopEnder;

public class Room {

    private Shape3D shape;

    public Room () {
        shape = createRoom( 5f, 0.3f, 0.75f, 0.5f );
    }

    public Shape3D getShape() {
        return shape;
    }

    private Shape3D createRoom( float size, float thickness, float borderWidth, float outerBorderThicknessFactor ) {
        borderWidth = borderWidth / 8;
        final float halfSize = size / 2f;
        final int res = 32; // number of fields (res * res)
        float halfThickness = thickness / 2f;
        final float totalWidth = size + borderWidth;
        final float fieldSize = size / (float)res;
        final float outerBorderThickness = thickness * outerBorderThicknessFactor; // thickness of the border on the outside (use 1.0 for a completely plain border)
        final float borderAngle = FastMath.atan( ( thickness - outerBorderThickness ) / borderWidth ); // angle between the board's and the borders' up-normal

        final float texCoordSOuter0 = 0f;
        final float texCoordSInner0 = borderWidth / totalWidth;
        final float texCoordSOuter1 = 1f;
        final float texCoordSInner1 = 1f - texCoordSInner0;
        final float texCoordTTop0 = 1f * 0.5f;
        final float texCoordTTop1 = ( 1f - ( borderWidth / ( borderWidth * 2 + outerBorderThickness ) ) ) * 0.5f;
        final float texCoordTBottom0 = 0f * 0.5f;
        final float texCoordTBottom1 = ( borderWidth / ( borderWidth * 2 + outerBorderThickness ) ) * 0.5f;
        //final float texCoordTOutside0 = texCoordTTop1;
        //final float texCoordTOutside1 = texCoordTBottom1;

        final float dvere = 0.4f;
        final float zem = 0f;

        int numBaseVertices = 6 * res;

        Vector3f normalUp = new Vector3f( 0f, +1f, 0f );
        Vector3f normalUp2 = new Vector3f( 0f, +1f, 0f );
        Vector3f normalDown = new Vector3f( 0f, -1f, 0f );
        Vector3f normalLeft = new Vector3f( -1f, 0f, 0f );
        Vector3f normalRight = new Vector3f( +1f, 0f, 0f );
        Vector3f normalFront = new Vector3f( 0f, 0f, +1f );
        Vector3f normalBack = new Vector3f( 0f, 0f, -1f );

        /*
         * Now we need to duplicate all the triangles to get top and bottom grids.
         *
         * Our Texture looks like this:
         * ---------------------------
         * |            |            |
         * |            |            |
         * |            |            |
         * |            |            |
         * |            |            |
         * ---------------------------
         * |                         |
         * |                         |
         * |                         |
         * |                         |
         * |                         |
         * ---------------------------
         *
         * We will use the upper left area for the black fields
         * and the upper right area for the white fields.
         * The bottom area is a wooden texture for the border.
         */

        TriangleArray geom = new TriangleArray( numBaseVertices * 2 + 72 + 18);

        Point3f bufferPoint = new Point3f();
        TexCoord2f bufferTexCoord = new TexCoord2f();

        int j = 0;
        for ( int i = 0; i < res; i++, j += 12 )
        {
            /*
             * These are the vertex-coordinates for the top grid (shifted a little bit higher).
             */
            geom.setCoordinate( j + 0, -halfSize, +halfThickness, +halfSize - fieldSize * i );
            geom.setCoordinate( j + 1, +halfSize, +halfThickness, +halfSize - fieldSize * i );
            geom.setCoordinate( j + 2, -halfSize, +halfThickness, +halfSize - fieldSize * ( i + 1 ) );
            geom.setCoordinate( j + 3, geom.getCoordinate( j + 1, bufferPoint ) );
            geom.setCoordinate( j + 4, geom.getCoordinate( j + 2, bufferPoint ) );
            geom.setCoordinate( j + 5, +halfSize, +halfThickness, +halfSize - fieldSize * ( i + 1 ) );

            /*
             * These are the vertex-coordinates for the bottom grid (shifted a little bit higher).
             */
            geom.setCoordinate( j + 6, -halfSize, zem, +halfSize - fieldSize * i );
            geom.setCoordinate( j + 7, +halfSize, zem, +halfSize - fieldSize * i );
            geom.setCoordinate( j + 8, -halfSize, zem, +halfSize - fieldSize * ( i + 1 ) );
            geom.setCoordinate( j + 9, geom.getCoordinate( j + 7, bufferPoint ) );
            geom.setCoordinate( j + 10, geom.getCoordinate( j + 8, bufferPoint ) );
            geom.setCoordinate( j + 11, +halfSize, zem, +halfSize - fieldSize * ( i + 1 ) );

            /*
             * These are the vertex-normals for the top grid.
             */
            geom.setNormal( j + 0, normalUp );
            geom.setNormal( j + 1, normalUp );
            geom.setNormal( j + 2, normalUp );
            geom.setNormal( j + 3, normalUp );
            geom.setNormal( j + 4, normalUp );
            geom.setNormal( j + 5, normalUp );

            /*
             * These are the vertex-normals for the bottom grid.
             */
            geom.setNormal( j + 6, normalDown );
            geom.setNormal( j + 7, normalDown );
            geom.setNormal( j + 8, normalDown );
            geom.setNormal( j + 9, normalDown );
            geom.setNormal( j + 10, normalDown );
            geom.setNormal( j + 11, normalDown );

            /*
             * These are the vertex-texture-coordinates for the top grid.
             */
            boolean isOdd = ( i % 2 ) == 0;
            float s0 = isOdd ? 0f : 0.5f;
            float s1 = 1f * (float)( isOdd ? res : res + 1 ) / 2f;

            geom.setTextureCoordinate( 0, j + 0, s0, 0.52f );
            geom.setTextureCoordinate( 0, j + 0, s0, 0.52f );
            geom.setTextureCoordinate( 0, j + 1, s1, 0.52f );
            geom.setTextureCoordinate( 0, j + 2, s0, 0.52f );
            geom.setTextureCoordinate( 0, j + 3, geom.getTextureCoordinate( 0, j + 1, bufferTexCoord ) );
            geom.setTextureCoordinate( 0, j + 4, geom.getTextureCoordinate( 0, j + 2, bufferTexCoord ) );
            geom.setTextureCoordinate( 0, j + 5, s1, 1f );

            /*
             * These are the vertex-texture-coordinates for the bottom grid.
             */
            geom.setTextureCoordinate( 0, j + 6, geom.getTextureCoordinate( 0, j + 0, bufferTexCoord ) );
            geom.setTextureCoordinate( 0, j + 7, geom.getTextureCoordinate( 0, j + 1, bufferTexCoord ) );
            geom.setTextureCoordinate( 0, j + 8, geom.getTextureCoordinate( 0, j + 2, bufferTexCoord ) );
            geom.setTextureCoordinate( 0, j + 9, geom.getTextureCoordinate( 0, j + 3, bufferTexCoord ) );
            geom.setTextureCoordinate( 0, j + 10, geom.getTextureCoordinate( 0, j + 4, bufferTexCoord ) );
            geom.setTextureCoordinate( 0, j + 11, geom.getTextureCoordinate( 0, j + 5, bufferTexCoord ) );
        }

        /*
         * Now we need some triangles to construct a nice border around the chessboard.
         */

        halfThickness = halfThickness * 8;

        /*
         * Front border...
         */
        geom.setCoordinate( j + 0, +halfSize, +halfThickness, +halfSize );
        geom.setCoordinate( j + 1, -halfSize, +halfThickness, +halfSize );
        geom.setCoordinate( j + 2, +halfSize + borderWidth, +halfThickness - thickness + outerBorderThickness, +halfSize + borderWidth );
        geom.setCoordinate( j + 3, geom.getCoordinate( j + 1, bufferPoint ) );
        geom.setCoordinate( j + 4, geom.getCoordinate( j + 2, bufferPoint ) );
        geom.setCoordinate( j + 5, -halfSize - borderWidth, +halfThickness - thickness + outerBorderThickness, +halfSize + borderWidth );

        geom.setCoordinate( j + 6, +halfSize, zem, +halfSize );
        geom.setCoordinate( j + 7, -halfSize, zem, +halfSize );
        geom.setCoordinate( j + 8, +halfSize + borderWidth, zem, +halfSize + borderWidth );
        geom.setCoordinate( j + 9, geom.getCoordinate( j + 7, bufferPoint ) );
        geom.setCoordinate( j + 10, geom.getCoordinate( j + 8, bufferPoint ) );
        geom.setCoordinate( j + 11, -halfSize - borderWidth, zem, +halfSize + borderWidth );

        geom.setCoordinate( j + 12, geom.getCoordinate( j + 2, bufferPoint ) );
        geom.setCoordinate( j + 13, geom.getCoordinate( j + 5, bufferPoint ) );
        geom.setCoordinate( j + 14, geom.getCoordinate( j + 8, bufferPoint ) );
        geom.setCoordinate( j + 15, geom.getCoordinate( j + 13, bufferPoint ) );
        geom.setCoordinate( j + 16, geom.getCoordinate( j + 14, bufferPoint ) );
        geom.setCoordinate( j + 17, geom.getCoordinate( j + 11, bufferPoint ) );

        MatrixUtils.getRotationMatrix( Vector3f.POSITIVE_X_AXIS, borderAngle ).transform( normalUp, normalUp2 );

        geom.setNormal( j + 0, normalUp2 );
        geom.setNormal( j + 1, normalUp2 );
        geom.setNormal( j + 2, normalUp2 );
        geom.setNormal( j + 3, normalUp2 );
        geom.setNormal( j + 4, normalUp2 );
        geom.setNormal( j + 5, normalUp2 );

        geom.setNormal( j + 6, normalDown );
        geom.setNormal( j + 7, normalDown );
        geom.setNormal( j + 8, normalDown );
        geom.setNormal( j + 9, normalDown );
        geom.setNormal( j + 10, normalDown );
        geom.setNormal( j + 11, normalDown );

        geom.setNormal( j + 12, normalFront );
        geom.setNormal( j + 13, normalFront );
        geom.setNormal( j + 14, normalFront );
        geom.setNormal( j + 15, normalFront );
        geom.setNormal( j + 16, normalFront );
        geom.setNormal( j + 17, normalFront );

        geom.setTextureCoordinate( 0, j + 0, texCoordSInner1, texCoordTTop0 );
        geom.setTextureCoordinate( 0, j + 1, texCoordSInner0, texCoordTTop0 );
        geom.setTextureCoordinate( 0, j + 2, texCoordSOuter1, texCoordTTop1 );
        geom.setTextureCoordinate( 0, j + 3, geom.getTextureCoordinate( 0, j + 1, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 4, geom.getTextureCoordinate( 0, j + 2, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 5, texCoordSOuter0, texCoordTTop1 );

        geom.setTextureCoordinate( 0, j + 6, texCoordSInner1, texCoordTBottom0 );
        geom.setTextureCoordinate( 0, j + 7, texCoordSInner0, texCoordTBottom0 );
        geom.setTextureCoordinate( 0, j + 8, texCoordSOuter1, texCoordTBottom1 );
        geom.setTextureCoordinate( 0, j + 9, geom.getTextureCoordinate( 0, j + 1, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 10, geom.getTextureCoordinate( 0, j + 2, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 11, texCoordSOuter0, texCoordTBottom1 );

        geom.setTextureCoordinate( 0, j + 12, geom.getTextureCoordinate( 0, j + 2, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 13, geom.getTextureCoordinate( 0, j + 5, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 14, geom.getTextureCoordinate( 0, j + 8, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 15, geom.getTextureCoordinate( 0, j + 13, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 16, geom.getTextureCoordinate( 0, j + 14, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 17, geom.getTextureCoordinate( 0, j + 11, bufferTexCoord ) );

        /*
         * Back border...
         */
        j += 18;

        geom.setCoordinate( j + 0, +halfSize, +halfThickness, -halfSize );
        geom.setCoordinate( j + 1, -halfSize, +halfThickness, -halfSize );
        geom.setCoordinate( j + 2, +halfSize + borderWidth, +halfThickness - thickness + outerBorderThickness, -halfSize - borderWidth );
        geom.setCoordinate( j + 3, geom.getCoordinate( j + 1, bufferPoint ) );
        geom.setCoordinate( j + 4, geom.getCoordinate( j + 2, bufferPoint ) );
        geom.setCoordinate( j + 5, -halfSize - borderWidth, +halfThickness - thickness + outerBorderThickness, -halfSize - borderWidth );

        geom.setCoordinate( j + 6, +halfSize, zem, -halfSize );
        geom.setCoordinate( j + 7, -halfSize, zem, -halfSize );
        geom.setCoordinate( j + 8, +halfSize + borderWidth, zem, -halfSize - borderWidth );
        geom.setCoordinate( j + 9, geom.getCoordinate( j + 7, bufferPoint ) );
        geom.setCoordinate( j + 10, geom.getCoordinate( j + 8, bufferPoint ) );
        geom.setCoordinate( j + 11, -halfSize - borderWidth, zem, -halfSize - borderWidth );

        geom.setCoordinate( j + 12, geom.getCoordinate( j + 2, bufferPoint ) );
        geom.setCoordinate( j + 13, geom.getCoordinate( j + 5, bufferPoint ) );
        geom.setCoordinate( j + 14, geom.getCoordinate( j + 8, bufferPoint ) );
        geom.setCoordinate( j + 15, geom.getCoordinate( j + 13, bufferPoint ) );
        geom.setCoordinate( j + 16, geom.getCoordinate( j + 14, bufferPoint ) );
        geom.setCoordinate( j + 17, geom.getCoordinate( j + 11, bufferPoint ) );

        MatrixUtils.getRotationMatrix( Vector3f.NEGATIVE_X_AXIS, borderAngle ).transform( normalUp, normalUp2 );

        geom.setNormal( j + 0, normalUp2 );
        geom.setNormal( j + 1, normalUp2 );
        geom.setNormal( j + 2, normalUp2 );
        geom.setNormal( j + 3, normalUp2 );
        geom.setNormal( j + 4, normalUp2 );
        geom.setNormal( j + 5, normalUp2 );

        geom.setNormal( j + 6, normalDown );
        geom.setNormal( j + 7, normalDown );
        geom.setNormal( j + 8, normalDown );
        geom.setNormal( j + 9, normalDown );
        geom.setNormal( j + 10, normalDown );
        geom.setNormal( j + 11, normalDown );

        geom.setNormal( j + 12, normalBack );
        geom.setNormal( j + 13, normalBack );
        geom.setNormal( j + 14, normalBack );
        geom.setNormal( j + 15, normalBack );
        geom.setNormal( j + 16, normalBack );
        geom.setNormal( j + 17, normalBack );

        geom.setTextureCoordinate( 0, j + 0, texCoordSInner1, texCoordTTop0 );
        geom.setTextureCoordinate( 0, j + 1, texCoordSInner0, texCoordTTop0 );
        geom.setTextureCoordinate( 0, j + 2, texCoordSOuter1, texCoordTTop1 );
        geom.setTextureCoordinate( 0, j + 3, geom.getTextureCoordinate( 0, j + 1, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 4, geom.getTextureCoordinate( 0, j + 2, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 5, texCoordSOuter0, texCoordTTop1 );

        geom.setTextureCoordinate( 0, j + 6, texCoordSInner1, texCoordTBottom0 );
        geom.setTextureCoordinate( 0, j + 7, texCoordSInner0, texCoordTBottom0 );
        geom.setTextureCoordinate( 0, j + 8, texCoordSOuter1, texCoordTBottom1 );
        geom.setTextureCoordinate( 0, j + 9, geom.getTextureCoordinate( 0, j + 1, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 10, geom.getTextureCoordinate( 0, j + 2, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 11, texCoordSOuter0, texCoordTBottom1 );

        geom.setTextureCoordinate( 0, j + 12, geom.getTextureCoordinate( 0, j + 2, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 13, geom.getTextureCoordinate( 0, j + 5, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 14, geom.getTextureCoordinate( 0, j + 8, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 15, geom.getTextureCoordinate( 0, j + 13, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 16, geom.getTextureCoordinate( 0, j + 14, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 17, geom.getTextureCoordinate( 0, j + 11, bufferTexCoord ) );

        /*
         * Left border...
         */
        j += 18;

        geom.setCoordinate( j + 0, -halfSize, +halfThickness, +halfSize );
        geom.setCoordinate( j + 1, -halfSize, +halfThickness, -halfSize );
        geom.setCoordinate( j + 2, -halfSize - borderWidth, +halfThickness - thickness + outerBorderThickness, +halfSize + borderWidth );
        geom.setCoordinate( j + 3, geom.getCoordinate( j + 1, bufferPoint ) );
        geom.setCoordinate( j + 4, geom.getCoordinate( j + 2, bufferPoint ) );
        geom.setCoordinate( j + 5, -halfSize - borderWidth, +halfThickness - thickness + outerBorderThickness, -halfSize - borderWidth );

        geom.setCoordinate( j + 6, -halfSize, zem, +halfSize );
        geom.setCoordinate( j + 7, -halfSize, zem, -halfSize );
        geom.setCoordinate( j + 8, -halfSize - borderWidth, zem, +halfSize + borderWidth );
        geom.setCoordinate( j + 9, geom.getCoordinate( j + 7, bufferPoint ) );
        geom.setCoordinate( j + 10, geom.getCoordinate( j + 8, bufferPoint ) );
        geom.setCoordinate( j + 11, -halfSize - borderWidth, zem, -halfSize - borderWidth );

        geom.setCoordinate( j + 12, geom.getCoordinate( j + 2, bufferPoint ) );
        geom.setCoordinate( j + 13, geom.getCoordinate( j + 5, bufferPoint ) );
        geom.setCoordinate( j + 14, geom.getCoordinate( j + 8, bufferPoint ) );
        geom.setCoordinate( j + 15, geom.getCoordinate( j + 13, bufferPoint ) );
        geom.setCoordinate( j + 16, geom.getCoordinate( j + 14, bufferPoint ) );
        geom.setCoordinate( j + 17, geom.getCoordinate( j + 11, bufferPoint ) );

        MatrixUtils.getRotationMatrix( Vector3f.POSITIVE_Z_AXIS, borderAngle ).transform( normalUp, normalUp2 );

        geom.setNormal( j + 0, normalUp2 );
        geom.setNormal( j + 1, normalUp2 );
        geom.setNormal( j + 2, normalUp2 );
        geom.setNormal( j + 3, normalUp2 );
        geom.setNormal( j + 4, normalUp2 );
        geom.setNormal( j + 5, normalUp2 );

        geom.setNormal( j + 6, normalDown );
        geom.setNormal( j + 7, normalDown );
        geom.setNormal( j + 8, normalDown );
        geom.setNormal( j + 9, normalDown );
        geom.setNormal( j + 10, normalDown );
        geom.setNormal( j + 11, normalDown );

        geom.setNormal( j + 12, normalLeft );
        geom.setNormal( j + 13, normalLeft );
        geom.setNormal( j + 14, normalLeft );
        geom.setNormal( j + 15, normalLeft );
        geom.setNormal( j + 16, normalLeft );
        geom.setNormal( j + 17, normalLeft );

        geom.setTextureCoordinate( 0, j + 0, texCoordSInner1, texCoordTTop0 );
        geom.setTextureCoordinate( 0, j + 1, texCoordSInner0, texCoordTTop0 );
        geom.setTextureCoordinate( 0, j + 2, texCoordSOuter1, texCoordTTop1 );
        geom.setTextureCoordinate( 0, j + 3, geom.getTextureCoordinate( 0, j + 1, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 4, geom.getTextureCoordinate( 0, j + 2, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 5, texCoordSOuter0, texCoordTTop1 );

        geom.setTextureCoordinate( 0, j + 6, texCoordSInner1, texCoordTBottom0 );
        geom.setTextureCoordinate( 0, j + 7, texCoordSInner0, texCoordTBottom0 );
        geom.setTextureCoordinate( 0, j + 8, texCoordSOuter1, texCoordTBottom1 );
        geom.setTextureCoordinate( 0, j + 9, geom.getTextureCoordinate( 0, j + 1, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 10, geom.getTextureCoordinate( 0, j + 2, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 11, texCoordSOuter0, texCoordTBottom1 );

        geom.setTextureCoordinate( 0, j + 12, geom.getTextureCoordinate( 0, j + 2, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 13, geom.getTextureCoordinate( 0, j + 5, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 14, geom.getTextureCoordinate( 0, j + 8, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 15, geom.getTextureCoordinate( 0, j + 13, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 16, geom.getTextureCoordinate( 0, j + 14, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 17, geom.getTextureCoordinate( 0, j + 11, bufferTexCoord ) );

        /*
         * Right border...
         */
        /*        j += 18;

                geom.setCoordinate( j + 0, +halfSize, +halfThickness, +halfSize );
                geom.setCoordinate( j + 1, +halfSize, +halfThickness, -halfSize );
                geom.setCoordinate( j + 2, +halfSize + borderWidth, +halfThickness - thickness + outerBorderThickness, +halfSize + borderWidth );
                geom.setCoordinate( j + 3, geom.getCoordinate( j + 1, bufferPoint ) );
                geom.setCoordinate( j + 4, geom.getCoordinate( j + 2, bufferPoint ) );
                geom.setCoordinate( j + 5, +halfSize + borderWidth, +halfThickness - thickness + outerBorderThickness, -halfSize - borderWidth );

                geom.setCoordinate( j + 6, +halfSize, zem, +halfSize );
                geom.setCoordinate( j + 7, +halfSize, zem, -halfSize );
                geom.setCoordinate( j + 8, +halfSize + borderWidth, zem, +halfSize + borderWidth );
                geom.setCoordinate( j + 9, geom.getCoordinate( j + 7, bufferPoint ) );
                geom.setCoordinate( j + 10, geom.getCoordinate( j + 8, bufferPoint ) );
                geom.setCoordinate( j + 11, +halfSize + borderWidth, zem, -halfSize - borderWidth );

                geom.setCoordinate( j + 12, geom.getCoordinate( j + 2, bufferPoint ) );
                geom.setCoordinate( j + 13, geom.getCoordinate( j + 5, bufferPoint ) );
                geom.setCoordinate( j + 14, geom.getCoordinate( j + 8, bufferPoint ) );
                geom.setCoordinate( j + 15, geom.getCoordinate( j + 13, bufferPoint ) );
                geom.setCoordinate( j + 16, geom.getCoordinate( j + 14, bufferPoint ) );
                geom.setCoordinate( j + 17, geom.getCoordinate( j + 11, bufferPoint ) );
        */
        j += 18;

        geom.setCoordinate( j + 0, +halfSize, +halfThickness, +halfSize );
        geom.setCoordinate( j + 1, +halfSize, +halfThickness, dvere );
        geom.setCoordinate( j + 2, +halfSize + borderWidth, +halfThickness - thickness + outerBorderThickness, +halfSize + borderWidth );
        geom.setCoordinate( j + 3, geom.getCoordinate( j + 1, bufferPoint ) );
        geom.setCoordinate( j + 4, geom.getCoordinate( j + 2, bufferPoint ) );
        geom.setCoordinate( j + 5, +halfSize + borderWidth, +halfThickness - thickness + outerBorderThickness, dvere - borderWidth );

        geom.setCoordinate( j + 6, +halfSize, zem, +halfSize );
        geom.setCoordinate( j + 7, +halfSize, zem, dvere );
        geom.setCoordinate( j + 8, +halfSize + borderWidth, zem, +halfSize + borderWidth );
        geom.setCoordinate( j + 9, geom.getCoordinate( j + 7, bufferPoint ) );
        geom.setCoordinate( j + 10, geom.getCoordinate( j + 8, bufferPoint ) );
        geom.setCoordinate( j + 11, +halfSize + borderWidth, zem, dvere - borderWidth );

        geom.setCoordinate( j + 12, geom.getCoordinate( j + 2, bufferPoint ) );
        geom.setCoordinate( j + 13, geom.getCoordinate( j + 5, bufferPoint ) );
        geom.setCoordinate( j + 14, geom.getCoordinate( j + 8, bufferPoint ) );
        geom.setCoordinate( j + 15, geom.getCoordinate( j + 13, bufferPoint ) );
        geom.setCoordinate( j + 16, geom.getCoordinate( j + 14, bufferPoint ) );
        geom.setCoordinate( j + 17, geom.getCoordinate( j + 11, bufferPoint ) );

        MatrixUtils.getRotationMatrix( Vector3f.NEGATIVE_Z_AXIS, borderAngle ).transform( normalUp, normalUp2 );

        geom.setNormal( j + 0, normalUp2 );
        geom.setNormal( j + 1, normalUp2 );
        geom.setNormal( j + 2, normalUp2 );
        geom.setNormal( j + 3, normalUp2 );
        geom.setNormal( j + 4, normalUp2 );
        geom.setNormal( j + 5, normalUp2 );

        geom.setNormal( j + 6, normalDown );
        geom.setNormal( j + 7, normalDown );
        geom.setNormal( j + 8, normalDown );
        geom.setNormal( j + 9, normalDown );
        geom.setNormal( j + 10, normalDown );
        geom.setNormal( j + 11, normalDown );

        geom.setNormal( j + 12, normalRight );
        geom.setNormal( j + 13, normalRight );
        geom.setNormal( j + 14, normalRight );
        geom.setNormal( j + 15, normalRight );
        geom.setNormal( j + 16, normalRight );
        geom.setNormal( j + 17, normalRight );

        geom.setTextureCoordinate( 0, j + 0, texCoordSInner1, texCoordTTop0 );
        geom.setTextureCoordinate( 0, j + 1, texCoordSInner0, texCoordTTop0 );
        geom.setTextureCoordinate( 0, j + 2, texCoordSOuter1, texCoordTTop1 );
        geom.setTextureCoordinate( 0, j + 3, geom.getTextureCoordinate( 0, j + 1, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 4, geom.getTextureCoordinate( 0, j + 2, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 5, texCoordSOuter0, texCoordTTop1 );

        geom.setTextureCoordinate( 0, j + 6, texCoordSInner1, texCoordTBottom0 );
        geom.setTextureCoordinate( 0, j + 7, texCoordSInner0, texCoordTBottom0 );
        geom.setTextureCoordinate( 0, j + 8, texCoordSOuter1, texCoordTBottom1 );
        geom.setTextureCoordinate( 0, j + 9, geom.getTextureCoordinate( 0, j + 1, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 10, geom.getTextureCoordinate( 0, j + 2, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 11, texCoordSOuter0, texCoordTBottom1 );

        geom.setTextureCoordinate( 0, j + 12, geom.getTextureCoordinate( 0, j + 2, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 13, geom.getTextureCoordinate( 0, j + 5, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 14, geom.getTextureCoordinate( 0, j + 8, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 15, geom.getTextureCoordinate( 0, j + 13, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 16, geom.getTextureCoordinate( 0, j + 14, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 17, geom.getTextureCoordinate( 0, j + 11, bufferTexCoord ) );

        j += 18;

        geom.setCoordinate( j + 0, +halfSize, +halfThickness, -dvere );
        geom.setCoordinate( j + 1, +halfSize, +halfThickness, -halfSize );
        geom.setCoordinate( j + 2, +halfSize + borderWidth, +halfThickness - thickness + outerBorderThickness, -dvere + borderWidth );
        geom.setCoordinate( j + 3, geom.getCoordinate( j + 1, bufferPoint ) );
        geom.setCoordinate( j + 4, geom.getCoordinate( j + 2, bufferPoint ) );
        geom.setCoordinate( j + 5, +halfSize + borderWidth, +halfThickness - thickness + outerBorderThickness, -halfSize - borderWidth );

        geom.setCoordinate( j + 6, +halfSize, zem, -dvere );
        geom.setCoordinate( j + 7, +halfSize, zem, -halfSize );
        geom.setCoordinate( j + 8, +halfSize + borderWidth, zem, -dvere + borderWidth );
        geom.setCoordinate( j + 9, geom.getCoordinate( j + 7, bufferPoint ) );
        geom.setCoordinate( j + 10, geom.getCoordinate( j + 8, bufferPoint ) );
        geom.setCoordinate( j + 11, +halfSize + borderWidth, zem, -halfSize - borderWidth );

        geom.setCoordinate( j + 12, geom.getCoordinate( j + 2, bufferPoint ) );
        geom.setCoordinate( j + 13, geom.getCoordinate( j + 5, bufferPoint ) );
        geom.setCoordinate( j + 14, geom.getCoordinate( j + 8, bufferPoint ) );
        geom.setCoordinate( j + 15, geom.getCoordinate( j + 13, bufferPoint ) );
        geom.setCoordinate( j + 16, geom.getCoordinate( j + 14, bufferPoint ) );
        geom.setCoordinate( j + 17, geom.getCoordinate( j + 11, bufferPoint ) );

        geom.setNormal( j + 0, normalUp2 );
        geom.setNormal( j + 1, normalUp2 );
        geom.setNormal( j + 2, normalUp2 );
        geom.setNormal( j + 3, normalUp2 );
        geom.setNormal( j + 4, normalUp2 );
        geom.setNormal( j + 5, normalUp2 );

        geom.setNormal( j + 6, normalDown );
        geom.setNormal( j + 7, normalDown );
        geom.setNormal( j + 8, normalDown );
        geom.setNormal( j + 9, normalDown );
        geom.setNormal( j + 10, normalDown );
        geom.setNormal( j + 11, normalDown );

        geom.setNormal( j + 12, normalRight );
        geom.setNormal( j + 13, normalRight );
        geom.setNormal( j + 14, normalRight );
        geom.setNormal( j + 15, normalRight );
        geom.setNormal( j + 16, normalRight );
        geom.setNormal( j + 17, normalRight );

        geom.setTextureCoordinate( 0, j + 0, texCoordSInner1, texCoordTTop0 );
        geom.setTextureCoordinate( 0, j + 1, texCoordSInner0, texCoordTTop0 );
        geom.setTextureCoordinate( 0, j + 2, texCoordSOuter1, texCoordTTop1 );
        geom.setTextureCoordinate( 0, j + 3, geom.getTextureCoordinate( 0, j + 1, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 4, geom.getTextureCoordinate( 0, j + 2, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 5, texCoordSOuter0, texCoordTTop1 );

        geom.setTextureCoordinate( 0, j + 6, texCoordSInner1, texCoordTBottom0 );
        geom.setTextureCoordinate( 0, j + 7, texCoordSInner0, texCoordTBottom0 );
        geom.setTextureCoordinate( 0, j + 8, texCoordSOuter1, texCoordTBottom1 );
        geom.setTextureCoordinate( 0, j + 9, geom.getTextureCoordinate( 0, j + 1, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 10, geom.getTextureCoordinate( 0, j + 2, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 11, texCoordSOuter0, texCoordTBottom1 );

        geom.setTextureCoordinate( 0, j + 12, geom.getTextureCoordinate( 0, j + 2, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 13, geom.getTextureCoordinate( 0, j + 5, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 14, geom.getTextureCoordinate( 0, j + 8, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 15, geom.getTextureCoordinate( 0, j + 13, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 16, geom.getTextureCoordinate( 0, j + 14, bufferTexCoord ) );
        geom.setTextureCoordinate( 0, j + 17, geom.getTextureCoordinate( 0, j + 11, bufferTexCoord ) );

        Appearance app = new Appearance();
        Texture2D texture = TextureLoader.getInstance().getTexture( "chessboard.jpg" );
        texture.setBoundaryModes( TextureBoundaryMode.WRAP, TextureBoundaryMode.WRAP );

        app.setTexture( 0, texture );

        Shape3D shape = new Shape3D( geom, app );

        return ( shape );
    }

}
