@Override
 public void getEdge(int i, Vector3f pa, Vector3f pb) {
   int index0 = i % points.size();
   int index1 = (i + 1) % points.size();
   VectorUtil.mul(pa, points.getQuick(index0), localScaling);
   VectorUtil.mul(pb, points.getQuick(index1), localScaling);
 }
  @Override
  public Vector3 localGetSupportingVertexWithoutMargin(Vector3 vec0, Vector3 out) {
    Stack stack = Stack.enter();
    Vector3 supVec = out;
    supVec.set(0f, 0f, 0f);

    float maxDot = -1e30f;

    Vector3 vec = stack.alloc(vec0);
    float lenSqr = vec.len2();
    if (lenSqr < 0.0001f) {
      vec.set(1f, 0f, 0f);
    } else {
      float rlen = 1f / (float) Math.sqrt(lenSqr);
      vec.scl(rlen);
    }

    Vector3 vtx = stack.allocVector3();
    float newDot;

    float radius = getRadius();

    Vector3 tmp1 = stack.allocVector3();
    Vector3 tmp2 = stack.allocVector3();
    Vector3 pos = stack.allocVector3();

    {
      pos.set(0f, 0f, 0f);
      VectorUtil.setCoord(pos, getUpAxis(), getHalfHeight());

      VectorUtil.mul(tmp1, vec, localScaling);
      tmp1.scl(radius);
      tmp2.set(vec).scl(getMargin());
      vtx.set(pos).add(tmp1);
      vtx.sub(tmp2);
      newDot = vec.dot(vtx);
      if (newDot > maxDot) {
        maxDot = newDot;
        supVec.set(vtx);
      }
    }
    {
      pos.set(0f, 0f, 0f);
      VectorUtil.setCoord(pos, getUpAxis(), -getHalfHeight());

      VectorUtil.mul(tmp1, vec, localScaling);
      tmp1.scl(radius);
      tmp2.set(vec).scl(getMargin());
      vtx.set(pos).add(tmp1);
      vtx.sub(tmp2);
      newDot = vec.dot(vtx);
      if (newDot > maxDot) {
        maxDot = newDot;
        supVec.set(vtx);
      }
    }
    stack.leave();
    return out;
  }
  @Override
  public void getAabb(Transform t, Vector3 aabbMin, Vector3 aabbMax) {
    Stack stack = Stack.enter();
    Vector3 tmp = stack.allocVector3();

    Vector3 halfExtents = stack.allocVector3();
    halfExtents.set(getRadius(), getRadius(), getRadius());
    VectorUtil.setCoord(halfExtents, upAxis, getRadius() + getHalfHeight());

    halfExtents.x += getMargin();
    halfExtents.y += getMargin();
    halfExtents.z += getMargin();

    Matrix3 abs_b = stack.allocMatrix3();
    abs_b.set(t.basis);
    MatrixUtil.absolute(abs_b);

    Vector3 center = t.origin;
    Vector3 extent = stack.allocVector3();

    MatrixUtil.getRow(abs_b, 0, tmp);
    extent.x = tmp.dot(halfExtents);
    MatrixUtil.getRow(abs_b, 1, tmp);
    extent.y = tmp.dot(halfExtents);
    MatrixUtil.getRow(abs_b, 2, tmp);
    extent.z = tmp.dot(halfExtents);

    aabbMin.set(center).sub(extent);
    aabbMax.set(center).add(extent);
    stack.leave();
  }
  @Override
  public void calculateLocalInertia(float mass, Vector3 inertia) {
    // as an approximation, take the inertia of the box that bounds the spheres

    Stack stack = Stack.enter();
    Transform ident = stack.allocTransform();
    ident.setIdentity();

    float radius = getRadius();

    Vector3 halfExtents = stack.allocVector3();
    halfExtents.set(radius, radius, radius);
    VectorUtil.setCoord(halfExtents, getUpAxis(), radius + getHalfHeight());

    float margin = BulletGlobals.CONVEX_DISTANCE_MARGIN;

    float lx = 2f * (halfExtents.x + margin);
    float ly = 2f * (halfExtents.y + margin);
    float lz = 2f * (halfExtents.z + margin);
    float x2 = lx * lx;
    float y2 = ly * ly;
    float z2 = lz * lz;
    float scaledmass = mass * 0.08333333f;

    inertia.x = scaledmass * (y2 + z2);
    inertia.y = scaledmass * (x2 + z2);
    inertia.z = scaledmass * (x2 + y2);
    stack.leave();
  }
  @Override
  public Vector3f localGetSupportingVertexWithoutMargin(Vector3f vec0, Vector3f out) {
    Vector3f supVec = out;
    supVec.set(0f, 0f, 0f);
    float newDot, maxDot = -1e30f;

    Vector3f vec = Stack.alloc(vec0);
    float lenSqr = vec.lengthSquared();
    if (lenSqr < 0.0001f) {
      vec.set(1f, 0f, 0f);
    } else {
      float rlen = 1f / (float) Math.sqrt(lenSqr);
      vec.scale(rlen);
    }

    Vector3f vtx = Stack.alloc(Vector3f.class);
    for (int i = 0; i < points.size(); i++) {
      VectorUtil.mul(vtx, points.getQuick(i), localScaling);

      newDot = vec.dot(vtx);
      if (newDot > maxDot) {
        maxDot = newDot;
        supVec.set(vtx);
      }
    }
    return out;
  }
  @Override
  public void batchedUnitVectorGetSupportingVertexWithoutMargin(
      Vector3f[] vectors, Vector3f[] supportVerticesOut, int numVectors) {
    float newDot;

    // JAVA NOTE: rewritten as code used W coord for temporary usage in Vector3
    // TODO: optimize it
    float[] wcoords = new float[numVectors];

    // use 'w' component of supportVerticesOut?
    {
      for (int i = 0; i < numVectors; i++) {
        // supportVerticesOut[i][3] = btScalar(-1e30);
        wcoords[i] = -1e30f;
      }
    }
    Vector3f vtx = Stack.alloc(Vector3f.class);
    for (int i = 0; i < points.size(); i++) {
      VectorUtil.mul(vtx, points.getQuick(i), localScaling);

      for (int j = 0; j < numVectors; j++) {
        Vector3f vec = vectors[j];

        newDot = vec.dot(vtx);
        // if (newDot > supportVerticesOut[j][3])
        if (newDot > wcoords[j]) {
          // WARNING: don't swap next lines, the w component would get overwritten!
          supportVerticesOut[j].set(vtx);
          // supportVerticesOut[j][3] = newDot;
          wcoords[j] = newDot;
        }
      }
    }
  }
 public void internalProcessTriangleIndex(Vector3f[] triangle, int partId, int triangleIndex) {
   VectorUtil.setMin(aabbMin, triangle[0]);
   VectorUtil.setMax(aabbMax, triangle[0]);
   VectorUtil.setMin(aabbMin, triangle[1]);
   VectorUtil.setMax(aabbMax, triangle[1]);
   VectorUtil.setMin(aabbMin, triangle[2]);
   VectorUtil.setMax(aabbMax, triangle[2]);
 }
 public float getHalfHeight() {
   return VectorUtil.getCoord(implicitShapeDimensions, upAxis);
 }
 public float getRadius() {
   int radiusAxis = (upAxis + 2) % 3;
   return VectorUtil.getCoord(implicitShapeDimensions, radiusAxis);
 }
Beispiel #10
0
  public boolean calcTimeOfImpact(
      Transform fromA, Transform toA, Transform fromB, Transform toB, CastResult result) {
    simplexSolver.reset();

    // compute linear velocity for this interval, to interpolate
    // assume no rotation/angular velocity, assert here?
    Vector3d linVelA = new Vector3d();
    Vector3d linVelB = new Vector3d();

    linVelA.sub(toA.origin, fromA.origin);
    linVelB.sub(toB.origin, fromB.origin);

    double radius = 0.001f;
    double lambda = 0f;
    Vector3d v = new Vector3d();
    v.set(1f, 0f, 0f);

    int maxIter = MAX_ITERATIONS;

    Vector3d n = new Vector3d();
    n.set(0f, 0f, 0f);
    boolean hasResult = false;
    Vector3d c = new Vector3d();
    Vector3d r = new Vector3d();
    r.sub(linVelA, linVelB);

    double lastLambda = lambda;
    // btScalar epsilon = btScalar(0.001);

    int numIter = 0;
    // first solution, using GJK

    Transform identityTrans = new Transform();
    identityTrans.setIdentity();

    // result.drawCoordSystem(sphereTr);

    PointCollector pointCollector = new PointCollector();

    gjk.init(convexA, convexB, simplexSolver, null); // penetrationDepthSolver);	
    ClosestPointInput input = pointInputsPool.get();
    input.init();
    try {
      // we don't use margins during CCD
      //	gjk.setIgnoreMargin(true);

      input.transformA.set(fromA);
      input.transformB.set(fromB);
      gjk.getClosestPoints(input, pointCollector, null);

      hasResult = pointCollector.hasResult;
      c.set(pointCollector.pointInWorld);

      if (hasResult) {
        double dist;
        dist = pointCollector.distance;
        n.set(pointCollector.normalOnBInWorld);

        // not close enough
        while (dist > radius) {
          numIter++;
          if (numIter > maxIter) {
            return false; // todo: report a failure
          }
          double dLambda = 0f;

          double projectedLinearVelocity = r.dot(n);

          dLambda = dist / (projectedLinearVelocity);

          lambda = lambda - dLambda;

          if (lambda > 1f) {
            return false;
          }
          if (lambda < 0f) {
            return false; // todo: next check with relative epsilon
          }

          if (lambda <= lastLambda) {
            return false;
            // n.setValue(0,0,0);
            // break;
          }
          lastLambda = lambda;

          // interpolate to next lambda
          result.debugDraw(lambda);
          VectorUtil.setInterpolate3(input.transformA.origin, fromA.origin, toA.origin, lambda);
          VectorUtil.setInterpolate3(input.transformB.origin, fromB.origin, toB.origin, lambda);

          gjk.getClosestPoints(input, pointCollector, null);
          if (pointCollector.hasResult) {
            if (pointCollector.distance < 0f) {
              result.fraction = lastLambda;
              n.set(pointCollector.normalOnBInWorld);
              result.normal.set(n);
              result.hitPoint.set(pointCollector.pointInWorld);
              return true;
            }
            c.set(pointCollector.pointInWorld);
            n.set(pointCollector.normalOnBInWorld);
            dist = pointCollector.distance;
          } else {
            // ??
            return false;
          }
        }

        // is n normalized?
        // don't report time of impact for motion away from the contact normal (or causes minor
        // penetration)
        if (n.dot(r) >= -result.allowedPenetration) {
          return false;
        }
        result.fraction = lambda;
        result.normal.set(n);
        result.hitPoint.set(c);
        return true;
      }

      return false;
    } finally {
      pointInputsPool.release(input);
    }
  }
 @Override
 public void getVertex(int i, Vector3f vtx) {
   VectorUtil.mul(vtx, points.getQuick(i), localScaling);
 }
Beispiel #12
0
    public float EvaluatePD(float accuracy) {
      pushStack();
      try {
        Vector3f tmp = Stack.alloc(Vector3f.class);

        // btBlock* sablock = sa->beginBlock();
        Face bestface = null;
        int markid = 1;
        depth = -cstInf;
        normal.set(0f, 0f, 0f);
        root = null;
        nfaces = 0;
        iterations = 0;
        failed = false;
        /* Prepare hull		*/
        if (gjk.EncloseOrigin()) {
          // const U* pfidx = 0;
          int[][] pfidx_ptr = null;
          int pfidx_index = 0;

          int nfidx = 0;
          // const U* peidx = 0;
          int[][] peidx_ptr = null;
          int peidx_index = 0;

          int neidx = 0;
          Mkv[] basemkv = new Mkv[5];
          Face[] basefaces = new Face[6];
          switch (gjk.order) {
              // Tetrahedron
            case 3:
              {
                // pfidx=(const U*)fidx;
                pfidx_ptr = tetrahedron_fidx;
                pfidx_index = 0;

                nfidx = 4;

                // peidx=(const U*)eidx;
                peidx_ptr = tetrahedron_eidx;
                peidx_index = 0;

                neidx = 6;
              }
              break;
              // Hexahedron
            case 4:
              {
                // pfidx=(const U*)fidx;
                pfidx_ptr = hexahedron_fidx;
                pfidx_index = 0;

                nfidx = 6;

                // peidx=(const U*)eidx;
                peidx_ptr = hexahedron_eidx;
                peidx_index = 0;

                neidx = 9;
              }
              break;
          }
          int i;

          for (i = 0; i <= gjk.order; ++i) {
            basemkv[i] = new Mkv();
            basemkv[i].set(gjk.simplex[i]);
          }
          for (i = 0; i < nfidx; ++i, pfidx_index++) {
            basefaces[i] =
                NewFace(
                    basemkv[pfidx_ptr[pfidx_index][0]],
                    basemkv[pfidx_ptr[pfidx_index][1]],
                    basemkv[pfidx_ptr[pfidx_index][2]]);
          }
          for (i = 0; i < neidx; ++i, peidx_index++) {
            Link(
                basefaces[peidx_ptr[peidx_index][0]],
                peidx_ptr[peidx_index][1],
                basefaces[peidx_ptr[peidx_index][2]],
                peidx_ptr[peidx_index][3]);
          }
        }
        if (0 == nfaces) {
          // sa->endBlock(sablock);
          return (depth);
        }
        /* Expand hull		*/
        for (; iterations < EPA_maxiterations; ++iterations) {
          Face bf = FindBest();
          if (bf != null) {
            tmp.negate(bf.n);
            Mkv w = Support(tmp);
            float d = bf.n.dot(w.w) + bf.d;
            bestface = bf;
            if (d < -accuracy) {
              Face[] cf = new Face[] {null};
              Face[] ff = new Face[] {null};
              int nf = 0;
              Detach(bf);
              bf.mark = ++markid;
              for (int i = 0; i < 3; ++i) {
                nf += BuildHorizon(markid, w, bf.f[i], bf.e[i], cf, ff);
              }
              if (nf <= 2) {
                break;
              }
              Link(cf[0], 1, ff[0], 2);
            } else {
              break;
            }
          } else {
            break;
          }
        }
        /* Extract contact	*/
        if (bestface != null) {
          Vector3f b = GetCoordinates(bestface, Stack.alloc(Vector3f.class));
          normal.set(bestface.n);
          depth = Math.max(0, bestface.d);
          for (int i = 0; i < 2; ++i) {
            float s = i != 0 ? -1f : 1f;
            for (int j = 0; j < 3; ++j) {
              tmp.scale(s, bestface.v[j].r);
              gjk.LocalSupport(tmp, i, features[i][j]);
            }
          }

          Vector3f tmp1 = Stack.alloc(Vector3f.class);
          Vector3f tmp2 = Stack.alloc(Vector3f.class);
          Vector3f tmp3 = Stack.alloc(Vector3f.class);

          tmp1.scale(b.x, features[0][0]);
          tmp2.scale(b.y, features[0][1]);
          tmp3.scale(b.z, features[0][2]);
          VectorUtil.add(nearest[0], tmp1, tmp2, tmp3);

          tmp1.scale(b.x, features[1][0]);
          tmp2.scale(b.y, features[1][1]);
          tmp3.scale(b.z, features[1][2]);
          VectorUtil.add(nearest[1], tmp1, tmp2, tmp3);
        } else {
          failed = true;
        }
        // sa->endBlock(sablock);
        return (depth);
      } finally {
        popStack();
      }
    }