Skip to content

Instantly share code, notes, and snippets.

@Bolloxim
Created August 15, 2014 09:35
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 Bolloxim/583cac231d1edd95e8f4 to your computer and use it in GitHub Desktop.
Save Bolloxim/583cac231d1edd95e8f4 to your computer and use it in GitHub Desktop.
A Pen by Andi Smithers.
<body>
<canvas id='uniform distribution''></canvas>
</body>

Random Normal

I call this Random Normal as it effectively generates randomized unit vectors uniformly distributed.

Instead of using x = random(2)-1, y = random(2)-1, z = random(2)-1 then normalized.. which is rather poor in many reasons.

We compute the euler angles for theta and phi. It works on a nice property of arc-cos which is a uniform distribution of the 'y' axis just by using -1 to 1.

as you can see by the rotating sphere.. no polar bias. lovely.

A Pen by Andi Smithers on CodePen.

License.

// constant options
const focalDepth = 80;
const focalPoint = 256;
// variables
var centreX;
var centreY;
var mouseX;
var mouseY;
var spawnX;
var spawnY;
var frameCount=0;
// variables
const maxpoints = 4096;
var pointcloud = [];
// uniform distribution of a randomized unit vector
function RandomNormal()
{
var theta = Math.random() * Math.PI * 2;
var nz = 1 - 2*Math.random();
var phi = Math.acos(nz);
var nx = Math.sin(theta)*Math.sin(phi);
var ny = Math.cos(theta)*Math.sin(phi);
return {x:nx, y:ny, z:nz};
}
function InitRandomDistribution()
{
for (var i=0; i<maxpoints;i++)
{
pointcloud.push(RandomNormal());
}
}
var theta = 0;
var phi = 0;
function RenderRandomDistribution()
{
theta+=0.01;
phi+=0.01;
var scale = 20* canvas.height/500;
context.beginPath();
for (var i=0; i<pointcloud.length; i++)
{
var point = pointcloud[i];
var x1 = point.x * Math.cos(theta) - point.z*Math.sin(theta);
var z1 = point.x * Math.sin(theta) + point.z*Math.cos(theta);
var y1 = point.y * Math.cos(phi) - z1*Math.sin(phi);
var z1 = point.y * Math.sin(phi) + z1*Math.cos(phi);
x1*=scale;
z1*=scale;
y1*=scale;
if (z1+focalDepth<0) continue;
var depth = focalPoint*3 / (z1 + focalDepth );
var x = x1 * depth + centreX;
var y = y1 * depth + centreY;
var sz = depth * 0.2;
// fill a rect
context.rect(x,y, sz, sz);
}
context.fillStyle = '#ffffff';
context.fill();
}
// initialization
function init()
{
// setup canvas and context
canvas = document.getElementById('uniform distribution');
context = canvas.getContext('2d');
// set canvas to be window dimensions
resize();
// create event listeners
canvas.addEventListener('mousemove', mouseMove);
canvas.addEventListener('click', mouseClick);
window.addEventListener('resize', resize);
// initialze variables
InitRandomDistribution();
}
// input functions
function mouseMove(event)
{
var rect = canvas.getBoundingClientRect();
mouseX = event.clientX - rect.left,
mouseY = event.clientY - rect.top
}
function mouseClick()
{
}
function resize()
{
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// compute centre of screen
centreX = canvas.width/2;
centreY = canvas.height/2;
}
// rendering functions
function render()
{
context.fillStyle = 'black';
context.clearRect(0, 0, canvas.width, canvas.height);
RenderRandomDistribution();
context.globalAlpha = 1.0;
context.font = '20pt Calibri';
context.fillStyle = 'rgb(255,255,0)';
context.textAlign = "center";
context.fillText('Random Normal', canvas.width/2, 25);
context.fillText('Or randomized unit vector with a uniform distribution', canvas.width/2, 45);
context.fillText('alternatively, even distribution of points on a the surface of a sphere', canvas.width/2, canvas.height-25);
}
// movement functions
function update()
{
}
// per frame tick functions
function animate()
{
frameCount++;
// movement update
update();
// render update
render();
// trigger next frame
requestAnimationFrame(animate);
}
// entry point
init();
animate();</script>
body{
background: #000000;
margin: 0px;
padding: 0px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment