Files
artloglaby/java/org/artisanlogiciel/games/stl/Wall3d.java
philippe lhardy f07767dcfd fix normals for vertices
- now stl output can be porcessed directly by slic3r without intermediate fix wihtin blender
- created Wall3dStream instead of keeping all within Wall3d
- can save only stl output ( 'Save stl' )
2020-10-11 22:14:10 +02:00

180 lines
5.7 KiB
Java

package org.artisanlogiciel.games.stl;
import java.util.Scanner;
import org.artisanlogiciel.games.Brick;
import org.artisanlogiciel.games.LabyModel;
import org.artisanlogiciel.games.WallsProvider;
import java.io.OutputStream;
import java.io.IOException;
/**
* Wall3d to create walls in 3d for stl conversion South, West North East...
*
* wall3D will create a rectangular cuboid with 2 triangle vertex for each face
**/
public class Wall3d {
// 4 triangles in 2 dim space reused 3 times
// in facts order matters...
final static int BASE[][][] = {
// lower left
{{0, 0}, {1, 0}, {0, 1}},
// higher right
{{1, 0}, {1, 1}, {0, 1}},
// lower right
{{0, 0}, {1, 0}, {1, 1}},
// higher left
{{0, 0}, {1, 1}, {0, 1}}};
final static short X = 1;
final static short Y = 2;
final static short Z = 4;
// final static short AXIS[][]= {{X,Y},{-Z,Y},{X,Y},{Z,Y},{X,-Z},{X,-Z}};
// [face][axis]
final static short AXIS[][] = {
// face 0 (x,y) back
{X, Y, 0},
// face 1 (z,y) left
{Z, Y, 0},
// face 2 (x,y,1)
{X, Y, 1},
// face 3
{Z, Y, 1},
// face 4
{X, Z, 0},
// face 5
{X, Z, 1}};
final static String normalx = "1.0 0.0 0.0";
final static String normaly = "0.0 1.0 0.0";
final static String normalz = "0.0 0.0 1.0";
final static String normalmx = "-1.0 0.0 0.0";
final static String normalmy = "0.0 -1.0 0.0";
final static String normalmz = "0.0 0.0 -1.0";
// final static short NORMAL[] = {Z,X,Z,X,Y,Y};
final static String normalstr[] =
{ normalmz, normalx,
normalz, normalmx,
normaly, normalmy
};
boolean reverse_vertex[] = {
true,false,false,true,false,true
};
int triangle[][][] = null;
public Wall3d(int t[][][]) {
triangle = t;
}
public Wall3d(Wall3d origin, int dx, int dy, int dz) {
triangle = origin.translate(dx, dy, dz);
}
Wall3d(int xl, int yl, int zl, int dx, int dy, int dz) {
int f = 0;
triangle = new int[12][3][3];
int[] factor = {xl, yl, zl};
int[] translate = {dx, dy, dz};
for (int facet = 0; facet < 12; facet++) {
// point in a triangle / facet
for (int p = 0; p < 3; p++) {
short uaxis = 0;
// a square face is two facets.
int face = facet / 2;
// first two axis ( projected on x,y,z depending on AXIS[face][] )
for (int axis = 0; axis < 2; axis++) {
short caxis = AXIS[face][axis];
if (caxis > 0) {
f = 1;
} else if (caxis < 0) {
// wait wait in AXIS there is no negative value ...
// so we never enter here, what was the purpose ? might be history.
f = -1;
caxis = (short) -caxis;
}
// what if caxis == 0 ? f is kept as its previous value ?
// which is 1 in facts due to AXIS[..][0] > 0
// uaxis keep track of used axes for this face to find last missing axis
uaxis |= caxis;
if (caxis == X) {
caxis = 0;
} else if (caxis == Y) {
caxis = 1;
} else {
caxis = 2;
}
triangle[facet][p][caxis] = translate[caxis] + BASE[facet % 4][p][axis] * f * factor[caxis];
}
// last remaining axis
if ((uaxis & X) == 0) {
// no X was used => X
uaxis = 0;
} else if ((uaxis & Y) == 0) {
// X was used byt not Y => Y
uaxis = 1;
} else {
// default X, and Y were used => Z
uaxis = 2;
}
triangle[facet][p][uaxis] = translate[uaxis] + AXIS[facet / 2][2] * factor[uaxis];
}
}
}
public int[][][] translate(int dx, int dy, int dz) {
int[] translate = {dx, dy, dz};
int t[][][] = new int[12][3][3];
for (int facet = 0; facet < 12; facet ++) {
// point in a triangle
for (int p = 0; p < 3; p++) {
for (int axis = 0; axis < 3; axis++) {
t[facet][p][axis] = translate[axis] + triangle[facet][p][axis];
}
}
}
return t;
}
/**
* write triangles as stl text
**/
public String toString() {
String s = "";
for (int facet = 0; facet < 12; facet++) {
int face = facet / 2;
// most software don't care normal but just rely on vertex order ( right hand ).
String normal = normalstr[face];
s += "facet normal " + normal + "\nouter loop\n";
boolean reverse = reverse_vertex[face];
for (int p = 0; p < 3; p++) {
s += "vertex";
// p that accept right hand
int rhp = p;
if ( reverse )
{
// reverse 2 and 1 ; 0 => 0, 1 => 2 , 2 => 1
rhp = ( p * 5 ) % 3;
}
for (int a = 0; a < 3; a++) {
s += " " + triangle[facet][rhp][a];
}
s += "\n";
}
s = s + "endloop\nendfacet\n";
}
return s;
}
}