use of com.jme3.math.Triangle in project jmonkeyengine by jMonkeyEngine.
the class LODGeomap method getGridTrianglesAtPoint.
/**
* Get the two triangles that make up the grid section at the specified point.
*
* For every grid space there are two triangles oriented like this:
* *----*
* |a / |
* | / b|
* *----*
* The corners of the mesh have differently oriented triangles. The two
* corners that we have to special-case are the top left and bottom right
* corners. They are oriented inversely:
* *----*
* | \ b|
* |a \ |
* *----*
*
* @param x local x coordinate
* @param z local z coordinate
* @return
*/
protected Triangle[] getGridTrianglesAtPoint(float x, float z) {
int gridX = (int) x;
int gridY = (int) z;
int index = findClosestHeightIndex(gridX, gridY);
if (index < 0) {
return null;
}
Triangle t = new Triangle(new Vector3f(), new Vector3f(), new Vector3f());
Triangle t2 = new Triangle(new Vector3f(), new Vector3f(), new Vector3f());
// top left
float h1 = hdata[index];
// top right
float h2 = hdata[index + 1];
// bottom left
float h3 = hdata[index + width];
// bottom right
float h4 = hdata[index + width + 1];
if ((gridX == 0 && gridY == 0) || (gridX == width - 2 && gridY == width - 2)) {
// top left or bottom right grid point
t.get(0).x = (gridX);
t.get(0).y = (h1);
t.get(0).z = (gridY);
t.get(1).x = (gridX);
t.get(1).y = (h3);
t.get(1).z = (gridY + 1);
t.get(2).x = (gridX + 1);
t.get(2).y = (h4);
t.get(2).z = (gridY + 1);
t2.get(0).x = (gridX);
t2.get(0).y = (h1);
t2.get(0).z = (gridY);
t2.get(1).x = (gridX + 1);
t2.get(1).y = (h4);
t2.get(1).z = (gridY + 1);
t2.get(2).x = (gridX + 1);
t2.get(2).y = (h2);
t2.get(2).z = (gridY);
} else {
// all other grid points
t.get(0).x = (gridX);
t.get(0).y = (h1);
t.get(0).z = (gridY);
t.get(1).x = (gridX);
t.get(1).y = (h3);
t.get(1).z = (gridY + 1);
t.get(2).x = (gridX + 1);
t.get(2).y = (h2);
t.get(2).z = (gridY);
t2.get(0).x = (gridX + 1);
t2.get(0).y = (h2);
t2.get(0).z = (gridY);
t2.get(1).x = (gridX);
t2.get(1).y = (h3);
t2.get(1).z = (gridY + 1);
t2.get(2).x = (gridX + 1);
t2.get(2).y = (h4);
t2.get(2).z = (gridY + 1);
}
return new Triangle[] { t, t2 };
}
use of com.jme3.math.Triangle in project jmonkeyengine by jMonkeyEngine.
the class LODGeomap method getTriangleAtPoint.
/**
* Get the triangle that the point is on.
*
* @param x coordinate in local space to the geomap
* @param z coordinate in local space to the geomap
* @return triangle in local space to the geomap
*/
protected Triangle getTriangleAtPoint(float x, float z) {
Triangle[] triangles = getGridTrianglesAtPoint(x, z);
if (triangles == null) {
//System.out.println("x,z: " + x + "," + z);
return null;
}
Vector2f point = new Vector2f(x, z);
Vector2f t1 = new Vector2f(triangles[0].get1().x, triangles[0].get1().z);
Vector2f t2 = new Vector2f(triangles[0].get2().x, triangles[0].get2().z);
Vector2f t3 = new Vector2f(triangles[0].get3().x, triangles[0].get3().z);
if (0 != FastMath.pointInsideTriangle(t1, t2, t3, point)) {
return triangles[0];
}
t1.set(triangles[1].get1().x, triangles[1].get1().z);
t1.set(triangles[1].get2().x, triangles[1].get2().z);
t1.set(triangles[1].get3().x, triangles[1].get3().z);
if (0 != FastMath.pointInsideTriangle(t1, t2, t3, point)) {
return triangles[1];
}
return null;
}
use of com.jme3.math.Triangle in project jmonkeyengine by jMonkeyEngine.
the class LODGeomap method getTriangleAtPoint.
/**
* Get a representation of the underlying triangle at the given point,
* translated to world coordinates.
*
* @param x local x coordinate
* @param z local z coordinate
* @return a triangle in world space not local space
*/
protected Triangle getTriangleAtPoint(float x, float z, Vector3f scale, Vector3f translation) {
Triangle tri = getTriangleAtPoint(x, z);
if (tri != null) {
tri.get1().multLocal(scale).addLocal(translation);
tri.get2().multLocal(scale).addLocal(translation);
tri.get3().multLocal(scale).addLocal(translation);
}
return tri;
}
use of com.jme3.math.Triangle in project jmonkeyengine by jMonkeyEngine.
the class Ray method intersects.
/**
* <code>intersects</code> does the actual intersection work.
*
* @param v0
* first point of the triangle.
* @param v1
* second point of the triangle.
* @param v2
* third point of the triangle.
* @param store
* storage vector - if null, no intersection is calc'd
* @param doPlanar
* true if we are calcing planar results.
* @param quad
* @return true if ray intersects triangle
*/
private boolean intersects(Vector3f v0, Vector3f v1, Vector3f v2, Vector3f store, boolean doPlanar, boolean quad) {
TempVars vars = TempVars.get();
Vector3f tempVa = vars.vect1, tempVb = vars.vect2, tempVc = vars.vect3, tempVd = vars.vect4;
Vector3f diff = origin.subtract(v0, tempVa);
Vector3f edge1 = v1.subtract(v0, tempVb);
Vector3f edge2 = v2.subtract(v0, tempVc);
Vector3f norm = edge1.cross(edge2, tempVd);
float dirDotNorm = direction.dot(norm);
float sign;
if (dirDotNorm > FastMath.FLT_EPSILON) {
sign = 1;
} else if (dirDotNorm < -FastMath.FLT_EPSILON) {
sign = -1f;
dirDotNorm = -dirDotNorm;
} else {
// ray and triangle/quad are parallel
vars.release();
return false;
}
float dirDotDiffxEdge2 = sign * direction.dot(diff.cross(edge2, edge2));
if (dirDotDiffxEdge2 >= 0.0f) {
float dirDotEdge1xDiff = sign * direction.dot(edge1.crossLocal(diff));
if (dirDotEdge1xDiff >= 0.0f) {
if (!quad ? dirDotDiffxEdge2 + dirDotEdge1xDiff <= dirDotNorm : dirDotEdge1xDiff <= dirDotNorm) {
float diffDotNorm = -sign * diff.dot(norm);
if (diffDotNorm >= 0.0f) {
// this method always returns
vars.release();
// if storage vector is null, just return true,
if (store == null) {
return true;
}
// else fill in.
float inv = 1f / dirDotNorm;
float t = diffDotNorm * inv;
if (!doPlanar) {
store.set(origin).addLocal(direction.x * t, direction.y * t, direction.z * t);
} else {
// these weights can be used to determine
// interpolated values, such as texture coord.
// eg. texcoord s,t at intersection point:
// s = w0*s0 + w1*s1 + w2*s2;
// t = w0*t0 + w1*t1 + w2*t2;
float w1 = dirDotDiffxEdge2 * inv;
float w2 = dirDotEdge1xDiff * inv;
//float w0 = 1.0f - w1 - w2;
store.set(t, w1, w2);
}
return true;
}
}
}
}
vars.release();
return false;
}
use of com.jme3.math.Triangle in project jmonkeyengine by jMonkeyEngine.
the class FbxMesh method createGeometries.
private List<Geometry> createGeometries() throws IOException {
Mesh mesh = new Mesh();
mesh.setMode(Mode.Triangles);
// Moreover quads should be triangulated (this increases number of vertices)
if (indices != null) {
iCount = indices.length;
srcVertexCount = vertices.length / 3;
// Indices contains negative numbers to define polygon last index
// Check indices strides to be sure we have triangles or quads
vCount = 0;
// Count number of vertices to be produced
int polyVertCount = 0;
for (int i = 0; i < iCount; ++i) {
int index = indices[i];
polyVertCount++;
if (index < 0) {
if (polyVertCount == 3) {
// A triangle
vCount += 3;
} else if (polyVertCount == 4) {
// A quad produce two triangles
vCount += 6;
} else {
throw new AssetLoadException("Unsupported PolygonVertexIndex stride");
}
polyVertCount = 0;
}
}
// Unroll index array into vertex mapping
vertexMap = new ArrayList<>(vCount);
indexMap = new ArrayList<>(vCount);
polyVertCount = 0;
for (int i = 0; i < iCount; ++i) {
int index = indices[i];
polyVertCount++;
if (index < 0) {
int lastIndex = -(index + 1);
if (polyVertCount == 3) {
vertexMap.add(indices[i - 2]);
vertexMap.add(indices[i - 1]);
vertexMap.add(lastIndex);
indexMap.add(i - 2);
indexMap.add(i - 1);
indexMap.add(i - 0);
} else if (polyVertCount == 4) {
vertexMap.add(indices[i - 3]);
vertexMap.add(indices[i - 2]);
vertexMap.add(indices[i - 1]);
vertexMap.add(indices[i - 3]);
vertexMap.add(indices[i - 1]);
vertexMap.add(lastIndex);
indexMap.add(i - 3);
indexMap.add(i - 2);
indexMap.add(i - 1);
indexMap.add(i - 3);
indexMap.add(i - 1);
indexMap.add(i - 0);
}
polyVertCount = 0;
}
}
// Build reverse vertex mapping
reverseVertexMap = new ArrayList<>(srcVertexCount);
for (int i = 0; i < srcVertexCount; ++i) reverseVertexMap.add(new ArrayList<Integer>());
for (int i = 0; i < vCount; ++i) {
int index = vertexMap.get(i);
reverseVertexMap.get(index).add(i);
}
} else {
// Stub for no vertex indexing (direct mapping)
iCount = vCount = srcVertexCount;
vertexMap = new ArrayList<>(vCount);
indexMap = new ArrayList<>(vCount);
reverseVertexMap = new ArrayList<>(vCount);
for (int i = 0; i < vCount; ++i) {
vertexMap.set(i, i);
indexMap.set(i, i);
List<Integer> l = new ArrayList<Integer>(1);
l.add(i);
reverseVertexMap.add(l);
}
}
if (vertices != null) {
// Unroll vertices data array
FloatBuffer posBuf = BufferUtils.createFloatBuffer(vCount * 3);
mesh.setBuffer(VertexBuffer.Type.Position, 3, posBuf);
int srcCount = vertices.length / 3;
for (int i = 0; i < vCount; ++i) {
int index = vertexMap.get(i);
if (index > srcCount)
throw new AssetLoadException("Invalid vertex mapping. Unexpected lookup vertex " + index + " from " + srcCount);
// XXX Why we should scale by unit size?
float x = (float) vertices[3 * index + 0] / scene.unitSize * scene.xAxis;
float y = (float) vertices[3 * index + 1] / scene.unitSize * scene.yAxis;
float z = (float) vertices[3 * index + 2] / scene.unitSize * scene.zAxis;
posBuf.put(x).put(y).put(z);
}
}
if (normals != null) {
// Unroll normals data array
FloatBuffer normBuf = BufferUtils.createFloatBuffer(vCount * 3);
mesh.setBuffer(VertexBuffer.Type.Normal, 3, normBuf);
List<Integer> mapping = null;
if (normalsMapping.equals("ByVertice"))
mapping = vertexMap;
else if (normalsMapping.equals("ByPolygonVertex"))
mapping = indexMap;
else
throw new IOException("Unknown normals mapping type: " + normalsMapping);
int srcCount = normals.length / 3;
for (int i = 0; i < vCount; ++i) {
int index = mapping.get(i);
if (index > srcCount)
throw new AssetLoadException("Invalid normal mapping. Unexpected lookup normal " + index + " from " + srcCount);
float x = (float) normals[3 * index + 0] * scene.xAxis;
float y = (float) normals[3 * index + 1] * scene.yAxis;
float z = (float) normals[3 * index + 2] * scene.zAxis;
normBuf.put(x).put(y).put(z);
}
}
if (tangents != null) {
// Unroll normals data array
FloatBuffer tanBuf = BufferUtils.createFloatBuffer(vCount * 4);
mesh.setBuffer(VertexBuffer.Type.Tangent, 4, tanBuf);
List<Integer> mapping = null;
if (tangentsMapping.equals("ByVertice"))
mapping = vertexMap;
else if (tangentsMapping.equals("ByPolygonVertex"))
mapping = indexMap;
else
throw new IOException("Unknown tangents mapping type: " + tangentsMapping);
int srcCount = tangents.length / 3;
for (int i = 0; i < vCount; ++i) {
int index = mapping.get(i);
if (index > srcCount)
throw new AssetLoadException("Invalid tangent mapping. Unexpected lookup tangent " + index + " from " + srcCount);
float x = (float) tangents[3 * index + 0] * scene.xAxis;
float y = (float) tangents[3 * index + 1] * scene.yAxis;
float z = (float) tangents[3 * index + 2] * scene.zAxis;
tanBuf.put(x).put(y).put(z).put(-1.0f);
}
}
if (binormals != null) {
// Unroll normals data array
FloatBuffer binormBuf = BufferUtils.createFloatBuffer(vCount * 3);
mesh.setBuffer(VertexBuffer.Type.Binormal, 3, binormBuf);
List<Integer> mapping = null;
if (binormalsMapping.equals("ByVertice"))
mapping = vertexMap;
else if (binormalsMapping.equals("ByPolygonVertex"))
mapping = indexMap;
else
throw new IOException("Unknown binormals mapping type: " + binormalsMapping);
int srcCount = binormals.length / 3;
for (int i = 0; i < vCount; ++i) {
int index = mapping.get(i);
if (index > srcCount)
throw new AssetLoadException("Invalid binormal mapping. Unexpected lookup binormal " + index + " from " + srcCount);
float x = (float) binormals[3 * index + 0] * scene.xAxis;
float y = (float) binormals[3 * index + 1] * scene.yAxis;
float z = (float) binormals[3 * index + 2] * scene.zAxis;
binormBuf.put(x).put(y).put(z);
}
}
for (int uvLayer = 0; uvLayer < uvs.size(); ++uvLayer) {
double[] uv = uvs.get(uvLayer);
int[] uvIndex = uvIndexes.size() > uvLayer ? uvIndexes.get(uvLayer) : null;
List<Integer> unIndexMap = vertexMap;
if (uvIndex != null) {
int uvIndexSrcCount = uvIndex.length;
if (uvIndexSrcCount != iCount)
throw new AssetLoadException("Invalid number of texcoord index data " + uvIndexSrcCount + " expected " + iCount);
// Unroll UV index array
unIndexMap = new ArrayList<>(vCount);
int polyVertCount = 0;
for (int i = 0; i < iCount; ++i) {
int index = indices[i];
polyVertCount++;
if (index < 0) {
if (polyVertCount == 3) {
unIndexMap.add(uvIndex[i - 2]);
unIndexMap.add(uvIndex[i - 1]);
unIndexMap.add(uvIndex[i - 0]);
} else if (polyVertCount == 4) {
unIndexMap.add(uvIndex[i - 3]);
unIndexMap.add(uvIndex[i - 2]);
unIndexMap.add(uvIndex[i - 1]);
unIndexMap.add(uvIndex[i - 3]);
unIndexMap.add(uvIndex[i - 1]);
unIndexMap.add(uvIndex[i - 0]);
}
polyVertCount = 0;
}
}
}
// Unroll UV data array
FloatBuffer tcBuf = BufferUtils.createFloatBuffer(vCount * 2);
VertexBuffer.Type type = VertexBuffer.Type.TexCoord;
switch(uvLayer) {
case 1:
type = VertexBuffer.Type.TexCoord2;
break;
case 2:
type = VertexBuffer.Type.TexCoord3;
break;
case 3:
type = VertexBuffer.Type.TexCoord4;
break;
case 4:
type = VertexBuffer.Type.TexCoord5;
break;
case 5:
type = VertexBuffer.Type.TexCoord6;
break;
case 6:
type = VertexBuffer.Type.TexCoord7;
break;
case 7:
type = VertexBuffer.Type.TexCoord8;
break;
}
mesh.setBuffer(type, 2, tcBuf);
int srcCount = uv.length / 2;
for (int i = 0; i < vCount; ++i) {
int index = unIndexMap.get(i);
if (index > srcCount)
throw new AssetLoadException("Invalid texcoord mapping. Unexpected lookup texcoord " + index + " from " + srcCount);
float u = (index >= 0) ? (float) uv[2 * index + 0] : 0;
float v = (index >= 0) ? (float) uv[2 * index + 1] : 0;
tcBuf.put(u).put(v);
}
}
List<Geometry> geometries = new ArrayList<Geometry>();
if (materialsReference.equals("IndexToDirect") && materialsMapping.equals("ByPolygon")) {
IntMap<List<Integer>> indexBuffers = new IntMap<>();
for (int polygon = 0; polygon < materials.length; ++polygon) {
int material = materials[polygon];
List<Integer> list = indexBuffers.get(material);
if (list == null) {
list = new ArrayList<>();
indexBuffers.put(material, list);
}
list.add(polygon * 3 + 0);
list.add(polygon * 3 + 1);
list.add(polygon * 3 + 2);
}
Iterator<Entry<List<Integer>>> iterator = indexBuffers.iterator();
while (iterator.hasNext()) {
Entry<List<Integer>> e = iterator.next();
int materialId = e.getKey();
List<Integer> indexes = e.getValue();
Mesh newMesh = mesh.clone();
newMesh.setBuffer(VertexBuffer.Type.Index, 3, toArray(indexes.toArray(new Integer[indexes.size()])));
newMesh.setStatic();
newMesh.updateBound();
newMesh.updateCounts();
Geometry geom = new Geometry();
geom.setMesh(newMesh);
geometries.add(geom);
geom.setUserData("FBXMaterial", materialId);
}
} else {
mesh.setStatic();
mesh.updateBound();
mesh.updateCounts();
Geometry geom = new Geometry();
geom.setMesh(mesh);
geometries.add(geom);
}
return geometries;
}
Aggregations