css3d_molecules.html 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
  6. <title>three.js css3d - molecules</title>
  7. <style>
  8. html, body {
  9. height: 100%;
  10. }
  11. body {
  12. background-color: #050505;
  13. background: rgb(43,45,48); /* Old browsers */
  14. background: -moz-radial-gradient(center, ellipse cover, rgba(43,45,48,1) 0%, rgba(0,0,0,1) 100%); /* FF3.6+ */
  15. background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,rgba(43,45,48,1)), color-stop(100%,rgba(0,0,0,1))); /* Chrome,Safari4+ */
  16. background: -webkit-radial-gradient(center, ellipse cover, rgba(43,45,48,1) 0%,rgba(0,0,0,1) 100%); /* Chrome10+,Safari5.1+ */
  17. background: -o-radial-gradient(center, ellipse cover, rgba(43,45,48,1) 0%,rgba(0,0,0,1) 100%); /* Opera 12+ */
  18. background: -ms-radial-gradient(center, ellipse cover, rgba(43,45,48,1) 0%,rgba(0,0,0,1) 100%); /* IE10+ */
  19. background: radial-gradient(ellipse at center, rgba(43,45,48,1) 0%,rgba(0,0,0,1) 100%); /* W3C */
  20. filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#2b2d30', endColorstr='#000000',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */
  21. margin: 0;
  22. font-family: Arial;
  23. overflow: hidden;
  24. }
  25. a {
  26. color: #ffffff;
  27. }
  28. #info {
  29. position: absolute;
  30. width: 100%;
  31. color: #ffffff;
  32. padding: 5px;
  33. font-family: Monospace;
  34. font-size: 13px;
  35. font-weight: bold;
  36. text-align: center;
  37. z-index: 100;
  38. }
  39. #menu {
  40. position: absolute;
  41. bottom: 20px;
  42. width: 100%;
  43. text-align: center;
  44. padding: 0;
  45. margin: 0;
  46. }
  47. button {
  48. color: rgb(255,255,255);
  49. background: transparent;
  50. border: 0px;
  51. padding: 5px 10px;
  52. cursor: pointer;
  53. }
  54. button:hover {
  55. background-color: rgba(0,255,255,0.5);
  56. }
  57. button:active {
  58. color: #000000;
  59. background-color: rgba(0,255,255,1);
  60. }
  61. .bond {
  62. width: 5px;
  63. height: 10px;
  64. background: #eee;
  65. display: block;
  66. }
  67. </style>
  68. </head>
  69. <body>
  70. <script src="../build/three.min.js"></script>
  71. <script src="js/controls/TrackballControls.js"></script>
  72. <script src="js/renderers/CSS3DRenderer.js"></script>
  73. <script src="js/loaders/PDBLoader.js"></script>
  74. <div id="container"></div>
  75. <div id="info"><a href="http://threejs.org" target="_blank">three.js css3d</a> - molecules</div>
  76. <div id="menu"></div>
  77. <script>
  78. var camera, scene, renderer;
  79. var controls;
  80. var root;
  81. var objects = [];
  82. var tmpVec1 = new THREE.Vector3();
  83. var tmpVec2 = new THREE.Vector3();
  84. var tmpVec3 = new THREE.Vector3();
  85. var tmpVec4 = new THREE.Vector3();
  86. var MOLECULES = {
  87. "Ethanol" :"ethanol.pdb",
  88. "Aspirin" :"aspirin.pdb",
  89. "Caffeine" :"caffeine.pdb",
  90. "Nicotine" :"nicotine.pdb",
  91. "LSD" :"lsd.pdb",
  92. "Cocaine" :"cocaine.pdb",
  93. "Cholesterol" :"cholesterol.pdb",
  94. "Lycopene" :"lycopene.pdb",
  95. "Glucose" : "glucose.pdb",
  96. "Aluminium oxide":"Al2O3.pdb",
  97. "Cubane" :"cubane.pdb",
  98. "Copper" :"cu.pdb",
  99. "Fluorite" :"caf2.pdb",
  100. "Salt" :"nacl.pdb",
  101. "YBCO superconductor":"ybco.pdb",
  102. "Buckyball" : "buckyball.pdb",
  103. //"Diamond" :"diamond.pdb",
  104. "Graphite" :"graphite.pdb"
  105. };
  106. var loader = new THREE.PDBLoader();
  107. var colorSpriteMap = {};
  108. var baseSprite = document.createElement( 'img' );
  109. var menu = document.getElementById( "menu" );
  110. init();
  111. animate();
  112. function init() {
  113. camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 5000 );
  114. camera.position.z = 1500;
  115. scene = new THREE.Scene();
  116. root = new THREE.Object3D();
  117. scene.add( root );
  118. //
  119. renderer = new THREE.CSS3DRenderer();
  120. renderer.setSize( window.innerWidth, window.innerHeight );
  121. renderer.domElement.style.position = 'absolute';
  122. renderer.domElement.style.top = 0;
  123. document.getElementById( 'container' ).appendChild( renderer.domElement );
  124. //
  125. controls = new THREE.TrackballControls( camera, renderer.domElement );
  126. controls.rotateSpeed = 0.5;
  127. controls.addEventListener( 'change', render );
  128. //
  129. baseSprite.onload = function () {
  130. loadMolecule( "models/molecules/caffeine.pdb" );
  131. createMenu();
  132. };
  133. baseSprite.src = 'textures/sprites/ball.png';
  134. //
  135. window.addEventListener( 'resize', onWindowResize, false );
  136. }
  137. //
  138. function generateButtonCallback( url ) {
  139. return function ( event ) {
  140. loadMolecule( url );
  141. }
  142. }
  143. function createMenu() {
  144. for ( var m in MOLECULES ) {
  145. var button = document.createElement( 'button' );
  146. button.innerHTML = m;
  147. menu.appendChild( button );
  148. var url = "models/molecules/" + MOLECULES[ m ];
  149. button.addEventListener( 'click', generateButtonCallback( url ), false );
  150. }
  151. }
  152. //
  153. function colorify( ctx, width, height, color, a ) {
  154. var r = color.r;
  155. var g = color.g;
  156. var b = color.b;
  157. var imageData = ctx.getImageData( 0, 0, width, height );
  158. var data = imageData.data;
  159. for ( var y = 0; y < height; y ++ ) {
  160. for ( var x = 0; x < width; x ++ ) {
  161. var index = ( y * width + x ) * 4;
  162. data[ index ] *= r;
  163. data[ index + 1 ] *= g;
  164. data[ index + 2 ] *= b;
  165. data[ index + 3 ] *= a;
  166. }
  167. }
  168. ctx.putImageData( imageData, 0, 0 );
  169. }
  170. function imageToCanvas( image ) {
  171. var width = image.width;
  172. var height = image.height;
  173. var canvas = document.createElement( 'canvas' );
  174. canvas.width = width;
  175. canvas.height = height;
  176. var context = canvas.getContext( '2d' );
  177. context.drawImage( image, 0, 0, width, height );
  178. return canvas;
  179. }
  180. //
  181. function loadMolecule( url ) {
  182. for ( var i = 0; i < objects.length; i ++ ) {
  183. var object = objects[ i ];
  184. object.parent.remove( object );
  185. renderer.cameraElement.removeChild( object.element );
  186. }
  187. objects = [];
  188. loader.load( url, function ( geometry, geometryBonds ) {
  189. var offset = THREE.GeometryUtils.center( geometry );
  190. geometryBonds.applyMatrix( new THREE.Matrix4().makeTranslation( offset.x, offset.y, offset.z ) );
  191. for ( var i = 0; i < geometry.vertices.length; i ++ ) {
  192. var position = geometry.vertices[ i ];
  193. var color = geometry.colors[ i ];
  194. var element = geometry.elements[ i ];
  195. if ( ! colorSpriteMap[ element ] ) {
  196. var canvas = imageToCanvas( baseSprite );
  197. var context = canvas.getContext( '2d' );
  198. colorify( context, canvas.width, canvas.height, color, 1 );
  199. var dataUrl = canvas.toDataURL();
  200. colorSpriteMap[ element ] = dataUrl;
  201. }
  202. colorSprite = colorSpriteMap[ element ];
  203. var atom = document.createElement( 'img' );
  204. atom.src = colorSprite;
  205. var object = new THREE.CSS3DSprite( atom );
  206. object.position.copy( position );
  207. object.position.multiplyScalar( 75 );
  208. object.billboard = true;
  209. root.add( object );
  210. objects.push( object );
  211. }
  212. for ( var i = 0; i < geometryBonds.vertices.length; i += 2 ) {
  213. var start = geometryBonds.vertices[ i ];
  214. var end = geometryBonds.vertices[ i + 1 ];
  215. start.multiplyScalar( 75 );
  216. end.multiplyScalar( 75 );
  217. tmpVec1.sub( end, start );
  218. var bondLength = tmpVec1.length() - 50;
  219. //
  220. var bond = document.createElement( 'div' );
  221. bond.className = "bond";
  222. bond.style.height = bondLength + "px";
  223. var object = new THREE.CSS3DObject( bond );
  224. object.position.copy( start );
  225. object.position.lerpSelf( end, 0.5 );
  226. //
  227. var axis = tmpVec2.set( 0, 1, 0 ).crossSelf( tmpVec1 );
  228. var radians = Math.acos( tmpVec3.set( 0, 1, 0 ).dot( tmpVec4.copy( tmpVec1 ).normalize() ) );
  229. var objMatrix = new THREE.Matrix4().makeRotationAxis( axis.normalize(), radians );
  230. object.matrix = objMatrix;
  231. object.rotation.setEulerFromRotationMatrix( object.matrix, object.eulerOrder );
  232. root.add( object );
  233. objects.push( object );
  234. //
  235. var bond = document.createElement( 'div' );
  236. bond.className = "bond";
  237. bond.style.height = bondLength + "px";
  238. var joint = new THREE.Object3D( bond );
  239. joint.position.copy( start );
  240. joint.position.lerpSelf( end, 0.5 );
  241. joint.matrix.copy( objMatrix );
  242. joint.rotation.setEulerFromRotationMatrix( joint.matrix, joint.eulerOrder );
  243. var object = new THREE.CSS3DObject( bond );
  244. object.rotation.y = Math.PI/2;
  245. joint.add( object );
  246. root.add( joint );
  247. objects.push( object );
  248. }
  249. //console.log( "CSS3DObjects:", objects.length );
  250. render();
  251. } );
  252. }
  253. //
  254. function onWindowResize() {
  255. camera.aspect = window.innerWidth / window.innerHeight;
  256. camera.updateProjectionMatrix();
  257. renderer.setSize( window.innerWidth, window.innerHeight );
  258. render();
  259. }
  260. function animate() {
  261. requestAnimationFrame( animate );
  262. controls.update();
  263. var time = Date.now() * 0.0004;
  264. root.rotation.x = time;
  265. root.rotation.y = time * 0.7;
  266. render();
  267. }
  268. function render() {
  269. renderer.render( scene, camera );
  270. }
  271. </script>
  272. </body>
  273. </html>