{"id":1229,"date":"2016-12-14T22:56:33","date_gmt":"2016-12-15T03:56:33","guid":{"rendered":"http:\/\/rpchurchill.com\/?p=1229"},"modified":"2017-02-03T13:11:16","modified_gmt":"2017-02-03T18:11:16","slug":"a-simple-discrete-event-simulation-part-58","status":"publish","type":"post","link":"https:\/\/rpchurchill.com\/wordpress\/posts\/2016\/12\/14\/a-simple-discrete-event-simulation-part-58\/","title":{"rendered":"A Simple Discrete-Event Simulation: Part 58"},"content":{"rendered":"<p><iframe loading=\"lazy\" width=\"300px\" height=\"300px\" src=\"https:\/\/www.rpchurchill.com\/demo\/des\/Example3D.html\" frameborder=\"0\" allowfullscreen><\/iframe><\/p>\n<p>Today I started experimenting with the <a href=\"https:\/\/threejs.org\/\">Three.js<\/a> framework that supports  the creation of <a href=\"https:\/\/en.wikipedia.org\/wiki\/WebGL\">WebGL<\/a> apps in most modern browsers.  I started from the <a href=\"https:\/\/threejs.org\/docs\/index.html#Manual\/Introduction\/Creating_a_scene\">most basic example<\/a> I saw demonstrated at a recent JavaScript Meetup in Baltimore.  I then began to dig around to figure out how to add an modify things the way I wanted them.  I first figured out how to display <a href=\"http:\/\/jsfiddle.net\/tfjvggfu\/24\/\">both the faces and the vertices<\/a> of 3D shapes, and then I figured out how to make the camera fly around the correct axis to maintain the perspective I was going for.  If x is left and right, y is up and down, and z is into the screen, then to make it look like you&#8217;re a helicopter flying around a landscape while always looking toward the same point you have to assume that the y-axis is the vertical about which you orbit (revolve) along or above the x-z plane.  Now that I have that sorted out a lot of the rest of rendering the simulation in 3D should be fairly straightforward, if detailed and time-consuming.<\/p>\n<p>Here&#8217;s the basic code so far.<\/p>\n<pre class=\"toolbar-overlay:false wrap:false height-set:true lang:default decode:true \">\r\n<!DOCTYPE html>\r\n<html>\r\n\t<head>\r\n\t\t<meta charset=utf-8>\r\n\t\t<title>My first Three.js app<\/title>\r\n\t\t<style>\r\n\t\t\tbody { margin: 0; }\r\n\t\t\tcanvas { width: 100%; height: 100%\r\n\t\t<\/style>\r\n\t<\/head>\r\n\t<body>\r\n\t\t<script src=\"js\/three.js\"><\/script>\r\n    <script>\r\n      var scene = new THREE.Scene();\r\n      var camera = new THREE.PerspectiveCamera( 75, window.innerWidth \/ window.innerHeight, 0.1, 1000 );\r\n\r\n\t    var light = new THREE.HemisphereLight( 0xeeeeee, 0x888888, 1 );\r\n\t    light.position.set( 0, 20, 0 );\r\n\t    scene.add( light );\r\n\r\n      var renderer = new THREE.WebGLRenderer();\r\n      renderer.setSize( window.innerWidth, window.innerHeight );\r\n      document.body.appendChild( renderer.domElement );\r\n      var geometry = new THREE.BoxGeometry( 1, 0.2, 1 );\r\n      var material = new THREE.MeshPhongMaterial({\r\n        color: 0x00ff00,\r\n        shading: THREE.FlatShading,\r\n        polygonOffset: true,\r\n        polygonOffsetFactor: 1,  \/\/positive value pushes polygon farther away\r\n        polygonOffsetUnits: 1\r\n      });\r\n      var cube = new THREE.Mesh( geometry, material );\r\n      \r\n      \/\/ wireframe\r\n      var geo = new THREE.EdgesGeometry( cube.geometry );\r\n      var mat = new THREE.LineBasicMaterial( { color: 0x222222, linewidth: 2 } );  \/\/linewidth defaults to 1 in Windows iirc\r\n      var wireframe = new THREE.LineSegments( geo, mat );\r\n      cube.add( wireframe );\r\n\r\n      cube.position.set(0,0,0);\r\n      scene.add( cube );\r\n\r\n      var cameraRadius = 6.0;\r\n      var cameraRevolutionAngle = Math.PI * 0.5;\r\n      var cameraRevolutionIncrement = -0.01;\r\n      \r\n      camera.position.x = cameraRadius * Math.cos(cameraRevolutionAngle);\r\n      camera.position.z = cameraRadius * Math.sin(cameraRevolutionAngle);\r\n      camera.position.y = 2;\r\n\r\n      renderer.render( scene, camera );\r\n        \r\n      function render() {\r\n        cameraRevolutionAngle += cameraRevolutionIncrement;\r\n        if (cameraRevolutionAngle > Math.PI * 2.0) {\r\n          cameraRevolutionAngle -= Math.PI * 2.0;\r\n        }\r\n        camera.position.x = cameraRadius * Math.cos(cameraRevolutionAngle);\r\n        camera.position.z = cameraRadius * Math.sin(cameraRevolutionAngle);\r\n        camera.lookAt(scene.position);\r\n\r\n        renderer.render( scene, camera );\r\n\r\n        requestAnimationFrame( render );\r\n      }\r\n      render();      \r\n\t\t<\/script>\r\n\t<\/body>\r\n<\/html>\r\n<\/pre>\n<p>I&#8217;m used to doing most of this sort of thing <a href=\"https:\/\/rpchurchill.com\/posts\/2016\/02\/09\/javascript-html5-canvas-pour-demo\/\">on my own<\/a> by managing my own coordinates, transforms, perspecitives, and renderings, but I never fully studied hidden surface algorithms, shading, and so on.  Learning this framework gives me a lot more leverage, and my existing experience helps me understand the whole thing easily enough.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today I started experimenting with the Three.js framework that supports the creation of WebGL apps in most modern browsers. I started from the most basic example I saw demonstrated at a recent JavaScript Meetup in Baltimore. I then began to &hellip; <a href=\"https:\/\/rpchurchill.com\/wordpress\/posts\/2016\/12\/14\/a-simple-discrete-event-simulation-part-58\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[60],"tags":[121,133,134],"_links":{"self":[{"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/posts\/1229"}],"collection":[{"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/comments?post=1229"}],"version-history":[{"count":6,"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/posts\/1229\/revisions"}],"predecessor-version":[{"id":1411,"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/posts\/1229\/revisions\/1411"}],"wp:attachment":[{"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/media?parent=1229"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/categories?post=1229"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/tags?post=1229"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}