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