@Override public Vector3 get3DPoint( final double gridX, final double gridY, final double height, final Vector3 store) { final Vector3 rVal = store != null ? store : new Vector3(); return rVal.set(gridX, gridY, height); }
@Override public void run() { while (true) { synchronized (lastestPosition) { currentPosition.set(lastestPosition); } // obtain the coordiante in geographic crs final ReadOnlyVector3 corrected = container.correctLocation(currentPosition); for (Double key : sensitives.keySet()) { final Object[] combination = sensitives.get(key); final Vector3 vect = (Vector3) combination[0]; final List<LocationSensitiveGraphic> graphics = (List<LocationSensitiveGraphic>) combination[1]; if (vect.distance(currentPosition) > key) { vect.set(currentPosition); for (LocationSensitiveGraphic gra : graphics) { gra.update(corrected); } } } try { // we dont need to consume much cpu sleep(100); } catch (InterruptedException ex) { Logging.getLogger(LocationSensitiveUpdater.class).log(Level.WARNING, null, ex); } } }
/** * update position (using current position and velocity), color (interpolating between start and * end color), size (interpolating between start and end size), spin (using parent's spin speed) * and current age of particle. If this particle's age is greater than its lifespan, it is set to * status DEAD. * * <p>Note that this only changes the parameters of the Particle, not the geometry the particle is * associated with. * * @param secondsPassed number of seconds passed since last update. * @return true if this particle is not ALIVE (in other words, if it is ready to be reused.) */ public boolean updateAndCheck(final double secondsPassed) { if (status != Status.Alive) { return true; } currentAge += secondsPassed * 1000; // add ms time to age if (currentAge > lifeSpan) { killParticle(); return true; } final Vector3 temp = Vector3.fetchTempInstance(); _position.addLocal(_velocity.multiply(secondsPassed * 1000f, temp)); Vector3.releaseTempInstance(temp); // get interpolated values from appearance ramp: parent.getRamp().getValuesAtAge(currentAge, lifeSpan, currColor, values, parent); // interpolate colors final int verts = ParticleSystem.getVertsForParticleType(type); for (int x = 0; x < verts; x++) { BufferUtils.setInBuffer( currColor, parent.getParticleGeometry().getMeshData().getColorBuffer(), startIndex + x); } // check for tex animation final int newTexIndex = parent.getTexAnimation().getTexIndexAtAge(currentAge, lifeSpan, parent); // Update tex coords if applicable if (currentTexIndex != newTexIndex) { // Only supported in Quad type for now. if (ParticleType.Quad.equals(parent.getParticleType())) { // determine side final float side = (float) Math.sqrt(parent.getTexQuantity()); int index = newTexIndex; if (index >= parent.getTexQuantity()) { index %= parent.getTexQuantity(); } // figure row / col final float row = side - (int) (index / side) - 1; final float col = index % side; // set texcoords final float sU = col / side, eU = (col + 1) / side; final float sV = row / side, eV = (row + 1) / side; final FloatBuffer texs = parent.getParticleGeometry().getMeshData().getTextureCoords(0).getBuffer(); texs.position(startIndex * 2); texs.put(eU).put(sV); texs.put(eU).put(eV); texs.put(sU).put(eV); texs.put(sU).put(sV); texs.clear(); } currentTexIndex = newTexIndex; } return false; }
@Override public boolean intersectsSphere(final BoundingSphere bs) { if (!Vector3.isValid(_center) || !Vector3.isValid(bs._center)) { return false; } final Vector3 diff = _compVect1.set(getCenter()).subtractLocal(bs.getCenter()); final double rsum = getRadius() + bs.getRadius(); return (diff.dot(diff) <= rsum * rsum); }
public void reconstruct(final Vector3 top, final Vector3 bottom, final double radius) { // our temp vars final Vector3 localTranslation = Vector3.fetchTempInstance(); final Vector3 capsuleUp = Vector3.fetchTempInstance(); // first make the capsule the right shape height = top.distance(bottom); this.radius = radius; setGeometryData(); // now orient it in space. localTranslation.set(_localTransform.getTranslation()); top.add(bottom, localTranslation).multiplyLocal(.5); // rotation that takes us from 0,1,0 to the unit vector described by top/center. top.subtract(localTranslation, capsuleUp).normalizeLocal(); final Matrix3 rotation = Matrix3.fetchTempInstance(); rotation.fromStartEndLocal(Vector3.UNIT_Y, capsuleUp); _localTransform.setRotation(rotation); Vector3.releaseTempInstance(localTranslation); Vector3.releaseTempInstance(capsuleUp); Matrix3.releaseTempInstance(rotation); updateWorldTransform(false); }
/** * Cause this particle to reset it's color, age and size per the parent's settings. status is set * to Status.Available. Location, velocity and lifespan are set as given. Actual geometry data is * not affected by this call, only particle params. * * @param velocity new initial particle velocity * @param position new initial particle position * @param lifeSpan new particle lifespan in ms */ public void init( final ReadOnlyVector3 velocity, final ReadOnlyVector3 position, final double lifeSpan) { this.lifeSpan = lifeSpan; _velocity.set(velocity); _position.set(position); currColor.set(parent.getStartColor()); currentAge = 0; status = Status.Available; values[VAL_CURRENT_SIZE] = parent.getStartSize(); }
public void killParticle() { setStatus(Status.Dead); final Vector3 tempVec3 = Vector3.fetchTempInstance(); final FloatBuffer vertexBuffer = parent.getParticleGeometry().getMeshData().getVertexBuffer(); BufferUtils.populateFromBuffer(tempVec3, vertexBuffer, startIndex); final int verts = ParticleSystem.getVertsForParticleType(type); for (int x = 1; x < verts; x++) { BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex + x); } Vector3.releaseTempInstance(tempVec3); }
public void read(final InputCapsule capsule) throws IOException { startIndex = capsule.readInt("startIndex", 0); _position.set((Vector3) capsule.readSavable("position", new Vector3(Vector3.ZERO))); status = capsule.readEnum("status", Status.class, Status.Available); lifeSpan = capsule.readDouble("lifeSpan", 0); currentAge = capsule.readInt("currentAge", 0); parent = (ParticleSystem) capsule.readSavable("parent", null); _velocity.set((Vector3) capsule.readSavable("velocity", new Vector3())); type = capsule.readEnum( "type", ParticleSystem.ParticleType.class, ParticleSystem.ParticleType.Quad); }
@Override public boolean intersectsBoundingBox(final BoundingBox bb) { if (!Vector3.isValid(_center) || !Vector3.isValid(bb._center)) { return false; } if (Math.abs(bb._center.getX() - getCenter().getX()) < getRadius() + bb.getXExtent() && Math.abs(bb._center.getY() - getCenter().getY()) < getRadius() + bb.getYExtent() && Math.abs(bb._center.getZ() - getCenter().getZ()) < getRadius() + bb.getZExtent()) { return true; } return false; }
protected RasterText createRowText( String name, double val, double x, double y, ReadOnlyColorRGBA color) { if (actualCoords) { val += origin.getYf(); } return (createText(name, val, x, y, color)); }
@Override public IntersectionRecord intersectsWhere(final ReadOnlyRay3 ray) { final Vector3 diff = ray.getOrigin().subtract(getCenter(), _compVect1); final double a = diff.dot(diff) - (getRadius() * getRadius()); double a1, discr, root; if (a <= 0.0) { // inside sphere a1 = ray.getDirection().dot(diff); discr = (a1 * a1) - a; root = Math.sqrt(discr); final double[] distances = new double[] {root - a1}; final Vector3[] points = new Vector3[] { ray.getDirection().multiply(distances[0], new Vector3()).addLocal(ray.getOrigin()) }; return new IntersectionRecord(distances, points); } a1 = ray.getDirection().dot(diff); if (a1 >= 0.0) { // No intersection return null; } discr = a1 * a1 - a; if (discr < 0.0) { return null; } else if (discr >= MathUtils.ZERO_TOLERANCE) { root = Math.sqrt(discr); final double[] distances = new double[] {-a1 - root, -a1 + root}; final Vector3[] points = new Vector3[] { ray.getDirection().multiply(distances[0], new Vector3()).addLocal(ray.getOrigin()), ray.getDirection().multiply(distances[1], new Vector3()).addLocal(ray.getOrigin()) }; final IntersectionRecord record = new IntersectionRecord(distances, points); return record; } final double[] distances = new double[] {-a1}; final Vector3[] points = new Vector3[] { ray.getDirection().multiply(distances[0], new Vector3()).addLocal(ray.getOrigin()) }; return new IntersectionRecord(distances, points); }
/** * Merges this sphere with the given OBB. * * @param volume The OBB to merge. * @return This sphere, after merging. */ private BoundingSphere mergeLocalOBB(final OrientedBoundingBox volume) { // check for infinite bounds to prevent NaN values... is so, return infinite bounds with center // at origin if (Double.isInfinite(getRadius()) || Vector3.isInfinite(volume.getExtent())) { setCenter(Vector3.ZERO); setRadius(Double.POSITIVE_INFINITY); return this; } // compute edge points from the obb if (!volume.correctCorners) { volume.computeCorners(); } final FloatBuffer mergeBuf = BufferUtils.createFloatBufferOnHeap(8 * 3); for (int i = 0; i < 8; i++) { mergeBuf.put((float) volume._vectorStore[i].getX()); mergeBuf.put((float) volume._vectorStore[i].getY()); mergeBuf.put((float) volume._vectorStore[i].getZ()); } // remember old radius and center final double oldRadius = getRadius(); final double oldCenterX = _center.getX(); final double oldCenterY = _center.getY(); final double oldCenterZ = _center.getZ(); // compute new radius and center from obb points computeFromPoints(mergeBuf); final double newCenterX = _center.getX(); final double newCenterY = _center.getY(); final double newCenterZ = _center.getZ(); final double newRadius = getRadius(); // restore old center and radius _center.set(oldCenterX, oldCenterY, oldCenterZ); setRadius(oldRadius); // merge obb points result merge(newRadius, _compVect4.set(newCenterX, newCenterY, newCenterZ), this); return this; }
/** * Calculates the distance from a spatial to the camera. Distance is a squared distance. * * @param spat Spatial to check distance. * @return Distance from Spatial to current context's camera. */ protected double distanceToCam(final Spatial spat) { if (spat._queueDistance != Double.NEGATIVE_INFINITY) { return spat._queueDistance; } final Camera cam = Camera.getCurrentCamera(); if (spat.getWorldBound() != null && Vector3.isValid(spat.getWorldBound().getCenter())) { spat._queueDistance = spat.getWorldBound().distanceToEdge(cam.getLocation()); } else { final ReadOnlyVector3 spatPosition = spat.getWorldTranslation(); if (!Vector3.isValid(spatPosition)) { spat._queueDistance = Double.POSITIVE_INFINITY; } else { spat._queueDistance = cam.getLocation().distance(spatPosition); } } return spat._queueDistance; }
@Override public void read(final Ardor3DImporter e) throws IOException { super.read(e); final InputCapsule cap = e.getCapsule(this); _swarmRangeSQ = cap.readDouble("swarmRangeSQ", DEFAULT_SWARM_RANGE_SQ); _deviance = cap.readDouble("deviance", DEFAULT_DEVIANCE); _turnSpeed = cap.readDouble("turnSpeed", DEFAULT_TURN_SPEED); _speedBump = cap.readDouble("speedBump", DEFAULT_SPEED_BUMP); _maxSpeed = cap.readDouble("maxSpeed", DEFAULT_MAX_SPEED); _swarmOffset.set((Vector3) cap.readSavable("swarmOffset", new Vector3())); }
@Override public void startWalk(final Ray3 walkRay) { // store ray _walkRay.set(walkRay); // simplify access to direction final ReadOnlyVector3 direction = _walkRay.getDirection(); // Move start point to grid space final Vector3 start = _walkRay.getOrigin().subtract(_gridOrigin, null); _gridLocation[0] = (int) MathUtils.floor(start.getX() / _gridSpacing.getX()); _gridLocation[1] = (int) MathUtils.floor(start.getY() / _gridSpacing.getY()); final double invDirX = 1.0 / direction.getX(); final double invDirY = 1.0 / direction.getY(); // Check which direction on the X world axis we are moving. if (direction.getX() > BresenhamZUpGridTracer.TOLERANCE) { _distToNextXIntersection = ((_gridLocation[0] + 1) * _gridSpacing.getX() - start.getX()) * invDirX; _distBetweenXIntersections = _gridSpacing.getX() * invDirX; _stepXDirection = 1; } else if (direction.getX() < -BresenhamZUpGridTracer.TOLERANCE) { _distToNextXIntersection = (start.getX() - _gridLocation[0] * _gridSpacing.getX()) * -direction.getX(); _distBetweenXIntersections = -_gridSpacing.getX() * invDirX; _stepXDirection = -1; } else { _distToNextXIntersection = Double.MAX_VALUE; _distBetweenXIntersections = Double.MAX_VALUE; _stepXDirection = 0; } // Check which direction on the Y world axis we are moving. if (direction.getY() > BresenhamZUpGridTracer.TOLERANCE) { _distToNextYIntersection = ((_gridLocation[1] + 1) * _gridSpacing.getY() - start.getY()) * invDirY; _distBetweenYIntersections = _gridSpacing.getY() * invDirY; _stepYDirection = 1; } else if (direction.getY() < -BresenhamZUpGridTracer.TOLERANCE) { _distToNextYIntersection = (start.getY() - _gridLocation[1] * _gridSpacing.getY()) * -direction.getY(); _distBetweenYIntersections = -_gridSpacing.getY() * invDirY; _stepYDirection = -1; } else { _distToNextYIntersection = Double.MAX_VALUE; _distBetweenYIntersections = Double.MAX_VALUE; _stepYDirection = 0; } // Reset some variables _rayLocation.set(start); _totalTravel = 0.0; _stepDirection = Direction.None; }
private Vector3 findFarthestIntersection( final List<? extends ReadOnlyVector3> wallUpperPoints, final ReadOnlyVector3 center, final Vector3 p) { double farthestDistance = 0; Vector3 farthestIntersection = null; final int n = wallUpperPoints.size(); for (int i = 0; i < n; i++) { final Vector3 intersect = Util.intersectLineSegments( center, p, wallUpperPoints.get(i), wallUpperPoints.get((i + 1) % n)); if (intersect != null) { final double d = intersect.distanceSquared(center); if (d > farthestDistance) { farthestDistance = d; farthestIntersection = intersect; } } } return farthestIntersection; }
/** * <code>averagePoints</code> selects the sphere center to be the average of the points and the * sphere radius to be the smallest value to enclose all points. * * @param points the list of points to contain. */ public void averagePoints(final Vector3[] points) { _center.set(points[0]); for (int i = 1; i < points.length; i++) { _center.addLocal(points[i]); } final double quantity = 1.0 / points.length; _center.multiplyLocal(quantity); double maxRadiusSqr = 0; for (int i = 0; i < points.length; i++) { final Vector3 diff = points[i].subtract(_center, _compVect1); final double radiusSqr = diff.lengthSquared(); if (radiusSqr > maxRadiusSqr) { maxRadiusSqr = radiusSqr; } } setRadius(Math.sqrt(maxRadiusSqr) + radiusEpsilon - 1f); }
@Override public boolean intersects(final ReadOnlyRay3 ray) { if (!Vector3.isValid(_center)) { return false; } final Vector3 diff = ray.getOrigin().subtract(getCenter(), _compVect1); final double radiusSquared = getRadius() * getRadius(); final double a = diff.dot(diff) - radiusSquared; if (a <= 0.0) { // in sphere return true; } // outside sphere final Vector3 dir = _compVect2.set(ray.getDirection()); final double b = dir.dot(diff); if (b >= 0.0) { return false; } return b * b >= a; }
@Override public void computeFromPrimitives( final MeshData data, final int section, final int[] indices, final int start, final int end) { if (end - start <= 0) { return; } final int vertsPerPrimitive = data.getIndexMode(section).getVertexCount(); final Vector3[] vertList = new Vector3[(end - start) * vertsPerPrimitive]; Vector3[] store = new Vector3[vertsPerPrimitive]; int count = 0; for (int i = start; i < end; i++) { store = data.getPrimitiveVertices(indices[i], section, store); for (int j = 0; j < vertsPerPrimitive; j++) { vertList[count++] = Vector3.fetchTempInstance().set(store[0]); } } averagePoints(vertList); for (int i = 0; i < vertList.length; i++) { Vector3.releaseTempInstance(vertList[i]); } }
/** * <code>merge</code> combines this sphere with a second bounding sphere. This new sphere contains * both bounding spheres and is returned. * * @param volume the sphere to combine with this sphere. * @return a new sphere */ @Override public BoundingVolume merge(final BoundingVolume volume) { if (volume == null) { return this; } switch (volume.getType()) { case Sphere: { final BoundingSphere sphere = (BoundingSphere) volume; final double temp_radius = sphere.getRadius(); final ReadOnlyVector3 tempCenter = sphere.getCenter(); final BoundingSphere rVal = new BoundingSphere(); return merge(temp_radius, tempCenter, rVal); } case AABB: { final BoundingBox box = (BoundingBox) volume; final Vector3 radVect = new Vector3(box.getXExtent(), box.getYExtent(), box.getZExtent()); final Vector3 tempCenter = box._center; final BoundingSphere rVal = new BoundingSphere(); return merge(radVect.length(), tempCenter, rVal); } case OBB: { final OrientedBoundingBox box = (OrientedBoundingBox) volume; final BoundingSphere rVal = (BoundingSphere) this.clone(null); return rVal.mergeLocalOBB(box); } default: return null; } }
@Override public void setPreviewPoint(final int x, final int y) { final EditState editState = new EditState(); if (editPointIndex == -1) { pickContainer(x, y, Wall.class); recalculateEditPoints = true; } else if (editPointIndex == 0) { final ReadOnlyVector3 base = getCenter(); final Vector3 p = Util.closestPoint(base, Vector3.UNIT_Z, x, y); if (p != null) { snapToGrid(p, getAbsPoint(editPointIndex), getGridSize()); height = Math.max(0, p.getZ() - base.getZ()); } } else if (editPointIndex == 1 || editPointIndex == 2) { final Vector3 hipDirection = container.getAbsPoint(2).subtractLocal(container.getAbsPoint(0)).normalizeLocal(); final Vector3 p = Util.closestPoint(getAbsPoint(0), hipDirection, x, y); if (p != null) { // snapToGrid(p, getAbsPoint(editPointIndex), getGridSize(), false); if (insideWallsPolygon(p)) points.get(editPointIndex).set(toRelative(p)); } } postEdit(editState); }
@Override public void applyFilter(final InteractManager manager) { final SpatialState state = manager.getSpatialState(); final ReadOnlyVector3 scale = state.getTransform().getScale(); final double x = MathUtils.clamp(scale.getX(), _minScale.getX(), _maxScale.getX()); final double y = MathUtils.clamp(scale.getY(), _minScale.getY(), _maxScale.getY()); final double z = MathUtils.clamp(scale.getZ(), _minScale.getZ(), _maxScale.getZ()); state.getTransform().setScale(x, y, z); }
@Override public void setInMotion(boolean inMotion, ReadOnlyVector3 pickPosition) { super.setInMotion(inMotion, pickPosition); if (inMotion) { pickPosition.subtract(getWorldTranslation(), offset); } else { if (actualCoords) { origin = new Vector3(getWorldTranslation()); buildText(); updateGeometricState(0, true); updateWorldTransform(true); updateWorldBound(true); } offset.set(Vector3.ZERO); } }
private BoundingVolume merge( final double otherRadius, final ReadOnlyVector3 otherCenter, final BoundingSphere store) { // check for infinite bounds... is so, return infinite bounds with center at origin if (Double.isInfinite(otherRadius) || Double.isInfinite(getRadius())) { store.setCenter(Vector3.ZERO); store.setRadius(Double.POSITIVE_INFINITY); return store; } final Vector3 diff = otherCenter.subtract(_center, _compVect1); final double lengthSquared = diff.lengthSquared(); final double radiusDiff = otherRadius - getRadius(); final double radiusDiffSqr = radiusDiff * radiusDiff; // if one sphere wholly contains the other if (radiusDiffSqr >= lengthSquared) { // if we contain the other if (radiusDiff <= 0.0) { store.setCenter(_center); store.setRadius(_radius); return store; } // else the other contains us else { store.setCenter(otherCenter); store.setRadius(otherRadius); return store; } } // distance between sphere centers final double length = Math.sqrt(lengthSquared); // init a center var using our center final Vector3 rCenter = _compVect2; rCenter.set(_center); // if our centers are at least a tiny amount apart from each other... if (length > MathUtils.EPSILON) { // place us between the two centers, weighted by radii final double coeff = (length + radiusDiff) / (2.0 * length); rCenter.addLocal(diff.multiplyLocal(coeff)); } // set center on our resulting bounds store.setCenter(rCenter); // Set radius store.setRadius(0.5 * (length + getRadius() + otherRadius)); return store; }
@Override public void apply(final double dt, final Particle particle, final int index) { if (_wanderRadius == 0 && _wanderDistance == 0 && _wanderJitter == 0) { return; } final Vector3 wanderTarget = _wanderTargets.get(index); wanderTarget.addLocal(calcNewJitter(), calcNewJitter(), calcNewJitter()); wanderTarget.normalizeLocal(); wanderTarget.multiplyLocal(_wanderRadius); _workVect.set(particle.getVelocity()).normalizeLocal().multiplyLocal(_wanderDistance); _workVect.addLocal(wanderTarget).normalizeLocal(); _workVect.multiplyLocal(particle.getVelocity().length()); particle.getVelocity().set(_workVect); }
@Override public void apply(final double dt, final Particle particle, final int index) { final Vector3 pVelocity = particle.getVelocity(); // determine if the particle is in the inner or outer zone final double pDist = particle.getPosition().distanceSquared(_swarmPoint); final Vector3 workVect = Vector3.fetchTempInstance(); final Vector3 workVect2 = Vector3.fetchTempInstance(); final Matrix3 workMat = Matrix3.fetchTempInstance(); workVect.set(_swarmPoint).subtractLocal(particle.getPosition()).normalizeLocal(); workVect2.set(pVelocity).normalizeLocal(); if (pDist > _swarmRangeSQ) { // IN THE OUTER ZONE... // Determine if the angle between particle velocity and a vector to // the swarmPoint is less than the accepted deviance final double angle = workVect.smallestAngleBetween(workVect2); if (angle < _deviance) { // if it is, increase the speed speedBump over time if (pVelocity.lengthSquared() < maxSpeedSQ) { final double change = _speedBump * dt; workVect2.multiplyLocal(change); // where workVector2 = pVelocity.normalizeLocal() pVelocity.addLocal(workVect2); } } else { final Vector3 axis = workVect2.crossLocal(workVect); // if it is not, shift the velocity to bring it back in line if ((Double.doubleToLongBits(pVelocity.lengthSquared()) & 0x1d) != 0) { workMat.fromAngleAxis(_turnSpeed * dt, axis); } else { workMat.fromAngleAxis(-_turnSpeed * dt, axis); } workMat.applyPost(pVelocity, pVelocity); } } else { final Vector3 axis = workVect2.crossLocal(workVect); // IN THE INNER ZONE... // Alter the heading based on how fast we are going if ((index & 0x1f) != 0) { workMat.fromAngleAxis(_turnSpeed * dt, axis); } else { workMat.fromAngleAxis(-_turnSpeed * dt, axis); } workMat.applyPost(pVelocity, pVelocity); } Vector3.releaseTempInstance(workVect); Vector3.releaseTempInstance(workVect2); Matrix3.releaseTempInstance(workMat); }
@Override public void prepare(final ParticleSystem system) { super.prepare(system); _swarmPoint.set(system.getOriginCenter()).addLocal(_swarmOffset); }
public SwarmInfluence(final ReadOnlyVector3 offset, final double swarmRange) { super(); _swarmRangeSQ = swarmRange * swarmRange; _swarmOffset.set(offset); }
public void setSwarmOffset(final ReadOnlyVector3 offset) { _swarmPoint.set(offset); }
public BoundingVolume(final Vector3 center) { _center.set(center); }