Created
June 2, 2012 01:28
-
-
Save jbenet/2856073 to your computer and use it in GitHub Desktop.
Remember your e50
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- 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> | |
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