diff options
author | petersont@google.com <petersont@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-12 21:00:00 +0000 |
---|---|---|
committer | petersont@google.com <petersont@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-12 21:00:00 +0000 |
commit | e512583b79e366db399a6566964412bb6e5af823 (patch) | |
tree | e15e3c05e273a0366caf2fcbc5689ae377b3e877 /o3d/samples/o3d-webgl | |
parent | a37a999f87eed77b08e7e1b6bdb86d406f31ea9b (diff) | |
download | chromium_src-e512583b79e366db399a6566964412bb6e5af823.zip chromium_src-e512583b79e366db399a6566964412bb6e5af823.tar.gz chromium_src-e512583b79e366db399a6566964412bb6e5af823.tar.bz2 |
Added textures, texture samplers and render targets to o3d-webgl. Also fixed bugs, added calls to parent class constructor to classes that didn't have them before, added a few demos to exhibit/test textures and render surfaces.
Review URL: http://codereview.chromium.org/856004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@41482 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d/samples/o3d-webgl')
31 files changed, 783 insertions, 189 deletions
diff --git a/o3d/samples/o3d-webgl/base.js b/o3d/samples/o3d-webgl/base.js index 9863ee6..9962de5 100644 --- a/o3d/samples/o3d-webgl/base.js +++ b/o3d/samples/o3d-webgl/base.js @@ -149,19 +149,31 @@ o3d.inherit = function(subClassName, superClassName) { subClass.prototype = new superClass; subClass.prototype.superClassName = superClassName; subClass.prototype.superClass = superClass; + subClass.prototype.className = subClassName; }; /** + * Utility function to remove an object from an array. + * @param {!Array} array The array. + * @param {Object} object The thing to be removed. + */ +o3d.removeFromArray = function(array, object) { + var i = array.indexOf(object); + if (i >= 0) { + array.splice(i, 1); + } +} + + +/** * If an o3d function has not been implemented in javascript yet, it should * call this function to throw an error because it's better than doing * nothing. */ o3d.notImplemented = function() { - var callerName = arguments.caller.toString(); - callerName = callerName.substr('function '.length); - callerName = ownName.substr(0, ownName.indexOf('(')); - throw 'Not implemented: ' + callerName; + debugger; + throw 'Not implemented.'; }; @@ -179,6 +191,8 @@ o3d.include('param_object'); o3d.include('param'); o3d.include('event'); o3d.include('raw_data'); +o3d.include('texture'); +o3d.include('bitmap'); o3d.include('file_request'); o3d.include('client'); o3d.include('render_node'); @@ -192,7 +206,6 @@ o3d.include('render_surface_set'); o3d.include('render_surface'); o3d.include('state'); o3d.include('draw_context'); -o3d.include('texture'); o3d.include('sampler'); o3d.include('transform'); o3d.include('pack'); diff --git a/o3d/samples/o3d-webgl/bitmap.js b/o3d/samples/o3d-webgl/bitmap.js index 6ce1df7..5e2fcfc 100644 --- a/o3d/samples/o3d-webgl/bitmap.js +++ b/o3d/samples/o3d-webgl/bitmap.js @@ -73,13 +73,20 @@ o3d.Bitmap.IMAGE = 6; o3d.Bitmap.SLICE = 7; +/** + * In webgl the bitmap object is represented by an offscreen canvas. + * @type {Canvas} + * @private + */ +o3d.Bitmap.prototype.canvas_ = null; + /** * Flips a bitmap vertically in place. - * @type {boolean} */ -o3d.Bitmap.prototype.flipVertically = false; - +o3d.Bitmap.prototype.flipVertically = function() { + this.defer_flip_vertically_to_texture_ = true; +}; /** @@ -94,7 +101,7 @@ o3d.Bitmap.prototype.flipVertically = false; */ o3d.Bitmap.prototype.generateMips = function(source_level, num_levels) { - o3d.notImplemented(); + this.defer_mipmaps_to_texture_ = true; }; @@ -113,12 +120,29 @@ o3d.Bitmap.prototype.width = 0; o3d.Bitmap.prototype.height = 0; +/** + * Instead of generating mipmaps in the bitmap object, just set this boolean + * to true, then the texture will generate mipmaps when it loads the bitmap. + * @type {boolean} + * @private + */ +o3d.Bitmap.prototype.defer_mipmaps_to_texture_ = false; + + +/** + * Instead of flipping vertically in the bitmap object, just set this boolean + * to true, then the texture will generate mipmaps when it loads the bitmap. + * @type {boolean} + * @private + */ +o3d.Bitmap.prototype.defer_flip_vertically_to_texture_ = false; + /** * The format of the bitmap (read only). - * @type {number} + * @type {!o3d.Texture.Format} */ -o3d.Bitmap.prototype.format = 0; +o3d.Bitmap.prototype.format = o3d.Texture.UNKNOWN_FORMAT; @@ -132,9 +156,9 @@ o3d.Bitmap.prototype.numMipmaps = 1; /** * The Semantic of the bitmap. - * @type {!o3d.Stream.Semantic} + * @type {!o3d.Bitmap.Semantic} */ -o3d.Bitmap.prototype.semantic = o3d.Stream.UNKNOWN_SEMANTIC; +o3d.Bitmap.prototype.semantic = o3d.Bitmap.UNKNOWN_SEMANTIC; diff --git a/o3d/samples/o3d-webgl/client.js b/o3d/samples/o3d-webgl/client.js index 5bbb7b2..95912a9 100644 --- a/o3d/samples/o3d-webgl/client.js +++ b/o3d/samples/o3d-webgl/client.js @@ -125,7 +125,10 @@ o3d.Renderer.installRenderInterval = function() { * The ClientInfo is used to get information about the client. * @constructor */ -o3d.ClientInfo = function() { }; +o3d.ClientInfo = function() { + o3d.NamedObject.call(this); +}; +o3d.inherit('ClientInfo', 'NamedObject'); /** @@ -208,6 +211,7 @@ o3d.ClientInfo.prototype.non_power_of_two_textures = true; * @constructor */ o3d.Client = function() { + o3d.NamedObject.call(this); this.root = new o3d.Transform; this.renderGraphRoot = new o3d.RenderNode; this.root = new o3d.Transform; @@ -231,7 +235,7 @@ o3d.Client.RenderCallback = goog.typedef; o3d.Client.TickCallback = goog.typedef; /** - * @type {function(!o3d.Event): void} + * @type {function(string): void} */ o3d.Client.ErrorCallback = goog.typedef; @@ -262,10 +266,13 @@ o3d.Client.prototype.then_ = 0; */ o3d.Client.prototype.root = null; + /** * Function that gets called when the client encounters an error. */ -o3d.Client.prototype.error_callback = function(error_message) {}; +o3d.Client.prototype.error_callback = function(error_message) { + alert(error_message); +}; /** @@ -300,7 +307,7 @@ o3d.Client.prototype.cleanup = function () { /** * Creates a pack object. * A pack object. - * @returns {!o3d.Pack} A new pack object. + * @return {!o3d.Pack} A new pack object. */ o3d.Client.prototype.createPack = function() { @@ -314,7 +321,7 @@ o3d.Client.prototype.createPack = * Searches the Client for an object matching the given id. * * @param {number} id The id of the object to look for. - * @returns {o3d.ObjectBase} The object or null if a object + * @return {o3d.ObjectBase} The object or null if a object * with the given id is not found. */ o3d.Client.prototype.getObjectById = @@ -327,7 +334,7 @@ o3d.Client.prototype.getObjectById = * Searches the Client for objects of a particular name and type. * @param {string} name name of object to look for. * @param {string} class_name name of class to look for. - * @returns {!Array.<!o3d.ObjectBase>} Array of objects found. + * @return {!Array.<!o3d.ObjectBase>} Array of objects found. */ o3d.Client.prototype.getObjects = function(name, class_name) { @@ -339,7 +346,7 @@ o3d.Client.prototype.getObjects = /** * Searches the Client for objects of a particular type. * @param {string} class_name name of class to look for. - * @returns {!Array.<!Object>} Array of objects found. + * @return {!Array.<!Object>} Array of objects found. */ o3d.Client.prototype.getObjectsByClassName = function(class_name) { @@ -506,6 +513,27 @@ o3d.Client.prototype.__defineSetter__('height', /** + * Initializes this client using the canvas. + * @param {Canvas} + */ +o3d.Client.prototype.initWithCanvas = function(canvas) { + var gl; + try {gl = canvas.getContext("experimental-webgl") } catch(e) { } + if (!gl) + try {gl = canvas.getContext("moz-webgl") } catch(e) { } + if (!gl) { + alert("No WebGL context found"); + return null; + } + + canvas.client.gl = gl; + gl.client = this; + gl.displayInfo = {width: canvas.width, + height: canvas.height}; +}; + + +/** * Sets the per frame render callback. * * Note: The callback will not be called recursively. When your callback is @@ -736,7 +764,7 @@ o3d.Client.prototype.invalidateAllParameters = function() { * @param {string} mime_type The type of data url you want. * Currently O3D only supports image/png. See HTML5 canvas tag * for info about toDataURL. - * @returns {string} A Data URL for the backbuffer. + * @return {string} A Data URL for the backbuffer. */ o3d.Client.prototype.toDataURL = function(opt_mime_type) { diff --git a/o3d/samples/o3d-webgl/draw_context.js b/o3d/samples/o3d-webgl/draw_context.js index ee30d9b..bf360cb 100644 --- a/o3d/samples/o3d-webgl/draw_context.js +++ b/o3d/samples/o3d-webgl/draw_context.js @@ -42,6 +42,7 @@ * @constructor */ o3d.DrawContext = function(opt_view, opt_projection) { + o3d.NamedObject.call(this); this.view = opt_view || [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]; this.projection = opt_projection || diff --git a/o3d/samples/o3d-webgl/draw_list.js b/o3d/samples/o3d-webgl/draw_list.js index 537751b..a0cffca4 100644 --- a/o3d/samples/o3d-webgl/draw_list.js +++ b/o3d/samples/o3d-webgl/draw_list.js @@ -37,6 +37,7 @@ * @constructor */ o3d.DrawList = function() { + o3d.NamedObject.call(this); this.list_ = []; }; o3d.inherit('DrawList', 'NamedObject'); @@ -72,7 +73,6 @@ o3d.DrawList.BY_PRIORITY = 2; */ o3d.DrawList.prototype.render = function() { // TODO(petersont): Add sort. - for (var i = 0; i < this.list_.length; ++i) { var drawElementInfo = this.list_[i]; var world = drawElementInfo.world; diff --git a/o3d/samples/o3d-webgl/draw_pass.js b/o3d/samples/o3d-webgl/draw_pass.js index f3deea8..495e357 100644 --- a/o3d/samples/o3d-webgl/draw_pass.js +++ b/o3d/samples/o3d-webgl/draw_pass.js @@ -39,6 +39,7 @@ * @constructor */ o3d.DrawPass = function(opt_drawList, opt_sortMethod) { + o3d.RenderNode.call(this); this.drawList = opt_drawList; this.sortMethod = opt_sortMethod || o3d.DrawList.BY_PERFORMANCE; }; diff --git a/o3d/samples/o3d-webgl/effect.js b/o3d/samples/o3d-webgl/effect.js index 53d8882..f8d7dc5 100644 --- a/o3d/samples/o3d-webgl/effect.js +++ b/o3d/samples/o3d-webgl/effect.js @@ -89,6 +89,7 @@ o3d.EffectParameterInfo.prototype.sas_class_name = ''; * @constructor */ o3d.EffectStreamInfo = function(opt_semantic, opt_semantic_index) { + o3d.NamedObject.call(this); if (!opt_semantic) { opt_semantic = o3d.Stream.UNKNOWN_SEMANTIC; } @@ -176,6 +177,13 @@ o3d.Effect.prototype.loadShaderFromString = function(shaderString, type) { var shader = this.gl.createShader(type); this.gl.shaderSource(shader, shaderString); this.gl.compileShader(shader); + + var log = this.gl.getShaderInfoLog(shader); + if (log != '') { + this.gl.client.error_callback( + 'Shader compile failed with error log:\n' + log); + } + this.gl.attachShader(this.program_, shader); }; @@ -245,24 +253,24 @@ o3d.Effect.prototype.createUniformParameters = 'worldView': true, 'worldProjection': true, 'worldViewProjection': true, - 'worldI': true, - 'viewI': true, - 'projectionI': true, - 'worldViewI': true, - 'worldProjectionI': true, - 'worldViewProjectionI': true, - 'worldT': true, - 'viewT': true, - 'projectionT': true, - 'worldViewT': true, - 'worldProjectionT': true, - 'worldViewProjectionT': true, - 'worldIT': true, - 'viewIT': true, - 'projectionIT': true, - 'worldViewIT': true, - 'worldProjectionIT': true, - 'worldViewProjectionIT': true}; + 'worldInverse': true, + 'viewInverse': true, + 'projectionInverse': true, + 'worldViewInverse': true, + 'worldProjectionInverse': true, + 'worldViewProjectionInverse': true, + 'worldTranspose': true, + 'viewTranspose': true, + 'projectionTranspose': true, + 'worldViewTranspose': true, + 'worldProjectionTranspose': true, + 'worldViewProjectionTranspose': true, + 'worldInverseTranspose': true, + 'viewInverseTranspose': true, + 'projectionInverseTranspose': true, + 'worldViewInverseTranspose': true, + 'worldProjectionInverseTranspose': true, + 'worldViewProjectionInverseTranspose': true}; for (name in this.uniforms) { var info = this.uniforms[name].info; @@ -330,7 +338,7 @@ o3d.Effect.prototype.createSASParameters = /** * Gets info about the parameters this effect needs. - * @returns {!Array.<!o3d.EffectParameterInfo>} an array of + * @return {!Array.<!o3d.EffectParameterInfo>} an array of * EffectParameterInfo objects. */ o3d.Effect.prototype.getParameterInfo = function() { @@ -341,7 +349,7 @@ o3d.Effect.prototype.getParameterInfo = function() { /** * Gets info about the streams this effect needs. - * @returns {!Array.<!o3d.EffectStreamInfo>} an array of + * @return {!Array.<!o3d.EffectStreamInfo>} an array of * EffectStreamInfo objects. */ o3d.Effect.prototype.getStreamInfo = function() { @@ -390,6 +398,12 @@ o3d.Effect.prototype.searchForParams = function(object_list) { } } } + + for (name in this.uniforms) { + if (!filled_map[name]) { + throw ('Uniform param not filled: '+name); + } + } }; diff --git a/o3d/samples/o3d-webgl/element.js b/o3d/samples/o3d-webgl/element.js index 8a953a8..e42a788 100644 --- a/o3d/samples/o3d-webgl/element.js +++ b/o3d/samples/o3d-webgl/element.js @@ -164,7 +164,7 @@ o3d.Element.prototype.drawElements = []; * pass null it will use the material on this Element. This allows you * to easily setup the default (just draw as is) by passing null or * setup a shadow pass by passing in a shadow material. - * @returns {!o3d.DrawElement} The created draw element. + * @return {!o3d.DrawElement} The created draw element. */ o3d.Element.prototype.createDrawElement = function(pack, material) { @@ -183,7 +183,7 @@ o3d.Element.prototype.createDrawElement = * @param {o3d.Cull} cull which side of the triangles to ignore. * @param {!o3d.math.Point3} start position of start of ray in local space. * @param {!o3d.math.Point3} end position of end of ray. in local space. - * @returns {!o3d.RayIntersectionInfo} RayIntersectionInfo class. If valid() + * @return {!o3d.RayIntersectionInfo} RayIntersectionInfo class. If valid() * is false then something was wrong, Check GetLastError(). If * intersected() is true then the ray intersected a something. position() * is the exact point of intersection. @@ -198,7 +198,7 @@ o3d.Element.prototype.intersectRay = * Computes the bounding box in same coordinate system as the specified * POSITION stream. * @param {number} position_stream_index Index of POSITION stream. - * @returns {!o3d.BoundingBox} The boundingbox for this element in local space. + * @return {!o3d.BoundingBox} The boundingbox for this element in local space. */ o3d.Element.prototype.getBoundingBox = function(position_stream_index) { diff --git a/o3d/samples/o3d-webgl/event.js b/o3d/samples/o3d-webgl/event.js index 91bfcbd..c928e23 100644 --- a/o3d/samples/o3d-webgl/event.js +++ b/o3d/samples/o3d-webgl/event.js @@ -35,7 +35,9 @@ * as an argument to event handlers triggered by the plugin. * @constructor */ -o3d.Event = function() { }; +o3d.Event = function() { + o3d.ObjectBase.call(this); +}; o3d.inherit('Event', 'ObjectBase'); @@ -233,7 +235,9 @@ o3d.Event.prototype.fullscreen = false; * An Event that gets sent to the render callback. * @constructor */ -o3d.RenderEvent = function() {}; +o3d.RenderEvent = function() { + o3d.Event.call(this); +}; o3d.inherit('RenderEvent', 'Event'); @@ -248,7 +252,9 @@ o3d.RenderEvent.prototype.elapsedTime = 0; * An Event that gets sent to the render callback. * @constructor */ -o3d.TickEvent = function() {}; +o3d.TickEvent = function() { + o3d.Event.call(this); +}; o3d.inherit('RenderEvent', 'Event'); diff --git a/o3d/samples/o3d-webgl/field.js b/o3d/samples/o3d-webgl/field.js index 5f82237..23058bf 100644 --- a/o3d/samples/o3d-webgl/field.js +++ b/o3d/samples/o3d-webgl/field.js @@ -37,7 +37,9 @@ * Buffer the Field's buffer property will be set to null. * @constructor */ -o3d.Field = function() { }; +o3d.Field = function() { + o3d.NamedObject.call(this); +}; o3d.inherit('Field', 'NamedObject'); /** @@ -101,7 +103,7 @@ o3d.Field.prototype.setAt = * * @param {number} start_index index of the first value to get. * @param {number} num_elements number of elements to read from field. - * @returns {number} The values of the field. + * @return {number} The values of the field. */ o3d.Field.prototype.getAt = function(start_index, num_elements) { @@ -114,21 +116,27 @@ o3d.Field.prototype.getAt = * A field that contains floating point numbers. * @constructor */ -o3d.FloatField = function() { }; +o3d.FloatField = function() { + o3d.Field.call(this); +}; o3d.inherit('FloatField', 'Field'); /** * A field that contains unsigned integers. * @constructor */ -o3d.UInt32Field = function() { }; +o3d.UInt32Field = function() { + o3d.Field.call(this); +}; o3d.inherit('UInt32Field', 'Field'); /** * A field that contains unsigned bytes. * @constructor */ -o3d.UByteNField = function() { }; +o3d.UByteNField = function() { + o3d.Field.call(this); +}; o3d.inherit('UByteNField', 'Field'); diff --git a/o3d/samples/o3d-webgl/file_request.js b/o3d/samples/o3d-webgl/file_request.js index 122364a..8c0d44c 100644 --- a/o3d/samples/o3d-webgl/file_request.js +++ b/o3d/samples/o3d-webgl/file_request.js @@ -133,6 +133,13 @@ o3d.FileRequest.prototype.done = false; o3d.FileRequest.prototype.success = false; +/** + * The image object if we are opening an image. + * @type {Image} + * @private + */ +o3d.FileRequest.prototype.image_ = null; + /** * An error message. @@ -143,17 +150,53 @@ o3d.FileRequest.prototype.success = false; o3d.FileRequest.prototype.error = ''; +/** + * Guesses from a url whether the url is an image file. + * @param {string} url The URL. + * @private + */ +o3d.FileRequest.prototype.isImageUrl_ = function(url) { + var extension = url.substring(url.length - 4); + return (extension == '.png' || extension == '.jpg'); +}; + + +/** + * Called by the image class when the image file is loaded... if we're + * loading an image. + * @private + */ +o3d.FileRequest.prototype.imageLoaded_ = function() { + if (this.image_.complete) { + this.success = true; + this.done = true; + this.readyState = 4; + this.data = new o3d.RawData(); + this.data.image_ = this.image_; + } + this.onreadystatechange.apply(this, arguments); +}; + /** * Set up several of the request fields. * @param {string} method "GET" is the only supported method at this time * @param {string} uri the location of the file to fetch - * @param {boolean} async true is the only legal value at this time + * @param {boolean} async true is the only legal value at this time. */ o3d.FileRequest.prototype.open = function(method, uri, async) { this.uri = uri; - this.request_.open(method, uri, async); + if (this.isImageUrl_(uri)) { + this.image_ = new Image(); + var that = this; + this.image_.onload = function() { + that.imageLoaded_.call(that); + } + this.image_.src = uri; + } else { + this.request_.open(method, uri, async); + } }; @@ -163,7 +206,7 @@ o3d.FileRequest.prototype.open = * matter what, with success or failure. */ o3d.FileRequest.prototype.send = function() { - this.request_.send(); + // This function left blank for compatability with o3djs.io. }; diff --git a/o3d/samples/o3d-webgl/named_object.js b/o3d/samples/o3d-webgl/named_object.js index ce6c871..0fd1ec2 100644 --- a/o3d/samples/o3d-webgl/named_object.js +++ b/o3d/samples/o3d-webgl/named_object.js @@ -31,29 +31,12 @@ /** - * Takes the name of a class as an argument, and returns true if this object is - * either an instance of that class or derives from that class. - * - * var t = pack.createObject('o3d.Transform'); - * t.isAClassName('o3d.Transform'); - * t.isAClassName('o3d.ParamObject'); - * t.isAClassName('o3d.Shape'); - * - * @param {o3d.String} class_name Name of class to check for. - * @returns {o3d.bool} true if this object is a or is derived from the given - * class name. - */ -o3d.ObjectBase.prototype.isAClassName = - function(class_name) { - o3d.notImplemented(); -}; - - -/** * Base class for all objects that can have their name set. * @constructor */ -o3d.NamedObject = function() { }; +o3d.NamedObject = function() { + o3d.NamedObjectBase.call(this); +}; o3d.inherit('NamedObject', 'NamedObjectBase'); diff --git a/o3d/samples/o3d-webgl/named_object_base.js b/o3d/samples/o3d-webgl/named_object_base.js index 5176426..b3b6858 100644 --- a/o3d/samples/o3d-webgl/named_object_base.js +++ b/o3d/samples/o3d-webgl/named_object_base.js @@ -34,7 +34,9 @@ * Base class for all objects that are identifiable by a name. * @constructor */ -o3d.NamedObjectBase = function() { }; +o3d.NamedObjectBase = function() { + o3d.ObjectBase.call(this); +}; o3d.inherit('NamedObjectBase', 'ObjectBase'); diff --git a/o3d/samples/o3d-webgl/object_base.js b/o3d/samples/o3d-webgl/object_base.js index 42931eb..a0f81b9 100644 --- a/o3d/samples/o3d-webgl/object_base.js +++ b/o3d/samples/o3d-webgl/object_base.js @@ -54,14 +54,16 @@ o3d.ObjectBase.prototype.superClass = null; /** * Traverses the current object's class and all its superclasses and * determines if any of them are of the given name. - * returns {bool} + * @param {string} className The name of a class. + * @return {boolean} Whether this is counts as a className. */ -o3d.ObjectBase.isAClassName = function(o, className) { - while (o != undefined) { - if (o.className == 'className') { +o3d.ObjectBase.prototype.isAClassName = function(className) { + var object = this; + while (object != undefined) { + if (object.className == className) { return true; } - o = o.superClass.prototype; + object = object.superClass && object.superClass.prototype; } return false; }; diff --git a/o3d/samples/o3d-webgl/pack.js b/o3d/samples/o3d-webgl/pack.js index fc10e49..925e5f7 100644 --- a/o3d/samples/o3d-webgl/pack.js +++ b/o3d/samples/o3d-webgl/pack.js @@ -39,6 +39,7 @@ * @constructor */ o3d.Pack = function() { + o3d.NamedObject.call(this); this.objects_ = []; }; o3d.inherit('Pack', 'NamedObject'); @@ -105,22 +106,12 @@ o3d.Pack.prototype.destroy = function() { * Now the last reference has been removed and myTransform will be freed. * * @param {o3d.ObjectBase} object Object to remove. - * @returns {boolean} True if the object was successfully removed. + * @return {boolean} True if the object was successfully removed. * False if the object is not part of this pack. */ o3d.Pack.prototype.removeObject = function(object) { - var i = 0; - for (var j = 0; j < this.objects_.length; ++j) { - if (this.objects_[i] == object) { - j++; - } - this.objects_[j] = this.objects_[i]; - i++; - } - if (this.objects_.length > i) { - this.objects_.pop(); - } + o3d.removeFromArray(this.objects_, object); }; @@ -176,7 +167,7 @@ o3d.Pack.prototype.removeObject = * ParamOp4FloatsToFloat4 * ParamOp16FloatsToMatrix4 * TRSToMatrix4 - * @returns {o3d.ObjectBase} The created object. + * @return {o3d.ObjectBase} The created object. */ o3d.Pack.prototype.createObject = function(type_name) { @@ -186,6 +177,7 @@ o3d.Pack.prototype.createObject = } var object = new foo(); object.gl = this.gl; + this.objects_.push(object); return object; }; @@ -204,11 +196,32 @@ o3d.Pack.prototype.createObject = * compelete mipmap chain. * @param {boolean} enable_render_surfaces If true, the texture object will * expose RenderSurface objects through GetRenderSurface(...). - * @returns {!o3d.Texture2D} The Texture2D object. + * @return {!o3d.Texture2D} The Texture2D object. */ o3d.Pack.prototype.createTexture2D = function(width, height, format, levels, enable_render_surfaces) { - o3d.notImplemented(); + var texture = this.createObject('Texture2D'); + texture.width = width; + texture.height = height; + texture.levels = levels; + texture.texture_ = this.gl.createTexture(); + + if (enable_render_surfaces) { + this.gl.bindTexture(this.gl.TEXTURE_2D, texture.texture_); + this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, width, height, + 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, null); + + this.gl.texParameteri(this.gl.TEXTURE_2D, + this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR); + this.gl.texParameteri(this.gl.TEXTURE_2D, + this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR); + this.gl.texParameteri(this.gl.TEXTURE_2D, + this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE); + this.gl.texParameteri(this.gl.TEXTURE_2D, + this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE); + } + + return texture; }; @@ -225,7 +238,7 @@ o3d.Pack.prototype.createTexture2D = * the compelete mipmap chain. * @param {boolean} enable_render_surfaces If true, the texture object * will expose RenderSurface objects through GetRenderSurface(...). - * @returns {!o3d.TextureCUBE} The TextureCUBE object. + * @return {!o3d.TextureCUBE} The TextureCUBE object. */ o3d.Pack.prototype.createTextureCUBE = function(edge_length, format, levels, enable_render_surfaces) { @@ -241,11 +254,13 @@ o3d.Pack.prototype.createTextureCUBE = * * @param {number} width The width of the RenderSurface in pixels * @param {number} height The height of the RenderSurface in pixels - * @returns {!o3d.RenderDepthStencilSurface} The RenderSurface object. + * @return {!o3d.RenderDepthStencilSurface} The RenderSurface object. */ o3d.Pack.prototype.createDepthStencilSurface = function(width, height) { - o3d.notImplemented(); + var surface = this.createObject("RenderDepthStencilSurface"); + surface.initWithSize_(width, height); + return surface; }; @@ -260,7 +275,7 @@ o3d.Pack.prototype.createDepthStencilSurface = * @param {string} class_type_name the Class of the object. It is okay * to pass base types for example "o3d.RenderNode" will return * ClearBuffers, DrawPasses, etc... - * @returns {!Array.<!o3d.ObjectBase>} Array of Objects. + * @return {!Array.<!o3d.ObjectBase>} Array of Objects. */ o3d.Pack.prototype.getObjects = function(name, class_type_name) { @@ -278,11 +293,24 @@ o3d.Pack.prototype.getObjects = * @param {string} class_type_name the Class of the object. It is * okay to pass base types for example "o3d.RenderNode" will return * ClearBuffers, DrawPasses, etc... - * @returns {!Array.<!o3d.ObjectBase>} Array of Objects. + * @return {!Array.<!o3d.ObjectBase>} Array of Objects. */ o3d.Pack.prototype.getObjectsByClassName = function(class_type_name) { - o3d.notImplemented(); + if (class_type_name.substr(0, 4) == 'o3d.') { + class_type_name = class_type_name.substr(4); + } + + var found = []; + + for (var i = 0; i < this.objects_.length; ++i) { + var object = this.objects_[i]; + if (object.isAClassName(class_type_name)) { + found.push(object); + } + } + + return found; }; @@ -311,7 +339,7 @@ o3d.Pack.prototype.objects_ = []; * load a texture is to load a RawData, use that to create Bitmap, Massage * the Bitmap to your liking the use that to create a Texture. * @param {string} type Must be "TEXTURE" or "RAWDATA" - * @returns {!o3d.FileRequest} a FileRequest + * @return {!o3d.FileRequest} a FileRequest */ o3d.Pack.prototype.createFileRequest = function(type) { @@ -328,18 +356,43 @@ o3d.Pack.prototype.createFileRequest = * * @param {!o3d.RawData} raw_data contains the bitmap data in a supported * format. - * @returns {!o3d.Bitmap} An Array of Bitmaps object. + * @return {!Array.<!o3d.Bitmap>} An Array of Bitmaps object. */ o3d.Pack.prototype.createBitmapsFromRawData = function(raw_data) { - o3d.notImplemented(); + var bitmap = this.createObject('Bitmap') + if (!raw_data.image_) { + throw ('Cannot create bitmap from non-image data.'); + return []; + } + bitmap.height = raw_data.image_.height; + bitmap.width = raw_data.image_.width; + + var canvas = document.createElement('CANVAS'); + + canvas.width = bitmap.width; + canvas.height = bitmap.height; + + bitmap.canvas_ = canvas; + var context = canvas.getContext('2d'); + // Flip it. + context.translate(0, bitmap.height); + context.scale(1, -1); + context.drawImage(raw_data.image_, + 0, 0, bitmap.width, bitmap.height); + + // TODO(petersont): I'm not sure how to get the format. + bitmap.format = o3d.Texture.ARGB8; + bitmap.numMipmaps = 1; + + return [bitmap]; }; /** * Create RawData given a data URL. * @param {string} data_url The data URL from which to create the RawData. - * @returns {!o3d.RawData} The RawData. + * @return {!o3d.RawData} The RawData. */ o3d.Pack.prototype.createRawDataFromDataURL = function(data_url) { diff --git a/o3d/samples/o3d-webgl/param.js b/o3d/samples/o3d-webgl/param.js index 0bb28fe..3b23f58 100644 --- a/o3d/samples/o3d-webgl/param.js +++ b/o3d/samples/o3d-webgl/param.js @@ -79,13 +79,39 @@ o3d.Param.prototype.outputConnections = []; o3d.Param.prototype.owner_ = null; /** + * @type {Object} The value of the parameter. + */ +o3d.Param.prototype.value_ = null; + +o3d.Param.prototype.__defineSetter__('value', + function(v) { + if (this.inputConnection) { + throw ('Tried to set bound parameter.'); + } else { + this.value_ = v; + } + } +); + +o3d.Param.prototype.__defineGetter__('value', + function() { + if (this.inputConnection) { + return this.inputConnection.value; + } else { + return this.value_; + } + } +); + + +/** * Directly binds two Param elements such that this parameter gets its value * from the source parameter. The source must be compatible with this * parameter. * * @param {o3d.Param} source_param The parameter that the value originates * from. Passing in null will unbind any parameter currently bound. - * @returns {boolean} True if the bind succeeded. + * @return {boolean} True if the bind succeeded. */ o3d.Param.prototype.bind = function(source_param) { @@ -130,20 +156,6 @@ o3d.Param.prototype.unbindOutputs = function() { o3d.Param.prototype.read_only_ = false; - -/** - * The input connection for this param. - */ -o3d.Param.prototype.input_connection = null; - - - -/** - * The output connections for this param. - */ -o3d.Param.prototype.output_connections = []; - - /** * @constructor */ @@ -703,7 +715,7 @@ o3d.inherit('WorldViewProjectionInverseTransposeParamMatrix4', * Called to specify the value of a uniform variable. */ o3d.ParamFloat.prototype.applyToLocation = function(gl, location) { - gl.uniform4fv(location, this.value); + gl.uniform1f(location, this.value); }; /** @@ -736,6 +748,18 @@ o3d.ParamMatrix4.prototype.applyToLocation = function(gl, location) { o3d.Transform.flattenMatrix4(this.value)); }; +/** + * Called to specify the value of a uniform variable. + */ +o3d.ParamSampler.prototype.applyToLocation = function(gl, location) { + var i = 0; + gl.activeTexture(gl.TEXTURE0 + i); + if (!this.value || !this.value.texture || !this.value.texture.texture_) { + throw ('Attempt to use texture parameter before texture value set.'); + } + gl.bindTexture(gl.TEXTURE_2D, this.value.texture.texture_); + gl.uniform1i(location, i); +}; /** @@ -759,43 +783,43 @@ o3d.Param.SAS.createParam('viewProjection', o3d.Param.SAS.createParam('worldViewProjection', 'WorldViewProjectionParamMatrix4'); -o3d.Param.SAS.createParam('worldI', +o3d.Param.SAS.createParam('worldInverse', 'WorldInverseParamMatrix4'); -o3d.Param.SAS.createParam('viewI', +o3d.Param.SAS.createParam('viewInverse', 'ViewInverseParamMatrix4'); -o3d.Param.SAS.createParam('projectionI', +o3d.Param.SAS.createParam('projectionInverse', 'ProjectionInverseParamMatrix4'); -o3d.Param.SAS.createParam('worldViewI', +o3d.Param.SAS.createParam('worldViewInverse', 'WorldViewInverseParamMatrix4'); -o3d.Param.SAS.createParam('viewProjectionI', +o3d.Param.SAS.createParam('viewProjectionInverse', 'ViewProjectionInverseParamMatrix4'); -o3d.Param.SAS.createParam('worldViewProjectionI', +o3d.Param.SAS.createParam('worldViewProjectionInverse', 'WorldViewProjectionInverseParamMatrix4'); -o3d.Param.SAS.createParam('worldT', +o3d.Param.SAS.createParam('worldTranspose', 'WorldInverseParamMatrix4'); -o3d.Param.SAS.createParam('viewT', +o3d.Param.SAS.createParam('viewTranspose', 'ViewTransposeParamMatrix4'); -o3d.Param.SAS.createParam('projectionT', +o3d.Param.SAS.createParam('projectionTranspose', 'ProjectionTransposeParamMatrix4'); -o3d.Param.SAS.createParam('worldViewT', +o3d.Param.SAS.createParam('worldViewTranspose', 'WorldViewTransposeParamMatrix4'); -o3d.Param.SAS.createParam('viewProjectionT', +o3d.Param.SAS.createParam('viewProjectionTranspose', 'ViewProjectionTransposeParamMatrix4'); -o3d.Param.SAS.createParam('worldViewProjectionT', +o3d.Param.SAS.createParam('worldViewProjectionTranspose', 'WorldViewProjectionTransposeParamMatrix4'); -o3d.Param.SAS.createParam('worldIT', +o3d.Param.SAS.createParam('worldInverseTranspose', 'WorldInverseTransposeParamMatrix4'); -o3d.Param.SAS.createParam('viewIT', +o3d.Param.SAS.createParam('viewInverseTranspose', 'ViewInverseTransposeParamMatrix4'); -o3d.Param.SAS.createParam('projectionIT', +o3d.Param.SAS.createParam('projectionInverseTranspose', 'ProjectionInverseTransposeParamMatrix4'); -o3d.Param.SAS.createParam('worldViewIT', +o3d.Param.SAS.createParam('worldViewInverseTranspose', 'WorldViewInverseTransposeParamMatrix4'); -o3d.Param.SAS.createParam('viewProjectionIT', +o3d.Param.SAS.createParam('viewProjectionInverseTranspose', 'ViewProjectionInverseTransposeParamMatrix4'); -o3d.Param.SAS.createParam('worldViewProjectionIT', +o3d.Param.SAS.createParam('worldViewProjectionInverseTranspose', 'WorldViewProjectionInverseTransposeParamMatrix4'); /** diff --git a/o3d/samples/o3d-webgl/param_object.js b/o3d/samples/o3d-webgl/param_object.js index 625f876..5c5ea89 100644 --- a/o3d/samples/o3d-webgl/param_object.js +++ b/o3d/samples/o3d-webgl/param_object.js @@ -36,6 +36,7 @@ * @constructor */ o3d.ParamObject = function() { + o3d.NamedObject.call(this); this.params_ = {}; }; o3d.inherit('ParamObject', 'NamedObject'); @@ -95,7 +96,7 @@ o3d.inherit('ParamObject', 'NamedObject'); * 'WorldViewProjectionInverseParamMatrix4' * 'WorldViewProjectionTransposeParamMatrix4' * 'WorldViewProjectionInverseTransposeParamMatrix4' - * @returns {!o3d.Param} The newly created Param or null on failure. + * @return {!o3d.Param} The newly created Param or null on failure. */ o3d.ParamObject.prototype.createParam = function(param_name, param_type_name) { @@ -113,7 +114,7 @@ o3d.ParamObject.prototype.createParam = * Searches by name for a Param defined in the object. * * @param {string} param_name Name to search for. - * @returns {!o3d.Param} The Param with the given name, or null otherwise. + * @return {!o3d.Param} The Param with the given name, or null otherwise. */ o3d.ParamObject.prototype.getParam = function(param_name) { @@ -128,7 +129,7 @@ o3d.ParamObject.prototype.getParam = * or if the param is unremovable. * * @param {!o3d.Param} param param to remove. - * @returns {boolean} True if the param was removed. + * @return {boolean} True if the param was removed. */ o3d.ParamObject.prototype.removeParam = function(param) { diff --git a/o3d/samples/o3d-webgl/raw_data.js b/o3d/samples/o3d-webgl/raw_data.js index ab3c0f4..59a441c 100644 --- a/o3d/samples/o3d-webgl/raw_data.js +++ b/o3d/samples/o3d-webgl/raw_data.js @@ -44,7 +44,9 @@ * request.send(); * @constructor */ -o3d.RawData = function() { }; +o3d.RawData = function() { + o3d.NamedObject.call(this); +}; o3d.inherit('RawData', 'NamedObject'); @@ -56,6 +58,13 @@ o3d.inherit('RawData', 'NamedObject'); o3d.RawData.prototype.string_value = ''; +/** + * The data as an image if it is an image. + * @type {Image} + * @private + */ +o3d.RawData.prototype.image_ = null; + /** * The uri of the RawData. diff --git a/o3d/samples/o3d-webgl/ray_intersection_info.js b/o3d/samples/o3d-webgl/ray_intersection_info.js index ab317b4..db37c4d 100644 --- a/o3d/samples/o3d-webgl/ray_intersection_info.js +++ b/o3d/samples/o3d-webgl/ray_intersection_info.js @@ -36,6 +36,7 @@ * @constructor */ o3d.RayIntersectionInfo = function() { + o3d.NamedObject.call(this); o3d.RayIntersectionInfo.prototype.position = [0, 0, 0]; }; o3d.inherit('RayIntersectionInfo', 'NamedObject'); diff --git a/o3d/samples/o3d-webgl/render_node.js b/o3d/samples/o3d-webgl/render_node.js index d97b2e9..fd82868 100644 --- a/o3d/samples/o3d-webgl/render_node.js +++ b/o3d/samples/o3d-webgl/render_node.js @@ -41,6 +41,7 @@ * @constructor */ o3d.RenderNode = function(opt_priority, opt_active) { + o3d.ParamObject.call(this); this.priority = opt_priority; this.children = []; }; @@ -77,8 +78,16 @@ o3d.RenderNode.prototype.parent = null; o3d.RenderNode.prototype.__defineSetter__('parent', function(p) { + if (this.parent_) { + this.parent_.removeChild(this); + } this.parent_ = p; - p.addChild(this); + if (this.parent_) { + if (!this.parent_.addChild) { + throw ('Parent of render node must be render node or null.'); + } + this.parent_.addChild(this); + } } ); @@ -97,6 +106,14 @@ o3d.RenderNode.prototype.addChild = function(child) { }; +/** + * Removes a child node. + * @param {o3d.RenderNode} child The child to add. + */ +o3d.RenderNode.prototype.removeChild = function(child) { + o3d.removeFromArray(this.children, child); +}; + /** * The immediate children of this RenderNode. @@ -146,7 +163,7 @@ o3d.RenderNode.prototype.getRenderNodesInTree = * will affect them. * * @param {string} name Rendernode name to look for. - * @returns {Array.<!o3d.RenderNode>} An array containing all nodes among + * @return {Array.<!o3d.RenderNode>} An array containing all nodes among * this node and its decendants that have the given name. */ o3d.RenderNode.prototype.getRenderNodesByNameInTree = @@ -164,7 +181,7 @@ o3d.RenderNode.prototype.getRenderNodesByNameInTree = * will affect them. * * @param {string} class_name class name to look for. - * @returns {Array.<!o3d.RenderNode>} An array containing all nodes among + * @return {Array.<!o3d.RenderNode>} An array containing all nodes among * this node and its decendants whose type is class_name. */ o3d.RenderNode.prototype.getRenderNodesByClassNameInTree = diff --git a/o3d/samples/o3d-webgl/render_surface.js b/o3d/samples/o3d-webgl/render_surface.js index d3b3877..8012bea 100644 --- a/o3d/samples/o3d-webgl/render_surface.js +++ b/o3d/samples/o3d-webgl/render_surface.js @@ -41,6 +41,9 @@ */ o3d.RenderSurfaceBase = function(width, height, texture) { o3d.ParamObject.call(this); + this.width = width; + this.height = height; + this.texture = texture; }; o3d.inherit('RenderSurfaceBase', 'ParamObject'); @@ -60,7 +63,6 @@ o3d.RenderSurfaceBase.prototype.width = 0; o3d.RenderSurfaceBase.prototype.height = 0; - /** * A RenderSurface encapsulates the notion of a renderable surface. * When used in conjunction with a RenderSurfaceSet node in the render graph, @@ -69,7 +71,9 @@ o3d.RenderSurfaceBase.prototype.height = 0; * only be accessed through the texture getRenderSurface(...) interfaces. * @constructor */ -o3d.RenderSurface = function() { }; +o3d.RenderSurface = function() { + o3d.RenderSurfaceBase.call(this); +}; o3d.inherit('RenderSurface', 'RenderSurfaceBase'); @@ -80,10 +84,61 @@ o3d.RenderSurface.prototype.texture = null; /** + * The mip level targeted by this render surface. + * @type {number} + */ +o3d.RenderSurface.level = 0; + + +/** + * The underlying GL framebuffer object. + * @type {WebGLFramebuffer} + * @private + */ +o3d.RenderSurfaceBase.prototype.framebuffer_ = null; + +/** + * Initializes a render surface to render to the given texture. + * @param {o3d.Texture2D} texture The texture. + */ +o3d.RenderSurface.prototype.initWithTexture = function(texture, level) { + this.framebuffer_ = this.gl.createFramebuffer(); + this.texture = texture; + this.level = level; + this.width = texture.width; + this.height = texture.height; +}; + +/** * A RenderDepthStencilSurface represents a depth stencil render surface. * @constructor */ -o3d.RenderDepthStencilSurface = function() { }; +o3d.RenderDepthStencilSurface = function() { + o3d.RenderSurfaceBase.call(this); +}; o3d.inherit('RenderDepthStencilSurface', 'RenderSurfaceBase'); +/** + * The GL renderbuffer object for the depth buffer. + * @type {WebGLRenderbuffer} + * @private + */ +o3d.RenderDepthStencilSurface.prototype.depth_stencil_buffer_ = null; + + +/** + * Allocates depth and stnecil buffers of the given size. + * @param {number} width + * @param {number} height + * @private + */ +o3d.RenderDepthStencilSurface.prototype.initWithSize_ = + function(width, height) { + this.depth_stencil_buffer_ = this.gl.createRenderbuffer(); + this.gl.bindRenderbuffer(this.gl.RENDERBUFFER, this.depth_stencil_buffer_); + this.gl.renderbufferStorage( + this.gl.RENDERBUFFER, this.gl.DEPTH_COMPONENT16, width, height); + this.width = width; + this.height = height; +}; diff --git a/o3d/samples/o3d-webgl/render_surface_set.js b/o3d/samples/o3d-webgl/render_surface_set.js index dfcd901..6b4bbec 100644 --- a/o3d/samples/o3d-webgl/render_surface_set.js +++ b/o3d/samples/o3d-webgl/render_surface_set.js @@ -36,8 +36,8 @@ * from the given RenderSurfaceSet node will operate on the contents of * the bound depth and color buffers. * Note the following usage constraints of this node: - * 1) If both a color and depth surface is bound, then they must be of matching - * dimensions. + * 1) If both a color and depth surface is bound, then they must be of + * matching dimensions. * 2) At least one of render_surface and render_depth_surface must non-null. * * @param {o3d.RenderSurface} opt_renderSurface The render surface to set. @@ -45,7 +45,9 @@ * depth stencil render surface to set. * @constructor */ -o3d.RenderSurfaceSet = function() { +o3d.RenderSurfaceSet = + function(opt_renderSurface, opt_renderDepthStencilSurface) { + o3d.RenderNode.call(this); o3d.RenderSurfaceSet.prototype.renderSurface = opt_renderSurface; o3d.RenderSurfaceSet.prototype.renderDepthStencilSurface = @@ -62,7 +64,6 @@ o3d.inherit('RenderSurfaceSet', 'RenderNode'); o3d.RenderSurfaceSet.prototype.renderSurface = null; - /** * The render depth stencil surface to which the depth contents of all * RenderNode children should be drawn. @@ -70,5 +71,95 @@ o3d.RenderSurfaceSet.prototype.renderSurface = null; */ o3d.RenderSurfaceSet.prototype.renderDepthStencilSurface = null; +/** + * Helper function to set the framebuffer back to the default one. + * @private + */ +o3d.RenderSurfaceSet.prototype.clearFramebufferObjects_ = + function() { + this.gl.bindFramebuffer( + this.gl.FRAMEBUFFER, this.renderSurface.framebuffer_); + + this.gl.framebufferRenderbuffer( + this.gl.FRAMEBUFFER, + this.gl.COLOR_ATTACHMENT0, + this.gl.RENDERBUFFER, + 0); + + this.gl.framebufferRenderbuffer( + this.gl.FRAMEBUFFER, + this.gl.DEPTH_STENCIL_ATTACHMENT, + this.gl.RENDERBUFFER, + 0); + + this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, 0); +}; + + +/** + * Helper function to set up both the color and depth-stencil targets. + * @private + */ +o3d.RenderSurfaceSet.prototype.installFramebufferObjects_ = + function() { + // Reset the bound attachments to the current framebuffer object. + this.clearFramebufferObjects_(); + + this.gl.bindFramebuffer( + this.gl.FRAMEBUFFER, this.renderSurface.framebuffer_); + + if (this.renderSurface) { + var texture = this.renderSurface.texture.texture_; + var level = this.renderSurface.level; + + // TODO(petersont): If it's a cube, this call should be different. + this.gl.bindTexture(this.gl.TEXTURE_2D, texture); + this.gl.framebufferTexture2D( + this.gl.FRAMEBUFFER, + this.gl.COLOR_ATTACHMENT0, + this.gl.TEXTURE_2D, + texture, + level); + } + + if (this.renderDepthStencilSurface) { + var depth_stencil_buffer = + this.renderDepthStencilSurface.depth_stencil_buffer_; + + // TODO(petersont): In the WebGL spec, there is a depth-stencil + // attachment, but it hasn't been implemented yet, once it is, + // this should use one of those. + this.gl.bindRenderbuffer(this.gl.RENDERBUFFER, depth_stencil_buffer); + this.gl.framebufferRenderbuffer( + this.gl.FRAMEBUFFER, + this.gl.DEPTH_ATTACHMENT, + this.gl.RENDERBUFFER, + depth_stencil_buffer); + } +}; + + +/** + * Called during the rendergraph traversal before the children are rendered. + * @private + */ +o3d.RenderSurfaceSet.prototype.before = function() { + this.installFramebufferObjects_(); + this.previousHeight = this.gl.displayInfo.height; + this.previousWidth = this.gl.displayInfo.width; + this.gl.displayInfo.height = this.renderSurface.height; + this.gl.displayInfo.width = this.renderSurface.width; +}; + + +/** + * Called during the rendergraph traversal after the children are rendered. + * @private + */ +o3d.RenderSurfaceSet.prototype.after = function() { + this.clearFramebufferObjects_(); + this.gl.displayInfo.height = this.previousHeight; + this.gl.displayInfo.width = this.previousWidth; +}; diff --git a/o3d/samples/o3d-webgl/sampler.js b/o3d/samples/o3d-webgl/sampler.js new file mode 100644 index 0000000..1748d83 --- /dev/null +++ b/o3d/samples/o3d-webgl/sampler.js @@ -0,0 +1,170 @@ +/* + * Copyright 2010, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/** + * Sampler is the base of all texture samplers. Texture samplers encapsulate + * a texture reference with a set of states that define how the texture + * gets applied to a surface. Sampler states are set either via Params defined + * on the Sampler object or directly via one the convenience methods defined + * on the Sampler. The following states are supported (default values are in + * parenthesis): + * \li 'addressModeU' (WRAP) + * \li 'addressModeV' (WRAP) + * \li 'addressModeW' (WRAP) + * \li 'magFilter' (LINEAR) + * \li 'minFilter' (LINEAR) + * \li 'mipFilter' (POINT) + * \li 'borderColor' ([0,0,0,0]) + * \li 'maxAnisotropy' (1) + */ +o3d.Sampler = function() { + o3d.ParamObject.call(this); + this.borderColor = [0, 0, 0, 0]; +}; +o3d.inherit('Sampler', 'ParamObject'); + + + +/** + * @type {number} + */ +o3d.Sampler.AddressMode = goog.typedef; + + +/** + * AddressMode, + * Controls what happens with texture coordinates outside the [0..1] range. + * WRAP + * MIRROR + * CLAMP + * BORDER + */ +o3d.Sampler.WRAP = 0; +o3d.Sampler.MIRROR = 1; +o3d.Sampler.CLAMP = 2; +o3d.Sampler.BORDER = 3; + + +/** + * @type {number} + */ +o3d.Sampler.FilterType = goog.typedef; + +/** + * FilterType, + * Texture filtering types. + * NONE + * POINT + * LINEAR + * ANISOTROPIC + */ +o3d.Sampler.NONE = 0; +o3d.Sampler.POINT = 1; +o3d.Sampler.LINEAR = 2; +o3d.Sampler.ANISOTROPIC = 3; + + +/** + * The texture address mode for the u coordinate. + * @type {!o3d.Sampler.AddressMode} + */ +o3d.Sampler.prototype.addressModeU = o3d.Sampler.WRAP; + + + +/** + * The texture address mode for the v coordinate. + * @type {!o3d.Sampler.AddressMode} + */ +o3d.Sampler.prototype.addressModeV = o3d.Sampler.WRAP; + + + +/** + * The texture address mode for the w coordinate. + * @type {!o3d.Sampler.AddressMode} + */ +o3d.Sampler.prototype.addressModeW = o3d.Sampler.WRAP; + + + +/** + * The magnification filter. Valid values for the mag filter are: POINT and + * @type {!o3d.Sampler.FilterType} + */ +o3d.Sampler.prototype.magFilter = o3d.Sampler.LINEAR; + + + +/** + * The minification filter. Valid values for the min filter are: POINT, LINEAR + * and ANISOTROPIC. + * @type {!o3d.Sampler.FilterType} + */ +o3d.Sampler.prototype.minFilter = o3d.Sampler.LINEAR; + + + +/** + * The mipmap filter used during minification. Valid values for the mip filter + * are: NONE, POINT and LINEAR. + * @type {!o3d.Sampler.FilterType} + */ +o3d.Sampler.prototype.mipFilter = o3d.Sampler.LINEAR; + + + +/** + * Color returned for texture coordinates outside the [0,1] range when the + * address mode is set to BORDER. + * @type {!Array.<number>} + */ +o3d.Sampler.prototype.borderColor = [0, 0, 0, 0]; + + + +/** + * Degree of anisotropy used when the ANISOTROPIC filter type is used. + * @type {number} + */ +o3d.Sampler.prototype.maxAnisotropy = 1; + + + +/** + * The Texture object used by this Sampler. + * @type {o3d.Texture} + */ +o3d.Sampler.prototype.texture = null; + + + diff --git a/o3d/samples/o3d-webgl/shape.js b/o3d/samples/o3d-webgl/shape.js index 4754869..ab47b2f 100644 --- a/o3d/samples/o3d-webgl/shape.js +++ b/o3d/samples/o3d-webgl/shape.js @@ -37,6 +37,7 @@ * @constructor */ o3d.Shape = function() { + o3d.ParamObject.call(this); this.elements = []; }; o3d.inherit('Shape', 'ParamObject'); @@ -72,7 +73,10 @@ o3d.Shape.prototype.elements = []; */ o3d.Shape.prototype.createDrawElements = function(pack, material) { - o3d.notImplemented(); + var elements = this.elements; + for (var i = 0; i < elements.length; ++i) { + elements[i].createDrawElement(pack, material); + } }; diff --git a/o3d/samples/o3d-webgl/state_set.js b/o3d/samples/o3d-webgl/state_set.js index 8fe1881..054b5a8 100644 --- a/o3d/samples/o3d-webgl/state_set.js +++ b/o3d/samples/o3d-webgl/state_set.js @@ -39,7 +39,7 @@ * @constructor */ o3d.StateSet = function(opt_state) { - o3d.ParamObject.call(this); + o3d.RenderNode.call(this); this.state = opt_state || null; }; o3d.inherit('StateSet', 'RenderNode'); diff --git a/o3d/samples/o3d-webgl/stream.js b/o3d/samples/o3d-webgl/stream.js index 0a3cf19..6a96aa1 100644 --- a/o3d/samples/o3d-webgl/stream.js +++ b/o3d/samples/o3d-webgl/stream.js @@ -35,6 +35,7 @@ * @constructor */ o3d.Stream = function(semantic, semantic_index, field, start_index) { + o3d.NamedObject.call(this); this.semantic = semantic; this.semanticIndex = semantic_index; this.field = field; diff --git a/o3d/samples/o3d-webgl/stream_bank.js b/o3d/samples/o3d-webgl/stream_bank.js index b6c032a..8329709 100644 --- a/o3d/samples/o3d-webgl/stream_bank.js +++ b/o3d/samples/o3d-webgl/stream_bank.js @@ -35,6 +35,7 @@ * @constructor */ o3d.StreamBank = function() { + o3d.NamedObject.call(this); this.vertexStreams = []; }; o3d.inherit('StreamBank', 'NamedObject'); @@ -53,7 +54,7 @@ o3d.StreamBank.prototype.vertexStreams = []; * @param {number} semantic_index Which index of a particular semantic to use. * @param {o3d.Field} field The field containing information for this stream. * @param {number} start_index The first element to use. - * @returns {boolean} True if successful. + * @return {boolean} True if successful. */ o3d.StreamBank.prototype.setVertexStream = function(semantic, semantic_index, field, start_index) { @@ -71,7 +72,7 @@ o3d.StreamBank.prototype.setVertexStream = * @param {o3d.Stream.Semantic} semantic The particular use of this stream. * @param {o3d.Stream.Semantic} semantic_index Which index of a particular * semantic to use. - * @returns {o3d.Stream} The found stream or null if it does not exist. + * @return {o3d.Stream} The found stream or null if it does not exist. */ o3d.StreamBank.prototype.getVertexStream = function(semantic, semantic_index) { @@ -87,7 +88,7 @@ o3d.StreamBank.prototype.getVertexStream = * @param {o3d.Stream.Semantic} semantic The particular use of this stream. * @param {o3d.Stream.Semantic} semantic_index Which index of a particular * semantic to use. - * @returns {boolean} true if the specified stream existed. + * @return {boolean} true if the specified stream existed. */ o3d.StreamBank.prototype.removeVertexStream = function(semantic, semantic_index) { diff --git a/o3d/samples/o3d-webgl/texture.js b/o3d/samples/o3d-webgl/texture.js index 767e608..7c5367b 100644 --- a/o3d/samples/o3d-webgl/texture.js +++ b/o3d/samples/o3d-webgl/texture.js @@ -105,7 +105,7 @@ o3d.Texture.prototype.format = o3d.Texture.UNKNOWN_FORMAT; /** * The number of mipmap levels used by the texture. - * type {number} + * @type {number} */ o3d.Texture.prototype.levels = 1; @@ -113,11 +113,18 @@ o3d.Texture.prototype.levels = 1; /** * True if all the alpha values in the texture are 1.0 - * type {boolean} + * @type {boolean} */ o3d.Texture.prototype.alphaIsOne = true; +/** + * The the associated gl texture. + * @type {WebGLTexture} + * @private + */ +o3d.Texture.prototype.texture_ = null; + /** * Generates Mips. @@ -126,7 +133,8 @@ o3d.Texture.prototype.alphaIsOne = true; */ o3d.Texture.prototype.generateMips = function(source_level, num_levels) { - o3d.notImplemented(); + this.gl.bindTexture(this.gl.TEXTURE_2D, this.texture_); + this.gl.generateMipmap(this.gl.TEXTURE_2D); }; @@ -138,9 +146,16 @@ o3d.Texture.prototype.generateMips = * @param {number} opt_height The height of this texture in pixels. * @constructor */ -o3d.Texture2D = function() { +o3d.Texture2D = function(opt_width, opt_height) { + o3d.Texture.call(this); this.width = opt_width || 0; this.height = opt_height || 0; + + /** + * The cache of rendersurface objects. + * @private + */ + this.renderSurfaces_ = []; }; o3d.inherit('Texture2D', 'Texture'); @@ -160,18 +175,22 @@ o3d.Texture2D.prototype.width = 0; o3d.Texture2D.prototype.height = 0; - /** * Returns a RenderSurface object associated with a mip_level of a texture. * * @param {number} mip_level The mip-level of the surface to be returned. - * @param {number} opt_pack pack This parameter is no longer used. - * The surface exists as long as the texture it came from exists. - * @returns {o3d.RenderSurface} The RenderSurface object. + * @return {o3d.RenderSurface} The RenderSurface object. */ o3d.Texture2D.prototype.getRenderSurface = - function(mip_level, opt_pack) { - o3d.notImplemented(); + function(mip_level) { + if (!this.renderSurfaces_[mip_level]) { + var renderSurface = new o3d.RenderSurface(); + renderSurface.gl = this.gl; + renderSurface.initWithTexture(this, mip_level); + this.renderSurfaces_[mip_level] = renderSurface; + } + + return this.renderSurfaces_[mip_level]; }; @@ -244,7 +263,7 @@ o3d.Texture2D.prototype.setRect = * @param {number} y The y coordinate of the area in the texture to retrieve. * @param {number} width The width of the area to retrieve. * @param {number} height The height of the area to retrieve. - * @returns {number} Array of pixel values. + * @return {number} Array of pixel values. */ o3d.Texture2D.prototype.getRect = function(level, x, y, width, height) { @@ -260,7 +279,24 @@ o3d.Texture2D.prototype.getRect = */ o3d.Texture2D.prototype.setFromBitmap = function(bitmap) { - o3d.notImplemented(); + this.gl.bindTexture(this.gl.TEXTURE_2D, this.texture_); + this.gl.texImage2D(this.gl.TEXTURE_2D, + 0, // Level. + bitmap.canvas_, + bitmap.defer_flip_verically_to_texture_); + + this.gl.texParameteri(this.gl.TEXTURE_2D, + this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR); + this.gl.texParameteri(this.gl.TEXTURE_2D, + this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR); + this.gl.texParameteri(this.gl.TEXTURE_2D, + this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE); + this.gl.texParameteri(this.gl.TEXTURE_2D, + this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE); + + if (bitmap.defer_mipmaps_to_texture_) { + this.generateMips(); + } }; @@ -301,7 +337,9 @@ o3d.Texture2D.prototype.drawImage = * @param {number} edgeLength The length of any edge of this texture * @constructor */ -o3d.TextureCUBE = function() { }; +o3d.TextureCUBE = function() { + o3d.Texture.call(this); +}; o3d.inherit('TextureCUBE', 'Texture'); @@ -346,7 +384,7 @@ o3d.TextureCUBE.prototype.edge_length = 0; * @param {o3d.Pack} pack This parameter is no longer used. The surface exists * as long as the texture it came from exists. * @param {number} mip_level The mip-level of the surface to be returned. - * @returns {o3d.RenderSurface} The RenderSurface object. + * @return {o3d.RenderSurface} The RenderSurface object. */ o3d.TextureCUBE.prototype.getRenderSurface = function(face, mip_level, opt_pack) { @@ -410,7 +448,7 @@ o3d.TextureCUBE.prototype.setRect = * @param {number} y The y coordinate of the area in the texture to retrieve. * @param {number} width The width of the area to retrieve. * @param {number} height The height of the area to retrieve. - * @returns {number} Array of pixel values. + * @return {number} Array of pixel values. */ o3d.TextureCUBE.prototype.getRect = function(face, level, x, y, width, height) { diff --git a/o3d/samples/o3d-webgl/transform.js b/o3d/samples/o3d-webgl/transform.js index 2ef5d21..ff72076 100644 --- a/o3d/samples/o3d-webgl/transform.js +++ b/o3d/samples/o3d-webgl/transform.js @@ -51,6 +51,7 @@ o3d.Transform = function(opt_localMatrix, opt_worldMatrix, opt_visible, opt_boundingBox, opt_cull) { + o3d.ParamObject.call(this); this.localMatrix = opt_localMatrix || [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]; this.worldMatrix = opt_worldMatrix || @@ -149,7 +150,7 @@ o3d.Transform.prototype.getTransformsInTree = * will affect them. * * @param {string} name Transform name to look for. - * @returns {Array.<o3d.Transform>} An array containing the transforms of the + * @return {Array.<o3d.Transform>} An array containing the transforms of the * under and including this transform matching the given name. */ o3d.Transform.prototype.getTransformsByNameInTree = @@ -182,12 +183,12 @@ o3d.Transform.prototype.addShape = /** * Removes a shape from this transform. * @param {o3d.Shape} shape Shape to remove. - * @returns {boolean} true if successful, false if shape was not in + * @return {boolean} true if successful, false if shape was not in * this transform. */ o3d.Transform.prototype.removeShape = function(shape) { - + o3d.notImplemented(); }; @@ -211,6 +212,7 @@ o3d.Transform.prototype.shapes = []; + /** * Walks the tree of transforms starting with this transform and creates * draw elements. If an Element already has a DrawElement that uses material a @@ -353,7 +355,7 @@ o3d.Transform.compose = function(a, b, opt_target) { * * @param {!Array.<!Array.<number>>} a A matrix. * @param {!Array.<!Array.<number>>} b Another matrix. - * @returns {boolean} Whether they are equal. + * @return {boolean} Whether they are equal. */ o3d.Transform.matricesEqual = function(a, b) { if (a==b) { @@ -416,7 +418,7 @@ o3d.Transform.transpose = function(m, opt_target) { * inverse of a. */ o3d.Transform.inverse = function(m, opt_target) { - var t = opt_target || a; + var t = opt_target || m; var m0 = m[0]; var m1 = m[1]; var m2 = m[2]; @@ -897,7 +899,7 @@ o3d.Transform.prototype.scale = * Utility function to flatten an o3djs-style matrix * (which is an array of arrays) into one array of entries. * @param {Array.<Array.<number> >} m The o3djs-style matrix. - * @returns {Array.<number>} The flattened matrix. + * @return {Array.<number>} The flattened matrix. */ o3d.Transform.flattenMatrix4 = function(m) { var m0 = m[0]; diff --git a/o3d/samples/o3d-webgl/tree_traversal.js b/o3d/samples/o3d-webgl/tree_traversal.js index 5a5dbb6..c92f601 100644 --- a/o3d/samples/o3d-webgl/tree_traversal.js +++ b/o3d/samples/o3d-webgl/tree_traversal.js @@ -42,8 +42,9 @@ * @constructor */ o3d.TreeTraversal = function(opt_transform) { + o3d.RenderNode.call(this); this.transform = opt_transform; - this.drawLists = []; + this.drawLists_ = []; this.drawListsToReset_ = []; }; o3d.inherit('TreeTraversal', 'RenderNode'); @@ -90,7 +91,7 @@ o3d.TreeTraversal.prototype.registerDrawList = /** * Unregisters a DrawList with this TreeTraversal. * @param {o3d.DrawList} draw_list DrawList to unregister. - * @returns {boolean} true if unregistered. false if this draw_list was + * @return {boolean} true if unregistered. false if this draw_list was * not registered. */ o3d.TreeTraversal.prototype.unregisterDrawList = diff --git a/o3d/samples/o3d-webgl/viewport.js b/o3d/samples/o3d-webgl/viewport.js index 6c082c0..70e1386 100644 --- a/o3d/samples/o3d-webgl/viewport.js +++ b/o3d/samples/o3d-webgl/viewport.js @@ -44,6 +44,7 @@ * @constructor */ o3d.Viewport = function(opt_viewport, opt_depthRange) { + o3d.RenderNode.call(this); this.viewport = opt_viewport || [0.0, 0.0, 1.0, 1.0]; this.depthRange = opt_depthRange || [0.0, 1.0]; }; @@ -66,7 +67,6 @@ o3d.inherit('Viewport', 'RenderNode'); o3d.Viewport.prototype.viewport = [0.0, 0.0, 1.0, 1.0]; - /** * The min Z and max Z depth range in [min Z, max Z] format. * Default = [0.0, 1.0]. @@ -81,16 +81,17 @@ o3d.Viewport.prototype.depthRange = [0.0, 1.0]; * scissor region in gl. */ o3d.Viewport.prototype.before = function() { - var x = this.viewport[0] * this.gl.canvas.width; - var y = this.viewport[1] * this.gl.canvas.height; - var width = this.viewport[2] * this.gl.canvas.width; - var height = this.viewport[3] * this.gl.canvas.height; + var x = this.viewport[0] * this.gl.displayInfo.width; + var y = this.viewport[1] * this.gl.displayInfo.height; + var width = this.viewport[2] * this.gl.displayInfo.width; + var height = this.viewport[3] * this.gl.displayInfo.height; + this.gl.viewport(x, y, width, height); if (x != 0 || y != 0 || this.viewport[2] != 1 || this.viewport[3] != 1) { this.gl.enable(this.gl.SCISSOR_TEST); this.gl.scissor(x, y, width, height); } else { - + this.gl.disable(this.gl.SCISSOR_TEST); } }; |