/* <copyright> This file contains proprietary software owned by Motorola Mobility, Inc.<br/> No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.<br/> (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. </copyright> */ var RDGE = RDGE || {}; RDGE.renderUtils = RDGE.renderUtils || {}; /* * Creates an indexed box primitive * @return a rdge primitive */ RDGE.renderUtils.createBox = function () { var renderer = RDGE.globals.engine.getContext().renderer; var coords = [1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, // front 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, // right 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, // top -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, // left -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, // bottom 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1]; // back var normals = [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, // front 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // right 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, // top -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, // left 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, // bottom 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1]; // back var uvs = [1, 1, 0, 1, 0, 0, 1, 0, // front 0, 1, 0, 0, 1, 0, 1, 1, // right 1, 0, 1, 1, 0, 1, 0, 0, // top 1, 1, 0, 1, 0, 0, 1, 0, // left 0, 0, 1, 0, 1, 1, 0, 1, // bottom 0, 0, 1, 0, 1, 1, 0, 1]; // back var indices = [0, 1, 2, 0, 2, 3, // front 4, 5, 6, 4, 6, 7, // right 8, 9, 10, 8, 10, 11, // top 12, 13, 14, 12, 14, 15, // left 16, 17, 18, 16, 18, 19, // bottom 20, 21, 22, 20, 22, 23]; // back var prim = new RDGE.rdgePrimitiveDefinition(); prim.vertexDefinition = { "vert": { 'type': RDGE.rdgeConstants.VS_ELEMENT_POS, 'bufferIndex': 0, 'bufferUsage': RDGE.rdgeConstants.BUFFER_STATIC }, "a_pos": { 'type': RDGE.rdgeConstants.VS_ELEMENT_POS, 'bufferIndex': 0, 'bufferUsage': RDGE.rdgeConstants.BUFFER_STATIC }, "normal": { 'type': RDGE.rdgeConstants.VS_ELEMENT_FLOAT3, 'bufferIndex': 1, 'bufferUsage': RDGE.rdgeConstants.BUFFER_STATIC }, "a_nrm": { 'type': RDGE.rdgeConstants.VS_ELEMENT_FLOAT3, 'bufferIndex': 1, 'bufferUsage': RDGE.rdgeConstants.BUFFER_STATIC }, "texcoord": { 'type': RDGE.rdgeConstants.VS_ELEMENT_FLOAT2, 'bufferIndex': 2, 'bufferUsage': RDGE.rdgeConstants.BUFFER_STATIC }, "a_uv": { 'type': RDGE.rdgeConstants.VS_ELEMENT_FLOAT2, 'bufferIndex': 2, 'bufferUsage': RDGE.rdgeConstants.BUFFER_STATIC } }; prim.bufferStreams = [ coords, normals, uvs ]; prim.streamUsage = [ RDGE.rdgeConstants.BUFFER_STATIC, RDGE.rdgeConstants.BUFFER_STATIC, RDGE.rdgeConstants.BUFFER_STATIC ]; prim.indexUsage = RDGE.rdgeConstants.BUFFER_STREAM; prim.indexBuffer = indices; prim.type = RDGE.rdgeConstants.TRIANGLES; renderer.createPrimitive(prim); return prim; }; // // makeSphere // // Create a sphere with the passed number of latitude and longitude bands and the passed radius. // Sphere has vertices, normals and texCoords. Create VBOs for each as well as the index array. // Return an object with the following properties: // // normalObject WebGLBuffer object for normals // texCoordObject WebGLBuffer object for texCoords // vertexObject WebGLBuffer object for vertices // indexObject WebGLBuffer object for indices // numIndices The number of indices in the indexObject // RDGE.renderUtils.makeSphere = function (ctx, radius, lats, longs) { var geometryData = []; var normalData = []; var texCoordData = []; var indexData = []; for (var latNumber = 0; latNumber <= lats; ++latNumber) { for (var longNumber = 0; longNumber <= longs; ++longNumber) { var theta = latNumber * Math.PI / lats; var phi = longNumber * 2 * Math.PI / longs; var sinTheta = Math.sin(theta); var sinPhi = Math.sin(phi); var cosTheta = Math.cos(theta); var cosPhi = Math.cos(phi); var x = cosPhi * sinTheta; var y = cosTheta; var z = sinPhi * sinTheta; var u = 1 - (longNumber / longs); var v = latNumber / lats; normalData.push(x); normalData.push(y); normalData.push(z); texCoordData.push(u); texCoordData.push(v); geometryData.push(radius * x); geometryData.push(radius * y); geometryData.push(radius * z); } } for (var latNumber = 0; latNumber < lats; ++latNumber) { for (var longNumber = 0; longNumber < longs; ++longNumber) { var first = (latNumber * (longs + 1)) + longNumber; var second = first + longs + 1; indexData.push(first); indexData.push(second); indexData.push(first + 1); indexData.push(second); indexData.push(second + 1); indexData.push(first + 1); } } var retval = {}; retval.normalObject = ctx.createBuffer(); ctx.bindBuffer(ctx.ARRAY_BUFFER, retval.normalObject); ctx.bufferData(ctx.ARRAY_BUFFER, new Float32Array(normalData), ctx.STATIC_DRAW); retval.texCoordObject = ctx.createBuffer(); ctx.bindBuffer(ctx.ARRAY_BUFFER, retval.texCoordObject); ctx.bufferData(ctx.ARRAY_BUFFER, new Float32Array(texCoordData), ctx.STATIC_DRAW); retval.vertexObject = ctx.createBuffer(); ctx.bindBuffer(ctx.ARRAY_BUFFER, retval.vertexObject); ctx.bufferData(ctx.ARRAY_BUFFER, new Float32Array(geometryData), ctx.STATIC_DRAW); retval.numIndices = indexData.length; retval.indexObject = ctx.createBuffer(); ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, retval.indexObject); ctx.bufferData(ctx.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexData), ctx.STREAM_DRAW); return retval; }; /* * Creates a plane as a grid of triangles/quads, orients the plane according the the plane normal * note: the center of the plane is always assumed to be the origin. */ RDGE.renderUtils.createPlane = function (numCols, numRows, width, height, uTileCount, vTileCount, planeNormal) { var renderer = RDGE.globals.engine.getContext().renderer; var pn = [0, 1, 0]; if (!planeNormal) pn = planeNormal; var coords = new Array(numCols * numRows * 3); var normals = new Array(numCols * numRows * 3); var uvs = new Array(numCols * numRows * 2); var indices = new Array(numCols * numRows); // setup the vertices's in a grid and on the plane var coordIdx = 0; var uvIdx = 0; for (var row = 0; row < numRows; ++row) { for (var col = 0; col < numCols; ++col) { coords[coordIdx] = col * width - (numCols - 1) * width * 0.5; coords[coordIdx + 1] = 0; coords[coordIdx + 2] = row * height - (numRows - 1) * height * 0.5; normals[coordIdx] = planeNormal[0]; normals[coordIdx + 1] = planeNormal[1]; normals[coordIdx + 2] = planeNormal[2]; uvs[uvIdx] = col / numCols * uTileCount; uvs[uvIdx + 1] = row / numRows * vTileCount; coordIdx += 3; uvIdx += 2; } } // take the grid of vertices's and create triangles var k = 0; for (var row = 0; row < numRows; ++row) { for (var col = 0; col < numCols; ++col) { // layout both triangles of the quad indices[k + 2] = row * numCols + col; indices[k + 1] = row * numCols + (col + 1); indices[k] = (row + 1) * numCols + col; indices[k + 5] = (row + 1) * numCols + col; indices[k + 4] = row * numCols + (col + 1); indices[k + 3] = (row + 1) * numCols + (col + 1); k += 6; } } // reorient to plane normal var prim = new RDGE.rdgePrimitiveDefinition(); prim.vertexDefinition = { "vert": { 'type': RDGE.rdgeConstants.VS_ELEMENT_POS, 'bufferIndex': 0, 'bufferUsage': RDGE.rdgeConstants.BUFFER_STATIC }, "a_pos": { 'type': RDGE.rdgeConstants.VS_ELEMENT_POS, 'bufferIndex': 0, 'bufferUsage': RDGE.rdgeConstants.BUFFER_STATIC }, "normal": { 'type': RDGE.rdgeConstants.VS_ELEMENT_FLOAT3, 'bufferIndex': 1, 'bufferUsage': RDGE.rdgeConstants.BUFFER_STATIC }, "a_nrm": { 'type': RDGE.rdgeConstants.VS_ELEMENT_FLOAT3, 'bufferIndex': 1, 'bufferUsage': RDGE.rdgeConstants.BUFFER_STATIC }, "texcoord": { 'type': RDGE.rdgeConstants.VS_ELEMENT_FLOAT2, 'bufferIndex': 2, 'bufferUsage': RDGE.rdgeConstants.BUFFER_STATIC }, "a_uv": { 'type': RDGE.rdgeConstants.VS_ELEMENT_FLOAT2, 'bufferIndex': 2, 'bufferUsage': RDGE.rdgeConstants.BUFFER_STATIC } }; prim.bufferStreams = [ coords, normals, uvs ]; prim.streamUsage = [ RDGE.rdgeConstants.BUFFER_STATIC, RDGE.rdgeConstants.BUFFER_STATIC, RDGE.rdgeConstants.BUFFER_STATIC ]; prim.indexUsage = RDGE.rdgeConstants.BUFFER_STREAM; prim.indexBuffer = indices; prim.type = RDGE.rdgeConstants.TRIANGLES; renderer.createPrimitive(prim); return prim; }; // creates a cubic volume of points RDGE.renderUtils.createCubeVolume = function (numCols_x, numLayers_y, numRows_z, x_interval, y_interval, z_interval, optPointsOut) { var renderer = RDGE.globals.engine.getContext().renderer; var coords = new Array(numCols_x * numRows_z * numLayers_y * 3); var indices = new Array(numCols_x * numRows_z * numLayers_y); var layerSize = numCols_x * numRows_z * 3; var coordIdx = 0; var idx = 0; for (var layer = 0; layer < numLayers_y; ++layer) { for (var row = 0; row < numRows_z; ++row) { for (var col = 0; col < numCols_x; ++col) { coords[coordIdx] = col * x_interval - (numCols_x - 1) * x_interval * 0.5; coords[coordIdx + 1] = layer * y_interval - (numLayers_y - 1) * y_interval * 0.5; coords[coordIdx + 2] = row * z_interval - (numRows_z - 1) * z_interval * 0.5; coordIdx += 3; indices.push(idx++); } } } if (optPointsOut) { optPointsOut = coords.slice(); } var prim = new RDGE.rdgePrimitiveDefinition(); prim.vertexDefinition = { "a_pos": { 'type': RDGE.rdgeConstants.VS_ELEMENT_POS, 'bufferIndex': 0, 'bufferUsage': RDGE.rdgeConstants.BUFFER_STATIC } }; prim.bufferStreams = [ coords ]; prim.streamUsage = [ RDGE.rdgeConstants.BUFFER_DYNAMIC ]; prim.indexUsage = RDGE.rdgeConstants.BUFFER_STREAM; prim.indexBuffer = indices; prim.type = RDGE.rdgeConstants.POINTS; prim.useDoubleBuffer = true; renderer.createPrimitive(prim); return prim; }; RDGE.renderUtils.createScreenAlignedQuad = function () { var renderer = RDGE.globals.engine.getContext().renderer; // Screen aligned quad var coords = [ -1.0, 1.0, 0.0, 1.0, 1.0, 0.0, -1.0, -1.0, 0.0, -1.0, -1.0, 0.0, 1.0, 1.0, 0.0, 1.0, -1.0, 0.0 ]; var uvs = [0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0]; var prim = new RDGE.rdgePrimitiveDefinition(); prim.vertexDefinition = { "vert": { 'type': RDGE.rdgeConstants.VS_ELEMENT_POS, 'bufferIndex': 0, 'bufferUsage': RDGE.rdgeConstants.BUFFER_STATIC }, "a_pos": { 'type': RDGE.rdgeConstants.VS_ELEMENT_POS, 'bufferIndex': 0, 'bufferUsage': RDGE.rdgeConstants.BUFFER_STATIC }, "texcoord": { 'type': RDGE.rdgeConstants.VS_ELEMENT_FLOAT2, 'bufferIndex': 1, 'bufferUsage': RDGE.rdgeConstants.BUFFER_STATIC }, "a_uv": { 'type': RDGE.rdgeConstants.VS_ELEMENT_FLOAT2, 'bufferIndex': 1, 'bufferUsage': RDGE.rdgeConstants.BUFFER_STATIC } }; prim.bufferStreams = [ coords, uvs ]; prim.streamUsage = [ RDGE.rdgeConstants.BUFFER_STATIC, RDGE.rdgeConstants.BUFFER_STATIC ]; prim.type = RDGE.rdgeConstants.TRIANGLES; renderer.createPrimitive(prim); return prim; };