mirror of
https://github.com/openglobus/openglobus.git
synced 2025-12-08 19:25:27 +00:00
381 lines
10 KiB
JavaScript
381 lines
10 KiB
JavaScript
goog.provide('og.Renderer');
|
|
|
|
goog.require('og.math.Vector3');
|
|
goog.require('og.RendererEvents');
|
|
goog.require('og.Camera');
|
|
goog.require('og.math.Pixel');
|
|
goog.require('og.utils');
|
|
|
|
/**
|
|
* Represents high level WebGL context interface that starts WebGL handler works real time.
|
|
* @class
|
|
* @param {og.webgl.Handler} handler - WebGL handler context.
|
|
* @fires og.RendererEvents#draw
|
|
* @fires og.RendererEvents#resize
|
|
* @fires og.RendererEvents#mousemove
|
|
* @fires og.RendererEvents#mousestop
|
|
* @fires og.RendererEvents#mouselbuttonclick
|
|
* @fires og.RendererEvents#mouserbuttonclick
|
|
* @fires og.RendererEvents#mousembuttonclick
|
|
* @fires og.RendererEvents#mouselbuttondoubleclick
|
|
* @fires og.RendererEvents#mouserbuttondoubleclick
|
|
* @fires og.RendererEvents#mousembuttondoubleclick
|
|
* @fires og.RendererEvents#mouselbuttonup
|
|
* @fires og.RendererEvents#mouserbuttonup
|
|
* @fires og.RendererEvents#mousembuttonup
|
|
* @fires og.RendererEvents#mouselbuttondown
|
|
* @fires og.RendererEvents#mouserbuttondown
|
|
* @fires og.RendererEvents#mousembuttondown
|
|
* @fires og.RendererEvents#mouselbuttonhold
|
|
* @fires og.RendererEvents#mouserbuttonhold
|
|
* @fires og.RendererEvents#mousembuttonhold
|
|
* @fires og.RendererEvents#mousewheel
|
|
* @fires og.RendererEvents#touchstart
|
|
* @fires og.RendererEvents#touchend
|
|
* @fires og.RendererEvents#touchcancel
|
|
* @fires og.RendererEvents#touchmove
|
|
* @fires og.RendererEvents#doubletouch
|
|
* @fires og.RendererEvents#touchleave
|
|
* @fires og.RendererEvents#touchenter
|
|
*/
|
|
og.Renderer = function (handler) {
|
|
|
|
/**
|
|
* Div element with WebGL canvas.
|
|
* @public
|
|
* @type {object}
|
|
*/
|
|
this.div = null;
|
|
|
|
/**
|
|
* WebGL handler context.
|
|
* @public
|
|
* @type {og.webgl.Handler}
|
|
*/
|
|
this.handler = handler;
|
|
|
|
/**
|
|
* Render nodes drawing queue.
|
|
* @private
|
|
* @type {Array.<og.scene.RenderNode>}
|
|
*/
|
|
this._renderNodesArr = [];
|
|
|
|
/**
|
|
* Render nodes store for the comfortable access by the node name.
|
|
* @public
|
|
* @type {Object.<og.scene.RenderNode>}
|
|
*/
|
|
this.renderNodes = {};
|
|
|
|
/**
|
|
* Cameras array.
|
|
* @public
|
|
* @type {Array.<og.Camera>}
|
|
*/
|
|
this.cameras = [];
|
|
|
|
/**
|
|
* Current active camera.
|
|
* @public
|
|
* @type {og.Camera}
|
|
*/
|
|
this.activeCamera = null;
|
|
|
|
/**
|
|
* Renderer events. Represents interface for setting events like mousemove, draw, keypress etc.
|
|
* @public
|
|
* @type {og.RendererEvents}
|
|
*/
|
|
this.events = new og.RendererEvents(this);
|
|
|
|
/**
|
|
* OpenGlobus controls array.
|
|
* @public
|
|
* @type {Array.<og.control.Control>}
|
|
*/
|
|
this.controls = [];
|
|
|
|
/**
|
|
* Provide exchange between controls.
|
|
* @public
|
|
* @type {Object}
|
|
*/
|
|
this.controlsBag = {};
|
|
|
|
/**
|
|
* Hash table for drawing objects.
|
|
* @public
|
|
* @type {Object}
|
|
*/
|
|
this.colorObjects = {};
|
|
|
|
/**
|
|
* Color picking objects rendering queue.
|
|
* @type {Array.<og.Renderer~pickingCallback>}
|
|
*/
|
|
this._pickingCallbacks = [];
|
|
|
|
/**
|
|
* Picking objects framebuffer.
|
|
* @private
|
|
* @type {og.webgl.Framebuffer}
|
|
*/
|
|
this._pickingFramebuffer = null;
|
|
|
|
/**
|
|
* Stores current picking rgb color.
|
|
* @private
|
|
* @type {Array.<number,number,number>}
|
|
*/
|
|
this._currPickingColor = [0, 0, 0];
|
|
|
|
/**
|
|
* Stores previous picked rgb color.
|
|
* @private
|
|
* @type {Array.<number,number,number>}
|
|
*/
|
|
this._prevPickingColor = [0, 0, 0];
|
|
};
|
|
|
|
/**
|
|
* Adds picking rendering callback function.
|
|
* @param {object} sender - Callback context.
|
|
* @param {og.Renderer~pickingCallback} callback - Rendering callback.
|
|
*/
|
|
og.Renderer.prototype.addPickingCallback = function (sender, callback) {
|
|
this._pickingCallbacks.push({ "callback": callback, "sender": sender });
|
|
};
|
|
|
|
/**
|
|
* Assign picking color to the object.
|
|
* @public
|
|
* @param {Object} obj - Object that pressuming to be picked.
|
|
*/
|
|
og.Renderer.prototype.assignPickingColor = function (obj) {
|
|
var r = 0, g = 0, b = 0;
|
|
var str = "0_0_0";
|
|
while (!(r || g || b) || this.colorObjects[str]) {
|
|
r = og.math.randomi(1, 255);
|
|
g = og.math.randomi(1, 255);
|
|
b = og.math.randomi(1, 255);
|
|
str = r + "_" + g + "_" + b;
|
|
}
|
|
|
|
if (!obj._pickingColor)
|
|
obj._pickingColor = new og.math.Vector3(r, g, b);
|
|
else
|
|
obj._pickingColor.set(r, g, b);
|
|
|
|
this.colorObjects[str] = obj;
|
|
};
|
|
|
|
/**
|
|
* Removes picking color from object.
|
|
* @public
|
|
* @param {Object} obj - Object to remove picking color from.
|
|
*/
|
|
og.Renderer.prototype.clearPickingColor = function (obj) {
|
|
var c = obj._pickingColor;
|
|
if (!c.isZero()) {
|
|
delete this.colorObjects[c.x + "_" + c.y + "_" + c.z];
|
|
c.x = c.y = c.z = 0;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Get the client width.
|
|
* @public
|
|
* @returns {number}
|
|
*/
|
|
og.Renderer.prototype.getWidth = function () {
|
|
return this.handler.gl.canvas.width;
|
|
};
|
|
|
|
/**
|
|
* Get the client height.
|
|
* @public
|
|
* @returns {number}
|
|
*/
|
|
og.Renderer.prototype.getHeight = function () {
|
|
return this.handler.gl.canvas.height;
|
|
};
|
|
|
|
/**
|
|
* Get center of the screen
|
|
* @public
|
|
* @returns {og.math.Pixel}
|
|
*/
|
|
og.Renderer.prototype.getCenter = function () {
|
|
var cnv = this.handler.gl.canvas;
|
|
return new og.math.Pixel(Math.round(cnv.width * 0.5), Math.round(cnv.height * 0.5));
|
|
};
|
|
|
|
/**
|
|
* Add the given control to the renderer.
|
|
* @param {og.control.BaseControl} control - Control.
|
|
*/
|
|
og.Renderer.prototype.addControl = function (control) {
|
|
control.addTo(this);
|
|
};
|
|
|
|
/**
|
|
* Add the given controls array to the planet node.
|
|
* @param {Array.<og.control.BaseControl>} cArr - Control array.
|
|
*/
|
|
og.Renderer.prototype.addControls = function (cArr) {
|
|
for (var i = 0; i < cArr.length; i++) {
|
|
cArr[i].addTo(this);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Remove the given control from the renderer.
|
|
* @param {og.control.BaseControl} control - Control.
|
|
* @return {og.control.BaseControl|undefined}
|
|
*/
|
|
og.Renderer.prototype.removeControl = function (control) {
|
|
for (var i = 0; i < this.controls.length; i++) {
|
|
if (this.controls[i] == control) {
|
|
this.controls.splice(i, 1);
|
|
control.remove();
|
|
return control;
|
|
}
|
|
}
|
|
return undefined;
|
|
};
|
|
|
|
/**
|
|
* Renderer initialization.
|
|
* @public
|
|
*/
|
|
og.Renderer.prototype.init = function () {
|
|
var that = this;
|
|
|
|
this.handler.setFrameCallback(function () {
|
|
that.draw();
|
|
});
|
|
|
|
this.activeCamera = new og.Camera(this, { eye: new og.math.Vector3(0, 0, 12000000), look: new og.math.Vector3(0, 0, 0), up: new og.math.Vector3(0, 1, 0) });
|
|
|
|
this.events.initialize();
|
|
|
|
this.handler.onCanvasResize = function (obj) {
|
|
that.activeCamera.setAspectRatio(obj.clientWidth / obj.clientHeight);
|
|
that._pickingFramebuffer.setSize(obj.clientWidth, obj.clientHeight);
|
|
that.events.dispatch(that.events.resize, obj);
|
|
}
|
|
|
|
this._pickingFramebuffer = new og.webgl.Framebuffer(this.handler);
|
|
};
|
|
|
|
/**
|
|
* Adds render node to the renderer.
|
|
* @public
|
|
* @param {og.scene.RenderNode} renderNode - Render node.
|
|
*/
|
|
og.Renderer.prototype.addRenderNode = function (renderNode) {
|
|
if (!this.renderNodes[renderNode.name]) {
|
|
renderNode.assignRenderer(this);
|
|
this._renderNodesArr.unshift(renderNode);
|
|
this.renderNodes[renderNode.name] = renderNode;
|
|
} else {
|
|
og.console.logWrn("og.Renderer 259 - node name: " + renderNode.name + " allready exists.");
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Adds render nodes array to the renderer.
|
|
* @public
|
|
* @param {Array.<og.scene.RenderNode>} nodesArr - Render nodes array.
|
|
*/
|
|
og.Renderer.prototype.addRenderNodes = function (nodesArr) {
|
|
for (var i = 0; i < nodesArr; i++) {
|
|
this.addRenderNode(nodesArr[i]);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Draw nodes.
|
|
* @public
|
|
*/
|
|
og.Renderer.prototype.draw = function () {
|
|
|
|
this.handler.clearFrame();
|
|
|
|
this.events.handleEvents();
|
|
|
|
this.events.dispatch(this.events.draw, this);
|
|
|
|
var rn = this._renderNodesArr;
|
|
var i = rn.length;
|
|
while (i--) {
|
|
//renderNodes frame call
|
|
rn[i].drawNode();
|
|
}
|
|
|
|
this._drawPickingBuffer();
|
|
|
|
this.events.mouseState.moving = false;
|
|
this.events.touchState.moving = false;
|
|
};
|
|
|
|
/**
|
|
* Get an picking object by screen coordinates
|
|
* @params {number} x - X position
|
|
* @params {number} y - Y position
|
|
* @return {Object} Object
|
|
*/
|
|
og.Renderer.prototype.getPickingObject = function (x, y) {
|
|
var c = this._pickingFramebuffer.readPixel(x, this._pickingFramebuffer.height - y);
|
|
return this.colorObjects[c[0] + "_" + c[1] + "_" + c[2]];
|
|
};
|
|
|
|
/**
|
|
* Draw picking objects framebuffer.
|
|
* @private
|
|
*/
|
|
og.Renderer.prototype._drawPickingBuffer = function () {
|
|
this._pickingFramebuffer.activate();
|
|
|
|
var h = this.handler;
|
|
var gl = h.gl;
|
|
gl.clearColor(0.0, 0.0, 0.0, 1.0);
|
|
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
gl.disable(h.gl.BLEND);
|
|
|
|
var dp = this._pickingCallbacks;
|
|
var i = dp.length;
|
|
while (i--) {
|
|
/**
|
|
* This callback renders picking frame.
|
|
* @callback og.Renderer~pickingCallback
|
|
*/
|
|
dp[i].callback.call(dp[i].sender);
|
|
}
|
|
|
|
this._pickingFramebuffer.deactivate();
|
|
|
|
var ms = this.events.mouseState;
|
|
var ts = this.events.touchState;
|
|
|
|
if (!(ms.leftButtonHold || ms.rightButtonHold || ms.middleButtonHold)) {
|
|
this._prevPickingColor[0] = this._currPickingColor[0];
|
|
this._prevPickingColor[1] = this._currPickingColor[1];
|
|
this._prevPickingColor[2] = this._currPickingColor[2];
|
|
|
|
if (ts.x || ts.y) {
|
|
this._currPickingColor = this._pickingFramebuffer.readPixel(ts.x, this._pickingFramebuffer.height - ts.y);
|
|
} else {
|
|
this._currPickingColor = this._pickingFramebuffer.readPixel(ms.x, this._pickingFramebuffer.height - ms.y);
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Function starts rendering.
|
|
* @public
|
|
*/
|
|
og.Renderer.prototype.start = function () {
|
|
this.handler.start();
|
|
}; |