Example #1
0
  @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);
  }
Example #2
0
  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;
  }
Example #3
0
 @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);
 }
Example #4
0
  /**
   * Update the vertices for this particle, taking size, spin and viewer into consideration. In the
   * case of particle type ParticleType.GeomMesh, the original triangle normal is maintained rather
   * than rotating it to face the camera or parent vectors.
   *
   * @param cam Camera to use in determining viewer aspect. If null, or if parent is not set to
   *     camera facing, parent's left and up vectors are used.
   */
  public void updateVerts(final Camera cam) {
    final double orient = parent.getParticleOrientation() + values[VAL_CURRENT_SPIN];
    final double currSize = values[VAL_CURRENT_SIZE];

    if (type == ParticleSystem.ParticleType.GeomMesh
        || type == ParticleSystem.ParticleType.Point) {; // nothing to do
    } else if (cam != null && parent.isCameraFacing()) {
      final ReadOnlyVector3 camUp = cam.getUp();
      final ReadOnlyVector3 camLeft = cam.getLeft();
      final ReadOnlyVector3 camDir = cam.getDirection();
      if (parent.isVelocityAligned()) {
        bbX.set(_velocity).normalizeLocal().multiplyLocal(currSize);
        camDir.cross(bbX, bbY).normalizeLocal().multiplyLocal(currSize);
      } else if (orient == 0) {
        bbX.set(camLeft).multiplyLocal(currSize);
        bbY.set(camUp).multiplyLocal(currSize);
      } else {
        final double cA = MathUtils.cos(orient) * currSize;
        final double sA = MathUtils.sin(orient) * currSize;
        bbX.set(camLeft)
            .multiplyLocal(cA)
            .addLocal(camUp.getX() * sA, camUp.getY() * sA, camUp.getZ() * sA);
        bbY.set(camLeft)
            .multiplyLocal(-sA)
            .addLocal(camUp.getX() * cA, camUp.getY() * cA, camUp.getZ() * cA);
      }
    } else {
      bbX.set(parent.getLeftVector()).multiplyLocal(0);
      bbY.set(parent.getUpVector()).multiplyLocal(0);
    }

    final Vector3 tempVec3 = Vector3.fetchTempInstance();
    final FloatBuffer vertexBuffer = parent.getParticleGeometry().getMeshData().getVertexBuffer();
    switch (type) {
      case Quad:
        {
          _position.subtract(bbX, tempVec3).subtractLocal(bbY);
          BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex + 0);

          _position.subtract(bbX, tempVec3).addLocal(bbY);
          BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex + 1);

          _position.add(bbX, tempVec3).addLocal(bbY);
          BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex + 2);

          _position.add(bbX, tempVec3).subtractLocal(bbY);
          BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex + 3);
          break;
        }
      case GeomMesh:
        {
          final Quaternion tempQuat = Quaternion.fetchTempInstance();
          final ReadOnlyVector3 norm = triModel.getNormal();
          if (orient != 0) {
            tempQuat.fromAngleNormalAxis(orient, norm);
          }

          for (int x = 0; x < 3; x++) {
            if (orient != 0) {
              tempQuat.apply(triModel.get(x), tempVec3);
            } else {
              tempVec3.set(triModel.get(x));
            }
            tempVec3.multiplyLocal(currSize).addLocal(_position);
            BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex + x);
          }
          Quaternion.releaseTempInstance(tempQuat);
          break;
        }
      case Triangle:
        {
          _position
              .subtract(3 * bbX.getX(), 3 * bbX.getY(), 3 * bbX.getZ(), tempVec3)
              .subtractLocal(bbY);
          BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex + 0);

          _position.add(bbX, tempVec3).addLocal(3 * bbY.getX(), 3 * bbY.getY(), 3 * bbY.getZ());
          BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex + 1);

          _position.add(bbX, tempVec3).subtractLocal(bbY);
          BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex + 2);
          break;
        }
      case Line:
        {
          _position.subtract(bbX, tempVec3);
          BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex);

          _position.add(bbX, tempVec3);
          BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex + 1);
          break;
        }
      case Point:
        {
          BufferUtils.setInBuffer(_position, vertexBuffer, startIndex);
          break;
        }
    }
    Vector3.releaseTempInstance(tempVec3);
  }
Example #5
0
  private void setGeometryData() {
    final FloatBuffer verts = _meshData.getVertexBuffer();
    final FloatBuffer norms = _meshData.getNormalBuffer();
    final FloatBuffer texs = _meshData.getTextureBuffer(0);
    verts.rewind();
    norms.rewind();
    texs.rewind();

    // generate geometry
    final double inverseRadial = 1.0 / radialSamples;
    final double inverseSphere = 1.0 / sphereSamples;
    final double halfHeight = 0.5 * height;

    // Generate points on the unit circle to be used in computing the mesh
    // points on a cylinder slice.
    final double[] sin = new double[radialSamples + 1];
    final double[] cos = new double[radialSamples + 1];

    for (int radialCount = 0; radialCount < radialSamples; radialCount++) {
      final double angle = MathUtils.TWO_PI * inverseRadial * radialCount;
      cos[radialCount] = MathUtils.cos(angle);
      sin[radialCount] = MathUtils.sin(angle);
    }
    sin[radialSamples] = sin[0];
    cos[radialSamples] = cos[0];

    final Vector3 tempA = new Vector3();

    // top point.
    verts.put(0).put((float) (radius + halfHeight)).put(0);
    norms.put(0).put(1).put(0);
    texs.put(1).put(1);

    // generating the top dome.
    for (int i = 0; i < sphereSamples; i++) {
      final double center = radius * (1 - (i + 1) * (inverseSphere));
      final double lengthFraction = (center + height + radius) / (height + 2 * radius);

      // compute radius of slice
      final double fSliceRadius = Math.sqrt(Math.abs(radius * radius - center * center));

      for (int j = 0; j <= radialSamples; j++) {
        final Vector3 kRadial = tempA.set(cos[j], 0, sin[j]);
        kRadial.multiplyLocal(fSliceRadius);
        verts.put(kRadial.getXf()).put((float) (center + halfHeight)).put(kRadial.getZf());
        kRadial.setY(center);
        kRadial.normalizeLocal();
        norms.put(kRadial.getXf()).put(kRadial.getYf()).put(kRadial.getZf());
        final double radialFraction = 1 - (j * inverseRadial); // in [0,1)
        texs.put((float) radialFraction).put((float) lengthFraction);
      }
    }

    // generate cylinder... but no need to add points for first and last
    // samples as they are already part of domes.
    for (int i = 1; i < axisSamples; i++) {
      final double center = halfHeight - (i * height / axisSamples);
      final double lengthFraction = (center + halfHeight + radius) / (height + 2 * radius);

      for (int j = 0; j <= radialSamples; j++) {
        final Vector3 kRadial = tempA.set(cos[j], 0, sin[j]);
        kRadial.multiplyLocal(radius);
        verts.put(kRadial.getXf()).put((float) center).put(kRadial.getZf());
        kRadial.normalizeLocal();
        norms.put(kRadial.getXf()).put(kRadial.getYf()).put(kRadial.getZf());
        final double radialFraction = 1 - (j * inverseRadial); // in [0,1)
        texs.put((float) radialFraction).put((float) lengthFraction);
      }
    }

    // generating the bottom dome.
    for (int i = 0; i < sphereSamples; i++) {
      final double center = i * (radius / sphereSamples);
      final double lengthFraction = (radius - center) / (height + 2 * radius);

      // compute radius of slice
      final double fSliceRadius = Math.sqrt(Math.abs(radius * radius - center * center));

      for (int j = 0; j <= radialSamples; j++) {
        final Vector3 kRadial = tempA.set(cos[j], 0, sin[j]);
        kRadial.multiplyLocal(fSliceRadius);
        verts.put(kRadial.getXf()).put((float) (-center - halfHeight)).put(kRadial.getZf());
        kRadial.setY(-center);
        kRadial.normalizeLocal();
        norms.put(kRadial.getXf()).put(kRadial.getYf()).put(kRadial.getZf());
        final double radialFraction = 1 - (j * inverseRadial); // in [0,1)
        texs.put((float) radialFraction).put((float) lengthFraction);
      }
    }

    // bottom point.
    verts.put(0).put((float) (-radius - halfHeight)).put(0);
    norms.put(0).put(-1).put(0);
    texs.put(0).put(0);
  }
Example #6
0
  private void setGeometryData() {
    // generate geometry
    final double inverseRadial = 1.0 / _radialSamples;
    final double inverseAxisLess = 1.0 / (_closed ? _axisSamples - 3 : _axisSamples - 1);
    final double inverseAxisLessTexture = 1.0 / (_axisSamples - 1);
    final double halfHeight = 0.5 * _height;

    // Generate points on the unit circle to be used in computing the mesh
    // points on a cylinder slice.
    final double[] sin = new double[_radialSamples + 1];
    final double[] cos = new double[_radialSamples + 1];

    for (int radialCount = 0; radialCount < _radialSamples; radialCount++) {
      final double angle = MathUtils.TWO_PI * inverseRadial * radialCount;
      cos[radialCount] = MathUtils.cos(angle);
      sin[radialCount] = MathUtils.sin(angle);
    }
    sin[_radialSamples] = sin[0];
    cos[_radialSamples] = cos[0];

    // generate the cylinder itself
    final Vector3 tempNormal = new Vector3();
    for (int axisCount = 0, i = 0; axisCount < _axisSamples; axisCount++) {
      double axisFraction;
      double axisFractionTexture;
      int topBottom = 0;
      if (!_closed) {
        axisFraction = axisCount * inverseAxisLess; // in [0,1]
        axisFractionTexture = axisFraction;
      } else {
        if (axisCount == 0) {
          topBottom = -1; // bottom
          axisFraction = 0;
          axisFractionTexture = inverseAxisLessTexture;
        } else if (axisCount == _axisSamples - 1) {
          topBottom = 1; // top
          axisFraction = 1;
          axisFractionTexture = 1 - inverseAxisLessTexture;
        } else {
          axisFraction = (axisCount - 1) * inverseAxisLess;
          axisFractionTexture = axisCount * inverseAxisLessTexture;
        }
      }
      final double z = -halfHeight + _height * axisFraction;

      // compute center of slice
      final Vector3 sliceCenter = new Vector3(0, 0, z);

      // compute slice vertices with duplication at end point
      final int save = i;
      for (int radialCount = 0; radialCount < _radialSamples; radialCount++) {
        final double radialFraction = radialCount * inverseRadial; // in [0,1)
        tempNormal.set(cos[radialCount], sin[radialCount], 0);
        if (topBottom == 0) {
          if (!_inverted) {
            _meshData
                .getNormalBuffer()
                .put(tempNormal.getXf())
                .put(tempNormal.getYf())
                .put(tempNormal.getZf());
          } else {
            _meshData
                .getNormalBuffer()
                .put(-tempNormal.getXf())
                .put(-tempNormal.getYf())
                .put(-tempNormal.getZf());
          }
        } else {
          _meshData.getNormalBuffer().put(0).put(0).put(topBottom * (_inverted ? -1 : 1));
        }

        tempNormal
            .multiplyLocal((_radius - _radius2) * axisFraction + _radius2)
            .addLocal(sliceCenter);
        _meshData
            .getVertexBuffer()
            .put(tempNormal.getXf())
            .put(tempNormal.getYf())
            .put(tempNormal.getZf());

        _meshData
            .getTextureCoords(0)
            .getBuffer()
            .put((float) (_inverted ? 1 - radialFraction : radialFraction))
            .put((float) axisFractionTexture);
        i++;
      }

      BufferUtils.copyInternalVector3(_meshData.getVertexBuffer(), save, i);
      BufferUtils.copyInternalVector3(_meshData.getNormalBuffer(), save, i);

      _meshData
          .getTextureCoords(0)
          .getBuffer()
          .put((_inverted ? 0.0f : 1.0f))
          .put((float) axisFractionTexture);

      i++;
    }

    if (_closed) {
      _meshData.getVertexBuffer().put(0).put(0).put((float) -halfHeight); // bottom center
      _meshData.getNormalBuffer().put(0).put(0).put(-1 * (_inverted ? -1 : 1));
      _meshData.getTextureCoords(0).getBuffer().put(0.5f).put(0);
      _meshData.getVertexBuffer().put(0).put(0).put((float) halfHeight); // top center
      _meshData.getNormalBuffer().put(0).put(0).put(1 * (_inverted ? -1 : 1));
      _meshData.getTextureCoords(0).getBuffer().put(0.5f).put(1);
    }
  }