/*
|
* Java port of Bullet (c) 2008 Martin Dvorak <jezek2@advel.cz>
|
*
|
* Bullet Continuous Collision Detection and Physics Library
|
* Copyright (c) 2003-2008 Erwin Coumans http://www.bulletphysics.com/
|
*
|
* This software is provided 'as-is', without any express or implied warranty.
|
* In no event will the authors be held liable for any damages arising from
|
* the use of this software.
|
*
|
* Permission is granted to anyone to use this software for any purpose,
|
* including commercial applications, and to alter it and redistribute it
|
* freely, subject to the following restrictions:
|
*
|
* 1. The origin of this software must not be misrepresented; you must not
|
* claim that you wrote the original software. If you use this software
|
* in a product, an acknowledgment in the product documentation would be
|
* appreciated but is not required.
|
* 2. Altered source versions must be plainly marked as such, and must not be
|
* misrepresented as being the original software.
|
* 3. This notice may not be removed or altered from any source distribution.
|
*/
|
|
package com.bulletphysics.collision.shapes;
|
|
import com.bulletphysics.linearmath.AabbUtil2;
|
import com.bulletphysics.linearmath.MatrixUtil;
|
import com.bulletphysics.linearmath.Transform;
|
import com.bulletphysics.linearmath.VectorUtil;
|
import cz.advel.stack.Stack;
|
import javax.vecmath.Matrix3f;
|
import javax.vecmath.Vector3f;
|
|
/**
|
* Concave triangle mesh abstract class. Use {@link BvhTriangleMeshShape} as concrete
|
* implementation.
|
*
|
* @author jezek2
|
*/
|
public abstract class TriangleMeshShape extends ConcaveShape {
|
|
protected final Vector3f localAabbMin = new Vector3f();
|
protected final Vector3f localAabbMax = new Vector3f();
|
protected StridingMeshInterface meshInterface;
|
|
/**
|
* TriangleMeshShape constructor has been disabled/protected, so that users will not mistakenly use this class.
|
* Don't use btTriangleMeshShape but use btBvhTriangleMeshShape instead!
|
*/
|
protected TriangleMeshShape(StridingMeshInterface meshInterface) {
|
this.meshInterface = meshInterface;
|
|
// JAVA NOTE: moved to BvhTriangleMeshShape
|
//recalcLocalAabb();
|
}
|
|
public Vector3f localGetSupportingVertex(Vector3f vec, Vector3f out) {
|
Vector3f tmp = Stack.alloc(Vector3f.class);
|
|
Vector3f supportVertex = out;
|
|
Transform ident = Stack.alloc(Transform.class);
|
ident.setIdentity();
|
|
SupportVertexCallback supportCallback = new SupportVertexCallback(vec, ident);
|
|
Vector3f aabbMax = Stack.alloc(Vector3f.class);
|
aabbMax.set(1e30f, 1e30f, 1e30f);
|
tmp.negate(aabbMax);
|
|
processAllTriangles(supportCallback, tmp, aabbMax);
|
|
supportCallback.getSupportVertexLocal(supportVertex);
|
|
return out;
|
}
|
|
public Vector3f localGetSupportingVertexWithoutMargin(Vector3f vec, Vector3f out) {
|
assert (false);
|
return localGetSupportingVertex(vec, out);
|
}
|
|
public void recalcLocalAabb() {
|
for (int i = 0; i < 3; i++) {
|
Vector3f vec = Stack.alloc(Vector3f.class);
|
vec.set(0f, 0f, 0f);
|
VectorUtil.setCoord(vec, i, 1f);
|
Vector3f tmp = localGetSupportingVertex(vec, Stack.alloc(Vector3f.class));
|
VectorUtil.setCoord(localAabbMax, i, VectorUtil.getCoord(tmp, i) + collisionMargin);
|
VectorUtil.setCoord(vec, i, -1f);
|
localGetSupportingVertex(vec, tmp);
|
VectorUtil.setCoord(localAabbMin, i, VectorUtil.getCoord(tmp, i) - collisionMargin);
|
}
|
}
|
|
@Override
|
public void getAabb(Transform trans, Vector3f aabbMin, Vector3f aabbMax) {
|
Vector3f tmp = Stack.alloc(Vector3f.class);
|
|
Vector3f localHalfExtents = Stack.alloc(Vector3f.class);
|
localHalfExtents.sub(localAabbMax, localAabbMin);
|
localHalfExtents.scale(0.5f);
|
|
Vector3f localCenter = Stack.alloc(Vector3f.class);
|
localCenter.add(localAabbMax, localAabbMin);
|
localCenter.scale(0.5f);
|
|
Matrix3f abs_b = (Matrix3f) Stack.alloc(trans.basis);
|
MatrixUtil.absolute(abs_b);
|
|
Vector3f center = (Vector3f) Stack.alloc(localCenter);
|
trans.transform(center);
|
|
Vector3f extent = Stack.alloc(Vector3f.class);
|
abs_b.getRow(0, tmp);
|
extent.x = tmp.dot(localHalfExtents);
|
abs_b.getRow(1, tmp);
|
extent.y = tmp.dot(localHalfExtents);
|
abs_b.getRow(2, tmp);
|
extent.z = tmp.dot(localHalfExtents);
|
|
Vector3f margin = Stack.alloc(Vector3f.class);
|
margin.set(getMargin(), getMargin(), getMargin());
|
extent.add(margin);
|
|
aabbMin.sub(center, extent);
|
aabbMax.add(center, extent);
|
}
|
|
@Override
|
public void processAllTriangles(TriangleCallback callback, Vector3f aabbMin, Vector3f aabbMax) {
|
FilteredCallback filterCallback = new FilteredCallback(callback, aabbMin, aabbMax);
|
|
meshInterface.internalProcessAllTriangles(filterCallback, aabbMin, aabbMax);
|
}
|
|
@Override
|
public void calculateLocalInertia(float mass, Vector3f inertia) {
|
// moving concave objects not supported
|
assert (false);
|
inertia.set(0f, 0f, 0f);
|
}
|
|
|
@Override
|
public void setLocalScaling(Vector3f scaling) {
|
meshInterface.setScaling(scaling);
|
recalcLocalAabb();
|
}
|
|
@Override
|
public Vector3f getLocalScaling(Vector3f out) {
|
return meshInterface.getScaling(out);
|
}
|
|
public StridingMeshInterface getMeshInterface() {
|
return meshInterface;
|
}
|
|
public Vector3f getLocalAabbMin(Vector3f out) {
|
out.set(localAabbMin);
|
return out;
|
}
|
|
public Vector3f getLocalAabbMax(Vector3f out) {
|
out.set(localAabbMax);
|
return out;
|
}
|
|
@Override
|
public String getName() {
|
return "TRIANGLEMESH";
|
}
|
|
////////////////////////////////////////////////////////////////////////////
|
|
private class SupportVertexCallback extends TriangleCallback {
|
private final Vector3f supportVertexLocal = new Vector3f(0f, 0f, 0f);
|
public final Transform worldTrans = new Transform();
|
public float maxDot = -1e30f;
|
public final Vector3f supportVecLocal = new Vector3f();
|
|
public SupportVertexCallback(Vector3f supportVecWorld,Transform trans) {
|
this.worldTrans.set(trans);
|
MatrixUtil.transposeTransform(supportVecLocal, supportVecWorld, worldTrans.basis);
|
}
|
|
public void processTriangle(Vector3f[] triangle, int partId, int triangleIndex) {
|
for (int i = 0; i < 3; i++) {
|
float dot = supportVecLocal.dot(triangle[i]);
|
if (dot > maxDot) {
|
maxDot = dot;
|
supportVertexLocal.set(triangle[i]);
|
}
|
}
|
}
|
|
public Vector3f getSupportVertexWorldSpace(Vector3f out) {
|
out.set(supportVertexLocal);
|
worldTrans.transform(out);
|
return out;
|
}
|
|
public Vector3f getSupportVertexLocal(Vector3f out) {
|
out.set(supportVertexLocal);
|
return out;
|
}
|
}
|
|
private static class FilteredCallback extends InternalTriangleIndexCallback {
|
public TriangleCallback callback;
|
public final Vector3f aabbMin = new Vector3f();
|
public final Vector3f aabbMax = new Vector3f();
|
|
public FilteredCallback(TriangleCallback callback, Vector3f aabbMin, Vector3f aabbMax) {
|
this.callback = callback;
|
this.aabbMin.set(aabbMin);
|
this.aabbMax.set(aabbMax);
|
}
|
|
public void internalProcessTriangleIndex(Vector3f[] triangle, int partId, int triangleIndex) {
|
if (AabbUtil2.testTriangleAgainstAabb2(triangle, aabbMin, aabbMax)) {
|
// check aabb in triangle-space, before doing this
|
callback.processTriangle(triangle, partId, triangleIndex);
|
}
|
}
|
}
|
|
}
|