@Override protected void processRoofEditPoints(final List<? extends ReadOnlyVector3> wallUpperPoints) { final ReadOnlyVector3 center = getCenter(); if (recalculateEditPoints) { recalculateEditPoints = false; points.get(0).set(toRelative(center)); // if (editPointIndex == -1) { recalculateEditPoints = false; points.add(toRelative(getCenter())); final Vector3 hipDirection = container.getAbsPoint(2).subtractLocal(container.getAbsPoint(0)).normalizeLocal(); Vector3 point1 = findFarthestIntersection( wallUpperPoints, center, center.add(hipDirection.multiply(-1000, null), null)); Vector3 point2 = findFarthestIntersection( wallUpperPoints, center, center.add(hipDirection.multiply(1000, null), null)); if (point1 == null) point1 = center.clone(); if (point2 == null) point2 = center.clone(); point1.addLocal(hipDirection.multiply(point1.distance(center) * 0.5, null)); point2.addLocal(hipDirection.multiply(-point2.distance(center) * 0.5, null)); points.get(1).set(toRelative(point1)); points.get(2).set(toRelative(point2)); computeHeight(wallUpperPoints); applyHeight(); // } } else { applyHeight(); } }
@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); }
/** * 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; }
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) { 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); }