/**
   * This is a <b>VERY </b> brute force method of detecting if two TriMesh objects intersect.
   *
   * @param mesh1 The first TriMesh.
   * @param mesh2 The second TriMesh.
   * @return True if they intersect, false otherwise.
   */
  public static boolean meshIntersection(TriMesh mesh1, TriMesh mesh2) {

    IntBuffer indexA = mesh1.getIndexBuffer();
    IntBuffer indexB = mesh2.getIndexBuffer();
    TransformMatrix aTransform = new TransformMatrix();
    aTransform.setRotationQuaternion(mesh1.getWorldRotation());
    aTransform.setTranslation(mesh1.getWorldTranslation());
    aTransform.setScale(mesh1.getWorldScale());

    TransformMatrix bTransform = new TransformMatrix();
    bTransform.setRotationQuaternion(mesh2.getWorldRotation());
    bTransform.setTranslation(mesh2.getWorldTranslation());
    bTransform.setScale(mesh2.getWorldScale());

    Vector3f[] vertA = BufferUtils.getVector3Array(mesh1.getVertexBuffer());
    for (int i = 0; i < vertA.length; i++) aTransform.multPoint(vertA[i]);

    Vector3f[] vertB = BufferUtils.getVector3Array(mesh2.getVertexBuffer());
    for (int i = 0; i < vertB.length; i++) bTransform.multPoint(vertB[i]);

    for (int i = 0; i < mesh1.getTriangleCount(); i++) {
      for (int j = 0; j < mesh2.getTriangleCount(); j++) {
        if (intersection(
            vertA[indexA.get(i * 3 + 0)],
            vertA[indexA.get(i * 3 + 1)],
            vertA[indexA.get(i * 3 + 2)],
            vertB[indexB.get(j * 3 + 0)],
            vertB[indexB.get(j * 3 + 1)],
            vertB[indexB.get(j * 3 + 2)])) return true;
      }
    }
    return false;
  }
  public void initParticleLocation(int index) {
    Particle p = particles[index];
    if (particleType == ParticleType.GeomMesh) {
      // Update the triangle model on each new particle creation.
      Vector3f[] vertices = new Vector3f[3];
      ((TriMesh) psGeom).getTriangle(index, vertices);
      Triangle t = p.getTriangleModel();
      if (t == null) t = new Triangle(vertices[0], vertices[1], vertices[2]);
      else for (int x = 0; x < 3; x++) t.set(x, vertices[x]);
      t.calculateCenter();
      t.calculateNormal();
      // turn the triangle corners into vector offsets from center
      for (int x = 0; x < 3; x++) {
        vertices[x].subtract(t.getCenter(), vertices[x]);
        t.set(x, vertices[x]);
      }
      p.setTriangleModel(t);
      psGeom.localToWorld(t.getCenter(), p.getPosition());
      p.getPosition().multLocal(getInvScale());

    } else if (getEmitType() == EmitType.Geometry) {
      if (getGeometry() != null && getGeometry() instanceof TriMesh)
        ((TriMesh) getGeometry()).randomPointOnTriangles(p.getPosition(), workVect3);
      else if (getGeometry() != null) getGeometry().randomVertex(p.getPosition());
      p.getPosition().multLocal(getInvScale());

    } else {
      switch (getEmitType()) {
        case Line:
          getLine().random(p.getPosition());
          break;
        case Rectangle:
          getRectangle().random(p.getPosition());
          break;
        case Ring:
          getRing().random(p.getPosition());
          break;
        case Point:
        default:
          p.getPosition().set(originOffset);
          break;
      }
      emitterTransform.multPoint(p.getPosition());
    }
  }
  public void updateGeometricState(float time, boolean initiator) {
    super.updateGeometricState(time, initiator);
    if (isRotateWithScene()) {
      if (emitType == EmitType.Geometry && getGeometry() != null) {
        getGeometry().getWorldRotation().mult(emissionDirection, worldEmit);
      } else {
        worldRotation.mult(emissionDirection, worldEmit);
      }
    } else worldEmit.set(emissionDirection);

    if (particlesInWorldCoords) {
      emitterTransform.set(worldRotation, worldTranslation.divide(worldScale));

      originCenter.set(worldTranslation).addLocal(originOffset);

      getWorldTranslation().set(0, 0, 0);
      getWorldRotation().set(0, 0, 0, 1);
    } else {
      originCenter.set(originOffset);
    }
  }