Example #1
0
  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);
  }
Example #2
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 #3
0
  /**
   * 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;
  }
Example #4
0
  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);
  }
Example #5
0
  @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]);
    }
  }
Example #6
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);
  }