/* * 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. */ /** * The Shape represents a collection of Elements. The typical example is a * cube with 6 faces where each face uses a different material would be * represented as 1 Shape with 6 Elements, one for each material. * @constructor */ o3d.Shape = function() { o3d.ParamObject.call(this); this.elements = []; }; o3d.inherit('Shape', 'ParamObject'); /** * The elements owned by this shape. * * Each access to this field gets the entire list so it is best to get it * just once. For example: * * var elements = renderNode.elements; * for (var i = 0; i < elements.length; i++) { * var element = elements[i]; * } * * Note that modifications to this array [e.g. push()] will not affect * the underlying Shape, while modifications to the array's members * will affect them. */ o3d.Shape.prototype.elements = []; /** * Creates a DrawElement for each Element owned by this Shape. * If an Element already has a DrawElement that uses \a material a new * DrawElement will not be created. * @param {o3d.Pack} pack pack used to manage created DrawElements. * @param {o3d.Material} material material to use for each DrawElement. * If you pass null it will use the material on the corresponding 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. */ o3d.Shape.prototype.createDrawElements = function(pack, material) { var elements = this.elements; for (var i = 0; i < elements.length; ++i) { elements[i].createDrawElement(pack, material); } }; /** * Adds and element to the list of elements for this shape. * @param {o3d.Element} element The element to add. */ o3d.Shape.prototype.addElement = function(element) { this.elements.push(element); }; /** * Removes and element to the list of elements for this shape. * @param {o3d.Element} element The element to add. */ o3d.Shape.prototype.removeElement = function(element) { o3d.removeFromArray(this.elements, element); }; /** * Called when the tree traversal finds this shape in the transform tree. * Adds objects to the given drawlists if the drawlist of the material matches. * @param {Array.} drawListInfos A list of objects containing * drawlists and matrix info. * @param {o3d.math.Matrix4} world The world matrix. */ o3d.Shape.prototype.writeToDrawLists = function(drawListInfos, world, transform) { var elements = this.elements; // Iterate through elements of this shape. for (var i = 0; i < elements.length; ++i) { var element = elements[i]; // For each element look at the DrawElements for that element. for (var j = 0; j < element.drawElements.length; ++j) { this.gl.client.render_stats_['drawElementsProcessed']++; var drawElement = element.drawElements[j]; var material = drawElement.material || drawElement.owner.material; var materialDrawList = material.drawList; var rendered = false; // Iterate through the drawlists we might write to. for (var k = 0; k < drawListInfos.length; ++k) { var drawListInfo = drawListInfos[k]; var list = drawListInfo.list; // If any of those drawlists matches the material on the drawElement, // add the drawElement to the list. if (materialDrawList == list) { var context = drawListInfo.context; var view = context.view; var projection = context.projection; var worldViewProjection = [[], [], [], []]; var viewProjection = [[], [], [], []]; o3d.Transform.compose(projection, view, viewProjection); o3d.Transform.compose(viewProjection, world, worldViewProjection); if (element.cull && element.boundingBox) { if (!element.boundingBox.inFrustum(worldViewProjection)) { continue; } } rendered = true; list.list_.push({ view: view, projection: projection, world: world, viewProjection: viewProjection, worldViewProjection: worldViewProjection, transform: transform, drawElement: drawElement }); } } if (rendered) { this.gl.client.render_stats_['drawElementsRendered']++; } else { this.gl.client.render_stats_['drawElementsCulled']++; } } } };