Skip to content

Instantly share code, notes, and snippets.

@jbenet
Created June 2, 2012 01:28
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 jbenet/2856073 to your computer and use it in GitHub Desktop.
Save jbenet/2856073 to your computer and use it in GitHub Desktop.
Remember your e50
CanvasMatrix4=function(m){if(typeof m=='object'){if("length"in m&&m.length>=16){this.load(m[0],m[1],m[2],m[3],m[4],m[5],m[6],m[7],m[8],m[9],m[10],m[11],m[12],m[13],m[14],m[15]);return}else if(m instanceof CanvasMatrix4){this.load(m);return}}this.makeIdentity()};CanvasMatrix4.prototype.load=function(){if(arguments.length==1&&typeof arguments[0]=='object'){var matrix=arguments[0];if("length"in matrix&&matrix.length==16){this.m11=matrix[0];this.m12=matrix[1];this.m13=matrix[2];this.m14=matrix[3];this.m21=matrix[4];this.m22=matrix[5];this.m23=matrix[6];this.m24=matrix[7];this.m31=matrix[8];this.m32=matrix[9];this.m33=matrix[10];this.m34=matrix[11];this.m41=matrix[12];this.m42=matrix[13];this.m43=matrix[14];this.m44=matrix[15];return}if(arguments[0]instanceof CanvasMatrix4){this.m11=matrix.m11;this.m12=matrix.m12;this.m13=matrix.m13;this.m14=matrix.m14;this.m21=matrix.m21;this.m22=matrix.m22;this.m23=matrix.m23;this.m24=matrix.m24;this.m31=matrix.m31;this.m32=matrix.m32;this.m33=matrix.m33;this.m34=matrix.m34;this.m41=matrix.m41;this.m42=matrix.m42;this.m43=matrix.m43;this.m44=matrix.m44;return}}this.makeIdentity()};CanvasMatrix4.prototype.getAsArray=function(){return[this.m11,this.m12,this.m13,this.m14,this.m21,this.m22,this.m23,this.m24,this.m31,this.m32,this.m33,this.m34,this.m41,this.m42,this.m43,this.m44]};CanvasMatrix4.prototype.getAsWebGLFloatArray=function(){return new WebGLFloatArray(this.getAsArray())};CanvasMatrix4.prototype.makeIdentity=function(){this.m11=1;this.m12=0;this.m13=0;this.m14=0;this.m21=0;this.m22=1;this.m23=0;this.m24=0;this.m31=0;this.m32=0;this.m33=1;this.m34=0;this.m41=0;this.m42=0;this.m43=0;this.m44=1};CanvasMatrix4.prototype.transpose=function(){var tmp=this.m12;this.m12=this.m21;this.m21=tmp;tmp=this.m13;this.m13=this.m31;this.m31=tmp;tmp=this.m14;this.m14=this.m41;this.m41=tmp;tmp=this.m23;this.m23=this.m32;this.m32=tmp;tmp=this.m24;this.m24=this.m42;this.m42=tmp;tmp=this.m34;this.m34=this.m43;this.m43=tmp};CanvasMatrix4.prototype.invert=function(){var det=this._determinant4x4();if(Math.abs(det)<1e-8)return null;this._makeAdjoint();this.m11/=det;this.m12/=det;this.m13/=det;this.m14/=det;this.m21/=det;this.m22/=det;this.m23/=det;this.m24/=det;this.m31/=det;this.m32/=det;this.m33/=det;this.m34/=det;this.m41/=det;this.m42/=det;this.m43/=det;this.m44/=det};CanvasMatrix4.prototype.translate=function(x,y,z){if(x==undefined)x=0;if(y==undefined)y=0;if(z==undefined)z=0;var matrix=new CanvasMatrix4();matrix.m41=x;matrix.m42=y;matrix.m43=z;this.multRight(matrix)};CanvasMatrix4.prototype.scale=function(x,y,z){if(x==undefined)x=1;if(z==undefined){if(y==undefined){y=x;z=x}else z=1}else if(y==undefined)y=x;var matrix=new CanvasMatrix4();matrix.m11=x;matrix.m22=y;matrix.m33=z;this.multRight(matrix)};CanvasMatrix4.prototype.rotate=function(angle,x,y,z){angle=angle/180*Math.PI;angle/=2;var sinA=Math.sin(angle);var cosA=Math.cos(angle);var sinA2=sinA*sinA;var length=Math.sqrt(x*x+y*y+z*z);if(length==0){x=0;y=0;z=1}else if(length!=1){x/=length;y/=length;z/=length}var mat=new CanvasMatrix4();if(x==1&&y==0&&z==0){mat.m11=1;mat.m12=0;mat.m13=0;mat.m21=0;mat.m22=1-2*sinA2;mat.m23=2*sinA*cosA;mat.m31=0;mat.m32=-2*sinA*cosA;mat.m33=1-2*sinA2;mat.m14=mat.m24=mat.m34=0;mat.m41=mat.m42=mat.m43=0;mat.m44=1}else if(x==0&&y==1&&z==0){mat.m11=1-2*sinA2;mat.m12=0;mat.m13=-2*sinA*cosA;mat.m21=0;mat.m22=1;mat.m23=0;mat.m31=2*sinA*cosA;mat.m32=0;mat.m33=1-2*sinA2;mat.m14=mat.m24=mat.m34=0;mat.m41=mat.m42=mat.m43=0;mat.m44=1}else if(x==0&&y==0&&z==1){mat.m11=1-2*sinA2;mat.m12=2*sinA*cosA;mat.m13=0;mat.m21=-2*sinA*cosA;mat.m22=1-2*sinA2;mat.m23=0;mat.m31=0;mat.m32=0;mat.m33=1;mat.m14=mat.m24=mat.m34=0;mat.m41=mat.m42=mat.m43=0;mat.m44=1}else{var x2=x*x;var y2=y*y;var z2=z*z;mat.m11=1-2*(y2+z2)*sinA2;mat.m12=2*(x*y*sinA2+z*sinA*cosA);mat.m13=2*(x*z*sinA2-y*sinA*cosA);mat.m21=2*(y*x*sinA2-z*sinA*cosA);mat.m22=1-2*(z2+x2)*sinA2;mat.m23=2*(y*z*sinA2+x*sinA*cosA);mat.m31=2*(z*x*sinA2+y*sinA*cosA);mat.m32=2*(z*y*sinA2-x*sinA*cosA);mat.m33=1-2*(x2+y2)*sinA2;mat.m14=mat.m24=mat.m34=0;mat.m41=mat.m42=mat.m43=0;mat.m44=1}this.multRight(mat)};CanvasMatrix4.prototype.multRight=function(mat){var m11=(this.m11*mat.m11+this.m12*mat.m21+this.m13*mat.m31+this.m14*mat.m41);var m12=(this.m11*mat.m12+this.m12*mat.m22+this.m13*mat.m32+this.m14*mat.m42);var m13=(this.m11*mat.m13+this.m12*mat.m23+this.m13*mat.m33+this.m14*mat.m43);var m14=(this.m11*mat.m14+this.m12*mat.m24+this.m13*mat.m34+this.m14*mat.m44);var m21=(this.m21*mat.m11+this.m22*mat.m21+this.m23*mat.m31+this.m24*mat.m41);var m22=(this.m21*mat.m12+this.m22*mat.m22+this.m23*mat.m32+this.m24*mat.m42);var m23=(this.m21*mat.m13+this.m22*mat.m23+this.m23*mat.m33+this.m24*mat.m43);var m24=(this.m21*mat.m14+this.m22*mat.m24+this.m23*mat.m34+this.m24*mat.m44);var m31=(this.m31*mat.m11+this.m32*mat.m21+this.m33*mat.m31+this.m34*mat.m41);var m32=(this.m31*mat.m12+this.m32*mat.m22+this.m33*mat.m32+this.m34*mat.m42);var m33=(this.m31*mat.m13+this.m32*mat.m23+this.m33*mat.m33+this.m34*mat.m43);var m34=(this.m31*mat.m14+this.m32*mat.m24+this.m33*mat.m34+this.m34*mat.m44);var m41=(this.m41*mat.m11+this.m42*mat.m21+this.m43*mat.m31+this.m44*mat.m41);var m42=(this.m41*mat.m12+this.m42*mat.m22+this.m43*mat.m32+this.m44*mat.m42);var m43=(this.m41*mat.m13+this.m42*mat.m23+this.m43*mat.m33+this.m44*mat.m43);var m44=(this.m41*mat.m14+this.m42*mat.m24+this.m43*mat.m34+this.m44*mat.m44);this.m11=m11;this.m12=m12;this.m13=m13;this.m14=m14;this.m21=m21;this.m22=m22;this.m23=m23;this.m24=m24;this.m31=m31;this.m32=m32;this.m33=m33;this.m34=m34;this.m41=m41;this.m42=m42;this.m43=m43;this.m44=m44};CanvasMatrix4.prototype.multLeft=function(mat){var m11=(mat.m11*this.m11+mat.m12*this.m21+mat.m13*this.m31+mat.m14*this.m41);var m12=(mat.m11*this.m12+mat.m12*this.m22+mat.m13*this.m32+mat.m14*this.m42);var m13=(mat.m11*this.m13+mat.m12*this.m23+mat.m13*this.m33+mat.m14*this.m43);var m14=(mat.m11*this.m14+mat.m12*this.m24+mat.m13*this.m34+mat.m14*this.m44);var m21=(mat.m21*this.m11+mat.m22*this.m21+mat.m23*this.m31+mat.m24*this.m41);var m22=(mat.m21*this.m12+mat.m22*this.m22+mat.m23*this.m32+mat.m24*this.m42);var m23=(mat.m21*this.m13+mat.m22*this.m23+mat.m23*this.m33+mat.m24*this.m43);var m24=(mat.m21*this.m14+mat.m22*this.m24+mat.m23*this.m34+mat.m24*this.m44);var m31=(mat.m31*this.m11+mat.m32*this.m21+mat.m33*this.m31+mat.m34*this.m41);var m32=(mat.m31*this.m12+mat.m32*this.m22+mat.m33*this.m32+mat.m34*this.m42);var m33=(mat.m31*this.m13+mat.m32*this.m23+mat.m33*this.m33+mat.m34*this.m43);var m34=(mat.m31*this.m14+mat.m32*this.m24+mat.m33*this.m34+mat.m34*this.m44);var m41=(mat.m41*this.m11+mat.m42*this.m21+mat.m43*this.m31+mat.m44*this.m41);var m42=(mat.m41*this.m12+mat.m42*this.m22+mat.m43*this.m32+mat.m44*this.m42);var m43=(mat.m41*this.m13+mat.m42*this.m23+mat.m43*this.m33+mat.m44*this.m43);var m44=(mat.m41*this.m14+mat.m42*this.m24+mat.m43*this.m34+mat.m44*this.m44);this.m11=m11;this.m12=m12;this.m13=m13;this.m14=m14;this.m21=m21;this.m22=m22;this.m23=m23;this.m24=m24;this.m31=m31;this.m32=m32;this.m33=m33;this.m34=m34;this.m41=m41;this.m42=m42;this.m43=m43;this.m44=m44};CanvasMatrix4.prototype.ortho=function(left,right,bottom,top,near,far){var tx=(left+right)/(left-right);var ty=(top+bottom)/(top-bottom);var tz=(far+near)/(far-near);var matrix=new CanvasMatrix4();matrix.m11=2/(left-right);matrix.m12=0;matrix.m13=0;matrix.m14=0;matrix.m21=0;matrix.m22=2/(top-bottom);matrix.m23=0;matrix.m24=0;matrix.m31=0;matrix.m32=0;matrix.m33=-2/(far-near);matrix.m34=0;matrix.m41=tx;matrix.m42=ty;matrix.m43=tz;matrix.m44=1;this.multRight(matrix)};CanvasMatrix4.prototype.frustum=function(left,right,bottom,top,near,far){var matrix=new CanvasMatrix4();var A=(right+left)/(right-left);var B=(top+bottom)/(top-bottom);var C=-(far+near)/(far-near);var D=-(2*far*near)/(far-near);matrix.m11=(2*near)/(right-left);matrix.m12=0;matrix.m13=0;matrix.m14=0;matrix.m21=0;matrix.m22=2*near/(top-bottom);matrix.m23=0;matrix.m24=0;matrix.m31=A;matrix.m32=B;matrix.m33=C;matrix.m34=-1;matrix.m41=0;matrix.m42=0;matrix.m43=D;matrix.m44=0;this.multRight(matrix)};CanvasMatrix4.prototype.perspective=function(fovy,aspect,zNear,zFar){var top=Math.tan(fovy*Math.PI/360)*zNear;var bottom=-top;var left=aspect*bottom;var right=aspect*top;this.frustum(left,right,bottom,top,zNear,zFar)};CanvasMatrix4.prototype.lookat=function(eyex,eyey,eyez,centerx,centery,centerz,upx,upy,upz){var matrix=new CanvasMatrix4();var zx=eyex-centerx;var zy=eyey-centery;var zz=eyez-centerz;var mag=Math.sqrt(zx*zx+zy*zy+zz*zz);if(mag){zx/=mag;zy/=mag;zz/=mag}var yx=upx;var yy=upy;var yz=upz;xx=yy*zz-yz*zy;xy=-yx*zz+yz*zx;xz=yx*zy-yy*zx;yx=zy*xz-zz*xy;yy=-zx*xz+zz*xx;yx=zx*xy-zy*xx;mag=Math.sqrt(xx*xx+xy*xy+xz*xz);if(mag){xx/=mag;xy/=mag;xz/=mag}mag=Math.sqrt(yx*yx+yy*yy+yz*yz);if(mag){yx/=mag;yy/=mag;yz/=mag}matrix.m11=xx;matrix.m12=xy;matrix.m13=xz;matrix.m14=0;matrix.m21=yx;matrix.m22=yy;matrix.m23=yz;matrix.m24=0;matrix.m31=zx;matrix.m32=zy;matrix.m33=zz;matrix.m34=0;matrix.m41=0;matrix.m42=0;matrix.m43=0;matrix.m44=1;matrix.translate(-eyex,-eyey,-eyez);this.multRight(matrix)};CanvasMatrix4.prototype._determinant2x2=function(a,b,c,d){return a*d-b*c};CanvasMatrix4.prototype._determinant3x3=function(a1,a2,a3,b1,b2,b3,c1,c2,c3){return a1*this._determinant2x2(b2,b3,c2,c3)-b1*this._determinant2x2(a2,a3,c2,c3)+c1*this._determinant2x2(a2,a3,b2,b3)};CanvasMatrix4.prototype._determinant4x4=function(){var a1=this.m11;var b1=this.m12;var c1=this.m13;var d1=this.m14;var a2=this.m21;var b2=this.m22;var c2=this.m23;var d2=this.m24;var a3=this.m31;var b3=this.m32;var c3=this.m33;var d3=this.m34;var a4=this.m41;var b4=this.m42;var c4=this.m43;var d4=this.m44;return a1*this._determinant3x3(b2,b3,b4,c2,c3,c4,d2,d3,d4)-b1*this._determinant3x3(a2,a3,a4,c2,c3,c4,d2,d3,d4)+c1*this._determinant3x3(a2,a3,a4,b2,b3,b4,d2,d3,d4)-d1*this._determinant3x3(a2,a3,a4,b2,b3,b4,c2,c3,c4)};CanvasMatrix4.prototype._makeAdjoint=function(){var a1=this.m11;var b1=this.m12;var c1=this.m13;var d1=this.m14;var a2=this.m21;var b2=this.m22;var c2=this.m23;var d2=this.m24;var a3=this.m31;var b3=this.m32;var c3=this.m33;var d3=this.m34;var a4=this.m41;var b4=this.m42;var c4=this.m43;var d4=this.m44;this.m11=this._determinant3x3(b2,b3,b4,c2,c3,c4,d2,d3,d4);this.m21=-this._determinant3x3(a2,a3,a4,c2,c3,c4,d2,d3,d4);this.m31=this._determinant3x3(a2,a3,a4,b2,b3,b4,d2,d3,d4);this.m41=-this._determinant3x3(a2,a3,a4,b2,b3,b4,c2,c3,c4);this.m12=-this._determinant3x3(b1,b3,b4,c1,c3,c4,d1,d3,d4);this.m22=this._determinant3x3(a1,a3,a4,c1,c3,c4,d1,d3,d4);this.m32=-this._determinant3x3(a1,a3,a4,b1,b3,b4,d1,d3,d4);this.m42=this._determinant3x3(a1,a3,a4,b1,b3,b4,c1,c3,c4);this.m13=this._determinant3x3(b1,b2,b4,c1,c2,c4,d1,d2,d4);this.m23=-this._determinant3x3(a1,a2,a4,c1,c2,c4,d1,d2,d4);this.m33=this._determinant3x3(a1,a2,a4,b1,b2,b4,d1,d2,d4);this.m43=-this._determinant3x3(a1,a2,a4,b1,b2,b4,c1,c2,c4);this.m14=-this._determinant3x3(b1,b2,b3,c1,c2,c3,d1,d2,d3);this.m24=this._determinant3x3(a1,a2,a3,c1,c2,c3,d1,d2,d3);this.m34=-this._determinant3x3(a1,a2,a3,b1,b2,b3,d1,d2,d3);this.m44=this._determinant3x3(a1,a2,a3,b1,b2,b3,c1,c2,c3)}
<!-- saved from url=(0055)http://www.ibiblio.org/e-notes/webgl/models/NaClb5.html -->
<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Crystal Structures in WebGL</title>
<link href='http://fonts.googleapis.com/css?family=Alike+Angular' rel='stylesheet' type='text/css'>
<style>
input {
padding: 0px;
margin: 5px;
}
#sceneNameDiv {
font-size: 22px;
font-weight: bold;
}
#canvas {
position: fixed;
top: 0px;
bottom: 0px;
left: 0px;
right: 0px;
}
#options {
padding: 5px;
position: fixed;
left: 0px;
bottom: 0px;
background-color: rgba(255, 255, 255, 0.3);
color: #FFFFFF;
text-align: center;
}
body {
font-family: Alike Angular, Arial;
}
</style>
<script src="./CanvasMatrix.js" type="text/javascript"></script>
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aPos; // Normals = Pos
uniform mat4 mvMatrix;
uniform mat4 prMatrix;
uniform vec3 color;
uniform float scale;
varying vec3 col;
const vec4 dirDif = vec4(0., 0., 1., 0.);
const vec4 dirHalf = vec4(-.4034, .259, .8776, 0.);
void main(void) {
gl_Position = prMatrix * mvMatrix * vec4(scale * aPos, 1.);
vec4 rotNorm = mvMatrix * vec4(aPos, .0);
float i = max( 0., dot(rotNorm, dirDif) );
col = i * color;
i = pow( max( 0., dot(rotNorm, dirHalf) ), 30.);
col += vec3(i, i, i);
}
</script>
<script id="shader-fs" type="x-shader/x-fragment">
#ifdef GL_ES
precision highp float;
#endif
varying vec3 col;
void main(void) {
gl_FragColor = vec4(col, 1.);
}
</script>
<script id="line-vs" type="x-shader/x-vertex">
attribute vec3 aPos;
uniform mat4 mvMatrix;
uniform mat4 prMatrix;
void main(void) {
gl_Position = prMatrix * mvMatrix * vec4( aPos, 1.);
}
</script>
<script id="line-fs" type="x-shader/x-fragment">
#ifdef GL_ES
precision highp float;
#endif
void main(void) {
gl_FragColor = vec4( 1.);
}
</script>
<script type="text/javascript">
function getShader ( gl, id ){
var shaderScript = document.getElementById ( id );
var str = "";
var k = shaderScript.firstChild;
while ( k ){
if ( k.nodeType == 3 ) str += k.textContent;
k = k.nextSibling;
}
var shader;
if ( shaderScript.type == "x-shader/x-fragment" )
shader = gl.createShader ( gl.FRAGMENT_SHADER );
else if ( shaderScript.type == "x-shader/x-vertex" )
shader = gl.createShader(gl.VERTEX_SHADER);
else return null;
gl.shaderSource(shader, str);
gl.compileShader(shader);
if (gl.getShaderParameter(shader, gl.COMPILE_STATUS) == 0)
alert(gl.getShaderInfoLog(shader));
return shader;
}
var gl = true;
var canvas = true;
var bonds = false;
var atomSize = 0.3;
var sceneName = 'BCC';
var drawScene = false;
var blendIsChecked = false;
var zoomHandler = function() {};
var xSize = 0.5;
var ySize = 0.5;
var zSize = 0.5;
var zoomMax = -10;
var zoomMin = -100;
function webGLStart() {
canvas = document.getElementById("canvas");
var size = Math.max(window.innerWidth, window.innerHeight);
canvas.width = size;
canvas.height = size;
canvas.style.top = -(size - window.innerHeight) /2 ;
canvas.style.left = -(size - window.innerWidth) / 2;
if (!window.WebGLRenderingContext){
alert("Your browser does not support WebGL. See http://get.webgl.org");
return;
}
try {
gl = canvas.getContext("experimental-webgl");
} catch(e) {
}
if ( !gl ) {
alert("No WebGL support. Try viewing in Google Chrome.");
return;
}
gl.viewport(0, 0, size, size);
drawScene = function() {
if (blendIsChecked) {
gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
gl.enable(gl.BLEND);
gl.disable(gl.DEPTH_TEST);
} else {
gl.disable(gl.BLEND);
gl.enable(gl.DEPTH_TEST);
}
gl.viewport(0, 0, size, size);
document.getElementById('xRange').value = xSize;
document.getElementById('yRange').value = ySize;
document.getElementById('zRange').value = zSize;
if (sceneName == 'BCC')
drawFeBCC();
else if (sceneName == 'FCC')
drawFeFCC();
else if (sceneName == 'Simple')
drawFeSimple();
else if (sceneName == 'NaCl')
drawNaCl();
else if (sceneName == 'Wurtzite')
drawWurtzite();
snd = document.getElementById('sceneNameDiv');
snd.innerText = sceneName + " Crystal System";
}
var prog = gl.createProgram();
gl.attachShader(prog, getShader( gl, "shader-vs" ));
gl.attachShader(prog, getShader( gl, "shader-fs" ));
var posLoc = 0;
gl.bindAttribLocation(prog, posLoc, "aPos");
gl.linkProgram(prog);
var line_prog = gl.createProgram();
gl.attachShader(line_prog, getShader( gl, "line-vs" ));
gl.attachShader(line_prog, getShader( gl, "line-fs" ));
var lineLoc = 1;
gl.bindAttribLocation(line_prog, lineLoc, "aPos");
gl.linkProgram(line_prog);
var vertices = [], ind = [];
var nPhi = 20, nTheta = 10,
dPhi = 2*Math.PI/nPhi, dTheta = Math.PI/nTheta;
for (var j = 0; j <= nTheta; j++ ){
var Theta = j * dTheta;
var cosTheta = Math.cos ( Theta );
var sinTheta = Math.sin ( Theta );
for (var i = 0; i <= nPhi; i++ ){
var Phi = i * dPhi;
var cosPhi = Math.cos ( Phi );
var sinPhi = Math.sin ( Phi );
vertices.push( cosPhi * sinTheta );
vertices.push( -sinPhi * sinTheta );
vertices.push( cosTheta );
}
}
var n1 = nPhi + 1;
for ( i = 0; i < nTheta; i++ )
for ( j = 0; j < nPhi; j++ ){
ind.push (i*n1+j); ind.push ((i+1)*n1+j+1); ind.push (i*n1+j+1);
ind.push (i*n1+j); ind.push ((i+1)*n1+j); ind.push ((i+1)*n1+j+1);
}
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
gl.vertexAttribPointer(posLoc, 3, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.createBuffer());
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(ind), gl.STATIC_DRAW);
var lines = []
var n = 2;
for (var i = -xSize; i <= xSize; i++ )
for (var j = -ySize; j <= ySize; j++ ){
lines.push( i, j, -(zSize + .5) ); lines.push( i, j, (zSize + .5) );
lines.push( i, -(ySize + .5), j ); lines.push( i, (ySize + .5), j );
lines.push( -(xSize + .5), i, j ); lines.push( (xSize + .5), i, j );
}
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array( lines ),gl.STATIC_DRAW);
gl.vertexAttribPointer(lineLoc, 3, gl.FLOAT, false, 0, 0);
var mvMatrix = new CanvasMatrix4();
var rotMat = new CanvasMatrix4();
rotMat.makeIdentity();
var mvMatLoc = gl.getUniformLocation(prog,"mvMatrix");
var colorLoc = gl.getUniformLocation(prog,"color");
var scaleLoc = gl.getUniformLocation(prog,"scale");
var prMatrix = new CanvasMatrix4();
var mvMatLine = gl.getUniformLocation(line_prog,"mvMatrix");
prMatrix.perspective(20, 1, .1, 100);
gl.useProgram(prog);
gl.uniformMatrix4fv( gl.getUniformLocation(prog,"prMatrix"),
false, new Float32Array(prMatrix.getAsArray()) );
gl.useProgram(line_prog);
gl.uniformMatrix4fv( gl.getUniformLocation(line_prog,"prMatrix"),
false, new Float32Array(prMatrix.getAsArray()) );
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
gl.clearDepth(1.0);
gl.clearColor(0, 0, 0, 1);
// gl.lineWidth(2);
var xOffs = yOffs = 0, drag = 0;
var xRot = yRot = 0;
var transl = -25;
drawScene();
function drawFeSimple() {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
rotMat.rotate(xRot/3, 1,0,0); rotMat.rotate(yRot/3, 0,1,0);
yRot = 0; xRot = 0;
gl.useProgram(prog);
gl.enableVertexAttribArray( posLoc );
for (var i= -xSize; i<= xSize; i++)
for (var j= -ySize; j<= ySize; j++)
for (var k= -zSize; k<= zSize; k++)
drawBall(i,j,k, 1,0,0, atomSize);
if (bonds){
gl.useProgram(line_prog);
mvMatrix.load( rotMat );
mvMatrix.translate(0, 0, transl);
gl.uniformMatrix4fv( mvMatLine, false,
new Float32Array(mvMatrix.getAsArray()) );
gl.enableVertexAttribArray( lineLoc );
gl.drawArrays(gl.LINES, 0, 6*(2*n + 1)*(2*n + 1));
}
gl.flush ();
}
function drawFeBCC() {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
rotMat.rotate(xRot/3, 1,0,0); rotMat.rotate(yRot/3, 0,1,0);
yRot = 0; xRot = 0;
gl.useProgram(prog);
gl.enableVertexAttribArray( posLoc );
for (var i= -xSize; i<= xSize; i++)
for (var j= -ySize; j<= ySize; j++)
for (var k= -zSize; k<= zSize; k++)
drawBall(i,j,k, 1,0,0, atomSize);
for (var i= -xSize +0.5; i<= xSize -0.5; i++)
for (var j= -ySize +0.5; j<= ySize -0.5; j++)
for (var k= -zSize +0.5; k<= zSize -0.5; k++)
drawBall(i,j,k, 1,0,0, atomSize);
if (bonds){
gl.useProgram(line_prog);
mvMatrix.load( rotMat );
mvMatrix.translate(0, 0, transl);
gl.uniformMatrix4fv( mvMatLine, false,
new Float32Array(mvMatrix.getAsArray()) );
gl.enableVertexAttribArray( lineLoc );
gl.drawArrays(gl.LINES, 0, 6*(2*n + 1)*(2*n + 1));
}
gl.flush ();
}
function drawFeFCC() {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
rotMat.rotate(xRot/3, 1,0,0); rotMat.rotate(yRot/3, 0,1,0);
yRot = 0; xRot = 0;
gl.useProgram(prog);
gl.enableVertexAttribArray( posLoc );
for (var i= -xSize; i<= xSize; i++)
for (var j= -ySize; j<= ySize; j++)
for (var k= -zSize; k<= zSize; k++)
drawBall(i,j,k, 1,0,0, atomSize);
for (var i= -xSize +0.5; i<= xSize -0.5; i++)
for (var j= -ySize +0.5; j<= ySize -0.5; j++)
for (var k= -zSize; k<= zSize; k++)
drawBall(i,j,k, 1,0,0, atomSize);
for (var i= -xSize +0.5; i<= xSize -0.5; i++)
for (var j= -ySize; j<= ySize; j++)
for (var k= -zSize +0.5; k<= zSize -0.5; k++)
drawBall(i,j,k, 1,0,0, atomSize);
for (var i= -xSize; i<= xSize; i++)
for (var j= -ySize +0.5; j<= ySize -0.5; j++)
for (var k= -zSize +0.5; k<= zSize -0.5; k++)
drawBall(i,j,k, 1,0,0, atomSize);
if (bonds) {
gl.useProgram(line_prog);
mvMatrix.load( rotMat );
mvMatrix.translate(0, 0, transl);
gl.uniformMatrix4fv( mvMatLine, false,
new Float32Array(mvMatrix.getAsArray()) );
gl.enableVertexAttribArray( lineLoc );
gl.drawArrays(gl.LINES, 0, 6*(2*n + 1)*(2*n + 1));
}
gl.flush ();
}
function drawWurtzite() {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
rotMat.rotate(xRot/3, 1,0,0); rotMat.rotate(yRot/3, 0,1,0);
yRot = 0; xRot = 0;
gl.useProgram(prog);
gl.enableVertexAttribArray( posLoc );
offRow = 0;
for (var i= -xSize; i<= xSize; i++) {
for (var j= -ySize - (offRow) * 0.50; j<= ySize + (offRow) * 0.50; j++) {
for (var k= -zSize; k<= zSize; k++)
drawBall(i,j,k, 1,0,0, atomSize);
}
offRow = (offRow + 1) % 2;
}
if (bonds) {
gl.useProgram(line_prog);
mvMatrix.load( rotMat );
mvMatrix.translate(0, 0, transl);
gl.uniformMatrix4fv( mvMatLine, false,
new Float32Array(mvMatrix.getAsArray()) );
gl.enableVertexAttribArray( lineLoc );
gl.drawArrays(gl.LINES, 0, 6*(2*n + 1)*(2*n + 1));
}
gl.flush ();
}
function drawNaCl(){
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
rotMat.rotate(xRot/3, 1,0,0); rotMat.rotate(yRot/3, 0,1,0);
yRot = 0; xRot = 0;
gl.useProgram(prog);
gl.enableVertexAttribArray( posLoc );
for (var i= -xSize; i<= xSize; i++)
for (var j= -ySize; j<= ySize; j++)
for (var k= -zSize; k<= zSize; k++)
if ((i+j+k)%2 != 0) drawBall(i,j,k, 1,0,0, atomSize / 2.0);
else drawBall(i,j,k, 1,1,0, atomSize);
if (bonds){
gl.useProgram(line_prog);
mvMatrix.load( rotMat );
mvMatrix.translate(0, 0, transl);
gl.uniformMatrix4fv( mvMatLine, false,
new Float32Array(mvMatrix.getAsArray()) );
gl.enableVertexAttribArray( lineLoc );
gl.drawArrays(gl.LINES, 0, 6*(2*n + 1)*(2*n + 1));
}
gl.flush ();
}
function drawBall(x,y,z, r,g,b, scale){
mvMatrix.makeIdentity();
mvMatrix.translate(x, y, z);
mvMatrix.multRight( rotMat );
mvMatrix.translate(0, 0, transl);
gl.uniformMatrix4fv( mvMatLoc, false,
new Float32Array(mvMatrix.getAsArray()) );
gl.uniform1f( scaleLoc, scale );
gl.uniform3f( colorLoc, r, g, b );
gl.drawElements(gl.TRIANGLES, 6*nPhi*nTheta, gl.UNSIGNED_SHORT, 0);
}
canvas.resize = function (){
var size = Math.max(window.innerWidth, window.innerHeight);
canvas.width = size;
canvas.height = size;
canvas.style.top = -(size - window.innerHeight) /2 ;
canvas.style.left = -(size - window.innerWidth) / 2;
drawScene();
}
canvas.onmousedown = function ( ev ){
drag = 1;
xOffs = ev.clientX; yOffs = ev.clientY;
}
canvas.onmouseup = function ( ev ){
drag = 0;
xOffs = ev.clientX; yOffs = ev.clientY;
}
canvas.onmousemove = function ( ev ){
if ( drag == 0 ) return;
if ( ev.shiftKey ) {
transl *= 1 + (ev.clientY - yOffs)/1000;
yRot = - xOffs + ev.clientX; }
else {
yRot = - xOffs + ev.clientX; xRot = - yOffs + ev.clientY; }
xOffs = ev.clientX; yOffs = ev.clientY;
drawScene();
}
zoomHandler = function(t) {
// bounds
t = Math.min(t, zoomMax);
t = Math.max(t, zoomMin);
transl = t;
document.getElementById('zoomlevel').value = parseInt(transl);
drawScene();
};
document.getElementById('zoomlevel').min = zoomMin;
document.getElementById('zoomlevel').max = zoomMax;
zoomHandler(-35);
var wheelHandler = function(ev) {
var del = 1.1;
if (ev.shiftKey) del = 1.01;
var ds = ((ev.detail || ev.wheelDelta) > 0) ? del : (1 / del);
zoomHandler(transl * ds)
ev.preventDefault();
};
canvas.addEventListener('DOMMouseScroll', wheelHandler, false);
canvas.addEventListener('mousewheel', wheelHandler, false);
}
function setBonds(v) {
if (sceneName == 'Wurtzite')
v = false;
bonds = v;
document.getElementById('cellbox').checked = v;
drawScene();
}
function setBlend(blend) {
blendIsChecked = blend;
drawScene();
}
function setAtomSize(size) {
atomSize = size;
drawScene();
}
function setScene(scene) {
sceneName = scene
drawScene();
setBonds(bonds);
}
function setUnitCell() {
xSize = 0.5;
ySize = 0.5;
zSize = 0.5;
drawScene();
}
</script>
</head>
<body onload="webGLStart();" onresize="canvas.resize();">
<canvas id="canvas"></canvas> <br />
<div id='options'>
<div id="sceneNameDiv"></div>
<div>
<input type="button" value="Simple" onClick="setScene('Simple');" />
<input type="button" value="FCC" onClick="setScene('FCC');" />
<input type="button" value="BCC" onClick="setScene('BCC');" />
<input type="button" value="Wurtzite" onClick="setScene('Wurtzite');" />
</div>
<br />
<div>
<input type="button" value="Unit Cell" onClick="setUnitCell();" />
<!-- <input type="checkbox" id="cellbox" onclick="setBonds(checked)">Grid -->
<input type="checkbox" onclick="setBlend(checked)">Clouds
</div>
Atom Size<input type="range" style="width:250px;" min="0.005" max="1.0" value="0.3"
step="0.01" onchange="setAtomSize(this.value);" />
<br />X Size
<input type="range" style="width:250px;" min="0" max="20" value="2"
id="xRange" step="0.5" onchange="xSize = this.value; drawScene();" />
<br />Y Size
<input type="range" style="width:250px;" min="0" max="20" value="2"
id="yRange" step="0.5" onchange="ySize = this.value; drawScene();" />
<br />Z Size
<input type="range" style="width:250px;" min="0" max="20" value="2"
id="zRange" step="0.5" onchange="zSize = this.value; drawScene();" />
<br />Zoom
<input type="range" style="width:250px;" min="0" max="20" value="2"
step="0.5" onchange="zoomHandler(this.value);" id="zoomlevel" />
<br /><br />
Drag to rotate model. Scroll to zoom.<br />
<br />
<i>"Remember your E50"</i> &nbsp;
by <a href="http://github.com/jbenet">Juan Batiz-Benet</a>. <br />
<br />Heavily based on <a href="http://www.ibiblio.org/e-notes/webgl/models/NaClb5.html">WebGL NaCl Demo</a>.
</div>
</body></html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment