UNPKG

j5-rc-receiver

Version:

Nintendo RC Receiver component class plugin for Johnny-Five

1,047 lines (945 loc) 45.7 kB
<html> <head> <title>Ovoid.JS Pitts Demo</title> <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"> <!-- Load Ovoid.JS API --> <script type="text/javascript" src="http://www.ovoid.org/js/rel/2.0/lib/ovoid.js"></script> <!-- Main script --> <script type="text/javascript"> /* ================================================================= * ================= Ovoid.JS Pitts Special Demo =================== * ================================================================= * Copyright (C) 2011 - 2014 Eric M. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * ================================================================= * Intermediary development application, see: * http://www.ovoid.org/js/rel/2.0/demo/pitts/dev-gui.html * http://www.ovoid.org/js/rel/2.0/demo/pitts/dev-avion.html * http://www.ovoid.org/js/rel/2.0/demo/pitts/dev-terrain.html * ================================================================= */ function main() { /* -------- Global Tools and Temporary objets elements -------- */ var rx, ry, rz, cy; var gVec = new Ovoid.Vector(); var gVx = new Ovoid.Vector(); var gVy = new Ovoid.Vector(); var gVz = new Ovoid.Vector(); var gPnt = new Ovoid.Point(); var gWorldX = new Ovoid.Vector(1.0,0.0,0.0); var gWorldY = new Ovoid.Vector(0.0,1.0,0.0); var gWorldZ = new Ovoid.Vector(0.0,0.0,1.0); /* -------------------------------------------------------------*/ /* --------------------- GAME VARIABLES ------------------------*/ /* -------------------------------------------------------------*/ var gCrashed = false; // Plane crashed flag var gViewMod = 0; // View cycle mode selected var gVomitive = 0.0; // Nausea value (computed but currently unused, maybe used later for more fun) /* -------------------------------------------------------------*/ /* ---------------------- SCENE OBJECTS ------------------------*/ /* -------------------------------------------------------------*/ /* ------------------- Global GUI elements -------------------- */ var GuiWatermark; // Common watermark var GuiHelpframe; // Splash help frame var GuiGaugA; // Altimeter gauge layer var GuiGaugApa; // Altimeter gauge little blade layer var GuiGaugAga; // Altimeter gauge big blade layer var GuiLocApa; // Altimeter gauge little blade locator var GuiLocAga; // Altimeter gauge big blade locator var GuiGaugV; // Airspeed gauge layer var GuiGaugVga; // Airspeed gauge big blade layer var GuiLocVga; // Airspeed gauge big blade locator var GuiGaugM; // RPM gauge layer var GuiGaugMga; // RMP gauge big blade layer var GuiLocMga; // RPM gauge big blade locator var GuiGaugG; // G-factor gauge layer var GuiGaugGga; // G-factor gauge big blade layer var GuiLocGga; // G-factor gauge big blade locator var GuiThrottleP; // Throttle panel var GuiThrottleM; // Throttle manet var GuiMsgR; // R - Restart messag var GuiWrnOS; // Overspeed warning message var GuiShowHf = true; // Show help frame flag var GuiShowRm = false; // Show restart message flag /* --------- Global Landscape & environment elements ---------- */ var LndLandGrp; // Group node of landscape squares var LndTreeGrp; // Group node of trees var LndAcbound; // Active bounding sphere /* ---------------- Global Aircraft elements ------------------ */ var PittsBody; // Pitts body node var PittsPhys; // Pitts physics constraint node var PittsLocl; // Pitts local space locator node var PittsPrpl; // Pitts propeller body/mesh var PittsPMat; // Pitts propeller's material node /* -------------------- Global GFX elements ------------------- */ var GfxBurnE; // Crash black smoke emitter var GfxBurnB; // Crash black smoke body var GfxDustE; // Ground touch dust emitter var GfxDustB; // Ground touch dust body var GfxDustT; // Ground touch dust timer (to auto stop emits) var GfxSmokE; // Aircraft tail smoke emitter var GfxSmokB; // Aircraft tail smoke body /* -------------------- Global SFX elements ------------------- */ var SfxPropIdle; // Engine Sound var SfxPropRun; // Engine & Fan Sound var SfxVent; // Wind sound var SfxTurb; // Turbulances sound var SfxCrash; // Crash sound var SfxMpitch; // RPM to Pitch conversion variable var SfxMute = false; // Mute sound flag /* --------------------- Global Cameras ----------------------- */ var CamFlw; // Aimed follow Camera var CamEmb; // Embedded fixed camera var CamOrb; // Orbit camera var CamOrbLoc; // Orbit camera locator var CamFly; // Flyby camera var CamAim; // Aim constraint node /* -------------------------------------------------------------*/ /* ------------------- SIMULATOR ELEMENTS ----------------------*/ /* -------------------------------------------------------------*/ /* --------------- Plane's Attitude Variables ------------------*/ var AcZvect = new Ovoid.Vector(); // Aircraft world forward vector var AcYvect = new Ovoid.Vector(); // Aircraft world upward vector var AcXvect = new Ovoid.Vector(); // Aircraft world side vector var AcVelocity = new Ovoid.Vector(); // Aircraft velocity /* -------------- Plane's Simulation Constants -----------------*/ var F = 500; // Air viscosity / Friction (const) var W = 600.0 // Aircraft weight (const) var P = 9.1; // Engine RPM/Traction factor (const) var Tmn = 0.25; // Throttle idle var Mac = 10.0; // Engine RPM acceleration factor (const) var Mmx = 2700.0; // Engine max RPM (const) var Pf = 15.0; // Portance factor (const) var Ef = 900.0; // Elevator factor (const) var Rf = 2000.0; // Aileron factor (const) var AcEngineLoc = new Ovoid.Point(0.0, 0.0, 0.0, 1.0); // Engine traction point var AcLwLoc = new Ovoid.Point(-2.0, 0.0, 0.0, 1.0); // Left Wing Plan Location Point var AcLwTensor = new Ovoid.Matrix3(); // Left Wing Plan Tensor Matrix AcLwTensor.m[0] = -0.05*F; AcLwTensor.m[4] = -0.05*F; AcLwTensor.m[5] = Pf; // Default Portance AcLwTensor.m[8] = -0.75*F; // Constraint on Z plane var AcRwLoc = new Ovoid.Point(2.0, 0.0, 0.0, 1.0); // Right Wing Plan Location Point var AcRwTensor = new Ovoid.Matrix3(); // Right Wing Plan Tensor Matrix AcRwTensor.m[0] = -0.05*F; AcRwTensor.m[4] = -0.05*F; AcRwTensor.m[5] = Pf; // Default Portance AcRwTensor.m[8] = -0.75*F; // Constraint on Z plane var AcElLoc = new Ovoid.Point(0.0, -2.5, 0.0, 1.0); // Elevator Plan Location Point var AcElTensor = new Ovoid.Matrix3(); // Elevator Plan Tensor Matrix AcElTensor.m[0] = -0.01*F; AcElTensor.m[4] = -0.01*F; AcElTensor.m[5] = 0.0; // Default Portance AcElTensor.m[8] = -0.25*F; // Constraint on Z plane var AcVfLoc = new Ovoid.Point(0.0, -2.5, 0.0, 1.0); // Vertical Fuselage Plan Location Point var AcVfTensor = new Ovoid.Matrix3(); // Vertical Fuselage Plan Tensor Matrix AcVfTensor.m[0] = -1.0*F; // Constraint on X plane AcVfTensor.m[4] = -0.01*F; AcVfTensor.m[5] = 0.0; AcVfTensor.m[8] = -0.01*F; /* -------------- Plane's Simulation Variables -----------------*/ var M = 0.0; // Engine RPM var RV = 0.0; // Relative Velocity var AV = 0.0; // Absolute Velocity var AA = 0.0; // Angle Of Attack var CM = 0.0; // Contact magnitude var CA = 0.0; // Contact angle var A = 0.0; // Absolute Alitude var uG = 0.0; // G force preview var G = 0.0; // G force /* -------------------------------------------------------------*/ /* ------------------- CONTROLS VARIABLES ----------------------*/ /* -------------------------------------------------------------*/ /* --------------- Joystick States variables -------------------*/ var JoyZ = 0.0; // Joystick Z axis - Throttle var JoyX = 0.0; // Joystick X axis - Ailerons (currently unused, maybe when joystick inputs will be implemented in browers) var JoyY = 0.0; // Joystick Y axis - Elevator (currently unused, maybe when joystick inputs will be implemented in browers) /* --------------- Controls States variables -------------------*/ var T = 0.0; // Throttle var E = 0.0; // Elevator angle var R = 0.0; // Ailerons angle /* --------------- Controls Models constants -------------------*/ var Ebase = 0.103; // Elevator rotation base var Erelease = true; // Elevator released to recenter flag var RHbaseX = 0.12; // Aileron rotation base var RHbaseY = 0.01; // Aileron rotation base var RHbaseZ = 0.045; // Aileron rotation base var RBbaseX = 0.12; // Aileron rotation base var RBbaseY = 0.02; // Aileron rotation base var RBbaseZ = 0.0; // Aileron rotation base var Rrelease = true; // Aileron released to recenter flag /* -------------------------------------------------------------*/ /* ------------------- CONTROLS FUNCTIONS ----------------------*/ /* -------------------------------------------------------------*/ /* ------------------- Throttle Increase -----------------------*/ var Mincr = function() { if(!gCrashed) { if(T < 1.0) { JoyZ += Oinst.Timer.quantum*(0.8); if(JoyZ > 0) { T = 0.165+Math.log((JoyZ*0.3)+2.0); } else { T = 0.0; } if(T > 1.0) T = 1.0; if(T < Tmn) T = Tmn; } } }; /* ------------------- Throttle Decrease -----------------------*/ var Mdecr = function() { if(!gCrashed) { if(T > Tmn) { JoyZ -= Oinst.Timer.quantum*(0.8); if(JoyZ > 0) { T = 0.165+Math.log((JoyZ*0.3)+2.0); } else { T = 0.0; } if(T < Tmn) T = Tmn; } } }; /* ---------------------- Elevator Up --------------------------*/ var EmoveUp = function() { if(E < 0.2) E+=Oinst.Timer.quantum*0.5; Erelease = false; }; /* -------------------- Elevator Donw --------------------------*/ var EmoveDn = function() { if(E > -0.2) E-=Oinst.Timer.quantum*0.5; Erelease = false; }; /* --------------- Elevator Release / Center -------------------*/ var EmoveCt = function() { Erelease = true; if(E > 0.03) E-=Oinst.Timer.quantum; if(E < -0.03) E+=Oinst.Timer.quantum; if(Math.abs(E) < 0.03) { E = 0.0; Erelease = false; } }; /* --------------------- Aileron to right ----------------------*/ var RmoveR = function() { if(R < 0.2) R+=Oinst.Timer.quantum*0.5; Rrelease = false; }; /* --------------------- Aileron to left -----------------------*/ var RmoveL = function() { if(R > -0.2) R-=Oinst.Timer.quantum*0.5; Rrelease = false; }; /* --------------- Aileron release/recenter --------------------*/ var RmoveCt = function() { Rrelease = true; if(R > 0.03) R-=Oinst.Timer.quantum; if(R < -0.03) R+=Oinst.Timer.quantum; if(Math.abs(R) < 0.03) { R = 0.0; Rrelease = false; } }; /* -------------------------------------------------------------*/ /* ------------------ ANIMATION EXPRESSIONS --------------------*/ /* -------------------------------------------------------------*/ /* ------------------- Proppeler rotation ----------------------*/ var Mrotate = function(node, t, l) { node.rotateXyz(0.0,((M*0.016)*3.14)*t,0.0, Ovoid.LOCAL, Ovoid.RELATIVE); // RPM/60 }; /* -------------------- Proppeler opacity ----------------------*/ var Mopacity = function(node, t, l) { node.opacity = (!gCrashed)?(1.2-(M/Mmx)):0.0; }; /* ------------------- Elevator rotation -----------------------*/ var Erotate = function(node, t, l) { node.rotateXyz(Ebase+E,0.0,0.0, Ovoid.LOCAL, Ovoid.ABSOLUTE); }; /* ----------- Aileron top left wing model rotation ------------*/ var RHGrotate = function(node, t, l) { node.rotateXyz(RHbaseX+R,-RHbaseY,RHbaseZ, Ovoid.WORLD, Ovoid.ABSOLUTE); }; /* ----------- Aileron top right wing model rotation -----------*/ var RHDrotate = function(node, t, l) { node.rotateXyz(RHbaseX-R,RHbaseY,-RHbaseZ, Ovoid.WORLD, Ovoid.ABSOLUTE); }; /* ---------- Aileron bottom left wing model rotation ----------*/ var RBGrotate = function(node, t, l) { node.rotateXyz(RBbaseX+R,RBbaseY,RBbaseZ, Ovoid.WORLD, Ovoid.ABSOLUTE); }; /* ---------- Aileron bottom right wing model rotation ----------*/ var RBDrotate = function(node, t, l) { node.rotateXyz(RBbaseX-R,-RBbaseY,-RBbaseZ, Ovoid.WORLD, Ovoid.ABSOLUTE); }; /* -------------------------------------------------------------*/ /* -------------------- CUSTOM FUNCTIONS -----------------------*/ /* -------------------------------------------------------------*/ /* ------------- Plane's physics oncontact func ----------------*/ var CfuncOnContact = function(node, p, n) { CM = n.dot(this.linearVelocity); /* this == PittsPhys */ CA = n.dot(AcYvect); if(CM < -5.0 || CA < 0.93) GfuncCrash(p, n); // Emitt dust at contact if(this.linearVelocity.size() > 15.0) { GfxDustB.move(p,0,1); GfxDustE.emits = true; GfxDustT = 0.3; } }; /* -------------------------------------------------------------*/ /* -------------------- GLOBAL FUNCTIONS -----------------------*/ /* -------------------------------------------------------------*/ /* --------------- Startup and restart Function ----------------*/ var GfuncStartup = function() { gCrashed = false; gVomitive = 0.0; gViewMod = 0; PittsPrpl.visible = true; A = 0.0; // Absolute Alitude G = 0.0; // G force M = 0.0; // Engine RPM E = 0.0; // Elevator angle R = 0.0; // Aulerons angle T = Tmn; // Throttle JoyZ = 0.0; AcLwTensor.m[5] = Pf; // Default value AcRwTensor.m[5] = Pf; // Default value AcVfTensor.m[3] = 0.0; // Default value PittsPhys.model = Ovoid.RIGID_LANDSCAPE; PittsPhys.clearInfluences(); PittsBody.moveXyz(0.0,2.5,0.0,0,1); PittsBody.rotateXyz(0.0,0.0,0.0,0,1); PittsBody.rotateXyz(-1.57,-1.57,0.0); PittsPhys.model = Ovoid.RIGID_MASSIVE_BOX; PittsPhys.useFriction = false; CamFlw.moveXyz(4.0,3.0,6.0,0,1); LndAcbound.setParent(CamFlw); CamAim.upvector.copy(gWorldY); GfxBurnB.setParent(Oinst.Scene.world); GfxBurnE.emits = false; GfxDustE.emits = false; GuiMsgR.visible = false; if(!SfxMute) { SfxTurb.play(); SfxVent.play(); SfxPropRun.play(); SfxPropIdle.play(); } Oinst.Scene.useCamera(CamFlw); }; /* ------------------ Show/Hide help Function ------------------*/ var GfuncShowHelp = function() { GuiHelpframe.visible = !GuiHelpframe.visible; }; /* ------------------- Cycle View Function ---------------------*/ var GfuncCycleView = function() { gViewMod++; if(gViewMod > 3) gViewMod = 0; switch(gViewMod) { case 1: Oinst.Scene.useCamera(CamEmb); LndAcbound.setParent(CamEmb); break; case 2: Oinst.Scene.useCamera(CamOrb); CamOrbLoc.move(PittsLocl.worldPosition, Ovoid.WORLD, Ovoid.ABSOLUTE); CamOrbLoc.cachTransform(); LndAcbound.setParent(CamOrb); break; case 3: Oinst.Scene.useCamera(CamFly); LndAcbound.setParent(CamFly); var m = PittsPhys.linearVelocity.size(); CamFly.move(PittsBody.worldPosition, Ovoid.WORLD, Ovoid.ABSOLUTE); CamFly.moveXyz(AcZvect.v[0]*(30.0+m), AcZvect.v[1]*(30.0+m), AcZvect.v[2]*(30.0+m),Ovoid.WORLD, Ovoid.RELATIVE); CamFly.moveXyz(AcXvect.v[0], AcXvect.v[1], AcXvect.v[2],Ovoid.WORLD, Ovoid.RELATIVE); CamFly.cachTransform(); CamAim.upvector.copy(gWorldY); break; default: Oinst.Scene.useCamera(CamFlw); LndAcbound.setParent(CamFlw); CamFlw.move(PittsBody.worldPosition, Ovoid.WORLD, Ovoid.ABSOLUTE); CamFlw.moveXyz(AcZvect.v[0]*-14.0, AcZvect.v[1]*-14.0, AcZvect.v[2]*-14.0,Ovoid.WORLD, Ovoid.RELATIVE); CamFlw.moveXyz(AcYvect.v[0], AcYvect.v[1]+2.0, AcYvect.v[2],Ovoid.WORLD, Ovoid.RELATIVE); CamFlw.cachTransform(); CamAim.upvector.copy(AcYvect); break; } }; /* ---------------------- Crash function -----------------------*/ var GfuncCrash = function(p, n) { if(!SfxMute) { SfxCrash.play(); SfxTurb.stop(); SfxVent.stop(); SfxPropRun.stop(); SfxPropIdle.stop(); } PittsPrpl.visible = false; // Emitt smoke at contact GfxDustB.move(p,0,1); GfxDustE.emits = true; GfxDustT = 0.3; // Apply violent impulse according to contact angle gVx.crossOf(n, PittsPhys.linearVelocity); gVec.crossOf(gVx, n); gVec.normalize(); gVec.scaleBy(-8000.0*PittsPhys.linearVelocity.size()); PittsPhys.impulse(gVec, p, 0); // Make fan invisible // Use friction for collision PittsPhys.useFriction = true; // Add black smoke GfxBurnB.setParent(PittsBody); GfxBurnE.emits = true; GfxSmokE.emits = false; // Disable engine M = 0.0; // Engine RPM T = 0.0; // Throttle // Show "R for Restart" message GuiMsgR.visible = true; // Crashed state enable gCrashed = true; }; /* ------------------- Toggle Smoke function -------------------*/ var GfuncToggleSmoke = function() { GfxSmokE.emits = !GfxSmokE.emits; } /* -------------------- Mute sound Function --------------------*/ var GfuncSxfMute = function() { if(SfxMute) { SfxTurb.play(); SfxVent.play(); SfxPropRun.play(); SfxPropIdle.play(); SfxMute = false; } else { SfxTurb.stop(); SfxVent.stop(); SfxPropRun.stop(); SfxPropIdle.stop(); SfxMute = true; } }; /* -------------------------------------------------------------*/ /* -------- OVOID.JS INSTANCE CREATION AND DEFINES -------------*/ /* -------------------------------------------------------------*/ /* ------ Config object for Ovoid.JS instance creation ---------*/ var cfg = Ovoid.newConfig(); cfg.opt_logLevel = 2; cfg.opt_showHud = false; cfg.opt_renderLopLevel = 2; cfg.opt_renderAdaptLop = false; cfg.opt_renderPerLightPass = false; cfg.opt_renderShadowCasting = false; cfg.opt_renderPickingMode = 0; cfg.opt_preloadStyle = 2; cfg.opt_renderClearColor = [0.0, 0.5, 1.0, 1.0]; cfg.opt_renderAmbientColor = [0.2, 0.3, 0.4, 1.0]; cfg.opt_renderFogColor = [0.8, 0.9, 1.2, 1.0]; cfg.opt_renderFogDensity = 0.00008; cfg.opt_renderCullFace = 1; cfg.opt_physicsIterativeSolver = false; cfg.opt_sceneIntersectDetect = false; cfg.opt_audioDopplerFactor = 50.0; // cfg.opt_customErrContent = "<img src=\"image.gif\" onerror=\"window.location.replace('http://www.ovoid.org/js/demo_err.html');\">"; /* --------------------- Instance creation ---------------------*/ var Oinst = Ovoid.newInstance("pittsdemo2", "canvas", cfg); if(Oinst) { // Defines variables for render layers var RLtree = 4; var RLclou = 3; var RLland = 0; var RLbat1 = 1; var RLbat2 = 2; /* ---------------------- data preloading ----------------------*/ // Loading OJS scene data Oinst.includeOjson("http://www.ovoid.org/js/rel/2.0/demos/pitts/ojs/pittsdemo2-avion.ojs"); Oinst.includeOjson("http://www.ovoid.org/js/rel/2.0/demos/pitts/ojs/pittsdemo2-gui.ojs"); Oinst.includeOjson("http://www.ovoid.org/js/rel/2.0/demos/pitts/ojs/pittsdemo2-terrain.ojs"); // Preload custom shaders in stock without using them, we will plug them later Oinst.includeShader("TERRAIN_1P", "http://www.ovoid.org/js/rel/2.0/demos/pitts/glsl/pitts_terrain.vs", "http://www.ovoid.org/js/rel/2.0/demos/pitts/glsl/pitts_terrain_1p.fs", null, Ovoid.PIPE_L2_GEOMETRY_1P, RLland); Oinst.includeShader("TREES_1P", "http://www.ovoid.org/js/rel/2.0/demos/pitts/glsl/pitts_trees.vs", "http://www.ovoid.org/js/rel/2.0/demos/pitts/glsl/pitts_trees_1p.fs", null, Ovoid.PIPE_L2_GEOMETRY_1P, RLtree); Oinst.includeShader("CLOUDS_1P", "http://www.ovoid.org/js/rel/2.0/demos/pitts/glsl/pitts_clouds.vs", "http://www.ovoid.org/js/rel/2.0/demos/pitts/glsl/pitts_clouds_1p.fs", null, Ovoid.PIPE_L2_GEOMETRY_1P, RLclou); Oinst.includeShader("BATIMENTS_1P", "http://www.ovoid.org/js/rel/2.0/demos/pitts/glsl/pitts_batiments.vs", "http://www.ovoid.org/js/rel/2.0/demos/pitts/glsl/pitts_batiments_1p.fs", null, Ovoid.PIPE_L2_GEOMETRY_1P, RLbat1); // Preload audio sources Oinst.includeAudio("SfxPropIdleSrc", "http://www.ovoid.org/js/rel/2.0/demos/pitts/ogg/propeller-idle.ogg"); Oinst.includeAudio("SfxPropRunSrc", "http://www.ovoid.org/js/rel/2.0/demos/pitts/ogg/propeller-run.ogg"); Oinst.includeAudio("SfxVentSrc", "http://www.ovoid.org/js/rel/2.0/demos/pitts/ogg/vent.ogg"); Oinst.includeAudio("SfxCrashSrc", "http://www.ovoid.org/js/rel/2.0/demos/pitts/ogg/crash.ogg"); /* -------------------------------------------------------------*/ /* ---------------------- onload function ----------------------*/ /* -------------------------------------------------------------*/ // This is where we put all together Oinst.onload = function() { // ------------------ Plug custom shaders -------------------- // We also plug shader to another layer this.Drawer.plugShader("BATIMENTS_1P", Ovoid.PIPE_L2_GEOMETRY_1P, RLbat2); this.Drawer.plugShader("BATIMENTS_1P", Ovoid.PIPE_L1_GEOMETRY_1P, RLbat2); this.Drawer.plugShader("BATIMENTS_1P", Ovoid.PIPE_L0_GEOMETRY_1P, RLbat2); // ----------------- Retrieve GUI elements ------------------- GuiGaugA = this.Scene.findNode("GuiGaugA"); GuiLocApa = this.Scene.findNode("GuiLocApa"); GuiLocAga = this.Scene.findNode("GuiLocAga"); GuiGaugApa = this.Scene.findNode("GuiGaugApa"); GuiGaugAga = this.Scene.findNode("GuiGaugAga"); GuiGaugV = this.Scene.findNode("GuiGaugV"); GuiLocVga = this.Scene.findNode("GuiLocVga"); GuiGaugVga = this.Scene.findNode("GuiGaugVga"); GuiGaugM = this.Scene.findNode("GuiGaugM"); GuiLocMga = this.Scene.findNode("GuiLocMga"); GuiGaugMga = this.Scene.findNode("GuiGaugMga"); GuiGaugG = this.Scene.findNode("GuiGaugG"); GuiLocGga = this.Scene.findNode("GuiLocGga"); GuiGaugGga = this.Scene.findNode("GuiGaugGga"); GuiMsgR = this.Scene.findNode("GuiMsgR"); GuiMsgR.visible = false; GuiWrnOS = this.Scene.findNode("GuiWrnOS"); GuiWrnOS.visible = false; GuiThrottleP = this.Scene.findNode("GuiThrottleP"); GuiThrottleM = this.Scene.findNode("GuiThrottleM"); GuiWatermark = this.Scene.findNode("watermarkLayer"); GuiHelpframe = this.Scene.findNode("helpframeLayer"); // -------------- Retrieve Landscape elements ---------------- LndLandGrp = this.Scene.findNode("landGrp"); LndTreeGrp = this.Scene.findNode("treeGrp"); LndAcbound = this.Scene.findNode("activeRangeSphere"); // ------------- Retrieve Pitts Model elements --------------- PittsBody = this.Scene.findNode("pittss1-fuselage"); PittsPhys = this.Scene.findNode("pittss1-fuselagePhysics"); PittsPhys.setMass(W); PittsPhys.setDamping(0.95, 0.1); PittsPhys.restitution = 0.0; PittsPhys.oncontact = CfuncOnContact; PittsLocl = this.Scene.findNode("pitts-centre"); PittsPrpl = this.Scene.findNode("pittss1-helices"); PittsPMat = this.Scene.findNode("pittss1MaterialHelices"); // ----------------- Create GFX elements --------------------- var smokeTex = this.Scene.newNode(Ovoid.TEXTURE, "smokeTexture"); smokeTex.loadSource("cloud.png", 1); GfxBurnE = this.Scene.newNode(Ovoid.EMITTER, "BurnSmokeEmt"); GfxBurnE.setColoursRgba(0.1, 0.1, 0.1, 1.0, 0.1, 0.1, 0.1, 0.0); GfxBurnE.setSizes(1.0, 2.0); GfxBurnE.setSprite(smokeTex); GfxBurnE.mass = -0.2; GfxBurnE.life = 3.0; GfxBurnE.rate = 100.0; GfxBurnE.damping = 0.5; GfxBurnE.velocity = 1.0; GfxBurnE.model = Ovoid.DIFFUSE; GfxBurnE.billboard = true; GfxBurnE.emits = false; GfxBurnB = this.Scene.newNode(Ovoid.BODY, "BurnSmokeBdy"); GfxBurnB.setShape(GfxBurnE); GfxBurnB.renderLayer = 5; GfxBurnB.renderAlpha = true; GfxDustE = this.Scene.newNode(Ovoid.EMITTER, "DustSmokeEmt"); GfxDustE.setColoursRgba(0.4, 0.4, 0.35, 1.0, 0.4, 0.4, 0.35, 0.0); GfxDustE.setSizes(0.8, 2.0); GfxDustE.setSprite(smokeTex); GfxDustE.mass = -0.1; GfxDustE.life = 3.0; GfxDustE.rate = 500.0; GfxDustE.damping = 0.5; GfxDustE.velocity = 3.0; GfxDustE.model = Ovoid.DIFFUSE; GfxDustE.billboard = true; GfxDustE.emits = false; GfxDustB = this.Scene.newNode(Ovoid.BODY, "DustSmokeBdy"); GfxDustB.setShape(GfxDustE); GfxDustB.renderLayer = 5; GfxDustB.renderAlpha = true; GfxSmokE = this.Scene.newNode(Ovoid.EMITTER, "TailSmokeEmt"); GfxSmokE.setColoursRgba(0.9, 0.9, 0.9, 0.9, 0.6, 0.6, 0.6, 0.0); GfxSmokE.setSizes(1.0, 40.0); GfxSmokE.setSprite(smokeTex); GfxSmokE.mass = -0.1; GfxSmokE.life = 11.0; GfxSmokE.rate = 60.0; GfxSmokE.damping = 0.99; GfxSmokE.velocity = 1.8; GfxSmokE.model = Ovoid.DIFFUSE; GfxSmokE.billboard = true; GfxSmokE.emits = false; GfxSmokB = this.Scene.newNode(Ovoid.BODY, "TailSmokeBdy"); GfxSmokB.setShape(GfxSmokE); GfxSmokB.renderLayer = 5; GfxSmokB.renderAlpha = true; GfxSmokB.setParent(PittsBody); GfxSmokB.moveXyz(0.0,0.0,-0.8); // ----------------- Create SFX elements --------------------- var audio; audio = this.Scene.findNode("SfxPropIdleSrc"); SfxPropIdle = this.Scene.newNode(Ovoid.SOUND, "SfxPropIdle"); SfxPropIdle.setAudio(audio); SfxPropIdle.setParent(PittsBody); SfxPropIdle.spatialize(true); SfxPropIdle.setPannerDist(5.0, 1000.0, 1.0); SfxPropIdle.setLoop(true); SfxPropIdle.volum(0.2); audio = this.Scene.findNode("SfxPropRunSrc"); SfxPropRun = this.Scene.newNode(Ovoid.SOUND, "SfxPropRun"); SfxPropRun.setAudio(audio); SfxPropRun.setParent(PittsBody); SfxPropRun.spatialize(true); SfxPropRun.setPannerDist(5.0, 1000.0, 0.2); SfxPropRun.setLoop(true); SfxPropRun.volum(0.0); audio = this.Scene.findNode("SfxVentSrc"); SfxVent = this.Scene.newNode(Ovoid.SOUND, "SfxVent"); SfxVent.setAudio(audio); SfxVent.setParent(PittsBody); SfxVent.spatialize(true); SfxVent.setPannerDist(5.0, 1000.0, 1.0); SfxVent.setLoop(true); SfxVent.volum(0.0); audio = this.Scene.findNode("SfxVentSrc"); SfxTurb = this.Scene.newNode(Ovoid.SOUND, "SfxTurb"); SfxTurb.setAudio(audio); SfxTurb.setParent(PittsBody); SfxTurb.spatialize(true); SfxTurb.setPannerDist(5.0, 1000.0, 1.0); SfxTurb.setLoop(true); SfxTurb.volum(0.0); audio = this.Scene.findNode("SfxCrashSrc"); SfxCrash = this.Scene.newNode(Ovoid.SOUND, "SfxCrash"); SfxCrash.setAudio(audio); SfxCrash.setParent(PittsBody); SfxCrash.spatialize(true); SfxCrash.setPannerDist(5.0, 1000.0, 1.0); SfxCrash.setLoop(false); SfxCrash.volum(1.0); // ------------- Create Camera/View Elements ----------------- CamFlw = this.Scene.newNode(Ovoid.CAMERA, "CameraFlw"); CamFlw.setClipping(0.1, -1.0); CamFlw.setFov(60); CamFly = this.Scene.newNode(Ovoid.CAMERA, "CameraFly"); CamFly.setClipping(0.1, -1.0); CamFly.setFov(20); CamEmb = this.Scene.newNode(Ovoid.CAMERA, "CameraEmb"); CamEmb.setClipping(0.1, -1.0); CamEmb.moveXyz(0.0,0.0,0.0,1,1); CamEmb.rotateXyz(0.0,0.0,0.0,1,1); CamEmb.rotateXyz(1.8,0.0,0.0); CamEmb.moveXyz(0.0,-1.9,0.3); CamEmb.setFov(90); CamEmb.setParent(PittsBody); CamOrbLoc = this.Scene.newNode(Ovoid.TRANSFORM, "CameraOrbLoc"); CamOrb = this.Scene.newNode(Ovoid.CAMERA, "CameraOrb"); CamOrb.setClipping(0.1, -1.0); CamOrb.setFov(60); CamOrb.setParent(CamOrbLoc); CamOrb.moveXyz(7.0,0.0,0.0); CamOrb.rotateXyz(0.0,1.57,0.0); CamAim = this.Scene.newNode(Ovoid.AIM, "CamAim"); CamAim.setTarget(CamFlw); CamAim.setTarget(CamFly); CamAim.aimat = PittsBody; // ------------- Create & Assign expressions ----------------- var expr; // Expression Handle // Create and assing Expression to Engine Fan model expr = this.Scene.newNode(Ovoid.EXPRESSION, "MRExpr"); expr.addExpression(Mrotate); expr.play(1.0); expr.setTarget(this.Scene.findNode("pittss1-nez")); expr = this.Scene.newNode(Ovoid.EXPRESSION, "MOExpr"); expr.addExpression(Mopacity); expr.play(1.0); expr.setTarget(PittsPMat); // Create and assign Expression to Elevator models expr = this.Scene.newNode(Ovoid.EXPRESSION, "EExpr"); expr.addExpression(Erotate); expr.play(1.0); expr.setTarget(this.Scene.findNode("pittss1-gouvprof")); // Create and assign Expression to top Left Ailerons models expr = this.Scene.newNode(Ovoid.EXPRESSION, "RHGExpr"); expr.addExpression(RHGrotate); expr.play(1.0); expr.setTarget(this.Scene.findNode("pittss1-aileronhg")); // Create and assign Expression to bottom Left Ailerons models expr = this.Scene.newNode(Ovoid.EXPRESSION, "RBGExpr"); expr.addExpression(RBGrotate); expr.play(1.0); expr.setTarget(this.Scene.findNode("pittss1-aileronbg")); // Create and assign Expression to top Right Ailerons models expr = this.Scene.newNode(Ovoid.EXPRESSION, "RHDExpr"); expr.addExpression(RHDrotate); expr.play(1.0); expr.setTarget(this.Scene.findNode("pittss1-aileronhd")); // Create and assign Expression to bottom Right Ailerons models expr = this.Scene.newNode(Ovoid.EXPRESSION, "RBDExpr"); expr.addExpression(RBDrotate); expr.play(1.0); expr.setTarget(this.Scene.findNode("pittss1-aileronbd")); // -------------- Bind keys / Input triggers ----------------- // Bind up and down arrow keys for Elevator this.Input.setTrigger(null, 38, Ovoid.HELD, EmoveUp); this.Input.setTrigger(null, 38, Ovoid.UP, EmoveCt); this.Input.setTrigger(null, 40, Ovoid.HELD, EmoveDn); this.Input.setTrigger(null, 40, Ovoid.UP, EmoveCt); // Bind left and right arrow keys for Ailerons this.Input.setTrigger(null, 37, Ovoid.HELD, RmoveL); this.Input.setTrigger(null, 37, Ovoid.UP, RmoveCt); this.Input.setTrigger(null, 39, Ovoid.HELD, RmoveR); this.Input.setTrigger(null, 39, Ovoid.UP, RmoveCt); // Bind pgup and pgdwn keys for Engine this.Input.setTrigger(null, 33, Ovoid.HELD, Mincr); this.Input.setTrigger(null, 34, Ovoid.HELD, Mdecr); this.Input.setTrigger(null, Ovoid.KB_P, Ovoid.HELD, Mincr); this.Input.setTrigger(null, Ovoid.KB_M, Ovoid.HELD, Mdecr); // Bind S for Start/Stop smoke gen this.Input.setTrigger(null, Ovoid.KB_S, Ovoid.DOWN, GfuncToggleSmoke); // Bind C for View cycle this.Input.setTrigger(null, Ovoid.KB_C, Ovoid.DOWN, GfuncCycleView); // Bind R for restart this.Input.setTrigger(null, Ovoid.KB_R, Ovoid.DOWN, GfuncStartup); // Bind X for mute sound this.Input.setTrigger(null, Ovoid.KB_X, Ovoid.DOWN, GfuncSxfMute); // Bind Esc for Show/Hide help this.Input.setTrigger(null, Ovoid.KB_ESCAPE, Ovoid.DOWN, GfuncShowHelp); // Bind nunpad for orbit camera this.Input.setTrigger(null, 104, Ovoid.HELD, function(){CamOrbLoc.rotateXyz(0.0,0.0,0.05,1,0);}); this.Input.setTrigger(null, 98, Ovoid.HELD, function(){CamOrbLoc.rotateXyz(0.0,0.0,-0.05,1,0);}); this.Input.setTrigger(null, 100, Ovoid.HELD, function(){CamOrbLoc.rotateXyz(0.0,-0.05,0.0,0,0);}); this.Input.setTrigger(null, 102, Ovoid.HELD, function(){CamOrbLoc.rotateXyz(0.0,0.05,0.0,0,0);}); // Initialize GfuncStartup(); }; // Oinst.onload() /* -------------------------------------------------------------*/ /* ---------------------- onloop function ----------------------*/ /* -------------------------------------------------------------*/ // This is where all program run. Oinst.onloop = function() { // ----------------- Update Camera & View -------------------- switch(gViewMod) { case 1: break; case 2: gVec.copy(PittsLocl.worldPosition); gVec.subBy(CamOrbLoc.worldPosition); gVec.scaleBy(this.Timer.quantum*80.0); CamOrbLoc.move(gVec, Ovoid.WORLD, Ovoid.RELATIVE); break; case 3: break; default: gVec.copy(PittsLocl.worldPosition); AcZvect.scaleBy(2.0); gVec.subBy(AcZvect); gVec.addBy(AcYvect); gVec.subBy(CamFlw.worldPosition); gVec.scaleBy(this.Timer.quantum*(AV*0.15)); CamFlw.move(gVec, Ovoid.WORLD, Ovoid.RELATIVE); gVec.copy(AcYvect); gVec.subBy(CamAim.upvector); gVec.scaleBy(this.Timer.quantum*(AV*0.15)); CamAim.upvector.addBy(gVec); CamAim.upvector.normalize(); break; } // ----------------- Update Plane Attitude ------------------- AcZvect.v[0] = PittsLocl.worldMatrix.m[4]; AcZvect.v[1] = PittsLocl.worldMatrix.m[5]; AcZvect.v[2] = PittsLocl.worldMatrix.m[6]; AcYvect.v[0] = PittsLocl.worldMatrix.m[8]; AcYvect.v[1] = PittsLocl.worldMatrix.m[9]; AcYvect.v[2] = PittsLocl.worldMatrix.m[10]; AcXvect.v[0] = PittsLocl.worldMatrix.m[0]; AcXvect.v[1] = PittsLocl.worldMatrix.m[1]; AcXvect.v[2] = PittsLocl.worldMatrix.m[2]; RV = AcZvect.dot(PittsPhys.linearVelocity); // Relative speed AV = PittsPhys.linearVelocity.size(); // Absolute speed // Local velocity vector AcVelocity.transform4InverseOf(PittsPhys.linearVelocity, PittsLocl.worldMatrix); // G load factor G = (-PittsPhys.linearVelocity.dot(AcYvect)/9.8) + AcYvect.dot(gWorldY); // Comput nausea d = Math.pow(0.8, this.Timer.quantum); gVomitive = d*gVomitive + (1-d)*(Math.abs(uG-G)*1000.0); uG = G; A = PittsBody.worldPosition.v[1]; // Aircraft altitude // -------------------- Update Controls ---------------------- if(!gCrashed) { // Recenter elevator & ailerons if(Erelease) EmoveCt(); if(Rrelease) RmoveCt(); // Update engine RPM M += (((T*Mmx) - M)*(this.Timer.quantum)); // Pull aircraft according to engine gVec.copy(AcZvect); gVec.scaleBy(Math.exp((M/Mmx)*P)); PittsPhys.impulse(gVec, AcEngineLoc, 1); // Adjust elevator portance to pich aircraft AcElTensor.m[5] = (-6.5)+(E*(Ef-RV)); // Adjust ailerons portance to roll aircraft AcLwTensor.m[5] = Pf+(R*Rf); AcRwTensor.m[5] = Pf-(R*Rf); // Check overspeed crash if(RV > 130.0) { // Make fan invisible PittsPrpl.visible = false; // Use friction for collision PittsPhys.useFriction = true; GfxBurnB.setParent(PittsBody); GfxBurnE.emits = true; M = 0.0; // Engine RPM T = 0.0; // Throttle GuiMsgR.visible = true; // Asymetric portance to twist aircraft AcLwTensor.m[5] = -500.0; gCrashed = true; } } // Apply aerodynamic tensors plane to physics node gVec.transform3Of(AcVelocity, AcLwTensor); gVec.transform4(PittsLocl.worldMatrix); PittsPhys.impulse(gVec, AcLwLoc, 1); gVec.transform3Of(AcVelocity, AcRwTensor); gVec.transform4(PittsLocl.worldMatrix); PittsPhys.impulse(gVec, AcRwLoc, 1); gVec.transform3Of(AcVelocity, AcElTensor); gVec.transform4(PittsLocl.worldMatrix); PittsPhys.impulse(gVec, AcElLoc, 1); gVec.transform3Of(AcVelocity, AcVfTensor); gVec.transform4(PittsLocl.worldMatrix); PittsPhys.impulse(gVec, AcVfLoc, 1); // --------------------- Update sounds ----------------------- var sv; SfxMpitch = M*0.0004; SfxPropIdle.pitch(0.8+SfxMpitch); SfxPropRun.volum((((SfxMpitch*2.0)-0.5) < 1.0)?((SfxMpitch*2.0)-0.5):1.0); SfxPropRun.pitch(0.3+SfxMpitch); SfxVent.volum(((RV*0.007) < 1.0)?(RV*0.007):1.0); SfxVent.pitch(RV*0.08); SfxTurb.volum((((Math.abs(G-1.0))*0.5) < 1.0)?((Math.abs(G-1.0))*0.5):1.0); SfxTurb.pitch(3.0); // ----------------- Update gauges positions ----------------- if(this.Frame.changed) { var pY = this.Frame.size.v[1]; var pX = this.Frame.size.v[0]; GuiGaugG.moveXyz(10, pY-135, 0, 1, 1); // G meter GuiGaugA.moveXyz(145, pY-135, 0, 1, 1); // Altimeter GuiGaugV.moveXyz(pX-325, pY-135, 0, 1, 1); // Airspeed GuiGaugM.moveXyz(pX-190, pY-135, 0, 1, 1); // RPM GuiThrottleP.moveXyz(pX-70, pY-260, 0, 1, 1); // Throttle pannel GuiWatermark.moveXyz((pX*0.5)-100, pY-80, 0, 1, 1); // Watermark GuiHelpframe.moveXyz((pX*0.5)-256, (pY*0.5)-256, 0, 1, 1); // Startup/help frame GuiMsgR.moveXyz((pX*0.5)-256, (pY*0.5)-256, 0, 1, 1); // Restart frame GuiWrnOS.moveXyz((pX*0.5)-256,192,0,1,1); // Overspeed warning message } // Update blades rotations GuiLocApa.rotateXyz(0.0,0.0,((A*3.28)*0.001)*0.318,1,1); // (Meter to Feet) / 1000 / 3.14 GuiLocAga.rotateXyz(0.0,0.0,((A*3.28)*0.01)*0.318,1,1); // (Meter to Feet) / 100 / 3.14 GuiLocVga.rotateXyz(0.0,0.0,((AV*1.9438)*0.00294)*3.14159,1,1); // (M/s to knots) / 340 * 3.14 GuiLocMga.rotateXyz(0.0,0.0,-1.35+((M*0.000285)*2.7),1,1); GuiLocGga.rotateXyz(0.0,0.0,-1.1+(G*0.2),1,1); // Update throttle manet position GuiThrottleM.moveXyz(0, 205-(JoyZ*205), 0, 1, 1); // Check overspeed if(RV > 110.0) { GuiWrnOS.visible = true; } else { GuiWrnOS.visible = false; } // ---------------- Update landscape and trees --------------- var i, j, k, d, r, t, l, n, s; // for all land squares i = LndLandGrp.child.length; n = 0; s = 0; while (i--) { l = LndLandGrp.child[i]; // check if land square is in the active bound sphere d = l.boundingSphere.worldCenter.dist(LndAcbound.boundingSphere.worldCenter); r = l.boundingSphere.radius+LndAcbound.boundingSphere.radius; if ( d <= r ) { j = l.shape.triangles[0].length; // for all land square's mesh polygons while (j--) { t = l.shape.triangles[0][j]; // get center and normal of polygon gPnt.copy(t.center); gPnt.transform4(l.worldMatrix); gVec.copy(t.normal); gVec.transform4(l.worldMatrix); // check if polygon orientation is correct for trees implentation if(gWorldY.dot(gVec) > 0.9 && gPnt.v[1] < 1000.0 ) { // check if polygon's center in the active bound sphere d = LndAcbound.boundingSphere.worldCenter.dist(gPnt); r = LndAcbound.boundingSphere.radius; if( d <= r ) { // Set trees's body visible LndTreeGrp.child[n].visible = true; // Exception for tree around the airbase if(i == 13 && j == 42) { gPnt.v[2]+=70.0; gPnt.v[0]-=50.0; } // Move trees's body to the polygon's center LndTreeGrp.child[n].move(gPnt, Ovoid.WORLD, Ovoid.ABSOLUTE); // Rotate tree's body according face's normal with aim-to based algorythm gVec.normalize(); gVx.crossOf(gWorldZ, gVec); // X vector gVy.crossOf(gVec, gVx); // Y vector rx, ry, rz; cy = Math.sqrt(gVx.v[0] * gVx.v[0] + gVx.v[1] * gVx.v[1]); if (cy > 0.001) { rx = Math.atan2(gVy.v[2], gVec.v[2]); ry = Math.atan2(-gVx.v[2], cy); rz = Math.atan2(gVx.v[1], gVx.v[0]); } else { rx = Math.atan2(-gVec.v[1], gVy.v[1]); ry = Math.atan2(-gVx.v[2], cy); rz = 0.0; } LndTreeGrp.child[n].rotateXyz(0.0,0.0,0.0,0,1); LndTreeGrp.child[n].rotateXyz(rx,ry,rz); n++; if(n == 24) break; } } } // Increase land square found s++; // If land square found > 4 we can stop if(s > 4) break; } } for(i = n; i < 24; i++) { LndTreeGrp.child[i].visible = false; } // ------------------- Update Gfx elements ------------------- // Contact Dust effect if(GfxDustE.emits) { GfxDustT -= Oinst.Timer.quantum; if(GfxDustT < 0.0) { GfxDustE.emits = false; } } }; // Oinst.onloop() // All defined, we start the instance. Oinst.start(); } } </script> </head> <body style="text-align:left; margin:0px;" onload="main();"> <canvas id="canvas" style="border:0; width:100%; height:100%;"/> </body> </html>