use of com.ardor3d.math.type.ReadOnlyTransform in project energy3d by concord-consortium.
the class Heliodon method initMouse.
private void initMouse(final LogicalLayer logicalLayer) {
logicalLayer.registerTrigger(new InputTrigger(new KeyPressedCondition(Key.F), new TriggerAction() {
@Override
public void perform(final Canvas source, final TwoInputStates inputStates, final double tpf) {
setSunRegionAlwaysVisible(!forceSunRegionOn);
}
}));
logicalLayer.registerTrigger(new InputTrigger(new MouseButtonPressedCondition(MouseButton.LEFT), new TriggerAction() {
@Override
public void perform(final Canvas source, final TwoInputStates inputStates, final double tpf) {
oldHourAngle = hourAngle;
changeTimeAndDateCommand = new ChangeTimeAndDateWithHeliodonCommand(calendar.getTime());
final int x = inputStates.getCurrent().getMouseState().getX();
final int y = inputStates.getCurrent().getMouseState().getY();
final Ray3 pickRay = SceneManager.getInstance().getCanvas().getCanvasRenderer().getCamera().getPickRay(new Vector2(x, y), false, null);
pickResults.clear();
PickingUtil.findPick(sun, pickRay, pickResults);
if (pickResults.getNumber() != 0) {
sunGrabbed = true;
} else {
sunGrabbed = false;
}
if (forceSunRegionOn) {
selectDifferentDeclinationWithMouse = true;
} else {
selectDifferentDeclinationWithMouse = false;
}
SceneManager.getInstance().setMouseControlEnabled(!sunGrabbed);
}
}));
logicalLayer.registerTrigger(new InputTrigger(new MouseButtonReleasedCondition(MouseButton.LEFT), new TriggerAction() {
@Override
public void perform(final Canvas source, final TwoInputStates inputStates, final double tpf) {
sunGrabbed = false;
if (!forceSunRegionOn) {
sunRegion.getSceneHints().setCullHint(CullHint.Always);
}
SceneManager.getInstance().setMouseControlEnabled(true);
if (!Util.isEqual(oldHourAngle, hourAngle) && changeTimeAndDateCommand != null) {
SceneManager.getInstance().getUndoManager().addEdit(changeTimeAndDateCommand);
}
}
}));
logicalLayer.registerTrigger(new InputTrigger(new MouseMovedCondition(), new TriggerAction() {
@Override
public void perform(final Canvas source, final TwoInputStates inputStates, final double tpf) {
if (!sunGrabbed) {
return;
}
final MouseState mouse = inputStates.getCurrent().getMouseState();
final Ray3 pickRay = SceneManager.getInstance().getCamera().getPickRay(new Vector2(mouse.getX(), mouse.getY()), false, null);
pickResults.clear();
PickingUtil.findPick(sunRegion, pickRay, pickResults);
final Vector3 intersectionPoint;
if (pickResults.getNumber() > 0) {
final IntersectionRecord intersectionRecord = pickResults.getPickData(0).getIntersectionRecord();
intersectionPoint = intersectionRecord.getIntersectionPoint(intersectionRecord.getClosestIntersection());
} else {
intersectionPoint = null;
}
double smallestDistance = Double.MAX_VALUE;
int hourVertex = -1;
int totalHourVertices = 0;
final Vector3 newSunLocation = new Vector3();
final Vector3 p = new Vector3();
final Vector3 p_abs = new Vector3();
final ReadOnlyTransform rootTansform = root.getTransform();
if (!selectDifferentDeclinationWithMouse) {
final FloatBuffer buf = sunPath.getMeshData().getVertexBuffer();
buf.rewind();
while (buf.hasRemaining()) {
p.set(buf.get(), buf.get(), buf.get());
rootTansform.applyForward(p, p_abs);
final double d;
d = pickRay.distanceSquared(p_abs, null);
if (d < smallestDistance) {
smallestDistance = d;
hourVertex = buf.position() / 3 - 1;
newSunLocation.set(p);
}
}
totalHourVertices = buf.limit() / 3;
}
if (smallestDistance > 5.0 * root.getTransform().getScale().getX() * root.getTransform().getScale().getX()) {
selectDifferentDeclinationWithMouse = true;
}
boolean declinationChanged = false;
if (selectDifferentDeclinationWithMouse) {
sunRegion.getSceneHints().setCullHint(CullHint.Inherit);
int rowCounter = 0;
int resultRow = -1;
final FloatBuffer buf = sunRegion.getMeshData().getVertexBuffer();
buf.rewind();
final double r = 5.0 / 2.0;
final Vector3 prev = new Vector3();
int quadVertexCounter = 0;
final double maxVertexInRow = HOUR_DIVISIONS * 4.0;
int rowVertexCounter = 0;
boolean foundInThisRow = false;
while (buf.hasRemaining()) {
p.set(buf.get(), buf.get(), buf.get());
rootTansform.applyForward(p, p_abs);
final double d;
if (intersectionPoint != null) {
d = intersectionPoint.distanceSquared(p_abs);
} else {
d = pickRay.distanceSquared(p_abs, null);
}
if (d < smallestDistance && p.getZ() >= -MathUtils.ZERO_TOLERANCE) {
smallestDistance = d;
newSunLocation.set(p);
resultRow = rowCounter + (quadVertexCounter >= 2 ? 1 : 0);
hourVertex = rowVertexCounter / 4 + (quadVertexCounter == 1 || quadVertexCounter == 2 ? 1 : 0);
foundInThisRow = true;
}
if (prev.lengthSquared() != 0 && (prev.distance(p) > r || rowVertexCounter >= maxVertexInRow)) {
rowCounter++;
if (foundInThisRow) {
totalHourVertices = rowVertexCounter / 4;
}
foundInThisRow = false;
rowVertexCounter = 0;
}
prev.set(p);
quadVertexCounter = (quadVertexCounter + 1) % 4;
rowVertexCounter++;
}
rowCounter++;
if (resultRow != -1) {
if (rowCounter < DECLINATION_DIVISIONS && latitude > 0) {
resultRow += DECLINATION_DIVISIONS - rowCounter;
}
final double newDeclinationAngle = -TILT_ANGLE + (2.0 * TILT_ANGLE * resultRow / DECLINATION_DIVISIONS);
declinationChanged = !Util.isEqual(newDeclinationAngle, declinationAngle);
if (declinationChanged) {
setDeclinationAngle(newDeclinationAngle, false, true);
dirtySunPath = true;
}
}
}
final double newHourAngle = (hourVertex - Math.floor(totalHourVertices / 2.0)) * Math.PI / 48.0;
final boolean hourAngleChanged = !Util.isEqual(newHourAngle, hourAngle);
if (hourAngleChanged) {
setHourAngle(newHourAngle, false, true, false);
}
if (declinationChanged || hourAngleChanged) {
setSunLocation(newSunLocation);
drawSunTriangle();
EnergyPanel.getInstance().updateRadiationHeatMap();
}
}
}));
}
use of com.ardor3d.math.type.ReadOnlyTransform in project energy3d by concord-consortium.
the class Window method makeRectangle.
private Rectangle2D makeRectangle(final Window window, final boolean isRoof) {
final ReadOnlyTransform transform;
if (isRoof) {
transform = ((Roof) container).getRoofPartsRoot().getChild(window.containerRoofIndex).getWorldTransform();
} else {
transform = null;
}
Rectangle2D thisWindow = null;
for (int i = 0; i < window.points.size(); i++) {
final Vector3 p = window.points.get(i);
if (isRoof) {
transform.applyInverse(p);
}
final double y = isRoof ? p.getY() : p.getZ();
if (thisWindow == null) {
thisWindow = new Rectangle2D.Double(p.getX(), y, 0, 0);
}
thisWindow.add(p.getX(), y);
}
return thisWindow;
}
use of com.ardor3d.math.type.ReadOnlyTransform in project energy3d by concord-consortium.
the class Foundation method importCollada.
public Node importCollada(final URL file, final Vector3 position) throws Exception {
if (importedNodes == null) {
importedNodes = new ArrayList<Node>();
}
if (importedNodeStates == null) {
importedNodeStates = new ArrayList<NodeState>();
}
if (position != null) {
// when position is null, the cursor is already set to be wait by the loading method
SceneManager.getInstance().cursorWait(true);
}
File sourceFile = new File(file.toURI());
if (!sourceFile.exists() && Scene.getURL() != null) {
sourceFile = new File(new File(Scene.getURL().toURI()).getParentFile(), Util.getFileName(file.getPath()).replaceAll("%20", " "));
}
if (sourceFile.exists()) {
final double az = Math.toRadians(getAzimuth());
final boolean zeroAz = Util.isZero(az);
// 0.633 is determined by fitting the length in Energy3D to the length in SketchUp
final double scale = Scene.getInstance().getAnnotationScale() * 0.633;
final ColladaStorage storage = new ColladaImporter().load(new URLResourceSource(sourceFile.toURI().toURL()));
final Node originalNode = storage.getScene();
originalNode.setScale(scale);
if (position != null) {
// when position is null, the node uses the position saved in the associated NodeState object
final NodeState ns = new NodeState();
ns.setSourceURL(file);
ns.setAbsolutePosition(position.clone());
importedNodeStates.add(ns);
originalNode.setTranslation(position);
final Vector3 relativePosition = position.subtract(getAbsCenter().multiplyLocal(1, 1, 0), null).addLocal(0, 0, height);
// why not -getAzimuth()?
ns.setRelativePosition(zeroAz ? relativePosition : new Matrix3().fromAngles(0, 0, az).applyPost(relativePosition, null));
}
// now construct a new node that is a parent of all planar meshes
final Node newNode = new Node(originalNode.getName());
final String nodeString = "Node #" + importedNodes.size() + ", Foundation #" + id;
final List<Mesh> meshes = new ArrayList<Mesh>();
Util.getMeshes(originalNode, meshes);
String warnInfo = null;
final int nodeIndex = importedNodes.size();
int meshIndex = 0;
for (final Mesh m : meshes) {
final ReadOnlyTransform t = m.getWorldTransform();
final MeshData md = m.getMeshData();
switch(md.getIndexMode(0)) {
case Triangles:
final List<Mesh> children = TriangleMeshLib.getPlanarMeshes(m);
if (!children.isEmpty()) {
for (final Mesh s : children) {
s.setTransform(t);
final UserData ud = new UserData(this, nodeIndex, meshIndex);
ud.setNormal((Vector3) s.getUserData());
ud.setRenderState(s.getLocalRenderState(StateType.Texture));
ud.setTextureBuffer(s.getMeshData().getTextureBuffer(0));
s.setUserData(ud);
s.setName("Mesh #" + meshIndex + ", " + nodeString);
newNode.attachChild(s);
meshIndex++;
}
}
break;
case Lines:
break;
default:
warnInfo = md.getIndexMode(0).name();
break;
}
}
if (warnInfo != null) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Non-triangular mesh " + warnInfo + " is found.", "Warning", JOptionPane.WARNING_MESSAGE);
}
if (newNode.getNumberOfChildren() > 0) {
importedNodes.add(newNode);
newNode.setScale(scale);
newNode.updateWorldTransform(true);
root.attachChild(newNode);
createMeshThickness(newNode);
if (!zeroAz) {
setRotatedNormalsForImportedMeshes();
}
return newNode;
}
if (position != null) {
SceneManager.getInstance().cursorWait(false);
}
} else {
if (position != null) {
// get rid of the dead nodes no longer linked to files
for (final Iterator<NodeState> it = importedNodeStates.iterator(); it.hasNext(); ) {
if (file.equals(it.next().getSourceURL())) {
it.remove();
}
}
}
}
return null;
}
use of com.ardor3d.math.type.ReadOnlyTransform in project energy3d by concord-consortium.
the class SolarPanel method drawSunBeam.
@Override
public void drawSunBeam() {
if (Heliodon.getInstance().isNightTime() || !drawSunBeam) {
sunBeam.setVisible(false);
normalVector.setVisible(false);
sunAngle.setVisible(false);
return;
}
final Vector3 o = (!onFlatSurface() || container instanceof Rack) ? getAbsPoint(0) : getAbsPoint(0).addLocal(0, 0, baseHeight);
final Vector3 sunLocation = Heliodon.getInstance().computeSunLocation(Heliodon.getInstance().getCalendar()).normalizeLocal();
final FloatBuffer beamsVertices = sunBeam.getMeshData().getVertexBuffer();
beamsVertices.rewind();
// draw sun vector
Vector3 r = o.clone();
r.addLocal(sunLocation.multiply(5000, null));
beamsVertices.put(o.getXf()).put(o.getYf()).put(o.getZf());
beamsVertices.put(r.getXf()).put(r.getYf()).put(r.getZf());
sunBeam.updateModelBound();
sunBeam.setVisible(true);
if (bloomRenderPass == null) {
bloomRenderPass = new BloomRenderPass(SceneManager.getInstance().getCamera(), 10);
bloomRenderPass.setBlurIntensityMultiplier(0.5f);
bloomRenderPass.setNrBlurPasses(2);
SceneManager.getInstance().getPassManager().add(bloomRenderPass);
}
if (!bloomRenderPass.contains(sunBeam)) {
bloomRenderPass.add(sunBeam);
}
final FloatBuffer normalVertices = normalVector.getMeshData().getVertexBuffer();
normalVertices.rewind();
// draw normal vector
r = o.clone();
r.addLocal(normal.multiply(normalVectorLength, null));
normalVertices.put(o.getXf()).put(o.getYf()).put(o.getZf());
normalVertices.put(r.getXf()).put(r.getYf()).put(r.getZf());
// draw arrows of the normal vector
final double arrowLength = 0.75;
final double arrowAngle = Math.toRadians(20);
final Matrix3 matrix = new Matrix3();
final FloatBuffer buf = mesh.getMeshData().getVertexBuffer();
final ReadOnlyTransform trans = mesh.getWorldTransform();
final Vector3 v1 = new Vector3();
final Vector3 v2 = new Vector3();
BufferUtils.populateFromBuffer(v1, buf, 1);
BufferUtils.populateFromBuffer(v2, buf, 2);
Vector3 a = trans.applyForward(v1).subtract(trans.applyForward(v2), null).normalizeLocal();
a = a.crossLocal(normal);
Vector3 s = normal.clone();
s = matrix.fromAngleNormalAxis(arrowAngle, a).applyPost(s, null).multiplyLocal(arrowLength);
s = r.subtract(s, null);
normalVertices.put(r.getXf()).put(r.getYf()).put(r.getZf());
normalVertices.put(s.getXf()).put(s.getYf()).put(s.getZf());
s = normal.clone();
s = matrix.fromAngleNormalAxis(-arrowAngle, a).applyPost(s, null).multiplyLocal(arrowLength);
s = r.subtract(s, null);
normalVertices.put(r.getXf()).put(r.getYf()).put(r.getZf());
normalVertices.put(s.getXf()).put(s.getYf()).put(s.getZf());
// draw the angle between the sun beam and the normal vector
normal.cross(sunLocation, a);
sunAngle.setRange(o, o.add(sunLocation, null), o.add(normal, null), a);
sunAngle.setVisible(true);
normalVector.updateModelBound();
normalVector.setVisible(true);
}
use of com.ardor3d.math.type.ReadOnlyTransform in project energy3d by concord-consortium.
the class SolarPanel method drawSolarCellOutlines.
// draw solar cell outlines when in heat map mode
private void drawSolarCellOutlines() {
final FloatBuffer vertexBuffer = mesh.getMeshData().getVertexBuffer();
// do not use WorldTransform
final ReadOnlyTransform trans = mesh.getTransform();
// (0, 0)
final Vector3 p0 = trans.applyForward(new Vector3(vertexBuffer.get(3), vertexBuffer.get(4), vertexBuffer.get(5)));
// (1, 0)
final Vector3 p1 = trans.applyForward(new Vector3(vertexBuffer.get(6), vertexBuffer.get(7), vertexBuffer.get(8)));
// (0, 1)
final Vector3 p2 = trans.applyForward(new Vector3(vertexBuffer.get(0), vertexBuffer.get(1), vertexBuffer.get(2)));
final int bufferSize = (getNumberOfCellsInX() + getNumberOfCellsInY() + 2) * 6;
FloatBuffer vertices = solarCellOutlines.getMeshData().getVertexBuffer();
if (vertices.capacity() != bufferSize) {
vertices = BufferUtils.createFloatBuffer(bufferSize);
solarCellOutlines.getMeshData().setVertexBuffer(vertices);
} else {
vertices.rewind();
vertices.limit(vertices.capacity());
}
final int nx = rotated ? getNumberOfCellsInY() : getNumberOfCellsInX();
final int ny = rotated ? getNumberOfCellsInX() : getNumberOfCellsInY();
final Vector3 u = p1.subtract(p0, null).normalizeLocal();
final Vector3 v = p2.subtract(p0, null).normalizeLocal();
final double margin = 0.3;
final double dx = (p1.distance(p0) - margin * 2) / ny;
final double dy = (p2.distance(p0) - margin * 2) / nx;
final Vector3 ud = u.multiply(dx, null);
final Vector3 vd = v.multiply(dy, null);
final Vector3 um = u.multiply(margin, null);
final Vector3 vm = v.multiply(margin, null);
Vector3 p, q;
// draw x-lines
for (int i = 0; i <= nx; i++) {
q = vm.add(vd.multiply(i, null), null);
p = p0.add(um, null).addLocal(q);
vertices.put(p.getXf()).put(p.getYf()).put(p.getZf());
p = p1.subtract(um, null).addLocal(q);
vertices.put(p.getXf()).put(p.getYf()).put(p.getZf());
}
// draw y-lines
for (int i = 0; i <= ny; i++) {
q = um.add(ud.multiply(i, null), null);
p = p0.add(vm, null).addLocal(q);
vertices.put(p.getXf()).put(p.getYf()).put(p.getZf());
p = p2.subtract(vm, null).addLocal(q);
vertices.put(p.getXf()).put(p.getYf()).put(p.getZf());
}
solarCellOutlines.updateModelBound();
solarCellOutlines.setVisible(true);
}
Aggregations