top of page
Search
cedarcantab

Marching Cube

Grid Class



class GRIDCELL {
  constructor(f, origin, scale) {
    this.pos = new Vector3(); // "position" of the cube
    this.f = f;
    this.origin = origin;
    this.scale = scale;
    this.cubeIndex = 0;
    this.val = new Array(8);
    this.p = [
      new Vector3(0,0,0).multiply(this.scale),
      new Vector3(1,0,0).multiply(this.scale),
      new Vector3(1,0,1).multiply(this.scale),
      new Vector3(0,0,1).multiply(this.scale),
      new Vector3(0,1,0).multiply(this.scale),
      new Vector3(1,1,0).multiply(this.scale),
      new Vector3(1,1,1).multiply(this.scale),
      new Vector3(0,1,1).multiply(this.scale)
    ]
   
  }
  
  march(i, j, k, isoLevel = 0) {   

    let origin = this.origin, scale = this.scale;
    
    this.cubeIndex = 0; // reset cube index to zero
    
    for (let v = 0; v<8; v++) {
      // calculate the scalar value at the corner
      let p = this.p[v]; // offset to get the relevant vertex
      let s = this.f(
        scale.x * i + p.x + origin.x, 
        scale.y * j + p.y + origin.y, 
        scale.z * k + p.z + origin.z
      );
      this.val[v] = s;
  
      // calculate the index into the triangulation table
      this.cubeIndex |= (s < isoLevel) ? (1 << v) : 0;
    }
   
    this.pos.set(scale.x * i + origin.x, scale.y * j + origin.y, scale.z * k + origin.z); // *position* of cube
    
  }
 
}


Polygonize!




function polygonise(f, isoLevel, _size, _bounds) {
  
  let size = _size; // this is the resolution (ie how many points to sample)
  let bounds = _bounds; // define the bounds of the shape
  let scale = bounds[1].clone().subtract(bounds[0]).divide(size);
  let origin = bounds[0]; // when calculated scalar values, "shift" the "grid coordinate" by this to get to x,y,z for calculation
  let grid = new GRIDCELL(f, origin, scale); // create cube to march!
 
  let vertices = [];
  let indices = [];
  let edges = new Array(12); // working array to temporarily hold the intersecting edges
 
  let vertList = Array.from(Array(12), ()=>new Vector3());
  
  for (let i =0; i < size.x-1; i++) {
    for (let j = 0; j < size.y-1; j++) {
      for (let k = 0; k < size.z-1; k++) {
        // for the indiviual marching cube, get the index into the triangulation table    
        grid.march(i, j, k, isoLevel);
        let cubeIndex = grid.cubeIndex;
        
         //Compute vertices
    
        if(edgeTable[cubeIndex] === 0)  continue;
        
        let pos = grid.pos;
        
        for (let i = 0; i < 12; i++) {

          if((edgeTable[cubeIndex] & (1<<i)) === 0)  continue; // if the edge is not intersecting, no need to compute the intersecting point
          edges[i] = vertices.length/3; // 3 vertices for a triangle, so length of the vertices array / 3 gives the index into the face
          
          let e = edgeIndex[i]; // e holds an array which holds the start and ending vertex indices of edge i
          let eStart = e[0], eEnd = e[1]; // the ending and starting vertex index of an edge 
          let ix = vertexInterp(isoLevel, grid.p[eStart], grid.p[eEnd], grid.val[eStart], grid.val[eEnd]).add(pos)
          vertices.push(ix.x, ix.y, ix.z)
        
        }
        //Add vertex indices for intersecting faces        
        let f = triTable[cubeIndex]; // f holds the sequence of intersecting edges to be joined together to form the intersecting faces
        for (let i = 0; f[i] !== -1; i+=3)	{       
           indices.push(edges[f[i]], edges[f[i+1]], edges[f[i+2]]);
         }
      }
    }
  }
  
  return {verts: vertices, indices: indices}  

}


CodePen


Example using



// Goursat Surface
 let f3 =  function(x,y,z) {
   return Math.pow(x,4) + Math.pow(y,4) + Math.pow(z,4) - 1.5 * (x*x  + y*y + z*z) + 1;
 }



Useful References



1 view0 comments

Recent Posts

See All

p2 naive broadphase

var Broadphase = require('../collision/Broadphase'); module.exports = NaiveBroadphase; /** * Naive broadphase implementation. Does N^2...

sopiro motor constranit

import { Matrix2, Vector2 } from "./math.js"; import { RigidBody } from "./rigidbody.js"; import { Settings } from "./settings.js";...

Comments


記事: Blog2_Post
bottom of page