xxxxxxxxxx
281
class Marching {
constructor(e1, e2, e3, e4, e5, e6, e7, e8) {
this.boundary = [];
this.vertices = [];
this.points = [];
this.points.push(e1);
this.points.push(e2);
this.points.push(e3);
this.points.push(e4);
this.points.push(e5);
this.points.push(e6);
this.points.push(e7);
this.points.push(e8);
this.facesRef = []; // the array that doesn change
this.facesRef.push([this.points[0],this.points[1],this.points[2],this.points[3]]);
this.facesRef.push([this.points[1],this.points[5],this.points[6],this.points[2]]);
this.facesRef.push([this.points[4],this.points[5],this.points[6],this.points[7]]);
this.facesRef.push([this.points[4],this.points[7],this.points[0],this.points[3]]);
this.facesRef.push([this.points[4],this.points[5],this.points[0],this.points[1]]);
this.facesRef.push([this.points[7],this.points[6],this.points[2],this.points[3]]);
this.faces = JSON.parse(JSON.stringify(this.facesRef));
this.edges = [
this.getmid(0, 1), this.getmid(1, 2), this.getmid(2, 3), this.getmid(3, 0),
this.getmid(4, 5), this.getmid(5, 6), this.getmid(6, 7), this.getmid(7, 4),
this.getmid(0, 4), this.getmid(1, 5), this.getmid(2, 6), this.getmid(7, 3),
this.getpnt(0), this.getpnt(1), this.getpnt(2), this.getpnt(3),
this.getpnt(4), this.getpnt(5), this.getpnt(6), this.getpnt(7),
];
this.setup();
}
getpnt(n) {
return this.points[n].pos;
}
getmid(n1, n2) {
let v1 = this.points[n1].pos;
let v2 = this.points[n2].pos;
return createVector(
(v1.x + v2.x) / 2,
(v1.y + v2.y) / 2,
(v1.z + v2.z) / 2
);
}
getCubeState() {
let a = this.points[0].active;
let b = this.points[1].active;
let c = this.points[2].active;
let d = this.points[3].active;
let e = this.points[4].active;
let f = this.points[5].active;
let g = this.points[6].active;
let h = this.points[7].active;
return a * 1 + b * 2 + c * 4 + d * 8 + e * 16 + f * 32 + g * 64 + h * 128;
}
construct(state) {
this.vertices = []; // reset vertices
// get all concerned vertices from the triangle table
for (let edgeIndex of triangleTable[state]) {
if (edgeIndex >= 0) {
this.vertices.push(
createVector(
this.edges[edgeIndex].x,
this.edges[edgeIndex].y,
this.edges[edgeIndex].z
)
);
}
}
//store each triangle as three vertices
for (let tri = 0; tri < triangleTable[state].length; tri += 3) {
if (triangleTable[state][tri] == -1) break; // End of valid triangles
let v1 = createVector(
this.edges[triangleTable[state][tri]].x,
this.edges[triangleTable[state][tri]].y,
this.edges[triangleTable[state][tri]].z
);
let v2 = createVector(
this.edges[triangleTable[state][tri + 1]].x,
this.edges[triangleTable[state][tri + 1]].y,
this.edges[triangleTable[state][tri + 1]].z
);
let v3 = createVector(
this.edges[triangleTable[state][tri + 2]].x,
this.edges[triangleTable[state][tri + 2]].y,
this.edges[triangleTable[state][tri + 2]].z
);
this.vertices.push(v1, v2, v3); // This ensures that you're pushing triangles
}
this.constructBoundary();
}
constructBoundary() {
// 1 - enlever des faces les points qui ne sont pas activé
for (let i = 0; i < this.faces.length; i++) { // pour chaque face
for (let j = this.faces[i].length - 1; j >= 0; j--) { // pour chaque point de chaque face
if (this.faces[i][j].active == 0) { // si le point est desactivé
this.faces[i].splice(j, 1); //remove the point from the face
}
}
}
// 2 - Recuperer les points des surfaces ISO et enlever les dupes
// recuperer la liste de points et supprimer les doubles
// Create a unique string representation for each vector in this.vertices
let vectorStrings = this.vertices.map(
(vec) => `${vec.x},${vec.y},${vec.z}`
);
// Filter out duplicates
let filteredVertices = this.vertices.filter((vec, index) => {
const vecStr = `${vec.x},${vec.y},${vec.z}`;
return vectorStrings.indexOf(vecStr) === index;
});
// 3 - Ajouter les points de surfaces sur chaque face
for (let i = 0; i < this.facesRef.length; i++) { // pour chaque face de reference
for (let j = 0; j < filteredVertices.length; j++) { // pour chaque point
let a = this.facesRef[i][0].pos;
let b = this.facesRef[i][1].pos;
let c = this.facesRef[i][2].pos;
let p = createVector(filteredVertices[j].x,filteredVertices[j].y,filteredVertices[j].z);
if (isPointOnPlane(a, b, c, p)) {
let newPoint = new LPoint(filteredVertices[j].x,filteredVertices[j].y,filteredVertices[j].z,"",0);
this.faces[i].push(newPoint);
}
}
}
// 4 - construire les triangles de chaque face indépendamment
for (let face of this.faces) {
let triangles = triangulateFace(face);
this.boundary.push(triangles);
}
}
setup() {
let cubeState = this.getCubeState();
this.construct(cubeState);
}
draw(c) {
// Draw your transparent objects
strokeWeight(2);
// stroke(231,59,36)
stroke(255);
// noStroke();
fill(0, 50);
//construct each triangle
push();
rotateX(-0.2);
rotateY(millis() / 10000);
beginShape(TRIANGLES);
stroke(255);
for (let vertice of this.vertices) {
vertex(vertice.x, vertice.y, vertice.z);
}
endShape();
beginShape(TRIANGLES);
// BUILD BOUNDARY
// 5 - build the FUCKING TRIANGLES
for (let i = 0; i < this.boundary.length; i++) {
if (this.boundary[i] != -1) {
for (let j = 0; j < this.boundary[i].length; j++) {
for (let k = 0; k < this.boundary[i][j].length; k++) {
vertex(
this.boundary[i][j][k].x,
this.boundary[i][j][k].y,
this.boundary[i][j][k].z
);
}
}
}
}
endShape();
pop();
}
}
function isPointOnPlane(A, B, C, P) {
let AB = p5.Vector.sub(B, A);
let AC = p5.Vector.sub(C, A);
let AP = p5.Vector.sub(P, A);
// Compute the normal vector
let normal = AB.cross(AC);
// Check dot product
let dot = normal.dot(AP);
// Check if dot product is close to 0
let epsilon = 0.0001; // Adjust as necessary for precision
return Math.abs(dot) < epsilon;
}
/////////////////////////////// TRIANGULATION
function getProjectionAxes(normal) {
let majorAxis = createVector(
Math.abs(normal.x),
Math.abs(normal.y),
Math.abs(normal.z)
).array();
if (majorAxis[0] >= majorAxis[1] && majorAxis[0] >= majorAxis[2]) {
return ["y", "z"];
} else if (majorAxis[1] >= majorAxis[0] && majorAxis[1] >= majorAxis[2]) {
return ["x", "z"];
} else {
return ["x", "y"];
}
}
function triangulateFace(face) {
if (face.length >= 3) {
// Assuming you can calculate or provide the normal of the plane
let normal = calculateNormal(face); // You'd need to implement this if you don't have it
// Get axes to use for projection based on the plane's normal
let [axis1, axis2] = getProjectionAxes(normal);
// Project the 3D points of your custom class to 2D based on the determined axes
let projectedPoints = face.map((point) => [
point.pos[axis1],
point.pos[axis2],
]);
// Triangulate the 2D points
let delaunay = Delaunator.from(projectedPoints);
// console.log("Projected Points:", projectedPoints);
// console.log("Triangle Indices:", delaunay.triangles);
// Extract triangles
let triangleIndices = delaunay.triangles;
// Convert triangle indices to actual coordinates stored in your custom class
let triangles = [];
for (let i = 0; i < triangleIndices.length; i += 3) {
triangles.push([
face[triangleIndices[i]].pos,
face[triangleIndices[i + 1]].pos,
face[triangleIndices[i + 2]].pos,
]);
}
return triangles;
} else {
return -1;
}
}
function calculateNormal(face) {
let A = face[0].pos;
let B = face[1].pos;
let C = face[2].pos;
let AB = createVector(B.x - A.x, B.y - A.y, B.z - A.z);
let AC = createVector(C.x - A.x, C.y - A.y, C.z - A.z);
let normal = AB.cross(AC);
normal.normalize();
return normal;
}