use of com.jme3.math.Plane in project jmonkeyengine by jMonkeyEngine.
the class TestMipMapGen method simpleInitApp.
@Override
public void simpleInitApp() {
BitmapText txt = guiFont.createLabel("Left: HW Mips");
txt.setLocalTranslation(0, settings.getHeight() - txt.getLineHeight() * 4, 0);
guiNode.attachChild(txt);
txt = guiFont.createLabel("Right: AWT Mips");
txt.setLocalTranslation(0, settings.getHeight() - txt.getLineHeight() * 3, 0);
guiNode.attachChild(txt);
// create a simple plane/quad
Quad quadMesh = new Quad(1, 1);
quadMesh.updateGeometry(1, 1, false);
quadMesh.updateBound();
Geometry quad1 = new Geometry("Textured Quad", quadMesh);
Geometry quad2 = new Geometry("Textured Quad 2", quadMesh);
Texture tex = assetManager.loadTexture("Interface/Logo/Monkey.png");
tex.setMinFilter(Texture.MinFilter.Trilinear);
Texture texCustomMip = tex.clone();
Image imageCustomMip = texCustomMip.getImage().clone();
MipMapGenerator.generateMipMaps(imageCustomMip);
texCustomMip.setImage(imageCustomMip);
Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat1.setTexture("ColorMap", tex);
Material mat2 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat2.setTexture("ColorMap", texCustomMip);
quad1.setMaterial(mat1);
// quad1.setLocalTranslation(1, 0, 0);
quad2.setMaterial(mat2);
quad2.setLocalTranslation(1, 0, 0);
rootNode.attachChild(quad1);
rootNode.attachChild(quad2);
}
use of com.jme3.math.Plane in project jmonkeyengine by jMonkeyEngine.
the class LightFilterTest method testSpotFiltering.
@Test
public void testSpotFiltering() {
SpotLight sl = new SpotLight(Vector3f.ZERO, Vector3f.UNIT_Z);
sl.setSpotRange(0);
geom.addLight(sl);
// Infinite spot lights are only filtered
checkFilteredLights(1);
// if the geometry is outside the infinite cone.
TempVars vars = TempVars.get();
try {
// The spot is not touching the near plane of the camera yet,
// should still be culled.
sl.setSpotRange(1f - FastMath.ZERO_TOLERANCE);
assert !sl.intersectsFrustum(cam, vars);
// should be culled from the geometry's PoV
checkFilteredLights(0);
// Now it touches the near plane.
sl.setSpotRange(1f);
// still culled from the geometry's PoV
checkFilteredLights(0);
assert sl.intersectsFrustum(cam, vars);
} finally {
vars.release();
}
// make it barely reach the geometry
sl.setSpotRange(9f);
checkFilteredLights(0);
// make it reach the geometry (touching its bound)
sl.setSpotRange(9f + FastMath.ZERO_TOLERANCE);
checkFilteredLights(1);
// rotate the cone a bit so it no longer faces the geom
sl.setDirection(new Vector3f(0.316f, 0, 0.948f).normalizeLocal());
checkFilteredLights(0);
// extent the range much farther
sl.setSpotRange(20);
checkFilteredLights(0);
// Create box of size X=10 (double the extent)
// now, the spot will touch the box.
geom.setMesh(new Box(5, 1, 1));
checkFilteredLights(1);
// ==================================
// Tests for bounding sphere, with a radius of 1f (in the box geom)
sl.setPosition(Vector3f.ZERO);
sl.setDirection(Vector3f.UNIT_Z);
geom.setLocalTranslation(Vector3f.ZERO);
geom.setModelBound(new BoundingSphere(1f, Vector3f.ZERO));
// Infinit spot lights are only filtered
// if the geometry is outside the infinite cone.
sl.setSpotRange(0);
checkFilteredLights(1);
//the geommetry is outside the infinit cone (cone direction going away from the geom)
sl.setPosition(Vector3f.UNIT_Z.mult(1 + FastMath.ZERO_TOLERANCE));
checkFilteredLights(0);
//place the spote ligth in the corner of the box geom, (in order to test bounding sphere)
sl.setDirection(new Vector3f(1, 1, 0).normalizeLocal());
geom.setLocalTranslation(0, 0, 10);
sl.setPosition(sl.getDirection().mult(-2f).add(geom.getLocalTranslation()));
// make it barely reach the sphere, incorect with a box
sl.setSpotRange(1f - FastMath.ZERO_TOLERANCE);
checkFilteredLights(0);
// make it reach the sphere
sl.setSpotRange(1f + FastMath.ZERO_TOLERANCE);
checkFilteredLights(1);
// extent the range
sl.setPosition(Vector3f.ZERO);
sl.setDirection(Vector3f.UNIT_Z);
sl.setSpotRange(20);
checkFilteredLights(1);
// rotate the cone a bit so it no longer faces the geom
sl.setDirection(new Vector3f(0, 0.3f, 0.7f).normalizeLocal());
checkFilteredLights(0);
// Create sphere of size X=10 (double the radius)
// now, the spot will touch the sphere.
geom.setModelBound(new BoundingSphere(5f, Vector3f.ZERO));
checkFilteredLights(1);
}
use of com.jme3.math.Plane in project jmonkeyengine by jMonkeyEngine.
the class MirrorModifier method apply.
@Override
public void apply(Node node, BlenderContext blenderContext) {
if (invalid) {
LOGGER.log(Level.WARNING, "Mirror modifier is invalid! Cannot be applied to: {0}", node.getName());
} else {
TemporalMesh temporalMesh = this.getTemporalMesh(node);
if (temporalMesh != null) {
LOGGER.log(Level.FINE, "Applying mirror modifier to: {0}", temporalMesh);
Vector3f mirrorPlaneCenter = new Vector3f();
if (pMirrorObject.isNotNull()) {
Structure objectStructure;
try {
objectStructure = pMirrorObject.fetchData().get(0);
ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
Node object = (Node) objectHelper.toObject(objectStructure, blenderContext);
if (object != null) {
// compute the mirror object coordinates in node's local space
mirrorPlaneCenter = this.getWorldMatrix(node).invertLocal().mult(object.getWorldTranslation());
}
} catch (BlenderFileException e) {
LOGGER.log(Level.SEVERE, "Cannot load mirror''s reference object. Cause: {0}", e.getLocalizedMessage());
LOGGER.log(Level.SEVERE, "Mirror modifier will not be applied to node named: {0}", node.getName());
return;
}
}
LOGGER.finest("Allocating temporal variables.");
float d;
Vector3f mirrorPlaneNormal = new Vector3f();
Vector3f shiftVector = new Vector3f();
LOGGER.fine("Mirroring mesh.");
for (int mirrorIndex = 0; mirrorIndex < 3; ++mirrorIndex) {
if (isMirrored[mirrorIndex]) {
boolean mirrorAtPoint0 = mirrorPlaneCenter.get(mirrorIndex) == 0;
if (!mirrorAtPoint0) {
// compute mirror's plane normal vector in node's space
mirrorPlaneNormal.set(0, 0, 0).set(mirrorIndex, Math.signum(mirrorPlaneCenter.get(mirrorIndex)));
}
TemporalMesh mirror = temporalMesh.clone();
for (int i = 0; i < mirror.getVertexCount(); ++i) {
Vector3f vertex = mirror.getVertices().get(i);
Vector3f normal = mirror.getNormals().get(i);
if (mirrorAtPoint0) {
d = Math.abs(vertex.get(mirrorIndex));
shiftVector.set(0, 0, 0).set(mirrorIndex, -vertex.get(mirrorIndex));
} else {
d = this.computeDistanceFromPlane(vertex, mirrorPlaneCenter, mirrorPlaneNormal);
mirrorPlaneNormal.mult(d, shiftVector);
}
if (merge && d <= tolerance) {
vertex.addLocal(shiftVector);
normal.set(mirrorIndex, 0);
temporalMesh.getVertices().get(i).addLocal(shiftVector);
temporalMesh.getNormals().get(i).set(mirrorIndex, 0);
} else {
vertex.addLocal(shiftVector.multLocal(2));
normal.set(mirrorIndex, -normal.get(mirrorIndex));
}
}
// flipping the indexes
for (Face face : mirror.getFaces()) {
face.flipIndexes();
}
for (Edge edge : mirror.getEdges()) {
edge.flipIndexes();
}
Collections.reverse(mirror.getPoints());
if (mirrorU || mirrorV) {
for (Face face : mirror.getFaces()) {
face.flipUV(mirrorU, mirrorV);
}
}
temporalMesh.append(mirror);
}
}
} else {
LOGGER.log(Level.WARNING, "Cannot find temporal mesh for node: {0}. The modifier will NOT be applied!", node);
}
}
}
use of com.jme3.math.Plane in project jmonkeyengine by jMonkeyEngine.
the class BoundingSphere method collideWithTri.
private int collideWithTri(Triangle tri, CollisionResults results) {
TempVars tvars = TempVars.get();
try {
// Much of this is based on adaptation from this algorithm:
// http://realtimecollisiondetection.net/blog/?p=103
// ...mostly the stuff about eliminating sqrts wherever
// possible.
// Math is done in center-relative space.
Vector3f a = tri.get1().subtract(center, tvars.vect1);
Vector3f b = tri.get2().subtract(center, tvars.vect2);
Vector3f c = tri.get3().subtract(center, tvars.vect3);
Vector3f ab = b.subtract(a, tvars.vect4);
Vector3f ac = c.subtract(a, tvars.vect5);
// Check the plane... if it doesn't intersect the plane
// then it doesn't intersect the triangle.
Vector3f n = ab.cross(ac, tvars.vect6);
float d = a.dot(n);
float e = n.dot(n);
if (d * d > radius * radius * e) {
// Can't possibly intersect
return 0;
}
// We intersect the verts, or the edges, or the face...
// First check against the face since it's the most
// specific.
// Calculate the barycentric coordinates of the
// sphere center
Vector3f v0 = ac;
Vector3f v1 = ab;
// a was P relative, so p.subtract(a) is just -a
// instead of wasting a vector we'll just negate the
// dot products below... it's all v2 is used for.
Vector3f v2 = a;
float dot00 = v0.dot(v0);
float dot01 = v0.dot(v1);
float dot02 = -v0.dot(v2);
float dot11 = v1.dot(v1);
float dot12 = -v1.dot(v2);
float invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
float u = (dot11 * dot02 - dot01 * dot12) * invDenom;
float v = (dot00 * dot12 - dot01 * dot02) * invDenom;
if (u >= 0 && v >= 0 && (u + v) <= 1) {
// We intersect... and we even know where
Vector3f part1 = ac;
Vector3f part2 = ab;
Vector3f p = center.add(a.add(part1.mult(u)).addLocal(part2.mult(v)));
CollisionResult r = new CollisionResult();
Vector3f normal = n.normalize();
// a is center relative, so -a points to center
float dist = -normal.dot(a);
dist = dist - radius;
r.setDistance(dist);
r.setContactNormal(normal);
r.setContactPoint(p);
results.addCollision(r);
return 1;
}
// Check the edges looking for the nearest point
// that is also less than the radius. We don't care
// about points that are farther away than that.
Vector3f nearestPt = null;
float nearestDist = radius * radius;
Vector3f base;
Vector3f edge;
float t;
// Edge AB
base = a;
edge = ab;
t = -edge.dot(base) / edge.dot(edge);
if (t >= 0 && t <= 1) {
Vector3f Q = base.add(edge.mult(t, tvars.vect7), tvars.vect8);
// distance squared to origin
float distSq = Q.dot(Q);
if (distSq < nearestDist) {
nearestPt = Q;
nearestDist = distSq;
}
}
// Edge AC
base = a;
edge = ac;
t = -edge.dot(base) / edge.dot(edge);
if (t >= 0 && t <= 1) {
Vector3f Q = base.add(edge.mult(t, tvars.vect7), tvars.vect9);
// distance squared to origin
float distSq = Q.dot(Q);
if (distSq < nearestDist) {
nearestPt = Q;
nearestDist = distSq;
}
}
// Edge BC
base = b;
Vector3f bc = c.subtract(b);
edge = bc;
t = -edge.dot(base) / edge.dot(edge);
if (t >= 0 && t <= 1) {
Vector3f Q = base.add(edge.mult(t, tvars.vect7), tvars.vect10);
// distance squared to origin
float distSq = Q.dot(Q);
if (distSq < nearestDist) {
nearestPt = Q;
nearestDist = distSq;
}
}
// done.
if (nearestPt != null) {
// We have a hit
float dist = FastMath.sqrt(nearestDist);
Vector3f cn = nearestPt.divide(-dist);
CollisionResult r = new CollisionResult();
r.setDistance(dist - radius);
r.setContactNormal(cn);
r.setContactPoint(nearestPt.add(center));
results.addCollision(r);
return 1;
}
// Finally check each of the triangle corners
// Vert A
base = a;
// distance squared to origin
t = base.dot(base);
if (t < nearestDist) {
nearestDist = t;
nearestPt = base;
}
// Vert B
base = b;
// distance squared to origin
t = base.dot(base);
if (t < nearestDist) {
nearestDist = t;
nearestPt = base;
}
// Vert C
base = c;
// distance squared to origin
t = base.dot(base);
if (t < nearestDist) {
nearestDist = t;
nearestPt = base;
}
if (nearestPt != null) {
// We have a hit
float dist = FastMath.sqrt(nearestDist);
Vector3f cn = nearestPt.divide(-dist);
CollisionResult r = new CollisionResult();
r.setDistance(dist - radius);
r.setContactNormal(cn);
r.setContactPoint(nearestPt.add(center));
results.addCollision(r);
return 1;
}
// Nothing hit... oh, well
return 0;
} finally {
tvars.release();
}
}
use of com.jme3.math.Plane in project jmonkeyengine by jMonkeyEngine.
the class Intersection method intersect.
// private boolean axisTest(float a, float b, float fa, float fb, Vector3f v0, Vector3f v1, )
// private boolean axisTestX01(float a, float b, float fa, float fb,
// Vector3f center, Vector3f ext,
// Vector3f v1, Vector3f v2, Vector3f v3){
// float p0 = a * v0.y - b * v0.z;
// float p2 = a * v2.y - b * v2.z;
// if(p0 < p2){
// min = p0;
// max = p2;
// } else {
// min = p2;
// max = p0;
// }
// float rad = fa * boxhalfsize.y + fb * boxhalfsize.z;
// if(min > rad || max < -rad)
// return false;
// }
public static boolean intersect(BoundingBox bbox, Vector3f v1, Vector3f v2, Vector3f v3) {
// use separating axis theorem to test overlap between triangle and box
// need to test for overlap in these directions:
// 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle
// we do not even need to test these)
// 2) normal of the triangle
// 3) crossproduct(edge from tri, {x,y,z}-directin)
// this gives 3x3=9 more tests
TempVars vars = TempVars.get();
Vector3f tmp0 = vars.vect1, tmp1 = vars.vect2, tmp2 = vars.vect3;
Vector3f e0 = vars.vect4, e1 = vars.vect5, e2 = vars.vect6;
Vector3f center = bbox.getCenter();
Vector3f extent = bbox.getExtent(null);
// float min,max,p0,p1,p2,rad,fex,fey,fez;
// float normal[3]
// This is the fastest branch on Sun
// move everything so that the boxcenter is in (0,0,0)
v1.subtract(center, tmp0);
v2.subtract(center, tmp1);
v3.subtract(center, tmp2);
// compute triangle edges
// tri edge 0
tmp1.subtract(tmp0, e0);
// tri edge 1
tmp2.subtract(tmp1, e1);
// tri edge 2
tmp0.subtract(tmp2, e2);
// Bullet 3:
// test the 9 tests first (this was faster)
float min, max;
float p0, p1, p2, rad;
float fex = FastMath.abs(e0.x);
float fey = FastMath.abs(e0.y);
float fez = FastMath.abs(e0.z);
//AXISTEST_X01(e0[Z], e0[Y], fez, fey);
p0 = e0.z * tmp0.y - e0.y * tmp0.z;
p2 = e0.z * tmp2.y - e0.y * tmp2.z;
min = min(p0, p2);
max = max(p0, p2);
rad = fez * extent.y + fey * extent.z;
if (min > rad || max < -rad) {
vars.release();
return false;
}
// AXISTEST_Y02(e0[Z], e0[X], fez, fex);
p0 = -e0.z * tmp0.x + e0.x * tmp0.z;
p2 = -e0.z * tmp2.x + e0.x * tmp2.z;
min = min(p0, p2);
max = max(p0, p2);
rad = fez * extent.x + fex * extent.z;
if (min > rad || max < -rad) {
vars.release();
return false;
}
// AXISTEST_Z12(e0[Y], e0[X], fey, fex);
p1 = e0.y * tmp1.x - e0.x * tmp1.y;
p2 = e0.y * tmp2.x - e0.x * tmp2.y;
min = min(p1, p2);
max = max(p1, p2);
rad = fey * extent.x + fex * extent.y;
if (min > rad || max < -rad) {
vars.release();
return false;
}
fex = FastMath.abs(e1.x);
fey = FastMath.abs(e1.y);
fez = FastMath.abs(e1.z);
// AXISTEST_X01(e1[Z], e1[Y], fez, fey);
p0 = e1.z * tmp0.y - e1.y * tmp0.z;
p2 = e1.z * tmp2.y - e1.y * tmp2.z;
min = min(p0, p2);
max = max(p0, p2);
rad = fez * extent.y + fey * extent.z;
if (min > rad || max < -rad) {
vars.release();
return false;
}
// AXISTEST_Y02(e1[Z], e1[X], fez, fex);
p0 = -e1.z * tmp0.x + e1.x * tmp0.z;
p2 = -e1.z * tmp2.x + e1.x * tmp2.z;
min = min(p0, p2);
max = max(p0, p2);
rad = fez * extent.x + fex * extent.z;
if (min > rad || max < -rad) {
vars.release();
return false;
}
// AXISTEST_Z0(e1[Y], e1[X], fey, fex);
p0 = e1.y * tmp0.x - e1.x * tmp0.y;
p1 = e1.y * tmp1.x - e1.x * tmp1.y;
min = min(p0, p1);
max = max(p0, p1);
rad = fey * extent.x + fex * extent.y;
if (min > rad || max < -rad) {
vars.release();
return false;
}
//
fex = FastMath.abs(e2.x);
fey = FastMath.abs(e2.y);
fez = FastMath.abs(e2.z);
// AXISTEST_X2(e2[Z], e2[Y], fez, fey);
p0 = e2.z * tmp0.y - e2.y * tmp0.z;
p1 = e2.z * tmp1.y - e2.y * tmp1.z;
min = min(p0, p1);
max = max(p0, p1);
rad = fez * extent.y + fey * extent.z;
if (min > rad || max < -rad) {
vars.release();
return false;
}
// AXISTEST_Y1(e2[Z], e2[X], fez, fex);
p0 = -e2.z * tmp0.x + e2.x * tmp0.z;
p1 = -e2.z * tmp1.x + e2.x * tmp1.z;
min = min(p0, p1);
max = max(p0, p1);
rad = fez * extent.x + fex * extent.y;
if (min > rad || max < -rad) {
vars.release();
return false;
}
// AXISTEST_Z12(e2[Y], e2[X], fey, fex);
p1 = e2.y * tmp1.x - e2.x * tmp1.y;
p2 = e2.y * tmp2.x - e2.x * tmp2.y;
min = min(p1, p2);
max = max(p1, p2);
rad = fey * extent.x + fex * extent.y;
if (min > rad || max < -rad) {
vars.release();
return false;
}
// Bullet 1:
// first test overlap in the {x,y,z}-directions
// find min, max of the triangle each direction, and test for overlap in
// that direction -- this is equivalent to testing a minimal AABB around
// the triangle against the AABB
Vector3f minMax = vars.vect7;
// test in X-direction
findMinMax(tmp0.x, tmp1.x, tmp2.x, minMax);
if (minMax.x > extent.x || minMax.y < -extent.x) {
vars.release();
return false;
}
// test in Y-direction
findMinMax(tmp0.y, tmp1.y, tmp2.y, minMax);
if (minMax.x > extent.y || minMax.y < -extent.y) {
vars.release();
return false;
}
// test in Z-direction
findMinMax(tmp0.z, tmp1.z, tmp2.z, minMax);
if (minMax.x > extent.z || minMax.y < -extent.z) {
vars.release();
return false;
}
// // Bullet 2:
// // test if the box intersects the plane of the triangle
// // compute plane equation of triangle: normal * x + d = 0
// Vector3f normal = new Vector3f();
// e0.cross(e1, normal);
Plane p = vars.plane;
p.setPlanePoints(v1, v2, v3);
if (bbox.whichSide(p) == Plane.Side.Negative) {
vars.release();
return false;
}
//
// if(!planeBoxOverlap(normal,v0,boxhalfsize)) return false;
vars.release();
return true;
/* box and triangle overlaps */
}
Aggregations