use of javafx.scene.transform.Affine in project FXyzLib by Birdasaur.
the class FrustumMesh method createFrustum.
private TriangleMesh createFrustum(float majorRadius, float minorRadius, float height, int level) {
TriangleMesh m0 = null;
if (level > 0) {
m0 = createFrustum(majorRadius, minorRadius, height, level - 1);
}
if (level == 0) {
a = new Affine();
int div = DEFAULT_DIVISIONS > 3 ? DEFAULT_DIVISIONS : 3;
if (getSectionType() != TriangleMeshHelper.SectionType.CIRCLE) {
div = getSectionType().getSides() * ((int) (div / getSectionType().getSides()) + 1);
}
if (getAxisOrigin() != null && getAxisEnd() != null) {
Point3D dir = getAxisEnd().substract(getAxisOrigin()).crossProduct(new Point3D(0, -1, 0));
double angle = Math.acos(getAxisEnd().substract(getAxisOrigin()).normalize().dotProduct(new Point3D(0, -1, 0)));
a = a.createConcatenation(new Translate(getAxisOrigin().x, getAxisOrigin().y - height / 2d, getAxisOrigin().z)).createConcatenation(new Rotate(-Math.toDegrees(angle), 0d, height / 2d, 0d, new javafx.geometry.Point3D(dir.x, -dir.y, dir.z)));
}
int nPoints = 2 * div + 2;
float rBase = majorRadius;
float rTop = minorRadius;
float h = height;
final float[] baseVertices = new float[nPoints * 3];
// base at y=h/2
for (int i = 0; i < div; i++) {
double ang = i * 2d * Math.PI / div;
double pol = polygonalSection(ang);
Point3D ta = transform(rBase * pol * Math.cos(ang), h / 2, rBase * pol * Math.sin(ang));
baseVertices[3 * i] = ta.x;
baseVertices[3 * i + 1] = ta.y;
baseVertices[3 * i + 2] = ta.z;
}
// top at y=-h/2
for (int i = div; i < 2 * div; i++) {
double ang = i * 2d * Math.PI / div;
double pol = polygonalSection(ang);
Point3D ta = transform(rTop * pol * Math.cos(ang), -h / 2, rTop * pol * Math.sin(ang));
baseVertices[3 * i] = ta.x;
baseVertices[3 * i + 1] = ta.y;
baseVertices[3 * i + 2] = ta.z;
}
Point3D ta = transform(0, h / 2, 0);
baseVertices[6 * div] = ta.x;
baseVertices[6 * div + 1] = ta.y;
baseVertices[6 * div + 2] = ta.z;
ta = transform(0, -h / 2, 0);
baseVertices[6 * div + 3] = ta.x;
baseVertices[6 * div + 4] = ta.y;
baseVertices[6 * div + 5] = ta.z;
int nTextCoords = div * 4 + 6;
float rectBase = (float) polygonalSize(rBase);
float rectTop = (float) polygonalSize(rTop);
float L = (float) (rBase + 2d * Math.PI * rBase);
float H = 2f * (rBase + rTop) + h;
final float[] baseTexCoords = new float[nTextCoords * 2];
// u right ,v up
for (int i = 0; i <= div; i++) {
baseTexCoords[2 * i] = (float) (rBase + i * rectBase / div) / L;
baseTexCoords[2 * i + 1] = (float) (2f * rTop + h) / H;
}
for (int i = 0; i <= div; i++) {
baseTexCoords[2 * div + 2 * i + 2] = (float) (rBase + i * rectTop / div) / L;
baseTexCoords[2 * div + 2 * i + 3] = (float) (2f * rTop) / H;
}
for (int i = 0; i <= div; i++) {
double ang = i * 2d * Math.PI / div;
double pol = polygonalSection(ang);
baseTexCoords[4 * div + 2 * i + 4] = (float) (rBase + rBase * pol * Math.sin(ang)) / L;
baseTexCoords[4 * div + 2 * i + 5] = (float) (2f * rTop + rBase + h - rBase * pol * Math.cos(ang)) / H;
}
for (int i = 0; i <= div; i++) {
double ang = i * 2d * Math.PI / div;
double pol = polygonalSection(ang);
baseTexCoords[6 * div + 2 * i + 6] = (float) (rBase + rTop * pol * Math.sin(ang)) / L;
baseTexCoords[6 * div + 2 * i + 7] = (float) (rTop + rTop * pol * Math.cos(ang)) / H;
}
baseTexCoords[8 * div + 8] = rBase / L;
baseTexCoords[8 * div + 9] = (2f * rTop + rBase + h) / H;
baseTexCoords[8 * div + 10] = rBase / L;
baseTexCoords[8 * div + 11] = rTop / H;
int nFaces = div * 4;
final int[] baseTexture = new int[nFaces * 3];
final int[] baseFaces = new int[nFaces * 3];
for (int i = 0; i < div; i++) {
int p1 = i + 1;
int p2 = i + div;
int p3 = i + div + 1;
baseFaces[6 * i] = i;
baseFaces[6 * i + 1] = p1 == div ? 0 : p1;
baseFaces[6 * i + 2] = p2;
baseFaces[6 * i + 3] = p3 % div == 0 ? p3 - div : p3;
baseFaces[6 * i + 4] = p2;
baseFaces[6 * i + 5] = p1 == div ? 0 : p1;
baseTexture[6 * i] = i;
baseTexture[6 * i + 1] = p1;
baseTexture[6 * i + 2] = p2 + 1;
baseTexture[6 * i + 3] = p3 + 1;
baseTexture[6 * i + 4] = p2 + 1;
baseTexture[6 * i + 5] = p1;
}
for (int i = 0; i < div; i++) {
int p1 = div * 2;
int p2 = i + 1;
baseFaces[6 * div + 3 * i] = i;
baseFaces[6 * div + 3 * i + 1] = p1;
baseFaces[6 * div + 3 * i + 2] = p2 == div ? 0 : p2;
baseTexture[6 * div + 3 * i] = (div + 1) * 2 + i;
baseTexture[6 * div + 3 * i + 1] = (div + 1) * 4;
baseTexture[6 * div + 3 * i + 2] = (div + 1) * 2 + i + 1;
}
for (int i = 0; i < div; i++) {
int p1 = div * 2 + 1;
int p2 = i + 1 + div;
baseFaces[9 * div + 3 * i] = i + div;
baseFaces[9 * div + 3 * i + 1] = p2 % div == 0 ? p2 - div : p2;
baseFaces[9 * div + 3 * i + 2] = p1;
baseTexture[9 * div + 3 * i] = (div + 1) * 3 + i;
baseTexture[9 * div + 3 * i + 1] = (div + 1) * 3 + i + 1;
baseTexture[9 * div + 3 * i + 2] = (div + 1) * 4 + 1;
}
points0 = baseVertices;
numVertices = baseVertices.length / 3;
texCoord0 = baseTexCoords;
numTexCoords = baseTexCoords.length / 2;
faces0 = IntStream.range(0, baseFaces.length / 3).mapToObj(i -> IntStream.of(baseFaces[3 * i], baseTexture[3 * i], baseFaces[3 * i + 1], baseTexture[3 * i + 1], baseFaces[3 * i + 2], baseTexture[3 * i + 2])).flatMapToInt(i -> i).toArray();
numFaces = baseFaces.length / 3;
} else if (m0 != null) {
points0 = new float[numVertices * m0.getPointElementSize()];
m0.getPoints().toArray(points0);
}
final float h = height;
List<Point3D> points1 = IntStream.range(0, numVertices).mapToObj(i -> {
Point3D p = new Point3D(points0[3 * i], points0[3 * i + 1], points0[3 * i + 2]);
p.f = (h / 2 - unTransform(p).y) / h;
return p;
}).collect(Collectors.toList());
if (level > 0 && m0 != null) {
texCoord0 = new float[numTexCoords * m0.getTexCoordElementSize()];
m0.getTexCoords().toArray(texCoord0);
}
texCoord1 = IntStream.range(0, numTexCoords).mapToObj(i -> new Point2D(texCoord0[2 * i], texCoord0[2 * i + 1])).collect(Collectors.toList());
if (level > 0 && m0 != null) {
faces0 = new int[numFaces * m0.getFaceElementSize()];
m0.getFaces().toArray(faces0);
}
List<Face3> faces1 = IntStream.range(0, numFaces).mapToObj(i -> new Face3(faces0[6 * i], faces0[6 * i + 2], faces0[6 * i + 4])).collect(Collectors.toList());
index.set(points1.size());
map.clear();
listVertices.clear();
listFaces.clear();
listVertices.addAll(points1);
faces1.forEach(face -> {
int v1 = face.p0;
int v2 = face.p1;
int v3 = face.p2;
if (level > 0) {
int a = getMiddle(v1, points1.get(v1), v2, points1.get(v2));
int b = getMiddle(v2, points1.get(v2), v3, points1.get(v3));
int c = getMiddle(v3, points1.get(v3), v1, points1.get(v1));
listFaces.add(new Face3(v1, a, c));
listFaces.add(new Face3(v2, b, a));
listFaces.add(new Face3(v3, c, b));
listFaces.add(new Face3(a, b, c));
} else {
listFaces.add(new Face3(v1, v2, v3));
}
});
map.clear();
numVertices = listVertices.size();
numFaces = listFaces.size();
List<Face3> textures1;
if (level == 0) {
textures1 = IntStream.range(0, faces0.length / 6).mapToObj(i -> new Face3(faces0[6 * i + 1], faces0[6 * i + 3], faces0[6 * i + 5])).collect(Collectors.toList());
} else {
textures1 = listTextures.stream().map(t -> t).collect(Collectors.toList());
}
index.set(texCoord1.size());
listTextures.clear();
AtomicInteger kk = new AtomicInteger();
textures1.forEach(face -> {
int v1 = face.p0;
int v2 = face.p1;
int v3 = face.p2;
if (level > 0) {
int a = getMiddle(v1, texCoord1.get(v1), v2, texCoord1.get(v2));
int b = getMiddle(v2, texCoord1.get(v2), v3, texCoord1.get(v3));
int c = getMiddle(v3, texCoord1.get(v3), v1, texCoord1.get(v1));
listTextures.add(new Face3(v1, a, c));
listTextures.add(new Face3(v2, b, a));
listTextures.add(new Face3(v3, c, b));
listTextures.add(new Face3(a, b, c));
} else {
listTextures.add(new Face3(v1, v2, v3));
}
});
map.clear();
texCoord0 = texCoord1.stream().flatMapToDouble(p -> DoubleStream.of(p.getX(), p.getY())).collect(() -> new FloatCollector(texCoord1.size() * 2), FloatCollector::add, FloatCollector::join).toArray();
numTexCoords = texCoord0.length / 2;
textureCoords = texCoord0;
if (level == getLevel()) {
areaMesh.setWidth(majorRadius + 2f * Math.PI * majorRadius);
areaMesh.setHeight(height + 2f * (minorRadius + majorRadius));
smoothingGroups = IntStream.range(0, listFaces.size()).map(i -> {
if (getSectionType() != TriangleMeshHelper.SectionType.CIRCLE) {
return 0;
}
if (i < listFaces.size() / 2) {
return 1;
} else if (i < 3 * listFaces.size() / 4) {
return 2;
}
return 4;
}).toArray();
}
return createMesh();
}
use of javafx.scene.transform.Affine in project FXyzLib by Birdasaur.
the class SegmentedSphereMesh method createSegmentedSphere.
private TriangleMesh createSegmentedSphere(int subDivY, int cropX, int cropY, float radius, float tubeStartAngle, float xOffset, float yOffset, float zOffset) {
listVertices.clear();
listTextures.clear();
listFaces.clear();
int subDivX = subDivY;
int numDivX = subDivX + 1 - 2 * cropX;
float pointX, pointY, pointZ;
areaMesh.setWidth((1 - 2 * cropX / subDivX) * 2d * Math.PI * radius);
areaMesh.setHeight((1 - 2 * cropY / subDivY) * 2d * Math.PI * radius);
a = new Affine();
if (center.get() != null) {
a = a.createConcatenation(new Translate(center.get().x, center.get().y, center.get().z));
}
// Create points
for (int y = cropY; y <= subDivY - cropY; y++) {
float dy = (float) y / subDivY;
for (int x = cropX; x <= subDivX - cropX; x++) {
float dx = (float) x / subDivX;
if (cropX > 0 || (cropX == 0 && x < subDivX)) {
pointX = (float) ((radius * Math.sin((-1d + dy) * Math.PI)) * (Math.cos((-1d + 2d * dx) * Math.PI) + xOffset));
pointZ = (float) ((radius * Math.sin((-1d + dy) * Math.PI)) * (Math.sin((-1d + 2d * dx) * Math.PI) + yOffset));
pointY = (float) (radius * Math.cos((-1d + dy) * Math.PI) * zOffset);
Point3D ta = transform(pointX, pointY, pointZ);
listVertices.add(ta);
}
}
}
// Create texture coordinates
// if(exterior.get()){
createTexCoords(subDivX - 2 * cropX, subDivY - 2 * cropY);
// Create textures indices
for (int y = cropY; y < subDivY - cropY; y++) {
for (int x = cropX; x < subDivX - cropX; x++) {
int p00 = (y - cropY) * numDivX + (x - cropX);
int p01 = p00 + 1;
int p10 = p00 + numDivX;
int p11 = p10 + 1;
if (y < subDivY - 1) {
listTextures.add(new Face3(p00, p10, p11));
}
if (y > 0) {
listTextures.add(new Face3(p11, p01, p00));
}
}
}
// Create faces indices
for (int y = cropY; y < subDivY - cropY; y++) {
for (int x = cropX; x < subDivX - cropX; x++) {
int p00 = (y - cropY) * ((cropX > 0) ? numDivX : numDivX - 1) + (x - cropX);
int p01 = p00 + 1;
if (cropX == 0 && x == subDivX - 1) {
p01 -= subDivX;
}
int p10 = p00 + ((cropX > 0) ? numDivX : numDivX - 1);
// if(cropY==0 && y==subDivY-1){
// p10-=subDivY*((cropX>0)?numDivX:numDivX-1);
// }
int p11 = p10 + 1;
if (cropX == 0 && x == subDivX - 1) {
p11 -= subDivX;
}
if (y < subDivY - 1) {
listFaces.add(new Face3(p00, p10, p11));
}
if (y > 0) {
listFaces.add(new Face3(p11, p01, p00));
}
}
}
return createMesh();
}
use of javafx.scene.transform.Affine in project FXyzLib by Birdasaur.
the class CuboidMesh method createCube.
private TriangleMesh createCube(float width, float height, float depth, int level) {
TriangleMesh m0 = null;
if (level > 0) {
m0 = createCube(width, height, depth, level - 1);
}
if (level == 0) {
a = new Affine();
float L = 2f * width + 2f * depth;
float H = height + 2f * depth;
float hw = width / 2f, hh = height / 2f, hd = depth / 2f;
if (center.get() != null) {
a = a.createConcatenation(new Translate(center.get().x, center.get().y, center.get().z));
// hw+=center.get().x;
// hh+=center.get().y;
// hd+=center.get().z;
}
final float[] baseVertices = new float[] { hw, hh, hd, hw, hh, -hd, hw, -hh, hd, hw, -hh, -hd, -hw, hh, hd, -hw, hh, -hd, -hw, -hh, hd, -hw, -hh, -hd };
final float[] baseTexCoords = new float[] { depth / L, 0f, (depth + width) / L, 0f, 0f, depth / H, depth / L, depth / H, (depth + width) / L, depth / H, (2f * depth + width) / L, depth / H, 1f, depth / H, 0f, (depth + height) / H, depth / L, (depth + height) / H, (depth + width) / L, (depth + height) / H, (2f * depth + width) / L, (depth + height) / H, 1f, (depth + height) / H, depth / L, 1f, (depth + width) / L, 1f };
final int[] baseTexture = new int[] { 8, 3, 7, 3, 2, 7, 9, 10, 4, 4, 10, 5, 8, 12, 9, 9, 12, 13, 3, 4, 0, 0, 4, 1, 8, 9, 3, 3, 9, 4, 11, 6, 10, 10, 6, 5 };
final List<Integer> baseFaces = Arrays.asList(0, 2, 1, 2, 3, 1, 4, 5, 6, 6, 5, 7, 0, 1, 4, 4, 1, 5, 2, 6, 3, 3, 6, 7, 0, 4, 2, 2, 4, 6, 1, 3, 5, 5, 3, 7);
for (int i = 0; i < baseVertices.length / 3; i++) {
Point3D ta = transform(baseVertices[3 * i], baseVertices[3 * i + 1], baseVertices[3 * i + 2]);
baseVertices[3 * i] = ta.x;
baseVertices[3 * i + 1] = ta.y;
baseVertices[3 * i + 2] = ta.z;
}
points0 = baseVertices;
numVertices = baseVertices.length / 3;
texCoord0 = baseTexCoords;
numTexCoords = baseTexCoords.length / 2;
faces0 = IntStream.range(0, baseFaces.size() / 3).mapToObj(i -> IntStream.of(baseFaces.get(3 * i), baseTexture[3 * i], baseFaces.get(3 * i + 1), baseTexture[3 * i + 1], baseFaces.get(3 * i + 2), baseTexture[3 * i + 2])).flatMapToInt(i -> i).toArray();
numFaces = baseFaces.size() / 3;
} else if (m0 != null) {
points0 = new float[numVertices * m0.getPointElementSize()];
m0.getPoints().toArray(points0);
}
List<Point3D> points1 = IntStream.range(0, numVertices).mapToObj(i -> new Point3D(points0[3 * i], points0[3 * i + 1], points0[3 * i + 2])).collect(Collectors.toList());
if (level > 0 && m0 != null) {
texCoord0 = new float[numTexCoords * m0.getTexCoordElementSize()];
m0.getTexCoords().toArray(texCoord0);
}
texCoord1 = IntStream.range(0, numTexCoords).mapToObj(i -> new Point2D(texCoord0[2 * i], texCoord0[2 * i + 1])).collect(Collectors.toList());
if (level > 0 && m0 != null) {
faces0 = new int[numFaces * m0.getFaceElementSize()];
m0.getFaces().toArray(faces0);
}
List<Face3> faces1 = IntStream.range(0, numFaces).mapToObj(i -> new Face3(faces0[6 * i], faces0[6 * i + 2], faces0[6 * i + 4])).collect(Collectors.toList());
index.set(points1.size());
map.clear();
listVertices.clear();
listFaces.clear();
listVertices.addAll(points1);
faces1.forEach(face -> {
int v1 = face.p0;
int v2 = face.p1;
int v3 = face.p2;
if (level > 0) {
int a = getMiddle(v1, points1.get(v1), v2, points1.get(v2));
int b = getMiddle(v2, points1.get(v2), v3, points1.get(v3));
int c = getMiddle(v3, points1.get(v3), v1, points1.get(v1));
listFaces.add(new Face3(v1, a, c));
listFaces.add(new Face3(v2, b, a));
listFaces.add(new Face3(v3, c, b));
listFaces.add(new Face3(a, b, c));
} else {
listFaces.add(new Face3(v1, v2, v3));
}
});
map.clear();
numVertices = listVertices.size();
numFaces = listFaces.size();
List<Face3> textures1;
if (level == 0) {
textures1 = IntStream.range(0, faces0.length / 6).mapToObj(i -> new Face3(faces0[6 * i + 1], faces0[6 * i + 3], faces0[6 * i + 5])).collect(Collectors.toList());
} else {
textures1 = listTextures.stream().map(t -> t).collect(Collectors.toList());
}
index.set(texCoord1.size());
listTextures.clear();
textures1.forEach(face -> {
int v1 = face.p0;
int v2 = face.p1;
int v3 = face.p2;
if (level > 0) {
int a = getMiddle(v1, texCoord1.get(v1), v2, texCoord1.get(v2));
int b = getMiddle(v2, texCoord1.get(v2), v3, texCoord1.get(v3));
int c = getMiddle(v3, texCoord1.get(v3), v1, texCoord1.get(v1));
listTextures.add(new Face3(v1, a, c));
listTextures.add(new Face3(v2, b, a));
listTextures.add(new Face3(v3, c, b));
listTextures.add(new Face3(a, b, c));
} else {
listTextures.add(new Face3(v1, v2, v3));
}
});
map.clear();
texCoord0 = texCoord1.stream().flatMapToDouble(p -> DoubleStream.of(p.getX(), p.getY())).collect(() -> new FloatCollector(texCoord1.size() * 2), FloatCollector::add, FloatCollector::join).toArray();
numTexCoords = texCoord0.length / 2;
textureCoords = texCoord0;
if (level == getLevel()) {
areaMesh.setWidth(2f * width + 2f * depth);
areaMesh.setHeight(height + 2f * depth);
// 1<<j -> bitset, 00100. Otherwise: 000111 will mean they are shared
smoothingGroups = IntStream.range(0, listFaces.size()).map(i -> 1 << (i / (listFaces.size() / 6))).toArray();
// smoothing groups based on 3DViewer -> same result
// float[] normals=new float[]{1,0,0,-1,0,0,0,1,0,0,-1,0,0,0,1,0,0,-1};
// int[] newFaces = IntStream.range(0, listFaces.size())
// .mapToObj(i->IntStream.of((int)listFaces.get(i).x, (int)listFaces.get(i).x,
// (int)listFaces.get(i).y, (int)listFaces.get(i).y,
// (int)listFaces.get(i).z, (int)listFaces.get(i).z))
// .flatMapToInt(i->i).toArray();
// int[] newFaceNormals = IntStream.range(0,listFaces.size()).mapToObj(i->{
// int j=(i/(listFaces.size()/6));
// return IntStream.of(j,j,j);
// }).flatMapToInt(i->i).toArray();
// smoothingGroups=SmoothingGroups.calcSmoothGroups(new TriangleMesh(), newFaces, newFaceNormals, normals);
}
return createMesh();
}
Aggregations