diff --git a/README.md b/README.md
index 342e5a3..5057a4b 100644
--- a/README.md
+++ b/README.md
@@ -1,105 +1,17 @@
-# Project 6: Implicit surfaces - Marching cubes
-**Goal:** Implement an isosurface created from metaballs using the marching cubes algorithm.
+# Project 5: Metaballs
-Metaballs are organic-looking n-dimensional objects. We will be implementing a 3-dimensional metaballs. They are great to make bloppy shapes. An isosurface is created whenever the metaball function crosses a certain threshold, called isolevel. The metaball function describes the total influences of each metaball to a given points. A metaball influence is a function between its radius and distance to the point:
+https://nnewberg.github.io/Project6-MarchingCubes-Implicit-Surfaces/
-`f(point) = (radius * radius) / (distance * distance)`
+## Project Overview
-By summing up all these influences, you effectively describes all the points that are greater than the isolevel as inside, and less than the isolevel as outside (or vice versa). As an observation, the bigger the metaball's radius is, the bigger its influence is.
+I have implemented lit-sphere shaded metaballs : - )
-Marching cubes essentially voxelize the space, then generate triangles based on the density function distribution at the corners of each voxel. By increasing the voxelized grid's resolution, the surface eventually gets that blobby, organic look of the metaballs. Marching cubes can achieve a similar effect to ray marching for rendering implicit surfaces, but in addition to the rendered image, you also retain actual geometries.
+Try changing the number of metaballs to activate a happy accident bug.
+You can make cool glob shapes!
-Marching cubes are commonly used in MRI scanning, where you can generate geometries for the scans. Marching cubes are also used to generate complex terrains with caves in games. The additional geometry information can handily support collision and other physical calculation for game engines. For example, their bounding boxes can then be computed to construct the acceleration data structure for collisions.
+## Pics
-**Warning**: this assignment option requires more effort than the ray marching option. The two base codes diverge significantly, so switching options midway can be costly for your time and effort.
+
-## Resources
-We suggest reading the following resources before starting your assignment:
-
-- [Generating complex terrain](https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch01.html) from [GPU Gems 3](https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_pref01.html).
-- [Polygonising a scalar field](http://paulbourke.net/geometry/polygonise/) by Paul Bourke.
-- [Marching squares](http://jamie-wong.com/2014/08/19/metaballs-and-marching-squares/) by Jamie Wong.
-
-## Base code framework
-
-We have provided a basecode as a reference. You are welcome to modify the framework for your project. The basecode implements metaballs on the CPU.
-
-_main.js_:
-
- - `App`:
-
-This is a global configuration object. All information for the marching cubes are stored here.
-
-**Note**: `App.visualDebug` is a global control of all the visual debugging components. Even though it is helpful for development, it could be memory intensive. Toggle this flag off for better perforamance at high resolution.
-
-_marching_cubes.js_:
-
- - `class MarchingCubes`:
- This class encapsulates everything about the metaballs, grid, voxels, and sampling information.
-
- - `class Voxel`:
- This class contains information about a single voxel, and its sample points. Polygonization happens here.
-
-_inspect_point.js_:
-
- - `class InspectPoint`:
- This class simply contains a single sample point that can output its value on the screen at its pixel location.
-
-_metaball.js_:
-
- - `class Metaball`:
- This class represents a single metaball.
-
-_marching_cube_LUT.js_:
-
-This file contains the edge table and the triangle table for the marching cubes.
-
-## Animate metaballs (5 points)
-Implement the `update` for metaballs to move its position based velocity. Reverse the velocity whenever the metaball goes out of bounds. Since the metaball function is not well defined at the boundaries, maintain an additional small margin so that the metaball can reverse its moving direction before reaching the bounds.
-
-## Metaball function (2 points)
-Implement the metaball function inside `sample` of `MarchingCubes`. This function should return the total influences of all moving metaballs with respect to a given point.
-
-## Sampling at corners (15 points)
-In order to polygonize a voxel, generate new samples at each corner of the voxel. Their isovalues must be updated as the metaball function changes due of metaballs moving.
-
-## Polygonization (50 points)
-Implement `polygonize` inside `Cell` class. This function should return the list of **vertices** and **normals** of the triangles polygonized in the voxel.
-
-### Vertices (30 points out of 50)
-To compute the vertices, we have provided the look-up tables from Paul Bourke's. The table assumes the following indexing scheme:
-
-
-- _The eight corners can be represented as an 8-bit number, where 1 means the isovalue is above or below the isolevel based on your implementation._
-- _The twelve edges can be represented as a 12-bit number, where 1 means that the isosurface intersects with this edge._
-
-- **EDGE_TABLE**: This table returns a 12-bit number that represents the edges intersected by the isosurface. For each intersected edge, compute the linearly interpolated vertex position on the edge according to the isovalue at each end corner of the edge.
-
-- **TRI_TABLE**: This table acts as the triangle indices. Every 16 elements in the table represents a possible polygonizing configuration. Within each configuration, every three consecutive elements represents the indices of a triangle that should be created from the edges above.
-
-### Normals (20 points out of 50)
-Compute the normals using the gradient of the vertex with respect to the x, y, and z. The normals are then used for shading different materials.
-
-## Meshing (18 points)
-The mesh for the metaball's isosurface should be created once. At each frame, using the list of **vertices** and **normals** polygonized from the voxels, update the mesh's geometry for the isosurface. Notice that the total volume of the mesh does change.
-
-## Materials and post-processing (10 points)
-Interesting shader materials beyond just the provided threejs materials. We encourage using your previous shaders assignment for this part.
-
-## Extra credits (Up to 30 points)
-- Metaball can be positive or negative. A negative metaball will substract from the surface, which pushed the surface inward. **Implement a scene with both positive and negative metaballs. (10 points)**
-- **More implicit surfaces!** For example: planes, mesh, etc.). Some very interesting ideas are to blend your metaballs into those surfaces. **(5 points for each)**
-
-## Submission
-
-- Update `README.md` to contain a solid description of your project
-- Publish your project to gh-pages. `npm run deploy`. It should now be visible at http://username.github.io/repo-name
-- Create a [pull request](https://help.github.com/articles/creating-a-pull-request/) to this repository, and in the comment, include a link to your published project.
-- Submit the link to your pull request on Canvas.
-
-## Deploy
-- `npm run build`
-- Add and commit all changes
-- `npm run deploy`
-- If you're having problems with assets not linking correctly, make sure you wrap you're filepaths in `require()`. This will make the bundler package and your static assets as well. So, instead of `loadTexture('./images/thing.bmp')`, do `loadTexture(require('./images/thing.bmp'))`.
\ No newline at end of file
+
diff --git a/screenshots/Screen Shot 2017-03-02 at 7.07.39 PM.png b/screenshots/Screen Shot 2017-03-02 at 7.07.39 PM.png
new file mode 100644
index 0000000..99fb4b0
Binary files /dev/null and b/screenshots/Screen Shot 2017-03-02 at 7.07.39 PM.png differ
diff --git a/screenshots/Screen Shot 2017-03-02 at 7.07.52 PM.png b/screenshots/Screen Shot 2017-03-02 at 7.07.52 PM.png
new file mode 100644
index 0000000..1c85eca
Binary files /dev/null and b/screenshots/Screen Shot 2017-03-02 at 7.07.52 PM.png differ
diff --git a/screenshots/Screen Shot 2017-03-02 at 7.08.21 PM.png b/screenshots/Screen Shot 2017-03-02 at 7.08.21 PM.png
new file mode 100644
index 0000000..7683716
Binary files /dev/null and b/screenshots/Screen Shot 2017-03-02 at 7.08.21 PM.png differ
diff --git a/src/assets/sphere-textures/bluegreen.jpg b/src/assets/sphere-textures/bluegreen.jpg
new file mode 100644
index 0000000..4f2b643
Binary files /dev/null and b/src/assets/sphere-textures/bluegreen.jpg differ
diff --git a/src/assets/sphere-textures/bronze.jpg b/src/assets/sphere-textures/bronze.jpg
new file mode 100644
index 0000000..4af0390
Binary files /dev/null and b/src/assets/sphere-textures/bronze.jpg differ
diff --git a/src/assets/sphere-textures/chrome.jpg b/src/assets/sphere-textures/chrome.jpg
new file mode 100644
index 0000000..2e2cd68
Binary files /dev/null and b/src/assets/sphere-textures/chrome.jpg differ
diff --git a/src/assets/sphere-textures/colorwheel.png b/src/assets/sphere-textures/colorwheel.png
new file mode 100644
index 0000000..2d07967
Binary files /dev/null and b/src/assets/sphere-textures/colorwheel.png differ
diff --git a/src/assets/sphere-textures/red.jpg b/src/assets/sphere-textures/red.jpg
new file mode 100644
index 0000000..fd1499b
Binary files /dev/null and b/src/assets/sphere-textures/red.jpg differ
diff --git a/src/assets/sphere-textures/slime.jpg b/src/assets/sphere-textures/slime.jpg
new file mode 100644
index 0000000..dc27ef4
Binary files /dev/null and b/src/assets/sphere-textures/slime.jpg differ
diff --git a/src/framework.js b/src/framework.js
index aebfa7e..caa7e1f 100644
--- a/src/framework.js
+++ b/src/framework.js
@@ -29,7 +29,7 @@ function init(callback, update) {
var renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
- renderer.setClearColor(0x020202, 0);
+ renderer.setClearColor(0x000000, 1);
var controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
diff --git a/src/glsl/lit-sphere-frag.glsl b/src/glsl/lit-sphere-frag.glsl
new file mode 100644
index 0000000..7e89078
--- /dev/null
+++ b/src/glsl/lit-sphere-frag.glsl
@@ -0,0 +1,10 @@
+uniform sampler2D uSphereTexture;
+
+varying vec2 vNormal;
+
+void main() {
+
+ vec3 textureColor = texture2D( uSphereTexture, vNormal ).rgb;
+ gl_FragColor = vec4( textureColor, 1. );
+
+}
\ No newline at end of file
diff --git a/src/glsl/lit-sphere-vert.glsl b/src/glsl/lit-sphere-vert.glsl
new file mode 100644
index 0000000..d52558b
--- /dev/null
+++ b/src/glsl/lit-sphere-vert.glsl
@@ -0,0 +1,20 @@
+varying vec2 vNormal;
+
+void main(){
+
+ vec4 vertPos = vec4(position, 1.0);
+
+ vec3 eye = normalize(vec3(modelViewMatrix * vertPos));
+ vec3 screenNormal = normalize(normalMatrix * normal);
+
+ vec3 reflected= reflect(eye, screenNormal);
+ float m = 2.0 * sqrt(
+ pow( reflected.x, 2.0 ) +
+ pow( reflected.y, 2.0 ) +
+ pow( reflected.z + 1.0, 2.0 )
+ );
+ vNormal = reflected.xy/m + 0.50;
+
+ gl_Position = projectionMatrix * modelViewMatrix * vertPos;
+
+}
\ No newline at end of file
diff --git a/src/main.js b/src/main.js
index 29f2f30..ba15aa0 100644
--- a/src/main.js
+++ b/src/main.js
@@ -10,14 +10,14 @@ import Framework from './framework'
import LUT from './marching_cube_LUT.js'
import MarchingCubes from './marching_cubes.js'
-const DEFAULT_VISUAL_DEBUG = true;
+const DEFAULT_VISUAL_DEBUG = false;
const DEFAULT_ISO_LEVEL = 1.0;
-const DEFAULT_GRID_RES = 4;
+const DEFAULT_GRID_RES = 30;
const DEFAULT_GRID_WIDTH = 10;
const DEFAULT_NUM_METABALLS = 10;
const DEFAULT_MIN_RADIUS = 0.5;
-const DEFAULT_MAX_RADIUS = 1;
-const DEFAULT_MAX_SPEED = 0.01;
+const DEFAULT_MAX_RADIUS = 1.0;
+const DEFAULT_MAX_SPEED = 0.025;
var App = {
//
@@ -71,8 +71,8 @@ function onLoad(framework) {
App.camera = camera;
App.renderer = renderer;
- renderer.setClearColor( 0xbfd1e5 );
- scene.add(new THREE.AxisHelper(20));
+ renderer.setClearColor( 0x222222 );
+ // scene.add(new THREE.AxisHelper(20));
setupCamera(App.camera);
setupLights(App.scene);
@@ -90,7 +90,7 @@ function onUpdate(framework) {
function setupCamera(camera) {
// set camera position
- camera.position.set(5, 5, 30);
+ camera.position.set(10, 10, 15);
camera.lookAt(new THREE.Vector3(0,0,0));
}
@@ -131,29 +131,29 @@ function setupGUI(gui) {
// --- DEBUG ---
- var debugFolder = gui.addFolder('Debug');
- debugFolder.add(App.marchingCubes, 'showGrid').onChange(function(value) {
- App.marchingCubes.showGrid = value;
- if (value) {
- App.marchingCubes.show();
- } else {
- App.marchingCubes.hide();
- }
- });
-
- debugFolder.add(App.marchingCubes, 'showSpheres').onChange(function(value) {
- App.marchingCubes.showSpheres = value;
- if (value) {
- for (var i = 0; i < App.config.numMetaballs; i++) {
- App.marchingCubes.balls[i].show();
- }
- } else {
- for (var i = 0; i < App.config.numMetaballs; i++) {
- App.marchingCubes.balls[i].hide();
- }
- }
- });
- debugFolder.open();
+ // var debugFolder = gui.addFolder('Debug');
+ // debugFolder.add(App.marchingCubes, 'showGrid').onChange(function(value) {
+ // App.marchingCubes.showGrid = value;
+ // if (value) {
+ // App.marchingCubes.show();
+ // } else {
+ // App.marchingCubes.hide();
+ // }
+ // });
+
+// debugFolder.add(App.marchingCubes, 'showSpheres').onChange(function(value) {
+// App.marchingCubes.showSpheres = value;
+// if (value) {
+// for (var i = 0; i < App.config.numMetaballs; i++) {
+// App.marchingCubes.balls[i].show();
+// }
+// } else {
+// for (var i = 0; i < App.config.numMetaballs; i++) {
+// App.marchingCubes.balls[i].hide();
+// }
+// }
+// });
+// debugFolder.open();
}
// when the scene is done initializing, it will call onLoad, then on frame updates, call onUpdate
diff --git a/src/marching_cubes.js b/src/marching_cubes.js
index 505eb24..9336df2 100644
--- a/src/marching_cubes.js
+++ b/src/marching_cubes.js
@@ -58,6 +58,7 @@ export default class MarchingCubes {
this.setupCells();
this.setupMetaballs();
this.makeMesh();
+
};
// Convert from 1D index to 3D indices
@@ -143,12 +144,38 @@ export default class MarchingCubes {
// This function samples a point from the metaball's density function
// Implement a function that returns the value of the all metaballs influence to a given point.
// Please follow the resources given in the write-up for details.
+ influence(ball, point){
+ var rSquared = Math.pow(ball.radius, 2.0);
+ var xDiffSquared = Math.pow(point.x - ball.pos.x, 2.0);
+ var yDiffSquared = Math.pow(point.y - ball.pos.y, 2.0);
+ var zDiffSquared = Math.pow(point.z - ball.pos.z, 2.0);
+ return (rSquared/(xDiffSquared + yDiffSquared + zDiffSquared));
+ };
+
sample(point) {
// @TODO
- var isovalue = 1.1;
+ var isovalue = 0.0;
+
+ // var i = this.influence(this.balls[0], point);
+
+ for (var i = 0; i < this.balls.length; i++){
+ isovalue += this.influence(this.balls[i], point);
+ }
+
+ // isovalue = 1.1;
+
return isovalue;
}
+ averageIso(voxel){
+ var sum =
+ voxel.v1.isovalue + voxel.v2.isovalue
+ + voxel.v3.isovalue + voxel.v4.isovalue
+ + voxel.v5.isovalue + voxel.v6.isovalue
+ + voxel.v7.isovalue + voxel.v8.isovalue;
+ return sum/8.0;
+ }
+
update() {
if (this.isPaused) {
@@ -164,22 +191,53 @@ export default class MarchingCubes {
// Sampling the center point
this.voxels[c].center.isovalue = this.sample(this.voxels[c].center.pos);
+ //Sampling the corner points
+ this.voxels[c].v1.isovalue = this.sample(this.voxels[c].v1.pos);
+ this.voxels[c].v2.isovalue = this.sample(this.voxels[c].v2.pos);
+ this.voxels[c].v3.isovalue = this.sample(this.voxels[c].v3.pos);
+ this.voxels[c].v4.isovalue = this.sample(this.voxels[c].v4.pos);
+ this.voxels[c].v5.isovalue = this.sample(this.voxels[c].v5.pos);
+ this.voxels[c].v6.isovalue = this.sample(this.voxels[c].v6.pos);
+ this.voxels[c].v7.isovalue = this.sample(this.voxels[c].v7.pos);
+ this.voxels[c].v8.isovalue = this.sample(this.voxels[c].v8.pos);
// Visualizing grid
if (VISUAL_DEBUG && this.showGrid) {
// Toggle voxels on or off
+ // if (this.averageIso(this.voxels[c]) > this.isolevel) {
if (this.voxels[c].center.isovalue > this.isolevel) {
this.voxels[c].show();
} else {
this.voxels[c].hide();
}
- this.voxels[c].center.updateLabel(this.camera);
+ // this.voxels[c].center.updateLabel(this.camera);
+ this.voxels[c].v1.updateLabel(this.camera);
+ this.voxels[c].v2.updateLabel(this.camera);
+ this.voxels[c].v3.updateLabel(this.camera);
+ this.voxels[c].v4.updateLabel(this.camera);
+ this.voxels[c].v5.updateLabel(this.camera);
+ this.voxels[c].v6.updateLabel(this.camera);
+ this.voxels[c].v7.updateLabel(this.camera);
+ this.voxels[c].v8.updateLabel(this.camera);
+
+
} else {
this.voxels[c].center.clearLabel();
+ this.voxels[c].v1.clearLabel();
+ this.voxels[c].v2.clearLabel();
+ this.voxels[c].v3.clearLabel();
+ this.voxels[c].v4.clearLabel();
+ this.voxels[c].v5.clearLabel();
+ this.voxels[c].v6.clearLabel();
+ this.voxels[c].v7.clearLabel();
+ this.voxels[c].v8.clearLabel();
+
}
+
}
+
this.updateMesh();
}
@@ -206,11 +264,71 @@ export default class MarchingCubes {
};
makeMesh() {
- // @TODO
+
+ var geometry = new THREE.Geometry();
+
+ var sphereTexture = THREE.ImageUtils.loadTexture('src/assets/sphere-textures/red.jpg');
+
+ var material = new THREE.ShaderMaterial({
+ uniforms: {
+ uSphereTexture: {
+ type: "t",
+ value: sphereTexture },
+ },
+ vertexShader: require('./glsl/lit-sphere-vert.glsl'),
+ fragmentShader: require('./glsl/lit-sphere-frag.glsl')
+ })
+
+ this.metaballsMesh = new THREE.Mesh(geometry, material);
+
+ this.scene.add(this.metaballsMesh);
+
}
updateMesh() {
- // @TODO
+
+ this.metaballsMesh.geometry.vertices = [];
+ this.metaballsMesh.geometry.faces = [];
+
+ var triCount = 0;
+
+ for (var i = 0; i < this.res3; i++){
+
+ var voxelPolygonMap = this.voxels[i].polygonize(this.isolevel);
+
+ if (voxelPolygonMap != 0){
+ var voxelVertices = voxelPolygonMap['vertPositions'];
+ var voxelNormals = voxelPolygonMap['vertNormals'];
+
+ // console.log(voxelVertices);
+ // console.log(voxelNormals);
+
+ for (var v = 0; v < voxelVertices.length; v+= 3){
+
+ this.metaballsMesh.geometry.vertices.push(voxelVertices[v]);
+ this.metaballsMesh.geometry.vertices.push(voxelVertices[v + 1]);
+ this.metaballsMesh.geometry.vertices.push(voxelVertices[v + 2]);
+
+ var face = new THREE.Face3(v + triCount*3, v+1 + triCount*3, v+2 + triCount*3,
+ [voxelNormals[v], voxelNormals[v+1], voxelNormals[v+2]]);
+
+ this.metaballsMesh.geometry.faces.push(face);
+
+ }
+
+ triCount+= voxelVertices.length/3;
+
+ }
+
+
+
+ }
+
+
+ this.metaballsMesh.geometry.verticesNeedUpdate = true;
+ this.metaballsMesh.geometry.elementsNeedUpdate = true;
+
+
}
};
@@ -282,7 +400,50 @@ class Voxel {
var red = 0xff0000;
// Center dot
- this.center = new InspectPoint(new THREE.Vector3(x, y, z), 0, VISUAL_DEBUG);
+ this.center = new InspectPoint(new THREE.Vector3(x, y, z), 0, VISUAL_DEBUG);
+
+ //Create labels at corners
+ //See http://mathstat.slu.edu/escher/upload/thumb/6/69/Cube-labeled.svg/300px-Cube-labeled.svg.png
+ var v1x = x - halfGridCellWidth;
+ var v1y = y + halfGridCellWidth;
+ var v1z = z - halfGridCellWidth;
+ this.v1 = new InspectPoint(new THREE.Vector3(v1x, v1y, v1z), 0, VISUAL_DEBUG);
+
+ var v2x = v1x;
+ var v2y = v1y;
+ var v2z = z + halfGridCellWidth;
+ this.v2 = new InspectPoint(new THREE.Vector3(v2x, v2y, v2z), 0, VISUAL_DEBUG);
+
+ var v3x = x + halfGridCellWidth;
+ var v3y = v2y;
+ var v3z = v2z;
+ this.v3 = new InspectPoint(new THREE.Vector3(v3x, v3y, v3z), 0, VISUAL_DEBUG);
+
+ var v4x = v3x;
+ var v4y = v3y;
+ var v4z = v1z;
+ this.v4 = new InspectPoint(new THREE.Vector3(v4x, v4y, v4z), 0, VISUAL_DEBUG);
+
+ var v5x = v1x;
+ var v5y = y - halfGridCellWidth;
+ var v5z = v1z;
+ this.v5 = new InspectPoint(new THREE.Vector3(v5x, v5y, v5z), 0, VISUAL_DEBUG);
+
+ var v6x = v5x;
+ var v6y = v5y;
+ var v6z = v2z;
+ this.v6 = new InspectPoint(new THREE.Vector3(v6x, v6y, v6z), 0, VISUAL_DEBUG);
+
+ var v7x = v3x;
+ var v7y = v6y;
+ var v7z = v6z;
+ this.v7 = new InspectPoint(new THREE.Vector3(v7x, v7y, v7z), 0, VISUAL_DEBUG);
+
+ var v8x = v7x;
+ var v8y = v7y;
+ var v8z = v4z;
+ this.v8 = new InspectPoint(new THREE.Vector3(v8x, v8y, v8z), 0, VISUAL_DEBUG);
+
}
show() {
@@ -306,21 +467,167 @@ class Voxel {
if (this.center) {
this.center.clearLabel();
}
+
+ if (this.v1){
+ this.v1.clearLabel();
+ }
+
+ if(this.v2){
+ this.v2.clearLabel();
+ }
+
+ if(this.v3){
+ this.v3.clearLabel();
+ }
+
+ if(this.v4){
+ this.v4.clearLabel();
+ }
+
+ if(this.v5){
+ this.v5.clearLabel();
+ }
+
+ if(this.v6){
+ this.v6.clearLabel();
+ }
+
+ if(this.v7){
+ this.v7.clearLabel();
+ }
+
+ if(this.v8){
+ this.v8.clearLabel();
+ }
}
- vertexInterpolation(isolevel, posA, posB) {
+ vertexInterpolation(isolevel, voxelA, voxelB) {
+
+ //@TODO
+ var mu;
+ var lerpPos = new THREE.Vector3();
+
+ if (Math.abs(isolevel - voxelA.isovalue) < 0.00001)
+ return voxelA.pos;
+ if (Math.abs(isolevel - voxelB.isovalue) < 0.00001)
+ return voxelB.pos;
+ if (Math.abs(voxelA.isovalue - voxelB.isovalue) < 0.00001)
+ return voxelA.pos;
+
+ mu = (isolevel - voxelA.isovalue) / (voxelB.isovalue - voxelA.isovalue);
+
+ lerpPos.x = voxelA.pos.x + mu * (voxelB.pos.x - voxelA.pos.x);
+ lerpPos.y = voxelA.pos.y + mu * (voxelB.pos.y - voxelA.pos.y);
+ lerpPos.z = voxelA.pos.z + mu * (voxelB.pos.z - voxelA.pos.z);
+
+ return lerpPos;
- // @TODO
- var lerpPos;
- return lerpPos;
}
polygonize(isolevel) {
// @TODO
+
var vertexList = [];
var normalList = [];
+ // var edgeTable = LUT.EDGE_TABLE;
+ // var triTable = LUT.TRI_TABLE;
+
+
+ /*
+ Determine the index into the edge table which
+ tells us which vertices are inside of the surface
+ */
+ //WARNING: might have to re-name voxel vertices to match Paul's figure
+ var cubeindex = 0;
+ //TODO: rename this shit to follow him
+ var v0 = this.v6;
+ var v1 = this.v7;
+ var v2 = this.v8;
+ var v3 = this.v5;
+ var v4 = this.v2;
+ var v5 = this.v3;
+ var v6 = this.v4;
+ var v7 = this.v1;
+
+ if (v0.isovalue < isolevel) cubeindex |= 1;
+ if (v1.isovalue < isolevel) cubeindex |= 2;
+ if (v2.isovalue < isolevel) cubeindex |= 4;
+ if (v3.isovalue < isolevel) cubeindex |= 8;
+ if (v4.isovalue < isolevel) cubeindex |= 16;
+ if (v5.isovalue < isolevel) cubeindex |= 32;
+ if (v6.isovalue < isolevel) cubeindex |= 64;
+ if (v7.isovalue < isolevel) cubeindex |= 128;
+
+ /* Cube is entirely in/out of the surface */
+ if (LUT.EDGE_TABLE[cubeindex] == 0)
+ return(0);
+
+ /* Find the vertices where the surface intersects the cube */
+ if (LUT.EDGE_TABLE[cubeindex] & 1)
+ vertexList[0] =
+ this.vertexInterpolation(isolevel,v0,v1);
+ if (LUT.EDGE_TABLE[cubeindex] & 2)
+ vertexList[1] =
+ this.vertexInterpolation(isolevel,v1,v2);
+ if (LUT.EDGE_TABLE[cubeindex] & 4)
+ vertexList[2] =
+ this.vertexInterpolation(isolevel,v2,v3);
+ if (LUT.EDGE_TABLE[cubeindex] & 8)
+ vertexList[3] =
+ this.vertexInterpolation(isolevel,v3,v0);
+ if (LUT.EDGE_TABLE[cubeindex] & 16)
+ vertexList[4] =
+ this.vertexInterpolation(isolevel,v4,v5);
+ if (LUT.EDGE_TABLE[cubeindex] & 32)
+ vertexList[5] =
+ this.vertexInterpolation(isolevel,v5,v6);
+ if (LUT.EDGE_TABLE[cubeindex] & 64)
+ vertexList[6] =
+ this.vertexInterpolation(isolevel,v6,v7);
+ if (LUT.EDGE_TABLE[cubeindex] & 128)
+ vertexList[7] =
+ this.vertexInterpolation(isolevel,v7,v4);
+ if (LUT.EDGE_TABLE[cubeindex] & 256)
+ vertexList[8] =
+ this.vertexInterpolation(isolevel,v0,v4);
+ if (LUT.EDGE_TABLE[cubeindex] & 512)
+ vertexList[9] =
+ this.vertexInterpolation(isolevel,v1,v5);
+ if (LUT.EDGE_TABLE[cubeindex] & 1024)
+ vertexList[10] =
+ this.vertexInterpolation(isolevel,v2,v6);
+ if (LUT.EDGE_TABLE[cubeindex] & 2048)
+ vertexList[11] =
+ this.vertexInterpolation(isolevel,v3,v7);
+
+ /* Create the triangle */
+ var vertPositions = [];
+ var vertNormals = [];
+
+ // console.log(cubeindex);
+
+ for (var i = 0; LUT.TRI_TABLE[cubeindex * 16 + i]!= -1; i+=3) {
+ var triV0 = vertexList[LUT.TRI_TABLE[cubeindex * 16 + i ]];
+ var triV1 = vertexList[LUT.TRI_TABLE[cubeindex * 16 + i + 1]];
+ var triV2 = vertexList[LUT.TRI_TABLE[cubeindex * 16 + i + 2]];
+ vertPositions.push(triV0);
+ vertPositions.push(triV1);
+ vertPositions.push(triV2);
+
+ //calc cross product for normal
+ var e10 = triV1.clone().sub(triV0);
+ var e21 = triV2.clone().sub(triV1);
+ var normal = e10.cross(e21);
+ vertNormals.push(normal);
+ vertNormals.push(normal);
+ vertNormals.push(normal);
+ }
+
+
+ // console.log(vertPositions.length == vertNormals.length);
+
return {
vertPositions: vertPositions,
vertNormals: vertNormals
diff --git a/src/metaball.js b/src/metaball.js
index 6a057bc..79d373a 100644
--- a/src/metaball.js
+++ b/src/metaball.js
@@ -2,24 +2,33 @@ const THREE = require('three')
var SPHERE_GEO = new THREE.SphereBufferGeometry(1, 32, 32);
var LAMBERT_WHITE = new THREE.MeshLambertMaterial( { color: 0x9EB3D8, transparent: true, opacity: 0.5 });
+var clock;
export default class Metaball {
constructor(pos, radius, vel, gridWidth, visualDebug) {
this.init(pos, radius, vel, gridWidth, visualDebug);
+ clock = new THREE.Clock();
}
init(pos, radius, vel, gridWidth, visualDebug) {
this.gridWidth = gridWidth;
this.pos = pos;
+
+ //start position for boundary calc
+ this.startPos = this.pos.clone();
+
this.vel = vel;
+ // console.log(this.pos);
+
this.radius = radius;
this.radius2 = radius * radius;
this.mesh = null;
+ this.makeMesh();
- if (visualDebug) {
- this.makeMesh();
- }
+ // if (visualDebug) {
+ // this.makeMesh();
+ // }
}
makeMesh() {
@@ -42,5 +51,16 @@ export default class Metaball {
update() {
// @TODO
+ var padding = this.radius * 1.2;
+
+ //reverse velocity if outside radius from center
+ if (Math.abs(this.startPos.distanceTo(this.pos)) > (this.gridWidth/2.0 - padding)){
+ this.vel.multiplyScalar(-1.0);
+ }
+
+
+ var newPos = this.pos.add(this.vel);;
+ // this.pos.add(v);
+ this.mesh.position.set(newPos.x, newPos.y, newPos.z);
}
}
\ No newline at end of file