j5-rc-receiver
Version:
Nintendo RC Receiver component class plugin for Johnny-Five
1,047 lines (945 loc) • 45.7 kB
HTML
<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>