Package cc.sketchchair.core

Source Code of cc.sketchchair.core.SketchChair

/*******************************************************************************
* This is part of SketchChair, an open-source tool for designing your own furniture.
*     www.sketchchair.cc
*    
*     Copyright (C) 2012, Diatom Studio ltd.  Contact: hello@diatom.cc
*
*     This program is free software: you can redistribute it and/or modify
*     it under the terms of the GNU General Public License as published by
*     the Free Software Foundation, either version 3 of the License, or
*     (at your option) any later version.
*
*     This program is distributed in the hope that it will be useful,
*     but WITHOUT ANY WARRANTY; without even the implied warranty of
*     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*     GNU General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with this program.  If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package cc.sketchchair.core;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.media.opengl.GL;
import javax.vecmath.Matrix4f;
import javax.vecmath.Vector3f;

import nu.xom.Attribute;
import nu.xom.Element;

import processing.core.PApplet;
import processing.core.PConstants;
import processing.core.PGraphics;
import processing.core.PImage;
import processing.opengl.PGL;
import processing.opengl.PGraphicsOpenGL;
import toxi.geom.Matrix4x4;
import toxi.geom.Plane;
import toxi.geom.Vec2D;
import toxi.geom.Vec3D;
import ShapePacking.BezierControlNode;
import ShapePacking.spShape;
import ShapePacking.spShapePack;

import cc.sketchchair.environments.Environment;
import cc.sketchchair.geometry.GeometryOperations;
import cc.sketchchair.geometry.SlicePlane;
import cc.sketchchair.geometry.SlicePlanes;
import cc.sketchchair.sketch.SETTINGS_SKETCH;
import cc.sketchchair.sketch.Sketch;
import cc.sketchchair.sketch.SketchPath;
import cc.sketchchair.sketch.SketchPoint;
import cc.sketchchair.sketch.SketchShape;
import cc.sketchchair.sketch.SketchShapes;
import cc.sketchchair.sketch.SketchSpline;
import cc.sketchchair.sketch.SketchTools;
import cc.sketchchair.sketch.SliceSlot;


import com.bulletphysics.BulletGlobals;
import com.bulletphysics.collision.dispatch.CollisionDispatcher;
import com.bulletphysics.collision.dispatch.CollisionFlags;
import com.bulletphysics.collision.dispatch.CollisionObject;
import com.bulletphysics.collision.shapes.CollisionShape;
import com.bulletphysics.collision.shapes.IndexedMesh;
import com.bulletphysics.collision.shapes.TriangleIndexVertexArray;
import com.bulletphysics.collision.shapes.VertexData;
import com.bulletphysics.dynamics.RigidBody;
import com.bulletphysics.dynamics.RigidBodyConstructionInfo;
import com.bulletphysics.dynamics.constraintsolver.Generic6DofConstraint;
import com.bulletphysics.extras.gimpact.GImpactCollisionAlgorithm;
import com.bulletphysics.extras.gimpact.GImpactMeshShape;
import com.bulletphysics.linearmath.DefaultMotionState;
import com.bulletphysics.linearmath.MatrixUtil;
import com.bulletphysics.linearmath.MotionState;
import com.bulletphysics.linearmath.Transform;
import com.bulletphysics.util.ObjectArrayList;


/**
* The SketchChair Class represents one SketchChair or SketchObject in the program,
* This Class Brings together a chairs geometry and settings specific to that chair.
*   
*<pre>
*       |\|\|\|\|\
*       || | | | |
*       || | | | |
*       || | | | |
*       || | | | |
*       ||\ \ \ \ \
*       || \ \ \ \ \
*        ||  \ \ \ \ \
*       ||  || | | |||
*       ||  ||      ||
*           ||      ||
*          ||      ||
*
* </pre> 
*
* @author Diatom Studio
*/
public class SketchChair {
  float slatSpacingX = 39f;

  boolean built = false;

  private boolean builtOuline = false;
  Vec3D centreOfMass = new Vec3D();

  float coverLength = 0;

  float coverWidth = 0;
  // private SketchSpline crossSpline;
  // SlicePlane curSlicePlane = null;
  boolean destroy;
  public transient RigidBody rigidBody = null;
  transient Vector3f rigidRenderOffset = new Vector3f();
  public SlicePlanes selectedPlanes = new SlicePlanes();
  // SketchShapes sketchShapes = new SketchShapes();

  // SketchSpline sketchSpline = new SketchSpline();

  float slicePlaceSpacing = SETTINGS_SKETCH.slat_x_spacing;// spacing in
  public SlicePlanes slicePlanesSlatSlices = new SlicePlanes();
  public SlicePlanes slicePlanesY = new SlicePlanes();

  public CrossSliceSelections crossSliceSelections = new CrossSliceSelections();
  public CrossSliceSelection creossSelectionTempOver = null;

  transient public DefaultMotionState startMotionState;

  transient public Transform startWorldTransform;
  transient public Transform currentWorldTransform = new Transform();
  transient GImpactMeshShape trimesh = null;

  private boolean updateCollisionMesh = false;
  private float width = SETTINGS.chair_width; // 600mm

  private boolean reScaling = false;

  transient private Generic6DofConstraint chairCentreConstraint;

  // private FeltCover feltCover;

  private float scale = 1f;

  private float mass = 8f;

  private boolean dragging;

  public float startCoverPercent = 0;

  public float endCoverPercent = .5f;

  private boolean personSeated = false;

  private float imgBorder = 25;

  public String cloudID = null;

  public String localSavelocation = null;

  public boolean rebuildLength;
  public int chairColour = 255;

  private float density = 0.0001f;

  private TriangleIndexVertexArray indexVertexArrays;

  private float rotateRend = 0;

  private float materialWidth;

  private boolean initailSliceAdded = false;

  public int selectedPlaneNumber;

  SketchChair() {
    // this.sketchSpline.slots_on_inside = true;
    // this.sketchShapes.add(this.sketchSpline);
    // this.sketchShapes.currentShape = sketchSpline;
    GLOBAL.undo.addOperation(new UndoAction(this, UndoAction.ADD_CHAIR));

    //GLOBAL.planesWidget.planes = this.getSlicePlanesY();
    buildWidth();
    rebuildWidth();

  }

  /**
   * Build design from a XML element
   * @param element
   */
  public SketchChair(Element element) {

    // wrong type
    if (!element.getLocalName().equals("SketchChair"))
      return;

    // get slat spacing
    if (element.getAttributeValue("cloudID") != null)
      cloudID = element.getAttributeValue("cloudID");

    // get slat spacing
    if (element.getAttributeValue("slatSpacingX") != null)
      slatSpacingX = Float.valueOf(element
          .getAttributeValue("slatSpacingX"));

    if (element.getAttributeValue("materialWidth") != null)
      SETTINGS.materialThickness = Float.valueOf(element
          .getAttributeValue("materialWidth"));

    if (element.getAttributeValue("scale") != null)
      SETTINGS.scale = Float.valueOf(element.getAttributeValue("scale"));

    element.addAttribute(new Attribute("materialWidth", String
        .valueOf(SETTINGS.materialThickness)));

    element.addAttribute(new Attribute("scale", String
        .valueOf(SETTINGS.scale)));

    for (int i = 0; i < element.getChildCount(); i++) {
      Element child = (Element) element.getChild(i);

      if (child.getLocalName().equals("SlicePlanes"))
        this.setSlicePlanesY(new SlicePlanes(child));

      if (child.getLocalName().equals("CrossSliceSelections"))
        this.crossSliceSelections = new CrossSliceSelections(child,
            this.getSlicePlanesY(), this);

    }

    if (GLOBAL.widgetMaterials != null
        && GLOBAL.widgetMaterials.slotSizeTextfield != null) {
      GLOBAL.widgetMaterials.slotSizeTextfield.setText(
          Float.toString(SETTINGS.materialThickness));
    }

    // now we are a "live" object again, so let's run rebuild and start
    this.currentWorldTransform = new Transform();
    this.selectedPlanes.empty();
    this.selectedPlanes.add(this.getSlicePlanesY());
    this.selectedPlanes.buildCurrentSketch();

    // this.updateCollisionShape();
    LOGGER.debug("SketchChair: finished load: about to build chair for the first time");
    this.buildPreview();
    this.addRigidModel();
    //buildWidth();

    //move the model to the ground plane
    this.setAtGroundHeightCentred();
    this.personSeated = false;

    setCurrentPositionAsStartTransform();
    GLOBAL.jBullet.update();
    this.update();
    this.initailSliceAdded = true;
    //  seatPerson();
    //buildWidth();
  }

  /**
   * Build design from SketchShape element
   * @param shape
   */
  public SketchChair(SketchShape shape) {

    SlicePlane plane = new SlicePlane(new Plane(new Vec3D(0, 0, 0),
        new Vec3D(0, 0, -1)));
    plane.setSelected(true);
    plane.getSketch().getSketchShapes().add(shape);
    this.selectedPlanes.add(plane);
    this.mouseReleased(0, 0);
   

  }

  /**
   * Constrain the current design to the center plane in physics engine. This stops the design from falling over.x
   */
  void addCentrePlaneConstraint() {
    /*
     *
     * Transform localA = new Transform(); Transform localB = new
     * Transform();
     *
     * localA.setIdentity();
     *
     * localB.setIdentity(); Vec3D centre = this.getCentreOfMass();
     * localA.origin.set(centre.x, centre.y, centre.z);
     *
     * localB.origin.set(0f, 0f, 0f);
     *
     * CollisionShape ZeroShape = null; jBullet.ZeroBodyChair = new
     * RigidBody(0.0f, null, ZeroShape);
     *
     * Transform Rotation = new Transform(); Rotation.setIdentity();
     *
     * MatrixUtil.setEulerZYX(Rotation.basis, BulletGlobals.SIMD_PI, 0, 0);
     *
     * jBullet.ZeroBodyChair.setWorldTransform(Rotation);
     *
     * this.chairCentreConstraint = new
     * Generic6DofConstraint(this.rigidBody, jBullet.ZeroBodyChair, localA,
     * localB, false);
     *
     * this.chairCentreConstraint.setLimit(0, 1, 0); // Disable X axis
     * limits this.chairCentreConstraint.setLimit(1, 1, 0); // Disable Y
     * axis limits this.chairCentreConstraint.setLimit(2, 1, 0); // Set the
     * Z axis to // always be equal to // zero
     * this.chairCentreConstraint.setLimit(3, 0, 0); // Disable X rotational
     * // axes this.chairCentreConstraint.setLimit(4, 0, 0); // Disable Y
     * rotational // axes this.chairCentreConstraint.setLimit(5, 1, 0); //
     * Uncap the rotational // axes
     *
     * // this.rotationConstrains = new Vector3f(0,0,1); //
     * this.rigidBody.setMassProps(this.mass ,rotationConstrains);
     * GLOBAL.jBullet.update();
     */
    /*
     *
     * this.chairCentreConstraint.setLimit(0,1,0); // Disable X axis limits
     * this.chairCentreConstraint.setLimit(1,1,0); // Disable Y axis limits
     * this.chairCentreConstraint.setLimit(2,0,0); // Set the Z axis to
     * always be equal to zero
     * //this.chairCentreConstraint.setLimit(3,(float)-Math.PI+
     * .001f,(float)-Math.PI+.01f); // Disable X rotational axes // this
     * this
     * .chairCentreConstraint.setLimit(3,(float)-Math.PI,(float)Math.PI); //
     * Disable X rotational axes // this
     *
     * //this.chairCentreConstraint.setLimit(3,0,0); // Disable X rotational
     * axes // this this.chairCentreConstraint.setLimit(4,0,0); // Disable Y
     * rotational axes this.chairCentreConstraint.setLimit(5,1,0); // Uncap
     * the Z rotational axes //#endif
     */
    // GLOBAL.jBullet.myWorld.addConstraint(this.chairCentreConstraint,
    // true);
    // this.rigidBody.setAngularFactor(.001f);
    this.rigidBody.setAngularFactor(new Vector3f(0, 0, 1));

    // GLOBAL.jBullet.myWorld
    // EnableVelocityXYZ(body,true,true,false);
    // EnableRotationXYZ(body,false,false,true);

    // GLOBAL.jBullet.myWorld.
    // EnableWorldRotationXYZ(false,false,true);

  }

  private void addCrossPlanes() {

    // add all of our profiles in the z dir and link them to a sketch
    // int numSlices = (int)(this.width / this.slicePlaceSpacing);

  }

  /**
   * Add a new slice plane to the design.
   */
  public void addNewSlicePlane() {

    SketchShape selected = this.selectedPlanes.getSelectedShape();
    SlicePlane selectedPlane = this.selectedPlanes.getSelectedShapePlane();

    if (selected != null && selectedPlane != null) {
      if (selected instanceof SketchSpline) {
        SketchSpline SketchSpline = (SketchSpline) selected;
        selected = SketchSpline.getPath();
      }

      CrossSliceSelection selection = new CrossSliceSelection(selected,
          selectedPlane, .1f, .5f, 25f, this);
      selection.editing = true;
      this.crossSliceSelections.add(selection);

    }

  }

  /**
   * Add a new layer to the design.
   */
  public void addLayer() {
    if (this.selectedPlanes.size() > 0) {
      SlicePlane copyPlane = this.selectedPlanes.getFirst().clone();

      int index = this.getSlicePlanesY().indexOf(
          this.selectedPlanes.getFirst());

      this.getSlicePlanesY().add(index, copyPlane);
      this.rebuildWidth();

    } else {
      SlicePlane copyPlane = this.getSlicePlanesY().getFirst().clone();
      this.getSlicePlanesY().add(copyPlane);
      this.rebuildWidth();

    }
    //  SETTINGS.slat_num++;

  }

  /**
   * Set the current designs position as the start position to start from after rewinding.
   */
  public void setCurrentPositionAsStartTransform() {
    Transform startTransform = new Transform();

    Vector3f localInertia = new Vector3f(0, 0, 0);
    float mass = this.getMass();
    trimesh.calculateLocalInertia(mass, localInertia);
    startTransform.origin.set(
        this.rigidBody.getMotionState().getWorldTransform(
            currentWorldTransform).origin.x,
        this.rigidBody.getMotionState().getWorldTransform(
            currentWorldTransform).origin.y,
        this.rigidBody.getMotionState().getWorldTransform(
            currentWorldTransform).origin.z);

    DefaultMotionState myMotionState = new DefaultMotionState(
        startTransform);

    this.startWorldTransform = startTransform;
  }

  /**
   * Return the centre position of the design in physics space.
   * @return
   */
  public Vec3D getPhysicsOrigin() {

    if (currentWorldTransform == null || rigidBody == null)
      return new Vec3D(0, 0, 0);

    float scaleBy = 1f / GLOBAL.jBullet.getScale();
    Transform myTransform = new Transform();
    myTransform = rigidBody.getMotionState().getWorldTransform(myTransform);

    Vector3f center = new Vector3f();
    rigidBody.getCenterOfMassPosition(center);

    return new Vec3D(center.x, center.y, center.z);
  }
 
 
 

  /**
   * Generate a collision mesh for the design and add this to the physics engine.
   */
  public void addRigidModel() {
    // create trimesh
    //if already contains a rigid model remove it.
    if (this.chairCentreConstraint != null)
      GLOBAL.jBullet.myWorld.removeConstraint(this.chairCentreConstraint);

    if (this.rigidBody != null) {
      removeRigidModel();
      GLOBAL.jBullet.myWorld.removeRigidBody(this.rigidBody);
      GLOBAL.jBullet.rigidBodies.remove(this.rigidBody);
      GLOBAL.jBullet.myWorld.stepSimulation(1);
    }

    Vec3D centreOfMass = this.getCentreOfMass();
    this.centreOfMass = centreOfMass;
    indexVertexArrays = this.getVertexArray(centreOfMass.x, centreOfMass.y,
        centreOfMass.z);
    //this.buildCoverMesh(indexVertexArrays, centreOfMass);

    if (indexVertexArrays == null)
      return;

    // if(indexVertexArrays.getIndexedMeshArray().size() < 2)
    // return;

    trimesh = new GImpactMeshShape(indexVertexArrays);
    trimesh.setLocalScaling(new Vector3f(1f, 1f, 1f));
    trimesh.updateBound();

    if (trimesh == null)
      return;

    CollisionDispatcher dispatcher = (CollisionDispatcher) GLOBAL.jBullet.myWorld
        .getDispatcher();
    if (dispatcher == null)
      return;

    GImpactCollisionAlgorithm.registerAlgorithm(dispatcher);
    Transform startTransform = new Transform();

    Vector3f localInertia = new Vector3f(0, 0, 0);
    float mass = this.getMass();
    trimesh.calculateLocalInertia(mass, localInertia);
    startTransform.origin.set(centreOfMass.x, centreOfMass.y,
        centreOfMass.z);
    DefaultMotionState myMotionState = new DefaultMotionState(
        startTransform);

    this.startWorldTransform = startTransform;
    RigidBodyConstructionInfo rbInfo = new RigidBodyConstructionInfo(mass,
        myMotionState, trimesh, localInertia);
    rigidBody = new RigidBody(rbInfo);
    Transform center = new Transform();
    center.origin.set(centreOfMass.x, centreOfMass.y, centreOfMass.z);
    rigidBody.setCenterOfMassTransform(center);

    rigidBody.setDamping(SETTINGS.chair_damping_linear,
        SETTINGS.chair_damping_ang);
    rigidBody.setDeactivationTime(0.8f);
    rigidBody.setSleepingThresholds(1.6f, 2.5f);
    rigidBody.setFriction(SETTINGS.chair_friction);

    // rigidBody.setCcdMotionThreshold(1f);
    GLOBAL.jBullet.myWorld.addRigidBody(rigidBody);
    GLOBAL.jBullet.rigidBodies.add(rigidBody);

    GImpactCollisionAlgorithm.registerAlgorithm(GLOBAL.jBullet.dispatcher);

    // just to load everything in
    GLOBAL.jBullet.update();
    rigidBody.getWorldTransform(this.currentWorldTransform);

    this.addCentrePlaneConstraint();
  }
 
 
 

  /**
   * Add the current design to the 2D shape packing engine.
   */
  void addToShapePack() {

    this.buildRender();
   
    GLOBAL.shapePack.empty();
    // GLOBAL.shapePack.pdf_pixels_per_mm = SETTINGS.pixels_per_mm;
    GLOBAL.shapePack.content_scale = SETTINGS.scale;
    //GLOBAL.shapePack.ZOOM = ((float) GLOBAL.applet.height) / 390f;
    for (int i = 0; i < this.getSlicePlanesY().size(); i++) {
      SlicePlane slicePlane = this.getSlicePlanesY().get(i);

      if (!slicePlane.guide) {
        spShape shape = slicePlane.getspShape();
        shape.shapePack = GLOBAL.shapePack; //hacky

        shape.build();
        shape.setLabel(((char) ('A' + i)) + "");
        shape.linkedObject = slicePlane;
        GLOBAL.shapePack.add(shape);
      }
    }

    for (int i = 0; i < this.slicePlanesSlatSlices.size(); i++) {
      SlicePlane slicePlane = this.slicePlanesSlatSlices.get(i);
      if (!slicePlane.guide) {
        spShape shape = slicePlane.getspShape();
        shape.shapePack = GLOBAL.shapePack; //hacky

        shape.build();
        shape.setLabel("" + (i + 1));
        shape.linkedObject = slicePlane;
        GLOBAL.shapePack.add(shape);
      }
    }
    GLOBAL.shapePack.scaleAll(SETTINGS.scale);
    GLOBAL.shapePack.build();
    this.buildPreview();

    /*
     *
     * spShape coverShape = new spShape(); ArrayList l = new ArrayList();
     * l.add(new Vec2D(0, 0)); l.add(new Vec2D(this.coverWidth, 0));
     * l.add(new Vec2D(this.coverWidth, this.coverLength)); l.add(new
     * Vec2D(0, this.coverLength)); coverShape.addOutline(l);
     * GLOBAL.shapePack.add(coverShape);
     */
  }
 
 
 
  /**
   * Add the current design to the 2D shape packing engine.
   */
  public void addToPreviewShapePack(spShapePack shapePack) {

    LOGGER.debug("addToPreviewShapePack");
    for (int i = 0; i < this.getSlicePlanesY().size(); i++) {
      SlicePlane slicePlane = this.getSlicePlanesY().get(i);

      if (!slicePlane.guide) {
        spShape shape = slicePlane.getspShape();
        shape.shapePack = shapePack; //hacky
        shape.build();
        shape.linkedObject = slicePlane;
        shapePack.add(shape);
      }
    }

    for (int i = 0; i < this.slicePlanesSlatSlices.size(); i++) {
      SlicePlane slicePlane = this.slicePlanesSlatSlices.get(i);
      if (!slicePlane.guide) {
        spShape shape = slicePlane.getspShape();
        shape.shapePack = shapePack; //hacky

        shape.build();
        shape.linkedObject = slicePlane;
        shapePack.add(shape);
      }
    }

  }
 
 
  /**
   * Apply the current translation matrix from the physics mesh in the physics engine to the display context.
   * @param g
   */
  public void applyTranslationMatrix(PGraphics g) {

    if (this.built == true) {

      if (rigidBody == null)
        return;

      float scaleBy = 1f / GLOBAL.jBullet.getScale();
      Transform myTransform = new Transform();
      myTransform = rigidBody.getMotionState().getWorldTransform(
          myTransform);

      Vector3f center = new Vector3f();
      rigidBody.getCenterOfMassPosition(center);

      g.translate(myTransform.origin.x * scaleBy,
          (myTransform.origin.y * scaleBy),
          (myTransform.origin.z * scaleBy));
      // g.rotateX((float) Math.PI);
      g.applyMatrix(myTransform.basis.m00, myTransform.basis.m01,
          myTransform.basis.m02, 0, myTransform.basis.m10,
          myTransform.basis.m11, myTransform.basis.m12, 0,
          myTransform.basis.m20, myTransform.basis.m21,
          myTransform.basis.m22, 0, 0, 0, 0, 1);
      g.rotateX((float) Math.PI);
      g.translate(-this.centreOfMass.x * scaleBy,
          (-this.centreOfMass.y * scaleBy), -this.centreOfMass.z
              * scaleBy);

    }

  }

 
  /**
   * Build all parts of the chair at preview quality for editing
   */
  public void buildPreview() {
    GLOBAL.SketchGlobals.BEZIER_DETAIL_CALCULATIONS = SETTINGS_SKETCH.BEZIER_DETAIL_CALCULATIONS_PREVIEW;
    GLOBAL.SketchGlobals.BEZIER_DETAIL_OFFSET = SETTINGS_SKETCH.BEZIER_DETAIL_OFFSET_PREVIEW;
    build();
  }
 
 
  /**
   * Build all parts of the chair at render quality for exporting or saving.
   */
  public void buildRender() {
    GLOBAL.SketchGlobals.BEZIER_DETAIL_CALCULATIONS = SETTINGS_SKETCH.BEZIER_DETAIL_CALCULATIONS_RENDER;
    GLOBAL.SketchGlobals.BEZIER_DETAIL_OFFSET = SETTINGS_SKETCH.BEZIER_DETAIL_OFFSET_RENDER;
  build();
  }
 
 
  /**
   * Rebuild all parametric parts of the chairs.
   */
  public void build() {
   
    LOGGER.debug("build");
   
    setPlaneWidth(SETTINGS.materialThickness);

    this.getSlicePlanesY().build();
    SlicePlane lastPlane = null;

   
    selectedPlanes.empty();
    for (int i = 0; i < this.getSlicePlanesY().getList().size(); i++) {
      SlicePlane plane = this.getSlicePlanesY().getList().get(i);
      if (plane.isSelected()){
        this.selectedPlanes.add(plane);
      }
    }

    this.builtOuline = true;
    this.updateCollisionMesh = true;
    this.personSeated = false;
    this.buildLen();
    this.setPlaneWidth(this.materialWidth);
    this.built = true;

   
    //rebuild the preview pattern
    slicePlanesSlatSlices.setEditable(false);
    if(GLOBAL.previewWidget != null && GLOBAL.previewWidget.visible)
      GLOBAL.previewWidget.rebuildPatternPreview();
  }

  /**
   * Add a mesh to the physics engine to simulate a cover.
   *
   * @param triangleArray
   * @param offset
   */
  void buildCoverMesh(TriangleIndexVertexArray triangleArray, Vec3D offset) {
    // this.feltCover = new FeltCover();

    /*
     * return new TriangleIndexVertexArray(TrianglesNum, this
     * .getIndexBuffer(gIndices), 4 * 3, VerticesNum / 3, this
     * .getVertexBuffer(gVertices), 4 * 3);
     */

    SlicePlane lastPlane = null;

    for (int i = 0; i < this.getSlicePlanesY().getList().size(); i++) {
      SlicePlane plane = this.getSlicePlanesY().getList().get(i);
      plane.buildCoverPath();
      if (lastPlane != null) {
        IndexedMesh vertexArray = lastPlane.loftCollisonMeshBetween(
            lastPlane.coverPath, plane, plane.coverPath, 0.2f,
            offset);
        if (vertexArray != null) {
          triangleArray.addIndexedMesh(vertexArray);
          // System.out.println("got mesh");

        }
      }

      lastPlane = plane;
    }
  }

 
 
  /**
   * Generate slices on design.
   */
  public void buildLen() {
    if (creossSelectionTempOver == null
        && this.getSlicePlanesY().size() < 1)
      return;
   
   
    LOGGER.debug("buildLen");

   

    //clear the cross planes of this object
    this.slicePlanesSlatSlices.destroyPlanes();
    this.slicePlanesSlatSlices.empty();

    //clear all slots
    for (int j = 0; j < this.getSlicePlanesY().size(); j++) {
      SlicePlane tempPlane = this.getSlicePlanesY().get(j);
      tempPlane.getSketch().getSlots().empty();
    }

    //what does this do?
    for (int s = 0; s < this.crossSliceSelections.l.size(); s++) {
      CrossSliceSelection crossSliceSelection;

      crossSliceSelection = (CrossSliceSelection) this.crossSliceSelections.l
          .get(s);

      //destroy selection
      if (crossSliceSelection.path != null
          && crossSliceSelection.path.isDestroying() == true)
        crossSliceSelection.destroy(null);

      Object sketch = crossSliceSelection.path;
      SketchShape guideSpline = (SketchShape) sketch;

      //if (guideSpline == null || guideSpline.size() < 2)
      //  return;

      if (crossSliceSelection != null
          && crossSliceSelection.type == CrossSliceSelection.SLICES
          || crossSliceSelection.type == CrossSliceSelection.LEG
          || crossSliceSelection.type == CrossSliceSelection.SINGLE_SLICE)
        GeometryOperations.generateSlices(this.slicePlanesY,
            this.slicePlanesSlatSlices, crossSliceSelection,
            guideSpline);

      if (crossSliceSelection != null
          && (crossSliceSelection.type == CrossSliceSelection.PLANE_ON_EDGE || crossSliceSelection.type == CrossSliceSelection.PLANE))
        GeometryOperations.generateSlat(this.slicePlanesY,
            this.slicePlanesSlatSlices, crossSliceSelection,
            guideSpline, this);

      if (crossSliceSelection != null
          && crossSliceSelection.type == CrossSliceSelection.SLATSLICES)
        GeometryOperations.generateSlatSlices(this.slicePlanesY,
            this.slicePlanesSlatSlices, crossSliceSelection,
            guideSpline, this);

    }

    //this.slicePlanesSlatSlices.checkForCollisions();
    if (SETTINGS.useSliceCollisionDetection)
      this.slicePlanesY.checkForCollisions();
   
   
    selectedPlanes.empty();
   

    for (int i = 0; i < slicePlanesSlatSlices.size(); i++) {
      SlicePlane plane = slicePlanesSlatSlices.get(i);
      if(plane.getCrossSliceSelection() != null && plane.getCrossSliceSelection().selected){
        selectedPlanes.add(plane);
      }else{
        plane.unselect();
      }
    }
   
   
    for (int i = 0; i < slicePlanesY.size(); i++) {
      SlicePlane plane = slicePlanesY.get(i);
      if(plane.isSelected()){
        selectedPlanes.add(plane);
      }else{
        plane.unselect();
      }
    }

    //this.slicePlanesSlatSlices.unselectAll();

  }

 
  /**
   * Copy initial Sketch and automatically generate additional layers from this.
   */
  public void buildWidth() {

    LOGGER.debug("buildWidth");

   
    this.getSlicePlanesY().empty();
    this.setWidth(SETTINGS.chair_width);
    int numSlices = (int) SETTINGS.slat_num;// (int)
    float spacing = this.getWidth() / (numSlices);
   
   

    for (float i = (-this.getWidth() / 2); i < (this.getWidth() / 2); i += spacing) {
      SlicePlane slicePlane = new SlicePlane(new Plane(
          new Vec3D(0, 0, i), new Vec3D(0, 0, -1)));
      this.getSlicePlanesY().add(slicePlane);
    }

    //this.updateCollisionShape();
    this.selectedPlanes.empty();
   
    this.getSlicePlanesY().selectAll();
    this.selectedPlanes.add(getSlicePlanesY());

  }

  /**
   * Change the width of the current design by a delta ammount.
   * @param deltaMouseY
   */
  public void changeWidth(float deltaMouseY) {
    // System.out.println(deltaMouseY);
    if (this.getSlicePlanesY().getList().size() > 0) {
      this.setWidth(this.getWidth() + deltaMouseY);
      this.rebuildWidth();
    }
  }


/**
* Return a copy of the design.
* @return
*/
  public SketchChair copy() {
    SketchChair newSketchChair = new SketchChair();
    newSketchChair.slatSpacingX = this.slatSpacingX;
    newSketchChair.setSlicePlanesY(this.getSlicePlanesY().copy());
    newSketchChair.crossSliceSelections = this.crossSliceSelections.copy(
        newSketchChair.getSlicePlanesY(), newSketchChair);
    return newSketchChair;

  }

  /*
   * Return a count of the number of the selected nodes in the design.
   */
  public int countSelectedNodes() {
    return this.getSlicePlanesY().countSelectedNodes();

  }

  /**
   * Delete selected layers.
   */
  public void deleteSelectedLayers() {
    this.selectedPlanes.destroyPlanes();
    this.selectedPlanes.update();
    this.slicePlanesSlatSlices.update();
    this.getSlicePlanesY().update();
    this.selectedPlanes.unselectAll();
  }

 
  /**
   * Delete selected Shapes.
   */
  public void deleteSelectedShapes() {
    this.selectedPlanes.deleteSelectedShapes();
  }

  /*
   * private TriangleIndexVertexArray getVertexArray() {
   *
   * float colResolution = 0.1f;
   *
   *
   * int cSizeFirst =
   * this.slicePlanesY.getFirst().sketchSpline.getCombinedSize(); int
   * cSizeNext = this.slicePlanesY.getLast().sketchSpline.getCombinedSize();
   *
   * SketchOutline skOtFirst =
   * this.slicePlanesY.getFirst().sketchShapes.sketchOutlines
   * .getOutterOutline(); SketchOutline skOtNext =
   * this.slicePlanesY.getLast().
   * sketchShapes.sketchOutlines.getOutterOutline();
   *
   *
   *
   *
   *
   * Vec2D centre = this.sketchSpline.getCentreOfMass();
   *
   * int VerticesNum = ((cSizeFirst +cSizeNext)) *3; int TrianglesNum =
   * (cSizeFirst +cSizeNext) * 2 ;
   *
   *
   * int IndicesNum = (TrianglesNum) * 4; float[] gVertices = new
   * float[VerticesNum]; int[] gIndices = new int[IndicesNum];
   *
   * int verIndex = 0; int IndicesIndex = 0;
   *
   * //add all verticies from end cap 1 for (int i = 0; i < 1;
   * i+=colResolution) { Vec2D v1l = (Vec2D) skOtFirst.getDist(i);
   * gVertices[verIndex] = v1l.x - centre.x; verIndex++; gVertices[verIndex] =
   * -v1l.y + centre.y; verIndex++; gVertices[verIndex] =
   * (this.slicePlanesY.getFirst().offset.z); verIndex++; }
   *
   *
   * for (int i = 0; i < 1; i+=colResolution) { Vec2D v1r = (Vec2D)
   * skOtNext.getDist(i); gVertices[verIndex] = v1r.x - centre.x; verIndex++;
   * gVertices[verIndex] = -v1r.y + centre.y; verIndex++; gVertices[verIndex]
   * = -(this.width / 2); verIndex++; }
   *
   * for (int i = 0; i < cSizeFirst - 1; i++) {
   *
   * // triangle 1 gIndices[IndicesIndex] = i + 1; IndicesIndex++;
   * gIndices[IndicesIndex] = i + 0; IndicesIndex++; gIndices[IndicesIndex] =
   * i + cSizeFirst; IndicesIndex++;
   *
   * // triangle 2 gIndices[IndicesIndex] = i + 0 + cSizeNext; IndicesIndex++;
   * gIndices[IndicesIndex] = i + 1; IndicesIndex++; gIndices[IndicesIndex] =
   * i + 1 + cSizeNext; IndicesIndex++;
   *
   * }
   *
   * // triangle 1 gIndices[IndicesIndex] = 0; IndicesIndex++;
   * gIndices[IndicesIndex] = cSizeFirst; IndicesIndex++;
   * gIndices[IndicesIndex] = cSizeFirst - 1; IndicesIndex++;
   *
   * gIndices[IndicesIndex] = cSizeFirst; IndicesIndex++;
   * gIndices[IndicesIndex] = cSizeFirst * 2 - 1; IndicesIndex++;
   * gIndices[IndicesIndex] = cSizeFirst- 1; IndicesIndex++;
   *
   * // side triangle1
   *
   * for (int i = 0; i < cSizeNext; i++) {
   *
   * // triangle 1 gIndices[IndicesIndex] = i + 1; IndicesIndex++;
   * gIndices[IndicesIndex] = i + 0; IndicesIndex++; gIndices[IndicesIndex] =
   * (sketchFirst.l.size() - i - 1) + sketchNext.l.size(); IndicesIndex++;
   *
   * // triangle 2 gIndices[IndicesIndex] = (sketchFirst.l.size() - i) +
   * sketchNext.l.size(); IndicesIndex++; gIndices[IndicesIndex] = i + 0;
   * IndicesIndex++; gIndices[IndicesIndex] = (sketchFirst.l.size() - i - 1) +
   * sketchNext.l.size(); IndicesIndex++;
   *
   * }
   *
   * for (int i = 0; i < sketchFirst.l.size(); i++) {
   *
   * // triangle 1 gIndices[IndicesIndex] = i + 1 + (cSizeNext - 1);
   * IndicesIndex++; gIndices[IndicesIndex] = i + 0 + (cSizeNext - 1);
   * IndicesIndex++; gIndices[IndicesIndex] = (sketchFirst.l.size() - i - 1) +
   * sketchFirst.l.size() + (cSizeNext - 1); IndicesIndex++;
   *
   * // triangle 2 gIndices[IndicesIndex] = (sketchFirst.l.size() - i) +
   * sketchFirst.l.size() + (cSizeNext - 1); IndicesIndex++;
   * gIndices[IndicesIndex] = i + 0 + cSizeNext; IndicesIndex++;
   * gIndices[IndicesIndex] = (sketchFirst.l.size() - i - 1) +
   * sketchFirst.l.size() + (cSizeNext - 1); IndicesIndex++;
   *
   * }
   *
   * // System.out.println(this.getVertexBuffer(gVertices).asDoubleBuffer());
   * return new TriangleIndexVertexArray(TrianglesNum, this
   * .getIndexBuffer(gIndices), 4 * 3, VerticesNum / 3, this
   * .getVertexBuffer(gVertices), 4 * 3);
   *
   * }
   */
 
  /**
   * Detroy the design.
   */
  void destroy() {

    this.destroy = true;

    if (this.chairCentreConstraint != null)
      GLOBAL.jBullet.myWorld.removeConstraint(this.chairCentreConstraint);

    if (this.rigidBody != null)
      GLOBAL.jBullet.myWorld.removeRigidBody(this.rigidBody);

  }

  /**
   * Move the design by a delta amount inside the physics engine.
   * @param offset
   */
  public void drag(Vec3D offset) {
    Vector3f offset3f = new Vector3f(offset.x, offset.y, offset.z);
    offset3f.scale(GLOBAL.jBullet.scale);
    this.rigidBody.translate(offset3f);
    GLOBAL.jBullet.update();
    this.setCurrentPositionAsStartTransform();
    //this.startWorldTransform.origin.set(offset3f);
  }

  /**
   * Flip the design around the Z Axis.
   */
  public void flipDesign() {
    Vec3D centre = this.getCentreOfMass();
    this.getSlicePlanesY().flipHorizontal(centre);
    this.buildLen();
  }

  /**
   * Get the total area of the 2D cut profiles of the design.
   * @return
   */
  float getArea() {
    float area = 0;
    area += this.slicePlanesSlatSlices.getArea();
    area += this.getSlicePlanesY().getArea();
    return area;

  }

  /**
   * Return the center of mass for the current design.
   * @return
   */
  private Vec3D getCentreOfMass() {
    Vec3D centre = new Vec3D();
    int planeCount = 0;
    for (int i = 0; i < this.getSlicePlanesY().size(); i++) {
      SlicePlane slicePlane = this.getSlicePlanesY().get(i);
      if (slicePlane.getCentreOfMass() != null) {
        centre.addSelf(slicePlane.getCentreOfMass());
        planeCount++;
      }
    }

    centre.x /= planeCount;
    centre.y /= planeCount;
    centre.z /= planeCount;

    //cache point
    //this.centreOfMass = centre;

    return centre;

  }

  /**
   * return the mass of the design based on it's density and surface area.
   * @return
   */
  float getMass() {
    return this.getArea() * this.density;
  }

  /**
   * Return the closest SketchPoint to a point.
   * @param x
   * @param y
   * @return
   */
  public SketchPoint getOverSelectPoint(float x, float y) {
    return this.selectedPlanes.getOverSelectPoint(x, y);
  }

  public SketchShapes getOverShapes(float x, float y) {
    return this.selectedPlanes.getOverShapes(x, y);
  }

  public SlicePlane getPlanePickBuffer(int col) {

    SlicePlane plane = this.slicePlanesSlatSlices.getPlanePickBuffer(col);
    if (plane != null)
      return plane;
    else
      return this.getSlicePlanesY().getPlanePickBuffer(col);
  }

  public PGraphics getScreenshot(float w, float h, float rotateX,
      float rotateY) {
    GLOBAL.screenshot = true;
    float border = 250;
    float rememberX = GLOBAL.rotateModelsX;
    float rememberY = GLOBAL.rotateModelsY;

    GLOBAL.rotateModelsX = rotateX;
    GLOBAL.rotateModelsY = rotateY;

    float minX = this.getSlicePlanesY().getMinXWorldSpace(
        this.currentWorldTransform);
    float minY = this.getSlicePlanesY().getMinYWorldSpace(
        this.currentWorldTransform);
    float maxX = this.getSlicePlanesY().getMaxXWorldSpace(
        this.currentWorldTransform);
    float maxY = this.getSlicePlanesY().getMaxYWorldSpace(
        this.currentWorldTransform);

    float minX2 = this.getSlicePlanesY().getMinX();
    float minY2 = this.getSlicePlanesY().getMinY();
    float maxX2 = this.getSlicePlanesY().getMaxX();
    float maxY2 = this.getSlicePlanesY().getMaxY();

    float width = Math.abs(maxX - minX) + (border * 2);
    float height = Math.abs(maxY - minY) + +(border * 2);

    float width2 = Math.abs(maxX2 - minX2) + (border * 2);
    float height2 = Math.abs(maxY2 - minY2) + (border * 2);

    // width += (width );
    // height += (height);

    // System.out.println("out: X world " + minX + ": "+maxX + ":"+width);
    // System.out.println("out: X model " + minX2 + ": "+maxX2 +
    // ":"+width2);
    // System.out.println("out: Y world " + minY + ": "+maxY + ":"+height);
    // System.out.println("out: Y model " + minY2 + ": "+maxY2 +
    // ":"+height2);

    // System.out.println(currentWorldTransform.origin.x);
    PGraphics saveImg = GLOBAL.applet.createGraphics((int) width,
        (int) height, PConstants.P3D);
    saveImg.beginDraw();
    saveImg.ortho(-(width / 2), (width / 2), -(height / 2), (height / 2),
        -1000, 10000);
    //saveImg.hint(PApplet.DISABLE_STROKE_PERSPECTIVE);

    saveImg.ambientLight(200, 200, 200);
    saveImg.directionalLight(69, 69, 69, 0, 0, -1);
    saveImg.lightFalloff(1, 0, 0);

    saveImg.smooth(8);

    saveImg.background(255);

    saveImg.pushMatrix();
    // this.applyTranslationMatrix(g);

    saveImg.translate(-minX + border, -minY + border);
    saveImg.translate(width / 2, height / 2, -(this.getWidth() / 4));
    saveImg.rotateX(rotateX);
    saveImg.rotateY(rotateY);
    saveImg.translate(-width / 2, -height / 2, (this.getWidth() / 4));
    this.render(saveImg);
    // this.renderSilhouette(saveImg);

    saveImg.popMatrix();
    saveImg.endDraw();
    GLOBAL.screenshot = false;

    GLOBAL.rotateModelsY = rememberY;
    GLOBAL.rotateModelsX = rememberX;
    return saveImg;

  }

  public SketchShape getShapePickBuffer(int col) {

    SketchShape shape = this.selectedPlanes.getShapePickBuffer(col);
    if (shape != null)
      return shape;

    shape = this.slicePlanesSlatSlices.getShapePickBuffer(col);
    if (shape != null)
      return shape;

    return this.getSlicePlanesY().getShapePickBuffer(col);

  }

  /**
   * @return the slicePlanesY
   */
  public SlicePlanes getSlicePlanesY() {
    return slicePlanesY;
  }

  //translates into model space
  public Vec3D getTranslated(Vec3D pIn) {
    Vec3D p = pIn.copy();
    if (this.built == true) {

      if (rigidBody == null) {
        LOGGER.debug("no rigid body in get Translated");
        return p;

      }

      float scaleBy = 1f / GLOBAL.jBullet.getScale();
      Transform myTransform = new Transform();
      myTransform = rigidBody.getMotionState().getWorldTransform(
          myTransform);

      Vector3f center = new Vector3f();
      rigidBody.getCenterOfMassPosition(center);
      LOGGER.debug("getCenterOfMassPosition" + center);
      /*
      p.addSelf(new Vec3D(center.x * scaleBy,
              (center.y * scaleBy), center.z
                  * scaleBy));
        */
      //  p.addSelf(new Vec3D(myTransform.origin.x * scaleBy,
      //      (myTransform.origin.y * scaleBy),
      //    (myTransform.origin.z * scaleBy)));
      // g.rotateX((float) Math.PI);
      Matrix4x4 m = new Matrix4x4(myTransform.basis.m00,
          myTransform.basis.m01, myTransform.basis.m02, 0,
          myTransform.basis.m10, myTransform.basis.m11,
          myTransform.basis.m12, 0, myTransform.basis.m20,
          myTransform.basis.m21, myTransform.basis.m22, 0, 0, 0, 0, 1);

      p = m.applyTo(p);

      /*
      p = p.rotateX((float) Math.PI);
      p.subSelf(new Vec3D(center.x * scaleBy,
          (center.y * scaleBy), center.z
              * scaleBy));
      */
    } else {
      LOGGER.debug("not built in get Translated");

    }

    return p;

  }

  public Vec2D getVec2DpickBuffer(int col) {

    Vec2D vec = this.selectedPlanes.getVec2DpickBuffer(col);
    if (vec != null)
      return vec;

    vec = this.slicePlanesSlatSlices.getVec2DpickBuffer(col);
    if (vec != null)
      return vec;

    return this.getSlicePlanesY().getVec2DpickBuffer(col);
  }

  private TriangleIndexVertexArray getVertexArray(float offsetX,
      float offsetY, float offsetZ) {

    TriangleIndexVertexArray triangleArray = new TriangleIndexVertexArray();

    for (int i = 0; i < this.getSlicePlanesY().getList().size(); i++) {
      SlicePlane slicePlane = this.getSlicePlanesY().getList().get(i);
      IndexedMesh vertexArray = slicePlane.getIndexedMesh(offsetX,
          offsetY, offsetZ);
      if (vertexArray != null)
        triangleArray.addIndexedMesh(vertexArray);
      // slicePlane.getIndexedMesh();
    }

    for (int i = 0; i < this.slicePlanesSlatSlices.getList().size(); i++) {
      SlicePlane slicePlane = this.slicePlanesSlatSlices.getList().get(i);
      IndexedMesh vertexArray = slicePlane.getIndexedMesh(offsetX,
          offsetY, offsetZ);
      if (vertexArray != null) {
        triangleArray.addIndexedMesh(vertexArray);
      }
      // slicePlane.getIndexedMesh();
    }

    if (this.getSlicePlanesY().getList().size() > 0)
      return triangleArray;
    else
      return null;

    /*
     * return new TriangleIndexVertexArray(TrianglesNum, this
     * .getIndexBuffer(gIndices), 4 * 3, VerticesNum / 3, this
     * .getVertexBuffer(gVertices), 4 * 3);
     */

  }

  /**
   * @return the width
   */
  public float getWidth() {
    return width;
  }

  public void hybernate() {

    this.hybernateCopy();
    this.destroy();
  }

  public void hybernateCopy() {
    float border = 15;
    GLOBAL.uiTools.hybernateChairToFileAuto(null);
    Environment chair = new Environment(
        GLOBAL.LAST_SAVED_LOCATION + ".png", GLOBAL.applet);
    float minX = this.getSlicePlanesY().getMinXWorldSpace(
        this.currentWorldTransform);
    float minY = this.getSlicePlanesY().getMinYWorldSpace(
        this.currentWorldTransform);
    float maxX = this.getSlicePlanesY().getMaxXWorldSpace(
        this.currentWorldTransform);
    float maxY = this.getSlicePlanesY().getMaxYWorldSpace(
        this.currentWorldTransform);

    float width = Math.abs(maxX - minX);
    float height = Math.abs(maxY - minY);
    // System.out.println(GLOBAL.LAST_SAVED_LOCATION);
    // System.out.println("DIFF" + (this.startWorldTransform.origin.y -
    // this.currentWorldTransform.origin.y));
    chair.pos.x = (minX) - imgBorder;// +
                      // ((this.startWorldTransform.origin.x
                      // -
                      // this.currentWorldTransform.origin.x)/GLOBAL.jBullet.scale);
    chair.pos.y = (minY) - imgBorder;// -
                      // ((this.startWorldTransform.origin.y
                      // -
                      // this.currentWorldTransform.origin.y)/GLOBAL.jBullet.scale);

    chair.linkedChair = GLOBAL.LAST_SAVED_LOCATION;
    GLOBAL.environments.l.add(chair);
  }

  /**
   * @return the reScaling
   */
  public boolean isReScaling() {
    return reScaling;
  }

  /**
   * @return the updateCollisionMesh
   */
  public boolean isUpdateCollisionMesh() {
    return updateCollisionMesh;
  }

  void justLoaded() {
    // this.trimesh = null;
    this.selectedPlanes.empty();
    this.selectedPlanes.add(this.getSlicePlanesY());

    // this.slicePlanesY.buildCurrentSketch();
    //
    // this.selectedPlanes.buildCurrentSketch();
    // this.updateCollisionMesh = true;

    this.setUpdateCollisionMesh(true);
    this.personSeated = false;

    // this.build();
    // addRigidModel();

    this.update();
  }

  boolean lastSketchOverlaps() {
    return this.selectedPlanes.lastSketchOverlaps();

  }

  // renders a Silhoette to a file, this is
  // without the chairs translation matrix so the silohouette will need to be
  // translated later

  private void makeNewChairFromLastSketch() {

    SketchShape lastShape = this.selectedPlanes.getFirst().getLastSketch();
    SketchChair newChair = new SketchChair(lastShape);

    this.selectedPlanes.removeLastSketch();

    if (SETTINGS.EXHIBITION_MODE) {
      // if (this.rigidBody != null)
      // GLOBAL.jBullet.myWorld.removeRigidBody(this.rigidBody);

      // this.selectedPlanes.buildCurrentSketch();

      // addRigidModel();

      // return;
    }

    this.hybernate();

    Vec3D thisCentre = this.getCentreOfMass();

    Transform worldTransform = new Transform();
    rigidBody.getMotionState().getWorldTransform(worldTransform);
    // worldTransform.origin.setX(
    // this.startWorldTransform.origin.x-worldTransform.origin.x );

    // worldTransform.origin.y - this.startWorldTransform.origin.y,
    // worldTransform.origin.z - this.startWorldTransform.origin.z

    // ));
    Vec3D thatCentre = newChair.getCentreOfMass();
    // System.out.println("ORIGIN" + worldTransform.origin.y+ " : " +
    // (thisCentre.y) + ": " + thatCentre.y);

    worldTransform.origin.x = (worldTransform.origin.x + (thatCentre.x - thisCentre.x));
    worldTransform.origin.y = (worldTransform.origin.y + ((thatCentre.y - thisCentre.y)));
    worldTransform.origin.z = (worldTransform.origin.z + (thatCentre.z - thisCentre.z));
    //
    //
    //
    // = new Vector3f(,
    // thisCentre.y-thatCentre.y,
    // thisCentre.z-thatCentre.z);
    newChair.rigidBody.setWorldTransform(worldTransform);
    // newChair.drag(new
    // Vec3D((this.startWorldTransform.origin.x-worldTransform.origin.x)
    // ,(worldTransform.origin.y-this.startWorldTransform.origin.y),0));

    GLOBAL.sketchChairs.add(newChair);

  }

  public void mouseDragged(float mouseX, float mouseY) {
    //if(GLOBAL.person.mouseOver(mouseX, mouseY))
    //  return;

    if (GLOBAL.person.clickedOnPerson)
      return;

    if (GLOBAL.uiTools.mouseButton != UITools.MOUSE_LEFT)
      return;

    this.selectedPlanes.mouseDragged(mouseX, mouseY);

    if (GLOBAL.uiTools.getCurrentTool() == UITools.SCALE_TOOL
        && this.isReScaling()) {
      float scaleVal = (GLOBAL.uiTools.pmouseY - GLOBAL.uiTools.mouseY);
      scaleVal *= .01;
      this.scale(scaleVal);
    }

    if (GLOBAL.uiTools.getCurrentTool() == UITools.MOVE_2D_TOOL
        || GLOBAL.uiTools.SketchTools.getCurrentTool() == SketchTools.SELECT_TOOL
        && this.dragging) {

      float deltaMx = (GLOBAL.uiTools.mouseX - GLOBAL.uiTools.pmouseX)
          * (float)(1 / GLOBAL.getZOOM());
      float deltaMy = (float) ((GLOBAL.uiTools.mouseY - GLOBAL.uiTools.pmouseY)
          * (float)(1 / GLOBAL.getZOOM()));

      float maxMouse = SETTINGS.mouseMoveClamp;

      if (deltaMx > maxMouse || deltaMx < -maxMouse || deltaMy > maxMouse
          || deltaMy < -maxMouse)
        return;

      this.drag(new Vec3D(deltaMx, deltaMy, 0));
    }
  }

  boolean mouseOver(float mouseX, float mouseY) {

    RigidBody selectedBod = GLOBAL.jBullet.getOver(mouseX, mouseY);

    if (selectedBod != null && this.rigidBody != null
        && this.rigidBody.equals(selectedBod)) {
      return true;
    }
    return false;
  }

  public void mousePressed(float mouseX, float mouseY) {

    if (GLOBAL.person.mouseOver(GLOBAL.uiTools.mouseXworld,
        GLOBAL.uiTools.mouseYworld))
      return;

   
    if (GLOBAL.uiTools.mouseButton == UITools.MOUSE_MIDDLE)
      return;

   
    selectedPlanes.mousePressed(mouseX, mouseY);

   
    if (GLOBAL.uiTools.getCurrentTool() == UITools.SCALE_TOOL) {

      if (this.mouseOver(mouseX, mouseY)) {
        this.setReScaling(true);
      }
    }

   
   
    if (GLOBAL.uiTools.getCurrentTool() == UITools.MOVE_2D_TOOL
        || GLOBAL.uiTools.SketchTools.getCurrentTool() == SketchTools.SELECT_TOOL
        && this.rigidBody != null) {

      if (this.mouseOver(GLOBAL.uiTools.mouseXworld,
          GLOBAL.uiTools.mouseYworld)
          && !overSelectPoint(GLOBAL.uiTools.mouseX,
              GLOBAL.uiTools.mouseY)
          && !GLOBAL.jBullet.physics_on) {
        LOGGER.debug("DRAG");
        this.dragging = true;

      }

    }


  }

  public void mouseReleased(float mouseX, float mouseY) {

   
   
   
    if (GLOBAL.person.clickedOnPerson)
      return;

    if (GLOBAL.uiTools.mouseButton == UITools.MOUSE_MIDDLE)
      return;
   
    selectedPlanes.mouseReleased(mouseX, mouseY);

    if (this.isReScaling()) {
      // this.built = false;
      //  this.updateCollisionShape();

    }
   
    this.crossSliceSelections.mouseReleased();
   
   
    //Sketch Slices finished?
    if(creossSelectionTempOver != null){
     
     
      creossSelectionTempOver.editing = true;
      creossSelectionTempOver.mouseReleased();
      //finished editing
      if(!creossSelectionTempOver.editing){

        if(creossSelectionTempOver.tempSlice){

        this.crossSliceSelections.add(creossSelectionTempOver);
        creossSelectionTempOver.tempSlice = false;
        }
       
        creossSelectionTempOver = null;
        GLOBAL.uiTools.setCurrentTool(UITools.SELECT_TOOL);
        this.buildLen();

      }
    }
   

   
    if(this.selectedPlanes.count() == 0)
      return;
   
   
    this.setReScaling(false);
    this.dragging = false;

    this.selectedPlanes.buildCurrentSketch();
    this.setUpdateCollisionMesh(true);

   
   
    //add initial
    if (!this.initailSliceAdded && getMass() > 0) {
      LOGGER.debug("initailSliceAdded");

      SlicePlane extrudeSlice = this.getSlicePlanesY().getFirst();
      Object spline = extrudeSlice.getSketch().getLast();

      if (spline != null && spline instanceof SketchPath
          && !((SketchPath) spline).getClosed())
        return;

      this.initailSliceAdded = true;

      if (spline != null && spline instanceof SketchSpline) {
       

        SketchSpline sketchSpline = (SketchSpline) spline;
        CrossSliceSelection sliceSelection = new CrossSliceSelection(
            sketchSpline.getCentrePath(), extrudeSlice, 0, 1,
            SETTINGS.DEFAULT_SLAT_SPACING, this);
        sliceSelection.cropToCurrentShape = true;
        this.crossSliceSelections.add(sliceSelection);
       
       
       
      }

      if (spline instanceof SketchSpline) {

      }

      if (spline != null && spline instanceof SketchPath) {
        SketchPath path = (SketchPath) spline;
        path.setClosed(true);
        this.crossSliceSelections.add(new CrossSliceSelection(path,
            extrudeSlice, this.endCoverPercent,
            this.startCoverPercent, SETTINGS.DEFAULT_SLAT_SPACING,
            this));
        GLOBAL.uiTools.setCurrentTool(UITools.CROSSSLICE_EDIT);
      }
    } else {
      if (GLOBAL.uiTools.SketchTools.getCurrentTool() == SketchTools.LEG_TOOL
          && SETTINGS.addLegSlices) {

        SlicePlane extrudeSlice = this.selectedPlanes.getFirst();
        Object spline = extrudeSlice.getSketch().getLast();
        //CrossSliceSelection lastSliceSelection = this.crossSliceSelections.getLast();

        //build a list of all leg splines
        List legSplines = new ArrayList();
       
        for(int i = 0; i < this.selectedPlanes.size(); i++){
         
          this.selectedPlanes.get(i).getSketch().getLast().setType(SketchSpline.TYPE_LEG);
          legSplines.add(this.selectedPlanes.get(i).getSketch().getLast());
        }
        //SketchShape shape = lastSliceSelection.path;

        //if (!shape.equals(spline)) {
        if (spline instanceof SketchSpline) {
          SketchSpline sketchSpline = (SketchSpline) spline;

          if (sketchSpline.getCentrePath().size() == 2
              && sketchSpline
                  .getCentrePath()
                  .get(0)
                  .distanceTo(
                      sketchSpline.getCentrePath().get(1)) > SETTINGS.MIN_LEG_LEN) {
           
           
            CrossSliceSelection sliceSelection = new CrossSliceSelection(
                sketchSpline.getCentrePath(), extrudeSlice,
                this);
            extrudeSlice.tiedToLeg = true;
            sliceSelection.tieToLeg = true;
            sliceSelection.legSpline = sketchSpline;
            sliceSelection.legSplines = legSplines;
            sliceSelection.type = CrossSliceSelection.LEG;
                sliceSelection.tiedToPlanes.addAll(this.selectedPlanes.getList());
            LOGGER.debug("TIED" + this.selectedPlanes.getList().size());
            sliceSelection.cropToCurrentShape = false;
            this.crossSliceSelections.add(sliceSelection);
          }

        }

      }

    }

    if (this.built) {

      if (this.getSlicePlanesY().count() == 1) {
        this.personSeated = false;
      }

    }

    if (GLOBAL.uiTools.SketchTools.getCurrentTool() != SketchTools.DRAW_PATH_TOOL)
      this.buildPreview();

    if (this.isReScaling()) {
      this.setReScaling(false);
      //  this.updateCollisionShape();
    }
    this.getSlicePlanesY().buildCurrentSketch();

  }

 
  public void mouseDoubleClick(int mouseX, int mouseY) {
    this.getSlicePlanesY().mouseDoubleClick(mouseX,mouseY);   
  }
 
  public boolean overSelectPoint(float mouseX, float mouseY) {
    if (this.selectedPlanes.overSelectPoint(mouseX, mouseY))
      return true;
    else
      return false;
  }

  // / Build all of the cross slats.
  // /
  public void previewSlices() {
    if (creossSelectionTempOver != null) {
           
      CrossSliceSelection crossSliceSelection = creossSelectionTempOver;

      //clear the cross planes of this object
      this.slicePlanesSlatSlices.destroyPlanes();
      this.slicePlanesSlatSlices.empty();

      Object sketch = crossSliceSelection.path;
      SketchShape guideSpline = (SketchShape) sketch;

      if (crossSliceSelection != null
          && crossSliceSelection.type == CrossSliceSelection.SLICES
          || crossSliceSelection.type == CrossSliceSelection.LEG
          || crossSliceSelection.type == CrossSliceSelection.SINGLE_SLICE)
        GeometryOperations.generateSlices(this.slicePlanesY,
            this.slicePlanesSlatSlices, crossSliceSelection,
            guideSpline);

      if (crossSliceSelection != null
          && (crossSliceSelection.type == CrossSliceSelection.PLANE_ON_EDGE || crossSliceSelection.type == CrossSliceSelection.PLANE))
        GeometryOperations.generateSlat(this.slicePlanesY,
            this.slicePlanesSlatSlices, crossSliceSelection,
            guideSpline, this);

      if (crossSliceSelection != null
          && crossSliceSelection.type == CrossSliceSelection.SLATSLICES)
        GeometryOperations.generateSlatSlices(this.slicePlanesY,
            this.slicePlanesSlatSlices, crossSliceSelection,
            guideSpline, this);

    }

  }

  private void readObject(ObjectInputStream in) throws IOException,
      ClassNotFoundException {
    try {
      // our "pseudo-constructor"
      in.defaultReadObject();
    } catch (IOException e) {
      e.printStackTrace();
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    }

    // now we are a "live" object again, so let's run rebuild and start
    currentWorldTransform = new Transform();
    this.buildPreview();

  }

  private void rebuildWidth() {
    float centreZ = 0;// this.slicePlanesY.getCentre().z;
    // System.out.println(centreZ);

    // System.out.println((this.slicePlanesY.l.size() - 1) + "planes");

    float spacing = (float) this.getWidth()
        / ((float) (this.getSlicePlanesY().getList().size()) - 1.5f);
    float offset = -(this.getWidth() / 2.0f);

    // System.out.println("width" + this.width);
    // System.out.println("spacing" + spacing);
    // System.out.println("offset" + offset);
    // System.out.println("num planes" + this.slicePlanesY.l.size());

    for (SlicePlane plane : this.getSlicePlanesY().getList()) {
      plane.getPlane().z = offset;
      offset += spacing;

    }
    //this.updateCollisionShape();
    GLOBAL.jBullet.update();
    // this.update();

    // his.buildLen();
  }

  public void removeRigidModel() {

    if (rigidBody != null)
      GLOBAL.jBullet.myWorld.removeRigidBody(rigidBody);

  }

  public void removeSelectedPlanes() {
    /*
    if (this.selectedPlanes.getList().size() > 0) {
      SlicePlane destroyPlane = this.selectedPlanes.getFirst();
      this.selectedPlanes.empty();
      this.getSlicePlanesY().remove(destroyPlane);
      destroyPlane.destroy = true;
      this.rebuildWidth();
    } else {
      SlicePlane destroyPlane = this.getSlicePlanesY().getLast();
      this.selectedPlanes.empty();
      this.getSlicePlanesY().remove(destroyPlane);
      destroyPlane.destroy = true;
      this.rebuildWidth();

    }
   
    */
    this.selectedPlanes.destroyPlanes();
    this.rebuildWidth();

    //SETTINGS.slat_num--;

  }

 

  /*  Main Render Function
   * This does the normal rendering when editing or previewing the main design
   */
  public void render(PGraphics g) {

    if(this.selectedPlanes.count() > 0){
    this.slicePlanesY.setRenderMode(Sketch.RENDER_3D_EDITING_PLANES);
    this.slicePlanesSlatSlices.setRenderMode(Sketch.RENDER_3D_EDITING_PLANES);
    }else{
    this.slicePlanesY.setRenderMode(Sketch.RENDER_3D_NORMAL);
    this.slicePlanesSlatSlices.setRenderMode(Sketch.RENDER_3D_NORMAL)
    }
   
    if(GLOBAL.rotateModelsX != 0 || GLOBAL.rotateModelsY != 0){
      this.slicePlanesY.setRender3D(true);
      this.slicePlanesSlatSlices.setRender3D(true);
    }else{
      this.slicePlanesY.setRender3D(false);
      this.slicePlanesSlatSlices.setRender3D(false);
    }
    g.pushMatrix();

    this.applyTranslationMatrix(g);
    GLOBAL.renderChairColour = this.chairColour;

    //only render slice planes if not resizing the model
    if (!this.isReScaling()) { 
     
      this.slicePlanesSlatSlices.render(g);
    }
    this.crossSliceSelections.render(g);
    this.getSlicePlanesY().render(g);
   
   
    //g.hint(g.DISABLE_DEPTH_TEST);
    //this.selectedPlanes.render(g);
    //g.hint(g.ENABLE_DEPTH_TEST);

    if (SETTINGS.DEBUG) {
      g.pushMatrix();
      g.translate(this.centreOfMass.x / GLOBAL.jBullet.scale,
          this.centreOfMass.y / GLOBAL.jBullet.scale,
          this.centreOfMass.z / GLOBAL.jBullet.scale);
      g.ellipse(0, 0, 25, 25);
      g.line(-25, 0, 25, 0);
      g.line(0, -25, 0, 25);
      g.popMatrix();
    }

   
   
    //measure tool
    if (this.isReScaling()) {
      float maxY = this.getSlicePlanesY().getMaxY();
      float minY = this.getSlicePlanesY().getMinY();
      float maxX = this.getSlicePlanesY().getMaxX();
      float minX = this.getSlicePlanesY().getMinX();
      MeasureTool.measure(maxX, minX, maxY, minY, g);
    }
   

   
   
   
    if (creossSelectionTempOver != null)
      creossSelectionTempOver.render(g);

   
   
   
    //DEBUG STUFF FOR drawing the collision mesh
    if (SETTINGS.draw_collision_mesh && indexVertexArrays != null) {
      g.pushMatrix();
      float scaleBy = -1 / GLOBAL.jBullet.scale;
      g.translate(-this.centreOfMass.x * scaleBy,
          (-this.centreOfMass.y * scaleBy), -this.centreOfMass.z
              * scaleBy);

      for (int i = 0; i < indexVertexArrays.getNumSubParts(); i++) {

        VertexData vd = indexVertexArrays
            .getLockedReadOnlyVertexIndexBase(i);

        for (int t = 0; t < vd.getIndexCount() / 3; t++) {

          Vector3f[] triangle = new Vector3f[] { new Vector3f(),
              new Vector3f(), new Vector3f() };
          Vector3f scale = new Vector3f(1 / GLOBAL.jBullet.scale, -1
              / GLOBAL.jBullet.scale, 1 / GLOBAL.jBullet.scale);
          vd.getTriangle(t * 3, scale, triangle);
          g.stroke(255, 0, 0);
          g.beginShape();
          g.vertex(triangle[0].x, triangle[0].y, triangle[0].z);
          g.vertex(triangle[1].x, triangle[1].y, triangle[1].z);
          g.vertex(triangle[2].x, triangle[2].y, triangle[2].z);
          g.endShape();
        }
      }
      g.popMatrix();

    }
    g.popMatrix();

  }

  /*  Pick Buffer Rendering
   * This renders a buffer that objects can be picked from
   */
  public void renderPickBuffer(PGraphics pickBuffer) {

    pickBuffer.pushMatrix();
    this.applyTranslationMatrix(pickBuffer);
    this.getSlicePlanesY().renderPickBuffer(pickBuffer);
    this.slicePlanesSlatSlices.renderPickBuffer(pickBuffer);
    pickBuffer.popMatrix();
  }

  void centreFillWindow(PGraphics g, int w, int h, float scaleRes) {

    float border = 40;
    float minX = -1;
    float minY = -1;
    float maxX = -1;
    float maxY = -1;
    float maxZ = -1;
    float minZ = -1;

    float scaleBy = -1 / GLOBAL.jBullet.scale;

    if (indexVertexArrays != null) {

      for (int i = 0; i < indexVertexArrays.getNumSubParts(); i++) {
        VertexData vd = indexVertexArrays
            .getLockedReadOnlyVertexIndexBase(i);

        for (int t = 0; t < vd.getIndexCount() / 3; t++) {

          Vector3f[] triangle = new Vector3f[] { new Vector3f(),
              new Vector3f(), new Vector3f() };
          Vector3f scale = new Vector3f(1 / GLOBAL.jBullet.scale, -1
              / GLOBAL.jBullet.scale, 1 / GLOBAL.jBullet.scale);
          vd.getTriangle(t * 3, scale, triangle);

          float screenX = g.screenX(triangle[0].x, triangle[0].y,
              triangle[0].z);
          float screenY = g.screenY(triangle[0].x, triangle[0].y,
              triangle[0].z);
          float screenZ = g.screenZ(triangle[0].x, triangle[0].y,
              triangle[0].z);

          if (screenX < minX || minX == -1)
            minX = screenX;

          if (screenX > maxX || maxX == -1)
            maxX = screenX;

          if (screenY < minY || minY == -1)
            minY = screenY;

          if (screenY > maxY || maxY == -1)
            maxY = screenY;

          if (screenZ < minZ || minZ == -1)
            minZ = screenZ;

          if (screenZ > maxZ || maxZ == -1)
            maxZ = screenZ;

          screenX = g.screenX(triangle[1].x, triangle[1].y,
              triangle[1].z);
          screenY = g.screenY(triangle[1].x, triangle[1].y,
              triangle[1].z);

          if (screenX < minX || minX == -1)
            minX = screenX;

          if (screenX > maxX || maxX == -1)
            maxX = screenX;

          if (screenY < minY || minY == -1)
            minY = screenY;

          if (screenY > maxY || maxY == -1)
            maxY = screenY;

          if (screenZ < minZ || minZ == -1)
            minZ = screenZ;

          if (screenZ > maxZ || maxZ == -1)
            maxZ = screenZ;

          screenX = g.screenX(triangle[2].x, triangle[2].y,
              triangle[2].z);
          screenY = g.screenY(triangle[2].x, triangle[2].y,
              triangle[2].z);

          if (screenX < minX || minX == -1)
            minX = screenX;

          if (screenX > maxX || maxX == -1)
            maxX = screenX;

          if (screenY < minY || minY == -1)
            minY = screenY;

          if (screenY > maxY || maxY == -1)
            maxY = screenY;

          if (screenZ < minZ || minZ == -1)
            minZ = screenZ;

          if (screenZ > maxZ || maxZ == -1)
            maxZ = screenZ;

        }
      }

    }

    float scale = 1;

    float modelWidth = maxX - minX;
    float modelHeight = maxY - minY;

    float widthRatio = 1 / ((modelWidth + (0)) / w);
    float heightRatio = 1 / ((modelHeight + (0)) / h);

    if (widthRatio > heightRatio) {
      scale = heightRatio;
    } else {
      scale = widthRatio;
    }
    //scale = 1;

    //scale = 2f;
    scale = scale * 0.8f;
    float cDeltaX = minX - (w / 2) + (modelWidth / 2);
    float cDeltaY = minY - (h / 2) + (modelHeight / 2);
    //LOGGER.info("cDeltaX " + cDeltaX + " cDeltaY " + cDeltaY );
    //LOGGER.info("borderScale" + borderScale);
    float zoom = (float) (GLOBAL.getZOOM() * scale);

    float offsetX = (((cDeltaX) / (zoom * scaleRes)) - (this.centreOfMass.x * scaleBy));
    float offsetY = ((cDeltaY / (zoom * scaleRes)) - (this.centreOfMass.y * scaleBy));
    //g.translate(-((-w / 2) + GLOBAL.CAM_OFFSET_X), -((-h / 2)+ GLOBAL.CAM_OFFSET_Y));

    g.scale(scale);
    //g.translate((-w / 2) + GLOBAL.CAM_OFFSET_X, (-h / 2)
    //    + GLOBAL.CAM_OFFSET_Y);
    //g.scale(scale);

    //g.translate(-border/(scale), -border/(scale));

    //LOGGER.info("scale "+scale );
    //g.scale(scale);
    //g.translate(-(w/2)/GLOBAL.getZOOM(), 0);
    //LOGGER.info("GLOBAL.rotateModelsX "  + " minX " + minX + "offsetX " + offsetX);

    float offsetRotateX = (this.centreOfMass.x * scaleBy);
    float offsetRotateY = (this.centreOfMass.y * scaleBy);

    //LOGGER.info("offsetRotateX " + offsetRotateX + " offsetRotateY " + offsetRotateY);

    g.translate((offsetRotateX), offsetRotateY);

    g.rotateY(-GLOBAL.rotateModelsY);
    g.rotateX(-GLOBAL.rotateModelsX);

    g.translate(-(offsetRotateX), -offsetRotateY);
    g.translate(-(offsetX), -(offsetY));
    //g.translate(border/(zoom), border/(zoom));
    g.rotateX(GLOBAL.rotateModelsX);
    g.rotateY(GLOBAL.rotateModelsY);
    //g.scale(0.9f);
    //  g.scale(0.5f);

    //g.scale(scale);
    //g.fill(0,255,0);
    //g.ellipse(0,0,1000,1000);
    //g.translate(-(w/2), (h/2));

    //g.scale(1.2f);
    //g.translate((w/2), -(h/2));

  }

 
 
  public PImage renderDiagram(int w, int h, boolean useCurrentView) {
    return renderDiagram(w, h, -1, -1, useCurrentView);

  }

  public PImage renderDiagram(int w, int h, float rotateX, float rotateY,
      boolean useCurrentView) {

    this.updateCollisionShape();

    //Setup the chair for outline diagram rendering
    this.slicePlanesSlatSlices.buildOutline(false, false);
    this.slicePlanesY.buildOutline(false, false);

    int P3D = 1;
    int OPENGL = 2;
    int SUNFLOW = 3;

    int renderMode = OPENGL;

    PGraphics diagramImg = null;
    //P5SunflowAPIAPI sunflow = null;

    float scale = 1f;
    w = (int) (w * scale);
    h = (int) (h * scale);

    float minX = this.getSlicePlanesY().getMinX();
    float minY = this.getSlicePlanesY().getMinY();
    float maxX = this.getSlicePlanesY().getMaxX();
    float maxY = this.getSlicePlanesY().getMaxY();

    float width = Math.abs(maxX - minX);
    float height = Math.abs(maxY - minY);

    float widthDelta = w / width;
    float heightDelta = h / height;

    float delta = Math.min(widthDelta, heightDelta);

    //glewIsSupported("GL_EXT_framebuffer_multisample");
    /*
   
    GL gl = ((PGraphicsOpenGL) GLOBAL.applet.g).gl;
    GLState state = new GLState(gl);
    */
    //boolean useVBO = true;//state.vbosAvailable;

    if (renderMode == P3D)
      diagramImg = GLOBAL.applet.createGraphics(w, h, GLOBAL.applet.P3D);

    if (renderMode == OPENGL)
      diagramImg = GLOBAL.applet.createGraphics(w, h, GLOBAL.applet.OPENGL);


    /*
    if (renderMode == SUNFLOW) {
      diagramImg = GLOBAL.applet.createGraphics(w, h,
          "sunflowapiapi.P5SunflowAPIAPI");
      sunflow = (P5SunflowAPIAPI) diagramImg;
      // set shader
      //sunflow.setDiffuseShader();
    }
*/
    diagramImg.beginDraw();
    //diagramImg.background(255,255,255,1);
    diagramImg.ortho(-(w / 2), (w / 2), -(h / 2), (h / 2), -1000, 10000);
    //diagramImg.hint(PApplet.DISABLE_STROKE_PERSPECTIVE);

    diagramImg.pushMatrix();
    diagramImg.smooth(8);

    if (useCurrentView) {

      diagramImg.translate(w / 2, h / 2, 0);

      if (rotateX == -1 && rotateY == -1) {
        diagramImg.rotateX(GLOBAL.rotateModelsX);
        diagramImg.rotateY(GLOBAL.rotateModelsY);
      } else {
        diagramImg.rotateX(rotateX);
        diagramImg.rotateY(rotateY);
      }
      diagramImg.scale((float) GLOBAL.getZOOM());
      diagramImg.scale(scale);

      //we scaled up so now we need to scale the window width move
      diagramImg.translate((-(w / scale) / 2) + (float)(GLOBAL.CAM_OFFSET_X),
          (-(h / scale) / 2) + (float)(GLOBAL.CAM_OFFSET_Y));

      //this.applyTranslationMatrix(diagramImg);

    } else {
      diagramImg.translate(w / 2, h / 2, 0);

      if (rotateX == -1 && rotateY == -1) {
        diagramImg.rotateX(GLOBAL.rotateModelsX);
        diagramImg.rotateY(GLOBAL.rotateModelsY);
      } else {
        diagramImg.rotateX(rotateX);
        diagramImg.rotateY(rotateY);
      }

      diagramImg.scale((float) GLOBAL.getZOOM());
      diagramImg.scale(scale);

      //this.applyTranslationMatrix(diagramImg);

      this.centreFillWindow(diagramImg, w, h, scale);

    }
    //g.translate(-minX , -minY);
    //g.translate(-minX , -minY);
    ///g.translate(((width/2)) , ((height/2)) );
    //g.rotateX(45);
    //g.translate(-((width/2)) , -((height/2)) );
    //g.translate(x/delta,y/delta);
    //RENDER_3D_PREVIW

    // if(GLOBAL.jBullet.physics_on)
    this.slicePlanesY.setRenderMode(Sketch.RENDER_3D_DIAGRAM);
    this.slicePlanesY.render(diagramImg);
    this.slicePlanesSlatSlices.setRenderMode(Sketch.RENDER_3D_DIAGRAM);
    this.slicePlanesSlatSlices.render(diagramImg);

    //this.slicePlanesX.render(g);

    diagramImg.popMatrix();
    diagramImg.endDraw();

    /*
    if (renderMode == SUNFLOW) {
      sunflow.setPathTracingGIEngine(8);
      sunflow.render();
      return sunflow;
    }
    */

    /*
    if (renderMode == OPENGL) {
      GLTexture tex = ((GLGraphicsOffScreen) diagramImg).getTexture();
      tex.updateTexture();
      tex.updatePixels();
      //diagramImg.delete();
      //((GLGraphicsOffScreen)diagramImg)
      GLState.deleteAllGLResources();
      return (PImage) tex;
    }
*/
   
    if (renderMode == P3D)
      return diagramImg;

    return diagramImg;

  }

 
 
  /* 3D Preview View ( top right corner)
   *
   */
  public float render3Dpreview(PGraphics g, float x, float y, float w, float h) {

    g.smooth(8);

    this.slicePlanesY.setRenderMode(Sketch.RENDER_3D_PREVIW);
    this.slicePlanesSlatSlices.setRenderMode(Sketch.RENDER_3D_PREVIW);

    float minX = this.getSlicePlanesY().getMinX();
    float minY = this.getSlicePlanesY().getMinY();
    float maxX = this.getSlicePlanesY().getMaxX();
    float maxY = this.getSlicePlanesY().getMaxY();

    float width = Math.abs(maxX - minX);
    float height = Math.abs(maxY - minY);

   
   
    float widthDelta = w / width;
    float heightDelta = h / height;
    float delta = Math.min(widthDelta, heightDelta);

    float goundOffset = (h-(height*delta))/delta;
    g.pushMatrix();
    g.scale(delta);
    g.translate(x / delta, y / delta);
    g.translate(0, +(height / 2)+goundOffset);

    g.rotateY((float) (-Math.PI / 4));
    //g.rotateY(rotateRend);
    g.translate(-minX - (width / 2), -minY - (height / 2));
    //g.translate(-minX , -minY);
    //g.translate(-minX , -minY);
    ///g.translate(((width/2)) , ((height/2)) );
    //g.rotateX(45);
    //g.translate(-((width/2)) , -((height/2)) );
    //g.translate(x/delta,y/delta);

    //this.slicePlanesY.setRenderMode(Sketch.RENDER_3D_PREVIW);
    this.slicePlanesY.render(g);
    //this.slicePlanesSlatSlices.render(g);
    g.popMatrix();
   
    return delta;

  }

  public void render3DPickPreview(PGraphics g, float x, float y, float w,
      float h) {

    float minX = this.getSlicePlanesY().getMinX();
    float minY = this.getSlicePlanesY().getMinY();
    float maxX = this.getSlicePlanesY().getMaxX();
    float maxY = this.getSlicePlanesY().getMaxY();

    float width = Math.abs(maxX - minX);
    float height = Math.abs(maxY - minY);

    float widthDelta = w / width;
    float heightDelta = h / height;
    float delta = Math.min(widthDelta, heightDelta);
    float goundOffset = (h-(height*delta))/delta;

    g.pushMatrix();
    g.scale(delta);
    g.translate(x / delta, y / delta);
    g.translate(0, +(height / 2));
    g.rotateY((float) (-Math.PI / 4));
    g.translate(-minX - (width / 2), -minY - (height / 2)+goundOffset);

    this.slicePlanesY.renderPickBuffer(g);
    g.popMatrix();

  }

  public void renderSilhouette(int thumbnailWidth, int thumbnailHeight,
      PGraphics g) {
    float minX = this.getSlicePlanesY().getMinX();
    float minY = this.getSlicePlanesY().getMinY();
    float maxX = this.getSlicePlanesY().getMaxX();
    float maxY = this.getSlicePlanesY().getMaxY();

    float width = Math.abs(maxX - minX);
    float height = Math.abs(maxY - minY);

    float widthDelta = thumbnailWidth / width;
    float heightDelta = thumbnailHeight / height;

    float delta = Math.min(widthDelta, heightDelta);
    g.pushMatrix();
    this.applyTranslationMatrix(g);
    g.scale(delta * .9f);
    g.translate(-minX * .95f, -minY * .95f);

    // this.applyTranslationMatrix(g);
    // this.selectedPlanes.renderSilhouette(g);
    // this.slicePlanesX.renderSilhouette(g);
    this.getSlicePlanesY().renderSilhouette(g);
    // g.ellipse(this.centreOfMass.x/GLOBAL.jBullet.scale,this.centreOfMass.y/GLOBAL.jBullet.scale,25,25);
    g.popMatrix();
  }

  public void renderSilhouette(PGraphics g) {
    g.pushMatrix();
    g.smooth(8);
    this.getSlicePlanesY().renderSilhouette(g);
    g.noSmooth();
    g.popMatrix();

  }

  public PGraphics renderToFile() {
    float border = 25;

    float minX = this.getSlicePlanesY().getMinXWorldSpace(
        this.currentWorldTransform);
    float minY = this.getSlicePlanesY().getMinYWorldSpace(
        this.currentWorldTransform);
    float maxX = this.getSlicePlanesY().getMaxXWorldSpace(
        this.currentWorldTransform);
    float maxY = this.getSlicePlanesY().getMaxYWorldSpace(
        this.currentWorldTransform);

    float minX2 = this.getSlicePlanesY().getMinX();
    float minY2 = this.getSlicePlanesY().getMinY();
    float maxX2 = this.getSlicePlanesY().getMaxX();
    float maxY2 = this.getSlicePlanesY().getMaxY();

    float width = Math.abs(maxX - minX) + (imgBorder * 2);
    float height = Math.abs(maxY - minY) + +(imgBorder * 2);

    float width2 = Math.abs(maxX2 - minX2) + (imgBorder * 2);
    float height2 = Math.abs(maxY2 - minY2) + (imgBorder * 2);

    PGraphics saveImg = GLOBAL.applet.createGraphics((int) width,
        (int) height, PConstants.P3D);
    saveImg.beginDraw();
    saveImg.ortho(-(width / 2), (width / 2), -(height / 2), (height / 2),
        -1000, 10000);
    //saveImg.hint(PApplet.DISABLE_STROKE_PERSPECTIVE);

    saveImg.smooth(8);
    saveImg.pushMatrix();

    saveImg.translate(-minX + border, -minY + border);
    this.renderSilhouette(saveImg);

    saveImg.popMatrix();
    saveImg.endDraw();
    return saveImg;

  }

  public void resetPhysics() {
    this.personSeated = false;
    rigidBody.setMotionState(new DefaultMotionState(
        this.startWorldTransform));
    GLOBAL.jBullet.update();

  }

  /*
   *
   */
  public void saveToPDF(PGraphics g) {
    this.getSlicePlanesY().saveToPDF(g);
    this.slicePlanesSlatSlices.saveToPDF(g, true);
  }

  /**
   * Scale the current design.
   * @param scale
   */
  private void scale(float scale) {
    Vec3D centre = this.getCentreOfMass();
    centre.scaleSelf(1 / GLOBAL.jBullet.scale);
    this.getSlicePlanesY().scale(scale, centre);
    this.scale += scale;
  }

  /*
   * Seat the figure on the design.
   */
  public void seatPerson() {
    if (SETTINGS.auto_seat && !GLOBAL.person.dragged) {
      GLOBAL.person.seat(
          this,
          this.getSlicePlanesY().getMaxXWorldSpace(
              this.currentWorldTransform), this.getSlicePlanesY()
              .getMaxYWorldSpace(this.currentWorldTransform), 0);
      this.personSeated = true;
    }
  }

  public void selectNodes(int mouseX, int mouseY) {
    this.selectedPlanes.selectNodes(mouseX, mouseY);
  }

  public void setBrushCap(int cap) {
    this.selectedPlanes.setBrushCap(cap);

  }

  public void setBrushDia(float val) {
    this.selectedPlanes.setBrushDia(val);
  }

  public void setHeight(float height) {

  }

  public void setPlaneWidth(float planeThicknes_mm) {
    this.materialWidth = planeThicknes_mm;
    this.selectedPlanes.setPlaneWidth(planeThicknes_mm);
    this.slicePlanesY.setPlaneWidth(planeThicknes_mm);
    this.slicePlanesSlatSlices.setPlaneWidth(planeThicknes_mm);
  }

  public void setPosTopCorner(int minX, int maxY) {

  }

  /**
   * @param reScaling the reScaling to set
   */
  public void setReScaling(boolean reScaling) {
    this.reScaling = reScaling;
  }

  /**
   * @param slicePlanesY the slicePlanesY to set
   */
  public void setSlicePlanesY(SlicePlanes slicePlanesY) {
    this.slicePlanesY = slicePlanesY;
  }

  /**
   * @param updateCollisionMesh the updateCollisionMesh to set
   */
  public void setUpdateCollisionMesh(boolean updateCollisionMesh) {
    this.updateCollisionMesh = updateCollisionMesh;
  }

  public Vec2D setVec2DpickBuffer(int col, SketchPoint selectedVec,
      SketchShape selectedShape, SlicePlane selectedVecPlane,
      boolean isSelectedVecOnOutline) {

    Vec2D vec = this.selectedPlanes.setVec2DpickBuffer(col, selectedVec,
        selectedShape, selectedVecPlane, isSelectedVecOnOutline);
    if (vec != null)
      return vec;

    vec = this.slicePlanesSlatSlices.setVec2DpickBuffer(col, selectedVec,
        selectedShape, selectedVecPlane, isSelectedVecOnOutline);

    if (vec != null)
      return vec;

    return this.getSlicePlanesY().setVec2DpickBuffer(col, selectedVec,
        selectedShape, selectedVecPlane, isSelectedVecOnOutline);
  }

 
 
  /*
   * Set the current width and rebuilt layers and slices to match.
   */
  public void setWidth(float w) {
    // System.out.println(deltaMouseY);
    this.width = w;
    if (this.getSlicePlanesY().size() > 1) {
      this.rebuildWidth();
    }
  }
 
 

  //Set the chair in the center of the playfiled at ground height, this can only currently be done before the chair is moved
  void setAtGroundHeightCentred() {
    //float minY = this.getSlicePlanesY().getMinY();
    float maxY = this.getSlicePlanesY().getMaxYWorldSpace(
        this.currentWorldTransform);

    float minX = this.getSlicePlanesY().getMinXWorldSpace(
        currentWorldTransform);
    float maxX = this.getSlicePlanesY().getMaxXWorldSpace(
        currentWorldTransform);
    //float height = (maxY-minY);
    float cWidth = maxX - minX;

    float offsetX = minX - (cWidth / 2);
    //LOGGER.info("minX " + minX);
    float offsetY = offsetY = maxY - 1570; // what is this weird hardcoded number?
    //debug info useful for working out the translations between different cord sys
    /*
        LOGGER.info("getMeshMinY()) " + (getMeshMinY()));
        LOGGER.info("maxY " + maxY);
        LOGGER.info("height " + height);
        LOGGER.info("getPhysicsOrigin().y" + (getPhysicsOrigin().y*(1 / GLOBAL.jBullet.scale)));
        LOGGER.info("getPhysicsOrigin().x" + (getPhysicsOrigin().x*(1 / GLOBAL.jBullet.scale)));
    */

    this.translate(-offsetX, (-offsetY), 0);

  }

  void toggleCentreConstraint() {
    if (this.chairCentreConstraint != null) {
      GLOBAL.jBullet.myWorld.removeConstraint(this.chairCentreConstraint);
      this.chairCentreConstraint = null;
    } else {
      this.addCentrePlaneConstraint();
    }

  }

  public void toggleUnion() {
    this.selectedPlanes.toggleUnion();
  }

  public Element toXML() {
    Element element = new Element("SketchChair");

    //cloudID
    // set slat spacing
    element.addAttribute(new Attribute("cloudID", String.valueOf(cloudID)));

    // set slat spacing
    element.addAttribute(new Attribute("slatSpacingX", String
        .valueOf(slatSpacingX)));

    element.addAttribute(new Attribute("materialWidth", String
        .valueOf(SETTINGS.materialThickness)));

    element.addAttribute(new Attribute("scale", String
        .valueOf(SETTINGS.scale)));

    element.appendChild(this.getSlicePlanesY().toXML());
    element.appendChild(crossSliceSelections.toXML());

    return element;

  }

  void translate(float x, float y, float z) {
    Vector3f offset3f = new Vector3f(x, y, z);
    offset3f.scale(GLOBAL.jBullet.scale);
    this.rigidBody.translate(offset3f);
    GLOBAL.jBullet.update();
    this.startWorldTransform.origin.set(offset3f);
  }

  public void update() {

    //this.setAtGroundHeight();

    if (this.rigidBody != null) {
      Transform myTransform = new Transform();
      myTransform = rigidBody.getMotionState().getWorldTransform(
          myTransform);
      this.currentWorldTransform = myTransform;
    }

    if (this.built && this.getSlicePlanesY().countNumberOfShapes() <= 0)
      this.destroy();

    if (trimesh != null)
      trimesh.updateBound();

    //The physics is running and we need to update our mesh so go and do it now !
    if (GLOBAL.jBullet.physics_on && this.isUpdateCollisionMesh()) {
      this.updateCollisionShape();
      this.setUpdateCollisionMesh(false);
    }

    if (GLOBAL.jBullet.physics_on && !this.personSeated
        && SETTINGS.auto_seat) {
      this.seatPerson();

    }

    boolean wasNotNull = false;
    if (creossSelectionTempOver != null)
      wasNotNull = true;

    boolean updateLen = false;

    if (creossSelectionTempOver != null && !creossSelectionTempOver.editing)
      creossSelectionTempOver = null;

    if (GLOBAL.uiTools.getCurrentTool() == UITools.SLICES_SINGLE_SLICE) {
      SketchShapes overShapes = getOverShapes(GLOBAL.uiTools.mouseX,
          GLOBAL.uiTools.mouseY);

      if (overShapes.size() > 0) {
        SketchShape overShape = overShapes.getClosest(
            GLOBAL.uiTools.mouseX, GLOBAL.uiTools.mouseY);
        creossSelectionTempOver = new CrossSliceSelection(overShape,
            overShape.getParentSketch().getOnSketchPlane(),
            overShape.lastMouseOverPercent,
            overShape.lastMouseOverPercent, 1, this);
        creossSelectionTempOver.type = CrossSliceSelection.SINGLE_SLICE;
        creossSelectionTempOver.select();
        creossSelectionTempOver.tempSlice = true;
        updateLen = true;

      }

    }

    if (GLOBAL.uiTools.getCurrentTool() == UITools.SLICES_GROUP_SLICES
        && ((creossSelectionTempOver == null || !creossSelectionTempOver.editing))) {

      SketchShapes overShapes = getOverShapes(GLOBAL.uiTools.mouseX,
          GLOBAL.uiTools.mouseY);
      if (overShapes.size() > 0) {
        SketchShape overShape = overShapes.getClosest(
            GLOBAL.uiTools.mouseX, GLOBAL.uiTools.mouseY);
        creossSelectionTempOver = new CrossSliceSelection(overShape,
            overShape.getParentSketch().getOnSketchPlane(),
            overShape.lastMouseOverPercent,
            overShape.lastMouseOverPercent, 10f, this);
        creossSelectionTempOver.type = CrossSliceSelection.SLICES;
        creossSelectionTempOver.mousePercent = overShape.lastMouseOverPercent;
        creossSelectionTempOver.select();
        creossSelectionTempOver.tempSlice = true;

        updateLen = true;
      }

    }

    if (GLOBAL.uiTools.getCurrentTool() == UITools.SLICES_SLATSLICE_GROUP
        && ((creossSelectionTempOver == null || !creossSelectionTempOver.editing))) {

      SketchShapes overShapes = getOverShapes(GLOBAL.uiTools.mouseX,
          GLOBAL.uiTools.mouseY);

      if (overShapes.size() > 0) {
        SketchShape overShape = overShapes.getClosest(
            GLOBAL.uiTools.mouseX, GLOBAL.uiTools.mouseY);
        creossSelectionTempOver = new CrossSliceSelection(overShape,
            overShape.getParentSketch().getOnSketchPlane(),
            overShape.lastMouseOverPercent,
            overShape.lastMouseOverPercent, 50, this);
        creossSelectionTempOver.type = CrossSliceSelection.SLATSLICES;
        creossSelectionTempOver
            .setSlatHeight(SETTINGS.DEFAULT_SLATSLICE_HEIGHT);
        creossSelectionTempOver.mousePercent = overShape.lastMouseOverPercent;
        creossSelectionTempOver.select();
        creossSelectionTempOver.tempSlice = true;

        updateLen = true;
      }

    }

    if (GLOBAL.uiTools.getCurrentTool() == UITools.SLICES_SINGLE_SLAT
        && ((creossSelectionTempOver == null || !creossSelectionTempOver.editing))) {

      SketchShapes overShapes = getOverShapes(GLOBAL.uiTools.mouseX,
          GLOBAL.uiTools.mouseY);

      if (overShapes.size() > 0) {
        SketchShape overShape = overShapes.getClosest(
            GLOBAL.uiTools.mouseX, GLOBAL.uiTools.mouseY);
        creossSelectionTempOver = new CrossSliceSelection(overShape,
            overShape.getParentSketch().getOnSketchPlane(),
            overShape.lastMouseOverPercent,
            overShape.lastMouseOverPercent + 0.01f, 1, this);
        creossSelectionTempOver.type = CrossSliceSelection.PLANE_ON_EDGE;
        creossSelectionTempOver.mousePercent = overShape.lastMouseOverPercent;
        creossSelectionTempOver.select();
        creossSelectionTempOver.tempSlice = true;

        updateLen = true;
      } else {
        if (this.selectedPlanes.size() > 0) {
          SlicePlane tempPlane = this.selectedPlanes.get(0);
          ;
          Vec2D tempP = new Vec2D(GLOBAL.uiTools.mouseX,
              GLOBAL.uiTools.mouseY);
          SketchPath tempPath = new SketchPath(tempPlane.getSketch());
          tempPath.add(new SketchPoint(GLOBAL.uiTools
              .getPointOnPlane(tempP, tempPlane.getPlane())));
          tempPath.add(new SketchPoint(GLOBAL.uiTools
              .getPointOnPlane(tempP, tempPlane.getPlane()).add(
                  100, 0)));
          tempPath.setIsContructionLine(true);
          creossSelectionTempOver = new CrossSliceSelection(tempPath,
              tempPath.getParentSketch().getOnSketchPlane(), 0,
              1, 1, this);
          creossSelectionTempOver.type = CrossSliceSelection.PLANE;
          creossSelectionTempOver.select();
          creossSelectionTempOver.tempSlice = true;

          updateLen = true;
        }
      }
    }

    if (creossSelectionTempOver != null && creossSelectionTempOver.editing) {
      creossSelectionTempOver.update();
      updateLen = true;
    }

    if (GLOBAL.uiTools.getCurrentTool() == UITools.CROSSSLICE_EDIT)
      this.buildLen();

    if (this.rebuildLength || updateLen) {
      this.previewSlices();
      this.rebuildLength = false;
    }

    //this.slicePlanesX.unselectAll();
    //LOGGER.info("UNSELECT " + this.selectedPlanes.size());
    this.getSlicePlanesY().unselectAll();
    this.selectedPlanes.selectAll();
    // this.sketchSpline.update();
    this.slicePlanesSlatSlices.update();
    this.getSlicePlanesY().update();
    this.selectedPlanes.update();
    this.crossSliceSelections.update();

  }

  public void updateCollisionShape() {
    if (this.trimesh == null) {
      addRigidModel();
      return;
    }
    // if (this.rigidBody != null)
    // GLOBAL.jBullet.myWorld.removeRigidBody(this.rigidBody);

    Vec3D centreOfMassOld = this.centreOfMass.copy();
    Vec3D centreOfMassTemp = this.getCentreOfMass();

    LOGGER.debug("current centre" + centreOfMassOld);
    LOGGER.debug("current centre Translated "
        + getTranslated(centreOfMassOld));

    LOGGER.debug("new centre" + centreOfMassTemp);
    LOGGER.debug("new centre Translated" + getTranslated(centreOfMassTemp));

    this.centreOfMass = centreOfMassTemp;
    Vec3D deltaCentreOfmass = getTranslated(this.centreOfMass).sub(
        getTranslated(centreOfMassOld));

    //  this.centreOfMass = centreOfMassTemp;
    // create trimesh
    indexVertexArrays = this.getVertexArray(centreOfMass.x, centreOfMass.y,
        centreOfMass.z);

    //this.buildCoverMesh(indexVertexArrays, centreOfMass);

    if (indexVertexArrays != null) {
      trimesh = new GImpactMeshShape(indexVertexArrays);
      trimesh.setLocalScaling(new Vector3f(1f, 1f, 1f));
      trimesh.updateBound();
      // rigidBody.setMotionState(myMotionState);
      if (trimesh != null && this.rigidBody != null)
        this.rigidBody.setCollisionShape(trimesh);

      if (this.rigidBody == null || trimesh == null)
        return;

      Transform transform = new Transform();
      MotionState motionstate = rigidBody.getMotionState();
      motionstate.getWorldTransform(transform);
      Matrix4f chairMatrix = new Matrix4f();
      transform.getMatrix(chairMatrix);
      //  LOGGER.debug("current origin"+transform.origin.toString());

      //this is overwritten when settign the chair matrix
      //transform.origin.set(this.centreOfMass.x, this.centreOfMass.y,
      //    this.centreOfMass.z);

      LOGGER.debug("delta x" + deltaCentreOfmass.x);
      LOGGER.debug("delta y" + deltaCentreOfmass.y);
      LOGGER.debug("delta z" + deltaCentreOfmass.z);

      float newX = ((chairMatrix.m00) * deltaCentreOfmass.x)
          + ((chairMatrix.m01) * deltaCentreOfmass.y)
          + ((chairMatrix.m02) * deltaCentreOfmass.z);
      float newY = (((chairMatrix.m10) * deltaCentreOfmass.x)
          + ((chairMatrix.m11) * deltaCentreOfmass.y) + ((chairMatrix.m12) * deltaCentreOfmass.z));
      float newZ = ((chairMatrix.m20) * deltaCentreOfmass.x)
          + ((chairMatrix.m21) * deltaCentreOfmass.y)
          + ((chairMatrix.m22) * deltaCentreOfmass.z);

      //these are the origin
      chairMatrix.m03 -= deltaCentreOfmass.x;//10;//deltaCentreOfmass.x;
      chairMatrix.m13 -= deltaCentreOfmass.y;//deltaCentreOfmass.y;
      chairMatrix.m23 += deltaCentreOfmass.z;//deltaCentreOfmass.z;

      //chairMatrix.m03 = this.centreOfMass.x;
      //chairMatrix.m13 = this.centreOfMass.y;
      //chairMatrix.m23 = this.centreOfMass.z;

      LOGGER.debug("delta x t " + newX);
      LOGGER.debug("delta y t " + newY);
      LOGGER.debug("delta z t " + newZ);

      transform.set(chairMatrix);
      motionstate.setWorldTransform(transform);
      rigidBody.setMotionState(motionstate);

      Vector3f center = new Vector3f();
      rigidBody.getCenterOfMassPosition(center);
      LOGGER.debug("getCenterOfMassPosition set " + center);

      // System.out.println("weight" + this.getArea());
      Vector3f AngularVelocity = new Vector3f(0, 0, 0);
      rigidBody.getAngularVelocity(AngularVelocity);

      Vector3f LinearVelocity = new Vector3f(0, 0, 0);
      rigidBody.getLinearVelocity(LinearVelocity);

      GLOBAL.jBullet.update();

      motionstate.getWorldTransform(transform);
      //  LOGGER.debug("new origin"+transform.origin.toString());

      //this.translate(-newX, newY, newZ);

      // rigidBody.setAngularVelocity(AngularVelocity);
      // rigidBody.setLinearVelocity(LinearVelocity);
      // rigidBody.setMassProps(this.getMass(), new Vector3f(0,1,0));

      rigidBody.setDamping(SETTINGS.chair_damping_linear,
          SETTINGS.chair_damping_ang);
      rigidBody.setDeactivationTime(0.8f);
      rigidBody.setSleepingThresholds(1.6f, 2.5f);
      rigidBody.setFriction(SETTINGS.chair_friction);
      motionstate = rigidBody.getMotionState();
      rigidBody.setCcdSweptSphereRadius(.1f);

    }

    // GLOBAL.person.solveOverlap();
  }

  private void writeObject(ObjectOutputStream out) throws IOException {
    out.defaultWriteObject();
  }

  public void importSVG(String path) {
   
    if(this.selectedPlanes.size() == 0){
      SlicePlane slicePlane = new SlicePlane(new Plane(
          new Vec3D(0, 0, 0), new Vec3D(0, 0, -1)));
      slicePlane.importSVG(path);
      this.getSlicePlanesY().add(slicePlane);
     
    }else{
      this.selectedPlanes.importSVG(path);
    }
     
     
  }

  public void unselectAllPlanes() {
    this.selectedPlanes.unselectAll();
    this.slicePlanesY.unselectAll();
    this.slicePlanesSlatSlices.unselectAll();
   
    this.selectedPlanes.unselectShapesAll();
    this.slicePlanesY.unselectShapesAll();
    this.slicePlanesSlatSlices.unselectShapesAll();
   
    this.selectedPlanes.empty();
  }

 

}
TOP

Related Classes of cc.sketchchair.core.SketchChair

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.