Пример #1
0
 private CollisionShape rotate(CollisionShape shape, Quat4f rot) {
   if (shape instanceof BoxShape) {
     BoxShape box = (BoxShape) shape;
     javax.vecmath.Vector3f extents = box.getHalfExtentsWithMargin(new javax.vecmath.Vector3f());
     com.bulletphysics.linearmath.QuaternionUtil.quatRotate(VecMath.to(rot), extents, extents);
     extents.absolute();
     return new BoxShape(extents);
   } else if (shape instanceof CompoundShape) {
     CompoundShape compound = (CompoundShape) shape;
     CompoundShape newShape = new CompoundShape();
     for (CompoundShapeChild child : compound.getChildList()) {
       CollisionShape rotatedChild = rotate(child.childShape, rot);
       javax.vecmath.Vector3f offset =
           com.bulletphysics.linearmath.QuaternionUtil.quatRotate(
               VecMath.to(rot), child.transform.origin, new javax.vecmath.Vector3f());
       newShape.addChildShape(
           new Transform(
               new javax.vecmath.Matrix4f(VecMath.to(Rotation.none().getQuat4f()), offset, 1.0f)),
           rotatedChild);
     }
     return newShape;
   } else if (shape instanceof ConvexHullShape) {
     ConvexHullShape convexHull = (ConvexHullShape) shape;
     ObjectArrayList<javax.vecmath.Vector3f> transformedVerts = new ObjectArrayList<>();
     for (javax.vecmath.Vector3f vert : convexHull.getPoints()) {
       transformedVerts.add(
           com.bulletphysics.linearmath.QuaternionUtil.quatRotate(
               VecMath.to(rot), vert, new javax.vecmath.Vector3f()));
     }
     return new ConvexHullShape(transformedVerts);
   }
   return shape;
 }
Пример #2
0
 private static Vector3f getEntityDirection(EntityRef entity) {
   LocationComponent loc = entity.getComponent(LocationComponent.class);
   if (loc != null) {
     Quat4f rot = loc.getWorldRotation();
     Vector3f dir = new Vector3f(0, 0, -1);
     QuaternionUtil.quatRotate(rot, dir, dir);
     return dir;
   }
   return new Vector3f();
 }
Пример #3
0
  public static Vector3d quatRotate(Quat4d rotation, Vector3d v, Vector3d out) {
    Quat4d q = new Quat4d(rotation);
    QuaternionUtil.mul(q, v);

    Quat4d tmp = new Quat4d();
    inverse(tmp, rotation);
    q.mul(tmp);

    out.set(q.x, q.y, q.z);
    return out;
  }
Пример #4
0
  protected void doGroundMovement() {
    if (!isOnGround) return;

    // ground movement is as follows, the arrow key dictate the target velocity, and accelleration
    // is
    // added to achieve that. If opposing keys are held the target velocity is set to zero.

    // This is the velocity in the normal plane in the player space
    Vector3f targetVelocity = new Vector3f();
    if (forward) targetVelocity.z += 1;
    if (backward) targetVelocity.z -= 1;
    if (left) targetVelocity.x -= 1;
    if (right) targetVelocity.x += 1;

    if (forward != backward || left != right) {
      targetVelocity.normalize();
      targetVelocity.scale(MAX_SPEED);
    }

    forward = false;
    backward = false;
    left = false;
    right = false;

    Vector3f forward = new Vector3f(0, 0, 1);
    QuaternionUtil.quatRotate(owner.getOrientation(), forward, forward);

    // right = normal x forward
    // forward = right x normal
    Vector3f right = new Vector3f();
    right.cross(surfaceNormal, forward);
    forward.cross(right, surfaceNormal);
    right.normalize();
    forward.normalize();

    Matrix3f transform = new Matrix3f();
    transform.setColumn(0, right);
    transform.setColumn(1, surfaceNormal);
    transform.setColumn(2, forward);

    transform.transform(targetVelocity);

    Vector3f delta = new Vector3f();
    owner.getRigidBody().getLinearVelocity(delta);
    delta.sub(targetVelocity, delta);

    // feet can't pull and don't need to push for now
    // Ds = D - N(N.D)
    Vector3f parComp = new Vector3f(surfaceNormal);
    parComp.scale(surfaceNormal.dot(delta));
    delta.sub(delta, parComp);

    owner.getRigidBody().applyCentralForce(scaleForce(delta));
  }
Пример #5
0
  public TestRig(DynamicsWorld ownerWorld, Vector3f positionOffset, boolean fixed) {
    this.ownerWorld = ownerWorld;

    Transform tmpTrans = new Transform();

    Vector3f up = new Vector3f();
    up.set(0.0f, 1.0f, 0.0f);

    //
    // Setup geometry
    //
    float bodySize = 0.25f;
    float legLength = 0.45f;
    float foreLegLength = 0.75f;
    shapes[0] = new CapsuleShape(bodySize, 0.10f);
    int i;
    for (i = 0; i < NUM_LEGS; i++) {
      shapes[1 + 2 * i] = new CapsuleShape(0.10f, legLength);
      shapes[2 + 2 * i] = new CapsuleShape(0.08f, foreLegLength);
    }

    //
    // Setup rigid bodies
    //
    float height = 0.5f;
    Transform offset = new Transform();
    offset.setIdentity();
    offset.origin.set(positionOffset);

    // root
    Vector3f root = new Vector3f();
    root.set(0.0f, height, 0.0f);
    Transform transform = new Transform();
    transform.setIdentity();
    transform.origin.set(root);
    tmpTrans.mul(offset, transform);
    if (fixed) {
      bodies[0] = localCreateRigidBody(0.0f, tmpTrans, shapes[0]);
    } else {
      bodies[0] = localCreateRigidBody(1.0f, tmpTrans, shapes[0]);
    }
    // legs
    for (i = 0; i < NUM_LEGS; i++) {
      float angle = BulletGlobals.SIMD_2_PI * i / NUM_LEGS;
      float sin = (float) Math.sin(angle);
      float cos = (float) Math.cos(angle);

      transform.setIdentity();
      Vector3f boneOrigin = new Vector3f();
      boneOrigin.set(
          cos * (bodySize + 0.5f * legLength), height, sin * (bodySize + 0.5f * legLength));
      transform.origin.set(boneOrigin);

      // thigh
      Vector3f toBone = new Vector3f(boneOrigin);
      toBone.sub(root);
      toBone.normalize();
      Vector3f axis = new Vector3f();
      axis.cross(toBone, up);
      Quat4f q = new Quat4f();
      QuaternionUtil.setRotation(q, axis, BulletGlobals.SIMD_HALF_PI);
      transform.setRotation(q);
      tmpTrans.mul(offset, transform);
      bodies[1 + 2 * i] = localCreateRigidBody(1.0f, tmpTrans, shapes[1 + 2 * i]);

      // shin
      transform.setIdentity();
      transform.origin.set(
          cos * (bodySize + legLength),
          height - 0.5f * foreLegLength,
          sin * (bodySize + legLength));
      tmpTrans.mul(offset, transform);
      bodies[2 + 2 * i] = localCreateRigidBody(1.0f, tmpTrans, shapes[2 + 2 * i]);
    }

    // Setup some damping on the bodies
    for (i = 0; i < BODYPART_COUNT; ++i) {
      bodies[i].setDamping(0.05f, 0.85f);
      bodies[i].setDeactivationTime(0.8f);
      bodies[i].setSleepingThresholds(1.6f, 2.5f);
    }

    //
    // Setup the constraints
    //
    HingeConstraint hingeC;
    // ConeTwistConstraint* coneC;

    Transform localA = new Transform();
    Transform localB = new Transform();
    Transform localC = new Transform();

    for (i = 0; i < NUM_LEGS; i++) {
      float angle = BulletGlobals.SIMD_2_PI * i / NUM_LEGS;
      float sin = (float) Math.sin(angle);
      float cos = (float) Math.cos(angle);

      // hip joints
      localA.setIdentity();
      localB.setIdentity();
      MatrixUtil.setEulerZYX(localA.basis, 0, -angle, 0);
      localA.origin.set(cos * bodySize, 0.0f, sin * bodySize);
      tmpTrans.inverse(bodies[1 + 2 * i].getWorldTransform(new Transform()));
      tmpTrans.mul(tmpTrans, bodies[0].getWorldTransform(new Transform()));
      localB.mul(tmpTrans, localA);
      hingeC = new HingeConstraint(bodies[0], bodies[1 + 2 * i], localA, localB);
      hingeC.setLimit(-0.75f * BulletGlobals.SIMD_2_PI * 0.125f, BulletGlobals.SIMD_2_PI * 0.0625f);
      // hingeC.setLimit(-0.1f, 0.1f);
      joints[2 * i] = hingeC;
      ownerWorld.addConstraint(joints[2 * i], true);

      // knee joints
      localA.setIdentity();
      localB.setIdentity();
      localC.setIdentity();
      MatrixUtil.setEulerZYX(localA.basis, 0, -angle, 0);
      localA.origin.set(cos * (bodySize + legLength), 0.0f, sin * (bodySize + legLength));
      tmpTrans.inverse(bodies[1 + 2 * i].getWorldTransform(new Transform()));
      tmpTrans.mul(tmpTrans, bodies[0].getWorldTransform(new Transform()));
      localB.mul(tmpTrans, localA);
      tmpTrans.inverse(bodies[2 + 2 * i].getWorldTransform(new Transform()));
      tmpTrans.mul(tmpTrans, bodies[0].getWorldTransform(new Transform()));
      localC.mul(tmpTrans, localA);
      hingeC = new HingeConstraint(bodies[1 + 2 * i], bodies[2 + 2 * i], localB, localC);
      // hingeC.setLimit(-0.01f, 0.01f);
      hingeC.setLimit(-BulletGlobals.SIMD_2_PI * 0.0625f, 0.2f);
      joints[1 + 2 * i] = hingeC;
      ownerWorld.addConstraint(joints[1 + 2 * i], true);
    }
  }
  @Override
  public void buildJacobian() {
    Vector3f tmp = Stack.alloc(Vector3f.class);
    Vector3f tmp1 = Stack.alloc(Vector3f.class);
    Vector3f tmp2 = Stack.alloc(Vector3f.class);

    Transform tmpTrans = Stack.alloc(Transform.class);

    appliedImpulse = 0f;

    // set bias, sign, clear accumulator
    swingCorrection = 0f;
    twistLimitSign = 0f;
    solveTwistLimit = false;
    solveSwingLimit = false;
    accTwistLimitImpulse = 0f;
    accSwingLimitImpulse = 0f;

    if (!angularOnly) {
      Vector3f pivotAInW = Stack.alloc(rbAFrame.origin);
      rbA.getCenterOfMassTransform(tmpTrans).transform(pivotAInW);

      Vector3f pivotBInW = Stack.alloc(rbBFrame.origin);
      rbB.getCenterOfMassTransform(tmpTrans).transform(pivotBInW);

      Vector3f relPos = Stack.alloc(Vector3f.class);
      relPos.sub(pivotBInW, pivotAInW);

      // TODO: stack
      Vector3f[] normal /*[3]*/ =
          new Vector3f[] {
            Stack.alloc(Vector3f.class), Stack.alloc(Vector3f.class), Stack.alloc(Vector3f.class)
          };
      if (relPos.lengthSquared() > BulletGlobals.FLT_EPSILON) {
        normal[0].normalize(relPos);
      } else {
        normal[0].set(1f, 0f, 0f);
      }

      TransformUtil.planeSpace1(normal[0], normal[1], normal[2]);

      for (int i = 0; i < 3; i++) {
        Matrix3f mat1 = rbA.getCenterOfMassTransform(Stack.alloc(Transform.class)).basis;
        mat1.transpose();

        Matrix3f mat2 = rbB.getCenterOfMassTransform(Stack.alloc(Transform.class)).basis;
        mat2.transpose();

        tmp1.sub(pivotAInW, rbA.getCenterOfMassPosition(tmp));
        tmp2.sub(pivotBInW, rbB.getCenterOfMassPosition(tmp));

        jac[i].init(
            mat1,
            mat2,
            tmp1,
            tmp2,
            normal[i],
            rbA.getInvInertiaDiagLocal(Stack.alloc(Vector3f.class)),
            rbA.getInvMass(),
            rbB.getInvInertiaDiagLocal(Stack.alloc(Vector3f.class)),
            rbB.getInvMass());
      }
    }

    Vector3f b1Axis1 = Stack.alloc(Vector3f.class),
        b1Axis2 = Stack.alloc(Vector3f.class),
        b1Axis3 = Stack.alloc(Vector3f.class);
    Vector3f b2Axis1 = Stack.alloc(Vector3f.class), b2Axis2 = Stack.alloc(Vector3f.class);

    rbAFrame.basis.getColumn(0, b1Axis1);
    getRigidBodyA().getCenterOfMassTransform(tmpTrans).basis.transform(b1Axis1);

    rbBFrame.basis.getColumn(0, b2Axis1);
    getRigidBodyB().getCenterOfMassTransform(tmpTrans).basis.transform(b2Axis1);

    float swing1 = 0f, swing2 = 0f;

    float swx = 0f, swy = 0f;
    float thresh = 10f;
    float fact;

    // Get Frame into world space
    if (swingSpan1 >= 0.05f) {
      rbAFrame.basis.getColumn(1, b1Axis2);
      getRigidBodyA().getCenterOfMassTransform(tmpTrans).basis.transform(b1Axis2);
      //			swing1 = ScalarUtil.atan2Fast(b2Axis1.dot(b1Axis2), b2Axis1.dot(b1Axis1));
      swx = b2Axis1.dot(b1Axis1);
      swy = b2Axis1.dot(b1Axis2);
      swing1 = ScalarUtil.atan2Fast(swy, swx);
      fact = (swy * swy + swx * swx) * thresh * thresh;
      fact = fact / (fact + 1f);
      swing1 *= fact;
    }

    if (swingSpan2 >= 0.05f) {
      rbAFrame.basis.getColumn(2, b1Axis3);
      getRigidBodyA().getCenterOfMassTransform(tmpTrans).basis.transform(b1Axis3);
      //			swing2 = ScalarUtil.atan2Fast(b2Axis1.dot(b1Axis3), b2Axis1.dot(b1Axis1));
      swx = b2Axis1.dot(b1Axis1);
      swy = b2Axis1.dot(b1Axis3);
      swing2 = ScalarUtil.atan2Fast(swy, swx);
      fact = (swy * swy + swx * swx) * thresh * thresh;
      fact = fact / (fact + 1f);
      swing2 *= fact;
    }

    float RMaxAngle1Sq = 1.0f / (swingSpan1 * swingSpan1);
    float RMaxAngle2Sq = 1.0f / (swingSpan2 * swingSpan2);
    float EllipseAngle =
        Math.abs(swing1 * swing1) * RMaxAngle1Sq + Math.abs(swing2 * swing2) * RMaxAngle2Sq;

    if (EllipseAngle > 1.0f) {
      swingCorrection = EllipseAngle - 1.0f;
      solveSwingLimit = true;

      // Calculate necessary axis & factors
      tmp1.scale(b2Axis1.dot(b1Axis2), b1Axis2);
      tmp2.scale(b2Axis1.dot(b1Axis3), b1Axis3);
      tmp.add(tmp1, tmp2);
      swingAxis.cross(b2Axis1, tmp);
      swingAxis.normalize();

      float swingAxisSign = (b2Axis1.dot(b1Axis1) >= 0.0f) ? 1.0f : -1.0f;
      swingAxis.scale(swingAxisSign);

      kSwing =
          1f
              / (getRigidBodyA().computeAngularImpulseDenominator(swingAxis)
                  + getRigidBodyB().computeAngularImpulseDenominator(swingAxis));
    }

    // Twist limits
    if (twistSpan >= 0f) {
      // Vector3f b2Axis2 = Stack.alloc(Vector3f.class);
      rbBFrame.basis.getColumn(1, b2Axis2);
      getRigidBodyB().getCenterOfMassTransform(tmpTrans).basis.transform(b2Axis2);

      Quat4f rotationArc =
          QuaternionUtil.shortestArcQuat(b2Axis1, b1Axis1, Stack.alloc(Quat4f.class));
      Vector3f TwistRef =
          QuaternionUtil.quatRotate(rotationArc, b2Axis2, Stack.alloc(Vector3f.class));
      float twist = ScalarUtil.atan2Fast(TwistRef.dot(b1Axis3), TwistRef.dot(b1Axis2));

      float lockedFreeFactor = (twistSpan > 0.05f) ? limitSoftness : 0f;
      if (twist <= -twistSpan * lockedFreeFactor) {
        twistCorrection = -(twist + twistSpan);
        solveTwistLimit = true;

        twistAxis.add(b2Axis1, b1Axis1);
        twistAxis.scale(0.5f);
        twistAxis.normalize();
        twistAxis.scale(-1.0f);

        kTwist =
            1f
                / (getRigidBodyA().computeAngularImpulseDenominator(twistAxis)
                    + getRigidBodyB().computeAngularImpulseDenominator(twistAxis));

      } else if (twist > twistSpan * lockedFreeFactor) {
        twistCorrection = (twist - twistSpan);
        solveTwistLimit = true;

        twistAxis.add(b2Axis1, b1Axis1);
        twistAxis.scale(0.5f);
        twistAxis.normalize();

        kTwist =
            1f
                / (getRigidBodyA().computeAngularImpulseDenominator(twistAxis)
                    + getRigidBodyB().computeAngularImpulseDenominator(twistAxis));
      }
    }
  }
Пример #7
0
    public boolean EncloseOrigin() {
      Vector3f tmp = Stack.alloc(Vector3f.class);
      Vector3f tmp1 = Stack.alloc(Vector3f.class);
      Vector3f tmp2 = Stack.alloc(Vector3f.class);

      switch (order) {
          // Point
        case 0:
          break;
          // Line
        case 1:
          {
            Vector3f ab = Stack.alloc(Vector3f.class);
            ab.sub(simplex[1].w, simplex[0].w);

            Vector3f[] b =
                new Vector3f[] {
                  Stack.alloc(Vector3f.class),
                  Stack.alloc(Vector3f.class),
                  Stack.alloc(Vector3f.class)
                };
            b[0].set(1f, 0f, 0f);
            b[1].set(0f, 1f, 0f);
            b[2].set(0f, 0f, 1f);

            b[0].cross(ab, b[0]);
            b[1].cross(ab, b[1]);
            b[2].cross(ab, b[2]);

            float m[] =
                new float[] {b[0].lengthSquared(), b[1].lengthSquared(), b[2].lengthSquared()};

            Quat4f tmpQuat = Stack.alloc(Quat4f.class);
            tmp.normalize(ab);
            QuaternionUtil.setRotation(tmpQuat, tmp, cst2Pi / 3f);

            Matrix3f r = Stack.alloc(Matrix3f.class);
            MatrixUtil.setRotation(r, tmpQuat);

            Vector3f w = Stack.alloc(Vector3f.class);
            w.set(b[m[0] > m[1] ? m[0] > m[2] ? 0 : 2 : m[1] > m[2] ? 1 : 2]);

            tmp.normalize(w);
            Support(tmp, simplex[4]);
            r.transform(w);
            tmp.normalize(w);
            Support(tmp, simplex[2]);
            r.transform(w);
            tmp.normalize(w);
            Support(tmp, simplex[3]);
            r.transform(w);
            order = 4;
            return (true);
          }
          // Triangle
        case 2:
          {
            tmp1.sub(simplex[1].w, simplex[0].w);
            tmp2.sub(simplex[2].w, simplex[0].w);
            Vector3f n = Stack.alloc(Vector3f.class);
            n.cross(tmp1, tmp2);
            n.normalize();

            Support(n, simplex[3]);

            tmp.negate(n);
            Support(tmp, simplex[4]);
            order = 4;
            return (true);
          }
          // Tetrahedron
        case 3:
          return (true);
          // Hexahedron
        case 4:
          return (true);
      }
      return (false);
    }