public static TriangleData processTriangle(int[] index, Vector3f[] v, Vector2f[] t) {
    Vector3f edge1 = new Vector3f();
    Vector3f edge2 = new Vector3f();
    Vector2f edge1uv = new Vector2f();
    Vector2f edge2uv = new Vector2f();

    Vector3f tangent = new Vector3f();
    Vector3f binormal = new Vector3f();
    Vector3f normal = new Vector3f();

    t[1].subtract(t[0], edge1uv);
    t[2].subtract(t[0], edge2uv);
    float det = edge1uv.x * edge2uv.y - edge1uv.y * edge2uv.x;

    boolean normalize = false;
    if (Math.abs(det) < ZERO_TOLERANCE) {
      //			log.log(Level.WARNING, "Colinear uv coordinates for triangle " + "[{0}, {1}, {2}]; tex0 =
      // [{3}, {4}], " + "tex1 = [{5}, {6}], tex2 = [{7}, {8}]",
      //					new Object[] { index[0], index[1], index[2], t[0].x, t[0].y, t[1].x, t[1].y, t[2].x,
      // t[2].y });
      det = 1;
      normalize = true;
    }

    v[1].subtract(v[0], edge1);
    v[2].subtract(v[0], edge2);

    tangent.set(edge1);
    tangent.normalizeLocal();
    binormal.set(edge2);
    binormal.normalizeLocal();

    if (Math.abs(Math.abs(tangent.dot(binormal)) - 1) < ZERO_TOLERANCE) {
      //			log.log(Level.WARNING, "Vertices are on the same line " + "for triangle [{0}, {1},
      // {2}].", new Object[] { index[0], index[1], index[2] });
    }

    float factor = 1 / det;
    tangent.x = (edge2uv.y * edge1.x - edge1uv.y * edge2.x) * factor;
    tangent.y = (edge2uv.y * edge1.y - edge1uv.y * edge2.y) * factor;
    tangent.z = (edge2uv.y * edge1.z - edge1uv.y * edge2.z) * factor;
    if (normalize) {
      tangent.normalizeLocal();
    }

    binormal.x = (edge1uv.x * edge2.x - edge2uv.x * edge1.x) * factor;
    binormal.y = (edge1uv.x * edge2.y - edge2uv.x * edge1.y) * factor;
    binormal.z = (edge1uv.x * edge2.z - edge2uv.x * edge1.z) * factor;
    if (normalize) {
      binormal.normalizeLocal();
    }

    tangent.cross(binormal, normal);
    normal.normalizeLocal();

    return new TriangleData(tangent, binormal, normal);
  }
  @Override
  public void render(RenderManager rm) {
    if (!isEnabled() || listener == null) {
      return;
    }

    Vector3f lastLocation = listener.getLocation();
    Vector3f currentLocation = camera.getLocation();
    Vector3f velocity = listener.getVelocity();

    if (!lastLocation.equals(currentLocation)) {
      velocity.set(currentLocation).subtractLocal(lastLocation);
      velocity.multLocal(1f / lastTpf);
      listener.setLocation(currentLocation);
      listener.setVelocity(velocity);
    } else if (!velocity.equals(Vector3f.ZERO)) {
      listener.setVelocity(Vector3f.ZERO);
    }

    Quaternion lastRotation = listener.getRotation();
    Quaternion currentRotation = camera.getRotation();
    if (!lastRotation.equals(currentRotation)) {
      listener.setRotation(currentRotation);
    }
  }
  /**
   * <code>rotateUpTo</code> is a utility function that alters the local rotation to point the Y
   * axis in the direction given by newUp.
   *
   * @param newUp the up vector to use - assumed to be a unit vector.
   */
  public void rotateUpTo(Vector3f newUp) {
    TempVars vars = TempVars.get();

    Vector3f compVecA = vars.vect1;
    Quaternion q = vars.quat1;

    // First figure out the current up vector.
    Vector3f upY = compVecA.set(Vector3f.UNIT_Y);
    Quaternion rot = localTransform.getRotation();
    rot.multLocal(upY);

    // get angle between vectors
    float angle = upY.angleBetween(newUp);

    // figure out rotation axis by taking cross product
    Vector3f rotAxis = upY.crossLocal(newUp).normalizeLocal();

    // Build a rotation quat and apply current local rotation.
    q.fromAngleNormalAxis(angle, rotAxis);
    q.mult(rot, rot);

    vars.release();

    setTransformRefresh();
  }
 /**
  * Warp into the scene on the nav mesh, finding the nearest cell. The currentCell and position3d
  * are updated and this new position is returned. This updates the state of the path finder!
  *
  * @return the new position in the nearest cell
  */
 public Vector3f warp(Vector3f newPos) {
   Vector3f newPos2d = new Vector3f(newPos.x, 0, newPos.z);
   currentCell = navMesh.findClosestCell(newPos2d);
   currentPos3d.set(navMesh.snapPointToCell(currentCell, newPos2d));
   currentPos3d.setY(newPos.getY());
   currentPos.set(currentPos3d.getX(), currentPos3d.getZ());
   return currentPos3d;
 }
 /**
  * This method applies the variation to the particle with already set velocity.
  *
  * @param particle the particle to be affected
  */
 protected void applyVelocityVariation(Particle particle) {
   particle.velocity.set(initialVelocity);
   temp.set(FastMath.nextRandomFloat(), FastMath.nextRandomFloat(), FastMath.nextRandomFloat());
   temp.multLocal(2f);
   temp.subtractLocal(1f, 1f, 1f);
   temp.multLocal(initialVelocity.length());
   particle.velocity.interpolate(temp, velocityVariation);
 }
  @Override
  public void onPreUpdate(float tpf) {
    Vector3f delta = velocity.mult(tpf);
    Vector3f pos = movedNode.getLocalTranslation().clone();
    smal.checkMotionAllowed(pos, delta, normal);
    movedNode.setLocalTranslation(pos.add(delta));
    velocity.set(0, 0, 0);

    normalAligned.rotateUpTo(normal);
  }
 /**
  * This is the main event loop--walking happens here. We check in which direction the player is
  * walking by interpreting the camera direction forward (camDir) and to the side (camLeft). The
  * setWalkDirection() command is what lets a physics-controlled player walk. We also make sure
  * here that the camera moves with player.
  */
 @Override
 public void simpleUpdate(float tpf) {
   camDir.set(cam.getDirection()).multLocal(0.6f);
   camLeft.set(cam.getLeft()).multLocal(0.4f);
   walkDirection.set(0, 0, 0);
   if (left) {
     walkDirection.addLocal(camLeft);
   }
   if (right) {
     walkDirection.addLocal(camLeft.negate());
   }
   if (up) {
     walkDirection.addLocal(camDir);
   }
   if (down) {
     walkDirection.addLocal(camDir.negate());
   }
   player.setWalkDirection(walkDirection);
   cam.setLocation(player.getPhysicsLocation());
 }
 private void interpolate(
     Vector3f[] targetVectors, float[] targetTimes, float currentTime, Vector3f result) {
   int index = 0;
   for (int i = 1; i < targetTimes.length; ++i) {
     if (targetTimes[i] < currentTime) {
       ++index;
     } else {
       break;
     }
   }
   if (index >= targetTimes.length - 1) {
     result.set(targetVectors[targetTimes.length - 1]);
   } else {
     float delta = targetTimes[index + 1] - targetTimes[index];
     if (delta == 0.0f) {
       result.set(targetVectors[index + 1]);
     } else {
       float scale =
           (currentTime - targetTimes[index]) / (targetTimes[index + 1] - targetTimes[index]);
       FastMath.interpolateLinear(scale, targetVectors[index], targetVectors[index + 1], result);
     }
   }
 }
  public void startWalk(final Ray walkRay) {
    // store ray
    this.walkRay.set(walkRay);

    // simplify access to direction
    Vector3f direction = this.walkRay.getDirection();

    // Move start point to grid space
    Vector3f start = this.walkRay.getOrigin().subtract(gridOrigin);

    gridLocation.x = (int) (start.x / gridSpacing.x);
    gridLocation.y = (int) (start.z / gridSpacing.z);

    Vector3f ooDirection = new Vector3f(1.0f / direction.x, 1, 1.0f / direction.z);

    // Check which direction on the X world axis we are moving.
    if (direction.x > TOLERANCE) {
      distToNextXIntersection = ((gridLocation.x + 1) * gridSpacing.x - start.x) * ooDirection.x;
      distBetweenXIntersections = gridSpacing.x * ooDirection.x;
      stepXDirection = 1;
    } else if (direction.x < -TOLERANCE) {
      distToNextXIntersection = (start.x - (gridLocation.x * gridSpacing.x)) * -direction.x;
      distBetweenXIntersections = -gridSpacing.x * ooDirection.x;
      stepXDirection = -1;
    } else {
      distToNextXIntersection = Float.MAX_VALUE;
      distBetweenXIntersections = Float.MAX_VALUE;
      stepXDirection = 0;
    }

    // Check which direction on the Z world axis we are moving.
    if (direction.z > TOLERANCE) {
      distToNextZIntersection = ((gridLocation.y + 1) * gridSpacing.z - start.z) * ooDirection.z;
      distBetweenZIntersections = gridSpacing.z * ooDirection.z;
      stepZDirection = 1;
    } else if (direction.z < -TOLERANCE) {
      distToNextZIntersection = (start.z - (gridLocation.y * gridSpacing.z)) * -direction.z;
      distBetweenZIntersections = -gridSpacing.z * ooDirection.z;
      stepZDirection = -1;
    } else {
      distToNextZIntersection = Float.MAX_VALUE;
      distBetweenZIntersections = Float.MAX_VALUE;
      stepZDirection = 0;
    }

    // Reset some variables
    rayLocation.set(start);
    rayLength = 0.0f;
    stepDirection = Direction.None;
  }
  /**
   * <code>lookAt</code> is a convenience method for auto-setting the local rotation based on a
   * position in world space and an up vector. It computes the rotation to transform the z-axis to
   * point onto 'position' and the y-axis to 'up'. Unlike {@link
   * Quaternion#lookAt(com.jme3.math.Vector3f, com.jme3.math.Vector3f) } this method takes a world
   * position to look at and not a relative direction.
   *
   * <p>Note : 28/01/2013 this method has been fixed as it was not taking into account the parent
   * rotation. This was resulting in improper rotation when the spatial had rotated parent nodes.
   * This method is intended to work in world space, so no matter what parent graph the spatial has,
   * it will look at the given position in world space.
   *
   * @param position where to look at in terms of world coordinates
   * @param upVector a vector indicating the (local) up direction. (typically {0, 1, 0} in jME.)
   */
  public void lookAt(Vector3f position, Vector3f upVector) {
    Vector3f worldTranslation = getWorldTranslation();

    TempVars vars = TempVars.get();

    Vector3f compVecA = vars.vect4;

    compVecA.set(position).subtractLocal(worldTranslation);
    getLocalRotation().lookAt(compVecA, upVector);

    if (getParent() != null) {
      Quaternion rot = vars.quat1;
      rot = rot.set(parent.getWorldRotation()).inverseLocal().multLocal(getLocalRotation());
      rot.normalizeLocal();
      setLocalRotation(rot);
    }
    vars.release();
    setTransformRefresh();
  }
  public void next() {
    // Walk us to our next location based on distances to next X or Z grid
    // line.
    if (distToNextXIntersection < distToNextZIntersection) {
      rayLength = distToNextXIntersection;
      gridLocation.x += stepXDirection;
      distToNextXIntersection += distBetweenXIntersections;
      switch (stepXDirection) {
        case -1:
          stepDirection = Direction.NegativeX;
          break;
        case 0:
          stepDirection = Direction.None;
          break;
        case 1:
          stepDirection = Direction.PositiveX;
          break;
      }
    } else {
      rayLength = distToNextZIntersection;
      gridLocation.y += stepZDirection;
      distToNextZIntersection += distBetweenZIntersections;
      switch (stepZDirection) {
        case -1:
          stepDirection = Direction.NegativeZ;
          break;
        case 0:
          stepDirection = Direction.None;
          break;
        case 1:
          stepDirection = Direction.PositiveZ;
          break;
      }
    }

    rayLocation.set(walkRay.direction).multLocal(rayLength).addLocal(walkRay.origin);
  }
  @Override
  public void onBinding(String binding, float value) {
    System.out.println(binding);

    if (binding.equals("Left")) {
      velocity.set(-5, 0, 0);
    } else if (binding.equals("Right")) {
      velocity.set(5, 0, 0);
    } else if (binding.equals("Up")) {
      velocity.set(0, 0, -5);
    } else if (binding.equals("Down")) {
      velocity.set(0, 0, 5);
    } else if (binding.equals("PgUp")) {
      velocity.set(0, 5, 0);
    } else if (binding.equals("PgDn")) {
      velocity.set(0, -5, 0);
    }
  }
Exemple #13
0
 @Override
 public void simpleUpdate(float lastTimePerFrame) {
   float playerMoveSpeed = ((cubesSettings.getBlockSize() * 6.5f) * lastTimePerFrame);
   Vector3f camDir = cam.getDirection().mult(playerMoveSpeed);
   Vector3f camLeft = cam.getLeft().mult(playerMoveSpeed);
   walkDirection.set(0, 0, 0);
   if (arrowKeys[0]) {
     walkDirection.addLocal(camDir);
   }
   if (arrowKeys[1]) {
     walkDirection.addLocal(camLeft.negate());
   }
   if (arrowKeys[2]) {
     walkDirection.addLocal(camDir.negate());
   }
   if (arrowKeys[3]) {
     walkDirection.addLocal(camLeft);
   }
   walkDirection.setY(0);
   walkDirection.normalize();
   walkDirection.multLocal(lastTimePerFrame * 10);
   playerControl.setWalkDirection(walkDirection);
   cam.setLocation(playerControl.getPhysicsLocation());
 }
  /**
   * Rebuilds the cylinder based on a new set of parameters.
   *
   * @param axisSamples the number of samples along the axis.
   * @param radialSamples the number of samples around the radial.
   * @param radius the radius of the bottom of the cylinder.
   * @param radius2 the radius of the top of the cylinder.
   * @param height the cylinder's height.
   * @param closed should the cylinder have top and bottom surfaces.
   * @param inverted is the cylinder is meant to be viewed from the inside.
   */
  public void updateGeometry(
      int axisSamples,
      int radialSamples,
      float radius,
      float radius2,
      float height,
      boolean closed,
      boolean inverted) {
    this.axisSamples = axisSamples + (closed ? 2 : 0);
    this.radialSamples = radialSamples;
    this.radius = radius;
    this.radius2 = radius2;
    this.height = height;
    this.closed = closed;
    this.inverted = inverted;

    //        VertexBuffer pvb = getBuffer(Type.Position);
    //        VertexBuffer nvb = getBuffer(Type.Normal);
    //        VertexBuffer tvb = getBuffer(Type.TexCoord);

    // Vertices
    int vertCount = axisSamples * (radialSamples + 1) + (closed ? 2 : 0);

    setBuffer(Type.Position, 3, createVector3Buffer(getFloatBuffer(Type.Position), vertCount));

    // Normals
    setBuffer(Type.Normal, 3, createVector3Buffer(getFloatBuffer(Type.Normal), vertCount));

    // Texture co-ordinates
    setBuffer(Type.TexCoord, 2, createVector2Buffer(vertCount));

    int triCount = ((closed ? 2 : 0) + 2 * (axisSamples - 1)) * radialSamples;

    setBuffer(Type.Index, 3, createShortBuffer(getShortBuffer(Type.Index), 3 * triCount));

    // generate geometry
    float inverseRadial = 1.0f / radialSamples;
    float inverseAxisLess = 1.0f / (closed ? axisSamples - 3 : axisSamples - 1);
    float inverseAxisLessTexture = 1.0f / (axisSamples - 1);
    float halfHeight = 0.5f * height;

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

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

    // calculate normals
    Vector3f[] vNormals = null;
    Vector3f vNormal = Vector3f.UNIT_Z;

    if ((height != 0.0f) && (radius != radius2)) {
      vNormals = new Vector3f[radialSamples];
      Vector3f vHeight = Vector3f.UNIT_Z.mult(height);
      Vector3f vRadial = new Vector3f();

      for (int radialCount = 0; radialCount < radialSamples; radialCount++) {
        vRadial.set(cos[radialCount], sin[radialCount], 0.0f);
        Vector3f vRadius = vRadial.mult(radius);
        Vector3f vRadius2 = vRadial.mult(radius2);
        Vector3f vMantle = vHeight.subtract(vRadius2.subtract(vRadius));
        Vector3f vTangent = vRadial.cross(Vector3f.UNIT_Z);
        vNormals[radialCount] = vMantle.cross(vTangent).normalize();
      }
    }

    FloatBuffer nb = getFloatBuffer(Type.Normal);
    FloatBuffer pb = getFloatBuffer(Type.Position);
    FloatBuffer tb = getFloatBuffer(Type.TexCoord);

    // generate the cylinder itself
    Vector3f tempNormal = new Vector3f();
    for (int axisCount = 0, i = 0; axisCount < axisSamples; axisCount++, i++) {
      float axisFraction;
      float 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;
        }
      }

      // compute center of slice
      float z = -halfHeight + height * axisFraction;
      Vector3f sliceCenter = new Vector3f(0, 0, z);

      // compute slice vertices with duplication at end point
      int save = i;
      for (int radialCount = 0; radialCount < radialSamples; radialCount++, i++) {
        float radialFraction = radialCount * inverseRadial; // in [0,1)
        tempNormal.set(cos[radialCount], sin[radialCount], 0.0f);

        if (vNormals != null) {
          vNormal = vNormals[radialCount];
        } else if (radius == radius2) {
          vNormal = tempNormal;
        }

        if (topBottom == 0) {
          if (!inverted) nb.put(vNormal.x).put(vNormal.y).put(vNormal.z);
          else nb.put(-vNormal.x).put(-vNormal.y).put(-vNormal.z);
        } else {
          nb.put(0).put(0).put(topBottom * (inverted ? -1 : 1));
        }

        tempNormal.multLocal((radius - radius2) * axisFraction + radius2).addLocal(sliceCenter);
        pb.put(tempNormal.x).put(tempNormal.y).put(tempNormal.z);

        tb.put((inverted ? 1 - radialFraction : radialFraction)).put(axisFractionTexture);
      }

      BufferUtils.copyInternalVector3(pb, save, i);
      BufferUtils.copyInternalVector3(nb, save, i);

      tb.put((inverted ? 0.0f : 1.0f)).put(axisFractionTexture);
    }

    if (closed) {
      pb.put(0).put(0).put(-halfHeight); // bottom center
      nb.put(0).put(0).put(-1 * (inverted ? -1 : 1));
      tb.put(0.5f).put(0);
      pb.put(0).put(0).put(halfHeight); // top center
      nb.put(0).put(0).put(1 * (inverted ? -1 : 1));
      tb.put(0.5f).put(1);
    }

    IndexBuffer ib = getIndexBuffer();
    int index = 0;
    // Connectivity
    for (int axisCount = 0, axisStart = 0; axisCount < axisSamples - 1; axisCount++) {
      int i0 = axisStart;
      int i1 = i0 + 1;
      axisStart += radialSamples + 1;
      int i2 = axisStart;
      int i3 = i2 + 1;
      for (int i = 0; i < radialSamples; i++) {
        if (closed && axisCount == 0) {
          if (!inverted) {
            ib.put(index++, i0++);
            ib.put(index++, vertCount - 2);
            ib.put(index++, i1++);
          } else {
            ib.put(index++, i0++);
            ib.put(index++, i1++);
            ib.put(index++, vertCount - 2);
          }
        } else if (closed && axisCount == axisSamples - 2) {
          ib.put(index++, i2++);
          ib.put(index++, inverted ? vertCount - 1 : i3++);
          ib.put(index++, inverted ? i3++ : vertCount - 1);
        } else {
          ib.put(index++, i0++);
          ib.put(index++, inverted ? i2 : i1);
          ib.put(index++, inverted ? i1 : i2);
          ib.put(index++, i1++);
          ib.put(index++, inverted ? i2++ : i3++);
          ib.put(index++, inverted ? i3++ : i2++);
        }
      }
    }

    updateBound();
  }
 public CreateAccelerometerSensorCommand setDimensions(float width, float height, float depth) {
   dimensions.set(width, height, depth);
   return this;
 }
Exemple #16
0
  /**
   * Updates the points array to contain the frustum corners of the given camera. The nearOverride
   * and farOverride variables can be used to override the camera's near/far values with own values.
   *
   * <p>TODO: Reduce creation of new vectors
   *
   * @param viewCam
   * @param nearOverride
   * @param farOverride
   */
  public static void updateFrustumPoints(
      Camera viewCam, float nearOverride, float farOverride, float scale, Vector3f[] points) {

    Vector3f pos = viewCam.getLocation();
    Vector3f dir = viewCam.getDirection();
    Vector3f up = viewCam.getUp();

    float depthHeightRatio = viewCam.getFrustumTop() / viewCam.getFrustumNear();
    float near = nearOverride;
    float far = farOverride;
    float ftop = viewCam.getFrustumTop();
    float fright = viewCam.getFrustumRight();
    float ratio = fright / ftop;

    float near_height;
    float near_width;
    float far_height;
    float far_width;

    if (viewCam.isParallelProjection()) {
      near_height = ftop;
      near_width = near_height * ratio;
      far_height = ftop;
      far_width = far_height * ratio;
    } else {
      near_height = depthHeightRatio * near;
      near_width = near_height * ratio;
      far_height = depthHeightRatio * far;
      far_width = far_height * ratio;
    }

    Vector3f right = dir.cross(up).normalizeLocal();

    Vector3f temp = new Vector3f();
    temp.set(dir).multLocal(far).addLocal(pos);
    Vector3f farCenter = temp.clone();
    temp.set(dir).multLocal(near).addLocal(pos);
    Vector3f nearCenter = temp.clone();

    Vector3f nearUp = temp.set(up).multLocal(near_height).clone();
    Vector3f farUp = temp.set(up).multLocal(far_height).clone();
    Vector3f nearRight = temp.set(right).multLocal(near_width).clone();
    Vector3f farRight = temp.set(right).multLocal(far_width).clone();

    points[0].set(nearCenter).subtractLocal(nearUp).subtractLocal(nearRight);
    points[1].set(nearCenter).addLocal(nearUp).subtractLocal(nearRight);
    points[2].set(nearCenter).addLocal(nearUp).addLocal(nearRight);
    points[3].set(nearCenter).subtractLocal(nearUp).addLocal(nearRight);

    points[4].set(farCenter).subtractLocal(farUp).subtractLocal(farRight);
    points[5].set(farCenter).addLocal(farUp).subtractLocal(farRight);
    points[6].set(farCenter).addLocal(farUp).addLocal(farRight);
    points[7].set(farCenter).subtractLocal(farUp).addLocal(farRight);

    if (scale != 1.0f) {
      // find center of frustum
      Vector3f center = new Vector3f();
      for (int i = 0; i < 8; i++) {
        center.addLocal(points[i]);
      }
      center.divideLocal(8f);

      Vector3f cDir = new Vector3f();
      for (int i = 0; i < 8; i++) {
        cDir.set(points[i]).subtractLocal(center);
        cDir.multLocal(scale - 1.0f);
        points[i].addLocal(cDir);
      }
    }
  }
  public void update(float tpf) {
    if (!enabled) {
      return;
    }
    TempVars vars = TempVars.get();

    Quaternion tmpRot1 = vars.quat1;
    Quaternion tmpRot2 = vars.quat2;

    // if the ragdoll has the control of the skeleton, we update each bone with its position in
    // physic world space.
    if (mode == mode.Ragdoll && targetModel.getLocalTranslation().equals(modelPosition)) {
      for (PhysicsBoneLink link : boneLinks.values()) {

        Vector3f position = vars.vect1;

        // retrieving bone position in physic world space
        Vector3f p = link.rigidBody.getMotionState().getWorldLocation();
        // transforming this position with inverse transforms of the model
        targetModel.getWorldTransform().transformInverseVector(p, position);

        // retrieving bone rotation in physic world space
        Quaternion q = link.rigidBody.getMotionState().getWorldRotationQuat();

        // multiplying this rotation by the initialWorld rotation of the bone,
        // then transforming it with the inverse world rotation of the model
        tmpRot1.set(q).multLocal(link.initalWorldRotation);
        tmpRot2.set(targetModel.getWorldRotation()).inverseLocal().mult(tmpRot1, tmpRot1);
        tmpRot1.normalizeLocal();

        // if the bone is the root bone, we apply the physic's transform to the model, so its
        // position and rotation are correctly updated
        if (link.bone.getParent() == null) {

          // offsetting the physic's position/rotation by the root bone inverse model space
          // position/rotaion
          modelPosition.set(p).subtractLocal(link.bone.getWorldBindPosition());
          targetModel
              .getParent()
              .getWorldTransform()
              .transformInverseVector(modelPosition, modelPosition);
          modelRotation
              .set(q)
              .multLocal(tmpRot2.set(link.bone.getWorldBindRotation()).inverseLocal());

          // applying transforms to the model
          targetModel.setLocalTranslation(modelPosition);

          targetModel.setLocalRotation(modelRotation);

          // Applying computed transforms to the bone
          link.bone.setUserTransformsWorld(position, tmpRot1);

        } else {
          // if boneList is empty, this means that every bone in the ragdoll has a collision shape,
          // so we just update the bone position
          if (boneList.isEmpty()) {
            link.bone.setUserTransformsWorld(position, tmpRot1);
          } else {
            // boneList is not empty, this means some bones of the skeleton might not be associated
            // with a collision shape.
            // So we update them recusively
            RagdollUtils.setTransform(link.bone, position, tmpRot1, false, boneList);
          }
        }
      }
    } else {
      // the ragdoll does not have the controll, so the keyframed animation updates the physic
      // position of the physic bonces
      for (PhysicsBoneLink link : boneLinks.values()) {

        Vector3f position = vars.vect1;

        // if blended control this means, keyframed animation is updating the skeleton,
        // but to allow smooth transition, we blend this transformation with the saved position of
        // the ragdoll
        if (blendedControl) {
          Vector3f position2 = vars.vect2;
          // initializing tmp vars with the start position/rotation of the ragdoll
          position.set(link.startBlendingPos);
          tmpRot1.set(link.startBlendingRot);

          // interpolating between ragdoll position/rotation and keyframed position/rotation
          tmpRot2.set(tmpRot1).nlerp(link.bone.getModelSpaceRotation(), blendStart / blendTime);
          position2
              .set(position)
              .interpolate(link.bone.getModelSpacePosition(), blendStart / blendTime);
          tmpRot1.set(tmpRot2);
          position.set(position2);

          // updating bones transforms
          if (boneList.isEmpty()) {
            // we ensure we have the control to update the bone
            link.bone.setUserControl(true);
            link.bone.setUserTransformsWorld(position, tmpRot1);
            // we give control back to the key framed animation.
            link.bone.setUserControl(false);
          } else {
            RagdollUtils.setTransform(link.bone, position, tmpRot1, true, boneList);
          }
        }
        // setting skeleton transforms to the ragdoll
        matchPhysicObjectToBone(link, position, tmpRot1);
        modelPosition.set(targetModel.getLocalTranslation());
      }

      // time control for blending
      if (blendedControl) {
        blendStart += tpf;
        if (blendStart > blendTime) {
          blendedControl = false;
        }
      }
    }
    vars.release();
  }
 public final Vector3f getCenter(Vector3f store) {
   store.set(center);
   return store;
 }
 /**
  * Get the nearest cell to the supplied position and place the returned position in that cell.
  *
  * @param position to place in the nearest cell
  * @return the position in the cell
  */
 public Vector3f warpInside(Vector3f position) {
   Vector3f newPos2d = new Vector3f(position.x, 0, position.z);
   Cell cell = navMesh.findClosestCell(newPos2d);
   position.set(navMesh.snapPointToCell(cell, newPos2d));
   return position;
 }
  private static BoneWorldGrid makeBoneWorldGrid(
      ByteArray3d boneMeshGrid, float worldScale, MyBone bone) {
    Transform transform = BoneTransformUtils.boneTransform2(bone);
    // bounding box needed for boneMeshGrid in world grid:
    float bs = 1.0f;
    Vector3f c1 =
        transform.transformVector(new Vector3f(-bs, -bs, -bs), null).multLocal(worldScale);
    Vector3f c2 =
        transform.transformVector(new Vector3f(+bs, -bs, -bs), null).multLocal(worldScale);
    Vector3f c3 =
        transform.transformVector(new Vector3f(-bs, +bs, -bs), null).multLocal(worldScale);
    Vector3f c4 =
        transform.transformVector(new Vector3f(-bs, -bs, +bs), null).multLocal(worldScale);
    Vector3f c5 =
        transform.transformVector(new Vector3f(+bs, +bs, -bs), null).multLocal(worldScale);
    Vector3f c6 =
        transform.transformVector(new Vector3f(-bs, +bs, +bs), null).multLocal(worldScale);
    Vector3f c7 =
        transform.transformVector(new Vector3f(+bs, -bs, +bs), null).multLocal(worldScale);
    Vector3f c8 =
        transform.transformVector(new Vector3f(+bs, +bs, +bs), null).multLocal(worldScale);

    Vector3f cmin = c1.clone();
    cmin.minLocal(c2);
    cmin.minLocal(c3);
    cmin.minLocal(c4);
    cmin.minLocal(c5);
    cmin.minLocal(c6);
    cmin.minLocal(c7);
    cmin.minLocal(c8);
    Vector3f cmax = c1.clone();
    cmax.maxLocal(c2);
    cmax.maxLocal(c3);
    cmax.maxLocal(c4);
    cmax.maxLocal(c5);
    cmax.maxLocal(c6);
    cmax.maxLocal(c7);
    cmax.maxLocal(c8);

    int xsize = (int) FastMath.ceil(cmax.x - cmin.x);
    int ysize = (int) FastMath.ceil(cmax.y - cmin.y);
    int zsize = (int) FastMath.ceil(cmax.z - cmin.z);

    ByteArray3d grid = new ByteArray3d(xsize, ysize, zsize);
    int w = grid.getWidth();
    int h = grid.getHeight();
    int d = grid.getDepth();
    Vector3f v = new Vector3f();
    Vector3f inv = new Vector3f();
    Vector3f inv2 = new Vector3f();

    // we want to calculate transform: (inv - (-bs)) * (sz / (bs - (-bs)))
    // se let's precalculate it to (inv + shift) * scale
    Vector3f scale =
        new Vector3f(boneMeshGrid.getWidth(), boneMeshGrid.getHeight(), boneMeshGrid.getDepth())
            .divideLocal(bs * 2);
    Vector3f shift = Vector3f.UNIT_XYZ.mult(bs);

    for (int x = 0; x < w; x++) {
      for (int y = 0; y < h; y++) {
        // calculate inverse transform at (x,y,0) and (x,y,1), the rest of the transforms in inner
        // loop
        // can be calculated by adding (inv2-inv1) because the transforms are linear
        v.set(x, y, 0).addLocal(cmin).divideLocal(worldScale);
        transform.transformInverseVector(v, inv);
        inv.addLocal(shift).multLocal(scale);

        v.set(x, y, 1).addLocal(cmin).divideLocal(worldScale);
        transform.transformInverseVector(v, inv2);
        inv2.addLocal(shift).multLocal(scale);

        Vector3f add = inv2.subtractLocal(inv);

        for (int z = 0; z < d; z++) {
          inv.addLocal(add);
          if (inv.x >= 0
              && inv.x < boneMeshGrid.getWidth()
              && inv.y >= 0
              && inv.y < boneMeshGrid.getHeight()
              && inv.z >= 0
              && inv.z < boneMeshGrid.getDepth()) {

            grid.set(x, y, z, boneMeshGrid.get((int) inv.x, (int) inv.y, (int) inv.z));
          }
        }
      }
    }

    // Once the boneMeshGrid has been transformed into world grid, it may suffer from
    // downsampling and upsampling artifacts (because the sampling is very simple nearest-neighbor).
    // Blurring the grid helps with both issues (blur=fake antialias). It has the added benefit
    // that each BoneWorldGrid will have some "smoothing buffer" around the actual shape, so that
    // the shape blends better with other bones' shapes.
    blurGrid(grid);

    BoneWorldGrid bwg2 = new BoneWorldGrid();
    bwg2.grid = grid;
    bwg2.location = new Vector3i(Math.round(cmin.x), Math.round(cmin.y), Math.round(cmin.z));
    return bwg2;
  }
 public final void setCenter(float x, float y, float z) {
   center.set(x, y, z);
 }
 public final void setCenter(Vector3f newCenter) {
   center.set(newCenter);
 }
  @Override
  public void initParticleData(Emitter emitter, int numParticles) {
    setMode(Mode.Triangles);

    this.emitter = emitter;

    this.finVerts = BufferUtils.createFloatBuffer(templateVerts.capacity() * numParticles);
    try {
      this.finCoords = BufferUtils.createFloatBuffer(templateCoords.capacity() * numParticles);
    } catch (Exception e) {
    }
    this.finIndexes = BufferUtils.createShortBuffer(templateIndexes.size() * numParticles);
    this.finNormals = BufferUtils.createFloatBuffer(templateNormals.capacity() * numParticles);
    this.finColors = BufferUtils.createFloatBuffer(templateVerts.capacity() / 3 * 4 * numParticles);

    int index = 0, index2 = 0, index3 = 0, index4 = 0, index5 = 0;
    int indexOffset = 0;

    for (int i = 0; i < numParticles; i++) {
      templateVerts.rewind();
      for (int v = 0; v < templateVerts.capacity(); v += 3) {
        tempV3.set(templateVerts.get(v), templateVerts.get(v + 1), templateVerts.get(v + 2));
        finVerts.put(index, tempV3.getX());
        index++;
        finVerts.put(index, tempV3.getY());
        index++;
        finVerts.put(index, tempV3.getZ());
        index++;
      }
      try {
        templateCoords.rewind();
        for (int v = 0; v < templateCoords.capacity(); v++) {
          finCoords.put(index2, templateCoords.get(v));
          index2++;
        }
      } catch (Exception e) {
      }
      for (int v = 0; v < templateIndexes.size(); v++) {
        finIndexes.put(index3, (short) (templateIndexes.get(v) + indexOffset));
        index3++;
      }
      indexOffset += templateVerts.capacity() / 3;

      templateNormals.rewind();
      for (int v = 0; v < templateNormals.capacity(); v++) {
        finNormals.put(index4, templateNormals.get(v));
        index4++;
      }

      for (int v = 0; v < finColors.capacity(); v++) {
        finColors.put(v, 1.0f);
      }
    }

    // Help GC
    //	tempV3 = null;
    //	templateVerts = null;
    //	templateCoords = null;
    //	templateIndexes = null;
    //	templateNormals = null;

    // Clear & ssign buffers
    this.clearBuffer(VertexBuffer.Type.Position);
    this.setBuffer(VertexBuffer.Type.Position, 3, finVerts);
    this.clearBuffer(VertexBuffer.Type.TexCoord);
    try {
      this.setBuffer(VertexBuffer.Type.TexCoord, 2, finCoords);
    } catch (Exception e) {
    }
    this.clearBuffer(VertexBuffer.Type.Index);
    this.setBuffer(VertexBuffer.Type.Index, 3, finIndexes);
    this.clearBuffer(VertexBuffer.Type.Normal);
    this.setBuffer(VertexBuffer.Type.Normal, 3, finNormals);
    this.clearBuffer(VertexBuffer.Type.Color);
    this.setBuffer(VertexBuffer.Type.Color, 4, finColors);
    this.updateBound();
  }
  private static void processTriangleData(
      Mesh mesh, List<VertexData> vertices, boolean approxTangent, boolean splitMirrored) {
    ArrayList<VertexInfo> vertexMap = linkVertices(mesh, splitMirrored);

    FloatBuffer tangents = BufferUtils.createFloatBuffer(vertices.size() * 4);

    ColorRGBA[] cols = null;
    if (debug) {
      cols = new ColorRGBA[vertices.size()];
    }

    Vector3f tangent = new Vector3f();
    Vector3f binormal = new Vector3f();
    // Vector3f normal = new Vector3f();
    Vector3f givenNormal = new Vector3f();

    Vector3f tangentUnit = new Vector3f();
    Vector3f binormalUnit = new Vector3f();

    for (int k = 0; k < vertexMap.size(); k++) {
      float wCoord = -1;

      VertexInfo vertexInfo = vertexMap.get(k);

      givenNormal.set(vertexInfo.normal);
      givenNormal.normalizeLocal();

      TriangleData firstTriangle = vertices.get(vertexInfo.indices.get(0)).triangles.get(0);

      // check tangent and binormal consistency
      tangent.set(firstTriangle.tangent);
      tangent.normalizeLocal();
      binormal.set(firstTriangle.binormal);
      binormal.normalizeLocal();

      for (int i : vertexInfo.indices) {
        ArrayList<TriangleData> triangles = vertices.get(i).triangles;

        for (int j = 0; j < triangles.size(); j++) {
          TriangleData triangleData = triangles.get(j);

          tangentUnit.set(triangleData.tangent);
          tangentUnit.normalizeLocal();
          if (tangent.dot(tangentUnit) < toleranceDot) {
            // log.log(Level.WARNING,
            // "Angle between tangents exceeds tolerance "
            // + "for vertex {0}.", i);
            break;
          }

          if (!approxTangent) {
            binormalUnit.set(triangleData.binormal);
            binormalUnit.normalizeLocal();
            if (binormal.dot(binormalUnit) < toleranceDot) {
              // log.log(Level.WARNING,
              // "Angle between binormals exceeds tolerance "
              // + "for vertex {0}.", i);
              break;
            }
          }
        }
      }

      // find average tangent
      tangent.set(0, 0, 0);
      binormal.set(0, 0, 0);

      int triangleCount = 0;
      for (int i : vertexInfo.indices) {
        ArrayList<TriangleData> triangles = vertices.get(i).triangles;
        triangleCount += triangles.size();
        if (debug) {
          cols[i] = ColorRGBA.White;
        }

        for (int j = 0; j < triangles.size(); j++) {
          TriangleData triangleData = triangles.get(j);
          tangent.addLocal(triangleData.tangent);
          binormal.addLocal(triangleData.binormal);
        }
      }

      int blameVertex = vertexInfo.indices.get(0);

      if (tangent.length() < ZERO_TOLERANCE) {
        log.log(Level.WARNING, "Shared tangent is zero for vertex {0}.", blameVertex);
        // attempt to fix from binormal
        if (binormal.length() >= ZERO_TOLERANCE) {
          binormal.cross(givenNormal, tangent);
          tangent.normalizeLocal();
        } // if all fails use the tangent from the first triangle
        else {
          tangent.set(firstTriangle.tangent);
        }
      } else {
        tangent.divideLocal(triangleCount);
      }

      tangentUnit.set(tangent);
      tangentUnit.normalizeLocal();
      if (Math.abs(Math.abs(tangentUnit.dot(givenNormal)) - 1) < ZERO_TOLERANCE) {
        log.log(Level.WARNING, "Normal and tangent are parallel for vertex {0}.", blameVertex);
      }

      if (!approxTangent) {
        if (binormal.length() < ZERO_TOLERANCE) {
          log.log(Level.WARNING, "Shared binormal is zero for vertex {0}.", blameVertex);
          // attempt to fix from tangent
          if (tangent.length() >= ZERO_TOLERANCE) {
            givenNormal.cross(tangent, binormal);
            binormal.normalizeLocal();
          } // if all fails use the binormal from the first triangle
          else {
            binormal.set(firstTriangle.binormal);
          }
        } else {
          binormal.divideLocal(triangleCount);
        }

        binormalUnit.set(binormal);
        binormalUnit.normalizeLocal();
        if (Math.abs(Math.abs(binormalUnit.dot(givenNormal)) - 1) < ZERO_TOLERANCE) {
          log.log(Level.WARNING, "Normal and binormal are parallel for vertex {0}.", blameVertex);
        }

        if (Math.abs(Math.abs(binormalUnit.dot(tangentUnit)) - 1) < ZERO_TOLERANCE) {
          log.log(Level.WARNING, "Tangent and binormal are parallel for vertex {0}.", blameVertex);
        }
      }

      Vector3f finalTangent = new Vector3f();
      Vector3f tmp = new Vector3f();
      for (int i : vertexInfo.indices) {
        if (approxTangent) {
          // Gram-Schmidt orthogonalize
          finalTangent
              .set(tangent)
              .subtractLocal(tmp.set(givenNormal).multLocal(givenNormal.dot(tangent)));
          finalTangent.normalizeLocal();

          wCoord = tmp.set(givenNormal).crossLocal(tangent).dot(binormal) < 0f ? -1f : 1f;

          tangents.put((i * 4), finalTangent.x);
          tangents.put((i * 4) + 1, finalTangent.y);
          tangents.put((i * 4) + 2, finalTangent.z);
          tangents.put((i * 4) + 3, wCoord);
        } else {
          tangents.put((i * 4), tangent.x);
          tangents.put((i * 4) + 1, tangent.y);
          tangents.put((i * 4) + 2, tangent.z);
          tangents.put((i * 4) + 3, wCoord);

          // setInBuffer(binormal, binormals, i);
        }
      }
    }
    tangents.limit(tangents.capacity());
    // If the model already had a tangent buffer, replace it with the regenerated one
    mesh.clearBuffer(Type.Tangent);
    mesh.setBuffer(Type.Tangent, 4, tangents);

    if (mesh.isAnimated()) {
      mesh.clearBuffer(Type.BindPoseNormal);
      mesh.clearBuffer(Type.BindPosePosition);
      mesh.clearBuffer(Type.BindPoseTangent);
      mesh.generateBindPose(true);
    }

    if (debug) {
      writeColorBuffer(vertices, cols, mesh);
    }
    mesh.updateBound();
    mesh.updateCounts();
  }
  public void setLighting(LightList list) {
    // XXX: This is abuse of setLighting() to
    // apply fixed function bindings
    // and do other book keeping.
    if (list == null || list.size() == 0) {
      glDisable(GL_LIGHTING);
      applyFixedFuncBindings(false);
      setModelView(worldMatrix, viewMatrix);
      return;
    }

    // Number of lights set previously
    int numLightsSetPrev = lightList.size();

    // If more than maxLights are defined, they will be ignored.
    // The GL1 renderer is not permitted to crash due to a
    // GL1 limitation. It must render anything that the GL2 renderer
    // can render (even incorrectly).
    lightList.clear();
    materialAmbientColor.set(0, 0, 0, 0);

    for (int i = 0; i < list.size(); i++) {
      Light l = list.get(i);
      if (l.getType() == Light.Type.Ambient) {
        // Gather
        materialAmbientColor.addLocal(l.getColor());
      } else {
        // Add to list
        lightList.add(l);

        // Once maximum lights reached, exit loop.
        if (lightList.size() >= maxLights) {
          break;
        }
      }
    }

    applyFixedFuncBindings(true);

    glEnable(GL_LIGHTING);

    fb16.clear();
    fb16.put(materialAmbientColor.r)
        .put(materialAmbientColor.g)
        .put(materialAmbientColor.b)
        .put(1)
        .flip();

    glLightModel(GL_LIGHT_MODEL_AMBIENT, fb16);

    if (context.matrixMode != GL_MODELVIEW) {
      glMatrixMode(GL_MODELVIEW);
      context.matrixMode = GL_MODELVIEW;
    }
    // Lights are already in world space, so just convert
    // them to view space.
    glLoadMatrix(storeMatrix(viewMatrix, fb16));

    for (int i = 0; i < lightList.size(); i++) {
      int glLightIndex = GL_LIGHT0 + i;
      Light light = lightList.get(i);
      Light.Type lightType = light.getType();
      ColorRGBA col = light.getColor();
      Vector3f pos;

      // Enable the light
      glEnable(glLightIndex);

      // OGL spec states default value for light ambient is black
      switch (lightType) {
        case Directional:
          DirectionalLight dLight = (DirectionalLight) light;

          fb16.clear();
          fb16.put(col.r).put(col.g).put(col.b).put(col.a).flip();
          glLight(glLightIndex, GL_DIFFUSE, fb16);
          glLight(glLightIndex, GL_SPECULAR, fb16);

          pos = tempVec.set(dLight.getDirection()).negateLocal().normalizeLocal();
          fb16.clear();
          fb16.put(pos.x).put(pos.y).put(pos.z).put(0.0f).flip();
          glLight(glLightIndex, GL_POSITION, fb16);
          glLightf(glLightIndex, GL_SPOT_CUTOFF, 180);
          break;
        case Point:
          PointLight pLight = (PointLight) light;

          fb16.clear();
          fb16.put(col.r).put(col.g).put(col.b).put(col.a).flip();
          glLight(glLightIndex, GL_DIFFUSE, fb16);
          glLight(glLightIndex, GL_SPECULAR, fb16);

          pos = pLight.getPosition();
          fb16.clear();
          fb16.put(pos.x).put(pos.y).put(pos.z).put(1.0f).flip();
          glLight(glLightIndex, GL_POSITION, fb16);
          glLightf(glLightIndex, GL_SPOT_CUTOFF, 180);

          if (pLight.getRadius() > 0) {
            // Note: this doesn't follow the same attenuation model
            // as the one used in the lighting shader.
            glLightf(glLightIndex, GL_CONSTANT_ATTENUATION, 1);
            glLightf(glLightIndex, GL_LINEAR_ATTENUATION, pLight.getInvRadius() * 2);
            glLightf(
                glLightIndex,
                GL_QUADRATIC_ATTENUATION,
                pLight.getInvRadius() * pLight.getInvRadius());
          } else {
            glLightf(glLightIndex, GL_CONSTANT_ATTENUATION, 1);
            glLightf(glLightIndex, GL_LINEAR_ATTENUATION, 0);
            glLightf(glLightIndex, GL_QUADRATIC_ATTENUATION, 0);
          }

          break;
        case Spot:
          SpotLight sLight = (SpotLight) light;

          fb16.clear();
          fb16.put(col.r).put(col.g).put(col.b).put(col.a).flip();
          glLight(glLightIndex, GL_DIFFUSE, fb16);
          glLight(glLightIndex, GL_SPECULAR, fb16);

          pos = sLight.getPosition();
          fb16.clear();
          fb16.put(pos.x).put(pos.y).put(pos.z).put(1.0f).flip();
          glLight(glLightIndex, GL_POSITION, fb16);

          Vector3f dir = sLight.getDirection();
          fb16.clear();
          fb16.put(dir.x).put(dir.y).put(dir.z).put(1.0f).flip();
          glLight(glLightIndex, GL_SPOT_DIRECTION, fb16);

          float outerAngleRad = sLight.getSpotOuterAngle();
          float innerAngleRad = sLight.getSpotInnerAngle();
          float spotCut = outerAngleRad * FastMath.RAD_TO_DEG;
          float spotExpo = 0.0f;
          if (outerAngleRad > 0) {
            spotExpo = (1.0f - (innerAngleRad / outerAngleRad)) * 128.0f;
          }

          glLightf(glLightIndex, GL_SPOT_CUTOFF, spotCut);
          glLightf(glLightIndex, GL_SPOT_EXPONENT, spotExpo);

          if (sLight.getSpotRange() > 0) {
            glLightf(glLightIndex, GL_LINEAR_ATTENUATION, sLight.getInvSpotRange());
          } else {
            glLightf(glLightIndex, GL_LINEAR_ATTENUATION, 0);
          }

          break;
        default:
          throw new UnsupportedOperationException("Unrecognized light type: " + lightType);
      }
    }

    // Disable lights after the index
    for (int i = lightList.size(); i < numLightsSetPrev; i++) {
      glDisable(GL_LIGHT0 + i);
    }

    // This will set view matrix as well.
    setModelView(worldMatrix, viewMatrix);
  }
  private static Mesh genTangentLines(Mesh mesh, float scale) {
    FloatBuffer vertexBuffer = (FloatBuffer) mesh.getBuffer(Type.Position).getData();
    FloatBuffer normalBuffer = (FloatBuffer) mesh.getBuffer(Type.Normal).getData();
    FloatBuffer tangentBuffer = (FloatBuffer) mesh.getBuffer(Type.Tangent).getData();

    FloatBuffer binormalBuffer = null;
    if (mesh.getBuffer(Type.Binormal) != null) {
      binormalBuffer = (FloatBuffer) mesh.getBuffer(Type.Binormal).getData();
    }

    ColorRGBA originColor = ColorRGBA.White;
    ColorRGBA tangentColor = ColorRGBA.Red;
    ColorRGBA binormalColor = ColorRGBA.Green;
    ColorRGBA normalColor = ColorRGBA.Blue;

    Mesh lineMesh = new Mesh();
    lineMesh.setMode(Mesh.Mode.Lines);

    Vector3f origin = new Vector3f();
    Vector3f point = new Vector3f();
    Vector3f tangent = new Vector3f();
    Vector3f normal = new Vector3f();

    IntBuffer lineIndex = BufferUtils.createIntBuffer(vertexBuffer.limit() / 3 * 6);
    FloatBuffer lineVertex = BufferUtils.createFloatBuffer(vertexBuffer.limit() * 4);
    FloatBuffer lineColor = BufferUtils.createFloatBuffer(vertexBuffer.limit() / 3 * 4 * 4);

    boolean hasParity = mesh.getBuffer(Type.Tangent).getNumComponents() == 4;
    float tangentW = 1;

    for (int i = 0; i < vertexBuffer.limit() / 3; i++) {
      populateFromBuffer(origin, vertexBuffer, i);
      populateFromBuffer(normal, normalBuffer, i);

      if (hasParity) {
        tangent.x = tangentBuffer.get(i * 4);
        tangent.y = tangentBuffer.get(i * 4 + 1);
        tangent.z = tangentBuffer.get(i * 4 + 2);
        tangentW = tangentBuffer.get(i * 4 + 3);
      } else {
        populateFromBuffer(tangent, tangentBuffer, i);
      }

      int index = i * 4;

      int id = i * 6;
      lineIndex.put(id, index);
      lineIndex.put(id + 1, index + 1);
      lineIndex.put(id + 2, index);
      lineIndex.put(id + 3, index + 2);
      lineIndex.put(id + 4, index);
      lineIndex.put(id + 5, index + 3);

      setInBuffer(origin, lineVertex, index);
      setInBuffer(originColor, lineColor, index);

      point.set(tangent);
      point.multLocal(scale);
      point.addLocal(origin);
      setInBuffer(point, lineVertex, index + 1);
      setInBuffer(tangentColor, lineColor, index + 1);

      // wvBinormal = cross(wvNormal, wvTangent) * -inTangent.w

      if (binormalBuffer == null) {
        normal.cross(tangent, point);
        point.multLocal(-tangentW);
        point.normalizeLocal();
      } else {
        populateFromBuffer(point, binormalBuffer, i);
      }

      point.multLocal(scale);
      point.addLocal(origin);
      setInBuffer(point, lineVertex, index + 2);
      setInBuffer(binormalColor, lineColor, index + 2);

      point.set(normal);
      point.multLocal(scale);
      point.addLocal(origin);
      setInBuffer(point, lineVertex, index + 3);
      setInBuffer(normalColor, lineColor, index + 3);
    }

    lineMesh.setBuffer(Type.Index, 1, lineIndex);
    lineMesh.setBuffer(Type.Position, 3, lineVertex);
    lineMesh.setBuffer(Type.Color, 4, lineColor);

    lineMesh.setStatic();
    // lineMesh.setInterleaved();
    return lineMesh;
  }
  @Override
  public void updateParticleData(ParticleData[] particles, Camera cam, Matrix3f inverseRotation) {

    for (int i = 0; i < particles.length; i++) {
      ParticleData p = particles[i];
      int offset = templateVerts.capacity() * i;
      int colorOffset = templateColors.capacity() * i;
      if (p.life == 0 || !p.active) {
        for (int x = 0; x < templateVerts.capacity(); x += 3) {
          finVerts.put(offset + x, 0);
          finVerts.put(offset + x + 1, 0);
          finVerts.put(offset + x + 2, 0);
        }
        continue;
      }

      for (int x = 0; x < templateVerts.capacity(); x += 3) {
        switch (emitter.getBillboardMode()) {
          case Velocity:
            if (p.velocity.x != Vector3f.UNIT_Y.x
                && p.velocity.y != Vector3f.UNIT_Y.y
                && p.velocity.z != Vector3f.UNIT_Y.z)
              up.set(p.velocity).crossLocal(Vector3f.UNIT_Y).normalizeLocal();
            else up.set(p.velocity).crossLocal(lock).normalizeLocal();
            left.set(p.velocity).crossLocal(up).normalizeLocal();
            dir.set(p.velocity);
            break;
          case Velocity_Z_Up:
            if (p.velocity.x != Vector3f.UNIT_Y.x
                && p.velocity.y != Vector3f.UNIT_Y.y
                && p.velocity.z != Vector3f.UNIT_Y.z)
              up.set(p.velocity).crossLocal(Vector3f.UNIT_Y).normalizeLocal();
            else up.set(p.velocity).crossLocal(lock).normalizeLocal();
            left.set(p.velocity).crossLocal(up).normalizeLocal();
            dir.set(p.velocity);
            rotStore = tempQ.fromAngleAxis(-90 * FastMath.DEG_TO_RAD, left);
            left = rotStore.mult(left);
            up = rotStore.mult(up);
            break;
          case Velocity_Z_Up_Y_Left:
            up.set(p.velocity).crossLocal(Vector3f.UNIT_Y).normalizeLocal();
            left.set(p.velocity).crossLocal(up).normalizeLocal();
            dir.set(p.velocity);
            tempV3.set(left).crossLocal(up).normalizeLocal();
            rotStore = tempQ.fromAngleAxis(90 * FastMath.DEG_TO_RAD, p.velocity);
            left = rotStore.mult(left);
            up = rotStore.mult(up);
            rotStore = tempQ.fromAngleAxis(-90 * FastMath.DEG_TO_RAD, left);
            up = rotStore.mult(up);
            break;
          case Normal:
            emitter.getShape().setNext(p.triangleIndex);
            tempV3.set(emitter.getShape().getNormal());
            if (tempV3 == Vector3f.UNIT_Y) tempV3.set(p.velocity);

            up.set(tempV3).crossLocal(Vector3f.UNIT_Y).normalizeLocal();
            left.set(tempV3).crossLocal(up).normalizeLocal();
            dir.set(tempV3);
            break;
          case Normal_Y_Up:
            emitter.getShape().setNext(p.triangleIndex);
            tempV3.set(p.velocity);
            if (tempV3 == Vector3f.UNIT_Y) tempV3.set(Vector3f.UNIT_X);

            up.set(Vector3f.UNIT_Y);
            left.set(tempV3).crossLocal(up).normalizeLocal();
            dir.set(tempV3);
            break;
          case Camera:
            up.set(cam.getUp());
            left.set(cam.getLeft());
            dir.set(cam.getDirection());
            break;
          case UNIT_X:
            up.set(Vector3f.UNIT_Y);
            left.set(Vector3f.UNIT_Z);
            dir.set(Vector3f.UNIT_X);
            break;
          case UNIT_Y:
            up.set(Vector3f.UNIT_Z);
            left.set(Vector3f.UNIT_X);
            dir.set(Vector3f.UNIT_Y);
            break;
          case UNIT_Z:
            up.set(Vector3f.UNIT_X);
            left.set(Vector3f.UNIT_Y);
            dir.set(Vector3f.UNIT_Z);
            break;
        }

        tempV3.set(templateVerts.get(x), templateVerts.get(x + 1), templateVerts.get(x + 2));
        tempV3 = rotStore.mult(tempV3);
        tempV3.multLocal(p.size);

        rotStore.fromAngles(p.angles.x, p.angles.y, p.angles.z);
        tempV3 = rotStore.mult(tempV3);

        tempV3.addLocal(p.position);
        if (!emitter.getParticlesFollowEmitter()) {
          tempV3.subtractLocal(
              emitter
                  .getEmitterNode()
                  .getWorldTranslation()
                  .subtract(p.initialPosition)); // .divide(8f));
        }

        finVerts.put(offset + x, tempV3.getX());
        finVerts.put(offset + x + 1, tempV3.getY());
        finVerts.put(offset + x + 2, tempV3.getZ());
      }
      if (p.emitter.getApplyLightingTransform()) {
        for (int v = 0; v < templateNormals.capacity(); v += 3) {
          tempV3.set(
              templateNormals.get(v), templateNormals.get(v + 1), templateNormals.get(v + 2));

          rotStore.fromAngles(p.angles.x, p.angles.y, p.angles.z);
          mat3.set(rotStore.toRotationMatrix());
          float vx = tempV3.x, vy = tempV3.y, vz = tempV3.z;
          tempV3.x = mat3.get(0, 0) * vx + mat3.get(0, 1) * vy + mat3.get(0, 2) * vz;
          tempV3.y = mat3.get(1, 0) * vx + mat3.get(1, 1) * vy + mat3.get(1, 2) * vz;
          tempV3.z = mat3.get(2, 0) * vx + mat3.get(2, 1) * vy + mat3.get(2, 2) * vz;

          finNormals.put(offset + v, tempV3.getX());
          finNormals.put(offset + v + 1, tempV3.getY());
          finNormals.put(offset + v + 2, tempV3.getZ());
        }
      }
      for (int v = 0; v < templateColors.capacity(); v += 4) {
        finColors
            .put(colorOffset + v, p.color.r)
            .put(colorOffset + v + 1, p.color.g)
            .put(colorOffset + v + 2, p.color.b)
            .put(colorOffset + v + 3, p.color.a * p.alpha);
      }
    }

    this.setBuffer(VertexBuffer.Type.Position, 3, finVerts);
    if (particles[0].emitter.getApplyLightingTransform())
      this.setBuffer(VertexBuffer.Type.Normal, 3, finNormals);
    this.setBuffer(VertexBuffer.Type.Color, 4, finColors);

    updateBound();
  }
 public Vector3f getGravity(Vector3f gravity) {
   return gravity.set(this.gravity);
 }
Exemple #29
0
  private static Transform convertPositions(FloatBuffer input, BoundingBox bbox, Buffer output) {
    if (output.capacity() < input.capacity())
      throw new RuntimeException("Output must be at least as large as input!");

    Vector3f offset = bbox.getCenter().negate();
    Vector3f size = new Vector3f(bbox.getXExtent(), bbox.getYExtent(), bbox.getZExtent());
    size.multLocal(2);

    ShortBuffer sb = null;
    ByteBuffer bb = null;
    float dataTypeSize;
    float dataTypeOffset;
    if (output instanceof ShortBuffer) {
      sb = (ShortBuffer) output;
      dataTypeOffset = shortOff;
      dataTypeSize = shortSize;
    } else {
      bb = (ByteBuffer) output;
      dataTypeOffset = byteOff;
      dataTypeSize = byteSize;
    }
    Vector3f scale = new Vector3f();
    scale.set(dataTypeSize, dataTypeSize, dataTypeSize).divideLocal(size);

    Vector3f invScale = new Vector3f();
    invScale.set(size).divideLocal(dataTypeSize);

    offset.multLocal(scale);
    offset.addLocal(dataTypeOffset, dataTypeOffset, dataTypeOffset);

    // offset = (-modelOffset * shortSize)/modelSize + shortOff
    // scale = shortSize / modelSize

    input.clear();
    output.clear();
    Vector3f temp = new Vector3f();
    int vertexCount = input.capacity() / 3;
    for (int i = 0; i < vertexCount; i++) {
      BufferUtils.populateFromBuffer(temp, input, i);

      // offset and scale vector into -32768 ... 32767
      // or into -128 ... 127 if using bytes
      temp.multLocal(scale);
      temp.addLocal(offset);

      // quantize and store
      if (sb != null) {
        short v1 = (short) temp.getX();
        short v2 = (short) temp.getY();
        short v3 = (short) temp.getZ();
        sb.put(v1).put(v2).put(v3);
      } else {
        byte v1 = (byte) temp.getX();
        byte v2 = (byte) temp.getY();
        byte v3 = (byte) temp.getZ();
        bb.put(v1).put(v2).put(v3);
      }
    }

    Transform transform = new Transform();
    transform.setTranslation(offset.negate().multLocal(invScale));
    transform.setScale(invScale);
    return transform;
  }
 @Override
 protected Vector3f deserialize(int i, Vector3f store) {
   int j = i * getTupleSize();
   store.set(array[j], array[j + 1], array[j + 2]);
   return store;
 }