kopia lustrzana https://github.com/cyoung/stratux
353 wiersze
10 KiB
JavaScript
353 wiersze
10 KiB
JavaScript
function ahrsRenderer(location_id) {
|
|
this.gcontext = {}; // globals
|
|
this.gl = null;
|
|
|
|
this.width = -1;
|
|
this.height = -1;
|
|
|
|
this.locationID = location_id;
|
|
this.canvas = document.getElementById(location_id);
|
|
this.canvas_container = document.getElementById(location_id).parentElement;
|
|
}
|
|
|
|
ahrsRenderer.prototype = {
|
|
constructor: ahrsRenderer,
|
|
|
|
_init_canvas: function () {
|
|
var gl = initWebGL(this.locationID);
|
|
if (!gl)
|
|
return;
|
|
this.gl = gl;
|
|
|
|
vertex_shader = ' \
|
|
uniform mat4 u_modelViewProjMatrix; \
|
|
uniform mat4 u_normalMatrix; \
|
|
uniform vec3 lightDir; \
|
|
attribute vec3 vNormal; \
|
|
attribute vec4 vColor; \
|
|
attribute vec4 vPosition; \
|
|
varying float v_Dot; \
|
|
varying vec4 v_Color; \
|
|
void main() { \
|
|
gl_Position = u_modelViewProjMatrix * vPosition; \
|
|
v_Color = vColor; \
|
|
vec4 transNormal = u_normalMatrix * vec4(vNormal, 1); \
|
|
v_Dot = max(dot(transNormal.xyz, lightDir), 0.0); \
|
|
}';
|
|
|
|
color_shader = '\
|
|
precision mediump float; \
|
|
varying float v_Dot; \
|
|
varying vec4 v_Color; \
|
|
void main() { \
|
|
gl_FragColor = vec4(v_Color.xyz * v_Dot, v_Color.a); \
|
|
}';
|
|
|
|
var vertexShader = loadShaderVertexScript(gl, vertex_shader);
|
|
var colorShader = loadShaderFragmentScript(gl, color_shader);
|
|
|
|
var program = gl.createProgram();
|
|
|
|
gl.attachShader(program, vertexShader);
|
|
gl.attachShader(program, colorShader);
|
|
|
|
// Bind attributes
|
|
gl.bindAttribLocation(program, 0, "vNormal");
|
|
gl.bindAttribLocation(program, 1, "vColor");
|
|
gl.bindAttribLocation(program, 2, "vPosition");
|
|
|
|
gl.linkProgram(program);
|
|
|
|
var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
|
|
if (!linked && !gl.isContextLost()) {
|
|
// something went wrong with the link
|
|
var error = gl.getProgramInfoLog(program);
|
|
log("Error in program linking:" + error);
|
|
gl.deleteProgram(program);
|
|
gl.deleteProgram(fragmentShader);
|
|
gl.deleteProgram(vertexShader);
|
|
} else {
|
|
gl.useProgram(program);
|
|
gl.clearColor(0, 0, 0, 0) // rgba for background color
|
|
gl.clearDepth(10000); //??
|
|
|
|
if (false /* funcky blending */ ) {
|
|
gl.disable(gl.DEPTH_TEST);
|
|
gl.enable(gl.BLEND);
|
|
gl.depthFunc(gl.LESS);
|
|
gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
|
|
} else {
|
|
gl.enable(gl.DEPTH_TEST);
|
|
gl.enable(gl.BLEND);
|
|
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
|
}
|
|
|
|
this.gcontext.program = program;
|
|
}
|
|
},
|
|
|
|
init: function () {
|
|
this._init_canvas(); // init the canvas
|
|
g = this.gcontext;
|
|
gl = this.gl;
|
|
|
|
if (gl === null)
|
|
return;
|
|
|
|
// Set up a uniform variable for the shaders
|
|
gl.uniform3f(gl.getUniformLocation(g.program, "lightDir"), 0, 1, 1); // above and back
|
|
|
|
// Create a box. On return 'gl' contains a 'box' property with
|
|
// the BufferObjects containing the arrays for vertices,
|
|
// normals, texture coords, and indices.
|
|
// g.box = makeBox(gl);
|
|
g.box = this.makePaperAirplane(gl);
|
|
|
|
// Create some matrices to use later and save their locations in the shaders
|
|
g.mvMatrix = new J3DIMatrix4();
|
|
g.u_normalMatrixLoc = gl.getUniformLocation(g.program, "u_normalMatrix");
|
|
g.normalMatrix = new J3DIMatrix4();
|
|
g.u_modelViewProjMatrixLoc =
|
|
gl.getUniformLocation(g.program, "u_modelViewProjMatrix");
|
|
g.mvpMatrix = new J3DIMatrix4();
|
|
|
|
gl.enableVertexAttribArray(0); // lighting
|
|
gl.enableVertexAttribArray(1); // color
|
|
gl.enableVertexAttribArray(2); // vertices
|
|
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, g.box.vertexObject);
|
|
gl.vertexAttribPointer(2, 3, gl.FLOAT, false, 0, 0);
|
|
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, g.box.normalObject);
|
|
gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
|
|
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, g.box.colorObject);
|
|
gl.vertexAttribPointer(1, 4, gl.FLOAT, false, 0, 0); // was gl.UNSIGNED_BYTE
|
|
|
|
// Bind the index array
|
|
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, g.box.indexObject);
|
|
|
|
this.pitch = 0;
|
|
this.roll = 0;
|
|
this.heading = 0;
|
|
|
|
this.resize();
|
|
},
|
|
|
|
resize: function () {
|
|
gl = this.gl;
|
|
g = this.gcontext;
|
|
if (gl === null)
|
|
return;
|
|
|
|
var canvasWidth = this.canvas_container.offsetWidth - 12; // was (2*(this.canvas_container.offsetLeft)) // account for padding adjustments
|
|
|
|
if (canvasWidth !== this.width) {
|
|
this.width = canvasWidth;
|
|
this.height = canvasWidth *0.5;
|
|
|
|
this.canvas.width = this.width;
|
|
this.canvas.height = this.height;
|
|
// Set the viewport and projection matrix for the scene
|
|
gl.viewport(0, 0, this.width, this.height);
|
|
g.perspectiveMatrix = new J3DIMatrix4();
|
|
g.perspectiveMatrix.perspective(30, this.width / this.height, 1, 10000);
|
|
g.perspectiveMatrix.lookat( 0, 0, 4, // eye location
|
|
0, 0, 0, // focal point
|
|
0, 1, 0); // up vector
|
|
}
|
|
},
|
|
|
|
orientation: function (x, y, z) {
|
|
if (x > 360) x -= 360;
|
|
if (y > 360) y -= 360;
|
|
if (z > 360) z -= 360;
|
|
this.pitch = x; // need to reorient to level
|
|
this.roll = y;
|
|
this.heading = z;
|
|
},
|
|
|
|
animate: function (t, x, y, z) {
|
|
var FPS = 24; // we assume we can maintain a certain frame rate
|
|
var x_inc = ((x - this.pitch) / (FPS * t));
|
|
var y_inc = ((y - this.roll) / (FPS * t));
|
|
if ((z < this.heading) && (this.heading - z) > 180) {
|
|
// let the animation wrap aroung gracefully clockwise
|
|
z += 360;
|
|
} else if ((z > this.heading) && (z - this.heading) > 180) {
|
|
// let the animation wrap aroung gracefully counter clockwise
|
|
this.heading += 360;
|
|
}
|
|
var z_inc = ((z - this.heading) / (FPS * t));
|
|
var _this = this;
|
|
//console.log(z_inc);
|
|
var frames = 0;
|
|
var f = function () {
|
|
_this.pitch += x_inc;
|
|
_this.roll += y_inc;
|
|
_this.heading += z_inc;
|
|
if (frames < (FPS * t)) {
|
|
_this.draw();
|
|
frames++
|
|
window.requestAnimationFrame(f, _this.canvas); // recurse
|
|
} else {
|
|
_this.orientation(x, y, z);
|
|
}
|
|
};
|
|
f();
|
|
},
|
|
|
|
draw: function () {
|
|
this.resize();
|
|
gl = this.gl;
|
|
g = this.gcontext;
|
|
if (gl === null)
|
|
return;
|
|
|
|
// Clear the canvas
|
|
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
|
|
// Make a model/view matrix.
|
|
g.mvMatrix.makeIdentity();
|
|
|
|
g.mvMatrix.rotate(15, 1, 0, 0); // adjust viewing angle slightly by pitching the airplane up
|
|
|
|
g.mvMatrix.rotate(this.pitch, 1, 0, 0);
|
|
g.mvMatrix.rotate(-this.roll, 0, 0, 1);
|
|
g.mvMatrix.rotate(-this.heading, 0, 1, 0);
|
|
|
|
// Construct the normal matrix from the model-view matrix and pass it in
|
|
g.normalMatrix.load(g.mvMatrix);
|
|
g.normalMatrix.invert();
|
|
g.normalMatrix.transpose();
|
|
g.normalMatrix.setUniform(gl, g.u_normalMatrixLoc, false);
|
|
|
|
// Construct the model-view * projection matrix and pass it in
|
|
g.mvpMatrix.load(g.perspectiveMatrix);
|
|
g.mvpMatrix.multiply(g.mvMatrix);
|
|
g.mvpMatrix.setUniform(gl, g.u_modelViewProjMatrixLoc, false);
|
|
|
|
// Draw the object
|
|
gl.drawElements(gl.TRIANGLES, g.box.numIndices, gl.UNSIGNED_BYTE, 0);
|
|
},
|
|
|
|
makePaperAirplane: function (ctx) {
|
|
// Return an object with the following properties:
|
|
// normalObject WebGLBuffer object for normals (for lighting)
|
|
// vertexObject WebGLBuffer object for vertices (actual 3d object)
|
|
// indexObject WebGLBuffer object for indices (index of triangles within object)
|
|
// numIndices The number of indices in the indexObject (number of triangles)
|
|
|
|
// constants to make it easy to adjust the proportions and axis of the object
|
|
var LENGTH = 1; var WIDTH = 1; var DEPTH = 0.33; var SPREAD = 0.1;
|
|
var CENTERX = 0; var CENTERY = 0; var CENTERZ = 0.5;
|
|
|
|
// vertex coords array
|
|
var vertices = new Float32Array([
|
|
CENTERX, CENTERY, -LENGTH-CENTERZ,
|
|
-WIDTH, CENTERY, LENGTH-CENTERZ,
|
|
-SPREAD, CENTERY, LENGTH-CENTERZ, // left wing
|
|
|
|
CENTERX, CENTERY, -LENGTH-CENTERZ,
|
|
CENTERX, -DEPTH, LENGTH-CENTERZ,
|
|
-SPREAD, CENTERY, LENGTH-CENTERZ, // left center section
|
|
|
|
CENTERX, CENTERY, -LENGTH-CENTERZ,
|
|
CENTERX, -DEPTH, LENGTH-CENTERZ,
|
|
SPREAD, CENTERY, LENGTH-CENTERZ, // right center section
|
|
|
|
CENTERX, CENTERY, -LENGTH-CENTERZ,
|
|
WIDTH, CENTERY, LENGTH-CENTERZ,
|
|
SPREAD, CENTERY, LENGTH-CENTERZ // right wing
|
|
]);
|
|
|
|
// normal array for light reflection and shading
|
|
var normals = new Float32Array([
|
|
0, 1, 0,
|
|
0, 1, 0,
|
|
0, 1, 0, // left wing actual perpendicular is up
|
|
1, 1, 0,
|
|
1, 1, 0,
|
|
1, 1, 0, // left center section estmated perpendicular is right
|
|
-1, 1, 0,
|
|
-1, 1, 0,
|
|
-1, 1, 0, // right center section estmated perpendicular is left
|
|
0, 1, 0,
|
|
0, 1, 0,
|
|
0, 1, 0 // right wing actual perpendicular is up
|
|
]);
|
|
|
|
|
|
// index array
|
|
var indices = new Uint8Array([
|
|
0, 1, 2, // left wing
|
|
3, 4, 5, // left center section
|
|
6, 7, 8, // right center section
|
|
9, 10, 11 // right wing
|
|
]);
|
|
|
|
// Set up the array of colors for the cube's faces
|
|
// the tip of the paper aiplane is lighter and then a gradiant back to red for teh left and a green for the right
|
|
var colors_rg = new Uint8Array([
|
|
1, 0, 0, 1,
|
|
1, 0, 0, 1,
|
|
1, 0, 0, 1, // left wing
|
|
|
|
1, 0, 0, 1,
|
|
1, 0, 0, 1,
|
|
1, 0, 0, 1, // left center section
|
|
|
|
0, 1, 0, 1,
|
|
0, 1, 0, 1,
|
|
0, 1, 0, 1, // right center section
|
|
|
|
0, 1, 0, 1,
|
|
0, 1, 0, 1,
|
|
0, 1, 0, 1 // right wing
|
|
]);
|
|
|
|
var colors_bt = new Float32Array([
|
|
.21, .31, .49, 1,
|
|
.21, .31, .49, 1,
|
|
.21, .31, .49, 1,
|
|
|
|
.21, .31, .49, 1,
|
|
.21, .31, .49, 1,
|
|
.21, .31, .49, 1,
|
|
|
|
.39, .38, .22, 1,
|
|
.39, .38, .22, 1,
|
|
.39, .38, .22, 1,
|
|
|
|
.39, .38, .22, 1,
|
|
.39, .38, .22, 1,
|
|
.39, .38, .22, 1
|
|
]);
|
|
|
|
var retval = {};
|
|
|
|
retval.vertexObject = ctx.createBuffer();
|
|
ctx.bindBuffer(ctx.ARRAY_BUFFER, retval.vertexObject);
|
|
ctx.bufferData(ctx.ARRAY_BUFFER, vertices, ctx.STATIC_DRAW);
|
|
|
|
retval.normalObject = ctx.createBuffer();
|
|
ctx.bindBuffer(ctx.ARRAY_BUFFER, retval.normalObject);
|
|
ctx.bufferData(ctx.ARRAY_BUFFER, normals, ctx.STATIC_DRAW);
|
|
|
|
ctx.bindBuffer(ctx.ARRAY_BUFFER, null);
|
|
|
|
retval.indexObject = ctx.createBuffer();
|
|
ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, retval.indexObject);
|
|
ctx.bufferData(ctx.ELEMENT_ARRAY_BUFFER, indices, ctx.STATIC_DRAW);
|
|
ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, null);
|
|
|
|
// Set up the vertex buffer for the colors
|
|
retval.colorObject = gl.createBuffer();
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, retval.colorObject);
|
|
gl.bufferData(gl.ARRAY_BUFFER, colors_bt, gl.STATIC_DRAW);
|
|
|
|
retval.numIndices = indices.length;
|
|
|
|
return retval;
|
|
}
|
|
} |