use of com.ardor3d.math.Matrix3 in project energy3d by concord-consortium.
the class Wall method flatten.
@Override
public void flatten(final double flattenTime) {
final ReadOnlyVector3 n = getNormal();
double angle = n.smallestAngleBetween(Vector3.NEG_UNIT_Y);
if (n.dot(Vector3.UNIT_X) < 0) {
angle = -angle;
}
root.setRotation((new Matrix3().fromAngles(0, 0, -flattenTime * angle)));
super.flatten(flattenTime);
for (final HousePart part : children) {
if (!part.isPrintable()) {
part.getRoot().setTransform(root.getTransform());
part.getRoot().updateGeometricState(0);
}
}
}
use of com.ardor3d.math.Matrix3 in project energy3d by concord-consortium.
the class CameraControl method getCurrentExtent.
// the extent that depends on the camera orientation (not a perfect solution)
private static double getCurrentExtent() {
double extent = 10;
final BoundingVolume volume = Scene.getRoot().getWorldBound();
if (volume instanceof BoundingBox) {
final BoundingBox box = (BoundingBox) volume;
final ReadOnlyVector3 cameraDirection = SceneManager.getInstance().getCamera().getDirection();
final Vector3 e1 = box.getExtent(null);
final double extent1 = Math.abs(e1.cross(cameraDirection, null).length());
final Vector3 e2 = new Matrix3().applyRotationZ(Math.PI / 2).applyPost(e1, null);
final double extent2 = Math.abs(e2.cross(cameraDirection, null).length());
extent = 0.45 * (extent1 + extent2);
}
return extent;
}
use of com.ardor3d.math.Matrix3 in project energy3d by concord-consortium.
the class ParabolicDish method drawMesh.
@Override
protected void drawMesh() {
if (container == null) {
return;
}
getEditPointShape(0).setDefaultColor(ColorRGBA.ORANGE);
normal = Heliodon.getInstance().computeSunLocation(Heliodon.getInstance().getCalendar()).normalizeLocal();
if (Util.isEqual(normal, Vector3.UNIT_Z)) {
normal = new Vector3(-0.001, 0, 1).normalizeLocal();
}
final double annotationScale = Scene.getInstance().getAnnotationScale();
dish.setRimRadius(rimRadius / annotationScale);
dish.updateModelBound();
baseZ = container instanceof Foundation ? container.getHeight() : container.getPoints().get(0).getZ();
points.get(0).setZ(baseZ + baseHeight);
final FloatBuffer vertexBuffer = mesh.getMeshData().getVertexBuffer();
FloatBuffer outlineBuffer = outlines.getMeshData().getVertexBuffer();
final int vertexCount = vertexBuffer.limit() / 3;
final Vector3 center = getAbsPoint(0);
final int rSamples = dish.getRSamples() + 1;
final int zSamples = dish.getZSamples() - 1;
final int outlineBufferSize = 6 * (rSamples * 3 + zSamples * nrib);
if (outlineBuffer.capacity() < outlineBufferSize) {
outlineBuffer = BufferUtils.createFloatBuffer(outlineBufferSize);
outlines.getMeshData().setVertexBuffer(outlineBuffer);
} else {
outlineBuffer.rewind();
outlineBuffer.limit(outlineBufferSize);
}
// draw the rim line
int i3;
for (int i = vertexCount - rSamples * 2; i < vertexCount - 1 - rSamples; i++) {
i3 = i * 3;
outlineBuffer.put(vertexBuffer.get(i3)).put(vertexBuffer.get(i3 + 1)).put(vertexBuffer.get(i3 + 2));
outlineBuffer.put(vertexBuffer.get(i3 + 3)).put(vertexBuffer.get(i3 + 4)).put(vertexBuffer.get(i3 + 5));
}
for (int i = (vertexCount - rSamples * 3) / 4; i < (vertexCount + rSamples) / 4; i++) {
i3 = i * 3;
outlineBuffer.put(vertexBuffer.get(i3)).put(vertexBuffer.get(i3 + 1)).put(vertexBuffer.get(i3 + 2) + zOffset);
outlineBuffer.put(vertexBuffer.get(i3 + 3)).put(vertexBuffer.get(i3 + 4)).put(vertexBuffer.get(i3 + 5) + zOffset);
}
// draw the rib lines
double xi, yi, zi, angle;
final double delta = dish.getRimRadius() * 2.0 / (zSamples + 1);
double cos, sin;
for (int i = 0; i < zSamples; i++) {
for (int j = 0; j < nrib; j++) {
angle = Math.PI / nrib * j;
cos = Math.cos(angle);
sin = Math.sin(angle);
xi = cos * (dish.getRimRadius() - delta * (i + 0.5));
yi = sin * (dish.getRimRadius() - delta * (i + 0.5));
zi = (xi * xi + yi * yi) / (dish.getCurvatureParameter() * dish.getCurvatureParameter());
outlineBuffer.put((float) xi).put((float) yi).put((float) zi + zOffset);
xi -= cos * delta;
yi -= sin * delta;
zi = (xi * xi + yi * yi) / (dish.getCurvatureParameter() * dish.getCurvatureParameter());
outlineBuffer.put((float) xi).put((float) yi).put((float) zi + zOffset);
}
}
final Matrix3 rotation = new Matrix3().lookAt(normal, Vector3.UNIT_Y);
mesh.setRotation(rotation);
mesh.setTranslation(center);
mesh.updateModelBound();
dishBack.setRotation(rotation);
dishBack.setTranslation(mesh.getTranslation());
outlines.setRotation(rotation);
outlines.setTranslation(mesh.getTranslation());
outlines.updateModelBound();
// slightly shorter so that the pole won't penetrate the surface of the dish
post.setHeight(baseHeight - 0.5 * post.getRadius());
final Vector3 p = center.clone();
p.setZ(baseZ + post.getHeight() / 2);
post.setTranslation(p);
final double flScaled = focalLength / annotationScale;
receiver.setRotation(rotation);
receiver.setTranslation(center.clone().addLocal(normal.multiply(flScaled, null)));
switch(structureType) {
case STRUCTURE_CENTRAL_POLE:
duct.setHeight(flScaled + receiver.getHeight());
duct.setRotation(rotation);
duct.setTranslation(center.clone().addLocal(normal.multiply(flScaled * 0.5, null)));
break;
case STRUCTURE_TRIPOD:
final Vector3 vi = new Vector3();
final Vector3 v0 = new Vector3(0, 0, flScaled);
for (int i = 0; i < 3; i++) {
angle = 2 * Math.PI / 3 * i;
xi = dish.getRimRadius() * 0.98 * Math.cos(angle);
yi = dish.getRimRadius() * 0.98 * Math.sin(angle);
zi = (xi * xi + yi * yi) / (dish.getCurvatureParameter() * dish.getCurvatureParameter());
vi.set(xi, yi, zi);
tripod[i].setHeight(vi.distance(v0));
final Vector3 ui = rotation.applyPost(vi, null);
final Vector3 u0 = rotation.applyPost(v0, null);
tripod[i].setTranslation(center.add(ui.addLocal(u0).multiplyLocal(0.5), null));
tripod[i].setRotation(rotation.multiply(new Matrix3().fromStartEndLocal(Vector3.UNIT_Z, vi.subtract(v0, null).normalizeLocal()), null));
}
duct.setHeight(receiver.getHeight());
duct.setRotation(mesh.getRotation());
duct.setTranslation(center.clone().subtractLocal(normal.multiply(duct.getHeight() * 0.5, null)));
break;
}
if (bloomRenderPassReceiver == null) {
bloomRenderPassReceiver = new BloomRenderPass(SceneManager.getInstance().getCamera(), 10);
bloomRenderPassReceiver.setBlurIntensityMultiplier(0.5f);
// bloomRenderPassTube.setNrBlurPasses(2);
SceneManager.getInstance().getPassManager().add(bloomRenderPassReceiver);
}
if (!bloomRenderPassReceiver.contains(receiver)) {
bloomRenderPassReceiver.add(receiver);
}
if (beamsVisible) {
drawSunBeam();
}
updateLabel();
CollisionTreeManager.INSTANCE.removeCollisionTree(mesh);
root.updateGeometricState(0);
}
use of com.ardor3d.math.Matrix3 in project energy3d by concord-consortium.
the class ParabolicTrough method drawMesh.
@Override
protected void drawMesh() {
if (container == null) {
return;
}
getEditPointShape(0).setDefaultColor(ColorRGBA.ORANGE);
final double az = Math.toRadians(relativeAzimuth);
final double annotationScale = Scene.getInstance().getAnnotationScale();
reflector.setSize(apertureWidth / annotationScale, troughLength / annotationScale);
reflector.setSemilatusRectum(semilatusRectum / annotationScale);
reflector.updateModelBound();
baseZ = container instanceof Foundation ? container.getHeight() : container.getPoints().get(0).getZ();
points.get(0).setZ(baseZ + baseHeight);
absorber.setHeight(reflector.getHeight());
absorberEnd1.setHeight(0.5 * reflector.getSemilatusRectum());
absorberEnd2.setHeight(absorberEnd1.getHeight());
if (detailed) {
absorberCore.setHeight(reflector.getHeight() - 1);
absorberEnd1Core.setHeight(absorberEnd1.getHeight() - 1);
absorberEnd2Core.setHeight(absorberEnd2.getHeight() - 1);
}
final FloatBuffer vertexBuffer = mesh.getMeshData().getVertexBuffer();
FloatBuffer outlineBuffer = outlines.getMeshData().getVertexBuffer();
FloatBuffer steelFrameBuffer = steelFrame.getMeshData().getVertexBuffer();
final int vertexCount = vertexBuffer.limit() / 6;
// number of vertex coordinates on each end
final int j = vertexCount * 3;
// start index of middle point on end 1
final int j1 = (j - 3) / 2;
// start index of middle point on end 2
final int j2 = j + j1;
// middle point on end 1
final Vector3 p1 = new Vector3(vertexBuffer.get(j1), vertexBuffer.get(j1 + 1), vertexBuffer.get(j1 + 2));
// middle point on end 2
final Vector3 p2 = new Vector3(vertexBuffer.get(j2), vertexBuffer.get(j2 + 1), vertexBuffer.get(j2 + 2));
// normal in the direction of cylinder axis
final Vector3 pd = p2.subtract(p1, null).normalizeLocal();
final double halfLength = troughLength * 0.5;
final Vector3 center = getAbsPoint(0);
final int nModules = Math.max(1, getNumberOfModules());
// 12 is for the two lateral lines
final int outlineBufferSize = 6 * (vertexCount - 1) * (nModules + 2) + 12;
if (outlineBuffer.capacity() < outlineBufferSize) {
outlineBuffer = BufferUtils.createFloatBuffer(outlineBufferSize);
outlines.getMeshData().setVertexBuffer(outlineBuffer);
} else {
outlineBuffer.rewind();
outlineBuffer.limit(outlineBufferSize);
}
// draw parabolic lines of the two end faces
int i3;
for (int i = 0; i < vertexCount - 1; i++) {
i3 = i * 3;
outlineBuffer.put(vertexBuffer.get(i3)).put(vertexBuffer.get(i3 + 1)).put(vertexBuffer.get(i3 + 2));
outlineBuffer.put(vertexBuffer.get(i3 + 3)).put(vertexBuffer.get(i3 + 4)).put(vertexBuffer.get(i3 + 5));
outlineBuffer.put(vertexBuffer.get(j + i3)).put(vertexBuffer.get(j + i3 + 1)).put(vertexBuffer.get(j + i3 + 2));
outlineBuffer.put(vertexBuffer.get(j + i3 + 3)).put(vertexBuffer.get(j + i3 + 4)).put(vertexBuffer.get(j + i3 + 5));
}
// draw lateral lines connecting the two end faces
outlineBuffer.put(vertexBuffer.get(0)).put(vertexBuffer.get(1)).put(vertexBuffer.get(2));
outlineBuffer.put(vertexBuffer.get(j)).put(vertexBuffer.get(j + 1)).put(vertexBuffer.get(j + 2));
outlineBuffer.put(vertexBuffer.get(j - 3)).put(vertexBuffer.get(j - 2)).put(vertexBuffer.get(j - 1));
outlineBuffer.put(vertexBuffer.get(2 * j - 3)).put(vertexBuffer.get(2 * j - 2)).put(vertexBuffer.get(2 * j - 1));
// draw seam lines between units
if (nModules > 1) {
// if there is only one module, don't draw
for (int k = 1; k < nModules; k++) {
final double ua = k * moduleLength / annotationScale;
for (int i = 0; i < vertexCount - 1; i++) {
i3 = i * 3;
final Vector3 v1 = new Vector3(vertexBuffer.get(i3), vertexBuffer.get(i3 + 1), vertexBuffer.get(i3 + 2));
final Vector3 v2 = new Vector3(vertexBuffer.get(i3 + 3), vertexBuffer.get(i3 + 4), vertexBuffer.get(i3 + 5));
v1.addLocal(0, ua, 0);
v2.addLocal(0, ua, 0);
outlineBuffer.put(v1.getXf()).put(v1.getYf()).put(v1.getZf());
outlineBuffer.put(v2.getXf()).put(v2.getYf()).put(v2.getZf());
}
}
}
outlineBuffer.limit(vertexCount * 12 + (vertexCount - 1) * 6 * (nModules - 1));
// draw steel frame lines
final int steelBufferSize = nModules * 6;
if (steelFrameBuffer.capacity() < steelBufferSize) {
steelFrameBuffer = BufferUtils.createFloatBuffer(steelBufferSize);
steelFrame.getMeshData().setVertexBuffer(steelFrameBuffer);
} else {
steelFrameBuffer.rewind();
steelFrameBuffer.limit(steelBufferSize);
}
modulesRoot.detachAllChildren();
if (nModules > 1) {
final Vector3 qd = new Matrix3().applyRotationZ(-az).applyPost(pd, null);
for (double u = moduleLength; u < troughLength; u += moduleLength) {
final double step = (u - halfLength) / annotationScale;
final Vector3 p = pd.multiply(step, null);
steelFrameBuffer.put(p.getXf()).put(p.getYf()).put(p.getZf());
steelFrameBuffer.put(p.getXf()).put(p.getYf()).put((float) (p.getZ() + 0.5 * reflector.getSemilatusRectum()));
final Vector3 q = qd.multiply(step, null);
addPole(q.addLocal(center), baseHeight, baseZ);
}
steelFrameBuffer.limit((nModules - 1) * 6);
steelFrame.getSceneHints().setCullHint(CullHint.Inherit);
} else {
addPole(center, baseHeight, baseZ);
// if there is only one module, don't draw frames
steelFrame.getSceneHints().setCullHint(CullHint.Always);
}
modulesRoot.getSceneHints().setCullHint(CullHint.Inherit);
final Vector3 sunDirection = Heliodon.getInstance().computeSunLocation(Heliodon.getInstance().getCalendar()).normalizeLocal();
final Vector3 rotationAxis = new Vector3(Math.sin(az), Math.cos(az), 0);
final double axisSunDot = sunDirection.dot(rotationAxis);
// avoid singularity when the direction of the sun is perpendicular to the axis of the trough
rotationAxis.multiplyLocal(Util.isZero(axisSunDot) ? 0.001 : axisSunDot);
normal = sunDirection.subtractLocal(rotationAxis).normalizeLocal();
if (Util.isEqual(normal, Vector3.UNIT_Z)) {
normal = new Vector3(-0.001, 0, 1).normalizeLocal();
}
final Matrix3 rotation = new Matrix3().lookAt(normal, rotationAxis);
mesh.setRotation(rotation);
mesh.setTranslation(center);
reflectorBack.setRotation(rotation);
reflectorBack.setTranslation(mesh.getTranslation());
outlines.setRotation(rotation);
outlines.setTranslation(mesh.getTranslation());
final Vector3 axis = rotationAxis.cross(Vector3.UNIT_Z, null);
absorber.setRotation(new Matrix3().fromAngleAxis(Math.acos(rotationAxis.dot(Vector3.UNIT_Z)), axis));
absorber.setTranslation(mesh.getTranslation().add(normal.multiply(0.5 * reflector.getSemilatusRectum(), null), null));
final Vector3 endShift = normal.multiply(0.5 * absorberEnd1.getHeight(), null);
absorberEnd1.setTranslation(mesh.getTranslation().add(rotation.applyPost(p1, null).add(endShift, null), null));
absorberEnd2.setTranslation(mesh.getTranslation().add(rotation.applyPost(p2, null).add(endShift, null), null));
absorberEnd1.setRotation(rotation);
absorberEnd2.setRotation(rotation);
steelFrame.setRotation(rotation);
steelFrame.setTranslation(mesh.getTranslation());
if (detailed) {
absorberCore.setRotation(absorber.getRotation());
absorberCore.setTranslation(absorber.getTranslation());
absorberEnd1Core.setTranslation(absorberEnd1.getTranslation());
absorberEnd2Core.setTranslation(absorberEnd2.getTranslation());
absorberEnd1Core.setRotation(rotation);
absorberEnd2Core.setRotation(rotation);
}
mesh.updateModelBound();
outlines.updateModelBound();
steelFrame.updateModelBound();
absorber.updateModelBound();
absorberEnd1.updateModelBound();
absorberEnd2.updateModelBound();
if (bloomRenderPassTube == null) {
bloomRenderPassTube = new BloomRenderPass(SceneManager.getInstance().getCamera(), 10);
bloomRenderPassTube.setBlurIntensityMultiplier(0.75f);
// bloomRenderPassTube.setNrBlurPasses(2);
SceneManager.getInstance().getPassManager().add(bloomRenderPassTube);
}
if (!bloomRenderPassTube.contains(absorber)) {
bloomRenderPassTube.add(absorber);
}
if (beamsVisible) {
drawSunBeam();
}
updateLabel();
CollisionTreeManager.INSTANCE.removeCollisionTree(mesh);
root.updateGeometricState(0);
}
use of com.ardor3d.math.Matrix3 in project energy3d by concord-consortium.
the class SolarPanel method setNormal.
// ensure that a solar panel in special cases (on a flat roof or at a tilt angle) will have correct orientation
private void setNormal(final double angle, final double azimuth) {
final Foundation foundation = getTopContainer();
Vector3 v = foundation.getAbsPoint(0);
// x direction
final Vector3 vx = foundation.getAbsPoint(2).subtractLocal(v);
// y direction
final Vector3 vy = foundation.getAbsPoint(1).subtractLocal(v);
final Matrix3 m = new Matrix3().applyRotationZ(-azimuth);
final Vector3 v1 = m.applyPost(vx, null);
final Vector3 v2 = m.applyPost(vy, null);
v = new Matrix3().fromAngleAxis(angle, v1).applyPost(v2, null);
if (v.getZ() < 0) {
v.negateLocal();
}
normal = v.normalizeLocal();
}
Aggregations