function GraphicsEngine() { this._scene = undefined; this._camera = undefined; this._renderer = undefined; this._canvasWidth = 500; this._canvasHeight = 500; this._containerContext = undefined; this._BALL_RADIUS = 0.25; this._controls = undefined; this._parts = [] this._debug1 = 0 this._showAxis = false; } GraphicsEngine.prototype.showPartAxis = function () { this._showAxis = true; } GraphicsEngine.prototype._createRenderer = function () { this._renderer = new THREE.WebGLRenderer({antialias: true}); this._renderer.setClearColor(0x000000, 1); this._renderer.setSize(this._canvasWidth, this._canvasHeight); this._containerContext = $("#container"); this._containerContext.append(this._renderer.domElement); } GraphicsEngine.prototype._prepareCamera = function () { this._camera = new THREE.PerspectiveCamera(45, this._canvasWidth / this._canvasHeight, 1, 100); this._camera.position.set(0, 0, 10); this._camera.lookAt(this._scene.position); this._scene.add(this._camera); } GraphicsEngine.prototype._addLight = function () { var directionalLight = new THREE.DirectionalLight(0xffffff); directionalLight.position = this._camera.position; directionalLight.intensity = 1; this._scene.add(directionalLight); } GraphicsEngine.prototype._rotateObject = function (object, part) { object.rotateX(part.getXrot()); object.rotateY(part.getYrot()); object.rotateZ(part.getZrot()); } GraphicsEngine.prototype._addBall = function (part) { var segments = 40, rings = 40; var sphereMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff }); sphereMaterial.color.setRGB(part.getR(), part.getG(), part.getB()) var ball = new THREE.Mesh( new THREE.SphereGeometry(part.getRadius()/4, segments, rings), sphereMaterial); ball.position.set(part.getX(), part.getY(), part.getZ()); this._rotateObject(ball, part); this._parts.push(ball); if(this._showAxis) ball.add(new THREE.AxisHelper(1)); this._scene.add(ball); } GraphicsEngine.prototype._addEllipsoid = function (part) { var geometry = new THREE.SphereGeometry(1, 20, 20); geometry.applyMatrix(new THREE.Matrix4().makeScale(part.getXshape(), part.getYshape(), part.getZshape())); var ellipsoidMaterial = new THREE.MeshPhongMaterial({color: 0xffffff}); ellipsoidMaterial.color.setRGB(part.getR(), part.getG(), part.getB()) var ellipsoid = new THREE.Mesh(geometry, ellipsoidMaterial); ellipsoid.position.set(part.getX(), part.getY(), part.getZ()); this._rotateObject(ellipsoid, part); this._parts.push(ellipsoid); if(this._showAxis) ellipsoid.add(new THREE.AxisHelper(1)); this._scene.add(ellipsoid); } GraphicsEngine.prototype._addCylinder = function (part) { var geometry = new THREE.CylinderGeometry(1, 1, 1, 10, 10, false); geometry.applyMatrix(new THREE.Matrix4().makeScale(part.getZshape(), part.getXshape(), part.getYshape())); var material = new THREE.MeshLambertMaterial({color: 0xffffff}); material.color.setRGB(part.getR(), part.getG(), part.getB()); var cylinder = new THREE.Mesh(geometry, material); cylinder.position.set(part.getX(), part.getY(), part.getZ()); cylinder.overdraw = true; this._rotateObject(cylinder, part); this._parts.push(cylinder); if(this._showAxis) cylinder.add(new THREE.AxisHelper(1)); this._scene.add(cylinder); } GraphicsEngine.prototype._addCuboid = function (part) { var geometry = new THREE.CubeGeometry(2, 2, 2, 10, 10, 10); geometry.applyMatrix(new THREE.Matrix4().makeScale(part.getXshape(), part.getYshape(), part.getZshape())); var material = new THREE.MeshLambertMaterial({color: 0xffffff}); material.color.setRGB(part.getR(), part.getG(), part.getB()); var cube = new THREE.Mesh(geometry, material); cube.position.set(part.getX(), part.getY(), part.getZ()); this._rotateObject(cube, part); this._parts.push(cube); if(this._showAxis) cube.add(new THREE.AxisHelper(1)); this._scene.add(cube); } GraphicsEngine.prototype.addPart = function (part) { switch (part.getType()) { case 0: this._addBall(part); break; case 1: this._addEllipsoid(part); break; case 2: this._addCuboid(part); break; case 3: this._addCylinder(part); break; default : throw new Error("Unknown shape of part"); break; } } GraphicsEngine.prototype._addStick = function (joint) { var p1Pos = this._parts[joint.getP1()].position; var p2Pos = this._parts[joint.getP2()].position; var p1Vector = new THREE.Vector3(p1Pos.x, p1Pos.y, p1Pos.z); var p2Vector = new THREE.Vector3(p2Pos.x, p2Pos.y, p2Pos.z); var HALF_PI = Math.PI * .5; var distance = p1Vector.distanceTo(p2Vector); var position = p2Vector.clone().add(p1Vector).divideScalar(2); var material = new THREE.MeshPhongMaterial({color: 0x0000ff}); material.color.setRGB(joint.getR(), joint.getG(), joint.getB()); var cylinder = new THREE.CylinderGeometry(0.05, 0.05, distance, 20, 20, false); var orientation = new THREE.Matrix4();//a new orientation matrix to offset pivot var offsetRotation = new THREE.Matrix4();//a matrix to fix pivot rotation orientation.lookAt(p1Vector, p2Vector, new THREE.Vector3(0, 1, 0));//look at destination offsetRotation.makeRotationX(HALF_PI);//rotate 90 degs on X orientation.multiply(offsetRotation);//combine orientation with rotation transformations cylinder.applyMatrix(orientation); var mesh = new THREE.Mesh(cylinder, material); mesh.position = position; this._scene.add(mesh); } GraphicsEngine.prototype._hasTranslation = function (joint) { if (joint.getXtran() != 0) return true; if (joint.getYtran() != 0) return true; if (joint.getZtran() != 0) return true; return false; } GraphicsEngine.prototype._translate = function (joint) { if(this._hasTranslation(joint)) { var p1 = joint.getP1(); var p2 = joint.getP2(); var copy = this._parts[p1].clone(); copy.rotateX(joint.getXrot()); copy.rotateY(joint.getYrot()); copy.rotateZ(joint.getZrot()); copy.translateX(joint.getXtran()); copy.translateY(joint.getYtran()); copy.translateZ(joint.getZtran()); this._parts[p2].position = copy.position.clone(); this._parts[p2].rotation = copy.rotation.clone(); delete copy; } } GraphicsEngine.prototype.addJoint = function (joint) { switch (joint.getType()) { case 0: this._translate(joint); this._addStick(joint); break; case 1: this._translate(joint); break; default : throw new Error("Unknown shape of joint"); break; } } GraphicsEngine.prototype.initializeScene = function () { this._createRenderer(); this._scene = new THREE.Scene(); this._prepareCamera(); this._addLight(); this._controls = new THREE.TrackballControls(this._camera, this._renderer.domElement) this._debug(); } GraphicsEngine.prototype.renderScene = function () { var self = this; requestAnimationFrame( function () { self.renderScene(); }); this._renderer.render(this._scene, this._camera); this._controls.update(); } GraphicsEngine.prototype._debug = function() { this._scene.add( new THREE.AxisHelper( 20 ) ); } GraphicsEngine.prototype.debugTest = function() { }