Skip to content

Instantly share code, notes, and snippets.

@dandavison
Created February 11, 2013 04:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dandavison/4752751 to your computer and use it in GitHub Desktop.
Save dandavison/4752751 to your computer and use it in GitHub Desktop.
width = 500
height = 300
cube =
nodes: [
{x: 0, y: 0, z:0},
{x: 0, y: 0, z:1},
{x: 0, y: 1, z:0},
{x: 0, y: 1, z:1},
{x: 1, y: 0, z:0},
{x: 1, y: 0, z:1},
{x: 1, y: 1, z:0},
{x: 1, y: 1, z:1},
]
faces: [
[0, 1, 3, 2, 0],
[0, 1, 5, 4, 0],
[4, 5, 7, 6, 4],
[6, 7, 3, 2, 6],
[0, 2, 6, 4, 0],
[1, 3, 7, 5, 1],
]
setupThree = ->
renderer = new THREE.WebGLRenderer(antialias: true)
renderer.setSize(width, height)
camera = new THREE.PerspectiveCamera(90, width / height, 1, 10000)
scene = new THREE.Scene()
focus = new THREE.Vector3(0.5, 0.5, 0.5) # cube center
camera.position = new THREE.Vector3(0.5, 0.5, 2) # looking down from above initially
[renderer, scene, camera, focus]
[renderer, scene, camera, focus] = setupThree()
project = (x, y, z) ->
camera.lookAt(focus)
renderer.render(scene, camera)
point = new THREE.Vector3(x, y, z)
projScreenMat = new THREE.Matrix4()
projScreenMat.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse)
point.applyMatrix4(projScreenMat)
x = d3.scale.linear()
.domain([-1, 1])
.range([0, width])
y = d3.scale.linear()
.domain([-1, 1])
.range([0, height])
area = d3.svg.area()
face_colors = ["#F0F9E8", "#CCEBC5", "#A8DDB5", "#7BCCC4", "#43A2CA", "#0868AC"]
for face in cube.faces
face.key = face.join('-')
render = (init=false) ->
nodes = (project(point.x, point.y, point.z) for point in cube.nodes)
face_data = []
for node_indices in cube.faces
face = ([x(nodes[i].x), y(nodes[i].y)] for i in node_indices)
face.key = node_indices.join('-')
face.zmax = d3.max(nodes[i].z for i in node_indices)
face_data.push(face)
faces = svg.selectAll("path.face")
# The DOM elements are reordered by z-level on each render
# event, so a data join key is required.
.data(face_data, (f) -> f.key)
.sort((f1, f2) ->
d3.ascending(f1.zmax, f2.zmax))
.attr("d", (f) -> area(f))
if init
faces.enter()
.append("path")
.attr("class", "face")
.attr("fill", (d, i) -> face_colors[i])
# How to avoid repeating this for update and enter selections?
.attr("d", (f) -> area(f))
svg = d3.select("#cube")
.append("svg")
.attr("width", width)
.attr("height", height)
slider =
x: '#x-slider'
y: '#y-slider'
z: '#z-slider'
for dim in ['x', 'y', 'z']
$(slider[dim]).slider({
min: -2.0,
max: 2.0,
step: 0.01
value: camera.position[dim]
slide: do (dim) -> (event, ui) ->
camera.position[dim] = ui.value
render()
}).width(500)
render(init=true)
// Generated by CoffeeScript 1.4.0
(function() {
var area, camera, cube, dim, face, face_colors, focus, height, init, project, render, renderer, scene, setupThree, slider, svg, width, x, y, _i, _j, _len, _len1, _ref, _ref1, _ref2;
width = 500;
height = 300;
cube = {
nodes: [
{
x: 0,
y: 0,
z: 0
}, {
x: 0,
y: 0,
z: 1
}, {
x: 0,
y: 1,
z: 0
}, {
x: 0,
y: 1,
z: 1
}, {
x: 1,
y: 0,
z: 0
}, {
x: 1,
y: 0,
z: 1
}, {
x: 1,
y: 1,
z: 0
}, {
x: 1,
y: 1,
z: 1
}
],
faces: [[0, 1, 3, 2, 0], [0, 1, 5, 4, 0], [4, 5, 7, 6, 4], [6, 7, 3, 2, 6], [0, 2, 6, 4, 0], [1, 3, 7, 5, 1]]
};
setupThree = function() {
var camera, focus, renderer, scene;
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(width, height);
camera = new THREE.PerspectiveCamera(90, width / height, 1, 10000);
scene = new THREE.Scene();
focus = new THREE.Vector3(0.5, 0.5, 0.5);
camera.position = new THREE.Vector3(0.5, 0.5, 2);
return [renderer, scene, camera, focus];
};
_ref = setupThree(), renderer = _ref[0], scene = _ref[1], camera = _ref[2], focus = _ref[3];
project = function(x, y, z) {
var point, projScreenMat;
camera.lookAt(focus);
renderer.render(scene, camera);
point = new THREE.Vector3(x, y, z);
projScreenMat = new THREE.Matrix4();
projScreenMat.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
return point.applyMatrix4(projScreenMat);
};
x = d3.scale.linear().domain([-1, 1]).range([0, width]);
y = d3.scale.linear().domain([-1, 1]).range([0, height]);
area = d3.svg.area();
face_colors = ["#F0F9E8", "#CCEBC5", "#A8DDB5", "#7BCCC4", "#43A2CA", "#0868AC"];
_ref1 = cube.faces;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
face = _ref1[_i];
face.key = face.join('-');
}
render = function(init) {
var face_data, faces, i, node_indices, nodes, point, _j, _len1, _ref2;
if (init == null) {
init = false;
}
nodes = (function() {
var _j, _len1, _ref2, _results;
_ref2 = cube.nodes;
_results = [];
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
point = _ref2[_j];
_results.push(project(point.x, point.y, point.z));
}
return _results;
})();
face_data = [];
_ref2 = cube.faces;
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
node_indices = _ref2[_j];
face = (function() {
var _k, _len2, _results;
_results = [];
for (_k = 0, _len2 = node_indices.length; _k < _len2; _k++) {
i = node_indices[_k];
_results.push([x(nodes[i].x), y(nodes[i].y)]);
}
return _results;
})();
face.key = node_indices.join('-');
face.zmax = d3.max((function() {
var _k, _len2, _results;
_results = [];
for (_k = 0, _len2 = node_indices.length; _k < _len2; _k++) {
i = node_indices[_k];
_results.push(nodes[i].z);
}
return _results;
})());
face_data.push(face);
}
faces = svg.selectAll("path.face").data(face_data, function(f) {
return f.key;
}).sort(function(f1, f2) {
return d3.ascending(f1.zmax, f2.zmax);
}).attr("d", function(f) {
return area(f);
});
if (init) {
return faces.enter().append("path").attr("class", "face").attr("fill", function(d, i) {
return face_colors[i];
}).attr("d", function(f) {
return area(f);
});
}
};
svg = d3.select("#cube").append("svg").attr("width", width).attr("height", height);
slider = {
x: '#x-slider',
y: '#y-slider',
z: '#z-slider'
};
_ref2 = ['x', 'y', 'z'];
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
dim = _ref2[_j];
$(slider[dim]).slider({
min: -2.0,
max: 2.0,
step: 0.01,
value: camera.position[dim],
slide: (function(dim) {
return function(event, ui) {
camera.position[dim] = ui.value;
return render();
};
})(dim)
}).width(500);
}
render(init = true);
}).call(this);
<!DOCTYPE html>
<meta charset="utf-8">
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.0/themes/base/jquery-ui.css" type="text/css" />
<style>
svg {
padding: 20px;
}
line {
stroke: black;
}
</style>
<body>
<div id="cube"></div>
<div id="camera-sliders">
<p>Camera position:</p>
<p> X <div id="x-slider"></div> </p>
<p> Y <div id="y-slider"></div> </p>
<p> Z <div id="z-slider"></div> </p>
</div>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.0/jquery-ui.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/three.js/r55/three.min.js"></script>
<script src="cube.js"></script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment