use of maspack.matrix.Vector3d in project artisynth_core by artisynth.
the class MeshBase method setNormals.
/**
* Explicitly sets the normals and associated indices for this mesh. The
* information supplied by <code>nrmls</code> and <code>indices</code> is
* copied to internal structures that are subsequently returned by {@link
* #getNormals} and {@link #getNormalIndices()}, respectively.
* The argument <code>indices</code> specifies an index values into
* <code>nrmls</code> for each vertex of each feature, as described for
* {@link #getNormalIndices()}. If a feature vertex has no normal value, the
* index should be specified as <code>-1</code>.
* <code>indices</code> is <code>null</code>, then <code>nrmls</code> should
* contain one normal per vertex and a default index set will be created,
* appropriate to the mesh subclass.
*
* <p>If <code>normals</code> is <code>null</code>, then
* normals are explicitly removed and subsequent calls to {@link
* #getNormals} will return <code>null</code>.
*
* <p>After this call, {@link #hasExplicitNormals} will return
* <code>true</code>.
*
* @param normals vertex normals to be set for this mesh
* @param indices normal indices, or <code>null</code> if the indices are to be
* automatically generated.
*/
public void setNormals(List<Vector3d> normals, int[] indices) {
if (normals == null) {
myNormals = null;
myNormalIndices = null;
} else {
ArrayList<Vector3d> newNormals = new ArrayList<Vector3d>(normals.size());
for (int i = 0; i < normals.size(); i++) {
newNormals.add(new Vector3d(normals.get(i)));
}
if (indices == null && normals.size() != numVertices()) {
throw new IllegalArgumentException("Number of normals must equal number of vertices when " + "indices argument is null");
}
int[] newIndices = createIndices(indices, normals.size());
myNormals = newNormals;
myNormalIndices = newIndices;
}
myRenderNormalsValidP = false;
myNormalsExplicitP = true;
notifyModified();
}
use of maspack.matrix.Vector3d in project artisynth_core by artisynth.
the class MeshBase method computeAverageRadius.
public double computeAverageRadius() {
if (myVertices.size() == 0) {
return 0;
}
Vector3d centroid = new Vector3d();
computeCentroid(centroid);
double radius = 0;
for (int i = 0; i < myVertices.size(); i++) {
radius += centroid.distance(myVertices.get(i).pnt);
}
return radius / myVertices.size();
}
use of maspack.matrix.Vector3d in project artisynth_core by artisynth.
the class MeshBase method epsilonEquals.
/**
* Base method for testing if two meshes are equal. Two MeshBase objects are
* considered equal if their vertex coordinates and transforms are equal
* within <code>eps</code>. This method, and its overrides, is used
* in mesh unit tests.
*/
public boolean epsilonEquals(MeshBase base, double eps) {
if (!XMeshToWorld.epsilonEquals(base.XMeshToWorld, eps)) {
return false;
}
if (myVertices.size() != base.myVertices.size()) {
return false;
}
for (int i = 0; i < myVertices.size(); i++) {
Vertex3d vtx0 = myVertices.get(i);
Vertex3d vtx1 = base.myVertices.get(i);
if (!vtx0.pnt.epsilonEquals(vtx1.pnt, eps)) {
return false;
}
}
if (myNormalsExplicitP != base.myNormalsExplicitP) {
return false;
}
if (myNormalsExplicitP) {
if (myNormals.size() != base.myNormals.size()) {
return false;
}
for (int i = 0; i < myNormals.size(); i++) {
Vector3d nrm0 = myNormals.get(i);
Vector3d nrm1 = base.myNormals.get(i);
if (!nrm0.epsilonEquals(nrm1, eps)) {
return false;
}
}
if (!Arrays.equals(myNormalIndices, base.myNormalIndices)) {
return false;
}
}
if ((myColors == null) != (base.myColors == null)) {
return false;
}
if (myColors != null) {
if (myColors.size() != base.myColors.size()) {
return false;
}
for (int i = 0; i < myColors.size(); i++) {
float[] col0 = myColors.get(i);
float[] col1 = base.myColors.get(i);
for (int j = 0; j < 4; j++) {
if (Math.abs(col0[j] - col1[j]) > eps) {
return false;
}
}
}
if (!Arrays.equals(getColorIndices(), base.getColorIndices())) {
return false;
}
}
if ((myTextureCoords == null) != (base.myTextureCoords == null)) {
return false;
}
if (myTextureCoords != null) {
if (myTextureCoords.size() != base.myTextureCoords.size()) {
return false;
}
for (int i = 0; i < myTextureCoords.size(); i++) {
Vector3d tex0 = myTextureCoords.get(i);
Vector3d tex1 = base.myTextureCoords.get(i);
if (!tex0.epsilonEquals(tex1, eps)) {
return false;
}
}
if (!Arrays.equals(myTextureIndices, base.myTextureIndices)) {
return false;
}
}
return true;
}
use of maspack.matrix.Vector3d in project artisynth_core by artisynth.
the class MeshFactory method createRectangle.
/**
* Create a open rectangular mesh, composed of triangles, in the x-y
* plane, centered on the origin and with normals directed along the z axis.
* Texture coordinates can optionally be created created for each triangle
* so that (0,0) and (1,1) correspond to the lower left and upper right
* corners.
*
* @param wx width in the x direction
* @param wy width in the y direction
* @param xdiv number of divisions in x (>=1)
* @param ydiv number of divisions in y (>=1)
* @param addNormals if <code>true</code>, generates normals in
* the positive z direction
* @param addTextureCoords if <code>true</code>, generates texture
* coordinates
* @return created mesh
*/
public static PolygonalMesh createRectangle(double wx, double wy, int xdiv, int ydiv, boolean addNormals, boolean addTextureCoords) {
Point3d[] plist = new Point3d[(xdiv + 1) * (ydiv + 1)];
int[][] faceIndices = new int[xdiv * ydiv * 2][];
ArrayList<Vector3d> vt = new ArrayList<Vector3d>();
double xoffset = -wx / 2;
double yoffset = -wy / 2;
double dx = wx / xdiv;
double dy = wy / ydiv;
double dxt = 1.0 / xdiv;
double dyt = 1.0 / ydiv;
for (int j = 0; j <= ydiv; j++) {
for (int i = 0; i <= xdiv; i++) {
plist[i + j * (xdiv + 1)] = new Point3d(xoffset + i * dx, yoffset + j * dy, 0);
if (addTextureCoords) {
vt.add(new Point3d(i * dxt, j * dyt, 0));
}
if (i < xdiv && j < ydiv) {
int idx1 = i + j * (xdiv + 1);
int idx2 = (i + 1) + j * (xdiv + 1);
int idx3 = (i + 1) + (j + 1) * (xdiv + 1);
int idx4 = i + (j + 1) * (xdiv + 1);
int istart = 2 * (i + j * xdiv);
if ((i + j) % 2 == 0) {
faceIndices[istart] = new int[] { idx1, idx2, idx4 };
faceIndices[istart + 1] = new int[] { idx2, idx3, idx4 };
} else {
faceIndices[istart] = new int[] { idx1, idx2, idx3 };
faceIndices[istart + 1] = new int[] { idx1, idx3, idx4 };
}
}
}
}
PolygonalMesh mesh = new PolygonalMesh();
mesh.set(plist, faceIndices);
if (addTextureCoords) {
mesh.setTextureCoords(vt, mesh.createVertexIndices());
}
if (addNormals) {
ArrayList<Vector3d> normals = new ArrayList<>();
normals.add(new Vector3d(0, 0, 1));
int[] indices = mesh.createVertexIndices();
mesh.setNormals(normals, indices);
}
return mesh;
}
use of maspack.matrix.Vector3d in project artisynth_core by artisynth.
the class MeshFactory method createBox.
/**
* Creates a box mesh, with a specified mesh resolution in each direction,
* and centered at a defined center point. The faces type is specified
* by <code>faceType</code>
*
* @param wx width in the x direction
* @param wy width in the y direction
* @param wz width in the z direction
* @param center center of the box
* @param nx number of subdivisions along x
* @param ny number of subdivisions along y
* @param nz number of subdivisions along z
* @param addNormals if <code>true</code>, generates normals perpendicular
* to each side
* @param faceType specifies the face type to be either quads, triangles,
* or triangles with alternating diagonals
*/
public static PolygonalMesh createBox(double wx, double wy, double wz, Point3d center, int nx, int ny, int nz, boolean addNormals, FaceType faceType) {
PolygonalMesh mesh = new PolygonalMesh();
Vertex3d[][][] vtxs = new Vertex3d[nx + 1][ny + 1][nz + 1];
Vertex3d[] faceVtxs = new Vertex3d[4];
ArrayList<Vector3d> nrmls = null;
int[] nrmlIdxs = null;
if (addNormals) {
nrmls = new ArrayList<Vector3d>();
nrmls.add(new Vector3d(1, 0, 0));
nrmls.add(new Vector3d(0, 1, 0));
nrmls.add(new Vector3d(0, 0, 1));
nrmls.add(new Vector3d(-1, 0, 0));
nrmls.add(new Vector3d(0, -1, 0));
nrmls.add(new Vector3d(0, 0, -1));
int nindices;
if (faceType == FaceType.QUAD) {
nindices = 8 * (nx * ny + nx * nz + ny * nz);
} else {
// trianglar
nindices = 12 * (nx * ny + nx * nz + ny * nz);
}
nrmlIdxs = new int[nindices];
}
Vector3d dx = new Vector3d(wx / (nx), wy / (ny), wz / (nz));
Point3d offset = new Point3d(-wx / 2, -wy / 2, -wz / 2);
boolean[] hardEdges;
// bottom/top (sides in x/y plane)
for (int i = 0; i < nx; i++) {
for (int j = 0; j < ny; j++) {
faceVtxs[0] = getOrCreateVertex(i, j, 0, vtxs, offset, dx, mesh);
faceVtxs[1] = getOrCreateVertex(i, j + 1, 0, vtxs, offset, dx, mesh);
faceVtxs[2] = getOrCreateVertex(i + 1, j + 1, 0, vtxs, offset, dx, mesh);
faceVtxs[3] = getOrCreateVertex(i + 1, j, 0, vtxs, offset, dx, mesh);
// notes: edge(i) appears *before* vertex(i).
hardEdges = new boolean[] { j == 0, i == 0, j == ny - 1, i == nx - 1 };
addFaces(mesh, faceVtxs, hardEdges, 5, nrmlIdxs, i + j, faceType);
faceVtxs[0] = getOrCreateVertex(i, j, nz, vtxs, offset, dx, mesh);
faceVtxs[3] = getOrCreateVertex(i, j + 1, nz, vtxs, offset, dx, mesh);
faceVtxs[2] = getOrCreateVertex(i + 1, j + 1, nz, vtxs, offset, dx, mesh);
faceVtxs[1] = getOrCreateVertex(i + 1, j, nz, vtxs, offset, dx, mesh);
hardEdges = new boolean[] { i == 0, j == 0, i == nx - 1, j == ny - 1 };
addFaces(mesh, faceVtxs, hardEdges, 2, nrmlIdxs, i + j, faceType);
}
}
// back/front (sides in z/x plane)
for (int i = 0; i < nx; i++) {
for (int k = 0; k < nz; k++) {
faceVtxs[0] = getOrCreateVertex(i, 0, k, vtxs, offset, dx, mesh);
faceVtxs[3] = getOrCreateVertex(i, 0, k + 1, vtxs, offset, dx, mesh);
faceVtxs[2] = getOrCreateVertex(i + 1, 0, k + 1, vtxs, offset, dx, mesh);
faceVtxs[1] = getOrCreateVertex(i + 1, 0, k, vtxs, offset, dx, mesh);
hardEdges = new boolean[] { i == 0, k == 0, i == nx - 1, k == nz - 1 };
addFaces(mesh, faceVtxs, hardEdges, 4, nrmlIdxs, i + k, faceType);
faceVtxs[0] = getOrCreateVertex(i, ny, k, vtxs, offset, dx, mesh);
faceVtxs[1] = getOrCreateVertex(i, ny, k + 1, vtxs, offset, dx, mesh);
faceVtxs[2] = getOrCreateVertex(i + 1, ny, k + 1, vtxs, offset, dx, mesh);
faceVtxs[3] = getOrCreateVertex(i + 1, ny, k, vtxs, offset, dx, mesh);
hardEdges = new boolean[] { k == 0, i == 0, k == nz - 1, i == nx - 1 };
addFaces(mesh, faceVtxs, hardEdges, 1, nrmlIdxs, i + k, faceType);
}
}
// left/right (sides in y/z plane)
for (int j = 0; j < ny; j++) {
for (int k = 0; k < nz; k++) {
faceVtxs[0] = getOrCreateVertex(0, j, k, vtxs, offset, dx, mesh);
faceVtxs[3] = getOrCreateVertex(0, j + 1, k, vtxs, offset, dx, mesh);
faceVtxs[2] = getOrCreateVertex(0, j + 1, k + 1, vtxs, offset, dx, mesh);
faceVtxs[1] = getOrCreateVertex(0, j, k + 1, vtxs, offset, dx, mesh);
hardEdges = new boolean[] { k == 0, j == 0, k == nz - 1, j == ny - 1 };
addFaces(mesh, faceVtxs, hardEdges, 3, nrmlIdxs, j + k, faceType);
faceVtxs[0] = getOrCreateVertex(nx, j, k, vtxs, offset, dx, mesh);
faceVtxs[1] = getOrCreateVertex(nx, j + 1, k, vtxs, offset, dx, mesh);
faceVtxs[2] = getOrCreateVertex(nx, j + 1, k + 1, vtxs, offset, dx, mesh);
faceVtxs[3] = getOrCreateVertex(nx, j, k + 1, vtxs, offset, dx, mesh);
hardEdges = new boolean[] { j == 0, k == 0, j == ny - 1, k == nz - 1 };
addFaces(mesh, faceVtxs, hardEdges, 0, nrmlIdxs, j + k, faceType);
}
}
if (addNormals) {
mesh.setNormals(nrmls, nrmlIdxs);
}
if (center != null) {
mesh.transform(new RigidTransform3d(center.x, center.y, center.z));
}
return mesh;
}
Aggregations