Merge pull request #59 from antstorm/rates-preview
Rates preview for the PID Tuning tab10.3.x-maintenance
commit
99106cb409
|
@ -766,6 +766,9 @@
|
||||||
"pidTuningRate": {
|
"pidTuningRate": {
|
||||||
"message": "Rate"
|
"message": "Rate"
|
||||||
},
|
},
|
||||||
|
"pidTuningRatesPreview": {
|
||||||
|
"message": "Rates Preview"
|
||||||
|
},
|
||||||
"pidTuningRcExpo": {
|
"pidTuningRcExpo": {
|
||||||
"message": "RC Expo"
|
"message": "RC Expo"
|
||||||
},
|
},
|
||||||
|
|
167
js/model.js
167
js/model.js
|
@ -2,30 +2,145 @@
|
||||||
|
|
||||||
// generate mixer
|
// generate mixer
|
||||||
var mixerList = [
|
var mixerList = [
|
||||||
{name: 'Tricopter', model: 'tricopter', image: 'tri'},
|
{name: 'Tricopter', model: 'tricopter', image: 'tri'},
|
||||||
{name: 'Quad +', model: 'quad_x', image: 'quad_p'},
|
{name: 'Quad +', model: 'quad_x', image: 'quad_p'},
|
||||||
{name: 'Quad X', model: 'quad_x', image: 'quad_x'},
|
{name: 'Quad X', model: 'quad_x', image: 'quad_x'},
|
||||||
{name: 'Bicopter', model: 'custom', image: 'bicopter'},
|
{name: 'Bicopter', model: 'custom', image: 'bicopter'},
|
||||||
{name: 'Gimbal', model: 'custom', image: 'custom'},
|
{name: 'Gimbal', model: 'custom', image: 'custom'},
|
||||||
{name: 'Y6', model: 'y6', image: 'y6'},
|
{name: 'Y6', model: 'y6', image: 'y6'},
|
||||||
{name: 'Hex +', model: 'hex_plus', image: 'hex_p'},
|
{name: 'Hex +', model: 'hex_plus', image: 'hex_p'},
|
||||||
{name: 'Flying Wing', model: 'custom', image: 'flying_wing'},
|
{name: 'Flying Wing', model: 'custom', image: 'flying_wing'},
|
||||||
{name: 'Y4', model: 'y4', image: 'y4'},
|
{name: 'Y4', model: 'y4', image: 'y4'},
|
||||||
{name: 'Hex X', model: 'hex_x', image: 'hex_x'},
|
{name: 'Hex X', model: 'hex_x', image: 'hex_x'},
|
||||||
{name: 'Octo X8', model: 'custom', image: 'octo_x8'},
|
{name: 'Octo X8', model: 'custom', image: 'octo_x8'},
|
||||||
{name: 'Octo Flat +', model: 'custom', image: 'octo_flat_p'},
|
{name: 'Octo Flat +', model: 'custom', image: 'octo_flat_p'},
|
||||||
{name: 'Octo Flat X', model: 'custom', image: 'octo_flat_x'},
|
{name: 'Octo Flat X', model: 'custom', image: 'octo_flat_x'},
|
||||||
{name: 'Airplane', model: 'custom', image: 'airplane'},
|
{name: 'Airplane', model: 'custom', image: 'airplane'},
|
||||||
{name: 'Heli 120', model: 'custom', image: 'custom'},
|
{name: 'Heli 120', model: 'custom', image: 'custom'},
|
||||||
{name: 'Heli 90', model: 'custom', image: 'custom'},
|
{name: 'Heli 90', model: 'custom', image: 'custom'},
|
||||||
{name: 'V-tail Quad', model: 'quad_vtail', image: 'vtail_quad'},
|
{name: 'V-tail Quad', model: 'quad_vtail', image: 'vtail_quad'},
|
||||||
{name: 'Hex H', model: 'custom', image: 'custom'},
|
{name: 'Hex H', model: 'custom', image: 'custom'},
|
||||||
{name: 'PPM to SERVO', model: 'custom', image: 'custom'},
|
{name: 'PPM to SERVO', model: 'custom', image: 'custom'},
|
||||||
{name: 'Dualcopter', model: 'custom', image: 'custom'},
|
{name: 'Dualcopter', model: 'custom', image: 'custom'},
|
||||||
{name: 'Singlecopter', model: 'custom', image: 'custom'},
|
{name: 'Singlecopter', model: 'custom', image: 'custom'},
|
||||||
{name: 'A-tail Quad', model: 'quad_atail', image: 'atail_quad'},
|
{name: 'A-tail Quad', model: 'quad_atail', image: 'atail_quad'},
|
||||||
{name: 'Custom', model: 'custom', image: 'custom'},
|
{name: 'Custom', model: 'custom', image: 'custom'},
|
||||||
{name: 'Custom Airplane', model: 'custom', image: 'custom'},
|
{name: 'Custom Airplane', model: 'custom', image: 'custom'},
|
||||||
{name: 'Custom Tricopter', model: 'custom', image: 'custom'}
|
{name: 'Custom Tricopter', model: 'custom', image: 'custom'}
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
// 3D model
|
||||||
|
var Model = function (wrapper, canvas) {
|
||||||
|
var useWebGLRenderer = this.canUseWebGLRenderer();
|
||||||
|
|
||||||
|
this.wrapper = wrapper;
|
||||||
|
this.canvas = canvas;
|
||||||
|
|
||||||
|
if (useWebGLRenderer) {
|
||||||
|
this.renderer = new THREE.WebGLRenderer({ canvas: this.canvas[0], alpha: true, antialias: true });
|
||||||
|
} else {
|
||||||
|
this.renderer = new THREE.CanvasRenderer({ canvas: this.canvas[0], alpha: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize render size for current canvas size
|
||||||
|
this.renderer.setSize(this.wrapper.width() * 2, this.wrapper.height() * 2);
|
||||||
|
|
||||||
|
// load the model including materials
|
||||||
|
var model_file = useWebGLRenderer ? mixerList[CONFIG.multiType - 1].model : 'fallback';
|
||||||
|
|
||||||
|
// Temporary workaround for 'custom' model until akfreak's custom model is merged.
|
||||||
|
if (model_file == 'custom') { model_file = 'fallback'; }
|
||||||
|
|
||||||
|
// setup scene
|
||||||
|
this.scene = new THREE.Scene();
|
||||||
|
|
||||||
|
// modelWrapper adds an extra axis of rotation to avoid gimbal lock with the euler angles
|
||||||
|
this.modelWrapper = new THREE.Object3D();
|
||||||
|
|
||||||
|
// stationary camera
|
||||||
|
this.camera = new THREE.PerspectiveCamera(60, this.wrapper.width() / this.wrapper.height(), 1, 10000);
|
||||||
|
|
||||||
|
// move camera away from the model
|
||||||
|
this.camera.position.z = 125;
|
||||||
|
|
||||||
|
// some light
|
||||||
|
var light = new THREE.AmbientLight(0x404040);
|
||||||
|
var light2 = new THREE.DirectionalLight(new THREE.Color(1, 1, 1), 1.5);
|
||||||
|
light2.position.set(0, 1, 0);
|
||||||
|
|
||||||
|
// add camera, model, light to the foreground scene
|
||||||
|
this.scene.add(light);
|
||||||
|
this.scene.add(light2);
|
||||||
|
this.scene.add(this.camera);
|
||||||
|
this.scene.add(this.modelWrapper);
|
||||||
|
|
||||||
|
// Load model file, add to scene and render it
|
||||||
|
this.loadJSON(model_file, (function (model) {
|
||||||
|
this.model = model;
|
||||||
|
|
||||||
|
this.modelWrapper.add(model);
|
||||||
|
this.scene.add(this.modelWrapper);
|
||||||
|
|
||||||
|
this.render();
|
||||||
|
}).bind(this));
|
||||||
|
};
|
||||||
|
|
||||||
|
Model.prototype.loadJSON = function (model_file, callback) {
|
||||||
|
var loader = new THREE.JSONLoader();
|
||||||
|
|
||||||
|
loader.load('./resources/models/' + model_file + '.json', function (geometry, materials) {
|
||||||
|
var modelMaterial = new THREE.MeshFaceMaterial(materials),
|
||||||
|
model = new THREE.Mesh(geometry, modelMaterial);
|
||||||
|
|
||||||
|
model.scale.set(15, 15, 15);
|
||||||
|
|
||||||
|
callback(model);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Model.prototype.canUseWebGLRenderer = function () {
|
||||||
|
// webgl capability detector
|
||||||
|
// it would seem the webgl "enabling" through advanced settings will be ignored in the future
|
||||||
|
// and webgl will be supported if gpu supports it by default (canary 40.0.2175.0), keep an eye on this one
|
||||||
|
var detector_canvas = document.createElement('canvas');
|
||||||
|
|
||||||
|
return window.WebGLRenderingContext && (detector_canvas.getContext('webgl') || detector_canvas.getContext('experimental-webgl'))
|
||||||
|
};
|
||||||
|
|
||||||
|
Model.prototype.rotateTo = function (x, y, z) {
|
||||||
|
if (!this.model) { return; }
|
||||||
|
|
||||||
|
this.model.rotation.x = x;
|
||||||
|
this.modelWrapper.rotation.y = y;
|
||||||
|
this.model.rotation.z = z;
|
||||||
|
|
||||||
|
this.render();
|
||||||
|
};
|
||||||
|
|
||||||
|
Model.prototype.rotateBy = function (x, y, z) {
|
||||||
|
if (!this.model) { return; }
|
||||||
|
|
||||||
|
this.model.rotateX(x);
|
||||||
|
this.model.rotateY(y);
|
||||||
|
this.model.rotateZ(z);
|
||||||
|
|
||||||
|
this.render();
|
||||||
|
};
|
||||||
|
|
||||||
|
Model.prototype.render = function () {
|
||||||
|
if (!this.model) { return; }
|
||||||
|
|
||||||
|
// draw
|
||||||
|
this.renderer.render(this.scene, this.camera);
|
||||||
|
};
|
||||||
|
|
||||||
|
// handle canvas resize
|
||||||
|
Model.prototype.resize = function () {
|
||||||
|
this.renderer.setSize(this.wrapper.width() * 2, this.wrapper.height() * 2);
|
||||||
|
|
||||||
|
this.camera.aspect = this.wrapper.width() / this.wrapper.height();
|
||||||
|
this.camera.updateProjectionMatrix();
|
||||||
|
|
||||||
|
this.render();
|
||||||
|
};
|
||||||
|
|
|
@ -177,11 +177,6 @@
|
||||||
border-top-right-radius: 3px;
|
border-top-right-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-pid_tuning .tpa {
|
|
||||||
/*border: 0px solid #ccc; */
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-pid_tuning .rc_curve {
|
.tab-pid_tuning .rc_curve {
|
||||||
float: right;
|
float: right;
|
||||||
width: calc(100% - 2px); /* - ( "virtual" margin) */
|
width: calc(100% - 2px); /* - ( "virtual" margin) */
|
||||||
|
@ -580,3 +575,21 @@
|
||||||
margin-top: -28px;
|
margin-top: -28px;
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tab-pid_tuning .rates_preview_cell {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 0;
|
||||||
|
padding-bottom: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-pid_tuning .rates_preview {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-image: url(../images/paper.jpg);
|
||||||
|
background-size: 100%;
|
||||||
|
background-position: center;
|
||||||
|
}
|
||||||
|
|
|
@ -199,50 +199,74 @@
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="cf_column half topspacer">
|
||||||
|
<div>
|
||||||
|
<table class="rc_curve cf">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th i18n="rcCurve"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
</tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="spacer" style="margin-top: 10px; margin-bottom: 10px;">
|
||||||
|
<div class="pitch_roll_curve">
|
||||||
|
<canvas height="120px" style="width: 100%; height: 100%"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="clear-both"></div>
|
||||||
|
</div>
|
||||||
|
<div class="topspacer">
|
||||||
|
<table class="rc_yaw_curve cf">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th i18n="rcYawCurve"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
</tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="spacer" style="margin-top: 10px; margin-bottom: 10px;">
|
||||||
|
<div class="yaw_curve">
|
||||||
|
<canvas height="120px" style="width: 100%; height: 100%"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="clear-both"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="cf_column half topspacer">
|
||||||
|
<table class="tpa cf">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th i18n="pidTuningRatesPreview"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td class="rates_preview_cell">
|
||||||
|
<div class="rates_preview">
|
||||||
|
<canvas id="canvas"></canvas>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="cf_column third_right">
|
<div class="cf_column third_right">
|
||||||
<div class="spacer_left">
|
<div class="spacer_left throttle">
|
||||||
<table class="rc_curve cf">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th i18n="rcCurve"></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
</tbody>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<div class="spacer" style="margin-top: 10px; margin-bottom: 10px;">
|
|
||||||
<div class="pitch_roll_curve">
|
|
||||||
<canvas height="120px" style="width: 100%; height: 100%"></canvas>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div class="spacer_left topspacer">
|
|
||||||
<table class="rc_yaw_curve cf">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th i18n="rcYawCurve"></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
</tbody>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<div class="spacer" style="margin-top: 10px; margin-bottom: 10px;">
|
|
||||||
<div class="yaw_curve">
|
|
||||||
<canvas height="120px" style="width: 100%; height: 100%"></canvas>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div class="spacer_left throttle topspacer">
|
|
||||||
<table class="cf">
|
<table class="cf">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -259,15 +283,23 @@
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="spacer_left topspacer">
|
||||||
|
<table class="tpa cf">
|
||||||
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th i18n="receiverThrottleMid"></th>
|
<th i18n="receiverThrottleMid"></th>
|
||||||
<th i18n="receiverThrottleExpo"></th>
|
<th i18n="receiverThrottleExpo"></th>
|
||||||
</tr>
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td><input type="number" name="mid" step="0.01" min="0" max="1" /></td>
|
<td><input type="number" name="mid" step="0.01" min="0" max="1" /></td>
|
||||||
<td><input type="number" name="expo" step="0.01" min="0" max="1" /></td>
|
<td><input type="number" name="expo" step="0.01" min="0" max="1" /></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div class="spacer_left topspacer">
|
<div class="spacer_left topspacer">
|
||||||
|
|
|
@ -315,7 +315,6 @@ TABS.pid_tuning.initialize = function (callback) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
pid_and_rc_to_form();
|
pid_and_rc_to_form();
|
||||||
|
|
||||||
var pidController_e = $('select[name="controller"]');
|
var pidController_e = $('select[name="controller"]');
|
||||||
|
@ -532,6 +531,13 @@ TABS.pid_tuning.initialize = function (callback) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Setup model for rates preview
|
||||||
|
self.initRatesPreview();
|
||||||
|
self.renderModel();
|
||||||
|
|
||||||
|
// enable RC data pulling for rates preview
|
||||||
|
GUI.interval_add('receiver_pull', self.getRecieverData, true);
|
||||||
|
|
||||||
// status data pulled via separate timer with static speed
|
// status data pulled via separate timer with static speed
|
||||||
GUI.interval_add('status_pull', function status_pull() {
|
GUI.interval_add('status_pull', function status_pull() {
|
||||||
MSP.send_message(MSP_codes.MSP_STATUS);
|
MSP.send_message(MSP_codes.MSP_STATUS);
|
||||||
|
@ -541,8 +547,42 @@ TABS.pid_tuning.initialize = function (callback) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TABS.pid_tuning.cleanup = function (callback) {
|
TABS.pid_tuning.getRecieverData = function () {
|
||||||
if (callback) {
|
MSP.send_message(MSP_codes.MSP_RC, false, false);
|
||||||
callback();
|
};
|
||||||
|
|
||||||
|
TABS.pid_tuning.initRatesPreview = function () {
|
||||||
|
this.keepRendering = true;
|
||||||
|
this.model = new Model($('.rates_preview'), $('.rates_preview canvas'));
|
||||||
|
|
||||||
|
var scale = d3.scale.linear().domain([900, 2100]);
|
||||||
|
|
||||||
|
this.rollScale = scale.range([Math.PI * 2, -Math.PI * 2]);
|
||||||
|
this.pitchScale = scale.range([Math.PI * 2, -Math.PI * 2]);
|
||||||
|
this.yawScale = scale.range([Math.PI * 2, -Math.PI * 2]);
|
||||||
|
|
||||||
|
$(window).on('resize', $.proxy(this.model.resize, this.model));
|
||||||
|
};
|
||||||
|
|
||||||
|
TABS.pid_tuning.renderModel = function () {
|
||||||
|
if (this.keepRendering) { requestAnimationFrame(this.renderModel.bind(this)); }
|
||||||
|
|
||||||
|
if (!this.clock) { this.clock = new THREE.Clock(); }
|
||||||
|
|
||||||
|
if (RC.channels[0] && RC.channels[1] && RC.channels[2]) {
|
||||||
|
var delta = this.clock.getDelta(),
|
||||||
|
roll = delta * this.rollScale(RC.channels[0]),
|
||||||
|
pitch = delta * this.pitchScale(RC.channels[1]),
|
||||||
|
yaw = delta * this.yawScale(RC.channels[2]);
|
||||||
|
|
||||||
|
this.model.rotateBy(pitch, yaw, roll);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TABS.pid_tuning.cleanup = function (callback) {
|
||||||
|
$(window).off('resize', $.proxy(this.model.resize, this.model));
|
||||||
|
|
||||||
|
this.keepRendering = false;
|
||||||
|
|
||||||
|
if (callback) callback();
|
||||||
|
};
|
||||||
|
|
110
tabs/setup.js
110
tabs/setup.js
|
@ -43,8 +43,9 @@ TABS.setup.initialize = function (callback) {
|
||||||
|
|
||||||
GUI.log(chrome.i18n.getMessage('initialSetupBackupAndRestoreApiVersion', [CONFIG.apiVersion, CONFIGURATOR.backupRestoreMinApiVersionAccepted]));
|
GUI.log(chrome.i18n.getMessage('initialSetupBackupAndRestoreApiVersion', [CONFIG.apiVersion, CONFIGURATOR.backupRestoreMinApiVersionAccepted]));
|
||||||
}
|
}
|
||||||
// initialize 3D
|
|
||||||
self.initialize3D();
|
// initialize 3D Model
|
||||||
|
self.initModel();
|
||||||
|
|
||||||
// set roll in interactive block
|
// set roll in interactive block
|
||||||
$('span.roll').text(chrome.i18n.getMessage('initialSetupAttitude', [0]));
|
$('span.roll').text(chrome.i18n.getMessage('initialSetupAttitude', [0]));
|
||||||
|
@ -191,7 +192,8 @@ TABS.setup.initialize = function (callback) {
|
||||||
roll_e.text(chrome.i18n.getMessage('initialSetupAttitude', [SENSOR_DATA.kinematics[0]]));
|
roll_e.text(chrome.i18n.getMessage('initialSetupAttitude', [SENSOR_DATA.kinematics[0]]));
|
||||||
pitch_e.text(chrome.i18n.getMessage('initialSetupAttitude', [SENSOR_DATA.kinematics[1]]));
|
pitch_e.text(chrome.i18n.getMessage('initialSetupAttitude', [SENSOR_DATA.kinematics[1]]));
|
||||||
heading_e.text(chrome.i18n.getMessage('initialSetupAttitude', [SENSOR_DATA.kinematics[2]]));
|
heading_e.text(chrome.i18n.getMessage('initialSetupAttitude', [SENSOR_DATA.kinematics[2]]));
|
||||||
self.render3D();
|
|
||||||
|
self.renderModel();
|
||||||
self.updateInstruments();
|
self.updateInstruments();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -215,104 +217,22 @@ TABS.setup.initializeInstruments = function() {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
TABS.setup.initialize3D = function (compatibility) {
|
TABS.setup.initModel = function () {
|
||||||
var self = this,
|
this.model = new Model($('.model-and-info #canvas_wrapper'), $('.model-and-info #canvas'));
|
||||||
loader, canvas, wrapper, renderer, camera, scene, light, light2, modelWrapper, model, model_file,
|
|
||||||
useWebGlRenderer = false;
|
|
||||||
|
|
||||||
canvas = $('.model-and-info #canvas');
|
$(window).on('resize', $.proxy(this.model.resize, this.model));
|
||||||
wrapper = $('.model-and-info #canvas_wrapper');
|
};
|
||||||
|
|
||||||
// webgl capability detector
|
TABS.setup.renderModel = function () {
|
||||||
// it would seem the webgl "enabling" through advanced settings will be ignored in the future
|
var x = (SENSOR_DATA.kinematics[1] * -1.0) * 0.017453292519943295,
|
||||||
// and webgl will be supported if gpu supports it by default (canary 40.0.2175.0), keep an eye on this one
|
y = ((SENSOR_DATA.kinematics[2] * -1.0) - this.yaw_fix) * 0.017453292519943295,
|
||||||
var detector_canvas = document.createElement('canvas');
|
z = (SENSOR_DATA.kinematics[0] * -1.0) * 0.017453292519943295;
|
||||||
if (window.WebGLRenderingContext && (detector_canvas.getContext('webgl') || detector_canvas.getContext('experimental-webgl'))) {
|
|
||||||
renderer = new THREE.WebGLRenderer({canvas: canvas.get(0), alpha: true, antialias: true});
|
|
||||||
useWebGlRenderer = true;
|
|
||||||
} else {
|
|
||||||
renderer = new THREE.CanvasRenderer({canvas: canvas.get(0), alpha: true});
|
|
||||||
}
|
|
||||||
// initialize render size for current canvas size
|
|
||||||
renderer.setSize(wrapper.width()*2, wrapper.height()*2);
|
|
||||||
|
|
||||||
|
this.model.rotateTo(x, y, z);
|
||||||
// // modelWrapper adds an extra axis of rotation to avoid gimbal lock with the euler angles
|
|
||||||
modelWrapper = new THREE.Object3D()
|
|
||||||
//
|
|
||||||
// load the model including materials
|
|
||||||
if (useWebGlRenderer) {
|
|
||||||
model_file = mixerList[CONFIG.multiType - 1].model;
|
|
||||||
} else {
|
|
||||||
model_file = 'fallback'
|
|
||||||
}
|
|
||||||
|
|
||||||
// Temporary workaround for 'custom' model until akfreak's custom model is merged.
|
|
||||||
var useLegacyCustomModel = false;
|
|
||||||
if (model_file == 'custom') {
|
|
||||||
model_file = 'fallback';
|
|
||||||
useLegacyCustomModel = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// setup scene
|
|
||||||
scene = new THREE.Scene();
|
|
||||||
|
|
||||||
loader = new THREE.JSONLoader();
|
|
||||||
loader.load('./resources/models/' + model_file + '.json', function (geometry, materials) {
|
|
||||||
var modelMaterial = new THREE.MeshFaceMaterial(materials);
|
|
||||||
model = new THREE.Mesh(geometry, modelMaterial);
|
|
||||||
|
|
||||||
model.scale.set(15, 15, 15);
|
|
||||||
|
|
||||||
modelWrapper.add(model);
|
|
||||||
scene.add(modelWrapper);
|
|
||||||
});
|
|
||||||
|
|
||||||
// stationary camera
|
|
||||||
camera = new THREE.PerspectiveCamera(50, wrapper.width() / wrapper.height(), 1, 10000);
|
|
||||||
|
|
||||||
// some light
|
|
||||||
light = new THREE.AmbientLight(0x404040);
|
|
||||||
light2 = new THREE.DirectionalLight(new THREE.Color(1, 1, 1), 1.5);
|
|
||||||
light2.position.set(0, 1, 0);
|
|
||||||
|
|
||||||
// move camera away from the model
|
|
||||||
camera.position.z = 125;
|
|
||||||
|
|
||||||
// add camera, model, light to the foreground scene
|
|
||||||
scene.add(light);
|
|
||||||
scene.add(light2);
|
|
||||||
scene.add(camera);
|
|
||||||
scene.add(modelWrapper);
|
|
||||||
|
|
||||||
this.render3D = function () {
|
|
||||||
if (!model) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// compute the changes
|
|
||||||
model.rotation.x = (SENSOR_DATA.kinematics[1] * -1.0) * 0.017453292519943295;
|
|
||||||
modelWrapper.rotation.y = ((SENSOR_DATA.kinematics[2] * -1.0) - self.yaw_fix) * 0.017453292519943295;
|
|
||||||
model.rotation.z = (SENSOR_DATA.kinematics[0] * -1.0) * 0.017453292519943295;
|
|
||||||
|
|
||||||
// draw
|
|
||||||
renderer.render(scene, camera);
|
|
||||||
};
|
|
||||||
|
|
||||||
// handle canvas resize
|
|
||||||
this.resize3D = function () {
|
|
||||||
renderer.setSize(wrapper.width()*2, wrapper.height()*2);
|
|
||||||
camera.aspect = wrapper.width() / wrapper.height();
|
|
||||||
camera.updateProjectionMatrix();
|
|
||||||
|
|
||||||
self.render3D();
|
|
||||||
};
|
|
||||||
|
|
||||||
$(window).on('resize', this.resize3D);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
TABS.setup.cleanup = function (callback) {
|
TABS.setup.cleanup = function (callback) {
|
||||||
$(window).off('resize', this.resize3D);
|
$(window).off('resize', $.proxy(this.model.resize, this.model));
|
||||||
|
|
||||||
if (callback) callback();
|
if (callback) callback();
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue