use of com.jme3.math.Triangle in project jmonkeyengine by jMonkeyEngine.
the class UVProjectionGenerator method sphereProjection.
/**
* Sphere projection for 2D textures.
*
* @param positions
* points to be projected
* @param bb
* the bounding box for projecting
* @return UV coordinates after the projection
*/
public static float[] sphereProjection(float[] positions, BoundingSphere bs) {
// TODO: rotate it to be vertical
float[] uvCoordinates = new float[positions.length / 3 * 2];
Vector3f v = new Vector3f();
float cx = bs.getCenter().x, cy = bs.getCenter().y, cz = bs.getCenter().z;
Vector3f uBase = new Vector3f(0, -1, 0);
Vector3f vBase = new Vector3f(0, 0, -1);
for (int i = 0, j = 0; i < positions.length; i += 3, j += 2) {
// calculating U
v.set(positions[i] - cx, positions[i + 1] - cy, 0);
v.normalizeLocal();
// result between [0; PI]
float angle = v.angleBetween(uBase);
if (v.x < 0) {
// the angle should be greater than PI, we're on the other part of the image then
angle = FastMath.TWO_PI - angle;
}
uvCoordinates[j] = angle / FastMath.TWO_PI;
// calculating V
v.set(positions[i] - cx, positions[i + 1] - cy, positions[i + 2] - cz);
v.normalizeLocal();
// result between [0; PI]
angle = v.angleBetween(vBase);
uvCoordinates[j + 1] = angle / FastMath.PI;
}
// looking for splitted triangles
Triangle triangle = new Triangle();
for (int i = 0; i < positions.length; i += 9) {
triangle.set(0, positions[i], positions[i + 1], positions[i + 2]);
triangle.set(1, positions[i + 3], positions[i + 4], positions[i + 5]);
triangle.set(2, positions[i + 6], positions[i + 7], positions[i + 8]);
float sgn1 = Math.signum(triangle.get1().x - cx);
float sgn2 = Math.signum(triangle.get2().x - cx);
float sgn3 = Math.signum(triangle.get3().x - cx);
float xSideFactor = sgn1 + sgn2 + sgn3;
float ySideFactor = Math.signum(triangle.get1().y - cy) + Math.signum(triangle.get2().y - cy) + Math.signum(triangle.get3().y - cy);
if ((xSideFactor > -3 || xSideFactor < 3) && ySideFactor < 0) {
// the triangle is on the splitting plane
if (sgn1 == 1.0f) {
uvCoordinates[i / 3 * 2] += 1.0f;
}
if (sgn2 == 1.0f) {
uvCoordinates[(i / 3 + 1) * 2] += 1.0f;
}
if (sgn3 == 1.0f) {
uvCoordinates[(i / 3 + 2) * 2] += 1.0f;
}
}
}
return uvCoordinates;
}
use of com.jme3.math.Triangle in project jmonkeyengine by jMonkeyEngine.
the class BIHTree method createNode.
// private BIHNode createNode2(int l, int r, BoundingBox nodeBbox, int depth){
// if ((r - l) < maxTrisPerNode || depth > 100)
// return createLeaf(l, r);
//
// BoundingBox currentBox = createBox(l, r);
// int axis = depth % 3;
// float split = currentBox.getCenter().get(axis);
//
// TriangleAxisComparator comparator = comparators[axis];
// Arrays.sort(tris, l, r, comparator);
// int splitIndex = -1;
//
// float leftPlane, rightPlane = Float.POSITIVE_INFINITY;
// leftPlane = tris[l].getExtreme(axis, false);
// for (int i = l; i <= r; i++){
// BIHTriangle tri = tris[i];
// if (splitIndex == -1){
// float v = tri.getCenter().get(axis);
// if (v > split){
// if (i == 0){
// // no left plane
// splitIndex = -2;
// }else{
// splitIndex = i;
// // first triangle assigned to right
// rightPlane = tri.getExtreme(axis, true);
// }
// }else{
// // triangle assigned to left
// float ex = tri.getExtreme(axis, false);
// if (ex > leftPlane)
// leftPlane = ex;
// }
// }else{
// float ex = tri.getExtreme(axis, true);
// if (ex < rightPlane)
// rightPlane = ex;
// }
// }
//
// if (splitIndex < 0){
// splitIndex = (r - l) / 2;
//
// leftPlane = Float.NEGATIVE_INFINITY;
// rightPlane = Float.POSITIVE_INFINITY;
//
// for (int i = l; i < splitIndex; i++){
// float ex = tris[i].getExtreme(axis, false);
// if (ex > leftPlane){
// leftPlane = ex;
// }
// }
// for (int i = splitIndex; i <= r; i++){
// float ex = tris[i].getExtreme(axis, true);
// if (ex < rightPlane){
// rightPlane = ex;
// }
// }
// }
//
// BIHNode node = new BIHNode(axis);
// node.leftPlane = leftPlane;
// node.rightPlane = rightPlane;
//
// node.leftIndex = l;
// node.rightIndex = r;
//
// BoundingBox leftBbox = new BoundingBox(currentBox);
// setMinMax(leftBbox, false, axis, split);
// node.left = createNode2(l, splitIndex-1, leftBbox, depth+1);
//
// BoundingBox rightBbox = new BoundingBox(currentBox);
// setMinMax(rightBbox, true, axis, split);
// node.right = createNode2(splitIndex, r, rightBbox, depth+1);
//
// return node;
// }
private BIHNode createNode(int l, int r, BoundingBox nodeBbox, int depth) {
if ((r - l) < maxTrisPerNode || depth > MAX_TREE_DEPTH) {
return new BIHNode(l, r);
}
BoundingBox currentBox = createBox(l, r);
Vector3f exteriorExt = nodeBbox.getExtent(null);
Vector3f interiorExt = currentBox.getExtent(null);
exteriorExt.subtractLocal(interiorExt);
int axis = 0;
if (exteriorExt.x > exteriorExt.y) {
if (exteriorExt.x > exteriorExt.z) {
axis = 0;
} else {
axis = 2;
}
} else {
if (exteriorExt.y > exteriorExt.z) {
axis = 1;
} else {
axis = 2;
}
}
if (exteriorExt.equals(Vector3f.ZERO)) {
axis = 0;
}
// Arrays.sort(tris, l, r, comparators[axis]);
float split = currentBox.getCenter().get(axis);
int pivot = sortTriangles(l, r, split, axis);
if (pivot == l || pivot == r) {
pivot = (r + l) / 2;
}
//If one of the partitions is empty, continue with recursion: same level but different bbox
if (pivot < l) {
//Only right
BoundingBox rbbox = new BoundingBox(currentBox);
setMinMax(rbbox, true, axis, split);
return createNode(l, r, rbbox, depth + 1);
} else if (pivot > r) {
//Only left
BoundingBox lbbox = new BoundingBox(currentBox);
setMinMax(lbbox, false, axis, split);
return createNode(l, r, lbbox, depth + 1);
} else {
//Build the node
BIHNode node = new BIHNode(axis);
//Left child
BoundingBox lbbox = new BoundingBox(currentBox);
setMinMax(lbbox, false, axis, split);
//The left node right border is the plane most right
node.setLeftPlane(getMinMax(createBox(l, max(l, pivot - 1)), false, axis));
//Recursive call
node.setLeftChild(createNode(l, max(l, pivot - 1), lbbox, depth + 1));
//Right Child
BoundingBox rbbox = new BoundingBox(currentBox);
setMinMax(rbbox, true, axis, split);
//The right node left border is the plane most left
node.setRightPlane(getMinMax(createBox(pivot, r), true, axis));
//Recursive call
node.setRightChild(createNode(pivot, r, rbbox, depth + 1));
return node;
}
}
use of com.jme3.math.Triangle in project jmonkeyengine by jMonkeyEngine.
the class BIHNode method intersectWhere.
public final int intersectWhere(Collidable col, BoundingBox box, Matrix4f worldMatrix, BIHTree tree, CollisionResults results) {
TempVars vars = TempVars.get();
ArrayList<BIHStackData> stack = vars.bihStack;
stack.clear();
float[] minExts = { box.getCenter().x - box.getXExtent(), box.getCenter().y - box.getYExtent(), box.getCenter().z - box.getZExtent() };
float[] maxExts = { box.getCenter().x + box.getXExtent(), box.getCenter().y + box.getYExtent(), box.getCenter().z + box.getZExtent() };
stack.add(new BIHStackData(this, 0, 0));
Triangle t = new Triangle();
int cols = 0;
stackloop: while (stack.size() > 0) {
BIHNode node = stack.remove(stack.size() - 1).node;
while (node.axis != 3) {
int a = node.axis;
float maxExt = maxExts[a];
float minExt = minExts[a];
if (node.leftPlane < node.rightPlane) {
// if the box is in that gap, we stop there
if (minExt > node.leftPlane && maxExt < node.rightPlane) {
continue stackloop;
}
}
if (maxExt < node.rightPlane) {
node = node.left;
} else if (minExt > node.leftPlane) {
node = node.right;
} else {
stack.add(new BIHStackData(node.right, 0, 0));
node = node.left;
}
// if (maxExt < node.leftPlane
// && maxExt < node.rightPlane){
// node = node.left;
// }else if (minExt > node.leftPlane
// && minExt > node.rightPlane){
// node = node.right;
// }else{
// }
}
for (int i = node.leftIndex; i <= node.rightIndex; i++) {
tree.getTriangle(i, t.get1(), t.get2(), t.get3());
if (worldMatrix != null) {
worldMatrix.mult(t.get1(), t.get1());
worldMatrix.mult(t.get2(), t.get2());
worldMatrix.mult(t.get3(), t.get3());
}
int added = col.collideWith(t, results);
if (added > 0) {
int index = tree.getTriangleIndex(i);
int start = results.size() - added;
for (int j = start; j < results.size(); j++) {
CollisionResult cr = results.getCollisionDirect(j);
cr.setTriangleIndex(index);
}
cols += added;
}
}
}
vars.release();
return cols;
}
use of com.jme3.math.Triangle in project jmonkeyengine by jMonkeyEngine.
the class LodGenerator method computeEdgeCollapseCost.
float computeEdgeCollapseCost(Vertex src, Edge dstEdge) {
// This is based on Ogre's collapse cost calculation algorithm.
Vertex dest = dstEdge.destination;
// then this would destroy the shape, so don't do this
if (src.triangles.size() == 1 && dest.triangles.size() == 1) {
return NEVER_COLLAPSE_COST;
}
// Look for a face normal changing by > 90 degrees
for (Triangle triangle : src.triangles) {
// Ignore the deleted faces (those including src & dest)
if (!triangle.hasVertex(dest)) {
// Test the new face normal
Vertex pv0, pv1, pv2;
// Replace src with dest wherever it is
pv0 = (triangle.vertex[0] == src) ? dest : triangle.vertex[0];
pv1 = (triangle.vertex[1] == src) ? dest : triangle.vertex[1];
pv2 = (triangle.vertex[2] == src) ? dest : triangle.vertex[2];
// Cross-product 2 edges
tmpV1.set(pv1.position).subtractLocal(pv0.position);
tmpV2.set(pv2.position).subtractLocal(pv1.position);
//computing the normal
Vector3f newNormal = tmpV1.crossLocal(tmpV2);
newNormal.normalizeLocal();
// If < 0 then more than 90 degree difference
if (newNormal.dot(triangle.normal) < 0.0f) {
// Don't do it!
return NEVER_COLLAPSE_COST;
}
}
}
float cost;
// If we're looking at a border vertex
if (isBorderVertex(src)) {
if (dstEdge.refCount > 1) {
// src is on a border, but the src-dest edge has more than one tri on it
// So it must be collapsing inwards
// Mark as very high-value cost
// curvature = 1.0f;
cost = 1.0f;
} else {
// Collapsing ALONG a border
// We can't use curvature to measure the effect on the model
// Instead, see what effect it has on 'pulling' the other border edges
// The more colinear, the less effect it will have
// So measure the 'kinkiness' (for want of a better term)
// Find the only triangle using this edge.
// PMTriangle* triangle = findSideTriangle(src, dst);
cost = 0.0f;
Vector3f collapseEdge = tmpV1.set(src.position).subtractLocal(dest.position);
collapseEdge.normalizeLocal();
for (Edge edge : src.edges) {
Vertex neighbor = edge.destination;
//reference check intended
if (neighbor != dest && edge.refCount == 1) {
Vector3f otherBorderEdge = tmpV2.set(src.position).subtractLocal(neighbor.position);
otherBorderEdge.normalizeLocal();
// This time, the nearer the dot is to -1, the better, because that means
// the edges are opposite each other, therefore less kinkiness
// Scale into [0..1]
float kinkiness = (otherBorderEdge.dot(collapseEdge) + 1.002f) * 0.5f;
cost = Math.max(cost, kinkiness);
}
}
}
} else {
// not a border
// Standard inner vertex
// Calculate curvature
// use the triangle facing most away from the sides
// to determine our curvature term
// Iterate over src's faces again
cost = 0.001f;
for (Triangle triangle : src.triangles) {
// curve for face i and closer side to it
float mincurv = 1.0f;
for (Triangle triangle2 : src.triangles) {
if (triangle2.hasVertex(dest)) {
// Dot product of face normal gives a good delta angle
float dotprod = triangle.normal.dot(triangle2.normal);
// NB we do (1-..) to invert curvature where 1 is high curvature [0..1]
// Whilst dot product is high when angle difference is low
mincurv = Math.min(mincurv, (1.002f - dotprod) * 0.5f);
}
}
cost = Math.max(cost, mincurv);
}
}
// check for texture seam ripping
if (src.isSeam) {
if (!dest.isSeam) {
cost += meshBoundingSphereRadius;
} else {
cost += meshBoundingSphereRadius * 0.5;
}
}
return cost * src.position.distanceSquared(dest.position);
}
use of com.jme3.math.Triangle in project jmonkeyengine by jMonkeyEngine.
the class LodGenerator method gatherIndexData.
private void gatherIndexData(Mesh mesh, List<Vertex> vertexLookup) {
VertexBuffer indexBuffer = mesh.getBuffer(VertexBuffer.Type.Index);
indexCount = indexBuffer.getNumElements() * 3;
Buffer b = indexBuffer.getDataReadOnly();
b.rewind();
while (b.remaining() != 0) {
Triangle tri = new Triangle();
tri.isRemoved = false;
triangleList.add(tri);
for (int i = 0; i < 3; i++) {
if (b instanceof IntBuffer) {
tri.vertexId[i] = ((IntBuffer) b).get();
} else {
//bit shift to avoid negative values due to conversion form short to int.
//we need an unsigned int here.
tri.vertexId[i] = ((ShortBuffer) b).get() & 0xffff;
}
// assert (tri.vertexId[i] < vertexLookup.size());
tri.vertex[i] = vertexLookup.get(tri.vertexId[i]);
//debug only;
tri.vertex[i].index = tri.vertexId[i];
}
if (tri.isMalformed()) {
if (!tri.isRemoved) {
logger.log(Level.FINE, "malformed triangle found with ID:{0}\n{1} It will be excluded from Lod level calculations.", new Object[] { triangleList.indexOf(tri), tri.toString() });
tri.isRemoved = true;
indexCount -= 3;
}
} else {
tri.computeNormal();
addTriangleToEdges(tri);
}
}
b.rewind();
}
Aggregations